From 9d7ff6c85b0827b7f54989050b4c34f1f459e94d Mon Sep 17 00:00:00 2001 From: Jukka Heinonen Date: Sun, 15 Dec 2002 01:18:40 +0000 Subject: [PATCH] Add support for DPMI32. Make winedos16.dll unnecessary. --- dlls/winedos/Makefile.in | 2 +- dlls/winedos/dosexe.h | 16 +++ dlls/winedos/himem.c | 41 +++++- dlls/winedos/int31.c | 56 ++------ dlls/winedos/interrupts.c | 225 ++++++++++++++++++++++--------- dlls/winedos/relay.c | 262 ++++++++++++++++++++++++++++++++++++ dlls/winedos/winedos16.spec | 39 ------ 7 files changed, 486 insertions(+), 155 deletions(-) create mode 100644 dlls/winedos/relay.c delete mode 100644 dlls/winedos/winedos16.spec diff --git a/dlls/winedos/Makefile.in b/dlls/winedos/Makefile.in index 5bf82a859fa..c6c59185b3e 100644 --- a/dlls/winedos/Makefile.in +++ b/dlls/winedos/Makefile.in @@ -4,7 +4,6 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = winedos.dll IMPORTS = user32 advapi32 kernel32 ntdll -ALTNAMES = winedos16.dll EXTRALIBS = $(LIBUNICODE) LDDLLFLAGS = @LDDLLFLAGS@ @@ -43,6 +42,7 @@ C_SRCS = \ interrupts.c \ ioports.c \ module.c \ + relay.c \ soundblaster.c \ vga.c \ xms.c diff --git a/dlls/winedos/dosexe.h b/dlls/winedos/dosexe.h index 864447d8333..c8cbad45412 100644 --- a/dlls/winedos/dosexe.h +++ b/dlls/winedos/dosexe.h @@ -28,6 +28,10 @@ #include "miscemu.h" struct _DOSEVENT; +struct _STACK16FRAME; + +/* amount of space reserved for relay stack */ +#define DOSVM_RELAY_DATA_SIZE 4096 /* various real-mode code stubs */ struct DPMI_segments @@ -37,6 +41,9 @@ struct DPMI_segments WORD dpmi_seg; WORD dpmi_sel; WORD int48_sel; + WORD int16_sel; + WORD relay_code_sel; + WORD relay_data_sel; }; /* 48-bit segmented pointers for DOS DPMI32 */ @@ -67,6 +74,8 @@ extern struct DPMI_segments *DOSVM_dpmi_segments; #define BIOS_DATA ((void *)0x400) +#define ADD_LOWORD(dw,val) ((dw) = ((dw) & 0xffff0000) | LOWORD((DWORD)(dw)+(val))) + /* module.c */ extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile ); extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk ); @@ -181,6 +190,7 @@ extern void WINAPI DOSVM_Int2fHandler(CONTEXT86*); /* int31.c */ extern void WINAPI DOSVM_Int31Handler(CONTEXT86*); +extern void WINAPI DOSVM_RawModeSwitchHandler(CONTEXT86*); extern BOOL DOSVM_IsDos32(void); extern FARPROC16 WINAPI DPMI_AllocInternalRMCB(RMCBPROC); extern void WINAPI DPMI_FreeInternalRMCB(FARPROC16); @@ -213,6 +223,12 @@ extern FARPROC48 DOSVM_GetPMHandler48( BYTE intnum ); extern void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler ); extern INTPROC DOSVM_GetBuiltinHandler( BYTE intnum ); +/* relay.c */ +void DOSVM_RelayHandler( CONTEXT86 * ); +void DOSVM_SaveCallFrame( CONTEXT86 *, struct _STACK16FRAME * ); +void DOSVM_RestoreCallFrame( CONTEXT86 *, struct _STACK16FRAME * ); +void DOSVM_BuildCallFrame( CONTEXT86 *, DOSRELAY, LPVOID ); + /* soundblaster.c */ extern void SB_ioport_out( WORD port, BYTE val ); extern BYTE SB_ioport_in( WORD port ); diff --git a/dlls/winedos/himem.c b/dlls/winedos/himem.c index b97bccd0e30..4cee0a58092 100644 --- a/dlls/winedos/himem.c +++ b/dlls/winedos/himem.c @@ -178,6 +178,12 @@ void DOSVM_InitSegments( void ) 0xCB /* lret */ }; + static const char relay[]= + { + 0xca, 0x04, 0x00, /* 16-bit far return and pop 4 bytes (relay void* arg) */ + 0xcd, 0x31 /* int 31 */ + }; + /* * Allocate pointer array. */ @@ -216,7 +222,7 @@ void DOSVM_InitSegments( void ) /* * Each 32-bit interrupt handler is 6 bytes: * 0xCD, = int (nested 16-bit interrupt) - * 0x66,0xCA,0x04,0x00 = ret 4 (32-bit far return and pop 4 bytes) + * 0x66,0xCA,0x04,0x00 = ret 4 (32-bit far return and pop 4 bytes / eflags) */ ptr[i * 6 + 0] = 0xCD; ptr[i * 6 + 1] = i; @@ -225,4 +231,37 @@ void DOSVM_InitSegments( void ) ptr[i * 6 + 4] = 0x04; ptr[i * 6 + 5] = 0x00; } + + /* + * PM / offset N*5: Interrupt N in 16-bit protected mode. + */ + ptr = DOSVM_AllocCodeUMB( 5 * 256, + 0, &DOSVM_dpmi_segments->int16_sel ); + for(i=0; i<256; i++) { + /* + * Each 16-bit interrupt handler is 5 bytes: + * 0xCD, = int (interrupt) + * 0xCA,0x02,0x00 = ret 2 (16-bit far return and pop 2 bytes / eflags) + */ + ptr[i * 5 + 0] = 0xCD; + ptr[i * 5 + 1] = i; + ptr[i * 5 + 2] = 0xCA; + ptr[i * 5 + 3] = 0x02; + ptr[i * 5 + 4] = 0x00; + } + + /* + * PM / offset 0: Stub where __wine_call_from_16_regs returns. + * PM / offset 3: Stub which swaps back to 32-bit application code/stack. + */ + ptr = DOSVM_AllocCodeUMB( sizeof(relay), + 0, &DOSVM_dpmi_segments->relay_code_sel); + memcpy( ptr, relay, sizeof(relay) ); + + /* + * Space for 16-bit stack used by relay code. + */ + ptr = DOSVM_AllocDataUMB( DOSVM_RELAY_DATA_SIZE, + 0, &DOSVM_dpmi_segments->relay_data_sel); + memset( ptr, 0, DOSVM_RELAY_DATA_SIZE ); } diff --git a/dlls/winedos/int31.c b/dlls/winedos/int31.c index 50d8d93641d..bebb7f3aad1 100644 --- a/dlls/winedos/int31.c +++ b/dlls/winedos/int31.c @@ -722,52 +722,21 @@ void WINAPI DOSVM_FreeRMCB( CONTEXT86 *context ) } } + /********************************************************************** - * DOSVM_RawModeSwitchWrapper + * DOSVM_RawModeSwitchHandler * - * DPMI Raw Mode Switch wrapper. + * DPMI Raw Mode Switch handler. * This routine does all the stack manipulation tricks needed * to return from protected mode interrupt using modified * code and stack pointers. */ -static void DOSVM_RawModeSwitchWrapper( CONTEXT86 *context ) +void WINAPI DOSVM_RawModeSwitchHandler( CONTEXT86 *context ) { - /* - * FIXME: This routine will not work if it is called - * from 32 bit DPMI program and the program returns - * to protected mode while ESP or EIP is over 0xffff. - * FIXME: This routine will not work if it is not called - * using 16-bit-to-Wine callback glue function. - */ - STACK16FRAME frame = *CURRENT_STACK16; - + STACK16FRAME frame; + DOSVM_SaveCallFrame( context, &frame ); DOSVM_RawModeSwitch( context ); - - /* - * After this function returns to relay code, protected mode - * 16 bit stack will contain STACK16FRAME and single WORD - * (EFlags, see next comment). - */ - NtCurrentTeb()->cur_stack = - MAKESEGPTR( context->SegSs, - context->Esp - sizeof(STACK16FRAME) - sizeof(WORD) ); - - /* - * After relay code returns to glue function, protected - * mode 16 bit stack will contain interrupt return record: - * IP, CS and EFlags. Since EFlags is ignored, it won't - * need to be initialized. - */ - context->Esp -= 3 * sizeof(WORD); - - /* - * Restore stack frame so that relay code won't be confused. - * It should be noted that relay code overwrites IP and CS - * in STACK16FRAME with values taken from current CONTEXT86. - * These values are what is returned to glue function - * (see previous comment). - */ - *CURRENT_STACK16 = frame; + DOSVM_RestoreCallFrame( context, &frame ); } @@ -781,15 +750,6 @@ static void DOSVM_RawModeSwitchWrapper( CONTEXT86 *context ) */ static BOOL DOSVM_CheckWrappers( CONTEXT86 *context ) { - /* Handle protected mode interrupts. */ - if (!ISV86(context)) { - if (context->SegCs == DOSVM_dpmi_segments->dpmi_sel) { - DOSVM_RawModeSwitchWrapper( context ); - return TRUE; - } - return FALSE; - } - /* check if it's our wrapper */ TRACE("called from real mode\n"); if (context->SegCs==DOSVM_dpmi_segments->dpmi_seg) { @@ -828,7 +788,7 @@ static BOOL DOSVM_CheckWrappers( CONTEXT86 *context ) */ void WINAPI DOSVM_Int31Handler( CONTEXT86 *context ) { - if (DOSVM_CheckWrappers(context)) + if (ISV86(context) && DOSVM_CheckWrappers(context)) return; RESET_CFLAG(context); diff --git a/dlls/winedos/interrupts.c b/dlls/winedos/interrupts.c index 4b50905c8f5..f7c88a7ce9a 100644 --- a/dlls/winedos/interrupts.c +++ b/dlls/winedos/interrupts.c @@ -56,11 +56,9 @@ static const INTPROC DOSVM_VectorsBuiltin[] = /* 64 */ 0, 0, 0, DOSVM_Int67Handler }; -/* Ordinal number for interrupt 0 handler in winedos16.dll */ -#define FIRST_INTERRUPT 100 /********************************************************************** - * DOSVM_DefaultHandler (WINEDOS16.356) + * DOSVM_DefaultHandler * * Default interrupt handler. This will be used to emulate all * interrupts that don't have their own interrupt handler. @@ -69,6 +67,70 @@ void WINAPI DOSVM_DefaultHandler( CONTEXT86 *context ) { } + +/********************************************************************** + * DOSVM_IntProcRelay + * + * Simple DOSRELAY that interprets its argument as INTPROC and calls it. + */ +static void DOSVM_IntProcRelay( CONTEXT86 *context, LPVOID data ) +{ + INTPROC proc = (INTPROC)data; + proc(context); +} + + +/********************************************************************** + * DOSVM_PushFlags + * + * This routine is used to make default int25 and int26 handlers leave the + * original eflags into stack. In order to do this, stack is manipulated + * so that it actually contains two copies of eflags, one of which is + * popped during return from interrupt handler. + */ +static void DOSVM_PushFlags( CONTEXT86 *context, BOOL islong, BOOL isstub ) +{ + if (islong) + { + DWORD *stack = CTX_SEG_OFF_TO_LIN(context, + context->SegSs, + context->Esp); + context->Esp += -4; /* One item will be added to stack. */ + + if (isstub) + { + DWORD ip = stack[0]; + DWORD cs = stack[1]; + stack += 2; /* Pop ip and cs. */ + *(--stack) = context->EFlags; + *(--stack) = cs; + *(--stack) = ip; + } + else + *(--stack) = context->EFlags; + } + else + { + WORD *stack = CTX_SEG_OFF_TO_LIN(context, + context->SegSs, + context->Esp); + ADD_LOWORD( context->Esp, -2 ); /* One item will be added to stack. */ + + if (isstub) + { + WORD ip = stack[0]; + WORD cs = stack[1]; + stack += 2; /* Pop ip and cs. */ + *(--stack) = LOWORD(context->EFlags); + *(--stack) = cs; + *(--stack) = ip; + } + else + *(--stack) = LOWORD(context->EFlags); + } +} + + /********************************************************************** * DOSVM_EmulateInterruptPM * @@ -80,49 +142,97 @@ void WINAPI DOSVM_DefaultHandler( CONTEXT86 *context ) */ void WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum ) { - BOOL islong; + if (context->SegCs == DOSVM_dpmi_segments->dpmi_sel) + { + DOSVM_BuildCallFrame( context, + DOSVM_IntProcRelay, + DOSVM_RawModeSwitchHandler ); + } + else if (context->SegCs == DOSVM_dpmi_segments->relay_code_sel) + { + /* + * This must not be called using DOSVM_BuildCallFrame. + */ + DOSVM_RelayHandler( context ); + } + else if (context->SegCs == DOSVM_dpmi_segments->int48_sel) + { + if (intnum == 0x25 || intnum == 0x26) + DOSVM_PushFlags( context, TRUE, TRUE ); - if(context->SegCs == DOSVM_dpmi_segments->int48_sel) - islong = FALSE; - else if(context->SegCs == DOSVM_dpmi_segments->dpmi_sel) - islong = FALSE; - else if(DOSVM_IsDos32()) - islong = TRUE; - else if(IS_SELECTOR_32BIT(context->SegCs)) { - WARN("Interrupt in 32-bit code and mode is not DPMI32\n"); - islong = TRUE; - } else - islong = FALSE; + DOSVM_BuildCallFrame( context, + DOSVM_IntProcRelay, + DOSVM_GetBuiltinHandler(intnum) ); + } + else if (context->SegCs == DOSVM_dpmi_segments->int16_sel) + { + if (intnum == 0x25 || intnum == 0x26) + DOSVM_PushFlags( context, FALSE, TRUE ); - if(islong) - { - FARPROC48 addr = DOSVM_GetPMHandler48( intnum ); - DWORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); - /* Push the flags and return address on the stack */ - *(--stack) = context->EFlags; - *(--stack) = context->SegCs; - *(--stack) = context->Eip; - /* Jump to the interrupt handler */ - context->SegCs = addr.selector; - context->Eip = addr.offset; - } - else - { - FARPROC16 addr = DOSVM_GetPMHandler16( intnum ); - WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); - /* Push the flags and return address on the stack */ - *(--stack) = LOWORD(context->EFlags); - *(--stack) = context->SegCs; - *(--stack) = LOWORD(context->Eip); - /* Jump to the interrupt handler */ - context->SegCs = HIWORD(addr); - context->Eip = LOWORD(addr); - } + DOSVM_BuildCallFrame( context, + DOSVM_IntProcRelay, + DOSVM_GetBuiltinHandler(intnum) ); + } + else if(DOSVM_IsDos32()) + { + FARPROC48 addr = DOSVM_GetPMHandler48( intnum ); + + if (addr.selector == DOSVM_dpmi_segments->int48_sel) + { + if (intnum == 0x25 || intnum == 0x26) + DOSVM_PushFlags( context, TRUE, FALSE ); - if (IS_SELECTOR_32BIT(context->SegSs)) - context->Esp += islong ? -12 : -6; - else - context->Esp = (context->Esp & ~0xffff) | (WORD)((context->Esp & 0xffff) + (islong ? -12 : -6)); + DOSVM_BuildCallFrame( context, + DOSVM_IntProcRelay, + DOSVM_GetBuiltinHandler(intnum) ); + } + else + { + DWORD *stack = CTX_SEG_OFF_TO_LIN(context, + context->SegSs, + context->Esp); + + /* Push the flags and return address on the stack */ + *(--stack) = context->EFlags; + *(--stack) = context->SegCs; + *(--stack) = context->Eip; + context->Esp += -12; + + /* Jump to the interrupt handler */ + context->SegCs = addr.selector; + context->Eip = addr.offset; + } + } + else + { + FARPROC16 addr = DOSVM_GetPMHandler16( intnum ); + + if (SELECTOROF(addr) == DOSVM_dpmi_segments->int16_sel) + { + if (intnum == 0x25 || intnum == 0x26) + DOSVM_PushFlags( context, FALSE, FALSE ); + + DOSVM_BuildCallFrame( context, + DOSVM_IntProcRelay, + DOSVM_GetBuiltinHandler(intnum) ); + } + else + { + WORD *stack = CTX_SEG_OFF_TO_LIN(context, + context->SegSs, + context->Esp); + + /* Push the flags and return address on the stack */ + *(--stack) = LOWORD(context->EFlags); + *(--stack) = context->SegCs; + *(--stack) = LOWORD(context->Eip); + ADD_LOWORD( context->Esp, -6 ); + + /* Jump to the interrupt handler */ + context->SegCs = HIWORD(addr); + context->Eip = LOWORD(addr); + } + } } /********************************************************************** @@ -147,6 +257,7 @@ void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler ) ((FARPROC16*)0)[intnum] = handler; } + /********************************************************************** * DOSVM_GetPMHandler16 * @@ -154,31 +265,13 @@ void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler ) */ FARPROC16 DOSVM_GetPMHandler16( BYTE intnum ) { - static HMODULE16 procs; - FARPROC16 handler = DOSVM_Vectors16[intnum]; - - if (!handler) - { - if (!procs && - (procs = GetModuleHandle16( "winedos16" )) < 32 && - (procs = LoadLibrary16( "winedos16" )) < 32) + if (!DOSVM_Vectors16[intnum]) { - ERR("could not load winedos16.dll\n"); - procs = 0; - return 0; + FARPROC16 proc = (FARPROC16)MAKESEGPTR( DOSVM_dpmi_segments->int16_sel, + 5 * intnum ); + DOSVM_Vectors16[intnum] = proc; } - - handler = GetProcAddress16( procs, (LPCSTR)(FIRST_INTERRUPT + intnum)); - if (!handler) - { - WARN("int%x not implemented, returning dummy handler\n", intnum ); - handler = GetProcAddress16( procs, (LPCSTR)(FIRST_INTERRUPT + 256)); - } - - DOSVM_Vectors16[intnum] = handler; - } - - return handler; + return DOSVM_Vectors16[intnum]; } diff --git a/dlls/winedos/relay.c b/dlls/winedos/relay.c new file mode 100644 index 00000000000..85978648393 --- /dev/null +++ b/dlls/winedos/relay.c @@ -0,0 +1,262 @@ +/* + * Routines for dynamically building calls to Wine from + * protected mode applications. + * + * Copyright 2002 Jukka Heinonen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "dosexe.h" +#include "stackframe.h" +#include "wine/debug.h" +#include "builtin16.h" + +WINE_DEFAULT_DEBUG_CHANNEL(int); + +/* + * Magic DWORD used to check stack integrity. + */ +#define RELAY_MAGIC 0xabcdef00 + +/* + * Memory block for temporary 16-bit stacks used when + * 32-bit code calls relay. + */ +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; + + +/********************************************************************** + * 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(DOSVM_dpmi_segments->relay_data_sel, offset)); +} + + +/********************************************************************** + * RELAY_MakeShortContext + * + * If context is using 32-bit stack or code segment, allocate + * 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( CONTEXT86 *context ) +{ + if (IS_SELECTOR_32BIT(context->SegCs) || IS_SELECTOR_32BIT(context->SegSs)) + { + 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 = DOSVM_dpmi_segments->relay_data_sel; + context->Esp = offset; + context->SegCs = DOSVM_dpmi_segments->relay_code_sel; + context->Eip = 3; + } +} + + +/********************************************************************** + * 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, + void *context ) +{ + proc( (CONTEXT86*)context, *(LPVOID *)args ); +} + + +/********************************************************************** + * DOSVM_RelayHandler + * + * Restore saved code and stack pointers and release stack block. + */ +void DOSVM_RelayHandler( CONTEXT86 *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_SaveCallFrame + * + * Save current call frame. This routine must be called from DOSRELAY + * called using DOSVM_BuildCallFrame before the relay modifies stack + * pointer. This routine makes sure that the relay can return safely + * to application context and that no memory is leaked. + * + * Note: If DOSVM_BuildCallFrame was called using 32-bit CS or SS, + * old values of CS and SS will be lost. This does not matter + * since this routine is only used by Raw Mode Switch. + */ +void DOSVM_SaveCallFrame( CONTEXT86 *context, STACK16FRAME *frame ) +{ + *frame = *CURRENT_STACK16; + + /* + * If context is using allocated stack, release it. + */ + if (context->SegSs == DOSVM_dpmi_segments->relay_data_sel) + { + RELAY_Stack16 *stack = RELAY_GetPointer( context->Esp ); + + if (!stack->inuse || + stack->stack_bottom != RELAY_MAGIC || + stack->stack_top != RELAY_MAGIC) + ERR( "Stack corrupted!\n" ); + + stack->inuse = 0; + } +} + + +/********************************************************************** + * DOSVM_RestoreCallFrame + * + * Restore saved call frame to currect stack. This routine must always + * be called after DOSVM_SaveCallFrame has been called and before returning + * from DOSRELAY. + */ +void DOSVM_RestoreCallFrame( CONTEXT86 *context, STACK16FRAME *frame ) +{ + /* + * Make sure that CS and SS are 16-bit. + */ + RELAY_MakeShortContext( context ); + + /* + * After this function returns to relay code, protected mode + * 16 bit stack will contain STACK16FRAME and single WORD + * (EFlags, see next comment). + */ + NtCurrentTeb()->cur_stack = + MAKESEGPTR( context->SegSs, + context->Esp - sizeof(STACK16FRAME) - sizeof(WORD) ); + + /* + * After relay code returns to glue function, protected + * mode 16 bit stack will contain interrupt return record: + * IP, CS and EFlags. Since EFlags is ignored, it won't + * need to be initialized. + */ + context->Esp -= 3 * sizeof(WORD); + + /* + * Restore stack frame so that relay code won't be confused. + * It should be noted that relay code overwrites IP and CS + * in STACK16FRAME with values taken from current CONTEXT86. + * These values are what is returned to glue function + * (see previous comment). + */ + *CURRENT_STACK16 = *frame; +} + + +/********************************************************************** + * 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( CONTEXT86 *context, DOSRELAY relay, LPVOID data ) +{ + WORD *stack; + WORD code_sel = DOSVM_dpmi_segments->relay_code_sel; + + /* + * Make sure that CS and SS are 16-bit. + */ + RELAY_MakeShortContext( context ); + + /* + * Get stack pointer after RELAY_MakeShortContext. + */ + stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); + + /* + * Build call frame. + */ + *(--stack) = HIWORD(data); /* argument.hiword */ + *(--stack) = LOWORD(data); /* argument.loword */ + *(--stack) = context->SegCs; /* STACK16FRAME.cs */ + *(--stack) = LOWORD(context->Eip); /* STACK16FRAME.ip */ + *(--stack) = LOWORD(context->Ebp); /* STACK16FRAME.bp */ + *(--stack) = HIWORD(relay); /* STACK16FRAME.entry_point.hiword */ + *(--stack) = LOWORD(relay); /* STACK16FRAME.entry_point.loword */ + *(--stack) = 0; /* STACK16FRAME.entry_ip */ + *(--stack) = HIWORD(RELAY_RelayStub); /* STACK16FRAME.relay.hiword */ + *(--stack) = LOWORD(RELAY_RelayStub); /* STACK16FRAME.relay.loword */ + *(--stack) = 0; /* STACK16FRAME.module_cs.hiword */ + *(--stack) = code_sel; /* STACK16FRAME.module_cs.loword */ + *(--stack) = 0; /* STACK16FRAME.callfrom_ip.hiword */ + *(--stack) = 0; /* STACK16FRAME.callfrom_ip.loword */ + + /* + * Adjust stack and code pointers. + */ + ADD_LOWORD( context->Esp, -28 ); + context->SegCs = wine_get_cs(); + context->Eip = (DWORD)__wine_call_from_16_regs; +} diff --git a/dlls/winedos/winedos16.spec b/dlls/winedos/winedos16.spec deleted file mode 100644 index 74851a58923..00000000000 --- a/dlls/winedos/winedos16.spec +++ /dev/null @@ -1,39 +0,0 @@ -# Interrupt vectors 0-255 are ordinals 100-355 -# The '-interrupt' keyword takes care of the flags pushed on the stack by the interrupt -109 pascal -interrupt DOSVM_Int09Handler() DOSVM_Int09Handler -116 pascal -interrupt DOSVM_Int10Handler() DOSVM_Int10Handler -117 pascal -interrupt DOSVM_Int11Handler() DOSVM_Int11Handler -118 pascal -interrupt DOSVM_Int12Handler() DOSVM_Int12Handler -119 pascal -interrupt DOSVM_Int13Handler() DOSVM_Int13Handler -121 pascal -interrupt DOSVM_Int15Handler() DOSVM_Int15Handler -122 pascal -interrupt DOSVM_Int16Handler() DOSVM_Int16Handler -123 pascal -interrupt DOSVM_Int17Handler() DOSVM_Int17Handler -126 pascal -interrupt DOSVM_Int1aHandler() DOSVM_Int1aHandler -132 pascal -interrupt DOSVM_Int20Handler() DOSVM_Int20Handler -133 pascal -interrupt DOSVM_Int21Handler() DOSVM_Int21Handler -# Note: int 25 and 26 don't pop the flags from the stack -137 pascal -register DOSVM_Int25Handler() DOSVM_Int25Handler -138 pascal -register DOSVM_Int26Handler() DOSVM_Int26Handler -141 pascal -interrupt DOSVM_Int29Handler() DOSVM_Int29Handler -142 pascal -interrupt DOSVM_Int2aHandler() DOSVM_Int2aHandler -147 pascal -interrupt DOSVM_Int2fHandler() DOSVM_Int2fHandler -149 pascal -interrupt DOSVM_Int31Handler() DOSVM_Int31Handler -151 pascal -interrupt DOSVM_Int33Handler() DOSVM_Int33Handler -152 pascal -interrupt DOSVM_Int34Handler() DOSVM_Int34Handler -153 pascal -interrupt DOSVM_Int35Handler() DOSVM_Int35Handler -154 pascal -interrupt DOSVM_Int36Handler() DOSVM_Int36Handler -155 pascal -interrupt DOSVM_Int37Handler() DOSVM_Int37Handler -156 pascal -interrupt DOSVM_Int38Handler() DOSVM_Int38Handler -157 pascal -interrupt DOSVM_Int39Handler() DOSVM_Int39Handler -158 pascal -interrupt DOSVM_Int3aHandler() DOSVM_Int3aHandler -159 pascal -interrupt DOSVM_Int3bHandler() DOSVM_Int3bHandler -160 pascal -interrupt DOSVM_Int3cHandler() DOSVM_Int3cHandler -161 pascal -interrupt DOSVM_Int3dHandler() DOSVM_Int3dHandler -162 pascal -interrupt DOSVM_Int3eHandler() DOSVM_Int3eHandler -165 pascal -interrupt DOSVM_Int41Handler() DOSVM_Int41Handler -175 pascal -interrupt DOSVM_Int4bHandler() DOSVM_Int4bHandler -192 pascal -interrupt DOSVM_Int5cHandler() DOSVM_Int5cHandler -203 pascal -interrupt DOSVM_Int67Handler() DOSVM_Int67Handler - -# default handler for unimplemented interrupts -356 pascal -interrupt DOSVM_DefaultHandler() DOSVM_DefaultHandler