391 lines
8.9 KiB
C++
391 lines
8.9 KiB
C++
|
/*==========================================================================
|
||
|
*
|
||
|
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* File: Handles.cpp
|
||
|
* Content: Handle manager
|
||
|
*
|
||
|
* History:
|
||
|
* Date By Reason
|
||
|
* ==== == ======
|
||
|
* 08/19/99 mjn Created
|
||
|
* 03/23/00 mjn Revised to ensure 64-bit compliance
|
||
|
* 03/24/00 mjn Added H_Enum
|
||
|
* 07/09/00 rmt Added signature bytes
|
||
|
* 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
|
||
|
* 08/31/00 rmt Whistler Prefix Bug 171826
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "dnlobbyi.h"
|
||
|
|
||
|
|
||
|
#define INC_SERIAL_COUNT(a) if (++((a)->dwSerial) == 0) ((a)->dwSerial)++
|
||
|
#define INDEX_MASK 0x000fffff
|
||
|
#define SERIAL_MASK 0xfff00000
|
||
|
#define SERIAL_SHIFT 20
|
||
|
#define GET_INDEX(h) (h & INDEX_MASK)
|
||
|
#define GET_SERIAL(h) ((h & SERIAL_MASK) >> SERIAL_SHIFT)
|
||
|
#define MAKE_HANDLE(i,s) ((i & INDEX_MASK) | ((s << SERIAL_SHIFT) & SERIAL_MASK))
|
||
|
#define VERIFY_HANDLE(p,h) (((h & INDEX_MASK) < (p)->dwNumHandles) && ((p)->HandleArray[(h & INDEX_MASK)].dwSerial) && ((h & SERIAL_MASK) == ((p)->HandleArray[(h & INDEX_MASK)].dwSerial << SERIAL_SHIFT)))
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "H_Grow"
|
||
|
|
||
|
HRESULT H_Grow(HANDLESTRUCT *const phs,
|
||
|
const DWORD dwIncSize)
|
||
|
{
|
||
|
HRESULT hResultCode = S_OK;
|
||
|
DWORD dw;
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Parameters: phs [0x%p], dwIncSize [%ld]",phs,dwIncSize);
|
||
|
|
||
|
if (dwIncSize == 0)
|
||
|
{
|
||
|
DPFERR("Must grow handles by at least 1");
|
||
|
return(E_INVALIDARG);
|
||
|
}
|
||
|
|
||
|
// Grab CS
|
||
|
DNEnterCriticalSection(&phs->dncs);
|
||
|
|
||
|
if (phs->HandleArray == NULL || phs->dwNumHandles == 0)
|
||
|
{
|
||
|
if ((phs->HandleArray = static_cast<HANDLEELEMENT*>(DNMalloc((dwIncSize + phs->dwNumHandles) * sizeof(HANDLEELEMENT)))) == NULL)
|
||
|
{
|
||
|
DPFERR("Could not create handle array");
|
||
|
hResultCode = E_OUTOFMEMORY;
|
||
|
goto EXIT_H_Grow;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ((phs->HandleArray = static_cast<HANDLEELEMENT*>(DNRealloc(phs->HandleArray,(dwIncSize + phs->dwNumHandles) * sizeof(HANDLEELEMENT)))) == NULL)
|
||
|
{
|
||
|
DPFERR("Could not grow handle array");
|
||
|
hResultCode = E_OUTOFMEMORY;
|
||
|
goto EXIT_H_Grow;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update Handle Structure
|
||
|
phs->dwFirstFreeHandle = phs->dwNumHandles;
|
||
|
phs->dwLastFreeHandle = phs->dwNumHandles + dwIncSize - 1;
|
||
|
phs->dwNumFreeHandles = dwIncSize;
|
||
|
phs->dwNumHandles += dwIncSize;
|
||
|
|
||
|
// Setup free Handle Elements
|
||
|
for (dw = 0 ; dw < dwIncSize - 1 ; dw++)
|
||
|
{
|
||
|
phs->HandleArray[phs->dwFirstFreeHandle + dw].dwSerial = 0;
|
||
|
phs->HandleArray[phs->dwFirstFreeHandle + dw].Entry.dwIndex = phs->dwFirstFreeHandle + dw + 1;
|
||
|
}
|
||
|
phs->HandleArray[phs->dwFirstFreeHandle + dw].dwSerial = 0;
|
||
|
phs->HandleArray[phs->dwFirstFreeHandle + dw].Entry.pvData = NULL;
|
||
|
|
||
|
EXIT_H_Grow:
|
||
|
|
||
|
// Release CS
|
||
|
DNLeaveCriticalSection(&phs->dncs);
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "H_Initialize"
|
||
|
|
||
|
HRESULT H_Initialize(HANDLESTRUCT *const phs,
|
||
|
const DWORD dwInitialNum)
|
||
|
{
|
||
|
HRESULT hResultCode = S_OK;
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Parameters: phs [0x%p], dwInitialNum [%ld]",phs,dwInitialNum);
|
||
|
|
||
|
if (dwInitialNum == 0)
|
||
|
{
|
||
|
DPFERR("Must initialize handles with at least 1");
|
||
|
return(E_INVALIDARG);
|
||
|
}
|
||
|
|
||
|
if (!DNInitializeCriticalSection(&phs->dncs))
|
||
|
{
|
||
|
DPFERR("DNInitializeCriticalSection() failed");
|
||
|
return(E_OUTOFMEMORY);
|
||
|
}
|
||
|
|
||
|
// Lock
|
||
|
DNEnterCriticalSection(&phs->dncs);
|
||
|
|
||
|
phs->dwSignature = DPLSIGNATURE_HANDLESTRUCT;
|
||
|
phs->HandleArray = NULL;
|
||
|
phs->dwNumHandles = 0;
|
||
|
phs->dwNumFreeHandles = 0;
|
||
|
phs->dwFirstFreeHandle = 0;
|
||
|
phs->dwLastFreeHandle = 0;
|
||
|
phs->dwSerial = 1;
|
||
|
|
||
|
if ((hResultCode = H_Grow(phs,dwInitialNum)) != S_OK)
|
||
|
{
|
||
|
DPFERR("H_Grow() failed");
|
||
|
goto EXIT_H_Initialize;
|
||
|
}
|
||
|
|
||
|
EXIT_H_Initialize:
|
||
|
|
||
|
// Unlock
|
||
|
DNLeaveCriticalSection(&phs->dncs);
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "H_Terminate"
|
||
|
|
||
|
void H_Terminate(HANDLESTRUCT *const phs)
|
||
|
{
|
||
|
DPFX(DPFPREP, 9,"Parameters: phs [0x%p]",phs);
|
||
|
|
||
|
if (phs->HandleArray != NULL)
|
||
|
DNFree(phs->HandleArray);
|
||
|
|
||
|
phs->dwNumHandles = 0;
|
||
|
phs->dwSignature = DPLSIGNATURE_HANDLESTRUCT_FREE;
|
||
|
|
||
|
DNDeleteCriticalSection(&phs->dncs);
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Returning");
|
||
|
}
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "H_Create"
|
||
|
|
||
|
HRESULT H_Create(HANDLESTRUCT *const phs,
|
||
|
void *const pvData,
|
||
|
DWORD *const pHandle)
|
||
|
{
|
||
|
DWORD dwIndex;
|
||
|
HRESULT hResultCode = S_OK;
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Parameters: phs [0x%p], pvData [0x%p], pHandle [0x%p]",phs,pvData,pHandle);
|
||
|
|
||
|
if (pHandle == NULL)
|
||
|
{
|
||
|
DPFERR("Invalid handle pointer");
|
||
|
return(E_INVALIDARG);
|
||
|
}
|
||
|
|
||
|
// Lock
|
||
|
DNEnterCriticalSection(&phs->dncs);
|
||
|
|
||
|
// If there are no free handles, double the handle array
|
||
|
if (phs->dwNumFreeHandles == 0)
|
||
|
{
|
||
|
if ((hResultCode = H_Grow(phs,phs->dwNumHandles)) != S_OK) // Double the size
|
||
|
{
|
||
|
DPFERR("H_Grow() failed");
|
||
|
goto EXIT_H_Create;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update internal handle pointers
|
||
|
dwIndex = phs->dwFirstFreeHandle;
|
||
|
phs->dwFirstFreeHandle = phs->HandleArray[dwIndex].Entry.dwIndex;
|
||
|
phs->dwNumFreeHandles--;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Update handle information
|
||
|
INC_SERIAL_COUNT(phs);
|
||
|
phs->HandleArray[dwIndex].dwSerial = phs->dwSerial;
|
||
|
phs->HandleArray[dwIndex].Entry.pvData = pvData;
|
||
|
|
||
|
// Create user's handle
|
||
|
*pHandle = MAKE_HANDLE(dwIndex,phs->dwSerial);
|
||
|
} while (*pHandle == 0); // Don't want 0 handle
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Returning: *pHandle = [0x%lx]",*pHandle);
|
||
|
|
||
|
EXIT_H_Create:
|
||
|
|
||
|
// Unlock
|
||
|
DNLeaveCriticalSection(&phs->dncs);
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "H_Destroy"
|
||
|
|
||
|
HRESULT H_Destroy(HANDLESTRUCT *const phs,
|
||
|
const DWORD handle)
|
||
|
{
|
||
|
DWORD dwIndex;
|
||
|
DWORD dwSerial;
|
||
|
HRESULT hResultCode = S_OK;
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Parameters: phs [0x%p], handle [0x%lx]",phs,handle);
|
||
|
|
||
|
// Lock
|
||
|
DNEnterCriticalSection(&phs->dncs);
|
||
|
|
||
|
// Ensure valid handle supplied
|
||
|
if (!VERIFY_HANDLE(phs,handle))
|
||
|
{
|
||
|
DPFERR("Invalid handle");
|
||
|
hResultCode = E_INVALIDARG;
|
||
|
goto EXIT_H_Destroy;
|
||
|
}
|
||
|
|
||
|
dwIndex = GET_INDEX(handle);
|
||
|
dwSerial = GET_SERIAL(handle);
|
||
|
|
||
|
// Add handle to end of free list
|
||
|
if (phs->dwNumFreeHandles == 0) // Only free handle
|
||
|
{
|
||
|
phs->dwFirstFreeHandle = phs->dwLastFreeHandle = dwIndex;
|
||
|
}
|
||
|
else // Other handles, so add to end of list
|
||
|
{
|
||
|
phs->HandleArray[phs->dwLastFreeHandle].Entry.dwIndex = dwIndex;
|
||
|
phs->dwLastFreeHandle = dwIndex;
|
||
|
}
|
||
|
|
||
|
// Clear out returned handle
|
||
|
phs->HandleArray[dwIndex].dwSerial = 0;
|
||
|
phs->HandleArray[dwIndex].Entry.pvData = NULL;
|
||
|
|
||
|
// Update handle structure
|
||
|
INC_SERIAL_COUNT(phs);
|
||
|
phs->dwNumFreeHandles++;
|
||
|
|
||
|
EXIT_H_Destroy:
|
||
|
|
||
|
// Unlock
|
||
|
DNLeaveCriticalSection(&phs->dncs);
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "H_Retrieve"
|
||
|
|
||
|
HRESULT H_Retrieve(HANDLESTRUCT *const phs,
|
||
|
const DWORD handle,
|
||
|
void **const ppvData)
|
||
|
{
|
||
|
DWORD dwIndex;
|
||
|
DWORD dwSerial;
|
||
|
HRESULT hResultCode = S_OK;
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Parameters: phs [0x%p], handle [0x%lx], ppvData [0x%p]",phs,handle,ppvData);
|
||
|
|
||
|
// Lock
|
||
|
DNEnterCriticalSection(&phs->dncs);
|
||
|
|
||
|
// Ensure valid handle supplied
|
||
|
if (!VERIFY_HANDLE(phs,handle))
|
||
|
{
|
||
|
DPFERR("Invalid handle");
|
||
|
hResultCode = DPNERR_INVALIDHANDLE;
|
||
|
goto EXIT_H_Retrieve;
|
||
|
}
|
||
|
|
||
|
if (ppvData == NULL)
|
||
|
{
|
||
|
DPFERR("Invalid data return pointer");
|
||
|
hResultCode = DPNERR_INVALIDHANDLE;
|
||
|
goto EXIT_H_Retrieve;
|
||
|
}
|
||
|
|
||
|
dwIndex = GET_INDEX(handle);
|
||
|
dwSerial = GET_SERIAL(handle);
|
||
|
|
||
|
*ppvData = phs->HandleArray[GET_INDEX(handle)].Entry.pvData;
|
||
|
DPFX(DPFPREP, 9,"Returning: *ppvData = [0x%p]",*ppvData);
|
||
|
|
||
|
EXIT_H_Retrieve:
|
||
|
|
||
|
// Unlock
|
||
|
DNLeaveCriticalSection(&phs->dncs);
|
||
|
|
||
|
DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "H_Enum"
|
||
|
|
||
|
HRESULT H_Enum(HANDLESTRUCT *const phs,
|
||
|
DWORD *const pdwNumHandles,
|
||
|
DWORD *const rgHandles)
|
||
|
{
|
||
|
HRESULT hResultCode;
|
||
|
DWORD dw;
|
||
|
DWORD dwNumHandles;
|
||
|
DWORD *pHandle;
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Parameters: phs [0x%p], pdwNumHandles [0x%p], rgHandles [0x%p]",
|
||
|
phs,pdwNumHandles,rgHandles);
|
||
|
|
||
|
DNASSERT(phs != NULL);
|
||
|
DNASSERT(pdwNumHandles != NULL);
|
||
|
DNASSERT(rgHandles != NULL || *pdwNumHandles == 0);
|
||
|
|
||
|
hResultCode = S_OK;
|
||
|
dwNumHandles = 0;
|
||
|
DNEnterCriticalSection(&phs->dncs);
|
||
|
for (dw = 0 ; dw < phs->dwNumHandles ; dw++)
|
||
|
{
|
||
|
if (phs->HandleArray[dw].dwSerial != NULL)
|
||
|
{
|
||
|
DPFX(DPFPREP, 5,"Found handle data at [%ld]",dw);
|
||
|
dwNumHandles++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwNumHandles)
|
||
|
{
|
||
|
if( rgHandles == NULL )
|
||
|
{
|
||
|
DPFX(DPFPREP, 1, "Buffer too small!" );
|
||
|
*pdwNumHandles = dwNumHandles;
|
||
|
DNLeaveCriticalSection(&phs->dncs);
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
if (dwNumHandles <= *pdwNumHandles)
|
||
|
{
|
||
|
pHandle = rgHandles;
|
||
|
for (dw = 0 ; dw < phs->dwNumHandles ; dw++)
|
||
|
{
|
||
|
if (phs->HandleArray[dw].dwSerial != NULL)
|
||
|
{
|
||
|
*pHandle++ = MAKE_HANDLE(dw,phs->HandleArray[dw].dwSerial);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hResultCode = E_POINTER;
|
||
|
}
|
||
|
}
|
||
|
*pdwNumHandles = dwNumHandles;
|
||
|
|
||
|
DNLeaveCriticalSection(&phs->dncs);
|
||
|
|
||
|
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode);
|
||
|
return(hResultCode);
|
||
|
}
|
||
|
|