[Csrss|Win32k]
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / class.c
index 95570f8..81e0076 100644 (file)
@@ -2,14 +2,14 @@
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * PURPOSE:          Window classes
- * FILE:             subsys/win32k/ntuser/class.c
+ * FILE:             subsystems/win32/win32k/ntuser/class.c
  * PROGRAMER:        Thomas Weidenmueller <w3seek@reactos.com>
  * REVISION HISTORY:
  *       06-06-2001  CSH  Created
  */
 /* INCLUDES ******************************************************************/
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
 #define WARN DPRINT1
 #define ERR DPRINT1
 
-PCLS SystemClassList = NULL;
-BOOL RegisteredSysClasses = FALSE;
+REGISTER_SYSCLASS DefaultServerClasses[] =
+{
+  { ((PWSTR)((ULONG_PTR)(WORD)(0x8001))),
+    CS_GLOBALCLASS|CS_DBLCLKS,
+    NULL,
+    0,
+    IDC_ARROW,
+    (HBRUSH)(COLOR_BACKGROUND + 1),
+    FNID_DESKTOP,
+    ICLS_DESKTOP
+  },
+  { ((PWSTR)((ULONG_PTR)(WORD)(0x8003))),
+    CS_VREDRAW|CS_HREDRAW|CS_SAVEBITS,
+    NULL, // Use User32 procs
+    sizeof(LONG),
+    IDC_ARROW,
+    NULL,
+    FNID_SWITCH,
+    ICLS_SWITCH
+  },
+  { ((PWSTR)((ULONG_PTR)(WORD)(0x8000))),
+    CS_DBLCLKS|CS_SAVEBITS,
+    NULL, // Use User32 procs
+    sizeof(LONG),
+    IDC_ARROW,
+    (HBRUSH)(COLOR_MENU + 1),
+    FNID_MENU,
+    ICLS_MENU
+  },
+  { L"ScrollBar",
+    CS_DBLCLKS|CS_VREDRAW|CS_HREDRAW|CS_PARENTDC,
+    NULL, // Use User32 procs
+    0,
+    IDC_ARROW,
+    NULL,
+    FNID_SCROLLBAR,
+    ICLS_SCROLLBAR
+  },
+  { ((PWSTR)((ULONG_PTR)(WORD)(0x8004))), // IconTitle is here for now...
+    0,
+    NULL, // Use User32 procs
+    0,
+    IDC_ARROW,
+    0,
+    FNID_ICONTITLE,
+    ICLS_ICONTITLE
+  },
+  { L"Message",
+    CS_GLOBALCLASS,
+    NULL, // Use User32 procs
+    0,
+    IDC_ARROW,
+    NULL,
+    FNID_MESSAGEWND,
+    ICLS_HWNDMESSAGE
+  }  
+};
 
 static struct
 {
     int FnId;
     int ClsId;
 }  FnidToiCls[] =
-{
- { FNID_BUTTON,     ICLS_BUTTON},
- { FNID_EDIT,       ICLS_EDIT}, 
- { FNID_STATIC,     ICLS_STATIC},
- { FNID_LISTBOX,    ICLS_LISTBOX},
+{ /* Function Ids to Class indexes. */
  { FNID_SCROLLBAR,  ICLS_SCROLLBAR},
+ { FNID_ICONTITLE,  ICLS_ICONTITLE},
+ { FNID_MENU,       ICLS_MENU},
+ { FNID_DESKTOP,    ICLS_DESKTOP},
+ { FNID_SWITCH,     ICLS_SWITCH},
+ { FNID_MESSAGEWND, ICLS_HWNDMESSAGE},
+ { FNID_BUTTON,     ICLS_BUTTON},
  { FNID_COMBOBOX,   ICLS_COMBOBOX},
- { FNID_MDICLIENT,  ICLS_MDICLIENT},
  { FNID_COMBOLBOX,  ICLS_COMBOLBOX},
  { FNID_DIALOG,     ICLS_DIALOG},  
- { FNID_MENU,       ICLS_MENU},
- { FNID_ICONTITLE,  ICLS_ICONTITLE}
+ { FNID_EDIT,       ICLS_EDIT}, 
+ { FNID_LISTBOX,    ICLS_LISTBOX},
+ { FNID_MDICLIENT,  ICLS_MDICLIENT},
+ { FNID_STATIC,     ICLS_STATIC},
+ { FNID_IME,        ICLS_IME},
+ { FNID_GHOST,      ICLS_GHOST},
+ { FNID_TOOLTIPS,   ICLS_TOOLTIPS}
 };
 
-static 
 BOOL
 FASTCALL
-LockupFnIdToiCls(int FnId, int *iCls )
+LookupFnIdToiCls(int FnId, int *iCls )
 {
   int i;
   
-  for ( i = 0; i < (sizeof(FnidToiCls)/2)/sizeof(int); i++)
+  for ( i = 0; i < ARRAYSIZE(FnidToiCls); i++)
   {
      if (FnidToiCls[i].FnId == FnId)
      {
-        *iCls = FnidToiCls[i].ClsId;
+        if (iCls) *iCls = FnidToiCls[i].ClsId;
         return TRUE;
      }
   }
+  if (iCls) *iCls = 0;
   return FALSE;
 }
 
@@ -74,6 +135,7 @@ IntFreeClassMenuName(IN OUT PCLS Class)
 static VOID
 IntDestroyClass(IN OUT PCLS Class)
 {
+    PDESKTOP pDesk;
     /* there shouldn't be any clones anymore */
     ASSERT(Class->cWndReferenceCount == 0);
     ASSERT(Class->pclsClone == NULL);
@@ -104,11 +166,13 @@ IntDestroyClass(IN OUT PCLS Class)
         IntFreeClassMenuName(Class);
     }
 
+    pDesk = Class->rpdeskParent;
+    Class->rpdeskParent = NULL;
+
     /* free the structure */
-    if (Class->rpdeskParent != NULL)
+    if (pDesk != NULL)
     {
-        DesktopHeapFree(Class->rpdeskParent,
-                        Class);
+        DesktopHeapFree(pDesk, Class);
     }
     else
     {
@@ -164,7 +228,7 @@ IntRegisterClassAtom(IN PUNICODE_STRING ClassName,
         /* FIXME - Don't limit to 64 characters! use SEH when allocating memory! */
         if (ClassName->Length / sizeof(WCHAR) >= sizeof(szBuf) / sizeof(szBuf[0]))
         {
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
             return (RTL_ATOM)0;
         }
 
@@ -177,20 +241,6 @@ IntRegisterClassAtom(IN PUNICODE_STRING ClassName,
     else
         AtomName = ClassName->Buffer;
 
-  /* If an Atom, need to verify, if it was already added to the global atom list. */
-    if (IS_ATOM(AtomName))
-    {
-       *pAtom = (RTL_ATOM)((ULONG_PTR)AtomName);
-       Status = RtlQueryAtomInAtomTable( gAtomTable,
-                                         *pAtom,
-                                         NULL,
-                                         NULL,
-                                         NULL,
-                                         NULL);
-
-       if (NT_SUCCESS(Status)) return TRUE;
-    }
-
     Status = RtlAddAtomToAtomTable(gAtomTable,
                                    AtomName,
                                    pAtom);
@@ -211,28 +261,6 @@ IntDeregisterClassAtom(IN RTL_ATOM Atom)
                                       Atom);
 }
 
-PCALLPROCDATA
-UserFindCallProc(IN PCLS Class,
-                 IN WNDPROC WndProc,
-                 IN BOOL bUnicode)
-{
-    PCALLPROCDATA CallProc;
-
-    CallProc = Class->spcpdFirst;
-    while (CallProc != NULL)
-    {
-        if (CallProc->pfnClientPrevious == WndProc &&
-            CallProc->Unicode == (UINT)bUnicode)
-        {
-            return CallProc;
-        }
-
-        CallProc = CallProc->spcpdNext;
-    }
-
-    return NULL;
-}
-
 VOID
 UserAddCallProcToClass(IN OUT PCLS Class,
                        IN PCALLPROCDATA CallProc)
@@ -286,133 +314,138 @@ IntSetClassAtom(IN OUT PCLS Class,
     return TRUE;
 }
 
-static WNDPROC
-IntGetClassWndProc(IN PCLS Class,
-                   IN PPROCESSINFO pi,
-                   IN BOOL Ansi) // This is what we are looking for?!?
+//
+// Same as User32:IntGetClsWndProc.
+//
+WNDPROC FASTCALL
+IntGetClassWndProc(PCLS Class, BOOL Ansi)
 {
-    ASSERT(UserIsEnteredExclusive() == TRUE);
-    /* System Classes */
-    if (Class->System)
-    {
-       // FIXME! System class have gpsi->apfnClientA/W to pick from.
-        return (Ansi ? Class->WndProcExtra : Class->lpfnWndProc);
-    }
-    else 
-    {   /* Unicode Proc */
-        if (!Ansi == Class->Unicode)
-        {
-            return Class->lpfnWndProc;
-        }
-        else // Ansi?
-        {
-            PCLS BaseClass;
-
-            /* make sure the call procedures are located on the desktop
-               of the base class! */
-            BaseClass = Class->pclsBase;
-            Class = BaseClass;
+  INT i;
+  WNDPROC gcpd = NULL, Ret = NULL;
 
-            if (Class->CallProc != NULL)
-            {
-                return GetCallProcHandle(Class->CallProc);
-            }
+  if (Class->CSF_flags & CSF_SERVERSIDEPROC)
+  {
+     for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
+     {
+         if (GETPFNSERVER(i) == Class->lpfnWndProc)
+         {
+            if (Ansi)
+               Ret = GETPFNCLIENTA(i);
             else
-            {
-                PCALLPROCDATA NewCallProc;
-
-                if (pi == NULL)
-                    return NULL;
-
-                NewCallProc = UserFindCallProc(Class,
-                                               Class->lpfnWndProc,
-                                               Class->Unicode);
-                if (NewCallProc == NULL)
-                {
-                    NewCallProc = CreateCallProc(NULL,
-                                                 Class->lpfnWndProc,
-                                                 Class->Unicode,
-                                                 pi);
-                    if (NewCallProc == NULL)
-                    {
-                        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-                        return NULL;
-                    }
-
-                    UserAddCallProcToClass(Class,
-                                           NewCallProc);
-                }
+               Ret = GETPFNCLIENTW(i);
+         }
+     }
+     return Ret;
+  }
+  Ret = Class->lpfnWndProc;
 
-                Class->CallProc = NewCallProc;
+  if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
+  {
+     if (Ansi)
+     {
+        if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc)
+           Ret = GETPFNCLIENTA(Class->fnid);
+     }
+     else
+     {
+        if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc)
+           Ret = GETPFNCLIENTW(Class->fnid);
+     }
+  }
 
-                /* update the clones */
-                Class = Class->pclsClone;
-                while (Class != NULL)
-                {
-                    Class->CallProc = NewCallProc;
+  if ( Ret != Class->lpfnWndProc ||
+       Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) )
+     return Ret;
 
-                    Class = Class->pclsNext;
-                }
+  gcpd = (WNDPROC)UserGetCPD( Class,
+                       (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDClass,
+                       (ULONG_PTR)Ret);
 
-                return GetCallProcHandle(NewCallProc);
-            }
-        }
-    }
+  return (gcpd ? gcpd : Ret);
 }
 
