diff --git a/if1632/relay.c b/if1632/relay.c index 9e4e304a0d3..38df3abd153 100644 --- a/if1632/relay.c +++ b/if1632/relay.c @@ -67,10 +67,10 @@ WORD CALLBACK CallTo16Word( FARPROC16 target, INT nArgs ) LONG CALLBACK CallTo16Long( FARPROC16 target, INT nArgs ) { assert( FALSE ); } -LONG CALLBACK CallTo16RegisterShort( const CONTEXT86 *context, INT nArgs ) +void CALLBACK CallTo16RegisterShort( CONTEXT86 *context, INT nArgs ) { assert( FALSE ); } -LONG CALLBACK CallTo16RegisterLong ( const CONTEXT86 *context, INT nArgs ) +void CALLBACK CallTo16RegisterLong ( CONTEXT86 *context, INT nArgs ) { assert( FALSE ); } WORD CallFrom16Word( void ) @@ -327,12 +327,27 @@ void RELAY_DebugCallTo16( LPVOID target, int nb_args, BOOL reg_func ) /*********************************************************************** * RELAY_DebugCallTo16Ret */ -void RELAY_DebugCallTo16Ret( int ret_val ) +void RELAY_DebugCallTo16Ret( BOOL reg_func, int ret_val ) { if (!TRACE_ON(relay)) return; - DPRINTF("CallTo16() ss:sp=%04x:%04x retval=0x%08x\n", - SELECTOROF(NtCurrentTeb()->cur_stack), - OFFSETOF(NtCurrentTeb()->cur_stack), ret_val); + if (!reg_func) + { + DPRINTF("CallTo16() ss:sp=%04x:%04x retval=0x%08x\n", + SELECTOROF(NtCurrentTeb()->cur_stack), + OFFSETOF(NtCurrentTeb()->cur_stack), ret_val); + } + else + { + CONTEXT86 *context = (CONTEXT86 *)ret_val; + + DPRINTF("CallTo16() ss:sp=%04x:%04x\n", + SELECTOROF(NtCurrentTeb()->cur_stack), + OFFSETOF(NtCurrentTeb()->cur_stack)); + DPRINTF(" AX=%04x BX=%04x CX=%04x DX=%04x BP=%04x SP=%04x\n", + AX_reg(context), BX_reg(context), CX_reg(context), + DX_reg(context), BP_reg(context), LOWORD(ESP_reg(context))); + } + SYSLEVEL_CheckNotLevel( 2 ); } diff --git a/include/builtin16.h b/include/builtin16.h index e069ad8873b..1ffe173b4c9 100644 --- a/include/builtin16.h +++ b/include/builtin16.h @@ -20,8 +20,8 @@ extern void CallFrom16Thunk(); extern WORD CALLBACK CallTo16Word( FARPROC16 target, INT nArgs ); extern LONG CALLBACK CallTo16Long( FARPROC16 target, INT nArgs ); -extern LONG CALLBACK CallTo16RegisterShort( const struct _CONTEXT86 *context, INT nArgs ); -extern LONG CALLBACK CallTo16RegisterLong ( const struct _CONTEXT86 *context, INT nArgs ); +extern void CALLBACK CallTo16RegisterShort( struct _CONTEXT86 *context, INT nArgs ); +extern void CALLBACK CallTo16RegisterLong ( struct _CONTEXT86 *context, INT nArgs ); #include "pshpack1.h" diff --git a/loader/ne/module.c b/loader/ne/module.c index 590a5f97918..5bbceb5e289 100644 --- a/loader/ne/module.c +++ b/loader/ne/module.c @@ -1193,7 +1193,8 @@ static void NE_InitProcess(void) SELECTOROF(pTask->teb->cur_stack), OFFSETOF(pTask->teb->cur_stack) ); - ExitThread( CallTo16RegisterShort( &context, 0 ) ); + CallTo16RegisterShort( &context, 0 ); + ExitThread( AX_reg( &context ) ); } SYSLEVEL_LeaveWin16Lock(); diff --git a/tools/winebuild/relay.c b/tools/winebuild/relay.c index fdab80cc28d..018dc45d6f3 100644 --- a/tools/winebuild/relay.c +++ b/tools/winebuild/relay.c @@ -504,20 +504,44 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func ) fprintf( outfile, "\tpushl %%cs\n" ); fprintf( outfile, "\tcall .LCallTo16%s\n", name ); - /* Convert and push return value */ - if ( short_ret ) + if ( !reg_func ) { - fprintf( outfile, "\tmovzwl %%ax, %%eax\n" ); - fprintf( outfile, "\tpushl %%eax\n" ); - } - else if ( reg_func != 2 ) - { - fprintf( outfile, "\tshll $16,%%edx\n" ); - fprintf( outfile, "\tmovw %%ax,%%dx\n" ); - fprintf( outfile, "\tpushl %%edx\n" ); + /* Convert and push return value */ + if ( short_ret ) + { + fprintf( outfile, "\tmovzwl %%ax, %%eax\n" ); + fprintf( outfile, "\tpushl %%eax\n" ); + } + else + { + fprintf( outfile, "\tshll $16,%%edx\n" ); + fprintf( outfile, "\tmovw %%ax,%%dx\n" ); + fprintf( outfile, "\tpushl %%edx\n" ); + } } else - fprintf( outfile, "\tpushl %%eax\n" ); + { + /* + * Modify CONTEXT86 structure to contain new values + * + * NOTE: We restore only EAX, EBX, EDX, EDX, EBP, and ESP. + * The segment registers as well as ESI and EDI should + * not be modified by a well-behaved 16-bit routine in + * any case. [If necessary, we could restore them as well, + * at the cost of a somewhat less efficient return path.] + */ + + fprintf( outfile, "\tmovl %d(%%esp), %%edi\n", STACK32OFFSET(target)-12 ); + fprintf( outfile, "\tmovl %%eax, %d(%%edi)\n", CONTEXTOFFSET(Eax) ); + fprintf( outfile, "\tmovl %%ebx, %d(%%edi)\n", CONTEXTOFFSET(Ebx) ); + fprintf( outfile, "\tmovl %%ecx, %d(%%edi)\n", CONTEXTOFFSET(Ecx) ); + fprintf( outfile, "\tmovl %%edx, %d(%%edi)\n", CONTEXTOFFSET(Edx) ); + 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 ) { @@ -531,10 +555,14 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func ) /* Print debugging info */ if (debugging) { + fprintf( outfile, "\tpushl $%d\n", reg_func ); + if ( UsePIC ) fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16Ret@PLT\n" ); else fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16Ret\n" ); + + fprintf( outfile, "\taddl $4, %%esp\n" ); } /* Leave Win16 Mutex */ @@ -657,17 +685,20 @@ static void BuildRet16Func( FILE *outfile ) fprintf( outfile, "\t.globl " PREFIX "CallTo16_Ret\n" ); fprintf( outfile, PREFIX "CallTo16_Ret:\n" ); + /* Save %esp into %esi */ + fprintf( outfile, "\tmovl %%esp,%%esi\n" ); + /* Restore 32-bit segment registers */ - fprintf( outfile, "\tmovw $0x%04x,%%bx\n", data_selector ); + fprintf( outfile, "\tmovw $0x%04x,%%di\n", data_selector ); #ifdef __svr4__ fprintf( outfile, "\tdata16\n"); #endif - fprintf( outfile, "\tmovw %%bx,%%ds\n" ); + fprintf( outfile, "\tmovw %%di,%%ds\n" ); #ifdef __svr4__ fprintf( outfile, "\tdata16\n"); #endif - fprintf( outfile, "\tmovw %%bx,%%es\n" ); + fprintf( outfile, "\tmovw %%di,%%es\n" ); fprintf( outfile, "\tmovw " PREFIX "SYSLEVEL_Win16CurrentTeb,%%fs\n" ); @@ -676,7 +707,7 @@ static void BuildRet16Func( FILE *outfile ) #ifdef __svr4__ fprintf( outfile, "\tdata16\n"); #endif - fprintf( outfile, "\tmovw %%bx,%%ss\n" ); + fprintf( outfile, "\tmovw %%di,%%ss\n" ); fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%esp\n", STACKOFFSET ); fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET ); diff --git a/windows/winproc.c b/windows/winproc.c index 5afea862b4a..87172379b9c 100644 --- a/windows/winproc.c +++ b/windows/winproc.c @@ -238,7 +238,8 @@ static LRESULT WINAPI WINPROC_CallWndProc16( WNDPROC16 proc, HWND16 hwnd, args[3] = msg; args[4] = hwnd; - ret = CallTo16RegisterShort( &context, 5 * sizeof(WORD) ); + CallTo16RegisterShort( &context, 5 * sizeof(WORD) ); + ret = MAKELONG( AX_reg(&context), DX_reg(&context) ); if (offset) stack16_pop( offset ); WIN_RestoreWndsLock(iWndsLocks);