[PATCH 2/3] krnl386: Return to a generated 16-bit entry point when calling builtin interrupt handlers.

Zebediah Figura zfigura at codeweavers.com
Tue Sep 28 20:39:04 CDT 2021


Instead of manually building a STACK16FRAME.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
I have changes planned that modify the STACK16FRAME layout and the 16-to-32
assembly code. This becomes much easier when there are not a half dozen places
which must implicitly be kept in sync.

 dlls/ifsmgr.vxd/ifsmgr.c              |  6 ++--
 dlls/krnl386.exe16/dosexe.h           |  6 +---
 dlls/krnl386.exe16/dosmem.c           | 14 ---------
 dlls/krnl386.exe16/instr.c            |  4 +--
 dlls/krnl386.exe16/interrupts.c       | 37 +++++++++++-----------
 dlls/krnl386.exe16/krnl386.exe16.spec |  3 +-
 dlls/krnl386.exe16/relay.c            | 44 ---------------------------
 dlls/vwin32.vxd/vwin32.c              |  6 ++--
 8 files changed, 30 insertions(+), 90 deletions(-)

diff --git a/dlls/ifsmgr.vxd/ifsmgr.c b/dlls/ifsmgr.vxd/ifsmgr.c
index 2fe3198a6ba..ab232ec6c23 100644
--- a/dlls/ifsmgr.vxd/ifsmgr.c
+++ b/dlls/ifsmgr.vxd/ifsmgr.c
@@ -97,7 +97,7 @@ static void CONTEXT_2_win32apieq(const CONTEXT *pCxt, struct win32apireq *pOut)
         /* FIXME: pOut->ar_pad ignored */
 }
 
-extern void __wine_call_int_handler( CONTEXT *context, BYTE intnum );
+extern void WINAPI __wine_call_int_handler16( BYTE intnum, CONTEXT *context );
 
 /***********************************************************************
  *           DeviceIoControl   (IFSMGR.VXD.@)
@@ -132,9 +132,9 @@ BOOL WINAPI IFSMGR_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpvInBuffer, DW
             win32apieq_2_CONTEXT(pIn,&cxt);
 
             if(dwIoControlCode==IFS_IOCTL_21)
-                __wine_call_int_handler( &cxt, 0x21 );
+                __wine_call_int_handler16( 0x21, &cxt );
             else
-                __wine_call_int_handler( &cxt, 0x2f );
+                __wine_call_int_handler16( 0x2f, &cxt );
 
             CONTEXT_2_win32apieq(&cxt,pOut);
             return TRUE;
diff --git a/dlls/krnl386.exe16/dosexe.h b/dlls/krnl386.exe16/dosexe.h
index 42b8e0f4437..1e4d15c75e5 100644
--- a/dlls/krnl386.exe16/dosexe.h
+++ b/dlls/krnl386.exe16/dosexe.h
@@ -40,7 +40,6 @@ typedef void (WINAPI *INTPROC)(CONTEXT*);
 
 extern WORD DOSVM_psp DECLSPEC_HIDDEN;     /* psp of current DOS task */
 extern WORD int16_sel DECLSPEC_HIDDEN;
-extern WORD relay_code_sel DECLSPEC_HIDDEN;
 
 #define ADD_LOWORD(dw,val)  ((dw) = ((dw) & 0xffff0000) | LOWORD((DWORD)(dw)+(val)))
 
@@ -236,7 +235,7 @@ extern void WINAPI DOSVM_Int2fHandler(CONTEXT*) DECLSPEC_HIDDEN;
 extern void WINAPI DOSVM_Int31Handler(CONTEXT*) DECLSPEC_HIDDEN;
 
 /* interrupts.c */
-extern void        __wine_call_int_handler( CONTEXT *, BYTE ) DECLSPEC_HIDDEN;
+extern void WINAPI __wine_call_int_handler16( BYTE, CONTEXT * ) DECLSPEC_HIDDEN;
 extern BOOL        DOSVM_EmulateInterruptPM( CONTEXT *, BYTE ) DECLSPEC_HIDDEN;
 extern FARPROC16   DOSVM_GetPMHandler16( BYTE ) DECLSPEC_HIDDEN;
 extern void        DOSVM_SetPMHandler16( BYTE, FARPROC16 ) DECLSPEC_HIDDEN;
