From 26a42f845284bdf642b863597dcb1a90d17b3e46 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 5 Jan 2010 14:26:05 +0100 Subject: [PATCH] winedos: Merge all of winedos back into krnl386. --- configure | 10 - configure.ac | 2 - dlls/ifsmgr.vxd/Makefile.in | 2 +- dlls/ifsmgr.vxd/ifsmgr.c | 24 +- dlls/krnl386.exe16/Makefile.in | 25 + dlls/{winedos => krnl386.exe16}/dma.c | 0 dlls/{winedos => krnl386.exe16}/dosaspi.c | 0 dlls/{winedos => krnl386.exe16}/dosconf.c | 0 .../devices.c => krnl386.exe16/dosdev.c} | 0 .../module.c => krnl386.exe16/dosexe.c} | 18 +- dlls/{winedos => krnl386.exe16}/dosexe.h | 19 +- dlls/krnl386.exe16/dosmem.c | 503 ++++++++++++++-- dlls/{winedos => krnl386.exe16}/dosvm.c | 25 +- dlls/{winedos => krnl386.exe16}/fpu.c | 0 dlls/krnl386.exe16/global.c | 18 - dlls/krnl386.exe16/instr.c | 33 +- dlls/{winedos => krnl386.exe16}/int09.c | 0 dlls/{winedos => krnl386.exe16}/int10.c | 2 +- dlls/{winedos => krnl386.exe16}/int13.c | 0 dlls/{winedos => krnl386.exe16}/int15.c | 0 dlls/{winedos => krnl386.exe16}/int16.c | 0 dlls/{winedos => krnl386.exe16}/int21.c | 1 + dlls/{winedos => krnl386.exe16}/int25.c | 0 dlls/{winedos => krnl386.exe16}/int26.c | 0 dlls/{winedos => krnl386.exe16}/int2f.c | 52 -- dlls/{winedos => krnl386.exe16}/int31.c | 13 +- dlls/{winedos => krnl386.exe16}/int33.c | 0 dlls/{winedos => krnl386.exe16}/int67.c | 0 dlls/{winedos => krnl386.exe16}/interrupts.c | 19 +- dlls/{winedos => krnl386.exe16}/ioports.c | 9 +- dlls/krnl386.exe16/kernel16_private.h | 59 +- dlls/krnl386.exe16/krnl386.exe16.spec | 4 + dlls/krnl386.exe16/ne_module.c | 1 + dlls/krnl386.exe16/relay.c | 176 +++++- .../{winedos => krnl386.exe16}/soundblaster.c | 0 dlls/{winedos => krnl386.exe16}/timer.c | 0 dlls/{winedos => krnl386.exe16}/vga.c | 0 dlls/{winedos => krnl386.exe16}/vga.h | 0 dlls/krnl386.exe16/vxd.c | 1 + dlls/vwin32.vxd/Makefile.in | 2 +- dlls/vwin32.vxd/vwin32.c | 35 +- dlls/winedos/Makefile.in | 39 -- dlls/winedos/dosmem.c | 551 ------------------ dlls/winedos/relay.c | 204 ------- dlls/winedos/winedos.spec | 13 - dlls/winedos/wprocs.spec | 19 - programs/winevdm/winevdm.c | 14 +- 47 files changed, 738 insertions(+), 1155 deletions(-) rename dlls/{winedos => krnl386.exe16}/dma.c (100%) rename dlls/{winedos => krnl386.exe16}/dosaspi.c (100%) rename dlls/{winedos => krnl386.exe16}/dosconf.c (100%) rename dlls/{winedos/devices.c => krnl386.exe16/dosdev.c} (100%) rename dlls/{winedos/module.c => krnl386.exe16/dosexe.c} (98%) rename dlls/{winedos => krnl386.exe16}/dosexe.h (97%) rename dlls/{winedos => krnl386.exe16}/dosvm.c (97%) rename dlls/{winedos => krnl386.exe16}/fpu.c (100%) rename dlls/{winedos => krnl386.exe16}/int09.c (100%) rename dlls/{winedos => krnl386.exe16}/int10.c (99%) rename dlls/{winedos => krnl386.exe16}/int13.c (100%) rename dlls/{winedos => krnl386.exe16}/int15.c (100%) rename dlls/{winedos => krnl386.exe16}/int16.c (100%) rename dlls/{winedos => krnl386.exe16}/int21.c (99%) rename dlls/{winedos => krnl386.exe16}/int25.c (100%) rename dlls/{winedos => krnl386.exe16}/int26.c (100%) rename dlls/{winedos => krnl386.exe16}/int2f.c (95%) rename dlls/{winedos => krnl386.exe16}/int31.c (99%) rename dlls/{winedos => krnl386.exe16}/int33.c (100%) rename dlls/{winedos => krnl386.exe16}/int67.c (100%) rename dlls/{winedos => krnl386.exe16}/interrupts.c (98%) rename dlls/{winedos => krnl386.exe16}/ioports.c (99%) rename dlls/{winedos => krnl386.exe16}/soundblaster.c (100%) rename dlls/{winedos => krnl386.exe16}/timer.c (100%) rename dlls/{winedos => krnl386.exe16}/vga.c (100%) rename dlls/{winedos => krnl386.exe16}/vga.h (100%) delete mode 100644 dlls/winedos/Makefile.in delete mode 100644 dlls/winedos/dosmem.c delete mode 100644 dlls/winedos/relay.c delete mode 100644 dlls/winedos/winedos.spec delete mode 100644 dlls/winedos/wprocs.spec diff --git a/configure b/configure index 68af9e193fb..46800516d73 100755 --- a/configure +++ b/configure @@ -4102,7 +4102,6 @@ enable_win16=${enable_win16:-no} if test "x$enable_win16" != "xyes" then enable_w32skrnl=${enable_w32skrnl:-no} - enable_winedos=${enable_winedos:-no} enable_winevdm=${enable_winevdm:-no} enable_wow32=${enable_wow32:-no} fi @@ -17009,14 +17008,6 @@ ALL_MAKEFILE_DEPENDS="$ALL_MAKEFILE_DEPENDS dlls/wined3d/Makefile: dlls/wined3d/Makefile.in dlls/Makedll.rules" ac_config_files="$ac_config_files dlls/wined3d/Makefile" -ALL_MAKEFILES="$ALL_MAKEFILES \\ - dlls/winedos/Makefile" -test "x$enable_winedos" != xno && ALL_DLL_DIRS="$ALL_DLL_DIRS \\ - winedos" -ALL_MAKEFILE_DEPENDS="$ALL_MAKEFILE_DEPENDS -dlls/winedos/Makefile: dlls/winedos/Makefile.in dlls/Makedll.rules" -ac_config_files="$ac_config_files dlls/winedos/Makefile" - ALL_MAKEFILES="$ALL_MAKEFILES \\ dlls/wineesd.drv/Makefile" test "x$enable_wineesd_drv" != xno && ALL_DLL_DIRS="$ALL_DLL_DIRS \\ @@ -19161,7 +19152,6 @@ do "dlls/winecoreaudio.drv/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/winecoreaudio.drv/Makefile" ;; "dlls/winecrt0/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/winecrt0/Makefile" ;; "dlls/wined3d/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/wined3d/Makefile" ;; - "dlls/winedos/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/winedos/Makefile" ;; "dlls/wineesd.drv/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/wineesd.drv/Makefile" ;; "dlls/winejack.drv/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/winejack.drv/Makefile" ;; "dlls/winejoystick.drv/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/winejoystick.drv/Makefile" ;; diff --git a/configure.ac b/configure.ac index 03a80d62c9a..417e2456922 100644 --- a/configure.ac +++ b/configure.ac @@ -172,7 +172,6 @@ enable_win16=${enable_win16:-no} if test "x$enable_win16" != "xyes" then enable_w32skrnl=${enable_w32skrnl:-no} - enable_winedos=${enable_winedos:-no} enable_winevdm=${enable_winevdm:-no} enable_wow32=${enable_wow32:-no} fi @@ -2538,7 +2537,6 @@ WINE_CONFIG_MAKEFILE([dlls/wineaudioio.drv/Makefile],[dlls/Makedll.rules],[dlls] WINE_CONFIG_MAKEFILE([dlls/winecoreaudio.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) WINE_CONFIG_MAKEFILE([dlls/winecrt0/Makefile],[dlls/Makeimplib.rules],[dlls],[ALL_IMPLIB_DIRS]) WINE_CONFIG_MAKEFILE([dlls/wined3d/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) -WINE_CONFIG_MAKEFILE([dlls/winedos/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) WINE_CONFIG_MAKEFILE([dlls/wineesd.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) WINE_CONFIG_MAKEFILE([dlls/winejack.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) WINE_CONFIG_MAKEFILE([dlls/winejoystick.drv/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) diff --git a/dlls/ifsmgr.vxd/Makefile.in b/dlls/ifsmgr.vxd/Makefile.in index aace9593ec4..82c3abde2df 100644 --- a/dlls/ifsmgr.vxd/Makefile.in +++ b/dlls/ifsmgr.vxd/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = ifsmgr.vxd -IMPORTS = kernel32 +IMPORTS = kernel32 kernel C_SRCS = \ ifsmgr.c diff --git a/dlls/ifsmgr.vxd/ifsmgr.c b/dlls/ifsmgr.vxd/ifsmgr.c index 1e60ad59898..68c44469b11 100644 --- a/dlls/ifsmgr.vxd/ifsmgr.c +++ b/dlls/ifsmgr.vxd/ifsmgr.c @@ -97,22 +97,7 @@ static void CONTEXT_2_win32apieq(const CONTEXT86 *pCxt, struct win32apireq *pOut /* FIXME: pOut->ar_pad ignored */ } -typedef void (WINAPI *CallBuiltinHandler)( CONTEXT *context, BYTE intnum ); - -static CallBuiltinHandler load_builtin_handler(void) -{ - static CallBuiltinHandler handler; - static BOOL init_done; - - if (!init_done) - { - HMODULE mod = LoadLibraryA( "winedos.dll" ); - if (mod) handler = (void *)GetProcAddress( mod, "CallBuiltinHandler" ); - if (!handler) FIXME( "DOS calls not supported\n" ); - init_done = TRUE; - } - return handler; -} +extern void __wine_call_int_handler( CONTEXT *context, BYTE intnum ); /*********************************************************************** * DeviceIoControl (IFSMGR.VXD.@) @@ -134,9 +119,6 @@ BOOL WINAPI IFSMGR_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpvInBuffer, DW CONTEXT86 cxt; struct win32apireq *pIn=lpvInBuffer; struct win32apireq *pOut=lpvOutBuffer; - CallBuiltinHandler handler; - - if (!(handler = load_builtin_handler())) return FALSE; TRACE( "Control '%s': " "proid=0x%08lx, eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, " @@ -150,9 +132,9 @@ BOOL WINAPI IFSMGR_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpvInBuffer, DW win32apieq_2_CONTEXT(pIn,&cxt); if(dwIoControlCode==IFS_IOCTL_21) - handler( &cxt, 0x21 ); + __wine_call_int_handler( &cxt, 0x21 ); else - handler( &cxt, 0x2f ); + __wine_call_int_handler( &cxt, 0x2f ); CONTEXT_2_win32apieq(&cxt,pOut); return TRUE; diff --git a/dlls/krnl386.exe16/Makefile.in b/dlls/krnl386.exe16/Makefile.in index a4edaa08e49..be18b05b670 100644 --- a/dlls/krnl386.exe16/Makefile.in +++ b/dlls/krnl386.exe16/Makefile.in @@ -5,17 +5,39 @@ VPATH = @srcdir@ MODULE = krnl386.exe16 IMPORTLIB = kernel IMPORTS = kernel32 ntdll +DELAYIMPORTS = ddraw dsound user32 EXTRAIMPLIBFLAGS = --subsystem win16 EXTRADLLFLAGS = -Wb,--subsystem,win16,--dll-name,kernel EXTRARCFLAGS = -O res16 C_SRCS = \ atom.c \ + dma.c \ + dosaspi.c \ + dosconf.c \ + dosdev.c \ + dosexe.c \ dosmem.c \ + dosvm.c \ error.c \ file.c \ + fpu.c \ global.c \ instr.c \ + int09.c \ + int10.c \ + int13.c \ + int15.c \ + int16.c \ + int21.c \ + int25.c \ + int26.c \ + int2f.c \ + int31.c \ + int33.c \ + int67.c \ + interrupts.c \ + ioports.c \ kernel.c \ local.c \ ne_module.c \ @@ -25,10 +47,13 @@ C_SRCS = \ resource.c \ selector.c \ snoop.c \ + soundblaster.c \ syslevel.c \ task.c \ thunk.c \ + timer.c \ utthunk.c \ + vga.c \ vxd.c \ wowthunk.c diff --git a/dlls/winedos/dma.c b/dlls/krnl386.exe16/dma.c similarity index 100% rename from dlls/winedos/dma.c rename to dlls/krnl386.exe16/dma.c diff --git a/dlls/winedos/dosaspi.c b/dlls/krnl386.exe16/dosaspi.c similarity index 100% rename from dlls/winedos/dosaspi.c rename to dlls/krnl386.exe16/dosaspi.c diff --git a/dlls/winedos/dosconf.c b/dlls/krnl386.exe16/dosconf.c similarity index 100% rename from dlls/winedos/dosconf.c rename to dlls/krnl386.exe16/dosconf.c diff --git a/dlls/winedos/devices.c b/dlls/krnl386.exe16/dosdev.c similarity index 100% rename from dlls/winedos/devices.c rename to dlls/krnl386.exe16/dosdev.c diff --git a/dlls/winedos/module.c b/dlls/krnl386.exe16/dosexe.c similarity index 98% rename from dlls/winedos/module.c rename to dlls/krnl386.exe16/dosexe.c index a4d9c51a1f4..c16d0df6241 100644 --- a/dlls/winedos/module.c +++ b/dlls/krnl386.exe16/dosexe.c @@ -46,6 +46,7 @@ #include "winuser.h" #include "winerror.h" #include "wine/debug.h" +#include "kernel16_private.h" #include "dosexe.h" #include "vga.h" @@ -77,14 +78,6 @@ void DOSVM_Exit( WORD retval ) #ifdef MZ_SUPPORTED -#ifdef HAVE_SYS_MMAN_H -# include -#endif - -/* define this to try mapping through /proc/pid/mem instead of a temp file, - but Linus doesn't like mmapping /proc/pid/mem, so it doesn't work for me */ -#undef MZ_MAPSELF - #define BIOS_DATA_SEGMENT 0x40 #define PSP_SIZE 0x10 @@ -362,12 +355,12 @@ load_error: } /*********************************************************************** - * wine_load_dos_exe (WINEDOS.@) + * __wine_load_dos_exe (KERNEL.@) * * Called from WineVDM when a new real-mode DOS process is started. * Loads DOS program into memory and executes the program. */ -void WINAPI wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline ) +void __wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline ) { char dos_cmdtail[126]; int dos_length = 0; @@ -376,6 +369,7 @@ void WINAPI wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline ) NULL, OPEN_EXISTING, 0, 0 ); if (hFile == INVALID_HANDLE_VALUE) return; DOSVM_isdosexe = TRUE; + DOSMEM_InitDosMemory(); if(cmdline && *cmdline) { @@ -757,9 +751,9 @@ BOOL MZ_Current( void ) #else /* !MZ_SUPPORTED */ /*********************************************************************** - * wine_load_dos_exe (WINEDOS.@) + * __wine_load_dos_exe (KERNEL.@) */ -void WINAPI wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline ) +void __wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline ) { FIXME("DOS executables not supported on this platform\n"); SetLastError(ERROR_BAD_FORMAT); diff --git a/dlls/winedos/dosexe.h b/dlls/krnl386.exe16/dosexe.h similarity index 97% rename from dlls/winedos/dosexe.h rename to dlls/krnl386.exe16/dosexe.h index 29cf8a0ec16..d25a411c13e 100644 --- a/dlls/winedos/dosexe.h +++ b/dlls/krnl386.exe16/dosexe.h @@ -352,7 +352,7 @@ typedef struct RMCBPROC interrupt; } WINEDEV; -/* module.c */ +/* dosexe.c */ extern BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk ); extern void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval ); extern BOOL MZ_Current( void ); @@ -371,6 +371,7 @@ extern void DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data extern void DOSVM_PIC_ioport_out( WORD port, BYTE val ); extern void DOSVM_SetTimer( UINT ticks ); extern LPVOID DOSVM_AllocDataUMB(DWORD, WORD *, WORD *); +extern void DOSVM_InitSegments(void); /* devices.c */ extern void DOSDEV_InstallDOSDevices(void); @@ -391,13 +392,6 @@ extern void DOSVM_ASPIHandler(CONTEXT86*); extern DOSCONF *DOSCONF_GetConfig( void ); /* dosmem.c */ -extern BOOL DOSMEM_InitDosMemory(void); -extern BOOL DOSMEM_MapDosLayout(void); -extern WORD DOSMEM_AllocSelector(WORD); /* FIXME: to be removed */ -extern LPVOID DOSMEM_AllocBlock(UINT size, WORD* p); -extern BOOL DOSMEM_FreeBlock(void* ptr); -extern UINT DOSMEM_ResizeBlock(void* ptr, UINT size, BOOL exact); -extern UINT DOSMEM_Available(void); extern BIOSDATA *DOSVM_BiosData( void ); /* fpu.c */ @@ -466,8 +460,9 @@ extern void WINAPI DOSVM_Int67Handler(CONTEXT86*); extern void EMS_Ioctl_Handler(CONTEXT86*); /* interrupts.c */ -extern void WINAPI DOSVM_CallBuiltinHandler( CONTEXT86 *, BYTE ); -extern BOOL WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *, BYTE ); +extern void __wine_call_int_handler( CONTEXT86 *, BYTE ); +extern void DOSVM_CallBuiltinHandler( CONTEXT86 *, BYTE ); +extern BOOL DOSVM_EmulateInterruptPM( CONTEXT86 *, BYTE ); extern BOOL DOSVM_EmulateInterruptRM( CONTEXT86 *, BYTE ); extern FARPROC16 DOSVM_GetPMHandler16( BYTE ); extern FARPROC48 DOSVM_GetPMHandler48( BYTE ); @@ -478,6 +473,10 @@ extern void DOSVM_SetPMHandler16( BYTE, FARPROC16 ); extern void DOSVM_SetPMHandler48( BYTE, FARPROC48 ); extern void DOSVM_SetRMHandler( BYTE, FARPROC16 ); +/* ioports.c */ +extern DWORD DOSVM_inport( int port, int size ); +extern void DOSVM_outport( int port, int size, DWORD value ); + /* relay.c */ void DOSVM_RelayHandler( CONTEXT86 * ); void DOSVM_BuildCallFrame( CONTEXT86 *, DOSRELAY, LPVOID ); diff --git a/dlls/krnl386.exe16/dosmem.c b/dlls/krnl386.exe16/dosmem.c index 5e84d237e9c..c73faf14b96 100644 --- a/dlls/krnl386.exe16/dosmem.c +++ b/dlls/krnl386.exe16/dosmem.c @@ -38,6 +38,7 @@ #include "wine/winbase16.h" #include "kernel16_private.h" +#include "dosexe.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(dosmem); @@ -51,6 +52,48 @@ WORD DOSMEM_BiosSysSeg; /* BIOS ROM segment at 0xf000:0 */ #define DOSMEM_SIZE 0x110000 #define DOSMEM_64KB 0x10000 +/* + * Memory Control Block (MCB) definition + * FIXME: implement Allocation Strategy + */ + +#define MCB_DUMP(mc) \ + TRACE ("MCB_DUMP base=%p type=%02xh psp=%04xh size=%04xh\n", mc, mc->type, mc->psp , mc->size ) + +#define MCB_NEXT(mc) \ + (MCB*) ((mc->type==MCB_TYPE_LAST) ? NULL : (char*)(mc) + ((mc->size + 1) << 4) ) + +/* FIXME: should we check more? */ +#define MCB_VALID(mc) \ + ((mc->type==MCB_TYPE_NORMAL) || (mc->type==MCB_TYPE_LAST)) + + +#define MCB_TYPE_NORMAL 0x4d +#define MCB_TYPE_LAST 0x5a + +#define MCB_PSP_DOS 0x0060 +#define MCB_PSP_FREE 0 + +#include "pshpack1.h" +typedef struct { + BYTE type; + WORD psp; /* segment of owner psp */ + WORD size; /* in paragraphs */ + BYTE pad[3]; + BYTE name[8]; +} MCB; +#include "poppack.h" + +/* +#define __DOSMEM_DEBUG__ + */ + +#define VM_STUB(x) (0x90CF00CD|(x<<8)) /* INT x; IRET; NOP */ +#define VM_STUB_SEGMENT 0xf000 /* BIOS segment */ + +/* FIXME: this should be moved to the LOL */ +static MCB* DOSMEM_root_block; + /* when looking at DOS and real mode memory, we activate in three different * modes, depending the situation. * 1/ By default (protected mode), the first MB of memory (actually 0x110000, @@ -71,55 +114,232 @@ WORD DOSMEM_BiosSysSeg; /* BIOS ROM segment at 0xf000:0 */ /* DOS memory base (linear in process address space) */ static char *DOSMEM_dosmem; +static char *DOSMEM_sysmem; /* number of bytes protected from _dosmem. 0 when DOS memory is initialized, * 64k otherwise to trap NULL pointers deref */ static DWORD DOSMEM_protect; static LONG WINAPI dosmem_handler(EXCEPTION_POINTERS* except); -struct winedos_exports winedos; - -BOOL load_winedos(void) +/*********************************************************************** + * DOSMEM_FillIsrTable + * + * Fill the interrupt table with fake BIOS calls to BIOSSEG (0xf000). + * + * NOTES: + * Linux normally only traps INTs performed from or destined to BIOSSEG + * for us to handle, if the int_revectored table is empty. Filling the + * interrupt table with calls to INT stubs in BIOSSEG allows DOS programs + * to hook interrupts, as well as use their familiar retf tricks to call + * them, AND let Wine handle any unhooked interrupts transparently. + */ +static void DOSMEM_FillIsrTable(void) { - static HANDLE hRunOnce /* = 0 */; - static HMODULE hWineDos /* = 0 */; + SEGPTR *isr = (SEGPTR*)DOSMEM_sysmem; + int x; - /* FIXME: this isn't 100% thread safe, as we won't catch access to 1MB while - * loading winedos (and may return uninitialized valued) + for (x=0; x<256; x++) isr[x]=MAKESEGPTR(VM_STUB_SEGMENT,x*4); +} + +static void DOSMEM_MakeIsrStubs(void) +{ + DWORD *stub = (DWORD*)(DOSMEM_dosmem + (VM_STUB_SEGMENT << 4)); + int x; + + for (x=0; x<256; x++) stub[x]=VM_STUB(x); +} + +BIOSDATA* DOSVM_BiosData(void) +{ + return (BIOSDATA *)(DOSMEM_sysmem + 0x400); +} + +/********************************************************************** + * DOSMEM_GetTicksSinceMidnight + * + * Return number of clock ticks since midnight. + */ +static DWORD DOSMEM_GetTicksSinceMidnight(void) +{ + SYSTEMTIME time; + + /* This should give us the (approximately) correct + * 18.206 clock ticks per second since midnight. */ - if (hWineDos) goto done; + + GetLocalTime( &time ); + + return (((time.wHour * 3600 + time.wMinute * 60 + + time.wSecond) * 18206) / 1000) + + (time.wMilliseconds * 1000 / 54927); +} + +/*********************************************************************** + * DOSMEM_FillBiosSegments + * + * Fill the BIOS data segment with dummy values. + */ +static void DOSMEM_FillBiosSegments(void) +{ + BYTE *pBiosSys = (BYTE*)DOSMEM_dosmem + 0xf0000; + BYTE *pBiosROMTable = pBiosSys+0xe6f5; + BIOSDATA *pBiosData = DOSVM_BiosData(); + static const char bios_date[] = "13/01/99"; + + /* Clear all unused values */ + memset( pBiosData, 0, sizeof(*pBiosData) ); + + /* FIXME: should check the number of configured drives and ports */ + pBiosData->Com1Addr = 0x3f8; + pBiosData->Com2Addr = 0x2f8; + pBiosData->Lpt1Addr = 0x378; + pBiosData->Lpt2Addr = 0x278; + pBiosData->InstalledHardware = 0x5463; + pBiosData->MemSize = 640; + pBiosData->NextKbdCharPtr = 0x1e; + pBiosData->FirstKbdCharPtr = 0x1e; + pBiosData->VideoMode = 3; + pBiosData->VideoColumns = 80; + pBiosData->VideoPageSize = 80 * 25 * 2; + pBiosData->VideoPageStartAddr = 0xb800; + pBiosData->VideoCtrlAddr = 0x3d4; + pBiosData->Ticks = DOSMEM_GetTicksSinceMidnight(); + pBiosData->NbHardDisks = 2; + pBiosData->KbdBufferStart = 0x1e; + pBiosData->KbdBufferEnd = 0x3e; + pBiosData->RowsOnScreenMinus1 = 24; + pBiosData->BytesPerChar = 0x10; + pBiosData->ModeOptions = 0x64; + pBiosData->FeatureBitsSwitches = 0xf9; + pBiosData->VGASettings = 0x51; + pBiosData->DisplayCombination = 0x08; + pBiosData->DiskDataRate = 0; + + /* fill ROM configuration table (values from Award) */ + *(pBiosROMTable+0x0) = 0x08; /* number of bytes following LO */ + *(pBiosROMTable+0x1) = 0x00; /* number of bytes following HI */ + *(pBiosROMTable+0x2) = 0xfc; /* model */ + *(pBiosROMTable+0x3) = 0x01; /* submodel */ + *(pBiosROMTable+0x4) = 0x00; /* BIOS revision */ + *(pBiosROMTable+0x5) = 0x74; /* feature byte 1 */ + *(pBiosROMTable+0x6) = 0x00; /* feature byte 2 */ + *(pBiosROMTable+0x7) = 0x00; /* feature byte 3 */ + *(pBiosROMTable+0x8) = 0x00; /* feature byte 4 */ + *(pBiosROMTable+0x9) = 0x00; /* feature byte 5 */ + + /* BIOS date string */ + memcpy(pBiosSys+0xfff5, bios_date, sizeof bios_date); + + /* BIOS ID */ + *(pBiosSys+0xfffe) = 0xfc; + + /* Reboot vector (f000:fff0 or ffff:0000) */ + *(DWORD*)(pBiosSys + 0xfff0) = VM_STUB(0x19); +} + +/*********************************************************************** + * BiosTick + * + * Increment the BIOS tick counter. Called by timer signal handler. + */ +static void CALLBACK BiosTick( LPVOID arg, DWORD low, DWORD high ) +{ + BIOSDATA *pBiosData = arg; + pBiosData->Ticks++; +} + +/*********************************************************************** + * timer_thread + */ +static DWORD CALLBACK timer_thread( void *arg ) +{ + LARGE_INTEGER when; + HANDLE timer; + + if (!(timer = CreateWaitableTimerA( NULL, FALSE, NULL ))) return 0; + + when.u.LowPart = when.u.HighPart = 0; + SetWaitableTimer( timer, &when, 55 /* actually 54.925 */, BiosTick, arg, FALSE ); + for (;;) SleepEx( INFINITE, TRUE ); +} + +/*********************************************************************** + * DOSMEM_Collapse + * + * Helper function for internal use only. + * Attach all following free blocks to this one, even if this one is not free. + */ +static void DOSMEM_Collapse( MCB* mcb ) +{ + MCB* next = MCB_NEXT( mcb ); + + while (next && next->psp == MCB_PSP_FREE) + { + mcb->size = mcb->size + next->size + 1; + mcb->type = next->type; /* make sure keeping MCB_TYPE_LAST */ + next = MCB_NEXT( next ); + } +} + +/****************************************************************** + * DOSMEM_InitDosMemory + */ +BOOL DOSMEM_InitDosMemory(void) +{ + static int done; + static HANDLE hRunOnce; + + if (done) return TRUE; + + /* FIXME: this isn't 100% thread safe, as we won't catch accesses while initializing */ if (hRunOnce == 0) { HANDLE hEvent = CreateEventW( NULL, TRUE, FALSE, NULL ); if (InterlockedCompareExchangePointer( &hRunOnce, hEvent, 0 ) == 0) { - HMODULE hModule; + BOOL ret; + DWORD reserve; /* ok, we're the winning thread */ - if (!VirtualProtect( DOSMEM_dosmem + DOSMEM_protect, - DOSMEM_SIZE - DOSMEM_protect, - PAGE_READWRITE, NULL ) || - !(hModule = LoadLibraryA( "winedos.dll" ))) - { - ERR("Could not load winedos.dll, DOS subsystem unavailable\n"); - hModule = (HMODULE)1; /* not to try to load it again */ - } - else - { -#define GET_ADDR(func) winedos.func = (void *)GetProcAddress( hModule, #func ); - GET_ADDR(AllocDosBlock); - GET_ADDR(FreeDosBlock); - GET_ADDR(ResizeDosBlock); - GET_ADDR(inport); - GET_ADDR(outport); - GET_ADDR(EmulateInterruptPM); - GET_ADDR(CallBuiltinHandler); -#undef GET_ADDR - } + if (!(ret = VirtualProtect( DOSMEM_dosmem + DOSMEM_protect, + DOSMEM_SIZE - DOSMEM_protect, + PAGE_READWRITE, NULL ))) + ERR("Cannot load access low 1Mb, DOS subsystem unavailable\n"); RtlRemoveVectoredExceptionHandler( dosmem_handler ); - hWineDos = hModule; + + /* + * Reserve either: + * - lowest 64k for NULL pointer catching (Win16) + * - lowest 1k for interrupt handlers and + * another 0.5k for BIOS, DOS and intra-application + * areas (DOS) + */ + if (DOSMEM_dosmem != DOSMEM_sysmem) + reserve = 0x10000; /* 64k */ + else + reserve = 0x600; /* 1.5k */ + + /* + * Set DOS memory base and initialize conventional memory. + */ + DOSMEM_FillBiosSegments(); + DOSMEM_FillIsrTable(); + + /* align root block to paragraph */ + DOSMEM_root_block = (MCB*)(DOSMEM_dosmem + reserve); + DOSMEM_root_block->type = MCB_TYPE_LAST; + DOSMEM_root_block->psp = MCB_PSP_FREE; + DOSMEM_root_block->size = (DOSMEM_dosmem + 0x9fffc - ((char*)DOSMEM_root_block)) >> 4; + + TRACE("DOS conventional memory initialized, %d bytes free.\n", + DOSMEM_Available()); + + DOSVM_InitSegments(); + CloseHandle( CreateThread( NULL, 0, timer_thread, DOSVM_BiosData(), 0, NULL )); + SetEvent( hRunOnce ); - goto done; + done = 1; + return ret; } /* someone beat us here... */ CloseHandle( hEvent ); @@ -127,8 +347,7 @@ BOOL load_winedos(void) /* and wait for the winner to have finished */ WaitForSingleObject( hRunOnce, INFINITE ); - done: - return (hWineDos != (HMODULE)1); + return TRUE; } /****************************************************************** @@ -143,7 +362,7 @@ static LONG WINAPI dosmem_handler(EXCEPTION_POINTERS* except) char *addr = (char *)except->ExceptionRecord->ExceptionInformation[1]; if (addr >= DOSMEM_dosmem + DOSMEM_protect && addr < DOSMEM_dosmem + DOSMEM_SIZE) { - if (load_winedos()) return EXCEPTION_CONTINUE_EXECUTION; + if (DOSMEM_InitDosMemory()) return EXCEPTION_CONTINUE_EXECUTION; } } return EXCEPTION_CONTINUE_SEARCH; @@ -157,7 +376,6 @@ static LONG WINAPI dosmem_handler(EXCEPTION_POINTERS* except) */ BOOL DOSMEM_Init(void) { - char *sysmem; void *addr = (void *)1; SIZE_T size = DOSMEM_SIZE - 1; @@ -172,20 +390,20 @@ BOOL DOSMEM_Init(void) { DOSMEM_dosmem = 0; DOSMEM_protect = DOSMEM_64KB; - sysmem = (char *)0xf0000; /* store sysmem in high addresses for now */ + DOSMEM_sysmem = (char *)0xf0000; /* store sysmem in high addresses for now */ } else { WARN( "First megabyte not available for DOS address space.\n" ); DOSMEM_dosmem = addr; DOSMEM_protect = 0; - sysmem = DOSMEM_dosmem; + DOSMEM_sysmem = DOSMEM_dosmem; } RtlAddVectoredExceptionHandler(FALSE, dosmem_handler); - DOSMEM_0000H = GLOBAL_CreateBlock( GMEM_FIXED, sysmem, + DOSMEM_0000H = GLOBAL_CreateBlock( GMEM_FIXED, DOSMEM_sysmem, DOSMEM_64KB, 0, WINE_LDT_FLAGS_DATA ); - DOSMEM_BiosDataSeg = GLOBAL_CreateBlock( GMEM_FIXED, sysmem + 0x400, + DOSMEM_BiosDataSeg = GLOBAL_CreateBlock( GMEM_FIXED, DOSMEM_sysmem + 0x400, 0x100, 0, WINE_LDT_FLAGS_DATA ); DOSMEM_BiosSysSeg = GLOBAL_CreateBlock( GMEM_FIXED, DOSMEM_dosmem + 0xf0000, DOSMEM_64KB, 0, WINE_LDT_FLAGS_DATA ); @@ -232,3 +450,210 @@ LPVOID DOSMEM_MapRealToLinear(DWORD x) TRACE_(selector)("(0x%08x) returns %p.\n", x, lin ); return lin; } + +/*********************************************************************** + * DOSMEM_AllocBlock + * + * Carve a chunk of the DOS memory block (without selector). + */ +LPVOID DOSMEM_AllocBlock(UINT size, UINT16* pseg) +{ + MCB *curr; + MCB *next = NULL; + WORD psp = DOSVM_psp; + + DOSMEM_InitDosMemory(); + + curr = DOSMEM_root_block; + if (!(psp = DOSVM_psp)) psp = MCB_PSP_DOS; + + *pseg = 0; + + TRACE( "(%04xh)\n", size ); + + /* round up to paragraph */ + size = (size + 15) >> 4; + +#ifdef __DOSMEM_DEBUG__ + DOSMEM_Available(); /* checks the whole MCB list */ +#endif + + /* loop over all MCB and search the next large enough MCB */ + while (curr) + { + if (!MCB_VALID (curr)) + { + ERR( "MCB List Corrupt\n" ); + MCB_DUMP( curr ); + return NULL; + } + if (curr->psp == MCB_PSP_FREE) + { + DOSMEM_Collapse( curr ); + /* is it large enough (one paragraph for the MCB)? */ + if (curr->size >= size) + { + if (curr->size > size) + { + /* split curr */ + next = (MCB *) ((char*) curr + ((size+1) << 4)); + next->psp = MCB_PSP_FREE; + next->size = curr->size - (size+1); + next->type = curr->type; + curr->type = MCB_TYPE_NORMAL; + curr->size = size; + } + /* curr is the found block */ + curr->psp = psp; + if( pseg ) *pseg = (((char*)curr) + 16 - DOSMEM_dosmem) >> 4; + return (LPVOID) ((char*)curr + 16); + } + } + curr = MCB_NEXT(curr); + } + return NULL; +} + +/*********************************************************************** + * DOSMEM_FreeBlock + */ +BOOL DOSMEM_FreeBlock(void* ptr) +{ + MCB* mcb = (MCB*) ((char*)ptr - 16); + + TRACE( "(%p)\n", ptr ); + +#ifdef __DOSMEM_DEBUG__ + DOSMEM_Available(); +#endif + + if (!MCB_VALID (mcb)) + { + ERR( "MCB invalid\n" ); + MCB_DUMP( mcb ); + return FALSE; + } + + mcb->psp = MCB_PSP_FREE; + DOSMEM_Collapse( mcb ); + return TRUE; +} + +/*********************************************************************** + * DOSMEM_ResizeBlock + * + * Resize DOS memory block in place. Returns block size or -1 on error. + * + * If exact is TRUE, returned value is either old or requested block + * size. If exact is FALSE, block is expanded even if there is not + * enough space for full requested block size. + * + * TODO: return also biggest block size + */ +UINT DOSMEM_ResizeBlock(void *ptr, UINT size, BOOL exact) +{ + MCB* mcb = (MCB*) ((char*)ptr - 16); + MCB* next; + + TRACE( "(%p,%04xh,%s)\n", ptr, size, exact ? "TRUE" : "FALSE" ); + + /* round up to paragraph */ + size = (size + 15) >> 4; + +#ifdef __DOSMEM_DEBUG__ + DOSMEM_Available(); +#endif + + if (!MCB_VALID (mcb)) + { + ERR( "MCB invalid\n" ); + MCB_DUMP( mcb ); + return -1; + } + + /* resize needed? */ + if (mcb->size == size) + return size << 4; + + /* collapse free blocks */ + DOSMEM_Collapse( mcb ); + + /* shrink mcb ? */ + if (mcb->size > size) + { + next = (MCB *) ((char*)mcb + ((size+1) << 4)); + next->type = mcb->type; + next->psp = MCB_PSP_FREE; + next->size = mcb->size - (size+1); + mcb->type = MCB_TYPE_NORMAL; + mcb->size = size; + return size << 4; + } + + if (!exact) + { + return mcb->size << 4; + } + + return -1; +} + +/*********************************************************************** + * DOSMEM_Available + */ +UINT DOSMEM_Available(void) +{ + UINT available = 0; + UINT total = 0; + MCB *curr = DOSMEM_root_block; + /* loop over all MCB and search the largest free MCB */ + while (curr) + { +#ifdef __DOSMEM_DEBUG__ + MCB_DUMP( curr ); +#endif + if (!MCB_VALID (curr)) + { + ERR( "MCB List Corrupt\n" ); + MCB_DUMP( curr ); + return 0; + } + if (curr->psp == MCB_PSP_FREE && + curr->size > available ) + available = curr->size; + + total += curr->size + 1; + curr = MCB_NEXT( curr ); + } + TRACE( " %04xh of %04xh paragraphs available\n", available, total ); + return available << 4; +} + +/****************************************************************** + * DOSMEM_MapDosLayout + * + * Initialize the first MB of memory to look like a real DOS setup + */ +BOOL DOSMEM_MapDosLayout(void) +{ + static int already_mapped; + + if (!already_mapped) + { + if (DOSMEM_dosmem || !VirtualProtect( NULL, DOSMEM_SIZE, PAGE_EXECUTE_READWRITE, NULL )) + { + ERR( "Need full access to the first megabyte for DOS mode\n" ); + ExitProcess(1); + } + /* copy the BIOS and ISR area down */ + memcpy( DOSMEM_dosmem, DOSMEM_sysmem, 0x400 + 0x100 ); + DOSMEM_sysmem = DOSMEM_dosmem; + SetSelectorBase( DOSMEM_0000H, 0 ); + SetSelectorBase( DOSMEM_BiosDataSeg, 0x400 ); + /* we may now need the actual interrupt stubs, and since we've just moved the + * interrupt vector table away, we can fill the area with stubs instead... */ + DOSMEM_MakeIsrStubs(); + already_mapped = 1; + } + return TRUE; +} diff --git a/dlls/winedos/dosvm.c b/dlls/krnl386.exe16/dosvm.c similarity index 97% rename from dlls/winedos/dosvm.c rename to dlls/krnl386.exe16/dosvm.c index fdd677f08e3..3db06498f94 100644 --- a/dlls/winedos/dosvm.c +++ b/dlls/krnl386.exe16/dosvm.c @@ -825,7 +825,7 @@ LPVOID DOSVM_AllocDataUMB( DWORD size, WORD *segment, WORD *selector ) * Initializes DOSVM_dpmi_segments. Allocates required memory and * sets up segments and selectors for accessing the memory. */ -static void DOSVM_InitSegments(void) +void DOSVM_InitSegments(void) { LPSTR ptr; int i; @@ -967,25 +967,6 @@ static void DOSVM_InitSegments(void) * As we store code in UMB we should make sure it is executable */ VirtualProtect((void *)DOSVM_UMB_BOTTOM, DOSVM_UMB_TOP - DOSVM_UMB_BOTTOM, PAGE_EXECUTE_READWRITE, NULL); -} - - -/********************************************************************** - * DllMain (DOSVM.0) - */ -BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) -{ - TRACE_(module)("(%p,%d,%p)\n", hinstDLL, fdwReason, lpvReserved); - - if (fdwReason == DLL_PROCESS_ATTACH) - { - DisableThreadLibraryCalls(hinstDLL); - if (!DOSMEM_InitDosMemory()) return FALSE; - DOSVM_InitSegments(); - - event_notifier = CreateEventW(NULL, FALSE, FALSE, NULL); - if(!event_notifier) - ERR("Failed to create event object!\n"); - } - return TRUE; + + event_notifier = CreateEventW(NULL, FALSE, FALSE, NULL); } diff --git a/dlls/winedos/fpu.c b/dlls/krnl386.exe16/fpu.c similarity index 100% rename from dlls/winedos/fpu.c rename to dlls/krnl386.exe16/fpu.c diff --git a/dlls/krnl386.exe16/global.c b/dlls/krnl386.exe16/global.c index f0d1af78f23..db07477b5ec 100644 --- a/dlls/krnl386.exe16/global.c +++ b/dlls/krnl386.exe16/global.c @@ -74,24 +74,6 @@ static int globalArenaSize; #define VALID_HANDLE(handle) (((handle)>>__AHSHIFT)> __AHSHIFT)) -static inline void* DOSMEM_AllocBlock(UINT size, UINT16* pseg) -{ - if (!winedos.AllocDosBlock) load_winedos(); - return winedos.AllocDosBlock ? winedos.AllocDosBlock(size, pseg) : NULL; -} - -static inline BOOL DOSMEM_FreeBlock(void* ptr) -{ - if (!winedos.FreeDosBlock) load_winedos(); - return winedos.FreeDosBlock ? winedos.FreeDosBlock( ptr ) : FALSE; -} - -static inline UINT DOSMEM_ResizeBlock(void *ptr, UINT size, BOOL exact) -{ - if (!winedos.ResizeDosBlock) load_winedos(); - return winedos.ResizeDosBlock ? winedos.ResizeDosBlock(ptr, size, TRUE) : 0; -} - static HANDLE get_win16_heap(void) { static HANDLE win16_heap; diff --git a/dlls/krnl386.exe16/instr.c b/dlls/krnl386.exe16/instr.c index 8fe4e9915ba..6ba985cf31d 100644 --- a/dlls/krnl386.exe16/instr.c +++ b/dlls/krnl386.exe16/instr.c @@ -32,6 +32,7 @@ #include "excpt.h" #include "wine/debug.h" #include "kernel16_private.h" +#include "dosexe.h" #include "wine/exception.h" WINE_DEFAULT_DEBUG_CHANNEL(int); @@ -361,10 +362,7 @@ static BOOL INSTR_EmulateLDS( CONTEXT86 *context, BYTE *instr, int long_op, */ static DWORD INSTR_inport( WORD port, int size, CONTEXT86 *context ) { - DWORD res = ~0U; - - if (!winedos.inport) load_winedos(); - if (winedos.inport) res = winedos.inport( port, size ); + DWORD res = DOSVM_inport( port, size ); if (TRACE_ON(io)) { @@ -395,8 +393,7 @@ static DWORD INSTR_inport( WORD port, int size, CONTEXT86 *context ) */ static void INSTR_outport( WORD port, int size, DWORD val, CONTEXT86 *context ) { - if (!winedos.outport) load_winedos(); - if (winedos.outport) winedos.outport( port, size, val ); + DOSVM_outport( port, size, val ); if (TRACE_ON(io)) { @@ -761,13 +758,9 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT86 *context ) break; /* Unable to emulate it */ case 0xcd: /* int */ - if (!winedos.EmulateInterruptPM) load_winedos(); - if (winedos.EmulateInterruptPM) - { - context->Eip += prefixlen + 2; - if (winedos.EmulateInterruptPM( context, instr[1] )) return ExceptionContinueExecution; - context->Eip -= prefixlen + 2; /* restore eip */ - } + context->Eip += prefixlen + 2; + if (DOSVM_EmulateInterruptPM( context, instr[1] )) return ExceptionContinueExecution; + context->Eip -= prefixlen + 2; /* restore eip */ break; /* Unable to emulate it */ case 0xcf: /* iret */ @@ -884,22 +877,12 @@ LONG CALLBACK INSTR_vectored_handler( EXCEPTION_POINTERS *ptrs ) } -/*********************************************************************** - * INSTR_CallBuiltinHandler - */ -static void INSTR_CallBuiltinHandler( CONTEXT86 *context, BYTE intnum ) -{ - if (!winedos.CallBuiltinHandler) load_winedos(); - if (winedos.CallBuiltinHandler) winedos.CallBuiltinHandler( context, intnum ); -} - - /*********************************************************************** * DOS3Call (KERNEL.102) */ void WINAPI DOS3Call( CONTEXT86 *context ) { - INSTR_CallBuiltinHandler( context, 0x21 ); + __wine_call_int_handler( context, 0x21 ); } @@ -908,7 +891,7 @@ void WINAPI DOS3Call( CONTEXT86 *context ) */ void WINAPI NetBIOSCall16( CONTEXT86 *context ) { - INSTR_CallBuiltinHandler( context, 0x5c ); + __wine_call_int_handler( context, 0x5c ); } diff --git a/dlls/winedos/int09.c b/dlls/krnl386.exe16/int09.c similarity index 100% rename from dlls/winedos/int09.c rename to dlls/krnl386.exe16/int09.c diff --git a/dlls/winedos/int10.c b/dlls/krnl386.exe16/int10.c similarity index 99% rename from dlls/winedos/int10.c rename to dlls/krnl386.exe16/int10.c index 52fe65730fc..2e47a4c378b 100644 --- a/dlls/winedos/int10.c +++ b/dlls/krnl386.exe16/int10.c @@ -620,7 +620,7 @@ static void INT10_FillStateInformation( BYTE *buffer, BIOSDATA *data ) /********************************************************************** * INT10_GetHeap */ -INT10_HEAP *INT10_GetHeap( void ) +static INT10_HEAP *INT10_GetHeap( void ) { static INT10_HEAP *heap_pointer = 0; diff --git a/dlls/winedos/int13.c b/dlls/krnl386.exe16/int13.c similarity index 100% rename from dlls/winedos/int13.c rename to dlls/krnl386.exe16/int13.c diff --git a/dlls/winedos/int15.c b/dlls/krnl386.exe16/int15.c similarity index 100% rename from dlls/winedos/int15.c rename to dlls/krnl386.exe16/int15.c diff --git a/dlls/winedos/int16.c b/dlls/krnl386.exe16/int16.c similarity index 100% rename from dlls/winedos/int16.c rename to dlls/krnl386.exe16/int16.c diff --git a/dlls/winedos/int21.c b/dlls/krnl386.exe16/int21.c similarity index 99% rename from dlls/winedos/int21.c rename to dlls/krnl386.exe16/int21.c index e85ad73664a..4f7ae02212f 100644 --- a/dlls/winedos/int21.c +++ b/dlls/krnl386.exe16/int21.c @@ -40,6 +40,7 @@ #include "winreg.h" #include "winternl.h" #include "wine/winbase16.h" +#include "kernel16_private.h" #include "dosexe.h" #include "winerror.h" #include "winuser.h" diff --git a/dlls/winedos/int25.c b/dlls/krnl386.exe16/int25.c similarity index 100% rename from dlls/winedos/int25.c rename to dlls/krnl386.exe16/int25.c diff --git a/dlls/winedos/int26.c b/dlls/krnl386.exe16/int26.c similarity index 100% rename from dlls/winedos/int26.c rename to dlls/krnl386.exe16/int26.c diff --git a/dlls/winedos/int2f.c b/dlls/krnl386.exe16/int2f.c similarity index 95% rename from dlls/winedos/int2f.c rename to dlls/krnl386.exe16/int2f.c index cab7391796e..43d10d9f7f2 100644 --- a/dlls/winedos/int2f.c +++ b/dlls/krnl386.exe16/int2f.c @@ -63,58 +63,6 @@ typedef struct static void do_int2f_16( CONTEXT86 *context ); static void MSCDEX_Handler( CONTEXT86 *context ); -/*********************************************************************** - * GetVersion (KERNEL.3) - * - * FIXME: Duplicated from kernel since it's a 16-bit function. - */ -DWORD WINAPI GetVersion16(void) -{ - static WORD dosver, winver; - - if (!dosver) /* not determined yet */ - { - RTL_OSVERSIONINFOEXW info; - - info.dwOSVersionInfoSize = sizeof(info); - if (RtlGetVersion( &info )) return 0; - - if (info.dwMajorVersion <= 3) - winver = MAKEWORD( info.dwMajorVersion, info.dwMinorVersion ); - else - winver = MAKEWORD( 3, 95 ); - - switch(info.dwPlatformId) - { - case VER_PLATFORM_WIN32s: - switch(MAKELONG( info.dwMinorVersion, info.dwMajorVersion )) - { - case 0x0200: - dosver = 0x0303; /* DOS 3.3 for Windows 2.0 */ - break; - case 0x0300: - dosver = 0x0500; /* DOS 5.0 for Windows 3.0 */ - break; - default: - dosver = 0x0616; /* DOS 6.22 for Windows 3.1 and later */ - break; - } - break; - case VER_PLATFORM_WIN32_WINDOWS: - /* DOS 8.0 for WinME, 7.0 for Win95/98 */ - if (info.dwMinorVersion >= 90) dosver = 0x0800; - else dosver = 0x0700; - break; - case VER_PLATFORM_WIN32_NT: - dosver = 0x0500; /* always DOS 5.0 for NT */ - break; - } - TRACE( "DOS %d.%02d Win %d.%02d\n", - HIBYTE(dosver), LOBYTE(dosver), LOBYTE(winver), HIBYTE(winver) ); - } - return MAKELONG( winver, dosver ); -} - /********************************************************************** * DOSVM_Int2fHandler * diff --git a/dlls/winedos/int31.c b/dlls/krnl386.exe16/int31.c similarity index 99% rename from dlls/winedos/int31.c rename to dlls/krnl386.exe16/int31.c index a0df8271769..51834705393 100644 --- a/dlls/winedos/int31.c +++ b/dlls/krnl386.exe16/int31.c @@ -28,6 +28,7 @@ #include "winternl.h" #include "wine/winbase16.h" #include "wownt32.h" +#include "kernel16_private.h" #include "dosexe.h" #include "excpt.h" @@ -125,7 +126,6 @@ static WORD alloc_pm_selector( WORD seg, unsigned char flags ) */ static LONG WINAPI dpmi_exception_handler(EXCEPTION_POINTERS *eptr) { -#ifdef __i386__ EXCEPTION_RECORD *rec = eptr->ExceptionRecord; CONTEXT *context = eptr->ContextRecord; @@ -144,7 +144,6 @@ static LONG WINAPI dpmi_exception_handler(EXCEPTION_POINTERS *eptr) return EXCEPTION_EXECUTE_HANDLER; } -#endif return EXCEPTION_CONTINUE_SEARCH; } @@ -298,8 +297,6 @@ static LPVOID DPMI_xrealloc( LPVOID ptr, DWORD newsize ) } -#ifdef __i386__ - void DPMI_CallRMCB32(RMCB *rmcb, UINT16 ss, DWORD esp, UINT16*es, DWORD*edi) #if 0 /* original code, which early gccs puke on */ { @@ -368,8 +365,6 @@ __ASM_GLOBAL_FUNC(DPMI_CallRMCB32, "ret") #endif -#endif /* __i386__ */ - /********************************************************************** * DPMI_CallRMCBProc * @@ -386,7 +381,6 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag ) /* Wine-internal RMCB, call directly */ ((RMCBPROC)rmcb->proc_ofs)(context); } else __TRY { -#ifdef __i386__ UINT16 ss,es; DWORD esp,edi; @@ -422,11 +416,8 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag ) } wine_ldt_free_entries( ss, 1 ); INT_GetRealModeContext( MapSL( MAKESEGPTR( es, edi )), context); -#else - ERR("RMCBs only implemented for i386\n"); -#endif } __EXCEPT(dpmi_exception_handler) { } __ENDTRY - + /* Restore virtual interrupt flag. */ get_vm86_teb_info()->dpmi_vif = old_vif; } diff --git a/dlls/winedos/int33.c b/dlls/krnl386.exe16/int33.c similarity index 100% rename from dlls/winedos/int33.c rename to dlls/krnl386.exe16/int33.c diff --git a/dlls/winedos/int67.c b/dlls/krnl386.exe16/int67.c similarity index 100% rename from dlls/winedos/int67.c rename to dlls/krnl386.exe16/int67.c diff --git a/dlls/winedos/interrupts.c b/dlls/krnl386.exe16/interrupts.c similarity index 98% rename from dlls/winedos/interrupts.c rename to dlls/krnl386.exe16/interrupts.c index 59f5b04d08b..bb5b769bd8f 100644 --- a/dlls/winedos/interrupts.c +++ b/dlls/krnl386.exe16/interrupts.c @@ -22,10 +22,11 @@ #include +#include "wine/winbase16.h" +#include "kernel16_private.h" #include "dosexe.h" #include "winternl.h" #include "wine/debug.h" -#include "wine/winbase16.h" WINE_DEFAULT_DEBUG_CHANNEL(int); WINE_DECLARE_DEBUG_CHANNEL(relay); @@ -258,7 +259,7 @@ static void DOSVM_PushFlags( CONTEXT86 *context, BOOL islong, BOOL isstub ) * Pushes interrupt frame to stack and changes instruction * pointer to interrupt handler. */ -BOOL WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum ) +BOOL DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum ) { TRACE_(relay)("Call DOS int 0x%02x ret=%04x:%08x\n" " eax=%08x ebx=%08x ecx=%08x edx=%08x\n" @@ -270,6 +271,8 @@ BOOL WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum ) context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->SegSs, context->EFlags ); + DOSMEM_InitDosMemory(); + if (context->SegCs == DOSVM_dpmi_segments->dpmi_sel) { DOSVM_BuildCallFrame( context, @@ -700,7 +703,7 @@ void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler ) * * Execute Wine interrupt handler procedure. */ -void WINAPI DOSVM_CallBuiltinHandler( CONTEXT86 *context, BYTE intnum ) +void DOSVM_CallBuiltinHandler( CONTEXT86 *context, BYTE intnum ) { /* * FIXME: Make all builtin interrupt calls go via this routine. @@ -713,6 +716,16 @@ void WINAPI DOSVM_CallBuiltinHandler( CONTEXT86 *context, BYTE intnum ) } +/********************************************************************** + * __wine_call_int_handler (KERNEL.@) + */ +void __wine_call_int_handler( CONTEXT86 *context, BYTE intnum ) +{ + DOSMEM_InitDosMemory(); + DOSVM_CallBuiltinHandler( context, intnum ); +} + + /********************************************************************** * DOSVM_Int11Handler * diff --git a/dlls/winedos/ioports.c b/dlls/krnl386.exe16/ioports.c similarity index 99% rename from dlls/winedos/ioports.c rename to dlls/krnl386.exe16/ioports.c index 25e03e8eb36..9ceb3aeb2f5 100644 --- a/dlls/winedos/ioports.c +++ b/dlls/krnl386.exe16/ioports.c @@ -52,6 +52,7 @@ #include "winnls.h" #include "winreg.h" #include "winternl.h" +#include "kernel16_private.h" #include "dosexe.h" #include "vga.h" #include "wine/unicode.h" @@ -734,12 +735,14 @@ static BOOL IO_pp_outp(int port, DWORD* res) * Note: The size argument has to be handled correctly _externally_ * (as we always return a DWORD) */ -DWORD WINAPI DOSVM_inport( int port, int size ) +DWORD DOSVM_inport( int port, int size ) { DWORD res = ~0U; TRACE("%d-byte value from port 0x%04x\n", size, port ); + DOSMEM_InitDosMemory(); + #ifdef HAVE_PPDEV if (do_pp_port_access == -1) do_pp_port_access =IO_pp_init(); if ((do_pp_port_access == 0 ) && (size == 1)) @@ -929,10 +932,12 @@ DWORD WINAPI DOSVM_inport( int port, int size ) /********************************************************************** * DOSVM_outport */ -void WINAPI DOSVM_outport( int port, int size, DWORD value ) +void DOSVM_outport( int port, int size, DWORD value ) { TRACE("IO: 0x%x (%d-byte value) to port 0x%04x\n", value, size, port ); + DOSMEM_InitDosMemory(); + #ifdef HAVE_PPDEV if (do_pp_port_access == -1) do_pp_port_access = IO_pp_init(); if ((do_pp_port_access == 0) && (size == 1)) diff --git a/dlls/krnl386.exe16/kernel16_private.h b/dlls/krnl386.exe16/kernel16_private.h index 14c558c9e77..2f68c57406a 100644 --- a/dlls/krnl386.exe16/kernel16_private.h +++ b/dlls/krnl386.exe16/kernel16_private.h @@ -190,10 +190,15 @@ static inline void stack16_pop( int size ) /* dosmem.c */ extern BOOL DOSMEM_Init(void); +extern BOOL DOSMEM_InitDosMemory(void); extern LPVOID DOSMEM_MapRealToLinear(DWORD); /* real-mode to linear */ extern LPVOID DOSMEM_MapDosToLinear(UINT); /* linear DOS to Wine */ extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */ -extern BOOL load_winedos(void); +extern BOOL DOSMEM_MapDosLayout(void); +extern LPVOID DOSMEM_AllocBlock(UINT size, WORD* p); +extern BOOL DOSMEM_FreeBlock(void* ptr); +extern UINT DOSMEM_ResizeBlock(void* ptr, UINT size, BOOL exact); +extern UINT DOSMEM_Available(void); /* global16.c */ extern HGLOBAL16 GLOBAL_CreateBlock( UINT16 flags, void *ptr, DWORD size, @@ -253,19 +258,6 @@ extern void TASK_InstallTHHook( THHOOK *pNewThook ); extern BOOL WOWTHUNK_Init(void); -extern struct winedos_exports -{ - /* for global16.c */ - void* (*AllocDosBlock)(UINT size, UINT16* pseg); - BOOL (*FreeDosBlock)(void* ptr); - UINT (*ResizeDosBlock)(void *ptr, UINT size, BOOL exact); - /* for instr.c */ - BOOL (WINAPI *EmulateInterruptPM)( CONTEXT86 *context, BYTE intnum ); - void (WINAPI *CallBuiltinHandler)( CONTEXT86 *context, BYTE intnum ); - DWORD (WINAPI *inport)( int port, int size ); - void (WINAPI *outport)( int port, int size, DWORD val ); -} winedos; - extern WORD DOSMEM_0000H; extern WORD DOSMEM_BiosDataSeg; extern WORD DOSMEM_BiosSysSeg; @@ -298,43 +290,4 @@ static inline struct kernel_thread_data *kernel_get_thread_data(void) "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" \ "ret $(4*" #args ")" ) /* fake ret to make copy protections happy */ -#define AX_reg(context) ((WORD)(context)->Eax) -#define BX_reg(context) ((WORD)(context)->Ebx) -#define CX_reg(context) ((WORD)(context)->Ecx) -#define DX_reg(context) ((WORD)(context)->Edx) -#define SI_reg(context) ((WORD)(context)->Esi) -#define DI_reg(context) ((WORD)(context)->Edi) - -#define AL_reg(context) ((BYTE)(context)->Eax) -#define AH_reg(context) ((BYTE)((context)->Eax >> 8)) -#define BL_reg(context) ((BYTE)(context)->Ebx) -#define BH_reg(context) ((BYTE)((context)->Ebx >> 8)) -#define CL_reg(context) ((BYTE)(context)->Ecx) -#define CH_reg(context) ((BYTE)((context)->Ecx >> 8)) -#define DL_reg(context) ((BYTE)(context)->Edx) -#define DH_reg(context) ((BYTE)((context)->Edx >> 8)) - -#define SET_CFLAG(context) ((context)->EFlags |= 0x0001) -#define RESET_CFLAG(context) ((context)->EFlags &= ~0x0001) -#define SET_ZFLAG(context) ((context)->EFlags |= 0x0040) -#define RESET_ZFLAG(context) ((context)->EFlags &= ~0x0040) -#define ISV86(context) ((context)->EFlags & 0x00020000) - -#define SET_AX(context,val) ((void)((context)->Eax = ((context)->Eax & ~0xffff) | (WORD)(val))) -#define SET_BX(context,val) ((void)((context)->Ebx = ((context)->Ebx & ~0xffff) | (WORD)(val))) -#define SET_CX(context,val) ((void)((context)->Ecx = ((context)->Ecx & ~0xffff) | (WORD)(val))) -#define SET_DX(context,val) ((void)((context)->Edx = ((context)->Edx & ~0xffff) | (WORD)(val))) -#define SET_SI(context,val) ((void)((context)->Esi = ((context)->Esi & ~0xffff) | (WORD)(val))) -#define SET_DI(context,val) ((void)((context)->Edi = ((context)->Edi & ~0xffff) | (WORD)(val))) - -#define SET_AL(context,val) ((void)((context)->Eax = ((context)->Eax & ~0xff) | (BYTE)(val))) -#define SET_BL(context,val) ((void)((context)->Ebx = ((context)->Ebx & ~0xff) | (BYTE)(val))) -#define SET_CL(context,val) ((void)((context)->Ecx = ((context)->Ecx & ~0xff) | (BYTE)(val))) -#define SET_DL(context,val) ((void)((context)->Edx = ((context)->Edx & ~0xff) | (BYTE)(val))) - -#define SET_AH(context,val) ((void)((context)->Eax = ((context)->Eax & ~0xff00) | (((BYTE)(val)) << 8))) -#define SET_BH(context,val) ((void)((context)->Ebx = ((context)->Ebx & ~0xff00) | (((BYTE)(val)) << 8))) -#define SET_CH(context,val) ((void)((context)->Ecx = ((context)->Ecx & ~0xff00) | (((BYTE)(val)) << 8))) -#define SET_DH(context,val) ((void)((context)->Edx = ((context)->Edx & ~0xff00) | (((BYTE)(val)) << 8))) - #endif /* __WINE_KERNEL16_PRIVATE_H */ diff --git a/dlls/krnl386.exe16/krnl386.exe16.spec b/dlls/krnl386.exe16/krnl386.exe16.spec index dd8850817c7..13e7091538d 100644 --- a/dlls/krnl386.exe16/krnl386.exe16.spec +++ b/dlls/krnl386.exe16/krnl386.exe16.spec @@ -743,6 +743,10 @@ # All functions must be prefixed with '__wine_' (for internal functions) # or 'wine_' (for user-visible functions) to avoid namespace conflicts. +# DOS support +@ cdecl -arch=win32 __wine_call_int_handler(ptr long) +@ cdecl -arch=win32 __wine_load_dos_exe(str str) + # VxDs @ cdecl -arch=win32 -private __wine_vxd_open(wstr long ptr) @ cdecl -arch=win32 -private __wine_vxd_get_proc(long) diff --git a/dlls/krnl386.exe16/ne_module.c b/dlls/krnl386.exe16/ne_module.c index 15d43bfe9a3..aa1c9c25e39 100644 --- a/dlls/krnl386.exe16/ne_module.c +++ b/dlls/krnl386.exe16/ne_module.c @@ -1072,6 +1072,7 @@ static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_ NE_InitializeDLLs(hModule); NE_DllProcessAttach(hModule); } + else DOSMEM_InitDosMemory(); /* we will be running a 16-bit task, setup DOS memory */ } return hinst; /* The last error that occurred */ } diff --git a/dlls/krnl386.exe16/relay.c b/dlls/krnl386.exe16/relay.c index d7151acff37..29a36f1df82 100644 --- a/dlls/krnl386.exe16/relay.c +++ b/dlls/krnl386.exe16/relay.c @@ -1,6 +1,7 @@ /* * Copyright 1993 Robert J. Amstadt * Copyright 1995 Alexandre Julliard + * Copyright 2002 Jukka Heinonen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,8 +21,6 @@ #include "config.h" #include "wine/port.h" -#ifdef __i386__ - #include #include #include @@ -33,12 +32,33 @@ #include "wine/winbase16.h" #include "winternl.h" #include "kernel16_private.h" +#include "dosexe.h" #include "wine/unicode.h" #include "wine/library.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(relay); +/* + * Magic DWORD used to check stack integrity. + */ +#define RELAY_MAGIC 0xabcdef00 + +/* + * Memory block for temporary 16-bit stacks used with relay calls. + */ +typedef struct { + DWORD inuse; /* non-zero if stack block is in use */ + DWORD eip; /* saved ip */ + DWORD seg_cs; /* saved cs */ + DWORD esp; /* saved sp */ + DWORD seg_ss; /* saved ss */ + DWORD stack_bottom; /* guard dword */ + BYTE stack[256-7*4]; /* 16-bit stack */ + DWORD stack_top; /* guard dword */ +} RELAY_Stack16; + + static const WCHAR **debug_relay_excludelist; static const WCHAR **debug_relay_includelist; static const WCHAR **debug_snoop_excludelist; @@ -577,4 +597,154 @@ int relay_call_from_16( void *entry_point, unsigned char *args16, CONTEXT86 *con return ret_val; } -#endif /* __i386__ */ +/********************************************************************** + * RELAY_GetPointer + * + * Get pointer to stack block when given esp pointing to 16-bit stack + * inside relay data segment. + */ +static RELAY_Stack16 *RELAY_GetPointer( DWORD offset ) +{ + offset = offset / sizeof(RELAY_Stack16) * sizeof(RELAY_Stack16); + return MapSL(MAKESEGPTR(DOSVM_dpmi_segments->relay_data_sel, offset)); +} + + +/********************************************************************** + * RELAY_MakeShortContext + * + * Allocate separate 16-bit stack, make stack pointer point to this + * stack and make code pointer point to stub that restores everything. + * So, after this routine, SS and CS are guaranteed to be 16-bit. + * + * Note: This might be called from signal handler, so the stack + * allocation algorithm must be signal safe. + */ +static void RELAY_MakeShortContext( CONTEXT86 *context ) +{ + DWORD offset = offsetof(RELAY_Stack16, stack_top); + RELAY_Stack16 *stack = RELAY_GetPointer( 0 ); + + while (stack->inuse && offset < DOSVM_RELAY_DATA_SIZE) { + stack++; + offset += sizeof(RELAY_Stack16); + } + + if (offset >= DOSVM_RELAY_DATA_SIZE) + ERR( "Too many nested interrupts!\n" ); + + stack->inuse = 1; + stack->eip = context->Eip; + stack->seg_cs = context->SegCs; + stack->esp = context->Esp; + stack->seg_ss = context->SegSs; + + stack->stack_bottom = RELAY_MAGIC; + stack->stack_top = RELAY_MAGIC; + + context->SegSs = DOSVM_dpmi_segments->relay_data_sel; + context->Esp = offset; + context->SegCs = DOSVM_dpmi_segments->relay_code_sel; + context->Eip = 3; +} + + +/********************************************************************** + * RELAY_RelayStub + * + * This stub is called by __wine_call_from_16_regs in order to marshall + * relay parameters. + */ +static void __stdcall RELAY_RelayStub( DOSRELAY proc, unsigned char *args, CONTEXT86 *context ) +{ + if (proc) + { + RELAY_Stack16 *stack = RELAY_GetPointer( context->Esp ); + + DWORD old_seg_cs = context->SegCs; + DWORD old_eip = context->Eip; + DWORD old_seg_ss = context->SegSs; + DWORD old_esp = context->Esp; + + context->SegCs = stack->seg_cs; + context->Eip = stack->eip; + context->SegSs = stack->seg_ss; + context->Esp = stack->esp; + + proc( context, *(LPVOID *)args ); + + stack->seg_cs = context->SegCs; + stack->eip = context->Eip; + stack->seg_ss = context->SegSs; + stack->esp = context->Esp; + + context->SegCs = old_seg_cs; + context->Eip = old_eip; + context->SegSs = old_seg_ss; + context->Esp = old_esp; + } +} + + +/********************************************************************** + * DOSVM_RelayHandler + * + * Restore saved code and stack pointers and release stack block. + */ +void DOSVM_RelayHandler( CONTEXT86 *context ) +{ + RELAY_Stack16 *stack = RELAY_GetPointer( context->Esp ); + + context->SegSs = stack->seg_ss; + context->Esp = stack->esp; + context->SegCs = stack->seg_cs; + context->Eip = stack->eip; + + if (!stack->inuse || + stack->stack_bottom != RELAY_MAGIC || + stack->stack_top != RELAY_MAGIC) + ERR( "Stack corrupted!\n" ); + + stack->inuse = 0; +} + + +/********************************************************************** + * DOSVM_BuildCallFrame + * + * Modifies the context so that return to context calls DOSRELAY and + * only after return from DOSRELAY the original context will be returned to. + */ +void DOSVM_BuildCallFrame( CONTEXT86 *context, DOSRELAY relay, LPVOID data ) +{ + WORD code_sel = DOSVM_dpmi_segments->relay_code_sel; + + /* + * Allocate separate stack for relay call. + */ + RELAY_MakeShortContext( context ); + + /* + * Build call frame. + */ + PUSH_WORD16( context, HIWORD(data) ); /* argument.hiword */ + PUSH_WORD16( context, LOWORD(data) ); /* argument.loword */ + PUSH_WORD16( context, context->SegCs ); /* STACK16FRAME.cs */ + PUSH_WORD16( context, LOWORD(context->Eip) ); /* STACK16FRAME.ip */ + PUSH_WORD16( context, LOWORD(context->Ebp) ); /* STACK16FRAME.bp */ + PUSH_WORD16( context, HIWORD(relay) ); /* STACK16FRAME.entry_point.hiword */ + PUSH_WORD16( context, LOWORD(relay) ); /* STACK16FRAME.entry_point.loword */ + PUSH_WORD16( context, 0 ); /* STACK16FRAME.entry_ip */ + PUSH_WORD16( context, HIWORD(RELAY_RelayStub) ); /* STACK16FRAME.relay.hiword */ + PUSH_WORD16( context, LOWORD(RELAY_RelayStub) ); /* STACK16FRAME.relay.loword */ + PUSH_WORD16( context, 0 ); /* STACK16FRAME.module_cs.hiword */ + PUSH_WORD16( context, code_sel ); /* STACK16FRAME.module_cs.loword */ + PUSH_WORD16( context, 0 ); /* STACK16FRAME.callfrom_ip.hiword */ + PUSH_WORD16( context, 0 ); /* STACK16FRAME.callfrom_ip.loword */ + + /* + * Adjust code pointer. + */ + context->SegCs = wine_get_cs(); + context->Eip = (DWORD)__wine_call_from_16_regs; +} diff --git a/dlls/winedos/soundblaster.c b/dlls/krnl386.exe16/soundblaster.c similarity index 100% rename from dlls/winedos/soundblaster.c rename to dlls/krnl386.exe16/soundblaster.c diff --git a/dlls/winedos/timer.c b/dlls/krnl386.exe16/timer.c similarity index 100% rename from dlls/winedos/timer.c rename to dlls/krnl386.exe16/timer.c diff --git a/dlls/winedos/vga.c b/dlls/krnl386.exe16/vga.c similarity index 100% rename from dlls/winedos/vga.c rename to dlls/krnl386.exe16/vga.c diff --git a/dlls/winedos/vga.h b/dlls/krnl386.exe16/vga.h similarity index 100% rename from dlls/winedos/vga.h rename to dlls/krnl386.exe16/vga.h diff --git a/dlls/krnl386.exe16/vxd.c b/dlls/krnl386.exe16/vxd.c index ddaaab2b832..c57f1463cab 100644 --- a/dlls/krnl386.exe16/vxd.c +++ b/dlls/krnl386.exe16/vxd.c @@ -44,6 +44,7 @@ #include "winternl.h" #include "winioctl.h" #include "kernel16_private.h" +#include "dosexe.h" #include "wine/library.h" #include "wine/unicode.h" #include "wine/server.h" diff --git a/dlls/vwin32.vxd/Makefile.in b/dlls/vwin32.vxd/Makefile.in index 128ac901e9f..afec3bd20b9 100644 --- a/dlls/vwin32.vxd/Makefile.in +++ b/dlls/vwin32.vxd/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = vwin32.vxd -IMPORTS = kernel32 +IMPORTS = kernel32 kernel C_SRCS = \ vwin32.c diff --git a/dlls/vwin32.vxd/vwin32.c b/dlls/vwin32.vxd/vwin32.c index ba78f74b945..972af125148 100644 --- a/dlls/vwin32.vxd/vwin32.c +++ b/dlls/vwin32.vxd/vwin32.c @@ -55,22 +55,7 @@ typedef struct tagMID { } MID, *PMID; #include -typedef void (WINAPI *CallBuiltinHandler)( CONTEXT *context, BYTE intnum ); - -static CallBuiltinHandler load_builtin_handler(void) -{ - static CallBuiltinHandler handler; - static BOOL init_done; - - if (!init_done) - { - HMODULE mod = LoadLibraryA( "winedos.dll" ); - if (mod) handler = (void *)GetProcAddress( mod, "CallBuiltinHandler" ); - if (!handler) FIXME( "DOS calls not supported\n" ); - init_done = TRUE; - } - return handler; -} +extern void __wine_call_int_handler( CONTEXT *context, BYTE intnum ); /* Pop a DWORD from the 32-bit stack */ static inline DWORD stack32_pop( CONTEXT86 *context ) @@ -136,13 +121,6 @@ BOOL WINAPI VWIN32_DeviceIoControl(DWORD dwIoControlCode, DIOC_REGISTERS *pIn = lpvInBuffer; DIOC_REGISTERS *pOut = lpvOutBuffer; BYTE intnum = 0; - CallBuiltinHandler handler; - - if (!(handler = load_builtin_handler())) - { - pOut->reg_Flags |= 0x0001; - return FALSE; - } TRACE( "Control '%s': " "eax=0x%08x, ebx=0x%08x, ecx=0x%08x, " @@ -177,7 +155,7 @@ BOOL WINAPI VWIN32_DeviceIoControl(DWORD dwIoControlCode, break; } - handler( &cxt, intnum ); + __wine_call_int_handler( &cxt, intnum ); CONTEXT_2_DIOCRegs( &cxt, pOut ); } return TRUE; @@ -225,19 +203,12 @@ DWORD WINAPI VWIN32_VxDCall( DWORD service, CONTEXT86 *context ) { DWORD callnum = stack32_pop(context); DWORD parm = stack32_pop(context); - CallBuiltinHandler handler; TRACE("Int31/DPMI dispatch(%08x)\n", callnum); - if (!(handler = load_builtin_handler())) - { - context->EFlags |= 0x0001; - return 0; - } - context->Eax = callnum; context->Ecx = parm; - handler( context, 0x31 ); + __wine_call_int_handler( context, 0x31 ); return LOWORD(context->Eax); } case 0x002a: /* Int41 dispatch - parm = int41 service number */ diff --git a/dlls/winedos/Makefile.in b/dlls/winedos/Makefile.in deleted file mode 100644 index 3c1605340d7..00000000000 --- a/dlls/winedos/Makefile.in +++ /dev/null @@ -1,39 +0,0 @@ -TOPSRCDIR = @top_srcdir@ -TOPOBJDIR = ../.. -SRCDIR = @srcdir@ -VPATH = @srcdir@ -MODULE = winedos.dll -IMPORTS = user32 kernel32 kernel ntdll -DELAYIMPORTS = ddraw dsound - -C_SRCS = \ - devices.c \ - dma.c \ - dosaspi.c \ - dosconf.c \ - dosmem.c \ - dosvm.c \ - fpu.c \ - int09.c \ - int10.c \ - int13.c \ - int15.c \ - int16.c \ - int21.c \ - int25.c \ - int26.c \ - int2f.c \ - int31.c \ - int33.c \ - int67.c \ - interrupts.c \ - ioports.c \ - module.c \ - relay.c \ - soundblaster.c \ - timer.c \ - vga.c - -@MAKE_DLL_RULES@ - -@DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/winedos/dosmem.c b/dlls/winedos/dosmem.c deleted file mode 100644 index 06823f854c3..00000000000 --- a/dlls/winedos/dosmem.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * DOS memory emulation - * - * Copyright 1995 Alexandre Julliard - * Copyright 1996 Marcus Meissner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_MMAN_H -# include -#endif - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "excpt.h" -#include "winternl.h" -#include "wine/winbase16.h" - -#include "dosexe.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(dosmem); - -/* DOS memory highest address (including HMA) */ -#define DOSMEM_SIZE 0x110000 -#define DOSMEM_64KB 0x10000 - -/* see dlls/kernel/dosmem.c for the details */ -static char *DOSMEM_dosmem; -static char *DOSMEM_sysmem; - -/* - * Memory Control Block (MCB) definition - * FIXME: implement Allocation Strategy - */ - -#define MCB_DUMP(mc) \ - TRACE ("MCB_DUMP base=%p type=%02xh psp=%04xh size=%04xh\n", mc, mc->type, mc->psp , mc->size ) - -#define MCB_NEXT(mc) \ - (MCB*) ((mc->type==MCB_TYPE_LAST) ? NULL : (char*)(mc) + ((mc->size + 1) << 4) ) - -/* FIXME: should we check more? */ -#define MCB_VALID(mc) \ - ((mc->type==MCB_TYPE_NORMAL) || (mc->type==MCB_TYPE_LAST)) - - -#define MCB_TYPE_NORMAL 0x4d -#define MCB_TYPE_LAST 0x5a - -#define MCB_PSP_DOS 0x0060 -#define MCB_PSP_FREE 0 - -#include "pshpack1.h" -typedef struct { - BYTE type; - WORD psp; /* segment of owner psp */ - WORD size; /* in paragraphs */ - BYTE pad[3]; - BYTE name[8]; -} MCB; -#include "poppack.h" - -/* -#define __DOSMEM_DEBUG__ - */ - -#define VM_STUB(x) (0x90CF00CD|(x<<8)) /* INT x; IRET; NOP */ -#define VM_STUB_SEGMENT 0xf000 /* BIOS segment */ - -/* FIXME: this should be moved to the LOL */ -static MCB* DOSMEM_root_block; - -/*********************************************************************** - * DOSMEM_MemoryTop - * - * Gets the DOS memory top. - */ -static char *DOSMEM_MemoryTop(void) -{ - return DOSMEM_dosmem+0x9FFFC; /* 640K */ -} - -/*********************************************************************** - * DOSMEM_FillIsrTable - * - * Fill the interrupt table with fake BIOS calls to BIOSSEG (0xf000). - * - * NOTES: - * Linux normally only traps INTs performed from or destined to BIOSSEG - * for us to handle, if the int_revectored table is empty. Filling the - * interrupt table with calls to INT stubs in BIOSSEG allows DOS programs - * to hook interrupts, as well as use their familiar retf tricks to call - * them, AND let Wine handle any unhooked interrupts transparently. - */ -static void DOSMEM_FillIsrTable(void) -{ - SEGPTR *isr = (SEGPTR*)DOSMEM_sysmem; - int x; - - for (x=0; x<256; x++) isr[x]=MAKESEGPTR(VM_STUB_SEGMENT,x*4); -} - -static void DOSMEM_MakeIsrStubs(void) -{ - DWORD *stub = (DWORD*)(DOSMEM_dosmem + (VM_STUB_SEGMENT << 4)); - int x; - - for (x=0; x<256; x++) stub[x]=VM_STUB(x); -} - -BIOSDATA* DOSVM_BiosData(void) -{ - return (BIOSDATA *)(DOSMEM_sysmem + 0x400); -} - -/********************************************************************** - * DOSMEM_GetTicksSinceMidnight - * - * Return number of clock ticks since midnight. - */ -static DWORD DOSMEM_GetTicksSinceMidnight(void) -{ - SYSTEMTIME time; - - /* This should give us the (approximately) correct - * 18.206 clock ticks per second since midnight. - */ - - GetLocalTime( &time ); - - return (((time.wHour * 3600 + time.wMinute * 60 + - time.wSecond) * 18206) / 1000) + - (time.wMilliseconds * 1000 / 54927); -} - -/*********************************************************************** - * DOSMEM_FillBiosSegments - * - * Fill the BIOS data segment with dummy values. - */ -static void DOSMEM_FillBiosSegments(void) -{ - BYTE *pBiosSys = (BYTE*)DOSMEM_dosmem + 0xf0000; - BYTE *pBiosROMTable = pBiosSys+0xe6f5; - BIOSDATA *pBiosData = DOSVM_BiosData(); - static const char bios_date[] = "13/01/99"; - - /* Clear all unused values */ - memset( pBiosData, 0, sizeof(*pBiosData) ); - - /* FIXME: should check the number of configured drives and ports */ - pBiosData->Com1Addr = 0x3f8; - pBiosData->Com2Addr = 0x2f8; - pBiosData->Lpt1Addr = 0x378; - pBiosData->Lpt2Addr = 0x278; - pBiosData->InstalledHardware = 0x5463; - pBiosData->MemSize = 640; - pBiosData->NextKbdCharPtr = 0x1e; - pBiosData->FirstKbdCharPtr = 0x1e; - pBiosData->VideoMode = 3; - pBiosData->VideoColumns = 80; - pBiosData->VideoPageSize = 80 * 25 * 2; - pBiosData->VideoPageStartAddr = 0xb800; - pBiosData->VideoCtrlAddr = 0x3d4; - pBiosData->Ticks = DOSMEM_GetTicksSinceMidnight(); - pBiosData->NbHardDisks = 2; - pBiosData->KbdBufferStart = 0x1e; - pBiosData->KbdBufferEnd = 0x3e; - pBiosData->RowsOnScreenMinus1 = 24; - pBiosData->BytesPerChar = 0x10; - pBiosData->ModeOptions = 0x64; - pBiosData->FeatureBitsSwitches = 0xf9; - pBiosData->VGASettings = 0x51; - pBiosData->DisplayCombination = 0x08; - pBiosData->DiskDataRate = 0; - - /* fill ROM configuration table (values from Award) */ - *(pBiosROMTable+0x0) = 0x08; /* number of bytes following LO */ - *(pBiosROMTable+0x1) = 0x00; /* number of bytes following HI */ - *(pBiosROMTable+0x2) = 0xfc; /* model */ - *(pBiosROMTable+0x3) = 0x01; /* submodel */ - *(pBiosROMTable+0x4) = 0x00; /* BIOS revision */ - *(pBiosROMTable+0x5) = 0x74; /* feature byte 1 */ - *(pBiosROMTable+0x6) = 0x00; /* feature byte 2 */ - *(pBiosROMTable+0x7) = 0x00; /* feature byte 3 */ - *(pBiosROMTable+0x8) = 0x00; /* feature byte 4 */ - *(pBiosROMTable+0x9) = 0x00; /* feature byte 5 */ - - /* BIOS date string */ - memcpy(pBiosSys+0xfff5, bios_date, sizeof bios_date); - - /* BIOS ID */ - *(pBiosSys+0xfffe) = 0xfc; - - /* Reboot vector (f000:fff0 or ffff:0000) */ - *(DWORD*)(pBiosSys + 0xfff0) = VM_STUB(0x19); -} - -/*********************************************************************** - * BiosTick - * - * Increment the BIOS tick counter. Called by timer signal handler. - */ -static void CALLBACK BiosTick( LPVOID arg, DWORD low, DWORD high ) -{ - BIOSDATA *pBiosData = arg; - pBiosData->Ticks++; -} - -/*********************************************************************** - * timer_thread - */ -static DWORD CALLBACK timer_thread( void *arg ) -{ - LARGE_INTEGER when; - HANDLE timer; - - if (!(timer = CreateWaitableTimerA( NULL, FALSE, NULL ))) return 0; - - when.u.LowPart = when.u.HighPart = 0; - SetWaitableTimer( timer, &when, 55 /* actually 54.925 */, BiosTick, arg, FALSE ); - for (;;) SleepEx( INFINITE, TRUE ); -} - -/*********************************************************************** - * DOSMEM_Collapse - * - * Helper function for internal use only. - * Attach all following free blocks to this one, even if this one is not free. - */ -static void DOSMEM_Collapse( MCB* mcb ) -{ - MCB* next = MCB_NEXT( mcb ); - - while (next && next->psp == MCB_PSP_FREE) - { - mcb->size = mcb->size + next->size + 1; - mcb->type = next->type; /* make sure keeping MCB_TYPE_LAST */ - next = MCB_NEXT( next ); - } -} - -/*********************************************************************** - * DOSMEM_AllocBlock - * - * Carve a chunk of the DOS memory block (without selector). - */ -LPVOID DOSMEM_AllocBlock(UINT size, UINT16* pseg) -{ - MCB *curr = DOSMEM_root_block; - MCB *next = NULL; - WORD psp = DOSVM_psp; - - if (!psp) - psp = MCB_PSP_DOS; - - *pseg = 0; - - TRACE( "(%04xh)\n", size ); - - /* round up to paragraph */ - size = (size + 15) >> 4; - -#ifdef __DOSMEM_DEBUG__ - DOSMEM_Available(); /* checks the whole MCB list */ -#endif - - /* loop over all MCB and search the next large enough MCB */ - while (curr) - { - if (!MCB_VALID (curr)) - { - ERR( "MCB List Corrupt\n" ); - MCB_DUMP( curr ); - return NULL; - } - if (curr->psp == MCB_PSP_FREE) - { - DOSMEM_Collapse( curr ); - /* is it large enough (one paragraph for the MCB)? */ - if (curr->size >= size) - { - if (curr->size > size) - { - /* split curr */ - next = (MCB *) ((char*) curr + ((size+1) << 4)); - next->psp = MCB_PSP_FREE; - next->size = curr->size - (size+1); - next->type = curr->type; - curr->type = MCB_TYPE_NORMAL; - curr->size = size; - } - /* curr is the found block */ - curr->psp = psp; - if( pseg ) *pseg = (((char*)curr) + 16 - DOSMEM_dosmem) >> 4; - return (LPVOID) ((char*)curr + 16); - } - } - curr = MCB_NEXT(curr); - } - return NULL; -} - -/*********************************************************************** - * DOSMEM_FreeBlock - */ -BOOL DOSMEM_FreeBlock(void* ptr) -{ - MCB* mcb = (MCB*) ((char*)ptr - 16); - - TRACE( "(%p)\n", ptr ); - -#ifdef __DOSMEM_DEBUG__ - DOSMEM_Available(); -#endif - - if (!MCB_VALID (mcb)) - { - ERR( "MCB invalid\n" ); - MCB_DUMP( mcb ); - return FALSE; - } - - mcb->psp = MCB_PSP_FREE; - DOSMEM_Collapse( mcb ); - return TRUE; -} - -/*********************************************************************** - * DOSMEM_ResizeBlock - * - * Resize DOS memory block in place. Returns block size or -1 on error. - * - * If exact is TRUE, returned value is either old or requested block - * size. If exact is FALSE, block is expanded even if there is not - * enough space for full requested block size. - * - * TODO: return also biggest block size - */ -UINT DOSMEM_ResizeBlock(void *ptr, UINT size, BOOL exact) -{ - MCB* mcb = (MCB*) ((char*)ptr - 16); - MCB* next; - - TRACE( "(%p,%04xh,%s)\n", ptr, size, exact ? "TRUE" : "FALSE" ); - - /* round up to paragraph */ - size = (size + 15) >> 4; - -#ifdef __DOSMEM_DEBUG__ - DOSMEM_Available(); -#endif - - if (!MCB_VALID (mcb)) - { - ERR( "MCB invalid\n" ); - MCB_DUMP( mcb ); - return -1; - } - - /* resize needed? */ - if (mcb->size == size) - return size << 4; - - /* collapse free blocks */ - DOSMEM_Collapse( mcb ); - - /* shrink mcb ? */ - if (mcb->size > size) - { - next = (MCB *) ((char*)mcb + ((size+1) << 4)); - next->type = mcb->type; - next->psp = MCB_PSP_FREE; - next->size = mcb->size - (size+1); - mcb->type = MCB_TYPE_NORMAL; - mcb->size = size; - return size << 4; - } - - if (!exact) - { - return mcb->size << 4; - } - - return -1; -} - -/*********************************************************************** - * DOSMEM_Available - */ -UINT DOSMEM_Available(void) -{ - UINT available = 0; - UINT total = 0; - MCB *curr = DOSMEM_root_block; - /* loop over all MCB and search the largest free MCB */ - while (curr) - { -#ifdef __DOSMEM_DEBUG__ - MCB_DUMP( curr ); -#endif - if (!MCB_VALID (curr)) - { - ERR( "MCB List Corrupt\n" ); - MCB_DUMP( curr ); - return 0; - } - if (curr->psp == MCB_PSP_FREE && - curr->size > available ) - available = curr->size; - - total += curr->size + 1; - curr = MCB_NEXT( curr ); - } - TRACE( " %04xh of %04xh paragraphs available\n", available, total ); - return available << 4; -} - -/*********************************************************************** - * DOSMEM_InitMemory - * - * Initialises the DOS memory structures. - */ -static void DOSMEM_InitMemory(char* addr) -{ - DOSMEM_FillBiosSegments(); - DOSMEM_FillIsrTable(); - - /* align root block to paragraph */ - DOSMEM_root_block = (MCB*) (( (DWORD_PTR)(addr+0xf) >> 4) << 4); - DOSMEM_root_block->type = MCB_TYPE_LAST; - DOSMEM_root_block->psp = MCB_PSP_FREE; - DOSMEM_root_block->size = (DOSMEM_MemoryTop() - ((char*)DOSMEM_root_block)) >> 4; - - TRACE("DOS conventional memory initialized, %d bytes free.\n", - DOSMEM_Available()); -} - -/****************************************************************** - * DOSMEM_InitDosMemory - * - * When WineDOS is loaded, initializes the current DOS memory layout. - */ -BOOL DOSMEM_InitDosMemory(void) -{ - HMODULE16 hModule; - unsigned short sel; - LDT_ENTRY entry; - DWORD reserve; - - if (!(hModule = GetModuleHandle16("KERNEL"))) return FALSE; - /* KERNEL.194: __F000H */ - sel = LOWORD(GetProcAddress16(hModule, (LPCSTR)(ULONG_PTR)194)); - wine_ldt_get_entry(sel, &entry); - DOSMEM_dosmem = (char*)wine_ldt_get_base(&entry) - 0xF0000; - /* KERNEL.183: __0000H */ - sel = LOWORD(GetProcAddress16(hModule, (LPCSTR)(DWORD_PTR)183)); - wine_ldt_get_entry(sel, &entry); - DOSMEM_sysmem = wine_ldt_get_base(&entry); - - /* - * Reserve either: - * - lowest 64k for NULL pointer catching (Win16) - * - lowest 1k for interrupt handlers and - * another 0.5k for BIOS, DOS and intra-application - * areas (DOS) - */ - if (DOSMEM_dosmem != DOSMEM_sysmem) - reserve = 0x10000; /* 64k */ - else - reserve = 0x600; /* 1.5k */ - - /* - * Round to paragraph boundary in order to make - * sure the alignment is correct. - */ - reserve = ((reserve + 15) >> 4) << 4; - - /* - * Set DOS memory base and initialize conventional memory. - */ - DOSMEM_InitMemory(DOSMEM_dosmem + reserve); - - CloseHandle( CreateThread( NULL, 0, timer_thread, DOSVM_BiosData(), 0, NULL )); - return TRUE; -} - -/****************************************************************** - * DOSMEM_MapDosLayout - * - * Initialize the first MB of memory to look like a real DOS setup - */ -BOOL DOSMEM_MapDosLayout(void) -{ - static int already_mapped; - - if (!already_mapped) - { - HMODULE16 hModule; - unsigned short sel; - LDT_ENTRY entry; - - if (DOSMEM_dosmem || !VirtualProtect( NULL, DOSMEM_SIZE, PAGE_EXECUTE_READWRITE, NULL )) - { - ERR( "Need full access to the first megabyte for DOS mode\n" ); - ExitProcess(1); - } - /* copy the BIOS and ISR area down */ - memcpy( DOSMEM_dosmem, DOSMEM_sysmem, 0x400 + 0x100 ); - DOSMEM_sysmem = DOSMEM_dosmem; - hModule = GetModuleHandle16("KERNEL"); - /* selector to 0000H */ - sel = LOWORD(GetProcAddress16(hModule, (LPCSTR)(DWORD_PTR)183)); - wine_ldt_get_entry(sel, &entry); - wine_ldt_set_base(&entry, NULL); - wine_ldt_set_entry(sel, &entry); - /* selector to BiosData */ - sel = LOWORD(GetProcAddress16(hModule, (LPCSTR)(DWORD_PTR)193)); - wine_ldt_get_entry(sel, &entry); - wine_ldt_set_base(&entry, (const void*)0x400); - wine_ldt_set_entry(sel, &entry); - /* we may now need the actual interrupt stubs, and since we've just moved the - * interrupt vector table away, we can fill the area with stubs instead... */ - DOSMEM_MakeIsrStubs(); - already_mapped = 1; - } - return TRUE; -} diff --git a/dlls/winedos/relay.c b/dlls/winedos/relay.c deleted file mode 100644 index acadd774fc6..00000000000 --- a/dlls/winedos/relay.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Routines for dynamically building calls to Wine from - * protected mode applications. - * - * Copyright 2002 Jukka Heinonen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ -#include "dosexe.h" -#include "wine/winbase16.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(int); - -/* - * Magic DWORD used to check stack integrity. - */ -#define RELAY_MAGIC 0xabcdef00 - -/* - * Memory block for temporary 16-bit stacks used with relay calls. - */ -typedef struct { - DWORD inuse; /* non-zero if stack block is in use */ - DWORD eip; /* saved ip */ - DWORD seg_cs; /* saved cs */ - DWORD esp; /* saved sp */ - DWORD seg_ss; /* saved ss */ - DWORD stack_bottom; /* guard dword */ - BYTE stack[256-7*4]; /* 16-bit stack */ - DWORD stack_top; /* guard dword */ -} RELAY_Stack16; - - -/********************************************************************** - * RELAY_GetPointer - * - * Get pointer to stack block when given esp pointing to 16-bit stack - * inside relay data segment. - */ -static RELAY_Stack16 *RELAY_GetPointer( DWORD offset ) -{ - offset = offset / sizeof(RELAY_Stack16) * sizeof(RELAY_Stack16); - return MapSL(MAKESEGPTR(DOSVM_dpmi_segments->relay_data_sel, offset)); -} - - -/********************************************************************** - * RELAY_MakeShortContext - * - * Allocate separate 16-bit stack, make stack pointer point to this - * stack and make code pointer point to stub that restores everything. - * So, after this routine, SS and CS are guaranteed to be 16-bit. - * - * Note: This might be called from signal handler, so the stack - * allocation algorithm must be signal safe. - */ -static void RELAY_MakeShortContext( CONTEXT86 *context ) -{ - DWORD offset = offsetof(RELAY_Stack16, stack_top); - RELAY_Stack16 *stack = RELAY_GetPointer( 0 ); - - while (stack->inuse && offset < DOSVM_RELAY_DATA_SIZE) { - stack++; - offset += sizeof(RELAY_Stack16); - } - - if (offset >= DOSVM_RELAY_DATA_SIZE) - ERR( "Too many nested interrupts!\n" ); - - stack->inuse = 1; - stack->eip = context->Eip; - stack->seg_cs = context->SegCs; - stack->esp = context->Esp; - stack->seg_ss = context->SegSs; - - stack->stack_bottom = RELAY_MAGIC; - stack->stack_top = RELAY_MAGIC; - - context->SegSs = DOSVM_dpmi_segments->relay_data_sel; - context->Esp = offset; - context->SegCs = DOSVM_dpmi_segments->relay_code_sel; - context->Eip = 3; -} - - -/********************************************************************** - * RELAY_RelayStub - * - * This stub is called by __wine_call_from_16_regs in order to marshall - * relay parameters. - */ -static void __stdcall RELAY_RelayStub( DOSRELAY proc, - unsigned char *args, - void *ctx86 ) -{ - if (proc) - { - CONTEXT86 *context = ctx86; - RELAY_Stack16 *stack = RELAY_GetPointer( context->Esp ); - - DWORD old_seg_cs = context->SegCs; - DWORD old_eip = context->Eip; - DWORD old_seg_ss = context->SegSs; - DWORD old_esp = context->Esp; - - context->SegCs = stack->seg_cs; - context->Eip = stack->eip; - context->SegSs = stack->seg_ss; - context->Esp = stack->esp; - - proc( context, *(LPVOID *)args ); - - stack->seg_cs = context->SegCs; - stack->eip = context->Eip; - stack->seg_ss = context->SegSs; - stack->esp = context->Esp; - - context->SegCs = old_seg_cs; - context->Eip = old_eip; - context->SegSs = old_seg_ss; - context->Esp = old_esp; - } -} - - -/********************************************************************** - * DOSVM_RelayHandler - * - * Restore saved code and stack pointers and release stack block. - */ -void DOSVM_RelayHandler( CONTEXT86 *context ) -{ - RELAY_Stack16 *stack = RELAY_GetPointer( context->Esp ); - - context->SegSs = stack->seg_ss; - context->Esp = stack->esp; - context->SegCs = stack->seg_cs; - context->Eip = stack->eip; - - if (!stack->inuse || - stack->stack_bottom != RELAY_MAGIC || - stack->stack_top != RELAY_MAGIC) - ERR( "Stack corrupted!\n" ); - - stack->inuse = 0; -} - - -/********************************************************************** - * DOSVM_BuildCallFrame - * - * Modifies the context so that return to context calls DOSRELAY and - * only after return from DOSRELAY the original context will be returned to. - */ -void DOSVM_BuildCallFrame( CONTEXT86 *context, DOSRELAY relay, LPVOID data ) -{ - static void (*__wine_call_from_16_regs_ptr)(void); - WORD code_sel = DOSVM_dpmi_segments->relay_code_sel; - - /* - * Allocate separate stack for relay call. - */ - RELAY_MakeShortContext( context ); - - /* - * Build call frame. - */ - PUSH_WORD16( context, HIWORD(data) ); /* argument.hiword */ - PUSH_WORD16( context, LOWORD(data) ); /* argument.loword */ - PUSH_WORD16( context, context->SegCs ); /* STACK16FRAME.cs */ - PUSH_WORD16( context, LOWORD(context->Eip) ); /* STACK16FRAME.ip */ - PUSH_WORD16( context, LOWORD(context->Ebp) ); /* STACK16FRAME.bp */ - PUSH_WORD16( context, HIWORD(relay) ); /* STACK16FRAME.entry_point.hiword */ - PUSH_WORD16( context, LOWORD(relay) ); /* STACK16FRAME.entry_point.loword */ - PUSH_WORD16( context, 0 ); /* STACK16FRAME.entry_ip */ - PUSH_WORD16( context, HIWORD(RELAY_RelayStub) ); /* STACK16FRAME.relay.hiword */ - PUSH_WORD16( context, LOWORD(RELAY_RelayStub) ); /* STACK16FRAME.relay.loword */ - PUSH_WORD16( context, 0 ); /* STACK16FRAME.module_cs.hiword */ - PUSH_WORD16( context, code_sel ); /* STACK16FRAME.module_cs.loword */ - PUSH_WORD16( context, 0 ); /* STACK16FRAME.callfrom_ip.hiword */ - PUSH_WORD16( context, 0 ); /* STACK16FRAME.callfrom_ip.loword */ - - /* - * Adjust code pointer. - */ - if (!__wine_call_from_16_regs_ptr) - __wine_call_from_16_regs_ptr = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), - "__wine_call_from_16_regs" ); - context->SegCs = wine_get_cs(); - context->Eip = (DWORD)__wine_call_from_16_regs_ptr; -} diff --git a/dlls/winedos/winedos.spec b/dlls/winedos/winedos.spec deleted file mode 100644 index 68478747de8..00000000000 --- a/dlls/winedos/winedos.spec +++ /dev/null @@ -1,13 +0,0 @@ -@ stdcall wine_load_dos_exe(str str) - -@ stdcall EmulateInterruptPM(ptr long) DOSVM_EmulateInterruptPM -@ stdcall CallBuiltinHandler(ptr long) DOSVM_CallBuiltinHandler - -# I/O functions -@ stdcall inport(long long) DOSVM_inport -@ stdcall outport(long long long) DOSVM_outport - -# DOS memory functions -@ cdecl FreeDosBlock(ptr) DOSMEM_FreeBlock -@ cdecl AllocDosBlock(long ptr) DOSMEM_AllocBlock -@ cdecl ResizeDosBlock(ptr long long) DOSMEM_ResizeBlock diff --git a/dlls/winedos/wprocs.spec b/dlls/winedos/wprocs.spec deleted file mode 100644 index 1691590938b..00000000000 --- a/dlls/winedos/wprocs.spec +++ /dev/null @@ -1,19 +0,0 @@ -# VxDs. The first Vxd is at 400 -# -#400+VXD_ID pascal -register () -# -401 pascal -register VXD_VMM() VXD_VMM -405 pascal -register VXD_Timer() VXD_Timer -409 pascal -register VXD_Reboot() VXD_Reboot -410 pascal -register VXD_VDD() VXD_VDD -412 pascal -register VXD_VMD() VXD_VMD -414 pascal -register VXD_Comm() VXD_Comm -#415 pascal -register VXD_Printer() VXD_Printer -423 pascal -register VXD_Shell() VXD_Shell -433 pascal -register VXD_PageFile() VXD_PageFile -438 pascal -register VXD_APM() VXD_APM -439 pascal -register VXD_VXDLoader() VXD_VXDLoader -445 pascal -register VXD_Win32s() VXD_Win32s -451 pascal -register VXD_ConfigMG() VXD_ConfigMG -455 pascal -register VXD_Enable() VXD_Enable -1490 pascal -register VXD_TimerAPI() VXD_TimerAPI diff --git a/programs/winevdm/winevdm.c b/programs/winevdm/winevdm.c index 280f0785c82..92ca50899a4 100644 --- a/programs/winevdm/winevdm.c +++ b/programs/winevdm/winevdm.c @@ -30,7 +30,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(winevdm); -static void (WINAPI *wine_load_dos_exe)( LPCSTR filename, LPCSTR cmdline ); +extern void __wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline ); /*** PIF file structures ***/ @@ -244,7 +244,7 @@ static VOID pif_cmd( char *filename, char *cmdline) * - hot key's * - etc. */ - wine_load_dos_exe( progpath, cmdline ); + __wine_load_dos_exe( progpath, cmdline ); return; } @@ -382,7 +382,6 @@ int main( int argc, char *argv[] ) STARTUPINFOA info; char *cmdline, *appname, **first_arg; char *p; - HMODULE winedos; MEMORY_BASIC_INFORMATION mem_info; if (!argv[1]) usage(); @@ -403,13 +402,6 @@ int main( int argc, char *argv[] ) first_arg = argv + 1; } - if (!(winedos = LoadLibraryA( "winedos.dll" )) || - !(wine_load_dos_exe = (void *)GetProcAddress( winedos, "wine_load_dos_exe" ))) - { - WINE_MESSAGE( "winevdm: unable to exec '%s': DOS support unavailable\n", appname ); - ExitProcess(1); - } - if (*first_arg) first_arg++; /* skip program name */ cmdline = build_command_line( first_arg ); @@ -455,7 +447,7 @@ int main( int argc, char *argv[] ) /* try DOS format */ /* loader expects arguments to be regular C strings */ - wine_load_dos_exe( appname, cmdline + 1 ); + __wine_load_dos_exe( appname, cmdline + 1 ); } /* if we get back here it failed */ instance = GetLastError();