* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: class.c,v 1.54 2004/05/16 19:31:09 navaraf Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
NTSTATUS FASTCALL
InitClassImpl(VOID)
{
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
NTSTATUS FASTCALL
CleanupClassImpl(VOID)
{
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
-BOOL FASTCALL
-ClassReferenceClassByAtom(
- PWNDCLASS_OBJECT* Class,
- RTL_ATOM Atom,
- HINSTANCE hInstance)
+
+inline VOID FASTCALL
+ClassDerefObject(PWNDCLASS_OBJECT Class)
{
- PWNDCLASS_OBJECT Current, BestMatch = NULL;
- PLIST_ENTRY CurrentEntry;
- PW32PROCESS Process = PsGetWin32Process();
-
- IntLockProcessClasses(Process);
- CurrentEntry = Process->ClassListHead.Flink;
- while (CurrentEntry != &Process->ClassListHead)
- {
- Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, ListEntry);
-
- if (Current->Atom == Atom && Current->hInstance == hInstance)
- {
- *Class = Current;
- ObmReferenceObject(Current);
- IntUnLockProcessClasses(Process);
- return TRUE;
- }
+ ASSERT(Class->refs >= 1);
+ Class->refs--;
+}
- if (Current->Atom == Atom && Current->Global)
- BestMatch = Current;
- CurrentEntry = CurrentEntry->Flink;
- }
- IntUnLockProcessClasses(Process);
+inline VOID FASTCALL
+ClassRefObject(PWNDCLASS_OBJECT Class)
+{
+ ASSERT(Class->refs >= 0);
+ Class->refs++;
+}
+
+
+VOID FASTCALL DestroyClass(PWNDCLASS_OBJECT Class)
+{
+ ASSERT(Class->refs == 0);
+
+ RemoveEntryList(&Class->ListEntry);
+ if (Class->hMenu)
+ UserDestroyMenu(Class->hMenu);
+ RtlDeleteAtomFromAtomTable(gAtomTable, Class->Atom);
+ ExFreePool(Class);
+}
+
+
+/* clean all process classes. all process windows must cleaned first!! */
+void FASTCALL DestroyProcessClasses(PW32PROCESS Process )
+{
+ PWNDCLASS_OBJECT Class;
- if (BestMatch != NULL)
+ while (!IsListEmpty(&Process->ClassList))
{
- *Class = BestMatch;
- ObmReferenceObject(BestMatch);
- return TRUE;
+ Class = CONTAINING_RECORD(RemoveHeadList(&Process->ClassList), WNDCLASS_OBJECT, ListEntry);
+ DestroyClass(Class);
}
-
- return FALSE;
}
-BOOL FASTCALL
-ClassReferenceClassByName(
- PWNDCLASS_OBJECT *Class,
- LPCWSTR ClassName,
- HINSTANCE hInstance)
-{
- PWINSTATION_OBJECT WinStaObject;
- NTSTATUS Status;
- BOOL Found;
- RTL_ATOM ClassAtom;
- if (!ClassName)
- return FALSE;
- Status = IntValidateWindowStationHandle(
- PROCESS_WINDOW_STATION(),
- KernelMode,
- 0,
- &WinStaObject);
- if (!NT_SUCCESS(Status))
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByAtom(RTL_ATOM Atom, HINSTANCE hInstance)
+{
+ PWNDCLASS_OBJECT Class;
+ PW32PROCESS Process = PsGetWin32Process();
+
+ LIST_FOR_EACH(Class, &Process->ClassList, WNDCLASS_OBJECT, ListEntry)
{
- DPRINT("Validation of window station handle (0x%X) failed\n",
- PROCESS_WINDOW_STATION());
- return FALSE;
+ if (Class->Atom != Atom) continue;
+
+ if (!hInstance || Class->Global || Class->hInstance == hInstance) return Class;
}
+
+ return NULL;
+}
+
+
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByName(LPCWSTR ClassName, HINSTANCE hInstance)
+{
+ NTSTATUS Status;
+ RTL_ATOM Atom;
+
+ if (!ClassName || !PsGetWin32Thread()->Desktop)
+ return FALSE;
Status = RtlLookupAtomInAtomTable(
- WinStaObject->AtomTable,
- (LPWSTR)ClassName,
- &ClassAtom);
+ gAtomTable,
+ (LPWSTR)ClassName,
+ &Atom);
if (!NT_SUCCESS(Status))
{
- ObDereferenceObject(WinStaObject);
+ DPRINT1("Failed to lookup class atom!\n");
return FALSE;
}
- Found = ClassReferenceClassByAtom(Class, ClassAtom, hInstance);
- ObDereferenceObject(WinStaObject);
-
- return Found;
+ return ClassGetClassByAtom(Atom, hInstance);
}
-BOOL FASTCALL
-ClassReferenceClassByNameOrAtom(
- PWNDCLASS_OBJECT *Class,
- LPCWSTR ClassNameOrAtom,
- HINSTANCE hInstance)
-{
- BOOL Found;
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByNameOrAtom(LPCWSTR ClassNameOrAtom, HINSTANCE hInstance)
+{
+ if (!ClassNameOrAtom) return NULL;
+
if (IS_ATOM(ClassNameOrAtom))
- Found = ClassReferenceClassByAtom(Class, (RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance);
+ return ClassGetClassByAtom((RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance);
else
- Found = ClassReferenceClassByName(Class, ClassNameOrAtom, hInstance);
-
- return Found;
+ return ClassGetClassByName(ClassNameOrAtom, hInstance);
}
-DWORD STDCALL
-NtUserGetClassInfo(
- HINSTANCE hInstance,
- LPCWSTR lpClassName,
- LPWNDCLASSEXW lpWndClassEx,
- BOOL Ansi,
- DWORD unknown3)
+
+static
+BOOL FASTCALL
+IntRegisterClass(
+ CONST WNDCLASSEXW *lpwcx,
+ DWORD Flags,
+ WNDPROC wpExtra,
+ PUNICODE_STRING MenuName,
+ RTL_ATOM Atom,
+ HMENU hMenu)
{
PWNDCLASS_OBJECT Class;
- RTL_ATOM Atom;
+ ULONG objectSize;
+ BOOL Global;
- if (IS_ATOM(lpClassName))
- DPRINT("NtUserGetClassInfo - %x (%lx)\n", lpClassName, hInstance);
- else
- DPRINT("NtUserGetClassInfo - %S (%lx)\n", lpClassName, hInstance);
+ ASSERT(lpwcx);
+ ASSERT(Atom);
+ ASSERT(lpwcx->hInstance);
- if (!ClassReferenceClassByNameOrAtom(&Class, lpClassName, hInstance))
+ Global = (Flags & REGISTERCLASS_SYSTEM) || (lpwcx->style & CS_GLOBALCLASS);
+
+ /* Check for double registration of the class. */
+ Class = ClassGetClassByAtom(Atom, lpwcx->hInstance);
+ if (Class && Global == Class->Global)
{
- SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
- return 0;
+ /* can max have one class of each type (global/local) */
+ SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
+ return(FALSE);
}
- lpWndClassEx->cbSize = sizeof(LPWNDCLASSEXW);
- lpWndClassEx->style = Class->style;
- if (Ansi)
- lpWndClassEx->lpfnWndProc = Class->lpfnWndProcA;
+ objectSize = sizeof(WNDCLASS_OBJECT) + lpwcx->cbClsExtra;
+
+ //FIXME: allocate in session heap (or possibly desktop heap)
+ Class = ExAllocatePool(PagedPool, objectSize);
+ if (!Class)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return(FALSE);
+ }
+ RtlZeroMemory(Class, objectSize);
+
+ Class->cbSize = lpwcx->cbSize;
+ Class->style = lpwcx->style;
+ Class->cbClsExtra = lpwcx->cbClsExtra;
+ Class->cbWndExtra = lpwcx->cbWndExtra;
+ Class->hInstance = lpwcx->hInstance;
+ Class->hIcon = lpwcx->hIcon;
+ Class->hCursor = lpwcx->hCursor;
+ Class->hMenu = hMenu;
+ Class->hbrBackground = lpwcx->hbrBackground;
+ Class->Unicode = !(Flags & REGISTERCLASS_ANSI);
+ Class->Global = Global;
+ Class->hIconSm = lpwcx->hIconSm;
+ Class->Atom = Atom;
+
+ if (wpExtra == NULL)
+ {
+ if (Flags & REGISTERCLASS_ANSI)
+ {
+ Class->lpfnWndProcA = lpwcx->lpfnWndProc;
+ Class->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
+ }
+ else
+ {
+ Class->lpfnWndProcW = lpwcx->lpfnWndProc;
+ Class->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
+ }
+ }
else
- lpWndClassEx->lpfnWndProc = Class->lpfnWndProcW;
- lpWndClassEx->cbClsExtra = Class->cbClsExtra;
- lpWndClassEx->cbWndExtra = Class->cbWndExtra;
- /* This is not typo, we're really not going to use Class->hInstance here. */
- lpWndClassEx->hInstance = hInstance;
- lpWndClassEx->hIcon = Class->hIcon;
- lpWndClassEx->hCursor = Class->hCursor;
- lpWndClassEx->hbrBackground = Class->hbrBackground;
- if (Class->lpszMenuName)
{
- if (!IS_INTRESOURCE((LPCWSTR)Class->lpszMenuName))
- RtlCopyUnicodeString((PUNICODE_STRING)lpWndClassEx->lpszMenuName, Class->lpszMenuName);
+ if (Flags & REGISTERCLASS_ANSI)
+ {
+ Class->lpfnWndProcA = lpwcx->lpfnWndProc;
+ Class->lpfnWndProcW = wpExtra;
+ }
else
- lpWndClassEx->lpszMenuName = (LPCWSTR)Class->lpszMenuName;
+ {
+ Class->lpfnWndProcW = lpwcx->lpfnWndProc;
+ Class->lpfnWndProcA = wpExtra;
+ }
+ }
+
+ if (MenuName->Length == 0)
+ {
+ Class->lpszMenuName.Length =
+ Class->lpszMenuName.MaximumLength = 0;
+ Class->lpszMenuName.Buffer = MenuName->Buffer;
}
else
- lpWndClassEx->lpszMenuName = (LPCWSTR)NULL;
- lpWndClassEx->lpszClassName = lpClassName;
- lpWndClassEx->hIconSm = Class->hIconSm;
- Atom = Class->Atom;
+ {
+ Class->lpszMenuName.Length =
+ Class->lpszMenuName.MaximumLength = MenuName->MaximumLength;
+ Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Class->lpszMenuName.MaximumLength, TAG_STRING);
+ RtlCopyUnicodeString(&Class->lpszMenuName, MenuName);
+ }
- ObmDereferenceObject(Class);
+ /* Extra class data */
+ if (Class->cbClsExtra)
+ Class->ExtraData = (PCHAR)(Class + 1);
- return Atom;
+ if (Global)
+ {
+ /* global classes go last (incl. system classes) */
+ InsertTailList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
+ }
+ else
+ {
+ /* local classes have priority so we put them first */
+ InsertHeadList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
+ }
+
+ return TRUE;
}
+
ULONG FASTCALL
-IntGetClassName(struct _WINDOW_OBJECT *WindowObject, LPWSTR lpClassName,
- ULONG nMaxCount)
+IntGetClassLong(PWINDOW_OBJECT Window, ULONG Offset, BOOL Ansi)
{
- ULONG Length;
- LPWSTR Name;
- PWINSTATION_OBJECT WinStaObject;
- NTSTATUS Status;
+ LONG Ret;
- Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
- KernelMode, 0, &WinStaObject);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Validation of window station handle (0x%X) failed\n",
- PROCESS_WINDOW_STATION());
- return 0;
- }
- Length = 0;
- Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,
- WindowObject->Class->Atom, NULL, NULL, NULL, &Length);
- Name = ExAllocatePoolWithTag(NonPagedPool, Length + sizeof(UNICODE_NULL), TAG_STRING);
- Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,
- WindowObject->Class->Atom, NULL, NULL, Name, &Length);
- if (!NT_SUCCESS(Status))
+ if ((int)Offset >= 0)
{
- DPRINT("IntGetClassName: RtlQueryAtomInAtomTable failed\n");
- return 0;
+ DPRINT("GetClassLong(%x, %d)\n", Window->hSelf, Offset);
+ if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ Ret = *((LONG *)(Window->Class->ExtraData + Offset));
+ DPRINT("Result: %x\n", Ret);
+ return Ret;
}
- Length /= sizeof(WCHAR);
- if (Length > nMaxCount)
+
+ switch (Offset)
{
- Length = nMaxCount;
+ case GCL_CBWNDEXTRA:
+ Ret = Window->Class->cbWndExtra;
+ break;
+ case GCL_CBCLSEXTRA:
+ Ret = Window->Class->cbClsExtra;
+ break;
+ case GCL_HBRBACKGROUND:
+ Ret = (ULONG)Window->Class->hbrBackground;
+ break;
+ case GCL_HCURSOR:
+ Ret = (ULONG)Window->Class->hCursor;
+ break;
+ case GCL_HICON:
+ Ret = (ULONG)Window->Class->hIcon;
+ break;
+ case GCL_HICONSM:
+ Ret = (ULONG)Window->Class->hIconSm;
+ break;
+ case GCL_HMODULE:
+ Ret = (ULONG)Window->Class->hInstance;
+ break;
+ case GCL_MENUNAME:
+ Ret = (ULONG)Window->Class->lpszMenuName.Buffer;
+ break;
+ case GCL_STYLE:
+ Ret = Window->Class->style;
+ break;
+ case GCL_WNDPROC:
+ if (Ansi)
+ {
+ Ret = (ULONG)Window->Class->lpfnWndProcA;
+ }
+ else
+ {
+ Ret = (ULONG)Window->Class->lpfnWndProcW;
+ }
+ break;
+ case GCW_ATOM:
+ Ret = Window->Class->Atom;
+ break;
+ default:
+ Ret = 0;
+ break;
}
- wcsncpy(lpClassName, Name, Length);
- /* FIXME: Check buffer size before doing this! */
- *(lpClassName + Length) = 0;
- ExFreePool(Name);
- ObDereferenceObject(WinStaObject);
-
- return Length;
+ return(Ret);
}
-DWORD STDCALL
-NtUserGetClassName (
- HWND hWnd,
- LPWSTR lpClassName,
- ULONG nMaxCount)
+static
+void FASTCALL
+co_IntSetClassLong(PWINDOW_OBJECT Window, ULONG Offset, LONG dwNewLong, BOOL Ansi)
{
- PWINDOW_OBJECT WindowObject;
- LONG Length;
+ ASSERT_REFS_CO(Window);
- WindowObject = IntGetWindowObject(hWnd);
- if (WindowObject == NULL)
+ if ((int)Offset >= 0)
{
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return 0;
+ DPRINT("SetClassLong(%x, %d, %x)\n", Window->hSelf, Offset, dwNewLong);
+ if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return;
+ }
+ *((LONG *)(Window->Class->ExtraData + Offset)) = dwNewLong;
+ return;
}
- Length = IntGetClassName(WindowObject, lpClassName, nMaxCount);
- IntReleaseWindowObject(WindowObject);
- return Length;
-}
-DWORD STDCALL
-NtUserGetWOWClass(DWORD Unknown0,
- DWORD Unknown1)
-{
- UNIMPLEMENTED;
- return(0);
+ switch (Offset)
+ {
+ case GCL_CBWNDEXTRA:
+ Window->Class->cbWndExtra = dwNewLong;
+ break;
+ case GCL_CBCLSEXTRA:
+ Window->Class->cbClsExtra = dwNewLong;
+ break;
+ case GCL_HBRBACKGROUND:
+ Window->Class->hbrBackground = (HBRUSH)dwNewLong;
+ break;
+ case GCL_HCURSOR:
+ Window->Class->hCursor = (HCURSOR)dwNewLong;
+ break;
+ case GCL_HICON:
+ Window->Class->hIcon = (HICON)dwNewLong;
+
+ if (!IntGetOwner(Window) && !IntGetParent(Window))
+ {
+ co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) Window->hSelf);
+ }
+ break;
+ case GCL_HICONSM:
+ Window->Class->hIconSm = (HICON)dwNewLong;
+ break;
+ case GCL_HMODULE:
+ Window->Class->hInstance = (HINSTANCE)dwNewLong;
+ break;
+ case GCL_MENUNAME:
+ if (Window->Class->lpszMenuName.MaximumLength)
+ RtlFreeUnicodeString(&Window->Class->lpszMenuName);
+ if (!IS_INTRESOURCE(dwNewLong))
+ {
+ Window->Class->lpszMenuName.Length =
+ Window->Class->lpszMenuName.MaximumLength = ((PUNICODE_STRING)dwNewLong)->MaximumLength;
+ Window->Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Window->Class->lpszMenuName.MaximumLength, TAG_STRING);
+ RtlCopyUnicodeString(&Window->Class->lpszMenuName, (PUNICODE_STRING)dwNewLong);
+ }
+ else
+ {
+ Window->Class->lpszMenuName.Length =
+ Window->Class->lpszMenuName.MaximumLength = 0;
+ Window->Class->lpszMenuName.Buffer = (LPWSTR)dwNewLong;
+ }
+ break;
+ case GCL_STYLE:
+ Window->Class->style = dwNewLong;
+ break;
+ case GCL_WNDPROC:
+ if (Ansi)
+ {
+ Window->Class->lpfnWndProcA = (WNDPROC)dwNewLong;
+ Window->Class->lpfnWndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,FALSE);
+ Window->Class->Unicode = FALSE;
+ }
+ else
+ {
+ Window->Class->lpfnWndProcW = (WNDPROC)dwNewLong;
+ Window->Class->lpfnWndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,TRUE);
+ Window->Class->Unicode = TRUE;
+ }
+ break;
+ }
}
+/* SYSCALLS *****************************************************************/
-PWNDCLASS_OBJECT FASTCALL
-IntCreateClass(
- CONST WNDCLASSEXW *lpwcx,
- DWORD Flags,
- WNDPROC wpExtra,
- PUNICODE_STRING MenuName,
- RTL_ATOM Atom)
-{
- PWNDCLASS_OBJECT ClassObject;
- ULONG objectSize;
- BOOL Global;
-
- Global = !(Flags & REGISTERCLASS_SYSTEM) ? ClassObject->style & CS_GLOBALCLASS : TRUE;
-
- /* Check for double registration of the class. */
- if (PsGetWin32Process() != NULL)
- {
- if (ClassReferenceClassByAtom(&ClassObject, Atom, lpwcx->hInstance))
- {
- /*
- * NOTE: We may also get a global class from
- * ClassReferenceClassByAtom. This simple check
- * prevents that we fail valid request.
- */
- if (ClassObject->hInstance == lpwcx->hInstance)
- {
- SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
- ObmDereferenceObject(ClassObject);
- return(NULL);
- }
- }
- }
-
- objectSize = sizeof(WNDCLASS_OBJECT) + lpwcx->cbClsExtra;
- ClassObject = ObmCreateObject(NULL, NULL, otClass, objectSize);
- if (ClassObject == 0)
- {
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
- return(NULL);
- }
-
- ClassObject->cbSize = lpwcx->cbSize;
- ClassObject->style = lpwcx->style;
- ClassObject->cbClsExtra = lpwcx->cbClsExtra;
- ClassObject->cbWndExtra = lpwcx->cbWndExtra;
- ClassObject->hInstance = lpwcx->hInstance;
- ClassObject->hIcon = lpwcx->hIcon;
- ClassObject->hCursor = lpwcx->hCursor;
- ClassObject->hbrBackground = lpwcx->hbrBackground;
- ClassObject->Unicode = !(Flags & REGISTERCLASS_ANSI);
- ClassObject->Global = Global;
- ClassObject->hIconSm = lpwcx->hIconSm;
- ClassObject->Atom = Atom;
- if (wpExtra == NULL) {
- if (Flags & REGISTERCLASS_ANSI)
- {
- ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
- ClassObject->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
- }
- else
- {
- ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
- ClassObject->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
- }
- } else {
- if (Flags & REGISTERCLASS_ANSI)
- {
- ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
- ClassObject->lpfnWndProcW = wpExtra;
- }
- else
- {
- ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
- ClassObject->lpfnWndProcA = wpExtra;
- }
- }
- if (MenuName->Length == 0)
- {
- ClassObject->lpszMenuName = (PUNICODE_STRING)MenuName->Buffer;
- }
- else
- {
- ClassObject->lpszMenuName = ExAllocatePoolWithTag(NonPagedPool, sizeof(UNICODE_STRING), TAG_STRING);
- RtlCreateUnicodeString(ClassObject->lpszMenuName, MenuName->Buffer);
- }
- /* Extra class data */
- if (ClassObject->cbClsExtra != 0)
- {
- ClassObject->ExtraData = (PCHAR)(ClassObject + 1);
- RtlZeroMemory(ClassObject->ExtraData, (ULONG)ClassObject->cbClsExtra);
- }
- else
- {
- ClassObject->ExtraData = NULL;
- }
-
- return(ClassObject);
-}
RTL_ATOM STDCALL
NtUserRegisterClassExWOW(
CONST WNDCLASSEXW* lpwcx,
PUNICODE_STRING ClassName,
- PUNICODE_STRING ClassNameCopy,
+ PUNICODE_STRING ClassNameCopy,//huhuhuhu???
PUNICODE_STRING MenuName,
- WNDPROC wpExtra, /* FIXME: Windows uses this parameter for something different. */
+ WNDPROC wpExtra,
DWORD Flags,
- DWORD Unknown7)
+ DWORD Unknown7,
+ HMENU hMenu)
/*
* FUNCTION:
*/
{
WNDCLASSEXW SafeClass;
- PWINSTATION_OBJECT WinStaObject;
- PWNDCLASS_OBJECT ClassObject;
NTSTATUS Status;
RTL_ATOM Atom;
-
+ DECLARE_RETURN(RTL_ATOM);
+
+ DPRINT("Enter NtUserRegisterClassExWOW\n");
+ UserEnterExclusive();
+
if (!lpwcx)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return (RTL_ATOM)0;
+ RETURN( (RTL_ATOM)0);
}
if (Flags & ~REGISTERCLASS_ALL)
{
SetLastWin32Error(ERROR_INVALID_FLAGS);
- return (RTL_ATOM)0;
+ RETURN( (RTL_ATOM)0);
}
Status = MmCopyFromCaller(&SafeClass, lpwcx, sizeof(WNDCLASSEXW));
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
- return (RTL_ATOM)0;
+ RETURN( (RTL_ATOM)0);
}
-
+
/* Deny negative sizes */
if (lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return (RTL_ATOM)0;
- }
-
- DPRINT("About to open window station handle (0x%X)\n",
- PROCESS_WINDOW_STATION());
- Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
- KernelMode,
- 0,
- &WinStaObject);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Validation of window station handle (0x%X) failed\n",
- PROCESS_WINDOW_STATION());
- return((RTL_ATOM)0);
- }
- if (ClassName->Length)
- {
- DPRINT("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer);
- /* FIXME - Safely copy/verify the buffer first!!! */
- Status = RtlAddAtomToAtomTable(WinStaObject->AtomTable,
- ClassName->Buffer,
- &Atom);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(WinStaObject);
- DPRINT("Failed adding class name (%S) to atom table\n",
- ClassName->Buffer);
- SetLastNtError(Status);
- return((RTL_ATOM)0);
- }
- }
- else
- {
- Atom = (RTL_ATOM)(ULONG)ClassName->Buffer;
- }
- ClassObject = IntCreateClass(&SafeClass, Flags, wpExtra, MenuName, Atom);
- if (ClassObject == NULL)
- {
- if (ClassName->Length)
- {
- RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Atom);
- }
- ObDereferenceObject(WinStaObject);
- DPRINT("Failed creating window class object\n");
- return((RTL_ATOM)0);
- }
- IntLockProcessClasses(PsGetWin32Process());
- InsertTailList(&PsGetWin32Process()->ClassListHead, &ClassObject->ListEntry);
- IntUnLockProcessClasses(PsGetWin32Process());
- ObDereferenceObject(WinStaObject);
- return(Atom);
-}
+ RETURN( (RTL_ATOM)0);
+ }
-ULONG FASTCALL
-IntGetClassLong(struct _WINDOW_OBJECT *WindowObject, ULONG Offset, BOOL Ansi)
-{
- LONG Ret;
-
- if ((int)Offset >= 0)
- {
- DPRINT("GetClassLong(%x, %d)\n", WindowObject->Self, Offset);
- if ((Offset + sizeof(LONG)) > WindowObject->Class->cbClsExtra)
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return 0;
- }
- Ret = *((LONG *)(WindowObject->Class->ExtraData + Offset));
- DPRINT("Result: %x\n", Ret);
- return Ret;
- }
-
- switch (Offset)
- {
- case GCL_CBWNDEXTRA:
- Ret = WindowObject->Class->cbWndExtra;
- break;
- case GCL_CBCLSEXTRA:
- Ret = WindowObject->Class->cbClsExtra;
- break;
- case GCL_HBRBACKGROUND:
- Ret = (ULONG)WindowObject->Class->hbrBackground;
- break;
- case GCL_HCURSOR:
- Ret = (ULONG)WindowObject->Class->hCursor;
- break;
- case GCL_HICON:
- Ret = (ULONG)WindowObject->Class->hIcon;
- break;
- case GCL_HICONSM:
- Ret = (ULONG)WindowObject->Class->hIconSm;
- break;
- case GCL_HMODULE:
- Ret = (ULONG)WindowObject->Class->hInstance;
- break;
- case GCL_MENUNAME:
- Ret = (ULONG)WindowObject->Class->lpszMenuName;
- break;
- case GCL_STYLE:
- Ret = WindowObject->Class->style;
- break;
- case GCL_WNDPROC:
- if (Ansi)
- {
- Ret = (ULONG)WindowObject->Class->lpfnWndProcA;
- }
- else
- {
- Ret = (ULONG)WindowObject->Class->lpfnWndProcW;
- }
- break;
- default:
- Ret = 0;
- break;
- }
- return(Ret);
+ if (!lpwcx->hInstance)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( (RTL_ATOM)0);
+ }
+
+ //FIXME: make ClassName ptr the atom, not buffer
+ if (ClassName->Length > 0)
+ {
+ DPRINT("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer);
+ /* FIXME - Safely copy/verify the buffer first!!! */
+ Status = RtlAddAtomToAtomTable(gAtomTable,
+ ClassName->Buffer,
+ &Atom);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed adding class name (%S) to atom table\n",
+ ClassName->Buffer);
+ SetLastNtError(Status);
+ RETURN((RTL_ATOM)0);
+ }
+ }
+ else
+ {
+ Atom = (RTL_ATOM)(ULONG)ClassName->Buffer;
+ }
+
+ if (!Atom)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN(0);
+ }
+
+ if (!IntRegisterClass(&SafeClass, Flags, wpExtra, MenuName, Atom, hMenu))
+ {
+ if (ClassName->Length)
+ {
+ RtlDeleteAtomFromAtomTable(gAtomTable, Atom);
+ }
+ DPRINT("Failed creating window class object\n");
+ RETURN((RTL_ATOM)0);
+ }
+
+ RETURN(Atom);
+
+CLEANUP:
+ DPRINT("Leave NtUserRegisterClassExWOW, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
+
+
DWORD STDCALL
NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
{
- PWINDOW_OBJECT WindowObject;
- LONG Ret;
-
- WindowObject = IntGetWindowObject(hWnd);
- if (WindowObject == NULL)
- {
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return 0;
- }
- Ret = IntGetClassLong(WindowObject, Offset, Ansi);
- IntReleaseWindowObject(WindowObject);
- return(Ret);
-}
+ PWINDOW_OBJECT Window;
+ DECLARE_RETURN(DWORD);
-void FASTCALL
-IntSetClassLong(PWINDOW_OBJECT WindowObject, ULONG Offset, LONG dwNewLong, BOOL Ansi)
-{
- PUNICODE_STRING str;
-
- if ((int)Offset >= 0)
- {
- DPRINT("SetClassLong(%x, %d, %x)\n", WindowObject->Self, Offset, dwNewLong);
- if ((Offset + sizeof(LONG)) > WindowObject->Class->cbClsExtra)
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return;
- }
- *((LONG *)(WindowObject->Class->ExtraData + Offset)) = dwNewLong;
- return;
- }
-
- switch (Offset)
- {
- case GCL_CBWNDEXTRA:
- WindowObject->Class->cbWndExtra = dwNewLong;
- break;
- case GCL_CBCLSEXTRA:
- WindowObject->Class->cbClsExtra = dwNewLong;
- break;
- case GCL_HBRBACKGROUND:
- WindowObject->Class->hbrBackground = (HBRUSH)dwNewLong;
- break;
- case GCL_HCURSOR:
- WindowObject->Class->hCursor = (HCURSOR)dwNewLong;
- break;
- case GCL_HICON:
- WindowObject->Class->hIcon = (HICON)dwNewLong;
- break;
- case GCL_HICONSM:
- WindowObject->Class->hIconSm = (HICON)dwNewLong;
- break;
- case GCL_HMODULE:
- WindowObject->Class->hInstance = (HINSTANCE)dwNewLong;
- break;
- case GCL_MENUNAME:
- if (!IS_INTRESOURCE(dwNewLong))
- {
- str = ExAllocatePoolWithTag(PagedPool,sizeof(UNICODE_STRING)+((PUNICODE_STRING)dwNewLong)->Length, TAG_STRING);
- memcpy(str,(PUNICODE_STRING)dwNewLong,sizeof(UNICODE_STRING)+((PUNICODE_STRING)dwNewLong)->Length);
- WindowObject->Class->lpszMenuName = str;
- }
- else
- {
- WindowObject->Class->lpszMenuName = (PUNICODE_STRING)dwNewLong;
- }
- break;
- case GCL_STYLE:
- WindowObject->Class->style = dwNewLong;
- break;
- case GCL_WNDPROC:
- if (Ansi)
- {
- WindowObject->Class->lpfnWndProcA = (WNDPROC)dwNewLong;
- WindowObject->Class->lpfnWndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,FALSE);
- WindowObject->Class->Unicode = FALSE;
- }
- else
- {
- WindowObject->Class->lpfnWndProcW = (WNDPROC)dwNewLong;
- WindowObject->Class->lpfnWndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,TRUE);
- WindowObject->Class->Unicode = TRUE;
- }
- break;
- }
+ DPRINT("Enter NtUserGetClassLong\n");
+ UserEnterExclusive();
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(0);
+ }
+
+ RETURN(IntGetClassLong(Window, Offset, Ansi));
+
+CLEANUP:
+ DPRINT("Leave NtUserGetClassLong, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
+
+
DWORD STDCALL
NtUserSetClassLong(HWND hWnd,
- DWORD Offset,
- LONG dwNewLong,
- BOOL Ansi)
+ DWORD Offset,
+ LONG dwNewLong,
+ BOOL Ansi)
{
- PWINDOW_OBJECT WindowObject;
- LONG Ret;
-
- WindowObject = IntGetWindowObject(hWnd);
- if (WindowObject == NULL)
- {
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return 0;
- }
- Ret = IntGetClassLong(WindowObject, Offset, Ansi);
- IntSetClassLong(WindowObject, Offset, dwNewLong, Ansi);
- IntReleaseWindowObject(WindowObject);
- return(Ret);
+ PWINDOW_OBJECT Window;
+ LONG Ret;
+ USER_REFERENCE_ENTRY Ref;
+ DECLARE_RETURN(DWORD);
+
+ DPRINT("Enter NtUserSetClassLong\n");
+ UserEnterExclusive();
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(0);
+ }
+
+ UserRefObjectCo(Window, &Ref);
+
+ Ret = IntGetClassLong(Window, Offset, Ansi);
+ co_IntSetClassLong(Window, Offset, dwNewLong, Ansi);
+
+ UserDerefObjectCo(Window);
+
+ RETURN(Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserSetClassLong, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
DWORD STDCALL
NtUserSetClassWord(DWORD Unknown0,
- DWORD Unknown1,
- DWORD Unknown2)
+ DWORD Unknown1,
+ DWORD Unknown2)
{
- UNIMPLEMENTED;
- return(0);
+ UNIMPLEMENTED;
+ return(0);
}
BOOL STDCALL
NtUserUnregisterClass(
LPCWSTR ClassNameOrAtom,
- HINSTANCE hInstance,
- DWORD Unknown)
+ HINSTANCE hInstance, /* can be 0 */
+ DWORD Unknown)
{
- NTSTATUS Status;
PWNDCLASS_OBJECT Class;
- PWINSTATION_OBJECT WinStaObject;
-
- DPRINT("NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
-
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
+ UserEnterExclusive();
+
if (!ClassNameOrAtom)
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return FALSE;
+ SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+ RETURN(FALSE);
}
-
- Status = IntValidateWindowStationHandle(
- PROCESS_WINDOW_STATION(),
- KernelMode,
- 0,
- &WinStaObject);
- if (!NT_SUCCESS(Status))
+
+ if (!(Class = ClassGetClassByNameOrAtom(ClassNameOrAtom, hInstance)))
{
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return FALSE;
+ SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+ RETURN(FALSE);
}
- if (!ClassReferenceClassByNameOrAtom(&Class, ClassNameOrAtom, hInstance))
+ if (Class->refs)
{
- SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
- return FALSE;
+ /* NOTE: the class will not be freed when its refs become 0 ie. no more
+ * windows are using it. I dunno why that is but its how Windows does it (and Wine).
+ * The class will hang around until the process exit. -Gunnar
+ */
+ SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
+ RETURN(FALSE);
}
-
- if (Class->hInstance && Class->hInstance != hInstance)
+
+ DestroyClass(Class);
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserUnregisterClass, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/* NOTE: for system classes hInstance is not NULL here, but User32Instance */
+DWORD STDCALL
+NtUserGetClassInfo(
+ HINSTANCE hInstance,
+ LPCWSTR lpClassName,
+ LPWNDCLASSEXW lpWndClassEx,
+ BOOL Ansi,
+ DWORD unknown3)
+{
+ PWNDCLASS_OBJECT Class;
+ RTL_ATOM Atom;
+ DECLARE_RETURN(DWORD);
+
+ if (IS_ATOM(lpClassName))
+ DPRINT("NtUserGetClassInfo - %x (%lx)\n", lpClassName, hInstance);
+ else
+ DPRINT("NtUserGetClassInfo - %S (%lx)\n", lpClassName, hInstance);
+
+ UserEnterExclusive();
+
+ if (!hInstance)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN(0);
+ }
+
+ if (!(Class = ClassGetClassByNameOrAtom(lpClassName, hInstance)))
{
- ObmDereferenceObject(Class);
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
- return FALSE;
+ RETURN(0);
+ }
+
+ lpWndClassEx->cbSize = sizeof(WNDCLASSEXW);
+ lpWndClassEx->style = Class->style;
+ if (Ansi)
+ lpWndClassEx->lpfnWndProc = Class->lpfnWndProcA;
+ else
+ lpWndClassEx->lpfnWndProc = Class->lpfnWndProcW;
+ lpWndClassEx->cbClsExtra = Class->cbClsExtra;
+ lpWndClassEx->cbWndExtra = Class->cbWndExtra;
+ /* This is not typo, we're really not going to use Class->hInstance here. */
+ /* Well, i think its wrong so i changed it -Gunnar */
+ lpWndClassEx->hInstance = Class->hInstance;
+ lpWndClassEx->hIcon = Class->hIcon;
+ lpWndClassEx->hCursor = Class->hCursor;
+ lpWndClassEx->hbrBackground = Class->hbrBackground;
+ if (Class->lpszMenuName.MaximumLength)
+ RtlCopyUnicodeString((PUNICODE_STRING)lpWndClassEx->lpszMenuName, &Class->lpszMenuName);
+ else
+ lpWndClassEx->lpszMenuName = Class->lpszMenuName.Buffer;
+ lpWndClassEx->lpszClassName = lpClassName;
+ lpWndClassEx->hIconSm = Class->hIconSm;
+ Atom = Class->Atom;
+
+ RETURN(Atom);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetClassInfo, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+
+DWORD STDCALL
+NtUserGetClassName (
+ HWND hWnd,
+ LPWSTR lpClassName,
+ ULONG nMaxCount /* in TCHARS */
+ )
+{
+ PWINDOW_OBJECT Window;
+ DECLARE_RETURN(DWORD);
+ NTSTATUS Status;
+
+ UserEnterShared();
+ DPRINT("Enter NtUserGetClassName\n");
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(0);
}
-
- if (ObmGetReferenceCount(Class) > 2)
+
+ nMaxCount *= sizeof(WCHAR);
+
+ //FIXME: wrap in SEH to protect lpClassName access
+ Status = RtlQueryAtomInAtomTable(gAtomTable,
+ Window->Class->Atom, NULL, NULL,
+ lpClassName, &nMaxCount);
+ if (!NT_SUCCESS(Status))
{
- ObmDereferenceObject(Class);
- SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
- return FALSE;
+ SetLastNtError(Status);
+ RETURN(0);
}
-
- /* Dereference the ClassReferenceClassByNameOrAtom() call */
- ObmDereferenceObject(Class);
-
- RemoveEntryList(&Class->ListEntry);
- RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Class->Atom);
- ObDereferenceObject(WinStaObject);
-
- /* Free the object */
- ObmDereferenceObject(Class);
-
- return TRUE;
+ RETURN(nMaxCount / sizeof(WCHAR));
+
+CLEANUP:
+ DPRINT("Leave NtUserGetClassName, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+DWORD STDCALL
+NtUserGetWOWClass(DWORD Unknown0,
+ DWORD Unknown1)
+{
+ UNIMPLEMENTED;
+ return(0);
}
+
/* EOF */