mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +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);
|
NULL);
|
||||||
if (ClassAtom != (RTL_ATOM)0)
|
if (ClassAtom != (RTL_ATOM)0)
|
||||||
{
|
{
|
||||||
|
ClassAtom = Class->atomNVClassName;
|
||||||
Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance);
|
Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -2807,7 +2807,7 @@ IntFindWindow(PWND Parent,
|
||||||
/* Do not send WM_GETTEXT messages in the kernel mode version!
|
/* Do not send WM_GETTEXT messages in the kernel mode version!
|
||||||
The user mode version however calls GetWindowText() which will
|
The user mode version however calls GetWindowText() which will
|
||||||
send WM_GETTEXT messages to windows belonging to its processes */
|
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
|
// FIXME: LARGE_STRING truncated
|
||||||
CurrentWindowName.Buffer = Child->strName.Buffer;
|
CurrentWindowName.Buffer = Child->strName.Buffer;
|
||||||
|
@ -2999,7 +2999,7 @@ NtUserFindWindowEx(HWND hwndParent,
|
||||||
(TopLevelWindow->strName.Length < 0xFFFF &&
|
(TopLevelWindow->strName.Length < 0xFFFF &&
|
||||||
!RtlCompareUnicodeString(&WindowName, &ustr, TRUE));
|
!RtlCompareUnicodeString(&WindowName, &ustr, TRUE));
|
||||||
ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
|
ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
|
||||||
ClassAtom == TopLevelWindow->pcls->atomClassName;
|
ClassAtom == TopLevelWindow->pcls->atomNVClassName;
|
||||||
|
|
||||||
if (WindowMatches && ClassMatches)
|
if (WindowMatches && ClassMatches)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,177 +13,38 @@
|
||||||
#include <wine/debug.h>
|
#include <wine/debug.h>
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
||||||
|
|
||||||
|
#define USE_VERSIONED_CLASSES
|
||||||
|
|
||||||
/* From rtl/actctx.c and must match! */
|
/* From rtl/actctx.c and must match! */
|
||||||
struct entity
|
struct strsection_header
|
||||||
{
|
{
|
||||||
DWORD kind; // Activation context type
|
DWORD magic;
|
||||||
WCHAR *name; // Class name
|
ULONG size;
|
||||||
WCHAR *clsid; // Not supported yet but needed for menu name.
|
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
|
ULONG size;
|
||||||
WCHAR *hash;
|
DWORD res;
|
||||||
DWORD Data; // Junk
|
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
|
// Use wine hack to process extended context classes.
|
||||||
//
|
|
||||||
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.
|
|
||||||
//
|
//
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* is_comctl32_class
|
* is_comctl32_class
|
||||||
*/
|
*/
|
||||||
static BOOL is_comctl32_class( const WCHAR *name )
|
LPCWSTR is_comctl32_class( const WCHAR *name )
|
||||||
{
|
{
|
||||||
static const WCHAR classesW[][20] =
|
static const WCHAR classesW[][20] =
|
||||||
{
|
{
|
||||||
|
@ -213,13 +74,121 @@ static BOOL is_comctl32_class( const WCHAR *name )
|
||||||
while (min <= max)
|
while (min <= max)
|
||||||
{
|
{
|
||||||
int res, pos = (min + max) / 2;
|
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;
|
if (res < 0) max = pos - 1;
|
||||||
else min = 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
|
BOOL
|
||||||
FASTCALL
|
FASTCALL
|
||||||
VersionRegisterClass(
|
VersionRegisterClass(
|
||||||
|
@ -228,64 +197,61 @@ VersionRegisterClass(
|
||||||
HANDLE Contex,
|
HANDLE Contex,
|
||||||
HMODULE * phLibModule)
|
HMODULE * phLibModule)
|
||||||
{
|
{
|
||||||
// Should be lpLibFileName.....
|
BOOL Ret = FALSE;
|
||||||
static const WCHAR comctl32W[] = {'c','o','m','c','t','l','3','2','.','d','l','l',0};
|
HMODULE hLibModule = NULL;
|
||||||
//
|
|
||||||
PREGISTERCLASSNAMEW pRegisterClassNameW;
|
PREGISTERCLASSNAMEW pRegisterClassNameW;
|
||||||
UNICODE_STRING ClassName;
|
UNICODE_STRING ClassName;
|
||||||
WCHAR ClassNameBuf[MAX_PATH] = {0};
|
WCHAR ClassNameBuf[MAX_PATH] = {0};
|
||||||
BOOL Ret = FALSE;
|
RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame = { sizeof(Frame), 1 };
|
||||||
HMODULE hLibModule = NULL;
|
|
||||||
|
|
||||||
if (!IS_ATOM(pszClass) && is_comctl32_class( pszClass ))
|
RtlActivateActivationContextUnsafeFast(&Frame, Contex);
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
_SEH2_TRY
|
hLibModule = LoadLibraryW(lpLibFileName);
|
||||||
|
if ( hLibModule )
|
||||||
{
|
{
|
||||||
hLibModule = LoadLibraryW(comctl32W);
|
if ((pRegisterClassNameW = (void*) GetProcAddress(hLibModule, "RegisterClassNameW")))
|
||||||
if ( hLibModule )
|
|
||||||
{
|
{
|
||||||
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;
|
ERR("Error while verifying ATOM\n");
|
||||||
ClassName.MaximumLength = sizeof(ClassNameBuf);
|
_SEH2_YIELD(goto Error_Exit);
|
||||||
if (!NtUserGetAtomName(LOWORD((DWORD_PTR)pszClass), &ClassName))
|
|
||||||
{
|
|
||||||
ERR("Error while verifying ATOM\n");
|
|
||||||
_SEH2_YIELD(goto Error_Exit);
|
|
||||||
}
|
|
||||||
pszClass = (PCWSTR)&ClassNameBuf;
|
|
||||||
}
|
}
|
||||||
Ret = pRegisterClassNameW(pszClass);
|
pszClass = ClassName.Buffer;
|
||||||
}
|
}
|
||||||
|
Ret = pRegisterClassNameW(pszClass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WARN("No RegisterClassNameW PROC\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
}
|
||||||
{
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
}
|
{
|
||||||
_SEH2_END
|
}
|
||||||
|
_SEH2_END
|
||||||
|
|
||||||
Error_Exit:
|
Error_Exit:
|
||||||
if ( Ret || !hLibModule )
|
if ( Ret || !hLibModule )
|
||||||
{
|
{
|
||||||
if ( phLibModule ) *phLibModule = 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);
|
else
|
||||||
return FALSE;
|
{
|
||||||
|
DWORD save_error = GetLastError();
|
||||||
|
FreeLibrary(hLibModule);
|
||||||
|
SetLastError(save_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlDeactivateActivationContextUnsafeFast(&Frame);
|
||||||
|
return Ret;
|
||||||
}
|
}
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
|
@ -301,7 +267,10 @@ GetClassInfoExA(
|
||||||
LPCSTR pszMenuName;
|
LPCSTR pszMenuName;
|
||||||
HMODULE hLibModule = NULL;
|
HMODULE hLibModule = NULL;
|
||||||
DWORD save_error;
|
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,
|
TRACE("%p class/atom: %s/%04x %p\n", hInstance,
|
||||||
IS_ATOM(lpszClass) ? NULL : lpszClass,
|
IS_ATOM(lpszClass) ? NULL : lpszClass,
|
||||||
|
@ -325,14 +294,19 @@ GetClassInfoExA(
|
||||||
return FALSE;
|
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);
|
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!RtlCreateUnicodeStringFromAsciiz(&ClassName,
|
ConvertedString = TRUE;
|
||||||
lpszClass))
|
if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, lpszClass))
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -353,13 +327,14 @@ GetClassInfoExA(
|
||||||
(LPWSTR *)&pszMenuName,
|
(LPWSTR *)&pszMenuName,
|
||||||
TRUE);
|
TRUE);
|
||||||
if (Ret) break;
|
if (Ret) break;
|
||||||
|
if (!lpLibFileName) break;
|
||||||
if (!ClassFound)
|
if (!ClassFound)
|
||||||
{
|
{
|
||||||
save_error = GetLastError();
|
save_error = GetLastError();
|
||||||
if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
|
if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
|
||||||
save_error == ERROR_CLASS_DOES_NOT_EXIST )
|
save_error == ERROR_CLASS_DOES_NOT_EXIST )
|
||||||
{
|
{
|
||||||
ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule);
|
ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule);
|
||||||
if (ClassFound) continue;
|
if (ClassFound) continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,7 +354,7 @@ GetClassInfoExA(
|
||||||
// lpwcx->lpszMenuName = pszMenuName;
|
// lpwcx->lpszMenuName = pszMenuName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_ATOM(lpszClass))
|
if (ConvertedString)
|
||||||
{
|
{
|
||||||
RtlFreeUnicodeString(&ClassName);
|
RtlFreeUnicodeString(&ClassName);
|
||||||
}
|
}
|
||||||
|
@ -403,6 +378,9 @@ GetClassInfoExW(
|
||||||
HMODULE hLibModule = NULL;
|
HMODULE hLibModule = NULL;
|
||||||
DWORD save_error;
|
DWORD save_error;
|
||||||
BOOL Ret, ClassFound = FALSE;
|
BOOL Ret, ClassFound = FALSE;
|
||||||
|
LPCWSTR lpszClsVersion;
|
||||||
|
HANDLE pCtx = NULL;
|
||||||
|
LPCWSTR lpLibFileName = NULL;
|
||||||
|
|
||||||
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,
|
||||||
|
@ -429,14 +407,18 @@ GetClassInfoExW(
|
||||||
return FALSE;
|
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);
|
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RtlInitUnicodeString(&ClassName,
|
RtlInitUnicodeString(&ClassName, lpszClass);
|
||||||
lpszClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RegisterDefaultClasses)
|
if (!RegisterDefaultClasses)
|
||||||
|
@ -453,13 +435,14 @@ GetClassInfoExW(
|
||||||
&pszMenuName,
|
&pszMenuName,
|
||||||
FALSE);
|
FALSE);
|
||||||
if (Ret) break;
|
if (Ret) break;
|
||||||
|
if (!lpLibFileName) break;
|
||||||
if (!ClassFound)
|
if (!ClassFound)
|
||||||
{
|
{
|
||||||
save_error = GetLastError();
|
save_error = GetLastError();
|
||||||
if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
|
if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ||
|
||||||
save_error == ERROR_CLASS_DOES_NOT_EXIST )
|
save_error == ERROR_CLASS_DOES_NOT_EXIST )
|
||||||
{
|
{
|
||||||
ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule);
|
ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule);
|
||||||
if (ClassFound) continue;
|
if (ClassFound) continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1419,12 +1402,11 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
|
||||||
ATOM Atom;
|
ATOM Atom;
|
||||||
WNDCLASSEXW WndClass;
|
WNDCLASSEXW WndClass;
|
||||||
UNICODE_STRING ClassName;
|
UNICODE_STRING ClassName;
|
||||||
|
UNICODE_STRING ClassVersion;
|
||||||
UNICODE_STRING MenuName = {0};
|
UNICODE_STRING MenuName = {0};
|
||||||
CLSMENUNAME clsMenuName;
|
CLSMENUNAME clsMenuName;
|
||||||
ANSI_STRING AnsiMenuName;
|
ANSI_STRING AnsiMenuName;
|
||||||
HMODULE hLibModule = NULL;
|
LPCWSTR lpszClsVersion;
|
||||||
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 ||
|
||||||
|
@ -1495,40 +1477,27 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
|
||||||
RtlInitUnicodeString(&ClassName, WndClass.lpszClassName);
|
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.pszClientAnsiMenuName = AnsiMenuName.Buffer;
|
||||||
clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer;
|
clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer;
|
||||||
clsMenuName.pusMenuName = &MenuName;
|
clsMenuName.pusMenuName = &MenuName;
|
||||||
|
|
||||||
for(;;)
|
Atom = NtUserRegisterClassExWOW( &WndClass,
|
||||||
{
|
&ClassName,
|
||||||
Atom = NtUserRegisterClassExWOW( &WndClass,
|
&ClassVersion,
|
||||||
&ClassName,
|
&clsMenuName,
|
||||||
&ClassName, //PUNICODE_STRING ClsNVersion,
|
fnID,
|
||||||
&clsMenuName,
|
dwFlags,
|
||||||
fnID,
|
pdwWowData);
|
||||||
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,
|
||||||
|
@ -1886,16 +1855,23 @@ UnregisterClassA(
|
||||||
{
|
{
|
||||||
UNICODE_STRING ClassName = {0};
|
UNICODE_STRING ClassName = {0};
|
||||||
BOOL Ret;
|
BOOL Ret;
|
||||||
|
LPCWSTR lpszClsVersion;
|
||||||
|
BOOL ConvertedString = FALSE;
|
||||||
|
|
||||||
TRACE("class/atom: %s/%04x %p\n",
|
TRACE("class/atom: %s/%04x %p\n",
|
||||||
IS_ATOM(lpClassName) ? NULL : lpClassName,
|
IS_ATOM(lpClassName) ? NULL : lpClassName,
|
||||||
IS_ATOM(lpClassName) ? lpClassName : 0,
|
IS_ATOM(lpClassName) ? lpClassName : 0,
|
||||||
hInstance);
|
hInstance);
|
||||||
|
|
||||||
if (!IS_ATOM(lpClassName))
|
lpszClsVersion = ClassNameToVersion(lpClassName, NULL, NULL, NULL, TRUE);
|
||||||
|
if (lpszClsVersion)
|
||||||
{
|
{
|
||||||
if (!RtlCreateUnicodeStringFromAsciiz(&ClassName,
|
RtlInitUnicodeString(&ClassName, lpszClsVersion);
|
||||||
lpClassName))
|
}
|
||||||
|
else if (!IS_ATOM(lpClassName))
|
||||||
|
{
|
||||||
|
ConvertedString = TRUE;
|
||||||
|
if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, lpClassName))
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1904,11 +1880,9 @@ UnregisterClassA(
|
||||||
else
|
else
|
||||||
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
|
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
|
||||||
|
|
||||||
Ret = NtUserUnregisterClass(&ClassName,
|
Ret = NtUserUnregisterClass(&ClassName, hInstance, 0);
|
||||||
hInstance,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (!IS_ATOM(lpClassName))
|
if (ConvertedString)
|
||||||
RtlFreeUnicodeString(&ClassName);
|
RtlFreeUnicodeString(&ClassName);
|
||||||
|
|
||||||
return Ret;
|
return Ret;
|
||||||
|
@ -1925,23 +1899,28 @@ UnregisterClassW(
|
||||||
HINSTANCE hInstance)
|
HINSTANCE hInstance)
|
||||||
{
|
{
|
||||||
UNICODE_STRING ClassName = {0};
|
UNICODE_STRING ClassName = {0};
|
||||||
|
LPCWSTR lpszClsVersion;
|
||||||
|
|
||||||
TRACE("class/atom: %S/%04x %p\n",
|
TRACE("class/atom: %S/%04x %p\n",
|
||||||
IS_ATOM(lpClassName) ? NULL : lpClassName,
|
IS_ATOM(lpClassName) ? NULL : lpClassName,
|
||||||
IS_ATOM(lpClassName) ? lpClassName : 0,
|
IS_ATOM(lpClassName) ? lpClassName : 0,
|
||||||
hInstance);
|
hInstance);
|
||||||
|
|
||||||
if (!IS_ATOM(lpClassName))
|
lpszClsVersion = ClassNameToVersion(lpClassName, NULL, NULL, NULL, FALSE);
|
||||||
|
if (lpszClsVersion)
|
||||||
{
|
{
|
||||||
RtlInitUnicodeString(&ClassName,
|
RtlInitUnicodeString(&ClassName, lpszClsVersion);
|
||||||
lpClassName);
|
}
|
||||||
|
else if (!IS_ATOM(lpClassName))
|
||||||
|
{
|
||||||
|
RtlInitUnicodeString(&ClassName, lpClassName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
|
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
|
||||||
|
}
|
||||||
|
|
||||||
return NtUserUnregisterClass(&ClassName,
|
return NtUserUnregisterClass(&ClassName, hInstance, 0);
|
||||||
hInstance,
|
|
||||||
0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
||||||
|
|
||||||
void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id );
|
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 *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
@ -165,13 +166,18 @@ User32CreateWindowEx(DWORD dwExStyle,
|
||||||
{
|
{
|
||||||
LARGE_STRING WindowName;
|
LARGE_STRING WindowName;
|
||||||
LARGE_STRING lstrClassName, *plstrClassName;
|
LARGE_STRING lstrClassName, *plstrClassName;
|
||||||
|
LARGE_STRING lstrClassVersion, *plstrClassVersion;
|
||||||
UNICODE_STRING ClassName;
|
UNICODE_STRING ClassName;
|
||||||
|
UNICODE_STRING ClassVersion;
|
||||||
WNDCLASSEXA wceA;
|
WNDCLASSEXA wceA;
|
||||||
WNDCLASSEXW wceW;
|
WNDCLASSEXW wceW;
|
||||||
HMODULE hLibModule = NULL;
|
HMODULE hLibModule = NULL;
|
||||||
DWORD save_error;
|
DWORD save_error;
|
||||||
BOOL Unicode, ClassFound = FALSE;
|
BOOL Unicode, ClassFound = FALSE;
|
||||||
HWND Handle = NULL;
|
HWND Handle = NULL;
|
||||||
|
LPCWSTR lpszClsVersion;
|
||||||
|
HANDLE pCtx;
|
||||||
|
LPCWSTR lpLibFileName;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
DbgPrint("[window] User32CreateWindowEx style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent);
|
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;
|
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(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
Handle = NtUserCreateWindowEx(dwExStyle,
|
Handle = NtUserCreateWindowEx(dwExStyle,
|
||||||
plstrClassName,
|
plstrClassName,
|
||||||
plstrClassName,
|
plstrClassVersion,
|
||||||
&WindowName,
|
&WindowName,
|
||||||
dwStyle,
|
dwStyle,
|
||||||
x,
|
x,
|
||||||
|
@ -281,12 +301,13 @@ User32CreateWindowEx(DWORD dwExStyle,
|
||||||
dwFlags,
|
dwFlags,
|
||||||
NULL);
|
NULL);
|
||||||
if (Handle) break;
|
if (Handle) break;
|
||||||
|
if (!lpLibFileName) break;
|
||||||
if (!ClassFound)
|
if (!ClassFound)
|
||||||
{
|
{
|
||||||
save_error = GetLastError();
|
save_error = GetLastError();
|
||||||
if ( save_error == ERROR_CANNOT_FIND_WND_CLASS )
|
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;
|
if (ClassFound) continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue