-include/ndk/rtltypes.h: add MAX_ATOM_LEN define
[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$
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 <w32k.h>
32
33 #define NDEBUG
34 #include <debug.h>
35
36 /* FUNCTIONS *****************************************************************/
37
38 NTSTATUS FASTCALL
39 InitClassImpl(VOID)
40 {
41 return(STATUS_SUCCESS);
42 }
43
44 NTSTATUS FASTCALL
45 CleanupClassImpl(VOID)
46 {
47 return(STATUS_SUCCESS);
48 }
49
50
51 /* return TRUE if class became destroyed */
52 inline VOID FASTCALL
53 ClassDerefObject(PWNDCLASS_OBJECT Class)
54 {
55 ASSERT(Class->refs >= 1);
56 Class->refs--;
57 }
58
59
60 inline VOID FASTCALL
61 ClassRefObject(PWNDCLASS_OBJECT Class)
62 {
63 ASSERT(Class->refs >= 0);
64 Class->refs++;
65 }
66
67
68 VOID FASTCALL DestroyClass(PWNDCLASS_OBJECT Class)
69 {
70 PWINSTATION_OBJECT WinSta;
71 WinSta = PsGetWin32Thread()->Desktop->WindowStation;
72
73 ASSERT(Class->refs == 0);
74 RemoveEntryList(&Class->ListEntry);
75 //FIXME: release ATOM
76 RtlDeleteAtomFromAtomTable(WinSta->AtomTable, Class->Atom);
77 ExFreePool(Class);
78 }
79
80
81 /* clean all process classes. all process windows must cleaned first!! */
82 void FASTCALL DestroyProcessClasses(PW32PROCESS Process )
83 {
84 PWNDCLASS_OBJECT Class;
85
86 while (!IsListEmpty(&Process->ClassList))
87 {
88 Class = CONTAINING_RECORD(RemoveHeadList(&Process->ClassList), WNDCLASS_OBJECT, ListEntry);
89 DestroyClass(Class);
90 }
91 }
92
93
94
95
96 PWNDCLASS_OBJECT FASTCALL
97 ClassGetClassByAtom(RTL_ATOM Atom, HINSTANCE hInstance)
98 {
99 PWNDCLASS_OBJECT Class;
100 PW32PROCESS Process = PsGetWin32Process();
101
102 LIST_FOR_EACH(Class, &Process->ClassList, WNDCLASS_OBJECT, ListEntry)
103 {
104 if (Class->Atom != Atom) continue;
105
106 if (!hInstance || Class->Global || Class->hInstance == hInstance) return Class;
107 }
108
109 return NULL;
110 }
111
112
113 PWNDCLASS_OBJECT FASTCALL
114 ClassGetClassByName(LPCWSTR ClassName, HINSTANCE hInstance)
115 {
116 PWINSTATION_OBJECT WinSta;
117 NTSTATUS Status;
118 RTL_ATOM Atom;
119
120 if (!ClassName || !PsGetWin32Thread()->Desktop)
121 return FALSE;
122
123 WinSta = PsGetWin32Thread()->Desktop->WindowStation;
124
125 Status = RtlLookupAtomInAtomTable(
126 WinSta->AtomTable,
127 (LPWSTR)ClassName,
128 &Atom);
129
130 if (!NT_SUCCESS(Status))
131 {
132 DPRINT1("Failed to lookup class atom!\n");
133 return FALSE;
134 }
135
136 return ClassGetClassByAtom(Atom, hInstance);
137 }
138
139
140 PWNDCLASS_OBJECT FASTCALL
141 ClassGetClassByNameOrAtom(LPCWSTR ClassNameOrAtom, HINSTANCE hInstance)
142 {
143 if (!ClassNameOrAtom) return NULL;
144
145 if (IS_ATOM(ClassNameOrAtom))
146 return ClassGetClassByAtom((RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance);
147 else
148 return ClassGetClassByName(ClassNameOrAtom, hInstance);
149 }
150
151
152 static
153 BOOL FASTCALL
154 IntRegisterClass(
155 CONST WNDCLASSEXW *lpwcx,
156 DWORD Flags,
157 WNDPROC wpExtra,
158 PUNICODE_STRING MenuName,
159 RTL_ATOM Atom)
160 {
161 PWNDCLASS_OBJECT Class;
162 ULONG objectSize;
163 BOOL Global;
164
165 ASSERT(lpwcx);
166 ASSERT(Atom);
167 ASSERT(lpwcx->hInstance);
168
169 Global = (Flags & REGISTERCLASS_SYSTEM) || (lpwcx->style & CS_GLOBALCLASS);
170
171 /* Check for double registration of the class. */
172 Class = ClassGetClassByAtom(Atom, lpwcx->hInstance);
173 if (Class && Global == Class->Global)
174 {
175 /* can max have one class of each type (global/local) */
176 SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
177 return(FALSE);
178 }
179
180 objectSize = sizeof(WNDCLASS_OBJECT) + lpwcx->cbClsExtra;
181
182 //FIXME: allocate in session heap (or possibly desktop heap)
183 Class = ExAllocatePool(PagedPool, objectSize);
184 if (!Class)
185 {
186 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
187 return(FALSE);
188 }
189 RtlZeroMemory(Class, objectSize);
190
191 Class->cbSize = lpwcx->cbSize;
192 Class->style = lpwcx->style;
193 Class->cbClsExtra = lpwcx->cbClsExtra;
194 Class->cbWndExtra = lpwcx->cbWndExtra;
195 Class->hInstance = lpwcx->hInstance;
196 Class->hIcon = lpwcx->hIcon;
197 Class->hCursor = lpwcx->hCursor;
198 Class->hbrBackground = lpwcx->hbrBackground;
199 Class->Unicode = !(Flags & REGISTERCLASS_ANSI);
200 Class->Global = Global;
201 Class->hIconSm = lpwcx->hIconSm;
202 Class->Atom = Atom;
203
204 if (wpExtra == NULL)
205 {
206 if (Flags & REGISTERCLASS_ANSI)
207 {
208 Class->lpfnWndProcA = lpwcx->lpfnWndProc;
209 Class->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
210 }
211 else
212 {
213 Class->lpfnWndProcW = lpwcx->lpfnWndProc;
214 Class->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
215 }
216 }
217 else
218 {
219 if (Flags & REGISTERCLASS_ANSI)
220 {
221 Class->lpfnWndProcA = lpwcx->lpfnWndProc;
222 Class->lpfnWndProcW = wpExtra;
223 }
224 else
225 {
226 Class->lpfnWndProcW = lpwcx->lpfnWndProc;
227 Class->lpfnWndProcA = wpExtra;
228 }
229 }
230
231 if (MenuName->Length == 0)
232 {
233 Class->lpszMenuName.Length =
234 Class->lpszMenuName.MaximumLength = 0;
235 Class->lpszMenuName.Buffer = MenuName->Buffer;
236 }
237 else
238 {
239 Class->lpszMenuName.Length =
240 Class->lpszMenuName.MaximumLength = MenuName->MaximumLength;
241 Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Class->lpszMenuName.MaximumLength, TAG_STRING);
242 RtlCopyUnicodeString(&Class->lpszMenuName, MenuName);
243 }
244
245 /* Extra class data */
246 if (Class->cbClsExtra)
247 Class->ExtraData = (PCHAR)(Class + 1);
248
249 if (Global)
250 {
251 /* global classes go last (incl. system classes) */
252 InsertTailList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
253 }
254 else
255 {
256 /* local classes have priority so we put them first */
257 InsertHeadList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
258 }
259
260 return TRUE;
261 }
262
263
264 ULONG FASTCALL
265 IntGetClassLong(PWINDOW_OBJECT Window, ULONG Offset, BOOL Ansi)
266 {
267 LONG Ret;
268
269 if ((int)Offset >= 0)
270 {
271 DPRINT("GetClassLong(%x, %d)\n", Window->hSelf, Offset);
272 if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra)
273 {
274 SetLastWin32Error(ERROR_INVALID_PARAMETER);
275 return 0;
276 }
277 Ret = *((LONG *)(Window->Class->ExtraData + Offset));
278 DPRINT("Result: %x\n", Ret);
279 return Ret;
280 }
281
282 switch (Offset)
283 {
284 case GCL_CBWNDEXTRA:
285 Ret = Window->Class->cbWndExtra;
286 break;
287 case GCL_CBCLSEXTRA:
288 Ret = Window->Class->cbClsExtra;
289 break;
290 case GCL_HBRBACKGROUND:
291 Ret = (ULONG)Window->Class->hbrBackground;
292 break;
293 case GCL_HCURSOR:
294 Ret = (ULONG)Window->Class->hCursor;
295 break;
296 case GCL_HICON:
297 Ret = (ULONG)Window->Class->hIcon;
298 break;
299 case GCL_HICONSM:
300 Ret = (ULONG)Window->Class->hIconSm;
301 break;
302 case GCL_HMODULE:
303 Ret = (ULONG)Window->Class->hInstance;
304 break;
305 case GCL_MENUNAME:
306 Ret = (ULONG)Window->Class->lpszMenuName.Buffer;
307 break;
308 case GCL_STYLE:
309 Ret = Window->Class->style;
310 break;
311 case GCL_WNDPROC:
312 if (Ansi)
313 {
314 Ret = (ULONG)Window->Class->lpfnWndProcA;
315 }
316 else
317 {
318 Ret = (ULONG)Window->Class->lpfnWndProcW;
319 }
320 break;
321 case GCW_ATOM:
322 Ret = Window->Class->Atom;
323 break;
324 default:
325 Ret = 0;
326 break;
327 }
328 return(Ret);
329 }
330
331 static
332 void FASTCALL
333 co_IntSetClassLong(PWINDOW_OBJECT Window, ULONG Offset, LONG dwNewLong, BOOL Ansi)
334 {
335 ASSERT_REFS_CO(Window);
336
337 if ((int)Offset >= 0)
338 {
339 DPRINT("SetClassLong(%x, %d, %x)\n", Window->hSelf, Offset, dwNewLong);
340 if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra)
341 {
342 SetLastWin32Error(ERROR_INVALID_PARAMETER);
343 return;
344 }
345 *((LONG *)(Window->Class->ExtraData + Offset)) = dwNewLong;
346 return;
347 }
348
349 switch (Offset)
350 {
351 case GCL_CBWNDEXTRA:
352 Window->Class->cbWndExtra = dwNewLong;
353 break;
354 case GCL_CBCLSEXTRA:
355 Window->Class->cbClsExtra = dwNewLong;
356 break;
357 case GCL_HBRBACKGROUND:
358 Window->Class->hbrBackground = (HBRUSH)dwNewLong;
359 break;
360 case GCL_HCURSOR:
361 Window->Class->hCursor = (HCURSOR)dwNewLong;
362 break;
363 case GCL_HICON:
364 Window->Class->hIcon = (HICON)dwNewLong;
365
366 if (!IntGetOwner(Window) && !IntGetParent(Window))
367 {
368 co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) Window->hSelf);
369 }
370 break;
371 case GCL_HICONSM:
372 Window->Class->hIconSm = (HICON)dwNewLong;
373 break;
374 case GCL_HMODULE:
375 Window->Class->hInstance = (HINSTANCE)dwNewLong;
376 break;
377 case GCL_MENUNAME:
378 if (Window->Class->lpszMenuName.MaximumLength)
379 RtlFreeUnicodeString(&Window->Class->lpszMenuName);
380 if (!IS_INTRESOURCE(dwNewLong))
381 {
382 Window->Class->lpszMenuName.Length =
383 Window->Class->lpszMenuName.MaximumLength = ((PUNICODE_STRING)dwNewLong)->MaximumLength;
384 Window->Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Window->Class->lpszMenuName.MaximumLength, TAG_STRING);
385 RtlCopyUnicodeString(&Window->Class->lpszMenuName, (PUNICODE_STRING)dwNewLong);
386 }
387 else
388 {
389 Window->Class->lpszMenuName.Length =
390 Window->Class->lpszMenuName.MaximumLength = 0;
391 Window->Class->lpszMenuName.Buffer = (LPWSTR)dwNewLong;
392 }
393 break;
394 case GCL_STYLE:
395 Window->Class->style = dwNewLong;
396 break;
397 case GCL_WNDPROC:
398 if (Ansi)
399 {
400 Window->Class->lpfnWndProcA = (WNDPROC)dwNewLong;
401 Window->Class->lpfnWndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,FALSE);
402 Window->Class->Unicode = FALSE;
403 }
404 else
405 {
406 Window->Class->lpfnWndProcW = (WNDPROC)dwNewLong;
407 Window->Class->lpfnWndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,TRUE);
408 Window->Class->Unicode = TRUE;
409 }
410 break;
411 }
412 }
413 /* SYSCALLS *****************************************************************/
414
415
416 RTL_ATOM STDCALL
417 NtUserRegisterClassExWOW(
418 CONST WNDCLASSEXW* lpwcx,
419 PUNICODE_STRING ClassName,
420 PUNICODE_STRING ClassNameCopy,//huhuhuhu???
421 PUNICODE_STRING MenuName,
422 WNDPROC wpExtra,
423 DWORD Flags,
424 DWORD Unknown7)
425
426 /*
427 * FUNCTION:
428 * Registers a new class with the window manager
429 * ARGUMENTS:
430 * lpwcx = Win32 extended window class structure
431 * bUnicodeClass = Whether to send ANSI or unicode strings
432 * to window procedures
433 * wpExtra = Extra window procedure, if this is not null, its used for the second window procedure for standard controls.
434 * RETURNS:
435 * Atom identifying the new class
436 */
437 {
438 WNDCLASSEXW SafeClass;
439 PWINSTATION_OBJECT WinSta;
440 NTSTATUS Status;
441 RTL_ATOM Atom;
442 DECLARE_RETURN(RTL_ATOM);
443
444 DPRINT("Enter NtUserRegisterClassExWOW\n");
445 UserEnterExclusive();
446
447 if (!lpwcx)
448 {
449 SetLastWin32Error(ERROR_INVALID_PARAMETER);
450 RETURN( (RTL_ATOM)0);
451 }
452
453 if (Flags & ~REGISTERCLASS_ALL)
454 {
455 SetLastWin32Error(ERROR_INVALID_FLAGS);
456 RETURN( (RTL_ATOM)0);
457 }
458
459 Status = MmCopyFromCaller(&SafeClass, lpwcx, sizeof(WNDCLASSEXW));
460 if (!NT_SUCCESS(Status))
461 {
462 SetLastNtError(Status);
463 RETURN( (RTL_ATOM)0);
464 }
465
466 /* Deny negative sizes */
467 if (lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0)
468 {
469 SetLastWin32Error(ERROR_INVALID_PARAMETER);
470 RETURN( (RTL_ATOM)0);
471 }
472
473 if (!lpwcx->hInstance)
474 {
475 SetLastWin32Error(ERROR_INVALID_PARAMETER);
476 RETURN( (RTL_ATOM)0);
477 }
478
479 WinSta = PsGetWin32Thread()->Desktop->WindowStation;
480
481 //FIXME: make ClassName ptr the atom, not buffer
482 if (ClassName->Length > 0)
483 {
484 DPRINT("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer);
485 /* FIXME - Safely copy/verify the buffer first!!! */
486 Status = RtlAddAtomToAtomTable(WinSta->AtomTable,
487 ClassName->Buffer,
488 &Atom);
489 if (!NT_SUCCESS(Status))
490 {
491 DPRINT1("Failed adding class name (%S) to atom table\n",
492 ClassName->Buffer);
493 SetLastNtError(Status);
494 RETURN((RTL_ATOM)0);
495 }
496 }
497 else
498 {
499 Atom = (RTL_ATOM)(ULONG)ClassName->Buffer;
500 }
501
502 if (!Atom)
503 {
504 SetLastWin32Error(ERROR_INVALID_PARAMETER);
505 RETURN(0);
506 }
507
508 if (!IntRegisterClass(&SafeClass, Flags, wpExtra, MenuName, Atom))
509 {
510 if (ClassName->Length)
511 {
512 RtlDeleteAtomFromAtomTable(WinSta->AtomTable, Atom);
513 }
514 DPRINT("Failed creating window class object\n");
515 RETURN((RTL_ATOM)0);
516 }
517
518 RETURN(Atom);
519
520 CLEANUP:
521 DPRINT("Leave NtUserRegisterClassExWOW, ret=%i\n",_ret_);
522 UserLeave();
523 END_CLEANUP;
524 }
525
526
527
528 DWORD STDCALL
529 NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
530 {
531 PWINDOW_OBJECT Window;
532 DECLARE_RETURN(DWORD);
533
534 DPRINT("Enter NtUserGetClassLong\n");
535 UserEnterExclusive();
536
537 if (!(Window = UserGetWindowObject(hWnd)))
538 {
539 RETURN(0);
540 }
541
542 RETURN(IntGetClassLong(Window, Offset, Ansi));
543
544 CLEANUP:
545 DPRINT("Leave NtUserGetClassLong, ret=%i\n",_ret_);
546 UserLeave();
547 END_CLEANUP;
548 }
549
550
551
552 DWORD STDCALL
553 NtUserSetClassLong(HWND hWnd,
554 DWORD Offset,
555 LONG dwNewLong,
556 BOOL Ansi)
557 {
558 PWINDOW_OBJECT Window;
559 LONG Ret;
560 DECLARE_RETURN(DWORD);
561
562 DPRINT("Enter NtUserSetClassLong\n");
563 UserEnterExclusive();
564
565 if (!(Window = UserGetWindowObject(hWnd)))
566 {
567 RETURN(0);
568 }
569
570 UserRefObjectCo(Window);
571
572 Ret = IntGetClassLong(Window, Offset, Ansi);
573 co_IntSetClassLong(Window, Offset, dwNewLong, Ansi);
574
575 UserDerefObjectCo(Window);
576
577 RETURN(Ret);
578
579 CLEANUP:
580 DPRINT("Leave NtUserSetClassLong, ret=%i\n",_ret_);
581 UserLeave();
582 END_CLEANUP;
583 }
584
585 DWORD STDCALL
586 NtUserSetClassWord(DWORD Unknown0,
587 DWORD Unknown1,
588 DWORD Unknown2)
589 {
590 UNIMPLEMENTED;
591 return(0);
592 }
593
594 BOOL STDCALL
595 NtUserUnregisterClass(
596 LPCWSTR ClassNameOrAtom,
597 HINSTANCE hInstance, /* can be 0 */
598 DWORD Unknown)
599 {
600 PWNDCLASS_OBJECT Class;
601 DECLARE_RETURN(BOOL);
602
603 DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
604 UserEnterExclusive();
605
606 if (!ClassNameOrAtom)
607 {
608 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
609 RETURN(FALSE);
610 }
611
612 if (!(Class = ClassGetClassByNameOrAtom(ClassNameOrAtom, hInstance)))
613 {
614 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
615 RETURN(FALSE);
616 }
617
618 /* this was probably ment to prevent sysclass dereg
619 Seems wrong. Any class can have NULL hInst, not only sysclasses
620
621 */
622 // if (Class->hInstance && Class->hInstance != hInstance)
623 // {
624 // SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
625 // RETURN( FALSE);
626 // }
627
628 if (Class->refs)
629 {
630 /* NOTE: the class will not be freed when its refs become 0 ie. no more
631 * windows are using it. I dunno why that is but its how Windows does it (and Wine).
632 * The class will hang around until the process exit. -Gunnar
633 */
634 SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
635 RETURN(FALSE);
636 }
637
638 DestroyClass(Class);
639
640 RETURN(TRUE);
641
642 CLEANUP:
643 DPRINT("Leave NtUserUnregisterClass, ret=%i\n",_ret_);
644 UserLeave();
645 END_CLEANUP;
646 }
647
648 /* NOTE: for system classes hInstance is not NULL here, but User32Instance */
649 DWORD STDCALL
650 NtUserGetClassInfo(
651 HINSTANCE hInstance,
652 LPCWSTR lpClassName,
653 LPWNDCLASSEXW lpWndClassEx,
654 BOOL Ansi,
655 DWORD unknown3)
656 {
657 PWNDCLASS_OBJECT Class;
658 RTL_ATOM Atom;
659 DECLARE_RETURN(DWORD);
660
661 if (IS_ATOM(lpClassName))
662 DPRINT("NtUserGetClassInfo - %x (%lx)\n", lpClassName, hInstance);
663 else
664 DPRINT("NtUserGetClassInfo - %S (%lx)\n", lpClassName, hInstance);
665
666 UserEnterExclusive();
667
668 if (!hInstance)
669 {
670 SetLastWin32Error(ERROR_INVALID_PARAMETER);
671 RETURN(0);
672 }
673
674 if (!(Class = ClassGetClassByNameOrAtom(lpClassName, hInstance)))
675 {
676 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
677 RETURN(0);
678 }
679
680 lpWndClassEx->cbSize = sizeof(WNDCLASSEXW);
681 lpWndClassEx->style = Class->style;
682 if (Ansi)
683 lpWndClassEx->lpfnWndProc = Class->lpfnWndProcA;
684 else
685 lpWndClassEx->lpfnWndProc = Class->lpfnWndProcW;
686 lpWndClassEx->cbClsExtra = Class->cbClsExtra;
687 lpWndClassEx->cbWndExtra = Class->cbWndExtra;
688 /* This is not typo, we're really not going to use Class->hInstance here. */
689 /* Well, i think its wrong so i changed it -Gunnar */
690 lpWndClassEx->hInstance = Class->hInstance;
691 lpWndClassEx->hIcon = Class->hIcon;
692 lpWndClassEx->hCursor = Class->hCursor;
693 lpWndClassEx->hbrBackground = Class->hbrBackground;
694 if (Class->lpszMenuName.MaximumLength)
695 RtlCopyUnicodeString((PUNICODE_STRING)lpWndClassEx->lpszMenuName, &Class->lpszMenuName);
696 else
697 lpWndClassEx->lpszMenuName = Class->lpszMenuName.Buffer;
698 lpWndClassEx->lpszClassName = lpClassName;
699 lpWndClassEx->hIconSm = Class->hIconSm;
700 Atom = Class->Atom;
701
702 RETURN(Atom);
703
704 CLEANUP:
705 DPRINT("Leave NtUserGetClassInfo, ret=%i\n",_ret_);
706 UserLeave();
707 END_CLEANUP;
708 }
709
710
711
712 DWORD STDCALL
713 NtUserGetClassName (
714 HWND hWnd,
715 LPWSTR lpClassName,
716 ULONG nMaxCount /* in TCHARS */
717 )
718 {
719 PWINDOW_OBJECT Window;
720 DECLARE_RETURN(DWORD);
721 PWINSTATION_OBJECT WinSta;
722 NTSTATUS Status;
723
724 UserEnterShared();
725 DPRINT("Enter NtUserGetClassName\n");
726
727 if (!(Window = UserGetWindowObject(hWnd)))
728 {
729 RETURN(0);
730 }
731
732 WinSta = PsGetWin32Thread()->Desktop->WindowStation;
733
734 nMaxCount *= sizeof(WCHAR);
735
736 //FIXME: wrap in SEH to protect lpClassName access
737 Status = RtlQueryAtomInAtomTable(WinSta->AtomTable,
738 Window->Class->Atom, NULL, NULL,
739 lpClassName, &nMaxCount);
740 if (!NT_SUCCESS(Status))
741 {
742 SetLastNtError(Status);
743 RETURN(0);
744 }
745
746 RETURN(nMaxCount / sizeof(WCHAR));
747
748 CLEANUP:
749 DPRINT("Leave NtUserGetClassName, ret=%i\n",_ret_);
750 UserLeave();
751 END_CLEANUP;
752 }
753
754 DWORD STDCALL
755 NtUserGetWOWClass(DWORD Unknown0,
756 DWORD Unknown1)
757 {
758 UNIMPLEMENTED;
759 return(0);
760 }
761
762
763 /* EOF */