//***************************************************************************** // // 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); }