fix bug 838 (Sol.exe is missing it's menubar)
[reactos.git] / reactos / subsys / win32k / ntuser / class.c
index 84bdaee..94e4cc0 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: class.c,v 1.51 2004/04/09 20:03:19 navaraf Exp $
+/* $Id$
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  */
 /* INCLUDES ******************************************************************/
 
-#include <ddk/ntddk.h>
-#include <win32k/win32k.h>
-#include <napi/win32.h>
-#include <include/class.h>
-#include <include/error.h>
-#include <include/winsta.h>
-#include <include/object.h>
-#include <include/guicheck.h>
-#include <include/window.h>
-#include <include/color.h>
-#include <include/tags.h>
-#include <internal/safe.h>
+#include <w32k.h>
 
 #define NDEBUG
 #include <debug.h>
 NTSTATUS FASTCALL
 InitClassImpl(VOID)
 {
-  return(STATUS_SUCCESS);
+   return(STATUS_SUCCESS);
 }
 
 NTSTATUS FASTCALL
 CleanupClassImpl(VOID)
 {
-  return(STATUS_SUCCESS);
+   return(STATUS_SUCCESS);
 }
 
 
-NTSTATUS FASTCALL
-ClassReferenceClassByAtom(PWNDCLASS_OBJECT* Class,
-                         RTL_ATOM Atom)
+inline VOID FASTCALL 
+ClassDerefObject(PWNDCLASS_OBJECT Class)
 {
-  PWNDCLASS_OBJECT Current;
-  PLIST_ENTRY CurrentEntry;
-  PW32PROCESS Process = PsGetWin32Process();
-  
-  IntLockProcessClasses(Process);
-  CurrentEntry = Process->ClassListHead.Flink;
-  while (CurrentEntry != &Process->ClassListHead)
-    {
-    Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, ListEntry);
-      
-       if (Current->Atom == Atom)
-       {
-       *Class = Current;
-       ObmReferenceObject(Current);
-       IntUnLockProcessClasses(Process);
-       return(STATUS_SUCCESS);
-       }
-
-       CurrentEntry = CurrentEntry->Flink;
-    }
-  IntUnLockProcessClasses(Process);
-  
-  return(STATUS_NOT_FOUND);
+   ASSERT(Class->refs >= 1);
+   Class->refs--;   
 }
 
-NTSTATUS STDCALL
-ClassReferenceClassByName(PWNDCLASS_OBJECT *Class,
-                         LPCWSTR ClassName)
+
+inline VOID FASTCALL 
+ClassRefObject(PWNDCLASS_OBJECT Class)
 {
-  PWINSTATION_OBJECT WinStaObject;
-  NTSTATUS Status;
-  RTL_ATOM ClassAtom;
-
-  if (!ClassName)
-    {
-      return(STATUS_INVALID_PARAMETER);
-    }
-
-  Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
-                                         KernelMode,
-                                         0,
-                                         &WinStaObject);
-  if (!NT_SUCCESS(Status))
-    {
-      DPRINT("Validation of window station handle (0x%X) failed\n",
-            PROCESS_WINDOW_STATION());
-      return(STATUS_UNSUCCESSFUL);
-    }
-
-  Status  = RtlLookupAtomInAtomTable(WinStaObject->AtomTable,
-                                    (LPWSTR)ClassName,
-                                    &ClassAtom);
-
-  if (!NT_SUCCESS(Status))
-    {
-      ObDereferenceObject(WinStaObject);  
-      return(Status);
-    }
-  Status = ClassReferenceClassByAtom(Class,
-                                    ClassAtom);
-  
-  ObDereferenceObject(WinStaObject);  
-  return(Status);
+   ASSERT(Class->refs >= 0);
+   Class->refs++;
 }
 
-NTSTATUS FASTCALL
-ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class,
-                               LPCWSTR ClassNameOrAtom)
+
+VOID FASTCALL DestroyClass(PWNDCLASS_OBJECT Class)
 {
-  NTSTATUS Status;
-
-  if (IS_ATOM(ClassNameOrAtom))
-    {
-      Status = ClassReferenceClassByAtom(Class, 
-                                 (RTL_ATOM)((ULONG_PTR)ClassNameOrAtom));
-  }
-  else
-    {
-      Status = ClassReferenceClassByName(Class, 
-                                        ClassNameOrAtom);
-    }
-
-  if (!NT_SUCCESS(Status))
-    {
-      SetLastNtError(Status);
-    }
-  
-  return(Status);
+   ASSERT(Class->refs == 0);
+   
+   RemoveEntryList(&Class->ListEntry);
+   if (Class->hMenu)
+      UserDestroyMenu(Class->hMenu);
+   RtlDeleteAtomFromAtomTable(gAtomTable, Class->Atom);
+   ExFreePool(Class);
 }
 
