You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
361 lines
9.6 KiB
361 lines
9.6 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: handles.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* HANDLES.C - Data handle manager
|
|
*
|
|
*
|
|
* This module allows a 32 bit value to be converted into a handle that
|
|
* can be validated with a high probability of correctness.
|
|
*
|
|
* A handle array is kept which contains the 32 bit data associated with
|
|
* it, and a copy of the correect handle value. The handle itself is
|
|
* composed of a combination of the index into the array for the associated
|
|
* data, the instance value, a type value and a DDEML instance value.
|
|
*
|
|
* The HIWORD of a handle is guarenteed not to be 0.
|
|
*
|
|
* History:
|
|
* 10-28-91 Sanfords Created
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
// globals
|
|
|
|
PCHANDLEENTRY aHandleEntry = NULL;
|
|
|
|
// statics
|
|
|
|
int cHandlesAllocated = 0;
|
|
int iFirstFree = 0;
|
|
DWORD nextId = 1;
|
|
|
|
#define GROW_COUNT 16
|
|
// #define TESTING
|
|
#ifdef TESTING
|
|
VOID CheckHandleTable()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < cHandlesAllocated; i++) {
|
|
if (aHandleEntry[i].handle && aHandleEntry[i].dwData) {
|
|
switch (TypeFromHandle(aHandleEntry[i].handle)) {
|
|
case HTYPE_INSTANCE:
|
|
UserAssert(((PCL_INSTANCE_INFO)aHandleEntry[i].dwData)->hInstClient == aHandleEntry[i].handle);
|
|
break;
|
|
|
|
case HTYPE_CLIENT_CONVERSATION:
|
|
case HTYPE_SERVER_CONVERSATION:
|
|
UserAssert(((PCONV_INFO)aHandleEntry[i].dwData)->hConv == (HCONV)aHandleEntry[i].handle ||
|
|
((PCONV_INFO)aHandleEntry[i].dwData)->hConv == 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
#define CheckHandleTable()
|
|
#endif // TESTING
|
|
|
|
|
|
/***************************************************************************\
|
|
* CreateHandle
|
|
*
|
|
* Description:
|
|
* Creates a client side handle.
|
|
*
|
|
* Returns 0 on error.
|
|
*
|
|
* History:
|
|
* 11-1-91 sanfords Created.
|
|
\***************************************************************************/
|
|
HANDLE CreateHandle(
|
|
ULONG_PTR dwData,
|
|
DWORD type,
|
|
DWORD inst)
|
|
{
|
|
HANDLE h;
|
|
int i, iNextFree;
|
|
PCHANDLEENTRY phe, pheTemp;
|
|
|
|
if (iFirstFree >= cHandlesAllocated) {
|
|
if (cHandlesAllocated == 0) {
|
|
aHandleEntry = (PCHANDLEENTRY)DDEMLAlloc(sizeof(CHANDLEENTRY) * GROW_COUNT);
|
|
} else {
|
|
pheTemp = (PCHANDLEENTRY)DDEMLReAlloc(aHandleEntry,
|
|
sizeof(CHANDLEENTRY) * (cHandlesAllocated + GROW_COUNT));
|
|
/*
|
|
* If the realloc failed, free the old ptr. We continue
|
|
* on in order to maintain compatibility with previous DDE code.
|
|
*/
|
|
if (pheTemp == NULL) {
|
|
DDEMLFree(aHandleEntry);
|
|
}
|
|
aHandleEntry = pheTemp;
|
|
}
|
|
if (aHandleEntry == NULL) {
|
|
return (0);
|
|
}
|
|
i = cHandlesAllocated;
|
|
cHandlesAllocated += GROW_COUNT;
|
|
phe = &aHandleEntry[i];
|
|
while (i < cHandlesAllocated) {
|
|
// phe->handle = 0; // indicates empty - ZERO init.
|
|
phe->dwData = ++i; // index to next free spot.
|
|
phe++;
|
|
}
|
|
}
|
|
h = aHandleEntry[iFirstFree].handle = (HANDLE)LongToHandle(
|
|
HandleFromId(nextId) |
|
|
HandleFromIndex(iFirstFree) |
|
|
HandleFromType(type) |
|
|
HandleFromInst(inst) );
|
|
iNextFree = (int)aHandleEntry[iFirstFree].dwData;
|
|
aHandleEntry[iFirstFree].dwData = dwData;
|
|
nextId++;
|
|
if (nextId == 0) { // guarentees HIWORD of handle != 0
|
|
nextId++;
|
|
}
|
|
iFirstFree = iNextFree;
|
|
|
|
CheckHandleTable();
|
|
return (h);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* DestroyHandle
|
|
*
|
|
* Description:
|
|
* Frees up a handle.
|
|
*
|
|
* Assumptions:
|
|
* The handle is valid.
|
|
* Critical Section is entered.
|
|
*
|
|
* Returns:
|
|
* Data in handle before destruction.
|
|
*
|
|
* History:
|
|
* 11-1-91 sanfords Created.
|
|
\***************************************************************************/
|
|
ULONG_PTR DestroyHandle(
|
|
HANDLE h)
|
|
{
|
|
register int i;
|
|
register ULONG_PTR dwRet;
|
|
|
|
CheckHandleTable();
|
|
|
|
i = IndexFromHandle(h);
|
|
UserAssert(aHandleEntry[i].handle == h);
|
|
aHandleEntry[i].handle = 0;
|
|
dwRet = aHandleEntry[i].dwData;
|
|
aHandleEntry[i].dwData = iFirstFree;
|
|
iFirstFree = i;
|
|
|
|
return (dwRet);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* GetHandleData
|
|
*
|
|
* Description:
|
|
* A quick way to retrieve a valid handle's data
|
|
*
|
|
* History:
|
|
* 11-19-91 sanfords Created.
|
|
\***************************************************************************/
|
|
ULONG_PTR GetHandleData(
|
|
HANDLE h)
|
|
{
|
|
register ULONG_PTR dwRet;
|
|
|
|
CheckHandleTable();
|
|
dwRet = aHandleEntry[IndexFromHandle(h)].dwData;
|
|
return (dwRet);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* SetHandleData
|
|
*
|
|
* Description:
|
|
* A quick way to change a valid handle's data.
|
|
*
|
|
* History:
|
|
* 11-19-91 sanfords Created.
|
|
\***************************************************************************/
|
|
VOID SetHandleData(
|
|
HANDLE h,
|
|
ULONG_PTR dwData)
|
|
{
|
|
aHandleEntry[IndexFromHandle(h)].dwData = dwData;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ValidateCHandle
|
|
*
|
|
* Description:
|
|
* General handle validation routine. ExpectedType or ExpectedInstance
|
|
* can be HTYPE_ANY/HINST_ANY. (note Expected Instance is an instance
|
|
* index into the aInstance array, NOT a instance handle.
|
|
*
|
|
* History:
|
|
* 11-19-91 sanfords Created.
|
|
\***************************************************************************/
|
|
ULONG_PTR ValidateCHandle(
|
|
HANDLE h,
|
|
DWORD ExpectedType,
|
|
DWORD ExpectedInstance)
|
|
{
|
|
register int i;
|
|
register ULONG_PTR dwRet;
|
|
|
|
CheckHandleTable();
|
|
dwRet = 0;
|
|
i = IndexFromHandle(h);
|
|
if (i < cHandlesAllocated &&
|
|
aHandleEntry[i].handle == h &&
|
|
(ExpectedType == -1 || ExpectedType == TypeFromHandle(h)) &&
|
|
(ExpectedInstance == -1 || ExpectedInstance == InstFromHandle(h))) {
|
|
dwRet = aHandleEntry[i].dwData;
|
|
}
|
|
|
|
return (dwRet);
|
|
}
|
|
|
|
|
|
PCL_INSTANCE_INFO PciiFromHandle(
|
|
HANDLE h)
|
|
{
|
|
PCHANDLEENTRY phe;
|
|
|
|
CheckDDECritIn;
|
|
|
|
if (!cHandlesAllocated) {
|
|
return(NULL);
|
|
}
|
|
phe = &aHandleEntry[cHandlesAllocated];
|
|
|
|
do {
|
|
phe--;
|
|
if (phe->handle != 0 &&
|
|
TypeFromHandle(phe->handle) == HTYPE_INSTANCE &&
|
|
(InstFromHandle(phe->handle) == InstFromHandle(h))) {
|
|
return(((PCL_INSTANCE_INFO)phe->dwData)->tid == GetCurrentThreadId() ?
|
|
(PCL_INSTANCE_INFO)phe->dwData : NULL);
|
|
}
|
|
} while (phe != aHandleEntry);
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* ApplyFunctionToObjects
|
|
*
|
|
* Description:
|
|
* Used for cleanup, this allows the handle array to be scanned for
|
|
* handles meeting the ExpectedType and ExpectedInstance criteria
|
|
* and apply the given function to each handle.
|
|
*
|
|
* History:
|
|
* 11-19-91 sanfords Created.
|
|
\***************************************************************************/
|
|
VOID ApplyFunctionToObjects(
|
|
DWORD ExpectedType,
|
|
DWORD ExpectedInstance,
|
|
PFNHANDLEAPPLY pfn)
|
|
{
|
|
PCHANDLEENTRY phe;
|
|
|
|
CheckDDECritIn;
|
|
|
|
if (!cHandlesAllocated) {
|
|
return;
|
|
}
|
|
phe = &aHandleEntry[cHandlesAllocated];
|
|
|
|
do {
|
|
phe--;
|
|
if (phe->handle != 0 &&
|
|
(ExpectedType == HTYPE_ANY ||
|
|
ExpectedType == TypeFromHandle(phe->handle)) &&
|
|
(ExpectedInstance == HTYPE_ANY ||
|
|
ExpectedInstance == InstFromHandle(phe->handle))) {
|
|
LeaveDDECrit;
|
|
CheckDDECritOut;
|
|
(*pfn)(phe->handle);
|
|
EnterDDECrit;
|
|
}
|
|
} while (phe != aHandleEntry);
|
|
}
|
|
|
|
|
|
DWORD GetFullUserHandle(WORD wHandle)
|
|
{
|
|
DWORD dwHandle;
|
|
PHE phe;
|
|
|
|
dwHandle = HMIndexFromHandle(wHandle);
|
|
|
|
if (dwHandle < gpsi->cHandleEntries) {
|
|
|
|
phe = &gSharedInfo.aheList[dwHandle];
|
|
|
|
if (phe->bType == TYPE_WINDOW)
|
|
return(MAKELONG(dwHandle, phe->wUniq));
|
|
}
|
|
|
|
/*
|
|
* object may be gone, but we must pass something.
|
|
* DDE terminates will fail if we don't map this right even after
|
|
* the window is dead!
|
|
*
|
|
* NOTE: This fix will only work for WOW apps, but since the 32bit
|
|
* tracking layer locks dde windows until the last terminate is
|
|
* received, we won't see this problem on the 32bit side.
|
|
*
|
|
* BUG: We WILL see a problem for OLE32 thunked DDE though.
|
|
*/
|
|
return(wHandle);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* BestSetLastDDEMLError
|
|
*
|
|
* Description:
|
|
* This sets the LastError field of all instances that belong to the
|
|
* current thread. This is used to get error information to applications
|
|
* which generated an error where the exact instance could not be
|
|
* determined.
|
|
*
|
|
* History:
|
|
* 11-12-91 sanfords Created.
|
|
\***************************************************************************/
|
|
VOID BestSetLastDDEMLError(
|
|
DWORD error)
|
|
{
|
|
PCHANDLEENTRY phe;
|
|
|
|
CheckDDECritIn;
|
|
|
|
if (!cHandlesAllocated) {
|
|
return;
|
|
}
|
|
phe = &aHandleEntry[cHandlesAllocated];
|
|
do {
|
|
phe--;
|
|
if (phe->handle != 0 && TypeFromHandle(phe->handle) == HTYPE_INSTANCE) {
|
|
SetLastDDEMLError((PCL_INSTANCE_INFO)phe->dwData, error);
|
|
}
|
|
} while (phe != aHandleEntry);
|
|
}
|