-static WNDPROC
+
+static
+WNDPROC FASTCALL
 IntSetClassWndProc(IN OUT PCLS Class,
                    IN WNDPROC WndProc,
                    IN BOOL Ansi)
 {
-    WNDPROC Ret;
+   INT i;
+   PCALLPROCDATA pcpd;
+   WNDPROC Ret, chWndProc;
 
-    if (Class->System)
-    {
-        DPRINT1("Attempted to change window procedure of system window class 0x%p!\n", Class->atomClassName);
-        SetLastWin32Error(ERROR_ACCESS_DENIED);
-        return NULL;
-    }
+   Ret = IntGetClassWndProc(Class, Ansi);
 
-    /* update the base class first */
-    Class = Class->pclsBase;
+   // If Server Side, downgrade to Client Side.
+   if (Class->CSF_flags & CSF_SERVERSIDEPROC)
+   {
+      if (Ansi) Class->CSF_flags |= CSF_ANSIPROC;
+      Class->CSF_flags &= ~CSF_SERVERSIDEPROC;
+      Class->Unicode = !Ansi;
+   }
 
-    /* resolve any callproc handle if possible */
-    if (IsCallProcHandle(WndProc))
-    {
-        WNDPROC_INFO wpInfo;
+   if (!WndProc) WndProc = Class->lpfnWndProc;
 
-        if (UserGetCallProcInfo((HANDLE)WndProc,
-                                &wpInfo))
-        {
-            WndProc = wpInfo.WindowProc;
-            /* FIXME - what if wpInfo.IsUnicode doesn't match Ansi? */
-        }
-    }
+   chWndProc = WndProc;
 
-    Ret = IntGetClassWndProc(Class,
-                             GetW32ProcessInfo(),
-                             Ansi);
-    if (Ret == NULL)
-    {
-        return NULL;
-    }
+   // Check if CallProc handle and retrieve previous call proc address and set.
+   if (IsCallProcHandle(WndProc))
+   {
+      pcpd = UserGetObject(gHandleTable, WndProc, otCallProc);
+      if (pcpd) chWndProc = pcpd->pfnClientPrevious;
+   }
 
-    /* update the class info */
-    Class->Unicode = !Ansi;
-    Class->lpfnWndProc = WndProc;
+   Class->lpfnWndProc = chWndProc;
 
-    /* update the clones */
-    Class = Class->pclsClone;
-    while (Class != NULL)
-    {
-        Class->Unicode = !Ansi;
-        Class->lpfnWndProc = WndProc;
+   // Clear test proc.
+   chWndProc = NULL;
 
-        Class = Class->pclsNext;
-    }
+   // Switch from Client Side call to Server Side call if match. Ref: "deftest".
+   for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
+   {
+       if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
+       {
+          chWndProc = GETPFNSERVER(i);
+          break;
+       }
+       if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
+       {
+          chWndProc = GETPFNSERVER(i);
+          break;
+       }
+   }
+   // If match, set/reset to Server Side and clear ansi.
+   if (chWndProc)
+   {
+      Class->lpfnWndProc = chWndProc;
+      Class->Unicode = TRUE;
+      Class->CSF_flags &= ~CSF_ANSIPROC;
+      Class->CSF_flags |= CSF_SERVERSIDEPROC;      
+   }
+   else
+   {
+      Class->Unicode = !Ansi;
 
-    return Ret;
+      if (Ansi)
+         Class->CSF_flags |= CSF_ANSIPROC;
+      else
+         Class->CSF_flags &= ~CSF_ANSIPROC;
+   }
+
+   /* update the clones */
+   chWndProc = Class->lpfnWndProc;
+
+   Class = Class->pclsClone;
+   while (Class != NULL)
+   {
+      Class->Unicode = !Ansi;
+      Class->lpfnWndProc = chWndProc;
+                                
+      Class = Class->pclsNext;
+   }
+
+   return Ret;
 }
 
 static PCLS
