From 01263aac8b514089f5dd167a73daecbe6ec88f31 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Sun, 3 Nov 2013 23:19:59 +0000 Subject: [PATCH] [User32] - Add context hack from wine. Pass alt tab info calls to win32k. - From wine: Alexandre Julliard : user32: Automatically load comctl32 when one of its classes is requested. svn path=/trunk/; revision=60858 --- .../win32ss/user/user32/include/regcontrol.h | 1 + reactos/win32ss/user/user32/windows/class.c | 238 ++++++++++++++++-- reactos/win32ss/user/user32/windows/window.c | 65 +++-- 3 files changed, 258 insertions(+), 46 deletions(-) diff --git a/reactos/win32ss/user/user32/include/regcontrol.h b/reactos/win32ss/user/user32/include/regcontrol.h index 91a9892520c..daed43b8def 100644 --- a/reactos/win32ss/user/user32/include/regcontrol.h +++ b/reactos/win32ss/user/user32/include/regcontrol.h @@ -39,3 +39,4 @@ extern const struct builtin_class_descr SCROLL_builtin_class; extern const struct builtin_class_descr STATIC_builtin_class; ATOM WINAPI RegisterClassExWOWW(WNDCLASSEXW *,LPDWORD,WORD,DWORD,BOOL); +BOOL FASTCALL VersionRegisterClass(PCWSTR,LPCWSTR,HANDLE,HMODULE *); diff --git a/reactos/win32ss/user/user32/windows/class.c b/reactos/win32ss/user/user32/windows/class.c index 9540b4c84d0..0d5494574e9 100644 --- a/reactos/win32ss/user/user32/windows/class.c +++ b/reactos/win32ss/user/user32/windows/class.c @@ -39,7 +39,7 @@ ClassNameToVersion( { NTSTATUS Status; UNICODE_STRING SectionName; - WCHAR SeactionNameBuf[256] = {0}; + WCHAR SeactionNameBuf[MAX_PATH] = {0}; ACTCTX_SECTION_KEYED_DATA KeyedData = { sizeof(KeyedData) }; if (IS_ATOM(lpszClass)) @@ -113,9 +113,12 @@ ClassNameToVersion( return lpszClass; } +// +// Ref: http://yvs-it.blogspot.com/2010/04/initcommoncontrolsex.html +// BOOL FASTCALL -VersionRegisterClass( +Real_VersionRegisterClass( PCWSTR pszClass, LPCWSTR lpLibFileName, HANDLE Contex, @@ -125,7 +128,7 @@ VersionRegisterClass( HMODULE hLibModule; PREGISTERCLASSNAMEW pRegisterClassNameW; UNICODE_STRING ClassName; - WCHAR ClassNameBuf[256] = {0}; + WCHAR ClassNameBuf[MAX_PATH] = {0}; RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame = { sizeof(Frame), 1 }; RtlActivateActivationContextUnsafeFast(&Frame, Contex); @@ -174,6 +177,117 @@ Error_Exit: 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_comctl32_class( pszClass )) + { + _SEH2_TRY + { + hLibModule = GetModuleHandleW( comctl32W ); + if (!hLibModule) 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 */ @@ -185,8 +299,10 @@ GetClassInfoExA( LPWNDCLASSEXA lpwcx) { UNICODE_STRING ClassName = {0}; - BOOL Ret; LPCSTR pszMenuName; + HMODULE hLibModule; + DWORD save_error; + BOOL Ret, ClassFound = FALSE; TRACE("%p class/atom: %s/%04x %p\n", hInstance, IS_ATOM(lpszClass) ? NULL : lpszClass, @@ -230,11 +346,34 @@ GetClassInfoExA( RegisterSystemControls(); } - Ret = NtUserGetClassInfo(hInstance, - &ClassName, - (LPWNDCLASSEXW)lpwcx, - (LPWSTR *)&pszMenuName, - TRUE); + for(;;) + { + Ret = NtUserGetClassInfo( hInstance, + &ClassName, + (LPWNDCLASSEXW)lpwcx, + (LPWSTR *)&pszMenuName, + TRUE); + if (Ret) break; + if (!ClassFound) + { + save_error = GetLastError(); + if ( save_error == ERROR_CANNOT_FIND_WND_CLASS || + save_error == ERROR_CLASS_DOES_NOT_EXIST ) + { + ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule); + if (ClassFound) continue; + } + } + if (hLibModule) + { + save_error = GetLastError(); + FreeLibrary(hLibModule); + SetLastError(save_error); + hLibModule = 0; + } + break; + } + if (Ret) { lpwcx->lpszClassName = lpszClass; @@ -261,8 +400,10 @@ GetClassInfoExW( LPWNDCLASSEXW lpwcx) { UNICODE_STRING ClassName = {0}; - BOOL Ret; LPWSTR pszMenuName; + HMODULE hLibModule; + DWORD save_error; + BOOL Ret, ClassFound = FALSE; TRACE("%p class/atom: %S/%04x %p\n", hInstance, IS_ATOM(lpszClass) ? NULL : lpszClass, @@ -305,11 +446,34 @@ GetClassInfoExW( RegisterSystemControls(); } - Ret = NtUserGetClassInfo( hInstance, - &ClassName, - lpwcx, - &pszMenuName, - FALSE); + for(;;) + { + Ret = NtUserGetClassInfo( hInstance, + &ClassName, + lpwcx, + &pszMenuName, + FALSE); + if (Ret) break; + if (!ClassFound) + { + save_error = GetLastError(); + if ( save_error == ERROR_CANNOT_FIND_WND_CLASS || + save_error == ERROR_CLASS_DOES_NOT_EXIST ) + { + ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule); + if (ClassFound) continue; + } + } + if (hLibModule) + { + save_error = GetLastError(); + FreeLibrary(hLibModule); + SetLastError(save_error); + hLibModule = 0; + } + break; + } + if (Ret) { lpwcx->lpszClassName = lpszClass; @@ -1265,6 +1429,9 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx, UNICODE_STRING MenuName = {0}; CLSMENUNAME clsMenuName; ANSI_STRING AnsiMenuName; + HMODULE hLibModule; + DWORD save_error; + BOOL ClassFound = FALSE; if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) || lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 || @@ -1338,13 +1505,36 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx, clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer; clsMenuName.pusMenuName = &MenuName; - Atom = NtUserRegisterClassExWOW( &WndClass, - &ClassName, - NULL, //PUNICODE_STRING ClsNVersion, - &clsMenuName, - fnID, - dwFlags, - pdwWowData); + for(;;) + { + Atom = NtUserRegisterClassExWOW( &WndClass, + &ClassName, + NULL, //PUNICODE_STRING ClsNVersion, + &clsMenuName, + fnID, + dwFlags, + pdwWowData); + + if (Atom) break; + if (!ClassFound) + { + save_error = GetLastError(); + if ( save_error == ERROR_CANNOT_FIND_WND_CLASS || + save_error == ERROR_CLASS_DOES_NOT_EXIST ) + { + ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule); + if (ClassFound) continue; + } + } + if (hLibModule) + { + save_error = GetLastError(); + FreeLibrary(hLibModule); + SetLastError(save_error); + hLibModule = 0; + } + break; + } TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n", Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground, @@ -1720,8 +1910,8 @@ UnregisterClassA( ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName); Ret = NtUserUnregisterClass(&ClassName, - hInstance, - 0); + hInstance, + 0); if (!IS_ATOM(lpClassName)) RtlFreeUnicodeString(&ClassName); diff --git a/reactos/win32ss/user/user32/windows/window.c b/reactos/win32ss/user/user32/windows/window.c index a26080702c5..d62e37e600d 100644 --- a/reactos/win32ss/user/user32/windows/window.c +++ b/reactos/win32ss/user/user32/windows/window.c @@ -169,7 +169,9 @@ User32CreateWindowEx(DWORD dwExStyle, UNICODE_STRING ClassName; WNDCLASSEXA wceA; WNDCLASSEXW wceW; - BOOL Unicode; + HMODULE hLibModule; + DWORD save_error; + BOOL Unicode, ClassFound = FALSE; HWND Handle = NULL; #if 0 @@ -262,21 +264,42 @@ User32CreateWindowEx(DWORD dwExStyle, if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR; - Handle = NtUserCreateWindowEx(dwExStyle, - plstrClassName, - NULL, - &WindowName, - dwStyle, - x, - y, - nWidth, - nHeight, - hWndParent, - hMenu, - hInstance, - lpParam, - dwFlags, - NULL); + for(;;) + { + Handle = NtUserCreateWindowEx(dwExStyle, + plstrClassName, + NULL, + &WindowName, + dwStyle, + x, + y, + nWidth, + nHeight, + hWndParent, + hMenu, + hInstance, + lpParam, + dwFlags, + NULL); + if (Handle) break; + if (!ClassFound) + { + save_error = GetLastError(); + if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ) + { + ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule); + if (ClassFound) continue; + } + } + if (hLibModule) + { + save_error = GetLastError(); + FreeLibrary(hLibModule); + SetLastError(save_error); + hLibModule = 0; + } + break; + } #if 0 DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle); @@ -845,7 +868,7 @@ FindWindowW(LPCWSTR lpClassName, LPCWSTR lpWindowName) /* - * @unimplemented + * @implemented */ BOOL WINAPI GetAltTabInfoA(HWND hwnd, @@ -854,13 +877,12 @@ GetAltTabInfoA(HWND hwnd, LPSTR pszItemText, UINT cchItemText) { - UNIMPLEMENTED; - return FALSE; + return NtUserGetAltTabInfo(hwnd,iItem,pati,(LPWSTR)pszItemText,cchItemText,TRUE); } /* - * @unimplemented + * @implemented */ BOOL WINAPI GetAltTabInfoW(HWND hwnd, @@ -869,8 +891,7 @@ GetAltTabInfoW(HWND hwnd, LPWSTR pszItemText, UINT cchItemText) { - UNIMPLEMENTED; - return FALSE; + return NtUserGetAltTabInfo(hwnd,iItem,pati,pszItemText,cchItemText,FALSE); }