- Removed commented-out code from FillRect to prevent anyone from uncommenting it...
[reactos.git] / reactos / subsys / win32k / ntuser / class.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: class.c,v 1.37 2003/10/22 14:02:54 navaraf Exp $
20 *
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)
26 * REVISION HISTORY:
27 * 06-06-2001 CSH Created
28 */
29 /* INCLUDES ******************************************************************/
30
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>
41
42 #define NDEBUG
43 #include <debug.h>
44
45 /* FUNCTIONS *****************************************************************/
46
47 NTSTATUS FASTCALL
48 InitClassImpl(VOID)
49 {
50 return(STATUS_SUCCESS);
51 }
52
53 NTSTATUS FASTCALL
54 CleanupClassImpl(VOID)
55 {
56 return(STATUS_SUCCESS);
57 }
58
59
60 NTSTATUS FASTCALL
61 ClassReferenceClassByAtom(PWNDCLASS_OBJECT* Class,
62 RTL_ATOM Atom)
63 {
64 PWNDCLASS_OBJECT Current;
65 PLIST_ENTRY CurrentEntry;
66 PW32PROCESS Process = PsGetWin32Process();
67
68 ExAcquireFastMutexUnsafe (&Process->ClassListLock);
69 CurrentEntry = Process->ClassListHead.Flink;
70 while (CurrentEntry != &Process->ClassListHead)
71 {
72 Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, ListEntry);
73
74 if (Current->lpszClassName == (PUNICODE_STRING)(ULONG)Atom)
75 {
76 *Class = Current;
77 ObmReferenceObject(Current);
78 ExReleaseFastMutexUnsafe (&Process->ClassListLock);
79 return(STATUS_SUCCESS);
80 }
81
82 CurrentEntry = CurrentEntry->Flink;
83 }
84 ExReleaseFastMutexUnsafe (&Process->ClassListLock);
85
86 return(STATUS_NOT_FOUND);
87 }
88
89 NTSTATUS STDCALL
90 ClassReferenceClassByName(PWNDCLASS_OBJECT *Class,
91 PWSTR ClassName)
92 {
93 PWINSTATION_OBJECT WinStaObject;
94 NTSTATUS Status;
95 RTL_ATOM ClassAtom;
96
97 if (!ClassName)
98 {
99 return(STATUS_INVALID_PARAMETER);
100 }
101
102 Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
103 KernelMode,
104 0,
105 &WinStaObject);
106 if (!NT_SUCCESS(Status))
107 {
108 DPRINT("Validation of window station handle (0x%X) failed\n",
109 PROCESS_WINDOW_STATION());
110 return(STATUS_UNSUCCESSFUL);
111 }
112
113 Status = RtlLookupAtomInAtomTable(WinStaObject->AtomTable,
114 ClassName,
115 &ClassAtom);
116
117 if (!NT_SUCCESS(Status))
118 {
119 ObDereferenceObject(WinStaObject);
120 return(Status);
121 }
122 Status = ClassReferenceClassByAtom(Class,
123 ClassAtom);
124
125 ObDereferenceObject(WinStaObject);
126 return(Status);
127 }
128
129 NTSTATUS FASTCALL
130 ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class,
131 LPWSTR ClassNameOrAtom)
132 {
133 NTSTATUS Status;
134
135 if (IS_ATOM(ClassNameOrAtom))
136 {
137 Status = ClassReferenceClassByAtom(Class,
138 (RTL_ATOM)((ULONG_PTR)ClassNameOrAtom));
139 }
140 else
141 {
142 Status = ClassReferenceClassByName(Class,
143 ClassNameOrAtom);
144 }
145
146 if (!NT_SUCCESS(Status))
147 {
148 SetLastNtError(Status);
149 }
150
151 return(Status);
152 }
153
154 DWORD STDCALL
155 NtUserGetClassInfo(HINSTANCE hInst,
156 LPCWSTR str,
157 LPWNDCLASSEXW wcex,
158 BOOL Ansi,
159 DWORD unknown3)
160 {
161 PWNDCLASS_OBJECT Class;
162 NTSTATUS Status;
163 Status = ClassReferenceClassByNameOrAtom(&Class,(LPWSTR)str);
164 if (!NT_SUCCESS(Status))
165 {
166 SetLastNtError(Status);
167 return 0;
168 }
169 wcex->cbSize = sizeof(LPWNDCLASSEXW);
170 wcex->style = Class->style;
171 if (Ansi)
172 {
173 wcex->lpfnWndProc = Class->lpfnWndProcA;
174 }
175 else
176 {
177 wcex->lpfnWndProc = Class->lpfnWndProcW;
178 }
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)
186 {
187 if(!IS_INTRESOURCE((LPCWSTR)Class->lpszMenuName))
188 RtlCopyUnicodeString((PUNICODE_STRING)wcex->lpszMenuName, Class->lpszMenuName);
189 else
190 wcex->lpszMenuName = (LPCWSTR)Class->lpszMenuName;
191 }
192 else
193 wcex->lpszMenuName = (LPCWSTR)NULL;
194 if(Class->lpszClassName)
195 {
196 if(!IS_ATOM((LPCWSTR)Class->lpszClassName))
197 RtlCopyUnicodeString((PUNICODE_STRING)wcex->lpszClassName, Class->lpszClassName);
198 else
199 wcex->lpszClassName = (LPCWSTR)Class->lpszClassName;
200 }
201 else
202 wcex->lpszClassName = (LPCWSTR)NULL;
203 wcex->hIconSm = Class->hIconSm;
204 return 1;
205 }
206
207 ULONG FASTCALL
208 IntGetClassName(struct _WINDOW_OBJECT *WindowObject,
209 LPWSTR lpClassName,
210 ULONG nMaxCount)
211 {
212 ULONG length;
213 LPWSTR name;
214 BOOL free;
215 PWINSTATION_OBJECT WinStaObject;
216 NTSTATUS Status;
217 if (IS_ATOM(WindowObject->Class->lpszClassName))
218 {
219 DPRINT("About to open window station handle (0x%X)\n",
220 PROCESS_WINDOW_STATION());
221 Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
222 KernelMode,
223 0,
224 &WinStaObject);
225 if (!NT_SUCCESS(Status))
226 {
227 DPRINT("Validation of window station handle (0x%X) failed\n",
228 PROCESS_WINDOW_STATION());
229 return((RTL_ATOM)0);
230 }
231 length = 0;
232 Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,(RTL_ATOM)(size_t)WindowObject->Class->lpszClassName,NULL,NULL,name,&length);
233 name = ExAllocatePool(PagedPool,length+sizeof(WCHAR));
234 free = TRUE;
235 Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,(RTL_ATOM)(size_t)WindowObject->Class->lpszClassName,NULL,NULL,name,&length);
236 if (!NT_SUCCESS(Status))
237 {
238 DPRINT("Validation of window station handle (0x%X) failed\n",
239 PROCESS_WINDOW_STATION());
240 return((RTL_ATOM)0);
241 }
242 ObDereferenceObject(WinStaObject);
243 }
244 else
245 {
246 name = WindowObject->Class->lpszClassName->Buffer;
247 length = WindowObject->Class->lpszClassName->Length / sizeof(WCHAR);
248 free = FALSE;
249 }
250 if (length > nMaxCount)
251 {
252 length = nMaxCount;
253 }
254 *(lpClassName+length) = 0;
255 wcsncpy(lpClassName,name,length);
256 if (free)
257 {
258 ExFreePool(name);
259 }
260 return length;
261 }
262
263 DWORD STDCALL
264 NtUserGetClassName (
265 HWND hWnd,
266 LPWSTR lpClassName,
267 ULONG nMaxCount)
268 {
269 PWINDOW_OBJECT WindowObject;
270 LONG Ret;
271
272 WindowObject = IntGetWindowObject(hWnd);
273 if (WindowObject == NULL)
274 {
275 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
276 return 0;
277 }
278 Ret = IntGetClassName(WindowObject, lpClassName, nMaxCount);
279 IntReleaseWindowObject(WindowObject);
280 return(Ret);
281 }
282
283 DWORD STDCALL
284 NtUserGetWOWClass(DWORD Unknown0,
285 DWORD Unknown1)
286 {
287 UNIMPLEMENTED;
288 return(0);
289 }
290
291 PWNDCLASS_OBJECT FASTCALL
292 IntCreateClass(CONST WNDCLASSEXW *lpwcx,
293 BOOL bUnicodeClass,
294 RTL_ATOM Atom)
295 {
296 PWNDCLASS_OBJECT ClassObject;
297 WORD objectSize;
298 objectSize = sizeof(WNDCLASS_OBJECT);
299 ClassObject = ObmCreateObject(NULL, NULL, otClass, objectSize);
300 if (ClassObject == 0)
301 {
302 return(NULL);
303 }
304
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;
316 if (bUnicodeClass)
317 {
318 ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
319 ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc+0x80000000;
320 }
321 else
322 {
323 ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
324 ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc+0x80000000;
325 }
326 if (IS_INTRESOURCE(lpwcx->lpszMenuName))
327 {
328 ClassObject->lpszMenuName = (PUNICODE_STRING)lpwcx->lpszMenuName;
329 }
330 else
331 {
332 ClassObject->lpszMenuName = ExAllocatePool(NonPagedPool,sizeof(UNICODE_STRING));
333 RtlCreateUnicodeString(ClassObject->lpszMenuName,(LPWSTR)lpwcx->lpszMenuName);
334 }
335 return(ClassObject);
336 }
337
338 RTL_ATOM STDCALL
339 NtUserRegisterClassExWOW(
340 CONST WNDCLASSEXW *lpwcx,
341 BOOL bUnicodeClass,
342 DWORD Unknown3,
343 DWORD Unknown4,
344 DWORD Unknown5)
345
346 /*
347 * FUNCTION:
348 * Registers a new class with the window manager
349 * ARGUMENTS:
350 * lpwcx = Win32 extended window class structure
351 * bUnicodeClass = Whether to send ANSI or unicode strings
352 * to window procedures
353 * RETURNS:
354 * Atom identifying the new class
355 */
356 {
357 PWINSTATION_OBJECT WinStaObject;
358 PWNDCLASS_OBJECT ClassObject;
359 NTSTATUS Status;
360 RTL_ATOM Atom;
361 DPRINT("About to open window station handle (0x%X)\n",
362 PROCESS_WINDOW_STATION());
363 Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
364 KernelMode,
365 0,
366 &WinStaObject);
367 if (!NT_SUCCESS(Status))
368 {
369 DPRINT("Validation of window station handle (0x%X) failed\n",
370 PROCESS_WINDOW_STATION());
371 return((RTL_ATOM)0);
372 }
373 if (!IS_ATOM(lpwcx->lpszClassName))
374 {
375 Status = RtlAddAtomToAtomTable(WinStaObject->AtomTable,
376 (LPWSTR)lpwcx->lpszClassName,
377 &Atom);
378 if (!NT_SUCCESS(Status))
379 {
380 ObDereferenceObject(WinStaObject);
381 DPRINT("Failed adding class name (%wS) to atom table\n",
382 lpwcx->lpszClassName);
383 SetLastNtError(Status);
384 return((RTL_ATOM)0);
385 }
386 }
387 else
388 {
389 Atom = (RTL_ATOM)(ULONG)lpwcx->lpszClassName;
390 }
391 ClassObject = IntCreateClass(lpwcx, bUnicodeClass, Atom);
392 if (ClassObject == NULL)
393 {
394 if (!IS_ATOM(lpwcx->lpszClassName))
395 {
396 RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Atom);
397 }
398 ObDereferenceObject(WinStaObject);
399 DPRINT("Failed creating window class object\n");
400 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
401 return((RTL_ATOM)0);
402 }
403 ExAcquireFastMutex(&PsGetWin32Process()->ClassListLock);
404 InsertTailList(&PsGetWin32Process()->ClassListHead, &ClassObject->ListEntry);
405 ExReleaseFastMutex(&PsGetWin32Process()->ClassListLock);
406 ObDereferenceObject(WinStaObject);
407 return(Atom);
408 }
409
410 ULONG FASTCALL
411 IntGetClassLong(struct _WINDOW_OBJECT *WindowObject, ULONG Offset, BOOL Ansi)
412 {
413 LONG Ret;
414 switch (Offset)
415 {
416 case GCL_CBWNDEXTRA:
417 Ret = WindowObject->Class->cbWndExtra;
418 break;
419 case GCL_CBCLSEXTRA:
420 Ret = WindowObject->Class->cbClsExtra;
421 break;
422 case GCL_HBRBACKGROUND:
423 Ret = (ULONG)WindowObject->Class->hbrBackground;
424 if (Ret != 0 && Ret < 0x4000)
425 {
426 Ret = (ULONG)NtGdiGetSysColorBrush(Ret - 1);
427 }
428 break;
429 case GCL_HCURSOR:
430 Ret = (ULONG)WindowObject->Class->hCursor;
431 break;
432 case GCL_HICON:
433 Ret = (ULONG)WindowObject->Class->hIcon;
434 break;
435 case GCL_HICONSM:
436 Ret = (ULONG)WindowObject->Class->hIconSm;
437 break;
438 case GCL_HMODULE:
439 Ret = (ULONG)WindowObject->Class->hInstance;
440 break;
441 case GCL_MENUNAME:
442 Ret = (ULONG)WindowObject->Class->lpszMenuName;
443 break;
444 case GCL_STYLE:
445 Ret = WindowObject->Class->style;
446 break;
447 case GCL_WNDPROC:
448 if (Ansi)
449 {
450 Ret = (ULONG)WindowObject->Class->lpfnWndProcA;
451 }
452 else
453 {
454 Ret = (ULONG)WindowObject->Class->lpfnWndProcW;
455 }
456 break;
457 default:
458 Ret = 0;
459 break;
460 }
461 return(Ret);
462 }
463
464 DWORD STDCALL
465 NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
466 {
467 PWINDOW_OBJECT WindowObject;
468 LONG Ret;
469
470 WindowObject = IntGetWindowObject(hWnd);
471 if (WindowObject == NULL)
472 {
473 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
474 return 0;
475 }
476 Ret = IntGetClassLong(WindowObject, Offset, Ansi);
477 IntReleaseWindowObject(WindowObject);
478 return(Ret);
479 }
480
481 void FASTCALL
482 IntSetClassLong(PWINDOW_OBJECT WindowObject, ULONG Offset, LONG dwNewLong, BOOL Ansi)
483 {
484 PUNICODE_STRING str;
485 switch (Offset)
486 {
487 case GCL_CBWNDEXTRA:
488 WindowObject->Class->cbWndExtra = dwNewLong;
489 break;
490 case GCL_CBCLSEXTRA:
491 WindowObject->Class->cbClsExtra = dwNewLong;
492 break;
493 case GCL_HBRBACKGROUND:
494 WindowObject->Class->hbrBackground = (HBRUSH)dwNewLong;
495 break;
496 case GCL_HCURSOR:
497 WindowObject->Class->hCursor = (HCURSOR)dwNewLong;
498 break;
499 case GCL_HICON:
500 WindowObject->Class->hIcon = (HICON)dwNewLong;
501 break;
502 case GCL_HICONSM:
503 WindowObject->Class->hIconSm = (HICON)dwNewLong;
504 break;
505 case GCL_HMODULE:
506 WindowObject->Class->hInstance = (HINSTANCE)dwNewLong;
507 break;
508 case GCL_MENUNAME:
509 if (!IS_INTRESOURCE(dwNewLong))
510 {
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;
514 }
515 else
516 {
517 WindowObject->Class->lpszMenuName = (PUNICODE_STRING)dwNewLong;
518 }
519 break;
520 case GCL_STYLE:
521 WindowObject->Class->style = dwNewLong;
522 break;
523 case GCL_WNDPROC:
524 if (Ansi)
525 {
526 WindowObject->Class->lpfnWndProcA = (WNDPROC)dwNewLong;
527 WindowObject->Class->lpfnWndProcW = (WNDPROC)dwNewLong+0x80000000;
528 WindowObject->Class->Unicode = FALSE;
529 }
530 else
531 {
532 WindowObject->Class->lpfnWndProcW = (WNDPROC)dwNewLong;
533 WindowObject->Class->lpfnWndProcA = (WNDPROC)dwNewLong+0x80000000;
534 WindowObject->Class->Unicode = TRUE;
535 }
536 break;
537 }
538 }
539
540 DWORD STDCALL
541 NtUserSetClassLong(HWND hWnd,
542 DWORD Offset,
543 LONG dwNewLong,
544 BOOL Ansi)
545 {
546 PWINDOW_OBJECT WindowObject;
547 LONG Ret;
548
549 WindowObject = IntGetWindowObject(hWnd);
550 if (WindowObject == NULL)
551 {
552 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
553 return 0;
554 }
555 Ret = IntGetClassLong(WindowObject, Offset, Ansi);
556 IntSetClassLong(WindowObject, Offset, dwNewLong, Ansi);
557 IntReleaseWindowObject(WindowObject);
558 return(Ret);
559 }
560
561 DWORD STDCALL
562 NtUserSetClassWord(DWORD Unknown0,
563 DWORD Unknown1,
564 DWORD Unknown2)
565 {
566 UNIMPLEMENTED;
567 return(0);
568 }
569
570 DWORD STDCALL
571 NtUserUnregisterClass(DWORD Unknown0,
572 DWORD Unknown1,
573 DWORD Unknown2)
574 {
575 UNIMPLEMENTED;
576 return(0);
577 }
578
579 /* EOF */