From e5557b357a8fb0244322c30c478d16f6ca193d75 Mon Sep 17 00:00:00 2001
From: Ove Kaaven <ovek@arcticnet.no>
Date: Tue, 26 Dec 2000 00:22:45 +0000
Subject: [PATCH] Separated the MZ loader and core DOS VM into dlls/winedos.

---
 Make.rules.in                         |  1 +
 configure                             |  2 ++
 configure.in                          |  1 +
 dlls/Makefile.in                      |  6 ++++
 dlls/ntdll/Makefile.in                |  1 -
 dlls/winedos/.cvsignore               |  2 ++
 dlls/winedos/Makefile.in              | 15 +++++++++
 {loader/dos => dlls/winedos}/dosvm.c  | 26 +++++++--------
 {loader/dos => dlls/winedos}/module.c | 22 ++++++-------
 dlls/winedos/winedos.spec             | 19 +++++++++++
 include/callback.h                    | 18 +++++++++++
 include/dosexe.h                      | 22 ++++++-------
 include/miscemu.h                     |  1 +
 loader/dos/Makefile.in                | 10 ++----
 miscemu/main.c                        |  4 ++-
 msdos/devices.c                       |  5 +--
 msdos/dpmi.c                          | 46 +++++++++++++++++++++------
 msdos/int09.c                         |  7 ++--
 msdos/int16.c                         |  3 +-
 msdos/int20.c                         |  5 +--
 msdos/int21.c                         | 17 ++++++----
 msdos/int33.c                         |  3 +-
 msdos/ioports.c                       | 11 ++++---
 23 files changed, 172 insertions(+), 75 deletions(-)
 create mode 100644 dlls/winedos/.cvsignore
 create mode 100644 dlls/winedos/Makefile.in
 rename {loader/dos => dlls/winedos}/dosvm.c (95%)
 rename {loader/dos => dlls/winedos}/module.c (96%)
 create mode 100644 dlls/winedos/winedos.spec

diff --git a/Make.rules.in b/Make.rules.in
index 49ef398e646..8c8805fa02b 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -152,6 +152,7 @@ DLLS = \
 	user32 \
 	version \
 	w32skrnl \
+	winedos \
 	wineoss.drv \
 	wineps \
 	wininet \
diff --git a/configure b/configure
index 9a335ad660d..ecfda11be3b 100755
--- a/configure
+++ b/configure
@@ -6752,6 +6752,7 @@ dlls/user/Makefile
 dlls/version/Makefile
 dlls/win32s/Makefile
 dlls/winaspi/Makefile
+dlls/winedos/Makefile
 dlls/wineps/Makefile
 dlls/wininet/Makefile
 dlls/winmm/Makefile
@@ -6994,6 +6995,7 @@ dlls/user/Makefile
 dlls/version/Makefile
 dlls/win32s/Makefile
 dlls/winaspi/Makefile
+dlls/winedos/Makefile
 dlls/wineps/Makefile
 dlls/wininet/Makefile
 dlls/winmm/Makefile
diff --git a/configure.in b/configure.in
index 0e540051dee..5a0fbe54c2e 100644
--- a/configure.in
+++ b/configure.in
@@ -1196,6 +1196,7 @@ dlls/user/Makefile
 dlls/version/Makefile
 dlls/win32s/Makefile
 dlls/winaspi/Makefile
+dlls/winedos/Makefile
 dlls/wineps/Makefile
 dlls/wininet/Makefile
 dlls/winmm/Makefile
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index fbaa45cfc17..5e34e17878c 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -57,6 +57,7 @@ DLLFILES = \
 	version/libversion.@LIBEXT@ \
 	win32s/libw32skrnl.@LIBEXT@ \
 	winaspi/libwnaspi32.@LIBEXT@ \
+	winedos/libwinedos.@LIBEXT@ \
 	wineps/libwineps.@LIBEXT@ \
 	wininet/libwininet.@LIBEXT@ \
 	winmm/joystick/libjoystick.drv.@LIBEXT@ \
