Release 960824

Sat Aug 24 13:57:01 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/scroll.c]
	Renamed SCROLLINFO to SCROLLBAR_INFO to avoid conflict with Win32.

	* [graphics/driver.c] [include/x11drv.h]
	New files for graphics driver handling.

	* [if1632/relay.c] [include/registers.h] [tools/build.c]
	Implemented Win32 register functions. Not really tested yet.

	* [include/gdi.h]
	Added a lot of functions to the DC func table.

	* [loader/pe_image.c]
	Initialise %fs before calling out to 32-bit code.

	* [windows/hook.c]
	Fixed bug in HOOK_GetHook().

	* [windows/win.c]
	Fixed FindWindow to return an error if the class name doesn't exist.

Wed Aug 21 15:15:53 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [if1632/Makefile.in] [misc/mpr.c] [if1632/mpr.spec]
	mpr.dll specs added.

	* [if1632/kernel32.spec] [win32/newfns.c] [memory/global.c]
	QueryPerformanceCounter(), GlobalMemoryStatus() added.

	* [if1632/user32.spec] [win32/error.c]
	SetLastErrorEx() added.

	* [misc/commdlg.c]
	lpstrFilter might be NULL in FILE_WMInitDialog (NS 3.0 setup).

	* [misc/registry.c]
	Some missing NULL ptr checks added, misc clean up.

Tue Aug 20 21:00:00 1996 Alex Korobka  <alex@pharm.sunysb.edu>

	* [controls/menu.c]
	Adjust popup menu coordinates so that it always stays within 
	the desktop.

	* [misc/main.c]
	Fixed GetEnvironment() return value for lpEnv == NULL case.

Mon Aug 19 22:48:36 1996  Jukka Iivonen <iivonen@cc.helsinki.fi>

	* [misc/crtdll.c] [if1632/crtdll.spec]
	Added some is* functions, strlen and tolower.
	
Mon Aug 19 13:33:13 1996  Stephen Simmons  <ssimmons@vitsemi.com>

	* [tools/wineconf]
	New perl script to generate the wine.conf file.

Fri Aug 16 15:31:44 1996   John Harvey <john@division.co.uk>

	* [if1632/gdi.spec]
        Lots of printer functions.
	
	* [include/callback.h]
        New functions for printer driver support.

	* [include/gdi.h]
        New/changed structures to support printer driver.

	* [misc/escape.c]
        New version that uses function table in DC structure.

	* [objects/dc.c]
        CreateDC copes with things other than Display.
	X code for CreateDC moved to graphics/x11drv directory.
	CreateCompatibleDC copies func table from original DC.

	* [objects/font.c]
        GetTextExtentPoint32A,GetTextMetrics16 use function table in
        DC and code moved to drivers directory.

	* [misc/printdrv.c] [graphics/*/*] [include/win16drv.h]
        New files for printer support. 

Fri Aug 16 12:33:00 1996  Bruce Milner <Bruce.Milner@genetics.utah.edu>

	* [controls/scroll.c]
	Added SetScrollInfo32 and GetScrollInfo32.  These just call existing
	code. There are a few options in which I'm probably the wrong person
	for the job (page size and disable bar). There are comments in the
	code as to what they should do.

	* [objects/gdiobj.c] [objects/font.c] [include/font.h]
	Added 32 bit version of FONT_GetObject.
diff --git a/ANNOUNCE b/ANNOUNCE
index 22055cb..627612c 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,12 +1,13 @@
-This is release 960818 of Wine, the MS Windows emulator.  This is still a
+This is release 960824 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-960818: (see ChangeLog for details)
-	- Many repainting fixes.
+WHAT'S NEW with Wine-960824: (see ChangeLog for details)
+	- Very preliminary printer support.
+	- Perl script to generate wine.conf.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -15,10 +16,10 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-960818.tar.gz
-  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-960818.tar.gz
-  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-960818.tar.gz
-  ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-960818.tar.gz
+  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-960824.tar.gz
+  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-960824.tar.gz
+  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-960824.tar.gz
+  ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-960824.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index b379c5b..e30e7a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,101 @@
 ----------------------------------------------------------------------
+Sat Aug 24 13:57:01 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [controls/scroll.c]
+	Renamed SCROLLINFO to SCROLLBAR_INFO to avoid conflict with Win32.
+
+	* [graphics/driver.c] [include/x11drv.h]
+	New files for graphics driver handling.
+
+	* [if1632/relay.c] [include/registers.h] [tools/build.c]
+	Implemented Win32 register functions. Not really tested yet.
+
+	* [include/gdi.h]
+	Added a lot of functions to the DC func table.
+
+	* [loader/pe_image.c]
+	Initialise %fs before calling out to 32-bit code.
+
+	* [windows/hook.c]
+	Fixed bug in HOOK_GetHook().
+
+	* [windows/win.c]
+	Fixed FindWindow to return an error if the class name doesn't exist.
+
+Wed Aug 21 15:15:53 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [if1632/Makefile.in] [misc/mpr.c] [if1632/mpr.spec]
+	mpr.dll specs added.
+
+	* [if1632/kernel32.spec] [win32/newfns.c] [memory/global.c]
+	QueryPerformanceCounter(), GlobalMemoryStatus() added.
+
+	* [if1632/user32.spec] [win32/error.c]
+	SetLastErrorEx() added.
+
+	* [misc/commdlg.c]
+	lpstrFilter might be NULL in FILE_WMInitDialog (NS 3.0 setup).
+
+	* [misc/registry.c]
+	Some missing NULL ptr checks added, misc clean up.
+
+Tue Aug 20 21:00:00 1996 Alex Korobka  <alex@pharm.sunysb.edu>
+
+	* [controls/menu.c]
+	Adjust popup menu coordinates so that it always stays within 
+	the desktop.
+
+	* [misc/main.c]
+	Fixed GetEnvironment() return value for lpEnv == NULL case.
+
+Mon Aug 19 22:48:36 1996  Jukka Iivonen <iivonen@cc.helsinki.fi>
+
+	* [misc/crtdll.c] [if1632/crtdll.spec]
+	Added some is* functions, strlen and tolower.
+	
+Mon Aug 19 13:33:13 1996  Stephen Simmons  <ssimmons@vitsemi.com>
+
+	* [tools/wineconf]
+	New perl script to generate the wine.conf file.
+
+Fri Aug 16 15:31:44 1996   John Harvey <john@division.co.uk>
+
+	* [if1632/gdi.spec]
+        Lots of printer functions.
+	
+	* [include/callback.h]
+        New functions for printer driver support.
+
+	* [include/gdi.h]
+        New/changed structures to support printer driver.
+
+	* [misc/escape.c]
+        New version that uses function table in DC structure.
+
+	* [objects/dc.c]
+        CreateDC copes with things other than Display.
+	X code for CreateDC moved to graphics/x11drv directory.
+	CreateCompatibleDC copies func table from original DC.
+
+	* [objects/font.c]
+        GetTextExtentPoint32A,GetTextMetrics16 use function table in
+        DC and code moved to drivers directory.
+
+	* [misc/printdrv.c] [graphics/*/*] [include/win16drv.h]
+        New files for printer support. 
+
+Fri Aug 16 12:33:00 1996  Bruce Milner <Bruce.Milner@genetics.utah.edu>
+
+	* [controls/scroll.c]
+	Added SetScrollInfo32 and GetScrollInfo32.  These just call existing
+	code. There are a few options in which I'm probably the wrong person
+	for the job (page size and disable bar). There are comments in the
+	code as to what they should do.
+
+	* [objects/gdiobj.c] [objects/font.c] [include/font.h]
+	Added 32 bit version of FONT_GetObject.
+
+----------------------------------------------------------------------
 Sun Aug 18 12:17:54 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
 	* [files/drive.c]
@@ -596,7 +693,7 @@
 	Char* added.
 	CompareString* added.
 
-Sun Jul  7 01:22:14  Jukka Iivonen <iivonen@cc.helsinki.fi>
+Sun Jul  7 01:22:14 1996  Jukka Iivonen <iivonen@cc.helsinki.fi>
 
 	* [objects/font.c] [if1632/gdi32.spec]
 	CreateFontIndirect32A and CreateFontIndirect32W added.
diff --git a/Makefile.in b/Makefile.in
index c311424..a50864f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -46,6 +46,8 @@
 	rc \
 	controls \
 	files \
+	graphics \
+	graphics/x11drv \
 	ipc \
 	loader \
 	memory \
@@ -59,6 +61,7 @@
 EMUSUBDIRS = \
 	tools \
 	debugger \
+	graphics/win16drv \
 	if1632 \
 	miscemu
 
@@ -71,6 +74,8 @@
 COMMONOBJS = \
 	controls/controls.o \
 	files/files.o \
+	graphics/graphics.o \
+	graphics/x11drv/x11drv.o \
 	ipc/ipc.o \
 	loader/loader.o \
 	memory/memory.o \
@@ -83,6 +88,7 @@
 
 EMUOBJS = \
 	debugger/debugger.o \
+	graphics/win16drv/win16drv.o \
 	if1632/if1632.o \
 	miscemu/miscemu.o
 
diff --git a/configure b/configure
index 47cc41d..cc2ab47 100755
--- a/configure
+++ b/configure
@@ -2065,6 +2065,9 @@
 controls/Makefile
 debugger/Makefile
 files/Makefile
+graphics/Makefile
+graphics/win16drv/Makefile
+graphics/x11drv/Makefile
 if1632/Makefile
 ipc/Makefile
 library/Makefile
@@ -2140,6 +2143,9 @@
 controls/Makefile
 debugger/Makefile
 files/Makefile
+graphics/Makefile
+graphics/win16drv/Makefile
+graphics/x11drv/Makefile
 if1632/Makefile
 ipc/Makefile
 library/Makefile
diff --git a/configure.in b/configure.in
index d305a3b..0df6d51 100644
--- a/configure.in
+++ b/configure.in
@@ -103,6 +103,9 @@
 controls/Makefile
 debugger/Makefile
 files/Makefile
+graphics/Makefile
+graphics/win16drv/Makefile
+graphics/x11drv/Makefile
 if1632/Makefile
 ipc/Makefile
 library/Makefile
diff --git a/controls/menu.c b/controls/menu.c
index 7ac8c35..bc1a6ac 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -751,11 +751,13 @@
  *
  * Display a popup menu.
  */
-static BOOL MENU_ShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, int x, int y)
+static BOOL MENU_ShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, int x, int y, 
+						        int xanchor, int yanchor)
 {
     POPUPMENU 	*menu;
     WND 	*wndPtr = NULL;
     BOOL	 skip_init = 0;
+    UINT	 width, height;
 
     if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu ))) return FALSE;
     if (menu->FocusedItem != NO_SELECTED_ITEM)
@@ -767,6 +769,31 @@
 		 MAKELONG( id, (menu->wFlags & MF_SYSMENU) ? 1 : 0 ));
     MENU_PopupMenuCalcSize( menu, hwndOwner );
 
+    /* adjust popup menu pos so that it fits within the desktop */
+
+    width = menu->Width + 2*SYSMETRICS_CXBORDER;
+    height = menu->Height + 2*SYSMETRICS_CYBORDER; 
+
+    if( x + width > SYSMETRICS_CXSCREEN )
+    {
+	if( xanchor )
+            x -= width - xanchor;
+        if( x + width > SYSMETRICS_CXSCREEN)
+	    x = SYSMETRICS_CXSCREEN - width;
+    }
+    if( x < 0 )
+         x = 0;
+
+    if( y + height > SYSMETRICS_CYSCREEN )
+    { 
+	if( yanchor )
+	    y -= height + yanchor;
+	if( y + height > SYSMETRICS_CYSCREEN )
+	    y = SYSMETRICS_CYSCREEN - height;
+    }
+    if( y < 0 )
+	y = 0;
+
     wndPtr = WIN_FindWndPtr( hwndOwner );
     if (!wndPtr) return FALSE;
 
@@ -774,8 +801,7 @@
     {
 	pTopPWnd = WIN_FindWndPtr(CreateWindow16( POPUPMENU_CLASS_ATOM, NULL,
                                           WS_POPUP | WS_BORDER, x, y,
-                                          menu->Width + 2*SYSMETRICS_CXBORDER,
-                                          menu->Height + 2*SYSMETRICS_CYBORDER,
+                                          width, height,
                                           0, 0, wndPtr->hInstance,
                                           (LPVOID)(HMENU32)hmenu ));
 	if (!pTopPWnd) return FALSE;
@@ -787,8 +813,7 @@
 	/* create new window for the submenu */
 	HWND  hWnd = CreateWindow16( POPUPMENU_CLASS_ATOM, NULL,
                                    WS_POPUP | WS_BORDER, x, y,
-                                   menu->Width + 2*SYSMETRICS_CXBORDER,
-                                   menu->Height + 2*SYSMETRICS_CYBORDER,
+				   width, height,
                                    menu->hWnd, 0, wndPtr->hInstance,
                                    (LPVOID)(HMENU32)hmenu );
 	if( !hWnd ) return FALSE;
@@ -808,8 +833,7 @@
 
     wndPtr = WIN_FindWndPtr( menu->hWnd );
 
-    SetWindowPos(menu->hWnd, 0, x, y, menu->Width + 2*SYSMETRICS_CXBORDER, 
-				      menu->Height + 2*SYSMETRICS_CYBORDER,
+    SetWindowPos(menu->hWnd, 0, x, y, width, height,
 		  		      SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW);
       /* Display the window */
 
@@ -1164,7 +1188,8 @@
     if (menu->FocusedItem == SYSMENU_SELECTED)
     {
 	MENU_ShowPopup(hwndOwner, wndPtr->hSysMenu, 0, wndPtr->rectClient.left,
-		wndPtr->rectClient.top - menu->Height - 2*SYSMETRICS_CYBORDER);
+		wndPtr->rectClient.top - menu->Height - 2*SYSMETRICS_CYBORDER,
+		SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE );
 	if (selectFirst) MENU_SelectItemRel( hwndOwner, wndPtr->hSysMenu, ITEM_NEXT );
 	return wndPtr->hSysMenu;
     }
@@ -1176,13 +1201,16 @@
     {
 	MENU_ShowPopup( hwndOwner, (HMENU)item->item_id, menu->FocusedItem,
 		 wndPtr->rectWindow.left + item->rect.right-arrow_bitmap_width,
-		 wndPtr->rectWindow.top + item->rect.top );
+		 wndPtr->rectWindow.top + item->rect.top,
+		 item->rect.left - item->rect.right + 2*arrow_bitmap_width, 
+		 item->rect.top - item->rect.bottom );
     }
     else
     {
 	MENU_ShowPopup( hwndOwner, (HMENU)item->item_id, menu->FocusedItem,
 		        wndPtr->rectWindow.left + item->rect.left,
-		        wndPtr->rectWindow.top + item->rect.bottom );
+		        wndPtr->rectWindow.top + item->rect.bottom,
+			item->rect.right - item->rect.left, item->rect.bottom - item->rect.top );
     }
     if (selectFirst) MENU_SelectItemRel( hwndOwner, (HMENU)item->item_id, ITEM_NEXT );
     return (HMENU)item->item_id;
