Leaked source code of windows server 2003
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

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