-DWORD STDCALL
-NtUserGetClassInfo(HINSTANCE hInstance, LPCWSTR lpClassName,
-   LPWNDCLASSEXW lpWndClassEx, BOOL Ansi, DWORD unknown3)
+
+/* clean all process classes. all process windows must cleaned first!! */
+void FASTCALL DestroyProcessClasses(PW32PROCESS Process )
+{
+   PWNDCLASS_OBJECT Class;
+
+   while (!IsListEmpty(&Process->ClassList))
+   {
+      Class = CONTAINING_RECORD(RemoveHeadList(&Process->ClassList), WNDCLASS_OBJECT, ListEntry);
+      DestroyClass(Class);
+   }
+}
+
+
+
+
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByAtom(RTL_ATOM Atom, HINSTANCE hInstance)
 {
    PWNDCLASS_OBJECT Class;
+   PW32PROCESS Process = PsGetWin32Process();
+
+   LIST_FOR_EACH(Class, &Process->ClassList, WNDCLASS_OBJECT, ListEntry)
+   {
+      if (Class->Atom != Atom) continue;
+
+      if (!hInstance || Class->Global || Class->hInstance == hInstance) return Class;
+   }
+   
+   return NULL;
+}
+
+
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByName(LPCWSTR ClassName, HINSTANCE hInstance)
+{
    NTSTATUS Status;
    RTL_ATOM Atom;
 
-   DPRINT("NtUserGetClassInfo(%S)\n", lpClassName);
-   Status = ClassReferenceClassByNameOrAtom(&Class, lpClassName);
+   if (!ClassName || !PsGetWin32Thread()->Desktop)
+      return FALSE;
+
+   Status = RtlLookupAtomInAtomTable(
+               gAtomTable,
+               (LPWSTR)ClassName,
+               &Atom);
+
    if (!NT_SUCCESS(Status))
    {
-      DPRINT("Error (%x)\n", Status);
-      SetLastNtError(Status);
-      return 0;
+      DPRINT1("Failed to lookup class atom!\n");
+      return FALSE;
    }
-   lpWndClassEx->cbSize = sizeof(LPWNDCLASSEXW);
-   lpWndClassEx->style = Class->style;
-   if (Ansi)
-      lpWndClassEx->lpfnWndProc = Class->lpfnWndProcA;
+
+   return ClassGetClassByAtom(Atom, hInstance);
+}
+
+
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByNameOrAtom(LPCWSTR ClassNameOrAtom, HINSTANCE hInstance)
+{
+   if (!ClassNameOrAtom) return NULL;
+   
+   if (IS_ATOM(ClassNameOrAtom))
+      return ClassGetClassByAtom((RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance);
    else
-      lpWndClassEx->lpfnWndProc = Class->lpfnWndProcW;
-   DPRINT("%x\n", lpWndClassEx->lpfnWndProc);
-   lpWndClassEx->cbClsExtra = Class->cbClsExtra;
-   lpWndClassEx->cbWndExtra = Class->cbWndExtra;
-   lpWndClassEx->hInstance = Class->hInstance;
-   lpWndClassEx->hIcon = Class->hIcon;
-   lpWndClassEx->hCursor = Class->hCursor;
-   lpWndClassEx->hbrBackground = Class->hbrBackground;
-   if (Class->lpszMenuName)
+      return ClassGetClassByName(ClassNameOrAtom, hInstance);
+}
+
+
+static
+BOOL FASTCALL
+IntRegisterClass(
+   CONST WNDCLASSEXW *lpwcx,
+   DWORD Flags,
+   WNDPROC wpExtra,
+   PUNICODE_STRING MenuName,
+   RTL_ATOM Atom,
+   HMENU hMenu)
+{
+   PWNDCLASS_OBJECT Class;
+   ULONG  objectSize;
+   BOOL Global;
+
+   ASSERT(lpwcx);
+   ASSERT(Atom);
+   ASSERT(lpwcx->hInstance);
+
+   Global = (Flags & REGISTERCLASS_SYSTEM) || (lpwcx->style & CS_GLOBALCLASS);
+
+   /* Check for double registration of the class. */
+   Class = ClassGetClassByAtom(Atom, lpwcx->hInstance);
+   if (Class && Global == Class->Global)
+   {
+      /* can max have one class of each type (global/local) */
+      SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
+      return(FALSE);
+   }
+
+   objectSize = sizeof(WNDCLASS_OBJECT) + lpwcx->cbClsExtra;
+   
+   //FIXME: allocate in session heap (or possibly desktop heap)
+   Class = ExAllocatePool(PagedPool, objectSize);
+   if (!Class)
+   {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return(FALSE);
+   }
+   RtlZeroMemory(Class, objectSize);
+
+   Class->cbSize = lpwcx->cbSize;
+   Class->style = lpwcx->style;
+   Class->cbClsExtra = lpwcx->cbClsExtra;
+   Class->cbWndExtra = lpwcx->cbWndExtra;
+   Class->hInstance = lpwcx->hInstance;
+   Class->hIcon = lpwcx->hIcon;
+   Class->hCursor = lpwcx->hCursor;
+   Class->hMenu = hMenu;
+   Class->hbrBackground = lpwcx->hbrBackground;
+   Class->Unicode = !(Flags & REGISTERCLASS_ANSI);
+   Class->Global = Global;
+   Class->hIconSm = lpwcx->hIconSm;
+   Class->Atom = Atom;
+   
+   if (wpExtra == NULL)
    {
-      if (!IS_INTRESOURCE((LPCWSTR)Class->lpszMenuName))
-         RtlCopyUnicodeString((PUNICODE_STRING)lpWndClassEx->lpszMenuName, Class->lpszMenuName);
+      if (Flags & REGISTERCLASS_ANSI)
+      {
+         Class->lpfnWndProcA = lpwcx->lpfnWndProc;
+         Class->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
+      }
       else
-         lpWndClassEx->lpszMenuName = (LPCWSTR)Class->lpszMenuName;
+      {
+         Class->lpfnWndProcW = lpwcx->lpfnWndProc;
+         Class->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
+      }
    }
    else
-      lpWndClassEx->lpszMenuName = (LPCWSTR)NULL;
-   lpWndClassEx->lpszClassName = lpClassName;
-   lpWndClassEx->hIconSm = Class->hIconSm;
-   Atom = Class->Atom;
+   {
+      if (Flags & REGISTERCLASS_ANSI)
+      {
+         Class->lpfnWndProcA = lpwcx->lpfnWndProc;
+         Class->lpfnWndProcW = wpExtra;
+      }
+      else
+      {
+         Class->lpfnWndProcW = lpwcx->lpfnWndProc;
+         Class->lpfnWndProcA = wpExtra;
+      }
+   }
+   
+   if (MenuName->Length == 0)
+   {
+      Class->lpszMenuName.Length =
+         Class->lpszMenuName.MaximumLength = 0;
+      Class->lpszMenuName.Buffer = MenuName->Buffer;
+   }
+   else
+   {
+      Class->lpszMenuName.Length =
+         Class->lpszMenuName.MaximumLength = MenuName->MaximumLength;
+      Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Class->lpszMenuName.MaximumLength, TAG_STRING);
+      RtlCopyUnicodeString(&Class->lpszMenuName, MenuName);
+   }
    
-   ObmDereferenceObject(Class);
+   /* Extra class data */
+   if (Class->cbClsExtra)
+      Class->ExtraData = (PCHAR)(Class + 1);
 
-   return Atom;
+   if (Global)
+   {
+      /* global classes go last (incl. system classes) */
+      InsertTailList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
+   }
+   else
+   {
+      /* local classes have priority so we put them first */
+      InsertHeadList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
+   }
+   
+   return TRUE;
 }
 
