2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: class.c,v 1.44 2003/12/07 23:01:01 weiden Exp $
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Window classes
24 * FILE: subsys/win32k/ntuser/class.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
29 /* INCLUDES ******************************************************************/
31 #include <ddk/ntddk.h>
32 #include <win32k/win32k.h>
33 #include <napi/win32.h>
34 #include <include/class.h>
35 #include <include/error.h>
36 #include <include/winsta.h>
37 #include <include/object.h>
38 #include <include/guicheck.h>
39 #include <include/window.h>
40 #include <include/color.h>
45 /* FUNCTIONS *****************************************************************/
50 return(STATUS_SUCCESS
);
54 CleanupClassImpl(VOID
)
56 return(STATUS_SUCCESS
);
61 ClassReferenceClassByAtom(PWNDCLASS_OBJECT
* Class
,
64 PWNDCLASS_OBJECT Current
;
65 PLIST_ENTRY CurrentEntry
;
66 PW32PROCESS Process
= PsGetWin32Process();
68 ExAcquireFastMutexUnsafe (&Process
->ClassListLock
);
69 CurrentEntry
= Process
->ClassListHead
.Flink
;
70 while (CurrentEntry
!= &Process
->ClassListHead
)
72 Current
= CONTAINING_RECORD(CurrentEntry
, WNDCLASS_OBJECT
, ListEntry
);
74 if (Current
->Atom
== Atom
)
77 ObmReferenceObject(Current
);
78 ExReleaseFastMutexUnsafe (&Process
->ClassListLock
);
79 return(STATUS_SUCCESS
);
82 CurrentEntry
= CurrentEntry
->Flink
;
84 ExReleaseFastMutexUnsafe (&Process
->ClassListLock
);
86 return(STATUS_NOT_FOUND
);
90 ClassReferenceClassByName(PWNDCLASS_OBJECT
*Class
,
93 PWINSTATION_OBJECT WinStaObject
;
99 return(STATUS_INVALID_PARAMETER
);
102 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
106 if (!NT_SUCCESS(Status
))
108 DPRINT("Validation of window station handle (0x%X) failed\n",
109 PROCESS_WINDOW_STATION());
110 return(STATUS_UNSUCCESSFUL
);
113 Status
= RtlLookupAtomInAtomTable(WinStaObject
->AtomTable
,
117 if (!NT_SUCCESS(Status
))
119 ObDereferenceObject(WinStaObject
);
122 Status
= ClassReferenceClassByAtom(Class
,
125 ObDereferenceObject(WinStaObject
);
130 ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT
*Class
,
131 LPCWSTR ClassNameOrAtom
)
135 if (IS_ATOM(ClassNameOrAtom
))
137 Status
= ClassReferenceClassByAtom(Class
,
138 (RTL_ATOM
)((ULONG_PTR
)ClassNameOrAtom
));
142 Status
= ClassReferenceClassByName(Class
,
146 if (!NT_SUCCESS(Status
))
148 SetLastNtError(Status
);
155 NtUserGetClassInfo(HINSTANCE hInstance
, LPCWSTR lpClassName
,
156 LPWNDCLASSEXW lpWndClassEx
, BOOL Ansi
, DWORD unknown3
)
158 PWNDCLASS_OBJECT Class
;
162 Status
= ClassReferenceClassByNameOrAtom(&Class
, lpClassName
);
163 if (!NT_SUCCESS(Status
))
165 SetLastNtError(Status
);
168 lpWndClassEx
->cbSize
= sizeof(LPWNDCLASSEXW
);
169 lpWndClassEx
->style
= Class
->style
;
171 lpWndClassEx
->lpfnWndProc
= Class
->lpfnWndProcA
;
173 lpWndClassEx
->lpfnWndProc
= Class
->lpfnWndProcW
;
174 lpWndClassEx
->cbClsExtra
= Class
->cbClsExtra
;
175 lpWndClassEx
->cbWndExtra
= Class
->cbWndExtra
;
176 lpWndClassEx
->hInstance
= Class
->hInstance
;
177 lpWndClassEx
->hIcon
= Class
->hIcon
;
178 lpWndClassEx
->hCursor
= Class
->hCursor
;
179 lpWndClassEx
->hbrBackground
= Class
->hbrBackground
;
180 if (Class
->lpszMenuName
)
182 if (!IS_INTRESOURCE((LPCWSTR
)Class
->lpszMenuName
))
183 RtlCopyUnicodeString((PUNICODE_STRING
)lpWndClassEx
->lpszMenuName
, Class
->lpszMenuName
);
185 lpWndClassEx
->lpszMenuName
= (LPCWSTR
)Class
->lpszMenuName
;
188 lpWndClassEx
->lpszMenuName
= (LPCWSTR
)NULL
;
189 lpWndClassEx
->lpszClassName
= lpClassName
;
190 lpWndClassEx
->hIconSm
= Class
->hIconSm
;
193 ObmDereferenceObject(Class
);
199 IntGetClassName(struct _WINDOW_OBJECT
*WindowObject
, LPWSTR lpClassName
,
204 PWINSTATION_OBJECT WinStaObject
;
207 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
208 KernelMode
, 0, &WinStaObject
);
209 if (!NT_SUCCESS(Status
))
211 DPRINT("Validation of window station handle (0x%X) failed\n",
212 PROCESS_WINDOW_STATION());
216 Status
= RtlQueryAtomInAtomTable(WinStaObject
->AtomTable
,
217 WindowObject
->Class
->Atom
, NULL
, NULL
, Name
, &Length
);
218 Name
= ExAllocatePool(NonPagedPool
, Length
+ sizeof(UNICODE_NULL
));
219 Status
= RtlQueryAtomInAtomTable(WinStaObject
->AtomTable
,
220 WindowObject
->Class
->Atom
, NULL
, NULL
, Name
, &Length
);
221 if (!NT_SUCCESS(Status
))
223 DPRINT("IntGetClassName: RtlQueryAtomInAtomTable failed\n");
226 Length
/= sizeof(WCHAR
);
227 if (Length
> nMaxCount
)
231 wcsncpy(lpClassName
, Name
, Length
);
232 /* FIXME: Check buffer size before doing this! */
233 *(lpClassName
+ Length
) = 0;
235 ObDereferenceObject(WinStaObject
);
246 PWINDOW_OBJECT WindowObject
;
249 WindowObject
= IntGetWindowObject(hWnd
);
250 if (WindowObject
== NULL
)
252 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
255 Length
= IntGetClassName(WindowObject
, lpClassName
, nMaxCount
);
256 IntReleaseWindowObject(WindowObject
);
261 NtUserGetWOWClass(DWORD Unknown0
,
268 PWNDCLASS_OBJECT FASTCALL
269 IntCreateClass(CONST WNDCLASSEXW
*lpwcx
,
274 PWNDCLASS_OBJECT ClassObject
;
278 /* Check for double registration of the class. */
279 if (PsGetWin32Process() != NULL
)
281 Status
= ClassReferenceClassByAtom(&ClassObject
, Atom
);
282 if (NT_SUCCESS(Status
))
284 ObmDereferenceObject(ClassObject
);
289 objectSize
= sizeof(WNDCLASS_OBJECT
) + lpwcx
->cbClsExtra
;
290 ClassObject
= ObmCreateObject(NULL
, NULL
, otClass
, objectSize
);
291 if (ClassObject
== 0)
296 ClassObject
->cbSize
= lpwcx
->cbSize
;
297 ClassObject
->style
= lpwcx
->style
;
298 ClassObject
->cbClsExtra
= lpwcx
->cbClsExtra
;
299 ClassObject
->cbWndExtra
= lpwcx
->cbWndExtra
;
300 ClassObject
->hInstance
= lpwcx
->hInstance
;
301 ClassObject
->hIcon
= lpwcx
->hIcon
;
302 ClassObject
->hCursor
= lpwcx
->hCursor
;
303 ClassObject
->hbrBackground
= lpwcx
->hbrBackground
;
304 ClassObject
->Unicode
= bUnicodeClass
;
305 ClassObject
->hIconSm
= lpwcx
->hIconSm
;
306 ClassObject
->Atom
= Atom
;
310 ClassObject
->lpfnWndProcW
= lpwcx
->lpfnWndProc
;
311 ClassObject
->lpfnWndProcA
= (WNDPROC
)IntAddWndProcHandle(lpwcx
->lpfnWndProc
,TRUE
);
315 ClassObject
->lpfnWndProcA
= lpwcx
->lpfnWndProc
;
316 ClassObject
->lpfnWndProcW
= (WNDPROC
)IntAddWndProcHandle(lpwcx
->lpfnWndProc
,FALSE
);
321 ClassObject
->lpfnWndProcW
= lpwcx
->lpfnWndProc
;
322 ClassObject
->lpfnWndProcA
= wpExtra
;
326 ClassObject
->lpfnWndProcA
= lpwcx
->lpfnWndProc
;
327 ClassObject
->lpfnWndProcW
= wpExtra
;
330 if (IS_INTRESOURCE(lpwcx
->lpszMenuName
))
332 ClassObject
->lpszMenuName
= (PUNICODE_STRING
)lpwcx
->lpszMenuName
;
336 ClassObject
->lpszMenuName
= ExAllocatePool(NonPagedPool
,sizeof(UNICODE_STRING
));
337 RtlCreateUnicodeString(ClassObject
->lpszMenuName
,(LPWSTR
)lpwcx
->lpszMenuName
);
339 /* Extra class data */
340 if (ClassObject
->cbClsExtra
!= 0)
342 ClassObject
->ExtraData
= (PCHAR
)(ClassObject
+ 1);
343 RtlZeroMemory(ClassObject
->ExtraData
, ClassObject
->cbClsExtra
);
347 ClassObject
->ExtraData
= NULL
;
354 NtUserRegisterClassExWOW(
355 CONST WNDCLASSEXW
*lpwcx
,
363 * Registers a new class with the window manager
365 * lpwcx = Win32 extended window class structure
366 * bUnicodeClass = Whether to send ANSI or unicode strings
367 * to window procedures
368 * wpExtra = Extra window procedure, if this is not null, its used for the second window procedure for standard controls.
370 * Atom identifying the new class
373 PWINSTATION_OBJECT WinStaObject
;
374 PWNDCLASS_OBJECT ClassObject
;
377 DPRINT("About to open window station handle (0x%X)\n",
378 PROCESS_WINDOW_STATION());
379 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
383 if (!NT_SUCCESS(Status
))
385 DPRINT("Validation of window station handle (0x%X) failed\n",
386 PROCESS_WINDOW_STATION());
389 if (!IS_ATOM(lpwcx
->lpszClassName
))
391 Status
= RtlAddAtomToAtomTable(WinStaObject
->AtomTable
,
392 (LPWSTR
)lpwcx
->lpszClassName
,
394 if (!NT_SUCCESS(Status
))
396 ObDereferenceObject(WinStaObject
);
397 DPRINT("Failed adding class name (%wS) to atom table\n",
398 lpwcx
->lpszClassName
);
399 SetLastNtError(Status
);
405 Atom
= (RTL_ATOM
)(ULONG
)lpwcx
->lpszClassName
;
407 ClassObject
= IntCreateClass(lpwcx
, bUnicodeClass
, wpExtra
, Atom
);
408 if (ClassObject
== NULL
)
410 if (!IS_ATOM(lpwcx
->lpszClassName
))
412 RtlDeleteAtomFromAtomTable(WinStaObject
->AtomTable
, Atom
);
414 ObDereferenceObject(WinStaObject
);
415 DPRINT("Failed creating window class object\n");
416 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
419 ExAcquireFastMutex(&PsGetWin32Process()->ClassListLock
);
420 InsertTailList(&PsGetWin32Process()->ClassListHead
, &ClassObject
->ListEntry
);
421 ExReleaseFastMutex(&PsGetWin32Process()->ClassListLock
);
422 ObDereferenceObject(WinStaObject
);
427 IntGetClassLong(struct _WINDOW_OBJECT
*WindowObject
, ULONG Offset
, BOOL Ansi
)
431 if ((int)Offset
>= 0)
433 DPRINT("GetClassLong(%x, %d)\n", WindowObject
->Self
, Offset
);
434 if (Offset
> WindowObject
->Class
->cbClsExtra
- sizeof(LONG
))
436 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
439 Ret
= *((LONG
*)(WindowObject
->Class
->ExtraData
+ Offset
));
440 DPRINT("Result: %x\n", Ret
);
447 Ret
= WindowObject
->Class
->cbWndExtra
;
450 Ret
= WindowObject
->Class
->cbClsExtra
;
452 case GCL_HBRBACKGROUND
:
453 Ret
= (ULONG
)WindowObject
->Class
->hbrBackground
;
454 if (Ret
!= 0 && Ret
< 0x4000)
456 Ret
= (ULONG
)NtGdiGetSysColorBrush(Ret
- 1);
460 Ret
= (ULONG
)WindowObject
->Class
->hCursor
;
463 Ret
= (ULONG
)WindowObject
->Class
->hIcon
;
466 Ret
= (ULONG
)WindowObject
->Class
->hIconSm
;
469 Ret
= (ULONG
)WindowObject
->Class
->hInstance
;
472 Ret
= (ULONG
)WindowObject
->Class
->lpszMenuName
;
475 Ret
= WindowObject
->Class
->style
;
480 Ret
= (ULONG
)WindowObject
->Class
->lpfnWndProcA
;
484 Ret
= (ULONG
)WindowObject
->Class
->lpfnWndProcW
;
495 NtUserGetClassLong(HWND hWnd
, DWORD Offset
, BOOL Ansi
)
497 PWINDOW_OBJECT WindowObject
;
500 WindowObject
= IntGetWindowObject(hWnd
);
501 if (WindowObject
== NULL
)
503 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
506 Ret
= IntGetClassLong(WindowObject
, Offset
, Ansi
);
507 IntReleaseWindowObject(WindowObject
);
512 IntSetClassLong(PWINDOW_OBJECT WindowObject
, ULONG Offset
, LONG dwNewLong
, BOOL Ansi
)
516 if ((int)Offset
>= 0)
518 DPRINT("SetClassLong(%x, %d, %x)\n", WindowObject
->Self
, Offset
, dwNewLong
);
519 if (Offset
> WindowObject
->Class
->cbClsExtra
- sizeof(LONG
))
521 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
524 *((LONG
*)(WindowObject
->Class
->ExtraData
+ Offset
)) = dwNewLong
;
531 WindowObject
->Class
->cbWndExtra
= dwNewLong
;
534 WindowObject
->Class
->cbClsExtra
= dwNewLong
;
536 case GCL_HBRBACKGROUND
:
537 WindowObject
->Class
->hbrBackground
= (HBRUSH
)dwNewLong
;
540 WindowObject
->Class
->hCursor
= (HCURSOR
)dwNewLong
;
543 WindowObject
->Class
->hIcon
= (HICON
)dwNewLong
;
546 WindowObject
->Class
->hIconSm
= (HICON
)dwNewLong
;
549 WindowObject
->Class
->hInstance
= (HINSTANCE
)dwNewLong
;
552 if (!IS_INTRESOURCE(dwNewLong
))
554 str
= ExAllocatePool(PagedPool
,sizeof(UNICODE_STRING
)+((PUNICODE_STRING
)dwNewLong
)->Length
);
555 memcpy(str
,(PUNICODE_STRING
)dwNewLong
,sizeof(UNICODE_STRING
)+((PUNICODE_STRING
)dwNewLong
)->Length
);
556 WindowObject
->Class
->lpszMenuName
= str
;
560 WindowObject
->Class
->lpszMenuName
= (PUNICODE_STRING
)dwNewLong
;
564 WindowObject
->Class
->style
= dwNewLong
;
569 WindowObject
->Class
->lpfnWndProcA
= (WNDPROC
)dwNewLong
;
570 WindowObject
->Class
->lpfnWndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)dwNewLong
,FALSE
);
571 WindowObject
->Class
->Unicode
= FALSE
;
575 WindowObject
->Class
->lpfnWndProcW
= (WNDPROC
)dwNewLong
;
576 WindowObject
->Class
->lpfnWndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)dwNewLong
,TRUE
);
577 WindowObject
->Class
->Unicode
= TRUE
;
584 NtUserSetClassLong(HWND hWnd
,
589 PWINDOW_OBJECT WindowObject
;
592 WindowObject
= IntGetWindowObject(hWnd
);
593 if (WindowObject
== NULL
)
595 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
598 Ret
= IntGetClassLong(WindowObject
, Offset
, Ansi
);
599 IntSetClassLong(WindowObject
, Offset
, dwNewLong
, Ansi
);
600 IntReleaseWindowObject(WindowObject
);
605 NtUserSetClassWord(DWORD Unknown0
,
614 NtUserUnregisterClass(LPCWSTR ClassNameOrAtom
,
619 PWNDCLASS_OBJECT Class
;
623 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
627 Status
= ClassReferenceClassByNameOrAtom(&Class
, ClassNameOrAtom
);
628 if(!NT_SUCCESS(Status
))
630 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
634 if(Class
->hInstance
&& (Class
->hInstance
!= hInstance
))
636 ObmDereferenceObject(Class
);
637 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST
);
641 if(ObmGetReferenceCount(Class
) > 2)
643 ObmDereferenceObject(Class
);
644 SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS
);
648 /* Dereference the ClassReferenceClassByNameOrAtom() call */
649 ObmDereferenceObject(Class
);
651 RemoveEntryList(&Class
->ListEntry
);
653 /* FIXME - delete the atom? */
655 /* Free the object */
656 ObmDereferenceObject(Class
);