@@ -170,6 +171,7 @@ SUBDIRS = \
 	version \
 	win32s \
 	winaspi \
+	winedos \
 	wineps \
 	wininet \
 	winmm \
@@ -358,6 +360,9 @@ libversion.@LIBEXT@ libver.@LIBEXT@: version/libversion.@LIBEXT@
 libw32skrnl.@LIBEXT@ libw32sys.@LIBEXT@ libwin32s16.@LIBEXT@: win32s/libw32skrnl.@LIBEXT@
 	$(RM) $@ && $(LN_S) win32s/libw32skrnl.@LIBEXT@ $@
 
+libwinedos.@LIBEXT@: winedos/libwinedos.@LIBEXT@
+	$(RM) $@ && $(LN_S) winedos/libwinedos.@LIBEXT@ $@
+
 libwineoss.drv.@LIBEXT@: winmm/wineoss/libwineoss.drv.@LIBEXT@
 	$(RM) $@ && $(LN_S) winmm/wineoss/libwineoss.drv.@LIBEXT@ $@
 
@@ -438,6 +443,7 @@ user/libuser32.@LIBEXT@: libgdi32.@LIBEXT@ libadvapi32.@LIBEXT@ libkernel32.@LIB
 version/libversion.@LIBEXT@: liblz32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
 win32s/libw32skrnl.@LIBEXT@: libkernel32.@LIBEXT@ libntdll.@LIBEXT@
 winaspi/libwnaspi32.@LIBEXT@: libadvapi32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
+winedos/libwinedos.@LIBEXT@: libuser32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
 wineps/libwineps.@LIBEXT@: libuser32.@LIBEXT@ libgdi32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
 wininet/libwininet.@LIBEXT@: libuser32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
 winmm/joystick/libjoystick.drv.@LIBEXT@: libwinmm.@LIBEXT@ libuser32.@LIBEXT@ libntdll.@LIBEXT@
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index 305273306cd..f43f755500a 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -33,7 +33,6 @@ EXTRA_OBJS = \
 	$(TOPOBJDIR)/if1632/if1632.o \
 	$(TOPOBJDIR)/loader/loader.o \
 	$(TOPOBJDIR)/loader/ne/ne.o \
-	$(TOPOBJDIR)/loader/dos/dos.o \
 	$(TOPOBJDIR)/memory/memory.o \
 	$(TOPOBJDIR)/misc/misc.o \
 	$(TOPOBJDIR)/msdos/msdos.o \
diff --git a/dlls/winedos/.cvsignore b/dlls/winedos/.cvsignore
new file mode 100644
index 00000000000..3670d73fe38
--- /dev/null
+++ b/dlls/winedos/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+winedos.spec.c
diff --git a/dlls/winedos/Makefile.in b/dlls/winedos/Makefile.in
new file mode 100644
index 00000000000..56eb36dce06
--- /dev/null
+++ b/dlls/winedos/Makefile.in
@@ -0,0 +1,15 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = winedos
+SOVERSION = 1.0
+IMPORTS   = user32 kernel32 ntdll
+
+C_SRCS = \
+	dosvm.c \
+	module.c
+
+@MAKE_DLL_RULES@
+
+### Dependencies:
diff --git a/loader/dos/dosvm.c b/dlls/winedos/dosvm.c
similarity index 95%
rename from loader/dos/dosvm.c
rename to dlls/winedos/dosvm.c
index eb3816695eb..4032d067214 100644
--- a/loader/dos/dosvm.c
+++ b/dlls/winedos/dosvm.c
@@ -33,7 +33,7 @@
 #include "file.h"
 #include "miscemu.h"
 #include "dosexe.h"
-#include "dosmod.h"
+#include "../../loader/dos/dosmod.h"
 #include "stackframe.h"
 #include "debugtools.h"
 
@@ -212,7 +212,7 @@ static void DOSVM_SendQueuedEvents(CONTEXT86 *context)
     DOSVM_SendQueuedEvent(context);
 }
 
