QT_Thunk patch

Andreas Mohr andi at rhlx01.fht-esslingen.de
Mon Jul 8 11:38:37 CDT 2002


Hi all,

ya know, our QT_Thunk is such a wonderfully beautifully implementation,
it's just marvelous...

...except for the fact that some programs decided to not play nice
with it ! ;-)

Some programs call QT_Thunk in a broken way, i.e. they don't reserve
0x40 bytes scratch buffer on the stack for QT_Thunk to do its magic
there.
As our QT_Thunk assumed that all programs use a fixed 0x40 bytes stack
buffer, it based its destination function argument count on it, which
led to *negative* function argument counts in case the QT_Thunk call
happened without such a 0x40 scratch buffer.
Thus QT_Thunk bombed in such cases.

- always copy (almost) the whole stack space over to the 16bit stack
  instead of calculating some potentially bogus parameter count
- add some comments (also about a DDJ article)

AddWeb 5 Professional (free download) uses QT_Thunk() to thunk down to
GetFreeSystemResources16(), and due to that crash and an exception
handler it refused to load with a "not enough resources" error.
This patch fixes it almost completely (except for crashes probably
due to unimplemented flat scrollbars).
Wonderfully complex program ! :)

-- 
Andreas Mohr                        Stauferstr. 6, D-71272 Renningen, Germany
Tel. +49 7159 800604                http://mohr.de.tt
-------------- next part --------------
Determining best CVS host...
Using CVSROOT :pserver:cvs at rhlx01.fht-esslingen.de:/home/wine
Index: dlls/kernel/thunk.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/thunk.c,v
retrieving revision 1.27
diff -u -r1.27 thunk.c
--- dlls/kernel/thunk.c	31 May 2002 23:25:48 -0000	1.27
+++ dlls/kernel/thunk.c	8 Jul 2002 16:29:28 -0000
@@ -299,9 +299,24 @@
  * 		QT_Thunk			(KERNEL32.@)
  *
  * The target address is in EDX.
- * The 16 bit arguments start at ESP.
+ * The 16bit arguments start at ESP.
  * The number of 16bit argument bytes is EBP-ESP-0x40 (64 Byte thunksetup).
+ * So the stack layout is 16bit argument bytes and then the 64 byte
+ * scratch buffer.
+ * The scratch buffer is used as work space by Windows' QT_Thunk
+ * function.
+ * As the programs unfortunately don't always provide a fixed size
+ * scratch buffer (danger, stack corruption ahead !!), we simply resort
+ * to copying over the whole EBP-ESP range to the 16bit stack
+ * (as there's no way to safely figure out the param count
+ * due to this misbehaviour of some programs).
  * [ok]
+ *
+ * See DDJ article 9614c for a very good description of QT_Thunk (also
+ * available online !).
+ *
+ * FIXME: DDJ talks of certain register usage rules; I'm not sure
+ * whether we cover this 100%.
  */
 void WINAPI QT_Thunk( CONTEXT86 *context )
 {
@@ -312,19 +327,35 @@
 
     context16.SegCs = HIWORD(context->Edx);
     context16.Eip   = LOWORD(context->Edx);
+    /* point EBP to the STACK16FRAME on the stack
+     * for the call_to_16 to set up the register content on calling */
     context16.Ebp   = OFFSETOF( NtCurrentTeb()->cur_stack )
                            + (WORD)&((STACK16FRAME*)0)->bp;
 
-    argsize = context->Ebp-context->Esp-0x40;
+    /*
+     * used to be (problematic):
+     * argsize = context->Ebp - context->Esp - 0x40;
+     * due to some programs abusing the API, we better assume the full
+     * EBP - ESP range for copying instead: */
+    argsize = context->Ebp - context->Esp;
+
+    /* ok, too much is insane; let's limit param count a bit again */
+    if (argsize > 64)
+	argsize = 64; /* 32 WORDs */
 
     memcpy( (LPBYTE)CURRENT_STACK16 - argsize,
             (LPBYTE)context->Esp, argsize );
 
+    /* let's hope call_to_16 won't mind getting called with such a
+     * potentially bogus large number of arguments */
     wine_call_to_16_regs_short( &context16, argsize );
     context->Eax = context16.Eax;
     context->Edx = context16.Edx;
     context->Ecx = context16.Ecx;
 
+    /* make sure to update the Win32 ESP, too, in order to throw away
+     * the number of parameters that the Win16 function
+     * accepted (that it popped from the corresponding Win16 stack) */
     context->Esp +=   LOWORD(context16.Esp) -
                         ( OFFSETOF( NtCurrentTeb()->cur_stack ) - argsize );
 }


More information about the wine-patches mailing list