- Several kernel.spec return type mismatch fixes
- [GS]etSelectorBase Win32s offset support by Ulrich Weigand (thanks v.m. !!)
- Move AppToWine/WineToApp macros as W32S_APP2WINE etc. to ldt.h
- LocalNotify() basic support
- Fixes for local heap handling with heap handles created by Virtual*()

diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index be35de9..0891322 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -12,13 +12,13 @@
 5   pascal16 LocalAlloc(word word) LocalAlloc16
 6   pascal16 LocalReAlloc(word word word) LocalReAlloc16
 7   pascal16 LocalFree(word) LocalFree16
-8   pascal16 LocalLock(word) LocalLock16
+8   pascal LocalLock(word) LocalLock16
 9   pascal16 LocalUnlock(word) LocalUnlock16
 10  pascal16 LocalSize(word) LocalSize16
 11  pascal16 LocalHandle(word) LocalHandle16
 12  pascal16 LocalFlags(word) LocalFlags16
 13  pascal16 LocalCompact(word) LocalCompact16
-14  pascal16 LocalNotify(long) LocalNotify
+14  pascal LocalNotify(long) LocalNotify
 15  pascal16 GlobalAlloc(word long) GlobalAlloc16
 16  pascal16 GlobalReAlloc(word long word) GlobalReAlloc16
 17  pascal16 GlobalFree(word) GlobalFree16
@@ -38,7 +38,7 @@
 31  pascal16 PostEvent(word) PostEvent
 32  pascal16 SetPriority(word s_word) SetPriority
 33  pascal16 LockCurrentTask(word) LockCurrentTask
-34  pascal SetTaskQueue(word word) SetTaskQueue
+34  pascal16 SetTaskQueue(word word) SetTaskQueue
 35  pascal16 GetTaskQueue(word) GetTaskQueue
 36  pascal   GetCurrentTask() WIN16_GetCurrentTask
 37  pascal GetCurrentPDB() GetCurrentPDB
@@ -188,8 +188,8 @@
 183 equate __0000H 0
 184 pascal GlobalDOSAlloc(long) GlobalDOSAlloc
 185 pascal16 GlobalDOSFree(word) GlobalDOSFree
-186 pascal GetSelectorBase(word) GetSelectorBase
-187 pascal16 SetSelectorBase(word long) SetSelectorBase
+186 pascal GetSelectorBase(word) WIN16_GetSelectorBase
+187 pascal16 SetSelectorBase(word long) WIN16_SetSelectorBase
 188 pascal GetSelectorLimit(word) GetSelectorLimit
 189 pascal16 SetSelectorLimit(word long) SetSelectorLimit
 190 equate __E000H 0
diff --git a/if1632/thunk.c b/if1632/thunk.c
index 59752b4..48c68e6 100644
--- a/if1632/thunk.c
+++ b/if1632/thunk.c
@@ -156,6 +156,7 @@
     (void *)CallTo16_word_lwww,            /* CallWordBreakProc */
     (void *)CallTo16_word_ww,              /* CallBootAppProc */
     (void *)CallTo16_word_www,             /* CallLoadAppSegProc */
+    (void *)CallTo16_word_www,             /* CallLocalNotifyFunc */
     (void *)CallTo16_word_,                /* CallSystemTimerProc */
     (void *)CallTo16_word_www,             /* CallResourceHandlerProc */
     (void *)CallTo16_word_wwwl,            /* CallPostAppMessageProc */
diff --git a/include/callback.h b/include/callback.h
index 14f42a9..1b46d6f 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -36,6 +36,7 @@
                                          INT16, INT16 );
     VOID (CALLBACK *CallBootAppProc)( FARPROC16, HANDLE16, HFILE16 );
     WORD (CALLBACK *CallLoadAppSegProc)( FARPROC16, HANDLE16, HFILE16, WORD );
+    WORD (CALLBACK *CallLocalNotifyFunc)( FARPROC16, WORD, HLOCAL16, WORD );
     VOID (CALLBACK *CallSystemTimerProc)( FARPROC16 );
     HGLOBAL16 (CALLBACK *CallResourceHandlerProc)( FARPROC16, HGLOBAL16, HMODULE16, HRSRC16 );
     BOOL16 (CALLBACK *CallPostAppMessageProc)( FARPROC16, HTASK16, UINT16, WPARAM16, LPARAM );
diff --git a/include/ldt.h b/include/ldt.h
index 0f46d9a..1e9d7db 100644
--- a/include/ldt.h
+++ b/include/ldt.h
@@ -67,6 +67,11 @@
 #define PTR_SEG_OFF_TO_HUGEPTR(seg,off) \
    PTR_SEG_OFF_TO_SEGPTR( (seg) + (HIWORD(off) << __AHSHIFT), LOWORD(off) )
 
