mirror of
https://github.com/reactos/reactos.git
synced 2025-04-19 04:07:16 +00:00
[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:
parent
5ad72c9145
commit
bd515ad606
6 changed files with 592 additions and 469 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(¶mSafe, 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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue