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