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;
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
, BOOL CallHooks
)
180 PWINDOW_OBJECT DesktopWindow
;
181 PSYSTEM_CURSORINFO CurInfo
;
182 LARGE_INTEGER LargeTickCount
;
183 MSLLHOOKSTRUCT MouseHookData
;
187 if(!(hDC
= IntGetScreenDC()))
192 CurInfo
= IntGetSysCursorInfo();
194 DesktopWindow
= UserGetDesktopWindow();
198 if(x
>= DesktopWindow
->Wnd
->rcClient
.right
)
199 x
= DesktopWindow
->Wnd
->rcClient
.right
- 1;
200 if(y
>= DesktopWindow
->Wnd
->rcClient
.bottom
)
201 y
= DesktopWindow
->Wnd
->rcClient
.bottom
- 1;
209 //Clip cursor position
210 if(CurInfo
->CursorClipInfo
.IsClipped
)
212 if(x
>= (LONG
)CurInfo
->CursorClipInfo
.Right
)
213 x
= (LONG
)CurInfo
->CursorClipInfo
.Right
- 1;
214 if(x
< (LONG
)CurInfo
->CursorClipInfo
.Left
)
215 x
= (LONG
)CurInfo
->CursorClipInfo
.Left
;
216 if(y
>= (LONG
)CurInfo
->CursorClipInfo
.Bottom
)
217 y
= (LONG
)CurInfo
->CursorClipInfo
.Bottom
- 1;
218 if(y
< (LONG
)CurInfo
->CursorClipInfo
.Top
)
219 y
= (LONG
)CurInfo
->CursorClipInfo
.Top
;
222 //Store the new cursor position
223 gpsi
->ptCursor
.x
= x
;
224 gpsi
->ptCursor
.y
= y
;
226 KeQueryTickCount(&LargeTickCount
);
227 Msg
.time
= MsqCalculateMessageTime(&LargeTickCount
);
229 //Move the mouse pointer
230 GreMovePointer(hDC
, x
, y
);
232 //Generate a mouse move message
233 Msg
.message
= WM_MOUSEMOVE
;
234 Msg
.wParam
= CurInfo
->ButtonsDown
;
235 Msg
.lParam
= MAKELPARAM(x
, y
);
236 Msg
.pt
= gpsi
->ptCursor
;
238 MouseHookData
.pt
.x
= LOWORD(Msg
.lParam
);
239 MouseHookData
.pt
.y
= HIWORD(Msg
.lParam
);
243 MouseHookData
.mouseData
= MAKELONG(0, GET_WHEEL_DELTA_WPARAM(Msg
.wParam
));
247 case WM_XBUTTONDBLCLK
:
248 case WM_NCXBUTTONDOWN
:
250 case WM_NCXBUTTONDBLCLK
:
251 MouseHookData
.mouseData
= MAKELONG(0, HIWORD(Msg
.wParam
));
254 MouseHookData
.mouseData
= 0;
258 MouseHookData
.flags
= 0;
259 MouseHookData
.time
= Msg
.time
;
260 MouseHookData
.dwExtraInfo
= 0;
264 /* If the hook procedure returned non zero, dont send the message */
265 if (co_HOOK_CallHooks(WH_MOUSE_LL
, HC_ACTION
, Msg
.message
, (LPARAM
) &MouseHookData
))
269 MsqInsertSystemMessage(&Msg
);
273 /* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
274 * User32 macro NtUserShowCursor */
275 int UserShowCursor(BOOL bShow
)
277 PSYSTEM_CURSORINFO CurInfo
= IntGetSysCursorInfo();
280 if (!(hdcScreen
= IntGetScreenDC()))
282 return 0; /* No mouse */
287 /* Check if were diplaying a cursor */
288 if (CurInfo
->ShowingCursor
== 1)
290 /* Remove the pointer */
291 GreMovePointer(hdcScreen
, -1, -1);
292 DPRINT("Removing pointer!\n");
294 CurInfo
->ShowingCursor
--;
298 if (CurInfo
->ShowingCursor
== 0)
301 GreMovePointer(hdcScreen
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
303 CurInfo
->ShowingCursor
++;
306 return CurInfo
->ShowingCursor
;
310 * We have to register that this object is in use by the current
311 * process. The only way to do that seems to be to walk the list
312 * of cursor/icon objects starting at W32Process->CursorIconListHead.
313 * If the object is already present in the list, we don't have to do
314 * anything, if it's not present we add it and inc the ProcessCount
315 * in the object. Having to walk the list kind of sucks, but that's
318 static BOOLEAN FASTCALL
319 ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon
)
321 PPROCESSINFO Win32Process
;
322 PCURICON_PROCESS Current
;
324 Win32Process
= PsGetCurrentProcessWin32Process();
326 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
328 if (Current
->Process
== Win32Process
)
330 /* Already registered for this process */
335 /* Not registered yet */
336 Current
= ExAllocateFromPagedLookasideList(&gProcessLookasideList
);
341 InsertHeadList(&CurIcon
->ProcessList
, &Current
->ListEntry
);
342 Current
->Process
= Win32Process
;
347 PCURICON_OBJECT FASTCALL
348 IntFindExistingCurIconObject(HMODULE hModule
,
349 HRSRC hRsrc
, LONG cx
, LONG cy
)
351 PCURICON_OBJECT CurIcon
;
353 LIST_FOR_EACH(CurIcon
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
356 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
357 // UserReferenceObject( CurIcon);
359 if ((CurIcon
->hModule
== hModule
) && (CurIcon
->hRsrc
== hRsrc
))
361 if (cx
&& ((cx
!= CurIcon
->Size
.cx
) || (cy
!= CurIcon
->Size
.cy
)))
363 // UserDereferenceObject(CurIcon);
366 if (! ReferenceCurIconByProcess(CurIcon
))
374 // UserDereferenceObject(CurIcon);
382 IntCreateCurIconHandle()
384 PCURICON_OBJECT CurIcon
;
387 CurIcon
= UserCreateObject(gHandleTable
, NULL
, &hCurIcon
, otCursorIcon
, sizeof(CURICON_OBJECT
));
391 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
395 CurIcon
->Self
= hCurIcon
;
396 InitializeListHead(&CurIcon
->ProcessList
);
398 if (! ReferenceCurIconByProcess(CurIcon
))
400 DPRINT1("Failed to add process\n");
401 UserDeleteObject(hCurIcon
, otCursorIcon
);
402 UserDereferenceObject(CurIcon
);
406 InsertHeadList(&gCurIconList
, &CurIcon
->ListEntry
);
412 IntDestroyCurIconObject(PCURICON_OBJECT CurIcon
, BOOL ProcessCleanup
)
414 PSYSTEM_CURSORINFO CurInfo
;
415 HBITMAP bmpMask
, bmpColor
;
417 PCURICON_PROCESS Current
= NULL
;
418 PPROCESSINFO W32Process
= PsGetCurrentProcessWin32Process();
420 /* Private objects can only be destroyed by their own process */
421 if (NULL
== CurIcon
->hModule
)
423 ASSERT(CurIcon
->ProcessList
.Flink
->Flink
== &CurIcon
->ProcessList
);
424 Current
= CONTAINING_RECORD(CurIcon
->ProcessList
.Flink
, CURICON_PROCESS
, ListEntry
);
425 if (Current
->Process
!= W32Process
)
427 DPRINT1("Trying to destroy private icon/cursor of another process\n");
431 else if (! ProcessCleanup
)
433 DPRINT("Trying to destroy shared icon/cursor\n");
437 /* Now find this process in the list of processes referencing this object and
438 remove it from that list */
439 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
441 if (Current
->Process
== W32Process
)
443 RemoveEntryList(&Current
->ListEntry
);
448 ExFreeToPagedLookasideList(&gProcessLookasideList
, Current
);
450 /* If there are still processes referencing this object we can't destroy it yet */
451 if (! IsListEmpty(&CurIcon
->ProcessList
))
457 if (! ProcessCleanup
)
459 RemoveEntryList(&CurIcon
->ListEntry
);
462 CurInfo
= IntGetSysCursorInfo();
464 if (CurInfo
->CurrentCursorObject
== CurIcon
)
466 /* Hide the cursor if we're destroying the current cursor */
467 UserSetCursor(NULL
, TRUE
);
470 bmpMask
= CurIcon
->IconInfo
.hbmMask
;
471 bmpColor
= CurIcon
->IconInfo
.hbmColor
;
476 GDIOBJ_SetOwnership(bmpMask
, PsGetCurrentProcess());
477 GreDeleteObject(bmpMask
);
478 CurIcon
->IconInfo
.hbmMask
= NULL
;
482 GDIOBJ_SetOwnership(bmpColor
, PsGetCurrentProcess());
483 GreDeleteObject(bmpColor
);
484 CurIcon
->IconInfo
.hbmColor
= NULL
;
487 /* We were given a pointer, no need to keep the reference anylonger! */
488 UserDereferenceObject(CurIcon
);
489 Ret
= UserDeleteObject(CurIcon
->Self
, otCursorIcon
);
495 IntCleanupCurIcons(struct _EPROCESS
*Process
, PPROCESSINFO Win32Process
)
497 PCURICON_OBJECT CurIcon
, tmp
;
498 PCURICON_PROCESS ProcessData
;
500 LIST_FOR_EACH_SAFE(CurIcon
, tmp
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
502 UserReferenceObject(CurIcon
);
503 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon)))
505 LIST_FOR_EACH(ProcessData
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
507 if (Win32Process
== ProcessData
->Process
)
509 RemoveEntryList(&CurIcon
->ListEntry
);
510 IntDestroyCurIconObject(CurIcon
, TRUE
);
516 // UserDereferenceObject(Object);
521 UserDereferenceObject(CurIcon
);
532 NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL
, BOOL Indirect
)
534 PCURICON_OBJECT CurIcon
;
538 DECLARE_RETURN(HANDLE
);
540 DPRINT("Enter NtUserCreateCursorIconHandle\n");
541 UserEnterExclusive();
543 if (!(CurIcon
= IntCreateCurIconHandle()))
545 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
553 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
, IconInfo
, sizeof(ICONINFO
));
554 if (NT_SUCCESS(Status
))
556 /* Copy bitmaps and size info */
560 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
561 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
562 if(CurIcon
->IconInfo
.hbmColor
)
564 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
565 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
570 if (CurIcon
->IconInfo
.hbmColor
&&
571 (psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
)))
573 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
574 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
575 SURFACE_UnlockSurface(psurfBmp
);
576 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
578 if (CurIcon
->IconInfo
.hbmMask
&&
579 (psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
581 if(!CurIcon
->IconInfo
.hbmColor
)
583 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
584 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
*2;
586 SURFACE_UnlockSurface(psurfBmp
);
587 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
591 /* Calculate icon hotspot */
592 if (CurIcon
->IconInfo
.fIcon
== TRUE
)
594 CurIcon
->IconInfo
.xHotspot
= CurIcon
->Size
.cx
>> 1;
595 CurIcon
->IconInfo
.yHotspot
= CurIcon
->Size
.cy
>> 1;
600 SetLastNtError(Status
);
601 /* FIXME - Don't exit here */
605 UserDereferenceObject(CurIcon
);
609 DPRINT("Leave NtUserCreateCursorIconHandle, ret=%i\n",_ret_
);
622 PUNICODE_STRING lpInstName
, // optional
623 PUNICODE_STRING lpResName
, // optional
624 LPDWORD pbpp
, // optional
628 PCURICON_OBJECT CurIcon
;
629 NTSTATUS Status
= STATUS_SUCCESS
;
633 DPRINT("Enter NtUserGetIconInfo\n");
634 UserEnterExclusive();
638 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
642 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
647 RtlCopyMemory(&ii
, &CurIcon
->IconInfo
, sizeof(ICONINFO
));
650 ii
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
651 ii
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
657 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
);
660 colorBpp
= BitsPerFormat(psurfBmp
->SurfObj
.iBitmapFormat
);
661 SURFACE_UnlockSurface(psurfBmp
);
668 ProbeForWrite(IconInfo
, sizeof(ICONINFO
), 1);
669 RtlCopyMemory(IconInfo
, &ii
, sizeof(ICONINFO
));
673 ProbeForWrite(pbpp
, sizeof(DWORD
), 1);
677 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
679 Status
= _SEH2_GetExceptionCode();
683 if (NT_SUCCESS(Status
))
686 SetLastNtError(Status
);
688 UserDereferenceObject(CurIcon
);
691 DPRINT("Leave NtUserGetIconInfo, ret=%i\n", Ret
);
706 PLONG plcx
, // &size.cx
707 PLONG plcy
) // &size.cy
709 PCURICON_OBJECT CurIcon
;
710 NTSTATUS Status
= STATUS_SUCCESS
;
713 DPRINT("Enter NtUserGetIconSize\n");
714 UserEnterExclusive();
716 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
723 ProbeForWrite(plcx
, sizeof(LONG
), 1);
724 RtlCopyMemory(plcx
, &CurIcon
->Size
.cx
, sizeof(LONG
));
725 ProbeForWrite(plcy
, sizeof(LONG
), 1);
726 RtlCopyMemory(plcy
, &CurIcon
->Size
.cy
, sizeof(LONG
));
728 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
730 Status
= _SEH2_GetExceptionCode();
734 if (NT_SUCCESS(Status
))
737 SetLastNtError(Status
); // maybe not, test this
739 UserDereferenceObject(CurIcon
);
742 DPRINT("Leave NtUserGetIconSize, ret=%i\n", bRet
);
753 NtUserGetCursorFrameInfo(
774 PSYSTEM_CURSORINFO CurInfo
;
775 NTSTATUS Status
= STATUS_SUCCESS
;
776 PCURICON_OBJECT CurIcon
;
778 DECLARE_RETURN(BOOL
);
780 DPRINT("Enter NtUserGetCursorInfo\n");
781 UserEnterExclusive();
783 CurInfo
= IntGetSysCursorInfo();
784 CurIcon
= (PCURICON_OBJECT
)CurInfo
->CurrentCursorObject
;
786 SafeCi
.cbSize
= sizeof(CURSORINFO
);
787 SafeCi
.flags
= ((CurInfo
->ShowingCursor
&& CurIcon
) ? CURSOR_SHOWING
: 0);
788 SafeCi
.hCursor
= (CurIcon
? (HCURSOR
)CurIcon
->Self
: (HCURSOR
)0);
790 SafeCi
.ptScreenPos
= gpsi
->ptCursor
;
794 if (pci
->cbSize
== sizeof(CURSORINFO
))
796 ProbeForWrite(pci
, sizeof(CURSORINFO
), 1);
797 RtlCopyMemory(pci
, &SafeCi
, sizeof(CURSORINFO
));
802 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
805 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
807 Status
= _SEH2_GetExceptionCode();
810 if (!NT_SUCCESS(Status
))
812 SetLastNtError(Status
);
818 DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_
);
828 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
829 PSYSTEM_CURSORINFO CurInfo
;
830 PWINDOW_OBJECT DesktopWindow
= NULL
;
832 CurInfo
= IntGetSysCursorInfo();
834 DesktopWindow
= UserGetDesktopWindow();
837 (prcl
->right
> prcl
->left
) &&
838 (prcl
->bottom
> prcl
->top
) &&
839 DesktopWindow
!= NULL
)
841 CurInfo
->CursorClipInfo
.IsClipped
= TRUE
;
842 CurInfo
->CursorClipInfo
.Left
= max(prcl
->left
, DesktopWindow
->Wnd
->rcWindow
.left
);
843 CurInfo
->CursorClipInfo
.Top
= max(prcl
->top
, DesktopWindow
->Wnd
->rcWindow
.top
);
844 CurInfo
->CursorClipInfo
.Right
= min(prcl
->right
, DesktopWindow
->Wnd
->rcWindow
.right
);
845 CurInfo
->CursorClipInfo
.Bottom
= min(prcl
->bottom
, DesktopWindow
->Wnd
->rcWindow
.bottom
);
847 UserSetCursorPos(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
, FALSE
);
851 CurInfo
->CursorClipInfo
.IsClipped
= FALSE
;
865 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
873 /* Probe and copy rect */
874 ProbeForRead(prcl
, sizeof(RECTL
), 1);
877 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
879 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
880 _SEH2_YIELD(return FALSE
;)
887 UserEnterExclusive();
889 /* Call the internal function */
890 bResult
= UserClipCursor(prcl
);
907 PCURICON_OBJECT CurIcon
;
909 DECLARE_RETURN(BOOL
);
911 DPRINT("Enter NtUserDestroyCursorIcon\n");
912 UserEnterExclusive();
914 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
919 ret
= IntDestroyCurIconObject(CurIcon
, FALSE
);
920 /* Note: IntDestroyCurIconObject will remove our reference for us! */
925 DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_
);
936 NtUserFindExistingCursorIcon(
942 PCURICON_OBJECT CurIcon
;
943 HANDLE Ret
= (HANDLE
)0;
944 DECLARE_RETURN(HICON
);
946 DPRINT("Enter NtUserFindExistingCursorIcon\n");
947 UserEnterExclusive();
949 CurIcon
= IntFindExistingCurIconObject(hModule
, hRsrc
, cx
, cy
);
954 // IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
958 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
962 DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_
);
976 /* FIXME - check if process has WINSTA_READATTRIBUTES */
977 PSYSTEM_CURSORINFO CurInfo
;
980 DECLARE_RETURN(BOOL
);
982 DPRINT("Enter NtUserGetClipCursor\n");
983 UserEnterExclusive();
988 CurInfo
= IntGetSysCursorInfo();
989 if (CurInfo
->CursorClipInfo
.IsClipped
)
991 Rect
.left
= CurInfo
->CursorClipInfo
.Left
;
992 Rect
.top
= CurInfo
->CursorClipInfo
.Top
;
993 Rect
.right
= CurInfo
->CursorClipInfo
.Right
;
994 Rect
.bottom
= CurInfo
->CursorClipInfo
.Bottom
;
1000 Rect
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1001 Rect
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1004 Status
= MmCopyToCaller(lpRect
, &Rect
, sizeof(RECT
));
1005 if (!NT_SUCCESS(Status
))
1007 SetLastNtError(Status
);
1014 DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_
);
1028 PCURICON_OBJECT CurIcon
;
1030 DECLARE_RETURN(HCURSOR
);
1032 DPRINT("Enter NtUserSetCursor\n");
1033 UserEnterExclusive();
1037 if (!(CurIcon
= UserGetCurIconObject(hCursor
)))
1047 OldCursor
= UserSetCursor(CurIcon
, FALSE
);
1051 UserDereferenceObject(CurIcon
);
1057 DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_
);
1068 NtUserSetCursorContents(
1070 PICONINFO UnsafeIconInfo
)
1072 PCURICON_OBJECT CurIcon
;
1077 DECLARE_RETURN(BOOL
);
1079 DPRINT("Enter NtUserSetCursorContents\n");
1080 UserEnterExclusive();
1082 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1088 Status
= MmCopyFromCaller(&IconInfo
, UnsafeIconInfo
, sizeof(ICONINFO
));
1089 if (!NT_SUCCESS(Status
))
1091 SetLastNtError(Status
);
1095 /* Delete old bitmaps */
1096 if (CurIcon
->IconInfo
.hbmColor
!= IconInfo
.hbmColor
)
1098 GreDeleteObject(CurIcon
->IconInfo
.hbmColor
);
1100 if (CurIcon
->IconInfo
.hbmMask
!= IconInfo
.hbmMask
)
1102 GreDeleteObject(CurIcon
->IconInfo
.hbmMask
);
1105 /* Copy new IconInfo field */
1106 CurIcon
->IconInfo
= IconInfo
;
1108 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
);
1111 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1112 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1113 SURFACE_UnlockSurface(psurfBmp
);
1114 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
1118 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
);
1122 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1123 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
/ 2;
1125 SURFACE_UnlockSurface(psurfBmp
);
1126 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
1135 UserDereferenceObject(CurIcon
);
1140 DPRINT("Leave NtUserSetCursorContents, ret=%i\n",_ret_
);
1152 NtUserSetCursorIconData(
1155 PUNICODE_STRING pstrResName
,
1156 PICONINFO pIconInfo
)
1158 PCURICON_OBJECT CurIcon
;
1160 NTSTATUS Status
= STATUS_SUCCESS
;
1162 DECLARE_RETURN(BOOL
);
1164 DPRINT("Enter NtUserSetCursorIconData\n");
1165 UserEnterExclusive();
1167 if (!(CurIcon
= UserGetCurIconObject(Handle
)))
1172 CurIcon
->hModule
= hModule
;
1173 CurIcon
->hRsrc
= NULL
; //hRsrc;
1174 CurIcon
->hGroupRsrc
= NULL
; //hGroupRsrc;
1178 ProbeForRead(pIconInfo
, sizeof(ICONINFO
), 1);
1179 RtlCopyMemory(&CurIcon
->IconInfo
, pIconInfo
, sizeof(ICONINFO
));
1181 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(pIconInfo
->hbmMask
);
1182 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(pIconInfo
->hbmColor
);
1184 if (CurIcon
->IconInfo
.hbmColor
)
1186 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
)))
1188 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1189 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1190 SURFACE_UnlockSurface(psurfBmp
);
1191 GDIOBJ_SetOwnership(GdiHandleTable
, CurIcon
->IconInfo
.hbmMask
, NULL
);
1194 if (CurIcon
->IconInfo
.hbmMask
)
1196 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
1198 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
1200 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1201 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1202 SURFACE_UnlockSurface(psurfBmp
);
1205 GDIOBJ_SetOwnership(GdiHandleTable
, CurIcon
->IconInfo
.hbmMask
, NULL
);
1208 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1210 Status
= _SEH2_GetExceptionCode();
1214 if (!NT_SUCCESS(Status
))
1215 SetLastNtError(Status
);
1219 UserDereferenceObject(CurIcon
);
1223 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1230 NtUserSetCursorIconData(
1238 PCURICON_OBJECT CurIcon
;
1242 DECLARE_RETURN(BOOL
);
1244 DPRINT("Enter NtUserSetCursorIconData\n");
1245 UserEnterExclusive();
1247 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1252 CurIcon
->hModule
= hModule
;
1253 CurIcon
->hRsrc
= hRsrc
;
1254 CurIcon
->hGroupRsrc
= hGroupRsrc
;
1259 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
.fIcon
, fIcon
, sizeof(BOOL
));
1260 if (!NT_SUCCESS(Status
))
1262 SetLastNtError(Status
);
1274 Status
= MmCopyFromCaller(&SafeHotspot
, Hotspot
, sizeof(POINT
));
1275 if (NT_SUCCESS(Status
))
1277 CurIcon
->IconInfo
.xHotspot
= SafeHotspot
.x
;
1278 CurIcon
->IconInfo
.yHotspot
= SafeHotspot
.y
;
1283 SetLastNtError(Status
);
1286 if (!fIcon
&& !Hotspot
)
1292 UserDereferenceObject(CurIcon
);
1297 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1308 NtUserSetSystemCursor(
1315 /* Mostly inspired from wine code */
1321 PCURICON_OBJECT pIcon
,
1325 HBRUSH hbrFlickerFreeDraw
,
1329 HBITMAP hbmMask
, hbmColor
;
1330 BITMAP bmpColor
, bm
;
1333 INT iOldBkColor
= 0, iOldTxtColor
= 0;
1335 HDC hMemDC
, hOffDC
= NULL
;
1336 HGDIOBJ hOldOffBrush
= 0;
1337 HGDIOBJ hOldOffBmp
= 0;
1338 HBITMAP hTmpBmp
= 0, hOffBmp
= 0;
1339 BOOL bAlpha
= FALSE
;
1341 hbmMask
= pIcon
->IconInfo
.hbmMask
;
1342 hbmColor
= pIcon
->IconInfo
.hbmColor
;
1345 DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
1347 if (!hbmMask
|| !IntGdiGetObject(hbmMask
, sizeof(BITMAP
), (PVOID
)&bm
))
1352 if (hbmColor
&& !IntGdiGetObject(hbmColor
, sizeof(BITMAP
), (PVOID
)&bmpColor
))
1357 if(!(hMemDC
= NtGdiCreateCompatibleDC(hDc
)))
1359 DPRINT1("NtGdiCreateCompatibleDC failed!\n");
1365 IconSize
.cx
= bmpColor
.bmWidth
;
1366 IconSize
.cy
= bmpColor
.bmHeight
;
1368 else /* take it from mask */
1370 IconSize
.cx
= bm
.bmWidth
;
1371 IconSize
.cy
= bm
.bmHeight
/2;
1375 diFlags
= DI_NORMAL
;
1377 /* NtGdiCreateCompatibleBitmap will create a monochrome bitmap
1378 when cxWidth or cyHeight is 0 */
1380 && (bmpColor
.bmBitsPixel
== 32)
1383 && (diFlags
& DI_IMAGE
))
1385 SURFACE
*psurfOff
= NULL
;
1386 PFN_DIB_GetPixel fnSource_GetPixel
= NULL
;
1389 /* In order to correctly display 32 bit icons Windows first scans the image,
1390 because information about transparency is not stored in any image's headers */
1391 psurfOff
= SURFACE_LockSurface(hbmColor
);
1394 fnSource_GetPixel
= DibFunctionsForBitmapFormat
[psurfOff
->SurfObj
.iBitmapFormat
].DIB_GetPixel
;
1395 if (fnSource_GetPixel
)
1397 for (x
= 0; x
< psurfOff
->SurfObj
.sizlBitmap
.cx
; x
++)
1399 for (y
= 0; y
< psurfOff
->SurfObj
.sizlBitmap
.cy
; y
++)
1401 bAlpha
= ((BYTE
)(fnSource_GetPixel(&psurfOff
->SurfObj
, x
, y
) >> 24) & 0xff);
1409 SURFACE_UnlockSurface(psurfOff
);
1414 cxWidth
= ((diFlags
& DI_DEFAULTSIZE
) ?
1415 UserGetSystemMetrics(SM_CXICON
) : IconSize
.cx
);
1418 cyHeight
= ((diFlags
& DI_DEFAULTSIZE
) ?
1419 UserGetSystemMetrics(SM_CYICON
) : IconSize
.cy
);
1421 DoFlickerFree
= (hbrFlickerFreeDraw
&&
1422 (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw
) == GDI_OBJECT_TYPE_BRUSH
));
1426 hOffDC
= NtGdiCreateCompatibleDC(hDc
);
1429 DPRINT1("NtGdiCreateCompatibleBitmap failed!\n");
1433 hOffBmp
= NtGdiCreateCompatibleBitmap(hDc
, cxWidth
, cyHeight
);
1436 DPRINT1("NtGdiCreateCompatibleBitmap failed!\n");
1439 hOldOffBmp
= NtGdiSelectBitmap(hOffDC
, hOffBmp
);
1440 hOldOffBrush
= NtGdiSelectBrush(hOffDC
, hbrFlickerFreeDraw
);
1441 NtGdiPatBlt(hOffDC
, 0, 0, cxWidth
, cyHeight
, PATCOPY
);
1442 NtGdiSelectBrush(hOffDC
, hOldOffBrush
);
1446 /* Set Background/foreground colors */
1447 iOldTxtColor
= IntGdiSetTextColor(hDc
, 0); //black
1448 iOldBkColor
= IntGdiSetBkColor(hDc
, 0x00FFFFFF); //white
1452 if (hbmMask
&& (diFlags
& DI_MASK
) && !bAlpha
)
1454 hTmpBmp
= NtGdiSelectBitmap(hMemDC
, hbmMask
);
1455 NtGdiStretchBlt(hOffDC
? hOffDC
: hDc
,
1467 NtGdiSelectBitmap(hMemDC
, hTmpBmp
);
1470 if(diFlags
& DI_IMAGE
)
1474 BLENDFUNCTION pixelblend
= { AC_SRC_OVER
, 0, 255, AC_SRC_ALPHA
};
1476 BYTE Red
, Green
, Blue
, Alpha
;
1481 HBITMAP hMemBmp
= NULL
;
1483 pBits
= ExAllocatePoolWithTag(PagedPool
,
1484 bmpColor
.bmWidthBytes
* abs(bmpColor
.bmHeight
),
1492 hMemBmp
= BITMAP_CopyBitmap(hbmColor
);
1495 DPRINT1("BITMAP_CopyBitmap failed!");
1499 psurf
= SURFACE_LockSurface(hMemBmp
);
1502 DPRINT1("SURFACE_LockSurface failed!\n");
1505 /* get color bits */
1506 IntGetBitmapBits(psurf
,
1507 bmpColor
.bmWidthBytes
* abs(bmpColor
.bmHeight
),
1510 /* premultiply with the alpha channel value */
1511 for (i
= 0; i
< cyHeight
; i
++)
1513 for (j
= 0; j
< cxWidth
; j
++)
1515 Pixel
= *(DWORD
*)(pBits
+ Count
);
1517 Alpha
= ((BYTE
)(Pixel
>> 24) & 0xff);
1519 Red
= (((BYTE
)(Pixel
>> 0)) * Alpha
) / 0xff;
1520 Green
= (((BYTE
)(Pixel
>> 8)) * Alpha
) / 0xff;
1521 Blue
= (((BYTE
)(Pixel
>> 16)) * Alpha
) / 0xff;
1523 *(DWORD
*)(pBits
+ Count
) = (DWORD
)(Red
| (Green
<< 8) | (Blue
<< 16) | (Alpha
<< 24));
1525 Count
+= sizeof(DWORD
);
1530 IntSetBitmapBits(psurf
,
1531 bmpColor
.bmWidthBytes
* abs(bmpColor
.bmHeight
),
1533 SURFACE_UnlockSurface(psurf
);
1535 hTmpBmp
= NtGdiSelectBitmap(hMemDC
, hMemBmp
);
1537 NtGdiAlphaBlend(hOffDC
? hOffDC
: hDc
,
1549 NtGdiSelectBitmap(hMemDC
, hTmpBmp
);
1551 if(pBits
) ExFreePoolWithTag(pBits
, TAG_BITMAP
);
1552 if(hMemBmp
) NtGdiDeleteObjectApp(hMemBmp
);
1556 DWORD rop
= (diFlags
& DI_MASK
) ? SRCINVERT
: SRCCOPY
;
1557 hTmpBmp
= NtGdiSelectBitmap(hMemDC
, hbmColor
);
1558 NtGdiStretchBlt(hOffDC
? hOffDC
: hDc
,
1570 NtGdiSelectBitmap(hMemDC
, hTmpBmp
);
1576 NtGdiBitBlt(hDc
, xLeft
, yTop
, cxWidth
, cyHeight
, hOffDC
, 0, 0, SRCCOPY
, 0, 0);
1580 IntGdiSetBkColor(hDc
, iOldBkColor
);
1581 IntGdiSetTextColor(hDc
, iOldTxtColor
);
1587 NtGdiDeleteObjectApp(hMemDC
);
1588 if(hOldOffBmp
) NtGdiSelectBitmap(hOffDC
, hOldOffBmp
);
1589 if(hOffDC
) NtGdiDeleteObjectApp(hOffDC
);
1590 if(hOffBmp
) NtGdiDeleteObjectApp(hOffBmp
);
1608 HBRUSH hbrFlickerFreeDraw
,
1610 BOOL bMetaHDC
, // When TRUE, GDI functions need to be handled in User32!
1613 PCURICON_OBJECT pIcon
;
1616 DPRINT("Enter NtUserDrawIconEx\n");
1617 UserEnterExclusive();
1619 if (!(pIcon
= UserGetCurIconObject(hIcon
)))
1621 DPRINT1("UserGetCurIconObject() failed!\n");
1626 Ret
= UserDrawIconEx(hdc
,
1636 UserDereferenceObject(pIcon
);