+
 ULONG FASTCALL
-IntGetClassName(struct _WINDOW_OBJECT *WindowObject, LPWSTR lpClassName,
-   ULONG nMaxCount)
+IntGetClassLong(PWINDOW_OBJECT Window, ULONG Offset, BOOL Ansi)
 {
-   ULONG Length;
-   LPWSTR Name;
-   PWINSTATION_OBJECT WinStaObject;
-   NTSTATUS Status;
+   LONG Ret;
 
-   Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
-      KernelMode, 0, &WinStaObject);
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT("Validation of window station handle (0x%X) failed\n",
-         PROCESS_WINDOW_STATION());
-      return 0;
-   }
-   Length = 0;
-   Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,
-      WindowObject->Class->Atom, NULL, NULL, Name, &Length);
-   Name = ExAllocatePoolWithTag(NonPagedPool, Length + sizeof(UNICODE_NULL), TAG_STRING);
-   Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,
-      WindowObject->Class->Atom, NULL, NULL, Name, &Length);
-   if (!NT_SUCCESS(Status))
+   if ((int)Offset >= 0)
    {
-      DPRINT("IntGetClassName: RtlQueryAtomInAtomTable failed\n");
-      return 0;
+      DPRINT("GetClassLong(%x, %d)\n", Window->hSelf, Offset);
+      if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra)
+      {
+         SetLastWin32Error(ERROR_INVALID_PARAMETER);
+         return 0;
+      }
+      Ret = *((LONG *)(Window->Class->ExtraData + Offset));
+      DPRINT("Result: %x\n", Ret);
+      return Ret;
    }
-   Length /= sizeof(WCHAR);
-   if (Length > nMaxCount)
+
+   switch (Offset)
    {
-      Length = nMaxCount;
+      case GCL_CBWNDEXTRA:
+         Ret = Window->Class->cbWndExtra;
+         break;
+      case GCL_CBCLSEXTRA:
+         Ret = Window->Class->cbClsExtra;
+         break;
+      case GCL_HBRBACKGROUND:
+         Ret = (ULONG)Window->Class->hbrBackground;
+         break;
+      case GCL_HCURSOR:
+         Ret = (ULONG)Window->Class->hCursor;
+         break;
+      case GCL_HICON:
+         Ret = (ULONG)Window->Class->hIcon;
+         break;
+      case GCL_HICONSM:
+         Ret = (ULONG)Window->Class->hIconSm;
+         break;
+      case GCL_HMODULE:
+         Ret = (ULONG)Window->Class->hInstance;
+         break;
+      case GCL_MENUNAME:
+         Ret = (ULONG)Window->Class->lpszMenuName.Buffer;
+         break;
+      case GCL_STYLE:
+         Ret = Window->Class->style;
+         break;
+      case GCL_WNDPROC:
+         if (Ansi)
+         {
+            Ret = (ULONG)Window->Class->lpfnWndProcA;
+         }
+         else
+         {
+            Ret = (ULONG)Window->Class->lpfnWndProcW;
+         }
+         break;
+      case GCW_ATOM:
+         Ret = Window->Class->Atom;
+         break;
+      default:
+         Ret = 0;
+         break;
    }
-   wcsncpy(lpClassName, Name, Length);
-   /* FIXME: Check buffer size before doing this! */
-   *(lpClassName + Length) = 0;
-   ExFreePool(Name);
-   ObDereferenceObject(WinStaObject);
-
-   return Length;
+   return(Ret);
 }
 
