windows-nt/Source/XPSP1/NT/multimedia/directx/dplay/dnet/lobby/dplhandles.cpp

391 lines
8.9 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*==========================================================================
*
* 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);
}