Instead of using a dedicated stack.
The dedicated stack was introduced by 9d7ff6c85b0827b7f54989050b4c34f1f459e94d, in order to support potentially nested DPMI interrupts. DPMI support was removed by ed6bdb3c51cd4b8c94f9839806321703e7aa9765; hence there is no longer a reason to account for nested interrupts.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/krnl386.exe16/dosexe.h | 2 - dlls/krnl386.exe16/dosmem.c | 8 -- dlls/krnl386.exe16/interrupts.c | 9 +-- dlls/krnl386.exe16/relay.c | 132 +------------------------------- 4 files changed, 3 insertions(+), 148 deletions(-)
diff --git a/dlls/krnl386.exe16/dosexe.h b/dlls/krnl386.exe16/dosexe.h index c4c8def5dce..42b8e0f4437 100644 --- a/dlls/krnl386.exe16/dosexe.h +++ b/dlls/krnl386.exe16/dosexe.h @@ -41,7 +41,6 @@ typedef void (WINAPI *INTPROC)(CONTEXT*); extern WORD DOSVM_psp DECLSPEC_HIDDEN; /* psp of current DOS task */ extern WORD int16_sel DECLSPEC_HIDDEN; extern WORD relay_code_sel DECLSPEC_HIDDEN; -extern WORD relay_data_sel DECLSPEC_HIDDEN;
#define ADD_LOWORD(dw,val) ((dw) = ((dw) & 0xffff0000) | LOWORD((DWORD)(dw)+(val)))
@@ -247,7 +246,6 @@ extern DWORD DOSVM_inport( int port, int size ) DECLSPEC_HIDDEN; extern void DOSVM_outport( int port, int size, DWORD value ) DECLSPEC_HIDDEN;
/* relay.c */ -void DOSVM_RelayHandler( CONTEXT * ) DECLSPEC_HIDDEN; void DOSVM_BuildCallFrame( CONTEXT *, DOSRELAY, LPVOID ) DECLSPEC_HIDDEN;
#endif /* __WINE_DOSEXE_H */ diff --git a/dlls/krnl386.exe16/dosmem.c b/dlls/krnl386.exe16/dosmem.c index 36b02aec484..2d55eb050de 100644 --- a/dlls/krnl386.exe16/dosmem.c +++ b/dlls/krnl386.exe16/dosmem.c @@ -45,7 +45,6 @@ WORD DOSMEM_BiosSysSeg; /* BIOS ROM segment at 0xf000:0 */ WORD DOSVM_psp = 0; WORD int16_sel = 0; WORD relay_code_sel = 0; -WORD relay_data_sel = 0;
/* DOS memory highest address (including HMA) */ #define DOSMEM_SIZE 0x110000 @@ -306,7 +305,6 @@ static void DOSMEM_InitSegments(void) static const char relay[]= { 0xca, 0x04, 0x00, /* 16-bit far return and pop 4 bytes (relay void* arg) */ - 0xcd, 0x31, /* int 31 */ };
/* @@ -330,17 +328,11 @@ static void DOSMEM_InitSegments(void)
/* * PM / offset 0: Stub where __wine_call_from_16_regs returns. - * PM / offset 3: Stub which swaps back to 32-bit application code/stack. */ relay_code_sel = GLOBAL_Alloc( GMEM_FIXED, sizeof(relay), 0, LDT_FLAGS_CODE ); ptr = GlobalLock16( relay_code_sel ); memcpy( ptr, relay, sizeof(relay) ); GlobalUnlock16( relay_code_sel ); - - /* - * Space for 16-bit stack used by relay code. - */ - relay_data_sel = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, DOSVM_RELAY_DATA_SIZE ); }
/****************************************************************** diff --git a/dlls/krnl386.exe16/interrupts.c b/dlls/krnl386.exe16/interrupts.c index e2a129e4a20..d397d20072d 100644 --- a/dlls/krnl386.exe16/interrupts.c +++ b/dlls/krnl386.exe16/interrupts.c @@ -250,14 +250,7 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum )
DOSMEM_InitDosMemory();
- if (context->SegCs == relay_code_sel) - { - /* - * This must not be called using DOSVM_BuildCallFrame. - */ - DOSVM_RelayHandler( context ); - } - else if (context->SegCs == int16_sel) + if (context->SegCs == int16_sel) { /* Restore original flags stored into the stack by the caller. */ WORD *stack = CTX_SEG_OFF_TO_LIN(context, diff --git a/dlls/krnl386.exe16/relay.c b/dlls/krnl386.exe16/relay.c index 3559bb460a7..116198e5ddb 100644 --- a/dlls/krnl386.exe16/relay.c +++ b/dlls/krnl386.exe16/relay.c @@ -34,26 +34,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(relay);
-/* - * Magic DWORD used to check stack integrity. - */ -#define RELAY_MAGIC 0xabcdef00 - -/* - * Memory block for temporary 16-bit stacks used with relay calls. - */ -typedef struct { - DWORD inuse; /* non-zero if stack block is in use */ - DWORD eip; /* saved ip */ - DWORD seg_cs; /* saved cs */ - DWORD esp; /* saved sp */ - DWORD seg_ss; /* saved ss */ - DWORD stack_bottom; /* guard dword */ - BYTE stack[256-7*4]; /* 16-bit stack */ - DWORD stack_top; /* guard dword */ -} RELAY_Stack16; - - static const char **debug_relay_excludelist; static const char **debug_relay_includelist; static const char **debug_snoop_excludelist; @@ -572,58 +552,6 @@ int relay_call_from_16( void *entry_point, unsigned char *args16, CONTEXT *conte return ret_val; }
-/********************************************************************** - * RELAY_GetPointer - * - * Get pointer to stack block when given esp pointing to 16-bit stack - * inside relay data segment. - */ -static RELAY_Stack16 *RELAY_GetPointer( DWORD offset ) -{ - offset = offset / sizeof(RELAY_Stack16) * sizeof(RELAY_Stack16); - return MapSL(MAKESEGPTR(relay_data_sel, offset)); -} - - -/********************************************************************** - * RELAY_MakeShortContext - * - * Allocate separate 16-bit stack, make stack pointer point to this - * stack and make code pointer point to stub that restores everything. - * So, after this routine, SS and CS are guaranteed to be 16-bit. - * - * Note: This might be called from signal handler, so the stack - * allocation algorithm must be signal safe. - */ -static void RELAY_MakeShortContext( CONTEXT *context ) -{ - DWORD offset = offsetof(RELAY_Stack16, stack_top); - RELAY_Stack16 *stack = RELAY_GetPointer( 0 ); - - while (stack->inuse && offset < DOSVM_RELAY_DATA_SIZE) { - stack++; - offset += sizeof(RELAY_Stack16); - } - - if (offset >= DOSVM_RELAY_DATA_SIZE) - ERR( "Too many nested interrupts!\n" ); - - stack->inuse = 1; - stack->eip = context->Eip; - stack->seg_cs = context->SegCs; - stack->esp = context->Esp; - stack->seg_ss = context->SegSs; - - stack->stack_bottom = RELAY_MAGIC; - stack->stack_top = RELAY_MAGIC; - - context->SegSs = relay_data_sel; - context->Esp = offset; - context->SegCs = relay_code_sel; - context->Eip = 3; -} - - /********************************************************************** * RELAY_RelayStub * @@ -632,58 +560,9 @@ static void RELAY_MakeShortContext( CONTEXT *context ) */ static void __stdcall RELAY_RelayStub( DOSRELAY proc, unsigned char *args, CONTEXT *context ) { - if (proc) - { - RELAY_Stack16 *stack = RELAY_GetPointer( context->Esp ); - - DWORD old_seg_cs = context->SegCs; - DWORD old_eip = context->Eip; - DWORD old_seg_ss = context->SegSs; - DWORD old_esp = context->Esp; - - context->SegCs = stack->seg_cs; - context->Eip = stack->eip; - context->SegSs = stack->seg_ss; - context->Esp = stack->esp; - - proc( context, *(LPVOID *)args ); - - stack->seg_cs = context->SegCs; - stack->eip = context->Eip; - stack->seg_ss = context->SegSs; - stack->esp = context->Esp; - - context->SegCs = old_seg_cs; - context->Eip = old_eip; - context->SegSs = old_seg_ss; - context->Esp = old_esp; - } + proc( context, *(LPVOID *)args ); }
- -/********************************************************************** - * DOSVM_RelayHandler - * - * Restore saved code and stack pointers and release stack block. - */ -void DOSVM_RelayHandler( CONTEXT *context ) -{ - RELAY_Stack16 *stack = RELAY_GetPointer( context->Esp ); - - context->SegSs = stack->seg_ss; - context->Esp = stack->esp; - context->SegCs = stack->seg_cs; - context->Eip = stack->eip; - - if (!stack->inuse || - stack->stack_bottom != RELAY_MAGIC || - stack->stack_top != RELAY_MAGIC) - ERR( "Stack corrupted!\n" ); - - stack->inuse = 0; -} - - /********************************************************************** * DOSVM_BuildCallFrame * @@ -692,13 +571,6 @@ void DOSVM_RelayHandler( CONTEXT *context ) */ void DOSVM_BuildCallFrame( CONTEXT *context, DOSRELAY relay, LPVOID data ) { - WORD code_sel = relay_code_sel; - - /* - * Allocate separate stack for relay call. - */ - RELAY_MakeShortContext( context ); - /* * Build call frame. */ @@ -713,7 +585,7 @@ void DOSVM_BuildCallFrame( CONTEXT *context, DOSRELAY relay, LPVOID data ) PUSH_WORD16( context, HIWORD(RELAY_RelayStub) ); /* STACK16FRAME.relay.hiword */ PUSH_WORD16( context, LOWORD(RELAY_RelayStub) ); /* STACK16FRAME.relay.loword */ PUSH_WORD16( context, 0 ); /* STACK16FRAME.module_cs.hiword */ - PUSH_WORD16( context, code_sel ); /* STACK16FRAME.module_cs.loword */ + PUSH_WORD16( context, relay_code_sel ); /* STACK16FRAME.module_cs.loword */ PUSH_WORD16( context, 0 ); /* STACK16FRAME.callfrom_ip.hiword */ PUSH_WORD16( context, 0 ); /* STACK16FRAME.callfrom_ip.loword */
Instead of manually building a STACK16FRAME.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- I have changes planned that modify the STACK16FRAME layout and the 16-to-32 assembly code. This becomes much easier when there are not a half dozen places which must implicitly be kept in sync.
dlls/ifsmgr.vxd/ifsmgr.c | 6 ++-- dlls/krnl386.exe16/dosexe.h | 6 +--- dlls/krnl386.exe16/dosmem.c | 14 --------- dlls/krnl386.exe16/instr.c | 4 +-- dlls/krnl386.exe16/interrupts.c | 37 +++++++++++----------- dlls/krnl386.exe16/krnl386.exe16.spec | 3 +- dlls/krnl386.exe16/relay.c | 44 --------------------------- dlls/vwin32.vxd/vwin32.c | 6 ++-- 8 files changed, 30 insertions(+), 90 deletions(-)
diff --git a/dlls/ifsmgr.vxd/ifsmgr.c b/dlls/ifsmgr.vxd/ifsmgr.c index 2fe3198a6ba..ab232ec6c23 100644 --- a/dlls/ifsmgr.vxd/ifsmgr.c +++ b/dlls/ifsmgr.vxd/ifsmgr.c @@ -97,7 +97,7 @@ static void CONTEXT_2_win32apieq(const CONTEXT *pCxt, struct win32apireq *pOut) /* FIXME: pOut->ar_pad ignored */ }
-extern void __wine_call_int_handler( CONTEXT *context, BYTE intnum ); +extern void WINAPI __wine_call_int_handler16( BYTE intnum, CONTEXT *context );
/*********************************************************************** * DeviceIoControl (IFSMGR.VXD.@) @@ -132,9 +132,9 @@ BOOL WINAPI IFSMGR_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpvInBuffer, DW win32apieq_2_CONTEXT(pIn,&cxt);
if(dwIoControlCode==IFS_IOCTL_21) - __wine_call_int_handler( &cxt, 0x21 ); + __wine_call_int_handler16( 0x21, &cxt ); else - __wine_call_int_handler( &cxt, 0x2f ); + __wine_call_int_handler16( 0x2f, &cxt );
CONTEXT_2_win32apieq(&cxt,pOut); return TRUE; diff --git a/dlls/krnl386.exe16/dosexe.h b/dlls/krnl386.exe16/dosexe.h index 42b8e0f4437..1e4d15c75e5 100644 --- a/dlls/krnl386.exe16/dosexe.h +++ b/dlls/krnl386.exe16/dosexe.h @@ -40,7 +40,6 @@ typedef void (WINAPI *INTPROC)(CONTEXT*);
extern WORD DOSVM_psp DECLSPEC_HIDDEN; /* psp of current DOS task */ extern WORD int16_sel DECLSPEC_HIDDEN; -extern WORD relay_code_sel DECLSPEC_HIDDEN;
#define ADD_LOWORD(dw,val) ((dw) = ((dw) & 0xffff0000) | LOWORD((DWORD)(dw)+(val)))
@@ -236,7 +235,7 @@ extern void WINAPI DOSVM_Int2fHandler(CONTEXT*) DECLSPEC_HIDDEN; extern void WINAPI DOSVM_Int31Handler(CONTEXT*) DECLSPEC_HIDDEN;
/* interrupts.c */ -extern void __wine_call_int_handler( CONTEXT *, BYTE ) DECLSPEC_HIDDEN; +extern void WINAPI __wine_call_int_handler16( BYTE, CONTEXT * ) DECLSPEC_HIDDEN; extern BOOL DOSVM_EmulateInterruptPM( CONTEXT *, BYTE ) DECLSPEC_HIDDEN; extern FARPROC16 DOSVM_GetPMHandler16( BYTE ) DECLSPEC_HIDDEN; extern void DOSVM_SetPMHandler16( BYTE, FARPROC16 ) DECLSPEC_HIDDEN; @@ -245,7 +244,4 @@ extern void DOSVM_SetPMHandler16( BYTE, FARPROC16 ) DECLSPEC_HIDDEN; extern DWORD DOSVM_inport( int port, int size ) DECLSPEC_HIDDEN; extern void DOSVM_outport( int port, int size, DWORD value ) DECLSPEC_HIDDEN;
-/* relay.c */ -void DOSVM_BuildCallFrame( CONTEXT *, DOSRELAY, LPVOID ) DECLSPEC_HIDDEN; - #endif /* __WINE_DOSEXE_H */ diff --git a/dlls/krnl386.exe16/dosmem.c b/dlls/krnl386.exe16/dosmem.c index 2d55eb050de..64df77a3747 100644 --- a/dlls/krnl386.exe16/dosmem.c +++ b/dlls/krnl386.exe16/dosmem.c @@ -44,7 +44,6 @@ WORD DOSMEM_BiosSysSeg; /* BIOS ROM segment at 0xf000:0 */
WORD DOSVM_psp = 0; WORD int16_sel = 0; -WORD relay_code_sel = 0;
/* DOS memory highest address (including HMA) */ #define DOSMEM_SIZE 0x110000 @@ -302,11 +301,6 @@ static void DOSMEM_InitSegments(void) LPSTR ptr; int i;
- static const char relay[]= - { - 0xca, 0x04, 0x00, /* 16-bit far return and pop 4 bytes (relay void* arg) */ - }; - /* * PM / offset N*5: Interrupt N in 16-bit protected mode. */ @@ -325,14 +319,6 @@ static void DOSMEM_InitSegments(void) ptr[i * 5 + 4] = 0x00; } GlobalUnlock16( int16_sel ); - - /* - * PM / offset 0: Stub where __wine_call_from_16_regs returns. - */ - relay_code_sel = GLOBAL_Alloc( GMEM_FIXED, sizeof(relay), 0, LDT_FLAGS_CODE ); - ptr = GlobalLock16( relay_code_sel ); - memcpy( ptr, relay, sizeof(relay) ); - GlobalUnlock16( relay_code_sel ); }
/****************************************************************** diff --git a/dlls/krnl386.exe16/instr.c b/dlls/krnl386.exe16/instr.c index ff7f866f9e0..789c6dfb212 100644 --- a/dlls/krnl386.exe16/instr.c +++ b/dlls/krnl386.exe16/instr.c @@ -895,7 +895,7 @@ LONG CALLBACK INSTR_vectored_handler( EXCEPTION_POINTERS *ptrs ) */ void WINAPI DOS3Call( CONTEXT *context ) { - __wine_call_int_handler( context, 0x21 ); + __wine_call_int_handler16( 0x21, context ); }
@@ -904,7 +904,7 @@ void WINAPI DOS3Call( CONTEXT *context ) */ void WINAPI NetBIOSCall16( CONTEXT *context ) { - __wine_call_int_handler( context, 0x5c ); + __wine_call_int_handler16( 0x5c, context ); }
diff --git a/dlls/krnl386.exe16/interrupts.c b/dlls/krnl386.exe16/interrupts.c index d397d20072d..3c99eabcbba 100644 --- a/dlls/krnl386.exe16/interrupts.c +++ b/dlls/krnl386.exe16/interrupts.c @@ -120,19 +120,25 @@ static INTPROC DOSVM_GetBuiltinHandler( BYTE intnum ) return DOSVM_DefaultHandler; }
- -/********************************************************************** - * DOSVM_IntProcRelay +/* Set up the context so that we will call __wine_call_int_handler16 upon + * resuming execution. * - * Simple DOSRELAY that interprets its argument as INTPROC and calls it. - */ -static void DOSVM_IntProcRelay( CONTEXT *context, LPVOID data ) + * We can't just call the interrupt handler directly, since some code (in + * particular, LoadModule16) assumes that it's running on the 32-bit stack and + * that CURRENT_STACK16 points to the bottom of the used 16-bit stack. */ +static void return_to_interrupt_handler( CONTEXT *context, BYTE intnum ) { - INTPROC proc = (INTPROC)data; - proc(context); + FARPROC16 addr = GetProcAddress16( GetModuleHandle16( "KERNEL" ), "__wine_call_int_handler" ); + WORD *stack = ldt_get_ptr( context->SegSs, context->Esp ); + + *--stack = intnum; + *--stack = context->SegCs; + *--stack = context->Eip; + context->Esp -= 3 * sizeof(WORD); + context->SegCs = SELECTOROF(addr); + context->Eip = OFFSETOF(addr); }
- /********************************************************************** * DOSVM_PushFlags * @@ -205,10 +211,7 @@ static void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum ) if (intnum == 0x25 || intnum == 0x26) DOSVM_PushFlags( context, FALSE, FALSE );
- DOSVM_BuildCallFrame( context, - DOSVM_IntProcRelay, - DOSVM_GetBuiltinHandler( - OFFSETOF(addr)/DOSVM_STUB_PM16 ) ); + return_to_interrupt_handler( context, OFFSETOF(addr) / DOSVM_STUB_PM16 ); } else { @@ -267,9 +270,7 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum ) if (intnum == 0x25 || intnum == 0x26) DOSVM_PushFlags( context, FALSE, TRUE );
- DOSVM_BuildCallFrame( context, - DOSVM_IntProcRelay, - DOSVM_GetBuiltinHandler(intnum) ); + return_to_interrupt_handler( context, intnum ); } else if (ldt_is_system(context->SegCs)) { @@ -399,9 +400,9 @@ static void DOSVM_CallBuiltinHandler( CONTEXT *context, BYTE intnum )
/********************************************************************** - * __wine_call_int_handler (KERNEL.@) + * __wine_call_int_handler16 (KERNEL.@) */ -void __wine_call_int_handler( CONTEXT *context, BYTE intnum ) +void WINAPI __wine_call_int_handler16( BYTE intnum, CONTEXT *context ) { DOSMEM_InitDosMemory(); DOSVM_CallBuiltinHandler( context, intnum ); diff --git a/dlls/krnl386.exe16/krnl386.exe16.spec b/dlls/krnl386.exe16/krnl386.exe16.spec index ddd321cbc31..c6ffd9df701 100644 --- a/dlls/krnl386.exe16/krnl386.exe16.spec +++ b/dlls/krnl386.exe16/krnl386.exe16.spec @@ -741,7 +741,8 @@ # or 'wine_' (for user-visible functions) to avoid namespace conflicts.
# DOS support -@ cdecl -arch=win32 __wine_call_int_handler(ptr long) +2000 pascal -register __wine_call_int_handler(word) __wine_call_int_handler16 +@ stdcall -arch=win32 __wine_call_int_handler16(long ptr)
# VxDs @ cdecl -arch=win32 -private __wine_vxd_open(wstr long ptr) diff --git a/dlls/krnl386.exe16/relay.c b/dlls/krnl386.exe16/relay.c index 116198e5ddb..2ec657bd3f8 100644 --- a/dlls/krnl386.exe16/relay.c +++ b/dlls/krnl386.exe16/relay.c @@ -551,47 +551,3 @@ int relay_call_from_16( void *entry_point, unsigned char *args16, CONTEXT *conte } return ret_val; } - -/********************************************************************** - * RELAY_RelayStub - * - * This stub is called by __wine_call_from_16_regs in order to marshall - * relay parameters. - */ -static void __stdcall RELAY_RelayStub( DOSRELAY proc, unsigned char *args, CONTEXT *context ) -{ - proc( context, *(LPVOID *)args ); -} - -/********************************************************************** - * DOSVM_BuildCallFrame - * - * Modifies the context so that return to context calls DOSRELAY and - * only after return from DOSRELAY the original context will be returned to. - */ -void DOSVM_BuildCallFrame( CONTEXT *context, DOSRELAY relay, LPVOID data ) -{ - /* - * Build call frame. - */ - PUSH_WORD16( context, HIWORD(data) ); /* argument.hiword */ - PUSH_WORD16( context, LOWORD(data) ); /* argument.loword */ - PUSH_WORD16( context, context->SegCs ); /* STACK16FRAME.cs */ - PUSH_WORD16( context, LOWORD(context->Eip) ); /* STACK16FRAME.ip */ - PUSH_WORD16( context, LOWORD(context->Ebp) ); /* STACK16FRAME.bp */ - PUSH_WORD16( context, HIWORD(relay) ); /* STACK16FRAME.entry_point.hiword */ - PUSH_WORD16( context, LOWORD(relay) ); /* STACK16FRAME.entry_point.loword */ - PUSH_WORD16( context, 0 ); /* STACK16FRAME.entry_ip */ - PUSH_WORD16( context, HIWORD(RELAY_RelayStub) ); /* STACK16FRAME.relay.hiword */ - PUSH_WORD16( context, LOWORD(RELAY_RelayStub) ); /* STACK16FRAME.relay.loword */ - PUSH_WORD16( context, 0 ); /* STACK16FRAME.module_cs.hiword */ - PUSH_WORD16( context, relay_code_sel ); /* STACK16FRAME.module_cs.loword */ - PUSH_WORD16( context, 0 ); /* STACK16FRAME.callfrom_ip.hiword */ - PUSH_WORD16( context, 0 ); /* STACK16FRAME.callfrom_ip.loword */ - - /* - * Adjust code pointer. - */ - context->SegCs = get_cs(); - context->Eip = (DWORD)__wine_call_from_16_regs; -} diff --git a/dlls/vwin32.vxd/vwin32.c b/dlls/vwin32.vxd/vwin32.c index 82fa80c4e65..5a33f2ba665 100644 --- a/dlls/vwin32.vxd/vwin32.c +++ b/dlls/vwin32.vxd/vwin32.c @@ -55,7 +55,7 @@ typedef struct tagMID { } MID, *PMID; #include <poppack.h>
-extern void __wine_call_int_handler( CONTEXT *context, BYTE intnum ); +extern void WINAPI __wine_call_int_handler16( BYTE intnum, CONTEXT *context );
/* Pop a DWORD from the 32-bit stack */ static inline DWORD stack32_pop( CONTEXT *context ) @@ -155,7 +155,7 @@ BOOL WINAPI VWIN32_DeviceIoControl(DWORD dwIoControlCode, break; }
- __wine_call_int_handler( &cxt, intnum ); + __wine_call_int_handler16( intnum, &cxt ); CONTEXT_2_DIOCRegs( &cxt, pOut ); } return TRUE; @@ -208,7 +208,7 @@ DWORD WINAPI VWIN32_VxDCall( DWORD service, CONTEXT *context )
context->Eax = callnum; context->Ecx = parm; - __wine_call_int_handler( context, 0x31 ); + __wine_call_int_handler16( 0x31, context ); return LOWORD(context->Eax); } case 0x002a: /* Int41 dispatch - parm = int41 service number */
Instead of manually building a STACK16FRAME.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/krnl386.exe16/krnl386.exe16.spec | 4 ++ dlls/krnl386.exe16/snoop.c | 56 +++++---------------------- 2 files changed, 13 insertions(+), 47 deletions(-)
diff --git a/dlls/krnl386.exe16/krnl386.exe16.spec b/dlls/krnl386.exe16/krnl386.exe16.spec index c6ffd9df701..6a55aad78f8 100644 --- a/dlls/krnl386.exe16/krnl386.exe16.spec +++ b/dlls/krnl386.exe16/krnl386.exe16.spec @@ -747,3 +747,7 @@ # VxDs @ cdecl -arch=win32 -private __wine_vxd_open(wstr long ptr) @ cdecl -arch=win32 -private __wine_vxd_get_proc(long) + +# Snoop support +2001 pascal -register __wine_snoop_entry() +2002 pascal -register __wine_snoop_return() diff --git a/dlls/krnl386.exe16/snoop.c b/dlls/krnl386.exe16/snoop.c index 170796da390..d5c528d3382 100644 --- a/dlls/krnl386.exe16/snoop.c +++ b/dlls/krnl386.exe16/snoop.c @@ -34,13 +34,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(snoop);
#include "pshpack1.h"
-static void WINAPI SNOOP16_Entry(FARPROC proc, LPBYTE args, CONTEXT *context); -static void WINAPI SNOOP16_Return(FARPROC proc, LPBYTE args, CONTEXT *context); - typedef struct tagSNOOP16_FUN { /* code part */ BYTE lcall; /* 0x9a call absolute with segment */ - DWORD snr; + FARPROC16 snoop_entry; /* unreached */ int nrofargs; FARPROC16 origfun; @@ -58,7 +55,7 @@ typedef struct tagSNOOP16_DLL { typedef struct tagSNOOP16_RETURNENTRY { /* code part */ BYTE lcall; /* 0x9a call absolute with segment */ - DWORD snr; + FARPROC16 snoop_return; /* unreached */ FARPROC16 origreturn; SNOOP16_DLL *dll; @@ -73,24 +70,10 @@ typedef struct tagSNOOP16_RETURNENTRIES { struct tagSNOOP16_RETURNENTRIES *next; } SNOOP16_RETURNENTRIES;
-typedef struct tagSNOOP16_RELAY { - WORD pushbp; /* 0x5566 */ - BYTE pusheax; /* 0x50 */ - WORD pushax; /* 0x5066 */ - BYTE pushl; /* 0x68 */ - DWORD realfun; /* SNOOP16_Return */ - BYTE lcall; /* 0x9a call absolute with segment */ - DWORD callfromregs; - WORD seg; - WORD lret; /* 0xcb66 */ -} SNOOP16_RELAY; - #include "poppack.h"
static SNOOP16_DLL *firstdll = NULL; static SNOOP16_RETURNENTRIES *firstrets = NULL; -static SNOOP16_RELAY *snr; -static HANDLE16 xsnr = 0;
void SNOOP16_RegisterDLL(HMODULE16 hModule,LPCSTR name) { @@ -102,29 +85,6 @@ SNOOP16_RegisterDLL(HMODULE16 hModule,LPCSTR name) {
TRACE("hmod=%x, name=%s\n", hModule, name);
- if (!snr) { - xsnr=GLOBAL_Alloc(GMEM_ZEROINIT,2*sizeof(*snr),0,LDT_FLAGS_CODE | LDT_FLAGS_32BIT); - snr = GlobalLock16(xsnr); - snr[0].pushbp = 0x5566; - snr[0].pusheax = 0x50; - snr[0].pushax = 0x5066; - snr[0].pushl = 0x68; - snr[0].realfun = (DWORD)SNOOP16_Entry; - snr[0].lcall = 0x9a; - snr[0].callfromregs = (DWORD)__wine_call_from_16_regs; - snr[0].seg = get_cs(); - snr[0].lret = 0xcb66; - - snr[1].pushbp = 0x5566; - snr[1].pusheax = 0x50; - snr[1].pushax = 0x5066; - snr[1].pushl = 0x68; - snr[1].realfun = (DWORD)SNOOP16_Return; - snr[1].lcall = 0x9a; - snr[1].callfromregs = (DWORD)__wine_call_from_16_regs; - snr[1].seg = get_cs(); - snr[1].lret = 0xcb66; - } while (*dll) { if ((*dll)->hmod == hModule) { @@ -181,7 +141,7 @@ SNOOP16_GetProcAddress16(HMODULE16 hmod,DWORD ordinal,FARPROC16 origfun) { fun = dll->funs+ordinal; /* already done? */ fun->lcall = 0x9a; - fun->snr = MAKELONG(0,xsnr); + fun->snoop_entry = GetProcAddress16( GetModuleHandle16( "KERNEL" ), "__wine_snoop_entry" ); fun->origfun = origfun; if (fun->name) return (FARPROC16)(SEGPTR)MAKELONG(((char*)fun-(char*)dll->funs),dll->funhandle); @@ -227,14 +187,15 @@ SNOOP16_GetProcAddress16(HMODULE16 hmod,DWORD ordinal,FARPROC16 origfun) { } } fun->lcall = 0x9a; - fun->snr = MAKELONG(0,xsnr); + fun->snoop_entry = GetProcAddress16( GetModuleHandle16( "KERNEL" ), "__wine_snoop_entry" ); fun->origfun = origfun; fun->nrofargs = -1; return (FARPROC16)(SEGPTR)MAKELONG(((char*)fun-(char*)dll->funs),dll->funhandle); }
#define CALLER1REF (*(DWORD*)(MapSL( MAKESEGPTR(context->SegSs,LOWORD(context->Esp)+4)))) -static void WINAPI SNOOP16_Entry(FARPROC proc, LPBYTE args, CONTEXT *context) { +void WINAPI __wine_snoop_entry( CONTEXT *context ) +{ DWORD ordinal=0; DWORD entry=(DWORD)MapSL( MAKESEGPTR(context->SegCs,LOWORD(context->Eip)) )-5; WORD xcs = context->SegCs; @@ -273,7 +234,7 @@ static void WINAPI SNOOP16_Entry(FARPROC proc, LPBYTE args, CONTEXT *context) { } ret = &((*rets)->entry[i]); ret->lcall = 0x9a; - ret->snr = MAKELONG(sizeof(SNOOP16_RELAY),xsnr); + ret->snoop_return = GetProcAddress16( GetModuleHandle16( "KERNEL" ), "__wine_snoop_return" ); ret->origreturn = (FARPROC16)CALLER1REF; CALLER1REF = MAKELONG((char*)&(ret->lcall)-(char*)((*rets)->entry),(*rets)->rethandle); ret->dll = dll; @@ -301,7 +262,8 @@ static void WINAPI SNOOP16_Entry(FARPROC proc, LPBYTE args, CONTEXT *context) { TRACE(") ret=%04x:%04x\n",HIWORD(ret->origreturn),LOWORD(ret->origreturn)); }
-static void WINAPI SNOOP16_Return(FARPROC proc, LPBYTE args, CONTEXT *context) { +void WINAPI __wine_snoop_return( CONTEXT *context ) +{ SNOOP16_RETURNENTRY *ret = (SNOOP16_RETURNENTRY*)((char *) MapSL( MAKESEGPTR(context->SegCs,LOWORD(context->Eip)) )-5);
/* We haven't found out the nrofargs yet. If we called a cdecl
September 28, 2021 8:39 PM, "Zebediah Figura" zfigura@codeweavers.com wrote:
The dedicated stack was introduced by 9d7ff6c85b0827b7f54989050b4c34f1f459e94d, in order to support potentially nested DPMI interrupts. DPMI support was removed by ed6bdb3c51cd4b8c94f9839806321703e7aa9765; hence there is no longer a reason to account for nested interrupts.
Isn't protected-mode Win16 a DPMI environment itself? In fact, it's why MS created DPMI in the first place.
Chip
On 9/28/21 21:59, Chip Davis wrote:
September 28, 2021 8:39 PM, "Zebediah Figura" zfigura@codeweavers.com wrote:
The dedicated stack was introduced by 9d7ff6c85b0827b7f54989050b4c34f1f459e94d, in order to support potentially nested DPMI interrupts. DPMI support was removed by ed6bdb3c51cd4b8c94f9839806321703e7aa9765; hence there is no longer a reason to account for nested interrupts.
Isn't protected-mode Win16 a DPMI environment itself? In fact, it's why MS created DPMI in the first place.
On Windows, yes, but as far as I understand it is not on Wine. I believe that our protected mode tasks never ran in virtual-8086 mode, and the DPMI support we had for them was removed by commits at about the same time as ed6bdb3c5.
My understanding of this area is definitely fuzzy, though, so I might have things wrong.
Am Mittwoch, 29. September 2021, 20:39:25 EAT schrieb Zebediah Figura (she/ her):
On 9/28/21 21:59, Chip Davis wrote:
September 28, 2021 8:39 PM, "Zebediah Figura" zfigura@codeweavers.com
wrote:
The dedicated stack was introduced by 9d7ff6c85b0827b7f54989050b4c34f1f459e94d, in order to support potentially nested DPMI interrupts. DPMI support was removed by ed6bdb3c51cd4b8c94f9839806321703e7aa9765; hence there is no longer a reason to account for nested interrupts.
Isn't protected-mode Win16 a DPMI environment itself? In fact, it's why MS created DPMI in the first place.
On Windows, yes, but as far as I understand it is not on Wine. I believe that our protected mode tasks never ran in virtual-8086 mode, and the DPMI support we had for them was removed by commits at about the same time as ed6bdb3c5.
My understanding of this area is definitely fuzzy, though, so I might have things wrong.
I think Zeb's wording is slightly wrong. My understanding is that "DPMI" is sort of the syscall interface of Win3x / Win9x. A process can ask the kernel for certain changes to its "virtual machine". Wine implements a pile of those syscalls in dlls/krnl386.exe16/int31.c. I'd expect Win9x's kernel32.dll to use those kinds of calls to implement stuff like VirtualAlloc() and MapViewOfFile().
What ed6bdb3c51 removed is the ability to call real mode code from a DPMI client. I was expecting to see some vm86() call somewhere, but can't find it, so I probably misunderstand. I also don't know how Windows (9x, and even more so NT) handled this. It could be done via vm86 or by switching the CPU back into actual real mode. DOS programs would need to do this kind of real mode call to call DOS services. Windows brings its own so called dos extender with it that wraps DOS APIs for you, and you aren't supposed to use DOS APIs anyway.
Now does that mean Zeb's patch is right or wrong? I have no clue...
On 9/29/21 13:25, Stefan Dösinger wrote:
Am Mittwoch, 29. September 2021, 20:39:25 EAT schrieb Zebediah Figura (she/ her):
On 9/28/21 21:59, Chip Davis wrote:
September 28, 2021 8:39 PM, "Zebediah Figura" zfigura@codeweavers.com
wrote:
The dedicated stack was introduced by 9d7ff6c85b0827b7f54989050b4c34f1f459e94d, in order to support potentially nested DPMI interrupts. DPMI support was removed by ed6bdb3c51cd4b8c94f9839806321703e7aa9765; hence there is no longer a reason to account for nested interrupts.
Isn't protected-mode Win16 a DPMI environment itself? In fact, it's why MS created DPMI in the first place.
On Windows, yes, but as far as I understand it is not on Wine. I believe that our protected mode tasks never ran in virtual-8086 mode, and the DPMI support we had for them was removed by commits at about the same time as ed6bdb3c5.
My understanding of this area is definitely fuzzy, though, so I might have things wrong.
I think Zeb's wording is slightly wrong. My understanding is that "DPMI" is sort of the syscall interface of Win3x / Win9x. A process can ask the kernel for certain changes to its "virtual machine". Wine implements a pile of those syscalls in dlls/krnl386.exe16/int31.c. I'd expect Win9x's kernel32.dll to use those kinds of calls to implement stuff like VirtualAlloc() and MapViewOfFile().
What ed6bdb3c51 removed is the ability to call real mode code from a DPMI client. I was expecting to see some vm86() call somewhere, but can't find it, so I probably misunderstand. I also don't know how Windows (9x, and even more so NT) handled this. It could be done via vm86 or by switching the CPU back into actual real mode. DOS programs would need to do this kind of real mode call to call DOS services. Windows brings its own so called dos extender with it that wraps DOS APIs for you, and you aren't supposed to use DOS APIs anyway.
Now does that mean Zeb's patch is right or wrong? I have no clue...
Well, my wording was wrong, or my understanding was :-)
I've gone back and stared at the old code some more, and I think I have a better idea of how it's supposed to work now.
I believe that ed6bdb3c51 isn't the relevant commit at all, but rather 5ec5449596 is. Trying to untangle how the IRQ code worked is difficult, but it doesn't particularly matter, because after 5ec5449596, we aren't triggering any DPMI IRQs anymore, so we can't get nested interrupts (not even with an STI with pending events). We can only get interrupts triggered by an INT instruction.
Wrt the vm86() call, I believe that DOSVM_CallRMProc()/DOSVM_CallRMInt() basically does a WOWCallback16Ex() with the VM86 flag set. Before 5e0fd3403e, that would trigger a call to __wine_enter_vm86 in ntdll, which would perform the vm86() call.