fixed some bugs in GetClassInfoExA/W()
[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.32 2003/08/19 00:36:40 weiden 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 wcex->cbSize = sizeof(LPWNDCLASSEXW);
169 wcex->style = Class->style;
170 if (Ansi)
171 {
172 wcex->lpfnWndProc = Class->lpfnWndProcA;
173 }
174 else
175 {
176 wcex->lpfnWndProc = Class->lpfnWndProcW;
177 }
178 wcex->cbClsExtra = Class->cbClsExtra;
179 wcex->cbWndExtra = Class->cbWndExtra;
180 wcex->hInstance = Class->hInstance;
181 wcex->hIcon = Class->hIcon;
182 wcex->hCursor = Class->hCursor;
183 wcex->hbrBackground = Class->hbrBackground;
184 if(Class->lpszMenuName)
185 RtlCopyUnicodeString((PUNICODE_STRING)wcex->lpszMenuName, Class->lpszMenuName);
186 else
187 wcex->lpszMenuName = (LPCWSTR)NULL;
188 wcex->lpszClassName = (LPCWSTR)Class->lpszClassName;
189 wcex->hIconSm = Class->hIconSm;
190 return 1;
191 }
192
193 ULONG FASTCALL
194 W32kGetClassName(struct _WINDOW_OBJECT *WindowObject,
195 LPWSTR lpClassName,
196 ULONG nMaxCount)
197 {
198 ULONG length;
199 LPWSTR name;
200 BOOL free;
201 PWINSTATION_OBJECT WinStaObject;
202 NTSTATUS Status;
203 if (IS_ATOM(WindowObject->Class->lpszClassName))
204 {
205 DPRINT("About to open window station handle (0x%X)\n",
206 PROCESS_WINDOW_STATION());
207 Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
208 KernelMode,
209 0,
210 &WinStaObject);
211 if (!NT_SUCCESS(Status))
212 {
213 DPRINT("Validation of window station handle (0x%X) failed\n",
214 PROCESS_WINDOW_STATION());
215 return((RTL_ATOM)0);
216 }
217 length = 0;
218 Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,(RTL_ATOM)(size_t)WindowObject->Class->lpszClassName,NULL,NULL,name,&length);
219 name = ExAllocatePool(PagedPool,length+1);
220 free = TRUE;
221 Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,(RTL_ATOM)(size_t)WindowObject->Class->lpszClassName,NULL,NULL,name,&length);
222 if (!NT_SUCCESS(Status))
223 {
224 DPRINT("Validation of window station handle (0x%X) failed\n",
225 PROCESS_WINDOW_STATION());
226 return((RTL_ATOM)0);
227 }
228 ObDereferenceObject(WinStaObject);
229 }
230 else
231 {
232 name = WindowObject->Class->lpszClassName->Buffer;
233 length = WindowObject->Class->lpszClassName->Length / sizeof(WCHAR);
234 free = FALSE;
235 }
236 if (length > nMaxCount)
237 {
238 length = nMaxCount;
239 }
240 *(lpClassName+length) = 0;
241 wcsncpy(lpClassName,name,length);
242 if (free)
243 {
244 ExFreePool(name);
245 }
246 return length;
247 }
248
249 DWORD STDCALL
250 NtUserGetClassName (
251 HWND hWnd,
252 LPWSTR lpClassName,
253 ULONG nMaxCount)
254 {
255 PWINDOW_OBJECT WindowObject;
256 LONG Ret;
257
258 WindowObject = W32kGetWindowObject(hWnd);
259 if (WindowObject == NULL)
260 {
261 return(0);
262 }
263 Ret = W32kGetClassName(WindowObject, lpClassName, nMaxCount);
264 W32kReleaseWindowObject(WindowObject);
265 return(Ret);
266 }
267
268 DWORD STDCALL
269 NtUserGetWOWClass(DWORD Unknown0,
270 DWORD Unknown1)
271 {
272 UNIMPLEMENTED;
273 return(0);
274 }
275
276 PWNDCLASS_OBJECT FASTCALL
277 W32kCreateClass(CONST WNDCLASSEXW *lpwcx,
278 BOOL bUnicodeClass,
279 RTL_ATOM Atom)
280 {
281 PWNDCLASS_OBJECT ClassObject;
282 WORD objectSize;
283 objectSize = sizeof(WNDCLASS_OBJECT);
284 ClassObject = ObmCreateObject(NULL, NULL, otClass, objectSize);
285 if (ClassObject == 0)
286 {
287 return(NULL);
288 }
289
290 ClassObject->cbSize = lpwcx->cbSize;
291 ClassObject->style = lpwcx->style;
292 ClassObject->cbClsExtra = lpwcx->cbClsExtra;
293 ClassObject->cbWndExtra = lpwcx->cbWndExtra;
294 ClassObject->hInstance = lpwcx->hInstance;
295 ClassObject->hIcon = lpwcx->hIcon;
296 ClassObject->hCursor = lpwcx->hCursor;
297 ClassObject->hbrBackground = lpwcx->hbrBackground;
298 ClassObject->Unicode = bUnicodeClass;
299 ClassObject->hIconSm = lpwcx->hIconSm;
300 ClassObject->lpszClassName = (PUNICODE_STRING)(ULONG)Atom;
301 if (bUnicodeClass)
302 {
303 ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
304 ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc+0x80000000;
305 }
306 else
307 {
308 ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
309 ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc+0x80000000;
310 }
311 if (IS_INTRESOURCE(lpwcx->lpszMenuName))
312 {
313 ClassObject->lpszMenuName = (PUNICODE_STRING)lpwcx->lpszMenuName;
314 }
315 else
316 {
317 ClassObject->lpszMenuName = ExAllocatePool(NonPagedPool,sizeof(UNICODE_STRING));
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)dwNewLong+0x80000000;
508 WindowObject->Class->Unicode = FALSE;
509 }
510 else
511 {
512 WindowObject->Class->lpfnWndProcW = (WNDPROC)dwNewLong;
513 WindowObject->Class->lpfnWndProcA = (WNDPROC)dwNewLong+0x80000000;
514 WindowObject->Class->Unicode = TRUE;
515 }
516 break;
517 }
518 }
519
520 DWORD STDCALL
521 NtUserSetClassLong(HWND hWnd,
522 DWORD Offset,
523 LONG dwNewLong,
524 BOOL Ansi)
525 {
526 PWINDOW_OBJECT WindowObject;
527 LONG Ret;
528
529 WindowObject = W32kGetWindowObject(hWnd);
530 if (WindowObject == NULL)
531 {
532 return(0);
533 }
534 Ret = W32kGetClassLong(WindowObject, Offset, Ansi);
535 W32kSetClassLong(WindowObject, Offset, dwNewLong, Ansi);
536 W32kReleaseWindowObject(WindowObject);
537 return(Ret);
538 }
539
540 DWORD STDCALL
541 NtUserSetClassWord(DWORD Unknown0,
542 DWORD Unknown1,
543 DWORD Unknown2)
544 {
545 UNIMPLEMENTED;
546 return(0);
547 }
548
549 DWORD STDCALL
550 NtUserUnregisterClass(DWORD Unknown0,
551 DWORD Unknown1,
552 DWORD Unknown2)
553 {
554 UNIMPLEMENTED;
555 return(0);
556 }
557
558 /* EOF */