[WIN32SS/USER]

- Start using CURSORDATA structure for passing data from user to kernel mode.
- Start using the proper CURSOR structure for win32k internal represesentation of cursor and icons
- Create the alpha bitmap in user mode instead of kernel mode.


svn path=/trunk/; revision=57692
This commit is contained in:
Jérôme Gardou 2012-11-08 12:51:24 +00:00
parent 5ad72c9145
commit bd515ad606
6 changed files with 592 additions and 469 deletions

View file

@ -976,6 +976,43 @@ typedef struct tagSETCLIPBDATA
BOOL fIncSerialNumber;
} SETCLIPBDATA, *PSETCLIPBDATA;
// Used with NtUserSetCursorIconData, last parameter.
typedef struct tagCURSORDATA
{
LPWSTR lpName;
LPWSTR lpModName;
USHORT rt;
USHORT dummy;
ULONG CURSORF_flags;
SHORT xHotspot;
SHORT yHotspot;
HBITMAP hbmMask;
HBITMAP hbmColor;
HBITMAP hbmAlpha;
RECT rcBounds;
HBITMAP hbmUserAlpha; // Could be in W7U, not in W2k
ULONG bpp;
ULONG cx;
ULONG cy;
INT cpcur;
INT cicur;
struct tagCURSORDATA * aspcur;
DWORD * aicur;
INT * ajifRate;
INT iicur;
} CURSORDATA, *PCURSORDATA; /* !dso CURSORDATA */
// CURSORF_flags:
#define CURSORF_FROMRESOURCE 0x0001
#define CURSORF_GLOBAL 0x0002
#define CURSORF_LRSHARED 0x0004
#define CURSORF_ACON 0x0008
#define CURSORF_WOWCLEANUP 0x0010
#define CURSORF_ACONFRAME 0x0040
#define CURSORF_SECRET 0x0080
#define CURSORF_LINKED 0x0100
#define CURSORF_CURRENT 0x0200
DWORD
NTAPI
NtUserAssociateInputContext(
@ -2737,15 +2774,21 @@ NtUserSetCursorIconData(
_In_ HCURSOR hCursor,
_In_ PUNICODE_STRING pustrModule,
_In_ PUNICODE_STRING puSrcName,
_In_ PICONINFO pii);
_In_ PCURSORDATA pCursorData);
typedef struct _tagFINDEXISTINGCURICONPARAM
{
BOOL bIcon;
LONG cx;
LONG cy;
} FINDEXISTINGCURICONPARAM;
HICON
NTAPI
NtUserFindExistingCursorIcon(
_In_ PUNICODE_STRING pustrModule,
_In_ PUNICODE_STRING pustrRsrc,
_In_ LONG cxDesired,
_In_ LONG cyDesired);
_In_ FINDEXISTINGCURICONPARAM* param);
#else
BOOL
NTAPI

View file

@ -9,26 +9,29 @@ typedef struct tagCURICON_PROCESS
} CURICON_PROCESS, *PCURICON_PROCESS;
#ifdef NEW_CURSORICON
typedef struct _CURICON_FRAME
{
HBITMAP hbmMask;
HBITMAP hbmColor;
HBITMAP hbmAlpha;
} CURICON_FRAME, *PCURICON_FRAME;
typedef struct _CURICON_OBJECT
{
PROCMARKHEAD head;
PROCMARKHEAD head;
struct _tagCURSOR* pcurNext;
UNICODE_STRING strName;
USHORT atomModName;
USHORT rt;
ULONG CURSORF_flags;
SHORT xHotspot;
SHORT yHotspot;
HBITMAP hbmMask;
HBITMAP hbmColor;
HBITMAP hbmAlpha;
RECT rcBounds;
HBITMAP hbmUserAlpha;
ULONG bpp;
ULONG cx;
ULONG cy;
/* ReactOS specific, to be deleted */
LIST_ENTRY ListEntry;
HANDLE Self;
LIST_ENTRY ProcessList;
UNICODE_STRING ustrModule;
UNICODE_STRING ustrRsrc;
SIZE Size;
BYTE Shadow;
BOOL bIcon;
POINTL ptlHotspot;
CURICON_FRAME aFrame[1];
} CURICON_OBJECT, *PCURICON_OBJECT;
#else

View file

