[WIN32SS] Implement windows class versioning, by Sylvain Deverre. CORE-11858 #comment Committed, thanks!

svn path=/trunk/; revision=72414
This commit is contained in:
Mark Jansen 2016-08-21 18:28:33 +00:00
parent 7e6c5db9a4
commit 8b95cbf0e2
4 changed files with 117 additions and 23 deletions

View file

@ -255,6 +255,9 @@ IntDestroyClass(IN OUT PCLS Class)
// 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 @@ IntSetClassAtom(IN OUT PCLS Class,
/* Update the base class first */
Class = Class->pclsBase;
if (!IntRegisterClassAtom(ClassName,
&Atom))
if (ClassName->Length > 0)
{
return FALSE;
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->atomClassName);
IntDeregisterClassAtom(Class->atomNVClassName);
Class->atomClassName = Atom;
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 @@ PCLS
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 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
{
SIZE_T ClassSize;
PCLS Class = NULL;
RTL_ATOM Atom;
RTL_ATOM Atom, verAtom;
WNDPROC WndProc;
PWSTR pszMenuName = NULL;
NTSTATUS Status = STATUS_SUCCESS;
@ -1023,6 +1042,14 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
return NULL;
}
if (!IntRegisterClassAtom(ClassVersion,
&verAtom))
{
ERR("Failed to register version class atom!\n");
IntDeregisterClassAtom(Atom);
return NULL;
}
ClassSize = sizeof(*Class) + lpwcx->cbClsExtra;
if (MenuName->Length != 0)
{
@ -1054,7 +1081,8 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
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 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
Class);
Class = NULL;
IntDeregisterClassAtom(verAtom);
IntDeregisterClassAtom(Atom);
}
}
@ -1193,12 +1222,13 @@ NoMem:
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 @@ IntGetAndReferenceClass(PUNICODE_STRING ClassName, HINSTANCE hInstance, BOOL bDe
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 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
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 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
Class = IntCreateClass(lpwcx,
ClassName,
ClassVersion,
MenuName,
fnID,
dwFlags,
@ -1501,7 +1533,7 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
(void)InterlockedExchangePointer((PVOID*)List,
Class);
Ret = Class->atomClassName;
Ret = Class->atomNVClassName;
}
else
{
@ -1624,7 +1656,7 @@ UserGetClassName(IN PCLS Class,
/* Query the class name */
Status = RtlQueryAtomInAtomTable(gAtomTable,
Atom ? Atom : Class->atomClassName,
Atom ? Atom : Class->atomNVClassName,
NULL,
NULL,
szTemp,
@ -1658,7 +1690,7 @@ UserGetClassName(IN PCLS Class,
/* Query the atom name */
Status = RtlQueryAtomInAtomTable(gAtomTable,
Atom ? Atom : Class->atomClassName,
Atom ? Atom : Class->atomNVClassName,
NULL,
NULL,
ClassName->Buffer,
@ -2165,7 +2197,7 @@ UserSetClassLongPtr(IN PCLS Class,
{
PUNICODE_STRING Value = (PUNICODE_STRING)NewLong;
Ret = (ULONG_PTR)Class->atomClassName;
Ret = (ULONG_PTR)Class->atomNVClassName;
if (!IntSetClassAtom(Class,
Value))
{
@ -2318,6 +2350,7 @@ UserRegisterSystemClasses(VOID)
wc.hIconSm = NULL;
Class = IntCreateClass( &wc,
&ClassName,
&ClassName,
&MenuName,
DefaultServerClasses[i].fiId,
@ -2366,7 +2399,7 @@ NtUserRegisterClassExWOW(
*/
{
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 @@ NtUserRegisterClassExWOW(
sizeof(WNDCLASSEXW));
CapturedName = ProbeForReadUnicodeString(ClassName);
CapturedVersion = ProbeForReadUnicodeString(ClsNVersion);
ProbeForRead(pClassMenuName,
sizeof(CLSMENUNAME),
@ -2439,6 +2473,21 @@ NtUserRegisterClassExWOW(
}
}
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 @@ InvalidParameter:
/* Register the class */
Ret = UserRegisterClass(&CapturedClassInfo,
&CapturedName,
&CapturedVersion,
&CapturedMenuName,
fnID,
Flags);
@ -2520,7 +2570,18 @@ NtUserSetClassLong(HWND hWnd,
/* 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;

View file

@ -2403,13 +2403,16 @@ NtUserCreateWindowEx(
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 @@ NtUserCreateWindowEx(
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 @@ NtUserCreateWindowEx(
UserEnterExclusive();
/* Call the internal function */
pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName, acbiBuffer);
pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName, acbiBuffer);
if(!pwnd)
{
@ -2498,6 +2527,10 @@ cleanup:
{
ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
}
if (lstrClsVersion.Buffer)
{
ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
}
return hwnd;
}

View file

@ -710,7 +710,7 @@ IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex)
break;
case GCW_ATOM:
Ret = (ULONG_PTR)Class->atomClassName;
Ret = (ULONG_PTR)Class->atomNVClassName;
break;
case GCLP_HCURSOR:
@ -784,7 +784,7 @@ IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex)
break;
case GCW_ATOM:
Ret = (ULONG_PTR)Class->atomClassName;
Ret = (ULONG_PTR)Class->atomNVClassName;
break;
case GCLP_HCURSOR:
@ -1503,7 +1503,7 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
{
Atom = NtUserRegisterClassExWOW( &WndClass,
&ClassName,
NULL, //PUNICODE_STRING ClsNVersion,
&ClassName, //PUNICODE_STRING ClsNVersion,
&clsMenuName,
fnID,
dwFlags,

View file

@ -267,7 +267,7 @@ User32CreateWindowEx(DWORD dwExStyle,
{
Handle = NtUserCreateWindowEx(dwExStyle,
plstrClassName,
NULL,
plstrClassName,
&WindowName,
dwStyle,
x,