- 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
This commit is contained in:
James Tabor 2013-11-03 23:19:59 +00:00
parent 16c4fe33fb
commit 01263aac8b
3 changed files with 258 additions and 46 deletions

View file

@ -39,3 +39,4 @@ extern const struct builtin_class_descr SCROLL_builtin_class;
extern const struct builtin_class_descr STATIC_builtin_class; extern const struct builtin_class_descr STATIC_builtin_class;
ATOM WINAPI RegisterClassExWOWW(WNDCLASSEXW *,LPDWORD,WORD,DWORD,BOOL); ATOM WINAPI RegisterClassExWOWW(WNDCLASSEXW *,LPDWORD,WORD,DWORD,BOOL);
BOOL FASTCALL VersionRegisterClass(PCWSTR,LPCWSTR,HANDLE,HMODULE *);

View file

@ -39,7 +39,7 @@ ClassNameToVersion(
{ {
NTSTATUS Status; NTSTATUS Status;
UNICODE_STRING SectionName; UNICODE_STRING SectionName;
WCHAR SeactionNameBuf[256] = {0}; WCHAR SeactionNameBuf[MAX_PATH] = {0};
ACTCTX_SECTION_KEYED_DATA KeyedData = { sizeof(KeyedData) }; ACTCTX_SECTION_KEYED_DATA KeyedData = { sizeof(KeyedData) };
if (IS_ATOM(lpszClass)) if (IS_ATOM(lpszClass))
@ -113,9 +113,12 @@ ClassNameToVersion(
return lpszClass; return lpszClass;
} }
//
// Ref: http://yvs-it.blogspot.com/2010/04/initcommoncontrolsex.html
//
BOOL BOOL
FASTCALL FASTCALL
VersionRegisterClass( Real_VersionRegisterClass(
PCWSTR pszClass, PCWSTR pszClass,
LPCWSTR lpLibFileName, LPCWSTR lpLibFileName,
HANDLE Contex, HANDLE Contex,
@ -125,7 +128,7 @@ VersionRegisterClass(
HMODULE hLibModule; HMODULE hLibModule;
PREGISTERCLASSNAMEW pRegisterClassNameW; PREGISTERCLASSNAMEW pRegisterClassNameW;
UNICODE_STRING ClassName; UNICODE_STRING ClassName;
WCHAR ClassNameBuf[256] = {0}; WCHAR ClassNameBuf[MAX_PATH] = {0};
RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame = { sizeof(Frame), 1 }; RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame = { sizeof(Frame), 1 };
RtlActivateActivationContextUnsafeFast(&Frame, Contex); RtlActivateActivationContextUnsafeFast(&Frame, Contex);
@ -174,6 +177,117 @@ Error_Exit:
return Ret; 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 * @implemented
*/ */
@ -185,8 +299,10 @@ GetClassInfoExA(
LPWNDCLASSEXA lpwcx) LPWNDCLASSEXA lpwcx)
{ {
UNICODE_STRING ClassName = {0}; UNICODE_STRING ClassName = {0};
BOOL Ret;
LPCSTR pszMenuName; LPCSTR pszMenuName;
HMODULE hLibModule;
DWORD save_error;
BOOL Ret, ClassFound = FALSE;
TRACE("%p class/atom: %s/%04x %p\n", hInstance, TRACE("%p class/atom: %s/%04x %p\n", hInstance,
IS_ATOM(lpszClass) ? NULL : lpszClass, IS_ATOM(lpszClass) ? NULL : lpszClass,
@ -230,11 +346,34 @@ GetClassInfoExA(
RegisterSystemControls(); RegisterSystemControls();
} }
Ret = NtUserGetClassInfo(hInstance, for(;;)
&ClassName, {
(LPWNDCLASSEXW)lpwcx, Ret = NtUserGetClassInfo( hInstance,
(LPWSTR *)&pszMenuName, &ClassName,
TRUE); (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) if (Ret)
{ {
lpwcx->lpszClassName = lpszClass; lpwcx->lpszClassName = lpszClass;
@ -261,8 +400,10 @@ GetClassInfoExW(
LPWNDCLASSEXW lpwcx) LPWNDCLASSEXW lpwcx)
{ {
UNICODE_STRING ClassName = {0}; UNICODE_STRING ClassName = {0};
BOOL Ret;
LPWSTR pszMenuName; LPWSTR pszMenuName;
HMODULE hLibModule;
DWORD save_error;
BOOL Ret, ClassFound = FALSE;
TRACE("%p class/atom: %S/%04x %p\n", hInstance, TRACE("%p class/atom: %S/%04x %p\n", hInstance,
IS_ATOM(lpszClass) ? NULL : lpszClass, IS_ATOM(lpszClass) ? NULL : lpszClass,
@ -305,11 +446,34 @@ GetClassInfoExW(
RegisterSystemControls(); RegisterSystemControls();
} }
Ret = NtUserGetClassInfo( hInstance, for(;;)
&ClassName, {
lpwcx, Ret = NtUserGetClassInfo( hInstance,
&pszMenuName, &ClassName,
FALSE); 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) if (Ret)
{ {
lpwcx->lpszClassName = lpszClass; lpwcx->lpszClassName = lpszClass;
@ -1265,6 +1429,9 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
UNICODE_STRING MenuName = {0}; UNICODE_STRING MenuName = {0};
CLSMENUNAME clsMenuName; CLSMENUNAME clsMenuName;
ANSI_STRING AnsiMenuName; ANSI_STRING AnsiMenuName;
HMODULE hLibModule;
DWORD save_error;
BOOL ClassFound = FALSE;
if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) || if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 || lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
@ -1338,13 +1505,36 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer; clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer;
clsMenuName.pusMenuName = &MenuName; clsMenuName.pusMenuName = &MenuName;
Atom = NtUserRegisterClassExWOW( &WndClass, for(;;)
&ClassName, {
NULL, //PUNICODE_STRING ClsNVersion, Atom = NtUserRegisterClassExWOW( &WndClass,
&clsMenuName, &ClassName,
fnID, NULL, //PUNICODE_STRING ClsNVersion,
dwFlags, &clsMenuName,
pdwWowData); 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", 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, Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
@ -1720,8 +1910,8 @@ UnregisterClassA(
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName); ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
Ret = NtUserUnregisterClass(&ClassName, Ret = NtUserUnregisterClass(&ClassName,
hInstance, hInstance,
0); 0);
if (!IS_ATOM(lpClassName)) if (!IS_ATOM(lpClassName))
RtlFreeUnicodeString(&ClassName); RtlFreeUnicodeString(&ClassName);

View file

@ -169,7 +169,9 @@ User32CreateWindowEx(DWORD dwExStyle,
UNICODE_STRING ClassName; UNICODE_STRING ClassName;
WNDCLASSEXA wceA; WNDCLASSEXA wceA;
WNDCLASSEXW wceW; WNDCLASSEXW wceW;
BOOL Unicode; HMODULE hLibModule;
DWORD save_error;
BOOL Unicode, ClassFound = FALSE;
HWND Handle = NULL; HWND Handle = NULL;
#if 0 #if 0
@ -262,21 +264,42 @@ User32CreateWindowEx(DWORD dwExStyle,
if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR; if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR;
Handle = NtUserCreateWindowEx(dwExStyle, for(;;)
plstrClassName, {
NULL, Handle = NtUserCreateWindowEx(dwExStyle,
&WindowName, plstrClassName,
dwStyle, NULL,
x, &WindowName,
y, dwStyle,
nWidth, x,
nHeight, y,
hWndParent, nWidth,
hMenu, nHeight,
hInstance, hWndParent,
lpParam, hMenu,
dwFlags, hInstance,
NULL); 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 #if 0
DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle); DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle);
@ -845,7 +868,7 @@ FindWindowW(LPCWSTR lpClassName, LPCWSTR lpWindowName)
/* /*
* @unimplemented * @implemented
*/ */
BOOL WINAPI BOOL WINAPI
GetAltTabInfoA(HWND hwnd, GetAltTabInfoA(HWND hwnd,
@ -854,13 +877,12 @@ GetAltTabInfoA(HWND hwnd,
LPSTR pszItemText, LPSTR pszItemText,
UINT cchItemText) UINT cchItemText)
{ {
UNIMPLEMENTED; return NtUserGetAltTabInfo(hwnd,iItem,pati,(LPWSTR)pszItemText,cchItemText,TRUE);
return FALSE;
} }
/* /*
* @unimplemented * @implemented
*/ */
BOOL WINAPI BOOL WINAPI
GetAltTabInfoW(HWND hwnd, GetAltTabInfoW(HWND hwnd,
@ -869,8 +891,7 @@ GetAltTabInfoW(HWND hwnd,
LPWSTR pszItemText, LPWSTR pszItemText,
UINT cchItemText) UINT cchItemText)
{ {
UNIMPLEMENTED; return NtUserGetAltTabInfo(hwnd,iItem,pati,pszItemText,cchItemText,FALSE);
return FALSE;
} }