Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

624 lines
12 KiB

/*++
Copyright (C) Microsoft Corporation, 1996 - 1999
Module Name:
handles
Abstract:
This header file describes the handle management service.
Author:
Doug Barlow (dbarlow) 5/9/1996
Environment:
Win32, C++ w/ Exceptions
Notes:
?Notes?
--*/
#ifndef _HANDLES_H_
#define _HANDLES_H_
#ifndef HANDLE_TYPE
#define HANDLE_TYPE DWORD_PTR
#endif
#if defined(_WIN64) || defined(WIN64)
static const DWORD_PTR
HANDLE_INDEX_MASK = 0x000000007fffffff,
HANDLE_COUNT_MASK = 0x00ffffff00000000,
HANDLE_ID_MASK = 0xff00000000000000;
static const DWORD
HANDLE_INDEX_OFFSET = 0,
HANDLE_COUNT_OFFSET = 32,
HANDLE_ID_OFFSET = 56;
#elif defined(_WIN32) || defined(WIN32)
static const DWORD_PTR
HANDLE_INDEX_MASK = 0x0000ffff,
HANDLE_COUNT_MASK = 0x00ff0000,
HANDLE_ID_MASK = 0xff000000;
static const DWORD
HANDLE_INDEX_OFFSET = 0,
HANDLE_COUNT_OFFSET = 16,
HANDLE_ID_OFFSET = 24;
#else
#error "Unsupported handle type length"
#endif
class CHandleList;
//
//==============================================================================
//
// CCritSect
//
class CCritSect
{
public:
CCritSect(LPCRITICAL_SECTION pCritSect)
{
m_pCritSect = pCritSect;
EnterCriticalSection(m_pCritSect);
};
~CCritSect()
{
LeaveCriticalSection(m_pCritSect);
};
protected:
LPCRITICAL_SECTION m_pCritSect;
};
//
//==============================================================================
//
// CHandle
//
class CHandle
{
public:
BOOL IsBad(void)
{ return m_fIsBad;};
protected:
// Constructors & Destructor
CHandle()
{
m_dwCount = 0;
m_dwIndex = (DWORD)(HANDLE_INDEX_MASK >> HANDLE_INDEX_OFFSET);
m_fIsBad = FALSE;
};
virtual ~CHandle() { /* Mandatory Base Class Destructor */ };
// Properties
DWORD m_dwCount;
DWORD m_dwIndex;
BOOL m_fIsBad;
// Methods
virtual void Cancel(void) {};
virtual void MarkAsBad(BOOL fCancel)
{
m_fIsBad = TRUE;
if (fCancel)
Cancel();
};
friend class CHandleList;
};
//
//==============================================================================
//
// CHandleList
//
class CHandleList
{
public:
// Constructors & Destructor
CHandleList(DWORD dwHandleId)
{
m_dwId = dwHandleId;
m_Max = m_Mac = 0;
m_phList = NULL;
m_fInitFailed = FALSE;
try {
if (! InitializeCriticalSectionAndSpinCount(
&m_critSect, 0x80000000))
m_fInitFailed = TRUE;
}
catch (HRESULT hr) {
m_fInitFailed = TRUE;
}
};
virtual ~CHandleList()
{
if (m_fInitFailed)
return;
Clear();
DeleteCriticalSection(&m_critSect);
};
// Properties
// Methods
DWORD Count(void)
{
CCritSect csLock(&m_critSect);
return m_Mac;
};
void
Clear(void)
{
CCritSect csLock(&m_critSect);
if (NULL != m_phList)
{
for (DWORD index = 0; index < m_Mac; index += 1)
if (NULL != m_phList[index].phObject)
delete m_phList[index].phObject;
delete[] m_phList;
m_phList = NULL;
m_Max = 0;
m_Mac = 0;
}
};
CHandle *
Close(
IN HANDLE_TYPE hItem);
HANDLE_TYPE
Add(
IN CHandle *phItem);
CHandle * const
GetQuietly(
IN HANDLE_TYPE hItem);
CHandle * const
Get(
IN HANDLE_TYPE hItem);
HANDLE_TYPE
IndexHandle(
DWORD nItem);
BOOL
InitFailed(void)
{ return m_fInitFailed; }
// Operators
CHandle * const
operator[](HANDLE_TYPE hItem)
{ return Get(hItem); };
void MarkContentAsBad(BOOL fCancel)
{
CCritSect csLock(&m_critSect);
if (NULL != m_phList)
{
for (DWORD index = 0; index < m_Mac; index += 1)
{
if (NULL != m_phList[index].phObject)
m_phList[index].phObject->MarkAsBad(fCancel);
}
}
}
CHandle *
GetFirst()
{
DWORD index = 0;
while (index < m_Mac)
{
if (NULL != m_phList[index].phObject)
return (m_phList[index].phObject);
index++;
}
return NULL;
}
CHandle *
GetNext(
IN CHandle * phObject)
{
DWORD index = 0;
while (index < m_Mac)
{
if (phObject == m_phList[index].phObject)
break;
index++;
}
if (index < m_Mac)
{
index++;
while (index < m_Mac)
{
if (NULL != m_phList[index].phObject)
return (m_phList[index].phObject);
index++;
}
}
return NULL;
}
protected:
struct HandlePtr
{
CHandle *phObject;
DWORD dwCount;
};
// Properties
DWORD
m_dwId; // Id number of handle list.
DWORD
m_Max, // Number of element slots available.
m_Mac; // Number of element slots used.
HandlePtr *
m_phList; // The elements.
CRITICAL_SECTION
m_critSect; // Handle list access control.
BOOL
m_fInitFailed; // InitCritSec failed in constructor
// Methods
HandlePtr *
GetHandlePtr(
IN HANDLE_TYPE hItem)
const;
};
/*++
Close:
This routine closes an item in the handle array.
Arguments:
hItem - Supplies the handle to the object to be closed.
Throws:
ERROR_INVALID_HANDLE - The supplied handle value is invalid.
Return Value:
The referenced object.
Author:
Doug Barlow (dbarlow) 7/13/1995
--*/
inline CHandle *
CHandleList::Close(
IN HANDLE_TYPE hItem)
{
CHandle *phItem;
CCritSect csLock(&m_critSect);
HandlePtr *pHandlePtr = GetHandlePtr(hItem);
if (NULL == pHandlePtr)
throw (DWORD)ERROR_INVALID_HANDLE;
phItem = pHandlePtr->phObject;
if (NULL == phItem)
throw (DWORD)ERROR_INVALID_HANDLE;
pHandlePtr->phObject = NULL;
pHandlePtr->dwCount += 1;
return phItem;
}
/*++
Add:
This method adds an item to the Handle list.
Arguments:
pvItem - Supplies the value to be added to the list.
Return Value:
The resultant handle of the Add operation.
Author:
Doug Barlow (dbarlow) 10/10/1995
--*/
inline HANDLE_TYPE
CHandleList::Add(
IN CHandle *phItem)
{
DWORD index;
HandlePtr * pHndl = NULL;
//
// Look for a vacant handle slot. We look through m_Max instead of m_Mac,
// so that if all the official ones are used, we fall into unused territory.
//
CCritSect csLock(&m_critSect);
for (index = 0; index < m_Max; index += 1)
{
pHndl = &m_phList[index];
if (NULL == pHndl->phObject)
break;
pHndl = NULL;
}
//
// Make sure the array was big enough.
//
if (NULL == pHndl)
{
DWORD newSize = (0 == m_Max ? 4 : m_Max * 2);
if ((HANDLE_INDEX_MASK >> HANDLE_INDEX_OFFSET) < newSize)
throw (DWORD)ERROR_OUTOFMEMORY;
pHndl = new HandlePtr[newSize];
if (NULL == pHndl)
throw (DWORD)ERROR_OUTOFMEMORY;
if (NULL != m_phList)
{
CopyMemory(pHndl, m_phList, sizeof(HandlePtr) * m_Mac);
delete[] m_phList;
}
ZeroMemory(&pHndl[m_Mac], sizeof(HandlePtr) * (newSize - m_Mac));
m_phList = pHndl;
m_Max = (DWORD)newSize;
index = m_Mac++;
pHndl = &m_phList[index];
}
else
{
if (m_Mac <= index)
m_Mac = index + 1;
}
//
// Cross index the list element and the object.
//
ASSERT(NULL == pHndl->phObject);
pHndl->phObject = phItem;
if (0 == pHndl->dwCount)
pHndl->dwCount = 1;
phItem->m_dwCount = (DWORD)(pHndl->dwCount
& (HANDLE_COUNT_MASK >> HANDLE_COUNT_OFFSET));
phItem->m_dwIndex = index;
return (HANDLE_TYPE)(
((((HANDLE_TYPE)m_dwId) << HANDLE_ID_OFFSET) & HANDLE_ID_MASK)
| ((((HANDLE_TYPE)pHndl->dwCount) << HANDLE_COUNT_OFFSET) & HANDLE_COUNT_MASK)
| ((((HANDLE_TYPE)index) << HANDLE_INDEX_OFFSET) & HANDLE_INDEX_MASK));
}
/*++
GetQuietly:
This method returns the element at the given handle. If the handle is
invalid, it returns NULL. It does not expand the array.
Arguments:
hItem - Supplies the index into the list.
Return Value:
The value stored at that handle in the list, or NULL if the handle is
invalid.
Author:
Doug Barlow (dbarlow) 7/13/1995
--*/
inline CHandle * const
CHandleList::GetQuietly(
HANDLE_TYPE hItem)
{
CCritSect csLock(&m_critSect);
HandlePtr *pHandlePtr = GetHandlePtr(hItem);
if (NULL == pHandlePtr)
return NULL;
return pHandlePtr->phObject;
}
/*++
Get:
This method returns the element at the given handle. If the handle is
invalid, it throws an error. It does not expand the array.
Arguments:
hItem - Supplies the index into the list.
Return Value:
The value stored at that handle in the list.
Throws:
ERROR_INVALID_HANDLE - Invalid handle value.
Author:
Doug Barlow (dbarlow) 7/13/1995
--*/
inline CHandle * const
CHandleList::Get(
HANDLE_TYPE hItem)
{
CCritSect csLock(&m_critSect);
HandlePtr *pHandlePtr = GetHandlePtr(hItem);
if (NULL == pHandlePtr)
throw (DWORD)ERROR_INVALID_HANDLE;
return pHandlePtr->phObject;
}
/*++
GetHandlePtr:
This routine finds the HandlePtr structure corresponding to a given handle.
Arguments:
hItem supplies the handle to look up.
Return Value:
The address of the HandlePtr structure corresponding to the handle, or NULL
if none exists.
Author:
Doug Barlow (dbarlow) 5/9/1996
--*/
inline CHandleList::HandlePtr *
CHandleList::GetHandlePtr(
HANDLE_TYPE hItem)
const
{
try
{
HandlePtr *pHandlePtr;
DWORD_PTR dwItem = (DWORD_PTR)hItem;
DWORD dwId = (DWORD)((dwItem & HANDLE_ID_MASK) >> HANDLE_ID_OFFSET);
DWORD dwCount = (DWORD)((dwItem & HANDLE_COUNT_MASK) >> HANDLE_COUNT_OFFSET);
DWORD dwIndex = (DWORD)((dwItem & HANDLE_INDEX_MASK) >> HANDLE_INDEX_OFFSET);
if (dwId != (m_dwId & (HANDLE_ID_MASK >> HANDLE_ID_OFFSET))
|| (m_Mac <= dwIndex))
return NULL;
pHandlePtr = &m_phList[dwIndex];
if (dwCount
!= (pHandlePtr->dwCount
& (HANDLE_ID_MASK >> HANDLE_ID_OFFSET)))
return NULL;
return pHandlePtr;
}
catch (...)
{
// Swallow the error.
}
return NULL;
}
/*++
IndexHandle:
This method converts an index into a handle. The handle is NULL if there is
no element stored at that index.
Arguments:
nItem supplies the index of the object to reference.
Return Value:
The handle of the object, or NULL if there is no object at that index.
Throws:
None
Author:
Doug Barlow (dbarlow) 1/3/1997
--*/
inline HANDLE_TYPE
CHandleList::IndexHandle(
DWORD nItem)
{
HANDLE_TYPE hItem = NULL;
HandlePtr * pHndl;
CCritSect csLock(&m_critSect);
if (m_Mac > nItem)
{
pHndl = &m_phList[nItem];
if (NULL != pHndl->phObject)
{
hItem =
((((HANDLE_TYPE)m_dwId) << HANDLE_ID_OFFSET) & HANDLE_ID_MASK)
| ((((HANDLE_TYPE)pHndl->dwCount) << HANDLE_COUNT_OFFSET) & HANDLE_COUNT_MASK)
| ((((HANDLE_TYPE)nItem) << HANDLE_INDEX_OFFSET) & HANDLE_INDEX_MASK);
}
}
return hItem;
}
#endif // _HANDLES_H_