Extended WOWCallback16Ex to support register functions too. This
allows simplifying the wine_call_to_16 assembly code by moving part of it to C code, and getting rid of the extra kernel exports.
This commit is contained in:
parent
cb1c112dd6
commit
3a5b7cf105
|
@ -1126,9 +1126,6 @@
|
|||
@ varargs __wine_call_from_16_word()
|
||||
@ varargs __wine_call_from_16_long()
|
||||
@ varargs __wine_call_from_16_regs()
|
||||
@ stdcall wine_call_to_16(ptr long)
|
||||
@ stdcall wine_call_to_16_regs_short(ptr long)
|
||||
@ stdcall wine_call_to_16_regs_long (ptr long)
|
||||
|
||||
# Unix files
|
||||
@ stdcall wine_get_unix_file_name(str ptr long)
|
||||
|
|
|
@ -1284,7 +1284,7 @@ DWORD NE_StartTask(void)
|
|||
SELECTOROF(pTask->teb->cur_stack),
|
||||
OFFSETOF(pTask->teb->cur_stack) );
|
||||
|
||||
wine_call_to_16_regs_short( &context, 0 );
|
||||
WOWCallback16Ex( 0, WCB16_REGS, 0, NULL, (DWORD *)&context );
|
||||
ExitThread( LOWORD(context.Eax) );
|
||||
}
|
||||
return hInstance; /* error code */
|
||||
|
|
|
@ -682,7 +682,7 @@ static BOOL NE_InitDLL( NE_MODULE *pModule )
|
|||
TRACE_(dll)("Calling LibMain, cs:ip=%04lx:%04lx ds=%04lx di=%04x cx=%04x\n",
|
||||
context.SegCs, context.Eip, context.SegDs,
|
||||
LOWORD(context.Edi), LOWORD(context.Ecx) );
|
||||
wine_call_to_16_regs_short( &context, 0 );
|
||||
WOWCallback16Ex( 0, WCB16_REGS, 0, NULL, (DWORD *)&context );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -769,8 +769,8 @@ static void NE_CallDllEntryPoint( NE_MODULE *pModule, DWORD dwReason )
|
|||
}
|
||||
else
|
||||
{
|
||||
LPBYTE stack = (LPBYTE)CURRENT_STACK16;
|
||||
CONTEXT86 context;
|
||||
WORD args[8];
|
||||
|
||||
memset( &context, 0, sizeof(context) );
|
||||
context.SegDs = ds;
|
||||
|
@ -781,14 +781,15 @@ static void NE_CallDllEntryPoint( NE_MODULE *pModule, DWORD dwReason )
|
|||
context.Ebp = OFFSETOF( NtCurrentTeb()->cur_stack )
|
||||
+ (WORD)&((STACK16FRAME*)0)->bp;
|
||||
|
||||
*(DWORD *)(stack - 4) = dwReason; /* dwReason */
|
||||
*(WORD *) (stack - 6) = hInst; /* hInst */
|
||||
*(WORD *) (stack - 8) = ds; /* wDS */
|
||||
*(WORD *) (stack - 10) = heap; /* wHeapSize */
|
||||
*(DWORD *)(stack - 14) = 0; /* dwReserved1 */
|
||||
*(WORD *) (stack - 16) = 0; /* wReserved2 */
|
||||
|
||||
wine_call_to_16_regs_short( &context, 16 );
|
||||
args[7] = HIWORD(dwReason);
|
||||
args[6] = LOWORD(dwReason);
|
||||
args[5] = hInst;
|
||||
args[4] = ds;
|
||||
args[3] = heap;
|
||||
args[2] = 0; /* HIWORD(dwReserved1) */
|
||||
args[1] = 0; /* LOWORD(dwReserved1) */
|
||||
args[0] = 0; /* wReserved2 */
|
||||
WOWCallback16Ex( 0, WCB16_REGS, sizeof(args), args, (DWORD *)&context );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "wingdi.h"
|
||||
#include "wine/winbase16.h"
|
||||
#include "wine/winuser16.h"
|
||||
#include "wownt32.h"
|
||||
#include "stackframe.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -173,7 +174,7 @@ static void call_timer_proc16( WORD timer )
|
|||
+ (WORD)&((STACK16FRAME*)0)->bp;
|
||||
context.Eax = timer;
|
||||
|
||||
wine_call_to_16_regs_short( &context, 0 );
|
||||
WOWCallback16Ex( 0, WCB16_REGS, 0, NULL, (DWORD *)&context );
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "winternl.h"
|
||||
#include "wownt32.h"
|
||||
#include "wine/winbase16.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
@ -349,12 +350,7 @@ void WINAPI QT_Thunk( CONTEXT86 *context )
|
|||
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 );
|
||||
WOWCallback16Ex( 0, WCB16_REGS, argsize, (void *)context->Esp, (DWORD *)&context16 );
|
||||
context->Eax = context16.Eax;
|
||||
context->Edx = context16.Edx;
|
||||
context->Ecx = context16.Ecx;
|
||||
|
@ -460,7 +456,8 @@ void WINAPI FT_Thunk( CONTEXT86 *context )
|
|||
|
||||
CONTEXT86 context16;
|
||||
DWORD i, argsize;
|
||||
LPBYTE newstack, oldstack;
|
||||
DWORD newstack[32];
|
||||
LPBYTE oldstack;
|
||||
|
||||
memcpy(&context16,context,sizeof(context16));
|
||||
|
||||
|
@ -470,7 +467,7 @@ void WINAPI FT_Thunk( CONTEXT86 *context )
|
|||
+ (WORD)&((STACK16FRAME*)0)->bp;
|
||||
|
||||
argsize = context->Ebp-context->Esp-0x40;
|
||||
newstack = (LPBYTE)CURRENT_STACK16 - argsize;
|
||||
if (argsize > sizeof(newstack)) argsize = sizeof(newstack);
|
||||
oldstack = (LPBYTE)context->Esp;
|
||||
|
||||
memcpy( newstack, oldstack, argsize );
|
||||
|
@ -478,13 +475,13 @@ void WINAPI FT_Thunk( CONTEXT86 *context )
|
|||
for (i = 0; i < 32; i++) /* NOTE: What about > 32 arguments? */
|
||||
if (mapESPrelative & (1 << i))
|
||||
{
|
||||
SEGPTR *arg = (SEGPTR *)(newstack + 2*i);
|
||||
SEGPTR *arg = (SEGPTR *)newstack[i];
|
||||
*arg = MAKESEGPTR(SELECTOROF(NtCurrentTeb()->cur_stack),
|
||||
OFFSETOF(NtCurrentTeb()->cur_stack) - argsize
|
||||
+ (*(LPBYTE *)arg - oldstack));
|
||||
}
|
||||
|
||||
wine_call_to_16_regs_short( &context16, argsize );
|
||||
WOWCallback16Ex( 0, WCB16_REGS, argsize, newstack, (DWORD *)&context16 );
|
||||
context->Eax = context16.Eax;
|
||||
context->Edx = context16.Edx;
|
||||
context->Ecx = context16.Ecx;
|
||||
|
@ -688,10 +685,11 @@ void WINAPI Common32ThkLS( CONTEXT86 *context )
|
|||
if (context->Edx == context->Eip)
|
||||
argsize = 6 * 4;
|
||||
|
||||
memcpy( (LPBYTE)CURRENT_STACK16 - argsize,
|
||||
(LPBYTE)context->Esp, argsize );
|
||||
|
||||
wine_call_to_16_regs_long(&context16, argsize + 32);
|
||||
/* Note: the first 32 bytes we copy are just garbage from the 32-bit stack, in order to reserve
|
||||
* the space. It is safe to do that since the register function prefix has reserved
|
||||
* a lot more space than that below context->Esp.
|
||||
*/
|
||||
WOWCallback16Ex( 0, WCB16_REGS, argsize + 32, (LPBYTE)context->Esp - 32, (DWORD *)&context16 );
|
||||
context->Eax = context16.Eax;
|
||||
|
||||
/* Clean up caller's stack frame */
|
||||
|
@ -739,10 +737,7 @@ void WINAPI OT_32ThkLSF( CONTEXT86 *context )
|
|||
|
||||
argsize = 2 * *(WORD *)context->Esp + 2;
|
||||
|
||||
memcpy( (LPBYTE)CURRENT_STACK16 - argsize,
|
||||
(LPBYTE)context->Esp, argsize );
|
||||
|
||||
wine_call_to_16_regs_short(&context16, argsize);
|
||||
WOWCallback16Ex( 0, WCB16_REGS, argsize, (void *)context->Esp, (DWORD *)&context16 );
|
||||
context->Eax = context16.Eax;
|
||||
context->Edx = context16.Edx;
|
||||
|
||||
|
|
|
@ -21,11 +21,14 @@
|
|||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "wine/winbase16.h"
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "wownt32.h"
|
||||
#include "winternl.h"
|
||||
#include "syslevel.h"
|
||||
#include "file.h"
|
||||
#include "task.h"
|
||||
#include "miscemu.h"
|
||||
|
@ -33,6 +36,7 @@
|
|||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(thunk);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(relay);
|
||||
|
||||
/*
|
||||
* These are the 16-bit side WOW routines. They reside in wownt16.h
|
||||
|
@ -290,7 +294,10 @@ WORD WINAPI K32WOWHandle16( HANDLE handle, WOW_HANDLE_TYPE type )
|
|||
BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags,
|
||||
DWORD cbArgs, LPVOID pArgs, LPDWORD pdwRetCode )
|
||||
{
|
||||
DWORD ret;
|
||||
#ifdef __i386__
|
||||
extern DWORD WINAPI wine_call_to_16( FARPROC16 target, DWORD cbArgs );
|
||||
extern void WINAPI wine_call_to_16_regs_short( CONTEXT86 *context, DWORD cbArgs );
|
||||
extern void WINAPI wine_call_to_16_regs_long ( CONTEXT86 *context, DWORD cbArgs );
|
||||
|
||||
/*
|
||||
* Arguments must be prepared in the correct order by the caller
|
||||
|
@ -299,17 +306,86 @@ BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags,
|
|||
*/
|
||||
memcpy( (LPBYTE)CURRENT_STACK16 - cbArgs, (LPBYTE)pArgs, cbArgs );
|
||||
|
||||
/*
|
||||
* Actually, we should take care whether the called routine cleans up
|
||||
* its stack or not. Fortunately, our wine_call_to_16 core doesn't rely on
|
||||
* the callee to do so; after the routine has returned, the 16-bit
|
||||
* stack pointer is always reset to the position it had before.
|
||||
*/
|
||||
if (dwFlags & (WCB16_REGS|WCB16_REGS_LONG))
|
||||
{
|
||||
CONTEXT *context = (CONTEXT *)pdwRetCode;
|
||||
|
||||
ret = wine_call_to_16( (FARPROC16)vpfn16, cbArgs );
|
||||
if (TRACE_ON(relay))
|
||||
{
|
||||
WORD *stack16 = (WORD *)CURRENT_STACK16;
|
||||
DWORD count = cbArgs / sizeof(WORD);
|
||||
|
||||
if ( pdwRetCode )
|
||||
*pdwRetCode = ret;
|
||||
DPRINTF("%04lx:CallTo16(func=%04lx:%04x,ds=%04lx",
|
||||
GetCurrentThreadId(),
|
||||
context->SegCs, LOWORD(context->Eip), context->SegDs );
|
||||
while (count--) DPRINTF( ",%04x", *--stack16 );
|
||||
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",
|
||||
(WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx,
|
||||
(WORD)context->Edx, (WORD)context->Esi, (WORD)context->Edi,
|
||||
(WORD)context->Ebp, (WORD)context->SegEs, (WORD)context->SegFs );
|
||||
SYSLEVEL_CheckNotLevel( 2 );
|
||||
}
|
||||
|
||||
_EnterWin16Lock();
|
||||
if (dwFlags & WCB16_REGS_LONG)
|
||||
wine_call_to_16_regs_long( context, cbArgs );
|
||||
else
|
||||
wine_call_to_16_regs_short( context, cbArgs );
|
||||
_LeaveWin16Lock();
|
||||
|
||||
if (TRACE_ON(relay))
|
||||
{
|
||||
DPRINTF("%04lx:RetFrom16() ss:sp=%04x:%04x ",
|
||||
GetCurrentThreadId(), SELECTOROF(NtCurrentTeb()->cur_stack),
|
||||
OFFSETOF(NtCurrentTeb()->cur_stack));
|
||||
DPRINTF(" ax=%04x bx=%04x cx=%04x dx=%04x bp=%04x sp=%04x\n",
|
||||
(WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx,
|
||||
(WORD)context->Edx, (WORD)context->Ebp, (WORD)context->Esp );
|
||||
SYSLEVEL_CheckNotLevel( 2 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
if (TRACE_ON(relay))
|
||||
{
|
||||
WORD *stack16 = (WORD *)CURRENT_STACK16;
|
||||
DWORD count = cbArgs / sizeof(WORD);
|
||||
|
||||
DPRINTF("%04lx:CallTo16(func=%04x:%04x,ds=%04x",
|
||||
GetCurrentThreadId(), HIWORD(vpfn16), LOWORD(vpfn16),
|
||||
SELECTOROF(NtCurrentTeb()->cur_stack) );
|
||||
while (count--) DPRINTF( ",%04x", *--stack16 );
|
||||
DPRINTF(") ss:sp=%04x:%04x\n",
|
||||
SELECTOROF(NtCurrentTeb()->cur_stack), OFFSETOF(NtCurrentTeb()->cur_stack) );
|
||||
SYSLEVEL_CheckNotLevel( 2 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Actually, we should take care whether the called routine cleans up
|
||||
* its stack or not. Fortunately, our wine_call_to_16 core doesn't rely on
|
||||
* the callee to do so; after the routine has returned, the 16-bit
|
||||
* stack pointer is always reset to the position it had before.
|
||||
*/
|
||||
_EnterWin16Lock();
|
||||
ret = wine_call_to_16( (FARPROC16)vpfn16, cbArgs );
|
||||
if (pdwRetCode) *pdwRetCode = ret;
|
||||
_LeaveWin16Lock();
|
||||
|
||||
if (TRACE_ON(relay))
|
||||
{
|
||||
DPRINTF("%04lx:RetFrom16() ss:sp=%04x:%04x retval=%08lx\n",
|
||||
GetCurrentThreadId(), SELECTOROF(NtCurrentTeb()->cur_stack),
|
||||
OFFSETOF(NtCurrentTeb()->cur_stack), ret);
|
||||
SYSLEVEL_CheckNotLevel( 2 );
|
||||
}
|
||||
}
|
||||
#else
|
||||
assert(0); /* cannot call to 16-bit on non-Intel architectures */
|
||||
#endif /* __i386__ */
|
||||
|
||||
return TRUE; /* success */
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "windef.h"
|
||||
#include "wine/winbase16.h"
|
||||
#include "wownt32.h"
|
||||
#include "miscemu.h"
|
||||
#include "task.h"
|
||||
#include "msdos.h"
|
||||
|
@ -362,7 +363,7 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
|
|||
ctx.SegEs = rmcb->regs_sel;
|
||||
ctx.Edi = rmcb->regs_ofs;
|
||||
/* FIXME: I'm pretty sure this isn't right - should push flags first */
|
||||
wine_call_to_16_regs_short(&ctx, 0);
|
||||
WOWCallback16Ex( 0, WCB16_REGS, 0, NULL, (DWORD *)&context );
|
||||
es = ctx.SegEs;
|
||||
edi = ctx.Edi;
|
||||
}
|
||||
|
@ -585,7 +586,7 @@ static void StartPM( CONTEXT86 *context )
|
|||
|
||||
__TRY
|
||||
{
|
||||
wine_call_to_16_regs_short(&pm_ctx, 0);
|
||||
WOWCallback16Ex( 0, WCB16_REGS, 0, NULL, (DWORD *)&pm_ctx );
|
||||
}
|
||||
__EXCEPT(dpmi_exception_handler)
|
||||
{
|
||||
|
|
103
if1632/relay.c
103
if1632/relay.c
|
@ -79,30 +79,6 @@ BOOL RELAY_Init(void)
|
|||
* (these will never be called but need to be present to satisfy the linker ...)
|
||||
*/
|
||||
#ifndef __i386__
|
||||
/***********************************************************************
|
||||
* wine_call_to_16 (KERNEL32.@)
|
||||
*/
|
||||
LONG WINAPI wine_call_to_16( FARPROC16 target, INT nArgs )
|
||||
{
|
||||
assert( FALSE );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* wine_call_to_16_regs_short (KERNEL32.@)
|
||||
*/
|
||||
void WINAPI wine_call_to_16_regs_short( CONTEXT86 *context, INT nArgs )
|
||||
{
|
||||
assert( FALSE );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* wine_call_to_16_regs_long (KERNEL32.@)
|
||||
*/
|
||||
void WINAPI wine_call_to_16_regs_long ( CONTEXT86 *context, INT nArgs )
|
||||
{
|
||||
assert( FALSE );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_call_from_16_word (KERNEL32.@)
|
||||
*/
|
||||
|
@ -387,82 +363,3 @@ void RELAY_DebugCallFrom16Ret( CONTEXT86 *context, int ret_val )
|
|||
}
|
||||
SYSLEVEL_CheckNotLevel( 2 );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RELAY_DebugCallTo16
|
||||
*
|
||||
* 'target' contains either the function to call (normal CallTo16)
|
||||
* or a pointer to the CONTEXT86 struct (register CallTo16).
|
||||
* 'nb_args' is the number of argument bytes on the 16-bit stack;
|
||||
* 'reg_func' specifies whether we have a register CallTo16 or not.
|
||||
*/
|
||||
void RELAY_DebugCallTo16( LPVOID target, int nb_args, BOOL reg_func )
|
||||
{
|
||||
WORD *stack16;
|
||||
TEB *teb;
|
||||
|
||||
if (!TRACE_ON(relay)) return;
|
||||
teb = NtCurrentTeb();
|
||||
stack16 = (WORD *)THREAD_STACK16(teb);
|
||||
|
||||
nb_args /= sizeof(WORD);
|
||||
|
||||
if ( reg_func )
|
||||
{
|
||||
CONTEXT86 *context = (CONTEXT86 *)target;
|
||||
|
||||
DPRINTF("%04lx:CallTo16(func=%04lx:%04x,ds=%04lx",
|
||||
GetCurrentThreadId(),
|
||||
context->SegCs, LOWORD(context->Eip), context->SegDs );
|
||||
while (nb_args--) DPRINTF( ",%04x", *--stack16 );
|
||||
DPRINTF(") ss:sp=%04x:%04x", SELECTOROF(teb->cur_stack),
|
||||
OFFSETOF(teb->cur_stack) );
|
||||
DPRINTF(" ax=%04x bx=%04x cx=%04x dx=%04x si=%04x di=%04x bp=%04x es=%04x fs=%04x\n",
|
||||
(WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx,
|
||||
(WORD)context->Edx, (WORD)context->Esi, (WORD)context->Edi,
|
||||
(WORD)context->Ebp, (WORD)context->SegEs, (WORD)context->SegFs );
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF("%04lx:CallTo16(func=%04x:%04x,ds=%04x",
|
||||
GetCurrentThreadId(),
|
||||
HIWORD(target), LOWORD(target), SELECTOROF(teb->cur_stack) );
|
||||
while (nb_args--) DPRINTF( ",%04x", *--stack16 );
|
||||
DPRINTF(") ss:sp=%04x:%04x\n", SELECTOROF(teb->cur_stack),
|
||||
OFFSETOF(teb->cur_stack) );
|
||||
}
|
||||
|
||||
SYSLEVEL_CheckNotLevel( 2 );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RELAY_DebugCallTo16Ret
|
||||
*/
|
||||
void RELAY_DebugCallTo16Ret( BOOL reg_func, int ret_val )
|
||||
{
|
||||
if (!TRACE_ON(relay)) return;
|
||||
|
||||
if (!reg_func)
|
||||
{
|
||||
DPRINTF("%04lx:RetFrom16() ss:sp=%04x:%04x retval=%08x\n",
|
||||
GetCurrentThreadId(),
|
||||
SELECTOROF(NtCurrentTeb()->cur_stack),
|
||||
OFFSETOF(NtCurrentTeb()->cur_stack), ret_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONTEXT86 *context = (CONTEXT86 *)ret_val;
|
||||
|
||||
DPRINTF("%04lx:RetFrom16() ss:sp=%04x:%04x ",
|
||||
GetCurrentThreadId(),
|
||||
SELECTOROF(NtCurrentTeb()->cur_stack),
|
||||
OFFSETOF(NtCurrentTeb()->cur_stack));
|
||||
DPRINTF(" ax=%04x bx=%04x cx=%04x dx=%04x bp=%04x sp=%04x\n",
|
||||
(WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx,
|
||||
(WORD)context->Edx, (WORD)context->Ebp, (WORD)context->Esp );
|
||||
}
|
||||
|
||||
SYSLEVEL_CheckNotLevel( 2 );
|
||||
}
|
||||
|
|
|
@ -38,13 +38,11 @@ typedef struct _STACK32FRAME
|
|||
SEGPTR frame16; /* 10 16-bit frame from last CallFrom16() */
|
||||
DWORD edi; /* 14 saved registers */
|
||||
DWORD esi; /* 18 */
|
||||
DWORD edx; /* 1c */
|
||||
DWORD ecx; /* 20 */
|
||||
DWORD ebx; /* 24 */
|
||||
DWORD ebp; /* 28 saved 32-bit frame pointer */
|
||||
DWORD retaddr; /* 2c return address */
|
||||
DWORD target; /* 30 target address / CONTEXT86 pointer */
|
||||
DWORD nb_args; /* 34 number of 16-bit argument bytes */
|
||||
DWORD ebx; /* 1c */
|
||||
DWORD ebp; /* 20 saved 32-bit frame pointer */
|
||||
DWORD retaddr; /* 24 return address */
|
||||
DWORD target; /* 28 target address / CONTEXT86 pointer */
|
||||
DWORD nb_args; /* 2c number of 16-bit argument bytes */
|
||||
} STACK32FRAME;
|
||||
|
||||
/* 16-bit stack layout after CallFrom16() */
|
||||
|
|
|
@ -220,6 +220,7 @@ HGLOBAL16 WINAPI GlobalLRUOldest16(HGLOBAL16);
|
|||
VOID WINAPI GlobalNotify16(FARPROC16);
|
||||
WORD WINAPI GlobalPageLock16(HGLOBAL16);
|
||||
WORD WINAPI GlobalPageUnlock16(HGLOBAL16);
|
||||
SEGPTR WINAPI HasGPHandler16(SEGPTR);
|
||||
BOOL16 WINAPI IsSharedSelector16(HANDLE16);
|
||||
BOOL16 WINAPI IsTask16(HTASK16);
|
||||
HTASK16 WINAPI IsTaskLocked16(void);
|
||||
|
@ -392,11 +393,6 @@ BOOL16 WINAPI WritePrivateProfileSection16(LPCSTR,LPCSTR,LPCSTR);
|
|||
BOOL16 WINAPI WritePrivateProfileStruct16(LPCSTR,LPCSTR,LPVOID,UINT16,LPCSTR);
|
||||
BOOL16 WINAPI WriteProfileSection16(LPCSTR,LPCSTR);
|
||||
|
||||
/* Wine-specific functions */
|
||||
LONG WINAPI wine_call_to_16( FARPROC16 target, INT nArgs );
|
||||
void WINAPI wine_call_to_16_regs_short( CONTEXT86 *context, INT nArgs );
|
||||
void WINAPI wine_call_to_16_regs_long ( CONTEXT86 *context, INT nArgs );
|
||||
|
||||
/* Some optimizations */
|
||||
extern inline LPVOID WINAPI MapSL( SEGPTR segptr )
|
||||
{
|
||||
|
|
|
@ -140,6 +140,10 @@ BOOL WINAPI K32WOWCallback16Ex(DWORD,DWORD,DWORD,LPVOID,LPDWORD);
|
|||
#define WCB16_CDECL 1
|
||||
#define WCB16_MAX_CBARGS 16
|
||||
|
||||
/* Wine extensions: call register function, context ptr is passed in the return value LPDWORD */
|
||||
#define WCB16_REGS 2
|
||||
#define WCB16_REGS_LONG 4 /* function uses 32-bit lret */
|
||||
|
||||
DWORD WINAPI WOWCallback16(DWORD,DWORD);
|
||||
BOOL WINAPI WOWCallback16Ex(DWORD,DWORD,DWORD,LPVOID,LPDWORD);
|
||||
|
||||
|
|
|
@ -485,8 +485,6 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
|
|||
|
||||
/* Save the 32-bit registers */
|
||||
fprintf( outfile, "\tpushl %%ebx\n" );
|
||||
fprintf( outfile, "\tpushl %%ecx\n" );
|
||||
fprintf( outfile, "\tpushl %%edx\n" );
|
||||
fprintf( outfile, "\tpushl %%esi\n" );
|
||||
fprintf( outfile, "\tpushl %%edi\n" );
|
||||
fprintf( outfile, "\t.byte 0x64\n\tmovl %%gs,(%d)\n", STRUCTOFFSET(TEB,gs_sel) );
|
||||
|
@ -500,28 +498,6 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
|
|||
fprintf( outfile, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-.L%s.getgot1], %%ebx\n", name );
|
||||
}
|
||||
|
||||
/* Print debugging info */
|
||||
if (debugging)
|
||||
{
|
||||
/* Push flags, number of arguments, and target */
|
||||
fprintf( outfile, "\tpushl $%d\n", reg_func );
|
||||
fprintf( outfile, "\tpushl 12(%%ebp)\n" );
|
||||
fprintf( outfile, "\tpushl 8(%%ebp)\n" );
|
||||
|
||||
if ( UsePIC )
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("RELAY_DebugCallTo16@PLT") "\n" );
|
||||
else
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("RELAY_DebugCallTo16") "\n" );
|
||||
|
||||
fprintf( outfile, "\taddl $12, %%esp\n" );
|
||||
}
|
||||
|
||||
/* Enter Win16 Mutex */
|
||||
if ( UsePIC )
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("_EnterWin16Lock@PLT") "\n" );
|
||||
else
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("_EnterWin16Lock") "\n" );
|
||||
|
||||
/* Setup exception frame */
|
||||
fprintf( outfile, "\t.byte 0x64\n\tpushl (%d)\n", STACKOFFSET );
|
||||
if (UsePIC)
|
||||
|
@ -551,10 +527,10 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
|
|||
|
||||
if ( !reg_func )
|
||||
{
|
||||
/* Convert and push return value */
|
||||
/* Convert return value */
|
||||
fprintf( outfile, "\tshll $16,%%edx\n" );
|
||||
fprintf( outfile, "\tmovw %%ax,%%dx\n" );
|
||||
fprintf( outfile, "\tpushl %%edx\n" );
|
||||
fprintf( outfile, "\tmovl %%edx,%%eax\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -578,46 +554,11 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
|
|||
fprintf( outfile, "\tmovl %%ebp, %d(%%edi)\n", CONTEXTOFFSET(Ebp) );
|
||||
fprintf( outfile, "\tmovl %%esi, %d(%%edi)\n", CONTEXTOFFSET(Esp) );
|
||||
/* The return glue code saved %esp into %esi */
|
||||
|
||||
fprintf( outfile, "\tpushl %%edi\n" );
|
||||
}
|
||||
|
||||
if ( UsePIC )
|
||||
{
|
||||
/* Get Global Offset Table into %ebx (might have been overwritten) */
|
||||
fprintf( outfile, "\tcall .L%s.getgot2\n", name );
|
||||
fprintf( outfile, ".L%s.getgot2:\n", name );
|
||||
fprintf( outfile, "\tpopl %%ebx\n" );
|
||||
fprintf( outfile, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-.L%s.getgot2], %%ebx\n", name );
|
||||
}
|
||||
|
||||
/* Leave Win16 Mutex */
|
||||
if ( UsePIC )
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("_LeaveWin16Lock@PLT") "\n" );
|
||||
else
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("_LeaveWin16Lock") "\n" );
|
||||
|
||||
/* Print debugging info */
|
||||
if (debugging)
|
||||
{
|
||||
fprintf( outfile, "\tpushl $%d\n", reg_func );
|
||||
|
||||
if ( UsePIC )
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("RELAY_DebugCallTo16Ret@PLT") "\n" );
|
||||
else
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("RELAY_DebugCallTo16Ret") "\n" );
|
||||
|
||||
fprintf( outfile, "\taddl $4, %%esp\n" );
|
||||
}
|
||||
|
||||
/* Get return value */
|
||||
fprintf( outfile, "\tpopl %%eax\n" );
|
||||
|
||||
/* Restore the 32-bit registers */
|
||||
fprintf( outfile, "\tpopl %%edi\n" );
|
||||
fprintf( outfile, "\tpopl %%esi\n" );
|
||||
fprintf( outfile, "\tpopl %%edx\n" );
|
||||
fprintf( outfile, "\tpopl %%ecx\n" );
|
||||
fprintf( outfile, "\tpopl %%ebx\n" );
|
||||
|
||||
/* Function exit sequence */
|
||||
|
|
|
@ -244,7 +244,7 @@ static LRESULT WINAPI WINPROC_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
|
|||
{
|
||||
CONTEXT86 context;
|
||||
LRESULT ret;
|
||||
WORD *args;
|
||||
WORD args[5];
|
||||
DWORD offset = 0;
|
||||
TEB *teb = NtCurrentTeb();
|
||||
int iWndsLocks;
|
||||
|
@ -287,15 +287,14 @@ static LRESULT WINAPI WINPROC_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
|
|||
|
||||
iWndsLocks = WIN_SuspendWndsLock();
|
||||
|
||||
args = (WORD *)THREAD_STACK16(teb) - 5;
|
||||
args[0] = LOWORD(lParam);
|
||||
args[1] = HIWORD(lParam);
|
||||
args[2] = wParam;
|
||||
args[3] = msg;
|
||||
args[4] = hwnd;
|
||||
|
||||
wine_call_to_16_regs_short( &context, 5 * sizeof(WORD) );
|
||||
args[3] = msg;
|
||||
args[2] = wParam;
|
||||
args[1] = HIWORD(lParam);
|
||||
args[0] = LOWORD(lParam);
|
||||
WOWCallback16Ex( 0, WCB16_REGS, sizeof(args), args, (DWORD *)&context );
|
||||
ret = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) );
|
||||
|
||||
if (offset) stack16_pop( offset );
|
||||
|
||||
WIN_RestoreWndsLock(iWndsLocks);
|
||||
|
|
Loading…
Reference in New Issue