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

374 lines
9.8 KiB
C

/*++ BUILD Version: 0001
*
* WOW v1.0
*
* Copyright (c) 1991, Microsoft Corporation
*
* WMMALIAS.C
* WOW32 16-bit handle alias support
*
* History:
* Created Sept-1-1992 by Chandan Chauhan (ChandanC)
* Modified 12-May-1992 by Mike Tricker (miketri) to add MultiMedia support
--*/
#include "precomp.h"
#pragma hdrstop
#include "wmmalias.h"
MODNAME(wmmalias.c);
HINFO hiMMedia; // MultiMedia handle alias info - MikeTri 12-May-1992
HINFO hiWinsock; // Winsock handle alias info - DavidTr 4-Oct-1992
#ifdef DEBUG
INT nAliases;
#endif
INT iLargestListSlot;
extern CRITICAL_SECTION mmHandleCriticalSection;
#ifdef DEBUG
extern BOOL fSkipLog; // TRUE to temporarily skip certain logging
#endif
/*
* Added MultiMedia functions - MikeTri 12-May-1992
*/
HAND16 GetMMedia16(HAND32 h32, INT iClass)
{
PHMAP phm;
EnterCriticalSection( &mmHandleCriticalSection );
if (phm = FindHMap32(h32, &hiMMedia, iClass)) {
LeaveCriticalSection( &mmHandleCriticalSection );
return phm->h16;
}
LeaveCriticalSection( &mmHandleCriticalSection );
return (HAND16)h32;
}
VOID FreeMMedia16(HAND16 h16)
{
EnterCriticalSection( &mmHandleCriticalSection );
FreeHMap16(h16, &hiMMedia);
LeaveCriticalSection( &mmHandleCriticalSection );
}
HAND32 GetMMedia32(HAND16 h16)
{
PHMAP phm;
EnterCriticalSection( &mmHandleCriticalSection );
if (phm = FindHMap16(h16, &hiMMedia)) {
LeaveCriticalSection( &mmHandleCriticalSection );
return phm->h32;
}
LeaveCriticalSection( &mmHandleCriticalSection );
return NULL;
// return (HAND32)INT32(h16);
}
PHMAP FindHMap32(HAND32 h32, PHINFO phi, INT iClass)
{
INT iHash;
#ifndef NEWALIAS
INT iList, iListEmpty;
#endif
register PHMAP phm, phmPrev, phmEmpty;
if (!h32 || (INT)h32 == 0xFFFF || (INT)h32 == -1)
return NULL;
// If we don't have a hash table yet, allocate one
if (!phi->pphmHash) {
if (!(phi->pphmHash = malloc_w(HASH_SLOTS*sizeof(PHMAP)))) {
LOGDEBUG(0,(" FindHMap32 ERROR: cannot allocate hash table\n"));
return NULL;
}
RtlZeroMemory(phi->pphmHash, HASH_SLOTS*sizeof(PHMAP));
}
// Compute the index into the hash table, and retrieve from it
// the initial HMAP pointer
iHash = HASH32(h32);
phmPrev = (PHMAP)(phi->pphmHash + iHash);
// Start walking the HMAP list, looking for a match (and keeping
// track of any free entries we may find in case we decide to reuse it)
#ifndef NEWALIAS
iList = 1;
#endif
phmEmpty = NULL;
while (phm = phmPrev->phmNext) {
if (MASK32(phm->h32) == MASK32(h32)) {
break;
}
if (phm->h32 == NULL && !phmEmpty) {
phmEmpty = phm;
#ifndef NEWALIAS
iListEmpty = iList;
#endif
}
phmPrev = phm;
#ifndef NEWALIAS
iList++;
#endif
}
// If we couldn't find a match but we did find an empty HMAP structure
// on the list, reuse it
if (!phm && phmEmpty) {
phm = phmEmpty;
#ifndef NEWALIAS
iList = iListEmpty;
#endif
}
// If we have to allocate a new HMAP, here's where we do it
if (!phm) {
#ifndef NEWALIAS
if (iList > LIST_SLOTS) {
LOGDEBUG(0,(" FindHMap32 ERROR: out of list slots for hash slot %d\n", iHash));
return NULL;
}
#else
// If we don't have an alias table yet, allocate one
if (!phi->pphmAlias) {
if (!(phi->pphmAlias = malloc_w(ALIAS_SLOTS*sizeof(PHMAP)))) {
LOGDEBUG(0,(" FindHMap32 ERROR: cannot allocate alias table\n"));
return NULL;
}
RtlZeroMemory(phi->pphmAlias, ALIAS_SLOTS*sizeof(PHMAP));
phi->nAliasEntries = ALIAS_SLOTS;
}
// If the current hint is in use, then look for the next free one
if (phi->pphmAlias[phi->iAliasHint] &&
!((INT)phi->pphmAlias[phi->iAliasHint]&1)) {
INT i;
LOGDEBUG(13,(" FindHMap32: alias hint failed, scanning...\n"));
for (i=phi->iAliasHint+1; i<phi->nAliasEntries; i++) {
if (!phi->pphmAlias[i] || ((INT)phi->pphmAlias[i]&1))
goto Break;
}
for (i=0; i<phi->iAliasHint; i++) {
if (!phi->pphmAlias[i] || ((INT)phi->pphmAlias[i]&1))
goto Break;
}
Break:
phi->iAliasHint = i;
// If we've exhausted all the slots in the existing table, grow it
if (phi->pphmAlias[i] && !((INT)phi->pphmAlias[i]&1)) {
PPHMAP p;
if (phi->nAliasEntries >= (1<<(16-RES_BITS))) {
LOGDEBUG(0,(" FindHMap32 ERROR: at 16-bit handle limit\n"));
return NULL;
}
LOGDEBUG(1,(" FindHMap32: growing handle alias array\n"));
if (!(p = realloc(phi->pphmAlias, (phi->nAliasEntries+ALIAS_SLOTS)*sizeof(PHMAP)))) {
LOGDEBUG(0,(" FindHMap32 ERROR: cannot grow alias table\n"));
return NULL;
}
phi->pphmAlias = p;
RtlZeroMemory(phi->pphmAlias+phi->nAliasEntries, ALIAS_SLOTS*sizeof(PHMAP));
phi->iAliasHint = phi->nAliasEntries;
phi->nAliasEntries += ALIAS_SLOTS;
}
}
#endif
phm = malloc_w(sizeof(HMAP));
if (!phm) {
LOGDEBUG(0,(" FindHMap32 ERROR: cannot allocate new list entry\n"));
return NULL;
}
phm->h32 = NULL;
#ifdef NEWALIAS
// Record the new list entry in the alias table
phm->h16 = (HAND16)(++phi->iAliasHint << RES_BITS);
if (phi->iAliasHint >= phi->nAliasEntries)
phi->iAliasHint = 0;
// New entries can simply be inserted at the head of the list,
// because their position in the list has no relationship to the aliases
phm->phmNext = phi->pphmHash[iHash];
phi->pphmHash[iHash] = phm;
#else
#ifdef DEBUG
nAliases++;
if (iList > iLargestListSlot) {
iLargestListSlot = iList;
LOGDEBUG(1,(" FindHMap32: largest list slot is now %d\n", iLargestListSlot));
}
#endif
phm->h16 = (HAND16)((iHash | (iList << HASH_BITS)) << RES_BITS);
// New entries must be appended rather than inserted, because
// our phoney 16-bit handles are dependent on position in the list
phm->phmNext = NULL;
phmPrev->phmNext = phm;
#endif
}
// If this a new entry, initialize it
if (!phm->h32) {
#ifdef DEBUG
if (!fSkipLog) {
LOGDEBUG(7,(" Adding %s alias %04x for %08lx\n",
GetHMapNameM(phi, iClass), phm->h16, h32));
}
#endif
// Insure that the alias pointer is valid
#ifdef NEWALIAS
phi->pphmAlias[(phm->h16>>RES_BITS)-1] = phm;
#endif
phm->h32 = h32;
phm->htask16 = FETCHWORD(CURRENTPTD()->htask16);
phm->iClass = iClass;
phm->dwStyle = 0;
phm->vpfnWndProc = 0;
phm->pwcd = 0;
}
return phm;
}
PHMAP FindHMap16(HAND16 h16, PHINFO phi)
{
#ifndef NEWALIAS
INT i, iHash, iList;
#endif
register PHMAP phm;
#ifdef HACK32
static HMAP hmDummy = {NULL, NULL, 0, 0, 0, 0, NULL, 0};
#endif
if (!h16 || h16 == 0xFFFF)
return NULL;
#ifdef HACK32
if (h16 == TRUE)
return &hmDummy;
#endif
// Verify all the RES_BITS are clear
if (h16 & ((1 << RES_BITS)-1)) {
WOW32ASSERT(FALSE);
return NULL;
}
h16 >>= RES_BITS;
#ifdef NEWALIAS
// Verify the handle is within range
WOW32ASSERT((INT)h16 <= phi->nAliasEntries);
// This can happen if we haven't allocated any aliases yet
if (!phi->pphmAlias)
return NULL;
phm = phi->pphmAlias[h16-1];
if ((INT)phm & 1) {
(INT)phm &= ~1;
LOGDEBUG(0,(" FindHMap16 WARNING: defunct alias %04x reused\n", h16<<RES_BITS));
}
#else
iHash = h16 & HASH_MASK;
iList = (h16 & LIST_MASK) >> HASH_BITS;
phm = (PHMAP)(phi->pphmHash + iHash);
i = iList;
while (i-- && phm) {
phm = phm->phmNext;
}
#endif
if (!phm) {
LOGDEBUG(0,(" FindHMap16 ERROR: could not find %04x\n", h16<<RES_BITS));
return NULL;
}
// Verify requested handle is same as stored in alias
if (h16 != (HAND16)(phm->h16>>RES_BITS)) {
LOGDEBUG(0, ("FindHMap16: Got bad H16\n"));
WOW32ASSERT(FALSE);
return NULL;
}
#ifdef DEBUG
if (!fSkipLog) {
LOGDEBUG(9,(" Found %s %08lx for alias %04x\n",
GetHMapNameM(phi, phm->iClass), phm->h32, h16<<RES_BITS));
}
#endif
return phm;
}
VOID FreeHMap16(HAND16 h16, PHINFO phi)
{
register PHMAP phm;
if (phm = FindHMap16(h16, phi)) {
LOGDEBUG(7,(" Freeing %s alias %04x for %08lx\n",
GetHMapNameM(phi, phm->iClass), phm->h16, phm->h32));
// if (phm->iClass == WOWCLASS_WIN16)
// phm->pwcd->nWindows--;
// BUGBUG -- We'll eventually want some garbage collection... -JTP
phm->h32 = NULL;
#ifdef NEWALIAS
// We don't want to totally zap the alias' hmap pointer yet, because
// if we're dealing with an app that is using cached handles after
// it has technically freed them, we want to try to reassociate their
// handle with a new 32-bit handle. So we'll just set the low bit
// of the alias hmap pointer and leave the hint index alone; we will
// still try to reuse entries with the low bit set however.
//
// phi->iAliasHint = (h16>>RES_BITS)-1;
// phi->pphmAlias[phi->iAliasHint] = NULL;
(INT)phi->pphmAlias[(h16>>RES_BITS)-1] |= 1;
#endif
return;
}
LOGDEBUG(1,(" FreeHMap16: handle alias %04x not found\n"));
}
PSZ GetHMapNameM(PHINFO phi, INT iClass)
{
return "MMEDIA";
}