374 lines
9.8 KiB
C
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";
|
||
|
}
|