-DWORD STDCALL
-NtUserGetClassName (
-  HWND hWnd,
-  LPWSTR lpClassName,
-  ULONG nMaxCount)
+static
+void FASTCALL
+co_IntSetClassLong(PWINDOW_OBJECT Window, ULONG Offset, LONG dwNewLong, BOOL Ansi)
 {
-   PWINDOW_OBJECT WindowObject;
-   LONG Length;
+   ASSERT_REFS_CO(Window);
 
-   WindowObject = IntGetWindowObject(hWnd);
-   if (WindowObject == NULL)
+   if ((int)Offset >= 0)
    {
-      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return 0;
+      DPRINT("SetClassLong(%x, %d, %x)\n", Window->hSelf, Offset, dwNewLong);
+      if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra)
+      {
+         SetLastWin32Error(ERROR_INVALID_PARAMETER);
+         return;
+      }
+      *((LONG *)(Window->Class->ExtraData + Offset)) = dwNewLong;
+      return;
    }
-   Length = IntGetClassName(WindowObject, lpClassName, nMaxCount);
-   IntReleaseWindowObject(WindowObject);
-   return Length;
-}
 
-DWORD STDCALL
-NtUserGetWOWClass(DWORD Unknown0,
-                 DWORD Unknown1)
-{
-  UNIMPLEMENTED;
-  return(0);
+   switch (Offset)
+   {
+      case GCL_CBWNDEXTRA:
+         Window->Class->cbWndExtra = dwNewLong;
+         break;
+      case GCL_CBCLSEXTRA:
+         Window->Class->cbClsExtra = dwNewLong;
+         break;
+      case GCL_HBRBACKGROUND:
+         Window->Class->hbrBackground = (HBRUSH)dwNewLong;
+         break;
+      case GCL_HCURSOR:
+         Window->Class->hCursor = (HCURSOR)dwNewLong;
+         break;
+      case GCL_HICON:
+         Window->Class->hIcon = (HICON)dwNewLong;
+
+         if (!IntGetOwner(Window) && !IntGetParent(Window))
+         {
+            co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) Window->hSelf);
+         }
+         break;
+      case GCL_HICONSM:
+         Window->Class->hIconSm = (HICON)dwNewLong;
+         break;
+      case GCL_HMODULE:
+         Window->Class->hInstance = (HINSTANCE)dwNewLong;
+         break;
+      case GCL_MENUNAME:
+         if (Window->Class->lpszMenuName.MaximumLength)
+            RtlFreeUnicodeString(&Window->Class->lpszMenuName);
+         if (!IS_INTRESOURCE(dwNewLong))
+         {
+            Window->Class->lpszMenuName.Length =
+               Window->Class->lpszMenuName.MaximumLength = ((PUNICODE_STRING)dwNewLong)->MaximumLength;
+            Window->Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Window->Class->lpszMenuName.MaximumLength, TAG_STRING);
+            RtlCopyUnicodeString(&Window->Class->lpszMenuName, (PUNICODE_STRING)dwNewLong);
+         }
+         else
+         {
+            Window->Class->lpszMenuName.Length =
+               Window->Class->lpszMenuName.MaximumLength = 0;
+            Window->Class->lpszMenuName.Buffer = (LPWSTR)dwNewLong;
+         }
+         break;
+      case GCL_STYLE:
+         Window->Class->style = dwNewLong;
+         break;
+      case GCL_WNDPROC:
+         if (Ansi)
+         {
+            Window->Class->lpfnWndProcA = (WNDPROC)dwNewLong;
+            Window->Class->lpfnWndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,FALSE);
+            Window->Class->Unicode = FALSE;
+         }
+         else
+         {
+            Window->Class->lpfnWndProcW = (WNDPROC)dwNewLong;
+            Window->Class->lpfnWndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,TRUE);
+            Window->Class->Unicode = TRUE;
+         }
+         break;
+   }
 }
+/* SYSCALLS *****************************************************************/
 