@@ -475,9 +508,18 @@ IntGetClassForDesktop(IN OUT PCLS BaseClass,
         if (Class != NULL)
         {
             /* simply clone the class */
-            RtlCopyMemory(Class,
-                          BaseClass,
-                          ClassSize);
+            RtlCopyMemory( Class, BaseClass, ClassSize);
+
+            DPRINT("Clone Class 0x%x hM 0x%x\n %S\n",Class, Class->hModule, Class->lpszClientUnicodeMenuName);
+
+            /* restore module address if default user class Ref: Bug 4778 */
+            if ( Class->hModule != hModClient &&
+                 Class->fnid <= FNID_GHOST    &&
+                 Class->fnid >= FNID_BUTTON )
+            {
+               Class->hModule = hModClient;
+               DPRINT("Clone Class 0x%x Reset hM 0x%x\n",Class, Class->hModule);
+            }
 
             /* update some pointers and link the class */
             Class->rpdeskParent = Desktop;
@@ -509,16 +551,15 @@ IntGetClassForDesktop(IN OUT PCLS BaseClass,
                 Class->pclsClone = NULL;
                 Class->pclsBase = BaseClass;
                 Class->pclsNext = BaseClass->pclsClone;
-                (void)InterlockedExchangePointer((VOID*)&BaseClass->pclsClone,
+                (void)InterlockedExchangePointer((PVOID*)&BaseClass->pclsClone,
                                                  Class);
             }
         }
         else
         {
-            SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+            EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         }
     }
-
     return Class;
 }
 
