Moved most global data out of the LPDOSTASK structure.
Allocate DPMI real-mode segments globally at startup.
Try to allocate DOS memory at address 0.

diff --git a/include/dosexe.h b/include/dosexe.h
index de4f3b6..6188c66 100644
--- a/include/dosexe.h
+++ b/include/dosexe.h
@@ -11,38 +11,13 @@
 #include "winbase.h"   /* for LPSTARTUPINFO32A */
 #include "winnt.h"     /* for PCONTEXT */
 
-typedef struct _DOSSYSTEM {
-  int id;
-  void *data;
-  struct _DOSSYSTEM *next;
-} DOSSYSTEM;
-
 struct _DOSEVENT;
 
 typedef struct _DOSTASK {
- LPVOID img;
- unsigned img_ofs;
- WORD psp_seg,load_seg;
- WORD init_cs,init_ip,init_ss,init_sp;
- WORD xms_seg;
- WORD dpmi_seg,dpmi_sel,dpmi_flag;
- char mm_name[128];
- int mm_fd;
- HANDLE hReadPipe,hXPipe,hConInput,hConOutput;
- int read_pipe,write_pipe;
- pid_t task;
- int sig_sent,entered,idling;
- struct _DOSEVENT *pending,*current;
- DOSSYSTEM *sys;
+ WORD psp_seg;
+ WORD dpmi_flag;
 } DOSTASK, *LPDOSTASK;
 
-typedef struct _DOSEVENT {
-  int irq,priority;
-  void (*relay)(LPDOSTASK,CONTEXT86*,void*);
-  void *data;
-  struct _DOSEVENT *next;
-} DOSEVENT, *LPDOSEVENT;
-
 #define DOS_PRIORITY_REALTIME 0  /* IRQ0 */
 #define DOS_PRIORITY_KEYBOARD 1  /* IRQ1 */
 #define DOS_PRIORITY_VGA      2  /* IRQ9 */
@@ -50,26 +25,19 @@
 #define DOS_PRIORITY_SERIAL   10 /* IRQ4 */
 
 #if defined(linux) && defined(__i386__)
-
 #define MZ_SUPPORTED
-
-extern BOOL MZ_InitTask( LPDOSTASK lpDosTask );
-extern void MZ_KillTask( LPDOSTASK lpDosTask );
-extern LPDOSTASK MZ_AllocDPMITask( void );
-
 #endif /* linux-i386 */
 
 #define V86_FLAG 0x00020000
 
 extern BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename );
 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)(LPDOSTASK,CONTEXT86*,void*), void *data );
+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 void DOSVM_SetSystemData( int id, void *data );
-extern void* DOSVM_GetSystemData( int id );
 
 #endif /* __WINE_DOSEXE_H */
diff --git a/include/ldt.h b/include/ldt.h
index c6ae65c..d600042 100644
--- a/include/ldt.h
+++ b/include/ldt.h
@@ -60,6 +60,8 @@
 
 #define PTR_SEG_OFF_TO_LIN(seg,off) \
    ((void*)(GET_SEL_BASE(seg) + (unsigned int)(off)))
+#define PTR_REAL_TO_LIN(seg,off) \
+   ((void*)(((unsigned int)(seg) << 4) + LOWORD(off)))
 #define PTR_SEG_TO_LIN(ptr) \
    PTR_SEG_OFF_TO_LIN(SELECTOROF(ptr),OFFSETOF(ptr))
 #define PTR_SEG_OFF_TO_SEGPTR(seg,off) \
diff --git a/include/miscemu.h b/include/miscemu.h
index 7807486..32fed3c 100644
--- a/include/miscemu.h
+++ b/include/miscemu.h
@@ -128,8 +128,11 @@
 
 extern DWORD DOSMEM_CollateTable;
 
-extern DWORD DOSMEM_ErrorCall;
-extern DWORD DOSMEM_ErrorBuffer;
+/* various real-mode code stubs */
+extern WORD DOSMEM_wrap_seg;
+extern WORD DOSMEM_xms_seg;
+extern WORD DOSMEM_dpmi_seg;
+extern WORD DOSMEM_dpmi_sel;
 
 extern DWORD DOS_LOLSeg;
 extern struct _DOS_LISTOFLISTS * DOSMEM_LOL();
@@ -249,7 +252,7 @@
  *       a *32-bit* general register as third parameter, e.g.
  *          CTX_SEG_OFF_TO_LIN( context, DS_reg(context), EDX_reg(context) )
  *       This will generate a linear pointer in all three cases:
- *         Real-Mode:   Seg*16 + LOWORD(Offset) + V86BASE
+ *         Real-Mode:   Seg*16 + LOWORD(Offset)
  *         16-bit:      convert (Seg, LOWORD(Offset)) to linear
  *         32-bit:      use Offset as linear address (DeviceIoControl!)
  *
@@ -258,8 +261,8 @@
  *       (0 counts also as 32-bit segment).
  */
 #define CTX_SEG_OFF_TO_LIN(context,seg,off) \
