ReactOS 0.4.15-dev-7842-g558ab78
class.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Window classes
5 * FILE: win32ss/user/ntuser/class.c
6 * PROGRAMER: Thomas Weidenmueller <w3seek@reactos.com>
7 */
8
9#include <win32k.h>
11
13{
14 L"Button",
15 L"Edit",
16 L"Static",
17 L"ListBox",
18 L"ScrollBar",
19 L"ComboBox",
20 L"MDIClient",
21 L"ComboLBox",
22 L"DDEMLEvent",
23 L"DDEMLMom",
24 L"DMGClass",
25 L"DDEMLAnsiClient",
26 L"DDEMLUnicodeClient",
27 L"DDEMLAnsiServer",
28 L"DDEMLUnicodeServer",
29 L"IME",
30 L"Ghost",
31};
32
34
36{
37 { ((PWSTR)WC_DESKTOP),
39 NULL, // Use User32 procs
40 sizeof(ULONG)*2,
41 (HICON)OCR_NORMAL,
42 (HBRUSH)(COLOR_BACKGROUND),
45 },
46 { ((PWSTR)WC_SWITCH),
48 NULL, // Use User32 procs
49 sizeof(LONG_PTR), // See user32_apitest GetClassInfo, 0: Pointer to ALTTABINFO
50 (HICON)OCR_NORMAL,
51 NULL,
54 },
55 { ((PWSTR)WC_MENU),
57 NULL, // Use User32 procs
58 16, // See user32_apitest GetClassInfo, PopupMenuWndProcW
59 (HICON)OCR_NORMAL,
60 (HBRUSH)(COLOR_MENU + 1),
63 },
64 { L"ScrollBar",
66 NULL, // Use User32 procs
67 sizeof(SBWND)-sizeof(WND),
68 (HICON)OCR_NORMAL,
69 NULL,
72 },
73#if 0
74 { ((PWSTR)((ULONG_PTR)(WORD)(0x8006))), // Tooltips
76 NULL, // Use User32 procs
77 0,
78 (HICON)OCR_NORMAL,
79 0,
82 },
83#endif
84 { ((PWSTR)WC_ICONTITLE), // IconTitle is here for now...
85 0,
86 NULL, // Use User32 procs
87 0,
88 (HICON)OCR_NORMAL,
89 0,
92 },
93 { L"Message",
95 NULL, // Use User32 procs
96 0,
97 (HICON)OCR_NORMAL,
98 NULL,
100 ICLS_HWNDMESSAGE
101 }
102};
103
104static struct
105{
106 int FnId;
107 int ClsId;
108} FnidToiCls[] =
109{ /* Function Ids to Class indexes. */
115 { FNID_MESSAGEWND, ICLS_HWNDMESSAGE},
124 { FNID_IME, ICLS_IME},
128
129BOOL
131LookupFnIdToiCls(int FnId, int *iCls )
132{
133 int i;
134
135 for ( i = 0; i < ARRAYSIZE(FnidToiCls); i++)
136 {
137 if (FnidToiCls[i].FnId == FnId)
138 {
139 if (iCls) *iCls = FnidToiCls[i].ClsId;
140 return TRUE;
141 }
142 }
143 if (iCls) *iCls = 0;
144 return FALSE;
145}
146
149NTAPI
151 _Out_ _When_(return>=0, _At_(pustrOut->Buffer, _Post_ _Notnull_)) PUNICODE_STRING pustrOut,
152 __in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe)
153{
155 UNICODE_STRING ustrCopy;
156
157 /* Default to NULL */
158 RtlInitEmptyUnicodeString(pustrOut, NULL, 0);
159
161 {
162 ProbeForRead(pustrUnsafe, sizeof(UNICODE_STRING), 1);
163
164 ustrCopy = *pustrUnsafe;
165
166 /* Validate the string */
167 if ((ustrCopy.Length & 1) || (ustrCopy.Buffer == NULL))
168 {
169 /* This is not legal */
171 }
172
173 /* Check if this is an atom */
174 if (IS_ATOM(ustrCopy.Buffer))
175 {
176 /* Copy the atom, length is 0 */
177 pustrOut->MaximumLength = pustrOut->Length = 0;
178 pustrOut->Buffer = ustrCopy.Buffer;
179 }
180 else
181 {
182 /* Get the length, maximum length includes zero termination */
183 pustrOut->Length = ustrCopy.Length;
184 pustrOut->MaximumLength = pustrOut->Length + sizeof(WCHAR);
185
186 /* Allocate a buffer */
187 pustrOut->Buffer = ExAllocatePoolWithTag(PagedPool,
188 pustrOut->MaximumLength,
189 TAG_STRING);
190 if (!pustrOut->Buffer)
191 {
193 }
194
195 /* Copy the string and zero terminate it */
196 ProbeForRead(ustrCopy.Buffer, pustrOut->Length, 1);
197 RtlCopyMemory(pustrOut->Buffer, ustrCopy.Buffer, pustrOut->Length);
198 pustrOut->Buffer[pustrOut->Length / sizeof(WCHAR)] = L'\0';
199 }
200 }
202 {
203 /* Check if we already allocated a buffer */
204 if (pustrOut->Buffer)
205 {
206 /* Free the buffer */
207 ExFreePoolWithTag(pustrOut->Buffer, TAG_STRING);
209 }
210 }
211 _SEH2_END;
212
213 return Status;
214}
215
216/* WINDOWCLASS ***************************************************************/
217
218static VOID
220{
221 /* Free the menu name, if it was changed and allocated */
222 if (Class->lpszClientUnicodeMenuName != NULL && Class->MenuNameIsString)
223 {
224 UserHeapFree(Class->lpszClientUnicodeMenuName);
225 Class->lpszClientUnicodeMenuName = NULL;
226 Class->lpszClientAnsiMenuName = NULL;
227 }
228}
229
230static VOID
232{
233 PDESKTOP pDesk;
234
235 /* There shouldn't be any clones anymore */
236 ASSERT(Class->cWndReferenceCount == 0);
237 ASSERT(Class->pclsClone == NULL);
238
239 if (Class->pclsBase == Class)
240 {
241 PCALLPROCDATA CallProc, NextCallProc;
242
243 /* Destroy allocated callproc handles */
244 CallProc = Class->spcpdFirst;
245 while (CallProc != NULL)
246 {
247 NextCallProc = CallProc->spcpdNext;
248
249 CallProc->spcpdNext = NULL;
250 DestroyCallProc(CallProc);
251
252 CallProc = NextCallProc;
253 }
254
255 // Fixes running the static test then run class test issue.
256 // Some applications do not use UnregisterClass before exiting.
257 // Keep from reusing the same atom with case insensitive
258 // comparisons, remove registration of the atom if not zeroed.
259 if (Class->atomClassName)
260 IntDeregisterClassAtom(Class->atomClassName);
261 // Dereference non-versioned class name
262 if (Class->atomNVClassName)
263 IntDeregisterClassAtom(Class->atomNVClassName);
264
265 if (Class->pdce)
266 {
267 DceFreeClassDCE(Class->pdce);
268 Class->pdce = NULL;
269 }
270
272 }
273
274 if (Class->spicn)
276 if (Class->spcur)
278 if (Class->spicnSm)
279 {
281 /* Destroy the icon if we own it */
282 if ((Class->CSF_flags & CSF_CACHEDSMICON)
285 }
286
287 pDesk = Class->rpdeskParent;
288 Class->rpdeskParent = NULL;
289
290 /* Free the structure */
291 if (pDesk != NULL)
292 {
293 DesktopHeapFree(pDesk, Class);
294 }
295 else
296 {
298 }
299}
300
301
302/* Clean all process classes. all process windows must cleaned first!! */
304{
305 PCLS Class;
307
308 if (pi != NULL)
309 {
310 /* Free all local classes */
311 Class = pi->pclsPrivateList;
312 while (Class != NULL)
313 {
314 pi->pclsPrivateList = Class->pclsNext;
315
316 ASSERT(Class->pclsBase == Class);
318
319 Class = pi->pclsPrivateList;
320 }
321
322 /* Free all global classes */
323 Class = pi->pclsPublicList;
324 while (Class != NULL)
325 {
326 pi->pclsPublicList = Class->pclsNext;
327
328 ASSERT(Class->pclsBase == Class);
330
331 Class = pi->pclsPublicList;
332 }
333 }
334}
335
336static BOOL
338 OUT RTL_ATOM *pAtom)
339{
340 WCHAR szBuf[65];
341 PWSTR AtomName = szBuf;
343
344 if (ClassName->Length != 0)
345 {
346 if (ClassName->Length + sizeof(UNICODE_NULL) > sizeof(szBuf))
347 {
349 ClassName->Length + sizeof(UNICODE_NULL),
350 TAG_USTR);
351
352 if (AtomName == NULL)
353 {
355 return FALSE;
356 }
357 }
358
360 {
361 RtlCopyMemory(AtomName,
362 ClassName->Buffer,
363 ClassName->Length);
364 }
366 {
367 if (AtomName != szBuf)
368 ExFreePoolWithTag(AtomName, TAG_USTR);
370 _SEH2_YIELD(return FALSE);
371 }
372 _SEH2_END;
373 AtomName[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
374 }
375 else
376 {
377 ASSERT(IS_ATOM(ClassName->Buffer));
378 AtomName = ClassName->Buffer;
379 }
380
382 AtomName,
383 pAtom);
384
385 if (AtomName != ClassName->Buffer && AtomName != szBuf)
386 ExFreePoolWithTag(AtomName, TAG_USTR);
387
388
389 if (!NT_SUCCESS(Status))
390 {
392 return FALSE;
393 }
394
395 return TRUE;
396}
397
400{
402 UNICODE_STRING ClassName;
403 INT i = 0;
404
405 while ( i < ICLS_DESKTOP)
406 {
407 RtlInitUnicodeString(&ClassName, ControlsList[i]);
408 if (IntRegisterClassAtom(&ClassName, &Atom))
409 {
411 TRACE("Reg Control Atom %ls: 0x%x\n", ControlsList[i], Atom);
412 }
413 i++;
414 }
415 return TRUE;
416}
417
418static NTSTATUS
420{
422 Atom);
423}
424
425VOID
427 IN PCALLPROCDATA CallProc)
428{
429 PCLS BaseClass;
430
431 ASSERT(CallProc->spcpdNext == NULL);
432
433 BaseClass = Class->pclsBase;
434 ASSERT(CallProc->spcpdNext == NULL);
435 CallProc->spcpdNext = BaseClass->spcpdFirst;
436 BaseClass->spcpdFirst = CallProc;
437
438 /* Update all clones */
439 Class = Class->pclsClone;
440 while (Class != NULL)
441 {
442 Class->spcpdFirst = BaseClass->spcpdFirst;
443 Class = Class->pclsNext;
444 }
445}
446
447static BOOL
449 IN PUNICODE_STRING ClassName)
450{
452
453 /* Update the base class first */
454 Class = Class->pclsBase;
455 if (ClassName->Length > 0)
456 {
457 if (!IntRegisterClassAtom(ClassName,
458 &Atom))
459 {
460 ERR("RegisterClassAtom failed ! %x\n", EngGetLastError());
461 return FALSE;
462 }
463 }
464 else
465 {
466 if (IS_ATOM(ClassName->Buffer))
467 {
468 Atom = (ATOM)((ULONG_PTR)ClassName->Buffer & 0xffff); // XXX: are we missing refcount here ?
469 }
470 else
471 {
473 return FALSE;
474 }
475 }
476
477 IntDeregisterClassAtom(Class->atomNVClassName);
478
479 Class->atomNVClassName = Atom;
480
481 /* Update the clones */
482 Class = Class->pclsClone;
483 while (Class != NULL)
484 {
485 Class->atomNVClassName = Atom;
486
487 Class = Class->pclsNext;
488 }
489
490 return TRUE;
491}
492
493//
494// Same as User32:IntGetClsWndProc.
495//
498{
499 INT i;
500 WNDPROC gcpd = NULL, Ret = NULL;
501
502 if (Class->CSF_flags & CSF_SERVERSIDEPROC)
503 {
504 for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
505 {
506 if (GETPFNSERVER(i) == Class->lpfnWndProc)
507 {
508 if (Ansi)
509 Ret = GETPFNCLIENTA(i);
510 else
511 Ret = GETPFNCLIENTW(i);
512 }
513 }
514 return Ret;
515 }
516 Ret = Class->lpfnWndProc;
517
518 if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
519 {
520 if (Ansi)
521 {
522 if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc)
523 Ret = GETPFNCLIENTA(Class->fnid);
524 }
525 else
526 {
527 if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc)
528 Ret = GETPFNCLIENTW(Class->fnid);
529 }
530 }
531
532 if ( Ret != Class->lpfnWndProc ||
533 Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) )
534 return Ret;
535
536 gcpd = (WNDPROC)UserGetCPD( Class,
538 (ULONG_PTR)Ret);
539
540 return (gcpd ? gcpd : Ret);
541}
542
543
544static
548 IN BOOL Ansi)
549{
550 INT i;
551 PCALLPROCDATA pcpd;
552 WNDPROC Ret, chWndProc;
553
554 Ret = IntGetClassWndProc(Class, Ansi);
555
556 // If Server Side, downgrade to Client Side.
557 if (Class->CSF_flags & CSF_SERVERSIDEPROC)
558 {
559 if (Ansi) Class->CSF_flags |= CSF_ANSIPROC;
560 Class->CSF_flags &= ~CSF_SERVERSIDEPROC;
561 Class->Unicode = !Ansi;
562 }
563
564 if (!WndProc) WndProc = Class->lpfnWndProc;
565
566 chWndProc = WndProc;
567
568 // Check if CallProc handle and retrieve previous call proc address and set.
570 {
572 if (pcpd) chWndProc = pcpd->pfnClientPrevious;
573 }
574
575 Class->lpfnWndProc = chWndProc;
576
577 // Clear test proc.
578 chWndProc = NULL;
579
580 // Switch from Client Side call to Server Side call if match. Ref: "deftest".
581 for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
582 {
583 if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
584 {
585 chWndProc = GETPFNSERVER(i);
586 break;
587 }
588 if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
589 {
590 chWndProc = GETPFNSERVER(i);
591 break;
592 }
593 }
594 // If match, set/reset to Server Side and clear ansi.
595 if (chWndProc)
596 {
597 Class->lpfnWndProc = chWndProc;
598 Class->Unicode = TRUE;
599 Class->CSF_flags &= ~CSF_ANSIPROC;
600 Class->CSF_flags |= CSF_SERVERSIDEPROC;
601 }
602 else
603 {
604 Class->Unicode = !Ansi;
605
606 if (Ansi)
607 Class->CSF_flags |= CSF_ANSIPROC;
608 else
609 Class->CSF_flags &= ~CSF_ANSIPROC;
610 }
611
612 /* Update the clones */
613 chWndProc = Class->lpfnWndProc;
614
615 Class = Class->pclsClone;
616 while (Class != NULL)
617 {
618 Class->Unicode = !Ansi;
619 Class->lpfnWndProc = chWndProc;
620
621 Class = Class->pclsNext;
622 }
623
624 return Ret;
625}
626
627static PCLS
629 IN OUT PCLS *ClassLink,
631{
632 SIZE_T ClassSize;
633 PCLS Class;
634
635 ASSERT(Desktop != NULL);
636 ASSERT(BaseClass->pclsBase == BaseClass);
637
638 if (BaseClass->rpdeskParent == Desktop)
639 {
640 /* It is most likely that a window is created on the same
641 desktop as the window class. */
642
643 return BaseClass;
644 }
645
646 if (BaseClass->rpdeskParent == NULL)
647 {
648 ASSERT(BaseClass->cWndReferenceCount == 0);
649 ASSERT(BaseClass->pclsClone == NULL);
650
651 /* Classes are also located in the shared heap when the class
652 was created before the thread attached to a desktop. As soon
653 as a window is created for such a class located on the shared
654 heap, the class is cloned into the desktop heap on which the
655 window is created. */
656 Class = NULL;
657 }
658 else
659 {
660 /* The user is asking for a class object on a different desktop,
661 try to find one! */
662 Class = BaseClass->pclsClone;
663 while (Class != NULL)
664 {
665 if (Class->rpdeskParent == Desktop)
666 {
667 ASSERT(Class->pclsBase == BaseClass);
668 ASSERT(Class->pclsClone == NULL);
669 break;
670 }
671
672 Class = Class->pclsNext;
673 }
674 }
675
676 if (Class == NULL)
677 {
678 /* The window is created on a different desktop, we need to
679 clone the class object to the desktop heap of the window! */
680 ClassSize = sizeof(*BaseClass) + (SIZE_T)BaseClass->cbclsExtra;
681
683 ClassSize);
684
685 if (Class != NULL)
686 {
687 /* Simply clone the class */
688 RtlCopyMemory( Class, BaseClass, ClassSize);
689
690 /* Reference our objects */
691 if (Class->spcur)
693 if (Class->spicn)
695 if (Class->spicnSm)
696 UserReferenceObject(Class->spicnSm);
697
698 TRACE("Clone Class 0x%p hM 0x%p\n %S\n",Class, Class->hModule, Class->lpszClientUnicodeMenuName);
699
700 /* Restore module address if default user class Ref: Bug 4778 */
701 if ( Class->hModule != hModClient &&
702 Class->fnid <= FNID_GHOST &&
703 Class->fnid >= FNID_BUTTON )
704 {
705 Class->hModule = hModClient;
706 TRACE("Clone Class 0x%p Reset hM 0x%p\n",Class, Class->hModule);
707 }
708
709 /* Update some pointers and link the class */
710 Class->rpdeskParent = Desktop;
711 Class->cWndReferenceCount = 0;
712
713 if (BaseClass->rpdeskParent == NULL)
714 {
715 /* We don't really need the base class on the shared
716 heap anymore, delete it so the only class left is
717 the clone we just created, which now serves as the
718 new base class */
719 ASSERT(BaseClass->pclsClone == NULL);
720 ASSERT(Class->pclsClone == NULL);
721 Class->pclsBase = Class;
722 Class->pclsNext = BaseClass->pclsNext;
723
724 /* Replace the base class */
726 Class);
727
728 /* Destroy the obsolete copy on the shared heap */
729 BaseClass->pclsBase = NULL;
730 BaseClass->pclsClone = NULL;
731 IntDestroyClass(BaseClass);
732 }
733 else
734 {
735 /* Link in the clone */
736 Class->pclsClone = NULL;
737 Class->pclsBase = BaseClass;
738 Class->pclsNext = BaseClass->pclsClone;
739 (void)InterlockedExchangePointer((PVOID*)&BaseClass->pclsClone,
740 Class);
741 }
742 }
743 else
744 {
746 }
747 }
748 return Class;
749}
750
751PCLS
753 IN OUT PCLS *ClassLink,
755{
756 PCLS Class;
757 ASSERT(BaseClass->pclsBase == BaseClass);
758
759 if (Desktop != NULL)
760 {
761 Class = IntGetClassForDesktop(BaseClass,
762 ClassLink,
763 Desktop);
764 }
765 else
766 {
767 Class = BaseClass;
768 }
769
770 if (Class != NULL)
771 {
772 Class->cWndReferenceCount++;
773 }
774
775 return Class;
776}
777
778static
779VOID
781 IN OUT PCLS *BaseClassLink,
782 IN OUT PCLS *CloneLink)
783{
784 PCLS Clone;
785
786 ASSERT(Class->pclsBase != Class);
787 ASSERT(Class->pclsBase->pclsClone != NULL);
788 ASSERT(Class->rpdeskParent != NULL);
789 ASSERT(Class->cWndReferenceCount != 0);
790 ASSERT(Class->pclsBase->rpdeskParent != NULL);
791 ASSERT(Class->pclsBase->cWndReferenceCount == 0);
792
793 /* Unlink the clone */
794 *CloneLink = Class->pclsNext;
795 Class->pclsClone = Class->pclsBase->pclsClone;
796
797 /* Update the class information to make it a base class */
798 Class->pclsBase = Class;
799 Class->pclsNext = (*BaseClassLink)->pclsNext;
800
801 /* Update all clones */
802 Clone = Class->pclsClone;
803 while (Clone != NULL)
804 {
805 ASSERT(Clone->pclsClone == NULL);
806 Clone->pclsBase = Class;
807
808 Clone = Clone->pclsNext;
809 }
810
811 /* Link in the new base class */
812 (void)InterlockedExchangePointer((PVOID*)BaseClassLink,
813 Class);
814}
815
816
817VOID
821{
822 PCLS *PrevLink, BaseClass, CurrentClass;
823
824 ASSERT(Class->cWndReferenceCount >= 1);
825
826 BaseClass = Class->pclsBase;
827
828 if (--Class->cWndReferenceCount == 0)
829 {
830 if (BaseClass == Class)
831 {
832 ASSERT(Class->pclsBase == Class);
833
834 TRACE("IntDereferenceClass 0x%p\n", Class);
835 /* Check if there are clones of the class on other desktops,
836 link the first clone in if possible. If there are no clones
837 then leave the class on the desktop heap. It will get moved
838 to the shared heap when the thread detaches. */
839 if (BaseClass->pclsClone != NULL)
840 {
841 if (BaseClass->Global)
842 PrevLink = &pi->pclsPublicList;
843 else
844 PrevLink = &pi->pclsPrivateList;
845
846 CurrentClass = *PrevLink;
847 while (CurrentClass != BaseClass)
848 {
849 ASSERT(CurrentClass != NULL);
850
851 PrevLink = &CurrentClass->pclsNext;
852 CurrentClass = CurrentClass->pclsNext;
853 }
854
855 ASSERT(*PrevLink == BaseClass);
856
857 /* Make the first clone become the new base class */
859 PrevLink,
860 &BaseClass->pclsClone);
861
862 /* Destroy the class, there's still another clone of the class
863 that now serves as a base class. Make sure we don't destruct
864 resources shared by all classes (Base = NULL)! */
865 BaseClass->pclsBase = NULL;
866 BaseClass->pclsClone = NULL;
867 IntDestroyClass(BaseClass);
868 }
869 }
870 else
871 {
872 TRACE("IntDereferenceClass1 0x%p\n", Class);
873
874 /* Locate the cloned class and unlink it */
875 PrevLink = &BaseClass->pclsClone;
876 CurrentClass = BaseClass->pclsClone;
877 while (CurrentClass != Class)
878 {
879 ASSERT(CurrentClass != NULL);
880
881 PrevLink = &CurrentClass->pclsNext;
882 CurrentClass = CurrentClass->pclsNext;
883 }
884
885 ASSERT(CurrentClass == Class);
886
888 Class->pclsNext);
889
890 ASSERT(Class->pclsBase == BaseClass);
891 ASSERT(Class->pclsClone == NULL);
892
893 /* The class was just a clone, we don't need it anymore */
895 }
896 }
897}
898
899static BOOL
901 IN OUT PCLS **ClassLinkPtr)
902{
903 PCLS NewClass;
904 SIZE_T ClassSize;
905
906 ASSERT(Class->pclsBase == Class);
907 ASSERT(Class->rpdeskParent != NULL);
908 ASSERT(Class->cWndReferenceCount == 0);
909 ASSERT(Class->pclsClone == NULL);
910
911 ClassSize = sizeof(*Class) + (SIZE_T)Class->cbclsExtra;
912
913 /* Allocate the new base class on the shared heap */
914 NewClass = UserHeapAlloc(ClassSize);
915 if (NewClass != NULL)
916 {
917 RtlCopyMemory(NewClass,
918 Class,
919 ClassSize);
920
921 NewClass->rpdeskParent = NULL;
922 NewClass->pclsBase = NewClass;
923
924 if (NewClass->spcur)
925 UserReferenceObject(NewClass->spcur);
926 if (NewClass->spicn)
927 UserReferenceObject(NewClass->spicn);
928 if (NewClass->spicnSm)
929 UserReferenceObject(NewClass->spicnSm);
930
931 /* Replace the class in the list */
932 (void)InterlockedExchangePointer((PVOID*)*ClassLinkPtr,
933 NewClass);
934 *ClassLinkPtr = &NewClass->pclsNext;
935
936 /* Free the obsolete class on the desktop heap */
937 Class->pclsBase = NULL;
939 return TRUE;
940 }
941
942 return FALSE;
943}
944
945static VOID
947 IN OUT PCLS *ClassList,
948 IN BOOL FreeOnFailure,
949 OUT BOOL *Ret)
950{
951 PCLS Class, NextClass, *Link;
952
953 /* NOTE: We only need to check base classes! When classes are no longer needed
954 on a desktop, the clones will be freed automatically as soon as possible.
955 However, we need to move base classes to the shared heap, as soon as
956 the last desktop heap where a class is allocated on is about to be destroyed.
957 If we didn't move the class to the shared heap, the class would become
958 inaccessible! */
959
960 ASSERT(Desktop != NULL);
961
962 Link = ClassList;
963 Class = *Link;
964 while (Class != NULL)
965 {
966 NextClass = Class->pclsNext;
967
968 ASSERT(Class->pclsBase == Class);
969
970 if (Class->rpdeskParent == Desktop &&
971 Class->cWndReferenceCount == 0)
972 {
973 /* There shouldn't be any clones around anymore! */
974 ASSERT(Class->pclsClone == NULL);
975
976 /* FIXME: If process is terminating, don't move the class but rather destroy it! */
977 /* FIXME: We could move the class to another desktop heap if there's still desktops
978 mapped into the process... */
979
980 /* Move the class to the shared heap */
982 &Link))
983 {
984 ASSERT(*Link == NextClass);
985 }
986 else
987 {
988 ASSERT(NextClass == Class->pclsNext);
989
990 if (FreeOnFailure)
991 {
992 /* Unlink the base class */
994 Class->pclsNext);
995
996 /* We can free the old base class now */
997 Class->pclsBase = NULL;
999 }
1000 else
1001 {
1002 Link = &Class->pclsNext;
1003 *Ret = FALSE;
1004 }
1005 }
1006 }
1007 else
1008 Link = &Class->pclsNext;
1009
1010 Class = NextClass;
1011 }
1012}
1013
1014BOOL
1016 IN BOOL FreeOnFailure)
1017{
1019 BOOL Ret = TRUE;
1020
1022
1023 /* Check all local classes */
1025 &pi->pclsPrivateList,
1026 FreeOnFailure,
1027 &Ret);
1028
1029 /* Check all global classes */
1031 &pi->pclsPublicList,
1032 FreeOnFailure,
1033 &Ret);
1034 if (!Ret)
1035 {
1036 ERR("Failed to move process classes from desktop 0x%p to the shared heap!\n", Desktop);
1038 }
1039
1040 return Ret;
1041}
1042
1043PCLS
1046 IN PUNICODE_STRING ClassName,
1047 IN PUNICODE_STRING ClassVersion,
1048 IN PUNICODE_STRING MenuName,
1049 IN DWORD fnID,
1053{
1054 SIZE_T ClassSize;
1055 PCLS Class = NULL;
1056 RTL_ATOM Atom, verAtom;
1058 PWSTR pszMenuName = NULL;
1060
1061 TRACE("lpwcx=%p ClassName=%wZ MenuName=%wZ dwFlags=%08x Desktop=%p pi=%p\n",
1062 lpwcx, ClassName, MenuName, dwFlags, Desktop, pi);
1063
1064 if (!IntRegisterClassAtom(ClassName,
1065 &Atom))
1066 {
1067 ERR("Failed to register class atom!\n");
1068 return NULL;
1069 }
1070
1071 if (!IntRegisterClassAtom(ClassVersion,
1072 &verAtom))
1073 {
1074 ERR("Failed to register version class atom!\n");
1076 return NULL;
1077 }
1078
1079 ClassSize = sizeof(*Class) + lpwcx->cbClsExtra;
1080 if (MenuName->Length != 0)
1081 {
1082 pszMenuName = UserHeapAlloc(MenuName->Length + sizeof(UNICODE_NULL) +
1083 RtlUnicodeStringToAnsiSize(MenuName));
1084 if (pszMenuName == NULL)
1085 goto NoMem;
1086 }
1087
1088 if (Desktop != NULL)
1089 {
1091 ClassSize);
1092 }
1093 else
1094 {
1095 /* FIXME: The class was created before being connected
1096 to a desktop. It is possible for the desktop window,
1097 but should it be allowed for any other case? */
1098 TRACE("This CLASS has no Desktop to heap from! Atom %u\n",Atom);
1099 Class = UserHeapAlloc(ClassSize);
1100 }
1101
1102 if (Class != NULL)
1103 {
1104 int iCls = 0;
1105
1106 RtlZeroMemory(Class, ClassSize);
1107
1108 Class->rpdeskParent = Desktop;
1109 Class->pclsBase = Class;
1110 Class->atomClassName = verAtom;
1111 Class->atomNVClassName = Atom;
1112 Class->fnid = fnID;
1113 Class->CSF_flags = dwFlags;
1114
1115 if (LookupFnIdToiCls(Class->fnid, &iCls) && gpsi->atomSysClass[iCls] == 0)
1116 {
1117 gpsi->atomSysClass[iCls] = Class->atomClassName;
1118 }
1119
1120 _SEH2_TRY
1121 {
1122 PWSTR pszMenuNameBuffer = pszMenuName;
1123
1124 /* Need to protect with SEH since accessing the WNDCLASSEX structure
1125 and string buffers might raise an exception! We don't want to
1126 leak memory... */
1127 // What?! If the user interface was written correctly this would not be an issue!
1128 Class->lpfnWndProc = lpwcx->lpfnWndProc;
1129 Class->style = lpwcx->style;
1130 Class->cbclsExtra = lpwcx->cbClsExtra;
1131 Class->cbwndExtra = lpwcx->cbWndExtra;
1132 Class->hModule = lpwcx->hInstance;
1133 Class->spicn = lpwcx->hIcon ? UserGetCurIconObject(lpwcx->hIcon) : NULL;
1134 Class->spcur = lpwcx->hCursor ? UserGetCurIconObject(lpwcx->hCursor) : NULL;
1135 Class->spicnSm = lpwcx->hIconSm ? UserGetCurIconObject(lpwcx->hIconSm) : NULL;
1137 Class->hbrBackground = lpwcx->hbrBackground;
1138
1139 /* Make a copy of the string */
1140 if (pszMenuNameBuffer != NULL)
1141 {
1142 Class->MenuNameIsString = TRUE;
1143
1144 Class->lpszClientUnicodeMenuName = pszMenuNameBuffer;
1145 RtlCopyMemory(Class->lpszClientUnicodeMenuName,
1146 MenuName->Buffer,
1147 MenuName->Length);
1148 Class->lpszClientUnicodeMenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1149
1150 pszMenuNameBuffer += (MenuName->Length / sizeof(WCHAR)) + 1;
1151 }
1152 else
1153 Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1154
1155 /* Save an ANSI copy of the string */
1156 if (pszMenuNameBuffer != NULL)
1157 {
1159
1160 Class->lpszClientAnsiMenuName = (PSTR)pszMenuNameBuffer;
1161 AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(MenuName);
1162 AnsiString.Buffer = Class->lpszClientAnsiMenuName;
1164 MenuName,
1165 FALSE);
1166 if (!NT_SUCCESS(Status))
1167 {
1168 ERR("Failed to convert unicode menu name to ansi!\n");
1169
1170 /* Life would've been much prettier if ntoskrnl exported RtlRaiseStatus()... */
1172 }
1173 }
1174 else
1175 Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1176
1177 /* Save kernel use menu name and ansi class name */
1178 Class->lpszMenuName = Class->lpszClientUnicodeMenuName; // FIXME!
1179 //Class->lpszAnsiClassName = FIXME
1180
1181 /* Server Side overrides class calling type (A/W)!
1182 User32 whine test_builtinproc: "deftest"
1183 built-in winproc - window A/W type automatically detected */
1184 if (!(Class->CSF_flags & CSF_SERVERSIDEPROC))
1185 {
1186 int i;
1187 WndProc = NULL;
1188 /* Due to the wine class "deftest" and most likely no FNID to reference
1189 from, sort through the Server Side list and compare proc addresses
1190 for match. This method will be used in related code.
1191 */
1192 for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
1193 { // Open ANSI or Unicode, just match, set and break.
1194 if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
1195 {
1197 break;
1198 }
1199 if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
1200 {
1202 break;
1203 }
1204 }
1205 if (WndProc)
1206 { // If a hit, we are Server Side so set the right flags and proc.
1207 Class->CSF_flags |= CSF_SERVERSIDEPROC;
1208 Class->CSF_flags &= ~CSF_ANSIPROC;
1209 Class->lpfnWndProc = WndProc;
1210 }
1211 }
1212
1213 if (!(Class->CSF_flags & CSF_ANSIPROC))
1214 Class->Unicode = TRUE;
1215
1216 if (Class->style & CS_GLOBALCLASS)
1217 Class->Global = TRUE;
1218 }
1220 {
1222 }
1223 _SEH2_END;
1224
1225 if (!NT_SUCCESS(Status))
1226 {
1227 ERR("Failed creating the class: 0x%x\n", Status);
1228
1230
1231 if (pszMenuName != NULL)
1232 UserHeapFree(pszMenuName);
1233
1235 Class);
1236 Class = NULL;
1237
1238 IntDeregisterClassAtom(verAtom);
1240 }
1241 }
1242 else
1243 {
1244NoMem:
1245 ERR("Failed to allocate class on Desktop 0x%p\n", Desktop);
1246
1247 if (pszMenuName != NULL)
1248 UserHeapFree(pszMenuName);
1249
1251 IntDeregisterClassAtom(verAtom);
1252
1254 }
1255
1256 TRACE("Created class 0x%p with name %wZ and proc 0x%p for atom 0x%x and version atom 0x%x and hInstance 0x%p, global %u\n",
1257 Class, ClassName, Class ? Class->lpfnWndProc : NULL, Atom, verAtom,
1258 Class ? Class->hModule : NULL , Class ? Class->Global : 0);
1259
1260 return Class;
1261}
1262
1263static PCLS
1266 IN PCLS *ClassList,
1268{
1269 PCLS Class, *PrevLink = ClassList;
1270
1271 Class = *PrevLink;
1272 while (Class != NULL)
1273 {
1274 if (Class->atomClassName == Atom &&
1275 (hInstance == NULL || Class->hModule == hInstance) &&
1276 !(Class->CSF_flags & CSF_WOWDEFERDESTROY))
1277 {
1278 ASSERT(Class->pclsBase == Class);
1279
1280 if (Link != NULL)
1281 *Link = PrevLink;
1282 break;
1283 }
1284
1285 PrevLink = &Class->pclsNext;
1286 Class = Class->pclsNext;
1287 }
1288
1289 return Class;
1290}
1291
1293BOOL
1294NTAPI
1295IntGetAtomFromStringOrAtom(
1296 _In_ PUNICODE_STRING ClassName,
1298{
1299 BOOL Ret = FALSE;
1300
1301 if (ClassName->Length != 0)
1302 {
1303 WCHAR szBuf[65];
1304 PWSTR AtomName = szBuf;
1306
1307 *Atom = 0;
1308
1309 /* NOTE: Caller has to protect the call with SEH! */
1310 if (ClassName->Length + sizeof(UNICODE_NULL) > sizeof(szBuf))
1311 {
1313 ClassName->Length + sizeof(UNICODE_NULL),
1314 TAG_USTR);
1315 if (AtomName == NULL)
1316 {
1318 return FALSE;
1319 }
1320 }
1321
1322 _SEH2_TRY
1323 {
1324 RtlCopyMemory(AtomName,
1325 ClassName->Buffer,
1326 ClassName->Length);
1327 }
1329 {
1330 if (AtomName != szBuf)
1331 ExFreePoolWithTag(AtomName, TAG_USTR);
1333 _SEH2_YIELD(return FALSE);
1334 }
1335 _SEH2_END;
1336 AtomName[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1337
1338 /* Lookup the atom */
1340
1341 if (AtomName != szBuf)
1342 ExFreePoolWithTag(AtomName, TAG_USTR);
1343
1344 if (NT_SUCCESS(Status))
1345 {
1346 Ret = TRUE;
1347 }
1348 else
1349 {
1351 {
1353 }
1354 }
1355 }
1356 else
1357 {
1358 if (ClassName->Buffer)
1359 {
1360 *Atom = (RTL_ATOM)((ULONG_PTR)ClassName->Buffer);
1361 Ret = TRUE;
1362 }
1363 else
1364 {
1365 *Atom = 0;
1367 Ret = FALSE;
1368 }
1369 }
1370
1371 return Ret;
1372}
1373
1376 _In_ PUNICODE_STRING ClassName,
1379 OUT PCLS *BaseClass OPTIONAL,
1381{
1382 RTL_ATOM Atom = (RTL_ATOM)0;
1383
1384 ASSERT(BaseClass != NULL);
1385
1386 if (IntGetAtomFromStringOrAtom(ClassName, &Atom) &&
1387 Atom != (RTL_ATOM)0)
1388 {
1389 PCLS Class;
1390
1391 /* Attempt to locate the class object */
1392
1393 ASSERT(pi != NULL);
1394
1395 /* Step 1: Try to find an exact match of locally registered classes */
1397 hInstance,
1398 &pi->pclsPrivateList,
1399 Link);
1400 if (Class != NULL)
1401 { TRACE("Step 1: 0x%p\n",Class );
1402 goto FoundClass;
1403 }
1404
1405 /* Step 2: Try to find any globally registered class. The hInstance
1406 is not relevant for global classes */
1408 NULL,
1409 &pi->pclsPublicList,
1410 Link);
1411 if (Class != NULL)
1412 { TRACE("Step 2: 0x%p 0x%p\n",Class, Class->hModule);
1413 goto FoundClass;
1414 }
1415
1416 /* Step 3: Try to find any local class registered by user32 */
1418 hModClient,
1419 &pi->pclsPrivateList,
1420 Link);
1421 if (Class != NULL)
1422 { TRACE("Step 3: 0x%p\n",Class );
1423 goto FoundClass;
1424 }
1425
1426 /* Step 4: Try to find any global class registered by user32 */
1428 hModClient,
1429 &pi->pclsPublicList,
1430 Link);
1431 if (Class == NULL)
1432 {
1433 return (RTL_ATOM)0;
1434 }else{TRACE("Step 4: 0x%p\n",Class );}
1435
1436FoundClass:
1437 *BaseClass = Class;
1438 }
1439 else
1440 {
1441 Atom = 0;
1442 }
1443
1444 return Atom;
1445}
1446
1447PCLS
1449{
1450 PCLS *ClassLink, Class = NULL;
1451 RTL_ATOM ClassAtom;
1452 PTHREADINFO pti;
1453
1454 if (bDesktopThread)
1455 pti = gptiDesktopThread;
1456 else
1458
1459 if ( !(pti->ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
1460 {
1462 }
1463
1464 /* Check the class. */
1465
1466 TRACE("Finding Class %wZ for hInstance 0x%p\n", ClassName, hInstance);
1467
1468 ClassAtom = IntGetClassAtom(ClassName,
1469 hInstance,
1470 pti->ppi,
1471 &Class,
1472 &ClassLink);
1473
1474 if (ClassAtom == (RTL_ATOM)0)
1475 {
1476 if (IS_ATOM(ClassName->Buffer))
1477 {
1478 ERR("Class 0x%p not found\n", ClassName->Buffer);
1479 }
1480 else
1481 {
1482 ERR("Class \"%wZ\" not found\n", ClassName);
1483 }
1484
1485 return NULL;
1486 }
1487
1488 TRACE("Referencing Class 0x%p with atom 0x%x\n", Class, ClassAtom);
1490 ClassLink,
1491 pti->rpdesk);
1492 if (Class == NULL)
1493 {
1494 ERR("Failed to reference window class!\n");
1495 return NULL;
1496 }
1497
1498 return Class;
1499}
1500
1503 IN PUNICODE_STRING ClassName,
1504 IN PUNICODE_STRING ClassVersion,
1505 IN PUNICODE_STRING MenuName,
1506 IN DWORD fnID,
1508{
1509 PTHREADINFO pti;
1511 PCLS Class;
1512 RTL_ATOM ClassAtom;
1513 RTL_ATOM Ret = (RTL_ATOM)0;
1514
1515 /* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */
1516
1517 pti = GetW32ThreadInfo();
1518
1519 pi = pti->ppi;
1520
1521 // Need only to test for two conditions not four....... Fix more whine tests....
1522 if ( IntGetAtomFromStringOrAtom( ClassVersion, &ClassAtom) &&
1523 ClassAtom != (RTL_ATOM)0 &&
1524 !(dwFlags & CSF_SERVERSIDEPROC) ) // Bypass Server Sides
1525 {
1526 Class = IntFindClass( ClassAtom,
1527 lpwcx->hInstance,
1528 &pi->pclsPrivateList,
1529 NULL);
1530
1531 if (Class != NULL && !Class->Global)
1532 {
1533 // Local class already exists
1534 TRACE("Local Class 0x%x does already exist!\n", ClassAtom);
1536 return (RTL_ATOM)0;
1537 }
1538
1539 if (lpwcx->style & CS_GLOBALCLASS)
1540 {
1541 Class = IntFindClass( ClassAtom,
1542 NULL,
1543 &pi->pclsPublicList,
1544 NULL);
1545
1546 if (Class != NULL && Class->Global)
1547 {
1548 TRACE("Global Class 0x%x does already exist!\n", ClassAtom);
1550 return (RTL_ATOM)0;
1551 }
1552 }
1553 }
1554
1555 Class = IntCreateClass(lpwcx,
1556 ClassName,
1557 ClassVersion,
1558 MenuName,
1559 fnID,
1560 dwFlags,
1561 pti->rpdesk,
1562 pi);
1563
1564 if (Class != NULL)
1565 {
1566 PCLS *List;
1567
1568 /* Register the class */
1569 if (Class->Global)
1570 List = &pi->pclsPublicList;
1571 else
1572 List = &pi->pclsPrivateList;
1573
1574 Class->pclsNext = *List;
1576 Class);
1577
1578 Ret = Class->atomNVClassName;
1579 }
1580 else
1581 {
1582 ERR("UserRegisterClass: Yes, that is right, you have no Class!\n");
1583 }
1584
1585 return Ret;
1586}
1587
1588BOOL
1591 OUT PCLSMENUNAME pClassMenuName)
1592{
1593 PCLS *Link;
1595 RTL_ATOM ClassAtom;
1596 PCLS Class;
1597
1599
1600 TRACE("UserUnregisterClass(%wZ, 0x%p)\n", ClassName, hInstance);
1601
1602 /* NOTE: Accessing the buffer in ClassName may raise an exception! */
1603 ClassAtom = IntGetClassAtom(ClassName,
1604 hInstance,
1605 pi,
1606 &Class,
1607 &Link);
1608 if (ClassAtom == (RTL_ATOM)0)
1609 {
1611 TRACE("UserUnregisterClass: No Class found.\n");
1612 return FALSE;
1613 }
1614
1615 ASSERT(Class != NULL);
1616
1617 if (Class->cWndReferenceCount != 0 ||
1618 Class->pclsClone != NULL)
1619 {
1620 TRACE("UserUnregisterClass: Class has a Window. Ct %u : Clone 0x%p\n", Class->cWndReferenceCount, Class->pclsClone);
1622 return FALSE;
1623 }
1624
1625 /* Must be a base class! */
1626 ASSERT(Class->pclsBase == Class);
1627
1628 /* Unlink the class */
1629 *Link = Class->pclsNext;
1630
1631 if (NT_SUCCESS(IntDeregisterClassAtom(Class->atomClassName)))
1632 {
1633 TRACE("Class 0x%p\n", Class);
1634 TRACE("UserUnregisterClass: Good Exit!\n");
1635 Class->atomClassName = 0; // Don't let it linger...
1636 /* Finally free the resources */
1638 return TRUE;
1639 }
1640 ERR("UserUnregisterClass: Can not deregister Class Atom.\n");
1641 return FALSE;
1642}
1643
1644INT
1646 IN OUT PUNICODE_STRING ClassName,
1648 IN BOOL Ansi)
1649{
1651 WCHAR szStaticTemp[32];
1652 PWSTR szTemp = NULL;
1653 ULONG BufLen = sizeof(szStaticTemp);
1654 INT Ret = 0;
1655
1656 /* Note: Accessing the buffer in ClassName may raise an exception! */
1657
1658 _SEH2_TRY
1659 {
1660 if (Ansi)
1661 {
1662 PANSI_STRING AnsiClassName = (PANSI_STRING)ClassName;
1663 UNICODE_STRING UnicodeClassName;
1664
1665 /* Limit the size of the static buffer on the stack to the
1666 size of the buffer provided by the caller */
1667 if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
1668 {
1669 BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
1670 }
1671
1672 /* Find out how big the buffer needs to be */
1674 Class->atomClassName,
1675 NULL,
1676 NULL,
1677 szStaticTemp,
1678 &BufLen);
1680 {
1681 if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
1682 {
1683 /* The buffer required exceeds the ansi buffer provided,
1684 pretend like we're using the ansi buffer and limit the
1685 size to the buffer size provided */
1686 BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
1687 }
1688
1689 /* Allocate a temporary buffer that can hold the unicode class name */
1691 BufLen,
1693 if (szTemp == NULL)
1694 {
1697 }
1698
1699 /* Query the class name */
1701 Atom ? Atom : Class->atomNVClassName,
1702 NULL,
1703 NULL,
1704 szTemp,
1705 &BufLen);
1706 }
1707 else
1708 szTemp = szStaticTemp;
1709
1710 if (NT_SUCCESS(Status))
1711 {
1712 /* Convert the atom name to ansi */
1713
1714 RtlInitUnicodeString(&UnicodeClassName,
1715 szTemp);
1716
1717 Status = RtlUnicodeStringToAnsiString(AnsiClassName,
1718 &UnicodeClassName,
1719 FALSE);
1720 if (!NT_SUCCESS(Status))
1721 {
1724 }
1725 }
1726
1727 Ret = BufLen / sizeof(WCHAR);
1728 }
1729 else /* !ANSI */
1730 {
1731 BufLen = ClassName->MaximumLength;
1732
1733 /* Query the atom name */
1735 Atom ? Atom : Class->atomNVClassName,
1736 NULL,
1737 NULL,
1738 ClassName->Buffer,
1739 &BufLen);
1740
1741 if (!NT_SUCCESS(Status))
1742 {
1745 }
1746
1747 Ret = BufLen / sizeof(WCHAR);
1748 }
1749 }
1751 {
1753 }
1754 _SEH2_END;
1755
1756 if (Ansi && szTemp != NULL && szTemp != szStaticTemp)
1757 {
1759 }
1760
1761 return Ret;
1762}
1763
1764static BOOL
1766 IN PUNICODE_STRING MenuName)
1767{
1768 BOOL Ret = FALSE;
1769
1770 /* Change the base class first */
1771 Class = Class->pclsBase;
1772
1773 if (MenuName->Length != 0)
1774 {
1776 PWSTR strBufW;
1777
1778 AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(MenuName);
1779
1780 strBufW = UserHeapAlloc(MenuName->Length + sizeof(UNICODE_NULL) +
1781 AnsiString.MaximumLength);
1782 if (strBufW != NULL)
1783 {
1784 _SEH2_TRY
1785 {
1787
1788 /* Copy the unicode string */
1789 RtlCopyMemory(strBufW,
1790 MenuName->Buffer,
1791 MenuName->Length);
1792 strBufW[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1793
1794 /* Create an ANSI copy of the string */
1795 AnsiString.Buffer = (PSTR)(strBufW + (MenuName->Length / sizeof(WCHAR)) + 1);
1797 MenuName,
1798 FALSE);
1799 if (!NT_SUCCESS(Status))
1800 {
1803 }
1804
1805 Ret = TRUE;
1806 }
1808 {
1810 }
1811 _SEH2_END;
1812
1813 if (Ret)
1814 {
1815 /* Update the base class */
1817 Class->lpszClientUnicodeMenuName = strBufW;
1818 Class->lpszClientAnsiMenuName = AnsiString.Buffer;
1819 Class->MenuNameIsString = TRUE;
1820
1821 /* Update the clones */
1822 Class = Class->pclsClone;
1823 while (Class != NULL)
1824 {
1825 Class->lpszClientUnicodeMenuName = strBufW;
1826 Class->lpszClientAnsiMenuName = AnsiString.Buffer;
1827 Class->MenuNameIsString = TRUE;
1828
1829 Class = Class->pclsNext;
1830 }
1831 }
1832 else
1833 {
1834 ERR("Failed to copy class menu name!\n");
1835 UserHeapFree(strBufW);
1836 }
1837 }
1838 else
1840 }
1841 else
1842 {
1843 ASSERT(IS_INTRESOURCE(MenuName->Buffer));
1844
1845 /* Update the base class */
1847 Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1848 Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1849 Class->MenuNameIsString = FALSE;
1850
1851 /* Update the clones */
1852 Class = Class->pclsClone;
1853 while (Class != NULL)
1854 {
1855 Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1856 Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1857 Class->MenuNameIsString = FALSE;
1858
1859 Class = Class->pclsNext;
1860 }
1861
1862 Ret = TRUE;
1863 }
1864
1865 return Ret;
1866}
1867
1870 IN INT Index,
1871 IN ULONG_PTR NewLong,
1872 IN BOOL Ansi)
1873{
1874 ULONG_PTR Ret = 0;
1875
1876 /* NOTE: For GCLP_MENUNAME and GCW_ATOM this function may raise an exception! */
1877
1878 /* Change the information in the base class first, then update the clones */
1879 Class = Class->pclsBase;
1880
1881 if (Index >= 0)
1882 {
1884
1885 TRACE("SetClassLong(%d, %x)\n", Index, NewLong);
1886
1887 if (((ULONG)Index + sizeof(ULONG_PTR)) < (ULONG)Index ||
1888 ((ULONG)Index + sizeof(ULONG_PTR)) > (ULONG)Class->cbclsExtra)
1889 {
1891 return 0;
1892 }
1893
1894 Data = (PULONG_PTR)((ULONG_PTR)(Class + 1) + Index);
1895
1896 /* FIXME: Data might be a unaligned pointer! Might be a problem on
1897 certain architectures, maybe using RtlCopyMemory is a
1898 better choice for those architectures! */
1899 Ret = *Data;
1900 *Data = NewLong;
1901
1902 /* Update the clones */
1903 Class = Class->pclsClone;
1904 while (Class != NULL)
1905 {
1906 *(PULONG_PTR)((ULONG_PTR)(Class + 1) + Index) = NewLong;
1907 Class = Class->pclsNext;
1908 }
1909
1910 return Ret;
1911 }
1912
1913 switch (Index)
1914 {
1915 case GCL_CBWNDEXTRA:
1916 Ret = (ULONG_PTR)Class->cbwndExtra;
1917 Class->cbwndExtra = (INT)NewLong;
1918
1919 /* Update the clones */
1920 Class = Class->pclsClone;
1921 while (Class != NULL)
1922 {
1923 Class->cbwndExtra = (INT)NewLong;
1924 Class = Class->pclsNext;
1925 }
1926
1927 break;
1928
1929 case GCL_CBCLSEXTRA:
1931 break;
1932
1933 case GCLP_HBRBACKGROUND:
1934 Ret = (ULONG_PTR)Class->hbrBackground;
1935 Class->hbrBackground = (HBRUSH)NewLong;
1936
1937 /* Update the clones */
1938 Class = Class->pclsClone;
1939 while (Class != NULL)
1940 {
1941 Class->hbrBackground = (HBRUSH)NewLong;
1942 Class = Class->pclsNext;
1943 }
1944 break;
1945
1946 case GCLP_HCURSOR:
1947 {
1948 PCURICON_OBJECT NewCursor = NULL;
1949
1950 if (NewLong)
1951 {
1952 NewCursor = UserGetCurIconObject((HCURSOR)NewLong);
1953 if (!NewCursor)
1954 {
1956 return 0;
1957 }
1958 }
1959
1960 if (Class->spcur)
1961 {
1962 Ret = (ULONG_PTR)UserHMGetHandle(Class->spcur);
1964 }
1965 else
1966 {
1967 Ret = 0;
1968 }
1969
1970 if (Ret == NewLong)
1971 {
1972 /* It's a nop */
1973 return Ret;
1974 }
1975
1976 Class->spcur = NewCursor;
1977
1978 /* Update the clones */
1979 Class = Class->pclsClone;
1980 while (Class != NULL)
1981 {
1982 if (Class->spcur)
1984 if (NewCursor)
1985 UserReferenceObject(NewCursor);
1986 Class->spcur = NewCursor;
1987 Class = Class->pclsNext;
1988 }
1989
1990 break;
1991 }
1992
1993 // MSDN:
1994 // hIconSm, A handle to a small icon that is associated with the window class.
1995 // If this member is NULL, the system searches the icon resource specified by
1996 // the hIcon member for an icon of the appropriate size to use as the small icon.
1997 //
1998 case GCLP_HICON:
1999 {
2000 PCURICON_OBJECT NewIcon = NULL;
2001 PCURICON_OBJECT NewSmallIcon = NULL;
2002
2003 if (NewLong)
2004 {
2005 NewIcon = UserGetCurIconObject((HCURSOR)NewLong);
2006 if (!NewIcon)
2007 {
2009 return 0;
2010 }
2011 }
2012
2013 if (Class->spicn)
2014 {
2015 Ret = (ULONG_PTR)UserHMGetHandle(Class->spicn);
2017 }
2018 else
2019 {
2020 Ret = 0;
2021 }
2022
2023 if (Ret == NewLong)
2024 {
2025 /* It's a nop */
2026 return Ret;
2027 }
2028
2029 if (Ret && (Class->CSF_flags & CSF_CACHEDSMICON))
2030 {
2031 /* We will change the small icon */
2032 UserDereferenceObject(Class->spicnSm);
2034 Class->spicnSm = NULL;
2035 Class->CSF_flags &= ~CSF_CACHEDSMICON;
2036 }
2037
2038 if (NewLong && !Class->spicnSm)
2039 {
2040 /* Create the new small icon from the new large(?) one */
2041 HICON SmallIconHandle = NULL;
2044 {
2045 SmallIconHandle = co_IntCopyImage(
2046 (HICON)NewLong,
2047 IMAGE_ICON,
2051 }
2052 if (!SmallIconHandle)
2053 {
2054 /* Retry without copying from resource */
2055 SmallIconHandle = co_IntCopyImage(
2056 (HICON)NewLong,
2057 IMAGE_ICON,
2060 0);
2061 }
2062 if (SmallIconHandle)
2063 {
2064 /* So use it */
2065 NewSmallIcon = Class->spicnSm = UserGetCurIconObject(SmallIconHandle);
2066 Class->CSF_flags |= CSF_CACHEDSMICON;
2067 }
2068 }
2069
2070 Class->spicn = NewIcon;
2071
2072 /* Update the clones */
2073 Class = Class->pclsClone;
2074 while (Class != NULL)
2075 {
2076 if (Class->spicn)
2078 if (NewIcon)
2079 UserReferenceObject(NewIcon);
2080 Class->spicn = NewIcon;
2081 if (NewSmallIcon)
2082 {
2083 if (Class->spicnSm)
2084 UserDereferenceObject(Class->spicnSm);
2085 UserReferenceObject(NewSmallIcon);
2086 Class->spicnSm = NewSmallIcon;
2087 Class->CSF_flags |= CSF_CACHEDSMICON;
2088 }
2089 Class = Class->pclsNext;
2090 }
2091 break;
2092 }
2093
2094 case GCLP_HICONSM:
2095 {
2096 PCURICON_OBJECT NewSmallIcon = NULL;
2097 BOOLEAN NewIconFromCache = FALSE;
2098
2099 if (NewLong)
2100 {
2101 NewSmallIcon = UserGetCurIconObject((HCURSOR)NewLong);
2102 if (!NewSmallIcon)
2103 {
2105 return 0;
2106 }
2107 }
2108 else
2109 {
2110 /* Create the new small icon from the large one */
2111 HICON SmallIconHandle = NULL;
2112 if((Class->spicn->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
2114 {
2115 SmallIconHandle = co_IntCopyImage(
2116 UserHMGetHandle(Class->spicn),
2117 IMAGE_ICON,
2121 }
2122 if (!SmallIconHandle)
2123 {
2124 /* Retry without copying from resource */
2125 SmallIconHandle = co_IntCopyImage(
2126 UserHMGetHandle(Class->spicn),
2127 IMAGE_ICON,
2130 0);
2131 }
2132 if (SmallIconHandle)
2133 {
2134 /* So use it */
2135 NewSmallIcon = UserGetCurIconObject(SmallIconHandle);
2136 NewIconFromCache = TRUE;
2137 }
2138 else
2139 {
2140 ERR("Failed getting a small icon for the class.\n");
2141 }
2142 }
2143
2144 if (Class->spicnSm)
2145 {
2146 if (Class->CSF_flags & CSF_CACHEDSMICON)
2147 {
2148 /* We must destroy the icon if we own it */
2150 Ret = 0;
2151 }
2152 else
2153 {
2154 Ret = (ULONG_PTR)UserHMGetHandle(Class->spicnSm);
2155 }
2156 UserDereferenceObject(Class->spicnSm);
2157 }
2158 else
2159 {
2160 Ret = 0;
2161 }
2162
2163 if (NewIconFromCache)
2164 Class->CSF_flags |= CSF_CACHEDSMICON;
2165 else
2166 Class->CSF_flags &= ~CSF_CACHEDSMICON;
2167 Class->spicnSm = NewSmallIcon;
2168
2169 /* Update the clones */
2170 Class = Class->pclsClone;
2171 while (Class != NULL)
2172 {
2173 if (Class->spicnSm)
2174 UserDereferenceObject(Class->spicnSm);
2175 if (NewSmallIcon)
2176 UserReferenceObject(NewSmallIcon);
2177 if (NewIconFromCache)
2178 Class->CSF_flags |= CSF_CACHEDSMICON;
2179 else
2180 Class->CSF_flags &= ~CSF_CACHEDSMICON;
2181 Class->spicnSm = NewSmallIcon;
2182 Class = Class->pclsNext;
2183 }
2184 }
2185 break;
2186
2187 case GCLP_HMODULE:
2188 Ret = (ULONG_PTR)Class->hModule;
2189 Class->hModule = (HINSTANCE)NewLong;
2190
2191 /* Update the clones */
2192 Class = Class->pclsClone;
2193 while (Class != NULL)
2194 {
2195 Class->hModule = (HINSTANCE)NewLong;
2196 Class = Class->pclsNext;
2197 }
2198 break;
2199
2200 case GCLP_MENUNAME:
2201 {
2203
2205 Value))
2206 {
2207 ERR("Setting the class menu name failed!\n");
2208 }
2209
2210 /* FIXME: Really return NULL? Wine does so... */
2211 break;
2212 }
2213
2214 case GCL_STYLE:
2215 Ret = (ULONG_PTR)Class->style;
2216 Class->style = (UINT)NewLong;
2217
2218 /* FIXME: What if the CS_GLOBALCLASS style is changed? should we
2219 move the class to the appropriate list? For now, we save
2220 the original value in Class->Global, so we can always
2221 locate the appropriate list */
2222
2223 /* Update the clones */
2224 Class = Class->pclsClone;
2225 while (Class != NULL)
2226 {
2227 Class->style = (UINT)NewLong;
2228 Class = Class->pclsNext;
2229 }
2230 break;
2231
2232 case GCLP_WNDPROC:
2234 (WNDPROC)NewLong,
2235 Ansi);
2236 break;
2237
2238 case GCW_ATOM:
2239 {
2241
2242 Ret = (ULONG_PTR)Class->atomNVClassName;
2244 Value))
2245 {
2246 Ret = 0;
2247 }
2248 break;
2249 }
2250
2251 default:
2253 break;
2254 }
2255
2256 return Ret;
2257}
2258
2259static BOOL
2261 OUT PWNDCLASSEXW lpwcx,
2262 IN BOOL Ansi,
2264{
2265 if (!Class) return FALSE;
2266
2267 lpwcx->style = Class->style;
2268
2269 // If fnId is set, clear the global bit. See wine class test check_style.
2270 if (Class->fnid)
2271 lpwcx->style &= ~CS_GLOBALCLASS;
2272
2273 lpwcx->lpfnWndProc = IntGetClassWndProc(Class, Ansi);
2274
2275 lpwcx->cbClsExtra = Class->cbclsExtra;
2276 lpwcx->cbWndExtra = Class->cbwndExtra;
2277 lpwcx->hIcon = Class->spicn ? UserHMGetHandle(Class->spicn) : NULL;
2278 lpwcx->hCursor = Class->spcur ? UserHMGetHandle(Class->spcur) : NULL;
2279 lpwcx->hIconSm = Class->spicnSm ? UserHMGetHandle(Class->spicnSm) : NULL;
2280 lpwcx->hbrBackground = Class->hbrBackground;
2281
2282 /* Copy non-string to user first. */
2283 if (Ansi)
2284 ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->lpszClientAnsiMenuName;
2285 else
2286 lpwcx->lpszMenuName = Class->lpszClientUnicodeMenuName;
2287/*
2288 * FIXME: CLSMENUNAME has the answers! Copy the already made buffers from there!
2289 * Cls: lpszMenuName and lpszAnsiClassName should be used by kernel space.
2290 * lpszClientXxxMenuName should already be mapped to user space.
2291 */
2292 /* Copy string ptr to user. */
2293 if ( Class->lpszClientUnicodeMenuName != NULL &&
2294 Class->MenuNameIsString)
2295 {
2296 lpwcx->lpszMenuName = UserHeapAddressToUser(Ansi ?
2297 (PVOID)Class->lpszClientAnsiMenuName :
2298 (PVOID)Class->lpszClientUnicodeMenuName);
2299 }
2300
2301 if (hInstance == hModClient)
2302 lpwcx->hInstance = NULL;
2303 else
2304 lpwcx->hInstance = hInstance;
2305
2306 /* FIXME: Return the string? Okay! This is performed in User32! */
2307 //lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName);
2308
2309 return TRUE;
2310}
2311
2312//
2313// Register System Classes....
2314//
2315BOOL
2318{
2319 UINT i;
2320 UNICODE_STRING ClassName, MenuName;
2322 WNDCLASSEXW wc;
2323 PCLS Class;
2324 BOOL Ret = TRUE;
2325 HBRUSH hBrush;
2326 DWORD Flags = 0;
2327
2328 if (ppi->W32PF_flags & W32PF_CLASSESREGISTERED)
2329 return TRUE;
2330
2331 if ( hModClient == NULL)
2332 return FALSE;
2333
2334 RtlZeroMemory(&ClassName, sizeof(ClassName));
2335 RtlZeroMemory(&MenuName, sizeof(MenuName));
2336
2337 for (i = 0; i != ARRAYSIZE(DefaultServerClasses); i++)
2338 {
2339 if (!IS_ATOM(DefaultServerClasses[i].ClassName))
2340 {
2341 RtlInitUnicodeString(&ClassName, DefaultServerClasses[i].ClassName);
2342 }
2343 else
2344 {
2345 ClassName.Buffer = DefaultServerClasses[i].ClassName;
2346 ClassName.Length = 0;
2347 ClassName.MaximumLength = 0;
2348 }
2349
2350 wc.cbSize = sizeof(wc);
2352
2354
2355 if (DefaultServerClasses[i].ProcW)
2356 {
2358 wc.hInstance = hModuleWin;
2359 }
2360 else
2361 {
2363 wc.hInstance = hModClient;
2364 }
2365
2366 wc.cbClsExtra = 0;
2368 wc.hIcon = NULL;
2369
2371 wc.hCursor = NULL;
2372 if (DefaultServerClasses[i].hCursor == (HICON)OCR_NORMAL)
2373 {
2374 if (SYSTEMCUR(ARROW) == NULL)
2375 {
2376 ERR("SYSTEMCUR(ARROW) == NULL, should not happen!!\n");
2377 }
2378 else
2379 {
2380 wc.hCursor = UserHMGetHandle(SYSTEMCUR(ARROW));
2381 }
2382 }
2383
2384 hBrush = DefaultServerClasses[i].hBrush;
2385 if (hBrush <= (HBRUSH)COLOR_MENUBAR)
2386 {
2387 hBrush = IntGetSysColorBrush(HandleToUlong(hBrush));
2388 }
2389 wc.hbrBackground = hBrush;
2390 wc.lpszMenuName = NULL;
2391 wc.lpszClassName = ClassName.Buffer;
2392 wc.hIconSm = NULL;
2393
2394 Class = IntCreateClass( &wc,
2395 &ClassName,
2396 &ClassName,
2397 &MenuName,
2398 DefaultServerClasses[i].fiId,
2399 Flags,
2400 NULL,
2401 ppi);
2402 if (Class != NULL)
2403 {
2404 Class->pclsNext = ppi->pclsPublicList;
2406 Class);
2407
2409 }
2410 else
2411 {
2412 ERR("!!! Registering system class failed!\n");
2413 Ret = FALSE;
2414 }
2415 }
2416 if (Ret) ppi->W32PF_flags |= W32PF_CLASSESREGISTERED;
2417 return Ret;
2418}
2419
2420/* SYSCALLS *****************************************************************/
2421
2425 WNDCLASSEXW* lpwcx,
2426 PUNICODE_STRING ClassName,
2427 PUNICODE_STRING ClsVersion,
2428 PCLSMENUNAME pClassMenuName,
2429 DWORD fnID,
2430 DWORD Flags,
2431 LPDWORD pWow)
2432/*
2433 * FUNCTION:
2434 * Registers a new class with the window manager
2435 * ARGUMENTS:
2436 * lpwcx = Win32 extended window class structure
2437 * bUnicodeClass = Whether to send ANSI or unicode strings
2438 * to window procedures
2439 * RETURNS:
2440 * Atom identifying the new class
2441 */
2442{
2443 WNDCLASSEXW CapturedClassInfo = {0};
2444 UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0}, CapturedVersion = {0};
2445 RTL_ATOM Ret = (RTL_ATOM)0;
2447 BOOL Exception = FALSE;
2448
2449 if (Flags & ~(CSF_ANSIPROC))
2450 {
2451 ERR("NtUserRegisterClassExWOW Bad Flags!\n");
2453 return Ret;
2454 }
2455
2457
2458 TRACE("NtUserRegisterClassExWOW ClsN %wZ\n",ClassName);
2459
2460 if ( !(ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
2461 {
2463 }
2464
2465 _SEH2_TRY
2466 {
2467 /* Probe the parameters and basic parameter checks */
2468 if (ProbeForReadUint(&lpwcx->cbSize) != sizeof(WNDCLASSEXW))
2469 {
2470 ERR("NtUserRegisterClassExWOW Wrong cbSize!\n");
2471 goto InvalidParameter;
2472 }
2473
2474 ProbeForRead(lpwcx,
2475 sizeof(WNDCLASSEXW),
2476 sizeof(ULONG));
2477 RtlCopyMemory(&CapturedClassInfo,
2478 lpwcx,
2479 sizeof(WNDCLASSEXW));
2480
2481 CapturedName = ProbeForReadUnicodeString(ClassName);
2482 CapturedVersion = ProbeForReadUnicodeString(ClsVersion);
2483
2484 ProbeForRead(pClassMenuName,
2485 sizeof(CLSMENUNAME),
2486 1);
2487
2488 CapturedMenuName = ProbeForReadUnicodeString(pClassMenuName->pusMenuName);
2489
2490 if ( (CapturedName.Length & 1) ||
2491 (CapturedMenuName.Length & 1) ||
2492 (CapturedClassInfo.cbClsExtra < 0) ||
2493 ((CapturedClassInfo.cbClsExtra + CapturedName.Length +
2494 CapturedMenuName.Length + sizeof(CLS))
2495 < (ULONG)CapturedClassInfo.cbClsExtra) ||
2496 (CapturedClassInfo.cbWndExtra < 0) ||
2497 (CapturedClassInfo.hInstance == NULL) )
2498 {
2499 ERR("NtUserRegisterClassExWOW Invalid Parameter Error!\n");
2500 goto InvalidParameter;
2501 }
2502
2503 if (CapturedName.Length != 0)
2504 {
2505 ProbeForRead(CapturedName.Buffer,
2506 CapturedName.Length,
2507 sizeof(WCHAR));
2508 }
2509 else
2510 {
2511 if (!IS_ATOM(CapturedName.Buffer))
2512 {
2513 ERR("NtUserRegisterClassExWOW ClassName Error!\n");
2514 goto InvalidParameter;
2515 }
2516 }
2517
2518 if (CapturedVersion.Length != 0)
2519 {
2520 ProbeForRead(CapturedVersion.Buffer,
2521 CapturedVersion.Length,
2522 sizeof(WCHAR));
2523 }
2524 else
2525 {
2526 if (!IS_ATOM(CapturedVersion.Buffer))
2527 {
2528 ERR("NtUserRegisterClassExWOW ClassName Error!\n");
2529 goto InvalidParameter;
2530 }
2531 }
2532
2533 if (CapturedMenuName.Length != 0)
2534 {
2535 ProbeForRead(CapturedMenuName.Buffer,
2536 CapturedMenuName.Length,
2537 sizeof(WCHAR));
2538 }
2539 else if (CapturedMenuName.Buffer != NULL &&
2540 !IS_INTRESOURCE(CapturedMenuName.Buffer))
2541 {
2542 ERR("NtUserRegisterClassExWOW MenuName Error!\n");
2546 }
2547
2548 if (IsCallProcHandle(lpwcx->lpfnWndProc))
2549 { // Never seen this yet, but I'm sure it's a little haxxy trick!
2550 // If this pops up we know what todo!
2551 ERR("NtUserRegisterClassExWOW WndProc is CallProc!!\n");
2552 }
2553
2554 TRACE("NtUserRegisterClassExWOW MnuN %wZ\n",&CapturedMenuName);
2555 }
2557 {
2558 ERR("NtUserRegisterClassExWOW Exception Error!\n");
2560 Exception = TRUE;
2561 }
2562 _SEH2_END;
2563
2564 if (!Exception)
2565 {
2566 /* Register the class */
2567 Ret = UserRegisterClass(&CapturedClassInfo,
2568 &CapturedName,
2569 &CapturedVersion,
2570 &CapturedMenuName,
2571 fnID,
2572 Flags);
2573 }
2574
2575 if (!Ret)
2576 {
2577 TRACE("NtUserRegisterClassExWOW Null Return!\n");
2578 }
2579
2580 UserLeave();
2581
2582 return Ret;
2583}
2584
2587 INT Offset,
2588 ULONG_PTR dwNewLong,
2589 BOOL Ansi)
2590{
2592 PWND Window;
2593 ULONG_PTR Ret = 0;
2594
2596
2598
2600 if (Window != NULL)
2601 {
2602 if (Window->head.pti->ppi != pi)
2603 {
2605 goto Cleanup;
2606 }
2607
2608 _SEH2_TRY
2609 {
2611
2612 /* Probe the parameters */
2613 if (Offset == GCW_ATOM || Offset == GCLP_MENUNAME)
2614 {
2615 /* FIXME: Resource ID can be passed directly without UNICODE_STRING ? */
2616 if (IS_ATOM(dwNewLong))
2617 {
2618 Value.MaximumLength = 0;
2619 Value.Length = 0;
2620 Value.Buffer = (PWSTR)dwNewLong;
2621 }
2622 else
2623 {
2625 }
2626
2627 if (Value.Length & 1)
2628 {
2629 goto InvalidParameter;
2630 }
2631
2632 if (Value.Length != 0)
2633 {
2634 ProbeForRead(Value.Buffer,
2635 Value.Length,
2636 sizeof(WCHAR));
2637 }
2638 else
2639 {
2640 if (Offset == GCW_ATOM && !IS_ATOM(Value.Buffer))
2641 {
2642 goto InvalidParameter;
2643 }
2644 else if (Offset == GCLP_MENUNAME && !IS_INTRESOURCE(Value.Buffer))
2645 {
2649 }
2650 }
2651
2652 dwNewLong = (ULONG_PTR)&Value;
2653 }
2654
2655 Ret = UserSetClassLongPtr(Window->pcls,
2656 Offset,
2657 dwNewLong,
2658 Ansi);
2659 switch(Offset)
2660 {
2661 case GCLP_HICONSM:
2662 case GCLP_HICON:
2663 {
2664 if (Ret && Ret != dwNewLong)
2666 }
2667 }
2668 }
2670 {
2672 }
2673 _SEH2_END;
2674 }
2675
2676Cleanup:
2677 UserLeave();
2678
2679 return Ret;
2680}
2681
2682WORD
2685 HWND hWnd,
2686 INT nIndex,
2687 WORD wNewWord)
2688{
2689/*
2690 * NOTE: Obsoleted in 32-bit windows
2691 */
2692 return(0);
2693}
2694
2695BOOL
2698 IN PUNICODE_STRING ClassNameOrAtom,
2700 OUT PCLSMENUNAME pClassMenuName)
2701{
2702 UNICODE_STRING SafeClassName;
2704 BOOL Ret;
2705
2706 Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom);
2707 if (!NT_SUCCESS(Status))
2708 {
2709 ERR("Error capturing the class name\n");
2711 return FALSE;
2712 }
2713
2715
2716 /* Unregister the class */
2717 Ret = UserUnregisterClass(&SafeClassName, hInstance, NULL); // Null for now~
2718
2719 UserLeave();
2720
2721 if (SafeClassName.Buffer && !IS_ATOM(SafeClassName.Buffer))
2722 ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2723
2724 return Ret;
2725}
2726
2727
2728/* NOTE: For system classes hInstance is not NULL here, but User32Instance */
2729BOOL
2733 PUNICODE_STRING ClassName,
2734 LPWNDCLASSEXW lpWndClassEx,
2735 LPWSTR *ppszMenuName,
2736 BOOL bAnsi)
2737{
2738 UNICODE_STRING SafeClassName;
2739 WNDCLASSEXW Safewcexw;
2740 PCLS Class;
2741 RTL_ATOM ClassAtom = 0;
2742 PPROCESSINFO ppi;
2743 BOOL Ret = TRUE;
2745
2746 _SEH2_TRY
2747 {
2748 ProbeForWrite( lpWndClassEx, sizeof(WNDCLASSEXW), sizeof(ULONG));
2749 RtlCopyMemory( &Safewcexw, lpWndClassEx, sizeof(WNDCLASSEXW));
2750 if (ppszMenuName)
2751 {
2752 ProbeForWrite(ppszMenuName, sizeof(*ppszMenuName), sizeof(PVOID));
2753 }
2754 }
2756 {
2758 _SEH2_YIELD(return FALSE);
2759 }
2760 _SEH2_END;
2761
2762 Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
2763 if (!NT_SUCCESS(Status))
2764 {
2765 ERR("Error capturing the class name\n");
2767 return FALSE;
2768 }
2769
2770 // If null instance use client.
2772
2773 TRACE("GetClassInfo(%wZ, %p)\n", &SafeClassName, hInstance);
2774
2775 /* NOTE: Need exclusive lock because getting the wndproc might require the
2776 creation of a call procedure handle */
2778
2779 ppi = GetW32ProcessInfo();
2780 if (!(ppi->W32PF_flags & W32PF_CLASSESREGISTERED))
2781 {
2783 }
2784
2785 ClassAtom = IntGetClassAtom(&SafeClassName,
2786 hInstance,
2787 ppi,
2788 &Class,
2789 NULL);
2790 if (ClassAtom != (RTL_ATOM)0)
2791 {
2792 ClassAtom = Class->atomNVClassName;
2793 Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance);
2794 }
2795 else
2796 {
2798 Ret = FALSE;
2799 }
2800
2801 UserLeave();
2802
2803 if (Ret)
2804 {
2805 _SEH2_TRY
2806 {
2807 /* Emulate Function. */
2808 if (ppszMenuName) *ppszMenuName = (LPWSTR)Safewcexw.lpszMenuName;
2809
2810 RtlCopyMemory(lpWndClassEx, &Safewcexw, sizeof(WNDCLASSEXW));
2811
2812 // From Wine:
2813 /* We must return the atom of the class here instead of just TRUE. */
2814 /* Undocumented behavior! Return the class atom as a BOOL! */
2815 Ret = (BOOL)ClassAtom;
2816 }
2818 {
2820 Ret = FALSE;
2821 }
2822 _SEH2_END;
2823 }
2824
2825 if (!IS_ATOM(SafeClassName.Buffer))
2826 ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2827
2828 return Ret;
2829}
2830
2831
2834 IN BOOL Real,
2835 OUT PUNICODE_STRING ClassName)
2836{
2837 PWND Window;
2838 UNICODE_STRING CapturedClassName;
2839 INT iCls, Ret = 0;
2840 RTL_ATOM Atom = 0;
2841
2843
2845 if (Window != NULL)
2846 {
2847 if (Real && Window->fnid && !(Window->fnid & FNID_DESTROY))
2848 {
2849 if (LookupFnIdToiCls(Window->fnid, &iCls))
2850 {
2851 Atom = gpsi->atomSysClass[iCls];
2852 }
2853 }
2854
2855 _SEH2_TRY
2856 {
2857 ProbeForWriteUnicodeString(ClassName);
2858 CapturedClassName = *ClassName;
2859 if (CapturedClassName.Length != 0)
2860 {
2861 ProbeForRead(CapturedClassName.Buffer,
2862 CapturedClassName.Length,
2863 sizeof(WCHAR));
2864 }
2865
2866 /* Get the class name */
2867 Ret = UserGetClassName(Window->pcls,
2868 &CapturedClassName,
2869 Atom,
2870 FALSE);
2871
2872 if (Ret != 0)
2873 {
2874 /* Update the Length field */
2875 ClassName->Length = CapturedClassName.Length;
2876 }
2877 }
2879 {
2881 }
2882 _SEH2_END;
2883 }
2884
2885 UserLeave();
2886
2887 return Ret;
2888}
2889
2890/* Return Pointer to Class structure. */
2891PCLS
2895 PUNICODE_STRING ClassName)
2896{
2897 UNICODE_STRING SafeClassName;
2899 PCLS Class = NULL;
2900 RTL_ATOM ClassAtom = 0;
2902
2903 Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
2904 if (!NT_SUCCESS(Status))
2905 {
2906 ERR("Error capturing the class name\n");
2908 return FALSE;
2909 }
2910
2912
2914
2915 ClassAtom = IntGetClassAtom(&SafeClassName,
2916 hInstance,
2917 pi,
2918 &Class,
2919 NULL);
2920 if (!ClassAtom)
2921 {
2923 }
2924
2925
2926 if (SafeClassName.Buffer && !IS_ATOM(SafeClassName.Buffer))
2927 ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2928
2929 UserLeave();
2930//
2931// Don't forget to use DesktopPtrToUser( ? ) with return pointer in user space.
2932//
2933 return Class;
2934}
2935
2936/* EOF */
unsigned char BOOLEAN
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
#define HandleToUlong(h)
Definition: basetsd.h:79
#define ERR(fmt,...)
Definition: debug.h:110
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
ULONG_PTR FASTCALL UserGetCPD(PVOID pvClsWnd, GETCPD Flags, ULONG_PTR ProcIn)
Definition: callproc.c:107
BOOLEAN DestroyCallProc(_Inout_ PVOID Object)
Definition: callproc.c:22
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
HINSTANCE hInstance
Definition: charmap.c:19
static __inline BOOL IsCallProcHandle(IN WNDPROC lpWndProc)
Definition: class.h:13
_Out_ RTL_ATOM * Atom
Definition: class.h:54
#define IS_ATOM(x)
Definition: class.h:3
#define SYSTEMCUR(func)
Definition: cursoricon.h:129
void FASTCALL DceFreeClassDCE(PDCE)
Definition: windc.c:762
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
float Real
Definition: definitions.h:36
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
WORD ATOM
Definition: dimm.idl:113
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define APIENTRY
Definition: api.h:79
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
PSERVERINFO gpsi
Definition: imm.c:18
static const WCHAR Cleanup[]
Definition: register.c:80
@ AnsiString
Definition: dnslib.h:19
#define ULONG_PTR
Definition: config.h:101
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
ANSI_STRING * PANSI_STRING
Definition: env_spec_w32.h:380
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define BufLen
Definition: fatfs.h:167
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define _SEH2_LEAVE
Definition: filesup.c:20
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
@ InvalidParameter
Definition: gdiplustypes.h:28
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ICLS_IME
Definition: ntuser.h:927
#define ICLS_DIALOG
Definition: ntuser.h:930
#define ICLS_LISTBOX
Definition: ntuser.h:915
#define ICLASS_TO_MASK(iCls)
Definition: ntuser.h:902
#define ICLS_EDIT
Definition: ntuser.h:913
#define ICLS_GHOST
Definition: ntuser.h:928
struct _PROCESSINFO * GetW32ProcessInfo(VOID)
Definition: misc.c:799
#define CURSORF_LRSHARED
Definition: ntuser.h:1201
#define FNID_SWITCH
Definition: ntuser.h:865
#define ICLS_COMBOBOX
Definition: ntuser.h:917
#define ICLS_STATIC
Definition: ntuser.h:914
#define FNID_SCROLLBAR
Definition: ntuser.h:859
#define GETPFNCLIENTW(fnid)
Definition: ntuser.h:906
#define FNID_ICONTITLE
Definition: ntuser.h:860
#define GETPFNCLIENTA(fnid)
Definition: ntuser.h:904
#define FNID_DESTROY
Definition: ntuser.h:898
#define CSF_ANSIPROC
Definition: ntuser.h:557
#define FNID_DESKTOP
Definition: ntuser.h:862
#define FNID_LISTBOX
Definition: ntuser.h:871
#define FNID_FIRST
Definition: ntuser.h:858
#define ICLS_ICONTITLE
Definition: ntuser.h:933
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
#define FNID_BUTTON
Definition: ntuser.h:866
@ UserGetCPDClass
Definition: ntuser.h:542
@ UserGetCPDU2A
Definition: ntuser.h:541
@ UserGetCPDA2U
Definition: ntuser.h:540
#define FNID_COMBOBOX
Definition: ntuser.h:867
#define ICLS_SCROLLBAR
Definition: ntuser.h:916
#define CSF_CACHEDSMICON
Definition: ntuser.h:562
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:805
#define FNID_DIALOG
Definition: ntuser.h:869
#define ICLS_MENU
Definition: ntuser.h:931
#define ICLS_COMBOLBOX
Definition: ntuser.h:919
#define ICLS_SWITCH
Definition: ntuser.h:932
#define GETPFNSERVER(fnid)
Definition: ntuser.h:909
#define FNID_STATIC
Definition: ntuser.h:873
#define FNID_EDIT
Definition: ntuser.h:870
#define ICLS_BUTTON
Definition: ntuser.h:912
@ TYPE_CALLPROC
Definition: ntuser.h:47
#define ICLS_DESKTOP
Definition: ntuser.h:929
#define FNID_IME
Definition: ntuser.h:874
#define CURSORF_FROMRESOURCE
Definition: ntuser.h:1199
#define CSF_SERVERSIDEPROC
Definition: ntuser.h:556
#define FNID_GHOST
Definition: ntuser.h:875
#define FNID_MENU
Definition: ntuser.h:861
#define ICLS_TOOLTIPS
Definition: ntuser.h:934
#define CSF_WOWDEFERDESTROY
Definition: ntuser.h:558
struct _SBWND SBWND
#define ICLS_MDICLIENT
Definition: ntuser.h:918
#define FNID_MESSAGEWND
Definition: ntuser.h:864
#define FNID_COMBOLBOX
Definition: ntuser.h:868
#define FNID_TOOLTIPS
Definition: ntuser.h:888
#define FNID_MDICLIENT
Definition: ntuser.h:872
HGDIOBJ FASTCALL IntGetSysColorBrush(INT Object)
Definition: stockobj.c:317
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static HICON
Definition: imagelist.c:84
unsigned short RTL_ATOM
Definition: atom.c:42
static refpint_t pi[]
Definition: server.c:96
#define _Success_(expr)
Definition: ms_sal.h:259
#define _Notnull_
Definition: ms_sal.h:658
#define _Post_
Definition: ms_sal.h:620
#define _At_(target, annos)
Definition: ms_sal.h:244
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define _Out_
Definition: ms_sal.h:345
#define _When_(expr, annos)
Definition: ms_sal.h:254
#define _In_
Definition: ms_sal.h:308
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI NTSTATUS NTAPI RtlAddAtomToAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ PWSTR AtomName, _Out_ PRTL_ATOM Atom)
NTSYSAPI NTSTATUS NTAPI RtlLookupAtomInAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ PWSTR AtomName, _Out_ PRTL_ATOM Atom)
NTSYSAPI NTSTATUS NTAPI RtlDeleteAtomFromAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ RTL_ATOM Atom)
NTSYSAPI NTSTATUS NTAPI RtlQueryAtomInAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ RTL_ATOM Atom, _Out_opt_ PULONG RefCount, _Out_opt_ PULONG PinCount, _Out_opt_z_bytecap_(*NameLength) PWSTR AtomName, _Inout_opt_ PULONG NameLength)
#define BOOL
Definition: nt_native.h:43
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define FASTCALL
Definition: nt_native.h:50
#define UNICODE_NULL
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
BOOL UserPaintCaption(PWND pWnd, INT Flags)
Definition: defwnd.c:398
HINSTANCE hModClient
Definition: ntuser.c:25
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:251
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:235
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:242
#define L(x)
Definition: ntvdm.h:50
struct _PROCESSINFO * PPROCESSINFO
Definition: ntwin32.h:5
#define TAG_STRING
Definition: oslist.h:22
#define CONST
Definition: pedump.c:81
unsigned short USHORT
Definition: pedump.c:61
#define INT
Definition: polytest.cpp:20
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define ProbeForWriteUnicodeString(Ptr)
Definition: probe.h:48
#define ProbeForReadUint(Ptr)
Definition: probe.h:67
#define ProbeForReadUnicodeString(Ptr)
Definition: probe.h:77
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define TRACE(s)
Definition: solgame.cpp:4
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
Definition: solitaire.cpp:614
#define __in_data_source(src_sym)
Definition: specstrings.h:348
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
Definition: window.c:28
USHORT MaximumLength
Definition: env_spec_w32.h:377
WNDPROC pfnClientPrevious
Definition: ntuser.h:552
struct _CALLPROCDATA * spcpdNext
Definition: ntuser.h:551
PUNICODE_STRING pusMenuName
Definition: ntuser.h:500
Definition: ntuser.h:566
struct _CURICON_OBJECT * spcur
Definition: ntuser.h:586
struct _DESKTOP * rpdeskParent
Definition: ntuser.h:571
struct _CLS * pclsBase
Definition: ntuser.h:577
UINT Global
Definition: ntuser.h:593
struct _CURICON_OBJECT * spicn
Definition: ntuser.h:585
PCALLPROCDATA spcpdFirst
Definition: ntuser.h:576
struct _CURICON_OBJECT * spicnSm
Definition: ntuser.h:590
struct _CLS * pclsClone
Definition: ntuser.h:578
struct _CLS * pclsNext
Definition: ntuser.h:567
ULONG CURSORF_flags
Definition: cursoricon.h:16
DWORD dwRegisteredClasses
Definition: win32.h:280
struct _CLS * pclsPublicList
Definition: win32.h:260
WNDPROC ProcW
Definition: ntuser.h:488
PPROCESSINFO ppi
Definition: win32.h:88
struct _DESKTOP * rpdesk
Definition: win32.h:92
USHORT MaximumLength
Definition: env_spec_w32.h:370
LPCWSTR lpszClassName
Definition: winuser.h:3226
LPCWSTR lpszMenuName
Definition: winuser.h:3225
HBRUSH hbrBackground
Definition: winuser.h:3224
WNDPROC lpfnWndProc
Definition: winuser.h:3218
UINT cbSize
Definition: winuser.h:3216
int cbWndExtra
Definition: winuser.h:3220
HCURSOR hCursor
Definition: winuser.h:3223
HICON hIconSm
Definition: winuser.h:3227
HINSTANCE hInstance
Definition: winuser.h:3221
UINT style
Definition: winuser.h:3217
int cbClsExtra
Definition: winuser.h:3219
HICON hIcon
Definition: winuser.h:3222
Definition: ntuser.h:694
ATOM atomSysClass[ICLS_NOTUSED+1]
Definition: ntuser.h:1060
#define TAG_USTR
Definition: tag.h:145
#define LONG_PTR
Definition: treelist.c:79
HANDLE HINSTANCE
Definition: typedefs.h:77
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG_PTR
Definition: typedefs.h:65
char * PSTR
Definition: typedefs.h:51
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define WC_SWITCH
Definition: undocuser.h:12
#define WC_ICONTITLE
Definition: undocuser.h:13
#define WC_DESKTOP
Definition: undocuser.h:10
#define WC_MENU
Definition: undocuser.h:9
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:122
static __inline PVOID UserHeapAlloc(SIZE_T Bytes)
Definition: usrheap.h:34
static __inline PVOID UserHeapAddressToUser(PVOID lpMem)
Definition: usrheap.h:99
static __inline BOOL UserHeapFree(PVOID lpMem)
Definition: usrheap.h:44
static int Link(const char **args)
Definition: vfdcmd.c:2414
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define W32PF_CLASSESREGISTERED
Definition: win32.h:17
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:31
HANDLE FASTCALL co_IntCopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags)
Definition: callback.c:985
int FnId
Definition: class.c:106
static VOID IntFreeClassMenuName(IN OUT PCLS Class)
Definition: class.c:219
INT UserGetClassName(IN PCLS Class, IN OUT PUNICODE_STRING ClassName, IN RTL_ATOM Atom, IN BOOL Ansi)
Definition: class.c:1645
ULONG_PTR UserSetClassLongPtr(IN PCLS Class, IN INT Index, IN ULONG_PTR NewLong, IN BOOL Ansi)
Definition: class.c:1869
static VOID IntMakeCloneBaseClass(IN OUT PCLS Class, IN OUT PCLS *BaseClassLink, IN OUT PCLS *CloneLink)
Definition: class.c:780
static BOOL IntMoveClassToSharedHeap(IN OUT PCLS Class, IN OUT PCLS **ClassLinkPtr)
Definition: class.c:900
static PCLS IntFindClass(IN RTL_ATOM Atom, IN HINSTANCE hInstance, IN PCLS *ClassList, OUT PCLS **Link OPTIONAL)
Definition: class.c:1264
RTL_ATOM UserRegisterClass(IN CONST WNDCLASSEXW *lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING ClassVersion, IN PUNICODE_STRING MenuName, IN DWORD fnID, IN DWORD dwFlags)
Definition: class.c:1502
REGISTER_SYSCLASS DefaultServerClasses[]
Definition: class.c:35
INT APIENTRY NtUserGetClassName(IN HWND hWnd, IN BOOL Real, OUT PUNICODE_STRING ClassName)
Definition: class.c:2833
VOID UserAddCallProcToClass(IN OUT PCLS Class, IN PCALLPROCDATA CallProc)
Definition: class.c:426
WORD APIENTRY NtUserSetClassWord(HWND hWnd, INT nIndex, WORD wNewWord)
Definition: class.c:2684
PCLS IntReferenceClass(IN OUT PCLS BaseClass, IN OUT PCLS *ClassLink, IN PDESKTOP Desktop)
Definition: class.c:752
static PCLS IntGetClassForDesktop(IN OUT PCLS BaseClass, IN OUT PCLS *ClassLink, IN PDESKTOP Desktop)
Definition: class.c:628
BOOL IntCheckProcessDesktopClasses(IN PDESKTOP Desktop, IN BOOL FreeOnFailure)
Definition: class.c:1015
BOOL FASTCALL RegisterControlAtoms(VOID)
Definition: class.c:399
void FASTCALL DestroyProcessClasses(PPROCESSINFO Process)
Definition: class.c:303
VOID IntDereferenceClass(IN OUT PCLS Class, IN PDESKTOPINFO Desktop, IN PPROCESSINFO pi)
Definition: class.c:818
static BOOL UserGetClassInfo(IN PCLS Class, OUT PWNDCLASSEXW lpwcx, IN BOOL Ansi, HINSTANCE hInstance)
Definition: class.c:2260
static PWSTR ControlsList[]
Definition: class.c:12
static BOOL IntRegisterClassAtom(IN PUNICODE_STRING ClassName, OUT RTL_ATOM *pAtom)
Definition: class.c:337
PCLS APIENTRY NtUserGetWOWClass(HINSTANCE hInstance, PUNICODE_STRING ClassName)
Definition: class.c:2893
RTL_ATOM IntGetClassAtom(_In_ PUNICODE_STRING ClassName, IN HINSTANCE hInstance OPTIONAL, IN PPROCESSINFO pi OPTIONAL, OUT PCLS *BaseClass OPTIONAL, OUT PCLS **Link OPTIONAL)
Definition: class.c:1375
static BOOL IntSetClassMenuName(IN PCLS Class, IN PUNICODE_STRING MenuName)
Definition: class.c:1765
_Must_inspect_result_ NTSTATUS NTAPI ProbeAndCaptureUnicodeStringOrAtom(_Out_ _When_(return >=0, _At_(pustrOut->Buffer, _Post_ _Notnull_)) PUNICODE_STRING pustrOut, __in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe)
Definition: class.c:150
WNDPROC FASTCALL IntGetClassWndProc(PCLS Class, BOOL Ansi)
Definition: class.c:497
BOOL APIENTRY NtUserUnregisterClass(IN PUNICODE_STRING ClassNameOrAtom, IN HINSTANCE hInstance, OUT PCLSMENUNAME pClassMenuName)
Definition: class.c:2697
PCLS IntGetAndReferenceClass(PUNICODE_STRING ClassName, HINSTANCE hInstance, BOOL bDesktopThread)
Definition: class.c:1448
static BOOL IntSetClassAtom(IN OUT PCLS Class, IN PUNICODE_STRING ClassName)
Definition: class.c:448
static struct @5122 FnidToiCls[]
static VOID IntCheckDesktopClasses(IN PDESKTOP Desktop, IN OUT PCLS *ClassList, IN BOOL FreeOnFailure, OUT BOOL *Ret)
Definition: class.c:946
PCLS FASTCALL IntCreateClass(IN CONST WNDCLASSEXW *lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING ClassVersion, IN PUNICODE_STRING MenuName, IN DWORD fnID, IN DWORD dwFlags, IN PDESKTOP Desktop, IN PPROCESSINFO pi)
Definition: class.c:1045
RTL_ATOM APIENTRY NtUserRegisterClassExWOW(WNDCLASSEXW *lpwcx, PUNICODE_STRING ClassName, PUNICODE_STRING ClsVersion, PCLSMENUNAME pClassMenuName, DWORD fnID, DWORD Flags, LPDWORD pWow)
Definition: class.c:2424
BOOL FASTCALL UserRegisterSystemClasses(VOID)
Definition: class.c:2317
BOOL UserUnregisterClass(IN PUNICODE_STRING ClassName, IN HINSTANCE hInstance, OUT PCLSMENUNAME pClassMenuName)
Definition: class.c:1589
static NTSTATUS IntDeregisterClassAtom(IN RTL_ATOM Atom)
Definition: class.c:419
ULONG_PTR APIENTRY NtUserSetClassLong(HWND hWnd, INT Offset, ULONG_PTR dwNewLong, BOOL Ansi)
Definition: class.c:2586
static VOID IntDestroyClass(IN OUT PCLS Class)
Definition: class.c:231
BOOL APIENTRY NtUserGetClassInfo(HINSTANCE hInstance, PUNICODE_STRING ClassName, LPWNDCLASSEXW lpWndClassEx, LPWSTR *ppszMenuName, BOOL bAnsi)
Definition: class.c:2731
BOOL FASTCALL LookupFnIdToiCls(int FnId, int *iCls)
Definition: class.c:131
int ClsId
Definition: class.c:107
static WNDPROC FASTCALL IntSetClassWndProc(IN OUT PCLS Class, IN WNDPROC WndProc, IN BOOL Ansi)
Definition: class.c:546
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
Definition: cursoricon.c:200
BOOLEAN IntDestroyCurIconObject(_In_ PVOID Object)
Definition: cursoricon.c:313
PTHREADINFO gptiDesktopThread
Definition: desktop.c:37
static __inline PVOID DesktopHeapAlloc(IN PDESKTOP Desktop, IN SIZE_T Bytes)
Definition: desktop.h:204
static __inline BOOL DesktopHeapFree(IN PDESKTOP Desktop, IN PVOID lpMem)
Definition: desktop.h:215
HANDLE hModuleWin
Definition: main.c:16
LONG NTAPI UserGetSystemMetrics(ULONG Index)
Definition: metric.c:213
PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:495
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:644
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13
BOOL FASTCALL UserObjectInDestroy(HANDLE h)
Definition: object.c:703
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:731
PRTL_ATOM_TABLE gAtomTable
Definition: session.c:13
#define USERTAG_CLASS
Definition: tags.h:204
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
ENGAPI ULONG APIENTRY EngGetLastError(VOID)
Definition: error.c:9
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:22
HICON HCURSOR
Definition: windef.h:299
#define ERROR_CLASS_HAS_WINDOWS
Definition: winerror.h:893
#define ERROR_CLASS_ALREADY_EXISTS
Definition: winerror.h:891
#define ERROR_INVALID_INDEX
Definition: winerror.h:894
#define ERROR_INVALID_CURSOR_HANDLE
Definition: winerror.h:883
#define ERROR_CLASS_DOES_NOT_EXIST
Definition: winerror.h:892
#define ERROR_INVALID_FLAGS
Definition: winerror.h:583
#define ERROR_INVALID_ICON_HANDLE
Definition: winerror.h:895
#define CS_DROPSHADOW
Definition: winuser.h:660
#define CS_VREDRAW
Definition: winuser.h:658
#define GCLP_MENUNAME
Definition: winuser.h:677
#define GCLP_HICONSM
Definition: winuser.h:675
#define COLOR_MENU
Definition: winuser.h:917
#define GCLP_HMODULE
Definition: winuser.h:676
#define IMAGE_ICON
Definition: winuser.h:212
#define GCLP_HICON
Definition: winuser.h:674
#define LR_COPYFROMRESOURCE
Definition: winuser.h:1099
#define CS_HREDRAW
Definition: winuser.h:653
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
#define GCLP_WNDPROC
Definition: winuser.h:678
#define SM_CYSMICON
Definition: winuser.h:1013
#define CS_DBLCLKS
Definition: winuser.h:651
#define GCLP_HCURSOR
Definition: winuser.h:673
#define GCL_CBWNDEXTRA
Definition: winuser.h:663
#define SM_CXSMICON
Definition: winuser.h:1012
#define CS_GLOBALCLASS
Definition: winuser.h:652
#define CS_SAVEBITS
Definition: winuser.h:657
struct _WNDCLASSEXA * PWNDCLASSEXA
#define DC_ICON
Definition: winuser.h:429
LRESULT(CALLBACK * WNDPROC)(HWND, UINT, WPARAM, LPARAM)
Definition: winuser.h:2906
#define CS_PARENTDC
Definition: winuser.h:656
#define GCLP_HBRBACKGROUND
Definition: winuser.h:672
#define COLOR_BACKGROUND
Definition: winuser.h:913
#define GCW_ATOM
Definition: winuser.h:661
#define GCL_STYLE
Definition: winuser.h:670
#define GCL_CBCLSEXTRA
Definition: winuser.h:662
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define RtlUnicodeStringToAnsiSize(String)
Definition: rtlfuncs.h:1005
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184