winedos: fix 16bit stack pushing

Markus Amsler markus.amsler at oribi.org
Sun Oct 17 18:50:50 CDT 2004


Pushing on stack from 16 bit mode was unsafe, because if esp was 0 it 
pushed into the previous segment instead of wrap around in the same one.
This caused some crashes while invoking hooked interrupts.

Changlog:
* Push on stack in 16 bit mode with segment wrap around
-------------- next part --------------
Index: dlls/winedos/dosexe.h
===================================================================
RCS file: /home/wine/wine/dlls/winedos/dosexe.h,v
retrieving revision 1.34
diff -u -r1.34 dosexe.h
--- dlls/winedos/dosexe.h	15 Nov 2003 00:13:21 -0000	1.34
+++ dlls/winedos/dosexe.h	17 Oct 2004 23:46:16 -0000
@@ -136,6 +136,11 @@
              LOWORD((context)->Ecx), LOWORD((context)->Edx), LOWORD((context)->Esi), \
              LOWORD((context)->Edi), (WORD)(context)->SegDs, (WORD)(context)->SegEs )
 
+/* pushing on stack in 16 bit needs segment wrap around */
+#define PUSH_WORD16(context,val) \
+    *((WORD*)CTX_SEG_OFF_TO_LIN((context), \
+        (context)->SegSs, ADD_LOWORD( context->Esp, -2 ) )) = (val)
+
 /* Macros for easier access to i386 context registers */
 
 #define AX_reg(context)      ((WORD)(context)->Eax)
Index: dlls/winedos/interrupts.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/interrupts.c,v
retrieving revision 1.24
diff -u -r1.24 interrupts.c
--- dlls/winedos/interrupts.c	25 Nov 2003 00:42:27 -0000	1.24
+++ dlls/winedos/interrupts.c	17 Oct 2004 23:46:25 -0000
@@ -392,8 +392,6 @@
         }
         else
         {
-            WORD *stack;
-            
             TRACE( "invoking hooked interrupt %02x at %04x:%04x\n", 
                    intnum, SELECTOROF(addr), OFFSETOF(addr) );
 
@@ -401,11 +399,9 @@
                 DOSVM_PrepareIRQ( context, FALSE );
 
             /* Push the flags and return address on the stack */
-            stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
-            *(--stack) = LOWORD(context->EFlags);
-            *(--stack) = context->SegCs;
-            *(--stack) = LOWORD(context->Eip);
-            ADD_LOWORD( context->Esp, -6 );
+            PUSH_WORD16( context, LOWORD(context->EFlags) );
+            PUSH_WORD16( context, context->SegCs );
+            PUSH_WORD16( context, LOWORD(context->Eip) );
 
             /* Jump to the interrupt handler */
             context->SegCs =  HIWORD(addr);
@@ -506,7 +502,6 @@
      else 
      {
          /* the interrupt is hooked, simulate interrupt in DOS space */ 
-         WORD* stack = PTR_REAL_TO_LIN( context->SegSs, context->Esp );
          WORD  flag  = LOWORD( context->EFlags );
 
          TRACE( "invoking hooked interrupt %02x at %04x:%04x\n", 
@@ -518,10 +513,10 @@
          else 
              flag &= ~IF_MASK;
 
-         *(--stack) = flag;
-         *(--stack) = context->SegCs;
-         *(--stack) = LOWORD( context->Eip );
-         context->Esp -= 6;
+         PUSH_WORD16( context, flag );
+         PUSH_WORD16( context, context->SegCs );
+         PUSH_WORD16( context, LOWORD( context->Eip ));
+         
          context->SegCs = SELECTOROF( handler );
          context->Eip   = OFFSETOF( handler );
 
Index: dlls/winedos/relay.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/relay.c,v
retrieving revision 1.6
diff -u -r1.6 relay.c
--- dlls/winedos/relay.c	14 Oct 2003 05:20:34 -0000	1.6
+++ dlls/winedos/relay.c	17 Oct 2004 23:46:26 -0000
@@ -168,7 +168,6 @@
  */
 void DOSVM_BuildCallFrame( CONTEXT86 *context, DOSRELAY relay, LPVOID data )
 {
-    WORD *stack;
     WORD  code_sel = DOSVM_dpmi_segments->relay_code_sel;
 
     /*
@@ -177,32 +176,26 @@
     RELAY_MakeShortContext( context );
 
     /*
-     * Get stack pointer after RELAY_MakeShortContext.
-     */
-    stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
-
-    /*
      * Build call frame.
      */
-    *(--stack) = HIWORD(data);            /* argument.hiword */ 
-    *(--stack) = LOWORD(data);            /* argument.loword */
-    *(--stack) = context->SegCs;          /* STACK16FRAME.cs */
-    *(--stack) = LOWORD(context->Eip);    /* STACK16FRAME.ip */
-    *(--stack) = LOWORD(context->Ebp);    /* STACK16FRAME.bp */
-    *(--stack) = HIWORD(relay);           /* STACK16FRAME.entry_point.hiword */
-    *(--stack) = LOWORD(relay);           /* STACK16FRAME.entry_point.loword */
-    *(--stack) = 0;                       /* STACK16FRAME.entry_ip */
-    *(--stack) = HIWORD(RELAY_RelayStub); /* STACK16FRAME.relay.hiword */
-    *(--stack) = LOWORD(RELAY_RelayStub); /* STACK16FRAME.relay.loword */
-    *(--stack) = 0;                       /* STACK16FRAME.module_cs.hiword */
-    *(--stack) = code_sel;                /* STACK16FRAME.module_cs.loword */
-    *(--stack) = 0;                       /* STACK16FRAME.callfrom_ip.hiword */
-    *(--stack) = 0;                       /* STACK16FRAME.callfrom_ip.loword */
+    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, code_sel );                /* STACK16FRAME.module_cs.loword */
+    PUSH_WORD16( context, 0 );                       /* STACK16FRAME.callfrom_ip.hiword */
+    PUSH_WORD16( context, 0 );                       /* STACK16FRAME.callfrom_ip.loword */
 
     /*
-     * Adjust stack and code pointers.
+     * Adjust code pointer.
      */
-    ADD_LOWORD( context->Esp, -28 );
     context->SegCs = wine_get_cs();
     context->Eip = (DWORD)__wine_call_from_16_regs;
 }


More information about the wine-patches mailing list