// 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)
{
/* 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;
}
FASTCALL
IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
IN PUNICODE_STRING ClassName,
+ IN PUNICODE_STRING ClassVersion,
IN PUNICODE_STRING MenuName,
IN DWORD fnID,
IN DWORD dwFlags,
{
SIZE_T ClassSize;
PCLS Class = NULL;
- RTL_ATOM Atom;
+ RTL_ATOM Atom, verAtom;
WNDPROC WndProc;
PWSTR pszMenuName = NULL;
NTSTATUS Status = STATUS_SUCCESS;
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)
{
Class->rpdeskParent = Desktop;
Class->pclsBase = Class;
- Class->atomClassName = Atom;
+ Class->atomClassName = verAtom;
+ Class->atomNVClassName = Atom;
Class->fnid = fnID;
Class->CSF_flags = dwFlags;
Class);
Class = NULL;
+ IntDeregisterClassAtom(verAtom);
IntDeregisterClassAtom(Atom);
}
}
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;
}
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)
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
{
Class = IntCreateClass(lpwcx,
ClassName,
+ ClassVersion,
MenuName,
fnID,
dwFlags,
(void)InterlockedExchangePointer((PVOID*)List,
Class);
- Ret = Class->atomClassName;
+ Ret = Class->atomNVClassName;
}
else
{
/* Query the class name */
Status = RtlQueryAtomInAtomTable(gAtomTable,
- Atom ? Atom : Class->atomClassName,
+ Atom ? Atom : Class->atomNVClassName,
NULL,
NULL,
szTemp,
/* Query the atom name */
Status = RtlQueryAtomInAtomTable(gAtomTable,
- Atom ? Atom : Class->atomClassName,
+ Atom ? Atom : Class->atomNVClassName,
NULL,
NULL,
ClassName->Buffer,
{
PUNICODE_STRING Value = (PUNICODE_STRING)NewLong;
- Ret = (ULONG_PTR)Class->atomClassName;
+ Ret = (ULONG_PTR)Class->atomNVClassName;
if (!IntSetClassAtom(Class,
Value))
{
wc.hIconSm = NULL;
Class = IntCreateClass( &wc,
+ &ClassName,
&ClassName,
&MenuName,
DefaultServerClasses[i].fiId,
*/
{
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;
sizeof(WNDCLASSEXW));
CapturedName = ProbeForReadUnicodeString(ClassName);
+ CapturedVersion = ProbeForReadUnicodeString(ClsNVersion);
ProbeForRead(pClassMenuName,
sizeof(CLSMENUNAME),
}
}
+ 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,
/* Register the class */
Ret = UserRegisterClass(&CapturedClassInfo,
&CapturedName,
+ &CapturedVersion,
&CapturedMenuName,
fnID,
Flags);
/* 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;
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);
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;
UserEnterExclusive();
/* Call the internal function */
- pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName, acbiBuffer);
+ pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName, acbiBuffer);
if(!pwnd)
{
{
ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
}
+ if (lstrClsVersion.Buffer)
+ {
+ ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
+ }
return hwnd;
}