reactos/reactos/subsystems/win32/win32k/ntuser/cursoricon.c

1694 lines
41 KiB
C
Raw Normal View History

/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* We handle two types of cursors/icons:
* - Private
* Loaded without LR_SHARED flag
* Private to a process
* Can be deleted by calling NtDestroyCursorIcon()
* CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc set to NULL
* - Shared
* Loaded with LR_SHARED flag
* Possibly shared by multiple processes
* Immune to NtDestroyCursorIcon()
* CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc are valid
* There's a M:N relationship between processes and (shared) cursor/icons.
* A process can have multiple cursor/icons and a cursor/icon can be used
* by multiple processes. To keep track of this we keep a list of all
* cursor/icons (CurIconList) and per cursor/icon we keep a list of
* CURICON_PROCESS structs starting at CurIcon->ProcessList.
*/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
static PAGED_LOOKASIDE_LIST gProcessLookasideList;
static LIST_ENTRY gCurIconList;
BOOL FASTCALL
IntGetCursorLocation(PWINSTATION_OBJECT WinSta, POINT *loc)
{
loc->x = gpsi->ptCursor.x;
loc->y = gpsi->ptCursor.y;
return TRUE;
}
/* This function creates a reference for the object! */
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
{
PCURICON_OBJECT CurIcon;
if (!hCurIcon)
{
SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
return NULL;
}
CurIcon = (PCURICON_OBJECT)UserReferenceObjectByHandle(hCurIcon, otCursorIcon);
if (!CurIcon)
{
/* we never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */
SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
return NULL;
}
ASSERT(USER_BODY_TO_HEADER(CurIcon)->RefCount >= 1);
return CurIcon;
}
HCURSOR
FASTCALL
IntSetCursor(
PWINSTATION_OBJECT WinSta,
PCURICON_OBJECT NewCursor,
BOOL ForceChange)
{
PSYSTEM_CURSORINFO CurInfo;
PCURICON_OBJECT OldCursor;
HCURSOR hOldCursor = (HCURSOR)0;
HDC hdcScreen;
BOOL bResult;
CurInfo = IntGetSysCursorInfo(WinSta);
OldCursor = CurInfo->CurrentCursorObject;
if (OldCursor)
{
hOldCursor = (HCURSOR)OldCursor->Self;
}
/* Is the new cursor the same as the old cursor? */
if (OldCursor == NewCursor)
{
/* Nothing to to do in this case */
return hOldCursor;
}
/* Get the screen DC */
if(!(hdcScreen = IntGetScreenDC()))
{
return (HCURSOR)0;
}
/* Do we have a new cursor? */
if (NewCursor)
{
UserReferenceObject(NewCursor);
CurInfo->ShowingCursor = CURSOR_SHOWING;
CurInfo->CurrentCursorObject = NewCursor;
/* Call GDI to set the new screen cursor */
bResult = GreSetPointerShape(hdcScreen,
NewCursor->IconInfo.hbmMask,
NewCursor->IconInfo.hbmColor,
NewCursor->IconInfo.xHotspot,
NewCursor->IconInfo.yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
}
else
{
/* Check if were diplaying a cursor */
if (OldCursor && CurInfo->ShowingCursor)
{
/* Remove the cursor */
GreMovePointer(hdcScreen, -1, -1);
DPRINT("Removing pointer!\n");
}
CurInfo->CurrentCursorObject = NULL;
CurInfo->ShowingCursor = 0;
}
/* OldCursor is not in use anymore */
if (OldCursor)
{
UserDereferenceObject(OldCursor);
}
/* Return handle of the old cursor */
return hOldCursor;
}
BOOL FASTCALL
IntSetupCurIconHandles(PWINSTATION_OBJECT WinSta)
{
ExInitializePagedLookasideList(&gProcessLookasideList,
NULL,
NULL,
0,
sizeof(CURICON_PROCESS),
TAG_DIB,
128);
InitializeListHead(&gCurIconList);
return TRUE;
}
/*
* We have to register that this object is in use by the current
* process. The only way to do that seems to be to walk the list
* of cursor/icon objects starting at W32Process->CursorIconListHead.
* If the object is already present in the list, we don't have to do
* anything, if it's not present we add it and inc the ProcessCount
* in the object. Having to walk the list kind of sucks, but that's
* life...
*/
static BOOLEAN FASTCALL
ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon)
{
PPROCESSINFO Win32Process;
PCURICON_PROCESS Current;
Win32Process = PsGetCurrentProcessWin32Process();
LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
{
if (Current->Process == Win32Process)
{
/* Already registered for this process */
return TRUE;
}
}
/* Not registered yet */
Current = ExAllocateFromPagedLookasideList(&gProcessLookasideList);
if (NULL == Current)
{
return FALSE;
}
InsertHeadList(&CurIcon->ProcessList, &Current->ListEntry);
Current->Process = Win32Process;
return TRUE;
}
PCURICON_OBJECT FASTCALL
IntFindExistingCurIconObject(PWINSTATION_OBJECT WinSta, HMODULE hModule,
HRSRC hRsrc, LONG cx, LONG cy)
{
PCURICON_OBJECT CurIcon;
LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry)
{
// if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
// UserReferenceObject( CurIcon);
// {
if ((CurIcon->hModule == hModule) && (CurIcon->hRsrc == hRsrc))
{
if (cx && ((cx != CurIcon->Size.cx) || (cy != CurIcon->Size.cy)))
{
// UserDereferenceObject(CurIcon);
continue;
}
if (! ReferenceCurIconByProcess(CurIcon))
{
return NULL;
}
return CurIcon;
}
// }
// UserDereferenceObject(CurIcon);
}
return NULL;
}
PCURICON_OBJECT FASTCALL
IntCreateCurIconHandle(PWINSTATION_OBJECT WinSta)
{
PCURICON_OBJECT CurIcon;
HANDLE hCurIcon;
CurIcon = UserCreateObject(gHandleTable, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT));
if (!CurIcon)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
CurIcon->Self = hCurIcon;
InitializeListHead(&CurIcon->ProcessList);
if (! ReferenceCurIconByProcess(CurIcon))
{
DPRINT1("Failed to add process\n");
UserDeleteObject(hCurIcon, otCursorIcon);
UserDereferenceObject(CurIcon);
return NULL;
}
InsertHeadList(&gCurIconList, &CurIcon->ListEntry);
return CurIcon;
}
BOOLEAN FASTCALL
IntDestroyCurIconObject(PWINSTATION_OBJECT WinSta, PCURICON_OBJECT CurIcon, BOOL ProcessCleanup)
{
PSYSTEM_CURSORINFO CurInfo;
HBITMAP bmpMask, bmpColor;
BOOLEAN Ret;
PCURICON_PROCESS Current = NULL;
PPROCESSINFO W32Process = PsGetCurrentProcessWin32Process();
/* Private objects can only be destroyed by their own process */
if (NULL == CurIcon->hModule)
{
ASSERT(CurIcon->ProcessList.Flink->Flink == &CurIcon->ProcessList);
Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry);
if (Current->Process != W32Process)
{
DPRINT1("Trying to destroy private icon/cursor of another process\n");
return FALSE;
}
}
else if (! ProcessCleanup)
{
DPRINT("Trying to destroy shared icon/cursor\n");
return FALSE;
}
/* Now find this process in the list of processes referencing this object and
remove it from that list */
LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
{
if (Current->Process == W32Process)
{
RemoveEntryList(&Current->ListEntry);
break;
}
}
ExFreeToPagedLookasideList(&gProcessLookasideList, Current);
/* If there are still processes referencing this object we can't destroy it yet */
if (! IsListEmpty(&CurIcon->ProcessList))
{
return TRUE;
}
if (! ProcessCleanup)
{
RemoveEntryList(&CurIcon->ListEntry);
}
CurInfo = IntGetSysCursorInfo(WinSta);
if (CurInfo->CurrentCursorObject == CurIcon)
{
/* Hide the cursor if we're destroying the current cursor */
IntSetCursor(WinSta, NULL, TRUE);
}
bmpMask = CurIcon->IconInfo.hbmMask;
bmpColor = CurIcon->IconInfo.hbmColor;
/* delete bitmaps */
if (bmpMask)
{
GDIOBJ_SetOwnership(bmpMask, PsGetCurrentProcess());
GreDeleteObject(bmpMask);
CurIcon->IconInfo.hbmMask = NULL;
}
if (bmpColor)
{
GDIOBJ_SetOwnership(bmpColor, PsGetCurrentProcess());
GreDeleteObject(bmpColor);
CurIcon->IconInfo.hbmColor = NULL;
}
/* We were given a pointer, no need to keep the reference anylonger! */
UserDereferenceObject(CurIcon);
Ret = UserDeleteObject(CurIcon->Self, otCursorIcon);
return Ret;
}
VOID FASTCALL
IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
{
PWINSTATION_OBJECT WinSta;
PCURICON_OBJECT CurIcon, tmp;
PCURICON_PROCESS ProcessData;
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
return;
}
LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
{
UserReferenceObject(CurIcon);
// if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon)))
{
LIST_FOR_EACH(ProcessData, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
{
if (Win32Process == ProcessData->Process)
{
RemoveEntryList(&CurIcon->ListEntry);
IntDestroyCurIconObject(WinSta, CurIcon, TRUE);
CurIcon = NULL;
break;
}
}
// UserDereferenceObject(Object);
}
if (CurIcon)
{
UserDereferenceObject(CurIcon);
}
}
ObDereferenceObject(WinSta);
}
/*
* @implemented
*/
HANDLE
APIENTRY
NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL, BOOL Indirect)
{
PCURICON_OBJECT CurIcon;
PWINSTATION_OBJECT WinSta;
PSURFACE psurfBmp;
NTSTATUS Status;
HANDLE Ret;
DECLARE_RETURN(HANDLE);
DPRINT("Enter NtUserCreateCursorIconHandle\n");
UserEnterExclusive();
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
RETURN((HANDLE)0);
}
if (!(CurIcon = IntCreateCurIconHandle(WinSta)))
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
ObDereferenceObject(WinSta);
RETURN((HANDLE)0);
}
Ret = CurIcon->Self;
if (IconInfo)
{
Status = MmCopyFromCaller(&CurIcon->IconInfo, IconInfo, sizeof(ICONINFO));
if (NT_SUCCESS(Status))
{
/* Copy bitmaps and size info */
if (Indirect)
{
// FIXME: WTF?
CurIcon->IconInfo.hbmMask = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmMask);
CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor);
}
if (CurIcon->IconInfo.hbmColor &&
(psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor)))
{
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
SURFACE_UnlockSurface(psurfBmp);
GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
}
if (CurIcon->IconInfo.hbmMask &&
(psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask)))
{
if (CurIcon->IconInfo.hbmColor == NULL)
{
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy >> 1;
}
SURFACE_UnlockSurface(psurfBmp);
GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
}
/* Calculate icon hotspot */
if (CurIcon->IconInfo.fIcon == TRUE)
{
CurIcon->IconInfo.xHotspot = CurIcon->Size.cx >> 1;
CurIcon->IconInfo.yHotspot = CurIcon->Size.cy >> 1;
}
}
else
{
SetLastNtError(Status);
/* FIXME - Don't exit here */
}
}
UserDereferenceObject(CurIcon);
ObDereferenceObject(WinSta);
RETURN(Ret);
CLEANUP:
DPRINT("Leave NtUserCreateCursorIconHandle, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/
BOOL
APIENTRY
NtUserGetIconInfo(
HANDLE hCurIcon,
PICONINFO IconInfo,
PUNICODE_STRING lpInstName, // optional
PUNICODE_STRING lpResName, // optional
LPDWORD pbpp, // optional
BOOL bInternal)
{
ICONINFO ii;
PCURICON_OBJECT CurIcon;
NTSTATUS Status = STATUS_SUCCESS;
BOOL Ret = FALSE;
DWORD colorBpp = 0;
DPRINT("Enter NtUserGetIconInfo\n");
UserEnterExclusive();
if (!IconInfo)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
goto leave;
}
if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
{
goto leave;
}
RtlCopyMemory(&ii, &CurIcon->IconInfo, sizeof(ICONINFO));
/* Copy bitmaps */
ii.hbmMask = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmMask);
ii.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor);
if (pbpp)
{
PSURFACE psurfBmp;
psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor);
if (psurfBmp)
{
colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
SURFACE_UnlockSurface(psurfBmp);
}
}
/* Copy fields */
_SEH2_TRY
{
ProbeForWrite(IconInfo, sizeof(ICONINFO), 1);
RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO));
if (pbpp)
{
ProbeForWrite(pbpp, sizeof(DWORD), 1);
*pbpp = colorBpp;
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (NT_SUCCESS(Status))
Ret = TRUE;
else
SetLastNtError(Status);
UserDereferenceObject(CurIcon);
leave:
DPRINT("Leave NtUserGetIconInfo, ret=%i\n", Ret);
UserLeave();
return Ret;
}
/*
* @implemented
*/
BOOL
APIENTRY
NtUserGetIconSize(
HANDLE hCurIcon,
UINT istepIfAniCur,
PLONG plcx, // &size.cx
PLONG plcy) // &size.cy
{
PCURICON_OBJECT CurIcon;
NTSTATUS Status = STATUS_SUCCESS;
BOOL bRet = FALSE;
DPRINT("Enter NtUserGetIconSize\n");
UserEnterExclusive();
if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
{
goto cleanup;
}
_SEH2_TRY
{
ProbeForWrite(plcx, sizeof(LONG), 1);
RtlCopyMemory(plcx, &CurIcon->Size.cx, sizeof(LONG));
ProbeForWrite(plcy, sizeof(LONG), 1);
RtlCopyMemory(plcy, &CurIcon->Size.cy, sizeof(LONG));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (NT_SUCCESS(Status))
bRet = TRUE;
else
SetLastNtError(Status); // maybe not, test this
UserDereferenceObject(CurIcon);
cleanup:
DPRINT("Leave NtUserGetIconSize, ret=%i\n", bRet);
UserLeave();
return bRet;
}
/*
* @unimplemented
*/
DWORD
APIENTRY
NtUserGetCursorFrameInfo(
DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3)
{
UNIMPLEMENTED
return 0;
}
/*
* @implemented
*/
BOOL
APIENTRY
NtUserGetCursorInfo(
PCURSORINFO pci)
{
CURSORINFO SafeCi;
PSYSTEM_CURSORINFO CurInfo;
PWINSTATION_OBJECT WinSta;
NTSTATUS Status = STATUS_SUCCESS;
PCURICON_OBJECT CurIcon;
BOOL Ret = FALSE;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserGetCursorInfo\n");
UserEnterExclusive();
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
RETURN(FALSE);
}
CurInfo = IntGetSysCursorInfo(WinSta);
CurIcon = (PCURICON_OBJECT)CurInfo->CurrentCursorObject;
SafeCi.cbSize = sizeof(CURSORINFO);
SafeCi.flags = ((CurInfo->ShowingCursor && CurIcon) ? CURSOR_SHOWING : 0);
SafeCi.hCursor = (CurIcon ? (HCURSOR)CurIcon->Self : (HCURSOR)0);
IntGetCursorLocation(WinSta, &SafeCi.ptScreenPos);
_SEH2_TRY
{
if (pci->cbSize == sizeof(CURSORINFO))
{
ProbeForWrite(pci, sizeof(CURSORINFO), 1);
RtlCopyMemory(pci, &SafeCi, sizeof(CURSORINFO));
Ret = TRUE;
}
else
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
}
ObDereferenceObject(WinSta);
RETURN(Ret);
CLEANUP:
DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/
BOOL
APIENTRY
NtUserClipCursor(
RECTL *UnsafeRect)
{
/* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
PWINSTATION_OBJECT WinSta;
PSYSTEM_CURSORINFO CurInfo;
RECTL Rect;
PWINDOW_OBJECT DesktopWindow = NULL;
POINT MousePos = {0};
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserClipCursor\n");
UserEnterExclusive();
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
RETURN(FALSE);
}
if (NULL != UnsafeRect && ! NT_SUCCESS(MmCopyFromCaller(&Rect, UnsafeRect, sizeof(RECT))))
{
ObDereferenceObject(WinSta);
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN(FALSE);
}
CurInfo = IntGetSysCursorInfo(WinSta);
IntGetCursorLocation(WinSta, &MousePos);
if (WinSta->ActiveDesktop)
DesktopWindow = UserGetWindowObject(WinSta->ActiveDesktop->DesktopWindow);
if ((Rect.right > Rect.left) && (Rect.bottom > Rect.top)
&& DesktopWindow && UnsafeRect != NULL)
{
MOUSEINPUT mi;
CurInfo->CursorClipInfo.IsClipped = TRUE;
CurInfo->CursorClipInfo.Left = max(Rect.left, DesktopWindow->Wnd->rcWindow.left);
CurInfo->CursorClipInfo.Top = max(Rect.top, DesktopWindow->Wnd->rcWindow.top);
CurInfo->CursorClipInfo.Right = min(Rect.right - 1, DesktopWindow->Wnd->rcWindow.right - 1);
CurInfo->CursorClipInfo.Bottom = min(Rect.bottom - 1, DesktopWindow->Wnd->rcWindow.bottom - 1);
mi.dx = MousePos.x;
mi.dy = MousePos.y;
mi.mouseData = 0;
mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
mi.time = 0;
mi.dwExtraInfo = 0;
IntMouseInput(&mi);
RETURN(TRUE);
}
CurInfo->CursorClipInfo.IsClipped = FALSE;
ObDereferenceObject(WinSta);
RETURN(TRUE);
CLEANUP:
DPRINT("Leave NtUserClipCursor, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/
BOOL
APIENTRY
NtUserDestroyCursor(
HANDLE hCurIcon,
DWORD Unknown)
{
PWINSTATION_OBJECT WinSta;
PCURICON_OBJECT CurIcon;
BOOL ret;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserDestroyCursorIcon\n");
UserEnterExclusive();
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
RETURN(FALSE);
}
if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
{
ObDereferenceObject(WinSta);
RETURN(FALSE);
}
ret = IntDestroyCurIconObject(WinSta, CurIcon, FALSE);
/* Note: IntDestroyCurIconObject will remove our reference for us! */
ObDereferenceObject(WinSta);
RETURN(ret);
CLEANUP:
DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/
HICON
APIENTRY
NtUserFindExistingCursorIcon(
HMODULE hModule,
HRSRC hRsrc,
LONG cx,
LONG cy)
{
PCURICON_OBJECT CurIcon;
PWINSTATION_OBJECT WinSta;
HANDLE Ret = (HANDLE)0;
DECLARE_RETURN(HICON);
DPRINT("Enter NtUserFindExistingCursorIcon\n");
UserEnterExclusive();
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
RETURN(Ret);
}
CurIcon = IntFindExistingCurIconObject(WinSta, hModule, hRsrc, cx, cy);
if (CurIcon)
{
Ret = CurIcon->Self;
// IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
ObDereferenceObject(WinSta);
RETURN(Ret);
}
SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
ObDereferenceObject(WinSta);
RETURN((HANDLE)0);
CLEANUP:
DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/
BOOL
APIENTRY
NtUserGetClipCursor(
RECTL *lpRect)
{
/* FIXME - check if process has WINSTA_READATTRIBUTES */
PSYSTEM_CURSORINFO CurInfo;
PWINSTATION_OBJECT WinSta;
RECTL Rect;
NTSTATUS Status;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserGetClipCursor\n");
UserEnterExclusive();
if (!lpRect)
RETURN(FALSE);
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
RETURN(FALSE);
}
CurInfo = IntGetSysCursorInfo(WinSta);
if (CurInfo->CursorClipInfo.IsClipped)
{
Rect.left = CurInfo->CursorClipInfo.Left;
Rect.top = CurInfo->CursorClipInfo.Top;
Rect.right = CurInfo->CursorClipInfo.Right;
Rect.bottom = CurInfo->CursorClipInfo.Bottom;
}
else
{
Rect.left = 0;
Rect.top = 0;
Rect.right = UserGetSystemMetrics(SM_CXSCREEN);
Rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
}
Status = MmCopyToCaller(lpRect, &Rect, sizeof(RECT));
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(WinSta);
SetLastNtError(Status);
RETURN(FALSE);
}
ObDereferenceObject(WinSta);
RETURN(TRUE);
CLEANUP:
DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/
HCURSOR
APIENTRY
NtUserSetCursor(
HCURSOR hCursor)
{
PCURICON_OBJECT CurIcon;
HICON OldCursor;
PWINSTATION_OBJECT WinSta;
DECLARE_RETURN(HCURSOR);
DPRINT("Enter NtUserSetCursor\n");
UserEnterExclusive();
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
RETURN(NULL);
}
if (hCursor)
{
if (!(CurIcon = UserGetCurIconObject(hCursor)))
{
ObDereferenceObject(WinSta);
RETURN(NULL);
}
}
else
{
CurIcon = NULL;
}
OldCursor = IntSetCursor(WinSta, CurIcon, FALSE);
if (CurIcon)
{
UserDereferenceObject(CurIcon);
}
ObDereferenceObject(WinSta);
RETURN(OldCursor);
CLEANUP:
DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/
BOOL
APIENTRY
NtUserSetCursorContents(
HANDLE hCurIcon,
PICONINFO UnsafeIconInfo)
{
PCURICON_OBJECT CurIcon;
ICONINFO IconInfo;
PSURFACE psurfBmp;
PWINSTATION_OBJECT WinSta;
NTSTATUS Status;
BOOL Ret = FALSE;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserSetCursorContents\n");
UserEnterExclusive();
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
RETURN(FALSE);
}
if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
{
ObDereferenceObject(WinSta);
RETURN(FALSE);
}
/* Copy fields */
Status = MmCopyFromCaller(&IconInfo, UnsafeIconInfo, sizeof(ICONINFO));
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
goto done;
}
/* Delete old bitmaps */
if (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor)
{
GreDeleteObject(CurIcon->IconInfo.hbmColor);
}
if (CurIcon->IconInfo.hbmMask != IconInfo.hbmMask)
{
GreDeleteObject(CurIcon->IconInfo.hbmMask);
}
/* Copy new IconInfo field */
CurIcon->IconInfo = IconInfo;
psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor);
if (psurfBmp)
{
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
SURFACE_UnlockSurface(psurfBmp);
GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
}
else
{
psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask);
if (!psurfBmp)
goto done;
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy / 2;
SURFACE_UnlockSurface(psurfBmp);
GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
}
Ret = TRUE;
done:
if (CurIcon)
{
UserDereferenceObject(CurIcon);
}
ObDereferenceObject(WinSta);
RETURN(Ret);
CLEANUP:
DPRINT("Leave NtUserSetCursorContents, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* @implemented
*/
#if 0
BOOL
APIENTRY
NtUserSetCursorIconData(
HANDLE Handle,
HMODULE hModule,
PUNICODE_STRING pstrResName,
PICONINFO pIconInfo)
{
PCURICON_OBJECT CurIcon;
PWINSTATION_OBJECT WinSta;
PSURFACE psurfBmp;
NTSTATUS Status = STATUS_SUCCESS;
BOOL Ret = FALSE;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserSetCursorIconData\n");
UserEnterExclusive();
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
RETURN(FALSE);
}
if (!(CurIcon = UserGetCurIconObject(Handle)))
{
ObDereferenceObject(WinSta);
RETURN(FALSE);
}
CurIcon->hModule = hModule;
CurIcon->hRsrc = NULL; //hRsrc;
CurIcon->hGroupRsrc = NULL; //hGroupRsrc;
_SEH2_TRY
{
ProbeForRead(pIconInfo, sizeof(ICONINFO), 1);
RtlCopyMemory(&CurIcon->IconInfo, pIconInfo, sizeof(ICONINFO));
CurIcon->IconInfo.hbmMask = BITMAP_CopyBitmap(pIconInfo->hbmMask);
CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(pIconInfo->hbmColor);
if (CurIcon->IconInfo.hbmColor)
{
if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor)))
{
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
SURFACE_UnlockSurface(psurfBmp);
GDIOBJ_SetOwnership(GdiHandleTable, CurIcon->IconInfo.hbmMask, NULL);
}
}
if (CurIcon->IconInfo.hbmMask)
{
if (CurIcon->IconInfo.hbmColor == NULL)
{
if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask)))
{
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
SURFACE_UnlockSurface(psurfBmp);
}
}
GDIOBJ_SetOwnership(GdiHandleTable, CurIcon->IconInfo.hbmMask, NULL);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
modified include/reactos/probe.h Workaround for gcc 4.1.3. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38054#c7 modified ntoskrnl/include/internal/mm.h gcc 4.3.2 doesn't like to be told to inline MmAcquirePageListLock modified ntoskrnl/include/internal/probe.h Cleaning up after TSVN's buggy "apply patch" modified subsystems/win32/win32k/ntuser/message.c Silence a gcc 4.3.2 warning (possibly incorrectly) modified dll/directx/ddraw/ddraw.rbuild modified dll/win32/gdi32/gdi32.rbuild modified dll/win32/kernel32/kernel32.rbuild modified dll/win32/psapi/psapi.rbuild modified dll/win32/setupapi/setupapi.rbuild modified dll/win32/syssetup/syssetup.rbuild modified dll/win32/user32/user32.rbuild modified drivers/input/kbdclass/kbdclass.rbuild modified drivers/input/mouclass/mouclass.rbuild modified drivers/network/afd/afd.rbuild modified drivers/network/tcpip/tcpip.rbuild modified lib/rtl/rtl.rbuild modified subsystems/win32/win32k/win32k.rbuild modified subsystems/win32/win32k/objects/gdiobj.c gcc 4.1.3 workarounds. See embedded comments modified base/services/eventlog/eventlog.h modified dll/win32/advapi32/advapi32.h Removed superfluous includes of pseh/pseh.h modified dll/directx/ddraw/Ddraw/ddraw_displaymode.c modified dll/directx/ddraw/Ddraw/ddraw_main.c modified dll/directx/ddraw/Ddraw/ddraw_setcooperativelevel.c modified dll/directx/ddraw/Ddraw/GetCaps.c modified dll/directx/ddraw/Ddraw/GetDeviceIdentifier.c modified dll/directx/ddraw/main.c modified dll/directx/ddraw/rosdraw.h modified dll/directx/ddraw/Surface/surface_main.c ddraw migrated to PSEH 2.0 modified dll/win32/gdi32/include/precomp.h modified dll/win32/gdi32/misc/misc.c modified dll/win32/gdi32/objects/bitmap.c gdi32 migrated to PSEH 2.0 modified dll/win32/kernel32/except/except.c modified dll/win32/kernel32/file/find.c modified dll/win32/kernel32/k32.h modified dll/win32/kernel32/mem/isbad.c modified dll/win32/kernel32/misc/console.c modified dll/win32/kernel32/process/procsup.c modified dll/win32/kernel32/string/lstring.c modified dll/win32/kernel32/thread/thread.c kernel32 migrated to PSEH 2.0 modified dll/win32/psapi/precomp.h modified dll/win32/psapi/psapi.c psapi migrated to PSEH 2.0 modified dll/win32/setupapi/cfgmgr.c modified dll/win32/setupapi/setupapi_private.h setupapi migrated to PSEH 2.0 modified dll/win32/syssetup/wizard.c syssetup migrated to PSEH 2.0 modified dll/win32/user32/include/user32.h modified dll/win32/user32/windows/class.c modified dll/win32/user32/windows/text.c modified dll/win32/user32/windows/window.c user32 migrated to PSEH 2.0 modified drivers/input/kbdclass/kbdclass.c modified drivers/input/kbdclass/kbdclass.h kbdclass migrated to PSEH 2.0 modified drivers/input/mouclass/mouclass.c modified drivers/input/mouclass/mouclass.h mouclass migrated to PSEH 2.0 modified drivers/network/afd/afd/info.c modified drivers/network/afd/afd/lock.c modified drivers/network/afd/afd/tdi.c modified drivers/network/afd/afd/tdiconn.c afd migrated to PSEH 2.0 modified drivers/network/lan/lan/lan.c lan migrated to PSEH 2.0 modified drivers/network/tcpip/tcpip/dispatch.c tcpip migrated to PSEH 2.0 modified lib/rtl/debug.c modified lib/rtl/res.c modified lib/rtl/rtl.h modified lib/rtl/unicode.c modified lib/rtl/workitem.c rtl migrated to PSEH 2.0 modified ntoskrnl/include/precomp.h ntoskrnl migrated to PSEH 2.0 modified subsystems/csr/csrsrv/api.c csrsrv migrated to PSEH 2.0 modified subsystems/win32/win32k/eng/bitblt.c modified subsystems/win32/win32k/eng/mem.c modified subsystems/win32/win32k/include/mmcopy.h modified subsystems/win32/win32k/misc/copy.c modified subsystems/win32/win32k/ntuser/callback.c modified subsystems/win32/win32k/ntuser/class.c modified subsystems/win32/win32k/ntuser/clipboard.c modified subsystems/win32/win32k/ntuser/cursoricon.c modified subsystems/win32/win32k/ntuser/display.c modified subsystems/win32/win32k/ntuser/hook.c modified subsystems/win32/win32k/ntuser/input.c modified subsystems/win32/win32k/ntuser/kbdlayout.c modified subsystems/win32/win32k/ntuser/menu.c modified subsystems/win32/win32k/ntuser/misc.c modified subsystems/win32/win32k/ntuser/ntstubs.c modified subsystems/win32/win32k/ntuser/painting.c modified subsystems/win32/win32k/ntuser/simplecall.c modified subsystems/win32/win32k/ntuser/sysparams.c modified subsystems/win32/win32k/ntuser/window.c modified subsystems/win32/win32k/objects/bitblt.c modified subsystems/win32/win32k/objects/bitmaps.c modified subsystems/win32/win32k/objects/brush.c modified subsystems/win32/win32k/objects/cliprgn.c modified subsystems/win32/win32k/objects/color.c modified subsystems/win32/win32k/objects/coord.c modified subsystems/win32/win32k/objects/dc.c modified subsystems/win32/win32k/objects/dcutil.c modified subsystems/win32/win32k/objects/dibobj.c modified subsystems/win32/win32k/objects/fillshap.c modified subsystems/win32/win32k/objects/font.c modified subsystems/win32/win32k/objects/freetype.c modified subsystems/win32/win32k/objects/icm.c modified subsystems/win32/win32k/objects/line.c modified subsystems/win32/win32k/objects/path.c modified subsystems/win32/win32k/objects/pen.c modified subsystems/win32/win32k/objects/print.c modified subsystems/win32/win32k/objects/region.c modified subsystems/win32/win32k/objects/text.c modified subsystems/win32/win32k/pch.h win32k migrated to PSEH 2.0 svn path=/trunk/; revision=37776
2008-11-30 19:28:11 +00:00
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
SetLastNtError(Status);
else
Ret = TRUE;
UserDereferenceObject(CurIcon);
ObDereferenceObject(WinSta);
RETURN(Ret);
CLEANUP:
DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
#else
BOOL
APIENTRY
NtUserSetCursorIconData(
HANDLE hCurIcon,
PBOOL fIcon,
POINT *Hotspot,
HMODULE hModule,
HRSRC hRsrc,
HRSRC hGroupRsrc)
{
PCURICON_OBJECT CurIcon;
PWINSTATION_OBJECT WinSta;
NTSTATUS Status;
POINT SafeHotspot;
BOOL Ret = FALSE;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserSetCursorIconData\n");
UserEnterExclusive();
WinSta = IntGetWinStaObj();
if (WinSta == NULL)
{
RETURN(FALSE);
}
if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
{
ObDereferenceObject(WinSta);
RETURN(FALSE);
}
CurIcon->hModule = hModule;
CurIcon->hRsrc = hRsrc;
CurIcon->hGroupRsrc = hGroupRsrc;
/* Copy fields */
if (fIcon)
{
Status = MmCopyFromCaller(&CurIcon->IconInfo.fIcon, fIcon, sizeof(BOOL));
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
goto done;
}
}
else
{
if (!Hotspot)
Ret = TRUE;
}
if (Hotspot)
{
Status = MmCopyFromCaller(&SafeHotspot, Hotspot, sizeof(POINT));
if (NT_SUCCESS(Status))
{
CurIcon->IconInfo.xHotspot = SafeHotspot.x;
CurIcon->IconInfo.yHotspot = SafeHotspot.y;
Ret = TRUE;
}
else
SetLastNtError(Status);
}
if (!fIcon && !Hotspot)
{
Ret = TRUE;
}
done:
UserDereferenceObject(CurIcon);
ObDereferenceObject(WinSta);
RETURN(Ret);
CLEANUP:
DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
#endif
/*
* @unimplemented
*/
BOOL
APIENTRY
NtUserSetSystemCursor(
HCURSOR hcur,
DWORD id)
{
return FALSE;
}
BOOL
UserDrawIconEx(
HDC hDc,
INT xLeft,
INT yTop,
PCURICON_OBJECT pIcon,
INT cxWidth,
INT cyHeight,
UINT istepIfAniCur,
HBRUSH hbrFlickerFreeDraw,
UINT diFlags)
{
BOOL Ret = FALSE;
HBITMAP hbmMask, hbmColor;
BITMAP bmpMask, bmpColor;
BOOL DoFlickerFree;
SIZE IconSize;
HDC hdcOff;
HGDIOBJ hOldOffBrush = 0;
HGDIOBJ hOldOffBmp = 0;
HBITMAP hbmOff = 0;
HDC hdcMask = 0;
HGDIOBJ hOldMask = NULL;
HDC hdcImage = 0;
HGDIOBJ hOldImage = NULL;
BOOL bAlpha = FALSE;
hbmMask = pIcon->IconInfo.hbmMask;
hbmColor = pIcon->IconInfo.hbmColor;
if (istepIfAniCur)
DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
if (!hbmMask || !IntGdiGetObject(hbmMask, sizeof(BITMAP), (PVOID)&bmpMask))
{
return FALSE;
}
if (hbmColor && !IntGdiGetObject(hbmColor, sizeof(BITMAP), (PVOID)&bmpColor))
{
return FALSE;
}
if (hbmColor)
{
IconSize.cx = bmpColor.bmWidth;
IconSize.cy = bmpColor.bmHeight;
}
else
{
IconSize.cx = bmpMask.bmWidth;
IconSize.cy = bmpMask.bmHeight / 2;
}
/* NtGdiCreateCompatibleBitmap will create a monochrome bitmap
when cxWidth or cyHeight is 0 */
if ((bmpColor.bmBitsPixel == 32) && (cxWidth != 0) && (cyHeight != 0))
{
SURFACE *psurfOff = NULL;
PFN_DIB_GetPixel fnSource_GetPixel = NULL;
INT x, y;
/* In order to correctly display 32 bit icons Windows first scans the image,
because information about transparency is not stored in any image's headers */
psurfOff = SURFACE_LockSurface(hbmColor ? hbmColor : hbmMask);
if (psurfOff)
{
fnSource_GetPixel = DibFunctionsForBitmapFormat[psurfOff->SurfObj.iBitmapFormat].DIB_GetPixel;
if (fnSource_GetPixel)
{
for (x = 0; x < psurfOff->SurfObj.sizlBitmap.cx; x++)
{
for (y = 0; y < psurfOff->SurfObj.sizlBitmap.cy; y++)
{
bAlpha = ((BYTE)(fnSource_GetPixel(&psurfOff->SurfObj, x, y) >> 24) & 0xff);
if (bAlpha)
break;
}
if (bAlpha)
break;
}
}
SURFACE_UnlockSurface(psurfOff);
}
}
if (!diFlags)
diFlags = DI_NORMAL;
if (!cxWidth)
cxWidth = ((diFlags & DI_DEFAULTSIZE) ?
UserGetSystemMetrics(SM_CXICON) : IconSize.cx);
if (!cyHeight)
cyHeight = ((diFlags & DI_DEFAULTSIZE) ?
UserGetSystemMetrics(SM_CYICON) : IconSize.cy);
DoFlickerFree = (hbrFlickerFreeDraw &&
(GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH));
if (DoFlickerFree || bAlpha)
{
RECTL r;
BITMAP bm;
SURFACE *psurfOff = NULL;
r.right = cxWidth;
r.bottom = cyHeight;
hdcOff = NtGdiCreateCompatibleDC(hDc);
if (!hdcOff)
{
DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
return FALSE;
}
hbmOff = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight);
if (!hbmOff)
{
DPRINT1("NtGdiCreateCompatibleBitmap() failed!\n");
goto cleanup;
}
/* make sure we have a 32 bit offscreen bitmap
otherwise we can't do alpha blending */
psurfOff = SURFACE_LockSurface(hbmOff);
if (psurfOff == NULL)
{
DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
goto cleanup;
}
BITMAP_GetObject(psurfOff, sizeof(BITMAP), (PVOID)&bm);
if (bm.bmBitsPixel != 32)
bAlpha = FALSE;
SURFACE_UnlockSurface(psurfOff);
hOldOffBmp = NtGdiSelectBitmap(hdcOff, hbmOff);
if (!hOldOffBmp)
{
DPRINT1("NtGdiSelectBitmap() failed!\n");
goto cleanup;
}
if (DoFlickerFree)
{
hOldOffBrush = NtGdiSelectBrush(hdcOff, hbrFlickerFreeDraw);
if (!hOldOffBrush)
{
DPRINT1("NtGdiSelectBrush() failed!\n");
goto cleanup;
}
NtGdiPatBlt(hdcOff, 0, 0, r.right, r.bottom, PATCOPY);
}
}
else
hdcOff = hDc;
if (diFlags & DI_IMAGE)
{
hdcImage = NtGdiCreateCompatibleDC(hDc);
if (!hdcImage)
{
DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
goto cleanup;
}
hOldImage = NtGdiSelectBitmap(hdcImage, (hbmColor ? hbmColor : hbmMask));
if (!hOldImage)
{
DPRINT("NtGdiSelectBitmap() failed!\n");
goto cleanup;
}
}
/* If DI_IMAGE flag is specified and hbmMask exists, then always use mask for drawing */
if (diFlags & DI_MASK || (diFlags & DI_IMAGE && hbmMask))
{
hdcMask = NtGdiCreateCompatibleDC(hDc);
if (!hdcMask)
{
DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
goto cleanup;
}
hOldMask = NtGdiSelectBitmap(hdcMask, hbmMask);
if (!hOldMask)
{
DPRINT("NtGdiSelectBitmap() failed!\n");
goto cleanup;
}
}
if (hdcMask || hdcImage)
{
GreStretchBltMask(hdcOff,
(DoFlickerFree || bAlpha) ? 0 : xLeft,
(DoFlickerFree || bAlpha) ? 0 : yTop,
cxWidth,
cyHeight,
hdcImage ? hdcImage : hdcMask,
0,
((diFlags & DI_MASK && !(diFlags & DI_IMAGE)) ||
(diFlags & DI_IMAGE && hbmColor) ? 0 : IconSize.cy),
IconSize.cx,
IconSize.cy,
SRCCOPY,
0,
hdcImage ? hdcMask : NULL);
}
if (hOldMask) NtGdiSelectBitmap(hdcMask, hOldMask);
if (hOldImage) NtGdiSelectBitmap(hdcImage, hOldImage);
if (hdcImage) NtGdiDeleteObjectApp(hdcImage);
if (hdcMask) NtGdiDeleteObjectApp(hdcMask);
if (bAlpha)
{
BITMAP bm;
SURFACE *psurfOff = NULL;
PBYTE pBits = NULL;
BLENDFUNCTION BlendFunc;
DWORD Pixel;
BYTE Red, Green, Blue, Alpha;
DWORD Count = 0;
INT i, j;
psurfOff = SURFACE_LockSurface(hbmOff);
if (psurfOff == NULL)
{
DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
goto cleanup;
}
BITMAP_GetObject(psurfOff, sizeof(BITMAP), (PVOID)&bm);
pBits = ExAllocatePoolWithTag(PagedPool, bm.bmWidthBytes * abs(bm.bmHeight), TAG_BITMAP);
if (pBits == NULL)
{
DPRINT1("ExAllocatePoolWithTag() failed!\n");
SURFACE_UnlockSurface(psurfOff);
goto cleanup;
}
/* get icon bits */
IntGetBitmapBits(psurfOff, bm.bmWidthBytes * abs(bm.bmHeight), pBits);
/* premultiply with the alpha channel value */
for (i = 0; i < cyHeight; i++)
{
for (j = 0; j < cxWidth; j++)
{
Pixel = *(DWORD *)(pBits + Count);
Alpha = ((BYTE)(Pixel >> 24) & 0xff);
Red = (((BYTE)(Pixel >> 0)) * Alpha) / 0xff;
Green = (((BYTE)(Pixel >> 8)) * Alpha) / 0xff;
Blue = (((BYTE)(Pixel >> 16)) * Alpha) / 0xff;
*(DWORD *)(pBits + Count) = (DWORD)(Red | (Green << 8) | (Blue << 16) | (Alpha << 24));
Count += sizeof(DWORD);
}
}
/* set icon bits */
IntSetBitmapBits(psurfOff, bm.bmWidthBytes * abs(bm.bmHeight), pBits);
ExFreePoolWithTag(pBits, TAG_BITMAP);
SURFACE_UnlockSurface(psurfOff);
BlendFunc.BlendOp = AC_SRC_OVER;
BlendFunc.BlendFlags = 0;
BlendFunc.SourceConstantAlpha = 255;
BlendFunc.AlphaFormat = AC_SRC_ALPHA;
NtGdiAlphaBlend(hDc, xLeft, yTop, cxWidth, cyHeight,
hdcOff, 0, 0, cxWidth, cyHeight, BlendFunc, 0);
}
else if (DoFlickerFree)
{
NtGdiBitBlt(hDc, xLeft, yTop, cxWidth,
cyHeight, hdcOff, 0, 0, SRCCOPY, 0, 0);
}
Ret = TRUE;
cleanup:
if (DoFlickerFree || bAlpha)
{
if (hOldOffBmp) NtGdiSelectBitmap(hdcOff, hOldOffBmp);
if (hOldOffBrush) NtGdiSelectBrush(hdcOff, hOldOffBrush);
if (hbmOff) GreDeleteObject(hbmOff);
if (hdcOff) NtGdiDeleteObjectApp(hdcOff);
}
return Ret;
}
/*
* @implemented
*/
BOOL
APIENTRY
NtUserDrawIconEx(
HDC hdc,
int xLeft,
int yTop,
HICON hIcon,
int cxWidth,
int cyHeight,
UINT istepIfAniCur,
HBRUSH hbrFlickerFreeDraw,
UINT diFlags,
DWORD Unknown0,
DWORD Unknown1)
{
PCURICON_OBJECT pIcon;
BOOL Ret;
DPRINT("Enter NtUserDrawIconEx\n");
UserEnterExclusive();
if (!(pIcon = UserGetCurIconObject(hIcon)))
{
DPRINT1("UserGetCurIconObject() failed!\n");
UserLeave();
return FALSE;
}
Ret = UserDrawIconEx(hdc,
xLeft,
yTop,
pIcon,
cxWidth,
cyHeight,
istepIfAniCur,
hbrFlickerFreeDraw,
diFlags);
UserDereferenceObject(pIcon);
UserLeave();
return Ret;
}
/* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
* User32 macro NtUserShowCursor */
int
APIENTRY
UserShowCursor(BOOL bShow)
{
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
PWINSTATION_OBJECT WinSta = pti->Desktop->WindowStation;
PSYSTEM_CURSORINFO CurInfo;
HDC Screen;
PDC dc;
SURFOBJ *SurfObj;
SURFACE *psurfDc;
PDEVOBJ *ppdev;
GDIPOINTER *pgp;
int showpointer=0;
if (!(Screen = IntGetScreenDC()))
{
return showpointer; /* No mouse */
}
dc = DC_LockDc(Screen);
if (!dc)
{
return showpointer; /* No mouse */
}
psurfDc = dc->dclevel.pSurface;
if (!psurfDc)
{
DC_UnlockDc(dc);
return showpointer; /* No Mouse */
}
SurfObj = &psurfDc->SurfObj;
if (SurfObj == NULL)
{
DC_UnlockDc(dc);
return showpointer; /* No mouse */
}
ppdev = GDIDEV(SurfObj);
if (ppdev == NULL)
{
DC_UnlockDc(dc);
return showpointer; /* No mouse */
}
pgp = &ppdev->Pointer;
CurInfo = IntGetSysCursorInfo(WinSta);
if (bShow == FALSE)
{
pgp->ShowPointer--;
showpointer = pgp->ShowPointer;
if (showpointer >= 0)
{
//ppdev->SafetyRemoveCount = 1;
//ppdev->SafetyRemoveLevel = 1;
IntEngMovePointer(SurfObj,-1,-1,NULL);
CurInfo->ShowingCursor = 0;
}
}
else
{
pgp->ShowPointer++;
showpointer = pgp->ShowPointer;
/* Show Cursor */
if (showpointer < 0)
{
//ppdev->SafetyRemoveCount = 0;
//ppdev->SafetyRemoveLevel = 0;
IntEngMovePointer(SurfObj,-1,-1,NULL);
CurInfo->ShowingCursor = CURSOR_SHOWING;
}
}
DC_UnlockDc(dc);
return showpointer;
}