fix bug 838 (Sol.exe is missing it's menubar)
[reactos.git] / reactos / subsys / win32k / ntuser / class.c
index 7d1087e..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.54 2004/05/16 19:31:09 navaraf Exp $
+/* $Id$
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
 NTSTATUS FASTCALL
 InitClassImpl(VOID)
 {
-  return(STATUS_SUCCESS);
+   return(STATUS_SUCCESS);
 }
 
 NTSTATUS FASTCALL
 CleanupClassImpl(VOID)
 {
-  return(STATUS_SUCCESS);
+   return(STATUS_SUCCESS);
 }
 
-BOOL FASTCALL
-ClassReferenceClassByAtom(
-   PWNDCLASS_OBJECT* Class,
-   RTL_ATOM Atom,
-   HINSTANCE hInstance)
+
+inline VOID FASTCALL 
+ClassDerefObject(PWNDCLASS_OBJECT Class)
 {
-   PWNDCLASS_OBJECT Current, BestMatch = NULL;
-   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 && Current->hInstance == hInstance)
-      {
-         *Class = Current;
-         ObmReferenceObject(Current);
-         IntUnLockProcessClasses(Process);
-         return TRUE;
-      }
+   ASSERT(Class->refs >= 1);
+   Class->refs--;   
+}
 
-      if (Current->Atom == Atom && Current->Global)
-         BestMatch = Current;
 
-      CurrentEntry = CurrentEntry->Flink;
-   }
-   IntUnLockProcessClasses(Process);
+inline VOID FASTCALL 
+ClassRefObject(PWNDCLASS_OBJECT Class)
+{
+   ASSERT(Class->refs >= 0);
+   Class->refs++;
+}
+
+
+VOID FASTCALL DestroyClass(PWNDCLASS_OBJECT Class)
+{
+   ASSERT(Class->refs == 0);
+   
+   RemoveEntryList(&Class->ListEntry);
+   if (Class->hMenu)
+      UserDestroyMenu(Class->hMenu);
+   RtlDeleteAtomFromAtomTable(gAtomTable, Class->Atom);
+   ExFreePool(Class);
+}
+
+
+/* clean all process classes. all process windows must cleaned first!! */
+void FASTCALL DestroyProcessClasses(PW32PROCESS Process )
+{
+   PWNDCLASS_OBJECT Class;
 
-   if (BestMatch != NULL)
+   while (!IsListEmpty(&Process->ClassList))
    {
-      *Class = BestMatch;
-      ObmReferenceObject(BestMatch);
-      return TRUE;
+      Class = CONTAINING_RECORD(RemoveHeadList(&Process->ClassList), WNDCLASS_OBJECT, ListEntry);
+      DestroyClass(Class);
    }
-  
-   return FALSE;
 }
 
-BOOL FASTCALL
-ClassReferenceClassByName(
-   PWNDCLASS_OBJECT *Class,
-   LPCWSTR ClassName,
-   HINSTANCE hInstance)
-{
-   PWINSTATION_OBJECT WinStaObject;
-   NTSTATUS Status;
-   BOOL Found;
-   RTL_ATOM ClassAtom;
 
-   if (!ClassName)
-      return FALSE;
 
-   Status = IntValidateWindowStationHandle(
-      PROCESS_WINDOW_STATION(),
-      KernelMode,
-      0,
-      &WinStaObject);
 
-   if (!NT_SUCCESS(Status))
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByAtom(RTL_ATOM Atom, HINSTANCE hInstance)
+{
+   PWNDCLASS_OBJECT Class;
+   PW32PROCESS Process = PsGetWin32Process();
+
+   LIST_FOR_EACH(Class, &Process->ClassList, WNDCLASS_OBJECT, ListEntry)
    {
-      DPRINT("Validation of window station handle (0x%X) failed\n",
-            PROCESS_WINDOW_STATION());
-      return FALSE;
+      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;
+
+   if (!ClassName || !PsGetWin32Thread()->Desktop)
+      return FALSE;
 
    Status = RtlLookupAtomInAtomTable(
-      WinStaObject->AtomTable,
-      (LPWSTR)ClassName,
-      &ClassAtom);
+               gAtomTable,
+               (LPWSTR)ClassName,
+               &Atom);
 
    if (!NT_SUCCESS(Status))
    {
-      ObDereferenceObject(WinStaObject);  
+      DPRINT1("Failed to lookup class atom!\n");
       return FALSE;
    }
 
-   Found = ClassReferenceClassByAtom(Class, ClassAtom, hInstance);
-   ObDereferenceObject(WinStaObject);  
-
-   return Found;
+   return ClassGetClassByAtom(Atom, hInstance);
 }
 
-BOOL FASTCALL
-ClassReferenceClassByNameOrAtom(
-   PWNDCLASS_OBJECT *Class,
-   LPCWSTR ClassNameOrAtom,
-   HINSTANCE hInstance)
-{
-   BOOL Found;
 
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByNameOrAtom(LPCWSTR ClassNameOrAtom, HINSTANCE hInstance)
+{
+   if (!ClassNameOrAtom) return NULL;
+   
    if (IS_ATOM(ClassNameOrAtom))
-      Found = ClassReferenceClassByAtom(Class, (RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance);
+      return ClassGetClassByAtom((RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance);
    else
-      Found = ClassReferenceClassByName(Class, ClassNameOrAtom, hInstance);
-
-   return Found;
+      return ClassGetClassByName(ClassNameOrAtom, hInstance);
 }
 
-DWORD STDCALL
-NtUserGetClassInfo(
-   HINSTANCE hInstance,
-   LPCWSTR lpClassName,
-   LPWNDCLASSEXW lpWndClassEx,
-   BOOL Ansi,
-   DWORD unknown3)
+
+static
+BOOL FASTCALL
+IntRegisterClass(
+   CONST WNDCLASSEXW *lpwcx,
+   DWORD Flags,
+   WNDPROC wpExtra,
+   PUNICODE_STRING MenuName,
+   RTL_ATOM Atom,
+   HMENU hMenu)
 {
    PWNDCLASS_OBJECT Class;
-   RTL_ATOM Atom;
+   ULONG  objectSize;
+   BOOL Global;
 
-   if (IS_ATOM(lpClassName))
-      DPRINT("NtUserGetClassInfo - %x (%lx)\n", lpClassName, hInstance);
-   else
-      DPRINT("NtUserGetClassInfo - %S (%lx)\n", lpClassName, hInstance);
+   ASSERT(lpwcx);
+   ASSERT(Atom);
+   ASSERT(lpwcx->hInstance);
 
-   if (!ClassReferenceClassByNameOrAtom(&Class, lpClassName, 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)
    {
-      SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
-      return 0;
+      /* can max have one class of each type (global/local) */
+      SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
+      return(FALSE);
    }
 
-   lpWndClassEx->cbSize = sizeof(LPWNDCLASSEXW);
-   lpWndClassEx->style = Class->style;
-   if (Ansi)
-      lpWndClassEx->lpfnWndProc = Class->lpfnWndProcA;
+   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 (Flags & REGISTERCLASS_ANSI)
+      {
+         Class->lpfnWndProcA = lpwcx->lpfnWndProc;
+         Class->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
+      }
+      else
+      {
+         Class->lpfnWndProcW = lpwcx->lpfnWndProc;
+         Class->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
+      }
+   }
    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. */
-   lpWndClassEx->hInstance = hInstance;
-   lpWndClassEx->hIcon = Class->hIcon;
-   lpWndClassEx->hCursor = Class->hCursor;
-   lpWndClassEx->hbrBackground = Class->hbrBackground;
-   if (Class->lpszMenuName)
    {
-      if (!IS_INTRESOURCE((LPCWSTR)Class->lpszMenuName))
-         RtlCopyUnicodeString((PUNICODE_STRING)lpWndClassEx->lpszMenuName, Class->lpszMenuName);
+      if (Flags & REGISTERCLASS_ANSI)
+      {
+         Class->lpfnWndProcA = lpwcx->lpfnWndProc;
+         Class->lpfnWndProcW = wpExtra;
+      }
       else
-         lpWndClassEx->lpszMenuName = (LPCWSTR)Class->lpszMenuName;
+      {
+         Class->lpfnWndProcW = lpwcx->lpfnWndProc;
+         Class->lpfnWndProcA = wpExtra;
+      }
+   }
+   
+   if (MenuName->Length == 0)
+   {
+      Class->lpszMenuName.Length =
+         Class->lpszMenuName.MaximumLength = 0;
+      Class->lpszMenuName.Buffer = MenuName->Buffer;
    }
    else
-      lpWndClassEx->lpszMenuName = (LPCWSTR)NULL;
-   lpWndClassEx->lpszClassName = lpClassName;
-   lpWndClassEx->hIconSm = Class->hIconSm;
-   Atom = Class->Atom;
+   {
+      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, NULL, &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,
-   DWORD Flags,
-   WNDPROC wpExtra,
-   PUNICODE_STRING MenuName,
-   RTL_ATOM Atom)
-{
-       PWNDCLASS_OBJECT ClassObject;
-       ULONG  objectSize;
-       BOOL Global;
-
-       Global = !(Flags & REGISTERCLASS_SYSTEM) ? ClassObject->style & CS_GLOBALCLASS : TRUE;
-
-       /* Check for double registration of the class. */
-       if (PsGetWin32Process() != NULL)
-       {
-               if (ClassReferenceClassByAtom(&ClassObject, Atom, lpwcx->hInstance))
-               {
-                       /*
-                        * NOTE: We may also get a global class from
-                         * ClassReferenceClassByAtom. This simple check
-                         * prevents that we fail valid request.
-                         */
-                       if (ClassObject->hInstance == lpwcx->hInstance)
-                       {
-                               SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
-                               ObmDereferenceObject(ClassObject);
-                               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 = !(Flags & REGISTERCLASS_ANSI);
-       ClassObject->Global = Global;
-       ClassObject->hIconSm = lpwcx->hIconSm;
-       ClassObject->Atom = Atom;
-       if (wpExtra == NULL) {
-               if (Flags & REGISTERCLASS_ANSI)
-               {
-                       ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
-                       ClassObject->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
-               }
-               else
-               {
-                       ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
-                       ClassObject->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
-               }
-       } else {
-               if (Flags & REGISTERCLASS_ANSI)
-               {
-                       ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
-                       ClassObject->lpfnWndProcW = wpExtra;
-               }
-               else
-               {
-                       ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
-                       ClassObject->lpfnWndProcA = wpExtra;
-               }
-       }
-       if (MenuName->Length == 0)
-       {
-               ClassObject->lpszMenuName = (PUNICODE_STRING)MenuName->Buffer;
-       }
-       else
-       {               
-               ClassObject->lpszMenuName = ExAllocatePoolWithTag(NonPagedPool, sizeof(UNICODE_STRING), TAG_STRING);
-               RtlCreateUnicodeString(ClassObject->lpszMenuName, MenuName->Buffer);
-       }
-       /* 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,
    PUNICODE_STRING ClassName,
-   PUNICODE_STRING ClassNameCopy,
+   PUNICODE_STRING ClassNameCopy,//huhuhuhu???
    PUNICODE_STRING MenuName,
-   WNDPROC wpExtra, /* FIXME: Windows uses this parameter for something different. */
+   WNDPROC wpExtra,
    DWORD Flags,
-   DWORD Unknown7)
+   DWORD Unknown7,
+   HMENU hMenu)
 
 /*
  * FUNCTION:
@@ -393,331 +434,313 @@ NtUserRegisterClassExWOW(
  */
 {
    WNDCLASSEXW SafeClass;
-   PWINSTATION_OBJECT WinStaObject;
-   PWNDCLASS_OBJECT ClassObject;
    NTSTATUS Status;
    RTL_ATOM Atom;
-  
+   DECLARE_RETURN(RTL_ATOM);
+
+   DPRINT("Enter NtUserRegisterClassExWOW\n");
+   UserEnterExclusive();
+
    if (!lpwcx)
    {
       SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      return (RTL_ATOM)0;
+      RETURN( (RTL_ATOM)0);
    }
 
    if (Flags & ~REGISTERCLASS_ALL)
    {
       SetLastWin32Error(ERROR_INVALID_FLAGS);
-      return (RTL_ATOM)0;
+      RETURN( (RTL_ATOM)0);
    }
 
    Status = MmCopyFromCaller(&SafeClass, lpwcx, sizeof(WNDCLASSEXW));
    if (!NT_SUCCESS(Status))
    {
       SetLastNtError(Status);
-      return (RTL_ATOM)0;
+      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 (ClassName->Length)
-  {
-    DPRINT("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer);
-    /* FIXME - Safely copy/verify the buffer first!!! */
-    Status = RtlAddAtomToAtomTable(WinStaObject->AtomTable,
-      ClassName->Buffer,
-      &Atom);
-    if (!NT_SUCCESS(Status))
-    {
-      ObDereferenceObject(WinStaObject);
-      DPRINT("Failed adding class name (%S) to atom table\n",
-       ClassName->Buffer);
-      SetLastNtError(Status);      
-      return((RTL_ATOM)0);
-    }
-  }
-  else
-  {
-    Atom = (RTL_ATOM)(ULONG)ClassName->Buffer;
-  }
-  ClassObject = IntCreateClass(&SafeClass, Flags, wpExtra, MenuName, Atom);
-  if (ClassObject == NULL)
-  {
-    if (ClassName->Length)
-    {
-      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);
-}
+      RETURN( (RTL_ATOM)0);
+   }
 
-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);
+   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);
    }
 
-   if (!ClassReferenceClassByNameOrAtom(&Class, ClassNameOrAtom, hInstance))
+   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 */