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.…
==============================================================================
--- 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…
==============================================================================
--- 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/window…
==============================================================================
--- 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/window…
==============================================================================
--- 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;
}
}