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.37 2003/10/22 14:02:54 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
= ValidateWindowStationHandle(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
= ValidateWindowStationHandle(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
,
296 PWNDCLASS_OBJECT ClassObject
;
298 objectSize
= sizeof(WNDCLASS_OBJECT
);
299 ClassObject
= ObmCreateObject(NULL
, NULL
, otClass
, objectSize
);
300 if (ClassObject
== 0)
305 ClassObject
->cbSize
= lpwcx
->cbSize
;
306 ClassObject
->style
= lpwcx
->style
;
307 ClassObject
->cbClsExtra
= lpwcx
->cbClsExtra
;
308 ClassObject
->cbWndExtra
= lpwcx
->cbWndExtra
;
309 ClassObject
->hInstance
= lpwcx
->hInstance
;
310 ClassObject
->hIcon
= lpwcx
->hIcon
;
311 ClassObject
->hCursor
= lpwcx
->hCursor
;
312 ClassObject
->hbrBackground
= lpwcx
->hbrBackground
;
313 ClassObject
->Unicode
= bUnicodeClass
;
314 ClassObject
->hIconSm
= lpwcx
->hIconSm
;
315 ClassObject
->lpszClassName
= (PUNICODE_STRING
)(ULONG
)Atom
;
318 ClassObject
->lpfnWndProcW
= lpwcx
->lpfnWndProc
;
319 ClassObject
->lpfnWndProcA
= lpwcx
->lpfnWndProc
+0x80000000;
323 ClassObject
->lpfnWndProcA
= lpwcx
->lpfnWndProc
;
324 ClassObject
->lpfnWndProcW
= lpwcx
->lpfnWndProc
+0x80000000;
326 if (IS_INTRESOURCE(lpwcx
->lpszMenuName
))
328 ClassObject
->lpszMenuName
= (PUNICODE_STRING
)lpwcx
->lpszMenuName
;
332 ClassObject
->lpszMenuName
= ExAllocatePool(NonPagedPool
,sizeof(UNICODE_STRING
));
333 RtlCreateUnicodeString(ClassObject
->lpszMenuName
,(LPWSTR
)lpwcx
->lpszMenuName
);
339 NtUserRegisterClassExWOW(
340 CONST WNDCLASSEXW
*lpwcx
,
348 * Registers a new class with the window manager
350 * lpwcx = Win32 extended window class structure
351 * bUnicodeClass = Whether to send ANSI or unicode strings
352 * to window procedures
354 * Atom identifying the new class
357 PWINSTATION_OBJECT WinStaObject
;
358 PWNDCLASS_OBJECT ClassObject
;
361 DPRINT("About to open window station handle (0x%X)\n",
362 PROCESS_WINDOW_STATION());
363 Status
= ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
367 if (!NT_SUCCESS(Status
))
369 DPRINT("Validation of window station handle (0x%X) failed\n",
370 PROCESS_WINDOW_STATION());
373 if (!IS_ATOM(lpwcx
->lpszClassName
))
375 Status
= RtlAddAtomToAtomTable(WinStaObject
->AtomTable
,
376 (LPWSTR
)lpwcx
->lpszClassName
,
378 if (!NT_SUCCESS(Status
))
380 ObDereferenceObject(WinStaObject
);
381 DPRINT("Failed adding class name (%wS) to atom table\n",
382 lpwcx
->lpszClassName
);
383 SetLastNtError(Status
);
389 Atom
= (RTL_ATOM
)(ULONG
)lpwcx
->lpszClassName
;
391 ClassObject
= IntCreateClass(lpwcx
, bUnicodeClass
, Atom
);
392 if (ClassObject
== NULL
)
394 if (!IS_ATOM(lpwcx
->lpszClassName
))
396 RtlDeleteAtomFromAtomTable(WinStaObject
->AtomTable
, Atom
);
398 ObDereferenceObject(WinStaObject
);
399 DPRINT("Failed creating window class object\n");
400 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
403 ExAcquireFastMutex(&PsGetWin32Process()->ClassListLock
);
404 InsertTailList(&PsGetWin32Process()->ClassListHead
, &ClassObject
->ListEntry
);
405 ExReleaseFastMutex(&PsGetWin32Process()->ClassListLock
);
406 ObDereferenceObject(WinStaObject
);
411 IntGetClassLong(struct _WINDOW_OBJECT
*WindowObject
, ULONG Offset
, BOOL Ansi
)
417 Ret
= WindowObject
->Class
->cbWndExtra
;
420 Ret
= WindowObject
->Class
->cbClsExtra
;
422 case GCL_HBRBACKGROUND
:
423 Ret
= (ULONG
)WindowObject
->Class
->hbrBackground
;
424 if (Ret
!= 0 && Ret
< 0x4000)
426 Ret
= (ULONG
)NtGdiGetSysColorBrush(Ret
- 1);
430 Ret
= (ULONG
)WindowObject
->Class
->hCursor
;
433 Ret
= (ULONG
)WindowObject
->Class
->hIcon
;
436 Ret
= (ULONG
)WindowObject
->Class
->hIconSm
;
439 Ret
= (ULONG
)WindowObject
->Class
->hInstance
;
442 Ret
= (ULONG
)WindowObject
->Class
->lpszMenuName
;
445 Ret
= WindowObject
->Class
->style
;
450 Ret
= (ULONG
)WindowObject
->Class
->lpfnWndProcA
;
454 Ret
= (ULONG
)WindowObject
->Class
->lpfnWndProcW
;
465 NtUserGetClassLong(HWND hWnd
, DWORD Offset
, BOOL Ansi
)
467 PWINDOW_OBJECT WindowObject
;
470 WindowObject
= IntGetWindowObject(hWnd
);
471 if (WindowObject
== NULL
)
473 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
476 Ret
= IntGetClassLong(WindowObject
, Offset
, Ansi
);
477 IntReleaseWindowObject(WindowObject
);
482 IntSetClassLong(PWINDOW_OBJECT WindowObject
, ULONG Offset
, LONG dwNewLong
, BOOL Ansi
)
488 WindowObject
->Class
->cbWndExtra
= dwNewLong
;
491 WindowObject
->Class
->cbClsExtra
= dwNewLong
;
493 case GCL_HBRBACKGROUND
:
494 WindowObject
->Class
->hbrBackground
= (HBRUSH
)dwNewLong
;
497 WindowObject
->Class
->hCursor
= (HCURSOR
)dwNewLong
;
500 WindowObject
->Class
->hIcon
= (HICON
)dwNewLong
;
503 WindowObject
->Class
->hIconSm
= (HICON
)dwNewLong
;
506 WindowObject
->Class
->hInstance
= (HINSTANCE
)dwNewLong
;
509 if (!IS_INTRESOURCE(dwNewLong
))
511 str
= ExAllocatePool(PagedPool
,sizeof(UNICODE_STRING
)+((PUNICODE_STRING
)dwNewLong
)->Length
);
512 memcpy(str
,(PUNICODE_STRING
)dwNewLong
,sizeof(UNICODE_STRING
)+((PUNICODE_STRING
)dwNewLong
)->Length
);
513 WindowObject
->Class
->lpszMenuName
= str
;
517 WindowObject
->Class
->lpszMenuName
= (PUNICODE_STRING
)dwNewLong
;
521 WindowObject
->Class
->style
= dwNewLong
;
526 WindowObject
->Class
->lpfnWndProcA
= (WNDPROC
)dwNewLong
;
527 WindowObject
->Class
->lpfnWndProcW
= (WNDPROC
)dwNewLong
+0x80000000;
528 WindowObject
->Class
->Unicode
= FALSE
;
532 WindowObject
->Class
->lpfnWndProcW
= (WNDPROC
)dwNewLong
;
533 WindowObject
->Class
->lpfnWndProcA
= (WNDPROC
)dwNewLong
+0x80000000;
534 WindowObject
->Class
->Unicode
= TRUE
;
541 NtUserSetClassLong(HWND hWnd
,
546 PWINDOW_OBJECT WindowObject
;
549 WindowObject
= IntGetWindowObject(hWnd
);
550 if (WindowObject
== NULL
)
552 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
555 Ret
= IntGetClassLong(WindowObject
, Offset
, Ansi
);
556 IntSetClassLong(WindowObject
, Offset
, dwNewLong
, Ansi
);
557 IntReleaseWindowObject(WindowObject
);
562 NtUserSetClassWord(DWORD Unknown0
,
571 NtUserUnregisterClass(DWORD Unknown0
,