@@ -528,7 +569,6 @@ IntReferenceClass(IN OUT PCLS BaseClass,
                   IN PDESKTOP Desktop)
 {
     PCLS Class;
-
     ASSERT(BaseClass->pclsBase == BaseClass);
 
     Class = IntGetClassForDesktop(BaseClass,
@@ -542,12 +582,13 @@ IntReferenceClass(IN OUT PCLS BaseClass,
     return Class;
 }
 
-static VOID
+static
+VOID
 IntMakeCloneBaseClass(IN OUT PCLS Class,
                       IN OUT PCLS *BaseClassLink,
                       IN OUT PCLS *CloneLink)
 {
-    PCLS Clone, BaseClass;
+    PCLS Clone;
 
     ASSERT(Class->pclsBase != Class);
     ASSERT(Class->pclsBase->pclsClone != NULL);
@@ -560,8 +601,6 @@ IntMakeCloneBaseClass(IN OUT PCLS Class,
     *CloneLink = Class->pclsNext;
     Class->pclsClone = Class->pclsBase->pclsClone;
 
-    BaseClass = Class->pclsBase;
-
     /* update the class information to make it a base class */
     Class->pclsBase = Class;
     Class->pclsNext = (*BaseClassLink)->pclsNext;
@@ -573,9 +612,6 @@ IntMakeCloneBaseClass(IN OUT PCLS Class,
         ASSERT(Clone->pclsClone == NULL);
         Clone->pclsBase = Class;
 
-        if (!Class->System)
-            Clone->CallProc = Class->CallProc;
-
         Clone = Clone->pclsNext;
     }
 
@@ -584,6 +620,7 @@ IntMakeCloneBaseClass(IN OUT PCLS Class,
                                      Class);
 }
 
+
 VOID
 IntDereferenceClass(IN OUT PCLS Class,
                     IN PDESKTOPINFO Desktop,
@@ -593,21 +630,20 @@ IntDereferenceClass(IN OUT PCLS Class,
 
     BaseClass = Class->pclsBase;
 
-    if (--Class->cWndReferenceCount == 0)
+    if (--Class->cWndReferenceCount <= 0)
     {
         if (BaseClass == Class)
         {
             ASSERT(Class->pclsBase == Class);
 
+            DPRINT("IntDereferenceClass 0x%x\n", Class);
             /* check if there are clones of the class on other desktops,
                link the first clone in if possible. If there are no clones
                then leave the class on the desktop heap. It will get moved
                to the shared heap when the thread detaches. */
             if (BaseClass->pclsClone != NULL)
             {
-                if (BaseClass->System)
-                    PrevLink = &SystemClassList;
-                else if (BaseClass->Global)
+                if (BaseClass->Global)
                     PrevLink = &pi->pclsPublicList;
                 else
                     PrevLink = &pi->pclsPrivateList;
@@ -638,6 +674,8 @@ IntDereferenceClass(IN OUT PCLS Class,
         }
         else
         {
+            DPRINT("IntDereferenceClass1 0x%x\n", Class);
+
             /* locate the cloned class and unlink it */
             PrevLink = &BaseClass->pclsClone;
             CurrentClass = BaseClass->pclsClone;
@@ -779,8 +817,6 @@ IntCheckProcessDesktopClasses(IN PDESKTOP Desktop,
     BOOL Ret = TRUE;
 
     pi = GetW32ProcessInfo();
-    if (pi == NULL)
-        return TRUE;
 
     /* check all local classes */
     IntCheckDesktopClasses(Desktop,
@@ -793,17 +829,10 @@ IntCheckProcessDesktopClasses(IN PDESKTOP Desktop,
                            &pi->pclsPublicList,
                            FreeOnFailure,
                            &Ret);
-
-    /* check all system classes */
-    IntCheckDesktopClasses(Desktop,
-                           &SystemClassList,
-                           FreeOnFailure,
-                           &Ret);
-
     if (!Ret)
     {
         DPRINT1("Failed to move process classes from desktop 0x%p to the shared heap!\n", Desktop);
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
     }
 
     return Ret;
@@ -814,7 +843,6 @@ FASTCALL
 IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
                IN PUNICODE_STRING ClassName,
                IN PUNICODE_STRING MenuName,
-               IN WNDPROC wpExtra,
                IN DWORD fnID,
                IN DWORD dwFlags,
                IN PDESKTOP Desktop,
@@ -823,11 +851,12 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
     SIZE_T ClassSize;
     PCLS Class = NULL;
     RTL_ATOM Atom;
+    WNDPROC WndProc;
     PWSTR pszMenuName = NULL;
     NTSTATUS Status = STATUS_SUCCESS;
 
-    TRACE("lpwcx=%p ClassName=%wZ MenuName=%wZ wpExtra=%p dwFlags=%08x Desktop=%p pi=%p\n",
-        lpwcx, ClassName, MenuName, wpExtra, dwFlags, Desktop, pi);
+    DPRINT("lpwcx=%p ClassName=%wZ MenuName=%wZ dwFlags=%08x Desktop=%p pi=%p\n",
+        lpwcx, ClassName, MenuName, dwFlags, Desktop, pi);
 
     if (!IntRegisterClassAtom(ClassName,
                               &Atom))
@@ -860,8 +889,9 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
 
     if (Class != NULL)
     {
-        RtlZeroMemory(Class,
-                      ClassSize);
+        int iCls = 0;
+
+        RtlZeroMemory(Class, ClassSize);
 
         Class->rpdeskParent = Desktop;
         Class->pclsBase = Class;
@@ -869,18 +899,9 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
         Class->fnid = fnID;
         Class->CSF_flags = dwFlags;
 
-        if (dwFlags & CSF_SYSTEMCLASS)
+        if (LookupFnIdToiCls(Class->fnid, &iCls))
         {
-            int iCls;
-
-            dwFlags &= ~CSF_ANSIPROC;
-            Class->WndProcExtra = wpExtra;
-            Class->System = TRUE;
-    /* Now set the Atom table, notice only non ntuser.c atoms can go in.*/
-            if (LockupFnIdToiCls(Class->fnid, &iCls))
-            {
-                gpsi->atomSysClass[iCls] = Class->atomClassName;
-            }
+            gpsi->atomSysClass[iCls] = Class->atomClassName;
         }
 
         _SEH2_TRY
@@ -890,6 +911,7 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
             /* need to protect with SEH since accessing the WNDCLASSEX structure
                and string buffers might raise an exception! We don't want to
                leak memory... */
+            // What?! If the user interface was written correctly this would not be an issue!
             Class->lpfnWndProc = lpwcx->lpfnWndProc;
             Class->style = lpwcx->style;
             Class->cbclsExtra = lpwcx->cbClsExtra;
@@ -900,7 +922,6 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
             Class->hCursor = lpwcx->hCursor; /* FIXME */
             Class->hbrBackground = lpwcx->hbrBackground;
 
-
             /* make a copy of the string */
             if (pszMenuNameBuffer != NULL)
             {
@@ -943,7 +964,39 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
             Class->lpszMenuName = Class->lpszClientUnicodeMenuName; // Fixme!
             //Class->lpszAnsiClassName = Fixme!
 
-            if (!(dwFlags & CSF_ANSIPROC))
+            /* Server Side overrides class calling type (A/W)!
+               User32 whine test_builtinproc: "deftest"
+                  built-in winproc - window A/W type automatically detected */
+            if (!(Class->CSF_flags & CSF_SERVERSIDEPROC))
+            {
+               int i;
+               WndProc = NULL;
+          /* Due to the wine class "deftest" and most likely no FNID to reference
+             from, sort through the Server Side list and compare proc addresses
+             for match. This method will be used in related code.
+           */
+               for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
+               { // Open Ansi or Unicode, just match, set and break.
+                   if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
+                   {
+                      WndProc = GETPFNSERVER(i);
+                      break;
+                   }
+                   if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
+                   {
+                      WndProc = GETPFNSERVER(i);
+                      break;
+                   }
+               }
+               if (WndProc)
+               {  // If a hit, we are Server Side so set the right flags and proc.
+                  Class->CSF_flags |= CSF_SERVERSIDEPROC;
+                  Class->CSF_flags &= ~CSF_ANSIPROC;
+                  Class->lpfnWndProc = WndProc;
+               }
+            }
+
+            if (!(Class->CSF_flags & CSF_ANSIPROC))
                 Class->Unicode = TRUE;
 
             if (Class->style & CS_GLOBALCLASS)
@@ -981,7 +1034,7 @@ NoMem:
 
         IntDeregisterClassAtom(Atom);
 
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
     }
 
     return Class;
@@ -1000,7 +1053,7 @@ IntFindClass(IN RTL_ATOM Atom,
     {
         if (Class->atomClassName == Atom &&
             (hInstance == NULL || Class->hModule == hInstance) &&
-            !Class->Destroying)
+            !(Class->CSF_flags & CSF_WOWDEFERDESTROY))
         {
             ASSERT(Class->pclsBase == Class);
 
@@ -1035,7 +1088,7 @@ IntGetAtomFromStringOrAtom(IN PUNICODE_STRING ClassName,
             /* FIXME - Don't limit to 64 characters! use SEH when allocating memory! */
             if (ClassName->Length / sizeof(WCHAR) >= sizeof(szBuf) / sizeof(szBuf[0]))
             {
-                SetLastWin32Error(ERROR_INVALID_PARAMETER);
+                EngSetLastError(ERROR_INVALID_PARAMETER);
                 return (RTL_ATOM)0;
             }
 
@@ -1064,7 +1117,7 @@ IntGetAtomFromStringOrAtom(IN PUNICODE_STRING ClassName,
         {
             if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
             {
-                SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS);
+                EngSetLastError(ERROR_CLASS_DOES_NOT_EXIST);
             }
             else
             {
@@ -1109,7 +1162,7 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName,
                              &pi->pclsPrivateList,
                              Link);
         if (Class != NULL)
-        {
+        {  DPRINT("Step 1: 0x%x\n",Class );
             goto FoundClass;
         }
 
@@ -1120,7 +1173,7 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName,
                              &pi->pclsPublicList,
                              Link);
         if (Class != NULL)
-        {
+        { DPRINT("Step 2: 0x%x 0x%x\n",Class, Class->hModule);
             goto FoundClass;
         }
 
@@ -1130,7 +1183,7 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName,
                              &pi->pclsPrivateList,
                              Link);
         if (Class != NULL)
-        {
+        { DPRINT("Step 3: 0x%x\n",Class );
             goto FoundClass;
         }
 
@@ -1139,21 +1192,11 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName,
                              hModClient,
                              &pi->pclsPublicList,
                              Link);
-        if (Class != NULL)
-        {
-            goto FoundClass;
-        }
-
-        /* Step 5: try to find a system class */
-        Class = IntFindClass(Atom,
-                             NULL,
-                             &SystemClassList,
-                             Link);
         if (Class == NULL)
         {
-            SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+            EngSetLastError(ERROR_CLASS_DOES_NOT_EXIST);
             return (RTL_ATOM)0;
-        }
+        }else{DPRINT("Step 4: 0x%x\n",Class );}
 
 FoundClass:
         *BaseClass = Class;
@@ -1162,16 +1205,65 @@ FoundClass:
     return Atom;
 }
 
+PCLS
+IntGetAndReferenceClass(PUNICODE_STRING ClassName, HINSTANCE hInstance)
+{
+   PCLS *ClassLink, Class = NULL;
+   RTL_ATOM ClassAtom;
+   PTHREADINFO pti;
+
+   pti = PsGetCurrentThreadWin32Thread();
+
+   if ( !(pti->ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
+   {
+      UserRegisterSystemClasses();
+   }
+
+   /* Check the class. */
+
+   DPRINT("Class %wZ\n", ClassName);
+
+   ClassAtom = IntGetClassAtom(ClassName,
+                               hInstance,
+                               pti->ppi,
+                               &Class,
+                               &ClassLink);
+
+   if (ClassAtom == (RTL_ATOM)0)
+   {
+      if (IS_ATOM(ClassName->Buffer))
+      {
+         DPRINT1("Class 0x%p not found\n", (DWORD_PTR) ClassName->Buffer);
+      }
+      else
+      {
+         DPRINT1("Class \"%wZ\" not found\n", ClassName);
+      }
+
+      EngSetLastError(ERROR_CANNOT_FIND_WND_CLASS);
+      return NULL;
+   }
+   DPRINT("ClassAtom %x\n", ClassAtom);
+   Class = IntReferenceClass(Class,
+                             ClassLink,
+                             pti->rpdesk);
+   if (Class == NULL)
+   {
+       DPRINT1("Failed to reference window class!\n");
+       return NULL;
+   }
+
+   return Class;
+}
+
 RTL_ATOM
 UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
                   IN PUNICODE_STRING ClassName,
                   IN PUNICODE_STRING MenuName,
-                  IN WNDPROC wpExtra,
                   IN DWORD fnID,
                   IN DWORD dwFlags)
 {
     PTHREADINFO pti;
-    PW32THREADINFO ti;
     PPROCESSINFO pi;
     PCLS Class;
     RTL_ATOM ClassAtom;
@@ -1179,50 +1271,50 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
 
     /* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */
 
-    pti = PsGetCurrentThreadWin32Thread();
-    ti = GetW32ThreadInfo();
-    if (ti == NULL || !RegisteredSysClasses)
-    {
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-        return (RTL_ATOM)0;
-    }
-
-    pi = ti->ppi;
-
-    /* try to find a previously registered class */
-    ClassAtom = IntGetClassAtom(ClassName,
-                                lpwcx->hInstance,
-                                pi,
-                                &Class,
+    pti = GetW32ThreadInfo();
+
+    pi = pti->ppi;
+
+    // Need only to test for two conditions not four....... Fix more whine tests....
+    if ( IntGetAtomFromStringOrAtom( ClassName, &ClassAtom) &&
+                                     ClassAtom != (RTL_ATOM)0 &&
+                                    !(dwFlags & CSF_SERVERSIDEPROC) ) // Bypass Server Sides
+    {
+       Class = IntFindClass( ClassAtom,
+                             lpwcx->hInstance,
+                            &pi->pclsPrivateList,
+                             NULL);
+
+       if (Class != NULL && !Class->Global)
+       {
+          // local class already exists
+          DPRINT("Local Class 0x%p does already exist!\n", ClassAtom);
+          EngSetLastError(ERROR_CLASS_ALREADY_EXISTS);
+          return (RTL_ATOM)0;
+       }
+
+       if (lpwcx->style & CS_GLOBALCLASS)
+       {
+          Class = IntFindClass( ClassAtom,
+                                NULL,
+                               &pi->pclsPublicList,
                                 NULL);
-    if (ClassAtom != (RTL_ATOM)0)
-    {
-        if (lpwcx->style & CS_GLOBALCLASS)
-        {
-            // global classes shall not have same names as system classes
-            if (Class->Global || Class->System)
-            {
-                DPRINT("Class 0x%p does already exist!\n", ClassAtom);
-                SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
-                return (RTL_ATOM)0;
-            }
-        }
-        else if ( !Class->Global && !Class->System)
-        {
-            // local class already exists
-            DPRINT("Class 0x%p does already exist!\n", ClassAtom);
-            SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
-            return (RTL_ATOM)0;
-        }
+
+          if (Class != NULL && Class->Global)
+          {
+             DPRINT("Global Class 0x%p does already exist!\n", ClassAtom);
+             EngSetLastError(ERROR_CLASS_ALREADY_EXISTS);
+             return (RTL_ATOM)0;
+          }
+       }
     }
 
     Class = IntCreateClass(lpwcx,
                            ClassName,
                            MenuName,
-                           wpExtra,
                            fnID,
                            dwFlags,
-                           pti->Desktop,
+                           pti->rpdesk,
                            pi);
 
     if (Class != NULL)
@@ -1230,9 +1322,7 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
         PCLS *List;
 
         /* Register the class */
-        if (Class->System)
-            List = &SystemClassList;
-        else if (Class->Global)
+        if (Class->Global)
             List = &pi->pclsPublicList;
         else
             List = &pi->pclsPrivateList;
@@ -1243,13 +1333,18 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
 
         Ret = Class->atomClassName;
     }
+    else
+    {
+       DPRINT1("UserRegisterClass: Yes, that is right, you have no Class!\n");
+    }
 
     return Ret;
 }
 
 BOOL
 UserUnregisterClass(IN PUNICODE_STRING ClassName,
-                    IN HINSTANCE hInstance)
+                    IN HINSTANCE hInstance,
+                    OUT PCLSMENUNAME pClassMenuName)
 {
     PCLS *Link;
     PPROCESSINFO pi;
@@ -1257,13 +1352,8 @@ UserUnregisterClass(IN PUNICODE_STRING ClassName,
     PCLS Class;
 
     pi = GetW32ProcessInfo();
-    if (pi == NULL)
-    {
-        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-        return FALSE;
-    }
 
-    TRACE("UserUnregisterClass(%wZ)\n", ClassName);
+    DPRINT("UserUnregisterClass(%wZ, 0x%x)\n", ClassName, hInstance);
 
     /* NOTE: Accessing the buffer in ClassName may raise an exception! */
     ClassAtom = IntGetClassAtom(ClassName,
@@ -1273,6 +1363,7 @@ UserUnregisterClass(IN PUNICODE_STRING ClassName,
                                 &Link);
     if (ClassAtom == (RTL_ATOM)0)
     {
+        DPRINT("UserUnregisterClass: No Class found.\n");
         return FALSE;
     }
 
@@ -1281,7 +1372,8 @@ UserUnregisterClass(IN PUNICODE_STRING ClassName,
     if (Class->cWndReferenceCount != 0 ||
         Class->pclsClone != NULL)
     {
-        SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
+        DPRINT("UserUnregisterClass: Class has a Window. Ct %d : Clone 0x%x\n", Class->cWndReferenceCount, Class->pclsClone);
+        EngSetLastError(ERROR_CLASS_HAS_WINDOWS);
         return FALSE;
     }
 
@@ -1293,11 +1385,14 @@ UserUnregisterClass(IN PUNICODE_STRING ClassName,
 
     if (NT_SUCCESS(IntDeregisterClassAtom(Class->atomClassName)))
     {
+        DPRINT("Class 0x%x\n", Class);
+        DPRINT("UserUnregisterClass: Good Exit!\n");
         /* finally free the resources */
         IntDestroyClass(Class);
         return TRUE;
     }
-       return FALSE;
+    DPRINT1("UserUnregisterClass: Can not deregister Class Atom.\n");
+    return FALSE;
 }
 
 INT
@@ -1345,11 +1440,12 @@ UserGetClassName(IN PCLS Class,
                 }
 
                 /* allocate a temporary buffer that can hold the unicode class name */
-                szTemp = ExAllocatePool(PagedPool,
-                                        BufLen);
+                szTemp = ExAllocatePoolWithTag(PagedPool,
+                                               BufLen,
+                                               USERTAG_CLASS);
                 if (szTemp == NULL)
                 {
-                    SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+                    EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
                     _SEH2_LEAVE;
                 }
 
@@ -1418,98 +1514,6 @@ UserGetClassName(IN PCLS Class,
     return Ret;
 }
 
-ULONG_PTR
-UserGetClassLongPtr(IN PCLS Class,
-                    IN INT Index,
-                    IN BOOL Ansi)
-{
-    ULONG_PTR Ret = 0;
-
-    if (Index >= 0)
-    {
-        PULONG_PTR Data;
-
-        TRACE("GetClassLong(%d)\n", Index);
-        if (Index + sizeof(ULONG_PTR) < Index ||
-            Index + sizeof(ULONG_PTR) > Class->cbclsExtra)
-        {
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
-            return 0;
-        }
-
-        Data = (PULONG_PTR)((ULONG_PTR)(Class + 1) + Index);
-
-        /* FIXME - Data might be a unaligned pointer! Might be a problem on
-                   certain architectures, maybe using RtlCopyMemory is a
-                   better choice for those architectures! */
-
-        TRACE("Result: %x\n", Ret);
-        return *Data;
-    }
-
-    switch (Index)
-    {
-        case GCL_CBWNDEXTRA:
-            Ret = (ULONG_PTR)Class->cbwndExtra;
-            break;
-
-        case GCL_CBCLSEXTRA:
-            Ret = (ULONG_PTR)Class->cbclsExtra;
-            break;
-
-        case GCLP_HBRBACKGROUND:
-            Ret = (ULONG_PTR)Class->hbrBackground;
-            break;
-
-        case GCLP_HCURSOR:
-            /* FIXME - get handle from pointer to CURSOR object */
-            Ret = (ULONG_PTR)Class->hCursor;
-            break;
-
-        case GCLP_HICON:
-            /* FIXME - get handle from pointer to ICON object */
-            Ret = (ULONG_PTR)Class->hIcon;
-            break;
-
-        case GCLP_HICONSM:
-            /* FIXME - get handle from pointer to ICON object */
-            Ret = (ULONG_PTR)Class->hIconSm;
-            break;
-
-        case GCLP_HMODULE:
-            Ret = (ULONG_PTR)Class->hModule;
-            break;
-
-        case GCLP_MENUNAME:
-            /* NOTE: Returns pointer in kernel heap! */
-            if (Ansi)
-                Ret = (ULONG_PTR)Class->lpszClientAnsiMenuName;
-            else
-                Ret = (ULONG_PTR)Class->lpszClientUnicodeMenuName;
-            break;
-
-        case GCL_STYLE:
-            Ret = (ULONG_PTR)Class->style;
-            break;
-
-        case GCLP_WNDPROC:
-            Ret = (ULONG_PTR)IntGetClassWndProc(Class,
-                                                GetW32ProcessInfo(),
-                                                Ansi);
-            break;
-
-        case GCW_ATOM:
-            Ret = (ULONG_PTR)Class->atomClassName;
-            break;
-
-        default:
-            SetLastWin32Error(ERROR_INVALID_INDEX);
-            break;
-    }
-
-    return Ret;
-}
-
 static BOOL
 IntSetClassMenuName(IN PCLS Class,
                     IN PUNICODE_STRING MenuName)
@@ -1585,7 +1589,7 @@ IntSetClassMenuName(IN PCLS Class,
             }
         }
         else
-            SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+            EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
     }
     else
     {
@@ -1636,7 +1640,7 @@ UserSetClassLongPtr(IN PCLS Class,
         if (Index + sizeof(ULONG_PTR) < Index ||
             Index + sizeof(ULONG_PTR) > Class->cbclsExtra)
         {
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
             return 0;
         }
 
@@ -1676,7 +1680,7 @@ UserSetClassLongPtr(IN PCLS Class,
             break;
 
         case GCL_CBCLSEXTRA:
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
             break;
 
         case GCLP_HBRBACKGROUND:
@@ -1799,7 +1803,7 @@ UserSetClassLongPtr(IN PCLS Class,
         }
 
         default:
-            SetLastWin32Error(ERROR_INVALID_INDEX);
+            EngSetLastError(ERROR_INVALID_INDEX);
             break;
     }
 
@@ -1812,30 +1816,33 @@ UserGetClassInfo(IN PCLS Class,
                  IN BOOL Ansi,
                  HINSTANCE hInstance)
 {
-    PPROCESSINFO pi;
+    if (!Class) return FALSE;
 
     lpwcx->style = Class->style;
 
-    pi = GetW32ProcessInfo();
-    lpwcx->lpfnWndProc = IntGetClassWndProc(Class,
-                                            pi,
-                                            Ansi);
+    // If fnId is set, clear the global bit. See wine class test check_style.
+    if (Class->fnid)
+       lpwcx->style &= ~CS_GLOBALCLASS;
 
+    lpwcx->lpfnWndProc = IntGetClassWndProc(Class, Ansi);
+    
     lpwcx->cbClsExtra = Class->cbclsExtra;
     lpwcx->cbWndExtra = Class->cbwndExtra;
     lpwcx->hIcon = Class->hIcon; /* FIXME - get handle from pointer */
     lpwcx->hCursor = Class->hCursor; /* FIXME - get handle from pointer */
     lpwcx->hbrBackground = Class->hbrBackground;
-/*
-    FIXME!
-    Cls: lpszMenuName and lpszAnsiClassName should be used by kernel space.
-    lpszClientXxxMenuName should already be mapped to user space.
- */
+
+    /* Copy non-string to user first. */
     if (Ansi)
        ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->lpszClientAnsiMenuName;
     else
        lpwcx->lpszMenuName = Class->lpszClientUnicodeMenuName;
-
+/*
+    FIXME! CLSMENUNAME has the answers! Copy the already made buffers from there!
+    Cls: lpszMenuName and lpszAnsiClassName should be used by kernel space.
+    lpszClientXxxMenuName should already be mapped to user space.
+ */
+    /* Copy string ptr to user. */
     if ( Class->lpszClientUnicodeMenuName != NULL && 
          Class->MenuNameIsString)
     {
@@ -1857,63 +1864,82 @@ UserGetClassInfo(IN PCLS Class,
     return TRUE;
 }
 
+//
+//
+//
 BOOL
-UserRegisterSystemClasses(IN ULONG Count,
-                          IN PREGISTER_SYSCLASS SystemClasses)
+FASTCALL
+UserRegisterSystemClasses(VOID)
 {
-    /* NOTE: This routine may raise exceptions! */
     UINT i;
     UNICODE_STRING ClassName, MenuName;
-    PPROCESSINFO pi = GetW32ProcessInfo();
+    PPROCESSINFO ppi = GetW32ProcessInfo();
     WNDCLASSEXW wc;
     PCLS Class;
     BOOL Ret = TRUE;
+    DWORD Flags = 0;
 
-    if ( hModClient == NULL)
-        return FALSE;
-    /* Init System Classes once only*/
-    if (RegisteredSysClasses)
+    if (ppi->W32PF_flags & W32PF_CLASSESREGISTERED)
        return TRUE;
 
+    if ( hModClient == NULL)
+       return FALSE;
+
+    RtlZeroMemory(&ClassName, sizeof(ClassName));
     RtlZeroMemory(&MenuName, sizeof(MenuName));
 
-    for (i = 0; i != Count; i++)
+    for (i = 0; i != ARRAYSIZE(DefaultServerClasses); i++)
     {
-        ClassName = ProbeForReadUnicodeString(&SystemClasses[i].ClassName);
-        if (ClassName.Length != 0)
+        if (!IS_ATOM(DefaultServerClasses[i].ClassName))
         {
-            ProbeForRead(ClassName.Buffer,
-                         ClassName.Length,
-                         sizeof(WCHAR));
+           RtlInitUnicodeString(&ClassName, DefaultServerClasses[i].ClassName);
         }
-
+        else
+        {
+           ClassName.Buffer = DefaultServerClasses[i].ClassName;
+           ClassName.Length = 0;
+           ClassName.MaximumLength = 0;
+        }
+        
         wc.cbSize = sizeof(wc);
-        wc.style = SystemClasses[i].Style;
-        wc.lpfnWndProc = SystemClasses[i].ProcW;
+        wc.style = DefaultServerClasses[i].Style;
+
+        Flags |= CSF_SERVERSIDEPROC;
+
+        if (DefaultServerClasses[i].ProcW)
+        {
+           wc.lpfnWndProc = DefaultServerClasses[i].ProcW;
+           wc.hInstance = hModuleWin;
+        }
+        else
+        {
+           wc.lpfnWndProc = GETPFNSERVER(DefaultServerClasses[i].fiId);
+           wc.hInstance = hModClient;
+        }
+
         wc.cbClsExtra = 0;
-        wc.cbWndExtra = SystemClasses[i].ExtraBytes;
-        wc.hInstance = hModClient;
+        wc.cbWndExtra = DefaultServerClasses[i].ExtraBytes;
         wc.hIcon = NULL;
-        wc.hCursor = SystemClasses[i].hCursor;
-        wc.hbrBackground = SystemClasses[i].hBrush;
+        wc.hCursor = DefaultServerClasses[i].hCursor;
+        wc.hbrBackground = DefaultServerClasses[i].hBrush;
         wc.lpszMenuName = NULL;
         wc.lpszClassName = ClassName.Buffer;
         wc.hIconSm = NULL;
 
-        Class = IntCreateClass(&wc,
-                               &ClassName,
-                               &MenuName,
-                               SystemClasses[i].ProcA,
-                               SystemClasses[i].ClassId,
-                               CSF_SYSTEMCLASS,
-                               NULL,
-                               pi);
+        Class = IntCreateClass( &wc,
+                                &ClassName,
+                                &MenuName,
+                                 DefaultServerClasses[i].fiId,
+                                 Flags,
+                                 NULL,
+                                 ppi);
         if (Class != NULL)
         {
-            ASSERT(Class->System);
-            Class->pclsNext = SystemClassList;
-            (void)InterlockedExchangePointer((PVOID*)&SystemClassList,
+            Class->pclsNext = ppi->pclsPublicList;
+            (void)InterlockedExchangePointer((PVOID*)&ppi->pclsPublicList,
                                              Class);
+
+            ppi->dwRegisteredClasses |= ICLASS_TO_MASK(DefaultServerClasses[i].iCls);
         }
         else
         {
@@ -1921,9 +1947,7 @@ UserRegisterSystemClasses(IN ULONG Count,
             Ret = FALSE;
         }
     }
-
-    if (Ret)
-        RegisteredSysClasses = TRUE;
+    if (Ret) ppi->W32PF_flags |= W32PF_CLASSESREGISTERED;
     return Ret;
 }
 
@@ -1953,21 +1977,30 @@ NtUserRegisterClassExWOW(
     WNDCLASSEXW CapturedClassInfo = {0};
     UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0};
     RTL_ATOM Ret = (RTL_ATOM)0;
-    WNDPROC wpExtra = NULL;
+    PPROCESSINFO ppi = GetW32ProcessInfo();
 
     if (Flags & ~(CSF_ANSIPROC))
     {
-        SetLastWin32Error(ERROR_INVALID_FLAGS);
+        DPRINT1("NtUserRegisterClassExWOW Bad Flags!\n");
+        EngSetLastError(ERROR_INVALID_FLAGS);
         return Ret;
     }
 
     UserEnterExclusive();
 
+    DPRINT("NtUserRegisterClassExWOW ClsN %wZ\n",ClassName);
+
+    if ( !(ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
+    {
+       UserRegisterSystemClasses();
+    }
+
     _SEH2_TRY
     {
         /* Probe the parameters and basic parameter checks */
         if (ProbeForReadUint(&lpwcx->cbSize) != sizeof(WNDCLASSEXW))
         {
+            DPRINT1("NtUserRegisterClassExWOW Wrong cbSize!\n");
             goto InvalidParameter;
         }
 
@@ -1996,6 +2029,7 @@ NtUserRegisterClassExWOW(
              CapturedClassInfo.cbWndExtra < 0 ||
              CapturedClassInfo.hInstance == NULL)
         {
+            DPRINT1("NtUserRegisterClassExWOW Invalid Parameter Error!\n");
             goto InvalidParameter;
         }
 
@@ -2009,6 +2043,7 @@ NtUserRegisterClassExWOW(
         {
             if (!IS_ATOM(CapturedName.Buffer))
             {
+                DPRINT1("NtUserRegisterClassExWOW ClassName Error!\n");
                 goto InvalidParameter;
             }
         }
@@ -2022,66 +2057,44 @@ NtUserRegisterClassExWOW(
         else if (CapturedMenuName.Buffer != NULL &&
                  !IS_INTRESOURCE(CapturedMenuName.Buffer))
         {
+            DPRINT1("NtUserRegisterClassExWOW MenuName Error!\n");
 InvalidParameter:
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
             _SEH2_LEAVE;
         }
+
+        if (IsCallProcHandle(lpwcx->lpfnWndProc))
+        {// Never seen this yet, but I'm sure it's a little haxxy trick!
+         // If this pops up we know what todo!
+           DPRINT1("NtUserRegisterClassExWOW WndProc is CallProc!!\n");
+        }
+
+        DPRINT("NtUserRegisterClassExWOW MnuN %wZ\n",&CapturedMenuName);
+
         /* Register the class */
         Ret = UserRegisterClass(&CapturedClassInfo,
                                 &CapturedName,
                                 &CapturedMenuName,
-                                wpExtra,
                                 fnID,
                                 Flags);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
+        DPRINT1("NtUserRegisterClassExWOW Exception Error!\n");
         SetLastNtError(_SEH2_GetExceptionCode());
     }
     _SEH2_END;
-
-    UserLeave();
-
-    return Ret;
-}
-
-ULONG_PTR APIENTRY
-NtUserGetClassLong(IN HWND hWnd,
-                   IN INT Offset,
-                   IN BOOL Ansi)
-{
-    PWINDOW_OBJECT Window;
-    ULONG_PTR Ret = 0;
-
-    if (Offset != GCLP_WNDPROC)
-    {
-        UserEnterShared();
-    }
-    else
-    {
-        UserEnterExclusive();
-    }
-
-    Window = UserGetWindowObject(hWnd);
-    if (Window != NULL)
+/*
+    if (!Ret)
     {
-        Ret = UserGetClassLongPtr(Window->Wnd->pcls,
-                                  Offset,
-                                  Ansi);
-
-        if (Ret != 0 && Offset == GCLP_MENUNAME && Window->Wnd->pcls->MenuNameIsString)
-        {
-            Ret = (ULONG_PTR)UserHeapAddressToUser((PVOID)Ret);
-        }
+       DPRINT1("NtUserRegisterClassExWOW Null Return!\n");
     }
-
+ */
     UserLeave();
 
     return Ret;
 }
 
-
-
 ULONG_PTR APIENTRY
 NtUserSetClassLong(HWND hWnd,
                    INT Offset,
@@ -2089,21 +2102,19 @@ NtUserSetClassLong(HWND hWnd,
                    BOOL Ansi)
 {
     PPROCESSINFO pi;
-    PWINDOW_OBJECT Window;
+    PWND Window;
     ULONG_PTR Ret = 0;
 
     UserEnterExclusive();
 
     pi = GetW32ProcessInfo();
-    if (pi == NULL)
-        goto Cleanup;
 
     Window = UserGetWindowObject(hWnd);
     if (Window != NULL)
     {
-        if (Window->ti->ppi != pi)
+        if (Window->head.pti->ppi != pi)
         {
-            SetLastWin32Error(ERROR_ACCESS_DENIED);
+            EngSetLastError(ERROR_ACCESS_DENIED);
             goto Cleanup;
         }
 
@@ -2135,7 +2146,7 @@ NtUserSetClassLong(HWND hWnd,
                     else if (Offset == GCLP_MENUNAME && !IS_INTRESOURCE(Value.Buffer))
                     {
 InvalidParameter:
-                        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+                        EngSetLastError(ERROR_INVALID_PARAMETER);
                         _SEH2_LEAVE;
                     }
                 }
@@ -2143,7 +2154,7 @@ InvalidParameter:
                 dwNewLong = (ULONG_PTR)&Value;
             }
 
-            Ret = UserSetClassLongPtr(Window->Wnd->pcls,
+            Ret = UserSetClassLongPtr(Window->pcls,
                                       Offset,
                                       dwNewLong,
                                       Ansi);
@@ -2204,14 +2215,15 @@ NtUserUnregisterClass(IN PUNICODE_STRING ClassNameOrAtom,
             if (!IS_ATOM(CapturedClassName.Buffer))
             {
 InvalidParameter:
-                SetLastWin32Error(ERROR_INVALID_PARAMETER);
+                EngSetLastError(ERROR_INVALID_PARAMETER);
                 _SEH2_LEAVE;
             }
         }
 
         /* unregister the class */
         Ret = UserUnregisterClass(&CapturedClassName,
-                                  hInstance);
+                                  hInstance,
+                                  NULL); // Null for now~
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -2236,18 +2248,18 @@ NtUserGetClassInfo(
    WNDCLASSEXW Safewcexw;
    PCLS Class;
    RTL_ATOM ClassAtom = 0;
-   PPROCESSINFO pi;
+   PPROCESSINFO ppi;
    BOOL Ret = TRUE;
 
    /* NOTE: need exclusive lock because getting the wndproc might require the
             creation of a call procedure handle */
    UserEnterExclusive();
 
-   pi = GetW32ProcessInfo();
-   if (pi == NULL)
+   ppi = GetW32ProcessInfo();
+
+   if ( !(ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
    {
-      ERR("GetW32ProcessInfo() returned NULL!\n");
-      goto Cleanup;
+      UserRegisterSystemClasses();
    }
 
    _SEH2_TRY
@@ -2262,7 +2274,9 @@ NtUserGetClassInfo(
 
       if (CapturedClassName.Length & 1)
       {
-         goto InvalidParameter;
+         EngSetLastError(ERROR_INVALID_PARAMETER);
+         Ret = FALSE;
+         _SEH2_LEAVE;
       }
 
       if (CapturedClassName.Length != 0)
@@ -2285,7 +2299,9 @@ NtUserGetClassInfo(
          if (!IS_ATOM(CapturedClassName.Buffer))
          {
             ERR("NtUserGetClassInfo() got ClassName instead of Atom!\n");
-            goto InvalidParameter;
+            EngSetLastError(ERROR_INVALID_PARAMETER);
+            Ret = FALSE;
+            _SEH2_LEAVE;
          }
 
          SafeClassName.Buffer = CapturedClassName.Buffer;
@@ -2293,30 +2309,26 @@ NtUserGetClassInfo(
          SafeClassName.MaximumLength = 0;
       }
 
-      if (ProbeForReadUint(&lpWndClassEx->cbSize) != sizeof(WNDCLASSEXW))
-      {
-InvalidParameter:
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         Ret = FALSE;
-         _SEH2_LEAVE;
-      }
-
       ProbeForWrite( lpWndClassEx, sizeof(WNDCLASSEXW), sizeof(ULONG));
 
       RtlCopyMemory( &Safewcexw, lpWndClassEx, sizeof(WNDCLASSEXW));
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
-      SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+      SetLastNtError(_SEH2_GetExceptionCode());
       Ret = FALSE;
    }
    _SEH2_END;
 
+   // If null instance use client.
+   if (!hInstance) hInstance = hModClient;
+
    if (Ret)
    {
+      DPRINT("GetClassInfo(%wZ, 0x%x)\n", ClassName, hInstance);
       ClassAtom = IntGetClassAtom( &SafeClassName,
                                     hInstance,
-                                    pi,
+                                    ppi,
                                    &Class,
                                     NULL);
       if (ClassAtom != (RTL_ATOM)0)
@@ -2330,7 +2342,7 @@ InvalidParameter:
       }
       else
       {
-         SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+         EngSetLastError(ERROR_CLASS_DOES_NOT_EXIST);
          Ret = FALSE;
       }
    }
@@ -2351,25 +2363,23 @@ InvalidParameter:
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
-      SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+      EngSetLastError(ERROR_CLASS_DOES_NOT_EXIST);
       Ret = FALSE;
    }
    _SEH2_END;
 
-Cleanup:
    if (SafeClassName.Length) ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
    UserLeave();
    return Ret;
 }
 
 
-
 INT APIENTRY
 NtUserGetClassName (IN HWND hWnd,
                     OUT PUNICODE_STRING ClassName,
                     IN BOOL Ansi)
 {
-    PWINDOW_OBJECT Window;
+    PWND Window;
     UNICODE_STRING CapturedClassName;
     INT Ret = 0;
 
@@ -2384,7 +2394,7 @@ NtUserGetClassName (IN HWND hWnd,
             CapturedClassName = *ClassName;
 
             /* get the class name */
-            Ret = UserGetClassName(Window->Wnd->pcls,
+            Ret = UserGetClassName(Window->pcls,
                                    &CapturedClassName,
                                    Ansi);
 
@@ -2420,11 +2430,6 @@ NtUserGetWOWClass(HINSTANCE hInstance,
   UserEnterExclusive();
 
   pi = GetW32ProcessInfo();
-  if (pi == NULL)
-  {
-     ERR("GetW32ProcessInfo() returned NULL!\n");
-     goto Cleanup;
-  }
 
   _SEH2_TRY
   {
@@ -2460,7 +2465,7 @@ NtUserGetWOWClass(HINSTANCE hInstance,
   }
   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
   {
-     SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+     EngSetLastError(ERROR_CLASS_DOES_NOT_EXIST);
      Hit = TRUE;
   }
   _SEH2_END;
@@ -2474,11 +2479,10 @@ NtUserGetWOWClass(HINSTANCE hInstance,
                                    NULL);
      if (!ClassAtom)
      {
-        SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+        EngSetLastError(ERROR_CLASS_DOES_NOT_EXIST);
      }
   }
 
-Cleanup:
   if (SafeClassName.Length) ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
   UserLeave();
 //