Author: mjansen
Date: Sun Aug 21 18:28:33 2016
New Revision: 72414
URL:
http://svn.reactos.org/svn/reactos?rev=72414&view=rev
Log:
[WIN32SS] Implement windows class versioning, by Sylvain Deverre. CORE-11858 #comment
Committed, thanks!
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] Sun Aug 21 18:28:33 2016
@@ -255,6 +255,9 @@
// comparisons, remove registration of the atom if not zeroed.
if (Class->atomClassName)
IntDeregisterClassAtom(Class->atomClassName);
+ // Dereference non-versioned class name
+ if (Class->atomNVClassName)
+ IntDeregisterClassAtom(Class->atomNVClassName);
if (Class->pdce)
{
@@ -423,22 +426,37 @@
/* Update the base class first */
Class = Class->pclsBase;
-
- if (!IntRegisterClassAtom(ClassName,
- &Atom))
- {
- return FALSE;
- }
-
- IntDeregisterClassAtom(Class->atomClassName);
-
- Class->atomClassName = Atom;
+ if (ClassName->Length > 0)
+ {
+ if (!IntRegisterClassAtom(ClassName,
+ &Atom))
+ {
+ ERR("RegisterClassAtom failed ! %x\n", EngGetLastError());
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (IS_ATOM(ClassName->Buffer))
+ {
+ Atom = (ATOM)((ULONG_PTR)ClassName->Buffer & 0xffff); // XXX: are we
missing refcount here ?
+ }
+ else
+ {
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ }
+
+ IntDeregisterClassAtom(Class->atomNVClassName);
+
+ Class->atomNVClassName = Atom;
/* Update the clones */
Class = Class->pclsClone;
while (Class != NULL)
{
- Class->atomClassName = Atom;
+ Class->atomNVClassName = Atom;
Class = Class->pclsNext;
}
@@ -1000,6 +1018,7 @@
FASTCALL
IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
IN PUNICODE_STRING ClassName,
+ IN PUNICODE_STRING ClassVersion,
IN PUNICODE_STRING MenuName,
IN DWORD fnID,
IN DWORD dwFlags,
@@ -1008,7 +1027,7 @@
{
SIZE_T ClassSize;
PCLS Class = NULL;
- RTL_ATOM Atom;
+ RTL_ATOM Atom, verAtom;
WNDPROC WndProc;
PWSTR pszMenuName = NULL;
NTSTATUS Status = STATUS_SUCCESS;
@@ -1020,6 +1039,14 @@
&Atom))
{
ERR("Failed to register class atom!\n");
+ return NULL;
+ }
+
+ if (!IntRegisterClassAtom(ClassVersion,
+ &verAtom))
+ {
+ ERR("Failed to register version class atom!\n");
+ IntDeregisterClassAtom(Atom);
return NULL;
}
@@ -1054,7 +1081,8 @@
Class->rpdeskParent = Desktop;
Class->pclsBase = Class;
- Class->atomClassName = Atom;
+ Class->atomClassName = verAtom;
+ Class->atomNVClassName = Atom;
Class->fnid = fnID;
Class->CSF_flags = dwFlags;
@@ -1181,6 +1209,7 @@
Class);
Class = NULL;
+ IntDeregisterClassAtom(verAtom);
IntDeregisterClassAtom(Atom);
}
}
@@ -1193,12 +1222,13 @@
UserHeapFree(pszMenuName);
IntDeregisterClassAtom(Atom);
+ IntDeregisterClassAtom(verAtom);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
- TRACE("Created class 0x%p with name %wZ and proc 0x%p for atom 0x%x and
hInstance 0x%p, global %u\n",
- Class, ClassName, Class->lpfnWndProc, Atom, Class->hModule,
Class->Global);
+ TRACE("Created class 0x%p with name %wZ and proc 0x%p for atom 0x%x and version
atom 0x%x and hInstance 0x%p, global %u\n",
+ Class, ClassName, Class->lpfnWndProc, Atom, verAtom, Class->hModule,
Class->Global);
return Class;
}
@@ -1429,6 +1459,7 @@
RTL_ATOM
UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
IN PUNICODE_STRING ClassName,
+ IN PUNICODE_STRING ClassVersion,
IN PUNICODE_STRING MenuName,
IN DWORD fnID,
IN DWORD dwFlags)
@@ -1446,7 +1477,7 @@
pi = pti->ppi;
// Need only to test for two conditions not four....... Fix more whine tests....
- if ( IntGetAtomFromStringOrAtom( ClassName, &ClassAtom) &&
+ if ( IntGetAtomFromStringOrAtom( ClassVersion, &ClassAtom) &&
ClassAtom != (RTL_ATOM)0 &&
!(dwFlags & CSF_SERVERSIDEPROC) ) // Bypass
Server Sides
{
@@ -1481,6 +1512,7 @@
Class = IntCreateClass(lpwcx,
ClassName,
+ ClassVersion,
MenuName,
fnID,
dwFlags,
@@ -1501,7 +1533,7 @@
(void)InterlockedExchangePointer((PVOID*)List,
Class);
- Ret = Class->atomClassName;
+ Ret = Class->atomNVClassName;
}
else
{
@@ -1624,7 +1656,7 @@
/* Query the class name */
Status = RtlQueryAtomInAtomTable(gAtomTable,
- Atom ? Atom : Class->atomClassName,
+ Atom ? Atom :
Class->atomNVClassName,
NULL,
NULL,
szTemp,
@@ -1658,7 +1690,7 @@
/* Query the atom name */
Status = RtlQueryAtomInAtomTable(gAtomTable,
- Atom ? Atom : Class->atomClassName,
+ Atom ? Atom : Class->atomNVClassName,
NULL,
NULL,
ClassName->Buffer,
@@ -2165,7 +2197,7 @@
{
PUNICODE_STRING Value = (PUNICODE_STRING)NewLong;
- Ret = (ULONG_PTR)Class->atomClassName;
+ Ret = (ULONG_PTR)Class->atomNVClassName;
if (!IntSetClassAtom(Class,
Value))
{
@@ -2318,6 +2350,7 @@
wc.hIconSm = NULL;
Class = IntCreateClass( &wc,
+ &ClassName,
&ClassName,
&MenuName,
DefaultServerClasses[i].fiId,
@@ -2366,7 +2399,7 @@
*/
{
WNDCLASSEXW CapturedClassInfo = {0};
- UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0};
+ UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0}, CapturedVersion = {0};
RTL_ATOM Ret = (RTL_ATOM)0;
PPROCESSINFO ppi = GetW32ProcessInfo();
BOOL Exception = FALSE;
@@ -2404,6 +2437,7 @@
sizeof(WNDCLASSEXW));
CapturedName = ProbeForReadUnicodeString(ClassName);
+ CapturedVersion = ProbeForReadUnicodeString(ClsNVersion);
ProbeForRead(pClassMenuName,
sizeof(CLSMENUNAME),
@@ -2439,6 +2473,21 @@
}
}
+ if (CapturedVersion.Length != 0)
+ {
+ ProbeForRead(CapturedVersion.Buffer,
+ CapturedVersion.Length,
+ sizeof(WCHAR));
+ }
+ else
+ {
+ if (!IS_ATOM(CapturedVersion.Buffer))
+ {
+ ERR("NtUserRegisterClassExWOW ClassName Error!\n");
+ goto InvalidParameter;
+ }
+ }
+
if (CapturedMenuName.Length != 0)
{
ProbeForRead(CapturedMenuName.Buffer,
@@ -2475,6 +2524,7 @@
/* Register the class */
Ret = UserRegisterClass(&CapturedClassInfo,
&CapturedName,
+ &CapturedVersion,
&CapturedMenuName,
fnID,
Flags);
@@ -2520,7 +2570,18 @@
/* Probe the parameters */
if (Offset == GCW_ATOM || Offset == GCLP_MENUNAME)
{
- Value = ProbeForReadUnicodeString((PUNICODE_STRING)dwNewLong);
+ /* FIXME: Resource ID can be passed directly without UNICODE_STRING ? */
+ if (IS_ATOM(dwNewLong))
+ {
+ Value.MaximumLength = 0;
+ Value.Length = 0;
+ Value.Buffer = (PWSTR)dwNewLong;
+ }
+ else
+ {
+ Value = ProbeForReadUnicodeString((PUNICODE_STRING)dwNewLong);
+ }
+
if (Value.Length & 1)
{
goto InvalidParameter;
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] Sun Aug 21 18:28:33 2016
@@ -2403,13 +2403,16 @@
NTSTATUS Status;
LARGE_STRING lstrWindowName;
LARGE_STRING lstrClassName;
+ LARGE_STRING lstrClsVersion;
UNICODE_STRING ustrClassName;
+ UNICODE_STRING ustrClsVersion;
CREATESTRUCTW Cs;
HWND hwnd = NULL;
PWND pwnd;
lstrWindowName.Buffer = NULL;
lstrClassName.Buffer = NULL;
+ lstrClsVersion.Buffer = NULL;
ASSERT(plstrWindowName);
@@ -2461,6 +2464,32 @@
ustrClassName.MaximumLength = (USHORT)min(lstrClassName.MaximumLength,
MAXUSHORT);
}
+ /* Check if the class version is an atom */
+ if (IS_ATOM(plstrClsVersion))
+ {
+ /* It is, pass the atom in the UNICODE_STRING */
+ ustrClsVersion.Buffer = (PVOID)plstrClsVersion;
+ ustrClsVersion.Length = 0;
+ ustrClsVersion.MaximumLength = 0;
+ }
+ else
+ {
+ /* It's not, capture the class name */
+ Status = ProbeAndCaptureLargeString(&lstrClsVersion, plstrClsVersion);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("NtUserCreateWindowEx: failed to capture plstrClsVersion\n");
+ /* Set last error, cleanup and return */
+ SetLastNtError(Status);
+ goto cleanup;
+ }
+
+ /* We pass it on as a UNICODE_STRING */
+ ustrClsVersion.Buffer = lstrClsVersion.Buffer;
+ ustrClsVersion.Length = (USHORT)min(lstrClsVersion.Length, MAXUSHORT); // FIXME:
LARGE_STRING truncated
+ ustrClsVersion.MaximumLength = (USHORT)min(lstrClsVersion.MaximumLength,
MAXUSHORT);
+ }
+
/* Fill the CREATESTRUCTW */
/* we will keep here the original parameters */
Cs.style = dwStyle;
@@ -2479,7 +2508,7 @@
UserEnterExclusive();
/* Call the internal function */
- pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName,
acbiBuffer);
+ pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName,
acbiBuffer);
if(!pwnd)
{
@@ -2497,6 +2526,10 @@
if (lstrClassName.Buffer)
{
ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
+ }
+ if (lstrClsVersion.Buffer)
+ {
+ ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
}
return hwnd;
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] Sun Aug 21 18:28:33
2016
@@ -710,7 +710,7 @@
break;
case GCW_ATOM:
- Ret = (ULONG_PTR)Class->atomClassName;
+ Ret = (ULONG_PTR)Class->atomNVClassName;
break;
case GCLP_HCURSOR:
@@ -784,7 +784,7 @@
break;
case GCW_ATOM:
- Ret = (ULONG_PTR)Class->atomClassName;
+ Ret = (ULONG_PTR)Class->atomNVClassName;
break;
case GCLP_HCURSOR:
@@ -1503,7 +1503,7 @@
{
Atom = NtUserRegisterClassExWOW( &WndClass,
&ClassName,
- NULL, //PUNICODE_STRING ClsNVersion,
+ &ClassName, //PUNICODE_STRING ClsNVersion,
&clsMenuName,
fnID,
dwFlags,
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] Sun Aug 21 18:28:33
2016
@@ -267,7 +267,7 @@
{
Handle = NtUserCreateWindowEx(dwExStyle,
plstrClassName,
- NULL,
+ plstrClassName,
&WindowName,
dwStyle,
x,