diff --git a/dlls/kernel/kernel_main.c b/dlls/kernel/kernel_main.c index 229dcc08089..649c051ec26 100644 --- a/dlls/kernel/kernel_main.c +++ b/dlls/kernel/kernel_main.c @@ -76,9 +76,6 @@ static BOOL process_attach(void) /* Force loading of some dlls */ if (LoadLibrary16( "system" ) < 32) return FALSE; - /* Read DOS config.sys */ - if (!DOSCONF_ReadConfig()) return FALSE; - /* Create 16-bit task */ TASK_CreateMainTask(); diff --git a/dlls/kernel/wprocs.spec b/dlls/kernel/wprocs.spec index 8af24f093b8..eeafdf5643a 100644 --- a/dlls/kernel/wprocs.spec +++ b/dlls/kernel/wprocs.spec @@ -4,7 +4,6 @@ owner kernel32 # Interrupt vectors 0-255 are ordinals 100-355 # The 'interrupt' keyword takes care of the flags pushed on the stack by the interrupt -116 interrupt INT_Int10Handler() INT_Int10Handler 117 interrupt INT_Int11Handler() INT_Int11Handler 118 interrupt INT_Int12Handler() INT_Int12Handler 119 interrupt INT_Int13Handler() INT_Int13Handler diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index f43f755500a..3d7058aa02b 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -28,7 +28,6 @@ C_SRCS = \ wcstring.c EXTRA_OBJS = \ - $(TOPOBJDIR)/console/console.o \ $(TOPOBJDIR)/files/files.o \ $(TOPOBJDIR)/if1632/if1632.o \ $(TOPOBJDIR)/loader/loader.o \ @@ -42,7 +41,6 @@ EXTRA_OBJS = \ $(TOPOBJDIR)/win32/win32.o SUBDIRS = \ - $(TOPOBJDIR)/console \ $(TOPOBJDIR)/files \ $(TOPOBJDIR)/if1632 \ $(TOPOBJDIR)/loader \ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 2cc319b1b84..f9dfbb1cd3b 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1,11 +1,11 @@ name ntdll type win32 -debug_channels (aspi atom cdrom console ddraw debug delayhlp dll dosfs dosmem - file fixup global heap int int10 int16 int17 int19 int21 int31 - io loaddll local module ntdll process profile reg relay resource - segment seh selector server snoop string system tape task thread - thunk tid timer toolhelp ver virtual vxd win32) +debug_channels (atom cdrom console debug delayhlp dll dosfs dosmem file fixup + global heap int int21 int31 io loaddll local module ntdll process + profile reg relay resource segment seh selector server snoop + string system tape task thread thunk tid timer toolhelp ver + virtual vxd win32) #note that the Zw... functions are alternate names for the #Nt... functions. (see www.sysinternals.com for details) diff --git a/dlls/winedos/Makefile.in b/dlls/winedos/Makefile.in index d1a053496ed..c9100692b3d 100644 --- a/dlls/winedos/Makefile.in +++ b/dlls/winedos/Makefile.in @@ -7,10 +7,33 @@ SOVERSION = 1.0 IMPORTS = user32 kernel32 ntdll C_SRCS = \ + dosaspi.c \ + devices.c \ dosvm.c \ int09.c \ - module.c + int10.c \ + int16.c \ + int17.c \ + int19.c \ + int20.c \ + int21.c \ + int29.c \ + int31.c \ + int33.c \ + ioports.c \ + module.c \ + vga.c \ + xms.c + +EXTRA_OBJS = \ + $(TOPOBJDIR)/console/console.o + +SUBDIRS = \ + $(TOPOBJDIR)/console @MAKE_DLL_RULES@ +$(EXTRA_OBJS): dummy + @cd `dirname $@` && $(MAKE) `basename $@` + ### Dependencies: diff --git a/msdos/devices.c b/dlls/winedos/devices.c similarity index 98% rename from msdos/devices.c rename to dlls/winedos/devices.c index 45e51663756..451e7bf39f1 100644 --- a/msdos/devices.c +++ b/dlls/winedos/devices.c @@ -10,7 +10,6 @@ #include "msdos.h" #include "miscemu.h" #include "dosexe.h" -#include "callback.h" #include "debugtools.h" #include "pshpack1.h" @@ -107,7 +106,6 @@ typedef struct WORD attr; RMCBPROC strategy; RMCBPROC interrupt; - } WINEDEV; static WINEDEV devs[] = @@ -136,7 +134,11 @@ typedef struct #define DOS_DATASEG_OFF(xxx) FIELD_OFFSET(DOS_DATASEG, xxx) -DWORD DOS_LOLSeg; +struct _DOS_LISTOFLISTS * DOSMEM_LOL() +{ + return (struct _DOS_LISTOFLISTS *)DOSMEM_MapRealToLinear + (MAKESEGPTR(HIWORD(DOS_LOLSeg),0)); +} /* the device implementations */ @@ -265,7 +267,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx) /* check for new keyboard input */ while (CurOfs == bios->FirstKbdCharPtr) { /* no input available yet, so wait... */ - Dosvm.Wait( -1, 0 ); + DOSVM_Wait( -1, 0 ); } /* read from keyboard queue (call int16?) */ data = ((WORD*)bios)[CurOfs]; @@ -284,7 +286,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx) /* check for new keyboard input */ while (CurOfs == bios->FirstKbdCharPtr) { /* no input available yet, so wait... */ - Dosvm.Wait( -1, 0 ); + DOSVM_Wait( -1, 0 ); } /* read from keyboard queue (call int16?) */ data = ((WORD*)bios)[CurOfs]; diff --git a/msdos/dosaspi.c b/dlls/winedos/dosaspi.c similarity index 96% rename from msdos/dosaspi.c rename to dlls/winedos/dosaspi.c index a7bb3be9cbc..140e8cae12b 100644 --- a/msdos/dosaspi.c +++ b/dlls/winedos/dosaspi.c @@ -167,8 +167,12 @@ void WINAPI ASPI_DOS_func(CONTEXT86 *context) } -/* returns the address of a real mode callback to ASPI_DOS_func() */ -void ASPI_DOS_HandleInt(CONTEXT86 *context) +/********************************************************************** + * DOSVM_ASPIHandler (WINEDOS.@) + * + * returns the address of a real mode callback to ASPI_DOS_func() + */ +void WINAPI DOSVM_ASPIHandler( CONTEXT86 *context ) { FARPROC16 *p = (FARPROC16 *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); TRACE("DOS ASPI opening\n"); diff --git a/dlls/winedos/dosexe.h b/dlls/winedos/dosexe.h new file mode 100644 index 00000000000..60fbd01a6d7 --- /dev/null +++ b/dlls/winedos/dosexe.h @@ -0,0 +1,98 @@ +/* + * DOS EXE loader + * + * Copyright 1998 Ove Kåven + */ + +#ifndef __WINE_DOSEXE_H +#define __WINE_DOSEXE_H + +#include "wine/windef16.h" +#include "winbase.h" /* for LPSTARTUPINFO32A */ +#include "winnt.h" /* for PCONTEXT */ + +struct _DOSEVENT; + +typedef void (*DOSRELAY)(CONTEXT86*,void*); + +#define DOS_PRIORITY_REALTIME 0 /* IRQ0 */ +#define DOS_PRIORITY_KEYBOARD 1 /* IRQ1 */ +#define DOS_PRIORITY_VGA 2 /* IRQ9 */ +#define DOS_PRIORITY_MOUSE 5 /* IRQ12 */ +#define DOS_PRIORITY_SERIAL 10 /* IRQ4 */ + +extern WORD DOSVM_psp; /* psp of current DOS task */ +extern WORD DOSVM_retval; /* return value of previous DOS task */ + +#if defined(linux) && defined(__i386__) +#define MZ_SUPPORTED +#endif /* linux-i386 */ + +#define V86_FLAG 0x00020000 + +extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile ); +extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk ); +extern void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval ); +extern BOOL WINAPI MZ_Current( void ); +extern void WINAPI MZ_AllocDPMITask( void ); +extern void WINAPI MZ_RunInThread( PAPCFUNC proc, ULONG_PTR arg ); +extern INT WINAPI DOSVM_Enter( CONTEXT86 *context ); +extern void WINAPI DOSVM_Wait( INT read_pipe, HANDLE hObject ); +extern DWORD WINAPI DOSVM_Loop( LPVOID lpExtra ); +extern void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data ); +extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val ); +extern void WINAPI DOSVM_SetTimer( UINT ticks ); +extern UINT WINAPI DOSVM_GetTimer( void ); +extern FARPROC16 DOSVM_GetRMHandler( BYTE intnum ); +extern void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler ); +extern void DOSVM_RealModeInterrupt( BYTE intnum, CONTEXT86 *context ); + +/* devices.c */ +extern void DOSDEV_InstallDOSDevices(void); +extern DWORD DOSDEV_Console(void); +extern DWORD DOSDEV_FindCharDevice(char*name); +extern int DOSDEV_Peek(DWORD dev, BYTE*data); +extern int DOSDEV_Read(DWORD dev, DWORD buf, int buflen); +extern int DOSDEV_Write(DWORD dev, DWORD buf, int buflen, int verify); +extern int DOSDEV_IoctlRead(DWORD dev, DWORD buf, int buflen); +extern int DOSDEV_IoctlWrite(DWORD dev, DWORD buf, int buflen); + +/* int09.c */ +extern void WINAPI DOSVM_Int09Handler(CONTEXT86*); +extern void WINAPI DOSVM_Int09SendScan(BYTE scan,BYTE ascii); +extern BYTE WINAPI DOSVM_Int09ReadScan(BYTE*ascii); + +/* int10.c */ +extern void WINAPI DOSVM_Int10Handler(CONTEXT86*); + +/* int16.c */ +extern void WINAPI DOSVM_Int16Handler(CONTEXT86*); +extern int WINAPI DOSVM_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek); +extern int WINAPI DOSVM_Int16AddChar(BYTE ascii,BYTE scan); + +/* int17.c */ +extern void WINAPI DOSVM_Int17Handler(CONTEXT86*); + +/* int19.c */ +extern void WINAPI DOSVM_Int19Handler(CONTEXT86*); + +/* int20.c */ +extern void WINAPI DOSVM_Int20Handler(CONTEXT86*); + +/* int21.c */ +extern void WINAPI DOSVM_Int21Handler(CONTEXT86*); + +/* int29.c */ +extern void WINAPI DOSVM_Int29Handler(CONTEXT86*); + +/* int31.c */ +extern void WINAPI DOSVM_Int31Handler(CONTEXT86*); + +/* int33.c */ +extern void WINAPI DOSVM_Int33Handler(CONTEXT86*); +extern void WINAPI DOSVM_Int33Message(UINT,WPARAM,LPARAM); + +/* xms.c */ +extern void WINAPI XMS_Handler(CONTEXT86*); + +#endif /* __WINE_DOSEXE_H */ diff --git a/dlls/winedos/dosvm.c b/dlls/winedos/dosvm.c index 6d23f36db46..f8338b9c2b0 100644 --- a/dlls/winedos/dosvm.c +++ b/dlls/winedos/dosvm.c @@ -35,10 +35,13 @@ #include "stackframe.h" #include "debugtools.h" -DECLARE_DEBUG_CHANNEL(int); +DEFAULT_DEBUG_CHANNEL(int); DECLARE_DEBUG_CHANNEL(module); DECLARE_DEBUG_CHANNEL(relay); +WORD DOSVM_psp = 0; +WORD DOSVM_retval = 0; + #ifdef MZ_SUPPORTED #ifdef HAVE_SYS_VM86_H @@ -128,7 +131,7 @@ static void DOSVM_Dump( int fn, int sig, struct vm86plus_struct*VM86 ) static int DOSVM_SimulateInt( int vect, CONTEXT86 *context, BOOL inwine ) { - FARPROC16 handler=INT_GetRMHandler(vect); + FARPROC16 handler=DOSVM_GetRMHandler(vect); /* check for our real-mode hooks */ if (vect==0x31) { @@ -141,16 +144,16 @@ static int DOSVM_SimulateInt( int vect, CONTEXT86 *context, BOOL inwine ) /* check if the call is from our fake BIOS interrupt stubs */ if ((context->SegCs==0xf000) && !inwine) { if (vect != (context->Eip/4)) { - TRACE_(int)("something fishy going on here (interrupt stub is %02lx)\n", context->Eip/4); + TRACE("something fishy going on here (interrupt stub is %02lx)\n", context->Eip/4); } - TRACE_(int)("builtin interrupt %02x has been branched to\n", vect); - INT_RealModeInterrupt(vect, context); + TRACE("builtin interrupt %02x has been branched to\n", vect); + DOSVM_RealModeInterrupt(vect, context); } /* check if the call goes to an unhooked interrupt */ else if (SELECTOROF(handler)==0xf000) { /* if so, call it directly */ - TRACE_(int)("builtin interrupt %02x has been invoked (through vector %02x)\n", OFFSETOF(handler)/4, vect); - INT_RealModeInterrupt(OFFSETOF(handler)/4, context); + TRACE("builtin interrupt %02x has been invoked (through vector %02x)\n", OFFSETOF(handler)/4, vect); + DOSVM_RealModeInterrupt(OFFSETOF(handler)/4, context); } /* the interrupt is hooked, simulate interrupt in DOS space */ else { @@ -186,19 +189,19 @@ static void DOSVM_SendQueuedEvent(CONTEXT86 *context) /* it's an IRQ, move it to "current" list */ event->next = current_event; current_event = event; - TRACE_(int)("dispatching IRQ %d\n",event->irq); + TRACE("dispatching IRQ %d\n",event->irq); /* note that if DOSVM_SimulateInt calls an internal interrupt directly, * current_event might be cleared (and event freed) in this very call! */ DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context,TRUE); } else { /* callback event */ - TRACE_(int)("dispatching callback event\n"); + TRACE("dispatching callback event\n"); (*event->relay)(context,event->data); free(event); } } if (!SHOULD_PEND(pending_event)) { - TRACE_(int)("clearing Pending flag\n"); + TRACE("clearing Pending flag\n"); CLR_PEND(context); } } @@ -221,7 +224,7 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data if (entered) { event = malloc(sizeof(DOSEVENT)); if (!event) { - ERR_(int)("out of memory allocating event entry\n"); + ERR("out of memory allocating event entry\n"); return; } event->irq = irq; event->priority = priority; @@ -240,11 +243,11 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data /* get dosmod's attention to the new event, if necessary */ if (!sig_sent) { - TRACE_(int)("new event queued, signalling dosmod\n"); + TRACE("new event queued, signalling dosmod\n"); kill(dosmod_pid,SIGUSR2); sig_sent++; } else { - TRACE_(int)("new event queued\n"); + TRACE("new event queued\n"); } } else { /* DOS subsystem not running */ @@ -256,7 +259,7 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data memset(&context,0,sizeof(context)); (*relay)(&context,data); } else { - ERR_(int)("IRQ without DOS task: should not happen"); + ERR("IRQ without DOS task: should not happen"); } } } @@ -299,19 +302,19 @@ static int DOSVM_Process( int fn, int sig, struct vm86plus_struct*VM86 ) switch (VM86_TYPE(fn)) { case VM86_SIGNAL: - TRACE_(int)("DOS module caught signal %d\n",sig); + TRACE("DOS module caught signal %d\n",sig); if ((sig==SIGALRM) || (sig==SIGUSR2)) { if (sig==SIGALRM) { sig_sent++; DOSVM_QueueEvent(0,DOS_PRIORITY_REALTIME,NULL,NULL); } if (pending_event) { - TRACE_(int)("setting Pending flag, interrupts are currently %s\n", + TRACE("setting Pending flag, interrupts are currently %s\n", IF_ENABLED(&context) ? "enabled" : "disabled"); SET_PEND(&context); DOSVM_SendQueuedEvents(&context); } else { - TRACE_(int)("no events are pending, clearing Pending flag\n"); + TRACE("no events are pending, clearing Pending flag\n"); CLR_PEND(&context); } sig_sent--; @@ -337,7 +340,7 @@ static int DOSVM_Process( int fn, int sig, struct vm86plus_struct*VM86 ) case VM86_STI: IF_SET(&context); /* case VM86_PICRETURN: */ - TRACE_(int)("DOS task enabled interrupts %s events pending, sending events\n", IS_PEND(&context)?"with":"without"); + TRACE("DOS task enabled interrupts %s events pending, sending events\n", IS_PEND(&context)?"with":"without"); DOSVM_SendQueuedEvents(&context); break; case VM86_TRAP: @@ -375,12 +378,12 @@ static void DOSVM_ProcessConsole(void) /* check whether extended bit is set, * and if so, queue the extension prefix */ if (msg.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY) { - INT_Int09SendScan(0xE0,0); + DOSVM_Int09SendScan(0xE0,0); } - INT_Int09SendScan(scan,msg.Event.KeyEvent.uChar.AsciiChar); + DOSVM_Int09SendScan(scan,msg.Event.KeyEvent.uChar.AsciiChar); break; default: - FIXME_(int)("unhandled console event: %d\n", msg.EventType); + FIXME("unhandled console event: %d\n", msg.EventType); } } } @@ -389,10 +392,10 @@ static void DOSVM_ProcessMessage(MSG *msg) { BYTE scan = 0; - TRACE_(int)("got message %04x, wparam=%08x, lparam=%08lx\n",msg->message,msg->wParam,msg->lParam); + TRACE("got message %04x, wparam=%08x, lparam=%08lx\n",msg->message,msg->wParam,msg->lParam); if ((msg->message>=WM_MOUSEFIRST)&& (msg->message<=WM_MOUSELAST)) { - INT_Int33Message(msg->message,msg->wParam,msg->lParam); + DOSVM_Int33Message(msg->message,msg->wParam,msg->lParam); } else { switch (msg->message) { case WM_KEYUP: @@ -406,9 +409,9 @@ static void DOSVM_ProcessMessage(MSG *msg) /* FIXME: some keys (function keys) have * extended bit set even when they shouldn't, * should check for them */ - INT_Int09SendScan(0xE0,0); + DOSVM_Int09SendScan(0xE0,0); } - INT_Int09SendScan(scan,0); + DOSVM_Int09SendScan(scan,0); break; } } @@ -571,7 +574,7 @@ void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val) if ((port==0x20) && (val==0x20)) { if (current_event) { /* EOI (End Of Interrupt) */ - TRACE_(int)("received EOI for current IRQ, clearing\n"); + TRACE("received EOI for current IRQ, clearing\n"); event = current_event; current_event = event->next; if (event->relay) @@ -582,15 +585,15 @@ void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val) !sig_sent) { /* another event is pending, which we should probably * be able to process now, so tell dosmod about it */ - TRACE_(int)("another event pending, signalling dosmod\n"); + TRACE("another event pending, signalling dosmod\n"); kill(dosmod_pid,SIGUSR2); sig_sent++; } } else { - WARN_(int)("EOI without active IRQ\n"); + WARN("EOI without active IRQ\n"); } } else { - FIXME_(int)("unrecognized PIC command %02x\n",val); + FIXME("unrecognized PIC command %02x\n",val); } } @@ -602,7 +605,7 @@ void WINAPI DOSVM_SetTimer( UINT ticks ) int stat=DOSMOD_SET_TIMER; struct timeval tim; - if (MZ_Current()) { + if (write_pipe != -1) { /* the PC clocks ticks at 1193180 Hz */ tim.tv_sec=0; tim.tv_usec=MulDiv(ticks,1000000,1193180); @@ -629,7 +632,7 @@ UINT WINAPI DOSVM_GetTimer( void ) int stat=DOSMOD_GET_TIMER; struct timeval tim; - if (MZ_Current()) { + if (write_pipe != -1) { if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { ERR_(module)("dosmod sync lost, errno=%d\n",errno); return 0; @@ -688,23 +691,82 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data memset(&context,0,sizeof(context)); (*relay)(&context,data); } else { - ERR_(int)("IRQ without DOS task: should not happen"); + ERR("IRQ without DOS task: should not happen"); } } #endif +/********************************************************************** + * DOSVM_GetRMHandler + * + * Return the real mode interrupt vector for a given interrupt. + */ +FARPROC16 DOSVM_GetRMHandler( BYTE intnum ) +{ + return ((FARPROC16*)DOSMEM_SystemBase())[intnum]; +} + + +/********************************************************************** + * DOSVM_SetRMHandler + * + * Set the real mode interrupt handler for a given interrupt. + */ +void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler ) +{ + TRACE("Set real mode interrupt vector %02x <- %04x:%04x\n", + intnum, HIWORD(handler), LOWORD(handler) ); + ((FARPROC16*)DOSMEM_SystemBase())[intnum] = handler; +} + + +static const INTPROC real_mode_handlers[] = +{ + /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 08 */ 0, DOSVM_Int09Handler, 0, 0, 0, 0, 0, 0, + /* 10 */ DOSVM_Int10Handler, INT_Int11Handler, INT_Int12Handler, INT_Int13Handler, + 0, INT_Int15Handler, DOSVM_Int16Handler, DOSVM_Int17Handler, + /* 18 */ 0, 0, INT_Int1aHandler, 0, 0, 0, 0, 0, + /* 20 */ DOSVM_Int20Handler, DOSVM_Int21Handler, 0, 0, 0, INT_Int25Handler, 0, 0, + /* 28 */ 0, DOSVM_Int29Handler, INT_Int2aHandler, 0, 0, 0, 0, INT_Int2fHandler, + /* 30 */ 0, DOSVM_Int31Handler, 0, DOSVM_Int33Handler +}; + + +/********************************************************************** + * DOSVM_RealModeInterrupt + * + * Handle real mode interrupts + */ +void DOSVM_RealModeInterrupt( BYTE intnum, CONTEXT86 *context ) +{ + if (intnum < sizeof(real_mode_handlers)/sizeof(INTPROC) && real_mode_handlers[intnum]) + (*real_mode_handlers[intnum])(context); + else + { + FIXME("Unknown Interrupt in DOS mode: 0x%x\n", intnum); + FIXME(" eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx\n", + context->Eax, context->Ebx, context->Ecx, context->Edx); + FIXME(" esi=%08lx edi=%08lx ds=%04lx es=%04lx\n", + context->Esi, context->Edi, context->SegDs, context->SegEs ); + } +} + + +/********************************************************************** + * DOSVM_Init + */ BOOL WINAPI DOSVM_Init( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) { - TRACE_(module)("(0x%08x,%ld,%p)\n", hinstDLL, fdwReason, lpvReserved); + TRACE_(module)("(0x%08x,%ld,%p)\n", hinstDLL, fdwReason, lpvReserved); - if (fdwReason == DLL_PROCESS_ATTACH) { - INT_SetWineHandler(9, INT_Int09Handler); - } - else if (fdwReason == DLL_PROCESS_DETACH) - { - INT_SetWineHandler(9, NULL); - } - - return TRUE; + if (fdwReason == DLL_PROCESS_ATTACH) + { + /* initialize the memory */ + TRACE("Initializing DOS memory structures\n"); + DOSMEM_Init( TRUE ); + DOSDEV_InstallDOSDevices(); + } + return TRUE; } diff --git a/dlls/winedos/int09.c b/dlls/winedos/int09.c index d281670f631..96f65e4faf2 100644 --- a/dlls/winedos/int09.c +++ b/dlls/winedos/int09.c @@ -11,7 +11,6 @@ #include "winuser.h" #include "miscemu.h" #include "debugtools.h" -#include "callback.h" #include "dosexe.h" DEFAULT_DEBUG_CHANNEL(int); @@ -25,13 +24,13 @@ static struct /********************************************************************** - * INT_Int09Handler + * DOSVM_Int09Handler * * Handler for int 09h. */ -void WINAPI INT_Int09Handler( CONTEXT86 *context ) +void WINAPI DOSVM_Int09Handler( CONTEXT86 *context ) { - BYTE ascii, scan = INT_Int09ReadScan(&ascii); + BYTE ascii, scan = DOSVM_Int09ReadScan(&ascii); BYTE ch[2]; int cnt, c2; @@ -49,21 +48,21 @@ void WINAPI INT_Int09Handler( CONTEXT86 *context ) } if (cnt>0) { for (c2=0; c2 #include "module.h" -#include "callback.h" #include "dosexe.h" #include "wincon.h" #include "debugtools.h" @@ -18,10 +17,10 @@ #include "winuser.h" #include "miscemu.h" -DEFAULT_DEBUG_CHANNEL(int16); +DEFAULT_DEBUG_CHANNEL(int); /********************************************************************** - * INT_Int16Handler + * DOSVM_Int16Handler * * Handler for int 16h (keyboard) * @@ -31,15 +30,15 @@ DEFAULT_DEBUG_CHANNEL(int16); * not currently listed here. */ -void WINAPI INT_Int16Handler( CONTEXT86 *context ) +void WINAPI DOSVM_Int16Handler( CONTEXT86 *context ) { switch AH_reg(context) { case 0x00: /* Get Keystroke */ /* Returns: AH = Scan code - AL = ASCII character */ + AL = ASCII character */ TRACE("Get Keystroke\n"); - INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE); + DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE); break; case 0x01: /* Check for Keystroke */ @@ -47,7 +46,7 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context ) /* AH = Scan code */ /* AL = ASCII character */ TRACE("Check for Keystroke\n"); - if (!INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE)) + if (!DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE)) { SET_ZFLAG(context); } @@ -57,10 +56,9 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context ) } break; - case 0x02: /* Get Shift Flags */ + case 0x02: /* Get Shift Flags */ AL_reg(context) = 0; -#if 0 /* FIXME: cannot call USER functions here */ if (GetAsyncKeyState(VK_RSHIFT)) AL_reg(context) |= 0x01; if (GetAsyncKeyState(VK_LSHIFT)) @@ -77,7 +75,6 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context ) AL_reg(context) |= 0x40; if (GetAsyncKeyState(VK_INSERT)) AL_reg(context) |= 0x80; -#endif TRACE("Get Shift Flags: returning 0x%02x\n", AL_reg(context)); break; @@ -98,17 +95,17 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context ) case 0x10: /* Get Enhanced Keystroke */ TRACE("Get Enhanced Keystroke - Partially supported\n"); /* Returns: AH = Scan code - AL = ASCII character */ - INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE); + AL = ASCII character */ + DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE); break; - + case 0x11: /* Check for Enhanced Keystroke */ /* Returns: ZF set if no keystroke */ /* AH = Scan code */ /* AL = ASCII character */ TRACE("Check for Enhanced Keystroke - Partially supported\n"); - if (!INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE)) + if (!DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE)) { SET_ZFLAG(context); } @@ -121,15 +118,15 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context ) case 0x12: /* Get Extended Shift States */ FIXME("Get Extended Shift States - Not Supported\n"); break; - + default: - FIXME("Unknown INT 16 function - 0x%x\n", AH_reg(context)); + FIXME("Unknown INT 16 function - 0x%x\n", AH_reg(context)); break; } } -int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek) +int WINAPI DOSVM_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek) { BIOSDATA *data = DOSMEM_BiosData(); WORD CurOfs = data->NextKbdCharPtr; @@ -141,7 +138,7 @@ int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek) } else { while (CurOfs == data->FirstKbdCharPtr) { /* no input available yet, so wait... */ - Dosvm.Wait( -1, 0 ); + DOSVM_Wait( -1, 0 ); } } /* read from keyboard queue */ @@ -156,7 +153,7 @@ int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek) return 1; } -int WINAPI INT_Int16AddChar(BYTE ascii,BYTE scan) +int WINAPI DOSVM_Int16AddChar(BYTE ascii,BYTE scan) { BIOSDATA *data = DOSMEM_BiosData(); WORD CurOfs = data->FirstKbdCharPtr; diff --git a/msdos/int17.c b/dlls/winedos/int17.c similarity index 85% rename from msdos/int17.c rename to dlls/winedos/int17.c index 48c0212c8d8..5324e53a614 100644 --- a/msdos/int17.c +++ b/dlls/winedos/int17.c @@ -9,14 +9,14 @@ #include "msdos.h" #include "winnt.h" -DEFAULT_DEBUG_CHANNEL(int17); +DEFAULT_DEBUG_CHANNEL(int); /********************************************************************** - * INT_Int17Handler + * DOSVM_Int17Handler * * Handler for int 17h (printer - output character). */ -void WINAPI INT_Int17Handler( CONTEXT86 *context ) +void WINAPI DOSVM_Int17Handler( CONTEXT86 *context ) { switch( AH_reg(context) ) { diff --git a/msdos/int19.c b/dlls/winedos/int19.c similarity index 69% rename from msdos/int19.c rename to dlls/winedos/int19.c index 966afc49d2d..d92daab9a61 100644 --- a/msdos/int19.c +++ b/dlls/winedos/int19.c @@ -6,15 +6,15 @@ #include "miscemu.h" #include "debugtools.h" -DEFAULT_DEBUG_CHANNEL(int19); +DEFAULT_DEBUG_CHANNEL(int); /********************************************************************** - * INT_Int19Handler + * DOSVM_Int19Handler * * Handler for int 19h (Reboot). */ -void WINAPI INT_Int19Handler( CONTEXT86 *context ) +void WINAPI DOSVM_Int19Handler( CONTEXT86 *context ) { WARN("Attempted Reboot\n"); } diff --git a/dlls/winedos/int20.c b/dlls/winedos/int20.c new file mode 100644 index 00000000000..bb6cef3f0e8 --- /dev/null +++ b/dlls/winedos/int20.c @@ -0,0 +1,18 @@ +/* + * DOS interrupt 20h handler (TERMINATE PROGRAM) + */ + +#include +#include "winbase.h" +#include "dosexe.h" +#include "miscemu.h" + +/********************************************************************** + * DOSVM_Int20Handler + * + * Handler for int 20h. + */ +void WINAPI DOSVM_Int20Handler( CONTEXT86 *context ) +{ + MZ_Exit( context, TRUE, 0 ); +} diff --git a/dlls/winedos/int21.c b/dlls/winedos/int21.c new file mode 100644 index 00000000000..e0dfda473f5 --- /dev/null +++ b/dlls/winedos/int21.c @@ -0,0 +1,187 @@ +/* + * DOS interrupt 21h handler + */ + +#include "config.h" + +#include "windef.h" +#include "winbase.h" +#include "ntddk.h" +#include "wine/winbase16.h" +#include "dosexe.h" +#include "miscemu.h" +#include "msdos.h" +#include "console.h" +#include "debugtools.h" + +DEFAULT_DEBUG_CHANNEL(int21); + + +/*********************************************************************** + * DOSVM_Int21Handler + * + * int 21h real-mode handler. Most calls are passed directly to DOS3Call. + */ +void WINAPI DOSVM_Int21Handler( CONTEXT86 *context ) +{ + RESET_CFLAG(context); /* Not sure if this is a good idea */ + + switch(AH_reg(context)) + { + case 0x00: /* TERMINATE PROGRAM */ + TRACE("TERMINATE PROGRAM\n"); + MZ_Exit( context, FALSE, 0 ); + break; + + case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */ + TRACE("DIRECT CHARACTER INPUT WITH ECHO\n"); + AL_reg(context) = CONSOLE_GetCharacter(); + /* FIXME: no echo */ + break; + + case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */ + TRACE("Write Character to Standard Output\n"); + CONSOLE_Write(DL_reg(context), 0, 0, 0); + break; + + case 0x06: /* DIRECT CONSOLE IN/OUTPUT */ + /* FIXME: Use DOSDEV_Peek/Read/Write(DOSDEV_Console(),...) !! */ + if (DL_reg(context) == 0xff) { + static char scan = 0; + TRACE("Direct Console Input\n"); + if (scan) { + /* return pending scancode */ + AL_reg(context) = scan; + RESET_ZFLAG(context); + scan = 0; + } else { + char ascii; + if (DOSVM_Int16ReadChar(&ascii,&scan,TRUE)) { + DOSVM_Int16ReadChar(&ascii,&scan,FALSE); + /* return ASCII code */ + AL_reg(context) = ascii; + RESET_ZFLAG(context); + /* return scan code on next call only if ascii==0 */ + if (ascii) scan = 0; + } else { + /* nothing pending, clear everything */ + AL_reg(context) = 0; + SET_ZFLAG(context); + scan = 0; /* just in case */ + } + } + } else { + TRACE("Direct Console Output\n"); + CONSOLE_Write(DL_reg(context), 0, 0, 0); + } + break; + + case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */ + /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */ + TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n"); + DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE); + break; + + case 0x08: /* CHARACTER INPUT WITHOUT ECHO */ + /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */ + TRACE("CHARACTER INPUT WITHOUT ECHO\n"); + DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE); + break; + + case 0x0b: /* GET STDIN STATUS */ + { + char x1,x2; + + if (CONSOLE_CheckForKeystroke(&x1,&x2)) + AL_reg(context) = 0xff; + else + AL_reg(context) = 0; + } + break; + + case 0x25: /* SET INTERRUPT VECTOR */ + DOSVM_SetRMHandler( AL_reg(context), + (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context))); + break; + + case 0x35: /* GET INTERRUPT VECTOR */ + TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context)); + { + FARPROC16 addr = DOSVM_GetRMHandler( AL_reg(context) ); + context->SegEs = SELECTOROF(addr); + BX_reg(context) = OFFSETOF(addr); + } + break; + + case 0x44: /* IOCTL */ + switch (AL_reg(context)) + { + case 0x0b: /* SET SHARING RETRY COUNT */ + TRACE("IOCTL - SET SHARING RETRY COUNT pause %d retries %d\n", + CX_reg(context), DX_reg(context)); + if (!CX_reg(context)) + { + AX_reg(context) = 1; + SET_CFLAG(context); + break; + } + DOSMEM_LOL()->sharing_retry_delay = CX_reg(context); + if (!DX_reg(context)) + DOSMEM_LOL()->sharing_retry_count = DX_reg(context); + RESET_CFLAG(context); + break; + } + break; + + case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */ + TRACE("EXEC %s\n", (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx )); + if (!MZ_Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx), + AL_reg(context), CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx) )) + { + AX_reg(context) = GetLastError(); + SET_CFLAG(context); + } + break; + + case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */ + TRACE("EXIT with return code %d\n",AL_reg(context)); + MZ_Exit( context, FALSE, AL_reg(context) ); + break; + + case 0x4d: /* GET RETURN CODE */ + TRACE("GET RETURN CODE (ERRORLEVEL)\n"); + AX_reg(context) = DOSVM_retval; + DOSVM_retval = 0; + break; + + case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */ + TRACE("SET CURRENT PROCESS ID (SET PSP ADDRESS)\n"); + DOSVM_psp = BX_reg(context); + break; + + case 0x51: /* GET PSP ADDRESS */ + TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n"); + /* FIXME: should we return the original DOS PSP upon */ + /* Windows startup ? */ + BX_reg(context) = DOSVM_psp; + break; + + case 0x52: /* "SYSVARS" - GET LIST OF LISTS */ + TRACE("SYSVARS - GET LIST OF LISTS\n"); + { + context->SegEs = HIWORD(DOS_LOLSeg); + BX_reg(context) = FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB); + } + break; + + case 0x62: /* GET PSP ADDRESS */ + TRACE("GET CURRENT PSP ADDRESS\n"); + /* FIXME: should we return the original DOS PSP upon */ + /* Windows startup ? */ + BX_reg(context) = DOSVM_psp; + break; + + default: + DOS3Call( context ); + } +} diff --git a/msdos/int29.c b/dlls/winedos/int29.c similarity index 82% rename from msdos/int29.c rename to dlls/winedos/int29.c index 8ffaa56c802..65d20a2da37 100644 --- a/msdos/int29.c +++ b/dlls/winedos/int29.c @@ -10,11 +10,11 @@ #include "miscemu.h" /********************************************************************** - * INT_Int29Handler + * DOSVM_Int29Handler * * Handler for int 29h (fast console output) */ -void WINAPI INT_Int29Handler( CONTEXT86 *context ) +void WINAPI DOSVM_Int29Handler( CONTEXT86 *context ) { /* Yes, it seems that this is really all this interrupt does. */ CONSOLE_Write(AL_reg(context), 0, 0, 0); diff --git a/dlls/winedos/int31.c b/dlls/winedos/int31.c new file mode 100644 index 00000000000..3efc177354e --- /dev/null +++ b/dlls/winedos/int31.c @@ -0,0 +1,634 @@ +/* + * DPMI 0.9 emulation + * + * Copyright 1995 Alexandre Julliard + */ + +#include "config.h" + +#include "windef.h" +#include "wine/winbase16.h" +#include "miscemu.h" +#include "task.h" +#include "msdos.h" +#include "dosexe.h" + +#include "debugtools.h" + +DEFAULT_DEBUG_CHANNEL(int31); + +/* Structure for real-mode callbacks */ +typedef struct +{ + DWORD edi; + DWORD esi; + DWORD ebp; + DWORD reserved; + DWORD ebx; + DWORD edx; + DWORD ecx; + DWORD eax; + WORD fl; + WORD es; + WORD ds; + WORD fs; + WORD gs; + WORD ip; + WORD cs; + WORD sp; + WORD ss; +} REALMODECALL; + +typedef struct tagRMCB { + DWORD address; + DWORD proc_ofs,proc_sel; + DWORD regs_ofs,regs_sel; + struct tagRMCB *next; +} RMCB; + +static RMCB *FirstRMCB = NULL; +static WORD dpmi_flag; + +/********************************************************************** + * INT_GetRealModeContext + */ +static void INT_GetRealModeContext( REALMODECALL *call, CONTEXT86 *context ) +{ + context->Eax = call->eax; + context->Ebx = call->ebx; + context->Ecx = call->ecx; + context->Edx = call->edx; + context->Esi = call->esi; + context->Edi = call->edi; + context->Ebp = call->ebp; + context->EFlags = call->fl | V86_FLAG; + context->Eip = call->ip; + context->Esp = call->sp; + context->SegCs = call->cs; + context->SegDs = call->ds; + context->SegEs = call->es; + context->SegFs = call->fs; + context->SegGs = call->gs; + context->SegSs = call->ss; +} + + +/********************************************************************** + * INT_SetRealModeContext + */ +static void INT_SetRealModeContext( REALMODECALL *call, CONTEXT86 *context ) +{ + call->eax = context->Eax; + call->ebx = context->Ebx; + call->ecx = context->Ecx; + call->edx = context->Edx; + call->esi = context->Esi; + call->edi = context->Edi; + call->ebp = context->Ebp; + call->fl = LOWORD(context->EFlags); + call->ip = LOWORD(context->Eip); + call->sp = LOWORD(context->Esp); + call->cs = context->SegCs; + call->ds = context->SegDs; + call->es = context->SegEs; + call->fs = context->SegFs; + call->gs = context->SegGs; + call->ss = context->SegSs; +} + + +#ifdef __i386__ + +void DPMI_CallRMCB32(RMCB *rmcb, UINT16 ss, DWORD esp, UINT16*es, DWORD*edi) +#if 0 /* original code, which early gccs puke on */ +{ + int _clobber; + __asm__ __volatile__( + "pushl %%ebp\n" + "pushl %%ebx\n" + "pushl %%es\n" + "pushl %%ds\n" + "pushfl\n" + "mov %7,%%es\n" + "mov %5,%%ds\n" + ".byte 0x36, 0xff, 0x18\n" /* lcall *%ss:(%eax) */ + "popl %%ds\n" + "mov %%es,%0\n" + "popl %%es\n" + "popl %%ebx\n" + "popl %%ebp\n" + : "=d" (*es), "=D" (*edi), "=S" (_clobber), "=a" (_clobber), "=c" (_clobber) + : "0" (ss), "2" (esp), + "4" (rmcb->regs_sel), "1" (rmcb->regs_ofs), + "3" (&rmcb->proc_ofs) ); +} +#else /* code generated by a gcc new enough */ +; +__ASM_GLOBAL_FUNC(DPMI_CallRMCB32, + "pushl %ebp\n\t" + "movl %esp,%ebp\n\t" + "pushl %edi\n\t" + "pushl %esi\n\t" + "movl 0x8(%ebp),%eax\n\t" + "movl 0x10(%ebp),%esi\n\t" + "movl 0xc(%ebp),%edx\n\t" + "movl 0x10(%eax),%ecx\n\t" + "movl 0xc(%eax),%edi\n\t" + "addl $0x4,%eax\n\t" + "pushl %ebp\n\t" + "pushl %ebx\n\t" + "pushl %es\n\t" + "pushl %ds\n\t" + "pushfl\n\t" + "mov %cx,%es\n\t" + "mov %dx,%ds\n\t" + ".byte 0x36, 0xff, 0x18\n\t" /* lcall *%ss:(%eax) */ + "popl %ds\n\t" + "mov %es,%dx\n\t" + "popl %es\n\t" + "popl %ebx\n\t" + "popl %ebp\n\t" + "movl 0x14(%ebp),%eax\n\t" + "movw %dx,(%eax)\n\t" + "movl 0x18(%ebp),%edx\n\t" + "movl %edi,(%edx)\n\t" + "popl %esi\n\t" + "popl %edi\n\t" + "leave\n\t" + "ret") +#endif + +#endif /* __i386__ */ + +/********************************************************************** + * DPMI_CallRMCBProc + * + * This routine does the hard work of calling a callback procedure. + */ +static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag ) +{ + if (IS_SELECTOR_SYSTEM( rmcb->proc_sel )) { + /* Wine-internal RMCB, call directly */ + ((RMCBPROC)rmcb->proc_ofs)(context); + } else { +#ifdef __i386__ + UINT16 ss,es; + DWORD esp,edi; + + INT_SetRealModeContext(MapSL(MAKESEGPTR( rmcb->regs_sel, rmcb->regs_ofs )), context); + ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, WINE_LDT_FLAGS_DATA ); + esp = context->Esp; + + FIXME("untested!\n"); + + /* The called proc ends with an IRET, and takes these parameters: + * DS:ESI = pointer to real-mode SS:SP + * ES:EDI = pointer to real-mode call structure + * It returns: + * ES:EDI = pointer to real-mode call structure (may be a copy) + * It is the proc's responsibility to change the return CS:IP in the + * real-mode call structure. */ + if (flag & 1) { + /* 32-bit DPMI client */ + DPMI_CallRMCB32(rmcb, ss, esp, &es, &edi); + } else { + /* 16-bit DPMI client */ + CONTEXT86 ctx = *context; + ctx.SegCs = rmcb->proc_sel; + ctx.Eip = rmcb->proc_ofs; + ctx.SegDs = ss; + ctx.Esi = esp; + ctx.SegEs = rmcb->regs_sel; + ctx.Edi = rmcb->regs_ofs; + /* FIXME: I'm pretty sure this isn't right - should push flags first */ + wine_call_to_16_regs_short(&ctx, 0); + es = ctx.SegEs; + edi = ctx.Edi; + } + FreeSelector16(ss); + INT_GetRealModeContext( MapSL( MAKESEGPTR( es, edi )), context); +#else + ERR("RMCBs only implemented for i386\n"); +#endif + } +} + + +/********************************************************************** + * DPMI_CallRMProc + * + * This routine does the hard work of calling a real mode procedure. + */ +int DPMI_CallRMProc( CONTEXT86 *context, LPWORD stack, int args, int iret ) +{ + LPWORD stack16; + LPVOID addr = NULL; /* avoid gcc warning */ + RMCB *CurrRMCB; + int alloc = 0, already = 0; + BYTE *code; + + TRACE("EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n", + context->Eax, context->Ebx, context->Ecx, context->Edx ); + TRACE("ESI=%08lx EDI=%08lx ES=%04lx DS=%04lx CS:IP=%04lx:%04x, %d WORD arguments, %s\n", + context->Esi, context->Edi, context->SegEs, context->SegDs, + context->SegCs, LOWORD(context->Eip), args, iret?"IRET":"FAR" ); + +callrmproc_again: + +/* there might be some code that just jumps to RMCBs or the like, + in which case following the jumps here might get us to a shortcut */ + code = CTX_SEG_OFF_TO_LIN(context, context->SegCs, context->Eip); + switch (*code) { + case 0xe9: /* JMP NEAR */ + context->Eip += 3 + *(WORD *)(code+1); + /* yeah, I know these gotos don't look good... */ + goto callrmproc_again; + case 0xea: /* JMP FAR */ + context->Eip = *(WORD *)(code+1); + context->SegCs = *(WORD *)(code+3); + /* ...but since the label is there anyway... */ + goto callrmproc_again; + case 0xeb: /* JMP SHORT */ + context->Eip += 2 + *(signed char *)(code+1); + /* ...because of other gotos below, so... */ + goto callrmproc_again; + } + +/* shortcut for chaining to internal interrupt handlers */ + if ((context->SegCs == 0xF000) && iret) + { + DOSVM_RealModeInterrupt( LOWORD(context->Eip)/4, context); + return 0; + } + +/* shortcut for RMCBs */ + CurrRMCB = FirstRMCB; + + while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs)) + CurrRMCB = CurrRMCB->next; + + if (!CurrRMCB && !MZ_Current()) + { + FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n"); + TRACE("creating VM86 task\n"); + MZ_AllocDPMITask(); + } + if (!already) { + if (!context->SegSs) { + alloc = 1; /* allocate default stack */ + stack16 = addr = DOSMEM_GetBlock( 64, (UINT16 *)&(context->SegSs) ); + context->Esp = 64-2; + stack16 += 32-1; + if (!addr) { + ERR("could not allocate default stack\n"); + return 1; + } + } else { + stack16 = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); + } + context->Esp -= (args + (iret?1:0)) * sizeof(WORD); + stack16 -= args; + if (args) memcpy(stack16, stack, args*sizeof(WORD) ); + /* push flags if iret */ + if (iret) { + stack16--; args++; + *stack16 = LOWORD(context->EFlags); + } + /* push return address (return to interrupt wrapper) */ + *(--stack16) = DOSMEM_wrap_seg; + *(--stack16) = 0; + /* adjust stack */ + context->Esp -= 2*sizeof(WORD); + already = 1; + } + + if (CurrRMCB) { + /* RMCB call, invoke protected-mode handler directly */ + DPMI_CallRMCBProc(context, CurrRMCB, dpmi_flag); + /* check if we returned to where we thought we would */ + if ((context->SegCs != DOSMEM_wrap_seg) || + (LOWORD(context->Eip) != 0)) { + /* we need to continue at different address in real-mode space, + so we need to set it all up for real mode again */ + goto callrmproc_again; + } + } else { + TRACE("entering real mode...\n"); + DOSVM_Enter( context ); + TRACE("returned from real-mode call\n"); + } + if (alloc) DOSMEM_FreeBlock( addr ); + return 0; +} + + +/********************************************************************** + * DOSVM_CallRMInt (WINEDOS.@) + */ +void WINAPI DOSVM_CallRMInt( CONTEXT86 *context ) +{ + CONTEXT86 realmode_ctx; + FARPROC16 rm_int = DOSVM_GetRMHandler( BL_reg(context) ); + REALMODECALL *call = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) )); + INT_GetRealModeContext( call, &realmode_ctx ); + + /* we need to check if a real-mode program has hooked the interrupt */ + if (HIWORD(rm_int)!=0xF000) { + /* yup, which means we need to switch to real mode... */ + realmode_ctx.SegCs = HIWORD(rm_int); + realmode_ctx.Eip = LOWORD(rm_int); + if (DPMI_CallRMProc( &realmode_ctx, NULL, 0, TRUE)) + SET_CFLAG(context); + } else { + RESET_CFLAG(context); + /* use the IP we have instead of BL_reg, in case some apps + decide to move interrupts around for whatever reason... */ + DOSVM_RealModeInterrupt( LOWORD(rm_int)/4, &realmode_ctx ); + } + INT_SetRealModeContext( call, &realmode_ctx ); +} + + +/********************************************************************** + * DOSVM_CallRMProc (WINEDOS.@) + */ +void WINAPI DOSVM_CallRMProc( CONTEXT86 *context, int iret ) +{ + REALMODECALL *p = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) )); + CONTEXT86 context16; + + TRACE("RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n", + p->eax, p->ebx, p->ecx, p->edx); + TRACE(" ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments, %s\n", + p->esi, p->edi, p->es, p->ds, p->cs, p->ip, CX_reg(context), iret?"IRET":"FAR" ); + + if (!(p->cs) && !(p->ip)) { /* remove this check + if Int21/6501 case map function + has been implemented */ + SET_CFLAG(context); + return; + } + INT_GetRealModeContext(p, &context16); + DPMI_CallRMProc( &context16, ((LPWORD)MapSL(MAKESEGPTR(context->SegSs, LOWORD(context->Esp))))+3, + CX_reg(context), iret ); + INT_SetRealModeContext(p, &context16); +} + + +/* (see dosmem.c, function DOSMEM_InitDPMI) */ +static void StartPM( CONTEXT86 *context ) +{ + UINT16 cs, ss, ds, es; + CONTEXT86 pm_ctx; + DWORD psp_ofs = (DWORD)(DOSVM_psp<<4); + PDB16 *psp = (PDB16 *)psp_ofs; + HANDLE16 env_seg = psp->environment; + unsigned char selflags = WINE_LDT_FLAGS_DATA; + + RESET_CFLAG(context); + dpmi_flag = AX_reg(context); +/* our mode switch wrapper have placed the desired CS into DX */ + cs = SELECTOR_AllocBlock( (void *)(DX_reg(context)<<4), 0x10000, WINE_LDT_FLAGS_CODE ); +/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they + can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a + ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing + 32-bit code using this stack. */ + if (dpmi_flag & 1) selflags |= WINE_LDT_FLAGS_32BIT; + ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, selflags ); +/* do the same for the data segments, just in case */ + if (context->SegDs == context->SegSs) ds = ss; + else ds = SELECTOR_AllocBlock( (void *)(context->SegDs<<4), 0x10000, selflags ); + es = SELECTOR_AllocBlock( psp, 0x100, selflags ); +/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */ + psp->environment = SELECTOR_AllocBlock( (void *)(env_seg<<4), 0x10000, WINE_LDT_FLAGS_DATA ); + + pm_ctx = *context; + pm_ctx.SegCs = DOSMEM_dpmi_sel; +/* our mode switch wrapper expects the new CS in DX, and the new SS in AX */ + pm_ctx.Eax = ss; + pm_ctx.Edx = cs; + pm_ctx.SegDs = ds; + pm_ctx.SegEs = es; + pm_ctx.SegFs = 0; + pm_ctx.SegGs = 0; + + TRACE("DOS program is now entering protected mode\n"); + wine_call_to_16_regs_short(&pm_ctx, 0); + + /* in the current state of affairs, we won't ever actually return here... */ + /* we should have int21/ah=4c do it someday, though... */ + + FreeSelector16(psp->environment); + psp->environment = env_seg; + FreeSelector16(es); + if (ds != ss) FreeSelector16(ds); + FreeSelector16(ss); + FreeSelector16(cs); +} + +static RMCB *DPMI_AllocRMCB( void ) +{ + RMCB *NewRMCB = HeapAlloc(GetProcessHeap(), 0, sizeof(RMCB)); + UINT16 uParagraph; + + if (NewRMCB) + { + LPVOID RMCBmem = DOSMEM_GetBlock(4, &uParagraph); + LPBYTE p = RMCBmem; + + *p++ = 0xcd; /* RMCB: */ + *p++ = 0x31; /* int $0x31 */ +/* it is the called procedure's task to change the return CS:EIP + the DPMI 0.9 spec states that if it doesn't, it will be called again */ + *p++ = 0xeb; + *p++ = 0xfc; /* jmp RMCB */ + NewRMCB->address = MAKELONG(0, uParagraph); + NewRMCB->next = FirstRMCB; + FirstRMCB = NewRMCB; + } + return NewRMCB; +} + + +FARPROC16 WINAPI DPMI_AllocInternalRMCB( RMCBPROC proc ) +{ + RMCB *NewRMCB = DPMI_AllocRMCB(); + + if (NewRMCB) { + NewRMCB->proc_ofs = (DWORD)proc; + NewRMCB->proc_sel = 0; + NewRMCB->regs_ofs = 0; + NewRMCB->regs_sel = 0; + return (FARPROC16)(NewRMCB->address); + } + return NULL; +} + + +static int DPMI_FreeRMCB( DWORD address ) +{ + RMCB *CurrRMCB = FirstRMCB; + RMCB *PrevRMCB = NULL; + + while (CurrRMCB && (CurrRMCB->address != address)) + { + PrevRMCB = CurrRMCB; + CurrRMCB = CurrRMCB->next; + } + if (CurrRMCB) + { + if (PrevRMCB) + PrevRMCB->next = CurrRMCB->next; + else + FirstRMCB = CurrRMCB->next; + DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(CurrRMCB->address)); + HeapFree(GetProcessHeap(), 0, CurrRMCB); + return 0; + } + return 1; +} + + +void WINAPI DPMI_FreeInternalRMCB( FARPROC16 proc ) +{ + DPMI_FreeRMCB( (DWORD)proc ); +} + + +/* DPMI Raw Mode Switch handler */ + +#if 0 +void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context ) +{ + LPDOSTASK lpDosTask = MZ_Current(); + CONTEXT86 rm_ctx; + int ret; + + if (!lpDosTask) { + /* we could probably start a DPMI-only dosmod task here, but I doubt + anything other than real DOS apps want to call raw mode switch */ + ERR("attempting raw mode switch without DOS task!\n"); + ExitProcess(1); + } + /* initialize real-mode context as per spec */ + memset(&rm_ctx, 0, sizeof(rm_ctx)); + rm_ctx.SegDs = AX_sig(context); + rm_ctx.SegEs = CX_sig(context); + rm_ctx.SegSs = DX_sig(context); + rm_ctx.Esp = EBX_sig(context); + rm_ctx.SegCs = SI_sig(context); + rm_ctx.Eip = EDI_sig(context); + rm_ctx.Ebp = EBP_sig(context); + rm_ctx.SegFs = 0; + rm_ctx.SegGs = 0; + rm_ctx.EFlags = EFL_sig(context); /* at least we need the IF flag */ + + /* enter real mode again */ + TRACE("re-entering real mode at %04lx:%04lx\n",rm_ctx.SegCs,rm_ctx.Eip); + ret = DOSVM_Enter( &rm_ctx ); + /* when the real-mode stuff call its mode switch address, + DOSVM_Enter will return and we will continue here */ + + if (ret<0) { + /* if the sync was lost, there's no way to recover */ + ExitProcess(1); + } + + /* alter protected-mode context as per spec */ + DS_sig(context) = LOWORD(rm_ctx.Eax); + ES_sig(context) = LOWORD(rm_ctx.Ecx); + SS_sig(context) = LOWORD(rm_ctx.Edx); + ESP_sig(context) = rm_ctx.Ebx; + CS_sig(context) = LOWORD(rm_ctx.Esi); + EIP_sig(context) = rm_ctx.Edi; + EBP_sig(context) = rm_ctx.Ebp; + FS_sig(context) = 0; + GS_sig(context) = 0; + + /* Return to new address and hope that we didn't mess up */ + TRACE("re-entering protected mode at %04x:%08lx\n", + CS_sig(context), EIP_sig(context)); +} +#endif + + +/********************************************************************** + * DOSVM_AllocRMCB (WINEDOS.@) + */ +void WINAPI DOSVM_AllocRMCB( CONTEXT86 *context ) +{ + RMCB *NewRMCB = DPMI_AllocRMCB(); + + TRACE("Function to call: %04x:%04x\n", (WORD)context->SegDs, SI_reg(context) ); + + if (NewRMCB) + { + /* FIXME: if 32-bit DPMI client, use ESI and EDI */ + NewRMCB->proc_ofs = LOWORD(context->Esi); + NewRMCB->proc_sel = context->SegDs; + NewRMCB->regs_ofs = LOWORD(context->Edi); + NewRMCB->regs_sel = context->SegEs; + SET_LOWORD( context->Ecx, HIWORD(NewRMCB->address) ); + SET_LOWORD( context->Edx, LOWORD(NewRMCB->address) ); + } + else + { + SET_LOWORD( context->Eax, 0x8015 ); /* callback unavailable */ + SET_CFLAG(context); + } +} + + +/********************************************************************** + * DOSVM_FreeRMCB (WINEDOS.@) + */ +void WINAPI DOSVM_FreeRMCB( CONTEXT86 *context ) +{ + FIXME("callback address: %04x:%04x\n", + CX_reg(context), DX_reg(context)); + + if (DPMI_FreeRMCB(MAKELONG(DX_reg(context), CX_reg(context)))) { + SET_LOWORD( context->Eax, 0x8024 ); /* invalid callback address */ + SET_CFLAG(context); + } +} + + +/********************************************************************** + * DOSVM_Int31Handler + * + * Handler for real-mode int 31h (DPMI). + */ +void WINAPI DOSVM_Int31Handler( CONTEXT86 *context ) +{ + /* check if it's our wrapper */ + TRACE("called from real mode\n"); + if (context->SegCs==DOSMEM_dpmi_seg) { + /* This is the protected mode switch */ + StartPM(context); + return; + } + else if (context->SegCs==DOSMEM_xms_seg) + { + /* This is the XMS driver entry point */ + XMS_Handler(context); + return; + } + else + { + /* Check for RMCB */ + RMCB *CurrRMCB = FirstRMCB; + + while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs)) + CurrRMCB = CurrRMCB->next; + + if (CurrRMCB) { + /* RMCB call, propagate to protected-mode handler */ + DPMI_CallRMCBProc(context, CurrRMCB, dpmi_flag); + return; + } + } + + /* chain to protected mode handler */ + INT_Int31Handler( context ); +} diff --git a/msdos/int33.c b/dlls/winedos/int33.c similarity index 93% rename from msdos/int33.c rename to dlls/winedos/int33.c index 944db4d7d23..9693d734e00 100644 --- a/msdos/int33.c +++ b/dlls/winedos/int33.c @@ -10,7 +10,6 @@ #include "wingdi.h" #include "winuser.h" #include "miscemu.h" -#include "callback.h" #include "dosexe.h" #include "vga.h" #include "debugtools.h" @@ -25,11 +24,11 @@ static struct } mouse_info; /********************************************************************** - * INT_Int33Handler + * DOSVM_Int33Handler * * Handler for int 33h (MS MOUSE). */ -void WINAPI INT_Int33Handler( CONTEXT86 *context ) +void WINAPI DOSVM_Int33Handler( CONTEXT86 *context ) { switch (LOWORD(context->Eax)) { case 0x00: @@ -100,7 +99,7 @@ static void MouseRelay(CONTEXT86 *context,void *mdata) DPMI_CallRMProc(&ctx, NULL, 0, 0); } -void WINAPI INT_Int33Message(UINT message,WPARAM wParam,LPARAM lParam) +void WINAPI DOSVM_Int33Message(UINT message,WPARAM wParam,LPARAM lParam) { WORD mask = 0; unsigned Height, Width, SX=1, SY=1; @@ -152,6 +151,6 @@ void WINAPI INT_Int33Message(UINT message,WPARAM wParam,LPARAM lParam) data->but = mouse_info.but; data->x = mouse_info.x; data->y = mouse_info.y; - Dosvm.QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data); + DOSVM_QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data); } } diff --git a/dlls/winedos/ioports.c b/dlls/winedos/ioports.c new file mode 100644 index 00000000000..b63e1addd8e --- /dev/null +++ b/dlls/winedos/ioports.c @@ -0,0 +1,54 @@ +/* + * Emulation of processor ioports. + * + * Copyright 1995 Morten Welinder + * Copyright 1998 Andreas Mohr, Ove Kaaven + */ + +#include "config.h" + +#include "windef.h" +#include "dosexe.h" +#include "vga.h" + + +/********************************************************************** + * DOSVM_inport + */ +BOOL WINAPI DOSVM_inport( int port, int size, DWORD *res ) +{ + switch (port) + { + case 0x60: + *res = DOSVM_Int09ReadScan(NULL); + break; + case 0x3ba: + case 0x3da: + *res = (DWORD)VGA_ioport_in( port ); + break; + default: + return FALSE; /* not handled */ + } + return TRUE; /* handled */ +} + + +/********************************************************************** + * DOSVM_outport + */ +BOOL WINAPI DOSVM_outport( int port, int size, DWORD value ) +{ + switch (port) + { + case 0x20: + DOSVM_PIC_ioport_out( port, (BYTE)value ); + break; + case 0x3c8: + case 0x3c9: + VGA_ioport_out( port, (BYTE)value ); + break; + default: + return FALSE; /* not handled */ + } + return TRUE; /* handled */ +} diff --git a/dlls/winedos/module.c b/dlls/winedos/module.c index 70c7154a524..a01118c60aa 100644 --- a/dlls/winedos/module.c +++ b/dlls/winedos/module.c @@ -33,8 +33,6 @@ DEFAULT_DEBUG_CHANNEL(module); -static LPDOSTASK dos_current; - #ifdef MZ_SUPPORTED #ifdef HAVE_SYS_MMAN_H @@ -74,7 +72,7 @@ typedef struct { static WORD init_cs,init_ip,init_ss,init_sp; static char mm_name[128]; -int read_pipe, write_pipe; +int read_pipe = -1, write_pipe = -1; HANDLE hReadPipe, hWritePipe; pid_t dosmod_pid; @@ -90,9 +88,9 @@ static void MZ_CreatePSP( LPVOID lpPSP, WORD env, WORD par ) /* some programs use this to calculate how much memory they need */ psp->nextParagraph=0x9FFF; /* FIXME: use a real value */ /* FIXME: dispatcher */ - psp->savedint22 = INT_GetRMHandler(0x22); - psp->savedint23 = INT_GetRMHandler(0x23); - psp->savedint24 = INT_GetRMHandler(0x24); + psp->savedint22 = DOSVM_GetRMHandler(0x22); + psp->savedint23 = DOSVM_GetRMHandler(0x23); + psp->savedint24 = DOSVM_GetRMHandler(0x24); psp->parentPSP=par; psp->environment=env; /* FIXME: more PSP stuff */ @@ -175,10 +173,6 @@ static BOOL MZ_InitMemory(void) int mm_fd; void *img_base; - /* initialize the memory */ - TRACE("Initializing DOS memory structures\n"); - DOSMEM_Init(TRUE); - /* allocate 1MB+64K shared memory */ tmpnam(mm_name); /* strcpy(mm_name,"/tmp/mydosimage"); */ @@ -201,7 +195,6 @@ static BOOL MZ_InitMemory(void) static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk ) { - LPDOSTASK lpDosTask = dos_current; IMAGE_DOS_HEADER mz_header; DWORD image_start,image_size,min_size,max_size,avail; BYTE*psp_start,*load_start,*oldenv; @@ -210,17 +203,15 @@ static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk ) WORD env_seg, load_seg, rel_seg, oldpsp_seg; DWORD len; - if (lpDosTask) { + if (DOSVM_psp) { /* DOS process already running, inherit from it */ - PDB16* par_psp = (PDB16*)((DWORD)lpDosTask->psp_seg << 4); + PDB16* par_psp = (PDB16*)((DWORD)DOSVM_psp << 4); alloc=0; oldenv = (LPBYTE)((DWORD)par_psp->environment << 4); - oldpsp_seg = lpDosTask->psp_seg; + oldpsp_seg = DOSVM_psp; } else { /* allocate new DOS process, inheriting from Wine environment */ alloc=1; - lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK)); - dos_current = lpDosTask; oldenv = GetEnvironmentStringsA(); oldpsp_seg = 0; } @@ -272,13 +263,13 @@ static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk ) goto load_error; } if (avail>max_size) avail=max_size; - psp_start=DOSMEM_GetBlock(avail,&lpDosTask->psp_seg); + psp_start=DOSMEM_GetBlock(avail,&DOSVM_psp); if (!psp_start) { ERR("error allocating DOS memory\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto load_error; } - load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE); + load_seg=DOSVM_psp+(old_com?0:PSP_SIZE); rel_seg=load_seg; load_start=psp_start+(PSP_SIZE<<4); MZ_CreatePSP(psp_start, env_seg, oldpsp_seg); @@ -324,9 +315,8 @@ static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk ) return TRUE; load_error: - lpDosTask->psp_seg = oldpsp_seg; + DOSVM_psp = oldpsp_seg; if (alloc) { - dos_current = NULL; if (mm_name[0]!=0) unlink(mm_name); } @@ -342,7 +332,7 @@ void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile ) } /*********************************************************************** - * Exec (WINEDOS.@) + * MZ_Exec */ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk ) { @@ -350,7 +340,6 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para * (i.e. one DOS app spawning another) */ /* FIXME: do we want to check binary type first, to check * whether it's a NE/PE executable? */ - LPDOSTASK lpDosTask = MZ_Current(); HFILE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); BOOL ret = FALSE; @@ -360,19 +349,19 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para case 1: /* load but don't execute */ { /* save current process's return SS:SP now */ - LPBYTE psp_start = (LPBYTE)((DWORD)lpDosTask->psp_seg << 4); + LPBYTE psp_start = (LPBYTE)((DWORD)DOSVM_psp << 4); PDB16 *psp = (PDB16 *)psp_start; psp->saveStack = (DWORD)MAKESEGPTR(context->SegSs, LOWORD(context->Esp)); } ret = MZ_DoLoadImage( hFile, filename, NULL ); if (ret) { - /* MZ_LoadImage created a new PSP and loaded new values into lpDosTask, + /* MZ_LoadImage created a new PSP and loaded new values into it, * let's work on the new values now */ - LPBYTE psp_start = (LPBYTE)((DWORD)lpDosTask->psp_seg << 4); + LPBYTE psp_start = (LPBYTE)((DWORD)DOSVM_psp << 4); ExecBlock *blk = (ExecBlock *)paramblk; MZ_FillPSP(psp_start, DOSMEM_MapRealToLinear(blk->cmdline)); /* the lame MS-DOS engineers decided that the return address should be in int22 */ - INT_SetRMHandler(0x22, (FARPROC16)MAKESEGPTR(context->SegCs, LOWORD(context->Eip))); + DOSVM_SetRMHandler(0x22, (FARPROC16)MAKESEGPTR(context->SegCs, LOWORD(context->Eip))); if (func) { /* don't execute, just return startup state */ blk->init_cs = init_cs; @@ -385,8 +374,8 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para context->Eip = init_ip; context->SegSs = init_ss; context->Esp = init_sp; - context->SegDs = lpDosTask->psp_seg; - context->SegEs = lpDosTask->psp_seg; + context->SegDs = DOSVM_psp; + context->SegEs = DOSVM_psp; context->Eax = 0; } } @@ -407,22 +396,16 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para } /*********************************************************************** - * LoadDPMI (WINEDOS.@) + * MZ_AllocDPMITask */ -LPDOSTASK WINAPI MZ_AllocDPMITask( void ) +void WINAPI MZ_AllocDPMITask( void ) { - LPDOSTASK lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK)); - - if (lpDosTask) { - dos_current = lpDosTask; MZ_InitMemory(); MZ_InitTask(); - } - return lpDosTask; } /*********************************************************************** - * RunInThread (WINEDOS.@) + * MZ_RunInThread */ void WINAPI MZ_RunInThread( PAPCFUNC proc, ULONG_PTR arg ) { @@ -536,10 +519,9 @@ static BOOL MZ_InitTask(void) static void MZ_Launch(void) { - LPDOSTASK lpDosTask = MZ_Current(); CONTEXT context; - TDB *pTask = TASK_GetCurrent(); - BYTE *psp_start = PTR_REAL_TO_LIN( lpDosTask->psp_seg, 0 ); + TDB *pTask = GlobalLock16( GetCurrentTask() ); + BYTE *psp_start = PTR_REAL_TO_LIN( DOSVM_psp, 0 ); MZ_FillPSP(psp_start, GetCommandLineA()); pTask->flags |= TDBF_WINOLDAP; @@ -549,8 +531,8 @@ static void MZ_Launch(void) context.Eip = init_ip; context.SegSs = init_ss; context.Esp = init_sp; - context.SegDs = lpDosTask->psp_seg; - context.SegEs = lpDosTask->psp_seg; + context.SegDs = DOSVM_psp; + context.SegEs = DOSVM_psp; context.EFlags = 0x00080000; /* virtual interrupt flag */ _LeaveWin16Lock(); DOSVM_Enter( &context ); @@ -564,34 +546,33 @@ static void MZ_KillTask(void) } /*********************************************************************** - * Exit (WINEDOS.@) + * MZ_Exit */ void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval ) { - LPDOSTASK lpDosTask = MZ_Current(); - if (lpDosTask) { - WORD psp_seg = cs_psp ? context->SegCs : lpDosTask->psp_seg; + if (DOSVM_psp) { + WORD psp_seg = cs_psp ? context->SegCs : DOSVM_psp; LPBYTE psp_start = (LPBYTE)((DWORD)psp_seg << 4); PDB16 *psp = (PDB16 *)psp_start; WORD parpsp = psp->parentPSP; /* check for parent DOS process */ if (parpsp) { /* retrieve parent's return address */ - FARPROC16 retaddr = INT_GetRMHandler(0x22); + FARPROC16 retaddr = DOSVM_GetRMHandler(0x22); /* restore interrupts */ - INT_SetRMHandler(0x22, psp->savedint22); - INT_SetRMHandler(0x23, psp->savedint23); - INT_SetRMHandler(0x24, psp->savedint24); + DOSVM_SetRMHandler(0x22, psp->savedint22); + DOSVM_SetRMHandler(0x23, psp->savedint23); + DOSVM_SetRMHandler(0x24, psp->savedint24); /* FIXME: deallocate file handles etc */ /* free process's associated memory * FIXME: walk memory and deallocate all blocks owned by process */ DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,psp->environment))); - DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,lpDosTask->psp_seg))); + DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,DOSVM_psp))); /* switch to parent's PSP */ - lpDosTask->psp_seg = parpsp; + DOSVM_psp = parpsp; psp_start = (LPBYTE)((DWORD)parpsp << 4); psp = (PDB16 *)psp_start; /* now return to parent */ - lpDosTask->retval = retval; + DOSVM_retval = retval; context->SegCs = SELECTOROF(retaddr); context->Eip = OFFSETOF(retaddr); context->SegSs = SELECTOROF(psp->saveStack); @@ -615,7 +596,7 @@ void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile ) } /*********************************************************************** - * Exec (WINEDOS.@) + * MZ_Exec */ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk ) { @@ -625,16 +606,16 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para } /*********************************************************************** - * LoadDPMI (WINEDOS.@) + * MZ_AllocDPMITask */ -LPDOSTASK WINAPI MZ_AllocDPMITask( void ) +void WINAPI MZ_AllocDPMITask( void ) { ERR("Actual real-mode calls not supported on this platform!\n"); return NULL; } /*********************************************************************** - * Exit (WINEDOS.@) + * MZ_Exit */ void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval ) { @@ -644,9 +625,9 @@ void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval ) #endif /* !MZ_SUPPORTED */ /*********************************************************************** - * GetCurrent (WINEDOS.@) + * MZ_Current */ -LPDOSTASK WINAPI MZ_Current( void ) +BOOL WINAPI MZ_Current( void ) { - return dos_current; + return (write_pipe != -1); /* FIXME: do a better check */ } diff --git a/msdos/vga.c b/dlls/winedos/vga.c similarity index 90% rename from msdos/vga.c rename to dlls/winedos/vga.c index 8175fa138cb..dc682a3d021 100644 --- a/msdos/vga.c +++ b/dlls/winedos/vga.c @@ -11,7 +11,7 @@ #include "winuser.h" #include "wincon.h" #include "miscemu.h" -#include "callback.h" +#include "dosexe.h" #include "vga.h" #include "ddraw.h" #include "services.h" @@ -29,9 +29,6 @@ static HANDLE poll_timer; typedef HRESULT WINAPI (*DirectDrawCreateProc)(LPGUID,LPDIRECTDRAW *,LPUNKNOWN); static DirectDrawCreateProc pDirectDrawCreate; -typedef HWND WINAPI (*CreateWindowExAProc)(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT, INT,INT,HWND,HMENU,HINSTANCE,LPVOID); -static CreateWindowExAProc pCreateWindowExA; - static PALETTEENTRY vga_def_palette[256]={ /* red green blue */ {0x00, 0x00, 0x00}, /* 0 - Black */ @@ -105,25 +102,12 @@ static void WINAPI VGA_DoSetMode(ULONG_PTR arg) return; } } - if (!pCreateWindowExA) - { - HMODULE hmod = LoadLibraryA( "user32.dll" ); - if (!hmod) { - ERR("Can't load user32.dll.\n"); - return; - } - if (hmod) pCreateWindowExA = (CreateWindowExAProc)GetProcAddress( hmod, "CreateWindowExA" ); - if (!pCreateWindowExA) { - ERR("Can't lookup CreateWindowExA from user32.dll.\n"); - return; - } - } res = pDirectDrawCreate(NULL,&lpddraw,NULL); if (!lpddraw) { ERR("DirectDraw is not available (res = %lx)\n",res); return; } - hwnd = pCreateWindowExA(0,"STATIC","WINEDOS VGA",WS_POPUP|WS_BORDER|WS_CAPTION|WS_SYSMENU,0,0,par->Xres,par->Yres,0,0,0,NULL); + hwnd = CreateWindowExA(0,"STATIC","WINEDOS VGA",WS_POPUP|WS_BORDER|WS_CAPTION|WS_SYSMENU,0,0,par->Xres,par->Yres,0,0,0,NULL); if (!hwnd) { ERR("Failed to create user window.\n"); } @@ -174,8 +158,7 @@ int VGA_SetMode(unsigned Xres,unsigned Yres,unsigned Depth) par.Xres = Xres; par.Yres = Yres; par.Depth = Depth; - if (Dosvm.RunInThread) Dosvm.RunInThread(VGA_DoSetMode, (ULONG_PTR)&par); - else VGA_DoSetMode((ULONG_PTR)&par); + MZ_RunInThread(VGA_DoSetMode, (ULONG_PTR)&par); return par.ret; } @@ -203,10 +186,7 @@ static void WINAPI VGA_DoExit(ULONG_PTR arg) void VGA_Exit(void) { - if (lpddraw) { - if (Dosvm.RunInThread) Dosvm.RunInThread(VGA_DoExit, 0); - else VGA_DoExit(0); - } + if (lpddraw) MZ_RunInThread(VGA_DoExit, 0); } void VGA_SetPalette(PALETTEENTRY*pal,int start,int len) @@ -352,8 +332,7 @@ void CALLBACK VGA_Poll( ULONG_PTR arg ) ch[X].Attributes = *dat++; } dest.Left=0; dest.Right=Width+1; - FIXME("output commented out for now, should be moved to winedos.dll\n"); - /*WriteConsoleOutputA(con, ch, siz, off, &dest);*/ + WriteConsoleOutputA(con, ch, siz, off, &dest); } } vga_refresh=1; diff --git a/include/vga.h b/dlls/winedos/vga.h similarity index 100% rename from include/vga.h rename to dlls/winedos/vga.h diff --git a/dlls/winedos/winedos.spec b/dlls/winedos/winedos.spec index cb21131ecc2..7030cbe9713 100644 --- a/dlls/winedos/winedos.spec +++ b/dlls/winedos/winedos.spec @@ -6,20 +6,19 @@ import user32.dll import kernel32.dll import ntdll.dll -debug_channels (int module relay) +debug_channels (aspi console ddraw int int21 int31 module relay) -@ stdcall GetCurrent() MZ_Current -@ stdcall LoadDPMI() MZ_AllocDPMITask @ stdcall LoadDosExe(str long) MZ_LoadImage -@ stdcall Exec(ptr str long ptr) MZ_Exec -@ stdcall Exit(ptr long long) MZ_Exit -@ stdcall RunInThread(ptr long) MZ_RunInThread -@ stdcall Enter(ptr) DOSVM_Enter -@ stdcall Wait(long long) DOSVM_Wait -@ stdcall QueueEvent(long long ptr ptr) DOSVM_QueueEvent -@ stdcall OutPIC(long long) DOSVM_PIC_ioport_out +# DPMI functions +@ stdcall CallRMInt(ptr) DOSVM_CallRMInt +@ stdcall CallRMProc(ptr ptr long long) DOSVM_CallRMProc +@ stdcall AllocRMCB(ptr) DOSVM_AllocRMCB +@ stdcall FreeRMCB(ptr) DOSVM_FreeRMCB + +# I/O functions @ stdcall SetTimer(long) DOSVM_SetTimer @ stdcall GetTimer() DOSVM_GetTimer - -@ stdcall KbdReadScan(ptr) INT_Int09ReadScan +@ stdcall inport(long long ptr) DOSVM_inport +@ stdcall outport(long long long) DOSVM_outport +@ stdcall ASPIHandler(ptr) DOSVM_ASPIHandler diff --git a/msdos/xms.c b/dlls/winedos/xms.c similarity index 100% rename from msdos/xms.c rename to dlls/winedos/xms.c diff --git a/graphics/dispdib.c b/graphics/dispdib.c index e6e3f9ad3e6..92b63c9ba52 100644 --- a/graphics/dispdib.c +++ b/graphics/dispdib.c @@ -9,13 +9,13 @@ #include "windef.h" #include "wingdi.h" #include "wine/wingdi16.h" -#include "miscemu.h" #include "dispdib.h" -#include "vga.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(ddraw); +#if 0 + static int dispdib_multi = 0; static WORD DISPDIB_Begin(WORD wFlags) @@ -80,6 +80,8 @@ static void DISPDIB_Show(LPBITMAPINFOHEADER lpbi,LPSTR lpBits,WORD uFlags) VGA_Poll(0); } +#endif + /********************************************************************* * DisplayDib (DISPDIB.1) @@ -115,6 +117,7 @@ WORD WINAPI DisplayDib( WORD wFlags /* [in] */ ) { +#if 0 WORD ret; if (wFlags&DISPLAYDIB_END) { @@ -138,5 +141,7 @@ WORD WINAPI DisplayDib( FIXME("wait not implemented\n"); } if (!dispdib_multi) DISPDIB_End(); +#endif + FIXME( "broken, should be rewritten using ddraw\n" ); return DISPLAYDIB_NOERROR; } diff --git a/include/callback.h b/include/callback.h index a93dc4ddd69..23b63bfb9dc 100644 --- a/include/callback.h +++ b/include/callback.h @@ -31,19 +31,20 @@ extern CALLOUT_TABLE Callout; typedef struct { - struct _DOSTASK* WINAPI (*Current)( void ); - struct _DOSTASK* WINAPI (*LoadDPMI)( void ); void WINAPI (*LoadDosExe)( LPCSTR filename, HANDLE hFile ); - BOOL WINAPI (*Exec)( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk ); - void WINAPI (*Exit)( CONTEXT86 *context, BOOL cs_psp, WORD retval ); - int WINAPI (*Enter)( CONTEXT86 *context ); - void WINAPI (*RunInThread)( PAPCFUNC proc, ULONG_PTR arg ); - void WINAPI (*Wait)( int read_pipe, HANDLE hObject ); - void WINAPI (*QueueEvent)( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data ); - void WINAPI (*OutPIC)( WORD port, BYTE val ); + + /* DPMI functions */ + void WINAPI (*CallRMInt)( CONTEXT86 *context ); + void WINAPI (*CallRMProc)( CONTEXT86 *context, int iret ); + void WINAPI (*AllocRMCB)( CONTEXT86 *context ); + void WINAPI (*FreeRMCB)( CONTEXT86 *context ); + + /* I/O functions */ void WINAPI (*SetTimer)( unsigned ticks ); unsigned WINAPI (*GetTimer)( void ); - BYTE WINAPI (*KbdReadScan)( BYTE *ascii ); + BOOL WINAPI (*inport)( int port, int size, DWORD *res ); + BOOL WINAPI (*outport)( int port, int size, DWORD val ); + void WINAPI (*ASPIHandler)( CONTEXT86 *context ); } DOSVM_TABLE; extern DOSVM_TABLE Dosvm; diff --git a/include/dosexe.h b/include/dosexe.h deleted file mode 100644 index 5e0fefd6d9a..00000000000 --- a/include/dosexe.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * DOS EXE loader - * - * Copyright 1998 Ove Kåven - */ - -#ifndef __WINE_DOSEXE_H -#define __WINE_DOSEXE_H - -#include /* pid_t */ -#include "winbase.h" /* for LPSTARTUPINFO32A */ -#include "winnt.h" /* for PCONTEXT */ - -struct _DOSEVENT; - -typedef void (*DOSRELAY)(CONTEXT86*,void*); - -typedef struct _DOSTASK { - WORD psp_seg, retval; - WORD dpmi_flag; -} DOSTASK, *LPDOSTASK; - -#define DOS_PRIORITY_REALTIME 0 /* IRQ0 */ -#define DOS_PRIORITY_KEYBOARD 1 /* IRQ1 */ -#define DOS_PRIORITY_VGA 2 /* IRQ9 */ -#define DOS_PRIORITY_MOUSE 5 /* IRQ12 */ -#define DOS_PRIORITY_SERIAL 10 /* IRQ4 */ - -#if defined(linux) && defined(__i386__) -#define MZ_SUPPORTED -#endif /* linux-i386 */ - -#define V86_FLAG 0x00020000 - -extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile ); -extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk ); -extern void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval ); -extern LPDOSTASK WINAPI MZ_Current( void ); -extern LPDOSTASK WINAPI MZ_AllocDPMITask( void ); -extern void WINAPI MZ_RunInThread( PAPCFUNC proc, ULONG_PTR arg ); -extern INT WINAPI DOSVM_Enter( CONTEXT86 *context ); -extern void WINAPI DOSVM_Wait( INT read_pipe, HANDLE hObject ); -extern DWORD WINAPI DOSVM_Loop( LPVOID lpExtra ); -extern void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data ); -extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val ); -extern void WINAPI DOSVM_SetTimer( UINT ticks ); -extern UINT WINAPI DOSVM_GetTimer( void ); - -#endif /* __WINE_DOSEXE_H */ diff --git a/include/miscemu.h b/include/miscemu.h index bd32ca7a82d..e1dd3e19fd0 100644 --- a/include/miscemu.h +++ b/include/miscemu.h @@ -155,40 +155,15 @@ extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */ /* memory/instr.c */ extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context ); -/* msdos/devices.c */ -extern void DOSDEV_InstallDOSDevices(void); -extern DWORD DOSDEV_Console(void); -extern DWORD DOSDEV_FindCharDevice(char*name); -extern int DOSDEV_Peek(DWORD dev, BYTE*data); -extern int DOSDEV_Read(DWORD dev, DWORD buf, int buflen); -extern int DOSDEV_Write(DWORD dev, DWORD buf, int buflen, int verify); -extern int DOSDEV_IoctlRead(DWORD dev, DWORD buf, int buflen); -extern int DOSDEV_IoctlWrite(DWORD dev, DWORD buf, int buflen); - /* msdos/interrupts.c */ typedef void WINAPI (*INTPROC)(CONTEXT86*); extern FARPROC16 INT_GetPMHandler( BYTE intnum ); extern void INT_SetPMHandler( BYTE intnum, FARPROC16 handler ); -extern FARPROC16 INT_GetRMHandler( BYTE intnum ); -extern void INT_SetRMHandler( BYTE intnum, FARPROC16 handler ); -extern FARPROC16 INT_CtxGetHandler( CONTEXT86 *context, BYTE intnum ); -extern void INT_CtxSetHandler( CONTEXT86 *context, BYTE intnum, FARPROC16 handler ); -extern int INT_RealModeInterrupt( BYTE intnum, CONTEXT86 *context ); -extern INTPROC INT_GetWineHandler( BYTE intnum ); -extern void INT_SetWineHandler( BYTE intnum, INTPROC proc ); /* msdos/ioports.c */ extern DWORD IO_inport( int port, int count ); extern void IO_outport( int port, int count, DWORD value ); -/* msdos/int09.c */ -extern void WINAPI INT_Int09Handler(CONTEXT86*); -extern void WINAPI INT_Int09SendScan(BYTE scan,BYTE ascii); -extern BYTE WINAPI INT_Int09ReadScan(BYTE*ascii); - -/* msdos/int10.c */ -extern void WINAPI INT_Int10Handler(CONTEXT86*); - /* msdos/int11.c */ extern void WINAPI INT_Int11Handler(CONTEXT86*); @@ -201,17 +176,6 @@ extern void WINAPI INT_Int13Handler(CONTEXT86*); /* msdos/int15.c */ extern void WINAPI INT_Int15Handler(CONTEXT86*); -/* msdos/int16.c */ -extern void WINAPI INT_Int16Handler(CONTEXT86*); -extern int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek); -extern int WINAPI INT_Int16AddChar(BYTE ascii,BYTE scan); - -/* msdos/int17.c */ -extern void WINAPI INT_Int17Handler(CONTEXT86*); - -/* msdos/int19.c */ -extern void WINAPI INT_Int19Handler(CONTEXT86*); - /* msdos/int1a.c */ extern DWORD INT1A_GetTicksSinceMidnight(void); extern void WINAPI INT_Int1aHandler(CONTEXT86*); @@ -225,19 +189,12 @@ extern void WINAPI INT_Int25Handler(CONTEXT86*); /* msdos/int26.c */ extern void WINAPI INT_Int26Handler(CONTEXT86*); -/* msdos/int29.c */ -extern void WINAPI INT_Int29Handler(CONTEXT86*); - /* msdos/int2a.c */ extern void WINAPI INT_Int2aHandler(CONTEXT86*); /* msdos/int2f.c */ extern void WINAPI INT_Int2fHandler(CONTEXT86*); -/* msdos/int33.c */ -extern void WINAPI INT_Int33Handler(CONTEXT86*); -extern void WINAPI INT_Int33Message(UINT,WPARAM,LPARAM); - /* msdos/dpmi.c */ typedef void WINAPI (*RMCBPROC)(CONTEXT86*); extern void WINAPI INT_Int31Handler(CONTEXT86*); @@ -246,12 +203,6 @@ extern FARPROC16 WINAPI DPMI_AllocInternalRMCB(RMCBPROC); extern void WINAPI DPMI_FreeInternalRMCB(FARPROC16); extern int DPMI_CallRMProc(CONTEXT86*,LPWORD,int,int); -/* msdos/xms.c */ -extern void WINAPI XMS_Handler(CONTEXT86*); - -/* misc/aspi.c */ -extern void ASPI_DOS_HandleInt(CONTEXT86 *context); - /* misc/ppdev.c */ extern BOOL IO_pp_outp(int port, DWORD* res); diff --git a/miscemu/main.c b/miscemu/main.c index aad576c340e..ececb2e900c 100644 --- a/miscemu/main.c +++ b/miscemu/main.c @@ -11,7 +11,6 @@ #include "miscemu.h" #include "callback.h" #include "options.h" -#include "dosexe.h" #include "debugtools.h" static char main_exe_name[MAX_PATH]; diff --git a/msdos/Makefile.in b/msdos/Makefile.in index 617b42ad5d2..4fc628b3d8c 100644 --- a/msdos/Makefile.in +++ b/msdos/Makefile.in @@ -6,29 +6,20 @@ VPATH = @srcdir@ MODULE = msdos C_SRCS = \ - devices.c \ - dosaspi.c \ dosconf.c \ dosmem.c \ dpmi.c \ - xms.c \ - int10.c \ int11.c \ int12.c \ int13.c \ int15.c \ - int16.c \ - int17.c \ - int19.c \ int1a.c \ int20.c \ int21.c \ int25.c \ int26.c \ - int29.c \ int2a.c \ int2f.c \ - int33.c \ int3d.c \ int41.c \ int4b.c \ @@ -36,7 +27,6 @@ C_SRCS = \ interrupts.c \ ioports.c \ ppdev.c \ - vga.c \ vxd.c all: $(MODULE).o diff --git a/msdos/dosmem.c b/msdos/dosmem.c index 55e800855c1..56604d6fe70 100644 --- a/msdos/dosmem.c +++ b/msdos/dosmem.c @@ -22,8 +22,6 @@ #include "global.h" #include "selectors.h" #include "miscemu.h" -#include "vga.h" -#include "dosexe.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(dosmem); @@ -76,6 +74,8 @@ WORD DOSMEM_xms_seg; WORD DOSMEM_dpmi_seg; WORD DOSMEM_dpmi_sel; +DWORD DOS_LOLSeg; + /*********************************************************************** * DOSMEM_SystemBase * @@ -225,12 +225,6 @@ BYTE * DOSMEM_BiosSys() return DOSMEM_dosmem+0xf0000; } -struct _DOS_LISTOFLISTS * DOSMEM_LOL() -{ - return (struct _DOS_LISTOFLISTS *)DOSMEM_MapRealToLinear - (MAKESEGPTR(HIWORD(DOS_LOLSeg),0)); -} - /*********************************************************************** * DOSMEM_FillBiosSegments * @@ -516,7 +510,6 @@ BOOL DOSMEM_Init(BOOL dos_init) DOSMEM_InitCollateTable(); DOSMEM_InitErrorTable(); DOSMEM_InitDPMI(); - DOSDEV_InstallDOSDevices(); already_done = 1; } else if (dos_init && !already_mapped) diff --git a/msdos/dpmi.c b/msdos/dpmi.c index 00d9c1ba86d..d8687d5f661 100644 --- a/msdos/dpmi.c +++ b/msdos/dpmi.c @@ -15,7 +15,6 @@ #include "builtin16.h" #include "miscemu.h" #include "msdos.h" -#include "dosexe.h" #include "task.h" #include "toolhelp.h" #include "selectors.h" @@ -30,42 +29,8 @@ void CreateBPB(int drive, BYTE *data, BOOL16 limited); /* defined in int21.c */ static void* lastvalloced = NULL; -/* Structure for real-mode callbacks */ -typedef struct -{ - DWORD edi; - DWORD esi; - DWORD ebp; - DWORD reserved; - DWORD ebx; - DWORD edx; - DWORD ecx; - DWORD eax; - WORD fl; - WORD es; - WORD ds; - WORD fs; - WORD gs; - WORD ip; - WORD cs; - WORD sp; - WORD ss; -} REALMODECALL; - - -typedef struct tagRMCB { - DWORD address; - DWORD proc_ofs,proc_sel; - DWORD regs_ofs,regs_sel; - struct tagRMCB *next; -} RMCB; - -static RMCB *FirstRMCB = NULL; - - -static LPDOSTASK WINAPI DPMI_NoCurrent(void) { return NULL; } -DOSVM_TABLE Dosvm = { DPMI_NoCurrent }; +DOSVM_TABLE Dosvm = { NULL, }; static HMODULE DosModule; @@ -80,19 +45,19 @@ BOOL DPMI_LoadDosSystem(void) ERR("could not load winedos.dll, DOS subsystem unavailable\n"); return FALSE; } - Dosvm.Current = (void *)GetProcAddress(DosModule, "GetCurrent"); - Dosvm.LoadDPMI = (void *)GetProcAddress(DosModule, "LoadDPMI"); - Dosvm.LoadDosExe = (void *)GetProcAddress(DosModule, "LoadDosExe"); - Dosvm.Exec = (void *)GetProcAddress(DosModule, "Exec"); - Dosvm.Exit = (void *)GetProcAddress(DosModule, "Exit"); - Dosvm.Enter = (void *)GetProcAddress(DosModule, "Enter"); - Dosvm.RunInThread = (void *)GetProcAddress(DosModule, "RunInThread"); - Dosvm.Wait = (void *)GetProcAddress(DosModule, "Wait"); - Dosvm.QueueEvent = (void *)GetProcAddress(DosModule, "QueueEvent"); - Dosvm.OutPIC = (void *)GetProcAddress(DosModule, "OutPIC"); - Dosvm.SetTimer = (void *)GetProcAddress(DosModule, "SetTimer"); - Dosvm.GetTimer = (void *)GetProcAddress(DosModule, "GetTimer"); - Dosvm.KbdReadScan = (void *)GetProcAddress(DosModule, "KbdReadScan"); +#define GET_ADDR(func) Dosvm.func = (void *)GetProcAddress(DosModule, #func); + + GET_ADDR(LoadDosExe); + GET_ADDR(CallRMInt); + GET_ADDR(CallRMProc); + GET_ADDR(AllocRMCB); + GET_ADDR(FreeRMCB); + GET_ADDR(SetTimer); + GET_ADDR(GetTimer); + GET_ADDR(inport); + GET_ADDR(outport); + GET_ADDR(ASPIHandler); +#undef GET_ADDR return TRUE; } @@ -167,552 +132,52 @@ DPMI_xrealloc(LPVOID ptr,DWORD newsize) { } return newptr; } -/********************************************************************** - * INT_GetRealModeContext - */ -static void INT_GetRealModeContext( REALMODECALL *call, CONTEXT86 *context ) -{ - context->Eax = call->eax; - context->Ebx = call->ebx; - context->Ecx = call->ecx; - context->Edx = call->edx; - context->Esi = call->esi; - context->Edi = call->edi; - context->Ebp = call->ebp; - context->EFlags = call->fl | V86_FLAG; - context->Eip = call->ip; - context->Esp = call->sp; - context->SegCs = call->cs; - context->SegDs = call->ds; - context->SegEs = call->es; - context->SegFs = call->fs; - context->SegGs = call->gs; - context->SegSs = call->ss; -} - - -/********************************************************************** - * INT_SetRealModeContext - */ -static void INT_SetRealModeContext( REALMODECALL *call, CONTEXT86 *context ) -{ - call->eax = context->Eax; - call->ebx = context->Ebx; - call->ecx = context->Ecx; - call->edx = context->Edx; - call->esi = context->Esi; - call->edi = context->Edi; - call->ebp = context->Ebp; - call->fl = LOWORD(context->EFlags); - call->ip = LOWORD(context->Eip); - call->sp = LOWORD(context->Esp); - call->cs = context->SegCs; - call->ds = context->SegDs; - call->es = context->SegEs; - call->fs = context->SegFs; - call->gs = context->SegGs; - call->ss = context->SegSs; -} - -#ifdef __i386__ - -void DPMI_CallRMCB32(RMCB *rmcb, UINT16 ss, DWORD esp, UINT16*es, DWORD*edi) -#if 0 /* original code, which early gccs puke on */ -{ - int _clobber; - __asm__ __volatile__( - "pushl %%ebp\n" - "pushl %%ebx\n" - "pushl %%es\n" - "pushl %%ds\n" - "pushfl\n" - "mov %7,%%es\n" - "mov %5,%%ds\n" - ".byte 0x36, 0xff, 0x18\n" /* lcall *%ss:(%eax) */ - "popl %%ds\n" - "mov %%es,%0\n" - "popl %%es\n" - "popl %%ebx\n" - "popl %%ebp\n" - : "=d" (*es), "=D" (*edi), "=S" (_clobber), "=a" (_clobber), "=c" (_clobber) - : "0" (ss), "2" (esp), - "4" (rmcb->regs_sel), "1" (rmcb->regs_ofs), - "3" (&rmcb->proc_ofs) ); -} -#else /* code generated by a gcc new enough */ -; -__ASM_GLOBAL_FUNC(DPMI_CallRMCB32, - "pushl %ebp\n\t" - "movl %esp,%ebp\n\t" - "pushl %edi\n\t" - "pushl %esi\n\t" - "movl 0x8(%ebp),%eax\n\t" - "movl 0x10(%ebp),%esi\n\t" - "movl 0xc(%ebp),%edx\n\t" - "movl 0x10(%eax),%ecx\n\t" - "movl 0xc(%eax),%edi\n\t" - "addl $0x4,%eax\n\t" - "pushl %ebp\n\t" - "pushl %ebx\n\t" - "pushl %es\n\t" - "pushl %ds\n\t" - "pushfl\n\t" - "mov %cx,%es\n\t" - "mov %dx,%ds\n\t" - ".byte 0x36, 0xff, 0x18\n\t" /* lcall *%ss:(%eax) */ - "popl %ds\n\t" - "mov %es,%dx\n\t" - "popl %es\n\t" - "popl %ebx\n\t" - "popl %ebp\n\t" - "movl 0x14(%ebp),%eax\n\t" - "movw %dx,(%eax)\n\t" - "movl 0x18(%ebp),%edx\n\t" - "movl %edi,(%edx)\n\t" - "popl %esi\n\t" - "popl %edi\n\t" - "leave\n\t" - "ret") -#endif - -#endif /* __i386__ */ - -/********************************************************************** - * DPMI_CallRMCBProc - * - * This routine does the hard work of calling a callback procedure. - */ -static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag ) -{ - if (IS_SELECTOR_SYSTEM( rmcb->proc_sel )) { - /* Wine-internal RMCB, call directly */ - ((RMCBPROC)rmcb->proc_ofs)(context); - } else { -#ifdef __i386__ - UINT16 ss,es; - DWORD esp,edi; - - INT_SetRealModeContext(MapSL(MAKESEGPTR( rmcb->regs_sel, rmcb->regs_ofs )), context); - ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, WINE_LDT_FLAGS_DATA ); - esp = context->Esp; - - FIXME("untested!\n"); - - /* The called proc ends with an IRET, and takes these parameters: - * DS:ESI = pointer to real-mode SS:SP - * ES:EDI = pointer to real-mode call structure - * It returns: - * ES:EDI = pointer to real-mode call structure (may be a copy) - * It is the proc's responsibility to change the return CS:IP in the - * real-mode call structure. */ - if (flag & 1) { - /* 32-bit DPMI client */ - DPMI_CallRMCB32(rmcb, ss, esp, &es, &edi); - } else { - /* 16-bit DPMI client */ - CONTEXT86 ctx = *context; - ctx.SegCs = rmcb->proc_sel; - ctx.Eip = rmcb->proc_ofs; - ctx.SegDs = ss; - ctx.Esi = esp; - ctx.SegEs = rmcb->regs_sel; - ctx.Edi = rmcb->regs_ofs; - /* FIXME: I'm pretty sure this isn't right - should push flags first */ - wine_call_to_16_regs_short(&ctx, 0); - es = ctx.SegEs; - edi = ctx.Edi; - } - FreeSelector16(ss); - INT_GetRealModeContext( MapSL( MAKESEGPTR( es, edi )), context); -#else - ERR("RMCBs only implemented for i386\n"); -#endif - } -} - - -/********************************************************************** - * DPMI_CallRMProc - * - * This routine does the hard work of calling a real mode procedure. - */ -int DPMI_CallRMProc( CONTEXT86 *context, LPWORD stack, int args, int iret ) -{ - LPWORD stack16; - LPVOID addr = NULL; /* avoid gcc warning */ - LPDOSTASK lpDosTask = Dosvm.Current(); - RMCB *CurrRMCB; - int alloc = 0, already = 0; - BYTE *code; - - TRACE("EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n", - context->Eax, context->Ebx, context->Ecx, context->Edx ); - TRACE("ESI=%08lx EDI=%08lx ES=%04lx DS=%04lx CS:IP=%04lx:%04x, %d WORD arguments, %s\n", - context->Esi, context->Edi, context->SegEs, context->SegDs, - context->SegCs, LOWORD(context->Eip), args, iret?"IRET":"FAR" ); - -callrmproc_again: - -/* there might be some code that just jumps to RMCBs or the like, - in which case following the jumps here might get us to a shortcut */ - code = CTX_SEG_OFF_TO_LIN(context, context->SegCs, context->Eip); - switch (*code) { - case 0xe9: /* JMP NEAR */ - context->Eip += 3 + *(WORD *)(code+1); - /* yeah, I know these gotos don't look good... */ - goto callrmproc_again; - case 0xea: /* JMP FAR */ - context->Eip = *(WORD *)(code+1); - context->SegCs = *(WORD *)(code+3); - /* ...but since the label is there anyway... */ - goto callrmproc_again; - case 0xeb: /* JMP SHORT */ - context->Eip += 2 + *(signed char *)(code+1); - /* ...because of other gotos below, so... */ - goto callrmproc_again; - } - -/* shortcut for chaining to internal interrupt handlers */ - if ((context->SegCs == 0xF000) && iret) { - return INT_RealModeInterrupt( LOWORD(context->Eip)/4, context); - } - -/* shortcut for RMCBs */ - CurrRMCB = FirstRMCB; - - while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs)) - CurrRMCB = CurrRMCB->next; - - if (!(CurrRMCB || lpDosTask)) { - FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n"); - TRACE("creating VM86 task\n"); - if ((!DPMI_LoadDosSystem()) || !(lpDosTask = Dosvm.LoadDPMI() )) { - ERR("could not setup VM86 task\n"); - return 1; - } - } - if (!already) { - if (!context->SegSs) { - alloc = 1; /* allocate default stack */ - stack16 = addr = DOSMEM_GetBlock( 64, (UINT16 *)&(context->SegSs) ); - context->Esp = 64-2; - stack16 += 32-1; - if (!addr) { - ERR("could not allocate default stack\n"); - return 1; - } - } else { - stack16 = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); - } - context->Esp -= (args + (iret?1:0)) * sizeof(WORD); - stack16 -= args; - if (args) memcpy(stack16, stack, args*sizeof(WORD) ); - /* push flags if iret */ - if (iret) { - stack16--; args++; - *stack16 = LOWORD(context->EFlags); - } - /* push return address (return to interrupt wrapper) */ - *(--stack16) = DOSMEM_wrap_seg; - *(--stack16) = 0; - /* adjust stack */ - context->Esp -= 2*sizeof(WORD); - already = 1; - } - - if (CurrRMCB) { - /* RMCB call, invoke protected-mode handler directly */ - DPMI_CallRMCBProc(context, CurrRMCB, lpDosTask ? lpDosTask->dpmi_flag : 0); - /* check if we returned to where we thought we would */ - if ((context->SegCs != DOSMEM_wrap_seg) || - (LOWORD(context->Eip) != 0)) { - /* we need to continue at different address in real-mode space, - so we need to set it all up for real mode again */ - goto callrmproc_again; - } - } else { - TRACE("entering real mode...\n"); - Dosvm.Enter( context ); - TRACE("returned from real-mode call\n"); - } - if (alloc) DOSMEM_FreeBlock( addr ); - return 0; -} - /********************************************************************** * CallRMInt */ static void CallRMInt( CONTEXT86 *context ) { - CONTEXT86 realmode_ctx; - FARPROC16 rm_int = INT_GetRMHandler( BL_reg(context) ); - REALMODECALL *call = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) )); - INT_GetRealModeContext( call, &realmode_ctx ); - - /* we need to check if a real-mode program has hooked the interrupt */ - if (HIWORD(rm_int)!=0xF000) { - /* yup, which means we need to switch to real mode... */ - realmode_ctx.SegCs = HIWORD(rm_int); - realmode_ctx.Eip = LOWORD(rm_int); - if (DPMI_CallRMProc( &realmode_ctx, NULL, 0, TRUE)) - SET_CFLAG(context); - } else { - RESET_CFLAG(context); - /* use the IP we have instead of BL_reg, in case some apps - decide to move interrupts around for whatever reason... */ - if (INT_RealModeInterrupt( LOWORD(rm_int)/4, &realmode_ctx )) - SET_CFLAG(context); - if (context->EFlags & 1) { - FIXME("%02x: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n", - BL_reg(context), realmode_ctx.Eax, realmode_ctx.Ebx, - realmode_ctx.Ecx, realmode_ctx.Edx); - FIXME(" ESI=%08lx EDI=%08lx DS=%04lx ES=%04lx\n", - realmode_ctx.Esi, realmode_ctx.Edi, - realmode_ctx.SegDs, realmode_ctx.SegEs ); - } + if (!Dosvm.CallRMInt && !DPMI_LoadDosSystem()) + { + ERR("could not setup real-mode calls\n"); + return; } - INT_SetRealModeContext( call, &realmode_ctx ); + Dosvm.CallRMInt( context ); } static void CallRMProc( CONTEXT86 *context, int iret ) { - REALMODECALL *p = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) )); - CONTEXT86 context16; - - TRACE("RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n", - p->eax, p->ebx, p->ecx, p->edx); - TRACE(" ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments, %s\n", - p->esi, p->edi, p->es, p->ds, p->cs, p->ip, CX_reg(context), iret?"IRET":"FAR" ); - - if (!(p->cs) && !(p->ip)) { /* remove this check - if Int21/6501 case map function - has been implemented */ - SET_CFLAG(context); - return; - } - INT_GetRealModeContext(p, &context16); - DPMI_CallRMProc( &context16, ((LPWORD)MapSL(MAKESEGPTR(context->SegSs, LOWORD(context->Esp))))+3, - CX_reg(context), iret ); - INT_SetRealModeContext(p, &context16); -} - - -static RMCB *DPMI_AllocRMCB( void ) -{ - RMCB *NewRMCB = HeapAlloc(GetProcessHeap(), 0, sizeof(RMCB)); - UINT16 uParagraph; - - if (NewRMCB) + if (!Dosvm.CallRMProc && !DPMI_LoadDosSystem()) { - LPVOID RMCBmem = DOSMEM_GetBlock(4, &uParagraph); - LPBYTE p = RMCBmem; - - *p++ = 0xcd; /* RMCB: */ - *p++ = 0x31; /* int $0x31 */ -/* it is the called procedure's task to change the return CS:EIP - the DPMI 0.9 spec states that if it doesn't, it will be called again */ - *p++ = 0xeb; - *p++ = 0xfc; /* jmp RMCB */ - NewRMCB->address = MAKELONG(0, uParagraph); - NewRMCB->next = FirstRMCB; - FirstRMCB = NewRMCB; + ERR("could not setup real-mode calls\n"); + return; } - return NewRMCB; + Dosvm.CallRMProc( context, iret ); } - static void AllocRMCB( CONTEXT86 *context ) { - RMCB *NewRMCB = DPMI_AllocRMCB(); - - TRACE("Function to call: %04x:%04x\n", (WORD)context->SegDs, SI_reg(context) ); - - if (NewRMCB) + if (!Dosvm.AllocRMCB && !DPMI_LoadDosSystem()) { - /* FIXME: if 32-bit DPMI client, use ESI and EDI */ - NewRMCB->proc_ofs = LOWORD(context->Esi); - NewRMCB->proc_sel = context->SegDs; - NewRMCB->regs_ofs = LOWORD(context->Edi); - NewRMCB->regs_sel = context->SegEs; - SET_LOWORD( context->Ecx, HIWORD(NewRMCB->address) ); - SET_LOWORD( context->Edx, LOWORD(NewRMCB->address) ); - } - else - { - SET_LOWORD( context->Eax, 0x8015 ); /* callback unavailable */ - SET_CFLAG(context); + ERR("could not setup real-mode calls\n"); + return; } + Dosvm.AllocRMCB( context ); } - -FARPROC16 WINAPI DPMI_AllocInternalRMCB( RMCBPROC proc ) -{ - RMCB *NewRMCB = DPMI_AllocRMCB(); - - if (NewRMCB) { - NewRMCB->proc_ofs = (DWORD)proc; - NewRMCB->proc_sel = 0; - NewRMCB->regs_ofs = 0; - NewRMCB->regs_sel = 0; - return (FARPROC16)(NewRMCB->address); - } - return NULL; -} - - -static int DPMI_FreeRMCB( DWORD address ) -{ - RMCB *CurrRMCB = FirstRMCB; - RMCB *PrevRMCB = NULL; - - while (CurrRMCB && (CurrRMCB->address != address)) - { - PrevRMCB = CurrRMCB; - CurrRMCB = CurrRMCB->next; - } - if (CurrRMCB) - { - if (PrevRMCB) - PrevRMCB->next = CurrRMCB->next; - else - FirstRMCB = CurrRMCB->next; - DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(CurrRMCB->address)); - HeapFree(GetProcessHeap(), 0, CurrRMCB); - return 0; - } - return 1; -} - - static void FreeRMCB( CONTEXT86 *context ) { - FIXME("callback address: %04x:%04x\n", - CX_reg(context), DX_reg(context)); - - if (DPMI_FreeRMCB(MAKELONG(DX_reg(context), CX_reg(context)))) { - SET_LOWORD( context->Eax, 0x8024 ); /* invalid callback address */ - SET_CFLAG(context); + if (!Dosvm.FreeRMCB) /* cannot have allocated one if dosvm not loaded */ + { + SET_LOWORD( context->Eax, 0x8024 ); /* invalid callback address */ + SET_CFLAG( context ); } + else Dosvm.FreeRMCB( context ); } -void WINAPI DPMI_FreeInternalRMCB( FARPROC16 proc ) -{ - DPMI_FreeRMCB( (DWORD)proc ); -} - - -/* (see dosmem.c, function DOSMEM_InitDPMI) */ - -static void StartPM( CONTEXT86 *context, LPDOSTASK lpDosTask ) -{ - UINT16 cs, ss, ds, es; - CONTEXT86 pm_ctx; - DWORD psp_ofs = (DWORD)(lpDosTask->psp_seg<<4); - PDB16 *psp = (PDB16 *)psp_ofs; - HANDLE16 env_seg = psp->environment; - unsigned char selflags = WINE_LDT_FLAGS_DATA; - - RESET_CFLAG(context); - lpDosTask->dpmi_flag = AX_reg(context); -/* our mode switch wrapper have placed the desired CS into DX */ - cs = SELECTOR_AllocBlock( (void *)(DX_reg(context)<<4), 0x10000, WINE_LDT_FLAGS_CODE ); -/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they - can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a - ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing - 32-bit code using this stack. */ - if (lpDosTask->dpmi_flag & 1) selflags |= WINE_LDT_FLAGS_32BIT; - ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, selflags ); -/* do the same for the data segments, just in case */ - if (context->SegDs == context->SegSs) ds = ss; - else ds = SELECTOR_AllocBlock( (void *)(context->SegDs<<4), 0x10000, selflags ); - es = SELECTOR_AllocBlock( psp, 0x100, selflags ); -/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */ - psp->environment = SELECTOR_AllocBlock( (void *)(env_seg<<4), 0x10000, WINE_LDT_FLAGS_DATA ); - - pm_ctx = *context; - pm_ctx.SegCs = DOSMEM_dpmi_sel; -/* our mode switch wrapper expects the new CS in DX, and the new SS in AX */ - pm_ctx.Eax = ss; - pm_ctx.Edx = cs; - pm_ctx.SegDs = ds; - pm_ctx.SegEs = es; - pm_ctx.SegFs = 0; - pm_ctx.SegGs = 0; - - TRACE("DOS program is now entering protected mode\n"); - wine_call_to_16_regs_short(&pm_ctx, 0); - - /* in the current state of affairs, we won't ever actually return here... */ - /* we should have int21/ah=4c do it someday, though... */ - - FreeSelector16(psp->environment); - psp->environment = env_seg; - FreeSelector16(es); - if (ds != ss) FreeSelector16(ds); - FreeSelector16(ss); - FreeSelector16(cs); -} - -/* DPMI Raw Mode Switch handler */ - -#if 0 -void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context ) -{ - LPDOSTASK lpDosTask = Dosvm.Current(); - CONTEXT86 rm_ctx; - int ret; - - if (!lpDosTask) { - /* we could probably start a DPMI-only dosmod task here, but I doubt - anything other than real DOS apps want to call raw mode switch */ - ERR("attempting raw mode switch without DOS task!\n"); - ExitProcess(1); - } - /* initialize real-mode context as per spec */ - memset(&rm_ctx, 0, sizeof(rm_ctx)); - rm_ctx.SegDs = AX_sig(context); - rm_ctx.SegEs = CX_sig(context); - rm_ctx.SegSs = DX_sig(context); - rm_ctx.Esp = EBX_sig(context); - rm_ctx.SegCs = SI_sig(context); - rm_ctx.Eip = EDI_sig(context); - rm_ctx.Ebp = EBP_sig(context); - rm_ctx.SegFs = 0; - rm_ctx.SegGs = 0; - rm_ctx.EFlags = EFL_sig(context); /* at least we need the IF flag */ - - /* enter real mode again */ - TRACE("re-entering real mode at %04lx:%04lx\n",rm_ctx.SegCs,rm_ctx.Eip); - ret = Dosvm.Enter( &rm_ctx ); - /* when the real-mode stuff call its mode switch address, - Dosvm.Enter will return and we will continue here */ - - if (ret<0) { - /* if the sync was lost, there's no way to recover */ - ExitProcess(1); - } - - /* alter protected-mode context as per spec */ - DS_sig(context) = LOWORD(rm_ctx.Eax); - ES_sig(context) = LOWORD(rm_ctx.Ecx); - SS_sig(context) = LOWORD(rm_ctx.Edx); - ESP_sig(context) = rm_ctx.Ebx; - CS_sig(context) = LOWORD(rm_ctx.Esi); - EIP_sig(context) = rm_ctx.Edi; - EBP_sig(context) = rm_ctx.Ebp; - FS_sig(context) = 0; - GS_sig(context) = 0; - - /* Return to new address and hope that we didn't mess up */ - TRACE("re-entering protected mode at %04x:%08lx\n", - CS_sig(context), EIP_sig(context)); -} -#endif - - /********************************************************************** * INT_Int31Handler (WPROCS.149) * @@ -729,36 +194,6 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context ) DWORD dw; BYTE *ptr; - LPDOSTASK lpDosTask = Dosvm.Current(); - - if (ISV86(context) && lpDosTask) { - /* Called from real mode, check if it's our wrapper */ - TRACE("called from real mode\n"); - if (context->SegCs==DOSMEM_dpmi_seg) { - /* This is the protected mode switch */ - StartPM(context,lpDosTask); - return; - } else - if (context->SegCs==DOSMEM_xms_seg) { - /* This is the XMS driver entry point */ - XMS_Handler(context); - return; - } else - { - /* Check for RMCB */ - RMCB *CurrRMCB = FirstRMCB; - - while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs)) - CurrRMCB = CurrRMCB->next; - - if (CurrRMCB) { - /* RMCB call, propagate to protected-mode handler */ - DPMI_CallRMCBProc(context, CurrRMCB, lpDosTask->dpmi_flag); - return; - } - } - } - RESET_CFLAG(context); switch(AX_reg(context)) { @@ -851,8 +286,8 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context ) W32S_APP2WINE(MAKELONG(DX_reg(context),CX_reg(context)))); dw = W32S_APP2WINE(MAKELONG(DX_reg(context), CX_reg(context))); if (dw < 0x10000) - /* app wants to access lower 64K of DOS memory, map it in now */ - DOSMEM_Init(TRUE); + /* app wants to access lower 64K of DOS memory, load DOS subsystem */ + DPMI_LoadDosSystem(); SetSelectorBase(BX_reg(context), dw); break; diff --git a/msdos/int20.c b/msdos/int20.c index 99640335b58..e98c4384fcb 100644 --- a/msdos/int20.c +++ b/msdos/int20.c @@ -5,9 +5,6 @@ #include #include "winbase.h" #include "miscemu.h" -/* #define DEBUG_INT */ -#include "debugtools.h" -#include "callback.h" /********************************************************************** * INT_Int20Handler (WPROCS.132) @@ -16,6 +13,5 @@ */ void WINAPI INT_Int20Handler( CONTEXT86 *context ) { - if (Dosvm.Exit) Dosvm.Exit( context, TRUE, 0 ); - else ExitThread( 0 ); + ExitThread( 0 ); } diff --git a/msdos/int21.c b/msdos/int21.c index e9db39dbac4..e0ca2cb90e2 100644 --- a/msdos/int21.c +++ b/msdos/int21.c @@ -26,12 +26,11 @@ #include "winerror.h" #include "drive.h" #include "file.h" +#include "callback.h" #include "msdos.h" #include "options.h" #include "miscemu.h" #include "task.h" -#include "dosexe.h" -#include "callback.h" #include "debugtools.h" #include "console.h" @@ -111,6 +110,13 @@ static WORD DosHeapHandle; extern char TempDirectory[]; +static void INT21_ReadConfigSys(void) +{ + static int done; + if (!done) DOSCONF_ReadConfig(); + done = 1; +} + static BOOL INT21_CreateHeap(void) { if (!(DosHeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct DosHeap)))) @@ -944,32 +950,15 @@ INT21_networkfunc (CONTEXT86 *context) } } -static void INT21_SetCurrentPSP(WORD psp) -{ - LPDOSTASK lpDosTask = Dosvm.Current(); - if (lpDosTask) - lpDosTask->psp_seg = psp; - else - ERR("Cannot change PSP for non-DOS task!\n"); -} - -static WORD INT21_GetCurrentPSP(void) -{ - LPDOSTASK lpDosTask = Dosvm.Current(); - if (lpDosTask) - return lpDosTask->psp_seg; - else - return GetCurrentPDB16(); -} -static WORD INT21_GetReturnCode(void) +static void ASPI_DOS_HandleInt( CONTEXT86 *context ) { - LPDOSTASK lpDosTask = Dosvm.Current(); - if (lpDosTask) { - WORD ret = lpDosTask->retval; - lpDosTask->retval = 0; - return ret; - } else return 0; + if (!Dosvm.ASPIHandler && !DPMI_LoadDosSystem()) + { + ERR("could not setup ASPI handler\n"); + return; + } + Dosvm.ASPIHandler( context ); } /*********************************************************************** @@ -1125,9 +1114,15 @@ void WINAPI DOS3Call( CONTEXT86 *context ) switch(AH_reg(context)) { + case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */ + case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */ case 0x03: /* READ CHARACTER FROM STDAUX */ case 0x04: /* WRITE CHARACTER TO STDAUX */ case 0x05: /* WRITE CHARACTER TO PRINTER */ + case 0x06: /* DIRECT CONSOLE IN/OUTPUT */ + case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */ + case 0x08: /* CHARACTER INPUT WITHOUT ECHO */ + case 0x0b: /* GET STDIN STATUS */ case 0x0f: /* OPEN FILE USING FCB */ case 0x10: /* CLOSE FILE USING FCB */ case 0x14: /* SEQUENTIAL READ FROM FCB FILE */ @@ -1140,68 +1135,14 @@ void WINAPI DOS3Call( CONTEXT86 *context ) case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */ case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */ case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */ + case 0x4d: /* GET RETURN CODE */ + case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */ INT_BARF( context, 0x21 ); break; case 0x00: /* TERMINATE PROGRAM */ TRACE("TERMINATE PROGRAM\n"); - if (Dosvm.Exit) Dosvm.Exit( context, FALSE, 0 ); - else ExitThread( 0 ); - break; - - case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */ - TRACE("DIRECT CHARACTER INPUT WITH ECHO\n"); - AL_reg(context) = CONSOLE_GetCharacter(); - /* FIXME: no echo */ - break; - - case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */ - TRACE("Write Character to Standard Output\n"); - CONSOLE_Write(DL_reg(context), 0, 0, 0); - break; - - case 0x06: /* DIRECT CONSOLE IN/OUTPUT */ - /* FIXME: Use DOSDEV_Peek/Read/Write(DOSDEV_Console(),...) !! */ - if (DL_reg(context) == 0xff) { - static char scan = 0; - TRACE("Direct Console Input\n"); - if (scan) { - /* return pending scancode */ - AL_reg(context) = scan; - RESET_ZFLAG(context); - scan = 0; - } else { - char ascii; - if (INT_Int16ReadChar(&ascii,&scan,TRUE)) { - INT_Int16ReadChar(&ascii,&scan,FALSE); - /* return ASCII code */ - AL_reg(context) = ascii; - RESET_ZFLAG(context); - /* return scan code on next call only if ascii==0 */ - if (ascii) scan = 0; - } else { - /* nothing pending, clear everything */ - AL_reg(context) = 0; - SET_ZFLAG(context); - scan = 0; /* just in case */ - } - } - } else { - TRACE("Direct Console Output\n"); - CONSOLE_Write(DL_reg(context), 0, 0, 0); - } - break; - - case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */ - /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */ - TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n"); - INT_Int16ReadChar(&AL_reg(context), NULL, FALSE); - break; - - case 0x08: /* CHARACTER INPUT WITHOUT ECHO */ - /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */ - TRACE("CHARACTER INPUT WITHOUT ECHO\n"); - INT_Int16ReadChar(&AL_reg(context), NULL, FALSE); + ExitThread( 0 ); break; case 0x09: /* WRITE STRING TO STANDARD OUTPUT */ @@ -1235,15 +1176,6 @@ void WINAPI DOS3Call( CONTEXT86 *context ) break; } - case 0x0b: {/* GET STDIN STATUS */ - char x1,x2; - - if (CONSOLE_CheckForKeystroke(&x1,&x2)) - AL_reg(context) = 0xff; - else - AL_reg(context) = 0; - break; - } case 0x2e: /* SET VERIFY FLAG */ TRACE("SET VERIFY FLAG ignored\n"); /* we cannot change the behaviour anyway, so just ignore it */ @@ -1320,8 +1252,7 @@ void WINAPI DOS3Call( CONTEXT86 *context ) break; case 0x25: /* SET INTERRUPT VECTOR */ - INT_CtxSetHandler( context, AL_reg(context), - (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context))); + INT_SetPMHandler( AL_reg(context), (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context))); break; case 0x29: /* PARSE FILENAME INTO FCB */ @@ -1387,16 +1318,19 @@ void WINAPI DOS3Call( CONTEXT86 *context ) { case 0x00: /* GET CURRENT EXTENDED BREAK STATE */ TRACE("GET CURRENT EXTENDED BREAK STATE\n"); + INT21_ReadConfigSys(); DL_reg(context) = DOSCONF_config.brk_flag; break; case 0x01: /* SET EXTENDED BREAK STATE */ TRACE("SET CURRENT EXTENDED BREAK STATE\n"); + INT21_ReadConfigSys(); DOSCONF_config.brk_flag = (DL_reg(context) > 0); break; case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE*/ TRACE("GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE\n"); + INT21_ReadConfigSys(); /* ugly coding in order to stay reentrant */ if (DL_reg(context)) { @@ -1439,7 +1373,7 @@ void WINAPI DOS3Call( CONTEXT86 *context ) case 0x35: /* GET INTERRUPT VECTOR */ TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context)); { - FARPROC16 addr = INT_CtxGetHandler( context, AL_reg(context) ); + FARPROC16 addr = INT_GetPMHandler( AL_reg(context) ); context->SegEs = SELECTOROF(addr); BX_reg(context) = OFFSETOF(addr); } @@ -1691,21 +1625,6 @@ void WINAPI DOS3Call( CONTEXT86 *context ) DX_reg(context) = 0; break; - case 0x0b: /* SET SHARING RETRY COUNT */ - TRACE("IOCTL - SET SHARING RETRY COUNT pause %d retries %d\n", - CX_reg(context), DX_reg(context)); - if (!CX_reg(context)) - { - AX_reg(context) = 1; - SET_CFLAG(context); - break; - } - DOSMEM_LOL()->sharing_retry_delay = CX_reg(context); - if (!DX_reg(context)) - DOSMEM_LOL()->sharing_retry_count = DX_reg(context); - RESET_CFLAG(context); - break; - case 0x0d: TRACE("IOCTL - GENERIC BLOCK DEVICE REQUEST %s\n", INT21_DriveName( BL_reg(context))); @@ -1842,29 +1761,15 @@ void WINAPI DOS3Call( CONTEXT86 *context ) break; case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */ - TRACE("EXEC %s\n", - (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx )); - if (ISV86(context)) { - if (!Dosvm.Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx), - AL_reg(context), CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx) )) - bSetDOSExtendedError = TRUE; - } else { - AX_reg(context) = WinExec16( CTX_SEG_OFF_TO_LIN(context, context->SegDs, - context->Edx ), - SW_NORMAL ); - if (AX_reg(context) < 32) SET_CFLAG(context); - } - break; - - case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */ - TRACE("EXIT with return code %d\n",AL_reg(context)); - if (Dosvm.Exit) Dosvm.Exit( context, FALSE, AL_reg(context) ); - else ExitThread( AL_reg(context) ); + TRACE("EXEC %s\n", (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx )); + AX_reg(context) = WinExec16( CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ), + SW_NORMAL ); + if (AX_reg(context) < 32) SET_CFLAG(context); break; - case 0x4d: /* GET RETURN CODE */ - TRACE("GET RETURN CODE (ERRORLEVEL)\n"); - AX_reg(context) = INT21_GetReturnCode(); + case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */ + TRACE("EXIT with return code %d\n",AL_reg(context)); + ExitThread( AL_reg(context) ); break; case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */ @@ -1883,27 +1788,22 @@ void WINAPI DOS3Call( CONTEXT86 *context ) } else AX_reg(context) = 0; /* OK */ break; - case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */ - TRACE("SET CURRENT PROCESS ID (SET PSP ADDRESS)\n"); - INT21_SetCurrentPSP(BX_reg(context)); - break; case 0x51: /* GET PSP ADDRESS */ TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n"); /* FIXME: should we return the original DOS PSP upon */ /* Windows startup ? */ - BX_reg(context) = INT21_GetCurrentPSP(); + BX_reg(context) = GetCurrentPDB16(); break; case 0x62: /* GET PSP ADDRESS */ - TRACE("GET CURRENT PSP ADDRESS\n"); /* FIXME: should we return the original DOS PSP upon */ /* Windows startup ? */ - BX_reg(context) = INT21_GetCurrentPSP(); + BX_reg(context) = GetCurrentPDB16(); break; case 0x52: /* "SYSVARS" - GET LIST OF LISTS */ TRACE("SYSVARS - GET LIST OF LISTS\n"); { - context->SegEs = ISV86(context) ? HIWORD(DOS_LOLSeg) : LOWORD(DOS_LOLSeg); + context->SegEs = LOWORD(DOS_LOLSeg); BX_reg(context) = FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB); } break; diff --git a/msdos/int2f.c b/msdos/int2f.c index 88dc312f21d..ed6fffbdd8e 100644 --- a/msdos/int2f.c +++ b/msdos/int2f.c @@ -11,7 +11,6 @@ #include #include "wine/winbase16.h" -#include "dosexe.h" #include "miscemu.h" #include "module.h" /* #define DEBUG_INT */ diff --git a/msdos/interrupts.c b/msdos/interrupts.c index 618a5731c44..4abf2e13b9d 100644 --- a/msdos/interrupts.c +++ b/msdos/interrupts.c @@ -14,17 +14,6 @@ DEFAULT_DEBUG_CHANNEL(int); -static INTPROC INT_WineHandler[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - INT_Int10Handler, INT_Int11Handler, INT_Int12Handler, INT_Int13Handler, - 0, INT_Int15Handler, INT_Int16Handler, INT_Int17Handler, - 0, 0, INT_Int1aHandler, 0, 0, 0, 0, 0, - INT_Int20Handler, DOS3Call, 0, 0, 0, INT_Int25Handler, 0, 0, - 0, INT_Int29Handler, INT_Int2aHandler, 0, 0, 0, 0, INT_Int2fHandler, - 0, INT_Int31Handler, 0, INT_Int33Handler -}; - static FARPROC16 INT_Vectors[256]; /* Ordinal number for interrupt 0 handler in WPROCS.DLL */ @@ -73,97 +62,6 @@ void INT_SetPMHandler( BYTE intnum, FARPROC16 handler ) } -/********************************************************************** - * INT_GetRMHandler - * - * Return the real mode interrupt vector for a given interrupt. - */ -FARPROC16 INT_GetRMHandler( BYTE intnum ) -{ - return ((FARPROC16*)DOSMEM_SystemBase())[intnum]; -} - - -/********************************************************************** - * INT_SetRMHandler - * - * Set the real mode interrupt handler for a given interrupt. - */ -void INT_SetRMHandler( BYTE intnum, FARPROC16 handler ) -{ - TRACE("Set real mode interrupt vector %02x <- %04x:%04x\n", - intnum, HIWORD(handler), LOWORD(handler) ); - ((FARPROC16*)DOSMEM_SystemBase())[intnum] = handler; -} - - -/********************************************************************** - * INT_CtxGetHandler - * - * Return the interrupt vector for a given interrupt. - */ -FARPROC16 INT_CtxGetHandler( CONTEXT86 *context, BYTE intnum ) -{ - if (ISV86(context)) - return INT_GetRMHandler(intnum); - else - return INT_GetPMHandler(intnum); -} - - -/********************************************************************** - * INT_CtxSetHandler - * - * Set the interrupt handler for a given interrupt. - */ -void INT_CtxSetHandler( CONTEXT86 *context, BYTE intnum, FARPROC16 handler ) -{ - if (ISV86(context)) - INT_SetRMHandler(intnum, handler); - else - INT_SetPMHandler(intnum, handler); -} - - -/********************************************************************** - * INT_GetWineHandler - * - * Return the Wine interrupt handler for a given interrupt. - */ -INTPROC INT_GetWineHandler( BYTE intnum ) -{ - return INT_WineHandler[intnum]; -} - - -/********************************************************************** - * INT_SetWineHandler - * - * Set the Wine interrupt handler for a given interrupt. - */ -void INT_SetWineHandler( BYTE intnum, INTPROC handler ) -{ - TRACE("Set Wine interrupt vector %02x <- %p\n", intnum, handler ); - INT_WineHandler[intnum] = handler; -} - - -/********************************************************************** - * INT_RealModeInterrupt - * - * Handle real mode interrupts - */ -int INT_RealModeInterrupt( BYTE intnum, CONTEXT86 *context ) -{ - if (INT_WineHandler[intnum]) { - (*INT_WineHandler[intnum])(context); - return 0; - } - FIXME("Unknown Interrupt in DOS mode: 0x%x\n", intnum); - return 1; -} - - /********************************************************************** * INT_DefaultHandler (WPROCS.356) * diff --git a/msdos/ioports.c b/msdos/ioports.c index 24450f0da65..235b1e1f5e3 100644 --- a/msdos/ioports.c +++ b/msdos/ioports.c @@ -20,9 +20,7 @@ #include #include #include "windef.h" -#include "vga.h" #include "callback.h" -#include "dosexe.h" #include "options.h" #include "miscemu.h" #include "debugtools.h" @@ -98,8 +96,7 @@ static void set_timer_maxval(unsigned timer, unsigned maxval) { switch (timer) { case 0: /* System timer counter divisor */ - if (Dosvm.Current()) - Dosvm.SetTimer(maxval); + if (Dosvm.SetTimer) Dosvm.SetTimer(maxval); break; case 1: /* RAM refresh */ FIXME("RAM refresh counter handling not implemented !\n"); @@ -292,6 +289,9 @@ DWORD IO_inport( int port, int size ) } #endif + /* first give the DOS VM a chance to handle it */ + if (Dosvm.inport && Dosvm.inport( port, size, &res )) return res; + switch (port) { case 0x40: @@ -308,7 +308,7 @@ DWORD IO_inport( int port, int size ) if (chan == 0) /* System timer counter divisor */ { /* FIXME: Dosvm.GetTimer() returns quite rigid values */ - if (Dosvm.Current()) + if (Dosvm.GetTimer) tempval = dummy_ctr + (WORD)Dosvm.GetTimer(); else tempval = dummy_ctr; @@ -345,7 +345,6 @@ DWORD IO_inport( int port, int size ) } break; case 0x60: - res = Dosvm.KbdReadScan ? Dosvm.KbdReadScan(NULL) : 0; #if 0 /* what's this port got to do with parport ? */ res = (DWORD)parport_8255[0]; #endif @@ -366,10 +365,6 @@ DWORD IO_inport( int port, int size ) case 0x201: res = 0xffffffff; /* no joystick */ break; - case 0x3ba: - case 0x3da: - res = (DWORD)VGA_ioport_in( port ); - break; default: WARN("Direct I/O read attempted from port %x\n", port); res = 0xffffffff; @@ -416,12 +411,11 @@ void IO_outport( int port, int size, DWORD value ) } #endif + /* first give the DOS VM a chance to handle it */ + if (Dosvm.outport && Dosvm.outport( port, size, value )) return; + switch (port) { - case 0x20: - if (Dosvm.Current()) - Dosvm.OutPIC( port, (BYTE)value ); - break; case 0x40: case 0x41: case 0x42: @@ -477,7 +471,7 @@ void IO_outport( int port, int size, DWORD value ) tmr_8253[chan].latched = TRUE; dummy_ctr -= 1 + (int)(10.0 * rand() / (RAND_MAX + 1.0)); if (chan == 0) /* System timer divisor */ - if (Dosvm.Current()) + if (Dosvm.GetTimer) tmr_8253[chan].latch = dummy_ctr + (WORD)Dosvm.GetTimer(); else tmr_8253[chan].latch = dummy_ctr; @@ -511,10 +505,6 @@ void IO_outport( int port, int size, DWORD value ) case 0x71: cmosimage[cmosaddress & 0x3f] = (BYTE)value; break; - case 0x3c8: - case 0x3c9: - VGA_ioport_out( port, (BYTE)value ); - break; default: WARN("Direct I/O write attempted to port %x\n", port ); break;