-    (ISV86(context) ? (void*)(V86BASE(context)+((seg)<<4)+(off&0xffff)) : \
-     (!seg || IS_SELECTOR_SYSTEM(seg))? (void *)off : PTR_SEG_OFF_TO_LIN(seg,off&0xffff))
+    (ISV86(context) ? PTR_REAL_TO_LIN((seg),(off)) : \
+     (!seg || IS_SELECTOR_SYSTEM(seg))? (void *)(off) : PTR_SEG_OFF_TO_LIN((seg),LOWORD(off)))
 
 #define INT_BARF(context,num) \
     ERR( "int%x: unknown/not implemented parameters:\n" \
diff --git a/include/winnt.h b/include/winnt.h
index cc0a550..b175a22 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -730,7 +730,6 @@
 #define RESET_ZFLAG(context) (EFL_reg(context) &= ~0x0040)
 
 #define ISV86(context)       (EFL_reg(context) & 0x00020000)
-#define V86BASE(context)     DOSMEM_MemoryBase()
 
 
 /* Macros to retrieve the current context */
diff --git a/loader/dos/dosvm.c b/loader/dos/dosvm.c
index 790b5d3..241f669 100644
--- a/loader/dos/dosvm.c
+++ b/loader/dos/dosvm.c
@@ -58,6 +58,21 @@
 
 #undef TRY_PICRETURN
 
+typedef struct _DOSEVENT {
+  int irq,priority;
+  void (*relay)(CONTEXT86*,void*);
+  void *data;
+  struct _DOSEVENT *next;
+} DOSEVENT, *LPDOSEVENT;
+
+static struct _DOSEVENT *pending_event, *current_event;
+static int sig_sent, entered;
+
+/* from module.c */
+extern int read_pipe, write_pipe;
+extern HANDLE hReadPipe;
+extern pid_t dosmod_pid;
+
 static void do_exception( int signal, CONTEXT86 *context )
 {
     EXCEPTION_RECORD rec;
@@ -77,10 +92,8 @@
     EXC_RtlRaiseException( &rec, context );
 }
 
-static void DOSVM_Dump( LPDOSTASK lpDosTask, int fn, int sig,
-                        struct vm86plus_struct*VM86 )
+static void DOSVM_Dump( int fn, int sig, struct vm86plus_struct*VM86 )
 {
- unsigned iofs;
  BYTE*inst;
  int x;
 
@@ -106,20 +119,17 @@
  fprintf(stderr,"CS=%04X DS=%04X ES=%04X SS=%04X\n",REGS.cs,REGS.ds,REGS.es,REGS.ss);
  fprintf(stderr,"IP=%04lX EFLAGS=%08lX\n",REGS.eip,REGS.eflags);
 
- iofs=((DWORD)REGS.cs<<4)+REGS.eip;
+ inst = PTR_REAL_TO_LIN( REGS.cs, REGS.eip );
 #undef REGS
- inst=(BYTE*)lpDosTask->img+iofs;
  printf("Opcodes:");
  for (x=0; x<8; x++) printf(" %02x",inst[x]);
  printf("\n");
 }
 
-static int DOSVM_Int( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask )
+static int DOSVM_Int( int vect, CONTEXT86 *context )
 {
- extern UINT16 DPMI_wrap_seg;
-
  if (vect==0x31) {
-  if (CS_reg(context)==DPMI_wrap_seg) {
+  if (CS_reg(context)==DOSMEM_wrap_seg) {
    /* exit from real-mode wrapper */
    return -1;
   }
@@ -129,7 +139,7 @@
  return 0;
 }
 
-static void DOSVM_SimulateInt( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask )
+static void DOSVM_SimulateInt( int vect, CONTEXT86 *context )
 {
   FARPROC16 handler=INT_GetRMHandler(vect);
 
@@ -137,7 +147,7 @@
     /* if internal interrupt, call it directly */
     INT_RealModeInterrupt(vect,context);
   } else {
-    WORD*stack=(WORD*)(V86BASE(context)+(((DWORD)SS_reg(context))<<4)+LOWORD(ESP_reg(context)));
+    WORD*stack= PTR_REAL_TO_LIN( context->SegSs, context->Esp );
     WORD flag=LOWORD(EFL_reg(context));
 
     if (IF_ENABLED(context)) flag|=IF_MASK;
@@ -154,51 +164,50 @@
 }
 
 #define SHOULD_PEND(x) \
-  (x && ((!lpDosTask->current) || (x->priority < lpDosTask->current->priority)))
+  (x && ((!current_event) || (x->priority < current_event->priority)))
 
-static void DOSVM_SendQueuedEvent(CONTEXT86 *context, LPDOSTASK lpDosTask)
+static void DOSVM_SendQueuedEvent(CONTEXT86 *context)
 {
-  LPDOSEVENT event = lpDosTask->pending;
+  LPDOSEVENT event = pending_event;
 
   if (SHOULD_PEND(event)) {
     /* remove from "pending" list */
-    lpDosTask->pending = event->next;
+    pending_event = event->next;
     /* process event */
     if (event->irq>=0) {
       /* it's an IRQ, move it to "current" list */
-      event->next = lpDosTask->current;
-      lpDosTask->current = event;
+      event->next = current_event;
+      current_event = event;
       TRACE_(int)("dispatching IRQ %d\n",event->irq);
       /* note that if DOSVM_SimulateInt calls an internal interrupt directly,
-       * lpDosTask->current might be cleared (and event freed) in this very call! */
-      DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context,lpDosTask);
+       * current_event might be cleared (and event freed) in this very call! */
+      DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context);
     } else {
       /* callback event */
       TRACE_(int)("dispatching callback event\n");
-      (*event->relay)(lpDosTask,context,event->data);
+      (*event->relay)(context,event->data);
       free(event);
     }
   }
-  if (!SHOULD_PEND(lpDosTask->pending)) {
+  if (!SHOULD_PEND(pending_event)) {
     TRACE_(int)("clearing Pending flag\n");
     CLR_PEND(context);
   }
 }
 
-static void DOSVM_SendQueuedEvents(CONTEXT86 *context, LPDOSTASK lpDosTask)
+static void DOSVM_SendQueuedEvents(CONTEXT86 *context)
 {
   /* we will send all queued events as long as interrupts are enabled,
    * but IRQ events will disable interrupts again */
   while (IS_PEND(context) && IF_ENABLED(context))
-    DOSVM_SendQueuedEvent(context,lpDosTask);
+    DOSVM_SendQueuedEvent(context);
 }
 
-void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*,void*), void *data)
+void DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data)
 {
-  LPDOSTASK lpDosTask = MZ_Current();
   LPDOSEVENT event, cur, prev;
 
-  if (lpDosTask && lpDosTask->entered) {
+  if (entered) {
     event = malloc(sizeof(DOSEVENT));
     if (!event) {
       ERR_(int)("out of memory allocating event entry\n");
@@ -209,20 +218,20 @@
 
     /* insert event into linked list, in order *after*
      * all earlier events of higher or equal priority */
-    cur = lpDosTask->pending; prev = NULL;
+    cur = pending_event; prev = NULL;
     while (cur && cur->priority<=priority) {
       prev = cur;
       cur = cur->next;
     }
     event->next = cur;
     if (prev) prev->next = event;
-    else lpDosTask->pending = event;
+    else pending_event = event;
     
     /* get dosmod's attention to the new event, if necessary */
-    if (!lpDosTask->sig_sent) {
+    if (!sig_sent) {
       TRACE_(int)("new event queued, signalling dosmod\n");
-      kill(lpDosTask->task,SIGUSR2);
-      lpDosTask->sig_sent++;
+      kill(dosmod_pid,SIGUSR2);
+      sig_sent++;
     } else {
       TRACE_(int)("new event queued\n");
     }
@@ -234,7 +243,7 @@
       /* callback event, perform it with dummy context */
       CONTEXT86 context;
       memset(&context,0,sizeof(context));
-      (*relay)(lpDosTask,&context,data);
+      (*relay)(&context,data);
     } else {
       ERR_(int)("IRQ without DOS task: should not happen");
     }
@@ -247,8 +256,7 @@
            CP(ss,SS); CP(fs,FS); CP(gs,GS); \
            CP(eip,EIP); CP(eflags,EFL)
 
-static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig,
-                          struct vm86plus_struct*VM86 )
+static int DOSVM_Process( int fn, int sig, struct vm86plus_struct*VM86 )
 {
  CONTEXT86 context;
  int ret=0;
@@ -270,7 +278,7 @@
  }
 #else
  /* linux doesn't preserve pending flag on return */
- if (SHOULD_PEND(lpDosTask->pending)) {
+ if (SHOULD_PEND(pending_event)) {
    SET_PEND(&context);
  }
 #endif
@@ -280,48 +288,48 @@
    TRACE_(int)("DOS module caught signal %d\n",sig);
    if ((sig==SIGALRM) || (sig==SIGUSR2)) {
      if (sig==SIGALRM) {
-       lpDosTask->sig_sent++;
+       sig_sent++;
        DOSVM_QueueEvent(0,DOS_PRIORITY_REALTIME,NULL,NULL);
      }
-     if (lpDosTask->pending) {
+     if (pending_event) {
        TRACE_(int)("setting Pending flag, interrupts are currently %s\n",
                  IF_ENABLED(&context) ? "enabled" : "disabled");
        SET_PEND(&context);
-       DOSVM_SendQueuedEvents(&context,lpDosTask);
+       DOSVM_SendQueuedEvents(&context);
      } else {
        TRACE_(int)("no events are pending, clearing Pending flag\n");
        CLR_PEND(&context);
      }
-     lpDosTask->sig_sent--;
+     sig_sent--;
    }
    else if ((sig==SIGHUP) || (sig==SIGILL) || (sig==SIGSEGV)) {
        do_exception( sig, &context );
    } else {
-    DOSVM_Dump(lpDosTask,fn,sig,VM86);
+    DOSVM_Dump(fn,sig,VM86);
     ret=-1;
    }
    break;
   case VM86_UNKNOWN: /* unhandled GPF */
-   DOSVM_Dump(lpDosTask,fn,sig,VM86);
+   DOSVM_Dump(fn,sig,VM86);
    do_exception( SIGSEGV, &context );
    break;
   case VM86_INTx:
    if (TRACE_ON(relay))
     DPRINTF("Call DOS int 0x%02x (EAX=%08lx) ret=%04lx:%04lx\n",VM86_ARG(fn),context.Eax,context.SegCs,context.Eip);
-   ret=DOSVM_Int(VM86_ARG(fn),&context,lpDosTask);
+   ret=DOSVM_Int(VM86_ARG(fn),&context);
    if (TRACE_ON(relay))
     DPRINTF("Ret  DOS int 0x%02x (EAX=%08lx) ret=%04lx:%04lx\n",VM86_ARG(fn),context.Eax,context.SegCs,context.Eip);
    break;
   case VM86_STI:
   case VM86_PICRETURN:
     TRACE_(int)("DOS task enabled interrupts with events pending, sending events\n");
-    DOSVM_SendQueuedEvents(&context,lpDosTask);
+    DOSVM_SendQueuedEvents(&context);
     break;
   case VM86_TRAP:
    do_exception( SIGTRAP, &context );
    break;
   default:
-   DOSVM_Dump(lpDosTask,fn,sig,VM86);
+   DOSVM_Dump(fn,sig,VM86);
    ret=-1;
  }
 
@@ -335,7 +343,7 @@
  return ret;
 }
 
-static void DOSVM_ProcessConsole(LPDOSTASK lpDosTask)
+static void DOSVM_ProcessConsole(void)
 {
   INPUT_RECORD msg;
   DWORD res;
@@ -360,7 +368,7 @@
   }
 }
 
-static void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg)
+static void DOSVM_ProcessMessage(MSG *msg)
 {
   BYTE scan = 0;
 
@@ -391,21 +399,20 @@
 
 void DOSVM_Wait( int read_pipe, HANDLE hObject )
 {
-  LPDOSTASK lpDosTask = MZ_Current();
   MSG msg;
   DWORD waitret;
   HANDLE objs[2];
   int objc;
   BOOL got_msg = FALSE;
 
-  objs[0]=lpDosTask->hConInput;
+  objs[0]=GetStdHandle(STD_INPUT_HANDLE);
   objs[1]=hObject;
   objc=hObject?2:1;
   do {
     /* check for messages (waste time before the response check below) */
     while (Callout.PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) {
       /* got a message */
-      DOSVM_ProcessMessage(lpDosTask,&msg);
+      DOSVM_ProcessMessage(&msg);
       /* we don't need a TranslateMessage here */
       Callout.DispatchMessageA(&msg);
       got_msg = TRUE;
@@ -415,7 +422,7 @@
       INPUT_RECORD msg;
       DWORD num;
       if (PeekConsoleInputA(objs[0],&msg,1,&num) && num) {
-        DOSVM_ProcessConsole(lpDosTask);
+        DOSVM_ProcessConsole();
         got_msg = TRUE;
       }
     }
@@ -439,63 +446,42 @@
       if (waitret==(WAIT_OBJECT_0+1)) break;
     }
     if (waitret==WAIT_OBJECT_0) {
-      DOSVM_ProcessConsole(lpDosTask);
+      DOSVM_ProcessConsole();
     }
   } while (TRUE);
 }
 
 int DOSVM_Enter( CONTEXT86 *context )
 {
- LPDOSTASK lpDosTask = MZ_Current();
  struct vm86plus_struct VM86;
  int stat,len,sig;
 
- if (!lpDosTask) {
-  /* MZ_CreateProcess or MZ_AllocDPMITask should have been called first */
-  ERR_(module)("dosmod has not been initialized!");
-  return -1;
- }
-
- if (context) {
 #define CP(x,y) VM86.regs.x = y##_reg(context)
   CV;
 #undef CP
   if (VM86.regs.eflags & IF_MASK)
     VM86.regs.eflags |= VIF_MASK;
- } else {
-/* initial setup */
-  /* registers */
-  memset(&VM86,0,sizeof(VM86));
-  VM86.regs.cs=lpDosTask->init_cs;
-  VM86.regs.eip=lpDosTask->init_ip;
-  VM86.regs.ss=lpDosTask->init_ss;
-  VM86.regs.esp=lpDosTask->init_sp;
-  VM86.regs.ds=lpDosTask->psp_seg;
-  VM86.regs.es=lpDosTask->psp_seg;
-  VM86.regs.eflags=VIF_MASK;
-  /* hmm, what else do we need? */
- }
 
  /* main exchange loop */
- lpDosTask->entered++;
+ entered++;
  do {
   TRACE_(module)("thread is: %lx\n",GetCurrentThreadId());
   stat = VM86_ENTER;
   errno = 0;
   /* transmit VM86 structure to dosmod task */
-  if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
-   ERR_(module)("dosmod sync lost, errno=%d, fd=%d, pid=%d\n",errno,lpDosTask->write_pipe,getpid());
+  if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
+   ERR_(module)("dosmod sync lost, errno=%d, fd=%d, pid=%d\n",errno,write_pipe,getpid());
    return -1;
   }
-  if (write(lpDosTask->write_pipe,&VM86,sizeof(VM86))!=sizeof(VM86)) {
+  if (write(write_pipe,&VM86,sizeof(VM86))!=sizeof(VM86)) {
    ERR_(module)("dosmod sync lost, errno=%d\n",errno);
    return -1;
   }
   /* wait for response, doing other things in the meantime */
-  DOSVM_Wait(lpDosTask->read_pipe, lpDosTask->hReadPipe);
+  DOSVM_Wait(read_pipe, hReadPipe);
   /* read response */
   while (1) {
-    if ((len=read(lpDosTask->read_pipe,&stat,sizeof(stat)))==sizeof(stat)) break;
+    if ((len=read(read_pipe,&stat,sizeof(stat)))==sizeof(stat)) break;
     if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) {
      WARN_(module)("rereading dosmod return code due to errno=%d, result=%d\n",errno,len);
      continue;
@@ -505,11 +491,10 @@
   }
   TRACE_(module)("dosmod return code=%d\n",stat);
   if (stat==DOSMOD_LEFTIDLE) {
-    lpDosTask->idling--;
     continue;
   }
   while (1) {
-    if ((len=read(lpDosTask->read_pipe,&VM86,sizeof(VM86)))==sizeof(VM86)) break;
+    if ((len=read(read_pipe,&VM86,sizeof(VM86)))==sizeof(VM86)) break;
     if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) {
      WARN_(module)("rereading dosmod VM86 structure due to errno=%d, result=%d\n",errno,len);
      continue;
@@ -519,7 +504,7 @@
   }
   if ((stat&0xff)==DOSMOD_SIGNAL) {
     while (1) {
-      if ((len=read(lpDosTask->read_pipe,&sig,sizeof(sig)))==sizeof(sig)) break;
+      if ((len=read(read_pipe,&sig,sizeof(sig)))==sizeof(sig)) break;
       if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) {
 	WARN_(module)("rereading dosmod signal due to errno=%d, result=%d\n",errno,len);
 	continue;
@@ -529,8 +514,8 @@
     } while (0);
   } else sig=0;
   /* got response */
- } while (DOSVM_Process(lpDosTask,stat,sig,&VM86)>=0);
- lpDosTask->entered--;
+ } while (DOSVM_Process(stat,sig,&VM86)>=0);
+ entered--;
 
  if (context) {
 #define CP(x,y) y##_reg(context) = VM86.regs.x
@@ -542,27 +527,25 @@
 
 void DOSVM_PIC_ioport_out( WORD port, BYTE val)
 {
-  LPDOSTASK lpDosTask = MZ_Current();
-  LPDOSEVENT event;
+    LPDOSEVENT event;
 
-  if (lpDosTask) {
     if ((port==0x20) && (val==0x20)) {
-      if (lpDosTask->current) {
+      if (current_event) {
 	/* EOI (End Of Interrupt) */
 	TRACE_(int)("received EOI for current IRQ, clearing\n");
-	event = lpDosTask->current;
-	lpDosTask->current = event->next;
+	event = current_event;
+	current_event = event->next;
 	if (event->relay)
-	(*event->relay)(lpDosTask,NULL,event->data);
+	(*event->relay)(NULL,event->data);
 	free(event);
 
-	if (lpDosTask->pending &&
-	    !lpDosTask->sig_sent) {
+	if (pending_event &&
+	    !sig_sent) {
 	  /* another event is pending, which we should probably
 	   * be able to process now, so tell dosmod about it */
 	  TRACE_(int)("another event pending, signalling dosmod\n");
-	  kill(lpDosTask->task,SIGUSR2);
-	  lpDosTask->sig_sent++;
+	  kill(dosmod_pid,SIGUSR2);
+	  sig_sent++;
 	}
       } else {
 	WARN_(int)("EOI without active IRQ\n");
@@ -570,27 +553,25 @@
     } else {
       FIXME_(int)("unrecognized PIC command %02x\n",val);
     }
-  }
 }
 
 void DOSVM_SetTimer( unsigned ticks )
 {
-  LPDOSTASK lpDosTask = MZ_Current();
   int stat=DOSMOD_SET_TIMER;
   struct timeval tim;
 
-  if (lpDosTask) {
+  if (MZ_Current()) {
     /* the PC clocks ticks at 1193180 Hz */
     tim.tv_sec=0;
     tim.tv_usec=((unsigned long long)ticks*1000000)/1193180;
     /* sanity check */
     if (!tim.tv_usec) tim.tv_usec=1;
 
-    if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
+    if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
       ERR_(module)("dosmod sync lost, errno=%d\n",errno);
       return;
     }
-    if (write(lpDosTask->write_pipe,&tim,sizeof(tim))!=sizeof(tim)) {
+    if (write(write_pipe,&tim,sizeof(tim))!=sizeof(tim)) {
       ERR_(module)("dosmod sync lost, errno=%d\n",errno);
       return;
     }
@@ -600,18 +581,17 @@
 
 unsigned DOSVM_GetTimer( void )
 {
-  LPDOSTASK lpDosTask = MZ_Current();
   int stat=DOSMOD_GET_TIMER;
   struct timeval tim;
 
-  if (lpDosTask) {
-    if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
+  if (MZ_Current()) {
+    if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
       ERR_(module)("dosmod sync lost, errno=%d\n",errno);
       return 0;
     }
     /* read response */
     while (1) {
-      if (read(lpDosTask->read_pipe,&tim,sizeof(tim))==sizeof(tim)) break;
+      if (read(read_pipe,&tim,sizeof(tim))==sizeof(tim)) break;
       if ((errno==EINTR)||(errno==EAGAIN)) continue;
       ERR_(module)("dosmod sync lost, errno=%d\n",errno);
       return 0;
@@ -621,47 +601,6 @@
   return 0;
 }
 
-void DOSVM_SetSystemData( int id, void *data )
-{
-  LPDOSTASK lpDosTask = MZ_Current();
-  DOSSYSTEM *sys, *prev;
-
-  if (lpDosTask) {
-    sys = lpDosTask->sys;
-    prev = NULL;
-    while (sys && (sys->id != id)) {
-      prev = sys;
-      sys = sys->next;
-    }
-    if (sys) {
-      free(sys->data);
-      sys->data = data;
-    } else {
-      sys = malloc(sizeof(DOSSYSTEM));
-      sys->id = id;
-      sys->data = data;
-      sys->next = NULL;
-      if (prev) prev->next = sys;
-      else lpDosTask->sys = sys;
-    }
-  } else free(data);
-}
-
-void* DOSVM_GetSystemData( int id )
-{
-  LPDOSTASK lpDosTask = MZ_Current();
-  DOSSYSTEM *sys;
-
-  if (lpDosTask) {
-    sys = lpDosTask->sys;
-    while (sys && (sys->id != id))
-      sys = sys->next;
-    if (sys)
-      return sys->data;
-  }
-  return NULL;
-}
-
 #else /* !MZ_SUPPORTED */
 
 int DOSVM_Enter( CONTEXT86 *context )
@@ -674,15 +613,13 @@
 void DOSVM_PIC_ioport_out( WORD port, BYTE val) {}
 void DOSVM_SetTimer( unsigned ticks ) {}
 unsigned DOSVM_GetTimer( void ) { return 0; }
-void DOSVM_SetSystemData( int id, void *data ) { free(data); }
-void* DOSVM_GetSystemData( int id ) { return NULL; }
-void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*,void*), void *data)
+void DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data)
 {
   if (irq<0) {
     /* callback event, perform it with dummy context */
     CONTEXT86 context;
     memset(&context,0,sizeof(context));
-    (*relay)(NULL,&context,data);
+    (*relay)(&context,data);
   } else {
     ERR_(int)("IRQ without DOS task: should not happen");
   }
diff --git a/loader/dos/module.c b/loader/dos/module.c
index f75d85a..3636cb4 100644
--- a/loader/dos/module.c
+++ b/loader/dos/module.c
@@ -37,6 +37,8 @@
 
 DEFAULT_DEBUG_CHANNEL(module);
 
+static LPDOSTASK dos_current;
+
 #ifdef MZ_SUPPORTED
 
 #ifdef HAVE_SYS_MMAN_H
@@ -48,15 +50,21 @@
 #undef MZ_MAPSELF
 
 #define BIOS_DATA_SEGMENT 0x40
-#define START_OFFSET 0
 #define PSP_SIZE 0x10
 
 #define SEG16(ptr,seg) ((LPVOID)((BYTE*)ptr+((DWORD)(seg)<<4)))
 #define SEGPTR16(ptr,segptr) ((LPVOID)((BYTE*)ptr+((DWORD)SELECTOROF(segptr)<<4)+OFFSETOF(segptr)))
 
-static LPDOSTASK dos_current;
+static WORD init_cs,init_ip,init_ss,init_sp;
+static char mm_name[128];
+
+int read_pipe, write_pipe;
+HANDLE hReadPipe, hWritePipe;
+pid_t dosmod_pid;
 
 static void MZ_Launch(void);
+static BOOL MZ_InitTask(void);
+static void MZ_KillTask(void);
 
 static void MZ_CreatePSP( LPVOID lpPSP, WORD env )
 {
@@ -107,68 +115,18 @@
  0xCF                 /* iret */
 };
 
-static void MZ_InitHandlers( LPDOSTASK lpDosTask )
+static void MZ_InitHandlers(void)
 {
  WORD seg;
  LPBYTE start=DOSMEM_GetBlock(sizeof(int08),&seg);
  memcpy(start,int08,sizeof(int08));
 /* INT 08: point it at our tick-incrementing handler */
- ((SEGPTR*)(lpDosTask->img))[0x08]=PTR_SEG_OFF_TO_SEGPTR(seg,0);
+ ((SEGPTR*)0)[0x08]=PTR_SEG_OFF_TO_SEGPTR(seg,0);
 /* INT 1C: just point it to IRET, we don't want to handle it ourselves */
- ((SEGPTR*)(lpDosTask->img))[0x1C]=PTR_SEG_OFF_TO_SEGPTR(seg,sizeof(int08)-1);
+ ((SEGPTR*)0)[0x1C]=PTR_SEG_OFF_TO_SEGPTR(seg,sizeof(int08)-1);
 }
 
-static char enter_xms[]={
-/* XMS hookable entry point */
- 0xEB,0x03,           /* jmp entry */
- 0x90,0x90,0x90,      /* nop;nop;nop */
-                      /* entry: */
-/* real entry point */
-/* for simplicity, we'll just use the same hook as DPMI below */
- 0xCD,0x31,           /* int $0x31 */
- 0xCB                 /* lret */
-};
-
-static void MZ_InitXMS( LPDOSTASK lpDosTask )
-{
- LPBYTE start=DOSMEM_GetBlock(sizeof(enter_xms),&(lpDosTask->xms_seg));
- memcpy(start,enter_xms,sizeof(enter_xms));
-}
-
-static char enter_pm[]={
- 0x50,                /* pushw %ax */
- 0x52,                /* pushw %dx */
- 0x55,                /* pushw %bp */
- 0x89,0xE5,           /* movw %sp,%bp */
-/* get return CS */
- 0x8B,0x56,0x08,      /* movw 8(%bp),%dx */
-/* just call int 31 here to get into protected mode... */
-/* it'll check whether it was called from dpmi_seg... */
- 0xCD,0x31,           /* int $0x31 */
-/* we are now in the context of a 16-bit relay call */
-/* need to fixup our stack;
- * 16-bit relay return address will be lost, but we won't worry quite yet */
- 0x8E,0xD0,           /* movw %ax,%ss */
- 0x66,0x0F,0xB7,0xE5, /* movzwl %bp,%esp */
-/* set return CS */
- 0x89,0x56,0x08,      /* movw %dx,8(%bp) */
- 0x5D,                /* popw %bp */
- 0x5A,                /* popw %dx */
- 0x58,                /* popw %ax */
- 0xCB                 /* lret */
-};
-
-static void MZ_InitDPMI( LPDOSTASK lpDosTask )
-{
- unsigned size=sizeof(enter_pm);
- LPBYTE start=DOSMEM_GetBlock(size,&(lpDosTask->dpmi_seg));
- 
- lpDosTask->dpmi_sel = SELECTOR_AllocBlock( start, size, SEGMENT_CODE, FALSE, FALSE );
-
- memcpy(start,enter_pm,sizeof(enter_pm));
-}
-
-static WORD MZ_InitEnvironment( LPDOSTASK lpDosTask, LPCSTR env, LPCSTR name )
+static WORD MZ_InitEnvironment( LPCSTR env, LPCSTR name )
 {
  unsigned sz=0;
  WORD seg;
@@ -191,39 +149,33 @@
  return seg;
 }
 
-static BOOL MZ_InitMemory( LPDOSTASK lpDosTask )
+static BOOL MZ_InitMemory(void)
 {
- if (lpDosTask->img) return TRUE; /* already allocated */
+    int mm_fd;
+    void *img_base;
 
- /* allocate 1MB+64K shared memory */
- lpDosTask->img_ofs=START_OFFSET;
-#ifdef MZ_MAPSELF
- lpDosTask->img=VirtualAlloc(NULL,0x110000,MEM_COMMIT,PAGE_READWRITE);
- /* make sure mmap accepts it */
- ((char*)lpDosTask->img)[0x10FFFF]=0;
-#else
- tmpnam(lpDosTask->mm_name);
-/* strcpy(lpDosTask->mm_name,"/tmp/mydosimage"); */
- lpDosTask->mm_fd=open(lpDosTask->mm_name,O_RDWR|O_CREAT /* |O_TRUNC */,S_IRUSR|S_IWUSR);
- if (lpDosTask->mm_fd<0) ERR("file %s could not be opened\n",lpDosTask->mm_name);
- /* expand file to 1MB+64K */
- ftruncate(lpDosTask->mm_fd,0x110000);
- /* map it in */
- lpDosTask->img=mmap(NULL,0x110000-START_OFFSET,PROT_READ|PROT_WRITE,MAP_SHARED,lpDosTask->mm_fd,0);
-#endif
- if (lpDosTask->img==(LPVOID)-1) {
-  ERR("could not map shared memory, error=%s\n",strerror(errno));
-  return FALSE;
- }
- TRACE("DOS VM86 image mapped at %08lx\n",(DWORD)lpDosTask->img);
+    /* initialize the memory */
+    TRACE("Initializing DOS memory structures\n");
+    DOSMEM_Init(TRUE);
 
- /* initialize the memory */
- TRACE("Initializing DOS memory structures\n");
- DOSMEM_Init(TRUE);
- MZ_InitHandlers(lpDosTask);
- MZ_InitXMS(lpDosTask);
- MZ_InitDPMI(lpDosTask);
- return TRUE;
+    /* allocate 1MB+64K shared memory */
+    tmpnam(mm_name);
+    /* strcpy(mm_name,"/tmp/mydosimage"); */
+    mm_fd = open(mm_name,O_RDWR|O_CREAT /* |O_TRUNC */,S_IRUSR|S_IWUSR);
+    if (mm_fd < 0) ERR("file %s could not be opened\n",mm_name);
+    /* fill the file with the DOS memory */
+    if (write( mm_fd, NULL, 0x110000 ) != 0x110000) ERR("cannot write DOS mem\n");
+    /* map it in */
+    img_base = mmap(NULL,0x110000,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED|MAP_FIXED,mm_fd,0);
+    close( mm_fd );
+
+    if (img_base)
+    {
+        ERR("could not map shared memory, error=%s\n",strerror(errno));
+        return FALSE;
+    }
+    MZ_InitHandlers();
+    return TRUE;
 }
 
 BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
@@ -235,7 +187,7 @@
   BYTE*psp_start,*load_start;
   int x, old_com=0, alloc=0;
   SEGPTR reloc;
-  WORD env_seg;
+  WORD env_seg, load_seg;
   DWORD len;
 
   win_hdr->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
@@ -244,7 +196,6 @@
   if (!lpDosTask) {
     alloc=1;
     lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
-    lpDosTask->mm_fd = -1;
     dos_current = lpDosTask;
   }
 
@@ -269,10 +220,10 @@
   max_size=image_size+((DWORD)mz_header.e_maxalloc<<4)+(PSP_SIZE<<4);
  }
 
- MZ_InitMemory(lpDosTask);
+ MZ_InitMemory();
 
  /* allocate environment block */
- env_seg=MZ_InitEnvironment(lpDosTask,GetEnvironmentStringsA(),filename);
+ env_seg=MZ_InitEnvironment(GetEnvironmentStringsA(),filename);
 
  /* allocate memory for the executable */
  TRACE("Allocating DOS memory (min=%ld, max=%ld)\n",min_size,max_size);
@@ -289,7 +240,7 @@
   SetLastError(ERROR_NOT_ENOUGH_MEMORY);
   goto load_error;
  }
- lpDosTask->load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE);
+ load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE);
  load_start=psp_start+(PSP_SIZE<<4);
  MZ_CreatePSP(psp_start, env_seg);
 
@@ -311,19 +262,19 @@
     SetLastError(ERROR_BAD_FORMAT);
     goto load_error;
    }
-   *(WORD*)SEGPTR16(load_start,reloc)+=lpDosTask->load_seg;
+   *(WORD*)SEGPTR16(load_start,reloc)+=load_seg;
   }
  }
 
- lpDosTask->init_cs=lpDosTask->load_seg+mz_header.e_cs;
- lpDosTask->init_ip=mz_header.e_ip;
- lpDosTask->init_ss=lpDosTask->load_seg+mz_header.e_ss;
- lpDosTask->init_sp=mz_header.e_sp;
+ init_cs = load_seg+mz_header.e_cs;
+ init_ip = mz_header.e_ip;
+ init_ss = load_seg+mz_header.e_ss;
+ init_sp = mz_header.e_sp;
 
-  TRACE("entry point: %04x:%04x\n",lpDosTask->init_cs,lpDosTask->init_ip);
+  TRACE("entry point: %04x:%04x\n",init_cs,init_ip);
 
-  if (!MZ_InitTask(lpDosTask)) {
-    MZ_KillTask(lpDosTask);
+  if (!MZ_InitTask()) {
+    MZ_KillTask();
     SetLastError(ERROR_GEN_FAILURE);
     return FALSE;
   }
@@ -333,12 +284,7 @@
 load_error:
   if (alloc) {
     dos_current = NULL;
-    if (lpDosTask->mm_name[0]!=0) {
-      if (lpDosTask->img!=NULL) munmap(lpDosTask->img,0x110000-START_OFFSET);
-      if (lpDosTask->mm_fd>=0) close(lpDosTask->mm_fd);
-      unlink(lpDosTask->mm_name);
-    } else
-      if (lpDosTask->img!=NULL) VirtualFree(lpDosTask->img,0x110000,MEM_RELEASE);
+    if (mm_name[0]!=0) unlink(mm_name);
   }
 
   return FALSE;
@@ -349,14 +295,14 @@
   LPDOSTASK lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
 
   if (lpDosTask) {
-    lpDosTask->mm_fd = -1;
     dos_current = lpDosTask;
-    MZ_InitMemory(lpDosTask);
+    MZ_InitMemory();
+    MZ_InitTask();
   }
   return lpDosTask;
 }
 
-static void MZ_InitTimer( LPDOSTASK lpDosTask, int ver )
+static void MZ_InitTimer( int ver )
 {
  if (ver<1) {
   /* can't make timer ticks */
@@ -367,55 +313,42 @@
   /* start dosmod timer at 55ms (18.2Hz) */
   func=DOSMOD_SET_TIMER;
   tim.tv_sec=0; tim.tv_usec=54925;
-  write(lpDosTask->write_pipe,&func,sizeof(func));
-  write(lpDosTask->write_pipe,&tim,sizeof(tim));
+  write(write_pipe,&func,sizeof(func));
+  write(write_pipe,&tim,sizeof(tim));
  }
 }
 
-BOOL MZ_InitTask( LPDOSTASK lpDosTask )
+static BOOL MZ_InitTask(void)
 {
   int write_fd[2],x_fd;
   pid_t child;
-  char *fname,*farg,arg[16],fproc[64],path[256],*fpath;
+  char path[256],*fpath;
 
-  if (!lpDosTask) return FALSE;
   /* create pipes */
-  if (!CreatePipe(&(lpDosTask->hReadPipe),&(lpDosTask->hXPipe),NULL,0)) return FALSE;
+  if (!CreatePipe(&hReadPipe,&hWritePipe,NULL,0)) return FALSE;
   if (pipe(write_fd)<0) {
-    CloseHandle(lpDosTask->hReadPipe);
-    CloseHandle(lpDosTask->hXPipe);
+    CloseHandle(hReadPipe);
+    CloseHandle(hWritePipe);
     return FALSE;
   }
 
-  lpDosTask->read_pipe = FILE_GetUnixHandle( lpDosTask->hReadPipe, GENERIC_READ );
-  x_fd = FILE_GetUnixHandle( lpDosTask->hXPipe, GENERIC_WRITE );
+  read_pipe = FILE_GetUnixHandle( hReadPipe, GENERIC_READ );
+  x_fd = FILE_GetUnixHandle( hWritePipe, GENERIC_WRITE );
 
   TRACE("win32 pipe: read=%d, write=%d, unix pipe: read=%d, write=%d\n",
-	       lpDosTask->hReadPipe,lpDosTask->hXPipe,lpDosTask->read_pipe,x_fd);
+        hReadPipe,hWritePipe,read_pipe,x_fd);
   TRACE("outbound unix pipe: read=%d, write=%d, pid=%d\n",write_fd[0],write_fd[1],getpid());
 
-  lpDosTask->write_pipe=write_fd[1];
-
-  lpDosTask->hConInput=GetStdHandle(STD_INPUT_HANDLE);
-  lpDosTask->hConOutput=GetStdHandle(STD_OUTPUT_HANDLE);
-
-  /* if we have a mapping file, use it */
-  fname=lpDosTask->mm_name; farg=NULL;
-  if (!fname[0]) {
-    /* otherwise, map our own memory image */
-    sprintf(fproc,"/proc/%d/mem",getpid());
-    sprintf(arg,"%ld",(unsigned long)lpDosTask->img);
-    fname=fproc; farg=arg;
-  }
+  write_pipe=write_fd[1];
 
   TRACE("Loading DOS VM support module\n");
   if ((child=fork())<0) {
     close(write_fd[0]);
-    close(lpDosTask->read_pipe);
-    close(lpDosTask->write_pipe);
+    close(read_pipe);
+    close(write_pipe);
     close(x_fd);
-    CloseHandle(lpDosTask->hReadPipe);
-    CloseHandle(lpDosTask->hXPipe);
+    CloseHandle(hReadPipe);
+    CloseHandle(hWritePipe);
     return FALSE;
   }
  if (child!=0) {
@@ -424,21 +357,21 @@
 
   close(write_fd[0]);
   close(x_fd);
-  lpDosTask->task=child;
+  dosmod_pid = child;
   /* wait for child process to signal readiness */
   while (1) {
-    if (read(lpDosTask->read_pipe,&ret,sizeof(ret))==sizeof(ret)) break;
+    if (read(read_pipe,&ret,sizeof(ret))==sizeof(ret)) break;
     if ((errno==EINTR)||(errno==EAGAIN)) continue;
     /* failure */
     ERR("dosmod has failed to initialize\n");
-    if (lpDosTask->mm_name[0]!=0) unlink(lpDosTask->mm_name);
+    if (mm_name[0]!=0) unlink(mm_name);
     return FALSE;
   }
   /* the child has now mmaped the temp file, it's now safe to unlink.
    * do it here to avoid leaving a mess in /tmp if/when Wine crashes... */
-  if (lpDosTask->mm_name[0]!=0) unlink(lpDosTask->mm_name);
+  if (mm_name[0]!=0) unlink(mm_name);
   /* start simulated system timer */
-  MZ_InitTimer(lpDosTask,ret);
+  MZ_InitTimer(ret);
   if (ret<2) {
     ERR("dosmod version too old! Please install newer dosmod properly\n");
     ERR("If you don't, the new dosmod event handling system will not work\n");
@@ -446,8 +379,8 @@
   /* all systems are now go */
  } else {
   /* child process */
-  close(lpDosTask->read_pipe);
-  close(lpDosTask->write_pipe);
+  close(read_pipe);
+  close(write_pipe);
   /* put our pipes somewhere dosmod can find them */
   dup2(write_fd[0],0); /* stdin */
   dup2(x_fd,1);        /* stdout */
@@ -457,16 +390,16 @@
   fpath=strrchr(strcpy(path,full_argv0),'/');
   if (fpath) {
    strcpy(fpath,"/dosmod");
-   execl(path,fname,farg,NULL);
+   execl(path,mm_name,NULL);
    strcpy(fpath,"/loader/dos/dosmod");
-   execl(path,fname,farg,NULL);
+   execl(path,mm_name,NULL);
   }
   /* okay, it wasn't there, try in the path */
-  execlp("dosmod",fname,farg,NULL);
+  execlp("dosmod",mm_name,NULL);
   /* last desperate attempts: current directory */
-  execl("dosmod",fname,farg,NULL);
+  execl("dosmod",mm_name,NULL);
   /* and, just for completeness... */
-  execl("loader/dos/dosmod",fname,farg,NULL);
+  execl("loader/dos/dosmod",mm_name,NULL);
   /* if failure, exit */
   ERR("Failed to spawn dosmod, error=%s\n",strerror(errno));
   exit(1);
@@ -477,53 +410,29 @@
 static void MZ_Launch(void)
 {
   LPDOSTASK lpDosTask = MZ_Current();
-  BYTE *psp_start = (BYTE*)lpDosTask->img + ((DWORD)lpDosTask->psp_seg << 4);
+  CONTEXT context;
+  TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
+  BYTE *psp_start = PTR_REAL_TO_LIN( lpDosTask->psp_seg, 0 );
 
   MZ_FillPSP(psp_start, GetCommandLineA());
+  pTask->flags |= TDBF_WINOLDAP;
 
-  DOSVM_Enter(NULL);
+  memset( &context, 0, sizeof(context) );
+  context.SegCs  = init_cs;
+  context.Eip    = init_ip;
+  context.SegSs  = init_ss;
+  context.Esp    = init_sp;
+  context.SegDs  = lpDosTask->psp_seg;
+  context.SegEs  = lpDosTask->psp_seg;
+  context.EFlags = 0x00080000;  /* virtual interrupt flag */
+  DOSVM_Enter( &context );
 }
 
-void MZ_KillTask( LPDOSTASK lpDosTask )
+static void MZ_KillTask(void)
 {
-  DOSEVENT *event,*p_event;
-  DOSSYSTEM *sys,*p_sys;
-
   TRACE("killing DOS task\n");
   VGA_Clean();
-  if (lpDosTask->mm_name[0]!=0) {
-    munmap(lpDosTask->img,0x110000-START_OFFSET);
-    close(lpDosTask->mm_fd);
-  } else VirtualFree(lpDosTask->img,0x110000,MEM_RELEASE);
-  close(lpDosTask->read_pipe);
-  close(lpDosTask->write_pipe);
-  CloseHandle(lpDosTask->hReadPipe);
-  CloseHandle(lpDosTask->hXPipe);
-  kill(lpDosTask->task,SIGTERM);
-/* free memory allocated for events and systems */
-#define DFREE(var,pvar,svar) \
-  var = lpDosTask->svar; \
-  while (var) { \
-    if (var->data) free(var->data); \
-    pvar = var->next; free(var); var = pvar; \
-  }
-
-  DFREE(event,p_event,pending)
-  DFREE(event,p_event,current)
-  DFREE(sys,p_sys,sys)
-
-#undef DFREE
-
-#if 0
-  /* FIXME: this seems to crash */
-  if (lpDosTask->dpmi_sel)
-    SELECTOR_FreeBlock(lpDosTask->dpmi_sel, 1);
-#endif
-}
-
-LPDOSTASK MZ_Current( void )
-{
-  return dos_current;
+  kill(dosmod_pid,SIGTERM);
 }
 
 #else /* !MZ_SUPPORTED */
@@ -535,9 +444,15 @@
  return FALSE;
 }
 
-LPDOSTASK MZ_Current( void )
+LPDOSTASK MZ_AllocDPMITask( void )
 {
-  return NULL;
+    ERR("Actual real-mode calls not supported on this architecture!\n");
+    return NULL;
 }
 
-#endif
+#endif /* !MZ_SUPPORTED */
+
+LPDOSTASK MZ_Current( void )
+{
+  return dos_current;
+}
diff --git a/loader/task.c b/loader/task.c
index adcee6a..6b29425 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -29,13 +29,13 @@
 #include "winsock.h"
 #include "syslevel.h"
 #include "debugtools.h"
-#include "dosexe.h"
 #include "services.h"
 #include "server.h"
 
-DEFAULT_DEBUG_CHANNEL(task)
-DECLARE_DEBUG_CHANNEL(relay)
-DECLARE_DEBUG_CHANNEL(toolhelp)
+
+DEFAULT_DEBUG_CHANNEL(task);
+DECLARE_DEBUG_CHANNEL(relay);
+DECLARE_DEBUG_CHANNEL(toolhelp);
 
   /* Min. number of thunks allocated when creating a new segment */
 #define MIN_THUNKS  32
@@ -243,7 +243,6 @@
         /* NOTE: for 16-bit tasks, the instance handles are updated later on
            in NE_InitProcess */
     }
-    if (MZ_Current() && MZ_Current()->load_seg) pTask->flags |= TDBF_WINOLDAP;
 
     pTask->version       = pModule->expected_version;
     pTask->hModule       = pModule->self;
diff --git a/memory/instr.c b/memory/instr.c
index 39b439b..34fbda8 100644
--- a/memory/instr.c
+++ b/memory/instr.c
@@ -29,7 +29,7 @@
 
 inline static void *make_ptr( CONTEXT86 *context, DWORD seg, DWORD off, int long_addr )
 {
-    if (ISV86(context)) return DOSMEM_MemoryBase() + (seg << 4) + LOWORD(off);
+    if (ISV86(context)) return PTR_REAL_TO_LIN( seg, off );
     if (IS_SELECTOR_SYSTEM(seg)) return (void *)off;
     if (!long_addr) off = LOWORD(off);
     return PTR_SEG_OFF_TO_LIN( seg, off );
@@ -38,7 +38,7 @@
 inline static void *get_stack( CONTEXT86 *context )
 {
     if (ISV86(context))
-        return DOSMEM_MemoryBase() + (context->SegSs << 4) + LOWORD(context->Esp);
+        return PTR_REAL_TO_LIN( context->SegSs, context->Esp );
     if (IS_SELECTOR_SYSTEM(context->SegSs))
         return (void *)context->Esp;
     if (IS_SELECTOR_32BIT(context->SegSs))
diff --git a/msdos/devices.c b/msdos/devices.c
index a3d0863..3fcccba 100644
--- a/msdos/devices.c
+++ b/msdos/devices.c
@@ -47,8 +47,9 @@
 
 #define CON_BUFFER 128
 
-#define SYSTEM_STRATEGY_NUL 0x0100
-#define SYSTEM_STRATEGY_CON 0x0101
+enum strategy { SYSTEM_STRATEGY_NUL, SYSTEM_STRATEGY_CON, NB_SYSTEM_STRATEGIES };
+
+static void *strategy_data[NB_SYSTEM_STRATEGIES];
 
 #define NONEXT ((DWORD)-1)
 
@@ -150,20 +151,19 @@
 static void do_strategy(CONTEXT86*ctx, int id, int extra)
 {
   REQUEST_HEADER *hdr = CTX_SEG_OFF_TO_LIN(ctx, ES_reg(ctx), EBX_reg(ctx));
-  void **hdr_ptr = DOSVM_GetSystemData(id);
+  void **hdr_ptr = strategy_data[id];
 
   if (!hdr_ptr) {
     hdr_ptr = calloc(1,sizeof(void *)+extra);
-    DOSVM_SetSystemData(id, hdr_ptr);
+    strategy_data[id] = hdr_ptr;
   }
-
   *hdr_ptr = hdr;
   do_lret(ctx);
 }
 
 static REQUEST_HEADER * get_hdr(int id, void**extra)
 {
-  void **hdr_ptr = DOSVM_GetSystemData(id);
+  void **hdr_ptr = strategy_data[id];
   if (extra)
     *extra = hdr_ptr ? (void*)(hdr_ptr+1) : (void *)NULL;
   return hdr_ptr ? *hdr_ptr : (void *)NULL;
@@ -209,7 +209,6 @@
   BYTE *curbuffer = (lol->offs_unread_CON) ?
     (((BYTE*)dataseg) + lol->offs_unread_CON) : (BYTE*)NULL;
   DOS_DEVICE_HEADER *con = dataseg->dev;
-  LPDOSTASK lpDosTask = MZ_Current();
 
   switch (hdr->command) {
   case CMD_INPUT:
@@ -301,7 +300,7 @@
 	    /* a character */
 	    if ((len+1)<CON_BUFFER) {
 	      linebuffer[len] = LOBYTE(data);
-	      WriteFile(lpDosTask->hConOutput, &linebuffer[len++], 1, NULL, NULL);
+	      WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), &linebuffer[len++], 1, NULL, NULL);
 	    }
 	    /* else beep, but I don't like noise */
 	  }
@@ -309,7 +308,7 @@
 	  case '\b':
 	    if (len>0) {
 	      len--;
-	      WriteFile(lpDosTask->hConOutput, "\b \b", 3, NULL, NULL);
+	      WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\b \b", 3, NULL, NULL);
 	    }
 	    break;
 	  }
@@ -377,7 +376,7 @@
 					SELECTOROF(io->buffer),
 					(DWORD)OFFSETOF(io->buffer));
       DWORD result = 0;
