[WIN32k]
[reactos.git] / reactos / win32ss / user / user32 / windows / class.c
index c7d0aaa..15b4e9f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * PROJECT:         ReactOS user32.dll
  * COPYRIGHT:       GPL - See COPYING in the top level directory
- * FILE:            dll/win32/user32/windows/class.c
+ * FILE:            win32ss/user/user32/windows/class.c
  * PURPOSE:         Window classes
  * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
  * UPDATE HISTORY:
 #include <wine/debug.h>
 WINE_DEFAULT_DEBUG_CHANNEL(user32);
 
+#define USE_VERSIONED_CLASSES
+
 /* From rtl/actctx.c and must match! */
-struct entity
+struct strsection_header
 {
-    DWORD  kind;  // Activation context type
-    WCHAR *name;  // Class name
-    WCHAR *clsid; // Not supported yet but needed for menu name.
+    DWORD magic;
+    ULONG size;
+    DWORD unk1[3];
+    ULONG count;
+    ULONG index_offset;
+    DWORD unk2[2];
+    ULONG global_offset;
+    ULONG global_len;
 };
 
-struct dll_redirect
+struct wndclass_redirect_data
 {
-    WCHAR *name; // Dll name
-    WCHAR *hash;
-    DWORD  Data; // Junk
+    ULONG size;
+    DWORD res;
+    ULONG name_len;
+    ULONG name_offset;  /* versioned name offset */
+    ULONG module_len;
+    ULONG module_offset;/* container name offset */
 };
 
-LPCWSTR
-FASTCALL
-ClassNameToVersion(
-  LPCTSTR lpszClass,
-  LPCWSTR lpszMenuName,
-  LPCWSTR *plpLibFileName,
-  HANDLE *pContext,
-  BOOL bAnsi)
-{
-   NTSTATUS Status;
-   UNICODE_STRING SectionName;
-   WCHAR SeactionNameBuf[MAX_PATH] = {0};
-   ACTCTX_SECTION_KEYED_DATA KeyedData = { sizeof(KeyedData) };
-
-   if (IS_ATOM(lpszClass))
-   {
-      SectionName.Buffer = (LPWSTR)&SeactionNameBuf;
-      SectionName.MaximumLength = sizeof(SeactionNameBuf);
-      if(!NtUserGetAtomName(LOWORD((DWORD_PTR)lpszClass), &SectionName))
-      {
-         return NULL;
-      }
-   }
-   else
-  {
-      if (bAnsi)
-      {
-         RtlCreateUnicodeStringFromAsciiz(&SectionName, (LPSTR)lpszClass);
-      }
-      else
-      {
-         RtlInitUnicodeString(&SectionName, lpszClass);
-      }
-   }
-   Status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
-                                                   NULL,
-                                                   ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION,
-                                                  &SectionName,
-                                                  &KeyedData );
-   if (NT_SUCCESS(Status) && KeyedData.ulDataFormatVersion == 1)
-   {
-      struct dll_redirect *dll = KeyedData.lpSectionBase;
-
-      if (plpLibFileName) *plpLibFileName = dll->name;
-
-      if (lpszMenuName)
-      {
-         WCHAR * mnubuf;
-         LPWSTR mnuNameW;
-         LPSTR mnuNameA;
-         int len = 0;
-         struct entity *entity = KeyedData.lpData;
-
-         FIXME("actctx: Needs to support menu name from redirected class!");
-
-         if (entity->clsid)
-         {
-            mnubuf = entity->clsid;
-            if (bAnsi)
-            {
-               mnuNameA = (LPSTR)lpszMenuName;
-               RtlUnicodeToMultiByteN( mnuNameA, 255, (PULONG)&len, mnubuf, strlenW(mnubuf) * sizeof(WCHAR) );
-               mnuNameA[len] = 0;
-            }
-            else
-            {
-               mnuNameW = (LPWSTR)lpszMenuName;
-               len = strlenW(mnubuf) * sizeof(WCHAR);
-               RtlCopyMemory((void *)mnuNameW, mnubuf, len);
-               mnuNameW[len] = 0;
-            }
-         }
-      }
-      if (pContext) *pContext = KeyedData.hActCtx;
-   }
-
-   if (!IS_ATOM(lpszClass) && bAnsi)
-      RtlFreeUnicodeString(&SectionName);
-   if (KeyedData.hActCtx)
-      RtlReleaseActivationContext(KeyedData.hActCtx);
-
-   return lpszClass;
-}
-
-//
-// Ref: http://yvs-it.blogspot.com/2010/04/initcommoncontrolsex.html
-//
-BOOL
-FASTCALL
-Real_VersionRegisterClass(
-  PCWSTR pszClass,
-  LPCWSTR lpLibFileName,
-  HANDLE Contex,
-  HMODULE * phLibModule)
-{
-   BOOL Ret;
-   HMODULE hLibModule;
-   PREGISTERCLASSNAMEW pRegisterClassNameW;
-   UNICODE_STRING ClassName;
-   WCHAR ClassNameBuf[MAX_PATH] = {0};
-   RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame = { sizeof(Frame), 1 };
-
-   RtlActivateActivationContextUnsafeFast(&Frame, Contex);
-
-   Ret = FALSE;
-   hLibModule = NULL;
-
-   _SEH2_TRY
-   {
-      hLibModule = LoadLibraryW(lpLibFileName);
-      if ( hLibModule )
-      {
-         if ((pRegisterClassNameW = (void*) GetProcAddress(hLibModule, "RegisterClassNameW")))
-         {
-            if (IS_ATOM(pszClass))
-            {
-               ClassName.Buffer = (LPWSTR)&ClassNameBuf;
-               ClassName.MaximumLength = sizeof(ClassNameBuf);
-               if (!NtUserGetAtomName(LOWORD((DWORD_PTR)pszClass), &ClassName))
-               {
-                  _SEH2_YIELD(goto Error_Exit);
-               }
-               pszClass = (PCWSTR)&ClassNameBuf;
-            }
-            Ret = pRegisterClassNameW(pszClass);
-         }
-      }
-   }
-   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-   {
-   }
-   _SEH2_END
-
-Error_Exit:
-   if ( Ret || !hLibModule )
-   {
-      if ( phLibModule ) *phLibModule = hLibModule;  
-   }
-   else
-   {
-      DWORD save_error = GetLastError();
-      FreeLibrary(hLibModule);
-      SetLastError(save_error);
-   }
-                                  
-   return Ret;
-}
-
 //
-// Use wine hack to process extened context classes.
+// Use wine hack to process extended context classes.
 //
 /***********************************************************************
  *           is_comctl32_class
  */
-static BOOL is_comctl32_class( const WCHAR *name )
+LPCWSTR is_comctl32_class( const WCHAR *name )
 {
     static const WCHAR classesW[][20] =
     {
@@ -213,13 +74,121 @@ static BOOL is_comctl32_class( const WCHAR *name )
     while (min <= max)
     {
         int res, pos = (min + max) / 2;
-        if (!(res = strcmpiW( name, classesW[pos] ))) return TRUE;
+        if (!(res = strcmpiW( name, classesW[pos] ))) return classesW[pos];
         if (res < 0) max = pos - 1;
         else min = pos + 1;
     }
-    return FALSE;
+    return NULL;
 }
 
+LPCWSTR
+FASTCALL
+ClassNameToVersion(
+  const void* lpszClass,
+  LPCWSTR lpszMenuName,
+  LPCWSTR *plpLibFileName,
+  HANDLE *pContext,
+  BOOL bAnsi)
+{
+    LPCWSTR VersionedClass = NULL;
+    NTSTATUS Status;
+    UNICODE_STRING SectionName;
+    WCHAR SectionNameBuf[MAX_PATH] = {0};
+    ACTCTX_SECTION_KEYED_DATA KeyedData = { sizeof(KeyedData) };
+
+    if(!lpszClass)
+    {
+        ERR("Null class given !\n");
+        return NULL;
+    }
+
+    if (IS_ATOM(lpszClass))
+    {
+        RtlInitEmptyUnicodeString(&SectionName, SectionNameBuf, sizeof(SectionNameBuf));
+        if(!NtUserGetAtomName(LOWORD((DWORD_PTR)lpszClass), &SectionName))
+        {
+            ERR("Couldn't get atom name for atom %x !\n", LOWORD((DWORD_PTR)lpszClass));
+            return NULL;
+        }
+        SectionName.Length = wcslen(SectionNameBuf) * sizeof(WCHAR);
+        TRACE("ClassNameToVersion got name %wZ from atom\n", &SectionName);
+    }
+    else
+    {
+        if (bAnsi)
+        {
+            ANSI_STRING AnsiString;
+            RtlInitAnsiString(&AnsiString, lpszClass);
+            RtlInitEmptyUnicodeString(&SectionName, SectionNameBuf, sizeof(SectionNameBuf));
+            RtlAnsiStringToUnicodeString(&SectionName, &AnsiString, FALSE);
+        }
+        else
+        {
+            RtlInitUnicodeString(&SectionName, lpszClass);
+        }
+    }
+    Status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
+                                                    NULL,
+                                                    ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION,
+                                                   &SectionName,
+                                                   &KeyedData );
+
+#ifdef USE_VERSIONED_CLASSES
+    if (NT_SUCCESS(Status) && KeyedData.ulDataFormatVersion == 1)
+    {
+        struct strsection_header *SectionHeader = KeyedData.lpSectionBase;
+
+        /* Find activation context */
+        if(SectionHeader && SectionHeader->count > 0)
+        {
+            struct wndclass_redirect_data *WindowRedirectionData = KeyedData.lpData;
+            if(WindowRedirectionData && WindowRedirectionData->module_len)
+            {
+                LPCWSTR lpLibFileName;
+
+                VersionedClass = (WCHAR*)((BYTE*)WindowRedirectionData + WindowRedirectionData->name_offset);
+                lpLibFileName = (WCHAR*)((BYTE*)KeyedData.lpSectionBase + WindowRedirectionData->module_offset);
+                TRACE("Returning VersionedClass=%S, plpLibFileName=%S for class %S\n", VersionedClass, lpLibFileName, SectionName.Buffer);
+
+                if (pContext) *pContext = KeyedData.hActCtx;
+                if (plpLibFileName) *plpLibFileName = lpLibFileName;
+
+            }
+        }
+    }
+
+    if (KeyedData.hActCtx)
+        RtlReleaseActivationContext(KeyedData.hActCtx);
+#endif
+
+#ifndef DEFAULT_ACTIVATION_CONTEXTS_SUPPORTED
+    /* This block is a hack! */
+    if (!VersionedClass)
+    {
+        /* 
+         * In windows the default activation context always contains comctl32v5 
+         * In reactos we don't have a default activation context so we 
+         * mimic wine here.
+         */
+        VersionedClass = is_comctl32_class(SectionName.Buffer);
+        if (VersionedClass)
+        {
+            if (pContext) *pContext = 0;
+            if (plpLibFileName) *plpLibFileName = L"comctl32";
+        }
+    }
+#endif
+
+    /* 
+     * The returned strings are pointers in the activation context and 
+     * will get freed when the activation context gets freed 
+     */
+    return VersionedClass;
+}
+
+//
+// Ref: http://yvs-it.blogspot.com/2010/04/initcommoncontrolsex.html
+//
 BOOL
 FASTCALL
 VersionRegisterClass(
@@ -228,64 +197,61 @@ VersionRegisterClass(
   HANDLE Contex,
   HMODULE * phLibModule)
 {
-   // Should be lpLibFileName.....
-   static const WCHAR comctl32W[] = {'c','o','m','c','t','l','3','2','.','d','l','l',0};
-   //
-   PREGISTERCLASSNAMEW pRegisterClassNameW;
-   UNICODE_STRING ClassName;
-   WCHAR ClassNameBuf[MAX_PATH] = {0};
-   BOOL Ret = FALSE;
-   HMODULE hLibModule = NULL;
-   
-   if (is_comctl32_class( pszClass ))
-   {
-   _SEH2_TRY
-   {
-      hLibModule = LoadLibraryW(comctl32W);
-      if ( hLibModule )
-      {
-         if ((pRegisterClassNameW = (void*) GetProcAddress(hLibModule, "RegisterClassNameW")))
-         {
-            if (IS_ATOM(pszClass))
+    BOOL Ret = FALSE;
+    HMODULE hLibModule = NULL;
+    PREGISTERCLASSNAMEW pRegisterClassNameW;
+    UNICODE_STRING ClassName;
+    WCHAR ClassNameBuf[MAX_PATH] = {0};
+    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame = { sizeof(Frame), 1 };
+
+    RtlActivateActivationContextUnsafeFast(&Frame, Contex);
+
+    _SEH2_TRY
+    {
+        hLibModule = LoadLibraryW(lpLibFileName);
+        if ( hLibModule )
+        {
+            if ((pRegisterClassNameW = (void*) GetProcAddress(hLibModule, "RegisterClassNameW")))
+            {
+                if (IS_ATOM(pszClass))
+                {
+                    ClassName.Buffer = ClassNameBuf;
+                    ClassName.MaximumLength = sizeof(ClassNameBuf);
+                    if (!NtUserGetAtomName(LOWORD((DWORD_PTR)pszClass), &ClassName))
+                    {
+                        ERR("Error while verifying ATOM\n");
+                        _SEH2_YIELD(goto Error_Exit);
+                    }
+                    pszClass = ClassName.Buffer;
+                }
+                Ret = pRegisterClassNameW(pszClass);
+            }
+            else
             {
-               ClassName.Buffer = (LPWSTR)&ClassNameBuf;
-               ClassName.MaximumLength = sizeof(ClassNameBuf);
-               if (!NtUserGetAtomName(LOWORD((DWORD_PTR)pszClass), &ClassName))
-               {
-                  ERR("Error while verifying ATOM\n");
-                  _SEH2_YIELD(goto Error_Exit);
-               }
-               pszClass = (PCWSTR)&ClassNameBuf;
+                WARN("No RegisterClassNameW PROC\n");
             }
-            Ret = pRegisterClassNameW(pszClass);
-         }
-      }
-   }
-   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-   {
-   }
-   _SEH2_END
+        }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+    }
+    _SEH2_END
 
 Error_Exit:
-   if ( Ret || !hLibModule )
-   {
-      if ( phLibModule ) *phLibModule = hLibModule;  
-   }
-   else
-   {
-      DWORD save_error = GetLastError();
-      FreeLibrary(hLibModule);
-      SetLastError(save_error);
-   }
-      TRACE( "%s retrying after loading comctl32\n", debugstr_w(pszClass) );
-      return Ret;
-   }
-   TRACE("NO ComCtl32 Class %S!\n",pszClass);
-   return FALSE;
+    if ( Ret || !hLibModule )
+    {
+        if ( phLibModule ) *phLibModule = hLibModule;
+    }
+    else
+    {
+        DWORD save_error = GetLastError();
+        FreeLibrary(hLibModule);
+        SetLastError(save_error);
+    }
+
+    RtlDeactivateActivationContextUnsafeFast(&Frame);
+    return Ret;
 }
-//
-//
-//
 
 /*
  * @implemented
@@ -301,7 +267,10 @@ GetClassInfoExA(
     LPCSTR pszMenuName;
     HMODULE hLibModule = NULL;
     DWORD save_error;
-    BOOL Ret, ClassFound = FALSE;
+    BOOL Ret, ClassFound = FALSE, ConvertedString = FALSE;
+    LPCWSTR lpszClsVersion;
+    HANDLE pCtx = NULL;
+    LPCWSTR lpLibFileName = NULL;
 
     TRACE("%p class/atom: %s/%04x %p\n", hInstance,
         IS_ATOM(lpszClass) ? NULL : lpszClass,
@@ -310,8 +279,8 @@ GetClassInfoExA(
 
     if (!lpwcx)
     {
-       SetLastError( ERROR_NOACCESS );
-       return FALSE;
+        SetLastError( ERROR_NOACCESS );
+        return FALSE;
     }
 
     if (hInstance == User32Instance)
@@ -325,14 +294,19 @@ GetClassInfoExA(
         return FALSE;
     }
 
-    if (IS_ATOM(lpszClass))
+    lpszClsVersion = ClassNameToVersion(lpszClass, NULL, &lpLibFileName, &pCtx, TRUE);
+    if (lpszClsVersion)
+    {
+        RtlInitUnicodeString(&ClassName, lpszClsVersion);
+    }
+    else if (IS_ATOM(lpszClass))
     {
         ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass);
     }
     else
     {
-        if (!RtlCreateUnicodeStringFromAsciiz(&ClassName,
-                                              lpszClass))
+        ConvertedString = TRUE;
+        if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, lpszClass))
         {
             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
             return FALSE;
@@ -347,39 +321,40 @@ GetClassInfoExA(
 
     for(;;)
     {
-       Ret = NtUserGetClassInfo( hInstance,
-                                &ClassName,
-                                (LPWNDCLASSEXW)lpwcx,
-                                (LPWSTR *)&pszMenuName,
+        Ret = NtUserGetClassInfo( hInstance,
+                                 &ClassName,
+                                 (LPWNDCLASSEXW)lpwcx,
+                                 (LPWSTR *)&pszMenuName,
                                  TRUE);
-       if (Ret) break;
-       if (!ClassFound)
-       {
-          save_error = GetLastError();
-          if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
-               save_error == ERROR_CLASS_DOES_NOT_EXIST )
-          {
-              ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule);
-              if (ClassFound) continue;
-          }
-       }
-       if (hLibModule)
-       {
-          save_error = GetLastError();
-          FreeLibrary(hLibModule);
-          SetLastError(save_error);
-          hLibModule = 0;
-       }
-       break;
+        if (Ret) break;
+        if (!lpLibFileName) break;
+        if (!ClassFound)
+        {
+            save_error = GetLastError();
+            if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
+                 save_error == ERROR_CLASS_DOES_NOT_EXIST )
+            {
+                ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule);
+                if (ClassFound) continue;
+            }
+        }
+        if (hLibModule)
+        {
+            save_error = GetLastError();
+            FreeLibrary(hLibModule);
+            SetLastError(save_error);
+            hLibModule = 0;
+        }
+        break;
     }
 
     if (Ret)
     {
-       lpwcx->lpszClassName = lpszClass;
+        lpwcx->lpszClassName = lpszClass;
 //       lpwcx->lpszMenuName  = pszMenuName;
     }
 
-    if (!IS_ATOM(lpszClass))
+    if (ConvertedString)
     {
         RtlFreeUnicodeString(&ClassName);
     }
@@ -403,6 +378,9 @@ GetClassInfoExW(
     HMODULE hLibModule = NULL;
     DWORD save_error;
     BOOL Ret, ClassFound = FALSE;
+    LPCWSTR lpszClsVersion;
+    HANDLE pCtx = NULL;
+    LPCWSTR lpLibFileName = NULL;
 
     TRACE("%p class/atom: %S/%04x %p\n", hInstance,
         IS_ATOM(lpszClass) ? NULL : lpszClass,
@@ -429,14 +407,18 @@ GetClassInfoExW(
         return FALSE;
     }
 
-    if (IS_ATOM(lpszClass))
+    lpszClsVersion = ClassNameToVersion(lpszClass, NULL, &lpLibFileName, &pCtx, FALSE);
+    if (lpszClsVersion)
+    {
+        RtlInitUnicodeString(&ClassName, lpszClsVersion);
+    }
+    else if (IS_ATOM(lpszClass))
     {
         ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass);
     }
     else
     {
-        RtlInitUnicodeString(&ClassName,
-                             lpszClass);
+        RtlInitUnicodeString(&ClassName, lpszClass);
     }
 
     if (!RegisterDefaultClasses)
@@ -447,35 +429,36 @@ GetClassInfoExW(
 
     for(;;)
     {
-       Ret = NtUserGetClassInfo( hInstance,
-                                &ClassName,
-                                 lpwcx,
-                                &pszMenuName,
-                                 FALSE);
-       if (Ret) break;
-       if (!ClassFound)
-       {
-          save_error = GetLastError();
-          if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
-               save_error == ERROR_CLASS_DOES_NOT_EXIST )
-          {
-              ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule);
-              if (ClassFound) continue;
-          }
-       }
-       if (hLibModule)
-       {
-          save_error = GetLastError();
-          FreeLibrary(hLibModule);
-          SetLastError(save_error);
-          hLibModule = 0;
-       }
-       break;
+        Ret = NtUserGetClassInfo( hInstance,
+                                 &ClassName,
+                                  lpwcx,
+                                 &pszMenuName,
+                                  FALSE);
+        if (Ret) break;
+        if (!lpLibFileName) break;
+        if (!ClassFound)
+        {
+            save_error = GetLastError();
+            if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
+                 save_error == ERROR_CLASS_DOES_NOT_EXIST )
+            {
+                ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule);
+                if (ClassFound) continue;
+            }
+        }
+        if (hLibModule)
+        {
+            save_error = GetLastError();
+            FreeLibrary(hLibModule);
+            SetLastError(save_error);
+            hLibModule = 0;
+        }
+        break;
     }
 
     if (Ret)
     {
-       lpwcx->lpszClassName = lpszClass;
+        lpwcx->lpszClassName = lpszClass;
 //       lpwcx->lpszMenuName  = pszMenuName;
     }
     return Ret;
@@ -549,51 +532,51 @@ GetClassInfoW(
 ULONG_PTR FASTCALL
 IntGetClsWndProc(PWND pWnd, PCLS Class, BOOL Ansi)
 {
-  INT i;
-  ULONG_PTR gcpd, Ret = 0;
+    INT i;
+    ULONG_PTR gcpd, Ret = 0;
  // If server side, sweep through proc list and return the client side proc.
-  if (Class->CSF_flags & CSF_SERVERSIDEPROC)
-  {  // Always scan through the list due to wine class "deftest".
-     for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
-     {
-         if (GETPFNSERVER(i) == Class->lpfnWndProc)
-         {
-            if (Ansi)
-               Ret = (ULONG_PTR)GETPFNCLIENTA(i);
-            else
-               Ret = (ULONG_PTR)GETPFNCLIENTW(i);
-         }
-     }
-     return Ret;
-  }
-  // Set return proc.
-  Ret = (ULONG_PTR)Class->lpfnWndProc;
-  // Return the proc if one of the FnId default class type.
-  if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
-  {
-     if (Ansi)
-     { // If match return the right proc by type.
-        if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc)
-           Ret = (ULONG_PTR)GETPFNCLIENTA(Class->fnid);
-     }
-     else
-     {
-        if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc)
-           Ret = (ULONG_PTR)GETPFNCLIENTW(Class->fnid);
-     }
-  }
-  // Return on change or Ansi/Unicode proc equal.
-  if ( Ret != (ULONG_PTR)Class->lpfnWndProc ||
-       Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) )
-     return Ret;
-
-  /* We have an Ansi and Unicode swap! If Ansi create Unicode proc handle.
-     This will force CallWindowProc to deal with it. */
-  gcpd = NtUserGetCPD( UserHMGetHandle(pWnd),
-                       (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWndtoCls,
-                       Ret);
-
-  return (gcpd ? gcpd : Ret);
+    if (Class->CSF_flags & CSF_SERVERSIDEPROC)
+    {  // Always scan through the list due to wine class "deftest".
+        for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
+        {
+            if (GETPFNSERVER(i) == Class->lpfnWndProc)
+            {
+                if (Ansi)
+                    Ret = (ULONG_PTR)GETPFNCLIENTA(i);
+                else
+                    Ret = (ULONG_PTR)GETPFNCLIENTW(i);
+            }
+        }
+         return Ret;
+    }
+    // Set return proc.
+    Ret = (ULONG_PTR)Class->lpfnWndProc;
+    // Return the proc if one of the FnId default class type.
+    if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
+    {
+        if (Ansi)
+        { // If match return the right proc by type.
+            if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc)
+                Ret = (ULONG_PTR)GETPFNCLIENTA(Class->fnid);
+        }
+        else
+        {
+            if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc)
+               Ret = (ULONG_PTR)GETPFNCLIENTW(Class->fnid);
+        }
+    }
+    // Return on change or Ansi/Unicode proc equal.
+    if ( Ret != (ULONG_PTR)Class->lpfnWndProc ||
+         Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) )
+        return Ret;
+
+    /* We have an Ansi and Unicode swap! If Ansi create Unicode proc handle.
+       This will force CallWindowProc to deal with it. */
+    gcpd = NtUserGetCPD( UserHMGetHandle(pWnd),
+                         (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWndtoCls,
+                         Ret);
+
+    return (gcpd ? gcpd : Ret);
 }
 
 //
