From: Giannis Adamopoulos Date: Fri, 17 Feb 2017 11:07:14 +0000 (+0000) Subject: [WIN32k] X-Git-Tag: ReactOS-0.4.4-CLT2017~284 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=c607de714cefce7ce0acc2cdf15837f3bcf3d6dd;hp=ebf8247723f6a2e4d76a2e3ade72c71e30023200 [WIN32k] -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 --- diff --git a/reactos/win32ss/user/ntuser/class.c b/reactos/win32ss/user/ntuser/class.c index c8139b8a35e..d3fc8bb020a 100644 --- a/reactos/win32ss/user/ntuser/class.c +++ b/reactos/win32ss/user/ntuser/class.c @@ -2743,6 +2743,7 @@ NtUserGetClassInfo( NULL); if (ClassAtom != (RTL_ATOM)0) { + ClassAtom = Class->atomNVClassName; Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance); } else diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 6129840310e..7b7fb72ec7f 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -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) { diff --git a/reactos/win32ss/user/user32/windows/class.c b/reactos/win32ss/user/user32/windows/class.c index 552e8a93488..15b4e9fa738 100644 --- a/reactos/win32ss/user/user32/windows/class.c +++ b/reactos/win32ss/user/user32/windows/class.c @@ -13,49 +13,114 @@ #include 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 */ diff --git a/reactos/win32ss/user/user32/windows/window.c b/reactos/win32ss/user/user32/windows/window.c index 81c5dbaac2e..9edebd5a0eb 100644 --- a/reactos/win32ss/user/user32/windows/window.c +++ b/reactos/win32ss/user/user32/windows/window.c @@ -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; } }