-      WriteFile(lpDosTask->hConOutput, buffer, io->count, &result, NULL);
+      WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buffer, io->count, &result, NULL);
       io->count = result;
       hdr->status = STAT_DONE;
     }
diff --git a/msdos/dosmem.c b/msdos/dosmem.c
index ac41340..cf632eb 100644
--- a/msdos/dosmem.c
+++ b/msdos/dosmem.c
@@ -5,30 +5,33 @@
  * Copyright 1996 Marcus Meissner
  */
 
+#include "config.h"
+
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
 #include "winbase.h"
 #include "wine/winbase16.h"
+
 #include "global.h"
 #include "ldt.h"
+#include "selectors.h"
 #include "miscemu.h"
 #include "vga.h"
 #include "dosexe.h"
 #include "debugtools.h"
 
-DEFAULT_DEBUG_CHANNEL(dosmem)
-DECLARE_DEBUG_CHANNEL(selector)
+DEFAULT_DEBUG_CHANNEL(dosmem);
+DECLARE_DEBUG_CHANNEL(selector);
 
 HANDLE16 DOSMEM_BiosDataSeg;  /* BIOS data segment at 0x40:0 */
 HANDLE16 DOSMEM_BiosSysSeg;   /* BIOS ROM segment at 0xf000:0 */
 