-void DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data)
+void WINAPI DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data)
 {
   LPDOSEVENT event, cur, prev;
 
@@ -407,7 +407,7 @@ static void DOSVM_ProcessMessage(MSG *msg)
   }
 }
 
-void DOSVM_Wait( int read_pipe, HANDLE hObject )
+void WINAPI DOSVM_Wait( int read_pipe, HANDLE hObject )
 {
   MSG msg;
   DWORD waitret;
@@ -468,7 +468,7 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject )
   } while (TRUE);
 }
 
-int DOSVM_Enter( CONTEXT86 *context )
+int WINAPI DOSVM_Enter( CONTEXT86 *context )
 {
  struct vm86plus_struct VM86;
  int stat,len,sig;
@@ -541,7 +541,7 @@ int DOSVM_Enter( CONTEXT86 *context )
  return 0;
 }
 
-void DOSVM_PIC_ioport_out( WORD port, BYTE val)
+void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val)
 {
     LPDOSEVENT event;
 
@@ -571,7 +571,7 @@ void DOSVM_PIC_ioport_out( WORD port, BYTE val)
     }
 }
 
-void DOSVM_SetTimer( unsigned ticks )
+void WINAPI DOSVM_SetTimer( unsigned ticks )
 {
   int stat=DOSMOD_SET_TIMER;
   struct timeval tim;
@@ -595,7 +595,7 @@ void DOSVM_SetTimer( unsigned ticks )
   }
 }
 
-unsigned DOSVM_GetTimer( void )
+unsigned WINAPI DOSVM_GetTimer( void )
 {
   int stat=DOSMOD_GET_TIMER;
   struct timeval tim;
@@ -619,17 +619,17 @@ unsigned DOSVM_GetTimer( void )
 
 #else /* !MZ_SUPPORTED */
 
-int DOSVM_Enter( CONTEXT86 *context )
+int WINAPI DOSVM_Enter( CONTEXT86 *context )
 {
  ERR_(module)("DOS realmode not supported on this architecture!\n");
  return -1;
 }
 
-void DOSVM_Wait( int read_pipe, HANDLE hObject) {}
-void DOSVM_PIC_ioport_out( WORD port, BYTE val) {}
-void DOSVM_SetTimer( unsigned ticks ) {}
-unsigned DOSVM_GetTimer( void ) { return 0; }
-void DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data)
+void WINAPI DOSVM_Wait( int read_pipe, HANDLE hObject) {}
+void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val) {}
+void WINAPI DOSVM_SetTimer( unsigned ticks ) {}
+unsigned WINAPI DOSVM_GetTimer( void ) { return 0; }
+void WINAPI DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data)
 {
   if (irq<0) {
     /* callback event, perform it with dummy context */
diff --git a/loader/dos/module.c b/dlls/winedos/module.c
similarity index 96%
rename from loader/dos/module.c
rename to dlls/winedos/module.c
index ce766fa1cbc..212aa0e9fb1 100644
--- a/loader/dos/module.c
+++ b/dlls/winedos/module.c
@@ -27,7 +27,7 @@
 #include "miscemu.h"
 #include "debugtools.h"
 #include "dosexe.h"
-#include "dosmod.h"
+#include "../../loader/dos/dosmod.h"
 #include "options.h"
 #include "vga.h"
 
@@ -199,7 +199,7 @@ static BOOL MZ_InitMemory(void)
     return TRUE;
 }
 
-BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk )
+static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk )
 {
   LPDOSTASK lpDosTask = dos_current;
   IMAGE_DOS_HEADER mz_header;
@@ -333,7 +333,7 @@ load_error:
   return FALSE;
 }
 
-BOOL MZ_LoadImage( LPCSTR cmdline )
+BOOL WINAPI MZ_LoadImage( LPCSTR cmdline )
 {
     HFILE hFile;
     char *name, buffer[MAX_PATH];
@@ -362,7 +362,7 @@ BOOL MZ_LoadImage( LPCSTR cmdline )
     return FALSE;
 }
 
-BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
+BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
 {
   /* this may only be called from existing DOS processes
    * (i.e. one DOS app spawning another) */
@@ -424,7 +424,7 @@ BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
   return ret;
 }
 
-LPDOSTASK MZ_AllocDPMITask( void )
+LPDOSTASK WINAPI MZ_AllocDPMITask( void )
 {
   LPDOSTASK lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
 
@@ -569,7 +569,7 @@ static void MZ_KillTask(void)
   kill(dosmod_pid,SIGTERM);
 }
 
-void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
+void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
 {
   LPDOSTASK lpDosTask = MZ_Current();
   if (lpDosTask) {
@@ -608,34 +608,34 @@ void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
 
 #else /* !MZ_SUPPORTED */
 
-BOOL MZ_LoadImage( LPCSTR cmdline )
+BOOL WINAPI MZ_LoadImage( LPCSTR cmdline )
 {
   WARN("DOS executables not supported on this platform\n");
   SetLastError(ERROR_BAD_FORMAT);
   return FALSE;
 }
 
-BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
+BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
 {
   /* can't happen */
   SetLastError(ERROR_BAD_FORMAT);
   return FALSE;
 }
 
-LPDOSTASK MZ_AllocDPMITask( void )
+LPDOSTASK WINAPI MZ_AllocDPMITask( void )
 {
     ERR("Actual real-mode calls not supported on this platform!\n");
     return NULL;
 }
 
-void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
+void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
 {
   ExitThread( retval );
 }
 
 #endif /* !MZ_SUPPORTED */
 
-LPDOSTASK MZ_Current( void )
+LPDOSTASK WINAPI MZ_Current( void )
 {
   return dos_current;
 }
diff --git a/dlls/winedos/winedos.spec b/dlls/winedos/winedos.spec
new file mode 100644
index 00000000000..2997fa804df
--- /dev/null
+++ b/dlls/winedos/winedos.spec
@@ -0,0 +1,19 @@
+name winedos
+type win32
+
+import user32.dll
+import kernel32.dll
+import ntdll.dll
+
+@ stdcall GetCurrent() MZ_Current
+@ stdcall LoadDPMI() MZ_AllocDPMITask
+@ stdcall LoadDosExe(str) MZ_LoadImage
+@ stdcall Exec(ptr str long ptr) MZ_Exec
+@ stdcall Exit(ptr long long) MZ_Exit
+
+@ 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
+@ stdcall SetTimer(long) DOSVM_SetTimer
+@ stdcall GetTimer() DOSVM_GetTimer
diff --git a/include/callback.h b/include/callback.h
index 7813e401541..89dc255574e 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -48,6 +48,24 @@ typedef struct
 
 extern CALLOUT_TABLE Callout;
 
+
+typedef struct {
+    struct _DOSTASK* WINAPI (*Current)( void );
+    struct _DOSTASK* WINAPI (*LoadDPMI)( void );
+    BOOL WINAPI             (*LoadDosExe)( LPCSTR cmdline );
+    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             (*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 );
+    void WINAPI             (*SetTimer)( unsigned ticks );
+    unsigned WINAPI         (*GetTimer)( void );
+} DOSVM_TABLE;
+
+extern DOSVM_TABLE Dosvm;
+
+
 #include "pshpack1.h"
 
 typedef struct tagTHUNK
diff --git a/include/dosexe.h b/include/dosexe.h
index 0ecbc8bcf9c..9a785229c46 100644
--- a/include/dosexe.h
+++ b/include/dosexe.h
@@ -30,16 +30,16 @@ typedef struct _DOSTASK {
 
 #define V86_FLAG 0x00020000
 
-extern BOOL MZ_LoadImage( LPCSTR cmdline );
-extern BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
-extern void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval );
-extern LPDOSTASK MZ_Current( void );
-extern LPDOSTASK MZ_AllocDPMITask( void );
-extern int DOSVM_Enter( CONTEXT86 *context );
-extern void DOSVM_Wait( int read_pipe, HANDLE hObject );
-extern void DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data );
-extern void DOSVM_PIC_ioport_out( WORD port, BYTE val );
-extern void DOSVM_SetTimer( unsigned ticks );
-extern unsigned DOSVM_GetTimer( void );
+extern BOOL WINAPI MZ_LoadImage( LPCSTR cmdline );
+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 int WINAPI DOSVM_Enter( CONTEXT86 *context );
+extern void WINAPI DOSVM_Wait( int read_pipe, HANDLE hObject );
+extern void WINAPI DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data );
+extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val );
+extern void WINAPI DOSVM_SetTimer( unsigned ticks );
+extern unsigned WINAPI DOSVM_GetTimer( void );
 
 #endif /* __WINE_DOSEXE_H */
