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
;
48 IntGetCursorLocation(PWINSTATION_OBJECT WinSta
, POINT
*loc
)
50 loc
->x
= gpsi
->ptCursor
.x
;
51 loc
->y
= gpsi
->ptCursor
.y
;
56 /* This function creates a reference for the object! */
57 PCURICON_OBJECT FASTCALL
UserGetCurIconObject(HCURSOR hCurIcon
)
59 PCURICON_OBJECT CurIcon
;
63 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
67 CurIcon
= (PCURICON_OBJECT
)UserReferenceObjectByHandle(hCurIcon
, otCursorIcon
);
70 /* we never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */
71 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
75 ASSERT(USER_BODY_TO_HEADER(CurIcon
)->RefCount
>= 1);
82 PWINSTATION_OBJECT WinSta
,
83 PCURICON_OBJECT NewCursor
,
86 PSYSTEM_CURSORINFO CurInfo
;
87 PCURICON_OBJECT OldCursor
;
88 HCURSOR hOldCursor
= (HCURSOR
)0;
92 CurInfo
= IntGetSysCursorInfo(WinSta
);
93 OldCursor
= CurInfo
->CurrentCursorObject
;
96 hOldCursor
= (HCURSOR
)OldCursor
->Self
;
99 /* Is the new cursor the same as the old cursor? */
100 if (OldCursor
== NewCursor
)
102 /* Nothing to to do in this case */
106 /* Get the screen DC */
107 if(!(hdcScreen
= IntGetScreenDC()))
112 /* Do we have a new cursor? */
115 UserReferenceObject(NewCursor
);
117 CurInfo
->ShowingCursor
= CURSOR_SHOWING
;
118 CurInfo
->CurrentCursorObject
= NewCursor
;
120 /* Call GDI to set the new screen cursor */
121 bResult
= GreSetPointerShape(hdcScreen
,
122 NewCursor
->IconInfo
.hbmMask
,
123 NewCursor
->IconInfo
.hbmColor
,
124 NewCursor
->IconInfo
.xHotspot
,
125 NewCursor
->IconInfo
.yHotspot
,
133 /* Check if were diplaying a cursor */
134 if (OldCursor
&& CurInfo
->ShowingCursor
)
136 /* Remove the cursor */
137 GreMovePointer(hdcScreen
, -1, -1);
138 DPRINT("Removing pointer!\n");
141 CurInfo
->CurrentCursorObject
= NULL
;
142 CurInfo
->ShowingCursor
= 0;
145 /* OldCursor is not in use anymore */
148 UserDereferenceObject(OldCursor
);
151 /* Return handle of the old cursor */
157 IntSetupCurIconHandles(PWINSTATION_OBJECT WinSta
)
159 ExInitializePagedLookasideList(&gProcessLookasideList
,
163 sizeof(CURICON_PROCESS
),
166 InitializeListHead(&gCurIconList
);
172 * We have to register that this object is in use by the current
173 * process. The only way to do that seems to be to walk the list
174 * of cursor/icon objects starting at W32Process->CursorIconListHead.
175 * If the object is already present in the list, we don't have to do
176 * anything, if it's not present we add it and inc the ProcessCount
177 * in the object. Having to walk the list kind of sucks, but that's
180 static BOOLEAN FASTCALL
181 ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon
)
183 PPROCESSINFO Win32Process
;
184 PCURICON_PROCESS Current
;
186 Win32Process
= PsGetCurrentProcessWin32Process();
188 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
190 if (Current
->Process
== Win32Process
)
192 /* Already registered for this process */
197 /* Not registered yet */
198 Current
= ExAllocateFromPagedLookasideList(&gProcessLookasideList
);
203 InsertHeadList(&CurIcon
->ProcessList
, &Current
->ListEntry
);
204 Current
->Process
= Win32Process
;
209 PCURICON_OBJECT FASTCALL
210 IntFindExistingCurIconObject(PWINSTATION_OBJECT WinSta
, HMODULE hModule
,
211 HRSRC hRsrc
, LONG cx
, LONG cy
)
213 PCURICON_OBJECT CurIcon
;
215 LIST_FOR_EACH(CurIcon
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
218 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
219 // UserReferenceObject( CurIcon);
221 if ((CurIcon
->hModule
== hModule
) && (CurIcon
->hRsrc
== hRsrc
))
223 if (cx
&& ((cx
!= CurIcon
->Size
.cx
) || (cy
!= CurIcon
->Size
.cy
)))
225 // UserDereferenceObject(CurIcon);
228 if (! ReferenceCurIconByProcess(CurIcon
))
236 // UserDereferenceObject(CurIcon);
243 PCURICON_OBJECT FASTCALL
244 IntCreateCurIconHandle(PWINSTATION_OBJECT WinSta
)
246 PCURICON_OBJECT CurIcon
;
249 CurIcon
= UserCreateObject(gHandleTable
, &hCurIcon
, otCursorIcon
, sizeof(CURICON_OBJECT
));
253 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
257 CurIcon
->Self
= hCurIcon
;
258 InitializeListHead(&CurIcon
->ProcessList
);
260 if (! ReferenceCurIconByProcess(CurIcon
))
262 DPRINT1("Failed to add process\n");
263 UserDeleteObject(hCurIcon
, otCursorIcon
);
264 UserDereferenceObject(CurIcon
);
268 InsertHeadList(&gCurIconList
, &CurIcon
->ListEntry
);
274 IntDestroyCurIconObject(PWINSTATION_OBJECT WinSta
, PCURICON_OBJECT CurIcon
, BOOL ProcessCleanup
)
276 PSYSTEM_CURSORINFO CurInfo
;
277 HBITMAP bmpMask
, bmpColor
;
279 PCURICON_PROCESS Current
= NULL
;
280 PPROCESSINFO W32Process
= PsGetCurrentProcessWin32Process();
282 /* Private objects can only be destroyed by their own process */
283 if (NULL
== CurIcon
->hModule
)
285 ASSERT(CurIcon
->ProcessList
.Flink
->Flink
== &CurIcon
->ProcessList
);
286 Current
= CONTAINING_RECORD(CurIcon
->ProcessList
.Flink
, CURICON_PROCESS
, ListEntry
);
287 if (Current
->Process
!= W32Process
)
289 DPRINT1("Trying to destroy private icon/cursor of another process\n");
293 else if (! ProcessCleanup
)
295 DPRINT("Trying to destroy shared icon/cursor\n");
299 /* Now find this process in the list of processes referencing this object and
300 remove it from that list */
301 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
303 if (Current
->Process
== W32Process
)
305 RemoveEntryList(&Current
->ListEntry
);
310 ExFreeToPagedLookasideList(&gProcessLookasideList
, Current
);
312 /* If there are still processes referencing this object we can't destroy it yet */
313 if (! IsListEmpty(&CurIcon
->ProcessList
))
319 if (! ProcessCleanup
)
321 RemoveEntryList(&CurIcon
->ListEntry
);
324 CurInfo
= IntGetSysCursorInfo(WinSta
);
326 if (CurInfo
->CurrentCursorObject
== CurIcon
)
328 /* Hide the cursor if we're destroying the current cursor */
329 IntSetCursor(WinSta
, NULL
, TRUE
);
332 bmpMask
= CurIcon
->IconInfo
.hbmMask
;
333 bmpColor
= CurIcon
->IconInfo
.hbmColor
;
338 GDIOBJ_SetOwnership(bmpMask
, PsGetCurrentProcess());
339 GreDeleteObject(bmpMask
);
340 CurIcon
->IconInfo
.hbmMask
= NULL
;
344 GDIOBJ_SetOwnership(bmpColor
, PsGetCurrentProcess());
345 GreDeleteObject(bmpColor
);
346 CurIcon
->IconInfo
.hbmColor
= NULL
;
349 /* We were given a pointer, no need to keep the reference anylonger! */
350 UserDereferenceObject(CurIcon
);
351 Ret
= UserDeleteObject(CurIcon
->Self
, otCursorIcon
);
357 IntCleanupCurIcons(struct _EPROCESS
*Process
, PPROCESSINFO Win32Process
)
359 PWINSTATION_OBJECT WinSta
;
360 PCURICON_OBJECT CurIcon
, tmp
;
361 PCURICON_PROCESS ProcessData
;
363 WinSta
= IntGetWinStaObj();
369 LIST_FOR_EACH_SAFE(CurIcon
, tmp
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
371 UserReferenceObject(CurIcon
);
372 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon)))
374 LIST_FOR_EACH(ProcessData
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
376 if (Win32Process
== ProcessData
->Process
)
378 RemoveEntryList(&CurIcon
->ListEntry
);
379 IntDestroyCurIconObject(WinSta
, CurIcon
, TRUE
);
385 // UserDereferenceObject(Object);
390 UserDereferenceObject(CurIcon
);
394 ObDereferenceObject(WinSta
);
402 NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL
, BOOL Indirect
)
404 PCURICON_OBJECT CurIcon
;
405 PWINSTATION_OBJECT WinSta
;
409 DECLARE_RETURN(HANDLE
);
411 DPRINT("Enter NtUserCreateCursorIconHandle\n");
412 UserEnterExclusive();
414 WinSta
= IntGetWinStaObj();
420 if (!(CurIcon
= IntCreateCurIconHandle(WinSta
)))
422 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
423 ObDereferenceObject(WinSta
);
431 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
, IconInfo
, sizeof(ICONINFO
));
432 if (NT_SUCCESS(Status
))
434 /* Copy bitmaps and size info */
438 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
439 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
441 if (CurIcon
->IconInfo
.hbmColor
&&
442 (psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
)))
444 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
445 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
446 SURFACE_UnlockSurface(psurfBmp
);
447 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
449 if (CurIcon
->IconInfo
.hbmMask
&&
450 (psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
452 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
454 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
455 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
>> 1;
457 SURFACE_UnlockSurface(psurfBmp
);
458 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
461 /* Calculate icon hotspot */
462 if (CurIcon
->IconInfo
.fIcon
== TRUE
)
464 CurIcon
->IconInfo
.xHotspot
= CurIcon
->Size
.cx
>> 1;
465 CurIcon
->IconInfo
.yHotspot
= CurIcon
->Size
.cy
>> 1;
470 SetLastNtError(Status
);
471 /* FIXME - Don't exit here */
475 UserDereferenceObject(CurIcon
);
476 ObDereferenceObject(WinSta
);
480 DPRINT("Leave NtUserCreateCursorIconHandle, ret=%i\n",_ret_
);
493 PUNICODE_STRING lpInstName
, // optional
494 PUNICODE_STRING lpResName
, // optional
495 LPDWORD pbpp
, // optional
499 PCURICON_OBJECT CurIcon
;
500 NTSTATUS Status
= STATUS_SUCCESS
;
504 DPRINT("Enter NtUserGetIconInfo\n");
505 UserEnterExclusive();
509 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
513 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
518 RtlCopyMemory(&ii
, &CurIcon
->IconInfo
, sizeof(ICONINFO
));
521 ii
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
522 ii
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
528 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
);
531 colorBpp
= BitsPerFormat(psurfBmp
->SurfObj
.iBitmapFormat
);
532 SURFACE_UnlockSurface(psurfBmp
);
539 ProbeForWrite(IconInfo
, sizeof(ICONINFO
), 1);
540 RtlCopyMemory(IconInfo
, &ii
, sizeof(ICONINFO
));
544 ProbeForWrite(pbpp
, sizeof(DWORD
), 1);
548 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
550 Status
= _SEH2_GetExceptionCode();
554 if (NT_SUCCESS(Status
))
557 SetLastNtError(Status
);
559 UserDereferenceObject(CurIcon
);
562 DPRINT("Leave NtUserGetIconInfo, ret=%i\n", Ret
);
577 PLONG plcx
, // &size.cx
578 PLONG plcy
) // &size.cy
580 PCURICON_OBJECT CurIcon
;
581 NTSTATUS Status
= STATUS_SUCCESS
;
584 DPRINT("Enter NtUserGetIconSize\n");
585 UserEnterExclusive();
587 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
594 ProbeForWrite(plcx
, sizeof(LONG
), 1);
595 RtlCopyMemory(plcx
, &CurIcon
->Size
.cx
, sizeof(LONG
));
596 ProbeForWrite(plcy
, sizeof(LONG
), 1);
597 RtlCopyMemory(plcy
, &CurIcon
->Size
.cy
, sizeof(LONG
));
599 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
601 Status
= _SEH2_GetExceptionCode();
605 if (NT_SUCCESS(Status
))
608 SetLastNtError(Status
); // maybe not, test this
610 UserDereferenceObject(CurIcon
);
613 DPRINT("Leave NtUserGetIconSize, ret=%i\n", bRet
);
624 NtUserGetCursorFrameInfo(
645 PSYSTEM_CURSORINFO CurInfo
;
646 PWINSTATION_OBJECT WinSta
;
647 NTSTATUS Status
= STATUS_SUCCESS
;
648 PCURICON_OBJECT CurIcon
;
650 DECLARE_RETURN(BOOL
);
652 DPRINT("Enter NtUserGetCursorInfo\n");
653 UserEnterExclusive();
655 WinSta
= IntGetWinStaObj();
661 CurInfo
= IntGetSysCursorInfo(WinSta
);
662 CurIcon
= (PCURICON_OBJECT
)CurInfo
->CurrentCursorObject
;
664 SafeCi
.cbSize
= sizeof(CURSORINFO
);
665 SafeCi
.flags
= ((CurInfo
->ShowingCursor
&& CurIcon
) ? CURSOR_SHOWING
: 0);
666 SafeCi
.hCursor
= (CurIcon
? (HCURSOR
)CurIcon
->Self
: (HCURSOR
)0);
668 IntGetCursorLocation(WinSta
, &SafeCi
.ptScreenPos
);
672 if (pci
->cbSize
== sizeof(CURSORINFO
))
674 ProbeForWrite(pci
, sizeof(CURSORINFO
), 1);
675 RtlCopyMemory(pci
, &SafeCi
, sizeof(CURSORINFO
));
680 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
683 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
685 Status
= _SEH2_GetExceptionCode();
688 if (!NT_SUCCESS(Status
))
690 SetLastNtError(Status
);
693 ObDereferenceObject(WinSta
);
697 DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_
);
711 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
713 PWINSTATION_OBJECT WinSta
;
714 PSYSTEM_CURSORINFO CurInfo
;
716 PWINDOW_OBJECT DesktopWindow
= NULL
;
717 POINT MousePos
= {0};
718 DECLARE_RETURN(BOOL
);
720 DPRINT("Enter NtUserClipCursor\n");
721 UserEnterExclusive();
723 WinSta
= IntGetWinStaObj();
729 if (NULL
!= UnsafeRect
&& ! NT_SUCCESS(MmCopyFromCaller(&Rect
, UnsafeRect
, sizeof(RECT
))))
731 ObDereferenceObject(WinSta
);
732 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
736 CurInfo
= IntGetSysCursorInfo(WinSta
);
737 IntGetCursorLocation(WinSta
, &MousePos
);
739 if (WinSta
->ActiveDesktop
)
740 DesktopWindow
= UserGetWindowObject(WinSta
->ActiveDesktop
->DesktopWindow
);
742 if ((Rect
.right
> Rect
.left
) && (Rect
.bottom
> Rect
.top
)
743 && DesktopWindow
&& UnsafeRect
!= NULL
)
747 CurInfo
->CursorClipInfo
.IsClipped
= TRUE
;
748 CurInfo
->CursorClipInfo
.Left
= max(Rect
.left
, DesktopWindow
->Wnd
->rcWindow
.left
);
749 CurInfo
->CursorClipInfo
.Top
= max(Rect
.top
, DesktopWindow
->Wnd
->rcWindow
.top
);
750 CurInfo
->CursorClipInfo
.Right
= min(Rect
.right
- 1, DesktopWindow
->Wnd
->rcWindow
.right
- 1);
751 CurInfo
->CursorClipInfo
.Bottom
= min(Rect
.bottom
- 1, DesktopWindow
->Wnd
->rcWindow
.bottom
- 1);
756 mi
.dwFlags
= MOUSEEVENTF_ABSOLUTE
| MOUSEEVENTF_MOVE
;
764 CurInfo
->CursorClipInfo
.IsClipped
= FALSE
;
765 ObDereferenceObject(WinSta
);
770 DPRINT("Leave NtUserClipCursor, ret=%i\n",_ret_
);
785 PWINSTATION_OBJECT WinSta
;
786 PCURICON_OBJECT CurIcon
;
788 DECLARE_RETURN(BOOL
);
790 DPRINT("Enter NtUserDestroyCursorIcon\n");
791 UserEnterExclusive();
793 WinSta
= IntGetWinStaObj();
799 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
801 ObDereferenceObject(WinSta
);
805 ret
= IntDestroyCurIconObject(WinSta
, CurIcon
, FALSE
);
806 /* Note: IntDestroyCurIconObject will remove our reference for us! */
808 ObDereferenceObject(WinSta
);
812 DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_
);
823 NtUserFindExistingCursorIcon(
829 PCURICON_OBJECT CurIcon
;
830 PWINSTATION_OBJECT WinSta
;
831 HANDLE Ret
= (HANDLE
)0;
832 DECLARE_RETURN(HICON
);
834 DPRINT("Enter NtUserFindExistingCursorIcon\n");
835 UserEnterExclusive();
837 WinSta
= IntGetWinStaObj();
843 CurIcon
= IntFindExistingCurIconObject(WinSta
, hModule
, hRsrc
, cx
, cy
);
848 // IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
849 ObDereferenceObject(WinSta
);
853 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
854 ObDereferenceObject(WinSta
);
858 DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_
);
872 /* FIXME - check if process has WINSTA_READATTRIBUTES */
873 PSYSTEM_CURSORINFO CurInfo
;
874 PWINSTATION_OBJECT WinSta
;
877 DECLARE_RETURN(BOOL
);
879 DPRINT("Enter NtUserGetClipCursor\n");
880 UserEnterExclusive();
885 WinSta
= IntGetWinStaObj();
891 CurInfo
= IntGetSysCursorInfo(WinSta
);
892 if (CurInfo
->CursorClipInfo
.IsClipped
)
894 Rect
.left
= CurInfo
->CursorClipInfo
.Left
;
895 Rect
.top
= CurInfo
->CursorClipInfo
.Top
;
896 Rect
.right
= CurInfo
->CursorClipInfo
.Right
;
897 Rect
.bottom
= CurInfo
->CursorClipInfo
.Bottom
;
903 Rect
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
904 Rect
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
907 Status
= MmCopyToCaller(lpRect
, &Rect
, sizeof(RECT
));
908 if (!NT_SUCCESS(Status
))
910 ObDereferenceObject(WinSta
);
911 SetLastNtError(Status
);
915 ObDereferenceObject(WinSta
);
920 DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_
);
934 PCURICON_OBJECT CurIcon
;
936 PWINSTATION_OBJECT WinSta
;
937 DECLARE_RETURN(HCURSOR
);
939 DPRINT("Enter NtUserSetCursor\n");
940 UserEnterExclusive();
942 WinSta
= IntGetWinStaObj();
950 if (!(CurIcon
= UserGetCurIconObject(hCursor
)))
952 ObDereferenceObject(WinSta
);
961 OldCursor
= IntSetCursor(WinSta
, CurIcon
, FALSE
);
965 UserDereferenceObject(CurIcon
);
967 ObDereferenceObject(WinSta
);
972 DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_
);
983 NtUserSetCursorContents(
985 PICONINFO UnsafeIconInfo
)
987 PCURICON_OBJECT CurIcon
;
990 PWINSTATION_OBJECT WinSta
;
993 DECLARE_RETURN(BOOL
);
995 DPRINT("Enter NtUserSetCursorContents\n");
996 UserEnterExclusive();
998 WinSta
= IntGetWinStaObj();
1004 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1006 ObDereferenceObject(WinSta
);
1011 Status
= MmCopyFromCaller(&IconInfo
, UnsafeIconInfo
, sizeof(ICONINFO
));
1012 if (!NT_SUCCESS(Status
))
1014 SetLastNtError(Status
);
1018 /* Delete old bitmaps */
1019 if (CurIcon
->IconInfo
.hbmColor
!= IconInfo
.hbmColor
)
1021 GreDeleteObject(CurIcon
->IconInfo
.hbmColor
);
1023 if (CurIcon
->IconInfo
.hbmMask
!= IconInfo
.hbmMask
)
1025 GreDeleteObject(CurIcon
->IconInfo
.hbmMask
);
1028 /* Copy new IconInfo field */
1029 CurIcon
->IconInfo
= IconInfo
;
1031 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
);
1034 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1035 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1036 SURFACE_UnlockSurface(psurfBmp
);
1037 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
1041 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
);
1045 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1046 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
/ 2;
1048 SURFACE_UnlockSurface(psurfBmp
);
1049 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
1058 UserDereferenceObject(CurIcon
);
1060 ObDereferenceObject(WinSta
);
1064 DPRINT("Leave NtUserSetCursorContents, ret=%i\n",_ret_
);
1076 NtUserSetCursorIconData(
1079 PUNICODE_STRING pstrResName
,
1080 PICONINFO pIconInfo
)
1082 PCURICON_OBJECT CurIcon
;
1083 PWINSTATION_OBJECT WinSta
;
1085 NTSTATUS Status
= STATUS_SUCCESS
;
1087 DECLARE_RETURN(BOOL
);
1089 DPRINT("Enter NtUserSetCursorIconData\n");
1090 UserEnterExclusive();
1092 WinSta
= IntGetWinStaObj();
1098 if (!(CurIcon
= UserGetCurIconObject(Handle
)))
1100 ObDereferenceObject(WinSta
);
1104 CurIcon
->hModule
= hModule
;
1105 CurIcon
->hRsrc
= NULL
; //hRsrc;
1106 CurIcon
->hGroupRsrc
= NULL
; //hGroupRsrc;
1110 ProbeForRead(pIconInfo
, sizeof(ICONINFO
), 1);
1111 RtlCopyMemory(&CurIcon
->IconInfo
, pIconInfo
, sizeof(ICONINFO
));
1113 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(pIconInfo
->hbmMask
);
1114 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(pIconInfo
->hbmColor
);
1116 if (CurIcon
->IconInfo
.hbmColor
)
1118 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
)))
1120 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1121 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1122 SURFACE_UnlockSurface(psurfBmp
);
1123 GDIOBJ_SetOwnership(GdiHandleTable
, CurIcon
->IconInfo
.hbmMask
, NULL
);
1126 if (CurIcon
->IconInfo
.hbmMask
)
1128 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
1130 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
1132 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1133 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1134 SURFACE_UnlockSurface(psurfBmp
);
1137 GDIOBJ_SetOwnership(GdiHandleTable
, CurIcon
->IconInfo
.hbmMask
, NULL
);
1140 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1142 Status
= _SEH2_GetExceptionCode();
1146 if (!NT_SUCCESS(Status
))
1147 SetLastNtError(Status
);
1151 UserDereferenceObject(CurIcon
);
1152 ObDereferenceObject(WinSta
);
1156 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1163 NtUserSetCursorIconData(
1171 PCURICON_OBJECT CurIcon
;
1172 PWINSTATION_OBJECT WinSta
;
1176 DECLARE_RETURN(BOOL
);
1178 DPRINT("Enter NtUserSetCursorIconData\n");
1179 UserEnterExclusive();
1181 WinSta
= IntGetWinStaObj();
1187 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1189 ObDereferenceObject(WinSta
);
1193 CurIcon
->hModule
= hModule
;
1194 CurIcon
->hRsrc
= hRsrc
;
1195 CurIcon
->hGroupRsrc
= hGroupRsrc
;
1200 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
.fIcon
, fIcon
, sizeof(BOOL
));
1201 if (!NT_SUCCESS(Status
))
1203 SetLastNtError(Status
);
1215 Status
= MmCopyFromCaller(&SafeHotspot
, Hotspot
, sizeof(POINT
));
1216 if (NT_SUCCESS(Status
))
1218 CurIcon
->IconInfo
.xHotspot
= SafeHotspot
.x
;
1219 CurIcon
->IconInfo
.yHotspot
= SafeHotspot
.y
;
1224 SetLastNtError(Status
);
1227 if (!fIcon
&& !Hotspot
)
1233 UserDereferenceObject(CurIcon
);
1234 ObDereferenceObject(WinSta
);
1239 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1250 NtUserSetSystemCursor(
1262 PCURICON_OBJECT pIcon
,
1266 HBRUSH hbrFlickerFreeDraw
,
1270 HBITMAP hbmMask
, hbmColor
;
1271 BITMAP bmpMask
, bmpColor
;
1276 HGDIOBJ hOldOffBrush
= 0;
1277 HGDIOBJ hOldOffBmp
= 0;
1280 HGDIOBJ hOldMask
= NULL
;
1282 HGDIOBJ hOldImage
= NULL
;
1283 BOOL bAlpha
= FALSE
;
1285 hbmMask
= pIcon
->IconInfo
.hbmMask
;
1286 hbmColor
= pIcon
->IconInfo
.hbmColor
;
1289 DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
1291 if (!hbmMask
|| !IntGdiGetObject(hbmMask
, sizeof(BITMAP
), (PVOID
)&bmpMask
))
1296 if (hbmColor
&& !IntGdiGetObject(hbmColor
, sizeof(BITMAP
), (PVOID
)&bmpColor
))
1303 IconSize
.cx
= bmpColor
.bmWidth
;
1304 IconSize
.cy
= bmpColor
.bmHeight
;
1308 IconSize
.cx
= bmpMask
.bmWidth
;
1309 IconSize
.cy
= bmpMask
.bmHeight
/ 2;
1312 /* NtGdiCreateCompatibleBitmap will create a monochrome bitmap
1313 when cxWidth or cyHeight is 0 */
1314 if ((bmpColor
.bmBitsPixel
== 32) && (cxWidth
!= 0) && (cyHeight
!= 0))
1316 SURFACE
*psurfOff
= NULL
;
1317 PFN_DIB_GetPixel fnSource_GetPixel
= NULL
;
1320 /* In order to correctly display 32 bit icons Windows first scans the image,
1321 because information about transparency is not stored in any image's headers */
1322 psurfOff
= SURFACE_LockSurface(hbmColor
? hbmColor
: hbmMask
);
1325 fnSource_GetPixel
= DibFunctionsForBitmapFormat
[psurfOff
->SurfObj
.iBitmapFormat
].DIB_GetPixel
;
1326 if (fnSource_GetPixel
)
1328 for (x
= 0; x
< psurfOff
->SurfObj
.sizlBitmap
.cx
; x
++)
1330 for (y
= 0; y
< psurfOff
->SurfObj
.sizlBitmap
.cy
; y
++)
1332 bAlpha
= ((BYTE
)(fnSource_GetPixel(&psurfOff
->SurfObj
, x
, y
) >> 24) & 0xff);
1340 SURFACE_UnlockSurface(psurfOff
);
1345 diFlags
= DI_NORMAL
;
1348 cxWidth
= ((diFlags
& DI_DEFAULTSIZE
) ?
1349 UserGetSystemMetrics(SM_CXICON
) : IconSize
.cx
);
1352 cyHeight
= ((diFlags
& DI_DEFAULTSIZE
) ?
1353 UserGetSystemMetrics(SM_CYICON
) : IconSize
.cy
);
1355 DoFlickerFree
= (hbrFlickerFreeDraw
&&
1356 (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw
) == GDI_OBJECT_TYPE_BRUSH
));
1358 if (DoFlickerFree
|| bAlpha
)
1362 SURFACE
*psurfOff
= NULL
;
1365 r
.bottom
= cyHeight
;
1367 hdcOff
= NtGdiCreateCompatibleDC(hDc
);
1370 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1374 hbmOff
= NtGdiCreateCompatibleBitmap(hDc
, cxWidth
, cyHeight
);
1377 DPRINT1("NtGdiCreateCompatibleBitmap() failed!\n");
1381 /* make sure we have a 32 bit offscreen bitmap
1382 otherwise we can't do alpha blending */
1383 psurfOff
= SURFACE_LockSurface(hbmOff
);
1384 if (psurfOff
== NULL
)
1386 DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
1389 BITMAP_GetObject(psurfOff
, sizeof(BITMAP
), (PVOID
)&bm
);
1391 if (bm
.bmBitsPixel
!= 32)
1394 SURFACE_UnlockSurface(psurfOff
);
1396 hOldOffBmp
= NtGdiSelectBitmap(hdcOff
, hbmOff
);
1399 DPRINT1("NtGdiSelectBitmap() failed!\n");
1405 hOldOffBrush
= NtGdiSelectBrush(hdcOff
, hbrFlickerFreeDraw
);
1408 DPRINT1("NtGdiSelectBrush() failed!\n");
1412 NtGdiPatBlt(hdcOff
, 0, 0, r
.right
, r
.bottom
, PATCOPY
);
1418 if (diFlags
& DI_IMAGE
)
1420 hdcImage
= NtGdiCreateCompatibleDC(hDc
);
1423 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1426 hOldImage
= NtGdiSelectBitmap(hdcImage
, (hbmColor
? hbmColor
: hbmMask
));
1429 DPRINT("NtGdiSelectBitmap() failed!\n");
1434 /* If DI_IMAGE flag is specified and hbmMask exists, then always use mask for drawing */
1435 if (diFlags
& DI_MASK
|| (diFlags
& DI_IMAGE
&& hbmMask
))
1437 hdcMask
= NtGdiCreateCompatibleDC(hDc
);
1440 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1444 hOldMask
= NtGdiSelectBitmap(hdcMask
, hbmMask
);
1447 DPRINT("NtGdiSelectBitmap() failed!\n");
1452 if (hdcMask
|| hdcImage
)
1454 GreStretchBltMask(hdcOff
,
1455 (DoFlickerFree
|| bAlpha
) ? 0 : xLeft
,
1456 (DoFlickerFree
|| bAlpha
) ? 0 : yTop
,
1459 hdcImage
? hdcImage
: hdcMask
,
1461 ((diFlags
& DI_MASK
&& !(diFlags
& DI_IMAGE
)) ||
1462 (diFlags
& DI_IMAGE
&& hbmColor
) ? 0 : IconSize
.cy
),
1467 hdcImage
? hdcMask
: NULL
);
1470 if (hOldMask
) NtGdiSelectBitmap(hdcMask
, hOldMask
);
1471 if (hOldImage
) NtGdiSelectBitmap(hdcImage
, hOldImage
);
1472 if (hdcImage
) NtGdiDeleteObjectApp(hdcImage
);
1473 if (hdcMask
) NtGdiDeleteObjectApp(hdcMask
);
1478 SURFACE
*psurfOff
= NULL
;
1480 BLENDFUNCTION BlendFunc
;
1482 BYTE Red
, Green
, Blue
, Alpha
;
1486 psurfOff
= SURFACE_LockSurface(hbmOff
);
1487 if (psurfOff
== NULL
)
1489 DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
1492 BITMAP_GetObject(psurfOff
, sizeof(BITMAP
), (PVOID
)&bm
);
1494 pBits
= ExAllocatePoolWithTag(PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1497 DPRINT1("ExAllocatePoolWithTag() failed!\n");
1498 SURFACE_UnlockSurface(psurfOff
);
1503 IntGetBitmapBits(psurfOff
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), pBits
);
1505 /* premultiply with the alpha channel value */
1506 for (i
= 0; i
< cyHeight
; i
++)
1508 for (j
= 0; j
< cxWidth
; j
++)
1510 Pixel
= *(DWORD
*)(pBits
+ Count
);
1512 Alpha
= ((BYTE
)(Pixel
>> 24) & 0xff);
1514 Red
= (((BYTE
)(Pixel
>> 0)) * Alpha
) / 0xff;
1515 Green
= (((BYTE
)(Pixel
>> 8)) * Alpha
) / 0xff;
1516 Blue
= (((BYTE
)(Pixel
>> 16)) * Alpha
) / 0xff;
1518 *(DWORD
*)(pBits
+ Count
) = (DWORD
)(Red
| (Green
<< 8) | (Blue
<< 16) | (Alpha
<< 24));
1520 Count
+= sizeof(DWORD
);
1525 IntSetBitmapBits(psurfOff
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), pBits
);
1526 ExFreePoolWithTag(pBits
, TAG_BITMAP
);
1528 SURFACE_UnlockSurface(psurfOff
);
1530 BlendFunc
.BlendOp
= AC_SRC_OVER
;
1531 BlendFunc
.BlendFlags
= 0;
1532 BlendFunc
.SourceConstantAlpha
= 255;
1533 BlendFunc
.AlphaFormat
= AC_SRC_ALPHA
;
1535 NtGdiAlphaBlend(hDc
, xLeft
, yTop
, cxWidth
, cyHeight
,
1536 hdcOff
, 0, 0, cxWidth
, cyHeight
, BlendFunc
, 0);
1538 else if (DoFlickerFree
)
1540 NtGdiBitBlt(hDc
, xLeft
, yTop
, cxWidth
,
1541 cyHeight
, hdcOff
, 0, 0, SRCCOPY
, 0, 0);
1547 if (DoFlickerFree
|| bAlpha
)
1549 if (hOldOffBmp
) NtGdiSelectBitmap(hdcOff
, hOldOffBmp
);
1550 if (hOldOffBrush
) NtGdiSelectBrush(hdcOff
, hOldOffBrush
);
1551 if (hbmOff
) GreDeleteObject(hbmOff
);
1552 if (hdcOff
) NtGdiDeleteObjectApp(hdcOff
);
1571 HBRUSH hbrFlickerFreeDraw
,
1576 PCURICON_OBJECT pIcon
;
1579 DPRINT("Enter NtUserDrawIconEx\n");
1580 UserEnterExclusive();
1582 if (!(pIcon
= UserGetCurIconObject(hIcon
)))
1584 DPRINT1("UserGetCurIconObject() failed!\n");
1589 Ret
= UserDrawIconEx(hdc
,
1599 UserDereferenceObject(pIcon
);
1605 /* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
1606 * User32 macro NtUserShowCursor */
1609 UserShowCursor(BOOL bShow
)
1611 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1612 PWINSTATION_OBJECT WinSta
= pti
->Desktop
->WindowStation
;
1613 PSYSTEM_CURSORINFO CurInfo
;
1623 if (!(Screen
= IntGetScreenDC()))
1625 return showpointer
; /* No mouse */
1628 dc
= DC_LockDc(Screen
);
1632 return showpointer
; /* No mouse */
1635 psurfDc
= dc
->dclevel
.pSurface
;
1640 return showpointer
; /* No Mouse */
1643 SurfObj
= &psurfDc
->SurfObj
;
1644 if (SurfObj
== NULL
)
1647 return showpointer
; /* No mouse */
1650 ppdev
= GDIDEV(SurfObj
);
1655 return showpointer
; /* No mouse */
1658 pgp
= &ppdev
->Pointer
;
1660 CurInfo
= IntGetSysCursorInfo(WinSta
);
1665 showpointer
= pgp
->ShowPointer
;
1667 if (showpointer
>= 0)
1669 //ppdev->SafetyRemoveCount = 1;
1670 //ppdev->SafetyRemoveLevel = 1;
1671 IntEngMovePointer(SurfObj
,-1,-1,NULL
);
1672 CurInfo
->ShowingCursor
= 0;
1679 showpointer
= pgp
->ShowPointer
;
1682 if (showpointer
< 0)
1684 //ppdev->SafetyRemoveCount = 0;
1685 //ppdev->SafetyRemoveLevel = 0;
1686 IntEngMovePointer(SurfObj
,-1,-1,NULL
);
1687 CurInfo
->ShowingCursor
= CURSOR_SHOWING
;