-static char	*DOSMEM_dosmem;
-
-       DWORD 	 DOSMEM_CollateTable;
-
-       DWORD	 DOSMEM_ErrorCall;
-       DWORD	 DOSMEM_ErrorBuffer;
+DWORD DOSMEM_CollateTable;
 
 /* use 2 low bits of 'size' for the housekeeping */
 
@@ -57,6 +60,17 @@
 #define VM_STUB(x) (0x90CF00CD|(x<<8)) /* INT x; IRET; NOP */
 #define VM_STUB_SEGMENT 0xf000         /* BIOS segment */
 
+/* DOS memory base */
+static char *DOSMEM_dosmem;
+/* bios area; normally at offset 0x400, but can be moved to trap NULL pointers */
+static void *DOSMEM_biosdata;
+
+/* various real-mode code stubs */
+WORD DOSMEM_wrap_seg;
+WORD DOSMEM_xms_seg;
+WORD DOSMEM_dpmi_seg;
+WORD DOSMEM_dpmi_sel;
+
 /***********************************************************************
  *           DOSMEM_MemoryBase
  *
@@ -64,12 +78,7 @@
  */
 char *DOSMEM_MemoryBase(void)
 {
-    LPDOSTASK lpDosTask = MZ_Current();
-
-    if (lpDosTask && lpDosTask->img)
-        return lpDosTask->img;
-    else
-        return DOSMEM_dosmem;
+    return DOSMEM_dosmem;
 }
 
 /***********************************************************************
@@ -79,7 +88,7 @@
  */
 static char *DOSMEM_MemoryTop(void)
 {
-    return DOSMEM_MemoryBase()+0x9FFFC; /* 640K */
+    return DOSMEM_dosmem+0x9FFFC; /* 640K */
 }
 
 /***********************************************************************
@@ -89,7 +98,7 @@
  */
 static dosmem_info *DOSMEM_InfoBlock(void)
 {
-    return (dosmem_info*)(DOSMEM_MemoryBase()+0x10000); /* 64K */
+    return (dosmem_info*)(DOSMEM_dosmem+0x10000); /* 64K */
 }
 
 /***********************************************************************
@@ -118,7 +127,7 @@
  */
 static void DOSMEM_FillIsrTable(void)
 {
-    SEGPTR *isr = (SEGPTR*)DOSMEM_MemoryBase();
+    SEGPTR *isr = (SEGPTR*)DOSMEM_dosmem;
     DWORD *stub = (DWORD*)((char*)isr + (VM_STUB_SEGMENT << 4));
     int x;
  
@@ -133,24 +142,66 @@
  */
 static void DOSMEM_InitDPMI(void)
 {
-    extern UINT16 DPMI_wrap_seg;
-    static char wrap_code[]={
+    LPSTR ptr;
+
+    static const char wrap_code[]={
      0xCD,0x31, /* int $0x31 */
      0xCB       /* lret */
     };
-    LPSTR wrapper = (LPSTR)DOSMEM_GetBlock(sizeof(wrap_code), &DPMI_wrap_seg);
 
-    memcpy(wrapper, wrap_code, sizeof(wrap_code));
+    static const char enter_xms[]=
+    {
+        /* XMS hookable entry point */
+        0xEB,0x03,           /* jmp entry */
+        0x90,0x90,0x90,      /* nop;nop;nop */
+                             /* entry: */
+        /* real entry point */
+        /* for simplicity, we'll just use the same hook as DPMI below */
+        0xCD,0x31,           /* int $0x31 */
+        0xCB                 /* lret */
+    };
+
+    static const char enter_pm[]=
+    {
+        0x50,                /* pushw %ax */
+        0x52,                /* pushw %dx */
+        0x55,                /* pushw %bp */
+        0x89,0xE5,           /* movw %sp,%bp */
+        /* get return CS */
+        0x8B,0x56,0x08,      /* movw 8(%bp),%dx */
+        /* just call int 31 here to get into protected mode... */
+        /* it'll check whether it was called from dpmi_seg... */
+        0xCD,0x31,           /* int $0x31 */
+        /* we are now in the context of a 16-bit relay call */
+        /* need to fixup our stack;
+         * 16-bit relay return address will be lost, but we won't worry quite yet */
+        0x8E,0xD0,           /* movw %ax,%ss */
+        0x66,0x0F,0xB7,0xE5, /* movzwl %bp,%esp */
+        /* set return CS */
+        0x89,0x56,0x08,      /* movw %dx,8(%bp) */
+        0x5D,                /* popw %bp */
+        0x5A,                /* popw %dx */
+        0x58,                /* popw %ax */
+        0xCB                 /* lret */
+    };
+
+    ptr = DOSMEM_GetBlock( sizeof(wrap_code), &DOSMEM_wrap_seg );
+    memcpy( ptr, wrap_code, sizeof(wrap_code) );
+    ptr = DOSMEM_GetBlock( sizeof(enter_xms), &DOSMEM_xms_seg );
+    memcpy( ptr, enter_xms, sizeof(enter_xms) );
+    ptr = DOSMEM_GetBlock( sizeof(enter_pm), &DOSMEM_dpmi_seg );
+    memcpy( ptr, enter_pm, sizeof(enter_pm) );
+    DOSMEM_dpmi_sel = SELECTOR_AllocBlock( ptr, sizeof(enter_pm), SEGMENT_CODE, FALSE, FALSE );
 }
 
 BIOSDATA * DOSMEM_BiosData()
 {
-    return (BIOSDATA *)(DOSMEM_MemoryBase()+0x400);
+    return (BIOSDATA *)DOSMEM_biosdata;
 }
 
 BYTE * DOSMEM_BiosSys()
 {
-    return DOSMEM_MemoryBase()+0xf0000;
+    return DOSMEM_dosmem+0xf0000;
 }
 
 struct _DOS_LISTOFLISTS * DOSMEM_LOL()
@@ -293,6 +344,7 @@
  */
 static void DOSMEM_InitErrorTable()
 {
+#if 0  /* no longer used */
 	DWORD		x;
 	char 		*call;
 
@@ -336,7 +388,7 @@
 	call = DOSMEM_MapRealToLinear(DOSMEM_ErrorCall);
 
         memset(call, 0, SIZE_TO_ALLOCATE);
-
+#endif
         /* Fixme - Copy assembly into buffer here */        
 }
 
@@ -368,28 +420,56 @@
 		     ;
 }
 
-/***********************************************************************
- *           DOSMEM_MovePointers
+/**********************************************************************
+ *		setup_dos_mem
  *
- * Relocates any pointers into DOS memory to a new address space.
+ * Setup the first megabyte for DOS memory access
  */
-static void DOSMEM_MovePointers(LPVOID dest, LPVOID src, DWORD size)
+static void setup_dos_mem( int dos_init )
 {
-  unsigned long delta = (char *) dest - (char *) src;
-  unsigned cnt;
-  ldt_entry ent;
+    int bios_offset = 0x400;
+    int page_size = VIRTUAL_GetPageSize();
+    void *addr = VIRTUAL_mmap( -1, (void *)page_size, 0x110000-page_size, 0,
+                               PROT_READ | PROT_WRITE | PROT_EXEC, 0 );
+    if (addr == (void *)page_size)  /* we got what we wanted */
+    {
+        /* now map from address 0 */
+        addr = VIRTUAL_mmap( -1, NULL, 0x110000, 0,
+                             PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED );
+        if (addr)
+        {
+            ERR("MAP_FIXED failed at address 0 for DOS address space\n" );
+            ExitProcess(1);
+        }
 
-  /* relocate base addresses of any selectors pointing into memory */
-  for (cnt=FIRST_LDT_ENTRY_TO_ALLOC; cnt<LDT_SIZE; cnt++) {
-    LDT_GetEntry(cnt, &ent);
-    if ((ent.base >= (unsigned long)src) && \
-	(ent.base < ((unsigned long)src + size))) {
-      ent.base += delta;
-      LDT_SetEntry(cnt, &ent);
+        /* inform the memory manager that there is a mapping here */
+        VirtualAlloc( addr, 0x110000, MEM_RESERVE | MEM_SYSTEM, PAGE_EXECUTE_READWRITE );
+
+        /* protect the first 64K to catch NULL pointers */
+        if (!dos_init)
+        {
+            VirtualProtect( addr, 0x10000, PAGE_NOACCESS, NULL );
+            /* move the BIOS data from 0x400 to 0xf0400 */
+            bios_offset += 0xf0000;
+        }
     }
-  }
+    else
+    {
+        ERR("Cannot use first megabyte for DOS address space, please report\n" );
+        if (dos_init) ExitProcess(1);
+        /* allocate the DOS area somewhere else */
+        addr = VirtualAlloc( NULL, 0x110000, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
+        if (!addr)
+        {
+            ERR( "Cannot allocate DOS memory\n" );
+            ExitProcess(1);
+        }
+    }
+    DOSMEM_dosmem = addr;
+    DOSMEM_biosdata = (char *)addr + bios_offset;
 }
 
+
 /***********************************************************************
  *           DOSMEM_Init
  *
@@ -398,44 +478,41 @@
  */
 BOOL DOSMEM_Init(BOOL dos_init)
 {
-    LPVOID base = DOSMEM_MemoryBase();
-    BOOL do_init = dos_init && !DOSMEM_dosmem;
+    static int already_done;
 
-    if (!base)
+    if (!already_done)
     {
-        /* Allocate 1 MB dosmemory 
-         */
-        DOSMEM_dosmem = VirtualAlloc( NULL, 0x100000, MEM_COMMIT,
-                                      PAGE_EXECUTE_READWRITE );
-        if (!DOSMEM_dosmem)
-        {
-            WARN("Could not allocate DOS memory.\n" );
-            return FALSE;
-        }
-        DOSMEM_BiosDataSeg = GLOBAL_CreateBlock(GMEM_FIXED,DOSMEM_dosmem+0x400,
-                                     0x100, 0, FALSE, FALSE, FALSE );
-        DOSMEM_BiosSysSeg = GLOBAL_CreateBlock(GMEM_FIXED,DOSMEM_dosmem+0xf0000,
-                                     0x10000, 0, FALSE, FALSE, FALSE );
-        base = DOSMEM_dosmem;
-        do_init = TRUE;
-    }
+        setup_dos_mem( dos_init );
 
-    if (do_init) {
-        DOSMEM_FillIsrTable();
+        DOSMEM_BiosDataSeg = GLOBAL_CreateBlock(GMEM_FIXED,DOSMEM_biosdata,
+                                                0x100, 0, FALSE, FALSE, FALSE );
+        DOSMEM_BiosSysSeg = GLOBAL_CreateBlock(GMEM_FIXED,DOSMEM_dosmem+0xf0000,
+                                               0x10000, 0, FALSE, FALSE, FALSE );
         DOSMEM_FillBiosSegments();
         DOSMEM_InitMemory();
         DOSMEM_InitCollateTable();
         DOSMEM_InitErrorTable();
         DOSMEM_InitDPMI();
-	DOSDEV_InstallDOSDevices();
+        DOSDEV_InstallDOSDevices();
+        already_done = 1;
     }
     else if (dos_init)
     {
-        /* bootstrap the new V86 task with a copy of the "system" memory */
-        memcpy(base, DOSMEM_dosmem, 0x100000);
-	/* then move existing selectors to it */
-	DOSMEM_MovePointers(base, DOSMEM_dosmem, 0x100000);
+        if (DOSMEM_dosmem)
+        {
+            ERR( "Needs access to the first megabyte for DOS mode\n" );
+            ExitProcess(1);
+        }
+        MESSAGE( "Warning: unprotecting the first 64KB of memory to allow real-mode calls.\n"
+                 "         NULL pointer accesses will no longer be caught.\n" );
+        VirtualProtect( NULL, 0x10000, PAGE_EXECUTE_READWRITE, NULL );
+        /* copy the BIOS area down to 0x400 */
+        memcpy( DOSMEM_dosmem + 0x400, DOSMEM_biosdata, 0x100 );
+        DOSMEM_biosdata = DOSMEM_dosmem + 0x400;
+        SetSelectorBase( DOSMEM_BiosDataSeg, 0x400 );
     }
+    /* interrupt table is at addr 0, so only do this when setting up DOS mode */
+    if (dos_init) DOSMEM_FillIsrTable();
     return TRUE;
 }
 
@@ -513,7 +590,7 @@
 
 	       info_block->blocks++;
 	       info_block->free -= dm->size;
-	       if( pseg ) *pseg = (block - DOSMEM_MemoryBase()) >> 4;
+	       if( pseg ) *pseg = (block - DOSMEM_dosmem) >> 4;
 #ifdef __DOSMEM_DEBUG__
                dm->size |= DM_BLOCK_DEBUG;
 #endif
@@ -535,7 +612,7 @@
 
    if( ptr >= (void*)(((char*)DOSMEM_RootBlock()) + sizeof(dosmem_entry)) &&
        ptr < (void*)DOSMEM_MemoryTop() && !((((char*)ptr)
-                  - DOSMEM_MemoryBase()) & 0xf) )
+                  - DOSMEM_dosmem) & 0xf) )
    {
        dosmem_entry  *dm = (dosmem_entry*)(((char*)ptr) - sizeof(dosmem_entry));
 
@@ -565,11 +642,11 @@
 
    if( ptr >= (void*)(((char*)DOSMEM_RootBlock()) + sizeof(dosmem_entry)) &&
        ptr < (void*)DOSMEM_MemoryTop() && !((((char*)ptr)
-                  - DOSMEM_MemoryBase()) & 0xf) )
+                  - DOSMEM_dosmem) & 0xf) )
    {
        dosmem_entry  *dm = (dosmem_entry*)(((char*)ptr) - sizeof(dosmem_entry));
 
-       if( pseg ) *pseg = ((char*)ptr - DOSMEM_MemoryBase()) >> 4;
+       if( pseg ) *pseg = ((char*)ptr - DOSMEM_dosmem) >> 4;
 
        if( !(dm->size & (DM_BLOCK_FREE | DM_BLOCK_TERMINAL))
 	 )
@@ -689,9 +766,9 @@
  */
 UINT DOSMEM_MapLinearToDos(LPVOID ptr)
 {
-    if (((char*)ptr >= DOSMEM_MemoryBase()) &&
-        ((char*)ptr < DOSMEM_MemoryBase() + 0x100000))
-	  return (UINT)ptr - (UINT)DOSMEM_MemoryBase();
+    if (((char*)ptr >= DOSMEM_dosmem) &&
+        ((char*)ptr < DOSMEM_dosmem + 0x100000))
+	  return (UINT)ptr - (UINT)DOSMEM_dosmem;
     return (UINT)ptr;
 }
 
@@ -703,7 +780,7 @@
  */
 LPVOID DOSMEM_MapDosToLinear(UINT ptr)
 {
-    if (ptr < 0x100000) return (LPVOID)(ptr + (UINT)DOSMEM_MemoryBase());
+    if (ptr < 0x100000) return (LPVOID)(ptr + (UINT)DOSMEM_dosmem);
     return (LPVOID)ptr;
 }
 
@@ -717,7 +794,7 @@
 {
    LPVOID       lin;
 
-   lin=DOSMEM_MemoryBase()+(x&0xffff)+(((x&0xffff0000)>>16)*16);
+   lin=DOSMEM_dosmem+(x&0xffff)+(((x&0xffff0000)>>16)*16);
    TRACE_(selector)("(0x%08lx) returns 0x%p.\n", x, lin );
    return lin;
 }
diff --git a/msdos/dpmi.c b/msdos/dpmi.c
index be2a596..d116467 100644
--- a/msdos/dpmi.c
+++ b/msdos/dpmi.c
@@ -62,7 +62,6 @@
 
 static RMCB *FirstRMCB = NULL;
 
-UINT16 DPMI_wrap_seg;
 
 /**********************************************************************
  *	    DPMI_xalloc
@@ -261,7 +260,7 @@
         DWORD esp,edi;
 
         INT_SetRealModeContext((REALMODECALL *)PTR_SEG_OFF_TO_LIN( rmcb->regs_sel, rmcb->regs_ofs ), context);
-        ss = SELECTOR_AllocBlock( DOSMEM_MemoryBase() + (DWORD)(SS_reg(context)<<4), 0x10000, SEGMENT_DATA, FALSE, FALSE );
+        ss = SELECTOR_AllocBlock( (void *)(SS_reg(context)<<4), 0x10000, SEGMENT_DATA, FALSE, FALSE );
         esp = ESP_reg(context);
 
         FIXME("untested!\n");
@@ -354,17 +353,12 @@
         CurrRMCB = CurrRMCB->next;
 
     if (!(CurrRMCB || lpDosTask)) {
-#ifdef MZ_SUPPORTED
         FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n");
         TRACE("creating VM86 task\n");
-        if (!MZ_InitTask( lpDosTask = MZ_AllocDPMITask() )) {
+        if (!(lpDosTask = MZ_AllocDPMITask() )) {
             ERR("could not setup VM86 task\n");
             return 1;
         }
-#else
-        ERR("Actual real-mode calls not supported on this architecture!\n");
-        return 1;
-#endif
     }
     if (!already) {
         if (!SS_reg(context)) {
@@ -388,7 +382,7 @@
             *stack16 = LOWORD(EFL_reg(context));
         }
         /* push return address (return to interrupt wrapper) */
-        *(--stack16) = DPMI_wrap_seg;
+        *(--stack16) = DOSMEM_wrap_seg;
         *(--stack16) = 0;
         /* adjust stack */
         ESP_reg(context) -= 2*sizeof(WORD);
@@ -399,21 +393,16 @@
         /* RMCB call, invoke protected-mode handler directly */
         DPMI_CallRMCBProc(context, CurrRMCB, lpDosTask ? lpDosTask->dpmi_flag : 0);
         /* check if we returned to where we thought we would */
-        if ((CS_reg(context) != DPMI_wrap_seg) ||
+        if ((CS_reg(context) != DOSMEM_wrap_seg) ||
             (LOWORD(EIP_reg(context)) != 0)) {
             /* we need to continue at different address in real-mode space,
                so we need to set it all up for real mode again */
             goto callrmproc_again;
         }
     } else {
-#ifdef MZ_SUPPORTED
         TRACE("entering real mode...\n");
         DOSVM_Enter( context );
         TRACE("returned from real-mode call\n");
-#else
-        /* we should never get here, but... */
-        ERR("cannot perform real-mode call\n");
-#endif
     }
     if (alloc) DOSMEM_FreeBlock( addr );
     return 0;
@@ -585,16 +574,14 @@
 }
 
 
