mirror of
https://github.com/reactos/reactos.git
synced 2025-07-02 23:21:23 +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.
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -267,7 +267,7 @@ User32CreateWindowEx(DWORD dwExStyle,
|
|||
{
|
||||
Handle = NtUserCreateWindowEx(dwExStyle,
|
||||
plstrClassName,
|
||||
NULL,
|
||||
plstrClassName,
|
||||
&WindowName,
|
||||
dwStyle,
|
||||
x,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue