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