-#ifdef MZ_SUPPORTED
-/* (see loader/dos/module.c, function MZ_InitDPMI) */
+/* (see dosmem.c, function DOSMEM_InitDPMI) */
 
 static void StartPM( CONTEXT86 *context, LPDOSTASK lpDosTask )
 {
-    char *base = DOSMEM_MemoryBase();
     UINT16 cs, ss, ds, es;
     CONTEXT86 pm_ctx;
     DWORD psp_ofs = (DWORD)(lpDosTask->psp_seg<<4);
-    PDB16 *psp = (PDB16 *)(base + psp_ofs);
+    PDB16 *psp = (PDB16 *)psp_ofs;
     HANDLE16 env_seg = psp->environment;
     int is32;
 
@@ -602,22 +589,22 @@
     lpDosTask->dpmi_flag = AX_reg(context);
     is32 = lpDosTask->dpmi_flag & 1;
 /* our mode switch wrapper have placed the desired CS into DX */
-    cs = SELECTOR_AllocBlock( base + (DWORD)(DX_reg(context)<<4), 0x10000, SEGMENT_CODE, FALSE, FALSE );
+    cs = SELECTOR_AllocBlock( (void *)(DX_reg(context)<<4), 0x10000, SEGMENT_CODE, FALSE, FALSE );
 /* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they
    can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a
    ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing
    32-bit code using this stack. */
-    ss = SELECTOR_AllocBlock( base + (DWORD)(SS_reg(context)<<4), 0x10000, SEGMENT_DATA, is32, FALSE );
+    ss = SELECTOR_AllocBlock( (void *)(SS_reg(context)<<4), 0x10000, SEGMENT_DATA, is32, FALSE );
 /* do the same for the data segments, just in case */
     if (DS_reg(context) == SS_reg(context)) ds = ss;
-    else ds = SELECTOR_AllocBlock( base + (DWORD)(DS_reg(context)<<4), 0x10000, SEGMENT_DATA, is32, FALSE );
-    es = SELECTOR_AllocBlock( base + psp_ofs, 0x100, SEGMENT_DATA, is32, FALSE );
+    else ds = SELECTOR_AllocBlock( (void *)(DS_reg(context)<<4), 0x10000, SEGMENT_DATA, is32, FALSE );
+    es = SELECTOR_AllocBlock( psp, 0x100, SEGMENT_DATA, is32, FALSE );
 /* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */
-    psp->environment = SELECTOR_AllocBlock( base + (DWORD)(env_seg<<4),
+    psp->environment = SELECTOR_AllocBlock( (void *)(env_seg<<4),
 					    0x10000, SEGMENT_DATA, FALSE, FALSE );
 
     pm_ctx = *context;
-    CS_reg(&pm_ctx) = lpDosTask->dpmi_sel;
+    CS_reg(&pm_ctx) = DOSMEM_dpmi_sel;
 /* our mode switch wrapper expects the new CS in DX, and the new SS in AX */
     EAX_reg(&pm_ctx) = ss;
     EDX_reg(&pm_ctx) = cs;
@@ -697,26 +684,6 @@
 }
 #endif
 
-#else
-#if 0
-void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context )
-{
-  ERR("don't even think about DPMI raw mode switch without DOS support!\n");
-  ExitProcess(1);
-}
-#endif
-#endif
-
-#define DOS_APP_ISDOS(addr,base) ((addr) < 0x110000)
-#define DOS_WINE_ISDOS(addr,base) (((addr) >= (base)) && ((addr) < (base) + 0x110000))
-#define DOS_UC_APPTOWINE(addr,base) ((addr) + (base))
-#define DOS_UC_WINETOAPP(addr,base) ((addr) - (base))
-#define DOS_APPTOWINE(addr,base) (DOS_APP_ISDOS(addr,base) ? DOS_UC_APPTOWINE(addr,base) : (addr))
-#define DOS_WINETOAPP(addr,base) (DOS_WINE_ISDOS(addr,base) ? DOS_UC_WINETOAPP(addr,base) : (addr))
-#define DOS_BADLIMIT(addr,base,limit) \
-  ((limit == 0xffffffff) || /* disallow "fat DS" for now */ \
-   (DOS_WINE_ISDOS(addr,base) && \
-    ((addr) + (limit) > (base) + 0x110000)))
 
 /**********************************************************************
  *	    INT_Int31Handler
@@ -738,16 +705,15 @@
 
     LPDOSTASK lpDosTask = MZ_Current();
 
-#ifdef MZ_SUPPORTED
     if (ISV86(context) && lpDosTask) {
         /* Called from real mode, check if it's our wrapper */
         TRACE("called from real mode\n");