+#define W32S_APPLICATION() (PROCESS_Current()->flags & PDB32_WIN32S_PROC)
+#define W32S_OFFSET 0x10000
+#define W32S_APP2WINE(addr, offset) ((addr)? (DWORD)(addr) + (DWORD)(offset) : 0)
+#define W32S_WINE2APP(addr, offset) ((addr)? (DWORD)(addr) - (DWORD)(offset) : 0)
+
 extern unsigned char ldt_flags_copy[LDT_SIZE];
 
 #define LDT_FLAGS_TYPE      0x03  /* Mask for segment type */
diff --git a/include/windows.h b/include/windows.h
index bfd5fda..b314b00 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -6616,7 +6616,7 @@
 HBRUSH16    WINAPI GetControlBrush(HWND16,HDC16,UINT16);
 VOID        WINAPI GetCodeInfo(FARPROC16,SEGINFO*);
 HFONT16     WINAPI GetCurLogFont(HDC16);
-HANDLE16    WINAPI GetCurrentPDB(void);
+DWORD       WINAPI GetCurrentPDB(void);
 DWORD       WINAPI GetCurrentPosition(HDC16);
 HTASK16     WINAPI GetCurrentTask(void);
 DWORD       WINAPI GetDCHook(HDC16,FARPROC16*);
diff --git a/loader/task.c b/loader/task.c
index badfc9d..c18f418 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -1426,13 +1426,15 @@
 
 /***********************************************************************
  *           GetCurrentPDB   (KERNEL.37)
+ *
+ * UNDOC: returns PSP of KERNEL in high word
  */
-HANDLE16 WINAPI GetCurrentPDB(void)
+DWORD WINAPI GetCurrentPDB(void)
 {
     TDB *pTask;
 
     if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return 0;
-    return pTask->hPDB;
+    return MAKELONG(pTask->hPDB, 0); /* FIXME */
 }
 
 
@@ -1596,6 +1598,9 @@
 
 /***********************************************************************
  *           GlobalNotify   (KERNEL.154)
+ *
+ * Note that GlobalNotify does _not_ return the old NotifyProc
+ * -- contrary to LocalNotify !!
  */
 VOID WINAPI GlobalNotify( FARPROC16 proc )
 {
diff --git a/memory/local.c b/memory/local.c
index bcd34e3..fe91eab 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -25,6 +25,7 @@
 #include "stackframe.h"
 #include "toolhelp.h"
 #include "debug.h"
+#include "callback.h"
 
 typedef struct
 {
@@ -44,6 +45,12 @@
 #define LOCAL_ARENA_FREE       0
 #define LOCAL_ARENA_FIXED      1
 
+/* LocalNotify() msgs */
+
+#define LN_OUTOFMEM	0
+#define LN_MOVE		1
+#define LN_DISCARD	2
+
 /* Layout of a handle entry table
  *
  * WORD                     count of entries
@@ -426,24 +433,29 @@
 /***********************************************************************
  *           LOCAL_GrowHeap
  */
-static void LOCAL_GrowHeap( HANDLE16 ds )
+static BOOL16 LOCAL_GrowHeap( HANDLE16 ds )
 {
-    HANDLE16 hseg = GlobalHandle16( ds );
-    LONG oldsize = GlobalSize16( hseg );
+    HANDLE16 hseg;
+    LONG oldsize;
     LONG end;
     LOCALHEAPINFO *pHeapInfo;
     WORD freeArena, lastArena;
     LOCALARENA *pArena, *pLastArena;
     char *ptr;
     
+    hseg = GlobalHandle16( ds );
+    /* maybe mem allocated by Virtual*() ? */
+    if (!hseg) return FALSE;
+
+    oldsize = GlobalSize16( hseg );
     /* if nothing can be gained, return */
-    if (oldsize > 0xfff0) return;
+    if (oldsize > 0xfff0) return FALSE;
     hseg = GlobalReAlloc16( hseg, 0x10000, GMEM_FIXED );
     ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
     pHeapInfo = LOCAL_GetHeap( ds );
     if (pHeapInfo == NULL) {
 	ERR(local, "Heap not found\n" );
-	return;
+	return FALSE;
     }
     end = GlobalSize16( hseg );
     lastArena = (end - sizeof(LOCALARENA)) & ~3;
@@ -478,6 +490,7 @@
 
     TRACE(local, "Heap expanded\n" );
     LOCAL_PrintHeap( ds );
+    return TRUE;
 }
 
 
@@ -715,6 +728,9 @@
                            movesize - ARENA_HEADER_SIZE );
                     /* Free the old location */  
                     LOCAL_FreeArena(ds, movearena);
+		    if (pInfo->notify)
+		        Callbacks->CallLocalNotifyFunc(pInfo->notify, LN_MOVE,
+			(WORD)((char *)pEntry - ptr), pEntry->addr);
                     /* Update handle table entry */
                     pEntry->addr = finalarena + ARENA_HEADER_SIZE + sizeof(HLOCAL16) ;
                 }
