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