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/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 */