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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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);
80 #define COLORCURSORS_ALLOWED FALSE
82 IntSetCursor(PWINSTATION_OBJECT WinSta
, PCURICON_OBJECT NewCursor
,
88 PSURFACE MaskBmpObj
= NULL
;
89 PSYSTEM_CURSORINFO CurInfo
;
90 PCURICON_OBJECT OldCursor
;
91 HCURSOR Ret
= (HCURSOR
)0;
93 SURFOBJ
*soMask
= NULL
, *soColor
= NULL
;
94 XLATEOBJ
*XlateObj
= NULL
;
99 CurInfo
= IntGetSysCursorInfo(WinSta
);
100 OldCursor
= CurInfo
->CurrentCursorObject
;
103 Ret
= (HCURSOR
)OldCursor
->Self
;
106 if (!ForceChange
&& OldCursor
== NewCursor
)
111 if (!(Screen
= IntGetScreenDC()))
115 /* FIXME use the desktop's HDC instead of using ScreenDeviceContext */
116 dc
= DC_LockDc(Screen
);
122 DevInfo
= (PDEVINFO
)&dc
->ppdev
->DevInfo
;
124 psurf
= dc
->dclevel
.pSurface
;
130 pso
= &psurf
->SurfObj
;
134 if (CurInfo
->CurrentCursorObject
|| ForceChange
)
136 if (CurInfo
->CurrentCursorObject
)
138 UserDereferenceObject(CurInfo
->CurrentCursorObject
);
139 if (CurInfo
->ShowingCursor
)
141 DPRINT("Removing pointer!\n");
142 /* Remove the cursor if it was displayed */
143 IntEngMovePointer(pso
, -1, -1, &GDIDEV(pso
)->Pointer
.Exclude
);
147 CurInfo
->CurrentCursorObject
= NewCursor
; /* i.e. CurrentCursorObject = NULL */
148 CurInfo
->ShowingCursor
= 0;
155 /* TODO: Fixme. Logic is screwed above */
157 MaskBmpObj
= SURFACE_LockSurface(NewCursor
->IconInfo
.hbmMask
);
160 const int maskBpp
= BitsPerFormat(MaskBmpObj
->SurfObj
.iBitmapFormat
);
161 SURFACE_UnlockSurface(MaskBmpObj
);
164 DPRINT1("SetCursor: The Mask bitmap must have 1BPP!\n");
169 if ((DevInfo
->flGraphicsCaps2
& GCAPS2_ALPHACURSOR
) &&
170 pso
->iBitmapFormat
>= BMF_16BPP
&&
171 pso
->iBitmapFormat
<= BMF_32BPP
&&
172 NewCursor
->Shadow
&& COLORCURSORS_ALLOWED
)
174 /* FIXME - Create a color pointer, only 32bit bitmap, set alpha bits!
175 Do not pass a mask bitmap to DrvSetPointerShape()!
176 Create a XLATEOBJ that describes the colors of the bitmap. */
177 DPRINT1("SetCursor: (Colored) alpha cursors are not supported!\n");
181 if (NewCursor
->IconInfo
.hbmColor
182 && COLORCURSORS_ALLOWED
)
184 /* FIXME - Create a color pointer, create only one 32bit bitmap!
185 Do not pass a mask bitmap to DrvSetPointerShape()!
186 Create a XLATEOBJ that describes the colors of the bitmap.
187 (16bit bitmaps are propably allowed) */
188 DPRINT1("SetCursor: Cursors with colors are not supported!\n");
192 MaskBmpObj
= SURFACE_LockSurface(NewCursor
->IconInfo
.hbmMask
);
195 RECTL DestRect
= {0, 0, MaskBmpObj
->SurfObj
.sizlBitmap
.cx
, MaskBmpObj
->SurfObj
.sizlBitmap
.cy
};
196 POINTL SourcePoint
= {0, 0};
199 * NOTE: For now we create the cursor in top-down bitmap,
200 * because VMware driver rejects it otherwise. This should
203 hMask
= EngCreateBitmap(
204 MaskBmpObj
->SurfObj
.sizlBitmap
, abs(MaskBmpObj
->SurfObj
.lDelta
),
205 MaskBmpObj
->SurfObj
.iBitmapFormat
, BMF_TOPDOWN
,
209 SURFACE_UnlockSurface(MaskBmpObj
);
213 soMask
= EngLockSurface((HSURF
)hMask
);
214 IntEngCopyBits(soMask
, &MaskBmpObj
->SurfObj
, NULL
, NULL
,
215 &DestRect
, &SourcePoint
);
216 SURFACE_UnlockSurface(MaskBmpObj
);
220 CurInfo
->ShowingCursor
= CURSOR_SHOWING
;
221 CurInfo
->CurrentCursorObject
= NewCursor
;
222 UserReferenceObject(NewCursor
);
226 CurInfo
->ShowingCursor
= 0;
227 CurInfo
->CurrentCursorObject
= NULL
;
230 /* OldCursor is not in use anymore */
233 UserDereferenceObject(OldCursor
);
236 Status
= IntEngSetPointerShape(pso
,
240 NewCursor
->IconInfo
.xHotspot
,
241 NewCursor
->IconInfo
.yHotspot
,
244 &(GDIDEV(pso
)->Pointer
.Exclude
),
247 if (Status
!= SPS_ACCEPT_NOEXCLUDE
)
249 DPRINT1("IntEngSetPointerShape returned %lx\n", Status
);
254 EngUnlockSurface(soMask
);
255 EngDeleteSurface((HSURF
)hMask
);
259 EngDeleteXlate(XlateObj
);
267 IntSetupCurIconHandles(PWINSTATION_OBJECT WinSta
)
269 ExInitializePagedLookasideList(&gProcessLookasideList
,
273 sizeof(CURICON_PROCESS
),
276 InitializeListHead(&gCurIconList
);
282 * We have to register that this object is in use by the current
283 * process. The only way to do that seems to be to walk the list
284 * of cursor/icon objects starting at W32Process->CursorIconListHead.
285 * If the object is already present in the list, we don't have to do
286 * anything, if it's not present we add it and inc the ProcessCount
287 * in the object. Having to walk the list kind of sucks, but that's
290 static BOOLEAN FASTCALL
291 ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon
)
293 PPROCESSINFO Win32Process
;
294 PCURICON_PROCESS Current
;
296 Win32Process
= PsGetCurrentProcessWin32Process();
298 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
300 if (Current
->Process
== Win32Process
)
302 /* Already registered for this process */
307 /* Not registered yet */
308 Current
= ExAllocateFromPagedLookasideList(&gProcessLookasideList
);
313 InsertHeadList(&CurIcon
->ProcessList
, &Current
->ListEntry
);
314 Current
->Process
= Win32Process
;
319 PCURICON_OBJECT FASTCALL
320 IntFindExistingCurIconObject(PWINSTATION_OBJECT WinSta
, HMODULE hModule
,
321 HRSRC hRsrc
, LONG cx
, LONG cy
)
323 PCURICON_OBJECT CurIcon
;
325 LIST_FOR_EACH(CurIcon
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
328 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
329 // UserReferenceObject( CurIcon);
331 if ((CurIcon
->hModule
== hModule
) && (CurIcon
->hRsrc
== hRsrc
))
333 if (cx
&& ((cx
!= CurIcon
->Size
.cx
) || (cy
!= CurIcon
->Size
.cy
)))
335 // UserDereferenceObject(CurIcon);
338 if (! ReferenceCurIconByProcess(CurIcon
))
346 // UserDereferenceObject(CurIcon);
353 PCURICON_OBJECT FASTCALL
354 IntCreateCurIconHandle(PWINSTATION_OBJECT WinSta
)
356 PCURICON_OBJECT CurIcon
;
359 CurIcon
= UserCreateObject(gHandleTable
, &hCurIcon
, otCursorIcon
, sizeof(CURICON_OBJECT
));
363 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
367 CurIcon
->Self
= hCurIcon
;
368 InitializeListHead(&CurIcon
->ProcessList
);
370 if (! ReferenceCurIconByProcess(CurIcon
))
372 DPRINT1("Failed to add process\n");
373 UserDeleteObject(hCurIcon
, otCursorIcon
);
374 UserDereferenceObject(CurIcon
);
378 InsertHeadList(&gCurIconList
, &CurIcon
->ListEntry
);
384 IntDestroyCurIconObject(PWINSTATION_OBJECT WinSta
, PCURICON_OBJECT CurIcon
, BOOL ProcessCleanup
)
386 PSYSTEM_CURSORINFO CurInfo
;
387 HBITMAP bmpMask
, bmpColor
;
389 PCURICON_PROCESS Current
= NULL
;
390 PPROCESSINFO W32Process
= PsGetCurrentProcessWin32Process();
392 /* Private objects can only be destroyed by their own process */
393 if (NULL
== CurIcon
->hModule
)
395 ASSERT(CurIcon
->ProcessList
.Flink
->Flink
== &CurIcon
->ProcessList
);
396 Current
= CONTAINING_RECORD(CurIcon
->ProcessList
.Flink
, CURICON_PROCESS
, ListEntry
);
397 if (Current
->Process
!= W32Process
)
399 DPRINT1("Trying to destroy private icon/cursor of another process\n");
403 else if (! ProcessCleanup
)
405 DPRINT("Trying to destroy shared icon/cursor\n");
409 /* Now find this process in the list of processes referencing this object and
410 remove it from that list */
411 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
413 if (Current
->Process
== W32Process
)
415 RemoveEntryList(&Current
->ListEntry
);
420 ExFreeToPagedLookasideList(&gProcessLookasideList
, Current
);
422 /* If there are still processes referencing this object we can't destroy it yet */
423 if (! IsListEmpty(&CurIcon
->ProcessList
))
429 if (! ProcessCleanup
)
431 RemoveEntryList(&CurIcon
->ListEntry
);
434 CurInfo
= IntGetSysCursorInfo(WinSta
);
436 if (CurInfo
->CurrentCursorObject
== CurIcon
)
438 /* Hide the cursor if we're destroying the current cursor */
439 IntSetCursor(WinSta
, NULL
, TRUE
);
442 bmpMask
= CurIcon
->IconInfo
.hbmMask
;
443 bmpColor
= CurIcon
->IconInfo
.hbmColor
;
448 GDIOBJ_SetOwnership(bmpMask
, PsGetCurrentProcess());
449 GreDeleteObject(bmpMask
);
450 CurIcon
->IconInfo
.hbmMask
= NULL
;
454 GDIOBJ_SetOwnership(bmpColor
, PsGetCurrentProcess());
455 GreDeleteObject(bmpColor
);
456 CurIcon
->IconInfo
.hbmColor
= NULL
;
459 /* We were given a pointer, no need to keep the reference anylonger! */
460 UserDereferenceObject(CurIcon
);
461 Ret
= UserDeleteObject(CurIcon
->Self
, otCursorIcon
);
467 IntCleanupCurIcons(struct _EPROCESS
*Process
, PPROCESSINFO Win32Process
)
469 PWINSTATION_OBJECT WinSta
;
470 PCURICON_OBJECT CurIcon
, tmp
;
471 PCURICON_PROCESS ProcessData
;
473 WinSta
= IntGetWinStaObj();
479 LIST_FOR_EACH_SAFE(CurIcon
, tmp
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
481 UserReferenceObject(CurIcon
);
482 // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon)))
484 LIST_FOR_EACH(ProcessData
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
486 if (Win32Process
== ProcessData
->Process
)
488 RemoveEntryList(&CurIcon
->ListEntry
);
489 IntDestroyCurIconObject(WinSta
, CurIcon
, TRUE
);
495 // UserDereferenceObject(Object);
500 UserDereferenceObject(CurIcon
);
504 ObDereferenceObject(WinSta
);
512 NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL
, BOOL Indirect
)
514 PCURICON_OBJECT CurIcon
;
515 PWINSTATION_OBJECT WinSta
;
519 DECLARE_RETURN(HANDLE
);
521 DPRINT("Enter NtUserCreateCursorIconHandle\n");
522 UserEnterExclusive();
524 WinSta
= IntGetWinStaObj();
530 if (!(CurIcon
= IntCreateCurIconHandle(WinSta
)))
532 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
533 ObDereferenceObject(WinSta
);
541 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
, IconInfo
, sizeof(ICONINFO
));
542 if (NT_SUCCESS(Status
))
544 /* Copy bitmaps and size info */
547 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
548 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
550 if (CurIcon
->IconInfo
.hbmColor
&&
551 (psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
)))
553 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
554 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
555 SURFACE_UnlockSurface(psurfBmp
);
556 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
558 if (CurIcon
->IconInfo
.hbmMask
&&
559 (psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
561 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
563 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
564 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
>> 1;
566 SURFACE_UnlockSurface(psurfBmp
);
567 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
570 /* Calculate icon hotspot */
571 if (CurIcon
->IconInfo
.fIcon
== TRUE
)
573 CurIcon
->IconInfo
.xHotspot
= CurIcon
->Size
.cx
>> 1;
574 CurIcon
->IconInfo
.yHotspot
= CurIcon
->Size
.cy
>> 1;
579 SetLastNtError(Status
);
580 /* FIXME - Don't exit here */
584 UserDereferenceObject(CurIcon
);
585 ObDereferenceObject(WinSta
);
589 DPRINT("Leave NtUserCreateCursorIconHandle, ret=%i\n",_ret_
);
602 PUNICODE_STRING lpInstName
, // optional
603 PUNICODE_STRING lpResName
, // optional
604 LPDWORD pbpp
, // optional
608 PCURICON_OBJECT CurIcon
;
609 PWINSTATION_OBJECT WinSta
;
610 NTSTATUS Status
= STATUS_SUCCESS
;
612 DECLARE_RETURN(BOOL
);
614 DPRINT("Enter NtUserGetIconInfo\n");
615 UserEnterExclusive();
619 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
623 WinSta
= IntGetWinStaObj();
629 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
631 ObDereferenceObject(WinSta
);
635 RtlCopyMemory(&ii
, &CurIcon
->IconInfo
, sizeof(ICONINFO
));
638 ii
.hbmMask
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
639 ii
.hbmColor
= BITMAP_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
644 ProbeForWrite(IconInfo
, sizeof(ICONINFO
), 1);
645 RtlCopyMemory(IconInfo
, &ii
, sizeof(ICONINFO
));
652 ProbeForWrite(pbpp
, sizeof(DWORD
), 1);
654 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
);
657 colorBpp
= BitsPerFormat(psurfBmp
->SurfObj
.iBitmapFormat
);
658 SURFACE_UnlockSurface(psurfBmp
);
661 RtlCopyMemory(pbpp
, &colorBpp
, sizeof(DWORD
));
665 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
667 Status
= _SEH2_GetExceptionCode();
671 if (NT_SUCCESS(Status
))
674 SetLastNtError(Status
);
676 UserDereferenceObject(CurIcon
);
677 ObDereferenceObject(WinSta
);
681 DPRINT("Leave NtUserGetIconInfo, ret=%i\n",_ret_
);
695 PLONG plcx
, // &size.cx
696 PLONG plcy
) // &size.cy
698 PCURICON_OBJECT CurIcon
;
699 NTSTATUS Status
= STATUS_SUCCESS
;
702 DPRINT("Enter NtUserGetIconSize\n");
703 UserEnterExclusive();
705 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
712 ProbeForWrite(plcx
, sizeof(LONG
), 1);
713 RtlCopyMemory(plcx
, &CurIcon
->Size
.cx
, sizeof(LONG
));
714 ProbeForWrite(plcy
, sizeof(LONG
), 1);
715 RtlCopyMemory(plcy
, &CurIcon
->Size
.cy
, sizeof(LONG
));
717 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
719 Status
= _SEH2_GetExceptionCode();
723 if (NT_SUCCESS(Status
))
726 SetLastNtError(Status
); // maybe not, test this
728 UserDereferenceObject(CurIcon
);
731 DPRINT("Leave NtUserGetIconSize, ret=%i\n", bRet
);
742 NtUserGetCursorFrameInfo(
763 PSYSTEM_CURSORINFO CurInfo
;
764 PWINSTATION_OBJECT WinSta
;
765 NTSTATUS Status
= STATUS_SUCCESS
;
766 PCURICON_OBJECT CurIcon
;
768 DECLARE_RETURN(BOOL
);
770 DPRINT("Enter NtUserGetCursorInfo\n");
771 UserEnterExclusive();
773 WinSta
= IntGetWinStaObj();
779 CurInfo
= IntGetSysCursorInfo(WinSta
);
780 CurIcon
= (PCURICON_OBJECT
)CurInfo
->CurrentCursorObject
;
782 SafeCi
.cbSize
= sizeof(CURSORINFO
);
783 SafeCi
.flags
= ((CurInfo
->ShowingCursor
&& CurIcon
) ? CURSOR_SHOWING
: 0);
784 SafeCi
.hCursor
= (CurIcon
? (HCURSOR
)CurIcon
->Self
: (HCURSOR
)0);
786 IntGetCursorLocation(WinSta
, &SafeCi
.ptScreenPos
);
790 if (pci
->cbSize
== sizeof(CURSORINFO
))
792 ProbeForWrite(pci
, sizeof(CURSORINFO
), 1);
793 RtlCopyMemory(pci
, &SafeCi
, sizeof(CURSORINFO
));
798 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
801 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
803 Status
= _SEH2_GetExceptionCode();
806 if (!NT_SUCCESS(Status
))
808 SetLastNtError(Status
);
811 ObDereferenceObject(WinSta
);
815 DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_
);
829 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
831 PWINSTATION_OBJECT WinSta
;
832 PSYSTEM_CURSORINFO CurInfo
;
834 PWINDOW_OBJECT DesktopWindow
= NULL
;
835 POINT MousePos
= {0};
836 DECLARE_RETURN(BOOL
);
838 DPRINT("Enter NtUserClipCursor\n");
839 UserEnterExclusive();
841 WinSta
= IntGetWinStaObj();
847 if (NULL
!= UnsafeRect
&& ! NT_SUCCESS(MmCopyFromCaller(&Rect
, UnsafeRect
, sizeof(RECT
))))
849 ObDereferenceObject(WinSta
);
850 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
854 CurInfo
= IntGetSysCursorInfo(WinSta
);
855 IntGetCursorLocation(WinSta
, &MousePos
);
857 if (WinSta
->ActiveDesktop
)
858 DesktopWindow
= UserGetWindowObject(WinSta
->ActiveDesktop
->DesktopWindow
);
860 if ((Rect
.right
> Rect
.left
) && (Rect
.bottom
> Rect
.top
)
861 && DesktopWindow
&& UnsafeRect
!= NULL
)
865 CurInfo
->CursorClipInfo
.IsClipped
= TRUE
;
866 CurInfo
->CursorClipInfo
.Left
= max(Rect
.left
, DesktopWindow
->Wnd
->rcWindow
.left
);
867 CurInfo
->CursorClipInfo
.Top
= max(Rect
.top
, DesktopWindow
->Wnd
->rcWindow
.top
);
868 CurInfo
->CursorClipInfo
.Right
= min(Rect
.right
- 1, DesktopWindow
->Wnd
->rcWindow
.right
- 1);
869 CurInfo
->CursorClipInfo
.Bottom
= min(Rect
.bottom
- 1, DesktopWindow
->Wnd
->rcWindow
.bottom
- 1);
874 mi
.dwFlags
= MOUSEEVENTF_ABSOLUTE
| MOUSEEVENTF_MOVE
;
882 CurInfo
->CursorClipInfo
.IsClipped
= FALSE
;
883 ObDereferenceObject(WinSta
);
888 DPRINT("Leave NtUserClipCursor, ret=%i\n",_ret_
);
903 PWINSTATION_OBJECT WinSta
;
904 PCURICON_OBJECT CurIcon
;
906 DECLARE_RETURN(BOOL
);
908 DPRINT("Enter NtUserDestroyCursorIcon\n");
909 UserEnterExclusive();
911 WinSta
= IntGetWinStaObj();
917 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
919 ObDereferenceObject(WinSta
);
923 ret
= IntDestroyCurIconObject(WinSta
, CurIcon
, FALSE
);
924 /* Note: IntDestroyCurIconObject will remove our reference for us! */
926 ObDereferenceObject(WinSta
);
930 DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_
);
941 NtUserFindExistingCursorIcon(
947 PCURICON_OBJECT CurIcon
;
948 PWINSTATION_OBJECT WinSta
;
949 HANDLE Ret
= (HANDLE
)0;
950 DECLARE_RETURN(HICON
);
952 DPRINT("Enter NtUserFindExistingCursorIcon\n");
953 UserEnterExclusive();
955 WinSta
= IntGetWinStaObj();
961 CurIcon
= IntFindExistingCurIconObject(WinSta
, hModule
, hRsrc
, cx
, cy
);
966 // IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
967 ObDereferenceObject(WinSta
);
971 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
972 ObDereferenceObject(WinSta
);
976 DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_
);
990 /* FIXME - check if process has WINSTA_READATTRIBUTES */
991 PSYSTEM_CURSORINFO CurInfo
;
992 PWINSTATION_OBJECT WinSta
;
995 DECLARE_RETURN(BOOL
);
997 DPRINT("Enter NtUserGetClipCursor\n");
998 UserEnterExclusive();
1003 WinSta
= IntGetWinStaObj();
1009 CurInfo
= IntGetSysCursorInfo(WinSta
);
1010 if (CurInfo
->CursorClipInfo
.IsClipped
)
1012 Rect
.left
= CurInfo
->CursorClipInfo
.Left
;
1013 Rect
.top
= CurInfo
->CursorClipInfo
.Top
;
1014 Rect
.right
= CurInfo
->CursorClipInfo
.Right
;
1015 Rect
.bottom
= CurInfo
->CursorClipInfo
.Bottom
;
1021 Rect
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1022 Rect
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1025 Status
= MmCopyToCaller(lpRect
, &Rect
, sizeof(RECT
));
1026 if (!NT_SUCCESS(Status
))
1028 ObDereferenceObject(WinSta
);
1029 SetLastNtError(Status
);
1033 ObDereferenceObject(WinSta
);
1038 DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_
);
1052 PCURICON_OBJECT CurIcon
;
1054 PWINSTATION_OBJECT WinSta
;
1055 DECLARE_RETURN(HCURSOR
);
1057 DPRINT("Enter NtUserSetCursor\n");
1058 UserEnterExclusive();
1060 WinSta
= IntGetWinStaObj();
1068 if (!(CurIcon
= UserGetCurIconObject(hCursor
)))
1070 ObDereferenceObject(WinSta
);
1079 OldCursor
= IntSetCursor(WinSta
, CurIcon
, FALSE
);
1083 UserDereferenceObject(CurIcon
);
1085 ObDereferenceObject(WinSta
);
1090 DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_
);
1101 NtUserSetCursorContents(
1103 PICONINFO UnsafeIconInfo
)
1105 PCURICON_OBJECT CurIcon
;
1108 PWINSTATION_OBJECT WinSta
;
1111 DECLARE_RETURN(BOOL
);
1113 DPRINT("Enter NtUserSetCursorContents\n");
1114 UserEnterExclusive();
1116 WinSta
= IntGetWinStaObj();
1122 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1124 ObDereferenceObject(WinSta
);
1129 Status
= MmCopyFromCaller(&IconInfo
, UnsafeIconInfo
, sizeof(ICONINFO
));
1130 if (!NT_SUCCESS(Status
))
1132 SetLastNtError(Status
);
1136 /* Delete old bitmaps */
1137 if (CurIcon
->IconInfo
.hbmColor
!= IconInfo
.hbmColor
)
1139 GreDeleteObject(CurIcon
->IconInfo
.hbmColor
);
1141 if (CurIcon
->IconInfo
.hbmMask
!= IconInfo
.hbmMask
)
1143 GreDeleteObject(CurIcon
->IconInfo
.hbmMask
);
1146 /* Copy new IconInfo field */
1147 CurIcon
->IconInfo
= IconInfo
;
1149 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
);
1152 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1153 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1154 SURFACE_UnlockSurface(psurfBmp
);
1155 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
1159 psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
);
1163 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1164 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
/ 2;
1166 SURFACE_UnlockSurface(psurfBmp
);
1167 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
1176 UserDereferenceObject(CurIcon
);
1178 ObDereferenceObject(WinSta
);
1182 DPRINT("Leave NtUserSetCursorContents, ret=%i\n",_ret_
);
1194 NtUserSetCursorIconData(
1197 PUNICODE_STRING pstrResName
,
1198 PICONINFO pIconInfo
)
1200 PCURICON_OBJECT CurIcon
;
1201 PWINSTATION_OBJECT WinSta
;
1203 NTSTATUS Status
= STATUS_SUCCESS
;
1205 DECLARE_RETURN(BOOL
);
1207 DPRINT("Enter NtUserSetCursorIconData\n");
1208 UserEnterExclusive();
1210 WinSta
= IntGetWinStaObj();
1216 if (!(CurIcon
= UserGetCurIconObject(Handle
)))
1218 ObDereferenceObject(WinSta
);
1222 CurIcon
->hModule
= hModule
;
1223 CurIcon
->hRsrc
= NULL
; //hRsrc;
1224 CurIcon
->hGroupRsrc
= NULL
; //hGroupRsrc;
1228 ProbeForRead(pIconInfo
, sizeof(ICONINFO
), 1);
1229 RtlCopyMemory(&CurIcon
->IconInfo
, pIconInfo
, sizeof(ICONINFO
));
1231 CurIcon
->IconInfo
.hbmMask
= BITMAP_CopyBitmap(pIconInfo
->hbmMask
);
1232 CurIcon
->IconInfo
.hbmColor
= BITMAP_CopyBitmap(pIconInfo
->hbmColor
);
1234 if (CurIcon
->IconInfo
.hbmColor
)
1236 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmColor
)))
1238 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1239 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1240 SURFACE_UnlockSurface(psurfBmp
);
1241 GDIOBJ_SetOwnership(GdiHandleTable
, CurIcon
->IconInfo
.hbmMask
, NULL
);
1244 if (CurIcon
->IconInfo
.hbmMask
)
1246 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
1248 if ((psurfBmp
= SURFACE_LockSurface(CurIcon
->IconInfo
.hbmMask
)))
1250 CurIcon
->Size
.cx
= psurfBmp
->SurfObj
.sizlBitmap
.cx
;
1251 CurIcon
->Size
.cy
= psurfBmp
->SurfObj
.sizlBitmap
.cy
;
1252 SURFACE_UnlockSurface(psurfBmp
);
1255 GDIOBJ_SetOwnership(GdiHandleTable
, CurIcon
->IconInfo
.hbmMask
, NULL
);
1258 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1260 Status
= _SEH2_GetExceptionCode();
1264 if (!NT_SUCCESS(Status
))
1265 SetLastNtError(Status
);
1269 UserDereferenceObject(CurIcon
);
1270 ObDereferenceObject(WinSta
);
1274 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1281 NtUserSetCursorIconData(
1289 PCURICON_OBJECT CurIcon
;
1290 PWINSTATION_OBJECT WinSta
;
1294 DECLARE_RETURN(BOOL
);
1296 DPRINT("Enter NtUserSetCursorIconData\n");
1297 UserEnterExclusive();
1299 WinSta
= IntGetWinStaObj();
1305 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1307 ObDereferenceObject(WinSta
);
1311 CurIcon
->hModule
= hModule
;
1312 CurIcon
->hRsrc
= hRsrc
;
1313 CurIcon
->hGroupRsrc
= hGroupRsrc
;
1318 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
.fIcon
, fIcon
, sizeof(BOOL
));
1319 if (!NT_SUCCESS(Status
))
1321 SetLastNtError(Status
);
1333 Status
= MmCopyFromCaller(&SafeHotspot
, Hotspot
, sizeof(POINT
));
1334 if (NT_SUCCESS(Status
))
1336 CurIcon
->IconInfo
.xHotspot
= SafeHotspot
.x
;
1337 CurIcon
->IconInfo
.yHotspot
= SafeHotspot
.y
;
1342 SetLastNtError(Status
);
1345 if (!fIcon
&& !Hotspot
)
1351 UserDereferenceObject(CurIcon
);
1352 ObDereferenceObject(WinSta
);
1357 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1368 NtUserSetSystemCursor(
1380 PCURICON_OBJECT pIcon
,
1384 HBRUSH hbrFlickerFreeDraw
,
1388 HBITMAP hbmMask
, hbmColor
;
1389 BITMAP bmpMask
, bmpColor
;
1394 HGDIOBJ hOldOffBrush
= 0;
1395 HGDIOBJ hOldOffBmp
= 0;
1398 HGDIOBJ hOldMask
= NULL
;
1400 HGDIOBJ hOldImage
= NULL
;
1401 BOOL bAlpha
= FALSE
;
1403 hbmMask
= pIcon
->IconInfo
.hbmMask
;
1404 hbmColor
= pIcon
->IconInfo
.hbmColor
;
1407 DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
1409 if (!hbmMask
|| !IntGdiGetObject(hbmMask
, sizeof(BITMAP
), (PVOID
)&bmpMask
))
1414 if (hbmColor
&& !IntGdiGetObject(hbmColor
, sizeof(BITMAP
), (PVOID
)&bmpColor
))
1421 IconSize
.cx
= bmpColor
.bmWidth
;
1422 IconSize
.cy
= bmpColor
.bmHeight
;
1426 IconSize
.cx
= bmpMask
.bmWidth
;
1427 IconSize
.cy
= bmpMask
.bmHeight
/ 2;
1430 /* NtGdiCreateCompatibleBitmap will create a monochrome bitmap
1431 when cxWidth or cyHeight is 0 */
1432 if ((bmpColor
.bmBitsPixel
== 32) && (cxWidth
!= 0) && (cyHeight
!= 0))
1434 SURFACE
*psurfOff
= NULL
;
1435 PFN_DIB_GetPixel fnSource_GetPixel
= NULL
;
1438 /* In order to correctly display 32 bit icons Windows first scans the image,
1439 because information about transparency is not stored in any image's headers */
1440 psurfOff
= SURFACE_LockSurface(hbmColor
? hbmColor
: hbmMask
);
1443 fnSource_GetPixel
= DibFunctionsForBitmapFormat
[psurfOff
->SurfObj
.iBitmapFormat
].DIB_GetPixel
;
1444 if (fnSource_GetPixel
)
1446 for (x
= 0; x
< psurfOff
->SurfObj
.sizlBitmap
.cx
; x
++)
1448 for (y
= 0; y
< psurfOff
->SurfObj
.sizlBitmap
.cy
; y
++)
1450 bAlpha
= ((BYTE
)(fnSource_GetPixel(&psurfOff
->SurfObj
, x
, y
) >> 24) & 0xff);
1458 SURFACE_UnlockSurface(psurfOff
);
1463 diFlags
= DI_NORMAL
;
1466 cxWidth
= ((diFlags
& DI_DEFAULTSIZE
) ?
1467 UserGetSystemMetrics(SM_CXICON
) : IconSize
.cx
);
1470 cyHeight
= ((diFlags
& DI_DEFAULTSIZE
) ?
1471 UserGetSystemMetrics(SM_CYICON
) : IconSize
.cy
);
1473 DoFlickerFree
= (hbrFlickerFreeDraw
&&
1474 (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw
) == GDI_OBJECT_TYPE_BRUSH
));
1476 if (DoFlickerFree
|| bAlpha
)
1480 SURFACE
*psurfOff
= NULL
;
1483 r
.bottom
= cyHeight
;
1485 hdcOff
= NtGdiCreateCompatibleDC(hDc
);
1488 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1492 hbmOff
= NtGdiCreateCompatibleBitmap(hDc
, cxWidth
, cyHeight
);
1495 DPRINT1("NtGdiCreateCompatibleBitmap() failed!\n");
1499 /* make sure we have a 32 bit offscreen bitmap
1500 otherwise we can't do alpha blending */
1501 psurfOff
= SURFACE_LockSurface(hbmOff
);
1502 if (psurfOff
== NULL
)
1504 DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
1507 BITMAP_GetObject(psurfOff
, sizeof(BITMAP
), (PVOID
)&bm
);
1509 if (bm
.bmBitsPixel
!= 32)
1512 SURFACE_UnlockSurface(psurfOff
);
1514 hOldOffBmp
= NtGdiSelectBitmap(hdcOff
, hbmOff
);
1517 DPRINT1("NtGdiSelectBitmap() failed!\n");
1523 hOldOffBrush
= NtGdiSelectBrush(hdcOff
, hbrFlickerFreeDraw
);
1526 DPRINT1("NtGdiSelectBrush() failed!\n");
1530 NtGdiPatBlt(hdcOff
, 0, 0, r
.right
, r
.bottom
, PATCOPY
);
1536 if (diFlags
& DI_IMAGE
)
1538 hdcImage
= NtGdiCreateCompatibleDC(hDc
);
1541 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1544 hOldImage
= NtGdiSelectBitmap(hdcImage
, (hbmColor
? hbmColor
: hbmMask
));
1547 DPRINT("NtGdiSelectBitmap() failed!\n");
1552 /* If DI_IMAGE flag is specified and hbmMask exists, then always use mask for drawing */
1553 if (diFlags
& DI_MASK
|| (diFlags
& DI_IMAGE
&& hbmMask
))
1555 hdcMask
= NtGdiCreateCompatibleDC(hDc
);
1558 DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
1562 hOldMask
= NtGdiSelectBitmap(hdcMask
, hbmMask
);
1565 DPRINT("NtGdiSelectBitmap() failed!\n");
1570 if (hdcMask
|| hdcImage
)
1572 GreStretchBltMask(hdcOff
,
1573 (DoFlickerFree
|| bAlpha
) ? 0 : xLeft
,
1574 (DoFlickerFree
|| bAlpha
) ? 0 : yTop
,
1577 hdcImage
? hdcImage
: hdcMask
,
1579 ((diFlags
& DI_MASK
&& !(diFlags
& DI_IMAGE
)) ||
1580 (diFlags
& DI_IMAGE
&& hbmColor
) ? 0 : IconSize
.cy
),
1585 hdcImage
? hdcMask
: NULL
);
1588 if (hOldMask
) NtGdiSelectBitmap(hdcMask
, hOldMask
);
1589 if (hOldImage
) NtGdiSelectBitmap(hdcImage
, hOldImage
);
1590 if (hdcImage
) NtGdiDeleteObjectApp(hdcImage
);
1591 if (hdcMask
) NtGdiDeleteObjectApp(hdcMask
);
1596 SURFACE
*psurfOff
= NULL
;
1598 BLENDFUNCTION BlendFunc
;
1600 BYTE Red
, Green
, Blue
, Alpha
;
1604 psurfOff
= SURFACE_LockSurface(hbmOff
);
1605 if (psurfOff
== NULL
)
1607 DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
1610 BITMAP_GetObject(psurfOff
, sizeof(BITMAP
), (PVOID
)&bm
);
1612 pBits
= ExAllocatePoolWithTag(PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1615 DPRINT1("ExAllocatePoolWithTag() failed!\n");
1616 SURFACE_UnlockSurface(psurfOff
);
1621 IntGetBitmapBits(psurfOff
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), pBits
);
1623 /* premultiply with the alpha channel value */
1624 for (i
= 0; i
< cyHeight
; i
++)
1626 for (j
= 0; j
< cxWidth
; j
++)
1628 Pixel
= *(DWORD
*)(pBits
+ Count
);
1630 Alpha
= ((BYTE
)(Pixel
>> 24) & 0xff);
1632 Red
= (((BYTE
)(Pixel
>> 0)) * Alpha
) / 0xff;
1633 Green
= (((BYTE
)(Pixel
>> 8)) * Alpha
) / 0xff;
1634 Blue
= (((BYTE
)(Pixel
>> 16)) * Alpha
) / 0xff;
1636 *(DWORD
*)(pBits
+ Count
) = (DWORD
)(Red
| (Green
<< 8) | (Blue
<< 16) | (Alpha
<< 24));
1638 Count
+= sizeof(DWORD
);
1643 IntSetBitmapBits(psurfOff
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), pBits
);
1644 ExFreePoolWithTag(pBits
, TAG_BITMAP
);
1646 SURFACE_UnlockSurface(psurfOff
);
1648 BlendFunc
.BlendOp
= AC_SRC_OVER
;
1649 BlendFunc
.BlendFlags
= 0;
1650 BlendFunc
.SourceConstantAlpha
= 255;
1651 BlendFunc
.AlphaFormat
= AC_SRC_ALPHA
;
1653 NtGdiAlphaBlend(hDc
, xLeft
, yTop
, cxWidth
, cyHeight
,
1654 hdcOff
, 0, 0, cxWidth
, cyHeight
, BlendFunc
, 0);
1656 else if (DoFlickerFree
)
1658 NtGdiBitBlt(hDc
, xLeft
, yTop
, cxWidth
,
1659 cyHeight
, hdcOff
, 0, 0, SRCCOPY
, 0, 0);
1665 if (DoFlickerFree
|| bAlpha
)
1667 if (hOldOffBmp
) NtGdiSelectBitmap(hdcOff
, hOldOffBmp
);
1668 if (hOldOffBrush
) NtGdiSelectBrush(hdcOff
, hOldOffBrush
);
1669 if (hbmOff
) GreDeleteObject(hbmOff
);
1670 if (hdcOff
) NtGdiDeleteObjectApp(hdcOff
);
1689 HBRUSH hbrFlickerFreeDraw
,
1694 PCURICON_OBJECT pIcon
;
1697 DPRINT("Enter NtUserDrawIconEx\n");
1698 UserEnterExclusive();
1700 if (!(pIcon
= UserGetCurIconObject(hIcon
)))
1702 DPRINT1("UserGetCurIconObject() failed!\n");
1707 Ret
= UserDrawIconEx(hdc
,
1717 UserDereferenceObject(pIcon
);
1723 /* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
1724 * User32 macro NtUserShowCursor */
1727 UserShowCursor(BOOL bShow
)
1729 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1730 PWINSTATION_OBJECT WinSta
= pti
->Desktop
->WindowStation
;
1731 PSYSTEM_CURSORINFO CurInfo
;
1741 if (!(Screen
= IntGetScreenDC()))
1743 return showpointer
; /* No mouse */
1746 dc
= DC_LockDc(Screen
);
1750 return showpointer
; /* No mouse */
1753 psurfDc
= dc
->dclevel
.pSurface
;
1758 return showpointer
; /* No Mouse */
1761 SurfObj
= &psurfDc
->SurfObj
;
1762 if (SurfObj
== NULL
)
1765 return showpointer
; /* No mouse */
1768 ppdev
= GDIDEV(SurfObj
);
1773 return showpointer
; /* No mouse */
1776 pgp
= &ppdev
->Pointer
;
1778 CurInfo
= IntGetSysCursorInfo(WinSta
);
1783 showpointer
= pgp
->ShowPointer
;
1785 if (showpointer
>= 0)
1787 //ppdev->SafetyRemoveCount = 1;
1788 //ppdev->SafetyRemoveLevel = 1;
1789 IntEngMovePointer(SurfObj
,-1,-1,NULL
);
1790 CurInfo
->ShowingCursor
= 0;
1797 showpointer
= pgp
->ShowPointer
;
1800 if (showpointer
< 0)
1802 //ppdev->SafetyRemoveCount = 0;
1803 //ppdev->SafetyRemoveLevel = 0;
1804 IntEngMovePointer(SurfObj
,-1,-1,NULL
);
1805 CurInfo
->ShowingCursor
= CURSOR_SHOWING
;