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