diff --git a/dlls/kernel/kernel32.spec b/dlls/kernel/kernel32.spec index 57aa909075b..01a277b8d77 100644 --- a/dlls/kernel/kernel32.spec +++ b/dlls/kernel/kernel32.spec @@ -1049,6 +1049,7 @@ init MAIN_KernelInit @ stdcall INT_Int15Handler(ptr) INT_Int15Handler @ stdcall INT_Int1aHandler(ptr) INT_Int1aHandler @ stdcall INT_Int25Handler(ptr) INT_Int25Handler +@ stdcall INT_Int26Handler(ptr) INT_Int26Handler @ stdcall INT_Int2aHandler(ptr) INT_Int2aHandler @ stdcall INT_Int2fHandler(ptr) INT_Int2fHandler @ stdcall INT_Int31Handler(ptr) INT_Int31Handler @@ -1063,6 +1064,9 @@ init MAIN_KernelInit @ stdcall INT_Int3cHandler(ptr) INT_Int3cHandler @ stdcall INT_Int3dHandler(ptr) INT_Int3dHandler @ stdcall INT_Int3eHandler(ptr) INT_Int3eHandler +@ stdcall INT_Int41Handler(ptr) INT_Int41Handler +@ stdcall INT_Int4bHandler(ptr) INT_Int4bHandler +@ stdcall NetBIOSCall16(ptr) NetBIOSCall16 @ cdecl INT_SetPMHandler(long long) INT_SetPMHandler @ cdecl LOCAL_Alloc(long long long) LOCAL_Alloc @ cdecl LOCAL_Compact(long long long) LOCAL_Compact diff --git a/dlls/winedos/int20.c b/dlls/winedos/int20.c index 349529ca02d..1b0e2f4df25 100644 --- a/dlls/winedos/int20.c +++ b/dlls/winedos/int20.c @@ -30,5 +30,9 @@ */ void WINAPI DOSVM_Int20Handler( CONTEXT86 *context ) { - MZ_Exit( context, TRUE, 0 ); + /* FIXME: Is this correct in DOS DPMI? */ + if (ISV86(context)) + MZ_Exit( context, TRUE, 0 ); + else + ExitThread(0); } diff --git a/dlls/winedos/int21.c b/dlls/winedos/int21.c index 8b74a656c10..26a3a3fd707 100644 --- a/dlls/winedos/int21.c +++ b/dlls/winedos/int21.c @@ -72,11 +72,17 @@ void WINAPI DOSVM_Int21Handler_Ioctl( CONTEXT86 *context ) /*********************************************************************** * DOSVM_Int21Handler * - * int 21h real-mode handler. Most calls are passed directly to DOS3Call. + * int 21h handler. Most calls are passed directly to DOS3Call. */ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context ) { BYTE ascii; + + if (DOSVM_IsWin16()) { + DOS3Call( context ); + return; + } + RESET_CFLAG(context); /* Not sure if this is a good idea */ if(AH_reg(context) == 0x0c) /* FLUSH BUFFER AND READ STANDARD INPUT */ diff --git a/dlls/winedos/int31.c b/dlls/winedos/int31.c index bb170bf30ef..75fab2a9310 100644 --- a/dlls/winedos/int31.c +++ b/dlls/winedos/int31.c @@ -614,26 +614,37 @@ void WINAPI DOSVM_FreeRMCB( CONTEXT86 *context ) } } - /********************************************************************** - * DOSVM_Int31Handler + * DOSVM_CheckWrappers * - * Handler for real-mode int 31h (DPMI). + * Check if this was really a wrapper call instead of an interrupt. + * FIXME: Protected mode stuff does not work in 32-bit DPMI. + * FIXME: If int31 is called asynchronously (unlikely) + * wrapper checks are wrong (CS/IP must not be used). */ -void WINAPI DOSVM_Int31Handler( CONTEXT86 *context ) +static BOOL DOSVM_CheckWrappers( CONTEXT86 *context ) { + /* Handle protected mode interrupts. */ + if (!ISV86(context)) { + if (context->SegCs == DOSVM_dpmi_segments->dpmi_sel) { + INT_Int31Handler( context ); /* FIXME: Call RawModeSwitch */ + return TRUE; + } + return FALSE; + } + /* check if it's our wrapper */ TRACE("called from real mode\n"); if (context->SegCs==DOSVM_dpmi_segments->dpmi_seg) { /* This is the protected mode switch */ StartPM(context); - return; + return TRUE; } else if (context->SegCs==DOSVM_dpmi_segments->xms_seg) { /* This is the XMS driver entry point */ XMS_Handler(context); - return; + return TRUE; } else { @@ -646,10 +657,57 @@ void WINAPI DOSVM_Int31Handler( CONTEXT86 *context ) if (CurrRMCB) { /* RMCB call, propagate to protected-mode handler */ DPMI_CallRMCBProc(context, CurrRMCB, dpmi_flag); - return; + return TRUE; } } - /* chain to protected mode handler */ - INT_Int31Handler( context ); + return FALSE; +} + +/********************************************************************** + * DOSVM_Int31Handler + * + * Handler for int 31h (DPMI). + */ +void WINAPI DOSVM_Int31Handler( CONTEXT86 *context ) +{ + if (DOSVM_CheckWrappers(context)) + return; + + RESET_CFLAG(context); + switch(AX_reg(context)) + { + case 0x0204: /* Get protected mode interrupt vector */ + TRACE("get protected mode interrupt handler (0x%02x)\n", + BL_reg(context)); + if (DOSVM_IsDos32()) { + FARPROC48 handler = DOSVM_GetPMHandler48( BL_reg(context) ); + SET_CX( context, handler.selector ); + context->Edx = handler.offset; + } else { + FARPROC16 handler = DOSVM_GetPMHandler16( BL_reg(context) ); + SET_CX( context, SELECTOROF(handler) ); + SET_DX( context, OFFSETOF(handler) ); + } + break; + + case 0x0205: /* Set protected mode interrupt vector */ + TRACE("set protected mode interrupt handler (0x%02x,0x%04x:0x%08lx)\n", + BL_reg(context), CX_reg(context), context->Edx); + if (DOSVM_IsDos32()) { + FARPROC48 handler; + handler.selector = CX_reg(context); + handler.offset = context->Edx; + DOSVM_SetPMHandler48( BL_reg(context), handler ); + } else { + FARPROC16 handler; + handler = (FARPROC16)MAKESEGPTR( CX_reg(context), DX_reg(context)); + DOSVM_SetPMHandler16( BL_reg(context), handler ); + } + break; + + default: + /* chain to protected mode handler */ + INT_Int31Handler( context ); /* FIXME: move DPMI code here */ + } } diff --git a/dlls/winedos/interrupts.c b/dlls/winedos/interrupts.c index 62455176e61..d1001aa3f2b 100644 --- a/dlls/winedos/interrupts.c +++ b/dlls/winedos/interrupts.c @@ -24,13 +24,80 @@ WINE_DEFAULT_DEBUG_CHANNEL(int); -static FARPROC16 DOSVM_Vectors16[256]; -static FARPROC48 DOSVM_Vectors48[256]; -static INTPROC DOSVM_VectorsBuiltin[256]; +/* + * FIXME: Interrupt handlers for interrupts implemented in other DLLs. + * These functions should be removed when the interrupt handlers have + * been moved to winedos. + */ +void WINAPI DOSVM_Int11Handler( CONTEXT86 *context ) { INT_Int11Handler(context); } +void WINAPI DOSVM_Int12Handler( CONTEXT86 *context ) { INT_Int12Handler(context); } +void WINAPI DOSVM_Int13Handler( CONTEXT86 *context ) { INT_Int13Handler(context); } +void WINAPI DOSVM_Int15Handler( CONTEXT86 *context ) { INT_Int15Handler(context); } +void WINAPI DOSVM_Int1aHandler( CONTEXT86 *context ) { INT_Int1aHandler(context); } +void WINAPI DOSVM_Int25Handler( CONTEXT86 *context ) { INT_Int25Handler(context); } +void WINAPI DOSVM_Int26Handler( CONTEXT86 *context ) { INT_Int26Handler(context); } +void WINAPI DOSVM_Int2aHandler( CONTEXT86 *context ) { INT_Int2aHandler(context); } +void WINAPI DOSVM_Int2fHandler( CONTEXT86 *context ) { INT_Int2fHandler(context); } +void WINAPI DOSVM_Int34Handler( CONTEXT86 *context ) { INT_Int34Handler(context); } +void WINAPI DOSVM_Int35Handler( CONTEXT86 *context ) { INT_Int35Handler(context); } +void WINAPI DOSVM_Int36Handler( CONTEXT86 *context ) { INT_Int36Handler(context); } +void WINAPI DOSVM_Int37Handler( CONTEXT86 *context ) { INT_Int37Handler(context); } +void WINAPI DOSVM_Int38Handler( CONTEXT86 *context ) { INT_Int38Handler(context); } +void WINAPI DOSVM_Int39Handler( CONTEXT86 *context ) { INT_Int39Handler(context); } +void WINAPI DOSVM_Int3aHandler( CONTEXT86 *context ) { INT_Int3aHandler(context); } +void WINAPI DOSVM_Int3bHandler( CONTEXT86 *context ) { INT_Int3bHandler(context); } +void WINAPI DOSVM_Int3cHandler( CONTEXT86 *context ) { INT_Int3cHandler(context); } +void WINAPI DOSVM_Int3dHandler( CONTEXT86 *context ) { INT_Int3dHandler(context); } +void WINAPI DOSVM_Int3eHandler( CONTEXT86 *context ) { INT_Int3eHandler(context); } +void WINAPI DOSVM_Int41Handler( CONTEXT86 *context ) { INT_Int41Handler(context); } +void WINAPI DOSVM_Int4bHandler( CONTEXT86 *context ) { INT_Int4bHandler(context); } +void WINAPI DOSVM_Int5cHandler( CONTEXT86 *context ) { NetBIOSCall16(context); } -/* Ordinal number for interrupt 0 handler in winedos.dll and winedos16.dll */ +static FARPROC16 DOSVM_Vectors16[256]; +static FARPROC48 DOSVM_Vectors48[256]; +static const INTPROC DOSVM_VectorsBuiltin[] = +{ + /* 00 */ 0, 0, 0, 0, + /* 04 */ 0, 0, 0, 0, + /* 08 */ 0, DOSVM_Int09Handler, 0, 0, + /* 0C */ 0, 0, 0, 0, + /* 10 */ DOSVM_Int10Handler, DOSVM_Int11Handler, DOSVM_Int12Handler, DOSVM_Int13Handler, + /* 14 */ 0, DOSVM_Int15Handler, DOSVM_Int16Handler, DOSVM_Int17Handler, + /* 18 */ 0, 0, DOSVM_Int1aHandler, 0, + /* 1C */ 0, 0, 0, 0, + /* 20 */ DOSVM_Int20Handler, DOSVM_Int21Handler, 0, 0, + /* 24 */ 0, DOSVM_Int25Handler, DOSVM_Int26Handler, 0, + /* 28 */ 0, DOSVM_Int29Handler, DOSVM_Int2aHandler, 0, + /* 2C */ 0, 0, 0, DOSVM_Int2fHandler, + /* 30 */ 0, DOSVM_Int31Handler, 0, DOSVM_Int33Handler, + /* 34 */ DOSVM_Int34Handler, DOSVM_Int35Handler, DOSVM_Int36Handler, DOSVM_Int37Handler, + /* 38 */ DOSVM_Int38Handler, DOSVM_Int39Handler, DOSVM_Int3aHandler, DOSVM_Int3bHandler, + /* 3C */ DOSVM_Int3cHandler, DOSVM_Int3dHandler, DOSVM_Int3eHandler, 0, + /* 40 */ 0, DOSVM_Int41Handler, 0, 0, + /* 44 */ 0, 0, 0, 0, + /* 48 */ 0, 0, 0, DOSVM_Int4bHandler, + /* 4C */ 0, 0, 0, 0, + /* 50 */ 0, 0, 0, 0, + /* 54 */ 0, 0, 0, 0, + /* 58 */ 0, 0, 0, 0, + /* 5C */ DOSVM_Int5cHandler, 0, 0, 0, + /* 60 */ 0, 0, 0, 0, + /* 64 */ 0, 0, 0, DOSVM_Int67Handler +}; + +/* Ordinal number for interrupt 0 handler in winedos16.dll */ #define FIRST_INTERRUPT 100 +/********************************************************************** + * DOSVM_DefaultHandler + * + * Default interrupt handler. This will be used to emulate all + * interrupts that don't have their own interrupt handler. + */ +void WINAPI DOSVM_DefaultHandler( CONTEXT86 *context ) +{ +} + /********************************************************************** * DOSVM_EmulateInterruptPM * @@ -143,11 +210,11 @@ FARPROC16 DOSVM_GetPMHandler16( BYTE intnum ) /********************************************************************** - * DOSVM_SetPMHandler + * DOSVM_SetPMHandler16 * * Set the protected mode interrupt handler for a given interrupt. */ -void DOSVM_SetPMHandler( BYTE intnum, FARPROC16 handler ) +void DOSVM_SetPMHandler16( BYTE intnum, FARPROC16 handler ) { TRACE("Set protected mode interrupt vector %02x <- %04x:%04x\n", intnum, HIWORD(handler), LOWORD(handler) ); @@ -190,41 +257,12 @@ void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler ) */ INTPROC DOSVM_GetBuiltinHandler( BYTE intnum ) { - static HMODULE procs; - INTPROC handler = DOSVM_VectorsBuiltin[intnum]; - - if (!handler) - { - if (!procs) - procs = LoadLibraryA( "winedos.dll" ); - - if (!procs) - { - ERR("could not load winedos.dll\n"); - return 0; - } - - handler = (INTPROC)GetProcAddress( procs, - (LPCSTR)(FIRST_INTERRUPT + intnum)); - if (!handler) - { - WARN("int%x not implemented, returning dummy handler\n", intnum ); - handler = (INTPROC)GetProcAddress( procs, - (LPCSTR)(FIRST_INTERRUPT + 256)); - } - - DOSVM_VectorsBuiltin[intnum] = handler; + if (intnum < sizeof(DOSVM_VectorsBuiltin)/sizeof(INTPROC)) { + INTPROC proc = DOSVM_VectorsBuiltin[intnum]; + if(proc) + return proc; } - return handler; -} - -/********************************************************************** - * DOSVM_DefaultHandler - * - * Default interrupt handler. This will be used to emulate all - * interrupts that don't have their own interrupt handler. - */ -void WINAPI DOSVM_DefaultHandler( CONTEXT86 *context ) -{ + WARN("int%x not implemented, returning dummy handler\n", intnum ); + return DOSVM_DefaultHandler; } diff --git a/include/miscemu.h b/include/miscemu.h index fd0302dcea6..965a442ccfa 100644 --- a/include/miscemu.h +++ b/include/miscemu.h @@ -240,6 +240,15 @@ extern void WINAPI INT_Int2aHandler(CONTEXT86*); /* msdos/int2f.c */ extern void WINAPI INT_Int2fHandler(CONTEXT86*); +/* msdos/int41.c */ +extern void WINAPI INT_Int41Handler(CONTEXT86*); + +/* msdos/int4b.c */ +extern void WINAPI INT_Int4bHandler(CONTEXT86*); + +/* msdos/int5c.c */ +extern void WINAPI NetBIOSCall16(CONTEXT86*); + /* fpu.c */ extern void WINAPI INT_Int34Handler(CONTEXT86*); extern void WINAPI INT_Int35Handler(CONTEXT86*);