@@ -245,7 +244,4 @@ extern void        DOSVM_SetPMHandler16( BYTE, FARPROC16 ) DECLSPEC_HIDDEN;
 extern DWORD DOSVM_inport( int port, int size ) DECLSPEC_HIDDEN;
 extern void DOSVM_outport( int port, int size, DWORD value ) DECLSPEC_HIDDEN;
 
-/* relay.c */
-void DOSVM_BuildCallFrame( CONTEXT *, DOSRELAY, LPVOID ) DECLSPEC_HIDDEN;
-
 #endif /* __WINE_DOSEXE_H */
diff --git a/dlls/krnl386.exe16/dosmem.c b/dlls/krnl386.exe16/dosmem.c
index 2d55eb050de..64df77a3747 100644
--- a/dlls/krnl386.exe16/dosmem.c
+++ b/dlls/krnl386.exe16/dosmem.c
@@ -44,7 +44,6 @@ WORD DOSMEM_BiosSysSeg;   /* BIOS ROM segment at 0xf000:0 */
 
 WORD DOSVM_psp = 0;
 WORD int16_sel = 0;
-WORD relay_code_sel = 0;
 
 /* DOS memory highest address (including HMA) */
 #define DOSMEM_SIZE             0x110000
@@ -302,11 +301,6 @@ static void DOSMEM_InitSegments(void)
     LPSTR ptr;
     int   i;
 
-    static const char relay[]=
-    {
-        0xca, 0x04, 0x00, /* 16-bit far return and pop 4 bytes (relay void* arg) */
-    };
-
     /*
      * PM / offset N*5: Interrupt N in 16-bit protected mode.
      */
@@ -325,14 +319,6 @@ static void DOSMEM_InitSegments(void)
         ptr[i * 5 + 4] = 0x00;
     }
     GlobalUnlock16( int16_sel );
-
-    /*
-     * PM / offset 0: Stub where __wine_call_from_16_regs returns.
-     */
-    relay_code_sel = GLOBAL_Alloc( GMEM_FIXED, sizeof(relay), 0, LDT_FLAGS_CODE );
-    ptr = GlobalLock16( relay_code_sel );
-    memcpy( ptr, relay, sizeof(relay) );
-    GlobalUnlock16( relay_code_sel );
 }
 
 /******************************************************************
diff --git a/dlls/krnl386.exe16/instr.c b/dlls/krnl386.exe16/instr.c
index ff7f866f9e0..789c6dfb212 100644
--- a/dlls/krnl386.exe16/instr.c
+++ b/dlls/krnl386.exe16/instr.c
@@ -895,7 +895,7 @@ LONG CALLBACK INSTR_vectored_handler( EXCEPTION_POINTERS *ptrs )
  */
 void WINAPI DOS3Call( CONTEXT *context )
 {
-    __wine_call_int_handler( context, 0x21 );
+    __wine_call_int_handler16( 0x21, context );
 }
 
 
@@ -904,7 +904,7 @@ void WINAPI DOS3Call( CONTEXT *context )
  */
 void WINAPI NetBIOSCall16( CONTEXT *context )
 {
-    __wine_call_int_handler( context, 0x5c );
+    __wine_call_int_handler16( 0x5c, context );
 }
 
 
diff --git a/dlls/krnl386.exe16/interrupts.c b/dlls/krnl386.exe16/interrupts.c
index d397d20072d..3c99eabcbba 100644
--- a/dlls/krnl386.exe16/interrupts.c
+++ b/dlls/krnl386.exe16/interrupts.c
@@ -120,19 +120,25 @@ static INTPROC DOSVM_GetBuiltinHandler( BYTE intnum )
     return DOSVM_DefaultHandler;
 }
 
