[WIN32k]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Fri, 17 Feb 2017 11:07:14 +0000 (11:07 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Fri, 17 Feb 2017 11:07:14 +0000 (11:07 +0000)
 -Fix a couple of cases where we use the versioned class atom instead of the non versioned one.

[USER32]
- Add support for versioned classes in RegisterClassExWOWW, GetClassInfoExW, GetClassInfoExA, UnregisterClassA, UnregisterClassW, and User32CreateWindowEx
- Make ClassNameToVersion return the name of the versioned class and the library name that implements it while preserving a hack that lets user32 know which classes are registered by comctl32 (this is needed because the default activation context doesn't contain the non versioned classes yet).
- Make VersionRegisterClass to load the specified library and make it register its classes which is used when the class is not registered yet but its manifest is active.

svn path=/trunk/; revision=73806

reactos/win32ss/user/ntuser/class.c
reactos/win32ss/user/ntuser/window.c
reactos/win32ss/user/user32/windows/class.c
reactos/win32ss/user/user32/windows/window.c

index c8139b8..d3fc8bb 100644 (file)
@@ -2743,6 +2743,7 @@ NtUserGetClassInfo(
                                 NULL);
     if (ClassAtom != (RTL_ATOM)0)
     {
+        ClassAtom = Class->atomNVClassName;
         Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance);
     }
     else
index 6129840..7b7fb72 100644 (file)
@@ -2807,7 +2807,7 @@ IntFindWindow(PWND Parent,
          /* Do not send WM_GETTEXT messages in the kernel mode version!
             The user mode version however calls GetWindowText() which will
             send WM_GETTEXT messages to windows belonging to its processes */
-         if (!ClassAtom || Child->pcls->atomClassName == ClassAtom)
+         if (!ClassAtom || Child->pcls->atomNVClassName == ClassAtom)
          {
              // FIXME: LARGE_STRING truncated
              CurrentWindowName.Buffer = Child->strName.Buffer;
@@ -2999,7 +2999,7 @@ NtUserFindWindowEx(HWND hwndParent,
                                 (TopLevelWindow->strName.Length < 0xFFFF &&
                                  !RtlCompareUnicodeString(&WindowName, &ustr, TRUE));
                 ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
-                               ClassAtom == TopLevelWindow->pcls->atomClassName;
+                               ClassAtom == TopLevelWindow->pcls->atomNVClassName;
 
                 if (WindowMatches && ClassMatches)
                 {
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 */
index 81c5dba..9edebd5 100644 (file)
@@ -16,6 +16,7 @@
 WINE_DEFAULT_DEBUG_CHANNEL(user32);
 
 void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id );
+extern LPCWSTR FASTCALL ClassNameToVersion(const void *lpszClass, LPCWSTR lpszMenuName, LPCWSTR *plpLibFileName, HANDLE *pContext, BOOL bAnsi);
 
 /* FUNCTIONS *****************************************************************/
 
@@ -165,13 +166,18 @@ User32CreateWindowEx(DWORD dwExStyle,
 {
     LARGE_STRING WindowName;
     LARGE_STRING lstrClassName, *plstrClassName;
+    LARGE_STRING lstrClassVersion, *plstrClassVersion;
     UNICODE_STRING ClassName;
+    UNICODE_STRING ClassVersion;
     WNDCLASSEXA wceA;
     WNDCLASSEXW wceW;
     HMODULE hLibModule = NULL;
     DWORD save_error;
     BOOL Unicode, ClassFound = FALSE;
     HWND Handle = NULL;
+    LPCWSTR lpszClsVersion;
+    HANDLE pCtx;
+    LPCWSTR lpLibFileName;
 
 #if 0
     DbgPrint("[window] User32CreateWindowEx style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent);
@@ -263,11 +269,25 @@ User32CreateWindowEx(DWORD dwExStyle,
 
     if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR;
 
+    lpszClsVersion = ClassNameToVersion(lpClassName, NULL, &lpLibFileName, &pCtx, !Unicode);
+    if (!lpszClsVersion)
+    {
+        plstrClassVersion = plstrClassName;
+    }
+    else
+    {
+        RtlInitUnicodeString(&ClassVersion, lpszClsVersion);
+        lstrClassVersion.Buffer = ClassVersion.Buffer;
+        lstrClassVersion.Length = ClassVersion.Length;
+        lstrClassVersion.MaximumLength = ClassVersion.MaximumLength;
+        plstrClassVersion = &lstrClassVersion;
+    }
+
     for(;;)
     {
        Handle = NtUserCreateWindowEx(dwExStyle,
                                      plstrClassName,
-                                     plstrClassName,
+                                     plstrClassVersion,
                                      &WindowName,
                                      dwStyle,
                                      x,
@@ -281,12 +301,13 @@ User32CreateWindowEx(DWORD dwExStyle,
                                      dwFlags,
                                      NULL);
        if (Handle) break;
+       if (!lpLibFileName) break;
        if (!ClassFound)
        {
           save_error = GetLastError();
           if ( save_error == ERROR_CANNOT_FIND_WND_CLASS )
           {
-              ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule);
+              ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule);
               if (ClassFound) continue;
           }
        }