mirror of
https://github.com/reactos/reactos.git
synced 2025-07-03 16:31:22 +00:00
[WIN32SS] Implement windows class versioning, by Sylvain Deverre. CORE-11858 #comment Committed, thanks!
svn path=/trunk/; revision=72414
This commit is contained in:
parent
7e6c5db9a4
commit
8b95cbf0e2
4 changed files with 117 additions and 23 deletions
|
@ -255,6 +255,9 @@ IntDestroyClass(IN OUT PCLS Class)
|
||||||
// comparisons, remove registration of the atom if not zeroed.
|
// comparisons, remove registration of the atom if not zeroed.
|
||||||
if (Class->atomClassName)
|
if (Class->atomClassName)
|
||||||
IntDeregisterClassAtom(Class->atomClassName);
|
IntDeregisterClassAtom(Class->atomClassName);
|
||||||
|
// Dereference non-versioned class name
|
||||||
|
if (Class->atomNVClassName)
|
||||||
|
IntDeregisterClassAtom(Class->atomNVClassName);
|
||||||
|
|
||||||
if (Class->pdce)
|
if (Class->pdce)
|
||||||
{
|
{
|
||||||
|
@ -423,22 +426,37 @@ IntSetClassAtom(IN OUT PCLS Class,
|
||||||
|
|
||||||
/* Update the base class first */
|
/* Update the base class first */
|
||||||
Class = Class->pclsBase;
|
Class = Class->pclsBase;
|
||||||
|
if (ClassName->Length > 0)
|
||||||
|
{
|
||||||
if (!IntRegisterClassAtom(ClassName,
|
if (!IntRegisterClassAtom(ClassName,
|
||||||
&Atom))
|
&Atom))
|
||||||
{
|
{
|
||||||
|
ERR("RegisterClassAtom failed ! %x\n", EngGetLastError());
|
||||||
return FALSE;
|
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 */
|
/* Update the clones */
|
||||||
Class = Class->pclsClone;
|
Class = Class->pclsClone;
|
||||||
while (Class != NULL)
|
while (Class != NULL)
|
||||||
{
|
{
|
||||||
Class->atomClassName = Atom;
|
Class->atomNVClassName = Atom;
|
||||||
|
|
||||||
Class = Class->pclsNext;
|
Class = Class->pclsNext;
|
||||||
}
|
}
|
||||||
|
@ -1000,6 +1018,7 @@ PCLS
|
||||||
FASTCALL
|
FASTCALL
|
||||||
IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
|
IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
|
||||||
IN PUNICODE_STRING ClassName,
|
IN PUNICODE_STRING ClassName,
|
||||||
|
IN PUNICODE_STRING ClassVersion,
|
||||||
IN PUNICODE_STRING MenuName,
|
IN PUNICODE_STRING MenuName,
|
||||||
IN DWORD fnID,
|
IN DWORD fnID,
|
||||||
IN DWORD dwFlags,
|
IN DWORD dwFlags,
|
||||||
|
@ -1008,7 +1027,7 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
|
||||||
{
|
{
|
||||||
SIZE_T ClassSize;
|
SIZE_T ClassSize;
|
||||||
PCLS Class = NULL;
|
PCLS Class = NULL;
|
||||||
RTL_ATOM Atom;
|
RTL_ATOM Atom, verAtom;
|
||||||
WNDPROC WndProc;
|
WNDPROC WndProc;
|
||||||
PWSTR pszMenuName = NULL;
|
PWSTR pszMenuName = NULL;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
@ -1023,6 +1042,14 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!IntRegisterClassAtom(ClassVersion,
|
||||||
|
&verAtom))
|
||||||
|
{
|
||||||
|
ERR("Failed to register version class atom!\n");
|
||||||
|
IntDeregisterClassAtom(Atom);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ClassSize = sizeof(*Class) + lpwcx->cbClsExtra;
|
ClassSize = sizeof(*Class) + lpwcx->cbClsExtra;
|
||||||
if (MenuName->Length != 0)
|
if (MenuName->Length != 0)
|
||||||
{
|
{
|
||||||
|
@ -1054,7 +1081,8 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
|
||||||
|
|
||||||
Class->rpdeskParent = Desktop;
|
Class->rpdeskParent = Desktop;
|
||||||
Class->pclsBase = Class;
|
Class->pclsBase = Class;
|
||||||
Class->atomClassName = Atom;
|
Class->atomClassName = verAtom;
|
||||||
|
Class->atomNVClassName = Atom;
|
||||||
Class->fnid = fnID;
|
Class->fnid = fnID;
|
||||||
Class->CSF_flags = dwFlags;
|
Class->CSF_flags = dwFlags;
|
||||||
|
|
||||||
|
@ -1181,6 +1209,7 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
|
||||||
Class);
|
Class);
|
||||||
Class = NULL;
|
Class = NULL;
|
||||||
|
|
||||||
|
IntDeregisterClassAtom(verAtom);
|
||||||
IntDeregisterClassAtom(Atom);
|
IntDeregisterClassAtom(Atom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1193,12 +1222,13 @@ NoMem:
|
||||||
UserHeapFree(pszMenuName);
|
UserHeapFree(pszMenuName);
|
||||||
|
|
||||||
IntDeregisterClassAtom(Atom);
|
IntDeregisterClassAtom(Atom);
|
||||||
|
IntDeregisterClassAtom(verAtom);
|
||||||
|
|
||||||
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
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",
|
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, Class->hModule, Class->Global);
|
Class, ClassName, Class->lpfnWndProc, Atom, verAtom, Class->hModule, Class->Global);
|
||||||
|
|
||||||
return Class;
|
return Class;
|
||||||
}
|
}
|
||||||
|
@ -1429,6 +1459,7 @@ IntGetAndReferenceClass(PUNICODE_STRING ClassName, HINSTANCE hInstance, BOOL bDe
|
||||||
RTL_ATOM
|
RTL_ATOM
|
||||||
UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
|
UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
|
||||||
IN PUNICODE_STRING ClassName,
|
IN PUNICODE_STRING ClassName,
|
||||||
|
IN PUNICODE_STRING ClassVersion,
|
||||||
IN PUNICODE_STRING MenuName,
|
IN PUNICODE_STRING MenuName,
|
||||||
IN DWORD fnID,
|
IN DWORD fnID,
|
||||||
IN DWORD dwFlags)
|
IN DWORD dwFlags)
|
||||||
|
@ -1446,7 +1477,7 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
|
||||||
pi = pti->ppi;
|
pi = pti->ppi;
|
||||||
|
|
||||||
// Need only to test for two conditions not four....... Fix more whine tests....
|
// 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 &&
|
ClassAtom != (RTL_ATOM)0 &&
|
||||||
!(dwFlags & CSF_SERVERSIDEPROC) ) // Bypass Server Sides
|
!(dwFlags & CSF_SERVERSIDEPROC) ) // Bypass Server Sides
|
||||||
{
|
{
|
||||||
|
@ -1481,6 +1512,7 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
|
||||||
|
|
||||||
Class = IntCreateClass(lpwcx,
|
Class = IntCreateClass(lpwcx,
|
||||||
ClassName,
|
ClassName,
|
||||||
|
ClassVersion,
|
||||||
MenuName,
|
MenuName,
|
||||||
fnID,
|
fnID,
|
||||||
dwFlags,
|
dwFlags,
|
||||||
|
@ -1501,7 +1533,7 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
|
||||||
(void)InterlockedExchangePointer((PVOID*)List,
|
(void)InterlockedExchangePointer((PVOID*)List,
|
||||||
Class);
|
Class);
|
||||||
|
|
||||||
Ret = Class->atomClassName;
|
Ret = Class->atomNVClassName;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1624,7 +1656,7 @@ UserGetClassName(IN PCLS Class,
|
||||||
|
|
||||||
/* Query the class name */
|
/* Query the class name */
|
||||||
Status = RtlQueryAtomInAtomTable(gAtomTable,
|
Status = RtlQueryAtomInAtomTable(gAtomTable,
|
||||||
Atom ? Atom : Class->atomClassName,
|
Atom ? Atom : Class->atomNVClassName,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
szTemp,
|
szTemp,
|
||||||
|
@ -1658,7 +1690,7 @@ UserGetClassName(IN PCLS Class,
|
||||||
|
|
||||||
/* Query the atom name */
|
/* Query the atom name */
|
||||||
Status = RtlQueryAtomInAtomTable(gAtomTable,
|
Status = RtlQueryAtomInAtomTable(gAtomTable,
|
||||||
Atom ? Atom : Class->atomClassName,
|
Atom ? Atom : Class->atomNVClassName,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
ClassName->Buffer,
|
ClassName->Buffer,
|
||||||
|
@ -2165,7 +2197,7 @@ UserSetClassLongPtr(IN PCLS Class,
|
||||||
{
|
{
|
||||||
PUNICODE_STRING Value = (PUNICODE_STRING)NewLong;
|
PUNICODE_STRING Value = (PUNICODE_STRING)NewLong;
|
||||||
|
|
||||||
Ret = (ULONG_PTR)Class->atomClassName;
|
Ret = (ULONG_PTR)Class->atomNVClassName;
|
||||||
if (!IntSetClassAtom(Class,
|
if (!IntSetClassAtom(Class,
|
||||||
Value))
|
Value))
|
||||||
{
|
{
|
||||||
|
@ -2318,6 +2350,7 @@ UserRegisterSystemClasses(VOID)
|
||||||
wc.hIconSm = NULL;
|
wc.hIconSm = NULL;
|
||||||
|
|
||||||
Class = IntCreateClass( &wc,
|
Class = IntCreateClass( &wc,
|
||||||
|
&ClassName,
|
||||||
&ClassName,
|
&ClassName,
|
||||||
&MenuName,
|
&MenuName,
|
||||||
DefaultServerClasses[i].fiId,
|
DefaultServerClasses[i].fiId,
|
||||||
|
@ -2366,7 +2399,7 @@ NtUserRegisterClassExWOW(
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
WNDCLASSEXW CapturedClassInfo = {0};
|
WNDCLASSEXW CapturedClassInfo = {0};
|
||||||
UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0};
|
UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0}, CapturedVersion = {0};
|
||||||
RTL_ATOM Ret = (RTL_ATOM)0;
|
RTL_ATOM Ret = (RTL_ATOM)0;
|
||||||
PPROCESSINFO ppi = GetW32ProcessInfo();
|
PPROCESSINFO ppi = GetW32ProcessInfo();
|
||||||
BOOL Exception = FALSE;
|
BOOL Exception = FALSE;
|
||||||
|
@ -2404,6 +2437,7 @@ NtUserRegisterClassExWOW(
|
||||||
sizeof(WNDCLASSEXW));
|
sizeof(WNDCLASSEXW));
|
||||||
|
|
||||||
CapturedName = ProbeForReadUnicodeString(ClassName);
|
CapturedName = ProbeForReadUnicodeString(ClassName);
|
||||||
|
CapturedVersion = ProbeForReadUnicodeString(ClsNVersion);
|
||||||
|
|
||||||
ProbeForRead(pClassMenuName,
|
ProbeForRead(pClassMenuName,
|
||||||
sizeof(CLSMENUNAME),
|
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)
|
if (CapturedMenuName.Length != 0)
|
||||||
{
|
{
|
||||||
ProbeForRead(CapturedMenuName.Buffer,
|
ProbeForRead(CapturedMenuName.Buffer,
|
||||||
|
@ -2475,6 +2524,7 @@ InvalidParameter:
|
||||||
/* Register the class */
|
/* Register the class */
|
||||||
Ret = UserRegisterClass(&CapturedClassInfo,
|
Ret = UserRegisterClass(&CapturedClassInfo,
|
||||||
&CapturedName,
|
&CapturedName,
|
||||||
|
&CapturedVersion,
|
||||||
&CapturedMenuName,
|
&CapturedMenuName,
|
||||||
fnID,
|
fnID,
|
||||||
Flags);
|
Flags);
|
||||||
|
@ -2519,8 +2569,19 @@ NtUserSetClassLong(HWND hWnd,
|
||||||
|
|
||||||
/* Probe the parameters */
|
/* Probe the parameters */
|
||||||
if (Offset == GCW_ATOM || Offset == GCLP_MENUNAME)
|
if (Offset == GCW_ATOM || Offset == GCLP_MENUNAME)
|
||||||
|
{
|
||||||
|
/* 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);
|
Value = ProbeForReadUnicodeString((PUNICODE_STRING)dwNewLong);
|
||||||
|
}
|
||||||
|
|
||||||
if (Value.Length & 1)
|
if (Value.Length & 1)
|
||||||
{
|
{
|
||||||
goto InvalidParameter;
|
goto InvalidParameter;
|
||||||
|
|
|
@ -2403,13 +2403,16 @@ NtUserCreateWindowEx(
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
LARGE_STRING lstrWindowName;
|
LARGE_STRING lstrWindowName;
|
||||||
LARGE_STRING lstrClassName;
|
LARGE_STRING lstrClassName;
|
||||||
|
LARGE_STRING lstrClsVersion;
|
||||||
UNICODE_STRING ustrClassName;
|
UNICODE_STRING ustrClassName;
|
||||||
|
UNICODE_STRING ustrClsVersion;
|
||||||
CREATESTRUCTW Cs;
|
CREATESTRUCTW Cs;
|
||||||
HWND hwnd = NULL;
|
HWND hwnd = NULL;
|
||||||
PWND pwnd;
|
PWND pwnd;
|
||||||
|
|
||||||
lstrWindowName.Buffer = NULL;
|
lstrWindowName.Buffer = NULL;
|
||||||
lstrClassName.Buffer = NULL;
|
lstrClassName.Buffer = NULL;
|
||||||
|
lstrClsVersion.Buffer = NULL;
|
||||||
|
|
||||||
ASSERT(plstrWindowName);
|
ASSERT(plstrWindowName);
|
||||||
|
|
||||||
|
@ -2461,6 +2464,32 @@ NtUserCreateWindowEx(
|
||||||
ustrClassName.MaximumLength = (USHORT)min(lstrClassName.MaximumLength, MAXUSHORT);
|
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 */
|
/* Fill the CREATESTRUCTW */
|
||||||
/* we will keep here the original parameters */
|
/* we will keep here the original parameters */
|
||||||
Cs.style = dwStyle;
|
Cs.style = dwStyle;
|
||||||
|
@ -2479,7 +2508,7 @@ NtUserCreateWindowEx(
|
||||||
UserEnterExclusive();
|
UserEnterExclusive();
|
||||||
|
|
||||||
/* Call the internal function */
|
/* Call the internal function */
|
||||||
pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName, acbiBuffer);
|
pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName, acbiBuffer);
|
||||||
|
|
||||||
if(!pwnd)
|
if(!pwnd)
|
||||||
{
|
{
|
||||||
|
@ -2498,6 +2527,10 @@ cleanup:
|
||||||
{
|
{
|
||||||
ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
|
ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
|
||||||
}
|
}
|
||||||
|
if (lstrClsVersion.Buffer)
|
||||||
|
{
|
||||||
|
ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
return hwnd;
|
return hwnd;
|
||||||
}
|
}
|
||||||
|
|
|
@ -710,7 +710,7 @@ IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GCW_ATOM:
|
case GCW_ATOM:
|
||||||
Ret = (ULONG_PTR)Class->atomClassName;
|
Ret = (ULONG_PTR)Class->atomNVClassName;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GCLP_HCURSOR:
|
case GCLP_HCURSOR:
|
||||||
|
@ -784,7 +784,7 @@ IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GCW_ATOM:
|
case GCW_ATOM:
|
||||||
Ret = (ULONG_PTR)Class->atomClassName;
|
Ret = (ULONG_PTR)Class->atomNVClassName;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GCLP_HCURSOR:
|
case GCLP_HCURSOR:
|
||||||
|
@ -1503,7 +1503,7 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
|
||||||
{
|
{
|
||||||
Atom = NtUserRegisterClassExWOW( &WndClass,
|
Atom = NtUserRegisterClassExWOW( &WndClass,
|
||||||
&ClassName,
|
&ClassName,
|
||||||
NULL, //PUNICODE_STRING ClsNVersion,
|
&ClassName, //PUNICODE_STRING ClsNVersion,
|
||||||
&clsMenuName,
|
&clsMenuName,
|
||||||
fnID,
|
fnID,
|
||||||
dwFlags,
|
dwFlags,
|
||||||
|
|
|
@ -267,7 +267,7 @@ User32CreateWindowEx(DWORD dwExStyle,
|
||||||
{
|
{
|
||||||
Handle = NtUserCreateWindowEx(dwExStyle,
|
Handle = NtUserCreateWindowEx(dwExStyle,
|
||||||
plstrClassName,
|
plstrClassName,
|
||||||
NULL,
|
plstrClassName,
|
||||||
&WindowName,
|
&WindowName,
|
||||||
dwStyle,
|
dwStyle,
|
||||||
x,
|
x,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue