2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * We handle two types of cursors/icons:
23 * Loaded without LR_SHARED flag
24 * Private to a process
25 * Can be deleted by calling NtDestroyCursorIcon()
26 * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc set to NULL
28 * Loaded with LR_SHARED flag
29 * Possibly shared by multiple processes
30 * Immune to NtDestroyCursorIcon()
31 * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc are valid
32 * There's a M:N relationship between processes and (shared) cursor/icons.
33 * A process can have multiple cursor/icons and a cursor/icon can be used
34 * by multiple processes. To keep track of this we keep a list of all
35 * cursor/icons (CurIconList) and per cursor/icon we keep a list of
36 * CURICON_PROCESS structs starting at CurIcon->ProcessList.
44 static PAGED_LOOKASIDE_LIST gProcessLookasideList
;
45 static LIST_ENTRY gCurIconList
;
47 SYSTEM_CURSORINFO gSysCursorInfo
;
52 ExInitializePagedLookasideList(&gProcessLookasideList
,
56 sizeof(CURICON_PROCESS
),
59 InitializeListHead(&gCurIconList
);
61 gSysCursorInfo
.Enabled
= FALSE
;
62 gSysCursorInfo
.ButtonsDown
= 0;
63 gSysCursorInfo
.bClipped
= FALSE
;
64 gSysCursorInfo
.LastBtnDown
= 0;
65 gSysCursorInfo
.CurrentCursorObject
= NULL
;
66 gSysCursorInfo
.ShowingCursor
= 0;
67 gSysCursorInfo
.ClickLockActive
= FALSE
;
68 gSysCursorInfo
.ClickLockTime
= 0;
76 return &gSysCursorInfo
;
79 /* This function creates a reference for the object! */
80 PCURICON_OBJECT FASTCALL
UserGetCurIconObject(HCURSOR hCurIcon
)
82 PCURICON_OBJECT CurIcon
;
86 EngSetLastError(ERROR_INVALID_CURSOR_HANDLE
);
90 CurIcon
= (PCURICON_OBJECT
)UserReferenceObjectByHandle(hCurIcon
, otCursorIcon
);
93 /* we never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */
94 EngSetLastError(ERROR_INVALID_CURSOR_HANDLE
);
98 ASSERT(CurIcon
->head
.cLockObj
>= 1);
105 PCURICON_OBJECT NewCursor
,
108 PSYSTEM_CURSORINFO CurInfo
;
109 PCURICON_OBJECT OldCursor
;
112 CurInfo
= IntGetSysCursorInfo();
114 OldCursor
= CurInfo
->CurrentCursorObject
;
116 /* Is the new cursor the same as the old cursor? */
117 if (OldCursor
== NewCursor
)
119 /* Nothing to to do in this case */
123 /* Get the screen DC */
124 if(!(hdcScreen
= IntGetScreenDC()))
129 /* Do we have a new cursor? */
132 CurInfo
->ShowingCursor
= 1;
133 CurInfo
->CurrentCursorObject
= NewCursor
;
135 /* Call GDI to set the new screen cursor */
136 GreSetPointerShape(hdcScreen
,
137 NewCursor
->IconInfo
.hbmMask
,
138 NewCursor
->IconInfo
.hbmColor
,
139 NewCursor
->IconInfo
.xHotspot
,
140 NewCursor
->IconInfo
.yHotspot
,
146 /* Check if were diplaying a cursor */
147 if (OldCursor
&& CurInfo
->ShowingCursor
)
149 /* Remove the cursor */
150 GreMovePointer(hdcScreen
, -1, -1);
151 DPRINT("Removing pointer!\n");
154 CurInfo
->CurrentCursorObject
= NULL
;
155 CurInfo
->ShowingCursor
= 0;
158 /* Return the old cursor */
162 BOOL
UserSetCursorPos( INT x
, INT y
, DWORD flags
, ULONG_PTR dwExtraInfo
, BOOL Hook
)
165 PSYSTEM_CURSORINFO CurInfo
;
171 if(!(hDC
= IntGetScreenDC()))
176 if(!(DesktopWindow
= UserGetDesktopWindow()))
181 CurInfo
= IntGetSysCursorInfo();
183 /* Clip cursor position */
184 if (!CurInfo
->bClipped
)
185 rcClip
= DesktopWindow
->rcClient
;
187 rcClip
= CurInfo
->rcClip
;
189 if(x
>= rcClip
.right
) x
= rcClip
.right
- 1;
190 if(x
< rcClip
.left
) x
= rcClip
.left
;
191 if(y
>= rcClip
.bottom
) y
= rcClip
.bottom
- 1;
192 if(y
< rcClip
.top
) y
= rcClip
.top
;
197 /* 3. Generate a mouse move message, this sets the htEx and Track Window too. */
198 Msg
.message
= WM_MOUSEMOVE
;
199 Msg
.wParam
= CurInfo
->ButtonsDown
;
200 Msg
.lParam
= MAKELPARAM(x
, y
);
202 co_MsqInsertMouseMessage(&Msg
, flags
, dwExtraInfo
, Hook
);
204 /* 1. Store the new cursor position */
207 /* 2. Move the mouse pointer */
208 GreMovePointer(hDC
, x
, y
);
213 /* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
214 * User32 macro NtUserShowCursor */
215 int UserShowCursor(BOOL bShow
)
217 PSYSTEM_CURSORINFO CurInfo
= IntGetSysCursorInfo();
220 if (!(hdcScreen
= IntGetScreenDC()))
222 return 0; /* No mouse */
227 /* Check if were diplaying a cursor */
228 if (CurInfo
->ShowingCursor
== 1)
230 /* Remove the pointer */
231 GreMovePointer(hdcScreen
, -1, -1);
232 DPRINT("Removing pointer!\n");
234 CurInfo
->ShowingCursor
--;
238 if (CurInfo
->ShowingCursor
== 0)
241 GreMovePointer(hdcScreen
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
243 CurInfo
->ShowingCursor
++;
246 return CurInfo
->ShowingCursor
;
250 * We have to register that this object is in use by the current
251 * process. The only way to do that seems to be to walk the list
252 * of cursor/icon objects starting at W32Process->CursorIconListHead.
253 * If the object is already present in the list, we don't have to do
254 * anything, if it's not present we add it and inc the ProcessCount
255 * in the object. Having to walk the list kind of sucks, but that's
258 static BOOLEAN FASTCALL
259 ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon
)
261 PPROCESSINFO Win32Process
;
262 PCURICON_PROCESS Current
;
264 Win32Process
= PsGetCurrentProcessWin32Process();
266 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
268 if (Current
->Process
== Win32Process
)
270 /* Already registered for this process */
275 /* Not registered yet */
276 Current
= ExAllocateFromPagedLookasideList(&gProcessLookasideList
);
281 InsertHeadList(&CurIcon
->ProcessList
, &Current
->ListEntry
);
282 Current
->Process
= Win32Process
;
287 PCURICON_OBJECT FASTCALL
288 IntFindExistingCurIconObject(HMODULE hModule
,
289 HRSRC hRsrc
, LONG cx
, LONG cy
)
291 PCURICON_OBJECT CurIcon
;
293 LIST_FOR_EACH(CurIcon
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
296 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
297 // UserReferenceObject( CurIcon);
299 if ((CurIcon
->hModule
== hModule
) && (CurIcon
->hRsrc
== hRsrc
))
301 if (cx
&& ((cx
!= CurIcon
->Size
.cx
) || (cy
!= CurIcon
->Size
.cy
)))
303 // UserDereferenceObject(CurIcon);
306 if (! ReferenceCurIconByProcess(CurIcon
))
314 // UserDereferenceObject(CurIcon);
322 IntCreateCurIconHandle()
324 PCURICON_OBJECT CurIcon
;
327 CurIcon
= UserCreateObject(gHandleTable
, NULL
, &hCurIcon
, otCursorIcon
, sizeof(CURICON_OBJECT
));
331 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
335 CurIcon
->Self
= hCurIcon
;
336 InitializeListHead(&CurIcon
->ProcessList
);
338 if (! ReferenceCurIconByProcess(CurIcon
))
340 DPRINT1("Failed to add process\n");
341 UserDeleteObject(hCurIcon
, otCursorIcon
);
342 UserDereferenceObject(CurIcon
);
346 InsertHeadList(&gCurIconList
, &CurIcon
->ListEntry
);
352 IntDestroyCurIconObject(PCURICON_OBJECT CurIcon
, BOOL ProcessCleanup
)
354 PSYSTEM_CURSORINFO CurInfo
;
355 HBITMAP bmpMask
, bmpColor
;
357 PCURICON_PROCESS Current
= NULL
;
358 PPROCESSINFO W32Process
= PsGetCurrentProcessWin32Process();
360 /* Private objects can only be destroyed by their own process */
361 if (NULL
== CurIcon
->hModule
)
363 ASSERT(CurIcon
->ProcessList
.Flink
->Flink
== &CurIcon
->ProcessList
);
364 Current
= CONTAINING_RECORD(CurIcon
->ProcessList
.Flink
, CURICON_PROCESS
, ListEntry
);
365 if (Current
->Process
!= W32Process
)
367 DPRINT1("Trying to destroy private icon/cursor of another process\n");
371 else if (! ProcessCleanup
)
373 DPRINT("Trying to destroy shared icon/cursor\n");
377 /* Now find this process in the list of processes referencing this object and
378 remove it from that list */
379 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
381 if (Current
->Process
== W32Process
)
383 RemoveEntryList(&Current
->ListEntry
);
388 ExFreeToPagedLookasideList(&gProcessLookasideList
, Current
);
390 /* If there are still processes referencing this object we can't destroy it yet */
391 if (! IsListEmpty(&CurIcon
->ProcessList
))
397 if (! ProcessCleanup
)
399 RemoveEntryList(&CurIcon
->ListEntry
);
402 CurInfo
= IntGetSysCursorInfo();
404 if (CurInfo
->CurrentCursorObject
== CurIcon
)
406 /* Hide the cursor if we're destroying the current cursor */
407 UserSetCursor(NULL
, TRUE
);
410 bmpMask
= CurIcon
->IconInfo
.hbmMask
;
411 bmpColor
= CurIcon
->IconInfo
.hbmColor
;
416 GreSetObjectOwner(bmpMask
, GDI_OBJ_HMGR_POWNED
);
417 GreDeleteObject(bmpMask
);
418 CurIcon
->IconInfo
.hbmMask
= NULL
;
422 GreSetObjectOwner(bmpColor
, GDI_OBJ_HMGR_POWNED
);
423 GreDeleteObject(bmpColor
);
424 CurIcon
->IconInfo
.hbmColor
= NULL
;
427 /* We were given a pointer, no need to keep the reference anylonger! */
428 UserDereferenceObject(CurIcon
);
429 Ret
= UserDeleteObject(CurIcon
->Self
, otCursorIcon
);
435 IntCleanupCurIcons(struct _EPROCESS
*Process
, PPROCESSINFO Win32Process
)
437 PCURICON_OBJECT CurIcon
, tmp
;
438 PCURICON_PROCESS ProcessData
;
440 LIST_FOR_EACH_SAFE(CurIcon
, tmp
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
442 UserReferenceObject(CurIcon
);
443 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon)))
445 LIST_FOR_EACH(ProcessData
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
447 if (Win32Process
== ProcessData
->Process
)
449 RemoveEntryList(&CurIcon
->ListEntry
);
450 IntDestroyCurIconObject(CurIcon
, TRUE
);
456 // UserDereferenceObject(Object);
461 UserDereferenceObject(CurIcon
);
476 PUNICODE_STRING lpInstName
, // optional
477 PUNICODE_STRING lpResName
, // optional
478 LPDWORD pbpp
, // optional
482 PCURICON_OBJECT CurIcon
;
483 NTSTATUS Status
= STATUS_SUCCESS
;
487 DPRINT("Enter NtUserGetIconInfo\n");
488 UserEnterExclusive();
492 EngSetLastError(ERROR_INVALID_PARAMETER
);
496 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
501 RtlCopyMemory(&ii
, &CurIcon
->IconInfo
, sizeof(ICONINFO
));
504 ii
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
505 ii
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
511 psurfBmp
= SURFACE_ShareLockSurface(CurIcon
->IconInfo
.hbmColor
);
514 colorBpp
= BitsPerFormat(psurfBmp
->SurfObj
.iBitmapFormat
);
515 SURFACE_ShareUnlockSurface(psurfBmp
);
522 ProbeForWrite(IconInfo
, sizeof(ICONINFO
), 1);
523 RtlCopyMemory(IconInfo
, &ii
, sizeof(ICONINFO
));
527 ProbeForWrite(pbpp
, sizeof(DWORD
), 1);
531 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
533 Status
= _SEH2_GetExceptionCode();
537 if (NT_SUCCESS(Status
))
540 SetLastNtError(Status
);
542 UserDereferenceObject(CurIcon
);
545 DPRINT("Leave NtUserGetIconInfo, ret=%i\n", Ret
);
560 PLONG plcx
, // &size.cx
561 PLONG plcy
) // &size.cy
563 PCURICON_OBJECT CurIcon
;
564 NTSTATUS Status
= STATUS_SUCCESS
;
567 DPRINT("Enter NtUserGetIconSize\n");
568 UserEnterExclusive();
570 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
577 ProbeForWrite(plcx
, sizeof(LONG
), 1);
578 RtlCopyMemory(plcx
, &CurIcon
->Size
.cx
, sizeof(LONG
));
579 ProbeForWrite(plcy
, sizeof(LONG
), 1);
580 RtlCopyMemory(plcy
, &CurIcon
->Size
.cy
, sizeof(LONG
));
582 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
584 Status
= _SEH2_GetExceptionCode();
588 if (NT_SUCCESS(Status
))
591 SetLastNtError(Status
); // maybe not, test this
593 UserDereferenceObject(CurIcon
);
596 DPRINT("Leave NtUserGetIconSize, ret=%i\n", bRet
);
611 PSYSTEM_CURSORINFO CurInfo
;
612 NTSTATUS Status
= STATUS_SUCCESS
;
613 PCURICON_OBJECT CurIcon
;
615 DECLARE_RETURN(BOOL
);
617 DPRINT("Enter NtUserGetCursorInfo\n");
618 UserEnterExclusive();
620 CurInfo
= IntGetSysCursorInfo();
621 CurIcon
= (PCURICON_OBJECT
)CurInfo
->CurrentCursorObject
;
623 SafeCi
.cbSize
= sizeof(CURSORINFO
);
624 SafeCi
.flags
= ((CurInfo
->ShowingCursor
&& CurIcon
) ? CURSOR_SHOWING
: 0);
625 SafeCi
.hCursor
= (CurIcon
? (HCURSOR
)CurIcon
->Self
: (HCURSOR
)0);
627 SafeCi
.ptScreenPos
= gpsi
->ptCursor
;
631 if (pci
->cbSize
== sizeof(CURSORINFO
))
633 ProbeForWrite(pci
, sizeof(CURSORINFO
), 1);
634 RtlCopyMemory(pci
, &SafeCi
, sizeof(CURSORINFO
));
639 EngSetLastError(ERROR_INVALID_PARAMETER
);
642 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
644 Status
= _SEH2_GetExceptionCode();
647 if (!NT_SUCCESS(Status
))
649 SetLastNtError(Status
);
655 DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_
);
665 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
666 PSYSTEM_CURSORINFO CurInfo
;
667 PWND DesktopWindow
= NULL
;
669 CurInfo
= IntGetSysCursorInfo();
671 DesktopWindow
= UserGetDesktopWindow();
674 (prcl
->right
> prcl
->left
) &&
675 (prcl
->bottom
> prcl
->top
) &&
676 DesktopWindow
!= NULL
)
678 CurInfo
->bClipped
= TRUE
;
679 RECTL_bIntersectRect(&CurInfo
->rcClip
, prcl
, &DesktopWindow
->rcWindow
);
680 UserSetCursorPos(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
, 0, 0, FALSE
);
684 CurInfo
->bClipped
= FALSE
;
705 /* Probe and copy rect */
706 ProbeForRead(prcl
, sizeof(RECTL
), 1);
709 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
711 EngSetLastError(ERROR_INVALID_PARAMETER
);
712 _SEH2_YIELD(return FALSE
;)
719 UserEnterExclusive();
721 /* Call the internal function */
722 bResult
= UserClipCursor(prcl
);
739 PCURICON_OBJECT CurIcon
;
741 DECLARE_RETURN(BOOL
);
743 DPRINT("Enter NtUserDestroyCursorIcon\n");
744 UserEnterExclusive();
746 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
751 ret
= IntDestroyCurIconObject(CurIcon
, FALSE
);
752 /* Note: IntDestroyCurIconObject will remove our reference for us! */
757 DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_
);
768 NtUserFindExistingCursorIcon(
774 PCURICON_OBJECT CurIcon
;
775 HANDLE Ret
= (HANDLE
)0;
776 DECLARE_RETURN(HICON
);
778 DPRINT("Enter NtUserFindExistingCursorIcon\n");
779 UserEnterExclusive();
781 CurIcon
= IntFindExistingCurIconObject(hModule
, hRsrc
, cx
, cy
);
786 // IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
790 EngSetLastError(ERROR_INVALID_CURSOR_HANDLE
);
794 DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_
);
808 /* FIXME - check if process has WINSTA_READATTRIBUTES */
809 PSYSTEM_CURSORINFO CurInfo
;
812 DECLARE_RETURN(BOOL
);
814 DPRINT("Enter NtUserGetClipCursor\n");
815 UserEnterExclusive();
820 CurInfo
= IntGetSysCursorInfo();
821 if (CurInfo
->bClipped
)
823 Rect
= CurInfo
->rcClip
;
829 Rect
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
830 Rect
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
833 Status
= MmCopyToCaller(lpRect
, &Rect
, sizeof(RECT
));
834 if (!NT_SUCCESS(Status
))
836 SetLastNtError(Status
);
843 DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_
);
857 PCURICON_OBJECT pcurOld
, pcurNew
;
858 HCURSOR hOldCursor
= NULL
;
860 DPRINT("Enter NtUserSetCursor\n");
861 UserEnterExclusive();
865 pcurNew
= UserGetCurIconObject(hCursor
);
868 EngSetLastError(ERROR_INVALID_CURSOR_HANDLE
);
877 pcurOld
= UserSetCursor(pcurNew
, FALSE
);
880 hOldCursor
= (HCURSOR
)pcurOld
->Self
;
881 UserDereferenceObject(pcurOld
);
895 NtUserSetCursorContents(
897 PICONINFO UnsafeIconInfo
)
899 PCURICON_OBJECT CurIcon
;
904 DECLARE_RETURN(BOOL
);
906 DPRINT("Enter NtUserSetCursorContents\n");
907 UserEnterExclusive();
909 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
915 Status
= MmCopyFromCaller(&IconInfo
, UnsafeIconInfo
, sizeof(ICONINFO
));
916 if (!NT_SUCCESS(Status
))
918 SetLastNtError(Status
);
922 /* Delete old bitmaps */
923 if ((CurIcon
->IconInfo
.hbmColor
)
924 && (CurIcon
->IconInfo
.hbmColor
!= IconInfo
.hbmColor
))
926 GreDeleteObject(CurIcon
->IconInfo
.hbmColor
);
928 if ((CurIcon
->IconInfo
.hbmMask
)
929 && CurIcon
->IconInfo
.hbmMask
!= IconInfo
.hbmMask
)
931 GreDeleteObject(CurIcon
->IconInfo
.hbmMask
);
934 /* Copy new IconInfo field */
935 CurIcon
->IconInfo
= IconInfo
;
937 if (CurIcon
->IconInfo
.hbmColor
)
939 psurfBmp
= SURFACE_ShareLockSurface(CurIcon
->IconInfo
.hbmColor
);
943 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
944 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
945 SURFACE_ShareUnlockSurface(psurfBmp
);
946 GreSetObjectOwner(CurIcon
->IconInfo
.hbmColor
, GDI_OBJ_HMGR_PUBLIC
);
950 psurfBmp
= SURFACE_ShareLockSurface(CurIcon
->IconInfo
.hbmMask
);
954 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
955 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
/ 2;
957 SURFACE_ShareUnlockSurface(psurfBmp
);
959 GreSetObjectOwner(CurIcon
->IconInfo
.hbmMask
, GDI_OBJ_HMGR_PUBLIC
);
967 UserDereferenceObject(CurIcon
);
972 DPRINT("Leave NtUserSetCursorContents, ret=%i\n",_ret_
);
984 NtUserSetCursorIconData(
987 PUNICODE_STRING pstrResName
,
990 PCURICON_OBJECT CurIcon
;
992 NTSTATUS Status
= STATUS_SUCCESS
;
994 DECLARE_RETURN(BOOL
);
996 DPRINT("Enter NtUserSetCursorIconData\n");
997 UserEnterExclusive();
999 if (!(CurIcon
= UserGetCurIconObject(Handle
)))
1004 CurIcon
->hModule
= hModule
;
1005 CurIcon
->hRsrc
= NULL
; //hRsrc;
1006 CurIcon
->hGroupRsrc
= NULL
; //hGroupRsrc;
1010 ProbeForRead(pIconInfo
, sizeof(ICONINFO
), 1);
1011 RtlCopyMemory(&CurIcon
->IconInfo
, pIconInfo
, sizeof(ICONINFO
));
1013 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(pIconInfo
->hbmMask
);
1014 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(pIconInfo
->hbmColor
);
1016 if (CurIcon
->IconInfo
.hbmColor
)
1018 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
)))
1020 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1021 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1022 SURFACE_UnlockSurface(psurfBmp
);
1023 GreSetObjectOwner(CurIcon
->IconInfo
.hbmMask
, GDI_OBJ_HMGR_PUBLIC
);
1026 if (CurIcon
->IconInfo
.hbmMask
)
1028 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
1030 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
1032 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1033 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1034 SURFACE_UnlockSurface(psurfBmp
);
1037 GreSetObjectOwner(CurIcon
->IconInfo
.hbmMask
, GDI_OBJ_HMGR_PUBLIC
);
1040 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1042 Status
= _SEH2_GetExceptionCode();
1046 if (!NT_SUCCESS(Status
))
1047 SetLastNtError(Status
);
1051 UserDereferenceObject(CurIcon
);
1055 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1062 NtUserSetCursorIconData(
1070 PCURICON_OBJECT CurIcon
;
1074 DECLARE_RETURN(BOOL
);
1076 DPRINT("Enter NtUserSetCursorIconData\n");
1077 UserEnterExclusive();
1079 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1084 CurIcon
->hModule
= hModule
;
1085 CurIcon
->hRsrc
= hRsrc
;
1086 CurIcon
->hGroupRsrc
= hGroupRsrc
;
1091 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
.fIcon
, fIcon
, sizeof(BOOL
));
1092 if (!NT_SUCCESS(Status
))
1094 SetLastNtError(Status
);
1106 Status
= MmCopyFromCaller(&SafeHotspot
, Hotspot
, sizeof(POINT
));
1107 if (NT_SUCCESS(Status
))
1109 CurIcon
->IconInfo
.xHotspot
= SafeHotspot
.x
;
1110 CurIcon
->IconInfo
.yHotspot
= SafeHotspot
.y
;
1115 SetLastNtError(Status
);
1118 if (!fIcon
&& !Hotspot
)
1126 /* This icon is shared now */
1127 GreSetObjectOwner(CurIcon
->IconInfo
.hbmMask
, GDI_OBJ_HMGR_PUBLIC
);
1128 if(CurIcon
->IconInfo
.hbmColor
)
1130 GreSetObjectOwner(CurIcon
->IconInfo
.hbmColor
, GDI_OBJ_HMGR_PUBLIC
);
1133 UserDereferenceObject(CurIcon
);
1138 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1144 /* Mostly inspired from wine code */
1150 PCURICON_OBJECT pIcon
,
1154 HBRUSH hbrFlickerFreeDraw
,
1158 HBITMAP hbmMask
, hbmColor
;
1159 BITMAP bmpColor
, bm
;
1161 INT iOldBkColor
= 0, iOldTxtColor
= 0;
1163 HDC hMemDC
, hDestDC
= hDc
;
1164 HGDIOBJ hOldOffBrush
= 0;
1165 HGDIOBJ hOldOffBmp
= 0;
1166 HBITMAP hTmpBmp
= 0, hOffBmp
= 0;
1167 BOOL bAlpha
= FALSE
;
1168 INT x
=xLeft
, y
=yTop
;
1170 hbmMask
= pIcon
->IconInfo
.hbmMask
;
1171 hbmColor
= pIcon
->IconInfo
.hbmColor
;
1174 DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
1176 if (!hbmMask
|| !GreGetObject(hbmMask
, sizeof(BITMAP
), (PVOID
)&bm
))
1181 if (hbmColor
&& !GreGetObject(hbmColor
, sizeof(BITMAP
), (PVOID
)&bmpColor
))
1186 if(!(hMemDC
= NtGdiCreateCompatibleDC(hDc
)))
1188 DPRINT1("NtGdiCreateCompatibleDC failed!\n");
1192 /* Check for alpha */
1194 && (bmpColor
.bmBitsPixel
== 32)
1195 && (diFlags
& DI_IMAGE
))
1197 SURFACE
*psurfOff
= NULL
;
1198 PFN_DIB_GetPixel fnSource_GetPixel
= NULL
;
1201 /* In order to correctly display 32 bit icons Windows first scans the image,
1202 because information about transparency is not stored in any image's headers */
1203 psurfOff
= SURFACE_ShareLockSurface(hbmColor
);
1206 fnSource_GetPixel
= DibFunctionsForBitmapFormat
[psurfOff
->SurfObj
.iBitmapFormat
].DIB_GetPixel
;
1207 if (fnSource_GetPixel
)
1209 for (i
= 0; i
< psurfOff
->SurfObj
.sizlBitmap
.cx
; i
++)
1211 for (j
= 0; j
< psurfOff
->SurfObj
.sizlBitmap
.cy
; j
++)
1213 bAlpha
= ((BYTE
)(fnSource_GetPixel(&psurfOff
->SurfObj
, i
, j
) >> 24) & 0xff);
1221 SURFACE_ShareUnlockSurface(psurfOff
);
1226 cxWidth
= ((diFlags
& DI_DEFAULTSIZE
) ?
1227 UserGetSystemMetrics(SM_CXICON
) : pIcon
->Size
.cx
);
1230 cyHeight
= ((diFlags
& DI_DEFAULTSIZE
) ?
1231 UserGetSystemMetrics(SM_CYICON
) : pIcon
->Size
.cy
);
1233 DoFlickerFree
= (hbrFlickerFreeDraw
&&
1234 (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw
) == GDI_OBJECT_TYPE_BRUSH
));
1238 hDestDC
= NtGdiCreateCompatibleDC(hDc
);
1241 DPRINT1("NtGdiCreateCompatibleDC failed!\n");
1245 hOffBmp
= NtGdiCreateCompatibleBitmap(hDc
, cxWidth
, cyHeight
);
1248 DPRINT1("NtGdiCreateCompatibleBitmap failed!\n");
1251 hOldOffBmp
= NtGdiSelectBitmap(hDestDC
, hOffBmp
);
1252 hOldOffBrush
= NtGdiSelectBrush(hDestDC
, hbrFlickerFreeDraw
);
1253 NtGdiPatBlt(hDestDC
, 0, 0, cxWidth
, cyHeight
, PATCOPY
);
1254 NtGdiSelectBrush(hDestDC
, hOldOffBrush
);
1258 /* Set Background/foreground colors */
1259 iOldTxtColor
= IntGdiSetTextColor(hDc
, 0); //black
1260 iOldBkColor
= IntGdiSetBkColor(hDc
, 0x00FFFFFF); //white
1262 if(bAlpha
&& (diFlags
& DI_IMAGE
))
1264 BLENDFUNCTION pixelblend
= { AC_SRC_OVER
, 0, 255, AC_SRC_ALPHA
};
1269 HBITMAP hMemBmp
= NULL
;
1271 hMemBmp
= BITMAP_CopyBitmap(hbmColor
);
1274 DPRINT1("BITMAP_CopyBitmap failed!");
1278 psurf
= SURFACE_ShareLockSurface(hMemBmp
);
1281 DPRINT1("SURFACE_LockSurface failed!\n");
1285 /* premultiply with the alpha channel value */
1286 for (i
= 0; i
< psurf
->SurfObj
.sizlBitmap
.cy
; i
++)
1288 ptr
= (PBYTE
)psurf
->SurfObj
.pvScan0
+ i
*psurf
->SurfObj
.lDelta
;
1289 for (j
= 0; j
< psurf
->SurfObj
.sizlBitmap
.cx
; j
++)
1292 ptr
[0] = (ptr
[0] * Alpha
) / 0xff;
1293 ptr
[1] = (ptr
[1] * Alpha
) / 0xff;
1294 ptr
[2] = (ptr
[2] * Alpha
) / 0xff;
1300 SURFACE_ShareUnlockSurface(psurf
);
1302 hTmpBmp
= NtGdiSelectBitmap(hMemDC
, hMemBmp
);
1304 Ret
= NtGdiAlphaBlend(hDestDC
,
1316 NtGdiSelectBitmap(hMemDC
, hTmpBmp
);
1318 if(hMemBmp
) NtGdiDeleteObjectApp(hMemBmp
);
1322 if (diFlags
& DI_MASK
)
1324 hTmpBmp
= NtGdiSelectBitmap(hMemDC
, hbmMask
);
1325 NtGdiStretchBlt(hDestDC
,
1337 NtGdiSelectBitmap(hMemDC
, hTmpBmp
);
1340 if(diFlags
& DI_IMAGE
)
1344 DWORD rop
= (diFlags
& DI_MASK
) ? SRCINVERT
: SRCCOPY
;
1345 hTmpBmp
= NtGdiSelectBitmap(hMemDC
, hbmColor
);
1346 NtGdiStretchBlt(hDestDC
,
1358 NtGdiSelectBitmap(hMemDC
, hTmpBmp
);
1362 /* Mask bitmap holds the information in its second half */
1363 DWORD rop
= (diFlags
& DI_MASK
) ? SRCINVERT
: SRCCOPY
;
1364 hTmpBmp
= NtGdiSelectBitmap(hMemDC
, hbmMask
);
1365 NtGdiStretchBlt(hDestDC
,
1377 NtGdiSelectBitmap(hMemDC
, hTmpBmp
);
1384 NtGdiBitBlt(hDc
, xLeft
, yTop
, cxWidth
, cyHeight
, hDestDC
, 0, 0, SRCCOPY
, 0, 0);
1387 /* Restore foreground and background colors */
1388 IntGdiSetBkColor(hDc
, iOldBkColor
);
1389 IntGdiSetTextColor(hDc
, iOldTxtColor
);
1394 NtGdiDeleteObjectApp(hMemDC
);
1397 if(hOldOffBmp
) NtGdiSelectBitmap(hDestDC
, hOldOffBmp
);
1398 NtGdiDeleteObjectApp(hDestDC
);
1399 if(hOffBmp
) NtGdiDeleteObjectApp(hOffBmp
);
1418 HBRUSH hbrFlickerFreeDraw
,
1420 BOOL bMetaHDC
, // When TRUE, GDI functions need to be handled in User32!
1423 PCURICON_OBJECT pIcon
;
1426 DPRINT("Enter NtUserDrawIconEx\n");
1427 UserEnterExclusive();
1429 if (!(pIcon
= UserGetCurIconObject(hIcon
)))
1431 DPRINT1("UserGetCurIconObject() failed!\n");
1436 Ret
= UserDrawIconEx(hdc
,
1446 UserDereferenceObject(pIcon
);