mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
[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
This commit is contained in:
parent
ebf8247723
commit
c607de714c
4 changed files with 263 additions and 262 deletions
|
@ -2743,6 +2743,7 @@ NtUserGetClassInfo(
|
|||
NULL);
|
||||
if (ClassAtom != (RTL_ATOM)0)
|
||||
{
|
||||
ClassAtom = Class->atomNVClassName;
|
||||
Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
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 */
|
||||
};
|
||||
|
||||
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 @@ static BOOL is_comctl32_class( const WCHAR *name )
|
|||
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 @@ VersionRegisterClass(
|
|||
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;
|
||||
RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame = { sizeof(Frame), 1 };
|
||||
|
||||
if (!IS_ATOM(pszClass) && is_comctl32_class( pszClass ))
|
||||
RtlActivateActivationContextUnsafeFast(&Frame, Contex);
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
_SEH2_TRY
|
||||
hLibModule = LoadLibraryW(lpLibFileName);
|
||||
if ( hLibModule )
|
||||
{
|
||||
hLibModule = LoadLibraryW(comctl32W);
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("No RegisterClassNameW PROC\n");
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
_SEH2_END
|
||||
}
|
||||
_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;
|
||||
if ( Ret || !hLibModule )
|
||||
{
|
||||
if ( phLibModule ) *phLibModule = hLibModule;
|
||||
}
|
||||
TRACE("NO ComCtl32 Class %S!\n",pszClass);
|
||||
return FALSE;
|
||||
else
|
||||
{
|
||||
DWORD save_error = GetLastError();
|
||||
FreeLibrary(hLibModule);
|
||||
SetLastError(save_error);
|
||||
}
|
||||
|
||||
RtlDeactivateActivationContextUnsafeFast(&Frame);
|
||||
return Ret;
|
||||
}
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
/*
|
||||
* @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,40 +1477,27 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
|
|||
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 @@ 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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue