- One last build fix.
[reactos.git] / reactos / subsys / win32k / ntuser / window.c
index 69cab79..87c43b7 100644 (file)
@@ -16,8 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: window.c,v 1.206 2004/03/31 19:20:18 gvg Exp $
- *
+/*
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * PURPOSE:          Windows
  * REVISION HISTORY:
  *       06-06-2001  CSH  Created
  */
+
 /* INCLUDES ******************************************************************/
 
-#include <ddk/ntddk.h>
-#include <internal/safe.h>
-#include <win32k/win32k.h>
-#include <include/object.h>
-#include <include/guicheck.h>
-#include <include/window.h>
-#include <include/class.h>
-#include <include/error.h>
-#include <include/winsta.h>
-#include <include/desktop.h>
-#include <include/winpos.h>
-#include <include/callback.h>
-#include <include/msgqueue.h>
-#include <include/rect.h>
-#include <include/dce.h>
-#include <include/paint.h>
-#include <include/painting.h>
-#include <include/scroll.h>
-#include <include/vis.h>
-#include <include/menu.h>
-#include <include/hotkey.h>
-#include <include/focus.h>
-#include <include/hook.h>
-#include <include/useratom.h>
-#include <include/tags.h>
-#include <include/timer.h>
+#include <w32k.h>
 
 #define NDEBUG
-#include <win32k/debug1.h>
 #include <debug.h>
 
 static WndProcHandle *WndProcHandlesArray = 0;
 static WORD WndProcHandlesArraySize = 0;
 #define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
 
+/* dialog resources appear to pass this in 16 bits, handle them properly */
+#define CW_USEDEFAULT16        (0x8000)
+
 #define POINT_IN_RECT(p, r) (((r.bottom >= p.y) && (r.top <= p.y))&&((r.left <= p.x )&&( r.right >= p.x )))
 
 /* PRIVATE FUNCTIONS **********************************************************/
@@ -98,20 +75,32 @@ CleanupWindowImpl(VOID)
 
 /* HELPER FUNCTIONS ***********************************************************/
 
+
+
+/* temp hack */
+PWINDOW_OBJECT FASTCALL UserGetWindowObjectNoRef(HWND hWnd)
+{
+   
+   PWINDOW_OBJECT w = IntGetWindowObject(hWnd);
+   if (w) IntReleaseWindowObject(w);
+   return w;
+}
+
+
 /*
  * IntIsWindow
  *
  * The function determines whether the specified window handle identifies
- * an existing window. 
+ * an existing window.
  *
  * Parameters
- *    hWnd 
- *       Handle to the window to test. 
+ *    hWnd
+ *       Handle to the window to test.
  *
  * Return Value
  *    If the window handle identifies an existing window, the return value
  *    is TRUE. If the window handle does not identify an existing window,
- *    the return value is FALSE. 
+ *    the return value is FALSE.
  */
 
 BOOL FASTCALL
@@ -121,7 +110,7 @@ IntIsWindow(HWND hWnd)
 
    if (!(Window = IntGetWindowObject(hWnd)))
       return FALSE;
-   
+
    IntReleaseWindowObject(Window);
    return TRUE;
 }
@@ -133,18 +122,21 @@ IntIsWindow(HWND hWnd)
  */
 
 PWINDOW_OBJECT FASTCALL
-IntGetProcessWindowObject(PW32PROCESS ProcessData, HWND hWnd)
+IntGetProcessWindowObject(PW32THREAD Thread, HWND hWnd)
 {
-   PWINDOW_OBJECT WindowObject;
+   PWINDOW_OBJECT Window;
    NTSTATUS Status;
 
-   Status = ObmReferenceObjectByHandle(ProcessData->WindowStation->HandleTable,
-      hWnd, otWindow, (PVOID*)&WindowObject);
-   if (!NT_SUCCESS(Status))
+   if(Thread->Desktop != NULL)
    {
-      return NULL;
+     Status = ObmReferenceObjectByHandle(gHandleTable,
+                                         hWnd, otWindow, (PVOID*)&Window);
+     if (NT_SUCCESS(Status))
+     {
+        return Window;
+     }
    }
-   return WindowObject;
+   return NULL;
 }
 
 
@@ -152,35 +144,43 @@ PWINDOW_OBJECT FASTCALL
 IntGetParent(PWINDOW_OBJECT Wnd)
 {
   HWND hWnd;
-  
+
   if (Wnd->Style & WS_POPUP)
   {
-    IntLockRelatives(Wnd);
-    hWnd = Wnd->Owner;
-    IntUnLockRelatives(Wnd);
+    hWnd = Wnd->hOwner;
     return IntGetWindowObject(hWnd);
   }
-  else if (Wnd->Style & WS_CHILD) 
+  else if (Wnd->Style & WS_CHILD)
   {
-    IntLockRelatives(Wnd);
-    hWnd = Wnd->Parent;
-    IntUnLockRelatives(Wnd);
-    return IntGetWindowObject(hWnd);
+    PWINDOW_OBJECT par;
+    
+    par = Wnd->Parent;
+    if (par) IntReferenceWindowObject(par);
+    return par;
+    //return IntGetWindowObject(hWnd);
   }
 
   return NULL;
 }
 
+PWINDOW_OBJECT FASTCALL
+IntGetOwner(PWINDOW_OBJECT Wnd)
+{
+  HWND hWnd;
+
+  hWnd = Wnd->hOwner;
+
+  return IntGetWindowObject(hWnd);
+}
 
 PWINDOW_OBJECT FASTCALL
 IntGetParentObject(PWINDOW_OBJECT Wnd)
 {
-  HWND hParent;
+  PWINDOW_OBJECT par;
   
-  IntLockRelatives(Wnd);
-  hParent = Wnd->Parent;
-  IntUnLockRelatives(Wnd);
-  return IntGetWindowObject(hParent);
+  par = Wnd->Parent;
+  if (par) IntReferenceWindowObject(par);
+  return par;
 }
 
 /*
@@ -200,30 +200,23 @@ IntWinListChildren(PWINDOW_OBJECT Window)
    HWND *List;
    UINT Index, NumChildren = 0;
 
-   IntLockRelatives(Window);
-
    for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
       ++NumChildren;
-  
-   if (NumChildren != 0)
+
+   List = ExAllocatePoolWithTag(PagedPool, (NumChildren + 1) * sizeof(HWND), TAG_WINLIST);
+   if(!List)
    {
-      List = ExAllocatePoolWithTag(PagedPool, (NumChildren + 1) * sizeof(HWND), TAG_WINLIST);
-      if(!List)
-      {
-        DPRINT1("Failed to allocate memory for children array\n");
-        IntUnLockRelatives(Window);
-        return NULL;
-      }
-      for (Child = Window->FirstChild, Index = 0;
-           Child != NULL;
-           Child = Child->NextSibling, ++Index)
-         List[Index] = Child->Self;
-      List[Index] = NULL;
+     DPRINT1("Failed to allocate memory for children array\n");
+     SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+     return NULL;
    }
+   for (Child = Window->FirstChild, Index = 0;
+        Child != NULL;
+        Child = Child->NextSibling, ++Index)
+      List[Index] = Child->hSelf;
+   List[Index] = NULL;
 
-   IntUnLockRelatives(Window);
-
-   return (NumChildren > 0) ? List : NULL;
+   return List;
 }
 
 /***********************************************************************
@@ -231,6 +224,8 @@ IntWinListChildren(PWINDOW_OBJECT Window)
  */
 static void IntSendDestroyMsg(HWND Wnd)
 {
+
+  PWINDOW_OBJECT Window, Owner, Parent;
 #if 0 /* FIXME */
   GUITHREADINFO info;
 
@@ -243,10 +238,29 @@ static void IntSendDestroyMsg(HWND Wnd)
     }
 #endif
 
+  Window = IntGetWindowObject(Wnd);
+  if (Window) {
+    Owner = IntGetOwner(Window);
+    if (!Owner) {
+      Parent = IntGetParent(Window);
+      if (!Parent)
+        co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (LPARAM) Wnd);
+      else
+        IntReleaseWindowObject(Parent);
+    } else {
+      IntReleaseWindowObject(Owner);
+    }
+
+    IntReleaseWindowObject(Window);
+  }
+
+  /* The window could already be destroyed here */
+
   /*
    * Send the WM_DESTROY to the window.
    */
-  IntSendMessage(Wnd, WM_DESTROY, 0, 0);
+
+  co_IntSendMessage(Wnd, WM_DESTROY, 0, 0);
 
   /*
    * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
@@ -281,7 +295,7 @@ static void IntSendDestroyMsg(HWND Wnd)
  *
  * Destroy storage associated to a window. "Internals" p.358
  */
-static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
+static LRESULT co_IntDestroyWindow(PWINDOW_OBJECT Window,
                                 PW32PROCESS ProcessData,
                                 PW32THREAD ThreadData,
                                 BOOLEAN SendMessages)
@@ -290,32 +304,30 @@ static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
   HWND *ChildHandle;
   PWINDOW_OBJECT Child;
   PMENU_OBJECT Menu;
-  BOOL BelongsToThreadData;
-  
+  BOOLEAN BelongsToThreadData;
+
   ASSERT(Window);
 
-  RemoveTimersWindow(Window->Self);
-  
-  IntLockThreadWindows(Window->OwnerThread->Win32Thread);
   if(Window->Status & WINDOWSTATUS_DESTROYING)
   {
-    IntUnLockThreadWindows(Window->OwnerThread->Win32Thread);
     DPRINT("Tried to call IntDestroyWindow() twice\n");
     return 0;
   }
   Window->Status |= WINDOWSTATUS_DESTROYING;
+  Window->Flags &= ~WS_VISIBLE;
   /* remove the window already at this point from the thread window list so we
      don't get into trouble when destroying the thread windows while we're still
      in IntDestroyWindow() */
   RemoveEntryList(&Window->ThreadListEntry);
-  IntUnLockThreadWindows(Window->OwnerThread->Win32Thread);
-  
+
   BelongsToThreadData = IntWndBelongsToThread(Window, ThreadData);
-  
+
+  IntDeRegisterShellHookWindow(Window->hSelf);
+
   if(SendMessages)
   {
     /* Send destroy messages */
-    IntSendDestroyMsg(Window->Self);
+    IntSendDestroyMsg(Window->hSelf);
   }
 
   /* free child windows */
@@ -329,59 +341,63 @@ static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
               if(!IntWndBelongsToThread(Child, ThreadData))
               {
                 /* send WM_DESTROY messages to windows not belonging to the same thread */
-                IntSendDestroyMsg(Child->Self);
+                IntSendDestroyMsg(Child->hSelf);
               }
               else
-                IntDestroyWindow(Child, ProcessData, ThreadData, SendMessages);
+                co_IntDestroyWindow(Child, ProcessData, ThreadData, SendMessages);
               IntReleaseWindowObject(Child);
             }
         }
       ExFreePool(Children);
     }
 
