windows-nt/Source/XPSP1/NT/base/mvdm/wow32/wcuricon.c
2020-09-26 16:20:57 +08:00

1161 lines
32 KiB
C

//*****************************************************************************
//
// Cursor and Icon compatibility Support -
//
// Support for apps - which do a GlobalLock on Cursors and Icons to
// create headaches for us.
//
// A compatibility issue.
//
//
// 21-Apr-92 NanduriR Created.
//
//*****************************************************************************
#include "precomp.h"
#pragma hdrstop
MODNAME(wcuricon.c);
extern void FreeAccelAliasEntry(LPACCELALIAS lpT);
LPCURSORICONALIAS lpCIAlias = NULL;
UINT cPendingCursorIconUpdates = 0;
//*****************************************************************************
//
// W32CreateCursorIcon32 -
//
// Creates a 32bit Cursor or Icon given a WIN31 Cursor or Icon HANDLE.
// The Cursor of Icon handle must correspond to an object that has
// been created (like CreateIcon). That is because the format of a
// resource cursor differs from that of a 'created' cursor.
//
// Returns the 32bit handle
//
//*****************************************************************************
HANDLE W32CreateCursorIcon32(LPCURSORICONALIAS lpCIAliasIn)
{
HANDLE hT;
PCURSORSHAPE16 pcurs16;
UINT flType;
int nWidth;
int nHeight;
int nPlanes;
int nBitsPixel;
DWORD nBytesAND;
LPBYTE lpBitsAND;
LPBYTE lpBitsXOR;
int ScanLen16;
pcurs16 = (PCURSORSHAPE16)lpCIAliasIn->pbDataNew;
flType = lpCIAliasIn->flType;
if (flType & HANDLE_TYPE_UNKNOWN) {
if (PROBABLYCURSOR(FETCHWORD(pcurs16->BitsPixel),
FETCHWORD(pcurs16->Planes)))
flType = HANDLE_TYPE_CURSOR;
else
flType = HANDLE_TYPE_ICON;
}
nWidth = INT32(FETCHWORD(pcurs16->cx));
nHeight = INT32(FETCHWORD(pcurs16->cy));
nPlanes = 1;
nBitsPixel = 1; // Monochrome
// Get the AND mask bits
ScanLen16 = (((nWidth*nBitsPixel)+15)/16) * 2 ; // bytes/scan in 16 bit world
// effectively nBitsPixel is 1
nBytesAND = ScanLen16*nHeight*nPlanes;
lpBitsAND = (LPBYTE)pcurs16 + sizeof(CURSORSHAPE16);
// Get the XOR mask bits
if (flType == HANDLE_TYPE_ICON) {
nPlanes = INT32(FETCHWORD(pcurs16->Planes));
nBitsPixel = INT32(FETCHWORD(pcurs16->BitsPixel)); // the actual value
}
lpBitsXOR = (LPBYTE)lpBitsAND + nBytesAND;
lpCIAliasIn->flType = (BYTE)flType;
if (flType & HANDLE_TYPE_CURSOR) {
hT = CreateCursor(HMODINST32(lpCIAliasIn->hInst16),
(INT)FETCHWORD(pcurs16->xHotSpot),
(INT)FETCHWORD(pcurs16->yHotSpot),
nWidth, nHeight, lpBitsAND, lpBitsXOR);
}
else if (flType & HANDLE_TYPE_ICON) {
hT = CreateIcon(HMODINST32(lpCIAliasIn->hInst16), nWidth, nHeight,
(BYTE)nPlanes, (BYTE)nBitsPixel, lpBitsAND, lpBitsXOR);
}
return hT;
}
//*****************************************************************************
//
// W32Create16BitCursorIcon -
//
// Creates a WIN31 compatible Cursor or Icon given the full 16bit
// definition of the object to be created.
//
//
//*****************************************************************************
HAND16 W32Create16BitCursorIcon(HAND16 hInst16, INT xHotSpot, INT yHotSpot,
INT nWidth, INT nHeight,
INT nPlanes, INT nBitsPixel,
LPBYTE lpBitsAND, LPBYTE lpBitsXOR,
INT nBytesAND, INT nBytesXOR )
{
WORD h16 = 0;
WORD wTotalSize;
PCURSORSHAPE16 pcshape16;
VPVOID vp;
LPBYTE lpT;
UNREFERENCED_PARAMETER(hInst16);
wTotalSize = (WORD)(sizeof(CURSORSHAPE16) + nBytesAND + nBytesXOR);
vp = GlobalAllocLock16(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE,
wTotalSize, &h16);
if (vp != (VPVOID)NULL) {
GETVDMPTR(vp, wTotalSize, pcshape16);
STOREWORD(pcshape16->xHotSpot, xHotSpot);
STOREWORD(pcshape16->yHotSpot, yHotSpot);
STOREWORD(pcshape16->cx, nWidth);
STOREWORD(pcshape16->cy, nHeight);
STOREWORD(pcshape16->cbWidth, (((nWidth + 0x0F) & ~0x0F) >> 3));
pcshape16->Planes = (BYTE)nPlanes;
pcshape16->BitsPixel = (BYTE)nBitsPixel;
lpT = (LPBYTE)pcshape16 + sizeof(CURSORSHAPE16);
RtlCopyMemory(lpT, lpBitsAND, nBytesAND);
RtlCopyMemory(lpT+nBytesAND, lpBitsXOR, nBytesXOR);
FLUSHVDMPTR(vp, wTotalSize, pcshape16);
FREEVDMPTR(pcshape16);
}
GlobalUnlock16(h16);
return (HAND16)h16;
}
//*****************************************************************************
//
// GetCursorIconAlias32 -
//
// Returns a 32bit handle given a 16bit Cursor or Icon HANDLE
// Creates the 32bit Cursor or Icon if necessary.
//
// Returns the 32bit handle
//
//*****************************************************************************
HANDLE GetCursorIconAlias32(HAND16 h16, UINT flType)
{
LPCURSORICONALIAS lpT;
VPVOID vp;
UINT cb;
PCURSORSHAPE16 pcurs16;
if (h16 == (HAND16)0)
return (ULONG)NULL;
lpT = FindCursorIconAlias((ULONG)h16, HANDLE_16BIT);
if (lpT) {
return lpT->h32;
}
else {
//
// BEGIN: Check for Bogus handle
//
if (BOGUSHANDLE(h16))
return (HANDLE)NULL;
#if defined(FE_SB)
//In Excel95, XLVISEX.EXE use wrong cursor handle
//that is already freed. So, we double check this handle
//whether it is valid or not. 09/27/96 bklee.
if (!FindCursorIconAliasInUse((ULONG)h16))
return (HANDLE)NULL;
#endif
vp = RealLockResource16(h16, (PINT)&cb);
if (vp == (VPVOID)NULL)
return (ULONG)NULL;
GETVDMPTR(vp, cb, pcurs16);
if (pcurs16->cbWidth != (SHORT)(((pcurs16->cx + 0x0f) & ~0x0f) >> 3))
return (ULONG)NULL;
//
// END: Check for Bogus handle
//
lpT = AllocCursorIconAlias();
if (!lpT) {
return (ULONG)NULL;
}
lpT->h16 = h16;
lpT->hTask16 = CURRENTPTD()->htask16;
lpT->vpData = vp;
lpT->cbData = (WORD)cb;
lpT->pbDataNew = (LPBYTE)pcurs16;
lpT->pbDataOld = malloc_w(cb);
if (lpT->pbDataOld) {
RtlCopyMemory(lpT->pbDataOld, lpT->pbDataNew, cb);
}
lpT->h32 = (HAND32)W32CreateCursorIcon32(lpT);
GlobalUnlock16(h16);
FREEVDMPTR(pcurs16);
lpT->pbDataNew = (LPBYTE)NULL;
if (lpT->h32) {
lpT->fInUse = TRUE;
SetCursorIconFlag(h16, TRUE);
}
else
lpT->fInUse = FALSE;
return lpT->h32;
}
}
//*****************************************************************************
//
// GetCursorIconAlias16 -
//
// Returns a 16bit handle given a 32bit Cursor or Icon HANDLE
// Creates the 16bit Cursor or Icon if necessary.
//
// Returns the 16bit handle
//
//*****************************************************************************
HAND16 GetCursorIconAlias16(HAND32 h32, UINT flType)
{
LPCURSORICONALIAS lpT;
if (h32 == (HAND32)0)
return (HAND16)NULL;
lpT = FindCursorIconAlias((ULONG)h32, HANDLE_32BIT);
if (lpT) {
return lpT->h16;
}
else {
HAND16 h16;
// HACK:
// From experience: numeric values of 32bit standard cursors and icons
// are very small. so check for these handles.
// we should not create aliases for standard cursors and
// icons here.
WOW32ASSERT((UINT)h32 >= 100);
//
// Always generate valid handles.
//
h16 = W32Create16BitCursorIconFrom32BitHandle(h32, (HAND16)NULL,
(PUINT)NULL);
if (h16) {
h16 = SetupCursorIconAlias((HAND16)NULL, h32, h16, flType,
NULL, (WORD)NULL);
}
return h16;
}
}
//*****************************************************************************
//
// AllocCursorIconAlias -
//
// Allocates and reurns pointer to CURSORICONALIAS buffer.
//
//*****************************************************************************
LPCURSORICONALIAS AllocCursorIconAlias()
{
LPCURSORICONALIAS lpT;
for (lpT = lpCIAlias; lpT != NULL; lpT = lpT->lpNext) {
if (!lpT->fInUse)
break;
}
if (lpT == NULL) {
lpT = (LPCURSORICONALIAS)malloc_w_small(sizeof(CURSORICONALIAS));
if (lpT) {
lpT->lpNext = lpCIAlias;
lpCIAlias = lpT;
}
else {
LOGDEBUG(0, ("AllocCursorIconAlias: malloc_w_small for alias failed\n"));
}
}
if (lpT != NULL) {
lpT->fInUse = TRUE;
lpT->h16 = (HAND16)0;
lpT->h32 = (HAND32)0;
lpT->vpData = (VPVOID)NULL;
lpT->cLock = 0;
lpT->cbData = 0;
lpT->pbDataOld = (LPBYTE)NULL;
lpT->pbDataNew = (LPBYTE)NULL;
lpT->lpszName = (LPBYTE)NULL;
lpT->flType = HANDLE_TYPE_UNKNOWN;
lpT->hInst16 = (HAND16)0;
lpT->hMod16 = (HAND16)0;
lpT->hTask16 = (HTASK16)0;
lpT->hRes16 = 0;
}
return lpT;
}
//*****************************************************************************
//
// FindCursorIconAlias -
//
// Searches for the given handle and returns corresponding
// LPCURSORICONALIAS.
//
//*****************************************************************************
LPCURSORICONALIAS FindCursorIconAlias(ULONG hCI, UINT flHandleSize)
{
LPCURSORICONALIAS lpT;
LPCURSORICONALIAS lpTprev;
lpTprev = (LPCURSORICONALIAS)NULL;
for (lpT = lpCIAlias; lpT != NULL; lpTprev = lpT, lpT = lpT->lpNext) {
if (lpT->fInUse) {
if ((flHandleSize == HANDLE_16BIT && lpT->h16 == (HAND16)hCI) ||
(flHandleSize == HANDLE_32BIT && lpT->h32 == (HAND32)hCI))
break;
else if (flHandleSize == HANDLE_16BITRES && lpT->hRes16 &&
(lpT->hRes16 == (HAND16)hCI))
break;
}
}
if (lpT) {
if (lpTprev) {
lpTprev->lpNext = lpT->lpNext;
lpT->lpNext = lpCIAlias;
lpCIAlias = lpT;
}
}
return lpT;
}
#if defined(FE_SB)
//*****************************************************************************
//
// FindCursorIconAliasInUse -
//
// Searches for the given handle and returns corresponding
// lpT->fInUse.
//
// 09/27/96 bklee
//*****************************************************************************
BOOL FindCursorIconAliasInUse(ULONG hCI)
{
LPCURSORICONALIAS lpT;
LPCURSORICONALIAS lpTprev;
lpTprev = (LPCURSORICONALIAS)NULL;
for (lpT = lpCIAlias; lpT != NULL; lpTprev = lpT, lpT = lpT->lpNext) {
if (lpT->h16 == (HAND16)hCI)
return lpT->fInUse;
}
return TRUE;
}
#endif
//*****************************************************************************
//
// DeleteCursorIconAlias -
//
// Searches for the given handle and if a 16bit handle frees the memory
// allocated for the Object. The alias table is not freed.
//
//*****************************************************************************
BOOL DeleteCursorIconAlias(ULONG hCI, UINT flHandleSize)
{
LPCURSORICONALIAS lpT;
WOW32ASSERT(flHandleSize == HANDLE_16BIT);
for (lpT = lpCIAlias; lpT != NULL; lpT = lpT->lpNext) {
if (lpT->fInUse && !(lpT->flType & HANDLE_TYPE_WOWGLOBAL)) {
// Have we found the handle mapping?
if (flHandleSize == HANDLE_16BIT && lpT->h16 == (HAND16)hCI) {
if (lpT->hTask16) {
// We don't want to free the handle mapping when
// the handle corresponds to a 16-bit resource, i.e.
// hRes16 is non-null.
if (!(lpT->hRes16)) {
SetCursorIconFlag(lpT->h16, FALSE);
GlobalUnlockFree16(RealLockResource16((HMEM16)hCI, NULL));
free_w(lpT->pbDataOld);
lpT->fInUse = FALSE;
return TRUE;
}
}
else {
WOW32ASSERT(FALSE);
}
break;
}
}
}
return FALSE;
}
//*****************************************************************************
//
// FreeCursorIconAlias -
//
// Frees all Cursors and Icons of the specified task.
//
//
//*****************************************************************************
BOOL FreeCursorIconAlias(HAND16 hand16, ULONG ulFlags)
{
LPCURSORICONALIAS lpT;
for (lpT = lpCIAlias; lpT != NULL; lpT = lpT->lpNext) {
if (lpT->fInUse &&
(((ulFlags & CIALIAS_HMOD) && (lpT->hMod16 == hand16)) ||
((ulFlags & CIALIAS_HTASK) && (lpT->hTask16 == hand16)))) {
if (ulFlags & CIALIAS_TASKISGONE) {
// We're here if this function is called after the task
// cleanup on the 16bit side... then we really can't
// callback. Setting appropriate fields to NULL will
// avoid callbacks, but will leak the corresponding
// memory. The asserts will catch this on a checked
// build.
WOW32ASSERT(lpT->h16==(HAND16)NULL);
WOW32ASSERT(lpT->hRes16==(HAND16)NULL);
lpT->h16 = (HAND16)NULL;
lpT->hRes16 = (HAND16)NULL;
}
InvalidateCursorIconAlias(lpT);
}
}
return TRUE;
}
//*****************************************************************************
//
// SetupCursorIconAlias -
//
// Sets up association (alias) between a 32bit and a 16bit handle.
// given both the handles.
//
//
//*****************************************************************************
HAND16 SetupCursorIconAlias(HAND16 hInst16, HAND32 h32, HAND16 h16, UINT flType,
LPBYTE lpResName, WORD hRes16)
{
LPCURSORICONALIAS lpT;
VPVOID vp;
INT cb;
lpT = AllocCursorIconAlias();
// paranoid check for memory exaust
if (!lpT) {
return (HAND16)NULL;
}
lpT->fInUse = TRUE;
lpT->h16 = h16;
lpT->h32 = h32;
lpT->flType = (BYTE)flType;
if (!(flType & HANDLE_TYPE_WOWGLOBAL)) {
lpT->hInst16 = hInst16;
lpT->hMod16 = GETHMOD16(HMODINST32(hInst16));
lpT->hTask16 = CURRENTPTD()->htask16;
lpT->hRes16 = hRes16;
vp = RealLockResource16(h16, &cb);
if (vp == (VPVOID)NULL)
return (HAND16)NULL;
lpT->vpData = vp;
lpT->cbData = (WORD)cb;
GETVDMPTR(vp, cb, lpT->pbDataNew);
lpT->pbDataOld = malloc_w(cb);
if (lpT->pbDataOld) {
RtlCopyMemory(lpT->pbDataOld, lpT->pbDataNew, cb);
}
if (hRes16) {
lpT->lpszName = lpResName;
if ((WORD)HIWORD(lpResName) != (WORD)NULL) {
UINT cb;
cb = strlen(lpResName)+1;
if (lpT->lpszName = malloc_w_small(cb)) {
memcpy (lpT->lpszName, lpResName, cb);
}
}
}
}
// the alias has been setup. Now turn on the GAH_CURSORICON flag.
SetCursorIconFlag(h16, TRUE);
return h16;
}
//*****************************************************************************
//
// SetupResCursorIconAlias -
//
// Sets up association (alias) between a 32bit and a 16bit handle.
// given the 32bit handle and a handle to a 16bit resource.
//
//
//*****************************************************************************
HAND16 SetupResCursorIconAlias(HAND16 hInst16, HAND32 h32, LPBYTE lpResName, WORD hRes16, UINT flType)
{
LPCURSORICONALIAS lpT;
HAND16 h16 = 0;
HAND16 h16Res = 0;
UINT cb;
if (hRes16) {
// 16bit resource has been loaded. We always want to return the
// SAME 16bit handle no matter howmany times the 'LoadIcon' or
// LoadCursor has been called.
h16Res = LOWORD(hRes16);
lpT = FindCursorIconAlias(h16Res, HANDLE_16BITRES);
}
else {
// Resource handle is NULL. The Resource must have been a
// standard predefined resource like ARROW etc.
lpT = FindCursorIconAlias((ULONG)h32, HANDLE_32BIT);
flType |= HANDLE_TYPE_WOWGLOBAL;
}
if (lpT == NULL) {
h16 = W32Create16BitCursorIconFrom32BitHandle(h32, hInst16, &cb);
h16 = SetupCursorIconAlias(hInst16, h32, h16, flType, lpResName, hRes16);
}
else {
if (lpT->flType & HANDLE_TYPE_WOWGLOBAL) {
// eachtime we should get the same h32 from usersrv.
//
WOW32ASSERT(lpT->h32 == h32);
}
else {
if (lpT->h32 != h32) {
if (lpT->flType == HANDLE_TYPE_CURSOR)
DestroyCursor(h32);
else
DestroyIcon(h32);
}
ReplaceCursorIcon(lpT);
}
h16 = lpT->h16;
}
return h16;
}
//*****************************************************************************
//
// SetCursorIconFlag -
//
// Sets/Clears the GAH_CURSORICONFLAG in the global arean header. This flag
// is used to identify Cursors and Icon when they are GlobaLocked and
// GlobalUnlocked
//
//*****************************************************************************
ULONG SetCursorIconFlag(HAND16 h16, BOOL fSet)
{
PARM16 Parm16;
VPVOID vp = 0;
Parm16.WndProc.wParam = h16;
Parm16.WndProc.wMsg = (WORD)fSet;
CallBack16(RET_SETCURSORICONFLAG, &Parm16, 0, &vp);
return (ULONG)0;
}
//*****************************************************************************
//
// UpdateCursorIcon -
//
// Compares the new object data with the old. If any of the bytes differ
// the old object is replaced with the new.
//
//*****************************************************************************
VOID UpdateCursorIcon()
{
LPCURSORICONALIAS lpT;
UINT cbData;
LPBYTE lpBitsNew, lpBitsOld;
UINT i = 0;
for (lpT = lpCIAlias; lpT != NULL ; lpT = lpT->lpNext) {
if (lpT->fInUse && lpT->cLock) {
GETVDMPTR(lpT->vpData, lpT->cbData, lpT->pbDataNew);
if (lpT->hRes16) {
if (lpT->flType == HANDLE_TYPE_ICON) {
lpBitsNew = lpT->pbDataNew + sizeof(BITMAPINFOHEADER16);
lpBitsOld = lpT->pbDataOld + sizeof(BITMAPINFOHEADER16);
cbData = lpT->cbData - sizeof(BITMAPINFOHEADER16);
}
else {
lpBitsNew = lpT->pbDataNew + sizeof(CURSORRESOURCE16);
lpBitsOld = lpT->pbDataOld + sizeof(CURSORRESOURCE16);
cbData = lpT->cbData - sizeof(CURSORRESOURCE16);
}
}
else {
lpBitsNew = lpT->pbDataNew + sizeof(CURSORSHAPE16);
lpBitsOld = lpT->pbDataOld + sizeof(CURSORSHAPE16);
cbData = lpT->cbData - sizeof(CURSORSHAPE16);
}
if (! RtlEqualMemory(lpBitsNew, lpBitsOld, cbData))
ReplaceCursorIcon(lpT);
if (cPendingCursorIconUpdates == ++i)
break;
}
}
}
//*****************************************************************************
//
// ReplaceCursorIcon -
//
// Updates the current cursor or icon. Creates a new icon or cursor and
// replaces the contents of the old handle with that of the new.
//
// returns TRUE for success.
//
//*****************************************************************************
BOOL ReplaceCursorIcon(LPCURSORICONALIAS lpIn)
{
HANDLE hT32;
if (lpIn != NULL) {
// Get the data
GETVDMPTR(lpIn->vpData, lpIn->cbData, lpIn->pbDataNew);
// Create the object
hT32 = (HAND32)W32CreateCursorIcon32(lpIn);
// SetCursorConents will replace the contents of OLD cursor/icon
// with that of the new handle and destroy the new handle
SetCursorContents(lpIn->h32, hT32);
// replace the old object data with the new
RtlCopyMemory(lpIn->pbDataOld, lpIn->pbDataNew, lpIn->cbData);
FREEVDMPTR(lpIn->pbDataNew);
lpIn->pbDataNew = (LPBYTE)NULL;
}
return (BOOL)TRUE;
}
//*****************************************************************************
//
// WK32WowCursorIconOp -
//
// Gets called when/from GlobalLock or GlobalUnlock are called. The fLock
// flag is TRUE if called from GlobalLock else it is FALSE.
//
//*****************************************************************************
BOOL FASTCALL WK32WowCursorIconOp(PVDMFRAME pFrame)
{
PWOWCURSORICONOP16 prci16;
HAND16 h16;
LPCURSORICONALIAS lpT;
BOOL fLock;
WORD wFuncId;
UINT cLockT;
GETARGPTR(pFrame, sizeof(WOWCURSORICONOP16), prci16);
wFuncId = FETCHWORD(prci16->wFuncId);
h16 = (HAND16)FETCHWORD(prci16->h16);
lpT = FindCursorIconAlias((ULONG)h16, HANDLE_16BIT);
// This is a Cursor or Icon
if (lpT != NULL) {
if (wFuncId == FUN_GLOBALLOCK || wFuncId == FUN_GLOBALUNLOCK) {
if (!(lpT->flType & HANDLE_TYPE_WOWGLOBAL)) {
fLock = (wFuncId == FUN_GLOBALLOCK);
// Store the current lockcount.
cLockT = lpT->cLock;
// Update the Lock count
lpT->cLock = fLock ? ++lpT->cLock : --lpT->cLock;
if (lpT->cLock == 0) {
// New lock count == 0 implies that it was decremented from
// 1 to 0 thereby impling that it was one of the cursors that
// was being updated regularly.
// Decrement the global count and update the cursor one last
// time
cPendingCursorIconUpdates--;
ReplaceCursorIcon(lpT);
}
else if (fLock && cLockT == 0) {
// If previous Lockcount was zero and the object is being locked
// then it means that this is the very first time that the object
// is being locked
cPendingCursorIconUpdates++;
}
}
}
else if (wFuncId == FUN_GLOBALFREE) {
// The h16 has not yet been GlobalFreed. We return TRUE if h16 can
// be freed else FALSE. The h16 can be freed only if it is not a
// global handle. ie, it doesn't correspond to a predefined cursor
// Also we donot free the handle if h16 corresponds to a resource.
// CorelDraw 3.0 calls FreeResource(h16) and then SetCursor(h16)
// thus GPing.
BOOL fFree;
fFree = !((lpT->flType & HANDLE_TYPE_WOWGLOBAL) || lpT->hRes16);
if (fFree) {
// Set handle to NULL so that InvalidateCursorIconAlias
// doesn't try to free it.
lpT->h16 = 0;
InvalidateCursorIconAlias(lpT);
}
return (BOOL)fFree;
}
else {
LOGDEBUG(0, ("WK32WowCursorIconOp: Unknown Func Id\n"));
}
}
// else if this is a GlobalFree call
else if (wFuncId == FUN_GLOBALFREE) {
// and if this is a handle to an accelerator
if(lpT = (LPCURSORICONALIAS)FindAccelAlias((HANDLE)h16, HANDLE_16BIT)) {
// free it from the accelerator alias list
FreeAccelAliasEntry((LPACCELALIAS) lpT);
// cause this hMem16 to really be free'd in 16-bit GlobalFree
return TRUE;
}
}
return TRUE;
}
//*****************************************************************************
//
// W32Create16BitResCursorIconFrom32BitHandle -
//
// Creates a WIN31 compatible Cursor or Icon given a 32bit cursor or icon
// handle. This is primarily used to create a 16bit Cursor or Icon which
// has been loaded from a 16bit resource.
//
//
// returns 16bit handle
//*****************************************************************************
HAND16 W32Create16BitCursorIconFrom32BitHandle(HANDLE h32, HAND16 hInst16,
PUINT pcbData)
{
HAND16 h16 = 0;
ICONINFO iinfo;
BITMAP bm;
BITMAP bmClr;
UINT nBytesAND = 0;
UINT nBytesXOR = 0;
LPBYTE lpBitsAND, lpBitsXOR;
if (GetIconInfo(h32, &iinfo)) {
if (GetObject(iinfo.hbmMask, sizeof(BITMAP), &bm)) {
nBytesAND = GetBitmapBits(iinfo.hbmMask, 0, (LPBYTE)NULL);
WOW32WARNMSG(nBytesAND,("WOW: W32C16BCIFBH: nBytesAND == 0\n"));
if (iinfo.hbmColor) {
GetObject(iinfo.hbmColor, sizeof(BITMAP), &bmClr);
nBytesXOR = GetBitmapBits(iinfo.hbmColor, 0, (LPBYTE)NULL);
WOW32WARNMSG(nBytesXOR,("WOW: W32C16BCIFBH: nBytesAND == 0\n"));
}
else {
bm.bmHeight /= 2;
nBytesAND /= 2;
nBytesXOR = nBytesAND;
}
if (pcbData) {
*pcbData = nBytesAND + nBytesXOR + sizeof(CURSORSHAPE16);
}
lpBitsAND = malloc_w(nBytesAND + nBytesXOR);
if (lpBitsAND != NULL) {
lpBitsXOR = lpBitsAND + nBytesAND;
GetBitmapBits(iinfo.hbmMask,
(iinfo.hbmColor) ? nBytesAND : (nBytesAND * 2),
lpBitsAND);
if (iinfo.hbmColor)
GetBitmapBits(iinfo.hbmColor, nBytesXOR, lpBitsXOR);
h16 = W32Create16BitCursorIcon(hInst16,
iinfo.xHotspot, iinfo.yHotspot,
bm.bmWidth, bm.bmHeight,
(iinfo.hbmColor) ? bmClr.bmPlanes :
bm.bmPlanes,
(iinfo.hbmColor) ? bmClr.bmBitsPixel :
bm.bmBitsPixel,
lpBitsAND, lpBitsXOR,
(INT)nBytesAND, (INT)nBytesXOR);
free_w(lpBitsAND);
}
}
DeleteObject(iinfo.hbmMask);
if (iinfo.hbmColor) {
DeleteObject(iinfo.hbmColor);
}
}
return h16;
}
//*****************************************************************************
//
// GetClassCursorIconAlias32 -
//
// Returns a 32bit handle given a 16bit Cursor or Icon HANDLE
// DOES NOT Create the 32bit Cursor or Icon if there is no alias.
// This is called in RegisterClass only - to support those apps which
// pass a bogus handle for WNDCLASS.hIcon.
//
// Returns the 32bit handle
//
//*****************************************************************************
HANDLE GetClassCursorIconAlias32(HAND16 h16)
{
LPCURSORICONALIAS lpT;
if (h16 == (HAND16)0)
return (ULONG)NULL;
lpT = FindCursorIconAlias((ULONG)h16, HANDLE_16BIT);
if (lpT) {
return lpT->h32;
}
else
return (HANDLE)NULL;
}
//*****************************************************************************
//
// InvalidateCursorIconAlias -
//
// Frees the allocated objects.
//
//*****************************************************************************
VOID InvalidateCursorIconAlias(LPCURSORICONALIAS lpT)
{
VPVOID vp=0;
PARM16 Parm16;
if (!lpT->fInUse)
return;
if (lpT->h16) {
SetCursorIconFlag(lpT->h16, FALSE);
GlobalUnlockFree16(RealLockResource16((HMEM16)lpT->h16, NULL));
}
if (lpT->hRes16) {
Parm16.WndProc.wParam = (HAND16) lpT->hRes16;
CallBack16(RET_FREERESOURCE, &Parm16, 0, &vp);
}
if (lpT->h32) {
if (lpT->flType == HANDLE_TYPE_CURSOR)
DestroyCursor(lpT->h32);
else
DestroyIcon(lpT->h32);
}
if (lpT->pbDataOld)
free_w(lpT->pbDataOld);
if (lpT->cLock)
cPendingCursorIconUpdates--;
if ((WORD)HIWORD(lpT->lpszName) != (WORD)NULL) {
free_w_small ((PVOID)lpT->lpszName);
}
lpT->fInUse = FALSE;
}
//*****************************************************************************
//
// InitStdCursorIconAlias -
//
// Creates the aliases of standard cursors and icons.
//
// NOTES:
//
// The idea is to createaliases for all the standard cursors and icons to
// make sure that we indeed generate valid handles.
//
// This problem cameup because of the following scenario
// the app turbotax does the following:
//
// h16Cursor1 = GetClassWord(hwndEditControl, GCL_HCURSOR);
// (bydefault, this is an I-beam)
// .....
// h16Cursor2 = LoadCursor(NULL, IDC_IBEAM);
// Because of the way we create and maintain our 32-16 alias hCursor1 is a
// a WOW bogus handle (ie > 0xf000) and since by default the "Edit" class is
// registered with hCursor = IDC_IBEAM, the h32s are same ie.
//
// GetClassWord(hwndEditControl, GCL_HCURSOR) == LoadCursor(..IDC_IBEAM);
//
// Thus h16Cursor2 will be same as h16Cursor1 and that's a problem because we
// are NOT returning a valid wow handle for a predefined cursor.
//
//
// The solution is to createaliases for all standard cursors and icons during
// init time so that we don't run into this problem. However I think this
// approach as wasteful and am creating the alias for the only known case
// ie IDC_IBEAM.
//
// - Nanduri Ramakrishna
//*****************************************************************************
DWORD InitCursorIds[] = {
(DWORD)IDC_ARROW,
(DWORD)IDC_IBEAM,
(DWORD)IDC_WAIT,
(DWORD)IDC_CROSS,
(DWORD)IDC_UPARROW,
(DWORD)IDC_SIZE,
(DWORD)IDC_ICON,
(DWORD)IDC_SIZENWSE,
(DWORD)IDC_SIZENESW,
(DWORD)IDC_SIZEWE,
(DWORD)IDC_SIZENS
};
BOOL InitStdCursorIconAlias()
{
HCURSOR h32;
UINT i;
for (i = 0; i < (sizeof(InitCursorIds) / sizeof(DWORD)); i++) {
//
// Create the alias for each standard cursor in the list
//
h32 = (HCURSOR)LoadCursor((HINSTANCE)NULL, (LPCSTR)InitCursorIds[i]);
WOW32ASSERT(h32);
if (h32) {
SetupResCursorIconAlias((HAND16)NULL, (HAND32)h32, NULL, (WORD)NULL,
HANDLE_TYPE_CURSOR);
}
}
//
// Add similar lines for standard icons.
//
return TRUE;
}
//*****************************************************************************
//
// W32CheckIfAlreadyLoaded -
//
// returns h16 if a cursoricon has previously been loaded.
//
//*****************************************************************************
HAND16 W32CheckIfAlreadyLoaded(VPVOID pData, WORD ResType)
{
LPCURSORICONALIAS lpT;
PICONCUR16 parg16;
PSZ psz;
GETMISCPTR(pData, parg16);
GETPSZIDPTR(parg16->lpStr, psz);
ResType = (ResType == NW_LOADCURSOR) ? HANDLE_TYPE_CURSOR : HANDLE_TYPE_ICON;
for (lpT = lpCIAlias; lpT != NULL; lpT = lpT->lpNext) {
if (lpT->fInUse) {
LPBYTE lpszNameT = lpT->lpszName;
if (lpszNameT && (lpT->flType & ResType) &&
lpT->hInst16 == parg16->hInst) {
WOW32ASSERT(!(lpT->flType & HANDLE_TYPE_WOWGLOBAL));
if (HIWORD(lpszNameT) && HIWORD(psz)) {
if (!(WOW32_stricmp(psz, (LPSTR)lpszNameT)))
break;
}
else if (lpszNameT == psz) {
break;
}
}
}
}
FREEPSZIDPTR(psz);
FREEMISCPTR(parg16);
if (lpT && lpT->cLock)
ReplaceCursorIcon(lpT);
return (lpT ? lpT->h16 : 0);
}