@@ -602,71 +585,71 @@ IntGetClsWndProc(PWND pWnd, PCLS Class, BOOL Ansi)
 WNDPROC FASTCALL
 IntGetWndProc(PWND pWnd, BOOL Ansi)
 {
-  INT i;
-  WNDPROC gcpd, Ret = 0;
-  PCLS Class = DesktopPtrToUser(pWnd->pcls);
-
-  if (!Class) return Ret;
-
-  if (pWnd->state & WNDS_SERVERSIDEWINDOWPROC)
-  {
-     for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
-     {
-         if (GETPFNSERVER(i) == pWnd->lpfnWndProc)
-         {
-            if (Ansi)
-               Ret = GETPFNCLIENTA(i);
-            else
-               Ret = GETPFNCLIENTW(i);
-         }
-     }
-     return Ret;
-  }
-  // Wine Class tests:
-  /*  Edit controls are special - they return a wndproc handle when
-      GetWindowLongPtr is called with a different A/W.
-      On the other hand there is no W->A->W conversion so this control
-      is treated specially.
-   */
-  if (Class->fnid == FNID_EDIT)
-     Ret = pWnd->lpfnWndProc;
-  else
-  {
-     // Set return proc.
-     Ret = pWnd->lpfnWndProc;
-
-     if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
-     {
-        if (Ansi)
+    INT i;
+    WNDPROC gcpd, Ret = 0;
+    PCLS Class = DesktopPtrToUser(pWnd->pcls);
+
+    if (!Class) return Ret;
+
+    if (pWnd->state & WNDS_SERVERSIDEWINDOWPROC)
+    {
+        for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
         {
-           if (GETPFNCLIENTW(Class->fnid) == pWnd->lpfnWndProc)
-              Ret = GETPFNCLIENTA(Class->fnid);
+            if (GETPFNSERVER(i) == pWnd->lpfnWndProc)
+            {
+                if (Ansi)
+                    Ret = GETPFNCLIENTA(i);
+                else
+                    Ret = GETPFNCLIENTW(i);
+            }
         }
-        else
+        return Ret;
+    }
+    // Wine Class tests:
+    /*  Edit controls are special - they return a wndproc handle when
+        GetWindowLongPtr is called with a different A/W.
+        On the other hand there is no W->A->W conversion so this control
+        is treated specially.
+     */
+    if (Class->fnid == FNID_EDIT)
+        Ret = pWnd->lpfnWndProc;
+    else
+    {
+        // Set return proc.
+        Ret = pWnd->lpfnWndProc;
+
+        if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
         {
-           if (GETPFNCLIENTA(Class->fnid) == pWnd->lpfnWndProc)
-              Ret = GETPFNCLIENTW(Class->fnid);
+            if (Ansi)
+            {
+                if (GETPFNCLIENTW(Class->fnid) == pWnd->lpfnWndProc)
+                    Ret = GETPFNCLIENTA(Class->fnid);
+            }
+            else
+            {
+                if (GETPFNCLIENTA(Class->fnid) == pWnd->lpfnWndProc)
+                    Ret = GETPFNCLIENTW(Class->fnid);
+            }
         }
-     }
-     // Return on the change.
-     if ( Ret != pWnd->lpfnWndProc)
-        return Ret;
-  }
+        // Return on the change.
+        if ( Ret != pWnd->lpfnWndProc)
+            return Ret;
+    }
 
-  if ( Ansi == !!(pWnd->state & WNDS_ANSIWINDOWPROC) )
-     return Ret;
+    if ( Ansi == !!(pWnd->state & WNDS_ANSIWINDOWPROC) )
+        return Ret;
 
-  gcpd = (WNDPROC)NtUserGetCPD( UserHMGetHandle(pWnd),
-                                (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWindow,
-                                (ULONG_PTR)Ret);
+    gcpd = (WNDPROC)NtUserGetCPD( UserHMGetHandle(pWnd),
+                                  (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWindow,
+                                  (ULONG_PTR)Ret);
 
-  return (gcpd ? gcpd : Ret);
+    return (gcpd ? gcpd : Ret);
 }
 
 static ULONG_PTR FASTCALL
 IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex)
 {
-       ULONG_PTR Ret = 0;
+    ULONG_PTR Ret = 0;
 
     if (nIndex >= 0)
     {
@@ -710,22 +693,19 @@ IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex)
                 break;
 
             case GCW_ATOM:
-                Ret = (ULONG_PTR)Class->atomClassName;
+                Ret = (ULONG_PTR)Class->atomNVClassName;
                 break;
 
             case GCLP_HCURSOR:
-                /* FIXME - get handle from pointer to CURSOR object */
-                Ret = (ULONG_PTR)Class->hCursor;
+                Ret = Class->spcur ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spcur))->h : 0;
                 break;
 
             case GCLP_HICON:
-                /* FIXME - get handle from pointer to ICON object */
-                Ret = (ULONG_PTR)Class->hIcon;
+                Ret = Class->spicn ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicn))->h : 0;
                 break;
 
             case GCLP_HICONSM:
-                /* FIXME - get handle from pointer to ICON object */
-                Ret = (ULONG_PTR)(Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern);
+                Ret = Class->spicnSm ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicnSm))->h : 0;
                 break;
 
             case GCLP_WNDPROC:
@@ -738,13 +718,13 @@ IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex)
         }
     }
 
-       return Ret;
+    return Ret;
 }
 
 static ULONG_PTR FASTCALL
 IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex)
 {
-       ULONG_PTR Ret = 0;
+    ULONG_PTR Ret = 0;
 
     if (nIndex >= 0)
     {
@@ -787,22 +767,19 @@ IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex)
                 break;
 
             case GCW_ATOM:
-                Ret = (ULONG_PTR)Class->atomClassName;
+                Ret = (ULONG_PTR)Class->atomNVClassName;
                 break;
 
             case GCLP_HCURSOR:
-                /* FIXME - get handle from pointer to CURSOR object */
-                Ret = (ULONG_PTR)Class->hCursor;
+                Ret = Class->spcur ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spcur))->h : 0;
                 break;
 
             case GCLP_HICON:
-                /* FIXME - get handle from pointer to ICON object */
-                Ret = (ULONG_PTR)Class->hIcon;
+                Ret = Class->spicn ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicn))->h : 0;
                 break;
 
             case GCLP_HICONSM:
-                /* FIXME - get handle from pointer to ICON object */
-                Ret = (ULONG_PTR)(Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern);
+                Ret = Class->spicnSm ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicnSm))->h : 0;
                 break;
 
             case GCLP_WNDPROC:
@@ -815,7 +792,7 @@ IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex)
         }
     }
 
-       return Ret;
+    return Ret;
 }
 
 /*
@@ -840,24 +817,24 @@ GetClassLongA(HWND hWnd, int nIndex)
         if (Class != NULL)
         {
 #ifdef _WIN64
-                       switch (nIndex)
-                       {
-                               case GCLP_HBRBACKGROUND:
-                               case GCLP_HCURSOR:
-                               case GCLP_HICON:
-                               case GCLP_HICONSM:
-                               case GCLP_HMODULE:
-                               case GCLP_MENUNAME:
-                               case GCLP_WNDPROC:
-                                       SetLastError(ERROR_INVALID_INDEX);
-                                       break;
-
-                               default:
-                                       Ret = IntGetClassLongA(Wnd, Class, nIndex);
-                                       break;
-                       }
+            switch (nIndex)
+            {
+                case GCLP_HBRBACKGROUND:
+                case GCLP_HCURSOR:
+                case GCLP_HICON:
+                case GCLP_HICONSM:
+                case GCLP_HMODULE:
+                case GCLP_MENUNAME:
+                case GCLP_WNDPROC:
+                    SetLastError(ERROR_INVALID_INDEX);
+                    break;
+
+                default:
+                    Ret = IntGetClassLongA(Wnd, Class, nIndex);
+                    break;
+            }
 #else
-                       Ret = IntGetClassLongA(Wnd, Class, nIndex);
+            Ret = IntGetClassLongA(Wnd, Class, nIndex);
 #endif
         }
         else
@@ -896,24 +873,24 @@ GetClassLongW ( HWND hWnd, int nIndex )
         if (Class != NULL)
         {
 #ifdef _WIN64
-                       switch (nIndex)
-                       {
-                               case GCLP_HBRBACKGROUND:
-                               case GCLP_HCURSOR:
-                               case GCLP_HICON:
-                               case GCLP_HICONSM:
-                               case GCLP_HMODULE:
-                               case GCLP_MENUNAME:
-                               case GCLP_WNDPROC:
-                                       SetLastError(ERROR_INVALID_INDEX);
-                                       break;
-
-                               default:
-                                       Ret = IntGetClassLongW(Wnd, Class, nIndex);
-                                       break;
-                       }
+            switch (nIndex)
+            {
+                case GCLP_HBRBACKGROUND:
+                case GCLP_HCURSOR:
+                case GCLP_HICON:
+                case GCLP_HICONSM:
+                case GCLP_HMODULE:
+                case GCLP_MENUNAME:
+                case GCLP_WNDPROC:
+                    SetLastError(ERROR_INVALID_INDEX);
+                    break;
+
+                default:
+                    Ret = IntGetClassLongW(Wnd, Class, nIndex);
+                    break;
+            }
 #else
-                       Ret = IntGetClassLongW(Wnd, Class, nIndex);
+            Ret = IntGetClassLongW(Wnd, Class, nIndex);
 #endif
         }
         else
@@ -954,7 +931,7 @@ GetClassLongPtrA(HWND hWnd,
         Class = DesktopPtrToUser(Wnd->pcls);
         if (Class != NULL)
         {
-                       Ret = IntGetClassLongA(Wnd, Class, nIndex);
+            Ret = IntGetClassLongA(Wnd, Class, nIndex);
         }
         else
         {
@@ -993,7 +970,7 @@ GetClassLongPtrW(HWND hWnd,
         Class = DesktopPtrToUser(Wnd->pcls);
         if (Class != NULL)
         {
-                       Ret = IntGetClassLongW(Wnd, Class, nIndex);
+            Ret = IntGetClassLongW(Wnd, Class, nIndex);
         }
         else
         {
@@ -1022,7 +999,7 @@ GetClassNameA(
 {
     WCHAR tmpbuf[MAX_ATOM_LEN + 1];
     int len;
-  
+
     if (nMaxCount <= 0) return 0;
     if (!GetClassNameW( hWnd, tmpbuf, sizeof(tmpbuf)/sizeof(WCHAR) )) return 0;
     RtlUnicodeToMultiByteN( lpClassName, nMaxCount - 1, (PULONG)&len, tmpbuf, strlenW(tmpbuf) * sizeof(WCHAR) );
@@ -1139,15 +1116,15 @@ LONG_PTR IntGetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
     case GWLP_ID:        retvalue = wndPtr->IDMenu; break;
     case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hModule; break;
     case GWLP_WNDPROC:
-       {
-               if (!TestWindowProcess(wndPtr))
-               {
-                       SetLastError(ERROR_ACCESS_DENIED);
-                       retvalue = 0;
-               }
-               retvalue = (ULONG_PTR)IntGetWndProc(wndPtr, !unicode);
+    {
+        if (!TestWindowProcess(wndPtr))
+        {
+            SetLastError(ERROR_ACCESS_DENIED);
+            retvalue = 0;
+        }
+        retvalue = (ULONG_PTR)IntGetWndProc(wndPtr, !unicode);
         break;
-       }
+    }
     default:
         WARN("Unknown offset %d\n", offset );
         SetLastError( ERROR_INVALID_INDEX );
@@ -1256,7 +1233,7 @@ RealGetWindowClassA(
 {
     WCHAR tmpbuf[MAX_ATOM_LEN + 1];
     UINT len;
-  
+
     if ((INT)cchType <= 0) return 0;
     if (!RealGetWindowClassW( hwnd, tmpbuf, sizeof(tmpbuf)/sizeof(WCHAR) )) return 0;
     RtlUnicodeToMultiByteN( pszType, cchType - 1, (PULONG)&len, tmpbuf, strlenW(tmpbuf) * sizeof(WCHAR) );
@@ -1271,147 +1248,147 @@ RealGetWindowClassA(
 static HICON
 CreateSmallIcon(HICON StdIcon)
 {
-   HICON SmallIcon = NULL;
-   ICONINFO StdInfo;
-   int SmallIconWidth;
-   int SmallIconHeight;
-   BITMAP StdBitmapInfo;
-   HDC hSourceDc = NULL;
-   HDC hDestDc = NULL;
-   ICONINFO SmallInfo;
-   HBITMAP OldSourceBitmap = NULL;
-   HBITMAP OldDestBitmap = NULL;
-
-   SmallInfo.hbmColor = NULL;
-   SmallInfo.hbmMask = NULL;
-
-   /* We need something to work with... */
-   if (NULL == StdIcon)
-   {
-      goto cleanup;
-   }
-
-   SmallIconWidth = GetSystemMetrics(SM_CXSMICON);
-   SmallIconHeight = GetSystemMetrics(SM_CYSMICON);
-   if (! GetIconInfo(StdIcon, &StdInfo))
-   {
-      ERR("Failed to get icon info for icon 0x%x\n", StdIcon);
-      goto cleanup;
-   }
+    HICON SmallIcon = NULL;
+    ICONINFO StdInfo;
+    int SmallIconWidth;
+    int SmallIconHeight;
+    BITMAP StdBitmapInfo;
+    HDC hSourceDc = NULL;
+    HDC hDestDc = NULL;
+    ICONINFO SmallInfo;
+    HBITMAP OldSourceBitmap = NULL;
+    HBITMAP OldDestBitmap = NULL;
+
+    SmallInfo.hbmColor = NULL;
+    SmallInfo.hbmMask = NULL;
+
+    /* We need something to work with... */
+    if (NULL == StdIcon)
+    {
+        goto cleanup;
+    }
+
+    SmallIconWidth = GetSystemMetrics(SM_CXSMICON);
+    SmallIconHeight = GetSystemMetrics(SM_CYSMICON);
+    if (! GetIconInfo(StdIcon, &StdInfo))
+    {
+        ERR("Failed to get icon info for icon 0x%x\n", StdIcon);
+        goto cleanup;
+    }
    if (! GetObjectW(StdInfo.hbmMask, sizeof(BITMAP), &StdBitmapInfo))
-   {
-      ERR("Failed to get bitmap info for icon 0x%x bitmap 0x%x\n",
-              StdIcon, StdInfo.hbmColor);
-      goto cleanup;
-   }
-   if (StdBitmapInfo.bmWidth == SmallIconWidth &&
-       StdBitmapInfo.bmHeight == SmallIconHeight)
-   {
-      /* Icon already has the correct dimensions */
-      return StdIcon;
-   }
-
-   hSourceDc = CreateCompatibleDC(NULL);
-   if (NULL == hSourceDc)
-   {
-      ERR("Failed to create source DC\n");
-      goto cleanup;
-   }
-   hDestDc = CreateCompatibleDC(NULL);
-   if (NULL == hDestDc)
-   {
-      ERR("Failed to create dest DC\n");
-      goto cleanup;
-   }
-
-   OldSourceBitmap = SelectObject(hSourceDc, StdInfo.hbmColor);
-   if (NULL == OldSourceBitmap)
-   {
-      ERR("Failed to select source color bitmap\n");
-      goto cleanup;
-   }
-   SmallInfo.hbmColor = CreateCompatibleBitmap(hSourceDc, SmallIconWidth,
-                                              SmallIconHeight);
-   if (NULL == SmallInfo.hbmColor)
-   {
-      ERR("Failed to create color bitmap\n");
-      goto cleanup;
-   }
-   OldDestBitmap = SelectObject(hDestDc, SmallInfo.hbmColor);
-   if (NULL == OldDestBitmap)
-   {
-      ERR("Failed to select dest color bitmap\n");
-      goto cleanup;
-   }
-   if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
-                    hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
-                    StdBitmapInfo.bmHeight, SRCCOPY))
-   {
-     ERR("Failed to stretch color bitmap\n");
-     goto cleanup;
-   }
-
-   if (NULL == SelectObject(hSourceDc, StdInfo.hbmMask))
-   {
-      ERR("Failed to select source mask bitmap\n");
-      goto cleanup;
-   }
-   SmallInfo.hbmMask = CreateCompatibleBitmap(hSourceDc, SmallIconWidth, SmallIconHeight);
-   if (NULL == SmallInfo.hbmMask)
-   {
-      ERR("Failed to create mask bitmap\n");
-      goto cleanup;
-   }
-   if (NULL == SelectObject(hDestDc, SmallInfo.hbmMask))
-   {
-      ERR("Failed to select dest mask bitmap\n");
-      goto cleanup;
-   }
-   if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
-                    hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
-                    StdBitmapInfo.bmHeight, SRCCOPY))
-   {
-      ERR("Failed to stretch mask bitmap\n");
-      goto cleanup;
-   }
-
-   SmallInfo.fIcon = TRUE;
-   SmallInfo.xHotspot = SmallIconWidth / 2;
-   SmallInfo.yHotspot = SmallIconHeight / 2;
-   SmallIcon = CreateIconIndirect(&SmallInfo);
-   if (NULL == SmallIcon)
-   {
-      ERR("Failed to create icon\n");
-      goto cleanup;
-   }
+    {
+        ERR("Failed to get bitmap info for icon 0x%x bitmap 0x%x\n",
+                StdIcon, StdInfo.hbmColor);
+        goto cleanup;
+    }
+    if (StdBitmapInfo.bmWidth == SmallIconWidth &&
+        StdBitmapInfo.bmHeight == SmallIconHeight)
+    {
+        /* Icon already has the correct dimensions */
+        return StdIcon;
+    }
+
+    hSourceDc = CreateCompatibleDC(NULL);
+    if (NULL == hSourceDc)
+    {
+        ERR("Failed to create source DC\n");
+        goto cleanup;
+    }
+    hDestDc = CreateCompatibleDC(NULL);
+    if (NULL == hDestDc)
+    {
+        ERR("Failed to create dest DC\n");
+        goto cleanup;
+    }
+
+    OldSourceBitmap = SelectObject(hSourceDc, StdInfo.hbmColor);
+    if (NULL == OldSourceBitmap)
+    {
+        ERR("Failed to select source color bitmap\n");
+        goto cleanup;
+    }
+    SmallInfo.hbmColor = CreateCompatibleBitmap(hSourceDc, SmallIconWidth,
+                                                SmallIconHeight);
+    if (NULL == SmallInfo.hbmColor)
+    {
+        ERR("Failed to create color bitmap\n");
+        goto cleanup;
+    }
+    OldDestBitmap = SelectObject(hDestDc, SmallInfo.hbmColor);
+    if (NULL == OldDestBitmap)
+    {
+        ERR("Failed to select dest color bitmap\n");
+        goto cleanup;
+    }
+    if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
+                     hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
+                     StdBitmapInfo.bmHeight, SRCCOPY))
+    {
+        ERR("Failed to stretch color bitmap\n");
+        goto cleanup;
+    }
+
+    if (NULL == SelectObject(hSourceDc, StdInfo.hbmMask))
+    {
+        ERR("Failed to select source mask bitmap\n");
+        goto cleanup;
+    }
+    SmallInfo.hbmMask = CreateCompatibleBitmap(hSourceDc, SmallIconWidth, SmallIconHeight);
+    if (NULL == SmallInfo.hbmMask)
+    {
+        ERR("Failed to create mask bitmap\n");
+        goto cleanup;
+    }
+    if (NULL == SelectObject(hDestDc, SmallInfo.hbmMask))
+    {
+        ERR("Failed to select dest mask bitmap\n");
+        goto cleanup;
+    }
+    if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
+                     hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
+                     StdBitmapInfo.bmHeight, SRCCOPY))
+    {
+        ERR("Failed to stretch mask bitmap\n");
+        goto cleanup;
+    }
+
+    SmallInfo.fIcon = TRUE;
+    SmallInfo.xHotspot = SmallIconWidth / 2;
+    SmallInfo.yHotspot = SmallIconHeight / 2;
+    SmallIcon = CreateIconIndirect(&SmallInfo);
+    if (NULL == SmallIcon)
+    {
+        ERR("Failed to create icon\n");
+        goto cleanup;
+    }
 
 cleanup:
-   if (NULL != SmallInfo.hbmMask)
-   {
-      DeleteObject(SmallInfo.hbmMask);
-   }
-   if (NULL != OldDestBitmap)
-   {
-      SelectObject(hDestDc, OldDestBitmap);
-   }
-   if (NULL != SmallInfo.hbmColor)
-   {
-      DeleteObject(SmallInfo.hbmColor);
-   }
-   if (NULL != hDestDc)
-   {
-      DeleteDC(hDestDc);
-   }
-   if (NULL != OldSourceBitmap)
-   {
-      SelectObject(hSourceDc, OldSourceBitmap);
-   }
-   if (NULL != hSourceDc)
-   {
-      DeleteDC(hSourceDc);
-   }
-
-   return SmallIcon;
+    if (NULL != SmallInfo.hbmMask)
+    {
+        DeleteObject(SmallInfo.hbmMask);
+    }
+    if (NULL != OldDestBitmap)
+    {
+        SelectObject(hDestDc, OldDestBitmap);
+    }
+    if (NULL != SmallInfo.hbmColor)
+    {
+        DeleteObject(SmallInfo.hbmColor);
+    }
+    if (NULL != hDestDc)
+    {
+        DeleteDC(hDestDc);
+    }
+    if (NULL != OldSourceBitmap)
+    {
+        SelectObject(hSourceDc, OldSourceBitmap);
+    }
+    if (NULL != hSourceDc)
+    {
+        DeleteDC(hSourceDc);
+    }
+
+    return SmallIcon;
 }
 #endif
 
@@ -1422,124 +1399,111 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
                     DWORD dwFlags,
                     BOOL ChkRegCls)
 {
-   ATOM Atom;
-   WNDCLASSEXW WndClass;
-   UNICODE_STRING ClassName;
-   UNICODE_STRING MenuName = {0};
-   CLSMENUNAME clsMenuName;
-   ANSI_STRING AnsiMenuName;
-   HMODULE hLibModule = NULL;
-   DWORD save_error;
-   BOOL ClassFound = FALSE;
-
-   if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
-       lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
-       lpwcx->lpszClassName == NULL)
-   {
-      TRACE("RegisterClassExWOWW Invalid Parameter Error!\n");
-      SetLastError(ERROR_INVALID_PARAMETER);
-      return 0;
-   }
-
-   if (ChkRegCls)
-   {
-      if (!RegisterDefaultClasses) RegisterSystemControls();
-   }
-   /*
-    * On real Windows this looks more like:
-    *    if (lpwcx->hInstance == User32Instance &&
-    *        *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
-    * But since I have no idea what the magic field in the
-    * TEB structure means, I rather decided to omit that.
-    * -- Filip Navara
-
-       GetWin32ClientInfo()->dwExpWinVer & (WINVER == 0x400)
-    */
-   if (lpwcx->hInstance == User32Instance)
-   {
-      TRACE("RegisterClassExWOWW User32Instance!\n");
-      SetLastError(ERROR_INVALID_PARAMETER);
-      return 0;
-   }
-   /* Yes, this is correct. We should modify the passed structure. */
-   if (lpwcx->hInstance == NULL)
-      ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);
-
-   RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
+    ATOM Atom;
+    WNDCLASSEXW WndClass;
+    UNICODE_STRING ClassName;
+    UNICODE_STRING ClassVersion;
+    UNICODE_STRING MenuName = {0};
+    CLSMENUNAME clsMenuName;
+    ANSI_STRING AnsiMenuName;
+    LPCWSTR lpszClsVersion;
+
+    if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
+        lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
+        lpwcx->lpszClassName == NULL)
+    {
+        TRACE("RegisterClassExWOWW Invalid Parameter Error!\n");
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+
+    if (ChkRegCls)
+    {
+        if (!RegisterDefaultClasses) RegisterSystemControls();
+    }
+    /*
+     * On real Windows this looks more like:
+     *    if (lpwcx->hInstance == User32Instance &&
+     *        *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
+     * But since I have no idea what the magic field in the
+     * TEB structure means, I rather decided to omit that.
+     * -- Filip Navara
+
+        GetWin32ClientInfo()->dwExpWinVer & (WINVER == 0x400)
+     */
+    if (lpwcx->hInstance == User32Instance)
+    {
+        TRACE("RegisterClassExWOWW User32Instance!\n");
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+    /* Yes, this is correct. We should modify the passed structure. */
+    if (lpwcx->hInstance == NULL)
+       ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);
+
+    RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
 /*
-   if (NULL == WndClass.hIconSm)
-   {
-      WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
-   }
+    if (NULL == WndClass.hIconSm)
+    {
+        WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
+    }
 */
-   if (WndClass.lpszMenuName != NULL)
-   {
-      if (!IS_INTRESOURCE(WndClass.lpszMenuName))
-      {
-         if (WndClass.lpszMenuName[0])
-         {
-            RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName);
-            RtlUnicodeStringToAnsiString( &AnsiMenuName, &MenuName, TRUE);
-         }
-      }
-      else
-      {
-         MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
-         AnsiMenuName.Buffer = (PCHAR)WndClass.lpszMenuName;
-      }
-   }
-
-   if (IS_ATOM(WndClass.lpszClassName))
-   {
-      ClassName.Length =
-      ClassName.MaximumLength = 0;
-      ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
-   }
-   else
-   {
-      RtlInitUnicodeString(&ClassName, WndClass.lpszClassName);
-   }
-
-   clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer;
-   clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer;
-   clsMenuName.pusMenuName = &MenuName;
-
-   for(;;)
-   {
-       Atom = NtUserRegisterClassExWOW( &WndClass,
-                                        &ClassName,
-                                         NULL, //PUNICODE_STRING ClsNVersion,
-                                        &clsMenuName,
-                                         fnID,
-                                         dwFlags,
-                                         pdwWowData);
-
-       if (Atom) break;
-       if (!ClassFound)
-       {
-          save_error = GetLastError();
-          if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
-               save_error == ERROR_CLASS_DOES_NOT_EXIST )
-          {
-              ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule);
-              if (ClassFound) continue;
-          }
-       }
-       if (hLibModule)
-       {
-          save_error = GetLastError();
-          FreeLibrary(hLibModule);
-          SetLastError(save_error);
-          hLibModule = 0;
-       }
-       break;
-   }
-
-   TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
-          Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
-          lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass);
+    RtlInitEmptyAnsiString(&AnsiMenuName, NULL, 0);
+    if (WndClass.lpszMenuName != NULL)
+    {
+        if (!IS_INTRESOURCE(WndClass.lpszMenuName))
+        {
+            if (WndClass.lpszMenuName[0])
+            {
+               RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName);
+               RtlUnicodeStringToAnsiString( &AnsiMenuName, &MenuName, TRUE);
+            }
+        }
+        else
+        {
+            MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
+             AnsiMenuName.Buffer = (PCHAR)WndClass.lpszMenuName;
+        }
+    }
+
+    if (IS_ATOM(WndClass.lpszClassName))
+    {
+        ClassName.Length =
+        ClassName.MaximumLength = 0;
+        ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
+    }
+    else
+    {
+        RtlInitUnicodeString(&ClassName, WndClass.lpszClassName);
+    }
 
-   return Atom;
+    ClassVersion = ClassName;
+    if (fnID == 0)
+    {
+        lpszClsVersion = ClassNameToVersion(lpwcx->lpszClassName, NULL, NULL, NULL, FALSE);
+        if (lpszClsVersion)
+        {
+            RtlInitUnicodeString(&ClassVersion, lpszClsVersion);
+        }
+    }
+
+    clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer;
+    clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer;
+    clsMenuName.pusMenuName = &MenuName;
+
+    Atom = NtUserRegisterClassExWOW( &WndClass,
+                                     &ClassName,
+                                     &ClassVersion,
+                                     &clsMenuName,
+                                     fnID,
+                                     dwFlags,
+                                     pdwWowData);
+
+    TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
+           Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
+           lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass);
+
+    return Atom;
 }
 
 /*
@@ -1548,44 +1512,44 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
 ATOM WINAPI
 RegisterClassExA(CONST WNDCLASSEXA *lpwcx)
 {
-   RTL_ATOM Atom;
-   WNDCLASSEXW WndClass;
-   WCHAR mname[MAX_BUFFER_LEN];
-   WCHAR cname[MAX_BUFFER_LEN];
-
-   RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXA));
-
-   if (WndClass.lpszMenuName != NULL)
-   {
-      if (!IS_INTRESOURCE(WndClass.lpszMenuName))
-      {
-         if (WndClass.lpszMenuName[0])
-         {
-            if (!MultiByteToWideChar( CP_ACP, 0, lpwcx->lpszMenuName, -1, mname, MAX_ATOM_LEN + 1 )) return 0;
-
-            WndClass.lpszMenuName = mname;
-         }
-      }
-   }
-
-   if (!IS_ATOM(WndClass.lpszClassName))
-   {
-      if (!MultiByteToWideChar( CP_ACP, 0, lpwcx->lpszClassName, -1, cname, MAX_ATOM_LEN + 1 )) return 0;
-
-      WndClass.lpszClassName = cname;
-   }
-
-   Atom = RegisterClassExWOWW( &WndClass,
+    RTL_ATOM Atom;
+    WNDCLASSEXW WndClass;
+    WCHAR mname[MAX_BUFFER_LEN];
+    WCHAR cname[MAX_BUFFER_LEN];
+
+    RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXA));
+
+    if (WndClass.lpszMenuName != NULL)
+    {
+        if (!IS_INTRESOURCE(WndClass.lpszMenuName))
+        {
+            if (WndClass.lpszMenuName[0])
+            {
+                if (!MultiByteToWideChar( CP_ACP, 0, lpwcx->lpszMenuName, -1, mname, MAX_ATOM_LEN + 1 )) return 0;
+
+                WndClass.lpszMenuName = mname;
+            }
+        }
+    }
+
+    if (!IS_ATOM(WndClass.lpszClassName))
+    {
+        if (!MultiByteToWideChar( CP_ACP, 0, lpwcx->lpszClassName, -1, cname, MAX_ATOM_LEN + 1 )) return 0;
+
+        WndClass.lpszClassName = cname;
+    }
+
+    Atom = RegisterClassExWOWW( &WndClass,
                                 0,
                                 0,
                                 CSF_ANSIPROC,
                                 TRUE);
 
-   TRACE("A atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
-          Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
-          lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass);
+    TRACE("A atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
+           Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
+           lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass);
 
-   return (ATOM)Atom;
+    return (ATOM)Atom;
 }
 
 /*
@@ -1594,15 +1558,15 @@ RegisterClassExA(CONST WNDCLASSEXA *lpwcx)
 ATOM WINAPI
 RegisterClassExW(CONST WNDCLASSEXW *lpwcx)
 {
-   ATOM Atom;
+    ATOM Atom;
 
-   Atom = RegisterClassExWOWW( (WNDCLASSEXW *)lpwcx, 0, 0, 0, TRUE);
+    Atom = RegisterClassExWOWW( (WNDCLASSEXW *)lpwcx, 0, 0, 0, TRUE);
 
-   TRACE("W atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d\n",
+    TRACE("W atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d\n",
           Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
           lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra);
 
-   return Atom;
+    return Atom;
 }
 
 /*
@@ -1611,16 +1575,16 @@ RegisterClassExW(CONST WNDCLASSEXW *lpwcx)
 ATOM WINAPI
 RegisterClassA(CONST WNDCLASSA *lpWndClass)
 {
-   WNDCLASSEXA Class;
+    WNDCLASSEXA Class;
 
-   if (lpWndClass == NULL)
-      return 0;
+    if (lpWndClass == NULL)
+        return 0;
 
-   RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSA));
-   Class.cbSize = sizeof(WNDCLASSEXA);
-   Class.hIconSm = NULL;
+    RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSA));
+    Class.cbSize = sizeof(WNDCLASSEXA);
+    Class.hIconSm = NULL;
 
-   return RegisterClassExA(&Class);
+    return RegisterClassExA(&Class);
 }
 
 /*
@@ -1629,16 +1593,16 @@ RegisterClassA(CONST WNDCLASSA *lpWndClass)
 ATOM WINAPI
 RegisterClassW(CONST WNDCLASSW *lpWndClass)
 {
-   WNDCLASSEXW Class;
+    WNDCLASSEXW Class;
 
-   if (lpWndClass == NULL)
-      return 0;
+    if (lpWndClass == NULL)
+        return 0;
 
-   RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSW));
-   Class.cbSize = sizeof(WNDCLASSEXW);
-   Class.hIconSm = NULL;
+    RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSW));
+    Class.cbSize = sizeof(WNDCLASSEXW);
+    Class.hIconSm = NULL;
 
-   return RegisterClassExW(&Class);
+    return RegisterClassExW(&Class);
 }
 
 /*
@@ -1832,12 +1796,13 @@ SetWindowWord ( HWND hWnd,int nIndex,WORD wNewWord )
  */
 LONG
 WINAPI
+DECLSPEC_HOTPATCH
 SetWindowLongA(
   HWND hWnd,
   int nIndex,
   LONG dwNewLong)
 {
-  return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, TRUE);
+    return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, TRUE);
 }
 
 /*
@@ -1850,7 +1815,7 @@ SetWindowLongW(
   int nIndex,
   LONG dwNewLong)
 {
-  return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
+    return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
 }
 
 #ifdef _WIN64
@@ -1863,7 +1828,7 @@ SetWindowLongPtrA(HWND hWnd,
                   INT nIndex,
                   LONG_PTR dwNewLong)
 {
-  return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
+    return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
 }
 
 /*
@@ -1875,7 +1840,7 @@ SetWindowLongPtrW(HWND hWnd,
                   INT nIndex,
                   LONG_PTR dwNewLong)
 {
-  return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
+    return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
 }
 #endif
 
@@ -1890,16 +1855,23 @@ UnregisterClassA(
 {
     UNICODE_STRING ClassName = {0};
     BOOL Ret;
+    LPCWSTR lpszClsVersion;
+    BOOL ConvertedString = FALSE;
 
     TRACE("class/atom: %s/%04x %p\n",
         IS_ATOM(lpClassName) ? NULL : lpClassName,
         IS_ATOM(lpClassName) ? lpClassName : 0,
         hInstance);
 
-    if (!IS_ATOM(lpClassName))
+    lpszClsVersion = ClassNameToVersion(lpClassName, NULL, NULL, NULL, TRUE);
+    if (lpszClsVersion)
     {
-        if (!RtlCreateUnicodeStringFromAsciiz(&ClassName,
-                                              lpClassName))
+        RtlInitUnicodeString(&ClassName, lpszClsVersion);
+    }
+    else if (!IS_ATOM(lpClassName))
+    {
+        ConvertedString = TRUE;
+        if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, lpClassName))
         {
             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
             return 0;
@@ -1908,11 +1880,9 @@ UnregisterClassA(
     else
         ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
 
-    Ret = NtUserUnregisterClass(&ClassName,
-                                 hInstance,
-                                 0);
+    Ret = NtUserUnregisterClass(&ClassName, hInstance, 0);
 
-    if (!IS_ATOM(lpClassName))
+    if (ConvertedString)
         RtlFreeUnicodeString(&ClassName);
 
     return Ret;
@@ -1929,23 +1899,28 @@ UnregisterClassW(
   HINSTANCE hInstance)
 {
     UNICODE_STRING ClassName = {0};
+    LPCWSTR lpszClsVersion;
 
     TRACE("class/atom: %S/%04x %p\n",
         IS_ATOM(lpClassName) ? NULL : lpClassName,
         IS_ATOM(lpClassName) ? lpClassName : 0,
         hInstance);
 
-    if (!IS_ATOM(lpClassName))
+    lpszClsVersion = ClassNameToVersion(lpClassName, NULL, NULL, NULL, FALSE);
+    if (lpszClsVersion)
+    {
+        RtlInitUnicodeString(&ClassName, lpszClsVersion);
+    }
+    else if (!IS_ATOM(lpClassName))
     {
-        RtlInitUnicodeString(&ClassName,
-                             lpClassName);
+        RtlInitUnicodeString(&ClassName, lpClassName);
     }
     else
+    {    
         ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
+    }
 
-    return NtUserUnregisterClass(&ClassName,
-                                 hInstance,
-                                 0);
+    return NtUserUnregisterClass(&ClassName, hInstance, 0);
 }
 
 /* EOF */