After this patch winedos will contain entry points for all interrupt handlers even though many of these entry points are just functions that forward interrupt handling to other DLLs. A bit ugly way of doing things but I believe this approach makes further interrupt work easier. Next patches shall add winedos16.dll for PM 16-bit entry points and a small patch after that shall start using interrupts.c tables for PM and RM interrupts. Then the real work of migrating interrupt handlers can be started... Changelog: Modify winedos interrupt handlers so that they work with PM interrupts. Add forwarding functions for handlers in other DLLs. Make DOSVM_GetBuiltinHandler use static table instead of GetProcAddress. Index: dlls/winedos/int20.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/int20.c,v retrieving revision 1.2 diff -u -r1.2 int20.c --- dlls/winedos/int20.c 9 Mar 2002 23:44:32 -0000 1.2 +++ dlls/winedos/int20.c 29 Oct 2002 18:53:10 -0000 @@ -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); } Index: dlls/winedos/int21.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/int21.c,v retrieving revision 1.13 diff -u -r1.13 int21.c --- dlls/winedos/int21.c 12 Sep 2002 22:07:04 -0000 1.13 +++ dlls/winedos/int21.c 29 Oct 2002 18:54:37 -0000 @@ -72,11 +72,17 @@ /*********************************************************************** * 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 */ Index: dlls/winedos/int31.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/int31.c,v retrieving revision 1.10 diff -u -r1.10 int31.c --- dlls/winedos/int31.c 28 Oct 2002 20:12:40 -0000 1.10 +++ dlls/winedos/int31.c 29 Oct 2002 18:55:29 -0000 @@ -614,26 +614,37 @@ } } - /********************************************************************** - * 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 @@ 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 + } } Index: dlls/winedos/interrupts.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/interrupts.c,v retrieving revision 1.2 diff -u -r1.2 interrupts.c --- dlls/winedos/interrupts.c 28 Oct 2002 20:12:40 -0000 1.2 +++ dlls/winedos/interrupts.c 29 Oct 2002 18:56:28 -0000 @@ -24,14 +24,81 @@ 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); } + +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 winedos.dll and winedos16.dll */ +/* 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 * * Emulate software interrupt in 16-bit or 32-bit protected mode. @@ -143,11 +210,11 @@ /********************************************************************** - * 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 @@ */ 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; } Index: include/miscemu.h =================================================================== RCS file: /home/wine/wine/include/miscemu.h,v retrieving revision 1.55 diff -u -r1.55 miscemu.h --- include/miscemu.h 23 Oct 2002 22:24:10 -0000 1.55 +++ include/miscemu.h 29 Oct 2002 19:00:47 -0000 @@ -240,6 +240,15 @@ /* 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*); Index: dlls/kernel/kernel32.spec =================================================================== RCS file: /home/wine/wine/dlls/kernel/kernel32.spec,v retrieving revision 1.66 diff -u -r1.66 kernel32.spec --- dlls/kernel/kernel32.spec 18 Oct 2002 00:29:33 -0000 1.66 +++ dlls/kernel/kernel32.spec 29 Oct 2002 19:01:29 -0000 @@ -1049,6 +1049,7 @@ @ 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 @@ @ 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 -- Jukka Heinonen <http://www.iki.fi/jhei/>