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.
 
 
 
 
 
 

436 lines
13 KiB

#ifndef _INC_DBLNUL_H
#define _INC_DBLNUL_H
#include <windows.h>
#include <strsafe.h>
#ifndef ASSERT
# include <assert.h>
# define ASSERT assert
#endif
#ifdef __cplusplus
//
//-----------------------------------------------------------------------------
// CDblNulTermListStrLib
//-----------------------------------------------------------------------------
//
// Type-specific string functions so the compiler can select the correct version
// to match the list type.
//
class CDblNulTermListStrLib
{
public:
static int StringLength(LPCSTR pszA)
{ return lstrlenA(pszA); }
static int StringLength(LPCWSTR pszW)
{ return lstrlenW(pszW); }
static HRESULT StringCopy(LPSTR pszDestA, size_t cchDestA, LPCSTR pszSrcA)
{ return StringCchCopyA(pszDestA, cchDestA, pszSrcA); }
static HRESULT StringCopy(LPWSTR pszDestW, size_t cchDestW, LPCWSTR pszSrcW)
{ return StringCchCopyW(pszDestW, cchDestW, pszSrcW); }
};
//
//-----------------------------------------------------------------------------
// CDblNulTermListEnumImpl<T>
//-----------------------------------------------------------------------------
//
// For iterating over items in a double-nul terminated list of
// text strings. An enumerator may be generated from an existing
// dblnul list object or may be created for a raw double nul terminated string.
//
template <typename T>
class CDblNulTermListEnumImpl
{
public:
explicit CDblNulTermListEnumImpl(const T *pszList)
: m_pszList(pszList),
m_pszCurrent(pszList) { }
~CDblNulTermListEnumImpl(void) { }
//
// Retrieve address of next string in list.
//
HRESULT Next(const T **ppszItem);
//
// Reset enumerator to the start of the list.
//
void Reset(void)
{ m_pszCurrent = m_pszList; }
private:
const T *m_pszList;
const T *m_pszCurrent;
};
// ----------------------------------------------------------------------------
// CEmptyList
// ----------------------------------------------------------------------------
//
// Provides type-sensitive empty dbl-nul-term lists.
// This is so that an empty dbl-nul-term list object will still provide a valid
// dbl-nul-term list if no items are added.
//
class CEmptyList
{
public:
CEmptyList(void)
{
m_pszEmptyA = "\0";
m_pszEmptyW = L"\0";
}
operator LPCSTR() const
{ return m_pszEmptyA; }
operator LPCWSTR() const
{ return m_pszEmptyW; }
bool operator == (LPCSTR pszA) const
{ return m_pszEmptyA == pszA; }
bool operator == (LPCWSTR pszW) const
{ return m_pszEmptyW == pszW; }
bool operator != (LPCSTR pszA) const
{ return !operator == (pszA); }
bool operator != (LPCWSTR pszW) const
{ return !operator == (pszW); }
private:
LPCSTR m_pszEmptyA;
LPCWSTR m_pszEmptyW;
};
//
//-----------------------------------------------------------------------------
// CDblNulTermListImpl<T>
//-----------------------------------------------------------------------------
//
template <typename T>
class CDblNulTermListImpl
{
public:
explicit CDblNulTermListImpl(int cchGrowMin = MAX_PATH)
: m_psz((T *) ((const T *)s_Empty)),
m_cchAlloc(0),
m_cchUsed(0),
m_cElements(0),
m_cchGrowMin(cchGrowMin) { }
~CDblNulTermListImpl(void)
{ if (s_Empty != m_psz) LocalFree(m_psz); }
//
// Add a string to the list.
//
HRESULT Add(const T *psz);
//
// Clear the list of all content.
//
void Clear(void);
//
// Return the count of strings in the list.
//
int Count(void) const
{ return m_cElements; }
//
// Return the number of bytes used by the list.
// +1 for the list's terminating nul.
//
int SizeBytes(void) const
{ return (m_cchUsed + 1) * sizeof(T); }
//
// Retrieve the address of the start of the list buffer.
// Use this and SizeBytes() to copy the list buffer.
//
// CopyMemory(pbDest, (LPCTSTR)list, list.SizeBytes());
//
operator const T * () const
{ return m_psz; }
//
// Create an enumerator for enumerating strings in the list.
//
CDblNulTermListEnumImpl<T> CreateEnumerator(void) const
{ return CDblNulTermListEnumImpl<T>(m_psz); }
private:
T * m_psz; // The text buffer.
int m_cchAlloc; // Total allocation in chars.
int m_cchUsed; // Total used excluding FINAL nul term.
int m_cElements; // Count of strings in list.
const int m_cchGrowMin; // Minimum chars to grow each expansion.
static CEmptyList s_Empty;
HRESULT _Grow(int cchGrowMin);
//
// Prevent copy.
//
CDblNulTermListImpl(const CDblNulTermListImpl& rhs);
CDblNulTermListImpl& operator = (const CDblNulTermListImpl& rhs);
};
//
// The list impl initially points to this so that an uninitialized
// list instance will simply provide an empty list.
//
template <typename T>
CEmptyList CDblNulTermListImpl<T>::s_Empty;
//
// Add a string to a dbl-nul-term list.
//
template <typename T>
HRESULT
CDblNulTermListImpl<T>::Add(
const T *psz
)
{
HRESULT hr = E_FAIL;
//
// +2 for this string's nul and for list nul terminator.
//
const int cchString = CDblNulTermListStrLib::StringLength(psz);
const int cchRequired = cchString + 2;
if ((m_cchAlloc - m_cchUsed) < cchRequired)
{
//
// Grow by the amount required PLUS the "min growth" amount.
// This way a client can choose between one of the two
// following strategies:
//
// 1. low-waste/frequent allocation
// 2. high-waste/infrequent allocation.
//
// The "waste" comes from the unused memory at the end
// of the list after all strings have been added.
//
hr = _Grow(cchRequired + m_cchGrowMin);
if (FAILED(hr))
{
return hr;
}
}
ASSERT(NULL != m_psz);
CDblNulTermListStrLib::StringCopy(m_psz + m_cchUsed, m_cchAlloc - m_cchUsed, psz);
m_cchUsed += cchString + 1;
m_cElements++;
return S_OK;
}
//
// Internal function used for allocating the list buffer as needed.
//
template <typename T>
HRESULT
CDblNulTermListImpl<T>::_Grow(int cchGrow)
{
ASSERT(m_cchGrowMin > 0);
HRESULT hr = E_OUTOFMEMORY;
int cb = (m_cchAlloc + cchGrow) * sizeof(T);
T *p = (T *)LocalAlloc(LPTR, cb);
if (NULL != p)
{
if (s_Empty != m_psz)
{
CopyMemory(p, m_psz, m_cchUsed * sizeof(T));
LocalFree(m_psz);
}
m_psz = p;
m_cchAlloc += cchGrow;
hr = S_OK;
}
return hr;
}
//
// Clears all items from the list.
//
template <typename T>
void
CDblNulTermListImpl<T>::Clear(void)
{
if (s_Empty != m_psz)
{
LocalFree(m_psz);
}
m_psz = (T *) ((const T *)s_Empty);
m_cchAlloc = 0;
m_cchUsed = 0;
m_cElements = 0;
}
//
// Retrieve the address of the next string in the enumeration.
// Returns S_FALSE if enumerator is exhausted.
//
template <typename T>
HRESULT
CDblNulTermListEnumImpl<T>::Next(
const T **ppszItem
)
{
if (*m_pszCurrent)
{
*ppszItem = m_pszCurrent;
m_pszCurrent += CDblNulTermListStrLib::StringLength(m_pszCurrent) + 1;
return S_OK;
}
return S_FALSE;
}
//
// Create some types so clients don't need to deal with templates.
// Clients work with these types:
//
// CDblNulTermList, CDblNulTermListA, CDblNulTermListW
//
// CDblNulTermListEnum, CDblNulTermListEnumA, CDblNulTermListEnumW
//
//
typedef CDblNulTermListImpl<WCHAR> CDblNulTermListW;
typedef CDblNulTermListImpl<char> CDblNulTermListA;
typedef CDblNulTermListEnumImpl<WCHAR> CDblNulTermListEnumW;
typedef CDblNulTermListEnumImpl<char> CDblNulTermListEnumA;
#ifdef UNICODE
# define CDblNulTermList CDblNulTermListW
# define CDblNulTermListEnum CDblNulTermListEnumW
#else
# define CDblNulTermList CDblNulTermListA
# define CDblNulTermListEnum CDblNulTermListEnumA
#endif
#endif // __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
//
// These types and functions support 'C' code or 'C++' code
// that prefers to work with handles rather than classes.
//
typedef void * HDBLNULTERMLISTW;
typedef void * HDBLNULTERMLISTENUMW;
typedef void * HDBLNULTERMLISTA;
typedef void * HDBLNULTERMLISTENUMA;
//
// Create a new dbl-nul-term list.
//
HRESULT DblNulTermListW_Create(int cchGrowMin, HDBLNULTERMLISTW *phList);
HRESULT DblNulTermListA_Create(int cchGrowMin, HDBLNULTERMLISTA *phList);
//
// Destroy a dbl-nul-term list.
//
void DblNulTermListW_Destroy(HDBLNULTERMLISTW hList);
void DblNulTermListA_Destroy(HDBLNULTERMLISTA hList);
//
// Add a string to a dbl-nul-term list.
//
HRESULT DblNulTermListW_Add(HDBLNULTERMLISTW hList, LPCWSTR pszW);
HRESULT DblNulTermListA_Add(HDBLNULTERMLISTA hList, LPCSTR pszA);
//
// Clear all entries in a dbl-nul-term list.
//
void DblNulTermListW_Clear(HDBLNULTERMLISTW hList);
void DblNulTermListA_Clear(HDBLNULTERMLISTA hList);
//
// Return count of entries in a dbl-nul-term list.
//
int DblNulTermListW_Count(HDBLNULTERMLISTW hList);
int DblNulTermListA_Count(HDBLNULTERMLISTA hList);
//
// Retrieve the address of the buffer in a dbl-nul-term list.
//
HRESULT DblNulTermListW_Buffer(HDBLNULTERMLISTW hList, LPCWSTR *ppszW);
HRESULT DblNulTermListA_Buffer(HDBLNULTERMLISTA hList, LPCSTR *ppszA);
//
// Create an enumerator for enumerating the strings in a dbl-nul-term list.
// Enumerator is created from an existing dbl-nul-term list object.
//
HRESULT DblNulTermListW_CreateEnum(HDBLNULTERMLISTA hList, HDBLNULTERMLISTENUMW *phEnum);
HRESULT DblNulTermListA_CreateEnum(HDBLNULTERMLISTW hList, HDBLNULTERMLISTENUMA *phEnum);
//
// Create an enumerator given the address of a raw double nul terminated string.
// The resulting enumerator can be used to enumerate the individual strings.
//
HRESULT DblNulTermListEnumW_Create(LPCWSTR pszW, HDBLNULTERMLISTENUMW *phEnum);
HRESULT DblNulTermListEnumA_Create(LPCSTR pszA, HDBLNULTERMLISTENUMA *phEnum);
//
// Destroy a dbl-nul-term list enumerator.
//
void DblNulTermListEnumW_Destroy(HDBLNULTERMLISTW hList);
void DblNulTermListEnumA_Destroy(HDBLNULTERMLISTA hList);
//
// Retrieve the address of the "next" string in a dbl-nul-term list enumerator.
// Returns S_FALSE when enumerator is exhausted.
//
HRESULT DblNulTermListEnumW_Next(HDBLNULTERMLISTW hList, LPCWSTR *ppszW);
HRESULT DblNulTermListEnumA_Next(HDBLNULTERMLISTA hList, LPCSTR *ppszA);
#ifdef UNICODE
# define HDBLNULTERMLIST HDBLNULTERMLISTW
# define HDBLNULTERMLISTENUM HDBLNULTERMLISTENUMW
# define DblNulTermList_Create DblNulTermListW_Create
# define DblNulTermList_Destroy DblNulTermListW_Destroy
# define DblNulTermList_Add DblNulTermListW_Add
# define DblNulTermList_Clear DblNulTermListW_Clear
# define DblNulTermList_Count DblNulTermListW_Count
# define DblNulTermList_Buffer DblNulTermListW_Buffer
# define DblNulTermList_CreateEnum DblNulTermListW_CreateEnum
# define DblNulTermListEnum_Create DblNulTermListEnumW_Create
# define DblNulTermListEnum_Destroy DblNulTermListEnumW_Destroy
# define DblNulTermListEnum_Next DblNulTermListEnumW_Next
#else
# define HDBLNULTERMLIST HDBLNULTERMLISTA
# define HDBLNULTERMLISTENUM HDBLNULTERMLISTENUMA
# define DblNulTermList_Create DblNulTermListA_Create
# define DblNulTermList_Destroy DblNulTermListA_Destroy
# define DblNulTermList_Add DblNulTermListA_Add
# define DblNulTermList_Clear DblNulTermListA_Clear
# define DblNulTermList_Count DblNulTermListA_Count
# define DblNulTermList_Buffer DblNulTermListA_Buffer
# define DblNulTermList_CreateEnum DblNulTermListA_CreateEnum
# define DblNulTermListEnum_Create DblNulTermListEnumA_Create
# define DblNulTermListEnum_Destroy DblNulTermListEnumA_Destroy
# define DblNulTermListEnum_Next DblNulTermListEnumA_Next
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif // INC_DBLNUL_H