@@ -751,9 +767,11 @@
                 TRACE(local, "Discarding handle %04x (block %04x).\n",
                               (char *)pEntry - ptr, pEntry->addr);
                 LOCAL_FreeArena(ds, ARENA_HEADER(pEntry->addr));
+		if (pInfo->notify)
+                    Callbacks->CallLocalNotifyFunc(pInfo->notify, LN_DISCARD,
+			(char *)pEntry - ptr, pEntry->flags);
                 pEntry->addr = 0;
                 pEntry->flags = (LMEM_DISCARDED >> 8);
-                /* Call localnotify proc */
             }
         }
         table = *(WORD *)pEntry;
@@ -814,6 +832,9 @@
     size += ARENA_HEADER_SIZE;
     size = LALIGN( MAX( size, sizeof(LOCALARENA) ) );
 
+#if 0
+notify_done:
+#endif
       /* Find a suitable free block */
     arena = LOCAL_FindFreeBlock( ds, size );
     if (arena == 0) {
@@ -823,7 +844,15 @@
     }
     if (arena == 0) {
 	/* still no space: try to grow the segment */
-	LOCAL_GrowHeap( ds );
+	if (!(LOCAL_GrowHeap( ds )))
+	{
+#if 0
+	    /* FIXME: doesn't work correctly yet */
+	    if ((pInfo->notify) && (Callbacks->CallLocalNotifyFunc(pInfo->notify, LN_OUTOFMEM, ds - 20, size))) /* FIXME: "size" correct ? (should indicate bytes needed) */
+		goto notify_done;
+#endif
+	    return 0;
+	}
 	ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
 	pInfo = LOCAL_GetHeap( ds );
 	arena = LOCAL_FindFreeBlock( ds, size );
@@ -839,6 +868,12 @@
 	    ERR(local, "not enough space in local heap "
 			 "%04x for %d bytes\n", ds, size );
 	}
+#if 0
+        if ((pInfo->notify) &&
+        /* FIXME: "size" correct ? (should indicate bytes needed) */
+	(Callbacks->CallLocalNotifyFunc(pInfo->notify, LN_OUTOFMEM, ds, size)))
+	    goto notify_done;
+#endif
 	return 0;
     }
 