-        if (CS_reg(context)==lpDosTask->dpmi_seg) {
+        if (CS_reg(context)==DOSMEM_dpmi_seg) {
             /* This is the protected mode switch */
             StartPM(context,lpDosTask);
             return;
         } else
-        if (CS_reg(context)==lpDosTask->xms_seg) {
+        if (CS_reg(context)==DOSMEM_xms_seg) {
             /* This is the XMS driver entry point */
             XMS_Handler(context);
             return;
@@ -766,7 +732,6 @@
             }
         }
     }
-#endif
 
     RESET_CFLAG(context);
     switch(AX_reg(context))
@@ -849,12 +814,6 @@
         }
         else
         {
-#ifdef MZ_SUPPORTED
-            if (lpDosTask) {
-                DWORD base = (DWORD)DOSMEM_MemoryBase();
-		dw = DOS_WINETOAPP(dw, base);
-            }
-#endif
             CX_reg(context) = HIWORD(W32S_WINE2APP(dw, offset));
             DX_reg(context) = LOWORD(W32S_WINE2APP(dw, offset));
         }
@@ -865,40 +824,12 @@
                      BX_reg(context),
                      W32S_APP2WINE(MAKELONG(DX_reg(context),CX_reg(context)), offset));
         dw = W32S_APP2WINE(MAKELONG(DX_reg(context), CX_reg(context)), offset);
