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
;
47 /* Look up the location of the cursor in the GDIDEVICE structure
48 * when all we know is the window station object
49 * Actually doesn't use the window station, but should... */
51 IntGetCursorLocation(PWINSTATION_OBJECT WinSta
, POINT
*loc
)
58 /* FIXME - get the screen dc from the window station or desktop */
59 if (!(hDC
= IntGetScreenDC()))
63 if (!(dc
= DC_LockDc(hDC
)))
65 GDIDevice
= (GDIDEVICE
*)dc
->GDIDevice
;
68 loc
->x
= GDIDevice
->Pointer
.Pos
.x
;
69 loc
->y
= GDIDevice
->Pointer
.Pos
.y
;
76 PCURICON_OBJECT FASTCALL
UserGetCurIconObject(HCURSOR hCurIcon
)
78 PCURICON_OBJECT CurIcon
;
82 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
86 CurIcon
= (PCURICON_OBJECT
)UserGetObject(&gHandleTable
, hCurIcon
, otCursorIcon
);
89 /* we never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */
90 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
94 ASSERT(USER_BODY_TO_HEADER(CurIcon
)->RefCount
>= 0);
99 #define COLORCURSORS_ALLOWED FALSE
101 IntSetCursor(PWINSTATION_OBJECT WinSta
, PCURICON_OBJECT NewCursor
,
104 BITMAPOBJ
*BitmapObj
;
107 PBITMAPOBJ MaskBmpObj
= NULL
;
108 PSYSTEM_CURSORINFO CurInfo
;
109 PCURICON_OBJECT OldCursor
;
110 HCURSOR Ret
= (HCURSOR
)0;
111 HBITMAP dcbmp
, hColor
= (HBITMAP
)0;
113 SURFOBJ
*soMask
= NULL
, *soColor
= NULL
;
114 XLATEOBJ
*XlateObj
= NULL
;
117 CurInfo
= IntGetSysCursorInfo(WinSta
);
118 OldCursor
= CurInfo
->CurrentCursorObject
;
121 Ret
= (HCURSOR
)OldCursor
->Self
;
124 if (!ForceChange
&& OldCursor
== NewCursor
)
130 if(!(Screen
= IntGetScreenDC()))
134 /* FIXME use the desktop's HDC instead of using ScreenDeviceContext */
135 PDC dc
= DC_LockDc(Screen
);
141 dcbmp
= dc
->w
.hBitmap
;
142 DevInfo
= dc
->DevInfo
;
145 BitmapObj
= BITMAPOBJ_LockBitmap(dcbmp
);
148 SurfObj
= &BitmapObj
->SurfObj
;
152 if (!NewCursor
&& (CurInfo
->CurrentCursorObject
|| ForceChange
))
154 if (NULL
!= CurInfo
->CurrentCursorObject
&& CurInfo
->ShowingCursor
)
156 /* Remove the cursor if it was displayed */
157 IntEngMovePointer(SurfObj
, -1, -1, &GDIDEV(SurfObj
)->Pointer
.Exclude
);
160 GDIDEV(SurfObj
)->Pointer
.Status
= SPS_ACCEPT_NOEXCLUDE
;
162 CurInfo
->CurrentCursorObject
= NewCursor
; /* i.e. CurrentCursorObject = NULL */
163 CurInfo
->ShowingCursor
= 0;
164 BITMAPOBJ_UnlockBitmap(BitmapObj
);
170 BITMAPOBJ_UnlockBitmap(BitmapObj
);
174 /* TODO: Fixme. Logic is screwed above */
177 MaskBmpObj
= BITMAPOBJ_LockBitmap(NewCursor
->IconInfo
.hbmMask
);
180 const int maskBpp
= BitsPerFormat(MaskBmpObj
->SurfObj
.iBitmapFormat
);
181 BITMAPOBJ_UnlockBitmap(MaskBmpObj
);
184 DPRINT1("SetCursor: The Mask bitmap must have 1BPP!\n");
185 BITMAPOBJ_UnlockBitmap(BitmapObj
);
189 if ((DevInfo
->flGraphicsCaps2
& GCAPS2_ALPHACURSOR
) &&
190 SurfObj
->iBitmapFormat
>= BMF_16BPP
&&
191 SurfObj
->iBitmapFormat
<= BMF_32BPP
&&
192 NewCursor
->Shadow
&& COLORCURSORS_ALLOWED
)
194 /* FIXME - Create a color pointer, only 32bit bitmap, set alpha bits!
195 Do not pass a mask bitmap to DrvSetPointerShape()!
196 Create a XLATEOBJ that describes the colors of the bitmap. */
197 DPRINT1("SetCursor: (Colored) alpha cursors are not supported!\n");
201 if(NewCursor
->IconInfo
.hbmColor
202 && COLORCURSORS_ALLOWED
)
204 /* FIXME - Create a color pointer, create only one 32bit bitmap!
205 Do not pass a mask bitmap to DrvSetPointerShape()!
206 Create a XLATEOBJ that describes the colors of the bitmap.
207 (16bit bitmaps are propably allowed) */
208 DPRINT1("SetCursor: Cursors with colors are not supported!\n");
212 MaskBmpObj
= BITMAPOBJ_LockBitmap(NewCursor
->IconInfo
.hbmMask
);
215 RECTL DestRect
= {0, 0, MaskBmpObj
->SurfObj
.sizlBitmap
.cx
, MaskBmpObj
->SurfObj
.sizlBitmap
.cy
};
216 POINTL SourcePoint
= {0, 0};
219 * NOTE: For now we create the cursor in top-down bitmap,
220 * because VMware driver rejects it otherwise. This should
223 hMask
= EngCreateBitmap(
224 MaskBmpObj
->SurfObj
.sizlBitmap
, abs(MaskBmpObj
->SurfObj
.lDelta
),
225 MaskBmpObj
->SurfObj
.iBitmapFormat
, BMF_TOPDOWN
,
229 BITMAPOBJ_UnlockBitmap(MaskBmpObj
);
230 BITMAPOBJ_UnlockBitmap(BitmapObj
);
233 soMask
= EngLockSurface((HSURF
)hMask
);
234 EngCopyBits(soMask
, &MaskBmpObj
->SurfObj
, NULL
, NULL
,
235 &DestRect
, &SourcePoint
);
236 BITMAPOBJ_UnlockBitmap(MaskBmpObj
);
240 CurInfo
->ShowingCursor
= CURSOR_SHOWING
;
241 CurInfo
->CurrentCursorObject
= NewCursor
;
245 CurInfo
->ShowingCursor
= 0;
246 CurInfo
->CurrentCursorObject
= NULL
;
249 if (GDIDEVFUNCS(SurfObj
).SetPointerShape
)
251 GDIDEV(SurfObj
)->Pointer
.Status
=
252 GDIDEVFUNCS(SurfObj
).SetPointerShape(
253 SurfObj
, soMask
, soColor
, XlateObj
,
254 NewCursor
->IconInfo
.xHotspot
,
255 NewCursor
->IconInfo
.yHotspot
,
256 GDIDEV(SurfObj
)->Pointer
.Pos
.x
,
257 GDIDEV(SurfObj
)->Pointer
.Pos
.y
,
258 &(GDIDEV(SurfObj
)->Pointer
.Exclude
),
260 DPRINT("SetCursor: DrvSetPointerShape() returned %x\n",
261 GDIDEV(SurfObj
)->Pointer
.Status
);
265 GDIDEV(SurfObj
)->Pointer
.Status
= SPS_DECLINE
;
268 if(GDIDEV(SurfObj
)->Pointer
.Status
== SPS_DECLINE
)
270 GDIDEV(SurfObj
)->Pointer
.Status
= EngSetPointerShape(
271 SurfObj
, soMask
, soColor
, XlateObj
,
272 NewCursor
->IconInfo
.xHotspot
,
273 NewCursor
->IconInfo
.yHotspot
,
274 GDIDEV(SurfObj
)->Pointer
.Pos
.x
,
275 GDIDEV(SurfObj
)->Pointer
.Pos
.y
,
276 &(GDIDEV(SurfObj
)->Pointer
.Exclude
),
278 GDIDEV(SurfObj
)->Pointer
.MovePointer
= NULL
;
282 GDIDEV(SurfObj
)->Pointer
.MovePointer
= GDIDEVFUNCS(SurfObj
).MovePointer
;
285 BITMAPOBJ_UnlockBitmap(BitmapObj
);
288 EngUnlockSurface(soMask
);
289 EngDeleteSurface((HSURF
)hMask
);
293 EngDeleteSurface((HSURF
)hColor
);
297 EngDeleteXlate(XlateObj
);
300 if(GDIDEV(SurfObj
)->Pointer
.Status
== SPS_ERROR
)
301 DPRINT1("SetCursor: DrvSetPointerShape() returned SPS_ERROR\n");
307 IntSetupCurIconHandles(PWINSTATION_OBJECT WinSta
)
309 ExInitializePagedLookasideList(&gProcessLookasideList
,
313 sizeof(CURICON_PROCESS
),
316 InitializeListHead(&gCurIconList
);
322 * We have to register that this object is in use by the current
323 * process. The only way to do that seems to be to walk the list
324 * of cursor/icon objects starting at W32Process->CursorIconListHead.
325 * If the object is already present in the list, we don't have to do
326 * anything, if it's not present we add it and inc the ProcessCount
327 * in the object. Having to walk the list kind of sucks, but that's
330 static BOOLEAN FASTCALL
331 ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon
)
333 PW32PROCESS Win32Process
;
334 PCURICON_PROCESS Current
;
336 Win32Process
= PsGetWin32Process();
338 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
340 if (Current
->Process
== Win32Process
)
342 /* Already registered for this process */
347 /* Not registered yet */
348 Current
= ExAllocateFromPagedLookasideList(&gProcessLookasideList
);
353 InsertHeadList(&CurIcon
->ProcessList
, &Current
->ListEntry
);
354 Current
->Process
= Win32Process
;
359 PCURICON_OBJECT FASTCALL
360 IntFindExistingCurIconObject(PWINSTATION_OBJECT WinSta
, HMODULE hModule
,
361 HRSRC hRsrc
, LONG cx
, LONG cy
)
363 PCURICON_OBJECT CurIcon
;
365 LIST_FOR_EACH(CurIcon
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
368 // if(NT_SUCCESS(ObmReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
369 // ObmReferenceObject( CurIcon);
371 if((CurIcon
->hModule
== hModule
) && (CurIcon
->hRsrc
== hRsrc
))
373 if(cx
&& ((cx
!= CurIcon
->Size
.cx
) || (cy
!= CurIcon
->Size
.cy
)))
375 // ObmDereferenceObject(CurIcon);
378 if (! ReferenceCurIconByProcess(CurIcon
))
386 // ObmDereferenceObject(CurIcon);
393 PCURICON_OBJECT FASTCALL
394 IntCreateCurIconHandle(PWINSTATION_OBJECT WinSta
)
396 PCURICON_OBJECT CurIcon
;
399 CurIcon
= ObmCreateObject(&gHandleTable
, &hCurIcon
, otCursorIcon
, sizeof(CURICON_OBJECT
));
403 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
407 CurIcon
->Self
= hCurIcon
;
408 InitializeListHead(&CurIcon
->ProcessList
);
410 if (! ReferenceCurIconByProcess(CurIcon
))
412 DPRINT1("Failed to add process\n");
413 ObmDeleteObject(hCurIcon
, otCursorIcon
);
414 ObmDereferenceObject(CurIcon
);
418 InsertHeadList(&gCurIconList
, &CurIcon
->ListEntry
);
420 ObmDereferenceObject(CurIcon
);
426 IntDestroyCurIconObject(PWINSTATION_OBJECT WinSta
, PCURICON_OBJECT CurIcon
, BOOL ProcessCleanup
)
428 PSYSTEM_CURSORINFO CurInfo
;
429 HBITMAP bmpMask
, bmpColor
;
431 PCURICON_PROCESS Current
= NULL
;
432 PW32PROCESS W32Process
= PsGetWin32Process();
434 /* Private objects can only be destroyed by their own process */
435 if (NULL
== CurIcon
->hModule
)
437 ASSERT(CurIcon
->ProcessList
.Flink
->Flink
== &CurIcon
->ProcessList
);
438 Current
= CONTAINING_RECORD(CurIcon
->ProcessList
.Flink
, CURICON_PROCESS
, ListEntry
);
439 if (Current
->Process
!= W32Process
)
441 DPRINT1("Trying to destroy private icon/cursor of another process\n");
445 else if (! ProcessCleanup
)
447 DPRINT("Trying to destroy shared icon/cursor\n");
451 /* Now find this process in the list of processes referencing this object and
452 remove it from that list */
453 LIST_FOR_EACH(Current
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
455 if (Current
->Process
== W32Process
)
457 RemoveEntryList(&Current
->ListEntry
);
462 ExFreeToPagedLookasideList(&gProcessLookasideList
, Current
);
464 /* If there are still processes referencing this object we can't destroy it yet */
465 if (! IsListEmpty(&CurIcon
->ProcessList
))
471 if (! ProcessCleanup
)
473 RemoveEntryList(&CurIcon
->ListEntry
);
476 CurInfo
= IntGetSysCursorInfo(WinSta
);
478 if (CurInfo
->CurrentCursorObject
== CurIcon
)
480 /* Hide the cursor if we're destroying the current cursor */
481 IntSetCursor(WinSta
, NULL
, TRUE
);
484 bmpMask
= CurIcon
->IconInfo
.hbmMask
;
485 bmpColor
= CurIcon
->IconInfo
.hbmColor
;
487 Ret
= ObmDeleteObject(CurIcon
->Self
, otCursorIcon
);
492 GDIOBJ_SetOwnership(bmpMask
, PsGetCurrentProcess());
493 NtGdiDeleteObject(bmpMask
);
497 GDIOBJ_SetOwnership(bmpColor
, PsGetCurrentProcess());
498 NtGdiDeleteObject(bmpColor
);
505 IntCleanupCurIcons(struct _EPROCESS
*Process
, PW32PROCESS Win32Process
)
507 PWINSTATION_OBJECT WinSta
;
508 PCURICON_OBJECT CurIcon
, tmp
;
509 PCURICON_PROCESS ProcessData
;
511 WinSta
= IntGetWinStaObj();
517 LIST_FOR_EACH_SAFE(CurIcon
, tmp
, &gCurIconList
, CURICON_OBJECT
, ListEntry
)
519 // ObmReferenceObject(CurIcon);
520 // if(NT_SUCCESS(ObmReferenceObjectByPointer(Object, otCursorIcon)))
522 LIST_FOR_EACH(ProcessData
, &CurIcon
->ProcessList
, CURICON_PROCESS
, ListEntry
)
524 if (Win32Process
== ProcessData
->Process
)
526 RemoveEntryList(&CurIcon
->ListEntry
);
527 IntDestroyCurIconObject(WinSta
, CurIcon
, TRUE
);
532 // ObmDereferenceObject(Object);
538 ObDereferenceObject(WinSta
);
546 NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL
, BOOL Indirect
)
548 PCURICON_OBJECT CurIcon
;
549 PWINSTATION_OBJECT WinSta
;
553 DECLARE_RETURN(HANDLE
);
555 DPRINT("Enter NtUserCreateCursorIconHandle\n");
556 UserEnterExclusive();
558 WinSta
= IntGetWinStaObj();
564 if (!(CurIcon
= IntCreateCurIconHandle(WinSta
)))
566 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
567 ObDereferenceObject(WinSta
);
575 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
, IconInfo
, sizeof(ICONINFO
));
576 if(NT_SUCCESS(Status
))
580 CurIcon
->IconInfo
.hbmMask
= BITMAPOBJ_CopyBitmap(CurIcon
->IconInfo
.hbmMask
);
581 CurIcon
->IconInfo
.hbmColor
= BITMAPOBJ_CopyBitmap(CurIcon
->IconInfo
.hbmColor
);
583 if(CurIcon
->IconInfo
.hbmColor
&&
584 (bmp
= BITMAPOBJ_LockBitmap(CurIcon
->IconInfo
.hbmColor
)))
586 CurIcon
->Size
.cx
= bmp
->SurfObj
.sizlBitmap
.cx
;
587 CurIcon
->Size
.cy
= bmp
->SurfObj
.sizlBitmap
.cy
;
588 BITMAPOBJ_UnlockBitmap(bmp
);
589 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
591 if(CurIcon
->IconInfo
.hbmMask
&&
592 (bmp
= BITMAPOBJ_LockBitmap(CurIcon
->IconInfo
.hbmMask
)))
594 if (CurIcon
->IconInfo
.hbmColor
== NULL
)
596 CurIcon
->Size
.cx
= bmp
->SurfObj
.sizlBitmap
.cx
;
597 CurIcon
->Size
.cy
= bmp
->SurfObj
.sizlBitmap
.cy
/ 2;
599 BITMAPOBJ_UnlockBitmap(bmp
);
600 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
605 SetLastNtError(Status
);
606 /* FIXME - Don't exit here */
610 ObDereferenceObject(WinSta
);
614 DPRINT("Leave NtUserCreateCursorIconHandle, ret=%i\n",_ret_
);
624 NtUserGetCursorIconInfo(
629 PCURICON_OBJECT CurIcon
;
630 PWINSTATION_OBJECT WinSta
;
633 DECLARE_RETURN(BOOL
);
635 DPRINT("Enter NtUserGetCursorIconInfo\n");
636 UserEnterExclusive();
640 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
644 WinSta
= IntGetWinStaObj();
650 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
652 ObDereferenceObject(WinSta
);
656 RtlCopyMemory(&ii
, &CurIcon
->IconInfo
, sizeof(ICONINFO
));
659 ii
.hbmMask
= BITMAPOBJ_CopyBitmap(ii
.hbmMask
);
660 ii
.hbmColor
= BITMAPOBJ_CopyBitmap(ii
.hbmColor
);
663 Status
= MmCopyToCaller(IconInfo
, &ii
, sizeof(ICONINFO
));
664 if(NT_SUCCESS(Status
))
667 SetLastNtError(Status
);
669 ObDereferenceObject(WinSta
);
673 DPRINT("Leave NtUserGetCursorIconInfo, ret=%i\n",_ret_
);
684 NtUserGetCursorIconSize(
689 PCURICON_OBJECT CurIcon
;
691 PWINSTATION_OBJECT WinSta
;
695 DECLARE_RETURN(BOOL
);
697 DPRINT("Enter NtUserGetCursorIconSize\n");
698 UserEnterExclusive();
700 WinSta
= IntGetWinStaObj();
706 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
708 ObDereferenceObject(WinSta
);
713 Status
= MmCopyToCaller(fIcon
, &CurIcon
->IconInfo
.fIcon
, sizeof(BOOL
));
714 if(!NT_SUCCESS(Status
))
716 SetLastNtError(Status
);
720 bmp
= BITMAPOBJ_LockBitmap(CurIcon
->IconInfo
.hbmColor
);
724 SafeSize
.cx
= bmp
->SurfObj
.sizlBitmap
.cx
;
725 SafeSize
.cy
= bmp
->SurfObj
.sizlBitmap
.cy
;
726 Status
= MmCopyToCaller(Size
, &SafeSize
, sizeof(SIZE
));
727 if(NT_SUCCESS(Status
))
730 SetLastNtError(Status
);
732 BITMAPOBJ_UnlockBitmap(bmp
);
735 ObDereferenceObject(WinSta
);
739 DPRINT("Leave NtUserGetCursorIconSize, ret=%i\n",_ret_
);
750 NtUserGetCursorFrameInfo(
771 PSYSTEM_CURSORINFO CurInfo
;
772 PWINSTATION_OBJECT WinSta
;
774 PCURICON_OBJECT CurIcon
;
775 DECLARE_RETURN(BOOL
);
777 DPRINT("Enter NtUserGetCursorInfo\n");
778 UserEnterExclusive();
784 /* FIXME - get the screen dc from the window station or desktop */
785 if (!(hDC
= IntGetScreenDC()))
791 Status
= MmCopyFromCaller(&SafeCi
.cbSize
, pci
, sizeof(DWORD
));
792 if(!NT_SUCCESS(Status
))
794 SetLastNtError(Status
);
798 if(SafeCi
.cbSize
!= sizeof(CURSORINFO
))
800 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
804 WinSta
= IntGetWinStaObj();
810 CurInfo
= IntGetSysCursorInfo(WinSta
);
811 CurIcon
= (PCURICON_OBJECT
)CurInfo
->CurrentCursorObject
;
813 SafeCi
.flags
= ((CurInfo
->ShowingCursor
&& CurIcon
) ? CURSOR_SHOWING
: 0);
814 SafeCi
.hCursor
= (CurIcon
? (HCURSOR
)CurIcon
->Self
: (HCURSOR
)0);
816 IntGetCursorLocation(WinSta
, &SafeCi
.ptScreenPos
);
818 Status
= MmCopyToCaller(pci
, &SafeCi
, sizeof(CURSORINFO
));
819 if(!NT_SUCCESS(Status
))
821 ObDereferenceObject(WinSta
);
822 SetLastNtError(Status
);
826 ObDereferenceObject(WinSta
);
830 DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_
);
844 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
846 PWINSTATION_OBJECT WinSta
;
847 PSYSTEM_CURSORINFO CurInfo
;
849 PWINDOW_OBJECT DesktopWindow
= NULL
;
850 POINT MousePos
= {0};
851 DECLARE_RETURN(BOOL
);
853 DPRINT("Enter NtUserClipCursor\n");
854 UserEnterExclusive();
856 WinSta
= IntGetWinStaObj();
862 if (NULL
!= UnsafeRect
&& ! NT_SUCCESS(MmCopyFromCaller(&Rect
, UnsafeRect
, sizeof(RECT
))))
864 ObDereferenceObject(WinSta
);
865 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
869 CurInfo
= IntGetSysCursorInfo(WinSta
);
870 IntGetCursorLocation(WinSta
, &MousePos
);
872 if(WinSta
->ActiveDesktop
)
873 DesktopWindow
= UserGetWindowObject(WinSta
->ActiveDesktop
->DesktopWindow
);
875 if((Rect
.right
> Rect
.left
) && (Rect
.bottom
> Rect
.top
)
876 && DesktopWindow
&& UnsafeRect
!= NULL
)
880 CurInfo
->CursorClipInfo
.IsClipped
= TRUE
;
881 CurInfo
->CursorClipInfo
.Left
= max(Rect
.left
, DesktopWindow
->WindowRect
.left
);
882 CurInfo
->CursorClipInfo
.Top
= max(Rect
.top
, DesktopWindow
->WindowRect
.top
);
883 CurInfo
->CursorClipInfo
.Right
= min(Rect
.right
- 1, DesktopWindow
->WindowRect
.right
- 1);
884 CurInfo
->CursorClipInfo
.Bottom
= min(Rect
.bottom
- 1, DesktopWindow
->WindowRect
.bottom
- 1);
889 mi
.dwFlags
= MOUSEEVENTF_ABSOLUTE
| MOUSEEVENTF_MOVE
;
897 CurInfo
->CursorClipInfo
.IsClipped
= FALSE
;
898 ObDereferenceObject(WinSta
);
903 DPRINT("Leave NtUserClipCursor, ret=%i\n",_ret_
);
914 NtUserDestroyCursorIcon(
918 PWINSTATION_OBJECT WinSta
;
919 PCURICON_OBJECT CurIcon
;
921 DECLARE_RETURN(BOOL
);
923 DPRINT("Enter NtUserDestroyCursorIcon\n");
924 UserEnterExclusive();
926 WinSta
= IntGetWinStaObj();
932 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
934 ObDereferenceObject(WinSta
);
938 ret
= IntDestroyCurIconObject(WinSta
, CurIcon
, FALSE
);
940 ObDereferenceObject(WinSta
);
944 DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_
);
955 NtUserFindExistingCursorIcon(
961 PCURICON_OBJECT CurIcon
;
962 PWINSTATION_OBJECT WinSta
;
963 HANDLE Ret
= (HANDLE
)0;
964 DECLARE_RETURN(HICON
);
966 DPRINT("Enter NtUserFindExistingCursorIcon\n");
967 UserEnterExclusive();
969 WinSta
= IntGetWinStaObj();
975 CurIcon
= IntFindExistingCurIconObject(WinSta
, hModule
, hRsrc
, cx
, cy
);
980 // IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
981 ObDereferenceObject(WinSta
);
985 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
986 ObDereferenceObject(WinSta
);
990 DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_
);
1001 NtUserGetClipCursor(
1004 /* FIXME - check if process has WINSTA_READATTRIBUTES */
1005 PSYSTEM_CURSORINFO CurInfo
;
1006 PWINSTATION_OBJECT WinSta
;
1009 DECLARE_RETURN(BOOL
);
1011 DPRINT("Enter NtUserGetClipCursor\n");
1012 UserEnterExclusive();
1017 WinSta
= IntGetWinStaObj();
1023 CurInfo
= IntGetSysCursorInfo(WinSta
);
1024 if(CurInfo
->CursorClipInfo
.IsClipped
)
1026 Rect
.left
= CurInfo
->CursorClipInfo
.Left
;
1027 Rect
.top
= CurInfo
->CursorClipInfo
.Top
;
1028 Rect
.right
= CurInfo
->CursorClipInfo
.Right
;
1029 Rect
.bottom
= CurInfo
->CursorClipInfo
.Bottom
;
1035 Rect
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1036 Rect
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1039 Status
= MmCopyToCaller((PRECT
)lpRect
, &Rect
, sizeof(RECT
));
1040 if(!NT_SUCCESS(Status
))
1042 ObDereferenceObject(WinSta
);
1043 SetLastNtError(Status
);
1047 ObDereferenceObject(WinSta
);
1052 DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_
);
1066 PCURICON_OBJECT CurIcon
;
1068 PWINSTATION_OBJECT WinSta
;
1069 DECLARE_RETURN(HCURSOR
);
1071 DPRINT("Enter NtUserSetCursor\n");
1072 UserEnterExclusive();
1074 WinSta
= IntGetWinStaObj();
1080 if(!(CurIcon
= UserGetCurIconObject(hCursor
)))
1082 ObDereferenceObject(WinSta
);
1086 OldCursor
= IntSetCursor(WinSta
, CurIcon
, FALSE
);
1088 ObDereferenceObject(WinSta
);
1093 DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_
);
1104 NtUserSetCursorIconContents(
1108 PCURICON_OBJECT CurIcon
;
1110 PWINSTATION_OBJECT WinSta
;
1113 DECLARE_RETURN(BOOL
);
1115 DPRINT("Enter NtUserSetCursorIconContents\n");
1116 UserEnterExclusive();
1118 WinSta
= IntGetWinStaObj();
1124 if (!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1126 ObDereferenceObject(WinSta
);
1131 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
, IconInfo
, sizeof(ICONINFO
));
1132 if(!NT_SUCCESS(Status
))
1134 SetLastNtError(Status
);
1138 bmp
= BITMAPOBJ_LockBitmap(CurIcon
->IconInfo
.hbmColor
);
1141 CurIcon
->Size
.cx
= bmp
->SurfObj
.sizlBitmap
.cx
;
1142 CurIcon
->Size
.cy
= bmp
->SurfObj
.sizlBitmap
.cy
;
1143 BITMAPOBJ_UnlockBitmap(bmp
);
1144 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmColor
, NULL
);
1148 bmp
= BITMAPOBJ_LockBitmap(CurIcon
->IconInfo
.hbmMask
);
1152 CurIcon
->Size
.cx
= bmp
->SurfObj
.sizlBitmap
.cx
;
1153 CurIcon
->Size
.cy
= bmp
->SurfObj
.sizlBitmap
.cy
/ 2;
1155 BITMAPOBJ_UnlockBitmap(bmp
);
1156 GDIOBJ_SetOwnership(CurIcon
->IconInfo
.hbmMask
, NULL
);
1163 ObDereferenceObject(WinSta
);
1167 DPRINT("Leave NtUserSetCursorIconContents, ret=%i\n",_ret_
);
1178 NtUserSetCursorIconData(
1186 PCURICON_OBJECT CurIcon
;
1187 PWINSTATION_OBJECT WinSta
;
1191 DECLARE_RETURN(BOOL
);
1193 DPRINT("Enter NtUserSetCursorIconData\n");
1194 UserEnterExclusive();
1196 WinSta
= IntGetWinStaObj();
1202 if(!(CurIcon
= UserGetCurIconObject(hCurIcon
)))
1204 ObDereferenceObject(WinSta
);
1208 CurIcon
->hModule
= hModule
;
1209 CurIcon
->hRsrc
= hRsrc
;
1210 CurIcon
->hGroupRsrc
= hGroupRsrc
;
1215 Status
= MmCopyFromCaller(&CurIcon
->IconInfo
.fIcon
, fIcon
, sizeof(BOOL
));
1216 if(!NT_SUCCESS(Status
))
1218 SetLastNtError(Status
);
1230 Status
= MmCopyFromCaller(&SafeHotspot
, Hotspot
, sizeof(POINT
));
1231 if(NT_SUCCESS(Status
))
1233 CurIcon
->IconInfo
.xHotspot
= SafeHotspot
.x
;
1234 CurIcon
->IconInfo
.yHotspot
= SafeHotspot
.y
;
1239 SetLastNtError(Status
);
1242 if(!fIcon
&& !Hotspot
)
1248 ObDereferenceObject(WinSta
);
1253 DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_
);
1264 NtUserSetSystemCursor(
1272 #define STRETCH_CAN_SRCCOPY_ONLY
1274 #ifdef STRETCH_CAN_SRCCOPY_ONLY
1277 DoStretchBlt(HDC DcDest
, int XDest
, int YDest
, int WidthDest
, int HeightDest
,
1278 HDC DcSrc
, int XSrc
, int YSrc
, int WidthSrc
, int HeightSrc
,
1279 DWORD Rop3
, BOOL Color
)
1282 HBITMAP BitmapStretched
;
1285 if (WidthDest
== WidthSrc
&& HeightDest
== HeightSrc
)
1287 NtGdiBitBlt(DcDest
, XDest
, YDest
, WidthDest
, HeightDest
,
1288 DcSrc
, XSrc
, YSrc
, Rop3
, 0, 0);
1290 else if (SRCCOPY
== Rop3
)
1292 NtGdiStretchBlt(DcDest
, XDest
, YDest
, WidthDest
, HeightDest
,
1293 DcSrc
, XSrc
, YSrc
, WidthSrc
, HeightSrc
,
1298 DcStretched
= NtGdiCreateCompatibleDC(DcSrc
);
1299 if (NULL
== DcStretched
)
1301 DPRINT1("Failed to create compatible DC\n");
1306 BitmapStretched
= NtGdiCreateCompatibleBitmap(DcDest
, WidthDest
,
1311 BitmapStretched
= NtGdiCreateBitmap(WidthDest
, HeightDest
, 1, 1, NULL
);
1313 if (NULL
== BitmapStretched
)
1315 NtGdiDeleteDC(DcStretched
);
1316 DPRINT1("Failed to create temporary bitmap\n");
1319 OldBitmap
= NtGdiSelectObject(DcStretched
, BitmapStretched
);
1320 if (NULL
== OldBitmap
)
1322 NtGdiDeleteObject(BitmapStretched
);
1323 NtGdiDeleteDC(DcStretched
);
1324 DPRINT1("Failed to create temporary bitmap\n");
1327 if (! NtGdiStretchBlt(DcStretched
, 0, 0, WidthDest
, HeightDest
,
1328 DcSrc
, XSrc
, YSrc
, WidthSrc
, HeightSrc
,
1330 ! NtGdiBitBlt(DcDest
, XDest
, YDest
, WidthDest
, HeightDest
,
1331 DcStretched
, 0, 0, Rop3
, 0, 0))
1333 DPRINT1("Failed to blt\n");
1335 NtGdiSelectObject(DcStretched
, OldBitmap
);
1336 NtGdiDeleteObject(BitmapStretched
);
1337 NtGdiDeleteDC(DcStretched
);
1341 #define DoStretchBlt(DcDest, XDest, YDest, WidthDest, HeightDest, \
1342 DcSrc, XSrc, YSrc, WidthSrc, HeightSrc, Rop3, Color) \
1343 NtGdiStretchBlt((DcDest), (XDest), (YDest), (WidthDest), (HeightDest), \
1344 (DcSrc), (XSrc), (YSrc), (WidthSrc), (HeightSrc), \
1346 #endif /* STRETCH_CAN_SRCCOPY_ONLY */
1361 HBRUSH hbrFlickerFreeDraw
,
1366 PCURICON_OBJECT CurIcon
;
1367 PWINSTATION_OBJECT WinSta
;
1368 HBITMAP hbmMask
, hbmColor
;
1369 BITMAP bmpMask
, bmpColor
;
1372 COLORREF oldFg
, oldBg
;
1373 HDC hdcMem
, hdcOff
= (HDC
)0;
1374 HBITMAP hbmOff
= (HBITMAP
)0;
1375 HGDIOBJ hOldOffBrush
= 0, hOldOffBmp
= 0, hOldMem
;
1379 DECLARE_RETURN(BOOL
);
1381 DPRINT("Enter NtUserDrawIconEx\n");
1382 UserEnterExclusive();
1384 WinSta
= IntGetWinStaObj();
1390 if (!(CurIcon
= UserGetCurIconObject(hIcon
)))
1392 ObDereferenceObject(WinSta
);
1396 hbmMask
= CurIcon
->IconInfo
.hbmMask
;
1397 hbmColor
= CurIcon
->IconInfo
.hbmColor
;
1400 DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
1402 if(!hbmMask
|| !IntGdiGetObject(hbmMask
, sizeof(BITMAP
), &bmpMask
))
1405 if(hbmColor
&& !IntGdiGetObject(hbmColor
, sizeof(BITMAP
), &bmpColor
))
1410 IconSize
.cx
= bmpColor
.bmWidth
;
1411 IconSize
.cy
= bmpColor
.bmHeight
;
1415 IconSize
.cx
= bmpMask
.bmWidth
;
1416 IconSize
.cy
= bmpMask
.bmHeight
/ 2;
1420 diFlags
= DI_NORMAL
;
1423 cxWidth
= ((diFlags
& DI_DEFAULTSIZE
) ? UserGetSystemMetrics(SM_CXICON
) : IconSize
.cx
);
1425 cyHeight
= ((diFlags
& DI_DEFAULTSIZE
) ? UserGetSystemMetrics(SM_CYICON
) : IconSize
.cy
);
1427 DoFlickerFree
= (hbrFlickerFreeDraw
&& (NtGdiGetObjectType(hbrFlickerFreeDraw
) == OBJ_BRUSH
));
1433 r
.bottom
= cyHeight
;
1435 hdcOff
= NtGdiCreateCompatibleDC(hdc
);
1439 hbmOff
= NtGdiCreateCompatibleBitmap(hdc
, cxWidth
, cyHeight
);
1442 NtGdiDeleteDC(hdcOff
);
1445 hOldOffBrush
= NtGdiSelectObject(hdcOff
, hbrFlickerFreeDraw
);
1446 hOldOffBmp
= NtGdiSelectObject(hdcOff
, hbmOff
);
1447 NtGdiPatBlt(hdcOff
, 0, 0, r
.right
, r
.bottom
, PATCOPY
);
1448 NtGdiSelectObject(hdcOff
, hbmOff
);
1451 hdcMem
= NtGdiCreateCompatibleDC(hdc
);
1458 nStretchMode
= NtGdiSetStretchBltMode(hdcOff
, STRETCH_DELETESCANS
);
1460 oldFg
= NtGdiSetTextColor(hdcOff
, RGB(0, 0, 0));
1461 oldBg
= NtGdiSetBkColor(hdcOff
, RGB(255, 255, 255));
1463 if(diFlags
& DI_MASK
)
1465 hOldMem
= NtGdiSelectObject(hdcMem
, hbmMask
);
1467 DoStretchBlt(hdcOff
, (DoFlickerFree
? 0 : xLeft
),
1468 (DoFlickerFree
? 0 : yTop
), cxWidth
, cyHeight
, hdcMem
,
1469 0, 0, IconSize
.cx
, IconSize
.cy
,
1470 ((diFlags
& DI_IMAGE
) ? SRCAND
: SRCCOPY
), FALSE
);
1472 if(!hbmColor
&& (bmpMask
.bmHeight
== 2 * bmpMask
.bmWidth
) && (diFlags
& DI_IMAGE
))
1474 DoStretchBlt(hdcOff
, (DoFlickerFree
? 0 : xLeft
),
1475 (DoFlickerFree
? 0 : yTop
), cxWidth
, cyHeight
, hdcMem
,
1476 0, IconSize
.cy
, IconSize
.cx
, IconSize
.cy
, SRCINVERT
,
1479 diFlags
&= ~DI_IMAGE
;
1481 NtGdiSelectObject(hdcMem
, hOldMem
);
1484 if(diFlags
& DI_IMAGE
)
1486 hOldMem
= NtGdiSelectObject(hdcMem
, (hbmColor
? hbmColor
: hbmMask
));
1488 DoStretchBlt(hdcOff
, (DoFlickerFree
? 0 : xLeft
),
1489 (DoFlickerFree
? 0 : yTop
), cxWidth
, cyHeight
, hdcMem
,
1490 0, (hbmColor
? 0 : IconSize
.cy
), IconSize
.cx
, IconSize
.cy
,
1491 ((diFlags
& DI_MASK
) ? SRCINVERT
: SRCCOPY
),
1494 NtGdiSelectObject(hdcMem
, hOldMem
);
1498 NtGdiBitBlt(hdc
, xLeft
, yTop
, cxWidth
, cyHeight
, hdcOff
, 0, 0, SRCCOPY
, 0, 0);
1500 NtGdiSetTextColor(hdcOff
, oldFg
);
1501 NtGdiSetBkColor(hdcOff
, oldBg
);
1503 NtGdiSetStretchBltMode(hdcOff
, nStretchMode
);
1511 NtGdiSelectObject(hdcOff
, hOldOffBmp
);
1512 NtGdiSelectObject(hdcOff
, hOldOffBrush
);
1513 NtGdiDeleteObject(hbmOff
);
1514 NtGdiDeleteDC(hdcOff
);
1517 NtGdiDeleteDC(hdcMem
);
1520 ObDereferenceObject(WinSta
);
1525 DPRINT("Leave NtUserDrawIconEx, ret=%i\n",_ret_
);