@@ -1563,6 +1598,21 @@
 
 /***********************************************************************
  *           LocalNotify   (KERNEL.14)
+ *
+ * Installs a callback function that is called for local memory events
+ * Callback function prototype is
+ * BOOL16 NotifyFunc(WORD wMsg, HLOCAL16 hMem, WORD wArg)
+ * wMsg:
+ * - LN_OUTOFMEM
+ *   NotifyFunc seems to be responsible for allocating some memory,
+ *   returns TRUE for success.
+ *   wArg = number of bytes needed additionally
+ * - LN_MOVE
+ *   hMem = handle; wArg = old mem location
+ * - LN_DISCARD
+ *   NotifyFunc seems to be strongly encouraged to return TRUE,
+ *   otherwise LogError() gets called.
+ *   hMem = handle; wArg = flags
  */
 FARPROC16 WINAPI LocalNotify( FARPROC16 func )
 {
diff --git a/memory/selector.c b/memory/selector.c
index 57fd391..ac64ef2 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -10,6 +10,7 @@
 #include "miscemu.h"
 #include "selectors.h"
 #include "stackframe.h"
+#include "process.h"
 #include "debug.h"
 
 
@@ -301,6 +302,17 @@
 /***********************************************************************
  *           GetSelectorBase   (KERNEL.186)
  */
+DWORD WINAPI WIN16_GetSelectorBase( WORD sel )
+{
+    /*
+     * Note: For Win32s processes, the whole linear address space is
+     *       shifted by 0x10000 relative to the OS linear address space.
+     *       See the comment in msdos/vxd.c.
+     */
+
+    DWORD base = GetSelectorBase( sel );
+    return W32S_WINE2APP( base, W32S_APPLICATION() ? W32S_OFFSET : 0 );
+}
 DWORD WINAPI GetSelectorBase( WORD sel )
 {
     DWORD base = GET_SEL_BASE(sel);
@@ -315,6 +327,18 @@
 /***********************************************************************
  *           SetSelectorBase   (KERNEL.187)
  */
+DWORD WINAPI WIN16_SetSelectorBase( WORD sel, DWORD base )
+{
+    /*
+     * Note: For Win32s processes, the whole linear address space is
+     *       shifted by 0x10000 relative to the OS linear address space.
+     *       See the comment in msdos/vxd.c.
+     */
+
+    SetSelectorBase( sel,
+	W32S_APP2WINE( base, W32S_APPLICATION() ? W32S_OFFSET : 0 ) );
+    return sel;
+}
 WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
 {
     ldt_entry entry;
diff --git a/misc/callback.c b/misc/callback.c
index c27eeb3..0449c70 100644
--- a/misc/callback.c
+++ b/misc/callback.c
@@ -110,6 +110,17 @@
 
 
 /**********************************************************************
+ *           CALLBACK_CallLocalNotifyFunc
+ */
+static WORD WINAPI CALLBACK_CallLocalNotifyFunc( FARPROC16 proc,
+                                                 WORD wMsg, HLOCAL16 hMem,
+                                                 WORD wArg )
+{
+    return proc( wMsg, hMem, wArg );
+}
+
+
+/**********************************************************************
  *	     CALLBACK_CallSystemTimerProc
  */
 static void WINAPI CALLBACK_CallSystemTimerProc( FARPROC16 proc )
@@ -262,6 +273,7 @@
     CALLBACK_CallWordBreakProc,       /* CallWordBreakProc */
     CALLBACK_CallBootAppProc,         /* CallBootAppProc */
     CALLBACK_CallLoadAppSegProc,      /* CallLoadAppSegProc */
+    CALLBACK_CallLocalNotifyFunc,     /* CallLocalNotifyFunc */
     CALLBACK_CallSystemTimerProc,     /* CallSystemTimerProc */
     CALLBACK_CallResourceHandlerProc, /* CallResourceHandlerProc */
     NULL,                             /* CallPostAppMessageProc */
diff --git a/msdos/dpmi.c b/msdos/dpmi.c
index 5387ce8..60db02a 100644
--- a/msdos/dpmi.c
+++ b/msdos/dpmi.c
@@ -486,9 +486,7 @@
      *       shifted by 0x10000 relative to the OS linear address space.
      *       See the comment in msdos/vxd.c.
      */
-    DWORD offset = PROCESS_Current()->flags & PDB32_WIN32S_PROC ? 0x10000 : 0;
-    #define AppToWine(addr) ((addr)? ((DWORD)(addr)) + offset : 0)
-    #define WineToApp(addr) ((addr)? ((DWORD)(addr)) - offset : 0)
+    DWORD offset = W32S_APPLICATION() ? W32S_OFFSET : 0;
 
     DWORD dw;
     BYTE *ptr;
@@ -603,16 +601,16 @@
                 if ((dw >= base) && (dw < base + 0x110000)) dw -= base;
             }
 #endif
-            CX_reg(context) = HIWORD(WineToApp(dw));
-            DX_reg(context) = LOWORD(WineToApp(dw));
+            CX_reg(context) = HIWORD(W32S_WINE2APP(dw, offset));
+            DX_reg(context) = LOWORD(W32S_WINE2APP(dw, offset));
         }
         break;
 
     case 0x0007:  /* Set selector base address */
     	TRACE(int31, "set selector base address (0x%04x,0x%08lx)\n",
                      BX_reg(context),
-                     AppToWine(MAKELONG(DX_reg(context),CX_reg(context))));
-        dw = AppToWine(MAKELONG(DX_reg(context), CX_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
         /* well, what else could we possibly do? */
         if (pModule && pModule->lpDosTask) {
@@ -657,7 +655,7 @@
         {
             ldt_entry entry;
             LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
-            entry.base = WineToApp(entry.base);
+            entry.base = W32S_WINE2APP(entry.base, offset);
 
             /* FIXME: should use ES:EDI for 32-bit clients */
             LDT_EntryToBytes( PTR_SEG_OFF_TO_LIN( ES_reg(context),
@@ -671,7 +669,7 @@
             ldt_entry entry;
             LDT_BytesToEntry( PTR_SEG_OFF_TO_LIN( ES_reg(context),
                                                   DI_reg(context) ), &entry );
-            entry.base = AppToWine(entry.base);
+            entry.base = W32S_APP2WINE(entry.base, offset);
 
             LDT_SetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
         }
@@ -784,31 +782,31 @@
             AX_reg(context) = 0x8012;  /* linear memory not available */
             SET_CFLAG(context);
         } else {
-            BX_reg(context) = SI_reg(context) = HIWORD(WineToApp(ptr));
-            CX_reg(context) = DI_reg(context) = LOWORD(WineToApp(ptr));
+            BX_reg(context) = SI_reg(context) = HIWORD(W32S_WINE2APP(ptr, offset));
+            CX_reg(context) = DI_reg(context) = LOWORD(W32S_WINE2APP(ptr, offset));
         }
         break;
 
     case 0x0502:  /* Free memory block */
         TRACE(int31, "free memory block (0x%08lx)\n",
-                     AppToWine(MAKELONG(DI_reg(context),SI_reg(context))));
-	DPMI_xfree( (void *)AppToWine(MAKELONG(DI_reg(context), 
-                                               SI_reg(context))) );
+                     W32S_APP2WINE(MAKELONG(DI_reg(context),SI_reg(context)), offset));
+	DPMI_xfree( (void *)W32S_APP2WINE(MAKELONG(DI_reg(context), 
+                                               SI_reg(context)), offset) );
         break;
 
     case 0x0503:  /* Resize memory block */
         TRACE(int31, "resize memory block (0x%08lx,%ld)\n",
-                     AppToWine(MAKELONG(DI_reg(context),SI_reg(context))),
+                     W32S_APP2WINE(MAKELONG(DI_reg(context),SI_reg(context)), offset),
                      MAKELONG(CX_reg(context),BX_reg(context)));
         if (!(ptr = (BYTE *)DPMI_xrealloc(
-                (void *)AppToWine(MAKELONG(DI_reg(context),SI_reg(context))),
+                (void *)W32S_APP2WINE(MAKELONG(DI_reg(context),SI_reg(context)), offset),
                 MAKELONG(CX_reg(context),BX_reg(context)))))
         {
             AX_reg(context) = 0x8012;  /* linear memory not available */
             SET_CFLAG(context);
         } else {
-            BX_reg(context) = SI_reg(context) = HIWORD(WineToApp(ptr));
-            CX_reg(context) = DI_reg(context) = LOWORD(WineToApp(ptr));
+            BX_reg(context) = SI_reg(context) = HIWORD(W32S_WINE2APP(ptr, offset));
+            CX_reg(context) = DI_reg(context) = LOWORD(W32S_WINE2APP(ptr, offset));
         }
         break;
 
@@ -855,8 +853,8 @@
          }
          else
          {
-             BX_reg(context) = HIWORD(WineToApp(ptr));
-             CX_reg(context) = LOWORD(WineToApp(ptr));
+             BX_reg(context) = HIWORD(W32S_WINE2APP(ptr, offset));
+             CX_reg(context) = LOWORD(W32S_WINE2APP(ptr, offset));
              RESET_CFLAG(context);
          }
          break;
@@ -868,6 +866,4 @@
         break;
     }
 
-    #undef AppToWine
-    #undef WineToApp
 }
diff --git a/msdos/int41.c b/msdos/int41.c
index 1f4d2f3..4ba588e 100644
--- a/msdos/int41.c
+++ b/msdos/int41.c
@@ -27,6 +27,7 @@
         /* Protected-mode debugger services */
         switch ( AX_reg(context) )
         {
+        case 0x4f:
         case 0x50:
         case 0x150:
         case 0x51:
diff --git a/msdos/vxd.c b/msdos/vxd.c
index 39744d3..e1de208 100644
--- a/msdos/vxd.c
+++ b/msdos/vxd.c
@@ -459,9 +459,6 @@
 
 void VXD_Win32s( CONTEXT *context )
 {
-    #define AppToWine(addr) ((addr)? ((LPBYTE)(addr)) + 0x10000 : NULL)
-    #define WineToApp(addr) ((addr)? ((DWORD) (addr)) - 0x10000 : 0)
-
     switch (AX_reg(context))
     {
     case 0x0000: /* Get Version */
@@ -570,7 +567,7 @@
 
         /* 
          * Mark process as Win32s, so that subsequent DPMI calls
-         * will perform the AppToWine/WineToApp address shift.
+         * will perform the W32S_APP2WINE/W32S_WINE2APP address shift.
          */
 
         PROCESS_Current()->flags |= PDB32_WIN32S_PROC;
@@ -682,7 +679,7 @@
          */
 
         struct Win32sModule *moduleTable = 
-                            (struct Win32sModule *)AppToWine(EDX_reg(context));
+                            (struct Win32sModule *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
         struct Win32sModule *module = moduleTable + ECX_reg(context);
 
         IMAGE_NT_HEADERS *nt_header = PE_HEADER(module->baseAddr);
@@ -774,7 +771,7 @@
          * Output:  EAX: 1 if OK
          */
         
-        TRACE(vxd, "UnMapModule: %lx\n", (DWORD)AppToWine(EDX_reg(context)));
+        TRACE(vxd, "UnMapModule: %lx\n", (DWORD)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET));
 
         /* As we didn't map anything, there's nothing to unmap ... */
 
@@ -797,9 +794,9 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack  = (DWORD *)AppToWine(EDX_reg(context));
-        DWORD *retv   = (DWORD *)AppToWine(stack[0]);
-        LPVOID base   = (LPVOID) AppToWine(stack[1]);
+        DWORD *stack  = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
+        DWORD *retv   = (DWORD *)W32S_APP2WINE(stack[0], W32S_OFFSET);
+        LPVOID base   = (LPVOID) W32S_APP2WINE(stack[1], W32S_OFFSET);
         DWORD  size   = stack[2];
         DWORD  type   = stack[3];
         DWORD  prot   = stack[4];
@@ -822,8 +819,8 @@
 
         result = (DWORD)VirtualAlloc(base, size, type, prot);
 
-        if (WineToApp(result))
-            *retv            = WineToApp(result),
+        if (W32S_WINE2APP(result, W32S_OFFSET))
+            *retv            = W32S_WINE2APP(result, W32S_OFFSET),
             EAX_reg(context) = STATUS_SUCCESS;
         else
             *retv            = 0,
@@ -846,9 +843,9 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack  = (DWORD *)AppToWine(EDX_reg(context));
-        DWORD *retv   = (DWORD *)AppToWine(stack[0]);
-        LPVOID base   = (LPVOID) AppToWine(stack[1]);
+        DWORD *stack  = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
+        DWORD *retv   = (DWORD *)W32S_APP2WINE(stack[0], W32S_OFFSET);
+        LPVOID base   = (LPVOID) W32S_APP2WINE(stack[1], W32S_OFFSET);
         DWORD  size   = stack[2];
         DWORD  type   = stack[3];
         DWORD  result;
@@ -883,12 +880,12 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack    = (DWORD *)AppToWine(EDX_reg(context));
-        DWORD *retv     = (DWORD *)AppToWine(stack[0]);
-        LPVOID base     = (LPVOID) AppToWine(stack[1]);
+        DWORD *stack    = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
+        DWORD *retv     = (DWORD *)W32S_APP2WINE(stack[0], W32S_OFFSET);
+        LPVOID base     = (LPVOID) W32S_APP2WINE(stack[1], W32S_OFFSET);
         DWORD  size     = stack[2];
         DWORD  new_prot = stack[3];
-        DWORD *old_prot = (DWORD *)AppToWine(stack[4]);
+        DWORD *old_prot = (DWORD *)W32S_APP2WINE(stack[4], W32S_OFFSET);
         DWORD  result;
 
         TRACE(vxd, "VirtualProtect(%lx, %lx, %lx, %lx, %lx)\n", 
@@ -920,11 +917,11 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack  = (DWORD *)AppToWine(EDX_reg(context));
-        DWORD *retv   = (DWORD *)AppToWine(stack[0]);
-        LPVOID base   = (LPVOID) AppToWine(stack[1]);
+        DWORD *stack  = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
+        DWORD *retv   = (DWORD *)W32S_APP2WINE(stack[0], W32S_OFFSET);
+        LPVOID base   = (LPVOID) W32S_APP2WINE(stack[1], W32S_OFFSET);
         LPMEMORY_BASIC_INFORMATION info = 
-                        (LPMEMORY_BASIC_INFORMATION)AppToWine(stack[2]);
+                        (LPMEMORY_BASIC_INFORMATION)W32S_APP2WINE(stack[2], W32S_OFFSET);
         DWORD  len    = stack[3];
         DWORD  result;
 
@@ -1003,11 +1000,11 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack    = (DWORD *)   AppToWine(EDX_reg(context));
-        HANDLE32 *retv  = (HANDLE32 *)AppToWine(stack[0]);
+        DWORD *stack    = (DWORD *)   W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
+        HANDLE32 *retv  = (HANDLE32 *)W32S_APP2WINE(stack[0], W32S_OFFSET);
         DWORD  flags1   = stack[1];
         DWORD  atom     = stack[2];
-        LARGE_INTEGER *size = (LARGE_INTEGER *)AppToWine(stack[3]);
+        LARGE_INTEGER *size = (LARGE_INTEGER *)W32S_APP2WINE(stack[3], W32S_OFFSET);
         DWORD  protect  = stack[4];
         DWORD  flags2   = stack[5];
         HFILE32 hFile   = HFILE16_TO_HFILE32(stack[6]);
@@ -1056,8 +1053,8 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack    = (DWORD *)   AppToWine(EDX_reg(context));
-        HANDLE32 *retv  = (HANDLE32 *)AppToWine(stack[0]);
+        DWORD *stack    = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
+        HANDLE32 *retv  = (HANDLE32 *)W32S_APP2WINE(stack[0], W32S_OFFSET);
         DWORD  protect  = stack[1];
         DWORD  atom     = stack[2];
 
@@ -1099,9 +1096,9 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack    = (DWORD *)AppToWine(EDX_reg(context));
+        DWORD *stack    = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
         HANDLE32 handle = stack[0];
-        DWORD *id       = (DWORD *)AppToWine(stack[1]);
+        DWORD *id       = (DWORD *)W32S_APP2WINE(stack[1], W32S_OFFSET);
 
         TRACE(vxd, "NtCloseSection(%lx, %lx)\n", (DWORD)handle, (DWORD)id);
 
@@ -1122,7 +1119,7 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack    = (DWORD *)AppToWine(EDX_reg(context));
+        DWORD *stack    = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
         HANDLE32 handle = stack[0];
 
         TRACE(vxd, "NtDupSection(%lx)\n", (DWORD)handle);
@@ -1153,19 +1150,20 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *  stack          = (DWORD *)AppToWine(EDX_reg(context));
+        DWORD *  stack          = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
         HANDLE32 SectionHandle  = stack[0];
         DWORD    ProcessHandle  = stack[1]; /* ignored */
-        DWORD *  BaseAddress    = (DWORD *)AppToWine(stack[2]);
+        DWORD *  BaseAddress    = (DWORD *)W32S_APP2WINE(stack[2], W32S_OFFSET);
         DWORD    ZeroBits       = stack[3];
         DWORD    CommitSize     = stack[4];
-        LARGE_INTEGER *SectionOffset = (LARGE_INTEGER *)AppToWine(stack[5]);
-        DWORD *  ViewSize       = (DWORD *)AppToWine(stack[6]);
+        LARGE_INTEGER *SectionOffset = (LARGE_INTEGER *)W32S_APP2WINE(stack[5], W32S_OFFSET);
+        DWORD *  ViewSize       = (DWORD *)W32S_APP2WINE(stack[6], W32S_OFFSET);
         DWORD    InheritDisposition = stack[7];
         DWORD    AllocationType = stack[8];
         DWORD    Protect        = stack[9];
 
-        LPBYTE address = (LPBYTE)(BaseAddress? AppToWine(*BaseAddress) : 0);
+        LPBYTE address = (LPBYTE)(BaseAddress?
+			W32S_APP2WINE(*BaseAddress, W32S_OFFSET) : 0);
         DWORD  access = 0, result;
 
         switch (Protect & ~(PAGE_GUARD|PAGE_NOCACHE))
@@ -1196,9 +1194,9 @@
 
         TRACE(vxd, "NtMapViewOfSection: result=%lx\n", result);
 
-        if (WineToApp(result))
+        if (W32S_WINE2APP(result, W32S_OFFSET))
         {
-            if (BaseAddress) *BaseAddress = WineToApp(result);
+            if (BaseAddress) *BaseAddress = W32S_WINE2APP(result, W32S_OFFSET);
             EAX_reg(context) = STATUS_SUCCESS;
         }
         else
@@ -1217,9 +1215,9 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack          = (DWORD *)AppToWine(EDX_reg(context));
+        DWORD *stack          = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
         DWORD  ProcessHandle  = stack[0]; /* ignored */
-        LPBYTE BaseAddress    = (LPBYTE)AppToWine(stack[1]);
+        LPBYTE BaseAddress    = (LPBYTE)W32S_APP2WINE(stack[1], W32S_OFFSET);
 
         TRACE(vxd, "NtUnmapViewOfSection(%lx, %lx)\n", 
                    ProcessHandle, (DWORD)BaseAddress);
@@ -1243,13 +1241,13 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack          = (DWORD *)AppToWine(EDX_reg(context));
+        DWORD *stack          = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
         DWORD  ProcessHandle  = stack[0]; /* ignored */
-        DWORD *BaseAddress    = (DWORD *)AppToWine(stack[1]);
-        DWORD *ViewSize       = (DWORD *)AppToWine(stack[2]);
-        DWORD *unknown        = (DWORD *)AppToWine(stack[3]);
+        DWORD *BaseAddress    = (DWORD *)W32S_APP2WINE(stack[1], W32S_OFFSET);
+        DWORD *ViewSize       = (DWORD *)W32S_APP2WINE(stack[2], W32S_OFFSET);
+        DWORD *unknown        = (DWORD *)W32S_APP2WINE(stack[3], W32S_OFFSET);
         
-        LPBYTE address = (LPBYTE)(BaseAddress? AppToWine(*BaseAddress) : 0);
+        LPBYTE address = (LPBYTE)(BaseAddress? W32S_APP2WINE(*BaseAddress, W32S_OFFSET) : 0);
         DWORD  size    = ViewSize? *ViewSize : 0;
 
         TRACE(vxd, "NtFlushVirtualMemory(%lx, %lx, %lx, %lx)\n", 
@@ -1350,9 +1348,9 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack  = (DWORD *)AppToWine(EDX_reg(context));
-        DWORD *retv   = (DWORD *)AppToWine(stack[0]);
-        LPVOID base   = (LPVOID) AppToWine(stack[1]);
+        DWORD *stack  = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
+        DWORD *retv   = (DWORD *)W32S_APP2WINE(stack[0], W32S_OFFSET);
+        LPVOID base   = (LPVOID) W32S_APP2WINE(stack[1], W32S_OFFSET);
         DWORD  size   = stack[2];
         DWORD  result;
 
@@ -1384,9 +1382,9 @@
          * Output:  EAX: NtStatus
          */
     {
-        DWORD *stack  = (DWORD *)AppToWine(EDX_reg(context));
-        DWORD *retv   = (DWORD *)AppToWine(stack[0]);
-        LPVOID base   = (LPVOID) AppToWine(stack[1]);
+        DWORD *stack  = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
+        DWORD *retv   = (DWORD *)W32S_APP2WINE(stack[0], W32S_OFFSET);
+        LPVOID base   = (LPVOID) W32S_APP2WINE(stack[1], W32S_OFFSET);
         DWORD  size   = stack[2];
         DWORD  result;
 
@@ -1424,8 +1422,8 @@
          *       FIXME: What about other OSes ?
          */
 
-        ECX_reg(context) = WineToApp(0x00000000);
-        EDX_reg(context) = WineToApp(0xbfffffff);
+        ECX_reg(context) = W32S_WINE2APP(0x00000000, W32S_OFFSET);
+        EDX_reg(context) = W32S_WINE2APP(0xbfffffff, W32S_OFFSET);
         break;
 
 
@@ -1448,7 +1446,7 @@
         };
 
         struct Win32sMemoryInfo *info = 
-                       (struct Win32sMemoryInfo *)AppToWine(ESI_reg(context));
+                       (struct Win32sMemoryInfo *)W32S_APP2WINE(ESI_reg(context), W32S_OFFSET);
 
         FIXME(vxd, "KGlobalMemStat(%lx)\n", (DWORD)info);
 
@@ -1485,7 +1483,7 @@
     {
         DWORD *stack  = PTR_SEG_OFF_TO_LIN(LOWORD(EDX_reg(context)), 
                                            HIWORD(EDX_reg(context)));
-        LPVOID base   = (LPVOID)AppToWine(stack[0]);
+        LPVOID base   = (LPVOID)W32S_APP2WINE(stack[0], W32S_OFFSET);
         DWORD  size   = stack[1];
         DWORD  type   = stack[2];
         DWORD  prot   = stack[3];
@@ -1502,12 +1500,13 @@
 
         result = (DWORD)VirtualAlloc(base, size, type, prot);
 
-        if (WineToApp(result))
-            EDX_reg(context) = WineToApp(result),
+        if (W32S_WINE2APP(result, W32S_OFFSET))
+            EDX_reg(context) = W32S_WINE2APP(result, W32S_OFFSET),
             EAX_reg(context) = STATUS_SUCCESS;
         else
             EDX_reg(context) = 0,
             EAX_reg(context) = STATUS_NO_MEMORY;  /* FIXME */
+	TRACE(vxd, "VirtualAlloc16: returning base %lx\n", EDX_reg(context));
     }
     break;
 
@@ -1526,7 +1525,7 @@
     {
         DWORD *stack  = PTR_SEG_OFF_TO_LIN(LOWORD(EDX_reg(context)), 
                                            HIWORD(EDX_reg(context)));
-        LPVOID base   = (LPVOID)AppToWine(stack[0]);
+        LPVOID base   = (LPVOID)W32S_APP2WINE(stack[0], W32S_OFFSET);
         DWORD  size   = stack[1];
         DWORD  type   = stack[2];
         DWORD  result;
@@ -1556,7 +1555,7 @@
          * Output:  NtStatus
          */
     {
-        DWORD *ptr = (DWORD *)AppToWine(ECX_reg(context));
+        DWORD *ptr = (DWORD *)W32S_APP2WINE(ECX_reg(context), W32S_OFFSET);
         BOOL32 set = EDX_reg(context);
         
         TRACE(vxd, "FWorkingSetSize(%lx, %lx)\n", (DWORD)ptr, (DWORD)set);
@@ -1575,7 +1574,5 @@
 	VXD_BARF( context, "W32S" );
     }
 
-    #undef AppToWine
-    #undef WineToApp
 }