-
-/**********************************************************************
- *          DOSVM_IntProcRelay
+/* Set up the context so that we will call __wine_call_int_handler16 upon
+ * resuming execution.
  *
- * Simple DOSRELAY that interprets its argument as INTPROC and calls it.
- */
-static void DOSVM_IntProcRelay( CONTEXT *context, LPVOID data )
+ * We can't just call the interrupt handler directly, since some code (in
+ * particular, LoadModule16) assumes that it's running on the 32-bit stack and
+ * that CURRENT_STACK16 points to the bottom of the used 16-bit stack. */
+static void return_to_interrupt_handler( CONTEXT *context, BYTE intnum )
 {
-    INTPROC proc = (INTPROC)data;
-    proc(context);
+    FARPROC16 addr = GetProcAddress16( GetModuleHandle16( "KERNEL" ), "__wine_call_int_handler" );
+    WORD *stack = ldt_get_ptr( context->SegSs, context->Esp );
+
+    *--stack = intnum;
+    *--stack = context->SegCs;
+    *--stack = context->Eip;
+    context->Esp -= 3 * sizeof(WORD);
+    context->SegCs = SELECTOROF(addr);
+    context->Eip = OFFSETOF(addr);
 }
 
-
 /**********************************************************************
  *          DOSVM_PushFlags
  *
@@ -205,10 +211,7 @@ static void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum )
         if (intnum == 0x25 || intnum == 0x26)
             DOSVM_PushFlags( context, FALSE, FALSE );
 
-        DOSVM_BuildCallFrame( context,
-                              DOSVM_IntProcRelay,
-                              DOSVM_GetBuiltinHandler(
-                                  OFFSETOF(addr)/DOSVM_STUB_PM16 ) );
+        return_to_interrupt_handler( context, OFFSETOF(addr) / DOSVM_STUB_PM16 );
     }
     else
     {
@@ -267,9 +270,7 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum )
         if (intnum == 0x25 || intnum == 0x26)
             DOSVM_PushFlags( context, FALSE, TRUE );
 
-        DOSVM_BuildCallFrame( context, 
-                              DOSVM_IntProcRelay, 
-                              DOSVM_GetBuiltinHandler(intnum) );
+        return_to_interrupt_handler( context, intnum );
     }
     else if (ldt_is_system(context->SegCs))
     {
@@ -399,9 +400,9 @@ static void DOSVM_CallBuiltinHandler( CONTEXT *context, BYTE intnum )
 
 
 /**********************************************************************
- *         __wine_call_int_handler    (KERNEL.@)
+ *         __wine_call_int_handler16    (KERNEL.@)
  */
-void __wine_call_int_handler( CONTEXT *context, BYTE intnum )
+void WINAPI __wine_call_int_handler16( BYTE intnum, CONTEXT *context )
 {
     DOSMEM_InitDosMemory();
     DOSVM_CallBuiltinHandler( context, intnum );
diff --git a/dlls/krnl386.exe16/krnl386.exe16.spec b/dlls/krnl386.exe16/krnl386.exe16.spec
index ddd321cbc31..c6ffd9df701 100644
--- a/dlls/krnl386.exe16/krnl386.exe16.spec
+++ b/dlls/krnl386.exe16/krnl386.exe16.spec
@@ -741,7 +741,8 @@
 # or 'wine_' (for user-visible functions) to avoid namespace conflicts.
 
 # DOS support
-@ cdecl -arch=win32 __wine_call_int_handler(ptr long)
+2000 pascal -register __wine_call_int_handler(word) __wine_call_int_handler16
+@ stdcall -arch=win32 __wine_call_int_handler16(long ptr)
 
 # VxDs
 @ cdecl -arch=win32 -private __wine_vxd_open(wstr long ptr)
diff --git a/dlls/krnl386.exe16/relay.c b/dlls/krnl386.exe16/relay.c
index 116198e5ddb..2ec657bd3f8 100644
--- a/dlls/krnl386.exe16/relay.c
+++ b/dlls/krnl386.exe16/relay.c
@@ -551,47 +551,3 @@ int relay_call_from_16( void *entry_point, unsigned char *args16, CONTEXT *conte
     }
     return ret_val;
 }
