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
.CursorClipInfo
.IsClipped
= FALSE
;
64 gSysCursorInfo
.LastBtnDown
= 0;
65 gSysCursorInfo
.CurrentCursorObject
= NULL
;
66 gSysCursorInfo
.ShowingCursor
= 0;
67 gSysCursorInfo
.ClickLockActive
= FALSE
;
68 gSysCursorInfo
.ClickLockTime
= 0;
73 PSYSTEM_CURSORINFO FASTCALL
76 return &gSysCursorInfo
;
79 /* This function creates a reference for the object! */
80 PCURICON_OBJECT FASTCALL
UserGetCurIconObject(HCURSOR hCurIcon
)
82 PCURICON_OBJECT CurIcon
;
86 SetLastWin32Error(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 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
98 ASSERT(CurIcon
->head
.cLockObj
>= 1);
105 PCURICON_OBJECT NewCursor
,
108 PSYSTEM_CURSORINFO CurInfo
;
109 PCURICON_OBJECT OldCursor
;
110 HCURSOR hOldCursor
= (HCURSOR
)0;
114 CurInfo
= IntGetSysCursorInfo();
116 OldCursor
= CurInfo
->CurrentCursorObject
;
119 hOldCursor
= (HCURSOR
)OldCursor
->Self
;
122 /* Is the new cursor the same as the old cursor? */
123 if (OldCursor
== NewCursor
)
125 /* Nothing to to do in this case */
129 /* Get the screen DC */
130 if(!(hdcScreen
= IntGetScreenDC()))
135 /* Do we have a new cursor? */
138 UserReferenceObject(NewCursor
);
140 CurInfo
->ShowingCursor
= 1;
141 CurInfo
->CurrentCursorObject
= NewCursor
;
143 /* Call GDI to set the new screen cursor */
144 bResult
= GreSetPointerShape(hdcScreen
,
145 NewCursor
->IconInfo
.hbmMask
,
146 NewCursor
->IconInfo
.hbmColor
,
147 NewCursor
->IconInfo
.xHotspot
,
148 NewCursor
->IconInfo
.yHotspot
,
156 /* Check if were diplaying a cursor */
157 if (OldCursor
&& CurInfo
->ShowingCursor
)
159 /* Remove the cursor */
160 GreMovePointer(hdcScreen
, -1, -1);
161 DPRINT("Removing pointer!\n");
164 CurInfo
->CurrentCursorObject
= NULL
;
165 CurInfo
->ShowingCursor
= 0;
168 /* OldCursor is not in use anymore */
171 UserDereferenceObject(OldCursor
);
174 /* Return handle of the old cursor */
178 BOOL
UserSetCursorPos( INT x
, INT y
)
180 PWINDOW_OBJECT DesktopWindow
;
181 PSYSTEM_CURSORINFO CurInfo
;
185 if(!(hDC
= IntGetScreenDC()))
190 CurInfo
= IntGetSysCursorInfo();
192 DesktopWindow
= UserGetDesktopWindow();
196 if(x
>= DesktopWindow
->Wnd
->rcClient
.right
)
197 x
= DesktopWindow
->Wnd
->rcClient
.right
- 1;
198 if(y
>= DesktopWindow
->Wnd
->rcClient
.bottom
)
199 y
= DesktopWindow
->Wnd
->rcClient
.bottom
- 1;
207 //Clip cursor position
208 if(CurInfo
->CursorClipInfo
.IsClipped
)
210 if(x
>= (LONG
)CurInfo
->CursorClipInfo
.Right
)
211 x
= (LONG
)CurInfo
->CursorClipInfo
.Right
- 1;
212 if(x
< (LONG
)CurInfo
->CursorClipInfo
.Left
)
213 x
= (LONG
)CurInfo
->CursorClipInfo
.Left
;
214 if(y
>= (LONG
)CurInfo
->CursorClipInfo
.Bottom
)
215 y
= (LONG
)CurInfo
->CursorClipInfo
.Bottom
- 1;
216 if(y
< (LONG
)CurInfo
->CursorClipInfo
.Top
)
217 y
= (LONG
)CurInfo
->CursorClipInfo
.Top
;
220 //Store the new cursor position
221 gpsi
->ptCursor
.x
= x
;
222 gpsi
->ptCursor
.y
= y
;
224 //Move the mouse pointer
225 GreMovePointer(hDC
, x
, y
);
227 //Generate a mouse move message
228 Msg
.message
= WM_MOUSEMOVE
;
229 Msg
.wParam
= CurInfo
->ButtonsDown
;
230 Msg
.lParam
= MAKELPARAM(x
, y
);
231 Msg
.pt
= gpsi
->ptCursor
;
232 MsqInsertSystemMessage(&Msg
);
237 /* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
238 * User32 macro NtUserShowCursor */
239 int UserShowCursor(BOOL bShow
)
241 PSYSTEM_CURSORINFO CurInfo
= IntGetSysCursorInfo();
244 if (!(hdcScreen
= IntGetScreenDC()))
246 return 0; /* No mouse */
251 /* Check if were diplaying a cursor */
252 if (CurInfo
->ShowingCursor
== 1)
254 /* Remove the pointer */
255 GreMovePointer(hdcScreen
, -1, -1);
256 DPRINT("Removing pointer!\n");
258 CurInfo
->ShowingCursor
--;
262 if (CurInfo
->ShowingCursor
== 0)
265 GreMovePointer(hdcScreen
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
267 CurInfo
->ShowingCursor
++;
270 return CurInfo
->ShowingCursor
;
274 * We have to register that this object is in use by the current
275 * process. The only way to do that seems to be to walk the list
276 * of cursor/icon objects starting at W32Process->CursorIconListHead.
277 * If the object is already present in the list, we don't have to do
278 * anything, if it's not present we add it and inc the ProcessCount
279 * in the object. Having to walk the list kind of sucks, but that's
282 static BOOLEAN FASTCALL
283 ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon
)
285 PPROCESSINFO Win32Process
;
286 PCURICON_PROCESS Current
;
288 Win32Process
= PsGetCurrentProcessWin32Process();
290 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
292 if (Current
->Process
== Win32Process
)
294 /* Already registered for this process */
299 /* Not registered yet */
300 Current
= ExAllocateFromPagedLookasideList(&gProcessLookasideList
);
305 InsertHeadList(&CurIcon
->ProcessList
, &Current
->ListEntry
);
306 Current
->Process
= Win32Process
;
311 PCURICON_OBJECT FASTCALL
312 IntFindExistingCurIconObject(HMODULE hModule
,
313 HRSRC hRsrc
, LONG cx
, LONG cy
)
315 PCURICON_OBJECT CurIcon
;
317 LIST_FOR_EACH(CurIcon
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
320 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
321 // UserReferenceObject( CurIcon);
323 if ((CurIcon
->hModule
== hModule
) && (CurIcon
->hRsrc
== hRsrc
))
325 if (cx
&& ((cx
!= CurIcon
->Size
.cx
) || (cy
!= CurIcon
->Size
.cy
)))
327 // UserDereferenceObject(CurIcon);
330 if (! ReferenceCurIconByProcess(CurIcon
))
338 // UserDereferenceObject(CurIcon);
345 PCURICON_OBJECT FASTCALL
346 IntCreateCurIconHandle()
348 PCURICON_OBJECT CurIcon
;
351 CurIcon
= UserCreateObject(gHandleTable
, NULL
, &hCurIcon
, otCursorIcon
, sizeof(CURICON_OBJECT
));
355 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
359 CurIcon
->Self
= hCurIcon
;
360 InitializeListHead(&CurIcon
->ProcessList
);
362 if (! ReferenceCurIconByProcess(CurIcon
))
364 DPRINT1("Failed to add process\n");
365 UserDeleteObject(hCurIcon
, otCursorIcon
);
366 UserDereferenceObject(CurIcon
);
370 InsertHeadList(&gCurIconList
, &CurIcon
->ListEntry
);
376 IntDestroyCurIconObject(PCURICON_OBJECT CurIcon
, BOOL ProcessCleanup
)
378 PSYSTEM_CURSORINFO CurInfo
;
379 HBITMAP bmpMask
, bmpColor
;
381 PCURICON_PROCESS Current
= NULL
;
382 PPROCESSINFO W32Process
= PsGetCurrentProcessWin32Process();
384 /* Private objects can only be destroyed by their own process */
385 if (NULL
== CurIcon
->hModule
)
387 ASSERT(CurIcon
->ProcessList
.Flink
->Flink
== &CurIcon
->ProcessList
);
388 Current
= CONTAINING_RECORD(CurIcon
->ProcessList
.Flink
, CURICON_PROCESS
, ListEntry
);
389 if (Current
->Process
!= W32Process
)
391 DPRINT1("Trying to destroy private icon/cursor of another process\n");
395 else if (! ProcessCleanup
)
397 DPRINT("Trying to destroy shared icon/cursor\n");
401 /* Now find this process in the list of processes referencing this object and
402 remove it from that list */
403 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
405 if (Current
->Process
== W32Process
)
407 RemoveEntryList(&Current
->ListEntry
);
412 ExFreeToPagedLookasideList(&gProcessLookasideList
, Current
);
414 /* If there are still processes referencing this object we can't destroy it yet */
415 if (! IsListEmpty(&CurIcon
->ProcessList
))
421 if (! ProcessCleanup
)
423 RemoveEntryList(&CurIcon
->ListEntry
);
426 CurInfo
= IntGetSysCursorInfo();
428 if (CurInfo
->CurrentCursorObject
== CurIcon
)
430 /* Hide the cursor if we're destroying the current cursor */
431 UserSetCursor(NULL
, TRUE
);
434 bmpMask
= CurIcon
->IconInfo
.hbmMask
;
435 bmpColor
= CurIcon
->IconInfo
.hbmColor
;
440 GDIOBJ_SetOwnership(bmpMask
, PsGetCurrentProcess());
441 GreDeleteObject(bmpMask
);
442 CurIcon
->IconInfo
.hbmMask
= NULL
;
446 GDIOBJ_SetOwnership(bmpColor
, PsGetCurrentProcess());
447 GreDeleteObject(bmpColor
);
448 CurIcon
->IconInfo
.hbmColor
= NULL
;
451 /* We were given a pointer, no need to keep the reference anylonger! */
452 UserDereferenceObject(CurIcon
);
453 Ret
= UserDeleteObject(CurIcon
->Self
, otCursorIcon
);
459 IntCleanupCurIcons(struct _EPROCESS
*Process
, PPROCESSINFO Win32Process
)
461 PCURICON_OBJECT CurIcon
, tmp
;
462 PCURICON_PROCESS ProcessData
;
464 LIST_FOR_EACH_SAFE(CurIcon
, tmp
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
466 UserReferenceObject(CurIcon
);
467 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon)))
469 LIST_FOR_EACH(ProcessData
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
471 if (Win32Process
== ProcessData
->Process
)
473 RemoveEntryList(&CurIcon
->ListEntry
);
474 IntDestroyCurIconObject(CurIcon
, TRUE
);
480 // UserDereferenceObject(Object);
485 UserDereferenceObject(CurIcon
);
496 NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL
, BOOL Indirect
)
498 PCURICON_OBJECT CurIcon
;
502 DECLARE_RETURN(HANDLE
);
504 DPRINT("Enter NtUserCreateCursorIconHandle\n");
505 UserEnterExclusive();
507 if (!(CurIcon
= IntCreateCurIconHandle()))
509 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
517 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
, IconInfo
, sizeof(ICONINFO
));
518 if (NT_SUCCESS(Status
))
520 /* Copy bitmaps and size info */
524 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
525 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
527 if (CurIcon
->IconInfo
.hbmColor
&&
528 (psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
)))
530 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
531 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
532 SURFACE_UnlockSurface(psurfBmp
);
533 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
535 if (CurIcon
->IconInfo
.hbmMask
&&
536 (psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
538 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
540 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
541 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
>> 1;
543 SURFACE_UnlockSurface(psurfBmp
);
544 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
547 /* Calculate icon hotspot */
548 if (CurIcon
->IconInfo
.fIcon
== TRUE
)
550 CurIcon
->IconInfo
.xHotspot
= CurIcon
->Size
.cx
>> 1;
551 CurIcon
->IconInfo
.yHotspot
= CurIcon
->Size
.cy
>> 1;
556 SetLastNtError(Status
);
557 /* FIXME - Don't exit here */
561 UserDereferenceObject(CurIcon
);
565 DPRINT("Leave NtUserCreateCursorIconHandle, ret=%i\n",_ret_
);
578 PUNICODE_STRING lpInstName
, // optional
579 PUNICODE_STRING lpResName
, // optional
580 LPDWORD pbpp
, // optional
584 PCURICON_OBJECT CurIcon
;
585 NTSTATUS Status
= STATUS_SUCCESS
;
589 DPRINT("Enter NtUserGetIconInfo\n");
590 UserEnterExclusive();
594 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
598 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
603 RtlCopyMemory(&ii
, &CurIcon
->IconInfo
, sizeof(ICONINFO
));
606 ii
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
607 ii
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
613 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
);
616 colorBpp
= BitsPerFormat(psurfBmp
->SurfObj
.iBitmapFormat
);
617 SURFACE_UnlockSurface(psurfBmp
);
624 ProbeForWrite(IconInfo
, sizeof(ICONINFO
), 1);
625 RtlCopyMemory(IconInfo
, &ii
, sizeof(ICONINFO
));
629 ProbeForWrite(pbpp
, sizeof(DWORD
), 1);
633 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
635 Status
= _SEH2_GetExceptionCode();
639 if (NT_SUCCESS(Status
))
642 SetLastNtError(Status
);
644 UserDereferenceObject(CurIcon
);
647 DPRINT("Leave NtUserGetIconInfo, ret=%i\n", Ret
);
662 PLONG plcx
, // &size.cx
663 PLONG plcy
) // &size.cy
665 PCURICON_OBJECT CurIcon
;
666 NTSTATUS Status
= STATUS_SUCCESS
;
669 DPRINT("Enter NtUserGetIconSize\n");
670 UserEnterExclusive();
672 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
679 ProbeForWrite(plcx
, sizeof(LONG
), 1);
680 RtlCopyMemory(plcx
, &CurIcon
->Size
.cx
, sizeof(LONG
));
681 ProbeForWrite(plcy
, sizeof(LONG
), 1);
682 RtlCopyMemory(plcy
, &CurIcon
->Size
.cy
, sizeof(LONG
));
684 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
686 Status
= _SEH2_GetExceptionCode();
690 if (NT_SUCCESS(Status
))
693 SetLastNtError(Status
); // maybe not, test this
695 UserDereferenceObject(CurIcon
);
698 DPRINT("Leave NtUserGetIconSize, ret=%i\n", bRet
);
709 NtUserGetCursorFrameInfo(
730 PSYSTEM_CURSORINFO CurInfo
;
731 NTSTATUS Status
= STATUS_SUCCESS
;
732 PCURICON_OBJECT CurIcon
;
734 DECLARE_RETURN(BOOL
);
736 DPRINT("Enter NtUserGetCursorInfo\n");
737 UserEnterExclusive();
739 CurInfo
= IntGetSysCursorInfo();
740 CurIcon
= (PCURICON_OBJECT
)CurInfo
->CurrentCursorObject
;
742 SafeCi
.cbSize
= sizeof(CURSORINFO
);
743 SafeCi
.flags
= ((CurInfo
->ShowingCursor
&& CurIcon
) ? CURSOR_SHOWING
: 0);
744 SafeCi
.hCursor
= (CurIcon
? (HCURSOR
)CurIcon
->Self
: (HCURSOR
)0);
746 SafeCi
.ptScreenPos
= gpsi
->ptCursor
;
750 if (pci
->cbSize
== sizeof(CURSORINFO
))
752 ProbeForWrite(pci
, sizeof(CURSORINFO
), 1);
753 RtlCopyMemory(pci
, &SafeCi
, sizeof(CURSORINFO
));
758 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
761 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
763 Status
= _SEH2_GetExceptionCode();
766 if (!NT_SUCCESS(Status
))
768 SetLastNtError(Status
);
774 DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_
);
784 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
785 PSYSTEM_CURSORINFO CurInfo
;
786 PWINDOW_OBJECT DesktopWindow
= NULL
;
788 CurInfo
= IntGetSysCursorInfo();
790 DesktopWindow
= UserGetDesktopWindow();
793 (prcl
->right
> prcl
->left
) &&
794 (prcl
->bottom
> prcl
->top
) &&
795 DesktopWindow
!= NULL
)
797 CurInfo
->CursorClipInfo
.IsClipped
= TRUE
;
798 CurInfo
->CursorClipInfo
.Left
= max(prcl
->left
, DesktopWindow
->Wnd
->rcWindow
.left
);
799 CurInfo
->CursorClipInfo
.Top
= max(prcl
->top
, DesktopWindow
->Wnd
->rcWindow
.top
);
800 CurInfo
->CursorClipInfo
.Right
= min(prcl
->right
, DesktopWindow
->Wnd
->rcWindow
.right
);
801 CurInfo
->CursorClipInfo
.Bottom
= min(prcl
->bottom
, DesktopWindow
->Wnd
->rcWindow
.bottom
);
803 UserSetCursorPos(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
807 CurInfo
->CursorClipInfo
.IsClipped
= FALSE
;
821 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
829 /* Probe and copy rect */
830 ProbeForRead(prcl
, sizeof(RECTL
), 1);
833 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
835 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
836 _SEH2_YIELD(return FALSE
;)
843 UserEnterExclusive();
845 /* Call the internal function */
846 bResult
= UserClipCursor(prcl
);
863 PCURICON_OBJECT CurIcon
;
865 DECLARE_RETURN(BOOL
);
867 DPRINT("Enter NtUserDestroyCursorIcon\n");
868 UserEnterExclusive();
870 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
875 ret
= IntDestroyCurIconObject(CurIcon
, FALSE
);
876 /* Note: IntDestroyCurIconObject will remove our reference for us! */
881 DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_
);
892 NtUserFindExistingCursorIcon(
898 PCURICON_OBJECT CurIcon
;
899 HANDLE Ret
= (HANDLE
)0;
900 DECLARE_RETURN(HICON
);
902 DPRINT("Enter NtUserFindExistingCursorIcon\n");
903 UserEnterExclusive();
905 CurIcon
= IntFindExistingCurIconObject(hModule
, hRsrc
, cx
, cy
);
910 // IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
914 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
918 DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_
);
932 /* FIXME - check if process has WINSTA_READATTRIBUTES */
933 PSYSTEM_CURSORINFO CurInfo
;
936 DECLARE_RETURN(BOOL
);
938 DPRINT("Enter NtUserGetClipCursor\n");
939 UserEnterExclusive();
944 CurInfo
= IntGetSysCursorInfo();
945 if (CurInfo
->CursorClipInfo
.IsClipped
)
947 Rect
.left
= CurInfo
->CursorClipInfo
.Left
;
948 Rect
.top
= CurInfo
->CursorClipInfo
.Top
;
949 Rect
.right
= CurInfo
->CursorClipInfo
.Right
;
950 Rect
.bottom
= CurInfo
->CursorClipInfo
.Bottom
;
956 Rect
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
957 Rect
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
960 Status
= MmCopyToCaller(lpRect
, &Rect
, sizeof(RECT
));
961 if (!NT_SUCCESS(Status
))
963 SetLastNtError(Status
);
970 DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_
);
984 PCURICON_OBJECT CurIcon
;
986 DECLARE_RETURN(HCURSOR
);
988 DPRINT("Enter NtUserSetCursor\n");
989 UserEnterExclusive();
993 if (!(CurIcon
= UserGetCurIconObject(hCursor
)))
1003 OldCursor
= UserSetCursor(CurIcon
, FALSE
);
1007 UserDereferenceObject(CurIcon
);
1013 DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_
);
1024 NtUserSetCursorContents(
1026 PICONINFO UnsafeIconInfo
)
1028 PCURICON_OBJECT CurIcon
;
1033 DECLARE_RETURN(BOOL
);
1035 DPRINT("Enter NtUserSetCursorContents\n");
1036 UserEnterExclusive();
1038 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1044 Status
= MmCopyFromCaller(&IconInfo
, UnsafeIconInfo
, sizeof(ICONINFO
));
1045 if (!NT_SUCCESS(Status
))
1047 SetLastNtError(Status
);
1051 /* Delete old bitmaps */
1052 if (CurIcon
->IconInfo
.hbmColor
!= IconInfo
.hbmColor
)
1054 GreDeleteObject(CurIcon
->IconInfo
.hbmColor
);
1056 if (CurIcon
->IconInfo
.hbmMask
!= IconInfo
.hbmMask
)
1058 GreDeleteObject(CurIcon
->IconInfo
.hbmMask
);
1061 /* Copy new IconInfo field */
1062 CurIcon
->IconInfo
= IconInfo
;
1064 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
);
1067 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1068 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1069 SURFACE_UnlockSurface(psurfBmp
);
1070 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
1074 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
);
1078 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1079 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
/ 2;
1081 SURFACE_UnlockSurface(psurfBmp
);
1082 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
1091 UserDereferenceObject(CurIcon
);
1096 DPRINT("Leave NtUserSetCursorContents, ret=%i\n",_ret_
);
1108 NtUserSetCursorIconData(
1111 PUNICODE_STRING pstrResName
,
1112 PICONINFO pIconInfo
)
1114 PCURICON_OBJECT CurIcon
;
1116 NTSTATUS Status
= STATUS_SUCCESS
;
1118 DECLARE_RETURN(BOOL
);
1120 DPRINT("Enter NtUserSetCursorIconData\n");
1121 UserEnterExclusive();
1123 if (!(CurIcon
= UserGetCurIconObject(Handle
)))
1128 CurIcon
->hModule
= hModule
;
1129 CurIcon
->hRsrc
= NULL
; //hRsrc;
1130 CurIcon
->hGroupRsrc
= NULL
; //hGroupRsrc;
1134 ProbeForRead(pIconInfo
, sizeof(ICONINFO
), 1);
1135 RtlCopyMemory(&CurIcon
->IconInfo
, pIconInfo
, sizeof(ICONINFO
));
1137 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(pIconInfo
->hbmMask
);
1138 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(pIconInfo
->hbmColor
);
1140 if (CurIcon
->IconInfo
.hbmColor
)
1142 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
)))
1144 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1145 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1146 SURFACE_UnlockSurface(psurfBmp
);
1147 GDIOBJ_SetOwnership(GdiHandleTable
, CurIcon
->IconInfo
.hbmMask
, NULL
);
1150 if (CurIcon
->IconInfo
.hbmMask
)
1152 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
1154 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
1156 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1157 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1158 SURFACE_UnlockSurface(psurfBmp
);
1161 GDIOBJ_SetOwnership(GdiHandleTable
, CurIcon
->IconInfo
.hbmMask
, NULL
);
1164 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1166 Status
= _SEH2_GetExceptionCode();
1170 if (!NT_SUCCESS(Status
))
1171 SetLastNtError(Status
);
1175 UserDereferenceObject(CurIcon
);
1179 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1186 NtUserSetCursorIconData(
1194 PCURICON_OBJECT CurIcon
;
1198 DECLARE_RETURN(BOOL
);
1200 DPRINT("Enter NtUserSetCursorIconData\n");
1201 UserEnterExclusive();
1203 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1208 CurIcon
->hModule
= hModule
;
1209 CurIcon
->hRsrc
= hRsrc
;
1210 CurIcon
->hGroupRsrc
= hGroupRsrc
;
1215 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
.fIcon
, fIcon
, sizeof(BOOL
));
1216 if (!NT_SUCCESS(Status
))
1218 SetLastNtError(Status
);
1230 Status
= MmCopyFromCaller(&SafeHotspot
, Hotspot
, sizeof(POINT
));
1231 if (NT_SUCCESS(Status
))
1233 CurIcon
->IconInfo
.xHotspot
= SafeHotspot
.x
;
1234 CurIcon
->IconInfo
.yHotspot
= SafeHotspot
.y
;
1239 SetLastNtError(Status
);
1242 if (!fIcon
&& !Hotspot
)
1248 UserDereferenceObject(CurIcon
);
1253 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1264 NtUserSetSystemCursor(
1276 PCURICON_OBJECT pIcon
,
1280 HBRUSH hbrFlickerFreeDraw
,
1284 HBITMAP hbmMask
, hbmColor
;
1285 BITMAP bmpMask
, bmpColor
;
1290 HGDIOBJ hOldOffBrush
= 0;
1291 HGDIOBJ hOldOffBmp
= 0;
1294 HGDIOBJ hOldMask
= NULL
;
1296 HGDIOBJ hOldImage
= NULL
;
1297 BOOL bAlpha
= FALSE
;
1299 hbmMask
= pIcon
->IconInfo
.hbmMask
;
1300 hbmColor
= pIcon
->IconInfo
.hbmColor
;
1303 DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
1305 if (!hbmMask
|| !IntGdiGetObject(hbmMask
, sizeof(BITMAP
), (PVOID
)&bmpMask
))
1310 if (hbmColor
&& !IntGdiGetObject(hbmColor
, sizeof(BITMAP
), (PVOID
)&bmpColor
))
1317 IconSize
.cx
= bmpColor
.bmWidth
;
1318 IconSize
.cy
= bmpColor
.bmHeight
;
1322 IconSize
.cx
= bmpMask
.bmWidth
;
1323 IconSize
.cy
= bmpMask
.bmHeight
/ 2;
1326 /* NtGdiCreateCompatibleBitmap will create a monochrome bitmap
1327 when cxWidth or cyHeight is 0 */
1328 if ((bmpColor
.bmBitsPixel
== 32) && (cxWidth
!= 0) && (cyHeight
!= 0))
1330 SURFACE
*psurfOff
= NULL
;
1331 PFN_DIB_GetPixel fnSource_GetPixel
= NULL
;
1334 /* In order to correctly display 32 bit icons Windows first scans the image,
1335 because information about transparency is not stored in any image's headers */
1336 psurfOff
= SURFACE_LockSurface(hbmColor
? hbmColor
: hbmMask
);
1339 fnSource_GetPixel
= DibFunctionsForBitmapFormat
[psurfOff
->SurfObj
.iBitmapFormat
].DIB_GetPixel
;
1340 if (fnSource_GetPixel
)
1342 for (x
= 0; x
< psurfOff
->SurfObj
.sizlBitmap
.cx
; x
++)
1344 for (y
= 0; y
< psurfOff
->SurfObj
.sizlBitmap
.cy
; y
++)
1346 bAlpha
= ((BYTE
)(fnSource_GetPixel(&psurfOff
->SurfObj
, x
, y
) >> 24) & 0xff);
1354 SURFACE_UnlockSurface(psurfOff
);
1359 diFlags
= DI_NORMAL
;
1362 cxWidth
= ((diFlags
& DI_DEFAULTSIZE
) ?
1363 UserGetSystemMetrics(SM_CXICON
) : IconSize
.cx
);
1366 cyHeight
= ((diFlags
& DI_DEFAULTSIZE
) ?
1367 UserGetSystemMetrics(SM_CYICON
) : IconSize
.cy
);
1369 DoFlickerFree
= (hbrFlickerFreeDraw
&&
1370 (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw
) == GDI_OBJECT_TYPE_BRUSH
));
1372 if (DoFlickerFree
|| bAlpha
)
1376 SURFACE
*psurfOff
= NULL
;
1379 r
.bottom
= cyHeight
;
1381 hdcOff
= NtGdiCreateCompatibleDC(hDc
);
1384 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1388 hbmOff
= NtGdiCreateCompatibleBitmap(hDc
, cxWidth
, cyHeight
);
1391 DPRINT1("NtGdiCreateCompatibleBitmap() failed!\n");
1395 /* make sure we have a 32 bit offscreen bitmap
1396 otherwise we can't do alpha blending */
1397 psurfOff
= SURFACE_LockSurface(hbmOff
);
1398 if (psurfOff
== NULL
)
1400 DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
1403 BITMAP_GetObject(psurfOff
, sizeof(BITMAP
), (PVOID
)&bm
);
1405 if (bm
.bmBitsPixel
!= 32)
1408 SURFACE_UnlockSurface(psurfOff
);
1410 hOldOffBmp
= NtGdiSelectBitmap(hdcOff
, hbmOff
);
1413 DPRINT1("NtGdiSelectBitmap() failed!\n");
1419 hOldOffBrush
= NtGdiSelectBrush(hdcOff
, hbrFlickerFreeDraw
);
1422 DPRINT1("NtGdiSelectBrush() failed!\n");
1426 NtGdiPatBlt(hdcOff
, 0, 0, r
.right
, r
.bottom
, PATCOPY
);
1432 if (diFlags
& DI_IMAGE
)
1434 hdcImage
= NtGdiCreateCompatibleDC(hDc
);
1437 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1440 hOldImage
= NtGdiSelectBitmap(hdcImage
, (hbmColor
? hbmColor
: hbmMask
));
1443 DPRINT("NtGdiSelectBitmap() failed!\n");
1448 /* If DI_IMAGE flag is specified and hbmMask exists, then always use mask for drawing */
1449 if (diFlags
& DI_MASK
|| (diFlags
& DI_IMAGE
&& hbmMask
))
1451 hdcMask
= NtGdiCreateCompatibleDC(hDc
);
1454 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1458 hOldMask
= NtGdiSelectBitmap(hdcMask
, hbmMask
);
1461 DPRINT("NtGdiSelectBitmap() failed!\n");
1466 if (hdcMask
|| hdcImage
)
1468 GreStretchBltMask(hdcOff
,
1469 (DoFlickerFree
|| bAlpha
) ? 0 : xLeft
,
1470 (DoFlickerFree
|| bAlpha
) ? 0 : yTop
,
1473 hdcImage
? hdcImage
: hdcMask
,
1482 hdcImage
? 0 : IconSize
.cy
);
1485 if (hOldMask
) NtGdiSelectBitmap(hdcMask
, hOldMask
);
1486 if (hOldImage
) NtGdiSelectBitmap(hdcImage
, hOldImage
);
1487 if (hdcImage
) NtGdiDeleteObjectApp(hdcImage
);
1488 if (hdcMask
) NtGdiDeleteObjectApp(hdcMask
);
1493 SURFACE
*psurfOff
= NULL
;
1495 BLENDFUNCTION BlendFunc
;
1497 BYTE Red
, Green
, Blue
, Alpha
;
1501 psurfOff
= SURFACE_LockSurface(hbmOff
);
1502 if (psurfOff
== NULL
)
1504 DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
1507 BITMAP_GetObject(psurfOff
, sizeof(BITMAP
), (PVOID
)&bm
);
1509 pBits
= ExAllocatePoolWithTag(PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1512 DPRINT1("ExAllocatePoolWithTag() failed!\n");
1513 SURFACE_UnlockSurface(psurfOff
);
1518 IntGetBitmapBits(psurfOff
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), pBits
);
1520 /* premultiply with the alpha channel value */
1521 for (i
= 0; i
< cyHeight
; i
++)
1523 for (j
= 0; j
< cxWidth
; j
++)
1525 Pixel
= *(DWORD
*)(pBits
+ Count
);
1527 Alpha
= ((BYTE
)(Pixel
>> 24) & 0xff);
1529 Red
= (((BYTE
)(Pixel
>> 0)) * Alpha
) / 0xff;
1530 Green
= (((BYTE
)(Pixel
>> 8)) * Alpha
) / 0xff;
1531 Blue
= (((BYTE
)(Pixel
>> 16)) * Alpha
) / 0xff;
1533 *(DWORD
*)(pBits
+ Count
) = (DWORD
)(Red
| (Green
<< 8) | (Blue
<< 16) | (Alpha
<< 24));
1535 Count
+= sizeof(DWORD
);
1540 IntSetBitmapBits(psurfOff
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), pBits
);
1541 ExFreePoolWithTag(pBits
, TAG_BITMAP
);
1543 SURFACE_UnlockSurface(psurfOff
);
1545 BlendFunc
.BlendOp
= AC_SRC_OVER
;
1546 BlendFunc
.BlendFlags
= 0;
1547 BlendFunc
.SourceConstantAlpha
= 255;
1548 BlendFunc
.AlphaFormat
= AC_SRC_ALPHA
;
1550 NtGdiAlphaBlend(hDc
, xLeft
, yTop
, cxWidth
, cyHeight
,
1551 hdcOff
, 0, 0, cxWidth
, cyHeight
, BlendFunc
, 0);
1553 else if (DoFlickerFree
)
1555 NtGdiBitBlt(hDc
, xLeft
, yTop
, cxWidth
,
1556 cyHeight
, hdcOff
, 0, 0, SRCCOPY
, 0, 0);
1562 if (DoFlickerFree
|| bAlpha
)
1564 if (hOldOffBmp
) NtGdiSelectBitmap(hdcOff
, hOldOffBmp
);
1565 if (hOldOffBrush
) NtGdiSelectBrush(hdcOff
, hOldOffBrush
);
1566 if (hbmOff
) GreDeleteObject(hbmOff
);
1567 if (hdcOff
) NtGdiDeleteObjectApp(hdcOff
);
1586 HBRUSH hbrFlickerFreeDraw
,
1588 BOOL bMetaHDC
, // When TRUE, GDI functions need to be handled in User32!
1591 PCURICON_OBJECT pIcon
;
1594 DPRINT("Enter NtUserDrawIconEx\n");
1595 UserEnterExclusive();
1597 if (!(pIcon
= UserGetCurIconObject(hIcon
)))
1599 DPRINT1("UserGetCurIconObject() failed!\n");
1604 Ret
= UserDrawIconEx(hdc
,
1614 UserDereferenceObject(pIcon
);