diff --git a/include/miscemu.h b/include/miscemu.h
index eeaabcfa5eb..d8ff0159599 100644
--- a/include/miscemu.h
+++ b/include/miscemu.h
@@ -238,6 +238,7 @@ extern void WINAPI INT_Int33Message(UINT,WPARAM,LPARAM);
 /* msdos/dpmi.c */
 typedef void WINAPI (*RMCBPROC)(CONTEXT86*);
 extern void WINAPI INT_Int31Handler(CONTEXT86*);
+extern BOOL DPMI_LoadDosSystem(void);
 extern FARPROC16 WINAPI DPMI_AllocInternalRMCB(RMCBPROC);
 extern void WINAPI DPMI_FreeInternalRMCB(FARPROC16);
 extern int DPMI_CallRMProc(CONTEXT86*,LPWORD,int,int);
diff --git a/loader/dos/Makefile.in b/loader/dos/Makefile.in
index 4f2c29d6e88..f90d2bcc4a3 100644
--- a/loader/dos/Makefile.in
+++ b/loader/dos/Makefile.in
@@ -3,22 +3,16 @@ TOPSRCDIR = @top_srcdir@
 TOPOBJDIR = ../..
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
-MODULE    = dos
 
-C_SRCS = \
-	module.c \
-	dosvm.c
+C_SRCS = dosmod.c
 
 PROGRAMS = dosmod
 
-all: $(MODULE).o $(PROGRAMS)
+all: $(PROGRAMS)
 
 dosmod: dosmod.c
 	$(CC) $(ALLCFLAGS) -o dosmod $(SRCDIR)/dosmod.c
 
 @MAKE_RULES@
 
-$(MODULE).o: $(OBJS) Makefile.in $(TOPSRCDIR)/Make.rules.in
-	$(LDCOMBINE) $(OBJS) -o $@
-
 ### Dependencies:
diff --git a/miscemu/main.c b/miscemu/main.c
index 5bcb2d66b2b..1fa6f9254ce 100644
--- a/miscemu/main.c
+++ b/miscemu/main.c
@@ -8,6 +8,7 @@
 #include "wingdi.h"
 #include "winuser.h"
 
+#include "miscemu.h"
 #include "callback.h"
 #include "options.h"
 #include "dosexe.h"