-
-/**********************************************************************
- *          RELAY_RelayStub
- *
- * This stub is called by __wine_call_from_16_regs in order to marshall
- * relay parameters.
- */
-static void __stdcall RELAY_RelayStub( DOSRELAY proc, unsigned char *args, CONTEXT *context )
-{
-    proc( context, *(LPVOID *)args );
-}
-
-/**********************************************************************
- *          DOSVM_BuildCallFrame
- *
- * Modifies the context so that return to context calls DOSRELAY and
- * only after return from DOSRELAY the original context will be returned to.
- */
-void DOSVM_BuildCallFrame( CONTEXT *context, DOSRELAY relay, LPVOID data )
-{
-    /*
-     * Build call frame.
-     */
-    PUSH_WORD16( context, HIWORD(data) );            /* argument.hiword */
-    PUSH_WORD16( context, LOWORD(data) );            /* argument.loword */
-    PUSH_WORD16( context, context->SegCs );          /* STACK16FRAME.cs */
-    PUSH_WORD16( context, LOWORD(context->Eip) );    /* STACK16FRAME.ip */
-    PUSH_WORD16( context, LOWORD(context->Ebp) );    /* STACK16FRAME.bp */
-    PUSH_WORD16( context, HIWORD(relay) );           /* STACK16FRAME.entry_point.hiword */
-    PUSH_WORD16( context, LOWORD(relay) );           /* STACK16FRAME.entry_point.loword */
-    PUSH_WORD16( context, 0 );                       /* STACK16FRAME.entry_ip */
-    PUSH_WORD16( context, HIWORD(RELAY_RelayStub) ); /* STACK16FRAME.relay.hiword */
-    PUSH_WORD16( context, LOWORD(RELAY_RelayStub) ); /* STACK16FRAME.relay.loword */
-    PUSH_WORD16( context, 0 );                       /* STACK16FRAME.module_cs.hiword */
-    PUSH_WORD16( context, relay_code_sel );          /* STACK16FRAME.module_cs.loword */
-    PUSH_WORD16( context, 0 );                       /* STACK16FRAME.callfrom_ip.hiword */
-    PUSH_WORD16( context, 0 );                       /* STACK16FRAME.callfrom_ip.loword */
-
-    /*
-     * Adjust code pointer.
-     */
-    context->SegCs = get_cs();
-    context->Eip = (DWORD)__wine_call_from_16_regs;
-}
diff --git a/dlls/vwin32.vxd/vwin32.c b/dlls/vwin32.vxd/vwin32.c
index 82fa80c4e65..5a33f2ba665 100644
--- a/dlls/vwin32.vxd/vwin32.c
+++ b/dlls/vwin32.vxd/vwin32.c
@@ -55,7 +55,7 @@ typedef struct tagMID {
 } MID, *PMID;
 #include <poppack.h>
 
-extern void __wine_call_int_handler( CONTEXT *context, BYTE intnum );
+extern void WINAPI __wine_call_int_handler16( BYTE intnum, CONTEXT *context );
 
 /* Pop a DWORD from the 32-bit stack */
 static inline DWORD stack32_pop( CONTEXT *context )
@@ -155,7 +155,7 @@ BOOL WINAPI VWIN32_DeviceIoControl(DWORD dwIoControlCode,
                 break;
             }
 
-            __wine_call_int_handler( &cxt, intnum );
+            __wine_call_int_handler16( intnum, &cxt );
             CONTEXT_2_DIOCRegs( &cxt, pOut );
         }
         return TRUE;
@@ -208,7 +208,7 @@ DWORD WINAPI VWIN32_VxDCall( DWORD service, CONTEXT *context )
 
             context->Eax = callnum;
             context->Ecx = parm;
-            __wine_call_int_handler( context, 0x31 );
+            __wine_call_int_handler16( 0x31, context );
             return LOWORD(context->Eax);
         }
     case 0x002a: /* Int41 dispatch - parm = int41 service number */
-- 
2.33.0




More information about the wine-devel mailing list