-PWNDCLASS_OBJECT FASTCALL
-IntCreateClass(CONST WNDCLASSEXW *lpwcx,
-                BOOL bUnicodeClass,
-                WNDPROC wpExtra,
-                RTL_ATOM Atom)
-{
-       PWNDCLASS_OBJECT ClassObject;
-       ULONG  objectSize;
-       NTSTATUS Status;
-
-       /* Check for double registration of the class. */
-       if (PsGetWin32Process() != NULL)
-       {
-               Status = ClassReferenceClassByAtom(&ClassObject, Atom);
-               if (NT_SUCCESS(Status))
-               {
-                       ObmDereferenceObject(ClassObject);
-                       SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
-                       return(NULL);
-               }       
-       }
-       
-       objectSize = sizeof(WNDCLASS_OBJECT) + lpwcx->cbClsExtra;
-       ClassObject = ObmCreateObject(NULL, NULL, otClass, objectSize);
-       if (ClassObject == 0)
-       {          
-               SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-               return(NULL);
-       }
-       
-       ClassObject->cbSize = lpwcx->cbSize;
-       ClassObject->style = lpwcx->style;
-       ClassObject->cbClsExtra = lpwcx->cbClsExtra;
-       ClassObject->cbWndExtra = lpwcx->cbWndExtra;
-       ClassObject->hInstance = lpwcx->hInstance;
-       ClassObject->hIcon = lpwcx->hIcon;
-       ClassObject->hCursor = lpwcx->hCursor;
-       ClassObject->hbrBackground = lpwcx->hbrBackground;
-       ClassObject->Unicode = bUnicodeClass;
-       ClassObject->hIconSm = lpwcx->hIconSm;
-       ClassObject->Atom = Atom;
-       if (wpExtra == 0) {
-       if (bUnicodeClass)
-       {
-               ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
-                       ClassObject->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
-       }
-       else
-       {
-               ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
-                       ClassObject->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
-               }
-       } else {
-               if (bUnicodeClass)
-               {
-                       ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
-                       ClassObject->lpfnWndProcA = wpExtra;
-               }
-               else
-               {
-                       ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
-                       ClassObject->lpfnWndProcW = wpExtra;
-               }
-       }
-       if (IS_INTRESOURCE(lpwcx->lpszMenuName))
-       {
-               ClassObject->lpszMenuName = (PUNICODE_STRING)lpwcx->lpszMenuName;
-       }
-       else
-       {               
-               ClassObject->lpszMenuName = ExAllocatePoolWithTag(NonPagedPool,sizeof(UNICODE_STRING), TAG_STRING);
-               RtlCreateUnicodeString(ClassObject->lpszMenuName,(LPWSTR)lpwcx->lpszMenuName);
-       }
-       /* Extra class data */
-       if (ClassObject->cbClsExtra != 0)
-       {
-               ClassObject->ExtraData = (PCHAR)(ClassObject + 1);
-               RtlZeroMemory(ClassObject->ExtraData, (ULONG)ClassObject->cbClsExtra);
-       }
-       else
-       {
-               ClassObject->ExtraData = NULL;
-       }
-
-       return(ClassObject);
-}
 
 RTL_ATOM STDCALL
 NtUserRegisterClassExWOW(
-       CONST WNDCLASSEXW *lpwcx,
-       BOOL bUnicodeClass,
-       WNDPROC wpExtra,
-       DWORD Unknown4,
-       DWORD Unknown5)
+   CONST WNDCLASSEXW* lpwcx,
+   PUNICODE_STRING ClassName,
+   PUNICODE_STRING ClassNameCopy,//huhuhuhu???
+   PUNICODE_STRING MenuName,
+   WNDPROC wpExtra,
+   DWORD Flags,
+   DWORD Unknown7,
+   HMENU hMenu)
 
 /*
  * FUNCTION:
@@ -377,327 +433,314 @@ NtUserRegisterClassExWOW(
  *   Atom identifying the new class
  */
 {
-  WNDCLASSEXW SafeClass;
-  PWINSTATION_OBJECT WinStaObject;
-  PWNDCLASS_OBJECT ClassObject;
-  NTSTATUS Status;
-  RTL_ATOM Atom;
-  
-  if(!lpwcx)
-  {
-    SetLastWin32Error(ERROR_INVALID_PARAMETER);
-    return (RTL_ATOM)0;
-  }
-  
-  Status = MmCopyFromCaller(&SafeClass, lpwcx, sizeof(WNDCLASSEXW));
-  if (!NT_SUCCESS(Status))
-  {
-    SetLastNtError(Status);
-    return (RTL_ATOM)0;
-  }
-  
-       /* Deny negative sizes */
-  if(lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0)
-  {
-    SetLastWin32Error(ERROR_INVALID_PARAMETER);
-    return (RTL_ATOM)0;
-  }
-  
-  DPRINT("About to open window station handle (0x%X)\n", 
-    PROCESS_WINDOW_STATION());
-  Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
-    KernelMode,
-    0,
-    &WinStaObject);
-  if (!NT_SUCCESS(Status))
-  {
-    DPRINT("Validation of window station handle (0x%X) failed\n",
-      PROCESS_WINDOW_STATION());
-    return((RTL_ATOM)0);
-  }
-  if (!IS_ATOM(SafeClass.lpszClassName))
-  {
-    DPRINT("NtUserRegisterClassExWOW(%S)\n", SafeClass.lpszClassName);
-    /* FIXME - Safely copy/verify the buffer first!!! */
-    Status = RtlAddAtomToAtomTable(WinStaObject->AtomTable,
-      (LPWSTR)SafeClass.lpszClassName,
-      &Atom);
-    if (!NT_SUCCESS(Status))
-    {
-      ObDereferenceObject(WinStaObject);
-      DPRINT("Failed adding class name (%wS) to atom table\n",
-       lpwcx->lpszClassName);
-      SetLastNtError(Status);      
-      return((RTL_ATOM)0);
-    }
-  }
-  else
-  {
-    Atom = (RTL_ATOM)(ULONG)SafeClass.lpszClassName;
-  }
-  ClassObject = IntCreateClass(&SafeClass, bUnicodeClass, wpExtra, Atom);
-  if (ClassObject == NULL)
-  {
-    if (!IS_ATOM(SafeClass.lpszClassName))
-    {
-      RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Atom);
-    }
-    ObDereferenceObject(WinStaObject);
-    DPRINT("Failed creating window class object\n");
-    return((RTL_ATOM)0);
-  }
-  IntLockProcessClasses(PsGetWin32Process());
-  InsertTailList(&PsGetWin32Process()->ClassListHead, &ClassObject->ListEntry);
-  IntUnLockProcessClasses(PsGetWin32Process());
-  ObDereferenceObject(WinStaObject);
-  return(Atom);
-}
+   WNDCLASSEXW SafeClass;
+   NTSTATUS Status;
+   RTL_ATOM Atom;
+   DECLARE_RETURN(RTL_ATOM);
 