@@ -34,7 +35,8 @@ int WINAPI wine_initial_task( HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, INT
     {
         if (instance == 11)  /* try DOS format */
         {
-            MZ_LoadImage( GetCommandLineA() );
+            if (DPMI_LoadDosSystem())
+                Dosvm.LoadDosExe( GetCommandLineA() );
             /* if we get back here it failed */
             instance = GetLastError();
         }
diff --git a/msdos/devices.c b/msdos/devices.c
index 2cbae1226bf..45e51663756 100644
--- a/msdos/devices.c
+++ b/msdos/devices.c
@@ -10,6 +10,7 @@
 #include "msdos.h"
 #include "miscemu.h"
 #include "dosexe.h"
+#include "callback.h"
 #include "debugtools.h"
 
 #include "pshpack1.h"
@@ -264,7 +265,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];
@@ -283,7 +284,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/dpmi.c b/msdos/dpmi.c
index f3255ce19cc..20906f9ae30 100644
--- a/msdos/dpmi.c
+++ b/msdos/dpmi.c
@@ -63,6 +63,36 @@ typedef struct tagRMCB {
 static RMCB *FirstRMCB = NULL;
 
 
+static LPDOSTASK WINAPI DPMI_NoCurrent(void) { return NULL; }
+DOSVM_TABLE Dosvm = { DPMI_NoCurrent };
+
+static HMODULE DosModule;
+
+/**********************************************************************
+ *	    DPMI_LoadDosSystem
+ */
+BOOL DPMI_LoadDosSystem(void)
+{
+    if (DosModule) return TRUE;
+    DosModule = LoadLibraryA( "winedos.dll" );
+    if (!DosModule) {
+        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.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");
+    return TRUE;
+}
+
 /**********************************************************************
  *	    DPMI_xalloc
  * special virtualalloc, allocates lineary monoton growing memory.
@@ -307,13 +337,11 @@ int DPMI_CallRMProc( CONTEXT86 *context, LPWORD stack, int args, int iret )
 {
     LPWORD stack16;
     LPVOID addr = NULL; /* avoid gcc warning */
-    LPDOSTASK lpDosTask = MZ_Current();
+    LPDOSTASK lpDosTask = Dosvm.Current();
     RMCB *CurrRMCB;
     int alloc = 0, already = 0;
     BYTE *code;
 
-    GlobalUnlock16( GetCurrentTask() );
-
     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",
@@ -355,7 +383,7 @@ callrmproc_again:
     if (!(CurrRMCB || lpDosTask)) {
         FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n");
         TRACE("creating VM86 task\n");
-        if (!(lpDosTask = MZ_AllocDPMITask() )) {
+        if ((!DPMI_LoadDosSystem()) || !(lpDosTask = Dosvm.LoadDPMI() )) {
             ERR("could not setup VM86 task\n");
             return 1;
         }
@@ -401,7 +429,7 @@ callrmproc_again:
         }
     } else {
         TRACE("entering real mode...\n");
-        DOSVM_Enter( context );
+        Dosvm.Enter( context );
         TRACE("returned from real-mode call\n");
     }
     if (alloc) DOSMEM_FreeBlock( addr );
@@ -630,7 +658,7 @@ static void StartPM( CONTEXT86 *context, LPDOSTASK lpDosTask )
 #if 0
 void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context )
 {
-  LPDOSTASK lpDosTask = MZ_Current();
+  LPDOSTASK lpDosTask = Dosvm.Current();
   CONTEXT86 rm_ctx;
   int ret;
 
@@ -655,9 +683,9 @@ void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context )
 
   /* enter real mode again */
   TRACE("re-entering real mode at %04lx:%04lx\n",rm_ctx.SegCs,rm_ctx.Eip);
-  ret = DOSVM_Enter( &rm_ctx );
+  ret = Dosvm.Enter( &rm_ctx );
   /* when the real-mode stuff call its mode switch address,
-     DOSVM_Enter will return and we will continue here */
+     Dosvm.Enter will return and we will continue here */
 
   if (ret<0) {
     /* if the sync was lost, there's no way to recover */
@@ -698,7 +726,7 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
     DWORD dw;
     BYTE *ptr;
 
-    LPDOSTASK lpDosTask = MZ_Current();
+    LPDOSTASK lpDosTask = Dosvm.Current();
 
     if (ISV86(context) && lpDosTask) {
         /* Called from real mode, check if it's our wrapper */
diff --git a/msdos/int09.c b/msdos/int09.c
index 16ca67acbda..513048abc0d 100644
--- a/msdos/int09.c
+++ b/msdos/int09.c
@@ -11,6 +11,7 @@
 #include "winuser.h"
 #include "miscemu.h"
 #include "debugtools.h"
+#include "callback.h"
 #include "dosexe.h"
 
 DEFAULT_DEBUG_CHANNEL(int);
@@ -59,13 +60,13 @@ void WINAPI INT_Int09Handler( CONTEXT86 *context )
       INT_Int16AddChar(0, scan);
     }
   }
-  DOSVM_PIC_ioport_out(0x20, 0x20); /* send EOI */
+  Dosvm.OutPIC(0x20, 0x20); /* send EOI */
 }
 
 static void KbdRelay( CONTEXT86 *context, void *data )
 {
   if (kbdinfo.queuelen) {
-    /* cleanup operation, called from DOSVM_PIC_ioport_out:
+    /* cleanup operation, called from Dosvm.OutPIC:
      * we'll remove current scancode from keyboard buffer here,
      * rather than in ReadScan, because some DOS apps depend on
      * the scancode being available for reading multiple times... */
@@ -86,7 +87,7 @@ void WINAPI INT_Int09SendScan( BYTE scan, BYTE ascii )
   kbdinfo.queue[kbdinfo.queuelen] = scan;
   kbdinfo.ascii[kbdinfo.queuelen++] = ascii;
   /* tell app to read it by triggering IRQ 1 (int 09) */
-  DOSVM_QueueEvent(1,DOS_PRIORITY_KEYBOARD,KbdRelay,NULL);
+  Dosvm.QueueEvent(1,DOS_PRIORITY_KEYBOARD,KbdRelay,NULL);
 }
 
 BYTE WINAPI INT_Int09ReadScan( BYTE*ascii )
diff --git a/msdos/int16.c b/msdos/int16.c
index 2d72fc24bef..feba5d93bf1 100644
--- a/msdos/int16.c
+++ b/msdos/int16.c
@@ -8,6 +8,7 @@
 
 #include "config.h"
 #include "module.h"
+#include "callback.h"
 #include "dosexe.h"
 #include "wincon.h"
 #include "debugtools.h"
@@ -139,7 +140,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 */
diff --git a/msdos/int20.c b/msdos/int20.c
index 9cc7e63890a..d493e96e3cf 100644
--- a/msdos/int20.c
+++ b/msdos/int20.c
@@ -8,7 +8,7 @@
 /* #define DEBUG_INT */
 #include "debugtools.h"
 #include "task.h"
-#include "dosexe.h"
+#include "callback.h"
 
 /**********************************************************************
  *	    INT_Int20Handler
@@ -17,5 +17,6 @@
  */
 void WINAPI INT_Int20Handler( CONTEXT86 *context )
 {
-        MZ_Exit( context, TRUE, 0 );
+        if (Dosvm.Exit) Dosvm.Exit( context, TRUE, 0 );
+        else ExitThread( 0 );
 }
diff --git a/msdos/int21.c b/msdos/int21.c
index 15c541d57bb..5d45d37837e 100644
--- a/msdos/int21.c
+++ b/msdos/int21.c
@@ -32,7 +32,8 @@
 #include "options.h"
 #include "miscemu.h"
 #include "task.h"
-#include "dosexe.h" /* for the MZ_SUPPORTED define */
+#include "dosexe.h"
+#include "callback.h"
 #include "debugtools.h"
 #include "console.h"
 
@@ -946,7 +947,7 @@ INT21_networkfunc (CONTEXT86 *context)
 
 static void INT21_SetCurrentPSP(WORD psp)
 {
-    LPDOSTASK lpDosTask = MZ_Current();
+    LPDOSTASK lpDosTask = Dosvm.Current();
     if (lpDosTask)
         lpDosTask->psp_seg = psp;
     else
@@ -955,7 +956,7 @@ static void INT21_SetCurrentPSP(WORD psp)
     
 static WORD INT21_GetCurrentPSP(void)
 {
-    LPDOSTASK lpDosTask = MZ_Current();
+    LPDOSTASK lpDosTask = Dosvm.Current();
     if (lpDosTask)
         return lpDosTask->psp_seg;
     else
@@ -964,7 +965,7 @@ static WORD INT21_GetCurrentPSP(void)
 
 static WORD INT21_GetReturnCode(void)
 {
-    LPDOSTASK lpDosTask = MZ_Current();
+    LPDOSTASK lpDosTask = Dosvm.Current();
     if (lpDosTask) {
         WORD ret = lpDosTask->retval;
         lpDosTask->retval = 0;
@@ -1144,7 +1145,8 @@ void WINAPI DOS3Call( CONTEXT86 *context )
 
     case 0x00: /* TERMINATE PROGRAM */
         TRACE("TERMINATE PROGRAM\n");
-        MZ_Exit( context, FALSE, 0 );
+        if (Dosvm.Exit) Dosvm.Exit( context, FALSE, 0 );
+        else ExitThread( 0 );
         break;
 
     case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
@@ -1843,7 +1845,7 @@ void WINAPI DOS3Call( CONTEXT86 *context )
         TRACE("EXEC %s\n",
 	      (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
 	if (ISV86(context)) {
-            if (!MZ_Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx),
+            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 {
@@ -1856,7 +1858,8 @@ void WINAPI DOS3Call( CONTEXT86 *context )
 	
     case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
         TRACE("EXIT with return code %d\n",AL_reg(context));
-        MZ_Exit( context, FALSE, AL_reg(context) );
+        if (Dosvm.Exit) Dosvm.Exit( context, FALSE, AL_reg(context) );
+        else ExitThread( AL_reg(context) );
         break;
 
     case 0x4d: /* GET RETURN CODE */
diff --git a/msdos/int33.c b/msdos/int33.c
index 90619a517de..7a8ee43136e 100644
--- a/msdos/int33.c
+++ b/msdos/int33.c
@@ -9,6 +9,7 @@
 #include "wingdi.h"
 #include "winuser.h"
 #include "miscemu.h"
+#include "callback.h"
 #include "dosexe.h"
 #include "vga.h"
 #include "debugtools.h"
@@ -150,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/msdos/ioports.c b/msdos/ioports.c
index a87ae76899d..b43bfde1a34 100644
--- a/msdos/ioports.c
+++ b/msdos/ioports.c
@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include "windef.h"
 #include "vga.h"
+#include "callback.h"
 #include "dosexe.h"
 #include "options.h"
 #include "miscemu.h"
@@ -91,7 +92,7 @@ static void set_timer_maxval(unsigned timer, unsigned maxval)
 {
     switch (timer) {
         case 0: /* System timer counter divisor */
-            DOSVM_SetTimer(maxval);
+            Dosvm.SetTimer(maxval);
             break;
         case 1: /* RAM refresh */
             FIXME("RAM refresh counter handling not implemented !");
@@ -292,8 +293,8 @@ DWORD IO_inport( int port, int size )
 	    dummy_ctr -= 1 + (int)(10.0 * rand() / (RAND_MAX + 1.0));
 	    if (chan == 0) /* System timer counter divisor */
 	    {
-		/* FIXME: DOSVM_GetTimer() returns quite rigid values */
-		tempval = dummy_ctr + (WORD)DOSVM_GetTimer();
+		/* FIXME: Dosvm.GetTimer() returns quite rigid values */
+		tempval = dummy_ctr + (WORD)Dosvm.GetTimer();
 	    }
 	    else
 	    {
@@ -393,7 +394,7 @@ void IO_outport( int port, int size, DWORD value )
     switch (port)
     {
     case 0x20:
-        DOSVM_PIC_ioport_out( port, (BYTE)value );
+        Dosvm.OutPIC( port, (BYTE)value );
         break;
     case 0x40:
     case 0x41:
@@ -450,7 +451,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 */
-		tmr_8253[chan].latch = dummy_ctr + (WORD)DOSVM_GetTimer();
+		tmr_8253[chan].latch = dummy_ctr + (WORD)Dosvm.GetTimer();
 	    else
 	    {
 		/* FIXME: intelligent hardware timer emulation needed */
-- 
GitLab