413 lines
11 KiB
C
413 lines
11 KiB
C
|
//*****************************************************************************
|
||
|
//
|
||
|
// LoadAccelerator - compatibility support.
|
||
|
// So much code for such a thing.
|
||
|
//
|
||
|
// 23-Jul-92 NanduriR Created.
|
||
|
//*****************************************************************************
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
MODNAME(waccel.c);
|
||
|
|
||
|
extern ULONG SetCursorIconFlag(HAND16 hAccel16, BOOL bFlag);
|
||
|
|
||
|
LPACCELALIAS lpAccelAlias = NULL;
|
||
|
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// WU32LoadAccelerators -
|
||
|
// This gets called from WU32NotifyWow. I use the familiar name WU32...
|
||
|
// because this gets called indirectly in response to LoadAccelerator
|
||
|
//
|
||
|
// returs TRUE for success.
|
||
|
//*****************************************************************************
|
||
|
|
||
|
|
||
|
ULONG FASTCALL WU32LoadAccelerators(VPVOID vpData)
|
||
|
{
|
||
|
PLOADACCEL16 ploadaccel16;
|
||
|
HACCEL hAccel;
|
||
|
BOOL fReturn = (BOOL)FALSE;
|
||
|
|
||
|
|
||
|
GETVDMPTR(vpData, sizeof(LOADACCEL16), ploadaccel16);
|
||
|
|
||
|
if (FindAccelAlias((HANDLE)FETCHWORD(ploadaccel16->hAccel),
|
||
|
HANDLE_16BIT)) {
|
||
|
LOGDEBUG(0, ("AccelAlias already exists\n"));
|
||
|
return (ULONG)TRUE;
|
||
|
}
|
||
|
|
||
|
if (hAccel = CreateAccel32(ploadaccel16->pAccel, ploadaccel16->cbAccel)) {
|
||
|
fReturn = (BOOL)SetupAccelAlias(FETCHWORD(ploadaccel16->hInst),
|
||
|
FETCHWORD(ploadaccel16->hAccel),
|
||
|
hAccel, TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
FREEVDMPTR(ploadaccel16);
|
||
|
return (ULONG)fReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// SetupAccelAlias -
|
||
|
// sets up the alias. the alias list is doubly linked. nothing fancy.
|
||
|
//
|
||
|
// returns pointer to the alias.
|
||
|
//*****************************************************************************
|
||
|
|
||
|
LPACCELALIAS SetupAccelAlias(
|
||
|
HAND16 hInstance,
|
||
|
HAND16 hAccel16,
|
||
|
HAND32 hAccel32,
|
||
|
BOOL f16
|
||
|
) {
|
||
|
LPACCELALIAS lpT;
|
||
|
WORD hTask16;
|
||
|
|
||
|
hTask16 = CURRENTPTD()->htask16;
|
||
|
lpT = FindAccelAlias((HANDLE)hAccel16, HANDLE_16BIT);
|
||
|
if (lpT == (LPACCELALIAS)NULL) {
|
||
|
lpT = malloc_w_small(sizeof(ACCELALIAS));
|
||
|
if (lpT) {
|
||
|
lpT->lpNext = lpAccelAlias;
|
||
|
lpT->lpPrev = (LPACCELALIAS)NULL;
|
||
|
|
||
|
if (lpAccelAlias)
|
||
|
lpAccelAlias->lpPrev = lpT;
|
||
|
|
||
|
lpAccelAlias = lpT;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
LOGDEBUG(0, ("SetupAccelAlias: Alias Already exists. how & why?\n"));
|
||
|
WOW32ASSERT(FALSE);
|
||
|
}
|
||
|
|
||
|
if (lpT) {
|
||
|
lpT->hInst = hInstance;
|
||
|
lpT->hTask16 = CURRENTPTD()->htask16;
|
||
|
lpT->h16 = hAccel16;
|
||
|
lpT->h32 = hAccel32;
|
||
|
lpT->f16 = (WORD)f16;
|
||
|
|
||
|
// mark this so we can remove it from the alias list when
|
||
|
// FreeResource() (in user.exe) calls GlobalFree() (in krnl386)
|
||
|
SetCursorIconFlag(hAccel16, TRUE);
|
||
|
}
|
||
|
else {
|
||
|
WOW32ASSERT(FALSE);
|
||
|
}
|
||
|
|
||
|
|
||
|
return (LPACCELALIAS)lpT;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// DestroyAccelAlias -
|
||
|
// Deletes the 32bit table and Frees the memory
|
||
|
//
|
||
|
// returns TRUE for success
|
||
|
//*****************************************************************************
|
||
|
|
||
|
BOOL DestroyAccelAlias(WORD hTask16)
|
||
|
{
|
||
|
WORD hCurTask16;
|
||
|
LPACCELALIAS lpT;
|
||
|
LPACCELALIAS lpTFree;
|
||
|
|
||
|
hCurTask16 = CURRENTPTD()->htask16;
|
||
|
lpT = lpAccelAlias;
|
||
|
while (lpT) {
|
||
|
if (lpT->hTask16 == hCurTask16) {
|
||
|
if (lpT->lpPrev)
|
||
|
lpT->lpPrev->lpNext = lpT->lpNext;
|
||
|
|
||
|
if (lpT->lpNext)
|
||
|
lpT->lpNext->lpPrev = lpT->lpPrev;
|
||
|
|
||
|
if ( lpT->f16 ) {
|
||
|
DestroyAcceleratorTable(lpT->h32);
|
||
|
} else {
|
||
|
// this function - DestroyAccelAlias- gets called during
|
||
|
// taskexit time and the 16bit task cleanup code has already
|
||
|
// freed this memory handle. so this callback is not needed.
|
||
|
// - nanduri
|
||
|
// WOWGlobalFree16( lpT->h16 );
|
||
|
}
|
||
|
|
||
|
lpTFree = lpT;
|
||
|
lpT = lpT->lpNext;
|
||
|
if (lpTFree == lpAccelAlias)
|
||
|
lpAccelAlias = lpT;
|
||
|
|
||
|
free_w_small(lpTFree);
|
||
|
}
|
||
|
else
|
||
|
lpT = lpT->lpNext;
|
||
|
}
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// FindAccelAlias -
|
||
|
// maps 16 bit handle to 32bit handle and vice versa
|
||
|
//
|
||
|
// returns TRUE for success
|
||
|
//*****************************************************************************
|
||
|
|
||
|
LPACCELALIAS FindAccelAlias(HANDLE hAccel, UINT fSize)
|
||
|
{
|
||
|
WORD hCurTask16;
|
||
|
LPACCELALIAS lpT;
|
||
|
|
||
|
hCurTask16 = CURRENTPTD()->htask16;
|
||
|
lpT = lpAccelAlias;
|
||
|
while (lpT) {
|
||
|
if (lpT->hTask16 == hCurTask16) {
|
||
|
if (fSize & HANDLE_16BIT) {
|
||
|
if (lpT->h16 == (HAND16)hAccel)
|
||
|
return lpT;
|
||
|
}
|
||
|
else {
|
||
|
if (lpT->h32 == (HAND32)hAccel)
|
||
|
return lpT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lpT = lpT->lpNext;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// GetAccelHandle32 -
|
||
|
// Returns h32, given h16.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
|
||
|
HAND32 GetAccelHandle32(HAND16 h16)
|
||
|
{
|
||
|
LPACCELALIAS lpT;
|
||
|
|
||
|
if (!(lpT = FindAccelAlias((HANDLE)(h16), HANDLE_16BIT))) {
|
||
|
DWORD cbAccel16;
|
||
|
VPVOID vpAccel16;
|
||
|
HACCEL hAccel;
|
||
|
|
||
|
if (vpAccel16 = RealLockResource16(h16, &cbAccel16)) {
|
||
|
if (hAccel = CreateAccel32(vpAccel16, cbAccel16)) {
|
||
|
lpT = SetupAccelAlias(CURRENTPTD()->hInst16, h16, hAccel, TRUE);
|
||
|
}
|
||
|
GlobalUnlock16(h16);
|
||
|
}
|
||
|
}
|
||
|
return (lpT) ? lpT->h32 : (HAND32)NULL;
|
||
|
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// GetAccelHandle16 -
|
||
|
// Returns h16, given h32.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
|
||
|
HAND16 GetAccelHandle16(HAND32 h32)
|
||
|
{
|
||
|
LPACCELALIAS lpT;
|
||
|
HAND16 hAccel16;
|
||
|
|
||
|
if (!(lpT = FindAccelAlias((HANDLE)(h32), HANDLE_32BIT))) {
|
||
|
//
|
||
|
// There isn't a corresponding 16-bit accelerator table handle already
|
||
|
// so create one.
|
||
|
//
|
||
|
if ( (hAccel16 = CreateAccel16(h32)) != 0 ) {
|
||
|
lpT = SetupAccelAlias(CURRENTPTD()->hInst16, hAccel16, h32, FALSE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (lpT) ? lpT->h16 : (HAND16)NULL;
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// CreateAccel32 -
|
||
|
// This gets called from WU32NotifyWow.
|
||
|
//
|
||
|
// returs TRUE for success.
|
||
|
//*****************************************************************************
|
||
|
|
||
|
|
||
|
HACCEL CreateAccel32(VPVOID vpAccel16, DWORD cbAccel16)
|
||
|
{
|
||
|
PSZ pAccel16;
|
||
|
DWORD nElem16;
|
||
|
|
||
|
LPACCEL lpAccel;
|
||
|
HACCEL hAccel = (HACCEL)NULL;
|
||
|
UINT i;
|
||
|
#if DBG
|
||
|
UINT LastKeyIndex = 0xffffffff;
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// pAccel16 is pointer to an array of records of length:
|
||
|
// (BYTE+WORD+WORD)
|
||
|
//
|
||
|
|
||
|
GETVDMPTR(vpAccel16 , cbAccel16, pAccel16);
|
||
|
if (pAccel16) {
|
||
|
|
||
|
//
|
||
|
// convert the 16bit accel table to 32bit format and create it.
|
||
|
//
|
||
|
|
||
|
nElem16 = cbAccel16 / (sizeof(BYTE) + 2 * sizeof(WORD));
|
||
|
lpAccel = (LPACCEL)malloc_w(nElem16 * sizeof(ACCEL));
|
||
|
if (lpAccel) {
|
||
|
for (i=0; i<nElem16; ++i) {
|
||
|
lpAccel[i].fVirt = *(LPBYTE)(pAccel16);
|
||
|
#if DBG
|
||
|
if ((lpAccel[i].fVirt & 0x80) && i < LastKeyIndex) {
|
||
|
LastKeyIndex = i;
|
||
|
}
|
||
|
#endif
|
||
|
((LPBYTE)pAccel16)++;
|
||
|
lpAccel[i].key = FETCHWORD(*(LPWORD)pAccel16);
|
||
|
((LPWORD)pAccel16)++;
|
||
|
lpAccel[i].cmd = FETCHWORD(*(LPWORD)pAccel16);
|
||
|
((LPWORD)pAccel16)++;
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
if (LastKeyIndex == 0xffffffff) {
|
||
|
LOGDEBUG(LOG_ALWAYS, ("WOW::CreateAccel32 : no LastKey found in 16-bit haccel\n"));
|
||
|
} else if (LastKeyIndex < nElem16-1) {
|
||
|
LOGDEBUG(LOG_ALWAYS, ("WOW::CreateAccel32 : bogus LastKey flags ignored in 16-bit haccel\n"));
|
||
|
}
|
||
|
#endif
|
||
|
hAccel = CreateAcceleratorTable(lpAccel, i);
|
||
|
free_w(lpAccel);
|
||
|
}
|
||
|
FREEVDMPTR(pAccel16);
|
||
|
}
|
||
|
|
||
|
return hAccel;
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// CreateAccel16 -
|
||
|
// This gets called from WU32NotifyWow.
|
||
|
//
|
||
|
// returns HACCEL16 for success.
|
||
|
//*****************************************************************************
|
||
|
|
||
|
HAND16 CreateAccel16(HACCEL hAccel32)
|
||
|
{
|
||
|
UINT iEntries;
|
||
|
UINT cbSize;
|
||
|
LPACCEL lpAccel32;
|
||
|
HAND16 hAccel16;
|
||
|
VPVOID vpAccel16;
|
||
|
LPBYTE lpAccel16;
|
||
|
LPBYTE lpAccel16Original;
|
||
|
UINT i;
|
||
|
|
||
|
iEntries = CopyAcceleratorTable( hAccel32, NULL, 0 );
|
||
|
|
||
|
if ( iEntries == 0 ) { // Invalid hAccel32
|
||
|
return( 0 );
|
||
|
}
|
||
|
|
||
|
lpAccel32 = (LPACCEL)malloc_w(iEntries * sizeof(ACCEL));
|
||
|
if ( lpAccel32 == NULL ) {
|
||
|
LOGDEBUG(LOG_ERROR, ("WOW::CreateAccel16 : Failed to alloc memory for 32-bit accel\n"));
|
||
|
return( 0 );
|
||
|
}
|
||
|
|
||
|
iEntries = CopyAcceleratorTable( hAccel32, lpAccel32, iEntries );
|
||
|
|
||
|
cbSize = iEntries * (sizeof(BYTE) + 2 * sizeof(WORD));
|
||
|
|
||
|
vpAccel16 = GlobalAllocLock16( GMEM_MOVEABLE, cbSize, &hAccel16 );
|
||
|
|
||
|
if ( vpAccel16 == 0 ) { // Out of 16-bit memory
|
||
|
LOGDEBUG(LOG_ERROR, ("WOW::CreateAccel16 : Failed to alloc memory for 16-bit haccel\n"));
|
||
|
free_w( lpAccel32 );
|
||
|
return( 0 );
|
||
|
}
|
||
|
|
||
|
GETVDMPTR(vpAccel16, cbSize, lpAccel16 );
|
||
|
|
||
|
WOW32ASSERT( lpAccel16 != NULL );
|
||
|
|
||
|
lpAccel16Original = lpAccel16;
|
||
|
|
||
|
//
|
||
|
// Now iterate through the entries changing them and moving them into
|
||
|
// the 16-bit memory.
|
||
|
//
|
||
|
|
||
|
i = 0;
|
||
|
|
||
|
while ( i < iEntries ) {
|
||
|
if ( i == iEntries-1 ) {
|
||
|
// Last one, set the last bit
|
||
|
*lpAccel16++ = lpAccel32[i].fVirt | 0x80;
|
||
|
} else {
|
||
|
*lpAccel16++ = lpAccel32[i].fVirt;
|
||
|
}
|
||
|
*((PWORD16)lpAccel16) = lpAccel32[i].key;
|
||
|
lpAccel16 += sizeof(WORD);
|
||
|
*((PWORD16)lpAccel16) = lpAccel32[i].cmd;
|
||
|
lpAccel16 += sizeof(WORD);
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
FLUSHVDMPTR(vpAccel16, cbSize, lpAccel16Original);
|
||
|
FREEVDMPTR(lpAccel16Original);
|
||
|
|
||
|
GlobalUnlock16( hAccel16 );
|
||
|
|
||
|
return( hAccel16 );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// this gets called indirectly from GlobalFree() in krnl386.exe
|
||
|
// via WK32WowCursorIconOp() in wcuricon.c
|
||
|
void FreeAccelAliasEntry(LPACCELALIAS lpT) {
|
||
|
|
||
|
if (lpT == lpAccelAlias)
|
||
|
lpAccelAlias = lpT->lpNext;
|
||
|
|
||
|
if (lpT->lpPrev)
|
||
|
lpT->lpPrev->lpNext = lpT->lpNext;
|
||
|
|
||
|
if (lpT->lpNext)
|
||
|
lpT->lpNext->lpPrev = lpT->lpPrev;
|
||
|
|
||
|
if ( lpT->f16 ) {
|
||
|
DestroyAcceleratorTable(lpT->h32);
|
||
|
} else {
|
||
|
// this function - FreeAccelAliasEntry -- is being called
|
||
|
// indirectly from GlobalFree() in krnl386. GlobalFree()
|
||
|
// takes care of freeing h16 so this callback is not needed.
|
||
|
// - a-craigj
|
||
|
// WOWGlobalFree16( lpT->h16 );
|
||
|
}
|
||
|
|
||
|
free_w_small(lpT);
|
||
|
}
|
||
|
|