-ULONG FASTCALL
-IntGetClassLong(struct _WINDOW_OBJECT *WindowObject, ULONG Offset, BOOL Ansi)
-{
-  LONG Ret;
-
-  if ((int)Offset >= 0)
-    {
-      DPRINT("GetClassLong(%x, %d)\n", WindowObject->Self, Offset);
-      if ((Offset + sizeof(LONG)) > WindowObject->Class->cbClsExtra)
-       {
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return 0;
-       }
-      Ret = *((LONG *)(WindowObject->Class->ExtraData + Offset));
-      DPRINT("Result: %x\n", Ret);
-      return Ret;
-    }
-
-  switch (Offset)
-    {
-    case GCL_CBWNDEXTRA:
-      Ret = WindowObject->Class->cbWndExtra;
-      break;
-    case GCL_CBCLSEXTRA:
-      Ret = WindowObject->Class->cbClsExtra;
-      break;
-    case GCL_HBRBACKGROUND:
-      Ret = (ULONG)WindowObject->Class->hbrBackground;
-      break;
-    case GCL_HCURSOR:
-      Ret = (ULONG)WindowObject->Class->hCursor;
-      break;
-    case GCL_HICON:
-      Ret = (ULONG)WindowObject->Class->hIcon;
-      break;
-    case GCL_HICONSM:
-      Ret = (ULONG)WindowObject->Class->hIconSm;
-      break;
-    case GCL_HMODULE:
-      Ret = (ULONG)WindowObject->Class->hInstance;
-      break;
-    case GCL_MENUNAME:
-      Ret = (ULONG)WindowObject->Class->lpszMenuName;
-      break;
-    case GCL_STYLE:
-      Ret = WindowObject->Class->style;
-      break;
-    case GCL_WNDPROC:
-         if (Ansi)
-         {
-               Ret = (ULONG)WindowObject->Class->lpfnWndProcA;
-         }
-         else
-         {
-               Ret = (ULONG)WindowObject->Class->lpfnWndProcW;
-         }
-      break;
-    default:
-      Ret = 0;
-      break;
-    }
-  return(Ret);
+   DPRINT("Enter NtUserRegisterClassExWOW\n");
+   UserEnterExclusive();
+
+   if (!lpwcx)
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      RETURN( (RTL_ATOM)0);
+   }
+
+   if (Flags & ~REGISTERCLASS_ALL)
+   {
+      SetLastWin32Error(ERROR_INVALID_FLAGS);
+      RETURN( (RTL_ATOM)0);
+   }
+
+   Status = MmCopyFromCaller(&SafeClass, lpwcx, sizeof(WNDCLASSEXW));
+   if (!NT_SUCCESS(Status))
+   {
+      SetLastNtError(Status);
+      RETURN( (RTL_ATOM)0);
+   }
+
+   /* Deny negative sizes */
+   if (lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0)
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      RETURN( (RTL_ATOM)0);
+   }
+
+   if (!lpwcx->hInstance)
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      RETURN( (RTL_ATOM)0);
+   }
+
+   //FIXME: make ClassName ptr the atom, not buffer
+   if (ClassName->Length > 0)
+   {
+      DPRINT("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer);
+      /* FIXME - Safely copy/verify the buffer first!!! */
+      Status = RtlAddAtomToAtomTable(gAtomTable,
+                                     ClassName->Buffer,
+                                     &Atom);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("Failed adding class name (%S) to atom table\n",
+                 ClassName->Buffer);
+         SetLastNtError(Status);
+         RETURN((RTL_ATOM)0);
+      }
+   }
+   else
+   {
+      Atom = (RTL_ATOM)(ULONG)ClassName->Buffer;
+   }
+
+   if (!Atom)
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      RETURN(0);
+   }
+
+   if (!IntRegisterClass(&SafeClass, Flags, wpExtra, MenuName, Atom, hMenu))
+   {
+      if (ClassName->Length)
+      {
+         RtlDeleteAtomFromAtomTable(gAtomTable, Atom);
+      }
+      DPRINT("Failed creating window class object\n");
+      RETURN((RTL_ATOM)0);
+   }
+
+   RETURN(Atom);
+
+CLEANUP:
+   DPRINT("Leave NtUserRegisterClassExWOW, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
+
+
 DWORD STDCALL
 NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
 {
-  PWINDOW_OBJECT WindowObject;
-  LONG Ret;
-
-  WindowObject = IntGetWindowObject(hWnd);
-  if (WindowObject == NULL)
-  {
-    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-    return 0;
-  }
-  Ret = IntGetClassLong(WindowObject, Offset, Ansi);
-  IntReleaseWindowObject(WindowObject);
-  return(Ret);
-}
+   PWINDOW_OBJECT Window;
+   DECLARE_RETURN(DWORD);
 
-void FASTCALL
-IntSetClassLong(PWINDOW_OBJECT WindowObject, ULONG Offset, LONG dwNewLong, BOOL Ansi)
-{
-  PUNICODE_STRING str;
-
-  if ((int)Offset >= 0)
-    {
-      DPRINT("SetClassLong(%x, %d, %x)\n", WindowObject->Self, Offset, dwNewLong);
-      if ((Offset + sizeof(LONG)) > WindowObject->Class->cbClsExtra)
-       {
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return;
-       }
-      *((LONG *)(WindowObject->Class->ExtraData + Offset)) = dwNewLong;
-      return;
-    }
-  
-  switch (Offset)
-    {
-    case GCL_CBWNDEXTRA:
-      WindowObject->Class->cbWndExtra = dwNewLong;
-      break;
-    case GCL_CBCLSEXTRA:
-      WindowObject->Class->cbClsExtra = dwNewLong;
-      break;
-    case GCL_HBRBACKGROUND:
-      WindowObject->Class->hbrBackground = (HBRUSH)dwNewLong;
-      break;
-    case GCL_HCURSOR:
-      WindowObject->Class->hCursor = (HCURSOR)dwNewLong;
-      break;
-    case GCL_HICON:
-      WindowObject->Class->hIcon = (HICON)dwNewLong;
-      break;
-    case GCL_HICONSM:
-      WindowObject->Class->hIconSm = (HICON)dwNewLong;
-      break;
-    case GCL_HMODULE:
-      WindowObject->Class->hInstance = (HINSTANCE)dwNewLong;
-      break;
-    case GCL_MENUNAME:
-         if (!IS_INTRESOURCE(dwNewLong))
-         {
-           str = ExAllocatePoolWithTag(PagedPool,sizeof(UNICODE_STRING)+((PUNICODE_STRING)dwNewLong)->Length, TAG_STRING);
-           memcpy(str,(PUNICODE_STRING)dwNewLong,sizeof(UNICODE_STRING)+((PUNICODE_STRING)dwNewLong)->Length);
-        WindowObject->Class->lpszMenuName = str;
-         }
-         else
-         {
-               WindowObject->Class->lpszMenuName = (PUNICODE_STRING)dwNewLong;
-         }
-      break;
-    case GCL_STYLE:
-      WindowObject->Class->style = dwNewLong;
-      break;
-    case GCL_WNDPROC:
-         if (Ansi)
-         {
-               WindowObject->Class->lpfnWndProcA = (WNDPROC)dwNewLong;
-        WindowObject->Class->lpfnWndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,FALSE);
-               WindowObject->Class->Unicode = FALSE;
-         }
-         else
-         {
-               WindowObject->Class->lpfnWndProcW = (WNDPROC)dwNewLong;
-        WindowObject->Class->lpfnWndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,TRUE);
-               WindowObject->Class->Unicode = TRUE;
-         }
-      break;
-    }
+   DPRINT("Enter NtUserGetClassLong\n");
+   UserEnterExclusive();
+
+   if (!(Window = UserGetWindowObject(hWnd)))
+   {
+      RETURN(0);
+   }
+
+   RETURN(IntGetClassLong(Window, Offset, Ansi));
+
+CLEANUP:
+   DPRINT("Leave NtUserGetClassLong, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
+
+
 DWORD STDCALL
 NtUserSetClassLong(HWND hWnd,
-                  DWORD Offset,
-                  LONG dwNewLong,
-                  BOOL Ansi)
+                   DWORD Offset,
+                   LONG dwNewLong,
+                   BOOL Ansi)
 {
-  PWINDOW_OBJECT WindowObject;
-  LONG Ret;
-
-  WindowObject = IntGetWindowObject(hWnd);
-  if (WindowObject == NULL)
-  {
-    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-    return 0;
-  }
-  Ret = IntGetClassLong(WindowObject, Offset, Ansi);
-  IntSetClassLong(WindowObject, Offset, dwNewLong, Ansi);
-  IntReleaseWindowObject(WindowObject);
-  return(Ret);
+   PWINDOW_OBJECT Window;
+   LONG Ret;
+   USER_REFERENCE_ENTRY Ref;
+   DECLARE_RETURN(DWORD);
+
+   DPRINT("Enter NtUserSetClassLong\n");
+   UserEnterExclusive();
+
+   if (!(Window = UserGetWindowObject(hWnd)))
+   {
+      RETURN(0);
+   }
+
+   UserRefObjectCo(Window, &Ref);
+
+   Ret = IntGetClassLong(Window, Offset, Ansi);
+   co_IntSetClassLong(Window, Offset, dwNewLong, Ansi);
+
+   UserDerefObjectCo(Window);
+
+   RETURN(Ret);
+
+CLEANUP:
+   DPRINT("Leave NtUserSetClassLong, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 DWORD STDCALL
 NtUserSetClassWord(DWORD Unknown0,
-                  DWORD Unknown1,
-                  DWORD Unknown2)
+                   DWORD Unknown1,
+                   DWORD Unknown2)
 {
-  UNIMPLEMENTED;
-  return(0);
+   UNIMPLEMENTED;
+   return(0);
 }
 
 BOOL STDCALL
 NtUserUnregisterClass(
    LPCWSTR ClassNameOrAtom,
-        HINSTANCE hInstance,
-        DWORD Unknown)
+   HINSTANCE hInstance, /* can be 0 */
+   DWORD Unknown)
 {
-   NTSTATUS Status;
    PWNDCLASS_OBJECT Class;
-   PWINSTATION_OBJECT WinStaObject;
-  
-   DPRINT("NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
-   
+   DECLARE_RETURN(BOOL);
+
+   DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
+   UserEnterExclusive();
+
    if (!ClassNameOrAtom)
    {
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      return FALSE;
+      SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+      RETURN(FALSE);
    }
-  
-   Status = IntValidateWindowStationHandle(
-      PROCESS_WINDOW_STATION(),
-      KernelMode,
-      0,
-      &WinStaObject);
-   if (!NT_SUCCESS(Status))
+
+   if (!(Class = ClassGetClassByNameOrAtom(ClassNameOrAtom, hInstance)))
    {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return FALSE;
+      SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+      RETURN(FALSE);
    }
 
-   Status = ClassReferenceClassByNameOrAtom(&Class, ClassNameOrAtom);
-   if (!NT_SUCCESS(Status))
+   if (Class->refs)
    {
-      SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
-      return FALSE;
+      /* NOTE: the class will not be freed when its refs become 0 ie. no more
+       * windows are using it. I dunno why that is but its how Windows does it (and Wine).
+       * The class will hang around until the process exit. -Gunnar
+       */
+      SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
+      RETURN(FALSE);
    }
-  
-   if (Class->hInstance && Class->hInstance != hInstance)
+
+   DestroyClass(Class);
+   
+   RETURN(TRUE);
+
+CLEANUP:
+   DPRINT("Leave NtUserUnregisterClass, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
+/* NOTE: for system classes hInstance is not NULL here, but User32Instance */
+DWORD STDCALL
+NtUserGetClassInfo(
+   HINSTANCE hInstance,
+   LPCWSTR lpClassName,
+   LPWNDCLASSEXW lpWndClassEx,
+   BOOL Ansi,
+   DWORD unknown3)
+{
+   PWNDCLASS_OBJECT Class;
+   RTL_ATOM Atom;
+   DECLARE_RETURN(DWORD);
+
+   if (IS_ATOM(lpClassName))
+      DPRINT("NtUserGetClassInfo - %x (%lx)\n", lpClassName, hInstance);
+   else
+      DPRINT("NtUserGetClassInfo - %S (%lx)\n", lpClassName, hInstance);
+
+   UserEnterExclusive();
+
+   if (!hInstance)
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      RETURN(0);
+   }
+
+   if (!(Class = ClassGetClassByNameOrAtom(lpClassName, hInstance)))
    {
-      ObmDereferenceObject(Class);
       SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
-      return FALSE;
+      RETURN(0);
+   }
+
+   lpWndClassEx->cbSize = sizeof(WNDCLASSEXW);
+   lpWndClassEx->style = Class->style;
+   if (Ansi)
+      lpWndClassEx->lpfnWndProc = Class->lpfnWndProcA;
+   else
+      lpWndClassEx->lpfnWndProc = Class->lpfnWndProcW;
+   lpWndClassEx->cbClsExtra = Class->cbClsExtra;
+   lpWndClassEx->cbWndExtra = Class->cbWndExtra;
+   /* This is not typo, we're really not going to use Class->hInstance here. */
+   /* Well, i think its wrong so i changed it -Gunnar */
+   lpWndClassEx->hInstance = Class->hInstance;
+   lpWndClassEx->hIcon = Class->hIcon;
+   lpWndClassEx->hCursor = Class->hCursor;
+   lpWndClassEx->hbrBackground = Class->hbrBackground;
+   if (Class->lpszMenuName.MaximumLength)
+      RtlCopyUnicodeString((PUNICODE_STRING)lpWndClassEx->lpszMenuName, &Class->lpszMenuName);
+   else
+      lpWndClassEx->lpszMenuName = Class->lpszMenuName.Buffer;
+   lpWndClassEx->lpszClassName = lpClassName;
+   lpWndClassEx->hIconSm = Class->hIconSm;
+   Atom = Class->Atom;
+
+   RETURN(Atom);
+
+CLEANUP:
+   DPRINT("Leave NtUserGetClassInfo, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
+
+
+DWORD STDCALL
+NtUserGetClassName (
+   HWND hWnd,
+   LPWSTR lpClassName,
+   ULONG nMaxCount /* in TCHARS */
+   )
+{
+   PWINDOW_OBJECT Window;
+   DECLARE_RETURN(DWORD);
+   NTSTATUS Status;
+
+   UserEnterShared();
+   DPRINT("Enter NtUserGetClassName\n");   
+
+   if (!(Window = UserGetWindowObject(hWnd)))
+   {
+      RETURN(0);
    }
-  
-   if (ObmGetReferenceCount(Class) > 2)
+
+   nMaxCount *= sizeof(WCHAR);
+   
+   //FIXME: wrap in SEH to protect lpClassName access
+   Status = RtlQueryAtomInAtomTable(gAtomTable,
+                                    Window->Class->Atom, NULL, NULL,
+                                    lpClassName, &nMaxCount);
+   if (!NT_SUCCESS(Status))
    {
-      ObmDereferenceObject(Class);
-      SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
-      return FALSE;
+      SetLastNtError(Status);
+      RETURN(0);
    }
-  
-   /* Dereference the ClassReferenceClassByNameOrAtom() call */
-   ObmDereferenceObject(Class);
-  
-   RemoveEntryList(&Class->ListEntry);
 
-   RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Class->Atom);
-   ObDereferenceObject(WinStaObject);
-  
-   /* Free the object */
-   ObmDereferenceObject(Class);
-  
-   return TRUE;
+   RETURN(nMaxCount / sizeof(WCHAR));
+
+CLEANUP:
+   DPRINT("Leave NtUserGetClassName, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
+DWORD STDCALL
+NtUserGetWOWClass(DWORD Unknown0,
+                  DWORD Unknown1)
+{
+   UNIMPLEMENTED;
+   return(0);
+}
+
+
 /* EOF */