[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    Re: Thunking problem is partially solved
From:       Ulrich Weigand <weigand () immd1 ! informatik ! uni-erlangen ! de>
Date:       2000-08-31 1:48:30
[Download RAW message or body]


Dmitry Timoshkov wrote:

> Examining the disassembled text of pm65.exe, I noted, that PM pushes
> different number of bytes in different places in the code before call
> to QT_Thunk. I assume, that it is an exact number of bytes, that 16-bit
> callee will get as arguments and should pop from the stack with pascal16
> function return type.

Right.  The problem is that we implement thunks differently than Win95
does, with the most important difference being that we actually have two
seperate stacks per app, a 16-bit one and a 32-bit one, where Win95 has 
only *one* stack:  16-bit apps have their 16-bit stack, and when thunking 
to 32-bit, ESP is simply set to the appropriate 32-bit flat pointer pointing 
to the current 16-bit stack location;  32-bit apps have their 32-bit stack,
and when thunking to 16-bit, a temporary SS selector is allocated that
covers the current 'window' on the 32-bit stack.

This means that Win95 does not in fact copy *any* arguments in QT_Thunk
and the other thunking routines;  they simply stay on the stack.
Similarly, all modifications made to SP by the called routine are
preserved, so if the 16-bit routine pops N argument bytes, those
arguments will also be popped on the 32-bit stack after return of 
QT_Thunk.

We, on the other hand, have to copy arguments to the 16-bit stack.
Unfortunately, we don't know how *many* arguments to copy, thus we
copy in fact the largest possible size (i.e. from ESP to EBP-0x40.
EBP-0x40 is because the region EBP-0x40..EBP is a parameter block
for use by QT_Thunk that has to be set up by the caller).  As we
don't know the actual argument size, we don't know how much to
pop off the 32-bit stack either.

This works fine if the caller of QT_Thunk is one of the thunk stubs
generated by the MS thunk compiler (which is supposed to be the *only*
code that ever calls QT_Thunk),  because these stubs don't have any
other local variables on the stack, and return to their caller 
immediately after QT_Thunk returned.

Apparently, your app calls QT_Thunk manually, from within a routine
that does in fact care about the proper ESP value after return of
QT_Thunk.  This unfortunately doesn't work with the current Wine
code.  To fix this, we'd need to find out how many bytes the 
16-bit routine popped off the stack, which is currently not possible.

 
> I made some addtional traces to find out the way to properly calculate
> number of bytes popped by 16-bit function from the 16-bit stack, but failed.

The problem is that the return path in CallTo16 restores proper
32-bit register values, without taking care of saving the values
left in the registers by the 16-bit function (except for the 
return value in AX/DX).   Thus, the caller has no way of finding
out these values.

One option to fix this problem might be to update the context
structure on return.  This is unfortunately a little tricky
because of the peculiar way we perform the 16->32 bit transition.
Furthermore it might have probably an adverse impact on 
performance ... 

Another way might be to change the arg_size parameter from a 
pure input parameter to in/out, and update this with the 
actual argument size (as popped by the called routine).

I'll have to think about this ...


Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic