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.40 2003/11/23 11:39:48 navaraf 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
->lpszClassName
== (PUNICODE_STRING
)(ULONG
)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 LPWSTR 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 hInst
,
161 PWNDCLASS_OBJECT Class
;
163 Status
= ClassReferenceClassByNameOrAtom(&Class
,(LPWSTR
)str
);
164 if (!NT_SUCCESS(Status
))
166 SetLastNtError(Status
);
169 wcex
->cbSize
= sizeof(LPWNDCLASSEXW
);
170 wcex
->style
= Class
->style
;
173 wcex
->lpfnWndProc
= Class
->lpfnWndProcA
;
177 wcex
->lpfnWndProc
= Class
->lpfnWndProcW
;
179 wcex
->cbClsExtra
= Class
->cbClsExtra
;
180 wcex
->cbWndExtra
= Class
->cbWndExtra
;
181 wcex
->hInstance
= Class
->hInstance
;
182 wcex
->hIcon
= Class
->hIcon
;
183 wcex
->hCursor
= Class
->hCursor
;
184 wcex
->hbrBackground
= Class
->hbrBackground
;
185 if(Class
->lpszMenuName
)
187 if(!IS_INTRESOURCE((LPCWSTR
)Class
->lpszMenuName
))
188 RtlCopyUnicodeString((PUNICODE_STRING
)wcex
->lpszMenuName
, Class
->lpszMenuName
);
190 wcex
->lpszMenuName
= (LPCWSTR
)Class
->lpszMenuName
;
193 wcex
->lpszMenuName
= (LPCWSTR
)NULL
;
194 if(Class
->lpszClassName
)
196 if(!IS_ATOM((LPCWSTR
)Class
->lpszClassName
))
197 RtlCopyUnicodeString((PUNICODE_STRING
)wcex
->lpszClassName
, Class
->lpszClassName
);
199 wcex
->lpszClassName
= (LPCWSTR
)Class
->lpszClassName
;
202 wcex
->lpszClassName
= (LPCWSTR
)NULL
;
203 wcex
->hIconSm
= Class
->hIconSm
;
208 IntGetClassName(struct _WINDOW_OBJECT
*WindowObject
,
215 PWINSTATION_OBJECT WinStaObject
;
217 if (IS_ATOM(WindowObject
->Class
->lpszClassName
))
219 DPRINT("About to open window station handle (0x%X)\n",
220 PROCESS_WINDOW_STATION());
221 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
225 if (!NT_SUCCESS(Status
))
227 DPRINT("Validation of window station handle (0x%X) failed\n",
228 PROCESS_WINDOW_STATION());
232 Status
= RtlQueryAtomInAtomTable(WinStaObject
->AtomTable
,(RTL_ATOM
)(size_t)WindowObject
->Class
->lpszClassName
,NULL
,NULL
,name
,&length
);
233 name
= ExAllocatePool(PagedPool
,length
+sizeof(WCHAR
));
235 Status
= RtlQueryAtomInAtomTable(WinStaObject
->AtomTable
,(RTL_ATOM
)(size_t)WindowObject
->Class
->lpszClassName
,NULL
,NULL
,name
,&length
);
236 if (!NT_SUCCESS(Status
))
238 DPRINT("Validation of window station handle (0x%X) failed\n",
239 PROCESS_WINDOW_STATION());
242 ObDereferenceObject(WinStaObject
);
246 name
= WindowObject
->Class
->lpszClassName
->Buffer
;
247 length
= WindowObject
->Class
->lpszClassName
->Length
/ sizeof(WCHAR
);
250 if (length
> nMaxCount
)
254 *(lpClassName
+length
) = 0;
255 wcsncpy(lpClassName
,name
,length
);
269 PWINDOW_OBJECT WindowObject
;
272 WindowObject
= IntGetWindowObject(hWnd
);
273 if (WindowObject
== NULL
)
275 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
278 Ret
= IntGetClassName(WindowObject
, lpClassName
, nMaxCount
);
279 IntReleaseWindowObject(WindowObject
);
284 NtUserGetWOWClass(DWORD Unknown0
,
291 PWNDCLASS_OBJECT FASTCALL
292 IntCreateClass(CONST WNDCLASSEXW
*lpwcx
,
297 PWNDCLASS_OBJECT ClassObject
;
301 /* Check for double registration of the class. */
302 if (PsGetWin32Process() != NULL
)
304 Status
= ClassReferenceClassByAtom(&ClassObject
, Atom
);
305 if (NT_SUCCESS(Status
))
307 ObmDereferenceObject(ClassObject
);
312 objectSize
= sizeof(WNDCLASS_OBJECT
) + lpwcx
->cbClsExtra
;
313 ClassObject
= ObmCreateObject(NULL
, NULL
, otClass
, objectSize
);
314 if (ClassObject
== 0)
319 ClassObject
->cbSize
= lpwcx
->cbSize
;
320 ClassObject
->style
= lpwcx
->style
;
321 ClassObject
->cbClsExtra
= lpwcx
->cbClsExtra
;
322 ClassObject
->cbWndExtra
= lpwcx
->cbWndExtra
;
323 ClassObject
->hInstance
= lpwcx
->hInstance
;
324 ClassObject
->hIcon
= lpwcx
->hIcon
;
325 ClassObject
->hCursor
= lpwcx
->hCursor
;
326 ClassObject
->hbrBackground
= lpwcx
->hbrBackground
;
327 ClassObject
->Unicode
= bUnicodeClass
;
328 ClassObject
->hIconSm
= lpwcx
->hIconSm
;
329 ClassObject
->lpszClassName
= (PUNICODE_STRING
)(ULONG
)Atom
;
333 ClassObject
->lpfnWndProcW
= lpwcx
->lpfnWndProc
;
334 ClassObject
->lpfnWndProcA
= (WNDPROC
)IntAddWndProcHandle(lpwcx
->lpfnWndProc
,TRUE
);
338 ClassObject
->lpfnWndProcA
= lpwcx
->lpfnWndProc
;
339 ClassObject
->lpfnWndProcW
= (WNDPROC
)IntAddWndProcHandle(lpwcx
->lpfnWndProc
,FALSE
);
344 ClassObject
->lpfnWndProcW
= lpwcx
->lpfnWndProc
;
345 ClassObject
->lpfnWndProcA
= wpExtra
;
349 ClassObject
->lpfnWndProcA
= lpwcx
->lpfnWndProc
;
350 ClassObject
->lpfnWndProcW
= wpExtra
;
353 if (IS_INTRESOURCE(lpwcx
->lpszMenuName
))
355 ClassObject
->lpszMenuName
= (PUNICODE_STRING
)lpwcx
->lpszMenuName
;
359 ClassObject
->lpszMenuName
= ExAllocatePool(NonPagedPool
,sizeof(UNICODE_STRING
));
360 RtlCreateUnicodeString(ClassObject
->lpszMenuName
,(LPWSTR
)lpwcx
->lpszMenuName
);
362 /* Extra class data */
363 if (ClassObject
->cbClsExtra
!= 0)
365 ClassObject
->ExtraData
= (PCHAR
)(ClassObject
+ 1);
366 RtlZeroMemory(ClassObject
->ExtraData
, ClassObject
->cbClsExtra
);
370 ClassObject
->ExtraData
= NULL
;
377 NtUserRegisterClassExWOW(
378 CONST WNDCLASSEXW
*lpwcx
,
386 * Registers a new class with the window manager
388 * lpwcx = Win32 extended window class structure
389 * bUnicodeClass = Whether to send ANSI or unicode strings
390 * to window procedures
391 * wpExtra = Extra window procedure, if this is not null, its used for the second window procedure for standard controls.
393 * Atom identifying the new class
396 PWINSTATION_OBJECT WinStaObject
;
397 PWNDCLASS_OBJECT ClassObject
;
400 DPRINT("About to open window station handle (0x%X)\n",
401 PROCESS_WINDOW_STATION());
402 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
406 if (!NT_SUCCESS(Status
))
408 DPRINT("Validation of window station handle (0x%X) failed\n",
409 PROCESS_WINDOW_STATION());
412 if (!IS_ATOM(lpwcx
->lpszClassName
))
414 Status
= RtlAddAtomToAtomTable(WinStaObject
->AtomTable
,
415 (LPWSTR
)lpwcx
->lpszClassName
,
417 if (!NT_SUCCESS(Status
))
419 ObDereferenceObject(WinStaObject
);
420 DPRINT("Failed adding class name (%wS) to atom table\n",
421 lpwcx
->lpszClassName
);
422 SetLastNtError(Status
);
428 Atom
= (RTL_ATOM
)(ULONG
)lpwcx
->lpszClassName
;
430 ClassObject
= IntCreateClass(lpwcx
, bUnicodeClass
, wpExtra
, Atom
);
431 if (ClassObject
== NULL
)
433 if (!IS_ATOM(lpwcx
->lpszClassName
))
435 RtlDeleteAtomFromAtomTable(WinStaObject
->AtomTable
, Atom
);
437 ObDereferenceObject(WinStaObject
);
438 DPRINT("Failed creating window class object\n");
439 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
442 ExAcquireFastMutex(&PsGetWin32Process()->ClassListLock
);
443 InsertTailList(&PsGetWin32Process()->ClassListHead
, &ClassObject
->ListEntry
);
444 ExReleaseFastMutex(&PsGetWin32Process()->ClassListLock
);
445 ObDereferenceObject(WinStaObject
);
450 IntGetClassLong(struct _WINDOW_OBJECT
*WindowObject
, ULONG Offset
, BOOL Ansi
)
454 if ((int)Offset
>= 0)
456 DbgPrint("GetClassLong(%x, %d)\n", WindowObject
->Self
, Offset
);
457 if (Offset
> WindowObject
->Class
->cbClsExtra
- sizeof(LONG
))
459 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
462 Ret
= *((LONG
*)(WindowObject
->Class
->ExtraData
+ Offset
));
463 DbgPrint("Result: %x\n", Ret
);
470 Ret
= WindowObject
->Class
->cbWndExtra
;
473 Ret
= WindowObject
->Class
->cbClsExtra
;
475 case GCL_HBRBACKGROUND
:
476 Ret
= (ULONG
)WindowObject
->Class
->hbrBackground
;
477 if (Ret
!= 0 && Ret
< 0x4000)
479 Ret
= (ULONG
)NtGdiGetSysColorBrush(Ret
- 1);
483 Ret
= (ULONG
)WindowObject
->Class
->hCursor
;
486 Ret
= (ULONG
)WindowObject
->Class
->hIcon
;
489 Ret
= (ULONG
)WindowObject
->Class
->hIconSm
;
492 Ret
= (ULONG
)WindowObject
->Class
->hInstance
;
495 Ret
= (ULONG
)WindowObject
->Class
->lpszMenuName
;
498 Ret
= WindowObject
->Class
->style
;
503 Ret
= (ULONG
)WindowObject
->Class
->lpfnWndProcA
;
507 Ret
= (ULONG
)WindowObject
->Class
->lpfnWndProcW
;
518 NtUserGetClassLong(HWND hWnd
, DWORD Offset
, BOOL Ansi
)
520 PWINDOW_OBJECT WindowObject
;
523 WindowObject
= IntGetWindowObject(hWnd
);
524 if (WindowObject
== NULL
)
526 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
529 Ret
= IntGetClassLong(WindowObject
, Offset
, Ansi
);
530 IntReleaseWindowObject(WindowObject
);
535 IntSetClassLong(PWINDOW_OBJECT WindowObject
, ULONG Offset
, LONG dwNewLong
, BOOL Ansi
)
539 if ((int)Offset
>= 0)
541 DbgPrint("SetClassLong(%x, %d, %x)\n", WindowObject
->Self
, Offset
, dwNewLong
);
542 if (Offset
> WindowObject
->Class
->cbClsExtra
- sizeof(LONG
))
544 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
547 *((LONG
*)(WindowObject
->Class
->ExtraData
+ Offset
)) = dwNewLong
;
554 WindowObject
->Class
->cbWndExtra
= dwNewLong
;
557 WindowObject
->Class
->cbClsExtra
= dwNewLong
;
559 case GCL_HBRBACKGROUND
:
560 WindowObject
->Class
->hbrBackground
= (HBRUSH
)dwNewLong
;
563 WindowObject
->Class
->hCursor
= (HCURSOR
)dwNewLong
;
566 WindowObject
->Class
->hIcon
= (HICON
)dwNewLong
;
569 WindowObject
->Class
->hIconSm
= (HICON
)dwNewLong
;
572 WindowObject
->Class
->hInstance
= (HINSTANCE
)dwNewLong
;
575 if (!IS_INTRESOURCE(dwNewLong
))
577 str
= ExAllocatePool(PagedPool
,sizeof(UNICODE_STRING
)+((PUNICODE_STRING
)dwNewLong
)->Length
);
578 memcpy(str
,(PUNICODE_STRING
)dwNewLong
,sizeof(UNICODE_STRING
)+((PUNICODE_STRING
)dwNewLong
)->Length
);
579 WindowObject
->Class
->lpszMenuName
= str
;
583 WindowObject
->Class
->lpszMenuName
= (PUNICODE_STRING
)dwNewLong
;
587 WindowObject
->Class
->style
= dwNewLong
;
592 WindowObject
->Class
->lpfnWndProcA
= (WNDPROC
)dwNewLong
;
593 WindowObject
->Class
->lpfnWndProcW
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)dwNewLong
,FALSE
);
594 WindowObject
->Class
->Unicode
= FALSE
;
598 WindowObject
->Class
->lpfnWndProcW
= (WNDPROC
)dwNewLong
;
599 WindowObject
->Class
->lpfnWndProcA
= (WNDPROC
) IntAddWndProcHandle((WNDPROC
)dwNewLong
,TRUE
);
600 WindowObject
->Class
->Unicode
= TRUE
;
607 NtUserSetClassLong(HWND hWnd
,
612 PWINDOW_OBJECT WindowObject
;
615 WindowObject
= IntGetWindowObject(hWnd
);
616 if (WindowObject
== NULL
)
618 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
621 Ret
= IntGetClassLong(WindowObject
, Offset
, Ansi
);
622 IntSetClassLong(WindowObject
, Offset
, dwNewLong
, Ansi
);
623 IntReleaseWindowObject(WindowObject
);
628 NtUserSetClassWord(DWORD Unknown0
,
637 NtUserUnregisterClass(DWORD Unknown0
,