Release 960928

Fri Sep 27 14:18:42 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/button.c]
	Fixed focus rectangle size and clipping.

	* [controls/scroll.c]
	Converted to Win32 and added support for scroll page.
	Completed SetScrollInfo() and implemented other Win32 functions.

	* [files/file.c]
	Removed FILE_Read() (use _lread32 instead).

	* [objects/dce.c] [include/dce.h]
	Allocate DCE on the Win32 heap, and use pointers instead of
	handles.
	Implemented Win32 version of DC functions.

	* [windows/painting.c]
	Attempt to make CS_PARENTDC style work again.

Wed Sep 25 23:40:52 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [windows/dce.c] [windows/winpos.c]
	Override SaveUnder attribute when painting took place
	in a window below. Force X to raise activated window 
	in seamless mode.

	* [misc/clipboard.c] [windows/event.c]
	Translation between DOS and Unix text formats and several
	other fixes for the sudden selection loss.

	* [windows/message.c]
	Apply "first" and "last" when checking for WM_QUIT in 
        MSG_PeekMessage().

	* [windows/win.c]
	Rearranged DestroyWindow() to fit "Windows Internals"
	description.

	* [windows/win.c] [windows/winpos.c] [windows/nonclient.c]
	Misc. fixes to CBT hook calls.

	* [controls/menu.c] [misc/user.c]
	Fixup resident popup menu window so that it doesn't get
	destroyed by USER_AppExit().

	* [loader/module.c] [loader/task.c] [windows/event.c]
	Process "unsafe" X events outside the scheduler to prevent
	deadlocks.

	* [windows/message.c] [windows/queue.c] [windows/winpos.c]
	Lots of fixes for better Win16 multitasking.

Wed Sep 25 20:36:30 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [include/windows.h]
	Added some missing HOOK defines.

	* [misc/shell.c][if1632/shell32.spec][include/shell.h]
	SHGetFileInfoA stub added (win95 mplayer.exe /play bla.avi).

	* [win32/console.c][include/wincon.h]
	GetConsoleScreenBufferInfo, GetLargestConsoleWindowSize added.

	* [misc/registry.c]
	Some null ptr fixes.

	* [loader/pe_image.c]
	Fixed exported function lookup. (msvcrt20.dll)
	Add debugsyms for entrypoint, exported functions and sections.

	* [multimedia/mmsystem.c]
	MCIOpen: support for element opens (mplayer.exe /play bla.avi).

	* [several]
	Added several missing things/stubs/simple thunks from win32
	to win16 code.

Sat Sep 21 17:27:44 1996  O.Flebbe  <flebbe@science-computing.uni-tuebingen.de>

	* [windows/property.c]
	Fixed debugging of 16 Bit RemoveProp().

	* [debugger/memory.c]
	Added DEBUG_checkmap_bad() for linux.

Thu Sep 19 20:48:31 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [windows/event.c] [windows/hook.c]
	Use EnableHardwareInput() for JournalPlayback hook.

	* [controls/listbox.c]
	Changed handling of LB_GETITEMRECT in empty listboxes.

Thu Sep 19 13:34:35 1996  Slaven Rezic  <eserte@cs.tu-berlin.de>

	* [misc/main.c]
	Fixes to X resources handling.	

Wed Sep 18 00:31:15 1996  Huw D. M. Davies <h.davies1@physics.oxford.ac.uk>

	* [objects/metafile.c] [include/gdi.h] [objects/dc.c]
	Individual handle table created for each metafile. Fixed
 	GlobalReAlloc() bug in MF_AddHandleDC() (was MF_AddHandleInternal).

	* [windows/graphics.c] [objects/dc.c]
	Rectangle() changed to work better with wide pens and PS_NULL.
	Use JoinMiter.

	* [windows/winpos.c]
	Make the whole (non X) window invalid on resize if CS_[VH]REDRAW
 	is set.

	* [windows/nonclient.c]
	AdjustWindowRectEx() should perform calculations even if the
 	window is minimized.

	* [windows/mdi.c]
	Better handling of system button painting. Maximized windows can
 	contain scroll bars. Icons now maximize properly.

	* [windows/defwnd.c] [windows/nonclient.c] [controls/menu.c]
	Improved greying of items in system menu. WM_INITMEMUPOPUP no
 	longer caught in DefWndProc, DEFWND_InitSysMenuPopup moved to
 	menu.c.

Mon Sep 16 21:30:00 1996  Uwe Bonnes <bon@elektron.ikp.physik.th-darmstadt.de>

	* [several files]
	Fix missing includes and wrong printing arguments.

	* [controls/listbox.c]
	Don't sort drives in ListBoxDirectory().
	
Sat Sep 14 09:05:47 1996  Petri Tuomola <ptuomola@xs4all.nl>

	* [windows/dialog.c]
	Fixed handling of Shift-TAB in dialogs.

Thu Sep 12 18:31:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>

	* [if1632/gdi32.spec]
	Added SelectClipRgn - call win16 version.

	* [if1632/user32.spec]
	Added GetAsyncKeyState, GetMenuItemID and GetMenuStringA.

	* [include/wincon.h]
	Added COORD and SMALL_RECT typedefs, moved CONSOLE_SCREEN_BUFFER_INFO
	out of #if 0 protected portion of file.

	* [loader/pe_image.c]
	PE_InitTEB() - Tidy up, bug fix to stack pointer value (Borland
	programs now work better)

	* [win32/console.c]
	Added stub functions for GetConsoleScreenBufferInfo and 
	GetLargestConsoleWindowSize

	* [win32/findfile.c]
	FindFirstFile32A() - removed erroneous strcpy

	* [windows/keyboard.c]
	GetAsyncKeyState() - bug fix - now returns value as per Microsoft
	specification. NB - I still have doubts about some other functions
	in this file.
diff --git a/ANNOUNCE b/ANNOUNCE
index 0712204..9eb3ba9 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,12 +1,14 @@
-This is release 960913 of Wine, the MS Windows emulator.  This is still a
+This is release 960928 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-960913: (see ChangeLog for details)
-	- Better Win32 file handling.
+WHAT'S NEW with Wine-960928: (see ChangeLog for details)
+	- Intertask messaging improved.
+	- Many painting fixes.
+	- Still more Win32 support.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -15,10 +17,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-960913.tar.gz
-  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-960913.tar.gz
-  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-960913.tar.gz
-  ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-960913.tar.gz
+  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-960928.tar.gz
+  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-960928.tar.gz
+  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-960928.tar.gz
+  ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-960928.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index 4db62be..c508615 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,172 @@
 ----------------------------------------------------------------------
+Fri Sep 27 14:18:42 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [controls/button.c]
+	Fixed focus rectangle size and clipping.
+
+	* [controls/scroll.c]
+	Converted to Win32 and added support for scroll page.
+	Completed SetScrollInfo() and implemented other Win32 functions.
+
+	* [files/file.c]
+	Removed FILE_Read() (use _lread32 instead).
+
+	* [objects/dce.c] [include/dce.h]
+	Allocate DCE on the Win32 heap, and use pointers instead of
+	handles.
+	Implemented Win32 version of DC functions.
+
+	* [windows/painting.c]
+	Attempt to make CS_PARENTDC style work again.
+
+Wed Sep 25 23:40:52 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu>
+
+	* [windows/dce.c] [windows/winpos.c]
+	Override SaveUnder attribute when painting took place
+	in a window below. Force X to raise activated window 
+	in seamless mode.
+
+	* [misc/clipboard.c] [windows/event.c]
+	Translation between DOS and Unix text formats and several
+	other fixes for the sudden selection loss.
+
+	* [windows/message.c]
+	Apply "first" and "last" when checking for WM_QUIT in 
+        MSG_PeekMessage().
+
+	* [windows/win.c]
+	Rearranged DestroyWindow() to fit "Windows Internals"
+	description.
+
+	* [windows/win.c] [windows/winpos.c] [windows/nonclient.c]
+	Misc. fixes to CBT hook calls.
+
+	* [controls/menu.c] [misc/user.c]
+	Fixup resident popup menu window so that it doesn't get
+	destroyed by USER_AppExit().
+
+	* [loader/module.c] [loader/task.c] [windows/event.c]
+	Process "unsafe" X events outside the scheduler to prevent
+	deadlocks.
+
+	* [windows/message.c] [windows/queue.c] [windows/winpos.c]
+	Lots of fixes for better Win16 multitasking.
+
+Wed Sep 25 20:36:30 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [include/windows.h]
+	Added some missing HOOK defines.
+
+	* [misc/shell.c][if1632/shell32.spec][include/shell.h]
+	SHGetFileInfoA stub added (win95 mplayer.exe /play bla.avi).
+
+	* [win32/console.c][include/wincon.h]
+	GetConsoleScreenBufferInfo, GetLargestConsoleWindowSize added.
+
+	* [misc/registry.c]
+	Some null ptr fixes.
+
+	* [loader/pe_image.c]
+	Fixed exported function lookup. (msvcrt20.dll)
+	Add debugsyms for entrypoint, exported functions and sections.
+
+	* [multimedia/mmsystem.c]
+	MCIOpen: support for element opens (mplayer.exe /play bla.avi).
+
+	* [several]
+	Added several missing things/stubs/simple thunks from win32
+	to win16 code.
+
+Sat Sep 21 17:27:44 1996  O.Flebbe  <flebbe@science-computing.uni-tuebingen.de>
+
+	* [windows/property.c]
+	Fixed debugging of 16 Bit RemoveProp().
+
+	* [debugger/memory.c]
+	Added DEBUG_checkmap_bad() for linux.
+
+Thu Sep 19 20:48:31 1996  Albrecht Kleine  <kleine@ak.sax.de>
+
+	* [windows/event.c] [windows/hook.c]
+	Use EnableHardwareInput() for JournalPlayback hook.
+
+	* [controls/listbox.c]
+	Changed handling of LB_GETITEMRECT in empty listboxes.
+
+Thu Sep 19 13:34:35 1996  Slaven Rezic  <eserte@cs.tu-berlin.de>
+
+	* [misc/main.c]
+	Fixes to X resources handling.	
+
+Wed Sep 18 00:31:15 1996  Huw D. M. Davies <h.davies1@physics.oxford.ac.uk>
+
+	* [objects/metafile.c] [include/gdi.h] [objects/dc.c]
+	Individual handle table created for each metafile. Fixed
+ 	GlobalReAlloc() bug in MF_AddHandleDC() (was MF_AddHandleInternal).
+
+	* [windows/graphics.c] [objects/dc.c]
+	Rectangle() changed to work better with wide pens and PS_NULL.
+	Use JoinMiter.
+
+	* [windows/winpos.c]
+	Make the whole (non X) window invalid on resize if CS_[VH]REDRAW
+ 	is set.
+
+	* [windows/nonclient.c]
+	AdjustWindowRectEx() should perform calculations even if the
+ 	window is minimized.
+
+	* [windows/mdi.c]
+	Better handling of system button painting. Maximized windows can
+ 	contain scroll bars. Icons now maximize properly.
+
+	* [windows/defwnd.c] [windows/nonclient.c] [controls/menu.c]
+	Improved greying of items in system menu. WM_INITMEMUPOPUP no
+ 	longer caught in DefWndProc, DEFWND_InitSysMenuPopup moved to
+ 	menu.c.
+
+Mon Sep 16 21:30:00 1996  Uwe Bonnes <bon@elektron.ikp.physik.th-darmstadt.de>
+
+	* [several files]
+	Fix missing includes and wrong printing arguments.
+
+	* [controls/listbox.c]
+	Don't sort drives in ListBoxDirectory().
+	
+Sat Sep 14 09:05:47 1996  Petri Tuomola <ptuomola@xs4all.nl>
+
+	* [windows/dialog.c]
+	Fixed handling of Shift-TAB in dialogs.
+
+Thu Sep 12 18:31:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
+
+	* [if1632/gdi32.spec]
+	Added SelectClipRgn - call win16 version.
+
+	* [if1632/user32.spec]
+	Added GetAsyncKeyState, GetMenuItemID and GetMenuStringA.
+
+	* [include/wincon.h]
+	Added COORD and SMALL_RECT typedefs, moved CONSOLE_SCREEN_BUFFER_INFO
+	out of #if 0 protected portion of file.
+
+	* [loader/pe_image.c]
+	PE_InitTEB() - Tidy up, bug fix to stack pointer value (Borland
+	programs now work better)
+
+	* [win32/console.c]
+	Added stub functions for GetConsoleScreenBufferInfo and 
+	GetLargestConsoleWindowSize
+
+	* [win32/findfile.c]
+	FindFirstFile32A() - removed erroneous strcpy
+
+	* [windows/keyboard.c]
+	GetAsyncKeyState() - bug fix - now returns value as per Microsoft
+	specification. NB - I still have doubts about some other functions
+	in this file.
+
+----------------------------------------------------------------------
 Wed Sep 11 18:08:30 1996  Albrecht Kleine  <kleine@ak.sax.de>
 
 	* [windows/event.c]
diff --git a/controls/button.c b/controls/button.c
index cfe6490..d224256 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -10,12 +10,12 @@
 #include "graphics.h"
 #include "button.h"
 
-static void PB_Paint( WND *wndPtr, HDC hDC, WORD action );
-static void PB_PaintGrayOnGray(HDC hDC,HFONT hFont,RECT16 *rc,char *text);
-static void CB_Paint( WND *wndPtr, HDC hDC, WORD action );
-static void GB_Paint( WND *wndPtr, HDC hDC, WORD action );
-static void UB_Paint( WND *wndPtr, HDC hDC, WORD action );
-static void OB_Paint( WND *wndPtr, HDC hDC, WORD action );
+static void PB_Paint( WND *wndPtr, HDC32 hDC, WORD action );
+static void PB_PaintGrayOnGray(HDC32 hDC,HFONT hFont,RECT32 *rc,char *text);
+static void CB_Paint( WND *wndPtr, HDC32 hDC, WORD action );
+static void GB_Paint( WND *wndPtr, HDC32 hDC, WORD action );
+static void UB_Paint( WND *wndPtr, HDC32 hDC, WORD action );
+static void OB_Paint( WND *wndPtr, HDC32 hDC, WORD action );
 static void BUTTON_CheckAutoRadioButton( WND *wndPtr );
 
 #define MAX_BTN_TYPE  12
@@ -36,7 +36,7 @@
     BUTTON_UNCHECKED    /* BS_OWNERDRAW */
 };
 
-typedef void (*pfPaint)( WND *wndPtr, HDC hdc, WORD action );
+typedef void (*pfPaint)( WND *wndPtr, HDC32 hdc, WORD action );
 
 static const pfPaint btnPaintFunc[MAX_BTN_TYPE] =
 {
@@ -56,9 +56,9 @@
 
 #define PAINT_BUTTON(wndPtr,style,action) \
      if (btnPaintFunc[style]) { \
-         HDC hdc = GetDC( (wndPtr)->hwndSelf ); \
+         HDC32 hdc = GetDC32( (wndPtr)->hwndSelf ); \
          (btnPaintFunc[style])(wndPtr,hdc,action); \
-         ReleaseDC( (wndPtr)->hwndSelf, hdc ); }
+         ReleaseDC32( (wndPtr)->hwndSelf, hdc ); }
 
 #define BUTTON_SEND_CTLCOLOR(wndPtr,hdc) \
     SendMessage32A( GetParent32((wndPtr)->hwndSelf), WM_CTLCOLORBTN, \
@@ -124,7 +124,7 @@
     case WM_LBUTTONDOWN:
         SendMessage32A( hWnd, BM_SETSTATE32, TRUE, 0 );
         SetFocus32( hWnd );
-        SetCapture( hWnd );
+        SetCapture32( hWnd );
         break;
 
     case WM_LBUTTONUP:
@@ -155,7 +155,7 @@
         break;
 
     case WM_MOUSEMOVE:
-        if (GetCapture() == hWnd)
+        if (GetCapture32() == hWnd)
         {
             GetClientRect16( hWnd, &rect );
             SendMessage32A( hWnd, BM_SETSTATE32,
@@ -249,16 +249,14 @@
  *       Push Button Functions
  */
 
-static void PB_Paint( WND *wndPtr, HDC hDC, WORD action )
+static void PB_Paint( WND *wndPtr, HDC32 hDC, WORD action )
 {
-    RECT16 rc;
+    RECT32 rc;
     HPEN16 hOldPen;
     HBRUSH hOldBrush;
-    DWORD dwTextSize;
-    TEXTMETRIC16 tm;
     BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
 
-    GetClientRect16(wndPtr->hwndSelf, &rc);
+    GetClientRect32( wndPtr->hwndSelf, &rc );
 
       /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */
     if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
@@ -274,12 +272,12 @@
         SetPixel( hDC, rc.right-1, rc.top, GetSysColor(COLOR_WINDOW) );
         SetPixel( hDC, rc.right-1, rc.bottom-1, GetSysColor(COLOR_WINDOW) );
     }
-    InflateRect16( &rc, -1, -1 );
+    InflateRect32( &rc, -1, -1 );
 
     if ((wndPtr->dwStyle & 0x000f) == BS_DEFPUSHBUTTON)
     {
         Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
-        InflateRect16( &rc, -1, -1 );
+        InflateRect32( &rc, -1, -1 );
     }
 
     if (infoPtr->state & BUTTON_HIGHLIGHTED)
@@ -296,32 +294,34 @@
     /* draw button label, if any: */
     if (wndPtr->text && wndPtr->text[0])
     {
-     LOGBRUSH16 lb;
-     GetObject16( sysColorObjects.hbrushBtnFace, sizeof(lb), &lb );
-     if (wndPtr->dwStyle & WS_DISABLED &&
-         GetSysColor(COLOR_GRAYTEXT)==lb.lbColor)
-         /* don't write gray text on gray bkg */
-         PB_PaintGrayOnGray(hDC,infoPtr->hFont,&rc,wndPtr->text);
-     else
-     {
-        SetTextColor( hDC, (wndPtr->dwStyle & WS_DISABLED) ?
-                     GetSysColor(COLOR_GRAYTEXT) : GetSysColor(COLOR_BTNTEXT));
-        DrawText16( hDC, wndPtr->text, -1, &rc,
-                    DT_SINGLELINE | DT_CENTER | DT_VCENTER );
-        /* do we have the focus? */
-        if (infoPtr->state & BUTTON_HASFOCUS)
+        LOGBRUSH16 lb;
+        GetObject16( sysColorObjects.hbrushBtnFace, sizeof(lb), &lb );
+        if (wndPtr->dwStyle & WS_DISABLED &&
+            GetSysColor(COLOR_GRAYTEXT)==lb.lbColor)
+            /* don't write gray text on gray bkg */
+            PB_PaintGrayOnGray(hDC,infoPtr->hFont,&rc,wndPtr->text);
+        else
         {
-            short xdelta, ydelta;
-            dwTextSize = GetTextExtent(hDC,wndPtr->text,strlen(wndPtr->text));
-            GetTextMetrics16( hDC, &tm );
-            xdelta = ((rc.right - rc.left) - LOWORD(dwTextSize) - 1) / 2;
-            ydelta = ((rc.bottom - rc.top) - tm.tmHeight - 1) / 2;
-            if (xdelta < 0) xdelta = 0;
-            if (ydelta < 0) ydelta = 0;
-            InflateRect16( &rc, -xdelta, -ydelta );
-            DrawFocusRect16( hDC, &rc );
-        }
-     }   
+            SetTextColor( hDC, (wndPtr->dwStyle & WS_DISABLED) ?
+                     GetSysColor(COLOR_GRAYTEXT) : GetSysColor(COLOR_BTNTEXT));
+            DrawText32A( hDC, wndPtr->text, -1, &rc,
+                         DT_SINGLELINE | DT_CENTER | DT_VCENTER );
+            /* do we have the focus? */
+            if (infoPtr->state & BUTTON_HASFOCUS)
+            {
+                RECT32 r = { 0, 0, 0, 0 };
+                INT32 xdelta, ydelta;
+
+                DrawText32A( hDC, wndPtr->text, -1, &r,
+                             DT_SINGLELINE | DT_CALCRECT );
+                xdelta = ((rc.right - rc.left) - (r.right - r.left) - 1) / 2;
+                ydelta = ((rc.bottom - rc.top) - (r.bottom - r.top) - 1) / 2;
+                if (xdelta < 0) xdelta = 0;
+                if (ydelta < 0) ydelta = 0;
+                InflateRect32( &rc, -xdelta, -ydelta );
+                DrawFocusRect32( hDC, &rc );
+            }
+        }   
     }
 
     SelectObject( hDC, hOldPen );
@@ -334,17 +334,17 @@
  *   using a raster brush to avoid gray text on gray background
  */
 
-void PB_PaintGrayOnGray(HDC hDC,HFONT hFont,RECT16 *rc,char *text)
+void PB_PaintGrayOnGray(HDC32 hDC,HFONT hFont,RECT32 *rc,char *text)
 {
     static int Pattern[] = {0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55};
     HBITMAP hbm  = CreateBitmap(8, 8, 1, 1, Pattern);
     HDC hdcMem   = CreateCompatibleDC(hDC);
     HBITMAP hbmMem;
     HBRUSH hBr;
-    RECT16 rect,rc2;
+    RECT32 rect,rc2;
 
     rect=*rc;
-    DrawText16( hDC, text, -1, &rect, DT_SINGLELINE | DT_CALCRECT);
+    DrawText32A( hDC, text, -1, &rect, DT_SINGLELINE | DT_CALCRECT);
     rc2=rect;
     rect.left=(rc->right-rect.right)/2;       /* for centering text bitmap */
     rect.top=(rc->bottom-rect.bottom)/2;
@@ -354,7 +354,7 @@
     DeleteObject( hbm);
     PatBlt( hdcMem,0,0,rect.right,rect.bottom,WHITENESS);
     if (hFont) SelectObject( hdcMem, hFont);
-    DrawText16( hdcMem, text, -1, &rc2, DT_SINGLELINE);  
+    DrawText32A( hdcMem, text, -1, &rc2, DT_SINGLELINE);  
     PatBlt( hdcMem,0,0,rect.right,rect.bottom,0xFA0089);
     DeleteObject( SelectObject( hdcMem,hBr));
     BitBlt( hDC,rect.left,rect.top,rect.right,rect.bottom,hdcMem,0,0,0x990000);
@@ -367,13 +367,12 @@
  *       Check Box & Radio Button Functions
  */
 
-static void CB_Paint( WND *wndPtr, HDC hDC, WORD action )
+static void CB_Paint( WND *wndPtr, HDC32 hDC, WORD action )
 {
     RECT16 rc;
     HBRUSH hBrush;
     int textlen, delta, x, y;
     TEXTMETRIC16 tm;
-    SIZE16 size;
     BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
 
     GetClientRect16(wndPtr->hwndSelf, &rc);
@@ -404,20 +403,22 @@
         if (wndPtr->dwStyle & WS_DISABLED)
             SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) );
         DrawText16( hDC, wndPtr->text, textlen, &rc,
-                    DT_SINGLELINE | DT_VCENTER );
+                    DT_SINGLELINE | DT_VCENTER | DT_NOCLIP );
     }
     
     if ((action == ODA_FOCUS) ||
         ((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS)))
     {
-        GetTextExtentPoint16( hDC, wndPtr->text, textlen, &size );
+        RECT16 rect = { 0, 0, 0, 0 };
+        DrawText16( hDC, wndPtr->text, textlen, &rect,
+                    DT_SINGLELINE | DT_CALCRECT );
         if (delta > 1)
         {
             rc.top += delta - 1;
             rc.bottom -= delta + 1;
         }
         rc.left--;
-        rc.right = MIN( rc.left + size.cx + 2, rc.right );
+        rc.right = rc.left + rect.right + 2;
         DrawFocusRect16( hDC, &rc );
     }
 }
@@ -444,10 +445,9 @@
  *       Group Box Functions
  */
 
-static void GB_Paint( WND *wndPtr, HDC hDC, WORD action )
+static void GB_Paint( WND *wndPtr, HDC32 hDC, WORD action )
 {
     RECT16 rc;
-    SIZE16 size;
     BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
 
     if (action != ODA_DRAWENTIRE) return;
@@ -465,13 +465,10 @@
     LineTo( hDC, rc.left, rc.top+2 );
 
     if (!wndPtr->text) return;
-    GetTextExtentPoint16( hDC, wndPtr->text, strlen(wndPtr->text), &size );
-    rc.left  += 10;
-    rc.right  = rc.left + size.cx + 1;
-    rc.bottom = size.cy;
     if (wndPtr->dwStyle & WS_DISABLED)
         SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) );
-    DrawText16( hDC, wndPtr->text, -1, &rc, DT_SINGLELINE );
+    rc.left += 10;
+    DrawText16( hDC, wndPtr->text, -1, &rc, DT_SINGLELINE | DT_NOCLIP );
 }
 
 
@@ -479,7 +476,7 @@
  *       User Button Functions
  */
 
-static void UB_Paint( WND *wndPtr, HDC hDC, WORD action )
+static void UB_Paint( WND *wndPtr, HDC32 hDC, WORD action )
 {
     RECT16 rc;
     HBRUSH hBrush;
@@ -503,7 +500,7 @@
  *       Ownerdrawn Button Functions
  */
 
-static void OB_Paint( WND *wndPtr, HDC hDC, WORD action )
+static void OB_Paint( WND *wndPtr, HDC32 hDC, WORD action )
 {
     BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
     DRAWITEMSTRUCT32 dis;
diff --git a/controls/combo.c b/controls/combo.c
index 0904e8b..412fb2e 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -87,7 +87,7 @@
   WND *wndPtr = WIN_FindWndPtr(hwnd);
 
   if (wndPtr->dwStyle & WS_VSCROLL) 
-    SetScrollRange(lphc->hWndLBox,SB_VERT,0,ListMaxFirstVisible(lphl),TRUE);
+    SetScrollRange32(lphc->hWndLBox,SB_VERT,0,ListMaxFirstVisible(lphl),TRUE);
   if (repaint && lphl->bRedrawFlag) InvalidateRect32( hwnd, NULL, TRUE );
 }
 
@@ -240,7 +240,11 @@
   {
     Rectangle(hdc,lphc->RectButton.left-1,lphc->RectButton.top-1,
 	      lphc->RectButton.right+1,lphc->RectButton.bottom+1);
-    GRAPH_DrawReliefRect(hdc, &lphc->RectButton, 2, 2, FALSE);
+    {
+        RECT32 r;
+        CONV_RECT16TO32( &lphc->RectButton, &r );
+        GRAPH_DrawReliefRect(hdc, &r, 2, 2, FALSE);
+    }
     GRAPH_DrawBitmap(hdc, hComboBit,
 		     lphc->RectButton.left + 2,lphc->RectButton.top + 2,
 		     0, 0, CBitWidth, CBitHeight );
@@ -889,7 +893,7 @@
   SendMessage16(GetParent16(hwnd), WM_COMMAND,ID_CLB,MAKELONG(0,CBN_SELCHANGE));
   lphl->ItemFocused = newFocused;
   ListBoxScrollToFocus(lphl);
-  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
   InvalidateRect32( hwnd, NULL, TRUE );
   return 0;
 }
@@ -971,7 +975,7 @@
   }
 
   if (wndPtr->dwStyle & WS_VSCROLL) 
-      SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
+      SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
 
   SelectObject(hdc,hOldFont);
   EndPaint16( hwnd, &ps );
@@ -1008,7 +1012,7 @@
   RECT16     rectsel;
 
 /*  SetFocus32(hwnd); */
-  SetCapture(hwnd);
+  SetCapture32(hwnd);
 
   lphl->PrevFocused = lphl->ItemFocused;
 
@@ -1030,7 +1034,7 @@
 {
   LPHEADLIST lphl = CLBoxGetListHeader(hwnd);
 
-  if (GetCapture() == hwnd) ReleaseCapture();
+  if (GetCapture32() == hwnd) ReleaseCapture();
 
   if(!lphl)
      {
@@ -1070,7 +1074,7 @@
     if (y < CBLMM_EDGE) {
       if (lphl->FirstVisible > 0) {
 	lphl->FirstVisible--;
-	SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 	ListBoxSetCurSel(lphl, wRet);
 	InvalidateRect32( hwnd, NULL, TRUE );
 	return 0;
@@ -1079,7 +1083,7 @@
     else if (y >= (rect.bottom-CBLMM_EDGE)) {
       if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
 	lphl->FirstVisible++;
-	SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 	ListBoxSetCurSel(lphl, wRet);
 	InvalidateRect32( hwnd, NULL, TRUE );
 	return 0;
@@ -1136,7 +1140,7 @@
     lphl->FirstVisible = ListMaxFirstVisible(lphl);
 
   if (y != lphl->FirstVisible) {
-    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+    SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
     InvalidateRect32( hwnd, NULL, TRUE );
   }
 
diff --git a/controls/desktop.c b/controls/desktop.c
index 810dd5c..f7529e8 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -4,13 +4,13 @@
  * Copyright 1994 Alexandre Julliard
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include "win.h"
 #include "desktop.h"
 #include "directory.h"
-#include "file.h"
 #include "graphics.h"
 #include "heap.h"
 
@@ -20,11 +20,11 @@
  *
  * Load a bitmap from a file. Used by SetDeskWallPaper().
  */
-static HBITMAP DESKTOP_LoadBitmap( HDC hdc, const char *filename )
+static HBITMAP32 DESKTOP_LoadBitmap( HDC32 hdc, const char *filename )
 {
     BITMAPFILEHEADER *fileHeader;
     BITMAPINFO *bitmapInfo;
-    HBITMAP hbitmap;
+    HBITMAP32 hbitmap;
     HFILE file;
     LPSTR buffer;
     LONG size;
@@ -33,10 +33,10 @@
 
     if ((file = _lopen( filename, OF_READ )) == HFILE_ERROR)
     {
-        UINT32 len = GetWindowsDirectory( NULL, 0 );
+        UINT32 len = GetWindowsDirectory32A( NULL, 0 );
         if (!(buffer = HeapAlloc( SystemHeap, 0, len + strlen(filename) + 2 )))
             return 0;
-        GetWindowsDirectory( buffer, len + 1 );
+        GetWindowsDirectory32A( buffer, len + 1 );
         strcat( buffer, "\\" );
         strcat( buffer, filename );
         file = _lopen( buffer, OF_READ );
@@ -50,7 +50,7 @@
 	return 0;
     }
     _llseek( file, 0, 0 );
-    size = FILE_Read( file, buffer, size );
+    size = _lread32( file, buffer, size );
     _lclose( file );
     fileHeader = (BITMAPFILEHEADER *)buffer;
     bitmapInfo = (BITMAPINFO *)(buffer + sizeof(BITMAPFILEHEADER));
@@ -74,15 +74,16 @@
  *
  * Handle the WM_ERASEBKGND message.
  */
-static LONG DESKTOP_DoEraseBkgnd( HWND hwnd, HDC hdc, DESKTOPINFO *infoPtr )
+static LRESULT DESKTOP_DoEraseBkgnd( HWND32 hwnd, HDC32 hdc,
+                                     DESKTOPINFO *infoPtr )
 {
-    RECT16 rect;
+    RECT32 rect;
     WND*   Wnd = WIN_FindWndPtr( hwnd );
 
     if( Wnd->hrgnUpdate > 1 ) DeleteObject( Wnd->hrgnUpdate );
     Wnd->hrgnUpdate = 0;
 
-    GetClientRect16( hwnd, &rect );    
+    GetClientRect32( hwnd, &rect );    
 
     /* Paint desktop pattern (only if wall paper does not cover everything) */
 
@@ -93,14 +94,14 @@
 	  /* Set colors in case pattern is a monochrome bitmap */
 	SetBkColor( hdc, RGB(0,0,0) );
 	SetTextColor( hdc, GetSysColor(COLOR_BACKGROUND) );
-	FillRect16( hdc, &rect, infoPtr->hbrushPattern );
+	FillRect32( hdc, &rect, infoPtr->hbrushPattern );
     }
 
       /* Paint wall paper */
 
     if (infoPtr->hbitmapWallPaper)
     {
-	int x, y;
+	INT32 x, y;
 
 	if (infoPtr->fTileWallPaper)
 	{
@@ -147,12 +148,12 @@
 	infoPtr->hbrushPattern = 0;
 	infoPtr->hbitmapWallPaper = 0;
 	SetDeskPattern();
-	SetDeskWallPaper( (LPSTR)-1 );
+	SetDeskWallPaper32( (LPSTR)-1 );
 	break;
 	
     case WM_ERASEBKGND:
 	if (rootWindow == DefaultRootWindow(display)) return 1;
-	return DESKTOP_DoEraseBkgnd( hwnd, (HDC)wParam, infoPtr );
+	return DESKTOP_DoEraseBkgnd( hwnd, (HDC32)wParam, infoPtr );
 
     case WM_SYSCOMMAND:
 	if ((wParam & 0xfff0) != SC_CLOSE) return 0;
@@ -169,7 +170,7 @@
 /***********************************************************************
  *           SetDeskPattern   (USER.279)
  */
-BOOL SetDeskPattern(void)
+BOOL16 SetDeskPattern(void)
 {
     char buffer[100];
     GetProfileString( "desktop", "Pattern", "(None)", buffer, 100 );
@@ -178,14 +179,25 @@
 
 
 /***********************************************************************
- *           SetDeskWallPaper   (USER.285)
+ *           SetDeskWallPaper16   (USER.285)
  */
-BOOL SetDeskWallPaper( LPCSTR filename )
+BOOL16 SetDeskWallPaper16( LPCSTR filename )
 {
-    HBITMAP hbitmap;
-    HDC hdc;
+    return SetDeskWallPaper32( filename );
+}
+
+
+/***********************************************************************
+ *           SetDeskWallPaper32   (USER32.475)
+ *
+ * FIXME: is there a unicode version?
+ */
+BOOL32 SetDeskWallPaper32( LPCSTR filename )
+{
+    HBITMAP32 hbitmap;
+    HDC32 hdc;
     char buffer[256];
-    WND *wndPtr = WIN_FindWndPtr( GetDesktopWindow() );
+    WND *wndPtr = WIN_GetDesktop();
     DESKTOPINFO *infoPtr = (DESKTOPINFO *)wndPtr->wExtra;
 
     if (filename == (LPSTR)-1)
@@ -193,16 +205,16 @@
 	GetProfileString( "desktop", "WallPaper", "(None)", buffer, 256 );
 	filename = buffer;
     }
-    hdc = GetDC( 0 );
+    hdc = GetDC32( 0 );
     hbitmap = DESKTOP_LoadBitmap( hdc, filename );
-    ReleaseDC( 0, hdc );
+    ReleaseDC32( 0, hdc );
     if (infoPtr->hbitmapWallPaper) DeleteObject( infoPtr->hbitmapWallPaper );
     infoPtr->hbitmapWallPaper = hbitmap;
     infoPtr->fTileWallPaper = GetProfileInt( "desktop", "TileWallPaper", 0 );
     if (hbitmap)
     {
-	BITMAP16 bmp;
-	GetObject16( hbitmap, sizeof(bmp), &bmp );
+	BITMAP32 bmp;
+	GetObject32A( hbitmap, sizeof(bmp), &bmp );
 	infoPtr->bitmapSize.cx = (bmp.bmWidth != 0) ? bmp.bmWidth : 1;
 	infoPtr->bitmapSize.cy = (bmp.bmHeight != 0) ? bmp.bmHeight : 1;
     }
@@ -215,9 +227,9 @@
  *
  * Set the desktop pattern.
  */
-BOOL DESKTOP_SetPattern(char *pattern )
+BOOL32 DESKTOP_SetPattern( LPCSTR pattern )
 {
-    WND *wndPtr = WIN_FindWndPtr( GetDesktopWindow() );
+    WND *wndPtr = WIN_GetDesktop();
     DESKTOPINFO *infoPtr = (DESKTOPINFO *)wndPtr->wExtra;
     int pat[8];
 
@@ -228,7 +240,7 @@
 			   &pat[4], &pat[5], &pat[6], &pat[7] ))
     {
 	WORD pattern[8];
-	HBITMAP hbitmap;
+	HBITMAP32 hbitmap;
 	int i;
 
 	for (i = 0; i < 8; i++) pattern[i] = pat[i] & 0xffff;
diff --git a/controls/edit.c b/controls/edit.c
index 939e100..fb87a79 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -14,7 +14,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <windows.h>
+#include "windows.h"
 #include "win.h"
 #include "local.h"
 #include "stddebug.h"
@@ -503,7 +503,7 @@
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	char *text = EDIT_GetPasswordPointer(wndPtr);
 	int ww = EDIT_GetWndWidth(wndPtr);
-	HDC hdc;
+	HDC32 hdc;
 	HFONT hFont;
 	HFONT oldFont = 0;
 	char *start, *cp;
@@ -512,7 +512,7 @@
 	int length;
 	LINE_END ending;
 
-	hdc = GetDC(wndPtr->hwndSelf);
+	hdc = GetDC32(wndPtr->hwndSelf);
 	hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L);
 	if (hFont)
 		oldFont = SelectObject(hdc, hFont);
@@ -598,7 +598,7 @@
 	}
 	if (hFont)
 		SelectObject(hdc, oldFont);
-	ReleaseDC(wndPtr->hwndSelf, hdc);
+	ReleaseDC32(wndPtr->hwndSelf, hdc);
 
 	free(text);
 }
@@ -1441,7 +1441,7 @@
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	char *text = EDIT_GetPasswordPointer(wndPtr);
 	INT ret;
-	HDC hdc;
+	HDC32 hdc;
 	HFONT hFont;
 	HFONT oldFont = 0;
 	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
@@ -1449,7 +1449,7 @@
 	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
 	UINT xoff = EDIT_GetXOffset(wndPtr);
 
-	hdc = GetDC(wndPtr->hwndSelf);
+	hdc = GetDC32(wndPtr->hwndSelf);
 	hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L);
 	if (hFont)
 		oldFont = SelectObject(hdc, hFont);
@@ -1460,7 +1460,7 @@
 			es->NumTabStops, es->TabStops)) - xoff;
 	if (hFont)
 		SelectObject(hdc, oldFont);
-	ReleaseDC(wndPtr->hwndSelf, hdc);
+	ReleaseDC32(wndPtr->hwndSelf, hdc);
 	free(text);
 	return ret;
 }
@@ -1859,10 +1859,10 @@
 		es->FirstVisibleLine = nfv;
 		es->XOffset = nxoff;
 		if (IsVScrollBar(wndPtr))
-			SetScrollPos(wndPtr->hwndSelf, SB_VERT,
+			SetScrollPos32(wndPtr->hwndSelf, SB_VERT,
 				EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
 		if (IsHScrollBar(wndPtr))
-			SetScrollPos(wndPtr->hwndSelf, SB_HORZ,
+			SetScrollPos32(wndPtr->hwndSelf, SB_HORZ,
 				EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
 		if (wndPtr->hwndSelf == GetFocus32()) {
 			GetCaretPos16(&pos);
@@ -2604,7 +2604,7 @@
 	UINT li;
 
 	SetFocus32(wndPtr->hwndSelf);
-	SetCapture(wndPtr->hwndSelf);
+	SetCapture32(wndPtr->hwndSelf);
 	l = MIN(fv + vlc - 1, MAX(fv, l));
 	x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
 	c = EDIT_ColFromWndX(wndPtr, l, x);
@@ -2626,7 +2626,7 @@
  */
 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
-	if (GetCapture() == wndPtr->hwndSelf)
+	if (GetCapture32() == wndPtr->hwndSelf)
 		ReleaseCapture();
 	return 0L;
 }
@@ -2648,7 +2648,7 @@
 	UINT vlc;
 	UINT li;
 
-	if (GetCapture() == wndPtr->hwndSelf) {
+	if (GetCapture32() == wndPtr->hwndSelf) {
 		x = (INT)LOWORD(lParam);
 		y = (INT)HIWORD(lParam);
 		fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
@@ -2775,11 +2775,11 @@
 	TEXTMETRIC16 tm;
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L);
-	HDC hdc;
+	HDC32 hdc;
 	HFONT oldFont = 0;
 
 	es->hFont = (HFONT)wParam;
-	hdc = GetDC(wndPtr->hwndSelf);
+	hdc = GetDC32(wndPtr->hwndSelf);
 	if (es->hFont)
 		oldFont = SelectObject(hdc, es->hFont);
 	GetTextMetrics16(hdc, &tm);
@@ -2787,7 +2787,7 @@
 	es->AveCharWidth = tm.tmAveCharWidth;
 	if (es->hFont)
 		SelectObject(hdc, oldFont);
-	ReleaseDC(wndPtr->hwndSelf, hdc);
+	ReleaseDC32(wndPtr->hwndSelf, hdc);
 	EDIT_BuildLineDefs(wndPtr);
 	if ((BOOL)lParam && EDIT_GetRedraw(wndPtr))
 		InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
diff --git a/controls/listbox.c b/controls/listbox.c
index 5a16e4a..4abf763 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -64,7 +64,7 @@
 void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent)
 {
   LPHEADLIST lphl;
-  HDC         hdc;
+  HDC32         hdc;
 
   lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST));
   SetWindowLong32A(hwnd, 0, (LONG)lphl);
@@ -87,14 +87,14 @@
   lphl->HasStrings     = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn;
 
   /* create dummy hdc to set text height */
-  if ((hdc = GetDC(0)))
+  if ((hdc = GetDC32(0)))
   {
       TEXTMETRIC16 tm;
       GetTextMetrics16( hdc, &tm );
       lphl->StdItemHeight = tm.tmHeight;
       dprintf_listbox(stddeb,"CreateListBoxStruct:  font height %d\n",
                       lphl->StdItemHeight);
-      ReleaseDC( 0, hdc );
+      ReleaseDC32( 0, hdc );
   }
 
   if (lphl->OwnerDrawn)
@@ -148,9 +148,9 @@
 void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint)
 {
   if (lphl->dwStyle & WS_VSCROLL)
-    SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
+    SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
   if ((lphl->dwStyle & WS_HSCROLL) && (lphl->ItemsPerColumn != 0))
-    SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
+    SetScrollRange32(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
 		   lphl->ItemsPerColumn + 1, TRUE);
 
   if (repaint && lphl->bRedrawFlag) InvalidateRect32( hwnd, NULL, TRUE );
@@ -811,12 +811,16 @@
     if (attrib & DDL_DRIVES)
     {
         int x;
+	DWORD oldstyle = lphl->dwStyle;
+	    
+	lphl->dwStyle &= ~LBS_SORT;
         strcpy( temp, "[-a-]" );
         for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++)
         {
             if (DRIVE_IsValid(x))
                 if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
         }
+	lphl->dwStyle = oldstyle;
     }
 
     free( path );
@@ -831,8 +835,22 @@
 {
   LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex);
 
-  if (lpls == NULL) return LB_ERR;
-  *lprect = lpls->itemRect;
+  dprintf_listbox(stddeb,"ListBox LB_GETITEMRECT %i %p", wIndex,lpls);
+  if (lpls == NULL)
+  {
+    if (lphl->dwStyle & LBS_OWNERDRAWVARIABLE)
+      return LB_ERR;
+    else 
+    {
+     GetClientRect16(lphl->hSelf,lprect);
+     lprect->bottom=lphl->StdItemHeight;
+     if (lprect->right<0) lprect->right=0;
+    }
+  }
+  else
+   *lprect = lpls->itemRect;
+  dprintf_listbox(stddeb," = %d,%d  %d,%d\n", lprect->left,lprect->top,
+                                              lprect->right,lprect->bottom);
   return 0;
 }
 
@@ -897,9 +915,9 @@
   lphl->ColumnsWidth = rect.right - rect.left;
 
   if (dwStyle & WS_VSCROLL) 
-    SetScrollRange(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
+    SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
   if (dwStyle & WS_HSCROLL) 
-    SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
+    SetScrollRange32(hwnd, SB_HORZ, 1, 1, TRUE);
 
   return 0;
 }
@@ -974,7 +992,7 @@
     lphl->FirstVisible = ListMaxFirstVisible(lphl);
 
   if (y != lphl->FirstVisible) {
-    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+    SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
     InvalidateRect32( hwnd, NULL, TRUE );
   }
   return 0;
@@ -1029,7 +1047,7 @@
     lphl->FirstVisible = lphl->FirstVisible /
       lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
     if (y != lphl->FirstVisible) {
-      SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible / 
+      SetScrollPos32(hwnd, SB_HORZ, lphl->FirstVisible / 
 		   lphl->ItemsPerColumn + 1, TRUE);
       InvalidateRect32( hwnd, NULL, TRUE );
     }
@@ -1048,7 +1066,7 @@
   RECT16     rectsel;
 
   SetFocus32(hwnd);
-  SetCapture(hwnd);
+  SetCapture32(hwnd);
 
   lphl->PrevFocused = lphl->ItemFocused;
 
@@ -1122,7 +1140,7 @@
 {
   LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
 
-  if (GetCapture() == hwnd) ReleaseCapture();
+  if (GetCapture32() == hwnd) ReleaseCapture();
 
   if (lphl->PrevFocused != lphl->ItemFocused)
     ListBoxSendNotification(lphl, LBN_SELCHANGE);
@@ -1158,7 +1176,7 @@
     if (y < LBMM_EDGE) {
       if (lphl->FirstVisible > 0) {
 	lphl->FirstVisible--;
-	SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 	InvalidateRect32( hwnd, NULL, TRUE );
 	return 0;
       }
@@ -1167,7 +1185,7 @@
     if (y >= (rect.bottom-LBMM_EDGE)) {
       if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
 	lphl->FirstVisible++;
-	SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 	InvalidateRect32( hwnd, NULL, TRUE );
 	return 0;
       }
@@ -1322,7 +1340,7 @@
           }
     }
 
-  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 
   return 0;
 }
@@ -1358,7 +1376,7 @@
 
   lphl->ItemFocused = newFocused;
   ListBoxScrollToFocus(lphl);
-  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 
   InvalidateRect32( hwnd, NULL, TRUE );
 
@@ -1385,7 +1403,7 @@
 static LONG LBSetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
   LPHEADLIST  lphl = ListBoxGetStorageHeader(hwnd);
-  HDC hdc;
+  HDC32 hdc;
 
   if (wParam == 0)
     lphl->hFont = GetStockObject(SYSTEM_FONT);
@@ -1395,14 +1413,14 @@
   /* a new font means possible new text height */
   /* does this mean the height of each entry must be separately changed? */
   /* or are we guaranteed to get a LBSetFont before the first insert/add? */
-  if ((hdc = GetDC(0)))
+  if ((hdc = GetDC32(0)))
   {
       TEXTMETRIC16 tm;
       GetTextMetrics16( hdc, &tm );
       lphl->StdItemHeight = tm.tmHeight;
       dprintf_listbox(stddeb,"LBSetFont:  new font %d with height %d\n",
                       lphl->hFont, lphl->StdItemHeight);
-      ReleaseDC( 0, hdc );
+      ReleaseDC32( 0, hdc );
   }
 
   return 0;
@@ -1517,7 +1535,7 @@
   if(!(lphl->dwStyle & LBS_MULTIPLESEL) )
        if( lphl->ItemsCount && lphl->ItemFocused != -1)
          {
-           HDC          hDC = GetDC(hwnd);
+           HDC32        hDC = GetDC32(hwnd);
            HFONT        hOldFont = SelectObject(hDC, lphl->hFont);
            LPLISTSTRUCT lpls;
 
@@ -1526,7 +1544,7 @@
 
            ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
            SelectObject(hDC, hOldFont);
-           ReleaseDC(hwnd,hDC);
+           ReleaseDC32(hwnd,hDC);
          }
 
   ListBoxSendNotification(lphl, LBN_SETFOCUS);
@@ -1547,7 +1565,7 @@
        if( lphl->ItemsCount )
            if( lphl->ItemFocused != -1 )
              {
-              HDC          hDC = GetDC(hwnd);
+              HDC32        hDC = GetDC32(hwnd);
               HFONT        hOldFont = SelectObject(hDC, lphl->hFont);
               LPLISTSTRUCT lpls;
 
@@ -1556,7 +1574,7 @@
 
               ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
               SelectObject(hDC, hOldFont);
-              ReleaseDC(hwnd,hDC);
+              ReleaseDC32(hwnd,hDC);
              }
            else
              dprintf_listbox(stddeb,"LBKillFocus: no focused item!\n");
@@ -1905,7 +1923,7 @@
   lphl->ItemFocused = wParam;
   i = ListBoxScrollToFocus (lphl);
 
-  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
   if(i)
     InvalidateRect32( hwnd, NULL, TRUE );
  
@@ -1988,7 +2006,7 @@
 
   wRet = ListBoxSetCurSel(lphl, wParam);
 
-  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
   InvalidateRect32( hwnd, NULL, TRUE );
 
   return wRet;
@@ -2034,7 +2052,7 @@
   dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
 		  wParam);
   lphl->FirstVisible = wParam;
-  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 
   InvalidateRect32( hwnd, NULL, TRUE );
 
diff --git a/controls/menu.c b/controls/menu.c
index bc1a6ac..d18b3ca 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -87,8 +87,9 @@
 #define IS_STRING_ITEM(flags) (!((flags) & (MF_BITMAP | MF_OWNERDRAW | \
 			     MF_MENUBARBREAK | MF_MENUBREAK | MF_SEPARATOR)))
 
-extern void NC_DrawSysButton(HWND hwnd, HDC hdc, BOOL down);  /* nonclient.c */
-extern BOOL NC_GetSysPopupPos(WND* wndPtr, RECT16* rect);
+extern void  NC_DrawSysButton(HWND hwnd, HDC hdc, BOOL down); /* nonclient.c */
+extern BOOL  NC_GetSysPopupPos(WND* wndPtr, RECT16* rect);
+extern HTASK TASK_GetNextTask(HTASK);
 
 static HBITMAP hStdCheck = 0;
 static HBITMAP hStdMnArrow = 0;
@@ -210,6 +211,30 @@
 
 
 /***********************************************************************
+ *           MENU_InitSysMenuPopup
+ *
+ * Grey the appropriate items in System menu.
+ */
+void MENU_InitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle)
+{
+    BOOL gray;
+
+    gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
+    EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = ((style & WS_MAXIMIZE) != 0);
+    EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
+    EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
+    EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
+    EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = (clsStyle & CS_NOCLOSE) != 0;
+    EnableMenuItem( hmenu, SC_CLOSE, (gray ? MF_GRAYED : MF_ENABLED) );
+}
+
+
+/***********************************************************************
  *           MENU_FindItem
  *
  * Find a menu item. Return a pointer on the item, and modifies *hmenu
@@ -407,13 +432,13 @@
 static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
 {
     MENUITEM *lpitem;
-    HDC hdc;
+    HDC32 hdc;
     int start, i;
     int orgX, orgY, maxX, maxTab, maxTabWidth;
 
     lppop->Width = lppop->Height = 0;
     if (lppop->nItems == 0) return;
-    hdc = GetDC( 0 );
+    hdc = GetDC32( 0 );
     maxX = start = 0;
     while (start < lppop->nItems)
     {
@@ -450,7 +475,7 @@
     }
 
     lppop->Width  = maxX;
-    ReleaseDC( 0, hdc );
+    ReleaseDC32( 0, hdc );
 }
 
 
@@ -731,12 +756,25 @@
 /***********************************************************************
  *	     MENU_SwitchTPWndTo
  */
-static BOOL MENU_SwitchTPWndTo( HTASK hTask)
+BOOL32 MENU_SwitchTPWndTo( HTASK hTask)
 {
-  /* This is supposed to be called when popup is hidden */
+  /* This is supposed to be called when popup is hidden. 
+   * AppExit() calls with hTask == 0, so we get the next to current.
+   */
 
-  TDB* task = (TDB*)GlobalLock16(hTask);
+  TDB* task;
 
+  if( !pTopPWnd ) return 0;
+
+  if( !hTask )
+  {
+    task = (TDB*)GlobalLock16( (hTask = GetCurrentTask()) );
+    if( task && task->hQueue == pTopPWnd->hmemTaskQ )
+	hTask = TASK_GetNextTask(hTask); 
+    else return 0;
+  }
+
+  task = (TDB*)GlobalLock16(hTask);
   if( !task ) return 0;
 
   /* if this task got as far as menu tracking it must have a queue */
@@ -802,7 +840,7 @@
 	pTopPWnd = WIN_FindWndPtr(CreateWindow16( POPUPMENU_CLASS_ATOM, NULL,
                                           WS_POPUP | WS_BORDER, x, y,
                                           width, height,
-                                          0, 0, wndPtr->hInstance,
+                                          hwndOwner, 0, wndPtr->hInstance,
                                           (LPVOID)(HMENU32)hmenu ));
 	if (!pTopPWnd) return FALSE;
 	skip_init = TRUE;
@@ -851,7 +889,7 @@
                              BOOL sendMenuSelect )
 {
     LPPOPUPMENU lppop;
-    HDC hdc;
+    HDC32 hdc;
 
     lppop = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
     if (!lppop->nItems) return;
@@ -860,8 +898,8 @@
 	(lppop->items[wIndex].item_flags & MF_SEPARATOR))
 	wIndex = NO_SELECTED_ITEM;
     if (lppop->FocusedItem == wIndex) return;
-    if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
-    else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
+    if (lppop->wFlags & MF_POPUP) hdc = GetDC32( lppop->hWnd );
+    else hdc = GetDCEx32( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
 
       /* Clear previous highlighted item */
     if (lppop->FocusedItem != NO_SELECTED_ITEM) 
@@ -903,7 +941,7 @@
         SendMessage16( hwndOwner, WM_MENUSELECT, hmenu,
                        MAKELONG( lppop->wFlags | MF_MOUSESELECT, hmenu ) );
 
-    ReleaseDC( lppop->hWnd, hdc );
+    ReleaseDC32( lppop->hWnd, hdc );
 }
 
 
@@ -1187,6 +1225,8 @@
     if (menu->FocusedItem == NO_SELECTED_ITEM) return hmenu;
     if (menu->FocusedItem == SYSMENU_SELECTED)
     {
+	MENU_InitSysMenuPopup(wndPtr->hSysMenu, wndPtr->dwStyle,
+				wndPtr->class->style);
 	MENU_ShowPopup(hwndOwner, wndPtr->hSysMenu, 0, wndPtr->rectClient.left,
 		wndPtr->rectClient.top - menu->Height - 2*SYSMETRICS_CYBORDER,
 		SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE );
@@ -1445,23 +1485,21 @@
 
     if( (menu->wFlags & (MF_POPUP | MF_SYSMENU)) == (MF_POPUP | MF_SYSMENU) )
 	{
-	  HDC hdc;
-
 	  ShowWindow( menu->hWnd, SW_HIDE );
 	  uSubPWndLevel = 0;
 
 	  if( !IsIconic( *hwndOwner ) )
 	  { 
-	    hdc = GetDCEx( *hwndOwner, 0, DCX_CACHE | DCX_WINDOW);
+	    HDC32 hdc = GetDCEx32( *hwndOwner, 0, DCX_CACHE | DCX_WINDOW);
 	    NC_DrawSysButton( *hwndOwner, hdc, FALSE );
-	    ReleaseDC( *hwndOwner, hdc );
+	    ReleaseDC32( *hwndOwner, hdc );
 	  }
 	}
 
     ReleaseCapture(); 
    *hwndOwner = HIWORD(l);
    *hmenu = LOWORD(l);
-    SetCapture( *hwndOwner );
+    SetCapture32( *hwndOwner );
 
     menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( *hmenu );
 
@@ -1484,9 +1522,9 @@
 
              if( !IsIconic( *hwndOwner ) )
              {
-               HDC hdc =  GetDCEx( *hwndOwner, 0, DCX_CACHE | DCX_WINDOW);
+               HDC32 hdc =  GetDCEx32( *hwndOwner, 0, DCX_CACHE | DCX_WINDOW);
                NC_DrawSysButton( *hwndOwner, hdc, TRUE );
-               ReleaseDC( *hwndOwner, hdc );
+               ReleaseDC32( *hwndOwner, hdc );
              }
 	  }
 	}
@@ -1618,7 +1656,7 @@
 	POINT16 pt = { x, y };
 	MENU_ButtonDown( hwnd, hmenu, &hmenuCurrent, pt );
     }
-    SetCapture( hwnd );
+    SetCapture32( hwnd );
     while (!fClosed)
     {
 	if (!MSG_InternalGetMessage( &msg, 0, hwnd, MSGF_MENU, 0, TRUE ))
@@ -1918,7 +1956,7 @@
 	     */
 
 	    if( hwnd == pTopPWnd->hwndSelf )
-		pTopPWnd = 0;
+	    {	pTopPWnd = NULL; uSubPWndLevel = 0; }
 	    else
 		uSubPWndLevel--;
 	    break;
@@ -1940,7 +1978,7 @@
  */
 UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth, int orgX, int orgY )
 {
-    HDC hdc;
+    HDC32 hdc;
     RECT16 rectBar;
     WND *wndPtr;
     LPPOPUPMENU lppop;
@@ -1948,10 +1986,10 @@
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
     if (!(lppop = (LPPOPUPMENU)USER_HEAP_LIN_ADDR((HMENU)wndPtr->wIDmenu)))
       return 0;
-    hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
+    hdc = GetDCEx32( hwnd, 0, DCX_CACHE | DCX_WINDOW );
     SetRect16(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+SYSMETRICS_CYMENU);
     MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
-    ReleaseDC( hwnd, hdc );
+    ReleaseDC32( hwnd, hdc );
     return lppop->Height;
 }
 
@@ -2522,7 +2560,7 @@
 		return FALSE;
 		}
 	dprintf_menu(stddeb,"SetMenu(%04x, %04x);\n", hWnd, hMenu);
-	if (GetCapture() == hWnd) ReleaseCapture();
+	if (GetCapture32() == hWnd) ReleaseCapture();
 	wndPtr->wIDmenu = (UINT)hMenu;
 	if (hMenu != 0)
 	{
diff --git a/controls/scroll.c b/controls/scroll.c
index 8b6fb07..34497fc 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -1,13 +1,11 @@
 /*		
- * Interface code to SCROLLBAR widget
+ * Scrollbar control
  *
- * Copyright  Martin Ayotte, 1993
- * Copyright  Alexandre Julliard, 1994
- *
- * Small fixes and implemented SB_THUMBPOSITION
- * by Peter Broadhurst, 940611
+ * Copyright 1993 Martin Ayotte
+ * Copyright 1994, 1996 Alexandre Julliard
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
@@ -23,18 +21,18 @@
 #include "debug.h"
 
 
-static HBITMAP hUpArrow = 0;
-static HBITMAP hDnArrow = 0;
-static HBITMAP hLfArrow = 0;
-static HBITMAP hRgArrow = 0;
-static HBITMAP hUpArrowD = 0;
-static HBITMAP hDnArrowD = 0;
-static HBITMAP hLfArrowD = 0;
-static HBITMAP hRgArrowD = 0;
-static HBITMAP hUpArrowI = 0;
-static HBITMAP hDnArrowI = 0;
-static HBITMAP hLfArrowI = 0;
-static HBITMAP hRgArrowI = 0;
+static HBITMAP32 hUpArrow = 0;
+static HBITMAP32 hDnArrow = 0;
+static HBITMAP32 hLfArrow = 0;
+static HBITMAP32 hRgArrow = 0;
+static HBITMAP32 hUpArrowD = 0;
+static HBITMAP32 hDnArrowD = 0;
+static HBITMAP32 hLfArrowD = 0;
+static HBITMAP32 hRgArrowD = 0;
+static HBITMAP32 hUpArrowI = 0;
+static HBITMAP32 hDnArrowI = 0;
+static HBITMAP32 hLfArrowI = 0;
+static HBITMAP32 hRgArrowI = 0;
 
 #define TOP_ARROW(flags,pressed) \
    (((flags)&ESB_DISABLE_UP) ? hUpArrowI : ((pressed) ? hUpArrowD:hUpArrow))
@@ -49,6 +47,9 @@
   /* Minimum size of the rectangle between the arrows */
 #define SCROLL_MIN_RECT  4  
 
+  /* Minimum size of the thumb in pixels */
+#define SCROLL_MIN_THUMB 4
+
   /* Delay (in ms) before first repetition when holding the button down */
 #define SCROLL_FIRST_DELAY   200
 
@@ -70,34 +71,38 @@
 };
 
  /* Thumb-tracking info */
-static HWND hwndTracking = 0;
-static int nBarTracking = 0;
-static UINT uTrackingPos = 0;
+static HWND32 SCROLL_TrackingWin = 0;
+static INT32  SCROLL_TrackingBar = 0;
+static INT32  SCROLL_TrackingPos = 0;
+static INT32  SCROLL_TrackingVal = 0;
+
+/* Is the moving thumb being displayed? */
+static BOOL32 SCROLL_MovingThumb = FALSE;
 
 /***********************************************************************
  *           SCROLL_LoadBitmaps
  */
 static void SCROLL_LoadBitmaps(void)
 {
-    hUpArrow  = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_UPARROW));
-    hDnArrow  = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_DNARROW));
-    hLfArrow  = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_LFARROW));
-    hRgArrow  = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_RGARROW));
-    hUpArrowD = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_UPARROWD));
-    hDnArrowD = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_DNARROWD));
-    hLfArrowD = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_LFARROWD));
-    hRgArrowD = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_RGARROWD));
-    hUpArrowI = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_UPARROWI));
-    hDnArrowI = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_DNARROWI));
-    hLfArrowI = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_LFARROWI));
-    hRgArrowI = LoadBitmap16((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_RGARROWI));
+    hUpArrow  = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_UPARROW) );
+    hDnArrow  = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_DNARROW) );
+    hLfArrow  = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_LFARROW) );
+    hRgArrow  = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_RGARROW) );
+    hUpArrowD = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_UPARROWD) );
+    hDnArrowD = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_DNARROWD) );
+    hLfArrowD = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_LFARROWD) );
+    hRgArrowD = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_RGARROWD) );
+    hUpArrowI = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_UPARROWI) );
+    hDnArrowI = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_DNARROWI) );
+    hLfArrowI = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_LFARROWI) );
+    hRgArrowI = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_RGARROWI) );
 }
 
 
 /***********************************************************************
  *           SCROLL_GetPtrScrollInfo
  */
-static SCROLLBAR_INFO *SCROLL_GetPtrScrollInfo( WND* wndPtr, int nBar )
+static SCROLLBAR_INFO *SCROLL_GetPtrScrollInfo( WND* wndPtr, INT32 nBar )
 {
     SCROLLBAR_INFO *infoPtr;
 
@@ -114,7 +119,7 @@
     {
         if ((infoPtr = HeapAlloc( SystemHeap, 0, sizeof(SCROLLBAR_INFO) )))
         {
-            infoPtr->MinVal = infoPtr->CurVal = 0;
+            infoPtr->MinVal = infoPtr->CurVal = infoPtr->Page = 0;
             infoPtr->MaxVal = 100;
             infoPtr->flags  = ESB_ENABLE_BOTH;
             if (nBar == SB_HORZ) wndPtr->pHScroll = infoPtr;
@@ -129,7 +134,7 @@
 /***********************************************************************
  *           SCROLL_GetScrollInfo
  */
-static SCROLLBAR_INFO *SCROLL_GetScrollInfo( HWND hwnd, int nBar )
+static SCROLLBAR_INFO *SCROLL_GetScrollInfo( HWND32 hwnd, INT32 nBar )
 {
    WND *wndPtr = WIN_FindWndPtr( hwnd );
    return SCROLL_GetPtrScrollInfo( wndPtr, nBar );
@@ -141,16 +146,18 @@
  *
  * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
  * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
- * 'arrowSize' returns the width or height of an arrow (depending on the
- * orientation of the scrollbar), and 'thumbPos' returns the position of
- * the thumb relative to the left or to the top.
+ * 'arrowSize' returns the width or height of an arrow (depending on
+ * the orientation of the scrollbar), 'thumbSize' returns the size of
+ * the thumb, and 'thumbPos' returns the position of the thumb
+ * relative to the left or to the top.
  * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
  */
-static BOOL SCROLL_GetScrollBarRect( HWND hwnd, int nBar, RECT16 *lprect,
-                                     WORD *arrowSize, WORD *thumbPos )
+static BOOL32 SCROLL_GetScrollBarRect( HWND32 hwnd, INT32 nBar, RECT32 *lprect,
+                                       INT32 *arrowSize, INT32 *thumbSize,
+                                       INT32 *thumbPos )
 {
-    int pixels;
-    BOOL vertical;
+    INT32 pixels;
+    BOOL32 vertical;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
     switch(nBar)
@@ -172,7 +179,7 @@
 	break;
 
       case SB_CTL:
-	GetClientRect16( hwnd, lprect );
+	GetClientRect32( hwnd, lprect );
         vertical = ((wndPtr->dwStyle & SBS_VERT) != 0);
 	break;
 
@@ -183,28 +190,44 @@
     if (vertical) pixels = lprect->bottom - lprect->top;
     else pixels = lprect->right - lprect->left;
 
-    if (pixels > 2*SYSMETRICS_CXVSCROLL + SCROLL_MIN_RECT)
+    if (pixels <= 2*SYSMETRICS_CXVSCROLL + SCROLL_MIN_RECT)
     {
-        *arrowSize = SYSMETRICS_CXVSCROLL;
+        if (pixels > SCROLL_MIN_RECT)
+            *arrowSize = (pixels - SCROLL_MIN_RECT) / 2;
+        else
+            *arrowSize = 0;
+        *thumbPos = *thumbSize = 0;
     }
-    else if (pixels > SCROLL_MIN_RECT)
-    {
-        *arrowSize = (pixels - SCROLL_MIN_RECT) / 2;
-    }
-    else *arrowSize = 0;
-    
-    if ((pixels -= 3*SYSMETRICS_CXVSCROLL+1) > 0)
+    else
     {
         SCROLLBAR_INFO *info = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
-        if ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)
-            *thumbPos = 0;
-        else if (info->MinVal == info->MaxVal)
-            *thumbPos = *arrowSize;
+
+        *arrowSize = SYSMETRICS_CXVSCROLL;
+        pixels -= 2 * SYSMETRICS_CXVSCROLL;
+
+        if (info->Page)
+        {
+            *thumbSize = pixels * info->Page / (info->MaxVal-info->MinVal+1);
+            if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
+        }
+        else *thumbSize = SYSMETRICS_CXVSCROLL;
+
+        if (((pixels -= *thumbSize + 1) < 0) ||
+            ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
+        {
+            /* Rectangle too small or scrollbar disabled -> no thumb */
+            *thumbPos = *thumbSize = 0;
+        }
         else
-            *thumbPos = *arrowSize + pixels * (info->CurVal - info->MinVal) /
-                                              (info->MaxVal - info->MinVal);
+        {
+            INT32 max = info->MaxVal - MAX( info->Page-1, 0 );
+            if (info->MinVal >= max)
+                *thumbPos = *arrowSize;
+            else
+                *thumbPos = *arrowSize + pixels * (info->CurVal-info->MinVal) /
+                                                  (max - info->MinVal);
+        }
     }
-    else *thumbPos = 0;
     return vertical;
 }
 
@@ -215,20 +238,29 @@
  * Compute the current scroll position based on the thumb position in pixels
  * from the top of the scroll-bar.
  */
-static UINT SCROLL_GetThumbVal( SCROLLBAR_INFO *infoPtr, RECT16 *rect,
-                                BOOL vertical, WORD pos )
+static UINT32 SCROLL_GetThumbVal( SCROLLBAR_INFO *infoPtr, RECT32 *rect,
+                                  BOOL32 vertical, INT32 pos )
 {
-    int pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
-    if ((pixels -= 3*SYSMETRICS_CXVSCROLL+1) <= 0) return infoPtr->MinVal;
+    INT32 thumbSize;
+    INT32 pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
+
+    if ((pixels -= 2*SYSMETRICS_CXVSCROLL) <= 0) return infoPtr->MinVal;
+
+    if (infoPtr->Page)
+    {
+        thumbSize = pixels * infoPtr->Page/(infoPtr->MaxVal-infoPtr->MinVal+1);
+        if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB;
+    }
+    else thumbSize = SYSMETRICS_CXVSCROLL;
+
+    if ((pixels -= thumbSize + 1) <= 0) return infoPtr->MinVal;
+
     pos = MAX( 0, pos - SYSMETRICS_CXVSCROLL );
     if (pos > pixels) pos = pixels;
-    dprintf_scroll(stddeb,"GetThumbVal: pos=%d ret=%d\n", pos,
-                   (infoPtr->MinVal
-            + (UINT)(((int)pos * (infoPtr->MaxVal-infoPtr->MinVal) + pixels/2)
-                     / pixels)) );
-    return (infoPtr->MinVal
-            + (UINT)(((int)pos * (infoPtr->MaxVal-infoPtr->MinVal) + pixels/2)
-                     / pixels));
+
+    if (!infoPtr->Page) pos *= infoPtr->MaxVal - infoPtr->MinVal;
+    else pos *= infoPtr->MaxVal - infoPtr->MinVal - infoPtr->Page + 1;
+    return infoPtr->MinVal + ((pos + pixels / 2) / pixels);
 }
 
 
@@ -237,14 +269,15 @@
  *
  * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
  */
-static enum SCROLL_HITTEST SCROLL_HitTest( HWND hwnd, int nBar, POINT16 pt )
+static enum SCROLL_HITTEST SCROLL_HitTest( HWND32 hwnd, INT32 nBar,
+                                           POINT32 pt )
 {
-    WORD arrowSize, thumbPos;
-    RECT16 rect;
+    INT32 arrowSize, thumbSize, thumbPos;
+    RECT32 rect;
 
-    BOOL vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
-                                             &arrowSize, &thumbPos );
-    if (!PtInRect16( &rect, pt )) return SCROLL_NOWHERE;
+    BOOL32 vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
+                                           &arrowSize, &thumbSize, &thumbPos );
+    if (!PtInRect32( &rect, pt )) return SCROLL_NOWHERE;
 
     if (vertical)
     {
@@ -252,8 +285,8 @@
         if (pt.y >= rect.bottom - arrowSize) return SCROLL_BOTTOM_ARROW;
         if (!thumbPos) return SCROLL_TOP_RECT;
         pt.y -= rect.top;
-        if (pt.y < (INT)thumbPos) return SCROLL_TOP_RECT;
-        if (pt.y > thumbPos+SYSMETRICS_CYHSCROLL) return SCROLL_BOTTOM_RECT;
+        if (pt.y < thumbPos) return SCROLL_TOP_RECT;
+        if (pt.y > thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
         return SCROLL_THUMB;
     }
     else  /* horizontal */
@@ -262,8 +295,8 @@
         if (pt.x >= rect.right - arrowSize) return SCROLL_BOTTOM_ARROW;
         if (!thumbPos) return SCROLL_TOP_RECT;
         pt.x -= rect.left;
-        if (pt.x < (INT)thumbPos) return SCROLL_TOP_RECT;
-        if (pt.x > thumbPos+SYSMETRICS_CXVSCROLL) return SCROLL_BOTTOM_RECT;
+        if (pt.x < thumbPos) return SCROLL_TOP_RECT;
+        if (pt.x > thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
         return SCROLL_THUMB;
     }
 }
@@ -274,12 +307,12 @@
  *
  * Draw the scroll bar arrows.
  */
-static void SCROLL_DrawArrows( HDC hdc, SCROLLBAR_INFO *infoPtr, RECT16 *rect,
-                               WORD arrowSize, BOOL vertical,
-                               BOOL top_pressed, BOOL bottom_pressed )
+static void SCROLL_DrawArrows( HDC32 hdc, SCROLLBAR_INFO *infoPtr,
+                               RECT32 *rect, INT32 arrowSize, BOOL32 vertical,
+                               BOOL32 top_pressed, BOOL32 bottom_pressed )
 {
-    HDC hdcMem = CreateCompatibleDC( hdc );
-    HBITMAP hbmpPrev = SelectObject( hdcMem, vertical ?
+    HDC32 hdcMem = CreateCompatibleDC( hdc );
+    HBITMAP32 hbmpPrev = SelectObject( hdcMem, vertical ?
                                     TOP_ARROW(infoPtr->flags, top_pressed)
                                     : LEFT_ARROW(infoPtr->flags, top_pressed));
     SetStretchBltMode( hdc, STRETCH_DELETESCANS );
@@ -315,28 +348,29 @@
  *
  * Draw the moving thumb rectangle.
  */
-static void SCROLL_DrawMovingThumb( HDC hdc, RECT16 *rect, BOOL vertical,
-                                    WORD arrowSize, WORD thumbPos )
+static void SCROLL_DrawMovingThumb( HDC32 hdc, RECT32 *rect, BOOL32 vertical,
+                                    INT32 arrowSize, INT32 thumbSize )
 {
-    RECT16 r = *rect;
+    RECT32 r = *rect;
     if (vertical)
     {
-        r.top += thumbPos;
+        r.top += SCROLL_TrackingPos;
         if (r.top < rect->top + arrowSize) r.top = rect->top + arrowSize;
-        if (r.top + SYSMETRICS_CYHSCROLL >= rect->bottom - arrowSize)
-            r.top = rect->bottom - arrowSize - SYSMETRICS_CYHSCROLL - 1;
-        r.bottom = r.top + SYSMETRICS_CYHSCROLL + 1;
+        if (r.top + thumbSize >= rect->bottom - arrowSize)
+            r.top = rect->bottom - arrowSize - thumbSize - 1;
+        r.bottom = r.top + thumbSize + 1;
     }
     else
     {
-        r.left += thumbPos;
+        r.left += SCROLL_TrackingPos;
         if (r.left < rect->left + arrowSize) r.left = rect->left + arrowSize;
-        if (r.left + SYSMETRICS_CXVSCROLL >= rect->right - arrowSize)
-            r.left = rect->right - arrowSize - SYSMETRICS_CXVSCROLL - 1;
-        r.right = r.left + SYSMETRICS_CXVSCROLL + 1;
+        if (r.left + thumbSize >= rect->right - arrowSize)
+            r.left = rect->right - arrowSize - thumbSize - 1;
+        r.right = r.left + thumbSize + 1;
     }
-    InflateRect16( &r, -1, -1 );
-    DrawFocusRect16( hdc, &r );
+    InflateRect32( &r, -1, -1 );
+    DrawFocusRect32( hdc, &r );
+    SCROLL_MovingThumb = !SCROLL_MovingThumb;
 }
 
 
@@ -345,12 +379,13 @@
  *
  * Draw the scroll bar interior (everything except the arrows).
  */
-static void SCROLL_DrawInterior( HWND hwnd, HDC hdc, int nBar, RECT16 *rect,
-                                 WORD arrowSize, WORD thumbPos, WORD flags,
-                                 BOOL vertical, BOOL top_selected,
-                                 BOOL bottom_selected )
+static void SCROLL_DrawInterior( HWND32 hwnd, HDC32 hdc, INT32 nBar, 
+                                 RECT32 *rect, INT32 arrowSize,
+                                 INT32 thumbSize, INT32 thumbPos,
+                                 UINT32 flags, BOOL32 vertical,
+                                 BOOL32 top_selected, BOOL32 bottom_selected )
 {
-    RECT16 r;
+    RECT32 r;
 
       /* Select the correct brush and pen */
 
@@ -364,8 +399,8 @@
     {
         if (nBar == SB_CTL)  /* Only scrollbar controls send WM_CTLCOLOR */
         {
-            HBRUSH hbrush = SendMessage32A( GetParent32(hwnd),
-                                            WM_CTLCOLORSCROLLBAR, hdc, hwnd );
+            HBRUSH32 hbrush = SendMessage32A(GetParent32(hwnd),
+                                             WM_CTLCOLORSCROLLBAR, hdc, hwnd );
             SelectObject( hdc, hbrush );
         }
         else SelectObject( hdc, sysColorObjects.hbrushScrollbar );
@@ -409,11 +444,11 @@
                 thumbPos - arrowSize,
                 top_selected ? 0x0f0000 : PATCOPY );
         r.top += thumbPos - arrowSize;
-        PatBlt( hdc, r.left + 1, r.top + SYSMETRICS_CYHSCROLL + 1,
+        PatBlt( hdc, r.left + 1, r.top + thumbSize + 1,
                 r.right - r.left - 2,
-                r.bottom - r.top - SYSMETRICS_CYHSCROLL - 2,
+                r.bottom - r.top - thumbSize - 2,
                 bottom_selected ? 0x0f0000 : PATCOPY );
-        r.bottom = r.top + SYSMETRICS_CYHSCROLL + 1;
+        r.bottom = r.top + thumbSize + 1;
     }
     else  /* horizontal */
     {
@@ -422,21 +457,26 @@
                 r.bottom - r.top - 2,
                 top_selected ? 0x0f0000 : PATCOPY );
         r.left += thumbPos - arrowSize;
-        PatBlt( hdc, r.left + SYSMETRICS_CYHSCROLL + 1, r.top + 1,
-                r.right - r.left - SYSMETRICS_CYHSCROLL - 2,
+        PatBlt( hdc, r.left + thumbSize + 1, r.top + 1,
+                r.right - r.left - thumbSize - 2,
                 r.bottom - r.top - 2,
                 bottom_selected ? 0x0f0000 : PATCOPY );
-        r.right = r.left + SYSMETRICS_CXVSCROLL + 1;
+        r.right = r.left + thumbSize + 1;
     }
 
       /* Draw the thumb */
 
     SelectObject( hdc, sysColorObjects.hbrushBtnFace );
     Rectangle( hdc, r.left, r.top, r.right, r.bottom );
-    InflateRect16( &r, -1, -1 );
+    InflateRect32( &r, -1, -1 );
     GRAPH_DrawReliefRect( hdc, &r, 1, 2, FALSE );
-    if ((hwndTracking == hwnd) && (nBarTracking == nBar))
-        SCROLL_DrawMovingThumb( hdc, rect, vertical, arrowSize, uTrackingPos);
+    if (SCROLL_MovingThumb &&
+        (SCROLL_TrackingWin == hwnd) &&
+        (SCROLL_TrackingBar == nBar))
+    {
+        SCROLL_DrawMovingThumb( hdc, rect, vertical, arrowSize, thumbSize );
+        SCROLL_MovingThumb = TRUE;
+    }
 }
 
 
@@ -445,11 +485,11 @@
  *
  * Redraw the whole scrollbar.
  */
-void SCROLL_DrawScrollBar( HWND hwnd, HDC hdc, int nBar )
+void SCROLL_DrawScrollBar( HWND32 hwnd, HDC32 hdc, INT32 nBar, BOOL32 arrows )
 {
-    WORD arrowSize, thumbPos;
-    RECT16 rect;
-    BOOL vertical;
+    INT32 arrowSize, thumbSize, thumbPos;
+    RECT32 rect;
+    BOOL32 vertical;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     SCROLLBAR_INFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
 
@@ -458,14 +498,14 @@
         ((nBar == SB_HORZ) && !(wndPtr->dwStyle & WS_HSCROLL))) return;
 
     vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
-                                        &arrowSize, &thumbPos );
+                                        &arrowSize, &thumbSize, &thumbPos );
       /* Draw the arrows */
 
-    if (arrowSize) SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize,
-                                      vertical, FALSE, FALSE );
+    if (arrows && arrowSize) SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize,
+                                                vertical, FALSE, FALSE );
     
-    SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbPos,
-                         infoPtr->flags, vertical, FALSE, FALSE );
+    SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
+                         thumbPos, infoPtr->flags, vertical, FALSE, FALSE );
 }
 
 
@@ -475,26 +515,13 @@
  * Repaint the scroll bar interior after a SetScrollRange() or
  * SetScrollPos() call.
  */
-static void SCROLL_RefreshScrollBar( HWND hwnd, int nBar )
+static void SCROLL_RefreshScrollBar( HWND32 hwnd, INT32 nBar, BOOL32 arrows )
 {
-    WORD arrowSize, thumbPos;
-    RECT16 rect;
-    BOOL vertical;
-    HDC hdc;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    SCROLLBAR_INFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
-
-    if (!wndPtr || !infoPtr ||
-        ((nBar == SB_VERT) && !(wndPtr->dwStyle & WS_VSCROLL)) ||
-        ((nBar == SB_HORZ) && !(wndPtr->dwStyle & WS_HSCROLL))) return;
-
-    vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
-                                        &arrowSize, &thumbPos );
-    hdc = GetDCEx( hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW) );
+    HDC32 hdc = GetDCEx32( hwnd, 0,
+                           DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW) );
     if (!hdc) return;
-    SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbPos,
-                         infoPtr->flags, vertical, FALSE, FALSE );
-    ReleaseDC( hwnd, hdc );
+    SCROLL_DrawScrollBar( hwnd, hdc, nBar, arrows );
+    ReleaseDC32( hwnd, hdc );
 }
 
 
@@ -503,10 +530,10 @@
  *
  * Handle a keyboard event (only for SB_CTL scrollbars).
  */
-static void SCROLL_HandleKbdEvent( HWND hwnd, WORD wParam )
+static void SCROLL_HandleKbdEvent( HWND32 hwnd, WPARAM32 wParam )
 {
     WND *wndPtr = WIN_FindWndPtr( hwnd );
-    WPARAM msg;
+    WPARAM32 msg;
     
     switch(wParam)
     {
@@ -532,33 +559,33 @@
  * 'pt' is the location of the mouse event in client (for SB_CTL) or
  * windows coordinates.
  */
-void SCROLL_HandleScrollEvent( HWND hwnd, int nBar, WORD msg, POINT16 pt )
+void SCROLL_HandleScrollEvent( HWND32 hwnd, INT32 nBar, UINT32 msg, POINT32 pt)
 {
       /* Previous mouse position for timer events */
-    static POINT16 prevPt;
+    static POINT32 prevPt;
       /* Hit test code of the last button-down event */
     static enum SCROLL_HITTEST trackHitTest;
       /* Thumb position when tracking started. */
-    static UINT trackThumbPos;
+    static UINT32 trackThumbPos;
       /* Position in the scroll-bar of the last button-down event. */
-    static int lastClickPos;
+    static INT32 lastClickPos;
       /* Position in the scroll-bar of the last mouse event. */
-    static int lastMousePos;
+    static INT32 lastMousePos;
 
     enum SCROLL_HITTEST hittest;
-    HWND hwndOwner, hwndCtl;
-    BOOL vertical;
-    WORD arrowSize, thumbPos;
-    RECT16 rect;
-    HDC hdc;
+    HWND32 hwndOwner, hwndCtl;
+    BOOL32 vertical;
+    INT32 arrowSize, thumbSize, thumbPos;
+    RECT32 rect;
+    HDC32 hdc;
 
     SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar );
     if (!infoPtr) return;
     if ((trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN)) return;
 
-    hdc = GetDCEx( hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW) );
+    hdc = GetDCEx32( hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
     vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
-                                        &arrowSize, &thumbPos );
+                                        &arrowSize, &thumbSize, &thumbPos );
     hwndOwner = (nBar == SB_CTL) ? GetParent32(hwnd) : hwnd;
     hwndCtl   = (nBar == SB_CTL) ? hwnd : 0;
 
@@ -570,7 +597,7 @@
           lastMousePos  = lastClickPos;
           trackThumbPos = thumbPos;
           prevPt = pt;
-          SetCapture( hwnd );
+          SetCapture32( hwnd );
           if (nBar == SB_CTL) SetFocus32( hwnd );
           break;
 
@@ -619,8 +646,8 @@
         break;
 
     case SCROLL_TOP_RECT:
-        SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbPos,
-                             infoPtr->flags, vertical,
+        SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
+                             thumbPos, infoPtr->flags, vertical,
                              (hittest == trackHitTest), FALSE );
         if (hittest == trackHitTest)
         {
@@ -639,43 +666,46 @@
     case SCROLL_THUMB:
         if (msg == WM_LBUTTONDOWN)
         {
-            SCROLL_DrawMovingThumb( hdc, &rect, vertical, arrowSize,
-                                 trackThumbPos + lastMousePos - lastClickPos );
-            hwndTracking = hwnd;
-            nBarTracking = nBar;
+            SCROLL_TrackingWin = hwnd;
+            SCROLL_TrackingBar = nBar;
+            SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos;
+            SCROLL_DrawMovingThumb(hdc, &rect, vertical, arrowSize, thumbSize);
         }
         else if (msg == WM_LBUTTONUP)
         {
-            hwndTracking = 0;
-            SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbPos,
-                                 infoPtr->flags, vertical, FALSE, FALSE );
+            SCROLL_TrackingWin = 0;
+            SCROLL_MovingThumb = FALSE;
+            SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
+                                 thumbPos, infoPtr->flags, vertical,
+                                 FALSE, FALSE );
         }
         else  /* WM_MOUSEMOVE */
         {
-            UINT pos, val;
+            UINT32 pos;
 
-            if (!PtInRect16( &rect, pt )) pos = lastClickPos;
+            if (!PtInRect32( &rect, pt )) pos = lastClickPos;
             else pos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
             if (pos != lastMousePos)
             {
-                SCROLL_DrawMovingThumb( hdc, &rect, vertical, arrowSize,
-                                 trackThumbPos + lastMousePos - lastClickPos );
-                lastMousePos = pos;
-                val = SCROLL_GetThumbVal( infoPtr, &rect, vertical,
-                                 trackThumbPos + lastMousePos - lastClickPos );
-                /* Save tracking info */
-                uTrackingPos = trackThumbPos + pos - lastClickPos;
-                SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
-                                MAKEWPARAM( SB_THUMBTRACK, val ), hwndCtl );
                 SCROLL_DrawMovingThumb( hdc, &rect, vertical,
-                                        arrowSize, uTrackingPos );
+                                        arrowSize, thumbSize );
+                lastMousePos = pos;
+                SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos;
+                SCROLL_TrackingVal = SCROLL_GetThumbVal( infoPtr, &rect,
+                                                         vertical,
+                                                         SCROLL_TrackingPos );
+                SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+                                MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal),
+                                hwndCtl );
+                SCROLL_DrawMovingThumb( hdc, &rect, vertical,
+                                        arrowSize, thumbSize );
             }
         }
         break;
         
     case SCROLL_BOTTOM_RECT:
-        SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbPos,
-                             infoPtr->flags, vertical,
+        SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
+                             thumbPos, infoPtr->flags, vertical,
                              FALSE, (hittest == trackHitTest) );
         if (hittest == trackHitTest)
         {
@@ -713,7 +743,7 @@
     {
         if (trackHitTest == SCROLL_THUMB)
         {
-            UINT val = SCROLL_GetThumbVal( infoPtr, &rect, vertical,
+            UINT32 val = SCROLL_GetThumbVal( infoPtr, &rect, vertical,
                                  trackThumbPos + lastMousePos - lastClickPos );
             SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
                             MAKEWPARAM( SB_THUMBPOSITION, val ), hwndCtl );
@@ -724,20 +754,21 @@
         trackHitTest = SCROLL_NOWHERE;  /* Terminate tracking */
     }
 
-    ReleaseDC( hwnd, hdc );
+    ReleaseDC32( hwnd, hdc );
 }
 
 
 /***********************************************************************
  *           ScrollBarWndProc
  */
-LONG ScrollBarWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+LRESULT ScrollBarWndProc( HWND32 hwnd, UINT32 message, WPARAM32 wParam,
+                          LPARAM lParam )
 {
     switch(message)
     {
     case WM_CREATE:
         {
-	    CREATESTRUCT16 *lpCreat = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
+	    CREATESTRUCT32A *lpCreat = (CREATESTRUCT32A *)lParam;
             if (lpCreat->style & SBS_SIZEBOX)
             {
                 fprintf( stdnimp, "Unimplemented style SBS_SIZEBOX.\n" );
@@ -775,7 +806,11 @@
     case WM_LBUTTONUP:
     case WM_MOUSEMOVE:
     case WM_SYSTIMER:
-        SCROLL_HandleScrollEvent( hwnd, SB_CTL, message, MAKEPOINT16(lParam) );
+        {
+            POINT32 pt;
+            CONV_POINT16TO32( (POINT16 *)&lParam, &pt );
+            SCROLL_HandleScrollEvent( hwnd, SB_CTL, message, pt );
+        }
         break;
 
     case WM_KEYDOWN:
@@ -790,64 +825,265 @@
 
     case WM_PAINT:
         {
-            PAINTSTRUCT16 ps;
-            HDC16 hdc = BeginPaint16( hwnd, &ps );
-            SCROLL_DrawScrollBar( hwnd, hdc, SB_CTL );
-            EndPaint16( hwnd, &ps );
+            PAINTSTRUCT32 ps;
+            HDC32 hdc = BeginPaint32( hwnd, &ps );
+            SCROLL_DrawScrollBar( hwnd, hdc, SB_CTL, TRUE );
+            EndPaint32( hwnd, &ps );
         }
         break;
 
-    case SBM_SETSCROLLPOS:
-        return SetScrollPos( hwnd, SB_CTL, wParam, (BOOL)lParam );
+    case SBM_SETPOS16:
+    case SBM_SETPOS32:
+        return SetScrollPos32( hwnd, SB_CTL, wParam, (BOOL32)lParam );
 
-    case SBM_GETSCROLLPOS:
-        return GetScrollPos( hwnd, SB_CTL );
+    case SBM_GETPOS16:
+    case SBM_GETPOS32:
+        return GetScrollPos32( hwnd, SB_CTL );
 
-    case SBM_SETSCROLLRANGE:
-        SetScrollRange( hwnd, SB_CTL, LOWORD(lParam), HIWORD(lParam),
-                        wParam  /* FIXME: Is this correct? */ );
+    case SBM_SETRANGE16:
+        SetScrollRange32( hwnd, SB_CTL, LOWORD(lParam), HIWORD(lParam),
+                          wParam  /* FIXME: Is this correct? */ );
         return 0;
 
-    case SBM_ENABLE:
-        return EnableScrollBar( hwnd, SB_CTL, wParam ); /* FIXME: lParam? */
+    case SBM_SETRANGE32:
+        SetScrollRange32( hwnd, SB_CTL, wParam, lParam, FALSE );
+        return 0;  /* FIXME: return previous position */
 
-    case 0x403: /* SBM_REDRAW */
-        fprintf(stdnimp,"ScrollBarWndProc: undocumented message %04x, please report\n", message );
+    case SBM_GETRANGE16:
+        /* FIXME */
+        fprintf( stderr, "ScrollBar: don't know how to handle SBM_GETRANGE16 (wp=%04x,lp=%08lx)\n",
+                 wParam, lParam );
+        return 0;
+
+    case SBM_GETRANGE32:
+        GetScrollRange32( hwnd, SB_CTL, (LPINT32)wParam, (LPINT32)lParam );
+        return 0;
+
+    case SBM_ENABLE_ARROWS16:
+    case SBM_ENABLE_ARROWS32:
+        return EnableScrollBar32( hwnd, SB_CTL, wParam );
+
+    case SBM_SETRANGEREDRAW32:
+        SetScrollRange32( hwnd, SB_CTL, wParam, lParam, TRUE );
+        return 0;  /* FIXME: return previous position */
+        
+    case SBM_SETSCROLLINFO32:
+        return SetScrollInfo32( hwnd, SB_CTL, (SCROLLINFO *)lParam, wParam );
+
+    case SBM_GETSCROLLINFO32:
+        return GetScrollInfo32( hwnd, SB_CTL, (SCROLLINFO *)lParam );
+
+    case 0x00e5:
+    case 0x00e7:
+    case 0x00e8:
+    case 0x00eb:
+    case 0x00ec:
+    case 0x00ed:
+    case 0x00ee:
+    case 0x00ef:
+        fprintf(stderr, "ScrollBar: unknown Win32 msg %04x wp=%08x lp=%08lx\n",
+                message, wParam, lParam );
         break;
 
     default:
-        return DefWindowProc16( hwnd, message, wParam, lParam );
+        if (message >= WM_USER)
+            fprintf( stderr, "ScrollBar: unknown msg %04x wp=%04x lp=%08lx\n",
+                     message, wParam, lParam );
+        return DefWindowProc32A( hwnd, message, wParam, lParam );
     }
     return 0;
 }
 
 
 /*************************************************************************
- *           SetScrollPos   (USER.62)
+ *           SetScrollInfo16   (USER.475)
  */
-int SetScrollPos( HWND hwnd, int nBar, int nPos, BOOL bRedraw )
+INT16 SetScrollInfo16( HWND16 hwnd, INT16 nBar, const SCROLLINFO *info,
+                       BOOL16 bRedraw )
+{
+    return (INT16)SetScrollInfo32( hwnd, nBar, info, bRedraw );
+}
+
+
+/*************************************************************************
+ *           SetScrollInfo32   (USER32.500)
+ */
+INT32 SetScrollInfo32( HWND32 hwnd, INT32 nBar, const SCROLLINFO *info,
+                       BOOL32 bRedraw )
 {
     SCROLLBAR_INFO *infoPtr;
-    INT oldPos;
+    UINT32 new_flags;
+    BOOL32 repaint_arrows = FALSE;
+
+    if (!(infoPtr = SCROLL_GetScrollInfo(hwnd, nBar))) return 0;
+    if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return 0;
+    if ((info->cbSize != sizeof(*info)) &&
+        (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return 0;
+
+    dprintf_scroll( stddeb, "SetScrollInfo: hwnd=%04x bar=%d", hwnd, nBar );
+
+    /* Set the page size */
+
+    if (info->fMask & SIF_PAGE)
+    {
+        dprintf_scroll( stddeb, " page=%d", info->nPage );
+        infoPtr->Page = info->nPage;
+    }
+
+    /* Set the scroll pos */
+
+    if (info->fMask & SIF_POS)
+    {
+        dprintf_scroll( stddeb, " pos=%d", info->nPos );
+        infoPtr->CurVal = info->nPos;
+    }
+
+    /* Set the scroll range */
+
+    if (info->fMask & SIF_RANGE)
+    {
+        dprintf_scroll( stddeb, " min=%d max=%d", info->nMin, info->nMax );
+
+        /* Invalid range -> range is set to (0,0) */
+        if ((info->nMin > info->nMax) ||
+            ((UINT32)(info->nMax - info->nMin) >= 0x80000000))
+        {
+            infoPtr->MinVal = 0;
+            infoPtr->MaxVal = 0;
+        }
+        else
+        {
+            infoPtr->MinVal = info->nMin;
+            infoPtr->MaxVal = info->nMax;
+        }
+    }
+
+    /* Make sure the page size is valid */
+
+    if (infoPtr->Page < 0) infoPtr->Page = 0;
+    else if (infoPtr->Page > infoPtr->MaxVal - infoPtr->MinVal + 1 )
+        infoPtr->Page = infoPtr->MaxVal - infoPtr->MinVal + 1;
+
+    /* Make sure the pos is inside the range */
+
+    if (infoPtr->CurVal < infoPtr->MinVal)
+        infoPtr->CurVal = infoPtr->MinVal;
+    else if (infoPtr->CurVal > infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
+        infoPtr->CurVal = infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 );
+
+    dprintf_scroll( stddeb, "\n   new values: page=%d pos=%d min=%d max=%d\n",
+                    infoPtr->Page, infoPtr->CurVal,
+                    infoPtr->MinVal, infoPtr->MaxVal );
+
+    /* Check if the scrollbar should be hidden or disabled */
+
+    new_flags = infoPtr->flags;
+    if (infoPtr->MinVal >= infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
+    {
+        /* Hide or disable scroll-bar */
+        if (info->fMask & SIF_DISABLENOSCROLL) new_flags = ESB_DISABLE_BOTH;
+        else if (nBar != SB_CTL)
+        {
+            ShowScrollBar32( hwnd, nBar, FALSE );
+            bRedraw = FALSE;  /* No need to repaint anything */
+        }
+    }
+    else  /* Show and enable scroll-bar */
+    {
+        new_flags = 0;
+        if (nBar != SB_CTL) ShowScrollBar32( hwnd, nBar, TRUE );
+    }
+
+    if (infoPtr->flags != new_flags)
+    {
+        infoPtr->flags = new_flags;
+        repaint_arrows = TRUE;
+    }
+
+    if (bRedraw || repaint_arrows)
+        SCROLL_RefreshScrollBar( hwnd, nBar, repaint_arrows );
+
+    /* Return current position */
+
+    return infoPtr->CurVal;
+}
+
+
+/*************************************************************************
+ *           GetScrollInfo16   (USER.476)
+ */
+BOOL16 GetScrollInfo16( HWND16 hwnd, INT16 nBar, LPSCROLLINFO info )
+{
+    return GetScrollInfo32( hwnd, nBar, info );
+}
+
+
+/*************************************************************************
+ *           GetScrollInfo32   (USER32.283)
+ */
+BOOL32 GetScrollInfo32( HWND32 hwnd, INT32 nBar, LPSCROLLINFO info )
+{
+    SCROLLBAR_INFO *infoPtr;
+
+    if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE;
+    if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return FALSE;
+    if ((info->cbSize != sizeof(*info)) &&
+        (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return FALSE;
+
+    if (info->fMask & SIF_PAGE) info->nPage = infoPtr->Page;
+    if (info->fMask & SIF_POS) info->nPos = infoPtr->CurVal;
+    if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info)))
+        info->nTrackPos = (SCROLL_TrackingWin==hwnd) ? SCROLL_TrackingVal : 0;
+    if (info->fMask & SIF_RANGE)
+    {
+	info->nMin = infoPtr->MinVal;
+	info->nMax = infoPtr->MaxVal;
+    }
+    return (info->fMask & SIF_ALL) != 0;
+}
+
+
+/*************************************************************************
+ *           SetScrollPos16   (USER.62)
+ */
+INT16 SetScrollPos16( HWND16 hwnd, INT16 nBar, INT16 nPos, BOOL16 bRedraw )
+{
+    return (INT16)SetScrollPos32( hwnd, nBar, nPos, bRedraw );
+}
+
+
+/*************************************************************************
+ *           SetScrollPos32   (USER32.501)
+ */
+INT32 SetScrollPos32( HWND32 hwnd, INT32 nBar, INT32 nPos, BOOL32 bRedraw )
+{
+    SCROLLINFO info;
+    SCROLLBAR_INFO *infoPtr;
+    INT32 oldPos;
 
     if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0;
-
-    dprintf_scroll( stddeb,"SetScrollPos min=%d max=%d pos=%d\n", 
-                    infoPtr->MinVal, infoPtr->MaxVal, nPos );
-
-    if (nPos < infoPtr->MinVal) nPos = infoPtr->MinVal;
-    else if (nPos > infoPtr->MaxVal) nPos = infoPtr->MaxVal;
-    oldPos = infoPtr->CurVal;
-    infoPtr->CurVal = nPos;
-    if (bRedraw) SCROLL_RefreshScrollBar( hwnd, nBar );
+    oldPos      = infoPtr->CurVal;
+    info.cbSize = sizeof(info);
+    info.nPos   = nPos;
+    info.fMask  = SIF_POS;
+    SetScrollInfo32( hwnd, nBar, &info, bRedraw );
     return oldPos;
 }
 
 
 /*************************************************************************
- *           GetScrollPos   (USER.63)
+ *           GetScrollPos16   (USER.63)
  */
-int GetScrollPos( HWND hwnd, int nBar )
+INT16 GetScrollPos16( HWND16 hwnd, INT16 nBar )
+{
+    return (INT16)GetScrollPos32( hwnd, nBar );
+}
+
+
+/*************************************************************************
+ *           GetScrollPos32   (USER32.284)
+ */
+INT32 GetScrollPos32( HWND32 hwnd, INT32 nBar )
 {
     SCROLLBAR_INFO *infoPtr;
 
@@ -857,30 +1093,34 @@
 
 
 /*************************************************************************
- *           SetScrollRange   (USER.64)
+ *           SetScrollRange16   (USER.64)
  */
-void SetScrollRange(HWND hwnd, int nBar, int MinVal, int MaxVal, BOOL bRedraw)
+void SetScrollRange16( HWND16 hwnd, INT16 nBar, INT16 MinVal, INT16 MaxVal,
+                       BOOL16 bRedraw )
 {
-    SCROLLBAR_INFO *infoPtr;
-
-    if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return;
-
-    dprintf_scroll( stddeb,"SetScrollRange hwnd=%04x bar=%d min=%d max=%d\n",
-                    hwnd, nBar, MinVal, MaxVal );
-
-      /* Invalid range -> range is set to (0,0) */
-    if ((MinVal > MaxVal) || ((long)MaxVal - MinVal > 32767L))
-        MinVal = MaxVal = 0;
-    if (infoPtr->CurVal < MinVal) infoPtr->CurVal = MinVal;
-    else if (infoPtr->CurVal > MaxVal) infoPtr->CurVal = MaxVal;
-    infoPtr->MinVal = MinVal;
-    infoPtr->MaxVal = MaxVal;
-
-      /* Non-client scroll-bar is hidden if min==max */
-    if (nBar != SB_CTL) ShowScrollBar( hwnd, nBar, (MinVal != MaxVal) );
-    if (bRedraw) SCROLL_RefreshScrollBar( hwnd, nBar );
+    /* Invalid range -> range is set to (0,0) */
+    if ((INT32)MaxVal - (INT32)MinVal > 0x7fff) MinVal = MaxVal = 0;
+    SetScrollRange32( hwnd, nBar, MinVal, MaxVal, bRedraw );
 }
 
+
+/*************************************************************************
+ *           SetScrollRange32   (USER32.502)
+ */
+BOOL32 SetScrollRange32( HWND32 hwnd, INT32 nBar, INT32 MinVal, INT32 MaxVal,
+                         BOOL32 bRedraw )
+{
+    SCROLLINFO info;
+
+    info.cbSize = sizeof(info);
+    info.nMin   = MinVal;
+    info.nMax   = MaxVal;
+    info.fMask  = SIF_RANGE;
+    SetScrollInfo32( hwnd, nBar, &info, bRedraw );
+    return TRUE;
+}
+
+
 /*************************************************************************
  *	     SCROLL_SetNCSbState
  *
@@ -914,44 +1154,74 @@
   return wndPtr->dwStyle & (WS_VSCROLL | WS_HSCROLL);
 }
 
-/*************************************************************************
- *           GetScrollRange   (USER.65)
- */
-void GetScrollRange(HWND hwnd, int nBar, LPINT16 lpMin, LPINT16 lpMax)
-{
-    SCROLLBAR_INFO *infoPtr;
 
-    if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return;
-    if (lpMin) *lpMin = infoPtr->MinVal;
-    if (lpMax) *lpMax = infoPtr->MaxVal;
+/*************************************************************************
+ *           GetScrollRange16   (USER.65)
+ */
+BOOL16 GetScrollRange16( HWND16 hwnd, INT16 nBar, LPINT16 lpMin, LPINT16 lpMax)
+{
+    INT32 min, max;
+    BOOL16 ret = GetScrollRange32( hwnd, nBar, &min, &max );
+    if (lpMin) *lpMin = min;
+    if (lpMax) *lpMax = max;
+    return ret;
 }
 
 
 /*************************************************************************
- *           ShowScrollBar   (USER.267)
+ *           GetScrollRange32   (USER32.285)
  */
-void ShowScrollBar( HWND hwnd, WORD wBar, BOOL fShow )
+BOOL32 GetScrollRange32( HWND32 hwnd, INT32 nBar, LPINT32 lpMin, LPINT32 lpMax)
+{
+    SCROLLBAR_INFO *infoPtr;
+
+    if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar )))
+    {
+        if (lpMin) lpMin = 0;
+        if (lpMax) lpMax = 0;
+        return FALSE;
+    }
+    if (lpMin) *lpMin = infoPtr->MinVal;
+    if (lpMax) *lpMax = infoPtr->MaxVal;
+    return TRUE;
+}
+
+
+/*************************************************************************
+ *           ShowScrollBar16   (USER.267)
+ */
+void ShowScrollBar16( HWND16 hwnd, INT16 nBar, BOOL16 fShow )
+{
+    ShowScrollBar32( hwnd, nBar, fShow );
+}
+
+
+/*************************************************************************
+ *           ShowScrollBar32   (USER32.531)
+ */
+BOOL32 ShowScrollBar32( HWND32 hwnd, INT32 nBar, BOOL32 fShow )
 {
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
-    if (!wndPtr) return;
-    dprintf_scroll( stddeb, "ShowScrollBar: hwnd=%04x bar=%d on=%d\n", hwnd, wBar, fShow );
+    if (!wndPtr) return FALSE;
+    dprintf_scroll( stddeb, "ShowScrollBar: hwnd=%04x bar=%d on=%d\n",
+                    hwnd, nBar, fShow );
 
-    switch(wBar)
+    switch(nBar)
     {
     case SB_CTL:
         ShowWindow( hwnd, fShow ? SW_SHOW : SW_HIDE );
-        return;
+        return TRUE;
 
     case SB_HORZ:
         if (fShow)
         {
-            if (wndPtr->dwStyle & WS_HSCROLL) return;
+            if (wndPtr->dwStyle & WS_HSCROLL) return TRUE;
             wndPtr->dwStyle |= WS_HSCROLL;
         }
         else  /* hide it */
         {
-            if (!(wndPtr->dwStyle & WS_HSCROLL)) return;
+            if (!(wndPtr->dwStyle & WS_HSCROLL)) return TRUE;
             wndPtr->dwStyle &= ~WS_HSCROLL;
         }
         break;
@@ -959,12 +1229,12 @@
     case SB_VERT:
         if (fShow)
         {
-            if (wndPtr->dwStyle & WS_VSCROLL) return;
+            if (wndPtr->dwStyle & WS_VSCROLL) return TRUE;
             wndPtr->dwStyle |= WS_VSCROLL;
         }
         else  /* hide it */
         {
-            if (!(wndPtr->dwStyle & WS_VSCROLL)) return;
+            if (!(wndPtr->dwStyle & WS_VSCROLL)) return TRUE;
             wndPtr->dwStyle &= ~WS_VSCROLL;
         }
         break;
@@ -973,98 +1243,50 @@
         if (fShow)
         {
             if ((wndPtr->dwStyle & WS_HSCROLL)
-                && (wndPtr->dwStyle & WS_VSCROLL)) return;
+                && (wndPtr->dwStyle & WS_VSCROLL)) return TRUE;
             wndPtr->dwStyle |= WS_HSCROLL | WS_VSCROLL;
         }
         else  /* hide it */
         {
             if (!(wndPtr->dwStyle & WS_HSCROLL)
-                && !(wndPtr->dwStyle & WS_HSCROLL)) return;
+                && !(wndPtr->dwStyle & WS_HSCROLL)) return TRUE;
             wndPtr->dwStyle &= ~(WS_HSCROLL | WS_VSCROLL);
         }
         break;
 
     default:
-        return;  /* Nothing to do! */
+        return TRUE;  /* Nothing to do! */
     }
     SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
                  | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
-}
-
-
-/*************************************************************************
- *           EnableScrollBar   (USER.482)
- */
-BOOL EnableScrollBar( HWND hwnd, UINT nBar, UINT flags )
-{
-    SCROLLBAR_INFO *infoPtr;
-    HDC hdc;
-
-    if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE;
-    dprintf_scroll( stddeb, "EnableScrollBar: %04x %d %d\n", hwnd, nBar, flags );
-    flags &= ESB_DISABLE_BOTH;
-    if (infoPtr->flags == flags) return FALSE;
-    infoPtr->flags = flags;
-
-      /* Redraw the whole scroll bar */
-    hdc = GetDCEx( hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW) );
-    SCROLL_DrawScrollBar( hwnd, hdc, nBar );
-    ReleaseDC( hwnd, hdc );
     return TRUE;
 }
 
 
 /*************************************************************************
- *           SetScrollInfo32   (USER32.500)
+ *           EnableScrollBar16   (USER.482)
  */
-INT32 SetScrollInfo32( HWND32 hwnd, INT32 nBar, LPSCROLLINFO32 lpsi,
-                       BOOL32 bRedraw )
+BOOL16 EnableScrollBar16( HWND16 hwnd, INT16 nBar, UINT16 flags )
 {
-    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);
+    return EnableScrollBar32( hwnd, nBar, flags );
 }
 
 
 /*************************************************************************
- *           GetScrollInfo32   (USER32.283)
+ *           EnableScrollBar32   (USER32.170)
  */
-BOOL32 GetScrollInfo32( HWND32 hwnd, INT32 nBar, LPSCROLLINFO32 lpsi )
+BOOL32 EnableScrollBar32( HWND32 hwnd, INT32 nBar, UINT32 flags )
 {
     SCROLLBAR_INFO *infoPtr;
 
     if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE;
+    dprintf_scroll( stddeb, "EnableScrollBar: %04x %d %d\n",
+                    hwnd, nBar, flags );
+    flags &= ESB_DISABLE_BOTH;
+    if (infoPtr->flags == flags) return FALSE;
+    infoPtr->flags = flags;
 
-    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;
-    }
+    /* Redraw the whole scroll bar */
+    SCROLL_RefreshScrollBar( hwnd, nBar, TRUE );
     return TRUE;
 }
diff --git a/controls/status.c b/controls/status.c
index 3217b2b..7996a26 100644
--- a/controls/status.c
+++ b/controls/status.c
@@ -4,6 +4,7 @@
  * Copyright 1996 Bruce Milner
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <stdio.h>
 #include <stdlib.h>
 #include "windows.h"
@@ -226,9 +227,9 @@
     }
     SW_SetPartBounds(hwnd, self);
 
-    hdc = GetDC(hwnd);
+    hdc = GetDC32(hwnd);
     SW_Refresh(hwnd, hdc, self);
-    ReleaseDC(hwnd, hdc);
+    ReleaseDC32(hwnd, hdc);
     return TRUE;
 }
 
@@ -272,11 +273,11 @@
     self->part0.style = 0;
 
     height = 40;
-    if ((hdc = GetDC(0))) {
+    if ((hdc = GetDC32(0))) {
 	TEXTMETRIC32A tm;
 	GetTextMetrics32A(hdc, &tm);
 	self->textHeight = tm.tmHeight;
-	ReleaseDC(0, hdc);
+	ReleaseDC32(0, hdc);
     }
 
     parent = GetParent32(hwnd);
@@ -369,9 +370,9 @@
 
     simple = (BOOL32) wParam;
     self->simple = simple;
-    hdc = GetDC(hwnd);
+    hdc = GetDC32(hwnd);
     SW_Refresh(hwnd, hdc, self);
-    ReleaseDC(hwnd, hdc);
+    ReleaseDC32(hwnd, hdc);
     return TRUE;
 }
 
diff --git a/controls/widgets.c b/controls/widgets.c
index 7495665..0235053 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -29,8 +29,6 @@
 {
     { CS_GLOBALCLASS | CS_PARENTDC,
        sizeof(STATICINFO), 0, "StaticWndProc", "STATIC" },
-    { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
-      sizeof(SCROLLBAR_INFO), 0, "ScrollBarWndProc", "SCROLLBAR" },
     { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
       8, 0, "ListBoxWndProc", "LISTBOX" },
     { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
@@ -54,9 +52,11 @@
 static WNDCLASS32A WIDGETS_BuiltinClasses32[] =
 {
     { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
-          ButtonWndProc, 0, sizeof(BUTTONINFO), 0, 0, 0, 0, 0, "BUTTON" },
+      ButtonWndProc, 0, sizeof(BUTTONINFO), 0, 0, 0, 0, 0, "BUTTON" },
+    { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
+      ScrollBarWndProc, 0, sizeof(SCROLLBAR_INFO), 0, 0, 0, 0, 0, "SCROLLBAR"},
     { CS_GLOBALCLASS, DesktopWndProc, 0, sizeof(DESKTOPINFO),
-          0, 0, 0, 0, 0, DESKTOP_CLASS_NAME }
+      0, 0, 0, 0, 0, DESKTOP_CLASS_NAME }
 };
 
 #define NB_BUILTIN_CLASSES32 \
diff --git a/debugger/memory.c b/debugger/memory.c
index 81ce74d..a51e915 100644
--- a/debugger/memory.c
+++ b/debugger/memory.c
@@ -11,6 +11,64 @@
 #include "debugger.h"
 
 
+/************************************************************
+ *   
+ *  Check if linear pointer in [addr, addr+size[
+ *     read  (rwflag == 1)
+ *   or
+ *     write (rwflag == 0)
+ ************************************************************/
+
+#ifdef linux
+BOOL32 DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag)
+{
+  FILE *fp;
+  char buf[80];      /* temporary line buffer */
+  char prot[5];      /* protection string */
+  char *start, *end;
+  int ret = TRUE;
+
+  /* 
+     The entries in /proc/self/maps are of the form:
+     08000000-08002000 r-xp 00000000 03:41 2361
+     08002000-08003000 rw-p 00001000 03:41 2361
+     08003000-08005000 rwxp 00000000 00:00 0
+     40000000-40005000 r-xp 00000000 03:41 67219
+     40005000-40006000 rw-p 00004000 03:41 67219
+     40006000-40007000 rw-p 00000000 00:00 0
+     ...
+      start    end     perm   ???    major:minor inode
+
+     Only permissions start and end are used here
+     */
+  
+  if (!(fp = fopen("/proc/self/maps", "r")))
+    return FALSE; 
+
+  while (fgets( buf, 79, fp)) {
+    sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot);
+    if ( end < addr)
+      continue;
+    if (start <= addr && addr+size < end) {
+      if (rwflag) 
+	ret = (prot[0] != 'r'); /* test for reading */
+      else
+	ret = (prot[1] != 'w'); /* test for writing */
+    }
+    break;
+  }
+  fclose( fp);
+  return ret;
+}
+#else  /* linux */
+/* FIXME: code needed for BSD et al. */
+BOOL32 DEBUG_checkmap_bad(char *addr, size_t size, int rwflag)
+{
+    return FALSE;
+}
+#endif  /* linux */
+
+
 /***********************************************************************
  *           DEBUG_IsBadReadPtr
  *
@@ -19,11 +77,12 @@
 BOOL32 DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
 {
     if (address->seg)  /* segmented addr */
-        return IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
-                                                 (WORD)address->seg ), size );
-        /* FIXME: should check if resulting linear addr is readable */
-    else  /* linear address */
-        return FALSE;  /* FIXME: should do some checks here */
+    {
+        if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
+                                              (WORD)address->seg ), size ))
+            return TRUE;
+    }
+    return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
 }
 
 
@@ -35,13 +94,14 @@
 BOOL32 DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
 {
     if (address->seg)  /* segmented addr */
+    {
         /* Note: we use IsBadReadPtr here because we are */
         /* always allowed to write to read-only segments */
-        return IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
-                                                 (WORD)address->seg ), size );
-        /* FIXME: should check if resulting linear addr is writable */
-    else  /* linear address */
-        return FALSE;  /* FIXME: should do some checks here */
+        if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
+                                              (WORD)address->seg ), size ))
+            return TRUE;
+    }
+    return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
 }
 
 
diff --git a/files/directory.c b/files/directory.c
index 07049f6..5d12ef2 100644
--- a/files/directory.c
+++ b/files/directory.c
@@ -15,10 +15,8 @@
 #include "msdos.h"
 #include "options.h"
 #include "xmalloc.h"
-#include "string32.h"
 #include "stddebug.h"
 #include "debug.h"
-#include "string32.h"
 
 #define MAX_PATH_ELEMENTS 20
 
@@ -200,18 +198,15 @@
  */
 UINT32 GetTempPath32W( UINT32 count, LPWSTR path )
 {
-    LPSTR tmp = (char*)xmalloc(count);
-    UINT32 len = GetTempPath32A( count, tmp );
-    if (path) STRING32_AnsiToUni( path, tmp );
-    free(tmp);
-    return len;
+    if (path) lstrcpynAtoW( path, DIR_TempDosDir, count );
+    return strlen( DIR_TempDosDir );
 }
 
 
 /***********************************************************************
  *           DIR_GetTempUnixDir
  */
-UINT DIR_GetTempUnixDir( LPSTR path, UINT count )
+UINT32 DIR_GetTempUnixDir( LPSTR path, UINT32 count )
 {
     if (path) lstrcpyn32A( path, DIR_TempUnixDir, count );
     return strlen( DIR_TempUnixDir );
@@ -221,7 +216,7 @@
 /***********************************************************************
  *           DIR_GetWindowsUnixDir
  */
-UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count )
+UINT32 DIR_GetWindowsUnixDir( LPSTR path, UINT32 count )
 {
     if (path) lstrcpyn32A( path, DIR_WindowsUnixDir, count );
     return strlen( DIR_WindowsUnixDir );
@@ -231,7 +226,7 @@
 /***********************************************************************
  *           DIR_GetSystemUnixDir
  */
-UINT DIR_GetSystemUnixDir( LPSTR path, UINT count )
+UINT32 DIR_GetSystemUnixDir( LPSTR path, UINT32 count )
 {
     if (path) lstrcpyn32A( path, DIR_SystemUnixDir, count );
     return strlen( DIR_SystemUnixDir );
@@ -241,7 +236,7 @@
 /***********************************************************************
  *           DIR_GetDosPath
  */
-UINT DIR_GetDosPath( int element, LPSTR path, UINT count )
+UINT32 DIR_GetDosPath( INT32 element, LPSTR path, UINT32 count )
 {
     if ((element < 0) || (element >= DIR_PathElements)) return 0;
     if (path) lstrcpyn32A( path, DIR_DosPath[element], count );
@@ -272,10 +267,20 @@
     return MAKELONG( GetTempDrive(ignored) | (':' << 8), 1 );
 }
 
+
 /***********************************************************************
- *           GetWindowsDirectory   (KERNEL.134)
+ *           GetWindowsDirectory16   (KERNEL.134)
  */
-UINT GetWindowsDirectory( LPSTR path, UINT count )
+UINT16 GetWindowsDirectory16( LPSTR path, UINT16 count )
+{
+    return (UINT16)GetWindowsDirectory32A( path, count );
+}
+
+
+/***********************************************************************
+ *           GetWindowsDirectory32A   (KERNEL32.311)
+ */
+UINT32 GetWindowsDirectory32A( LPSTR path, UINT32 count )
 {
     if (path) lstrcpyn32A( path, DIR_WindowsDosDir, count );
     return strlen( DIR_WindowsDosDir );
@@ -283,6 +288,16 @@
 
 
 /***********************************************************************
+ *           GetWindowsDirectory32W   (KERNEL32.312)
+ */
+UINT32 GetWindowsDirectory32W( LPWSTR path, UINT32 count )
+{
+    if (path) lstrcpynAtoW( path, DIR_WindowsDosDir, count );
+    return strlen( DIR_WindowsDosDir );
+}
+
+
+/***********************************************************************
  *           GetSystemDirectory16   (KERNEL.135)
  */
 UINT16 GetSystemDirectory16( LPSTR path, UINT16 count )
@@ -306,11 +321,6 @@
  */
 UINT32 GetSystemDirectory32W( LPWSTR path, UINT32 count )
 {
-    if (path)
-    {
-        LPWSTR tmp = STRING32_DupAnsiToUni( DIR_SystemDosDir );
-        lstrcpyn32W( path, tmp, count );
-	free (tmp);
-    }
+    if (path) lstrcpynAtoW( path, DIR_SystemDosDir, count );
     return strlen( DIR_SystemDosDir );
 }
diff --git a/files/dos_fs.c b/files/dos_fs.c
index 376368a..4ed1544 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -777,3 +777,15 @@
     lstrcpynAtoW( shortpath, dostruename, shortlen );
     return strlen(dostruename);
 }
+
+/***********************************************************************
+ *           GetFullPathNameA   (KERNEL32.272)
+ */
+DWORD GetFullPathName32A( LPCSTR fn, DWORD buflen, LPSTR buf, LPSTR *lastpart) {
+	dprintf_file(stddeb,"GetFullPathNameA(%s)\n",fn);
+	/* FIXME */
+	lstrcpyn32A(buf,fn,buflen);
+	if (lastpart)
+		*lastpart=strrchr(buf,'\\');
+	return strlen(fn);
+}
diff --git a/files/file.c b/files/file.c
index ee4a7e8..2d786f2 100644
--- a/files/file.c
+++ b/files/file.c
@@ -542,23 +542,6 @@
 
 
 /***********************************************************************
- *           FILE_Read
- */
-INT32 FILE_Read( HFILE hFile, LPVOID buffer, UINT32 count )
-{
-    DOS_FILE *file;
-    INT32 result;
-
-    dprintf_file( stddeb, "FILE_Read: %d %p %d\n", hFile, buffer, count );
-    if (!(file = FILE_GetFile( hFile ))) return -1;
-    if (!count) return 0;
-    if ((result = read( file->unix_handle, buffer, count )) == -1)
-        FILE_SetDosError();
-    return result;
-}
-
-
-/***********************************************************************
  *           GetTempFileName16   (KERNEL.97)
  */
 UINT16 GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique,
@@ -735,7 +718,7 @@
 
     /* Try the Windows directory */
 
-    GetWindowsDirectory( ofs->szPathName, len );
+    GetWindowsDirectory32A( ofs->szPathName, len );
     strcat( ofs->szPathName, "\\" );
     strcat( ofs->szPathName, name );
     if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )) != NULL)
@@ -893,7 +876,7 @@
         goto found;
 
     /* Try the Windows directory */
-    GetWindowsDirectory(testpath,len);
+    GetWindowsDirectory32A(testpath,len);
     strcat(testpath,"\\");
     strcat(testpath,name);
     if ((unixName = DOSFS_GetUnixFileName((LPCSTR)testpath,TRUE))!=NULL)
@@ -991,7 +974,7 @@
     /* Some programs pass a count larger than the allocated buffer */
     maxlen = GetSelectorLimit( SELECTOROF(buffer) ) - OFFSETOF(buffer) + 1;
     if (count > maxlen) count = maxlen;
-    return FILE_Read( hFile, PTR_SEG_TO_LIN(buffer), count );
+    return _lread32( hFile, PTR_SEG_TO_LIN(buffer), count );
 }
 
 
@@ -1009,7 +992,15 @@
  */
 UINT32 _lread32( HFILE hFile, LPVOID buffer, UINT32 count )
 {
-    return (UINT32)FILE_Read( hFile, buffer, (LONG)count );
+    DOS_FILE *file;
+    UINT32 result;
+
+    dprintf_file( stddeb, "_lread32: %d %p %d\n", hFile, buffer, count );
+    if (!(file = FILE_GetFile( hFile ))) return -1;
+    if (!count) return 0;
+    if ((result = read( file->unix_handle, buffer, count )) == -1)
+        FILE_SetDosError();
+    return result;
 }
 
 
@@ -1018,7 +1009,7 @@
  */
 UINT16 _lread16( HFILE hFile, LPVOID buffer, UINT16 count )
 {
-    return (UINT16)FILE_Read( hFile, buffer, (LONG)count );
+    return (UINT16)_lread32( hFile, buffer, (LONG)count );
 }
 
 
@@ -1131,7 +1122,7 @@
  */
 LONG _hread( HFILE hFile, LPVOID buffer, LONG count)
 {
-    return FILE_Read( hFile, buffer, count );
+    return _lread32( hFile, buffer, count );
 }
 
 
diff --git a/files/profile.c b/files/profile.c
index b7c0595..4570b5e 100644
--- a/files/profile.c
+++ b/files/profile.c
@@ -382,7 +382,7 @@
     }
     else
     {
-        GetWindowsDirectory( buffer, sizeof(buffer) );
+        GetWindowsDirectory32A( buffer, sizeof(buffer) );
         strcat( buffer, "\\" );
         strcat( buffer, filename );
         if (!(dos_name = DOSFS_GetDosTrueName( buffer, FALSE ))) return FALSE;
diff --git a/if1632/crtdll.spec b/if1632/crtdll.spec
index b290cb0..bd07234 100644
--- a/if1632/crtdll.spec
+++ b/if1632/crtdll.spec
@@ -483,7 +483,7 @@
 478 stub strtod
 479 stub strtok
 480 stub strtol
-481 stub strtoul
+481 cdecl strtoul(ptr ptr long) strtoul
 482 stub strxfrm
 483 stub swprintf
 484 stub swscanf
diff --git a/if1632/gdi32.spec b/if1632/gdi32.spec
index d70567e..443043b 100644
--- a/if1632/gdi32.spec
+++ b/if1632/gdi32.spec
@@ -283,7 +283,7 @@
 0276 stub Polyline
 0277 stub PolylineTo
 0278 stdcall PtInRegion(long long long) PtInRegion
-0279 stub PtVisible
+0279 stdcall PtVisible(long long long) PtVisible
 0280 stdcall RealizePalette(long) RealizePalette
 0281 stdcall RectInRegion(long ptr) RectInRegion32
 0282 stdcall RectVisible(long ptr) RectVisible32
@@ -301,7 +301,7 @@
 0294 stdcall ScaleWindowExtEx(long long long long long ptr) ScaleWindowExtEx32
 0295 stub SelectBrushLocal
 0296 stub SelectClipPath
-0297 stub SelectClipRgn
+0297 stdcall SelectClipRgn(long long) SelectClipRgn
 0298 stub SelectFontLocal
 0299 stdcall SelectObject(long long) SelectObject
 0300 stdcall SelectPalette(long long long) SelectPalette
@@ -356,7 +356,8 @@
 0348 stub StartDocW
 0349 stub StartPage
 0350 stdcall StretchBlt(long long long long long long long long long long long) StretchBlt
-0351 stub StretchDIBits
+0351 stdcall StretchDIBits(long long long long long long long
+                               long long long long long long) StretchDIBits
 0352 stub StrokeAndFillPath
 0353 stub StrokePath
 0354 stub SwapBuffers
@@ -392,5 +393,4 @@
 0383 stub UpdateICMRegKeyA
 0384 stub UpdateICMRegKeyW
 0385 stub gdiPlaySpoolStream
-
-
+0386 return SetObjectOwner 8 0
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 39c0ca1..604c87c 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -132,7 +132,7 @@
 131 pascal GetDOSEnvironment() GetDOSEnvironment
 132 pascal GetWinFlags() GetWinFlags
 133 pascal16 GetExePtr(word) GetExePtr
-134 pascal16 GetWindowsDirectory(ptr word) GetWindowsDirectory
+134 pascal16 GetWindowsDirectory(ptr word) GetWindowsDirectory16
 135 pascal16 GetSystemDirectory(ptr word) GetSystemDirectory16
 136 pascal16 GetDriveType(byte) GetDriveType16
 137 pascal FatalAppExit(word ptr) FatalAppExit
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index 18d2279..ca3fc9b 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -192,7 +192,7 @@
 0187 stub GetConsoleInputWaitHandle
 0188 stub GetConsoleMode
 0189 stub GetConsoleOutputCP
-0190 stub GetConsoleScreenBufferInfo
+0190 stdcall GetConsoleScreenBufferInfo(long ptr) GetConsoleScreenBufferInfo
 0191 stub GetConsoleTitleA
 0192 stub GetConsoleTitleW
 0193 stub GetCurrencyFormatA
@@ -225,10 +225,10 @@
 0220 stub GetFileSize
 0221 stub GetFileTime
 0222    stdcall GetFileType(long) GetFileType
-0223 stub GetFullPathNameA
+0223 stdcall GetFullPathNameA(ptr long ptr ptr) GetFullPathName32A
 0224 stub GetFullPathNameW
 0225 stub GetHandleInformation
-0226 stub GetLargestConsoleWindowSize
+0226 stdcall GetLargestConsoleWindowSize(long) GetLargestConsoleWindowSize
 0227    stdcall GetLastError() GetLastError
 0228    stdcall GetLocalTime(ptr) GetLocalTime
 0229 stdcall GetLocaleInfoA(long long ptr long) GetLocaleInfoA
@@ -283,7 +283,7 @@
 0278 stub GetStringTypeExW
 0279 stub GetStringTypeW
 0280 stdcall GetSystemDefaultLCID() GetSystemDefaultLCID
-0281 stub GetSystemDefaultLangID
+0281 stdcall GetSystemDefaultLangID() GetSystemDefaultLangID
 0282 stdcall GetSystemDirectoryA(ptr long) GetSystemDirectory32A
 0283 stdcall GetSystemDirectoryW(ptr long) GetSystemDirectory32W
 0284 stub GetSystemInfo
@@ -306,15 +306,15 @@
 0301 stub GetTimeFormatW
 0302    stdcall GetTimeZoneInformation(ptr) GetTimeZoneInformation
 0303 stdcall GetUserDefaultLCID() GetUserDefaultLCID
-0304 stub GetUserDefaultLangID
+0304 stdcall GetUserDefaultLangID() GetUserDefaultLangID
 0305 stub GetVDMCurrentDirectories
 0306 stdcall GetVersion() GetVersion32
 0307 stdcall GetVersionExA(ptr) GetVersionEx32A
 0308 stdcall GetVersionExW(ptr) GetVersionEx32W
 0309 stdcall GetVolumeInformationA(ptr ptr long ptr ptr ptr ptr long) GetVolumeInformation32A
 0310 stdcall GetVolumeInformationW(ptr ptr long ptr ptr ptr ptr long) GetVolumeInformation32W
-0311 stdcall GetWindowsDirectoryA(ptr long) GetWindowsDirectory
-0312 stub GetWindowsDirectoryW
+0311 stdcall GetWindowsDirectoryA(ptr long) GetWindowsDirectory32A
+0312 stdcall GetWindowsDirectoryW(ptr long) GetWindowsDirectory32W
 0313 stdcall GlobalAddAtomA(ptr) GlobalAddAtom32A
 0314 stdcall GlobalAddAtomW(ptr) GlobalAddAtom32W
 0315 stdcall GlobalAlloc(long long) GlobalAlloc32
@@ -363,7 +363,7 @@
 0358 return IsDBCSLeadByte 4 0
 0359 stub IsDBCSLeadByteEx
 0360 stub IsValidCodePage
-0361 stub IsValidLocale
+0361 stdcall IsValidLocale(long long) IsValidLocale
 0362 stub LCMapStringA
 0363 stub LCMapStringW
 0364 stdcall LeaveCriticalSection(ptr)	LeaveCriticalSection
@@ -556,7 +556,7 @@
 0551 stub VirtualLock
 0552 stub VirtualProtect
 0553 stub VirtualProtectEx
-0554 stub VirtualQuery
+0554 stdcall VirtualQuery(ptr ptr long) VirtualQuery
 0555 stub VirtualQueryEx
 0556 stub VirtualUnlock
 0557 stub WaitCommEvent
@@ -639,3 +639,13 @@
 0633 stub MakeCriticalSectionGlobal
 #extra late additions
 0634 stdcall ThunkConnect32(ptr ptr ptr ptr ptr ptr) ThunkConnect32
+0636 stub SUnMapLS
+0637 stub SMapLS
+0638 stdcall ReinitializeCriticalSection(ptr) ReinitializeCriticalSection
+0639 stub FT_Thunk
+0640 stub FT_Exit20
+0641 stub SMapLS_IP_EBP_12
+0642 stub SUnMapLS_IP_EBP_12
+0643 stub MapSLFix
+0644 stub UnMapSLFixArray
+0645 stub dprintf
diff --git a/if1632/shell32.spec b/if1632/shell32.spec
index acb26b4..4b513b4 100644
--- a/if1632/shell32.spec
+++ b/if1632/shell32.spec
@@ -56,8 +56,8 @@
 0051 stub SHFormatDrive
 0052 stub SHFreeNameMappings
 0053 stub SHGetDesktopFolder
-0054 stub SHGetFileInfo
-0055 stub SHGetFileInfoA
+0054 stdcall SHGetFileInfo(ptr long ptr long long) SHGetFileInfo32A
+0055 stdcall SHGetFileInfoA(ptr long ptr long long) SHGetFileInfo32A
 0056 stub SHGetFileInfoW
 0057 stub SHGetInstanceExplorer
 0058 stub SHGetMalloc
diff --git a/if1632/user.spec b/if1632/user.spec
index 7a05205..b833439 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -17,7 +17,7 @@
 15  pascal   GetCurrentTime() GetCurrentTime
 16  pascal16 ClipCursor(ptr) ClipCursor16
 17  pascal16 GetCursorPos(ptr) GetCursorPos16
-18  pascal16 SetCapture(word) SetCapture
+18  pascal16 SetCapture(word) SetCapture16
 19  pascal16 ReleaseCapture() ReleaseCapture
 20  pascal16 SetDoubleClickTime(word) SetDoubleClickTime
 21  pascal16 GetDoubleClickTime() GetDoubleClickTime
@@ -62,13 +62,13 @@
 59  pascal16 SetActiveWindow(word) SetActiveWindow
 60  pascal16 GetActiveWindow() GetActiveWindow
 61  pascal16 ScrollWindow(word s_word s_word ptr ptr) ScrollWindow
-62  pascal16 SetScrollPos(word word s_word word) SetScrollPos
-63  pascal16 GetScrollPos(word word) GetScrollPos
-64  pascal16 SetScrollRange(word word s_word s_word word) SetScrollRange
-65  pascal16 GetScrollRange(word word ptr ptr) GetScrollRange
-66  pascal16 GetDC(word) GetDC
-67  pascal16 GetWindowDC(word) GetWindowDC
-68  pascal16 ReleaseDC(word word) ReleaseDC
+62  pascal16 SetScrollPos(word word s_word word) SetScrollPos16
+63  pascal16 GetScrollPos(word word) GetScrollPos16
+64  pascal16 SetScrollRange(word word s_word s_word word) SetScrollRange16
+65  pascal16 GetScrollRange(word word ptr ptr) GetScrollRange16
+66  pascal16 GetDC(word) GetDC16
+67  pascal16 GetWindowDC(word) GetWindowDC16
+68  pascal16 ReleaseDC(word word) ReleaseDC16
 69  pascal16 SetCursor(word) SetCursor
 70  pascal16 SetCursorPos(word word) SetCursorPos
 71  pascal16 ShowCursor(word) ShowCursor
@@ -117,7 +117,7 @@
 115 pascal16 ReplyMessage(long) ReplyMessage
 116 pascal16 PostAppMessage(word word word long) PostAppMessage
 118 pascal16 RegisterWindowMessage(segptr) RegisterWindowMessage16
-117 pascal16 WindowFromDC(word) WindowFromDC
+117 pascal16 WindowFromDC(word) WindowFromDC16
 119 pascal   GetMessagePos() GetMessagePos
 120 pascal   GetMessageTime() GetMessageTime
 121 pascal   SetWindowsHook(s_word segptr) SetWindowsHook
@@ -236,7 +236,7 @@
 233 pascal16 SetParent(word word) SetParent
 234 pascal16 UnhookWindowsHook(s_word segptr) UnhookWindowsHook
 235 pascal   DefHookProc(s_word word long ptr) DefHookProc
-236 pascal16 GetCapture() GetCapture
+236 pascal16 GetCapture() GetCapture16
 237 pascal16 GetUpdateRgn(word word word) GetUpdateRgn
 238 pascal16 ExcludeUpdateRgn(word word) ExcludeUpdateRgn
 239 pascal16 DialogBoxParam(word segptr word segptr long) DialogBoxParam16
@@ -270,7 +270,7 @@
 264 pascal16 GetMenuItemID(word word) GetMenuItemID
 265 pascal16 ShowOwnedPopups(word word) ShowOwnedPopups
 266 pascal16 SetMessageQueue(word) SetMessageQueue
-267 pascal16 ShowScrollBar(word word word) ShowScrollBar
+267 pascal16 ShowScrollBar(word word word) ShowScrollBar16
 268 pascal16 GlobalAddAtom(segptr) GlobalAddAtom16
 269 pascal16 GlobalDeleteAtom(word) GlobalDeleteAtom
 270 pascal16 GlobalFindAtom(segptr) GlobalFindAtom16
@@ -288,8 +288,8 @@
 282 pascal16 SelectPalette(word word word) SelectPalette
 283 pascal16 RealizePalette(word) RealizePalette
 284 pascal16 GetFreeSystemResources(word) GetFreeSystemResources
-#285 BEAR285
-286 pascal16 GetDesktopWindow() GetDesktopWindow
+285 pascal16 SetDeskWallPaper(ptr) SetDeskWallPaper16
+286 pascal16 GetDesktopWindow() GetDesktopWindow16
 287 pascal16 GetLastActivePopup(word) GetLastActivePopup
 288 pascal   GetMessageExtraInfo() GetMessageExtraInfo
 #289 KEYB_EVENT
@@ -326,7 +326,7 @@
 356 stub LoadDIBCursorHandler
 357 stub LoadDIBIconHandler
 358 pascal16 IsMenu(word) IsMenu
-359 pascal16 GetDCEx(word word long) GetDCEx
+359 pascal16 GetDCEx(word word long) GetDCEx16
 362 pascal16 DCHook(word word long long) DCHook
 364 stub LookupIconIDFromDirectoryEx
 368 pascal16 CopyIcon(word word) CopyIcon16
@@ -416,14 +416,14 @@
 471 pascal16 lstrcmpi(ptr ptr) lstrcmpi16
 472 pascal   AnsiNext(segptr) AnsiNext
 473 pascal   AnsiPrev(segptr segptr) AnsiPrev
-475 stub SetScrollInfo
-476 stub GetScrollInfo
+475 pascal16 SetScrollInfo(word s_word ptr word) SetScrollInfo16
+476 pascal16 GetScrollInfo(word s_word ptr) GetScrollInfo16
 477 stub GetKeyboardLayoutName
 478 stub LoadKeyboardLayout
 479 stub MenuItemFromPoint
 480 stub GetUserLocalObjType
 #481 HARDWARE_EVENT
-482 pascal16 EnableScrollBar(word word word) EnableScrollBar
+482 pascal16 EnableScrollBar(word word word) EnableScrollBar16
 483 pascal16 SystemParametersInfo(word word ptr word) SystemParametersInfo
 #484 __GP
 # Stubs for Hebrew version
diff --git a/if1632/user32.spec b/if1632/user32.spec
index 01268cb..133cf02 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -10,7 +10,7 @@
 0005 stdcall AppendMenuW(long long long ptr) AppendMenu32W
 0006 stub ArrangeIconicWindows
 0007 stub AttachThreadInput
-0008 stub BeginDeferWindowPos
+0008 stdcall BeginDeferWindowPos(long) BeginDeferWindowPos
 0009 stdcall BeginPaint(long ptr) BeginPaint32
 0010 stdcall BringWindowToTop(long) BringWindowToTop
 0011 stub BroadcastSystemMessage
@@ -62,7 +62,7 @@
 0057 stub CopyAcceleratorTableA
 0058 stub CopyAcceleratorTableW
 0059 stdcall CopyIcon(long) CopyIcon32
-0060 stub CopyImage
+0060 stdcall CopyImage(long long long long long) CopyImage32
 0061 stdcall CopyRect(ptr ptr) CopyRect32
 0062 stub CountClipboardFormats
 0063 stub CreateAcceleratorTableA
@@ -131,7 +131,7 @@
 0124 stdcall DefMDIChildProcW(long long long long) DefMDIChildProc32W
 0125 stdcall DefWindowProcA(long long long long) DefWindowProc32A
 0126 stdcall DefWindowProcW(long long long long) DefWindowProc32W
-0127 stub DeferWindowPos
+0127 stdcall DeferWindowPos(long long long long long long long long) DeferWindowPos
 0128 stdcall DeleteMenu(long) DeleteMenu
 0129 stub DestroyAcceleratorTable
 0130 stdcall DestroyCaret() DestroyCaret
@@ -174,9 +174,9 @@
 0167 stub EditWndProc
 0168 stdcall EmptyClipboard()				EmptyClipboard
 0169 stdcall EnableMenuItem(long long long) EnableMenuItem
-0170 stdcall EnableScrollBar(long long long)	EnableScrollBar
-0171 stdcall EnableWindow(long long)		EnableWindow
-0172 stub EndDeferWindowPos
+0170 stdcall EnableScrollBar(long long long) EnableScrollBar32
+0171 stdcall EnableWindow(long long) EnableWindow
+0172 stdcall EndDeferWindowPos(long) EndDeferWindowPos
 0173 stdcall EndDialog(long long) EndDialog
 0174 stub EndMenu
 0175 stdcall EndPaint(long ptr) EndPaint32
@@ -210,8 +210,8 @@
 0203 stub FreeDDElParam
 0204 stdcall GetActiveWindow() GetActiveWindow
 0205 stdcall GetAppCompatFlags(long) GetAppCompatFlags
-0206 stub GetAsyncKeyState
-0207 stub GetCapture
+0206 stdcall GetAsyncKeyState(long) GetAsyncKeyState
+0207 stdcall GetCapture() GetCapture32
 0208 stdcall GetCaretBlinkTime() GetCaretBlinkTime32
 0209 stdcall GetCaretPos(ptr) GetCaretPos32
 0210 stdcall GetClassInfoA(long ptr ptr) GetClassInfo32A
@@ -233,10 +233,10 @@
 0226 stub GetCursor
 0227 stub GetCursorInfo
 0228 stdcall GetCursorPos(ptr) GetCursorPos32
-0229 stdcall GetDC(long) GetDC
-0230 stub GetDCEx
-0231 stdcall GetDesktopWindow() GetDesktopWindow
-0232 stub GetDialogBaseUnits
+0229 stdcall GetDC(long) GetDC32
+0230 stdcall GetDCEx(long long long) GetDCEx32
+0231 stdcall GetDesktopWindow() GetDesktopWindow32
+0232 stdcall GetDialogBaseUnits() GetDialogBaseUnits
 0233 stdcall GetDlgCtrlID(long) GetDlgCtrlID
 0234 stdcall GetDlgItem(long long) GetDlgItem
 0235 stdcall GetDlgItemInt(long long long long) GetDlgItemInt
@@ -244,7 +244,7 @@
 0237 stdcall GetDlgItemTextW(long long ptr long) GetDlgItemText32W
 0238 stub GetDoubleClickTime
 0239 stdcall GetFocus() GetFocus32
-0240 stub GetForegroundWindow
+0240 return GetForegroundWindow 0 0		#FIXME
 0241 stub GetIconInfo
 0242 stub GetInputDesktop
 0243 stub GetInputState
@@ -266,12 +266,12 @@
 0259 stub GetMenuDefaultItem
 0260 stub GetMenuIndex
 0261 stdcall GetMenuItemCount(long) GetMenuItemCount
-0262 stub GetMenuItemID
+0262 stdcall GetMenuItemID(long long) GetMenuItemID
 0263 stub GetMenuItemInfoA
 0264 stub GetMenuItemInfoW
 0265 stub GetMenuItemRect
-0266 stub GetMenuState
-0267 stub GetMenuStringA
+0266 stdcall GetMenuState(long long long) GetMenuState
+0267 stdcall GetMenuStringA(long long ptr long long) GetMenuString
 0268 stub GetMenuStringW
 0269 stdcall GetMessageA(ptr long long long) USER32_GetMessageA
 0270 stub GetMessageExtraInfo
@@ -288,8 +288,8 @@
 0281 stdcall GetPropW(long ptr) GetProp32W
 0282 stub GetQueueStatus
 0283 stdcall GetScrollInfo(long long ptr) GetScrollInfo32
-0284 stdcall GetScrollPos(long long) GetScrollPos
-0285 stub GetScrollRange
+0284 stdcall GetScrollPos(long long) GetScrollPos32
+0285 stdcall GetScrollRange(long long ptr ptr) GetScrollRange32
 0286 return GetShellWindow 0 0
 0287 stdcall GetSubMenu(long long) GetSubMenu
 0288 stdcall GetSysColor(long) GetSysColor
@@ -307,7 +307,7 @@
 0300 stub GetUserObjectSecurity
 0301 stdcall GetWindow(long long) GetWindow
 0302 stub GetWindowContextHelpId
-0303 stdcall GetWindowDC(long) GetWindowDC
+0303 stdcall GetWindowDC(long) GetWindowDC32
 0304 stdcall GetWindowLongA(long long) GetWindowLong32A
 0305 stdcall GetWindowLongW(long long) GetWindowLong32W
 0306 stdcall GetWindowPlacement(long ptr) GetWindowPlacement32
@@ -443,7 +443,7 @@
 0436 stdcall RegisterWindowMessageA(ptr) RegisterWindowMessage32A
 0437 stdcall RegisterWindowMessageW(ptr) RegisterWindowMessage32W
 0438 stdcall ReleaseCapture() ReleaseCapture
-0439 stdcall ReleaseDC(long long) ReleaseDC
+0439 stdcall ReleaseDC(long long) ReleaseDC32
 0440 stub RemoveMenu
 0441 stdcall RemovePropA(long ptr) RemoveProp32A
 0442 stdcall RemovePropW(long ptr) RemoveProp32W
@@ -467,7 +467,7 @@
 0460 stub SendNotifyMessageW
 0461 stub ServerSetFunctionPointers
 0462 stub SetActiveWindow
-0463 stdcall SetCapture(long) SetCapture
+0463 stdcall SetCapture(long) SetCapture32
 0464 stdcall SetCaretBlinkTime(long) SetCaretBlinkTime
 0465 stdcall SetCaretPos(long long) SetCaretPos
 0466 stdcall SetClassLongA(long long long) SetClassLong32A
@@ -479,7 +479,7 @@
 0472 stub SetCursorContents
 0473 stub SetCursorPos
 0474 stub SetDebugErrorLevel
-0475 stub SetDeskWallpaper
+0475 stdcall SetDeskWallPaper(ptr) SetDeskWallPaper32
 0476 stdcall SetDlgItemInt(long long long long) SetDlgItemInt32
 0477 stdcall SetDlgItemTextA(long long ptr) SetDlgItemText32A
 0478 stdcall SetDlgItemTextW(long long ptr) SetDlgItemText32W
@@ -505,8 +505,8 @@
 0498 stdcall SetRect(ptr long long long long) SetRect32
 0499 stdcall SetRectEmpty(ptr) SetRectEmpty32
 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
+0501 stdcall SetScrollPos(long long long long) SetScrollPos32
+0502 stdcall SetScrollRange(long long long long long) SetScrollRange32
 0503 stub SetShellWindow
 0504 stub SetSysColors
 0505 stub SetSysColorsTemp
@@ -528,19 +528,19 @@
 0521 stdcall SetWindowTextA(long ptr) SetWindowText32A
 0522 stdcall SetWindowTextW(long ptr) SetWindowText32W
 0523 stdcall SetWindowWord(long long long) SetWindowWord
-0524 stub SetWindowsHookA
+0524 stdcall SetWindowsHookA(long ptr) SetWindowsHook32A
 0525 stdcall SetWindowsHookExA(long long long long) SetWindowsHookEx32A
 0526 stub SetWindowsHookExW
 0527 stub SetWindowsHookW
 0528 stdcall ShowCaret(long) ShowCaret
 0529 stdcall ShowCursor(long) ShowCursor
 0530 stub ShowOwnedPopups
-0531 stdcall ShowScrollBar(long long long) ShowScrollBar
+0531 stdcall ShowScrollBar(long long long) ShowScrollBar32
 0532 stub ShowStartGlass
 0533 stdcall ShowWindow(long long) ShowWindow
 0534 stub ShowWindowAsync
 0535 stdcall SubtractRect(ptr ptr ptr) SubtractRect32
-0536 stub SwapMouseButton
+0536 stdcall SwapMouseButton(long) SwapMouseButton
 0537 stub SwitchDesktop
 0538 stub SwitchToThisWindow
 0539 	stdcall SystemParametersInfoA(long long ptr long) SystemParametersInfo
@@ -584,7 +584,7 @@
 0577 stub WaitMessage
 0578 stdcall WinHelpA(long ptr long long)	WIN32_WinHelpA
 0579 stub WinHelpW
-0580 stdcall WindowFromDC(long) WindowFromDC
+0580 stdcall WindowFromDC(long) WindowFromDC32
 0581 stdcall WindowFromPoint(long long) WindowFromPoint32
 0582 stub keybd_event
 0583 stub mouse_event
diff --git a/include/class.h b/include/class.h
index 418f723..e02bec7 100644
--- a/include/class.h
+++ b/include/class.h
@@ -12,6 +12,8 @@
 
 #define CLASS_MAGIC   ('C' | ('L' << 8) | ('A' << 16) | ('S' << 24))
 
+struct tagDCE;
+
 typedef struct tagCLASS
 {
     struct tagCLASS *next;          /* Next class */
@@ -23,13 +25,13 @@
     INT32            cbWndExtra;    /* Window extra bytes */
     LPSTR            menuNameA;     /* Default menu name (ASCII string) */
     LPWSTR           menuNameW;     /* Default menu name (Unicode) */
+    struct tagDCE   *dce;           /* Class DCE (if CS_CLASSDC) */
     HINSTANCE32      hInstance;     /* Module that created the task */
     HICON16          hIcon;         /* Default icon */
     HICON16          hIconSm;       /* Default small icon */
     HCURSOR16        hCursor;       /* Default cursor */
     HBRUSH16         hbrBackground; /* Default background */
     ATOM             atomName;      /* Name of the class */
-    HANDLE16         hdce;          /* Class DCE (if CS_CLASSDC) */
     LONG             wExtra[1];     /* Class extra bytes */
 } CLASS;
 
diff --git a/include/clipboard.h b/include/clipboard.h
index 62bdcab..17cc340 100644
--- a/include/clipboard.h
+++ b/include/clipboard.h
@@ -2,8 +2,8 @@
 #define __WINE_CLIPBOARD_H
 
 void CLIPBOARD_ReadSelection(Window w,Atom prop);
-void CLIPBOARD_ReleaseSelection(HWND hwnd);
-void CLIPBOARD_DisOwn(HWND hWnd);
+void CLIPBOARD_ReleaseSelection(Window w,HWND hwnd);
+void CLIPBOARD_DisOwn(WND* pWnd);
 BOOL CLIPBOARD_IsPresent(WORD wFormat);
 
 #endif /* __WINE_CLIPBOARD_H */
diff --git a/include/dce.h b/include/dce.h
index 43a7ec5..06ff062 100644
--- a/include/dce.h
+++ b/include/dce.h
@@ -34,18 +34,18 @@
 
 typedef struct tagDCE
 {
-    HANDLE     hNext;
-    HDC	       hDC;
-    HWND       hwndCurrent;
-    HWND       hwndDC;
-    HRGN       hClipRgn;
-    DCE_TYPE   type;
-    DWORD      DCXflags;
+    struct tagDCE *next;
+    HDC32          hDC;
+    HWND32         hwndCurrent;
+    HWND32         hwndDC;
+    HRGN32         hClipRgn;
+    DCE_TYPE       type;
+    DWORD          DCXflags;
 } DCE;
 
 
-extern void 	DCE_Init(void);
-extern HANDLE 	DCE_AllocDCE( HWND hWnd, DCE_TYPE type );
-extern void 	DCE_FreeDCE( HANDLE hdce );
+extern void DCE_Init(void);
+extern DCE *DCE_AllocDCE( HWND32 hWnd, DCE_TYPE type );
+extern void DCE_FreeDCE( DCE *dce );
 
 #endif  /* DCE_H */
diff --git a/include/dde_mem.h b/include/dde_mem.h
index bdcdf3e..09b382a 100644
--- a/include/dde_mem.h
+++ b/include/dde_mem.h
@@ -25,14 +25,14 @@
 
 WORD DDE_SyncHandle(HGLOBAL16 handle, WORD sel);
 void *DDE_malloc(unsigned int flags,unsigned long size, SHMDATA *shmdata);
-HANDLE DDE_GlobalReAlloc(WORD,long,WORD);
+HANDLE16 DDE_GlobalReAlloc(WORD,long,WORD);
 HGLOBAL16 DDE_GlobalFree(HGLOBAL16 block);
 void *DDE_AttachHandle(HGLOBAL16 handle, SEGPTR *segptr);
 WORD DDE_GlobalHandleToSel( HGLOBAL16 handle );
 int DDE_GlobalUnlock(int);
-HANDLE DDE_GlobalSize(WORD);
-HANDLE DDE_GlobalHandle(WORD);
-HANDLE DDE_GlobalFlags(WORD);
+HANDLE16 DDE_GlobalSize(WORD);
+HANDLE16 DDE_GlobalHandle(WORD);
+HANDLE16 DDE_GlobalFlags(WORD);
 
 #endif  /* CONFIG_IPC */
 
diff --git a/include/debug.h b/include/debug.h
index 9ccba2b..7906c06 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -80,6 +80,7 @@
 #undef DEBUG_SCROLL
 #undef DEBUG_SELECTOR
 #undef DEBUG_SEM
+#undef DEBUG_SENDMSG
 #undef DEBUG_SHM
 #undef DEBUG_STRESS
 #undef DEBUG_SYSCOLOR
@@ -159,6 +160,7 @@
 #define DEBUG_SCROLL
 #define DEBUG_SELECTOR
 #define DEBUG_SEM
+#define DEBUG_SENDMSG
 #define DEBUG_SHM
 #define DEBUG_STRESS
 #define DEBUG_SYSCOLOR
@@ -496,6 +498,11 @@
 #else
     0,
 #endif
+#ifdef DEBUG_SENDMSG
+    1,
+#else
+    0,
+#endif
 #ifdef DEBUG_SHM
     1,
 #else
@@ -1396,8 +1403,21 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_shm if(!debug_msg_enabled[64]) ; else fprintf
-#define debugging_shm debug_msg_enabled[64]
+#define dprintf_sendmsg if(!debug_msg_enabled[64]) ; else fprintf
+#define debugging_sendmsg debug_msg_enabled[64]
+#else
+#ifdef DEBUG_SENDMSG
+#define dprintf_sendmsg fprintf
+#define debugging_sendmsg 1
+#else
+#define dprintf_sendmsg while(0) fprintf
+#define debugging_sendmsg 0
+#endif
+#endif
+
+#ifdef DEBUG_RUNTIME
+#define dprintf_shm if(!debug_msg_enabled[65]) ; else fprintf
+#define debugging_shm debug_msg_enabled[65]
 #else
 #ifdef DEBUG_SHM
 #define dprintf_shm fprintf
@@ -1409,8 +1429,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_stress if(!debug_msg_enabled[65]) ; else fprintf
-#define debugging_stress debug_msg_enabled[65]
+#define dprintf_stress if(!debug_msg_enabled[66]) ; else fprintf
+#define debugging_stress debug_msg_enabled[66]
 #else
 #ifdef DEBUG_STRESS
 #define dprintf_stress fprintf
@@ -1422,8 +1442,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_syscolor if(!debug_msg_enabled[66]) ; else fprintf
-#define debugging_syscolor debug_msg_enabled[66]
+#define dprintf_syscolor if(!debug_msg_enabled[67]) ; else fprintf
+#define debugging_syscolor debug_msg_enabled[67]
 #else
 #ifdef DEBUG_SYSCOLOR
 #define dprintf_syscolor fprintf
@@ -1435,8 +1455,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_task if(!debug_msg_enabled[67]) ; else fprintf
-#define debugging_task debug_msg_enabled[67]
+#define dprintf_task if(!debug_msg_enabled[68]) ; else fprintf
+#define debugging_task debug_msg_enabled[68]
 #else
 #ifdef DEBUG_TASK
 #define dprintf_task fprintf
@@ -1448,8 +1468,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_text if(!debug_msg_enabled[68]) ; else fprintf
-#define debugging_text debug_msg_enabled[68]
+#define dprintf_text if(!debug_msg_enabled[69]) ; else fprintf
+#define debugging_text debug_msg_enabled[69]
 #else
 #ifdef DEBUG_TEXT
 #define dprintf_text fprintf
@@ -1461,8 +1481,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_timer if(!debug_msg_enabled[69]) ; else fprintf
-#define debugging_timer debug_msg_enabled[69]
+#define dprintf_timer if(!debug_msg_enabled[70]) ; else fprintf
+#define debugging_timer debug_msg_enabled[70]
 #else
 #ifdef DEBUG_TIMER
 #define dprintf_timer fprintf
@@ -1474,8 +1494,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_toolhelp if(!debug_msg_enabled[70]) ; else fprintf
-#define debugging_toolhelp debug_msg_enabled[70]
+#define dprintf_toolhelp if(!debug_msg_enabled[71]) ; else fprintf
+#define debugging_toolhelp debug_msg_enabled[71]
 #else
 #ifdef DEBUG_TOOLHELP
 #define dprintf_toolhelp fprintf
@@ -1487,8 +1507,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_ver if(!debug_msg_enabled[71]) ; else fprintf
-#define debugging_ver debug_msg_enabled[71]
+#define dprintf_ver if(!debug_msg_enabled[72]) ; else fprintf
+#define debugging_ver debug_msg_enabled[72]
 #else
 #ifdef DEBUG_VER
 #define dprintf_ver fprintf
@@ -1500,8 +1520,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_vxd if(!debug_msg_enabled[72]) ; else fprintf
-#define debugging_vxd debug_msg_enabled[72]
+#define dprintf_vxd if(!debug_msg_enabled[73]) ; else fprintf
+#define debugging_vxd debug_msg_enabled[73]
 #else
 #ifdef DEBUG_VXD
 #define dprintf_vxd fprintf
@@ -1513,8 +1533,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win if(!debug_msg_enabled[73]) ; else fprintf
-#define debugging_win debug_msg_enabled[73]
+#define dprintf_win if(!debug_msg_enabled[74]) ; else fprintf
+#define debugging_win debug_msg_enabled[74]
 #else
 #ifdef DEBUG_WIN
 #define dprintf_win fprintf
@@ -1526,8 +1546,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win32 if(!debug_msg_enabled[74]) ; else fprintf
-#define debugging_win32 debug_msg_enabled[74]
+#define dprintf_win32 if(!debug_msg_enabled[75]) ; else fprintf
+#define debugging_win32 debug_msg_enabled[75]
 #else
 #ifdef DEBUG_WIN32
 #define dprintf_win32 fprintf
@@ -1539,8 +1559,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_winsock if(!debug_msg_enabled[75]) ; else fprintf
-#define debugging_winsock debug_msg_enabled[75]
+#define dprintf_winsock if(!debug_msg_enabled[76]) ; else fprintf
+#define debugging_winsock debug_msg_enabled[76]
 #else
 #ifdef DEBUG_WINSOCK
 #define dprintf_winsock fprintf
@@ -1619,6 +1639,7 @@
     "scroll",
     "selector",
     "sem",
+    "sendmsg",
     "shm",
     "stress",
     "syscolor",
diff --git a/include/desktop.h b/include/desktop.h
index 0de03fa..44ced36 100644
--- a/include/desktop.h
+++ b/include/desktop.h
@@ -11,13 +11,13 @@
 
 typedef struct
 {
-    HBRUSH   hbrushPattern;
-    HBITMAP  hbitmapWallPaper;
-    SIZE16   bitmapSize;
-    BOOL     fTileWallPaper;
+    HBRUSH32   hbrushPattern;
+    HBITMAP32  hbitmapWallPaper;
+    SIZE32     bitmapSize;
+    BOOL32     fTileWallPaper;
 } DESKTOPINFO;
 
-extern BOOL DESKTOP_SetPattern(char *pattern );
+extern BOOL32 DESKTOP_SetPattern( LPCSTR pattern );
 extern LRESULT DesktopWndProc( HWND32 hwnd, UINT32 message,
                                WPARAM32 wParam, LPARAM lParam );
 
diff --git a/include/directory.h b/include/directory.h
index 28e5d64..c9c34a8 100644
--- a/include/directory.h
+++ b/include/directory.h
@@ -8,10 +8,10 @@
 #define __WINE_DIRECTORY_H
 
 extern int DIR_Init(void);
-extern UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count );
-extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count );
-extern UINT DIR_GetTempUnixDir( LPSTR path, UINT count );
-extern UINT DIR_GetDosPath( int element, LPSTR path, UINT count );
-extern UINT DIR_GetUnixPath( int element, LPSTR path, UINT count );
+extern UINT32 DIR_GetWindowsUnixDir( LPSTR path, UINT32 count );
+extern UINT32 DIR_GetSystemUnixDir( LPSTR path, UINT32 count );
+extern UINT32 DIR_GetTempUnixDir( LPSTR path, UINT32 count );
+extern UINT32 DIR_GetDosPath( INT32 element, LPSTR path, UINT32 count );
+extern UINT32 DIR_GetUnixPath( INT32 element, LPSTR path, UINT32 count );
 
 #endif  /* __WINE_DIRECTORY_H */
diff --git a/include/file.h b/include/file.h
index cb665c8..048383a 100644
--- a/include/file.h
+++ b/include/file.h
@@ -22,7 +22,6 @@
 extern HFILE FILE_Dup( HFILE hFile );
 extern HFILE FILE_Dup2( HFILE hFile1, HFILE hFile2 );
 extern HFILE FILE_Open( LPCSTR path, INT32 mode );
-extern INT32 FILE_Read( HFILE hFile, LPVOID buffer, UINT32 count );
 extern BOOL32 FILE_SetFileType( HFILE hFile, DWORD type );
 extern HFILE _lcreat_uniq( LPCSTR path, INT32 attr );
 
diff --git a/include/gdi.h b/include/gdi.h
index cd68ba3..5e88208 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -75,7 +75,9 @@
     int           flags;
     const DeviceCaps *devCaps;
 
-    HANDLE16      hMetaFile;
+    HMETAFILE16   hMetaFile;
+    HGLOBAL16     hHT;          /* Handle table for metafile */
+    WORD          HTLen;        /* Handle table length (in entries) */
     HRGN16        hClipRgn;     /* Clip region (may be 0) */
     HRGN16        hVisRgn;      /* Visible region (must never be 0) */
     HRGN16        hGCClipRgn;   /* GC clip region (ClipRgn AND VisRgn) */
diff --git a/include/graphics.h b/include/graphics.h
index a9d4423..9ffdbb3 100644
--- a/include/graphics.h
+++ b/include/graphics.h
@@ -8,9 +8,13 @@
 #ifndef __WINE_GRAPHICS_H
 #define __WINE_GRAPHICS_H
 
-extern void GRAPH_DrawReliefRect( HDC hdc, RECT16 *rect, int highlight_size,
-                                  int shadow_size, BOOL pressed );
-extern BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
-                              int xsrc, int ysrc, int width, int height );
+#include "windows.h"
+
+extern void GRAPH_DrawReliefRect( HDC32 hdc, const RECT32 *rect,
+                                  INT32 highlight_size, INT32 shadow_size,
+                                  BOOL32 pressed );
+extern BOOL32 GRAPH_DrawBitmap( HDC32 hdc, HBITMAP32 hbitmap,
+                                int xdest, int ydest, int xsrc, int ysrc,
+                                int width, int height );
 
 #endif /* __WINE_GRAPHICS_H */
diff --git a/include/listbox.h b/include/listbox.h
index 8b9130f..2dd1101 100644
--- a/include/listbox.h
+++ b/include/listbox.h
@@ -54,6 +54,7 @@
 extern int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData);
 extern int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex);
 extern int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr);
+extern int ListBoxFindStringExact(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr);
 extern int ListBoxResetContent(LPHEADLIST lphl);
 extern int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex);
 extern int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state);
diff --git a/include/menu.h b/include/menu.h
index 4beed85..dfb7ec5 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -7,6 +7,7 @@
 
 extern BOOL MENU_Init(void);
 extern HMENU MENU_GetDefSysMenu(void);
+extern void MENU_InitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle);
 extern UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth,
 				   int orgX, int orgY );
 extern void MENU_TrackMouseMenuBar( HWND hwnd, POINT16 pt );
diff --git a/include/message.h b/include/message.h
index 6bb32bc..622059a 100644
--- a/include/message.h
+++ b/include/message.h
@@ -27,7 +27,7 @@
                                  HQUEUE16 hQueue, BOOL32 remove );
 
 /* event.c */
-extern BOOL32 EVENT_WaitXEvent( BOOL32 sleep );
+extern BOOL32 EVENT_WaitXEvent( BOOL32 sleep, BOOL32 peek );
 extern void EVENT_Synchronize(void);
 extern void EVENT_ProcessEvent( XEvent *event );
 extern void EVENT_RegisterWindow( WND *pWnd );
diff --git a/include/module.h b/include/module.h
index 322328a..dba95d9 100644
--- a/include/module.h
+++ b/include/module.h
@@ -117,7 +117,9 @@
 extern int MODULE_OpenFile( HMODULE16 hModule );
 extern LPSTR MODULE_GetModuleName( HMODULE16 hModule );
 extern void MODULE_RegisterModule( NE_MODULE *pModule );
+extern HMODULE16 MODULE_FindModule( LPCSTR path );
 extern HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule );
+extern HMODULE16 MODULE_CreateDummyModule( const OFSTRUCT *ofs );
 extern WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name );
 extern FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal );
 extern BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal,
diff --git a/include/queue.h b/include/queue.h
index 803019a..3010784 100644
--- a/include/queue.h
+++ b/include/queue.h
@@ -16,6 +16,12 @@
     MSG16   msg;
 } QMSG;
 
+typedef struct
+{
+  LRESULT   lResult;
+  BOOL16    bPending;
+} QSMCTRL;
+
 #pragma pack(1)
 
 typedef struct tagMESSAGEQUEUE
@@ -40,7 +46,7 @@
   WORD      wPostQMsg;              /* 2c PostQuitMessage flag */
   WORD      wExitCode;              /* 2e PostQuitMessage exit code */
   WORD      flags;                  /* 30 Queue flags */
-  WORD      reserved3[2];           /* 32 Unknown */
+  QSMCTRL*  smResultInit;           /* 32 1st LRESULT ptr - was: reserved */
   WORD      wWinVersion;            /* 36 Expected Windows version */
   HQUEUE16  InSendMessageHandle;    /* 38 Queue of task that sent a message */
   HTASK16   hSendingTask;           /* 3a Handle of task that sent a message */
@@ -50,21 +56,22 @@
   WORD      changeBits;             /* 42 Changed wake-up bits */
   WORD      wakeBits;               /* 44 Queue wake-up bits */
   WORD      wakeMask;               /* 46 Queue wake-up mask */
-  WORD      SendMsgReturnPtrs[3];   /* 48 Near ptr to return values (?) */
+  QSMCTRL*  smResultCurrent;        /* 48 ptrs to SendMessage() LRESULT - point to */
+  WORD      SendMsgReturnPtr[1];    /*    values on stack */
   HANDLE16  hCurHook;               /* 4e Current hook */
   HANDLE16  hooks[WH_NB_HOOKS];     /* 50 Task hooks list */
-  WORD      reserved4[3];           /* 68 Unknown */
-  QMSG      messages[1];            /* 6e Queue messages */
+  QSMCTRL*  smResult;               /* 6c 3rd LRESULT ptr - was: reserved */
+  QMSG      messages[1];            /* 70 Queue messages */
 } MESSAGEQUEUE;
 
 #pragma pack(4)
 
-/* Extra (undocumented) queue wake bits; not sure about the values */
-#define QS_SMRESULT      0x0100  /* Queue has a SendMessage() result */
-#define QS_SMPARAMSFREE  0x0200  /* SendMessage() parameters are available */
+/* Extra (undocumented) queue wake bits - see "Undoc. Windows" */
+#define QS_SMRESULT      0x8000  /* Queue has a SendMessage() result */
+#define QS_SMPARAMSFREE  0x4000  /* SendMessage() parameters are available */
 
 /* Queue flags */
-#define QUEUE_FLAG_REPLIED  0x0001  /* Replied to a SendMessage() */
+#define QUEUE_FLAG_XEVENT  0x0001
 
 extern void QUEUE_DumpQueue( HQUEUE16 hQueue );
 extern void QUEUE_WalkQueues(void);
diff --git a/include/scroll.h b/include/scroll.h
index 92d590f..90411dc 100644
--- a/include/scroll.h
+++ b/include/scroll.h
@@ -12,16 +12,18 @@
 
 typedef struct
 {
-    INT   CurVal;   /* Current scroll-bar value */
-    INT   MinVal;   /* Minimum scroll-bar value */
-    INT   MaxVal;   /* Maximum scroll-bar value */
-    INT   Page;     /* Page size of scroll bar (Win32) */
-    WORD  flags;    /* EnableScrollBar flags */
+    INT32   CurVal;   /* Current scroll-bar value */
+    INT32   MinVal;   /* Minimum scroll-bar value */
+    INT32   MaxVal;   /* Maximum scroll-bar value */
+    INT32   Page;     /* Page size of scroll bar (Win32) */
+    UINT32  flags;    /* EnableScrollBar flags */
 } SCROLLBAR_INFO;
 
-extern LONG ScrollBarWndProc( HWND hwnd, WORD uMsg, WORD wParam, LONG lParam );
-extern void SCROLL_DrawScrollBar( HWND hwnd, HDC hdc, int nBar );
-extern void SCROLL_HandleScrollEvent( HWND hwnd, int nBar,
-                                      WORD msg, POINT16 pt );
+extern LRESULT ScrollBarWndProc( HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam,
+                                 LPARAM lParam );
+extern void SCROLL_DrawScrollBar( HWND32 hwnd, HDC32 hdc, INT32 nBar,
+                                  BOOL32 arrows );
+extern void SCROLL_HandleScrollEvent( HWND32 hwnd, INT32 nBar,
+                                      UINT32 msg, POINT32 pt );
 
 #endif  /* SCROLL_H */
diff --git a/include/shell.h b/include/shell.h
index 565dbd0..41cfb71 100644
--- a/include/shell.h
+++ b/include/shell.h
@@ -9,6 +9,10 @@
 #include "windows.h"
 #include "winreg.h"
 
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
 extern INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
                       HICON16 hIcon);
 extern void SHELL_LoadRegistry();
@@ -32,6 +36,44 @@
 	/* memory block with filenames follows */     
 } DROPFILESTRUCT, *LPDROPFILESTRUCT; 
 
+typedef struct tagSHFILEINFO32A {
+	HICON32	hIcon;			/* icon */
+	int	iIcon;			/* icon index */
+	DWORD	dwAttributes;		/* SFGAO_ flags */
+	CHAR	szDisplayName[MAX_PATH];/* display name (or path) */
+	CHAR	szTypeName[80];		/* type name */
+} SHFILEINFO32A;
+
+typedef struct tagSHFILEINFO32W {
+	HICON32	hIcon;			/* icon */
+	int	iIcon;			/* icon index */
+	DWORD	dwAttributes;		/* SFGAO_ flags */
+	WCHAR	szDisplayName[MAX_PATH];/* display name (or path) */
+	WCHAR	szTypeName[80];		/* type name */
+} SHFILEINFO32W;
+
+DECL_WINELIB_TYPE_AW(SHFILEINFO);
+
+#define SHGFI_ICON              0x000000100     /* get icon */
+#define SHGFI_DISPLAYNAME       0x000000200     /* get display name */
+#define SHGFI_TYPENAME          0x000000400     /* get type name */
+#define SHGFI_ATTRIBUTES        0x000000800     /* get attributes */
+#define SHGFI_ICONLOCATION      0x000001000     /* get icon location */
+#define SHGFI_EXETYPE           0x000002000     /* return exe type */
+#define SHGFI_SYSICONINDEX      0x000004000     /* get system icon index */
+#define SHGFI_LINKOVERLAY       0x000008000     /* put a link overlay on icon */
+#define SHGFI_SELECTED          0x000010000     /* show icon in selected state */
+#define SHGFI_LARGEICON         0x000000000     /* get large icon */
+#define SHGFI_SMALLICON         0x000000001     /* get small icon */
+#define SHGFI_OPENICON          0x000000002     /* get open icon */
+#define SHGFI_SHELLICONSIZE     0x000000004     /* get shell size icon */
+#define SHGFI_PIDL              0x000000008     /* pszPath is a pidl */
+#define SHGFI_USEFILEATTRIBUTES 0x000000010     /* use passed dwFileAttribute */
+
+DWORD SHGetFileInfo32A(LPCSTR,DWORD,SHFILEINFO32A*,UINT32,UINT32);
+DWORD SHGetFileInfo32W(LPCWSTR,DWORD,SHFILEINFO32W*,UINT32,UINT32);
+#define SHGetFileInfo WINELIB_NAME_AW(SHGetFileInfo)
+
 #define SE_ERR_SHARE            26
 #define SE_ERR_ASSOCINCOMPLETE  27
 #define SE_ERR_DDETIMEOUT       28
diff --git a/include/stddebug.h b/include/stddebug.h
index 331575a..d54da52 100644
--- a/include/stddebug.h
+++ b/include/stddebug.h
@@ -140,6 +140,7 @@
 #undef DEBUG_SCROLL
 #undef DEBUG_SELECTOR
 #undef DEBUG_SEM
+#undef DEBUG_SENDMSG
 #undef DEBUG_SHM
 #undef DEBUG_STRESS
 #undef DEBUG_SYSCOLOR
@@ -219,6 +220,7 @@
 #define DEBUG_SCROLL
 #define DEBUG_SELECTOR
 #define DEBUG_SEM
+#define DEBUG_SENDMSG
 #define DEBUG_SHM
 #define DEBUG_STRESS
 #define DEBUG_SYSCOLOR
diff --git a/include/win.h b/include/win.h
index 92653ed6..18c3321 100644
--- a/include/win.h
+++ b/include/win.h
@@ -32,6 +32,8 @@
 #define RDW_C_USEHRGN		0x0001
 #define RDW_C_DELETEHRGN	0x0002
 
+struct tagDCE;
+
 typedef struct tagWND
 {
     struct tagWND *next;          /* Next sibling */
@@ -52,12 +54,12 @@
     void          *pVScroll;      /* Vertical scroll-bar info */
     void          *pHScroll;      /* Horizontal scroll-bar info */
     void          *pProp;         /* Pointer to properties list */
+    struct tagDCE *dce;           /* Window DCE (if CS_OWNDC or CS_CLASSDC) */
     HGLOBAL16      hmemTaskQ;     /* Task queue global memory handle */
     HRGN16         hrgnUpdate;    /* Update region */
     HWND16         hwndLastActive;/* Last active popup hwnd */
     DWORD          dwStyle;       /* Window style (from CreateWindow) */
     DWORD          dwExStyle;     /* Extended style (from CreateWindowEx) */
-    HANDLE16       hdce;          /* Window DCE (if CS_OWNDC or CS_CLASSDC) */
     UINT16         wIDmenu;       /* ID or hmenu (from CreateWindow) */
     WORD           flags;         /* Misc. flags (see below) */
     Window         window;        /* X window (only for top-level windows) */
@@ -77,6 +79,7 @@
 #define WIN_NCACTIVATED        0x0080 /* last WM_NCACTIVATE was positive */
 #define WIN_MANAGED            0x0100 /* Window managed by the X wm */
 #define WIN_ISDIALOG           0x0200 /* Window is a dialog */
+#define WIN_SAVEUNDER_OVERRIDE 0x0400
 
   /* Window functions */
 extern WND *WIN_FindWndPtr( HWND32 hwnd );
@@ -89,6 +92,7 @@
 extern HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue );
 extern void WIN_SendParentNotify( HWND32 hwnd, WORD event,
                                   WORD idChild, LPARAM lValue );
+extern void WIN_DestroyQueueWindows( WND* wnd, HQUEUE16 hQueue );
 extern BOOL32 WIN_CreateDesktopWindow(void);
 extern HWND32 WIN_GetTopParent( HWND32 hwnd );
 extern BOOL32 WIN_IsWindowDrawable(WND*, BOOL32 );
diff --git a/include/wincon.h b/include/wincon.h
index bb5ffd0..1c612d0 100644
--- a/include/wincon.h
+++ b/include/wincon.h
@@ -1,7 +1,57 @@
+#ifndef _WINECON_H_
+#define _WINECON_H_
+
+#define CTRL_C_EVENT 0
+#define CTRL_BREAK_EVENT 1
+#define CTRL_CLOSE_EVENT 2
+#define CTRL_LOGOFF_EVENT 5
+#define CTRL_SHUTDOWN_EVENT 6
+
+typedef BOOL32 HANDLER_ROUTINE(WORD);
+
+/*
+ * Attributes flags:
+ */
+
+#define FOREGROUND_BLUE      0x0001 /* text color contains blue. */
+#define FOREGROUND_GREEN     0x0002 /* text color contains green. */
+#define FOREGROUND_RED       0x0004 /* text color contains red. */
+#define FOREGROUND_INTENSITY 0x0008 /* text color is intensified. */
+#define BACKGROUND_BLUE      0x0010 /* background color contains blue. */
+#define BACKGROUND_GREEN     0x0020 /* background color contains green. */
+#define BACKGROUND_RED       0x0040 /* background color contains red. */
+#define BACKGROUND_INTENSITY 0x0080 /* background color is intensified. */
+
+typedef struct tagCOORD
+{
+    INT16 x;
+    INT16 y;
+} COORD,*LPCOORD;
+
+typedef struct tagSMALL_RECT
+{
+    INT16 Left;
+    INT16 Right;
+    INT16 Top;
+    INT16 Bottom;
+} SMALL_RECT,*LPSMALL_RECT;
+
+typedef struct tagCONSOLE_SCREEN_BUFFER_INFO
+{
+    COORD       dwSize;
+    COORD       dwCursorPosition;
+    WORD        wAttributes;
+    SMALL_RECT  srWindow;
+    COORD       dwMaximumWindowSize;
+} CONSOLE_SCREEN_BUFFER_INFO,*LPCONSOLE_SCREEN_BUFFER_INFO;
+
+
+#endif
+
+#if 0
 #ifndef _WINCON_H_
 #define _WINCON_H_
 
-
 #ifdef UNICODE
 #define FillConsoleOutputCharacter FillConsoleOutputCharacterW
 #define GetConsoleTitle GetConsoleTitleW
@@ -143,29 +193,6 @@
   }
 CHAR_INFO;
 
-
-
-
-#define FOREGROUND_BLUE 0x01
-#define FOREGROUND_GREEN 0x02
-#define FOREGROUND_RED 0x04
-#define FOREGROUND_INTENSITY 0x08
-#define BACKGROUND_BLUE 0x10
-#define BACKGROUND_GREEN 0x20
-#define BACKGROUND_RED 0x40
-#define BACKGROUND_INTENSITY 0x80
-
-
-typedef struct
-  {
-    COORD dwSize;
-    COORD dwCursorPosition;
-    WORD wAttrs;
-    SMALL_RECT srWindow;
-    COORD dwMaximumWindowSize;
-  }
-CONSOLE_SCREEN_BUFFER_INFO;
-
 typedef struct
   {
     DWORD size;
@@ -176,14 +203,6 @@
 #endif
 
 
-#define CTRL_C_EVENT 0
-#define CTRL_BREAK_EVENT 1
-#define CTRL_CLOSE_EVENT 2
-#define CTRL_LOGOFF_EVENT 5
-#define CTRL_SHUTDOWN_EVENT 6
-
-typedef BOOL HANDLER_ROUTINE (WORD ctrltype);
-
 #if 0
 
 #define ENABLE_PROCESSED_INPUT 0x01
@@ -255,3 +274,4 @@
 #endif
 #endif
 
+#endif /* 0 */
diff --git a/include/windows.h b/include/windows.h
index f834039..28b9c8a 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -435,6 +435,7 @@
 /***** Window hooks *****/
 
   /* Hook values */
+#define WH_MIN		    (-1)
 #define WH_MSGFILTER	    (-1)
 #define WH_JOURNALRECORD    0
 #define WH_JOURNALPLAYBACK  1
@@ -447,10 +448,13 @@
 #define WH_HARDWARE	    8
 #define WH_DEBUG	    9
 #define WH_SHELL            10
+#define WH_FOREGROUNDIDLE   11
+#define WH_CALLWNDPROCRET   12
+#define WH_MAX              12
 
-#define WH_FIRST_HOOK       WH_MSGFILTER
-#define WH_LAST_HOOK        WH_SHELL
-#define WH_NB_HOOKS         (WH_LAST_HOOK-WH_FIRST_HOOK+1)
+#define WH_MINHOOK          WH_MIN
+#define WH_MAXHOOK          WH_MAX
+#define WH_NB_HOOKS         (WH_MAXHOOK-WH_MINHOOK+1)
 
   /* Hook action codes */
 #define HC_ACTION           0
@@ -2546,27 +2550,35 @@
 #define ESB_DISABLE_LTUP    ESB_DISABLE_LEFT
 #define ESB_DISABLE_RTDN    ESB_DISABLE_RIGHT
 
-/* Scrollbar messages (undocumented) */
-#define SBM_SETSCROLLPOS      (WM_USER+0)
-#define SBM_GETSCROLLPOS      (WM_USER+1)
-#define SBM_SETSCROLLRANGE    (WM_USER+2)
-#define SBM_REDRAW            (WM_USER+3)
-#define SBM_ENABLE            (WM_USER+4)
+/* Scrollbar messages */
+#define SBM_SETPOS16             (WM_USER+0)
+#define SBM_SETPOS32             0x00e0
+#define SBM_SETPOS               WINELIB_NAME(SBM_SETPOS)
+#define SBM_GETPOS16             (WM_USER+1)
+#define SBM_GETPOS32             0x00e1
+#define SBM_GETPOS               WINELIB_NAME(SBM_GETPOS)
+#define SBM_SETRANGE16           (WM_USER+2)
+#define SBM_SETRANGE32           0x00e2
+#define SBM_SETRANGE             WINELIB_NAME(SBM_SETRANGE)
+#define SBM_GETRANGE16           (WM_USER+3)
+#define SBM_GETRANGE32           0x00e3
+#define SBM_GETRANGE             WINELIB_NAME(SBM_GETRANGE)
+#define SBM_ENABLE_ARROWS16      (WM_USER+4)
+#define SBM_ENABLE_ARROWS32      0x00e4
+#define SBM_ENABLE_ARROWS        WINELIB_NAME(SBM_ENABLE_ARROWS)
+#define SBM_SETRANGEREDRAW16     WM_NULL  /* Not in Win16 */
+#define SBM_SETRANGEREDRAW32     0x00e6
+#define SBM_SETRANGEREDRAW       WINELIB_NAME(SBM_SETRANGEREDRAW)
+#define SBM_SETSCROLLINFO16      WM_NULL  /* Not in Win16 */
+#define SBM_SETSCROLLINFO32      0x00e9
+#define SBM_SETSCROLLINFO        WINELIB_NAME(SBM_SETSCROLLINFO)
+#define SBM_GETSCROLLINFO16      WM_NULL  /* Not in Win16 */
+#define SBM_GETSCROLLINFO32      0x00ea
+#define SBM_GETSCROLLINFO        WINELIB_NAME(SBM_GETSCROLLINFO)
 
 /* 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;
@@ -2574,11 +2586,8 @@
     UINT32    nPage;
     INT32     nPos;
     INT32     nTrackPos;
-} SCROLLINFO32, *LPSCROLLINFO32;
+} SCROLLINFO, *LPSCROLLINFO;
  
-DECL_WINELIB_TYPE(SCROLLINFO);
-DECL_WINELIB_TYPE(LPSCROLLINFO);
-
 /* GetScrollInfo() flags */ 
 #define SIF_RANGE           0x0001
 #define SIF_PAGE            0x0002
@@ -3587,6 +3596,22 @@
 #define	DLL_THREAD_ATTACH	2	/* attach new thread */
 #define	DLL_THREAD_DETACH	3	/* detach thread */
 
+typedef struct _MEMORY_BASIC_INFORMATION
+{
+    LPVOID   BaseAddress;
+    LPVOID   AllocationBase;
+    DWORD    AllocationProtect;
+    DWORD    RegionSize;
+    DWORD    State;
+    DWORD    Protect;
+    DWORD    Type;
+} MEMORY_BASIC_INFORMATION,*LPMEMORY_BASIC_INFORMATION;
+
+typedef DWORD (*LPTHREAD_START_ROUTINE)(LPVOID);
+
+typedef BOOL32 (*CODEPAGE_ENUMPROC32A)(LPSTR);
+typedef BOOL32 (*CODEPAGE_ENUMPROC32W)(LPWSTR);
+DECL_WINELIB_TYPE_AW(CODEPAGE_ENUMPROC);
 
 #pragma pack(4)
 
@@ -3598,6 +3623,7 @@
 WORD       AllocSelectorArray(WORD);
 INT16      Catch(LPCATCHBUF);
 INT16      CloseComm(INT16);
+BOOL16     EnableHardwareInput(BOOL16);
 HANDLE16   FarGetOwner(HGLOBAL16);
 VOID       FarSetOwner(HGLOBAL16,HANDLE16);
 VOID       FillWindow(HWND16,HWND16,HDC16,HBRUSH16);
@@ -3609,6 +3635,7 @@
 UINT16     GetCommEventMask(INT16,UINT16);
 HANDLE16   GetCurrentPDB(void);
 HTASK16    GetCurrentTask(void);
+HWND16     GetDesktopHwnd(void);
 HMODULE16  GetExePtr(HANDLE16);
 WORD       GetExeVersion(void);
 BOOL16     GetModuleName(HINSTANCE16,LPSTR,INT16);
@@ -3631,6 +3658,7 @@
 DWORD      SetBitmapDimension(HBITMAP16,INT16,INT16);
 DWORD      SetBrushOrg(HDC16,INT16,INT16);
 UINT16*    SetCommEventMask(INT16,UINT16);
+BOOL16     SetDeskPattern(void);
 WORD       SetSelectorBase(WORD,DWORD);
 WORD       SetSelectorLimit(WORD,DWORD);
 FARPROC16  SetTaskSignalProc(HTASK16,FARPROC16);
@@ -3763,6 +3791,7 @@
 UINT16     RealizePalette(HDC32);
 DWORD      RegCloseKey(HKEY);
 DWORD      RegFlushKey(HKEY);
+VOID       ReleaseCapture(void);
 LONG       SetBitmapBits(HBITMAP32,LONG,LPCVOID);
 COLORREF   SetBkColor(HDC32,COLORREF);
 BOOL16     SetCaretBlinkTime(UINT32);
@@ -3776,7 +3805,6 @@
 COLORREF   SetTextColor(HDC32,COLORREF);
 WORD       SetWindowWord(HWND32,INT32,WORD);
 BOOL16     ShowCaret(HWND32);
-HWND16     WindowFromDC(HDC32);
 LONG       _hread(HFILE,LPVOID,LONG);
 HFILE      _lclose(HFILE);
 HFILE      _lcreat(LPCSTR,INT32);
@@ -3996,6 +4024,9 @@
 INT32      DrawText32A(HDC32,LPCSTR,INT32,LPRECT32,UINT32);
 INT32      DrawText32W(HDC32,LPCWSTR,INT32,LPRECT32,UINT32);
 #define    DrawText WINELIB_NAME_AW(DrawText)
+BOOL16     EnableScrollBar16(HWND16,INT16,UINT16);
+BOOL32     EnableScrollBar32(HWND32,INT32,UINT32);
+#define    EnableScrollBar WINELIB_NAME(EnableScrollBar)
 BOOL16     EndPaint16(HWND16,const PAINTSTRUCT16*);
 BOOL32     EndPaint32(HWND32,const PAINTSTRUCT32*);
 #define    EndPaint WINELIB_NAME(EndPaint)
@@ -4067,6 +4098,9 @@
 BOOL16     GetBrushOrgEx16(HDC16,LPPOINT16);
 BOOL32     GetBrushOrgEx32(HDC32,LPPOINT32);
 #define    GetBrushOrgEx WINELIB_NAME(GetBrushOrgEx)
+HWND16     GetCapture16(void);
+HWND32     GetCapture32(void);
+#define    GetCapture WINELIB_NAME(GetCapture)
 UINT16     GetCaretBlinkTime16(void);
 UINT32     GetCaretBlinkTime32(void);
 #define    GetCaretBlinkTime WINELIB_NAME(GetCaretBlinkTime)
@@ -4111,6 +4145,15 @@
 void       GetCursorPos16(LPPOINT16);
 void       GetCursorPos32(LPPOINT32);
 #define    GetCursorPos WINELIB_NAME(GetCursorPos)
+HDC16      GetDC16(HWND16);
+HDC32      GetDC32(HWND32);
+#define    GetDC WINELIB_NAME(GetDC)
+HDC16      GetDCEx16(HWND16,HRGN16,DWORD);
+HDC32      GetDCEx32(HWND32,HRGN32,DWORD);
+#define    GetDCEx WINELIB_NAME(GetDCEx)
+HWND16     GetDesktopWindow16(void);
+HWND32     GetDesktopWindow32(void);
+#define    GetDesktopWindow WINELIB_NAME(GetDesktopWindow)
 BOOL16     GetDiskFreeSpace16(LPCSTR,LPDWORD,LPDWORD,LPDWORD,LPDWORD);
 BOOL32     GetDiskFreeSpace32A(LPCSTR,LPDWORD,LPDWORD,LPDWORD,LPDWORD);
 BOOL32     GetDiskFreeSpace32W(LPCWSTR,LPDWORD,LPDWORD,LPDWORD,LPDWORD);
@@ -4165,9 +4208,15 @@
 INT16      GetRgnBox16(HRGN16,LPRECT16);
 INT32      GetRgnBox32(HRGN32,LPRECT32);
 #define    GetRgnBox WINELIB_NAME(GetRgnBox)
-BOOL16     GetScrollInfo16(HWND16,INT16,LPSCROLLINFO16);
-BOOL32     GetScrollInfo32(HWND32,INT32,LPSCROLLINFO32);
+BOOL16     GetScrollInfo16(HWND16,INT16,LPSCROLLINFO);
+BOOL32     GetScrollInfo32(HWND32,INT32,LPSCROLLINFO);
 #define    GetScrollInfo WINELIB_NAME(GetScrollInfo)
+INT16      GetScrollPos16(HWND16,INT16);
+INT32      GetScrollPos32(HWND32,INT32);
+#define    GetScrollPos WINELIB_NAME(GetScrollPos)
+BOOL16     GetScrollRange16(HWND16,INT16,LPINT16,LPINT16);
+BOOL32     GetScrollRange32(HWND32,INT32,LPINT32,LPINT32);
+#define    GetScrollRange WINELIB_NAME(GetScrollRange)
 DWORD      GetShortPathName32A(LPCSTR,LPSTR,DWORD);
 DWORD      GetShortPathName32W(LPCWSTR,LPWSTR,DWORD);
 #define    GetShortPathName WINELIB_NAME_AW(GetShortPathName)
@@ -4208,6 +4257,9 @@
 BOOL32     GetVolumeInformation32A(LPCSTR,LPSTR,DWORD,LPDWORD,LPDWORD,LPDWORD,LPSTR,DWORD);
 BOOL32     GetVolumeInformation32W(LPCWSTR,LPWSTR,DWORD,LPDWORD,LPDWORD,LPDWORD,LPWSTR,DWORD);
 #define    GetVolumeInformation WINELIB_NAME_AW(GetVolumeInformation)
+HDC16      GetWindowDC16(HWND16);
+HDC32      GetWindowDC32(HWND32);
+#define    GetWindowDC WINELIB_NAME(GetWindowDC)
 BOOL16     GetWindowExtEx16(HDC16,LPPOINT16);
 BOOL32     GetWindowExtEx32(HDC32,LPPOINT32);
 #define    GetWindowExtEx WINELIB_NAME(GetWindowExtEx)
@@ -4224,6 +4276,10 @@
 void       GetWindowRect16(HWND16,LPRECT16);
 void       GetWindowRect32(HWND32,LPRECT32);
 #define    GetWindowRect WINELIB_NAME(GetWindowRect)
+UINT16     GetWindowsDirectory16(LPSTR,UINT16);
+UINT32     GetWindowsDirectory32A(LPSTR,UINT32);
+UINT32     GetWindowsDirectory32W(LPWSTR,UINT32);
+#define    GetWindowsDirectory WINELIB_NAME_AW(GetWindowsDirectory)
 HTASK16    GetWindowTask16(HWND16);
 #define    GetWindowTask32(hwnd) ((HTASK32)GetWindowThreadProcessId(hwnd,NULL))
 #define    GetWindowTask WINELIB_NAME(GetWindowTask)
@@ -4521,6 +4577,9 @@
 DWORD      RegSetValueEx32A(HKEY,LPSTR,DWORD,DWORD,LPBYTE,DWORD);
 DWORD      RegSetValueEx32W(HKEY,LPWSTR,DWORD,DWORD,LPBYTE,DWORD);
 #define    RegSetValueEx WINELIB_NAME_AW(RegSetValueEx)
+INT16      ReleaseDC16(HWND16,HDC16);
+INT32      ReleaseDC32(HWND32,HDC32);
+#define    ReleaseDC WINELIB_NAME(ReleaseDC)
 HANDLE16   RemoveProp16(HWND16,LPCSTR);
 HANDLE32   RemoveProp32A(HWND32,LPCSTR);
 HANDLE32   RemoveProp32W(HWND32,LPCWSTR);
@@ -4549,6 +4608,9 @@
 BOOL16     SetBitmapDimensionEx16(HBITMAP16,INT16,INT16,LPSIZE16);
 BOOL32     SetBitmapDimensionEx32(HBITMAP32,INT32,INT32,LPSIZE32);
 #define    SetBitmapDimensionEx WINELIB_NAME(SetBitmapDimensionEx)
+HWND16     SetCapture16(HWND16);
+HWND32     SetCapture32(HWND32);
+#define    SetCapture WINELIB_NAME(SetCapture)
 LONG       SetClassLong16(HWND16,INT16,LONG);
 LONG       SetClassLong32A(HWND32,INT32,LONG);
 LONG       SetClassLong32W(HWND32,INT32,LONG);
@@ -4559,6 +4621,9 @@
 INT16      SetCommState16(LPDCB16);
 BOOL32     SetCommState32(INT32,LPDCB32);
 #define    SetCommState WINELIB_NAME(SetCommState)
+BOOL16     SetDeskWallPaper16(LPCSTR);
+BOOL32     SetDeskWallPaper32(LPCSTR);
+#define    SetDeskWallPaper WINELIB_NAME(SetDeskWallPaper)
 void       SetDlgItemInt16(HWND16,INT16,UINT16,BOOL16);
 void       SetDlgItemInt32(HWND32,INT32,UINT32,BOOL32);
 #define    SetDlgItemInt WINELIB_NAME(SetDlgItemInt)
@@ -4592,9 +4657,15 @@
 void       SetRectEmpty16(LPRECT16);
 void       SetRectEmpty32(LPRECT32);
 #define    SetRectEmpty WINELIB_NAME(SetRectEmpty)
-INT16      SetScrollInfo16(HWND16,INT16,LPSCROLLINFO16,BOOL16);
-INT32      SetScrollInfo32(HWND32,INT32,LPSCROLLINFO32,BOOL32);
+INT16      SetScrollInfo16(HWND16,INT16,const SCROLLINFO*,BOOL16);
+INT32      SetScrollInfo32(HWND32,INT32,const SCROLLINFO*,BOOL32);
 #define    SetScrollInfo WINELIB_NAME(SetScrollInfo)
+INT16      SetScrollPos16(HWND16,INT16,INT16,BOOL16);
+INT32      SetScrollPos32(HWND32,INT32,INT32,BOOL32);
+#define    SetScrollPos WINELIB_NAME(SetScrollPos)
+void       SetScrollRange16(HWND16,INT16,INT16,INT16,BOOL16);
+BOOL32     SetScrollRange32(HWND32,INT32,INT32,INT32,BOOL32);
+#define    SetScrollRange WINELIB_NAME(SetScrollRange)
 HWND16     SetSysModalWindow16(HWND16);
 #define    SetSysModalWindow32(hwnd) ((HWND32)0)
 #define    SetSysModalWindow WINELIB_NAME(SetSysModalWindow)
@@ -4627,6 +4698,9 @@
 void       SetWindowText32A(HWND32,LPCSTR);
 void       SetWindowText32W(HWND32,LPCWSTR);
 #define    SetWindowText WINELIB_NAME_AW(SetWindowText)
+void       ShowScrollBar16(HWND16,INT16,BOOL16);
+BOOL32     ShowScrollBar32(HWND32,INT32,BOOL32);
+#define    ShowScrollBar WINELIB_NAME(ShowScrollBar)
 BOOL16     SubtractRect16(LPRECT16,const RECT16*,const RECT16*);
 BOOL32     SubtractRect32(LPRECT32,const RECT32*,const RECT32*);
 #define    SubtractRect WINELIB_NAME(SubtractRect)
@@ -4669,6 +4743,9 @@
 DWORD      VerQueryValue32A(LPVOID,LPCSTR,LPVOID*,UINT32*);
 DWORD      VerQueryValue32W(LPVOID,LPCWSTR,LPVOID*,UINT32*);
 #define    VerQueryValue WINELIB_NAME_AW(VerQueryValue)
+HWND16     WindowFromDC16(HDC16);
+HWND32     WindowFromDC32(HDC32);
+#define    WindowFromDC WINELIB_NAME(WindowFromDC)
 HWND16     WindowFromPoint16(POINT16);
 HWND32     WindowFromPoint32(POINT32);
 #define    WindowFromPoint WINELIB_NAME(WindowFromPoint)
@@ -4859,12 +4936,10 @@
 DWORD      DumpIcon(SEGPTR,WORD*,SEGPTR*,SEGPTR*);
 BOOL       Ellipse(HDC,INT,INT,INT,INT);
 BOOL       EmptyClipboard(void);
-BOOL       EnableHardwareInput(BOOL);
 BOOL       EnableMenuItem(HMENU,UINT,UINT);
-BOOL       EnableScrollBar(HWND,UINT,UINT);
 BOOL       EnableWindow(HWND,BOOL);
 BOOL       EndDeferWindowPos(HDWP16);
-UINT       EnumClipboardFormats(UINT);
+UINT16     EnumClipboardFormats(UINT16);
 INT        EnumFontFamilies(HDC,LPCSTR,FONTENUMPROC16,LPARAM);
 INT        EnumFonts(HDC,LPCSTR,FONTENUMPROC16,LPARAM);
 BOOL       EnumMetaFile(HDC,HMETAFILE16,MFENUMPROC16,LPARAM);
@@ -4891,7 +4966,6 @@
 COLORREF   GetBkColor(HDC);
 WORD       GetBkMode(HDC);
 DWORD      GetBrushOrg(HDC);
-HWND       GetCapture(void);
 BOOL       GetCharABCWidths(HDC,UINT,UINT,LPABC16);
 BOOL       GetCharWidth(HDC,WORD,WORD,LPINT16);
 HRGN       GetClipRgn(HDC);
@@ -4905,15 +4979,11 @@
 DWORD      GetCurrentPosition(HDC);
 DWORD      GetCurrentTime(void);
 HCURSOR16  GetCursor(void);
-HDC        GetDC(HWND);
-HDC        GetDCEx(HWND,HRGN,DWORD);
 DWORD      GetDCHook(HDC,FARPROC16*);
 DWORD      GetDCOrg(HDC);
 HDC        GetDCState(HDC);
 int        GetDIBits(HDC,HANDLE,WORD,WORD,LPSTR,LPBITMAPINFO,WORD);
 SEGPTR     GetDOSEnvironment(void);
-HWND       GetDesktopHwnd(void);
-HWND       GetDesktopWindow(void);
 int        GetDeviceCaps(HDC,WORD);
 DWORD      GetDialogBaseUnits(void);
 HWND       GetDlgItem(HWND,WORD);
@@ -4968,8 +5038,6 @@
 BOOL       GetRasterizerCaps(LPRASTERIZER_STATUS,UINT);
 WORD       GetROP2(HDC);
 WORD       GetRelAbs(HDC);
-int        GetScrollPos(HWND,int);
-void       GetScrollRange(HWND,int,LPINT16,LPINT16);
 HANDLE     GetStockObject(int);
 WORD       GetStretchBltMode(HDC);
 HMENU      GetSubMenu(HMENU,short);
@@ -4994,11 +5062,9 @@
 BOOL       GetWinDebugInfo(LPWINDEBUGINFO,UINT);
 LONG       GetWinFlags(void);
 HWND       GetWindow(HWND,WORD);
-HDC        GetWindowDC(HWND);
 DWORD      GetWindowExt(HDC);
 DWORD      GetWindowOrg(HDC);
 int        GetWindowTextLength(HWND);
-UINT       GetWindowsDirectory(LPSTR,UINT);
 ATOM       GlobalDeleteAtom(ATOM);
 void       GlobalFix(HGLOBAL16);
 void       GlobalFreeAll(HGLOBAL16);
@@ -5047,6 +5113,7 @@
 BOOL       OemToAnsi(LPCSTR,LPSTR);
 void       OemToAnsiBuff(LPCSTR,LPSTR,INT);
 int        OffsetClipRgn(HDC,short,short);
+void       OldYield(void);
 BOOL       OpenClipboard(HWND);
 BOOL       OpenIcon(HWND);
 int        OpenSound(void);
@@ -5073,8 +5140,6 @@
 WORD       RealizeDefaultPalette(HDC);
 BOOL       Rectangle(HDC,INT,INT,INT,INT);
 WORD       RegisterClipboardFormat(LPCSTR);
-void       ReleaseCapture(void);
-int        ReleaseDC(HWND,HDC);
 BOOL       RemoveFontResource(LPSTR);
 BOOL       RemoveMenu(HMENU,UINT,UINT);
 void       ReplyMessage(LRESULT);
@@ -5095,7 +5160,6 @@
 int        SelectVisRgn(HDC,HRGN);
 HWND       SetActiveWindow(HWND);
 WORD       SetBkMode(HDC,WORD);
-HWND       SetCapture(HWND);
 HANDLE     SetClipboardData(WORD,HANDLE);
 HWND       SetClipboardViewer(HWND);
 void       SetConvertHook(BOOL);
@@ -5105,8 +5169,6 @@
 void       SetCursorPos(short,short);
 BOOL       SetDCHook(HDC,FARPROC16,DWORD);
 void       SetDCState(HDC,HDC);
-BOOL       SetDeskPattern(void);
-BOOL       SetDeskWallPaper(LPCSTR);
 void       SetDoubleClickTime(WORD);
 int        SetEnvironment(LPCSTR,LPCSTR,WORD);
 UINT       SetErrorMode(UINT);
@@ -5125,8 +5187,6 @@
 WORD       SetROP2(HDC,WORD);
 WORD       SetRelAbs(HDC,WORD);
 FARPROC16  SetResourceHandler(HANDLE,LPSTR,FARPROC16);
-int        SetScrollPos(HWND,int,int,BOOL);
-void       SetScrollRange(HWND,int,int,int,BOOL);
 int        SetSoundNoise(int,int);
 WORD       SetStretchBltMode(HDC,WORD);
 LONG       SetSwapAreaSize(WORD);
@@ -5151,7 +5211,6 @@
 HINSTANCE  ShellExecute(HWND,LPCSTR,LPCSTR,LPSTR,LPCSTR,INT);
 int        ShowCursor(BOOL);
 void       ShowOwnedPopups(HWND,BOOL);
-void       ShowScrollBar(HWND,WORD,BOOL);
 BOOL       ShowWindow(HWND,int);
 DWORD      SizeofResource(HMODULE16,HRSRC16);
 VOID       Sleep(DWORD); /* Win32 */
diff --git a/ipc/dde_proc.c b/ipc/dde_proc.c
index b78482d..59d8942 100644
--- a/ipc/dde_proc.c
+++ b/ipc/dde_proc.c
@@ -475,7 +475,7 @@
   }
 
   /* iterate through all the windows */
-  for (wndPtr = WIN_FindWndPtr(GetTopWindow(GetDesktopWindow()));
+  for (wndPtr = WIN_FindWndPtr(GetTopWindow(GetDesktopWindow32()));
        wndPtr != NULL;
        wndPtr = wndPtr->next)
   {
diff --git a/ipc/wine_test_stub.c b/ipc/wine_test_stub.c
index 4ecfa75..0fdb599 100644
--- a/ipc/wine_test_stub.c
+++ b/ipc/wine_test_stub.c
@@ -34,7 +34,7 @@
 }
 
 /* stub */
-HWND GetDesktopWindow()
+HWND32 GetDesktopWindow32()
 {
   printf("GetDesktopWindow\n");
   return 0;
diff --git a/loader/builtin.c b/loader/builtin.c
index 00571c5..0b67254 100644
--- a/loader/builtin.c
+++ b/loader/builtin.c
@@ -145,7 +145,7 @@
     { &W32SYS_Descriptor,   0 },
     /* Win32 DLLs */
     { &ADVAPI32_Descriptor, 0 },
-    { &COMCTL32_Descriptor, 0 },
+    { &COMCTL32_Descriptor, DLL_FLAG_NOT_USED },
     { &COMDLG32_Descriptor, 0 },
     { &CRTDLL_Descriptor,   0 },
     { &OLE32_Descriptor,    0 },
diff --git a/loader/module.c b/loader/module.c
index f8074df..c5ec62b 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -459,15 +459,15 @@
          ((offset)+(size) <= fastload_offset+fastload_length)) ? \
         (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
         (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
-         FILE_Read( hFile, (buffer), (size) ) == (size)))
+         _lread32( hFile, (buffer), (size) ) == (size)))
 
     _llseek( hFile, 0, SEEK_SET );
-    if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
+    if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
         (mz_header.mz_magic != MZ_SIGNATURE))
         return (HMODULE16)11;  /* invalid exe */
 
     _llseek( hFile, mz_header.ne_offset, SEEK_SET );
-    if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
+    if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
         return (HMODULE16)11;  /* invalid exe */
 
     if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE16)21;  /* win32 exe */
@@ -517,7 +517,7 @@
         if ((fastload = (char *)malloc( fastload_length )) != NULL)
         {
             _llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET );
-            if (FILE_Read( hFile, fastload, fastload_length ) != fastload_length)
+            if (_lread32(hFile, fastload, fastload_length) != fastload_length)
             {
                 free( fastload );
                 fastload = NULL;
@@ -632,7 +632,7 @@
         }
         buffer = GlobalLock16( pModule->nrname_handle );
         _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
-        if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length )
+        if (_lread32( hFile, buffer, ne_header.nrname_tab_length )
               != ne_header.nrname_tab_length)
         {
             GlobalFree16( pModule->nrname_handle );
@@ -1165,7 +1165,6 @@
 		  IF1632_Stack32_base = WIN16_GlobalLock16(hInitialStack32);
 
 		}
-                /* FIXME: we probably need a DOS handle here */
                 hf = FILE_DupUnixHandle( MODULE_OpenFile( hModule ) );
 		CallTo16_word_ww( selfloadheader->BootApp, hModule, hf );
                 _lclose(hf);
@@ -1215,6 +1214,7 @@
 
     if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
     {
+	HTASK16 hTask;
         WORD	showcmd;
 
 	/* PowerPoint passes NULL as showCmd */
@@ -1222,10 +1222,13 @@
 		showcmd = *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1);
 	else
 		showcmd = 0; /* FIXME: correct */
-        TASK_CreateTask( hModule, hInstance, hPrevInstance,
-                         params->hEnvironment,
-                         (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
-                         showcmd );
+
+        hTask = TASK_CreateTask( hModule, hInstance, hPrevInstance,
+                                 params->hEnvironment,
+                                (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
+                                 showcmd );
+
+	if( hTask && TASK_GetNextTask(hTask)) Yield();
     }
 
     return hInstance;
@@ -1479,14 +1482,8 @@
 #if 0
     if (handle < (HANDLE)32)	/* Error? */
 	return handle;
-    
-/* FIXME: Yield never returns! 
-   We may want to run more applications or start the debugger
-   before calling Yield. If we don't Yield will be called immdiately
-   after returning.  Why is it needed for Word anyway? */
-    Yield();	/* program is executed immediately ....needed for word */
-
 #endif
+
     return handle;
 }
 
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 6514c18..8ab35e9 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -2,6 +2,7 @@
 /* 
  *  Copyright	1994	Eric Youndale & Erik Bos
  *  Copyright	1995	Martin von Löwis
+ *  Copyright   1996    Marcus Meissner
  *
  *	based on Eric Youndale's pe-test and:
  *
@@ -30,6 +31,7 @@
 #include "registers.h"
 #include "stddebug.h"
 #include "debug.h"
+#include "debugger.h"
 #include "xmalloc.h"
 
 void my_wcstombs(char * result, u_short * source, int len)
@@ -77,34 +79,53 @@
 
 void dump_exports(struct PE_Export_Directory * pe_exports, unsigned int load_addr)
 { 
-  char * Module;
-  int i;
-  u_short * ordinal;
-  u_long * function;
-  u_char ** name, *ename;
+  char		*Module;
+  int		i;
+  u_short	*ordinal;
+  u_long	*function,*functions;
+  u_char	**name,*ename;
+  char		buffer[1000];
+  DBG_ADDR	daddr;
 
-  Module = ((char *) load_addr) + pe_exports->Name;
+  daddr.seg = 0;
+  Module = ((char*)load_addr)+pe_exports->Name;
   dprintf_win32(stddeb,"\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n", 
 	 Module,
 	 pe_exports->Number_Of_Functions,
 	 pe_exports->Number_Of_Names);
 
-  ordinal = (u_short *) (((char *) load_addr) + (int) pe_exports->Address_Of_Name_Ordinals);
-  function = (u_long *)  (((char *) load_addr) + (int) pe_exports->AddressOfFunctions);
-  name = (u_char **)  (((char *) load_addr) + (int) pe_exports->AddressOfNames);
+  ordinal=(u_short*)(((char*)load_addr)+(int)pe_exports->Address_Of_Name_Ordinals);
+  functions=function=(u_long*)(((char*)load_addr)+(int)pe_exports->AddressOfFunctions);
+  name=(u_char**)(((char*)load_addr)+(int)pe_exports->AddressOfNames);
 
   dprintf_win32(stddeb,"%-32s Ordinal Virt Addr\n", "Function Name");
-  for(i=0; i< pe_exports->Number_Of_Functions; i++) {
+  for (i=0;i<pe_exports->Number_Of_Functions;i++) {
       if (i<pe_exports->Number_Of_Names) {
-	  ename =  (char *) (((char *) load_addr) + (int) *name++);
-	  dprintf_win32(stddeb,"%-32s %4d    %8.8lx\n", ename, *ordinal++, *function++);
+	  ename=(char*)(((char*)load_addr)+(int)*name++);
+	  dprintf_win32(stddeb,"%-32s %4d    %8.8lx (%8.8lx)\n",ename,*ordinal,functions[*ordinal],*function);
+	  sprintf(buffer,"%s.%s",Module,ename);
+	  daddr.off=load_addr+functions[*ordinal];
+	  ordinal++;
+	  function++;
       } else {
       	  /* ordinals/names no longer valid, but we still got functions */
-	  dprintf_win32(stddeb,"%-32s %4s    %8.8lx\n","","",*function++);
+	  dprintf_win32(stddeb,"%-32s %4s    %8s %8.8lx\n","","","",*function);
+	  sprintf(buffer,"%s.%d",Module,i);
+	  daddr.off=load_addr+*functions;
+	  function++;
       }
+      DEBUG_AddSymbol(buffer,&daddr);
   }
 }
 
+/* Look up the specified function or ordinal in the exportlist:
+ * If it is a string:
+ * 	- look up the name in the Name list. 
+ *	- look up the ordinal with that index.
+ *	- use the ordinal as offset into the functionlist
+ * If it is a ordinal:
+ *	- use ordinal-pe_export->Base as offset into the functionlist
+ */
 FARPROC32 PE_FindExportedFunction(struct pe_data *pe, LPCSTR funcName)
 {
 	struct PE_Export_Directory * exports = pe->pe_export;
@@ -114,32 +135,29 @@
 	u_char ** name, *ename;
 	int i;
 
+	if (HIWORD(funcName))
+		dprintf_win32(stddeb,"PE_FindExportedFunction(%s)\n",funcName);
+	else
+		dprintf_win32(stddeb,"PE_FindExportedFunction(%d)\n",(int)funcName);
 	if (!exports)
 		return NULL;
 	ordinal=(u_short*)(((char*)load_addr)+(int)exports->Address_Of_Name_Ordinals);
 	function=(u_long*)(((char*)load_addr)+(int)exports->AddressOfFunctions);
 	name=(u_char **)(((char*)load_addr)+(int)exports->AddressOfNames);
 	if (HIWORD(funcName)) {
-		for(i=0; i<exports->Number_Of_Names; i++)
-		{
-			ename =  (char *) (((char *) load_addr) + (int) *name);
-			if(strcmp(ename,funcName)==0)
-				return (FARPROC32)(load_addr + *function);
-			function++;
+		for(i=0; i<exports->Number_Of_Names; i++) {
+			ename=(char*)(((char*)load_addr)+(int)*name);
+			if(!strcmp(ename,funcName))
+				return (FARPROC32)(load_addr+function[*ordinal]);
+			ordinal++;
 			name++;
 		}
 	} else {
-		/* if we got no name directory, we use the ordinal as offset */
-		if (!exports->Number_Of_Names) {
-			i = function[(int)funcName-exports->Base];
-			return (FARPROC32)(load_addr+i);
+		if (funcName-exports->Base > exports->Number_Of_Functions) {
+			dprintf_win32(stddeb,"	ordinal %d out of range!\n",funcName);
+			return NULL;
 		}
-		for(i=0; i<exports->Number_Of_Names; i++) {
-			if((int)funcName == (int)*ordinal + exports->Base)
-				return (FARPROC32)(load_addr + *function);
-			function++;
-			ordinal++;
-		}
+		return (FARPROC32)(load_addr+function[(int)funcName-exports->Base]);
 	}
 	return NULL;
 }
@@ -357,6 +375,10 @@
     int i, result;
     unsigned int load_addr;
     struct Directory dir;
+    char	buffer[200];
+    DBG_ADDR	daddr;
+
+	daddr.seg=0;
 
 	pe = xmalloc(sizeof(struct pe_data));
 	memset(pe,0,sizeof(struct pe_data));
@@ -511,9 +533,28 @@
 		dprintf_win32(stdnimp,"Callback directory ignored\n");
 
 
+	if(pe->pe_reloc) do_relocations(pe);
 	if(pe->pe_import) fixup_imports(pe, hModule);
 	if(pe->pe_export) dump_exports(pe->pe_export,load_addr);
-	if(pe->pe_reloc) do_relocations(pe);
+  		
+	if (pe->pe_export) {
+		/* add start of sections as debugsymbols */
+		for(i=0;i<pe->pe_header->coff.NumberOfSections;i++) {
+			sprintf(buffer,"%s.%s",
+				((char*)load_addr)+pe->pe_export->Name,
+				pe->pe_seg[i].Name
+			);
+			daddr.off=load_addr+pe->pe_seg[i].Virtual_Address;
+			DEBUG_AddSymbol(buffer,&daddr);
+		}
+		/* add entry point */
+		sprintf(buffer,"%s.EntryPoint",((char*)load_addr)+pe->pe_export->Name);
+		daddr.off=load_addr+pe->pe_header->opt_coff.AddressOfEntryPoint;
+		DEBUG_AddSymbol(buffer,&daddr);
+		/* add start of DLL */
+		daddr.off=load_addr;
+		DEBUG_AddSymbol(((char*)load_addr)+pe->pe_export->Name,&daddr);
+	}
         return pe;
 }
 
@@ -607,7 +648,7 @@
         printf("InitPEDLL() called!\n");
         CallDLLEntryProc32( (FARPROC32)(pe->load_addr + 
                                   pe->pe_header->opt_coff.AddressOfEntryPoint),
-                            hModule, DLL_PROCESS_ATTACH, 0 );
+                            hModule, DLL_PROCESS_ATTACH, (void *)-1 );
     }
 }
 
@@ -631,8 +672,8 @@
     TEB *pTEB;
 
     pTask = (TDB *)(GlobalLock16(GetCurrentTask() & 0xffff));
-    pTEB = (TEB *)(PTR_SEG_OFF_TO_LIN(hTEB, 0));
-    pTEB->stack = (void *)(GlobalLock16(pTask->hStack32));
+    pTEB  = (TEB *)(GlobalLock16(hTEB));
+    pTEB->stack = pTask->esp;
     pTEB->Except = (void *)(-1); 
     pTEB->TEBDSAlias = pTEB;
     pTEB->taskid = getpid();
diff --git a/loader/task.c b/loader/task.c
index cd58f36..0983041 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -671,18 +671,42 @@
     Yield();
     /* We should never return from this Yield() */
 
-    fprintf(stderr,"It's alive! Alive!!!\n");
+    fprintf(stderr,"Return of the living dead %04x!!!\n", hCurrentTask);
     exit(1);
 }
 
+/***********************************************************************
+ *           TASK_YieldToSystem
+ *
+ * Scheduler interface, this way we ensure that all "unsafe" events are
+ * processed outside the scheduler.
+ */
+void TASK_YieldToSystem(TDB* pTask)
+{
+  MESSAGEQUEUE*		pQ;
+
+  TASK_SCHEDULE();
+
+  if( pTask )
+  {
+    pQ = (MESSAGEQUEUE*)GlobalLock16(pTask->hQueue);
+    if( pQ && pQ->flags & QUEUE_FLAG_XEVENT )
+    {
+      pQ->flags &= ~QUEUE_FLAG_XEVENT;
+      EVENT_WaitXEvent( FALSE, FALSE );
+    }
+  }
+}
 
 /***********************************************************************
  *           TASK_Reschedule
  *
  * This is where all the magic of task-switching happens!
  *
- * This function should only be called via the TASK_SCHEDULE() macro, to make
- * sure that all the context is saved correctly.
+ * Note: This function should only be called via the TASK_YieldToSystem()
+ *       wrapper, to make sure that all the context is saved correctly.
+ *   
+ *       It must not call functions that may yield control.
  */
 void TASK_Reschedule(void)
 {
@@ -700,22 +724,22 @@
         hTaskToKill = 0;
     }
 
-    /* Flush any X events that happened in the meantime */
-
-    EVENT_WaitXEvent( FALSE );
-
     /* Find a task to yield to */
 
     pOldTask = (TDB *)GlobalLock16( hCurrentTask );
     if (pOldTask && pOldTask->hYieldTo)
     {
-        /* If a task is stored in hYieldTo of the current task (put there */
-        /* by DirectedYield), yield to it only if it has events pending.  */
+        /* check for DirectedYield() */
+
         hTask = pOldTask->hYieldTo;
         if (!(pNewTask = (TDB *)GlobalLock16( hTask )) || !pNewTask->nEvents)
             hTask = 0;
     }
 
+    /* extract hardware events only! */
+
+    EVENT_WaitXEvent( FALSE, TRUE );
+
     while (!hTask)
     {
         /* Find a task that has an event pending */
@@ -724,6 +748,9 @@
         while (hTask)
         {
             pNewTask = (TDB *)GlobalLock16( hTask );
+
+	    dprintf_task( stddeb, "\ttask = %04x, events = %i\n", hTask, pNewTask->nEvents);
+
             if (pNewTask->nEvents) break;
             hTask = pNewTask->hNext;
         }
@@ -732,11 +759,14 @@
 
         /* No task found, wait for some events to come in */
 
-        EVENT_WaitXEvent( TRUE );
+        EVENT_WaitXEvent( TRUE, TRUE );
     }
 
-    if (hTask == hCurrentTask) return;  /* Nothing to do */
-
+    if (hTask == hCurrentTask) 
+    {
+       dprintf_task( stddeb, "returning to the current task(%04x)\n", hTask );
+       return;  /* Nothing to do */
+    }
     pNewTask = (TDB *)GlobalLock16( hTask );
     dprintf_task( stddeb, "Switching to task %04x (%.8s)\n",
                   hTask, pNewTask->module_name );
@@ -843,10 +873,11 @@
         pTask->nEvents--;
         return FALSE;
     }
-    TASK_SCHEDULE();
+    TASK_YieldToSystem(pTask);
+
     /* When we get back here, we have an event */
+
     if (pTask->nEvents > 0) pTask->nEvents--;
-    else fprintf( stderr, "WaitEvent: reschedule returned without event\n" );
     return TRUE;
 }
 
@@ -914,7 +945,7 @@
 
     pCurTask = (TDB *)GlobalLock16( hCurrentTask );
     if (pCurTask) pCurTask->nEvents++;  /* Make sure we get back here */
-    TASK_SCHEDULE();
+    TASK_YieldToSystem(pCurTask);
     if (pCurTask) pCurTask->nEvents--;
 }
 
diff --git a/misc/clipboard.c b/misc/clipboard.c
index d25775c..03d80ca 100644
--- a/misc/clipboard.c
+++ b/misc/clipboard.c
@@ -30,7 +30,7 @@
     WORD	wRefCount;
     WORD	wDataPresent;
     LPSTR	Name;
-    HANDLE	hData;
+    HANDLE16	hData;
     DWORD	BufSize;
     struct tagCLIPFORMAT *PrevFormat;
     struct tagCLIPFORMAT *NextFormat;
@@ -47,42 +47,80 @@
 static BOOL bClipChanged  = FALSE;
 static WORD LastRegFormat = CF_REGFORMATBASE;
 
-static Bool wait_for_selection = False;
-static Bool wineOwnsSelection = False;
+static Bool   selectionWait = False;
+static Bool   selectionAcquired = False;
+static Window selectionWindow = None;
+static Window selectionPrevWindow = None;
 
 static CLIPFORMAT ClipFormats[16]  = {
-    { CF_TEXT, 1, 0, "Text", (HANDLE)NULL, 0, NULL, &ClipFormats[1] },
-    { CF_BITMAP, 1, 0, "Bitmap", (HANDLE)NULL, 0, &ClipFormats[0], &ClipFormats[2] },
-    { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE)NULL, 0, &ClipFormats[1], &ClipFormats[3] },
-    { CF_SYLK, 1, 0, "Sylk", (HANDLE)NULL, 0, &ClipFormats[2], &ClipFormats[4] },
-    { CF_DIF, 1, 0, "DIF", (HANDLE)NULL, 0, &ClipFormats[3], &ClipFormats[5] },
-    { CF_TIFF, 1, 0, "TIFF", (HANDLE)NULL, 0, &ClipFormats[4], &ClipFormats[6] },
-    { CF_OEMTEXT, 1, 0, "OEM Text", (HANDLE)NULL, 0, &ClipFormats[5], &ClipFormats[7] },
-    { CF_DIB, 1, 0, "DIB", (HANDLE)NULL, 0, &ClipFormats[6], &ClipFormats[8] },
-    { CF_PALETTE, 1, 0, "Palette", (HANDLE)NULL, 0, &ClipFormats[7], &ClipFormats[9] },
-    { CF_PENDATA, 1, 0, "PenData", (HANDLE)NULL, 0, &ClipFormats[8], &ClipFormats[10] },
-    { CF_RIFF, 1, 0, "RIFF", (HANDLE)NULL, 0, &ClipFormats[9], &ClipFormats[11] },
-    { CF_WAVE, 1, 0, "Wave", (HANDLE)NULL, 0, &ClipFormats[10], &ClipFormats[12] },
-    { CF_OWNERDISPLAY, 1, 0, "Owner Display", (HANDLE)NULL, 0, &ClipFormats[11], &ClipFormats[13] },
-    { CF_DSPTEXT, 1, 0, "DSPText", (HANDLE)NULL, 0, &ClipFormats[12], &ClipFormats[14] },
-    { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", (HANDLE)NULL, 0, &ClipFormats[13], &ClipFormats[15] },
-    { CF_DSPBITMAP, 1, 0, "DSPBitmap", (HANDLE)NULL, 0, &ClipFormats[14], NULL }
+    { CF_TEXT, 1, 0, "Text", (HANDLE16)NULL, 0, NULL, &ClipFormats[1] },
+    { CF_BITMAP, 1, 0, "Bitmap", (HANDLE16)NULL, 0, &ClipFormats[0], &ClipFormats[2] },
+    { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE16)NULL, 0, &ClipFormats[1], &ClipFormats[3] },
+    { CF_SYLK, 1, 0, "Sylk", (HANDLE16)NULL, 0, &ClipFormats[2], &ClipFormats[4] },
+    { CF_DIF, 1, 0, "DIF", (HANDLE16)NULL, 0, &ClipFormats[3], &ClipFormats[5] },
+    { CF_TIFF, 1, 0, "TIFF", (HANDLE16)NULL, 0, &ClipFormats[4], &ClipFormats[6] },
+    { CF_OEMTEXT, 1, 0, "OEM Text", (HANDLE16)NULL, 0, &ClipFormats[5], &ClipFormats[7] },
+    { CF_DIB, 1, 0, "DIB", (HANDLE16)NULL, 0, &ClipFormats[6], &ClipFormats[8] },
+    { CF_PALETTE, 1, 0, "Palette", (HANDLE16)NULL, 0, &ClipFormats[7], &ClipFormats[9] },
+    { CF_PENDATA, 1, 0, "PenData", (HANDLE16)NULL, 0, &ClipFormats[8], &ClipFormats[10] },
+    { CF_RIFF, 1, 0, "RIFF", (HANDLE16)NULL, 0, &ClipFormats[9], &ClipFormats[11] },
+    { CF_WAVE, 1, 0, "Wave", (HANDLE16)NULL, 0, &ClipFormats[10], &ClipFormats[12] },
+    { CF_OWNERDISPLAY, 1, 0, "Owner Display", (HANDLE16)NULL, 0, &ClipFormats[11], &ClipFormats[13] },
+    { CF_DSPTEXT, 1, 0, "DSPText", (HANDLE16)NULL, 0, &ClipFormats[12], &ClipFormats[14] },
+    { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", (HANDLE16)NULL, 0, &ClipFormats[13], &ClipFormats[15] },
+    { CF_DSPBITMAP, 1, 0, "DSPBitmap", (HANDLE16)NULL, 0, &ClipFormats[14], NULL }
     };
 
 /**************************************************************************
- *			CLIPBOARD_DisOwn
+ *                      CLIPBOARD_CheckSelection
  */
-void CLIPBOARD_DisOwn(HWND hWnd)
+void CLIPBOARD_CheckSelection(WND* pWnd)
+{
+  dprintf_clipboard(stddeb,"\tchecking %08x\n", (unsigned)pWnd->window);
+
+  if( selectionAcquired && selectionWindow != None &&
+      pWnd->window == selectionWindow )
+  {
+    selectionPrevWindow = selectionWindow;
+    selectionWindow = None;
+
+    if( pWnd->next ) 
+         selectionWindow = pWnd->next->window;
+    else if( pWnd->parent )
+             if( pWnd->parent->child != pWnd ) 
+                 selectionWindow = pWnd->parent->child->window;
+
+    dprintf_clipboard(stddeb,"\tswitching selection from %08x to %08x\n", 
+                    (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
+
+    if( selectionWindow != None )
+    {
+        XSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
+        if( XGetSelectionOwner(display, XA_PRIMARY) != selectionWindow )
+            selectionWindow = None;
+    }
+  }
+}
+
+/**************************************************************************
+ *			CLIPBOARD_DisOwn
+ *
+ * Called from DestroyWindow().
+ */
+void CLIPBOARD_DisOwn(WND* pWnd)
 {
   LPCLIPFORMAT lpFormat = ClipFormats;
 
-  if( hWnd != hWndClipOwner || !hWndClipOwner ) return;
+  dprintf_clipboard(stddeb,"DisOwn: clipboard owner = %04x, sw = %08x\n", 
+				hWndClipOwner, (unsigned)selectionWindow);
 
-  SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
+  if( pWnd->hwndSelf == hWndClipOwner)
+  {
+    SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
 
-  /* check if all formats were rendered */
+    /* check if all formats were rendered */
 
-  while(lpFormat)
+    while(lpFormat)
     { 
        if( lpFormat->wDataPresent && !lpFormat->hData )
 	 {
@@ -91,8 +129,12 @@
 	 }
        lpFormat = lpFormat->NextFormat;
     }
+    hWndClipOwner = 0;
+  }
 
-  hWndClipOwner = 0;
+  /* now try to salvage current selection from being destroyed by X */
+
+  CLIPBOARD_CheckSelection(pWnd);
 }
 
 /**************************************************************************
@@ -117,21 +159,31 @@
  */
 BOOL CLIPBOARD_RequestXSelection()
 {
-  HWND hWnd = hWndClipWindow;
+  HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
 
-  if( !hWnd ) hWnd = GetActiveWindow(); 
+  if( !hWnd ) return FALSE;
 
-  wait_for_selection=True;
-  dprintf_clipboard(stddeb,"Requesting selection\n");
+  dprintf_clipboard(stddeb,"Requesting selection...\n");
+
+  /* request data type XA_STRING, later
+   * CLIPBOARD_ReadSelection() will be invoked 
+   * from the SelectionNotify event handler */
 
   XConvertSelection(display,XA_PRIMARY,XA_STRING,
                     XInternAtom(display,"PRIMARY_TEXT",False),
                     WIN_GetXWindow(hWnd),CurrentTime);
 
-  /* TODO: need time-out for broken clients */
-  while(wait_for_selection) EVENT_WaitXEvent( TRUE );
+  /* wait until SelectionNotify is processed */
 
-  return (BOOL)ClipFormats[0].wDataPresent;
+  selectionWait=True;
+  while(selectionWait) 
+        EVENT_WaitXEvent( TRUE, FALSE );
+
+  /* we treat Unix text as CF_OEMTEXT */
+  dprintf_clipboard(stddeb,"\tgot CF_OEMTEXT = %i\n", 
+		    ClipFormats[CF_OEMTEXT-1].wDataPresent);
+
+  return (BOOL)ClipFormats[CF_OEMTEXT-1].wDataPresent;
 }
 
 /**************************************************************************
@@ -141,11 +193,18 @@
 {
     LPCLIPFORMAT lpFormat = ClipFormats; 
 
+    /* special case */
+
+    if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
+        return lpFormat[CF_TEXT-1].wDataPresent | 
+               lpFormat[CF_OEMTEXT-1].wDataPresent;
+
     while(TRUE) {
         if (lpFormat == NULL) return FALSE;
         if (lpFormat->wFormatID == wFormat) break;
         lpFormat = lpFormat->NextFormat;
         }
+
     return (lpFormat->wDataPresent);
 }
 
@@ -203,7 +262,7 @@
   
     while(lpFormat) 
       {
-	if ( lpFormat->wDataPresent )
+	if ( lpFormat->wDataPresent || lpFormat->hData )
 	     CLIPBOARD_DeleteRecord( lpFormat );
 
 	lpFormat = lpFormat->NextFormat;
@@ -211,9 +270,15 @@
 
     hWndClipOwner = hWndClipWindow;
 
-    if(wineOwnsSelection){
-        dprintf_clipboard(stddeb,"Losing selection\n");
-	wineOwnsSelection=False;
+    if(selectionAcquired)
+    {
+	selectionAcquired	= False;
+	selectionPrevWindow 	= selectionWindow;
+	selectionWindow 	= None;
+
+	dprintf_clipboard(stddeb, "\tgiving up selection (spw = %08x)\n", 
+				 	(unsigned)selectionPrevWindow);
+
 	XSetSelectionOwner(display,XA_PRIMARY,None,CurrentTime);
     }
     return TRUE;
@@ -240,7 +305,7 @@
     Window       owner;
 
     dprintf_clipboard(stddeb,
-		"SetClipboardDate(%04X, %04x) !\n", wFormat, hData);
+		"SetClipboardData(%04X, %04x) !\n", wFormat, hData);
 
     while(TRUE) 
       {
@@ -249,59 +314,138 @@
 	lpFormat = lpFormat->NextFormat;
       }
 
-    /* Acquire X selection:
-     *
-     * doc says we shouldn't use CurrentTime 
-     * should we become owner of CLIPBOARD as well? 
-     */
+    /* Acquire X selection if text format */
 
-    owner = WIN_GetXWindow(hWndClipWindow);
-
-    XSetSelectionOwner(display,XA_PRIMARY,owner,CurrentTime);
-    if( XGetSelectionOwner(display,XA_PRIMARY) == owner )
+    if( !selectionAcquired && 
+	(wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
+    {
+      owner = WIN_GetXWindow(hWndClipWindow);
+      XSetSelectionOwner(display,XA_PRIMARY,owner,CurrentTime);
+      if( XGetSelectionOwner(display,XA_PRIMARY) == owner )
       {
-        wineOwnsSelection = True;
-        dprintf_clipboard(stddeb,"Getting selection\n");
-      }
+        selectionAcquired = True;
+	selectionWindow = owner;
 
-    if ( lpFormat->wDataPresent ) 
-         CLIPBOARD_DeleteRecord(lpFormat);
+        dprintf_clipboard(stddeb,"Grabbed X selection, owner=(%08x)\n", 
+						(unsigned) owner);
+      }
+    }
+
+    if ( lpFormat->wDataPresent || lpFormat->hData ) 
+    {
+	CLIPBOARD_DeleteRecord(lpFormat);
+
+	/* delete existing CF_TEXT/CF_OEMTEXT aliases */
+
+	if( wFormat == CF_TEXT && ClipFormats[CF_OEMTEXT-1].hData
+	    && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
+	    CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1]);
+        if( wFormat == CF_OEMTEXT && ClipFormats[CF_TEXT-1].hData
+	    && !ClipFormats[CF_TEXT-1].wDataPresent )
+	    CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1]);
+    }
 
     bClipChanged = TRUE;
-    lpFormat->wDataPresent = TRUE;
-    lpFormat->hData = hData;
+    lpFormat->wDataPresent = 1;
+    lpFormat->hData = hData;          /* 0 is legal, see WM_RENDERFORMAT */
 
     return lpFormat->hData;
 }
 
+/**************************************************************************
+ *                      CLIPBOARD_RenderFormat
+ */
+BOOL32 CLIPBOARD_RenderFormat(LPCLIPFORMAT lpFormat)
+{
+ if( lpFormat->wDataPresent && !lpFormat->hData )
+   if( IsWindow(hWndClipOwner) )
+       SendMessage16(hWndClipOwner,WM_RENDERFORMAT,(WPARAM)lpFormat->wFormatID,0L);
+   else
+   {
+       dprintf_clipboard(stddeb,"\thWndClipOwner (%04x) is lost!\n", 
+                                      hWndClipOwner);
+       hWndClipOwner = 0; lpFormat->wDataPresent = 0;
+       return FALSE;
+   }
+ return (lpFormat->hData) ? TRUE : FALSE;
+}
+
+/**************************************************************************
+ *                      CLIPBOARD_RenderText
+ */
+BOOL32 CLIPBOARD_RenderText(LPCLIPFORMAT lpTarget, LPCLIPFORMAT lpSource)
+{
+  UINT		size = GlobalSize16( lpSource->hData );
+  LPCSTR	lpstrS = (LPSTR)GlobalLock16(lpSource->hData);
+  LPSTR		lpstrT;
+
+  if( !lpstrS ) return FALSE;
+  dprintf_clipboard(stddeb,"\tconverting from '%s' to '%s', %i chars\n",
+			   	      lpSource->Name, lpTarget->Name, size);
+
+  lpTarget->hData = GlobalAlloc16(GMEM_ZEROINIT, size); 
+  lpstrT = (LPSTR)GlobalLock16(lpTarget->hData);
+
+  if( lpstrT )
+  {
+    if( lpSource->wFormatID == CF_TEXT )
+	AnsiToOemBuff(lpstrS, lpstrT, size);
+    else
+	OemToAnsiBuff(lpstrS, lpstrT, size);
+    dprintf_clipboard(stddeb,"\tgot %s\n", lpstrT);
+    return TRUE;
+  }
+
+  lpTarget->hData = 0;
+  return FALSE;
+}
 
 /**************************************************************************
  *			GetClipboardData	[USER.142]
  */
 HANDLE GetClipboardData(WORD wFormat)
 {
-    LPCLIPFORMAT lpFormat = ClipFormats; 
-    dprintf_clipboard(stddeb,"GetClipboardData(%04X)\n", wFormat);
+    LPCLIPFORMAT lpRender = ClipFormats; 
+    LPCLIPFORMAT lpUpdate = NULL;
 
     if (!hWndClipWindow) return 0;
 
-    /*  if(wFormat == CF_TEXT && !wineOwnsSelection)
-        CLIPBOARD_RequestXSelection(); 
-     */
+    dprintf_clipboard(stddeb,"GetClipboardData(%04X)\n", wFormat);
 
-    while(TRUE) {
-	if (lpFormat == NULL) return 0;
-	if (lpFormat->wFormatID == wFormat) break;
-	lpFormat = lpFormat->NextFormat;
-	}
+    if( wFormat == CF_TEXT && !lpRender[CF_TEXT-1].wDataPresent 
+			   &&  lpRender[CF_OEMTEXT-1].wDataPresent )
+    {
+	lpRender = &ClipFormats[CF_OEMTEXT-1];
+	lpUpdate = &ClipFormats[CF_TEXT-1];
 
-    if( lpFormat->wDataPresent && !lpFormat->hData )
-      if( IsWindow(hWndClipOwner) )
-	  SendMessage16(hWndClipOwner,WM_RENDERFORMAT,(WPARAM)lpFormat->wFormatID,0L);
-      else
-	  dprintf_clipboard(stddeb,"\thWndClipOwner is lost\n");
-      
-    return lpFormat->hData;
+	dprintf_clipboard(stddeb,"\tOEMTEXT -> TEXT\n");
+    }
+    else if( wFormat == CF_OEMTEXT && !lpRender[CF_OEMTEXT-1].wDataPresent
+				   &&  lpRender[CF_TEXT-1].wDataPresent )
+    {
+        lpRender = &ClipFormats[CF_TEXT-1];
+	lpUpdate = &ClipFormats[CF_OEMTEXT-1];
+	
+	dprintf_clipboard(stddeb,"\tTEXT -> OEMTEXT\n");
+    }
+    else
+    {
+      while(TRUE) 
+      {
+	if (lpRender == NULL) return 0;
+	if (lpRender->wFormatID == wFormat) break;
+	lpRender = lpRender->NextFormat;
+      }
+      lpUpdate = lpRender;
+    }
+   
+    if( !CLIPBOARD_RenderFormat(lpRender) ) return 0; 
+    if( lpUpdate != lpRender &&
+	!lpUpdate->hData ) CLIPBOARD_RenderText(lpUpdate, lpRender);
+
+    dprintf_clipboard(stddeb,"\treturning %04x (type %i)\n", 
+			      lpUpdate->hData, lpUpdate->wFormatID);
+    return lpUpdate->hData;
 }
 
 
@@ -315,6 +459,11 @@
 
     dprintf_clipboard(stddeb,"CountClipboardFormats()\n");
 
+    if( !selectionAcquired ) CLIPBOARD_RequestXSelection();
+
+    FormatCount += abs(lpFormat[CF_TEXT-1].wDataPresent -
+		       lpFormat[CF_OEMTEXT-1].wDataPresent); 
+
     while(TRUE) {
 	if (lpFormat == NULL) break;
 	if (lpFormat->wDataPresent) 
@@ -334,21 +483,22 @@
 /**************************************************************************
  *			EnumClipboardFormats	[USER.144]
  */
-UINT EnumClipboardFormats(UINT wFormat)
+UINT16 EnumClipboardFormats(UINT16 wFormat)
 {
     LPCLIPFORMAT lpFormat = ClipFormats; 
 
     dprintf_clipboard(stddeb,"EnumClipboardFormats(%04X)\n", wFormat);
 
-    if( (!wFormat || wFormat == CF_TEXT) && !wineOwnsSelection)
-        CLIPBOARD_RequestXSelection();
+    if( !hWndClipWindow ) return 0;
 
-    if (wFormat == 0) {
-	if (lpFormat->wDataPresent) 
+    if( (!wFormat || wFormat == CF_TEXT || wFormat == CF_OEMTEXT) 
+	 && !selectionAcquired) CLIPBOARD_RequestXSelection();
+
+    if (wFormat == 0)
+	if (lpFormat->wDataPresent || ClipFormats[CF_OEMTEXT-1].wDataPresent) 
 	    return lpFormat->wFormatID;
 	else 
-	    wFormat = lpFormat->wFormatID;
-	}
+	    wFormat = lpFormat->wFormatID; /* and CF_TEXT is not available */
 
     /* walk up to the specified format record */
 
@@ -363,12 +513,12 @@
     lpFormat = lpFormat->NextFormat;
     while(TRUE) {
 	if (lpFormat == NULL) return 0;
-	if (lpFormat->wDataPresent ) break;
+	if (lpFormat->wDataPresent ||
+	       (lpFormat->wFormatID == CF_OEMTEXT &&
+		ClipFormats[CF_TEXT-1].wDataPresent)) break;
 	lpFormat = lpFormat->NextFormat;
 	}
 
-    dprintf_clipboard(stddeb, "\t got not empty - Id=%04X hData=%04x !\n",
-				lpFormat->wFormatID, lpFormat->hData);
     return lpFormat->wFormatID;
 }
 
@@ -500,8 +650,8 @@
 {
     dprintf_clipboard(stddeb,"IsClipboardFormatAvailable(%04X) !\n", wFormat);
 
-    if(wFormat == CF_TEXT && !wineOwnsSelection)
-	CLIPBOARD_RequestXSelection();
+    if( (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) &&
+        !selectionAcquired ) CLIPBOARD_RequestXSelection();
 
     return CLIPBOARD_IsPresent(wFormat);
 }
@@ -533,72 +683,112 @@
 /**************************************************************************
  *			CLIPBOARD_ReadSelection
  *
- *	The current selection owner has set prop at our window w
- *	Transfer the property contents into the Clipboard
+ * Called from the SelectionNotify event handler. 
  */
 void CLIPBOARD_ReadSelection(Window w,Atom prop)
 {
-    HANDLE hText;
+    HANDLE16 	 hText = 0;
     LPCLIPFORMAT lpFormat = ClipFormats; 
-    if(prop==None)
-        hText=0;
-    else
-      {
-	Atom atype=None;
-	int aformat;
-	unsigned long nitems,remain;
-	unsigned char *val=NULL;
 
-        dprintf_clipboard(stddeb,"Received prop %s\n",XGetAtomName(display,prop));
+    dprintf_clipboard(stddeb,"ReadSelection callback\n");
+
+    if(prop != None)
+    {
+	Atom		atype=AnyPropertyType;
+	int		aformat;
+	unsigned long 	nitems,remain;
+	unsigned char*	val=NULL;
+
+        dprintf_clipboard(stddeb,"\tgot property %s\n",XGetAtomName(display,prop));
 
         /* TODO: Properties longer than 64K */
 
 	if(XGetWindowProperty(display,w,prop,0,0x3FFF,True,XA_STRING,
-	    &atype, &aformat, &nitems, &remain, &val)!=Success)
-		fprintf(stderr,"couldn't read property\n");
+	    &atype, &aformat, &nitems, &remain, &val) != Success)
+	    dprintf_clipboard(stddeb,"\tcouldn't read property\n");
+	else
+	{
+           dprintf_clipboard(stddeb,"\tType %s,Format %d,nitems %ld,value %s\n",
+		             XGetAtomName(display,atype),aformat,nitems,val);
 
-        dprintf_clipboard(stddeb,"Type %s,Format %d,nitems %ld,value %s\n",
-		XGetAtomName(display,atype),aformat,nitems,val);
+	   if(atype == XA_STRING && aformat == 8)
+	   {
+	      int 	i,inlcount = 0;
+	      char*	lpstr;
 
-	if(atype!=XA_STRING || aformat!=8){
-	    fprintf(stderr,"Property not set\n");
-	    hText=0;
-	} else {
-	    dprintf_clipboard(stddeb,"Selection is %s\n",val);
-	    hText=GlobalAlloc16(GMEM_MOVEABLE, nitems+1);
-	    memcpy(GlobalLock16(hText),val,nitems+1);
-	    GlobalUnlock16(hText);
+	      dprintf_clipboard(stddeb,"\tselection is '%s'\n",val);
+
+	      for(i=0; i <= nitems; i++)
+		  if( val[i] == '\n' ) inlcount++;
+
+	      if( nitems )
+	      {
+	        hText=GlobalAlloc16(GMEM_MOVEABLE, nitems + inlcount + 1);
+	        if( (lpstr = (char*)GlobalLock16(hText)) )
+	          for(i=0,inlcount=0; i <= nitems; i++)
+	          {
+	  	     if( val[i] == '\n' ) lpstr[inlcount++]='\r';
+		     lpstr[inlcount++]=val[i];
+		  }
+	        else hText = 0;
+	      }
+	   }
+	   XFree(val);
 	}
-	XFree(val);
-      }
+   }
 
-    while(TRUE) {
-	if (lpFormat == NULL) return;
-	if (lpFormat->wFormatID == CF_TEXT) break;
-	lpFormat = lpFormat->NextFormat;
-	}
+   /* delete previous CF_TEXT and CF_OEMTEXT data */
 
-    if (lpFormat->wDataPresent) 
-       CLIPBOARD_DeleteRecord(lpFormat);
+   if( hText )
+   {
+     lpFormat = &ClipFormats[CF_TEXT-1];
+     if (lpFormat->wDataPresent || lpFormat->hData) 
+         CLIPBOARD_DeleteRecord(lpFormat);
+     lpFormat = &ClipFormats[CF_OEMTEXT-1];
+     if (lpFormat->wDataPresent || lpFormat->hData) 
+         CLIPBOARD_DeleteRecord(lpFormat);
 
-    wait_for_selection=False;
+     lpFormat->wDataPresent = 1;
+     lpFormat->hData = hText;
+   }
 
-    lpFormat->wDataPresent = TRUE;
-    lpFormat->hData = hText;
-    dprintf_clipboard(stddeb,"Received selection\n");
+   selectionWait=False;
 }
 
 /**************************************************************************
  *			CLIPBOARD_ReleaseSelection
  *
- *	Wine lost the primary selection.
- *	Empty the clipboard, but don't set the current owner to None.
- *	Make sure current get/put attempts fail.
+ * Wine might have lost XA_PRIMARY selection because of
+ * EmptyClipboard() or other client. 
  */
-void CLIPBOARD_ReleaseSelection(HWND hwnd)
+void CLIPBOARD_ReleaseSelection(Window w, HWND hwnd)
 {
-    wineOwnsSelection=False;
-    OpenClipboard(hwnd);
-    EmptyClipboard();
-    CloseClipboard();
+  /* w is the window that lost selection,
+   * 
+   * selectionPrevWindow is nonzero if CheckSelection() was called. 
+   */
+
+  dprintf_clipboard(stddeb,"\tevent->window = %08x (sw = %08x, spw=%08x)\n", 
+	  (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionPrevWindow );
+
+  if( selectionAcquired )
+    if( w == selectionWindow || selectionPrevWindow == None)
+    {
+      /* alright, we really lost it */
+
+      selectionAcquired = False;
+      selectionWindow = None; 
+
+      /* but we'll keep existing data for internal use */
+    }
+    else if( w == selectionPrevWindow )
+    {
+      w =  XGetSelectionOwner(display, XA_PRIMARY);
+
+      if( w == None )
+        XSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
+    }
+
+  selectionPrevWindow = None;
 }
+
diff --git a/misc/comm.c b/misc/comm.c
index 8fda4ae..613957b 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -1576,7 +1576,7 @@
  *	GetCommTimeouts		(KERNEL32.160)
  */
 BOOL32 GetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) {
-	dprintf_comm(stddeb,"GetCommTimeouts(%lx,%p), empty stub.\n",
+	dprintf_comm(stddeb,"GetCommTimeouts(%x,%p), empty stub.\n",
 		fd,lptimeouts
 	);
 	return TRUE;
@@ -1586,7 +1586,7 @@
  *	SetCommTimeouts		(KERNEL32.453)
  */
 BOOL32 SetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) {
-	dprintf_comm(stddeb,"SetCommTimeouts(%lx,%p), empty stub.\n",
+	dprintf_comm(stddeb,"SetCommTimeouts(%x,%p), empty stub.\n",
 		fd,lptimeouts
 	);
 	return TRUE;
diff --git a/misc/commdlg.c b/misc/commdlg.c
index e356a82..cb24335 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -1475,12 +1475,12 @@
 static void CC_PaintSelectedColor(HWND hDlg,COLORREF cr)
 {
  RECT16 rect;
- HDC  hdc;
+ HDC32  hdc;
  HBRUSH hBrush;
  HWND hwnd=GetDlgItem(hDlg,0x2c5);
  if (IsWindowVisible(GetDlgItem(hDlg,0x2c6)))   /* if full size */
  {
-  hdc=GetDC(hwnd);
+  hdc=GetDC32(hwnd);
   GetClientRect16 (hwnd, &rect) ;
   hBrush = CreateSolidBrush(cr);
   if (hBrush)
@@ -1496,7 +1496,7 @@
     DeleteObject (SelectObject (hdc, hBrush)) ;
    }
   }
-  ReleaseDC(hwnd,hdc);
+  ReleaseDC32(hwnd,hdc);
  }
 }
 
@@ -1505,7 +1505,7 @@
  */
 static void CC_PaintTriangle(HWND hDlg,int y)
 {
- HDC hDC;
+ HDC32 hDC;
  long temp;
  int w=GetDialogBaseUnits();
  POINT16 points[3];
@@ -1519,7 +1519,7 @@
  {
    GetClientRect16(hwnd,&rect);
    height=rect.bottom;
-   hDC=GetDC(hDlg);
+   hDC=GetDC32(hDlg);
 
    points[0].y=rect.top;
    points[0].x=rect.right;           /*  |  /|  */
@@ -1540,7 +1540,7 @@
    lpp->old3angle.top   =points[2].y-1;
    lpp->old3angle.bottom=points[1].y+1;
    Polygon16(hDC,points,3);
-   ReleaseDC(hDlg,hDC);
+   ReleaseDC32(hDlg,hDC);
  }
 }
 
@@ -1550,7 +1550,7 @@
  */
 static void CC_PaintCross(HWND hDlg,int x,int y)
 {
- HDC hDC;
+ HDC32 hDC;
  int w=GetDialogBaseUnits();
  HWND hwnd=GetDlgItem(hDlg,0x2c6);
  struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong32A(hDlg, DWL_USER); 
@@ -1561,7 +1561,7 @@
  if (IsWindowVisible(GetDlgItem(hDlg,0x2c6)))   /* if full size */
  {
    GetClientRect16(hwnd,&rect);
-   hDC=GetDC(hwnd);
+   hDC=GetDC32(hwnd);
    SelectClipRgn(hDC,CreateRectRgnIndirect16(&rect));   
    hPen=CreatePen(PS_SOLID,2,0);
    hPen=SelectObject(hDC,hPen);
@@ -1582,7 +1582,7 @@
    MoveTo(hDC,point.x,point.y-w); 
    LineTo(hDC,point.x,point.y+w);
    DeleteObject(SelectObject(hDC,hPen));
-   ReleaseDC(hwnd,hDC);
+   ReleaseDC32(hwnd,hDC);
  }
 }
 
@@ -1600,12 +1600,12 @@
  HWND hwnd=GetDlgItem(hDlg,0x2c6);
  struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong32A(hDlg, DWL_USER);  
  HBRUSH hbrush;
- HDC hdc ;
+ HDC32 hdc ;
  RECT16 rect,client;
  HCURSOR16 hcursor=SetCursor(LoadCursor16(0,IDC_WAIT));
 
  GetClientRect16(hwnd,&client);
- hdc=GetDC(hwnd);
+ hdc=GetDC32(hwnd);
  lpp->hdcMem = CreateCompatibleDC(hdc);
  lpp->hbmMem = CreateCompatibleBitmap(hdc,client.right,client.bottom);
  SelectObject(lpp->hdcMem,lpp->hbmMem);
@@ -1631,7 +1631,7 @@
   }
   rect.left=rect.right;
  }
- ReleaseDC(hwnd,hdc);
+ ReleaseDC32(hwnd,hdc);
  SetCursor(hcursor);
 }
 
@@ -1642,20 +1642,20 @@
 {
  HWND hwnd=GetDlgItem(hDlg,0x2c6);
  struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong32A(hDlg, DWL_USER); 
- HDC  hDC;
+ HDC32  hDC;
  RECT16 rect;
  if (IsWindowVisible(hwnd))   /* if full size */
  {
   if (!lpp->hdcMem)
    CC_PrepareColorGraph(hDlg);   /* should not be necessary */
 
-  hDC=GetDC(hwnd);
+  hDC=GetDC32(hwnd);
   GetClientRect16(hwnd,&rect);
   if (lpp->hdcMem)
     BitBlt(hDC,0,0,rect.right,rect.bottom,lpp->hdcMem,0,0,SRCCOPY);
   else
     fprintf(stderr,"choose color: hdcMem is not defined\n");
-  ReleaseDC(hwnd,hDC);
+  ReleaseDC32(hwnd,hDC);
  }
 }
 /***********************************************************************
@@ -1667,11 +1667,11 @@
  RECT16 rect,client;
  int lum,ldif,ydif,r,g,b;
  HBRUSH hbrush;
- HDC hDC;
+ HDC32 hDC;
 
  if (IsWindowVisible(hwnd))
  {
-  hDC=GetDC(hwnd);
+  hDC=GetDC32(hwnd);
   GetClientRect16(hwnd,&client);
   rect=client;
 
@@ -1690,7 +1690,7 @@
   }
   GetClientRect16(hwnd,&rect);
   FrameRect16(hDC,&rect,GetStockObject(BLACK_BRUSH));
-  ReleaseDC(hwnd,hDC);
+  ReleaseDC32(hwnd,hDC);
  }
 }
 
@@ -1775,7 +1775,7 @@
 {
  HWND hwnd=GetDlgItem(hDlg,0x2d0);
  RECT16 rect;
- HDC  hdc;
+ HDC32  hdc;
  HBRUSH hBrush;
  int dx,dy,i,j,k;
 
@@ -1784,7 +1784,7 @@
  dy=rect.bottom/rows;
  k=rect.left;
 
- hdc=GetDC(hwnd);
+ hdc=GetDC32(hwnd);
  GetClientRect16 (hwnd, &rect) ;
 
  for (j=0;j<rows;j++)
@@ -1804,7 +1804,7 @@
   rect.top=rect.top+dy;
   rect.left=k;
  }
- ReleaseDC(hwnd,hdc);
+ ReleaseDC32(hwnd,hdc);
  /* FIXME: draw_a_focus_rect */
 }
 /***********************************************************************
@@ -1814,7 +1814,7 @@
 {
  HWND hwnd=GetDlgItem(hDlg,0x2d1);
  RECT16 rect;
- HDC  hdc;
+ HDC32  hdc;
  HBRUSH hBrush;
  int dx,dy,i,j,k;
 
@@ -1824,7 +1824,7 @@
  dy=rect.bottom/rows;
  k=rect.left;
 
- hdc=GetDC(hwnd);
+ hdc=GetDC32(hwnd);
  if (hdc)
  {
   for (j=0;j<rows;j++)
@@ -1844,7 +1844,7 @@
    rect.top=rect.top+dy;
    rect.left=k;
   }
-  ReleaseDC(hwnd,hdc);
+  ReleaseDC32(hwnd,hdc);
  }
  /* FIXME: draw_a_focus_rect */
 }
@@ -1940,7 +1940,7 @@
 {
     int r,g,b,i,xx;
     UINT cokmsg;
-    HDC hdc;
+    HDC32 hdc;
     COLORREF *cr;
     struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong32A(hDlg, DWL_USER); 
     dprintf_commdlg(stddeb,"CC_WMCommand wParam=%x lParam=%lx\n",wParam,lParam);
@@ -2018,9 +2018,9 @@
 	       break;
 
           case 0x2c9:              /* resulting color */
-	       hdc=GetDC(hDlg);
+	       hdc=GetDC32(hDlg);
 	       lpp->lpcc->rgbResult=GetNearestColor(hdc,lpp->lpcc->rgbResult);
-	       ReleaseDC(hDlg,hdc);
+	       ReleaseDC32(hDlg,hdc);
 	       CC_EditSetRGB(hDlg,lpp->lpcc->rgbResult);
 	       CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
 	       r=GetRValue(lpp->lpcc->rgbResult);
@@ -2402,10 +2402,10 @@
 
   if (!SendMessage16(hcmb2,CB_GETCOUNT,0,0))
   {
-       HDC hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
+       HDC hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC32(hDlg);
        i=SetFontStylesToCombo2(hcmb2,hdc,lplf,lptm);
        if (!(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC))
-         ReleaseDC(hDlg,hdc);
+         ReleaseDC32(hDlg,hdc);
        if (i)
         return 0;  
   }
@@ -2418,7 +2418,7 @@
  */
 LRESULT CFn_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam)
 {
-  HDC hdc;
+  HDC32 hdc;
   int i,j,res,init=0;
   long l;
   LPLOGFONT16 lpxx;
@@ -2466,7 +2466,7 @@
     ShowWindow(GetDlgItem(hDlg,grp1),SW_HIDE);
     ShowWindow(GetDlgItem(hDlg,stc4),SW_HIDE);
   }
-  hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
+  hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC32(hDlg);
   if (hdc)
   {
     if (!EnumFontFamilies (hdc, NULL,FontFamilyEnumProc,(LPARAM)GetDlgItem(hDlg,cmb1)))
@@ -2520,7 +2520,7 @@
   }
 
   if (!(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC))
-    ReleaseDC(hDlg,hdc);
+    ReleaseDC32(hDlg,hdc);
   res=TRUE;
   if (CFn_HookCallChk(lpcf))
     res=CallWindowProc16(lpcf->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
@@ -2670,7 +2670,7 @@
   {
 	case cmb1:if (HIWORD(lParam)==CBN_SELCHANGE)
 		  {
-		    hdc=(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
+		    hdc=(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC32(hDlg);
 		    if (hdc)
 		    {
                       SendDlgItemMessage16(hDlg,cmb2,CB_RESETCONTENT,0,0); 
@@ -2689,7 +2689,7 @@
                         SEGPTR_FREE(str);
 		      }
 		      if (!(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC))
- 		        ReleaseDC(hDlg,hdc);
+ 		        ReleaseDC32(hDlg,hdc);
  		    }
  		    else
                     {
diff --git a/misc/lstr.c b/misc/lstr.c
index 318e3da..33b65d8 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -697,6 +697,7 @@
 				char	*fmtstr,*sprintfbuf,*x;
 				DWORD	*argliststart;
 
+				fmtstr = NULL;
 				f++;
 				if (!*f) {
 					ADD_TO_T('%');
@@ -722,7 +723,7 @@
 						f++;
 						if (NULL!=(x=strchr(f,'!'))) {
 							*x='\0';
-							fmtstr=xmalloc(strlen(f)+2);
+							fmtstr=(char*)xmalloc(strlen(f)+2);
 							sprintf(fmtstr,"%%%s",f);
 							f=x+1;
 						}
diff --git a/misc/lzexpand.c b/misc/lzexpand.c
index 717b586..1c47990 100644
--- a/misc/lzexpand.c
+++ b/misc/lzexpand.c
@@ -75,7 +75,7 @@
 		*b		= lzs->get[lzs->getcur++];
 		return		1;
 	} else {
-		int ret = FILE_Read(lzs->realfd,lzs->get,GETLEN);
+		int ret = _lread32(lzs->realfd,lzs->get,GETLEN);
 		if (ret==HFILE_ERROR)
 			return HFILE_ERROR;
 		if (ret==0)
@@ -102,7 +102,7 @@
 	/* We can't directly read the lzfileheader struct due to 
 	 * structure element alignment
 	 */
-	if (FILE_Read(fd,buf,14)<14)
+	if (_lread32(fd,buf,14)<14)
 		return 0;
 	memcpy(head->magic,buf,8);
 	memcpy(&(head->compressiontype),buf+8,1);
@@ -306,7 +306,7 @@
 		if (lzstates[i].lzfd==fd)
 			break;
 	if (i==nroflzstates)
-		return FILE_Read(fd,buf,toread);
+		return _lread32(fd,buf,toread);
 	lzs=lzstates+i;
 
 /* The decompressor itself is in a define, cause we need it twice
@@ -447,7 +447,7 @@
 
 	/* not compressed? just copy */
 	if (i==nroflzstates)
-		xread=FILE_Read;
+		xread=(INT32(*)(HFILE,LPVOID,UINT32))_lread32;
 	else
 		xread=LZRead32;
 	len=0;
diff --git a/misc/main.c b/misc/main.c
index 3adf5fb..ae853fc 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -9,13 +9,14 @@
 #include <string.h>
 #include <unistd.h>
 #include <ctype.h>
-#include <locale.h>
+/* #include <locale.h> */
 #ifdef MALLOC_DEBUGGING
 #include <malloc.h>
 #endif
 #include <X11/Xlib.h>
 #include <X11/Xresource.h>
 #include <X11/Xutil.h>
+#include <X11/Xlocale.h>
 #include <X11/cursorfont.h>
 #include "message.h"
 #include "module.h"
@@ -75,6 +76,8 @@
 
 #define WINE_CLASS    "Wine"    /* Class name for resources */
 
+#define WINE_APP_DEFAULTS "/usr/lib/X11/app-defaults/Wine"
+
 typedef struct tagENVENTRY {
   LPSTR	       	        Name;
   LPSTR	       	        Value;
@@ -371,14 +374,21 @@
  */
 static void MAIN_ParseOptions( int *argc, char *argv[] )
 {
-    char *display_name;
+    char *display_name = NULL;
     XrmValue value;
-    XrmDatabase db = XrmGetFileDatabase("/usr/lib/X11/app-defaults/Wine");
+    XrmDatabase db = XrmGetFileDatabase(WINE_APP_DEFAULTS);
+    int i;
+    char *xrm_string;
 
-      /* Parse command line */
     Options.programName = MAIN_GetProgramName( *argc, argv );
-    XrmParseCommand( &db, optionsTable, NB_OPTIONS,
-		     Options.programName, argc, argv );
+
+      /* Get display name from command line */
+    for (i = 1; i < *argc - 1; i++)
+        if (!strcmp( argv[i], "-display" ))
+	{
+	    display_name = argv[i+1];
+	    break;
+        }
 
 #ifdef WINELIB
     /* Need to assemble command line and pass it to WinMain */
@@ -389,8 +399,8 @@
 
       /* Open display */
 
-    if (MAIN_GetResource( db, ".display", &value )) display_name = value.addr;
-    else display_name = NULL;
+    if (display_name == NULL &&
+	MAIN_GetResource( db, ".display", &value )) display_name = value.addr;
 
     if (!(display = XOpenDisplay( display_name )))
     {
@@ -399,6 +409,17 @@
 	exit(1);
     }
 
+      /* Merge file and screen databases */
+    if ((xrm_string = XResourceManagerString( display )) != NULL)
+    {
+        XrmDatabase display_db = XrmGetStringDatabase( xrm_string );
+        XrmMergeDatabases( display_db, &db );
+    }
+
+      /* Parse command line */
+    XrmParseCommand( &db, optionsTable, NB_OPTIONS,
+		     Options.programName, argc, argv );
+
       /* Get all options */
     if (MAIN_GetResource( db, ".iconic", &value ))
 	Options.cmdShow = SW_SHOWMINIMIZED;
@@ -1130,7 +1151,7 @@
 			break;
 
 		case SPI_SETDESKWALLPAPER:
-			return (SetDeskWallPaper((LPSTR) lpvParam));
+			return (SetDeskWallPaper32((LPSTR) lpvParam));
 			break;
 
 		case SPI_SETDESKPATTERN:
diff --git a/misc/ole2nls.c b/misc/ole2nls.c
index 5690ec9..66a7a74 100644
--- a/misc/ole2nls.c
+++ b/misc/ole2nls.c
@@ -1229,3 +1229,8 @@
 	fprintf(stdnimp,"SetLocaleInfoA(%ld,%ld,%s)\n",lcid,lctype,data);
 	return TRUE;
 }
+
+BOOL IsValidLocale(DWORD lcid,DWORD flags) {
+	fprintf(stdnimp,"IsValidLocale(%ld,%ld)\n",lcid,flags);
+	return TRUE;
+}
diff --git a/misc/registry.c b/misc/registry.c
index ac00c2c..a0606ff 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -1106,19 +1106,19 @@
 	if (hfd==HFILE_ERROR)
 		return;
 	magic[4]=0;
-	if (4!=FILE_Read(hfd,magic,4))
+	if (4!=_lread32(hfd,magic,4))
 		return;
 	if (strcmp(magic,"CREG")) {
 		fprintf(stddeb,"%s is not a w95 registry.\n",fn);
 		return;
 	}
-	if (4!=FILE_Read(hfd,&version,4))
+	if (4!=_lread32(hfd,&version,4))
 		return;
-	if (4!=FILE_Read(hfd,&rgdbsection,4))
+	if (4!=_lread32(hfd,&rgdbsection,4))
 		return;
 	if (-1==_llseek(hfd,0x20,SEEK_SET))
 		return;
-	if (4!=FILE_Read(hfd,magic,4))
+	if (4!=_lread32(hfd,magic,4))
 		return;
 	if (strcmp(magic,"RGKN")) {
 		dprintf_reg(stddeb,"second IFF header not RGKN, but %s\n",magic);
@@ -1133,7 +1133,7 @@
 
 	nrofdkes = (end-where)/sizeof(struct dke)+100;
 	data = (char*)xmalloc(end-where);
-	if ((end-where)!=FILE_Read(hfd,data,end-where))
+	if ((end-where)!=_lread32(hfd,data,end-where))
 		return;
 	curdata = data;
 
@@ -1215,7 +1215,7 @@
 	if (-1==_llseek(hfd,rgdbsection,SEEK_SET))
 		return;
 	data = (char*)xmalloc(end-rgdbsection);
-	if ((end-rgdbsection)!=FILE_Read(hfd,data,end-rgdbsection))
+	if ((end-rgdbsection)!=_lread32(hfd,data,end-rgdbsection))
 		return;
 	_lclose(hfd);
 	curdata = data;
@@ -1554,13 +1554,14 @@
 	if (!lpszSubKey || !*lpszSubKey) {
 		add_handle(++currenthandle,lpNextKey,samDesired);
 		*retkey=currenthandle;
+		lpNextKey->flags|=REG_OPTION_TAINTED;
 		return SHELL_ERROR_SUCCESS;
 	}
 	split_keypath(lpszSubKey,&wps,&wpc);
 	i 	= 0;
 	while ((i<wpc) && (wps[i][0]=='\0')) i++;
 	lpxkey	= lpNextKey;
-	while (i<wpc) {
+	while (wps[i]) {
 		lpxkey=lpNextKey->nextsub;
 		while (lpxkey) {
 			if (!lstrcmp32W(wps[i],lpxkey->keyname))
@@ -1574,13 +1575,15 @@
 	}
 	if (lpxkey) {
 		add_handle(++currenthandle,lpxkey,samDesired);
+		lpxkey->flags  |= REG_OPTION_TAINTED;
 		*retkey		= currenthandle;
-		*lpDispos	= REG_OPENED_EXISTING_KEY;
+		if (lpDispos)
+			*lpDispos	= REG_OPENED_EXISTING_KEY;
 		FREE_KEY_PATH;
 		return	SHELL_ERROR_SUCCESS;
 	}
 	/* good. now the hard part */
-	while (i<wpc) {
+	while (wps[i]) {
 		lplpPrevKey	= &(lpNextKey->nextsub);
 		lpxkey		= *lplpPrevKey;
 		while (lpxkey) {
@@ -1598,6 +1601,7 @@
 		(*lplpPrevKey)->nextsub	= NULL;
 		(*lplpPrevKey)->values	= NULL;
 		(*lplpPrevKey)->nrofvalues = 0;
+		(*lplpPrevKey)->flags 	= REG_OPTION_TAINTED;
 		if (lpszClass)
 			(*lplpPrevKey)->class = strdupW(lpszClass);
 		else
@@ -1608,14 +1612,14 @@
 	add_handle(++currenthandle,lpNextKey,samDesired);
 
 	/*FIXME: flag handling correct? */
-	lpNextKey->flags= fdwOptions;
+	lpNextKey->flags= fdwOptions |REG_OPTION_TAINTED;
 	if (lpszClass)
 		lpNextKey->class = strdupW(lpszClass);
 	else
 		lpNextKey->class = NULL;
-	lpNextKey->flags|=REG_OPTION_TAINTED;
 	*retkey		= currenthandle;
-	*lpDispos	= REG_CREATED_NEW_KEY;
+	if (lpDispos)
+		*lpDispos	= REG_CREATED_NEW_KEY;
 	FREE_KEY_PATH;
 	return SHELL_ERROR_SUCCESS;
 }
diff --git a/misc/shell.c b/misc/shell.c
index dd7aa3b..4e80173 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -414,11 +414,11 @@
   int		size;
   
   _llseek( hFile, 0, SEEK_SET );
-  if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
+  if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
       (mz_header.mz_magic != MZ_SIGNATURE)) return (BYTE*)-1;
 
   _llseek( hFile, mz_header.ne_offset, SEEK_SET );
-  if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
+  if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
       return NULL;
 
   if (ne_header.ne_magic == PE_SIGNATURE) 
@@ -436,7 +436,7 @@
       if( !pTypeInfo ) return NULL;
 
       _llseek(hFile, mz_header.ne_offset+ne_header.resource_tab_offset, SEEK_SET);
-      if( FILE_Read( hFile, (char*)pTypeInfo, size) != size )
+      if( _lread32( hFile, (char*)pTypeInfo, size) != size )
 	{ free(pTypeInfo); return NULL; }
       return pTypeInfo;
     }
@@ -456,7 +456,7 @@
  if( (ptr = (BYTE*)GlobalLock16( handle )) )
    {
     _llseek( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
-     FILE_Read( hFile, (char*)ptr, pNInfo->length << sizeShift);
+     _lread32( hFile, (char*)ptr, pNInfo->length << sizeShift);
      return handle;
    }
  return (HANDLE)0;
@@ -473,7 +473,7 @@
  if( (ptr = (BYTE*)GlobalLock16( handle )) )
    {
     _llseek( hFile, lpiIDE->dwImageOffset, SEEK_SET);
-     FILE_Read( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
+     _lread32( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
      return handle;
    }
  return (HANDLE)0;
@@ -491,7 +491,7 @@
   int		i;
  
   _llseek( hFile, 0, SEEK_SET );
-  if( FILE_Read(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
+  if( _lread32(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
 
   /* check .ICO header 
    *
@@ -504,7 +504,7 @@
 
   lpiID = (LPicoICONDIR)xmalloc(i);
 
-  if( FILE_Read(hFile,(char*)lpiID->idEntries,i) == i )
+  if( _lread32(hFile,(char*)lpiID->idEntries,i) == i )
   {  
      HANDLE	handle = DirectResAlloc( hInst, 0x10,
 					 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
@@ -820,3 +820,16 @@
 	dprintf_reg(stdnimp, "ShellHookProc : Empty Stub !!!\n");
         return 0;
 }
+
+/*************************************************************************
+ *				SHGetFileInfoA		[SHELL32.54]
+ */
+DWORD
+SHGetFileInfo32A(LPCSTR path,DWORD dwFileAttributes,SHFILEINFO32A *psfi,
+	UINT32 sizeofpsfi,UINT32 flags
+) {
+	fprintf(stdnimp,"SHGetFileInfo32A(%s,0x%08lx,%p,%ld,0x%08lx)\n",
+		path,dwFileAttributes,psfi,sizeofpsfi,flags
+	);
+	return TRUE;
+}
diff --git a/misc/spy.c b/misc/spy.c
index 1a1b325..3cdf52d 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -148,8 +148,17 @@
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
     /* 0x00E0 - Win32 Scrollbars */
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    "SBM_SETPOS32",             /* 0x00e0 */
+    "SBM_GETPOS32",             /* 0x00e1 */
+    "SBM_SETRANGE32",           /* 0x00e2 */
+    "SBM_GETRANGE32",           /* 0x00e3 */
+    "SBM_ENABLE_ARROWS32",      /* 0x00e4 */
+    NULL,
+    "SBM_SETRANGEREDRAW32",     /* 0x00e6 */
+    NULL, NULL,
+    "SBM_SETSCROLLINFO32",      /* 0x00e9 */
+    "SBM_GETSCROLLINFO32",      /* 0x00ea */
+    NULL, NULL, NULL, NULL, NULL,
 
     /* 0x00F0 - Win32 Buttons */
     "BM_GETCHECK32",            /* 0x00f0 */
diff --git a/misc/user.c b/misc/user.c
index 3885e09..5763a46 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -16,11 +16,13 @@
 #include "hook.h"
 #include "debug.h"
 #include "toolhelp.h"
+#include "message.h"
 
 WORD USER_HeapSel = 0;
 
 
 extern HTASK	TASK_GetNextTask(HTASK);
+extern BOOL32   MENU_SwitchTPWndTo(HTASK);
 
 /***********************************************************************
  *           GetFreeSystemResources   (USER.284)
@@ -117,10 +119,13 @@
 
     WND* desktop = WIN_GetDesktop();
 
-    /* Patch desktop window queue */
+    /* Patch desktop window */
     if( desktop->hmemTaskQ == hQueue )
 	desktop->hmemTaskQ = GetTaskQueue(TASK_GetNextTask(hTask));
 
+    /* Patch resident popup menu window */
+    MENU_SwitchTPWndTo(0);
+
     /* Nuke timers */
 
     TIMER_RemoveQueueTimers( hQueue );
diff --git a/misc/winsocket.c b/misc/winsocket.c
index ce3c916..5cdae3d 100644
--- a/misc/winsocket.c
+++ b/misc/winsocket.c
@@ -1687,7 +1687,7 @@
 
 VOID
 WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6) {
-	fprintf(stdnimp,"WsControl(%lx,%lx,%lx,%lx,%lx,%lx)\n",
+	fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
 		x1,x2,x3,x4,x5,x6
 	);
 	fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
diff --git a/miscemu/dpmi.c b/miscemu/dpmi.c
index 453032d..77a3285 100644
--- a/miscemu/dpmi.c
+++ b/miscemu/dpmi.c
@@ -181,7 +181,20 @@
         AX_reg(context) = 0x8011; /* descriptor unavailable */
         SET_CFLAG(context);
         break;
-
+    case 0x0200: /* get real mode interrupt vector */
+	fprintf(stdnimp,
+		"int31: get realmode interupt vector(0x%02x) unimplemented.\n",
+		BL_reg(context)
+	);
+    	SET_CFLAG(context);
+        break;
+    case 0x0201: /* set real mode interrupt vector */
+	fprintf(stdnimp,
+		"int31: set realmode interupt vector(0x%02x,0x%04x:0x%04x) unimplemented\n",
+		BL_reg(context),CX_reg(context),DX_reg(context)
+	);
+    	SET_CFLAG(context);
+        break;
     case 0x0204:  /* Get protected mode interrupt vector */
 	dw = (DWORD)INT_GetHandler( BL_reg(context) );
 	CX_reg(context) = HIWORD(dw);
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index 3662fef..a1fef77 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -553,7 +553,7 @@
 
 #define	_MCI_STRDUP_TO_SEG(dest,source) {\
 	HANDLE	x;\
-	x=USER_HEAP_ALLOC(strlen(source));\
+	x=USER_HEAP_ALLOC(strlen(source)+1);\
 	dest=(LPSTR)MAKELONG(x,USER_HeapSel);\
 	strcpy(PTR_SEG_TO_LIN(dest),source);\
 }
@@ -575,8 +575,44 @@
 		}
 	}
 	dprintf_mmsys(stddeb, "mciOpen // wDevID=%d \n", wDevID);
-
 	memcpy(&mciOpenDrv[wDevID],lpParms,sizeof(*lpParms));
+
+	if (dwParam & MCI_OPEN_ELEMENT) {
+		char	*s,*t;
+
+		dprintf_mmsys(stddeb,"mciOpen // lpstrElementName='%s'\n",
+			(char*)PTR_SEG_TO_LIN(lpParms->lpstrElementName)
+		);
+		s=(char*)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
+		t=strrchr(s,'.');
+		if (t) {
+			GetProfileString("mci extensions",t+1,"*",str,sizeof(str));
+			AnsiUpper(str);
+			if (strcmp(str, "CDAUDIO") == 0) {
+				uDevTyp = MCI_DEVTYPE_CD_AUDIO;
+			} else
+			if (strcmp(str, "WAVEAUDIO") == 0) {
+				uDevTyp = MCI_DEVTYPE_WAVEFORM_AUDIO;
+			} else
+			if (strcmp(str, "SEQUENCER") == 0)	{
+				uDevTyp = MCI_DEVTYPE_SEQUENCER;
+			} else
+			if (strcmp(str, "ANIMATION1") == 0) {
+				uDevTyp = MCI_DEVTYPE_ANIMATION;
+			} else
+			if (strcmp(str, "AVIVIDEO") == 0) {
+				uDevTyp = MCI_DEVTYPE_DIGITAL_VIDEO;
+			} else 
+			if (strcmp(str,"*") == 0) {
+				dprintf_mmsys(stddeb,"No [mci extensions] entry for %s found.\n",t);
+				return MCIERR_EXTENSION_NOT_FOUND;
+			} else  {
+				dprintf_mmsys(stddeb,"[mci extensions] entry %s for %s not supported.\n",str,t);
+			}
+		} else
+			return MCIERR_EXTENSION_NOT_FOUND;
+	}
+
 	if (dwParam & MCI_OPEN_ALIAS) {
 		dprintf_mmsys(stddeb, "MCI_OPEN // Alias='%s' !\n",
 			(char*)PTR_SEG_TO_LIN(lpParms->lpstrAlias));
@@ -1911,7 +1947,7 @@
 	dprintf_mmio(stddeb, "mmioRead(%04X, %p, %ld);\n", hmmio, pch, cch);
 	lpmminfo = (LPMMIOINFO)GlobalLock16(hmmio);
 	if (lpmminfo == NULL) return 0;
-	count = FILE_Read(LOWORD(lpmminfo->dwReserved2), pch, cch);
+	count = _lread32(LOWORD(lpmminfo->dwReserved2), pch, cch);
 	GlobalUnlock16(hmmio);
 	dprintf_mmio(stddeb, "mmioRead // count=%ld\n", count);
 	return count;
@@ -2013,7 +2049,7 @@
 	lpmminfo = (LPMMIOINFO)GlobalLock16(hmmio);
 	if (lpmminfo == NULL) return 0;
 	if (uFlags == MMIO_READ) {
-		count = FILE_Read(LOWORD(lpmminfo->dwReserved2), 
+		count = _lread32(LOWORD(lpmminfo->dwReserved2), 
 			lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
 		}
 	if (uFlags == MMIO_WRITE) {
@@ -2081,7 +2117,7 @@
 		(uFlags & MMIO_FINDLIST)) {
 		dprintf_mmio(stddeb, "mmioDescend // MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc);
 		while (TRUE) {
-			if (FILE_Read(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, 
+			if (_lread32(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, 
 					sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
 				_llseek(LOWORD(lpmminfo->dwReserved2), dwOldPos, SEEK_SET);
 				GlobalUnlock16(hmmio);
@@ -2097,7 +2133,7 @@
 			}
 		}
 	else {
-		if (FILE_Read(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, 
+		if (_lread32(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, 
 				sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
 			_llseek(LOWORD(lpmminfo->dwReserved2), dwOldPos, SEEK_SET);
 			GlobalUnlock16(hmmio);
diff --git a/objects/bitmap.c b/objects/bitmap.c
index 5b060b0..53237a8 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -262,12 +262,34 @@
 }
 
 /**********************************************************************
+ *	    CopyImage32    (USER32.60)
+ *
+ * FIXME: implementation still lacks nearly all features, see LR_*
+ * defines in windows.h
+ */
+HANDLE32 CopyImage32( HANDLE32 hnd, UINT32 type, INT32 desiredx,
+                      INT32 desiredy, UINT32 flags )
+{
+    switch (type)
+    {
+	case IMAGE_BITMAP:
+		return hnd;	/* FIXME ... need to copy here */
+	case IMAGE_ICON:
+		return CopyIcon32(hnd);
+	case IMAGE_CURSOR:
+		return CopyCursor32(hnd);
+    }
+    return 0;
+}
+
+
+/**********************************************************************
  *	    LoadBitmap16    (USER.175)
  */
 HBITMAP16 LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
 {
     HBITMAP16 hbitmap = 0;
-    HDC hdc;
+    HDC32 hdc;
     HRSRC16 hRsrc;
     HGLOBAL16 handle;
     BITMAPINFO *info;
@@ -292,12 +314,12 @@
     if (!(handle = LoadResource16( instance, hRsrc ))) return 0;
 
     info = (BITMAPINFO *)LockResource16( handle );
-    if ((hdc = GetDC(0)) != 0)
+    if ((hdc = GetDC32(0)) != 0)
     {
         char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS );
         hbitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
                                   bits, info, DIB_RGB_COLORS );
-        ReleaseDC( 0, hdc );
+        ReleaseDC32( 0, hdc );
     }
     FreeResource16( handle );
     return hbitmap;
@@ -309,7 +331,7 @@
 HBITMAP32 LoadBitmap32W( HINSTANCE32 instance, LPCWSTR name )
 {
     HBITMAP32 hbitmap = 0;
-    HDC hdc;
+    HDC32 hdc;
     HRSRC32 hRsrc;
     HGLOBAL32 handle;
     BITMAPINFO *info;
@@ -325,12 +347,12 @@
     if (!(handle = LoadResource32( instance, hRsrc ))) return 0;
 
     info = (BITMAPINFO *)LockResource32( handle );
-    if ((hdc = GetDC(0)) != 0)
+    if ((hdc = GetDC32(0)) != 0)
     {
         char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS );
         hbitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
                                   bits, info, DIB_RGB_COLORS );
-        ReleaseDC( 0, hdc );
+        ReleaseDC32( 0, hdc );
     }
     return hbitmap;
 }
diff --git a/objects/cursoricon.c b/objects/cursoricon.c
index 2b1c67f..180e1ae 100644
--- a/objects/cursoricon.c
+++ b/objects/cursoricon.c
@@ -236,7 +236,7 @@
                                       BOOL fCursor )
 {
     HANDLE hAndBits, hXorBits;
-    HDC hdc;
+    HDC32 hdc;
     int size, sizeAnd, sizeXor;
     POINT16 hotspot = { 0 ,0 };
     BITMAPOBJ *bmpXor, *bmpAnd;
@@ -285,7 +285,7 @@
 
     /* Create the XOR bitmap */
 
-    if (!(hdc = GetDC( 0 )))
+    if (!(hdc = GetDC32( 0 )))
     {
         free( pInfo );
         return 0;
@@ -323,7 +323,7 @@
 
     hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader, CBM_INIT,
                                bits, pInfo, DIB_RGB_COLORS );
-    ReleaseDC( 0, hdc );
+    ReleaseDC32( 0, hdc );
 
     /* Now create the CURSORICONINFO structure */
 
@@ -788,7 +788,7 @@
     else
     {
         /* Set the same cursor for all top-level windows */
-        HWND hwnd = GetWindow( GetDesktopWindow(), GW_CHILD );
+        HWND hwnd = GetWindow( GetDesktopWindow32(), GW_CHILD );
         while(hwnd)
         {
             Window win = WIN_GetXWindow( hwnd );
diff --git a/objects/dc.c b/objects/dc.c
index db20ea8..76d925a 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -26,6 +26,8 @@
     0,                      /* flags */
     NULL,                   /* devCaps */
     0,                      /* hMetaFile */
+    0,			    /* hHT */
+    0,			    /* HTLen */
     0,                      /* hClipRgn */
     0,                      /* hVisRgn */
     0,                      /* hGCClipRgn */
@@ -293,7 +295,7 @@
     else val.line_style = LineSolid;
     val.line_width = dc->u.x.pen.width;
     val.cap_style  = CapRound;
-    val.join_style = JoinBevel;
+    val.join_style = JoinMiter;
     XChangeGC( display, dc->u.x.gc, 
 	       GCFunction | GCForeground | GCBackground | GCLineWidth |
 	       GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index 7686405..f196635 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -108,7 +108,7 @@
 static FONTOBJ SystemFont =
 {
     { 0, FONT_MAGIC, 1 },   /* header */
-    { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+    { 12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
 };
 
@@ -122,7 +122,7 @@
 static FONTOBJ SystemFixedFont =
 {
     { 0, FONT_MAGIC, 1 },   /* header */
-    { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+    { 12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
 };
 
diff --git a/objects/metafile.c b/objects/metafile.c
index 170a6d9..3d38d3a 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -2,7 +2,7 @@
  * Metafile functions
  *
  * Copyright  David W. Metcalfe, 1994
- *            Niels de Carpentier, Albrecht Kleine 1996
+ *            Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
  *
  */
 
@@ -17,9 +17,6 @@
 
 #define HTINCR  10      /* handle table allocation size increment */
 
-static HANDLE hHT;      /* handle of the handle table */
-static int HTLen;       /* allocated length of handle table */
-
 /******************************************************************
  *         GetMetafile         GDI.124 By Kenny MacDonald 30 Nov 94
  */
@@ -49,7 +46,7 @@
     return 0;
   }
   
-  if (FILE_Read(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
+  if (_lread32(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
     GlobalFree16(hmf);
     return 0;
   }
@@ -64,7 +61,7 @@
     return 0;
   }
   
-  if (FILE_Read(hFile, (char*)mh + mh->mtHeaderSize * 2, 
+  if (_lread32(hFile, (char*)mh + mh->mtHeaderSize * 2, 
 	        size - mh->mtHeaderSize * 2) == HFILE_ERROR) {
     GlobalFree16(hmf);
     return 0;
@@ -91,7 +88,7 @@
     DC *dc;
     HANDLE handle;
     METAHEADER *mh;
-    int hFile;
+    HFILE hFile;
     
     dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
 
@@ -106,7 +103,14 @@
         GDI_FreeObject(handle);
 	return 0;
     }
-    dc->w.bitsPerPixel    = screenDepth;
+    if (!(dc->w.hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
+				    sizeof(HANDLETABLE16) * HTINCR))) {
+	GlobalFree16(dc->w.hMetaFile);
+	GDI_FreeObject(handle);
+	return 0;
+    }
+    dc->w.HTLen = HTINCR;
+    dc->w.bitsPerPixel = screenDepth;
     mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
 
     mh->mtHeaderSize = MFHEADERSIZE / 2;
@@ -122,7 +126,9 @@
 	hFile = _lcreat(lpFilename, 0);
 	if (_lwrite32(hFile, (char *)mh, MFHEADERSIZE) == -1)
 	{
+	    GlobalFree16(dc->w.hHT);
 	    GlobalFree16(dc->w.hMetaFile);
+	    GDI_FreeObject(handle);
 	    return 0;
 	}
 	mh->mtNoParameters = hFile; /* store file descriptor here */
@@ -131,11 +137,6 @@
     else                     /* memory based metafile */
 	mh->mtType = 0;
 
-    /* create the handle table */
-    HTLen = HTINCR;
-    hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, 
-		      sizeof(HANDLETABLE16) * HTLen);
-    
     GlobalUnlock16(dc->w.hMetaFile);
     dprintf_metafile(stddeb,"CreateMetaFile: returning %04x\n", handle);
     return handle;
@@ -150,7 +151,7 @@
     HMETAFILE16 handle = 0;
     METAHEADER *mh;
     METAHEADER *mh2;
-    int hFile;
+    HFILE hFile;
     
     dprintf_metafile(stddeb,"CopyMetaFile: %s\n", lpFilename);
     
@@ -191,12 +192,13 @@
 {
     BOOL resu=FALSE;
     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
-    if (mh)
+    if (mh) {
       if (mh->mtType == 1 || mh->mtType == 0) 
         if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
           if (mh->mtVersion == MFVERSION)
             resu=TRUE;
-    GlobalUnlock16(hmf);            
+      GlobalUnlock16(hmf);
+    }
     dprintf_metafile(stddeb,"IsValidMetaFile %x => %d\n",hmf,resu);
     return resu;         
 }
@@ -228,7 +230,9 @@
 
     if (!MF_MetaParam0(dc, META_EOF))
     {
+	GlobalFree16(dc->w.hHT);
 	GlobalFree16(dc->w.hMetaFile);
+	GDI_FreeObject(hdc);
 	return 0;
     }	
 
@@ -238,20 +242,22 @@
 	mh->mtNoParameters = 0;
         if (_llseek(hFile, 0L, 0) == -1)
         {
+	    GlobalFree16(dc->w.hHT);
             GlobalFree16(dc->w.hMetaFile);
+	    GDI_FreeObject(hdc);
             return 0;
         }
         if (_lwrite32(hFile, (char *)mh, MFHEADERSIZE) == -1)
         {
+	    GlobalFree16(dc->w.hHT);
             GlobalFree16(dc->w.hMetaFile);
+	    GDI_FreeObject(hdc);
             return 0;
         }
         _lclose(hFile);
     }
 
-    /* delete the handle table */
-    GlobalFree16(hHT);
-
+    GlobalFree16(dc->w.hHT);
     hmf = dc->w.hMetaFile;
     GlobalUnlock16(hmf);
     GDI_FreeObject(hdc);
@@ -284,6 +290,7 @@
     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
     METARECORD *mr;
     HANDLETABLE16 *ht;
+    HGLOBAL16 hHT;
     int offset = 0;
     WORD i;
 
@@ -326,6 +333,7 @@
 {
     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
     METARECORD *mr;
+    HGLOBAL16 hHT;
     SEGPTR ht, spRecord;
     int offset = 0;
   
@@ -848,32 +856,27 @@
 
 
 /******************************************************************
- *         MF_AddHandleInternal
+ *         MF_AddHandleDC
  *
- *    Add a handle to the internal handle table and return the index
+ *    Add a handle to the handle table in the DC, growing table if
+ *    necessary. Return the index
  */
 
-int MF_AddHandleInternal(HANDLE hobj)
+int MF_AddHandleDC(DC *dc, HANDLE hobj)
 {
     int i;
-    HANDLETABLE16 *ht = (HANDLETABLE16 *)GlobalLock16(hHT);
+    HANDLETABLE16 *ht = (HANDLETABLE16 *)GlobalLock16(dc->w.hHT);
 
-    for (i = 0; i < HTLen; i++)
-    {
-	if (*(ht->objectHandle + i) == 0)
-	{
-	    *(ht->objectHandle + i) = hobj;
-	    GlobalUnlock16(hHT);
-	    return i;
-	}
+    if((i = MF_AddHandle(ht, dc->w.HTLen, hobj)) == -1) {
+	GlobalUnlock16(dc->w.hHT);
+	if(!(dc->w.hHT = GlobalReAlloc16(dc->w.hHT, (dc->w.HTLen + HTINCR) *
+	 sizeof(HANDLETABLE16), GMEM_MOVEABLE | GMEM_ZEROINIT)))
+	    return -1;
+	dc->w.HTLen += HTINCR;
+	ht = (HANDLETABLE16 *)GlobalLock16(dc->w.hHT);
+	i = MF_AddHandle(ht, dc->w.HTLen, hobj);
     }
-    GlobalUnlock16(hHT);
-    if (!(hHT = GlobalReAlloc16(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
-	return -1;
-    HTLen += HTINCR;
-    ht = (HANDLETABLE16 *)GlobalLock16(hHT);
-    *(ht->objectHandle + i) = hobj;
-    GlobalUnlock16(hHT);
+    GlobalUnlock16(dc->w.hHT);
     return i;
 }
 
@@ -1036,7 +1039,7 @@
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
 
-    if ((index = MF_AddHandleInternal(hBrush)) == -1)
+    if ((index = MF_AddHandleDC(dc, hBrush)) == -1)
 	return FALSE;
 
     mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
@@ -1128,7 +1131,7 @@
     mr = (METARECORD *)&buffer;
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
-    if ((index = MF_AddHandleInternal(hBrush)) == -1)
+    if ((index = MF_AddHandleDC(dc, hBrush)) == -1)
 	return FALSE;
 
     mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
@@ -1165,7 +1168,7 @@
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
 
-    if ((index = MF_AddHandleInternal(hPen)) == -1)
+    if ((index = MF_AddHandleDC(dc, hPen)) == -1)
 	return FALSE;
 
     mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
@@ -1202,7 +1205,7 @@
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
 
-    if ((index = MF_AddHandleInternal(hFont)) == -1)
+    if ((index = MF_AddHandleDC(dc, hFont)) == -1)
 	return FALSE;
 
     mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile);
diff --git a/objects/palette.c b/objects/palette.c
index a4897ba..1682d91 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -387,8 +387,8 @@
 
     if( hPal != STOCK_DEFAULT_PALETTE )
     {
-	HWND hWnd = WindowFromDC( hDC );
-	HWND hActive = GetActiveWindow();
+	HWND32 hWnd = WindowFromDC32( hDC );
+	HWND32 hActive = GetActiveWindow();
 	
 	/* set primary palette if it's related to current active */
 
@@ -414,8 +414,8 @@
     {
 	/* Send palette change notification */
 
-	HWND hWnd;
- 	if( (hWnd = WindowFromDC( hDC )) )
+	HWND32 hWnd;
+ 	if( (hWnd = WindowFromDC32( hDC )) )
             SendMessage16( HWND_BROADCAST, WM_PALETTECHANGED, hWnd, 0L);
     }
     return realized;
@@ -428,7 +428,7 @@
  */
 int UpdateColors( HDC hDC )
 {
-    HWND hWnd = WindowFromDC( hDC );
+    HWND32 hWnd = WindowFromDC32( hDC );
 
     /* Docs say that we have to remap current drawable pixel by pixel
      * but it would take forever given the speed of XGet/PutPixel.
diff --git a/objects/text.c b/objects/text.c
index fbe88bc..3d7eb81 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -224,6 +224,8 @@
 	tabwidth = size.cx * tabstop;
     }
 
+    if (flags & DT_CALCRECT) flags |= DT_NOCLIP;
+
     do
     {
 	prefix_offset = -1;
@@ -268,7 +270,7 @@
 	y += lh;
 	if (strPtr)
 	{
-	    if (!(flags & DT_NOCLIP) && !(flags & DT_CALCRECT))
+	    if (!(flags & DT_NOCLIP))
 	    {
 		if (y > rect->bottom - lh)
 		    break;
diff --git a/win32/console.c b/win32/console.c
index d933df5..ec866f5 100644
--- a/win32/console.c
+++ b/win32/console.c
@@ -11,6 +11,15 @@
 #include "stddebug.h"
 #include "debug.h"
 
+static CONSOLE_SCREEN_BUFFER_INFO dummyinfo =
+{
+    {80, 24},
+    {0, 0},
+    0,
+    {0, 0, 79, 23},
+    {80, 24}
+};
+
 /***********************************************************************
  *           SetConsoleCtrlHandler               (KERNEL32.459)
  */
@@ -19,3 +28,34 @@
 	return 0;
 }
 
+/***********************************************************************
+ *           GetConsoleScreenBufferInfo   (KERNEL32.190)
+ */
+BOOL32 GetConsoleScreenBufferInfo( HANDLE32 hConsoleOutput,
+                                   LPCONSOLE_SCREEN_BUFFER_INFO csbi )
+{
+    csbi->dwSize.x = 80;
+    csbi->dwSize.y = 24;
+    csbi->dwCursorPosition.x = 0;
+    csbi->dwCursorPosition.y = 0;
+    csbi->wAttributes = 0;
+    csbi->srWindow.Left	= 0;
+    csbi->srWindow.Right	= 79;
+    csbi->srWindow.Top	= 0;
+    csbi->srWindow.Bottom	= 23;
+    csbi->dwMaximumWindowSize.x = 80;
+    csbi->dwMaximumWindowSize.y = 24;
+    return TRUE;
+}
+
+/***********************************************************************
+ *            GetLargestConsoleWindowSize   (KERNEL32.226)
+ */
+COORD GetLargestConsoleWindowSize( HANDLE32 hConsoleOutput )
+{
+    return dummyinfo.dwMaximumWindowSize;
+}
+
+
+
+
diff --git a/win32/cursoricon32.c b/win32/cursoricon32.c
index 0e256a4..fb8a226 100644
--- a/win32/cursoricon32.c
+++ b/win32/cursoricon32.c
@@ -270,7 +270,7 @@
                                       BOOL fCursor )
 {
     HANDLE hAndBits, hXorBits, hRes;
-    HDC hdc;
+    HDC32 hdc;
     int size, sizeAnd, sizeXor;
     POINT16 hotspot = { 0 ,0 };
     BITMAPOBJ *bmpXor, *bmpAnd;
@@ -320,7 +320,7 @@
 
     /* Create the XOR bitmap */
 
-    if (!(hdc = GetDC( 0 )))
+    if (!(hdc = GetDC32( 0 )))
     {
         free( pInfo );
         return 0;
@@ -358,7 +358,7 @@
 
     hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader, CBM_INIT,
                                bits, pInfo, DIB_RGB_COLORS );
-    ReleaseDC( 0, hdc );
+    ReleaseDC32( 0, hdc );
 
     /* Now create the CURSORICONINFO structure */
 
diff --git a/win32/file.c b/win32/file.c
index c8463cb..150322b 100644
--- a/win32/file.c
+++ b/win32/file.c
@@ -167,7 +167,7 @@
 time_t FileTimeToUnixTime(FILETIME *filetime)
 {
     /* reverse of UnixTimeToFileTime */
-    return filetime->dwLowDateTime+(filetime->dwHighDateTime<<16);
+    return (filetime->dwLowDateTime>>16)+(filetime->dwHighDateTime<<16);
 }
 
 /***********************************************************************
@@ -339,7 +339,9 @@
 
 int CloseFileHandle(HFILE hFile)
 {
-    return _lclose(hFile);
+    if (!_lclose(hFile))
+	return TRUE;
+    return FALSE;
 }
 
 static int TranslateAccessFlags(DWORD access_flags)
@@ -451,6 +453,7 @@
 		buf.st_mode &= ~0222; /* octal!, clear write permission bits */
 		attributes &= ~FILE_ATTRIBUTE_READONLY;
 	}
+	attributes &= ~(FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
 	if (attributes)
 		fprintf(stdnimp,"SetFileAttributesA(%s):%lx attribute(s) not implemented.\n",lpFileName,attributes);
 	if (-1==chmod(fn,buf.st_mode)) {
diff --git a/win32/findfile.c b/win32/findfile.c
index 4520d2e..8f9bf52 100644
--- a/win32/findfile.c
+++ b/win32/findfile.c
@@ -148,8 +148,6 @@
 	return INVALID_HANDLE_VALUE;
     }
 
-    strcpy(context->mask, slash+1);
-
     /* uppercase mask in place */
     for (p = context->mask ; *p; p++)
 	*p = toupper(*p);
diff --git a/win32/memory.c b/win32/memory.c
index 86bca6e..a08b07f 100644
--- a/win32/memory.c
+++ b/win32/memory.c
@@ -268,6 +268,15 @@
     return 1;
 }
 
+/***********************************************************************
+ *           VirtualQuery               (KERNEL32.554)
+ */
+BOOL32 VirtualQuery(LPCVOID address,LPMEMORY_BASIC_INFORMATION buf,DWORD len) 
+{
+	/* FIXME: fill out structure  ... */
+	return TRUE;
+}
+
 int TranslateProtectionFlags(DWORD protection_flags)
 {
     int prot;
@@ -308,7 +317,7 @@
  */
 BOOL WIN32_IsBadReadPtr(void* ptr, unsigned int bytes)
 {
-	dprintf_global(stddeb,"IsBadReadPtr(%x,%x)\n",ptr,bytes);
+	dprintf_global(stddeb,"IsBadReadPtr(%x,%x)\n",(int)ptr,bytes);
 	/* FIXME: Should make check based on actual mappings, here */
 	return FALSE;
 }
@@ -318,7 +327,7 @@
  */
 BOOL WIN32_IsBadWritePtr(void* ptr, unsigned int bytes)
 {
-	dprintf_global(stddeb,"IsBadWritePtr(%x,%x)\n",ptr,bytes);
+	dprintf_global(stddeb,"IsBadWritePtr(%x,%x)\n",(int)ptr,bytes);
 	/* FIXME: Should make check based on actual mappings, here */
 	return FALSE;
 }
@@ -327,7 +336,7 @@
  */
 BOOL WIN32_IsBadCodePtr(void* ptr, unsigned int bytes)
 {
-	dprintf_global(stddeb,"IsBadCodePtr(%x,%x)\n",ptr,bytes);
+	dprintf_global(stddeb,"IsBadCodePtr(%x,%x)\n",(int)ptr,bytes);
 	/* FIXME: Should make check based on actual mappings, here */
 	return FALSE;
 }
diff --git a/win32/newfns.c b/win32/newfns.c
index 9af9c00..b114cdd 100644
--- a/win32/newfns.c
+++ b/win32/newfns.c
@@ -33,6 +33,14 @@
 	return (HHOOK) NULL;
 }
 
+HHOOK SetWindowsHook32A(int HookId, HOOKPROC32 hookfn)
+{
+	/* Stub for now */
+	fprintf(stdnimp, "SetWindowsHook32A Stub called! (hook Id %d)\n", HookId);
+	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+	return (HHOOK) NULL;
+}
+
 BOOL UnhookWindowsHookEx32(HHOOK hHook)
 
 {
diff --git a/win32/thread.c b/win32/thread.c
index 6b67874..accc9f4 100644
--- a/win32/thread.c
+++ b/win32/thread.c
@@ -67,6 +67,11 @@
 	return;
 }
 
+void
+ReinitializeCriticalSection(CRITICAL_SECTION *lpCrit) {
+	/* hmm */
+}
+
 /***********************************************************************
  *           Tls is available only for the single thread
  * (BTW: TLS means Thread Local Storage)
diff --git a/windows/caret.c b/windows/caret.c
index e7f4b65..86acfa3 100644
--- a/windows/caret.c
+++ b/windows/caret.c
@@ -49,7 +49,7 @@
  */
 static void CARET_DisplayCaret( DISPLAY_CARET status )
 {
-    HDC16 hdc;
+    HDC32 hdc;
     HBRUSH16 hPrevBrush;
 
     if (Caret.on && (status == CARET_ON)) return;
@@ -58,11 +58,11 @@
     /* So now it's always a toggle */
 
     Caret.on = !Caret.on;
-    if (!(hdc = GetDCEx( Caret.hwnd, 0, DCX_USESTYLE | DCX_CACHE ))) return;
+    if (!(hdc = GetDCEx32( Caret.hwnd, 0, DCX_USESTYLE | DCX_CACHE ))) return;
     hPrevBrush = SelectObject( hdc, Caret.hBrush );
     PatBlt( hdc, Caret.x, Caret.y, Caret.width, Caret.height, PATINVERT );
     SelectObject( hdc, hPrevBrush );
-    ReleaseDC( Caret.hwnd, hdc );
+    ReleaseDC32( Caret.hwnd, hdc );
 }
 
   
diff --git a/windows/class.c b/windows/class.c
index e956801..c89e96f 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -44,10 +44,10 @@
     fprintf( stderr, "Class %p:\n", ptr );
     fprintf( stderr,
              "next=%p  name=%04x '%s'  style=%08x  wndProc=%08x\n"
-             "inst=%04x  hdce=%04x  icon=%04x  cursor=%04x  bkgnd=%04x\n"
+             "inst=%04x  dce=%08x  icon=%04x  cursor=%04x  bkgnd=%04x\n"
              "clsExtra=%d  winExtra=%d  #windows=%d\n",
              ptr->next, ptr->atomName, className, ptr->style,
-             (UINT32)ptr->winproc, ptr->hInstance, ptr->hdce,
+             (UINT32)ptr->winproc, ptr->hInstance, (UINT32)ptr->dce,
              ptr->hIcon, ptr->hCursor, ptr->hbrBackground,
              ptr->cbClsExtra, ptr->cbWndExtra, ptr->cWindows );
     if (ptr->cbClsExtra)
@@ -181,7 +181,7 @@
 
     /* Delete the class */
 
-    if (classPtr->hdce) DCE_FreeDCE( classPtr->hdce );
+    if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
     if (classPtr->hbrBackground) DeleteObject( classPtr->hbrBackground );
     GlobalDeleteAtom( classPtr->atomName );
     CLASS_SetMenuNameA( classPtr, NULL );
@@ -288,7 +288,9 @@
     classPtr->atomName    = atom;
     classPtr->menuNameA   = 0;
     classPtr->menuNameW   = 0;
-    classPtr->hdce        = (style&CS_CLASSDC) ? DCE_AllocDCE(0, DCE_CLASS_DC): 0;
+    classPtr->dce         = (style & CS_CLASSDC) ?
+                                 DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
+
     WINPROC_SetProc( &classPtr->winproc, wndProc, wndProcType );
 
     /* Other values must be set by caller */
diff --git a/windows/dce.c b/windows/dce.c
index b52d547..7afa5f7 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -19,7 +19,7 @@
 #include "class.h"
 #include "win.h"
 #include "gdi.h"
-#include "user.h"
+#include "heap.h"
 #include "sysmetrics.h"
 #include "stddebug.h"
 /* #define DEBUG_DC */
@@ -27,7 +27,7 @@
 
 #define NB_DCE    5  /* Number of DCEs created at startup */
 
-static HANDLE firstDCE = 0;
+static DCE *firstDCE = 0;
 static HDC defaultDCstate = 0;
 
 BOOL   DCHook(HDC, WORD, DWORD, DWORD);
@@ -37,26 +37,24 @@
 *
  * Allocate a new DCE.
  */
-HANDLE DCE_AllocDCE( HWND hWnd, DCE_TYPE type )
+DCE *DCE_AllocDCE( HWND32 hWnd, DCE_TYPE type )
 {
     DCE * dce;
-    HANDLE handle = USER_HEAP_ALLOC( sizeof(DCE) );
-    if (!handle) return 0;
-    dce = (DCE *) USER_HEAP_LIN_ADDR( handle );
+    if (!(dce = HeapAlloc( SystemHeap, 0, sizeof(DCE) ))) return NULL;
     if (!(dce->hDC = CreateDC( "DISPLAY", NULL, NULL, NULL )))
     {
-	USER_HEAP_FREE( handle );
+        HeapFree( SystemHeap, 0, dce );
 	return 0;
     }
 
     /* store DCE handle in DC hook data field */
 
-    SetDCHook(dce->hDC, GDI_GetDefDCHook(), MAKELONG(handle,DC_MAGIC));
+    SetDCHook(dce->hDC, GDI_GetDefDCHook(), (DWORD)dce);
 
     dce->hwndCurrent = hWnd;
-    dce->hNext = firstDCE;
-    dce->hClipRgn = 0;
-    firstDCE = handle;
+    dce->hClipRgn    = 0;
+    dce->next        = firstDCE;
+    firstDCE = dce;
 
     if( type != DCE_CACHE_DC )
       {
@@ -72,77 +70,60 @@
       }
     else dce->DCXflags = DCX_CACHE;
 
-    return handle;
+    return dce;
 }
 
 
 /***********************************************************************
  *           DCE_FreeDCE
  */
-void DCE_FreeDCE( HANDLE hdce )
+void DCE_FreeDCE( DCE *dce )
 {
-    DCE * dce;
-    HANDLE *handle = &firstDCE;
+    DCE **ppDCE = &firstDCE;
 
-    if (!(dce = (DCE *) USER_HEAP_LIN_ADDR( hdce ))) return;
-    while (*handle && (*handle != hdce))
-    {
-	DCE * prev = (DCE *) USER_HEAP_LIN_ADDR( *handle );	
-	handle = &prev->hNext;
-    }
-    if (*handle == hdce) *handle = dce->hNext;
+    if (!dce) return;
+    while (*ppDCE && (*ppDCE != dce)) ppDCE = &(*ppDCE)->next;
+    if (*ppDCE == dce) *ppDCE = dce->next;
 
     SetDCHook(dce->hDC,(SEGPTR)NULL,0L);
 
     DeleteDC( dce->hDC );
     if( dce->hClipRgn && !(dce->DCXflags & DCX_KEEPCLIPRGN) )
 	DeleteObject(dce->hClipRgn);
-    USER_HEAP_FREE( hdce );
+    HeapFree( SystemHeap, 0, dce );
 }
 
-/***********************************************************************
- *           DCE_FindDCE
- */
-HANDLE DCE_FindDCE(HDC hDC)
-{
- HANDLE hdce = firstDCE;
- DCE*   dce;
-
- while( hdce )
-  {
-    dce = (DCE *) USER_HEAP_LIN_ADDR(hdce);
-    if( dce->hDC == hDC ) break;
-    hdce = dce->hNext;
-  }
- return hdce;
-}
 
 /**********************************************************************
- *          WindowFromDC   (USER.117) (USER32.580)
+ *          WindowFromDC16   (USER32.580)
  */
-HWND16 WindowFromDC( HDC32 hDC )
+HWND16 WindowFromDC16( HDC16 hDC )
 {
- HANDLE16 hdce = DCE_FindDCE(hDC); 
-
- if( hdce )
-   {
-     DCE* dce = (DCE *) USER_HEAP_LIN_ADDR(hdce);
-     return dce->hwndCurrent;
-   }
-
- return 0;
+    return (HWND16)WindowFromDC32( hDC );
 }
 
+
+/**********************************************************************
+ *          WindowFromDC32   (USER32.580)
+ */
+HWND32 WindowFromDC32( HDC32 hDC )
+{
+    DCE *dce = firstDCE;
+    while (dce && (dce->hDC != hDC)) dce = dce->next;
+    return dce ? dce->hwndCurrent : 0;
+}
+
+
 /***********************************************************************
  *   DCE_InvalidateDCE
  *
  * It is called from SetWindowPos - we have to invalidate all busy
  * DCE's for windows whose client rect intersects with update rectangle 
  */
-BOOL DCE_InvalidateDCE(WND* wndScope, RECT16* pRectUpdate)
+BOOL32 DCE_InvalidateDCE(WND* wndScope, RECT16* pRectUpdate)
 {
- HANDLE hdce;
- DCE*   dce;
+    BOOL32 bRet = FALSE;
+    DCE *dce;
 
  if( !wndScope ) return 0;
 
@@ -151,10 +132,8 @@
 				        pRectUpdate->right,pRectUpdate->bottom);
  /* walk all DCE's */
 
- for( hdce = firstDCE; (hdce); hdce=dce->hNext)
+ for (dce = firstDCE; (dce); dce = dce->next)
   { 
-    dce = (DCE*)USER_HEAP_LIN_ADDR(hdce);
-
     if( dce->DCXflags & DCX_DCEBUSY )
       {
         WND * wndCurrent, * wnd; 
@@ -177,12 +156,15 @@
 	        MapWindowPoints16(wndCurrent->parent->hwndSelf, wndScope->hwndSelf,
 			 				       (LPPOINT16)&wndRect, 2);
 	        if( IntersectRect16(&wndRect,&wndRect,pRectUpdate) )
-	            SetHookFlags(dce->hDC, DCHF_INVALIDATEVISRGN);
+	        {    
+		   SetHookFlags(dce->hDC, DCHF_INVALIDATEVISRGN);
+		   bRet = TRUE;
+		}
 	        break;
 	      }
       }
   }
- return 1;
+ return bRet;
 }
 
 /***********************************************************************
@@ -191,13 +173,11 @@
 void DCE_Init()
 {
     int i;
-    HANDLE handle;
     DCE * dce;
         
     for (i = 0; i < NB_DCE; i++)
     {
-	if (!(handle = DCE_AllocDCE( 0, DCE_CACHE_DC ))) return;
-	dce = (DCE *) USER_HEAP_LIN_ADDR( handle );	
+	if (!(dce = DCE_AllocDCE( 0, DCE_CACHE_DC ))) return;
 	if (!defaultDCstate) defaultDCstate = GetDCState( dce->hDC );
     }
 }
@@ -400,14 +380,23 @@
     }
 }
 
+
 /***********************************************************************
- *           GetDCEx    (USER.359)
+ *           GetDCEx16    (USER.359)
+ */
+HDC16 GetDCEx16( HWND16 hwnd, HRGN16 hrgnClip, DWORD flags )
+{
+    return (HDC16)GetDCEx32( hwnd, hrgnClip, flags );
+}
+
+
+/***********************************************************************
+ *           GetDCEx32    (USER32.230)
  *
  * Unimplemented flags: DCX_LOCKWINDOWUPDATE
  */
-HDC GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
+HDC32 GetDCEx32( HWND32 hwnd, HRGN32 hrgnClip, DWORD flags )
 {
-    HANDLE 	hdce;
     HRGN 	hrgnVisible;
     HDC 	hdc = 0;
     DCE * 	dce;
@@ -446,7 +435,8 @@
         flags &= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN);
       }
 
-    if (hwnd==GetDesktopWindow() || !(wndPtr->dwStyle & WS_CHILD)) flags &= ~DCX_PARENTCLIP;
+    if (hwnd == GetDesktopWindow32() || !(wndPtr->dwStyle & WS_CHILD))
+        flags &= ~DCX_PARENTCLIP;
 
     if (flags & DCX_WINDOW) flags = (flags & ~DCX_CLIPCHILDREN) | DCX_CACHE;
 
@@ -464,17 +454,14 @@
 
     if (flags & DCX_CACHE)
     {
-	for (hdce = firstDCE; (hdce); hdce = dce->hNext)
+	for (dce = firstDCE; (dce); dce = dce->next)
 	{
-	    if (!(dce = (DCE *) USER_HEAP_LIN_ADDR( hdce ))) return 0;
 	    if ((dce->DCXflags & DCX_CACHE) && !(dce->DCXflags & DCX_DCEBUSY)) break;
 	}
     }
     else 
     {
-        hdce = (wndPtr->class->style & CS_OWNDC)?wndPtr->hdce:wndPtr->class->hdce;
-	dce = (DCE *) USER_HEAP_LIN_ADDR( hdce );
-
+        dce = (wndPtr->class->style & CS_OWNDC)?wndPtr->dce:wndPtr->class->dce;
 	if( dce->hwndCurrent == hwnd )
 	  {
 	    dprintf_dc(stddeb,"\tskipping hVisRgn update\n");
@@ -491,8 +478,7 @@
 
     dcx_flags = flags & ( DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_CACHE | DCX_WINDOW | DCX_WINDOWPAINT);
 
-    if (!hdce) return 0;
-    dce = (DCE *) USER_HEAP_LIN_ADDR( hdce );
+    if (!dce) return 0;
     dce->hwndCurrent = hwnd;
     dce->hClipRgn = 0;
     dce->DCXflags = dcx_flags | DCX_DCEBUSY;
@@ -502,7 +488,7 @@
 
     DCE_SetDrawable( wndPtr, dc, flags );
     if( need_update || dc->w.flags & DC_DIRTY )
-     {
+    {
       dprintf_dc(stddeb,"updating hDC anyway\n");
 
       if (flags & DCX_PARENTCLIP)
@@ -521,16 +507,27 @@
         }
            /* optimize away GetVisRgn for desktop if it isn't there */
 
-      else if ((hwnd == GetDesktopWindow()) &&
+      else if ((hwnd == GetDesktopWindow32()) &&
                (rootWindow == DefaultRootWindow(display)))
 	       hrgnVisible = CreateRectRgn( 0, 0, SYSMETRICS_CXSCREEN,
                                                   SYSMETRICS_CYSCREEN);
       else hrgnVisible = DCE_GetVisRgn( hwnd, flags );
 
-      dc->w.flags &= ~DC_DIRTY;
+      if( wndPtr->parent && wndPtr->window )
+      {
+        WND* 	wnd = wndPtr->parent->child;
+	RECT16  rect;
+	
+        for( ; wnd != wndPtr; wnd = wnd->next )
+           if( wnd->class->style & CS_SAVEBITS &&
+               wnd->dwStyle & WS_VISIBLE &&
+	       IntersectRect16(&rect, &wndPtr->rectClient, &wnd->rectClient) )
+               wnd->flags |= WIN_SAVEUNDER_OVERRIDE;
+      }
 
+      dc->w.flags &= ~DC_DIRTY;
       SelectVisRgn( hdc, hrgnVisible );
-     }
+    }
     else hrgnVisible = CreateRectRgn(0,0,0,0);
 
     if ((flags & DCX_INTERSECTRGN) || (flags & DCX_EXCLUDERGN))
@@ -552,49 +549,67 @@
     return hdc;
 }
 
-/***********************************************************************
- *           GetDC    (USER.66)
- */
-HDC GetDC( HWND hwnd )
-{
-    if( !hwnd ) return GetDCEx( GetDesktopWindow(), 0, DCX_CACHE | DCX_WINDOW );
 
-    return GetDCEx( hwnd, 0, DCX_USESTYLE );
+/***********************************************************************
+ *           GetDC16    (USER.66)
+ */
+HDC16 GetDC16( HWND16 hwnd )
+{
+    return (HDC16)GetDC32( hwnd );
 }
 
 
 /***********************************************************************
- *           GetWindowDC    (USER.67)
+ *           GetDC32    (USER32.229)
  */
-HDC GetWindowDC( HWND hwnd )
+HDC32 GetDC32( HWND32 hwnd )
 {
-    if (hwnd)
-    {
-	WND * wndPtr;
-	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-    }
-    else hwnd = GetDesktopWindow();
-
-    return GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW );
+    if (!hwnd)
+        return GetDCEx32( GetDesktopWindow32(), 0, DCX_CACHE | DCX_WINDOW );
+    return GetDCEx32( hwnd, 0, DCX_USESTYLE );
 }
 
 
 /***********************************************************************
- *           ReleaseDC    (USER.68)
+ *           GetWindowDC16    (USER.67)
  */
-int ReleaseDC( HWND hwnd, HDC hdc )
+HDC16 GetWindowDC16( HWND16 hwnd )
 {
-    HANDLE hdce;
-    DCE * dce = NULL;
+    if (!hwnd) hwnd = GetDesktopWindow16();
+    return GetDCEx16( hwnd, 0, DCX_USESTYLE | DCX_WINDOW );
+}
+
+
+/***********************************************************************
+ *           GetWindowDC32    (USER32.)
+ */
+HDC32 GetWindowDC32( HWND32 hwnd )
+{
+    if (!hwnd) hwnd = GetDesktopWindow32();
+    return GetDCEx32( hwnd, 0, DCX_USESTYLE | DCX_WINDOW );
+}
+
+
+/***********************************************************************
+ *           ReleaseDC16    (USER.68)
+ */
+INT16 ReleaseDC16( HWND16 hwnd, HDC16 hdc )
+{
+    return (INT32)ReleaseDC32( hwnd, hdc );
+}
+
+
+/***********************************************************************
+ *           ReleaseDC32    (USER32.439)
+ */
+INT32 ReleaseDC32( HWND32 hwnd, HDC32 hdc )
+{
+    DCE * dce = firstDCE;
     
     dprintf_dc(stddeb, "ReleaseDC: %04x %04x\n", hwnd, hdc );
         
-    for (hdce = firstDCE; (hdce); hdce = dce->hNext)
-    {
-	if (!(dce = (DCE *) USER_HEAP_LIN_ADDR( hdce ))) return 0;
-	if (dce->hDC == hdc) break;
-    }
-    if (!hdce) return 0;
+    while (dce && (dce->hDC != hdc)) dce = dce->next;
+    if (!dce) return 0;
     if (!(dce->DCXflags & DCX_DCEBUSY) ) return 0;
 
     /* restore previous visible region */
@@ -631,24 +646,18 @@
  */
 BOOL DCHook(HDC hDC, WORD code, DWORD data, DWORD lParam)
 {
-  HANDLE hdce;
-  HRGN hVisRgn;
+    HRGN32 hVisRgn;
+    DCE *dce = firstDCE;;
 
-  dprintf_dc(stddeb,"DCHook: hDC = %04x, %i\n", hDC, code);
+    dprintf_dc(stddeb,"DCHook: hDC = %04x, %i\n", hDC, code);
 
-  if( HIWORD(data) == DC_MAGIC )
-      hdce = (HANDLE)LOWORD(data);
-  else
-      hdce = DCE_FindDCE(hDC);
-
-  if( !hdce ) return 0;
+    while (dce && (dce->hDC != hDC)) dce = dce->next;
+    if (!dce) return 0;
 
   switch( code )
     {
       case DCHC_INVALIDVISRGN:
          {
-           DCE* dce = (DCE*) USER_HEAP_LIN_ADDR(hdce);
-
            if( dce->DCXflags & DCX_DCEBUSY )
  	     {
 	       SetHookFlags(hDC, DCHF_VALIDATEVISRGN);
diff --git a/windows/defwnd.c b/windows/defwnd.c
index e1767ae..7284cd1 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -29,31 +29,6 @@
 static short iF10Key = 0;
 static short iMenuSysKey = 0;
 
-
-/***********************************************************************
- *           DEFWND_InitSysMenuPopup
- *
- * Handle the WM_INITMENUPOPUP message on the system menu.
- */
-static void DEFWND_InitSysMenuPopup( HMENU hmenu, DWORD style, DWORD clsStyle )
-{
-    BOOL gray;
-
-    gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
-    EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
-    gray = ((style & WS_MAXIMIZE) != 0);
-    EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
-    gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
-    EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
-    gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
-    EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
-    gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
-    EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
-    gray = (clsStyle & CS_NOCLOSE) != 0;
-    EnableMenuItem( hmenu, SC_CLOSE, (gray ? MF_GRAYED : MF_ENABLED) );
-}
-
-
 /***********************************************************************
  *           DEFWND_HandleWindowPosChanged
  *
@@ -322,17 +297,10 @@
         ShowWindow( wndPtr->hwndSelf, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
 	break; 
 
-    case WM_INITMENUPOPUP:
-        /* Not absolutely sure this belongs here -- AJ */
-        if (HIWORD(lParam))  /* system menu */
-            DEFWND_InitSysMenuPopup( (HMENU)wParam, wndPtr->dwStyle,
-                                     wndPtr->class->style );
-        break;
-
     case WM_CANCELMODE:
 	/* EndMenu() should be called if in menu state but currently it's
 	   impossible to detect - menu code should be updated*/
-	if (GetCapture() == wndPtr->hwndSelf) ReleaseCapture();
+	if (GetCapture32() == wndPtr->hwndSelf) ReleaseCapture();
 	break;
 
     case WM_VKEYTOITEM:
diff --git a/windows/dialog.c b/windows/dialog.c
index 44511b3..fe31129 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -514,13 +514,12 @@
 	{
 	    TEXTMETRIC16 tm;
 	    HFONT oldFont;
-	    HDC hdc;
 
-	    hdc = GetDC(0);
+	    HDC32 hdc = GetDC32(0);
 	    oldFont = SelectObject( hdc, hFont );
 	    GetTextMetrics16( hdc, &tm );
 	    SelectObject( hdc, oldFont );
-	    ReleaseDC( 0, hdc );
+	    ReleaseDC32( 0, hdc );
 	    xUnit = tm.tmAveCharWidth;
 	    yUnit = tm.tmHeight;
             if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
@@ -744,8 +743,8 @@
 	if (dlgInfo->fEnd) break;
     }
     retval = dlgInfo->msgResult;
-    DestroyWindow( hwnd );
     EnableWindow( owner, TRUE );
+    DestroyWindow( hwnd );
     return retval;
 }
 
@@ -897,7 +896,7 @@
             if (!(dlgCode & DLGC_WANTTAB))
             {
                 SendMessage16( hwndDlg, WM_NEXTDLGCTL,
-                             (GetKeyState(VK_SHIFT) & 0x80), 0 );
+                             (GetKeyState(VK_SHIFT) & 0x8000), 0 );
                 return TRUE;
             }
             break;
diff --git a/windows/event.c b/windows/event.c
index 3759ac0..77532ea 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -22,17 +22,18 @@
 #include "windows.h"
 #include "gdi.h"
 #include "heap.h"
+#include "queue.h"
 #include "win.h"
 #include "class.h"
 #include "clipboard.h"
 #include "debugger.h"
-#include "hook.h"
 #include "message.h"
 #include "module.h"
 #include "options.h"
 #include "queue.h"
 #include "winpos.h"
 #include "registers.h"
+#include "xmalloc.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "dde_proc.h"
@@ -52,8 +53,8 @@
        WPARAM   lastEventChar = 0; /* this will have to be changed once
 				    * ToAscii starts working */
 
-static HWND 	captureWnd = 0;
-static BOOL	InputEnabled = TRUE;
+static HWND32 captureWnd = 0;
+static BOOL32 InputEnabled = TRUE;
 
 /* Keyboard translation tables */
 static const int special_key[] =
@@ -174,17 +175,17 @@
     {
     case KeyPress:
     case KeyRelease:
-        if (!HOOK_GetHook(WH_JOURNALPLAYBACK, 0) )
+        if (InputEnabled)
             EVENT_key( (XKeyEvent*)event );
 	break;
 	
     case ButtonPress:
-        if (!HOOK_GetHook(WH_JOURNALPLAYBACK, 0) )
+        if (InputEnabled)
             EVENT_ButtonPress( (XButtonEvent*)event );
 	break;
 
     case ButtonRelease:
-        if (!HOOK_GetHook(WH_JOURNALPLAYBACK, 0) )
+        if (InputEnabled)
             EVENT_ButtonRelease( (XButtonEvent*)event );
 	break;
 
@@ -197,7 +198,7 @@
 	   problems if the event order is important. I'm not yet seen
 	   of any problems. Jon 7/6/96.
 	 */
-	if (!HOOK_GetHook(WH_JOURNALPLAYBACK, 0) )
+        if (InputEnabled)
 	{
             while (XCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
                                           MotionNotify, event));    
@@ -240,6 +241,7 @@
     case ClientMessage:
 	EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
 	break;
+
 /*  case EnterNotify:
  *       EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
  *       break;
@@ -287,7 +289,7 @@
  * Return TRUE if an event is pending, FALSE on timeout or error
  * (for instance lost connection with the server).
  */
-BOOL32 EVENT_WaitXEvent( BOOL32 sleep )
+BOOL32 EVENT_WaitXEvent( BOOL32 sleep, BOOL32 peek )
 {
     fd_set read_set;
     struct timeval timeout;
@@ -335,6 +337,7 @@
     }
 
     /* Process the event (and possibly others that occurred in the meantime) */
+
     do
     {
 
@@ -346,8 +349,39 @@
         }
 #endif  /* CONFIG_IPC */
 
-        XNextEvent( display, &event );
-        EVENT_ProcessEvent( &event );
+	XNextEvent( display, &event );
+
+        if( peek )
+        {
+	  WND*		pWnd;
+	  MESSAGEQUEUE* pQ;
+  
+          if( XFindContext( display, ((XAnyEvent *)&event)->window, winContext, (char **)&pWnd) 
+	      || event.type == NoExpose )  
+              continue;
+
+	  /* check for the "safe" hardware events */
+
+	  if( event.type == MotionNotify ||
+	      event.type == ButtonPress || event.type == ButtonRelease ||
+	      event.type == KeyPress || event.type == KeyRelease ||
+	      event.type == SelectionRequest || event.type == SelectionClear )
+	  {
+	       EVENT_ProcessEvent( &event );
+               continue;
+	  }
+
+	  if( pWnd )
+            if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
+            {
+              pQ->flags |= QUEUE_FLAG_XEVENT;
+              PostEvent(pQ->hTask);
+	      XPutBackEvent(display, &event);
+              break;
+	    }
+        }
+        else
+          EVENT_ProcessEvent( &event );
     }
     while (XPending( display ));
     return TRUE;
@@ -684,7 +718,7 @@
      * window structure is created. WIN_GetDesktop() check is a hack.
      */
 
-    if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow())
+    if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow32())
     {
         desktopX = event->x;
 	desktopY = event->y;
@@ -694,7 +728,7 @@
         WND *wndPtr;
 	WINDOWPOS16 *winpos;
 	RECT16 newWindowRect, newClientRect;
-        HRGN hrgnOldPos, hrgnNewPos;
+	HRGN hrgnOldPos, hrgnNewPos;
 
 	if (!(wndPtr = WIN_FindWndPtr( hwnd )) ||
 	    !(wndPtr->flags & WIN_MANAGED) )
@@ -702,6 +736,9 @@
 	
         if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
 
+/*	XTranslateCoordinates(display, event->window, rootWindow,
+	    event->x, event->y, &event->x, &event->y, &child);
+            */
 
 	/* Fill WINDOWPOS struct */
 	winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
@@ -764,24 +801,45 @@
     if(event->target == XA_STRING)
     {
 	HANDLE hText;
-	LPSTR text;
+	LPSTR  text;
+	int    size,i,j;
 
         rprop = event->property;
 
 	if(rprop == None) rprop = event->target;
 
         if(event->selection!=XA_PRIMARY) rprop = None;
-        else if(!CLIPBOARD_IsPresent(CF_TEXT)) rprop = None;
-	else{
-            /* Don't worry if we can't open */
-	    BOOL couldOpen=OpenClipboard( pWnd->hwndSelf );
-	    hText=GetClipboardData(CF_TEXT);
-	    text=GlobalLock16(hText);
-	    XChangeProperty(display,request,rprop,XA_STRING,
-		8,PropModeReplace,text,strlen(text));
-	    GlobalUnlock16(hText);
+        else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None;
+	else
+	{
+            /* open to make sure that clipboard is available */
+
+	    BOOL 	couldOpen = OpenClipboard( pWnd->hwndSelf );
+	    char*	lpstr = 0;
+
+	    hText = GetClipboardData(CF_TEXT);
+	    text = GlobalLock16(hText);
+	    size = GlobalSize16(hText);
+
+	    /* remove carriage returns */
+
+	    lpstr = (char*)xmalloc(size--);
+	    for(i=0,j=0; i < size; i++ )
+	    {
+	       if( text[i] == '\r' && text[i+1] == '\n' ) continue;
+	       lpstr[j++] = text[i];
+	       if( text[i] == '\0' ) break;
+	    }
+	    lpstr[j]='\0';
+
+	    XChangeProperty(display, request, rprop, 
+			    XA_STRING, 8, PropModeReplace, 
+			    lpstr, j);
+	    free(lpstr);
+
 	    /* close only if we opened before */
-	    if(couldOpen)CloseClipboard();
+
+	    if(couldOpen) CloseClipboard();
 	}
     }
 
@@ -805,8 +863,11 @@
 static void EVENT_SelectionNotify( XSelectionEvent *event )
 {
     if (event->selection != XA_PRIMARY) return;
+
     if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
-    CLIPBOARD_ReadSelection( event->requestor, event->property );
+    else CLIPBOARD_ReadSelection( event->requestor, event->property );
+
+    dprintf_clipboard(stddeb,"\tSelectionNotify done!\n");
 }
 
 
@@ -816,7 +877,7 @@
 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
 {
     if (event->selection != XA_PRIMARY) return;
-    CLIPBOARD_ReleaseSelection( pWnd->hwndSelf ); 
+    CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf ); 
 }
 
 
@@ -857,6 +918,8 @@
   }
  */ 
 
+extern void FOCUS_SetXFocus( HWND32 );
+
 /**********************************************************************
  *		EVENT_MapNotify
  */
@@ -865,18 +928,28 @@
     HWND32 hwndFocus = GetFocus32();
 
     if (hwndFocus && IsChild( hWnd, hwndFocus ))
-      FOCUS_SetXFocus( hwndFocus );
+      FOCUS_SetXFocus( (HWND32)hwndFocus );
 
     return;
 }
 
+
 /**********************************************************************
- *		SetCapture 	(USER.18)
+ *		SetCapture16   (USER.18)
  */
-HWND SetCapture( HWND hwnd )
+HWND16 SetCapture16( HWND16 hwnd )
+{
+    return (HWND16)SetCapture32( hwnd );
+}
+
+
+/**********************************************************************
+ *		SetCapture32   (USER32.463)
+ */
+HWND32 SetCapture32( HWND32 hwnd )
 {
     Window win;
-    HWND old_capture_wnd = captureWnd;
+    HWND32 old_capture_wnd = captureWnd;
 
     if (!hwnd)
     {
@@ -898,9 +971,9 @@
 
 
 /**********************************************************************
- *		ReleaseCapture	(USER.19)
+ *		ReleaseCapture   (USER.19) (USER32.438)
  */
-void ReleaseCapture()
+void ReleaseCapture(void)
 {
     if (captureWnd == 0) return;
     XUngrabPointer( display, CurrentTime );
@@ -908,10 +981,20 @@
     dprintf_win(stddeb, "ReleaseCapture\n");
 }
 
+
 /**********************************************************************
- *		GetCapture 	(USER.236)
+ *		GetCapture16   (USER.236)
  */
-HWND GetCapture()
+HWND16 GetCapture16(void)
+{
+    return (HWND16)captureWnd;
+}
+
+
+/**********************************************************************
+ *		GetCapture32   (USER32.207)
+ */
+HWND32 GetCapture32(void)
 {
     return captureWnd;
 }
@@ -971,13 +1054,13 @@
 
 
 /**********************************************************************
- *			EnableHardwareInput 		[USER.331]
+ *			EnableHardwareInput   (USER.331)
  */
-BOOL EnableHardwareInput(BOOL bEnable)
+BOOL16 EnableHardwareInput(BOOL16 bEnable)
 {
-  BOOL bOldState = InputEnabled;
-  dprintf_event(stdnimp,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
+  BOOL16 bOldState = InputEnabled;
+  dprintf_event(stdnimp,"EnableHardwareInput(%d);\n", bEnable);
   InputEnabled = bEnable;
-  return (bOldState && !bEnable);
+  return bOldState;
 }
 
diff --git a/windows/graphics.c b/windows/graphics.c
index e64aa2f..aca1f6c 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -12,6 +12,7 @@
 #ifndef PI
 #define PI M_PI
 #endif
+#include "graphics.h"
 #include "dc.h"
 #include "bitmap.h"
 #include "callback.h"
@@ -279,6 +280,7 @@
  */
 BOOL Rectangle( HDC hdc, INT left, INT top, INT right, INT bottom )
 {
+    INT32 width;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) 
     {
@@ -305,21 +307,24 @@
 		  dc->w.DCOrgY + bottom);
 	return TRUE;
     }
-    
+    width = dc->u.x.pen.width;
+    if (!width) width = 1;
+    if(dc->u.x.pen.style == PS_NULL) width = 0;
+
     if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
-        (dc->u.x.pen.width < right-left) &&
-        (dc->u.x.pen.width < bottom-top))
+        (width < right-left) && (width < bottom-top))
     {
-        left   += dc->u.x.pen.width / 2;
-        right  -= (dc->u.x.pen.width + 1) / 2;
-        top    += dc->u.x.pen.width / 2;
-        bottom -= (dc->u.x.pen.width + 1) / 2;
+        left   += width / 2;
+        right  -= (width + 1) / 2;
+        top    += width / 2;
+        bottom -= (width + 1) / 2;
     }
 
     if (DC_SetupGCForBrush( dc ))
 	XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
-		        right-left, bottom-top );
+		        dc->w.DCOrgX + left + (width + 1) / 2,
+		        dc->w.DCOrgY + top + (width + 1) / 2,
+		        right-left-width-1, bottom-top-width-1);
     if (DC_SetupGCForPen( dc ))
 	XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
 		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
@@ -745,8 +750,8 @@
  * Short-cut function to blit a bitmap into a device.
  * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
  */
-BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
-		       int xsrc, int ysrc, int width, int height )
+BOOL32 GRAPH_DrawBitmap( HDC32 hdc, HBITMAP32 hbitmap, int xdest, int ydest,
+                         int xsrc, int ysrc, int width, int height )
 {
     BITMAPOBJ *bmp;
     DC *dc;
@@ -778,8 +783,8 @@
 /**********************************************************************
  *          GRAPH_DrawReliefRect  (Not a MSWin Call)
  */
-void GRAPH_DrawReliefRect( HDC hdc, RECT16 *rect, int highlight_size,
-                           int shadow_size, BOOL pressed )
+void GRAPH_DrawReliefRect( HDC32 hdc, const RECT32 *rect, INT32 highlight_size,
+                           INT32 shadow_size, BOOL32 pressed )
 {
     HBRUSH hbrushOld;
     int i;
diff --git a/windows/hook.c b/windows/hook.c
index 6f9f09a..ce58107 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -37,7 +37,7 @@
     if (data->next) return data->next;
     if (!data->ownerQueue) return 0;  /* Already system hook */
     /* Now start enumerating the system hooks */
-    return HOOK_systemHooks[data->id - WH_FIRST_HOOK];
+    return HOOK_systemHooks[data->id - WH_MINHOOK];
 }
 
 
@@ -52,8 +52,8 @@
     HANDLE16 hook = 0;
 
     if ((queue = (MESSAGEQUEUE *)GlobalLock16( hQueue )) != NULL)
-        hook = queue->hooks[id - WH_FIRST_HOOK];
-    if (!hook) hook = HOOK_systemHooks[id - WH_FIRST_HOOK];
+        hook = queue->hooks[id - WH_MINHOOK];
+    if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
     return hook;
 }
 
@@ -70,7 +70,7 @@
     HANDLE16 handle;
     HQUEUE16 hQueue = 0;
 
-    if ((id < WH_FIRST_HOOK) || (id > WH_LAST_HOOK)) return 0;
+    if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
     if (!(hInst = GetExePtr( hInst ))) return 0;
 
     dprintf_hook( stddeb, "Setting hook %d: %08x %04x %04x\n",
@@ -83,12 +83,19 @@
         if (!(hQueue = GetTaskQueue( hTask ))) return 0;
     }
 
-    if (id == WH_CBT || id == WH_DEBUG || id == WH_SHELL)
+    if (id == WH_DEBUG)
     {
-	fprintf( stdnimp, "Unimplemented hook set: (%d,%08lx,%04x,%04x)!\n",
-                 id, (DWORD)proc, hInst, hTask );
+        fprintf( stdnimp,"WH_DEBUG is broken in 16-bit Windows.\n");
+        return 0;
+    }
+    else if (id == WH_CBT || id == WH_SHELL)
+    {
+	fprintf( stdnimp, "Half-implemented hook set: (%s,%08lx,%04x,%04x)!\n",
+                 (id==WH_CBT)?"WH_CBT":"WH_SHELL", (DWORD)proc, hInst, hTask );
     }
 
+    if (id == WH_JOURNALPLAYBACK) EnableHardwareInput(FALSE);
+     
     /* Create the hook structure */
 
     if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
@@ -105,13 +112,13 @@
     if (hQueue)
     {
         MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
-        data->next = queue->hooks[id - WH_FIRST_HOOK];
-        queue->hooks[id - WH_FIRST_HOOK] = handle;
+        data->next = queue->hooks[id - WH_MINHOOK];
+        queue->hooks[id - WH_MINHOOK] = handle;
     }
     else
     {
-        data->next = HOOK_systemHooks[id - WH_FIRST_HOOK];
-        HOOK_systemHooks[id - WH_FIRST_HOOK] = handle;
+        data->next = HOOK_systemHooks[id - WH_MINHOOK];
+        HOOK_systemHooks[id - WH_MINHOOK] = handle;
     }
     return handle;
 }
@@ -138,15 +145,17 @@
         return TRUE;
     }
 
+    if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput(TRUE);
+     
     /* Remove it from the linked list */
 
     if (data->ownerQueue)
     {
         MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( data->ownerQueue );
         if (!queue) return FALSE;
-        prevHook = &queue->hooks[data->id - WH_FIRST_HOOK];
+        prevHook = &queue->hooks[data->id - WH_MINHOOK];
     }
-    else prevHook = &HOOK_systemHooks[data->id - WH_FIRST_HOOK];
+    else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
 
     while (*prevHook && *prevHook != hook)
         prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
@@ -224,9 +233,9 @@
   HHOOK         hook, next;
   int           id;
 
-  for( id = WH_FIRST_HOOK; id <= WH_LAST_HOOK; id++ )
+  for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
     {
-       hook = HOOK_systemHooks[id - WH_FIRST_HOOK];
+       hook = HOOK_systemHooks[id - WH_MINHOOK];
        while( hook )
           if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
 	    {
@@ -253,7 +262,7 @@
   HHOOK 	hook, next;
   int 		id;
 
-  for( id = WH_FIRST_HOOK; id <= WH_LAST_HOOK; id++ )
+  for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
     {
        hook = HOOK_GetHook( id, hQueue );
        while( hook )
@@ -277,15 +286,10 @@
 FARPROC16 SetWindowsHook( INT16 id, HOOKPROC16 proc )
 {
     HINSTANCE16 hInst = __winelib ? 0 : FarGetOwner( HIWORD(proc) );
-    /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
-    HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
+    HTASK16 	hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
+    HANDLE16 	handle = HOOK_SetHook( id, proc, hInst, hTask );
 
-    HANDLE16 handle = HOOK_SetHook( id, proc, hInst, hTask );
-    if (!handle) return (FARPROC16)-1;
-    if (!((HOOKDATA *)USER_HEAP_LIN_ADDR( handle ))->next) return 0;
-    /* Not sure if the return value is correct; should not matter much
-     * since it's never used (see DefHookProc). -- AJ */
-    return (FARPROC16)MAKELONG( handle, HOOK_MAGIC );
+    return (handle) ? (FARPROC16)MAKELONG( handle, HOOK_MAGIC ) : NULL;
 }
 
 
@@ -343,7 +347,7 @@
                         HTASK16 hTask )
 {
     HANDLE16 handle = HOOK_SetHook( id, proc, hInst, hTask );
-    return MAKELONG( handle, HOOK_MAGIC );
+    return (handle) ? MAKELONG( handle, HOOK_MAGIC ) : NULL;
 }
 
 
diff --git a/windows/keyboard.c b/windows/keyboard.c
index ac6cc0f..ccc815b 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -64,7 +64,7 @@
  *            GetAsyncKeyState        (USER.249)
  *
  *	Determine if a key is or was pressed.  retval has high-order 
- * byte set to 1 if currently pressed, low-order byte 1 if key has
+ * bit set to 1 if currently pressed, low-order bit set to 1 if key has
  * been pressed.
  *
  *	This uses the variable AsyncMouseButtonsStates and
@@ -92,7 +92,7 @@
 	break;
      default:
 	retval = AsyncKeyStateTable[nKey] | 
-	(KeyStateTable[nKey] << 8);
+	(KeyStateTable[nKey] ? 0x8000 : 0);
 	break;
     }
 
diff --git a/windows/mdi.c b/windows/mdi.c
index 19b40a6..40b0d4d 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -406,7 +406,8 @@
 
  MapWindowPoints16(clientWnd->parent->hwndSelf, 
 	       ((MDICLIENTINFO*)clientWnd->wExtra)->self, (LPPOINT16)&rect, 2);
- AdjustWindowRectEx16( &rect, childWnd->dwStyle, 0, childWnd->dwExStyle );
+ AdjustWindowRectEx16( &rect, childWnd->dwStyle & ~(WS_VSCROLL | WS_HSCROLL),
+		      0, childWnd->dwExStyle );
 
  lpMinMax->ptMaxSize.x = rect.right -= rect.left;
  lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
@@ -539,6 +540,7 @@
     /* deactivate prev. active child */
     if( wndPrev )
     {
+	wndPrev->dwStyle |= WS_SYSMENU;
 	SendMessage16( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L );
 
 #ifdef WINELIB32
@@ -869,8 +871,6 @@
  EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
  EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
 
- child->dwStyle &= ~WS_SYSMENU;
-
  /* redraw menu */
  DrawMenuBar(frame->hwndSelf);
 
@@ -882,7 +882,6 @@
  */
 BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild)
 {
- WND*   child    = WIN_FindWndPtr(hChild);
  INT	nItems   = GetMenuItemCount(frameWnd->wIDmenu) - 1;
 
  dprintf_mdi(stddeb,"MDI_RestoreFrameMenu: for child %04x\n",hChild);
@@ -890,7 +889,6 @@
  if( GetMenuItemID(frameWnd->wIDmenu,nItems) != SC_RESTORE )
      return 0; 
 
- child->dwStyle |= WS_SYSMENU;
 
  RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
  DeleteMenu(frameWnd->wIDmenu,nItems-1,MF_BYPOSITION);
@@ -1079,7 +1077,7 @@
 	
       case WM_MDITILE:
 	ci->sbNeedUpdate = TRUE;
-	ShowScrollBar(hwnd,SB_BOTH,FALSE);
+	ShowScrollBar32(hwnd,SB_BOTH,FALSE);
 	MDITile(w, ci,wParam);
         ci->sbNeedUpdate = FALSE;
         return 0;
@@ -1366,10 +1364,15 @@
 		case SC_MOVE:
 		     if( ci->hwndChildMaximized == hwnd) return 0;
 		     break;
+	        case SC_RESTORE:
+	        case SC_MINIMIZE:
+		     WIN_FindWndPtr(hwnd)->dwStyle |= WS_SYSMENU;
+		     break;
 		case SC_MAXIMIZE:
 		     if( ci->hwndChildMaximized == hwnd) 
 			 return SendMessage16( clientWnd->parent->hwndSelf,
                                              message, wParam, lParam);
+		     WIN_FindWndPtr(hwnd)->dwStyle &= ~WS_SYSMENU;
 		     break;
 		case SC_NEXTWINDOW:
 		     SendMessage16( ci->self, WM_MDINEXT, 0, 0);
@@ -1627,15 +1630,15 @@
     vpos = clientRect.top - childRect.top;
 
     if( noscroll )
-	ShowScrollBar(hwnd, SB_BOTH, FALSE);
+	ShowScrollBar32(hwnd, SB_BOTH, FALSE);
     else
     switch( scroll )
       {
 	case SB_HORZ:
 			vpos = hpos; vmin = hmin; vmax = hmax;
 	case SB_VERT:
-			SetScrollPos(hwnd, scroll, vpos, FALSE);
-			SetScrollRange(hwnd, scroll, vmin, vmax, TRUE);
+			SetScrollPos32(hwnd, scroll, vpos, FALSE);
+			SetScrollRange32(hwnd, scroll, vmin, vmax, TRUE);
 			break;
 	case SB_BOTH:
 			SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
@@ -1654,23 +1657,23 @@
  short 	 newPos=-1;
  short 	 curPos;
  short 	 length;
- INT16 	 minPos;
- INT16 	 maxPos;
+ INT32 	 minPos;
+ INT32 	 maxPos;
  short   shift;
 
  if( !wndPtr ) return;
 
  if( uMsg == WM_HSCROLL )
    {
-     GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
-     curPos = GetScrollPos(hWnd,SB_HORZ);
+     GetScrollRange32(hWnd,SB_HORZ,&minPos,&maxPos);
+     curPos = GetScrollPos32(hWnd,SB_HORZ);
      length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
      shift = SYSMETRICS_CYHSCROLL;
    }
  else if( uMsg == WM_VSCROLL )
 	{
-	  GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
-	  curPos = GetScrollPos(hWnd,SB_VERT);
+	  GetScrollRange32(hWnd,SB_VERT,&minPos,&maxPos);
+	  curPos = GetScrollPos32(hWnd,SB_VERT);
 	  length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
 	  shift = SYSMETRICS_CXVSCROLL;
 	}
@@ -1714,7 +1717,7 @@
  else if( newPos < minPos )
 	  newPos = minPos;
 
- SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
+ SetScrollPos32(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
 
  if( uMsg == WM_VSCROLL )
      ScrollWindow(hWnd ,0 ,curPos - newPos, NULL, NULL);
diff --git a/windows/message.c b/windows/message.c
index 5dd9fae..2f9cae1 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -34,15 +34,21 @@
 
 #define ASCII_CHAR_HACK 0x0800 
 
+typedef enum { SYSQ_MSG_ABANDON, SYSQ_MSG_SKIP, SYSQ_MSG_ACCEPT } SYSQ_STATUS;
+
 extern WPARAM	lastEventChar;				 /* event.c */
 extern BOOL MouseButtonsStates[3];
 extern BOOL AsyncMouseButtonsStates[3];
 extern BYTE KeyStateTable[256];
 extern BYTE AsyncKeyStateTable[256];
 
+extern MESSAGEQUEUE *pCursorQueue;			 /* queue.c */
+extern MESSAGEQUEUE *pActiveQueue;
+
 DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
 
 static WORD doubleClickSpeed = 452;
+static INT32 debugSMRL = 0;       /* intertask SendMessage() recursion level */
 
 /***********************************************************************
  *           MSG_TranslateMouseMsg
@@ -59,7 +65,7 @@
  *   the coordinates to client coordinates.
  * - Send the WM_SETCURSOR message.
  */
-static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
+static SYSQ_STATUS MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
 {
     WND *pWnd;
     BOOL eatMsg = FALSE;
@@ -70,6 +76,7 @@
     static WORD  lastClickMsg = 0;
     static POINT16 lastClickPos = { 0, 0 };
     POINT16 pt = msg->pt;
+    MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16(GetTaskQueue(0));
 
     BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
 		       (msg->message == WM_RBUTTONDOWN) ||
@@ -77,7 +84,7 @@
 
       /* Find the window */
 
-    if ((msg->hwnd = GetCapture()) != 0)
+    if ((msg->hwnd = GetCapture16()) != 0)
     {
         BOOL32 ret;
 
@@ -87,7 +94,7 @@
 
         if (!HOOK_GetHook( WH_MOUSE, GetTaskQueue(0)) ||
             !(hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16)))
-            return TRUE;
+            return SYSQ_MSG_ACCEPT;
         hook->pt           = msg->pt;
         hook->hwnd         = msg->hwnd;
         hook->wHitTestCode = HTCLIENT;
@@ -95,21 +102,22 @@
         ret = !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
                                msg->message, (LPARAM)SEGPTR_GET(hook));
         SEGPTR_FREE(hook);
-        return ret;
+        return ret ? SYSQ_MSG_ACCEPT : SYSQ_MSG_SKIP ;
     }
    
     hittest = WINPOS_WindowFromPoint( msg->pt, &pWnd );
     if (pWnd->hmemTaskQ != GetTaskQueue(0))
     {
         /* Not for the current task */
-        MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) );
         if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
         /* Wake up the other task */
         queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
         if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
-        return FALSE;
+        return SYSQ_MSG_ABANDON;
     }
-    msg->hwnd = pWnd->hwndSelf;
+    pCursorQueue = queue;
+    msg->hwnd    = pWnd->hwndSelf;
+
     if ((hittest != HTERROR) && mouseClick)
     {
         HWND hwndTop = WIN_GetTopParent( msg->hwnd );
@@ -121,7 +129,8 @@
 
         /* Activate the window if needed */
 
-        if (msg->hwnd != GetActiveWindow() && msg->hwnd != GetDesktopWindow())
+        if (msg->hwnd != GetActiveWindow() &&
+            msg->hwnd != GetDesktopWindow16())
         {
             LONG ret = SendMessage16( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
                                     MAKELONG( hittest, msg->message ) );
@@ -139,7 +148,7 @@
 
     SendMessage16( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd,
                    MAKELONG( hittest, msg->message ));
-    if (eatMsg) return FALSE;
+    if (eatMsg) return SYSQ_MSG_SKIP;
 
       /* Check for double-click */
 
@@ -189,7 +198,7 @@
 
     if (!HOOK_GetHook( WH_MOUSE, GetTaskQueue(0)) ||
         !(hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16)))
-        return TRUE;
+        return SYSQ_MSG_ACCEPT;
 
     hook->pt           = msg->pt;
     hook->hwnd         = msg->hwnd;
@@ -198,7 +207,7 @@
     ret = !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
                            msg->message, (LPARAM)SEGPTR_GET(hook) );
     SEGPTR_FREE(hook);
-    return ret;
+    return ret ? SYSQ_MSG_ACCEPT : SYSQ_MSG_SKIP;
 }
 
 
@@ -209,7 +218,7 @@
  * Return value indicates whether the translated message must be passed
  * to the user.
  */
-static BOOL MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
+static SYSQ_STATUS MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
 {
     WND *pWnd;
 
@@ -235,12 +244,14 @@
         /* Wake up the other task */
         queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
         if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
-        return FALSE;
+        return SYSQ_MSG_ABANDON;
     }
-    return !HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
-                            msg->wParam, msg->lParam );
+    return (HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
+                            msg->wParam, msg->lParam ))
+            ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT;
 }
 
+
 /***********************************************************************
  *           MSG_JournalRecordMsg
  *
@@ -392,26 +403,30 @@
 static BOOL MSG_PeekHardwareMsg( MSG16 *msg, HWND hwnd, WORD first, WORD last,
                                  BOOL remove )
 {
+    SYSQ_STATUS status;
     MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
     int i, pos = sysMsgQueue->nextMessage;
 
     /* If the queue is empty, attempt to fill it */
-    if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( FALSE );
+    if (!sysMsgQueue->msgCount && XPending(display))
+        EVENT_WaitXEvent( FALSE, FALSE );
 
     for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
     {
         if (pos >= sysMsgQueue->queueSize) pos = 0;
 	*msg = sysMsgQueue->messages[pos].msg;
 
-          /* Translate message */
+          /* Translate message; return FALSE immediately on SYSQ_MSG_ABANDON */
 
         if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
         {
-            if (!MSG_TranslateMouseMsg( msg, remove )) continue;
+            if ((status = MSG_TranslateMouseMsg(msg,remove)) == SYSQ_MSG_ABANDON)
+                return FALSE;
         }
         else if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
         {
-            if (!MSG_TranslateKeyboardMsg( msg, remove )) continue;
+            if ((status = MSG_TranslateKeyboardMsg(msg,remove)) == SYSQ_MSG_ABANDON)
+                return FALSE;
         }
         else  /* Non-standard hardware event */
         {
@@ -427,21 +442,28 @@
                                       remove ? HC_ACTION : HC_NOREMOVE,
                                       0, (LPARAM)SEGPTR_GET(hook) );
                 SEGPTR_FREE(hook);
-                if (ret) continue;
+                status = ret ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT;
             }
         }
 
+        if (status == SYSQ_MSG_SKIP)
+        {
+            if (remove) QUEUE_RemoveMsg( sysMsgQueue, pos );
+            /* FIXME: call CBT_CLICKSKIPPED from here */
+            continue;
+        }
+
           /* Check message against filters */
 
         if (hwnd && (msg->hwnd != hwnd)) continue;
         if ((first || last) && 
             ((msg->message < first) || (msg->message > last))) continue;
-        if ((msg->hwnd != GetDesktopWindow()) && 
-            (GetWindowTask16(msg->hwnd) != GetCurrentTask()))
-            continue;  /* Not for this task */
-        if (remove && HOOK_GetHook( WH_JOURNALRECORD, GetTaskQueue(0) ))
-            MSG_JournalRecordMsg( msg );
-        if (remove) QUEUE_RemoveMsg( sysMsgQueue, pos );
+        if (remove)
+        {
+            if (HOOK_GetHook( WH_JOURNALRECORD, GetTaskQueue(0) ))
+                MSG_JournalRecordMsg( msg );
+            QUEUE_RemoveMsg( sysMsgQueue, pos );
+        }
         return TRUE;
     }
     return FALSE;
@@ -474,43 +496,71 @@
 static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
                                 WPARAM wParam, LPARAM lParam )
 {
+    INT32	  prevSMRL = debugSMRL;
+    QSMCTRL 	  qCtrl = { 0, 1};
     MESSAGEQUEUE *queue, *destQ;
 
     if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return 0;
     if (!(destQ = (MESSAGEQUEUE*)GlobalLock16( hDestQueue ))) return 0;
 
-    if (IsTaskLocked())
+    if (IsTaskLocked() || !IsWindow(hwnd)) return 0;
+
+    debugSMRL+=4;
+    dprintf_sendmsg(stddeb,"%*sSM: %s [%04x] (%04x -> %04x)\n", 
+		    prevSMRL, "", SPY_GetMsgName(msg), msg, queue->self, hDestQueue );
+
+    if( !(queue->wakeBits & QS_SMPARAMSFREE) )
     {
-        fprintf( stderr, "SendMessage: task is locked\n" );
-        return 0;
+      dprintf_sendmsg(stddeb,"\tIntertask SendMessage: sleeping since unreplied SendMessage pending\n");
+      queue->changeBits &= ~QS_SMPARAMSFREE;
+      QUEUE_WaitBits( QS_SMPARAMSFREE );
     }
 
-    if (queue->hWnd)
-    {
-        fprintf( stderr, "Nested SendMessage(), msg %04x skipped\n", msg );
-        return 0;
-    }
+    /* resume sending */ 
+
     queue->hWnd   = hwnd;
     queue->msg    = msg;
     queue->wParam = wParam;
     queue->lParam = lParam;
     queue->hPrevSendingTask = destQ->hSendingTask;
     destQ->hSendingTask = GetTaskQueue(0);
+
+    queue->wakeBits &= ~QS_SMPARAMSFREE;
+
+    dprintf_sendmsg(stddeb,"%*ssm: smResultInit = %08x\n", prevSMRL, "", (unsigned)&qCtrl);
+
+    queue->smResultInit = &qCtrl;
+
     QUEUE_SetWakeBit( destQ, QS_SENDMESSAGE );
 
-    /* Wait for the result */
+    /* perform task switch and wait for the result */
 
-    printf( "SendMessage %04x to %04x\n", msg, hDestQueue );
-
-    if (!(queue->wakeBits & QS_SMRESULT))
+    while( qCtrl.bPending )
     {
+      if (!(queue->wakeBits & QS_SMRESULT))
+      {
+        queue->changeBits &= ~QS_SMRESULT;
         DirectedYield( destQ->hTask );
         QUEUE_WaitBits( QS_SMRESULT );
+	dprintf_sendmsg(stddeb,"\tsm: have result!\n");
+      }
+      /* got something */
+
+      dprintf_sendmsg(stddeb,"%*ssm: smResult = %08x\n", prevSMRL, "", (unsigned)queue->smResult );
+
+      queue->smResult->lResult = queue->SendMessageReturn;
+      queue->smResult->bPending = FALSE;
+      queue->wakeBits &= ~QS_SMRESULT;
+
+      if( queue->smResult != &qCtrl )
+	  dprintf_msg(stddeb,"%*ssm: weird scenes inside the goldmine!\n", prevSMRL, "");
     }
-    printf( "SendMessage %04x to %04x: got %08lx\n",
-            msg, hDestQueue, queue->SendMessageReturn );
-    queue->wakeBits &= ~QS_SMRESULT;
-    return queue->SendMessageReturn;
+    queue->smResultInit = NULL;
+    
+    dprintf_sendmsg(stddeb,"%*sSM: [%04x] returning %08lx\n", prevSMRL, "", msg, qCtrl.lResult);
+    debugSMRL-=4;
+
+    return qCtrl.lResult;
 }
 
 
@@ -522,19 +572,33 @@
     MESSAGEQUEUE *senderQ;
     MESSAGEQUEUE *queue;
 
-    printf( "ReplyMessage\n " );
     if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return;
-    if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
-        return;
-    for (;;)
+
+    dprintf_msg(stddeb,"ReplyMessage, queue %04x\n", queue->self);
+
+    while( (senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
     {
-        if (queue->wakeBits & QS_SENDMESSAGE) QUEUE_ReceiveMessage( queue );
-        else if (senderQ->wakeBits & QS_SMRESULT) Yield();
-        else break;
-    }
-    printf( "ReplyMessage: res = %08lx\n", result );
+      dprintf_msg(stddeb,"\trpm: replying to %04x (%04x -> %04x)\n",
+                          queue->msg, queue->self, senderQ->self);
+
+      if( queue->wakeBits & QS_SENDMESSAGE )
+      {
+	QUEUE_ReceiveMessage( queue );
+	continue; /* ReceiveMessage() already called us */
+      }
+
+      if(!(senderQ->wakeBits & QS_SMRESULT) ) break;
+      OldYield();
+    } 
+    if( !senderQ ) { dprintf_msg(stddeb,"\trpm: done\n"); return; }
+
     senderQ->SendMessageReturn = result;
+    dprintf_msg(stddeb,"\trpm: smResult = %08x, result = %08lx\n", 
+			(unsigned)queue->smResultCurrent, result );
+
+    senderQ->smResult = queue->smResultCurrent;
     queue->InSendMessageHandle = 0;
+
     QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
     DirectedYield( queue->hSendingTask );
 }
@@ -582,6 +646,23 @@
 
 	if (msgQueue->wakeBits & QS_SENDMESSAGE)
             QUEUE_ReceiveMessage( msgQueue );
+
+        /* Now handle a WM_QUIT message 
+	 *
+	 * FIXME: PostQuitMessage() should post WM_QUIT and 
+	 *	  set QS_POSTMESSAGE wakebit instead of this.
+	 */
+
+        if (msgQueue->wPostQMsg &&
+	   (!first || WM_QUIT >= first) && 
+	   (!last || WM_QUIT <= last) )
+        {
+            msg->hwnd    = hwnd;
+            msg->message = WM_QUIT;
+            msg->wParam  = msgQueue->wExitCode;
+            msg->lParam  = 0;
+            break;
+        }
     
         /* Now find a normal message */
 
@@ -612,17 +693,6 @@
             break;
         }
 
-        /* Now handle a WM_QUIT message */
-
-	if (msgQueue->wPostQMsg)
-	{
-	    msg->hwnd    = hwnd;
-	    msg->message = WM_QUIT;
-	    msg->wParam  = msgQueue->wExitCode;
-	    msg->lParam  = 0;
-	    break;
-	}
-
         /* Check again for SendMessage */
 
  	if (msgQueue->wakeBits & QS_SENDMESSAGE)
diff --git a/windows/msgbox.c b/windows/msgbox.c
index f019d41..693ccba 100644
--- a/windows/msgbox.c
+++ b/windows/msgbox.c
@@ -23,7 +23,7 @@
   LPMSGBOX lpmb;
   RECT16 rect, textrect;
   HWND hItem;
-  HDC hdc;
+  HDC32 hdc;
   LONG lRet;
   int i, buttons, bwidth, bheight, theight, wwidth, bpos;
   int borheight, iheight, tiheight;
@@ -111,12 +111,12 @@
     MapWindowPoints16(0, hwnd, (LPPOINT16)&textrect, 2);
     
     GetClientRect16(hItem, &rect);
-    hdc = GetDC(hItem);
+    hdc = GetDC32(hItem);
     lRet = DrawText16( hdc, lpmb->text, -1, &rect,
                        DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_CALCRECT);
     theight = rect.bottom  - rect.top;
     tiheight = 16 + MAX(iheight, theight);
-    ReleaseDC(hItem, hdc);
+    ReleaseDC32(hItem, hdc);
     
     /* Position the text */
     SetWindowPos(hItem, 0, textrect.left, (tiheight - theight) / 2, 
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 64de6c0..fe3148d 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -15,6 +15,7 @@
 #include "syscolor.h"
 #include "menu.h"
 #include "winpos.h"
+#include "hook.h"
 #include "scroll.h"
 #include "nonclient.h"
 #include "graphics.h"
@@ -63,8 +64,6 @@
  */
 static void NC_AdjustRect(LPRECT16 rect, DWORD style, BOOL menu, DWORD exStyle)
 {
-    if (style & WS_ICONIC) return;  /* Nothing to change for an icon */
-
     /* Decide if the window will be managed (see CreateWindowEx) */
     if (!(Options.managed && !(style & WS_CHILD) &&
           ((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
@@ -233,6 +232,10 @@
 LONG NC_HandleNCCalcSize( WND *pWnd, RECT16 *winRect )
 {
     RECT16 tmpRect = { 0, 0, 0, 0 };
+    LONG result = 0;
+
+    if (pWnd->class->style & CS_VREDRAW) result |= WVR_VREDRAW;
+    if (pWnd->class->style & CS_HREDRAW) result |= WVR_HREDRAW;
 
     if( !( pWnd->dwStyle & WS_MINIMIZE ) )
     {
@@ -249,7 +252,7 @@
                                               -tmpRect.left, -tmpRect.top ) + 1;
       }
     }
-    return 0;
+    return result;
 }
 
 
@@ -668,7 +671,7 @@
  */
 void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
 {
-    HDC 	hdc;
+    HDC32 hdc;
     RECT16 rect;
     BOOL	active;
 
@@ -681,7 +684,7 @@
 
     dprintf_nonclient(stddeb, "NC_DoNCPaint: %04x %d\n", hwnd, active );
 
-    if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
+    if (!(hdc = GetDCEx32( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
 
     if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
 		        wndPtr->rectClient.top-wndPtr->rectWindow.top,
@@ -689,7 +692,7 @@
 		        wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
 	== NULLREGION)
     {
-	ReleaseDC( hwnd, hdc );
+	ReleaseDC32( hwnd, hdc );
 	return;
     }
 
@@ -735,8 +738,10 @@
 
       /* Draw the scroll-bars */
 
-    if (wndPtr->dwStyle & WS_VSCROLL) SCROLL_DrawScrollBar(hwnd, hdc, SB_VERT);
-    if (wndPtr->dwStyle & WS_HSCROLL) SCROLL_DrawScrollBar(hwnd, hdc, SB_HORZ);
+    if (wndPtr->dwStyle & WS_VSCROLL)
+        SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE );
+    if (wndPtr->dwStyle & WS_HSCROLL)
+        SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE );
 
       /* Draw the "size-box" */
 
@@ -748,7 +753,7 @@
         FillRect16( hdc, &r, sysColorObjects.hbrushScrollbar );
     }    
 
-    ReleaseDC( hwnd, hdc );
+    ReleaseDC32( hwnd, hdc );
 }
 
 
@@ -870,7 +875,8 @@
     RECT16 rect;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     int iconic = wndPtr->dwStyle & WS_MINIMIZE;
-
+    HMENU hmenu;
+    
     if (!(wndPtr->dwStyle & WS_SYSMENU)) return;
 
     /* If window has a menu, track the menu bar normally if it not minimized */
@@ -881,7 +887,10 @@
 
 	NC_GetSysPopupPos( wndPtr, &rect );
 	if (!iconic) NC_DrawSysButton( hwnd, hdc, TRUE );
-	TrackPopupMenu16( GetSystemMenu(hwnd, 0), TPM_LEFTALIGN | TPM_LEFTBUTTON,
+	hmenu = GetSystemMenu(hwnd, 0);
+	MENU_InitSysMenuPopup(hmenu, wndPtr->dwStyle,
+				    wndPtr->class->style);
+	TrackPopupMenu16( hmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
                           rect.left, rect.bottom, 0, hwnd, &rect );
 	if (!iconic) NC_DrawSysButton( hwnd, hdc, FALSE );
     }
@@ -920,7 +929,7 @@
     }
     else  /* SC_SIZE */
     {
-	SetCapture(hwnd);
+	SetCapture32(hwnd);
 	while(!hittest)
 	{
             MSG_InternalGetMessage( &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE );
@@ -982,7 +991,7 @@
     MSG16 msg;
     LONG hittest;
     RECT16 sizingRect, mouseRect;
-    HDC hdc;
+    HDC32 hdc;
     BOOL thickframe;
     POINT16 minTrack, maxTrack, capturePoint = pt;
     WND * wndPtr = WIN_FindWndPtr( hwnd );
@@ -1005,7 +1014,7 @@
 	if (hittest) hittest += HTLEFT-1;
 	else
 	{
-	    SetCapture(hwnd);
+	    SetCapture32(hwnd);
 	    hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
 	    if (!hittest)
 	    {
@@ -1044,16 +1053,16 @@
     }
     SendMessage16( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
 
-    if (GetCapture() != hwnd) SetCapture( hwnd );    
+    if (GetCapture32() != hwnd) SetCapture32( hwnd );    
 
     if (wndPtr->dwStyle & WS_CHILD)
     {
           /* Retrieve a default cache DC (without using the window style) */
-        hdc = GetDCEx( wndPtr->parent->hwndSelf, 0, DCX_CACHE );
+        hdc = GetDCEx32( wndPtr->parent->hwndSelf, 0, DCX_CACHE );
     }
     else
     {  /* Grab the server only when moving top-level windows without desktop */
-	hdc = GetDC( 0 );
+	hdc = GetDC32( 0 );
 	if (rootWindow == DefaultRootWindow(display)) XGrabServer( display );
     }
     NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
@@ -1116,12 +1125,28 @@
     NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
     ReleaseCapture();
 
-    if (wndPtr->dwStyle & WS_CHILD) ReleaseDC( wndPtr->parent->hwndSelf, hdc );
+    if (wndPtr->dwStyle & WS_CHILD)
+        ReleaseDC32( wndPtr->parent->hwndSelf, hdc );
     else
     {
-	ReleaseDC( 0, hdc );
+	ReleaseDC32( 0, hdc );
 	if (rootWindow == DefaultRootWindow(display)) XUngrabServer( display );
     }
+
+    if (HOOK_GetHook( WH_CBT, GetTaskQueue(0) ))
+    {
+       RECT16* pr = SEGPTR_NEW(RECT16);
+       if( pr )
+       {
+	 *pr = sizingRect;
+	  if( HOOK_CallHooks( WH_CBT, HCBT_MOVESIZE, hwnd,
+			             (LPARAM)SEGPTR_GET(pr)) )
+	      sizingRect = wndPtr->rectWindow;
+	  else
+	      sizingRect = *pr;
+	  SEGPTR_FREE(pr);
+       }
+    }
     SendMessage16( hwnd, WM_EXITSIZEMOVE, 0, 0 );
     SendMessage16( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
 
@@ -1154,10 +1179,10 @@
 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
 {
     MSG16 msg;
-    HDC hdc = GetWindowDC( hwnd );
+    HDC32 hdc = GetWindowDC32( hwnd );
     BOOL pressed = TRUE;
 
-    SetCapture( hwnd );
+    SetCapture32( hwnd );
     if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, TRUE );
     else NC_DrawMaxButton( hwnd, hdc, TRUE );
 
@@ -1178,7 +1203,7 @@
     else NC_DrawMaxButton( hwnd, hdc, FALSE );
 
     ReleaseCapture();
-    ReleaseDC( hwnd, hdc );
+    ReleaseDC32( hwnd, hdc );
     if (!pressed) return;
 
     if (wParam == HTMINBUTTON) 
@@ -1194,10 +1219,10 @@
  *
  * Track a mouse button press on the horizontal or vertical scroll-bar.
  */
-static void NC_TrackScrollBar( HWND hwnd, WORD wParam, POINT16 pt )
+static void NC_TrackScrollBar( HWND32 hwnd, WPARAM32 wParam, POINT32 pt )
 {
     MSG16 *msg;
-    WORD scrollbar;
+    INT32 scrollbar;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
     if ((wParam & 0xfff0) == SC_HSCROLL)
@@ -1214,7 +1239,7 @@
     if (!(msg = SEGPTR_NEW(MSG16))) return;
     pt.x -= wndPtr->rectWindow.left;
     pt.y -= wndPtr->rectWindow.top;
-    SetCapture( hwnd );
+    SetCapture32( hwnd );
     SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
 
     do
@@ -1252,7 +1277,7 @@
  */
 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
 {
-    HDC hdc = GetWindowDC( hwnd );
+    HDC32 hdc;
 
     switch(wParam)  /* Hit test */
     {
@@ -1261,7 +1286,9 @@
 	break;
 
     case HTSYSMENU:
+        hdc = GetWindowDC32( hwnd );
 	NC_TrackSysMenu( hwnd, hdc, MAKEPOINT16(lParam) );
+        ReleaseDC32( hwnd, hdc );
 	break;
 
     case HTMENU:
@@ -1295,8 +1322,6 @@
     case HTBORDER:
 	break;
     }
-
-    ReleaseDC( hwnd, hdc );
     return 0;
 }
 
@@ -1345,6 +1370,7 @@
 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, POINT16 pt )
 {
     WND *wndPtr = WIN_FindWndPtr( hwnd );
+    POINT32 pt32;
 
     dprintf_nonclient(stddeb, "Handling WM_SYSCOMMAND %x %d,%d\n", 
 		      wParam, pt.x, pt.y );
@@ -1380,7 +1406,8 @@
 
     case SC_VSCROLL:
     case SC_HSCROLL:
-	NC_TrackScrollBar( hwnd, wParam, pt );
+        CONV_POINT16TO32( &pt, &pt32 );
+	NC_TrackScrollBar( hwnd, wParam, pt32 );
 	break;
 
     case SC_MOUSEMENU:
diff --git a/windows/painting.c b/windows/painting.c
index c1b3d09..76c5a73 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -114,8 +114,8 @@
      * (because rectClient == rectWindow for WS_MINIMIZE windows).
      */
 
-    lps->hdc = GetDCEx( hwnd, hrgnUpdate, DCX_INTERSECTRGN | DCX_WINDOWPAINT |
-                        DCX_USESTYLE | (bIcon ? DCX_WINDOW : 0) );
+    lps->hdc = GetDCEx16(hwnd, hrgnUpdate, DCX_INTERSECTRGN | DCX_WINDOWPAINT |
+                         DCX_USESTYLE | (bIcon ? DCX_WINDOW : 0) );
 
     dprintf_win(stddeb,"hdc = %04x\n", lps->hdc);
 
@@ -166,7 +166,7 @@
  */
 BOOL16 EndPaint16( HWND16 hwnd, const PAINTSTRUCT16* lps )
 {
-    ReleaseDC( hwnd, lps->hdc );
+    ReleaseDC16( hwnd, lps->hdc );
     ShowCaret( hwnd );
     return TRUE;
 }
@@ -177,7 +177,7 @@
  */
 BOOL32 EndPaint32( HWND32 hwnd, const PAINTSTRUCT32 *lps )
 {
-    ReleaseDC( hwnd, (HDC16)lps->hdc );
+    ReleaseDC32( hwnd, lps->hdc );
     ShowCaret( hwnd );
     return TRUE;
 }
@@ -245,7 +245,7 @@
     RECT32 rectClient;
     WND* wndPtr;
 
-    if (!hwnd) hwnd = GetDesktopWindow();
+    if (!hwnd) hwnd = GetDesktopWindow32();
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
     if (!IsWindowVisible(hwnd) || (wndPtr->flags & WIN_NO_REDRAW))
         return TRUE;  /* No redraw needed */
@@ -262,7 +262,14 @@
         dprintf_win(stddeb, "RedrawWindow: %04x NULL %04x flags=%04x\n",
                      hwnd, hrgnUpdate, flags);
     }
-    GetClientRect32( hwnd, &rectClient );
+
+    if (wndPtr->class->style & CS_PARENTDC)
+    {
+        GetClientRect32( wndPtr->parent->hwndSelf, &rectClient );
+        OffsetRect32( &rectClient, -wndPtr->rectClient.left,
+                      -wndPtr->rectClient.top );
+    }
+    else GetClientRect32( hwnd, &rectClient );
 
     if (flags & RDW_INVALIDATE)  /* Invalidate */
     {
@@ -364,17 +371,17 @@
 
         if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
         {
-            HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
-                               DCX_INTERSECTRGN | DCX_USESTYLE |
-                               DCX_KEEPCLIPRGN | DCX_WINDOWPAINT |
-                               (bIcon ? DCX_WINDOW : 0) );
+            HDC32 hdc = GetDCEx32( hwnd, wndPtr->hrgnUpdate,
+                                   DCX_INTERSECTRGN | DCX_USESTYLE |
+                                   DCX_KEEPCLIPRGN | DCX_WINDOWPAINT |
+                                   (bIcon ? DCX_WINDOW : 0) );
             if (hdc)
             {
                if (SendMessage16( hwnd, (bIcon) ? WM_ICONERASEBKGND
 						: WM_ERASEBKGND,
                                   (WPARAM)hdc, 0 ))
                   wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
-               ReleaseDC( hwnd, hdc );
+               ReleaseDC32( hwnd, hdc );
             }
         }
     }
@@ -400,18 +407,29 @@
            for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
 	     if( wndPtr->dwStyle & WS_VISIBLE )
 	       {
-                 SetRectRgn( hrgn, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
-                                   wndPtr->rectWindow.right, wndPtr->rectWindow.bottom);
-                 if( CombineRgn( hrgn, hrgn, hrgnUpdate, RGN_AND ) != NULLREGION )
-                 {
-		   if( control & RDW_C_USEHRGN &&
-		       wndPtr->dwStyle & WS_CLIPSIBLINGS ) 
-		       CombineRgn( hrgnUpdate, hrgnUpdate, hrgn, RGN_DIFF );
+                   if (wndPtr->class->style & CS_PARENTDC)
+                   {
+                       if (!CombineRgn( hrgn, hrgnUpdate, 0, RGN_COPY ))
+                           continue;
+                   }
+                   else
+                   {
+                       SetRectRgn( hrgn, wndPtr->rectWindow.left,
+                                   wndPtr->rectWindow.top,
+                                   wndPtr->rectWindow.right,
+                                   wndPtr->rectWindow.bottom);
+                       if (!CombineRgn( hrgn, hrgn, hrgnUpdate, RGN_AND ))
+                           continue;
+                   }
+#if 0
+                   if( control & RDW_C_USEHRGN &&
+                       wndPtr->dwStyle & WS_CLIPSIBLINGS ) 
+                       CombineRgn( hrgnUpdate, hrgnUpdate, hrgn, RGN_DIFF );
+#endif
 
                    OffsetRgn( hrgn, -wndPtr->rectClient.left,
                                  -wndPtr->rectClient.top );
                    PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn, flags, RDW_C_USEHRGN );
-                 }
                }
 	   DeleteObject( hrgn );
 	   if( control & RDW_C_DELETEHRGN ) DeleteObject( hrgnUpdate );
diff --git a/windows/property.c b/windows/property.c
index 089d35b..876bd58 100644
--- a/windows/property.c
+++ b/windows/property.c
@@ -166,7 +166,12 @@
     PROPERTY **pprop, *prop;
     WND *pWnd = WIN_FindWndPtr( hwnd );
 
-    dprintf_prop( stddeb, "RemoveProp: %04x '%s'\n", hwnd, str );
+    if (HIWORD(str))
+      dprintf_prop( stddeb, "RemoveProp: %04x '%s'\n", hwnd, str );
+    else
+      dprintf_prop( stddeb, "RemoveProp: %04x #%04x\n", hwnd, LOWORD(str));
+
+
     if (!pWnd) return NULL;
     if (HIWORD(str))
     {
diff --git a/windows/queue.c b/windows/queue.c
index ca6b4d9..aeff35c 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -15,11 +15,15 @@
 #define MAX_QUEUE_SIZE   120  /* Max. size of a message queue */
 
 static HQUEUE16 hFirstQueue = 0;
+static HQUEUE16 hDoomedQueue = 0;
 static HQUEUE16 hmemSysMsgQueue = 0;
+static MESSAGEQUEUE *sysMsgQueue = NULL;
+
 static MESSAGEQUEUE *pMouseQueue = NULL;  /* Queue for last mouse message */
 static MESSAGEQUEUE *pKbdQueue = NULL;    /* Queue for last kbd message */
-static HQUEUE16 hDoomedQueue = 0;
-static MESSAGEQUEUE *sysMsgQueue = NULL;
+
+MESSAGEQUEUE *pCursorQueue = NULL; 
+MESSAGEQUEUE *pActiveQueue = NULL;
 
 /***********************************************************************
  *	     QUEUE_DumpQueue
@@ -119,9 +123,10 @@
     if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, queueSize )))
         return 0;
     msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
-    msgQueue->self = hQueue;
-    msgQueue->msgSize = sizeof(QMSG);
-    msgQueue->queueSize = size;
+    msgQueue->self        = hQueue;
+    msgQueue->msgSize     = sizeof(QMSG);
+    msgQueue->queueSize   = size;
+    msgQueue->wakeBits    = msgQueue->changeBits = QS_SMPARAMSFREE;
     msgQueue->wWinVersion = pTask ? pTask->version : 0;
     GlobalUnlock16( hQueue );
     return hQueue;
@@ -136,6 +141,7 @@
 BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
 {
     MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)GlobalLock16(hQueue);
+    HQUEUE16  senderQ;
     HQUEUE16 *pPrev;
 
     dprintf_msg(stddeb,"Deleting message queue %04x\n", hQueue);
@@ -145,6 +151,19 @@
 	dprintf_msg(stddeb,"DeleteMsgQueue: invalid argument.\n");
 	return 0;
     }
+    if( pCursorQueue == msgQueue ) pCursorQueue = NULL;
+    if( pActiveQueue == msgQueue ) pActiveQueue = NULL;
+
+    /* flush sent messages */
+    senderQ = msgQueue->hSendingTask;
+    while( senderQ )
+    {
+      MESSAGEQUEUE* sq = (MESSAGEQUEUE*)GlobalLock16(senderQ);
+      if( !sq ) break;
+      sq->SendMessageReturn = 0L;
+      QUEUE_SetWakeBit( sq, QS_SMRESULT );
+      senderQ = sq->hPrevSendingTask;
+    }
 
     pPrev = &hFirstQueue;
     while (*pPrev && (*pPrev != hQueue))
@@ -191,6 +210,9 @@
  */
 void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
 {
+    dprintf_msg(stddeb,"SetWakeBit: queue = %04x (wm=%04x), bit = %04x\n", 
+	                queue->self, queue->wakeMask, bit );
+
     if (bit & QS_MOUSE) pMouseQueue = queue;
     if (bit & QS_KEY) pKbdQueue = queue;
     queue->changeBits |= bit;
@@ -222,9 +244,12 @@
 {
     MESSAGEQUEUE *queue;
 
+    dprintf_msg(stddeb,"WaitBits: q %04x waiting for %04x\n", GetTaskQueue(0), bits);
+
     for (;;)
     {
         if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
+
         if (queue->changeBits & bits)
         {
             /* One of the bits is set; we can return */
@@ -234,9 +259,17 @@
         if (queue->wakeBits & QS_SENDMESSAGE)
         {
             /* Process the sent message immediately */
+
+	    queue->wakeMask = 0;
             QUEUE_ReceiveMessage( queue );
+	    continue;				/* nested sm crux */
         }
+
         queue->wakeMask = bits | QS_SENDMESSAGE;
+	if(queue->changeBits & bits) continue;
+	
+	dprintf_msg(stddeb,"wb: (%04x) wakeMask is %04x, waiting\n", queue->self, queue->wakeMask);
+
         WaitEvent( 0 );
     }
 }
@@ -249,57 +282,55 @@
  */
 void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
 {
-    MESSAGEQUEUE *senderQ;
-    HWND hwnd;
-    UINT msg;
-    WPARAM wParam;
-    LPARAM lParam;
-    LRESULT result = 0;
-    HQUEUE16 oldSender;
+    MESSAGEQUEUE *senderQ = NULL;
+    HQUEUE16      prevSender = 0;
+    QSMCTRL*      prevCtrlPtr = NULL;
+    LRESULT       result = 0;
 
-    printf( "ReceiveMessage\n" );
-    if (!(queue->wakeBits & QS_SENDMESSAGE)) return;
-    if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask))) return;
+    dprintf_msg(stddeb, "ReceiveMessage, queue %04x\n", queue->self );
+    if (!(queue->wakeBits & QS_SENDMESSAGE) ||
+        !(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask))) 
+	{ dprintf_msg(stddeb,"\trcm: nothing to do\n"); return; }
 
-    /* Remove sending queue from the list */
-    oldSender                  = queue->InSendMessageHandle;
     queue->InSendMessageHandle = queue->hSendingTask;
-    queue->hSendingTask        = senderQ->hPrevSendingTask;
-    senderQ->hPrevSendingTask  = 0;
-    if (!queue->hSendingTask)
+    if( !(queue->hSendingTask = senderQ->hPrevSendingTask) )
     {
-        queue->wakeBits &= ~QS_SENDMESSAGE;
-        queue->changeBits &= ~QS_SENDMESSAGE;
+      queue->wakeBits &= ~QS_SENDMESSAGE;	/* no more sent messages */
+      queue->changeBits &= ~QS_SENDMESSAGE;
     }
 
-    /* Get the parameters from the sending task */
-    hwnd   = senderQ->hWnd;
-    msg    = senderQ->msg;
-    wParam = senderQ->wParam;
-    lParam = senderQ->lParam;
-    senderQ->hWnd = 0;
+    /* Remove sending queue from the list */
+    prevSender                 = queue->InSendMessageHandle;
+    prevCtrlPtr		       = queue->smResultCurrent;
+    queue->smResultCurrent     = senderQ->smResultInit;
+
+    dprintf_msg(stddeb, "\trcm: smResultCurrent = %08x, prevCtrl = %08x\n", 
+				(unsigned)queue->smResultCurrent, (unsigned)prevCtrlPtr );
     QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE );
 
-    printf( "ReceiveMessage: calling wnd proc %04x %04x %04x %08x\n",
-            hwnd, msg, wParam, lParam );
+    dprintf_msg(stddeb, "\trcm: calling wndproc - %04x %04x %04x %08x\n",
+            senderQ->hWnd, senderQ->msg, senderQ->wParam, (unsigned)senderQ->lParam );
 
-    /* Call the window procedure */
-    /* FIXME: should we use CallWindowProc here? */
-    if (IsWindow( hwnd ))
+    if (IsWindow( senderQ->hWnd ))
     {
         DWORD extraInfo = queue->GetMessageExtraInfoVal;
         queue->GetMessageExtraInfoVal = senderQ->GetMessageExtraInfoVal;
-        result = SendMessage16( hwnd, msg, wParam, lParam );
-        queue->GetMessageExtraInfoVal = extraInfo;  /* Restore extra info */
-    }
 
-    printf( "ReceiveMessage: wnd proc %04x %04x %04x %08x ret = %08x\n",
-            hwnd, msg, wParam, lParam, result );
+        result = CallWindowProc16( (WNDPROC16)GetWindowLong16(senderQ->hWnd, GWL_WNDPROC),
+				   senderQ->hWnd, senderQ->msg, senderQ->wParam, senderQ->lParam );
+
+        queue->GetMessageExtraInfoVal = extraInfo;  /* Restore extra info */
+	dprintf_msg(stddeb,"\trcm: result =  %08x\n", (unsigned)result );
+    }
+    else dprintf_msg(stddeb,"\trcm: bad hWnd\n");
 
     /* Return the result to the sender task */
     ReplyMessage( result );
 
-    queue->InSendMessageHandle = oldSender;
+    queue->InSendMessageHandle = prevSender;
+    queue->smResultCurrent     = prevCtrlPtr;
+
+    dprintf_msg(stddeb,"ReceiveMessage: done!\n");
 }
 
 
@@ -399,39 +430,44 @@
  */
 static void QUEUE_WakeSomeone( UINT message )
 {
-    HWND hwnd;
-    WORD wakeBit;
-    HQUEUE16 hQueue;
-    MESSAGEQUEUE *queue = NULL;
+    WND*	  wndPtr = NULL;
+    HWND          hwnd;
+    WORD          wakeBit;
+    MESSAGEQUEUE *queue = pCursorQueue;
 
-    if ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST)) wakeBit = QS_KEY;
-    else wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
+    if( (message >= WM_KEYFIRST) && (message <= WM_KEYLAST) )
+    {
+       wakeBit = QS_KEY;
+       if( pActiveQueue ) queue = pActiveQueue;
+    }
+    else 
+    {
+       wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
+       if( (hwnd = GetCapture32()) )
+	 if( (wndPtr = WIN_FindWndPtr( hwnd )) ) 
+	   queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
+    }
 
-    if (!(hwnd = GetSysModalWindow16()))
+    if( (hwnd = GetSysModalWindow16()) )
+      if( (wndPtr = WIN_FindWndPtr( hwnd )) )
+        queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
+
+    if( !queue ) 
     {
-        if (wakeBit == QS_KEY)
-        {
-            if (!(hwnd = GetFocus32())) hwnd = GetActiveWindow();
-        }
-        else hwnd = GetCapture();
+      queue = GlobalLock16( hFirstQueue );
+      while( queue )
+      {
+        if (queue->wakeMask & wakeBit) break;
+        queue = GlobalLock16( queue->next );
+      }
+      if( !queue )
+      { 
+        dprintf_msg(stddeb,"WakeSomeone: couldn't find queue\n"); 
+        return; 
+      }
     }
-    if (hwnd)
-    {
-        WND *wndPtr = WIN_FindWndPtr( hwnd );
-        if (wndPtr) queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
-    }
-    else if (!(queue = pMouseQueue))
-    {
-        hQueue = hFirstQueue;
-        while (hQueue)
-        {
-            queue = GlobalLock16( hQueue );
-            if (queue->wakeBits & wakeBit) break;
-            hQueue = queue->next;
-        }
-    }
-    if (!queue) printf( "WakeSomeone: no one found\n" );
-    if (queue) QUEUE_SetWakeBit( queue, wakeBit );
+
+    QUEUE_SetWakeBit( queue, wakeBit );
 }
 
 
@@ -595,15 +631,23 @@
 	dprintf_msg(stddeb,"SetMessageQueue: failed!\n");
 	return FALSE;
     }
+    queuePtr = (MESSAGEQUEUE *)GlobalLock16( hNewQueue );
 
-    /* Free the old message queue */
-    if ((hQueue = GetTaskQueue(0)) != 0) QUEUE_DeleteMsgQueue( hQueue );
+    /* Copy data and free the old message queue */
+    if ((hQueue = GetTaskQueue(0)) != 0) 
+    {
+       MESSAGEQUEUE *oldQ = (MESSAGEQUEUE *)GlobalLock16( hQueue );
+       memcpy( &queuePtr->reserved2, &oldQ->reserved2, 
+			(int)oldQ->messages - (int)(&oldQ->reserved2) );
+       QUEUE_DeleteMsgQueue( hQueue );
+    }
 
     /* Link new queue into list */
-    queuePtr = (MESSAGEQUEUE *)GlobalLock16( hNewQueue );
     queuePtr->hTask = GetCurrentTask();
     queuePtr->next  = hFirstQueue;
     hFirstQueue = hNewQueue;
+    
+    if( !queuePtr->next ) pCursorQueue = queuePtr;
 
     SetTaskQueue( 0, hNewQueue );
     return TRUE;
diff --git a/windows/scroll.c b/windows/scroll.c
index 9b8d699..f92adf1 100644
--- a/windows/scroll.c
+++ b/windows/scroll.c
@@ -29,7 +29,7 @@
  */
 void ScrollWindow(HWND hwnd, short dx, short dy, LPRECT16 rect, LPRECT16 clipRect)
 {
-    HDC  	hdc;
+    HDC32  	hdc;
     HRGN 	hrgnUpdate,hrgnClip;
     RECT16 	rc, cliprc;
     HWND 	hCaretWnd = CARET_GetHwnd();
@@ -52,7 +52,7 @@
               HideCaret(hCaretWnd);
           else hCaretWnd = 0;
  
-	  hdc      = GetDCEx(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS);
+	  hdc = GetDCEx32(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS);
           DeleteObject(hrgnClip);
        }
     else	/* clip children */
@@ -63,7 +63,7 @@
           if (hCaretWnd == hwnd) HideCaret(hCaretWnd);
           else hCaretWnd = 0;
 
-	  hdc = GetDC(hwnd);
+	  hdc = GetDC32(hwnd);
        }
 
     if (clipRect == NULL)
@@ -73,7 +73,7 @@
 
     hrgnUpdate = CreateRectRgn(0, 0, 0, 0);
     ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, NULL);
-    ReleaseDC(hwnd, hdc);
+    ReleaseDC32(hwnd, hdc);
 
     if( !rect )		/* move child windows and update region */
     { 
@@ -230,12 +230,12 @@
 int ScrollWindowEx(HWND hwnd, short dx, short dy, LPRECT16 rect, LPRECT16 clipRect,
 		   HRGN hrgnUpdate, LPRECT16 rcUpdate, WORD flags)
 {
-    HDC hdc;
+    HDC32 hdc;
     RECT16 rc, cliprc;
 
     dprintf_scroll(stddeb,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx, dy, flags);
 
-    hdc = GetDC(hwnd);
+    hdc = GetDC32(hwnd);
 
     if (rect == NULL)
 	GetClientRect16(hwnd, &rc);
@@ -254,6 +254,6 @@
                         ((flags & SW_ERASE) ? RDW_ERASENOW : 0), 0 );
     }
 
-    ReleaseDC(hwnd, hdc);
+    ReleaseDC32(hwnd, hdc);
     return RgnType;
 }
diff --git a/windows/win.c b/windows/win.c
index 80debdf..563c788 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -44,6 +44,9 @@
 static WORD wDragHeight= 3;
 
 extern HCURSOR16 CURSORICON_IconToCursor(HICON16);
+extern HWND32 CARET_GetHwnd(void);
+extern BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd);
+extern void   WINPOS_CheckActive(HWND32);
 
 /***********************************************************************
  *           WIN_FindWndPtr
@@ -90,13 +93,13 @@
     fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
     fprintf( stderr,
              "next=%p  child=%p  parent=%p  owner=%p  class=%p '%s'\n"
-             "inst=%04x  taskQ=%04x  updRgn=%04x  active=%04x hdce=%04x  idmenu=%04x\n"
+             "inst=%04x  taskQ=%04x  updRgn=%04x  active=%04x dce=%p  idmenu=%04x\n"
              "style=%08lx  exstyle=%08lx  wndproc=%08x  text='%s'\n"
              "client=%d,%d-%d,%d  window=%d,%d-%d,%d  iconpos=%d,%d  maxpos=%d,%d\n"
              "sysmenu=%04x  flags=%04x  props=%p  vscroll=%p  hscroll=%p\n",
              ptr->next, ptr->child, ptr->parent, ptr->owner,
              ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
-             ptr->hrgnUpdate, ptr->hwndLastActive, ptr->hdce, ptr->wIDmenu,
+             ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
              ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
              ptr->text ? ptr->text : "",
              ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
@@ -301,37 +304,71 @@
 /***********************************************************************
  *           WIN_DestroyWindow
  *
- * Destroy storage associated to a window
+ * Destroy storage associated to a window. "Internals" p.358
  */
-static void WIN_DestroyWindow( HWND hwnd )
+static void WIN_DestroyWindow( WND* wndPtr )
 {
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    HWND hwnd = wndPtr->hwndSelf;
+    WND* pWnd,*pNext;
 
 #ifdef CONFIG_IPC
     if (main_block)
-	DDE_DestroyWindow(hwnd);
+	DDE_DestroyWindow(wndPtr->hwndSelf);
 #endif  /* CONFIG_IPC */
 	
-    if (!wndPtr) return;
-    WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
-    TIMER_RemoveWindowTimers( hwnd );
+    /* free child windows */
+
+    pNext = wndPtr->child;
+    while( (pWnd = pNext) )
+    {
+        pNext = pWnd->next;
+        WIN_DestroyWindow( pWnd );
+    }
+
+    SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
+
+    /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
+
+    WINPOS_CheckActive( hwnd );
+    if( hwnd == GetCapture32()) ReleaseCapture();
+
+    /* free resources associated with the window */
+
+    TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
     PROPERTY_RemoveWindowProps( wndPtr );
+
     wndPtr->dwMagic = 0;  /* Mark it as invalid */
     wndPtr->hwndSelf = 0;
+
     if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
     {
         if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
         QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
     }
-    if (!(wndPtr->dwStyle & WS_CHILD))
+
+    /* toss stale messages from the queue */
+
+    if( wndPtr->hmemTaskQ )
     {
-        if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
+      int           pos;
+      MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
+
+      while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 ) 
+	      QUEUE_RemoveMsg(msgQ, pos);
+      wndPtr->hmemTaskQ = 0;
     }
+
+    if (!(wndPtr->dwStyle & WS_CHILD))
+       if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
     if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
     if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
-    if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
+    if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->dce );
+
     WINPROC_FreeProc( wndPtr->winproc );
+
     wndPtr->class->cWindows--;
+    wndPtr->class = NULL;
+
     USER_HEAP_FREE( hwnd );
 }
 
@@ -398,7 +435,7 @@
     pWndDesktop->dwStyle           = WS_VISIBLE | WS_CLIPCHILDREN |
                                      WS_CLIPSIBLINGS;
     pWndDesktop->dwExStyle         = 0;
-    pWndDesktop->hdce              = 0;
+    pWndDesktop->dce               = NULL;
     pWndDesktop->pVScroll          = NULL;
     pWndDesktop->pHScroll          = NULL;
     pWndDesktop->pProp             = NULL;
@@ -426,7 +463,7 @@
 {
     CLASS *classPtr;
     WND *wndPtr;
-    HWND16 hwnd;
+    HWND16 hwnd, hwndLinkAfter;
     POINT16 maxSize, maxPos, minTrack, maxTrack;
     LRESULT wmcreate;
 
@@ -493,12 +530,23 @@
     /* Fill the window structure */
 
     wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
-    wndPtr->next           = NULL;
-    wndPtr->child          = NULL;
-    wndPtr->parent         = (cs->style & WS_CHILD) ?
-                              WIN_FindWndPtr( cs->hwndParent ) : pWndDesktop;
-    wndPtr->owner          = (cs->style & WS_CHILD) ? NULL :
-                              WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
+    wndPtr->next  = NULL;
+    wndPtr->child = NULL;
+
+    if (cs->style & WS_CHILD)
+    {
+        wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
+        wndPtr->owner  = NULL;
+    }
+    else
+    {
+        wndPtr->parent = pWndDesktop;
+        if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
+            wndPtr->owner = NULL;
+        else
+            wndPtr->owner = WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
+    }
+
     wndPtr->window         = 0;
     wndPtr->class          = classPtr;
     wndPtr->winproc        = NULL;
@@ -524,10 +572,46 @@
     wndPtr->userdata       = 0;
 
     if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
-    classPtr->cWindows++;
+
+    /* Call the WH_CBT hook */
+
+    hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
+
+    if (HOOK_GetHook( WH_CBT, GetTaskQueue(0) ))
+    {
+        CBT_CREATEWND16* cbtc;
+
+        if ((cbtc = SEGPTR_NEW(CBT_CREATEWND16)))
+        {
+            /* Dummy message params to use WINPROC_MapMsg functions */
+            UINT16 msg;
+            WPARAM16 wparam;
+            LPARAM lparam;
+
+            /* Map the CREATESTRUCT to 16-bit format */
+            lparam = (LPARAM)cs;
+            if (unicode)
+                WINPROC_MapMsg32WTo16( WM_CREATE, 0, &msg, &wparam, &lparam );
+            else
+                WINPROC_MapMsg32ATo16( WM_CREATE, 0, &msg, &wparam, &lparam );
+            cbtc->lpcs = (CREATESTRUCT16 *)lparam;
+            cbtc->hwndInsertAfter = hwndLinkAfter;
+            wmcreate = !HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, hwnd,
+                                        (LPARAM)SEGPTR_GET(cbtc) );
+            WINPROC_UnmapMsg32ATo16( WM_CREATE, 0, lparam );
+            SEGPTR_FREE(cbtc);
+            if (!wmcreate)
+            {
+                dprintf_win(stddeb,"CreateWindowEx: CBT-hook returned 0\n" );
+                USER_HEAP_FREE( hwnd );
+                return 0;
+            }
+        }
+    }
 
     /* Set the window procedure */
 
+    classPtr->cWindows++;
     WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
 
     /* Correct the window style */
@@ -541,54 +625,13 @@
 
     /* Get class or window DC if needed */
 
-    if (classPtr->style & CS_OWNDC) wndPtr->hdce = DCE_AllocDCE(hwnd, DCE_WINDOW_DC);
-    else if (classPtr->style & CS_CLASSDC) wndPtr->hdce = classPtr->hdce;
-    else wndPtr->hdce = 0;
+    if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
+    else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
+    else wndPtr->dce = NULL;
 
     /* Insert the window in the linked list */
 
-    WIN_LinkWindow( hwnd, (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP );
-
-    /* Call the WH_CBT hook */
-
-    if (HOOK_GetHook( WH_CBT, GetTaskQueue(0) ))
-    {
-        CBT_CREATEWND16* cbtc;
-
-        if ((cbtc = SEGPTR_NEW(CBT_CREATEWND16)))
-        {
-            /* Dummy message params to use WINPROC_MapMsg functions */
-            UINT16 msg;
-            WPARAM16 wparam;
-            LPARAM lparam;
-
-            HWND hwndZnew = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
-
-            /* Map the CREATESTRUCT to 16-bit format */
-            lparam = (LPARAM)cs;
-            if (unicode)
-                WINPROC_MapMsg32WTo16( WM_CREATE, 0, &msg, &wparam, &lparam );
-            else
-                WINPROC_MapMsg32ATo16( WM_CREATE, 0, &msg, &wparam, &lparam );
-            cbtc->lpcs = (CREATESTRUCT16 *)lparam;
-            cbtc->hwndInsertAfter = hwndZnew;
-            wmcreate = !HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, hwnd,
-                                        (LPARAM)SEGPTR_GET(cbtc) );
-            WINPROC_UnmapMsg32ATo16( WM_CREATE, 0, lparam );
-            if (hwndZnew != cbtc->hwndInsertAfter)
-            {
-                WIN_UnlinkWindow( hwnd );
-                WIN_LinkWindow( hwnd, cbtc->hwndInsertAfter );
-            }
-            SEGPTR_FREE(cbtc);
-            if (!wmcreate)
-            {
-                dprintf_win(stddeb,"CreateWindowEx: CBT-hook returned 0\n" );
-                WIN_DestroyWindow( hwnd );
-                return 0;
-            }
-        }
-    }
+    WIN_LinkWindow( hwnd, hwndLinkAfter );
 
     /* Send the WM_GETMINMAXINFO message and fix the size if needed */
 
@@ -722,7 +765,8 @@
     {
 	  /* Abort window creation */
 	dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
-        WIN_DestroyWindow( hwnd );
+        WIN_UnlinkWindow( hwnd );
+        WIN_DestroyWindow( wndPtr );
 	return 0;
     }
 
@@ -884,7 +928,14 @@
 
     if (!(classAtom = GlobalFindAtom32W( className )))
     {
-        fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
+    	if (HIWORD(className))
+        {
+            LPSTR cn = STRING32_DupUniToAnsi(className);
+            fprintf( stderr, "CreateWindowEx32W: bad class name '%s'\n",cn);
+            free(cn);
+	}
+        else
+            fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
         return 0;
     }
 
@@ -909,6 +960,45 @@
 
 
 /***********************************************************************
+ *           WIN_CheckFocus
+ */
+static void WIN_CheckFocus( WND* pWnd )
+{
+  if( GetFocus16() == pWnd->hwndSelf )
+      SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 ); 
+}
+
+/***********************************************************************
+ *           WIN_SendDestroyMsg
+ */
+static void WIN_SendDestroyMsg( WND* pWnd )
+{
+  WND*	pChild;
+
+  WIN_CheckFocus(pWnd);
+
+  if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
+  if( !pWnd->window ) CLIPBOARD_DisOwn( pWnd ); 
+  
+  SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
+
+  if( !IsWindow(pWnd->hwndSelf) )
+  {
+    dprintf_win(stddeb,"\tdestroyed itself while in WM_DESTROY!\n");
+    return;
+  }
+
+  pChild = pWnd->child;
+  while( pChild )
+  { 
+    WIN_SendDestroyMsg( pChild );
+    pChild = pChild->next;
+  }
+  WIN_CheckFocus(pWnd);
+}
+
+
+/***********************************************************************
  *           DestroyWindow   (USER.53)
  */
 BOOL DestroyWindow( HWND hwnd )
@@ -922,7 +1012,10 @@
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
     if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
 
-      /* Top-level window */
+      /* Call hooks */
+
+    if( HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
+        return FALSE;
 
     if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
     {
@@ -930,41 +1023,61 @@
         /* FIXME: clean up palette - see "Internals" p.352 */
     }
 
+    if( !QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ) )
+	 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
+    if( !IsWindow(hwnd) ) return TRUE;
+
+    if( wndPtr->window ) CLIPBOARD_DisOwn( wndPtr ); /* before window is unmapped */
+
       /* Hide the window */
 
     if (wndPtr->dwStyle & WS_VISIBLE)
-	SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
-		      SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
-    if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
-	ReleaseCapture();
-    WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
-
-    CLIPBOARD_DisOwn( hwnd );
+    {
+        SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
+		      SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE |
+		    ((QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
+	if( !IsWindow(hwnd) ) return TRUE;
+    }
 
       /* Recursively destroy owned windows */
 
-    for (;;)
+    if( !(wndPtr->dwStyle & WS_CHILD) )
     {
+      for (;;)
+      {
         WND *siblingPtr = wndPtr->parent->child;  /* First sibling */
         while (siblingPtr)
         {
-            if (siblingPtr->owner == wndPtr) break;
+            if (siblingPtr->owner == wndPtr)
+               if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
+                   break;
+               else 
+                   siblingPtr->owner = NULL;
             siblingPtr = siblingPtr->next;
         }
         if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
         else break;
+      }
+
+      WINPOS_ActivateOtherWindow(wndPtr);
+
+      if( wndPtr->owner &&
+	  wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
+	  wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
     }
 
-      /* Send destroy messages and destroy children */
+      /* Send destroy messages */
 
-    SendMessage16( hwnd, WM_DESTROY, 0, 0 );
-    while (wndPtr->child)  /* The child removes itself from the list */
-	DestroyWindow( wndPtr->child->hwndSelf );
-    SendMessage16( hwnd, WM_NCDESTROY, 0, 0 );
+    WIN_SendDestroyMsg( wndPtr );
+    if( !IsWindow(hwnd) ) return TRUE;
 
-      /* Destroy the window */
+      /* Unlink now so we won't bother with the children later on */
 
-    WIN_DestroyWindow( hwnd );
+    if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
+
+      /* Destroy the window storage */
+
+    WIN_DestroyWindow( wndPtr );
     return TRUE;
 }
 
@@ -1145,9 +1258,18 @@
 
 
 /**********************************************************************
- *           GetDesktopWindow   (USER.286)
+ *           GetDesktopWindow16   (USER.286)
  */
-HWND GetDesktopWindow(void)
+HWND16 GetDesktopWindow16(void)
+{
+    return (HWND16)pWndDesktop->hwndSelf;
+}
+
+
+/**********************************************************************
+ *           GetDesktopWindow32   (USER32.231)
+ */
+HWND32 GetDesktopWindow32(void)
 {
     return pWndDesktop->hwndSelf;
 }
@@ -1159,9 +1281,9 @@
  * Exactly the same thing as GetDesktopWindow(), but not documented.
  * Don't ask me why...
  */
-HWND GetDesktopHwnd(void)
+HWND16 GetDesktopHwnd(void)
 {
-    return pWndDesktop->hwndSelf;
+    return (HWND16)pWndDesktop->hwndSelf;
 }
 
 
@@ -1186,7 +1308,7 @@
 	wndPtr->dwStyle |= WS_DISABLED;
 	if ((hwnd == GetFocus32()) || IsChild( hwnd, GetFocus32() ))
 	    SetFocus32( 0 );  /* A disabled window can't have the focus */
-	if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
+	if ((hwnd == GetCapture32()) || IsChild( hwnd, GetCapture32() ))
 	    ReleaseCapture();  /* A disabled window can't capture the mouse */
 	SendMessage16( hwnd, WM_ENABLE, FALSE, 0 );
 	return FALSE;
@@ -1892,12 +2014,12 @@
     {
         if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
         {
-            HDC hDC = GetDC(hWnd);
+            HDC32 hDC = GetDC32(hWnd);
             
             if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM)hDC, (LPARAM)0 ))
                 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
             
-            ReleaseDC( hWnd, hDC );
+            ReleaseDC32( hWnd, hDC );
             wndPtr->flags |= WIN_NCACTIVATED;
         }
         else
@@ -2026,7 +2148,7 @@
   rect.top = pt.y - wDragHeight;
   rect.bottom = pt.y + wDragHeight;
 
-  SetCapture(hWnd);
+  SetCapture32(hWnd);
 
   while(1)
    {
@@ -2105,7 +2227,7 @@
  lpDragInfo->hOfStruct = hOfStruct;
  lpDragInfo->l = 0L; 
 
- SetCapture(hWnd);
+ SetCapture32(hWnd);
  ShowCursor(1);
 
  while( !dragDone )
diff --git a/windows/winpos.c b/windows/winpos.c
index 48d43ee..7efd791 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -48,6 +48,21 @@
 static HWND hwndActive      = 0;  /* Currently active window */
 static HWND hwndPrevActive  = 0;  /* Previously active window */
 
+extern MESSAGEQUEUE* pActiveQueue;
+
+/***********************************************************************
+ *           WINPOS_CheckActive
+ */
+void WINPOS_CheckActive( HWND32 hwnd )
+{
+  if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
+  if( hwnd == hwndActive )
+  {
+      hwndActive = 0; 
+      dprintf_win(stddeb,"\tattempt to activate destroyed window!\n");
+  }
+}
+
 /***********************************************************************
  *           WINPOS_FindIconPos
  *
@@ -483,13 +498,23 @@
 /*******************************************************************
  *         GetActiveWindow    (USER.60)
  */
-HWND GetActiveWindow()
+HWND GetActiveWindow(void)
 {
     return hwndActive;
 }
 
 
 /*******************************************************************
+ *         WINPOS_IsGoodEnough
+ */
+static BOOL32 WINPOS_IsGoodEnough(WND* pWnd)
+{
+ return (pWnd) ? ((!(pWnd->dwStyle & WS_DISABLED) &&
+                     pWnd->dwStyle & WS_VISIBLE ) ? TRUE : FALSE) : FALSE;
+}
+
+
+/*******************************************************************
  *         SetActiveWindow    (USER.59)
  */
 HWND SetActiveWindow( HWND hwnd )
@@ -497,8 +522,7 @@
     HWND prev = hwndActive;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
-    if (!wndPtr || (wndPtr->dwStyle & WS_DISABLED) ||
-	!(wndPtr->dwStyle & WS_VISIBLE)) return 0;
+    if ( !WINPOS_IsGoodEnough(wndPtr) ) return 0;
 
     WINPOS_SetActiveWindow( hwnd, 0, 0 );
     return prev;
@@ -562,6 +586,9 @@
             swpflags |= SWP_FRAMECHANGED;
             if (!(wndPtr->dwStyle & WS_MINIMIZE))
             {
+		if( HOOK_CallHooks( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
+		    return 0;
+
                 if (wndPtr->dwStyle & WS_MAXIMIZE)
                 {
                     wndPtr->flags |= WIN_RESTORE_MAX;
@@ -587,6 +614,9 @@
             swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
             if (!(wndPtr->dwStyle & WS_MAXIMIZE))
             {
+		if( HOOK_CallHooks( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
+		    return 0;
+
                   /* Store the current position and find the maximized size */
                 if (!(wndPtr->dwStyle & WS_MINIMIZE))
                     wndPtr->rectNormal = wndPtr->rectWindow; 
@@ -630,6 +660,9 @@
 
             if (wndPtr->dwStyle & WS_MINIMIZE)
             {
+		if( HOOK_CallHooks( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
+		    return 0;
+
                 if( !SendMessage16( hwnd, WM_QUERYOPEN, 0, 0L) )
                   {
                     swpflags |= SWP_NOSIZE | SWP_NOMOVE;
@@ -660,6 +693,9 @@
             }
             else if (wndPtr->dwStyle & WS_MAXIMIZE)
             {
+		if( HOOK_CallHooks( WH_CBT, HCBT_MINMAX, hwnd, cmd) )
+		    return 0;
+
                 wndPtr->ptMaxPos.x = wndPtr->rectWindow.left;
                 wndPtr->ptMaxPos.y = wndPtr->rectWindow.top;
                 wndPtr->dwStyle &= ~WS_MAXIMIZE;
@@ -855,6 +891,43 @@
     return TRUE;
 }
 
+/***********************************************************************
+ *           WINPOS_ForceXWindowRaise
+ */
+void WINPOS_ForceXWindowRaise( WND* pWnd )
+{
+    XWindowChanges winChanges;
+    WND *wndStop, *wndLast;
+
+    if (!pWnd->window) return;
+
+    wndLast = wndStop = pWnd;
+    winChanges.stack_mode = Above;
+    XReconfigureWMWindow( display, pWnd->window, 0, CWStackMode, &winChanges );
+
+    /* Recursively raise owned popups according to their z-order
+     * (it would be easier with sibling-related Below but it doesn't
+     * work very well with SGI mwm for instance)
+     */
+    while (wndLast)
+    {
+        WND *wnd = WIN_GetDesktop()->child;
+        wndLast = NULL;
+        while (wnd != wndStop)
+        {
+            if (wnd->owner == pWnd &&
+                (wnd->dwStyle & WS_POPUP) &&
+                (wnd->dwStyle & WS_VISIBLE))
+                wndLast = wnd;
+            wnd = wnd->next;
+        }
+        if (wndLast)
+        {
+            WINPOS_ForceXWindowRaise( wndLast );
+            wndStop = wndLast;
+        }
+    }
+}
 
 /*******************************************************************
  *	   WINPOS_SetActiveWindow
@@ -867,20 +940,16 @@
     WND                   *wndTemp         = WIN_FindWndPtr(hwndActive);
     CBTACTIVATESTRUCT16   *cbtStruct;
     WORD                   wIconized=0;
-    HANDLE hNewActiveQueue;
-
-    /* FIXME: When proper support for cooperative multitasking is in place 
-     *        hActiveQ will be global 
-     */
-
-    HANDLE                 hActiveQ = 0;   
+    HANDLE		   hOldActiveQueue = (pActiveQueue)?pActiveQueue->self:0;
+    HANDLE 		   hNewActiveQueue;
 
     /* paranoid checks */
-    if( hWnd == GetDesktopWindow() || hWnd == hwndActive )
+    if( hWnd == GetDesktopWindow32() || hWnd == hwndActive )
 	return 0;
 
-    if (wndPtr && (GetTaskQueue(0) != wndPtr->hmemTaskQ))
+/* if (wndPtr && (GetTaskQueue(0) != wndPtr->hmemTaskQ))
 	return 0;
+        */
 
     if( wndTemp )
 	wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
@@ -946,15 +1015,10 @@
         if( !IsWindow(hWnd) ) return 0;
     }
 
-    if (hwndPrevActive)
-    {
-        wndTemp = WIN_FindWndPtr( hwndPrevActive );
-        if (wndTemp) hActiveQ = wndTemp->hmemTaskQ;
-    }
     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
 
     /* send WM_ACTIVATEAPP if necessary */
-    if (hActiveQ != hNewActiveQueue)
+    if (hOldActiveQueue != hNewActiveQueue)
     {
         WND **list, **ppWnd;
 
@@ -962,24 +1026,27 @@
         {
             for (ppWnd = list; *ppWnd; ppWnd++)
             {
-                /* Make sure that the window still exists */
                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
-                if ((*ppWnd)->hmemTaskQ != hActiveQ) continue;
-                SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
-                               0, QUEUE_GetQueueTask(hNewActiveQueue) );
+
+                if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
+                   SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
+                                   0, QUEUE_GetQueueTask(hNewActiveQueue) );
             }
             HeapFree( SystemHeap, 0, list );
         }
 
+	pActiveQueue = (hNewActiveQueue)
+		       ? (MESSAGEQUEUE*) GlobalLock16(hNewActiveQueue) : NULL;
+
         if ((list = WIN_BuildWinArray( WIN_GetDesktop() )))
         {
             for (ppWnd = list; *ppWnd; ppWnd++)
             {
-                /* Make sure that the window still exists */
                 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
-                if ((*ppWnd)->hmemTaskQ != hNewActiveQueue) continue;
-                SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
-                               1, QUEUE_GetQueueTask( hActiveQ ) );
+
+                if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
+                   SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
+                                  1, QUEUE_GetQueueTask( hOldActiveQueue ) );
             }
             HeapFree( SystemHeap, 0, list );
         }
@@ -1009,6 +1076,10 @@
 	    FOCUS_SwitchFocus( GetFocus32(),
 			       (wndPtr->dwStyle & WS_MINIMIZE)? 0: hwndActive);
 
+    if( !hwndPrevActive && wndPtr && 
+	 wndPtr->window && !(wndPtr->flags & WIN_MANAGED) )
+	WINPOS_ForceXWindowRaise(wndPtr);
+
     /* if active wnd is minimized redraw icon title 
   if( hwndActive )
       {
@@ -1020,6 +1091,50 @@
     return (hWnd == hwndActive);
 }
 
+/*******************************************************************
+ *         WINPOS_ActivateOtherWindow
+ *
+ * DestroyWindow() helper. pWnd must be a top-level window.
+ */
+BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd)
+{
+  BOOL32	bRet = 0;
+  WND*  	pWndTo = NULL;
+
+  if( pWnd->hwndSelf == hwndPrevActive )
+      hwndPrevActive = 0;
+
+  if( hwndActive != pWnd->hwndSelf && 
+    ( hwndActive || QUEUE_IsDoomedQueue(pWnd->hmemTaskQ)) )
+      return 0;
+
+  if( pWnd->dwStyle & WS_POPUP &&
+      WINPOS_IsGoodEnough( pWnd->owner ) ) pWndTo = pWnd->owner;
+  else
+  {
+    WND* pWndPtr = pWnd;
+
+    pWndTo = WIN_FindWndPtr(hwndPrevActive);
+
+    while( !WINPOS_IsGoodEnough(pWndTo) ) 
+    {
+      /* by now owned windows should've been taken care of */
+
+      pWndTo = pWndPtr->next;
+      pWndPtr = pWndTo;
+      if( !pWndTo ) return 0;
+    }
+  }
+
+  bRet = WINPOS_SetActiveWindow( pWndTo->hwndSelf, FALSE, TRUE );
+
+  /* switch desktop queue to current active */
+  if( pWndTo->parent == WIN_GetDesktop())
+      WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
+
+  hwndPrevActive = 0;
+  return bRet;  
+}
 
 /*******************************************************************
  *	   WINPOS_ChangeActiveWindow
@@ -1219,67 +1334,41 @@
  */
 HWND WINPOS_ReorderOwnedPopups(HWND hwndInsertAfter, WND* wndPtr, WORD flags)
 {
- WND* 	w = WIN_GetDesktop();
+ WND* 	w = WIN_GetDesktop()->child;
 
- w = w->child;
+  if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
+  {
+   /* implement "local z-order" between the top and owner window */
 
- /* if we are dealing with owned popup... 
-  */
- if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner && hwndInsertAfter != HWND_TOP )
-   {
-     BOOL bFound = FALSE;
      HWND hwndLocalPrev = HWND_TOP;
-     HWND hwndNewAfter = 0;
 
-     while( w )
-       {
-         if( !bFound && hwndInsertAfter == hwndLocalPrev )
-             hwndInsertAfter = HWND_TOP;
+     if( hwndInsertAfter != HWND_TOP )
+     {
+	while( w != wndPtr->owner )
+	{
+	  hwndLocalPrev = w->hwndSelf;
+	  if( hwndLocalPrev == hwndInsertAfter ) break;
+	  w = w->next;
+	}
+	hwndInsertAfter = hwndLocalPrev;
+     }
 
-         if( w->dwStyle & WS_POPUP && w->owner == wndPtr->owner )
-           {
-             bFound = TRUE;
+  }
+  else if( wndPtr->dwStyle & WS_CHILD ) return hwndInsertAfter;
 
-             if( hwndInsertAfter == HWND_TOP )
-               {
-                 hwndInsertAfter = hwndLocalPrev;
-                 break;
-               }
-             hwndNewAfter = hwndLocalPrev;
-           }
+  w = WIN_GetDesktop()->child;
+  while( w )
+  {
+    if( w == wndPtr ) break;
 
-         if( w == wndPtr->owner )
-           {
-             /* basically HWND_BOTTOM */
-             hwndInsertAfter = hwndLocalPrev;
-
-             if( bFound )
-                 hwndInsertAfter = hwndNewAfter;
-             break;
-           }
-
-           if( w != wndPtr )
-               hwndLocalPrev = w->hwndSelf;
-
-           w = w->next;
-        }
-   }
- else 
-   /* or overlapped top-level window... 
-    */
-   if( !(wndPtr->dwStyle & WS_CHILD) )
-      while( w )
-        {
-          if( w == wndPtr ) break;
-
-          if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
-            {
-              SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
-                                        SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
-              hwndInsertAfter = w->hwndSelf;
-            }
-          w = w->next;
-        }
+    if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
+    {
+      SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
+                                SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
+      hwndInsertAfter = w->hwndSelf;
+    }
+    w = w->next;
+  }
 
   return hwndInsertAfter;
 }
@@ -1343,7 +1432,7 @@
    } 
  else			/* bitblt old client area */
    { 
-     HDC   hDC;
+     HDC32 hDC;
      int   update;
      HRGN  updateRgn;
      int   xfrom,yfrom,xto,yto,width,height;
@@ -1386,11 +1475,13 @@
 	 OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top);
 	 CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
 
-         hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn, DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CACHE | DCX_CLIPSIBLINGS);
+         hDC = GetDCEx32( Wnd->parent->hwndSelf, oldVisRgn,
+                          DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
+                          DCX_CACHE | DCX_CLIPSIBLINGS);
 
          BitBlt( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
     
-	 ReleaseDC( Wnd->parent->hwndSelf, hDC); 
+	 ReleaseDC32( Wnd->parent->hwndSelf, hDC); 
        }
 
      if( update != NULLREGION )
@@ -1412,45 +1503,6 @@
 
 
 /***********************************************************************
- *           WINPOS_ForceXWindowRaise
- */
-void WINPOS_ForceXWindowRaise( WND* pWnd )
-{
-    XWindowChanges winChanges;
-    WND *wndStop, *wndLast;
-
-    if (!pWnd->window) return;
-        
-    wndLast = wndStop = pWnd;
-    winChanges.stack_mode = Above;
-    XReconfigureWMWindow( display, pWnd->window, 0, CWStackMode, &winChanges );
-
-    /* Recursively raise owned popups according to their z-order 
-     * (it would be easier with sibling-related Below but it doesn't
-     * work very well with SGI mwm for instance)
-     */
-    while (wndLast)
-    {
-        WND *wnd = WIN_GetDesktop()->child;
-        wndLast = NULL;
-        while (wnd != wndStop)
-        {
-            if (wnd->owner == pWnd &&
-                (wnd->dwStyle & WS_POPUP) &&
-                (wnd->dwStyle & WS_VISIBLE))
-                wndLast = wnd;
-            wnd = wnd->next;
-        }
-        if (wndLast)
-        {
-            WINPOS_ForceXWindowRaise( wndLast );
-            wndStop = wndLast;
-        }
-    }
-}
-
-
-/***********************************************************************
  *           WINPOS_SetXWindowPos
  *
  * SetWindowPos() for an X window. Used by the real SetWindowPos().
@@ -1496,22 +1548,27 @@
     }
     if (!(winpos->flags & SWP_NOZORDER))
     {
+	winChanges.stack_mode = Below;
+	changeMask |= CWStackMode;
+
         if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
-        else winChanges.stack_mode = Below;
-        if ((winpos->hwndInsertAfter != HWND_TOP) &&
-            (winpos->hwndInsertAfter != HWND_BOTTOM))
+        else if (winpos->hwndInsertAfter != HWND_BOTTOM)
         {
-            WND * insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
-            winChanges.sibling = insertPtr->window;
-            changeMask |= CWSibling;
-        }
-        changeMask |= CWStackMode;
+            WND*   insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
+	    Window stack[2];
+
+	    stack[0] = insertPtr->window;
+	    stack[1] = wndPtr->window;
+
+	    /* for stupid window managers (i.e. all of them) */
+
+	    XRestackWindows(display, stack, 2); 
+	    changeMask &= ~CWStackMode;
+	}
     }
     if (!changeMask) return;
-    if (wndPtr->flags & WIN_MANAGED)
-        XReconfigureWMWindow( display, wndPtr->window, 0,
-                              changeMask, &winChanges );
-    else XConfigureWindow( display, wndPtr->window, changeMask, &winChanges );
+
+    XReconfigureWMWindow( display, wndPtr->window, 0, changeMask, &winChanges );
 }
 
 
@@ -1533,7 +1590,7 @@
 						 hwnd, x, y, x+cx, y+cy, flags);  
       /* Check window handle */
 
-    if (hwnd == GetDesktopWindow()) return FALSE;
+    if (hwnd == GetDesktopWindow32()) return FALSE;
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
 
     if (wndPtr->dwStyle & WS_VISIBLE) flags &= ~SWP_SHOWWINDOW;
@@ -1839,7 +1896,7 @@
 	    HWND newActive = hwndPrevActive;
 	    if (!IsWindow(newActive) || (newActive == winpos->hwnd))
 	    {
-		newActive = GetTopWindow( GetDesktopWindow() );
+		newActive = GetTopWindow( GetDesktopWindow32() );
 		if (newActive == winpos->hwnd)
                     newActive = wndPtr->next ? wndPtr->next->hwndSelf : 0;
 	    }	    
@@ -1859,7 +1916,14 @@
     EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
 
     if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
-        PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
+    {
+	RECT32	rect;
+	CONV_RECT16TO32( &oldWindowRect, &rect );
+        PAINT_RedrawWindow( wndPtr->parent->hwndSelf, (wndPtr->flags & WIN_SAVEUNDER_OVERRIDE) 
+			    ? &rect : NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW |
+			  ((wndPtr->flags & WIN_SAVEUNDER_OVERRIDE) ? RDW_INVALIDATE : 0), 0 );
+        wndPtr->flags &= ~WIN_SAVEUNDER_OVERRIDE;
+    }
     else if( wndPtr->parent == WIN_GetDesktop() && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
 	PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
 
@@ -1911,7 +1975,7 @@
 
     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
     if (!pDWP) return 0;
-    if (hwnd == GetDesktopWindow()) return 0;
+    if (hwnd == GetDesktopWindow32()) return 0;
 
       /* All the windows of a DeferWindowPos() must have the same parent */