-#ifdef MZ_SUPPORTED
-        if (lpDosTask) {
-            DWORD base = (DWORD)DOSMEM_MemoryBase();
-	    dw = DOS_APPTOWINE(dw, base);
-        }
-#endif
         SetSelectorBase(BX_reg(context), dw);
         break;
 
     case 0x0008:  /* Set selector limit */
     	TRACE("set selector limit (0x%04x,0x%08lx)\n",BX_reg(context),MAKELONG(DX_reg(context),CX_reg(context)));
         dw = MAKELONG( DX_reg(context), CX_reg(context) );
-#ifdef MZ_SUPPORTED
-        if (lpDosTask) {
-	    DWORD base = (DWORD)DOSMEM_MemoryBase();
-            DWORD sbase = GetSelectorBase( BX_reg(context) );
-	    if (!sbase) {
-	        /* the app has set the limit without setting the base,
-	         * it must be relying on that the default should be DOS space;
-	         * so set the base address now */
-	        SetSelectorBase( BX_reg(context), sbase = base );
-	        if (dw == 0xffffffff) {
-	            /* djgpp does this without checking (in _dos_ds setup, crt1.c),
-	             * so we have to override the limit here */
-	            dw = 0x110000;
-	        }
-	    }
-	    if (DOS_BADLIMIT(sbase, base, dw)) {
-                AX_reg(context) = 0x8021;  /* invalid value */
-                SET_CFLAG(context);
-                break;
-            }
-        }
-#endif
         SetSelectorLimit16( BX_reg(context), dw );
         break;
 
@@ -921,12 +852,6 @@
         {
             ldt_entry entry;
             LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
-#ifdef MZ_SUPPORTED
-            if (lpDosTask) {
-                DWORD base = (DWORD)DOSMEM_MemoryBase();
-		entry.base = DOS_WINETOAPP(entry.base, base);
-            }
-#endif
             entry.base = W32S_WINE2APP(entry.base, offset);
 
             /* FIXME: should use ES:EDI for 32-bit clients */
@@ -942,18 +867,6 @@
             LDT_BytesToEntry( PTR_SEG_OFF_TO_LIN( ES_reg(context),
                                                   DI_reg(context) ), &entry );
             entry.base = W32S_APP2WINE(entry.base, offset);
-#ifdef MZ_SUPPORTED
-            if (lpDosTask) {
-                DWORD base = (DWORD)DOSMEM_MemoryBase();
-	        entry.base = DOS_APPTOWINE(entry.base, base);
-		if (DOS_BADLIMIT(entry.base, base, entry.limit)) {
-		    AX_reg(context) = 0x8021;  /* invalid value */
-                    SET_CFLAG(context);
-		    break;
-		}
-            }
-#endif
-
             LDT_SetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
         }
         break;
@@ -1032,7 +945,7 @@
         /* we probably won't need this kind of state saving */
         AX_reg(context) = 0;
 	/* real mode: just point to the lret */
-	BX_reg(context) = DPMI_wrap_seg;
+	BX_reg(context) = DOSMEM_wrap_seg;
 	ECX_reg(context) = 2;
 	/* protected mode: don't have any handler yet... */
 	FIXME("no protected-mode dummy state save/restore handler yet\n");
@@ -1042,18 +955,12 @@
 
     case 0x0306:  /* Get Raw Mode Switch Addresses */
         TRACE("get raw mode switch addresses\n");
-	if (lpDosTask) {
-	  /* real mode, point to standard DPMI return wrapper */
-	  BX_reg(context) = DPMI_wrap_seg;
-	  ECX_reg(context) = 0;
-	  /* protected mode, point to DPMI call wrapper */
-	  SI_reg(context) = lpDosTask->dpmi_sel;
-	  EDI_reg(context) = 8; /* offset of the INT 0x31 call */
-	} else {
-	  ERR("win app attempting to get raw mode switch!\n");
-	  AX_reg(context) = 0x8001; /* unsupported function */
-	  SET_CFLAG(context);
-	}
+        /* real mode, point to standard DPMI return wrapper */
+        BX_reg(context) = DOSMEM_wrap_seg;
+        ECX_reg(context) = 0;
+        /* protected mode, point to DPMI call wrapper */
+        SI_reg(context) = DOSMEM_dpmi_sel;
+        EDI_reg(context) = 8; /* offset of the INT 0x31 call */
 	break;
     case 0x0400:  /* Get DPMI version */
         TRACE("get DPMI version\n");
