ReactOS 0.4.15-dev-7924-g5949c20
cursoricon.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: Cursor and icon functions
5 * FILE: win32ss/user/ntuser/cursoricon.c
6 * PROGRAMER: ReactOS Team
7 */
8/*
9 * We handle two types of cursors/icons:
10 * - Private
11 * Loaded without LR_SHARED flag
12 * Private to a process
13 * Can be deleted by calling NtDestroyCursorIcon()
14 * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc set to NULL
15 * - Shared
16 * Loaded with LR_SHARED flag
17 * Possibly shared by multiple processes
18 * Immune to NtDestroyCursorIcon()
19 * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc are valid
20 */
21
22#include <win32k.h>
24
26
27PCURICON_OBJECT gcurFirst = NULL; // After all is done, this should be WINLOGO!
28
29//
30// System Cursors
31//
33 {OCR_NORMAL, NULL},
34 {OCR_IBEAM, NULL},
35 {OCR_WAIT, NULL},
36 {OCR_CROSS, NULL},
37 {OCR_UP, NULL},
38 {OCR_ICON, NULL},
39 {OCR_SIZE, NULL},
40 {OCR_SIZENWSE, NULL},
41 {OCR_SIZENESW, NULL},
42 {OCR_SIZEWE, NULL},
43 {OCR_SIZENS, NULL},
44 {OCR_SIZEALL, NULL},
45 {OCR_NO, NULL},
46 {OCR_HAND, NULL},
47 {OCR_APPSTARTING,NULL},
48 {OCR_HELP, NULL},
49 };
50
51//
52// System Icons
53//
55 {OIC_SAMPLE, NULL},
56 {OIC_HAND, NULL},
57 {OIC_QUES, NULL},
58 {OIC_BANG, NULL},
59 {OIC_NOTE, NULL},
60 {OIC_WINLOGO,NULL},
61 };
62
63BOOL
65{
74
75 return TRUE;
76}
77
78static
79VOID
82{
83 PPROCESSINFO ppi = pcur->head.ppi;
84 PCURICON_OBJECT *ppcurHead;
85 NT_ASSERT((pcur->CURSORF_flags & (CURSORF_GLOBAL|CURSORF_LRSHARED)) != 0);
86 NT_ASSERT((pcur->CURSORF_flags & CURSORF_LINKED) == 0);
87
88 /* Get the right list head */
89 ppcurHead = (pcur->CURSORF_flags & CURSORF_GLOBAL) ?
90 &gcurFirst : &ppi->pCursorCache;
91
93 pcur->pcurNext = *ppcurHead;
94 *ppcurHead = pcur;
96}
97
98// FIXME: should think about using a LIST_ENTRY!
99static
100VOID
103{
104 PPROCESSINFO ppi = pcur->head.ppi;
105 PCURICON_OBJECT *ppcurHead;
106 PCURICON_OBJECT *ppcur;
107 NT_ASSERT((pcur->CURSORF_flags & (CURSORF_GLOBAL|CURSORF_LRSHARED)) != 0);
108 NT_ASSERT((pcur->CURSORF_flags & CURSORF_LINKED) != 0);
109
110 /* Get the right list head */
111 ppcurHead = (pcur->CURSORF_flags & CURSORF_GLOBAL) ?
112 &gcurFirst : &ppi->pCursorCache;
113
114 /* Loop all cursors in the cache */
115 for (ppcur = ppcurHead;
116 (*ppcur) != NULL;
117 ppcur = &(*ppcur)->pcurNext)
118 {
119 /* Check if this is the one we are looking for */
120 if ((*ppcur) == pcur)
121 {
122 /* Remove it from the list */
123 (*ppcur) = pcur->pcurNext;
124
125 /* Dereference it */
127 pcur->CURSORF_flags &= ~CURSORF_LINKED;
128 return;
129 }
130 }
131
132 /* We did not find it, this must not happen */
134}
135
136VOID
138{
139 PCURICON_OBJECT pcur;
140 int i;
141 PPROCESSINFO ppi;
142
143 if (hcur)
144 {
145 pcur = UserGetCurIconObject(hcur);
146 if (!pcur)
147 {
149 return;
150 }
151
153
154 if (!(ppi->W32PF_flags & W32PF_CREATEDWINORDC))
155 return;
156
157 // Set Small Window Icon and do not link.
158 if ( id == OIC_WINLOGO+1 )
159 {
162 pcur->head.ppi = NULL;
163 return;
164 }
165
166 for (i = 0 ; i < 6; i++)
167 {
168 if (gasysico[i].type == id)
169 {
170 gasysico[i].handle = pcur;
172
173 //
174 // The active switch between LR shared and Global public.
175 // This is hacked around to support this while at the initial system start up.
176 //
177 pcur->head.ppi = NULL;
178
180 return;
181 }
182 }
183 }
184}
185
188{
189 return &gSysCursorInfo;
190}
191
193BOOL
195{
196 return MAKEINTRESOURCE(object->rt) == RT_ICON;
197}
198
199/* This function creates a reference for the object! */
201{
202 PCURICON_OBJECT CurIcon;
203
204 if (!hCurIcon)
205 {
207 return NULL;
208 }
209
210 if (UserObjectInDestroy(hCurIcon))
211 {
212 WARN("Requesting invalid/destroyed cursor.\n");
214 return NULL;
215 }
216
218 if (!CurIcon)
219 {
220 /* We never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */
222 return NULL;
223 }
224
225 ASSERT(CurIcon->head.cLockObj >= 1);
226 return CurIcon;
227}
228
231{
232 PCURICON_OBJECT pcurOld = UserSetCursor(pcurNew, FALSE);
233 if (pcurNew) UserReferenceObject(pcurNew);
234 if (pcurOld) UserDereferenceObject(pcurOld);
235 return pcurOld;
236}
237
239{
241 PSYSTEM_CURSORINFO CurInfo;
242 MSG Msg;
243 RECTL rcClip;
244 POINT pt;
245
247 {
248 return FALSE;
249 }
250
251 CurInfo = IntGetSysCursorInfo();
252
253 /* Clip cursor position */
254 if (!CurInfo->bClipped)
255 rcClip = DesktopWindow->rcClient;
256 else
257 rcClip = CurInfo->rcClip;
258
259 if (x >= rcClip.right) x = rcClip.right - 1;
260 if (x < rcClip.left) x = rcClip.left;
261 if (y >= rcClip.bottom) y = rcClip.bottom - 1;
262 if (y < rcClip.top) y = rcClip.top;
263
264 pt.x = x;
265 pt.y = y;
266
267 if ((gpsi->ptCursor.x != x) || (gpsi->ptCursor.y != y))
268 {
269 /* 1. Generate a mouse move message, this sets the htEx and Track Window too. */
270 Msg.message = WM_MOUSEMOVE;
271 Msg.wParam = UserGetMouseButtonsState();
272 Msg.lParam = MAKELPARAM(x, y);
273 Msg.pt = pt;
274 co_MsqInsertMouseMessage(&Msg, flags, dwExtraInfo, Hook);
275 }
276 /* 2. Store the new cursor position */
277 gpsi->ptCursor = pt;
278
279 return TRUE;
280}
281
282HANDLE
284{
285 PCURICON_OBJECT CurIcon;
286 HANDLE hCurIcon;
287
288 CurIcon = UserCreateObject(
290 NULL,
292 &hCurIcon,
294 Animated ? sizeof(ACON) : sizeof(CURICON_OBJECT));
295
296 if (!CurIcon)
297 {
299 return FALSE;
300 }
301
302 if (Animated)
303 {
304 /* We MUST set this flag, to track whether this is an ACON! */
305 CurIcon->CURSORF_flags |= CURSORF_ACON;
306 }
307
308 NT_ASSERT(CurIcon->pcurNext == NULL);
309 UserDereferenceObject(CurIcon);
310
311 return hCurIcon;
312}
313
317{
318 PCURICON_OBJECT CurIcon = Object;
319
320 /* Check if the cursor is in a list */
321 if (CurIcon->CURSORF_flags & CURSORF_LINKED)
322 {
323 /* Remove the cursor from it's list */
325 }
326
327 /* We just mark the handle as being destroyed.
328 * Deleting all the stuff will be deferred to the actual struct free. */
330 return TRUE;
331}
332
333VOID
336{
337 PCURICON_OBJECT CurIcon = Object;
338
339 if (!(CurIcon->CURSORF_flags & CURSORF_ACON))
340 {
341 HBITMAP bmpMask = CurIcon->hbmMask;
342 HBITMAP bmpColor = CurIcon->hbmColor;
343 HBITMAP bmpAlpha = CurIcon->hbmAlpha;
344
345 /* Delete bitmaps */
346 if (bmpMask)
347 {
349 NT_VERIFY(GreDeleteObject(bmpMask) == TRUE);
350 CurIcon->hbmMask = NULL;
351 }
352 if (bmpColor)
353 {
355 NT_VERIFY(GreDeleteObject(bmpColor) == TRUE);
356 CurIcon->hbmColor = NULL;
357 }
358 if (bmpAlpha)
359 {
361 NT_VERIFY(GreDeleteObject(bmpAlpha) == TRUE);
362 CurIcon->hbmAlpha = NULL;
363 }
364 }
365 else
366 {
367 PACON AniCurIcon = (PACON)CurIcon;
368 UINT i;
369
370 for (i = 0; i < AniCurIcon->cpcur; i++)
371 {
372 UserDereferenceObject(AniCurIcon->aspcur[i]);
374 }
376 }
377
378 if (CurIcon->CURSORF_flags & CURSORF_LRSHARED)
379 {
380 if (!IS_INTRESOURCE(CurIcon->strName.Buffer))
382 if (CurIcon->atomModName)
384 CurIcon->strName.Buffer = NULL;
385 CurIcon->atomModName = 0;
386 }
387
388 /* Finally free the thing */
389 FreeProcMarkObject(CurIcon);
390}
391
394{
395 PCURICON_OBJECT CurIcon;
396
397 /* Run through the list of icon objects */
398 while (Win32Process->pCursorCache)
399 {
400 CurIcon = Win32Process->pCursorCache;
401 Win32Process->pCursorCache = CurIcon->pcurNext;
402 UserDereferenceObject(CurIcon);
403 }
404}
405
406/*
407 * @implemented
408 */
409_Success_(return != FALSE)
410BOOL
411NTAPI
412NtUserGetIconInfo(
413 _In_ HANDLE hCurIcon,
419{
420 ICONINFO ii;
421 PCURICON_OBJECT CurIcon;
423 BOOL Ret = FALSE;
424 DWORD colorBpp = 0;
425
426 TRACE("Enter NtUserGetIconInfo\n");
427
428 /* Check if something was actually asked */
429 if (!IconInfo && !lpModule && !lpResName)
430 {
431 WARN("Nothing to fill.\n");
433 return FALSE;
434 }
435
437
438 if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
439 {
440 WARN("UserGetIconObject(0x%p) Failed.\n", hCurIcon);
441 UserLeave();
442 return FALSE;
443 }
444
445 /* Give back the icon information */
446 if (IconInfo)
447 {
448 PCURICON_OBJECT FrameCurIcon = CurIcon;
449 if (CurIcon->CURSORF_flags & CURSORF_ACON)
450 {
451 /* Get information from first frame. */
452 FrameCurIcon = ((PACON)CurIcon)->aspcur[0];
453 }
454
455 /* Fill data */
456 ii.fIcon = is_icon(FrameCurIcon);
457 ii.xHotspot = FrameCurIcon->xHotspot;
458 ii.yHotspot = FrameCurIcon->yHotspot;
459
460 /* Copy bitmaps */
461 ii.hbmMask = BITMAP_CopyBitmap(FrameCurIcon->hbmMask);
463 ii.hbmColor = BITMAP_CopyBitmap(FrameCurIcon->hbmColor);
465 colorBpp = FrameCurIcon->bpp;
466
467 /* Copy fields */
469 {
470 ProbeForWrite(IconInfo, sizeof(ICONINFO), 1);
471 RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO));
472
473 if (pbpp)
474 {
475 ProbeForWrite(pbpp, sizeof(DWORD), 1);
476 *pbpp = colorBpp;
477 }
478 }
480 {
482 }
484
485 if (!NT_SUCCESS(Status))
486 {
487 WARN("Status: 0x%08lx\n", Status);
489 goto leave;
490 }
491 }
492
493 /* Give back the module name */
494 if (lpModule)
495 {
496 ULONG BufLen = 0;
497 if (!CurIcon->atomModName)
498 goto leave;
499
501 /* Get the module name from the atom table */
503 {
504 BufLen += sizeof(WCHAR);
505 if (BufLen > (lpModule->MaximumLength))
506 {
507 lpModule->Length = 0;
508 lpModule->MaximumLength = BufLen;
509 }
510 else
511 {
512 ProbeForWrite(lpModule->Buffer, lpModule->MaximumLength, 1);
513 BufLen = lpModule->MaximumLength;
514 RtlQueryAtomInAtomTable(gAtomTable, CurIcon->atomModName, NULL, NULL, lpModule->Buffer, &BufLen);
515 lpModule->Length = BufLen;
516 }
517 }
519 {
521 }
523
524 if (!NT_SUCCESS(Status))
525 {
527 goto leave;
528 }
529 }
530
531 if (lpResName)
532 {
533 if (!CurIcon->strName.Buffer)
534 goto leave;
535
536 /* Copy it */
538 {
540 if (IS_INTRESOURCE(CurIcon->strName.Buffer))
541 {
542 lpResName->Buffer = CurIcon->strName.Buffer;
543 lpResName->Length = 0;
544 lpResName->MaximumLength = 0;
545 }
546 else if (lpResName->MaximumLength < CurIcon->strName.MaximumLength)
547 {
548 lpResName->Length = 0;
549 lpResName->MaximumLength = CurIcon->strName.MaximumLength;
550 }
551 else
552 {
553 ProbeForWrite(lpResName->Buffer, lpResName->MaximumLength, 1);
554 RtlCopyMemory(lpResName->Buffer, CurIcon->strName.Buffer, CurIcon->strName.Length);
555 lpResName->Length = CurIcon->strName.Length;
556 }
557 }
559 {
561 }
563 }
564
565 if (!NT_SUCCESS(Status))
566 {
568 goto leave;
569 }
570
571 Ret = TRUE;
572
573leave:
574 UserDereferenceObject(CurIcon);
575
576 TRACE("Leave NtUserGetIconInfo, ret=%i\n", Ret);
577 UserLeave();
578
579 return Ret;
580}
581
582
583/*
584 * @implemented
585 */
586BOOL
589 HANDLE hCurIcon,
590 UINT istepIfAniCur,
591 PLONG plcx, // &size.cx
592 PLONG plcy) // &size.cy
593{
594 PCURICON_OBJECT CurIcon;
596 BOOL bRet = FALSE;
597
598 TRACE("Enter NtUserGetIconSize\n");
600
601 if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
602 {
603 goto cleanup;
604 }
605
606 if (CurIcon->CURSORF_flags & CURSORF_ACON)
607 {
608 /* Use first frame for animated cursors */
609 PACON AniCurIcon = (PACON)CurIcon;
610 CurIcon = AniCurIcon->aspcur[0];
611 UserDereferenceObject(AniCurIcon);
612 UserReferenceObject(CurIcon);
613 }
614
616 {
617 ProbeForWrite(plcx, sizeof(LONG), 1);
618 *plcx = CurIcon->cx;
619 ProbeForWrite(plcy, sizeof(LONG), 1);
620 *plcy = CurIcon->cy;
621 }
623 {
625 }
627
628 if (NT_SUCCESS(Status))
629 bRet = TRUE;
630 else
631 SetLastNtError(Status); // Maybe not, test this
632
633 UserDereferenceObject(CurIcon);
634
635cleanup:
636 TRACE("Leave NtUserGetIconSize, ret=%i\n", bRet);
637 UserLeave();
638 return bRet;
639}
640
641
642/*
643 * @implemented
644 */
645BOOL
648 PCURSORINFO pci)
649{
650 CURSORINFO SafeCi;
651 PSYSTEM_CURSORINFO CurInfo;
653 PCURICON_OBJECT CurIcon;
654 BOOL Ret = FALSE;
655
656 TRACE("Enter NtUserGetCursorInfo\n");
658
659 CurInfo = IntGetSysCursorInfo();
660 CurIcon = (PCURICON_OBJECT)CurInfo->CurrentCursorObject;
661
662 SafeCi.cbSize = sizeof(CURSORINFO);
663 SafeCi.flags = ((CurIcon && CurInfo->ShowingCursor >= 0) ? CURSOR_SHOWING : 0);
664 SafeCi.hCursor = (CurIcon ? UserHMGetHandle(CurIcon) : NULL);
665
666 SafeCi.ptScreenPos = gpsi->ptCursor;
667
669 {
670 if (pci->cbSize == sizeof(CURSORINFO))
671 {
672 ProbeForWrite(pci, sizeof(CURSORINFO), 1);
673 RtlCopyMemory(pci, &SafeCi, sizeof(CURSORINFO));
674 Ret = TRUE;
675 }
676 else
677 {
679 }
680 }
682 {
684 }
685 _SEH2_END;
686 if (!NT_SUCCESS(Status))
687 {
689 }
690
691 TRACE("Leave NtUserGetCursorInfo, ret=%i\n", Ret);
692 UserLeave();
693 return Ret;
694}
695
696BOOL
699 RECTL *prcl)
700{
701 PSYSTEM_CURSORINFO CurInfo;
703
705 {
706 return FALSE;
707 }
708
709 CurInfo = IntGetSysCursorInfo();
710
712
713 if (prcl != NULL && DesktopWindow != NULL)
714 {
715 if (prcl->right < prcl->left || prcl->bottom < prcl->top)
716 {
718 return FALSE;
719 }
720
721 CurInfo->bClipped = TRUE;
722
723 /* Set nw cliping region. Note: we can't use RECTL_bIntersectRect because
724 it sets rect to 0 0 0 0 when it's empty. For more info see monitor winetest */
725 CurInfo->rcClip.left = max(prcl->left, DesktopWindow->rcWindow.left);
726 CurInfo->rcClip.right = min(prcl->right, DesktopWindow->rcWindow.right);
727 if (CurInfo->rcClip.right < CurInfo->rcClip.left)
728 CurInfo->rcClip.right = CurInfo->rcClip.left;
729
730 CurInfo->rcClip.top = max(prcl->top, DesktopWindow->rcWindow.top);
731 CurInfo->rcClip.bottom = min(prcl->bottom, DesktopWindow->rcWindow.bottom);
732 if (CurInfo->rcClip.bottom < CurInfo->rcClip.top)
733 CurInfo->rcClip.bottom = CurInfo->rcClip.top;
734
735 /* Make sure cursor is in clipping region */
736 UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, 0, 0, FALSE);
737 }
738 else
739 {
740 CurInfo->bClipped = FALSE;
741 }
742
743 return TRUE;
744}
745
746/*
747 * @implemented
748 */
749BOOL
752 RECTL *prcl)
753{
754 RECTL rclLocal;
755 BOOL bResult;
756
757 if (prcl)
758 {
760 {
761 /* Probe and copy rect */
762 ProbeForRead(prcl, sizeof(RECTL), 1);
763 rclLocal = *prcl;
764 }
766 {
768 _SEH2_YIELD(return FALSE;)
769 }
771
772 prcl = &rclLocal;
773 }
774
776
777 /* Call the internal function */
778 bResult = UserClipCursor(prcl);
779
780 UserLeave();
781
782 return bResult;
783}
784
785
786/*
787 * @implemented
788 */
789BOOL
792 _In_ HANDLE hCurIcon,
793 _In_ BOOL bForce)
794{
795 BOOL ret;
796 PCURICON_OBJECT CurIcon = NULL;
797
798 TRACE("Enter NtUserDestroyCursorIcon (%p, %i)\n", hCurIcon, bForce);
800
801 CurIcon = UserGetCurIconObject(hCurIcon);
802 if (!CurIcon)
803 {
804 ret = FALSE;
805 goto leave;
806 }
807
808 if (!bForce)
809 {
810 /* Can not destroy global objects */
811 if (CurIcon->head.ppi == NULL)
812 {
813 ERR("Trying to delete global cursor!\n");
814 ret = TRUE;
815 goto leave;
816 }
817
818 /* Maybe we have good reasons not to destroy this object */
819 if (CurIcon->head.ppi != PsGetCurrentProcessWin32Process())
820 {
821 /* No way, you're not touching my cursor */
822 ret = FALSE;
823 goto leave;
824 }
825
826 if (CurIcon->CURSORF_flags & CURSORF_CURRENT)
827 {
828 WARN("Trying to delete current cursor!\n");
829 ret = FALSE;
830 goto leave;
831 }
832
833 if (CurIcon->CURSORF_flags & CURSORF_LRSHARED)
834 {
835 WARN("Trying to delete shared cursor.\n");
836 /* This one is not an error */
837 ret = TRUE;
838 goto leave;
839 }
840 }
841
842 /* Destroy the handle */
843 ret = IntDestroyCurIconObject(CurIcon);
844
845leave:
846 if (CurIcon)
847 UserDereferenceObject(CurIcon);
848 TRACE("Leave NtUserDestroyCursorIcon, ret=%i\n", ret);
849 UserLeave();
850 return ret;
851}
852
853
854/*
855 * @implemented
856 */
857HICON
858NTAPI
860 _In_ PUNICODE_STRING pustrModule,
861 _In_ PUNICODE_STRING pustrRsrc,
863{
864 PCURICON_OBJECT CurIcon;
865 HICON Ret = NULL;
866 UNICODE_STRING ustrModuleSafe, ustrRsrcSafe;
867 FINDEXISTINGCURICONPARAM paramSafe;
870 RTL_ATOM atomModName;
871
872 TRACE("Enter NtUserFindExistingCursorIcon\n");
873
875 {
876 ProbeForRead(param, sizeof(*param), 1);
877 RtlCopyMemory(&paramSafe, param, sizeof(paramSafe));
878 }
880 {
882 }
884
885 /* Capture resource name (it can be an INTRESOURCE == ATOM) */
886 Status = ProbeAndCaptureUnicodeStringOrAtom(&ustrRsrcSafe, pustrRsrc);
887 if (!NT_SUCCESS(Status))
888 return NULL;
889 Status = ProbeAndCaptureUnicodeString(&ustrModuleSafe, UserMode, pustrModule);
890 if (!NT_SUCCESS(Status))
891 goto done;
892 Status = RtlLookupAtomInAtomTable(gAtomTable, ustrModuleSafe.Buffer, &atomModName);
893 ReleaseCapturedUnicodeString(&ustrModuleSafe, UserMode);
894 if (!NT_SUCCESS(Status))
895 {
896 /* The module is not in the atom table. No chance to find the cursor */
897 goto done;
898 }
899
901 CurIcon = pProcInfo->pCursorCache;
902 while (CurIcon)
903 {
904 /* Icon/cursor */
905 if (paramSafe.bIcon != is_icon(CurIcon))
906 {
907 CurIcon = CurIcon->pcurNext;
908 continue;
909 }
910 /* See if module names match */
911 if (atomModName == CurIcon->atomModName)
912 {
913 /* They do. Now see if this is the same resource */
914 if (IS_INTRESOURCE(CurIcon->strName.Buffer) != IS_INTRESOURCE(ustrRsrcSafe.Buffer))
915 {
916 /* One is an INT resource and the other is not -> no match */
917 CurIcon = CurIcon->pcurNext;
918 continue;
919 }
920
921 if (IS_INTRESOURCE(CurIcon->strName.Buffer))
922 {
923 if (CurIcon->strName.Buffer == ustrRsrcSafe.Buffer)
924 {
925 /* INT resources match */
926 break;
927 }
928 }
929 else if (RtlCompareUnicodeString(&ustrRsrcSafe, &CurIcon->strName, TRUE) == 0)
930 {
931 /* Resource name strings match */
932 break;
933 }
934 }
935 CurIcon = CurIcon->pcurNext;
936 }
937
938 /* Now search Global Cursors or Icons. */
939 if (CurIcon == NULL)
940 {
941 CurIcon = gcurFirst;
942 while (CurIcon)
943 {
944 /* Icon/cursor */
945 if (paramSafe.bIcon != is_icon(CurIcon))
946 {
947 CurIcon = CurIcon->pcurNext;
948 continue;
949 }
950 /* See if module names match */
951 if (atomModName == CurIcon->atomModName)
952 {
953 /* They do. Now see if this is the same resource */
954 if (IS_INTRESOURCE(CurIcon->strName.Buffer) != IS_INTRESOURCE(ustrRsrcSafe.Buffer))
955 {
956 /* One is an INT resource and the other is not -> no match */
957 CurIcon = CurIcon->pcurNext;
958 continue;
959 }
960 if (IS_INTRESOURCE(CurIcon->strName.Buffer))
961 {
962 if (CurIcon->strName.Buffer == ustrRsrcSafe.Buffer)
963 {
964 /* INT resources match */
965 break;
966 }
967 }
968 else if (RtlCompareUnicodeString(&ustrRsrcSafe, &CurIcon->strName, TRUE) == 0)
969 {
970 /* Resource name strings match */
971 break;
972 }
973 }
974 CurIcon = CurIcon->pcurNext;
975 }
976 }
977 if (CurIcon)
978 Ret = UserHMGetHandle(CurIcon);
979 UserLeave();
980
981done:
982 if (!IS_INTRESOURCE(ustrRsrcSafe.Buffer))
983 ExFreePoolWithTag(ustrRsrcSafe.Buffer, TAG_STRING);
984
985 return Ret;
986}
987
988
989/*
990 * @implemented
991 */
992BOOL
995 RECTL *lpRect)
996{
997 PSYSTEM_CURSORINFO CurInfo;
998 RECTL Rect;
1000 BOOL Ret = FALSE;
1001
1002 TRACE("Enter NtUserGetClipCursor\n");
1004
1006 {
1007 goto Exit; // Return FALSE
1008 }
1009
1010 if (!lpRect)
1011 goto Exit; // Return FALSE
1012
1013 CurInfo = IntGetSysCursorInfo();
1014 if (CurInfo->bClipped)
1015 {
1016 Rect = CurInfo->rcClip;
1017 }
1018 else
1019 {
1020 Rect.left = 0;
1021 Rect.top = 0;
1024 }
1025
1026 Status = MmCopyToCaller(lpRect, &Rect, sizeof(RECT));
1027 if (!NT_SUCCESS(Status))
1028 {
1030 goto Exit; // Return FALSE
1031 }
1032
1033 Ret = TRUE;
1034
1035Exit:
1036 TRACE("Leave NtUserGetClipCursor, ret=%i\n", Ret);
1037 UserLeave();
1038 return Ret;
1039}
1040
1041
1042/*
1043 * @implemented
1044 */
1045HCURSOR
1048 HCURSOR hCursor)
1049{
1050 PCURICON_OBJECT pcurOld, pcurNew;
1051 HCURSOR hOldCursor = NULL;
1052
1053 TRACE("Enter NtUserSetCursor: %p\n", hCursor);
1055
1056 if (hCursor)
1057 {
1058 pcurNew = UserGetCurIconObject(hCursor);
1059 if (!pcurNew)
1060 {
1062 goto leave;
1063 }
1064 pcurNew->CURSORF_flags |= CURSORF_CURRENT;
1065 }
1066 else
1067 {
1068 pcurNew = NULL;
1069 }
1070
1071 pcurOld = UserSetCursor(pcurNew, FALSE);
1072
1073 // If returning an old cursor than validate it, Justin Case!
1074 if ( pcurOld &&
1076 {
1077 hOldCursor = UserHMGetHandle(pcurOld);
1078 /*
1079 Problem:
1080
1081 System Global Cursors start out having at least 2 lock counts. If a system
1082 cursor is the default cursor and is returned to the caller twice in its
1083 life, the count will reach zero. Causing an assert to occur in objects.
1084
1085 This fixes a SeaMonkey crash while the mouse crosses a boundary.
1086 */
1087 if (pcurOld->CURSORF_flags & CURSORF_GLOBAL)
1088 {
1089 TRACE("Returning Global Cursor hcur %p\n",hOldCursor);
1090
1091 /*if (pcurOld->head.cLockObj > 2) // Throttle down to 2.
1092 {
1093 UserDereferenceObject(pcurOld);
1094 }
1095
1096 goto leave;*/
1097 }
1098
1099 /* See if it was destroyed in the meantime */
1100 if (UserObjectInDestroy(hOldCursor))
1101 hOldCursor = NULL;
1102 pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
1103 UserDereferenceObject(pcurOld);
1104 }
1105
1106leave:
1107 UserLeave();
1108 return hOldCursor;
1109}
1110
1111
1112/*
1113 * @unimplemented
1114 */
1115BOOL
1118 HANDLE hCurIcon,
1119 PICONINFO UnsafeIconInfo)
1120{
1121 FIXME(" is UNIMPLEMENTED.\n");
1122 return FALSE;
1123}
1124
1125
1126static
1127BOOL
1130 _In_opt_ PUNICODE_STRING pustrName,
1131 _In_ ATOM atomModName,
1132 _In_ const CURSORDATA* pcursordata)
1133{
1134 /* Check if the CURSORF_ACON is also set in the cursor data */
1135 if (pcursordata->CURSORF_flags & CURSORF_ACON)
1136 {
1137 ERR("Mismatch in CURSORF_flags! cursor: 0x%08lx, data: 0x%08lx\n",
1138 pcur->CURSORF_flags, pcursordata->CURSORF_flags);
1139 return FALSE;
1140 }
1141
1142 /* Check if this cursor was already set */
1143 if (pcur->hbmMask != NULL)
1144 {
1145 ERR("Cursor data already set!\n");
1146 return FALSE;
1147 }
1148
1149 /* We need a mask */
1150 if (pcursordata->hbmMask == NULL)
1151 {
1152 ERR("NtUserSetCursorIconData was got no hbmMask.\n");
1154 return FALSE;
1155 }
1156
1157 /* Take ownership of the mask bitmap */
1158 if (!GreSetBitmapOwner(pcursordata->hbmMask, GDI_OBJ_HMGR_PUBLIC))
1159 {
1160 ERR("Failed to set ownership of hbmMask %p.\n", pcursordata->hbmMask);
1161 return FALSE;
1162 }
1163
1164 /* Check if we have a color bitmap */
1165 if (pcursordata->hbmColor)
1166 {
1167 /* Take ownership of the color bitmap */
1168 if (!GreSetBitmapOwner(pcursordata->hbmColor, GDI_OBJ_HMGR_PUBLIC))
1169 {
1170 ERR("Failed to set ownership of hbmColor %p.\n", pcursordata->hbmColor);
1171 GreSetBitmapOwner(pcursordata->hbmMask, GDI_OBJ_HMGR_POWNED);
1172 return FALSE;
1173 }
1174 }
1175
1176 /* Check if we have an alpha bitmap */
1177 if (pcursordata->hbmAlpha)
1178 {
1179 /* Take ownership of the alpha bitmap */
1180 if (!GreSetBitmapOwner(pcursordata->hbmAlpha, GDI_OBJ_HMGR_PUBLIC))
1181 {
1182 ERR("Failed to set ownership of hbmAlpha %p.\n", pcursordata->hbmAlpha);
1183 GreSetBitmapOwner(pcursordata->hbmMask, GDI_OBJ_HMGR_POWNED);
1184 if (pcursordata->hbmColor)
1185 {
1186 GreSetBitmapOwner(pcursordata->hbmColor, GDI_OBJ_HMGR_POWNED);
1187 }
1188 return FALSE;
1189 }
1190 }
1191
1192 /* Free the old name (Must be NULL atm, but later we might allow this) */
1193 NT_ASSERT(pcur->strName.Buffer == NULL);
1194 if (pcur->strName.Buffer != NULL)
1195 {
1196 if (!IS_INTRESOURCE(pcur->strName.Buffer))
1197 {
1198 ExFreePoolWithTag(pcur->strName.Buffer, TAG_STRING);
1199 }
1200 RtlInitEmptyUnicodeString(&pcur->strName, NULL, 0);
1201 }
1202
1203 /* Free the module atom */
1204 if (pcur->atomModName != 0)
1205 {
1207 }
1208
1209 /* Now set the new cursor data */
1210 pcur->atomModName = atomModName;
1211 pcur->rt = pcursordata->rt;
1212 pcur->CURSORF_flags = pcursordata->CURSORF_flags & CURSORF_USER_MASK;
1213 pcur->xHotspot = pcursordata->xHotspot;
1214 pcur->yHotspot = pcursordata->yHotspot;
1215 pcur->hbmMask = pcursordata->hbmMask;
1216 pcur->hbmColor = pcursordata->hbmColor;
1217 pcur->hbmAlpha = pcursordata->hbmAlpha;
1218 pcur->rcBounds.left = 0;
1219 pcur->rcBounds.top = 0;
1220 pcur->rcBounds.right = pcursordata->cx;
1221 pcur->rcBounds.bottom = pcursordata->cy;
1222 pcur->hbmUserAlpha = pcursordata->hbmUserAlpha;
1223 pcur->bpp = pcursordata->bpp;
1224 pcur->cx = pcursordata->cx;
1225 pcur->cy = pcursordata->cy;
1226 if (pustrName != NULL)
1227 {
1228 pcur->strName = *pustrName;
1229 }
1230
1231 return TRUE;
1232}
1233
1234static
1235BOOL
1237 _Inout_ PACON pacon,
1238 _In_opt_ PUNICODE_STRING pustrName,
1239 _In_ ATOM atomModName,
1240 _In_ const CURSORDATA *pcursordata)
1241{
1242 PCURICON_OBJECT *aspcur;
1243 DWORD *aicur;
1244 INT *ajifRate;
1245 PCURSORDATA pcdFrame;
1246 HCURSOR hcurFrame;
1247 UINT cjSize, i;
1248
1249 NT_ASSERT((pacon->CURSORF_flags & CURSORF_ACON) != 0);
1250 NT_ASSERT((pacon->CURSORF_flags & CURSORF_ACONFRAME) == 0);
1251 NT_ASSERT((ULONG_PTR)pcursordata->aspcur > MmUserProbeAddress);
1252 NT_ASSERT((ULONG_PTR)pcursordata->aicur > MmUserProbeAddress);
1253 NT_ASSERT((ULONG_PTR)pcursordata->ajifRate > MmUserProbeAddress);
1254 NT_ASSERT((pcursordata->CURSORF_flags & ~CURSORF_USER_MASK) == 0);
1255 NT_ASSERT(pcursordata->cpcur > 0);
1256 NT_ASSERT(pcursordata->cicur > 0);
1257
1258 /* Check if the CURSORF_ACON is also set in the cursor data */
1259 if (!(pcursordata->CURSORF_flags & CURSORF_ACON))
1260 {
1261 ERR("Mismatch in CURSORF_flags! acon: 0x%08lx, data: 0x%08lx\n",
1262 pacon->CURSORF_flags, pcursordata->CURSORF_flags);
1263 return FALSE;
1264 }
1265
1266 /* Check if this acon was already set */
1267 if (pacon->aspcur != NULL)
1268 {
1269 ERR("Acon data already set!\n");
1270 return FALSE;
1271 }
1272
1273 /* Loop all frames indexes */
1274 for (i = 0; i < pcursordata->cicur; i++)
1275 {
1276 /* Check if the index is within the range of the frames */
1277 if (pcursordata->aicur[i] >= pcursordata->cpcur)
1278 {
1279 ERR("aicur[%lu] is out or range. Got %lu, cpcur = %u\n",
1280 i, pcursordata->aicur[i], pcursordata->cpcur);
1281 return FALSE;
1282 }
1283
1284 /* FIXME: check the JIF rates? */
1285 }
1286
1287 /* Calculate size: one cursor object for each frame, and a frame
1288 index and jiffies for each "step" */
1289 cjSize = (pcursordata->cpcur * sizeof(CURICON_OBJECT*)) +
1290 (pcursordata->cicur * sizeof(DWORD)) +
1291 (pcursordata->cicur * sizeof(INT));
1292
1293 /* Allocate a buffer */
1295 if (aspcur == NULL)
1296 {
1297 ERR("Failed to allocate memory (cpcur = %u, cicur = %u)\n",
1298 pcursordata->cpcur, pcursordata->cicur);
1299 return FALSE;
1300 }
1301
1302 /* Set the pointers */
1303 aicur = (DWORD*)&aspcur[pcursordata->cpcur];
1304 ajifRate = (INT*)&aicur[pcursordata->cicur];
1305
1306 /* Copy the values */
1307 RtlCopyMemory(aicur, pcursordata->aicur, pcursordata->cicur * sizeof(DWORD));
1308 RtlCopyMemory(ajifRate, pcursordata->ajifRate, pcursordata->cicur * sizeof(INT));
1309
1310 /* Zero out the array, so we can handle cleanup */
1311 RtlZeroMemory(aspcur, pcursordata->cpcur * sizeof(PCURICON_OBJECT));
1312
1313 /* Get a pointer to the cursor data for each frame */
1314 pcdFrame = pcursordata->aspcur;
1315
1316 /* Create the cursors */
1317 for (i = 0; i < pcursordata->cpcur; i++)
1318 {
1319 /* Create a cursor for this frame */
1320 hcurFrame = IntCreateCurIconHandle(FALSE);
1321 if (hcurFrame == NULL)
1322 {
1323 ERR("Failed to create a cursor for frame %u\n", i);
1324 goto Cleanup;
1325 }
1326
1327 /* Get a pointer to the frame cursor */
1328 aspcur[i] = UserGetCurIconObject(hcurFrame);
1330 NT_ASSERT(aspcur[i] != NULL);
1331
1332 /* Check if the flags are valid */
1334 {
1335 ERR("Invalid flags for acon frame %u: 0x%08lx\n",
1336 i, pcdFrame->CURSORF_flags);
1337 goto Cleanup;
1338 }
1339
1340 /* Set the cursor data for this frame */
1341 if (!IntSetCursorData(aspcur[i], NULL, 0, &pcdFrame[i]))
1342 {
1343 ERR("Failed to set cursor data for frame %u\n", i);
1344 goto Cleanup;
1345 }
1346
1347 /* Mark this cursor as an acon frame */
1348 aspcur[i]->CURSORF_flags |= CURSORF_ACONFRAME;
1349 }
1350
1351 /* Free the old name (Must be NULL atm.) */
1352 NT_ASSERT(pacon->strName.Buffer == NULL);
1353 if (pacon->strName.Buffer != NULL)
1354 {
1355 if (!IS_INTRESOURCE(pacon->strName.Buffer))
1356 {
1357 ExFreePoolWithTag(pacon->strName.Buffer, TAG_STRING);
1358 }
1359 RtlInitEmptyUnicodeString(&pacon->strName, NULL, 0);
1360 }
1361
1362 /* Free the module atom */
1363 if (pacon->atomModName != 0)
1364 {
1366 }
1367
1368 /* Free the previous frames */
1369 if (pacon->aspcur != NULL)
1370 {
1371 for (i = 0; i < pacon->cpcur; i++)
1372 {
1373 UserDereferenceObject(pacon->aspcur[i]);
1374 NT_VERIFY(IntDestroyCurIconObject(pacon->aspcur[i]) == TRUE);
1375 }
1376 ExFreePoolWithTag(pacon->aspcur, USERTAG_CURSOR);
1377 }
1378
1379 /* Finally set the data in the acon */
1380 pacon->atomModName = atomModName;
1381 pacon->rt = pcursordata->rt;
1382 pacon->CURSORF_flags = pcursordata->CURSORF_flags & CURSORF_USER_MASK;
1383 pacon->cpcur = pcursordata->cpcur;
1384 pacon->cicur = pcursordata->cicur;
1385 pacon->aspcur = aspcur;
1386 pacon->aicur = aicur;
1387 pacon->ajifRate = ajifRate;
1388 pacon->iicur = 0;
1389 if (pustrName != NULL)
1390 {
1391 pacon->strName = *pustrName;
1392 }
1393
1394 return TRUE;
1395
1396Cleanup:
1397
1398 /* Clean up the cursors we created */
1399 for (i = 0; i < pcursordata->cpcur; i++)
1400 {
1401 if (aspcur[i] == NULL)
1402 break;
1403
1404 /* Destroy this cursor */
1405 UserDereferenceObject(aspcur[i]);
1407 }
1408
1409 /* Delete the allocated structure */
1411
1412 return FALSE;
1413}
1414
1415BOOL
1418 _In_ HCURSOR hcursor,
1419 _In_opt_ PUNICODE_STRING pustrModule,
1420 _In_opt_ PUNICODE_STRING pustrRsrc,
1421 _In_ PCURSORDATA pcursordata)
1422{
1423 PCURICON_OBJECT pcur;
1424 ATOM atomModName;
1426 BOOL bResult;
1427
1428 /* Do we have a module name? */
1429 if (pustrModule != NULL)
1430 {
1431 /* Create an atom for the module name */
1433 pustrModule->Buffer,
1434 &atomModName);
1435 if (!NT_SUCCESS(status))
1436 {
1437 ERR("Failed to create atom from module name '%wZ': 0x%08lx\n",
1438 pustrModule, status);
1439 return FALSE;
1440 }
1441 }
1442 else
1443 {
1444 /* No module name atom */
1445 atomModName = 0;
1446 }
1447
1448 /* Reference the cursor */
1449 pcur = UserGetCurIconObject(hcursor);
1450 if (pcur == NULL)
1451 {
1452 ERR("Failed to reference cursor %p\n", hcursor);
1453 bResult = FALSE;
1454 goto Exit;
1455 }
1456
1457 /* Check if this is an acon */
1458 if (pcur->CURSORF_flags & CURSORF_ACON)
1459 {
1460 bResult = IntSetAconData((PACON)pcur,
1461 pustrRsrc,
1462 atomModName,
1463 pcursordata);
1464 }
1465 else
1466 {
1467 bResult = IntSetCursorData(pcur,
1468 pustrRsrc,
1469 atomModName,
1470 pcursordata);
1471 }
1472
1473Exit:
1474
1475 /* Check if we had success */
1476 if (bResult != FALSE)
1477 {
1478 /* Check if this is an LRSHARED cursor now */
1479 if (pcur->CURSORF_flags & CURSORF_LRSHARED)
1480 {
1481 /* Insert the cursor into the list. */
1483 }
1484 }
1485 else
1486 {
1487 /* Cleanup on failure */
1488 if (atomModName != 0)
1489 {
1491 }
1492 }
1493
1494 /* Dereference the cursor and return the result */
1495 if (pcur)
1497
1498 return bResult;
1499}
1500
1501
1502/*
1503 * @implemented
1504 */
1506BOOL
1509 _In_ HCURSOR hcursor,
1510 _In_opt_ PUNICODE_STRING pustrModule,
1511 _In_opt_ PUNICODE_STRING pustrRsrc,
1512 _In_ const CURSORDATA* pCursorData)
1513{
1514 CURSORDATA cursordata;
1515 UNICODE_STRING ustrModule, ustrRsrc;
1516 _SEH2_VOLATILE PVOID pvBuffer;
1517 CURSORDATA* aspcur;
1518 DWORD* aicur;
1519 PINT ajifRate;
1520 UINT cjSize;
1522 BOOL bResult = FALSE;
1523
1524 TRACE("Enter NtUserSetCursorIconData\n");
1525
1526 /* Initialize buffer, so we can handle cleanup */
1527 ustrRsrc.Buffer = NULL;
1528 ustrModule.Buffer = NULL;
1529 pvBuffer = NULL;
1530
1531 _SEH2_TRY
1532 {
1533 /* Probe and capture the cursor data structure */
1534 ProbeForRead(pCursorData, sizeof(*pCursorData), 1);
1535 cursordata = *pCursorData;
1536
1537 /* Check if this is an animated cursor */
1538 if (cursordata.CURSORF_flags & CURSORF_ACON)
1539 {
1540 /* Check of the range is ok */
1541 if ((cursordata.cpcur == 0) || (cursordata.cicur == 0) ||
1542 (cursordata.cpcur > 1000) || (cursordata.cicur > 1000))
1543 {
1544 ERR("Range error (cpcur = %u, cicur = %u)\n",
1545 cursordata.cpcur, cursordata.cicur);
1546 goto Exit;
1547 }
1548
1549 /* Calculate size: one cursor data structure for each frame,
1550 and a frame index and jiffies for each "step" */
1551 cjSize = (cursordata.cpcur * sizeof(CURSORDATA)) +
1552 (cursordata.cicur * sizeof(DWORD)) +
1553 (cursordata.cicur * sizeof(INT));
1554
1555 /* Allocate a buffer */
1557 if (pvBuffer == NULL)
1558 {
1559 ERR("Failed to allocate memory (cpcur = %u, cicur = %u)\n",
1560 cursordata.cpcur, cursordata.cicur);
1561 goto Exit;
1562 }
1563
1564 /* Calculate the kernel mode pointers */
1565 aspcur = (CURSORDATA*)pvBuffer;
1566 aicur = (DWORD*)&aspcur[cursordata.cpcur];
1567 ajifRate = (INT*)&aicur[cursordata.cicur];
1568
1569 /* Probe and copy aspcur */
1570 ProbeForRead(cursordata.aspcur, cursordata.cpcur * sizeof(CURSORDATA), 1);
1571 RtlCopyMemory(aspcur,
1572 cursordata.aspcur,
1573 cursordata.cpcur * sizeof(CURSORDATA));
1574
1575 /* Probe and copy aicur */
1576 ProbeForRead(cursordata.aicur, cursordata.cicur * sizeof(DWORD), 1);
1577 RtlCopyMemory(aicur,
1578 cursordata.aicur,
1579 cursordata.cicur * sizeof(DWORD));
1580
1581 /* Probe and copy ajifRate */
1582 ProbeForRead(cursordata.ajifRate, cursordata.cicur * sizeof(INT), 1);
1583 RtlCopyMemory(ajifRate,
1584 cursordata.ajifRate,
1585 cursordata.cicur * sizeof(INT));
1586
1587 /* Set the new pointers */
1588 cursordata.aspcur = aspcur;
1589 cursordata.aicur = aicur;
1590 cursordata.ajifRate = ajifRate;
1591 }
1592 else
1593 {
1594 /* This is a standard cursor, we don't use the pointers */
1595 cursordata.aspcur = NULL;
1596 cursordata.aicur = NULL;
1597 cursordata.ajifRate = NULL;
1598 }
1599 }
1601 {
1603 goto Exit;
1604 }
1605 _SEH2_END
1606
1607 /* Check if we got a module name */
1608 if (pustrModule != NULL)
1609 {
1610 /* Capture the name */
1611 status = ProbeAndCaptureUnicodeString(&ustrModule, UserMode, pustrModule);
1612 if (!NT_SUCCESS(status))
1613 {
1614 ERR("Failed to copy pustrModule: status 0x%08lx\n", status);
1615 goto Exit;
1616 }
1617 }
1618
1619 /* Check if we got a resource name */
1620 if (pustrRsrc != NULL)
1621 {
1622 /* We use this function, because INTRESOURCEs and ATOMs are the same */
1623 status = ProbeAndCaptureUnicodeStringOrAtom(&ustrRsrc, pustrRsrc);
1624 if (!NT_SUCCESS(status))
1625 {
1626 ERR("Failed to copy pustrRsrc: status 0x%08lx\n", status);
1627 goto Exit;
1628 }
1629 }
1630
1631 /* Make sure the caller doesn't give us invalid flags */
1632 if (cursordata.CURSORF_flags & ~CURSORF_USER_MASK)
1633 {
1634 ERR("Invalid cursor flags: 0x%08lx\n", cursordata.CURSORF_flags);
1635 goto Exit;
1636 }
1637
1638 /* Acquire the global user lock */
1640
1641 /* Call the internal function */
1642 bResult = UserSetCursorIconData(hcursor,
1643 pustrModule ? &ustrModule : NULL,
1644 pustrRsrc ? &ustrRsrc : NULL,
1645 &cursordata);
1646
1647 /* Release the global user lock */
1648 UserLeave();
1649
1650Exit:
1651
1652 /* Free the captured module name */
1653 if ((ustrModule.Buffer != NULL) && !IS_INTRESOURCE(ustrModule.Buffer))
1654 {
1656 }
1657
1658 if (pvBuffer != NULL)
1659 {
1661 }
1662
1663 /* Additional cleanup on failure */
1664 if (bResult == FALSE)
1665 {
1666 if ((ustrRsrc.Buffer != NULL) &&
1667 !IS_INTRESOURCE(ustrRsrc.Buffer))
1668 {
1670 }
1671 }
1672
1673 TRACE("Leave NtUserSetCursorIconData, bResult = %i\n", bResult);
1674
1675 return bResult;
1676}
1677
1678/* Mostly inspired from wine code.
1679 * We use low level functions because:
1680 * - at this point, the icon bitmap could have a different bit depth than the DC,
1681 * making it thus impossible to use NtCreateCompatibleDC and selecting the bitmap.
1682 * This happens after a mode setting change.
1683 * - it avoids massive GDI objects locking when only the destination surface needs it.
1684 * - It makes (small) performance gains.
1685 */
1686BOOL
1688 HDC hDc,
1689 INT xLeft,
1690 INT yTop,
1691 PCURICON_OBJECT pIcon,
1692 INT cxWidth,
1693 INT cyHeight,
1694 UINT istepIfAniCur,
1695 HBRUSH hbrFlickerFreeDraw,
1696 UINT diFlags)
1697{
1698 PSURFACE psurfDest, psurfMask, psurfColor; //, psurfOffScreen = NULL;
1699 PDC pdc = NULL;
1700 BOOL Ret = FALSE;
1701 HBITMAP hbmMask, hbmColor, hbmAlpha;
1702 BOOL bOffScreen;
1703 RECTL rcDest, rcSrc;
1704 CLIPOBJ* pdcClipObj = NULL;
1705 EXLATEOBJ exlo;
1706
1707 /* Stupid case */
1708 if ((diFlags & DI_NORMAL) == 0)
1709 {
1710 ERR("DrawIconEx called without mask or color bitmap to draw.\n");
1711 return FALSE;
1712 }
1713
1714 if (pIcon->CURSORF_flags & CURSORF_ACON)
1715 {
1716 ACON* pAcon = (ACON*)pIcon;
1717 if (istepIfAniCur >= pAcon->cicur)
1718 {
1719 ERR("NtUserDrawIconEx: istepIfAniCur too big!\n");
1720 return FALSE;
1721 }
1722 pIcon = pAcon->aspcur[pAcon->aicur[istepIfAniCur]];
1723 }
1724
1725 hbmMask = pIcon->hbmMask;
1726 hbmColor = pIcon->hbmColor;
1727 hbmAlpha = pIcon->hbmAlpha;
1728
1729 /*
1730 * Get our objects.
1731 * Shared locks are enough, we are only reading those bitmaps
1732 */
1733 psurfMask = SURFACE_ShareLockSurface(hbmMask);
1734 if (psurfMask == NULL)
1735 {
1736 ERR("Unable to lock the mask surface.\n");
1737 return FALSE;
1738 }
1739
1740 /* Color bitmap is not mandatory */
1741 if (hbmColor == NULL)
1742 {
1743 /* But then the mask bitmap must have the information in it's bottom half */
1744 ASSERT(psurfMask->SurfObj.sizlBitmap.cy == 2*pIcon->cy);
1745 psurfColor = NULL;
1746 }
1747 else if ((psurfColor = SURFACE_ShareLockSurface(hbmColor)) == NULL)
1748 {
1749 ERR("Unable to lock the color bitmap.\n");
1750 SURFACE_ShareUnlockSurface(psurfMask);
1751 return FALSE;
1752 }
1753
1754 pdc = DC_LockDc(hDc);
1755 if (!pdc)
1756 {
1757 ERR("Could not lock the destination DC.\n");
1758 SURFACE_ShareUnlockSurface(psurfMask);
1759 if (psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
1760 return FALSE;
1761 }
1762
1763 /* Fix width parameter, if needed */
1764 if (!cxWidth)
1765 {
1766 if (diFlags & DI_DEFAULTSIZE)
1767 cxWidth = is_icon(pIcon) ?
1769 else
1770 cxWidth = pIcon->cx;
1771 }
1772
1773 /* Fix height parameter, if needed */
1774 if (!cyHeight)
1775 {
1776 if (diFlags & DI_DEFAULTSIZE)
1777 cyHeight = is_icon(pIcon) ?
1779 else
1780 cyHeight = pIcon->cy;
1781 }
1782
1783 /* Calculate destination rectangle */
1784 RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight);
1785 IntLPtoDP(pdc, (LPPOINT)&rcDest, 2);
1786 RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
1787
1788 /* Prepare the underlying surface */
1789 DC_vPrepareDCsForBlit(pdc, &rcDest, NULL, NULL);
1790
1791 /* We now have our destination surface and rectangle */
1792 psurfDest = pdc->dclevel.pSurface;
1793
1794 if (psurfDest == NULL)
1795 {
1796 /* Empty DC */
1797 DC_vFinishBlit(pdc, NULL);
1798 DC_UnlockDc(pdc);
1799 SURFACE_ShareUnlockSurface(psurfMask);
1800 if (psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
1801 return FALSE;
1802 }
1803
1804 /* Set source rect */
1805 RECTL_vSetRect(&rcSrc, 0, 0, pIcon->cx, pIcon->cy);
1806
1807 /* Should we render off-screen? */
1808 bOffScreen = hbrFlickerFreeDraw &&
1809 (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH);
1810
1811 if (bOffScreen)
1812 {
1813 /* Yes: Allocate and paint the offscreen surface */
1814 EBRUSHOBJ eboFill;
1815 PBRUSH pbrush = BRUSH_ShareLockBrush(hbrFlickerFreeDraw);
1816
1817 TRACE("Performing off-screen rendering.\n");
1818
1819 if (!pbrush)
1820 {
1821 ERR("Failed to get brush object.\n");
1822 goto Cleanup;
1823 }
1824
1825#if 0 //We lock the hdc surface during the whole function it makes no sense to use an offscreen surface for "flicker free" drawing
1826 psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP,
1827 cxWidth, cyHeight, psurfDest->SurfObj.iBitmapFormat,
1828 0, 0, NULL);
1829 if (!psurfOffScreen)
1830 {
1831 ERR("Failed to allocate the off-screen surface.\n");
1832 BRUSH_ShareUnlockBrush(pbrush);
1833 goto Cleanup;
1834 }
1835
1836 /* Paint the brush */
1837 EBRUSHOBJ_vInit(&eboFill, pbrush, psurfOffScreen, 0x00FFFFFF, 0, NULL);
1838 RECTL_vSetRect(&rcDest, 0, 0, cxWidth, cyHeight);
1839
1840 Ret = IntEngBitBlt(&psurfOffScreen->SurfObj,
1841 NULL,
1842 NULL,
1843 NULL,
1844 NULL,
1845 &rcDest,
1846 NULL,
1847 NULL,
1848 &eboFill.BrushObject,
1849 &pbrush->ptOrigin,
1850 ROP4_PATCOPY);
1851
1852 /* Clean up everything */
1853 EBRUSHOBJ_vCleanup(&eboFill);
1854 BRUSH_ShareUnlockBrush(pbrush);
1855
1856 if (!Ret)
1857 {
1858 ERR("Failed to paint the off-screen surface.\n");
1859 goto Cleanup;
1860 }
1861
1862 /* We now have our destination surface */
1863 psurfDest = psurfOffScreen;
1864#else
1865 pdcClipObj = (CLIPOBJ *)&pdc->co;
1866 /* Paint the brush */
1867 EBRUSHOBJ_vInit(&eboFill, pbrush, psurfDest, 0x00FFFFFF, 0, NULL);
1868
1869 Ret = IntEngBitBlt(&psurfDest->SurfObj,
1870 NULL,
1871 NULL,
1872 pdcClipObj,
1873 NULL,
1874 &rcDest,
1875 NULL,
1876 NULL,
1877 &eboFill.BrushObject,
1878 &pbrush->ptOrigin,
1879 ROP4_PATCOPY);
1880
1881 /* Clean up everything */
1882 EBRUSHOBJ_vCleanup(&eboFill);
1883 BRUSH_ShareUnlockBrush(pbrush);
1884
1885 if (!Ret)
1886 {
1887 ERR("Failed to paint the off-screen surface.\n");
1888 goto Cleanup;
1889 }
1890#endif
1891 }
1892 else
1893 {
1894 /* We directly draw to the DC */
1895 TRACE("Performing on screen rendering.\n");
1896 pdcClipObj = (CLIPOBJ *)&pdc->co;
1897 // psurfOffScreen = NULL;
1898 }
1899
1900 /* Now do the rendering */
1901 if (hbmAlpha && ((diFlags & DI_NORMAL) == DI_NORMAL))
1902 {
1903 BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } };
1904 PSURFACE psurf = NULL;
1905
1906 psurf = SURFACE_ShareLockSurface(hbmAlpha);
1907 if (!psurf)
1908 {
1909 ERR("SURFACE_LockSurface failed!\n");
1910 goto NoAlpha;
1911 }
1912
1913 /* Initialize color translation object */
1914 EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xFFFFFFFF, 0xFFFFFFFF, 0);
1915
1916 /* Now do it */
1917 Ret = IntEngAlphaBlend(&psurfDest->SurfObj,
1918 &psurf->SurfObj,
1919 pdcClipObj,
1920 &exlo.xlo,
1921 &rcDest,
1922 &rcSrc,
1923 &blendobj);
1924
1925 EXLATEOBJ_vCleanup(&exlo);
1927 if (Ret) goto done;
1928 ERR("NtGdiAlphaBlend failed!\n");
1929 }
1930NoAlpha:
1931 if (diFlags & DI_MASK)
1932 {
1933 DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY;
1934
1935 EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);
1936
1937 Ret = IntEngStretchBlt(&psurfDest->SurfObj,
1938 &psurfMask->SurfObj,
1939 NULL,
1940 pdcClipObj,
1941 &exlo.xlo,
1942 NULL,
1943 &rcDest,
1944 &rcSrc,
1945 NULL,
1946 NULL,
1947 NULL,
1948 rop4);
1949
1950 EXLATEOBJ_vCleanup(&exlo);
1951
1952 if (!Ret)
1953 {
1954 ERR("Failed to mask the bitmap data.\n");
1955 goto Cleanup;
1956 }
1957 }
1958
1959 if (diFlags & DI_IMAGE)
1960 {
1961 if (psurfColor)
1962 {
1963 DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ;
1964
1965 EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
1966
1967 Ret = IntEngStretchBlt(&psurfDest->SurfObj,
1968 &psurfColor->SurfObj,
1969 NULL,
1970 pdcClipObj,
1971 &exlo.xlo,
1972 NULL,
1973 &rcDest,
1974 &rcSrc,
1975 NULL,
1976 NULL,
1977 NULL,
1978 rop4);
1979
1980 EXLATEOBJ_vCleanup(&exlo);
1981
1982 if (!Ret)
1983 {
1984 ERR("Failed to render the icon bitmap.\n");
1985 goto Cleanup;
1986 }
1987 }
1988 else
1989 {
1990 /* Mask bitmap holds the information in its bottom half */
1991 DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY;
1992 RECTL_vOffsetRect(&rcSrc, 0, pIcon->cy);
1993
1994 EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);
1995
1996 Ret = IntEngStretchBlt(&psurfDest->SurfObj,
1997 &psurfMask->SurfObj,
1998 NULL,
1999 pdcClipObj,
2000 &exlo.xlo,
2001 NULL,
2002 &rcDest,
2003 &rcSrc,
2004 NULL,
2005 NULL,
2006 NULL,
2007 rop4);
2008
2009 EXLATEOBJ_vCleanup(&exlo);
2010
2011 if (!Ret)
2012 {
2013 ERR("Failed to render the icon bitmap.\n");
2014 goto Cleanup;
2015 }
2016 }
2017 }
2018
2019done:
2020#if 0
2021 /* We're done. Was it a double buffered draw ? */
2022 if (bOffScreen)
2023 {
2024 /* Yes. Draw it back to our DC */
2025 POINTL ptSrc = {0, 0};
2026
2027 /* Calculate destination rectangle */
2028 RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight);
2029 IntLPtoDP(pdc, (LPPOINT)&rcDest, 2);
2030 RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
2031
2032 /* Get the clip object */
2033 pdcClipObj = pdc->rosdc.CombinedClip;
2034
2035 /* We now have our destination surface and rectangle */
2036 psurfDest = pdc->dclevel.pSurface;
2037
2038 /* Color translation */
2039 EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
2040
2041 /* Blt it! */
2042 Ret = IntEngBitBlt(&psurfDest->SurfObj,
2043 &psurfOffScreen->SurfObj,
2044 NULL,
2045 pdcClipObj,
2046 &exlo.xlo,
2047 &rcDest,
2048 &ptSrc,
2049 NULL,
2050 NULL,
2051 NULL,
2052 ROP4_SRCCOPY);
2053
2054 EXLATEOBJ_vCleanup(&exlo);
2055 }
2056#endif
2057Cleanup:
2058 if (pdc)
2059 {
2060 DC_vFinishBlit(pdc, NULL);
2061 DC_UnlockDc(pdc);
2062 }
2063
2064#if 0
2065 /* Delete off screen rendering surface */
2066 if (psurfOffScreen)
2067 GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject);
2068#endif
2069
2070 /* Unlock other surfaces */
2071 SURFACE_ShareUnlockSurface(psurfMask);
2072 if (psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
2073
2074 return Ret;
2075}
2076
2077/*
2078 * @implemented
2079 */
2080BOOL
2083 HDC hdc,
2084 int xLeft,
2085 int yTop,
2086 HICON hIcon,
2087 int cxWidth,
2088 int cyHeight,
2089 UINT istepIfAniCur,
2090 HBRUSH hbrFlickerFreeDraw,
2091 UINT diFlags,
2092 BOOL bMetaHDC, // When TRUE, GDI functions need to be handled in User32!
2093 PVOID pDIXData)
2094{
2095 PCURICON_OBJECT pIcon;
2096 BOOL Ret;
2097
2098 TRACE("Enter NtUserDrawIconEx\n");
2100
2101 if (!(pIcon = UserGetCurIconObject(hIcon)))
2102 {
2103 ERR("UserGetCurIconObject(0x%p) failed!\n", hIcon);
2104 UserLeave();
2105 return FALSE;
2106 }
2107
2108 Ret = UserDrawIconEx(hdc,
2109 xLeft,
2110 yTop,
2111 pIcon,
2112 cxWidth,
2113 cyHeight,
2114 istepIfAniCur,
2115 hbrFlickerFreeDraw,
2116 diFlags);
2117
2118 UserDereferenceObject(pIcon);
2119
2120 UserLeave();
2121 return Ret;
2122}
2123
2124/*
2125 * @unimplemented
2126 */
2127HCURSOR
2128NTAPI
2130 HCURSOR hCursor,
2131 DWORD istep,
2132 INT* rate_jiffies,
2133 DWORD* num_steps)
2134{
2135 PCURICON_OBJECT CurIcon;
2136 HCURSOR ret;
2137 INT jiffies = 0;
2138 DWORD steps = 1;
2140
2141 TRACE("Enter NtUserGetCursorFrameInfo\n");
2143
2144 if (!(CurIcon = UserGetCurIconObject(hCursor)))
2145 {
2146 UserLeave();
2147 return NULL;
2148 }
2149
2150 ret = UserHMGetHandle(CurIcon);
2151
2152 if (CurIcon->CURSORF_flags & CURSORF_ACON)
2153 {
2154 PACON AniCurIcon = (PACON)CurIcon;
2155 if (istep >= AniCurIcon->cicur)
2156 {
2157 UserDereferenceObject(CurIcon);
2158 UserLeave();
2159 return NULL;
2160 }
2161 jiffies = AniCurIcon->ajifRate[istep];
2162 steps = AniCurIcon->cicur;
2163 ret = UserHMGetHandle(AniCurIcon->aspcur[AniCurIcon->aicur[istep]]);
2164 }
2165
2166 _SEH2_TRY
2167 {
2168 ProbeForWrite(rate_jiffies, sizeof(INT), 1);
2169 ProbeForWrite(num_steps, sizeof(DWORD), 1);
2170 *rate_jiffies = jiffies;
2171 *num_steps = steps;
2172 }
2174 {
2176 }
2177 _SEH2_END
2178
2179 if (!NT_SUCCESS(Status))
2180 {
2181 WARN("Status: 0x%08lx\n", Status);
2183 ret = NULL;
2184 }
2185
2186 UserDereferenceObject(CurIcon);
2187 UserLeave();
2188
2189 TRACE("Leaving NtUserGetCursorFrameInfo, ret = 0x%p\n", ret);
2190
2191 return ret;
2192}
2193
2194/*
2195 * @implemented
2196 */
2197BOOL
2200 HCURSOR hcur,
2201 DWORD id)
2202{
2203 PCURICON_OBJECT pcur, pcurOrig = NULL;
2204 int i;
2205 PPROCESSINFO ppi;
2206 BOOL Ret = FALSE;
2208
2210 {
2211 goto Exit;
2212 }
2213
2214 if (hcur)
2215 {
2216 pcur = UserGetCurIconObject(hcur);
2217 if (!pcur)
2218 {
2220 goto Exit;
2221 }
2222
2224
2225 for (i = 0 ; i < 16; i++)
2226 {
2227 if (gasyscur[i].type == id)
2228 {
2229 pcurOrig = gasyscur[i].handle;
2230
2231 if (pcurOrig) break;
2232
2233 if (ppi->W32PF_flags & W32PF_CREATEDWINORDC)
2234 {
2235 gasyscur[i].handle = pcur;
2237 pcur->head.ppi = NULL;
2239 Ret = TRUE;
2240 }
2241 break;
2242 }
2243 }
2244 if (pcurOrig)
2245 {
2246 FIXME("Need to copy cursor data or do something! pcurOrig %p new pcur %p\n",pcurOrig,pcur);
2247 }
2248 }
2249Exit:
2250 UserLeave();
2251 return Ret;
2252}
2253
2254/* EOF */
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
HBITMAP FASTCALL BITMAP_CopyBitmap(HBITMAP hBitmap)
Definition: bitmaps.c:714
BOOL NTAPI GreSetBitmapOwner(_In_ HBITMAP hbmp, _In_ ULONG ulOwner)
Definition: bitmaps.c:17
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
#define leave
Definition: btrfs_drv.h:138
struct @1632 Msg[]
static BOOLEAN IntLPtoDP(DC *pdc, PPOINTL ppt, UINT count)
Definition: coord.h:182
struct tagACON * PACON
struct _CURICON_OBJECT * PCURICON_OBJECT
#define CURSORF_USER_MASK
Definition: cursoricon.h:6
VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdcDest, const RECT *rcDest, PDC pdcSrc, const RECT *rcSrc)
Definition: dclife.c:505
VOID FASTCALL DC_vFinishBlit(PDC pdc1, PDC pdc2)
Definition: dclife.c:614
FORCEINLINE VOID DC_UnlockDc(PDC pdc)
Definition: dc.h:238
FORCEINLINE PDC DC_LockDc(HDC hdc)
Definition: dc.h:220
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
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 APIENTRY
Definition: api.h:79
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
PSERVERINFO gpsi
Definition: imm.c:18
static void cleanup(void)
Definition: main.c:1335
static const WCHAR Cleanup[]
Definition: register.c:80
#define pt(x, y)
Definition: drawing.c:79
VOID NTAPI EBRUSHOBJ_vCleanup(EBRUSHOBJ *pebo)
Definition: engbrush.c:153
VOID NTAPI EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PSURFACE psurf, COLORREF crBackgroundClr, COLORREF crForegroundClr, PPALETTE ppalDC)
Definition: engbrush.c:52
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
#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
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define BRUSH_ShareLockBrush(hBrush)
Definition: brush.h:117
#define BRUSH_ShareUnlockBrush(pBrush)
Definition: brush.h:118
#define GDI_OBJECT_TYPE_BRUSH
Definition: gdi.h:52
#define GDI_HANDLE_GET_TYPE(h)
Definition: gdi.h:31
Status
Definition: gdiplustypes.h:25
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLbitfield flags
Definition: glext.h:7161
GLfloat param
Definition: glext.h:5796
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 CURSORF_LRSHARED
Definition: ntuser.h:1201
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
_Out_opt_ PICONINFO _Inout_opt_ PUNICODE_STRING _Inout_opt_ PUNICODE_STRING _Out_opt_ LPDWORD _In_ BOOL bInternal
Definition: ntuser.h:2298
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:805
#define CURSORF_CURRENT
Definition: ntuser.h:1207
_Out_opt_ PICONINFO IconInfo
Definition: ntuser.h:2294
#define CURSORF_LINKED
Definition: ntuser.h:1206
@ TYPE_CURSOR
Definition: ntuser.h:43
struct tagCURSORDATA CURSORDATA
#define CURSORF_GLOBAL
Definition: ntuser.h:1200
#define CURSORF_ACONFRAME
Definition: ntuser.h:1204
_Out_opt_ PICONINFO _Inout_opt_ PUNICODE_STRING _Inout_opt_ PUNICODE_STRING lpResName
Definition: ntuser.h:2296
_Out_opt_ PICONINFO _Inout_opt_ PUNICODE_STRING _Inout_opt_ PUNICODE_STRING _Out_opt_ LPDWORD pbpp
Definition: ntuser.h:2297
#define CURSORF_ACON
Definition: ntuser.h:1202
BOOL APIENTRY IntEngStretchBlt(SURFOBJ *DestObj, SURFOBJ *SourceObj, SURFOBJ *Mask, CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, COLORADJUSTMENT *pca, RECTL *DestRect, RECTL *SourceRect, POINTL *pMaskOrigin, BRUSHOBJ *Brush, POINTL *BrushOrigin, ULONG Mode)
#define MmCopyToCaller(x, y, z)
Definition: mmcopy.h:19
#define ASSERT(a)
Definition: mode.c:44
#define jiffies
Definition: module.h:1085
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define for
Definition: utility.h:88
#define AC_SRC_ALPHA
Definition: alphablend.c:9
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:92
static HICON
Definition: imagelist.c:84
unsigned short RTL_ATOM
Definition: atom.c:42
static DWORD DWORD DWORD DWORD * steps
Definition: cursoricon.c:1638
static DWORD DWORD istep
Definition: cursoricon.c:1638
#define min(a, b)
Definition: monoChain.cc:55
#define _Out_opt_
Definition: ms_sal.h:346
#define _Success_(expr)
Definition: ms_sal.h:259
#define _Inout_
Definition: ms_sal.h:378
#define _Inout_opt_
Definition: ms_sal.h:379
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
HICON hIcon
Definition: msconfig.c:44
VOID FASTCALL co_MsqInsertMouseMessage(MSG *Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook)
Definition: msgqueue.c:580
PCURICON_OBJECT FASTCALL UserSetCursor(PCURICON_OBJECT NewCursor, BOOL ForceChange)
Definition: msgqueue.c:93
unsigned int UINT
Definition: ndis.h:50
#define UserMode
Definition: asm.h:35
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 FASTCALL
Definition: nt_native.h:50
#define DWORD
Definition: nt_native.h:44
#define GDI_OBJ_HMGR_POWNED
Definition: ntgdihdl.h:117
#define GDI_OBJ_HMGR_PUBLIC
Definition: ntgdihdl.h:116
ULONG MmUserProbeAddress
Definition: init.c:50
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
BOOL FASTCALL CheckWinstaAttributeAccess(ACCESS_MASK DesiredAccess)
Definition: winsta.c:377
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 TAG_STRING
Definition: oslist.h:22
#define RT_ICON
Definition: pedump.c:365
long LONG
Definition: pedump.c:60
#define INT
Definition: polytest.cpp:20
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_VOLATILE
Definition: pseh2_64.h:163
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
static __inline NTSTATUS ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest, IN KPROCESSOR_MODE CurrentMode, IN const UNICODE_STRING *UnsafeSrc)
Definition: probe.h:142
static __inline VOID ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString, IN KPROCESSOR_MODE CurrentMode)
Definition: probe.h:239
#define STATUS_SUCCESS
Definition: shellext.h:65
static void Exit(void)
Definition: sock.c:1330
#define TRACE(s)
Definition: solgame.cpp:4
#define __kernel_entry
Definition: specstrings.h:355
Definition: polytest.cpp:41
CLIPOBJ CombinedClip
Definition: polytest.cpp:42
Implementation of the Explorer desktop window.
Definition: desktop.h:52
long bottom
Definition: polytest.cpp:53
long right
Definition: polytest.cpp:53
long top
Definition: polytest.cpp:53
long left
Definition: polytest.cpp:53
PCURICON_OBJECT handle
Definition: cursoricon.h:99
Definition: types.h:101
struct _CURICON_OBJECT * pcurNext
Definition: cursoricon.h:12
HBITMAP hbmColor
Definition: cursoricon.h:20
HBITMAP hbmMask
Definition: cursoricon.h:19
UNICODE_STRING strName
Definition: cursoricon.h:13
USHORT atomModName
Definition: cursoricon.h:14
PROCMARKHEAD head
Definition: cursoricon.h:11
ULONG CURSORF_flags
Definition: cursoricon.h:16
HBITMAP hbmAlpha
Definition: cursoricon.h:21
BRUSHOBJ BrushObject
Definition: brush.h:71
XLATEOBJ xlo
Definition: xlateobj.h:21
DWORD yHotspot
Definition: winuser.h:3125
BOOL fIcon
Definition: winuser.h:3123
DWORD xHotspot
Definition: winuser.h:3124
HBITMAP hbmColor
Definition: winuser.h:3127
HBITMAP hbmMask
Definition: winuser.h:3126
struct _CURICON_OBJECT * pCursorCache
Definition: win32.h:272
struct _PROCESSINFO * ppi
Definition: ntuser.h:227
LONG cy
Definition: kdterminal.h:28
SURFOBJ SurfObj
Definition: surface.h:8
struct _PALETTE *const ppal
Definition: surface.h:11
SIZEL sizlBitmap
Definition: winddi.h:1209
ULONG iBitmapFormat
Definition: winddi.h:1215
PCURICON_OBJECT CurrentCursorObject
Definition: cursoricon.h:74
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: ntuser.h:694
Definition: ps.c:97
UINT cpcur
Definition: cursoricon.h:37
UINT cicur
Definition: cursoricon.h:38
DWORD * aicur
Definition: cursoricon.h:40
PCURICON_OBJECT * aspcur
Definition: cursoricon.h:39
INT * ajifRate
Definition: cursoricon.h:41
DWORD * aicur
Definition: ntuser.h:1193
INT * ajifRate
Definition: ntuser.h:1194
ULONG CURSORF_flags
Definition: ntuser.h:1179
UINT cpcur
Definition: ntuser.h:1190
UINT cicur
Definition: ntuser.h:1191
struct tagCURSORDATA * aspcur
Definition: ntuser.h:1192
DWORD flags
Definition: winuser.h:3720
DWORD cbSize
Definition: winuser.h:3719
HCURSOR hCursor
Definition: winuser.h:3721
POINT ptScreenPos
Definition: winuser.h:3722
#define __WARNING_READ_OVERRUN
Definition: suppress.h:142
#define _PRAGMA_WARNING_SUPPRESS(x)
Definition: suppress.h:28
#define max(a, b)
Definition: svc.c:63
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
#define NTAPI
Definition: typedefs.h:36
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
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
int ret
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
#define FORCEINLINE
Definition: wdftypes.h:67
#define W32PF_CREATEDWINORDC
Definition: win32.h:34
#define ROP4_SRCCOPY
Definition: dib.h:13
#define ROP4_PATCOPY
Definition: dib.h:15
#define ROP4_SRCINVERT
Definition: dib.h:9
#define ROP4_SRCAND
Definition: dib.h:10
BOOL APIENTRY IntEngAlphaBlend(_Inout_ SURFOBJ *psoDest, _In_ SURFOBJ *psoSource, _In_opt_ CLIPOBJ *pco, _In_opt_ XLATEOBJ *pxlo, _In_ RECTL *prclDest, _In_ RECTL *prclSrc, _In_ BLENDOBJ *pBlendObj)
Definition: alphablend.c:197
BOOL APIENTRY IntEngBitBlt(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush, ROP4 Rop4)
Definition: bitblt.c:656
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:31
PSURFACE NTAPI SURFACE_AllocSurface(_In_ USHORT iType, _In_ ULONG cx, _In_ ULONG cy, _In_ ULONG iFormat, _In_ ULONG fjBitmap, _In_opt_ ULONG cjWidth, _In_opt_ ULONG cjBufSize, _In_opt_ PVOID pvBits)
Definition: surface.c:116
#define SURFACE_ShareUnlockSurface(pBMObj)
Definition: surface.h:102
#define SURFACE_ShareLockSurface(hBMObj)
Definition: surface.h:91
BOOL NTAPI GreSetObjectOwner(HGDIOBJ hobj, ULONG ulOwner)
Definition: gdiobj.c:1255
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
VOID NTAPI GDIOBJ_vDeleteObject(POBJ pobj)
Definition: gdiobj.c:1111
FORCEINLINE VOID RECTL_vSetRect(_Out_ RECTL *prcl, _In_ LONG left, _In_ LONG top, _In_ LONG right, _In_ LONG bottom)
Definition: rect.h:5
FORCEINLINE VOID RECTL_vOffsetRect(_Inout_ RECTL *prcl, _In_ INT cx, _In_ INT cy)
Definition: rect.h:31
_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
BOOL APIENTRY NtUserGetClipCursor(RECTL *lpRect)
Definition: cursoricon.c:994
VOID FreeCurIconObject(_In_ PVOID Object)
Definition: cursoricon.c:334
static VOID IntInsertCursorIntoList(_Inout_ PCURICON_OBJECT pcur)
Definition: cursoricon.c:80
BOOL APIENTRY NtUserDrawIconEx(HDC hdc, int xLeft, int yTop, HICON hIcon, int cxWidth, int cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags, BOOL bMetaHDC, PVOID pDIXData)
Definition: cursoricon.c:2082
HANDLE IntCreateCurIconHandle(BOOLEAN Animated)
Definition: cursoricon.c:283
BOOL APIENTRY UserSetCursorIconData(_In_ HCURSOR hcursor, _In_opt_ PUNICODE_STRING pustrModule, _In_opt_ PUNICODE_STRING pustrRsrc, _In_ PCURSORDATA pcursordata)
Definition: cursoricon.c:1417
static BOOL IntSetCursorData(_Inout_ PCURICON_OBJECT pcur, _In_opt_ PUNICODE_STRING pustrName, _In_ ATOM atomModName, _In_ const CURSORDATA *pcursordata)
Definition: cursoricon.c:1128
SYSTEMCURICO gasyscur[]
Definition: cursoricon.c:32
BOOL APIENTRY NtUserGetIconSize(HANDLE hCurIcon, UINT istepIfAniCur, PLONG plcx, PLONG plcy)
Definition: cursoricon.c:588
HICON NTAPI NtUserFindExistingCursorIcon(_In_ PUNICODE_STRING pustrModule, _In_ PUNICODE_STRING pustrRsrc, _In_ FINDEXISTINGCURICONPARAM *param)
Definition: cursoricon.c:859
BOOL APIENTRY NtUserSetCursorContents(HANDLE hCurIcon, PICONINFO UnsafeIconInfo)
Definition: cursoricon.c:1117
BOOL InitCursorImpl(VOID)
Definition: cursoricon.c:64
BOOL APIENTRY NtUserClipCursor(RECTL *prcl)
Definition: cursoricon.c:751
BOOL UserSetCursorPos(INT x, INT y, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook)
Definition: cursoricon.c:238
BOOL APIENTRY NtUserDestroyCursor(_In_ HANDLE hCurIcon, _In_ BOOL bForce)
Definition: cursoricon.c:791
__kernel_entry BOOL APIENTRY NtUserSetCursorIconData(_In_ HCURSOR hcursor, _In_opt_ PUNICODE_STRING pustrModule, _In_opt_ PUNICODE_STRING pustrRsrc, _In_ const CURSORDATA *pCursorData)
Definition: cursoricon.c:1508
VOID IntLoadSystenIcons(HICON hcur, DWORD id)
Definition: cursoricon.c:137
PCURICON_OBJECT IntSystemSetCursor(PCURICON_OBJECT pcurNew)
Definition: cursoricon.c:230
PSYSTEM_CURSORINFO IntGetSysCursorInfo(VOID)
Definition: cursoricon.c:187
BOOL APIENTRY NtUserSetSystemCursor(HCURSOR hcur, DWORD id)
Definition: cursoricon.c:2199
BOOL APIENTRY NtUserGetCursorInfo(PCURSORINFO pci)
Definition: cursoricon.c:647
FORCEINLINE BOOL is_icon(PCURICON_OBJECT object)
Definition: cursoricon.c:194
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
Definition: cursoricon.c:200
BOOL APIENTRY UserClipCursor(RECTL *prcl)
Definition: cursoricon.c:698
BOOL UserDrawIconEx(HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth, INT cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags)
Definition: cursoricon.c:1687
HCURSOR APIENTRY NtUserSetCursor(HCURSOR hCursor)
Definition: cursoricon.c:1047
static BOOL IntSetAconData(_Inout_ PACON pacon, _In_opt_ PUNICODE_STRING pustrName, _In_ ATOM atomModName, _In_ const CURSORDATA *pcursordata)
Definition: cursoricon.c:1236
VOID FASTCALL IntCleanupCurIconCache(PPROCESSINFO Win32Process)
Definition: cursoricon.c:393
SYSTEM_CURSORINFO gSysCursorInfo
Definition: cursoricon.c:25
PCURICON_OBJECT gcurFirst
Definition: cursoricon.c:27
HCURSOR NTAPI NtUserGetCursorFrameInfo(HCURSOR hCursor, DWORD istep, INT *rate_jiffies, DWORD *num_steps)
Definition: cursoricon.c:2129
SYSTEMCURICO gasysico[]
Definition: cursoricon.c:54
BOOLEAN IntDestroyCurIconObject(_In_ PVOID Object)
Definition: cursoricon.c:315
static VOID IntRemoveCursorFromList(_Inout_ PCURICON_OBJECT pcur)
Definition: cursoricon.c:101
PWND FASTCALL UserGetDesktopWindow(VOID)
Definition: desktop.c:1386
WORD FASTCALL UserGetMouseButtonsState(VOID)
Definition: mouse.c:22
LONG NTAPI UserGetSystemMetrics(ULONG Index)
Definition: metric.c:213
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:644
PVOID FASTCALL UserReferenceObjectByHandle(HANDLE handle, HANDLE_TYPE type)
Definition: object.c:741
BOOL FASTCALL UserDeleteObject(HANDLE h, HANDLE_TYPE type)
Definition: object.c:717
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13
BOOL FASTCALL UserObjectInDestroy(HANDLE h)
Definition: object.c:703
void FreeProcMarkObject(_In_ PVOID Object)
Definition: object.c:175
PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, PDESKTOP pDesktop, PTHREADINFO pti, HANDLE *h, HANDLE_TYPE type, ULONG size)
Definition: object.c:568
PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:481
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:731
PRTL_ATOM_TABLE gAtomTable
Definition: session.c:13
#define USERTAG_CURSOR
Definition: tags.h:209
#define STYPE_BITMAP
Definition: winddi.h:1175
_In_opt_ SURFOBJ _In_opt_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ _In_ RECTL _In_opt_ POINTL _In_opt_ POINTL _In_opt_ BRUSHOBJ _In_opt_ POINTL _In_ ROP4 rop4
Definition: winddi.h:3442
_In_ ULONG _In_ CLIPOBJ _In_ RECTL * prcl
Definition: winddi.h:3531
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:22
_In_ ULONG cjSize
Definition: winddi.h:3634
int * PINT
Definition: windef.h:177
HICON HCURSOR
Definition: windef.h:299
#define ERROR_INVALID_CURSOR_HANDLE
Definition: winerror.h:883
#define AC_SRC_OVER
Definition: wingdi.h:1369
#define DI_NORMAL
Definition: wingdi.h:72
#define DI_IMAGE
Definition: wingdi.h:70
#define DI_MASK
Definition: wingdi.h:71
#define DI_DEFAULTSIZE
Definition: wingdi.h:69
#define MAKELPARAM(l, h)
Definition: winuser.h:4008
#define SM_CYSCREEN
Definition: winuser.h:960
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
#define CURSOR_SHOWING
Definition: winuser.h:2658
#define WM_MOUSEMOVE
Definition: winuser.h:1775
#define WINSTA_READATTRIBUTES
Definition: winuser.h:414
#define SM_CYICON
Definition: winuser.h:973
#define SM_CXSCREEN
Definition: winuser.h:959
#define WINSTA_WRITEATTRIBUTES
Definition: winuser.h:416
#define SM_CYCURSOR
Definition: winuser.h:975
#define SM_CXICON
Definition: winuser.h:972
#define MAKEINTRESOURCE
Definition: winuser.h:591
#define SM_CXCURSOR
Definition: winuser.h:974
#define NT_ASSERT
Definition: rtlfuncs.h:3310
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3287
VOID NTAPI EXLATEOBJ_vInitialize(_Out_ PEXLATEOBJ pexlo, _In_opt_ PALETTE *ppalSrc, _In_opt_ PALETTE *ppalDst, _In_ COLORREF crSrcBackColor, _In_ COLORREF crDstBackColor, _In_ COLORREF crDstForeColor)
Definition: xlateobj.c:358
VOID NTAPI EXLATEOBJ_vCleanup(_Inout_ PEXLATEOBJ pexlo)
Definition: xlateobj.c:649
VOID NTAPI EXLATEOBJ_vInitSrcMonoXlate(PEXLATEOBJ pexlo, PPALETTE ppalDst, COLORREF crBackgroundClr, COLORREF crForegroundClr)
Definition: xlateobj.c:632
__wchar_t WCHAR
Definition: xmlstorage.h:180