-  if (SendMessages)
-    {      
-      /*
-       * Clear the update region to make sure no WM_PAINT messages will be
-       * generated for this window while processing the WM_NCDESTROY.
-       */ 
-      IntRedrawWindow(Window, NULL, 0,
-                      RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE |
-                      RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
+  if(SendMessages)
+  {
+    /*
+     * Clear the update region to make sure no WM_PAINT messages will be
+     * generated for this window while processing the WM_NCDESTROY.
+     */
+    co_UserRedrawWindow(Window, NULL, 0,
+                    RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE |
+                    RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
+    if(BelongsToThreadData)
+      co_IntSendMessage(Window->hSelf, WM_NCDESTROY, 0, 0);
+  }
+  MsqRemoveTimersWindow(ThreadData->MessageQueue, Window->hSelf);
 
-      /*
-       * Send the WM_NCDESTROY to the window being destroyed.
-       */
-      if(BelongsToThreadData)
-        IntSendMessage(Window->Self, WM_NCDESTROY, 0, 0);
-    }
+  /* flush the message queue */
+  MsqRemoveWindowMessagesFromQueue(Window);
+
+  /* from now on no messages can be sent to this window anymore */
+  Window->Status |= WINDOWSTATUS_DESTROYED;
+  /* don't remove the WINDOWSTATUS_DESTROYING bit */
 
   /* reset shell window handles */
-  if(ProcessData->WindowStation)
+  if(ThreadData->Desktop)
   {
-    if (Window->Self == ProcessData->WindowStation->ShellWindow)
-      ProcessData->WindowStation->ShellWindow = NULL;
+    if (Window->hSelf == ThreadData->Desktop->WindowStation->ShellWindow)
+      ThreadData->Desktop->WindowStation->ShellWindow = NULL;
 
-    if (Window->Self == ProcessData->WindowStation->ShellListView)
-      ProcessData->WindowStation->ShellListView = NULL;
+    if (Window->hSelf == ThreadData->Desktop->WindowStation->ShellListView)
+      ThreadData->Desktop->WindowStation->ShellListView = NULL;
   }
-  
+
   /* Unregister hot keys */
   UnregisterWindowHotKeys (Window);
 
   /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
 
 #if 0 /* FIXME */
-  WinPosCheckInternalPos(Window->Self);
-  if (Window->Self == GetCapture())
+  WinPosCheckInternalPos(Window->hSelf);
+  if (Window->hSelf == GetCapture())
     {
       ReleaseCapture();
     }
 
   /* free resources associated with the window */
-  TIMER_RemoveWindowTimers(Window->Self);
+  TIMER_RemoveWindowTimers(Window->hSelf);
 #endif
-  
+
   if (!(Window->Style & WS_CHILD) && Window->IDMenu
       && (Menu = IntGetMenuObject((HMENU)Window->IDMenu)))
     {
@@ -389,7 +405,7 @@ static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
        Window->IDMenu = 0;
        IntReleaseMenuObject(Menu);
     }
-  
+
   if(Window->SystemMenu
      && (Menu = IntGetMenuObject(Window->SystemMenu)))
   {
@@ -397,98 +413,146 @@ static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
     Window->SystemMenu = (HMENU)0;
     IntReleaseMenuObject(Menu);
   }
-  
+
   DceFreeWindowDCE(Window);    /* Always do this to catch orphaned DCs */
 #if 0 /* FIXME */
   WINPROC_FreeProc(Window->winproc, WIN_PROC_WINDOW);
   CLASS_RemoveWindow(Window->Class);
 #endif
-  
+
   IntUnlinkWindow(Window);
-  
+
   IntReferenceWindowObject(Window);
-  ObmCloseHandle(ProcessData->WindowStation->HandleTable, Window->Self);
-  
-  IntDestroyScrollBar(Window, SB_VERT);
-  IntDestroyScrollBar(Window, SB_HORZ);
-  
-  IntLockThreadWindows(Window->OwnerThread->Win32Thread);
-  Window->Status |= WINDOWSTATUS_DESTROYED;
-  /* don't remove the WINDOWSTATUS_DESTROYING bit */
-  IntUnLockThreadWindows(Window->OwnerThread->Win32Thread);
-  
-  ObmDereferenceObject(Window->Class);
+  ObmCloseHandle(gHandleTable, Window->hSelf);
+
+  IntDestroyScrollBars(Window);
+
+  /* remove the window from the class object */
+  RemoveEntryList(&Window->ClassListEntry);
+
+  /* dereference the class */
+  ClassDereferenceObject(Window->Class);
   Window->Class = NULL;
-  
+
   if(Window->WindowRegion)
   {
     NtGdiDeleteObject(Window->WindowRegion);
   }
-  
+
+  RtlFreeUnicodeString(&Window->WindowName);
+
   IntReleaseWindowObject(Window);
 
   return 0;
 }
 
+VOID FASTCALL
+IntGetWindowBorderMeasures(PWINDOW_OBJECT Window, UINT *cx, UINT *cy)
+{
+  if(HAS_DLGFRAME(Window->Style, Window->ExStyle) && !(Window->Style & WS_MINIMIZE))
+  {
+    *cx = UserGetSystemMetrics(SM_CXDLGFRAME);
+    *cy = UserGetSystemMetrics(SM_CYDLGFRAME);
+  }
+  else
+  {
+    if(HAS_THICKFRAME(Window->Style, Window->ExStyle)&& !(Window->Style & WS_MINIMIZE))
+    {
+      *cx = UserGetSystemMetrics(SM_CXFRAME);
+      *cy = UserGetSystemMetrics(SM_CYFRAME);
+    }
+    else if(HAS_THINFRAME(Window->Style, Window->ExStyle))
+    {
+      *cx = UserGetSystemMetrics(SM_CXBORDER);
+      *cy = UserGetSystemMetrics(SM_CYBORDER);
+    }
+    else
+    {
+      *cx = *cy = 0;
+    }
+  }
+}
+
+BOOL FASTCALL
+IntGetWindowInfo(PWINDOW_OBJECT Window, PWINDOWINFO pwi)
+{
+  pwi->cbSize = sizeof(WINDOWINFO);
+  pwi->rcWindow = Window->WindowRect;
+  pwi->rcClient = Window->ClientRect;
+  pwi->dwStyle = Window->Style;
+  pwi->dwExStyle = Window->ExStyle;
+  pwi->dwWindowStatus = (UserGetForegroundWindow() == Window->hSelf); /* WS_ACTIVECAPTION */
+  IntGetWindowBorderMeasures(Window, &pwi->cxWindowBorders, &pwi->cyWindowBorders);
+  pwi->atomWindowType = (Window->Class ? Window->Class->Atom : 0);
+  pwi->wCreatorVersion = 0x400; /* FIXME - return a real version number */
+  return TRUE;
+}
+
 static BOOL FASTCALL
 IntSetMenu(
-   PWINDOW_OBJECT WindowObject,
+   PWINDOW_OBJECT Window,
    HMENU Menu,
    BOOL *Changed)
 {
-  PMENU_OBJECT OldMenuObject, NewMenuObject;
+  PMENU_OBJECT OldMenu, NewMenu = NULL;
+
+  if ((Window->Style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+    {
+      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+      return FALSE;
+    }
 
-  *Changed = (WindowObject->IDMenu != (UINT) Menu);
+  *Changed = (Window->IDMenu != (UINT) Menu);
   if (! *Changed)
     {
       return TRUE;
     }
 
-  if (0 != WindowObject->IDMenu)
+  if (Window->IDMenu)
     {
-      OldMenuObject = IntGetMenuObject((HMENU) WindowObject->IDMenu);
-      ASSERT(NULL == OldMenuObject || OldMenuObject->MenuInfo.Wnd == WindowObject->Self);
+      OldMenu = IntGetMenuObject((HMENU) Window->IDMenu);
+      ASSERT(NULL == OldMenu || OldMenu->MenuInfo.Wnd == Window->hSelf);
     }
   else
     {
-      OldMenuObject = NULL;
+      OldMenu = NULL;
     }
 
   if (NULL != Menu)
     {
-      NewMenuObject = IntGetMenuObject(Menu);
-      if (NULL == NewMenuObject)
+      NewMenu = IntGetMenuObject(Menu);
+      if (NULL == NewMenu)
         {
-          if (NULL != OldMenuObject)
+          if (NULL != OldMenu)
             {
-              IntReleaseMenuObject(OldMenuObject);
+              IntReleaseMenuObject(OldMenu);
             }
           SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
           return FALSE;
         }
-      if (NULL != NewMenuObject->MenuInfo.Wnd)
+      if (NULL != NewMenu->MenuInfo.Wnd)
         {
           /* Can't use the same menu for two windows */
-          if (NULL != OldMenuObject)
+          if (NULL != OldMenu)
             {
-              IntReleaseMenuObject(OldMenuObject);
+              IntReleaseMenuObject(OldMenu);
             }
           SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
           return FALSE;
         }
+
     }
 
-  WindowObject->IDMenu = (UINT) Menu;
-  if (NULL != NewMenuObject)
+  Window->IDMenu = (UINT) Menu;
+  if (NULL != NewMenu)
     {
-      NewMenuObject->MenuInfo.Wnd = WindowObject->Self;
-      IntReleaseMenuObject(NewMenuObject);
+      NewMenu->MenuInfo.Wnd = Window->hSelf;
+      IntReleaseMenuObject(NewMenu);
     }
-  if (NULL != OldMenuObject)
+  if (NULL != OldMenu)
     {
-      OldMenuObject->MenuInfo.Wnd = NULL;
-      IntReleaseMenuObject(OldMenuObject);
+      OldMenu->MenuInfo.Wnd = NULL;
+      IntReleaseMenuObject(OldMenu);
     }
 
   return TRUE;
@@ -499,7 +563,7 @@ IntSetMenu(
 
 
 VOID FASTCALL
-DestroyThreadWindows(struct _ETHREAD *Thread)
+co_DestroyThreadWindows(struct _ETHREAD *Thread)
 {
   PLIST_ENTRY Current;
   PW32PROCESS Win32Process;
@@ -507,24 +571,22 @@ DestroyThreadWindows(struct _ETHREAD *Thread)
   PWINDOW_OBJECT *List, *pWnd;
   ULONG Cnt = 0;
 
-  Win32Thread = Thread->Win32Thread;
-  Win32Process = Thread->ThreadsProcess->Win32Process;
-  
-  IntLockThreadWindows(Win32Thread);
+  Win32Thread = Thread->Tcb.Win32Thread;
+  Win32Process = (PW32PROCESS)Thread->ThreadsProcess->Win32Process;
+
   Current = Win32Thread->WindowListHead.Flink;
   while (Current != &(Win32Thread->WindowListHead))
   {
     Cnt++;
     Current = Current->Flink;
   }
-  
+
   if(Cnt > 0)
   {
     List = ExAllocatePool(PagedPool, (Cnt + 1) * sizeof(PWINDOW_OBJECT));
     if(!List)
     {
       DPRINT("Not enough memory to allocate window handle list\n");
-      IntUnLockThreadWindows(Win32Thread);
       return;
     }
     pWnd = List;
@@ -536,19 +598,17 @@ DestroyThreadWindows(struct _ETHREAD *Thread)
       pWnd++;
       Current = Current->Flink;
     }
-    IntUnLockThreadWindows(Win32Thread);
     *pWnd = NULL;
-    
+
     for(pWnd = List; *pWnd; pWnd++)
     {
-      NtUserDestroyWindow((*pWnd)->Self);
+      co_UserDestroyWindow(*pWnd);
       IntReleaseWindowObject(*pWnd);
     }
     ExFreePool(List);
     return;
   }
-  
-  IntUnLockThreadWindows(Win32Thread);
+
 }
 
 
@@ -559,14 +619,14 @@ DestroyThreadWindows(struct _ETHREAD *Thread)
  * \note Does not check the validity of the parameters
 */
 VOID FASTCALL
-IntGetClientRect(PWINDOW_OBJECT WindowObject, PRECT Rect)
+IntGetClientRect(PWINDOW_OBJECT Window, PRECT Rect)
 {
-  ASSERT( WindowObject );
+  ASSERT( Window );
   ASSERT( Rect );
 
   Rect->left = Rect->top = 0;
-  Rect->right = WindowObject->ClientRect.right - WindowObject->ClientRect.left;
-  Rect->bottom = WindowObject->ClientRect.bottom - WindowObject->ClientRect.top;
+  Rect->right = Window->ClientRect.right - Window->ClientRect.left;
+  Rect->bottom = Window->ClientRect.bottom - Window->ClientRect.top;
 }
 
 
@@ -590,85 +650,85 @@ IntGetFocusWindow(VOID)
 #endif
 
 PMENU_OBJECT FASTCALL
-IntGetSystemMenu(PWINDOW_OBJECT WindowObject, BOOL bRevert, BOOL RetMenu)
+IntGetSystemMenu(PWINDOW_OBJECT Window, BOOL bRevert, BOOL RetMenu)
 {
-  PMENU_OBJECT MenuObject, NewMenuObject, SysMenuObject, ret = NULL;
-  PW32PROCESS W32Process;
-  HMENU NewMenu, SysMenu;
+  PMENU_OBJECT Menu, NewMenu = NULL, SysMenu = NULL, ret = NULL;
+  PW32THREAD W32Thread;
+  HMENU hNewMenu, hSysMenu;
   ROSMENUITEMINFO ItemInfo;
 
   if(bRevert)
   {
-    W32Process = PsGetWin32Process();
-    
-    if(!W32Process->WindowStation)
+    W32Thread = PsGetWin32Thread();
+
+    if(!W32Thread->Desktop)
       return NULL;
-      
-    if(WindowObject->SystemMenu)
+
+    if(Window->SystemMenu)
     {
-      MenuObject = IntGetMenuObject(WindowObject->SystemMenu);
-      if(MenuObject)
+      Menu = IntGetMenuObject(Window->SystemMenu);
+      if(Menu)
       {
-        IntDestroyMenuObject(MenuObject, FALSE, TRUE);
-        WindowObject->SystemMenu = (HMENU)0;
-        IntReleaseMenuObject(MenuObject);
+        IntDestroyMenuObject(Menu, FALSE, TRUE);
+        Window->SystemMenu = (HMENU)0;
+        IntReleaseMenuObject(Menu);
       }
     }
-      
-    if(W32Process->WindowStation->SystemMenuTemplate)
+
+    if(W32Thread->Desktop->WindowStation->SystemMenuTemplate)
     {
       /* clone system menu */
-      MenuObject = IntGetMenuObject(W32Process->WindowStation->SystemMenuTemplate);
-      if(!MenuObject)
+      Menu = IntGetMenuObject(W32Thread->Desktop->WindowStation->SystemMenuTemplate);
+      if(!Menu)
         return NULL;
 
-      NewMenuObject = IntCloneMenu(MenuObject);
-      if(NewMenuObject)
+      NewMenu = IntCloneMenu(Menu);
+      if(NewMenu)
       {
-        WindowObject->SystemMenu = NewMenuObject->MenuInfo.Self;
-        NewMenuObject->MenuInfo.Flags |= MF_SYSMENU;
-        NewMenuObject->MenuInfo.Wnd = WindowObject->Self;
-        ret = NewMenuObject;
+        Window->SystemMenu = NewMenu->MenuInfo.Self;
+        NewMenu->MenuInfo.Flags |= MF_SYSMENU;
+        NewMenu->MenuInfo.Wnd = Window->hSelf;
+        ret = NewMenu;
         //IntReleaseMenuObject(NewMenuObject);
       }
-      IntReleaseMenuObject(MenuObject);
+      IntReleaseMenuObject(Menu);
     }
     else
     {
-      SysMenu = NtUserCreateMenu(FALSE);
+      hSysMenu = UserCreateMenu(FALSE);
       if (NULL == SysMenu)
       {
         return NULL;
       }
-      SysMenuObject = IntGetMenuObject(SysMenu);
-      if (NULL == SysMenuObject)
+      SysMenu = IntGetMenuObject(hSysMenu);
+      if (NULL == SysMenu)
       {
-        NtUserDestroyMenu(SysMenu);
+        UserDestroyMenu(hSysMenu);
         return NULL;
       }
-      SysMenuObject->MenuInfo.Flags |= MF_SYSMENU;
-      SysMenuObject->MenuInfo.Wnd = WindowObject->Self;
-      NewMenu = IntLoadSysMenuTemplate();
+      SysMenu->MenuInfo.Flags |= MF_SYSMENU;
+      SysMenu->MenuInfo.Wnd = Window->hSelf;
+      hNewMenu = co_IntLoadSysMenuTemplate();
       if(!NewMenu)
       {
-        IntReleaseMenuObject(SysMenuObject);
-        NtUserDestroyMenu(SysMenu);
+        IntReleaseMenuObject(SysMenu);
+        UserDestroyMenu(hSysMenu);
         return NULL;
       }
-      MenuObject = IntGetMenuObject(NewMenu);
-      if(!MenuObject)
+      Menu = IntGetMenuObject(hNewMenu);
+      if(!Menu)
       {
-        IntReleaseMenuObject(SysMenuObject);
-        NtUserDestroyMenu(SysMenu);
+        IntReleaseMenuObject(SysMenu);
+        UserDestroyMenu(hSysMenu);
         return NULL;
       }
-      
-      NewMenuObject = IntCloneMenu(MenuObject);
-      if(NewMenuObject)
+
+      NewMenu = IntCloneMenu(Menu);
+      if(NewMenu)
       {
-        NewMenuObject->MenuInfo.Flags |= MF_SYSMENU | MF_POPUP;
-        IntReleaseMenuObject(NewMenuObject);
-       NtUserSetMenuDefaultItem(NewMenuObject->MenuInfo.Self, SC_CLOSE, FALSE);
+        NewMenu->MenuInfo.Flags |= MF_SYSMENU | MF_POPUP;
+        IntReleaseMenuObject(NewMenu);
+        UserSetMenuDefaultItem(NewMenu->MenuInfo.Self, SC_CLOSE, FALSE);
 
         ItemInfo.cbSize = sizeof(MENUITEMINFOW);
         ItemInfo.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_SUBMENU;
@@ -676,15 +736,15 @@ IntGetSystemMenu(PWINDOW_OBJECT WindowObject, BOOL bRevert, BOOL RetMenu)
         ItemInfo.fState = MFS_ENABLED;
         ItemInfo.dwTypeData = NULL;
         ItemInfo.cch = 0;
-        ItemInfo.hSubMenu = NewMenuObject->MenuInfo.Self;
-        IntInsertMenuItem(SysMenuObject, (UINT) -1, TRUE, &ItemInfo);
+        ItemInfo.hSubMenu = NewMenu->MenuInfo.Self;
+        IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo);
 
-        WindowObject->SystemMenu = SysMenuObject->MenuInfo.Self;
+        Window->SystemMenu = SysMenu->MenuInfo.Self;
 
-        ret = SysMenuObject;
+        ret = SysMenu;
       }
-      IntDestroyMenuObject(MenuObject, FALSE, TRUE);
-      IntReleaseMenuObject(MenuObject);
+      IntDestroyMenuObject(Menu, FALSE, TRUE);
+      IntReleaseMenuObject(Menu);
     }
     if(RetMenu)
       return ret;
@@ -693,8 +753,8 @@ IntGetSystemMenu(PWINDOW_OBJECT WindowObject, BOOL bRevert, BOOL RetMenu)
   }
   else
   {
-    if(WindowObject->SystemMenu)
-      return IntGetMenuObject((HMENU)WindowObject->SystemMenu);
+    if(Window->SystemMenu)
+      return IntGetMenuObject((HMENU)Window->SystemMenu);
     else
       return NULL;
   }
@@ -704,49 +764,41 @@ IntGetSystemMenu(PWINDOW_OBJECT WindowObject, BOOL bRevert, BOOL RetMenu)
 BOOL FASTCALL
 IntIsChildWindow(HWND Parent, HWND Child)
 {
-  PWINDOW_OBJECT BaseWindow, Window, Old;
-  
-  if(!(BaseWindow = IntGetWindowObject(Child)))
+  PWINDOW_OBJECT BaseWindow, Window;
+
+  if(!(BaseWindow = UserGetWindowObjectNoRef(Child)))
   {
     return FALSE;
   }
-  
+
   Window = BaseWindow;
   while (Window)
   {
-    if (Window->Self == Parent)
+    if (Window->hSelf == Parent)
     {
-      if(Window != BaseWindow)
-        IntReleaseWindowObject(Window);
-      IntReleaseWindowObject(BaseWindow);
       return(TRUE);
     }
     if(!(Window->Style & WS_CHILD))
     {
-      if(Window != BaseWindow)
-        IntReleaseWindowObject(Window);
       break;
     }
-    Old = Window;
-    Window = IntGetParentObject(Window);
-    if(Old != BaseWindow)
-      IntReleaseWindowObject(Old);
+
+    Window = Window->Parent;
   }
-  
-  IntReleaseWindowObject(BaseWindow);
-  return(FALSE);  
+
+  return(FALSE);
 }
 
 BOOL FASTCALL
 IntIsWindowVisible(HWND hWnd)
 {
   PWINDOW_OBJECT BaseWindow, Window, Old;
-  
+
   if(!(BaseWindow = IntGetWindowObject(hWnd)))
   {
     return FALSE;
   }
-  
+
   Window = BaseWindow;
   while(Window)
   {
@@ -766,7 +818,7 @@ IntIsWindowVisible(HWND hWnd)
     if(Old != BaseWindow)
       IntReleaseWindowObject(Old);
   }
-  
+
   if(Window)
   {
     if(Window->Style & WS_VISIBLE)
@@ -787,55 +839,44 @@ IntIsWindowVisible(HWND hWnd)
 /* link the window into siblings and parent. children are kept in place. */
 VOID FASTCALL
 IntLinkWindow(
-  PWINDOW_OBJECT Wnd, 
+  PWINDOW_OBJECT Wnd,
   PWINDOW_OBJECT WndParent,
   PWINDOW_OBJECT WndPrevSibling /* set to NULL if top sibling */
   )
 {
   PWINDOW_OBJECT Parent;
-  
-  IntLockRelatives(Wnd);
-  Wnd->Parent = WndParent->Self;
+
+  Wnd->Parent = WndParent;
   if ((Wnd->PrevSibling = WndPrevSibling))
   {
     /* link after WndPrevSibling */
     if ((Wnd->NextSibling = WndPrevSibling->NextSibling))
       Wnd->NextSibling->PrevSibling = Wnd;
-    else if ((Parent = IntGetWindowObject(Wnd->Parent)))
+    else if ((Parent = Wnd->Parent))
     {
-      IntLockRelatives(Parent);
-      if(Parent->LastChild == WndPrevSibling) 
+      if(Parent->LastChild == WndPrevSibling)
         Parent->LastChild = Wnd;
-      IntUnLockRelatives(Parent);
-      IntReleaseWindowObject(Parent);
     }
     Wnd->PrevSibling->NextSibling = Wnd;
   }
   else
   {
     /* link at top */
-    Parent = IntGetWindowObject(Wnd->Parent);
-    if ((Wnd->NextSibling = WndParent->FirstChild)) 
+    Parent = Wnd->Parent;
+    if ((Wnd->NextSibling = WndParent->FirstChild))
       Wnd->NextSibling->PrevSibling = Wnd;
     else if (Parent)
     {
-      IntLockRelatives(Parent);
       Parent->LastChild = Wnd;
       Parent->FirstChild = Wnd;
-      IntUnLockRelatives(Parent);
-      IntReleaseWindowObject(Parent);
-      IntUnLockRelatives(Wnd);
       return;
     }
     if(Parent)
     {
-      IntLockRelatives(Parent);
       Parent->FirstChild = Wnd;
-      IntUnLockRelatives(Parent);
-      IntReleaseWindowObject(Parent);
     }
   }
-  IntUnLockRelatives(Wnd);
+
 }
 
 HWND FASTCALL
@@ -843,32 +884,30 @@ IntSetOwner(HWND hWnd, HWND hWndNewOwner)
 {
   PWINDOW_OBJECT Wnd, WndOldOwner, WndNewOwner;
   HWND ret;
-  
+
   Wnd = IntGetWindowObject(hWnd);
   if(!Wnd)
     return NULL;
-  
-  IntLockRelatives(Wnd);
-  WndOldOwner = IntGetWindowObject(Wnd->Owner);
+
+  WndOldOwner = IntGetWindowObject(Wnd->hOwner);
   if (WndOldOwner)
   {
-     ret = WndOldOwner->Self;
+     ret = WndOldOwner->hSelf;
      IntReleaseWindowObject(WndOldOwner);
   }
   else
   {
      ret = 0;
   }
-  
+
   if((WndNewOwner = IntGetWindowObject(hWndNewOwner)))
   {
-    Wnd->Owner = hWndNewOwner;
+    Wnd->hOwner = hWndNewOwner;
     IntReleaseWindowObject(WndNewOwner);
   }
   else
-    Wnd->Owner = NULL;
-  
-  IntUnLockRelatives(Wnd);
+    Wnd->hOwner = NULL;
+
   IntReleaseWindowObject(Wnd);
   return ret;
 }
@@ -880,18 +919,18 @@ IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
    HWND hWnd, hWndNewParent, hWndOldParent;
    BOOL WasVisible;
    BOOL MenuChanged;
-   
+
    ASSERT(Wnd);
    ASSERT(WndNewParent);
-   
-   hWnd = Wnd->Self;
-   hWndNewParent = WndNewParent->Self;
+
+   hWnd = Wnd->hSelf;
+   hWndNewParent = WndNewParent->hSelf;
 
    /*
     * Windows hides the window first, then shows it again
     * including the WM_SHOWWINDOW messages and all
     */
-   WasVisible = WinPosShowWindow(hWnd, SW_HIDE);
+   WasVisible = co_WinPosShowWindow(hWnd, SW_HIDE);
 
    /* Validate that window and parent still exist */
    if (!IntIsWindow(hWnd) || !IntIsWindow(hWndNewParent))
@@ -902,7 +941,7 @@ IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
       return NULL;
 
    WndOldParent = IntGetParentObject(Wnd);
-   hWndOldParent = (WndOldParent ? WndOldParent->Self : NULL);
+   hWndOldParent = (WndOldParent ? WndOldParent->hSelf : NULL);
 
    if (WndNewParent != WndOldParent)
    {
@@ -911,14 +950,12 @@ IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
       if (0 == (Wnd->ExStyle & WS_EX_TOPMOST))
       {
         /* Not a TOPMOST window, put after TOPMOSTs of new parent */
-        IntLockRelatives(WndNewParent);
         Sibling = WndNewParent->FirstChild;
         while (NULL != Sibling && 0 != (Sibling->ExStyle & WS_EX_TOPMOST))
         {
           InsertAfter = Sibling;
           Sibling = Sibling->NextSibling;
         }
-        IntUnLockRelatives(WndNewParent);
       }
       if (NULL == InsertAfter)
       {
@@ -931,7 +968,7 @@ IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
         IntReleaseWindowObject(InsertAfter);
       }
 
-      if (WndNewParent->Self != IntGetDesktopWindow()) /* a child window */
+      if (WndNewParent->hSelf != IntGetDesktopWindow()) /* a child window */
       {
          if (!(Wnd->Style & WS_CHILD))
          {
@@ -940,13 +977,13 @@ IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
          }
       }
    }
-   
+
    /*
     * SetParent additionally needs to make hwnd the top window
     * in the z-order and send the expected WM_WINDOWPOSCHANGING and
     * WM_WINDOWPOSCHANGED notification messages.
     */
-   WinPosSetWindowPos(hWnd, (0 == (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOP : HWND_TOPMOST),
+   co_WinPosSetWindowPos(hWnd, (0 == (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOP : HWND_TOPMOST),
                       0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE
                                 | (WasVisible ? SWP_SHOWWINDOW : 0));
 
@@ -954,19 +991,19 @@ IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
     * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
     * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
     */
-   
+
    /*
     * Validate that the old parent still exist, since it migth have been
-    * destroyed during the last callbacks to user-mode 
+    * destroyed during the last callbacks to user-mode
     */
    if(WndOldParent)
    {
-     if(!IntIsWindow(WndOldParent->Self))
+     if(!IntIsWindow(WndOldParent->hSelf))
      {
        IntReleaseWindowObject(WndOldParent);
        return NULL;
      }
-     
+
      /* don't dereference the window object here, it must be done by the caller
         of IntSetParent() */
      return WndOldParent;
@@ -975,28 +1012,28 @@ IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
 }
 
 BOOL FASTCALL
-IntSetSystemMenu(PWINDOW_OBJECT WindowObject, PMENU_OBJECT MenuObject)
+IntSetSystemMenu(PWINDOW_OBJECT Window, PMENU_OBJECT Menu)
 {
-  PMENU_OBJECT OldMenuObject;
-  if(WindowObject->SystemMenu)
+  PMENU_OBJECT OldMenu;
+  if(Window->SystemMenu)
   {
-    OldMenuObject = IntGetMenuObject(WindowObject->SystemMenu);
-    if(OldMenuObject)
+    OldMenu = IntGetMenuObject(Window->SystemMenu);
+    if(OldMenu)
     {
-      OldMenuObject->MenuInfo.Flags &= ~ MF_SYSMENU;
-      IntReleaseMenuObject(OldMenuObject);
+      OldMenu->MenuInfo.Flags &= ~ MF_SYSMENU;
+      IntReleaseMenuObject(OldMenu);
     }
   }
-  
-  if(MenuObject)
+
+  if(Menu)
   {
     /* FIXME check window style, propably return FALSE ? */
-    WindowObject->SystemMenu = MenuObject->MenuInfo.Self;
-    MenuObject->MenuInfo.Flags |= MF_SYSMENU;
+    Window->SystemMenu = Menu->MenuInfo.Self;
+    Menu->MenuInfo.Flags |= MF_SYSMENU;
   }
   else
-    WindowObject->SystemMenu = (HMENU)0;
-  
+    Window->SystemMenu = (HMENU)0;
+
   return TRUE;
 }
 
@@ -1005,27 +1042,49 @@ IntSetSystemMenu(PWINDOW_OBJECT WindowObject, PMENU_OBJECT MenuObject)
 VOID FASTCALL
 IntUnlinkWindow(PWINDOW_OBJECT Wnd)
 {
-  PWINDOW_OBJECT WndParent;
-  
-  IntLockRelatives(Wnd);
-  if((WndParent = IntGetWindowObject(Wnd->Parent)))
-  {
-    IntLockRelatives(WndParent);
-  }
-  
+  PWINDOW_OBJECT WndParent = Wnd->Parent;
+
   if (Wnd->NextSibling) Wnd->NextSibling->PrevSibling = Wnd->PrevSibling;
   else if (WndParent && WndParent->LastChild == Wnd) WndParent->LastChild = Wnd->PrevSibling;
+
   if (Wnd->PrevSibling) Wnd->PrevSibling->NextSibling = Wnd->NextSibling;
   else if (WndParent && WndParent->FirstChild == Wnd) WndParent->FirstChild = Wnd->NextSibling;
-  
-  if(WndParent)
+
+  Wnd->PrevSibling = Wnd->NextSibling = Wnd->Parent = NULL;
+}
+
+BOOL FASTCALL
+IntAnyPopup(VOID)
+{
+  PWINDOW_OBJECT Window, Child;
+
+  if(!(Window = IntGetWindowObject(IntGetDesktopWindow())))
   {
-    IntUnLockRelatives(WndParent);
-    IntReleaseWindowObject(WndParent);
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    return FALSE;
   }
-  Wnd->PrevSibling = Wnd->NextSibling = Wnd->Parent = NULL;
-  IntUnLockRelatives(Wnd);
+
+  for(Child = Window->FirstChild; Child; Child = Child->NextSibling)
+  {
+    if(Child->hOwner && Child->Style & WS_VISIBLE)
+    {
+      /*
+       * The desktop has a popup window if one of them has
+       * an owner window and is visible
+       */
+      IntReleaseWindowObject(Window);
+      return TRUE;
+    }
+  }
+
+  IntReleaseWindowObject(Window);
+  return FALSE;
+}
+
+BOOL FASTCALL
+IntIsWindowInDestroy(PWINDOW_OBJECT Window)
+{
+  return ((Window->Status & WINDOWSTATUS_DESTROYING) == WINDOWSTATUS_DESTROYING);
 }
 
 /* FUNCTIONS *****************************************************************/
@@ -1066,121 +1125,126 @@ NtUserBuildHwndList(
   HWND* pWnd,
   ULONG nBufSize)
 {
+  NTSTATUS Status;
   ULONG dwCount = 0;
 
   /* FIXME handle bChildren */
-  if ( hwndParent )
+
+  if(hwndParent)
+  {
+    PWINDOW_OBJECT Window, Child;
+    if(!(Window = IntGetWindowObject(hwndParent)))
     {
-      PWINDOW_OBJECT WindowObject = NULL;
-      PWINDOW_OBJECT Child;
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return 0;
+    }
 
-      WindowObject = IntGetWindowObject ( hwndParent );
-      if ( !WindowObject )
-       {
-         DPRINT("Bad window handle 0x%x\n", hwndParent);
-         SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-         return 0;
-       }
+    for(Child = Window->FirstChild; Child != NULL; Child = Child->NextSibling)
+    {
+      if(dwCount++ < nBufSize && pWnd)
+      {
+        Status = MmCopyToCaller(pWnd++, &Child->hSelf, sizeof(HWND));
+        if(!NT_SUCCESS(Status))
+        {
+          SetLastNtError(Status);
+          break;
+        }
+      }
+    }
 
-      IntLockRelatives(WindowObject );
-      Child = WindowObject->FirstChild;
-      while (Child)
-       {
-         if ( pWnd && dwCount < nBufSize )
-           pWnd[dwCount] = Child->Self;
-         dwCount++;
-    Child = Child->NextSibling;
-       }
-      IntUnLockRelatives(WindowObject);
-      IntReleaseWindowObject ( WindowObject );
-    }
-  else if ( dwThreadId )
-    {
-      NTSTATUS Status;
-      struct _ETHREAD* Thread;
-      struct _EPROCESS* ThreadsProcess;
-      struct _W32PROCESS*   Win32Process;
-      struct _WINSTATION_OBJECT* WindowStation;
-      PUSER_HANDLE_TABLE HandleTable;
-      PLIST_ENTRY Current;
-      PUSER_HANDLE_BLOCK Block = NULL;
-      ULONG i;
-
-      Status = PsLookupThreadByThreadId ( (PVOID)dwThreadId, &Thread );
-      if ( !NT_SUCCESS(Status) || !Thread )
-       {
-         DPRINT("Bad ThreadId 0x%x\n", dwThreadId );
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return 0;
-       }
-      ThreadsProcess = Thread->ThreadsProcess;
-      ASSERT(ThreadsProcess);
-      Win32Process = ThreadsProcess->Win32Process;
-      ASSERT(Win32Process);
-      WindowStation = Win32Process->WindowStation;
-      ASSERT(WindowStation);
-      HandleTable = (PUSER_HANDLE_TABLE)(WindowStation->HandleTable);
-      ASSERT(HandleTable);
+    IntReleaseWindowObject(Window);
+  }
+  else if(dwThreadId)
+  {
+    PETHREAD Thread;
+    PW32THREAD W32Thread;
+    PLIST_ENTRY Current;
+    PWINDOW_OBJECT Window;
 
+    Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
+    if(!NT_SUCCESS(Status))
+    {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return 0;
+    }
+    if(!(W32Thread = Thread->Tcb.Win32Thread))
+    {
       ObDereferenceObject(Thread);
+      DPRINT("Thread is not a GUI Thread!\n");
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return 0;
+    }
 
-      ObmpLockHandleTable(HandleTable);
-
-      Current = HandleTable->ListHead.Flink;
-      while ( Current != &HandleTable->ListHead )
-       {
-         Block = CONTAINING_RECORD(Current, USER_HANDLE_BLOCK, ListEntry);
-         for ( i = 0; i < HANDLE_BLOCK_ENTRIES; i++ )
-           {
-             PVOID ObjectBody = Block->Handles[i].ObjectBody;
-             if ( ObjectBody )
-             {
-               if ( pWnd && dwCount < nBufSize )
-                 {
-                   pWnd[dwCount] =
-                     (HWND)IntReferenceWindowObject(ObjectBody);
-                 }
-               dwCount++;
-             }
-           }
-         Current = Current->Flink;
-       }
+    Current = W32Thread->WindowListHead.Flink;
+    while(Current != &(W32Thread->WindowListHead))
+    {
+      Window = CONTAINING_RECORD(Current, WINDOW_OBJECT, ThreadListEntry);
+      ASSERT(Window);
 
-      ObmpUnlockHandleTable(HandleTable);
+      if(dwCount < nBufSize && pWnd)
+      {
+        Status = MmCopyToCaller(pWnd++, &Window->hSelf, sizeof(HWND));
+        if(!NT_SUCCESS(Status))
+        {
+          SetLastNtError(Status);
+          break;
+        }
+      }
+      dwCount++;
+      Current = Current->Flink;
     }
+
+    ObDereferenceObject(Thread);
+  }
   else
+  {
+    PDESKTOP_OBJECT Desktop;
+    PWINDOW_OBJECT Window, Child;
+
+    if(hDesktop == NULL && !(Desktop = IntGetActiveDesktop()))
     {
-      PDESKTOP_OBJECT DesktopObject = NULL;
-      KIRQL OldIrql;
-      PWINDOW_OBJECT Child, WndDesktop;
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return 0;
+    }
 
-#if 0
-      if ( hDesktop )
-       DesktopObject = IntGetDesktopObject ( hDesktop );
-      else
-#endif
-       DesktopObject = IntGetActiveDesktop();
-      if (!DesktopObject)
-       {
-         DPRINT("Bad desktop handle 0x%x\n", hDesktop );
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return 0;
-       }
-
-      KeAcquireSpinLock ( &DesktopObject->Lock, &OldIrql );
+    if(hDesktop)
+    {
+      Status = IntValidateDesktopHandle(hDesktop,
+                                        UserMode,
+                                        0,
+                                        &Desktop);
+      if(!NT_SUCCESS(Status))
+      {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return 0;
+      }
+    }
+    if(!(Window = IntGetWindowObject(Desktop->DesktopWindow)))
+    {
+      if(hDesktop)
+        ObDereferenceObject(Desktop);
+      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+      return 0;
+    }
 
-      WndDesktop = IntGetWindowObject(DesktopObject->DesktopWindow);
-      Child = (WndDesktop ? WndDesktop->FirstChild : NULL);
-      while (Child)
-       {
-         if ( pWnd && dwCount < nBufSize )
-           pWnd[dwCount] = Child->Self;
-         dwCount++;
-    Child = Child->NextSibling;
-       }
-      KeReleaseSpinLock ( &DesktopObject->Lock, OldIrql );
+    for(Child = Window->FirstChild; Child != NULL; Child = Child->NextSibling)
+    {
+      if(dwCount++ < nBufSize && pWnd)
+      {
+        Status = MmCopyToCaller(pWnd++, &Child->hSelf, sizeof(HWND));
+        if(!NT_SUCCESS(Status))
+        {
+          SetLastNtError(Status);
+          break;
+        }
+      }
     }
 
+    IntReleaseWindowObject(Window);
+    if(hDesktop)
+      ObDereferenceObject(Desktop);
+  }
+
   return dwCount;
 }
 
@@ -1188,76 +1252,122 @@ NtUserBuildHwndList(
 /*
  * @implemented
  */
- /* FIXME - NEEDS TO BE FIXED - UNSAFE !!! */
 HWND STDCALL
 NtUserChildWindowFromPointEx(HWND hwndParent,
                             LONG x,
                             LONG y,
                             UINT uiFlags)
 {
-    PWINDOW_OBJECT pParent, pCurrent, pLast, pPar;
-    POINT p = {x,y};
-    RECT rc;
-    BOOL bFirstRun = TRUE; 
-     
-    if(hwndParent)
+  PWINDOW_OBJECT Parent;
+  POINTL Pt;
+  HWND Ret;
+  HWND *List, *phWnd;
+
+  if(!(Parent = IntGetWindowObject(hwndParent)))
+  {
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    return NULL;
+  }
+
+  Pt.x = x;
+  Pt.y = y;
+
+  if(Parent->hSelf != IntGetDesktopWindow())
+  {
+    Pt.x += Parent->ClientRect.left;
+    Pt.y += Parent->ClientRect.top;
+  }
+
+  if(!IntPtInWindow(Parent, Pt.x, Pt.y))
+  {
+    IntReleaseWindowObject(Parent);
+    return NULL;
+  }
+
+  Ret = Parent->hSelf;
+  if((List = IntWinListChildren(Parent)))
+  {
+    for(phWnd = List; *phWnd; phWnd++)
     {
-        pParent = IntGetWindowObject(hwndParent);
-        if(pParent)
+      PWINDOW_OBJECT Child;
+      if((Child = IntGetWindowObject(*phWnd)))
+      {
+        if(!(Child->Style & WS_VISIBLE) && (uiFlags & CWP_SKIPINVISIBLE))
         {
-            IntLockRelatives(pParent);
-            
-            pLast = IntGetWindowObject(pParent->LastChild->Self);
-            pCurrent = IntGetWindowObject(pParent->FirstChild->Self);
-            
-            do
-            {
-                if (!bFirstRun)
-                {
-                    pCurrent = IntGetWindowObject(pCurrent->NextSibling->Self);
-                    
-                }
-                else
-                    bFirstRun = FALSE;
-                if(!pCurrent)
-                {
-                    IntUnLockRelatives(pParent);
-                    return (HWND)NULL;
-                }
-                if(!(pPar = IntGetWindowObject(pCurrent->Parent)))
-                {
-                    IntUnLockRelatives(pParent);
-                    return (HWND)NULL;
-                }
-                rc.left = pCurrent->WindowRect.left - pPar->ClientRect.left;
-                rc.top = pCurrent->WindowRect.top - pPar->ClientRect.top;
-                rc.right = rc.left + (pCurrent->WindowRect.right - pCurrent->WindowRect.left);
-                rc.bottom = rc.top + (pCurrent->WindowRect.bottom - pCurrent->WindowRect.top);
-                DbgPrint("Rect:  %i,%i,%i,%i\n",rc.left, rc.top, rc.right, rc.bottom);
-                IntReleaseWindowObject(pPar);
-                if (POINT_IN_RECT(p,rc)) /* Found a match */
-                {
-                    if ( (uiFlags & CWP_SKIPDISABLED) && (pCurrent->Style & WS_DISABLED) )
-                        continue;
-                    if( (uiFlags & CWP_SKIPTRANSPARENT) && (pCurrent->ExStyle & WS_EX_TRANSPARENT) )
-                        continue;
-                    if( (uiFlags & CWP_SKIPINVISIBLE) && !(pCurrent->Style & WS_VISIBLE) )
-                        continue;
-
-                    IntUnLockRelatives(pParent);                  
-                    return pCurrent->Self;
-                }
-            }
-            while(pCurrent != pLast);
-            
-            IntUnLockRelatives(pParent);
-            return (HWND)NULL;
+          IntReleaseWindowObject(Child);
+          continue;
         }
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        if((Child->Style & WS_DISABLED) && (uiFlags & CWP_SKIPDISABLED))
+        {
+          IntReleaseWindowObject(Child);
+          continue;
+        }
+        if((Child->ExStyle & WS_EX_TRANSPARENT) && (uiFlags & CWP_SKIPTRANSPARENT))
+        {
+          IntReleaseWindowObject(Child);
+          continue;
+        }
+        if(IntPtInWindow(Child, Pt.x, Pt.y))
+        {
+          Ret = Child->hSelf;
+          IntReleaseWindowObject(Child);
+          break;
+        }
+        IntReleaseWindowObject(Child);
+      }
     }
+    ExFreePool(List);
+  }
+
+  IntReleaseWindowObject(Parent);
+  return Ret;
+}
+
+
+/*
+ * calculates the default position of a window
+ */
+BOOL FASTCALL
+IntCalcDefPosSize(PWINDOW_OBJECT Parent, PWINDOW_OBJECT Window, RECT *rc, BOOL IncPos)
+{
+  SIZE Sz;
+  POINT Pos = {0, 0};
+
+  if(Parent != NULL)
+  {
+    IntGdiIntersectRect(rc, rc, &Parent->ClientRect);
+
+    if(IncPos)
+    {
+      Pos.x = Parent->TiledCounter * (UserGetSystemMetrics(SM_CXSIZE) + UserGetSystemMetrics(SM_CXFRAME));
+      Pos.y = Parent->TiledCounter * (UserGetSystemMetrics(SM_CYSIZE) + UserGetSystemMetrics(SM_CYFRAME));
+      if(Pos.x > ((rc->right - rc->left) / 4) ||
+         Pos.y > ((rc->bottom - rc->top) / 4))
+      {
+        /* reset counter and position */
+        Pos.x = 0;
+        Pos.y = 0;
+        Parent->TiledCounter = 0;
+      }
+      Parent->TiledCounter++;
+    }
+    Pos.x += rc->left;
+    Pos.y += rc->top;
+  }
+  else
+  {
+    Pos.x = rc->left;
+    Pos.y = rc->top;
+  }
+
+  Sz.cx = EngMulDiv(rc->right - rc->left, 3, 4);
+  Sz.cy = EngMulDiv(rc->bottom - rc->top, 3, 4);
 
-    return (HWND)NULL;
+  rc->left = Pos.x;
+  rc->top = Pos.y;
+  rc->right = rc->left + Sz.cx;
+  rc->bottom = rc->top + Sz.cy;
+  return TRUE;
 }
 
 
@@ -1265,31 +1375,31 @@ NtUserChildWindowFromPointEx(HWND hwndParent,
  * @implemented
  */
 HWND STDCALL
-NtUserCreateWindowEx(DWORD dwExStyle,
-                    PUNICODE_STRING lpClassName,
-                    PUNICODE_STRING lpWindowName,
-                    DWORD dwStyle,
-                    LONG x,
-                    LONG y,
-                    LONG nWidth,
-                    LONG nHeight,
-                    HWND hWndParent,
-                    HMENU hMenu,
-                    HINSTANCE hInstance,
-                    LPVOID lpParam,
-                    DWORD dwShowMode,
-                        BOOL bUnicodeWindow)
+co_IntCreateWindowEx(DWORD dwExStyle,
+                 PUNICODE_STRING ClassName,
+                 PUNICODE_STRING WindowName,
+                 DWORD dwStyle,
+                 LONG x,
+                 LONG y,
+                 LONG nWidth,
+                 LONG nHeight,
+                 HWND hWndParent,
+                 HMENU hMenu,
+                 HINSTANCE hInstance,
+                 LPVOID lpParam,
+                 DWORD dwShowMode,
+                 BOOL bUnicodeWindow)
 {
-  PWINSTATION_OBJECT WinStaObject;
-  PWNDCLASS_OBJECT ClassObject;
-  PWINDOW_OBJECT WindowObject;
+  PWINSTATION_OBJECT WinSta;
+  PWNDCLASS_OBJECT Class;
+  PWINDOW_OBJECT Window;
   PWINDOW_OBJECT ParentWindow, OwnerWindow;
   HWND ParentWindowHandle;
   HWND OwnerWindowHandle;
   PMENU_OBJECT SystemMenu;
-  UNICODE_STRING WindowName;
-  NTSTATUS Status;
   HANDLE Handle;
+  POINT Pos;
+  SIZE Size;
 #if 0
   POINT MaxSize, MaxPos, MinTrack, MaxTrack;
 #else
@@ -1299,16 +1409,9 @@ NtUserCreateWindowEx(DWORD dwExStyle,
   CBT_CREATEWNDW CbtCreate;
   LRESULT Result;
   BOOL MenuChanged;
+  BOOL ClassFound;
 
-  DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
-
-  if (! RtlCreateUnicodeString(&WindowName,
-                               NULL == lpWindowName->Buffer ?
-                               L"" : lpWindowName->Buffer))
-    {
-      SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
-      return((HWND)0);
-    }
+  BOOL HasOwner;
 
   ParentWindowHandle = PsGetWin32Thread()->Desktop->DesktopWindow;
   OwnerWindowHandle = NULL;
@@ -1319,18 +1422,17 @@ NtUserCreateWindowEx(DWORD dwExStyle,
        * native ole32.OleInitialize uses HWND_MESSAGE to create the
        * message window (style: WS_POPUP|WS_DISABLED)
        */
-      UNIMPLEMENTED;
+      DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
     }
   else if (hWndParent)
     {
       if ((dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD)
         ParentWindowHandle = hWndParent;
       else
-        OwnerWindowHandle = NtUserGetAncestor(hWndParent, GA_ROOT);
+        OwnerWindowHandle = UserGetAncestor(hWndParent, GA_ROOT);
     }
   else if ((dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD)
     {
-      RtlFreeUnicodeString(&WindowName);
       return (HWND)0;  /* WS_CHILD needs a parent, but WS_POPUP doesn't */
     }
 
@@ -1342,53 +1444,54 @@ NtUserCreateWindowEx(DWORD dwExStyle,
     {
       ParentWindow = NULL;
     }
-    
+
   /* FIXME: parent must belong to the current process */
 
   /* Check the class. */
-  Status = ClassReferenceClassByNameOrAtom(&ClassObject, lpClassName->Buffer);
-  if (!NT_SUCCESS(Status))
-    {
-      RtlFreeUnicodeString(&WindowName);
-      if (NULL != ParentWindow)
-        {
-          IntReleaseWindowObject(ParentWindow);
-        }
-      return((HWND)0);
-    }
+  ClassFound = ClassReferenceClassByNameOrAtom(&Class, ClassName->Buffer, hInstance);
+  if (!ClassFound)
+  {
+     if (IS_ATOM(ClassName->Buffer))
+       {
+         DPRINT1("Class 0x%x not found\n", (DWORD_PTR) ClassName->Buffer);
+       }
+     else
+       {
+         DPRINT1("Class %wZ not found\n", ClassName);
+       }
+     if (NULL != ParentWindow)
+     {
+        IntReleaseWindowObject(ParentWindow);
+     }
+     SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS);
+     return((HWND)0);
+  }
 
   /* Check the window station. */
-  DPRINT("IoGetCurrentProcess() %X\n", IoGetCurrentProcess());
-  DPRINT("PROCESS_WINDOW_STATION %X\n", PROCESS_WINDOW_STATION());
-  Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
-                                         KernelMode,
-                                         0,
-                                         &WinStaObject);
-  if (!NT_SUCCESS(Status))
+  if (PsGetWin32Thread()->Desktop == NULL)
     {
-      ObmDereferenceObject(ClassObject);
-      RtlFreeUnicodeString(&WindowName);
+      ClassDereferenceObject(Class);
       if (NULL != ParentWindow)
         {
           IntReleaseWindowObject(ParentWindow);
         }
-      DPRINT("Validation of window station handle (0x%X) failed\n",
-            PROCESS_WINDOW_STATION());
+      DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
       return (HWND)0;
     }
+  WinSta = PsGetWin32Thread()->Desktop->WindowStation;
+  ObReferenceObjectByPointer(WinSta, KernelMode, ExWindowStationObjectType, 0);
 
   /* Create the window object. */
-  WindowObject = (PWINDOW_OBJECT)
-    ObmCreateObject(PsGetWin32Process()->WindowStation->HandleTable, &Handle,
-        otWindow, sizeof(WINDOW_OBJECT) + ClassObject->cbWndExtra
+  Window = (PWINDOW_OBJECT)
+    ObmCreateObject(gHandleTable, &Handle,
+        otWindow, sizeof(WINDOW_OBJECT) + Class->cbWndExtra
         );
 
   DPRINT("Created object with handle %X\n", Handle);
-  if (!WindowObject)
+  if (!Window)
     {
-      ObDereferenceObject(WinStaObject);
-      ObmDereferenceObject(ClassObject);
-      RtlFreeUnicodeString(&WindowName);
+      ObDereferenceObject(WinSta);
+      ClassDereferenceObject(Class);
       if (NULL != ParentWindow)
         {
           IntReleaseWindowObject(ParentWindow);
@@ -1396,7 +1499,7 @@ NtUserCreateWindowEx(DWORD dwExStyle,
       SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
       return (HWND)0;
     }
-  ObDereferenceObject(WinStaObject);
+  ObDereferenceObject(WinSta);
 
   if (NULL == PsGetWin32Thread()->Desktop->DesktopWindow)
     {
@@ -1407,154 +1510,276 @@ NtUserCreateWindowEx(DWORD dwExStyle,
   /*
    * Fill out the structure describing it.
    */
-  WindowObject->Class = ClassObject;
-  WindowObject->ExStyle = dwExStyle;
-  WindowObject->Style = dwStyle & ~WS_VISIBLE;
-  DPRINT("1: Style is now %d\n", WindowObject->Style);
-  
-  WindowObject->SystemMenu = (HMENU)0;
-  WindowObject->ContextHelpId = 0;
-  WindowObject->IDMenu = 0;
-  WindowObject->Instance = hInstance;
-  WindowObject->Self = Handle;
+  Window->Class = Class;
+
+  InsertTailList(&Class->ClassWindowsListHead, &Window->ClassListEntry);
+
+  Window->ExStyle = dwExStyle;
+  Window->Style = dwStyle & ~WS_VISIBLE;
+  DPRINT("1: Style is now %lx\n", Window->Style);
+
+  Window->SystemMenu = (HMENU)0;
+  Window->ContextHelpId = 0;
+  Window->IDMenu = 0;
+  Window->Instance = hInstance;
+  Window->hSelf = Handle;
   if (0 != (dwStyle & WS_CHILD))
     {
-      WindowObject->IDMenu = (UINT) hMenu;
+      Window->IDMenu = (UINT) hMenu;
     }
   else
     {
-      IntSetMenu(WindowObject, hMenu, &MenuChanged);
+      IntSetMenu(Window, hMenu, &MenuChanged);
     }
-  WindowObject->MessageQueue = PsGetWin32Thread()->MessageQueue;
-  WindowObject->Parent = (ParentWindow ? ParentWindow->Self : NULL);
+  Window->MessageQueue = PsGetWin32Thread()->MessageQueue;
+  IntReferenceMessageQueue(Window->MessageQueue);
+  Window->Parent = ParentWindow;
   if((OwnerWindow = IntGetWindowObject(OwnerWindowHandle)))
   {
-    WindowObject->Owner = OwnerWindowHandle;
+    Window->hOwner = OwnerWindowHandle;
     IntReleaseWindowObject(OwnerWindow);
+    HasOwner = TRUE;
+  } else {
+    Window->hOwner = NULL;
+    HasOwner = FALSE;
   }
-  else
-    WindowObject->Owner = NULL;
-  WindowObject->UserData = 0;
-  if ((((DWORD)ClassObject->lpfnWndProcA & 0xFFFF0000) != 0xFFFF0000)
-      && (((DWORD)ClassObject->lpfnWndProcW & 0xFFFF0000) != 0xFFFF0000)) 
+  Window->UserData = 0;
+  if ((((DWORD)Class->lpfnWndProcA & 0xFFFF0000) != 0xFFFF0000)
+      && (((DWORD)Class->lpfnWndProcW & 0xFFFF0000) != 0xFFFF0000))
     {
-      WindowObject->Unicode = bUnicodeWindow;
+      Window->Unicode = bUnicodeWindow;
     }
   else
     {
-      WindowObject->Unicode = ClassObject->Unicode;
+      Window->Unicode = Class->Unicode;
     }
-  WindowObject->WndProcA = ClassObject->lpfnWndProcA;
-  WindowObject->WndProcW = ClassObject->lpfnWndProcW;
-  WindowObject->OwnerThread = PsGetCurrentThread();
-  WindowObject->FirstChild = NULL;
-  WindowObject->LastChild = NULL;
-  WindowObject->PrevSibling = NULL;
-  WindowObject->NextSibling = NULL;
+  Window->WndProcA = Class->lpfnWndProcA;
+  Window->WndProcW = Class->lpfnWndProcW;
+  Window->OwnerThread = PsGetCurrentThread();
+  Window->FirstChild = NULL;
+  Window->LastChild = NULL;
+  Window->PrevSibling = NULL;
+  Window->NextSibling = NULL;
 
   /* extra window data */
-  if (ClassObject->cbWndExtra != 0)
+  if (Class->cbWndExtra != 0)
+    {
+      Window->ExtraData = (PCHAR)(Window + 1);
+      Window->ExtraDataSize = Class->cbWndExtra;
+      RtlZeroMemory(Window->ExtraData, Window->ExtraDataSize);
+    }
+  else
+    {
+      Window->ExtraData = NULL;
+      Window->ExtraDataSize = 0;
+    }
+
+  InitializeListHead(&Window->PropListHead);
+  InitializeListHead(&Window->WndObjListHead);
+
+  if (NULL != WindowName->Buffer)
     {
-      WindowObject->ExtraData = (PCHAR)(WindowObject + 1);
-      WindowObject->ExtraDataSize = ClassObject->cbWndExtra;
-      RtlZeroMemory(WindowObject->ExtraData, WindowObject->ExtraDataSize);
+      Window->WindowName.MaximumLength = WindowName->MaximumLength;
+      Window->WindowName.Length = WindowName->Length;
+      Window->WindowName.Buffer = ExAllocatePoolWithTag(PagedPool, WindowName->MaximumLength,
+                                                              TAG_STRING);
+      if (NULL == Window->WindowName.Buffer)
+        {
+          ClassDereferenceObject(Class);
+          DPRINT1("Failed to allocate mem for window name\n");
+          SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+          return NULL;
+        }
+      RtlCopyMemory(Window->WindowName.Buffer, WindowName->Buffer, WindowName->MaximumLength);
     }
   else
     {
-      WindowObject->ExtraData = NULL;
-      WindowObject->ExtraDataSize = 0;
+      RtlInitUnicodeString(&Window->WindowName, NULL);
     }
 
-  InitializeListHead(&WindowObject->PropListHead);
-  ExInitializeFastMutex(&WindowObject->PropListLock);
-  ExInitializeFastMutex(&WindowObject->RelativesLock);
-  ExInitializeFastMutex(&WindowObject->UpdateLock);
 
-  RtlInitUnicodeString(&WindowObject->WindowName, WindowName.Buffer);
+  /*
+   * This has been tested for WS_CHILD | WS_VISIBLE.  It has not been
+   * tested for WS_POPUP
+   */
+  if ((dwExStyle & WS_EX_DLGMODALFRAME) ||
+      ((!(dwExStyle & WS_EX_STATICEDGE)) &&
+      (dwStyle & (WS_DLGFRAME | WS_THICKFRAME))))
+    dwExStyle |= WS_EX_WINDOWEDGE;
+  else
+    dwExStyle &= ~WS_EX_WINDOWEDGE;
 
   /* Correct the window style. */
   if (!(dwStyle & WS_CHILD))
     {
-      WindowObject->Style |= WS_CLIPSIBLINGS;
-      DPRINT("3: Style is now %d\n", WindowObject->Style);
+      Window->Style |= WS_CLIPSIBLINGS;
+      DPRINT("3: Style is now %lx\n", Window->Style);
       if (!(dwStyle & WS_POPUP))
        {
-         WindowObject->Style |= WS_CAPTION;
-          WindowObject->Flags |= WINDOWOBJECT_NEED_SIZE;
-          DPRINT("4: Style is now %d\n", WindowObject->Style);
-         /* FIXME: Note the window needs a size. */ 
+         Window->Style |= WS_CAPTION;
+          Window->Flags |= WINDOWOBJECT_NEED_SIZE;
+          DPRINT("4: Style is now %lx\n", Window->Style);
        }
     }
-  
+
   /* create system menu */
-  if((WindowObject->Style & WS_SYSMENU) && (WindowObject->Style & WS_CAPTION))
+  if((Window->Style & WS_SYSMENU) &&
+     (Window->Style & WS_CAPTION) == WS_CAPTION)
   {
-    SystemMenu = IntGetSystemMenu(WindowObject, TRUE, TRUE);
+    SystemMenu = IntGetSystemMenu(Window, TRUE, TRUE);
     if(SystemMenu)
     {
-      WindowObject->SystemMenu = SystemMenu->MenuInfo.Self;
+      Window->SystemMenu = SystemMenu->MenuInfo.Self;
       IntReleaseMenuObject(SystemMenu);
     }
   }
-  
+
   /* Insert the window into the thread's window list. */
-  IntLockThreadWindows(PsGetWin32Thread());
-  InsertTailList (&PsGetWin32Thread()->WindowListHead, 
-                 &WindowObject->ThreadListEntry);
-  IntUnLockThreadWindows(PsGetWin32Thread());
+  InsertTailList (&PsGetWin32Thread()->WindowListHead, &Window->ThreadListEntry);
 
   /* Allocate a DCE for this window. */
   if (dwStyle & CS_OWNDC)
     {
-      WindowObject->Dce = DceAllocDCE(WindowObject->Self, DCE_WINDOW_DC);
+      Window->Dce = DceAllocDCE(Window->hSelf, DCE_WINDOW_DC);
     }
   /* FIXME:  Handle "CS_CLASSDC" */
 
-  /* Initialize the window dimensions. */
-  WindowObject->WindowRect.left = x;
-  WindowObject->WindowRect.top = y;
-  WindowObject->WindowRect.right = x + nWidth;
-  WindowObject->WindowRect.bottom = y + nHeight;
-  if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow)
-    {
-      NtGdiOffsetRect(&(WindowObject->WindowRect), ParentWindow->ClientRect.left,
-                      ParentWindow->ClientRect.top);
-    }
-  WindowObject->ClientRect = WindowObject->WindowRect;
+  Pos.x = x;
+  Pos.y = y;
+  Size.cx = nWidth;
+  Size.cy = nHeight;
 
+  /* call hook */
   Cs.lpCreateParams = lpParam;
   Cs.hInstance = hInstance;
   Cs.hMenu = hMenu;
   Cs.hwndParent = ParentWindowHandle;
-  Cs.cx = nWidth;
-  Cs.cy = nHeight;
-  Cs.x = x;
-  Cs.y = y;
+  Cs.cx = Size.cx;
+  Cs.cy = Size.cy;
+  Cs.x = Pos.x;
+  Cs.y = Pos.y;
   Cs.style = dwStyle;
-  Cs.lpszName = lpWindowName->Buffer;
-  Cs.lpszClass = lpClassName->Buffer;
+  Cs.lpszName = (LPCWSTR) WindowName;
+  Cs.lpszClass = (LPCWSTR) ClassName;
   Cs.dwExStyle = dwExStyle;
   CbtCreate.lpcs = &Cs;
   CbtCreate.hwndInsertAfter = HWND_TOP;
-  if (HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) Handle, (LPARAM) &CbtCreate))
+  if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) Handle, (LPARAM) &CbtCreate))
     {
       if (NULL != ParentWindow)
         {
           IntReleaseWindowObject(ParentWindow);
         }
+
+      /* FIXME - Delete window object and remove it from the thread windows list */
+      /* FIXME - delete allocated DCE */
+
+      ClassDereferenceObject(Class);
       DPRINT1("CBT-hook returned !0\n");
       return (HWND) NULL;
     }
 
+  x = Cs.x;
+  y = Cs.y;
+  nWidth = Cs.cx;
+  nHeight = Cs.cy;
+
+  /* default positioning for overlapped windows */
+  if(!(Window->Style & (WS_POPUP | WS_CHILD)))
+  {
+    RECT rc, WorkArea;
+    PRTL_USER_PROCESS_PARAMETERS ProcessParams;
+    BOOL CalculatedDefPosSize = FALSE;
+
+    IntGetDesktopWorkArea(Window->OwnerThread->Tcb.Win32Thread->Desktop, &WorkArea);
+
+    rc = WorkArea;
+    ProcessParams = PsGetCurrentProcess()->Peb->ProcessParameters;
+
+    if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
+    {
+      CalculatedDefPosSize = IntCalcDefPosSize(ParentWindow, Window, &rc, TRUE);
+
+      if(ProcessParams->WindowFlags & STARTF_USEPOSITION)
+      {
+        ProcessParams->WindowFlags &= ~STARTF_USEPOSITION;
+        Pos.x = WorkArea.left + ProcessParams->StartingX;
+        Pos.y = WorkArea.top + ProcessParams->StartingY;
+      }
+      else
+      {
+        Pos.x = rc.left;
+        Pos.y = rc.top;
+      }
+
+      /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
+         y is something else */
+      if(y != CW_USEDEFAULT && y != CW_USEDEFAULT16)
+      {
+        dwShowMode = y;
+      }
+    }
+    if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)
+    {
+      if(!CalculatedDefPosSize)
+      {
+        IntCalcDefPosSize(ParentWindow, Window, &rc, FALSE);
+      }
+      if(ProcessParams->WindowFlags & STARTF_USESIZE)
+      {
+        ProcessParams->WindowFlags &= ~STARTF_USESIZE;
+        Size.cx = ProcessParams->CountX;
+        Size.cy = ProcessParams->CountY;
+      }
+      else
+      {
+        Size.cx = rc.right - rc.left;
+        Size.cy = rc.bottom - rc.top;
+      }
+
+      /* move the window if necessary */
+      if(Pos.x > rc.left)
+        Pos.x = max(rc.left, 0);
+      if(Pos.y > rc.top)
+        Pos.y = max(rc.top, 0);
+    }
+  }
+  else
+  {
+    /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
+    if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
+    {
+      Pos.x = 0;
+      Pos.y = 0;
+    }
+    if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)
+    {
+      Size.cx = 0;
+      Size.cy = 0;
+    }
+  }
+
+  /* Initialize the window dimensions. */
+  Window->WindowRect.left = Pos.x;
+  Window->WindowRect.top = Pos.y;
+  Window->WindowRect.right = Pos.x + Size.cx;
+  Window->WindowRect.bottom = Pos.y + Size.cy;
+  if (0 != (Window->Style & WS_CHILD) && ParentWindow)
+    {
+      IntGdiOffsetRect(&(Window->WindowRect), ParentWindow->ClientRect.left,
+                      ParentWindow->ClientRect.top);
+    }
+  Window->ClientRect = Window->WindowRect;
+
   /*
    * Get the size and position of the window.
    */
   if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD)))
     {
       POINT MaxSize, MaxPos, MinTrack, MaxTrack;
-     
+
       /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
-      WinPosGetMinMaxInfo(WindowObject, &MaxSize, &MaxPos, &MinTrack,
+      co_WinPosGetMinMaxInfo(Window, &MaxSize, &MaxPos, &MinTrack,
                          &MaxTrack);
       if (MaxSize.x < nWidth) nWidth = MaxSize.x;
       if (MaxSize.y < nHeight) nHeight = MaxSize.y;
@@ -1564,41 +1789,29 @@ NtUserCreateWindowEx(DWORD dwExStyle,
       if (nHeight < 0) nHeight = 0;
     }
 
-  WindowObject->WindowRect.left = x;
-  WindowObject->WindowRect.top = y;
-  WindowObject->WindowRect.right = x + nWidth;
-  WindowObject->WindowRect.bottom = y + nHeight;
-  if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow)
+  Window->WindowRect.left = Pos.x;
+  Window->WindowRect.top = Pos.y;
+  Window->WindowRect.right = Pos.x + Size.cx;
+  Window->WindowRect.bottom = Pos.y + Size.cy;
+  if (0 != (Window->Style & WS_CHILD) && ParentWindow)
     {
-      NtGdiOffsetRect(&(WindowObject->WindowRect), ParentWindow->ClientRect.left,
+      IntGdiOffsetRect(&(Window->WindowRect), ParentWindow->ClientRect.left,
                       ParentWindow->ClientRect.top);
     }
-  WindowObject->ClientRect = WindowObject->WindowRect;
+  Window->ClientRect = Window->WindowRect;
 
   /* FIXME: Initialize the window menu. */
-  
-  /* Initialize the window's scrollbars */
-  if (dwStyle & WS_VSCROLL)
-  {
-     WindowObject->Style &= ~WS_VSCROLL;
-     NtUserShowScrollBar(WindowObject->Self, SB_VERT, TRUE);
-  }
-  if (dwStyle & WS_HSCROLL)
-  {
-     WindowObject->Style &= ~WS_HSCROLL;
-     NtUserShowScrollBar(WindowObject->Self, SB_HORZ, TRUE);
-  }
 
   /* Send a NCCREATE message. */
-  Cs.cx = nWidth;
-  Cs.cy = nHeight;
-  Cs.x = x;
-  Cs.y = y;
-
-  DPRINT("[win32k.window] NtUserCreateWindowEx style %d, exstyle %d, parent %d\n", Cs.style, Cs.dwExStyle, Cs.hwndParent);
-  DPRINT("NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
-  DPRINT("NtUserCreateWindowEx(): About to send NCCREATE message.\n");
-  Result = IntSendMessage(WindowObject->Self, WM_NCCREATE, 0, (LPARAM) &Cs);
+  Cs.cx = Size.cx;
+  Cs.cy = Size.cy;
+  Cs.x = Pos.x;
+  Cs.y = Pos.y;
+
+  DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs.style, Cs.dwExStyle, Cs.hwndParent);
+  DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
+  DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
+  Result = co_IntSendMessage(Window->hSelf, WM_NCCREATE, 0, (LPARAM) &Cs);
   if (!Result)
     {
       /* FIXME: Cleanup. */
@@ -1606,21 +1819,21 @@ NtUserCreateWindowEx(DWORD dwExStyle,
         {
           IntReleaseWindowObject(ParentWindow);
         }
-      DPRINT("NtUserCreateWindowEx(): NCCREATE message failed.\n");
+      DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
       return((HWND)0);
     }
+
   /* Calculate the non-client size. */
-  MaxPos.x = WindowObject->WindowRect.left;
-  MaxPos.y = WindowObject->WindowRect.top;
-  DPRINT("NtUserCreateWindowEx(): About to get non-client size.\n");
+  MaxPos.x = Window->WindowRect.left;
+  MaxPos.y = Window->WindowRect.top;
+  DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
   /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
-  Result = WinPosGetNonClientSize(WindowObject->Self, 
-                                 &WindowObject->WindowRect,
-                                 &WindowObject->ClientRect);
-  NtGdiOffsetRect(&WindowObject->WindowRect, 
-                MaxPos.x - WindowObject->WindowRect.left,
-                MaxPos.y - WindowObject->WindowRect.top);
+  Result = co_WinPosGetNonClientSize(Window->hSelf,
+                                 &Window->WindowRect,
+                                 &Window->ClientRect);
+  IntGdiOffsetRect(&Window->WindowRect,
+                MaxPos.x - Window->WindowRect.left,
+                MaxPos.y - Window->WindowRect.top);
 
   if (NULL != ParentWindow)
     {
@@ -1628,12 +1841,10 @@ NtUserCreateWindowEx(DWORD dwExStyle,
       if ((dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
         {
           PWINDOW_OBJECT PrevSibling;
-          IntLockRelatives(ParentWindow);
           if((PrevSibling = ParentWindow->LastChild))
             IntReferenceWindowObject(PrevSibling);
-          IntUnLockRelatives(ParentWindow);
           /* link window as bottom sibling */
-          IntLinkWindow(WindowObject, ParentWindow, PrevSibling /*prev sibling*/);
+          IntLinkWindow(Window, ParentWindow, PrevSibling /*prev sibling*/);
           if(PrevSibling)
             IntReleaseWindowObject(PrevSibling);
         }
@@ -1643,7 +1854,6 @@ NtUserCreateWindowEx(DWORD dwExStyle,
           PWINDOW_OBJECT InsertAfter, Sibling;
           if (0 == (dwExStyle & WS_EX_TOPMOST))
             {
-              IntLockRelatives(ParentWindow);
               InsertAfter = NULL;
               Sibling = ParentWindow->FirstChild;
               while (NULL != Sibling && 0 != (Sibling->ExStyle & WS_EX_TOPMOST))
@@ -1651,7 +1861,6 @@ NtUserCreateWindowEx(DWORD dwExStyle,
                   InsertAfter = Sibling;
                   Sibling = Sibling->NextSibling;
                 }
-              IntUnLockRelatives(ParentWindow);
             }
           else
             {
@@ -1661,7 +1870,7 @@ NtUserCreateWindowEx(DWORD dwExStyle,
             {
               IntReferenceWindowObject(InsertAfter);
             }
-          IntLinkWindow(WindowObject, ParentWindow, InsertAfter /* prev sibling */);
+          IntLinkWindow(Window, ParentWindow, InsertAfter /* prev sibling */);
           if (NULL != InsertAfter)
             {
               IntReleaseWindowObject(InsertAfter);
@@ -1670,8 +1879,8 @@ NtUserCreateWindowEx(DWORD dwExStyle,
     }
 
   /* Send the WM_CREATE message. */
-  DPRINT("NtUserCreateWindowEx(): about to send CREATE message.\n");
-  Result = IntSendMessage(WindowObject->Self, WM_CREATE, 0, (LPARAM) &Cs);
+  DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
+  Result = co_IntSendMessage(Window->hSelf, WM_CREATE, 0, (LPARAM) &Cs);
   if (Result == (LRESULT)-1)
     {
       /* FIXME: Cleanup. */
@@ -1679,89 +1888,189 @@ NtUserCreateWindowEx(DWORD dwExStyle,
         {
           IntReleaseWindowObject(ParentWindow);
         }
-      DPRINT("NtUserCreateWindowEx(): send CREATE message failed.\n");
+      ClassDereferenceObject(Class);
+      DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
       return((HWND)0);
-    } 
-  
+    }
+
   /* Send move and size messages. */
-  if (!(WindowObject->Flags & WINDOWOBJECT_NEED_SIZE))
+  if (!(Window->Flags & WINDOWOBJECT_NEED_SIZE))
     {
       LONG lParam;
 
-      DPRINT("NtUserCreateWindow(): About to send WM_SIZE\n");
+      DPRINT("IntCreateWindow(): About to send WM_SIZE\n");
 
-      if ((WindowObject->ClientRect.right - WindowObject->ClientRect.left) < 0 ||
-          (WindowObject->ClientRect.bottom - WindowObject->ClientRect.top) < 0)
+      if ((Window->ClientRect.right - Window->ClientRect.left) < 0 ||
+          (Window->ClientRect.bottom - Window->ClientRect.top) < 0)
+      {
          DPRINT("Sending bogus WM_SIZE\n");
-      
-      lParam = MAKE_LONG(WindowObject->ClientRect.right - 
-                 WindowObject->ClientRect.left,
-                 WindowObject->ClientRect.bottom - 
-                 WindowObject->ClientRect.top);
-      IntSendMessage(WindowObject->Self, WM_SIZE, SIZE_RESTORED, 
+      }
+
+      lParam = MAKE_LONG(Window->ClientRect.right -
+                 Window->ClientRect.left,
+                 Window->ClientRect.bottom -
+                 Window->ClientRect.top);
+      co_IntSendMessage(Window->hSelf, WM_SIZE, SIZE_RESTORED,
           lParam);
 
-      DPRINT("NtUserCreateWindow(): About to send WM_MOVE\n");
+      DPRINT("IntCreateWindow(): About to send WM_MOVE\n");
 
-      if (0 != (WindowObject->Style & WS_CHILD) && ParentWindow)
+      if (0 != (Window->Style & WS_CHILD) && ParentWindow)
        {
-         lParam = MAKE_LONG(WindowObject->ClientRect.left - ParentWindow->ClientRect.left,
-             WindowObject->ClientRect.top - ParentWindow->ClientRect.top);
+         lParam = MAKE_LONG(Window->ClientRect.left - ParentWindow->ClientRect.left,
+             Window->ClientRect.top - ParentWindow->ClientRect.top);
        }
       else
        {
-         lParam = MAKE_LONG(WindowObject->ClientRect.left,
-             WindowObject->ClientRect.top);
+         lParam = MAKE_LONG(Window->ClientRect.left,
+             Window->ClientRect.top);
        }
-      IntSendMessage(WindowObject->Self, WM_MOVE, 0, lParam);
+      co_IntSendMessage(Window->hSelf, WM_MOVE, 0, lParam);
+
+      /* Call WNDOBJ change procs */
+      IntEngWindowChanged(Window, WOC_RGN_CLIENT);
     }
 
   /* Show or maybe minimize or maximize the window. */
-  if (WindowObject->Style & (WS_MINIMIZE | WS_MAXIMIZE))
+  if (Window->Style & (WS_MINIMIZE | WS_MAXIMIZE))
     {
       RECT NewPos;
       UINT16 SwFlag;
 
-      SwFlag = (WindowObject->Style & WS_MINIMIZE) ? SW_MINIMIZE : 
+      SwFlag = (Window->Style & WS_MINIMIZE) ? SW_MINIMIZE :
        SW_MAXIMIZE;
-      WinPosMinMaximize(WindowObject, SwFlag, &NewPos);
-      SwFlag = 
-       ((WindowObject->Style & WS_CHILD) || NtUserGetActiveWindow()) ?
+      co_WinPosMinMaximize(Window, SwFlag, &NewPos);
+      SwFlag =
+       ((Window->Style & WS_CHILD) || UserGetActiveWindow()) ?
        SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED :
        SWP_NOZORDER | SWP_FRAMECHANGED;
-      DPRINT("NtUserCreateWindow(): About to minimize/maximize\n");
+      DPRINT("IntCreateWindow(): About to minimize/maximize\n");
       DPRINT("%d,%d %dx%d\n", NewPos.left, NewPos.top, NewPos.right, NewPos.bottom);
-      WinPosSetWindowPos(WindowObject->Self, 0, NewPos.left, NewPos.top,
+      co_WinPosSetWindowPos(Window->hSelf, 0, NewPos.left, NewPos.top,
                         NewPos.right, NewPos.bottom, SwFlag);
     }
 
   /* Notify the parent window of a new child. */
-  if ((WindowObject->Style & WS_CHILD) &&
-      (!(WindowObject->ExStyle & WS_EX_NOPARENTNOTIFY)) && ParentWindow)
+  if ((Window->Style & WS_CHILD) &&
+      (!(Window->ExStyle & WS_EX_NOPARENTNOTIFY)) && ParentWindow)
     {
-      DPRINT("NtUserCreateWindow(): About to notify parent\n");
-      IntSendMessage(ParentWindow->Self,
-                     WM_PARENTNOTIFY, 
-                     MAKEWPARAM(WM_CREATE, WindowObject->IDMenu),
-                     (LPARAM)WindowObject->Self);
+      DPRINT("IntCreateWindow(): About to notify parent\n");
+      co_IntSendMessage(ParentWindow->hSelf,
+                     WM_PARENTNOTIFY,
+                     MAKEWPARAM(WM_CREATE, Window->IDMenu),
+                     (LPARAM)Window->hSelf);
     }
 
+  if ((!hWndParent) && (!HasOwner)) {
+      DPRINT("Sending CREATED notify\n");
+      co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)Handle);
+  } else {
+      DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow, HasOwner);
+  }
+
   if (NULL != ParentWindow)
     {
       IntReleaseWindowObject(ParentWindow);
     }
 
+  /* Initialize and show the window's scrollbars */
+  if (Window->Style & WS_VSCROLL)
+  {
+     co_UserShowScrollBar(Window->hSelf, SB_VERT, TRUE);
+  }
+  if (Window->Style & WS_HSCROLL)
+  {
+     co_UserShowScrollBar(Window->hSelf, SB_HORZ, TRUE);
+  }
+
   if (dwStyle & WS_VISIBLE)
     {
-      DPRINT("NtUserCreateWindow(): About to show window\n");
-      WinPosShowWindow(WindowObject->Self, dwShowMode);
+      DPRINT("IntCreateWindow(): About to show window\n");
+      co_WinPosShowWindow(Window->hSelf, dwShowMode);
     }
 
-  DPRINT("NtUserCreateWindow(): = %X\n", Handle);
-  DPRINT("WindowObject->SystemMenu = 0x%x\n", WindowObject->SystemMenu);
+  DPRINT("IntCreateWindow(): = %X\n", Handle);
+  DPRINT("WindowObject->SystemMenu = 0x%x\n", Window->SystemMenu);
   return((HWND)Handle);
 }
 
+HWND STDCALL
+NtUserCreateWindowEx(DWORD dwExStyle,
+                    PUNICODE_STRING UnsafeClassName,
+                    PUNICODE_STRING UnsafeWindowName,
+                    DWORD dwStyle,
+                    LONG x,
+                    LONG y,
+                    LONG nWidth,
+                    LONG nHeight,
+                    HWND hWndParent,
+                    HMENU hMenu,
+                    HINSTANCE hInstance,
+                    LPVOID lpParam,
+                    DWORD dwShowMode,
+                    BOOL bUnicodeWindow)
+{
+  NTSTATUS Status;
+  UNICODE_STRING WindowName;
+  UNICODE_STRING ClassName;
+  HWND NewWindow;
+  DECLARE_RETURN(HWND);
+
+  DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
+  UserEnterExclusive();
+
+  /* Get the class name (string or atom) */
+  Status = MmCopyFromCaller(&ClassName, UnsafeClassName, sizeof(UNICODE_STRING));
+  if (! NT_SUCCESS(Status))
+    {
+      SetLastNtError(Status);
+      RETURN( NULL);
+    }
+  if (! IS_ATOM(ClassName.Buffer))
+    {
+      Status = IntSafeCopyUnicodeStringTerminateNULL(&ClassName, UnsafeClassName);
+      if (! NT_SUCCESS(Status))
+        {
+          SetLastNtError(Status);
+          RETURN( NULL);
+        }
+    }
+
+  /* safely copy the window name */
+  if (NULL != UnsafeWindowName)
+    {
+      Status = IntSafeCopyUnicodeString(&WindowName, UnsafeWindowName);
+      if (! NT_SUCCESS(Status))
+        {
+          if (! IS_ATOM(ClassName.Buffer))
+            {
+              RtlFreeUnicodeString(&ClassName);
+            }
+          SetLastNtError(Status);
+          RETURN( NULL);
+        }
+    }
+  else
+    {
+      RtlInitUnicodeString(&WindowName, NULL);
+    }
+
+  NewWindow = co_IntCreateWindowEx(dwExStyle, &ClassName, &WindowName, dwStyle, x, y, nWidth, nHeight,
+                               hWndParent, hMenu, hInstance, lpParam, dwShowMode, bUnicodeWindow);
+
+  RtlFreeUnicodeString(&WindowName);
+  if (! IS_ATOM(ClassName.Buffer))
+    {
+      RtlFreeUnicodeString(&ClassName);
+    }
+
+  RETURN( NewWindow);
+  
+CLEANUP:
+  DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
+}
 
 /*
  * @unimplemented
@@ -1782,16 +2091,10 @@ NtUserDeferWindowPos(HDWP WinPosInfo,
 }
 
 
-/*
- * @implemented
- */
-BOOLEAN STDCALL
-NtUserDestroyWindow(HWND Wnd)
+BOOLEAN FASTCALL co_UserDestroyWindow(PWINDOW_OBJECT Window)
 {
-  PWINDOW_OBJECT Window;
   BOOLEAN isChild;
 
-  Window = IntGetWindowObject(Wnd);
   if (Window == NULL)
     {
       return FALSE;
@@ -1800,7 +2103,6 @@ NtUserDestroyWindow(HWND Wnd)
   /* Check for owner thread and desktop window */
   if ((Window->OwnerThread != PsGetCurrentThread()) || IntIsDesktopWindow(Window))
     {
-      IntReleaseWindowObject(Window);
       SetLastWin32Error(ERROR_ACCESS_DENIED);
       return FALSE;
     }
@@ -1808,30 +2110,31 @@ NtUserDestroyWindow(HWND Wnd)
   /* Look whether the focus is within the tree of windows we will
    * be destroying.
    */
-  if (!WinPosShowWindow(Wnd, SW_HIDE))
+  if (!co_WinPosShowWindow(Window->hSelf, SW_HIDE))
     {
-      if (NtUserGetActiveWindow() == Wnd)
+      if (UserGetActiveWindow() == Window->hSelf)
         {
-          WinPosActivateOtherWindow(Window);
+          co_WinPosActivateOtherWindow(Window);
         }
     }
-  IntLockMessageQueue(Window->MessageQueue);
-  if (Window->MessageQueue->ActiveWindow == Window->Self)
+
+  if (Window->MessageQueue->ActiveWindow == Window->hSelf)
     Window->MessageQueue->ActiveWindow = NULL;
-  if (Window->MessageQueue->FocusWindow == Window->Self)
+  if (Window->MessageQueue->FocusWindow == Window->hSelf)
     Window->MessageQueue->FocusWindow = NULL;
-  if (Window->MessageQueue->CaptureWindow == Window->Self)
+  if (Window->MessageQueue->CaptureWindow == Window->hSelf)
     Window->MessageQueue->CaptureWindow = NULL;
-  IntUnLockMessageQueue(Window->MessageQueue);
 
+  IntDereferenceMessageQueue(Window->MessageQueue);
   /* Call hooks */
 #if 0 /* FIXME */
-  if (HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hwnd, 0, TRUE))
+  if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hwnd, 0, TRUE))
     {
     return FALSE;
     }
 #endif
 
+  IntEngWindowChanged(Window, WOC_DELETE);
   isChild = (0 != (Window->Style & WS_CHILD));
 
 #if 0 /* FIXME */
@@ -1844,21 +2147,16 @@ NtUserDestroyWindow(HWND Wnd)
     }
   else if (NULL != GetWindow(Wnd, GW_OWNER))
     {
-      HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
+      co_HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
       /* FIXME: clean up palette - see "Internals" p.352 */
     }
-
-  if (! IsWindow(Wnd))
-    {
-    return TRUE;
-    }
 #endif
 
-  if (!IntIsWindow(Wnd))
+  if (!IntIsWindow(Window->hSelf))
     {
     return TRUE;
     }
-  
+
   /* Recursively destroy owned windows */
   if (! isChild)
     {
@@ -1878,35 +2176,26 @@ NtUserDestroyWindow(HWND Wnd)
                {
                  Child = IntGetWindowObject(*ChildHandle);
                  if (Child == NULL)
-                   {
-                     continue;
-                   }
-                 if(Child->Self == Wnd)
-                 {
-                   IntReleaseWindowObject(Child);
                    continue;
-                 }
-                 IntLockRelatives(Child);
-                 if (Child->Parent != Window->Self)
+                 if (Child->hOwner != Window->hSelf)
                    {
-                     IntUnLockRelatives(Child);
                      IntReleaseWindowObject(Child);
                      continue;
                    }
-                 IntUnLockRelatives(Child);
+
                  if (IntWndBelongsToThread(Child, PsGetWin32Thread()))
                    {
-                     IntReleaseWindowObject(Child);
-                     NtUserDestroyWindow(*ChildHandle);
-                     GotOne = TRUE;                  
+            co_UserDestroyWindow(Child);
+            IntReleaseWindowObject(Child);
+                     GotOne = TRUE;
                      continue;
                    }
-                 IntLockRelatives(Child);
-                 if (Child->Owner != NULL)
+
+                 if (Child->hOwner != NULL)
                    {
-                     Child->Owner = NULL;
+                     Child->hOwner = NULL;
                    }
-                 IntUnLockRelatives(Child);
+
                  IntReleaseWindowObject(Child);
                }
              ExFreePool(Children);
@@ -1917,21 +2206,49 @@ NtUserDestroyWindow(HWND Wnd)
            }
        }
     }
-  
-  if (!IntIsWindow(Wnd))
+
+  if (!IntIsWindow(Window->hSelf))
     {
-      IntReleaseWindowObject(Window);
       return TRUE;
     }
 
   /* Destroy the window storage */
-  IntDestroyWindow(Window, PsGetWin32Process(), PsGetWin32Thread(), TRUE);
-  
-  IntReleaseWindowObject(Window);
+  co_IntDestroyWindow(Window, PsGetWin32Process(), PsGetWin32Thread(), TRUE);
+
   return TRUE;
 }
 
 
+
+
+/*
+ * @implemented
+ */
+BOOLEAN STDCALL
+NtUserDestroyWindow(HWND Wnd)
+{
+  PWINDOW_OBJECT Window;
+  DECLARE_RETURN(BOOLEAN);
+
+  DPRINT("Enter NtUserDestroyWindow\n");
+  UserEnterExclusive();
+
+  Window = IntGetWindowObject(Wnd);
+  if (Window == NULL)
+    {
+      RETURN(FALSE);
+    }
+  
+  RETURN(co_UserDestroyWindow(Window));
+
+CLEANUP:
+  DPRINT("Leave NtUserDestroyWindow, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
+}
+
+
+
 /*
  * @unimplemented
  */
@@ -1958,7 +2275,7 @@ NtUserEndDeferWindowPosEx(DWORD Unknown0,
                          DWORD Unknown1)
 {
   UNIMPLEMENTED
-    
+
   return 0;
 }
 
@@ -1978,15 +2295,67 @@ NtUserFillWindow(DWORD Unknown0,
 }
 
 
+HWND FASTCALL
+IntFindWindow(PWINDOW_OBJECT Parent,
+              PWINDOW_OBJECT ChildAfter,
+              RTL_ATOM ClassAtom,
+              PUNICODE_STRING WindowName)
+{
+  BOOL CheckWindowName;
+  HWND *List, *phWnd;
+  HWND Ret = NULL;
+
+  ASSERT(Parent);
+
+  CheckWindowName = (WindowName && (WindowName->Length > 0));
+
+  if((List = IntWinListChildren(Parent)))
+  {
+    phWnd = List;
+    if(ChildAfter)
+    {
+      /* skip handles before and including ChildAfter */
+      while(*phWnd && (*(phWnd++) != ChildAfter->hSelf));
+    }
+
+    /* search children */
+    while(*phWnd)
+    {
+      PWINDOW_OBJECT Child;
+      if(!(Child = IntGetWindowObject(*(phWnd++))))
+      {
+        continue;
+      }
+
+      /* Do not send WM_GETTEXT messages in the kernel mode version!
+         The user mode version however calls GetWindowText() which will
+         send WM_GETTEXT messages to windows belonging to its processes */
+      if((!CheckWindowName || !RtlCompareUnicodeString(WindowName, &(Child->WindowName), FALSE)) &&
+         (!ClassAtom || Child->Class->Atom == ClassAtom))
+      {
+        Ret = Child->hSelf;
+        IntReleaseWindowObject(Child);
+        break;
+      }
+
+      IntReleaseWindowObject(Child);
+    }
+    ExFreePool(List);
+  }
+
+  return Ret;
+}
+
 /*
  * FUNCTION:
  *   Searches a window's children for a window with the specified
  *   class and name
  * ARGUMENTS:
- *   hwndParent            = The window whose childs are to be searched. 
+ *   hwndParent            = The window whose childs are to be searched.
  *                                       NULL = desktop
+ *                                       HWND_MESSAGE = message-only windows
  *
- *   hwndChildAfter = Search starts after this child window. 
+ *   hwndChildAfter = Search starts after this child window.
  *                                       NULL = start from beginning
  *
  *   ucClassName    = Class name to search for
@@ -1994,13 +2363,9 @@ NtUserFillWindow(DWORD Unknown0,
  *
  *   ucWindowName   = Window name
  *                                       ->Buffer == NULL = don't care
- *                       
+ *
  * RETURNS:
  *   The HWND of the window if it was found, otherwise NULL
- *
- * FIXME:
- *   Should use MmCopyFromCaller, we don't want an access violation in here
- *      
  */
 /*
  * @implemented
@@ -2011,81 +2376,205 @@ NtUserFindWindowEx(HWND hwndParent,
                   PUNICODE_STRING ucClassName,
                   PUNICODE_STRING ucWindowName)
 {
-  NTSTATUS status;
-  HWND windowHandle;
-  PWINDOW_OBJECT ParentWindow, WndChildAfter, WndChild;
-  PWNDCLASS_OBJECT classObject;
-  
-  // Get a pointer to the class
-  status = ClassReferenceClassByNameOrAtom(&classObject, ucClassName->Buffer);
-  if (!NT_SUCCESS(status))
-    {
-      return NULL;
-    }
-  
-  // If hwndParent==NULL use the desktop window instead
-  if(!hwndParent)
-      hwndParent = PsGetWin32Thread()->Desktop->DesktopWindow;
+  PWINDOW_OBJECT Parent, ChildAfter;
+  UNICODE_STRING ClassName, WindowName;
+  NTSTATUS Status;
+  HWND Desktop, Ret = NULL;
+  RTL_ATOM ClassAtom;
+  DECLARE_RETURN(HWND);
 
-  // Get the object
-  ParentWindow = IntGetWindowObject(hwndParent);
+  DPRINT("Enter NtUserFindWindowEx\n");
+  UserEnterShared();
 
-  if(!ParentWindow)
-    {
-      ObmDereferenceObject(classObject);
-      return NULL;      
-    }
+  Desktop = IntGetCurrentThreadDesktopWindow();
+
+  if(hwndParent == NULL)
+    hwndParent = Desktop;
+  /* FIXME
+  else if(hwndParent == HWND_MESSAGE)
+  {
+    hwndParent = IntGetMessageWindow();
+  }
+  */
 
-  IntLockRelatives(ParentWindow);
+  if(!(Parent = IntGetWindowObject(hwndParent)))
+  {
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    RETURN( NULL);
+  }
 
-  if(hwndChildAfter)
+  ChildAfter = NULL;
+  if(hwndChildAfter && !(ChildAfter = IntGetWindowObject(hwndChildAfter)))
+  {
+    IntReleaseWindowObject(Parent);
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    RETURN( NULL);
+  }
+
+  /* copy the window name */
+  Status = IntSafeCopyUnicodeString(&WindowName, ucWindowName);
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastNtError(Status);
+    goto Cleanup3;
+  }
+
+  /* safely copy the class name */
+  Status = MmCopyFromCaller(&ClassName, ucClassName, sizeof(UNICODE_STRING));
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastNtError(Status);
+    goto Cleanup2;
+  }
+  if(ClassName.Length > 0 && ClassName.Buffer)
   {
-    if (!(WndChildAfter = IntGetWindowObject(hwndChildAfter)))
+    WCHAR *buf;
+    /* safely copy the class name string (NULL terminated because class-lookup
+       depends on it... */
+    buf = ExAllocatePoolWithTag(PagedPool, ClassName.Length + sizeof(WCHAR), TAG_STRING);
+    if(!buf)
     {
-      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return NULL;
+      SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES);
+      goto Cleanup2;
     }
-
-    /* must be a direct child (not a decendant child)*/
-    IntLockRelatives(WndChildAfter);
-    if (WndChildAfter->Parent != ParentWindow->Self)
+    Status = MmCopyFromCaller(buf, ClassName.Buffer, ClassName.Length);
+    if(!NT_SUCCESS(Status))
     {
-      IntUnLockRelatives(WndChildAfter);
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      return NULL;
+      ExFreePool(buf);
+      SetLastNtError(Status);
+      goto Cleanup2;
     }
-    IntUnLockRelatives(WndChildAfter);
-    
-    WndChild = WndChildAfter->NextSibling;
+    ClassName.Buffer = buf;
+    /* make sure the string is null-terminated */
+    buf += ClassName.Length / sizeof(WCHAR);
+    *buf = L'\0';
   }
-  else
-  {
-    WndChild = ParentWindow->FirstChild;
+
+  /* find the class object */
+  if(ClassName.Buffer)
+    {
+      PWINSTATION_OBJECT WinStaObject;
+
+      if (PsGetWin32Thread()->Desktop == NULL)
+        {
+          SetLastWin32Error(ERROR_INVALID_HANDLE);
+          goto Cleanup;
+        }
+
+      WinStaObject = PsGetWin32Thread()->Desktop->WindowStation;
+
+      Status = RtlLookupAtomInAtomTable(
+         WinStaObject->AtomTable,
+         ClassName.Buffer,
+         &ClassAtom);
+
+      if (!NT_SUCCESS(Status))
+        {
+          DPRINT1("Failed to lookup class atom!\n");
+          SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+          goto Cleanup;
+        }
   }
 
-  while (WndChild)
+  if(Parent->hSelf == Desktop)
   {
-    if (classObject == WndChild->Class && (ucWindowName->Buffer==NULL || 
-        RtlCompareUnicodeString (ucWindowName, &WndChild->WindowName, TRUE) == 0))
+    HWND *List, *phWnd;
+    PWINDOW_OBJECT TopLevelWindow;
+    BOOLEAN CheckWindowName;
+    BOOLEAN CheckClassName;
+    BOOLEAN WindowMatches;
+    BOOLEAN ClassMatches;
+
+    /* windows searches through all top-level windows if the parent is the desktop
+       window */
+
+    if((List = IntWinListChildren(Parent)))
     {
-      windowHandle = WndChild->Self;
+      phWnd = List;
 
-      IntUnLockRelatives(ParentWindow);
-      IntReleaseWindowObject(ParentWindow);
-      ObmDereferenceObject (classObject);
-      
-      return windowHandle;
+      if(ChildAfter)
+      {
+        /* skip handles before and including ChildAfter */
+        while(*phWnd && (*(phWnd++) != ChildAfter->hSelf));
+      }
+
+      CheckWindowName = WindowName.Length > 0;
+      CheckClassName = ClassName.Buffer != NULL;
+
+      /* search children */
+      while(*phWnd)
+      {
+        if(!(TopLevelWindow = IntGetWindowObject(*(phWnd++))))
+        {
+          continue;
+        }
+
+        /* Do not send WM_GETTEXT messages in the kernel mode version!
+           The user mode version however calls GetWindowText() which will
+           send WM_GETTEXT messages to windows belonging to its processes */
+        WindowMatches = !CheckWindowName || !RtlCompareUnicodeString(
+                        &WindowName, &TopLevelWindow->WindowName, FALSE);
+        ClassMatches = !CheckClassName ||
+                       ClassAtom == TopLevelWindow->Class->Atom;
+
+        if (WindowMatches && ClassMatches)
+        {
+          Ret = TopLevelWindow->hSelf;
+          IntReleaseWindowObject(TopLevelWindow);
+          break;
+        }
+
+        if (IntFindWindow(TopLevelWindow, NULL, ClassAtom, &WindowName))
+        {
+          /* window returns the handle of the top-level window, in case it found
+             the child window */
+          Ret = TopLevelWindow->hSelf;
+          IntReleaseWindowObject(TopLevelWindow);
+          break;
+        }
+
+        IntReleaseWindowObject(TopLevelWindow);
+      }
+      ExFreePool(List);
     }
-    
-    WndChild = WndChild->NextSibling;
   }
+  else
+    Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
 
-  IntUnLockRelatives(ParentWindow);
+#if 0
+  if(Ret == NULL && hwndParent == NULL && hwndChildAfter == NULL)
+  {
+    /* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
+               search the message-only windows. Should this also be done if
+               Parent is the desktop window??? */
+    PWINDOW_OBJECT MsgWindows;
+
+    if((MsgWindows = IntGetWindowObject(IntGetMessageWindow())))
+    {
+      Ret = IntFindWindow(MsgWindows, ChildAfter, ClassAtom, &WindowName);
+      IntReleaseWindowObject(MsgWindows);
+    }
+  }
+#endif
+
+  Cleanup:
+  if(ClassName.Length > 0 && ClassName.Buffer)
+    ExFreePool(ClassName.Buffer);
 
-  IntReleaseWindowObject(ParentWindow);
-  ObmDereferenceObject (classObject);
+  Cleanup2:
+  RtlFreeUnicodeString(&WindowName);
 
-  return  NULL;
+  Cleanup3:
+  if(ChildAfter)
+    IntReleaseWindowObject(ChildAfter);
+  IntReleaseWindowObject(Parent);
+
+  RETURN( Ret);
+  
+CLEANUP:
+  DPRINT("Leave NtUserFindWindowEx, ret %i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 
@@ -2104,8 +2593,7 @@ NtUserFlashWindowEx(DWORD Unknown0)
 /*
  * @implemented
  */
-HWND STDCALL
-NtUserGetAncestor(HWND hWnd, UINT Type)
+HWND FASTCALL UserGetAncestor(HWND hWnd, UINT Type)
 {
    PWINDOW_OBJECT Wnd, WndAncestor, Parent;
    HWND hWndAncestor;
@@ -2124,40 +2612,38 @@ NtUserGetAncestor(HWND hWnd, UINT Type)
    switch (Type)
    {
       case GA_PARENT:
+      {
          WndAncestor = IntGetParentObject(Wnd);
          break;
+      }
 
       case GA_ROOT:
+      {
+         PWINDOW_OBJECT tmp;
          WndAncestor = Wnd;
          Parent = NULL;
-#if 0
-         while (0 != (WndAncestor->Style & WS_CHILD))
-         {
-           Parent = IntGetParentObject(WndAncestor);
-           if (WndAncestor != Wnd)
-           {
-             IntReleaseWindowObject(WndAncestor);
-           }
-           WndAncestor = Parent;
-         }
-#else
+
          for(;;)
          {
-           if(Parent)
+           tmp = Parent;
+           if(!(Parent = IntGetParentObject(WndAncestor)))
            {
-             IntReleaseWindowObject(Parent);
+             break;
            }
-           if(!(Parent = IntGetParentObject(WndAncestor)) ||
-              !IntIsDesktopWindow(WndAncestor))
+           if(IntIsDesktopWindow(Parent))
            {
+             IntReleaseWindowObject(Parent);
              break;
            }
+           if(tmp)
+             IntReleaseWindowObject(tmp);
            WndAncestor = Parent;
          }
-#endif
          break;
-    
+      }
+
       case GA_ROOTOWNER:
+      {
          WndAncestor = Wnd;
          IntReferenceWindowObject(WndAncestor);
          for (;;)
@@ -2173,27 +2659,45 @@ NtUserGetAncestor(HWND hWnd, UINT Type)
             WndAncestor = Parent;
          }
          break;
+      }
 
       default:
+      {
          IntReleaseWindowObject(Wnd);
          return NULL;
+      }
    }
-   
-   IntReleaseWindowObject(Wnd);
-   
-   if(!WndAncestor)
-   {
-     return NULL;
-   }
-   
-   hWndAncestor = WndAncestor->Self;
-   if(WndAncestor != Wnd)
+
+   hWndAncestor = (WndAncestor ? WndAncestor->hSelf : NULL);
+   IntReleaseWindowObject(Wnd);
+
+   if(WndAncestor && (WndAncestor != Wnd))
      IntReleaseWindowObject(WndAncestor);
 
    return hWndAncestor;
 }
 
 
+
+/*
+ * @implemented
+ */
+HWND STDCALL
+NtUserGetAncestor(HWND hWnd, UINT Type)
+{
+   DECLARE_RETURN(HWND);
+
+   DPRINT("Enter NtUserGetAncestor\n");
+   UserEnterExclusive();
+
+   RETURN(UserGetAncestor(hWnd, Type));
+
+CLEANUP:
+   DPRINT("Leave NtUserGetAncestor, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
 /*!
  * Returns client window rectangle relative to the upper-left corner of client area.
  *
@@ -2207,23 +2711,32 @@ NtUserGetAncestor(HWND hWnd, UINT Type)
 BOOL STDCALL
 NtUserGetClientRect(HWND hWnd, LPRECT Rect)
 {
-  PWINDOW_OBJECT WindowObject;
+  PWINDOW_OBJECT Window;
   RECT SafeRect;
+  DECLARE_RETURN(BOOL);
 
-  if(!(WindowObject = IntGetWindowObject(hWnd)))
+  DPRINT("Enter NtUserGetClientRect\n");
+  UserEnterShared();
+
+  if(!(Window = IntGetWindowObject(hWnd)))
   {
-    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);      
-    return FALSE;
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    RETURN( FALSE);
   }
 
-  IntGetClientRect(WindowObject, &SafeRect);
-  IntReleaseWindowObject(WindowObject);
-  
+  IntGetClientRect(Window, &SafeRect);
+  IntReleaseWindowObject(Window);
+
   if(!NT_SUCCESS(MmCopyToCaller(Rect, &SafeRect, sizeof(RECT))))
   {
-    return FALSE;
+    RETURN( FALSE);
   }
-  return TRUE;
+  RETURN( TRUE);
+  
+CLEANUP:
+  DPRINT("Leave NtUserGetClientRect, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 
@@ -2233,7 +2746,17 @@ NtUserGetClientRect(HWND hWnd, LPRECT Rect)
 HWND STDCALL
 NtUserGetDesktopWindow()
 {
-   return IntGetDesktopWindow();
+   DECLARE_RETURN(HWND);
+
+   DPRINT("Enter NtUserGetDesktopWindow\n");
+   UserEnterShared();
+   
+   RETURN( IntGetDesktopWindow());
+   
+CLEANUP:
+   DPRINT("Leave NtUserGetDesktopWindow, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 
@@ -2289,7 +2812,7 @@ NtUserGetLastActivePopup(HWND hWnd)
  * NtUserGetParent
  *
  * The NtUserGetParent function retrieves a handle to the specified window's
- * parent or owner. 
+ * parent or owner.
  *
  * Remarks
  *    Note that, despite its name, this function can return an owner window
@@ -2304,44 +2827,39 @@ NtUserGetParent(HWND hWnd)
 {
    PWINDOW_OBJECT Wnd, WndParent;
    HWND hWndParent = NULL;
+   DECLARE_RETURN(HWND);
+
+   DPRINT("Enter NtUserGetParent\n");
+   UserEnterExclusive();
 
    if (!(Wnd = IntGetWindowObject(hWnd)))
    {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return NULL;
+      RETURN( NULL);
    }
 
    WndParent = IntGetParent(Wnd);
    if (WndParent)
    {
-      hWndParent = WndParent->Self;
+      hWndParent = WndParent->hSelf;
       IntReleaseWindowObject(WndParent);
    }
 
    IntReleaseWindowObject(Wnd);
 
-   return hWndParent;
+   RETURN( hWndParent);
+   
+CLEANUP:
+   DPRINT("Leave NtUserGetParent, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
-/*
- * NtUserSetParent
- *
- * The NtUserSetParent function changes the parent window of the specified
- * child window. 
- *
- * Remarks
- *    The new parent window and the child window must belong to the same
- *    application. If the window identified by the hWndChild parameter is
- *    visible, the system performs the appropriate redrawing and repainting. 
- *    For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
- *    or WS_POPUP window styles of the window whose parent is being changed.
- *
- * Status
- *    @implemented
- */
 
-HWND STDCALL
-NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
+
+
+HWND FASTCALL
+UserSetParent(HWND hWndChild, HWND hWndNewParent)
 {
    PWINDOW_OBJECT Wnd = NULL, WndParent = NULL, WndOldParent;
    HWND hWndOldParent = NULL;
@@ -2349,13 +2867,13 @@ NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
    if (IntIsBroadcastHwnd(hWndChild) || IntIsBroadcastHwnd(hWndNewParent))
    {
       SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      return NULL;
+      return( NULL);
    }
-  
+
    if (hWndChild == IntGetDesktopWindow())
    {
       SetLastWin32Error(ERROR_ACCESS_DENIED);
-      return NULL;
+      return( NULL);
    }
 
    if (hWndNewParent)
@@ -2363,7 +2881,7 @@ NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
       if (!(WndParent = IntGetWindowObject(hWndNewParent)))
       {
          SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-         return NULL;
+         return( NULL);
       }
    }
    else
@@ -2371,7 +2889,7 @@ NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
       if (!(WndParent = IntGetWindowObject(IntGetDesktopWindow())))
       {
          SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-         return NULL;
+         return( NULL);
       }
    }
 
@@ -2379,53 +2897,107 @@ NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
    {
       IntReleaseWindowObject(WndParent);
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return NULL;
+      return( NULL);
    }
 
    WndOldParent = IntSetParent(Wnd, WndParent);
 
    if (WndOldParent)
    {
-      hWndOldParent = WndOldParent->Self;
+      hWndOldParent = WndOldParent->hSelf;
       IntReleaseWindowObject(WndOldParent);
    }
 
    IntReleaseWindowObject(Wnd);
    IntReleaseWindowObject(WndParent);
 
-   return hWndOldParent;
+   return( hWndOldParent);
 }
 
+
+
 /*
- * NtUserGetShellWindow
+ * NtUserSetParent
  *
- * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
+ * The NtUserSetParent function changes the parent window of the specified
+ * child window.
+ *
+ * Remarks
+ *    The new parent window and the child window must belong to the same
+ *    application. If the window identified by the hWndChild parameter is
+ *    visible, the system performs the appropriate redrawing and repainting.
+ *    For compatibility reasons, NtUserSetParent does not modify the WS_CHILD
+ *    or WS_POPUP window styles of the window whose parent is being changed.
  *
  * Status
  *    @implemented
  */
 
 HWND STDCALL
-NtUserGetShellWindow()
+NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
+{
+   DECLARE_RETURN(HWND);
+
+   DPRINT("Enter NtUserSetParent\n");
+   UserEnterExclusive();
+
+   RETURN( UserSetParent(hWndChild, hWndNewParent));
+   
+CLEANUP:
+   DPRINT("Leave NtUserSetParent, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
+
+
+
+HWND FASTCALL UserGetShellWindow()
 {
   PWINSTATION_OBJECT WinStaObject;
   HWND Ret;
 
-  NTSTATUS Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
-                                      KernelMode,
-                                      0,
-                                      &WinStaObject);
-  
+  NTSTATUS Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
+                   KernelMode,
+                   0,
+                   &WinStaObject);
+
   if (!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
-    return (HWND)0;
+    return( (HWND)0);
   }
-  
+
   Ret = (HWND)WinStaObject->ShellWindow;
-  
+
   ObDereferenceObject(WinStaObject);
-  return Ret;
+  return( Ret);
+}
+
+
+/*
+ * NtUserGetShellWindow
+ *
+ * Returns a handle to shell window that was set by NtUserSetShellWindowEx.
+ *
+ * Status
+ *    @implemented
+ */
+
+HWND STDCALL
+NtUserGetShellWindow()
+{
+  DECLARE_RETURN(HWND);
+
+  DPRINT("Enter NtUserGetShellWindow\n");
+  UserEnterShared();
+
+  RETURN( UserGetShellWindow() );
+  
+CLEANUP:
+  DPRINT("Leave NtUserGetShellWindow, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 /*
@@ -2442,25 +3014,29 @@ BOOL STDCALL
 NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
 {
   PWINSTATION_OBJECT WinStaObject;
+  DECLARE_RETURN(BOOL);
 
-  NTSTATUS Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
+  DPRINT("Enter NtUserSetShellWindowEx\n");
+  UserEnterExclusive();
+
+  NTSTATUS Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
                                       KernelMode,
                                       0,
                                       &WinStaObject);
-  
+
   if (!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
-    return FALSE;
+    RETURN( FALSE);
   }
-  
+
    /*
     * Test if we are permitted to change the shell window.
     */
    if (WinStaObject->ShellWindow)
    {
       ObDereferenceObject(WinStaObject);
-      return FALSE;
+      RETURN( FALSE);
    }
 
    /*
@@ -2473,29 +3049,34 @@ NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
  * -- Filip, 01/nov/2003
  */
 #if 0
-       WinPosSetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+       co_WinPosSetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
 #endif
 
-      if (NtUserGetWindowLong(hwndListView, GWL_EXSTYLE, FALSE) & WS_EX_TOPMOST)
+      if (UserGetWindowLong(hwndListView, GWL_EXSTYLE, FALSE) & WS_EX_TOPMOST)
       {
          ObDereferenceObject(WinStaObject);
-         return FALSE;
+         RETURN( FALSE);
       }
    }
 
-   if (NtUserGetWindowLong(hwndShell, GWL_EXSTYLE, FALSE) & WS_EX_TOPMOST)
+   if (UserGetWindowLong(hwndShell, GWL_EXSTYLE, FALSE) & WS_EX_TOPMOST)
    {
       ObDereferenceObject(WinStaObject);
-      return FALSE;
+      RETURN( FALSE);
    }
 
-   WinPosSetWindowPos(hwndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+   co_WinPosSetWindowPos(hwndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
 
    WinStaObject->ShellWindow = hwndShell;
    WinStaObject->ShellListView = hwndListView;
-   
+
    ObDereferenceObject(WinStaObject);
-   return TRUE;
+   RETURN( TRUE);
+   
+CLEANUP:
+  DPRINT("Leave NtUserSetShellWindowEx, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 /*
@@ -2503,23 +3084,23 @@ NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
  *
  * The NtUserGetSystemMenu function allows the application to access the
  * window menu (also known as the system menu or the control menu) for
- * copying and modifying. 
+ * copying and modifying.
  *
  * Parameters
- *    hWnd 
- *       Handle to the window that will own a copy of the window menu. 
- *    bRevert 
+ *    hWnd
+ *       Handle to the window that will own a copy of the window menu.
+ *    bRevert
  *       Specifies the action to be taken. If this parameter is FALSE,
  *       NtUserGetSystemMenu returns a handle to the copy of the window menu
  *       currently in use. The copy is initially identical to the window menu
- *       but it can be modified. 
+ *       but it can be modified.
  *       If this parameter is TRUE, GetSystemMenu resets the window menu back
  *       to the default state. The previous window menu, if any, is destroyed.
  *
  * Return Value
  *    If the bRevert parameter is FALSE, the return value is a handle to a
  *    copy of the window menu. If the bRevert parameter is TRUE, the return
- *    value is NULL. 
+ *    value is NULL.
  *
  * Status
  *    @implemented
@@ -2529,25 +3110,32 @@ HMENU STDCALL
 NtUserGetSystemMenu(HWND hWnd, BOOL bRevert)
 {
    HMENU Result = 0;
-   PWINDOW_OBJECT WindowObject;
-   PMENU_OBJECT MenuObject;
+   PWINDOW_OBJECT Window;
+   PMENU_OBJECT Menu;
+   DECLARE_RETURN(HMENU);
+
+   DPRINT("Enter NtUserGetSystemMenu\n");
+   UserEnterShared();
 
-   WindowObject = IntGetWindowObject((HWND)hWnd);
-   if (WindowObject == NULL)
+   if (!(Window = IntGetWindowObject(hWnd)))
    {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return 0;
+      RETURN( 0);
    }
-  
-   MenuObject = IntGetSystemMenu(WindowObject, bRevert, FALSE);
-   if (MenuObject)
+
+   if (!(Menu = IntGetSystemMenu(Window, bRevert, FALSE)))
    {
-      Result = MenuObject->MenuInfo.Self;
-      IntReleaseMenuObject(MenuObject);
+      Result = Menu->MenuInfo.Self;
+      IntReleaseMenuObject(Menu);
    }
-  
-   IntReleaseWindowObject(WindowObject);
-   return Result;
+
+   IntReleaseWindowObject(Window);
+   RETURN( Result);
+   
+CLEANUP:
+   DPRINT("Leave NtUserGetSystemMenu, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 /*
@@ -2561,230 +3149,219 @@ BOOL STDCALL
 NtUserSetSystemMenu(HWND hWnd, HMENU hMenu)
 {
    BOOL Result = FALSE;
-   PWINDOW_OBJECT WindowObject;
-   PMENU_OBJECT MenuObject;
+   PWINDOW_OBJECT Window;
+   PMENU_OBJECT Menu;
+   DECLARE_RETURN(BOOL);
 
-   WindowObject = IntGetWindowObject(hWnd);
-   if (!WindowObject)
+   DPRINT("Enter NtUserSetSystemMenu\n");
+   UserEnterExclusive();
+
+   if (!(Window = IntGetWindowObject(hWnd)))
    {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return FALSE;
+      RETURN( FALSE);
    }
-  
+
    if (hMenu)
    {
       /*
        * Assign new menu handle.
        */
-      MenuObject = IntGetMenuObject(hMenu);
-      if (!MenuObject)
+      Menu = IntGetMenuObject(hMenu);
+      if (!Menu)
       {
-         IntReleaseWindowObject(WindowObject);
+         IntReleaseWindowObject(Window);
          SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
-         return FALSE;
+         RETURN( FALSE);
       }
-    
-      Result = IntSetSystemMenu(WindowObject, MenuObject);
-    
-      IntReleaseMenuObject(MenuObject);
+
+      Result = IntSetSystemMenu(Window, Menu);
+
+      IntReleaseMenuObject(Menu);
    }
-  
-   IntReleaseWindowObject(WindowObject);
-   return Result;
+
+   IntReleaseWindowObject(Window);
+
+   RETURN( Result);
+   
+CLEANUP:
+   DPRINT("Leave NtUserSetSystemMenu, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
-/*
- * NtUserGetWindow
- *
- * The NtUserGetWindow function retrieves a handle to a window that has the
- * specified relationship (Z order or owner) to the specified window.
- *
- * Status
- *    @implemented
- */
 
-HWND STDCALL
-NtUserGetWindow(HWND hWnd, UINT Relationship)
+
+
+HWND FASTCALL
+UserGetWindow(HWND hWnd, UINT Relationship)
 {
-   PWINDOW_OBJECT WindowObject, Parent;
+   PWINDOW_OBJECT Parent, Window;
    HWND hWndResult = NULL;
 
-   if (!(WindowObject = IntGetWindowObject(hWnd)))
-   {
-      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return NULL;
-   }
-  
+   if (!(Window = UserGetWindowObjectNoRef(hWnd))) return NULL;
+
    switch (Relationship)
    {
       case GW_HWNDFIRST:
-         if((Parent = IntGetParentObject(WindowObject)))
+         if((Parent = Window->Parent))
          {
-           IntLockRelatives(Parent);
            if (Parent->FirstChild)
-              hWndResult = Parent->FirstChild->Self;
-           IntUnLockRelatives(Parent);
-           IntReleaseWindowObject(Parent);
+              hWndResult = Parent->FirstChild->hSelf;
          }
          break;
 
       case GW_HWNDLAST:
-         if((Parent = IntGetParentObject(WindowObject)))
+         if((Parent = Window->Parent))
          {
-           IntLockRelatives(Parent);
            if (Parent->LastChild)
-              hWndResult = Parent->LastChild->Self;
-           IntUnLockRelatives(Parent);
-           IntReleaseWindowObject(Parent);
+              hWndResult = Parent->LastChild->hSelf;
          }
          break;
 
       case GW_HWNDNEXT:
-         IntLockRelatives(WindowObject);
-         if (WindowObject->NextSibling)
-            hWndResult = WindowObject->NextSibling->Self;
-         IntUnLockRelatives(WindowObject);
+         if (Window->NextSibling)
+            hWndResult = Window->NextSibling->hSelf;
          break;
 
       case GW_HWNDPREV:
-         IntLockRelatives(WindowObject);
-         if (WindowObject->PrevSibling)
-            hWndResult = WindowObject->PrevSibling->Self;
-         IntUnLockRelatives(WindowObject);
+         if (Window->PrevSibling)
+            hWndResult = Window->PrevSibling->hSelf;
          break;
 
       case GW_OWNER:
-         IntLockRelatives(WindowObject);
-         if((Parent = IntGetWindowObject(WindowObject->Owner)))
+         if((Parent = IntGetWindowObject(Window->hOwner)))
          {
-           hWndResult = Parent->Self;
+           hWndResult = Parent->hSelf;
            IntReleaseWindowObject(Parent);
          }
-         IntUnLockRelatives(WindowObject);
          break;
       case GW_CHILD:
-         IntLockRelatives(WindowObject);
-         if (WindowObject->FirstChild)
-            hWndResult = WindowObject->FirstChild->Self;
-         IntUnLockRelatives(WindowObject);
+         if (Window->FirstChild)
+            hWndResult = Window->FirstChild->hSelf;
          break;
    }
 
-   IntReleaseWindowObject(WindowObject);
-
    return hWndResult;
 }
 
+
+
 /*
- * NtUserGetWindowDC
+ * NtUserGetWindow
  *
- * The NtUserGetWindowDC function retrieves the device context (DC) for the
- * entire window, including title bar, menus, and scroll bars. A window device
- * context permits painting anywhere in a window, because the origin of the
- * device context is the upper-left corner of the window instead of the client
- * area. 
+ * The NtUserGetWindow function retrieves a handle to a window that has the
+ * specified relationship (Z order or owner) to the specified window.
  *
  * Status
  *    @implemented
  */
 
-DWORD STDCALL
-NtUserGetWindowDC(HWND hWnd)
+HWND STDCALL
+NtUserGetWindow(HWND hWnd, UINT Relationship)
 {
-   return (DWORD)NtUserGetDCEx(hWnd, 0, DCX_USESTYLE | DCX_WINDOW);
+   DECLARE_RETURN(HWND);
+   
+   DPRINT("Enter NtUserGetWindow\n");
+   UserEnterShared();
+   
+   RETURN(UserGetWindow(hWnd, Relationship));
+   
+CLEANUP:
+   DPRINT("Leave NtUserGetWindow, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
+
+
+
 /*
  * NtUserGetWindowLong
  *
  * The NtUserGetWindowLong function retrieves information about the specified
  * window. The function also retrieves the 32-bit (long) value at the
- * specified offset into the extra window memory. 
+ * specified offset into the extra window memory.
  *
  * Status
  *    @implemented
  */
 
-LONG STDCALL
-NtUserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi)
+LONG FASTCALL
+UserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi)
 {
-   PWINDOW_OBJECT WindowObject, Parent;
-   LONG Result;
+   PWINDOW_OBJECT Window, Parent;
+   LONG Result = 0;
 
    DPRINT("NtUserGetWindowLong(%x,%d,%d)\n", hWnd, (INT)Index, Ansi);
 
-   WindowObject = IntGetWindowObject(hWnd);
-   if (WindowObject == NULL)
+   if (!(Window = IntGetWindowObject(hWnd)))
    {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
       return 0;
    }
 
    /*
-    * Only allow CSRSS to mess with the desktop window
+    * WndProc is only available to the owner process
     */
-   if (hWnd == IntGetDesktopWindow()
-       && WindowObject->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
+   if (GWL_WNDPROC == Index
+       && Window->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
    {
-      SetLastWin32Error(STATUS_ACCESS_DENIED);
+      SetLastWin32Error(ERROR_ACCESS_DENIED);
       return 0;
    }
 
    if ((INT)Index >= 0)
    {
-      if ((Index + sizeof(LONG)) > WindowObject->ExtraDataSize)
+      if ((Index + sizeof(LONG)) > Window->ExtraDataSize)
       {
          SetLastWin32Error(ERROR_INVALID_PARAMETER);
          return 0;
       }
-      Result = *((LONG *)(WindowObject->ExtraData + Index));
+      Result = *((LONG *)(Window->ExtraData + Index));
    }
    else
    {
       switch (Index)
       {
          case GWL_EXSTYLE:
-            Result = WindowObject->ExStyle;
+            Result = Window->ExStyle;
             break;
 
          case GWL_STYLE:
-            Result = WindowObject->Style;
+            Result = Window->Style;
             break;
 
          case GWL_WNDPROC:
             if (Ansi)
-               Result = (LONG) WindowObject->WndProcA;
+               Result = (LONG) Window->WndProcA;
             else
-               Result = (LONG) WindowObject->WndProcW;
+               Result = (LONG) Window->WndProcW;
             break;
 
          case GWL_HINSTANCE:
-            Result = (LONG) WindowObject->Instance;
+            Result = (LONG) Window->Instance;
             break;
 
          case GWL_HWNDPARENT:
-            IntLockRelatives(WindowObject);
-            Parent = IntGetWindowObject(WindowObject->Parent);
-            IntUnLockRelatives(WindowObject);
+            Parent = Window->Parent;
             if(Parent)
             {
-              if (Parent && Parent->Self == IntGetDesktopWindow())
-                 Result = (LONG) NtUserGetWindow(WindowObject->Self, GW_OWNER);
+              if (Parent && Parent->hSelf == IntGetDesktopWindow())
+                 Result = (LONG) UserGetWindow(Window->hSelf, GW_OWNER);
               else
-                 Result = (LONG) Parent->Self;
-              IntReleaseWindowObject(Parent);
+                 Result = (LONG) Parent->hSelf;
             }
             break;
 
          case GWL_ID:
-            Result = (LONG) WindowObject->IDMenu;
+            Result = (LONG) Window->IDMenu;
             break;
 
          case GWL_USERDATA:
-            Result = WindowObject->UserData;
+            Result = Window->UserData;
             break;
-    
+
          default:
             DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index);
             SetLastWin32Error(ERROR_INVALID_PARAMETER);
@@ -2793,27 +3370,48 @@ NtUserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi)
       }
    }
 
-   IntReleaseWindowObject(WindowObject);
+   IntReleaseWindowObject(Window);
 
    return Result;
 }
 
+
+
+
 /*
- * NtUserSetWindowLong
+ * NtUserGetWindowLong
  *
- * The NtUserSetWindowLong function changes an attribute of the specified
- * window. The function also sets the 32-bit (long) value at the specified
- * offset into the extra window memory. 
+ * The NtUserGetWindowLong function retrieves information about the specified
+ * window. The function also retrieves the 32-bit (long) value at the
+ * specified offset into the extra window memory.
  *
  * Status
  *    @implemented
  */
 
 LONG STDCALL
-NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
+NtUserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi)
+{
+   DECLARE_RETURN(LONG);
+
+   DPRINT("Enter NtUserGetWindowLong(%x,%d,%d)\n", hWnd, (INT)Index, Ansi);
+   UserEnterExclusive();
+
+   RETURN(UserGetWindowLong(hWnd, Index, Ansi));
+
+CLEANUP:
+   DPRINT("Leave NtUserGetWindowLong, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
+
+
+
+LONG FASTCALL
+UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
 {
-   PWINDOW_OBJECT WindowObject, Parent;
-   PW32PROCESS Process;
+   PWINDOW_OBJECT Window, Parent;
    PWINSTATION_OBJECT WindowStation;
    LONG OldValue;
    STYLESTRUCT Style;
@@ -2821,104 +3419,102 @@ NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
    if (hWnd == IntGetDesktopWindow())
    {
       SetLastWin32Error(STATUS_ACCESS_DENIED);
-      return 0;
+      return( 0);
    }
 
-   WindowObject = IntGetWindowObject(hWnd);
-   if (WindowObject == NULL)
+   if (!(Window = IntGetWindowObject(hWnd)))
    {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return 0;
+      return( 0);
    }
 
    if ((INT)Index >= 0)
    {
-      if ((Index + sizeof(LONG)) > WindowObject->ExtraDataSize)
+      if ((Index + sizeof(LONG)) > Window->ExtraDataSize)
       {
          SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         IntReleaseWindowObject(WindowObject);
-         return 0;
+         IntReleaseWindowObject(Window);
+         return( 0);
       }
-      OldValue = *((LONG *)(WindowObject->ExtraData + Index));
-      *((LONG *)(WindowObject->ExtraData + Index)) = NewValue;
+      OldValue = *((LONG *)(Window->ExtraData + Index));
+      *((LONG *)(Window->ExtraData + Index)) = NewValue;
    }
    else
    {
       switch (Index)
       {
          case GWL_EXSTYLE:
-            OldValue = (LONG) WindowObject->ExStyle;
+            OldValue = (LONG) Window->ExStyle;
             Style.styleOld = OldValue;
             Style.styleNew = NewValue;
 
             /*
              * Remove extended window style bit WS_EX_TOPMOST for shell windows.
              */
-            Process = WindowObject->OwnerThread->ThreadsProcess->Win32Process;
-            WindowStation = Process->WindowStation;
+            WindowStation = Window->OwnerThread->Tcb.Win32Thread->Desktop->WindowStation;
             if(WindowStation)
             {
               if (hWnd == WindowStation->ShellWindow || hWnd == WindowStation->ShellListView)
                  Style.styleNew &= ~WS_EX_TOPMOST;
             }
 
-            IntSendMessage(hWnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM) &Style);
-            WindowObject->ExStyle = (DWORD)Style.styleNew;
-            IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
+            co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_EXSTYLE, (LPARAM) &Style);
+            Window->ExStyle = (DWORD)Style.styleNew;
+            co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
             break;
 
          case GWL_STYLE:
-            OldValue = (LONG) WindowObject->Style;
+            OldValue = (LONG) Window->Style;
             Style.styleOld = OldValue;
             Style.styleNew = NewValue;
-            IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
-            WindowObject->Style = (DWORD)Style.styleNew;
-            IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
+            co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
+            Window->Style = (DWORD)Style.styleNew;
+            co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
             break;
 
          case GWL_WNDPROC:
             /* FIXME: should check if window belongs to current process */
             if (Ansi)
             {
-               OldValue = (LONG) WindowObject->WndProcA;
-               WindowObject->WndProcA = (WNDPROC) NewValue;
-               WindowObject->WndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,FALSE);
-               WindowObject->Unicode = FALSE;
+               OldValue = (LONG) Window->WndProcA;
+               Window->WndProcA = (WNDPROC) NewValue;
+               Window->WndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,FALSE);
+               Window->Unicode = FALSE;
             }
             else
             {
-               OldValue = (LONG) WindowObject->WndProcW;
-               WindowObject->WndProcW = (WNDPROC) NewValue;
-               WindowObject->WndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,TRUE);
-               WindowObject->Unicode = TRUE;
+               OldValue = (LONG) Window->WndProcW;
+               Window->WndProcW = (WNDPROC) NewValue;
+               Window->WndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,TRUE);
+               Window->Unicode = TRUE;
             }
             break;
 
          case GWL_HINSTANCE:
-            OldValue = (LONG) WindowObject->Instance;
-            WindowObject->Instance = (HINSTANCE) NewValue;
+            OldValue = (LONG) Window->Instance;
+            Window->Instance = (HINSTANCE) NewValue;
             break;
 
          case GWL_HWNDPARENT:
-            Parent = IntGetParentObject(WindowObject);
-            if (Parent && (Parent->Self == IntGetDesktopWindow()))
-               OldValue = (LONG) IntSetOwner(WindowObject->Self, (HWND) NewValue);
+            Parent = IntGetParentObject(Window);
+            if (Parent && (Parent->hSelf == IntGetDesktopWindow()))
+               OldValue = (LONG) IntSetOwner(Window->hSelf, (HWND) NewValue);
             else
-               OldValue = (LONG) NtUserSetParent(WindowObject->Self, (HWND) NewValue);
+               OldValue = (LONG) UserSetParent(Window->hSelf, (HWND) NewValue);
             if(Parent)
               IntReleaseWindowObject(Parent);
             break;
 
          case GWL_ID:
-            OldValue = (LONG) WindowObject->IDMenu;
-            WindowObject->IDMenu = (UINT) NewValue;
+            OldValue = (LONG) Window->IDMenu;
+            Window->IDMenu = (UINT) NewValue;
             break;
 
          case GWL_USERDATA:
-            OldValue = WindowObject->UserData;
-            WindowObject->UserData = NewValue;
+            OldValue = Window->UserData;
+            Window->UserData = NewValue;
             break;
-    
+
          default:
             DPRINT1("NtUserSetWindowLong(): Unsupported index %d\n", Index);
             SetLastWin32Error(ERROR_INVALID_PARAMETER);
@@ -2927,9 +3523,38 @@ NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
       }
    }
 
-   IntReleaseWindowObject(WindowObject);
-   return OldValue;
+   IntReleaseWindowObject(Window);
+
+   return( OldValue);
+}
+
+
+
+/*
+ * NtUserSetWindowLong
+ *
+ * The NtUserSetWindowLong function changes an attribute of the specified
+ * window. The function also sets the 32-bit (long) value at the specified
+ * offset into the extra window memory.
+ *
+ * Status
+ *    @implemented
+ */
+
+LONG STDCALL
+NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
+{
+   DECLARE_RETURN(LONG);
+
+   DPRINT("Enter NtUserSetWindowLong\n");
+   UserEnterExclusive();
+
+   RETURN( UserSetWindowLong(hWnd, Index, NewValue, Ansi));
+   
+CLEANUP:
+   DPRINT("Leave NtUserSetWindowLong, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 /*
@@ -2944,43 +3569,51 @@ NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
 WORD STDCALL
 NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewValue)
 {
-   PWINDOW_OBJECT WindowObject;
+   PWINDOW_OBJECT Window;
    WORD OldValue;
+   DECLARE_RETURN(WORD);
+   
+   DPRINT("Enter NtUserSetWindowWord\n");
+   UserEnterExclusive();
 
    switch (Index)
    {
       case GWL_ID:
       case GWL_HINSTANCE:
       case GWL_HWNDPARENT:
-         return NtUserSetWindowLong(hWnd, Index, (UINT)NewValue, TRUE);
+         RETURN( UserSetWindowLong(hWnd, Index, (UINT)NewValue, TRUE));
       default:
          if (Index < 0)
          {
             SetLastWin32Error(ERROR_INVALID_INDEX);
-            return 0;
+            RETURN( 0);
          }
    }
 
-   WindowObject = IntGetWindowObject(hWnd);
-   if (WindowObject == NULL)
+   if (!(Window = IntGetWindowObject(hWnd)))
    {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return 0;
+      RETURN( 0);
    }
 
-   if (Index > WindowObject->ExtraDataSize - sizeof(WORD))
+   if (Index > Window->ExtraDataSize - sizeof(WORD))
    {
       SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      IntReleaseWindowObject(WindowObject);
-      return 0;
+      IntReleaseWindowObject(Window);
+      RETURN( 0);
    }
 
-   OldValue = *((WORD *)(WindowObject->ExtraData + Index));
-   *((WORD *)(WindowObject->ExtraData + Index)) = NewValue;
+   OldValue = *((WORD *)(Window->ExtraData + Index));
+   *((WORD *)(Window->ExtraData + Index)) = NewValue;
 
-   IntReleaseWindowObject(WindowObject);
+   IntReleaseWindowObject(Window);
 
-   return OldValue;
+   RETURN( OldValue);
+   
+CLEANUP:
+  DPRINT("Leave NtUserSetWindowWord, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 /*
@@ -2990,39 +3623,42 @@ BOOL STDCALL
 NtUserGetWindowPlacement(HWND hWnd,
                         WINDOWPLACEMENT *lpwndpl)
 {
-  PWINDOW_OBJECT WindowObject;
+  PWINDOW_OBJECT Window;
   PINTERNALPOS InternalPos;
   POINT Size;
   WINDOWPLACEMENT Safepl;
   NTSTATUS Status;
-  
-  WindowObject = IntGetWindowObject(hWnd);
-  if (WindowObject == NULL)
+  DECLARE_RETURN(BOOL);
+   
+  DPRINT("Enter NtUserGetWindowPlacement\n");
+  UserEnterShared();
+
+  if (!(Window = IntGetWindowObject(hWnd)))
   {
     SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-    return FALSE;
+    RETURN( FALSE);
   }
-  
+
   Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
   if(!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
-    IntReleaseWindowObject(WindowObject);
-    return FALSE;
+    IntReleaseWindowObject(Window);
+    RETURN( FALSE);
   }
   if(Safepl.length != sizeof(WINDOWPLACEMENT))
   {
-    IntReleaseWindowObject(WindowObject);
-    return FALSE;
+    IntReleaseWindowObject(Window);
+    RETURN( FALSE);
   }
-  
+
   Safepl.flags = 0;
-  Safepl.showCmd = ((WindowObject->Flags & WINDOWOBJECT_RESTOREMAX) ? SW_MAXIMIZE : SW_SHOWNORMAL);
-  
-  Size.x = WindowObject->WindowRect.left;
-  Size.y = WindowObject->WindowRect.top;
-  InternalPos = WinPosInitInternalPos(WindowObject, &Size, 
-                                     &WindowObject->WindowRect);
+  Safepl.showCmd = ((Window->Flags & WINDOWOBJECT_RESTOREMAX) ? SW_MAXIMIZE : SW_SHOWNORMAL);
+
+  Size.x = Window->WindowRect.left;
+  Size.y = Window->WindowRect.top;
+  InternalPos = WinPosInitInternalPos(Window, &Size,
+                                     &Window->WindowRect);
   if (InternalPos)
   {
     Safepl.rcNormalPosition = InternalPos->NormalRect;
@@ -3031,20 +3667,25 @@ NtUserGetWindowPlacement(HWND hWnd,
   }
   else
   {
-    IntReleaseWindowObject(WindowObject);
-    return FALSE;
+    IntReleaseWindowObject(Window);
+    RETURN( FALSE);
   }
-  
+
   Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
   if(!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
-    IntReleaseWindowObject(WindowObject);
-    return FALSE;
+    IntReleaseWindowObject(Window);
+    RETURN( FALSE);
   }
+
+  IntReleaseWindowObject(Window);
+  RETURN( TRUE);
   
-  IntReleaseWindowObject(WindowObject);
-  return TRUE;
+CLEANUP:
+  DPRINT("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 
@@ -3061,22 +3702,31 @@ NtUserGetWindowRect(HWND hWnd, LPRECT Rect)
 {
   PWINDOW_OBJECT Wnd;
   NTSTATUS Status;
+  DECLARE_RETURN(BOOL);
+   
+  DPRINT("Enter NtUserGetWindowRect\n");
+  UserEnterShared();
 
   if (!(Wnd = IntGetWindowObject(hWnd)))
   {
-    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);      
-    return FALSE;
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    RETURN(FALSE);
   }
   Status = MmCopyToCaller(Rect, &Wnd->WindowRect, sizeof(RECT));
   if (!NT_SUCCESS(Status))
   {
     IntReleaseWindowObject(Wnd);
     SetLastNtError(Status);
-    return FALSE;
+    RETURN( FALSE);
   }
-  
+
   IntReleaseWindowObject(Wnd);
-  return TRUE;
+  RETURN( TRUE);
+  
+CLEANUP:
+  DPRINT("Leave NtUserGetWindowRect, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 
@@ -3088,19 +3738,28 @@ NtUserGetWindowThreadProcessId(HWND hWnd, LPDWORD UnsafePid)
 {
    PWINDOW_OBJECT Wnd;
    DWORD tid, pid;
+   DECLARE_RETURN(DWORD);
    
+   DPRINT("Enter NtUserGetWindowThreadProcessId\n");
+   UserEnterShared();
+
    if (!(Wnd = IntGetWindowObject(hWnd)))
    {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return 0;
+      RETURN( 0);
    }
 
    tid = (DWORD)IntGetWndThreadId(Wnd);
    pid = (DWORD)IntGetWndProcessId(Wnd);
-   
+
    if (UnsafePid) MmCopyToCaller(UnsafePid, &pid, sizeof(DWORD));
+
+   RETURN( tid);
    
-   return tid;
+CLEANUP:
+   DPRINT("Leave NtUserGetWindowThreadProcessId, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 
@@ -3120,7 +3779,7 @@ NtUserLockWindowUpdate(DWORD Unknown0)
  * @implemented
  */
 BOOL STDCALL
-NtUserMoveWindow(      
+NtUserMoveWindow(
     HWND hWnd,
     int X,
     int Y,
@@ -3128,8 +3787,8 @@ NtUserMoveWindow(
     int nHeight,
     BOOL bRepaint)
 {
-       return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight, 
-                              (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE : 
+       return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight,
+                              (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE :
                                SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW));
 }
 
@@ -3153,23 +3812,31 @@ NtUserQueryWindow(HWND hWnd, DWORD Index)
 {
    PWINDOW_OBJECT Window = IntGetWindowObject(hWnd);
    DWORD Result;
+   DECLARE_RETURN(UINT);
+   
+   DPRINT("Enter NtUserQueryWindow\n");
+   UserEnterShared();
 
    if (Window == NULL)
    {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return 0;
+      RETURN( 0);
    }
 
    switch(Index)
    {
-      case 0x00:
+      case QUERY_WINDOW_UNIQUE_PROCESS_ID:
          Result = (DWORD)IntGetWndProcessId(Window);
          break;
 
-      case 0x01:
+      case QUERY_WINDOW_UNIQUE_THREAD_ID:
          Result = (DWORD)IntGetWndThreadId(Window);
          break;
 
+      case QUERY_WINDOW_ISHUNG:
+         Result = (DWORD)MsqIsHung(Window->MessageQueue);
+         break;
+
       default:
          Result = (DWORD)NULL;
          break;
@@ -3177,7 +3844,13 @@ NtUserQueryWindow(HWND hWnd, DWORD Index)
 
    IntReleaseWindowObject(Window);
 
-   return Result;
+   RETURN( Result);
+   
+  
+CLEANUP:
+   DPRINT("Leave NtUserQueryWindow, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 
@@ -3201,76 +3874,36 @@ NtUserRealChildWindowFromPoint(DWORD Unknown0,
 UINT STDCALL
 NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe)
 {
-#if 0
-  PLIST_ENTRY Current;
-  PREGISTERED_MESSAGE NewMsg, RegMsg;
-  UINT Msg = REGISTERED_MESSAGE_MIN;
-  UNICODE_STRING MessageName;
+  UNICODE_STRING SafeMessageName;
   NTSTATUS Status;
+  UINT Ret;
+  DECLARE_RETURN(UINT);
+   
+  DPRINT("Enter NtUserRegisterWindowMessage\n");
+  UserEnterExclusive();
 
-  Status = MmCopyFromCaller(&MessageName, MessageNameUnsafe, sizeof(UNICODE_STRING));
-  if (! NT_SUCCESS(Status))
-    {
-      SetLastNtError(Status);
-      return 0;
-    }
-
-  NewMsg = ExAllocatePoolWithTag(PagedPool,
-                                 sizeof(REGISTERED_MESSAGE) +
-                                 MessageName.Length,
-                                 TAG_WNAM);
-  if (NULL == NewMsg)
-    {
-      SetLastNtError(STATUS_NO_MEMORY);
-      return 0;
-    }
-
-  Status = MmCopyFromCaller(NewMsg->MessageName, MessageName.Buffer, MessageName.Length);
-  if (! NT_SUCCESS(Status))
-    {
-      ExFreePool(NewMsg);
-      SetLastNtError(Status);
-      return 0;
-    }
-  NewMsg->MessageName[MessageName.Length / sizeof(WCHAR)] = L'\0';
-  if (wcslen(NewMsg->MessageName) != MessageName.Length / sizeof(WCHAR))
-    {
-      ExFreePool(NewMsg);
-      SetLastNtError(STATUS_INVALID_PARAMETER);
-      return 0;
-    }
-
-  Current = RegisteredMessageListHead.Flink;
-  while (Current != &RegisteredMessageListHead)
-    {
-      RegMsg = CONTAINING_RECORD(Current, REGISTERED_MESSAGE, ListEntry);
-      if (0 == wcscmp(NewMsg->MessageName, RegMsg->MessageName))
-       {
-         ExFreePool(NewMsg);
-         return Msg;
-       }
-      Msg++;
-      Current = Current->Flink;
-    }
+  if(MessageNameUnsafe == NULL)
+  {
+    SetLastWin32Error(ERROR_INVALID_PARAMETER);
+    RETURN( 0);
+  }
 
-  if (REGISTERED_MESSAGE_MAX < Msg)
-    {
-      ExFreePool(NewMsg);
-      SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
-      return 0;
-    }
+  Status = IntSafeCopyUnicodeStringTerminateNULL(&SafeMessageName, MessageNameUnsafe);
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastNtError(Status);
+    RETURN( 0);
+  }
 
-  InsertTailList(&RegisteredMessageListHead, &(NewMsg->ListEntry));
+  Ret = (UINT)IntAddAtom(SafeMessageName.Buffer);
 
-  return Msg;
-#else
-   /*
-    * Notes:
-    * - There's no need to call MmSafe*, because it should be done in kernel.
-    * - The passed UNICODE_STRING is expected to be NULL-terminated.
-    */
-   return (UINT)IntAddAtom(MessageNameUnsafe->Buffer);
-#endif
+  RtlFreeUnicodeString(&SafeMessageName);
+  RETURN( Ret);
+  
+CLEANUP:
+  DPRINT("Leave NtUserRegisterWindowMessage, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 
@@ -3335,35 +3968,43 @@ NtUserSetLogonNotifyWindow(DWORD Unknown0)
  */
 BOOL STDCALL
 NtUserSetMenu(
-   HWND Wnd,
+   HWND hWnd,
    HMENU Menu,
    BOOL Repaint)
 {
-  PWINDOW_OBJECT WindowObject;
+  PWINDOW_OBJECT Window;
   BOOL Changed;
+  DECLARE_RETURN(BOOL);
+   
+  DPRINT("Enter NtUserSetMenu\n");
+  UserEnterExclusive();
 
-  WindowObject = IntGetWindowObject((HWND) Wnd);
-  if (NULL == WindowObject)
+  if (!(Window = IntGetWindowObject(hWnd)))
     {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return FALSE;
+      RETURN( FALSE);
     }
-  
-  if (! IntSetMenu(WindowObject, Menu, &Changed))
+
+  if (! IntSetMenu(Window, Menu, &Changed))
     {
-      IntReleaseWindowObject(WindowObject);
-      return FALSE;
+      IntReleaseWindowObject(Window);
+      RETURN( FALSE);
     }
-  
-  IntReleaseWindowObject(WindowObject);
-  
+
+  IntReleaseWindowObject(Window);
+
   if (Changed && Repaint)
     {
-      WinPosSetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+      co_WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
                          SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
     }
+
+  RETURN( TRUE);
   
-  return TRUE;
+CLEANUP:
+  DPRINT("Leave NtUserSetMenu, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 
@@ -3388,49 +4029,57 @@ BOOL STDCALL
 NtUserSetWindowPlacement(HWND hWnd,
                         WINDOWPLACEMENT *lpwndpl)
 {
-  PWINDOW_OBJECT WindowObject;
+  PWINDOW_OBJECT Window;
   WINDOWPLACEMENT Safepl;
   NTSTATUS Status;
+  DECLARE_RETURN(BOOL);
+   
+  DPRINT("Enter NtUserSetWindowPlacement\n");
+  UserEnterExclusive();
 
-  WindowObject = IntGetWindowObject(hWnd);
-  if (WindowObject == NULL)
+  if (!(Window = IntGetWindowObject(hWnd)))
   {
     SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-    return FALSE;
+    RETURN( FALSE);
   }
   Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
   if(!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
-    IntReleaseWindowObject(WindowObject);
-    return FALSE;
+    IntReleaseWindowObject(Window);
+    RETURN( FALSE);
   }
   if(Safepl.length != sizeof(WINDOWPLACEMENT))
   {
-    IntReleaseWindowObject(WindowObject);
-    return FALSE;
+    IntReleaseWindowObject(Window);
+    RETURN( FALSE);
   }
-  
-  if ((WindowObject->Style & (WS_MAXIMIZE | WS_MINIMIZE)) == 0)
+
+  if ((Window->Style & (WS_MAXIMIZE | WS_MINIMIZE)) == 0)
   {
-     WinPosSetWindowPos(WindowObject->Self, NULL,
+     co_WinPosSetWindowPos(Window->hSelf, NULL,
         Safepl.rcNormalPosition.left, Safepl.rcNormalPosition.top,
         Safepl.rcNormalPosition.right - Safepl.rcNormalPosition.left,
         Safepl.rcNormalPosition.bottom - Safepl.rcNormalPosition.top,
         SWP_NOZORDER | SWP_NOACTIVATE);
   }
-  
+
   /* FIXME - change window status */
-  WinPosShowWindow(WindowObject->Self, Safepl.showCmd);
+  co_WinPosShowWindow(Window->hSelf, Safepl.showCmd);
 
-  if (WindowObject->InternalPos == NULL)
-     WindowObject->InternalPos = ExAllocatePoolWithTag(PagedPool, sizeof(INTERNALPOS), TAG_WININTLIST);
-  WindowObject->InternalPos->NormalRect = Safepl.rcNormalPosition;
-  WindowObject->InternalPos->IconPos = Safepl.ptMinPosition;
-  WindowObject->InternalPos->MaxPos = Safepl.ptMaxPosition;
+  if (Window->InternalPos == NULL)
+     Window->InternalPos = ExAllocatePoolWithTag(PagedPool, sizeof(INTERNALPOS), TAG_WININTLIST);
+  Window->InternalPos->NormalRect = Safepl.rcNormalPosition;
+  Window->InternalPos->IconPos = Safepl.ptMinPosition;
+  Window->InternalPos->MaxPos = Safepl.ptMaxPosition;
 
-  IntReleaseWindowObject(WindowObject);
-  return TRUE;
+  IntReleaseWindowObject(Window);
+  RETURN( TRUE);
+  
+CLEANUP:
+  DPRINT("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 
@@ -3438,7 +4087,7 @@ NtUserSetWindowPlacement(HWND hWnd,
  * @implemented
  */
 BOOL STDCALL
-NtUserSetWindowPos(      
+NtUserSetWindowPos(
     HWND hWnd,
     HWND hWndInsertAfter,
     int X,
@@ -3447,7 +4096,17 @@ NtUserSetWindowPos(
     int cy,
     UINT uFlags)
 {
-   return WinPosSetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
+   DECLARE_RETURN(BOOL);
+   
+   DPRINT("Enter NtUserSetWindowPos\n");
+   UserEnterExclusive();
+   
+   RETURN( co_WinPosSetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags));
+   
+CLEANUP:
+   DPRINT("Leave NtUserSetWindowPos, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 
@@ -3455,41 +4114,41 @@ INT FASTCALL
 IntGetWindowRgn(HWND hWnd, HRGN hRgn)
 {
   INT Ret;
-  PWINDOW_OBJECT WindowObject;
+  PWINDOW_OBJECT Window;
   HRGN VisRgn;
   ROSRGNDATA *pRgn;
-  
-  if(!(WindowObject = IntGetWindowObject(hWnd)))
+
+  if(!(Window = IntGetWindowObject(hWnd)))
   {
     SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
     return ERROR;
   }
   if(!hRgn)
   {
-    IntReleaseWindowObject(WindowObject);
+    IntReleaseWindowObject(Window);
     return ERROR;
   }
-  
+
   /* Create a new window region using the window rectangle */
-  VisRgn = UnsafeIntCreateRectRgnIndirect(&WindowObject->WindowRect);
-  NtGdiOffsetRgn(VisRgn, -WindowObject->WindowRect.left, -WindowObject->WindowRect.top);
+  VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
+  NtGdiOffsetRgn(VisRgn, -Window->WindowRect.left, -Window->WindowRect.top);
   /* if there's a region assigned to the window, combine them both */
-  if(WindowObject->WindowRegion && !(WindowObject->Style & WS_MINIMIZE))
-    NtGdiCombineRgn(VisRgn, VisRgn, WindowObject->WindowRegion, RGN_AND);
+  if(Window->WindowRegion && !(Window->Style & WS_MINIMIZE))
+    NtGdiCombineRgn(VisRgn, VisRgn, Window->WindowRegion, RGN_AND);
   /* Copy the region into hRgn */
   NtGdiCombineRgn(hRgn, VisRgn, NULL, RGN_COPY);
-  
+
   if((pRgn = RGNDATA_LockRgn(hRgn)))
   {
     Ret = pRgn->rdh.iType;
-    RGNDATA_UnlockRgn(hRgn);
+    RGNDATA_UnlockRgn(pRgn);
   }
   else
     Ret = ERROR;
-  
+
   NtGdiDeleteObject(VisRgn);
-  
-  IntReleaseWindowObject(WindowObject);
+
+  IntReleaseWindowObject(Window);
   return Ret;
 }
 
@@ -3497,40 +4156,40 @@ INT FASTCALL
 IntGetWindowRgnBox(HWND hWnd, RECT *Rect)
 {
   INT Ret;
-  PWINDOW_OBJECT WindowObject;
+  PWINDOW_OBJECT Window;
   HRGN VisRgn;
   ROSRGNDATA *pRgn;
-  
-  if(!(WindowObject = IntGetWindowObject(hWnd)))
+
+  if(!(Window = IntGetWindowObject(hWnd)))
   {
     SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
     return ERROR;
   }
   if(!Rect)
   {
-    IntReleaseWindowObject(WindowObject);
+    IntReleaseWindowObject(Window);
     return ERROR;
   }
-  
+
   /* Create a new window region using the window rectangle */
-  VisRgn = UnsafeIntCreateRectRgnIndirect(&WindowObject->WindowRect);
-  NtGdiOffsetRgn(VisRgn, -WindowObject->WindowRect.left, -WindowObject->WindowRect.top);
+  VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
+  NtGdiOffsetRgn(VisRgn, -Window->WindowRect.left, -Window->WindowRect.top);
   /* if there's a region assigned to the window, combine them both */
-  if(WindowObject->WindowRegion && !(WindowObject->Style & WS_MINIMIZE))
-    NtGdiCombineRgn(VisRgn, VisRgn, WindowObject->WindowRegion, RGN_AND);
-  
+  if(Window->WindowRegion && !(Window->Style & WS_MINIMIZE))
+    NtGdiCombineRgn(VisRgn, VisRgn, Window->WindowRegion, RGN_AND);
+
   if((pRgn = RGNDATA_LockRgn(VisRgn)))
   {
     Ret = pRgn->rdh.iType;
     *Rect = pRgn->rdh.rcBound;
-    RGNDATA_UnlockRgn(VisRgn);
+    RGNDATA_UnlockRgn(pRgn);
   }
   else
     Ret = ERROR;
-  
+
   NtGdiDeleteObject(VisRgn);
-  
-  IntReleaseWindowObject(WindowObject);
+
+  IntReleaseWindowObject(Window);
   return Ret;
 }
 
@@ -3544,34 +4203,42 @@ NtUserSetWindowRgn(
   HRGN hRgn,
   BOOL bRedraw)
 {
-  PWINDOW_OBJECT WindowObject;
+  PWINDOW_OBJECT Window;
+  DECLARE_RETURN(INT);
+  
+  DPRINT("Enter NtUserSetWindowRgn\n");
+  UserEnterExclusive();
   
-  WindowObject = IntGetWindowObject(hWnd);
-  if (WindowObject == NULL)
+  if (!(Window = IntGetWindowObject(hWnd)))
   {
     SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-    return 0;
+    RETURN( 0);
   }
-  
+
   /* FIXME - Verify if hRgn is a valid handle!!!!
              Propably make this operation thread-safe, but maybe it's not necessary */
-  
-  if(WindowObject->WindowRegion)
+
+  if(Window->WindowRegion)
   {
     /* Delete no longer needed region handle */
-    NtGdiDeleteObject(WindowObject->WindowRegion);
+    NtGdiDeleteObject(Window->WindowRegion);
   }
-  WindowObject->WindowRegion = hRgn;
-  
+  Window->WindowRegion = hRgn;
+
   /* FIXME - send WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED messages to the window */
-  
+
   if(bRedraw)
   {
-    IntRedrawWindow(WindowObject, NULL, NULL, RDW_INVALIDATE);
+    co_UserRedrawWindow(Window, NULL, NULL, RDW_INVALIDATE);
   }
+
+  IntReleaseWindowObject(Window);
+  RETURN( (INT)hRgn);
   
-  IntReleaseWindowObject(WindowObject);
-  return (INT)hRgn;
+CLEANUP:
+  DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 
@@ -3582,7 +4249,17 @@ BOOL STDCALL
 NtUserShowWindow(HWND hWnd,
                 LONG nCmdShow)
 {
-   return WinPosShowWindow(hWnd, nCmdShow);
+  DECLARE_RETURN(BOOL);
+
+  DPRINT("Enter NtUserShowWindow\n");
+  UserEnterExclusive();
+   
+  RETURN( co_WinPosShowWindow(hWnd, nCmdShow));
+   
+CLEANUP:
+  DPRINT("Leave NtUserShowWindow, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 
@@ -3638,28 +4315,38 @@ NtUserWindowFromPoint(LONG X, LONG Y)
    POINT pt;
    HWND Ret;
    PWINDOW_OBJECT DesktopWindow, Window = NULL;
+   DECLARE_RETURN(HWND);
+
+   DPRINT("Enter NtUserWindowFromPoint\n");
+   UserEnterExclusive();
 
    if ((DesktopWindow = IntGetWindowObject(IntGetDesktopWindow())))
    {
       USHORT Hit;
-      
+
       pt.x = X;
       pt.y = Y;
-      
-      Hit = WinPosWindowFromPoint(DesktopWindow, TRUE, &pt, &Window);
-      
+
+      Hit = co_WinPosWindowFromPoint(DesktopWindow, PsGetWin32Thread()->MessageQueue, &pt, &Window);
+
       if(Window)
       {
-        Ret = Window->Self;
+        Ret = Window->hSelf;
         IntReleaseWindowObject(Window);
         IntReleaseWindowObject(DesktopWindow);
-        return Ret;
+        RETURN( Ret);
       }
-      
+
       IntReleaseWindowObject(DesktopWindow);
    }
-  
-   return NULL;
+
+   RETURN( NULL);
+   
+CLEANUP:
+   DPRINT("Leave NtUserWindowFromPoint, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+   
 }
 
 
@@ -3669,81 +4356,155 @@ NtUserWindowFromPoint(LONG X, LONG Y)
  * Undocumented function that is called from DefWindowProc to set
  * window text.
  *
- * FIXME: Call this from user32.dll!
- *
  * Status
- *    @unimplemented
+ *    @implemented
  */
 
 BOOL STDCALL
-NtUserDefSetText(HWND WindowHandle, PANSI_STRING Text)
+NtUserDefSetText(HWND hWnd, PUNICODE_STRING WindowText)
 {
-   PWINDOW_OBJECT WindowObject;
-   UNICODE_STRING NewWindowName;
-   BOOL Result = FALSE;
+  PWINDOW_OBJECT Window, Parent, Owner;
+  UNICODE_STRING SafeText;
+  NTSTATUS Status;
+  DECLARE_RETURN(INT);
+   
+  DPRINT("Enter NtUserDefSetText\n");
+  UserEnterExclusive();
 
-   WindowObject = IntGetWindowObject(WindowHandle);
-   if (!WindowObject)
-   {
-      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return FALSE;
-   }
+  if(!(Window = IntGetWindowObject(hWnd)))
+  {
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    RETURN( FALSE);
+  }
 
-   if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NewWindowName, Text, TRUE)))
-   {
-      RtlFreeUnicodeString(&WindowObject->WindowName);
-      WindowObject->WindowName.Buffer = NewWindowName.Buffer;
-      WindowObject->WindowName.Length = NewWindowName.Length;
-      WindowObject->WindowName.MaximumLength = NewWindowName.MaximumLength;
-      Result = TRUE;
-   }
+  if(WindowText)
+  {
+    Status = IntSafeCopyUnicodeString(&SafeText, WindowText);
+    if(!NT_SUCCESS(Status))
+    {
+      SetLastNtError(Status);
+      IntReleaseWindowObject(Window);
+      RETURN( FALSE);
+    }
+  }
+  else
+  {
+    RtlInitUnicodeString(&SafeText, NULL);
+  }
 
-   IntReleaseWindowObject(WindowObject);
+  /* FIXME - do this thread-safe! otherwise one could crash here! */
+  RtlFreeUnicodeString(&Window->WindowName);
 
-   return Result;
+  Window->WindowName = SafeText;
+
+  /* Send shell notifications */
+
+  Owner = IntGetOwner(Window);
+  Parent = IntGetParent(Window);
+
+  if ((!Owner) && (!Parent))
+  {
+    co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) hWnd);
+  }
+
+  if (Owner)
+  {
+    IntReleaseWindowObject(Owner);
+  }
+
+  if (Parent)
+  {
+    IntReleaseWindowObject(Parent);
+  }
+
+  IntReleaseWindowObject(Window);
+  RETURN( TRUE);
+  
+CLEANUP:
+  DPRINT("Leave NtUserDefSetText, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 /*
  * NtUserInternalGetWindowText
  *
- * FIXME: Call this from user32.dll!
- *
  * Status
  *    @implemented
  */
 
-DWORD STDCALL
-NtUserInternalGetWindowText(HWND WindowHandle, LPWSTR Text, INT MaxCount)
+INT STDCALL
+NtUserInternalGetWindowText(HWND hWnd, LPWSTR lpString, INT nMaxCount)
 {
-   PWINDOW_OBJECT WindowObject;
-   DWORD Result;
+  PWINDOW_OBJECT Window;
+  NTSTATUS Status;
+  INT Result;
+  DECLARE_RETURN(INT);
+   
+  DPRINT("Enter NtUserInternalGetWindowText\n");
+  UserEnterShared();
 
-   WindowObject = IntGetWindowObject(WindowHandle);
-   if (!WindowObject)
-   {
-      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return 0;
-   }
+  if(lpString && (nMaxCount <= 1))
+  {
+    SetLastWin32Error(ERROR_INVALID_PARAMETER);
+    RETURN( 0);
+  }
 
-   Result = WindowObject->WindowName.Length / sizeof(WCHAR);
-   if (Text)
-   {
-      /* FIXME: Shouldn't it be always NULL terminated? */
-      wcsncpy(Text, WindowObject->WindowName.Buffer, MaxCount);
-      if (MaxCount < Result)
+  if(!(Window = IntGetWindowObject(hWnd)))
+  {
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    RETURN( 0);
+  }
+
+  /* FIXME - do this thread-safe! otherwise one could crash here! */
+  Result = Window->WindowName.Length / sizeof(WCHAR);
+  if(lpString)
+  {
+    const WCHAR Terminator = L'\0';
+    INT Copy;
+    WCHAR *Buffer = (WCHAR*)lpString;
+
+    Copy = min(nMaxCount - 1, Result);
+    if(Copy > 0)
+    {
+      Status = MmCopyToCaller(Buffer, Window->WindowName.Buffer, Copy * sizeof(WCHAR));
+      if(!NT_SUCCESS(Status))
       {
-         Result = MaxCount;
+        SetLastNtError(Status);
+        IntReleaseWindowObject(Window);
+        RETURN( 0);
       }
-   }
+      Buffer += Copy;
+    }
 
-   IntReleaseWindowObject(WindowObject);
+    Status = MmCopyToCaller(Buffer, &Terminator, sizeof(WCHAR));
+    if(!NT_SUCCESS(Status))
+    {
+      SetLastNtError(Status);
+      IntReleaseWindowObject(Window);
+      RETURN( 0);
+    }
 
-   return Result;
+    Result = Copy;
+  }
+
+  IntReleaseWindowObject(Window);
+  RETURN( Result);
+  
+CLEANUP:
+  DPRINT("Leave NtUserInternalGetWindowText, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 DWORD STDCALL
 NtUserDereferenceWndProcHandle(WNDPROC wpHandle, WndProcHandle *Data)
 {
+   DECLARE_RETURN(DWORD);
+   
+   DPRINT("Enter NtUserDereferenceWndProcHandle\n");
+   UserEnterShared();
+   
        WndProcHandle Entry;
        if (((DWORD)wpHandle & 0xFFFF0000) == 0xFFFF0000)
        {
@@ -3751,18 +4512,23 @@ NtUserDereferenceWndProcHandle(WNDPROC wpHandle, WndProcHandle *Data)
                Data->WindowProc = Entry.WindowProc;
                Data->IsUnicode = Entry.IsUnicode;
                Data->ProcessID = Entry.ProcessID;
-               return TRUE;
+      RETURN(  TRUE);
        } else {
-               return FALSE;
+      RETURN(  FALSE);
        }
-       return FALSE;
+       RETURN( FALSE);
+   
+CLEANUP:
+  DPRINT("Leave NtUserDereferenceWndProcHandle, ret=%i\n",_ret_);
+  UserLeave();
+  END_CLEANUP;
 }
 
 DWORD
 IntAddWndProcHandle(WNDPROC WindowProc, BOOL IsUnicode)
 {
        WORD i;
-       WORD FreeSpot;
+       WORD FreeSpot = 0;
        BOOL found;
        WndProcHandle *OldArray;
        WORD OldArraySize;
@@ -3822,4 +4588,65 @@ IntRemoveProcessWndProcHandles(HANDLE ProcessID)
        return TRUE;
 }
 
+#define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
+
+BOOL
+FASTCALL
+IntShowOwnedPopups( HWND owner, BOOL fShow )
+{
+  int count = 0;
+  PWINDOW_OBJECT Window, pWnd;
+  HWND *win_array;
+
+  if(!(Window = IntGetWindowObject(owner)))
+  {
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    return FALSE;
+  }
+
+  win_array = IntWinListChildren( Window);
+  IntReleaseWindowObject(Window);
+
+  if (!win_array) return TRUE;
+
+  while (win_array[count]) count++;
+  while (--count >= 0)
+    {
+        if (UserGetWindow( win_array[count], GW_OWNER ) != owner) continue;
+        if (!(pWnd = IntGetWindowObject( win_array[count] ))) continue;
+//        if (pWnd == WND_OTHER_PROCESS) continue;
+
+        if (fShow)
+        {
+            if (pWnd->Flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
+             {
+                IntReleaseWindowObject( pWnd );
+                /* In Windows, ShowOwnedPopups(TRUE) generates
+                 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
+                 * regardless of the state of the owner
+                 */
+                co_IntSendMessage(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
+                continue;
+            }
+        }
+        else
+        {
+            if (pWnd->Style & WS_VISIBLE)
+            {
+                IntReleaseWindowObject( pWnd );
+                /* In Windows, ShowOwnedPopups(FALSE) generates
+                 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
+                 * regardless of the state of the owner
+                 */
+                co_IntSendMessage(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
+                continue;
+            }
+        }
+        IntReleaseWindowObject( pWnd );
+    }
+    ExFreePool( win_array );
+    return TRUE;
+}
+
+
 /* EOF */