@@ -1451,7 +1479,8 @@
 	  else
 	  { 
 	     if( NC_GetSysPopupPos( wndPtr, &rect ) )
-	         MENU_ShowPopup( *hwndOwner, *hmenu, 0, rect.left, rect.bottom );
+	         MENU_ShowPopup( *hwndOwner, *hmenu, 0, rect.left, rect.bottom,
+		 SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE );
 
              if( !IsIconic( *hwndOwner ) )
              {
@@ -1837,7 +1866,7 @@
     BOOL ret = FALSE;
 
     HideCaret(0);
-    if (MENU_ShowPopup( hWnd, hMenu, 0, x, y )) 
+    if (MENU_ShowPopup( hWnd, hMenu, 0, x, y, 0, 0 )) 
 	ret = MENU_TrackMenu( hMenu, wFlags, 0, 0, hWnd, lpRect );
     ShowCaret(0);
     return ret;
diff --git a/controls/scroll.c b/controls/scroll.c
index c54421c..4bc72d6 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -97,22 +97,22 @@
 /***********************************************************************
  *           SCROLL_GetPtrScrollInfo
  */
-static SCROLLINFO *SCROLL_GetPtrScrollInfo( WND* wndPtr, int nBar )
+static SCROLLBAR_INFO *SCROLL_GetPtrScrollInfo( WND* wndPtr, int nBar )
 {
-    SCROLLINFO *infoPtr;
+    SCROLLBAR_INFO *infoPtr;
 
     if (!wndPtr) return NULL;
     switch(nBar)
     {
-        case SB_HORZ: infoPtr = (SCROLLINFO *)wndPtr->pHScroll; break;
-        case SB_VERT: infoPtr = (SCROLLINFO *)wndPtr->pVScroll; break;
-        case SB_CTL:  infoPtr = (SCROLLINFO *)wndPtr->wExtra; break;
+        case SB_HORZ: infoPtr = (SCROLLBAR_INFO *)wndPtr->pHScroll; break;
+        case SB_VERT: infoPtr = (SCROLLBAR_INFO *)wndPtr->pVScroll; break;
+        case SB_CTL:  infoPtr = (SCROLLBAR_INFO *)wndPtr->wExtra; break;
         default:      return NULL;
     }
 
     if (!infoPtr)  /* Create the info structure if needed */
     {
-        if ((infoPtr = HeapAlloc( SystemHeap, 0, sizeof(SCROLLINFO) )))
+        if ((infoPtr = HeapAlloc( SystemHeap, 0, sizeof(SCROLLBAR_INFO) )))
         {
             infoPtr->MinVal = infoPtr->CurVal = 0;
             infoPtr->MaxVal = 100;
@@ -129,7 +129,7 @@
 /***********************************************************************
  *           SCROLL_GetScrollInfo
  */
-static SCROLLINFO *SCROLL_GetScrollInfo( HWND hwnd, int nBar )
+static SCROLLBAR_INFO *SCROLL_GetScrollInfo( HWND hwnd, int nBar )
 {
    WND *wndPtr = WIN_FindWndPtr( hwnd );
    return SCROLL_GetPtrScrollInfo( wndPtr, nBar );
@@ -195,7 +195,7 @@
     
     if ((pixels -= 3*SYSMETRICS_CXVSCROLL+1) > 0)
     {
-        SCROLLINFO *info = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
+        SCROLLBAR_INFO *info = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
         if ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)
             *thumbPos = 0;
         else if (info->MinVal == info->MaxVal)
@@ -215,7 +215,7 @@
  * Compute the current scroll position based on the thumb position in pixels
  * from the top of the scroll-bar.
  */
-static UINT SCROLL_GetThumbVal( SCROLLINFO *infoPtr, RECT16 *rect,
+static UINT SCROLL_GetThumbVal( SCROLLBAR_INFO *infoPtr, RECT16 *rect,
                                 BOOL vertical, WORD pos )
 {
     int pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
@@ -274,7 +274,7 @@
  *
  * Draw the scroll bar arrows.
  */
-static void SCROLL_DrawArrows( HDC hdc, SCROLLINFO *infoPtr, RECT16 *rect,
+static void SCROLL_DrawArrows( HDC hdc, SCROLLBAR_INFO *infoPtr, RECT16 *rect,
                                WORD arrowSize, BOOL vertical,
                                BOOL top_pressed, BOOL bottom_pressed )
 {
@@ -451,7 +451,7 @@
     RECT16 rect;
     BOOL vertical;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
-    SCROLLINFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
+    SCROLLBAR_INFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
 
     if (!wndPtr || !infoPtr ||
         ((nBar == SB_VERT) && !(wndPtr->dwStyle & WS_VSCROLL)) ||
@@ -482,7 +482,7 @@
     BOOL vertical;
     HDC hdc;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
-    SCROLLINFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
+    SCROLLBAR_INFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
 
     if (!wndPtr || !infoPtr ||
         ((nBar == SB_VERT) && !(wndPtr->dwStyle & WS_VSCROLL)) ||
@@ -552,7 +552,7 @@
     RECT16 rect;
     HDC hdc;
 
-    SCROLLINFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar );
+    SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar );
     if (!infoPtr) return;
     if ((trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN)) return;
 
@@ -827,7 +827,7 @@
  */
 int SetScrollPos( HWND hwnd, int nBar, int nPos, BOOL bRedraw )
 {
-    SCROLLINFO *infoPtr;
+    SCROLLBAR_INFO *infoPtr;
     INT oldPos;
 
     if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0;
@@ -849,7 +849,7 @@
  */
 int GetScrollPos( HWND hwnd, int nBar )
 {
-    SCROLLINFO *infoPtr;
+    SCROLLBAR_INFO *infoPtr;
 
     if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0;
     return infoPtr->CurVal;
@@ -861,7 +861,7 @@
  */
 void SetScrollRange(HWND hwnd, int nBar, int MinVal, int MaxVal, BOOL bRedraw)
 {
-    SCROLLINFO *infoPtr;
+    SCROLLBAR_INFO *infoPtr;
 
     if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return;
 
@@ -889,7 +889,7 @@
 DWORD SCROLL_SetNCSbState(WND* wndPtr, int vMin, int vMax, int vPos,
 				       int hMin, int hMax, int hPos)
 {
-  SCROLLINFO  *infoPtr = SCROLL_GetPtrScrollInfo(wndPtr, SB_VERT);
+  SCROLLBAR_INFO  *infoPtr = SCROLL_GetPtrScrollInfo(wndPtr, SB_VERT);
  
   wndPtr->dwStyle |= (WS_VSCROLL | WS_HSCROLL);
 
@@ -919,7 +919,7 @@
  */
 void GetScrollRange(HWND hwnd, int nBar, LPINT16 lpMin, LPINT16 lpMax)
 {
-    SCROLLINFO *infoPtr;
+    SCROLLBAR_INFO *infoPtr;
 
     if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return;
     if (lpMin) *lpMin = infoPtr->MinVal;
@@ -997,7 +997,7 @@
  */
 BOOL EnableScrollBar( HWND hwnd, UINT nBar, UINT flags )
 {
-    SCROLLINFO *infoPtr;
+    SCROLLBAR_INFO *infoPtr;
     HDC hdc;
 
     if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE;
@@ -1012,3 +1012,59 @@
     ReleaseDC( hwnd, hdc );
     return TRUE;
 }
+
+
+/*************************************************************************
+ *           SetScrollInfo32   (USER32.500)
+ */
+INT32 SetScrollInfo32( HWND32 hwnd, INT32 nBar, LPSCROLLINFO32 lpsi,
+                       BOOL32 bRedraw )
+{
+    SCROLLBAR_INFO *infoPtr;
+
+    if (!(infoPtr = SCROLL_GetScrollInfo(hwnd, nBar))) return 0;
+
+    if (lpsi->fMask & SIF_PAGE) {
+	/* fixme: The page size isn't used in the current
+	 * scrolling code - it's new for win32
+	 */
+	infoPtr->Page = lpsi->nPage;
+    }
+    if (lpsi->fMask & SIF_POS)
+        SetScrollPos(hwnd, nBar, lpsi->nPos, FALSE);
+    if (lpsi->fMask & SIF_RANGE)
+        SetScrollRange(hwnd, nBar, lpsi->nMin, lpsi->nMax, FALSE);
+    if (lpsi->fMask & SIF_DISABLENOSCROLL) {
+	/* fixme: Disable scroll bar if the new parameters make
+	 * the scroll bar unneeded
+	 */
+	dprintf_scroll(stddeb, "SetScrollInfo: SIF_DISABLENOSCROLL not supported yet\n");
+    }
+
+    if (bRedraw) SCROLL_RefreshScrollBar(hwnd, nBar);
+
+    /* return current thumb position */
+    return (infoPtr->CurVal);
+}
+
+
+/*************************************************************************
+ *           GetScrollInfo32   (USER32.283)
+ */
+BOOL32 GetScrollInfo32( HWND32 hwnd, INT32 nBar, LPSCROLLINFO32 lpsi )
+{
+    SCROLLBAR_INFO *infoPtr;
+
+    if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE;
+
+    if (lpsi->fMask & SIF_PAGE) lpsi->nPage = infoPtr->Page;
+    if (lpsi->fMask & SIF_POS) lpsi->nPos = infoPtr->CurVal;
+    if (lpsi->fMask & SIF_TRACKPOS)
+        lpsi->nTrackPos = hwndTracking ? uTrackingPos : 0;
+    if (lpsi->fMask & SIF_RANGE)
+    {
+	lpsi->nMin = infoPtr->MinVal;
+	lpsi->nMax = infoPtr->MaxVal;
+    }
+    return TRUE;
+}
diff --git a/controls/widgets.c b/controls/widgets.c
index 236dfe3..7495665 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -30,7 +30,7 @@
     { CS_GLOBALCLASS | CS_PARENTDC,
        sizeof(STATICINFO), 0, "StaticWndProc", "STATIC" },
     { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
-      sizeof(SCROLLINFO), 0, "ScrollBarWndProc", "SCROLLBAR" },
+      sizeof(SCROLLBAR_INFO), 0, "ScrollBarWndProc", "SCROLLBAR" },
     { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
       8, 0, "ListBoxWndProc", "LISTBOX" },
     { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
diff --git a/graphics/Makefile.in b/graphics/Makefile.in
new file mode 100644
index 0000000..7049eca
--- /dev/null
+++ b/graphics/Makefile.in
@@ -0,0 +1,12 @@
+DEFS   = -D__WINE__ -DNO_TRANSITION_TYPES
+TOPSRC = @top_srcdir@
+MODULE = graphics
+
+C_SRCS = \
+	driver.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
diff --git a/graphics/driver.c b/graphics/driver.c
new file mode 100644
index 0000000..e26b2c3
--- /dev/null
+++ b/graphics/driver.c
@@ -0,0 +1,93 @@
+/*
+ * Graphics driver management functions
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <stdio.h>
+#include "gdi.h"
+#include "heap.h"
+
+typedef struct tagGRAPHICS_DRIVER
+{
+    struct tagGRAPHICS_DRIVER *next;
+    LPSTR                      name;
+    const DC_FUNCTIONS        *funcs;
+} GRAPHICS_DRIVER;
+
+static GRAPHICS_DRIVER *firstDriver = NULL;
+static GRAPHICS_DRIVER *genericDriver = NULL;
+
+/**********************************************************************
+ *	     DRIVER_RegisterDriver
+ */
+BOOL32 DRIVER_RegisterDriver( LPCSTR name, const DC_FUNCTIONS *funcs )
+{
+    GRAPHICS_DRIVER *driver = HeapAlloc( SystemHeap, 0, sizeof(*driver) );
+    if (!driver) return FALSE;
+    driver->funcs = funcs;
+    if (name)
+    {
+        driver->name  = HEAP_strdupA( SystemHeap, 0, name );
+        driver->next  = firstDriver;
+        firstDriver = driver;
+        return TRUE;
+    }
+    /* No name -> it's the generic driver */
+    if (genericDriver)
+    {
+        fprintf( stderr, "DRIVER_RegisterDriver: already a generic driver\n" );
+        HeapFree( SystemHeap, 0, driver );
+        return FALSE;
+    }
+    driver->name = NULL;
+    genericDriver = driver;
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	     DRIVER_FindDriver
+ */
+const DC_FUNCTIONS *DRIVER_FindDriver( LPCSTR name )
+{
+    GRAPHICS_DRIVER *driver = firstDriver;
+    while (driver)
+    {
+        if (!lstrcmpi32A( driver->name, name )) return driver->funcs;
+        driver = driver->next;
+    }
+    return genericDriver ? genericDriver->funcs : NULL;
+}
+
+
+/**********************************************************************
+ *	     DRIVER_UnregisterDriver
+ */
+BOOL32 DRIVER_UnregisterDriver( LPCSTR name )
+{
+    if (name)
+    {
+        GRAPHICS_DRIVER **ppDriver = &firstDriver;
+        while (*ppDriver)
+        {
+            if (!lstrcmpi32A( (*ppDriver)->name, name ))
+            {
+                GRAPHICS_DRIVER *driver = *ppDriver;
+                (*ppDriver) = driver->next;
+                HeapFree( SystemHeap, 0, driver->name );
+                HeapFree( SystemHeap, 0, driver );
+                return TRUE;
+            }
+            ppDriver = &(*ppDriver)->next;
+        }
+        return FALSE;
+    }
+    else
+    {
+        if (!genericDriver) return FALSE;
+        HeapFree( SystemHeap, 0, genericDriver );
+        genericDriver = NULL;
+        return TRUE;
+    }
+}
diff --git a/graphics/win16drv/Makefile.in b/graphics/win16drv/Makefile.in
new file mode 100644
index 0000000..119ab9d
--- /dev/null
+++ b/graphics/win16drv/Makefile.in
@@ -0,0 +1,13 @@
+DEFS   = -D__WINE__ -DNO_TRANSITION_TYPES
+TOPSRC = @top_srcdir@
+MODULE = win16drv
+
+C_SRCS = \
+	font.c \
+	init.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
diff --git a/graphics/win16drv/font.c b/graphics/win16drv/font.c
new file mode 100644
index 0000000..72f0c96
--- /dev/null
+++ b/graphics/win16drv/font.c
@@ -0,0 +1,72 @@
+/*
+ * Windows driver font functions
+ *
+ * Copyright 1996 John Harvey
+ */
+
+#include "windows.h"
+#include "win16drv.h"
+#include "gdi.h"
+
+
+/***********************************************************************
+ *           WIN16DRV_GetTextExtentPoint
+ */
+BOOL32 WIN16DRV_GetTextExtentPoint( DC *dc, LPCSTR str, INT32 count,
+                                    LPSIZE32 size )
+{
+    WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
+    
+    printf("LPGDI_GetTextExtPoint: %04x %s %d %p\n", dc->hSelf, str, count, size);
+
+	/* TTD support PS fonts */
+	/* Assume fixed font */
+    size->cx = count * physDev->tm.tmAveCharWidth;
+    size->cy = physDev->tm.tmHeight;
+    printf("LPGDI_GetTextExtPoint: cx=%d, cy=%d\n", size->cx,size->cy);
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           WIN16DRV_GetTextMetrics
+ */
+BOOL32 WIN16DRV_GetTextMetrics( DC *dc, TEXTMETRIC32A *metrics )
+{
+    WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
+
+    printf("LPGDI_GetTextMetrics: %04x \n", dc->hSelf);
+
+    metrics->tmHeight           = physDev->tm.tmHeight;
+    metrics->tmAscent           = physDev->tm.tmAscent;
+    metrics->tmDescent          = physDev->tm.tmDescent;
+    metrics->tmInternalLeading  = physDev->tm.tmInternalLeading;
+    metrics->tmExternalLeading  = physDev->tm.tmExternalLeading;
+    metrics->tmAveCharWidth     = physDev->tm.tmAveCharWidth;
+    metrics->tmMaxCharWidth     = physDev->tm.tmMaxCharWidth;
+    metrics->tmWeight           = physDev->tm.tmWeight;
+    metrics->tmOverhang         = physDev->tm.tmOverhang;
+    metrics->tmDigitizedAspectX = physDev->tm.tmDigitizedAspectX;
+    metrics->tmDigitizedAspectY = physDev->tm.tmDigitizedAspectY;
+    metrics->tmFirstChar        = physDev->tm.tmFirstChar;
+    metrics->tmLastChar         = physDev->tm.tmLastChar;
+    metrics->tmDefaultChar      = physDev->tm.tmDefaultChar;
+    metrics->tmBreakChar        = physDev->tm.tmBreakChar;
+    metrics->tmItalic           = physDev->tm.tmItalic;
+    metrics->tmUnderlined       = physDev->tm.tmUnderlined;
+    metrics->tmStruckOut        = physDev->tm.tmStruckOut;
+    metrics->tmPitchAndFamily   = physDev->tm.tmPitchAndFamily;
+    metrics->tmCharSet          = physDev->tm.tmCharSet;
+
+    printf("H %d, A %d, D %d, Int %d, Ext %d, AW %d, MW %d, W %d\n",
+           physDev->tm.tmHeight,
+           physDev->tm.tmAscent,
+           physDev->tm.tmDescent,
+           physDev->tm.tmInternalLeading,
+           physDev->tm.tmExternalLeading,
+           physDev->tm.tmAveCharWidth,
+           physDev->tm.tmMaxCharWidth,
+           physDev->tm.tmWeight);
+
+    return TRUE;
+}
diff --git a/graphics/win16drv/init.c b/graphics/win16drv/init.c
new file mode 100644
index 0000000..1a209e1
--- /dev/null
+++ b/graphics/win16drv/init.c
@@ -0,0 +1,1166 @@
+/*
+ * Windows Device Context initialisation functions
+ *
+ * Copyright 1996 John Harvey
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include "win16drv.h"
+#include "gdi.h"
+#include "bitmap.h"
+#include "heap.h"
+#include "color.h"
+#include "font.h"
+#include "callback.h"
+#include "stddebug.h"
+#include "debug.h"
+
+#define SUPPORT_REALIZED_FONTS 1 	
+typedef SEGPTR LPPDEVICE;
+
+
+#if 0
+static BOOL16 windrvExtTextOut16( DC *dc, INT16 x, INT16 y, UINT16 flags, const RECT16 * lprect,
+                                 LPCSTR str, UINT16 count, const INT16 *lpDx);
+#endif
+
+static BOOL32 WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
+                                 LPCSTR output, const DEVMODE* initData );
+static INT32 WIN16DRV_Escape( DC *dc, INT32 nEscape, INT32 cbInput, 
+                              SEGPTR lpInData, SEGPTR lpOutData );
+
+static const DC_FUNCTIONS WIN16DRV_Funcs =
+{
+    NULL,                            /* pArc */
+    NULL,                            /* pBitBlt */
+    NULL,                            /* pChord */
+    WIN16DRV_CreateDC,               /* pCreateDC */
+    NULL,                            /* pDeleteDC */
+    NULL,                            /* pDeleteObject */
+    NULL,                            /* pEllipse */
+    WIN16DRV_Escape,                 /* pEscape */
+    NULL,                            /* pExcludeClipRect */
+    NULL,                            /* pExcludeVisRect */
+    NULL,                            /* pExtFloodFill */
+    NULL,                            /* pExtTextOut */
+    NULL,                            /* pFillRgn */
+    NULL,                            /* pFloodFill */
+    NULL,                            /* pFrameRgn */
+    WIN16DRV_GetTextExtentPoint,     /* pGetTextExtentPoint */
+    WIN16DRV_GetTextMetrics,         /* pGetTextMetrics */
+    NULL,                            /* pIntersectClipRect */
+    NULL,                            /* pIntersectVisRect */
+    NULL,                            /* pInvertRgn */
+    NULL,                            /* pLineTo */
+    NULL,                            /* pMoveToEx */
+    NULL,                            /* pOffsetClipRgn */
+    NULL,                            /* pOffsetViewportOrgEx */
+    NULL,                            /* pOffsetWindowOrgEx */
+    NULL,                            /* pPaintRgn */
+    NULL,                            /* pPatBlt */
+    NULL,                            /* pPie */
+    NULL,                            /* pPolyPolygon */
+    NULL,                            /* pPolygon */
+    NULL,                            /* pPolyline */
+    NULL,                            /* pRealizePalette */
+    NULL,                            /* pRectangle */
+    NULL,                            /* pRestoreDC */
+    NULL,                            /* pRoundRect */
+    NULL,                            /* pSaveDC */
+    NULL,                            /* pScaleViewportExtEx */
+    NULL,                            /* pScaleWindowExtEx */
+    NULL,                            /* pSelectClipRgn */
+    NULL,                            /* pSelectObject */
+    NULL,                            /* pSelectPalette */
+    NULL,                            /* pSetBkColor */
+    NULL,                            /* pSetBkMode */
+    NULL,                            /* pSetDIBitsToDevice */
+    NULL,                            /* pSetMapMode */
+    NULL,                            /* pSetMapperFlags */
+    NULL,                            /* pSetPixel */
+    NULL,                            /* pSetPolyFillMode */
+    NULL,                            /* pSetROP2 */
+    NULL,                            /* pSetRelAbs */
+    NULL,                            /* pSetStretchBltMode */
+    NULL,                            /* pSetTextAlign */
+    NULL,                            /* pSetTextCharacterExtra */
+    NULL,                            /* pSetTextColor */
+    NULL,                            /* pSetTextJustification */
+    NULL,                            /* pSetViewportExtEx */
+    NULL,                            /* pSetViewportOrgEx */
+    NULL,                            /* pSetWindowExtEx */
+    NULL,                            /* pSetWindowOrgEx */
+    NULL,                            /* pStretchBlt */
+    NULL,                            /* pStretchDIBits */
+    NULL                             /* pTextOut */
+};
+
+
+#define MAX_PRINTER_DRIVERS 	16
+
+static LOADED_PRINTER_DRIVER *gapLoadedPrinterDrivers[MAX_PRINTER_DRIVERS];
+
+
+/**********************************************************************
+ *	     WIN16DRV_Init
+ */
+BOOL32 WIN16DRV_Init(void)
+{
+    return DRIVER_RegisterDriver( NULL /* generic driver */, &WIN16DRV_Funcs );
+}
+
+/* Tempory functions, for initialising structures */
+/* These values should be calculated, not hardcoded */
+void InitTextXForm(LPTEXTXFORM lpTextXForm)
+{
+    lpTextXForm->txfHeight 	= 0x0001;
+    lpTextXForm->txfWidth 	= 0x000c;
+    lpTextXForm->txfEscapement 	= 0x0000;
+    lpTextXForm->txfOrientation = 0x0000;
+    lpTextXForm->txfWeight 	= 0x0190;
+    lpTextXForm->txfItalic 	= 0x00;
+    lpTextXForm->txfUnderline 	= 0x00;
+    lpTextXForm->txfStrikeOut 	= 0x00; 
+    lpTextXForm->txfOutPrecision = 0x02;
+    lpTextXForm->txfClipPrecision = 0x01;
+    lpTextXForm->txfAccelerator = 0x0001;
+    lpTextXForm->txfOverhang 	= 0x0000;
+}
+
+
+void InitDrawMode(LPDRAWMODE lpDrawMode)
+{
+    lpDrawMode->Rop2		= 0x000d;       
+    lpDrawMode->bkMode		= 0x0001;     
+    lpDrawMode->bkColor		= 0x3fffffff;    
+    lpDrawMode->TextColor	= 0x20000000;  
+    lpDrawMode->TBreakExtra	= 0x0000;
+    lpDrawMode->BreakExtra	= 0x0000; 
+    lpDrawMode->BreakErr	= 0x0000;   
+    lpDrawMode->BreakRem	= 0x0000;   
+    lpDrawMode->BreakCount	= 0x0000; 
+    lpDrawMode->CharExtra	= 0x0000;  
+    lpDrawMode->LbkColor	= 0x00ffffff;   
+    lpDrawMode->LTextColor	= 0x00000000;     
+}
+/* 
+ * Thunking utility functions
+ */
+
+static BOOL32 AddData(SEGPTR *pSegPtr, void *pData, int nSize, SEGPTR Limit)
+{
+    BOOL32 bRet = FALSE;
+    char *pBuffer = PTR_SEG_TO_LIN((*pSegPtr));
+    char *pLimit = PTR_SEG_TO_LIN(Limit);
+
+
+    if ((pBuffer + nSize) < pLimit)
+    {
+	DWORD *pdw = (DWORD *)pSegPtr;
+	SEGPTR SegPtrOld = *pSegPtr;
+	SEGPTR SegPtrNew;
+
+	printf("AddData: Copying %d from %p to %p(0x%x)\n", nSize, pData, pBuffer, (UINT32)*pSegPtr);
+	memcpy(pBuffer, pData, nSize); 
+	SegPtrNew = (SegPtrOld + nSize + 1);
+	*pdw = (DWORD)SegPtrNew;
+    }
+    return bRet;
+}
+
+
+static BOOL32 GetParamData(SEGPTR SegPtrSrc,void *pDataDest, int nSize)
+{
+    char *pSrc =  PTR_SEG_TO_LIN(SegPtrSrc);
+    char *pDest = pDataDest;
+
+    printf("GetParamData: Copying %d from %lx(%lx) to %lx\n", nSize, (DWORD)pSrc, (DWORD)SegPtrSrc, (DWORD)pDataDest);
+    memcpy(pDest, pSrc, nSize);
+    return TRUE;
+}
+
+
+static void GetPrinterDriverFunctions(HINSTANCE16 hInst, LOADED_PRINTER_DRIVER *pLPD)
+{
+#define LoadPrinterDrvFunc(A,B) pLPD->fn[A] = \
+      GetProcAddress16(hInst, MAKEINTRESOURCE(B))
+
+      LoadPrinterDrvFunc(FUNC_CONTROL, ORD_CONTROL); 	       	/* 3 */
+      LoadPrinterDrvFunc(FUNC_ENABLE, ORD_ENABLE);		/* 5 */
+      LoadPrinterDrvFunc(FUNC_ENUMDFONTS, ORD_ENUMDFONTS);	/* 6 */
+      LoadPrinterDrvFunc(FUNC_REALIZEOBJECT, ORD_REALIZEOBJECT);/* 10 */
+      LoadPrinterDrvFunc(FUNC_EXTTEXTOUT, ORD_EXTTEXTOUT);	/* 14 */
+      printf ("got func CONTROL 0x%p enable 0x%p enumDfonts 0x%p realizeobject 0x%p extextout 0x%p\n",
+              pLPD->fn[FUNC_CONTROL],
+              pLPD->fn[FUNC_ENABLE],
+              pLPD->fn[FUNC_ENUMDFONTS],
+              pLPD->fn[FUNC_REALIZEOBJECT],
+              pLPD->fn[FUNC_EXTTEXTOUT]);
+      
+
+}
+
+static LOADED_PRINTER_DRIVER *FindPrinterDriverFromPDEVICE(SEGPTR segptrPDEVICE)
+{
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+
+    /* Find the printer driver associated with this PDEVICE */
+    /* Each of the PDEVICE structures has a PDEVICE_HEADER structure */
+    /* just before it */
+    if (segptrPDEVICE != (SEGPTR)NULL)
+    {
+	PDEVICE_HEADER *pPDH = (PDEVICE_HEADER *)
+	  (PTR_SEG_TO_LIN(segptrPDEVICE) - sizeof(PDEVICE_HEADER)); 
+        pLPD = pPDH->pLPD;
+    }
+    return pLPD;
+}
+
+static LOADED_PRINTER_DRIVER *FindPrinterDriverFromName(char *pszDriver)
+{
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+    int		nDriverSlot = 0;
+
+    /* Look to see if the printer driver is already loaded */
+    while (pLPD == NULL && nDriverSlot < MAX_PRINTER_DRIVERS)
+    {
+	LOADED_PRINTER_DRIVER *ptmpLPD;
+	ptmpLPD = gapLoadedPrinterDrivers[nDriverSlot++];
+	if (ptmpLPD != NULL)
+	{
+	    printf("Comparing %s,%s\n",ptmpLPD->szDriver,pszDriver);
+	    /* Found driver store info, exit loop */
+	    if (lstrcmpi32A(ptmpLPD->szDriver, pszDriver) == 0)
+	      pLPD = ptmpLPD;
+	}
+    }
+    if (pLPD == NULL) printf("Couldn't find driver %s\n", pszDriver);
+    return pLPD;
+}
+/* 
+ * Load a printer driver, adding it self to the list of loaded drivers.
+ */
+
+static LOADED_PRINTER_DRIVER *LoadPrinterDriver(const char *pszDriver)
+{                                        
+    HINSTANCE16	hInst;	
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+    int		nDriverSlot = 0;
+    BOOL32	bSlotFound = FALSE;
+
+    /* First look to see if driver is loaded */
+    pLPD = FindPrinterDriverFromName(pszDriver);
+    if (pLPD != NULL)
+    {
+	/* Already loaded so increase usage count */
+	pLPD->nUsageCount++;
+	return pLPD;
+    }
+
+    /* Not loaded so try and find an empty slot */
+    while (!bSlotFound && nDriverSlot < MAX_PRINTER_DRIVERS)
+    {
+	if (gapLoadedPrinterDrivers[nDriverSlot] == NULL)
+	  bSlotFound = TRUE;
+	else
+	  nDriverSlot++;
+    }
+    if (!bSlotFound)
+    {
+	printf("Too many printers drivers loaded\n");
+	return NULL;
+    }
+
+    {
+        char *drvName = malloc(strlen(pszDriver)+5);
+        strcpy(drvName, pszDriver);
+        strcat(drvName, ".DRV");
+        hInst = LoadLibrary(drvName);
+    }
+    printf("Loaded the library\n");
+
+    
+    if (hInst <= 32)
+    {
+	/* Failed to load driver */
+	fprintf(stderr, "Failed to load printer driver %s\n", pszDriver);
+    }
+    else
+    {
+	HANDLE16 hHandle;
+
+	/* Allocate some memory for printer driver info */
+	pLPD = malloc(sizeof(LOADED_PRINTER_DRIVER));
+	memset(pLPD, 0 , sizeof(LOADED_PRINTER_DRIVER));
+	
+	pLPD->hInst = hInst;
+	strcpy(pLPD->szDriver,pszDriver);
+
+	/* Get DS for the printer module */
+	pLPD->ds_reg = hInst;
+
+	printf("DS for %s is %x\n", pszDriver, pLPD->ds_reg);
+
+	/* Get address of printer driver functions */
+	GetPrinterDriverFunctions(hInst, pLPD);
+
+	/* Set initial usage count */
+	pLPD->nUsageCount = 1;
+
+	/* Create a thunking buffer */
+	hHandle = GlobalAlloc16(GHND, (1024 * 8));
+	pLPD->hThunk = hHandle;
+	pLPD->ThunkBufSegPtr = WIN16_GlobalLock16(hHandle);
+	pLPD->ThunkBufLimit = pLPD->ThunkBufSegPtr + (1024*8);
+
+	/* Update table of loaded printer drivers */
+	pLPD->nIndex = nDriverSlot;
+	gapLoadedPrinterDrivers[nDriverSlot] = pLPD;
+    }
+
+    return pLPD;
+}
+/*
+ *  Control (ordinal 3)
+ */
+INT16 PRTDRV_Control(LPPDEVICE lpDestDev, WORD wfunction, SEGPTR lpInData, SEGPTR lpOutData)
+{
+    /* wfunction == Escape code */
+    /* lpInData, lpOutData depend on code */
+
+    WORD wRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+
+    printf("PRTDRV_Control: %08x 0x%x %08lx %08lx\n", (unsigned int)lpDestDev, wfunction, lpInData, lpOutData);
+
+    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
+    {
+	LONG lP1, lP3, lP4;
+	WORD wP2;
+
+	if (pLPD->fn[FUNC_CONTROL] == NULL)
+	{
+	    printf("PRTDRV_Control: Not supported by driver\n");
+	    return 0;
+	}
+
+	lP1 = (SEGPTR)lpDestDev;
+	wP2 = wfunction;
+	lP3 = (SEGPTR)lpInData;
+	lP4 = (SEGPTR)lpOutData;
+
+	wRet = CallTo16_word_lwll(pLPD->fn[FUNC_CONTROL], 
+                                  lP1, wP2, lP3, lP4);
+    }
+    printf("PRTDRV_Control: return %x\n", wRet);
+    return wRet;
+
+    return 0;
+}
+
+/*
+ *	Enable (ordinal 5)
+ */
+static WORD PRTDRV_Enable(LPVOID lpDevInfo, WORD wStyle, LPCSTR  lpDestDevType, 
+                          LPCSTR lpDeviceName, LPCSTR lpOutputFile, LPVOID lpData)
+{
+    WORD wRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+
+    printf("PRTDRV_Enable: %s %s\n",lpDestDevType, lpOutputFile);
+
+    /* Get the printer driver info */
+    if (wStyle == INITPDEVICE)
+    {
+	pLPD = FindPrinterDriverFromPDEVICE((SEGPTR)lpDevInfo);
+    }
+    else
+    {
+	pLPD = FindPrinterDriverFromName((char *)lpDeviceName);
+    }
+    if (pLPD != NULL)
+    {
+	LONG lP1, lP3, lP4, lP5;
+	WORD wP2;
+	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
+	SEGPTR Limit = pLPD->ThunkBufLimit;
+	int   nSize;
+
+	if (pLPD->fn[FUNC_ENABLE] == NULL)
+	{
+	    printf("PRTDRV_Enable: Not supported by driver\n");
+	    return 0;
+	}
+
+	if (wStyle == INITPDEVICE)
+	{
+	    /* All ready a 16 address */
+	    lP1 = (SEGPTR)lpDevInfo;
+	}
+	else
+	{
+	    /* 32 bit data */
+	    lP1 = SegPtr;
+	    nSize = sizeof(DeviceCaps);
+	    AddData(&SegPtr, lpDevInfo, nSize, Limit);	
+	}
+	
+	wP2 = wStyle;
+	
+	lP3 = SegPtr;
+	nSize = strlen(lpDestDevType) + 1;
+	AddData(&SegPtr, lpDestDevType, nSize, Limit);	
+
+	lP4 = SegPtr; 
+	nSize = strlen(lpOutputFile) + 1;
+	AddData(&SegPtr, lpOutputFile, nSize, Limit);	
+
+	lP5 = (LONG)lpData;
+        
+
+	wRet = CallTo16_word_lwlll(pLPD->fn[FUNC_ENABLE], 
+				   lP1, wP2, lP3, lP4, lP5);
+
+	/* Get the data back */
+	if (lP1 != 0 && wStyle != INITPDEVICE)
+	{
+	    nSize = sizeof(DeviceCaps);
+	    GetParamData(lP1, lpDevInfo, nSize);
+	}
+    }
+    printf("PRTDRV_Enable: return %x\n", wRet);
+    return wRet;
+}
+
+
+/*
+ * EnumCallback (GDI.158)
+ * 
+ * This is the callback function used when EnumDFonts is called. 
+ * (The printer drivers uses it to pass info on available fonts).
+ *
+ * lpvClientData is the pointer passed to EnumDFonts, which points to a WEPFC
+ * structure (WEPFC = WINE_ENUM_PRINTER_FONT_CALLBACK).  This structure 
+ * contains infomation on how to store the data passed .
+ *
+ * There are two modes:
+ * 	1) Just count the number of fonts available.
+ * 	2) Store all font data passed.
+ */
+WORD WineEnumDFontCallback(LPLOGFONT16 lpLogFont, LPTEXTMETRIC16 lpTextMetrics, 
+			   WORD wFontType, LONG lpvClientData) 
+{
+    int wRet = 0;
+    WEPFC *pWEPFC = (WEPFC *)lpvClientData; 
+    
+    /* Make sure we have the right structure */
+    if (pWEPFC != NULL )
+    {
+        printf("mode is 0x%x\n",pWEPFC->nMode);
+        
+	switch (pWEPFC->nMode)
+	{
+	    /* Count how many fonts */
+	  case 1:
+	    pWEPFC->nCount++;
+	    break;
+
+	    /* Store the fonts in the printer driver structure */
+	  case 2:
+	  {
+	      PRINTER_FONTS_INFO *pPFI;
+                  
+	      printf("WineEnumDFontCallback: Found %s %x\n", 
+		     lpLogFont->lfFaceName, wFontType);
+	      
+	      pPFI = &pWEPFC->pLPD->paPrinterFonts[pWEPFC->nCount];
+	      memcpy(&(pPFI->lf), lpLogFont, sizeof(LOGFONT16));
+	      memcpy(&(pPFI->tm), lpTextMetrics, sizeof(TEXTMETRIC16));	      
+	      pWEPFC->nCount++;
+              
+	  }
+	    break;
+	}
+	wRet = 1;
+    }
+    printf("WineEnumDFontCallback: returnd %d\n", wRet);
+    return wRet;
+}
+
+/*
+ *	EnumDFonts (ordinal 6)
+ */
+WORD PRTDRV_EnumDFonts(LPPDEVICE lpDestDev, LPSTR lpFaceName,  
+		       FARPROC16 lpCallbackFunc, LPVOID lpClientData)
+{
+    WORD wRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+
+    printf("PRTDRV_EnumDFonts:\n");
+
+    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
+    {
+	LONG lP1, lP2, lP3, lP4;
+
+	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
+	SEGPTR Limit = pLPD->ThunkBufLimit;
+	int   nSize;
+
+	if (pLPD->fn[FUNC_ENUMDFONTS] == NULL)
+	{
+	    printf("PRTDRV_EnumDFonts: Not supported by driver\n");
+	    return 0;
+	}
+
+	lP1 = (SEGPTR)lpDestDev;
+	
+	if (lpFaceName == NULL)
+	{
+	    lP2 = 0;
+	}
+	else
+	{
+	    lP2 = SegPtr;
+	    nSize = strlen(lpFaceName) + 1;
+	    AddData(&SegPtr, lpFaceName, nSize, Limit);	
+	}
+
+	lP3 = (LONG)lpCallbackFunc; 
+
+	lP4 = (LONG)lpClientData;
+        
+	wRet = CallTo16_word_llll(pLPD->fn[FUNC_ENUMDFONTS], 
+                                  lP1, lP2, lP3, lP4);
+    }
+    else 
+        printf("Failed to find device\n");
+    
+    printf("PRTDRV_EnumDFonts: return %x\n", wRet);
+    return wRet;
+}
+
+/* 
+ * RealizeObject (ordinal 10)
+ */
+DWORD PRTDRV_RealizeObject(LPPDEVICE lpDestDev, WORD wStyle, 
+		    LPVOID lpInObj, LPVOID lpOutObj,
+                    LPTEXTXFORM lpTextXForm)
+{
+    WORD dwRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+    
+    printf("PRTDRV_RealizeObject:\n");
+    
+    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
+    {
+	LONG lP1, lP3, lP4, lP5;  
+	WORD wP2;
+	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
+	SEGPTR Limit = pLPD->ThunkBufLimit;
+	int   nSize;
+
+	if (pLPD->fn[FUNC_REALIZEOBJECT] == NULL)
+	{
+	    printf("PRTDRV_RealizeObject: Not supported by driver\n");
+	    return 0;
+	}
+
+	lP1 = lpDestDev;
+	wP2 = wStyle;
+	
+	lP3 = SegPtr;
+	switch (wStyle)
+	{
+        case 3: 
+            nSize = sizeof(LOGFONT16); 
+            break;
+        default:
+	    printf("PRTDRV_RealizeObject: Object type %d not supported\n", wStyle);
+            nSize = 0;
+            
+	}
+	AddData(&SegPtr, lpInObj, nSize, Limit);	
+	
+	lP4 = (LONG)lpOutObj;
+
+	if (lpTextXForm != NULL)
+	{
+	    lP5 = SegPtr;
+	    nSize = sizeof(TEXTXFORM);
+	    AddData(&SegPtr, lpTextXForm, nSize, Limit);	
+	}
+	else
+	  lP5 = 0L;
+
+	dwRet = CallTo16_long_lwlll(pLPD->fn[FUNC_REALIZEOBJECT], 
+                                    lP1, wP2, lP3, lP4, lP5);
+
+    }
+    printf("PRTDRV_RealizeObject: return %x\n", dwRet);
+    return dwRet;
+}
+
+
+BOOL32 WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device, LPCSTR output,
+                          const DEVMODE* initData )
+{
+    LOADED_PRINTER_DRIVER *pLPD;
+    WORD wRet;
+    DeviceCaps *printerDevCaps;
+    FARPROC16 pfnCallback;
+    int nPDEVICEsize;
+    PDEVICE_HEADER *pPDH;
+    WIN16DRV_PDEVICE *physDev;
+
+    /* Realizing fonts */
+    TEXTXFORM TextXForm;
+    int nSize;
+
+    printf("In creatdc for (%s,%s,%s) initData 0x%p\n",driver, device, output, initData);
+
+    physDev = (WIN16DRV_PDEVICE *)HeapAlloc( SystemHeap, 0, sizeof(*physDev) );
+    if (!physDev) return FALSE;
+    dc->physDev = physDev;
+
+    pLPD = LoadPrinterDriver(driver);
+    if (pLPD == NULL)
+    {
+	printf("LPGDI_CreateDC: Failed to find printer driver\n");
+        HeapFree( SystemHeap, 0, physDev );
+        return FALSE;
+    }
+    printf("windevCreateDC pLPD 0x%p\n", pLPD);
+
+    /* Now Get the device capabilities from the printer driver */
+    
+    printerDevCaps = (DeviceCaps *) malloc(sizeof(DeviceCaps));
+    memset(printerDevCaps, 0, sizeof(DeviceCaps));
+
+    /* Get GDIINFO which is the same as a DeviceCaps structure */
+    wRet = PRTDRV_Enable(printerDevCaps, GETGDIINFO, device, driver, output,NULL); 
+
+    /* Add this to the DC */
+    dc->w.devCaps = printerDevCaps;
+    
+    /* Now we allocate enough memory for the PDEVICE structure */
+    /* The size of this varies between printer drivers */
+    /* This PDEVICE is used by the printer DRIVER not by the GDI so must */
+    /* be accessable from 16 bit code */
+    nPDEVICEsize = dc->w.devCaps->pdeviceSize + sizeof(PDEVICE_HEADER);
+
+    /* TTD Shouldn't really do pointer arithmetic on segment points */
+    physDev->segptrPDEVICE = WIN16_GlobalLock16(GlobalAlloc16(GHND, nPDEVICEsize))+sizeof(PDEVICE_HEADER);
+    *(BYTE *)(PTR_SEG_TO_LIN(physDev->segptrPDEVICE)+0) = 'N'; 
+    *(BYTE *)(PTR_SEG_TO_LIN(physDev->segptrPDEVICE)+1) = 'B'; 
+
+    /* Set up the header */
+    pPDH = (PDEVICE_HEADER *)(PTR_SEG_TO_LIN(physDev->segptrPDEVICE) - sizeof(PDEVICE_HEADER)); 
+    pPDH->pLPD = pLPD;
+    
+    printf("PRTDRV_Enable: PDEVICE allocated %08lx\n",(DWORD)(physDev->segptrPDEVICE));
+    
+    /* Now get the printer driver to initialise this data */
+    wRet = PRTDRV_Enable((LPVOID)physDev->segptrPDEVICE, INITPDEVICE, device, driver, output, NULL); 
+
+    /* Now enumerate the fonts supported by the printer driver*/
+    /* GDI.158 is EnumCallback, which is called by the 16bit printer driver */
+    /* passing information on the available fonts */
+    if (pLPD->paPrinterFonts == NULL)
+    {
+	pfnCallback = GetProcAddress16(GetModuleHandle("GDI"), 
+				     (MAKEINTRESOURCE(158)));
+        
+	if (pfnCallback != NULL)
+	{
+	    WEPFC wepfc;
+	    
+	    wepfc.nMode = 1;
+	    wepfc.nCount = 0;
+	    wepfc.pLPD = pLPD;
+	    
+	    /* First count the number of fonts */
+            
+	    PRTDRV_EnumDFonts(physDev->segptrPDEVICE, NULL, pfnCallback, 
+			      (void *)&wepfc);
+	    
+	    /* Allocate a buffer to store all of the fonts */
+	    pLPD->nPrinterFonts = wepfc.nCount;
+            printf("Got %d fonts\n",wepfc.nCount);
+            
+	    if (wepfc.nCount > 0)
+	    {
+
+		pLPD->paPrinterFonts = malloc(sizeof(PRINTER_FONTS_INFO) * wepfc.nCount);
+		
+		/* Now get all of the fonts */
+		wepfc.nMode = 2;
+		wepfc.nCount = 0;
+		PRTDRV_EnumDFonts(physDev->segptrPDEVICE, NULL, pfnCallback, 
+				  (void *)&wepfc);
+	    }
+	}
+    }
+		
+    /* Select the first font into the DC */
+    /* Set up the logfont */
+    memcpy(&physDev->lf, 
+	   &pLPD->paPrinterFonts[0].lf, 
+	   sizeof(LOGFONT16));
+
+    /* Set up the textmetrics */
+    memcpy(&physDev->tm, 
+	   &pLPD->paPrinterFonts[0].tm, 
+	   sizeof(TEXTMETRIC16));
+
+#ifdef SUPPORT_REALIZED_FONTS
+    /* TTD should calculate this */
+    InitTextXForm(&TextXForm);
+    
+    /* First get the size of the realized font */
+    nSize = PRTDRV_RealizeObject(physDev->segptrPDEVICE, OBJ_FONT,
+				 &pLPD->paPrinterFonts[0], NULL, 
+				 NULL);
+    
+    physDev->segptrFontInfo = WIN16_GlobalLock16(GlobalAlloc16(GHND, nSize));
+    /* Realize the font */
+    PRTDRV_RealizeObject(physDev->segptrPDEVICE, OBJ_FONT,
+			 &pLPD->paPrinterFonts[0], 
+			 (LPVOID)physDev->segptrFontInfo, 
+			 &TextXForm);
+    /* Quick look at structure */
+    if (physDev->segptrFontInfo)
+    {  
+	FONTINFO *p = (FONTINFO *)PTR_SEG_TO_LIN(physDev->segptrFontInfo);
+
+	printf("T:%d VR:%d HR:%d, F:%d L:%d\n",
+	       p->dfType,
+	       p->dfVertRes, p->dfHorizRes,
+	       p->dfFirstCHAR, p->dfLastCHAR
+	       );
+    }
+
+#endif
+    /* TTD Lots more to do here */
+
+    return TRUE;
+}
+
+
+/* 
+ * Escape (GDI.38)
+ */
+static INT32 WIN16DRV_Escape( DC *dc, INT32 nEscape, INT32 cbInput, 
+                              SEGPTR lpInData, SEGPTR lpOutData )
+{
+    WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
+    int nRet = 0;
+
+    /* We should really process the nEscape parameter, but for now just
+       pass it all to the driver */
+    if (dc != NULL && physDev->segptrPDEVICE != 0)
+    {
+	switch(nEscape)
+	{
+	  case 0x9:
+	    printf("Escape: SetAbortProc ignored\n");
+	    break;
+
+	  default:
+	    nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape, 
+				  lpInData, lpOutData);
+	}
+    }
+    else
+	fprintf(stderr, "Escape(nEscape = %04x)\n", nEscape);      
+    return nRet;
+}
+
+DWORD PRTDRV_ExtTextOut(LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg,
+                        RECT16 *lpClipRect, LPCSTR lpString, WORD wCount, 
+                        SEGPTR lpFontInfo, LPDRAWMODE lpDrawMode, 
+                        LPTEXTXFORM lpTextXForm, SHORT *lpCharWidths,
+                        RECT16 *     lpOpaqueRect, WORD wOptions)
+{
+    DWORD dwRet = 0;
+    LOADED_PRINTER_DRIVER *pLPD = NULL;
+    
+    printf("PRTDRV_ExtTextOut:\n");
+    
+    if ((pLPD = FindPrinterDriverFromPDEVICE(lpDestDev)) != NULL)
+    {
+	LONG lP1, lP4, lP5, lP7, lP8, lP9, lP10, lP11;  
+	WORD wP2, wP3, wP6, wP12;
+	SEGPTR SegPtr = pLPD->ThunkBufSegPtr;
+	SEGPTR Limit = pLPD->ThunkBufLimit;
+	int   nSize;
+
+	if (pLPD->fn[FUNC_EXTTEXTOUT] == NULL)
+	{
+	    printf("PRTDRV_ExtTextOut: Not supported by driver\n");
+	    return 0;
+	}
+
+	lP1 = lpDestDev;
+	wP2 = wDestXOrg;
+	wP3 = wDestYOrg;
+	
+	if (lpClipRect != NULL)
+	{
+	    lP4 = SegPtr;
+	    nSize = sizeof(RECT16);
+            printf("Adding lpClipRect\n");
+            
+	    AddData(&SegPtr, lpClipRect, nSize, Limit);	
+	}
+	else
+	  lP4 = 0L;
+
+	if (lpString != NULL)
+	{
+	    /* TTD WARNING THIS STRING ISNT NULL TERMINATED */
+	    lP5 = SegPtr;
+	    nSize = strlen(lpString);
+            printf("Adding string size %d\n",nSize);
+            
+	    AddData(&SegPtr, lpString, nSize, Limit);	
+	}
+	else
+	  lP5 = 0L;
+	
+	wP6 = wCount;
+	
+	/* This should be realized by the driver, so in 16bit data area */
+	lP7 = lpFontInfo;
+	
+	if (lpDrawMode != NULL)
+	{
+	    lP8 = SegPtr;
+	    nSize = sizeof(DRAWMODE);
+            printf("adding lpDrawMode\n");
+            
+	    AddData(&SegPtr, lpDrawMode, nSize, Limit);	
+	}
+	else
+	  lP8 = 0L;
+	
+	if (lpTextXForm != NULL)
+	{
+	    lP9 = SegPtr;
+	    nSize = sizeof(TEXTXFORM);
+            printf("Adding TextXForm\n");
+	    AddData(&SegPtr, lpTextXForm, nSize, Limit);	
+	}
+	else
+	  lP9 = 0L;
+	
+	if (lpCharWidths != NULL) 
+	  printf("PRTDRV_ExtTextOut: Char widths not supported\n");
+	lP10 = 0;
+	
+	if (lpOpaqueRect != NULL)
+	{
+	    lP11 = SegPtr;
+	    nSize = sizeof(RECT16);
+            printf("Adding opaqueRect\n");
+	    AddData(&SegPtr, lpOpaqueRect, nSize, Limit);	
+	}
+	else
+	  lP11 = 0L;
+	
+	wP12 = wOptions;
+	printf("Calling exttextout 0x%lx 0x%x 0x%x 0x%lx\n0x%lx 0x%x 0x%lx 0x%lx\n"
+               "0x%lx 0x%lx 0x%lx 0x%x\n",lP1, wP2, wP3, lP4, 
+					   lP5, wP6, lP7, lP8, lP9, lP10,
+					   lP11, wP12);
+	dwRet = CallTo16_long_lwwllwlllllw(pLPD->fn[FUNC_EXTTEXTOUT], 
+                                           lP1, wP2, wP3, lP4, 
+					   lP5, wP6, lP7, lP8, lP9, lP10,
+					   lP11, wP12);
+    }
+    printf("PRTDRV_ExtTextOut: return %lx\n", dwRet);
+    return dwRet;
+}
+
+
+/*
+ * ExtTextOut (GDI.351)
+ */
+static BOOL16 windrvExtTextOut16( DC *dc, INT16 x, INT16 y, UINT16 flags, const RECT16 * lprect,
+                                 LPCSTR str, UINT16 count, const INT16 *lpDx)
+{
+    WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
+    BOOL32 bRet = 1;
+    DRAWMODE DrawMode;
+    LPDRAWMODE lpDrawMode = &DrawMode;
+    TEXTXFORM TextXForm;
+    LPTEXTXFORM lpTextXForm = &TextXForm;
+    RECT16 rcClipRect;
+    RECT16 * lpClipRect = &rcClipRect;
+    RECT16 rcOpaqueRect;
+    RECT16 *lpOpaqueRect = &rcOpaqueRect;
+    WORD wOptions = 0;
+    WORD wCount = count;
+
+    static BOOL32 bInit = FALSE;
+    
+
+
+    if (count == 0)
+      return FALSE;
+
+    printf("LPGDI_ExtTextOut: %04x %d %d %x %p %*s %p\n", dc->hSelf, x, y, 
+	   flags,  lprect, count > 0 ? count : 8, str, lpDx);
+
+    InitTextXForm(lpTextXForm);
+    InitDrawMode(lpDrawMode);
+
+    if (bInit == FALSE)
+    {
+	DWORD dwRet;
+
+	dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, 0, 0, 
+				  NULL, " ", 
+				  -1,  physDev->segptrFontInfo, lpDrawMode, 
+				  lpTextXForm, NULL, NULL, 0);
+	bInit = TRUE;
+    }
+
+    if (dc != NULL)   
+    {
+	DWORD dwRet;
+/*
+	dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, 0, 0, 
+				  NULL, "0", 
+				  -1,  physDev->segptrFontInfo, lpDrawMode, 
+				  lpTextXForm, NULL, NULL, 0);
+
+	dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, 0, 0, 
+				  NULL, str, -wCount,
+				  physDev->segptrFontInfo, lpDrawMode, 
+				  lpTextXForm, NULL, NULL, 0);
+*/
+	lpClipRect->left = 0;
+	lpClipRect->top = 0;
+	lpClipRect->right = 0x3fc;
+	lpClipRect->bottom = 0x42;
+	lpOpaqueRect->left = x;
+	lpOpaqueRect->top = y;
+	lpOpaqueRect->right = 0x3a1;
+	lpOpaqueRect->bottom = 0x01;
+/*
+	dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, x, y, 
+				  lpClipRect, str, 
+				  wCount,  physDev->segptrFontInfo, lpDrawMode, 
+				  lpTextXForm, lpDx, lpOpaqueRect, wOptions);
+*/
+	dwRet = PRTDRV_ExtTextOut(physDev->segptrPDEVICE, x, y, 
+				  NULL, str, 
+				  wCount,  physDev->segptrFontInfo, lpDrawMode, 
+				  lpTextXForm, NULL, NULL, wOptions);
+    }
+    return bRet;
+}
+
+/****************** misc. printer releated functions */
+
+/*
+ * The following function should implement a queing system
+ */
+#ifndef HPQ 
+#define HPQ WORD
+#endif
+HPQ CreatePQ(int size) { printf("CreatePQ: %d\n",size); return 1; }
+int DeletePQ(HPQ hPQ) { printf("DeletePQ: %x\n", hPQ); return 0; }
+int ExtractPQ(HPQ hPQ) { printf("ExtractPQ: %x\n", hPQ); return 0; }
+int InsertPQ(HPQ hPQ, int tag, int key) 
+{ printf("ExtractPQ: %x %d %d\n", hPQ, tag, key);  return 0; }
+int MinPQ(HPQ hPQ) { printf("MinPQ: %x\n", hPQ); return 0; }
+int SizePQ(HPQ hPQ, int sizechange) 
+{  printf("SizePQ: %x %d\n", hPQ, sizechange); return -1; }
+
+/* 
+ * The following functions implement part of the spooling process to 
+ * print manager.  I would like to see wine have a version of print managers
+ * that used LPR/LPD.  For simplicity print jobs will be sent to a file for
+ * now.
+ */
+typedef struct PRINTJOB
+{
+    char	*pszOutput;
+    char 	*pszTitle;
+    HDC16  	hDC;
+    HANDLE16 	hHandle;
+    int		nIndex;
+    int		fd;
+} PRINTJOB, *PPRINTJOB;
+
+#define MAX_PRINT_JOBS 1
+#define SP_ERROR -1
+#define SP_OUTOFDISK -4
+#define SP_OK 1
+
+PPRINTJOB gPrintJobsTable[MAX_PRINT_JOBS];
+
+
+static PPRINTJOB FindPrintJobFromHandle(HANDLE16 hHandle)
+{
+    return gPrintJobsTable[0];
+}
+
+/* TTD Need to do some DOS->UNIX file conversion here */
+static int CreateSpoolFile(LPSTR pszOutput)
+{
+    int fd;
+    char szSpoolFile[32];
+
+    /* TTD convert the 'output device' into a spool file name */
+
+    if (pszOutput == NULL || *pszOutput == '\0')
+	strcpy(szSpoolFile,"lp.out");
+    else
+	strcpy(szSpoolFile, pszOutput);
+
+    if ((fd = open(szSpoolFile, O_CREAT | O_TRUNC | O_WRONLY , 0600)) < 0)
+    {
+	printf("Failed to create spool file %s, errno = %d\n", szSpoolFile, errno);
+    }
+    return fd;
+}
+
+static int FreePrintJob(HANDLE16 hJob)
+{
+    int nRet = SP_ERROR;
+    PPRINTJOB pPrintJob;
+
+    pPrintJob = FindPrintJobFromHandle(hJob);
+    if (pPrintJob != NULL)
+    {
+	gPrintJobsTable[pPrintJob->nIndex] = NULL;
+	free(pPrintJob->pszOutput);
+	free(pPrintJob->pszTitle);
+	if (pPrintJob->fd >= 0) close(pPrintJob->fd);
+	free(pPrintJob);
+	nRet = SP_OK;
+    }
+    return nRet;
+}
+
+HANDLE16 OpenJob(LPSTR lpOutput, LPSTR lpTitle, HDC16 hDC)
+{
+    HANDLE16 hHandle = SP_ERROR;
+    PPRINTJOB pPrintJob;
+
+    printf("OpenJob: \"%s\" \"%s\" %04x\n", lpOutput, lpTitle, hDC);
+
+    pPrintJob = gPrintJobsTable[0];
+    if (pPrintJob == NULL)
+    {
+	int fd;
+
+	/* Try an create a spool file */
+	fd = CreateSpoolFile(lpOutput);
+	if (fd >= 0)
+	{
+	    hHandle = 1;
+
+	    pPrintJob = malloc(sizeof(PRINTJOB));
+	    memset(pPrintJob, 0, sizeof(PRINTJOB));
+
+	    pPrintJob->pszOutput = strdup(lpOutput);
+	    pPrintJob->pszTitle = strdup(lpTitle);
+	    pPrintJob->hDC = hDC;
+	    pPrintJob->fd = fd;
+	    pPrintJob->nIndex = 0;
+	    pPrintJob->hHandle = hHandle; 
+	    gPrintJobsTable[pPrintJob->nIndex] = pPrintJob; 
+	}
+    }
+    printf("OpenJob: return %04x\n", hHandle);
+    return hHandle;
+}
+
+int CloseJob(HANDLE16 hJob)
+{
+    int nRet = SP_ERROR;
+    PPRINTJOB pPrintJob = NULL;
+
+    printf("CloseJob: %04x\n", hJob);
+
+    pPrintJob = FindPrintJobFromHandle(hJob);
+    if (pPrintJob != NULL)
+    {
+	/* Close the spool file */
+	close(pPrintJob->fd);
+	FreePrintJob(hJob);
+	nRet  = 1;
+    }
+    return nRet;
+}
+
+int WriteSpool(HANDLE16 hJob, LPSTR lpData, WORD cch)
+{
+    int nRet = SP_ERROR;
+    PPRINTJOB pPrintJob = NULL;
+
+    printf("WriteSpool: %04x %08lx %04x\n", hJob, (DWORD)lpData, cch);
+
+    pPrintJob = FindPrintJobFromHandle(hJob);
+    if (pPrintJob != NULL && pPrintJob->fd >= 0 && cch)
+    {
+	if (write(pPrintJob->fd, lpData, cch) != cch)
+	  nRet = SP_OUTOFDISK;
+	else
+	  nRet = cch;
+    }
+    return nRet;
+}
+
+int WriteDialog(HANDLE16 hJob, LPSTR lpMsg, WORD cchMsg)
+{
+    int nRet = 0;
+
+    printf("WriteDialog: %04x %04x \"%s\"\n", hJob,  cchMsg, lpMsg);
+
+    nRet = MessageBox(NULL, lpMsg, "Printing Error", MB_OKCANCEL);
+    return nRet;
+}
+
+int DeleteJob(HANDLE16 hJob, WORD wNotUsed)
+{
+    int nRet;
+
+    printf("DeleteJob: %04x\n", hJob);
+
+    nRet = FreePrintJob(hJob);
+    return nRet;
+}
+
+/* 
+ * The following two function would allow a page to be sent to the printer
+ * when it has been processed.  For simplicity they havn't been implemented.
+ * This means a whole job has to be processed before it is sent to the printer.
+ */
+int StartSpoolPage(HANDLE16 hJob)
+{
+    printf("StartSpoolPage GDI.246 unimplemented\n");
+    return 1;
+
+}
+int EndSpoolPage(HANDLE16 hJob)
+{
+    printf("EndSpoolPage GDI.247 unimplemented\n");
+    return 1;
+}
+
+
+DWORD GetSpoolJob(int nOption, LONG param)
+{
+    DWORD retval = 0;
+    printf("In GetSpoolJob param 0x%lx noption %d\n",param, nOption);
+    return retval;
+}
diff --git a/graphics/x11drv/Makefile.in b/graphics/x11drv/Makefile.in
new file mode 100644
index 0000000..255c66e
--- /dev/null
+++ b/graphics/x11drv/Makefile.in
@@ -0,0 +1,13 @@
+DEFS   = -D__WINE__ -DNO_TRANSITION_TYPES
+TOPSRC = @top_srcdir@
+MODULE = x11drv
+
+C_SRCS = \
+	font.c \
+	init.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
diff --git a/graphics/x11drv/font.c b/graphics/x11drv/font.c
new file mode 100644
index 0000000..532d68c
--- /dev/null
+++ b/graphics/x11drv/font.c
@@ -0,0 +1,27 @@
+/*
+ * X11 driver font functions
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include "windows.h"
+#include "x11drv.h"
+#include "gdi.h"
+
+/***********************************************************************
+ *           X11DRV_GetTextExtentPoint
+ */
+BOOL32 X11DRV_GetTextExtentPoint( DC *dc, LPCSTR str, INT32 count,
+                                  LPSIZE32 size )
+{
+    int dir, ascent, descent;
+    XCharStruct info;
+
+    XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
+		  &ascent, &descent, &info );
+    size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
+		    * dc->w.WndExtX / dc->w.VportExtX);
+    size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
+		    * dc->w.WndExtY / dc->w.VportExtY);
+    return TRUE;
+}
diff --git a/graphics/x11drv/init.c b/graphics/x11drv/init.c
new file mode 100644
index 0000000..5933d73
--- /dev/null
+++ b/graphics/x11drv/init.c
@@ -0,0 +1,148 @@
+/*
+ * X11 graphics driver initialisation functions
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <string.h>
+#include "x11drv.h"
+#include "bitmap.h"
+#include "gdi.h"
+
+
+static BOOL32 X11DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
+                               LPCSTR output, const DEVMODE* initData );
+static BOOL32 X11DRV_DeleteDC( DC *dc );
+
+static const DC_FUNCTIONS X11DRV_Funcs =
+{
+    NULL,                            /* pArc */
+    NULL,                            /* pBitBlt */
+    NULL,                            /* pChord */
+    X11DRV_CreateDC,                 /* pCreateDC */
+    X11DRV_DeleteDC,                 /* pDeleteDC */
+    NULL,                            /* pDeleteObject */
+    NULL,                            /* pEllipse */
+    NULL,                            /* pEscape */
+    NULL,                            /* pExcludeClipRect */
+    NULL,                            /* pExcludeVisRect */
+    NULL,                            /* pExtFloodFill */
+    NULL,                            /* pExtTextOut */
+    NULL,                            /* pFillRgn */
+    NULL,                            /* pFloodFill */
+    NULL,                            /* pFrameRgn */
+    X11DRV_GetTextExtentPoint,       /* pGetTextExtentPoint */
+    NULL,                            /* pGetTextMetrics */
+    NULL,                            /* pIntersectClipRect */
+    NULL,                            /* pIntersectVisRect */
+    NULL,                            /* pInvertRgn */
+    NULL,                            /* pLineTo */
+    NULL,                            /* pMoveToEx */
+    NULL,                            /* pOffsetClipRgn */
+    NULL,                            /* pOffsetViewportOrgEx */
+    NULL,                            /* pOffsetWindowOrgEx */
+    NULL,                            /* pPaintRgn */
+    NULL,                            /* pPatBlt */
+    NULL,                            /* pPie */
+    NULL,                            /* pPolyPolygon */
+    NULL,                            /* pPolygon */
+    NULL,                            /* pPolyline */
+    NULL,                            /* pRealizePalette */
+    NULL,                            /* pRectangle */
+    NULL,                            /* pRestoreDC */
+    NULL,                            /* pRoundRect */
+    NULL,                            /* pSaveDC */
+    NULL,                            /* pScaleViewportExtEx */
+    NULL,                            /* pScaleWindowExtEx */
+    NULL,                            /* pSelectClipRgn */
+    NULL,                            /* pSelectObject */
+    NULL,                            /* pSelectPalette */
+    NULL,                            /* pSetBkColor */
+    NULL,                            /* pSetBkMode */
+    NULL,                            /* pSetDIBitsToDevice */
+    NULL,                            /* pSetMapMode */
+    NULL,                            /* pSetMapperFlags */
+    NULL,                            /* pSetPixel */
+    NULL,                            /* pSetPolyFillMode */
+    NULL,                            /* pSetROP2 */
+    NULL,                            /* pSetRelAbs */
+    NULL,                            /* pSetStretchBltMode */
+    NULL,                            /* pSetTextAlign */
+    NULL,                            /* pSetTextCharacterExtra */
+    NULL,                            /* pSetTextColor */
+    NULL,                            /* pSetTextJustification */
+    NULL,                            /* pSetViewportExtEx */
+    NULL,                            /* pSetViewportOrgEx */
+    NULL,                            /* pSetWindowExtEx */
+    NULL,                            /* pSetWindowOrgEx */
+    NULL,                            /* pStretchBlt */
+    NULL,                            /* pStretchDIBits */
+    NULL                             /* pTextOut */
+};
+
+static DeviceCaps X11DRV_DevCaps;
+
+/**********************************************************************
+ *	     X11DRV_Init
+ */
+BOOL32 X11DRV_Init(void)
+{
+    return DRIVER_RegisterDriver( "DISPLAY", &X11DRV_Funcs );
+}
+
+
+/**********************************************************************
+ *	     X11DRV_CreateDC
+ */
+static BOOL32 X11DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
+                               LPCSTR output, const DEVMODE* initData )
+{
+    X11DRV_PDEVICE *physDev;
+
+    if (!X11DRV_DevCaps.version) DC_FillDevCaps( &X11DRV_DevCaps );
+
+    physDev = &dc->u.x;  /* for now */
+
+    memset( physDev, 0, sizeof(*physDev) );
+    dc->physDev        = physDev;
+    dc->w.devCaps      = &X11DRV_DevCaps;
+    if (dc->w.flags & DC_MEMORY)
+    {
+        BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( dc->w.hBitmap,
+                                                      BITMAP_MAGIC );
+        physDev->drawable  = bmp->pixmap;
+        physDev->gc        = XCreateGC( display, physDev->drawable, 0, NULL );
+        dc->w.bitsPerPixel = bmp->bitmap.bmBitsPixel;
+        dc->w.hVisRgn      = CreateRectRgn( 0, 0, bmp->bitmap.bmWidth,
+                                            bmp->bitmap.bmHeight );
+    }
+    else
+    {
+        physDev->drawable  = rootWindow;
+        physDev->gc        = XCreateGC( display, physDev->drawable, 0, NULL );
+        dc->w.bitsPerPixel = screenDepth;
+        dc->w.hVisRgn      = CreateRectRgn( 0, 0, screenWidth, screenHeight );
+    }
+
+    if (!dc->w.hVisRgn)
+    {
+        XFreeGC( display, physDev->gc );
+        return FALSE;
+    }
+
+    XSetGraphicsExposures( display, physDev->gc, False );
+    XSetSubwindowMode( display, physDev->gc, IncludeInferiors );
+
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	     X11DRV_DeleteDC
+ */
+static BOOL32 X11DRV_DeleteDC( DC *dc )
+{
+    X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
+    XFreeGC( display, physDev->gc );
+    return TRUE;
+}
diff --git a/if1632/Makefile.in b/if1632/Makefile.in
index 5eb7110..6e2c87f 100644
--- a/if1632/Makefile.in
+++ b/if1632/Makefile.in
@@ -19,6 +19,7 @@
 	lzexpand.spec \
 	mmsystem.spec \
 	mouse.spec \
+	mpr.spec \
 	ntdll.spec	\
 	ole2.spec \
 	ole2conv.spec \
diff --git a/if1632/crtdll.spec b/if1632/crtdll.spec
index 0294041..733d405 100644
--- a/if1632/crtdll.spec
+++ b/if1632/crtdll.spec
@@ -396,17 +396,17 @@
 391 cdecl gets(ptr) CRTDLL_gets
 392 stub gmtime
 393 stub is_wctype
-394 stub isalnum
-395 stub isalpha
-396 stub iscntrl
-397 stub isdigit
-398 stub isgraph
+394 cdecl isalnum(long) CRTDLL_isalnum
+395 cdecl isalpha(long) CRTDLL_isalpha
+396 cdecl iscntrl(long) CRTDLL_iscntrl
+397 cdecl isdigit(long) CRTDLL_isdigit
+398 cdecl isgraph(long) CRTDLL_isgraph
 399 stub isleadbyte
-400 stub islower
-401 stub isprint
-402 stub ispunct
-403 stub isspace
-404 stub isupper
+400 cdecl islower(long) CRTDLL_islower
+401 cdecl isprint(long) CRTDLL_isprint
+402 cdecl ispunct(long) CRTDLL_ispunct
+403 cdecl isspace(long) CRTDLL_isspace
+404 cdecl isupper(long) CRTDLL_isupper
 405 stub iswalnum
 406 stub iswalpha
 407 stub iswascii
@@ -464,18 +464,18 @@
 459 stub sqrt
 460 cdecl srand(long) CRTDLL_srand
 461 stub sscanf
-462 stub strcat
+462 cdecl strcat(ptr ptr) lstrcat32A
 463 stub strchr
-464 stub strcmp
+464 cdecl strcmp(ptr ptr) lstrcmp32A
 465 stub strcoll
-466 stub strcpy
+466 cdecl strcpy(ptr ptr) lstrcpy32A
 467 stub strcspn
 468 stub strerror
 469 stub strftime
-470 stub strlen
-471 stub strncat
-472 stub strncmp
-473 stub strncpy
+470 cdecl strlen(ptr) lstrlen32A
+471 cdecl strncat(ptr ptr long) lstrcatn32A
+472 cdecl strncmp(ptr ptr long) lstrncmp32A
+473 cdecl strncpy(ptr ptr long) lstrcpyn32A
 474 stub strpbrk
 475 stub strrchr
 476 stub strspn
@@ -493,7 +493,7 @@
 488 cdecl time(ptr) CRTDLL_time
 489 stub tmpfile
 490 stub tmpnam
-491 stub tolower
+491 cdecl tolower(long) CRTDLL_tolower
 492 cdecl toupper(long) CRTDLL_toupper
 493 stub towlower
 494 stub towupper
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index cf39e6f..6ab8988 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -45,7 +45,7 @@
                         s_word s_word long) StretchBlt
 36  pascal16 Polygon (word ptr word) Polygon16
 37  pascal16 Polyline (word ptr word) Polyline16
-38  pascal Escape(word word word ptr ptr) Escape
+38  pascal Escape(word word word segptr segptr) Escape
 39  pascal16 RestoreDC(word s_word) RestoreDC
 40  pascal16 FillRgn(word word word) FillRgn
 41  pascal16 FrameRgn(word word word word word) FrameRgn
@@ -141,6 +141,7 @@
 154 pascal GetNearestColor(word long) GetNearestColor
 155 stub QueryAbort
 156 pascal16 CreateDiscardableBitmap(word word word) CreateDiscardableBitmap
+158 pascal16 EnumCallback(ptr ptr word long) WineEnumDFontCallback
 159 pascal16 GetMetaFileBits(word) GetMetaFileBits
 160 pascal16 SetMetaFileBits(word) SetMetaFileBits
 161 pascal16 PtInRegion(word s_word s_word) PtInRegion
@@ -180,20 +181,20 @@
 218 stub DMSTRETCHDIBITS
 219 stub DMSETDIBTODEV
 220 stub DMTRANSPOSE
-230 stub CREATEPQ
-231 stub MINPQ
-232 stub EXTRACTPQ
-233 stub INSERTPQ
-234 stub SIZEPQ
-235 stub DELETEPQ
-240 stub OPENJOB
-241 stub WRITESPOOL
-242 stub WRITEDIALOG
-243 stub CLOSEJOB
-244 stub DELETEJOB
-245 stub GetSpoolJob
-246 stub StartSpoolPage
-247 stub EndSpoolPage
+230 pascal16 CreatePQ(word) CreatePQ
+231 pascal16 MinPQ(word) MinPQ
+232 pascal16 ExtractPQ(word) ExtractPQ
+233 pascal16 InsertPQ(word word word) InsertPQ
+234 pascal16 SizePQ(word word) SizePQ
+235 pascal16 DeletePQ(word) DeletePQ
+240 pascal16 OpenJob(ptr ptr word) OpenJob
+241 pascal16 WriteSpool(word ptr word) WriteSpool
+242 pascal16 WriteDialog(word ptr word) WriteDialog
+243 pascal16 CloseJob(word) CloseJob
+244 pascal16 DeleteJob(word word) DeleteJob
+245 pascal GetSpoolJob(word ptr) GetSpoolJob
+246 pascal16 StartSpoolPage(word) StartSpoolPage
+247 pascal16 EndSpoolPage(word) EndSpoolPage
 248 stub QueryJob
 250 pascal16 Copy(ptr ptr word) Copy
 253 stub DeleteSpoolPage
@@ -206,8 +207,8 @@
 272 stub EndDocPrinter
 274 stub ClosePrinter
 280 stub GetRealDriverInfo
-281 stub DrvSetPrinterData
-282 stub DrvGetPrinterData
+281 pascal DrvSetPrinterData(ptr ptr ptr ptr long) DrvSetPrinterData
+282 pascal DrvGetPrinterData(ptr ptr ptr ptr long ptr) DrvGetPrinterData
 299 stub ENGINEGETCHARWIDTHEX
 300 stub ENGINEENUMERATEFONT
 301 stub ENGINEDELETEFONT
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index 95fc4a2..3cd982d 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -329,7 +329,7 @@
 0324 stdcall GlobalGetAtomNameW(long ptr long) GlobalGetAtomName32W
 0325 stdcall GlobalHandle(ptr) GlobalHandle32
 0326 stdcall GlobalLock(long) GlobalLock32
-0327 stub GlobalMemoryStatus
+0327 stdcall GlobalMemoryStatus(ptr) GlobalMemoryStatus
 0328 stdcall GlobalReAlloc(long long long) GlobalReAlloc32
 0329 stdcall GlobalSize(long) GlobalSize32
 0330 stub GlobalUnWire
@@ -417,7 +417,7 @@
 0412 stub PurgeComm
 0413 stub QueryDosDeviceA
 0414 stub QueryDosDeviceW
-0415 stub QueryPerformanceCounter
+0415 stdcall QueryPerformanceCounter(ptr) QueryPerformanceCounter
 0416 stub QueryPerformanceFrequency
 0417 stub QueryWin31IniFilesMappedToRegistry
 0418 stdcall RaiseException(long long long ptr) RaiseException
diff --git a/if1632/mpr.spec b/if1632/mpr.spec
new file mode 100644
index 0000000..f040dca
--- /dev/null
+++ b/if1632/mpr.spec
@@ -0,0 +1,83 @@
+name mpr
+type win32
+
+0009 stub DllCanUnloadNow
+0010 stub DllGetClassObject
+0025 stub MultinetGetConnectionPerformanceA
+0026 stub MultinetGetConnectionPerformanceW
+0027 stub MultinetGetErrorTextA
+0028 stub MultinetGetErrorTextW
+0029 stub NPSAuthenticationDialogA
+0030 stub NPSCopyStringA
+0031 stub NPSDeviceGetNumberA
+0032 stub NPSDeviceGetStringA
+0033 stub NPSGetProviderHandleA
+0034 stub NPSGetProviderNameA
+0035 stub NPSGetSectionNameA
+0036 stub NPSNotifyGetContextA
+0037 stub NPSNotifyRegisterA
+0038 stub NPSSetCustomTextA
+0039 stub NPSSetExtendedErrorA
+0040 stub PwdChangePasswordA
+0041 stub PwdChangePasswordW
+0042 stub PwdGetPasswordStatusA
+0043 stub PwdGetPasswordStatusW
+0044 stub PwdSetPasswordStatusA
+0045 stub PwdSetPasswordStatusW
+0046 stub WNetAddConnection2A
+0047 stub WNetAddConnection2W
+0048 stub WNetAddConnection3A
+0049 stub WNetAddConnection3W
+0050 stub WNetAddConnectionA
+0051 stub WNetAddConnectionW
+0052 stub WNetCachePassword
+0053 stub WNetCancelConnection2A
+0054 stub WNetCancelConnection2W
+0055 stub WNetCancelConnectionA
+0056 stub WNetCancelConnectionW
+0057 stub WNetCloseEnum
+0060 stub WNetConnectionDialog
+0058 stub WNetConnectionDialog1A
+0059 stub WNetConnectionDialog1W
+0063 stub WNetDisconnectDialog
+0061 stub WNetDisconnectDialog1A
+0062 stub WNetDisconnectDialog1W
+0064 stub WNetEnumCachedPasswords
+0065 stub WNetEnumResourceA
+0066 stub WNetEnumResourceW
+0067 stub WNetFormatNetworkNameA
+0068 stub WNetFormatNetworkNameW
+0069 stdcall WNetGetCachedPassword(ptr long ptr ptr long) WNetGetCachedPassword
+0070 stub WNetGetConnectionA
+0071 stub WNetGetConnectionW
+0072 stub WNetGetHomeDirectoryA
+0073 stub WNetGetHomeDirectoryW
+0074 stub WNetGetLastErrorA
+0075 stub WNetGetLastErrorW
+0076 stub WNetGetNetworkInformationA
+0077 stub WNetGetNetworkInformationW
+0078 stub WNetGetProviderNameA
+0079 stub WNetGetProviderNameW
+0080 stub WNetGetResourceInformationA
+0081 stub WNetGetResourceInformationW
+0082 stub WNetGetResourceParentA
+0083 stub WNetGetResourceParentW
+0084 stub WNetGetUniversalNameA
+0085 stub WNetGetUniversalNameW
+0086 stub WNetGetUserA
+0087 stub WNetGetUserW
+0088 stub WNetLogoffA
+0089 stub WNetLogoffW
+0090 stub WNetLogonA
+0091 stub WNetLogonW
+0092 stub WNetOpenEnumA
+0093 stub WNetOpenEnumW
+0094 stub WNetRemoveCachedPassword
+0095 stub WNetRestoreConnectionA
+0096 stub WNetRestoreConnectionW
+0097 stub WNetSetConnectionA
+0098 stub WNetSetConnectionW
+0099 stub WNetUseConnectionA
+0100 stub WNetUseConnectionW
+0101 stub WNetVerifyPasswordA
+0102 stub WNetVerifyPasswordW 
diff --git a/if1632/relay.c b/if1632/relay.c
index 614c419..ce0f4dd 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -212,32 +212,73 @@
 
 /***********************************************************************
  *           RELAY_DebugCallFrom32
+ *
+ * 'stack' points to the saved ebp on the stack.
+ * Stack layout:
+ *  ...        ...
+ * (stack+12)  arg2
+ * (stack+8)   arg1
+ * (stack+4)   ret addr
+ * (stack)     ebp
+ * (stack-4)   entry point
+ * (stack-8)   relay addr
  */
-void RELAY_DebugCallFrom32( int nb_args, void *relay_addr,
-                            void *entry_point, int ebp, int ret_addr, int arg1)
+void RELAY_DebugCallFrom32( int *stack, int nb_args )
 {
     int *parg;
 
     if (!debugging_relay) return;
-    printf( "Call %s(", BUILTIN_GetEntryPoint32( relay_addr ));
-    for (parg = &arg1; nb_args; parg++, nb_args--)
+    printf( "Call %s(", BUILTIN_GetEntryPoint32( (void *)stack[-2] ));
+    if (nb_args > 0)
     {
-        printf( "%08x", *parg );
-        if (nb_args > 1) printf( "," );
+        for (parg = &stack[2]; nb_args; parg++, nb_args--)
+        {
+            printf( "%08x", *parg );
+            if (nb_args > 1) printf( "," );
+        }
     }
-    printf( ") ret=%08x\n", ret_addr );
+    printf( ") ret=%08x\n", stack[1] );
+    if (nb_args == -1)  /* Register function */
+    {
+        CONTEXT *context = (CONTEXT *)((BYTE *)stack - sizeof(CONTEXT) - 12);
+        printf( " EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
+                context->Eax, context->Ebx, context->Ecx, context->Edx,
+                context->Esi, context->Edi );
+        printf( " EBP=%08lx ESP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
+                context->Ebp, context->Esp, context->SegDs, context->SegEs,
+                context->SegFs, context->SegGs, context->EFlags );
+    }
 }
 
 
 /***********************************************************************
  *           RELAY_DebugCallFrom32Ret
+ *
+ * 'stack' points to the saved ebp on the stack.
+ * Stack layout:
+ *  ...        ...
+ * (stack+12)  arg2
+ * (stack+8)   arg1
+ * (stack+4)   ret addr
+ * (stack)     ebp
+ * (stack-4)   entry point
+ * (stack-8)   relay addr
  */
-void RELAY_DebugCallFrom32Ret( int ret_val, void *relay_addr,
-                               void *entry_point, int ebp, int ret_addr )
+void RELAY_DebugCallFrom32Ret( int *stack, int nb_args, int ret_val )
 {
     if (!debugging_relay) return;
-    printf( "Ret  %s() retval=0x%08x ret=%08x\n",
-            BUILTIN_GetEntryPoint32( relay_addr ), ret_val, ret_addr );
+    printf( "Ret  %s() retval=%08x ret=%08x\n",
+            BUILTIN_GetEntryPoint32( (void *)stack[-2] ), ret_val, stack[1] );
+    if (nb_args == -1)  /* Register function */
+    {
+        CONTEXT *context = (CONTEXT *)((BYTE *)stack - sizeof(CONTEXT) - 12);
+        printf( " EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
+                context->Eax, context->Ebx, context->Ecx, context->Edx,
+                context->Esi, context->Edi );
+        printf( " EBP=%08lx ESP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
+                context->Ebp, context->Esp, context->SegDs, context->SegEs,
+                context->SegFs, context->SegGs, context->EFlags );
+    }
 }
 
 
diff --git a/if1632/user32.spec b/if1632/user32.spec
index 02325ff..faff16a 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -287,7 +287,7 @@
 0280 stdcall GetPropA(long ptr) GetProp32A
 0281 stdcall GetPropW(long ptr) GetProp32W
 0282 stub GetQueueStatus
-0283 stub GetScrollInfo
+0283 stdcall GetScrollInfo(long long ptr) GetScrollInfo32
 0284 stub GetScrollPos
 0285 stub GetScrollRange
 0286 stub GetShellWindow
@@ -488,7 +488,7 @@
 0481 stub SetForegroundWindow
 0482 stdcall SetInternalWindowPos(long long ptr ptr) SetInternalWindowPos32
 0483 stub SetKeyboardState
-0484 stub SetLastErrorEx
+0484 stdcall SetLastErrorEx(long long) SetLastErrorEx
 0485 stub SetLogonNotifyWindow
 0486 stdcall SetMenu(long long) SetMenu
 0487 stub SetMenuContextHelpId
@@ -504,7 +504,7 @@
 0497 stdcall SetPropW(long ptr long) SetProp32W
 0498 stdcall SetRect(ptr long long long long) SetRect32
 0499 stdcall SetRectEmpty(ptr) SetRectEmpty32
-0500 stub SetScrollInfo
+0500 stdcall SetScrollInfo(long long ptr long) SetScrollInfo32
 0501 stdcall SetScrollPos(long long long long) SetScrollPos
 0502 stdcall SetScrollRange(long long long long long) SetScrollRange
 0503 stub SetShellWindow
diff --git a/include/bitmap.h b/include/bitmap.h
index 7528707..45cbad7 100644
--- a/include/bitmap.h
+++ b/include/bitmap.h
@@ -36,12 +36,12 @@
 }
 
   /* objects/bitmap.c */
-extern BOOL BITMAP_Init(void);
+extern BOOL32 BITMAP_Init(void);
 extern INT16 BITMAP_GetObject16( BITMAPOBJ * bmp, INT16 count, LPVOID buffer );
 extern INT32 BITMAP_GetObject32( BITMAPOBJ * bmp, INT32 count, LPVOID buffer );
-extern BOOL BITMAP_DeleteObject( HBITMAP hbitmap, BITMAPOBJ * bitmap );
-extern HBITMAP BITMAP_SelectObject( DC * dc, HBITMAP hbitmap,
-                                    BITMAPOBJ * bmp );
+extern BOOL32 BITMAP_DeleteObject( HBITMAP16 hbitmap, BITMAPOBJ * bitmap );
+extern HBITMAP16 BITMAP_SelectObject( DC * dc, HBITMAP16 hbitmap,
+                                      BITMAPOBJ * bmp );
 
   /* objects/dib.c */
 extern int DIB_GetImageWidthBytes( int width, int depth );
diff --git a/include/brush.h b/include/brush.h
index d1836b3..a7c02f6 100644
--- a/include/brush.h
+++ b/include/brush.h
@@ -9,17 +9,13 @@
 
 #include "gdi.h"
 
-#pragma pack(1)
-
   /* GDI logical brush object */
 typedef struct
 {
     GDIOBJHDR   header;
-    LOGBRUSH16  logbrush WINE_PACKED;
+    LOGBRUSH16  logbrush;
 } BRUSHOBJ;
 
-#pragma pack(4)
-
 extern BOOL BRUSH_Init(void);
 extern int BRUSH_GetObject( BRUSHOBJ * brush, int count, LPSTR buffer );
 extern BOOL BRUSH_DeleteObject( HBRUSH hbrush, BRUSHOBJ * brush );
diff --git a/include/callback.h b/include/callback.h
index 5921cad..dfd37e9 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -39,6 +39,14 @@
 extern LONG CallTo16_long_lllllllwlwwwl( FARPROC16, LONG, LONG, LONG,
                                          LONG, LONG, LONG, LONG, WORD, LONG,
                                          WORD, WORD, WORD, LONG );
+extern WORD CallTo16_word_lwll ( FARPROC16, LONG, WORD, LONG, LONG);
+extern WORD CallTo16_word_lwlll( FARPROC16, LONG, WORD, LONG, LONG, LONG );
+extern WORD CallTo16_word_llll ( FARPROC16, LONG, LONG, LONG, LONG);
+extern LONG CallTo16_long_lwlll( FARPROC16, LONG, WORD, LONG, LONG, LONG );
+extern LONG CallTo16_long_lwwllwlllllw( FARPROC16, LONG, WORD, WORD, LONG, 
+				       LONG, WORD, LONG, LONG, LONG, LONG, 
+				       LONG, WORD);
+
 
 extern WORD CallTo16_regs_( FARPROC16 func, WORD ds, WORD es, WORD bp, WORD ax,
                             WORD bx, WORD cx, WORD dx, WORD si, WORD di );
diff --git a/include/color.h b/include/color.h
index 7cc07e9..cd42b82 100644
--- a/include/color.h
+++ b/include/color.h
@@ -16,14 +16,14 @@
 extern HPALETTE16 	COLOR_Init(void);
 extern COLORREF		COLOR_ToLogical(int pixel);
 extern int 		COLOR_ToPhysical( DC *dc, COLORREF color );
-extern int 		COLOR_SetMapping( PALETTEOBJ* pal, BOOL mapOnly );
-extern BOOL 		COLOR_IsSolid( COLORREF color );
+extern int 		COLOR_SetMapping( PALETTEOBJ* pal, BOOL32 mapOnly );
+extern BOOL32 		COLOR_IsSolid( COLORREF color );
 extern Colormap		COLOR_GetColormap();
 extern UINT16		COLOR_GetSystemPaletteSize();
 extern UINT16		COLOR_GetSystemPaletteFlags();
 
 extern COLORREF		COLOR_LookupNearestColor( PALETTEENTRY*, int, COLORREF );
-extern int		COLOR_PaletteLookupPixel( PALETTEENTRY*, int, int* , COLORREF, BOOL );
+extern int		COLOR_PaletteLookupPixel( PALETTEENTRY*, int, int* , COLORREF, BOOL32 );
 
 extern int 	COLOR_mapEGAPixel[16];
 extern int* 	COLOR_PaletteToPixel;
diff --git a/include/except.h b/include/except.h
index ee93e3e..582a695 100644
--- a/include/except.h
+++ b/include/except.h
@@ -6,8 +6,8 @@
 #ifndef __WINE_EXCEPT_H
 #define __WINE_EXCEPT_H
 
-#include"wintypes.h"
-
+#include "wintypes.h"
+#include "registers.h"
 /*
  * exception codes
  */
@@ -88,59 +88,6 @@
 #define EXCEPTION_CONTINUABLE        0
 #define EXCEPTION_NONCONTINUABLE     EH_NONCONTINUABLE
  
-/* 
- * data types
- */
-
-/*
- * The i386 context used by Win32 for almost everything. 
- */
-  
-#define SIZE_OF_80387_REGISTERS      80
-
-typedef struct _FLOATING_SAVE_AREA
-{
-    DWORD   ControlWord;
-    DWORD   StatusWord;
-    DWORD   TagWord;    
-    DWORD   ErrorOffset;
-    DWORD   ErrorSelector;
-    DWORD   DataOffset;
-    DWORD   DataSelector;    
-    BYTE    RegisterArea[SIZE_OF_80387_REGISTERS];
-    DWORD   Cr0NpxState;
-} FLOATING_SAVE_AREA;
-
-typedef struct __CONTEXT
-{
-    DWORD   ContextFlags;
-    DWORD   Dr0;
-    DWORD   Dr1;    
-    DWORD   Dr2;    
-    DWORD   Dr3;
-    DWORD   Dr6;
-    DWORD   Dr7;    
-    FLOATING_SAVE_AREA FloatSave;
-    DWORD   SegGs;
-    DWORD   SegFs;
-    DWORD   SegEs;
-    DWORD   SegDs;    
-    DWORD   Edi;
-    DWORD   Esi;
-    DWORD   Ebx;
-    DWORD   Edx;    
-    DWORD   Ecx;
-    DWORD   Eax;
-    DWORD   Ebp;    
-    DWORD   Eip;
-    DWORD   SegCs;
-    DWORD   EFlags;
-    DWORD   Esp;
-    DWORD   SegSs;
-} CONTEXT;
-
-typedef struct __CONTEXT *PCONTEXT;
-
 /*
  * The exception record used by Win32 to give additional information 
  * about exception to exception handlers.
diff --git a/include/font.h b/include/font.h
index f282a0d..641d029 100644
--- a/include/font.h
+++ b/include/font.h
@@ -25,8 +25,8 @@
 #define GGO_NATIVE	0x4F50
 typedef struct
 {
-	UINT	gmBlackBoxX;
-	UINT	gmBlackBoxY;
+	UINT16	gmBlackBoxX;
+	UINT16	gmBlackBoxY;
 	POINT16	gmptGlyphOrigin;
 	int	gmCellIncX;
 	int	gmCellIncY;
@@ -40,8 +40,9 @@
 } MAT2,*LPMAT2;
 
 
-extern BOOL FONT_Init( void );
-extern int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer );
-extern HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font );
+extern BOOL32 FONT_Init( void );
+extern INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer );
+extern INT32 FONT_GetObject32A( FONTOBJ * font, INT32 count, LPSTR buffer );
+extern HFONT16 FONT_SelectObject( DC * dc, HFONT16 hfont, FONTOBJ * font );
 
 #endif /* __WINE_FONT_H */
diff --git a/include/gdi.h b/include/gdi.h
index 86b68e9..cd68ba3 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -7,12 +7,10 @@
 #ifndef GDI_H
 #define GDI_H
 
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
 #include "windows.h"
 #include "ldt.h"
 #include "local.h"
+#include "x11drv.h"
 
   /* GDI objects magic numbers */
 #define PEN_MAGIC             0x4f47
@@ -33,7 +31,6 @@
     HANDLE16    hNext;
     WORD        wMagic;
     DWORD       dwCount;
-    WORD        wMetaList;
 } GDIOBJHDR;
 
 
@@ -71,11 +68,12 @@
     WORD   colorRes;      /* 108: color resolution */    
 } DeviceCaps;
 
+
   /* Device independent DC information */
 typedef struct
 {
     int           flags;
-    DeviceCaps   *devCaps;
+    const DeviceCaps *devCaps;
 
     HANDLE16      hMetaFile;
     HRGN16        hClipRgn;     /* Clip region (may be 0) */
@@ -125,52 +123,19 @@
     short         VportExtY;
 } WIN_DC_INFO;
 
-
-  /* X physical pen */
-typedef struct
-{
-    int          style;
-    int          pixel;
-    int          width;
-    char *       dashes;
-    int          dash_len;
-} X_PHYSPEN;
-
-  /* X physical brush */
-typedef struct
-{
-    int          style;
-    int          fillStyle;
-    int          pixel;
-    Pixmap       pixmap;
-} X_PHYSBRUSH;
-
-  /* X physical font */
-typedef struct
-{
-    XFontStruct * fstruct;
-    TEXTMETRIC16  metrics;
-} X_PHYSFONT;
-
-  /* X-specific DC information */
-typedef struct
-{
-    GC            gc;          /* X Window GC */
-    Drawable      drawable;
-    X_PHYSFONT    font;
-    X_PHYSPEN     pen;
-    X_PHYSBRUSH   brush;
-} X_DC_INFO;
-
+typedef X11DRV_PDEVICE X_DC_INFO;  /* Temporary */
 
 typedef struct tagDC
 {
-    GDIOBJHDR     header;
-    WORD          saveLevel;
-    DWORD         dwHookData;
-    FARPROC16     hookProc;
-    HDC16         hSelf;
-    WIN_DC_INFO   w;
+    GDIOBJHDR      header;
+    HDC16          hSelf;            /* Handle to this DC */
+    const struct tagDC_FUNCS *funcs; /* DC function table */
+    void          *physDev;          /* Physical device (driver-specific) */
+    WORD           saveLevel;
+    DWORD          dwHookData;
+    FARPROC16      hookProc;
+
+    WIN_DC_INFO w;
     union
     {
 	X_DC_INFO x;
@@ -178,6 +143,73 @@
     } u;
 } DC;
 
+/* Device functions for the Wine driver interface */
+typedef struct tagDC_FUNCS
+{
+    BOOL32     (*pArc)(DC*,INT32,INT32,INT32,INT32,INT32,INT32,INT32,INT32);
+    BOOL32     (*pBitBlt)(DC*,INT32,INT32,INT32,INT32,DC*,INT32,INT32,DWORD);
+    BOOL32     (*pChord)(DC*,INT32,INT32,INT32,INT32,INT32,INT32,INT32,INT32);
+    BOOL32     (*pCreateDC)(DC*,LPCSTR,LPCSTR,LPCSTR,const DEVMODE*);
+    BOOL32     (*pDeleteDC)(DC*);
+    BOOL32     (*pDeleteObject)(HGDIOBJ16);
+    BOOL32     (*pEllipse)(DC*,INT32,INT32,INT32,INT32);
+    INT32      (*pEscape)(DC*,INT32,INT32,SEGPTR,SEGPTR);
+    INT32      (*pExcludeClipRect)(DC*,INT32,INT32,INT32,INT32);
+    INT32      (*pExcludeVisRect)(DC*,INT32,INT32,INT32,INT32);
+    BOOL32     (*pExtFloodFill)(DC*,INT32,INT32,COLORREF,UINT32);
+    BOOL32     (*pExtTextOut)(DC*,INT32,INT32,UINT32,const RECT32*,LPCSTR,UINT32,const INT32*);
+    BOOL32     (*pFillRgn)(DC*,HRGN32,HBRUSH32);
+    BOOL32     (*pFloodFill)(DC*,INT32,INT32,COLORREF);
+    BOOL32     (*pFrameRgn)(DC*,HRGN32,HBRUSH32,INT32,INT32);
+    BOOL32     (*pGetTextExtentPoint)(DC*,LPCSTR,INT32,LPSIZE32);
+    BOOL32     (*pGetTextMetrics)(DC*,TEXTMETRIC32A*);
+    INT32      (*pIntersectClipRect)(DC*,INT32,INT32,INT32,INT32);
+    INT32      (*pIntersectVisRect)(DC*,INT32,INT32,INT32,INT32);
+    BOOL32     (*pInvertRgn)(DC*,HRGN32);
+    BOOL32     (*pLineTo)(DC*,INT32,INT32);
+    BOOL32     (*pMoveToEx)(DC*,INT32,INT32,LPPOINT32);
+    INT32      (*pOffsetClipRgn)(DC*,INT32,INT32);
+    BOOL32     (*pOffsetViewportOrgEx)(DC*,INT32,INT32,LPPOINT32);
+    BOOL32     (*pOffsetWindowOrgEx)(DC*,INT32,INT32,LPPOINT32);
+    BOOL32     (*pPaintRgn)(DC*,HRGN32);
+    BOOL32     (*pPatBlt)(DC*,INT32,INT32,INT32,INT32,DWORD);
+    BOOL32     (*pPie)(DC*,INT32,INT32,INT32,INT32,INT32,INT32,INT32,INT32);
+    BOOL32     (*pPolyPolygon)(DC*,LPPOINT32,LPINT32,UINT32);
+    BOOL32     (*pPolygon)(DC*,LPPOINT32,INT32);
+    BOOL32     (*pPolyline)(DC*,LPPOINT32,INT32);
+    UINT32     (*pRealizePalette)(DC*);
+    BOOL32     (*pRectangle)(DC*,INT32,INT32,INT32,INT32);
+    BOOL32     (*pRestoreDC)(DC*,INT32);
+    BOOL32     (*pRoundRect)(DC*,INT32,INT32,INT32,INT32,INT32,INT32);
+    INT32      (*pSaveDC)(DC*);
+    BOOL32     (*pScaleViewportExtEx)(DC*,INT32,INT32,INT32,INT32,LPSIZE32);
+    BOOL32     (*pScaleWindowExtEx)(DC*,INT32,INT32,INT32,INT32,LPSIZE32);
+    INT32      (*pSelectClipRgn)(DC*,HRGN32);
+    HANDLE32   (*pSelectObject)(DC*,HANDLE32);
+    HPALETTE32 (*pSelectPalette)(DC*,HPALETTE32,BOOL32);
+    COLORREF   (*pSetBkColor)(DC*,COLORREF);
+    WORD       (*pSetBkMode)(DC*,WORD);
+    INT32      (*pSetDIBitsToDevice)(DC*,INT32,INT32,DWORD,DWORD,INT32,INT32,UINT32,UINT32,LPCVOID,const BITMAPINFO*,UINT32);
+    WORD       (*pSetMapMode)(DC*,WORD);
+    DWORD      (*pSetMapperFlags)(DC*,DWORD);
+    COLORREF   (*pSetPixel)(DC*,INT32,INT32,COLORREF);
+    WORD       (*pSetPolyFillMode)(DC*,WORD);
+    WORD       (*pSetROP2)(DC*,WORD);
+    WORD       (*pSetRelAbs)(DC*,WORD);
+    WORD       (*pSetStretchBltMode)(DC*,WORD);
+    WORD       (*pSetTextAlign)(DC*,WORD);
+    INT32      (*pSetTextCharacterExtra)(DC*,INT32);
+    DWORD      (*pSetTextColor)(DC*,DWORD);
+    INT32      (*pSetTextJustification)(DC*,INT32,INT32);
+    BOOL32     (*pSetViewportExtEx)(DC*,INT32,INT32,LPSIZE32);
+    BOOL32     (*pSetViewportOrgEx)(DC*,INT32,INT32,LPPOINT32);
+    BOOL32     (*pSetWindowExtEx)(DC*,INT32,INT32,LPSIZE32);
+    BOOL32     (*pSetWindowOrgEx)(DC*,INT32,INT32,LPPOINT32);
+    BOOL32     (*pStretchBlt)(DC*,INT32,INT32,INT32,INT32,DC*,INT32,INT32,INT32,INT32,DWORD);
+    INT32      (*pStretchDIBits)(DC*,INT32,INT32,INT32,INT32,INT32,INT32,INT32,INT32,LPSTR,LPBITMAPINFO,WORD,DWORD);
+    BOOL32     (*pTextOut)(DC*,INT32,INT32,LPCSTR,INT32);
+} DC_FUNCTIONS;
+
   /* DC hook codes */
 #define DCHC_INVALIDVISRGN      0x0001
 #define DCHC_DELETEDC           0x0002
@@ -257,6 +289,10 @@
 extern GDIOBJHDR * GDI_GetObjPtr( HANDLE16, WORD );
 extern FARPROC16 GDI_GetDefDCHook(void);
 
+extern BOOL32 DRIVER_RegisterDriver( LPCSTR name, const DC_FUNCTIONS *funcs );
+extern const DC_FUNCTIONS *DRIVER_FindDriver( LPCSTR name );
+extern BOOL32 DRIVER_UnregisterDriver( LPCSTR name );
+
 extern Display * display;
 extern Screen * screen;
 extern Window rootWindow;
diff --git a/include/palette.h b/include/palette.h
index 1bdef2f..7729f93 100644
--- a/include/palette.h
+++ b/include/palette.h
@@ -9,20 +9,16 @@
 
 #include "gdi.h"
 
-#pragma pack(1)
-
   /* GDI logical palette object */
 typedef struct
 {
     GDIOBJHDR   header;
-    int        *mapping    WINE_PACKED; 
-    LOGPALETTE  logpalette WINE_PACKED; /* _MUST_ be the last field */
+    int        *mapping;
+    LOGPALETTE  logpalette; /* _MUST_ be the last field */
 } PALETTEOBJ;
 
-#pragma pack(4)
-
 extern int PALETTE_GetObject( PALETTEOBJ * palette, int count, LPSTR buffer );
-extern BOOL PALETTE_DeleteObject( HPALETTE16 hpalette, PALETTEOBJ *palette );
-extern BOOL PALETTE_UnrealizeObject( HPALETTE16 hpalette, PALETTEOBJ *palette);
+extern BOOL32 PALETTE_DeleteObject( HPALETTE16 hpalette, PALETTEOBJ *palette );
+extern BOOL32 PALETTE_UnrealizeObject( HPALETTE16 hpalette, PALETTEOBJ *palette);
      
 #endif /* __WINE_PALETTE_H */
diff --git a/include/pen.h b/include/pen.h
index d9c8ff9..0a43406 100644
--- a/include/pen.h
+++ b/include/pen.h
@@ -9,17 +9,13 @@
 
 #include "gdi.h"
 
-#pragma pack(1)
-
   /* GDI logical pen object */
 typedef struct
 {
     GDIOBJHDR   header;
-    LOGPEN16    logpen WINE_PACKED;
+    LOGPEN16    logpen;
 } PENOBJ;
 
-#pragma pack(4)
-
 extern int PEN_GetObject( PENOBJ * pen, int count, LPSTR buffer );
 extern HPEN16 PEN_SelectObject( DC * dc, HPEN16 hpen, PENOBJ * pen );
 
diff --git a/include/registers.h b/include/registers.h
index 490861d..6c93955 100644
--- a/include/registers.h
+++ b/include/registers.h
@@ -9,6 +9,70 @@
 
 #include "wintypes.h"
 
+/* The Win32 register context */
+
+#define CONTEXT_i386      0x00010000
+#define CONTEXT_i486      CONTEXT_i386
+#define CONTEXT_CONTROL   (CONTEXT_i386 | 0x0001) /* SS:SP, CS:IP, FLAGS, BP */
+#define CONTEXT_INTEGER   (CONTEXT_i386 | 0x0002) /* AX, BX, CX, DX, SI, DI */
+#define CONTEXT_SEGMENTS  (CONTEXT_i386 | 0x0004) /* DS, ES, FS, GS */
+#define CONTEXT_FLOATING_POINT  (CONTEXT_i386 | 0x0008L) /* 387 state */
+#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x0010L) /* DB 0-3,6,7 */
+#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)
+
+#define SIZE_OF_80387_REGISTERS      80
+
+typedef struct
+{
+    DWORD   ControlWord;
+    DWORD   StatusWord;
+    DWORD   TagWord;    
+    DWORD   ErrorOffset;
+    DWORD   ErrorSelector;
+    DWORD   DataOffset;
+    DWORD   DataSelector;    
+    BYTE    RegisterArea[SIZE_OF_80387_REGISTERS];
+    DWORD   Cr0NpxState;
+} FLOATING_SAVE_AREA;
+
+typedef struct
+{
+    DWORD   ContextFlags;
+
+    /* These are selected by CONTEXT_DEBUG_REGISTERS */
+    DWORD   Dr0;
+    DWORD   Dr1;
+    DWORD   Dr2;
+    DWORD   Dr3;
+    DWORD   Dr6;
+    DWORD   Dr7;
+
+    /* These are selected by CONTEXT_FLOATING_POINT */
+    FLOATING_SAVE_AREA FloatSave;
+
+    /* These are selected by CONTEXT_SEGMENTS */
+    DWORD   SegGs;
+    DWORD   SegFs;
+    DWORD   SegEs;
+    DWORD   SegDs;    
+
+    /* These are selected by CONTEXT_INTEGER */
+    DWORD   Edi;
+    DWORD   Esi;
+    DWORD   Ebx;
+    DWORD   Edx;    
+    DWORD   Ecx;
+    DWORD   Eax;
+
+    /* These are selected by CONTEXT_CONTROL */
+    DWORD   Ebp;    
+    DWORD   Eip;
+    DWORD   SegCs;
+    DWORD   EFlags;
+    DWORD   Esp;
+    DWORD   SegSs;
+} CONTEXT, *PCONTEXT;
+
 #ifndef WINELIB
 
 #ifdef i386
diff --git a/include/scroll.h b/include/scroll.h
index 8445a97..92d590f 100644
--- a/include/scroll.h
+++ b/include/scroll.h
@@ -15,9 +15,9 @@
     INT   CurVal;   /* Current scroll-bar value */
     INT   MinVal;   /* Minimum scroll-bar value */
     INT   MaxVal;   /* Maximum scroll-bar value */
-    WORD  unused;   /* Unused word, for MS-Windows compatibility */
+    INT   Page;     /* Page size of scroll bar (Win32) */
     WORD  flags;    /* EnableScrollBar flags */
-} SCROLLINFO;
+} SCROLLBAR_INFO;
 
 extern LONG ScrollBarWndProc( HWND hwnd, WORD uMsg, WORD wParam, LONG lParam );
 extern void SCROLL_DrawScrollBar( HWND hwnd, HDC hdc, int nBar );
diff --git a/include/win16drv.h b/include/win16drv.h
new file mode 100644
index 0000000..6ee48af
--- /dev/null
+++ b/include/win16drv.h
@@ -0,0 +1,214 @@
+/*
+ * Win16 printer driver definitions
+ */
+
+#ifndef __WINE_WIN16DRV_H
+#define __WINE_WIN16DRV_H
+
+#include "windows.h"
+#include "gdi.h"
+
+#define SETHIGHBIT 
+#undef SETHIGHBIT
+#ifdef SETHIGHBIT
+#define GETGDIINFO  0x8001
+#define INITPDEVICE 0x8000
+#else
+#define GETGDIINFO  0x0001
+#define INITPDEVICE 0x0000
+#endif
+
+/* Internal Data */
+#define ORD_BITBLT		1
+#define ORD_COLORINFO		2		
+#define ORD_CONTROL		3
+#define ORD_DISABLE		4
+#define ORD_ENABLE		5
+#define ORD_ENUMDFONTS		6
+#define ORD_ENUMOBJ		7
+#define ORD_OUTPUT		8
+#define ORD_PIXEL		9	
+#define ORD_REALIZEOBJECT	10
+#define ORD_STRBLT		11
+#define ORD_SCANLR		12
+#define ORD_DEVICEMODE		13
+#define ORD_EXTTEXTOUT		14
+#define ORD_GETCHARWIDTH	15
+#define ORD_DEVICEBITMAP	16
+#define ORD_FASTBORDER		17
+#define ORD_SETATTRIBUTE	18
+
+#define ORD_STRETCHBLT		27
+#define ORD_STRETCHDIBITS	28
+#define ORD_SELECTBITMAP	29
+#define ORD_BITMAPBITS		30
+
+#define ORD_EXTDEVICEMODE	90
+#define ORD_DEVICECAPABILITIES	91
+#define ORD_ADVANCEDSETUPDIALOG	93
+
+#define ORD_DIALOGFN		100
+#define ORD_PSEUDOEDIT		101
+                        
+enum {
+    FUNC_BITBLT = 0,		 
+    FUNC_COLORINFO,    	 
+    FUNC_CONTROL,    	
+    FUNC_DISABLE,    	
+    FUNC_ENABLE,    		
+    FUNC_ENUMDFONTS,    	
+    FUNC_ENUMOBJ,    	
+    FUNC_OUTPUT,    		
+    FUNC_PIXEL,    			
+    FUNC_REALIZEOBJECT,    	
+    FUNC_STRBLT,    		
+    FUNC_SCANLR,    		
+    FUNC_DEVICEMODE,    	
+    FUNC_EXTTEXTOUT,    	
+    FUNC_GETCHARWIDTH,    	
+    FUNC_DEVICEBITMAP,    	
+    FUNC_FASTBORDER,         
+    FUNC_SETATTRIBUTE,    				
+    FUNC_STRETCHBLT,    	
+    FUNC_STRETCHDIBITS,  	
+    FUNC_SELECTBITMAP,    	
+    FUNC_BITMAPBITS,    			       
+    FUNC_EXTDEVICEMODE,    	
+    FUNC_DEVICECAPABILITIES,	
+    FUNC_ADVANCEDSETUPDIALOG,			
+    FUNC_DIALOGFN,		
+    FUNC_PSEUDOEDIT,
+    TOTAL_PRINTER_DRIVER_FUNCTIONS /* insert functions before here */
+};
+
+typedef struct PRINTER_FONTS_INFO
+{
+    LOGFONT16		lf;			/* LogFont infomation */
+    TEXTMETRIC16	tm;			/* Text metrics infomation */
+} PRINTER_FONTS_INFO;
+
+typedef struct
+{
+    char 	szDriver[9];		/* Driver name eg EPSON */
+    HINSTANCE16	hInst;			/* Handle for driver */
+    WORD	ds_reg;			/* DS of driver */
+    FARPROC16 	fn[TOTAL_PRINTER_DRIVER_FUNCTIONS];	/* Printer functions */
+    int		nUsageCount;		/* Usage count, unload == 0 */
+    int		nPrinterFonts;		/* Number of printer fonts */
+    PRINTER_FONTS_INFO *paPrinterFonts; /* array of printer fonts */
+    int		nIndex;			/* Index in global driver array */
+    HGLOBAL16   hThunk;			/* Thunking buffer */
+    SEGPTR	ThunkBufSegPtr;
+    SEGPTR	ThunkBufLimit;
+} LOADED_PRINTER_DRIVER;
+
+typedef struct PDEVICE_HEADER
+{
+    LOADED_PRINTER_DRIVER *pLPD;	/* Associated printer driver */
+} PDEVICE_HEADER;
+
+typedef short SHORT; 
+
+#pragma pack(1)
+
+typedef struct TEXTXFORM 
+{
+    SHORT  txfHeight;
+    SHORT  txfWidth;
+    SHORT  txfEscapement;
+    SHORT  txfOrientation;
+    SHORT  txfWeight;
+    CHAR   txfItalic;
+    CHAR   txfUnderline;
+    CHAR   txfStrikeOut;
+    CHAR   txfOutPrecision;
+    CHAR   txfClipPrecision;
+    SHORT  txfAccelerator WINE_PACKED;
+    SHORT  txfOverhang WINE_PACKED;
+} TEXTXFORM, *LPTEXTXFORM;
+
+#define PCOLOR DWORD
+typedef struct DRAWMODE 
+{
+    SHORT    Rop2;       
+    SHORT    bkMode;     
+    PCOLOR   bkColor;    
+    PCOLOR   TextColor;  
+    SHORT    TBreakExtra;
+    SHORT    BreakExtra; 
+    SHORT    BreakErr;   
+    SHORT    BreakRem;   
+    SHORT    BreakCount; 
+    SHORT    CharExtra;  
+    COLORREF LbkColor;   
+    COLORREF LTextColor; 
+} DRAWMODE, *LPDRAWMODE;
+
+typedef struct FONTINFO 
+{
+    SHORT dfType;
+    SHORT dfPoints;
+    SHORT dfVertRes;
+    SHORT dfHorizRes;
+    SHORT dfAscent;
+    SHORT dfInternalLeading;
+    SHORT dfExternalLeading;
+    CHAR  dfItalic;
+    CHAR  dfUnderline;
+    CHAR  dfStrikeOut;
+    SHORT dfWeight;
+    CHAR  dfCHARSet;
+    SHORT dfPixWidth;
+    SHORT dfPixHeight;
+    CHAR  dfPitchAndFamily;
+    SHORT dfAvgWidth;
+    SHORT dfMaxWidth;
+    CHAR  dfFirstCHAR;
+    CHAR  dfLastCHAR;
+    CHAR  dfDefaultCHAR;
+    CHAR  dfBreakCHAR;
+    SHORT dfWidthBytes;
+    LONG  dfDevice;
+    LONG  dfFace;
+    LONG  dfBitsPointer;
+    LONG  dfBitsOffset;
+    CHAR  dfReserved;
+    LONG  dfFlags;
+    SHORT dfAspace;
+    SHORT dfBspace;
+    SHORT dfCspace;
+    LONG  dfColorPointer;
+    LONG  dfReserved1[4];
+} FONTINFO, *LPFONTINFO;
+
+#pragma pack(4)
+
+typedef struct WINE_ENUM_PRINTER_FONT_CALLBACK
+{
+    DWORD	magic;			/* magic number */
+    int 	nMode;			/* Mode 0=count, 1=store */
+    int 	nCount;			/* Callback count */
+    LOADED_PRINTER_DRIVER *pLPD;    	/* Printer driver info */
+} WEPFC;
+
+#define OBJ_PEN 	1       
+#define OBJ_BRUSH 	2  
+#define OBJ_FONT 	3   
+#define OBJ_PBITMAP 	5
+
+/* Win16 printer driver physical DC */
+typedef struct
+{
+    SEGPTR	segptrPDEVICE;	/* PDEVICE used by 16 bit printer drivers */
+    LOGFONT16	lf;		/* Current font details */
+    TEXTMETRIC16	tm;		/* Current font metrics */
+    SEGPTR	segptrFontInfo; /* Current font realized by printer driver */
+} WIN16DRV_PDEVICE;
+
+/* Wine driver functions */
+
+extern BOOL32 WIN16DRV_GetTextExtentPoint( DC *dc, LPCSTR str, INT32 count,
+                                           LPSIZE32 size );
+extern BOOL32 WIN16DRV_GetTextMetrics( DC *dc, TEXTMETRIC32A *metrics );
+
+#endif  /* __WINE_WIN16DRV_H */
diff --git a/include/winbase.h b/include/winbase.h
index 536e73f..bb7de5b 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -1,7 +1,7 @@
 #ifndef __WINE_WINBASE_H
 #define __WINE_WINBASE_H
 
-#include "wintypes.h"
+#include "windows.h"
 
 #define INVALID_HANDLE_VALUE    ((HANDLE32) -1)
 
diff --git a/include/windows.h b/include/windows.h
index b8fb02d..988d8d7 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -2521,6 +2521,40 @@
 #define SBM_REDRAW            (WM_USER+3)
 #define SBM_ENABLE            (WM_USER+4)
 
+/* Scrollbar info */
+typedef struct
+{
+    UINT16    cbSize;
+    UINT16    fMask;
+    INT16     nMin;
+    INT16     nMax;
+    UINT16    nPage;
+    INT16     nPos;
+    INT16     nTrackPos;
+} SCROLLINFO16, *LPSCROLLINFO16;
+
+typedef struct
+{
+    UINT32    cbSize;
+    UINT32    fMask;
+    INT32     nMin;
+    INT32     nMax;
+    UINT32    nPage;
+    INT32     nPos;
+    INT32     nTrackPos;
+} SCROLLINFO32, *LPSCROLLINFO32;
+ 
+DECL_WINELIB_TYPE(SCROLLINFO);
+DECL_WINELIB_TYPE(LPSCROLLINFO);
+
+/* GetScrollInfo() flags */ 
+#define SIF_RANGE           0x0001
+#define SIF_PAGE            0x0002
+#define SIF_POS             0x0004
+#define SIF_DISABLENOSCROLL 0x0008
+#define SIF_TRACKPOS        0x0010
+#define SIF_ALL             (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
+
 /* Listbox styles */
 #define LBS_NOTIFY            0x0001L
 #define LBS_SORT              0x0002L
@@ -2942,6 +2976,18 @@
 #define GPTR                (GMEM_FIXED | GMEM_ZEROINIT)
 
 
+typedef struct tagMEMORYSTATUS
+{
+    DWORD    dwLength;
+    DWORD    dwMemoryLoad;
+    DWORD    dwTotalPhys;
+    DWORD    dwAvailPhys;
+    DWORD    dwTotalPageFile;
+    DWORD    dwAvailPageFile;
+    DWORD    dwTotalVirtual;
+    DWORD    dwAvailVirtual;
+} MEMORYSTATUS, *LPMEMORYSTATUS;
+
 /* Predefined Clipboard Formats */
 #define CF_TEXT              1
 #define CF_BITMAP            2
@@ -3396,6 +3442,23 @@
 #define LR_LOADREALSIZE		0x0020
 #define LR_LOADMAP3DCOLORS	0x1000
 
+typedef struct _LARGE_INTEGER
+{
+    DWORD    LowPart;
+    LONG     HighPart;
+} LARGE_INTEGER,*LPLARGE_INTEGER;
+
+typedef struct _ULARGE_INTEGER
+{
+    DWORD    LowPart;
+    DWORD    HighPart;
+} ULARGE_INTEGER,*LPULARGE_INTEGER;
+
+/* SetLastErrorEx types */
+#define	SLE_ERROR	0x00000001
+#define	SLE_MINORERROR	0x00000002
+#define	SLE_WARNING	0x00000003
+
 #pragma pack(4)
 
 /* Declarations for functions that exist only in Win16 */
@@ -3459,6 +3522,7 @@
 BOOL32     GetCommTimeouts(HANDLE32,LPCOMMTIMEOUTS);
 DWORD      GetLogicalDrives(void);
 HANDLE32   GetProcessHeap(void);
+VOID       GlobalMemoryStatus(LPMEMORYSTATUS);
 LPVOID     HeapAlloc(HANDLE32,DWORD,DWORD);
 DWORD      HeapCompact(HANDLE32,DWORD);
 HANDLE32   HeapCreate(DWORD,DWORD,DWORD);
@@ -3470,6 +3534,7 @@
 BOOL32     HeapUnlock(HANDLE32);
 BOOL32     HeapValidate(HANDLE32,DWORD,LPVOID);
 BOOL32     IsWindowUnicode(HWND32);
+BOOL32     QueryPerformanceCounter(LPLARGE_INTEGER);
 DWORD      RegCreateKeyEx32A(HKEY,LPCSTR,DWORD,LPSTR,DWORD,REGSAM,
                              LPSECURITY_ATTRIBUTES,LPHKEY,LPDWORD);
 DWORD      RegCreateKeyEx32W(HKEY,LPCWSTR,DWORD,LPWSTR,DWORD,REGSAM,
@@ -3545,7 +3610,8 @@
 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       SetLastError(DWORD); /* FIXME: not 100% sure about that */
+VOID       SetLastError(DWORD); /* FIXME: not 100% sure it's only in win32 */
+VOID       SetLastErrorEx(DWORD,DWORD);
 VOID       SetRectRgn(HRGN32,INT32,INT32,INT32,INT32);
 WORD       SetWindowWord(HWND32,INT32,WORD);
 BOOL16     ShowCaret(HWND32);
@@ -3914,6 +3980,9 @@
 INT16      GetRgnBox16(HRGN16,LPRECT16);
 INT32      GetRgnBox32(HRGN32,LPRECT32);
 #define    GetRgnBox WINELIB_NAME(GetRgnBox)
+BOOL16     GetScrollInfo16(HWND16,INT16,LPSCROLLINFO16);
+BOOL32     GetScrollInfo32(HWND32,INT32,LPSCROLLINFO32);
+#define    GetScrollInfo WINELIB_NAME(GetScrollInfo)
 DWORD      GetShortPathName32A(LPCSTR,LPSTR,DWORD);
 DWORD      GetShortPathName32W(LPCWSTR,LPWSTR,DWORD);
 #define    GetShortPathName WINELIB_NAME_AW(GetShortPathName)
@@ -4309,6 +4378,9 @@
 void       SetRectEmpty16(LPRECT16);
 void       SetRectEmpty32(LPRECT32);
 #define    SetRectEmpty WINELIB_NAME(SetRectEmpty)
+INT16      SetScrollInfo16(HWND16,INT16,LPSCROLLINFO16,BOOL16);
+INT32      SetScrollInfo32(HWND32,INT32,LPSCROLLINFO32,BOOL32);
+#define    SetScrollInfo WINELIB_NAME(SetScrollInfo)
 HWND16     SetSysModalWindow16(HWND16);
 #define    SetSysModalWindow32(hwnd) ((HWND32)0)
 #define    SetSysModalWindow WINELIB_NAME(SetSysModalWindow)
@@ -4578,7 +4650,7 @@
 INT        EnumFonts(HDC,LPCSTR,FONTENUMPROC16,LPARAM);
 BOOL       EnumMetaFile(HDC,HMETAFILE16,MFENUMPROC16,LPARAM);
 INT        EnumObjects(HDC,INT,GOBJENUMPROC16,LPARAM);
-INT        Escape(HDC,INT,INT,LPCSTR,LPVOID);
+INT        Escape(HDC,INT,INT,SEGPTR,SEGPTR);
 int        ExcludeClipRect(HDC,short,short,short,short);
 int        ExcludeVisRect(HDC,short,short,short,short);
 BOOL       ExitWindows(DWORD,WORD);
@@ -4819,7 +4891,7 @@
 int        SelectVisRgn(HDC,HRGN);
 WORD       SelectorAccessRights(WORD,WORD,WORD);
 HWND       SetActiveWindow(HWND);
-DWORD      SetBkColor(HDC,COLORREF);
+COLORREF   SetBkColor(HDC,COLORREF);
 WORD       SetBkMode(HDC,WORD);
 HWND       SetCapture(HWND);
 HANDLE     SetClipboardData(WORD,HANDLE);
diff --git a/include/x11drv.h b/include/x11drv.h
new file mode 100644
index 0000000..9ee3943
--- /dev/null
+++ b/include/x11drv.h
@@ -0,0 +1,56 @@
+/*
+ * X11 display driver definitions
+ */
+
+#ifndef __WINE_X11DRV_H
+#define __WINE_X11DRV_H
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "windows.h"
+
+  /* X physical pen */
+typedef struct
+{
+    int          style;
+    int          pixel;
+    int          width;
+    char *       dashes;
+    int          dash_len;
+} X_PHYSPEN;
+
+  /* X physical brush */
+typedef struct
+{
+    int          style;
+    int          fillStyle;
+    int          pixel;
+    Pixmap       pixmap;
+} X_PHYSBRUSH;
+
+  /* X physical font */
+typedef struct
+{
+    XFontStruct * fstruct;
+    TEXTMETRIC16  metrics;
+} X_PHYSFONT;
+
+  /* X physical device */
+typedef struct
+{
+    GC            gc;          /* X Window GC */
+    Drawable      drawable;
+    X_PHYSFONT    font;
+    X_PHYSPEN     pen;
+    X_PHYSBRUSH   brush;
+} X11DRV_PDEVICE;
+
+/* Wine driver X11 functions */
+
+struct tagDC;
+
+extern BOOL32 X11DRV_GetTextExtentPoint( struct tagDC *dc, LPCSTR str,
+                                         INT32 count, LPSIZE32 size );
+
+#endif  /* __WINE_X11DRV_H */
diff --git a/loader/builtin.c b/loader/builtin.c
index e450025..00571c5 100644
--- a/loader/builtin.c
+++ b/loader/builtin.c
@@ -101,6 +101,7 @@
 extern const DLL_DESCRIPTOR GDI32_Descriptor;
 extern const DLL_DESCRIPTOR KERNEL32_Descriptor;
 extern const DLL_DESCRIPTOR LZ32_Descriptor;
+extern const DLL_DESCRIPTOR MPR_Descriptor;
 extern const DLL_DESCRIPTOR NTDLL_Descriptor;
 extern const DLL_DESCRIPTOR SHELL32_Descriptor;
 extern const DLL_DESCRIPTOR USER32_Descriptor;
@@ -151,6 +152,7 @@
     { &GDI32_Descriptor,    0 },
     { &KERNEL32_Descriptor, DLL_FLAG_ALWAYS_USED },
     { &LZ32_Descriptor,     0 },
+    { &MPR_Descriptor,      0 },
     { &NTDLL_Descriptor,    0 },
     { &SHELL32_Descriptor,  0 },
     { &USER32_Descriptor,   0 },
diff --git a/loader/main.c b/loader/main.c
index 28f9987..1501255 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -56,6 +56,7 @@
 int MAIN_Init(void)
 {
     extern BOOL32 RELAY_Init(void);
+    extern BOOL32 WIN16DRV_Init(void);
     extern BOOL32 SIGNAL_Init(void);
     extern BOOL32 WIDGETS_Init(void);
     extern int KERN32_Init(void);
@@ -93,6 +94,9 @@
 
       /* Initialize signal handling */
     if (!SIGNAL_Init()) return 0;
+
+    /* Create the Win16 printer driver */
+    if (!WIN16DRV_Init()) return 0;
 #endif  /* WINELIB */
 
     /* Initialise DOS drives */
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 4dad04b..87fc649 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -547,10 +547,15 @@
 
     if (!(pModule->pe_module->pe_header->coff.Characteristics & IMAGE_FILE_DLL))
     {
+        int fs;
         TASK_CreateTask( hModule, hInstance, 0,
                          params->hEnvironment,
                          (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
                          *((WORD*)PTR_SEG_TO_LIN(params->showCmd) + 1) );
+        fs=(int)GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, 0x10000 );
+        PE_InitTEB(fs);
+        /* FIXME: this should be done in the context of the new task */
+        __asm__ __volatile__("movw %w0,%%fs"::"r" (fs));
         PE_InitializeDLLs( hModule );
     }
     return hInstance;
@@ -561,7 +566,6 @@
 
 void PE_Win32CallToStart( SIGCONTEXT *context )
 {
-    int fs;
     HMODULE16 hModule;
     NE_MODULE *pModule;
 
@@ -570,9 +574,6 @@
     hModule = GetExePtr( GetCurrentTask() );
     pModule = MODULE_GetPtr( hModule );
     USER_InitApp( hModule );
-    fs=(int)GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, 0x10000 );
-    PE_InitTEB(fs);
-    __asm__ __volatile__("movw %w0,%%fs"::"r" (fs));
     CallTaskStart32( (FARPROC32)(pModule->pe_module->load_addr + 
                                pModule->pe_module->pe_header->opt_coff.AddressOfEntryPoint) );
 }
diff --git a/loader/task.c b/loader/task.c
index 44825ac..4e62f3c 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -493,7 +493,7 @@
 
       /* Get the compatibility flags */
 
-    pTask->compat_flags = GetProfileInt( name, "Compatibility", 0 );
+    pTask->compat_flags = GetProfileInt( "Compatibility", name, 0 );
 
       /* Allocate a code segment alias for the TDB */
 
diff --git a/memory/global.c b/memory/global.c
index c7a06cc..4718a63 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -890,3 +890,18 @@
 {
     return TRUE;
 }
+
+
+/***********************************************************************
+ *           GlobalMemoryStatus   (KERNEL32.327)
+ */
+VOID GlobalMemoryStatus( LPMEMORYSTATUS lpmem )
+{
+    /* FIXME: should do something like MemManInfo() here */
+    lpmem->dwMemoryLoad    = 0;
+    lpmem->dwTotalPhys     = 16*1024*1024;
+    lpmem->dwAvailPhys     = 16*1024*1024;
+    lpmem->dwTotalPageFile = 0;
+    lpmem->dwAvailPageFile = 16*1024*1024;
+    lpmem->dwAvailVirtual  = 16*1024*1024;
+}
diff --git a/memory/ldt.c b/memory/ldt.c
index 9b1ef9e..d365936 100644
--- a/memory/ldt.c
+++ b/memory/ldt.c
@@ -14,11 +14,12 @@
 #include "debug.h"
 
 #ifdef linux
-#include <linux/unistd.h>
+#include <syscall.h>
 #include <linux/head.h>
 #include <linux/ldt.h>
 
-_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
+static __inline__ _syscall3(int, modify_ldt, int, func, void *, ptr,
+                            unsigned long, bytecount);
 #endif  /* linux */
 
 #if defined(__svr4__) || defined(_SCO_DS)
diff --git a/misc/Makefile.in b/misc/Makefile.in
index 0d9d3a9..a7d7746 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -15,6 +15,7 @@
 	lstr.c \
 	lzexpand.c \
 	main.c \
+	mpr.c \
 	network.c \
 	ole2.c \
 	ole2disp.c \
@@ -22,6 +23,7 @@
 	olecli.c \
 	olesvr.c \
 	port.c \
+	printdrv.c \
 	rect.c \
 	registry.c \
 	shell.c \
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 43ca13d..d35ec48 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -360,20 +360,21 @@
 	}
     }
   /* read filter information */
-  pstr = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFilter);
-  n = 0;
-  while(*pstr)
-    {
-      dprintf_commdlg(stddeb,"lpstrFilter // add str='%s' ", pstr);
-      i = SendDlgItemMessage16(hWnd, cmb1, CB_ADDSTRING, 0,
-                               (LPARAM)lpofn->lpstrFilter + n );
-      n += strlen(pstr) + 1;
-      pstr += strlen(pstr) + 1;
-      dprintf_commdlg(stddeb,"associated to '%s'\n", pstr);
-      SendDlgItemMessage16(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
-      n += strlen(pstr) + 1;
-      pstr += strlen(pstr) + 1;
-    }
+  if (lpofn->lpstrFilter) {
+	pstr = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFilter);
+	n = 0;
+	while(*pstr) {
+	  dprintf_commdlg(stddeb,"lpstrFilter // add str='%s' ", pstr);
+	  i = SendDlgItemMessage16(hWnd, cmb1, CB_ADDSTRING, 0,
+				       (LPARAM)lpofn->lpstrFilter + n );
+	  n += strlen(pstr) + 1;
+	  pstr += strlen(pstr) + 1;
+	  dprintf_commdlg(stddeb,"associated to '%s'\n", pstr);
+	  SendDlgItemMessage16(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
+	  n += strlen(pstr) + 1;
+	  pstr += strlen(pstr) + 1;
+	}
+  }
   /* set default filter */
   if (lpofn->nFilterIndex == 0 && lpofn->lpstrCustomFilter == (SEGPTR)NULL)
   	lpofn->nFilterIndex = 1;
diff --git a/misc/crtdll.c b/misc/crtdll.c
index 9139d00..c87b28d 100644
--- a/misc/crtdll.c
+++ b/misc/crtdll.c
@@ -168,11 +168,114 @@
 	return gets(buf);
 }
 
-CHAR
-CRTDLL_toupper(CHAR x) {
+
+/*********************************************************************
+ *                  isalnum       (CRTDLL.394)
+ */
+CHAR CRTDLL_isalnum(CHAR x)
+{
+    return isalnum(x);
+}
+
+
+/*********************************************************************
+ *                  isalpha       (CRTDLL.395)
+ */
+CHAR CRTDLL_isalpha(CHAR x)
+{
+    return isalpha(x);
+}
+
+
+/*********************************************************************
+ *                  iscntrl       (CRTDLL.396)
+ */
+CHAR CRTDLL_iscntrl(CHAR x)
+{
+    return iscntrl(x);
+}
+
+
+/*********************************************************************
+ *                  isdigit       (CRTDLL.397)
+ */
+CHAR CRTDLL_isdigit(CHAR x)
+{
+    return isdigit(x);
+}
+
+
+/*********************************************************************
+ *                  isgraph       (CRTDLL.398)
+ */
+CHAR CRTDLL_isgraph(CHAR x)
+{
+    return isgraph(x);
+}
+
+
+/*********************************************************************
+ *                  islower       (CRTDLL.400)
+ */
+CHAR CRTDLL_islower(CHAR x)
+{
+    return islower(x);
+}
+
+
+/*********************************************************************
+ *                  isprint       (CRTDLL.401)
+ */
+CHAR CRTDLL_isprint(CHAR x)
+{
+    return isprint(x);
+}
+
+
+/*********************************************************************
+ *                  ispunct       (CRTDLL.402)
+ */
+CHAR CRTDLL_ispunct(CHAR x)
+{
+    return ispunct(x);
+}
+
+
+/*********************************************************************
+ *                  isspace       (CRTDLL.403)
+ */
+CHAR CRTDLL_isspace(CHAR x)
+{
+    return isspace(x);
+}
+
+
+/*********************************************************************
+ *                  isupper       (CRTDLL.404)
+ */
+CHAR CRTDLL_isupper(CHAR x)
+{
+    return isupper(x);
+}
+
+
+/*********************************************************************
+ *                  tolower       (CRTDLL.491)
+ */
+CHAR CRTDLL_tolower(CHAR x)
+{
+    return tolower(x);
+}
+
+
+/*********************************************************************
+ *                  toupper       (CRTDLL.492)
+ */
+CHAR CRTDLL_toupper(CHAR x) {
 	return toupper(x);
 }
 
+
 void
 CRTDLL_putchar(INT32 x) {
 	putchar(x);
diff --git a/misc/escape.c b/misc/escape.c
index 9336c84..79ef0e4 100644
--- a/misc/escape.c
+++ b/misc/escape.c
@@ -2,17 +2,23 @@
  * Escape() function.
  *
  * Copyright 1994  Bob Amstadt
- *
-static char Copyright[] = "Copyright  Bob Amstadt, 1994";
-*/
+ */
 
 #include <stdlib.h>
 #include <stdio.h>
 #include "windows.h"
+#include "gdi.h"
 
-INT Escape(HDC hdc, INT nEscape, INT cbInput, 
-	   LPCSTR lpszInData, LPVOID lpvOutData)
+INT Escape( HDC hdc, INT nEscape, INT cbInput,
+            SEGPTR lpszInData, SEGPTR lpvOutData )
 {
-/*     fprintf(stderr, "Escape(nEscape = %04x)\n", nEscape); */
-    return 0;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return 0;
+    }
+
+    if (!dc->funcs->pEscape) return 0;
+    return dc->funcs->pEscape( dc, nEscape, cbInput, lpszInData, lpvOutData );
 }
diff --git a/misc/main.c b/misc/main.c
index e2bc1f5..3adf5fb 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -892,13 +892,15 @@
 {
     WORD       nCount;
     LPENVENTRY lpEnv = lpEnvList;
+
     dprintf_env(stddeb, "GetEnvironment('%s', '%s', %d) !\n",
 		lpPortName, lpEnviron, nMaxSiz);
     while (lpEnv != NULL) {
 	if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
+	    if( lpEnviron == NULL ) return lpEnv->wSize;
 	    nCount = MIN(nMaxSiz, lpEnv->wSize);
-	    memcpy(lpEnviron, lpEnv->Value, nCount);
-	    dprintf_env(stddeb, "GetEnvironment() // found '%s' !\n", lpEnviron);
+            memcpy(lpEnviron, lpEnv->Value, nCount);
+	    dprintf_env(stddeb, "GetEnvironment() // found '%s' !\n", lpEnv->Value);
 	    return nCount;
 	}
 	lpEnv = lpEnv->Next;
diff --git a/misc/mpr.c b/misc/mpr.c
new file mode 100644
index 0000000..62f9f85
--- /dev/null
+++ b/misc/mpr.c
@@ -0,0 +1,23 @@
+/* MPR.dll
+ *
+ * Copyright 1996 Marcus Meissner
+ */
+
+#include <stdio.h>
+#include "win.h"
+#include "stddebug.h"
+#include "debug.h"
+
+DWORD
+WNetGetCachedPassword(
+	LPSTR	pbResource,
+	WORD	cbResource,
+	LPSTR	pbPassword,
+	LPWORD	pcbPassword,
+	BYTE	nType
+) {
+	fprintf(stdnimp,"WNetGetCachedPassword(%s,%d,%p,%d,%d)\n",
+		pbResource,cbResource,pbPassword,*pcbPassword,nType
+	);
+	return 0;
+}
diff --git a/misc/printdrv.c b/misc/printdrv.c
new file mode 100644
index 0000000..0d7094d
--- /dev/null
+++ b/misc/printdrv.c
@@ -0,0 +1,37 @@
+/* 
+ * Implementation of some printer driver bits
+ * 
+ * Copyright 1996 John Harvey
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "windows.h"
+#include "win.h"
+#include "winerror.h"
+
+
+DWORD
+DrvGetPrinterData(LPSTR lpPrinter, LPSTR lpProfile, LPDWORD lpType,
+                  LPBYTE lpPrinterData, int cbData, LPDWORD lpNeeded)
+{
+    fprintf(stderr,"In DrvGetPrinterData printer %s profile %s lpType %p \n",
+           lpPrinter, lpProfile, lpType);
+    return 0;
+}
+
+
+
+DWORD
+DrvSetPrinterData(LPSTR lpPrinter, LPSTR lpProfile, LPDWORD lpType,
+                  LPBYTE lpPrinterData, DWORD dwSize)
+{
+    fprintf(stderr,"In DrvSetPrinterData printer %s profile %s lpType %p \n",
+           lpPrinter, lpProfile, lpType);
+    return 0;
+}
+
+
+
diff --git a/misc/registry.c b/misc/registry.c
index 6064937..62bc558 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -83,10 +83,8 @@
 #define strdupA2W(x)	STRING32_DupAnsiToUni(x)
 #define strdupW2A(x)	STRING32_DupUniToAnsi(x)
 #define strdupW(x)	STRING32_strdupW(x)
-#define strcmpW(a,b)	lstrcmp32W(a,b)
 #define strcmpniW(a,b)	STRING32_lstrcmpniW(a,b)
 #define strchrW(a,c)	STRING32_lstrchrW(a,c)
-#define strlenW(a)	lstrlen32W(a)
 #define strcpyWA(a,b)	STRING32_UniToAnsi(a,b)
 
 static struct openhandle {
@@ -466,7 +464,7 @@
 	lplpkey= &(lpkey->nextsub);
 	lpxkey	= *lplpkey;
 	while (lpxkey) {
-		if (!strcmpW(lpxkey->keyname,keyname))
+		if (!lstrcmp32W(lpxkey->keyname,keyname))
 			break;
 		lplpkey	= &(lpxkey->next);
 		lpxkey	= *lplpkey;
@@ -496,7 +494,7 @@
 				break;
 		} else {
 			if (	val->name!=NULL && 
-				!strcmpW(val->name,name)
+				!lstrcmp32W(val->name,name)
 			)
 				break;
 		}
@@ -676,7 +674,7 @@
 				if ((1<<type) & UNICONVMASK) {
 					s=_wine_read_USTRING(s,(LPWSTR*)&data);
 					if (data)
-						len = strlenW((LPWSTR)data)*2+2;
+						len = lstrlen32W((LPWSTR)data)*2+2;
 					else	
 						len = 0;
 				} else {
@@ -931,7 +929,7 @@
 			data	= key->values[i].data;
 			if ((1<<key->values[i].type) & UNICONVMASK) {
 				data = (BYTE*)strdupA2W(data);
-				len  = strlenW((LPWSTR)data)*2+2;
+				len  = lstrlen32W((LPWSTR)data)*2+2;
 				free(key->values[i].data);
 			}
 			_find_or_add_value(
@@ -1367,7 +1365,7 @@
 	while (i<wpc) {
 		lpxkey=lpNextKey->nextsub;
 		while (lpxkey) {
-			if (!strcmpW(wps[i],lpxkey->keyname))
+			if (!lstrcmp32W(wps[i],lpxkey->keyname))
 				break;
 			lpxkey=lpxkey->next;
 		}
@@ -1502,7 +1500,7 @@
 	while (i<wpc) {
 		lpxkey=lpNextKey->nextsub;
 		while (lpxkey) {
-			if (!strcmpW(wps[i],lpxkey->keyname))
+			if (!lstrcmp32W(wps[i],lpxkey->keyname))
 				break;
 			lpxkey=lpxkey->next;
 		}
@@ -1710,7 +1708,9 @@
 				break;
 	} else {
 		for (i=0;i<lpkey->nrofvalues;i++)
-			if (!strcmpW(lpszValueName,lpkey->values[i].name))
+			if (	lpkey->values[i].name &&
+				!lstrcmp32W(lpszValueName,lpkey->values[i].name)
+			)
 				break;
 	}
 	if (i==lpkey->nrofvalues) {
@@ -1972,7 +1972,9 @@
 				break;
 	} else {
 		for (i=0;i<lpkey->nrofvalues;i++)
-			if (!strcmpW(lpszValueName,lpkey->values[i].name))
+			if (	lpkey->values[i].name &&
+				!lstrcmp32W(lpszValueName,lpkey->values[i].name)
+			)
 				break;
 	}
 	if (i==lpkey->nrofvalues) {
@@ -2070,11 +2072,11 @@
 		fprintf(stddeb,"RegSetValueX called with dwType=%ld!\n",dwType);
 		dwType=REG_SZ;
 	}
-	if (cbData!=2*strlenW(lpszData)+2) {
+	if (cbData!=2*lstrlen32W(lpszData)+2) {
 		dprintf_reg(stddeb,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
-			cbData,W2C(lpszData,0),2*strlenW(lpszData)+2
+			cbData,W2C(lpszData,0),2*lstrlen32W(lpszData)+2
 		);
-		cbData=2*strlenW(lpszData)+2;
+		cbData=2*lstrlen32W(lpszData)+2;
 	}
 	ret=RegSetValueEx32W(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
 	if (hkey!=xhkey)
@@ -2167,9 +2169,9 @@
 	}
 	if (iSubkey || !lpxkey)
 		return ERROR_NO_MORE_ITEMS;
-	if (2*strlenW(lpxkey->keyname)+2>*lpcchName)
+	if (2*lstrlen32W(lpxkey->keyname)+2>*lpcchName)
 		return ERROR_MORE_DATA;
-	memcpy(lpszName,lpxkey->keyname,strlenW(lpxkey->keyname)*2+2);
+	memcpy(lpszName,lpxkey->keyname,lstrlen32W(lpxkey->keyname)*2+2);
 	if (lpszClass) {
 		/* what should we write into it? */
 		*lpszClass		= 0;
@@ -2319,12 +2321,12 @@
 	val	= lpkey->values+iValue;
 
 	if (val->name) {
-		if (strlenW(val->name)*2+2>*lpcchValue) {
-			*lpcchValue = strlenW(val->name)*2+2;
+		if (lstrlen32W(val->name)*2+2>*lpcchValue) {
+			*lpcchValue = lstrlen32W(val->name)*2+2;
 			return ERROR_MORE_DATA;
 		}
-		memcpy(lpszValue,val->name,2*strlenW(val->name)+2);
-		*lpcchValue=strlenW(val->name)*2+2;
+		memcpy(lpszValue,val->name,2*lstrlen32W(val->name)+2);
+		*lpcchValue=lstrlen32W(val->name)*2+2;
 	} else {
 		/* how to handle NULL value? */
 		*lpszValue	= 0;
@@ -2459,7 +2461,7 @@
 	while (i<wpc-1) {
 		lpxkey=lpNextKey->nextsub;
 		while (lpxkey) {
-			if (!strcmpW(wps[i],lpxkey->keyname))
+			if (!lstrcmp32W(wps[i],lpxkey->keyname))
 				break;
 			lpxkey=lpxkey->next;
 		}
@@ -2474,7 +2476,7 @@
 	lpxkey	= lpNextKey->nextsub;
 	lplpPrevKey = &(lpNextKey->nextsub);
 	while (lpxkey) {
-		if (!strcmpW(wps[i],lpxkey->keyname))
+		if (!lstrcmp32W(wps[i],lpxkey->keyname))
 			break;
 		lplpPrevKey	= &(lpxkey->next);
 		lpxkey		= lpxkey->next;
@@ -2536,7 +2538,9 @@
 		return SHELL_ERROR_BADKEY;
 	if (lpszValue) {
 		for (i=0;i<lpkey->nrofvalues;i++)
-			if (!strcmpW(lpkey->values[i].name,lpszValue))
+			if (	lpkey->values[i].name &&
+				!lstrcmp32W(lpkey->values[i].name,lpszValue)
+			)
 				break;
 	} else {
 		for (i=0;i<lpkey->nrofvalues;i++)
@@ -2616,35 +2620,35 @@
 		return SHELL_ERROR_BADKEY;
 	if (lpszClass) {
 		if (lpkey->class) {
-			if (strlenW(lpkey->class)*2+2>*lpcchClass) {
-				*lpcchClass=strlenW(lpkey->class)*2;
+			if (lstrlen32W(lpkey->class)*2+2>*lpcchClass) {
+				*lpcchClass=lstrlen32W(lpkey->class)*2;
 				return ERROR_MORE_DATA;
 			}
-			*lpcchClass=strlenW(lpkey->class)*2;
-			memcpy(lpszClass,lpkey->class,strlenW(lpkey->class));
+			*lpcchClass=lstrlen32W(lpkey->class)*2;
+			memcpy(lpszClass,lpkey->class,lstrlen32W(lpkey->class));
 		} else {
 			*lpszClass	= 0;
 			*lpcchClass	= 0;
 		}
 	} else {
 		if (lpcchClass)
-			*lpcchClass	= strlenW(lpkey->class)*2;
+			*lpcchClass	= lstrlen32W(lpkey->class)*2;
 	}
 	lpxkey=lpkey->nextsub;
 	nrofkeys=maxsubkey=maxclass=maxvalues=maxvname=maxvdata=0;
 	while (lpxkey) {
 		nrofkeys++;
-		if (strlenW(lpxkey->keyname)>maxsubkey)
-			maxsubkey=strlenW(lpxkey->keyname);
-		if (lpxkey->class && strlenW(lpxkey->class)>maxclass)
-			maxclass=strlenW(lpxkey->class);
+		if (lstrlen32W(lpxkey->keyname)>maxsubkey)
+			maxsubkey=lstrlen32W(lpxkey->keyname);
+		if (lpxkey->class && lstrlen32W(lpxkey->class)>maxclass)
+			maxclass=lstrlen32W(lpxkey->class);
 		if (lpxkey->nrofvalues>maxvalues)
 			maxvalues=lpxkey->nrofvalues;
 		for (i=0;i<lpxkey->nrofvalues;i++) {
 			LPKEYVALUE	val=lpxkey->values+i;
 
-			if (val->name && strlenW(val->name)>maxvname)
-				maxvname=strlenW(val->name);
+			if (val->name && lstrlen32W(val->name)>maxvname)
+				maxvname=lstrlen32W(val->name);
 			if (val->len>maxvdata)
 				maxvdata=val->len;
 		}
diff --git a/objects/bitmap.c b/objects/bitmap.c
index afc0b6b..b836e20 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -25,7 +25,7 @@
 /***********************************************************************
  *           BITMAP_Init
  */
-BOOL BITMAP_Init(void)
+BOOL32 BITMAP_Init(void)
 {
     Pixmap tmpPixmap;
     
@@ -356,7 +356,7 @@
 /***********************************************************************
  *           BITMAP_DeleteObject
  */
-BOOL BITMAP_DeleteObject( HBITMAP hbitmap, BITMAPOBJ * bitmap )
+BOOL32 BITMAP_DeleteObject( HBITMAP16 hbitmap, BITMAPOBJ * bitmap )
 {
     XFreePixmap( display, bitmap->pixmap );
     return GDI_FreeObject( hbitmap );
@@ -396,8 +396,8 @@
 /***********************************************************************
  *           BITMAP_SelectObject
  */
-HBITMAP BITMAP_SelectObject( DC * dc, HBITMAP hbitmap,
-			     BITMAPOBJ * bmp )
+HBITMAP16 BITMAP_SelectObject( DC * dc, HBITMAP16 hbitmap,
+                               BITMAPOBJ * bmp )
 {
     HRGN hrgn;
     HBITMAP prevHandle = dc->w.hBitmap;
diff --git a/objects/color.c b/objects/color.c
index 5ed37ec..d5afb9d 100644
--- a/objects/color.c
+++ b/objects/color.c
@@ -602,7 +602,7 @@
  *
  * Check whether 'color' can be represented with a solid color.
  */
-BOOL COLOR_IsSolid( COLORREF color )
+BOOL32 COLOR_IsSolid( COLORREF color )
 {
     int i;
     const PALETTEENTRY *pEntry = COLOR_sysPal;
@@ -626,7 +626,7 @@
  *	     COLOR_PaletteLookupPixel
  */
 int COLOR_PaletteLookupPixel( PALETTEENTRY* palPalEntry, int size,
-                              int* mapping, COLORREF col, BOOL skipReserved )
+                              int* mapping, COLORREF col, BOOL32 skipReserved )
 {
     int i, best = 0, diff = 0x7fffffff;
     int r,g,b;
@@ -898,7 +898,7 @@
  * Set the color-mapping table for selected palette. 
  * Return number of entries which mapping has changed.
  */
-int COLOR_SetMapping( PALETTEOBJ* palPtr, BOOL mapOnly )
+int COLOR_SetMapping( PALETTEOBJ* palPtr, BOOL32 mapOnly )
 {
     int  i, index;
     char flag;
diff --git a/objects/dc.c b/objects/dc.c
index 58529ac..f8d552f 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -17,8 +17,6 @@
 #include "callback.h"
 #include "xmalloc.h"
 
-static DeviceCaps * displayDevCaps = NULL;
-
 extern void CLIPPING_UpdateGCRegion( DC * dc );     /* objects/clipping.c */
 extern BOOL DCHook( HDC, WORD, DWORD, DWORD );      /* windows/dce.c */
 
@@ -158,8 +156,6 @@
     SelectObject( dc->hSelf, dc->w.hPen );
     SelectObject( dc->hSelf, dc->w.hBrush );
     SelectObject( dc->hSelf, dc->w.hFont );
-    XSetGraphicsExposures( display, dc->u.x.gc, False );
-    XSetSubwindowMode( display, dc->u.x.gc, IncludeInferiors );
     CLIPPING_UpdateGCRegion( dc );
 }
 
@@ -491,8 +487,11 @@
 HDC CreateDC( LPCSTR driver, LPCSTR device, LPCSTR output, const DEVMODE* initData )
 {
     DC * dc;
-    HANDLE handle;
-    
+    HDC16 handle;
+    const DC_FUNCTIONS *funcs;
+
+    if (!(funcs = DRIVER_FindDriver( driver ))) return 0;
+
     handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
     if (!handle) return 0;
     dc = (DC *) GDI_HEAP_LIN_ADDR( handle );
@@ -500,29 +499,20 @@
     dprintf_dc(stddeb, "CreateDC(%s %s %s): returning %04x\n",
 	    driver, device, output, handle );
 
-    if (!displayDevCaps)
-    {
-	displayDevCaps = (DeviceCaps *) xmalloc( sizeof(DeviceCaps) );
-	DC_FillDevCaps( displayDevCaps );
-    }
-
-    dc->hSelf = (HDC)handle;
-    dc->saveLevel = 0;
+    dc->hSelf      = handle;
+    dc->funcs      = funcs;
+    dc->physDev    = NULL;
+    dc->saveLevel  = 0;
     dc->dwHookData = 0L;
-    dc->hookProc = (SEGPTR)NULL;
+    dc->hookProc   = (SEGPTR)0;
 
     memcpy( &dc->w, &DC_defaultValues, sizeof(DC_defaultValues) );
-    memset( &dc->u.x, 0, sizeof(dc->u.x) );
+    dc->w.flags = 0;
 
-    dc->u.x.drawable   = rootWindow;
-    dc->u.x.gc         = XCreateGC( display, dc->u.x.drawable, 0, NULL );
-    dc->w.flags        = 0;
-    dc->w.devCaps      = displayDevCaps;
-    dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
-    dc->w.hVisRgn      = CreateRectRgn( 0, 0, displayDevCaps->horzRes,
-                                        displayDevCaps->vertRes );
-    if (!dc->w.hVisRgn)
+    if (dc->funcs->pCreateDC &&
+        !dc->funcs->pCreateDC( dc, driver, device, output, initData ))
     {
+        dprintf_dc( stddeb, "CreateDC: creation aborted by device\n" );
         GDI_HEAP_FREE( handle );
         return 0;
     }
@@ -548,10 +538,14 @@
  */
 HDC CreateCompatibleDC( HDC hdc )
 {
-    DC * dc;
-    HANDLE handle;
+    DC *dc, *origDC;
+    HDC16 handle;
     HBITMAP hbitmap;
-    BITMAPOBJ *bmp;
+    const DC_FUNCTIONS *funcs;
+
+    if ((origDC = (DC *)GDI_GetObjPtr( hdc, DC_MAGIC ))) funcs = origDC->funcs;
+    else funcs = DRIVER_FindDriver( "DISPLAY" );
+    if (!funcs) return 0;
 
     handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
     if (!handle) return 0;
@@ -565,34 +559,29 @@
 	GDI_HEAP_FREE( handle );
 	return 0;
     }
-    bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
-
-    dc->hSelf = (HDC)handle;    
-    dc->saveLevel = 0;
-    dc->dwHookData = 0L; 
-    dc->hookProc = (SEGPTR)NULL;
 
     memcpy( &dc->w, &DC_defaultValues, sizeof(DC_defaultValues) );
-    memset( &dc->u.x, 0, sizeof(dc->u.x) );
 
-    dc->u.x.drawable   = bmp->pixmap;
-    dc->u.x.gc         = XCreateGC( display, dc->u.x.drawable, 0, NULL );
+    dc->hSelf          = handle;
+    dc->funcs          = funcs;
+    dc->physDev        = NULL;
+    dc->saveLevel      = 0;
+    dc->dwHookData     = 0L;
+    dc->hookProc       = (SEGPTR)0;
     dc->w.flags        = DC_MEMORY;
     dc->w.bitsPerPixel = 1;
-    dc->w.devCaps      = displayDevCaps;
     dc->w.hBitmap      = hbitmap;
     dc->w.hFirstBitmap = hbitmap;
-    dc->w.hVisRgn      = CreateRectRgn( 0, 0, 1, 1 );
 
-    if (!dc->w.hVisRgn)
+    if (dc->funcs->pCreateDC &&
+        !dc->funcs->pCreateDC( dc, NULL, NULL, NULL, NULL ))
     {
+        dprintf_dc( stddeb, "CreateDC: creation aborted by device\n" );
         DeleteObject( hbitmap );
         GDI_HEAP_FREE( handle );
         return 0;
     }
 
-    DC_InitDC( dc );
-
     return handle;
 }
 
@@ -622,8 +611,8 @@
 	SelectObject( hdc, STOCK_BLACK_PEN );
 	SelectObject( hdc, STOCK_WHITE_BRUSH );
 	SelectObject( hdc, STOCK_SYSTEM_FONT );
-	XFreeGC( display, dc->u.x.gc );
         if (dc->w.flags & DC_MEMORY) DeleteObject( dc->w.hFirstBitmap );
+        if (dc->funcs->pDeleteDC) dc->funcs->pDeleteDC(dc);
     }
 
     if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
diff --git a/objects/font.c b/objects/font.c
index 5cdfd38..615569f 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -64,7 +64,7 @@
 /***********************************************************************
  *           FONT_Init
  */
-BOOL FONT_Init( void )
+BOOL32 FONT_Init( void )
 {
   char  temp[1024];
   LPSTR ptr;
@@ -480,9 +480,9 @@
 
 
 /***********************************************************************
- *           FONT_GetObject
+ *           FONT_GetObject16
  */
-int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
+INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer )
 {
     if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
     memcpy( buffer, &font->logfont, count );
@@ -491,9 +491,39 @@
 
 
 /***********************************************************************
+ *           FONT_GetObject32A
+ */
+INT32 FONT_GetObject32A( FONTOBJ *font, INT32 count, LPSTR buffer )
+{
+    LOGFONT32A fnt32;
+
+    memset(&fnt32, 0, sizeof(fnt32));
+    fnt32.lfHeight         = font->logfont.lfHeight;
+    fnt32.lfWidth          = font->logfont.lfWidth;
+    fnt32.lfEscapement     = font->logfont.lfEscapement;
+    fnt32.lfOrientation    = font->logfont.lfOrientation;
+    fnt32.lfWeight         = font->logfont.lfWeight;
+    fnt32.lfItalic         = font->logfont.lfItalic;
+    fnt32.lfUnderline      = font->logfont.lfUnderline;
+    fnt32.lfStrikeOut      = font->logfont.lfStrikeOut;
+    fnt32.lfCharSet        = font->logfont.lfCharSet;
+    fnt32.lfOutPrecision   = font->logfont.lfOutPrecision;
+    fnt32.lfClipPrecision  = font->logfont.lfClipPrecision;
+    fnt32.lfQuality        = font->logfont.lfQuality;
+    fnt32.lfPitchAndFamily = font->logfont.lfPitchAndFamily;
+    strncpy( fnt32.lfFaceName, font->logfont.lfFaceName,
+             sizeof(fnt32.lfFaceName) );
+
+    if (count > sizeof(fnt32)) count = sizeof(fnt32);
+    memcpy( buffer, &fnt32, count );
+    return count;
+}
+
+
+/***********************************************************************
  *           FONT_SelectObject
  */
-HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
+HFONT16 FONT_SelectObject( DC * dc, HFONT16 hfont, FONTOBJ * font )
 {
     static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
 
@@ -749,20 +779,19 @@
 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
                               LPSIZE32 size )
 {
-    int dir, ascent, descent;
-    XCharStruct info;
-
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return FALSE;
-    XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
-		  &ascent, &descent, &info );
-    size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
-		    * dc->w.WndExtX / dc->w.VportExtX);
-    size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
-		    * dc->w.WndExtY / dc->w.VportExtY);
+    if (!dc)
+    {
+	if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
+            return FALSE;
+    }
 
-    dprintf_font(stddeb,"GetTextExtentPoint(%08x '%*.*s' %d %p): returning %d,%d\n",
-		 hdc, count, count, str, count, size, size->cx, size->cy );
+    if (!dc->funcs->pGetTextExtentPoint ||
+        !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
+        return FALSE;
+
+    dprintf_font(stddeb,"GetTextExtentPoint(%08x '%.*s' %d %p): returning %d,%d\n",
+		 hdc, count, str, count, size, size->cx, size->cy );
     return TRUE;
 }
 
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index d36acda..7686405 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -32,96 +32,96 @@
 
 static BRUSHOBJ WhiteBrush =
 {
-    { 0, BRUSH_MAGIC, 1, 0 },          /* header */
+    { 0, BRUSH_MAGIC, 1 },             /* header */
     { BS_SOLID, RGB(255,255,255), 0 }  /* logbrush */
 };
 
 static BRUSHOBJ LtGrayBrush =
 {
-    { 0, BRUSH_MAGIC, 1, 0 },          /* header */
+    { 0, BRUSH_MAGIC, 1 },             /* header */
     { BS_SOLID, RGB(192,192,192), 0 }  /* logbrush */
 };
 
 static BRUSHOBJ GrayBrush =
 {
-    { 0, BRUSH_MAGIC, 1, 0 },          /* header */
+    { 0, BRUSH_MAGIC, 1 },             /* header */
     { BS_SOLID, RGB(128,128,128), 0 }  /* logbrush */
 };
 
 static BRUSHOBJ DkGrayBrush =
 {
-    { 0, BRUSH_MAGIC, 1, 0 },       /* header */
+    { 0, BRUSH_MAGIC, 1 },          /* header */
     { BS_SOLID, RGB(64,64,64), 0 }  /* logbrush */
 };
 
 static BRUSHOBJ BlackBrush =
 {
-    { 0, BRUSH_MAGIC, 1, 0 },    /* header */
+    { 0, BRUSH_MAGIC, 1 },       /* header */
     { BS_SOLID, RGB(0,0,0), 0 }  /* logbrush */
 };
 
 static BRUSHOBJ NullBrush =
 {
-    { 0, BRUSH_MAGIC, 1, 0 },  /* header */
-    { BS_NULL, 0, 0 }          /* logbrush */
+    { 0, BRUSH_MAGIC, 1 },  /* header */
+    { BS_NULL, 0, 0 }       /* logbrush */
 };
 
 static PENOBJ WhitePen =
 {
-    { 0, PEN_MAGIC, 1, 0 },                  /* header */
+    { 0, PEN_MAGIC, 1 },                     /* header */
     { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
 };
 
 static PENOBJ BlackPen =
 {
-    { 0, PEN_MAGIC, 1, 0 },            /* header */
+    { 0, PEN_MAGIC, 1 },               /* header */
     { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
 };
 
 static PENOBJ NullPen =
 {
-    { 0, PEN_MAGIC, 1, 0 },   /* header */
+    { 0, PEN_MAGIC, 1 },      /* header */
     { PS_NULL, { 1, 0 }, 0 }  /* logpen */
 };
 
 static FONTOBJ OEMFixedFont =
 {
-    { 0, FONT_MAGIC, 1, 0 },   /* header */
+    { 0, FONT_MAGIC, 1 },   /* header */
     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
 };
 
 static FONTOBJ AnsiFixedFont =
 {
-    { 0, FONT_MAGIC, 1, 0 },   /* header */
+    { 0, FONT_MAGIC, 1 },   /* header */
     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
 };
 
 static FONTOBJ AnsiVarFont =
 {
-    { 0, FONT_MAGIC, 1, 0 },   /* header */
+    { 0, FONT_MAGIC, 1 },   /* header */
     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
 };
 
 static FONTOBJ SystemFont =
 {
-    { 0, FONT_MAGIC, 1, 0 },   /* header */
+    { 0, FONT_MAGIC, 1 },   /* header */
     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
 };
 
 static FONTOBJ DeviceDefaultFont =
 {
-    { 0, FONT_MAGIC, 1, 0 },   /* header */
+    { 0, FONT_MAGIC, 1 },   /* header */
     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
 };
 
 static FONTOBJ SystemFixedFont =
 {
-    { 0, FONT_MAGIC, 1, 0 },   /* header */
+    { 0, FONT_MAGIC, 1 },   /* header */
     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
 };
@@ -159,6 +159,13 @@
 BOOL32 GDI_Init(void)
 {
     HPALETTE16 hpalette;
+    extern BOOL32 X11DRV_Init(void);
+
+    /* Initialize drivers */
+
+    if (!X11DRV_Init()) return FALSE;
+
+    /* Get default hook */
 
     defDCHookCallback = (FARPROC16)MODULE_GetEntryPoint(GetModuleHandle("USER"),
                                                         362  /* DCHook */ );
@@ -317,7 +324,7 @@
       case BITMAP_MAGIC: 
 	  return BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
       case FONT_MAGIC:
-	  return FONT_GetObject( (FONTOBJ *)ptr, count, buffer );
+	  return FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
       case PALETTE_MAGIC:
 	  return PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
     }
@@ -344,9 +351,10 @@
     {
       case BITMAP_MAGIC: 
 	  return BITMAP_GetObject32( (BITMAPOBJ *)ptr, count, buffer );
+      case FONT_MAGIC:
+	  return FONT_GetObject32A( (FONTOBJ *)ptr, count, buffer );
       case PEN_MAGIC:
       case BRUSH_MAGIC: 
-      case FONT_MAGIC:
       case PALETTE_MAGIC:
           fprintf( stderr, "GetObject32: magic %04x not implemented\n",
                    ptr->wMagic );
diff --git a/objects/metafile.c b/objects/metafile.c
index 37d0b56..b273a54 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -1261,7 +1261,7 @@
     *(mr->rdParam + 1) = x;
     *(mr->rdParam + 2) = count;
     *(mr->rdParam + 3) = flags;
-    memcpy(mr->rdParam + 4, rect, sizeof(RECT16));
+    if (rect) memcpy(mr->rdParam + 4, rect, sizeof(RECT16));
     memcpy(mr->rdParam + 8, str, count);
     if (lpDx)
      memcpy(mr->rdParam + 8+ ((count + 1) >> 1),lpDx,count*sizeof(INT16));
diff --git a/objects/palette.c b/objects/palette.c
index ab8f25b..a4897ba 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -243,7 +243,7 @@
 /***********************************************************************
  *           PALETTE_UnrealizeObject
  */
-BOOL PALETTE_UnrealizeObject( HPALETTE16 hpalette, PALETTEOBJ *palette )
+BOOL32 PALETTE_UnrealizeObject( HPALETTE16 hpalette, PALETTEOBJ *palette )
 {
     if (palette->mapping)
     {
@@ -258,7 +258,7 @@
 /***********************************************************************
  *           PALETTE_DeleteObject
  */
-BOOL PALETTE_DeleteObject( HPALETTE16 hpalette, PALETTEOBJ *palette )
+BOOL32 PALETTE_DeleteObject( HPALETTE16 hpalette, PALETTEOBJ *palette )
 {
     free( palette->mapping );
     return GDI_FreeObject( hpalette );
diff --git a/tools/build.c b/tools/build.c
index cdd1544..76de29e 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -31,7 +31,7 @@
     TYPE_LONG,         /* long variable */
     TYPE_PASCAL_16,    /* pascal function with 16-bit return (Win16) */
     TYPE_PASCAL,       /* pascal function with 32-bit return (Win16) */
-    TYPE_REGISTER,     /* register function (Win16) */
+    TYPE_REGISTER,     /* register function */
     TYPE_ABS,          /* absolute value */
     TYPE_RETURN,       /* simple return value function */
     TYPE_STUB,         /* unimplemented stub */
@@ -131,10 +131,13 @@
 
 static int debugging = 1;
 
-  /* Offset of register relative to the end of the context struct */
-#define CONTEXTOFFSET(reg) \
+  /* Offset of register relative to the end of the SIGCONTEXT struct */
+#define SIGCONTEXTOFFSET(reg) \
     ((int)&reg##_reg((SIGCONTEXT *)0) - sizeof(SIGCONTEXT))
 
+  /* Offset of register relative to the start of the CONTEXT struct */
+#define CONTEXTOFFSET(reg) ((int)&((CONTEXT *)0)->reg)
+
 static void *xmalloc (size_t size)
 {
     void *res;
@@ -970,13 +973,15 @@
         case TYPE_STDCALL:
         case TYPE_CDECL:
         case TYPE_STUB:
+        case TYPE_REGISTER:
             printf( "/* %s.%d (%s) */\n",
                      DLLName, i, odp->name);
             printf( "%s_%d:\n", DLLName, i );
             printf( "\tpushl %%ebp\n" );
             printf( "\tpushl $" PREFIX "%s\n", odp->u.func.link_name );
             printf( "\tcall " PREFIX "CallFrom32_%s_%d\n",
-                    (odp->type == TYPE_STDCALL) ? "stdcall" : "cdecl",
+                    (odp->type == TYPE_REGISTER) ? "regs" :
+                    ((odp->type == TYPE_STDCALL) ? "stdcall" : "cdecl"),
                     strlen(odp->u.func.arg_types));
             printf( "\tnop\n" );
             break;
@@ -1409,13 +1414,13 @@
 
 
 /*******************************************************************
- *         BuildContext
+ *         BuildContext16
  *
  * Build the context structure on the 32-bit stack.
  * The only valid registers in the context structure are:
  *   eax, ebx, ecx, edx, esi, edi, ds, es, (some of the) flags
  */
-static void BuildContext(void)
+static void BuildContext16(void)
 {
     /* Save ebx first */
 
@@ -1427,27 +1432,27 @@
 
     /* Store the registers */
 
-    printf( "\tpopl %d(%%ebx)\n", CONTEXTOFFSET(EBX) ); /* Get ebx from stack*/
-    printf( "\tmovl %%eax,%d(%%ebx)\n", CONTEXTOFFSET(EAX) );
-    printf( "\tmovl %%ecx,%d(%%ebx)\n", CONTEXTOFFSET(ECX) );
-    printf( "\tmovl %%edx,%d(%%ebx)\n", CONTEXTOFFSET(EDX) );
-    printf( "\tmovl %%esi,%d(%%ebx)\n", CONTEXTOFFSET(ESI) );
-    printf( "\tmovl %%edi,%d(%%ebx)\n", CONTEXTOFFSET(EDI) );
+    printf( "\tpopl %d(%%ebx)\n", SIGCONTEXTOFFSET(EBX) ); /* Get ebx from stack*/
+    printf( "\tmovl %%eax,%d(%%ebx)\n", SIGCONTEXTOFFSET(EAX) );
+    printf( "\tmovl %%ecx,%d(%%ebx)\n", SIGCONTEXTOFFSET(ECX) );
+    printf( "\tmovl %%edx,%d(%%ebx)\n", SIGCONTEXTOFFSET(EDX) );
+    printf( "\tmovl %%esi,%d(%%ebx)\n", SIGCONTEXTOFFSET(ESI) );
+    printf( "\tmovl %%edi,%d(%%ebx)\n", SIGCONTEXTOFFSET(EDI) );
     printf( "\tmovw -10(%%ebp),%%ax\n" );  /* Get saved ds from stack */
-    printf( "\tmovw %%ax,%d(%%ebx)\n", CONTEXTOFFSET(DS) );
+    printf( "\tmovw %%ax,%d(%%ebx)\n", SIGCONTEXTOFFSET(DS) );
     printf( "\tmovw -6(%%ebp),%%ax\n" );  /* Get saved es from stack */
-    printf( "\tmovw %%ax,%d(%%ebx)\n", CONTEXTOFFSET(ES) );
+    printf( "\tmovw %%ax,%d(%%ebx)\n", SIGCONTEXTOFFSET(ES) );
     printf( "\tpushfl\n" );
-    printf( "\tpopl %d(%%ebx)\n", CONTEXTOFFSET(EFL) );
+    printf( "\tpopl %d(%%ebx)\n", SIGCONTEXTOFFSET(EFL) );
 }
 
 
 /*******************************************************************
- *         RestoreContext
+ *         RestoreContext16
  *
  * Restore the registers from the context structure
  */
-static void RestoreContext(void)
+static void RestoreContext16(void)
 {
     /* Get the 32-bit stack pointer */
 
@@ -1455,18 +1460,18 @@
 
     /* Restore the registers */
 
-    printf( "\tmovl %d(%%ebx),%%ecx\n", CONTEXTOFFSET(ECX) );
-    printf( "\tmovl %d(%%ebx),%%edx\n", CONTEXTOFFSET(EDX) );
-    printf( "\tmovl %d(%%ebx),%%esi\n", CONTEXTOFFSET(ESI) );
-    printf( "\tmovl %d(%%ebx),%%edi\n", CONTEXTOFFSET(EDI) );
+    printf( "\tmovl %d(%%ebx),%%ecx\n", SIGCONTEXTOFFSET(ECX) );
+    printf( "\tmovl %d(%%ebx),%%edx\n", SIGCONTEXTOFFSET(EDX) );
+    printf( "\tmovl %d(%%ebx),%%esi\n", SIGCONTEXTOFFSET(ESI) );
+    printf( "\tmovl %d(%%ebx),%%edi\n", SIGCONTEXTOFFSET(EDI) );
     printf( "\tpopl %%eax\n" );  /* Remove old ds and ip from stack */
     printf( "\tpopl %%eax\n" );  /* Remove old cs and es from stack */
-    printf( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(DS) ); /* Push new ds */
-    printf( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(ES) ); /* Push new es */
-    printf( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(EFL) );
+    printf( "\tpushw %d(%%ebx)\n", SIGCONTEXTOFFSET(DS) ); /* Push new ds */
+    printf( "\tpushw %d(%%ebx)\n", SIGCONTEXTOFFSET(ES) ); /* Push new es */
+    printf( "\tpushl %d(%%ebx)\n", SIGCONTEXTOFFSET(EFL) );
     printf( "\tpopfl\n" );
-    printf( "\tmovl %d(%%ebx),%%eax\n", CONTEXTOFFSET(EAX) );
-    printf( "\tmovl %d(%%ebx),%%ebx\n", CONTEXTOFFSET(EBX) );
+    printf( "\tmovl %d(%%ebx),%%eax\n", SIGCONTEXTOFFSET(EAX) );
+    printf( "\tmovl %d(%%ebx),%%ebx\n", SIGCONTEXTOFFSET(EBX) );
 }
 
 
@@ -1551,7 +1556,7 @@
 
     /* Transfer the arguments */
 
-    if (reg_func) BuildContext();
+    if (reg_func) BuildContext16();
     else if (*args) argsize = TransferArgs16To32( args );
 
     /* Get the address of the API function */
@@ -1624,7 +1629,7 @@
     if (reg_func)
     {
         /* Restore registers from the context structure */
-        RestoreContext();
+        RestoreContext16();
         
         /* Calc the arguments size */
         while (*args)
@@ -1919,6 +1924,91 @@
 
 
 /*******************************************************************
+ *         BuildContext32
+ *
+ * Build the context structure on the stack.
+ */
+static void BuildContext32(void)
+{
+    /* Build the context structure */
+
+    printf( "\tpushfl\n" );
+    printf( "\tsubl $%d,%%esp\n", sizeof(CONTEXT) );
+    printf( "\tmovl %%eax,%d(%%esp)\n", CONTEXTOFFSET(Eax) );
+    printf( "\tmovl %%ebx,%d(%%esp)\n", CONTEXTOFFSET(Ebx) );
+    printf( "\tmovl %%ecx,%d(%%esp)\n", CONTEXTOFFSET(Ecx) );
+    printf( "\tmovl %%edx,%d(%%esp)\n", CONTEXTOFFSET(Edx) );
+    printf( "\tmovl %%esi,%d(%%esp)\n", CONTEXTOFFSET(Esi) );
+    printf( "\tmovl %%edi,%d(%%esp)\n", CONTEXTOFFSET(Edi) );
+
+    printf( "\tmovl %d(%%esp),%%eax\n", sizeof(CONTEXT) );
+    printf( "\tmovl %%eax,%d(%%esp)\n", CONTEXTOFFSET(EFlags) );
+
+    printf( "\tmovl %%cs,%d(%%esp)\n", CONTEXTOFFSET(SegCs) );
+    printf( "\tmovl %%ds,%d(%%esp)\n", CONTEXTOFFSET(SegDs) );
+    printf( "\tmovl %%es,%d(%%esp)\n", CONTEXTOFFSET(SegEs) );
+    printf( "\tmovl %%fs,%d(%%esp)\n", CONTEXTOFFSET(SegFs) );
+    printf( "\tmovl %%gs,%d(%%esp)\n", CONTEXTOFFSET(SegGs) );
+    printf( "\tmovl %%ss,%d(%%esp)\n", CONTEXTOFFSET(SegSs) );
+
+    printf( "\tfsave %d(%%esp)\n", CONTEXTOFFSET(FloatSave) );
+
+    printf( "\tmovl 4(%%ebp),%%eax\n" ); /* %eip at time of call */
+    printf( "\tmovl %%eax,%d(%%esp)\n", CONTEXTOFFSET(Eip) );
+    printf( "\tmovl 0(%%ebp),%%eax\n" ); /* %ebp at time of call */
+    printf( "\tmovl %%eax,%d(%%esp)\n", CONTEXTOFFSET(Ebp) );
+    printf( "\tleal 8(%%ebp),%%eax\n" ); /* %esp at time of call */
+    printf( "\tmovl %%eax,%d(%%esp)\n", CONTEXTOFFSET(Esp) );
+
+    /* Push pointer to context */
+
+    printf( "\tpushl %%esp\n" );
+}
+
+
+/*******************************************************************
+ *         RestoreContext32
+ *
+ * Restore the registers from the context structure
+ */
+static void RestoreContext32(void)
+{
+    /* Restore the context structure */
+
+    printf( "\tleal %d(%%ebp),%%esp\n", -sizeof(CONTEXT)-12 );
+    printf( "\tfrstor %d(%%esp)\n", CONTEXTOFFSET(FloatSave) );
+
+    printf( "\tmovl %d(%%esp),%%ebx\n", CONTEXTOFFSET(Ebx) );
+    printf( "\tmovl %d(%%esp),%%ecx\n", CONTEXTOFFSET(Ecx) );
+    printf( "\tmovl %d(%%esp),%%edx\n", CONTEXTOFFSET(Edx) );
+    printf( "\tmovl %d(%%esp),%%esi\n", CONTEXTOFFSET(Esi) );
+    printf( "\tmovl %d(%%esp),%%edi\n", CONTEXTOFFSET(Edi) );
+
+    printf( "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(EFlags) );
+    printf( "\tmovl %%eax,%d(%%esp)\n", sizeof(CONTEXT) );
+
+/*    printf( "\tmovl %d(%%esp),%%cs\n", CONTEXTOFFSET(SegCs) ); */
+    printf( "\tmovl %d(%%esp),%%ds\n", CONTEXTOFFSET(SegDs) );
+    printf( "\tmovl %d(%%esp),%%es\n", CONTEXTOFFSET(SegEs) );
+    printf( "\tmovl %d(%%esp),%%fs\n", CONTEXTOFFSET(SegFs) );
+    printf( "\tmovl %d(%%esp),%%gs\n", CONTEXTOFFSET(SegGs) );
+
+    printf( "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(Eip) );
+    printf( "\tmovl %%eax,4(%%ebp)\n" ); /* %eip at time of call */
+    printf( "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(Ebp) );
+    printf( "\tmovl %%eax,0(%%ebp)\n" ); /* %ebp at time of call */
+
+/*    printf( "\tmovl %d(%%esp),%%ss\n", CONTEXTOFFSET(SegSs) ); */
+/*    printf( "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(Esp) ); */
+
+    printf( "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(Eax) );
+
+    printf( "\taddl $%d,%%esp\n", sizeof(CONTEXT) );
+    printf( "\tpopfl\n" );
+}
+
+
+/*******************************************************************
  *         BuildCallFrom32Func
  *
  * Build a 32-bit-to-Wine call-back function.
@@ -1931,22 +2021,28 @@
  * (ebp+4)   ret addr
  * (ebp)     ebp
  * (ebp-4)   entry point
- * (ebp-8)   func name
+ * (ebp-8)   relay addr
  */
 static void BuildCallFrom32Func( const char *profile )
 {
-    int args, stdcall;
+    int args, stdcall, reg_func;
 
     if (!strncmp( profile, "stdcall", 7 ))
     {
         stdcall = 1;
+        reg_func = 0;
         args = atoi( profile + 8 );
     }
     else if (!strncmp( profile, "cdecl", 5 ))
     {
-        stdcall = 0;
+        stdcall = reg_func = 0;
         args = atoi( profile + 6 );
     }
+    else if (!strncmp( profile, "regs", 4 ))
+    {
+        stdcall = reg_func = 1;
+        args = atoi( profile + 5 );
+    }
     else
     {
         fprintf( stderr, "Invalid function profile '%s'\n", profile );
@@ -1966,23 +2062,16 @@
 
     printf( "\tleal 8(%%esp),%%ebp\n" );
 
-    /* Print the debugging info */
-
-    if (debugging)
-    {
-        printf( "\tpushl $%d\n", args );
-        printf( "\tcall " PREFIX "RELAY_DebugCallFrom32\n" );
-        printf( "\tadd $4, %%esp\n" );
-    }
-
     /* Transfer the arguments */
 
+    if (reg_func) BuildContext32();
+
     if (args)
     {
         int i;
         for (i = args; i > 0; i--) printf( "\tpushl %d(%%ebp)\n", 4 * i + 4 );
     }
-    else
+    else if (!reg_func)
     {
         /* Push the address of the arguments. The called function will */
         /* ignore this if it really takes no arguments. */
@@ -1990,6 +2079,16 @@
         printf( "\tpushl %%eax\n" );
     }
 
+    /* Print the debugging info */
+
+    if (debugging)
+    {
+        printf( "\tpushl $%d\n", reg_func ? -1 : args );  /* Nb args */
+        printf( "\tpushl %%ebp\n" );
+        printf( "\tcall " PREFIX "RELAY_DebugCallFrom32\n" );
+        printf( "\tadd $8, %%esp\n" );
+    }
+
     /* Call the function */
 
     printf( "\tcall -4(%%ebp)\n" );
@@ -1998,12 +2097,17 @@
 
     if (debugging)
     {
-        printf( "\tadd $%d,%%esp\n", args ? (args * 4) : 4 );
         printf( "\tpushl %%eax\n" );
+        printf( "\tpushl $%d\n", reg_func ? -1 : args );  /* Nb args */
+        printf( "\tpushl %%ebp\n" );
         printf( "\tcall " PREFIX "RELAY_DebugCallFrom32Ret\n" );
         printf( "\tpopl %%eax\n" );
+        printf( "\tpopl %%eax\n" );
+        printf( "\tpopl %%eax\n" );
     }
 
+    if (reg_func) RestoreContext32();
+
     printf( "\tmovl %%ebp,%%esp\n" );
     printf( "\tpopl %%ebp\n" );
 
diff --git a/tools/wineconf b/tools/wineconf
new file mode 100755
index 0000000..9610366
--- /dev/null
+++ b/tools/wineconf
@@ -0,0 +1,418 @@
+#!/usr/bin/perl
+
+# This program generates wine.conf files on STDOUT.
+# (C) 1996 Stephen Simmons
+# Redistributable under Wine License
+
+$RCS_ID = '$Id$ ';
+
+# This program examines the contents of the DOS filesystems and
+# attempts to generate a sensible wine.conf file.  This is output
+# to STDOUT.
+# It reads /etc/FSTAB to find mounting locations of the hard disk drives
+# It uses the correct algorithm for ordering DOS drives, with the
+# exception of the case of multiple drive controller types, where I don't
+# know what DOS's algorithm is.
+# It uses find to find all of the win.ini files on any DOS partition
+# and sorts them by age to guess which is part of the active Windows
+# installation.
+# It reads the autoexec.bat file (if found) and records all variable
+# settings.   There are some inaccuracies in its determination.
+# First, while variables are interpolated properly, no control
+# structures are supported so calls and execs to other batch files are
+# ignored, and all variable settings take effect regardless of whether
+# they would in DOS (i,e., both if and else clauses are read).
+# This is used to determine the path and temp directories.  Duplicate
+# path directories and path directories that don't exist are thrown
+# out.
+# On failing to find C:\AUTOEXEC.BAT, wineconf finds all executables
+# in the windows directory and subdirectories, and generates an
+# optimized path statement encompassing all the executables.
+# Then it also looks for \TEMP and \TMP on all drives taking the first
+# one it finds.
+# wineconf doesn't support floppy drives, network drives, printers,
+# and serial device configuration is hardcoded and not configured for
+# the machine it runs on.  Similarly, spy parameters are hard coded.
+
+# It would make sense to incorporate much of the hueristic code in
+# this program into a library to be shared with a dosemu configuration
+# program, because it seems that at least some of the same stuff will
+# be wanted.  The program needs to be cleaned up still.  A better tmp
+# search algorithm could be written.  A fast option is planned.  Less
+# Linux-dependence is desired.  Should look for devices independent
+# of /etc/fstab; then sanity checks on /etc/fstab can be performed.
+
+use Getopt::Long;
+use File::Basename;
+use Carp;
+
+GetOptions('windir=s', 'sysdir=s', 'thorough', 'debug:s') || &Usage;
+
+&ReadFSTAB();
+&FindWindowsDir();
+&ReadAutoexecBat();
+&StandardStuff();
+
+sub Usage {
+    print "Usage: $0 <options>\n";
+#    print "-fstab <filename>    Location of alternate fstab file\n";
+    print "-windir <filename>   Location of windows dir in DOS space\n";
+    print "-thorough            Do careful analysis (default)\n";
+    print "-sysdir <filename>   Location of systems dir in DOS space\n";
+#    print "-tmpdir <filename>   Location of tmp directory\n";
+    print "Generates (to STDOUT) a wine configuration file based on\n";
+    print "/etc/fstab and searching around in DOS directories\n";
+    print "The options above can override certain values\n";
+    print "This should be considered ALPHA code\n";
+    exit(0);
+}
+
+sub ReadFSTAB {
+    $opt_f = $opt_f ? $opt_f : '/etc/fstab';
+    open(FSTAB, $opt_f) || die "Cannot read $opt_f\n";
+    while(<FSTAB>) {
+	next if /^\s*\#/;
+	next if /^\s*$/;
+	($device, $mntpoint, $type, @rest) = split(' ', $_);
+	if ($type eq "msdos") {
+	    push(@FatDrives, [$device, $mntpoint]);
+	}
+	elsif ($type eq "iso9660") {
+	    push(@CdromDrives, [$device, $mntpoint]);
+	}
+    }
+    if (!@FatDrives) {
+	warn "ERROR ($0): Cannot find any MSDOS drives.\n";
+	warn "This does not mean you cannot run Wine, but $0\n";
+	warn "cannot help you (yet)\n";
+	exit(1);
+    }
+    $MagicDrive = 'C';
+    @FatDrives = sort byDriveOrder @FatDrives;
+    @CdromDrives = sort byCdOrder @CdromDrives;
+    foreach $FatDrive (@FatDrives) {
+	print "[Drive $MagicDrive]\n";
+	$MntPoint = $FatDrive->[1];
+	print "Path=$MntPoint\n";
+	print "Type=hd\n";
+	print "\n";
+	&RegisterDrive($MagicDrive, $FatDrive);
+	if(!&IsMounted($FatDrive->[0])) {
+	    warn "WARNING: DOS Drive $MagicDrive (" . $FatDrive->[0] . 
+		") is not mounted\n";
+	}
+	$MagicDrive++;
+    }
+    foreach $CdromDrive (@CdromDrives) {
+	print "[Drive $MagicDrive]\n";
+	$MntPoint = $CdromDrive->[1];
+	print "Path=$MntPoint\n";
+	print "Type=cdrom\n";
+	print "\n";
+	&RegisterDrive($MagicDrive, $CdromDrive);
+	$MagicDrive++;
+    }
+}
+
+sub FindWindowsDir {
+    my($MagicDrive) = 'C';
+    my(@FATD)=@FatDrives;
+    my(@wininis) = ();
+    if (!$opt_windir && !$opt_fast && !$opt_thorough) {
+	$opt_thorough++;
+    }
+    if ($opt_windir) {
+	$winini = &ToUnix($opt_windir);
+	if (!-e $winini) {
+	    die "ERROR: Specified winini file does not exist\n";
+	}
+    }
+    elsif ($opt_fast) {
+	die "-fast code can be implemented\n";
+    }
+    elsif ($opt_thorough) {
+	if ($opt_debug) { print STDERR "DEBUG: Num FATD = ", $#FATD+1, "\n"; }
+	foreach(@FATD) {
+	    $ThisDrive = shift(@FATD);
+	    $MntPoint = $ThisDrive->[1];
+	    push(@wininis, `find $MntPoint -name win.ini -print`);
+	}
+	foreach $winini (@wininis) {
+	    chomp $winini;
+	}
+	my($winini_cnt) = $#wininis+1;
+	if ($opt_debug) { 
+	    print STDERR "DEBUG: Num wininis found: $winini_cnt\n";}
+	if ($winini_cnt > 1) {
+	    warn "$winini_cnt win.ini files found:\n";
+	    @wininis = sort byFileAge @wininis;
+	    warn join("\n", @wininis), "\n";
+	    $winini = $wininis[0];
+	    warn "Using most recent one: $winini\n";
+	}
+	elsif ($winini_cnt == 0) {
+	    die "ERROR: No win.ini found in DOS partitions\n";
+	}
+	else {
+	    $winini = $wininis[0];
+	}
+    }
+    else {
+	die "ERROR: None of -windir, -fast, or -thorough set\n";
+    }
+    $windir = &ToDos(dirname($winini));
+    print "[wine]\n";
+    print "windows=$windir\n";
+    if ($opt_sysdir) {
+	print "system=$opt_sysdir\n";
+    }
+    else {
+	print "system=$windir\\SYSTEM\n";
+    }
+}
+
+# Returns 1 if the device is mounted; -1 if mount check failed; 0 if not
+# mounted.
+# This code is Linux specific, and needs to be broadened.
+sub IsMounted {
+    my($Device) = @_;
+    if (-d "/proc") {
+	if (-e "/proc/mounts") {
+	    open(MOUNTS, "/proc/mounts") || 
+		(warn "Cannot open /proc/mounts, although it exists\n" &&
+		 return -1);
+	    while(<MOUNTS>) {
+		if (/^$Device/) { 
+		    return 1; # Tested 1.4
+		}
+	    }
+	    return 0; # Tested 1.4
+	}
+    }
+    return -1;
+}
+
+sub RegisterDrive {
+    my($DOSdrive, $Drive) = @_;
+    $DOS2Unix{$DOSdrive} = $Drive;
+    $Device2DOS{$Drive->[0]} = $DOSdrive;
+    $MntPoint2DOS{$Drive->[1]} = $DOSdrive;
+    $DOS2MntPoint{$DOSdrive} = $Drive->[1];
+    $DOS2Device{$DOSdrive} = $Drive->[0];
+}
+
+sub ReadAutoexecBat {
+    if (!%DOS2Unix) { &ReadFSTAB; }
+    my($DriveC) = $DOS2MntPoint{"C"};
+    $DriveC =~ s%/$%%;
+    my($path);
+    if ($opt_debug) { 
+	print STDERR "DEBUG: Looking for $DriveC/autoexec.bat\n"; }
+    if (-e "$DriveC/autoexec.bat") {
+	# Tested 1.4
+        open(AUTOEXEC, "$DriveC/autoexec.bat") || 
+            die "Cannot read autoexec.bat\n";
+        while(<AUTOEXEC>) {
+	    s/\015//;
+            if (/^\s*(set\s+)?(\w+)\s*[\s\=]\s*(.*)$/i) {
+		my($varname) = $2;
+	        my($varvalue) = $3;
+		chomp($varvalue);
+		$varname =~ tr/A-Z/a-z/;
+		while ($varvalue =~ /%(\w+)%/) {
+		    $matchname = $subname = $1;
+		    $subname =~ tr/A-Z/a-z/;
+		    if ($opt_debug =~ /path/i) {
+			print STDERR "DEBUG: Found $matchname as $subname\n";
+			print STDERR "DEBUG: Old varvalue:\n$varvalue\n";
+			print STDERR "DEBUG: Old subname value:\n" .
+			    $DOSenv{$subname} . "\n";
+		    }
+		    if ($DOSenv{$subname}) {
+			$varvalue =~ s/\%$matchname\%/$DOSenv{$subname}/;
+		    }
+		    else {
+			warn "DOS environment variable $subname not\n"; 
+			warn "defined in autoexec.bat. (Reading config.sys\n";
+			warn "is not implemented.)  Using null value\n";
+			$varvalue =~ s/%$matchname%//;
+		    }
+		    if ($opt_debug =~ /path/i) {
+			print STDERR "DEBUG: New varvalue:\n$varvalue\n";
+		    }
+		}
+		if ($opt_debug) {
+		    print STDERR "DEBUG: $varname = $varvalue\n";
+		}
+		$DOSenv{$varname} = $varvalue;
+            }
+        }
+	close(AUTOEXEC);
+    }
+    else {
+	# Tested 1.4
+	warn "WARNING: C:\AUTOEXEC.BAT was not found.\n";
+    }
+
+    if ($DOSenv{"path"}) {
+	@pathdirs = split(/\s*;\s*/, $DOSenv{"path"});
+	if ($opt_debug =~ /path/i) {
+	    print STDERR "DEBUG (path): @pathdirs\n";
+	}
+	foreach $pathdir (@pathdirs) {
+	    if (-d &ToUnix($pathdir)) {
+		if ($DOSpathdir{$pathdir}++) {
+		    warn "Ignoring duplicate DOS path entry $pathdir\n";
+		}
+		else {
+		    if ($opt_debug =~ /path/i) {
+			print STDERR "DEBUG (path): Found $pathdir\n";
+		    }
+		    push(@DOSpathlist, $pathdir);
+		}
+	    }
+	    else {
+	        warn "Ignoring DOS path directory $pathdir, as it does not\n";
+		warn "exist\n";
+	    }
+	}
+	print "path=" . join(";", @DOSpathlist) . "\n";
+    }
+    else {
+	# Code status: tested 1.4
+	warn "WARNING: Making assumptions for PATH\n";
+	warn "Will scan windows directory for executables and generate\n";
+	warn "path from that\n";
+	$shellcmd = 'find ' . &ToUnix($windir) . " -iregex '" .
+	    '.*\.\(exe\|bat\|com\|dll\)' . "' -print";
+	if ($opt_debug) { 
+	    print STDERR "DEBUG: autoexec.bat search command:\n $shellcmd\n";
+	}
+	push(@DOScommand, `$shellcmd`);
+	if ($opt_debug =~ /autoexec/i) { 
+	    print STDERR "DEBUG: autoexec.bat search results:\n@DOScommand\n";
+	}
+	foreach $command (@DOScommand) {
+	    $command =~ s%[^/]+$%%;
+	    $DOSexecdir{$command}++;
+	}
+	print "path=" . 
+	    join(";", 
+		 grep(s%/$%%, 
+		      sort {$DOSexecdir{$b} <=> $DOSexecdir{$a}}
+		      (keys %DOSexecdir))) . "\n";
+    }
+
+    if ($DOSenv{"temp"} && -d &ToUnix($DOSenv{"temp"})) {
+	print "temp=" . $DOSenv{"temp"} . "\n";
+    }
+    else {
+        warn "WARNING: Making assumptions for TEMP\n";
+	warn "Looking for \\TEMP and then \\TMP on every drive\n";
+	# Watch out .. might pick CDROM drive :-)
+	foreach $DOSdrive (keys %DOS2Unix) {
+	    $tmp = &ToUnix("$DOSdrive:\\temp");
+	    if (-d $tmp) { $TheTemp = "$DOSdrive:\\temp"; last; }
+	    $tmp = &ToUnix("$DOSdrive:\\tmp");
+	    if (-d $tmp) { $TheTemp = "$DOSdrive:\\tmp"; last; }
+	}
+	if ($TheTemp) {
+	    warn "Using $TheTemp\n";
+	    print "temp=$TheTemp\n";
+	}
+	else {
+	    warn "Using C:\\\n";
+	    print "temp=C:\\\n";
+	}
+    }
+    print "\n";
+}
+
+# FNunix = &ToUnix(FNdos);
+#   Converts DOS filenames to Unix filenames, leaving Unix filenames
+#   untouched.
+sub ToUnix {
+    my($FNdos) = @_;
+    my($FNunix);
+
+    # Initialize tables if necessary.
+    if (!%DOS2Unix) { &ReadFSTAB; }
+
+    # Determine which type of conversion is necessary
+    if ($FNdos =~ /^([A-Z])\:(.*)$/) { # DOS drive specified
+	$FNunix = $DOS2MntPoint{$1} . "/$2";
+    }
+    elsif ($FNdos =~ m%\\%) { # DOS drive not specified, C: is default
+	$FNunix = $DOS2MntPoint{"C"} . "/$FNdos";
+    }
+    else { # Unix filename
+	$FNunix = $FNdos;
+    }
+    1 while ($FNunix =~ s%\\%/%);    # Convert \ to /
+    $FNunix =~ tr/A-Z/a-z/;          # Translate to lower case
+    1 while ($FNunix =~ s%//%/%);    # Translate double / to /
+    return $FNunix;
+}
+
+# FNdos = &ToDOS(FNunix)
+#   Converts Unix filenames to DOS filenames
+sub ToDos {
+    my($FNunix) = @_;
+    my(@MntList) = keys %MntPoint2DOS;
+    foreach $MntPt (@MntList) { # Scan mount point list to see if path matches
+	if ($FNunix =~ /^$MntPt/) {
+	    $TheMntPt = $MntPt;
+	    last;
+	}
+    }
+    if (!$TheMntPt) {
+	Carp("ERROR: $FNunix not found in DOS directories\n");
+	exit(1);
+    }
+    $FNdos = $FNunix;
+    $FNdos =~ s/^$TheMntPt//;
+    $FNdos = $MntPoint2DOS{$TheMntPt} . ":" . $FNdos;
+    1 while($FNdos =~ s%/%\\%);
+    return $FNdos;
+}
+
+
+sub StandardStuff {
+    print "[serial]\n";
+    print "com1=/dev/cua0\n";
+    print "com2=/dev/cua1\n";
+    print "\n";
+    print "[spy]\n";
+    print ";File=CON\n";
+    print ";File=spy.log\n";
+    print "Exclude=WM_TIMER;WM_SETCURSOR;WM_MOUSEMOVE;WM_NCHITTEST;\n";
+    print "Include=WM_COMMAND;\n";
+}
+
+sub byFileAge {
+    -M $a <=> -M $b;
+}
+
+sub byDriveOrder {
+    my($DeviceA) = $a->[0];
+    my($DeviceB) = $b->[0];
+
+    # Primary drives come first, logical drives last
+    # DOS User's Guide (version 6) p. 70, IBM version.
+    # If both drives are the same type, sort alphabetically
+    # This makes drive a come before b, etc.
+    # It also makes SCSI drives come before IDE drives;
+    # this may or may not be right :-(
+    my($Alogical, $Blogical);
+    if (substr($DeviceA, 3, 1) >= 5) { $Alogical++; }
+    if (substr($DeviceB, 3, 1) >= 5) { $Blogical++; }
+    if ($Alogical && !$Blogical) { return -1; }
+    elsif ($Blogical && !$Alogical) { return 1; }
+    else { return ($DeviceA cmp $DeviceB); }
+}
+
+sub byCdOrder {
+    my($DeviceA) = $a->[0];
+    my($DeviceB) = $b->[0];
+    $DeviceA cmp $DeviceB;
+}
diff --git a/win32/error.c b/win32/error.c
index 8a8ac31..8f66793 100644
--- a/win32/error.c
+++ b/win32/error.c
@@ -117,6 +117,13 @@
     WIN32_LastError = error;
 }
 
+/**********************************************************************
+ *              SetLastErrorEx            (USER32.484)
+ */
+void SetLastErrorEx(DWORD error,DWORD type) {
+    WIN32_LastError = error;
+}
+
 DWORD ErrnoToLastError(int errno_num)
 {
     DWORD rc = ERROR_UNKNOWN;
diff --git a/win32/newfns.c b/win32/newfns.c
index 4ea3beb..9af9c00 100644
--- a/win32/newfns.c
+++ b/win32/newfns.c
@@ -40,3 +40,14 @@
 	fprintf(stdnimp, "UnhookWindowsHookEx32 Stub called!\n");
 	return FALSE;
 }
+
+/****************************************************************************
+ *		QueryPerformanceCounter (KERNEL32.415)
+ */
+BOOL32
+QueryPerformanceCounter(LPLARGE_INTEGER counter) {
+	/* FIXME: don't know what are good values */
+	counter->LowPart	= 1;
+	counter->HighPart	= 0;
+	return TRUE;
+}
diff --git a/windows/hook.c b/windows/hook.c
index a8bc38b..f29bf4b 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -51,7 +51,7 @@
     MESSAGEQUEUE *queue;
     HANDLE16 hook = 0;
 
-    if ((queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(hQueue) )) != NULL)
+    if ((queue = (MESSAGEQUEUE *)GlobalLock16( hQueue )) != NULL)
         hook = queue->hooks[id - WH_FIRST_HOOK];
     if (!hook) hook = HOOK_systemHooks[id - WH_FIRST_HOOK];
     return hook;
@@ -208,7 +208,7 @@
  */
 LRESULT HOOK_CallHooks( INT16 id, INT16 code, WPARAM16 wParam, LPARAM lParam )
 {
-    HANDLE16 hook = HOOK_GetHook( id , 0 );
+    HANDLE16 hook = HOOK_GetHook( id , GetTaskQueue(0) );
     if (!hook) return 0;
     return HOOK_CallHook( hook, code, wParam, lParam );
 }
diff --git a/windows/message.c b/windows/message.c
index 4d5b558..4624478 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -614,10 +614,10 @@
             {
                 BOOL32 ret;
                 *pmsg = *msg;
-                ret = (HOOK_CallHooks( WH_SYSMSGFILTER, code, 0,
-                                       (LPARAM)SEGPTR_GET(pmsg) ) ||
-                       HOOK_CallHooks( WH_MSGFILTER, code, 0,
-                                       (LPARAM)SEGPTR_GET(pmsg) ));
+                ret = ((BOOL16)HOOK_CallHooks( WH_SYSMSGFILTER, code, 0,
+                                               (LPARAM)SEGPTR_GET(pmsg) ) ||
+                       (BOOL16)HOOK_CallHooks( WH_MSGFILTER, code, 0,
+                                               (LPARAM)SEGPTR_GET(pmsg) ));
                 SEGPTR_FREE(pmsg);
                 if (ret)
                 {
diff --git a/windows/property.c b/windows/property.c
index 4b0796b..089d35b 100644
--- a/windows/property.c
+++ b/windows/property.c
@@ -63,8 +63,13 @@
 {
     PROPERTY *prop = PROP_FindProp( hwnd, str );
 
-    dprintf_prop( stddeb, "GetProp(%08x,'%s'): returning %08x\n",
-                  hwnd, str, prop ? prop->handle : 0 );
+    if (HIWORD(str))
+        dprintf_prop( stddeb, "GetProp(%08x,'%s'): returning %08x\n",
+                      hwnd, str, prop ? prop->handle : 0 );
+    else
+        dprintf_prop( stddeb, "GetProp(%08x,#%04x): returning %08x\n",
+                      hwnd, LOWORD(str), prop ? prop->handle : 0 );
+
     return prop ? prop->handle : 0;
 }
 
@@ -101,7 +106,12 @@
 {
     PROPERTY *prop;
 
-    dprintf_prop( stddeb, "SetProp: %04x '%s' %08x\n", hwnd, str, handle );
+    if (HIWORD(str))
+        dprintf_prop( stddeb, "SetProp: %04x '%s' %08x\n", hwnd, str, handle );
+    else
+        dprintf_prop( stddeb, "SetProp: %04x #%04x %08x\n",
+                      hwnd, LOWORD(str), handle );
+
     if (!(prop = PROP_FindProp( hwnd, str )))
     {
         /* We need to create it */
diff --git a/windows/win.c b/windows/win.c
index 95e7923..cbca5aa 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -1023,9 +1023,14 @@
 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
                        SEGPTR className, LPCSTR title )
 {
-    ATOM atom;
+    ATOM atom = 0;
 
-    atom = className ? GlobalFindAtom16( className ) : 0;
+    if (className)
+    {
+        /* If the atom doesn't exist, then no class */
+        /* with this name exists either. */
+        if (!(atom = GlobalFindAtom16( className ))) return 0;
+    }
     return WIN_FindWindow( parent, child, atom, title );
 }
 
@@ -1045,9 +1050,14 @@
 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
                         LPCSTR className, LPCSTR title )
 {
-    ATOM atom;
+    ATOM atom = 0;
 
-    atom = className ? GlobalFindAtom32A( className ) : 0;
+    if (className)
+    {
+        /* If the atom doesn't exist, then no class */
+        /* with this name exists either. */
+        if (!(atom = GlobalFindAtom32A( className ))) return 0;
+    }
     return WIN_FindWindow( 0, 0, atom, title );
 }
 
@@ -1058,11 +1068,16 @@
 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
                         LPCWSTR className, LPCWSTR title )
 {
-    ATOM atom;
+    ATOM atom = 0;
     char *buffer;
     HWND hwnd;
 
-    atom = className ? GlobalFindAtom32W( className ) : 0;
+    if (className)
+    {
+        /* If the atom doesn't exist, then no class */
+        /* with this name exists either. */
+        if (!(atom = GlobalFindAtom32W( className ))) return 0;
+    }
     buffer = title ? STRING32_DupUniToAnsi( title ) : NULL;
     hwnd = WIN_FindWindow( 0, 0, atom, buffer );
     if (buffer) free( buffer );