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(USER_BODY_TO_HEADER(CurIcon
)->RefCount
>= 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
= CURSOR_SHOWING
;
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 */
179 * We have to register that this object is in use by the current
180 * process. The only way to do that seems to be to walk the list
181 * of cursor/icon objects starting at W32Process->CursorIconListHead.
182 * If the object is already present in the list, we don't have to do
183 * anything, if it's not present we add it and inc the ProcessCount
184 * in the object. Having to walk the list kind of sucks, but that's
187 static BOOLEAN FASTCALL
188 ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon
)
190 PPROCESSINFO Win32Process
;
191 PCURICON_PROCESS Current
;
193 Win32Process
= PsGetCurrentProcessWin32Process();
195 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
197 if (Current
->Process
== Win32Process
)
199 /* Already registered for this process */
204 /* Not registered yet */
205 Current
= ExAllocateFromPagedLookasideList(&gProcessLookasideList
);
210 InsertHeadList(&CurIcon
->ProcessList
, &Current
->ListEntry
);
211 Current
->Process
= Win32Process
;
216 PCURICON_OBJECT FASTCALL
217 IntFindExistingCurIconObject(HMODULE hModule
,
218 HRSRC hRsrc
, LONG cx
, LONG cy
)
220 PCURICON_OBJECT CurIcon
;
222 LIST_FOR_EACH(CurIcon
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
225 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
226 // UserReferenceObject( CurIcon);
228 if ((CurIcon
->hModule
== hModule
) && (CurIcon
->hRsrc
== hRsrc
))
230 if (cx
&& ((cx
!= CurIcon
->Size
.cx
) || (cy
!= CurIcon
->Size
.cy
)))
232 // UserDereferenceObject(CurIcon);
235 if (! ReferenceCurIconByProcess(CurIcon
))
243 // UserDereferenceObject(CurIcon);
250 PCURICON_OBJECT FASTCALL
251 IntCreateCurIconHandle()
253 PCURICON_OBJECT CurIcon
;
256 CurIcon
= UserCreateObject(gHandleTable
, &hCurIcon
, otCursorIcon
, sizeof(CURICON_OBJECT
));
260 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
264 CurIcon
->Self
= hCurIcon
;
265 InitializeListHead(&CurIcon
->ProcessList
);
267 if (! ReferenceCurIconByProcess(CurIcon
))
269 DPRINT1("Failed to add process\n");
270 UserDeleteObject(hCurIcon
, otCursorIcon
);
271 UserDereferenceObject(CurIcon
);
275 InsertHeadList(&gCurIconList
, &CurIcon
->ListEntry
);
281 IntDestroyCurIconObject(PCURICON_OBJECT CurIcon
, BOOL ProcessCleanup
)
283 PSYSTEM_CURSORINFO CurInfo
;
284 HBITMAP bmpMask
, bmpColor
;
286 PCURICON_PROCESS Current
= NULL
;
287 PPROCESSINFO W32Process
= PsGetCurrentProcessWin32Process();
289 /* Private objects can only be destroyed by their own process */
290 if (NULL
== CurIcon
->hModule
)
292 ASSERT(CurIcon
->ProcessList
.Flink
->Flink
== &CurIcon
->ProcessList
);
293 Current
= CONTAINING_RECORD(CurIcon
->ProcessList
.Flink
, CURICON_PROCESS
, ListEntry
);
294 if (Current
->Process
!= W32Process
)
296 DPRINT1("Trying to destroy private icon/cursor of another process\n");
300 else if (! ProcessCleanup
)
302 DPRINT("Trying to destroy shared icon/cursor\n");
306 /* Now find this process in the list of processes referencing this object and
307 remove it from that list */
308 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
310 if (Current
->Process
== W32Process
)
312 RemoveEntryList(&Current
->ListEntry
);
317 ExFreeToPagedLookasideList(&gProcessLookasideList
, Current
);
319 /* If there are still processes referencing this object we can't destroy it yet */
320 if (! IsListEmpty(&CurIcon
->ProcessList
))
326 if (! ProcessCleanup
)
328 RemoveEntryList(&CurIcon
->ListEntry
);
331 CurInfo
= IntGetSysCursorInfo();
333 if (CurInfo
->CurrentCursorObject
== CurIcon
)
335 /* Hide the cursor if we're destroying the current cursor */
336 UserSetCursor(NULL
, TRUE
);
339 bmpMask
= CurIcon
->IconInfo
.hbmMask
;
340 bmpColor
= CurIcon
->IconInfo
.hbmColor
;
345 GDIOBJ_SetOwnership(bmpMask
, PsGetCurrentProcess());
346 GreDeleteObject(bmpMask
);
347 CurIcon
->IconInfo
.hbmMask
= NULL
;
351 GDIOBJ_SetOwnership(bmpColor
, PsGetCurrentProcess());
352 GreDeleteObject(bmpColor
);
353 CurIcon
->IconInfo
.hbmColor
= NULL
;
356 /* We were given a pointer, no need to keep the reference anylonger! */
357 UserDereferenceObject(CurIcon
);
358 Ret
= UserDeleteObject(CurIcon
->Self
, otCursorIcon
);
364 IntCleanupCurIcons(struct _EPROCESS
*Process
, PPROCESSINFO Win32Process
)
366 PCURICON_OBJECT CurIcon
, tmp
;
367 PCURICON_PROCESS ProcessData
;
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(CurIcon
, TRUE
);
385 // UserDereferenceObject(Object);
390 UserDereferenceObject(CurIcon
);
401 NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL
, BOOL Indirect
)
403 PCURICON_OBJECT CurIcon
;
407 DECLARE_RETURN(HANDLE
);
409 DPRINT("Enter NtUserCreateCursorIconHandle\n");
410 UserEnterExclusive();
412 if (!(CurIcon
= IntCreateCurIconHandle()))
414 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
422 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
, IconInfo
, sizeof(ICONINFO
));
423 if (NT_SUCCESS(Status
))
425 /* Copy bitmaps and size info */
429 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
430 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
432 if (CurIcon
->IconInfo
.hbmColor
&&
433 (psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
)))
435 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
436 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
437 SURFACE_UnlockSurface(psurfBmp
);
438 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
440 if (CurIcon
->IconInfo
.hbmMask
&&
441 (psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
443 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
445 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
446 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
>> 1;
448 SURFACE_UnlockSurface(psurfBmp
);
449 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
452 /* Calculate icon hotspot */
453 if (CurIcon
->IconInfo
.fIcon
== TRUE
)
455 CurIcon
->IconInfo
.xHotspot
= CurIcon
->Size
.cx
>> 1;
456 CurIcon
->IconInfo
.yHotspot
= CurIcon
->Size
.cy
>> 1;
461 SetLastNtError(Status
);
462 /* FIXME - Don't exit here */
466 UserDereferenceObject(CurIcon
);
470 DPRINT("Leave NtUserCreateCursorIconHandle, ret=%i\n",_ret_
);
483 PUNICODE_STRING lpInstName
, // optional
484 PUNICODE_STRING lpResName
, // optional
485 LPDWORD pbpp
, // optional
489 PCURICON_OBJECT CurIcon
;
490 NTSTATUS Status
= STATUS_SUCCESS
;
494 DPRINT("Enter NtUserGetIconInfo\n");
495 UserEnterExclusive();
499 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
503 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
508 RtlCopyMemory(&ii
, &CurIcon
->IconInfo
, sizeof(ICONINFO
));
511 ii
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
512 ii
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
518 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
);
521 colorBpp
= BitsPerFormat(psurfBmp
->SurfObj
.iBitmapFormat
);
522 SURFACE_UnlockSurface(psurfBmp
);
529 ProbeForWrite(IconInfo
, sizeof(ICONINFO
), 1);
530 RtlCopyMemory(IconInfo
, &ii
, sizeof(ICONINFO
));
534 ProbeForWrite(pbpp
, sizeof(DWORD
), 1);
538 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
540 Status
= _SEH2_GetExceptionCode();
544 if (NT_SUCCESS(Status
))
547 SetLastNtError(Status
);
549 UserDereferenceObject(CurIcon
);
552 DPRINT("Leave NtUserGetIconInfo, ret=%i\n", Ret
);
567 PLONG plcx
, // &size.cx
568 PLONG plcy
) // &size.cy
570 PCURICON_OBJECT CurIcon
;
571 NTSTATUS Status
= STATUS_SUCCESS
;
574 DPRINT("Enter NtUserGetIconSize\n");
575 UserEnterExclusive();
577 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
584 ProbeForWrite(plcx
, sizeof(LONG
), 1);
585 RtlCopyMemory(plcx
, &CurIcon
->Size
.cx
, sizeof(LONG
));
586 ProbeForWrite(plcy
, sizeof(LONG
), 1);
587 RtlCopyMemory(plcy
, &CurIcon
->Size
.cy
, sizeof(LONG
));
589 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
591 Status
= _SEH2_GetExceptionCode();
595 if (NT_SUCCESS(Status
))
598 SetLastNtError(Status
); // maybe not, test this
600 UserDereferenceObject(CurIcon
);
603 DPRINT("Leave NtUserGetIconSize, ret=%i\n", bRet
);
614 NtUserGetCursorFrameInfo(
635 PSYSTEM_CURSORINFO CurInfo
;
636 NTSTATUS Status
= STATUS_SUCCESS
;
637 PCURICON_OBJECT CurIcon
;
639 DECLARE_RETURN(BOOL
);
641 DPRINT("Enter NtUserGetCursorInfo\n");
642 UserEnterExclusive();
644 CurInfo
= IntGetSysCursorInfo();
645 CurIcon
= (PCURICON_OBJECT
)CurInfo
->CurrentCursorObject
;
647 SafeCi
.cbSize
= sizeof(CURSORINFO
);
648 SafeCi
.flags
= ((CurInfo
->ShowingCursor
&& CurIcon
) ? CURSOR_SHOWING
: 0);
649 SafeCi
.hCursor
= (CurIcon
? (HCURSOR
)CurIcon
->Self
: (HCURSOR
)0);
651 SafeCi
.ptScreenPos
= gpsi
->ptCursor
;
655 if (pci
->cbSize
== sizeof(CURSORINFO
))
657 ProbeForWrite(pci
, sizeof(CURSORINFO
), 1);
658 RtlCopyMemory(pci
, &SafeCi
, sizeof(CURSORINFO
));
663 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
666 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
668 Status
= _SEH2_GetExceptionCode();
671 if (!NT_SUCCESS(Status
))
673 SetLastNtError(Status
);
679 DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_
);
693 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
694 PSYSTEM_CURSORINFO CurInfo
;
696 PWINDOW_OBJECT DesktopWindow
= NULL
;
697 DECLARE_RETURN(BOOL
);
699 DPRINT("Enter NtUserClipCursor\n");
700 UserEnterExclusive();
702 if (NULL
!= UnsafeRect
&& ! NT_SUCCESS(MmCopyFromCaller(&Rect
, UnsafeRect
, sizeof(RECT
))))
704 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
708 CurInfo
= IntGetSysCursorInfo();
710 DesktopWindow
= UserGetDesktopWindow();
712 if ((Rect
.right
> Rect
.left
) && (Rect
.bottom
> Rect
.top
)
713 && DesktopWindow
&& UnsafeRect
!= NULL
)
717 CurInfo
->CursorClipInfo
.IsClipped
= TRUE
;
718 CurInfo
->CursorClipInfo
.Left
= max(Rect
.left
, DesktopWindow
->Wnd
->rcWindow
.left
);
719 CurInfo
->CursorClipInfo
.Top
= max(Rect
.top
, DesktopWindow
->Wnd
->rcWindow
.top
);
720 CurInfo
->CursorClipInfo
.Right
= min(Rect
.right
- 1, DesktopWindow
->Wnd
->rcWindow
.right
- 1);
721 CurInfo
->CursorClipInfo
.Bottom
= min(Rect
.bottom
- 1, DesktopWindow
->Wnd
->rcWindow
.bottom
- 1);
723 mi
.dx
= gpsi
->ptCursor
.x
;
724 mi
.dy
= gpsi
->ptCursor
.y
;
726 mi
.dwFlags
= MOUSEEVENTF_ABSOLUTE
| MOUSEEVENTF_MOVE
;
734 CurInfo
->CursorClipInfo
.IsClipped
= FALSE
;
738 DPRINT("Leave NtUserClipCursor, ret=%i\n",_ret_
);
753 PCURICON_OBJECT CurIcon
;
755 DECLARE_RETURN(BOOL
);
757 DPRINT("Enter NtUserDestroyCursorIcon\n");
758 UserEnterExclusive();
760 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
765 ret
= IntDestroyCurIconObject(CurIcon
, FALSE
);
766 /* Note: IntDestroyCurIconObject will remove our reference for us! */
771 DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_
);
782 NtUserFindExistingCursorIcon(
788 PCURICON_OBJECT CurIcon
;
789 HANDLE Ret
= (HANDLE
)0;
790 DECLARE_RETURN(HICON
);
792 DPRINT("Enter NtUserFindExistingCursorIcon\n");
793 UserEnterExclusive();
795 CurIcon
= IntFindExistingCurIconObject(hModule
, hRsrc
, cx
, cy
);
800 // IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
804 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
808 DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_
);
822 /* FIXME - check if process has WINSTA_READATTRIBUTES */
823 PSYSTEM_CURSORINFO CurInfo
;
826 DECLARE_RETURN(BOOL
);
828 DPRINT("Enter NtUserGetClipCursor\n");
829 UserEnterExclusive();
834 CurInfo
= IntGetSysCursorInfo();
835 if (CurInfo
->CursorClipInfo
.IsClipped
)
837 Rect
.left
= CurInfo
->CursorClipInfo
.Left
;
838 Rect
.top
= CurInfo
->CursorClipInfo
.Top
;
839 Rect
.right
= CurInfo
->CursorClipInfo
.Right
;
840 Rect
.bottom
= CurInfo
->CursorClipInfo
.Bottom
;
846 Rect
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
847 Rect
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
850 Status
= MmCopyToCaller(lpRect
, &Rect
, sizeof(RECT
));
851 if (!NT_SUCCESS(Status
))
853 SetLastNtError(Status
);
860 DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_
);
874 PCURICON_OBJECT CurIcon
;
876 DECLARE_RETURN(HCURSOR
);
878 DPRINT("Enter NtUserSetCursor\n");
879 UserEnterExclusive();
883 if (!(CurIcon
= UserGetCurIconObject(hCursor
)))
893 OldCursor
= UserSetCursor(CurIcon
, FALSE
);
897 UserDereferenceObject(CurIcon
);
903 DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_
);
914 NtUserSetCursorContents(
916 PICONINFO UnsafeIconInfo
)
918 PCURICON_OBJECT CurIcon
;
923 DECLARE_RETURN(BOOL
);
925 DPRINT("Enter NtUserSetCursorContents\n");
926 UserEnterExclusive();
928 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
934 Status
= MmCopyFromCaller(&IconInfo
, UnsafeIconInfo
, sizeof(ICONINFO
));
935 if (!NT_SUCCESS(Status
))
937 SetLastNtError(Status
);
941 /* Delete old bitmaps */
942 if (CurIcon
->IconInfo
.hbmColor
!= IconInfo
.hbmColor
)
944 GreDeleteObject(CurIcon
->IconInfo
.hbmColor
);
946 if (CurIcon
->IconInfo
.hbmMask
!= IconInfo
.hbmMask
)
948 GreDeleteObject(CurIcon
->IconInfo
.hbmMask
);
951 /* Copy new IconInfo field */
952 CurIcon
->IconInfo
= IconInfo
;
954 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
);
957 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
958 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
959 SURFACE_UnlockSurface(psurfBmp
);
960 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
964 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
);
968 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
969 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
/ 2;
971 SURFACE_UnlockSurface(psurfBmp
);
972 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
981 UserDereferenceObject(CurIcon
);
986 DPRINT("Leave NtUserSetCursorContents, ret=%i\n",_ret_
);
998 NtUserSetCursorIconData(
1001 PUNICODE_STRING pstrResName
,
1002 PICONINFO pIconInfo
)
1004 PCURICON_OBJECT CurIcon
;
1006 NTSTATUS Status
= STATUS_SUCCESS
;
1008 DECLARE_RETURN(BOOL
);
1010 DPRINT("Enter NtUserSetCursorIconData\n");
1011 UserEnterExclusive();
1013 if (!(CurIcon
= UserGetCurIconObject(Handle
)))
1018 CurIcon
->hModule
= hModule
;
1019 CurIcon
->hRsrc
= NULL
; //hRsrc;
1020 CurIcon
->hGroupRsrc
= NULL
; //hGroupRsrc;
1024 ProbeForRead(pIconInfo
, sizeof(ICONINFO
), 1);
1025 RtlCopyMemory(&CurIcon
->IconInfo
, pIconInfo
, sizeof(ICONINFO
));
1027 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(pIconInfo
->hbmMask
);
1028 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(pIconInfo
->hbmColor
);
1030 if (CurIcon
->IconInfo
.hbmColor
)
1032 if ((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(GdiHandleTable
, CurIcon
->IconInfo
.hbmMask
, NULL
);
1040 if (CurIcon
->IconInfo
.hbmMask
)
1042 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
1044 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
1046 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1047 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1048 SURFACE_UnlockSurface(psurfBmp
);
1051 GDIOBJ_SetOwnership(GdiHandleTable
, CurIcon
->IconInfo
.hbmMask
, NULL
);
1054 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1056 Status
= _SEH2_GetExceptionCode();
1060 if (!NT_SUCCESS(Status
))
1061 SetLastNtError(Status
);
1065 UserDereferenceObject(CurIcon
);
1069 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1076 NtUserSetCursorIconData(
1084 PCURICON_OBJECT CurIcon
;
1088 DECLARE_RETURN(BOOL
);
1090 DPRINT("Enter NtUserSetCursorIconData\n");
1091 UserEnterExclusive();
1093 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1098 CurIcon
->hModule
= hModule
;
1099 CurIcon
->hRsrc
= hRsrc
;
1100 CurIcon
->hGroupRsrc
= hGroupRsrc
;
1105 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
.fIcon
, fIcon
, sizeof(BOOL
));
1106 if (!NT_SUCCESS(Status
))
1108 SetLastNtError(Status
);
1120 Status
= MmCopyFromCaller(&SafeHotspot
, Hotspot
, sizeof(POINT
));
1121 if (NT_SUCCESS(Status
))
1123 CurIcon
->IconInfo
.xHotspot
= SafeHotspot
.x
;
1124 CurIcon
->IconInfo
.yHotspot
= SafeHotspot
.y
;
1129 SetLastNtError(Status
);
1132 if (!fIcon
&& !Hotspot
)
1138 UserDereferenceObject(CurIcon
);
1143 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1154 NtUserSetSystemCursor(
1166 PCURICON_OBJECT pIcon
,
1170 HBRUSH hbrFlickerFreeDraw
,
1174 HBITMAP hbmMask
, hbmColor
;
1175 BITMAP bmpMask
, bmpColor
;
1180 HGDIOBJ hOldOffBrush
= 0;
1181 HGDIOBJ hOldOffBmp
= 0;
1184 HGDIOBJ hOldMask
= NULL
;
1186 HGDIOBJ hOldImage
= NULL
;
1187 BOOL bAlpha
= FALSE
;
1189 hbmMask
= pIcon
->IconInfo
.hbmMask
;
1190 hbmColor
= pIcon
->IconInfo
.hbmColor
;
1193 DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
1195 if (!hbmMask
|| !IntGdiGetObject(hbmMask
, sizeof(BITMAP
), (PVOID
)&bmpMask
))
1200 if (hbmColor
&& !IntGdiGetObject(hbmColor
, sizeof(BITMAP
), (PVOID
)&bmpColor
))
1207 IconSize
.cx
= bmpColor
.bmWidth
;
1208 IconSize
.cy
= bmpColor
.bmHeight
;
1212 IconSize
.cx
= bmpMask
.bmWidth
;
1213 IconSize
.cy
= bmpMask
.bmHeight
/ 2;
1216 /* NtGdiCreateCompatibleBitmap will create a monochrome bitmap
1217 when cxWidth or cyHeight is 0 */
1218 if ((bmpColor
.bmBitsPixel
== 32) && (cxWidth
!= 0) && (cyHeight
!= 0))
1220 SURFACE
*psurfOff
= NULL
;
1221 PFN_DIB_GetPixel fnSource_GetPixel
= NULL
;
1224 /* In order to correctly display 32 bit icons Windows first scans the image,
1225 because information about transparency is not stored in any image's headers */
1226 psurfOff
= SURFACE_LockSurface(hbmColor
? hbmColor
: hbmMask
);
1229 fnSource_GetPixel
= DibFunctionsForBitmapFormat
[psurfOff
->SurfObj
.iBitmapFormat
].DIB_GetPixel
;
1230 if (fnSource_GetPixel
)
1232 for (x
= 0; x
< psurfOff
->SurfObj
.sizlBitmap
.cx
; x
++)
1234 for (y
= 0; y
< psurfOff
->SurfObj
.sizlBitmap
.cy
; y
++)
1236 bAlpha
= ((BYTE
)(fnSource_GetPixel(&psurfOff
->SurfObj
, x
, y
) >> 24) & 0xff);
1244 SURFACE_UnlockSurface(psurfOff
);
1249 diFlags
= DI_NORMAL
;
1252 cxWidth
= ((diFlags
& DI_DEFAULTSIZE
) ?
1253 UserGetSystemMetrics(SM_CXICON
) : IconSize
.cx
);
1256 cyHeight
= ((diFlags
& DI_DEFAULTSIZE
) ?
1257 UserGetSystemMetrics(SM_CYICON
) : IconSize
.cy
);
1259 DoFlickerFree
= (hbrFlickerFreeDraw
&&
1260 (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw
) == GDI_OBJECT_TYPE_BRUSH
));
1262 if (DoFlickerFree
|| bAlpha
)
1266 SURFACE
*psurfOff
= NULL
;
1269 r
.bottom
= cyHeight
;
1271 hdcOff
= NtGdiCreateCompatibleDC(hDc
);
1274 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1278 hbmOff
= NtGdiCreateCompatibleBitmap(hDc
, cxWidth
, cyHeight
);
1281 DPRINT1("NtGdiCreateCompatibleBitmap() failed!\n");
1285 /* make sure we have a 32 bit offscreen bitmap
1286 otherwise we can't do alpha blending */
1287 psurfOff
= SURFACE_LockSurface(hbmOff
);
1288 if (psurfOff
== NULL
)
1290 DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
1293 BITMAP_GetObject(psurfOff
, sizeof(BITMAP
), (PVOID
)&bm
);
1295 if (bm
.bmBitsPixel
!= 32)
1298 SURFACE_UnlockSurface(psurfOff
);
1300 hOldOffBmp
= NtGdiSelectBitmap(hdcOff
, hbmOff
);
1303 DPRINT1("NtGdiSelectBitmap() failed!\n");
1309 hOldOffBrush
= NtGdiSelectBrush(hdcOff
, hbrFlickerFreeDraw
);
1312 DPRINT1("NtGdiSelectBrush() failed!\n");
1316 NtGdiPatBlt(hdcOff
, 0, 0, r
.right
, r
.bottom
, PATCOPY
);
1322 if (diFlags
& DI_IMAGE
)
1324 hdcImage
= NtGdiCreateCompatibleDC(hDc
);
1327 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1330 hOldImage
= NtGdiSelectBitmap(hdcImage
, (hbmColor
? hbmColor
: hbmMask
));
1333 DPRINT("NtGdiSelectBitmap() failed!\n");
1338 /* If DI_IMAGE flag is specified and hbmMask exists, then always use mask for drawing */
1339 if (diFlags
& DI_MASK
|| (diFlags
& DI_IMAGE
&& hbmMask
))
1341 hdcMask
= NtGdiCreateCompatibleDC(hDc
);
1344 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1348 hOldMask
= NtGdiSelectBitmap(hdcMask
, hbmMask
);
1351 DPRINT("NtGdiSelectBitmap() failed!\n");
1356 if (hdcMask
|| hdcImage
)
1358 GreStretchBltMask(hdcOff
,
1359 (DoFlickerFree
|| bAlpha
) ? 0 : xLeft
,
1360 (DoFlickerFree
|| bAlpha
) ? 0 : yTop
,
1363 hdcImage
? hdcImage
: hdcMask
,
1372 hdcImage
? 0 : IconSize
.cy
);
1375 if (hOldMask
) NtGdiSelectBitmap(hdcMask
, hOldMask
);
1376 if (hOldImage
) NtGdiSelectBitmap(hdcImage
, hOldImage
);
1377 if (hdcImage
) NtGdiDeleteObjectApp(hdcImage
);
1378 if (hdcMask
) NtGdiDeleteObjectApp(hdcMask
);
1383 SURFACE
*psurfOff
= NULL
;
1385 BLENDFUNCTION BlendFunc
;
1387 BYTE Red
, Green
, Blue
, Alpha
;
1391 psurfOff
= SURFACE_LockSurface(hbmOff
);
1392 if (psurfOff
== NULL
)
1394 DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
1397 BITMAP_GetObject(psurfOff
, sizeof(BITMAP
), (PVOID
)&bm
);
1399 pBits
= ExAllocatePoolWithTag(PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1402 DPRINT1("ExAllocatePoolWithTag() failed!\n");
1403 SURFACE_UnlockSurface(psurfOff
);
1408 IntGetBitmapBits(psurfOff
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), pBits
);
1410 /* premultiply with the alpha channel value */
1411 for (i
= 0; i
< cyHeight
; i
++)
1413 for (j
= 0; j
< cxWidth
; j
++)
1415 Pixel
= *(DWORD
*)(pBits
+ Count
);
1417 Alpha
= ((BYTE
)(Pixel
>> 24) & 0xff);
1419 Red
= (((BYTE
)(Pixel
>> 0)) * Alpha
) / 0xff;
1420 Green
= (((BYTE
)(Pixel
>> 8)) * Alpha
) / 0xff;
1421 Blue
= (((BYTE
)(Pixel
>> 16)) * Alpha
) / 0xff;
1423 *(DWORD
*)(pBits
+ Count
) = (DWORD
)(Red
| (Green
<< 8) | (Blue
<< 16) | (Alpha
<< 24));
1425 Count
+= sizeof(DWORD
);
1430 IntSetBitmapBits(psurfOff
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), pBits
);
1431 ExFreePoolWithTag(pBits
, TAG_BITMAP
);
1433 SURFACE_UnlockSurface(psurfOff
);
1435 BlendFunc
.BlendOp
= AC_SRC_OVER
;
1436 BlendFunc
.BlendFlags
= 0;
1437 BlendFunc
.SourceConstantAlpha
= 255;
1438 BlendFunc
.AlphaFormat
= AC_SRC_ALPHA
;
1440 NtGdiAlphaBlend(hDc
, xLeft
, yTop
, cxWidth
, cyHeight
,
1441 hdcOff
, 0, 0, cxWidth
, cyHeight
, BlendFunc
, 0);
1443 else if (DoFlickerFree
)
1445 NtGdiBitBlt(hDc
, xLeft
, yTop
, cxWidth
,
1446 cyHeight
, hdcOff
, 0, 0, SRCCOPY
, 0, 0);
1452 if (DoFlickerFree
|| bAlpha
)
1454 if (hOldOffBmp
) NtGdiSelectBitmap(hdcOff
, hOldOffBmp
);
1455 if (hOldOffBrush
) NtGdiSelectBrush(hdcOff
, hOldOffBrush
);
1456 if (hbmOff
) GreDeleteObject(hbmOff
);
1457 if (hdcOff
) NtGdiDeleteObjectApp(hdcOff
);
1476 HBRUSH hbrFlickerFreeDraw
,
1481 PCURICON_OBJECT pIcon
;
1484 DPRINT("Enter NtUserDrawIconEx\n");
1485 UserEnterExclusive();
1487 if (!(pIcon
= UserGetCurIconObject(hIcon
)))
1489 DPRINT1("UserGetCurIconObject() failed!\n");
1494 Ret
= UserDrawIconEx(hdc
,
1504 UserDereferenceObject(pIcon
);
1510 /* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
1511 * User32 macro NtUserShowCursor */
1514 UserShowCursor(BOOL bShow
)
1516 PSYSTEM_CURSORINFO CurInfo
;
1525 CurInfo
= IntGetSysCursorInfo();
1527 if (!(Screen
= IntGetScreenDC()))
1529 return showpointer
; /* No mouse */
1532 dc
= DC_LockDc(Screen
);
1536 return showpointer
; /* No mouse */
1539 psurfDc
= dc
->dclevel
.pSurface
;
1544 return showpointer
; /* No Mouse */
1547 SurfObj
= &psurfDc
->SurfObj
;
1548 if (SurfObj
== NULL
)
1551 return showpointer
; /* No mouse */
1554 ppdev
= GDIDEV(SurfObj
);
1559 return showpointer
; /* No mouse */
1562 pgp
= &ppdev
->Pointer
;
1567 showpointer
= pgp
->ShowPointer
;
1569 if (showpointer
>= 0)
1571 //ppdev->SafetyRemoveCount = 1;
1572 //ppdev->SafetyRemoveLevel = 1;
1573 IntEngMovePointer(SurfObj
,-1,-1,NULL
);
1574 CurInfo
->ShowingCursor
= 0;
1581 showpointer
= pgp
->ShowPointer
;
1584 if (showpointer
< 0)
1586 //ppdev->SafetyRemoveCount = 0;
1587 //ppdev->SafetyRemoveLevel = 0;
1588 IntEngMovePointer(SurfObj
,-1,-1,NULL
);
1589 CurInfo
->ShowingCursor
= CURSOR_SHOWING
;