naming changes:
[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 WindowObject;
239 LONG Length;
240 DECLARE_RETURN(DWORD);
241
242 UserEnterShared();
243
244 WindowObject = IntGetWindowObject(hWnd);
245 if (WindowObject == NULL)
246 {
247 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
248 RETURN(0);
249 }
250 Length = IntGetClassName(WindowObject, lpClassName, nMaxCount);
251 IntReleaseWindowObject(WindowObject);
252 RETURN(Length);
253
254 CLEANUP:
255 DPRINT("Leave NtUserGetClassName, ret=%i\n",_ret_);
256 UserLeave();
257 END_CLEANUP;
258 }
259
260 DWORD STDCALL
261 NtUserGetWOWClass(DWORD Unknown0,
262 DWORD Unknown1)
263 {
264 UNIMPLEMENTED;
265 return(0);
266 }
267
268 PWNDCLASS_OBJECT FASTCALL
269 IntCreateClass(
270 CONST WNDCLASSEXW *lpwcx,
271 DWORD Flags,
272 WNDPROC wpExtra,
273 PUNICODE_STRING MenuName,
274 RTL_ATOM Atom)
275 {
276 PWNDCLASS_OBJECT ClassObject;
277 ULONG objectSize;
278 BOOL Global;
279
280 Global = (Flags & REGISTERCLASS_SYSTEM) || (lpwcx->style & CS_GLOBALCLASS) ? TRUE : FALSE;
281
282 /* Check for double registration of the class. */
283 if (PsGetWin32Process() != NULL)
284 {
285 if (ClassReferenceClassByAtom(&ClassObject, Atom, lpwcx->hInstance))
286 {
287 /*
288 * NOTE: We may also get a global class from
289 * ClassReferenceClassByAtom. This simple check
290 * prevents that we fail valid request.
291 */
292 if (ClassObject->hInstance == lpwcx->hInstance)
293 {
294 SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
295 ObmDereferenceObject(ClassObject);
296 return(NULL);
297 }
298 }
299 }
300
301 objectSize = sizeof(WNDCLASS_OBJECT) + lpwcx->cbClsExtra;
302 ClassObject = ObmCreateObject(NULL, NULL, otClass, objectSize);
303 if (ClassObject == 0)
304 {
305 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
306 return(NULL);
307 }
308
309 ClassObject->cbSize = lpwcx->cbSize;
310 ClassObject->style = lpwcx->style;
311 ClassObject->cbClsExtra = lpwcx->cbClsExtra;
312 ClassObject->cbWndExtra = lpwcx->cbWndExtra;
313 ClassObject->hInstance = lpwcx->hInstance;
314 ClassObject->hIcon = lpwcx->hIcon;
315 ClassObject->hCursor = lpwcx->hCursor;
316 ClassObject->hbrBackground = lpwcx->hbrBackground;
317 ClassObject->Unicode = !(Flags & REGISTERCLASS_ANSI);
318 ClassObject->Global = Global;
319 ClassObject->hIconSm = lpwcx->hIconSm;
320 ClassObject->Atom = Atom;
321 if (wpExtra == NULL) {
322 if (Flags & REGISTERCLASS_ANSI)
323 {
324 ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
325 ClassObject->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
326 }
327 else
328 {
329 ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
330 ClassObject->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
331 }
332 } else {
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 default:
531 Ret = 0;
532 break;
533 }
534 return(Ret);
535 }
536
537 DWORD STDCALL
538 NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
539 {
540 PWINDOW_OBJECT Window;
541 LONG Ret;
542 DECLARE_RETURN(DWORD);
543
544 DPRINT("Enter NtUserGetClassLong\n");
545 UserEnterExclusive();
546
547 Window = IntGetWindowObject(hWnd);
548 if (Window == NULL)
549 {
550 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
551 RETURN(0);
552 }
553 Ret = IntGetClassLong(Window, Offset, Ansi);
554 IntReleaseWindowObject(Window);
555 RETURN(Ret);
556
557 CLEANUP:
558 DPRINT("Leave NtUserGetClassLong, ret=%i\n",_ret_);
559 UserLeave();
560 END_CLEANUP;
561 }
562
563 void FASTCALL
564 co_IntSetClassLong(PWINDOW_OBJECT Window, ULONG Offset, LONG dwNewLong, BOOL Ansi)
565 {
566 PWINDOW_OBJECT Parent, Owner;
567
568 if ((int)Offset >= 0)
569 {
570 DPRINT("SetClassLong(%x, %d, %x)\n", Window->hSelf, Offset, dwNewLong);
571 if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra)
572 {
573 SetLastWin32Error(ERROR_INVALID_PARAMETER);
574 return;
575 }
576 *((LONG *)(Window->Class->ExtraData + Offset)) = dwNewLong;
577 return;
578 }
579
580 switch (Offset)
581 {
582 case GCL_CBWNDEXTRA:
583 Window->Class->cbWndExtra = dwNewLong;
584 break;
585 case GCL_CBCLSEXTRA:
586 Window->Class->cbClsExtra = dwNewLong;
587 break;
588 case GCL_HBRBACKGROUND:
589 Window->Class->hbrBackground = (HBRUSH)dwNewLong;
590 break;
591 case GCL_HCURSOR:
592 Window->Class->hCursor = (HCURSOR)dwNewLong;
593 break;
594 case GCL_HICON:
595 Window->Class->hIcon = (HICON)dwNewLong;
596 Owner = IntGetOwner(Window);
597 Parent = IntGetParent(Window);
598
599 if ((!Owner) && (!Parent))
600 {
601 co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) Window->hSelf);
602 }
603
604 if (Parent)
605 {
606 IntReleaseWindowObject(Parent);
607 }
608
609 if (Owner)
610 {
611 IntReleaseWindowObject(Owner);
612 }
613
614
615 break;
616 case GCL_HICONSM:
617 Window->Class->hIconSm = (HICON)dwNewLong;
618 break;
619 case GCL_HMODULE:
620 Window->Class->hInstance = (HINSTANCE)dwNewLong;
621 break;
622 case GCL_MENUNAME:
623 if (Window->Class->lpszMenuName.MaximumLength)
624 RtlFreeUnicodeString(&Window->Class->lpszMenuName);
625 if (!IS_INTRESOURCE(dwNewLong))
626 {
627 Window->Class->lpszMenuName.Length =
628 Window->Class->lpszMenuName.MaximumLength = ((PUNICODE_STRING)dwNewLong)->MaximumLength;
629 Window->Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Window->Class->lpszMenuName.MaximumLength, TAG_STRING);
630 RtlCopyUnicodeString(&Window->Class->lpszMenuName, (PUNICODE_STRING)dwNewLong);
631 }
632 else
633 {
634 Window->Class->lpszMenuName.Length =
635 Window->Class->lpszMenuName.MaximumLength = 0;
636 Window->Class->lpszMenuName.Buffer = (LPWSTR)dwNewLong;
637 }
638 break;
639 case GCL_STYLE:
640 Window->Class->style = dwNewLong;
641 break;
642 case GCL_WNDPROC:
643 if (Ansi)
644 {
645 Window->Class->lpfnWndProcA = (WNDPROC)dwNewLong;
646 Window->Class->lpfnWndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,FALSE);
647 Window->Class->Unicode = FALSE;
648 }
649 else
650 {
651 Window->Class->lpfnWndProcW = (WNDPROC)dwNewLong;
652 Window->Class->lpfnWndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,TRUE);
653 Window->Class->Unicode = TRUE;
654 }
655 break;
656 }
657 }
658
659 DWORD STDCALL
660 NtUserSetClassLong(HWND hWnd,
661 DWORD Offset,
662 LONG dwNewLong,
663 BOOL Ansi)
664 {
665 PWINDOW_OBJECT Window;
666 LONG Ret;
667 DECLARE_RETURN(DWORD);
668
669 DPRINT("Enter NtUserSetClassLong\n");
670 UserEnterExclusive();
671
672 if (!(Window = IntGetWindowObject(hWnd)))
673 {
674 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
675 RETURN(0);
676 }
677 Ret = IntGetClassLong(Window, Offset, Ansi);
678 co_IntSetClassLong(Window, Offset, dwNewLong, Ansi);
679 IntReleaseWindowObject(Window);
680 RETURN(Ret);
681
682 CLEANUP:
683 DPRINT("Leave NtUserSetClassLong, ret=%i\n",_ret_);
684 UserLeave();
685 END_CLEANUP;
686 }
687
688 DWORD STDCALL
689 NtUserSetClassWord(DWORD Unknown0,
690 DWORD Unknown1,
691 DWORD Unknown2)
692 {
693 UNIMPLEMENTED;
694 return(0);
695 }
696
697 BOOL STDCALL
698 NtUserUnregisterClass(
699 LPCWSTR ClassNameOrAtom,
700 HINSTANCE hInstance,
701 DWORD Unknown)
702 {
703 PWNDCLASS_OBJECT Class;
704 PWINSTATION_OBJECT WinSta;
705 DECLARE_RETURN(BOOL);
706
707 DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
708 UserEnterExclusive();
709
710 if (!ClassNameOrAtom || !PsGetWin32Thread()->Desktop)
711 {
712 SetLastWin32Error(ERROR_INVALID_PARAMETER);
713 RETURN( FALSE);
714 }
715
716 WinSta = PsGetWin32Thread()->Desktop->WindowStation;
717
718 if (!ClassReferenceClassByNameOrAtom(&Class, ClassNameOrAtom, hInstance))
719 {
720 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
721 RETURN( FALSE);
722 }
723
724 if (Class->hInstance && Class->hInstance != hInstance)
725 {
726 ClassDereferenceObject(Class);
727 SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
728 RETURN( FALSE);
729 }
730
731 if (!IsListEmpty(&Class->ClassWindowsListHead))
732 {
733 /* Dereference the ClassReferenceClassByNameOrAtom() call */
734 ObmDereferenceObject(Class);
735 SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
736 RETURN( FALSE);
737 }
738
739 /* Dereference the ClassReferenceClassByNameOrAtom() call */
740 ClassDereferenceObject(Class);
741
742 RemoveEntryList(&Class->ListEntry);
743
744 RtlDeleteAtomFromAtomTable(WinSta->AtomTable, Class->Atom);
745
746 /* Free the object */
747 ClassDereferenceObject(Class);
748
749 RETURN( TRUE);
750
751 CLEANUP:
752 DPRINT("Leave NtUserUnregisterClass, ret=%i\n",_ret_);
753 UserLeave();
754 END_CLEANUP;
755 }
756
757 /* EOF */