@ -27,8 +27,8 @@
#include <win32k.h>
DBG_DEFAULT_CHANNEL(UserIcon);
static PPAGED_LOOKASIDE_LIST pgProcessLookasideList;
static LIST_ENTRY gCurIconList;
static PAGED_LOOKASIDE_LIST *pgProcessLookasideList;
SYSTEM_CURSORINFO gSysCursorInfo;
@ -48,14 +48,14 @@ InitCursorImpl()
128);
InitializeListHead(&gCurIconList);
gSysCursorInfo.Enabled = FALSE;
gSysCursorInfo.ButtonsDown = 0;
gSysCursorInfo.bClipped = FALSE;
gSysCursorInfo.LastBtnDown = 0;
gSysCursorInfo.CurrentCursorObject = NULL;
gSysCursorInfo.ShowingCursor = -1;
gSysCursorInfo.ClickLockActive = FALSE;
gSysCursorInfo.ClickLockTime = 0;
gSysCursorInfo.Enabled = FALSE;
gSysCursorInfo.ButtonsDown = 0;
gSysCursorInfo.bClipped = FALSE;
gSysCursorInfo.LastBtnDown = 0;
gSysCursorInfo.CurrentCursorObject = NULL;
gSysCursorInfo.ShowingCursor = -1;
gSysCursorInfo.ClickLockActive = FALSE;
gSysCursorInfo.ClickLockTime = 0;
return TRUE;
}
@ -66,6 +66,13 @@ IntGetSysCursorInfo()
return &gSysCursorInfo;
}
FORCEINLINE
BOOL
is_icon(PCURICON_OBJECT object)
{
return MAKEINTRESOURCE(object->rt) == RT_ICON;
}
/* This function creates a reference for the object! */
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
{
@ -182,23 +189,23 @@ IntFindExistingCurIconObject(
LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry)
{
/* See if we are looking for an icon or a cursor */
if(CurIcon->bIcon != param->bIcon)
if(MAKEINTRESOURCE(CurIcon->rt) != (param->bIcon ? RT_ICON : RT_CURSOR))
continue;
/* See if module names match */
if(RtlCompareUnicodeString(pustrModule, &CurIcon->ustrModule, TRUE) == 0)
{
/* They do. Now see if this is the same resource */
if(IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer) && IS_INTRESOURCE(pustrRsrc->Buffer))
if(IS_INTRESOURCE(CurIcon->strName.Buffer) && IS_INTRESOURCE(pustrRsrc->Buffer))
{
if(CurIcon->ustrRsrc.Buffer != pustrRsrc->Buffer)
if(CurIcon->strName.Buffer != pustrRsrc->Buffer)
continue;
}
else if(IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer) || IS_INTRESOURCE(pustrRsrc->Buffer))
else if(IS_INTRESOURCE(CurIcon->strName.Buffer) || IS_INTRESOURCE(pustrRsrc->Buffer))
continue;
else if(RtlCompareUnicodeString(pustrRsrc, &CurIcon->ustrRsrc, TRUE) != 0)
else if(RtlCompareUnicodeString(pustrRsrc, &CurIcon->strName, TRUE) != 0)
continue;
if ((param->cx == CurIcon->Size.cx) &&(param->cy == CurIcon->Size.cy))
if ((param->cx == CurIcon->cx) && (param->cy == CurIcon->cy))
{
if (! ReferenceCurIconByProcess(CurIcon))
{
@ -217,13 +224,12 @@ PCURICON_OBJECT
IntCreateCurIconHandle(DWORD dwNumber)
{
PCURICON_OBJECT CurIcon;
BOOLEAN bIcon = dwNumber == 0;
HANDLE hCurIcon;
if(dwNumber == 0)
dwNumber = 1;
CurIcon = UserCreateObject(gHandleTable, NULL, NULL, &hCurIcon, otCursorIcon, FIELD_OFFSET(CURICON_OBJECT, aFrame[dwNumber]));
CurIcon = UserCreateObject(gHandleTable, NULL, NULL, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT));
if (!CurIcon)
{
@ -232,14 +238,13 @@ IntCreateCurIconHandle(DWORD dwNumber)
}
CurIcon->Self = hCurIcon;
CurIcon->bIcon = bIcon;
InitializeListHead(&CurIcon->ProcessList);
if (! ReferenceCurIconByProcess(CurIcon))
{
ERR("Failed to add process\n");
UserDeleteObject(hCurIcon, otCursorIcon);
UserDereferenceObject(CurIcon);
UserDeleteObject(hCurIcon, otCursorIcon);
return NULL;
}
@ -251,11 +256,17 @@ IntCreateCurIconHandle(DWORD dwNumber)
BOOLEAN FASTCALL
IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi, BOOLEAN bForce)
{
PSYSTEM_CURSORINFO CurInfo;
HBITMAP bmpMask, bmpColor, bmpAlpha;
BOOLEAN Ret, bListEmpty, bFound = FALSE;
PCURICON_PROCESS Current = NULL;
/* Check if this is the current cursor */
if(CurIcon->CURSORF_flags & CURSORF_CURRENT)
{
UserDereferenceObject(CurIcon);
return FALSE;
}
/* For handles created without any data (error handling) */
if(IsListEmpty(&CurIcon->ProcessList))
goto emptyList;
@ -308,40 +319,32 @@ emptyList:
/* Remove it from the list */
RemoveEntryList(&CurIcon->ListEntry);
CurInfo = IntGetSysCursorInfo();
if (CurInfo->CurrentCursorObject == CurIcon)
{
/* Hide the cursor if we're destroying the current cursor */
UserSetCursor(NULL, TRUE);
}
bmpMask = CurIcon->aFrame[0].hbmMask;
bmpColor = CurIcon->aFrame[0].hbmColor;
bmpAlpha = CurIcon->aFrame[0].hbmAlpha;
bmpMask = CurIcon->hbmMask;
bmpColor = CurIcon->hbmColor;
bmpAlpha = CurIcon->hbmAlpha;
/* Delete bitmaps */
if (bmpMask)
{
GreSetObjectOwner(bmpMask, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(bmpMask);
CurIcon->aFrame[0].hbmMask = NULL;
CurIcon->hbmMask = NULL;
}
if (bmpColor)
{
GreSetObjectOwner(bmpColor, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(bmpColor);
CurIcon->aFrame[0].hbmColor = NULL;
CurIcon->hbmColor = NULL;
}
if (bmpAlpha)
{
GreSetObjectOwner(bmpAlpha, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(bmpAlpha);
CurIcon->aFrame[0].hbmAlpha = NULL;
CurIcon->hbmAlpha = NULL;
}
if(!IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer))
ExFreePoolWithTag(CurIcon->ustrRsrc.Buffer, TAG_STRING);
if(!IS_INTRESOURCE(CurIcon->strName.Buffer))
ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING);
if(CurIcon->ustrModule.Buffer)
ReleaseCapturedUnicodeString(&CurIcon->ustrModule, UserMode);
@ -408,27 +411,16 @@ NtUserGetIconInfo(
if(IconInfo)
{
/* Fill data */
ii.fIcon = CurIcon->bIcon;
ii.xHotspot = CurIcon->ptlHotspot.x;
ii.yHotspot = CurIcon->ptlHotspot.y;
ii.fIcon = is_icon(CurIcon);
ii.xHotspot = CurIcon->xHotspot;
ii.yHotspot = CurIcon->yHotspot;
/* Copy bitmaps */
ii.hbmMask = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmMask);
ii.hbmMask = BITMAP_CopyBitmap(CurIcon->hbmMask);
GreSetObjectOwner(ii.hbmMask, GDI_OBJ_HMGR_POWNED);
ii.hbmColor = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmColor);
ii.hbmColor = BITMAP_CopyBitmap(CurIcon->hbmColor);
GreSetObjectOwner(ii.hbmColor, GDI_OBJ_HMGR_POWNED);
if (pbpp)
{
PSURFACE psurfBmp;
psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor);
if (psurfBmp)
{
colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
SURFACE_ShareUnlockSurface(psurfBmp);
}
}
colorBpp = CurIcon->bpp;
/* Copy fields */
_SEH2_TRY
@ -487,7 +479,7 @@ NtUserGetIconInfo(
if(lpResName)
{
if(!CurIcon->ustrRsrc.Buffer)
if(!CurIcon->strName.Buffer)
{
EngSetLastError(ERROR_INVALID_HANDLE);
goto leave;
@ -496,15 +488,15 @@ NtUserGetIconInfo(
_SEH2_TRY
{
ProbeForWrite(lpResName, sizeof(UNICODE_STRING), 1);
if(IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer))
if(IS_INTRESOURCE(CurIcon->strName.Buffer))
{
lpResName->Buffer = CurIcon->ustrRsrc.Buffer;
lpResName->Buffer = CurIcon->strName.Buffer;
lpResName->Length = 0;
}
else
{
lpResName->Length = min(lpResName->MaximumLength, CurIcon->ustrRsrc.Length);
RtlCopyMemory(lpResName->Buffer, CurIcon->ustrRsrc.Buffer, lpResName->Length);
lpResName->Length = min(lpResName->MaximumLength, CurIcon->strName.Length);
RtlCopyMemory(lpResName->Buffer, CurIcon->strName.Buffer, lpResName->Length);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@ -558,9 +550,9 @@ NtUserGetIconSize(
_SEH2_TRY
{
ProbeForWrite(plcx, sizeof(LONG), 1);
RtlCopyMemory(plcx, &CurIcon->Size.cx, sizeof(LONG));
*plcx = CurIcon->cx;
ProbeForWrite(plcy, sizeof(LONG), 1);
RtlCopyMemory(plcy, &CurIcon->Size.cy, sizeof(LONG));
*plcy = CurIcon->cy;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@ -788,7 +780,7 @@ NtUserFindExistingCursorIcon(
_SEH2_TRY
{
ProbeForRead(param, sizeof(*param), 1);
paramSafe = *param;
RtlCopyMemory(&paramSafe, param, sizeof(paramSafe));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@ -882,6 +874,7 @@ NtUserSetCursor(
EngSetLastError(ERROR_INVALID_CURSOR_HANDLE);
goto leave;
}
pcurNew->CURSORF_flags |= CURSORF_CURRENT;
}
else
{
@ -892,6 +885,7 @@ NtUserSetCursor(
if (pcurOld)
{
hOldCursor = (HCURSOR)pcurOld->Self;
pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
UserDereferenceObject(pcurOld);
}
@ -902,7 +896,7 @@ leave:
/*
* @implemented
* @unimplemented
*/
BOOL
APIENTRY
@ -910,150 +904,8 @@ NtUserSetCursorContents(
HANDLE hCurIcon,
PICONINFO UnsafeIconInfo)
{
PCURICON_OBJECT CurIcon;
ICONINFO IconInfo;
PSURFACE psurfBmp;
NTSTATUS Status;
BOOL Ret = FALSE;
DECLARE_RETURN(BOOL);
TRACE("Enter NtUserSetCursorContents\n");
UserEnterExclusive();
if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
{
RETURN(FALSE);
}
/* Copy fields */
Status = MmCopyFromCaller(&IconInfo, UnsafeIconInfo, sizeof(ICONINFO));
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
goto done;
}
#if 0
/* Check if we get valid information */
if(IconInfo.fIcon != CurInfo->bIcon)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
goto done;
}
#endif
/* Delete old bitmaps */
if (CurIcon->aFrame[0].hbmColor)
GreDeleteObject(CurIcon->aFrame[0].hbmColor);
if (CurIcon->aFrame[0].hbmMask)
GreDeleteObject(CurIcon->aFrame[0].hbmMask);
if(CurIcon->aFrame[0].hbmAlpha)
GreDeleteObject(CurIcon->aFrame[0].hbmAlpha);
/* Set fields */
CurIcon->bIcon = IconInfo.fIcon;
CurIcon->ptlHotspot.x = IconInfo.xHotspot;
CurIcon->ptlHotspot.y = IconInfo.yHotspot;
CurIcon->aFrame[0].hbmMask = IconInfo.hbmMask;
CurIcon->aFrame[0].hbmColor = IconInfo.hbmColor;
CurIcon->aFrame[0].hbmAlpha = NULL;
if (IconInfo.hbmColor)
{
BOOLEAN bAlpha = FALSE;
psurfBmp = SURFACE_ShareLockSurface(IconInfo.hbmColor);
if (!psurfBmp)
goto done;
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
/* 32bpp bitmap is likely to have an alpha channel */
if(psurfBmp->SurfObj.iBitmapFormat == BMF_32BPP)
{
PFN_DIB_GetPixel fn_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel;
INT i, j;
fn_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel;
for (i = 0; i < psurfBmp->SurfObj.sizlBitmap.cx; i++)
{
for (j = 0; j < psurfBmp->SurfObj.sizlBitmap.cy; j++)
{
bAlpha = ((BYTE)(fn_GetPixel(&psurfBmp->SurfObj, i, j) >> 24)) != 0;
if (bAlpha)
break;
}
if (bAlpha)
break;
}
}
/* We're done with this one */
SURFACE_ShareUnlockSurface(psurfBmp);
GreSetObjectOwner(IconInfo.hbmColor, GDI_OBJ_HMGR_PUBLIC);
if(bAlpha)
{
UCHAR Alpha;
PUCHAR ptr;
INT i, j;
/* Copy the bitmap */
CurIcon->aFrame[0].hbmAlpha = BITMAP_CopyBitmap(IconInfo.hbmColor);
if(!CurIcon->aFrame[0].hbmAlpha)
{
ERR("BITMAP_CopyBitmap failed!");
goto done;
}
psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmAlpha);
if(!psurfBmp)
{
ERR("SURFACE_LockSurface failed!\n");
goto done;
}
/* Premultiply with the alpha channel value */
for (i = 0; i < psurfBmp->SurfObj.sizlBitmap.cy; i++)
{
ptr = (PBYTE)psurfBmp->SurfObj.pvScan0 + i*psurfBmp->SurfObj.lDelta;
for (j = 0; j < psurfBmp->SurfObj.sizlBitmap.cx; j++)
{
Alpha = ptr[3];
ptr[0] = (ptr[0] * Alpha) / 0xff;
ptr[1] = (ptr[1] * Alpha) / 0xff;
ptr[2] = (ptr[2] * Alpha) / 0xff;
ptr += 4;
}
}
SURFACE_ShareUnlockSurface(psurfBmp);
GreSetObjectOwner(CurIcon->aFrame[0].hbmAlpha, GDI_OBJ_HMGR_PUBLIC);
}
}
else
{
psurfBmp = SURFACE_ShareLockSurface(IconInfo.hbmMask);
if (!psurfBmp)
goto done;
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy / 2;
SURFACE_ShareUnlockSurface(psurfBmp);
}
GreSetObjectOwner(IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC);
Ret = TRUE;
done:
if (CurIcon)
{
UserDereferenceObject(CurIcon);
}
RETURN(Ret);
CLEANUP:
TRACE("Leave NtUserSetCursorContents, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
FIXME(" is UNIMPLEMENTED.\n");
return FALSE;
}
@ -1066,13 +918,12 @@ NtUserSetCursorIconData(
_In_ HCURSOR Handle,
_In_opt_ PUNICODE_STRING pustrModule,
_In_opt_ PUNICODE_STRING pustrRsrc,
_In_ PICONINFO pIconInfo)
_In_ PCURSORDATA pCursorData)
{
PCURICON_OBJECT CurIcon;
PSURFACE psurfBmp;
NTSTATUS Status = STATUS_SUCCESS;
BOOL Ret = FALSE;
ICONINFO ii;
CURSORDATA dataSafe;
TRACE("Enter NtUserSetCursorIconData\n");
@ -1091,8 +942,8 @@ NtUserSetCursorIconData(
_SEH2_TRY
{
ProbeForRead(pIconInfo, sizeof(ICONINFO), 1);
ii = *pIconInfo;
ProbeForRead(pCursorData, sizeof(*pCursorData), 1);
RtlCopyMemory(&dataSafe, pCursorData, sizeof(dataSafe));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@ -1105,60 +956,46 @@ NtUserSetCursorIconData(
SetLastNtError(Status);
goto done;
}
CurIcon->xHotspot = dataSafe.xHotspot;
CurIcon->yHotspot = dataSafe.yHotspot;
CurIcon->cx = dataSafe.cx;
CurIcon->cy = dataSafe.cy;
CurIcon->rt = dataSafe.rt;
CurIcon->bpp = dataSafe.bpp;
/* This is probably not what windows does, but consistency checks can't hurt */
if(CurIcon->bIcon != ii.fIcon)
if(!dataSafe.hbmMask)
{
ERR("NtUserSetCursorIconData was got no hbmMask.\n");
EngSetLastError(ERROR_INVALID_PARAMETER);
goto done;
}
CurIcon->ptlHotspot.x = ii.xHotspot;
CurIcon->ptlHotspot.y = ii.yHotspot;
CurIcon->hbmMask = BITMAP_CopyBitmap(dataSafe.hbmMask);
if(!CurIcon->hbmMask)
goto done;
GreSetObjectOwner(CurIcon->hbmMask, GDI_OBJ_HMGR_PUBLIC);
if(dataSafe.hbmColor)
{
CurIcon->hbmColor = BITMAP_CopyBitmap(dataSafe.hbmColor);
if(!CurIcon->hbmColor)
goto done;
GreSetObjectOwner(CurIcon->hbmColor, GDI_OBJ_HMGR_PUBLIC);
}
if(!ii.hbmMask)
if(dataSafe.hbmAlpha)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
goto done;
}
CurIcon->aFrame[0].hbmMask = BITMAP_CopyBitmap(ii.hbmMask);
if(!CurIcon->aFrame[0].hbmMask)
goto done;
if(ii.hbmColor)
{
CurIcon->aFrame[0].hbmColor = BITMAP_CopyBitmap(ii.hbmColor);
if(!CurIcon->aFrame[0].hbmColor)
CurIcon->hbmAlpha = BITMAP_CopyBitmap(dataSafe.hbmAlpha);
if(!CurIcon->hbmAlpha)
goto done;
GreSetObjectOwner(CurIcon->hbmAlpha, GDI_OBJ_HMGR_PUBLIC);
}
if (CurIcon->aFrame[0].hbmColor)
{
psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor);
if(!psurfBmp)
goto done;
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
SURFACE_ShareUnlockSurface(psurfBmp);
GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_PUBLIC);
}
else
{
psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmMask);
if(!psurfBmp)
goto done;
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy/2;
SURFACE_ShareUnlockSurface(psurfBmp);
}
GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC);
if(pustrModule)
{
/* We use this convenient function, because INTRESOURCEs and ATOMs are the same */
Status = ProbeAndCaptureUnicodeStringOrAtom(&CurIcon->ustrRsrc, pustrRsrc);
Status = ProbeAndCaptureUnicodeStringOrAtom(&CurIcon->strName, pustrRsrc);
if(!NT_SUCCESS(Status))
goto done;
Status = ProbeAndCaptureUnicodeString(&CurIcon->ustrModule, UserMode, pustrModule);
@ -1169,27 +1006,32 @@ NtUserSetCursorIconData(
Ret = TRUE;
done:
UserDereferenceObject(CurIcon);
if(!Ret)
{
if (CurIcon->aFrame[0].hbmMask)
if (CurIcon->hbmMask)
{
GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(CurIcon->aFrame[0].hbmMask);
CurIcon->aFrame[0].hbmMask = NULL;
GreSetObjectOwner(CurIcon->hbmMask, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(CurIcon->hbmMask);
CurIcon->hbmMask = NULL;
}
if (CurIcon->aFrame[0].hbmColor)
if (CurIcon->hbmColor)
{
GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(CurIcon->aFrame[0].hbmColor);
CurIcon->aFrame[0].hbmColor = NULL;
GreSetObjectOwner(CurIcon->hbmColor, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(CurIcon->hbmColor);
CurIcon->hbmColor = NULL;
}
if(!IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer))
ExFreePoolWithTag(CurIcon->ustrRsrc.Buffer, TAG_STRING);
if (CurIcon->hbmAlpha)
{
GreSetObjectOwner(CurIcon->hbmAlpha, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(CurIcon->hbmAlpha);
CurIcon->hbmAlpha = NULL;
}
if(!IS_INTRESOURCE(CurIcon->strName.Buffer))
ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING);
if(CurIcon->ustrModule.Buffer)
ReleaseCapturedUnicodeString(&CurIcon->ustrModule, UserMode);
}
UserDereferenceObject(CurIcon);
TRACE("Leave NtUserSetCursorIconData, ret=%i\n",Ret);
UserLeave();
@ -1232,9 +1074,9 @@ UserDrawIconEx(
return FALSE;
}
hbmMask = pIcon->aFrame[0].hbmMask;
hbmColor = pIcon->aFrame[0].hbmColor;
hbmAlpha = pIcon->aFrame[0].hbmAlpha;
hbmMask = pIcon->hbmMask;
hbmColor = pIcon->hbmColor;
hbmAlpha = pIcon->hbmAlpha;
if (istepIfAniCur)
ERR("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
@ -1254,7 +1096,7 @@ UserDrawIconEx(
if(hbmColor == NULL)
{
/* But then the mask bitmap must have the information in it's bottom half */
ASSERT(psurfMask->SurfObj.sizlBitmap.cy == 2*pIcon->Size.cy);
ASSERT(psurfMask->SurfObj.sizlBitmap.cy == 2*pIcon->cy);
psurfColor = NULL;
}
else if ((psurfColor = SURFACE_ShareLockSurface(hbmColor)) == NULL)
@ -1294,26 +1136,26 @@ UserDrawIconEx(
}
/* Set source rect */
RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy);
RECTL_vSetRect(&rcSrc, 0, 0, pIcon->cx, pIcon->cy);
/* Fix width parameter, if needed */
if (!cxWidth)
{
if(diFlags & DI_DEFAULTSIZE)
cxWidth = pIcon->bIcon ?
cxWidth = is_icon(pIcon) ?
UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR);
else
cxWidth = pIcon->Size.cx;
cxWidth = pIcon->cx;
}
/* Fix height parameter, if needed */
if (!cyHeight)
{
if(diFlags & DI_DEFAULTSIZE)
cyHeight = pIcon->bIcon ?
cyHeight = is_icon(pIcon) ?
UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR);
else
cyHeight = pIcon->Size.cy;
cyHeight = pIcon->cy;
}
/* Should we render off-screen? */
@ -1410,7 +1252,7 @@ UserDrawIconEx(
}
/* Now do the rendering */
if(hbmAlpha && (diFlags & DI_IMAGE))
if(hbmAlpha && ((diFlags & DI_NORMAL) == DI_NORMAL))
{
BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } };
PSURFACE psurf = NULL;
@ -1501,7 +1343,7 @@ NoAlpha:
{
/* Mask bitmap holds the information in its bottom half */
DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY;
RECTL_vOffsetRect(&rcSrc, 0, pIcon->Size.cy);
RECTL_vOffsetRect(&rcSrc, 0, pIcon->cy);
EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);

View file

@ -147,10 +147,10 @@ UserSetCursor(
/* Call GDI to set the new screen cursor */
#ifdef NEW_CURSORICON
GreSetPointerShape(hdcScreen,
NewCursor->aFrame[0].hbmMask,
NewCursor->aFrame[0].hbmColor,
NewCursor->ptlHotspot.x,
NewCursor->ptlHotspot.y,
NewCursor->hbmMask,
NewCursor->hbmColor,
NewCursor->xHotspot,
NewCursor->yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
#else
@ -583,10 +583,10 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
/* Call GDI to set the new screen cursor */
#ifdef NEW_CURSORICON
GreSetPointerShape(hdcScreen,
MessageQueue->CursorObject->aFrame[0].hbmMask,
MessageQueue->CursorObject->aFrame[0].hbmColor,
MessageQueue->CursorObject->ptlHotspot.x,
MessageQueue->CursorObject->ptlHotspot.y,
MessageQueue->CursorObject->hbmMask,
MessageQueue->CursorObject->hbmColor,
MessageQueue->CursorObject->xHotspot,
MessageQueue->CursorObject->yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
#else

View file

@ -1,8 +1,8 @@
/*
* PROJECT: ReactOS user32.dll
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: dll/win32/user32/windows/class.c
* PURPOSE: Window classes
* FILE: dll/win32/user32/windows/cursoricon.c
* PURPOSE: cursor and icons implementation
* PROGRAMMER: Jérôme Gardou (jerome.gardou@reactos.org)
*/
@ -171,13 +171,144 @@ static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
return -1;
}
/***********************************************************************
* bmi_has_alpha
*/
static BOOL bmi_has_alpha( const BITMAPINFO *info, const void *bits )
{
int i;
BOOL has_alpha = FALSE;
const unsigned char *ptr = bits;
if (info->bmiHeader.biBitCount != 32) return FALSE;
for (i = 0; i < info->bmiHeader.biWidth * abs(info->bmiHeader.biHeight); i++, ptr += 4)
if ((has_alpha = (ptr[3] != 0))) break;
return has_alpha;
}
/***********************************************************************
* create_alpha_bitmap
*
* Create the alpha bitmap for a 32-bpp icon that has an alpha channel.
*/
static HBITMAP create_alpha_bitmap(
_In_ HBITMAP color,
_In_opt_ const BITMAPINFO *src_info,
_In_opt_ const void *color_bits )
{
HBITMAP alpha = NULL, hbmpOld;
BITMAPINFO *info = NULL;
HDC hdc = NULL, hdcScreen;
void *bits = NULL;
unsigned char *ptr;
int i;
LONG width, height;
BITMAP bm;
if (!GetObjectW( color, sizeof(bm), &bm ))
return NULL;
if (bm.bmBitsPixel != 32)
return NULL;
hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL);
if(!hdcScreen)
return NULL;
if(GetDeviceCaps(hdcScreen, BITSPIXEL) != 32)
goto done;
hdc = CreateCompatibleDC(hdcScreen);
if(!hdc)
goto done;
if(src_info)
{
WORD bpp;
DWORD compr;
int size;
if(!bmi_has_alpha(src_info, color_bits))
goto done;
if(!DIB_GetBitmapInfo(&src_info->bmiHeader, &width, &height, &bpp, &compr))
goto done;
if(bpp != 32)
goto done;
size = get_dib_image_size(width, height, bpp);
bits = HeapAlloc(GetProcessHeap(), 0, size);
if(!bits)
goto done;
CopyMemory(bits, color_bits, size);
}
else
{
info = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(BITMAPINFO, bmiColors[256]));
if(!info)
goto done;
info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info->bmiHeader.biWidth = bm.bmWidth;
info->bmiHeader.biHeight = -bm.bmHeight;
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biBitCount = 32;
info->bmiHeader.biCompression = BI_RGB;
info->bmiHeader.biSizeImage = bm.bmWidth * bm.bmHeight * 4;
info->bmiHeader.biXPelsPerMeter = 0;
info->bmiHeader.biYPelsPerMeter = 0;
info->bmiHeader.biClrUsed = 0;
info->bmiHeader.biClrImportant = 0;
bits = HeapAlloc(GetProcessHeap(), 0, info->bmiHeader.biSizeImage);
if(!bits)
goto done;
if(!GetDIBits( hdc, color, 0, bm.bmHeight, bits, info, DIB_RGB_COLORS ))
goto done;
if (!bmi_has_alpha( info, bits ))
goto done;
width = bm.bmWidth;
height = bm.bmHeight;
}
/* pre-multiply by alpha */
for (i = 0, ptr = bits; i < width * height; i++, ptr += 4)
{
unsigned int alpha = ptr[3];
ptr[0] = ptr[0] * alpha / 255;
ptr[1] = ptr[1] * alpha / 255;
ptr[2] = ptr[2] * alpha / 255;
}
/* Create the bitmap */
alpha = CreateCompatibleBitmap(hdcScreen, bm.bmWidth, bm.bmHeight);
if(!alpha)
goto done;
hbmpOld = SelectObject(hdc, alpha);
if(!hbmpOld)
goto done;
if(!StretchDIBits( hdc, 0, 0, bm.bmWidth, bm.bmHeight,
0, 0, width, height,
bits, src_info ? src_info : info, DIB_RGB_COLORS, SRCCOPY ))
{
SelectObject(hdc, hbmpOld);
hbmpOld = NULL;
DeleteObject(alpha);
alpha = NULL;
}
SelectObject(hdc, hbmpOld);
done:
DeleteDC(hdcScreen);
if(hdc) DeleteDC( hdc );
if(info) HeapFree( GetProcessHeap(), 0, info );
if(bits) HeapFree(GetProcessHeap(), 0, bits);
TRACE("Returning 0x%08x.\n", alpha);
return alpha;
}
/************* IMPLEMENTATION CORE ****************/
static BOOL CURSORICON_GetIconInfoFromBMI(
_Inout_ ICONINFO* pii,
_In_ const BITMAPINFO *pbmi,
_In_ int cxDesired,
_In_ int cyDesired
static BOOL CURSORICON_GetCursorDataFromBMI(
_Inout_ CURSORDATA* pdata,
_In_ const BITMAPINFO *pbmi
)
{
UINT ubmiSize = bitmap_info_size(pbmi, DIB_RGB_COLORS);
@ -201,13 +332,22 @@ static BOOL CURSORICON_GetIconInfoFromBMI(
if(compr != BI_RGB)
return FALSE;
/* If no dimensions were set, use the one from the icon */
if(!pdata->cx) pdata->cx = width;
if(!pdata->cy) pdata->cy = height < 0 ? -height/2 : height/2;
/* Fix the hotspot coords */
if(!pii->fIcon)
if(pdata->rt == (USHORT)((ULONG_PTR)RT_CURSOR))
{
if(cxDesired != pbmi->bmiHeader.biWidth)
pii->xHotspot = (pii->xHotspot * cxDesired) / pbmi->bmiHeader.biWidth;
if(cxDesired != (pbmi->bmiHeader.biHeight/2))
pii->yHotspot = (pii->yHotspot * cyDesired * 2) / pbmi->bmiHeader.biHeight;
if(pdata->cx != width)
pdata->xHotspot = (pdata->xHotspot * pdata->cx) / width;
if(pdata->cy != height/2)
pdata->yHotspot = (pdata->yHotspot * pdata->cy * 2) / height;
}
else
{
pdata->xHotspot = pdata->cx/2;
pdata->yHotspot = pdata->cy/2;
}
hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL);
@ -230,49 +370,52 @@ static BOOL CURSORICON_GetIconInfoFromBMI(
((BITMAPCOREHEADER*)&pbmiCopy->bmiHeader)->bcHeight /= 2;
else
pbmiCopy->bmiHeader.biHeight /= 2;
height /= 2;
pvColor = (const char*)pbmi + ubmiSize;
pvMask = (const char*)pvColor +
get_dib_image_size(pbmi->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight, pbmi->bmiHeader.biBitCount );
get_dib_image_size(width, height, bpp );
/* Set XOR bits */
if(monochrome)
{
/* Create the 1bpp bitmap which will contain everything */
pii->hbmColor = NULL;
pii->hbmMask = CreateCompatibleBitmap(hdc, cxDesired, cyDesired * 2);
if(!pii->hbmMask)
pdata->hbmColor = NULL;
pdata->hbmMask = CreateBitmap(pdata->cx, pdata->cy * 2, 1, 1, NULL);
if(!pdata->hbmMask)
goto done;
hbmpOld = SelectObject(hdc, pii->hbmMask);
hbmpOld = SelectObject(hdc, pdata->hbmMask);
if(!hbmpOld)
goto done;
if(!StretchDIBits(hdc, 0, cyDesired, cxDesired, cyDesired,
0, 0, pbmiCopy->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight,
if(!StretchDIBits(hdc, 0, pdata->cy, pdata->cx, pdata->cy,
0, 0, width, height,
pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
goto done;
pdata->bpp = 1;
}
else
{
/* Create the bitmap. It has to be compatible with the screen surface */
pii->hbmColor = CreateCompatibleBitmap(hdcScreen, cxDesired, cyDesired);
if(!pii->hbmColor)
pdata->hbmColor = CreateCompatibleBitmap(hdcScreen, pdata->cx, pdata->cy);
if(!pdata->hbmColor)
goto done;
/* Create the 1bpp mask bitmap */
pii->hbmMask = CreateCompatibleBitmap(hdc, cxDesired, cyDesired);
if(!pii->hbmMask)
pdata->hbmMask = CreateBitmap(pdata->cx, pdata->cy, 1, 1, NULL);
if(!pdata->hbmMask)
goto done;
hbmpOld = SelectObject(hdc, pii->hbmColor);
hbmpOld = SelectObject(hdc, pdata->hbmColor);
if(!hbmpOld)
goto done;
if(!StretchDIBits(hdc, 0, 0, cxDesired, cyDesired,
0, 0, pbmiCopy->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight,
if(!StretchDIBits(hdc, 0, 0, pdata->cx, pdata->cy,
0, 0, width, height,
pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
goto done;
pdata->bpp = GetDeviceCaps(hdcScreen, BITSPIXEL);
if(pdata->bpp == 32)
pdata->hbmAlpha = create_alpha_bitmap(pdata->hbmColor, pbmiCopy, pvColor);
/* Now convert the info to monochrome for the mask bits */
pbmiCopy->bmiHeader.biBitCount = 1;
/* Handle the CORE/INFO difference */
if (pbmiCopy->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
{
RGBQUAD *rgb = pbmiCopy->bmiColors;
@ -281,6 +424,7 @@ static BOOL CURSORICON_GetIconInfoFromBMI(
rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
pbmiCopy->bmiHeader.biBitCount = 1;
}
else
{
@ -288,14 +432,15 @@ static BOOL CURSORICON_GetIconInfoFromBMI(
rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
((BITMAPCOREHEADER*)&pbmiCopy->bmiHeader)->bcBitCount = 1;
}
}
/* Set the mask bits */
if(!SelectObject(hdc, pii->hbmMask))
if(!SelectObject(hdc, pdata->hbmMask))
goto done;
bResult = StretchDIBits(hdc, 0, 0, cxDesired, cyDesired,
0, 0, pbmiCopy->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight,
pvMask, pbmiCopy, DIB_RGB_COLORS, SRCCOPY) != 0;
bResult = StretchDIBits(hdc, 0, 0, pdata->cx, pdata->cy,
0, 0, width, height,
pvMask, pbmiCopy, DIB_RGB_COLORS, SRCCOPY) != 0;
done:
DeleteDC(hdcScreen);
@ -305,12 +450,65 @@ done:
/* Clean up in case of failure */
if(!bResult)
{
if(pii->hbmMask) DeleteObject(pii->hbmMask);
if(pii->hbmColor) DeleteObject(pii->hbmColor);
if(pdata->hbmMask) DeleteObject(pdata->hbmMask);
if(pdata->hbmColor) DeleteObject(pdata->hbmColor);
if(pdata->hbmAlpha) DeleteObject(pdata->hbmAlpha);
}
return bResult;
}
static BOOL CURSORICON_GetCursorDataFromIconInfo(
_Out_ CURSORDATA* pCursorData,
_In_ ICONINFO* pIconInfo
)
{
BITMAP bm;
ZeroMemory(pCursorData, sizeof(*pCursorData));
/* Use the CopyImage function, as it will gracefully convert our bitmap to the screen bit depth */
if(pIconInfo->hbmColor)
{
pCursorData->hbmColor = CopyImage(pIconInfo->hbmColor, IMAGE_BITMAP, 0, 0, 0);
if(!pCursorData->hbmColor)
return FALSE;
}
pCursorData->hbmMask = CopyImage(pIconInfo->hbmMask, IMAGE_BITMAP, 0, 0, LR_MONOCHROME);
if(!pCursorData->hbmMask)
return FALSE;
/* Now, fill some information */
pCursorData->rt = (USHORT)((ULONG_PTR)(pIconInfo->fIcon ? RT_ICON : RT_CURSOR));
if(pCursorData->hbmColor)
{
GetObject(pCursorData->hbmColor, sizeof(bm), &bm);
pCursorData->bpp = bm.bmBitsPixel;
pCursorData->cx = bm.bmWidth;
pCursorData->cy = bm.bmHeight;
if(pCursorData->bpp == 32)
pCursorData->hbmAlpha = create_alpha_bitmap(pCursorData->hbmColor, NULL, NULL);
}
else
{
GetObject(pCursorData->hbmMask, sizeof(bm), &bm);
pCursorData->bpp = 1;
pCursorData->cx = bm.bmWidth;
pCursorData->cy = bm.bmHeight/2;
}
if(pIconInfo->fIcon)
{
pCursorData->xHotspot = pCursorData->cx/2;
pCursorData->yHotspot = pCursorData->cy/2;
}
else
{
pCursorData->xHotspot = pIconInfo->xHotspot;
pCursorData->yHotspot = pIconInfo->yHotspot;
}
return TRUE;
}
static
HBITMAP
BITMAP_LoadImageW(
@ -324,14 +522,17 @@ BITMAP_LoadImageW(
const BITMAPINFO* pbmi;
BITMAPINFO* pbmiScaled = NULL;
BITMAPINFO* pbmiCopy = NULL;
const VOID* pvMapping;
const VOID* pvMapping = NULL;
DWORD dwOffset = 0;
HGLOBAL hgRsrc;
HGLOBAL hgRsrc = NULL;
int iBMISize;
PVOID pvBits;
HDC hdcScreen = NULL;
HDC hdc = NULL;
HBITMAP hbmpRet, hbmpOld;
HBITMAP hbmpOld, hbmpRet = NULL;
LONG width, height;
WORD bpp;
DWORD compr;
/* Map the bitmap info */
if(fuLoad & LR_LOADFROMFILE)
@ -371,7 +572,18 @@ BITMAP_LoadImageW(
return NULL;
}
/* See if we must scale the bitmap */
/* Fix up values */
if(DIB_GetBitmapInfo(&pbmi->bmiHeader, &width, &height, &bpp, &compr) == -1)
goto end;
if((width > 65535) || (height > 65535))
goto end;
if(cxDesired == 0)
cxDesired = width;
if(cyDesired == 0)
cyDesired = height;
else if(height < 0)
cyDesired = -cyDesired;
iBMISize = bitmap_info_size(pbmi, DIB_RGB_COLORS);
/* Get a pointer to the image data */
@ -492,35 +704,15 @@ create_bitmap:
if(pbmiScaled->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
BITMAPCOREHEADER* pbmch = (BITMAPCOREHEADER*)&pbmiScaled->bmiHeader;
if(cxDesired == 0)
cxDesired = pbmch->bcWidth;
if(cyDesired == 0)
cyDesired == pbmch->bcHeight;
else if(pbmch->bcHeight < 0)
cyDesired = -cyDesired;
pbmch->bcWidth = cxDesired;
pbmch->bcHeight = cyDesired;
}
else
{
if ((pbmi->bmiHeader.biHeight > 65535) || (pbmi->bmiHeader.biWidth > 65535)) {
WARN("Broken BITMAPINFO!\n");
goto end;
}
if(cxDesired == 0)
cxDesired = pbmi->bmiHeader.biWidth;
if(cyDesired == 0)
cyDesired = pbmi->bmiHeader.biHeight;
else if(pbmi->bmiHeader.biHeight < 0)
cyDesired = -cyDesired;
pbmiScaled->bmiHeader.biWidth = cxDesired;
pbmiScaled->bmiHeader.biHeight = cyDesired;
/* No compression for DIB sections */
if(fuLoad & LR_CREATEDIBSECTION)
pbmiScaled->bmiHeader.biCompression = BI_RGB;
pbmiScaled->bmiHeader.biCompression = BI_RGB;
}
}
@ -574,9 +766,9 @@ end:
HeapFree(GetProcessHeap(), 0, pbmiScaled);
if(pbmiCopy)
HeapFree(GetProcessHeap(), 0, pbmiCopy);
if (fuLoad & LR_LOADFROMFILE)
if (pvMapping)
UnmapViewOfFile( pvMapping );
else
if(hgRsrc)
FreeResource(hgRsrc);
return hbmpRet;
@ -621,9 +813,9 @@ CURSORICON_LoadFromFileW(
CURSORICONFILEDIR *dir;
DWORD filesize = 0;
LPBYTE bits;
HANDLE hRet = NULL;
HANDLE hCurIcon = NULL;
WORD i;
ICONINFO ii;
CURSORDATA cursorData;
TRACE("loading %s\n", debugstr_w( lpszName ));
@ -696,25 +888,42 @@ CURSORICON_LoadFromFileW(
/* Get our entry */
entry = &dir->idEntries[i-1];
/* Fix dimensions */
if(!cxDesired) cxDesired = entry->bWidth;
if(!cyDesired) cyDesired = entry->bHeight;
/* A bit of preparation */
ii.xHotspot = entry->xHotspot;
ii.yHotspot = entry->yHotspot;
ii.fIcon = bIcon;
ZeroMemory(&cursorData, sizeof(cursorData));
if(!bIcon)
{
cursorData.xHotspot = entry->xHotspot;
cursorData.yHotspot = entry->yHotspot;
}
cursorData.rt = (USHORT)((ULONG_PTR)(bIcon ? RT_ICON : RT_CURSOR));
/* Do the dance */
if(!CURSORICON_GetIconInfoFromBMI(&ii, (BITMAPINFO*)&bits[entry->dwDIBOffset], cxDesired, cyDesired))
if(!CURSORICON_GetCursorDataFromBMI(&cursorData, (BITMAPINFO*)&bits[entry->dwDIBOffset]))
goto end;
/* Create the icon. NOTE: there's no LR_SHARED icons if they are created from file */
hRet = CreateIconIndirect(&ii);
hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1);
if(!hCurIcon)
goto end_clean;
/* Tell win32k */
if(!NtUserSetCursorIconData(hCurIcon, NULL, NULL, &cursorData))
{
NtUserDestroyCursor(hCurIcon, TRUE);
hCurIcon = NULL;
}
/* Clean up */
DeleteObject(ii.hbmMask);
DeleteObject(ii.hbmColor);
end_clean:
DeleteObject(cursorData.hbmMask);
if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
end:
UnmapViewOfFile(bits);
return hRet;
return hCurIcon;
}
static
@ -733,7 +942,7 @@ CURSORICON_LoadImageW(
CURSORICONDIR* dir;
WORD wResId;
LPBYTE bits;
ICONINFO ii;
CURSORDATA cursorData;
BOOL bStatus;
UNICODE_STRING ustrRsrc;
UNICODE_STRING ustrModule = {0, 0, NULL};
@ -775,7 +984,7 @@ CURSORICON_LoadImageW(
/* Get it */
do
{
DWORD ret = GetModuleFileName(hinst, ustrModule.Buffer, size);
DWORD ret = GetModuleFileNameW(hinst, ustrModule.Buffer, size);
if(ret == 0)
{
HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
@ -783,8 +992,8 @@ CURSORICON_LoadImageW(
}
if(ret < size)
{
ustrModule.Length = ret;
ustrModule.MaximumLength = size;
ustrModule.Length = ret*sizeof(WCHAR);
ustrModule.MaximumLength = size*sizeof(WCHAR);
break;
}
size *= 2;
@ -845,27 +1054,24 @@ CURSORICON_LoadImageW(
goto done;
}
/* Get the hotspot */
if(bIcon)
{
ii.xHotspot = cxDesired/2;
ii.yHotspot = cyDesired/2;
}
if(!bIcon)
ZeroMemory(&cursorData, sizeof(cursorData));
if(dir->idType == 2)
{
/* idType == 2 for cursor resources */
SHORT* ptr = (SHORT*)bits;
ii.xHotspot = ptr[0];
ii.yHotspot = ptr[1];
cursorData.xHotspot = ptr[0];
cursorData.yHotspot = ptr[1];
bits += 2*sizeof(SHORT);
}
ii.fIcon = bIcon;
cursorData.cx = cxDesired;
cursorData.cy = cyDesired;
cursorData.rt = (USHORT)((ULONG_PTR)(bIcon ? RT_ICON : RT_CURSOR));
/* Get the bitmaps */
bStatus = CURSORICON_GetIconInfoFromBMI(
&ii,
(BITMAPINFO*)bits,
cxDesired,
cyDesired);
bStatus = CURSORICON_GetCursorDataFromBMI(
&cursorData,
(BITMAPINFO*)bits);
FreeResource( handle );
@ -876,16 +1082,17 @@ CURSORICON_LoadImageW(
hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1);
if(!hCurIcon)
{
DeleteObject(ii.hbmMask);
if(ii.hbmColor) DeleteObject(ii.hbmColor);
DeleteObject(cursorData.hbmMask);
if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
goto done;
}
/* Tell win32k */
if(fuLoad & LR_SHARED)
bStatus = NtUserSetCursorIconData(hCurIcon, &ustrModule, &ustrRsrc, &ii);
bStatus = NtUserSetCursorIconData(hCurIcon, &ustrModule, &ustrRsrc, &cursorData);
else
bStatus = NtUserSetCursorIconData(hCurIcon, NULL, NULL, &ii);
bStatus = NtUserSetCursorIconData(hCurIcon, NULL, NULL, &cursorData);
if(!bStatus)
{
@ -893,8 +1100,9 @@ CURSORICON_LoadImageW(
hCurIcon = NULL;
}
DeleteObject(ii.hbmMask);
if(ii.hbmColor) DeleteObject(ii.hbmColor);
DeleteObject(cursorData.hbmMask);
if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
done:
if(ustrModule.Buffer)
@ -905,10 +1113,10 @@ done:
static
HBITMAP
BITMAP_CopyImage(
_In_ HBITMAP hbmp,
_In_ int cxDesired,
_In_ int cyDesired,
_In_ UINT fuFlags
_In_ HBITMAP hnd,
_In_ int desiredx,
_In_ int desiredy,
_In_ UINT flags
)
{
HBITMAP res = NULL;
@ -916,22 +1124,22 @@ BITMAP_CopyImage(
int objSize;
BITMAPINFO * bi;
objSize = GetObjectW( hbmp, sizeof(ds), &ds );
objSize = GetObjectW( hnd, sizeof(ds), &ds );
if (!objSize) return 0;
if ((cxDesired < 0) || (cyDesired < 0)) return 0;
if ((desiredx < 0) || (desiredy < 0)) return 0;
if (fuFlags & LR_COPYFROMRESOURCE)
if (flags & LR_COPYFROMRESOURCE)
{
FIXME("The flag LR_COPYFROMRESOURCE is not implemented for bitmaps\n");
}
if (fuFlags & LR_COPYRETURNORG)
if (flags & LR_COPYRETURNORG)
{
FIXME("The flag LR_COPYRETURNORG is not implemented for bitmaps\n");
}
if (cxDesired == 0) cxDesired = ds.dsBm.bmWidth;
if (cyDesired == 0) cyDesired = ds.dsBm.bmHeight;
if (desiredx == 0) desiredx = ds.dsBm.bmWidth;
if (desiredy == 0) desiredy = ds.dsBm.bmHeight;
/* Allocate memory for a BITMAPINFOHEADER structure and a
color table. The maximum number of colors in a color table
@ -945,7 +1153,7 @@ BITMAP_CopyImage(
bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel;
bi->bmiHeader.biCompression = BI_RGB;
if (fuFlags & LR_CREATEDIBSECTION)
if (flags & LR_CREATEDIBSECTION)
{
/* Create a DIB section. LR_MONOCHROME is ignored */
void * bits;
@ -958,12 +1166,11 @@ BITMAP_CopyImage(
memcpy(bi, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
}
/* Get the color table or the color masks */
GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
bi->bmiHeader.biWidth = desiredx;
bi->bmiHeader.biHeight = desiredy;
bi->bmiHeader.biWidth = cxDesired;
bi->bmiHeader.biHeight = cyDesired;
bi->bmiHeader.biSizeImage = 0;
/* Get the color table or the color masks */
GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
res = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
DeleteDC(dc);
@ -972,16 +1179,16 @@ BITMAP_CopyImage(
{
/* Create a device-dependent bitmap */
BOOL monochrome = (fuFlags & LR_MONOCHROME);
BOOL monochrome = (flags & LR_MONOCHROME);
if (objSize == sizeof(DIBSECTION))
{
/* The source bitmap is a DIB section.
Get its attributes */
HDC dc = CreateCompatibleDC(NULL);
bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel;
GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
bi->bmiHeader.biWidth = ds.dsBm.bmWidth;
bi->bmiHeader.biHeight = ds.dsBm.bmHeight;
GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
DeleteDC(dc);
if (!monochrome && ds.dsBm.bmBitsPixel == 1)
@ -1015,12 +1222,12 @@ BITMAP_CopyImage(
if (monochrome)
{
res = CreateBitmap(cxDesired, cyDesired, 1, 1, NULL);
res = CreateBitmap(desiredx, desiredy, 1, 1, NULL);
}
else
{
HDC screenDC = GetDC(NULL);
res = CreateCompatibleBitmap(screenDC, cxDesired, cyDesired);
res = CreateCompatibleBitmap(screenDC, desiredx, desiredy);
ReleaseDC(NULL, screenDC);
}
}
@ -1061,7 +1268,7 @@ BITMAP_CopyImage(
bi->bmiHeader.biClrImportant = 0;
/* Fill in biSizeImage */
GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bi->bmiHeader.biSizeImage);
if (bits)
@ -1069,11 +1276,11 @@ BITMAP_CopyImage(
HBITMAP oldBmp;
/* Get the image bits of the source bitmap */
GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, bits, bi, DIB_RGB_COLORS);
GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, bits, bi, DIB_RGB_COLORS);
/* Copy it to the destination bitmap */
oldBmp = SelectObject(dc, res);
StretchDIBits(dc, 0, 0, cxDesired, cyDesired,
StretchDIBits(dc, 0, 0, desiredx, desiredy,
0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight,
bits, bi, DIB_RGB_COLORS, SRCCOPY);
SelectObject(dc, oldBmp);
@ -1084,9 +1291,9 @@ BITMAP_CopyImage(
DeleteDC(dc);
}
if (fuFlags & LR_COPYDELETEORG)
if (flags & LR_COPYDELETEORG)
{
DeleteObject(hbmp);
DeleteObject(hnd);
}
}
HeapFree(GetProcessHeap(), 0, bi);
@ -1114,17 +1321,17 @@ CURSORICON_CopyImage(
PVOID pvBuf;
HMODULE hModule;
ustrModule.MaximumLength = MAX_PATH;
ustrModule.MaximumLength = MAX_PATH * sizeof(WCHAR);
ustrRsrc.MaximumLength = 256;
ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrModule.MaximumLength * sizeof(WCHAR));
ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrModule.MaximumLength);
if(!ustrModule.Buffer)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
/* Keep track of the buffer for the resource, NtUserGetIconInfo might overwrite it */
pvBuf = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(WCHAR));
pvBuf = HeapAlloc(GetProcessHeap(), 0, ustrRsrc.MaximumLength);
if(!pvBuf)
{
HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
@ -1153,7 +1360,7 @@ CURSORICON_CopyImage(
{
PWSTR newBuffer;
ustrModule.MaximumLength *= 2;
newBuffer = HeapReAlloc(GetProcessHeap(), 0, ustrModule.Buffer, ustrModule.MaximumLength * sizeof(WCHAR));
newBuffer = HeapReAlloc(GetProcessHeap(), 0, ustrModule.Buffer, ustrModule.MaximumLength);
if(!ustrModule.Buffer)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
@ -1165,7 +1372,7 @@ CURSORICON_CopyImage(
if(ustrRsrc.Length == ustrRsrc.MaximumLength)
{
ustrRsrc.MaximumLength *= 2;
pvBuf = HeapReAlloc(GetProcessHeap(), 0, ustrRsrc.Buffer, ustrRsrc.MaximumLength * sizeof(WCHAR));
pvBuf = HeapReAlloc(GetProcessHeap(), 0, ustrRsrc.Buffer, ustrRsrc.MaximumLength);
if(!pvBuf)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
@ -1176,14 +1383,15 @@ CURSORICON_CopyImage(
} while(TRUE);
/* NULL-terminate our strings */
ustrModule.Buffer[ustrModule.Length] = 0;
ustrModule.Buffer[ustrModule.Length/sizeof(WCHAR)] = 0;
if(!IS_INTRESOURCE(ustrRsrc.Buffer))
ustrRsrc.Buffer[ustrRsrc.Length] = 0;
ustrRsrc.Buffer[ustrRsrc.Length/sizeof(WCHAR)] = 0;
/* Get the module handle */
if(!GetModuleHandleExW(0, ustrModule.Buffer, &hModule))
{
/* This hould never happen */
ERR("Invalid handle?.\n");
SetLastError(ERROR_INVALID_PARAMETER);
goto leave;
}
@ -1198,6 +1406,8 @@ CURSORICON_CopyImage(
HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
HeapFree(GetProcessHeap(), 0, pvBuf);
TRACE("Returning 0x%08x.\n", ret);
return ret;
}
@ -1499,21 +1709,6 @@ int WINAPI LookupIconIdFromDirectoryEx(
return 0;
}
/* idType == 2 is for cursors, 1 for icons */
/*if(fIcon)
{
if(dir->idType == 2)
{
WARN("An icon was asked for a cursor resource.\n");
return 0;
}
}
else if(dir->idType == 1)
{
WARN("A cursor was asked for an icon resource.\n");
return 0;
}*/
if(Flags & LR_MONOCHROME)
bppDesired = 1;
else
@ -1526,6 +1721,11 @@ int WINAPI LookupIconIdFromDirectoryEx(
bppDesired = GetDeviceCaps(icScreen, BITSPIXEL);
DeleteDC(icScreen);
}
if(!cxDesired)
cxDesired = GetSystemMetrics(fIcon ? SM_CXICON : SM_CXCURSOR);
if(!cyDesired)
cyDesired = GetSystemMetrics(fIcon ? SM_CYICON : SM_CYCURSOR);
/* Find the best match for the desired size */
cxyDiff = 0xFFFFFFFF;
@ -1658,7 +1858,7 @@ HICON WINAPI CreateIconFromResource(
_In_ DWORD dwVer
)
{
return CreateIconFromResourceEx( presbits, dwResSize, fIcon, dwVer, 0,0,0);
return CreateIconFromResourceEx( presbits, dwResSize, fIcon, dwVer, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
}
HICON WINAPI CreateIconFromResourceEx(
@ -1671,34 +1871,60 @@ HICON WINAPI CreateIconFromResourceEx(
_In_ UINT uFlags
)
{
ICONINFO ii;
CURSORDATA cursorData;
HICON hIcon;
if(uFlags)
FIXME("uFlags 0x%08x ignored.\n", uFlags);
TRACE("%p, %lu, %lu, %lu, %i, %i, %lu.\n", pbIconBits, cbIconBits, fIcon, dwVersion, cxDesired, cyDesired, uFlags);
if(fIcon)
if(uFlags & ~LR_DEFAULTSIZE)
FIXME("uFlags 0x%08x ignored.\n", uFlags & ~LR_DEFAULTSIZE);
if(uFlags & LR_DEFAULTSIZE)
{
ii.xHotspot = cxDesired/2;
ii.yHotspot = cyDesired/2;
if(!cxDesired) cxDesired = GetSystemMetrics(fIcon ? SM_CXICON : SM_CXCURSOR);
if(!cyDesired) cyDesired = GetSystemMetrics(fIcon ? SM_CYICON : SM_CYCURSOR);
}
else
/* Check if this is an animated cursor */
if(!memcmp(pbIconBits, "RIFF", 4))
{
UNIMPLEMENTED;
return NULL;
}
ZeroMemory(&cursorData, sizeof(cursorData));
cursorData.cx = cxDesired;
cursorData.cy = cyDesired;
cursorData.rt = (USHORT)((ULONG_PTR)(fIcon ? RT_ICON : RT_CURSOR));
if(!fIcon)
{
WORD* pt = (WORD*)pbIconBits;
ii.xHotspot = *pt++;
ii.yHotspot = *pt++;
cursorData.xHotspot = *pt++;
cursorData.yHotspot = *pt++;
pbIconBits = (PBYTE)pt;
}
ii.fIcon = fIcon;
if(!CURSORICON_GetIconInfoFromBMI(&ii, (BITMAPINFO*)pbIconBits, cxDesired, cyDesired))
if(!CURSORICON_GetCursorDataFromBMI(&cursorData, (BITMAPINFO*)pbIconBits))
{
ERR("Couldn't fill the CURSORDATA structure.\n");
return NULL;
}
hIcon = NtUserxCreateEmptyCurObject(fIcon ? 0 : 1);
if(!hIcon)
return NULL;
hIcon = CreateIconIndirect(&ii);
if(!NtUserSetCursorIconData(hIcon, NULL, NULL, &cursorData))
{
ERR("NtUserSetCursorIconData failed.\n");
NtUserDestroyCursor(hIcon, TRUE);
hIcon = NULL;
}
/* Clean up */
DeleteObject(ii.hbmMask);
if(ii.hbmColor) DeleteObject(ii.hbmColor);
DeleteObject(cursorData.hbmMask);
if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
return hIcon;
}
@ -1709,19 +1935,28 @@ HICON WINAPI CreateIconIndirect(
{
/* As simple as creating a handle, and let win32k deal with the bitmaps */
HICON hiconRet;
CURSORDATA cursorData;
TRACE("%p.\n", piconinfo);
if(!CURSORICON_GetCursorDataFromIconInfo(&cursorData, piconinfo))
return NULL;
hiconRet = NtUserxCreateEmptyCurObject(piconinfo->fIcon ? 0 : 1);
if(!hiconRet)
return NULL;
if(!NtUserSetCursorIconData(hiconRet, NULL, NULL, piconinfo))
if(!NtUserSetCursorIconData(hiconRet, NULL, NULL, &cursorData))
{
NtUserDestroyCursor(hiconRet, FALSE);
hiconRet = NULL;
}
/* Clean up */
DeleteObject(cursorData.hbmMask);
if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
TRACE("Returning 0x%08x.\n", hiconRet);
return hiconRet;
@ -1768,8 +2003,7 @@ BOOL WINAPI SetCursorPos(
_In_ int Y
)
{
UNIMPLEMENTED;
return FALSE;
return NtUserxSetCursorPos(X,Y);
}
BOOL WINAPI GetCursorPos(
@ -1783,14 +2017,12 @@ int WINAPI ShowCursor(
_In_ BOOL bShow
)
{
UNIMPLEMENTED;
return -1;
return NtUserxShowCursor(bShow);
}
HCURSOR WINAPI GetCursor(void)
{
UNIMPLEMENTED;
return NULL;
return (HCURSOR)NtUserGetThreadState(THREADSTATE_GETCURSOR);
}
BOOL WINAPI DestroyCursor(

View file

@ -380,8 +380,11 @@ SVC_(UserEnumDisplaySettings, 4)
SVC_(UserEvent, 1)
SVC_(UserExcludeUpdateRgn, 2)
SVC_(UserFillWindow, 4)
// SVC_(UserFindExistingCursorIcon, 3, Wrong, number, of, param, ?)
#ifdef NEW_CURSORICON
SVC_(UserFindExistingCursorIcon, 3)
#else
SVC_(UserFindExistingCursorIcon, 4)
#endif
SVC_(UserFindWindowEx, 5)
SVC_(UserFlashWindowEx, 1)
SVC_(UserGetAltTabInfo, 6)