Release 960705

Fri Jul  5 16:27:43 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/desktop.c]
	Use Windows file I/O routines to load the desktop bitmap.

	* [files/file.c]
	Implemented RemoveDirectory* and DeleteFile*.

	* [include/wine.h]
	Added SIGCONTEXT typedef to replace #define sigcontext_struct.

	* [loader/task.c]
	Fixed initial breakpoint setting for Win32 tasks.

	* [misc/wsprintf.c]
	Ignore Unicode formats for wsprintf16().

	* [objects/font.c]
	Implemented Win32 version of GetTextMetrics.

	* [windows/winproc.c] [windows/win.c] [windows/class.c]
	  [windows/dialog.c]
	Modified windows procedures to use thunks, to ensure that the
	procedure can be called directly from the Windows program.

	* [windows/win.c]
	Added function WIN_BuildWinArray() to make it easier to enumerate
	windows. Implemented Win32 version of EnumWindows() and friends.

Fri Jul  5 11:56:22 1996  Andreas Kirschbaum <ank@rbg.informatik.th-darmstadt.de>

	* [controls/button.c] [windows/win.c]
	Operator precedence fixes.

	* [controls/edit.c]
	Implemented ES_PASSWORD, ES_LOWERCASE and ES_UPPERCASE styles.
	Fixed word wrap with long words.

	* [debugger/debug.l]
	New alias "where" for command "backtrace".

	* [if1632/gdi.spec]
	Corrected parameter of ExtTextOut.

	* [loader/module.c]
	Corrected printing of table of modules.

	* [misc/spy.c]
	Removed superfluous \n in message name.

	* [windows/message.c]
	Declared MSG_SendMessage as static.
	Changed parameter of DirectedYield() from queue handle to task handle.
	Removed warning mesages for argument of printf.

	* [windows/nonclient.c]
	Added the flag DT_NOPREFIX when drawing window titles.

	* [windows/win.c]
	WIN_WalkWindows now prints the invalid window handle.
	Added a warning if Get-/SetWindowWord/-Long gets an invalid offset.

	* [windows/winproc.c]
	Allows creating dialog windows with NULL as dialog function.

Wed Jul  3 09:26:41 1996  Andrew Lewycky <plewycky@oise.utoronto.ca>

	* [windows/event.c]
	EVENT_key: Fixes to VK_ code generation for space bar and
	punctuation.

	* [files/file.c]
	GetTempFileName: first character in temporary name is "~".

	* [memory/heap.c]
	HEAP_MakeInUseBlockFree now frees the whole subheap if possible.

	* [objects/text.c]
	ExtTextOut16(): handle NULL lpRect and ETO_OPAQUE.

	* [misc/driver.c]
	Removed some bugs and reformatted. Actually loads drivers now.

	* [include/callback.h]
	Added CallDriverProc() and CallWindowsExitProc().

	* [loader/module.c]
	MODULE_CallWEP(): new function.

	* [misc/lzexpand.c]
	LZSeek(): return new pointer, not old one.

	* [misc/ver.c]
	find_ne_resource(): fixed dependence on LZSeek() bug.
	GetFileResource(): initialize reslen before using it.

	* [windows/class.c]
	SetClassWord(): add missing else.

	* [objects/font.c]
	lpFontList is now MAX_FONTS+1. It used to overwrite the array.
	InitFontList: allocate one huge array of structures.
	FONT_MatchFont: uppercase the face name.

Thu Jun 27 12:41:40 1996  Bruce Milner <bruce@genetics.utah.edu>

	* [memory/heap.c]
	Fixed a typo in HeapReAlloc().

Tue Jun 25 22:22:03 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [files/directory.c] [files/drive.c] [if1632/kernel.spec]
	  [if1632/kernel32.spec] [if1632/shell.spec] [include/windows.h]
	GetTempPath* added
	GetDriveType* fixed, updated to NewNameStandard.
	GetCurrentDirectory* fixed (needs to prepend X:\).

	* [controls/listbox.c]
	Missing NULL check added.

	* [if1632/winmm.spec] [loader/builtin.c]
	winmm.dll (32bit mmsystem equivalent) specs added.

	* [memory/string.c] [if1632/kernel32.spec] [include/windows.h]
	Rtl{Move,Zero,Fill}Memory added.

	* [misc/registry.c]
	Some NULL ptr dereference bugs fixed.

	* [multimedia/mcicda.c][multimedia/mcistring.c][multimedia/mmsystem.c]
	Check for NULL ptr.
	Fill mciOpenDrv when mixing mciOpen and mciSendString("open ..").
	Aliasing should work for all MCI devices.

	* [windows/win.c]
	Allow passing invalid window handles to CloseWindow().

Tue Jun 25 20:02:15 1996  Jukka Iivonen <iivonen@cc.helsinki.fi>

	* [files/directory.c] [if1632/kernel32.spec]
	GetSystemDirectory32A and GetSystemDirectory32W added.

	* [misc/main.c] [if1632/kernel32.spec]
	Beep and SetEnvironmentVariable32W added.
diff --git a/ANNOUNCE b/ANNOUNCE
index 76dac67..decf527 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,12 +1,12 @@
-This is release 960623 of Wine, the MS Windows emulator.  This is still a
+This is release 960705 of Wine, the MS Windows emulator.  This is still a
 developer's only release.  There are many bugs and many unimplemented API
 features.  Most applications still do not work correctly.
 
 Patches should be submitted to "julliard@lrc.epfl.ch".  Please don't
 forget to include a ChangeLog entry.
 
-WHAT'S NEW with Wine-960623: (see ChangeLog for details)
-	- More Win32 code.
+WHAT'S NEW with Wine-960705: (see ChangeLog for details)
+	- New window procedure thunks.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -15,10 +15,10 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-    sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960623.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960623.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960623.tar.gz
-    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960623.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960705.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960705.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960705.tar.gz
+    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960705.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index e94ed93..7b3b3bc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,150 @@
 ----------------------------------------------------------------------
+Fri Jul  5 16:27:43 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [controls/desktop.c]
+	Use Windows file I/O routines to load the desktop bitmap.
+
+	* [files/file.c]
+	Implemented RemoveDirectory* and DeleteFile*.
+
+	* [include/wine.h]
+	Added SIGCONTEXT typedef to replace #define sigcontext_struct.
+
+	* [loader/task.c]
+	Fixed initial breakpoint setting for Win32 tasks.
+
+	* [misc/wsprintf.c]
+	Ignore Unicode formats for wsprintf16().
+
+	* [objects/font.c]
+	Implemented Win32 version of GetTextMetrics.
+
+	* [windows/winproc.c] [windows/win.c] [windows/class.c]
+	  [windows/dialog.c]
+	Modified windows procedures to use thunks, to ensure that the
+	procedure can be called directly from the Windows program.
+
+	* [windows/win.c]
+	Added function WIN_BuildWinArray() to make it easier to enumerate
+	windows. Implemented Win32 version of EnumWindows() and friends.
+
+Fri Jul  5 11:56:22 1996  Andreas Kirschbaum <ank@rbg.informatik.th-darmstadt.de>
+
+	* [controls/button.c] [windows/win.c]
+	Operator precedence fixes.
+
+	* [controls/edit.c]
+	Implemented ES_PASSWORD, ES_LOWERCASE and ES_UPPERCASE styles.
+	Fixed word wrap with long words.
+
+	* [debugger/debug.l]
+	New alias "where" for command "backtrace".
+
+	* [if1632/gdi.spec]
+	Corrected parameter of ExtTextOut.
+
+	* [loader/module.c]
+	Corrected printing of table of modules.
+
+	* [misc/spy.c]
+	Removed superfluous \n in message name.
+
+	* [windows/message.c]
+	Declared MSG_SendMessage as static.
+	Changed parameter of DirectedYield() from queue handle to task handle.
+	Removed warning mesages for argument of printf.
+
+	* [windows/nonclient.c]
+	Added the flag DT_NOPREFIX when drawing window titles.
+
+	* [windows/win.c]
+	WIN_WalkWindows now prints the invalid window handle.
+	Added a warning if Get-/SetWindowWord/-Long gets an invalid offset.
+
+	* [windows/winproc.c]
+	Allows creating dialog windows with NULL as dialog function.
+
+Wed Jul  3 09:26:41 1996  Peter Lewycky <plewycky@oise.utoronto.ca>
+
+	* [windows/event.c]
+	EVENT_key: Fixes to VK_ code generation for space bar and
+	punctuation.
+
+	* [files/file.c]
+	GetTempFileName: first character in temporary name is "~".
+
+	* [memory/heap.c]
+	HEAP_MakeInUseBlockFree now frees the whole subheap if possible.
+
+	* [objects/text.c]
+	ExtTextOut16(): handle NULL lpRect and ETO_OPAQUE.
+
+	* [misc/driver.c]
+	Removed some bugs and reformatted. Actually loads drivers now.
+
+	* [include/callback.h]
+	Added CallDriverProc() and CallWindowsExitProc().
+
+	* [loader/module.c]
+	MODULE_CallWEP(): new function.
+
+	* [misc/lzexpand.c]
+	LZSeek(): return new pointer, not old one.
+
+	* [misc/ver.c]
+	find_ne_resource(): fixed dependence on LZSeek() bug.
+	GetFileResource(): initialize reslen before using it.
+
+	* [windows/class.c]
+	SetClassWord(): add missing else.
+
+	* [objects/font.c]
+	lpFontList is now MAX_FONTS+1. It used to overwrite the array.
+	InitFontList: allocate one huge array of structures.
+	FONT_MatchFont: uppercase the face name.
+
+Thu Jun 27 12:41:40 1996  Bruce Milner <bruce@genetics.utah.edu>
+
+	* [memory/heap.c]
+	Fixed a typo in HeapReAlloc().
+
+Tue Jun 25 22:22:03 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [files/directory.c] [files/drive.c] [if1632/kernel.spec]
+	  [if1632/kernel32.spec] [if1632/shell.spec] [include/windows.h]
+	GetTempPath* added
+	GetDriveType* fixed, updated to NewNameStandard.
+	GetCurrentDirectory* fixed (needs to prepend X:\).
+
+	* [controls/listbox.c]
+	Missing NULL check added.
+
+	* [if1632/winmm.spec] [loader/builtin.c]
+	winmm.dll (32bit mmsystem equivalent) specs added.
+
+	* [memory/string.c] [if1632/kernel32.spec] [include/windows.h]
+	Rtl{Move,Zero,Fill}Memory added.
+
+	* [misc/registry.c]
+	Some NULL ptr dereference bugs fixed.
+
+	* [multimedia/mcicda.c][multimedia/mcistring.c][multimedia/mmsystem.c]
+	Check for NULL ptr.
+	Fill mciOpenDrv when mixing mciOpen and mciSendString("open ..").
+	Aliasing should work for all MCI devices.
+
+	* [windows/win.c]
+	Allow passing invalid window handles to CloseWindow().
+
+Tue Jun 25 20:02:15 1996  Jukka Iivonen <iivonen@cc.helsinki.fi>
+
+	* [files/directory.c] [if1632/kernel32.spec]
+	GetSystemDirectory32A and GetSystemDirectory32W added.
+
+	* [misc/main.c] [if1632/kernel32.spec]
+	Beep and SetEnvironmentVariable32W added.
+
+----------------------------------------------------------------------
 Wed Jun 19 14:49:27 1996  Marcus Meissner <msmeissn@faui45.informatik.uni-erlangen.de>
 
 	* [files/drive.c] 
diff --git a/controls/button.c b/controls/button.c
index 3181a56..620f288 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -313,7 +313,7 @@
         {
             short xdelta, ydelta;
             dwTextSize = GetTextExtent(hDC,wndPtr->text,strlen(wndPtr->text));
-            GetTextMetrics( hDC, &tm );
+            GetTextMetrics16( hDC, &tm );
             xdelta = ((rc.right - rc.left) - LOWORD(dwTextSize) - 1) / 2;
             ydelta = ((rc.bottom - rc.top) - tm.tmHeight - 1) / 2;
             if (xdelta < 0) xdelta = 0;
@@ -382,7 +382,7 @@
     hBrush = BUTTON_SEND_CTLCOLOR( wndPtr, hDC );
     if (action == ODA_DRAWENTIRE) FillRect16( hDC, &rc, hBrush );
 
-    GetTextMetrics(hDC, &tm);
+    GetTextMetrics16(hDC, &tm);
     delta = (rc.bottom - rc.top - tm.tmHeight) >> 1;
 
       /* Draw the check-box bitmap */
@@ -512,9 +512,9 @@
     dis.CtlID      = wndPtr->wIDmenu;
     dis.itemID     = 0;
     dis.itemAction = action;
-    dis.itemState  = (infoPtr->state & BUTTON_HASFOCUS) ? ODS_FOCUS : 0 |
-                     (infoPtr->state & BUTTON_HIGHLIGHTED) ? ODS_SELECTED : 0 |
-                     (wndPtr->dwStyle & WS_DISABLED) ? ODS_DISABLED : 0;
+    dis.itemState  = ((infoPtr->state & BUTTON_HASFOCUS) ? ODS_FOCUS : 0) |
+                     ((infoPtr->state & BUTTON_HIGHLIGHTED) ? ODS_SELECTED : 0) |
+                     ((wndPtr->dwStyle & WS_DISABLED) ? ODS_DISABLED : 0);
     dis.hwndItem   = wndPtr->hwndSelf;
     dis.hDC        = hDC;
     dis.itemData   = 0;
diff --git a/controls/desktop.c b/controls/desktop.c
index a71a6f8..9b01ae7 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -4,16 +4,15 @@
  * Copyright 1994 Alexandre Julliard
  */
 
-#include <fcntl.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include "win.h"
 #include "desktop.h"
 #include "directory.h"
-#include "dos_fs.h"
+#include "file.h"
 #include "graphics.h"
+#include "heap.h"
 
 
 /***********************************************************************
@@ -26,47 +25,46 @@
     BITMAPFILEHEADER *fileHeader;
     BITMAPINFO *bitmapInfo;
     HBITMAP hbitmap;
-    char *buffer;
-    const char *unixFileName;
-    int file;
-    long size;
+    HFILE file;
+    LPSTR buffer;
+    LONG size;
 
-      /* Read all the file into memory */
+    /* Read all the file into memory */
 
-    if (!(unixFileName = DOSFS_GetUnixFileName( filename, TRUE )))
+    if ((file = _lopen( filename, OF_READ )) == HFILE_ERROR)
     {
-        int len = DIR_GetWindowsUnixDir( NULL, 0 );
-        if (!(buffer = malloc( len + strlen(filename) + 2 ))) return 0;
-        DIR_GetWindowsUnixDir( buffer, len + 1 );
-        strcat( buffer, "/" );
+        UINT32 len = GetWindowsDirectory( NULL, 0 );
+        if (!(buffer = HeapAlloc( SystemHeap, 0, len + strlen(filename) + 2 )))
+            return 0;
+        GetWindowsDirectory( buffer, len + 1 );
+        strcat( buffer, "\\" );
         strcat( buffer, filename );
-        unixFileName = DOSFS_GetUnixFileName( buffer, TRUE );
-        free( buffer );
-        if (!unixFileName) return 0;
+        file = _lopen( buffer, OF_READ );
+        HeapFree( SystemHeap, 0, buffer );
     }
-    if ((file = open( unixFileName, O_RDONLY )) == -1) return 0;
-    size = lseek( file, 0, SEEK_END );
-    if (!(buffer = (char *)malloc( size )))
+    if (file == HFILE_ERROR) return 0;
+    size = _llseek( file, 0, 2 );
+    if (!(buffer = HeapAlloc( SystemHeap, 0, size )))
     {
-	close( file );
+	_lclose( file );
 	return 0;
     }
-    lseek( file, 0, SEEK_SET );
-    size = read( file, buffer, size );
-    close( file );
+    _llseek( file, 0, 0 );
+    size = FILE_Read( file, buffer, size );
+    _lclose( file );
     fileHeader = (BITMAPFILEHEADER *)buffer;
     bitmapInfo = (BITMAPINFO *)(buffer + sizeof(BITMAPFILEHEADER));
     
       /* Check header content */
     if ((fileHeader->bfType != 0x4d42) || (size < fileHeader->bfSize))
     {
-	free( buffer );
+	HeapFree( SystemHeap, 0, buffer );
 	return 0;
     }
     hbitmap = CreateDIBitmap( hdc, &bitmapInfo->bmiHeader, CBM_INIT,
 			      buffer + fileHeader->bfOffBits,
 			      bitmapInfo, DIB_RGB_COLORS );
-    free( buffer );
+    HeapFree( SystemHeap, 0, buffer );
     return hbitmap;
 }
 
diff --git a/controls/edit.c b/controls/edit.c
index 7db7bd4..62be0ea 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -79,6 +79,9 @@
 #define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL)
 #define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY)
 #define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0)
+#define IsPassword(wndPtr) ((wndPtr)->dwStyle & ES_PASSWORD)
+#define IsLower(wndPtr) ((wndPtr)->dwStyle & ES_LOWERCASE)
+#define IsUpper(wndPtr) ((wndPtr)->dwStyle & ES_UPPERCASE)
 
 #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
 
@@ -127,6 +130,7 @@
 static UINT    EDIT_GetLineHeight(WND *wndPtr);
 static void    EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc);
 static char *  EDIT_GetPointer(WND *wndPtr);
+static char *  EDIT_GetPasswordPointer(WND *wndPtr);
 static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
 static BOOL    EDIT_GetRedraw(WND *wndPtr);
 static UINT    EDIT_GetTextWidth(WND *wndPtr);
@@ -504,14 +508,14 @@
  *	EDIT_BuildLineDefs
  *
  *	Build array of pointers to text lines.
- *	Lines can end with '\0' (last line), nothing (if it is to long),
+ *	Lines can end with '\0' (last line), nothing (if it is too long),
  *	a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
  *
  */
 static void EDIT_BuildLineDefs(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	char *text = EDIT_GetPointer(wndPtr);
+	char *text = EDIT_GetPasswordPointer(wndPtr);
 	int ww = EDIT_GetWndWidth(wndPtr);
 	HDC hdc;
 	HFONT hFont;
@@ -562,16 +566,23 @@
 					width = LOWORD(GetTabbedTextExtent(hdc, start, next,
 							es->NumTabStops, es->TabStops));
 				} while (width <= ww);
-				if (prev) {
-					length = prev;
-					if (EDIT_CallWordBreakProc(wndPtr, start, length - 1,
-									length, WB_ISDELIMITER)) {
-						length--;
-						ending = END_DELIMIT;
-					} else
-						ending = END_NONE;
-				} else {
+				if (!prev) {
+					next = 0;
+					do {
+						prev = next;
+						next++;
+						width = LOWORD(GetTabbedTextExtent(hdc, start, next,
+								es->NumTabStops, es->TabStops));
+					} while (width <= ww);
+					if(!prev) prev = 1;
 				}
+				length = prev;
+				if (EDIT_CallWordBreakProc(wndPtr, start, length - 1,
+								length, WB_ISDELIMITER)) {
+					length--;
+					ending = END_DELIMIT;
+				} else
+					ending = END_NONE;
 				width = LOWORD(GetTabbedTextExtent(hdc, start, length,
 							es->NumTabStops, es->TabStops));
 			}
@@ -602,6 +613,8 @@
 	if (hFont)
 		SelectObject(hdc, oldFont);
 	ReleaseDC(wndPtr->hwndSelf, hdc);
+
+	free(text);
 }
 
 
@@ -755,6 +768,30 @@
 
 /*********************************************************************
  *
+ *	EDIT_GetPasswordPointer
+ *
+ *
+ */
+static char *EDIT_GetPasswordPointer(WND *wndPtr)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	char *text = xstrdup(EDIT_GetPointer(wndPtr));
+	char *p;
+
+	if(es->PasswordChar) {
+		p = text;
+		while(*p != '\0') {
+			if(*p != '\r' && *p != '\n')
+				*p = es->PasswordChar;
+			p++;
+		}
+	}
+	return text;
+}
+
+
+/*********************************************************************
+ *
  *	EDIT_GetRect
  *
  *	Beware: This is not the function called on EM_GETRECT.
@@ -1272,11 +1309,12 @@
 		SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
 		SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
 	}
-	text = EDIT_GetPointer(wndPtr);
+	text = EDIT_GetPasswordPointer(wndPtr);
 	li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
 	xoff = EDIT_GetXOffset(wndPtr);
 	ret = LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
-					es->NumTabStops, es->TabStops, -xoff));	
+					es->NumTabStops, es->TabStops, -xoff));
+	free(text);
 	if (rev) {
 		SetBkColor(hdc, BkColor);
 		SetTextColor(hdc, TextColor);
@@ -1341,6 +1379,10 @@
 		p[strl] = p[0];
 	for (i = 0 , p = text + e ; i < strl ; i++)
 		p[i] = str[i];
+	if(IsUpper(wndPtr))
+		AnsiUpperBuff(p, strl);
+	else if(IsLower(wndPtr))
+		AnsiLowerBuff(p, strl);
 	EDIT_BuildLineDefs(wndPtr);
 	e += strl;
 	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(e, e));
@@ -1403,7 +1445,7 @@
 static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col)
 {	
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	char *text = EDIT_GetPointer(wndPtr);
+	char *text = EDIT_GetPasswordPointer(wndPtr);
 	INT ret;
 	HDC hdc;
 	HFONT hFont;
@@ -1425,6 +1467,7 @@
 	if (hFont)
 		SelectObject(hdc, oldFont);
 	ReleaseDC(wndPtr->hwndSelf, hdc);
+	free(text);
 	return ret;
 }
 
@@ -2753,7 +2796,7 @@
 	hdc = GetDC(wndPtr->hwndSelf);
 	if (es->hFont)
 		oldFont = SelectObject(hdc, es->hFont);
-	GetTextMetrics(hdc, &tm);
+	GetTextMetrics16(hdc, &tm);
 	es->LineHeight = HIWORD(GetTextExtent(hdc, "X", 1));
 	es->AveCharWidth = tm.tmAveCharWidth;
 	if (es->hFont)
diff --git a/controls/listbox.c b/controls/listbox.c
index b6f1f79..0a31780 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -107,7 +107,7 @@
   if ((hdc = GetDC(0)))
   {
       TEXTMETRIC16 tm;
-      GetTextMetrics( hdc, &tm );
+      GetTextMetrics16( hdc, &tm );
       lphl->StdItemHeight = tm.tmHeight;
       dprintf_listbox(stddeb,"CreateListBoxStruct:  font height %d\n",
                       lphl->StdItemHeight);
@@ -1273,7 +1273,7 @@
   if ((hdc = GetDC(0)))
   {
       TEXTMETRIC16 tm;
-      GetTextMetrics( hdc, &tm );
+      GetTextMetrics16( hdc, &tm );
       lphl->StdItemHeight = tm.tmHeight;
       dprintf_listbox(stddeb,"LBSetFont:  new font %d with height %d\n",
                       lphl->hFont, lphl->StdItemHeight);
@@ -2094,7 +2094,7 @@
     {
         char mask[20];
         
-        if (!filespec[0]) strcpy( mask, "*.*" );
+        if (!filespec || !filespec[0]) strcpy( mask, "*.*" );
         else
         {
             /* If the path exists and is a directory, chdir to it */
diff --git a/controls/menu.c b/controls/menu.c
index bf6a69d..a99da2a 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -732,7 +732,7 @@
 /***********************************************************************
  *	     MENU_SwitchTPWndTo
  */
-BOOL MENU_SwitchTPWndTo( HTASK hTask)
+static BOOL MENU_SwitchTPWndTo( HTASK hTask)
 {
   /* This is supposed to be called when popup is hidden */
 
diff --git a/debugger/break.c b/debugger/break.c
index 1726c16..be92e1f 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -71,7 +71,7 @@
  * Determine if the instruction at CS:EIP is an instruction that
  * we need to step over (like a call or a repetitive string move).
  */
-static BOOL DEBUG_IsStepOverInstr( struct sigcontext_struct *context )
+static BOOL DEBUG_IsStepOverInstr( SIGCONTEXT *context )
 {
     BYTE *instr = (BYTE *)PTR_SEG_OFF_TO_LIN(CS_reg(context),EIP_reg(context));
 
@@ -135,7 +135,7 @@
  *
  * Set or remove all the breakpoints.
  */
-void DEBUG_SetBreakpoints( BOOL set )
+void DEBUG_SetBreakpoints( BOOL32 set )
 {
     int i;
 
@@ -236,7 +236,7 @@
  *
  * Enable or disable a break point.
  */
-void DEBUG_EnableBreakpoint( int num, BOOL enable )
+void DEBUG_EnableBreakpoint( int num, BOOL32 enable )
 {
     if ((num <= 0) || (num >= next_bp) || !breakpoints[num].in_use)
     {
@@ -275,8 +275,7 @@
  * Determine if we should continue execution after a SIGTRAP signal when
  * executing in the given mode.
  */
-BOOL DEBUG_ShouldContinue( struct sigcontext_struct *context,
-                           enum exec_mode mode )
+BOOL32 DEBUG_ShouldContinue( SIGCONTEXT *context, enum exec_mode mode )
 {
     DBG_ADDR addr;
     int bpnum;
@@ -316,8 +315,8 @@
  * Set the breakpoints to the correct state to restart execution
  * in the given mode.
  */
-void DEBUG_RestartExecution( struct sigcontext_struct *context,
-                             enum exec_mode mode, int instr_len )
+void DEBUG_RestartExecution( SIGCONTEXT *context, enum exec_mode mode,
+                             int instr_len )
 {
     DBG_ADDR addr;
 
diff --git a/debugger/dbg.y b/debugger/dbg.y
index e6064ca..45e806b 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -229,7 +229,7 @@
 }
 
 
-void wine_debug( int signal, struct sigcontext_struct *regs )
+void wine_debug( int signal, SIGCONTEXT *regs )
 {
     static int loaded_symbols = 0;
     char SymbolTableFile[256];
@@ -239,7 +239,7 @@
 #endif
 
     yyin = stdin;
-    DEBUG_context = (struct sigcontext_struct *)regs;
+    DEBUG_context = regs;
 
     DEBUG_SetBreakpoints( FALSE );
 
diff --git a/debugger/debug.l b/debugger/debug.l
index 0806e05..709c23a 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -103,7 +103,8 @@
 
 help|hel|he|"?"			{ return tHELP; }
 
-backtrace|bt			{ return tBACKTRACE; }
+backtrace|backtrac|backtra|backt|back|bac|ba|bt { return tBACKTRACE; }
+where|wher|whe                  { return tBACKTRACE; }
 
 cont|con|co|c   		{ return tCONT; }
 step|ste|st|s   		{ return tSTEP; }
diff --git a/debugger/hash.c b/debugger/hash.c
index 56af9e5..39dbdab 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -66,7 +66,7 @@
  *
  * Get the address of a named symbol.
  */
-BOOL DEBUG_GetSymbolValue( const char * name, DBG_ADDR *addr )
+BOOL32 DEBUG_GetSymbolValue( const char * name, DBG_ADDR *addr )
 {
     char buffer[256];
     struct name_hash *nh;
@@ -93,7 +93,7 @@
  *
  * Set the address of a named symbol.
  */
-BOOL DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr )
+BOOL32 DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr )
 {
     char buffer[256];
     struct name_hash *nh;
diff --git a/debugger/memory.c b/debugger/memory.c
index 49108c2..cfe16a2 100644
--- a/debugger/memory.c
+++ b/debugger/memory.c
@@ -15,7 +15,7 @@
  *
  * Check if we are allowed to read memory at 'address'.
  */
-BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
+BOOL32 DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
 {
     if (address->seg)  /* segmented addr */
         return IsBadReadPtr( (SEGPTR)MAKELONG( (WORD)address->off,
@@ -31,7 +31,7 @@
  *
  * Check if we are allowed to write memory at 'address'.
  */
-BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
+BOOL32 DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
 {
     if (address->seg)  /* segmented addr */
         /* Note: we use IsBadReadPtr here because we are */
diff --git a/debugger/registers.c b/debugger/registers.c
index a8b66a5..57aaf96 100644
--- a/debugger/registers.c
+++ b/debugger/registers.c
@@ -8,7 +8,7 @@
 #include "debugger.h"
 
 
-struct sigcontext_struct *DEBUG_context;
+SIGCONTEXT *DEBUG_context;
 
 
 
diff --git a/files/directory.c b/files/directory.c
index 432b8c4..285468e 100644
--- a/files/directory.c
+++ b/files/directory.c
@@ -15,8 +15,10 @@
 #include "msdos.h"
 #include "options.h"
 #include "xmalloc.h"
+#include "string32.h"
 #include "stddebug.h"
 #include "debug.h"
+#include "string32.h"
 
 #define MAX_PATH_ELEMENTS 20
 
@@ -178,9 +180,9 @@
 
 
 /***********************************************************************
- *           DIR_GetTempDosDir
+ *           GetTempPath32A   (KERNEL32.292)
  */
-UINT DIR_GetTempDosDir( LPSTR path, UINT count )
+UINT32 GetTempPath32A( UINT32 count, LPSTR path )
 {
     if (path) lstrcpyn32A( path, DIR_TempDosDir, count );
     return strlen( DIR_TempDosDir );
@@ -188,6 +190,19 @@
 
 
 /***********************************************************************
+ *           GetTempPath32W   (KERNEL32.293)
+ */
+UINT32 GetTempPath32W( UINT32 count, LPWSTR path )
+{
+    LPSTR tmp = (char*)xmalloc(count);
+    UINT32 len = GetTempPath32A( count, tmp );
+    if (path) STRING32_AnsiToUni( path, tmp );
+    free(tmp);
+    return len;
+}
+
+
+/***********************************************************************
  *           DIR_GetTempUnixDir
  */
 UINT DIR_GetTempUnixDir( LPSTR path, UINT count )
@@ -248,10 +263,34 @@
 
 
 /***********************************************************************
- *           GetSystemDirectory   (KERNEL.135)
+ *           GetSystemDirectory16   (KERNEL.135)
  */
-UINT GetSystemDirectory( LPSTR path, UINT count )
+UINT16 GetSystemDirectory16( LPSTR path, UINT16 count )
+{
+    return (UINT16)GetSystemDirectory32A( path, count );
+}
+
+
+/***********************************************************************
+ *           GetSystemDirectory32A   (KERNEL32.282)
+ */
+UINT32 GetSystemDirectory32A( LPSTR path, UINT32 count )
 {
     if (path) lstrcpyn32A( path, DIR_SystemDosDir, count );
     return strlen( DIR_SystemDosDir );
 }
+
+
+/***********************************************************************
+ *           GetSystemDirectory32W   (KERNEL32.283)
+ */
+UINT32 GetSystemDirectory32W( LPWSTR path, UINT32 count )
+{
+    if (path)
+    {
+        LPWSTR tmp = STRING32_DupAnsiToUni( DIR_SystemDosDir );
+        lstrcpyn32W( path, tmp, count );
+	free (tmp);
+    }
+    return strlen( DIR_SystemDosDir );
+}
diff --git a/files/drive.c b/files/drive.c
index f886bda..b57267b 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -525,9 +525,9 @@
 
 
 /***********************************************************************
- *           GetDriveType   (KERNEL.136)
+ *           GetDriveType16   (KERNEL.136)
  */
-WORD GetDriveType( INT drive )
+UINT16 GetDriveType16( UINT16 drive )
 {
     dprintf_dosfs( stddeb, "GetDriveType(%c:)\n", 'A' + drive );
     switch(DRIVE_GetType(drive))
@@ -543,9 +543,9 @@
 
 
 /***********************************************************************
- *           GetDriveType32A   (KERNEL32.)
+ *           GetDriveType32A   (KERNEL32.208)
  */
-WORD GetDriveType32A( LPCSTR root )
+UINT32 GetDriveType32A( LPCSTR root )
 {
     dprintf_dosfs( stddeb, "GetDriveType32A(%s)\n", root );
     if ((root[1] != ':') || (root[2] != '\\'))
@@ -566,18 +566,61 @@
 
 
 /***********************************************************************
- *           GetCurrentDirectory   (KERNEL.411) (KERNEL32.196)
+ *           GetDriveType32W   (KERNEL32.209)
  */
-UINT32 GetCurrentDirectory( UINT32 buflen, LPSTR buf )
+UINT32 GetDriveType32W( LPCWSTR root )
 {
+    LPSTR xpath=STRING32_DupUniToAnsi(root);
+    UINT32 ret;
+
+    ret = GetDriveType32A(xpath);
+    free(xpath);
+    return ret;
+}
+
+
+/***********************************************************************
+ *           GetCurrentDirectory16   (KERNEL.411)
+ */
+UINT16 GetCurrentDirectory16( UINT16 buflen, LPSTR buf )
+{
+    return (UINT16)GetCurrentDirectory32A( buflen, buf );
+}
+
+
+/***********************************************************************
+ *           GetCurrentDirectory32A   (KERNEL32.196)
+ *
+ * Returns "X:\\path\\etc\\".
+ */
+UINT32 GetCurrentDirectory32A( UINT32 buflen, LPSTR buf )
+{
+    char *pref = "A:\\";
     const char *s = DRIVE_GetDosCwd( DRIVE_GetCurrentDrive() );
     if (!s)
     {
         *buf = '\0';
         return 0;
     }
-    lstrcpyn32A( buf, s, buflen );
-    return strlen(s); /* yes */
+    lstrcpyn32A( buf, pref, 3 );
+    if (buflen) buf[0] += DRIVE_GetCurrentDrive();
+    if (buflen >= 3) lstrcpyn32A( buf + 3, s, buflen - 3 );
+    return strlen(s) + 3; /* length of WHOLE current directory */
+}
+
+
+/***********************************************************************
+ *           GetCurrentDirectory32W   (KERNEL32.197)
+ */
+UINT32 GetCurrentDirectory32W( UINT32 buflen, LPWSTR buf )
+{
+    LPSTR xpath=(char*)xmalloc(buflen+1);
+    UINT32 ret;
+
+    ret = GetCurrentDirectory32A(buflen,xpath);
+    STRING32_AnsiToUni(buf,xpath);
+    free(xpath);
+    return ret;
 }
 
 
diff --git a/files/file.c b/files/file.c
index 390b6de..e324d3f 100644
--- a/files/file.c
+++ b/files/file.c
@@ -385,32 +385,6 @@
 
 
 /***********************************************************************
- *           FILE_Unlink
- */
-int FILE_Unlink( LPCSTR path )
-{
-    const char *unixName;
-
-    dprintf_file(stddeb, "FILE_Unlink: '%s'\n", path );
-
-    if ((unixName = DOSFS_IsDevice( path )) != NULL)
-    {
-        dprintf_file(stddeb, "FILE_Unlink: removing device '%s'!\n", unixName);
-        DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
-        return 0;
-    }
-
-    if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return 0;
-    if (unlink( unixName ) == -1)
-    {
-        FILE_SetDosError();
-        return 0;
-    }
-    return 1;
-}
-
-
-/***********************************************************************
  *           FILE_Stat
  *
  * Stat a Unix path name. Return 1 if OK.
@@ -485,31 +459,6 @@
 
 
 /***********************************************************************
- *           FILE_RemoveDir
- */
-int FILE_RemoveDir( LPCSTR path )
-{
-    const char *unixName;
-
-    dprintf_file(stddeb, "FILE_RemoveDir: '%s'\n", path );
-
-    if ((unixName = DOSFS_IsDevice( path )) != NULL)
-    {
-        dprintf_file(stddeb, "FILE_RemoveDir: device '%s'!\n", unixName);
-        DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
-        return 0;
-    }
-    if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return 0;
-    if (rmdir( unixName ) == -1)
-    {
-        FILE_SetDosError();
-        return 0;
-    }
-    return 1;
-}
-
-
-/***********************************************************************
  *           FILE_Dup
  *
  * dup() function for DOS handles.
@@ -599,11 +548,12 @@
     }
     else
     {
-        DIR_GetTempDosDir( buffer, 132 );  /* buffer must be at least 144 */
+        GetTempPath32A( 132, buffer );  /* buffer must be at least 144 */
         strcat( buffer, "\\" );
     }
 
     p = buffer + strlen(buffer);
+    *p++ = '~';
     for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
     sprintf( p, "%04x.tmp", num );
 
@@ -668,7 +618,7 @@
     {
         if (!(dosName = DOSFS_GetDosTrueName( name, FALSE ))) goto error;
         lstrcpyn32A( ofs->szPathName, dosName, sizeof(ofs->szPathName) );
-        ofs->fFixedDisk = (GetDriveType( dosName[0]-'A' ) != DRIVE_REMOVABLE);
+        ofs->fFixedDisk = (GetDriveType16( dosName[0]-'A' ) != DRIVE_REMOVABLE);
         dprintf_file( stddeb, "OpenFile(%s): OF_PARSE, res = '%s', %d\n",
                       name, ofs->szPathName, hFileRet );
         /* Return the handle, but close it first */
@@ -723,7 +673,7 @@
 
     /* Try the Windows system directory */
 
-    GetSystemDirectory( ofs->szPathName, len );
+    GetSystemDirectory32A( ofs->szPathName, len );
     strcat( ofs->szPathName, "\\" );
     strcat( ofs->szPathName, name );
     if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )) != NULL)
@@ -1080,6 +1030,53 @@
 
 
 /***********************************************************************
+ *           DeleteFile16   (KERNEL.146)
+ */
+BOOL16 DeleteFile16( LPCSTR path )
+{
+    return DeleteFile32A( path );
+}
+
+
+/***********************************************************************
+ *           DeleteFile32A   (KERNEL32.71)
+ */
+BOOL32 DeleteFile32A( LPCSTR path )
+{
+    const char *unixName;
+
+    dprintf_file(stddeb, "DeleteFile: '%s'\n", path );
+
+    if ((unixName = DOSFS_IsDevice( path )) != NULL)
+    {
+        dprintf_file(stddeb, "DeleteFile: removing device '%s'!\n", unixName);
+        DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+        return FALSE;
+    }
+
+    if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return FALSE;
+    if (unlink( unixName ) == -1)
+    {
+        FILE_SetDosError();
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           DeleteFile32W   (KERNEL32.72)
+ */
+BOOL32 DeleteFile32W( LPCWSTR path )
+{
+    LPSTR xpath = STRING32_DupUniToAnsi(path);
+    BOOL32 ret = RemoveDirectory32A( xpath );
+    free(xpath);
+    return ret;
+}
+
+
+/***********************************************************************
  *           CreateDirectory16   (KERNEL.144)
  */
 BOOL16 CreateDirectory16( LPCSTR path, LPVOID dummy )
@@ -1123,3 +1120,49 @@
     free(xpath);
     return ret;
 }
+
+
+/***********************************************************************
+ *           RemoveDirectory16   (KERNEL)
+ */
+BOOL16 RemoveDirectory16( LPCSTR path )
+{
+    return (BOOL16)RemoveDirectory32A( path );
+}
+
+
+/***********************************************************************
+ *           RemoveDirectory32A   (KERNEL32.437)
+ */
+BOOL32 RemoveDirectory32A( LPCSTR path )
+{
+    const char *unixName;
+
+    dprintf_file(stddeb, "RemoveDirectory: '%s'\n", path );
+
+    if ((unixName = DOSFS_IsDevice( path )) != NULL)
+    {
+        dprintf_file(stddeb, "RemoveDirectory: device '%s'!\n", unixName);
+        DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
+        return FALSE;
+    }
+    if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return FALSE;
+    if (rmdir( unixName ) == -1)
+    {
+        FILE_SetDosError();
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           RemoveDirectory32W   (KERNEL32.438)
+ */
+BOOL32 RemoveDirectory32W( LPCWSTR path )
+{
+    LPSTR xpath = STRING32_DupUniToAnsi(path);
+    BOOL32 ret = RemoveDirectory32A( xpath );
+    free(xpath);
+    return ret;
+}
diff --git a/if1632/Makefile.in b/if1632/Makefile.in
index c4bd7cc..d54fde2 100644
--- a/if1632/Makefile.in
+++ b/if1632/Makefile.in
@@ -41,6 +41,7 @@
 	version.spec \
 	w32sys.spec \
 	win87em.spec \
+	winmm.spec \
 	winsock.spec \
 	winspool.spec \
 	wprocs.spec \
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 635e163..1dfb7a6 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -100,7 +100,7 @@
 90  pascal GetTextColor(word) GetTextColor
 91  pascal GetTextExtent(word ptr s_word) GetTextExtent
 92  pascal16 GetTextFace(word s_word ptr) GetTextFace
-93  pascal16 GetTextMetrics(word ptr) GetTextMetrics
+93  pascal16 GetTextMetrics(word ptr) GetTextMetrics16
 94  pascal GetViewportExt(word) GetViewportExt
 95  pascal GetViewportOrg(word) GetViewportOrg
 96  pascal GetWindowExt(word) GetWindowExt
@@ -235,7 +235,7 @@
                    s_word s_word) Chord
 349 pascal SetMapperFlags(word long) SetMapperFlags
 350 pascal16 GetCharWidth(word word word ptr) GetCharWidth
-351 pascal16 ExtTextOut(word s_word s_word word ptr ptr s_word ptr) ExtTextOut16
+351 pascal16 ExtTextOut(word s_word s_word word ptr ptr word ptr) ExtTextOut16
 352 stub GetPhysicalFontHandle
 353 stub GetAspectRatioFilter
 354 stub ShrinkGDIHeap
diff --git a/if1632/gdi32.spec b/if1632/gdi32.spec
index e7dc132..5305d54 100644
--- a/if1632/gdi32.spec
+++ b/if1632/gdi32.spec
@@ -238,8 +238,8 @@
 0233 stdcall GetTextExtentPointW(long ptr long ptr) GetTextExtentPoint32W
 0234 stub GetTextFaceA
 0235 stub GetTextFaceW
-0236 stub GetTextMetricsA
-0237 stub GetTextMetricsW
+0236 stdcall GetTextMetricsA(long ptr) GetTextMetrics32A
+0237 stdcall GetTextMetricsW(long ptr) GetTextMetrics32W
 0238 stub GetTransform
 0239 stub GetViewportExtEx
 0240 stub GetViewportOrgEx
@@ -314,8 +314,9 @@
 0309 stub SetColorAdjustment
 0310 stub SetColorSpace
 0311 stub SetDIBColorTable
-0312 stub SetDIBits
-0313 stub SetDIBitsToDevice
+0312 stdcall SetDIBits(long long long long ptr ptr long) SetDIBits
+0313 stdcall SetDIBitsToDevice(long long long long long long long long long
+                               ptr ptr long) SetDIBitsToDevice
 0314 stub SetDeviceGammaRamp
 0315 stub SetEnhMetaFileBits
 0316 stub SetFontEnumeration
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 9ff222e..11723e1 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -23,8 +23,8 @@
 20  pascal GlobalSize(word) GlobalSize16
 21  pascal GlobalHandle(word) GlobalHandle16
 22  pascal16 GlobalFlags(word) GlobalFlags16
-23  pascal16 LockSegment(word) LockSegment
-24  pascal16 UnlockSegment(word) UnlockSegment
+23  pascal16 LockSegment(word) LockSegment16
+24  pascal16 UnlockSegment(word) UnlockSegment16
 25  pascal GlobalCompact(long) GlobalCompact16
 26  pascal16 GlobalFreeAll(word) GlobalFreeAll
 27  stub GetModuleName
@@ -42,13 +42,13 @@
 41  return EnableDos 0 0
 42  return DisableDos 0 0
 45  pascal16 LoadModule(ptr ptr) LoadModule
-46  pascal16 FreeModule(word) FreeModule
+46  pascal16 FreeModule(word) FreeModule16
 47  pascal16 GetModuleHandle(segptr) WIN16_GetModuleHandle
 48  pascal16 GetModuleUsage(word) GetModuleUsage
 49  pascal16 GetModuleFileName(word ptr s_word) GetModuleFileName
 50  pascal GetProcAddress(word segptr) GetProcAddress
-51  pascal MakeProcInstance(segptr word) MakeProcInstance
-52  pascal16 FreeProcInstance(segptr) FreeProcInstance
+51  pascal MakeProcInstance(segptr word) MakeProcInstance16
+52  pascal16 FreeProcInstance(segptr) FreeProcInstance16
 53  stub CallProcInstance
 54  pascal16 GetInstanceData(word word word) GetInstanceData
 55  pascal16 Catch(ptr) Catch 
@@ -133,8 +133,8 @@
 132 pascal GetWinFlags() GetWinFlags
 133 pascal16 GetExePtr(word) GetExePtr
 134 pascal16 GetWindowsDirectory(ptr word) GetWindowsDirectory
-135 pascal16 GetSystemDirectory(ptr word) GetSystemDirectory
-136 pascal16 GetDriveType(byte) GetDriveType
+135 pascal16 GetSystemDirectory(ptr word) GetSystemDirectory16
+136 pascal16 GetDriveType(byte) GetDriveType16
 137 pascal FatalAppExit(word ptr) FatalAppExit
 138 pascal GetHeapSpaces(word) GetHeapSpaces
 139 stub DoSignal
@@ -143,8 +143,8 @@
 142 stub GetProfileSectionNames
 143 stub GetPrivateProfileSectionNames
 144 pascal16 CreateDirectory(ptr ptr) CreateDirectory16
-145 stub RemoveDirectory
-146 stub DeleteFile
+145 pascal16 RemoveDirectory(ptr) RemoveDirectory16
+146 pascal16 DeleteFile(ptr) DeleteFile16
 147 stub SetLastError
 148 stub GetLastError
 149 stub GetVersionEx
@@ -270,7 +270,7 @@
 404 pascal16 FarGetOwner(word) FarGetOwner
 406 stub WritePrivateProfileStruct
 407 stub GetPrivateProfileStruct
-411 pascal   GetCurrentDirectory(long ptr) GetCurrentDirectory
+411 pascal   GetCurrentDirectory(long ptr) GetCurrentDirectory16
 412 pascal16 SetCurrentDirectory(ptr) SetCurrentDirectory
 413 stub FindFirstFile
 414 stub FindNextFile
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index 5a3b4b2..7a60849 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -13,7 +13,7 @@
 0008 stub BackupWrite
 0009 stub BaseAttachCompleteThunk
 0010 stub BasepDebugDump
-0011 stub Beep
+0011 stdcall Beep(long long) Beep
 0012 stub BeginUpdateResourceA
 0013 stub BeginUpdateResourceW
 0014 stub BuildCommDCBA
@@ -73,8 +73,8 @@
 0068 stub DefineDosDeviceW
 0069 stub DeleteAtom
 0070 stdcall DeleteCriticalSection(ptr)	DeleteCriticalSection
-0071 stub DeleteFileA
-0072 stub DeleteFileW
+0071 stdcall DeleteFileA(ptr) DeleteFile32A
+0072 stdcall DeleteFileW(ptr) DeleteFile32W
 0073 stub DeviceIoControl
 0074 stub DisableThreadLibraryCalls
 0075 stub DisconnectNamedPipe
@@ -198,9 +198,9 @@
 0193 stub GetCurrencyFormatA
 0194 stub GetCurrencyFormatW
 0195 stub GetCurrentConsoleFont
-0196 	stdcall GetCurrentDirectoryA(ptr ptr) GetCurrentDirectory
-0197 stub GetCurrentDirectoryW
-0198 	stdcall GetCurrentProcess() GetCurrentProcess
+0196 stdcall GetCurrentDirectoryA(long ptr) GetCurrentDirectory32A
+0197 stdcall GetCurrentDirectoryW(long ptr) GetCurrentDirectory32W
+0198 stdcall GetCurrentProcess() GetCurrentProcess
 0199 stdcall GetCurrentProcessId() GetCurrentThreadId
 0200 	stdcall GetCurrentThread() GetCurrentThread
 0201	stdcall GetCurrentThreadId()	GetCurrentThreadId
@@ -211,7 +211,7 @@
 0206 	stdcall GetDiskFreeSpaceA(ptr ptr ptr ptr ptr) GetDiskFreeSpace32A
 0207 	stdcall GetDiskFreeSpaceW(ptr ptr ptr ptr ptr) GetDiskFreeSpace32W
 0208 stdcall GetDriveTypeA(ptr) GetDriveType32A
-0209 stub GetDriveTypeW
+0209 stdcall GetDriveTypeW(ptr) GetDriveType32W
 0210	stdcall GetEnvironmentStrings()	GetEnvironmentStrings
 0211 stub GetEnvironmentStringsA
 0212 	stdcall GetEnvironmentStringsW()		GetEnvironmentStringsW
@@ -284,8 +284,8 @@
 0279 stub GetStringTypeW
 0280 stdcall GetSystemDefaultLCID() GetSystemDefaultLCID
 0281 stub GetSystemDefaultLangID
-0282 stub GetSystemDirectoryA
-0283 stub GetSystemDirectoryW
+0282 stdcall GetSystemDirectoryA(ptr long) GetSystemDirectory32A
+0283 stdcall GetSystemDirectoryW(ptr long) GetSystemDirectory32W
 0284 stub GetSystemInfo
 0285 	stdcall GetSystemTime(ptr) GetSystemTime
 0286 stub GetSystemTimeAdjustment
@@ -294,8 +294,8 @@
 0289 stub GetTapeStatus
 0290 stub GetTempFileNameA
 0291 stub GetTempFileNameW
-0292 stub GetTempPathA
-0293 stub GetTempPathW
+0292 stdcall GetTempPathA(long ptr) GetTempPath32A
+0293 stdcall GetTempPathW(long ptr) GetTempPath32W
 0294	stdcall GetThreadContext(long ptr)	GetThreadContext
 0295 stub GetThreadLocale
 0296 stub GetThreadPriority
@@ -439,14 +439,14 @@
 0434 stub RegisterWowExec
 0435 	stdcall ReleaseMutex(long) ReleaseMutex
 0436 stub ReleaseSemaphore
-0437 stub RemoveDirectoryA
-0438 stub RemoveDirectoryW
+0437 stdcall RemoveDirectoryA(ptr) RemoveDirectory32A
+0438 stdcall RemoveDirectoryW(ptr) RemoveDirectory32W
 0439 	stdcall ResetEvent(long) ResetEvent
 0440 stub ResumeThread
-0441 stub RtlFillMemory
-0442 stub RtlMoveMemory
-0443    stdcall RtlUnwind(ptr long ptr long) RtlUnwind
-0444 stub RtlZeroMemory
+0441 stdcall RtlFillMemory(ptr long long) RtlFillMemory
+0442 stdcall RtlMoveMemory(ptr ptr long) RtlMoveMemory
+0443 stdcall RtlUnwind(ptr long ptr long) RtlUnwind
+0444 stdcall RtlZeroMemory(ptr long) RtlZeroMemory
 0445 stub ScrollConsoleScreenBufferA
 0446 stub ScrollConsoleScreenBufferW
 0447 stub SearchPathA
@@ -486,8 +486,8 @@
 0481 stub SetDefaultCommConfigA
 0482 stub SetDefaultCommConfigW
 0483 stub SetEndOfFile
-0484    stdcall SetEnvironmentVariableA(ptr ptr) SetEnvironmentVariableA
-0485 stub SetEnvironmentVariableW
+0484 stdcall SetEnvironmentVariableA(ptr ptr) SetEnvironmentVariable32A
+0485 stdcall SetEnvironmentVariableW(ptr ptr) SetEnvironmentVariable32W
 0486 stdcall SetErrorMode(long) SetErrorMode
 0487 	stdcall	SetEvent(long) SetEvent
 0488 stub SetFileApisToANSI
diff --git a/if1632/ntdll.spec b/if1632/ntdll.spec
index ea49e96..5835922 100644
--- a/if1632/ntdll.spec
+++ b/if1632/ntdll.spec
@@ -362,7 +362,7 @@
 358 stub RtlExtendedIntegerMultiply
 359 stub RtlExtendedLargeIntegerDivide
 360 stub RtlExtendedMagicDivide
-361 stub RtlFillMemory
+361 stdcall RtlFillMemory(ptr long long) RtlFillMemory
 362 stub RtlFillMemoryUlong
 363 stub RtlFindClearBits
 364 stub RtlFindClearBitsAndSet
@@ -436,7 +436,7 @@
 432 stub RtlLookupElementGenericTable
 433 stub RtlMakeSelfRelativeSD
 434 stub RtlMapGenericMask
-435 stub RtlMoveMemory
+435 stdcall RtlMoveMemory(ptr ptr long) RtlMoveMemory
 436 stub RtlMultiByteToUnicodeN
 437 stub RtlMultiByteToUnicodeSize
 438 stub RtlNewInstanceSecurityObject
@@ -539,7 +539,7 @@
 535 stub RtlWalkHeap
 536 stub RtlWriteRegistryValue
 537 stub RtlZeroHeap
-538 stub RtlZeroMemory
+538 stdcall RtlZeroMemory(ptr long) RtlZeroMemory
 539 stub RtlpInitializeRtl
 540 stub RtlpNtCreateKey
 541 stub RtlpNtEnumerateSubKey
diff --git a/if1632/relay.c b/if1632/relay.c
index f14fd3b..6d4c75e 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -9,6 +9,7 @@
 #include "module.h"
 #include "registers.h"
 #include "stackframe.h"
+#include "task.h"
 #include "stddebug.h"
 /* #define DEBUG_RELAY */
 #include "debug.h"
@@ -122,7 +123,7 @@
 
     if (func_type == 2)  /* register function */
     {
-        struct sigcontext_struct *context = (struct sigcontext_struct *)&args32;
+        SIGCONTEXT *context = (SIGCONTEXT *)&args32;
         printf( "     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
                 AX_reg(context), BX_reg(context), CX_reg(context),
                 DX_reg(context), SI_reg(context), DI_reg(context),
@@ -170,7 +171,7 @@
         printf( "retval=none ret=%04x:%04x ds=%04x\n",
                 frame->cs, frame->ip, frame->ds );
         {
-            struct sigcontext_struct *context = (struct sigcontext_struct *)&args32;
+            SIGCONTEXT *context = (SIGCONTEXT *)&args32;
             printf( "     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
                     AX_reg(context), BX_reg(context), CX_reg(context),
                     DX_reg(context), SI_reg(context), DI_reg(context),
@@ -195,11 +196,11 @@
     NE_MODULE *pModule  = BUILTIN_GetEntryPoint( frame->entry_cs,
                                                  frame->entry_ip,
                                                  &ordinal, &name );
-    fprintf( stderr, "No handler for routine %.*s.%d (%.*s)\n",
+    fprintf( stderr, "No handler for Win16 routine %.*s.%d (%.*s) called from %04x:%04x\n",
              *((BYTE *)pModule + pModule->name_table),
              (char *)pModule + pModule->name_table + 1,
-             ordinal, *name, name + 1 );
-    exit(1);
+             ordinal, *name, name + 1, frame->cs, frame->ip );
+    TASK_KillCurrentTask(1);
 }
 
 
@@ -211,10 +212,11 @@
  * (The args are the same than for RELAY_DebugCallFrom32).
  */
 void RELAY_Unimplemented32( int nb_args, void *entry_point,
-                            const char *func_name )
+                            const char *func_name, int ebp, int ret_addr )
 {
-    fprintf( stderr, "No handler for Win32 routine %s\n", func_name );
-    exit(1);
+    fprintf( stderr, "No handler for Win32 routine %s called from %08x\n",
+             func_name, ret_addr );
+    TASK_KillCurrentTask(1);
 }
 
 
diff --git a/if1632/shell.spec b/if1632/shell.spec
index a6d722d..8b53f1e 100644
--- a/if1632/shell.spec
+++ b/if1632/shell.spec
@@ -35,7 +35,7 @@
 #  157 RESTARTDIALOG
 #  166 PICKICONDLG
 
-262 pascal16 DriveType(long) GetDriveType
+262 pascal16 DriveType(long) GetDriveType16
 
 #  263 SH16TO32DRIVEIOCTL
 #  264 SH16TO32INT2526
diff --git a/if1632/user.spec b/if1632/user.spec
index 9afd4b4..c0828b8 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -54,8 +54,8 @@
 #51 BEAR51
 52  pascal16 AnyPopup() AnyPopup
 53  pascal16 DestroyWindow(word) DestroyWindow
-54  pascal16 EnumWindows(segptr long) EnumWindows
-55  pascal16 EnumChildWindows(word segptr long) EnumChildWindows
+54  pascal16 EnumWindows(segptr long) EnumWindows16
+55  pascal16 EnumChildWindows(word segptr long) EnumChildWindows16
 56  pascal16 MoveWindow(word word word word word word) MoveWindow
 57  pascal16 RegisterClass(ptr) RegisterClass16
 58  pascal16 GetClassName(word ptr word) GetClassName16
@@ -225,7 +225,7 @@
 222 pascal16 GetKeyboardState(ptr) GetKeyboardState
 223 pascal16 SetKeyboardState(ptr) SetKeyboardState
 224 pascal16 GetWindowTask(word) GetWindowTask
-225 pascal16 EnumTaskWindows(word segptr long) EnumTaskWindows
+225 pascal16 EnumTaskWindows(word segptr long) EnumTaskWindows16
 226 stub LockInput
 227 pascal16 GetNextDlgGroupItem(word word word) GetNextDlgGroupItem
 228 pascal16 GetNextDlgTabItem(word word word) GetNextDlgTabItem
diff --git a/if1632/user32.spec b/if1632/user32.spec
index 3580e6e..c7c2316 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -181,7 +181,7 @@
 0174 stub EndMenu
 0175 stdcall EndPaint(long ptr) EndPaint32
 0176 stub EndTask
-0177 stub EnumChildWindows
+0177 stdcall EnumChildWindows(long ptr long) EnumChildWindows32
 0178 stub EnumClipboardFormats
 0179 stub EnumDesktopsA
 0180 stub EnumDesktopsW
@@ -193,10 +193,10 @@
 0186 stub EnumPropsExA
 0187 stub EnumPropsExW
 0188 stub EnumPropsW
-0189 stub EnumThreadWindows
+0189 stdcall EnumThreadWindows(long ptr long) EnumThreadWindows
 0190 stub EnumWindowStationsA
 0191 stub EnumWindowStationsW
-0192 stub EnumWindows
+0192 stdcall EnumWindows(ptr long) EnumWindows32
 0193 stdcall EqualRect(ptr ptr) EqualRect32
 0194 stdcall ExcludeUpdateRgn(long long) ExcludeUpdateRgn
 0195 stub ExitWindowsEx
diff --git a/if1632/winmm.spec b/if1632/winmm.spec
new file mode 100644
index 0000000..b5c47c4
--- /dev/null
+++ b/if1632/winmm.spec
@@ -0,0 +1,185 @@
+name winmm
+type win32
+
+0004 stub CloseDriver
+0005 stub DefDriverProc
+0006 stub DriverCallback
+0007 stub DrvClose
+0008 stub DrvDefDriverProc
+0009 stub DrvGetModuleHandle
+0010 stub DrvOpen
+0011 stub DrvOpenA
+0012 stub DrvSendMessage
+0013 stub GetDriverFlags
+0014 stub GetDriverModuleHandle
+0015 stub OpenDriver
+0016 stub OpenDriverA
+0017 stub PlaySound
+0001 stub PlaySoundA
+0018 stub PlaySoundW
+0019 stub SendDriverMessage
+0020 stub auxGetDevCapsA
+0021 stub auxGetDevCapsW
+0022 stub auxGetNumDevs
+0023 stub auxGetVolume
+0024 stub auxOutMessage
+0025 stub auxSetVolume
+0026 stub joyConfigChanged
+0027 stub joyGetDevCapsA
+0028 stub joyGetDevCapsW
+0029 stub joyGetNumDevs
+0030 stub joyGetPos
+0031 stub joyGetPosEx
+0032 stub joyGetThreshold
+0033 stub joyReleaseCapture
+0034 stub joySetCapture
+0035 stub joySetThreshold
+0036 stub mciDriverNotify
+0037 stub mciDriverYield
+0038 stub mciExecute
+0039 stub mciFreeCommandResource
+0040 stub mciGetCreatorTask
+0041 stub mciGetDeviceIDA
+0042 stub mciGetDeviceIDFromElementIDW
+0043 stub mciGetDeviceIDW
+0044 stub mciGetDriverData
+0045 stub mciGetErrorStringA
+0046 stub mciGetErrorStringW
+0047 stub mciGetYieldProc
+0048 stub mciLoadCommandResource
+0049 stub mciSendCommandA
+0050 stub mciSendCommandW
+0051 stub mciSendStringA
+0052 stub mciSendStringW
+0053 stub mciSetDriverData
+0054 stub mciSetYieldProc
+0055 stub midiConnect
+0056 stub midiDisconnect
+0057 stub midiInAddBuffer
+0058 stub midiInClose
+0059 stub midiInGetDevCapsA
+0060 stub midiInGetDevCapsW
+0061 stub midiInGetErrorTextA
+0062 stub midiInGetErrorTextW
+0063 stub midiInGetID
+0064 stub midiInGetNumDevs
+0065 stub midiInMessage
+0066 stub midiInOpen
+0067 stub midiInPrepareHeader
+0068 stub midiInReset
+0069 stub midiInStart
+0070 stub midiInStop
+0071 stub midiInUnprepareHeader
+0072 stub midiOutCacheDrumPatches
+0073 stub midiOutCachePatches
+0074 stub midiOutClose
+0075 stub midiOutGetDevCapsA
+0076 stub midiOutGetDevCapsW
+0077 stub midiOutGetErrorTextA
+0078 stub midiOutGetErrorTextW
+0079 stub midiOutGetID
+0080 stub midiOutGetNumDevs
+0081 stub midiOutGetVolume
+0082 stub midiOutLongMsg
+0083 stub midiOutMessage
+0084 stub midiOutOpen
+0085 stub midiOutPrepareHeader
+0086 stub midiOutReset
+0087 stub midiOutSetVolume
+0088 stub midiOutShortMsg
+0089 stub midiOutUnprepareHeader
+0090 stub midiStreamClose
+0091 stub midiStreamOpen
+0092 stub midiStreamOut
+0093 stub midiStreamPause
+0094 stub midiStreamPosition
+0095 stub midiStreamProperty
+0096 stub midiStreamRestart
+0097 stub midiStreamStop
+0098 stub mixerClose
+0099 stub mixerGetControlDetailsA
+0100 stub mixerGetControlDetailsW
+0101 stub mixerGetDevCapsA
+0102 stub mixerGetDevCapsW
+0103 stub mixerGetID
+0104 stub mixerGetLineControlsA
+0105 stub mixerGetLineControlsW
+0106 stub mixerGetLineInfoA
+0107 stub mixerGetLineInfoW
+0108 stub mixerGetNumDevs
+0109 stub mixerMessage
+0110 stub mixerOpen
+0111 stub mixerSetControlDetails
+0112 stub mmioAdvance
+0113 stub mmioAscend
+0114 stub mmioClose
+0115 stub mmioCreateChunk
+0116 stub mmioDescend
+0117 stub mmioFlush
+0118 stub mmioGetInfo
+0119 stub mmioInstallIOProc16
+0120 stub mmioInstallIOProcA
+0121 stub mmioInstallIOProcW
+0122 stub mmioOpenA
+0123 stub mmioOpenW
+0124 stub mmioRead
+0125 stub mmioRenameA
+0126 stub mmioRenameW
+0127 stub mmioSeek
+0128 stub mmioSendMessage
+0129 stub mmioSetBuffer
+0130 stub mmioSetInfo
+0131 stub mmioStringToFOURCCA
+0132 stub mmioStringToFOURCCW
+0133 stub mmioWrite
+0134 stub mmsystemGetVersion
+0135 stub sndPlaySoundA
+0136 stub sndPlaySoundW
+0137 stub timeBeginPeriod
+0138 stub timeEndPeriod
+0139 stub timeGetDevCaps
+0140 stub timeGetSystemTime
+0141 stub timeGetTime
+0142 stub timeKillEvent
+0143 stub timeSetEvent
+0144 stub waveInAddBuffer
+0145 stub waveInClose
+0146 stub waveInGetDevCapsA
+0147 stub waveInGetDevCapsW
+0148 stub waveInGetErrorTextA
+0149 stub waveInGetErrorTextW
+0150 stub waveInGetID
+0151 stub waveInGetNumDevs
+0152 stub waveInGetPosition
+0153 stub waveInMessage
+0154 stub waveInOpen
+0155 stub waveInPrepareHeader
+0156 stub waveInReset
+0157 stub waveInStart
+0158 stub waveInStop
+0159 stub waveInUnprepareHeader
+0160 stub waveOutBreakLoop
+0161 stub waveOutClose
+0162 stub waveOutGetDevCapsA
+0163 stub waveOutGetDevCapsW
+0164 stub waveOutGetErrorTextA
+0165 stub waveOutGetErrorTextW
+0166 stub waveOutGetID
+0167 	stdcall waveOutGetNumDevs() waveOutGetNumDevs
+0168 stub waveOutGetPitch
+0169 stub waveOutGetPlaybackRate
+0170 stub waveOutGetPosition
+0171 stub waveOutGetVolume
+0172 stub waveOutMessage
+0173 stub waveOutOpen
+0174 stub waveOutPause
+0175 stub waveOutPrepareHeader
+0176 stub waveOutReset
+0177 stub waveOutRestart
+0178 stub waveOutSetPitch
+0179 stub waveOutSetPlaybackRate
+0180 stub waveOutSetVolume
+0181 stub waveOutUnprepareHeader
+0182 stub waveOutWrite
+0183 stub winmmf_ThunkData32
+0184 stub winmmsl_ThunkData32
diff --git a/if1632/wprocs.spec b/if1632/wprocs.spec
index 531b647..4e47f58 100644
--- a/if1632/wprocs.spec
+++ b/if1632/wprocs.spec
@@ -1,6 +1,7 @@
 name	wprocs
 type	win16
 
+1  pascal WINPROC_CallProc16To32A(word word word long long) WINPROC_CallProc16To32A
 2  pascal StaticWndProc(word word word long) StaticWndProc
 3  pascal ScrollBarWndProc(word word word long) ScrollBarWndProc
 4  pascal ListBoxWndProc(word word word long) ListBoxWndProc
@@ -25,7 +26,6 @@
 26 register Win32CallToStart() PE_Win32CallToStart
 27 pascal EntryAddrProc(word word) MODULE_GetEntryPoint
 28 pascal MyAlloc(word word word) MODULE_AllocateSegment
-29 pascal16 ActivateAppProc(word long) ACTIVATEAPP_callback
 30 pascal FormatCharDlgProc(word word word long) FormatCharDlgProc
 31 pascal16 FontStyleEnumProc(ptr ptr word long)   FontStyleEnumProc
 32 pascal16 FontFamilyEnumProc(ptr ptr word long)  FontFamilyEnumProc
diff --git a/include/callback.h b/include/callback.h
index 537cfa9..b45373b 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -24,6 +24,7 @@
 
 #ifndef WINELIB
 
+extern WORD CallTo16_word_w    (FARPROC16, WORD, WORD);
 extern WORD CallTo16_word_ww   (FARPROC16, WORD, WORD, WORD);
 extern WORD CallTo16_word_wl   (FARPROC16, WORD, WORD, LONG);
 extern WORD CallTo16_word_ll   (FARPROC16, WORD, LONG, LONG);
@@ -36,6 +37,7 @@
 extern WORD CallTo16_word_lwww (FARPROC16, WORD, LONG, WORD, WORD, WORD);
 extern WORD CallTo16_word_wwll (FARPROC16, WORD, WORD, WORD, LONG, LONG);
 extern WORD CallTo16_word_wllwl(FARPROC16, WORD, WORD, LONG, LONG, WORD, LONG);
+extern LONG CallTo16_long_lwwll(FARPROC16, WORD, LONG, WORD, WORD, LONG, LONG);
 extern WORD CallTo16_word_wwlll(FARPROC16, WORD, WORD, WORD, LONG, LONG, LONG);
 extern LONG CallTo16_long_lllllllwlwwwl( FARPROC16, WORD, LONG, LONG, LONG,
                                          LONG, LONG, LONG, LONG, WORD, LONG,
@@ -44,6 +46,10 @@
 extern WORD CallTo16_regs_( FARPROC16 func, WORD ds, WORD es, WORD bp, WORD ax,
                             WORD bx, WORD cx, WORD dx, WORD si, WORD di );
 
+#define CallDCHookProc( func, hdc, code, data, lparam) \
+    CallTo16_word_wwll( func, CURRENT_DS, hdc, code, data, lparam )
+#define CallDriverProc( func, dwId, msg, hdrvr, lparam1, lparam2 ) \
+    CallTo16_long_lwwll( func, CURRENT_DS, dwId, msg, hdrvr, lparam1, lparam2 )
 #define CallEnumChildProc( func, hwnd, lParam ) \
     CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
 #define CallEnumFontFamProc( func, lpfont, lpmetric, type, lParam ) \
@@ -58,7 +64,7 @@
     CallTo16_word_wlw( func, CURRENT_DS, hwnd, lpstr, data )
 #define CallEnumTaskWndProc( func, hwnd, lParam ) \
     CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
-#define CallEnumWindowsProc( func, hwnd, lParam ) \
+#define CallEnumWindowsProc16( func, hwnd, lParam ) \
     CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
 #define CallLineDDAProc( func, xPos, yPos, lParam ) \
     CallTo16_word_wwl( func, CURRENT_DS, xPos, yPos, lParam )
@@ -68,12 +74,12 @@
     CallTo16_long_wwl( func, CURRENT_DS, code, wParam, lParam )
 #define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \
     CallTo16_word_wwlll( func, CURRENT_DS, id, msg, dwUser, dw1, dw2 )
+#define CallWindowsExitProc( func, nExitType ) \
+    CallTo16_word_w( func, CURRENT_DS, nExitType )
 #define CallWndProc16( func, ds, hwnd, msg, wParam, lParam ) \
     CallTo16_long_wwwl( func, ds, hwnd, msg, wParam, lParam )
 #define CallWordBreakProc( func, lpch, ichCurrent, cch, code ) \
     CallTo16_word_lwww( func, CURRENT_DS, lpch, ichCurrent, cch, code )
-#define CallDCHookProc( func, hdc, code, data, lparam) \
-    CallTo16_word_wwll( func, CURRENT_DS, hdc, code, data, lparam )
 #define CallWndProcNCCREATE16( func, ds, exStyle, clsName, winName, style, \
                                x, y, cx, cy, hparent, hmenu, instance, \
                                params, hwnd, msg, wParam, lParam ) \
@@ -86,6 +92,7 @@
 /* by the build program to generate the file if1632/callto32.S */
 
 extern LONG CallTo32_0( FARPROC32 );
+extern LONG CallTo32_2( FARPROC32, DWORD, DWORD );
 extern LONG CallTo32_3( FARPROC32, DWORD, DWORD, DWORD );
 extern LONG CallTo32_4( FARPROC32, DWORD, DWORD, DWORD, DWORD );
 
@@ -93,12 +100,18 @@
     CallTo32_0( func )
 #define CallDLLEntryProc32( func, hmodule, a, b ) \
     CallTo32_3( func, hmodule, a, b )
+#define CallEnumWindowsProc32( func, hwnd, lParam ) \
+    CallTo32_2( func, hwnd, lParam )
 #define CallWndProc32( func, hwnd, msg, wParam, lParam ) \
     CallTo32_4( func, hwnd, msg, wParam, lParam )
 
 
 #else  /* WINELIB */
 
+#define CallDCHookProc( func, hdc, code, data, lparam ) \
+    (*func)( hdc, code, data, lparam )
+#define CallDriverProc( func, dwId, msg, hdrvr, lparam1, lparam2 ) \
+    (*func)( dwId, msg, hdrvr, lparam1, lparam2 )
 #define CallEnumChildProc( func, hwnd, lParam ) \
     (*func)( hwnd, lParam )
 #define CallEnumFontFamProc( func, lpfont, lpmetric, type, lParam ) \
@@ -113,7 +126,9 @@
     (*func)( hwnd, (LPCTSTR)(lpstr), data )
 #define CallEnumTaskWndProc( func, hwnd, lParam ) \
     (*func)( hwnd, lParam )
-#define CallEnumWindowsProc( func, hwnd, lParam ) \
+#define CallEnumWindowsProc16( func, hwnd, lParam ) \
+    (*func)( hwnd, lParam )
+#define CallEnumWindowsProc32( func, hwnd, lParam ) \
     (*func)( hwnd, lParam )
 #define CallLineDDAProc( func, xPos, yPos, lParam ) \
     (*func)( xPos, yPos, lParam )
@@ -123,16 +138,15 @@
     (*func)( code, wParam, lParam )
 #define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \
     (*func)( id, msg, dwUser, dw1, dw2 )
+#define CallWindowsExitProc( func, nExitType ) \
+    (*func)( nExitType )
 #define CallWndProc16( func, ds, hwnd, msg, wParam, lParam ) \
     (*func)( hwnd, msg, wParam, lParam )
 #define CallWndProc32( func, hwnd, msg, wParam, lParam ) \
     (*func)( hwnd, msg, wParam, lParam )
-#define CallDCHookProc( func, hdc, code, data, lparam ) \
-    (*func)( hdc, code, data, lparam )
 #define CallWordBreakProc( func, lpch, ichCurrent, cch, code ) \
     (*func)( lpch, ichCurrent, cch, code )
 
-
 #endif  /* WINELIB */
 
 
diff --git a/include/class.h b/include/class.h
index 8cd8d06..dda909c 100644
--- a/include/class.h
+++ b/include/class.h
@@ -8,6 +8,7 @@
 #define CLASS_H
 
 #include "windows.h"
+#include "winproc.h"
 
 #define CLASS_MAGIC   ('C' | ('L' << 8) | ('A' << 16) | ('S' << 24))
 
@@ -17,7 +18,7 @@
     UINT32           magic;         /* Magic number */
     UINT32           cWindows;      /* Count of existing windows */
     UINT32           style;         /* Class style */
-    HANDLE32         winproc;       /* Window procedure */ 
+    HWINDOWPROC      winproc;       /* Window procedure */ 
     INT32            cbClsExtra;    /* Class extra bytes */
     INT32            cbWndExtra;    /* Window extra bytes */
     LPSTR            menuNameA;     /* Default menu name (ASCII string) */
@@ -34,7 +35,7 @@
 
 extern void CLASS_DumpClass( CLASS *class );
 extern void CLASS_WalkClasses(void);
-extern void CLASS_FreeModuleClasses( HMODULE hModule );
+extern void CLASS_FreeModuleClasses( HMODULE16 hModule );
 extern CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE16 hinstance );
 extern CLASS * CLASS_FindClassByName( SEGPTR name, HINSTANCE hinstance );
 
diff --git a/include/debugger.h b/include/debugger.h
index 866e202..6cb3e97 100644
--- a/include/debugger.h
+++ b/include/debugger.h
@@ -61,29 +61,28 @@
     EXEC_STEP_INSTR  /* Single-stepping an instruction */
 };
 
-extern struct sigcontext_struct *DEBUG_context;  /* debugger/registers.c */
+extern SIGCONTEXT *DEBUG_context;  /* debugger/registers.c */
 extern unsigned int dbg_mode;
 
   /* debugger/break.c */
-extern void DEBUG_SetBreakpoints( BOOL set );
+extern void DEBUG_SetBreakpoints( BOOL32 set );
 extern int DEBUG_FindBreakpoint( const DBG_ADDR *addr );
 extern void DEBUG_AddBreakpoint( const DBG_ADDR *addr );
 extern void DEBUG_DelBreakpoint( int num );
-extern void DEBUG_EnableBreakpoint( int num, BOOL enable );
+extern void DEBUG_EnableBreakpoint( int num, BOOL32 enable );
 extern void DEBUG_InfoBreakpoints(void);
-extern BOOL DEBUG_HandleTrap( struct sigcontext_struct *context );
-extern BOOL DEBUG_ShouldContinue( struct sigcontext_struct *context,
-                                  enum exec_mode mode );
-extern void DEBUG_RestartExecution( struct sigcontext_struct *context,
-                                    enum exec_mode mode, int instr_len );
+extern BOOL32 DEBUG_HandleTrap( SIGCONTEXT *context );
+extern BOOL32 DEBUG_ShouldContinue( SIGCONTEXT *context, enum exec_mode mode );
+extern void DEBUG_RestartExecution( SIGCONTEXT *context, enum exec_mode mode,
+                                    int instr_len );
 
   /* debugger/db_disasm.c */
 extern void DEBUG_Disasm( DBG_ADDR *addr );
 
   /* debugger/hash.c */
 extern void DEBUG_AddSymbol( const char *name, const DBG_ADDR *addr );
-extern BOOL DEBUG_GetSymbolValue( const char * name, DBG_ADDR *addr );
-extern BOOL DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr );
+extern BOOL32 DEBUG_GetSymbolValue( const char * name, DBG_ADDR *addr );
+extern BOOL32 DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr );
 extern const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr );
 extern void DEBUG_ReadSymbolTable( const char * filename );
 extern void DEBUG_LoadEntryPoints(void);
@@ -95,8 +94,8 @@
 extern void DEBUG_List( DBG_ADDR *addr, int count );
 
   /* debugger/memory.c */
-extern BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size );
-extern BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size );
+extern BOOL32 DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size );
+extern BOOL32 DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size );
 extern int DEBUG_ReadMemory( const DBG_ADDR *address );
 extern void DEBUG_WriteMemory( const DBG_ADDR *address, int value );
 extern void DEBUG_ExamineMemory( const DBG_ADDR *addr, int count, char format);
@@ -112,6 +111,6 @@
 
   /* debugger/dbg.y */
 extern void DEBUG_EnterDebugger(void);
-extern void wine_debug( int signal, struct sigcontext_struct * regs );
+extern void wine_debug( int signal, SIGCONTEXT *regs );
 
 #endif  /* DEBUGGER_H */
diff --git a/include/dialog.h b/include/dialog.h
index bb4b677..fefdc45 100644
--- a/include/dialog.h
+++ b/include/dialog.h
@@ -8,6 +8,7 @@
 #define DIALOG_H
 
 #include "windows.h"
+#include "winproc.h"
 
   /* Dialog info structure.
    * This structure is stored into the window extra bytes (cbWndExtra).
@@ -15,16 +16,16 @@
    */
 typedef struct
 {
-    INT32     msgResult;   /* Result of EndDialog() / Default button id */
-    HANDLE32  dlgProc;     /* Dialog procedure */
-    LONG      userInfo;    /* User information (for DWL_USER) */
-    HWND      hwndFocus;   /* Current control with focus */
-    HFONT     hUserFont;   /* Dialog font */
-    HMENU     hMenu;       /* Dialog menu */
-    WORD      xBaseUnit;   /* Dialog units (depends on the font) */
-    WORD      yBaseUnit;
-    WORD      fEnd;        /* EndDialog() called for this dialog */
-    HANDLE    hDialogHeap;
+    INT32       msgResult;   /* Result of EndDialog() / Default button id */
+    HWINDOWPROC dlgProc;     /* Dialog procedure */
+    LONG        userInfo;    /* User information (for DWL_USER) */
+    HWND        hwndFocus;   /* Current control with focus */
+    HFONT       hUserFont;   /* Dialog font */
+    HMENU       hMenu;       /* Dialog menu */
+    WORD        xBaseUnit;   /* Dialog units (depends on the font) */
+    WORD        yBaseUnit;
+    WORD        fEnd;        /* EndDialog() called for this dialog */
+    HANDLE      hDialogHeap;
 } DIALOGINFO;
 
 extern BOOL DIALOG_Init(void);
diff --git a/include/directory.h b/include/directory.h
index c466af8..28e5d64 100644
--- a/include/directory.h
+++ b/include/directory.h
@@ -11,7 +11,6 @@
 extern UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count );
 extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count );
 extern UINT DIR_GetTempUnixDir( LPSTR path, UINT count );
-extern UINT DIR_GetTempDosDir( LPSTR path, UINT count );
 extern UINT DIR_GetDosPath( int element, LPSTR path, UINT count );
 extern UINT DIR_GetUnixPath( int element, LPSTR path, UINT count );
 
diff --git a/include/driver.h b/include/driver.h
index 5c2a08e..63e0651 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -37,29 +37,32 @@
 	LPCSTR  lpszDCIAliasName;
 } DRVCONFIGINFO, *LPDRVCONFIGINFO;
 
-typedef struct {
-	UINT    length;
-	HDRVR   hDriver;
-	HINSTANCE hModule;
-	char    szAliasName[128];
-} DRIVERINFOSTRUCT, *LPDRIVERINFOSTRUCT;
+typedef struct
+{
+    UINT16       length;
+    HDRVR16      hDriver;
+    HINSTANCE16  hModule;
+    CHAR         szAliasName[128];
+} DRIVERINFOSTRUCT16, *LPDRIVERINFOSTRUCT16;
 
-typedef struct {
-	DRIVERINFOSTRUCT dis;
-	WORD		count;
-	void		*lpPrevItem;
-	void		*lpNextItem;
-	DRIVERPROC	lpDrvProc;
+typedef struct tagDRIVERITEM
+{
+    DRIVERINFOSTRUCT16    dis;
+    WORD                  count;
+    struct tagDRIVERITEM *lpPrevItem;
+    struct tagDRIVERITEM *lpNextItem;
+    DRIVERPROC            lpDrvProc;
 } DRIVERITEM, *LPDRIVERITEM;
 
-LRESULT DefDriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, 
-						DWORD dwParam1, DWORD dwParam2);
-HDRVR   OpenDriver(LPSTR szDriverName, LPSTR szSectionName, LPARAM lParam2);
-LRESULT CloseDriver(HDRVR hDriver, LPARAM lParam1, LPARAM lParam2);
-LRESULT SendDriverMessage(HDRVR hDriver, WORD message, LPARAM lParam1, LPARAM lParam2);
-HINSTANCE GetDriverModuleHandle(HDRVR hDriver);
-HDRVR   GetNextDriver(HDRVR, DWORD);
-BOOL    GetDriverInfo(HDRVR, DRIVERINFOSTRUCT *);
+LRESULT DefDriverProc(DWORD dwDevID, HDRVR hDriv, UINT16 wMsg, 
+                      LPARAM dwParam1, LPARAM dwParam2);
+HDRVR16 OpenDriver(LPSTR szDriverName, LPSTR szSectionName, LPARAM lParam2);
+LRESULT CloseDriver(HDRVR16 hDriver, LPARAM lParam1, LPARAM lParam2);
+LRESULT SendDriverMessage( HDRVR16 hDriver, UINT16 message, LPARAM lParam1,
+                           LPARAM lParam2 );
+HMODULE16 GetDriverModuleHandle(HDRVR16 hDriver);
+HDRVR16 GetNextDriver(HDRVR16, DWORD);
+BOOL16 GetDriverInfo(HDRVR16, DRIVERINFOSTRUCT16 *);
 
 
 
diff --git a/include/file.h b/include/file.h
index 82f7b80..8a63e3d 100644
--- a/include/file.h
+++ b/include/file.h
@@ -18,8 +18,6 @@
 extern int FILE_SetDateTime( HFILE hFile, WORD date, WORD time );
 extern int FILE_Fstat( HFILE hFile, BYTE *pattr, DWORD *psize,
                        WORD *pdate, WORD *ptime );
-extern int FILE_Unlink( LPCSTR path );
-extern int FILE_RemoveDir( LPCSTR path );
 extern HFILE FILE_Dup( HFILE hFile );
 extern HFILE FILE_Dup2( HFILE hFile1, HFILE hFile2 );
 extern INT32 FILE_Read( HFILE hFile, LPVOID buffer, UINT32 count );
diff --git a/include/gdi.h b/include/gdi.h
index 398b9c5..7bb9aa1 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -34,7 +34,7 @@
 
 typedef struct tagGDIOBJHDR
 {
-    HANDLE      hNext;
+    HANDLE16    hNext;
     WORD        wMagic;
     DWORD       dwCount;
     WORD        wMetaList;
@@ -86,16 +86,16 @@
     int           flags;
     DeviceCaps   *devCaps;
 
-    HANDLE        hMetaFile;
-    HRGN          hClipRgn;     /* Clip region (may be 0) */
-    HRGN          hVisRgn;      /* Visible region (must never be 0) */
-    HRGN          hGCClipRgn;   /* GC clip region (ClipRgn AND VisRgn) */
+    HANDLE16      hMetaFile;
+    HRGN16        hClipRgn;     /* Clip region (may be 0) */
+    HRGN16        hVisRgn;      /* Visible region (must never be 0) */
+    HRGN16        hGCClipRgn;   /* GC clip region (ClipRgn AND VisRgn) */
     HPEN16        hPen;
-    HBRUSH        hBrush;
-    HFONT         hFont;
-    HBITMAP       hBitmap;
-    HBITMAP       hFirstBitmap; /* Bitmap selected at creation of the DC */
-    HANDLE        hDevice;
+    HBRUSH16      hBrush;
+    HFONT16       hFont;
+    HBITMAP16     hBitmap;
+    HBITMAP16     hFirstBitmap; /* Bitmap selected at creation of the DC */
+    HANDLE16      hDevice;
     HPALETTE16    hPalette;
 
     WORD          ROPmode;
@@ -164,8 +164,8 @@
   /* X physical palette information */
 typedef struct
 {
-    HANDLE    hMapping;     /* Color mapping table (or 0 for identity) */
-    HANDLE    hRevMapping;  /* Reverse color mapping table */
+    HANDLE16  hMapping;     /* Color mapping table (or 0 for identity) */
+    HANDLE16  hRevMapping;  /* Reverse color mapping table */
     WORD      mappingSize;
 } X_PHYSPALETTE;
 
@@ -187,7 +187,7 @@
     WORD          saveLevel;
     DWORD         dwHookData;
     FARPROC16     hookProc;
-    HDC           hSelf;
+    HDC16         hSelf;
     WIN_DC_INFO   w;
     union
     {
@@ -275,10 +275,10 @@
 
 #endif  /* WINELIB */
 
-extern BOOL GDI_Init(void);
-extern HANDLE GDI_AllocObject( WORD, WORD );
-extern BOOL GDI_FreeObject( HANDLE );
-extern GDIOBJHDR * GDI_GetObjPtr( HANDLE, WORD );
+extern BOOL32 GDI_Init(void);
+extern HANDLE16 GDI_AllocObject( WORD, WORD );
+extern BOOL32 GDI_FreeObject( HANDLE16 );
+extern GDIOBJHDR * GDI_GetObjPtr( HANDLE16, WORD );
 extern FARPROC16 GDI_GetDefDCHook(void);
 
 extern Display * display;
diff --git a/include/hook.h b/include/hook.h
index 23aa709..eb04e86 100644
--- a/include/hook.h
+++ b/include/hook.h
@@ -18,12 +18,12 @@
   /* Hook data (pointed to by a HHOOK) */
 typedef struct
 {
-    HANDLE   next;               /* 00 Next hook in chain */
-    HOOKPROC proc WINE_PACKED;   /* 02 Hook procedure */
-    short    id;                 /* 06 Hook id (WH_xxx) */
-    HQUEUE   ownerQueue;         /* 08 Owner queue (0 for system hook) */
-    HMODULE  ownerModule;        /* 0a Owner module */
-    WORD     inHookProc;         /* 0c TRUE if in this->proc */
+    HANDLE16   next;               /* 00 Next hook in chain */
+    HOOKPROC   proc WINE_PACKED;   /* 02 Hook procedure */
+    short      id;                 /* 06 Hook id (WH_xxx) */
+    HQUEUE16   ownerQueue;         /* 08 Owner queue (0 for system hook) */
+    HMODULE16  ownerModule;        /* 0a Owner module */
+    WORD       inHookProc;         /* 0c TRUE if in this->proc */
 } HOOKDATA;
 
 #ifndef WINELIB
@@ -35,7 +35,7 @@
 extern HANDLE HOOK_GetHook( short id , HQUEUE hQueue );
 extern DWORD HOOK_CallHooks( short id, short code,
                              WPARAM wParam, LPARAM lParam );
-extern void HOOK_FreeModuleHooks( HMODULE hModule );
-extern void HOOK_FreeQueueHooks( HQUEUE hQueue );
+extern void HOOK_FreeModuleHooks( HMODULE16 hModule );
+extern void HOOK_FreeQueueHooks( HQUEUE16 hQueue );
 
 #endif  /* __WINE_HOOK_H */
diff --git a/include/kernel32.h b/include/kernel32.h
index 834cc2f..ab3b567 100644
--- a/include/kernel32.h
+++ b/include/kernel32.h
@@ -27,7 +27,7 @@
         DWORD InternalHigh;
         DWORD Offset;
         DWORD OffsetHigh;
-        HANDLE hEvent;
+        HANDLE32 hEvent;
 } OVERLAPPED, *LPOVERLAPPED;
 
 /* Process startup information.
@@ -48,9 +48,9 @@
         WORD wShowWindow;
         WORD cbReserved2;
         BYTE *lpReserved2;
-        HANDLE hStdInput;
-        HANDLE hStdOutput;
-        HANDLE hStdError;
+        HANDLE32 hStdInput;
+        HANDLE32 hStdOutput;
+        HANDLE32 hStdError;
 } STARTUPINFO, *LPSTARTUPINFO;
 
 typedef struct {
@@ -119,6 +119,6 @@
 #define FILE_ATTRIBUTE_ATOMIC_WRITE     0x0200
 #define FILE_ATTRIBUTE_XACTION_WRITE    0x0400
 
-BOOL       SetTimeZoneInformation(const TIME_ZONE_INFORMATION*);
+BOOL32     SetTimeZoneInformation(const TIME_ZONE_INFORMATION*);
 
 #endif  /* __WINE_KERNEL32_H */
diff --git a/include/local.h b/include/local.h
index 5561078..114a92f 100644
--- a/include/local.h
+++ b/include/local.h
@@ -23,6 +23,6 @@
 extern UINT16 LOCAL_HeapSize( HANDLE16 ds );
 extern UINT16 LOCAL_CountFree( HANDLE16 ds );
 extern LPSTR LOCAL_Lock( HANDLE16 ds, HLOCAL16 handle );
-extern BOOL LOCAL_Unlock( HANDLE16 ds, HLOCAL16 handle );
+extern BOOL16 LOCAL_Unlock( HANDLE16 ds, HLOCAL16 handle );
 
 #endif  /* __WINE_LOCAL_H */
diff --git a/include/miscemu.h b/include/miscemu.h
index 0ee35f6..dd05077 100644
--- a/include/miscemu.h
+++ b/include/miscemu.h
@@ -17,7 +17,7 @@
 extern HANDLE DOSMEM_BiosSeg;
 
   /* miscemu/instr.c */
-extern BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context );
+extern BOOL INSTR_EmulateInstruction( SIGCONTEXT *context );
 
   /* miscemu/interrupts.c */
 extern BOOL INT_Init(void);
diff --git a/include/module.h b/include/module.h
index 6ded804..4eed450 100644
--- a/include/module.h
+++ b/include/module.h
@@ -20,7 +20,7 @@
     WORD    magic;            /* 00 'NE' signature */
     WORD    count;            /* 02 Usage count */
     WORD    entry_table;      /* 04 Near ptr to entry table */
-    HMODULE next;             /* 06 Selector to next module */
+    HMODULE16  next;          /* 06 Selector to next module */
     WORD    dgroup_entry;     /* 08 Near ptr to segment entry for DGROUP */
     WORD    fileinfo;         /* 0a Near ptr to file info (OFSTRUCT) */
     WORD    flags;            /* 0c Module flags */
@@ -45,13 +45,13 @@
     WORD    truetype;         /* 34 Set to 2 if TrueType font */
     BYTE    os_flags;         /* 36 Operating system flags */
     BYTE    misc_flags;       /* 37 Misc. flags */
-    HANDLE  dlls_to_init;     /* 38 List of DLLs to initialize */
-    HANDLE  nrname_handle;    /* 3a Handle to non-resident name table */
+    HANDLE16   dlls_to_init;  /* 38 List of DLLs to initialize */
+    HANDLE16   nrname_handle; /* 3a Handle to non-resident name table */
     WORD    min_swap_area;    /* 3c Min. swap area size */
     WORD    expected_version; /* 3e Expected Windows version */
     /* From here, these are extra fields not present in normal Windows */
     PE_MODULE *pe_module;     /* 40 PE module handle for Win32 modules */
-    HMODULE self;             /* 44 Handle for this module */
+    HMODULE16  self;          /* 44 Handle for this module */
     WORD    self_loading_sel; /* 46 Selector used for self-loading apps. */
 } NE_MODULE;
 
@@ -59,11 +59,11 @@
   /* In-memory segment table */
 typedef struct
 {
-    WORD    filepos;   /* Position in file, in sectors */
-    WORD    size;      /* Segment size on disk */
-    WORD    flags;     /* Segment flags */
-    WORD    minsize;   /* Min. size of segment in memory */
-    HANDLE  selector;  /* Selector of segment in memory */
+    WORD      filepos;   /* Position in file, in sectors */
+    WORD      size;      /* Segment size on disk */
+    WORD      flags;     /* Segment flags */
+    WORD      minsize;   /* Min. size of segment in memory */
+    HANDLE16  selector;  /* Selector of segment in memory */
 } SEGTABLEENTRY;
 
 
@@ -71,27 +71,27 @@
 
 typedef struct
 {
-    WORD    version;		/* Must be 0xA0 */
-    WORD    reserved;   
-    FARPROC BootApp;    	/* startup procedure */
-    FARPROC LoadAppSeg; 	/* procedure to load a segment */
-    FARPROC reserved2;
-    FARPROC MyAlloc;     	/* memory allocation procedure, 
-				 * wine must write this field */
-    FARPROC EntryAddrProc;
-    FARPROC ExitProc;		/* exit procedure */
-    WORD    reserved3[4];
-    FARPROC SetOwner;           /* Set Owner procedure, exported by wine */
+    WORD      version;       /* Must be 0xA0 */
+    WORD      reserved;
+    FARPROC16 BootApp;       /* startup procedure */
+    FARPROC16 LoadAppSeg;    /* procedure to load a segment */
+    FARPROC16 reserved2;
+    FARPROC16 MyAlloc;       /* memory allocation procedure, 
+                              * wine must write this field */
+    FARPROC16 EntryAddrProc;
+    FARPROC16 ExitProc;      /* exit procedure */
+    WORD      reserved3[4];
+    FARPROC16 SetOwner;      /* Set Owner procedure, exported by wine */
 } SELFLOADHEADER;
 
   /* Parameters for LoadModule() */
 
 typedef struct
 {
-    HANDLE hEnvironment;  /* Environment segment */
-    SEGPTR cmdLine;       /* Command-line */
-    SEGPTR showCmd;       /* Code for ShowWindow() */
-    SEGPTR reserved;
+    HANDLE16 hEnvironment;  /* Environment segment */
+    SEGPTR   cmdLine;       /* Command-line */
+    SEGPTR   showCmd;       /* Code for ShowWindow() */
+    SEGPTR   reserved;
 } LOADPARAMS;
 
 /* Resource types */
@@ -116,30 +116,31 @@
 #endif
 
 /* module.c */
-extern NE_MODULE *MODULE_GetPtr( HMODULE hModule );
-extern void MODULE_DumpModule( HMODULE hmodule );
+extern NE_MODULE *MODULE_GetPtr( HMODULE16 hModule );
+extern void MODULE_DumpModule( HMODULE16 hmodule );
 extern void MODULE_WalkModules(void);
-extern int MODULE_OpenFile( HMODULE hModule );
-extern LPSTR MODULE_GetModuleName( HMODULE hModule );
+extern int MODULE_OpenFile( HMODULE16 hModule );
+extern LPSTR MODULE_GetModuleName( HMODULE16 hModule );
 extern void MODULE_RegisterModule( NE_MODULE *pModule );
-extern HINSTANCE MODULE_GetInstance( HMODULE hModule );
-extern WORD MODULE_GetOrdinal( HMODULE hModule, const char *name );
-extern SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal );
-extern BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset );
+extern HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule );
+extern WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name );
+extern SEGPTR MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal );
+extern BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal,
+                                    WORD offset );
 extern FARPROC16 MODULE_GetWndProcEntry16( const char *name );
 
 /* builtin.c */
-extern BOOL BUILTIN_Init(void);
-extern HMODULE BUILTIN_LoadModule( LPCSTR name, BOOL force );
+extern BOOL16 BUILTIN_Init(void);
+extern HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL16 force );
 extern NE_MODULE *BUILTIN_GetEntryPoint( WORD cs, WORD ip,
                                          WORD *pOrd, char **ppName );
 extern DWORD BUILTIN_GetProcAddress32( NE_MODULE *pModule, char *function );
-extern BOOL BUILTIN_ParseDLLOptions( const char *str );
+extern BOOL16 BUILTIN_ParseDLLOptions( const char *str );
 extern void BUILTIN_PrintDLLs(void);
 
 /* ne_image.c */
-extern BOOL NE_LoadSegment( HMODULE hModule, WORD segnum );
+extern BOOL16 NE_LoadSegment( HMODULE16 hModule, WORD segnum );
 extern void NE_FixupPrologs( NE_MODULE *pModule );
-extern void NE_InitializeDLLs( HMODULE hModule );
+extern void NE_InitializeDLLs( HMODULE16 hModule );
 
 #endif  /* _WINE_MODULE_H */
diff --git a/include/pe_image.h b/include/pe_image.h
index b9c74d8..a60c893 100644
--- a/include/pe_image.h
+++ b/include/pe_image.h
@@ -19,7 +19,7 @@
 
 typedef struct pe_data PE_MODULE;
 
-extern int PE_unloadImage(HMODULE hModule);
+extern int PE_unloadImage(HMODULE32 hModule);
 extern void my_wcstombs(char * result, u_short * source, int len);
 
 #endif /* __WINE_PE_IMAGE_H */
diff --git a/include/queue.h b/include/queue.h
index cffd7e3..f0e254f 100644
--- a/include/queue.h
+++ b/include/queue.h
@@ -54,8 +54,8 @@
   WORD      wakeBits;               /* 44 Queue wake-up bits */
   WORD      wakeMask;               /* 46 Queue wake-up mask */
   WORD      SendMsgReturnPtrs[3];   /* 48 Near ptr to return values (?) */
-  HANDLE    hCurHook;               /* 4e Current hook */
-  HANDLE    hooks[WH_NB_HOOKS];     /* 50 Task hooks list */
+  HANDLE16  hCurHook;               /* 4e Current hook */
+  HANDLE16  hooks[WH_NB_HOOKS];     /* 50 Task hooks list */
   WORD      reserved4[3];           /* 68 Unknown */
   QMSG      messages[1];            /* 6e Queue messages */
 } MESSAGEQUEUE;
diff --git a/include/region.h b/include/region.h
index 552f5c5..e73fc23 100644
--- a/include/region.h
+++ b/include/region.h
@@ -17,7 +17,7 @@
 } RGNOBJ;
 
 
-extern BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj );
-extern BOOL REGION_FrameRgn( HRGN dest, HRGN src, INT32 x, INT32 y );
+extern BOOL16 REGION_DeleteObject( HRGN32 hrgn, RGNOBJ * obj );
+extern BOOL16 REGION_FrameRgn( HRGN32 dest, HRGN32 src, INT32 x, INT32 y );
 
 #endif  /* __WINE_REGION_H */
diff --git a/include/registers.h b/include/registers.h
index 98f28ee..1f919a5 100644
--- a/include/registers.h
+++ b/include/registers.h
@@ -62,9 +62,6 @@
 #define IP_reg(context)      (*(WORD*)(&(context)->sc_eip))
 #define SP_reg(context)      (*(WORD*)(&(context)->sc_esp))
                             
-#define SET_CFLAG(context)   (EFL_reg(context) |= 0x0001)
-#define RESET_CFLAG(context) (EFL_reg(context) &= 0xfffffffe)
-
 #else  /* __svr4__ || _SCO_DS */
 
 #ifdef _SCO_DS
@@ -123,9 +120,9 @@
 #define SP_reg(context)      (*(WORD*)(&(context)->uc_mcontext.gregs[ESP]))
 #endif
                             
+#endif  /* __svr4__ || _SCO_DS */
+
 #define SET_CFLAG(context)   (EFL_reg(context) |= 0x0001)
 #define RESET_CFLAG(context) (EFL_reg(context) &= 0xfffffffe)
 
-#endif  /* __svr4__ || _SCO_DS */
-
 #endif /* __WINE_REGISTERS_H */
diff --git a/include/selectors.h b/include/selectors.h
index e826d8d..f5e3800 100644
--- a/include/selectors.h
+++ b/include/selectors.h
@@ -11,10 +11,10 @@
 #include "ldt.h"
 
 extern WORD SELECTOR_AllocBlock( const void *base, DWORD size,
-				 enum seg_type type, BOOL is32bit,
-				 BOOL readonly );
+				 enum seg_type type, BOOL32 is32bit,
+				 BOOL32 readonly );
 extern WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size,
-                                   enum seg_type type, BOOL is32bit,
-                                   BOOL readonly );
+                                   enum seg_type type, BOOL32 is32bit,
+                                   BOOL32 readonly );
 
 #endif /* __WINE_SELECTORS_H */
diff --git a/include/task.h b/include/task.h
index b00f6fb..f9a8b9c 100644
--- a/include/task.h
+++ b/include/task.h
@@ -13,10 +13,6 @@
 #pragma pack(1)
 #endif
 
-
-extern BOOL TASK_Init(void);
-extern void TASK_KillCurrentTask( int exitCode );
-
   /* Process database (i.e. a normal DOS PSP) */
 
 typedef struct
@@ -115,8 +111,10 @@
 #pragma pack(4)
 #endif
 
+extern BOOL TASK_Init(void);
 extern HTASK TASK_CreateTask( HMODULE hModule, HANDLE hInstance,
                               HANDLE hPrevInstance, HANDLE hEnvironment,
                               char *cmdLine, WORD cmdShow );
+extern void TASK_KillCurrentTask( int exitCode );
 
 #endif /* _WINE_TASK_H */
diff --git a/include/toolhelp.h b/include/toolhelp.h
index e161101..c1d9836 100644
--- a/include/toolhelp.h
+++ b/include/toolhelp.h
@@ -20,19 +20,19 @@
 
 typedef struct
 {
-    DWORD   dwSize;
-    DWORD   dwAddress;
-    DWORD   dwBlockSize;
-    HGLOBAL hBlock;
-    WORD    wcLock;
-    WORD    wcPageLock;
-    WORD    wFlags;
-    BOOL    wHeapPresent;
-    HGLOBAL hOwner;
-    WORD    wType;
-    WORD    wData;
-    DWORD   dwNext;
-    DWORD   dwNextAlt;
+    DWORD     dwSize;
+    DWORD     dwAddress;
+    DWORD     dwBlockSize;
+    HGLOBAL16 hBlock;
+    WORD      wcLock;
+    WORD      wcPageLock;
+    WORD      wFlags;
+    BOOL16    wHeapPresent;
+    HGLOBAL16 hOwner;
+    WORD      wType;
+    WORD      wData;
+    DWORD     dwNext;
+    DWORD     dwNextAlt;
 } GLOBALENTRY;
 
   /* GlobalFirst()/GlobalNext() flags */
@@ -74,11 +74,11 @@
 /* wFlags values */
 #define GF_PDB_OWNER        0x0100      /* Low byte is KERNEL flags */
 
-BOOL GlobalInfo( GLOBALINFO *pInfo );
-BOOL GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags );
-BOOL GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags) ;
-BOOL GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL16 hItem );
-BOOL GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE16 hModule, WORD wSeg );
+BOOL16 GlobalInfo( GLOBALINFO *pInfo );
+BOOL16 GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags );
+BOOL16 GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags) ;
+BOOL16 GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL16 hItem );
+BOOL16 GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE16 hModule, WORD wSeg );
 
 /* Local heap */
 
@@ -152,55 +152,55 @@
 #define LT_USER_HANDLETABLE         32
 #define LT_USER_MAX                 LT_USER_HANDLETABLE
 
-BOOL LocalInfo( LOCALINFO *pLocalInfo, HGLOBAL handle );
-BOOL LocalFirst( LOCALENTRY *pLocalEntry, HGLOBAL handle );
-BOOL LocalNext( LOCALENTRY *pLocalEntry );
+BOOL16 LocalInfo( LOCALINFO *pLocalInfo, HGLOBAL16 handle );
+BOOL16 LocalFirst( LOCALENTRY *pLocalEntry, HGLOBAL16 handle );
+BOOL16 LocalNext( LOCALENTRY *pLocalEntry );
 
 
 /* modules */
 
-typedef struct {
-    DWORD dwSize;
-    char szModule[MAX_MODULE_NAME + 1];
-    HMODULE hModule;
-    WORD wcUsage;
-    char szExePath[MAX_PATH + 1];
-    HANDLE wNext;
-} MODULEENTRY;
-typedef MODULEENTRY *LPMODULEENTRY;
+typedef struct
+{
+    DWORD      dwSize;
+    char       szModule[MAX_MODULE_NAME + 1];
+    HMODULE16  hModule;
+    WORD       wcUsage;
+    char       szExePath[MAX_PATH + 1];
+    HANDLE16   wNext;
+} MODULEENTRY, *LPMODULEENTRY;
 
-BOOL	ModuleFirst(MODULEENTRY *lpModule);
-BOOL	ModuleNext(MODULEENTRY *lpModule);
-BOOL    ModuleFindName(MODULEENTRY *lpModule, LPCSTR lpstrName);
-BOOL    ModuleFindHandle(MODULEENTRY *lpModule, HMODULE hModule);
+BOOL16 ModuleFirst(MODULEENTRY *lpModule);
+BOOL16 ModuleNext(MODULEENTRY *lpModule);
+BOOL16 ModuleFindName(MODULEENTRY *lpModule, LPCSTR lpstrName);
+BOOL16 ModuleFindHandle(MODULEENTRY *lpModule, HMODULE16 hModule);
 
 /* tasks */
 
-typedef struct tagTASKENTRY {
-	DWORD dwSize;
-	HTASK hTask;
-	HTASK hTaskParent;
-	HINSTANCE hInst;
-	HMODULE hModule;
-	WORD wSS;
-	WORD wSP;
-	WORD wStackTop;
-	WORD wStackMinimum;
-	WORD wStackBottom;
-	WORD wcEvents;
-	HGLOBAL hQueue;
-	char szModule[MAX_MODULE_NAME + 1];
-	WORD wPSPOffset;
-	HANDLE hNext;
-} TASKENTRY;
-typedef TASKENTRY *LPTASKENTRY;
+typedef struct
+{
+    DWORD        dwSize;
+    HTASK16      hTask;
+    HTASK16      hTaskParent;
+    HINSTANCE16  hInst;
+    HMODULE16    hModule;
+    WORD         wSS;
+    WORD         wSP;
+    WORD         wStackTop;
+    WORD         wStackMinimum;
+    WORD         wStackBottom;
+    WORD         wcEvents;
+    HGLOBAL16    hQueue;
+    char         szModule[MAX_MODULE_NAME + 1];
+    WORD         wPSPOffset;
+    HANDLE16     hNext;
+} TASKENTRY, *LPTASKENTRY;
 
-BOOL	TaskFirst(LPTASKENTRY lpTask);
-BOOL	TaskNext(LPTASKENTRY lpTask);
-BOOL	TaskFindHandle(LPTASKENTRY lpTask, HTASK hTask);
-DWORD	TaskSetCSIP(HTASK hTask, WORD wCS, WORD wIP);
-DWORD	TaskGetCSIP(HTASK hTask);
-BOOL	TaskSwitch(HTASK hTask, DWORD dwNewCSIP);
+BOOL16 TaskFirst(LPTASKENTRY lpTask);
+BOOL16 TaskNext(LPTASKENTRY lpTask);
+BOOL16 TaskFindHandle(LPTASKENTRY lpTask, HTASK16 hTask);
+DWORD TaskSetCSIP(HTASK16 hTask, WORD wCS, WORD wIP);
+DWORD TaskGetCSIP(HTASK16 hTask);
+BOOL16 TaskSwitch(HTASK16 hTask, DWORD dwNewCSIP);
 
 /* mem info */
 
@@ -221,15 +221,15 @@
 
 typedef struct
 {
-    DWORD   dwSize;
-    WORD    wUserFreePercent;
-    WORD    wGDIFreePercent;
-    HGLOBAL hUserSegment;
-    HGLOBAL hGDISegment;
+    DWORD     dwSize;
+    WORD      wUserFreePercent;
+    WORD      wGDIFreePercent;
+    HGLOBAL16 hUserSegment;
+    HGLOBAL16 hGDISegment;
 } SYSHEAPINFO;
 
-BOOL MemManInfo(LPMEMMANINFO lpEnhMode);
-BOOL SystemHeapInfo( SYSHEAPINFO *pHeapInfo );
+BOOL16 MemManInfo(LPMEMMANINFO lpEnhMode);
+BOOL16 SystemHeapInfo( SYSHEAPINFO *pHeapInfo );
 
 /* timer info */
 
@@ -239,20 +239,20 @@
 	DWORD dwmsThisVM;
 } TIMERINFO;
 
-BOOL TimerCount( TIMERINFO *pTimerInfo );
+BOOL16 TimerCount( TIMERINFO *pTimerInfo );
 
 /* Window classes */
 
 typedef struct
 {
     DWORD     dwSize;
-    HMODULE   hInst;              /* This is really an hModule */
+    HMODULE16 hInst;              /* This is really an hModule */
     char      szClassName[MAX_CLASSNAME + 1];
-    HANDLE    wNext;
+    HANDLE16  wNext;
 } CLASSENTRY;
 
-BOOL ClassFirst( CLASSENTRY *pClassEntry );
-BOOL ClassNext( CLASSENTRY *pClassEntry );
+BOOL16 ClassFirst( CLASSENTRY *pClassEntry );
+BOOL16 ClassNext( CLASSENTRY *pClassEntry );
 
 
 /* Memory read/write */
@@ -267,7 +267,7 @@
 #define NF_TASKSWITCH	1	/* get taskswitch information */
 #define NF_RIP		2	/* get debugerrors of system */
 
-BOOL NotifyRegister(HTASK htask,FARPROC lpfnCallback,WORD wFlags);
+BOOL16 NotifyRegister(HTASK16 htask,FARPROC16 lpfnCallback,WORD wFlags);
 
 #define NFY_UNKNOWN	0
 #define NFY_LOADSEG	1
@@ -285,10 +285,10 @@
 /* called when loading/starting a DLL */
 #define NFY_STARTDLL	3
 struct {
-	DWORD	dwSize;
-	HMODULE	hModule;
-	WORD	wCS;
-	WORD	wIP;
+    DWORD      dwSize;
+    HMODULE16  hModule;
+    WORD       wCS;
+    WORD       wIP;
 } NFYSTARTDLL;
 
 /* called when starting a task. dwData is CS:IP */
@@ -331,16 +331,16 @@
 #define NFY_LOGERROR	12
 struct {
 	DWORD	dwSize;
-	UINT	wErrCode;
+	UINT16	wErrCode;
 	VOID   *lpInfo; /* depends on wErrCode */
 } NFYLOGERROR;
 
 /* called for parameter errors? */
 #define NFY_LOGPARAMERROR	13
 struct {
-	DWORD	dwSize;
-	UINT	wErrCode;
-	FARPROC	lpfnErrorAddr;
-	void  **lpBadParam;
+    DWORD       dwSize;
+    UINT16      wErrCode;
+    FARPROC16   lpfnErrorAddr;
+    void      **lpBadParam;
 } NFYLOGPARAMERROR;
 #endif /* __TOOLHELP_H */
diff --git a/include/win.h b/include/win.h
index 81e0c08..7a36cec 100644
--- a/include/win.h
+++ b/include/win.h
@@ -11,6 +11,7 @@
 
 #include "ldt.h"
 #include "class.h"
+#include "winproc.h"
 
 #define WND_MAGIC     0x444e4957  /* 'WIND' */
 
@@ -34,7 +35,7 @@
     struct tagWND *parent;        /* Window parent (from CreateWindow) */
     struct tagWND *owner;         /* Window owner */
     CLASS         *class;         /* Window class */
-    HANDLE32       winproc;       /* Window procedure */
+    HWINDOWPROC    winproc;       /* Window procedure */
     DWORD          dwMagic;       /* Magic number (must be WND_MAGIC) */
     HWND16         hwndSelf;      /* Handle of this window */
     HINSTANCE16    hInstance;     /* Window hInstance (from CreateWindow) */
@@ -71,6 +72,7 @@
 #define WIN_NEED_SIZE          0x0040 /* Internal WM_SIZE is needed */
 #define WIN_NCACTIVATED        0x0080 /* last WM_NCACTIVATE was positive */
 #define WIN_MANAGED            0x0100 /* Window managed by the X wm */
+#define WIN_ISDIALOG           0x0200 /* Window is a dialog */
 
   /* Window functions */
 extern WND *WIN_FindWndPtr( HWND hwnd );
@@ -86,6 +88,7 @@
 extern BOOL WIN_CreateDesktopWindow(void);
 extern HWND WIN_GetTopParent( HWND hwnd );
 extern HINSTANCE WIN_GetWindowInstance( HWND hwnd );
+extern WND **WIN_BuildWinArray( WND *wndPtr );
 
 extern void DEFWND_SetText( WND *wndPtr, LPCSTR text );  /* windows/defwnd.c */
 
diff --git a/include/winbase.h b/include/winbase.h
index 1a5317d..f221fa2 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -3,14 +3,6 @@
 
 #include "wintypes.h"
 
-#ifdef UNICODE
-#define LoadAccelerators LoadAcceleratorsW
-#define TranslateAccelat
-#else
-#define LoadAccelerators LoadAcceleratorsA
-#endif
-
-
 #define INVALID_HANDLE_VALUE    ((HANDLE32) -1)
 
 #define WAIT_FAILED		0xffffffff
@@ -116,8 +108,8 @@
 	LPVOID	DebugInfo;
 	LONG LockCount;
 	LONG RecursionCount;
-	HANDLE OwningThread;
-	HANDLE LockSemaphore;
+	HANDLE32 OwningThread;
+	HANDLE32 LockSemaphore;
 	DWORD Reserved;
 }CRITICAL_SECTION;
 
@@ -150,36 +142,16 @@
 BOOL32 GetVersionEx32W(OSVERSIONINFO32W*);
 #define GetVersionEx WINELIB_NAME_AW(GetVersionEx)
 
-int WinMain(HINSTANCE, HINSTANCE prev, char *cmd, int show);
+/*int WinMain(HINSTANCE, HINSTANCE prev, char *cmd, int show);*/
 
-#define GMEM_FIXED          0x0000
-#define GMEM_MOVEABLE 	    0x0002
-
-HACCEL32 LoadAcceleratorsA(   HINSTANCE, const char *);
-#define FreeModule(hLibModule) FreeLibrary((hLibModule))
-#define MakeProcInstance(lpProc,hInstance) (lpProc)
-#define FreeProcInstance(lpProc) (lpProc)
-
+HACCEL32 LoadAcceleratorsA(   HINSTANCE32, const char *);
 
 void     DeleteCriticalSection(CRITICAL_SECTION *lpCrit);
 void     EnterCriticalSection(CRITICAL_SECTION *lpCrit);
 int      GetCurrentProcessId(void);
-HANDLE32 GetProcessHeap(void);
-LPVOID   HeapAlloc(HANDLE32,DWORD,DWORD);
-DWORD    HeapCompact(HANDLE32,DWORD);
-HANDLE32 HeapCreate(DWORD,DWORD,DWORD);
-BOOL     HeapDestroy(HANDLE32);
-BOOL     HeapFree(HANDLE32,DWORD,LPVOID);
-BOOL     HeapLock(HANDLE32);
-LPVOID   HeapReAlloc(HANDLE32,DWORD,LPVOID,DWORD);
-DWORD    HeapSize(HANDLE32,DWORD,LPVOID);
-BOOL     HeapUnlock(HANDLE32);
-BOOL     HeapValidate(HANDLE32,DWORD,LPVOID);
 void     InitializeCriticalSection(CRITICAL_SECTION *lpCrit);
 void     LeaveCriticalSection(CRITICAL_SECTION *lpCrit);
-HANDLE   OpenProcess(DWORD access, BOOL inherit, DWORD id);
-int      TerminateProcess(HANDLE h, int ret);
-LPVOID   VirtualAlloc(LPVOID addr,DWORD size,DWORD type,DWORD protect);
-BOOL     VirtualFree( LPVOID addr, DWORD size, DWORD type );
+HANDLE32 OpenProcess(DWORD access, BOOL32 inherit, DWORD id);
+int      TerminateProcess(HANDLE32 h, int ret);
 
 #endif  /* __WINE_WINBASE_H */
diff --git a/include/windows.h b/include/windows.h
index 41d242b..16e6f80 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -1,5 +1,3 @@
-/* Initial draft attempt of windows.h, by Peter MacDonald, pmacdona@sanjuan.uvic.ca */
-
 #ifndef __WINE_WINDOWS_H
 #define __WINE_WINDOWS_H
 
@@ -478,6 +476,10 @@
 #define MSGF_MAINLOOP       8
 #define MSGF_USER        4096
 
+  /* Windows Exit Procedure flag values */
+#define	WEP_FREE_DLL        0
+#define	WEP_SYSTEM_EXIT     1
+
   /* Journalling hook structure */
 
 typedef struct
@@ -3145,8 +3147,13 @@
 
 /* Declarations for functions that exist only in Win16 */
 
+WORD       AllocSelector(WORD);
+WORD       AllocSelectorArray(WORD);
 VOID       FillWindow(HWND16,HWND16,HDC16,HBRUSH16);
+WORD       FreeSelector(WORD);
 DWORD      GetBitmapDimension(HBITMAP16);
+HTASK16    GetCurrentTask(void);
+BOOL16     LocalInit(HANDLE16,WORD,WORD);
 DWORD      OffsetViewportOrg(HDC16,INT16,INT16);
 DWORD      OffsetWindowOrg(HDC16,INT16,INT16);
 VOID       PaintRect(HWND16,HWND16,HDC16,HBRUSH16,const RECT16*);
@@ -3161,15 +3168,38 @@
 
 /* Declarations for functions that exist only in Win32 */
 
+BOOL32     Beep(DWORD,DWORD);
+BOOL32     EnumThreadWindows(DWORD,WNDENUMPROC32,LPARAM);
 BOOL32     FlushFileBuffers(HFILE);
 DWORD      GetLogicalDrives(void);
+HANDLE32   GetProcessHeap(void);
+LPVOID     HeapAlloc(HANDLE32,DWORD,DWORD);
+DWORD      HeapCompact(HANDLE32,DWORD);
+HANDLE32   HeapCreate(DWORD,DWORD,DWORD);
+BOOL32     HeapDestroy(HANDLE32);
+BOOL32     HeapFree(HANDLE32,DWORD,LPVOID);
+BOOL32     HeapLock(HANDLE32);
+LPVOID     HeapReAlloc(HANDLE32,DWORD,LPVOID,DWORD);
+DWORD      HeapSize(HANDLE32,DWORD,LPVOID);
+BOOL32     HeapUnlock(HANDLE32);
+BOOL32     HeapValidate(HANDLE32,DWORD,LPVOID);
+VOID       RtlFillMemory(LPVOID,UINT32,UINT32);
+VOID       RtlMoveMemory(LPVOID,LPCVOID,UINT32);
+VOID       RtlZeroMemory(LPVOID,UINT32);
+LPVOID     VirtualAlloc(LPVOID,DWORD,DWORD,DWORD);
+BOOL32     VirtualFree(LPVOID,DWORD,DWORD);
 
 /* Declarations for functions that are the same in Win16 and Win32 */
 
+INT16      CombineRgn(HRGN32,HRGN32,HRGN32,INT32);
 HBITMAP16  CreateBitmap(INT32,INT32,UINT32,UINT32,LPCVOID);
 HBITMAP16  CreateCompatibleBitmap(HDC32,INT32,INT32);
 HBITMAP16  CreateDiscardableBitmap(HDC32,INT32,INT32);
+HRGN16     CreateEllipticRgn(INT32,INT32,INT32,INT32);
+HRGN16     CreateRectRgn(INT32,INT32,INT32,INT32);
+HRGN16     CreateRoundRectRgn(INT32,INT32,INT32,INT32,INT32,INT32);
 BOOL16     EndDialog(HWND32,INT32);
+BOOL16     EqualRgn(HRGN32,HRGN32);
 INT16      ExcludeUpdateRgn(HDC32,HWND32);
 DWORD      GetAppCompatFlags(HTASK32);
 LONG       GetBitmapBits(HBITMAP32,LONG,LPVOID);
@@ -3177,10 +3207,14 @@
 INT16      GetUpdateRgn(HWND32,HRGN32,BOOL32);
 WORD       GetWindowWord(HWND32,INT32);
 INT16      OffsetRgn(HRGN32,INT32,INT32);
+BOOL16     PtInRegion(HRGN32,INT32,INT32);
 DWORD      RegCloseKey(HKEY);
 DWORD      RegFlushKey(HKEY);
 LONG       SetBitmapBits(HBITMAP32,LONG,LPCVOID);
 WORD       SetClassWord(HWND32,INT32,WORD);
+INT16      SetDIBits(HDC32,HBITMAP32,UINT32,UINT32,LPCVOID,const BITMAPINFO*,UINT32);
+INT16      SetDIBitsToDevice(HDC32,INT32,INT32,DWORD,DWORD,INT32,INT32,UINT32,UINT32,LPCVOID,const BITMAPINFO*,UINT32);
+VOID       SetRectRgn(HRGN32,INT32,INT32,INT32,INT32);
 WORD       SetWindowWord(HWND32,INT32,WORD);
 
 /* Declarations for functions that change between Win16 and Win32 */
@@ -3287,6 +3321,10 @@
 LRESULT    DefWindowProc32A(HWND32,UINT32,WPARAM32,LPARAM);
 LRESULT    DefWindowProc32W(HWND32,UINT32,WPARAM32,LPARAM);
 #define    DefWindowProc WINELIB_NAME_AW(DefWindowProc)
+BOOL16     DeleteFile16(LPCSTR);
+BOOL32     DeleteFile32A(LPCSTR);
+BOOL32     DeleteFile32W(LPCWSTR);
+#define    DeleteFile WINELIB_NAME_AW(DeleteFile)
 INT16      DialogBox16(HINSTANCE16,SEGPTR,HWND16,DLGPROC16);
 #define    DialogBox32A(inst,template,owner,func) \
            DialogBoxParam32A(inst,template,owner,func,0)
@@ -3324,6 +3362,16 @@
 BOOL16     EndPaint16(HWND16,const PAINTSTRUCT16*);
 BOOL32     EndPaint32(HWND32,const PAINTSTRUCT32*);
 #define    EndPaint WINELIB_NAME(EndPaint)
+BOOL16     EnumChildWindows16(HWND16,WNDENUMPROC16,LPARAM);
+BOOL32     EnumChildWindows32(HWND32,WNDENUMPROC32,LPARAM);
+#define    EnumChildWindows WINELIB_NAME(EnumChildWindows)
+BOOL16     EnumTaskWindows16(HTASK16,WNDENUMPROC16,LPARAM);
+#define    EnumTaskWindows32(handle,proc,lparam) \
+           EnumThreadWindows(handle,proc,lparam)
+#define    EnumTaskWindows WINELIB_NAME(EnumTaskWindows)
+BOOL16     EnumWindows16(WNDENUMPROC16,LPARAM);
+BOOL32     EnumWindows32(WNDENUMPROC32,LPARAM);
+#define    EnumWindows WINELIB_NAME(EnumWindows)
 BOOL16     EqualRect16(const RECT16*,const RECT16*);
 BOOL32     EqualRect32(const RECT32*,const RECT32*);
 #define    EqualRect WINELIB_NAME(EqualRect)
@@ -3345,6 +3393,12 @@
 INT16      FrameRect16(HDC16,const RECT16*,HBRUSH16);
 INT32      FrameRect32(HDC32,const RECT32*,HBRUSH32);
 #define    FrameRect WINELIB_NAME(FrameRect)
+BOOL16     FreeModule16(HMODULE16);
+#define    FreeModule32(handle) FreeLibrary32(handle)
+#define    FreeModule WINELIB_NAME(FreeModule)
+void       FreeProcInstance16(FARPROC16);
+#define    FreeProcInstance32(proc) (proc)
+#define    FreeProcInstance WINELIB_NAME(FreeProcInstance)
 BOOL16     GetBitmapDimensionEx16(HBITMAP16,LPSIZE16);
 BOOL32     GetBitmapDimensionEx32(HBITMAP32,LPSIZE32);
 #define    GetBitmapDimensionEx WINELIB_NAME(GetBitmapDimensionEx)
@@ -3379,6 +3433,10 @@
 void       GetClipCursor16(LPRECT16);
 void       GetClipCursor32(LPRECT32);
 #define    GetClipCursor WINELIB_NAME(GetClipCursor)
+UINT16     GetCurrentDirectory16(UINT16,LPSTR);
+UINT32     GetCurrentDirectory32A(UINT32,LPSTR);
+UINT32     GetCurrentDirectory32W(UINT32,LPWSTR);
+#define    GetCurrentDirectory WINELIB_NAME_AW(GetCurrentDirectory)
 BOOL16     GetCurrentPositionEx16(HDC16,LPPOINT16);
 BOOL32     GetCurrentPositionEx32(HDC32,LPPOINT32);
 #define    GetCurrentPositionEx WINELIB_NAME(GetCurrentPositionEx)
@@ -3393,6 +3451,10 @@
 INT32      GetDlgItemText32A(HWND32,INT32,LPSTR,UINT32);
 INT32      GetDlgItemText32W(HWND32,INT32,LPWSTR,UINT32);
 #define    GetDlgItemText WINELIB_NAME_AW(GetDlgItemText)
+UINT16     GetDriveType16(UINT16); /* yes, the arguments differ */
+UINT32     GetDriveType32A(LPCSTR);
+UINT32     GetDriveType32W(LPCWSTR);
+#define    GetDriveType WINELIB_NAME_AW(GetDriveType)
 UINT16     GetInternalWindowPos16(HWND16,LPRECT16,LPPOINT16);
 UINT32     GetInternalWindowPos32(HWND32,LPRECT32,LPPOINT32);
 #define    GetInternalWindowPos WINELIB_NAME(GetInternalWindowPos)
@@ -3406,10 +3468,21 @@
 INT16      GetRgnBox16(HRGN16,LPRECT16);
 INT32      GetRgnBox32(HRGN32,LPRECT32);
 #define    GetRgnBox WINELIB_NAME(GetRgnBox)
+UINT16     GetSystemDirectory16(LPSTR,UINT16);
+UINT32     GetSystemDirectory32A(LPSTR,UINT32);
+UINT32     GetSystemDirectory32W(LPWSTR,UINT32);
+#define    GetSystemDirectory WINELIB_NAME_AW(GetSystemDirectory)
+UINT32     GetTempPath32A(UINT32,LPSTR);
+UINT32     GetTempPath32W(UINT32,LPWSTR);
+#define    GetTempPath WINELIB_NAME_AW(GetTempPath)
 BOOL16     GetTextExtentPoint16(HDC16,LPCSTR,INT16,LPSIZE16);
 BOOL32     GetTextExtentPoint32A(HDC32,LPCSTR,INT32,LPSIZE32);
 BOOL32     GetTextExtentPoint32W(HDC32,LPCWSTR,INT32,LPSIZE32);
 #define    GetTextExtentPoint WINELIB_NAME_AW(GetTextExtentPoint)
+BOOL16     GetTextMetrics16(HDC16,LPTEXTMETRIC16);
+BOOL32     GetTextMetrics32A(HDC32,LPTEXTMETRIC32A);
+BOOL32     GetTextMetrics32W(HDC32,LPTEXTMETRIC32W);
+#define    GetTextMetrics WINELIB_NAME_AW(GetTextMetrics)
 BOOL16     GetUpdateRect16(HWND16,LPRECT16,BOOL16);
 BOOL32     GetUpdateRect32(HWND32,LPRECT32,BOOL32);
 #define    GetUpdateRect WINELIB_NAME(GetUpdateRect)
@@ -3534,9 +3607,15 @@
 BOOL16     LocalUnlock16(HLOCAL16);
 BOOL32     LocalUnlock32(HLOCAL32);
 #define    LocalUnlock WINELIB_NAME(LocalUnlock)
+HGLOBAL16  LockSegment16(HGLOBAL16);
+#define    LockSegment32(handle) GlobalFix((HANDLE32)(handle))
+#define    LockSegment WINELIB_NAME(LockSegment)
 BOOL16     LPtoDP16(HDC16,LPPOINT16,INT16);
 BOOL32     LPtoDP32(HDC32,LPPOINT32,INT32);
 #define    LPtoDP WINELIB_NAME(LPtoDP)
+FARPROC16  MakeProcInstance16(FARPROC16,HANDLE16);
+#define    MakeProcInstance32(proc,inst) (proc)
+#define    MakeProcInstance WINELIB_NAME(MakeProcInstance)
 void       MapDialogRect16(HWND16,LPRECT16);
 void       MapDialogRect32(HWND32,LPRECT32);
 #define    MapDialogRect WINELIB_NAME(MapDialogRect)
@@ -3659,6 +3738,10 @@
 DWORD      RegSetValueEx32A(HKEY,LPSTR,DWORD,DWORD,LPBYTE,DWORD);
 DWORD      RegSetValueEx32W(HKEY,LPWSTR,DWORD,DWORD,LPBYTE,DWORD);
 #define    RegSetValueEx WINELIB_NAME_AW(RegSetValueEx)
+BOOL16     RemoveDirectory16(LPCSTR);
+BOOL32     RemoveDirectory32A(LPCSTR);
+BOOL32     RemoveDirectory32W(LPCWSTR);
+#define    RemoveDirectory WINELIB_NAME_AW(RemoveDirectory)
 BOOL16     ScaleViewportExtEx16(HDC16,INT16,INT16,INT16,INT16,LPSIZE16);
 BOOL32     ScaleViewportExtEx32(HDC32,INT32,INT32,INT32,INT32,LPSIZE32);
 #define    ScaleViewportExtEx WINELIB_NAME(ScaleViewportExtEx)
@@ -3690,6 +3773,9 @@
 void       SetDlgItemText32A(HWND32,INT32,LPCSTR);
 void       SetDlgItemText32W(HWND32,INT32,LPCWSTR);
 #define    SetDlgItemText WINELIB_NAME_AW(SetDlgItemText)
+BOOL32     SetEnvironmentVariable32A(LPCSTR,LPCSTR);
+BOOL32     SetEnvironmentVariable32W(LPCWSTR,LPCWSTR);
+#define    SetEnvironmentVariable WINELIB_NAME_AW(SetEnvironmentVariable)
 void       SetInternalWindowPos16(HWND16,UINT16,LPRECT16,LPPOINT16);
 void       SetInternalWindowPos32(HWND32,UINT32,LPRECT32,LPPOINT32);
 #define    SetInternalWindowPos WINELIB_NAME(SetInternalWindowPos)
@@ -3735,6 +3821,9 @@
 BOOL16     UnionRect16(LPRECT16,const RECT16*,const RECT16*);
 BOOL32     UnionRect32(LPRECT32,const RECT32*,const RECT32*);
 #define    UnionRect WINELIB_NAME(UnionRect)
+void       UnlockSegment16(HGLOBAL16);
+#define    UnlockSegment32(handle) GlobalUnfix((HANDLE32)(handle))
+#define    UnlockSegment WINELIB_NAME(UnlockSegment)
 BOOL16     UnregisterClass16(SEGPTR,HINSTANCE16);
 BOOL32     UnregisterClass32A(LPCSTR,HINSTANCE32);
 BOOL32     UnregisterClass32W(LPCWSTR,HINSTANCE32);
@@ -3847,7 +3936,6 @@
 /*typedef int (*MFENUMPROC)(HDC,HANDLETABLE*,METARECORD*,int,LPARAM);*/
 typedef int (*MFENUMPROC)(HDC,void*,void*,int,LPARAM);
 typedef BOOL (*PROPENUMPROC)(HWND,LPCTSTR,HANDLE);
-typedef LRESULT (*WNDENUMPROC)(HWND,LPARAM);
 #else
 typedef SEGPTR DRIVERPROC;
 typedef SEGPTR EDITWORDBREAKPROC;
@@ -3855,12 +3943,9 @@
 typedef SEGPTR GOBJENUMPROC;
 typedef SEGPTR MFENUMPROC;
 typedef SEGPTR PROPENUMPROC;
-typedef SEGPTR WNDENUMPROC;
 #endif
 typedef FARPROC HOOKPROC;
 
-#endif  /* NO_TRANSITION_TYPES */
-
 
 INT        AccessResource(HINSTANCE,HRSRC);
 ATOM       AddAtom(SEGPTR);
@@ -3868,8 +3953,6 @@
 WORD       AllocCStoDSAlias(WORD);
 WORD       AllocDStoCSAlias(WORD);
 HGLOBAL    AllocResource(HINSTANCE,HRSRC,DWORD);
-WORD       AllocSelector(WORD);
-WORD       AllocSelectorArray(WORD);
 BOOL       AnimatePalette(HPALETTE16,UINT,UINT,LPPALETTEENTRY);
 LPSTR      AnsiLower(LPSTR);
 UINT       AnsiLowerBuff(LPSTR,UINT);
@@ -3902,7 +3985,6 @@
 HMETAFILE  CloseMetaFile(HDC);
 void       CloseSound(void);
 BOOL       CloseWindow(HWND);
-INT16      CombineRgn(HRGN32,HRGN32,HRGN32,INT32);
 int        ConvertRequest(HWND,LPKANJISTRUCT);
 #ifdef WINELIB32
 HCURSOR    CopyCursor(HCURSOR); /* Win32 */
@@ -3922,7 +4004,6 @@
 HDC        CreateDC(LPCSTR,LPCSTR,LPCSTR,const DEVMODE*);
 HBRUSH     CreateDIBPatternBrush(HGLOBAL,UINT);
 HBITMAP    CreateDIBitmap(HDC,BITMAPINFOHEADER*,DWORD,LPVOID,BITMAPINFO*,UINT);
-HRGN       CreateEllipticRgn(INT32,INT32,INT32,INT32);
 HFONT      CreateFont(INT,INT,INT,INT,INT,BYTE,BYTE,BYTE,BYTE,BYTE,BYTE,BYTE,BYTE,LPCSTR);
 HFONT      CreateFontIndirect(const LOGFONT16*);
 HBRUSH     CreateHatchBrush(INT,COLORREF);
@@ -3935,8 +4016,6 @@
 HPEN16     CreatePen(INT,INT,COLORREF);
 HPEN16     CreatePenIndirect(const LOGPEN16*);
 HMENU      CreatePopupMenu(void);
-HRGN       CreateRectRgn(INT32,INT32,INT32,INT32);
-HRGN       CreateRoundRectRgn(INT32,INT32,INT32,INT32,INT32,INT32);
 HBRUSH     CreateSolidBrush(COLORREF);
 void       DebugBreak(void);
 DWORD      DefHookProc(short,WORD,DWORD,HHOOK*);
@@ -3969,16 +4048,12 @@
 BOOL       EnableScrollBar(HWND,UINT,UINT);
 BOOL       EnableWindow(HWND,BOOL);
 BOOL       EndDeferWindowPos(HDWP16);
-BOOL       EnumChildWindows(HWND,WNDENUMPROC,LPARAM);
 UINT       EnumClipboardFormats(UINT);
 INT        EnumFontFamilies(HDC,LPCSTR,FONTENUMPROC,LPARAM);
 INT        EnumFonts(HDC,LPCSTR,FONTENUMPROC,LPARAM);
 BOOL       EnumMetaFile(HDC,HMETAFILE,MFENUMPROC,LPARAM);
 INT        EnumObjects(HDC,INT,GOBJENUMPROC,LPARAM);
 INT        EnumProps(HWND,PROPENUMPROC);
-BOOL       EnumTaskWindows(HTASK,WNDENUMPROC,LPARAM);
-BOOL       EnumWindows(WNDENUMPROC,LPARAM);
-BOOL       EqualRgn(HRGN32,HRGN32);
 INT        Escape(HDC,INT,INT,LPCSTR,LPVOID);
 LONG       EscapeCommFunction(int,int);
 int        ExcludeClipRect(HDC,short,short,short,short);
@@ -3986,8 +4061,8 @@
 BOOL       ExitWindows(DWORD,WORD);
 BOOL       ExtFloodFill(HDC,INT,INT,COLORREF,WORD);
 HICON      ExtractIcon(HINSTANCE,LPCSTR,WORD);
-WORD       FarGetOwner(HANDLE);
-void       FarSetOwner(HANDLE,HANDLE);
+HANDLE16   FarGetOwner(HANDLE16);
+void       FarSetOwner(HANDLE16,HANDLE16);
 void       FatalAppExit(UINT,LPCSTR);
 void       FatalExit(int);
 BOOL       FillRgn(HDC,HRGN,HBRUSH);
@@ -3999,10 +4074,7 @@
 int        FlushComm(int,int);
 BOOL       FrameRgn(HDC,HRGN,HBRUSH,int,int);
 void       FreeLibrary(HANDLE);
-BOOL       FreeModule(HANDLE);
-void       FreeProcInstance(FARPROC);
 BOOL       FreeResource(HGLOBAL);
-WORD       FreeSelector(WORD);
 UINT       GDIRealizePalette(HDC);
 HPALETTE16 GDISelectPalette(HDC,HPALETTE16);
 HWND       GetActiveWindow(void);
@@ -4028,10 +4100,8 @@
 UINT       GetCommEventMask(int,int);
 int        GetCommState(int,DCB*);
 HBRUSH     GetControlBrush(HWND,HDC,WORD);
-UINT32     GetCurrentDirectory(UINT32,LPSTR);
 HANDLE     GetCurrentPDB(void);
 DWORD      GetCurrentPosition(HDC);
-HANDLE     GetCurrentTask(void);
 DWORD      GetCurrentTime(void);
 HCURSOR    GetCursor(void);
 HDC        GetDC(HWND);
@@ -4049,12 +4119,11 @@
 HWND       GetDlgItem(HWND,WORD);
 WORD       GetDlgItemInt(HWND,WORD,BOOL*,BOOL);
 WORD       GetDoubleClickTime(void);
-WORD       GetDriveType(INT);
 int        GetEnvironment(LPSTR,LPSTR,WORD);
 HMODULE    GetExePtr(HANDLE);
 HWND       GetFocus(void);
 DWORD      GetFreeSpace(UINT16);
-DWORD      GetHeapSpaces(HMODULE);
+DWORD      GetHeapSpaces(HMODULE16);
 BOOL       GetInputState(void);
 int        GetInstanceData(HANDLE,WORD,int);
 int        GetKBCodePage(void);
@@ -4079,7 +4148,7 @@
 HANDLE     GetMetaFile(LPSTR);
 HANDLE     GetMetaFileBits(HANDLE);
 int        GetModuleFileName(HANDLE,LPSTR,short);
-HANDLE     GetModuleHandle(LPCSTR);
+HMODULE16  GetModuleHandle(LPCSTR);
 int        GetModuleUsage(HANDLE);
 FARPROC    GetMouseEventProc(void);
 DWORD      GetNearestColor(HDC,DWORD);
@@ -4113,7 +4182,6 @@
 HMENU      GetSubMenu(HMENU,short);
 COLORREF   GetSysColor(short);
 HWND       GetSysModalWindow(void);
-UINT       GetSystemDirectory(LPSTR,UINT);
 HMENU      GetSystemMenu(HWND,BOOL);
 int        GetSystemMetrics(WORD);
 WORD       GetSystemPaletteEntries(HDC,WORD,WORD,LPPALETTEENTRY);
@@ -4130,7 +4198,6 @@
 COLORREF   GetTextColor(HDC);
 DWORD      GetTextExtent(HDC,LPCSTR,short);
 INT        GetTextFace(HDC,INT,LPSTR);
-BOOL       GetTextMetrics(HDC,LPTEXTMETRIC16);
 LPINT16    GetThresholdEvent(void);
 int        GetThresholdStatus(void);
 DWORD      GetTickCount(void);
@@ -4157,7 +4224,7 @@
 void       GlobalNotify(FARPROC);
 WORD       GlobalPageLock(HGLOBAL16);
 WORD       GlobalPageUnlock(HGLOBAL16);
-BOOL       GlobalUnWire(HGLOBAL16);
+BOOL16     GlobalUnWire(HGLOBAL16);
 void       GlobalUnfix(HGLOBAL16);
 SEGPTR     GlobalWire(HGLOBAL16);
 BOOL       GrayString(HDC,HBRUSH,FARPROC,LPARAM,INT,INT,INT,INT,INT);
@@ -4208,12 +4275,9 @@
 HANDLE     LoadModule(LPCSTR,LPVOID);
 HGLOBAL    LoadResource(HINSTANCE,HRSRC);
 int        LoadString(HANDLE,WORD,LPSTR,int);
-BOOL       LocalInit(HANDLE,WORD,WORD);
 FARPROC    LocalNotify(FARPROC);
 LPVOID     LockResource(HGLOBAL);
-HGLOBAL    LockSegment(HGLOBAL);
 HMENU      LookupMenuHandle(HMENU,INT);
-FARPROC    MakeProcInstance(FARPROC,HANDLE);
 WORD       MapVirtualKey(WORD,WORD);
 void       MessageBeep(WORD);
 int        MessageBox(HWND,LPCSTR,LPCSTR,WORD);
@@ -4247,7 +4311,6 @@
 void       ProfSetup(int,int);
 void       ProfStart(void);
 void       ProfStop(void);
-BOOL       PtInRegion(HRGN32,INT32,INT32);
 BOOL       PtVisible(HDC,short,short);
 int        ReadComm(int,LPSTR,int);
 WORD       RealizeDefaultPalette(HDC);
@@ -4295,12 +4358,10 @@
 void       SetCursorPos(short,short);
 BOOL       SetDCHook(HDC,FARPROC16,DWORD);
 void       SetDCState(HDC,HDC);
-int        SetDIBits(HDC,HANDLE,WORD,WORD,LPSTR,LPBITMAPINFO,WORD);
-int        SetDIBitsToDevice(HDC,short,short,WORD,WORD,WORD,WORD,WORD,WORD,LPSTR,LPBITMAPINFO,WORD);
 BOOL       SetDeskPattern(void);
 BOOL       SetDeskWallPaper(LPCSTR);
 void       SetDoubleClickTime(WORD);
-int        SetEnvironment(LPSTR,LPSTR,WORD);
+int        SetEnvironment(LPCSTR,LPCSTR,WORD);
 UINT       SetErrorMode(UINT);
 HWND       SetFocus(HWND);
 WORD       SetHandleCount(WORD);
@@ -4318,7 +4379,6 @@
 WORD       SetPolyFillMode(HDC,WORD);
 BOOL       SetProp(HWND,SEGPTR,HANDLE);
 WORD       SetROP2(HDC,WORD);
-void       SetRectRgn(HRGN32,INT32,INT32,INT32,INT32);
 WORD       SetRelAbs(HDC,WORD);
 FARPROC    SetResourceHandler(HANDLE,LPSTR,FARPROC);
 int        SetScrollPos(HWND,int,int,BOOL);
@@ -4378,7 +4438,6 @@
 int        UngetCommChar(int,char);
 BOOL       UnhookWindowsHook(short,FARPROC);
 BOOL       UnhookWindowsHookEx(HHOOK);
-void       UnlockSegment(HGLOBAL);
 BOOL       UnrealizeObject(HBRUSH);
 int        UpdateColors(HDC);
 void       UpdateWindow(HWND32);
@@ -4408,6 +4467,7 @@
 INT        _lread(HFILE,SEGPTR,WORD);
 INT        _lwrite(HFILE,LPCSTR,WORD);
 
+#endif  /* NO_TRANSITION_TYPES */
 
 #ifdef WINELIB
 #define WINELIB_UNIMP(x) fprintf (stderr, "WineLib: Unimplemented %s\n", x)
diff --git a/include/wine.h b/include/wine.h
index af1be18..bcfffca 100644
--- a/include/wine.h
+++ b/include/wine.h
@@ -9,8 +9,8 @@
 
 #ifndef WINELIB
 
-#if defined ( linux) 
-struct sigcontext_struct
+#ifdef linux
+typedef struct
 {
 	unsigned short sc_gs, __gsh;
 	unsigned short sc_fs, __fsh;
@@ -34,17 +34,17 @@
 	unsigned long i387;
 	unsigned long oldmask;
 	unsigned long cr2;
-};
+} SIGCONTEXT;
 #define WINE_DATA_SELECTOR 0x2b
 #define WINE_CODE_SELECTOR 0x23
 #endif  /* linux */
 
 #ifdef __NetBSD__
 #include <signal.h>
-#define sigcontext_struct sigcontext
+typedef struct sigcontext SIGCONTEXT;
 #define WINE_DATA_SELECTOR 0x1f
 #define WINE_CODE_SELECTOR 0x17
-#endif
+#endif  /* NetBSD */
 
 #if defined(__svr4__) || defined(_SCO_DS)
 #include <signal.h>
@@ -52,17 +52,23 @@
 #include <sys/regset.h>
 #endif
 #include <sys/ucontext.h>
-#define sigcontext_struct ucontext
+typedef struct ucontext SIGCONTEXT;
 #define WINE_DATA_SELECTOR 0x1f
 #define WINE_CODE_SELECTOR 0x17
-#endif
+#endif  /* svr4 || SCO_DS */
 
 #ifdef __FreeBSD__
 #include <signal.h>
-#define sigcontext_struct sigcontext
+typedef struct sigcontext SIGCONTEXT;
 #define WINE_DATA_SELECTOR 0x27
 #define WINE_CODE_SELECTOR 0x1f
-#endif
+#endif  /* FreeBSD */
+
+#else  /* WINELIB */
+
+typedef void SIGCONTEXT;
+#define WINE_DATA_SELECTOR 0x00
+#define WINE_CODE_SELECTOR 0x00
 
 #endif  /* WINELIB */
 
diff --git a/include/winpos.h b/include/winpos.h
index 02b2a92..fed1e37 100644
--- a/include/winpos.h
+++ b/include/winpos.h
@@ -25,13 +25,6 @@
     WINDOWPOS16 winPos[1];
 } DWP;
 
-typedef struct
-{
-  HTASK        hWindowTask;
-  HTASK        hTaskSendTo;
-  BOOL         wFlag;
-} ACTIVATESTRUCT, *LPACTIVATESTRUCT;
-
 extern void WINPOS_FindIconPos( HWND hwnd );
 extern BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus);
 extern BOOL WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg );
diff --git a/include/winproc.h b/include/winproc.h
index 7f799e1..fd9b22a 100644
--- a/include/winproc.h
+++ b/include/winproc.h
@@ -17,11 +17,13 @@
     WIN_PROC_32W
 } WINDOWPROCTYPE;
 
-extern HANDLE32 WINPROC_AllocWinProc( UINT32 func, WINDOWPROCTYPE type );
-extern HANDLE32 WINPROC_CopyWinProc( HANDLE32 handle );
-extern void WINPROC_FreeWinProc( HANDLE32 handle );
-extern WINDOWPROCTYPE WINPROC_GetWinProcType( HANDLE32 handle );
-extern WNDPROC16 WINPROC_GetFunc16( HANDLE32 handle );
-extern WNDPROC32 WINPROC_GetFunc32( HANDLE32 handle );
+typedef void *HWINDOWPROC;  /* Really a pointer to a WINDOWPROC */
+
+extern BOOL32 WINPROC_Init(void);
+extern WNDPROC16 WINPROC_GetProc( HWINDOWPROC proc, WINDOWPROCTYPE type );
+extern BOOL32 WINPROC_SetProc( HWINDOWPROC *pFirst, WNDPROC16 func,
+                               WINDOWPROCTYPE type );
+extern void WINPROC_FreeProc( HWINDOWPROC proc );
+extern WINDOWPROCTYPE WINPROC_GetProcType( HWINDOWPROC proc );
 
 #endif  /* __WINE_WINPROC_H */
diff --git a/include/wintypes.h b/include/wintypes.h
index 33bcebd..4f6c53e 100644
--- a/include/wintypes.h
+++ b/include/wintypes.h
@@ -154,11 +154,13 @@
 #ifdef WINELIB
 typedef LRESULT (*DLGPROC16)(HWND16,UINT16,WPARAM16,LPARAM);
 typedef LRESULT (*FARPROC16)();
+typedef LRESULT (*WNDENUMPROC16)(HWND16,LPARAM);
 typedef LRESULT (*WNDPROC16)(HWND16,UINT16,WPARAM16,LPARAM);
 #else
 /* Function pointers are SEGPTR in Win16 */
 typedef SEGPTR DLGPROC16;
 typedef SEGPTR FARPROC16;
+typedef SEGPTR WNDENUMPROC16;
 typedef SEGPTR WNDPROC16;
 #endif
 
@@ -166,6 +168,7 @@
 
 typedef LRESULT (*DLGPROC32)(HWND32,UINT32,WPARAM32,LPARAM);
 typedef LRESULT (*FARPROC32)();
+typedef LRESULT (*WNDENUMPROC32)(HWND32,LPARAM);
 typedef LRESULT (*WNDPROC32)(HWND32,UINT32,WPARAM32,LPARAM);
 
 /* TCHAR data types definitions for Winelib. */
@@ -226,7 +229,9 @@
 DECL_WINELIB_TYPE(HWAVEOUT);
 DECL_WINELIB_TYPE(HWND);
 
+DECL_WINELIB_TYPE(DLGPROC);
 DECL_WINELIB_TYPE(FARPROC);
+DECL_WINELIB_TYPE(WNDENUMPROC);
 DECL_WINELIB_TYPE(WNDPROC);
 
 /* Misc. constants. */
diff --git a/library/miscstubs.c b/library/miscstubs.c
index fa59b22..c6b61bf 100644
--- a/library/miscstubs.c
+++ b/library/miscstubs.c
@@ -43,7 +43,6 @@
 
 WORD CallTo16_word_ ( FARPROC func, WORD arg ) { return func(arg); }
 
-extern LRESULT ACTIVATEAPP_callback(HWND,UINT,WPARAM,LPARAM);
 extern LRESULT AboutDlgProc(HWND,UINT,WPARAM,LPARAM);
 extern LRESULT CARET_Callback(HWND,UINT,WPARAM,LPARAM);
 extern LRESULT ColorDlgProc(HWND,UINT,WPARAM,LPARAM);
@@ -78,7 +77,6 @@
 WNDPROC MODULE_GetWndProcEntry16( char *name )
 {
 #define MAP_STR_TO_PROC(str,proc) if(!strcmp(name,str))return proc
-  MAP_STR_TO_PROC("ActivateAppProc",ACTIVATEAPP_callback);
   MAP_STR_TO_PROC("AboutDlgProc",AboutDlgProc);
   MAP_STR_TO_PROC("CARET_Callback",CARET_Callback);
   MAP_STR_TO_PROC("ColorDlgProc",ColorDlgProc);
diff --git a/loader/builtin.c b/loader/builtin.c
index 7cfb347..0d90272 100644
--- a/loader/builtin.c
+++ b/loader/builtin.c
@@ -105,6 +105,7 @@
 extern const DLL_DESCRIPTOR SHELL32_Descriptor;
 extern const DLL_DESCRIPTOR USER32_Descriptor;
 extern const DLL_DESCRIPTOR VERSION_Descriptor;
+extern const DLL_DESCRIPTOR WINMM_Descriptor;
 extern const DLL_DESCRIPTOR WINSPOOL_Descriptor;
 extern const DLL_DESCRIPTOR WSOCK32_Descriptor;
 
@@ -154,6 +155,7 @@
     { &SHELL32_Descriptor,  0 },
     { &USER32_Descriptor,   0 },
     { &VERSION_Descriptor,  0 },
+    { &WINMM_Descriptor,    0 },
     { &WINSPOOL_Descriptor, 0 },
     { &WSOCK32_Descriptor,  0 },
     /* Last entry */
@@ -166,7 +168,7 @@
  *
  * Load all built-in modules marked as 'always used'.
  */
-BOOL BUILTIN_Init(void)
+BOOL16 BUILTIN_Init(void)
 {
     BUILTIN_DLL *dll;
     NE_MODULE *pModule;
@@ -196,7 +198,7 @@
  * Load a built-in module. If the 'force' parameter is FALSE, we only
  * load the module if it has not been disabled via the -dll option.
  */
-HMODULE BUILTIN_LoadModule( LPCSTR name, BOOL force )
+HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL16 force )
 {
     HMODULE hModule;
     NE_MODULE *pModule;
@@ -377,7 +379,7 @@
  *
  * Set runtime DLL usage flags
  */
-BOOL BUILTIN_ParseDLLOptions( const char *str )
+BOOL16 BUILTIN_ParseDLLOptions( const char *str )
 {
     BUILTIN_DLL *dll;
     const char *p;
diff --git a/loader/main.c b/loader/main.c
index bc3ac02..02917c4 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -36,6 +36,7 @@
 #include "dce.h"
 #include "pe_image.h"
 #include "shell.h"
+#include "winproc.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -117,7 +118,10 @@
 
       /* Create the DCEs */
     DCE_Init();
-    
+
+    /* Initialize window procedures */
+    if (!WINPROC_Init()) return 0;
+
       /* Initialize dialog manager */
     if (!DIALOG_Init()) return 0;
 
diff --git a/loader/module.c b/loader/module.c
index d394aa3..c643c7d 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -30,8 +30,8 @@
 
 extern HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
 
-static HMODULE hFirstModule = 0;
-static HMODULE hCachedModule = 0;  /* Module cached by MODULE_OpenFile */
+static HMODULE16 hFirstModule = 0;
+static HMODULE16 hCachedModule = 0;  /* Module cached by MODULE_OpenFile */
 
 #ifndef WINELIB
 static HANDLE hInitialStack32 = 0;
@@ -41,7 +41,7 @@
 /***********************************************************************
  *           MODULE_GetPtr
  */
-NE_MODULE *MODULE_GetPtr( HMODULE hModule )
+NE_MODULE *MODULE_GetPtr( HMODULE16 hModule )
 {
     NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule );
     if (!pModule || (pModule->magic != NE_SIGNATURE) ||
@@ -53,7 +53,7 @@
 /***********************************************************************
  *           MODULE_DumpModule
  */
-void MODULE_DumpModule( HMODULE hmodule )
+void MODULE_DumpModule( HMODULE16 hmodule )
 {
     int i, ordinal;
     SEGTABLEENTRY *pSeg;
@@ -134,9 +134,8 @@
         pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
         for (i = 0; i < pModule->modref_count; i++, pword++)
         {
-            char *name = (char *)pModule + pModule->import_table + *pword;
-            printf( "%d: %04x -> '%*.*s'\n",
-                    i, *pword, *name, *name, name + 1 );
+	    printf( "%d: %04x -> '%s'\n", i, *pword,
+		    MODULE_GetModuleName(*pword));
         }
     }
     else printf( "None\n" );
@@ -217,7 +216,7 @@
 /***********************************************************************
  *           MODULE_OpenFile
  */
-int MODULE_OpenFile( HMODULE hModule )
+int MODULE_OpenFile( HMODULE16 hModule )
 {
     NE_MODULE *pModule;
     char *name;
@@ -288,7 +287,7 @@
  *           MODULE_CreateSegments
  */
 #ifndef WINELIB32
-static BOOL MODULE_CreateSegments( HMODULE hModule )
+static BOOL MODULE_CreateSegments( HMODULE16 hModule )
 {
     SEGTABLEENTRY *pSegment;
     NE_MODULE *pModule;
@@ -321,7 +320,7 @@
  *           MODULE_GetInstance
  */
 #ifndef WINELIB32
-HINSTANCE MODULE_GetInstance( HMODULE hModule )
+HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule )
 {
     SEGTABLEENTRY *pSegment;
     NE_MODULE *pModule;
@@ -339,7 +338,7 @@
 /***********************************************************************
  *           MODULE_CreateInstance
  */
-HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
+HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
 {
     SEGTABLEENTRY *pSegment;
     NE_MODULE *pModule;
@@ -373,12 +372,12 @@
 /***********************************************************************
  *           MODULE_LoadExeHeader
  */
-static HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
+static HMODULE16 MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
 {
     struct mz_header_s mz_header;
     struct ne_header_s ne_header;
     int size;
-    HMODULE hModule;
+    HMODULE16 hModule;
     NE_MODULE *pModule;
     BYTE *pData;
     char *buffer, *fastload = NULL;
@@ -394,14 +393,15 @@
 
     _llseek( hFile, 0, SEEK_SET );
     if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
-        (mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11;  /* invalid exe */
+        (mz_header.mz_magic != MZ_SIGNATURE))
+        return (HMODULE16)11;  /* invalid exe */
 
     _llseek( hFile, mz_header.ne_offset, SEEK_SET );
     if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
-        return (HMODULE)11;  /* invalid exe */
+        return (HMODULE16)11;  /* invalid exe */
 
-    if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21;  /* win32 exe */
-    if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE)11;  /* invalid exe */
+    if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE16)21;  /* win32 exe */
+    if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE16)11;  /* invalid exe */
 
     /* We now have a valid NE header */
 
@@ -422,7 +422,7 @@
            ne_header.entry_tab_length;
 
     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
-    if (!hModule) return (HMODULE)11;  /* invalid exe */
+    if (!hModule) return (HMODULE16)11;  /* invalid exe */
     FarSetOwner( hModule, hModule );
     pModule = (NE_MODULE *)GlobalLock16( hModule );
     memcpy( pModule, &ne_header, sizeof(ne_header) );
@@ -474,7 +474,7 @@
 
         if (!READ( ne_header.segment_tab_offset,
              ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
-             buffer )) return (HMODULE)11;  /* invalid exe */
+             buffer )) return (HMODULE16)11;  /* invalid exe */
         pSeg = (struct ne_segment_table_entry_s *)buffer;
         for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
         {
@@ -486,7 +486,7 @@
     else
     {
         GlobalFree16( hModule );
-        return (HMODULE)11;  /* invalid exe */
+        return (HMODULE16)11;  /* invalid exe */
     }
 
     /* Get the resource table */
@@ -496,7 +496,7 @@
         pModule->res_table = (int)pData - (int)pModule;
         if (!READ(ne_header.resource_tab_offset,
                   ne_header.rname_tab_offset - ne_header.resource_tab_offset,
-                  pData )) return (HMODULE)11;  /* invalid exe */
+                  pData )) return (HMODULE16)11;  /* invalid exe */
         pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
     }
     else pModule->res_table = 0;  /* No resource table */
@@ -509,7 +509,7 @@
                pData ))
     {
         GlobalFree16( hModule );
-        return (HMODULE)11;  /* invalid exe */
+        return (HMODULE16)11;  /* invalid exe */
     }
     pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
 
@@ -520,7 +520,7 @@
         pModule->modref_table = (int)pData - (int)pModule;
         if (!READ( ne_header.moduleref_tab_offset,
                   ne_header.n_mod_ref_tab * sizeof(WORD),
-                  pData )) return (HMODULE)11;  /* invalid exe */
+                  pData )) return (HMODULE16)11;  /* invalid exe */
         pData += ne_header.n_mod_ref_tab * sizeof(WORD);
     }
     else pModule->modref_table = 0;  /* No module references */
@@ -533,7 +533,7 @@
                pData ))
     {
         GlobalFree16( hModule );
-        return (HMODULE)11;  /* invalid exe */
+        return (HMODULE16)11;  /* invalid exe */
     }
     pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
 
@@ -545,7 +545,7 @@
                pData ))
     {
         GlobalFree16( hModule );
-        return (HMODULE)11;  /* invalid exe */
+        return (HMODULE16)11;  /* invalid exe */
     }
     pData += ne_header.entry_tab_length;
 
@@ -558,7 +558,7 @@
         if (!pModule->nrname_handle)
         {
             GlobalFree16( hModule );
-            return (HMODULE)11;  /* invalid exe */
+            return (HMODULE16)11;  /* invalid exe */
         }
         buffer = GlobalLock16( pModule->nrname_handle );
         _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
@@ -567,7 +567,7 @@
         {
             GlobalFree16( pModule->nrname_handle );
             GlobalFree16( hModule );
-            return (HMODULE)11;  /* invalid exe */
+            return (HMODULE16)11;  /* invalid exe */
         }
     }
     else pModule->nrname_handle = 0;
@@ -577,13 +577,13 @@
     if (pModule->modref_count)
     {
         pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
-                                    (pModule->modref_count+1)*sizeof(HMODULE),
+                                    (pModule->modref_count+1)*sizeof(HMODULE16),
                                     hModule, FALSE, FALSE, FALSE );
         if (!pModule->dlls_to_init)
         {
             if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
             GlobalFree16( hModule );
-            return (HMODULE)11;  /* invalid exe */
+            return (HMODULE16)11;  /* invalid exe */
         }
     }
     else pModule->dlls_to_init = 0;
@@ -599,7 +599,7 @@
  *
  * Lookup the ordinal for a given name.
  */
-WORD MODULE_GetOrdinal( HMODULE hModule, const char *name )
+WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name )
 {
     char buffer[256], *cpnt;
     BYTE len;
@@ -663,7 +663,7 @@
  *
  * Return the entry point for a given ordinal.
  */
-SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
+SEGPTR MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
 {
     NE_MODULE *pModule;
     WORD curOrdinal = 1;
@@ -714,7 +714,7 @@
  * Change the value of an entry point. Use with caution!
  * It can only change the offset value, not the selector.
  */
-BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset )
+BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
 {
     NE_MODULE *pModule;
     WORD curOrdinal = 1;
@@ -763,7 +763,7 @@
 {
     WORD ordinal;
     FARPROC16 ret;
-    static HMODULE hModule = 0;
+    static HMODULE16 hModule = 0;
 
     if (!hModule) hModule = GetModuleHandle( "WPROCS" );
     ordinal = MODULE_GetOrdinal( hModule, name );
@@ -777,7 +777,7 @@
 /***********************************************************************
  *           MODULE_GetModuleName
  */
-LPSTR MODULE_GetModuleName( HMODULE hModule )
+LPSTR MODULE_GetModuleName( HMODULE16 hModule )
 {
     NE_MODULE *pModule;
     BYTE *p, len;
@@ -807,9 +807,9 @@
  *
  * Find a module from a path name.
  */
-HMODULE MODULE_FindModule( LPCSTR path )
+HMODULE16 MODULE_FindModule( LPCSTR path )
 {
-    HMODULE hModule = hFirstModule;
+    HMODULE16 hModule = hFirstModule;
     LPCSTR filename, dotptr, modulepath, modulename;
     BYTE len, *name_table;
 
@@ -839,23 +839,44 @@
 
 
 /**********************************************************************
+ *	    MODULE_CallWEP
+ *
+ * Call a DLL's WEP, allowing it to shut down.
+ * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
+ */
+static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
+{
+    FARPROC16 WEP = (FARPROC16)0;
+    WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
+
+    if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
+    if (!WEP)
+    {
+	dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
+	return FALSE;
+    }
+    return CallWindowsExitProc( WEP, WEP_FREE_DLL );
+}
+
+
+/**********************************************************************
  *	    MODULE_FreeModule
  *
  * Remove a module from memory.
  */
-static void MODULE_FreeModule( HMODULE hModule )
+static void MODULE_FreeModule( HMODULE16 hModule )
 {
-    HMODULE *hPrevModule;
+    HMODULE16 *hPrevModule;
     NE_MODULE *pModule;
     SEGTABLEENTRY *pSegment;
-    HMODULE *pModRef;
+    HMODULE16 *pModRef;
     int i;
 
     if (!(pModule = MODULE_GetPtr( hModule ))) return;
     if (pModule->flags & NE_FFLAGS_BUILTIN)
         return;  /* Can't free built-in module */
 
-    /* FIXME: should call the exit code for the library here */
+    if (pModule->flags & NE_FFLAGS_LIBMODULE) MODULE_CallWEP( hModule );
 
     /* Free the objects owned by the module */
 
@@ -885,10 +906,10 @@
 
       /* Free the referenced modules */
 
-    pModRef = (HMODULE*)NE_MODULE_TABLE( pModule );
+    pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
     for (i = 0; i < pModule->modref_count; i++, pModRef++)
     {
-        FreeModule( *pModRef );
+        FreeModule16( *pModRef );
     }
 
       /* Free the module storage */
@@ -908,7 +929,7 @@
  */
 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
 {
-    HMODULE hModule;
+    HMODULE16 hModule;
     HANDLE hInstance, hPrevInstance;
     NE_MODULE *pModule;
     LOADPARAMS *params = (LOADPARAMS *)paramBlock;
@@ -977,7 +998,7 @@
             {
                 /* If the DLL is not loaded yet, load it and store */
                 /* its handle in the list of DLLs to initialize.   */
-                HMODULE hDLL;
+                HMODULE16 hDLL;
 
                 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2)  /* file not found */
                 {
@@ -1015,7 +1036,7 @@
 		SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
 		SELFLOADHEADER *selfloadheader;
                 STACK16FRAME *stack16Top;
-		HMODULE hselfload = GetModuleHandle("WPROCS");
+		HMODULE16 hselfload = GetModuleHandle("WPROCS");
 		WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
 		fprintf (stderr, "Warning:  %*.*s is a self-loading module\n"
                                 "Support for self-loading modules is very experimental\n",
@@ -1138,16 +1159,16 @@
 
 
 /**********************************************************************
- *	    FreeModule    (KERNEL.46)
+ *	    FreeModule16    (KERNEL.46)
  */
-BOOL FreeModule( HANDLE hModule )
+BOOL16 FreeModule16( HMODULE16 hModule )
 {
     NE_MODULE *pModule;
 
     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
     if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
 
-    dprintf_module( stddeb, "FreeModule: %s count %d\n", 
+    dprintf_module( stddeb, "FreeModule16: %s count %d\n", 
 		    MODULE_GetModuleName(hModule), pModule->count );
     if (--pModule->count == 0) MODULE_FreeModule( hModule );
     return TRUE;
@@ -1157,13 +1178,13 @@
 /**********************************************************************
  *	    GetModuleHandle    (KERNEL.47)
  */
-HMODULE WIN16_GetModuleHandle( SEGPTR name )
+HMODULE16 WIN16_GetModuleHandle( SEGPTR name )
 {
     if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
     return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
 }
 
-HMODULE GetModuleHandle( LPCSTR name )
+HMODULE16 GetModuleHandle( LPCSTR name )
 {
     return MODULE_FindModule( name );
 }
@@ -1237,7 +1258,7 @@
 void FreeLibrary( HANDLE handle )
 {
     dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
-    FreeModule( handle );
+    FreeModule16( handle );
 }
 
 
@@ -1416,7 +1437,7 @@
 /**********************************************************************
  *	    GetExpWinVer    (KERNEL.167)
  */
-WORD GetExpWinVer( HMODULE hModule )
+WORD GetExpWinVer( HMODULE16 hModule )
 {
     NE_MODULE *pModule = MODULE_GetPtr( hModule );
     return pModule ? pModule->expected_version : 0;
@@ -1426,7 +1447,7 @@
 /**********************************************************************
  *	    ModuleFirst    (TOOLHELP.59)
  */
-BOOL ModuleFirst( MODULEENTRY *lpme )
+BOOL16 ModuleFirst( MODULEENTRY *lpme )
 {
     lpme->wNext = hFirstModule;
     return ModuleNext( lpme );
@@ -1436,7 +1457,7 @@
 /**********************************************************************
  *	    ModuleNext    (TOOLHELP.60)
  */
-BOOL ModuleNext( MODULEENTRY *lpme )
+BOOL16 ModuleNext( MODULEENTRY *lpme )
 {
     NE_MODULE *pModule;
 
@@ -1457,7 +1478,7 @@
 /**********************************************************************
  *	    ModuleFindName    (TOOLHELP.61)
  */
-BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
+BOOL16 ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
 {
     lpme->wNext = GetModuleHandle( name );
     return ModuleNext( lpme );
@@ -1467,7 +1488,7 @@
 /**********************************************************************
  *	    ModuleFindHandle    (TOOLHELP.62)
  */
-BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
+BOOL16 ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
 {
     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
     lpme->wNext = hModule;
diff --git a/loader/pe_image.c b/loader/pe_image.c
index e97df39..296560a 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -533,7 +533,7 @@
 }
 
 HINSTANCE MODULE_CreateInstance(HMODULE hModule,LOADPARAMS *params);
-void InitTask(struct sigcontext_struct context);
+void InitTask(SIGCONTEXT context);
 
 HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params )
 {
@@ -604,7 +604,7 @@
 	pSegment->selector=(void*)cts;
 	pModule->ip=0;
 #else
-	pSegment->selector=cts>>16;
+	pSegment->selector=cts>>16;  /* FIXME!! */
 	pModule->ip=cts & 0xFFFF;
 #endif
 	pSegment++;
@@ -644,7 +644,7 @@
 int USER_InitApp(HINSTANCE hInstance);
 void PE_InitTEB(int hTEB);
 
-void PE_Win32CallToStart(struct sigcontext_struct context)
+void PE_Win32CallToStart(SIGCONTEXT context)
 {
     int fs;
     HMODULE hModule;
diff --git a/loader/signal.c b/loader/signal.c
index 0d200ca..0aea7fe 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -54,13 +54,13 @@
  * SIGALRM handler.
  */
 #ifdef linux
-static void wine_timer(int signal, struct sigcontext_struct context_struct)
+static void wine_timer(int signal, SIGCONTEXT context_struct)
 {
 #elif defined(__svr4__)
-static void wine_timer(int signal, void *siginfo, ucontext_t *context)
+static void wine_timer(int signal, void *siginfo, SIGCONTEXT *context)
 {
 #else
-static void wine_timer(int signal, int code, struct sigcontext *context)
+static void wine_timer(int signal, int code, SIGCONTEXT *context)
 {
 #endif
     /* Should do real-time timers here */
@@ -75,14 +75,14 @@
  * SIGTRAP handler.
  */
 #ifdef linux
-static void SIGNAL_trap(int signal, struct sigcontext_struct context_struct)
+static void SIGNAL_trap(int signal, SIGCONTEXT context_struct)
 {
-    struct sigcontext_struct *context = &context_struct;
+    SIGCONTEXT *context = &context_struct;
 #elif defined(__svr4__) || defined(_SCO_DS)
-static void SIGNAL_trap(int signal, void *siginfo, ucontext_t *context)
+static void SIGNAL_trap(int signal, void *siginfo, SIGCONTEXT *context)
 {
 #else
-static void SIGNAL_trap(int signal, int code, struct sigcontext *context)
+static void SIGNAL_trap(int signal, int code, SIGCONTEXT *context)
 {
 #endif
     wine_debug( signal, context );  /* Enter our debugger */
@@ -95,14 +95,14 @@
  * Segfault handler.
  */
 #ifdef linux
-static void SIGNAL_fault(int signal, struct sigcontext_struct context_struct)
+static void SIGNAL_fault(int signal, SIGCONTEXT context_struct)
 {
-    struct sigcontext_struct *context = &context_struct;
+    SIGCONTEXT *context = &context_struct;
 #elif defined(__svr4__) || defined(_SCO_DS)
-static void SIGNAL_fault(int signal, void *siginfo, ucontext_t *context)
+static void SIGNAL_fault(int signal, void *siginfo, SIGCONTEXT *context)
 {
 #else
-static void SIGNAL_fault(int signal, int code, struct sigcontext *context)
+static void SIGNAL_fault(int signal, int code, SIGCONTEXT *context)
 {
 #endif
     if (CS_reg(context) == WINE_CODE_SELECTOR)
diff --git a/loader/task.c b/loader/task.c
index 48bf3ee..43c7d87 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -22,6 +22,8 @@
 #include "module.h"
 #include "neexe.h"
 #include "options.h"
+#include "peexe.h"
+#include "pe_image.h"
 #include "queue.h"
 #include "toolhelp.h"
 #include "stddebug.h"
@@ -116,7 +118,7 @@
         winpathlen += len + 1;
     }
     if (!winpathlen) winpathlen = 1;
-    sysdirlen  = GetSystemDirectory( NULL, 0 ) + 1;
+    sysdirlen  = GetSystemDirectory32A( NULL, 0 ) + 1;
     initial_size = 5 + winpathlen +           /* PATH=xxxx */
                    1 +                        /* BYTE 0 at end */
                    sizeof(WORD) +             /* WORD 1 */
@@ -176,7 +178,7 @@
     *p++ = '\0';
     PUT_WORD( p, 1 );
     p += sizeof(WORD);
-    GetSystemDirectory( p, sysdirlen );
+    GetSystemDirectory32A( p, sysdirlen );
     strcat( p, "\\" );
     strcat( p, program_name );
 
@@ -554,9 +556,19 @@
 
     if (Options.debug)
     {
-        DBG_ADDR addr = { pSegTable[pModule->cs-1].selector, pModule->ip };
-        fprintf( stderr, "Task '%s': ", name );
-        DEBUG_AddBreakpoint( &addr );
+        if (pModule->flags & NE_FFLAGS_WIN32)
+        {
+            DBG_ADDR addr = { 0, pModule->pe_module->load_addr + 
+                              pModule->pe_module->pe_header->opt_coff.AddressOfEntryPoint };
+            fprintf( stderr, "Win32 task '%s': ", name );
+            DEBUG_AddBreakpoint( &addr );
+        }
+        else
+        {
+            DBG_ADDR addr = { pSegTable[pModule->cs-1].selector, pModule->ip };
+            fprintf( stderr, "Win16 task '%s': ", name );
+            DEBUG_AddBreakpoint( &addr );
+        }
     }
 #endif
 
@@ -584,7 +596,7 @@
 
     /* Free the task module */
 
-    FreeModule( pTask->hModule );
+    FreeModule16( pTask->hModule );
 
     /* Close all open files of this task */
 
@@ -619,6 +631,7 @@
     extern void EXEC_ExitWindows( int retCode );
 
     TDB* pTask = (TDB*) GlobalLock16( hCurrentTask );
+    if (!pTask) EXEC_ExitWindows(0);  /* No current task yet */
 
     /* Perform USER cleanup */
 
@@ -753,7 +766,7 @@
 #ifdef WINELIB
 void InitTask(void)
 #else
-void InitTask( struct sigcontext_struct context )
+void InitTask( SIGCONTEXT context )
 #endif
 {
     static int firstTask = 1;
@@ -959,12 +972,12 @@
 
 
 /***********************************************************************
- *           MakeProcInstance  (KERNEL.51)
+ *           MakeProcInstance16  (KERNEL.51)
  */
-FARPROC MakeProcInstance( FARPROC func, HANDLE hInstance )
+FARPROC16 MakeProcInstance16( FARPROC16 func, HANDLE16 hInstance )
 {
-#ifdef WINELIB32
-    return func; /* func can be called directly in Win32 */
+#ifdef WINELIB
+    return func; /* func can be called directly in Winelib */
 #else
     BYTE *thunk;
     SEGPTR thunkaddr;
@@ -987,11 +1000,11 @@
 
 
 /***********************************************************************
- *           FreeProcInstance  (KERNEL.52)
+ *           FreeProcInstance16  (KERNEL.52)
  */
-void FreeProcInstance( FARPROC func )
+void FreeProcInstance16( FARPROC16 func )
 {
-#ifndef WINELIB32
+#ifndef WINELIB
     dprintf_task( stddeb, "FreeProcInstance(%08lx)\n", (DWORD)func );
     TASK_FreeThunk( hCurrentTask, (SEGPTR)func );
 #endif
@@ -1060,7 +1073,7 @@
  *           GetTaskQueueDS  (KERNEL.118)
  */
 #ifndef WINELIB
-void GetTaskQueueDS( struct sigcontext_struct context )
+void GetTaskQueueDS( SIGCONTEXT context )
 {
     DS_reg(&context) = GlobalHandleToSel( GetTaskQueue(0) );
 }
@@ -1071,7 +1084,7 @@
  *           GetTaskQueueES  (KERNEL.119)
  */
 #ifndef WINELIB
-void GetTaskQueueES( struct sigcontext_struct context )
+void GetTaskQueueES( SIGCONTEXT context )
 {
     ES_reg(&context) = GlobalHandleToSel( GetTaskQueue(0) );
 }
@@ -1081,7 +1094,7 @@
 /***********************************************************************
  *           GetCurrentTask   (KERNEL.36)
  */
-HTASK GetCurrentTask(void)
+HTASK16 GetCurrentTask(void)
 {
     return hCurrentTask;
 }
@@ -1223,7 +1236,7 @@
 /***********************************************************************
  *           TaskFirst   (TOOLHELP.63)
  */
-BOOL TaskFirst( TASKENTRY *lpte )
+BOOL16 TaskFirst( TASKENTRY *lpte )
 {
     lpte->hNext = hFirstTask;
     return TaskNext( lpte );
@@ -1233,7 +1246,7 @@
 /***********************************************************************
  *           TaskNext   (TOOLHELP.64)
  */
-BOOL TaskNext( TASKENTRY *lpte )
+BOOL16 TaskNext( TASKENTRY *lpte )
 {
     TDB *pTask;
     INSTANCEDATA *pInstData;
@@ -1265,7 +1278,7 @@
 /***********************************************************************
  *           TaskFindHandle   (TOOLHELP.65)
  */
-BOOL TaskFindHandle( TASKENTRY *lpte, HTASK hTask )
+BOOL16 TaskFindHandle( TASKENTRY *lpte, HTASK16 hTask )
 {
     lpte->hNext = hTask;
     return TaskNext( lpte );
diff --git a/memory/global.c b/memory/global.c
index 1f58f09..111885c 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -485,24 +485,24 @@
 
 
 /***********************************************************************
- *           LockSegment   (KERNEL.23)
+ *           LockSegment16   (KERNEL.23)
  */
-HGLOBAL LockSegment( HGLOBAL handle )
+HGLOBAL16 LockSegment16( HGLOBAL16 handle )
 {
     dprintf_global( stddeb, "LockSegment: %04x\n", handle );
-    if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
+    if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
     GET_ARENA_PTR(handle)->lockCount++;
     return handle;
 }
 
 
 /***********************************************************************
- *           UnlockSegment   (KERNEL.24)
+ *           UnlockSegment16   (KERNEL.24)
  */
-void UnlockSegment( HGLOBAL handle )
+void UnlockSegment16( HGLOBAL16 handle )
 {
     dprintf_global( stddeb, "UnlockSegment: %04x\n", handle );
-    if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
+    if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
     GET_ARENA_PTR(handle)->lockCount--;
     /* FIXME: this ought to return the lock count in CX (go figure...) */
 }
@@ -546,7 +546,7 @@
 /***********************************************************************
  *           GlobalUnWire   (KERNEL.112)
  */
-BOOL GlobalUnWire( HGLOBAL16 handle )
+BOOL16 GlobalUnWire( HGLOBAL16 handle )
 {
     return GlobalUnlock16( handle );
 }
@@ -588,7 +588,7 @@
 HGLOBAL16 GlobalLRUOldest( HGLOBAL16 handle )
 {
     dprintf_global( stddeb, "GlobalLRUOldest: %04x\n", handle );
-    if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
+    if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
     return handle;
 }
 
@@ -599,7 +599,7 @@
 HGLOBAL16 GlobalLRUNewest( HGLOBAL16 handle )
 {
     dprintf_global( stddeb, "GlobalLRUNewest: %04x\n", handle );
-    if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
+    if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
     return handle;
 }
 
@@ -656,7 +656,7 @@
 /***********************************************************************
  *           FarSetOwner   (KERNEL.403)
  */
-void FarSetOwner( HANDLE handle, HANDLE hOwner )
+void FarSetOwner( HANDLE16 handle, HANDLE16 hOwner )
 {
     GET_ARENA_PTR(handle)->hOwner = hOwner;
 }
@@ -665,7 +665,7 @@
 /***********************************************************************
  *           FarGetOwner   (KERNEL.404)
  */
-WORD FarGetOwner( HANDLE handle )
+HANDLE16 FarGetOwner( HANDLE16 handle )
 {
     return GET_ARENA_PTR(handle)->hOwner;
 }
@@ -693,7 +693,7 @@
 /***********************************************************************
  *           GlobalFirst   (TOOLHELP.51)
  */
-BOOL GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags )
+BOOL16 GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags )
 {
     if (wFlags == GLOBAL_LRU) return FALSE;
     pGlobal->dwNext = 0;
@@ -704,7 +704,7 @@
 /***********************************************************************
  *           GlobalNext   (TOOLHELP.52)
  */
-BOOL GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags)
+BOOL16 GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags)
 {
     GLOBALARENA *pArena;
 
@@ -737,7 +737,7 @@
 /***********************************************************************
  *           GlobalInfo   (TOOLHELP.53)
  */
-BOOL GlobalInfo( GLOBALINFO *pInfo )
+BOOL16 GlobalInfo( GLOBALINFO *pInfo )
 {
     int i;
     GLOBALARENA *pArena;
@@ -754,7 +754,7 @@
 /***********************************************************************
  *           GlobalEntryHandle   (TOOLHELP.54)
  */
-BOOL GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL16 hItem )
+BOOL16 GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL16 hItem )
 {
     return FALSE;
 }
@@ -763,7 +763,7 @@
 /***********************************************************************
  *           GlobalEntryModule   (TOOLHELP.55)
  */
-BOOL GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE16 hModule, WORD wSeg )
+BOOL16 GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE16 hModule, WORD wSeg )
 {
     return FALSE;
 }
@@ -772,7 +772,7 @@
 /***********************************************************************
  *           MemManInfo   (TOOLHELP.72)
  */
-BOOL MemManInfo( MEMMANINFO *pInfo )
+BOOL16 MemManInfo( MEMMANINFO *pInfo )
 {
 #ifdef linux
     /* FIXME: does not take into account the dwSize member
diff --git a/memory/heap.c b/memory/heap.c
index 2411161..a2a60b6 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -4,6 +4,7 @@
  * Copyright 1996 Alexandre Julliard
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -236,7 +237,7 @@
  *
  * Make sure the heap storage is committed up to (not including) ptr.
  */
-static BOOL HEAP_Commit( SUBHEAP *subheap, void *ptr )
+static BOOL32 HEAP_Commit( SUBHEAP *subheap, void *ptr )
 {
     DWORD size = (DWORD)((char *)ptr - (char *)subheap);
     size = (size + 0xfff) & 0xfffff000;  /* Align size on a page boundary */
@@ -262,7 +263,7 @@
  *
  * If possible, decommit the heap storage from (including) 'ptr'.
  */
-static BOOL HEAP_Decommit( SUBHEAP *subheap, void *ptr )
+static BOOL32 HEAP_Decommit( SUBHEAP *subheap, void *ptr )
 {
     DWORD size = (DWORD)((char *)ptr - (char *)subheap);
     size = (size + 0xfff) & 0xfffff000;  /* Align size on a page boundary */
@@ -373,7 +374,18 @@
     if (((char *)pFree == (char *)subheap + subheap->headerSize) &&
         (subheap != &subheap->heap->subheap))
     {
-        /* FIXME: free the sub-heap here */
+        SUBHEAP *pPrev = &subheap->heap->subheap;
+        /* Remove the free block from the list */
+        pFree->next->prev = pFree->prev;
+        pFree->prev->next = pFree->next;
+        /* Remove the subheap from the list */
+        while (pPrev && (pPrev->next != subheap)) pPrev = pPrev->next;
+        if (pPrev) pPrev->next = subheap->next;
+        /* Free the memory */
+        subheap->magic = 0;
+        if (subheap->selector) FreeSelector( subheap->selector );
+        VirtualFree( subheap, subheap->size, MEM_DECOMMIT );
+        VirtualFree( subheap, 0, MEM_RELEASE );
         return;
     }
     
@@ -541,7 +553,7 @@
  *
  * Check that the pointer is inside the range possible for arenas.
  */
-static BOOL HEAP_IsValidArenaPtr( HEAP *heap, void *ptr )
+static BOOL32 HEAP_IsValidArenaPtr( HEAP *heap, void *ptr )
 {
     int i;
     SUBHEAP *subheap = HEAP_FindSubHeap( heap, ptr );
@@ -557,7 +569,7 @@
 /***********************************************************************
  *           HEAP_ValidateFreeArena
  */
-static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena )
+static BOOL32 HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena )
 {
     char *heapEnd = (char *)subheap + subheap->size;
 
@@ -639,7 +651,7 @@
 /***********************************************************************
  *           HEAP_ValidateInUseArena
  */
-static BOOL HEAP_ValidateInUseArena( SUBHEAP *subheap, ARENA_INUSE *pArena )
+static BOOL32 HEAP_ValidateInUseArena( SUBHEAP *subheap, ARENA_INUSE *pArena )
 {
     char *heapEnd = (char *)subheap + subheap->size;
 
@@ -829,7 +841,7 @@
 /***********************************************************************
  *           HeapDestroy   (KERNEL32.337)
  */
-BOOL HeapDestroy( HANDLE32 heap )
+BOOL32 HeapDestroy( HANDLE32 heap )
 {
     HEAP *heapPtr = HEAP_GetPtr( heap );
     SUBHEAP *subheap;
@@ -842,6 +854,7 @@
     while (subheap)
     {
         SUBHEAP *next = subheap->next;
+        if (subheap->selector) FreeSelector( subheap->selector );
         VirtualFree( subheap, subheap->commitSize, MEM_DECOMMIT );
         VirtualFree( subheap, 0, MEM_RELEASE );
         subheap = next;
@@ -913,7 +926,7 @@
 /***********************************************************************
  *           HeapFree   (KERNEL32.338)
  */
-BOOL HeapFree( HANDLE32 heap, DWORD flags, LPVOID ptr )
+BOOL32 HeapFree( HANDLE32 heap, DWORD flags, LPVOID ptr )
 {
     ARENA_INUSE *pInUse;
     SUBHEAP *subheap;
@@ -1030,7 +1043,7 @@
                                + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE);
             pInUse->threadId = GetCurrentTask();
             pInUse->magic    = ARENA_INUSE_MAGIC;
-            HEAP_ShrinkBlock( subheap, pInUse, size );
+            HEAP_ShrinkBlock( newsubheap, pInUse, size );
             memcpy( pInUse + 1, pArena + 1, oldSize );
 
             /* Free the previous block */
@@ -1077,7 +1090,7 @@
 /***********************************************************************
  *           HeapLock   (KERNEL32.339)
  */
-BOOL HeapLock( HANDLE32 heap )
+BOOL32 HeapLock( HANDLE32 heap )
 {
     HEAP *heapPtr = HEAP_GetPtr( heap );
 
@@ -1090,7 +1103,7 @@
 /***********************************************************************
  *           HeapUnlock   (KERNEL32.342)
  */
-BOOL HeapUnlock( HANDLE32 heap )
+BOOL32 HeapUnlock( HANDLE32 heap )
 {
     HEAP *heapPtr = HEAP_GetPtr( heap );
 
@@ -1133,7 +1146,7 @@
 /***********************************************************************
  *           HeapValidate   (KERNEL32.343)
  */
-BOOL HeapValidate( HANDLE32 heap, DWORD flags, LPVOID block )
+BOOL32 HeapValidate( HANDLE32 heap, DWORD flags, LPVOID block )
 {
     SUBHEAP *subheap;
     HEAP *heapPtr = (HEAP *)heap;
@@ -1185,7 +1198,7 @@
 /***********************************************************************
  *           HeapWalk   (KERNEL32.344)
  */
-BOOL HeapWalk( HANDLE32 heap, void *entry )
+BOOL32 HeapWalk( HANDLE32 heap, void *entry )
 {
     fprintf( stderr, "HeapWalk(%08x): not implemented\n", heap );
     return FALSE;
diff --git a/memory/local.c b/memory/local.c
index 7bc0546..5994e61 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -78,7 +78,7 @@
     WORD hdelta;                /* 18 Delta to expand the handle table */
     WORD expand;                /* 1a Pointer to expand function (unused) */
     WORD pstat;                 /* 1c Pointer to status structure (unused) */
-    FARPROC notify WINE_PACKED; /* 1e Pointer to LocalNotify() function */
+    FARPROC16 notify WINE_PACKED; /* 1e Pointer to LocalNotify() function */
     WORD lock;                  /* 22 Lock count for the heap */
     WORD extra;                 /* 24 Extra bytes to allocate when expanding */
     WORD minsize;               /* 26 Minimum size of the heap */
@@ -294,7 +294,7 @@
 /***********************************************************************
  *           LocalInit   (KERNEL.4)
  */
-BOOL LocalInit( HANDLE selector, WORD start, WORD end )
+BOOL16 LocalInit( HANDLE16 selector, WORD start, WORD end )
 {
     char *ptr;
     WORD heapInfoArena, freeArena, lastArena;
@@ -410,7 +410,7 @@
  */
 static void LOCAL_GrowHeap( HANDLE16 ds )
 {
-    HANDLE hseg = GlobalHandle16( ds );
+    HANDLE16 hseg = GlobalHandle16( ds );
     LONG oldsize = GlobalSize16( hseg );
     LONG end;
     LOCALHEAPINFO *pHeapInfo;
@@ -814,7 +814,7 @@
 /***********************************************************************
  *           LOCAL_NewHTable
  */
-static BOOL LOCAL_NewHTable( HANDLE16 ds )
+static BOOL16 LOCAL_NewHTable( HANDLE16 ds )
 {
     char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
     LOCALHEAPINFO *pInfo;
@@ -1230,7 +1230,7 @@
 /***********************************************************************
  *           LOCAL_Unlock
  */
-BOOL LOCAL_Unlock( HANDLE16 ds, HLOCAL16 handle )
+BOOL16 LOCAL_Unlock( HANDLE16 ds, HLOCAL16 handle )
 {
     char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
 
@@ -1460,10 +1460,10 @@
 /***********************************************************************
  *           LocalNotify   (KERNEL.14)
  */
-FARPROC LocalNotify( FARPROC func )
+FARPROC16 LocalNotify( FARPROC16 func )
 {
     LOCALHEAPINFO *pInfo;
-    FARPROC oldNotify;
+    FARPROC16 oldNotify;
     HANDLE16 ds = CURRENT_DS;
 
     if (!(pInfo = LOCAL_GetHeap( ds )))
@@ -1492,7 +1492,7 @@
 /***********************************************************************
  *           GetHeapSpaces   (KERNEL.138)
  */
-DWORD GetHeapSpaces( HMODULE module )
+DWORD GetHeapSpaces( HMODULE16 module )
 {
     NE_MODULE *pModule;
     WORD ds;
@@ -1545,7 +1545,7 @@
 /***********************************************************************
  *           LocalInfo   (TOOLHELP.56)
  */
-BOOL LocalInfo( LOCALINFO *pLocalInfo, HGLOBAL handle )
+BOOL16 LocalInfo( LOCALINFO *pLocalInfo, HGLOBAL16 handle )
 {
     LOCALHEAPINFO *pInfo = LOCAL_GetHeap(SELECTOROF(WIN16_GlobalLock16(handle)));
     if (!pInfo) return FALSE;
@@ -1557,7 +1557,7 @@
 /***********************************************************************
  *           LocalFirst   (TOOLHELP.57)
  */
-BOOL LocalFirst( LOCALENTRY *pLocalEntry, HGLOBAL handle )
+BOOL16 LocalFirst( LOCALENTRY *pLocalEntry, HGLOBAL16 handle )
 {
     WORD ds = GlobalHandleToSel( handle );
     char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
@@ -1580,7 +1580,7 @@
 /***********************************************************************
  *           LocalNext   (TOOLHELP.58)
  */
-BOOL LocalNext( LOCALENTRY *pLocalEntry )
+BOOL16 LocalNext( LOCALENTRY *pLocalEntry )
 {
     WORD ds = GlobalHandleToSel( pLocalEntry->hHeap );
     char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
diff --git a/memory/selector.c b/memory/selector.c
index 4b9e45a..b0ddc79 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -101,8 +101,8 @@
  * Set the LDT entries for an array of selectors.
  */
 static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size,
-                                 enum seg_type type, BOOL is32bit,
-                                 BOOL readonly )
+                                 enum seg_type type, BOOL32 is32bit,
+                                 BOOL32 readonly )
 {
     ldt_entry entry;
     WORD i, count;
@@ -136,7 +136,7 @@
  * Allocate selectors for a block of linear memory.
  */
 WORD SELECTOR_AllocBlock( const void *base, DWORD size, enum seg_type type,
-                          BOOL is32bit, BOOL readonly )
+                          BOOL32 is32bit, BOOL32 readonly )
 {
     WORD sel, count;
 
@@ -154,7 +154,7 @@
  * Change the size of a block of selectors.
  */
 WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size,
-                            enum seg_type type, BOOL is32bit, BOOL readonly )
+                           enum seg_type type, BOOL32 is32bit, BOOL32 readonly)
 {
     WORD i, oldcount, newcount;
     ldt_entry entry;
diff --git a/memory/string.c b/memory/string.c
index 3348ec8..88cd5f5 100644
--- a/memory/string.c
+++ b/memory/string.c
@@ -5,6 +5,7 @@
  * Copyright 1996 Alexandre Julliard
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <ctype.h>
 #include <string.h>
 #include "windows.h"
@@ -333,3 +334,39 @@
     }
     return toupper(*str1) - toupper(*str2);
 }
+
+
+/***********************************************************************
+ *           RtlFillMemory   (KERNEL32.441)
+ */
+VOID RtlFillMemory( LPVOID ptr, UINT32 len, UINT32 fill )
+{
+    memset( ptr, fill, len );
+}
+
+
+/***********************************************************************
+ *           RtlMoveMemory   (KERNEL32.442)
+ */
+VOID RtlMoveMemory( LPVOID dst, LPCVOID src, UINT32 len )
+{
+    /* memcpy does not support overlapped copies, */
+    /* and memmove is not portable. */
+    if (((BYTE *)dst + len <= (BYTE *)src) ||
+        ((BYTE *)src + len <= (BYTE *)dst))
+    {
+        memcpy( dst, src, len );
+        return;
+    }
+    /* do it the hard way (FIXME: could do better than this) */
+    while (len--) *((BYTE *)dst)++ = *((BYTE *)src)++;
+}
+
+
+/***********************************************************************
+ *           RtlZeroMemory   (KERNEL32.444)
+ */
+VOID RtlZeroMemory( LPVOID ptr, UINT32 len )
+{
+    memset( ptr, 0, len );
+}
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 4ca2ee7..dc5a829 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -2292,7 +2292,7 @@
      lplf->lfWeight=fontstyles[i].weight;
      hf=CreateFontIndirect(lplf);
      hf=SelectObject(hdc,hf);
-     GetTextMetrics(hdc,lptm);
+     GetTextMetrics16(hdc,lptm);
      hf=SelectObject(hdc,hf);
      DeleteObject(hf);
 
diff --git a/misc/driver.c b/misc/driver.c
index eb51ba9..6277f8a 100644
--- a/misc/driver.c
+++ b/misc/driver.c
@@ -2,14 +2,14 @@
  * Wine Drivers functions
  *
  * Copyright 1994 Martin Ayotte
-static char Copyright[] = "Copyright  Martin Ayotte, 1994";
 */
 
 #include <stdio.h>
 #include "windows.h"
 #include "win.h"
-#include "user.h"
+#include "callback.h"
 #include "driver.h"
+#include "module.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -17,205 +17,294 @@
 
 void LoadStartupDrivers(void)
 {
-	HDRVR	hDrv;
-	char	str[256];
-	LPSTR	ptr	= str;
-	LPSTR	file = "SYSTEM.INI";
-	if (GetPrivateProfileString("drivers", NULL, 
-		"", str, sizeof(str), file) < 2) {
-        	fprintf(stderr,
-		"LoadStartupDrivers // can't find drivers section in '%s'\n", 
-		file);
-		return;
-		}
-	while(strlen(ptr) != 0) {
-        	dprintf_driver(stddeb,"LoadStartupDrivers // str='%s'\n", ptr);
-		hDrv = OpenDriver(ptr, "drivers", 0L);
-        	dprintf_driver(stddeb,
-			"LoadStartupDrivers // hDrv=%04x\n", hDrv);
-		ptr += strlen(ptr) + 1;
-		}
-    	dprintf_driver(stddeb,"LoadStartupDrivers // end of list !\n");
+    HDRVR16 hDrv;
+    char  str[256];
+    LPSTR ptr;
+
+    if (GetPrivateProfileString( "drivers", NULL, "", str, sizeof(str),
+				 "SYSTEM.INI" ) < 2)
+    {
+    	fprintf( stderr,
+		 "LoadStartupDrivers // can't find drivers section in system.ini\n" );
+	return;
+    }
+
+    ptr = str;
+    while (lstrlen32A( ptr ) != 0)
+    {
+	dprintf_driver( stddeb, "LoadStartupDrivers // str='%s'\n", ptr );
+	hDrv = OpenDriver( ptr, "drivers", 0L );
+	dprintf_driver( stddeb, "LoadStartupDrivers // hDrv=%04x\n", hDrv );
+	ptr += lstrlen32A(ptr) + 1;
+    }
+    dprintf_driver( stddeb, "LoadStartupDrivers // end of list !\n" );
+
+    return;
 }
 
 /**************************************************************************
  *				SendDriverMessage		[USER.251]
  */
-LRESULT SendDriverMessage(HDRVR hDriver, WORD msg, LPARAM lParam1, LPARAM lParam2)
+LRESULT SendDriverMessage(HDRVR16 hDriver, UINT16 msg, LPARAM lParam1,
+			  LPARAM lParam2)
 {
-	dprintf_driver(stdnimp,"SendDriverMessage(%04x, %04X, %08lX, %08lX);\n",
-						hDriver, msg, lParam1, lParam2);
-        return 0;
+    LPDRIVERITEM lpdrv;
+    LRESULT retval;
+
+    dprintf_driver( stddeb, "SendDriverMessage(%04x, %04X, %08lX, %08lX)\n",
+		    hDriver, msg, lParam1, lParam2 );
+
+    lpdrv = (LPDRIVERITEM)GlobalLock16( hDriver );
+    if (lpdrv == NULL || lpdrv->dis.hDriver != hDriver)
+    {
+	GlobalUnlock16( hDriver );
+	return 0;
+    }
+
+    retval = CallDriverProc( lpdrv->lpDrvProc, 0L /* FIXME */, hDriver, msg,
+			     lParam1, lParam2 );
+
+    dprintf_driver( stddeb, "SendDriverMessage // retval = %ld\n", retval );
+
+    GlobalUnlock16( hDriver );
+    return retval;
 }
 
 /**************************************************************************
  *				OpenDriver		        [USER.252]
  */
-HDRVR OpenDriver(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
+HDRVR16 OpenDriver(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
 {
-	HDRVR			hDrvr;
-	LPDRIVERITEM	lpnewdrv;
-	LPDRIVERITEM	lpdrv = lpDrvItemList;
-	char			DrvName[128];
-    	dprintf_driver(stddeb,"OpenDriver('%s', '%s', %08lX);\n",
-		lpDriverName, lpSectionName, lParam);
-	if (lpSectionName == NULL) lpSectionName = "drivers";
-	GetPrivateProfileString(lpSectionName, lpDriverName,
-		"", DrvName, sizeof(DrvName), "SYSTEM.INI");
-    	dprintf_driver(stddeb,"OpenDriver // DrvName='%s'\n", DrvName);
-	if (strlen(DrvName) < 1) return 0;
-	while (lpdrv != NULL) {
-		if (lpdrv->lpNextItem == NULL) break;
-		lpdrv = lpdrv->lpNextItem;
-		}
-	hDrvr = GlobalAlloc16(GMEM_MOVEABLE, sizeof(DRIVERITEM));
-	lpnewdrv = (LPDRIVERITEM) GlobalLock16(hDrvr);
-	if (lpnewdrv == NULL) return 0;
-	lpnewdrv->dis.length = sizeof(DRIVERINFOSTRUCT);
-	lpnewdrv->dis.hModule = 0;
-/*	lpnewdrv->dis.hModule = LoadImage(DrvName, DLL, 0);
-	if (lpnewdrv->dis.hModule == 0) {
-		GlobalUnlock(hDrvr);
-		GlobalFree(hDrvr);
-		return 0;
-		} */
-	lpnewdrv->dis.hDriver = hDrvr;
-	strcpy(lpnewdrv->dis.szAliasName, lpDriverName);
-	lpnewdrv->count = 0;
-	lpnewdrv->lpNextItem = NULL;
-	if (lpDrvItemList == NULL || lpdrv == NULL) {
-		lpDrvItemList = lpnewdrv;
-		lpnewdrv->lpPrevItem = NULL;
-		}
-	else {
-		lpdrv->lpNextItem = lpnewdrv;
-		lpnewdrv->lpPrevItem = lpdrv;
-		}
-	lpnewdrv->lpDrvProc = (DRIVERPROC)NULL;
-    	dprintf_driver(stddeb,"OpenDriver // hDrvr=%04x loaded !\n", hDrvr);
-	return hDrvr;
+    HDRVR16 hDrvr;
+    LPDRIVERITEM lpdrv, lpnewdrv;
+    char DrvName[128];
+    WORD ordinal;
+
+    dprintf_driver( stddeb,"OpenDriver('%s', '%s', %08lX);\n",
+		    lpDriverName, lpSectionName, lParam );
+
+    if (lpSectionName == NULL) lpSectionName = "drivers";
+    GetPrivateProfileString( lpSectionName, lpDriverName, "", DrvName,
+			     sizeof(DrvName), "SYSTEM.INI" );
+    dprintf_driver( stddeb,"OpenDriver // DrvName='%s'\n", DrvName );
+    if (lstrlen32A(DrvName) < 1) return 0;
+
+    lpdrv = lpDrvItemList;
+    while (lpdrv)			/* XXX find it... like this? */
+    {
+	if (!lstrcmpi32A( lpDriverName, lpdrv->dis.szAliasName ))
+	{
+	    lpdrv->count++;
+	    SendDriverMessage( lpdrv->dis.hDriver, DRV_OPEN, 0L, lParam );
+	    return lpdrv->dis.hDriver;
+	}
+	lpdrv = lpdrv->lpNextItem;
+    }
+
+    lpdrv = lpDrvItemList;	/* find end of list */
+    if (lpdrv != NULL)
+      while (lpdrv->lpNextItem != NULL)
+	lpdrv = lpdrv->lpNextItem;
+
+    hDrvr = GlobalAlloc16( GMEM_MOVEABLE, sizeof(DRIVERITEM) );
+    lpnewdrv = (LPDRIVERITEM)GlobalLock16( hDrvr );
+    if (lpnewdrv == NULL) return 0;
+    lpnewdrv->dis.length = sizeof( DRIVERINFOSTRUCT16 );
+    lpnewdrv->dis.hModule = LoadModule( DrvName, (LPVOID)-1 );
+    if (!lpnewdrv->dis.hModule)
+    {
+	GlobalUnlock16( hDrvr );
+	GlobalFree16( hDrvr );
+	return 0;
+    }
+    lpnewdrv->dis.hDriver = hDrvr;
+    lstrcpy32A( lpnewdrv->dis.szAliasName, lpDriverName );
+    lpnewdrv->count = 1;
+    ordinal = MODULE_GetOrdinal( lpnewdrv->dis.hModule, "DRIVERPROC" );
+    if (!ordinal ||
+        !(lpnewdrv->lpDrvProc = MODULE_GetEntryPoint( lpnewdrv->dis.hModule,
+                                                      ordinal )))
+    {
+	FreeModule16( lpnewdrv->dis.hModule );
+	GlobalUnlock16( hDrvr );
+	GlobalFree16( hDrvr );
+	return 0;
+    }
+
+    lpnewdrv->lpNextItem = NULL;
+    if (lpDrvItemList == NULL)
+    {
+	lpDrvItemList = lpnewdrv;
+	lpnewdrv->lpPrevItem = NULL;
+    }
+    else
+    {
+	lpdrv->lpNextItem = lpnewdrv;
+	lpnewdrv->lpPrevItem = lpdrv;
+    }
+
+    SendDriverMessage( hDrvr, DRV_LOAD, 0L, lParam );
+    SendDriverMessage( hDrvr, DRV_ENABLE, 0L, lParam );
+    SendDriverMessage( hDrvr, DRV_OPEN, 0L, lParam );
+
+    dprintf_driver( stddeb, "OpenDriver // hDrvr=%04x loaded !\n", hDrvr );
+    return hDrvr;
 }
 
 /**************************************************************************
  *				CloseDriver				[USER.253]
  */
-LRESULT CloseDriver(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2)
+LRESULT CloseDriver(HDRVR16 hDrvr, LPARAM lParam1, LPARAM lParam2)
 {
-	LPDRIVERITEM	lpdrv;
-    	dprintf_driver(stddeb,
-		"CloseDriver(%04x, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
-	lpdrv = (LPDRIVERITEM) GlobalLock16(hDrvr);
-	if (lpdrv != NULL && lpdrv->dis.hDriver == hDrvr) {
-		if (lpdrv->lpPrevItem)
-			((LPDRIVERITEM)lpdrv->lpPrevItem)->lpNextItem = lpdrv->lpNextItem;
-		if (lpdrv->lpNextItem)
-			((LPDRIVERITEM)lpdrv->lpNextItem)->lpPrevItem = lpdrv->lpPrevItem;
-		GlobalUnlock16(hDrvr);
-		GlobalFree16(hDrvr);
-        dprintf_driver(stddeb,"CloseDriver // hDrvr=%04x closed !\n", hDrvr);
-		return TRUE;
-		}
-	return FALSE;
+    LPDRIVERITEM lpdrv;
+
+    dprintf_driver( stddeb, "CloseDriver(%04x, %08lX, %08lX);\n",
+		    hDrvr, lParam1, lParam2 );
+
+    lpdrv = (LPDRIVERITEM)GlobalLock16( hDrvr );
+    if (lpdrv != NULL && lpdrv->dis.hDriver == hDrvr)
+    {
+	SendDriverMessage( hDrvr, DRV_CLOSE, lParam1, lParam2 );
+	if (--lpdrv->count == 0)
+	{
+	    SendDriverMessage( hDrvr, DRV_DISABLE, lParam1, lParam2 );
+	    SendDriverMessage( hDrvr, DRV_FREE, lParam1, lParam2 );
+
+	    if (lpdrv->lpPrevItem)
+	      lpdrv->lpPrevItem->lpNextItem = lpdrv->lpNextItem;
+            else
+                lpDrvItemList = lpdrv->lpNextItem;
+	    if (lpdrv->lpNextItem)
+	      lpdrv->lpNextItem->lpPrevItem = lpdrv->lpPrevItem;
+
+	    FreeModule16( lpdrv->dis.hModule );
+	    GlobalUnlock16( hDrvr );
+	    GlobalFree16( hDrvr );
+	}
+
+        dprintf_driver( stddeb, "CloseDriver // hDrvr=%04x closed !\n",
+		        hDrvr );
+	return TRUE;
+    }
+    return FALSE;
 }
 
 /**************************************************************************
  *				GetDriverModuleHandle	[USER.254]
  */
-HANDLE GetDriverModuleHandle(HDRVR hDrvr)
+HMODULE16 GetDriverModuleHandle(HDRVR16 hDrvr)
 {
-	LPDRIVERITEM	lpdrv;
-	HANDLE			hModule = 0;
-    	dprintf_driver(stddeb,"GetDriverModuleHandle(%04x);\n", hDrvr);
-	lpdrv = (LPDRIVERITEM) GlobalLock16(hDrvr);
-	if (lpdrv != NULL) {
-		hModule = lpdrv->dis.hModule;
-		GlobalUnlock16(hDrvr);
-		}
-	return hModule;
+    LPDRIVERITEM lpdrv;
+    HMODULE hModule = 0;
+
+    dprintf_driver( stddeb, "GetDriverModuleHandle(%04x);\n", hDrvr);
+
+    lpdrv = (LPDRIVERITEM)GlobalLock16( hDrvr );
+    if (lpdrv != NULL && lpdrv->dis.hDriver == hDrvr)
+    {
+	hModule = lpdrv->dis.hModule;
+	GlobalUnlock16( hDrvr );
+    }
+    return hModule;
 }
 
 /**************************************************************************
  *				DefDriverProc			[USER.255]
  */
-LRESULT DefDriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, 
-						DWORD dwParam1, DWORD dwParam2)
+LRESULT DefDriverProc(DWORD dwDevID, HDRVR hDriv, UINT16 wMsg, 
+		      LPARAM lParam1, LPARAM lParam2)
 {
-	switch(wMsg) {
-		case DRV_LOAD:
-			return (LRESULT)0L;
-		case DRV_FREE:
-			return (LRESULT)0L;
-		case DRV_OPEN:
-			return (LRESULT)0L;
-		case DRV_CLOSE:
-			return (LRESULT)0L;
-		case DRV_ENABLE:
-			return (LRESULT)0L;
-		case DRV_DISABLE:
-			return (LRESULT)0L;
-		case DRV_QUERYCONFIGURE:
-			return (LRESULT)0L;
-		case DRV_CONFIGURE:
-			MessageBox((HWND)NULL, "Driver isn't configurable !", 
-									"Wine Driver", MB_OK);
-			return (LRESULT)0L;
-		case DRV_INSTALL:
-			return (LRESULT)DRVCNF_RESTART;
-		case DRV_REMOVE:
-			return (LRESULT)DRVCNF_RESTART;
-		default:
-			return (LRESULT)0L;
-		}
+    switch(wMsg)
+    {
+      case DRV_LOAD:
+	return (LRESULT)0L;
+      case DRV_FREE:
+	return (LRESULT)0L;
+      case DRV_OPEN:
+	return (LRESULT)0L;
+      case DRV_CLOSE:
+	return (LRESULT)0L;
+      case DRV_ENABLE:
+	return (LRESULT)0L;
+      case DRV_DISABLE:
+	return (LRESULT)0L;
+      case DRV_QUERYCONFIGURE:
+	return (LRESULT)0L;
+
+      case DRV_CONFIGURE:
+	MessageBox( (HWND)NULL, "Driver isn't configurable !", 
+		    "Wine Driver", MB_OK );
+	return (LRESULT)0L;
+
+      case DRV_INSTALL:
+	return (LRESULT)DRVCNF_RESTART;
+
+      case DRV_REMOVE:
+	return (LRESULT)DRVCNF_RESTART;
+
+      default:
+	return (LRESULT)0L;
+    }
 }
 
 /**************************************************************************
  *				GetDriverInfo			[USER.256]
  */
-BOOL GetDriverInfo(HDRVR hDrvr, LPDRIVERINFOSTRUCT lpDrvInfo)
+BOOL16 GetDriverInfo(HDRVR16 hDrvr, LPDRIVERINFOSTRUCT16 lpDrvInfo)
 {
-	LPDRIVERITEM	lpdrv;
-    	dprintf_driver(stddeb,"GetDriverInfo(%04x, %p);\n", hDrvr, lpDrvInfo);
-	if (lpDrvInfo == NULL) return FALSE;
-	lpdrv = (LPDRIVERITEM) GlobalLock16(hDrvr);
-	if (lpdrv == NULL) return FALSE;
-	memcpy(lpDrvInfo, &lpdrv->dis, sizeof(DRIVERINFOSTRUCT));
-	GlobalUnlock16(hDrvr);
-	return TRUE;
+    LPDRIVERITEM lpdrv;
+
+    dprintf_driver( stddeb, "GetDriverInfo(%04x, %p);\n", hDrvr, lpDrvInfo );
+
+    if (lpDrvInfo == NULL) return FALSE;
+
+    lpdrv = (LPDRIVERITEM)GlobalLock16( hDrvr );
+    if (lpdrv == NULL) return FALSE;
+    memcpy( lpDrvInfo, &lpdrv->dis, sizeof(DRIVERINFOSTRUCT16) );
+    GlobalUnlock16( hDrvr );
+
+    return TRUE;
 }
 
 /**************************************************************************
  *				GetNextDriver			[USER.257]
  */
-HDRVR GetNextDriver(HDRVR hDrvr, DWORD dwFlags)
+HDRVR16 GetNextDriver(HDRVR16 hDrvr, DWORD dwFlags)
 {
-	LPDRIVERITEM	lpdrv;
-	HDRVR			hRetDrv = 0;
-    	dprintf_driver(stddeb,"GetNextDriver(%04x, %08lX);\n", hDrvr, dwFlags);
-	if (hDrvr == 0) {
-		if (lpDrvItemList == NULL) {
-            		dprintf_driver(stddeb,
-				"GetNextDriver // drivers list empty !\n");
-			LoadStartupDrivers();
-			if (lpDrvItemList == NULL) return 0;
-			}
-        	dprintf_driver(stddeb,"GetNextDriver // return first %04x !\n",
-					lpDrvItemList->dis.hDriver);
-		return lpDrvItemList->dis.hDriver;
-		}
-	lpdrv = (LPDRIVERITEM) GlobalLock16(hDrvr);
-	if (lpdrv != NULL) {
-		if (dwFlags & GND_REVERSE) {
-			if (lpdrv->lpPrevItem) 
-				hRetDrv = ((LPDRIVERITEM)lpdrv->lpPrevItem)->dis.hDriver;
-			}
-		else {
-			if (lpdrv->lpNextItem) 
-				hRetDrv = ((LPDRIVERITEM)lpdrv->lpNextItem)->dis.hDriver;
-			}
-		GlobalUnlock16(hDrvr);
-		}
-    	dprintf_driver(stddeb,"GetNextDriver // return %04x !\n", hRetDrv);
-	return hRetDrv;
+    LPDRIVERITEM lpdrv;
+    HDRVR16 hRetDrv = 0;
+
+    dprintf_driver( stddeb, "GetNextDriver(%04x, %08lX);\n", hDrvr, dwFlags );
+
+    if (hDrvr == 0)
+    {
+	if (lpDrvItemList == NULL)
+	{
+	    dprintf_driver(stddeb, "GetNextDriver // drivers list empty !\n");
+	    LoadStartupDrivers();
+	    if (lpDrvItemList == NULL) return 0;
+	}
+	dprintf_driver( stddeb,"GetNextDriver // return first %04x !\n",
+		        lpDrvItemList->dis.hDriver );
+	return lpDrvItemList->dis.hDriver;
+    }
+
+    lpdrv = (LPDRIVERITEM)GlobalLock16( hDrvr );
+    if (lpdrv != NULL)
+    {
+	if (dwFlags & GND_REVERSE)
+	{
+	    if (lpdrv->lpPrevItem) 
+	      hRetDrv = lpdrv->lpPrevItem->dis.hDriver;
+	}
+	else
+	{
+	    if (lpdrv->lpNextItem) 
+	      hRetDrv = lpdrv->lpNextItem->dis.hDriver;
+	}
+	GlobalUnlock16( hDrvr );
+    }
+
+    dprintf_driver( stddeb, "GetNextDriver // return %04x !\n", hRetDrv );
+    return hRetDrv;
 }
-
-
diff --git a/misc/exec.c b/misc/exec.c
index d863e16..fb67a0b 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -7,9 +7,10 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include "windows.h"
+#include "heap.h"
 #include "neexe.h"
 #include "shell.h"
-#include "windows.h"
 #include "callback.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -54,50 +55,36 @@
  */
 BOOL ExitWindows( DWORD dwReturnCode, WORD wReserved )
 {
-    HWND hwndDesktop;
-    WND *wndPtr;
-    HWND *list, *pWnd;
-    int count, i;
-    BOOL result;
+    int i;
+    BOOL16 result;
+    WND **list, **ppWnd;
         
     api_assert("ExitWindows", wReserved == 0);
     api_assert("ExitWindows", HIWORD(dwReturnCode) == 0);
 
     /* We have to build a list of all windows first, as in EnumWindows */
 
-    /* First count the windows */
+    if (!(list = WIN_BuildWinArray( WIN_GetDesktop() ))) return FALSE;
 
-    hwndDesktop = GetDesktopWindow();
-    count = 0;
-    for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
-        count++;
-    if (!count) /* No windows, we can exit at once */
-        EXEC_ExitWindows( LOWORD(dwReturnCode) );
+    /* Send a WM_QUERYENDSESSION message to every window */
 
-      /* Now build the list of all windows */
-
-    if (!(pWnd = list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
-    for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
-        *pWnd++ = wndPtr->hwndSelf;
-
-      /* Now send a WM_QUERYENDSESSION message to every window */
-
-    for (pWnd = list, i = 0; i < count; i++, pWnd++)
+    for (ppWnd = list, i = 0; *ppWnd; ppWnd++, i++)
     {
-          /* Make sure that window still exists */
-        if (!IsWindow(*pWnd)) continue;
-	if (!SendMessage16( *pWnd, WM_QUERYENDSESSION, 0, 0 )) break;
+        /* Make sure that the window still exists */
+        if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
+	if (!SendMessage16( (*ppWnd)->hwndSelf, WM_QUERYENDSESSION, 0, 0 ))
+            break;
     }
-    result = (i == count);
+    result = !(*ppWnd);
 
     /* Now notify all windows that got a WM_QUERYENDSESSION of the result */
 
-    for (pWnd = list; i > 0; i--, pWnd++)
+    for (ppWnd = list; i > 0; i--, ppWnd++)
     {
-	if (!IsWindow(*pWnd)) continue;
-	SendMessage16( *pWnd, WM_ENDSESSION, result, 0 );
+        if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
+	SendMessage16( (*ppWnd)->hwndSelf, WM_ENDSESSION, result, 0 );
     }
-    free( list );
+    HeapFree( SystemHeap, 0, list );
 
     if (result) EXEC_ExitWindows( LOWORD(dwReturnCode) );
     return FALSE;
diff --git a/misc/lzexpand.c b/misc/lzexpand.c
index e907bfd..7726d96 100644
--- a/misc/lzexpand.c
+++ b/misc/lzexpand.c
@@ -396,7 +396,7 @@
 LZSeek(HFILE fd,LONG off,INT32 type) {
 	int	i;
 	struct	lzstate	*lzs;
-	LONG	lastwanted,newwanted;
+	LONG	newwanted;
 
 	dprintf_file(stddeb,"LZSeek(%d,%ld,%d)\n",fd,off,type);
 	for (i=0;i<nroflzstates;i++)
@@ -406,7 +406,6 @@
 	if (i==nroflzstates)
 		return _llseek(fd,off,type);
 	lzs		= lzstates+i;
-	lastwanted	= lzs->realwanted;
 	newwanted	= lzs->realwanted;
 	switch (type) {
 	case 1:	/* SEEK_CUR */
@@ -424,7 +423,7 @@
 	if (newwanted<0)
 		return LZERROR_BADVALUE;
 	lzs->realwanted	= newwanted;
-	return lastwanted;
+	return newwanted;
 }
 
 /* 
diff --git a/misc/main.c b/misc/main.c
index adc8255..2e01aa0 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -227,7 +227,7 @@
  *                    ParseDebugOptions
  *
  *  Turns specific debug messages on or off, according to "options".
- *  Returns TRUE if parsing was successfull 
+ *  Returns TRUE if parsing was successful
  */
 #ifdef DEBUG_RUNTIME
 
@@ -655,6 +655,17 @@
 
 
 /***********************************************************************
+ *           Beep   (KERNEL32.11)
+ */
+BOOL32 Beep( DWORD dwFreq, DWORD dwDur )
+{
+    /* dwFreq and dwDur are ignored by Win95 */
+    XBell(display, 100);
+    return TRUE;
+}
+
+
+/***********************************************************************
  *      GetVersion (KERNEL.3)
  */
 LONG GetVersion(void)
@@ -761,7 +772,7 @@
 /***********************************************************************
  *	SetEnvironment (GDI.132)
  */
-int SetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nCount)
+int SetEnvironment(LPCSTR lpPortName, LPCSTR lpEnviron, WORD nCount)
 {
     LPENVENTRY	lpNewEnv;
     LPENVENTRY	lpEnv = lpEnvList;
@@ -826,10 +837,11 @@
     return nCount;
 }
 
+
 /***********************************************************************
- *      SetEnvironmentVariableA (KERNEL32.484)
+ *      SetEnvironmentVariable32A   (KERNEL32.484)
  */
-BOOL SetEnvironmentVariableA(LPSTR lpName, LPSTR lpValue)
+BOOL32 SetEnvironmentVariable32A( LPCSTR lpName, LPCSTR lpValue )
 {
     int rc;
 
@@ -837,6 +849,24 @@
     return (rc > 0) ? 1 : 0;
 }
 
+
+/***********************************************************************
+ *      SetEnvironmentVariable32W   (KERNEL32.485)
+ */
+BOOL32 SetEnvironmentVariable32W( LPCWSTR lpName, LPCWSTR lpValue )
+{
+    LPSTR lpAName, lpAValue;
+    BOOL ret;
+
+    lpAName = STRING32_DupUniToAnsi( lpName );
+    lpAValue = STRING32_DupUniToAnsi ( lpValue );
+    ret = SetEnvironment(lpAName, lpAValue, strlen(lpAValue) + 1);
+    free (lpAName);
+    free (lpAValue);
+    return (ret > 0) ? 1 : 0;    
+}
+
+
 /***********************************************************************
  *	GetEnvironment (GDI.134)
  */
diff --git a/misc/network.c b/misc/network.c
index 65ef9cb..7303d60 100644
--- a/misc/network.c
+++ b/misc/network.c
@@ -161,7 +161,7 @@
     if (lpLocalName[1] == ':')
     {
         int drive = toupper(lpLocalName[0]) - 'A';
-        switch(GetDriveType(drive))
+        switch(GetDriveType16(drive))
         {
         case DRIVE_CANNOTDETERMINE:
         case DRIVE_DOESNOTEXIST:
diff --git a/misc/registry.c b/misc/registry.c
index de792a1..31c41a8 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -1714,9 +1714,12 @@
 	}
 	if (i==lpkey->nrofvalues) {
 		if (lpszValueName==NULL) {
-			*(WCHAR*)lpbData = 0;
-			*lpcbData	= 2;
-			*lpdwType	= REG_SZ;
+			if (lpbData) {
+				*(WCHAR*)lpbData = 0;
+				*lpcbData	= 2;
+			}
+			if (lpdwType)
+				*lpdwType	= REG_SZ;
 			return SHELL_ERROR_SUCCESS;
 		}
 		return SHELL_ERROR_BADKEY;/*FIXME: correct return? */
@@ -1790,6 +1793,7 @@
 	LPBYTE	buf;
 	DWORD	ret,myxlen;
 	DWORD	*mylen;
+	DWORD	type;
 
 	dprintf_reg(stddeb,"RegQueryValueEx32A(%x,%s,%p,%p,%p,%ld)\n->",
 		hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,
@@ -1813,18 +1817,21 @@
 	else 
 		lpszValueNameW=NULL;
 
+	if (lpdwType)
+		type=*lpdwType;
 	ret=RegQueryValueEx32W(
 		hkey,
 		lpszValueNameW,
 		lpdwReserved,
-		lpdwType,
+		&type,
 		buf,
 		mylen
 	);
-
+	if (lpdwType) 
+		*lpdwType=type;
 	if (ret==ERROR_SUCCESS) {
 		if (buf) {
-			if (UNICONVMASK & (1<<(*lpdwType))) {
+			if (UNICONVMASK & (1<<(type))) {
 				/* convert UNICODE to ASCII */
 				strcpyWA(lpbData,(LPWSTR)buf);
 				*lpcbData	= myxlen/2;
@@ -1837,11 +1844,11 @@
 				*lpcbData	= myxlen;
 			}
 		} else {
-			if ((UNICONVMASK & (1<<(*lpdwType))) && lpcbData)
+			if ((UNICONVMASK & (1<<(type))) && lpcbData)
 				*lpcbData	= myxlen/2;
 		}
 	} else {
-		if ((UNICONVMASK & (1<<(*lpdwType))) && lpcbData)
+		if ((UNICONVMASK & (1<<(type))) && lpcbData)
 			*lpcbData	= myxlen/2;
 	}
 	if (buf)
diff --git a/misc/spy.c b/misc/spy.c
index f5fbd4d..8425ad9 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -429,7 +429,7 @@
         if (!MessageTypeNames[msg]) return "???";
         return MessageTypeNames[msg];
     }
-    sprintf( buffer, "WM_USER+%04x\n", msg - WM_USER );
+    sprintf( buffer, "WM_USER+%04x", msg - WM_USER );
     return buffer;
 }
 
diff --git a/misc/system.c b/misc/system.c
index 2b17178..ee60a03 100644
--- a/misc/system.c
+++ b/misc/system.c
@@ -21,7 +21,7 @@
         return 54925;
 
     case 1:  /* Get drive type */
-        drivetype = GetDriveType( drive );
+        drivetype = GetDriveType16( drive );
         return MAKELONG( drivetype, drivetype );
 
     case 2:  /* Enable one-drive logic */
diff --git a/misc/toolhelp.c b/misc/toolhelp.c
index cd34e20..551078c 100644
--- a/misc/toolhelp.c
+++ b/misc/toolhelp.c
@@ -29,8 +29,7 @@
 
 static int nrofnotifys = 0;
 
-BOOL
-NotifyRegister(HTASK htask,FARPROC lpfnCallback,WORD wFlags)
+BOOL16 NotifyRegister( HTASK16 htask, FARPROC16 lpfnCallback, WORD wFlags )
 {
     int	i;
 
diff --git a/misc/user.c b/misc/user.c
index b20b262..8976d77 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -76,7 +76,7 @@
 /***********************************************************************
  *           TimerCount   (TOOLHELP.80)
  */
-BOOL TimerCount( TIMERINFO *pTimerInfo )
+BOOL16 TimerCount( TIMERINFO *pTimerInfo )
 {
     /* FIXME
      * In standard mode, dwmsSinceStart = dwmsThisVM 
diff --git a/misc/ver.c b/misc/ver.c
index 7541a82..5a47d12 100644
--- a/misc/ver.c
+++ b/misc/ver.c
@@ -21,7 +21,9 @@
 #include "winreg.h"
 #include "string32.h"
 
-#define LZREAD(what)	if (sizeof(*what)!=LZRead32(lzfd,what,sizeof(*what))) return 0;
+#define LZREAD(what) \
+  if (sizeof(*what)!=LZRead32(lzfd,what,sizeof(*what))) return 0;
+#define LZTELL(lzfd) LZSeek(lzfd, 0, SEEK_CUR);
 
 #define strdupW2A(x)	STRING32_DupUniToAnsi(x)
 #define strdupA2W(x)	STRING32_DupAnsiToUni(x)
@@ -57,7 +59,8 @@
 	WORD		shiftcount;
 	DWORD		nehdoffset;
 
-	nehdoffset=LZSeek(lzfd,nehd->resource_tab_offset,SEEK_CUR);
+	nehdoffset = LZTELL(lzfd);
+	LZSeek(lzfd,nehd->resource_tab_offset,SEEK_CUR);
 	LZREAD(&shiftcount);
 	dprintf_resource(stderr,"shiftcount is %d\n",shiftcount);
 	dprintf_resource(stderr,"reading resource typeinfo dir.\n");
@@ -83,7 +86,8 @@
 				char	*str;
 				DWORD	whereleft;
 
-				whereleft=LZSeek(
+				whereleft = LZTELL(lzfd);
+				LZSeek(
 					lzfd,
 					nehdoffset+nehd->resource_tab_offset+ti.type_id,
 					SEEK_SET
@@ -123,7 +127,8 @@
 					char	*str;
 					DWORD	whereleft;
 
-					whereleft=LZSeek(
+					whereleft = LZTELL(lzfd);
+					  LZSeek(
 						lzfd,
 						nehdoffset+nehd->resource_tab_offset+ni.id,
 						SEEK_SET
@@ -187,7 +192,7 @@
 	return reslen;
 }
 
-/* GetFileResourceSize				[VER.3] */
+/* GetFileResource				[VER.3] */
 DWORD
 GetFileResource(LPCSTR filename,SEGPTR restype,SEGPTR resid,
 		DWORD off,DWORD datalen,LPVOID data
@@ -195,7 +200,7 @@
 	HFILE	lzfd;
 	OFSTRUCT	ofs;
 	BYTE	*resdata;
-	int	reslen;
+	int	reslen=datalen;
 	struct	ne_header_s	nehd;
 	fprintf(stderr,"GetFileResource(%s,%lx,%lx,%ld,%ld,%p)\n",
 		filename,(LONG)restype,(LONG)resid,off,datalen,data
diff --git a/misc/wsprintf.c b/misc/wsprintf.c
index f8f77aa..a57d23f 100644
--- a/misc/wsprintf.c
+++ b/misc/wsprintf.c
@@ -4,6 +4,7 @@
  * Copyright 1996 Alexandre Julliard
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
@@ -246,10 +247,12 @@
         spec += WPRINTF_ParseFormatA( spec, &format );
         switch(format.type)
         {
+        case WPR_WCHAR:  /* No Unicode in Win16 */
         case WPR_CHAR:
             cur_arg = (DWORD)*(CHAR *)args;
             args = (WORD *)args + 1;
             break;
+        case WPR_WSTRING:  /* No Unicode in Win16 */
         case WPR_STRING:
             cur_arg = (DWORD)PTR_SEG_TO_LIN( *(SEGPTR *)args );
             args = (SEGPTR *)args + 1;
@@ -268,10 +271,6 @@
                 args = (UINT16 *)args + 1;
             }
             break;
-        case WPR_WCHAR:
-        case WPR_WSTRING:
-            fprintf( stderr, "Unicode not supported in wsprintf16\n" );
-            continue;
         }
         len = WPRINTF_GetLen( &format, &cur_arg, number, maxlen - 1 );
         if (!(format.flags & WPRINTF_LEFTALIGN))
diff --git a/miscemu/dosmem.c b/miscemu/dosmem.c
index 9bcf311..ed5bd16 100644
--- a/miscemu/dosmem.c
+++ b/miscemu/dosmem.c
@@ -86,7 +86,7 @@
  */
 BOOL DOSMEM_Init(void)
 {
-    HMODULE hModule = GetModuleHandle( "KERNEL" );
+    HMODULE16 hModule = GetModuleHandle( "KERNEL" );
     char *dosmem;
 
     /* Allocate 7 64k segments for 0000, A000, B000, C000, D000, E000, F000. */
diff --git a/miscemu/dpmi.c b/miscemu/dpmi.c
index 291af75..4c7e67f 100644
--- a/miscemu/dpmi.c
+++ b/miscemu/dpmi.c
@@ -41,14 +41,14 @@
     WORD  ss;
 } REALMODECALL;
 
-extern void do_mscdex(struct sigcontext_struct *context);
+extern void do_mscdex( SIGCONTEXT *context );
 
 /**********************************************************************
  *	    INT_Int31Handler
  *
  * Handler for int 31h (DPMI).
  */
-void INT_Int31Handler( struct sigcontext_struct context )
+void INT_Int31Handler( SIGCONTEXT context )
 {
     DWORD dw;
     BYTE *ptr;
@@ -199,7 +199,7 @@
              */
             if ((BL_reg(&context) == 0x2f) && ((p->eax & 0xFF00) == 0x1500))
             {
-                struct sigcontext_struct context2;
+                SIGCONTEXT context2;
                 EAX_reg(&context2) = p->eax;
                 EBX_reg(&context2) = p->ebx;
                 ECX_reg(&context2) = p->ecx;
diff --git a/miscemu/emulate.c b/miscemu/emulate.c
index d31ccb7..37dec4e 100644
--- a/miscemu/emulate.c
+++ b/miscemu/emulate.c
@@ -30,7 +30,7 @@
  */
 /* FIXME: Only skeletal implementation for now */
 
-void WIN87_fpmath( struct sigcontext_struct context )
+void WIN87_fpmath( SIGCONTEXT context )
 {
     dprintf_int(stddeb, "_fpmath: (cs:eip=%x:%lx es=%x bx=%04x ax=%04x dx==%04x)\n",
                  CS_reg(&context), EIP_reg(&context),
diff --git a/miscemu/instr.c b/miscemu/instr.c
index 767f4e8..0b2e957 100644
--- a/miscemu/instr.c
+++ b/miscemu/instr.c
@@ -24,7 +24,7 @@
  * Try to replace an invalid selector by a valid one.
  * For now, only selector 0x40 is handled here.
  */
-static WORD INSTR_ReplaceSelector( struct sigcontext_struct *context, WORD sel)
+static WORD INSTR_ReplaceSelector( SIGCONTEXT *context, WORD sel)
 {
     if (sel == 0x40)
     {
@@ -43,9 +43,8 @@
  *
  * Return the address of an instruction operand (from the mod/rm byte).
  */
-static BYTE *INSTR_GetOperandAddr( struct sigcontext_struct *context,
-                                   BYTE *instr, int long_addr,
-                                   int segprefix, int *len )
+static BYTE *INSTR_GetOperandAddr( SIGCONTEXT *context, BYTE *instr,
+                                   int long_addr, int segprefix, int *len )
 {
     int mod, rm, base, index = 0, ss = 0, seg = 0, off;
 
@@ -197,14 +196,16 @@
  *
  * Emulate the LDS (and LES,LFS,etc.) instruction.
  */
-static BOOL INSTR_EmulateLDS( struct sigcontext_struct *context,
-                              BYTE *instr, int long_op, int long_addr,
-                              int segprefix, int *len )
+static BOOL INSTR_EmulateLDS( SIGCONTEXT *context, BYTE *instr, int long_op,
+                              int long_addr, int segprefix, int *len )
 {
+    WORD seg;
     BYTE *regmodrm = instr + 1 + (*instr == 0x0f);
     BYTE *addr = INSTR_GetOperandAddr( context, regmodrm,
                                        long_addr, segprefix, len );
-    WORD seg = *(WORD *)(addr + (long_op ? 4 : 2));
+    if (!addr)
+        return FALSE;  /* Unable to emulate it */
+    seg = *(WORD *)(addr + (long_op ? 4 : 2));
 
     if (!(seg = INSTR_ReplaceSelector( context, seg )))
         return FALSE;  /* Unable to emulate it */
@@ -278,7 +279,7 @@
  *
  * Emulate a priviledged instruction. Returns TRUE if emulation successful.
  */
-BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context )
+BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
 {
     int prefix, segprefix, prefixlen, len, repX, long_op, long_addr;
     BYTE *instr;
@@ -489,8 +490,12 @@
 
         case 0x8e: /* mov XX,segment_reg */
             {
-                WORD seg = *(WORD *)INSTR_GetOperandAddr( context, instr + 1,
+                WORD seg;
+                BYTE *addr = INSTR_GetOperandAddr(context, instr + 1,
                                                   long_addr, segprefix, &len );
+                if (!addr)
+                    break;  /* Unable to emulate it */
+                seg = *(WORD *)addr;
                 if (!(seg = INSTR_ReplaceSelector( context, seg )))
                     break;  /* Unable to emulate it */
 
diff --git a/miscemu/int10.c b/miscemu/int10.c
index 3d93812..c22ba05 100644
--- a/miscemu/int10.c
+++ b/miscemu/int10.c
@@ -13,7 +13,7 @@
  *
  * Handler for int 10h (video).
  */
-void INT_Int10Handler( struct sigcontext_struct context )
+void INT_Int10Handler( SIGCONTEXT context )
 {
     switch(AH_reg(&context))
     {
diff --git a/miscemu/int13.c b/miscemu/int13.c
index f867a92..20f72c1 100644
--- a/miscemu/int13.c
+++ b/miscemu/int13.c
@@ -13,7 +13,7 @@
  *
  * Handler for int 13h (disk I/O).
  */
-void INT_Int13Handler( struct sigcontext_struct context )
+void INT_Int13Handler( SIGCONTEXT context )
 {
     switch(AH_reg(&context))
     {
diff --git a/miscemu/int1a.c b/miscemu/int1a.c
index 738029c..9a0ddf0 100644
--- a/miscemu/int1a.c
+++ b/miscemu/int1a.c
@@ -42,7 +42,7 @@
  *
  * Handler for int 1ah (date and time).
  */
-void INT_Int1aHandler( struct sigcontext_struct context )
+void INT_Int1aHandler( SIGCONTEXT context )
 {
     time_t ltime;
     DWORD ticks;
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 030881b..d301ca6 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -134,7 +134,7 @@
 	}	
 }
 
-static int INT21_GetFreeDiskSpace(struct sigcontext_struct *context)
+static int INT21_GetFreeDiskSpace( SIGCONTEXT *context )
 {
     DWORD cluster_sectors, sector_bytes, free_clusters, total_clusters;
     char root[] = "A:\\";
@@ -149,7 +149,7 @@
     return 1;
 }
 
-static int INT21_GetDriveAllocInfo(struct sigcontext_struct *context)
+static int INT21_GetDriveAllocInfo( SIGCONTEXT *context )
 {
     if (!INT21_GetFreeDiskSpace( context )) return 0;
     heap->mediaID = 0xf0;
@@ -158,7 +158,7 @@
     return 1;
 }
 
-static void GetDrivePB(struct sigcontext_struct *context, int drive)
+static void GetDrivePB( SIGCONTEXT *context, int drive )
 {
         if(!DRIVE_IsValid(drive))
         {
@@ -201,7 +201,7 @@
 }
 
 
-static void ioctlGetDeviceInfo(struct sigcontext_struct *context)
+static void ioctlGetDeviceInfo( SIGCONTEXT *context )
 {
     dprintf_int (stddeb, "int21: ioctl (%d, GetDeviceInfo)\n", BX_reg(context));
     
@@ -214,7 +214,7 @@
     RESET_CFLAG(context);
 }
 
-static void ioctlGenericBlkDevReq(struct sigcontext_struct *context)
+static void ioctlGenericBlkDevReq( SIGCONTEXT *context )
 {
 	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
 	int drive = DOS_GET_DRIVE( BL_reg(context) );
@@ -258,7 +258,7 @@
 	}
 }
 
-static void GetSystemDate(struct sigcontext_struct *context)
+static void GetSystemDate( SIGCONTEXT *context )
 {
 	struct tm *now;
 	time_t ltime;
@@ -271,7 +271,7 @@
 	AX_reg(context) = now->tm_wday;
 }
 
-static void INT21_GetSystemTime(struct sigcontext_struct *context)
+static void INT21_GetSystemTime( SIGCONTEXT *context )
 {
 	struct tm *now;
 	struct timeval tv;
@@ -286,7 +286,7 @@
 					/* Note hundredths of seconds */
 }
 
-static void CreateFile(struct sigcontext_struct *context)
+static void CreateFile( SIGCONTEXT *context )
 {
     AX_reg(context) = _lcreat( PTR_SEG_OFF_TO_LIN( DS_reg(context),
                                           DX_reg(context) ), CX_reg(context) );
@@ -298,7 +298,7 @@
 }
 
 
-void OpenExistingFile(struct sigcontext_struct *context)
+void OpenExistingFile( SIGCONTEXT *context )
 {
     AX_reg(context) = _lopen( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)),
                               AL_reg(context) );
@@ -379,7 +379,7 @@
 #endif
 }
 
-static void CloseFile(struct sigcontext_struct *context)
+static void CloseFile( SIGCONTEXT *context )
 {
     if ((AX_reg(context) = _lclose( BX_reg(context) )) != 0)
     {
@@ -388,7 +388,7 @@
     }
 }
 
-void ExtendedOpenCreateFile(struct sigcontext_struct *context)
+void ExtendedOpenCreateFile(SIGCONTEXT *context )
 {
   BYTE action=DL_reg(context);
   dprintf_int(stddeb, "int21: extended open/create: file= %s \n",
@@ -478,7 +478,7 @@
 }
 
 
-static int INT21_RenameFile(struct sigcontext_struct *context)
+static int INT21_RenameFile( SIGCONTEXT *context )
 {
     const char *newname, *oldname;
     char *buffer;
@@ -511,7 +511,7 @@
 }
 
 
-static void INT21_ChangeDir(struct sigcontext_struct *context)
+static void INT21_ChangeDir( SIGCONTEXT *context )
 {
     int drive;
     char *dirname = PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context));
@@ -531,7 +531,7 @@
 }
 
 
-static int INT21_FindFirst(struct sigcontext_struct *context)
+static int INT21_FindFirst( SIGCONTEXT *context )
 {
     const char *path, *unixPath, *mask;
     char *p;
@@ -566,7 +566,7 @@
 }
 
 
-static int INT21_FindNext(struct sigcontext_struct *context)
+static int INT21_FindNext( SIGCONTEXT *context )
 {
     FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA();
     DOS_DIRENT entry;
@@ -597,7 +597,7 @@
 }
 
 
-static int INT21_CreateTempFile(struct sigcontext_struct *context)
+static int INT21_CreateTempFile( SIGCONTEXT *context )
 {
     static int counter = 0;
     char *name = PTR_SEG_OFF_TO_LIN( DS_reg(context), DX_reg(context) );
@@ -618,7 +618,7 @@
 }
 
 
-static int INT21_GetCurrentDirectory(struct sigcontext_struct *context)
+static int INT21_GetCurrentDirectory( SIGCONTEXT *context ) 
 {
     int drive = DOS_GET_DRIVE( DL_reg(context) );
     char *ptr = (char *)PTR_SEG_OFF_TO_LIN( DS_reg(context), SI_reg(context) );
@@ -635,7 +635,7 @@
 }
 
 
-static int INT21_GetDiskSerialNumber(struct sigcontext_struct *context)
+static int INT21_GetDiskSerialNumber( SIGCONTEXT *context )
 {
     BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
     int drive = DOS_GET_DRIVE( BL_reg(context) );
@@ -654,7 +654,7 @@
 }
 
 
-static int INT21_SetDiskSerialNumber(struct sigcontext_struct *context)
+static int INT21_SetDiskSerialNumber( SIGCONTEXT *context )
 {
     BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
     int drive = DOS_GET_DRIVE( BL_reg(context) );
@@ -673,7 +673,7 @@
 /* microsoft's programmers should be shot for using CP/M style int21
    calls in Windows for Workgroup's winfile.exe */
 
-static int INT21_FindFirstFCB( struct sigcontext_struct *context )
+static int INT21_FindFirstFCB( SIGCONTEXT *context )
 {
     BYTE *fcb = (BYTE *)PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
     FINDFILE_FCB *pFCB;
@@ -701,7 +701,7 @@
 }
 
 
-static int INT21_FindNextFCB( struct sigcontext_struct *context )
+static int INT21_FindNextFCB( SIGCONTEXT *context )
 {
     BYTE *fcb = (BYTE *)PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
     FINDFILE_FCB *pFCB;
@@ -743,7 +743,7 @@
 }
 
 
-static void DeleteFileFCB(struct sigcontext_struct *context)
+static void DeleteFileFCB( SIGCONTEXT *context )
 {
     fprintf( stderr, "DeleteFileFCB: not implemented yet\n" );
 #if 0
@@ -785,7 +785,7 @@
 #endif
 }
 
-static void RenameFileFCB(struct sigcontext_struct *context)
+static void RenameFileFCB( SIGCONTEXT *context )
 {
     fprintf( stderr, "RenameFileFCB: not implemented yet\n" );
 #if 0
@@ -831,7 +831,7 @@
 
 
 
-static void fLock (struct sigcontext_struct * context)
+static void fLock( SIGCONTEXT * context )
 {
 #if 0
     struct flock f;
@@ -882,7 +882,7 @@
 } 
 
 
-static int INT21_GetFileAttribute (struct sigcontext_struct * context)
+static int INT21_GetFileAttribute( SIGCONTEXT * context )
 {
     const char *unixName;
 
@@ -901,7 +901,7 @@
 /***********************************************************************
  *           DOS3Call  (KERNEL.102)
  */
-void DOS3Call( struct sigcontext_struct context )
+void DOS3Call( SIGCONTEXT context )
 {
     dprintf_int( stddeb, "int21: AX=%04x BX=%04x CX=%04x DX=%04x "
                  "SI=%04x DI=%04x DS=%04x ES=%04x EFL=%08lx\n",
@@ -1136,8 +1136,8 @@
         break;
 	
     case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */
-        if (!FILE_RemoveDir( PTR_SEG_OFF_TO_LIN( DS_reg(&context),
-                                                 DX_reg(&context) )))
+        if (!RemoveDirectory32A( PTR_SEG_OFF_TO_LIN( DS_reg(&context),
+                                                     DX_reg(&context) )))
         {
             AX_reg(&context) = DOS_ExtendedError;
             SET_CFLAG(&context);
@@ -1201,8 +1201,8 @@
         break;
 
     case 0x41: /* "UNLINK" - DELETE FILE */
-        if (!FILE_Unlink( PTR_SEG_OFF_TO_LIN( DS_reg(&context),
-                                              DX_reg(&context) )))
+        if (!DeleteFile32A( PTR_SEG_OFF_TO_LIN( DS_reg(&context),
+                                                DX_reg(&context) )))
         {
             AX_reg(&context) = DOS_ExtendedError;
             SET_CFLAG(&context);
@@ -1252,7 +1252,7 @@
             break;
 
         case 0x08:   /* Check if drive is removable. */
-            switch(GetDriveType( DOS_GET_DRIVE( BL_reg(&context) )))
+            switch(GetDriveType16( DOS_GET_DRIVE( BL_reg(&context) )))
             {
             case DRIVE_CANNOTDETERMINE:
                 DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk );
@@ -1269,7 +1269,7 @@
             break;
 
         case 0x09:   /* CHECK IF BLOCK DEVICE REMOTE */
-            switch(GetDriveType( DOS_GET_DRIVE( BL_reg(&context) )))
+            switch(GetDriveType16( DOS_GET_DRIVE( BL_reg(&context) )))
             {
             case DRIVE_CANNOTDETERMINE:
                 DOS_ERROR( ER_InvalidDrive, EC_NotFound, SA_Abort, EL_Disk );
diff --git a/miscemu/int25.c b/miscemu/int25.c
index 799816a..1f4832d 100644
--- a/miscemu/int25.c
+++ b/miscemu/int25.c
@@ -16,7 +16,7 @@
  *
  * Handler for int 25h (absolute disk read).
  */
-void INT_Int25Handler( struct sigcontext_struct context )
+void INT_Int25Handler( SIGCONTEXT context )
 {
     BYTE *dataptr = PTR_SEG_OFF_TO_LIN( DS_reg(&context), BX_reg(&context) );
     DWORD begin, length;
diff --git a/miscemu/int26.c b/miscemu/int26.c
index 53f1abc..270de63 100644
--- a/miscemu/int26.c
+++ b/miscemu/int26.c
@@ -15,7 +15,7 @@
  *
  * Handler for int 26h (absolute disk read).
  */
-void INT_Int26Handler( struct sigcontext_struct context )
+void INT_Int26Handler( SIGCONTEXT context )
 {
     BYTE *dataptr = PTR_SEG_OFF_TO_LIN( DS_reg(&context), BX_reg(&context) );
     DWORD begin, length;
diff --git a/miscemu/int2a.c b/miscemu/int2a.c
index 13de9ff..4dfa3e9 100644
--- a/miscemu/int2a.c
+++ b/miscemu/int2a.c
@@ -13,7 +13,7 @@
  *
  * Handler for int 2ah (network).
  */
-void INT_Int2aHandler( struct sigcontext_struct context )
+void INT_Int2aHandler( SIGCONTEXT context )
 {
     switch(AH_reg(&context))
     {
diff --git a/miscemu/int2f.c b/miscemu/int2f.c
index fdfd3a5..ad8817d 100644
--- a/miscemu/int2f.c
+++ b/miscemu/int2f.c
@@ -17,15 +17,15 @@
   /* base WPROCS.DLL ordinal number for VxDs */
 #define VXD_BASE 400
 
-static void do_int2f_16(struct sigcontext_struct *context);
-void do_mscdex(struct sigcontext_struct *context);
+static void do_int2f_16( SIGCONTEXT *context );
+void do_mscdex( SIGCONTEXT *context );
 
 /**********************************************************************
  *	    INT_Int2fHandler
  *
  * Handler for int 2fh (multiplex).
  */
-void INT_Int2fHandler( struct sigcontext_struct context )
+void INT_Int2fHandler( SIGCONTEXT context )
 {
     switch(AH_reg(&context))
     {
@@ -67,7 +67,7 @@
 /**********************************************************************
  *	    do_int2f_16
  */
-static void do_int2f_16(struct sigcontext_struct *context)
+static void do_int2f_16( SIGCONTEXT *context )
 {
     DWORD addr;
 
@@ -138,7 +138,7 @@
     }
 }
 
-void do_mscdex(struct sigcontext_struct *context)
+void do_mscdex( SIGCONTEXT *context )
 {
     int drive, count;
     char *p;
diff --git a/miscemu/int4b.c b/miscemu/int4b.c
index 16cf0b6..e78e285 100644
--- a/miscemu/int4b.c
+++ b/miscemu/int4b.c
@@ -15,7 +15,7 @@
  *           INT_Int4bHandler
  *
  */
-void INT_Int4bHandler( struct sigcontext_struct context )
+void INT_Int4bHandler( SIGCONTEXT context )
 {
 
   switch(AH_reg(&context))
diff --git a/miscemu/int5c.c b/miscemu/int5c.c
index 28540f2..190c0e1 100644
--- a/miscemu/int5c.c
+++ b/miscemu/int5c.c
@@ -18,7 +18,7 @@
  *
  * Also handler for interrupt 5c. 
  */
-void NetBIOSCall( struct sigcontext_struct context )
+void NetBIOSCall( SIGCONTEXT context )
 {
   BYTE* ptr;
 
diff --git a/miscemu/interrupts.c b/miscemu/interrupts.c
index 308d69f..3b3d3fe 100644
--- a/miscemu/interrupts.c
+++ b/miscemu/interrupts.c
@@ -28,7 +28,7 @@
 BOOL INT_Init(void)
 {
     WORD vector;
-    HMODULE hModule = GetModuleHandle( "WPROCS" );
+    HMODULE16 hModule = GetModuleHandle( "WPROCS" );
 
     for (vector = 0; vector < 256; vector++)
     {
@@ -70,7 +70,7 @@
 /**********************************************************************
  *	    INT_DummyHandler
  */
-void INT_DummyHandler( struct sigcontext_struct context )
+void INT_DummyHandler( SIGCONTEXT context )
 {
     WORD ordinal;
     char *name;
@@ -85,7 +85,7 @@
  *
  * Handler for int 11h (get equipment list).
  */
-void INT_Int11Handler( struct sigcontext_struct context )
+void INT_Int11Handler( SIGCONTEXT context )
 {
     int diskdrives = 0;
     int parallelports = 0;
@@ -144,7 +144,7 @@
  *
  * Handler for int 12h (get memory size).
  */
-void INT_Int12Handler( struct sigcontext_struct context )
+void INT_Int12Handler( SIGCONTEXT context )
 {
     AX_reg(&context) = 640;
 }
@@ -155,7 +155,7 @@
  *
  * Handler for int 15h.
  */
-void INT_Int15Handler( struct sigcontext_struct context )
+void INT_Int15Handler( SIGCONTEXT context )
 {
     INT_BARF( &context, 0x15 );
 }
@@ -166,7 +166,7 @@
  *
  * Handler for int 16h (keyboard).
  */
-void INT_Int16Handler( struct sigcontext_struct context )
+void INT_Int16Handler( SIGCONTEXT context )
 {
     INT_BARF( &context, 0x16 );
 }
diff --git a/miscemu/vxd.c b/miscemu/vxd.c
index 95712f4..b1bb3b0 100644
--- a/miscemu/vxd.c
+++ b/miscemu/vxd.c
@@ -17,7 +17,7 @@
 /***********************************************************************
  *           VXD_PageFile
  */
-void VXD_PageFile( struct sigcontext_struct context )
+void VXD_PageFile( SIGCONTEXT context )
 {
     /* taken from Ralf Brown's Interrupt List */
 
@@ -62,7 +62,7 @@
 /***********************************************************************
  *           VXD_Shell
  */
-void VXD_Shell( struct sigcontext_struct context )
+void VXD_Shell( SIGCONTEXT context )
 {
     dprintf_vxd(stddeb,"VxD Shell called ...\n");
 
@@ -120,7 +120,7 @@
 /***********************************************************************
  *           VXD_Comm
  */
-void VXD_Comm( struct sigcontext_struct context )
+void VXD_Comm( SIGCONTEXT context )
 {
     dprintf_vxd(stddeb,"VxD Comm called ...\n");
 
diff --git a/multimedia/mcicda.c b/multimedia/mcicda.c
index e517fe6..80c2151 100644
--- a/multimedia/mcicda.c
+++ b/multimedia/mcicda.c
@@ -394,8 +394,9 @@
 		}
 	switch (CDADev[wDevID].sc.cdsc_audiostatus) {
 		case CDROM_AUDIO_INVALID:
-            		dprintf_cdaudio(stddeb,"CDAUDIO_GetCDStatus // device doesn't support status !\n");
-			return FALSE;
+            		dprintf_cdaudio(stddeb,"CDAUDIO_GetCDStatus // device doesn't support status, returning NOT_READY.\n");
+			CDADev[wDevID].mode = MCI_MODE_NOT_READY;
+			break;
 		case CDROM_AUDIO_NO_STATUS: 
 			CDADev[wDevID].mode = MCI_MODE_STOP;
             		dprintf_cdaudio(stddeb,"CDAUDIO_GetCDStatus // MCI_MODE_STOP !\n");
@@ -737,7 +738,10 @@
     	dprintf_cdaudio(stddeb,"CDAUDIO_mciSeek(%u, %08lX, %p);\n", 
 		wDevID, dwFlags, lpParms);
 	if (lpParms == NULL) return MCIERR_INTERNAL;
-	if (ioctl(CDADev[wDevID].unixdev, CDROMRESUME)) return MCIERR_HARDWARE;
+	if (ioctl(CDADev[wDevID].unixdev, CDROMRESUME)) {
+		perror("ioctl CDROMRESUME");
+		return MCIERR_HARDWARE;
+	}
 	CDADev[wDevID].mode = MCI_MODE_SEEK;
 	switch(dwFlags) {
 		case MCI_SEEK_TO_START:
diff --git a/multimedia/mcistring.c b/multimedia/mcistring.c
index c21081a..8e7c2d4 100644
--- a/multimedia/mcistring.c
+++ b/multimedia/mcistring.c
@@ -35,7 +35,7 @@
 /* FIXME: I need to remember the aliasname of a spec. driver. 
  *        and this is the easiest way. *sigh*
  */
-static MCI_OPEN_PARMS		mciOpenDrv[MAXMCIDRIVERS];
+extern MCI_OPEN_PARMS		mciOpenDrv[MAXMCIDRIVERS];
 
 LONG DrvDefDriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, 
 		      DWORD dwParam1, DWORD dwParam2);
@@ -2087,7 +2087,7 @@
 	DWORD	dwFlags;
 	int	res=0,i,nrofkeywords;
 
-	dprintf_mci(stdnimp,"mciSendString('%s', %p, %d, %X)\n", lpstrCommand, 
+	dprintf_mci(stddeb,"mciSendString('%s', %p, %d, %X)\n", lpstrCommand, 
 		lpstrReturnString, uReturnLength, hwndCallback
 	);
 	/* format is <command> <device> <optargs> */
@@ -2146,7 +2146,7 @@
 			dname=(SEGPTR)mciOpenDrv[wDevID].lpstrAlias;
 			if (dname==NULL) 
 				dname=(SEGPTR)mciOpenDrv[wDevID].lpstrDeviceType;
-			if (!STRCMP(PTR_SEG_TO_LIN(dname),dev))
+			if ((dname!=NULL)&&(!STRCMP(PTR_SEG_TO_LIN(dname),dev)))
 				break;
 			if (++wDevID >= MAXMCIDRIVERS) {
 				dprintf_mci(stddeb, __FILE__":mciSendString:MAXMCIDRIVERS reached!\n");
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index f2d40f0..283c928 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -31,6 +31,10 @@
 static LPSTR	lpInstallNames = NULL;
 
 MCI_OPEN_DRIVER_PARMS	mciDrv[MAXMCIDRIVERS];
+/* struct below is to remember alias/devicenames for mcistring.c 
+ * FIXME: should use some internal struct ... 
+ */
+MCI_OPEN_PARMS		mciOpenDrv[MAXMCIDRIVERS];
 
 UINT midiGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
 UINT waveGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
@@ -547,12 +551,21 @@
 /**************************************************************************
 * 				mciOpen					[internal]
 */
+
+#define	_MCI_STRDUP_TO_SEG(dest,source) {\
+	HANDLE	x;\
+	x=USER_HEAP_ALLOC(strlen(source));\
+	dest=(LPSTR)MAKELONG(x,USER_HeapSel);\
+	strcpy(PTR_SEG_TO_LIN(dest),source);\
+}
+
 DWORD mciOpen(DWORD dwParam, LPMCI_OPEN_PARMS lp16Parms)
 {
 	char	str[128];
 	LPMCI_OPEN_PARMS lpParms;
 	UINT	uDevTyp = 0;
 	UINT	wDevID = 0;
+
 	lpParms = PTR_SEG_TO_LIN(lp16Parms);
 	dprintf_mmsys(stddeb, "mciOpen(%08lX, %p (%p))\n", dwParam, lp16Parms, lpParms);
 	if (lp16Parms == NULL) return MCIERR_INTERNAL;
@@ -560,46 +573,52 @@
 		if (++wDevID >= MAXMCIDRIVERS) {
 			dprintf_mmsys(stddeb, "MCI_OPEN // MAXMCIDRIVERS reached !\n");
 			return MCIERR_INTERNAL;
-			}
 		}
+	}
 	dprintf_mmsys(stddeb, "mciOpen // wDevID=%d \n", wDevID);
+
+	memcpy(&mciOpenDrv[wDevID],lpParms,sizeof(*lpParms));
 	if (dwParam & MCI_OPEN_ALIAS) {
 		dprintf_mmsys(stddeb, "MCI_OPEN // Alias='%s' !\n",
 			(char*)PTR_SEG_TO_LIN(lpParms->lpstrAlias));
-		uDevTyp = MCI_DEVTYPE_WAVEFORM_AUDIO;
- 		}
+		_MCI_STRDUP_TO_SEG(
+			mciOpenDrv[wDevID].lpstrAlias,
+			(char*)PTR_SEG_TO_LIN(lpParms->lpstrAlias)
+		);
+		/* mplayer does allocate alias to CDAUDIO */
+	}
 	if (dwParam & MCI_OPEN_TYPE) {
 		if (dwParam & MCI_OPEN_TYPE_ID) {
 			dprintf_mmsys(stddeb, "MCI_OPEN // Dev=%p !\n", lpParms->lpstrDeviceType);
 			uDevTyp = LOWORD((DWORD)lpParms->lpstrDeviceType);
-			}
-		else {
+			mciOpenDrv[wDevID].lpstrDeviceType=lpParms->lpstrDeviceType;
+		} else {
 			if (lpParms->lpstrDeviceType == NULL) return MCIERR_INTERNAL;
 			dprintf_mmsys(stddeb, "MCI_OPEN // Dev='%s' !\n",
                               (char*)PTR_SEG_TO_LIN(lpParms->lpstrDeviceType));
+			_MCI_STRDUP_TO_SEG(
+				mciOpenDrv[wDevID].lpstrDeviceType,
+				(char*)PTR_SEG_TO_LIN(lpParms->lpstrDeviceType)
+			);
 			strcpy(str, PTR_SEG_TO_LIN(lpParms->lpstrDeviceType));
 			AnsiUpper(str);
 			if (strcmp(str, "CDAUDIO") == 0) {
 				uDevTyp = MCI_DEVTYPE_CD_AUDIO;
-				}
-			else
+			} else
 			if (strcmp(str, "WAVEAUDIO") == 0) {
 				uDevTyp = MCI_DEVTYPE_WAVEFORM_AUDIO;
-				}
-			else
+			} else
 			if (strcmp(str, "SEQUENCER") == 0)	{
 				uDevTyp = MCI_DEVTYPE_SEQUENCER;
-				}
-			else
+			} else
 			if (strcmp(str, "ANIMATION1") == 0) {
 				uDevTyp = MCI_DEVTYPE_ANIMATION;
-				}
-			else
+			} else
 			if (strcmp(str, "AVIVIDEO") == 0) {
 				uDevTyp = MCI_DEVTYPE_DIGITAL_VIDEO;
-				}
 			}
 		}
+	}
 	mciDrv[wDevID].wType = uDevTyp;
 	mciDrv[wDevID].wDeviceID = wDevID;
 	lpParms->wDeviceID = wDevID;
diff --git a/objects/dib.c b/objects/dib.c
index becf185..8190af4 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -101,7 +101,7 @@
  * Get the info from a bitmap header.
  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
  */
-static int DIB_GetBitmapInfo( BITMAPINFOHEADER *header, DWORD *width,
+static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
                               DWORD *height, WORD *bpp )
 {
     if (header->biSize == sizeof(BITMAPINFOHEADER))
@@ -639,10 +639,10 @@
 
 
 /***********************************************************************
- *           SetDIBits    (GDI.440)
+ *           SetDIBits    (GDI.440) (GDI32.312)
  */
-int SetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
-	       LPSTR bits, BITMAPINFO * info, WORD coloruse )
+INT16 SetDIBits( HDC32 hdc, HBITMAP32 hbitmap, UINT32 startscan, UINT32 lines,
+                 LPCVOID bits, const BITMAPINFO *info, UINT32 coloruse )
 {
     DC * dc;
     BITMAPOBJ * bmp;
@@ -670,11 +670,12 @@
 
 
 /***********************************************************************
- *           SetDIBitsToDevice    (GDI.443)
+ *           SetDIBitsToDevice    (GDI.443) (GDI32.313)
  */
-int SetDIBitsToDevice( HDC hdc, short xDest, short yDest, WORD cx, WORD cy,
-		       WORD xSrc, WORD ySrc, WORD startscan, WORD lines,
-		       LPSTR bits, BITMAPINFO * info, WORD coloruse )
+INT16 SetDIBitsToDevice( HDC32 hdc, INT32 xDest, INT32 yDest, DWORD cx,
+                         DWORD cy, INT32 xSrc, INT32 ySrc, UINT32 startscan,
+                         UINT32 lines, LPCVOID bits, const BITMAPINFO *info,
+                         UINT32 coloruse )
 {
     DC * dc;
     DWORD width, height, compression = 0;
diff --git a/objects/font.c b/objects/font.c
index a259011..39dac67 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -24,7 +24,7 @@
 
 #define FONTCACHE 	32	/* dynamic font cache size */
 #define MAX_FONTS	256
-static LPLOGFONT16 lpLogFontList[MAX_FONTS];
+static LPLOGFONT16 lpLogFontList[MAX_FONTS+1];
 
 static int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz);
 
@@ -266,7 +266,8 @@
     if (!*font->lfFaceName)
       ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
       /* we need a font name for function GetTextFace() even if there isn't one ;-) */  
-    
+    AnsiUpper(font->lfFaceName);
+
     fontStruct = XLoadQueryFont( display, *names );
     XFreeFontNames( names );
     return fontStruct;
@@ -701,9 +702,9 @@
 
 
 /***********************************************************************
- *           GetTextMetrics    (GDI.93)
+ *           GetTextMetrics16    (GDI.93)
  */
-BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC16 metrics )
+BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return FALSE;
@@ -770,6 +771,68 @@
 
 
 /***********************************************************************
+ *           GetTextMetrics32A    (GDI32.236)
+ */
+BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
+{
+    TEXTMETRIC16 tm;
+    if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
+    metrics->tmHeight           = tm.tmHeight;
+    metrics->tmAscent           = tm.tmAscent;
+    metrics->tmDescent          = tm.tmDescent;
+    metrics->tmInternalLeading  = tm.tmInternalLeading;
+    metrics->tmExternalLeading  = tm.tmExternalLeading;
+    metrics->tmAveCharWidth     = tm.tmAveCharWidth;
+    metrics->tmMaxCharWidth     = tm.tmMaxCharWidth;
+    metrics->tmWeight           = tm.tmWeight;
+    metrics->tmOverhang         = tm.tmOverhang;
+    metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
+    metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
+    metrics->tmFirstChar        = tm.tmFirstChar;
+    metrics->tmLastChar         = tm.tmLastChar;
+    metrics->tmDefaultChar      = tm.tmDefaultChar;
+    metrics->tmBreakChar        = tm.tmBreakChar;
+    metrics->tmItalic           = tm.tmItalic;
+    metrics->tmUnderlined       = tm.tmUnderlined;
+    metrics->tmStruckOut        = tm.tmStruckOut;
+    metrics->tmPitchAndFamily   = tm.tmPitchAndFamily;
+    metrics->tmCharSet          = tm.tmCharSet;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           GetTextMetrics32W    (GDI32.237)
+ */
+BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
+{
+    TEXTMETRIC16 tm;
+    if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
+    metrics->tmHeight           = tm.tmHeight;
+    metrics->tmAscent           = tm.tmAscent;
+    metrics->tmDescent          = tm.tmDescent;
+    metrics->tmInternalLeading  = tm.tmInternalLeading;
+    metrics->tmExternalLeading  = tm.tmExternalLeading;
+    metrics->tmAveCharWidth     = tm.tmAveCharWidth;
+    metrics->tmMaxCharWidth     = tm.tmMaxCharWidth;
+    metrics->tmWeight           = tm.tmWeight;
+    metrics->tmOverhang         = tm.tmOverhang;
+    metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
+    metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
+    metrics->tmFirstChar        = tm.tmFirstChar;
+    metrics->tmLastChar         = tm.tmLastChar;
+    metrics->tmDefaultChar      = tm.tmDefaultChar;
+    metrics->tmBreakChar        = tm.tmBreakChar;
+    metrics->tmItalic           = tm.tmItalic;
+    metrics->tmUnderlined       = tm.tmUnderlined;
+    metrics->tmStruckOut        = tm.tmStruckOut;
+    metrics->tmPitchAndFamily   = tm.tmPitchAndFamily;
+    metrics->tmCharSet          = tm.tmCharSet;
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           SetMapperFlags    (GDI.349)
  */
 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
@@ -894,23 +957,31 @@
   char 	slant, spacing;
   int 	i, count;
   LPLOGFONT16 lpNewFont;
+
+  dprintf_font(stddeb,"InitFontsList !\n");
+
   weight = "medium";
   slant = 'r';
   spacing = '*';
   charset = "*";
   family = "*-*";
-  dprintf_font(stddeb,"InitFontsList !\n");
+
   sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
 	  family, weight, slant, spacing, charset);
   names = XListFonts( display, pattern, MAX_FONTS, &count );
   dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
+
+  lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
+  if (lpNewFont == NULL) {
+      dprintf_font(stddeb,
+		   "InitFontsList // Error alloc new font structure !\n");
+      XFreeFontNames(names);
+      return;
+  }
+
   for (i = 0; i < count; i++) {
-    lpNewFont = malloc(sizeof(LOGFONT16) + LF_FACESIZE);
-    if (lpNewFont == NULL) {
-      dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
-      break;
-    }
     dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
+
     ParseFontParms(names[i], 2, str, sizeof(str));
 #if 0
     /* not necessary because new function FONT_ChkX11Family() */
@@ -950,12 +1021,21 @@
       lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
       break;
     }
-    dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
-    dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
-    dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
+    dprintf_font( stddeb,
+		  "InitFontsList // lpNewFont->lfHeight=%d\n",
+		  lpNewFont->lfHeight );
+    dprintf_font( stddeb,
+		  "InitFontsList // lpNewFont->lfWidth=%d\n",
+		  lpNewFont->lfWidth );
+    dprintf_font( stddeb,
+		  "InitFontsList // lfFaceName='%s'\n",
+		  lpNewFont->lfFaceName );
     lpLogFontList[i] = lpNewFont;
-    lpLogFontList[i+1] = NULL;
+    lpNewFont = (LPLOGFONT16)
+      ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
   }
+  lpLogFontList[i] = NULL;
+
   qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
   XFreeFontNames(names);
 }
@@ -976,7 +1056,7 @@
   char	       FaceName[LF_FACESIZE];
   int          nRet = 0;
   int          i;
-  
+
   dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n", 
 	       hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
   if (lpEnumFunc == 0) return 0;
@@ -1014,7 +1094,7 @@
     memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT16) + LF_FACESIZE);
     hFont = CreateFontIndirect(lpLogFont);
     hOldFont = SelectObject(hDC, hFont);
-    GetTextMetrics(hDC, lptm);
+    GetTextMetrics16(hDC, lptm);
     SelectObject(hDC, hOldFont);
     DeleteObject(hFont);
     dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
@@ -1083,7 +1163,7 @@
     strcpy(lpEnumLogFont->elfStyle,"");
     hFont = CreateFontIndirect((LPLOGFONT16)lpEnumLogFont);
     hOldFont = SelectObject(hDC, hFont);
-    GetTextMetrics(hDC, lptm);
+    GetTextMetrics16(hDC, lptm);
     SelectObject(hDC, hOldFont);
     DeleteObject(hFont);
     dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index ddf0a21..98289bc 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -161,7 +161,7 @@
  *
  * GDI initialization.
  */
-BOOL GDI_Init(void)
+BOOL32 GDI_Init(void)
 {
     HPALETTE16 hpalette;
 
@@ -203,7 +203,7 @@
 /***********************************************************************
  *           GDI_AllocObject
  */
-HANDLE GDI_AllocObject( WORD size, WORD magic )
+HANDLE16 GDI_AllocObject( WORD size, WORD magic )
 {
     static DWORD count = 0;
     GDIOBJHDR * obj;
@@ -220,7 +220,7 @@
 /***********************************************************************
  *           GDI_FreeObject
  */
-BOOL GDI_FreeObject( HANDLE handle )
+BOOL32 GDI_FreeObject( HANDLE16 handle )
 {
     GDIOBJHDR * object;
 
@@ -244,7 +244,7 @@
  * Return a pointer to the GDI object associated to the handle.
  * Return NULL if the object has the wrong magic number.
  */
-GDIOBJHDR * GDI_GetObjPtr( HANDLE handle, WORD magic )
+GDIOBJHDR * GDI_GetObjPtr( HANDLE16 handle, WORD magic )
 {
     GDIOBJHDR * ptr = NULL;
 
diff --git a/objects/region.c b/objects/region.c
index 29bcbc1..0b43fb9 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -2,9 +2,9 @@
  * GDI region objects
  *
  * Copyright 1993, 1994, 1995 Alexandre Julliard
- *
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <stdlib.h>
 #include <stdio.h>
 #include "region.h"
@@ -15,7 +15,7 @@
 /***********************************************************************
  *           REGION_DeleteObject
  */
-BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj )
+BOOL16 REGION_DeleteObject( HRGN32 hrgn, RGNOBJ * obj )
 {
     dprintf_region(stddeb, "DeleteRegion: %04x\n", hrgn );
     if (obj->xrgn) XDestroyRegion( obj->xrgn );
@@ -76,9 +76,9 @@
 /***********************************************************************
  *           CreateRectRgn    (GDI.64) (GDI32.59)
  */
-HRGN CreateRectRgn( INT32 left, INT32 top, INT32 right, INT32 bottom )
+HRGN16 CreateRectRgn( INT32 left, INT32 top, INT32 right, INT32 bottom )
 {
-    HRGN hrgn;
+    HRGN16 hrgn;
     RGNOBJ *obj;
 
     if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
@@ -121,7 +121,7 @@
 /***********************************************************************
  *           SetRectRgn    (GDI.172) (GDI32.332)
  */
-void SetRectRgn( HRGN32 hrgn, INT32 left, INT32 top, INT32 right, INT32 bottom)
+VOID SetRectRgn( HRGN32 hrgn, INT32 left, INT32 top, INT32 right, INT32 bottom)
 {
     RGNOBJ * obj;
 
@@ -143,11 +143,11 @@
 /***********************************************************************
  *           CreateRoundRectRgn    (GDI.444) (GDI32.61)
  */
-HRGN CreateRoundRectRgn( INT32 left, INT32 top, INT32 right, INT32 bottom,
-			 INT32 ellipse_width, INT32 ellipse_height )
+HRGN16 CreateRoundRectRgn( INT32 left, INT32 top, INT32 right, INT32 bottom,
+                           INT32 ellipse_width, INT32 ellipse_height )
 {
     RGNOBJ * obj;
-    HRGN hrgn;
+    HRGN16 hrgn;
     XRectangle rect;
     int asq, bsq, d, xd, yd;
 
@@ -239,7 +239,7 @@
 /***********************************************************************
  *           CreateEllipticRgn    (GDI.54) (GDI32.39)
  */
-HRGN CreateEllipticRgn( INT32 left, INT32 top, INT32 right, INT32 bottom )
+HRGN16 CreateEllipticRgn( INT32 left, INT32 top, INT32 right, INT32 bottom )
 {
     return CreateRoundRectRgn( left, top, right, bottom,
                                right-left, bottom-top );
@@ -282,7 +282,7 @@
                                INT16 nbpolygons, INT16 mode )
 {
     RGNOBJ * obj;
-    HRGN hrgn;
+    HRGN16 hrgn;
     int i, j, maxPoints;
     XPoint *xpoints, *pt;
     Region xrgn;
@@ -345,7 +345,7 @@
 /***********************************************************************
  *           PtInRegion    (GDI.161) (GDI32.278)
  */
-BOOL PtInRegion( HRGN32 hrgn, INT32 x, INT32 y )
+BOOL16 PtInRegion( HRGN32 hrgn, INT32 x, INT32 y )
 {
     RGNOBJ * obj;
     
@@ -388,7 +388,7 @@
 /***********************************************************************
  *           EqualRgn    (GDI.72) (GDI32.90)
  */
-BOOL EqualRgn( HRGN32 rgn1, HRGN32 rgn2 )
+BOOL16 EqualRgn( HRGN32 rgn1, HRGN32 rgn2 )
 {
     RGNOBJ *obj1, *obj2;
     if (!(obj1 = (RGNOBJ *) GDI_GetObjPtr( rgn1, REGION_MAGIC ))) return FALSE;
@@ -428,7 +428,7 @@
  *
  * Create a region that is a frame around another region
  */
-BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT32 x, INT32 y )
+BOOL16 REGION_FrameRgn( HRGN32 hDest, HRGN32 hSrc, INT32 x, INT32 y )
 {
     RGNOBJ *destObj,*srcObj;
     Region result;
diff --git a/objects/text.c b/objects/text.c
index d6ee0eb..f8f8258 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -205,7 +205,7 @@
     if (count == -1) count = strlen(str);
     strPtr = str;
 
-    GetTextMetrics(hdc, &tm);
+    GetTextMetrics16(hdc, &tm);
     if (flags & DT_EXTERNALLEADING)
 	lh = tm.tmHeight + tm.tmExternalLeading;
     else
@@ -351,17 +351,34 @@
 	x = dc->w.CursPosX;
 	y = dc->w.CursPosY;
     }
+
+    if (flags & (ETO_OPAQUE | ETO_CLIPPED))  /* there's a rectangle */
+    {
+        if (!lprect)  /* not always */
+        {
+            SIZE16 sz;
+            if (flags & ETO_CLIPPED)  /* Can't clip with no rectangle */
+	      return FALSE;
+	    if (!GetTextExtentPoint16( hdc, str, count, &sz ))
+	      return FALSE;
+	    rect.left   = XLPTODP( dc, x );
+	    rect.right  = XLPTODP( dc, x+sz.cx );
+	    rect.top    = YLPTODP( dc, y );
+	    rect.bottom = YLPTODP( dc, y+sz.cy );
+	}
+	else
+	{
+	    rect.left   = XLPTODP( dc, lprect->left );
+	    rect.right  = XLPTODP( dc, lprect->right );
+	    rect.top    = YLPTODP( dc, lprect->top );
+	    rect.bottom = YLPTODP( dc, lprect->bottom );
+	}
+	if (rect.right < rect.left) SWAP_INT( rect.left, rect.right );
+	if (rect.bottom < rect.top) SWAP_INT( rect.top, rect.bottom );
+    }
+
     x = XLPTODP( dc, x );
     y = YLPTODP( dc, y );
-    if (flags & (ETO_OPAQUE | ETO_CLIPPED))  /* There's a rectangle */
-    {
-        rect.left   = XLPTODP( dc, lprect->left );
-        rect.right  = XLPTODP( dc, lprect->right );
-        rect.top    = YLPTODP( dc, lprect->top );
-        rect.bottom = YLPTODP( dc, lprect->bottom );
-        if (rect.right < rect.left) SWAP_INT( rect.left, rect.right );
-        if (rect.bottom < rect.top) SWAP_INT( rect.top, rect.bottom );
-    }
 
     dprintf_text(stddeb,"\treal coord: x=%i, y=%i, rect=(%d,%d-%d,%d)\n",
 			  x, y, rect.left, rect.top, rect.right, rect.bottom);
@@ -641,7 +658,7 @@
     else
     {
         TEXTMETRIC16 tm;
-        GetTextMetrics( hdc, &tm );
+        GetTextMetrics16( hdc, &tm );
         defWidth = 8 * tm.tmAveCharWidth;
     }
     
diff --git a/programs/progman/program.c b/programs/progman/program.c
index 84d4fff..7855dfe 100644
--- a/programs/progman/program.c
+++ b/programs/progman/program.c
@@ -257,7 +257,7 @@
   LPSTR lpszCmdLine = LocalLock(program->hCmdLine);
   LPSTR lpszWorkDir = LocalLock(program->hWorkDir);
 
-  /* FIXME set working direktory */
+  /* FIXME set working directory */
   lpszWorkDir = lpszWorkDir;
 
   WinExec(lpszCmdLine, program->nCmdShow);
diff --git a/tools/build.c b/tools/build.c
index a60ed33..d72a5fc 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -81,7 +81,7 @@
 char DLLName[80];
 int Limit = 0;
 int Base = 0;
-int HeapSize = 0;
+int DLLHeapSize = 0;
 FILE *SpecFp;
 
 char *ParseBuffer = NULL;
@@ -93,8 +93,7 @@
 
   /* Offset of register relative to the end of the context struct */
 #define CONTEXTOFFSET(reg) \
-  ((int)&reg##_reg((struct sigcontext_struct *)0) \
-   - sizeof(struct sigcontext_struct))
+    ((int)&reg##_reg((SIGCONTEXT *)0) - sizeof(SIGCONTEXT))
 
 static void *xmalloc (size_t size)
 {
@@ -521,7 +520,7 @@
 		fprintf(stderr, "%d: Expected number after heap\n", Line);
 		exit(1);
             }
-            HeapSize = atoi(token);
+            DLLHeapSize = atoi(token);
 	}
 	else if (IsNumberString(token))
 	{
@@ -631,7 +630,7 @@
     pModule->next = 0;
     pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN | NE_FFLAGS_LIBMODULE;
     pModule->dgroup = 2;
-    pModule->heap_size = HeapSize;
+    pModule->heap_size = DLLHeapSize;
     pModule->stack_size = 0;
     pModule->ip = 0;
     pModule->cs = 0;
@@ -815,7 +814,7 @@
     pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN |
                      NE_FFLAGS_LIBMODULE | NE_FFLAGS_WIN32;
     pModule->dgroup = 0;
-    pModule->heap_size = HeapSize;
+    pModule->heap_size = DLLHeapSize;
     pModule->stack_size = 0;
     pModule->ip = 0;
     pModule->cs = 0;
@@ -1482,7 +1481,7 @@
     printf( "\tpushw %%ds\n" );
     printf( "\tpopw %%ss\n" );
     printf( "\tleal -%d(%%ebp),%%esp\n",
-            reg_func ? sizeof(struct sigcontext_struct) : 4 * strlen(args) );
+            reg_func ? sizeof(SIGCONTEXT) : 4 * strlen(args) );
 
     /* Setup %ebp to point to the previous stack frame (built by CallTo16) */
 
diff --git a/win32/memory.c b/win32/memory.c
index c50a45c..4b78f3d 100644
--- a/win32/memory.c
+++ b/win32/memory.c
@@ -247,7 +247,7 @@
 /***********************************************************************
  *           VirtualFree               (KERNEL32.550)
  */
-BOOL VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD fdwFreeType)
+BOOL32 VirtualFree(LPVOID lpvAddress, DWORD cbSize, DWORD fdwFreeType)
 {
     int i;
 
diff --git a/win32/time.c b/win32/time.c
index 5d649a0..4756a31 100644
--- a/win32/time.c
+++ b/win32/time.c
@@ -119,20 +119,13 @@
 /***********************************************************************
  *              SetTimeZoneInformation  (KERNEL32.515)
  */
-BOOL SetTimeZoneInformation(const TIME_ZONE_INFORMATION *tzinfo)
+BOOL32 SetTimeZoneInformation(const TIME_ZONE_INFORMATION *tzinfo)
 {
     struct timezone tz;
 
     tz.tz_minuteswest = tzinfo->Bias;
     tz.tz_dsttime = DST_NONE;
-    if (settimeofday(NULL, &tz))
-    {
-        return FALSE;
-    }
-    else
-    {
-        return TRUE;
-    }
+    return !settimeofday(NULL, &tz);
 }
 
 
diff --git a/win32/user32.c b/win32/user32.c
index 39ef0d7..47035de 100644
--- a/win32/user32.c
+++ b/win32/user32.c
@@ -19,7 +19,6 @@
 #include "resource32.h"
 #include "string32.h"
 #include "win.h"
-#include "winproc.h"
 #include "debug.h"
 #include "stddebug.h"
 
diff --git a/windows/class.c b/windows/class.c
index a2a37a2..ae75f00 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -47,7 +47,7 @@
              "inst=%04x  hdce=%04x  icon=%04x  cursor=%04x  bkgnd=%04x\n"
              "clsExtra=%d  winExtra=%d  #windows=%d\n",
              ptr->next, ptr->atomName, className, ptr->style,
-             ptr->winproc, ptr->hInstance, ptr->hdce,
+             (UINT32)ptr->winproc, ptr->hInstance, ptr->hdce,
              ptr->hIcon, ptr->hCursor, ptr->hbrBackground,
              ptr->cbClsExtra, ptr->cbWndExtra, ptr->cWindows );
     if (ptr->cbClsExtra)
@@ -76,7 +76,7 @@
     {
         GlobalGetAtomName32A( ptr->atomName, className, sizeof(className) );
         fprintf( stderr, "%08x %-20.20s %08x %08x\n", (UINT32)ptr, className,
-                 ptr->style, ptr->winproc );
+                 ptr->style, (UINT32)ptr->winproc );
     }
     fprintf( stderr, "\n" );
 }
@@ -156,21 +156,6 @@
 
 
 /***********************************************************************
- *           CLASS_SetWndProc
- *
- * Set the window procedure and return the old one.
- */
-static HANDLE32 CLASS_SetWndProc( CLASS *classPtr, HANDLE32 proc,
-                                  WINDOWPROCTYPE type )
-{
-    HANDLE32 oldProc = classPtr->winproc;
-    classPtr->winproc = WINPROC_AllocWinProc( proc, type );
-    if (oldProc) WINPROC_FreeWinProc( oldProc );
-    return oldProc;
-}
-
-
-/***********************************************************************
  *           CLASS_FreeClass
  *
  * Free a class structure.
@@ -200,7 +185,7 @@
     if (classPtr->hbrBackground) DeleteObject( classPtr->hbrBackground );
     GlobalDeleteAtom( classPtr->atomName );
     CLASS_SetMenuNameA( classPtr, NULL );
-    CLASS_SetWndProc( classPtr, (HANDLE32)0, WIN_PROC_16 );
+    WINPROC_FreeProc( classPtr->winproc );
     HeapFree( SystemHeap, 0, classPtr );
     return TRUE;
 }
@@ -209,7 +194,7 @@
 /***********************************************************************
  *           CLASS_FreeModuleClasses
  */
-void CLASS_FreeModuleClasses( HMODULE hModule )
+void CLASS_FreeModuleClasses( HMODULE16 hModule )
 {
     CLASS *ptr, *next;
   
@@ -273,7 +258,7 @@
  */
 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE32 hInstance,
                                    DWORD style, INT32 classExtra,
-                                   INT32 winExtra, HANDLE32 wndProc,
+                                   INT32 winExtra, WNDPROC16 wndProc,
                                    WINDOWPROCTYPE wndProcType )
 {
     CLASS *classPtr;
@@ -308,7 +293,7 @@
     classPtr->magic       = CLASS_MAGIC;
     classPtr->cWindows    = 0;  
     classPtr->style       = style;
-    classPtr->winproc     = 0;
+    classPtr->winproc     = (HWINDOWPROC)0;
     classPtr->cbWndExtra  = winExtra;
     classPtr->cbClsExtra  = classExtra;
     classPtr->hInstance   = hInstance;
@@ -316,7 +301,8 @@
     classPtr->menuNameA   = 0;
     classPtr->menuNameW   = 0;
     classPtr->hdce        = (style&CS_CLASSDC) ? DCE_AllocDCE(0, DCE_CLASS_DC): 0;
-    CLASS_SetWndProc( classPtr, wndProc, wndProcType );
+    WINPROC_SetProc( &classPtr->winproc, wndProc, wndProcType );
+
     /* Other values must be set by caller */
 
     if (classExtra) memset( classPtr->wExtra, 0, classExtra );
@@ -338,8 +324,7 @@
     if (!(atom = GlobalAddAtom16( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
                                           wc->cbClsExtra, wc->cbWndExtra,
-                                          (HANDLE32)wc->lpfnWndProc,
-                                          WIN_PROC_16 )))
+                                          wc->lpfnWndProc, WIN_PROC_16 )))
     {
         GlobalDeleteAtom( atom );
         return 0;
@@ -375,7 +360,7 @@
     if (!(atom = GlobalAddAtom32A( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
                                           wc->cbClsExtra, wc->cbWndExtra,
-                                          (HANDLE32)wc->lpfnWndProc,
+                                          (WNDPROC16)wc->lpfnWndProc,
                                           WIN_PROC_32A )))
     {
         GlobalDeleteAtom( atom );
@@ -410,7 +395,7 @@
     if (!(atom = GlobalAddAtom32W( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
                                           wc->cbClsExtra, wc->cbWndExtra,
-                                          (HANDLE32)wc->lpfnWndProc,
+                                          (WNDPROC16)wc->lpfnWndProc,
                                           WIN_PROC_32W )))
     {
         GlobalDeleteAtom( atom );
@@ -444,8 +429,7 @@
     if (!(atom = GlobalAddAtom16( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
                                           wc->cbClsExtra, wc->cbWndExtra,
-                                          (HANDLE32)wc->lpfnWndProc,
-                                          WIN_PROC_16 )))
+                                          wc->lpfnWndProc, WIN_PROC_16 )))
     {
         GlobalDeleteAtom( atom );
         return 0;
@@ -481,7 +465,7 @@
     if (!(atom = GlobalAddAtom32A( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
                                           wc->cbClsExtra, wc->cbWndExtra,
-                                          (HANDLE32)wc->lpfnWndProc,
+                                          (WNDPROC16)wc->lpfnWndProc,
                                           WIN_PROC_32A )))
     {
         GlobalDeleteAtom( atom );
@@ -516,7 +500,7 @@
     if (!(atom = GlobalAddAtom32W( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
                                           wc->cbClsExtra, wc->cbWndExtra,
-                                          (HANDLE32)wc->lpfnWndProc,
+                                          (WNDPROC16)wc->lpfnWndProc,
                                           WIN_PROC_32W )))
     {
         GlobalDeleteAtom( atom );
@@ -621,20 +605,20 @@
  */
 LONG GetClassLong16( HWND16 hwnd, INT16 offset )
 {
+    WND *wndPtr;
     LONG ret;
 
     switch( offset )
     {
+    case GCL_WNDPROC:
+        if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+        return (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_16 );
     case GCL_MENUNAME:
         ret = GetClassLong32A( hwnd, offset );
         return (LONG)SEGPTR_GET( (void *)ret );
-    case GCL_WNDPROC:
-        ret = GetClassLong32A( hwnd, offset );
-        return (LONG)WINPROC_GetFunc16( (HANDLE32)ret );
     default:
         return GetClassLong32A( hwnd, offset );
     }
-    return (LONG)ret;
 }
 
 
@@ -658,7 +642,7 @@
         case GCL_CBCLSEXTRA: return (LONG)wndPtr->class->cbClsExtra;
         case GCL_HMODULE:    return (LONG)wndPtr->class->hInstance;
         case GCL_WNDPROC:
-            return (LONG)WINPROC_GetFunc32( wndPtr->class->winproc );
+            return (LONG)WINPROC_GetProc(wndPtr->class->winproc, WIN_PROC_32A);
         case GCL_MENUNAME:
             return (LONG)CLASS_GetMenuNameA( wndPtr->class );
         case GCL_HBRBACKGROUND:
@@ -678,10 +662,18 @@
 LONG GetClassLong32W( HWND32 hwnd, INT32 offset )
 {
     WND * wndPtr;
-    
-    if (offset != GCL_MENUNAME) return GetClassLong32A( hwnd, offset );
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-    return (LONG)CLASS_GetMenuNameW( wndPtr->class );
+
+    switch(offset)
+    {
+    case GCL_WNDPROC:
+        if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+        return (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_32W );
+    case GCL_MENUNAME:
+        if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+        return (LONG)CLASS_GetMenuNameW( wndPtr->class );
+    default:
+        return GetClassLong32A( hwnd, offset );
+    }
 }
 
 
@@ -697,8 +689,9 @@
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
     if (offset >= 0)
     {
-        if (offset <= wndPtr->class->cbClsExtra - sizeof(WORD))
+        if (offset + sizeof(WORD) <= wndPtr->class->cbClsExtra)
             ptr = ((char *)wndPtr->class->wExtra) + offset;
+        else
         {
             fprintf( stderr, "Warning: invalid offset %d for SetClassWord()\n",
                      offset );
@@ -734,13 +727,16 @@
 LONG SetClassLong16( HWND16 hwnd, INT16 offset, LONG newval )
 {
     WND *wndPtr;
+    LONG retval;
 
     switch(offset)
     {
     case GCL_WNDPROC:
         if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
-        return (LONG)CLASS_SetWndProc( wndPtr->class, (HANDLE32)newval,
-                                       WIN_PROC_16 );
+        retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_16 );
+        WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
+                         WIN_PROC_16 );
+        return retval;
     case GCL_MENUNAME:
         return SetClassLong32A( hwnd, offset, (LONG)PTR_SEG_TO_LIN(newval) );
     default:
@@ -761,7 +757,7 @@
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
     if (offset >= 0)
     {
-        if (offset <= wndPtr->class->cbClsExtra - sizeof(LONG))
+        if (offset + sizeof(LONG) <= wndPtr->class->cbClsExtra)
             ptr = ((char *)wndPtr->class->wExtra) + offset;
         else
         {
@@ -776,8 +772,11 @@
             CLASS_SetMenuNameA( wndPtr->class, (LPCSTR)newval );
             return 0;  /* Old value is now meaningless anyway */
         case GCL_WNDPROC:
-            return (LONG)CLASS_SetWndProc( wndPtr->class, (HANDLE32)newval,
-                                           WIN_PROC_32A );
+            retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc,
+                                            WIN_PROC_32A );
+            WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
+                             WIN_PROC_32A );
+            return retval;
         case GCL_HBRBACKGROUND:
         case GCL_HCURSOR:
         case GCL_HICON:
@@ -804,14 +803,18 @@
 LONG SetClassLong32W( HWND32 hwnd, INT32 offset, LONG newval )
 {
     WND *wndPtr;
-    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+    LONG retval;
 
     switch(offset)
     {
     case GCL_WNDPROC:
-        return (LONG)CLASS_SetWndProc( wndPtr->class, (HANDLE32)newval,
-                                       WIN_PROC_32W );
+        if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+        retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_32W );
+        WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
+                         WIN_PROC_32W );
+        return retval;
     case GCL_MENUNAME:
+        if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
         CLASS_SetMenuNameW( wndPtr->class, (LPCWSTR)newval );
         return 0;  /* Old value is now meaningless anyway */
     default:
@@ -866,7 +869,7 @@
         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
         (hInstance != classPtr->hInstance)) return FALSE;
     wc->style         = (UINT16)classPtr->style;
-    wc->lpfnWndProc   = WINPROC_GetFunc16( classPtr->winproc );
+    wc->lpfnWndProc   = WINPROC_GetProc( classPtr->winproc, WIN_PROC_16 );
     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
     wc->hInstance     = (HINSTANCE16)classPtr->hInstance;
@@ -894,7 +897,8 @@
         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
         (hInstance != classPtr->hInstance)) return FALSE;
     wc->style         = classPtr->style;
-    wc->lpfnWndProc   = WINPROC_GetFunc32( classPtr->winproc );
+    wc->lpfnWndProc   = (WNDPROC32)WINPROC_GetProc( classPtr->winproc,
+                                                    WIN_PROC_32A );
     wc->cbClsExtra    = classPtr->cbClsExtra;
     wc->cbWndExtra    = classPtr->cbWndExtra;
     wc->hInstance     = classPtr->hInstance;
@@ -920,7 +924,8 @@
         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
         (hInstance != classPtr->hInstance)) return FALSE;
     wc->style         = classPtr->style;
-    wc->lpfnWndProc   = WINPROC_GetFunc32( classPtr->winproc );
+    wc->lpfnWndProc   = (WNDPROC32)WINPROC_GetProc( classPtr->winproc,
+                                                    WIN_PROC_32W );
     wc->cbClsExtra    = classPtr->cbClsExtra;
     wc->cbWndExtra    = classPtr->cbWndExtra;
     wc->hInstance     = classPtr->hInstance;
@@ -949,7 +954,7 @@
         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
         (hInstance != classPtr->hInstance)) return FALSE;
     wc->style         = classPtr->style;
-    wc->lpfnWndProc   = WINPROC_GetFunc16( classPtr->winproc );
+    wc->lpfnWndProc   = WINPROC_GetProc( classPtr->winproc, WIN_PROC_16 );
     wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
     wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
     wc->hInstance     = (HINSTANCE16)classPtr->hInstance;
@@ -979,7 +984,8 @@
         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
         (hInstance != classPtr->hInstance)) return FALSE;
     wc->style         = classPtr->style;
-    wc->lpfnWndProc   = WINPROC_GetFunc32( classPtr->winproc );
+    wc->lpfnWndProc   = (WNDPROC32)WINPROC_GetProc( classPtr->winproc,
+                                                    WIN_PROC_32A );
     wc->cbClsExtra    = classPtr->cbClsExtra;
     wc->cbWndExtra    = classPtr->cbWndExtra;
     wc->hInstance     = classPtr->hInstance;
@@ -1007,7 +1013,8 @@
         !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
         (hInstance != classPtr->hInstance)) return FALSE;
     wc->style         = classPtr->style;
-    wc->lpfnWndProc   = WINPROC_GetFunc32( classPtr->winproc );
+    wc->lpfnWndProc   = (WNDPROC32)WINPROC_GetProc( classPtr->winproc,
+                                                    WIN_PROC_32W );
     wc->cbClsExtra    = classPtr->cbClsExtra;
     wc->cbWndExtra    = classPtr->cbWndExtra;
     wc->hInstance     = classPtr->hInstance;
@@ -1024,7 +1031,7 @@
 /***********************************************************************
  *           ClassFirst      (TOOLHELP.69)
  */
-BOOL ClassFirst( CLASSENTRY *pClassEntry )
+BOOL16 ClassFirst( CLASSENTRY *pClassEntry )
 {
     pClassEntry->wNext = 1;
     return ClassNext( pClassEntry );
@@ -1034,7 +1041,7 @@
 /***********************************************************************
  *           ClassNext      (TOOLHELP.70)
  */
-BOOL ClassNext( CLASSENTRY *pClassEntry )
+BOOL16 ClassNext( CLASSENTRY *pClassEntry )
 {
     int i;
     CLASS *class = firstClass;
diff --git a/windows/defdlg.c b/windows/defdlg.c
index 9379e07..0ddbea8 100644
--- a/windows/defdlg.c
+++ b/windows/defdlg.c
@@ -151,11 +151,8 @@
 	    }
 
             /* Delete window procedure */
-            if (dlgInfo->dlgProc)
-            {
-                WINPROC_FreeWinProc( dlgInfo->dlgProc );
-                dlgInfo->dlgProc = 0;
-            }
+            WINPROC_FreeProc( dlgInfo->dlgProc );
+            dlgInfo->dlgProc = (HWINDOWPROC)0;
 
 	      /* Window clean-up */
 	    return DefWindowProc32A( hwnd, msg, wParam, lParam );
@@ -224,8 +221,8 @@
     if (dlgInfo->dlgProc)
     {
 	  /* Call dialog procedure */
-	result = (BOOL16)CallWindowProc16( (WNDPROC16)dlgInfo->dlgProc, hwnd, 
-                                           msg, wParam, lParam );
+	result = (BOOL16)CallWindowProc16( (WNDPROC16)dlgInfo->dlgProc,
+                                           hwnd, msg, wParam, lParam );
 
         /* Check if window was destroyed by dialog procedure */
         if (result || !IsWindow( hwnd )) return result;
@@ -268,8 +265,8 @@
     if (dlgInfo->dlgProc)
     {
 	  /* Call dialog procedure */
-	result = (BOOL16)CallWindowProc32A( (WNDPROC32)dlgInfo->dlgProc, hwnd, 
-                                            msg, wParam, lParam );
+	result = (BOOL16)CallWindowProc32A( (WNDPROC32)dlgInfo->dlgProc,
+                                            hwnd, msg, wParam, lParam );
 
         /* Check if window was destroyed by dialog procedure */
         if (result || !IsWindow( hwnd )) return result;
@@ -311,8 +308,8 @@
     if (dlgInfo->dlgProc)
     {
 	  /* Call dialog procedure */
-	result = (BOOL16)CallWindowProc32W( (WNDPROC32)dlgInfo->dlgProc, hwnd, 
-                                            msg, wParam, lParam );
+	result = (BOOL16)CallWindowProc32W( (WNDPROC32)dlgInfo->dlgProc,
+                                            hwnd, msg, wParam, lParam );
 
         /* Check if window was destroyed by dialog procedure */
         if (result || !IsWindow( hwnd )) return result;
diff --git a/windows/dialog.c b/windows/dialog.c
index b7aa611..ce5a675 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -71,7 +71,7 @@
       /* Calculate the dialog base units */
 
     if (!(hdc = CreateDC( "DISPLAY", NULL, NULL, NULL ))) return FALSE;
-    GetTextMetrics( hdc, &tm );
+    GetTextMetrics16( hdc, &tm );
     DeleteDC( hdc );
     xBaseUnit = tm.tmAveCharWidth;
     yBaseUnit = tm.tmHeight;
@@ -477,8 +477,8 @@
  *           DIALOG_CreateIndirect
  */
 static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCSTR dlgTemplate,
-                                   HWND owner, HANDLE32 dlgProc,
-                                   LPARAM param, BOOL win32 )
+                                   HWND owner, DLGPROC16 dlgProc,
+                                   LPARAM param, WINDOWPROCTYPE procType )
 {
     HMENU hMenu = 0;
     HFONT hFont = 0;
@@ -493,8 +493,10 @@
       /* Parse dialog template */
 
     if (!dlgTemplate) return 0;
-    if (win32) dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
-    else dlgTemplate = DIALOG_ParseTemplate16( dlgTemplate, &template );
+    if (procType != WIN_PROC_16)
+        dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
+    else
+        dlgTemplate = DIALOG_ParseTemplate16( dlgTemplate, &template );
 
       /* Load menu */
 
@@ -523,7 +525,7 @@
 
 	    hdc = GetDC(0);
 	    oldFont = SelectObject( hdc, hFont );
-	    GetTextMetrics( hdc, &tm );
+	    GetTextMetrics16( hdc, &tm );
 	    SelectObject( hdc, oldFont );
 	    ReleaseDC( 0, hdc );
 	    xUnit = tm.tmAveCharWidth;
@@ -555,7 +557,7 @@
             ClientToScreen16( owner, (POINT16 *)&rect );
     }
 
-    if (win32)
+    if (procType != WIN_PROC_16)
         hwnd = CreateWindowEx32W(template.exStyle, (LPCWSTR)template.className,
                                  (LPCWSTR)template.caption,
                                  template.style & ~WS_VISIBLE,
@@ -573,6 +575,7 @@
 	return 0;
     }
     wndPtr = WIN_FindWndPtr( hwnd );
+    wndPtr->flags |= WIN_ISDIALOG;
 
       /* Initialise dialog extra data */
 
@@ -587,7 +590,7 @@
     /* Create controls */
 
     if (!DIALOG_CreateControls( wndPtr, dlgTemplate, template.nbItems,
-                                hInst, win32 ))
+                                hInst, (procType != WIN_PROC_16) ))
     {
         DestroyWindow( hwnd );
         return 0;
@@ -595,7 +598,7 @@
 
     /* Send initialisation messages and set focus */
 
-    dlgInfo->dlgProc   = dlgProc;
+    WINPROC_SetProc( &dlgInfo->dlgProc, dlgProc, procType );
     dlgInfo->hwndFocus = DIALOG_GetFirstTabItem( hwnd );
     if (dlgInfo->hUserFont)
 	SendMessage32A( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
@@ -687,9 +690,8 @@
                                     HWND16 owner, DLGPROC16 dlgProc,
                                     LPARAM param )
 {
-    HANDLE32 proc = WINPROC_AllocWinProc( (UINT32)dlgProc, WIN_PROC_16 );
-    return DIALOG_CreateIndirect( hInst, dlgTemplate,
-                                  owner, proc, param, FALSE );
+    return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
+                                  dlgProc, param, WIN_PROC_16 );
 }
 
 
@@ -700,9 +702,8 @@
                                      HWND32 owner, DLGPROC32 dlgProc,
                                      LPARAM param )
 {
-    HANDLE32 proc = WINPROC_AllocWinProc( (UINT32)dlgProc, WIN_PROC_32A );
-    return DIALOG_CreateIndirect( hInst, dlgTemplate,
-                                  owner, proc, param, TRUE );
+    return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
+                                  (DLGPROC16)dlgProc, param, WIN_PROC_32A );
 }
 
 
@@ -713,9 +714,8 @@
                                      HWND32 owner, DLGPROC32 dlgProc,
                                      LPARAM param )
 {
-    HANDLE32 proc = WINPROC_AllocWinProc( (UINT32)dlgProc, WIN_PROC_32W );
-    return DIALOG_CreateIndirect( hInst, dlgTemplate,
-                                  owner, proc, param, TRUE );
+    return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
+                                  (DLGPROC16)dlgProc, param, WIN_PROC_32W );
 }
 
 
diff --git a/windows/event.c b/windows/event.c
index 4f421a4..4a87d91 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -462,9 +462,38 @@
     else if (key_type == 0)                        /* character key */
     {
 	if ( isalnum(key) )
-	     vkey = toupper(key);                  /* convert lower to uppercase */
+	     vkey = toupper(key);                  /* convert lc to uc */
+	else if ( isspace(key) )
+	  vkey = key;				   /* XXX approximately */
         else  
-	     vkey = 0xbe;
+	  switch (key)				   /* the rest... */
+	  {
+#define vkcase(k,val) case k: vkey = val; break;
+#define vkcase2(k1,k2,val) case k1: case k2: vkey = val; break;
+
+	      /* I wish I had a bit-paired keyboard! */
+	      vkcase('!','1'); vkcase('@','2'); vkcase('#','3');
+	      vkcase('$','4'); vkcase('%','5'); vkcase('^','6');
+	      vkcase('&','7'); vkcase('*','8'); vkcase('(','9');
+	      vkcase(')','0');
+
+	      vkcase2('`','~',0xc0);
+	      vkcase2('-','_',0xbd);
+	      vkcase2('=','+',0xbb);
+	      vkcase2('[','{',0xdb);
+	      vkcase2(']','}',0xdd);
+	      vkcase2(';',':',0xba);
+	      vkcase2('\'','\"',0xde);
+	      vkcase2(',','<',0xbc);
+	      vkcase2('.','>',0xbe);
+	      vkcase2('/','?',0xbf);
+	      vkcase2('\\','|',0xdc);
+#undef vkcase
+#undef vkcase2
+	    default:
+	      fprintf( stderr, "Unknown key! Please report!\n" );
+	      vkey = 0;				   /* whatever */
+	  }
     }
 
     if (event->type == KeyPress)
@@ -845,7 +874,7 @@
  */
 FARPROC GetMouseEventProc(void)
 {
-    HMODULE hmodule = GetModuleHandle("USER");
+    HMODULE16 hmodule = GetModuleHandle("USER");
     return MODULE_GetEntryPoint( hmodule,
                                  MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
 }
@@ -855,7 +884,7 @@
  *           Mouse_Event   (USER.299)
  */
 #ifndef WINELIB
-void Mouse_Event( struct sigcontext_struct context )
+void Mouse_Event( SIGCONTEXT context )
 {
     /* Register values:
      * AX = mouse event
diff --git a/windows/hook.c b/windows/hook.c
index 74c2259..9ea7c9e 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -21,7 +21,7 @@
 #include "debug.h"
 
   /* This should probably reside in USER heap */
-static HANDLE HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
+static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
 
 
 /***********************************************************************
@@ -124,7 +124,7 @@
 static BOOL HOOK_RemoveHook( HANDLE hook )
 {
     HOOKDATA *data;
-    HANDLE *prevHook;
+    HANDLE16 *prevHook;
 
     dprintf_hook( stddeb, "Removing hook %04x\n", hook );
 
@@ -215,7 +215,7 @@
 /***********************************************************************
  *	     HOOK_FreeModuleHooks
  */
-void HOOK_FreeModuleHooks( HMODULE hModule )
+void HOOK_FreeModuleHooks( HMODULE16 hModule )
 {
  /* remove all system hooks registered by this module */
 
@@ -244,7 +244,7 @@
 /***********************************************************************
  *	     HOOK_FreeQueueHooks
  */
-void HOOK_FreeQueueHooks( HQUEUE hQueue )
+void HOOK_FreeQueueHooks( HQUEUE16 hQueue )
 {
   /* remove all hooks registered by this queue */
 
diff --git a/windows/message.c b/windows/message.c
index c777683..4713f6e 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -19,6 +19,7 @@
 #include "atom.h"
 #include "dde.h"
 #include "queue.h"
+#include "winproc.h"
 #include "stddebug.h"
 /* #define DEBUG_MSG */
 #include "debug.h"
@@ -290,7 +291,7 @@
  *
  * Implementation of an inter-task SendMessage.
  */
-LRESULT MSG_SendMessage( HQUEUE hDestQueue, HWND hwnd, UINT msg,
+static LRESULT MSG_SendMessage( HQUEUE hDestQueue, HWND hwnd, UINT msg,
                          WPARAM wParam, LPARAM lParam )
 {
     MESSAGEQUEUE *queue, *destQ;
@@ -323,10 +324,10 @@
 
     if (!(queue->wakeBits & QS_SMRESULT))
     {
-        DirectedYield( hDestQueue );
+        DirectedYield( destQ->hTask );
         QUEUE_WaitBits( QS_SMRESULT );
     }
-    printf( "SendMessage %04x to %04x: got %08x\n",
+    printf( "SendMessage %04x to %04x: got %08lx\n",
             msg, hDestQueue, queue->SendMessageReturn );
     queue->wakeBits &= ~QS_SMRESULT;
     return queue->SendMessageReturn;
@@ -351,7 +352,7 @@
         else if (senderQ->wakeBits & QS_SMRESULT) Yield();
         else break;
     }
-    printf( "ReplyMessage: res = %08x\n", result );
+    printf( "ReplyMessage: res = %08lx\n", result );
     senderQ->SendMessageReturn = result;
     queue->InSendMessageHandle = 0;
     QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
@@ -845,7 +846,8 @@
 
     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, msg->hwnd, msg->message,
                       msg->wParam, msg->lParam );
-    retval = CallWindowProc16( wndPtr->winproc, msg->hwnd, msg->message,
+    retval = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
+                               msg->hwnd, msg->message,
                                msg->wParam, msg->lParam );
     SPY_ExitMessage( SPY_RESULT_OK16, msg->hwnd, msg->message, retval );
 
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 67b052d..4d4751d 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -640,7 +640,7 @@
 	else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
 	SetBkMode( hdc, TRANSPARENT );
 	DrawText16( hdc, buffer, -1, &r,
-                    DT_SINGLELINE | DT_CENTER | DT_VCENTER );
+                    DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
     }
 }
 
diff --git a/windows/win.c b/windows/win.c
index c6e5188..7fc2b25 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -98,7 +98,7 @@
              ptr->next, ptr->child, ptr->parent, ptr->owner,
              ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
              ptr->hrgnUpdate, ptr->hwndLastActive, ptr->hdce, ptr->wIDmenu,
-             ptr->dwStyle, ptr->dwExStyle, ptr->winproc,
+             ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
              ptr->text ? ptr->text : "",
              ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
              ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
@@ -130,7 +130,7 @@
     ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
     if (!ptr)
     {
-        fprintf( stderr, "*** Invalid window handle\n" );
+        fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
         return;
     }
 
@@ -146,7 +146,7 @@
         
         fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
                  (DWORD)ptr, ptr->hmemTaskQ, className,
-                 (unsigned) ptr->dwStyle, ptr->winproc );
+                 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
         
         if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
         ptr = ptr->next;
@@ -303,20 +303,6 @@
 
 
 /***********************************************************************
- *           WIN_SetWndProc
- *
- * Set the window procedure and return the old one.
- */
-static HANDLE32 WIN_SetWndProc( WND *pWnd, HANDLE32 proc, WINDOWPROCTYPE type)
-{
-    HANDLE32 oldProc = pWnd->winproc;
-    pWnd->winproc = WINPROC_AllocWinProc( proc, type );
-    if (oldProc) WINPROC_FreeWinProc( oldProc );
-    return oldProc;
-}
-
-
-/***********************************************************************
  *           WIN_DestroyWindow
  *
  * Destroy storage associated to a window
@@ -347,7 +333,7 @@
     if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
     if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
     if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
-    WIN_SetWndProc( wndPtr, (HANDLE32)0, WIN_PROC_16 );
+    WINPROC_FreeProc( wndPtr->winproc );
     wndPtr->class->cWindows--;
     USER_HEAP_FREE( hwnd );
 }
@@ -395,7 +381,7 @@
     pWndDesktop->parent            = NULL;
     pWndDesktop->owner             = NULL;
     pWndDesktop->class             = class;
-    pWndDesktop->winproc           = WINPROC_CopyWinProc( class->winproc );
+    pWndDesktop->winproc           = NULL;
     pWndDesktop->dwMagic           = WND_MAGIC;
     pWndDesktop->hwndSelf          = hwndDesktop;
     pWndDesktop->hInstance         = 0;
@@ -426,6 +412,7 @@
     pWndDesktop->hProp             = 0;
     pWndDesktop->userdata          = 0;
 
+    WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
     EVENT_RegisterWindow( pWndDesktop );
     SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
     if ((hdc = GetDC( hwndDesktop )) != 0)
@@ -522,7 +509,7 @@
                               WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
     wndPtr->window         = 0;
     wndPtr->class          = classPtr;
-    wndPtr->winproc        = WINPROC_CopyWinProc( classPtr->winproc );
+    wndPtr->winproc        = NULL;
     wndPtr->dwMagic        = WND_MAGIC;
     wndPtr->hwndSelf       = hwnd;
     wndPtr->hInstance      = cs->hInstance;
@@ -547,6 +534,10 @@
     if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
     classPtr->cWindows++;
 
+    /* Set the window procedure */
+
+    WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
+
     /* Correct the window style */
 
     if (!(cs->style & (WS_POPUP | WS_CHILD)))  /* Overlapped window */
@@ -706,14 +697,14 @@
         WINPOS_FindIconPos( hwnd );
         SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
                       SYSMETRICS_CXICON, SYSMETRICS_CYICON, SWP_FRAMECHANGED |
-                      (cs->style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
+                      ((cs->style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 ));
     }
     else if (wndPtr->dwStyle & WS_MAXIMIZE)
     {
         POINT16 maxSize, maxPos, minTrack, maxTrack;
         NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
         SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
-            SWP_FRAMECHANGED | (cs->style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0 );
+            SWP_FRAMECHANGED | ((cs->style & WS_VISIBLE) ? SWP_SHOWWINDOW : 0) );
     }
     else if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
 
@@ -928,7 +919,7 @@
 BOOL CloseWindow(HWND hWnd)
 {
     WND * wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr->dwStyle & WS_CHILD) return TRUE;
+    if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return TRUE;
     ShowWindow(hWnd, SW_MINIMIZE);
     return TRUE;
 }
@@ -1057,9 +1048,9 @@
     HWND hwnd;
 
     atom = className ? GlobalFindAtom32W( className ) : 0;
-    buffer = STRING32_DupUniToAnsi( title );
+    buffer = title ? STRING32_DupUniToAnsi( title ) : NULL;
     hwnd = WIN_FindWindow( 0, 0, atom, buffer );
-    free( buffer );
+    if (buffer) free( buffer );
     return hwnd;
 }
 
@@ -1153,7 +1144,7 @@
     WND * wndPtr; 
 
     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
-    return (WINPROC_GetWinProcType( wndPtr->winproc ) == WIN_PROC_32W);
+    return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
 }
 
 
@@ -1164,7 +1155,15 @@
 {
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
-    if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
+    if (offset >= 0)
+    {
+        if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
+        {
+            fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
+            return 0;
+        }
+        return *(WORD *)(((char *)wndPtr->wExtra) + offset);
+    }
     switch(offset)
     {
     case GWW_ID:         return wndPtr->wIDmenu;
@@ -1196,7 +1195,15 @@
     WORD *ptr, retval;
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
-    if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
+    if (offset >= 0)
+    {
+        if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
+        {
+            fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
+            return 0;
+        }
+        ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
+    }
     else switch(offset)
     {
 	case GWW_ID:        ptr = (WORD *)&wndPtr->wIDmenu; break;
@@ -1212,85 +1219,82 @@
 
 
 /**********************************************************************
- *	     GetWindowLong16    (USER.135)
+ *	     WIN_GetWindowLong
+ *
+ * Helper function for GetWindowLong().
  */
-LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
+static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
 {
-    LONG ret = GetWindowLong32A( (HWND32)hwnd, offset );
-    if (offset == GWL_WNDPROC) return (LONG)WINPROC_GetFunc16( (HANDLE32)ret );
-    return ret;
-}
-
-
-/**********************************************************************
- *	     GetWindowLong32A    (USER32.304)
- */
-LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
-{
+    LONG retval;
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
-    if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
+    if (offset >= 0)
+    {
+        if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
+        {
+            fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
+            return 0;
+        }
+        retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
+        /* Special case for dialog window procedure */
+        if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
+            return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
+        return retval;
+    }
     switch(offset)
     {
         case GWL_USERDATA:   return wndPtr->userdata;
         case GWL_STYLE:      return wndPtr->dwStyle;
         case GWL_EXSTYLE:    return wndPtr->dwExStyle;
         case GWL_ID:         return wndPtr->wIDmenu;
-        case GWL_WNDPROC:    return (LONG)WINPROC_GetFunc32( wndPtr->winproc );
+        case GWL_WNDPROC:    return (LONG)WINPROC_GetProc( wndPtr->winproc,
+                                                           type );
         case GWL_HWNDPARENT: return wndPtr->parent ?
                                         (HWND32)wndPtr->parent->hwndSelf : 0;
         case GWL_HINSTANCE:  return (HINSTANCE32)wndPtr->hInstance;
         default:
-            fprintf( stderr, "GetWindowLong32A: unknown offset %d\n", offset );
+            fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
     }
     return 0;
 }
 
 
 /**********************************************************************
- *	     GetWindowLong32W    (USER32.305)
+ *	     WIN_SetWindowLong
+ *
+ * Helper function for SetWindowLong().
  */
-LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
-{
-    return GetWindowLong32A( hwnd, offset );
-}
-
-
-/**********************************************************************
- *	     SetWindowLong16    (USER.136)
- */
-LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
-{
-    if (offset == GWL_WNDPROC)
-    {
-        HANDLE32 ret;
-        WND *wndPtr = WIN_FindWndPtr( hwnd );
-        if (!wndPtr) return 0;
-        ret = WIN_SetWndProc( wndPtr, (HANDLE32)newval, WIN_PROC_16 );
-        return (LONG)WINPROC_GetFunc16( ret );
-    }
-    return SetWindowLong32A( hwnd, offset, newval );
-}
-
-
-/**********************************************************************
- *	     SetWindowLong32A    (USER32.516)
- */
-LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
+static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
+                               WINDOWPROCTYPE type )
 {
     LONG *ptr, retval;
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
-    if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
+    if (offset >= 0)
+    {
+        if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
+        {
+            fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
+            return 0;
+        }
+        ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
+        /* Special case for dialog window procedure */
+        if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
+        {
+            retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
+            WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
+            return retval;
+        }
+    }
     else switch(offset)
     {
         case GWL_ID:
         case GWL_HINSTANCE:
             return SetWindowWord( hwnd, offset, (WORD)newval );
 	case GWL_WNDPROC:
-            return (LONG)WINPROC_GetFunc32( WIN_SetWndProc( wndPtr,
-                                                            (HANDLE32)newval,
-                                                            WIN_PROC_32A ));
+            retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
+            WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
+            return retval;
         case GWL_USERDATA: ptr = &wndPtr->userdata; break;
 	case GWL_STYLE:    ptr = &wndPtr->dwStyle; break;
         case GWL_EXSTYLE:  ptr = &wndPtr->dwExStyle; break;
@@ -1305,19 +1309,56 @@
 
 
 /**********************************************************************
+ *	     GetWindowLong16    (USER.135)
+ */
+LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
+{
+    return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
+}
+
+
+/**********************************************************************
+ *	     GetWindowLong32A    (USER32.304)
+ */
+LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
+{
+    return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
+}
+
+
+/**********************************************************************
+ *	     GetWindowLong32W    (USER32.305)
+ */
+LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
+{
+    return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
+}
+
+
+/**********************************************************************
+ *	     SetWindowLong16    (USER.136)
+ */
+LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
+{
+    return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
+}
+
+
+/**********************************************************************
+ *	     SetWindowLong32A    (USER32.516)
+ */
+LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
+{
+    return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
+}
+
+
+/**********************************************************************
  *	     SetWindowLong32W    (USER32.517)
  */
 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
 {
-    if (offset == GCL_WNDPROC)
-    {
-        WND *wndPtr = WIN_FindWndPtr( hwnd );
-        if (!wndPtr) return 0;
-        return (LONG)WINPROC_GetFunc32( WIN_SetWndProc( wndPtr,
-                                                        (HANDLE32)newval,
-                                                        WIN_PROC_32W ));
-    }
-    return SetWindowLong32A( hwnd, offset, newval );
+    return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
 }
 
 
@@ -1568,126 +1609,224 @@
 
 
 /*******************************************************************
- *           EnumWindows   (USER.54)
+ *           WIN_BuildWinArray
+ *
+ * Build an array of pointers to all children of a given window.
+ * The array must be freed with HeapFree(SystemHeap).
  */
-BOOL EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
+WND **WIN_BuildWinArray( WND *wndPtr )
 {
-    WND *wndPtr;
-    HWND *list, *pWnd;
-    int count;
+    WND **list, **ppWnd;
+    WND *pWnd;
+    INT32 count;
+
+    /* First count the windows */
+
+    if (!wndPtr) wndPtr = pWndDesktop;
+    for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) count++;
+    count++;  /* For the terminating NULL */
+
+    /* Now build the list of all windows */
+
+    if (!(list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * count )))
+        return NULL;
+    for (pWnd = wndPtr->child, ppWnd = list; pWnd; pWnd = pWnd->next)
+        *ppWnd++ = pWnd;
+    *ppWnd = NULL;
+    return list;
+}
+
+
+/*******************************************************************
+ *           EnumWindows16   (USER.54)
+ */
+BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
+{
+    WND **list, **ppWnd;
 
     /* We have to build a list of all windows first, to avoid */
     /* unpleasant side-effects, for instance if the callback  */
     /* function changes the Z-order of the windows.           */
 
-      /* First count the windows */
+    if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
 
-    count = 0;
-    for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next) count++;
-    if (!count) return TRUE;
+    /* Now call the callback function for every window */
 
-      /* Now build the list of all windows */
-
-    if (!(pWnd = list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
-    for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
-        *pWnd++ = wndPtr->hwndSelf;
-
-      /* Now call the callback function for every window */
-
-    for (pWnd = list; count > 0; count--, pWnd++)
+    for (ppWnd = list; *ppWnd; ppWnd++)
     {
-          /* Make sure that window still exists */
-        if (!IsWindow(*pWnd)) continue;
-        if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
+        /* Make sure that the window still exists */
+        if (!IsWindow((*ppWnd)->hwndSelf)) continue;
+        if (!CallEnumWindowsProc16( lpEnumFunc, (*ppWnd)->hwndSelf, lParam ))
+            break;
     }
-    free( list );
+    HeapFree( SystemHeap, 0, list );
+    return TRUE;
+}
+
+
+/*******************************************************************
+ *           EnumWindows32   (USER32.192)
+ */
+BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
+{
+    WND **list, **ppWnd;
+
+    /* We have to build a list of all windows first, to avoid */
+    /* unpleasant side-effects, for instance if the callback  */
+    /* function changes the Z-order of the windows.           */
+
+    if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
+
+    /* Now call the callback function for every window */
+
+    for (ppWnd = list; *ppWnd; ppWnd++)
+    {
+        /* Make sure that the window still exists */
+        if (!IsWindow((*ppWnd)->hwndSelf)) continue;
+        if (!CallEnumWindowsProc32( lpEnumFunc, (*ppWnd)->hwndSelf, lParam ))
+            break;
+    }
+    HeapFree( SystemHeap, 0, list );
     return TRUE;
 }
 
 
 /**********************************************************************
- *           EnumTaskWindows   (USER.225)
+ *           EnumTaskWindows16   (USER.225)
  */
-BOOL EnumTaskWindows( HTASK hTask, WNDENUMPROC lpEnumFunc, LPARAM lParam )
+BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
 {
-    WND *wndPtr;
-    HWND *list, *pWnd;
+    WND **list, **ppWnd;
     HANDLE hQueue = GetTaskQueue( hTask );
-    int count;
 
     /* This function is the same as EnumWindows(),    */
     /* except for an added check on the window queue. */
 
-      /* First count the windows */
+    if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
 
-    count = 0;
-    for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
-        if (wndPtr->hmemTaskQ == hQueue) count++;
-    if (!count) return TRUE;
+    /* Now call the callback function for every window */
 
-      /* Now build the list of all windows */
-
-    if (!(pWnd = list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
-    for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
-        if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = wndPtr->hwndSelf;
-
-      /* Now call the callback function for every window */
-
-    for (pWnd = list; count > 0; count--, pWnd++)
+    for (ppWnd = list; *ppWnd; ppWnd++)
     {
-          /* Make sure that window still exists */
-        if (!IsWindow(*pWnd)) continue;
-        if (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
+        /* Make sure that the window still exists */
+        if (!IsWindow((*ppWnd)->hwndSelf)) continue;
+        if ((*ppWnd)->hmemTaskQ != hQueue) continue;  /* Check the queue */
+        if (!CallEnumWindowsProc16( func, (*ppWnd)->hwndSelf, lParam ))
+            break;
     }
-    free( list );
+    HeapFree( SystemHeap, 0, list );
     return TRUE;
 }
 
 
-/*******************************************************************
- *    WIN_EnumChildWin
- *
- *   o hwnd is the first child to use, loop until all next windows
- *     are processed
- * 
- *   o call wdnenumprc
- *
- *   o call ourselves with the next child window
- * 
+/**********************************************************************
+ *           EnumThreadWindows   (USER32.189)
  */
-static BOOL WIN_EnumChildWin( WND *wndPtr, FARPROC wndenumprc, LPARAM lParam )
+BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
 {
-    WND *pWndNext, *pWndChild;
-    while (wndPtr)
+    WND **list, **ppWnd;
+    HANDLE hQueue = GetTaskQueue( (DWORD)id );
+
+    if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
+
+    /* Now call the callback function for every window */
+
+    for (ppWnd = list; *ppWnd; ppWnd++)
     {
-        pWndNext = wndPtr->next;    /* storing hwnd is a way to avoid.. */
-        pWndChild = wndPtr->child;  /* ..side effects after wndenumprc  */
-        if (!CallEnumWindowsProc( wndenumprc, wndPtr->hwndSelf, lParam ))
-            return 0;
-        if (pWndChild && IsWindow(pWndChild->hwndSelf))
-            if (!WIN_EnumChildWin(pWndChild, wndenumprc, lParam)) return 0;
-        wndPtr = pWndNext;
-    } 
-    return 1;
+        /* Make sure that the window still exists */
+        if (!IsWindow((*ppWnd)->hwndSelf)) continue;
+        if ((*ppWnd)->hmemTaskQ != hQueue) continue;  /* Check the queue */
+        if (!CallEnumWindowsProc32( func, (*ppWnd)->hwndSelf, lParam ))
+            break;
+    }
+    HeapFree( SystemHeap, 0, list );
+    return TRUE;
 }
 
 
-/*******************************************************************
- *    EnumChildWindows        (USER.55)
+/**********************************************************************
+ *           WIN_EnumChildWindows16
  *
- *   o gets the first child of hwnd
- *
- *   o calls WIN_EnumChildWin to do a recursive decent of child windows
+ * Helper function for EnumChildWindows16().
  */
-BOOL EnumChildWindows(HWND hwnd, WNDENUMPROC wndenumprc, LPARAM lParam)
+static BOOL16 WIN_EnumChildWindows16( WND **ppWnd, WNDENUMPROC16 func,
+                                      LPARAM lParam )
 {
-    WND *wndPtr;
+    WND **childList;
+    BOOL16 ret = FALSE;
 
-    dprintf_enum(stddeb,"EnumChildWindows\n");
+    while (*ppWnd)
+    {
+        /* Make sure that the window still exists */
+        if (!IsWindow((*ppWnd)->hwndSelf)) continue;
+        /* Build children list first */
+        if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
+        if (!CallEnumWindowsProc16( func, (*ppWnd)->hwndSelf, lParam ))
+            return FALSE;
+        ret = WIN_EnumChildWindows16( childList, func, lParam );
+        HeapFree( SystemHeap, 0, childList );
+        if (!ret) return FALSE;
+        ppWnd++;
+    }
+    return TRUE;
+}
 
-    if (hwnd == 0) return 0;
-    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
-    return WIN_EnumChildWin(wndPtr->child, wndenumprc, lParam);
+
+/**********************************************************************
+ *           WIN_EnumChildWindows32
+ *
+ * Helper function for EnumChildWindows32().
+ */
+static BOOL32 WIN_EnumChildWindows32( WND **ppWnd, WNDENUMPROC32 func,
+                                      LPARAM lParam )
+{
+    WND **childList;
+    BOOL32 ret = FALSE;
+
+    while (*ppWnd)
+    {
+        /* Make sure that the window still exists */
+        if (!IsWindow((*ppWnd)->hwndSelf)) continue;
+        /* Build children list first */
+        if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
+        if (!CallEnumWindowsProc32( func, (*ppWnd)->hwndSelf, lParam ))
+            return FALSE;
+        ret = WIN_EnumChildWindows32( childList, func, lParam );
+        HeapFree( SystemHeap, 0, childList );
+        if (!ret) return FALSE;
+        ppWnd++;
+    }
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *           EnumChildWindows16   (USER.55)
+ */
+BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
+{
+    WND **list, *pParent;
+
+    if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
+    if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
+    WIN_EnumChildWindows16( list, func, lParam );
+    HeapFree( SystemHeap, 0, list );
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *           EnumChildWindows32   (USER32.177)
+ */
+BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
+{
+    WND **list, *pParent;
+
+    if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
+    if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
+    WIN_EnumChildWindows32( list, func, lParam );
+    HeapFree( SystemHeap, 0, list );
+    return TRUE;
 }
 
 
diff --git a/windows/winpos.c b/windows/winpos.c
index e2c3ff7..1acf4b5 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -825,21 +825,6 @@
 
 
 /*******************************************************************
- *	   ACTIVATEAPP_callback
- */
-BOOL ACTIVATEAPP_callback(HWND hWnd, LPARAM lParam)
-{
-    ACTIVATESTRUCT  *lpActStruct = (ACTIVATESTRUCT*)lParam;
- 
-    if (GetWindowTask(hWnd) != lpActStruct->hTaskSendTo) return 1;
-
-    SendMessage16( hWnd, WM_ACTIVATEAPP, lpActStruct->wFlag,
-		(LPARAM)((lpActStruct->hWindowTask)?lpActStruct->hWindowTask:0));
-    return 1;
-}
-
-
-/*******************************************************************
  *	   WINPOS_SetActiveWindow
  *
  * back-end to SetActiveWindow
@@ -849,8 +834,6 @@
     WND                   *wndPtr          = WIN_FindWndPtr(hWnd);
     WND                   *wndTemp         = WIN_FindWndPtr(hwndActive);
     CBTACTIVATESTRUCT16   *cbtStruct;
-    FARPROC                enumCallback    = MODULE_GetWndProcEntry16("ActivateAppProc");
-    ACTIVATESTRUCT         actStruct;
     WORD                   wIconized=0;
 
     /* FIXME: When proper support for cooperative multitasking is in place 
@@ -940,24 +923,34 @@
     /* send WM_ACTIVATEAPP if necessary */
     if (hActiveQ != wndPtr->hmemTaskQ)
     {
-	HTASK hT = QUEUE_GetQueueTask( hActiveQ );
+        WND **list, **ppWnd;
 
-	actStruct.wFlag = 0;                  /* deactivate */
-	actStruct.hWindowTask = QUEUE_GetQueueTask(wndPtr->hmemTaskQ);
-	actStruct.hTaskSendTo = hT;
+        if ((list = WIN_BuildWinArray( WIN_GetDesktop() )))
+        {
+            for (ppWnd = list; *ppWnd; ppWnd++)
+            {
+                /* Make sure that the window still exists */
+                if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
+                if ((*ppWnd)->hmemTaskQ != hActiveQ) continue;
+                SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
+                               0, QUEUE_GetQueueTask(wndPtr->hmemTaskQ) );
+            }
+            HeapFree( SystemHeap, 0, list );
+        }
 
-	/* send WM_ACTIVATEAPP to top-level windows
-	 * that belong to the actStruct.hTaskSendTo task
-	 */
-	EnumWindows( enumCallback , (LPARAM)&actStruct );
-
-	actStruct.wFlag = 1;                  /* activate */
-	actStruct.hWindowTask = hT;
-	actStruct.hTaskSendTo = QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
-
-	EnumWindows( enumCallback , (LPARAM)&actStruct );
-
-	if( !IsWindow(hWnd) ) return 0;
+        if ((list = WIN_BuildWinArray( WIN_GetDesktop() )))
+        {
+            for (ppWnd = list; *ppWnd; ppWnd++)
+            {
+                /* Make sure that the window still exists */
+                if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
+                if ((*ppWnd)->hmemTaskQ != wndPtr->hmemTaskQ) continue;
+                SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
+                               1, QUEUE_GetQueueTask( hActiveQ ) );
+            }
+            HeapFree( SystemHeap, 0, list );
+        }
+	if (!IsWindow(hWnd)) return 0;
     }
 
     /* walk up to the first unowned window */
diff --git a/windows/winproc.c b/windows/winproc.c
index f206657..ff10000 100644
--- a/windows/winproc.c
+++ b/windows/winproc.c
@@ -14,21 +14,134 @@
 #include "string32.h"
 #include "struct32.h"
 #include "win.h"
+#include "wine.h"
 #include "winproc.h"
 
-
+/* Window procedure 16-bit thunk; see BuildSpec16Files() in tools/build.c */
 typedef struct
 {
-    UINT32          magic;    /* Magic number */
-    WINDOWPROCTYPE  type;     /* Function type */
-    UINT32          count;    /* Reference count */
-    UINT32          func;     /* 16- or 32-bit function */
+    BYTE       popl_eax;             /* popl  %eax (return address) */
+    BYTE       pushl_func;           /* pushl $proc */
+    WNDPROC32  proc WINE_PACKED;
+    BYTE       pushl_eax;            /* pushl %eax */
+    WORD       pushw_bp WINE_PACKED; /* pushw %bp */
+    BYTE       pushl_thunk;          /* pushl $thunkfrom16 */
+    void     (*thunk32)() WINE_PACKED;
+    BYTE       lcall;                /* lcall cs:relay */
+    void     (*relay)() WINE_PACKED;
+    WORD       cs WINE_PACKED;
+} WINPROC_THUNK_FROM16;
+
+/* Window procedure 32-bit thunk; see BuildSpec32Files() in tools/build.c */
+typedef struct
+{
+    BYTE       popl_eax;             /* popl  %eax (return address) */
+    BYTE       pushl;                /* pushl $proc */
+    WNDPROC16  proc WINE_PACKED;
+    BYTE       pushl_eax;            /* pushl %eax */
+    BYTE       pushl_ebp;            /* pushl %ebp */
+    BYTE       pushl_name;           /* pushl $name */
+    LPCSTR     name WINE_PACKED;
+    BYTE       pushl_thunk;          /* pushl $thunkfrom32 */
+    void     (*thunk32)() WINE_PACKED;
+    BYTE       jmp;                  /* jmp   relay */
+    void     (*relay)() WINE_PACKED;
+} WINPROC_THUNK_FROM32;
+
+typedef union
+{
+    WINPROC_THUNK_FROM16  t_from16;
+    WINPROC_THUNK_FROM32  t_from32;
+} WINPROC_THUNK;
+
+typedef struct tagWINDOWPROC
+{
+    WINPROC_THUNK         thunk;    /* Thunk */
+    struct tagWINDOWPROC *next;     /* Next window proc */
+    UINT32                magic;    /* Magic number */
+    WINDOWPROCTYPE        type;     /* Function type */
 } WINDOWPROC;
 
 #define WINPROC_MAGIC  ('W' | ('P' << 8) | ('R' << 16) | ('C' << 24))
 
+#define WINPROC_THUNKPROC(pproc) \
+    (((pproc)->type == WIN_PROC_16) ? \
+          (WNDPROC16)((pproc)->thunk.t_from32.proc) : \
+          (WNDPROC16)((pproc)->thunk.t_from16.proc))
 
-static HANDLE32 WinProcHeap = 0;
+LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
+                                 WPARAM16 wParam, LPARAM lParam,
+                                 WNDPROC32 func );
+LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
+                                 WPARAM16 wParam, LPARAM lParam,
+                                 WNDPROC32 func );
+static LRESULT WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
+                                        UINT32 msg, WPARAM32 wParam,
+                                        LPARAM lParam );
+static LRESULT WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
+                                        UINT32 msg, WPARAM32 wParam,
+                                        LPARAM lParam );
+
+#ifndef WINELIB
+extern void CallFrom16_long_wwwll(void);
+extern void CallFrom32_5(void);
+#else
+static void CallFrom16_long_wwwll(void) {}
+static void CallFrom32_5(void) {}
+#endif  /* WINELIB */
+
+/* Reference 16->32A thunk */
+static const WINPROC_THUNK_FROM16 WINPROC_ThunkRef16To32A =
+{
+    0x58,                                       /* popl  %eax */
+    0x68, 0x00000000,                           /* pushl $proc32 */
+    0x50,                                       /* pushl %eax */
+    0x5566,                                     /* pushw %bp */
+    0x68, (void (*)())WINPROC_CallProc16To32A,  /* pushl $thunk32 */
+    0x9a, CallFrom16_long_wwwll,                /* lcall cs:relay */
+    WINE_CODE_SELECTOR
+};
+
+/* Reference 16->32W thunk */
+static const WINPROC_THUNK_FROM16 WINPROC_ThunkRef16To32W =
+{
+    0x58,                                       /* popl  %eax */
+    0x68, 0x00000000,                           /* pushl $proc32 */
+    0x50,                                       /* pushl %eax */
+    0x5566,                                     /* pushw %bp */
+    0x68, (void (*)())WINPROC_CallProc16To32W,  /* pushl $thunk32 */
+    0x9a, CallFrom16_long_wwwll,                /* lcall cs:relay */
+    WINE_CODE_SELECTOR
+};
+
+/* Reference 32A->16 thunk */
+static const WINPROC_THUNK_FROM32 WINPROC_ThunkRef32ATo16 =
+{
+    0x58,                                       /* popl  %eax */
+    0x68, 0x00000000,                           /* pushl $proc16 */
+    0x50,                                       /* pushl %eax */
+    0x55,                                       /* pushl %ebp */
+    0x68, "WINPROC_CallProc32ATo16",            /* pushl $name */
+    0x68, (void (*)())WINPROC_CallProc32ATo16,  /* pushl $thunk32 */
+    0xe9, CallFrom32_5                          /* jmp   relay */
+};
+
+
+static HANDLE32 WinProcHeap;
+
+/**********************************************************************
+ *	     WINPROC_Init
+ */
+BOOL32 WINPROC_Init(void)
+{
+    WinProcHeap = HeapCreate( HEAP_WINE_SEGPTR | HEAP_WINE_CODESEG, 0, 0 );
+    if (!WinProcHeap)
+    {
+        fprintf( stderr, "Unable to create winproc heap\n" );
+        return FALSE;
+    }
+    return TRUE;
+}
 
 
 /**********************************************************************
@@ -36,7 +149,7 @@
  *
  * Return a pointer to the win proc.
  */
-static WINDOWPROC *WINPROC_GetPtr( HANDLE32 handle )
+static WINDOWPROC *WINPROC_GetPtr( WNDPROC16 handle )
 {
     WINDOWPROC *proc;
 
@@ -65,111 +178,899 @@
  *
  * Allocate a new window procedure.
  */
-HANDLE32 WINPROC_AllocWinProc( UINT32 func, WINDOWPROCTYPE type )
+static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC16 func, WINDOWPROCTYPE type )
 {
-    WINDOWPROC *proc;
+    WINDOWPROC *proc, *oldproc;
 
-    /* Create the heap if necessary */
-
-    if (!WinProcHeap)
-    {
-        if (!(WinProcHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return 0;
-    }
-
-    /* Check if function is already a win proc */
-
-    if ((proc = WINPROC_GetPtr( (HANDLE32)func )))
-    {
-        proc->count++;
-        return (HANDLE32)func;
-    }
-
-    /* Now allocate a new one */
+    /* Allocate a window procedure */
 
     if (!(proc = HeapAlloc( WinProcHeap, 0, sizeof(WINDOWPROC) ))) return 0;
-    proc->magic = WINPROC_MAGIC;
-    proc->type  = type;
-    proc->count = 1;
-    proc->func  = func;
-    return (HANDLE32)proc;
+
+    /* Check if the function is already a win proc */
+
+    if ((oldproc = WINPROC_GetPtr( func )))
+    {
+        *proc = *oldproc;
+    }
+    else
+    {
+        switch(type)
+        {
+        case WIN_PROC_16:
+            proc->thunk.t_from32 = WINPROC_ThunkRef32ATo16;
+            proc->thunk.t_from32.proc = func;
+            /* We need to fix the relative jump target */
+            proc->thunk.t_from32.relay = (void (*)())((DWORD)proc->thunk.t_from32.relay -
+                                     (DWORD)(&proc->thunk.t_from32.relay + 1));
+            break;
+        case WIN_PROC_32A:
+            proc->thunk.t_from16 = WINPROC_ThunkRef16To32A;
+            proc->thunk.t_from16.proc = (FARPROC32)func;
+            break;
+        case WIN_PROC_32W:
+            proc->thunk.t_from16 = WINPROC_ThunkRef16To32W;
+            proc->thunk.t_from16.proc = (FARPROC32)func;
+            break;
+        default:
+            /* Should not happen */
+            break;
+        }
+        proc->magic = WINPROC_MAGIC;
+        proc->type  = type;
+    }
+    proc->next  = NULL;
+    return proc;
 }
 
 
 /**********************************************************************
- *	     WINPROC_CopyWinProc
+ *	     WINPROC_GetProc
  *
- * Copy a window procedure.
+ * Get a window procedure pointer that can be passed to the Windows program.
  */
-HANDLE32 WINPROC_CopyWinProc( HANDLE32 handle )
+WNDPROC16 WINPROC_GetProc( HWINDOWPROC proc, WINDOWPROCTYPE type )
 {
-    WINDOWPROC *proc;
-    if ((proc = WINPROC_GetPtr( (HANDLE32)handle )))
+    if (type == WIN_PROC_16)  /* We want a 16:16 address */
     {
-        proc->count++;
-        return handle;
+        if (((WINDOWPROC *)proc)->type == WIN_PROC_16)
+            return ((WINDOWPROC *)proc)->thunk.t_from32.proc;
+        else
+            return (WNDPROC16)HEAP_GetSegptr( WinProcHeap, 0, proc );
     }
-    return (HANDLE32)0;
+    else  /* We want a 32-bit address */
+    {
+        if (((WINDOWPROC *)proc)->type == WIN_PROC_16)
+            return (WNDPROC16)proc;
+        else
+            return (WNDPROC16)((WINDOWPROC *)proc)->thunk.t_from16.proc;
+    }
 }
 
 
 /**********************************************************************
- *	     WINPROC_FreeWinProc
+ *	     WINPROC_SetProc
  *
- * Free a window procedure.
+ * Set the window procedure for a window or class.
  */
-void WINPROC_FreeWinProc( HANDLE32 handle )
+BOOL32 WINPROC_SetProc( HWINDOWPROC *pFirst, WNDPROC16 func,
+                        WINDOWPROCTYPE type )
 {
-    WINDOWPROC *proc;
+    WINDOWPROC *proc, **ppPrev;
 
-    if (!(proc = WINPROC_GetPtr( handle )))
+    /* Check if function is already in the list */
+
+    ppPrev = (WINDOWPROC **)pFirst;
+    proc = WINPROC_GetPtr( func );
+    while (*ppPrev)
     {
-        fprintf( stderr, "WINPROC_FreeWinProc: invalid proc %08x\n", handle );
-        return;
+        if (proc)
+        {
+            if (*ppPrev == proc) break;
+        }
+        else
+        {
+            if (((*ppPrev)->type == type) &&
+                (func == WINPROC_THUNKPROC(*ppPrev))) break;
+        }
+        ppPrev = &(*ppPrev)->next;
     }
-    if (--proc->count == 0)
+
+    if (*ppPrev)  /* Remove it from the list */
     {
-        proc->magic = 0;  /* Just in case */
+        proc = *ppPrev;
+        *ppPrev = proc->next;
+    }
+    else  /* Allocate a new one */
+    {
+        if (proc)  /* Was already a win proc */
+        {
+            type = proc->type;
+            func = WINPROC_THUNKPROC(proc);
+        }
+        proc = WINPROC_AllocWinProc( func, type );
+        if (!proc) return FALSE;
+    }
+
+    /* Add the win proc at the head of the list */
+
+    proc->next  = *(WINDOWPROC **)pFirst;
+    *(WINDOWPROC **)pFirst = proc;
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	     WINPROC_FreeProc
+ *
+ * Free a list of win procs.
+ */
+void WINPROC_FreeProc( HWINDOWPROC proc )
+{
+    while (proc)
+    {
+        WINDOWPROC *next = ((WINDOWPROC *)proc)->next;
         HeapFree( WinProcHeap, 0, proc );
+        proc = next;
     }
 }
 
 
 /**********************************************************************
- *	     WINPROC_GetWinProcType
+ *	     WINPROC_GetProcType
  *
  * Return the window procedure type.
  */
-WINDOWPROCTYPE WINPROC_GetWinProcType( HANDLE32 handle )
+WINDOWPROCTYPE WINPROC_GetProcType( HWINDOWPROC proc )
 {
-    WINDOWPROC *proc = WINPROC_GetPtr( handle );
-    if (!proc) return WIN_PROC_INVALID;
-    return proc->type;
+    if (!proc ||
+        (((WINDOWPROC *)proc)->magic != WINPROC_MAGIC))
+        return WIN_PROC_INVALID;
+    return ((WINDOWPROC *)proc)->type;
 }
 
 
 /**********************************************************************
- *	     WINPROC_GetFunc16
+ *	     WINPROC_MapMsg32ATo32W
  *
- * Return the 16-bit function pointer, or NULL if none.
+ * Map a message from Ansi to Unicode.
+ * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
  */
-WNDPROC16 WINPROC_GetFunc16( HANDLE32 handle )
+INT32 WINPROC_MapMsg32ATo32W( UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
 {
-    WINDOWPROC *proc = WINPROC_GetPtr( handle );
-    if (!proc) return (WNDPROC16)0;
-    return (WNDPROC16)HEAP_GetSegptr( WinProcHeap, 0, proc );
+    switch(msg)
+    {
+    case WM_GETTEXT:
+        {
+            LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
+                                     wParam * sizeof(WCHAR) + sizeof(LPARAM) );
+            if (!ptr) return -1;
+            *ptr++ = *plparam;  /* Store previous lParam */
+            *plparam = (LPARAM)ptr;
+        }
+        return 1;
+    case WM_SETTEXT:
+        *plparam = (LPARAM)STRING32_DupAnsiToUni( (LPCSTR)*plparam );
+        return (*plparam ? 1 : -1);
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
+                                                                sizeof(*cs) );
+            if (!cs) return -1;
+            *cs = *(CREATESTRUCT32W *)*plparam;
+            if (HIWORD(cs->lpszName))
+                cs->lpszName = STRING32_DupAnsiToUni( (LPCSTR)cs->lpszName );
+            if (HIWORD(cs->lpszClass))
+                cs->lpszClass = STRING32_DupAnsiToUni( (LPCSTR)cs->lpszClass );
+            *plparam = (LPARAM)cs;
+        }
+        return 1;
+    default:  /* No translation needed */
+        return 0;
+    }
 }
 
 
 /**********************************************************************
- *	     WINPROC_GetFunc32
+ *	     WINPROC_UnmapMsg32ATo32W
  *
- * Return the 32-bit function pointer, or NULL if none.
+ * Unmap a message that was mapped from Ansi to Unicode.
  */
-WNDPROC32 WINPROC_GetFunc32( HANDLE32 handle )
+void WINPROC_UnmapMsg32ATo32W( UINT32 msg, WPARAM32 wParam, LPARAM lParam )
 {
-    WINDOWPROC *proc = WINPROC_GetPtr( handle );
-    if (!proc) return (WNDPROC32)0;
-    return (WNDPROC32)proc;
+    switch(msg)
+    {
+    case WM_GETTEXT:
+        {
+            LPARAM *ptr = (LPARAM *)lParam - 1;
+            STRING32_UniToAnsi( (LPSTR)*ptr, (LPWSTR)(ptr + 1) );
+            HeapFree( SystemHeap, 0, ptr );
+        }
+        break;
+    case WM_SETTEXT:
+        free( (void *)lParam );
+        break;
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
+            if (HIWORD(cs->lpszName)) free( (LPVOID)cs->lpszName );
+            if (HIWORD(cs->lpszClass)) free( (LPVOID)cs->lpszClass );
+            HeapFree( SystemHeap, 0, cs );
+        }
+        break;
+    }
+}
+
+
+/**********************************************************************
+ *	     WINPROC_MapMsg32WTo32A
+ *
+ * Map a message from Unicode to Ansi.
+ * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
+ */
+INT32 WINPROC_MapMsg32WTo32A( UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
+{
+    switch(msg)
+    {
+    case WM_GETTEXT:
+        {
+            LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
+                                               wParam + sizeof(LPARAM) );
+            if (!ptr) return -1;
+            *ptr++ = *plparam;  /* Store previous lParam */
+            *plparam = (LPARAM)ptr;
+        }
+        return 1;
+    case WM_SETTEXT:
+        *plparam = (LPARAM)STRING32_DupUniToAnsi( (LPCWSTR)*plparam );
+        return (*plparam ? 1 : -1);
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
+                                                                sizeof(*cs) );
+            if (!cs) return -1;
+            *cs = *(CREATESTRUCT32A *)*plparam;
+            if (HIWORD(cs->lpszName))
+                cs->lpszName  = STRING32_DupUniToAnsi( (LPCWSTR)cs->lpszName );
+            if (HIWORD(cs->lpszClass))
+                cs->lpszClass = STRING32_DupUniToAnsi( (LPCWSTR)cs->lpszClass);
+            *plparam = (LPARAM)cs;
+        }
+        return 1;
+    default:  /* No translation needed */
+        return 0;
+    }
+}
+
+
+/**********************************************************************
+ *	     WINPROC_UnmapMsg32WTo32A
+ *
+ * Unmap a message that was mapped from Unicode to Ansi.
+ */
+void WINPROC_UnmapMsg32WTo32A( UINT32 msg, WPARAM32 wParam, LPARAM lParam )
+{
+    switch(msg)
+    {
+    case WM_GETTEXT:
+        {
+            LPARAM *ptr = (LPARAM *)lParam - 1;
+            STRING32_AnsiToUni( (LPWSTR)*ptr, (LPSTR)(ptr + 1) );
+            HeapFree( SystemHeap, 0, ptr );
+        }
+        break;
+    case WM_SETTEXT:
+        free( (void *)lParam );
+        break;
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
+            if (HIWORD(cs->lpszName)) free( (LPVOID)cs->lpszName );
+            if (HIWORD(cs->lpszClass)) free( (LPVOID)cs->lpszClass );
+            HeapFree( SystemHeap, 0, cs );
+        }
+        break;
+    }
+}
+
+
+/**********************************************************************
+ *	     WINPROC_MapMsg16To32A
+ *
+ * Map a message from 16- to 32-bit Ansi.
+ * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
+ */
+INT32 WINPROC_MapMsg16To32A( UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
+                             WPARAM32 *pwparam32, LPARAM *plparam )
+{
+    *pmsg32 = (UINT32)msg16;
+    *pwparam32 = (WPARAM32)wParam16;
+    switch(msg16)
+    {
+    case WM_ACTIVATE:
+    case WM_CHARTOITEM:
+    case WM_COMMAND:
+    case WM_HSCROLL:
+    case WM_VKEYTOITEM:
+    case WM_VSCROLL:
+        *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
+        *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
+        return 0;
+    case WM_CTLCOLOR:
+        *pmsg32    = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
+        *pwparam32 = (WPARAM32)(HDC32)wParam16;
+        *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
+        return 0;
+    case WM_DRAWITEM:
+        {
+            DRAWITEMSTRUCT16* dis16 = (DRAWITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
+            DRAWITEMSTRUCT32 *dis = (DRAWITEMSTRUCT32*)HeapAlloc(SystemHeap, 0,
+                                                                 sizeof(*dis));
+            if (!dis) return -1;
+            dis->CtlType    = dis16->CtlType;
+            dis->CtlID      = dis16->CtlID;
+            dis->itemID     = dis16->itemID;
+            dis->itemAction = dis16->itemAction;
+            dis->itemState  = dis16->itemState;
+            dis->hwndItem   = dis16->hwndItem;
+            dis->hDC        = dis16->hDC;
+            dis->itemData   = dis16->itemData;
+            CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
+            *plparam = (LPARAM)dis;
+        }
+        return 1;
+    case WM_GETMINMAXINFO:
+        {
+            MINMAXINFO32 *mmi = (MINMAXINFO32 *)HeapAlloc( SystemHeap, 0,
+                                                sizeof(*mmi) + sizeof(LPARAM));
+            if (!mmi) return -1;
+            STRUCT32_MINMAXINFO16to32( (MINMAXINFO16*)PTR_SEG_TO_LIN(*plparam),
+                                       mmi );
+            *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)mmi;
+        }
+        return 1;
+    case WM_GETTEXT:
+        *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
+        return 0;
+    case WM_MDISETMENU:
+        *pwparam32 = (WPARAM32)(HMENU32)LOWORD(*plparam);
+        *plparam   = (LPARAM)(HMENU32)HIWORD(*plparam);
+        return 0;
+    case WM_MENUCHAR:
+    case WM_MENUSELECT:
+        *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
+        *plparam   = (LPARAM)(HMENU32)HIWORD(*plparam);
+        return 0;
+    case WM_NCCALCSIZE:
+        {
+            NCCALCSIZE_PARAMS16 *nc16;
+            NCCALCSIZE_PARAMS32 *nc;
+
+            nc = (NCCALCSIZE_PARAMS32 *)HeapAlloc( SystemHeap, 0,
+                                                sizeof(*nc) + sizeof(LPARAM) );
+            if (!nc) return -1;
+            nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(*plparam);
+            CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
+            if (wParam16)
+            {
+                nc->lppos = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
+                                                      sizeof(*nc->lppos) );
+                CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
+                CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
+                if (nc->lppos) STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos), nc->lppos );
+            }
+            *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)nc;
+        }
+        return 1;
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
+            CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
+                                                sizeof(*cs) + sizeof(LPARAM) );
+            if (!cs) return -1;
+            STRUCT32_CREATESTRUCT16to32A( cs16, cs );
+            cs->lpszName  = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszName);
+            cs->lpszClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
+            *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)cs;
+        }
+        return 1;
+    case WM_PARENTNOTIFY:
+        if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
+        {
+            *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
+            *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
+        }
+        else
+        {
+            *pwparam32 = MAKEWPARAM( wParam16, 0  /* FIXME? */ );
+        }
+        return 0;
+    case WM_SETTEXT:
+        *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
+        return 0;
+    case WM_WINDOWPOSCHANGING:
+    case WM_WINDOWPOSCHANGED:
+        {
+            WINDOWPOS32 *wp = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
+                                                sizeof(*wp) + sizeof(LPARAM) );
+            if (!wp) return -1;
+            STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(*plparam),
+                                      wp );
+            *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)wp;
+        }
+        return 1;
+    case WM_ASKCBFORMATNAME:
+    case WM_COMPAREITEM:
+    case WM_DELETEITEM:
+    case WM_DEVMODECHANGE:
+    case WM_MDIACTIVATE:
+    case WM_MDICREATE:
+    case WM_MEASUREITEM:
+    case WM_PAINTCLIPBOARD:
+    case WM_SIZECLIPBOARD:
+    case WM_WININICHANGE:
+        fprintf( stderr, "MapMsg16To32A: message %04x needs translation\n",
+                 msg16 );
+        return -1;
+
+    default:  /* No translation needed */
+        return 0;
+    }
+}
+
+
+/**********************************************************************
+ *	     WINPROC_UnmapMsg16To32A
+ *
+ * Unmap a message that was mapped from 16- to 32-bit Ansi.
+ */
+void WINPROC_UnmapMsg16To32A( UINT32 msg, WPARAM32 wParam, LPARAM lParam )
+{
+    switch(msg)
+    {
+    case WM_DRAWITEM:
+        HeapFree( SystemHeap, 0, (LPVOID)lParam );
+        break;
+    case WM_GETMINMAXINFO:
+        {
+            MINMAXINFO32 *mmi = (MINMAXINFO32 *)lParam;
+            lParam = *(LPARAM *)(mmi + 1);
+            STRUCT32_MINMAXINFO32to16( mmi,
+                                       (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam));
+            HeapFree( SystemHeap, 0, mmi );
+        }
+        break;
+    case WM_NCCALCSIZE:
+        {
+            NCCALCSIZE_PARAMS16 *nc16;
+            NCCALCSIZE_PARAMS32 *nc = (NCCALCSIZE_PARAMS32 *)lParam;
+            lParam = *(LPARAM *)(nc + 1);
+            nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
+            CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
+            if (wParam)
+            {
+                CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
+                CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
+                if (nc->lppos)
+                {
+                    STRUCT32_WINDOWPOS32to16( nc->lppos,
+                                   (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos));
+                    HeapFree( SystemHeap, 0, nc->lppos );
+                }
+            }
+            HeapFree( SystemHeap, 0, nc );
+        }
+	break;
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
+            lParam = *(LPARAM *)(cs + 1);
+            STRUCT32_CREATESTRUCT32Ato16( cs,
+                                    (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
+            HeapFree( SystemHeap, 0, cs );
+        }
+        break;
+    case WM_WINDOWPOSCHANGING:
+    case WM_WINDOWPOSCHANGED:
+        {
+            WINDOWPOS32 *wp = (WINDOWPOS32 *)lParam;
+            lParam = *(LPARAM *)(wp + 1);
+            STRUCT32_WINDOWPOS32to16(wp,(WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam));
+            HeapFree( SystemHeap, 0, wp );
+        }
+        break;
+    }
+}
+
+
+/**********************************************************************
+ *	     WINPROC_MapMsg16To32W
+ *
+ * Map a message from 16- to 32-bit Unicode.
+ * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
+ */
+INT32 WINPROC_MapMsg16To32W( UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
+                             WPARAM32 *pwparam32, LPARAM *plparam )
+{
+    switch(msg16)
+    {
+    case WM_GETTEXT:
+    case WM_SETTEXT:
+        *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
+        return WINPROC_MapMsg32ATo32W( *pmsg32, *pwparam32, plparam );
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
+            CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
+                                                sizeof(*cs) + sizeof(LPARAM) );
+            if (!cs) return -1;
+            STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCT32A *)cs );
+            cs->lpszName  = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszName);
+            cs->lpszClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
+            if (HIWORD(cs->lpszName))
+                cs->lpszName = STRING32_DupAnsiToUni( (LPCSTR)cs->lpszName );
+            if (HIWORD(cs->lpszClass))
+                cs->lpszClass = STRING32_DupAnsiToUni( (LPCSTR)cs->lpszClass );
+            *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)cs;
+        }
+        return 1;
+    default:  /* No Unicode translation needed */
+        return WINPROC_MapMsg16To32A( msg16, wParam16, pmsg32,
+                                      pwparam32, plparam );
+    }
+}
+
+
+/**********************************************************************
+ *	     WINPROC_UnmapMsg16To32W
+ *
+ * Unmap a message that was mapped from 16- to 32-bit Unicode.
+ */
+void WINPROC_UnmapMsg16To32W( UINT32 msg, WPARAM32 wParam, LPARAM lParam )
+{
+    switch(msg)
+    {
+    case WM_GETTEXT:
+    case WM_SETTEXT:
+        WINPROC_UnmapMsg32ATo32W( msg, wParam, lParam );
+        break;
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
+            lParam = *(LPARAM *)(cs + 1);
+            STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs,
+                                    (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
+            if (HIWORD(cs->lpszName)) free( (LPVOID)cs->lpszName );
+            if (HIWORD(cs->lpszClass)) free( (LPVOID)cs->lpszClass );
+            HeapFree( SystemHeap, 0, cs );
+        }
+        break;
+    default:
+        WINPROC_UnmapMsg16To32A( msg, wParam, lParam );
+        break;
+    }
+}
+
+
+/**********************************************************************
+ *	     WINPROC_MapMsg32ATo16
+ *
+ * Map a message from 32-bit Ansi to 16-bit.
+ * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
+ */
+INT32 WINPROC_MapMsg32ATo16( UINT32 msg32, WPARAM32 wParam32, UINT16 *pmsg16,
+                             WPARAM16 *pwparam16, LPARAM *plparam )
+{
+    *pmsg16 = (UINT16)msg32;
+    *pwparam16 = (WPARAM16)LOWORD(wParam32);
+    switch(msg32)
+    {
+    case WM_ACTIVATE:
+    case WM_CHARTOITEM:
+    case WM_COMMAND:
+    case WM_HSCROLL:
+    case WM_VKEYTOITEM:
+    case WM_VSCROLL:
+        *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
+        return 0;
+    case WM_CTLCOLORMSGBOX:
+    case WM_CTLCOLOREDIT:
+    case WM_CTLCOLORLISTBOX:
+    case WM_CTLCOLORBTN:
+    case WM_CTLCOLORDLG:
+    case WM_CTLCOLORSCROLLBAR:
+    case WM_CTLCOLORSTATIC:
+        *pmsg16  = WM_CTLCOLOR;
+        *plparam = MAKELPARAM( (HWND16)*plparam,
+                               (WORD)msg32 - WM_CTLCOLORMSGBOX );
+        return 0;
+    case WM_DRAWITEM:
+        {
+            DRAWITEMSTRUCT32 *dis32 = (DRAWITEMSTRUCT32 *)*plparam;
+            DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16);
+            if (!dis) return -1;
+            dis->CtlType    = (UINT16)dis32->CtlType;
+            dis->CtlID      = (UINT16)dis32->CtlID;
+            dis->itemID     = (UINT16)dis32->itemID;
+            dis->itemAction = (UINT16)dis32->itemAction;
+            dis->itemState  = (UINT16)dis32->itemState;
+            dis->hwndItem   = (HWND16)dis32->hwndItem;
+            dis->hDC        = (HDC16)dis32->hDC;
+            dis->itemData   = dis32->itemData;
+            CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
+            *plparam = (LPARAM)SEGPTR_GET(dis);
+        }
+        return 1;
+    case WM_GETMINMAXINFO:
+        {
+            MINMAXINFO16 *mmi = (MINMAXINFO16 *)SEGPTR_ALLOC( sizeof(*mmi) +
+                                                              sizeof(LPARAM) );
+            if (!mmi) return -1;
+            STRUCT32_MINMAXINFO32to16( (MINMAXINFO32 *)*plparam, mmi );
+            *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)SEGPTR_GET(mmi);
+        }
+        return 1;
+    case WM_GETTEXT:
+        {
+            LPSTR str;
+            *pwparam16 = (WPARAM16)MIN( wParam32, 0xff80 ); /* Must be < 64K */
+            if (!(str = SEGPTR_ALLOC(*pwparam16 + sizeof(LPARAM)))) return -1;
+            *((LPARAM *)str)++ = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)SEGPTR_GET(str);
+        }
+        return 1;
+    case WM_MDISETMENU:
+        *pwparam16 = TRUE;  /* FIXME? */
+        *plparam   = MAKELPARAM( (HMENU16)LOWORD(wParam32),
+                                 (HMENU16)LOWORD(*plparam) );
+        return 0;
+    case WM_MENUCHAR:
+    case WM_MENUSELECT:
+        *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
+        return 0;
+    case WM_NCCALCSIZE:
+        {
+            NCCALCSIZE_PARAMS32 *nc32 = (NCCALCSIZE_PARAMS32 *)*plparam;
+            NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)SEGPTR_ALLOC( sizeof(*nc) + sizeof(LPARAM) );
+            if (!nc) return -1;
+
+            CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
+            if (wParam32)
+            {
+                WINDOWPOS16 *wp;
+                CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
+                CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
+                if (!(wp = SEGPTR_NEW(WINDOWPOS16)))
+                {
+                    SEGPTR_FREE(nc);
+                    return -1;
+                }
+                STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
+                nc->lppos = SEGPTR_GET(wp);
+            }
+            *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)SEGPTR_GET(nc);
+        }
+        return 1;
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT16 *cs;
+            CREATESTRUCT32A *cs32 = (CREATESTRUCT32A *)*plparam;
+            LPSTR name, cls;
+
+            if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
+            STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
+            name = SEGPTR_STRDUP( cs32->lpszName );
+            cls  = SEGPTR_STRDUP( cs32->lpszClass );
+            cs->lpszName  = SEGPTR_GET(name);
+            cs->lpszClass = SEGPTR_GET(cls);
+            *plparam = (LPARAM)SEGPTR_GET(cs);
+        }
+        return 1;
+    case WM_PARENTNOTIFY:
+        if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
+            *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
+        /* else nothing to do */
+        return 0;
+    case WM_SETTEXT:
+        {
+            LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
+            if (!str) return -1;
+            *plparam = (LPARAM)SEGPTR_GET(str);
+        }
+        return 1;
+    case WM_WINDOWPOSCHANGING:
+    case WM_WINDOWPOSCHANGED:
+        {
+            WINDOWPOS16 *wp = (WINDOWPOS16 *)SEGPTR_ALLOC( sizeof(*wp) +
+                                                           sizeof(LPARAM) );
+            if (!wp) return -1;
+            STRUCT32_WINDOWPOS32to16( (WINDOWPOS32 *)*plparam, wp );
+            *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)SEGPTR_GET(wp);
+        }
+        return 1;
+    case WM_ASKCBFORMATNAME:
+    case WM_COMPAREITEM:
+    case WM_DELETEITEM:
+    case WM_DEVMODECHANGE:
+    case WM_MDIACTIVATE:
+    case WM_MDICREATE:
+    case WM_MEASUREITEM:
+    case WM_PAINTCLIPBOARD:
+    case WM_SIZECLIPBOARD:
+    case WM_WININICHANGE:
+        fprintf( stderr, "MapMsg32ATo16: message %04x needs translation\n",
+                 msg32 );
+        return -1;
+
+    default:  /* No translation needed */
+        return 0;
+    }
+}
+
+
+/**********************************************************************
+ *	     WINPROC_UnmapMsg32ATo16
+ *
+ * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
+ */
+void WINPROC_UnmapMsg32ATo16( UINT16 msg, WPARAM16 wParam, LPARAM lParam )
+{
+    switch(msg)
+    {
+    case WM_DRAWITEM:
+        SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
+        break;
+    case WM_GETMINMAXINFO:
+        {
+            MINMAXINFO16 *mmi = (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam);
+            lParam = *(LPARAM *)(mmi + 1);
+            STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO32 *)lParam );
+            SEGPTR_FREE(mmi);
+        }
+        break;
+    case WM_GETTEXT:
+        {
+            LPSTR str = (LPSTR)PTR_SEG_TO_LIN(lParam);
+            lParam = *((LPARAM *)str - 1);
+            strcpy( (LPSTR)lParam, str );
+            SEGPTR_FREE( (LPARAM *)str - 1 );
+        }
+        break;
+    case WM_NCCALCSIZE:
+        {
+            NCCALCSIZE_PARAMS32 *nc32;
+            NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
+            lParam = *(LPARAM *)(nc + 1);
+            nc32 = (NCCALCSIZE_PARAMS32 *)lParam;
+            CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
+            if (wParam)
+            {
+                CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
+                CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
+                STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc->lppos),
+                                          nc32->lppos );
+                SEGPTR_FREE( PTR_SEG_TO_LIN(nc->lppos) );
+            }
+            SEGPTR_FREE(nc);
+        }
+        break;
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
+            SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszName) );
+            SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszClass) );
+            SEGPTR_FREE( cs );
+        }
+        break;
+    case WM_SETTEXT:
+        SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
+        break;
+    case WM_WINDOWPOSCHANGING:
+    case WM_WINDOWPOSCHANGED:
+        {
+            WINDOWPOS16 *wp = (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam);
+            lParam = *(LPARAM *)(wp + 1);
+            STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS32 *)lParam );
+            SEGPTR_FREE(wp);
+        }
+        break;
+    }
+}
+
+
+/**********************************************************************
+ *	     WINPROC_MapMsg32WTo16
+ *
+ * Map a message from 32-bit Unicode to 16-bit.
+ * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
+ */
+INT32 WINPROC_MapMsg32WTo16( UINT32 msg32, WPARAM32 wParam32, UINT16 *pmsg16,
+                             WPARAM16 *pwparam16, LPARAM *plparam )
+{
+    switch(msg32)
+    {
+    case WM_NCCREATE:
+    case WM_CREATE:
+        {
+            CREATESTRUCT16 *cs;
+            CREATESTRUCT32W *cs32 = (CREATESTRUCT32W *)*plparam;
+
+            if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
+            STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs32, cs );
+            if (HIWORD(cs32->lpszName))
+            {
+                LPSTR name = SEGPTR_ALLOC( lstrlen32W(cs32->lpszName) + 1 );
+                STRING32_UniToAnsi( name, cs32->lpszName );
+                cs->lpszName = SEGPTR_GET(name);
+            }
+            else cs->lpszName = (SEGPTR)cs32->lpszName;
+            if (HIWORD(cs32->lpszClass))
+            {
+                LPSTR name = SEGPTR_ALLOC( lstrlen32W(cs32->lpszClass) + 1 );
+                STRING32_UniToAnsi( name, cs32->lpszClass );
+                cs->lpszClass = SEGPTR_GET(name);
+            }
+            else cs->lpszClass = (SEGPTR)cs32->lpszClass;
+            *pmsg16    = (UINT16)msg32;
+            *pwparam16 = (WPARAM16)LOWORD(wParam32);
+            *plparam   = (LPARAM)SEGPTR_GET(cs);
+        }
+        return 1;
+    case WM_SETTEXT:
+        {
+            LPSTR str = SEGPTR_ALLOC( lstrlen32W((LPWSTR)*plparam) + 1 );
+            if (!str) return -1;
+            STRING32_UniToAnsi( str, (LPWSTR)*plparam );
+            *pmsg16    = (UINT16)msg32;
+            *pwparam16 = (WPARAM16)LOWORD(wParam32);
+            *plparam   = (LPARAM)SEGPTR_GET(str);
+        }
+        return 1;
+    default:  /* No Unicode translation needed */
+        return WINPROC_MapMsg32ATo16( msg32, wParam32, pmsg16,
+                                      pwparam16, plparam );
+    }
+}
+
+
+/**********************************************************************
+ *	     WINPROC_UnmapMsg32WTo16
+ *
+ * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
+ */
+void WINPROC_UnmapMsg32WTo16( UINT16 msg, WPARAM16 wParam, LPARAM lParam )
+{
+    switch(msg)
+    {
+    case WM_GETTEXT:
+        {
+            LPSTR str = (LPSTR)PTR_SEG_TO_LIN(lParam);
+            lParam = *((LPARAM *)str - 1);
+            STRING32_AnsiToUni( (LPWSTR)lParam, str );
+            SEGPTR_FREE( (LPARAM *)str - 1 );
+        }
+        break;
+    default:
+        WINPROC_UnmapMsg32ATo16( msg, wParam, lParam );
+        break;
+    }
 }
 
 
@@ -184,42 +1085,10 @@
 {
     LRESULT result;
 
-    switch(msg)
-    {
-    case WM_GETTEXT:
-        {
-            LPWSTR str = (LPWSTR)HeapAlloc(SystemHeap,0,wParam*sizeof(WCHAR));
-            if (!str) return 0;
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str );
-            STRING32_UniToAnsi( (LPSTR)lParam, str );
-            HeapFree( SystemHeap, 0, str );
-        }
-        return result;  /* FIXME? */
-
-    case WM_SETTEXT:
-        {
-            LPWSTR str = STRING32_DupAnsiToUni( (LPCSTR)lParam );
-            if (!str) return 0;
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str );
-            free( str );
-        }
-        return result;
-
-    case WM_NCCREATE:
-    case WM_CREATE:
-        {
-            CREATESTRUCT32W cs = *(CREATESTRUCT32W *)lParam;
-            cs.lpszName  = STRING32_DupAnsiToUni( (LPCSTR)cs.lpszName );
-            cs.lpszClass = STRING32_DupAnsiToUni( (LPCSTR)cs.lpszName );
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&cs );
-            free( (LPVOID)cs.lpszName );
-            free( (LPVOID)cs.lpszClass );
-        }
-        return result;
-	
-    default:  /* No translation needed */
-        return CallWndProc32( func, hwnd, msg, wParam, lParam );
-    }
+    if (WINPROC_MapMsg32ATo32W( msg, wParam, &lParam ) == -1) return 0;
+    result = CallWndProc32( func, hwnd, msg, wParam, lParam );
+    WINPROC_UnmapMsg32ATo32W( msg, wParam, lParam );
+    return result;
 }
 
 
@@ -234,44 +1103,10 @@
 {
     LRESULT result;
 
-    switch(msg)
-    {
-    case WM_GETTEXT:
-        {
-            LPSTR str = (LPSTR)HeapAlloc( SystemHeap, 0, wParam );
-            if (!str) return 0;
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str );
-            STRING32_AnsiToUni( (LPWSTR)lParam, str );
-            HeapFree( SystemHeap, 0, str );
-        }
-        return result;  /* FIXME? */
-
-    case WM_SETTEXT:
-        {
-            LPSTR str = STRING32_DupUniToAnsi( (LPCWSTR)lParam );
-            if (!str) return 0;
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str );
-            free( str );
-        }
-        return result;
-
-    case WM_NCCREATE:
-    case WM_CREATE:
-        {
-            CREATESTRUCT32A cs = *(CREATESTRUCT32A *)lParam;
-            if (HIWORD(cs.lpszName))
-                cs.lpszName  = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName );
-            if (HIWORD(cs.lpszClass))
-                cs.lpszClass = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName );
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&cs );
-            if (HIWORD(cs.lpszName)) free( (LPVOID)cs.lpszName );
-            if (HIWORD(cs.lpszClass)) free( (LPVOID)cs.lpszClass );
-        }
-        return result;
-	
-    default:  /* No translation needed */
-        return CallWndProc32( func, hwnd, msg, wParam, lParam );
-    }
+    if (WINPROC_MapMsg32WTo32A( msg, wParam, &lParam ) == -1) return 0;
+    result = CallWndProc32( func, hwnd, msg, wParam, lParam );
+    WINPROC_UnmapMsg32WTo32A( msg, wParam, lParam );
+    return result;
 }
 
 
@@ -280,161 +1115,19 @@
  *
  * Call a 32-bit window procedure, translating the 16-bit args.
  */
-static LRESULT WINPROC_CallProc16To32A(WNDPROC32 func, HWND16 hwnd, UINT16 msg,
-                                       WPARAM16 wParam, LPARAM lParam )
+LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
+                                 WPARAM16 wParam, LPARAM lParam,
+                                 WNDPROC32 func )
 {
     LRESULT result;
+    UINT32 msg32;
+    WPARAM32 wParam32;
 
-    switch(msg)
-    {
-    case WM_ACTIVATE:
-    case WM_CHARTOITEM:
-    case WM_COMMAND:
-    case WM_HSCROLL:
-    case WM_VKEYTOITEM:
-    case WM_VSCROLL:
-        return CallWndProc32( func, hwnd, msg,
-                              MAKEWPARAM( wParam, HIWORD(lParam) ),
-                              (LPARAM)(HWND32)LOWORD(lParam) );
-    case WM_CTLCOLOR:
-        return CallWndProc32( func, hwnd, WM_CTLCOLORMSGBOX + HIWORD(lParam),
-                              (WPARAM32)(HDC32)wParam,
-                              (LPARAM)(HWND32)LOWORD(lParam) );
-    case WM_DRAWITEM:
-        {
-            DRAWITEMSTRUCT16*dis16 = (DRAWITEMSTRUCT16*)PTR_SEG_TO_LIN(lParam);
-            DRAWITEMSTRUCT32 dis;
-            dis.CtlType    = dis16->CtlType;
-            dis.CtlID      = dis16->CtlID;
-            dis.itemID     = dis16->itemID;
-            dis.itemAction = dis16->itemAction;
-            dis.itemState  = dis16->itemState;
-            dis.hwndItem   = dis16->hwndItem;
-            dis.hDC        = dis16->hDC;
-            dis.itemData   = dis16->itemData;
-            CONV_RECT16TO32( &dis16->rcItem, &dis.rcItem );
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&dis );
-            /* We don't bother to translate it back */
-        }
-        return result;
-
-    case WM_GETMINMAXINFO:
-        {
-            MINMAXINFO32 mmi;
-            STRUCT32_MINMAXINFO16to32( (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam),
-                                       &mmi );
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&mmi);
-            STRUCT32_MINMAXINFO32to16( &mmi,
-                                       (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam));
-        }
-        return result;
-
-    case WM_GETTEXT:
-        return CallWndProc32( func, hwnd, msg, wParam,
-                              (LPARAM)PTR_SEG_TO_LIN(lParam) );
-    case WM_MDISETMENU:
-        return CallWndProc32( func, hwnd, msg,
-                              (WPARAM32)(HMENU32)LOWORD(lParam),
-                              (LPARAM)(HMENU32)HIWORD(lParam) );
-    case WM_MENUCHAR:
-    case WM_MENUSELECT:
-        return CallWndProc32( func, hwnd, msg,
-                              MAKEWPARAM( wParam, LOWORD(lParam) ),
-                              (LPARAM)(HMENU32)HIWORD(lParam) );
-    case WM_NCCALCSIZE:
-        {
-            NCCALCSIZE_PARAMS16 *pnc16;
-            NCCALCSIZE_PARAMS32 nc;
-            WINDOWPOS32 wp;
-
-            pnc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
-            CONV_RECT16TO32( &pnc16->rgrc[0], &nc.rgrc[0] );
-            if (wParam)
-            {
-                CONV_RECT16TO32( &pnc16->rgrc[1], &nc.rgrc[1] );
-                CONV_RECT16TO32( &pnc16->rgrc[2], &nc.rgrc[2] );
-                STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(pnc16->lppos),
-                                          &wp );
-                nc.lppos = &wp;
-            }
-
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&nc );
-
-            pnc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
-            CONV_RECT32TO16( &nc.rgrc[0], &pnc16->rgrc[0] );
-            if (wParam)
-            {
-                CONV_RECT32TO16( &nc.rgrc[1], &pnc16->rgrc[1] );
-                CONV_RECT32TO16( &nc.rgrc[2], &pnc16->rgrc[2] );
-                STRUCT32_WINDOWPOS32to16( nc.lppos,
-                                  (WINDOWPOS16 *)PTR_SEG_TO_LIN(pnc16->lppos));
-            }
-        }
-        return result;
-	
-    case WM_NCCREATE:
-    case WM_CREATE:
-        {
-            CREATESTRUCT16 *pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
-            CREATESTRUCT32A cs;
-
-            STRUCT32_CREATESTRUCT16to32A( pcs16, &cs );
-            /* FIXME: Unicode */
-            cs.lpszName       = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName);
-            cs.lpszClass      = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass);
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&cs );
-            pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
-            STRUCT32_CREATESTRUCT32Ato16( &cs, pcs16 );
-
-            if (cs.lpszName != (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName))
-                fprintf( stderr, "CallWindowProc16: WM_NCCREATE(%04x) changed lpszName (%p->%p), please report.\n",
-                    msg, (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName), cs.lpszName);
-            if (cs.lpszClass != (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass))
-                fprintf( stderr, "CallWindowProc16: WM_NCCREATE(%04x) changed lpszClass (%p->%p), please report.\n",
-                  msg, (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass), cs.lpszClass);
-        }
-        return result;
-
-    case WM_PARENTNOTIFY:
-        if ((wParam == WM_CREATE) || (wParam == WM_DESTROY))
-            return CallWndProc32( func, hwnd, msg,
-                                  MAKEWPARAM( wParam, HIWORD(lParam) ),
-                                  (LPARAM)(HWND32)LOWORD(lParam) );
-        else return CallWndProc32( func, hwnd, msg,
-                                   MAKEWPARAM( wParam, 0  /* FIXME? */ ),
-                                   lParam );
-    case WM_SETTEXT:
-        /* FIXME: Unicode */
-        return CallWndProc32( func, hwnd, msg, wParam,
-                              (LPARAM)PTR_SEG_TO_LIN(lParam) );
-
-    case WM_WINDOWPOSCHANGING:
-    case WM_WINDOWPOSCHANGED:
-        {
-            WINDOWPOS32 wp;
-            STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam),
-                                      &wp );
-            result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&wp );
-            STRUCT32_WINDOWPOS32to16( &wp,
-                                      (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam) );
-        }
-        return result;
-
-    case WM_ASKCBFORMATNAME:
-    case WM_COMPAREITEM:
-    case WM_DELETEITEM:
-    case WM_DEVMODECHANGE:
-    case WM_MDIACTIVATE:
-    case WM_MDICREATE:
-    case WM_MEASUREITEM:
-    case WM_PAINTCLIPBOARD:
-    case WM_SIZECLIPBOARD:
-    case WM_WININICHANGE:
-        fprintf( stderr, "CallWindowProc16To32: message %04x needs translation\n", msg );
-
-    default:  /* No translation needed */
-        return CallWndProc32( func, hwnd, msg, (WPARAM32)wParam, lParam );
-    }
+    if (WINPROC_MapMsg16To32A( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
+        return 0;
+    result = CallWndProc32( func, hwnd, msg32, wParam32, lParam );
+    WINPROC_UnmapMsg16To32A( msg32, wParam32, lParam );
+    return result;
 }
 
 
@@ -443,37 +1136,19 @@
  *
  * Call a 32-bit window procedure, translating the 16-bit args.
  */
-static LRESULT WINPROC_CallProc16To32W(WNDPROC32 func, HWND16 hwnd, UINT16 msg,
-                                       WPARAM16 wParam, LPARAM lParam )
+LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
+                                 WPARAM16 wParam, LPARAM lParam,
+                                 WNDPROC32 func )
 {
-    LRESULT result = 0;
+    LRESULT result;
+    UINT32 msg32;
+    WPARAM32 wParam32;
 
-    switch(msg)
-    {
-    case WM_GETTEXT:
-    case WM_SETTEXT:
-        return WINPROC_CallProc32ATo32W( func, hwnd, msg, wParam,
-                                         (LPARAM)PTR_SEG_TO_LIN(lParam) );
-
-    case WM_NCCREATE:
-    case WM_CREATE:
-        {
-            CREATESTRUCT16 *pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
-            CREATESTRUCT32A cs;
-
-            STRUCT32_CREATESTRUCT16to32A( pcs16, &cs );
-            cs.lpszName       = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName);
-            cs.lpszClass      = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass);
-            result = WINPROC_CallProc32ATo32W( func, hwnd, msg, wParam,
-                                               (LPARAM)&cs );
-            pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
-            STRUCT32_CREATESTRUCT32Ato16( &cs, pcs16 );
-        }
-        return result;
-
-    default:  /* No Unicode translation needed */
-        return WINPROC_CallProc16To32A( func, hwnd, msg, wParam, lParam );
-    }
+    if (WINPROC_MapMsg16To32W( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
+        return 0;
+    result = CallWndProc32( func, hwnd, msg32, wParam32, lParam );
+    WINPROC_UnmapMsg16To32W( msg32, wParam32, lParam );
+    return result;
 }
 
 
@@ -482,201 +1157,37 @@
  *
  * Call a 16-bit window procedure, translating the 32-bit args.
  */
-static LRESULT WINPROC_CallProc32ATo16( WNDPROC16 func, WORD ds, HWND32 hwnd,
+static LRESULT WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
                                         UINT32 msg, WPARAM32 wParam,
                                         LPARAM lParam )
 {
     LRESULT result;
+    UINT16 msg16;
+    WPARAM16 wParam16;
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    WORD ds = wndPtr ? wndPtr->hInstance : CURRENT_DS;
 
-    switch(msg)
+    if (WINPROC_MapMsg32ATo16( msg, wParam, &msg16, &wParam16, &lParam ) == -1)
+        return 0;
+#ifndef WINELIB
+    if ((msg16 == WM_CREATE) || (msg16 == WM_NCCREATE))
     {
-    case WM_ACTIVATE:
-    case WM_CHARTOITEM:
-    case WM_COMMAND:
-    case WM_HSCROLL:
-    case WM_VKEYTOITEM:
-    case WM_VSCROLL:
-        return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                              MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
-        
-    case WM_CTLCOLORMSGBOX:
-    case WM_CTLCOLOREDIT:
-    case WM_CTLCOLORLISTBOX:
-    case WM_CTLCOLORBTN:
-    case WM_CTLCOLORDLG:
-    case WM_CTLCOLORSCROLLBAR:
-    case WM_CTLCOLORSTATIC:
-        return CallWndProc16( func, ds, hwnd, WM_CTLCOLOR, (WPARAM16)wParam,
-                              MAKELPARAM( (HWND16)lParam,
-                                          (WORD)msg - WM_CTLCOLORMSGBOX ) );
-    case WM_DRAWITEM:
-        {
-            DRAWITEMSTRUCT32 *dis32 = (DRAWITEMSTRUCT32 *)lParam;
-            DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16);
-            if (!dis) return 0;
-            dis->CtlType    = (UINT16)dis32->CtlType;
-            dis->CtlID      = (UINT16)dis32->CtlID;
-            dis->itemID     = (UINT16)dis32->itemID;
-            dis->itemAction = (UINT16)dis32->itemAction;
-            dis->itemState  = (UINT16)dis32->itemState;
-            dis->hwndItem   = (HWND16)dis32->hwndItem;
-            dis->hDC        = (HDC16)dis32->hDC;
-            dis->itemData   = dis32->itemData;
-            CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
-            result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                                    (LPARAM)SEGPTR_GET(dis) );
-            /* We don't bother to translate it back */
-            SEGPTR_FREE(dis);
-        }
-        return result;
-
-    case WM_GETMINMAXINFO:
-        {
-            MINMAXINFO16 *mmi = SEGPTR_NEW(MINMAXINFO16);
-            if (!mmi) return 0;
-            STRUCT32_MINMAXINFO32to16( (MINMAXINFO32 *)lParam, mmi );
-            result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                                    (LPARAM)SEGPTR_GET(mmi) );
-            STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO32 *)lParam );
-            SEGPTR_FREE(mmi);
-        }
-        return result;
-
-    case WM_GETTEXT:
-        {
-            LPSTR str;
-            wParam = MIN( wParam, 0xff80 );  /* Size must be < 64K */
-            if (!(str = SEGPTR_ALLOC( wParam ))) return 0;
-            result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                                    (LPARAM)SEGPTR_GET(str) );
-            if (result > 0) memcpy( (LPSTR)lParam, str, result );
-            SEGPTR_FREE(str);
-        }
-        return result;
-
-    case WM_MDISETMENU:
-        return CallWndProc16( func, ds, hwnd, msg, TRUE /* FIXME? */,
-                              MAKELPARAM( (HMENU16)LOWORD(lParam),
-                                          (HMENU16)HIWORD(lParam) ) );
-    case WM_MENUCHAR:
-    case WM_MENUSELECT:
-        return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)LOWORD(wParam),
-                              MAKELPARAM( HIWORD(wParam), (HMENU16)lParam ) );
-    case WM_NCCALCSIZE:
-        {
-            NCCALCSIZE_PARAMS32 *nc32 = (NCCALCSIZE_PARAMS32 *)lParam;
-            NCCALCSIZE_PARAMS16 *nc;
-            WINDOWPOS16 *wp = NULL;
-
-            if (!(nc = SEGPTR_NEW(NCCALCSIZE_PARAMS16))) return 0;
-            CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
-            if (wParam)
-            {
-                CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
-                CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
-                if (!(wp = SEGPTR_NEW(WINDOWPOS16)))
-                {
-                    SEGPTR_FREE(nc);
-                    return 0;
-                }
-                STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
-                nc->lppos = SEGPTR_GET(wp);
-            }
-            result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                                    (LPARAM)SEGPTR_GET(nc) );
-            CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
-            if (wParam)
-            {
-                CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
-                CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
-                STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc->lppos),
-                                          nc32->lppos );
-                SEGPTR_FREE(wp);
-            }
-            SEGPTR_FREE(nc);
-        }
-        return result;
-
-    case WM_NCCREATE:
-    case WM_CREATE:
-        {
-            CREATESTRUCT16 *cs;
-            CREATESTRUCT32A *cs32 = (CREATESTRUCT32A *)lParam;
-            LPSTR name, cls;
-
-            if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return 0;
-            STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
-            name = SEGPTR_STRDUP( cs32->lpszName );
-            cls  = SEGPTR_STRDUP( cs32->lpszClass );
-            cs->lpszName  = SEGPTR_GET(name);
-            cs->lpszClass = SEGPTR_GET(cls);
-#ifdef WINELIB
-            result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                                    (LPARAM)SEGPTR_GET(cs) );
-#else
-            /* Build the CREATESTRUCT on the 16-bit stack. */
-            /* This is really ugly, but some programs (notably the */
-            /* "Undocumented Windows" examples) want it that way.  */
-            result = CallWndProcNCCREATE16( func, ds, cs->dwExStyle,
+        CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
+        /* Build the CREATESTRUCT on the 16-bit stack. */
+        /* This is really ugly, but some programs (notably the */
+        /* "Undocumented Windows" examples) want it that way.  */
+        result = CallWndProcNCCREATE16( func, ds, cs->dwExStyle,
                       cs->lpszClass, cs->lpszName, cs->style, cs->x, cs->y,
                       cs->cx, cs->cy, cs->hwndParent, cs->hMenu, cs->hInstance,
-                      (LONG)cs->lpCreateParams, hwnd, msg, (WPARAM16)wParam,
+                      (LONG)cs->lpCreateParams, hwnd, msg16, wParam16,
                       MAKELONG( IF1632_Saved16_sp-sizeof(CREATESTRUCT16),
                                 IF1632_Saved16_ss ) );
-#endif  /* WINELIB */
-            /* We don't bother to translate the structure back */
-            SEGPTR_FREE(name);
-            SEGPTR_FREE(cls);
-            SEGPTR_FREE(cs);
-        }
-        return result;
-	
-    case WM_PARENTNOTIFY:
-        if ((wParam == WM_CREATE) || (wParam == WM_DESTROY))
-            return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                                  MAKELPARAM( (HWND16)lParam, LOWORD(wParam)));
-        else
-            return CallWndProc16( func, ds, hwnd, msg,
-                                  (WPARAM16)wParam, lParam );
-
-    case WM_SETTEXT:
-        {
-            LPSTR str = SEGPTR_STRDUP( (LPSTR)lParam );
-            if (!str) return 0;
-            result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                                    (LPARAM)SEGPTR_GET(str) );
-            SEGPTR_FREE(str);
-        }
-        return result;
-
-    case WM_WINDOWPOSCHANGING:
-    case WM_WINDOWPOSCHANGED:
-        {
-            WINDOWPOS16 *wp;
-            if (!(wp = SEGPTR_NEW(WINDOWPOS16))) return 0;
-            STRUCT32_WINDOWPOS32to16( (WINDOWPOS32 *)lParam, wp );
-            result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                                    (LPARAM)SEGPTR_GET(wp) );
-            STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS32 *)lParam );
-            SEGPTR_FREE(wp);
-        }
-        return result;
-
-    case WM_ASKCBFORMATNAME:
-    case WM_COMPAREITEM:
-    case WM_DELETEITEM:
-    case WM_DEVMODECHANGE:
-    case WM_MDIACTIVATE:
-    case WM_MDICREATE:
-    case WM_MEASUREITEM:
-    case WM_PAINTCLIPBOARD:
-    case WM_SIZECLIPBOARD:
-    case WM_WININICHANGE:
-        fprintf( stderr, "CallWindowProc32To16: message %04x needs translation\n", msg );
-
-    default:  /* No translation needed */
-        return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, lParam );
     }
+    else
+#endif  /* WINELIB */
+        result = CallWndProc16( func, ds, hwnd, msg16, wParam16, lParam );
+    WINPROC_UnmapMsg32ATo16( msg16, wParam16, lParam );
+    return result;
 }
 
 
@@ -685,55 +1196,21 @@
  *
  * Call a 16-bit window procedure, translating the 32-bit args.
  */
-static LRESULT WINPROC_CallProc32WTo16( WNDPROC16 func, WORD ds, HWND32 hwnd,
+static LRESULT WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
                                         UINT32 msg, WPARAM32 wParam,
                                         LPARAM lParam )
 {
     LRESULT result;
+    UINT16 msg16;
+    WPARAM16 wParam16;
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
 
-    switch(msg)
-    {
-    case WM_GETTEXT:
-        {
-            LPSTR str;
-            wParam = MIN( wParam, 0xff80 );  /* Size must be < 64K */
-            if (!(str = SEGPTR_ALLOC( wParam ))) return 0;
-            result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                                    (LPARAM)SEGPTR_GET(str) );
-            if (result > 0) STRING32_AnsiToUni( (LPWSTR)lParam, str );
-            SEGPTR_FREE(str);
-        }
-        return result;
-
-    case WM_NCCREATE:
-    case WM_CREATE:
-        {
-            CREATESTRUCT32A cs = *(CREATESTRUCT32A *)lParam;
-            if (HIWORD(cs.lpszName))
-                cs.lpszName  = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName );
-            if (HIWORD(cs.lpszClass))
-                cs.lpszClass = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName );
-            result = WINPROC_CallProc32ATo16( func, ds, hwnd, msg, wParam,
-                                              (LPARAM)&cs );
-            if (HIWORD(cs.lpszName)) free( (LPVOID)cs.lpszName );
-            if (HIWORD(cs.lpszClass)) free( (LPVOID)cs.lpszClass );
-        }
-        return result;
-	
-    case WM_SETTEXT:
-        {
-            LPSTR str = SEGPTR_ALLOC( lstrlen32W( (LPWSTR)lParam ) );
-            if (!str) return 0;
-            STRING32_UniToAnsi( str, (LPWSTR)lParam );
-            result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
-                                    (LPARAM)SEGPTR_GET(str) );
-            SEGPTR_FREE(str);
-        }
-        return result;
-
-    default:  /* No Unicode translation needed */
-        return WINPROC_CallProc32ATo16( func, ds, hwnd, msg, wParam, lParam );
-    }
+    if (WINPROC_MapMsg32WTo16( msg, wParam, &msg16, &wParam16, &lParam ) == -1)
+        return 0;
+    result = CallWndProc16( func, wndPtr ? wndPtr->hInstance : CURRENT_DS,
+                            hwnd, msg16, wParam16, lParam );
+    WINPROC_UnmapMsg32WTo16( msg16, wParam16, lParam );
+    return result;
 }
 
 
@@ -744,29 +1221,38 @@
                           WPARAM16 wParam, LPARAM lParam )
 {
     WND *wndPtr;
-    WINDOWPROC *proc = WINPROC_GetPtr( (HANDLE32)func );
+    WINDOWPROC *proc = WINPROC_GetPtr( func );
 
     if (!proc)
     {
         wndPtr = WIN_FindWndPtr( hwnd );
-        return CallWndProc16( (FARPROC)func,
+        return CallWndProc16( (FARPROC16)func,
                               wndPtr ? wndPtr->hInstance : CURRENT_DS,
                               hwnd, msg, wParam, lParam );
     }
-
+#if testing
+    wndPtr = WIN_FindWndPtr( hwnd );
+    return CallWndProc16( WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16),
+                          wndPtr ? wndPtr->hInstance : CURRENT_DS,
+                          hwnd, msg, wParam, lParam );
+#endif
+    
     switch(proc->type)
     {
     case WIN_PROC_16:
+        if (!proc->thunk.t_from32.proc) return 0;
         wndPtr = WIN_FindWndPtr( hwnd );
-        return CallWndProc16( (FARPROC)proc->func,
+        return CallWndProc16( proc->thunk.t_from32.proc,
                               wndPtr ? wndPtr->hInstance : CURRENT_DS,
                               hwnd, msg, wParam, lParam );
     case WIN_PROC_32A:
-        return WINPROC_CallProc16To32A( (WNDPROC32)proc->func,
-                                        hwnd, msg, wParam, lParam );
+        if (!proc->thunk.t_from16.proc) return 0;
+        return WINPROC_CallProc16To32A( hwnd, msg, wParam, lParam,
+                                        proc->thunk.t_from16.proc );
     case WIN_PROC_32W:
-        return WINPROC_CallProc16To32W( (WNDPROC32)proc->func,
-                                        hwnd, msg, wParam, lParam );
+        if (!proc->thunk.t_from16.proc) return 0;
+        return WINPROC_CallProc16To32W( hwnd, msg, wParam, lParam,
+                                        proc->thunk.t_from16.proc );
     default:
         fprintf( stderr, "CallWindowProc16: invalid proc %p\n", proc );
         return 0;
@@ -780,23 +1266,28 @@
 LRESULT CallWindowProc32A( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
                            WPARAM32 wParam, LPARAM lParam )
 {
-    WND *wndPtr;
-    WINDOWPROC *proc = WINPROC_GetPtr( (HANDLE32)func );
+    WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
 
     if (!proc) return CallWndProc32( func, hwnd, msg, wParam, lParam );
 
+#if testing
+    func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
+    return CallWndProc32( func, hwnd, msg, wParam, lParam );
+#endif
+
     switch(proc->type)
     {
     case WIN_PROC_16:
-        wndPtr = WIN_FindWndPtr( hwnd );
-        return WINPROC_CallProc32ATo16( (FARPROC)proc->func,
-                                       wndPtr ? wndPtr->hInstance : CURRENT_DS,
-                                       hwnd, msg, wParam, lParam );
+        if (!proc->thunk.t_from32.proc) return 0;
+        return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
+                                        hwnd, msg, wParam, lParam );
     case WIN_PROC_32A:
-        return CallWndProc32( (WNDPROC32)proc->func,
+        if (!proc->thunk.t_from16.proc) return 0;
+        return CallWndProc32( proc->thunk.t_from16.proc,
                               hwnd, msg, wParam, lParam );
     case WIN_PROC_32W:
-        return WINPROC_CallProc32ATo32W( (WNDPROC32)proc->func,
+        if (!proc->thunk.t_from16.proc) return 0;
+        return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
                                          hwnd, msg, wParam, lParam );
     default:
         fprintf( stderr, "CallWindowProc32A: invalid proc %p\n", proc );
@@ -811,23 +1302,28 @@
 LRESULT CallWindowProc32W( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
                            WPARAM32 wParam, LPARAM lParam )
 {
-    WND *wndPtr;
-    WINDOWPROC *proc = WINPROC_GetPtr( (HANDLE32)func );
+    WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
 
     if (!proc) return CallWndProc32( func, hwnd, msg, wParam, lParam );
 
+#if testing
+    func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
+    return CallWndProc32( func, hwnd, msg, wParam, lParam );
+#endif
+
     switch(proc->type)
     {
     case WIN_PROC_16:
-        wndPtr = WIN_FindWndPtr( hwnd );
-        return WINPROC_CallProc32WTo16( (FARPROC)proc->func,
-                                       wndPtr ? wndPtr->hInstance : CURRENT_DS,
-                                       hwnd, msg, wParam, lParam );
+        if (!proc->thunk.t_from32.proc) return 0;
+        return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
+                                        hwnd, msg, wParam, lParam );
     case WIN_PROC_32A:
-        return WINPROC_CallProc32WTo32A( (WNDPROC32)proc->func,
+        if (!proc->thunk.t_from16.proc) return 0;
+        return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
                                          hwnd, msg, wParam, lParam );
     case WIN_PROC_32W:
-        return CallWndProc32( (WNDPROC32)proc->func,
+        if (!proc->thunk.t_from16.proc) return 0;
+        return CallWndProc32( proc->thunk.t_from16.proc,
                               hwnd, msg, wParam, lParam );
     default:
         fprintf( stderr, "CallWindowProc32W: invalid proc %p\n", proc );