diff --git a/msdos/int09.c b/msdos/int09.c
index f232b8d..6a527e3 100644
--- a/msdos/int09.c
+++ b/msdos/int09.c
@@ -15,9 +15,11 @@
 
 #define QUEUELEN 31
 
-typedef struct {
+static struct
+{
   BYTE queuelen,queue[QUEUELEN],ascii[QUEUELEN];
-} KBDSYSTEM;
+} kbdinfo;
+
 
 /**********************************************************************
  *	    INT_Int09Handler
@@ -58,48 +60,35 @@
   DOSVM_PIC_ioport_out(0x20, 0x20); /* send EOI */
 }
 
-static void KbdRelay( LPDOSTASK lpDosTask, CONTEXT86 *context, void *data )
+static void KbdRelay( CONTEXT86 *context, void *data )
 {
-  KBDSYSTEM *sys = (KBDSYSTEM *)DOSVM_GetSystemData(0x09);
-
-  if (sys && sys->queuelen) {
+  if (kbdinfo.queuelen) {
     /* cleanup operation, called from DOSVM_PIC_ioport_out:
      * 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... */
-    if (--sys->queuelen) {
-      memmove(sys->queue,sys->queue+1,sys->queuelen);
-      memmove(sys->ascii,sys->ascii+1,sys->queuelen);
+    if (--kbdinfo.queuelen) {
+      memmove(kbdinfo.queue,kbdinfo.queue+1,kbdinfo.queuelen);
+      memmove(kbdinfo.ascii,kbdinfo.ascii+1,kbdinfo.queuelen);
     }
   }
 }
 
 void WINAPI INT_Int09SendScan( BYTE scan, BYTE ascii )
 {
-  KBDSYSTEM *sys = (KBDSYSTEM *)DOSVM_GetSystemData(0x09);
-  if (!sys) {
-    sys = calloc(1,sizeof(KBDSYSTEM));
-    DOSVM_SetSystemData(0x09,sys);
-  }
-  if (sys->queuelen == QUEUELEN) {
+  if (kbdinfo.queuelen == QUEUELEN) {
     ERR("keyboard queue overflow\n");
     return;
   }
   /* add scancode to queue */
-  sys->queue[sys->queuelen] = scan;
-  sys->ascii[sys->queuelen++] = 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);
 }
 
 BYTE WINAPI INT_Int09ReadScan( BYTE*ascii )
 {
-  KBDSYSTEM *sys = (KBDSYSTEM *)DOSVM_GetSystemData(0x09);
-  if (sys) {
-    if (ascii) *ascii = sys->ascii[0];
-    return sys->queue[0];
-  } else {
-    if (ascii) *ascii = 0;
-    return 0;
-  }
+    if (ascii) *ascii = kbdinfo.ascii[0];
+    return kbdinfo.queue[0];
 }
diff --git a/msdos/int2f.c b/msdos/int2f.c
index dca31b5..43a014a 100644
--- a/msdos/int2f.c
+++ b/msdos/int2f.c
@@ -115,9 +115,7 @@
 	    break;
 	case 0x10:   /* XMS v2+ get driver address */
 	{
-            LPDOSTASK lpDosTask = MZ_Current();
-
-            ES_reg(context) = lpDosTask ? lpDosTask->xms_seg : 0;
+            ES_reg(context) = DOSMEM_xms_seg;
             BX_reg(context) = 0;
             break;
 	}
@@ -349,15 +347,13 @@
 #endif
         {
 	    SYSTEM_INFO si;
-	    LPDOSTASK lpDosTask = MZ_Current();
-
 	    GetSystemInfo(&si);
 	    AX_reg(context) = 0x0000; /* DPMI Installed */
             BX_reg(context) = 0x0001; /* 32bits available */
             CL_reg(context) = si.wProcessorLevel;
             DX_reg(context) = 0x005a; /* DPMI major/minor 0.90 */
             SI_reg(context) = 0;      /* # of para. of DOS extended private data */
-            ES_reg(context) = lpDosTask ? lpDosTask->dpmi_seg : 0;
+            ES_reg(context) = DOSMEM_dpmi_seg;
             DI_reg(context) = 0;      /* ES:DI is DPMI switch entry point */
             break;
         }
@@ -402,9 +398,8 @@
     case 3:
     case 12:
 	ptr += sprintf(ptr, "\n\t\t\t\tIO_struct => ");
-	ios = (dorealmode) ? 
-		DOSMEM_MapRealToLinear(MAKELONG(PTR_AT(req, 14, WORD), PTR_AT(req, 16, WORD))) :
-		    PTR_SEG_OFF_TO_LIN(PTR_AT(req, 16, WORD), PTR_AT(req, 14, WORD));
+	ios = (dorealmode) ? PTR_REAL_TO_LIN( PTR_AT(req, 16, WORD), PTR_AT(req, 14, WORD)) :
+                             PTR_SEG_OFF_TO_LIN(PTR_AT(req, 16, WORD), PTR_AT(req, 14, WORD));
 
 	for (i = 0; i < PTR_AT(req, 18, WORD); i++) {
 	    ptr += sprintf(ptr, "%02x ", ios[i]);
@@ -476,9 +471,7 @@
 	    BYTE 	Error = 255; /* No Error */ 
 	    int		dorealmode = ISV86(context);
 	    
-	    driver_request = (dorealmode) ? 
-		DOSMEM_MapRealToLinear(MAKELONG(BX_reg(context), ES_reg(context))) : 
-		PTR_SEG_OFF_TO_LIN(ES_reg(context), BX_reg(context));
+	    driver_request = CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx);
 	    
 	    if (!driver_request) {
 		/* FIXME - to be deleted ?? */
@@ -517,7 +510,7 @@
 	    switch (driver_request[2]) {
 	    case 3:
 		io_stru = (dorealmode) ? 
-		    DOSMEM_MapRealToLinear(MAKELONG(PTR_AT(driver_request, 14, WORD), PTR_AT(driver_request, 16, WORD))) :
+                    PTR_REAL_TO_LIN( PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD) ) :
 			PTR_SEG_OFF_TO_LIN(PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD));
 		
 		TRACE(" --> IOCTL INPUT <%d>\n", io_stru[0]); 
@@ -682,7 +675,7 @@
 		
 	    case 12:
 		io_stru = (dorealmode) ? 
-		    DOSMEM_MapRealToLinear(MAKELONG(PTR_AT(driver_request, 14, WORD), PTR_AT(driver_request, 16, WORD))) :
+		    PTR_REAL_TO_LIN( PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD)) :
 			PTR_SEG_OFF_TO_LIN(PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD));
 		
 		TRACE(" --> IOCTL OUTPUT <%d>\n", io_stru[0]); 
diff --git a/msdos/int33.c b/msdos/int33.c
index abbc641..10d2f67 100644
--- a/msdos/int33.c
+++ b/msdos/int33.c
@@ -13,11 +13,12 @@
 
 DEFAULT_DEBUG_CHANNEL(int)
 
-typedef struct {
+static struct
+{
   DWORD x, y, but;
   FARPROC16 callback;
   WORD callmask;
-} MOUSESYSTEM;
+} mouse_info;
 
 /**********************************************************************
  *	    INT_Int33Handler
@@ -26,15 +27,12 @@
  */
 void WINAPI INT_Int33Handler( CONTEXT86 *context )
 {
-  MOUSESYSTEM *sys = (MOUSESYSTEM *)DOSVM_GetSystemData(0x33);
-
   switch (AX_reg(context)) {
   case 0x00:
     TRACE("Reset mouse driver and request status\n");
     AX_reg(context) = 0xFFFF; /* installed */
     BX_reg(context) = 3;      /* # of buttons */
-    sys = calloc(1,sizeof(MOUSESYSTEM));
-    DOSVM_SetSystemData(0x33, sys);
+    memset( &mouse_info, 0, sizeof(mouse_info) );
     break;
   case 0x01:
     FIXME("Show mouse cursor\n");
@@ -44,9 +42,9 @@
     break;
   case 0x03:
     TRACE("Return mouse position and button status\n");
-    BX_reg(context) = sys->but;
-    CX_reg(context) = sys->x;
-    DX_reg(context) = sys->y;
+    BX_reg(context) = mouse_info.but;
+    CX_reg(context) = mouse_info.x;
+    DX_reg(context) = mouse_info.y;
     break;
   case 0x04:
     FIXME("Position mouse cursor\n");
@@ -65,8 +63,8 @@
     break;
   case 0x0C:
     TRACE("Define mouse interrupt subroutine\n");
-    sys->callmask = CX_reg(context);
-    sys->callback = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR(ES_reg(context), DX_reg(context));
+    mouse_info.callmask = CX_reg(context);
+    mouse_info.callback = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR(ES_reg(context), DX_reg(context));
     break;
   case 0x10:
     FIXME("Define screen region for update\n");
@@ -81,7 +79,7 @@
   WORD mask,but,x,y,mx,my;
 } MCALLDATA;
 
-static void MouseRelay(LPDOSTASK lpDosTask,CONTEXT86 *context,void *mdata)
+static void MouseRelay(CONTEXT86 *context,void *mdata)
 {
   MCALLDATA *data = (MCALLDATA *)mdata;
   CONTEXT86 ctx = *context;
@@ -100,58 +98,56 @@
 
 void WINAPI INT_Int33Message(UINT message,WPARAM wParam,LPARAM lParam)
 {
-  MOUSESYSTEM *sys = (MOUSESYSTEM *)DOSVM_GetSystemData(0x33);
   WORD mask = 0;
   unsigned Height, Width, SX=1, SY=1;
 
-  if (!sys) return;
   if (!VGA_GetMode(&Height,&Width,NULL)) {
     /* may need to do some coordinate scaling */
     SX = 640/Width;
     if (!SX) SX=1;
   }
-  sys->x = LOWORD(lParam) * SX;
-  sys->y = HIWORD(lParam) * SY;
+  mouse_info.x = LOWORD(lParam) * SX;
+  mouse_info.y = HIWORD(lParam) * SY;
   switch (message) {
   case WM_MOUSEMOVE:
     mask |= 0x01;
     break;
   case WM_LBUTTONDOWN:
   case WM_LBUTTONDBLCLK:
-    sys->but |= 0x01;
+    mouse_info.but |= 0x01;
     mask |= 0x02;
     break;
   case WM_LBUTTONUP:
-    sys->but &= ~0x01;
+    mouse_info.but &= ~0x01;
     mask |= 0x04;
     break;
   case WM_RBUTTONDOWN:
   case WM_RBUTTONDBLCLK:
-    sys->but |= 0x02;
+    mouse_info.but |= 0x02;
     mask |= 0x08;
     break;
   case WM_RBUTTONUP:
-    sys->but &= ~0x02;
+    mouse_info.but &= ~0x02;
     mask |= 0x10;
     break;
   case WM_MBUTTONDOWN:
   case WM_MBUTTONDBLCLK:
-    sys->but |= 0x04;
+    mouse_info.but |= 0x04;
     mask |= 0x20;
     break;
   case WM_MBUTTONUP:
-    sys->but &= ~0x04;
+    mouse_info.but &= ~0x04;
     mask |= 0x40;
     break;
   }
 
-  if ((mask & sys->callmask) && sys->callback) {
+  if ((mask & mouse_info.callmask) && mouse_info.callback) {
     MCALLDATA *data = calloc(1,sizeof(MCALLDATA));
-    data->proc = sys->callback;
-    data->mask = mask & sys->callmask;
-    data->but = sys->but;
-    data->x = sys->x;
-    data->y = sys->y;
+    data->proc = mouse_info.callback;
+    data->mask = mask & mouse_info.callmask;
+    data->but = mouse_info.but;
+    data->x = mouse_info.x;
+    data->y = mouse_info.y;
     DOSVM_QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data);
   }
 }