Fix DPMI Event Checking in K32WowCallback16Ex

Robert Shearman rob at codeweavers.com
Wed Sep 22 20:01:54 CDT 2004


Hi,

The first fix is to bail from the event check if we are inside the 
system as we should do an event check when we go back to 16-bit code anyway.
The second fix is thanks to Jukka's suggestion that iret is only 
emulated in bad cases. In this case it was due to stack corruption 
caused by using a stale (1 or 2 DWORDs may have been added to it) stack 
point in K32WowCallback16Ex. The fix was to always keep the stack 
variable up-to-date.

Rob

Changelog:
- Don't perform event check if in system code. Fixes infinite recursion bug.
- Fix stack corruption that could occur in K32WowCallback16Ex if an 
event check was inserted.
-------------- next part --------------
Index: wine/dlls/kernel/wowthunk.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/wowthunk.c,v
retrieving revision 1.52
diff -u -p -r1.52 wowthunk.c
--- wine/dlls/kernel/wowthunk.c	17 May 2004 21:08:31 -0000	1.52
+++ wine/dlls/kernel/wowthunk.c	23 Sep 2004 00:51:12 -0000
@@ -194,6 +194,10 @@ static void insert_event_check( CONTEXT 
 {
     char *stack = wine_ldt_get_ptr( context->SegSs, context->Esp );
 
+    /* don't do event check while in system code */
+    if (wine_ldt_is_system(context->SegCs))
+        return;
+
     if(context->SegCs == dpmi_checker_selector &&
        context->Eip   >= dpmi_checker_offset_call && 
        context->Eip   <= dpmi_checker_offset_cleanup)
@@ -598,7 +602,7 @@ BOOL WINAPI K32WOWCallback16Ex( DWORD vp
      * (both for PASCAL and CDECL calling convention), so we simply
      * copy them to the 16-bit stack ...
      */
-    WORD *stack = (WORD *)CURRENT_STACK16 - cbArgs / sizeof(WORD);
+    char *stack = (char *)CURRENT_STACK16 - cbArgs;
 
     memcpy( stack, pArgs, cbArgs );
 
@@ -609,11 +613,12 @@ BOOL WINAPI K32WOWCallback16Ex( DWORD vp
         if (TRACE_ON(relay))
         {
             DWORD count = cbArgs / sizeof(WORD);
+            WORD * wstack = (WORD *)stack;
 
             DPRINTF("%04lx:CallTo16(func=%04lx:%04x,ds=%04lx",
                     GetCurrentThreadId(),
                     context->SegCs, LOWORD(context->Eip), context->SegDs );
-            while (count) DPRINTF( ",%04x", stack[--count] );
+            while (count) DPRINTF( ",%04x", wstack[--count] );
             DPRINTF(") ss:sp=%04x:%04x",
                     SELECTOROF(NtCurrentTeb()->cur_stack), OFFSETOF(NtCurrentTeb()->cur_stack) );
             DPRINTF(" ax=%04x bx=%04x cx=%04x dx=%04x si=%04x di=%04x bp=%04x es=%04x fs=%04x\n",
@@ -636,13 +641,16 @@ BOOL WINAPI K32WOWCallback16Ex( DWORD vp
             /* push return address */
             if (dwFlags & WCB16_REGS_LONG)
             {
-                *((DWORD *)stack - 1) = HIWORD(call16_ret_addr);
-                *((DWORD *)stack - 2) = LOWORD(call16_ret_addr);
+                stack -= sizeof(DWORD);
+                *((DWORD *)stack) = HIWORD(call16_ret_addr);
+                stack -= sizeof(DWORD);
+                *((DWORD *)stack) = LOWORD(call16_ret_addr);
                 cbArgs += 2 * sizeof(DWORD);
             }
             else
             {
-                *((SEGPTR *)stack - 1) = call16_ret_addr;
+                stack -= sizeof(SEGPTR);
+                *((SEGPTR *)stack) = call16_ret_addr;
                 cbArgs += sizeof(SEGPTR);
             }
 
@@ -653,7 +661,6 @@ BOOL WINAPI K32WOWCallback16Ex( DWORD vp
              */
             if (NtCurrentTeb()->dpmi_vif)
             {
-                context->SegSs = wine_get_ds();
                 context->Esp   = (DWORD)stack;
                 insert_event_check( context );
                 cbArgs += (DWORD)stack - context->Esp;
@@ -682,18 +689,20 @@ BOOL WINAPI K32WOWCallback16Ex( DWORD vp
         if (TRACE_ON(relay))
         {
             DWORD count = cbArgs / sizeof(WORD);
+            WORD * wstack = (WORD *)stack;
 
             DPRINTF("%04lx:CallTo16(func=%04x:%04x,ds=%04x",
                     GetCurrentThreadId(), HIWORD(vpfn16), LOWORD(vpfn16),
                     SELECTOROF(NtCurrentTeb()->cur_stack) );
-            while (count) DPRINTF( ",%04x", stack[--count] );
+            while (count) DPRINTF( ",%04x", wstack[--count] );
             DPRINTF(") ss:sp=%04x:%04x\n",
                     SELECTOROF(NtCurrentTeb()->cur_stack), OFFSETOF(NtCurrentTeb()->cur_stack) );
             SYSLEVEL_CheckNotLevel( 2 );
         }
 
         /* push return address */
-        *((SEGPTR *)stack - 1) = call16_ret_addr;
+        stack -= sizeof(SEGPTR);
+        *((SEGPTR *)stack) = call16_ret_addr;
         cbArgs += sizeof(SEGPTR);
 
         /*


More information about the wine-patches mailing list