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 ProcessLookasideList
;
45 static LIST_ENTRY CurIconList
;
46 static FAST_MUTEX CurIconListLock
;
48 /* Look up the location of the cursor in the GDIDEVICE structure
49 * when all we know is the window station object
50 * Actually doesn't use the window station, but should... */
52 IntGetCursorLocation(PWINSTATION_OBJECT WinStaObject
, POINT
*loc
)
59 /* FIXME - get the screen dc from the window station or desktop */
60 if (!(hDC
= IntGetScreenDC()))
64 if (!(dc
= DC_LockDc(hDC
)))
66 GDIDevice
= (GDIDEVICE
*)dc
->GDIDevice
;
69 loc
->x
= GDIDevice
->Pointer
.Pos
.x
;
70 loc
->y
= GDIDevice
->Pointer
.Pos
.y
;
75 PCURICON_OBJECT FASTCALL
76 IntGetCurIconObject(PWINSTATION_OBJECT WinStaObject
, HANDLE Handle
)
78 PCURICON_OBJECT Object
;
81 Status
= ObmReferenceObjectByHandle(WinStaObject
->HandleTable
,
82 Handle
, otCursorIcon
, (PVOID
*)&Object
);
83 if (!NT_SUCCESS(Status
))
90 #define COLORCURSORS_ALLOWED FALSE
92 IntSetCursor(PWINSTATION_OBJECT WinStaObject
, PCURICON_OBJECT NewCursor
,
98 PBITMAPOBJ MaskBmpObj
= NULL
;
99 PSYSTEM_CURSORINFO CurInfo
;
100 PCURICON_OBJECT OldCursor
;
101 HCURSOR Ret
= (HCURSOR
)0;
102 HBITMAP dcbmp
, hColor
= (HBITMAP
)0;
104 SURFOBJ
*soMask
= NULL
, *soColor
= NULL
;
105 XLATEOBJ
*XlateObj
= NULL
;
108 CurInfo
= IntGetSysCursorInfo(WinStaObject
);
109 OldCursor
= CurInfo
->CurrentCursorObject
;
112 Ret
= (HCURSOR
)OldCursor
->Self
;
115 if (!ForceChange
&& OldCursor
== NewCursor
)
121 if(!(Screen
= IntGetScreenDC()))
125 /* FIXME use the desktop's HDC instead of using ScreenDeviceContext */
126 PDC dc
= DC_LockDc(Screen
);
132 dcbmp
= dc
->w
.hBitmap
;
133 DevInfo
= dc
->DevInfo
;
136 BitmapObj
= BITMAPOBJ_LockBitmap(dcbmp
);
139 SurfObj
= &BitmapObj
->SurfObj
;
143 if (!NewCursor
&& (CurInfo
->CurrentCursorObject
|| ForceChange
))
145 if (NULL
!= CurInfo
->CurrentCursorObject
&& CurInfo
->ShowingCursor
)
147 /* Remove the cursor if it was displayed */
148 IntEngMovePointer(SurfObj
, -1, -1, &GDIDEV(SurfObj
)->Pointer
.Exclude
);
151 GDIDEV(SurfObj
)->Pointer
.Status
= SPS_ACCEPT_NOEXCLUDE
;
153 CurInfo
->CurrentCursorObject
= NewCursor
; /* i.e. CurrentCursorObject = NULL */
154 CurInfo
->ShowingCursor
= 0;
155 BITMAPOBJ_UnlockBitmap(BitmapObj
);
161 BITMAPOBJ_UnlockBitmap(BitmapObj
);
165 /* TODO: Fixme. Logic is screwed above */
168 MaskBmpObj
= BITMAPOBJ_LockBitmap(NewCursor
->IconInfo
.hbmMask
);
171 const int maskBpp
= BitsPerFormat(MaskBmpObj
->SurfObj
.iBitmapFormat
);
172 BITMAPOBJ_UnlockBitmap(MaskBmpObj
);
175 DPRINT1("SetCursor: The Mask bitmap must have 1BPP!\n");
176 BITMAPOBJ_UnlockBitmap(BitmapObj
);
180 if ((DevInfo
->flGraphicsCaps2
& GCAPS2_ALPHACURSOR
) &&
181 SurfObj
->iBitmapFormat
>= BMF_16BPP
&&
182 SurfObj
->iBitmapFormat
<= BMF_32BPP
&&
183 NewCursor
->Shadow
&& COLORCURSORS_ALLOWED
)
185 /* FIXME - Create a color pointer, only 32bit bitmap, set alpha bits!
186 Do not pass a mask bitmap to DrvSetPointerShape()!
187 Create a XLATEOBJ that describes the colors of the bitmap. */
188 DPRINT1("SetCursor: (Colored) alpha cursors are not supported!\n");
192 if(NewCursor
->IconInfo
.hbmColor
193 && COLORCURSORS_ALLOWED
)
195 /* FIXME - Create a color pointer, create only one 32bit bitmap!
196 Do not pass a mask bitmap to DrvSetPointerShape()!
197 Create a XLATEOBJ that describes the colors of the bitmap.
198 (16bit bitmaps are propably allowed) */
199 DPRINT1("SetCursor: Cursors with colors are not supported!\n");
203 MaskBmpObj
= BITMAPOBJ_LockBitmap(NewCursor
->IconInfo
.hbmMask
);
206 RECTL DestRect
= {0, 0, MaskBmpObj
->SurfObj
.sizlBitmap
.cx
, MaskBmpObj
->SurfObj
.sizlBitmap
.cy
};
207 POINTL SourcePoint
= {0, 0};
210 * NOTE: For now we create the cursor in top-down bitmap,
211 * because VMware driver rejects it otherwise. This should
214 hMask
= EngCreateBitmap(
215 MaskBmpObj
->SurfObj
.sizlBitmap
, abs(MaskBmpObj
->SurfObj
.lDelta
),
216 MaskBmpObj
->SurfObj
.iBitmapFormat
, BMF_TOPDOWN
,
220 BITMAPOBJ_UnlockBitmap(MaskBmpObj
);
221 BITMAPOBJ_UnlockBitmap(BitmapObj
);
224 soMask
= EngLockSurface((HSURF
)hMask
);
225 EngCopyBits(soMask
, &MaskBmpObj
->SurfObj
, NULL
, NULL
,
226 &DestRect
, &SourcePoint
);
227 BITMAPOBJ_UnlockBitmap(MaskBmpObj
);
231 CurInfo
->ShowingCursor
= CURSOR_SHOWING
;
232 CurInfo
->CurrentCursorObject
= NewCursor
;
236 CurInfo
->ShowingCursor
= 0;
237 CurInfo
->CurrentCursorObject
= NULL
;
240 if (GDIDEVFUNCS(SurfObj
).SetPointerShape
)
242 GDIDEV(SurfObj
)->Pointer
.Status
=
243 GDIDEVFUNCS(SurfObj
).SetPointerShape(
244 SurfObj
, soMask
, soColor
, XlateObj
,
245 NewCursor
->IconInfo
.xHotspot
,
246 NewCursor
->IconInfo
.yHotspot
,
247 GDIDEV(SurfObj
)->Pointer
.Pos
.x
,
248 GDIDEV(SurfObj
)->Pointer
.Pos
.y
,
249 &(GDIDEV(SurfObj
)->Pointer
.Exclude
),
251 DPRINT("SetCursor: DrvSetPointerShape() returned %x\n",
252 GDIDEV(SurfObj
)->Pointer
.Status
);
256 GDIDEV(SurfObj
)->Pointer
.Status
= SPS_DECLINE
;
259 if(GDIDEV(SurfObj
)->Pointer
.Status
== SPS_DECLINE
)
261 GDIDEV(SurfObj
)->Pointer
.Status
= EngSetPointerShape(
262 SurfObj
, soMask
, soColor
, XlateObj
,
263 NewCursor
->IconInfo
.xHotspot
,
264 NewCursor
->IconInfo
.yHotspot
,
265 GDIDEV(SurfObj
)->Pointer
.Pos
.x
,
266 GDIDEV(SurfObj
)->Pointer
.Pos
.y
,
267 &(GDIDEV(SurfObj
)->Pointer
.Exclude
),
269 GDIDEV(SurfObj
)->Pointer
.MovePointer
= NULL
;
273 GDIDEV(SurfObj
)->Pointer
.MovePointer
= GDIDEVFUNCS(SurfObj
).MovePointer
;
276 BITMAPOBJ_UnlockBitmap(BitmapObj
);
279 EngUnlockSurface(soMask
);
280 EngDeleteSurface((HSURF
)hMask
);
284 EngDeleteSurface((HSURF
)hColor
);
288 EngDeleteXlate(XlateObj
);
291 if(GDIDEV(SurfObj
)->Pointer
.Status
== SPS_ERROR
)
292 DPRINT1("SetCursor: DrvSetPointerShape() returned SPS_ERROR\n");
298 IntSetupCurIconHandles(PWINSTATION_OBJECT WinStaObject
)
300 ExInitializePagedLookasideList(&ProcessLookasideList
,
304 sizeof(CURICON_PROCESS
),
307 InitializeListHead(&CurIconList
);
308 ExInitializeFastMutex(&CurIconListLock
);
314 * We have to register that this object is in use by the current
315 * process. The only way to do that seems to be to walk the list
316 * of cursor/icon objects starting at W32Process->CursorIconListHead.
317 * If the object is already present in the list, we don't have to do
318 * anything, if it's not present we add it and inc the ProcessCount
319 * in the object. Having to walk the list kind of sucks, but that's
322 static BOOLEAN FASTCALL
323 ReferenceCurIconByProcess(PCURICON_OBJECT Object
)
325 PW32PROCESS Win32Process
;
327 PCURICON_PROCESS Current
;
329 Win32Process
= PsGetWin32Process();
331 ExAcquireFastMutex(&Object
->Lock
);
332 Search
= Object
->ProcessList
.Flink
;
333 while (Search
!= &Object
->ProcessList
)
335 Current
= CONTAINING_RECORD(Search
, CURICON_PROCESS
, ListEntry
);
336 if (Current
->Process
== Win32Process
)
338 /* Already registered for this process */
339 ExReleaseFastMutex(&Object
->Lock
);
342 Search
= Search
->Flink
;
345 /* Not registered yet */
346 Current
= ExAllocateFromPagedLookasideList(&ProcessLookasideList
);
351 InsertHeadList(&Object
->ProcessList
, &Current
->ListEntry
);
352 Current
->Process
= Win32Process
;
354 ExReleaseFastMutex(&Object
->Lock
);
358 PCURICON_OBJECT FASTCALL
359 IntFindExistingCurIconObject(PWINSTATION_OBJECT WinStaObject
, HMODULE hModule
,
360 HRSRC hRsrc
, LONG cx
, LONG cy
)
362 PLIST_ENTRY CurrentEntry
;
363 PCURICON_OBJECT Object
;
365 ExAcquireFastMutex(&CurIconListLock
);
367 CurrentEntry
= CurIconList
.Flink
;
368 while (CurrentEntry
!= &CurIconList
)
370 Object
= CONTAINING_RECORD(CurrentEntry
, CURICON_OBJECT
, ListEntry
);
371 CurrentEntry
= CurrentEntry
->Flink
;
372 if(NT_SUCCESS(ObmReferenceObjectByPointer(Object
, otCursorIcon
)))
374 if((Object
->hModule
== hModule
) && (Object
->hRsrc
== hRsrc
))
376 if(cx
&& ((cx
!= Object
->Size
.cx
) || (cy
!= Object
->Size
.cy
)))
378 ObmDereferenceObject(Object
);
381 if (! ReferenceCurIconByProcess(Object
))
383 ExReleaseFastMutex(&CurIconListLock
);
386 ExReleaseFastMutex(&CurIconListLock
);
390 ObmDereferenceObject(Object
);
393 ExReleaseFastMutex(&CurIconListLock
);
398 PCURICON_OBJECT FASTCALL
399 IntCreateCurIconHandle(PWINSTATION_OBJECT WinStaObject
)
401 PCURICON_OBJECT Object
;
404 Object
= ObmCreateObject(WinStaObject
->HandleTable
, &Handle
, otCursorIcon
, sizeof(CURICON_OBJECT
));
408 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
412 Object
->Self
= Handle
;
413 ExInitializeFastMutex(&Object
->Lock
);
414 InitializeListHead(&Object
->ProcessList
);
416 if (! ReferenceCurIconByProcess(Object
))
418 DPRINT1("Failed to add process\n");
419 ObmCloseHandle(WinStaObject
->HandleTable
, Handle
);
420 ObmDereferenceObject(Object
);
424 ExAcquireFastMutex(&CurIconListLock
);
425 InsertHeadList(&CurIconList
, &Object
->ListEntry
);
426 ExReleaseFastMutex(&CurIconListLock
);
428 ObmDereferenceObject(Object
);
434 IntDestroyCurIconObject(PWINSTATION_OBJECT WinStaObject
, PCURICON_OBJECT Object
, BOOL ProcessCleanup
)
436 PSYSTEM_CURSORINFO CurInfo
;
437 HBITMAP bmpMask
, bmpColor
;
440 PCURICON_PROCESS Current
= NULL
;
441 PW32PROCESS W32Process
= PsGetWin32Process();
443 ExAcquireFastMutex(&Object
->Lock
);
445 /* Private objects can only be destroyed by their own process */
446 if (NULL
== Object
->hModule
)
448 ASSERT(Object
->ProcessList
.Flink
->Flink
== &Object
->ProcessList
);
449 Current
= CONTAINING_RECORD(Object
->ProcessList
.Flink
, CURICON_PROCESS
, ListEntry
);
450 if (Current
->Process
!= W32Process
)
452 ExReleaseFastMutex(&Object
->Lock
);
453 DPRINT1("Trying to destroy private icon/cursor of another process\n");
457 else if (! ProcessCleanup
)
459 ExReleaseFastMutex(&Object
->Lock
);
460 DPRINT("Trying to destroy shared icon/cursor\n");
464 /* Now find this process in the list of processes referencing this object and
465 remove it from that list */
466 Search
= Object
->ProcessList
.Flink
;
467 while (Search
!= &Object
->ProcessList
)
469 Current
= CONTAINING_RECORD(Search
, CURICON_PROCESS
, ListEntry
);
470 if (Current
->Process
== W32Process
)
474 Search
= Search
->Flink
;
476 ASSERT(Search
!= &Object
->ProcessList
);
477 RemoveEntryList(Search
);
478 ExFreeToPagedLookasideList(&ProcessLookasideList
, Current
);
480 /* If there are still processes referencing this object we can't destroy it yet */
481 if (! IsListEmpty(&Object
->ProcessList
))
483 ExReleaseFastMutex(&Object
->Lock
);
487 ExReleaseFastMutex(&Object
->Lock
);
489 if (! ProcessCleanup
)
491 ExAcquireFastMutex(&CurIconListLock
);
492 RemoveEntryList(&Object
->ListEntry
);
493 ExReleaseFastMutex(&CurIconListLock
);
496 CurInfo
= IntGetSysCursorInfo(WinStaObject
);
498 if (CurInfo
->CurrentCursorObject
== Object
)
500 /* Hide the cursor if we're destroying the current cursor */
501 IntSetCursor(WinStaObject
, NULL
, TRUE
);
504 bmpMask
= Object
->IconInfo
.hbmMask
;
505 bmpColor
= Object
->IconInfo
.hbmColor
;
507 Ret
= NT_SUCCESS(ObmCloseHandle(WinStaObject
->HandleTable
, Object
->Self
));
512 GDIOBJ_SetOwnership(bmpMask
, PsGetCurrentProcess());
513 NtGdiDeleteObject(bmpMask
);
517 GDIOBJ_SetOwnership(bmpColor
, PsGetCurrentProcess());
518 NtGdiDeleteObject(bmpColor
);
525 IntCleanupCurIcons(struct _EPROCESS
*Process
, PW32PROCESS Win32Process
)
527 PWINSTATION_OBJECT WinStaObject
;
528 PLIST_ENTRY CurrentEntry
;
529 PCURICON_OBJECT Object
;
530 PLIST_ENTRY ProcessEntry
;
531 PCURICON_PROCESS ProcessData
;
533 WinStaObject
= IntGetWinStaObj();
534 if(WinStaObject
== NULL
)
539 ExAcquireFastMutex(&CurIconListLock
);
541 CurrentEntry
= CurIconList
.Flink
;
542 while (CurrentEntry
!= &CurIconList
)
544 Object
= CONTAINING_RECORD(CurrentEntry
, CURICON_OBJECT
, ListEntry
);
545 CurrentEntry
= CurrentEntry
->Flink
;
546 if(NT_SUCCESS(ObmReferenceObjectByPointer(Object
, otCursorIcon
)))
548 ExAcquireFastMutex(&Object
->Lock
);
549 ProcessEntry
= Object
->ProcessList
.Flink
;
550 while (ProcessEntry
!= &Object
->ProcessList
)
552 ProcessData
= CONTAINING_RECORD(ProcessEntry
, CURICON_PROCESS
, ListEntry
);
553 if (Win32Process
== ProcessData
->Process
)
555 ExReleaseFastMutex(&Object
->Lock
);
556 RemoveEntryList(&Object
->ListEntry
);
557 IntDestroyCurIconObject(WinStaObject
, Object
, TRUE
);
560 ProcessEntry
= ProcessEntry
->Flink
;
562 if (ProcessEntry
== &Object
->ProcessList
)
564 ExReleaseFastMutex(&Object
->Lock
);
566 ObmDereferenceObject(Object
);
570 ExReleaseFastMutex(&CurIconListLock
);
571 ObDereferenceObject(WinStaObject
);
579 NtUserCreateCursorIconHandle(PICONINFO IconInfo
, BOOL Indirect
)
581 PCURICON_OBJECT CurIconObject
;
582 PWINSTATION_OBJECT WinStaObject
;
587 WinStaObject
= IntGetWinStaObj();
588 if(WinStaObject
== NULL
)
593 CurIconObject
= IntCreateCurIconHandle(WinStaObject
);
596 Ret
= CurIconObject
->Self
;
600 Status
= MmCopyFromCaller(&CurIconObject
->IconInfo
, IconInfo
, sizeof(ICONINFO
));
601 if(NT_SUCCESS(Status
))
605 CurIconObject
->IconInfo
.hbmMask
= BITMAPOBJ_CopyBitmap(CurIconObject
->IconInfo
.hbmMask
);
606 CurIconObject
->IconInfo
.hbmColor
= BITMAPOBJ_CopyBitmap(CurIconObject
->IconInfo
.hbmColor
);
608 if(CurIconObject
->IconInfo
.hbmColor
&&
609 (bmp
= BITMAPOBJ_LockBitmap(CurIconObject
->IconInfo
.hbmColor
)))
611 CurIconObject
->Size
.cx
= bmp
->SurfObj
.sizlBitmap
.cx
;
612 CurIconObject
->Size
.cy
= bmp
->SurfObj
.sizlBitmap
.cy
;
613 BITMAPOBJ_UnlockBitmap(bmp
);
614 GDIOBJ_SetOwnership(CurIconObject
->IconInfo
.hbmColor
, NULL
);
616 if(CurIconObject
->IconInfo
.hbmMask
&&
617 (bmp
= BITMAPOBJ_LockBitmap(CurIconObject
->IconInfo
.hbmMask
)))
619 if (CurIconObject
->IconInfo
.hbmColor
== NULL
)
621 CurIconObject
->Size
.cx
= bmp
->SurfObj
.sizlBitmap
.cx
;
622 CurIconObject
->Size
.cy
= bmp
->SurfObj
.sizlBitmap
.cy
/ 2;
624 BITMAPOBJ_UnlockBitmap(bmp
);
625 GDIOBJ_SetOwnership(CurIconObject
->IconInfo
.hbmMask
, NULL
);
630 SetLastNtError(Status
);
631 /* FIXME - Don't exit here */
635 ObDereferenceObject(WinStaObject
);
639 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
640 ObDereferenceObject(WinStaObject
);
649 NtUserGetCursorIconInfo(
654 PCURICON_OBJECT CurIconObject
;
655 PWINSTATION_OBJECT WinStaObject
;
659 WinStaObject
= IntGetWinStaObj();
660 if(WinStaObject
== NULL
)
665 CurIconObject
= IntGetCurIconObject(WinStaObject
, Handle
);
670 RtlCopyMemory(&ii
, &CurIconObject
->IconInfo
, sizeof(ICONINFO
));
673 ii
.hbmMask
= BITMAPOBJ_CopyBitmap(ii
.hbmMask
);
674 ii
.hbmColor
= BITMAPOBJ_CopyBitmap(ii
.hbmColor
);
677 Status
= MmCopyToCaller(IconInfo
, &ii
, sizeof(ICONINFO
));
678 if(NT_SUCCESS(Status
))
681 SetLastNtError(Status
);
685 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
688 IntReleaseCurIconObject(CurIconObject
);
689 ObDereferenceObject(WinStaObject
);
693 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
694 ObDereferenceObject(WinStaObject
);
704 NtUserGetCursorIconSize(
709 PCURICON_OBJECT CurIconObject
;
711 PWINSTATION_OBJECT WinStaObject
;
716 WinStaObject
= IntGetWinStaObj();
717 if(WinStaObject
== NULL
)
722 CurIconObject
= IntGetCurIconObject(WinStaObject
, Handle
);
726 Status
= MmCopyToCaller(fIcon
, &CurIconObject
->IconInfo
.fIcon
, sizeof(BOOL
));
727 if(!NT_SUCCESS(Status
))
729 SetLastNtError(Status
);
733 bmp
= BITMAPOBJ_LockBitmap(CurIconObject
->IconInfo
.hbmColor
);
737 SafeSize
.cx
= bmp
->SurfObj
.sizlBitmap
.cx
;
738 SafeSize
.cy
= bmp
->SurfObj
.sizlBitmap
.cy
;
739 Status
= MmCopyToCaller(Size
, &SafeSize
, sizeof(SIZE
));
740 if(NT_SUCCESS(Status
))
743 SetLastNtError(Status
);
745 BITMAPOBJ_UnlockBitmap(bmp
);
748 IntReleaseCurIconObject(CurIconObject
);
749 ObDereferenceObject(WinStaObject
);
753 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
754 ObDereferenceObject(WinStaObject
);
764 NtUserGetCursorFrameInfo(
785 PSYSTEM_CURSORINFO CurInfo
;
786 PWINSTATION_OBJECT WinStaObject
;
788 PCURICON_OBJECT CursorObject
;
793 /* FIXME - get the screen dc from the window station or desktop */
794 if (!(hDC
= IntGetScreenDC()))
800 Status
= MmCopyFromCaller(&SafeCi
.cbSize
, pci
, sizeof(DWORD
));
801 if(!NT_SUCCESS(Status
))
803 SetLastNtError(Status
);
807 if(SafeCi
.cbSize
!= sizeof(CURSORINFO
))
809 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
813 WinStaObject
= IntGetWinStaObj();
814 if(WinStaObject
== NULL
)
819 CurInfo
= IntGetSysCursorInfo(WinStaObject
);
820 CursorObject
= (PCURICON_OBJECT
)CurInfo
->CurrentCursorObject
;
822 SafeCi
.flags
= ((CurInfo
->ShowingCursor
&& CursorObject
) ? CURSOR_SHOWING
: 0);
823 SafeCi
.hCursor
= (CursorObject
? (HCURSOR
)CursorObject
->Self
: (HCURSOR
)0);
825 IntGetCursorLocation(WinStaObject
, &SafeCi
.ptScreenPos
);
827 Status
= MmCopyToCaller(pci
, &SafeCi
, sizeof(CURSORINFO
));
828 if(!NT_SUCCESS(Status
))
830 ObDereferenceObject(WinStaObject
);
831 SetLastNtError(Status
);
835 ObDereferenceObject(WinStaObject
);
848 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
850 PWINSTATION_OBJECT WinStaObject
;
851 PSYSTEM_CURSORINFO CurInfo
;
853 PWINDOW_OBJECT DesktopWindow
= NULL
;
856 WinStaObject
= IntGetWinStaObj();
857 if (WinStaObject
== NULL
)
862 if (NULL
!= UnsafeRect
&& ! NT_SUCCESS(MmCopyFromCaller(&Rect
, UnsafeRect
, sizeof(RECT
))))
864 ObDereferenceObject(WinStaObject
);
865 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
869 CurInfo
= IntGetSysCursorInfo(WinStaObject
);
870 IntGetCursorLocation(WinStaObject
, &MousePos
);
872 if(WinStaObject
->ActiveDesktop
)
873 DesktopWindow
= IntGetWindowObject(WinStaObject
->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);
885 IntReleaseWindowObject(DesktopWindow
);
890 mi
.dwFlags
= MOUSEEVENTF_ABSOLUTE
| MOUSEEVENTF_MOVE
;
898 CurInfo
->CursorClipInfo
.IsClipped
= FALSE
;
899 ObDereferenceObject(WinStaObject
);
910 NtUserDestroyCursorIcon(
914 PWINSTATION_OBJECT WinStaObject
;
915 PCURICON_OBJECT Object
;
918 WinStaObject
= IntGetWinStaObj();
919 if(WinStaObject
== NULL
)
924 Status
= ObmReferenceObjectByHandle(WinStaObject
->HandleTable
, Handle
, otCursorIcon
, (PVOID
*)&Object
);
925 if(!NT_SUCCESS(Status
))
927 ObDereferenceObject(WinStaObject
);
928 SetLastNtError(Status
);
932 if(IntDestroyCurIconObject(WinStaObject
, Object
, FALSE
))
934 ObmDereferenceObject(Object
);
935 ObDereferenceObject(WinStaObject
);
939 ObmDereferenceObject(Object
);
940 ObDereferenceObject(WinStaObject
);
941 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
951 NtUserFindExistingCursorIcon(
957 PCURICON_OBJECT CurIconObject
;
958 PWINSTATION_OBJECT WinStaObject
;
959 HANDLE Ret
= (HANDLE
)0;
961 WinStaObject
= IntGetWinStaObj();
962 if(WinStaObject
== NULL
)
967 CurIconObject
= IntFindExistingCurIconObject(WinStaObject
, hModule
, hRsrc
, cx
, cy
);
970 Ret
= CurIconObject
->Self
;
972 IntReleaseCurIconObject(CurIconObject
);
973 ObDereferenceObject(WinStaObject
);
977 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
978 ObDereferenceObject(WinStaObject
);
991 /* FIXME - check if process has WINSTA_READATTRIBUTES */
992 PSYSTEM_CURSORINFO CurInfo
;
993 PWINSTATION_OBJECT WinStaObject
;
1000 WinStaObject
= IntGetWinStaObj();
1001 if (WinStaObject
== NULL
)
1006 CurInfo
= IntGetSysCursorInfo(WinStaObject
);
1007 if(CurInfo
->CursorClipInfo
.IsClipped
)
1009 Rect
.left
= CurInfo
->CursorClipInfo
.Left
;
1010 Rect
.top
= CurInfo
->CursorClipInfo
.Top
;
1011 Rect
.right
= CurInfo
->CursorClipInfo
.Right
;
1012 Rect
.bottom
= CurInfo
->CursorClipInfo
.Bottom
;
1018 Rect
.right
= NtUserGetSystemMetrics(SM_CXSCREEN
);
1019 Rect
.bottom
= NtUserGetSystemMetrics(SM_CYSCREEN
);
1022 Status
= MmCopyToCaller((PRECT
)lpRect
, &Rect
, sizeof(RECT
));
1023 if(!NT_SUCCESS(Status
))
1025 ObDereferenceObject(WinStaObject
);
1026 SetLastNtError(Status
);
1030 ObDereferenceObject(WinStaObject
);
1044 PCURICON_OBJECT CurIconObject
;
1045 HICON OldCursor
= (HCURSOR
)0;
1046 PWINSTATION_OBJECT WinStaObject
;
1048 WinStaObject
= IntGetWinStaObj();
1049 if(WinStaObject
== NULL
)
1054 CurIconObject
= IntGetCurIconObject(WinStaObject
, hCursor
);
1057 OldCursor
= IntSetCursor(WinStaObject
, CurIconObject
, FALSE
);
1058 IntReleaseCurIconObject(CurIconObject
);
1061 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
1063 ObDereferenceObject(WinStaObject
);
1073 NtUserSetCursorIconContents(
1077 PCURICON_OBJECT CurIconObject
;
1079 PWINSTATION_OBJECT WinStaObject
;
1083 WinStaObject
= IntGetWinStaObj();
1084 if(WinStaObject
== NULL
)
1089 CurIconObject
= IntGetCurIconObject(WinStaObject
, Handle
);
1093 Status
= MmCopyFromCaller(&CurIconObject
->IconInfo
, IconInfo
, sizeof(ICONINFO
));
1094 if(!NT_SUCCESS(Status
))
1096 SetLastNtError(Status
);
1100 bmp
= BITMAPOBJ_LockBitmap(CurIconObject
->IconInfo
.hbmColor
);
1103 CurIconObject
->Size
.cx
= bmp
->SurfObj
.sizlBitmap
.cx
;
1104 CurIconObject
->Size
.cy
= bmp
->SurfObj
.sizlBitmap
.cy
;
1105 BITMAPOBJ_UnlockBitmap(bmp
);
1106 GDIOBJ_SetOwnership(CurIconObject
->IconInfo
.hbmColor
, NULL
);
1110 bmp
= BITMAPOBJ_LockBitmap(CurIconObject
->IconInfo
.hbmMask
);
1114 CurIconObject
->Size
.cx
= bmp
->SurfObj
.sizlBitmap
.cx
;
1115 CurIconObject
->Size
.cy
= bmp
->SurfObj
.sizlBitmap
.cy
/ 2;
1117 BITMAPOBJ_UnlockBitmap(bmp
);
1118 GDIOBJ_SetOwnership(CurIconObject
->IconInfo
.hbmMask
, NULL
);
1124 IntReleaseCurIconObject(CurIconObject
);
1125 ObDereferenceObject(WinStaObject
);
1129 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
1130 ObDereferenceObject(WinStaObject
);
1140 NtUserSetCursorIconData(
1148 PCURICON_OBJECT CurIconObject
;
1149 PWINSTATION_OBJECT WinStaObject
;
1154 WinStaObject
= IntGetWinStaObj();
1155 if(WinStaObject
== NULL
)
1160 CurIconObject
= IntGetCurIconObject(WinStaObject
, Handle
);
1163 CurIconObject
->hModule
= hModule
;
1164 CurIconObject
->hRsrc
= hRsrc
;
1165 CurIconObject
->hGroupRsrc
= hGroupRsrc
;
1170 Status
= MmCopyFromCaller(&CurIconObject
->IconInfo
.fIcon
, fIcon
, sizeof(BOOL
));
1171 if(!NT_SUCCESS(Status
))
1173 SetLastNtError(Status
);
1185 Status
= MmCopyFromCaller(&SafeHotspot
, Hotspot
, sizeof(POINT
));
1186 if(NT_SUCCESS(Status
))
1188 CurIconObject
->IconInfo
.xHotspot
= SafeHotspot
.x
;
1189 CurIconObject
->IconInfo
.yHotspot
= SafeHotspot
.y
;
1194 SetLastNtError(Status
);
1197 if(!fIcon
&& !Hotspot
)
1203 IntReleaseCurIconObject(CurIconObject
);
1204 ObDereferenceObject(WinStaObject
);
1208 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
1209 ObDereferenceObject(WinStaObject
);
1219 NtUserSetSystemCursor(
1227 #define CANSTRETCHBLT 0
1241 HBRUSH hbrFlickerFreeDraw
,
1246 PCURICON_OBJECT CurIconObject
;
1247 PWINSTATION_OBJECT WinStaObject
;
1248 HBITMAP hbmMask
, hbmColor
;
1249 BITMAP bmpMask
, bmpColor
;
1252 COLORREF oldFg
, oldBg
;
1253 HDC hdcMem
, hdcOff
= (HDC
)0;
1254 HBITMAP hbmOff
= (HBITMAP
)0;
1255 HGDIOBJ hOldOffBrush
= 0, hOldOffBmp
= 0, hOldMem
;
1261 WinStaObject
= IntGetWinStaObj();
1262 if(WinStaObject
== NULL
)
1267 CurIconObject
= IntGetCurIconObject(WinStaObject
, hIcon
);
1270 hbmMask
= CurIconObject
->IconInfo
.hbmMask
;
1271 hbmColor
= CurIconObject
->IconInfo
.hbmColor
;
1272 IntReleaseCurIconObject(CurIconObject
);
1275 DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
1277 if(!hbmMask
|| !IntGdiGetObject(hbmMask
, sizeof(BITMAP
), &bmpMask
))
1280 if(hbmColor
&& !IntGdiGetObject(hbmColor
, sizeof(BITMAP
), &bmpColor
))
1285 IconSize
.cx
= bmpColor
.bmWidth
;
1286 IconSize
.cy
= bmpColor
.bmHeight
;
1290 IconSize
.cx
= bmpMask
.bmWidth
;
1291 IconSize
.cy
= bmpMask
.bmHeight
/ 2;
1295 diFlags
= DI_NORMAL
;
1298 cxWidth
= ((diFlags
& DI_DEFAULTSIZE
) ? NtUserGetSystemMetrics(SM_CXICON
) : IconSize
.cx
);
1300 cyWidth
= ((diFlags
& DI_DEFAULTSIZE
) ? NtUserGetSystemMetrics(SM_CYICON
) : IconSize
.cy
);
1302 DoFlickerFree
= (hbrFlickerFreeDraw
&& (NtGdiGetObjectType(hbrFlickerFreeDraw
) == OBJ_BRUSH
));
1310 hdcOff
= NtGdiCreateCompatableDC(hdc
);
1314 hbmOff
= NtGdiCreateCompatibleBitmap(hdc
, cxWidth
, cyWidth
);
1317 NtGdiDeleteDC(hdcOff
);
1320 hOldOffBrush
= NtGdiSelectObject(hdcOff
, hbrFlickerFreeDraw
);
1321 hOldOffBmp
= NtGdiSelectObject(hdcOff
, hbmOff
);
1322 NtGdiPatBlt(hdcOff
, 0, 0, r
.right
, r
.bottom
, PATCOPY
);
1323 NtGdiSelectObject(hdcOff
, hbmOff
);
1326 hdcMem
= NtGdiCreateCompatableDC(hdc
);
1334 nStretchMode
= NtGdiSetStretchBltMode(hdcOff
, STRETCH_DELETESCANS
);
1336 oldFg
= NtGdiSetTextColor(hdcOff
, RGB(0, 0, 0));
1337 oldBg
= NtGdiSetBkColor(hdcOff
, RGB(255, 255, 255));
1339 if(diFlags
& DI_MASK
)
1341 hOldMem
= NtGdiSelectObject(hdcMem
, hbmMask
);
1343 NtGdiStretchBlt(hdcOff
, (DoFlickerFree
? 0 : xLeft
), (DoFlickerFree
? 0 : yTop
),
1344 cxWidth
, cyWidth
, hdcMem
, 0, 0, IconSize
.cx
, IconSize
.cy
,
1345 ((diFlags
& DI_IMAGE
) ? SRCAND
: SRCCOPY
));
1347 NtGdiBitBlt(hdcOff
, (DoFlickerFree
? 0 : xLeft
), (DoFlickerFree
? 0 : yTop
),
1348 cxWidth
, cyWidth
, hdcMem
, 0, 0, ((diFlags
& DI_IMAGE
) ? SRCAND
: SRCCOPY
));
1350 if(!hbmColor
&& (bmpMask
.bmHeight
== 2 * bmpMask
.bmWidth
) && (diFlags
& DI_IMAGE
))
1353 NtGdiStretchBlt(hdcOff
, (DoFlickerFree
? 0 : xLeft
), (DoFlickerFree
? 0 : yTop
),
1354 cxWidth
, cyWidth
, hdcMem
, 0, IconSize
.cy
, IconSize
.cx
, IconSize
.cy
, SRCINVERT
);
1356 NtGdiBitBlt(hdcOff
, (DoFlickerFree
? 0 : xLeft
), (DoFlickerFree
? 0 : yTop
),
1357 cxWidth
, cyWidth
, hdcMem
, 0, IconSize
.cy
, SRCINVERT
);
1359 diFlags
&= ~DI_IMAGE
;
1361 NtGdiSelectObject(hdcMem
, hOldMem
);
1364 if(diFlags
& DI_IMAGE
)
1366 hOldMem
= NtGdiSelectObject(hdcMem
, (hbmColor
? hbmColor
: hbmMask
));
1368 NtGdiStretchBlt(hdcOff
, (DoFlickerFree
? 0 : xLeft
), (DoFlickerFree
? 0 : yTop
),
1369 cxWidth
, cyWidth
, hdcMem
, 0, (hbmColor
? 0 : IconSize
.cy
),
1370 IconSize
.cx
, IconSize
.cy
, ((diFlags
& DI_MASK
) ? SRCINVERT
: SRCCOPY
));
1372 NtGdiBitBlt(hdcOff
, (DoFlickerFree
? 0 : xLeft
), (DoFlickerFree
? 0 : yTop
),
1373 cxWidth
, cyWidth
, hdcMem
, 0, (hbmColor
? 0 : IconSize
.cy
),
1374 ((diFlags
& DI_MASK
) ? SRCINVERT
: SRCCOPY
));
1376 NtGdiSelectObject(hdcMem
, hOldMem
);
1380 NtGdiBitBlt(hdc
, xLeft
, yTop
, cxWidth
, cyWidth
, hdcOff
, 0, 0, SRCCOPY
);
1382 NtGdiSetTextColor(hdcOff
, oldFg
);
1383 NtGdiSetBkColor(hdcOff
, oldBg
);
1385 SetStretchBltMode(hdcOff
, nStretchMode
);
1394 NtGdiSelectObject(hdcOff
, hOldOffBmp
);
1395 NtGdiSelectObject(hdcOff
, hOldOffBrush
);
1396 NtGdiDeleteObject(hbmOff
);
1397 NtGdiDeleteDC(hdcOff
);
1400 NtGdiDeleteDC(hdcMem
);
1403 ObDereferenceObject(WinStaObject
);
1408 SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE
);
1409 ObDereferenceObject(WinStaObject
);