* 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.22 2003/08/05 15:41:03 weiden Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
*/
/* INCLUDES ******************************************************************/
-#include <ddk/ntddk.h>
-#include <win32k/win32k.h>
-#include <napi/win32.h>
-#include <include/class.h>
-#include <include/error.h>
-#include <include/winsta.h>
-#include <include/object.h>
-#include <include/guicheck.h>
-#include <include/window.h>
+#include <w32k.h>
#define NDEBUG
#include <debug.h>
NTSTATUS FASTCALL
InitClassImpl(VOID)
{
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
NTSTATUS FASTCALL
CleanupClassImpl(VOID)
{
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
-NTSTATUS FASTCALL
-ClassReferenceClassByAtom(PWNDCLASS_OBJECT* Class,
- RTL_ATOM Atom)
+inline VOID FASTCALL
+ClassDerefObject(PWNDCLASS_OBJECT Class)
{
- PWNDCLASS_OBJECT Current;
- PLIST_ENTRY CurrentEntry;
- PW32PROCESS Process = PsGetWin32Process();
-
- ExAcquireFastMutexUnsafe (&Process->ClassListLock);
- CurrentEntry = Process->ClassListHead.Flink;
- while (CurrentEntry != &Process->ClassListHead)
- {
- Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, ListEntry);
-
- if (Current->ClassW.lpszClassName == (LPWSTR)(ULONG)Atom)
- {
- *Class = Current;
- ObmReferenceObject(Current);
- ExReleaseFastMutexUnsafe (&Process->ClassListLock);
- return(STATUS_SUCCESS);
- }
-
- CurrentEntry = CurrentEntry->Flink;
- }
- ExReleaseFastMutexUnsafe (&Process->ClassListLock);
-
- return(STATUS_NOT_FOUND);
+ ASSERT(Class->refs >= 1);
+ Class->refs--;
}
-NTSTATUS STDCALL
-ClassReferenceClassByName(PWNDCLASS_OBJECT *Class,
- PWSTR ClassName)
+
+inline VOID FASTCALL
+ClassRefObject(PWNDCLASS_OBJECT Class)
{
- PWINSTATION_OBJECT WinStaObject;
- NTSTATUS Status;
- RTL_ATOM ClassAtom;
-
- if (!ClassName)
- {
- return(STATUS_INVALID_PARAMETER);
- }
-
- Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
- KernelMode,
- 0,
- &WinStaObject);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Validation of window station handle (0x%X) failed\n",
- PROCESS_WINDOW_STATION());
- return(STATUS_UNSUCCESSFUL);
- }
-
- Status = RtlLookupAtomInAtomTable(WinStaObject->AtomTable,
- ClassName,
- &ClassAtom);
-
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(WinStaObject);
- return(Status);
- }
- Status = ClassReferenceClassByAtom(Class,
- ClassAtom);
-
- ObDereferenceObject(WinStaObject);
- return(Status);
+ ASSERT(Class->refs >= 0);
+ Class->refs++;
}
-NTSTATUS FASTCALL
-ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class,
- LPWSTR ClassNameOrAtom)
+
+VOID FASTCALL DestroyClass(PWNDCLASS_OBJECT Class)
{
- NTSTATUS Status;
-
- if (IS_ATOM(ClassNameOrAtom))
- {
- Status = ClassReferenceClassByAtom(Class,
- (RTL_ATOM)((ULONG_PTR)ClassNameOrAtom));
- }
- else
- {
- Status = ClassReferenceClassByName(Class,
- ClassNameOrAtom);
- }
-
- if (!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- }
-
- return(Status);
+ ASSERT(Class->refs == 0);
+
+ RemoveEntryList(&Class->ListEntry);
+ if (Class->hMenu)
+ UserDestroyMenu(Class->hMenu);
+ RtlDeleteAtomFromAtomTable(gAtomTable, Class->Atom);
+ ExFreePool(Class);
}
-DWORD STDCALL
-NtUserGetClassInfo(IN LPWSTR ClassName,
- IN ULONG InfoClass,
- OUT PVOID Info,
- IN ULONG InfoLength,
- OUT PULONG ReturnedLength)
+
+/* clean all process classes. all process windows must cleaned first!! */
+void FASTCALL DestroyProcessClasses(PW32PROCESS Process )
{
- UNIMPLEMENTED;
-
- return(0);
+ PWNDCLASS_OBJECT Class;
+
+ while (!IsListEmpty(&Process->ClassList))
+ {
+ Class = CONTAINING_RECORD(RemoveHeadList(&Process->ClassList), WNDCLASS_OBJECT, ListEntry);
+ DestroyClass(Class);
+ }
}
-ULONG FASTCALL
-W32kGetClassName(struct _WINDOW_OBJECT *WindowObject,
- LPWSTR lpClassName,
- int nMaxCount)
+
+
+
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByAtom(RTL_ATOM Atom, HINSTANCE hInstance)
{
- int length;
- length = wcslen(WindowObject->Class->ClassW.lpszClassName);
- if (length > nMaxCount)
- {
- length = nMaxCount;
- }
- wcsncpy(lpClassName,WindowObject->Class->ClassW.lpszClassName,length+1);
- return length;
+ PWNDCLASS_OBJECT Class;
+ PW32PROCESS Process = PsGetWin32Process();
+
+ LIST_FOR_EACH(Class, &Process->ClassList, WNDCLASS_OBJECT, ListEntry)
+ {
+ if (Class->Atom != Atom) continue;
+
+ if (!hInstance || Class->Global || Class->hInstance == hInstance) return Class;
+ }
+
+ return NULL;
}
-DWORD STDCALL
-NtUserGetClassName(HWND hWnd,
- LPWSTR lpClassName,
- int nMaxCount)
+
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByName(LPCWSTR ClassName, HINSTANCE hInstance)
{
- PWINDOW_OBJECT WindowObject;
- LONG Ret;
-
- WindowObject = W32kGetWindowObject(hWnd);
- if (WindowObject == NULL)
- {
- return(0);
- }
- Ret = W32kGetClassName(WindowObject, lpClassName, nMaxCount);
- W32kReleaseWindowObject(WindowObject);
- return(Ret);
+ NTSTATUS Status;
+ RTL_ATOM Atom;
+
+ if (!ClassName || !PsGetWin32Thread()->Desktop)
+ return FALSE;
+
+ Status = RtlLookupAtomInAtomTable(
+ gAtomTable,
+ (LPWSTR)ClassName,
+ &Atom);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to lookup class atom!\n");
+ return FALSE;
+ }
+
+ return ClassGetClassByAtom(Atom, hInstance);
}
-DWORD STDCALL
-NtUserGetWOWClass(DWORD Unknown0,
- DWORD Unknown1)
+
+PWNDCLASS_OBJECT FASTCALL
+ClassGetClassByNameOrAtom(LPCWSTR ClassNameOrAtom, HINSTANCE hInstance)
{
- UNIMPLEMENTED;
-
- return(0);
+ if (!ClassNameOrAtom) return NULL;
+
+ if (IS_ATOM(ClassNameOrAtom))
+ return ClassGetClassByAtom((RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance);
+ else
+ return ClassGetClassByName(ClassNameOrAtom, hInstance);
}
-PWNDCLASS_OBJECT FASTCALL
-W32kCreateClass(CONST WNDCLASSEXW *lpwcxw,
- CONST WNDCLASSEXA *lpwcxa,
- BOOL bUnicodeClass,
- RTL_ATOM Atom)
+
+static
+BOOL FASTCALL
+IntRegisterClass(
+ CONST WNDCLASSEXW *lpwcx,
+ DWORD Flags,
+ WNDPROC wpExtra,
+ PUNICODE_STRING MenuName,
+ RTL_ATOM Atom,
+ HMENU hMenu)
{
- PWNDCLASS_OBJECT ClassObject;
- WORD objectSize;
- LPWSTR namePtrW;
- LPSTR namePtrA;
- ULONG menulenA=1, menulenW=sizeof(WCHAR);
-
- /* FIXME - how to handle INT resources? */
- /* FIXME - lpszClassName = Atom? is that right */
- if ( bUnicodeClass )
- {
- if ( lpwcxw->lpszMenuName )
- {
- menulenW = (wcslen(lpwcxw->lpszMenuName) + 1) * sizeof(WCHAR);
- RtlUnicodeToMultiByteSize ( &menulenA, lpwcxw->lpszMenuName, menulenW );
- }
- }
- else
- {
- if ( lpwcxa->lpszMenuName )
- {
- menulenA = strlen(lpwcxa->lpszMenuName) + 1;
- RtlMultiByteToUnicodeSize ( &menulenW, lpwcxa->lpszMenuName, menulenA );
- }
- }
- objectSize = sizeof(WNDCLASS_OBJECT);
- ClassObject = ObmCreateObject(NULL, NULL, otClass, objectSize);
- if (ClassObject == 0)
- {
- return(NULL);
- }
-
- if ( bUnicodeClass )
- {
- memmove ( &ClassObject->ClassW, lpwcxw, sizeof(ClassObject->ClassW) );
- memmove ( &ClassObject->ClassA, &ClassObject->ClassW, sizeof(ClassObject->ClassA) );
- ClassObject->ClassA.lpfnWndProc = 0xCCCCCCCC; /*FIXME: figure out what the correct strange value is and what to do with it */
- namePtrW = ExAllocatePool(PagedPool, menulenW);
- if ( lpwcxw->lpszMenuName )
- memmove ( namePtrW, lpwcxw->lpszMenuName, menulenW );
- else
- *namePtrW = L'\0';
- ClassObject->ClassW.lpszMenuName = namePtrW;
- namePtrA = ExAllocatePool(PagedPool, menulenA);
- if ( *namePtrW )
- RtlUnicodeToMultiByteN ( namePtrA, menulenA, NULL, namePtrW, menulenW );
- else
- *namePtrA = '\0';
- ClassObject->ClassA.lpszMenuName = namePtrA;
- }
- else
- {
- memmove ( &ClassObject->ClassA, lpwcxa, sizeof(ClassObject->ClassA) );
- memmove ( &ClassObject->ClassW, &ClassObject->ClassA, sizeof(ClassObject->ClassW) );
- ClassObject->ClassW.lpfnWndProc = 0xCCCCCCCC; /* FIXME: figure out what the correct strange value is and what to do with it */
- namePtrA = ExAllocatePool(PagedPool, menulenA);
- if ( lpwcxa->lpszMenuName )
- memmove ( namePtrA, lpwcxa->lpszMenuName, menulenA );
+ PWNDCLASS_OBJECT Class;
+ ULONG objectSize;
+ BOOL Global;
+
+ ASSERT(lpwcx);
+ ASSERT(Atom);
+ ASSERT(lpwcx->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)
+ {
+ /* can max have one class of each type (global/local) */
+ SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
+ return(FALSE);
+ }
+
+ 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
- *namePtrA = '\0';
- ClassObject->ClassA.lpszMenuName = namePtrA;
- namePtrW = ExAllocatePool(PagedPool, menulenW);
- if ( *namePtrA )
- RtlMultiByteToUnicodeN ( namePtrW, menulenW, NULL, namePtrA, menulenA );
+ {
+ Class->lpfnWndProcW = lpwcx->lpfnWndProc;
+ Class->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
+ }
+ }
+ else
+ {
+ if (Flags & REGISTERCLASS_ANSI)
+ {
+ Class->lpfnWndProcA = lpwcx->lpfnWndProc;
+ Class->lpfnWndProcW = wpExtra;
+ }
else
- *namePtrW = L'\0';
- ClassObject->ClassW.lpszMenuName = namePtrW;
- }
- ClassObject->Unicode = bUnicodeClass;
- ClassObject->ClassW.lpszClassName = (LPWSTR)(ULONG)Atom;
- ClassObject->ClassA.lpszClassName = (LPSTR)(ULONG)Atom;
- return(ClassObject);
+ {
+ Class->lpfnWndProcW = lpwcx->lpfnWndProc;
+ Class->lpfnWndProcA = wpExtra;
+ }
+ }
+
+ if (MenuName->Length == 0)
+ {
+ Class->lpszMenuName.Length =
+ Class->lpszMenuName.MaximumLength = 0;
+ Class->lpszMenuName.Buffer = MenuName->Buffer;
+ }
+ else
+ {
+ Class->lpszMenuName.Length =
+ Class->lpszMenuName.MaximumLength = MenuName->MaximumLength;
+ Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Class->lpszMenuName.MaximumLength, TAG_STRING);
+ RtlCopyUnicodeString(&Class->lpszMenuName, MenuName);
+ }
+
+ /* Extra class data */
+ if (Class->cbClsExtra)
+ Class->ExtraData = (PCHAR)(Class + 1);
+
+ 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
+IntGetClassLong(PWINDOW_OBJECT Window, ULONG Offset, BOOL Ansi)
+{
+ LONG Ret;
+
+ if ((int)Offset >= 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;
+ }
+
+ switch (Offset)
+ {
+ 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;
+ }
+ return(Ret);
+}
+
+static
+void FASTCALL
+co_IntSetClassLong(PWINDOW_OBJECT Window, ULONG Offset, LONG dwNewLong, BOOL Ansi)
+{
+ ASSERT_REFS_CO(Window);
+
+ if ((int)Offset >= 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;
+ }
+
+ 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 *****************************************************************/
+
RTL_ATOM STDCALL
-NtUserRegisterClassExWOW(CONST WNDCLASSEXW *lpwcxw,
- CONST WNDCLASSEXA *lpwcxa,
- BOOL bUnicodeClass,
- DWORD Unknown3,
- DWORD Unknown4,
- DWORD Unknown5)
+NtUserRegisterClassExWOW(
+ CONST WNDCLASSEXW* lpwcx,
+ PUNICODE_STRING ClassName,
+ PUNICODE_STRING ClassNameCopy,//huhuhuhu???
+ PUNICODE_STRING MenuName,
+ WNDPROC wpExtra,
+ DWORD Flags,
+ DWORD Unknown7,
+ HMENU hMenu)
+
/*
* FUNCTION:
* Registers a new class with the window manager
* ARGUMENTS:
- * lpcxw = Win32 extended window class structure (unicode)
- * lpcxa = Win32 extended window class structure (ascii)
- * bUnicodeClass = Wether to send ANSI or unicode strings
+ * lpwcx = Win32 extended window class structure
+ * bUnicodeClass = Whether to send ANSI or unicode strings
* to window procedures
+ * wpExtra = Extra window procedure, if this is not null, its used for the second window procedure for standard controls.
* RETURNS:
* Atom identifying the new class
*/
{
- PWINSTATION_OBJECT WinStaObject;
- PWNDCLASS_OBJECT ClassObject;
- NTSTATUS Status;
- RTL_ATOM Atom;
- LPWSTR classname;
- int len;
-
- DPRINT("About to open window station handle (0x%X)\n",
- PROCESS_WINDOW_STATION());
-
- Status = ValidateWindowStationHandle(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 (bUnicodeClass)
- {
- if (!IS_ATOM(lpwcxw->lpszClassName))
- {
- Status = RtlAddAtomToAtomTable(WinStaObject->AtomTable,
- (LPWSTR)lpwcxw->lpszClassName,
- &Atom);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(WinStaObject);
- DPRINT("Failed adding class name (%wS) to atom table\n",
- lpwcxw->lpszClassName);
- SetLastNtError(Status);
- return((RTL_ATOM)0);
- }
- }
- else
- {
- Atom = (RTL_ATOM)(ULONG)lpwcxw->lpszClassName;
- }
- ClassObject = W32kCreateClass(lpwcxw, NULL, bUnicodeClass, Atom);
- if (ClassObject == NULL)
- {
- if (!IS_ATOM(lpwcxw->lpszClassName))
- {
- RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Atom);
- }
- ObDereferenceObject(WinStaObject);
- DPRINT("Failed creating window class object\n");
- SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
- return((RTL_ATOM)0);
- }
- }
- else
- {
- if (!IS_ATOM(lpwcxa->lpszClassName))
- {
- len = strlen(lpwcxa->lpszClassName);
- classname = ExAllocatePool(PagedPool, ((len + 1) * sizeof(WCHAR)));
- Status = RtlMultiByteToUnicodeN (classname,
- ((len + 1) * sizeof(WCHAR)),
- NULL,
- lpwcxa->lpszClassName,
- len);
- if (!NT_SUCCESS(Status))
- {
- return 0;
- }
- Status = RtlAddAtomToAtomTable(WinStaObject->AtomTable,
- (LPWSTR)classname,
- &Atom);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(WinStaObject);
- DPRINT("Failed adding class name (%wS) to atom table\n",
- lpwcxa->lpszClassName);
- SetLastNtError(Status);
- return((RTL_ATOM)0);
- }
- }
- else
- {
- Atom = (RTL_ATOM)(ULONG)lpwcxa->lpszClassName;
- }
- ClassObject = W32kCreateClass(NULL, lpwcxa, bUnicodeClass, Atom);
- if (ClassObject == NULL)
- {
- if (!IS_ATOM(lpwcxa->lpszClassName))
- {
- RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Atom);
- }
- ObDereferenceObject(WinStaObject);
- DPRINT("Failed creating window class object\n");
- SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
- return((RTL_ATOM)0);
- }
- }
- ExAcquireFastMutex(&PsGetWin32Process()->ClassListLock);
- InsertTailList(&PsGetWin32Process()->ClassListHead, &ClassObject->ListEntry);
- ExReleaseFastMutex(&PsGetWin32Process()->ClassListLock);
-
- ObDereferenceObject(WinStaObject);
-
- return(Atom);
+ WNDCLASSEXW SafeClass;
+ NTSTATUS Status;
+ RTL_ATOM Atom;
+ DECLARE_RETURN(RTL_ATOM);
+
+ DPRINT("Enter NtUserRegisterClassExWOW\n");
+ UserEnterExclusive();
+
+ if (!lpwcx)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( (RTL_ATOM)0);
+ }
+
+ if (Flags & ~REGISTERCLASS_ALL)
+ {
+ SetLastWin32Error(ERROR_INVALID_FLAGS);
+ RETURN( (RTL_ATOM)0);
+ }
+
+ Status = MmCopyFromCaller(&SafeClass, lpwcx, sizeof(WNDCLASSEXW));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( (RTL_ATOM)0);
+ }
+
+ /* Deny negative sizes */
+ if (lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( (RTL_ATOM)0);
+ }
+
+ 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;
}
-ULONG FASTCALL
-W32kGetClassLong(struct _WINDOW_OBJECT *WindowObject, ULONG Offset, BOOL Ansi)
-{
- LONG Ret;
- switch (Offset)
- {
- case GCL_CBWNDEXTRA:
- Ret = WindowObject->Class->ClassW.cbWndExtra;
- break;
- case GCL_CBCLSEXTRA:
- Ret = WindowObject->Class->ClassW.cbClsExtra;
- break;
- case GCL_HBRBACKGROUND:
- Ret = (ULONG)WindowObject->Class->ClassW.hbrBackground;
- break;
- case GCL_HCURSOR:
- Ret = (ULONG)WindowObject->Class->ClassW.hCursor;
- break;
- case GCL_HICON:
- Ret = (ULONG)WindowObject->Class->ClassW.hIcon;
- break;
- case GCL_HICONSM:
- Ret = (ULONG)WindowObject->Class->ClassW.hIconSm;
- break;
- case GCL_HMODULE:
- Ret = (ULONG)WindowObject->Class->ClassW.hInstance;
- break;
- case GCL_MENUNAME:
- if (Ansi)
- {
- Ret = (ULONG)WindowObject->Class->ClassA.lpszMenuName;
- }
- else
- {
- Ret = (ULONG)WindowObject->Class->ClassW.lpszMenuName;
- }
- break;
- case GCL_STYLE:
- Ret = WindowObject->Class->ClassW.style;
- break;
- case GCL_WNDPROC:
- if (WindowObject->Unicode)
- {
- Ret = (ULONG)WindowObject->Class->ClassW.lpfnWndProc;
- }
- else
- {
- Ret = (ULONG)WindowObject->Class->ClassA.lpfnWndProc;
- }
- break;
- default:
- Ret = 0;
- break;
- }
- return(Ret);
-}
+
DWORD STDCALL
NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
{
- PWINDOW_OBJECT WindowObject;
- LONG Ret;
-
- WindowObject = W32kGetWindowObject(hWnd);
- if (WindowObject == NULL)
- {
- return(0);
- }
- Ret = W32kGetClassLong(WindowObject, Offset, Ansi);
- W32kReleaseWindowObject(WindowObject);
- return(Ret);
-}
+ PWINDOW_OBJECT Window;
+ DECLARE_RETURN(DWORD);
-void FASTCALL
-W32kSetClassLong(PWINDOW_OBJECT WindowObject, ULONG Offset, LONG dwNewLong, BOOL Ansi)
-{
- switch (Offset)
- {
- case GCL_CBWNDEXTRA:
- WindowObject->Class->ClassW.cbWndExtra = dwNewLong;
- WindowObject->Class->ClassA.cbWndExtra = dwNewLong;
- break;
- case GCL_CBCLSEXTRA:
- WindowObject->Class->ClassW.cbClsExtra = dwNewLong;
- WindowObject->Class->ClassA.cbClsExtra = dwNewLong;
- break;
- case GCL_HBRBACKGROUND:
- WindowObject->Class->ClassW.hbrBackground = (HBRUSH)dwNewLong;
- WindowObject->Class->ClassA.hbrBackground = (HBRUSH)dwNewLong;
- break;
- case GCL_HCURSOR:
- WindowObject->Class->ClassW.hCursor = (HCURSOR)dwNewLong;
- WindowObject->Class->ClassA.hCursor = (HCURSOR)dwNewLong;
- break;
- case GCL_HICON:
- WindowObject->Class->ClassW.hIcon = (HICON)dwNewLong;
- WindowObject->Class->ClassA.hIcon = (HICON)dwNewLong;
- break;
- case GCL_HICONSM:
- WindowObject->Class->ClassW.hIconSm = (HICON)dwNewLong;
- WindowObject->Class->ClassA.hIconSm = (HICON)dwNewLong;
- break;
- case GCL_HMODULE:
- WindowObject->Class->ClassW.hInstance = (HINSTANCE)dwNewLong;
- WindowObject->Class->ClassA.hInstance = (HINSTANCE)dwNewLong;
- break;
- /*case GCL_MENUNAME:
- WindowObject->Class->Class.lpszMenuName = (LPCWSTR)dwNewLong;
- break;*/
- case GCL_STYLE:
- WindowObject->Class->ClassW.style = dwNewLong;
- WindowObject->Class->ClassA.style = dwNewLong;
- break;
- /*case GCL_WNDPROC:
- WindowObject->Class->Class.lpfnWndProc = (WNDPROC)dwNewLong;
- 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 = W32kGetWindowObject(hWnd);
- if (WindowObject == NULL)
- {
- return(0);
- }
- Ret = W32kGetClassLong(WindowObject, Offset, Ansi);
- W32kSetClassLong(WindowObject, Offset, dwNewLong, Ansi);
- W32kReleaseWindowObject(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;
+ UNIMPLEMENTED;
+ return(0);
+}
- return(0);
+BOOL STDCALL
+NtUserUnregisterClass(
+ LPCWSTR ClassNameOrAtom,
+ HINSTANCE hInstance, /* can be 0 */
+ DWORD Unknown)
+{
+ PWNDCLASS_OBJECT Class;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
+ UserEnterExclusive();
+
+ if (!ClassNameOrAtom)
+ {
+ SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+ RETURN(FALSE);
+ }
+
+ if (!(Class = ClassGetClassByNameOrAtom(ClassNameOrAtom, hInstance)))
+ {
+ SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+ RETURN(FALSE);
+ }
+
+ if (Class->refs)
+ {
+ /* 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);
+ }
+
+ 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
-NtUserUnregisterClass(DWORD Unknown0,
- DWORD Unknown1,
- DWORD Unknown2)
+NtUserGetClassInfo(
+ HINSTANCE hInstance,
+ LPCWSTR lpClassName,
+ LPWNDCLASSEXW lpWndClassEx,
+ BOOL Ansi,
+ DWORD unknown3)
{
- UNIMPLEMENTED;
+ 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)))
+ {
+ SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+ 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;
+}
+
+
- return(0);
+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);
+ }
+
+ 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))
+ {
+ SetLastNtError(Status);
+ RETURN(0);
+ }
+
+ 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 */