Commit 9d7ff6c8 authored by Jukka Heinonen's avatar Jukka Heinonen Committed by Alexandre Julliard

Add support for DPMI32. Make winedos16.dll unnecessary.

parent 91c6f817
...@@ -4,7 +4,6 @@ SRCDIR = @srcdir@ ...@@ -4,7 +4,6 @@ SRCDIR = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
MODULE = winedos.dll MODULE = winedos.dll
IMPORTS = user32 advapi32 kernel32 ntdll IMPORTS = user32 advapi32 kernel32 ntdll
ALTNAMES = winedos16.dll
EXTRALIBS = $(LIBUNICODE) EXTRALIBS = $(LIBUNICODE)
LDDLLFLAGS = @LDDLLFLAGS@ LDDLLFLAGS = @LDDLLFLAGS@
...@@ -43,6 +42,7 @@ C_SRCS = \ ...@@ -43,6 +42,7 @@ C_SRCS = \
interrupts.c \ interrupts.c \
ioports.c \ ioports.c \
module.c \ module.c \
relay.c \
soundblaster.c \ soundblaster.c \
vga.c \ vga.c \
xms.c xms.c
......
...@@ -28,6 +28,10 @@ ...@@ -28,6 +28,10 @@
#include "miscemu.h" #include "miscemu.h"
struct _DOSEVENT; struct _DOSEVENT;
struct _STACK16FRAME;
/* amount of space reserved for relay stack */
#define DOSVM_RELAY_DATA_SIZE 4096
/* various real-mode code stubs */ /* various real-mode code stubs */
struct DPMI_segments struct DPMI_segments
...@@ -37,6 +41,9 @@ struct DPMI_segments ...@@ -37,6 +41,9 @@ struct DPMI_segments
WORD dpmi_seg; WORD dpmi_seg;
WORD dpmi_sel; WORD dpmi_sel;
WORD int48_sel; WORD int48_sel;
WORD int16_sel;
WORD relay_code_sel;
WORD relay_data_sel;
}; };
/* 48-bit segmented pointers for DOS DPMI32 */ /* 48-bit segmented pointers for DOS DPMI32 */
...@@ -67,6 +74,8 @@ extern struct DPMI_segments *DOSVM_dpmi_segments; ...@@ -67,6 +74,8 @@ extern struct DPMI_segments *DOSVM_dpmi_segments;
#define BIOS_DATA ((void *)0x400) #define BIOS_DATA ((void *)0x400)
#define ADD_LOWORD(dw,val) ((dw) = ((dw) & 0xffff0000) | LOWORD((DWORD)(dw)+(val)))
/* module.c */ /* module.c */
extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile ); extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile );
extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk ); extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
...@@ -181,6 +190,7 @@ extern void WINAPI DOSVM_Int2fHandler(CONTEXT86*); ...@@ -181,6 +190,7 @@ extern void WINAPI DOSVM_Int2fHandler(CONTEXT86*);
/* int31.c */ /* int31.c */
extern void WINAPI DOSVM_Int31Handler(CONTEXT86*); extern void WINAPI DOSVM_Int31Handler(CONTEXT86*);
extern void WINAPI DOSVM_RawModeSwitchHandler(CONTEXT86*);
extern BOOL DOSVM_IsDos32(void); extern BOOL DOSVM_IsDos32(void);
extern FARPROC16 WINAPI DPMI_AllocInternalRMCB(RMCBPROC); extern FARPROC16 WINAPI DPMI_AllocInternalRMCB(RMCBPROC);
extern void WINAPI DPMI_FreeInternalRMCB(FARPROC16); extern void WINAPI DPMI_FreeInternalRMCB(FARPROC16);
...@@ -213,6 +223,12 @@ extern FARPROC48 DOSVM_GetPMHandler48( BYTE intnum ); ...@@ -213,6 +223,12 @@ extern FARPROC48 DOSVM_GetPMHandler48( BYTE intnum );
extern void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler ); extern void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler );
extern INTPROC DOSVM_GetBuiltinHandler( BYTE intnum ); 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 */ /* soundblaster.c */
extern void SB_ioport_out( WORD port, BYTE val ); extern void SB_ioport_out( WORD port, BYTE val );
extern BYTE SB_ioport_in( WORD port ); extern BYTE SB_ioport_in( WORD port );
......
...@@ -178,6 +178,12 @@ void DOSVM_InitSegments( void ) ...@@ -178,6 +178,12 @@ void DOSVM_InitSegments( void )
0xCB /* lret */ 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. * Allocate pointer array.
*/ */
...@@ -216,7 +222,7 @@ void DOSVM_InitSegments( void ) ...@@ -216,7 +222,7 @@ void DOSVM_InitSegments( void )
/* /*
* Each 32-bit interrupt handler is 6 bytes: * Each 32-bit interrupt handler is 6 bytes:
* 0xCD,<i> = int <i> (nested 16-bit interrupt) * 0xCD,<i> = int <i> (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 + 0] = 0xCD;
ptr[i * 6 + 1] = i; ptr[i * 6 + 1] = i;
...@@ -225,4 +231,37 @@ void DOSVM_InitSegments( void ) ...@@ -225,4 +231,37 @@ void DOSVM_InitSegments( void )
ptr[i * 6 + 4] = 0x04; ptr[i * 6 + 4] = 0x04;
ptr[i * 6 + 5] = 0x00; 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,<i> = int <i> (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 );
} }
...@@ -722,52 +722,21 @@ void WINAPI DOSVM_FreeRMCB( CONTEXT86 *context ) ...@@ -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 * This routine does all the stack manipulation tricks needed
* to return from protected mode interrupt using modified * to return from protected mode interrupt using modified
* code and stack pointers. * code and stack pointers.
*/ */
static void DOSVM_RawModeSwitchWrapper( CONTEXT86 *context ) void WINAPI DOSVM_RawModeSwitchHandler( CONTEXT86 *context )
{ {
/* STACK16FRAME frame;
* FIXME: This routine will not work if it is called DOSVM_SaveCallFrame( context, &frame );
* 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;
DOSVM_RawModeSwitch( context ); DOSVM_RawModeSwitch( context );
DOSVM_RestoreCallFrame( context, &frame );
/*
* 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;
} }
...@@ -781,15 +750,6 @@ static void DOSVM_RawModeSwitchWrapper( CONTEXT86 *context ) ...@@ -781,15 +750,6 @@ static void DOSVM_RawModeSwitchWrapper( CONTEXT86 *context )
*/ */
static BOOL DOSVM_CheckWrappers( 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 */ /* check if it's our wrapper */
TRACE("called from real mode\n"); TRACE("called from real mode\n");
if (context->SegCs==DOSVM_dpmi_segments->dpmi_seg) { if (context->SegCs==DOSVM_dpmi_segments->dpmi_seg) {
...@@ -828,7 +788,7 @@ static BOOL DOSVM_CheckWrappers( CONTEXT86 *context ) ...@@ -828,7 +788,7 @@ static BOOL DOSVM_CheckWrappers( CONTEXT86 *context )
*/ */
void WINAPI DOSVM_Int31Handler( CONTEXT86 *context ) void WINAPI DOSVM_Int31Handler( CONTEXT86 *context )
{ {
if (DOSVM_CheckWrappers(context)) if (ISV86(context) && DOSVM_CheckWrappers(context))
return; return;
RESET_CFLAG(context); RESET_CFLAG(context);
......
...@@ -56,11 +56,9 @@ static const INTPROC DOSVM_VectorsBuiltin[] = ...@@ -56,11 +56,9 @@ static const INTPROC DOSVM_VectorsBuiltin[] =
/* 64 */ 0, 0, 0, DOSVM_Int67Handler /* 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 * Default interrupt handler. This will be used to emulate all
* interrupts that don't have their own interrupt handler. * interrupts that don't have their own interrupt handler.
...@@ -69,6 +67,70 @@ void WINAPI DOSVM_DefaultHandler( CONTEXT86 *context ) ...@@ -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 * DOSVM_EmulateInterruptPM
* *
...@@ -80,49 +142,97 @@ void WINAPI DOSVM_DefaultHandler( CONTEXT86 *context ) ...@@ -80,49 +142,97 @@ void WINAPI DOSVM_DefaultHandler( CONTEXT86 *context )
*/ */
void WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum ) void WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum )
{ {
BOOL islong; if (context->SegCs == DOSVM_dpmi_segments->dpmi_sel)
{
if(context->SegCs == DOSVM_dpmi_segments->int48_sel) DOSVM_BuildCallFrame( context,
islong = FALSE; DOSVM_IntProcRelay,
else if(context->SegCs == DOSVM_dpmi_segments->dpmi_sel) DOSVM_RawModeSwitchHandler );
islong = FALSE; }
else if(DOSVM_IsDos32()) else if (context->SegCs == DOSVM_dpmi_segments->relay_code_sel)
islong = TRUE; {
else if(IS_SELECTOR_32BIT(context->SegCs)) { /*
WARN("Interrupt in 32-bit code and mode is not DPMI32\n"); * This must not be called using DOSVM_BuildCallFrame.
islong = TRUE; */
} else DOSVM_RelayHandler( context );
islong = FALSE; }
else if (context->SegCs == DOSVM_dpmi_segments->int48_sel)
if(islong) {
{ if (intnum == 0x25 || intnum == 0x26)
FARPROC48 addr = DOSVM_GetPMHandler48( intnum ); DOSVM_PushFlags( context, TRUE, TRUE );
DWORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
/* Push the flags and return address on the stack */ DOSVM_BuildCallFrame( context,
*(--stack) = context->EFlags; DOSVM_IntProcRelay,
*(--stack) = context->SegCs; DOSVM_GetBuiltinHandler(intnum) );
*(--stack) = context->Eip; }
/* Jump to the interrupt handler */ else if (context->SegCs == DOSVM_dpmi_segments->int16_sel)
context->SegCs = addr.selector; {
context->Eip = addr.offset; if (intnum == 0x25 || intnum == 0x26)
} DOSVM_PushFlags( context, FALSE, TRUE );
else
{ DOSVM_BuildCallFrame( context,
FARPROC16 addr = DOSVM_GetPMHandler16( intnum ); DOSVM_IntProcRelay,
WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); DOSVM_GetBuiltinHandler(intnum) );
/* Push the flags and return address on the stack */ }
*(--stack) = LOWORD(context->EFlags); else if(DOSVM_IsDos32())
*(--stack) = context->SegCs; {
*(--stack) = LOWORD(context->Eip); FARPROC48 addr = DOSVM_GetPMHandler48( intnum );
/* Jump to the interrupt handler */
context->SegCs = HIWORD(addr); if (addr.selector == DOSVM_dpmi_segments->int48_sel)
context->Eip = LOWORD(addr); {
} if (intnum == 0x25 || intnum == 0x26)
DOSVM_PushFlags( context, TRUE, FALSE );
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 );
if (IS_SELECTOR_32BIT(context->SegSs)) DOSVM_BuildCallFrame( context,
context->Esp += islong ? -12 : -6; DOSVM_IntProcRelay,
else DOSVM_GetBuiltinHandler(intnum) );
context->Esp = (context->Esp & ~0xffff) | (WORD)((context->Esp & 0xffff) + (islong ? -12 : -6)); }
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 ) ...@@ -147,6 +257,7 @@ void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler )
((FARPROC16*)0)[intnum] = handler; ((FARPROC16*)0)[intnum] = handler;
} }
/********************************************************************** /**********************************************************************
* DOSVM_GetPMHandler16 * DOSVM_GetPMHandler16
* *
...@@ -154,31 +265,13 @@ void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler ) ...@@ -154,31 +265,13 @@ void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler )
*/ */
FARPROC16 DOSVM_GetPMHandler16( BYTE intnum ) FARPROC16 DOSVM_GetPMHandler16( BYTE intnum )
{ {
static HMODULE16 procs; if (!DOSVM_Vectors16[intnum])
FARPROC16 handler = DOSVM_Vectors16[intnum];
if (!handler)
{
if (!procs &&
(procs = GetModuleHandle16( "winedos16" )) < 32 &&
(procs = LoadLibrary16( "winedos16" )) < 32)
{ {
ERR("could not load winedos16.dll\n"); FARPROC16 proc = (FARPROC16)MAKESEGPTR( DOSVM_dpmi_segments->int16_sel,
procs = 0; 5 * intnum );
return 0; DOSVM_Vectors16[intnum] = proc;
} }
return DOSVM_Vectors16[intnum];
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;
} }
......
/*
* 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;
}
# 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment