[WIN32k]
[reactos.git] / reactos / win32ss / user / user32 / windows / class.c
index 552e8a9..15b4e9f 100644 (file)
 #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 */
 };
 
+//
+// Use wine hack to process extended context classes.
+//
+/***********************************************************************
+ *           is_comctl32_class
+ */
+LPCWSTR is_comctl32_class( const WCHAR *name )
+{
+    static const WCHAR classesW[][20] =
+    {
+        {'C','o','m','b','o','B','o','x','E','x','3','2',0},
+        {'m','s','c','t','l','s','_','h','o','t','k','e','y','3','2',0},
+        {'m','s','c','t','l','s','_','p','r','o','g','r','e','s','s','3','2',0},
+        {'m','s','c','t','l','s','_','s','t','a','t','u','s','b','a','r','3','2',0},
+        {'m','s','c','t','l','s','_','t','r','a','c','k','b','a','r','3','2',0},
+        {'m','s','c','t','l','s','_','u','p','d','o','w','n','3','2',0},
+        {'N','a','t','i','v','e','F','o','n','t','C','t','l',0},
+        {'R','e','B','a','r','W','i','n','d','o','w','3','2',0},
+        {'S','y','s','A','n','i','m','a','t','e','3','2',0},
+        {'S','y','s','D','a','t','e','T','i','m','e','P','i','c','k','3','2',0},
+        {'S','y','s','H','e','a','d','e','r','3','2',0},
+        {'S','y','s','I','P','A','d','d','r','e','s','s','3','2',0},
+        {'S','y','s','L','i','s','t','V','i','e','w','3','2',0},
+        {'S','y','s','M','o','n','t','h','C','a','l','3','2',0},
+        {'S','y','s','P','a','g','e','r',0},
+        {'S','y','s','T','a','b','C','o','n','t','r','o','l','3','2',0},
+        {'S','y','s','T','r','e','e','V','i','e','w','3','2',0},
+        {'T','o','o','l','b','a','r','W','i','n','d','o','w','3','2',0},
+        {'t','o','o','l','t','i','p','s','_','c','l','a','s','s','3','2',0},
+    };
+
+    int min = 0, max = (sizeof(classesW) / sizeof(classesW[0])) - 1;
+
+    while (min <= max)
+    {
+        int res, pos = (min + max) / 2;
+        if (!(res = strcmpiW( name, classesW[pos] ))) return classesW[pos];
+        if (res < 0) max = pos - 1;
+        else min = pos + 1;
+    }
+    return NULL;
+}
+
 LPCWSTR
 FASTCALL
 ClassNameToVersion(
-  LPCTSTR lpszClass,
+  const void* lpszClass,
   LPCWSTR lpszMenuName,
   LPCWSTR *plpLibFileName,
   HANDLE *pContext,
   BOOL bAnsi)
 {
+    LPCWSTR VersionedClass = NULL;
     NTSTATUS Status;
     UNICODE_STRING SectionName;
-    WCHAR SeactionNameBuf[MAX_PATH] = {0};
+    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))
     {
-        SectionName.Buffer = (LPWSTR)&SeactionNameBuf;
-        SectionName.MaximumLength = sizeof(SeactionNameBuf);
+        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)
         {
-            RtlCreateUnicodeStringFromAsciiz(&SectionName, (LPSTR)lpszClass);
+            ANSI_STRING AnsiString;
+            RtlInitAnsiString(&AnsiString, lpszClass);
+            RtlInitEmptyUnicodeString(&SectionName, SectionNameBuf, sizeof(SectionNameBuf));
+            RtlAnsiStringToUnicodeString(&SectionName, &AnsiString, FALSE);
         }
         else
         {
@@ -68,49 +133,57 @@ ClassNameToVersion(
                                                    &SectionName,
                                                    &KeyedData );
 
+#ifdef USE_VERSIONED_CLASSES
     if (NT_SUCCESS(Status) && KeyedData.ulDataFormatVersion == 1)
     {
-        struct dll_redirect *dll = KeyedData.lpSectionBase;
-
-        if (plpLibFileName) *plpLibFileName = dll->name;
+        struct strsection_header *SectionHeader = KeyedData.lpSectionBase;
 
-        if (lpszMenuName)
+        /* Find activation context */
+        if(SectionHeader && SectionHeader->count > 0)
         {
-            WCHAR * mnubuf;
-            LPWSTR mnuNameW;
-            LPSTR mnuNameA;
-            int len = 0;
-            struct entity *entity = KeyedData.lpData;
+            struct wndclass_redirect_data *WindowRedirectionData = KeyedData.lpData;
+            if(WindowRedirectionData && WindowRedirectionData->module_len)
+            {
+                LPCWSTR lpLibFileName;
 
-            FIXME("actctx: Needs to support menu name from redirected class!");
+                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 (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);
+#endif
 
-    return lpszClass;
+#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;
 }
 
 //
@@ -118,14 +191,14 @@ ClassNameToVersion(
 //
 BOOL
 FASTCALL
-Real_VersionRegisterClass(
+VersionRegisterClass(
   PCWSTR pszClass,
   LPCWSTR lpLibFileName,
   HANDLE Contex,
   HMODULE * phLibModule)
 {
-    BOOL Ret;
-    HMODULE hLibModule;
+    BOOL Ret = FALSE;
+    HMODULE hLibModule = NULL;
     PREGISTERCLASSNAMEW pRegisterClassNameW;
     UNICODE_STRING ClassName;
     WCHAR ClassNameBuf[MAX_PATH] = {0};
@@ -133,9 +206,6 @@ Real_VersionRegisterClass(
 
     RtlActivateActivationContextUnsafeFast(&Frame, Contex);
 
-    Ret = FALSE;
-    hLibModule = NULL;
-
     _SEH2_TRY
     {
         hLibModule = LoadLibraryW(lpLibFileName);
@@ -145,16 +215,21 @@ Real_VersionRegisterClass(
             {
                 if (IS_ATOM(pszClass))
                 {
-                    ClassName.Buffer = (LPWSTR)&ClassNameBuf;
+                    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 = (PCWSTR)&ClassNameBuf;
+                    pszClass = ClassName.Buffer;
                 }
                 Ret = pRegisterClassNameW(pszClass);
             }
+            else
+            {
+                WARN("No RegisterClassNameW PROC\n");
+            }
         }
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -174,119 +249,10 @@ Error_Exit:
         SetLastError(save_error);
     }
 
+    RtlDeactivateActivationContextUnsafeFast(&Frame);
     return Ret;
 }
 
-//
-// Use wine hack to process extened context classes.
-//
-/***********************************************************************
- *           is_comctl32_class
- */
-static BOOL is_comctl32_class( const WCHAR *name )
-{
-    static const WCHAR classesW[][20] =
-    {
-        {'C','o','m','b','o','B','o','x','E','x','3','2',0},
-        {'m','s','c','t','l','s','_','h','o','t','k','e','y','3','2',0},
-        {'m','s','c','t','l','s','_','p','r','o','g','r','e','s','s','3','2',0},
-        {'m','s','c','t','l','s','_','s','t','a','t','u','s','b','a','r','3','2',0},
-        {'m','s','c','t','l','s','_','t','r','a','c','k','b','a','r','3','2',0},
-        {'m','s','c','t','l','s','_','u','p','d','o','w','n','3','2',0},
-        {'N','a','t','i','v','e','F','o','n','t','C','t','l',0},
-        {'R','e','B','a','r','W','i','n','d','o','w','3','2',0},
-        {'S','y','s','A','n','i','m','a','t','e','3','2',0},
-        {'S','y','s','D','a','t','e','T','i','m','e','P','i','c','k','3','2',0},
-        {'S','y','s','H','e','a','d','e','r','3','2',0},
-        {'S','y','s','I','P','A','d','d','r','e','s','s','3','2',0},
-        {'S','y','s','L','i','s','t','V','i','e','w','3','2',0},
-        {'S','y','s','M','o','n','t','h','C','a','l','3','2',0},
-        {'S','y','s','P','a','g','e','r',0},
-        {'S','y','s','T','a','b','C','o','n','t','r','o','l','3','2',0},
-        {'S','y','s','T','r','e','e','V','i','e','w','3','2',0},
-        {'T','o','o','l','b','a','r','W','i','n','d','o','w','3','2',0},
-        {'t','o','o','l','t','i','p','s','_','c','l','a','s','s','3','2',0},
-    };
-
-    int min = 0, max = (sizeof(classesW) / sizeof(classesW[0])) - 1;
-
-    while (min <= max)
-    {
-        int res, pos = (min + max) / 2;
-        if (!(res = strcmpiW( name, classesW[pos] ))) return TRUE;
-        if (res < 0) max = pos - 1;
-        else min = pos + 1;
-    }
-    return FALSE;
-}
-
-BOOL
-FASTCALL
-VersionRegisterClass(
-  PCWSTR pszClass,
-  LPCWSTR lpLibFileName,
-  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_ATOM(pszClass) && is_comctl32_class( pszClass ))
-    {
-        _SEH2_TRY
-        {
-            hLibModule = LoadLibraryW(comctl32W);
-            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))
-                        {
-                            ERR("Error while verifying ATOM\n");
-                            _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);
-        }
-        TRACE( "%s retrying after loading comctl32\n", debugstr_w(pszClass) );
-        return Ret;
-    }
-    TRACE("NO ComCtl32 Class %S!\n",pszClass);
-    return FALSE;
-}
-//
-//
-//
-
 /*
  * @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,
@@ -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;
@@ -353,13 +327,14 @@ GetClassInfoExA(
                                  (LPWSTR *)&pszMenuName,
                                  TRUE);
         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, NULL, NULL, &hLibModule);
+                ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule);
                 if (ClassFound) continue;
             }
         }
@@ -379,7 +354,7 @@ GetClassInfoExA(
 //       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)
@@ -453,13 +435,14 @@ GetClassInfoExW(
                                  &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, NULL, NULL, &hLibModule);
+                ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule);
                 if (ClassFound) continue;
             }
         }
@@ -1419,12 +1402,11 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
     ATOM Atom;
     WNDCLASSEXW WndClass;
     UNICODE_STRING ClassName;
+    UNICODE_STRING ClassVersion;
     UNICODE_STRING MenuName = {0};
     CLSMENUNAME clsMenuName;
     ANSI_STRING AnsiMenuName;
-    HMODULE hLibModule = NULL;
-    DWORD save_error;
-    BOOL ClassFound = FALSE;
+    LPCWSTR lpszClsVersion;
 
     if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
         lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
@@ -1495,41 +1477,28 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
         RtlInitUnicodeString(&ClassName, WndClass.lpszClassName);
     }
 
-    clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer;
-    clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer;
-    clsMenuName.pusMenuName = &MenuName;
-
-    for(;;)
+    ClassVersion = ClassName;
+    if (fnID == 0)
     {
-        Atom = NtUserRegisterClassExWOW( &WndClass,
-                                         &ClassName,
-                                         &ClassName, //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)
+        lpszClsVersion = ClassNameToVersion(lpwcx->lpszClassName, NULL, NULL, NULL, FALSE);
+        if (lpszClsVersion)
         {
-            save_error = GetLastError();
-            FreeLibrary(hLibModule);
-            SetLastError(save_error);
-            hLibModule = 0;
+            RtlInitUnicodeString(&ClassVersion, lpszClsVersion);
         }
-        break;
     }
 
+    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);
@@ -1886,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;
@@ -1904,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;
@@ -1925,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,
-                             lpClassName);
+        RtlInitUnicodeString(&ClassName, lpszClsVersion);
+    }
+    else if (!IS_ATOM(lpClassName))
+    {
+        RtlInitUnicodeString(&ClassName, lpClassName);
     }
     else
+    {    
         ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
+    }
 
-    return NtUserUnregisterClass(&ClassName,
-                                 hInstance,
-                                 0);
+    return NtUserUnregisterClass(&ClassName, hInstance, 0);
 }
 
 /* EOF */