Author: gadamopoulos Date: Fri Feb 17 11:07:14 2017 New Revision: 73806 URL: http://svn.reactos.org/svn/reactos?rev=73806&view=rev Log: [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. Modified: trunk/reactos/win32ss/user/ntuser/class.c trunk/reactos/win32ss/user/ntuser/window.c trunk/reactos/win32ss/user/user32/windows/class.c trunk/reactos/win32ss/user/user32/windows/window.c Modified: trunk/reactos/win32ss/user/ntuser/class.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/class.c?rev=73806&r1=73805&r2=73806&view=diff ============================================================================== --- trunk/reactos/win32ss/user/ntuser/class.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/class.c [iso-8859-1] Fri Feb 17 11:07:14 2017 @@ -2743,6 +2743,7 @@ NULL); if (ClassAtom != (RTL_ATOM)0) { + ClassAtom = Class->atomNVClassName; Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance); } else Modified: trunk/reactos/win32ss/user/ntuser/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/window.c?rev=73806&r1=73805&r2=73806&view=diff ============================================================================== --- trunk/reactos/win32ss/user/ntuser/window.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/window.c [iso-8859-1] Fri Feb 17 11:07:14 2017 @@ -2807,7 +2807,7 @@ /* 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 @@ (TopLevelWindow->strName.Length < 0xFFFF && !RtlCompareUnicodeString(&WindowName, &ustr, TRUE)); ClassMatches = (ClassAtom == (RTL_ATOM)0) || - ClassAtom == TopLevelWindow->pcls->atomClassName; + ClassAtom == TopLevelWindow->pcls->atomNVClassName; if (WindowMatches && ClassMatches) { Modified: trunk/reactos/win32ss/user/user32/windows/class.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/user32/windows/class.c?rev=73806&r1=73805&r2=73806&view=diff ============================================================================== --- trunk/reactos/win32ss/user/user32/windows/class.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/user32/windows/class.c [iso-8859-1] Fri Feb 17 11:07:14 2017 @@ -13,177 +13,38 @@ #include <wine/debug.h> WINE_DEFAULT_DEBUG_CHANNEL(user32); +#define USE_VERSIONED_CLASSES + /* From rtl/actctx.c and must match! */ -struct entity -{ - DWORD kind; // Activation context type - WCHAR *name; // Class name - WCHAR *clsid; // Not supported yet but needed for menu name. +struct strsection_header +{ + DWORD magic; + ULONG size; + DWORD unk1[3]; + ULONG count; + ULONG index_offset; + DWORD unk2[2]; + ULONG global_offset; + ULONG global_len; }; -struct dll_redirect -{ - WCHAR *name; // Dll name - WCHAR *hash; - DWORD Data; // Junk +struct wndclass_redirect_data +{ + 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 @@ 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 @@ HANDLE Contex, HMODULE * phLibModule) { - // Should be lpLibFileName..... - static const WCHAR comctl32W[] = {'c','o','m','c','t','l','3','2','.','d','l','l',0}; - // + BOOL Ret = FALSE; + HMODULE hLibModule = NULL; 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 ) + 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 ((pRegisterClassNameW = (void*) GetProcAddress(hLibModule, "RegisterClassNameW"))) + if (IS_ATOM(pszClass)) { - if (IS_ATOM(pszClass)) + ClassName.Buffer = ClassNameBuf; + ClassName.MaximumLength = sizeof(ClassNameBuf); + if (!NtUserGetAtomName(LOWORD((DWORD_PTR)pszClass), &ClassName)) { - 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; + ERR("Error while verifying ATOM\n"); + _SEH2_YIELD(goto Error_Exit); } - Ret = pRegisterClassNameW(pszClass); + pszClass = ClassName.Buffer; } + Ret = pRegisterClassNameW(pszClass); } - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - } - _SEH2_END + else + { + WARN("No RegisterClassNameW PROC\n"); + } + } + } + _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 @@ 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 @@ 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 @@ (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 @@ // lpwcx->lpszMenuName = pszMenuName; } - if (!IS_ATOM(lpszClass)) + if (ConvertedString) { RtlFreeUnicodeString(&ClassName); } @@ -403,6 +378,9 @@ 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 @@ 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 @@ &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 @@ 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,40 +1477,27 @@ RtlInitUnicodeString(&ClassName, WndClass.lpszClassName); } + 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; - for(;;) - { - 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) - { - save_error = GetLastError(); - FreeLibrary(hLibModule); - SetLastError(save_error); - hLibModule = 0; - } - break; - } + 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, @@ -1886,16 +1855,23 @@ { 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)) - { - if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, - lpClassName)) + lpszClsVersion = ClassNameToVersion(lpClassName, NULL, NULL, NULL, TRUE); + if (lpszClsVersion) + { + 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 @@ else ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName); - Ret = NtUserUnregisterClass(&ClassName, - hInstance, - 0); - - if (!IS_ATOM(lpClassName)) + Ret = NtUserUnregisterClass(&ClassName, hInstance, 0); + + if (ConvertedString) RtlFreeUnicodeString(&ClassName); return Ret; @@ -1925,23 +1899,28 @@ 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)) - { - RtlInitUnicodeString(&ClassName, - lpClassName); + lpszClsVersion = ClassNameToVersion(lpClassName, NULL, NULL, NULL, FALSE); + if (lpszClsVersion) + { + 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 */ Modified: trunk/reactos/win32ss/user/user32/windows/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/user32/windows/window.c?rev=73806&r1=73805&r2=73806&view=diff ============================================================================== --- trunk/reactos/win32ss/user/user32/windows/window.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/user32/windows/window.c [iso-8859-1] Fri Feb 17 11:07:14 2017 @@ -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 @@ { 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 @@ 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 @@ 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; } }