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.
 
 
 
 
 
 

5793 lines
105 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
Wrappers.h
Abstract:
Contains some commonly used macros, inline utility functions and
wrapper/helper classes
Author:
Hakki T. Bostanci (hakkib) 06-Apr-2000
Revision History:
--*/
#ifndef _WRAPPERS_H_
#define _WRAPPERS_H_
//////////////////////////////////////////////////////////////////////////
//
// Cross references
//
#include <assert.h>
#include "Conv.h"
#include "Result.h"
//////////////////////////////////////////////////////////////////////////
//
//
//
#ifndef ASSERT
#define ASSERT assert
#endif
typedef CONST TCHAR *PCTSTR;
#if !defined(NDEBUG) || defined(_DEBUG) || defined(DBG)
#ifndef DEBUG
#define DEBUG
#endif //DEBUG
#endif
#ifdef DEBUG
#define IFDEBUG(Statement) Statement
#else //DEBUG
#define IFDEBUG(Statement)
#endif //DEBUG
//////////////////////////////////////////////////////////////////////////
//
// COUNTOF
//
// Returns the number of elements in an array
//
#define COUNTOF(array) ( sizeof(array) / sizeof(array[0]) )
//////////////////////////////////////////////////////////////////////////
//
// STRING
//
// Stringizing operator
//
#define STRING(arg) #arg
//////////////////////////////////////////////////////////////////////////
//
// DISABLE_COPY_CONTRUCTION
//
// Declares copy construction operators as private to prevent outside access
//
#define DISABLE_COPY_CONTRUCTION(Class) \
private: \
Class(const Class&) { } \
Class& operator =(const Class&) { return *this; } \
//////////////////////////////////////////////////////////////////////////
//
// IS_NT
//
// Returns true on an NT based OS
//
#define IS_NT ( GetVersion() < 0x80000000 )
//////////////////////////////////////////////////////////////////////////
//
// LONG_PATH
//
// Returns the \\?\ string (that can be used in file APIs) in UNICODE builds
//
#ifdef UNICODE
#define LONG_PATH L"\\\\?\\"
#else //UNICODE
#define LONG_PATH
#endif //UNICODE
//////////////////////////////////////////////////////////////////////////
//
// AW, _AW
//
// Append a 'W' or 'A' depending on UNICODE or ANSI builds
//
#ifdef UNICODE
#define AW(name) name##W
#define _AW "W"
#else //UNICODE
#define AW(name) name##A
#define _AW "A"
#endif //UNICODE
//////////////////////////////////////////////////////////////////////////
//
// IGNORE_EXCEPTIONS
//
// Ignores any exceptions thrown from the code block
//
#define IGNORE_EXCEPTIONS(Statement) try { Statement; } catch (...) {}
//////////////////////////////////////////////////////////////////////////
//
// WAIT_AND_RETRY_ON_EXCEPTION
//
// Pauses and retries if an exception is thrown from the code block
//
#define WAIT_AND_RETRY_ON_EXCEPTION(func, nRetries, nWaitTime) \
{ \
int nTrials = nRetries; \
\
while (1) \
{ \
try \
{ \
func; \
break; \
} \
catch (...) \
{ \
if (nTrials-- == 0) \
{ \
throw; \
} \
\
Sleep(nWaitTime); \
} \
} \
} \
//////////////////////////////////////////////////////////////////////////
//
// Abs
//
// Returns the absolute value of the variable
//
template <class T>
inline const T Abs(const T& x)
{
return x < 0 ? -x : x;
}
//////////////////////////////////////////////////////////////////////////
//
// Sqr
//
// Returns x^2
//
template <class T>
inline const T Sqr(const T& x)
{
return x * x;
}
//////////////////////////////////////////////////////////////////////////
//
// Cube
//
// Returns x^3
//
template <class T>
inline const T Cube(const T& x)
{
return x * x * x;
}
//////////////////////////////////////////////////////////////////////////
//
// Swap
//
// Swaps the values of two variables
//
template <class T>
inline void Swap(T& x, T& y)
{
T temp = x;
x = y;
y = temp;
}
//////////////////////////////////////////////////////////////////////////
//
// Min
//
// Returns the smaller of the two variables (based on "<" operator)
//
template <class T>
inline const T Min(const T& x, const T& y)
{
return x < y ? x : y;
}
//////////////////////////////////////////////////////////////////////////
//
// Max
//
// Returns the larger of the two variables (based on "<" operator)
//
template <class T>
inline const T Max(const T& x, const T& y)
{
return x < y ? y : x;
}
//////////////////////////////////////////////////////////////////////////
//
// Cmp
//
// Compares two variables (based on "==" and "<" operators)
//
template <class T>
inline int Cmp(const T& x, const T& y)
{
return x == y ? 0 : x < y ? -1 : 1;
}
//////////////////////////////////////////////////////////////////////////
//
// StructCmp
//
// Compares two structs byte by byte
//
template <class T>
inline int StructCmp(const T *x, const T *y)
{
return memcmp(x, y, sizeof(T));
}
//////////////////////////////////////////////////////////////////////////
//
// CopyData
//
// Copies a number of data structures memory from one location to another
// Source and destination blocks should not overlap
//
template <class T>
inline void CopyData(T *x, const T *y, int n)
{
CopyMemory(x, y, n * sizeof(T));
}
//////////////////////////////////////////////////////////////////////////
//
// MoveData
//
// Copies a number of data structures memory from one location to another
// Source and destination blocks may overlap
//
template <class T>
inline void MoveData(T *x, const T *y, int n)
{
MoveMemory(x, y, n * sizeof(T));
}
//////////////////////////////////////////////////////////////////////////
//
// IsEqual
//
// Returns true if the two comperands are equal
//
template <class T>
inline BOOL IsEqual(T lhs, T rhs)
{
return lhs == rhs;
}
template <class T>
inline BOOL IsEqual(const T *lhs, const T *rhs)
{
return *lhs == *rhs;
}
template <>
inline BOOL IsEqual(const CHAR *lhs, const CHAR *rhs)
{
return strcmp(lhs, rhs) == 0;
}
template <>
inline BOOL IsEqual(const WCHAR *lhs, const WCHAR *rhs)
{
return wcscmp(lhs, rhs) == 0;
}
//////////////////////////////////////////////////////////////////////////
//
// CharLower
//
// Converts a single character to lowercase
//
inline TCHAR CharLower(TCHAR c)
{
return (TCHAR) CharLower((PTSTR) c);
}
//////////////////////////////////////////////////////////////////////////
//
// CharUpper
//
// Converts a single character to uppercase
//
inline TCHAR CharUpper(TCHAR c)
{
return (TCHAR) CharUpper((PTSTR) c);
}
//////////////////////////////////////////////////////////////////////////
//
// _tcssafecmp
//
// Compares two strings (that can be null)
//
inline int strsafecmp(PCSTR psz1, PCSTR psz2)
{
return psz1 != 0 ? (psz2 != 0 ? strcmp(psz1, psz2) : 1) : (psz2 != 0 ? -1 : 0);
}
inline int wcssafecmp(PCWSTR psz1, PCWSTR psz2)
{
return psz1 != 0 ? (psz2 != 0 ? wcscmp(psz1, psz2) : 1) : (psz2 != 0 ? -1 : 0);
}
#ifdef UNICODE
#define _tcssafecmp wcssafecmp
#else //UNICODE
#define _tcssafecmp strsafecmp
#endif //UNICODE
//////////////////////////////////////////////////////////////////////////
//
// multiszlen
//
// Returns the length of a null terminated list of null terminated strings
//
inline size_t multiszlenA(PCSTR pszzStr)
{
PCSTR pszStr = pszzStr;
if (pszStr)
{
while (*pszStr)
{
pszStr += strlen(pszStr) + 1;
}
}
return pszStr - pszzStr;
}
inline size_t multiszlenW(PCWSTR pwszzStr)
{
PCWSTR pwszStr = pwszzStr;
if (pwszStr)
{
while (*pwszStr)
{
pwszStr += wcslen(pwszStr) + 1;
}
}
return pwszStr - pwszzStr;
}
#ifdef UNICODE
#define multiszlen multiszlenW
#else //UNICODE
#define multiszlen multiszlenA
#endif //UNICODE
//////////////////////////////////////////////////////////////////////////
//
// FindFileNamePortion
//
// Returns a pointer to the file name portion of a full path name
//
inline PSTR FindFileNamePortionA(PCSTR pPathName)
{
PCSTR pFileName = pPathName ? strrchr(pPathName, '\\') : 0;
return const_cast<PSTR>(pFileName ? pFileName + 1 : pPathName);
}
inline PWSTR FindFileNamePortionW(PCWSTR pPathName)
{
PCWSTR pFileName = pPathName ? wcsrchr(pPathName, '\\') : 0;
return const_cast<PWSTR>(pFileName ? pFileName + 1 : pPathName);
}
#ifdef UNICODE
#define FindFileNamePortion FindFileNamePortionW
#else //UNICODE
#define FindFileNamePortion FindFileNamePortionA
#endif //UNICODE
//////////////////////////////////////////////////////////////////////////
//
// FindEol
//
// Finds the first end-of-line character in a string
//
inline PTSTR FindEol(PCTSTR pStr)
{
while (*pStr != '\0' && *pStr != '\r' && *pStr != '\n')
{
pStr = CharNext(pStr);
}
return const_cast<PTSTR>(pStr);
}
#ifdef _SHLOBJ_H_
//////////////////////////////////////////////////////////////////////////
//
// SHFree
//
// Frees a block of memory allocated through shell's IMalloc interface
//
inline void SHFree(PVOID pVoid)
{
LPMALLOC pMalloc;
SHGetMalloc(&pMalloc);
pMalloc->Free(pVoid);
pMalloc->Release();
}
#endif //_SHLOBJ_H_
//////////////////////////////////////////////////////////////////////////
//
// WriteConsole
//
// Writes a character string to a console screen
//
inline BOOL WriteConsole(PCTSTR pStr, DWORD nStdHandle = STD_OUTPUT_HANDLE)
{
DWORD dwNumWritten;
return WriteConsole(
GetStdHandle(nStdHandle),
pStr,
_tcslen(pStr),
&dwNumWritten,
0
);
}
#ifdef _INC_STDLIB
//////////////////////////////////////////////////////////////////////////
//
// GetEnvironmentInt
//
// Retrieves the value of the specified variable from the environment block
//
inline BOOL GetEnvironmentInt(PCTSTR pName, PINT piValue)
{
TCHAR szValue[48];
DWORD dwResult = GetEnvironmentVariable(pName, szValue, COUNTOF(szValue));
if (dwResult > 0 && dwResult < COUNTOF(szValue))
{
if (piValue == 0)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
*piValue = _ttoi(szValue);
return TRUE;
}
return FALSE;
}
#endif //_INC_STDLIB
#ifdef _INC_STDIO
//////////////////////////////////////////////////////////////////////////
//
// _tcsdupc
//
// Duplicates a string to a buffer allocated by new []
//
inline PTSTR _tcsdupc(PCTSTR pStrSource)
{
if (!pStrSource)
{
pStrSource = _T("");
}
PTSTR pStrDest = new TCHAR[_tcslen(pStrSource) + 1];
if (pStrDest)
{
_tcscpy(pStrDest, pStrSource);
}
return pStrDest;
}
//////////////////////////////////////////////////////////////////////////
//
// bufvprintf, bufprintf
//
// Writes a printf style formatted string to a buffer allocated by new []
//
inline PTSTR bufvprintf(PCTSTR format, va_list arglist)
{
PTSTR pBuffer = 0;
for (
size_t nBufferSize = 1024;
(pBuffer = new TCHAR[nBufferSize]) != 0 &&
_vsntprintf(pBuffer, nBufferSize, format, arglist) < 0;
delete [] pBuffer, nBufferSize *= 2
)
{
// start with a 1KB buffer size
// if buffer allocation fails, exit
// if _vsntprintf succeeds, exit
// otherwise, delete the buffer and retry with double size
}
return pBuffer;
}
inline PTSTR __cdecl bufprintf(PCTSTR format, ...)
{
va_list arglist;
va_start(arglist, format);
return bufvprintf(format, arglist);
}
//////////////////////////////////////////////////////////////////////////
//
// TextOutF
//
// Writes a printf style formatted string to the DC
//
inline BOOL __cdecl TextOutF(HDC hDC, int nX, int nY, PCTSTR format, ...)
{
va_list arglist;
va_start(arglist, format);
BOOL bResult = FALSE;
PTSTR pStr = bufvprintf(format, arglist);
if (pStr)
{
bResult = TextOut(hDC, nX, nY, pStr, _tcslen(pStr));
delete [] pStr;
}
return bResult;
}
//////////////////////////////////////////////////////////////////////////
//
// OutputDebugStringF
//
// Outputs a printf style formatted string to the debug console
//
inline void __cdecl OutputDebugStringF(PCTSTR format, ...)
{
va_list arglist;
va_start(arglist, format);
PTSTR pStr = bufvprintf(format, arglist);
if (pStr)
{
OutputDebugString(pStr);
delete [] pStr;
}
va_end(arglist);
}
#ifdef DEBUG
#define DEBUGMSG(x) OutputDebugString(x)
#define DEBUGMSGF(x) OutputDebugStringF x
#else //DEBUG
#define DEBUGMSG(x)
#define DEBUGMSGF(x)
#endif //DEBUG
//////////////////////////////////////////////////////////////////////////
//
// IsChildWindow
//
// Determines whether the second hWnd is a child of the first
//
inline BOOL IsChildWindow(HWND hWndParent, HWND hWnd)
{
while (hWnd)
{
hWnd = GetParent(hWnd);
if (hWnd == hWndParent)
{
return TRUE;
}
}
return FALSE;
}
#endif //_INC_STDIO
#if defined(_INC_IO) && defined(_INC_FCNTL)
//////////////////////////////////////////////////////////////////////////
//
// OpenOSHandle
//
// Associates a stream with an operating-system file handle
//
inline FILE *OpenOSHandle(HANDLE osfhandle, int flags, PCTSTR mode)
{
int hCrt = _open_osfhandle((intptr_t) osfhandle, flags);
return hCrt ? _tfdopen(hCrt, mode) : 0;
}
//////////////////////////////////////////////////////////////////////////
//
// OpenStdHandle
//
// Assigns a stream to an operating-system file handle for standard I/O
//
inline void OpenStdHandle(HANDLE osfhandle, FILE *stream, PCTSTR mode)
{
*stream = *OpenOSHandle(osfhandle, _O_TEXT, mode);
setvbuf(stream, 0, _IONBF, 0);
}
//////////////////////////////////////////////////////////////////////////
//
// AllocCRTConsole
//
// Allocates a new console and associates standard handles with this console
//
inline void AllocCRTConsole()
{
if (AllocConsole())
{
OpenStdHandle(GetStdHandle(STD_INPUT_HANDLE), stdin, _T("r"));
OpenStdHandle(GetStdHandle(STD_OUTPUT_HANDLE), stdout, _T("w"));
OpenStdHandle(GetStdHandle(STD_ERROR_HANDLE), stderr, _T("w"));
}
}
#endif //defined(_INC_IO) && defined(_INC_FCNTL)
#ifdef _INC_COMMCTRL
//////////////////////////////////////////////////////////////////////////
//
// ListView_InsertColumn2
//
// Inserts a new column in a list view control
//
inline
int
ListView_InsertColumn2(
HWND hWnd,
int nCol,
PCTSTR pszColumnHeading,
int nFormat,
int nWidth,
int nSubItem
)
{
LVCOLUMN column;
column.mask = LVCF_TEXT|LVCF_FMT|LVCF_WIDTH|LVCF_SUBITEM;
column.pszText = (PTSTR) pszColumnHeading;
column.fmt = nFormat;
column.cx = nWidth;
column.iSubItem = nSubItem;
return ListView_InsertColumn(hWnd, nCol, &column);
}
//////////////////////////////////////////////////////////////////////////
//
// ListView_GetItemData
//
// Returns the lParam value associated with a list view item
//
inline
LPARAM
ListView_GetItemData(HWND hWnd, int nItem)
{
LVITEM item;
item.mask = LVIF_PARAM;
item.iItem = nItem;
item.iSubItem = 0;
item.lParam = 0;
ListView_GetItem(hWnd, &item);
return item.lParam;
}
//////////////////////////////////////////////////////////////////////////
//
// ListView_GetItemData
//
// Sets the lParam value associated with a list view item
//
inline
BOOL
ListView_SetItemData(HWND hWnd, int nItem, LPARAM lParam)
{
LVITEM item;
item.mask = LVIF_PARAM;
item.iItem = nItem;
item.iSubItem = 0;
item.lParam = lParam;
return ListView_SetItem(hWnd, &item);
}
//////////////////////////////////////////////////////////////////////////
//
// operator ==, operator !=
//
// Compares two TVITEM structs based on their contents
//
inline bool operator ==(const TVITEM &lhs, const TVITEM &rhs)
{
UINT mask = lhs.mask;
return
mask == rhs.mask &&
(!(mask & TVIF_HANDLE) || lhs.hItem == rhs.hItem) &&
(!(mask & TVIF_STATE) || (lhs.state == rhs.state && lhs.stateMask == rhs.stateMask)) &&
(!(mask & TVIF_TEXT) || (lhs.pszText == rhs.pszText && lhs.cchTextMax == rhs.cchTextMax)) &&
(!(mask & TVIF_IMAGE) || lhs.iImage == rhs.iImage) &&
(!(mask & TVIF_SELECTEDIMAGE) || lhs.iSelectedImage == rhs.iSelectedImage) &&
(!(mask & TVIF_CHILDREN) || lhs.cChildren == rhs.cChildren) &&
(!(mask & TVIF_PARAM) || lhs.lParam == rhs.lParam);
}
inline bool operator !=(const TVITEM &lhs, const TVITEM &rhs)
{
return !(lhs == rhs);
}
#endif //_INC_COMMCTRL
//////////////////////////////////////////////////////////////////////////
//
// ResizeDlgItem
//
// Changes the relative position and size of a dialog item
//
inline
BOOL
ResizeDlgItem(
HWND hWnd,
HWND hDlgItem,
int dX,
int dY,
int dW,
int dH,
BOOL bRepaint = TRUE
)
{
RECT r;
return
GetWindowRect(hDlgItem, &r) &&
ScreenToClient(hWnd, (PPOINT) &r.left) &&
ScreenToClient(hWnd, (PPOINT) &r.right) &&
MoveWindow(
hDlgItem,
r.left + dX,
r.top + dY,
r.right - r.left + dW,
r.bottom - r.top + dH,
bRepaint
);
}
//////////////////////////////////////////////////////////////////////////
//
// CLargeInteger
//
class CLargeInteger // union cannot be used as a base class
{
public:
CLargeInteger(
DWORD LowPart,
LONG HighPart
)
{
m_Int.LowPart = LowPart;
m_Int.HighPart = HighPart;
}
CLargeInteger(
LONGLONG QuadPart
)
{
m_Int.QuadPart = QuadPart;
}
CLargeInteger(
const LARGE_INTEGER& rhs
)
{
m_Int.QuadPart = rhs.QuadPart;
}
LARGE_INTEGER * operator &()
{
return &m_Int;
}
const LARGE_INTEGER * operator &() const
{
return &m_Int;
}
operator LONGLONG&()
{
return m_Int.QuadPart;
}
operator const LONGLONG&() const
{
return m_Int.QuadPart;
}
private:
LARGE_INTEGER m_Int;
};
//////////////////////////////////////////////////////////////////////////
//
// CULargeInteger
//
class CULargeInteger // union cannot be used as a base class
{
public:
CULargeInteger(
DWORD LowPart,
DWORD HighPart
)
{
m_Int.LowPart = LowPart;
m_Int.HighPart = HighPart;
}
CULargeInteger(
ULONGLONG QuadPart
)
{
m_Int.QuadPart = QuadPart;
}
CULargeInteger(
const ULARGE_INTEGER& rhs
)
{
m_Int.QuadPart = rhs.QuadPart;
}
ULARGE_INTEGER * operator &()
{
return &m_Int;
}
const ULARGE_INTEGER * operator &() const
{
return &m_Int;
}
operator ULONGLONG&()
{
return m_Int.QuadPart;
}
operator const ULONGLONG&() const
{
return m_Int.QuadPart;
}
private:
ULARGE_INTEGER m_Int;
};
//////////////////////////////////////////////////////////////////////////
//
// CFileTime
//
class CFileTime : public FILETIME
{
public:
CFileTime()
{
}
CFileTime(ULONGLONG Value)
{
((ULARGE_INTEGER *)this)->QuadPart = Value;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CHandle
//
// Base class that handles reference counting
//
template <class T, class Child>
class CHandle
{
public:
CHandle()
{
m_pNext = 0;
}
explicit CHandle(const T &Value)
{
m_pNext = 0;
Attach(Value);
}
CHandle(CHandle &rhs)
{
m_pNext = 0;
Attach(rhs);
}
CHandle & operator =(const T &Value)
{
Detach();
Attach(Value);
return *this;
}
CHandle & operator =(CHandle &rhs)
{
if (&rhs != this)
{
Detach();
Attach(rhs);
}
return *this;
}
~CHandle()
{
Detach();
}
operator const T &() const
{
return m_Value;
}
// void Destroy()
// {
// must be defined in the derived class
// }
// bool IsValid()
// {
// must be defined in the derived class
// }
void Attach(const T &Value)
{
ASSERT(!IsAttached());
m_Value = Value;
CHECK(((Child *)this)->IsValid());
m_pNext = this;
m_pPrev = this;
}
void Attach(CHandle &rhs)
{
ASSERT(!IsAttached());
if (rhs.IsAttached())
{
m_Value = rhs.m_Value;
m_pPrev = &rhs;
m_pNext = rhs.m_pNext;
m_pPrev->m_pNext = this;
m_pNext->m_pPrev = this;
}
}
void Detach()
{
if (IsLastReference())
{
((Child *)this)->Destroy();
m_pNext = 0;
}
else
{
Unlink();
}
}
void Unlink()
{
if (IsAttached())
{
m_pPrev->m_pNext = m_pNext;
m_pNext->m_pPrev = m_pPrev;
m_pNext = 0;
}
}
bool IsLastReference() const
{
return m_pNext == this;
}
bool IsAttached() const
{
return m_pNext != 0;
}
private:
T m_Value;
CHandle *m_pNext;
CHandle *m_pPrev;
};
//////////////////////////////////////////////////////////////////////////
//
// CKernelObject
//
// Base class for kernel objects that can be destroyed with CloseHandle()
//
template <class Child>
class CKernelObject : public CHandle<HANDLE, Child>
{
typedef CHandle<HANDLE, Child> parent_type;
protected:
CKernelObject()
{
}
explicit
CKernelObject(
HANDLE hHandle
) :
parent_type(hHandle)
{
}
public:
void Destroy()
{
::CloseHandle(*this);
}
bool IsValid()
{
return *this != 0;
}
DWORD
WaitForSingleObject(
DWORD dwMilliseconds = INFINITE,
BOOL bAlertable = FALSE
) const
{
return ::WaitForSingleObjectEx(
*this,
dwMilliseconds,
bAlertable
);
}
bool IsSignaled() const
{
return WaitForSingleObject(0) == WAIT_OBJECT_0;
}
};
//////////////////////////////////////////////////////////////////////////
//
// File
//
// Wrapper class for Win32 file handles
//
class File : public CKernelObject<File>
{
public:
File()
{
}
File(
PCTSTR pFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES pSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
HANDLE hTemplateFile = 0
) :
CKernelObject<File>(::CreateFile(
pFileName,
dwDesiredAccess,
dwShareMode,
pSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile
))
{
}
bool IsValid()
{
return (HANDLE) *this != INVALID_HANDLE_VALUE;
}
LARGE_INTEGER
GetFileSize() const
{
LARGE_INTEGER Result;
Result.LowPart = ::GetFileSize(
*this,
(PDWORD) &Result.HighPart
);
return Result;
}
DWORD
WriteFile(
CONST VOID *pBuffer,
DWORD nNumberOfBytesToWrite,
LPOVERLAPPED pOverlapped = 0
) const
{
DWORD dwNumberOfBytesWritten;
CHECK(::WriteFile(
*this,
pBuffer,
nNumberOfBytesToWrite,
&dwNumberOfBytesWritten,
pOverlapped
));
return dwNumberOfBytesWritten;
}
DWORD
ReadFile(
PVOID pBuffer,
DWORD nNumberOfBytesToRead,
LPOVERLAPPED pOverlapped = 0
) const
{
DWORD dwNumberOfBytesRead;
CHECK(::ReadFile(
*this,
pBuffer,
nNumberOfBytesToRead,
&dwNumberOfBytesRead,
pOverlapped
));
return dwNumberOfBytesRead;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CInFile
//
// Read only file
//
class CInFile : public File
{
public:
CInFile()
{
}
explicit
CInFile(
PCTSTR pFileName,
DWORD dwDesiredAccess = GENERIC_READ,
DWORD dwShareMode = FILE_SHARE_READ,
LPSECURITY_ATTRIBUTES pSecurityAttributes = 0,
DWORD dwCreationDisposition = OPEN_EXISTING,
DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
HANDLE hTemplateFile = 0
) :
File(
pFileName,
dwDesiredAccess,
dwShareMode,
pSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile
)
{
}
};
//////////////////////////////////////////////////////////////////////////
//
// COutFile
//
// Write only file
//
class COutFile : public File
{
public:
COutFile()
{
}
explicit
COutFile(
PCTSTR pFileName,
DWORD dwDesiredAccess = GENERIC_WRITE,
DWORD dwShareMode = FILE_SHARE_READ,
LPSECURITY_ATTRIBUTES pSecurityAttributes = 0,
DWORD dwCreationDisposition = CREATE_ALWAYS,
DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
HANDLE hTemplateFile = 0
) :
File(
pFileName,
dwDesiredAccess,
dwShareMode,
pSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile
)
{
}
};
//////////////////////////////////////////////////////////////////////////
//
// CopyFileContents
//
// Copies the contents of one file to another
//
inline void CopyFileContents(const File &InFile, const File &OutFile)
{
BYTE Buffer[32*1024];
DWORD nNumRead;
do
{
nNumRead = InFile.ReadFile(Buffer, sizeof(Buffer));
OutFile.WriteFile(Buffer, nNumRead);
}
while (nNumRead == sizeof(Buffer));
}
#ifdef _INC_STDIO
#include <share.h>
//////////////////////////////////////////////////////////////////////////
//
// CCFile
//
// Wrapper class for C-runtime stream based file handles
//
class CCFile : public CHandle<FILE *, CCFile>
{
typedef CHandle<FILE *, CCFile> parent_type;
public:
CCFile()
{
}
CCFile(
PCTSTR filename,
PCTSTR mode,
int shflag = _SH_DENYNO
) :
parent_type(::_tfsopen(
filename,
mode,
shflag
))
{
}
void Destroy()
{
::fclose(*this);
}
bool IsValid()
{
return *this != 0;
}
};
#endif _INC_STDIO
//////////////////////////////////////////////////////////////////////////
//
// CNamedPipe
//
// Wrapper class for named pipes
//
class CNamedPipe : public File
{
public:
CNamedPipe()
{
}
CNamedPipe(
PCTSTR pName,
DWORD dwOpenMode,
DWORD dwPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
DWORD nMaxInstances = PIPE_UNLIMITED_INSTANCES,
DWORD nOutBufferSize = 0,
DWORD nInBufferSize = 0,
DWORD nDefaultTimeOut = INFINITE,
LPSECURITY_ATTRIBUTES pSecurityAttributes = 0
)
{
Attach(::CreateNamedPipe(
pName,
dwOpenMode,
dwPipeMode,
nMaxInstances,
nOutBufferSize,
nInBufferSize,
nDefaultTimeOut,
pSecurityAttributes
));
}
};
//////////////////////////////////////////////////////////////////////////
//
// CFileMapping
//
// Wrapper class for file mapping objects
//
class CFileMapping : public CKernelObject<CFileMapping>
{
public:
CFileMapping()
{
}
CFileMapping(
HANDLE hFile,
LPSECURITY_ATTRIBUTES pFileMappingAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh = 0,
DWORD dwMaximumSizeLow = 0,
PCTSTR pName = 0
) :
CKernelObject<CFileMapping>(::CreateFileMapping(
hFile,
pFileMappingAttributes,
flProtect,
dwMaximumSizeHigh,
dwMaximumSizeLow,
pName
))
{
}
};
#ifdef _LZEXPAND_
//////////////////////////////////////////////////////////////////////////
//
// CLZFile
//
// Wrapper class for LZ compressed files
//
class CLZFile : public CHandle<INT, CLZFile>
{
typedef CHandle<INT, CLZFile> parent_type;
public:
CLZFile(
PTSTR pFileName,
WORD wStyle
) :
parent_type(::LZOpenFile(
pFileName,
&m_of,
wStyle
))
{
}
void Destroy()
{
::LZClose(*this);
}
bool IsValid()
{
return *this >= 0;
}
private:
OFSTRUCT m_of;
};
#endif _LZEXPAND_
//////////////////////////////////////////////////////////////////////////
//
// CStartupInfo
//
// Wrapper class for the STARTUPINFO struct
//
class CStartupInfo : public STARTUPINFO
{
public:
CStartupInfo()
{
ZeroMemory(this, sizeof(STARTUPINFO));
cb = sizeof(STARTUPINFO);
}
void
UseStdHandles(
HANDLE _hStdInput = GetStdHandle(STD_INPUT_HANDLE),
HANDLE _hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE),
HANDLE _hStdError = GetStdHandle(STD_ERROR_HANDLE)
)
{
dwFlags |= STARTF_USESTDHANDLES;
hStdInput = _hStdInput;
hStdOutput = _hStdOutput;
hStdError = _hStdError;
}
void
UseShowWindow(WORD _wShowWindow)
{
dwFlags |= STARTF_USESHOWWINDOW;
wShowWindow = _wShowWindow;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CProcess
//
// Wrapper class for process handles
//
class CProcess : public CHandle<PROCESS_INFORMATION, CProcess>
{
public:
CProcess()
{
}
explicit
CProcess(
PTSTR pCommandLine,
PSECURITY_ATTRIBUTES pProcessAttributes = 0,
PSECURITY_ATTRIBUTES pThreadAttributes = 0,
BOOL bInheritHandles = FALSE,
DWORD dwCreationFlags = 0,
PVOID pEnvironment = 0,
PCTSTR pCurrentDirectory = 0,
LPSTARTUPINFO psi = &CStartupInfo()
)
{
PROCESS_INFORMATION pi;
CHECK(::CreateProcess(
0,
pCommandLine,
pProcessAttributes,
pThreadAttributes,
bInheritHandles,
dwCreationFlags,
pEnvironment,
pCurrentDirectory,
psi,
&pi
));
Attach(pi);
}
CProcess(
HANDLE hToken,
PTSTR pCommandLine,
PSECURITY_ATTRIBUTES pProcessAttributes = 0,
PSECURITY_ATTRIBUTES pThreadAttributes = 0,
BOOL bInheritHandles = FALSE,
DWORD dwCreationFlags = 0,
PVOID pEnvironment = 0,
PCTSTR pCurrentDirectory = 0,
LPSTARTUPINFO psi = &CStartupInfo()
)
{
PROCESS_INFORMATION pi;
CHECK(::CreateProcessAsUser(
hToken,
0,
pCommandLine,
pProcessAttributes,
pThreadAttributes,
bInheritHandles,
dwCreationFlags,
pEnvironment,
pCurrentDirectory,
psi,
&pi
));
Attach(pi);
}
#if (_WIN32_WINNT >= 0x0500) && defined(UNICODE)
CProcess(
PCWSTR pUsername,
PCWSTR pDomain,
PCWSTR pPassword,
DWORD dwLogonFlags,
PWSTR pCommandLine,
DWORD dwCreationFlags = 0,
PVOID pEnvironment = 0,
PCWSTR pCurrentDirectory = 0,
LPSTARTUPINFO psi = &CStartupInfo()
)
{
PROCESS_INFORMATION pi;
CHECK(::CreateProcessWithLogonW(
pUsername,
pDomain,
pPassword,
dwLogonFlags,
0,
pCommandLine,
dwCreationFlags,
pEnvironment,
pCurrentDirectory,
psi,
&pi
));
Attach(pi);
}
#endif
void Destroy()
{
::CloseHandle(((PROCESS_INFORMATION &)(*this)).hThread);
::CloseHandle(((PROCESS_INFORMATION &)(*this)).hProcess);
}
bool IsValid()
{
return ((PROCESS_INFORMATION &)(*this)).hProcess != 0;
}
DWORD
WaitForInputIdle(
DWORD dwMilliseconds = INFINITE
) const
{
return ::WaitForInputIdle(
((PROCESS_INFORMATION &)(*this)).hProcess,
dwMilliseconds
);
}
DWORD
WaitForSingleObject(
DWORD dwMilliseconds = INFINITE
) const
{
return ::WaitForSingleObject(
((PROCESS_INFORMATION &)(*this)).hProcess,
dwMilliseconds
);
}
VOID
Terminate(
DWORD dwExitCode = 0
) const
{
CHECK(::TerminateProcess(
((PROCESS_INFORMATION &)(*this)).hProcess,
dwExitCode
));
}
DWORD
GetExitCode() const
{
DWORD dwExitCode;
CHECK(::GetExitCodeProcess(
((PROCESS_INFORMATION &)(*this)).hProcess,
&dwExitCode
));
return dwExitCode;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CThreadBase
//
// Base class for Win32 and CRT library style thread objects
//
class CThreadBase : public CKernelObject<CThreadBase>
{
protected:
CThreadBase()
{
}
explicit
CThreadBase(
HANDLE hHandle
) :
CKernelObject<CThreadBase>(hHandle)
{
}
public:
operator DWORD() const
{
return m_dwThreadId;
}
VOID
Terminate(
DWORD dwExitCode = 0
) const
{
CHECK(::TerminateThread(
*this,
dwExitCode
));
}
DWORD
GetExitCode() const
{
DWORD dwExitCode;
CHECK(::GetExitCodeThread(
*this,
&dwExitCode
));
return dwExitCode;
}
protected:
DWORD m_dwThreadId;
};
//////////////////////////////////////////////////////////////////////////
//
// CThread
//
// Wrapper class for Win32 thread handles
//
class CThread : public CThreadBase
{
public:
CThread()
{
}
explicit
CThread(
PTHREAD_START_ROUTINE pStartAddress,
PVOID pParameter = 0,
PSECURITY_ATTRIBUTES pThreadAttributes = 0,
DWORD dwStackSize = 0,
DWORD dwCreationFlags = 0
) :
CThreadBase(::CreateThread(
pThreadAttributes,
dwStackSize,
pStartAddress,
pParameter,
dwCreationFlags,
&m_dwThreadId
))
{
}
};
#ifdef _INC_PROCESS
//////////////////////////////////////////////////////////////////////////
//
// CCThread
//
// Wrapper class for C-runtime threads
//
class CCThread : public CThreadBase
{
public:
CCThread()
{
}
explicit
CCThread(
unsigned ( __stdcall *start_address )( void * ),
void *arglist = 0,
void *security = 0,
unsigned stack_size = 0,
unsigned initflag = 0
) :
CThreadBase((HANDLE)(LONG_PTR) _beginthreadex(
security,
stack_size,
start_address,
arglist,
initflag,
(unsigned int *) &m_dwThreadId
))
{
}
};
#endif //_INC_PROCESS
//////////////////////////////////////////////////////////////////////////
//
// Event
//
// Wrapper class for event handles
//
class Event : public CKernelObject<Event>
{
public:
Event()
{
}
Event(
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName = 0,
LPSECURITY_ATTRIBUTES lpEventAttributes = 0
) :
CKernelObject<Event>(::CreateEvent(
lpEventAttributes,
bManualReset,
bInitialState,
lpName
))
{
}
public:
VOID
Set() const
{
CHECK(::SetEvent(*this));
}
VOID
Reset() const
{
CHECK(::ResetEvent(*this));
}
};
//////////////////////////////////////////////////////////////////////////
//
// Mutex
//
// Wrapper class for mutex handles
//
class Mutex : public CKernelObject<Mutex>
{
public:
Mutex()
{
}
explicit
Mutex(
BOOL bInitialOwner,
PCTSTR pName = 0,
PSECURITY_ATTRIBUTES pMutexAttributes = 0
) :
CKernelObject<Mutex>(::CreateMutex(
pMutexAttributes,
bInitialOwner,
pName
))
{
}
public:
VOID
Release() const
{
CHECK(::ReleaseMutex(*this));
}
};
//////////////////////////////////////////////////////////////////////////
//
// Semaphore
//
// Wrapper class for semaphore handles
//
class Semaphore : public CKernelObject<Semaphore>
{
public:
Semaphore()
{
}
Semaphore(
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName = 0,
LPSECURITY_ATTRIBUTES lpEventAttributes = 0
) :
CKernelObject<Semaphore>(::CreateSemaphore(
lpEventAttributes,
lInitialCount,
lMaximumCount,
lpName
))
{
}
public:
VOID
Release(
LONG lReleaseCount = 1,
PLONG pPreviousCount = 0
) const
{
CHECK(::ReleaseSemaphore(*this, lReleaseCount, pPreviousCount));
}
VOID
WaitFor(
LONG lCount
) const
{
for (int i = 0; i < lCount; ++i)
{
WaitForSingleObject();
}
Release(lCount);
}
};
#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
//////////////////////////////////////////////////////////////////////////
//
// CWaitableTimer
//
// Wrapper class for waitable timer handles
//
class CWaitableTimer : public CKernelObject<CWaitableTimer>
{
public:
CWaitableTimer()
{
}
explicit
CWaitableTimer(
BOOL bManualReset,
PCTSTR pTimerName = 0,
PSECURITY_ATTRIBUTES pTimerAttributes = 0
) :
CKernelObject<CWaitableTimer>(::CreateWaitableTimer(
pTimerAttributes,
bManualReset,
pTimerName
))
{
}
public:
VOID
Set(
const CLargeInteger &DueTime,
LONG lPeriod = 0,
PTIMERAPCROUTINE pfnCompletionRoutine = 0,
LPVOID lpArgToCompletionRoutine = 0,
BOOL fResume = FALSE
) const
{
CHECK(::SetWaitableTimer(
*this,
&DueTime,
lPeriod,
pfnCompletionRoutine,
lpArgToCompletionRoutine,
fResume
));
}
VOID
Cancel() const
{
CHECK(::CancelWaitableTimer(*this));
}
};
#endif
//////////////////////////////////////////////////////////////////////////
//
// CriticalSection
//
// Wrapper class for critical sections
//
class CriticalSection : private CRITICAL_SECTION
{
public:
CriticalSection()
{
::InitializeCriticalSection(this);
}
~CriticalSection()
{
::DeleteCriticalSection(this);
}
#if _WIN32_WINNT >= 0x0400
BOOL
TryEnter()
{
return ::TryEnterCriticalSection(this);
}
#endif //_WIN32_WINNT >= 0x0400
VOID
Enter()
{
::EnterCriticalSection(this);
}
VOID
Leave()
{
::LeaveCriticalSection(this);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CLibrary
//
// Wrapper class for loading DLL's
//
class CLibrary : public CHandle<HINSTANCE, CLibrary>
{
typedef CHandle<HINSTANCE, CLibrary> parent_type;
public:
CLibrary()
{
}
explicit
CLibrary(
PCTSTR pLibFileName,
DWORD dwFlags = 0
) :
parent_type(::LoadLibraryEx(pLibFileName, 0, dwFlags))
{
}
void Destroy()
{
::FreeLibrary(*this);
}
bool IsValid()
{
return *this != 0;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CPointer
//
// Base class for pointer wrappers
//
#pragma warning(4: 4284) // return type for 'identifier::operator ->()' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
template <class T, class Child>
class CPointer : public CHandle<T *, Child >
{
typedef CHandle<T *, Child> parent_type;
typedef T *pointer_type;
public:
CPointer()
{
}
CPointer(
const T *pPointer
) :
parent_type((pointer_type) pPointer)
{
}
CPointer & operator =(const T *pPointer)
{
return (CPointer &) parent_type::operator =((pointer_type) pPointer);
}
T * operator ->()
{
return *this;
}
bool IsValid()
{
return *this != 0;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CCppMem
//
// Wrapper class for allocations through C++ new[] and delete[] operators
//
template <class T>
class CCppMem : public CPointer<T, CCppMem<T> >
{
typedef CPointer<T, CCppMem<T> > parent_type;
public:
CCppMem()
{
}
CCppMem(
const T *pPointer
) :
parent_type(pPointer)
{
}
explicit
CCppMem(
size_t nSize,
BOOL bZeroInit = FALSE
) :
parent_type(new T[nSize])
{
if (bZeroInit)
{
ZeroMemory(*this, sizeof(T) * nSize);
}
}
// bugbug: why isn't this inherited?
CCppMem & operator =(const T *pPointer)
{
return (CCppMem &) parent_type::operator =(pPointer);
}
void Destroy()
{
delete [] *this;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CGlobalMem
//
// Wrapper class for allocations through GlobalAlloc() GlobalFree() APIs
//
template <class T>
class CGlobalMem : public CPointer<T, CGlobalMem<T> >
{
typedef CPointer<T, CGlobalMem<T> > parent_type;
public:
CGlobalMem()
{
}
CGlobalMem(
const T *pPointer
) :
parent_type(pPointer)
{
}
explicit
CGlobalMem(
DWORD dwBytes,
UINT uFlags = GMEM_FIXED
) :
parent_type((T *) ::GlobalAlloc(uFlags, dwBytes))
{
}
// bugbug: why isn't this inherited?
CGlobalMem & operator =(const T *pPointer)
{
return (CGlobalMem &) parent_type::operator =(pPointer);
}
void Destroy()
{
::GlobalFree(*this);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CLocalMem
//
// Wrapper class for allocations through LocalAlloc() LocalFree() APIs
//
template <class T>
class CLocalMem : public CPointer<T, CLocalMem<T> >
{
typedef CPointer<T, CLocalMem<T> > parent_type;
public:
CLocalMem()
{
}
CLocalMem(
const T *pPointer
) :
parent_type(pPointer)
{
}
explicit
CLocalMem(
DWORD dwBytes,
UINT uFlags = LMEM_FIXED
) :
parent_type((T *) ::LocalAlloc(uFlags, dwBytes))
{
}
// bugbug: why isn't this inherited?
CLocalMem & operator =(const T *pPointer)
{
return (CLocalMem &) parent_type::operator =(pPointer);
}
void Destroy()
{
::LocalFree(*this);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CMapViewOfFile
//
// Wrapper class for memory mapped file objects
//
template <class T>
class CMapViewOfFile : public CPointer<T, CMapViewOfFile<T> >
{
public:
CMapViewOfFile()
{
}
CMapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh = 0,
DWORD dwFileOffsetLow = 0,
DWORD dwNumberOfBytesToMap = 0,
PVOID pBaseAddress = 0
) :
CPointer<T, CMapViewOfFile<T> >((T *) ::MapViewOfFileEx(
hFileMappingObject,
dwDesiredAccess,
dwFileOffsetHigh,
dwFileOffsetLow,
dwNumberOfBytesToMap,
pBaseAddress
))
{
}
void Destroy()
{
::UnmapViewOfFile(*this);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CMapFile
//
// Helper class for CreateFile(), CreateNamedPipe() and MapViewOfFileEx() APIs
//
// bugbug: these should be defined in class scope, but vc5 doesn't let me...
template <int> struct mapping_traits { };
template <> struct mapping_traits<FILE_MAP_READ>
{
enum
{
dwDesiredAccess = GENERIC_READ,
dwShareMode = FILE_SHARE_READ,
flProtect = PAGE_READONLY,
dwDesiredMapAccess = FILE_MAP_READ
};
};
template <> struct mapping_traits<FILE_MAP_WRITE>
{
enum
{
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE,
dwShareMode = 0,
flProtect = PAGE_READWRITE,
dwDesiredMapAccess = FILE_MAP_WRITE
};
};
template <> struct mapping_traits<FILE_MAP_COPY>
{
enum
{
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE,
dwShareMode = FILE_SHARE_READ,
flProtect = PAGE_WRITECOPY,
dwDesiredMapAccess = FILE_MAP_COPY
};
};
template <class T, int Access>
class CMapFile
{
public:
CMapFile(
PCTSTR pFileName
) :
m_File(
pFileName, // PCTSTR pFileName
mapping_traits<Access>::dwDesiredAccess, // DWORD dwDesiredAccess
mapping_traits<Access>::dwShareMode, // DWORD dwShareMode
0, // LPSECURITY_ATTRIBUTES
OPEN_EXISTING, // DWORD dwCreationDisposition
FILE_ATTRIBUTE_NORMAL, // DWORD dwFlagsAndAttributes
0 // HANDLE hTemplateFile
),
m_Mapping(
m_File, // HANDLE hFile
0, // LPSECURITY_ATTRIBUTES
mapping_traits<Access>::flProtect, // DWORD flProtect
0, // DWORD dwMaximumSizeHigh
0, // DWORD dwMaximumSizeLow
0 // PCTSTR pName
),
m_ViewOfFile(
m_Mapping, // HANDLE hFileMappingObject
mapping_traits<Access>::dwDesiredMapAccess, // DWORD dwDesiredAccess
0, // DWORD dwFileOffsetHigh
0, // DWORD dwFileOffsetLow
0, // DWORD dwNumberOfBytesToMap
0 // PVOID pBaseAddress
)
{
}
operator T *()
{
return m_ViewOfFile;
}
private:
File m_File;
CFileMapping m_Mapping;
CMapViewOfFile<T> m_ViewOfFile;
};
//////////////////////////////////////////////////////////////////////////
//
// CSecurityDescriptor
//
// Wrapper class for SECURITY_DESCRIPTOR struct
//
class CSecurityDescriptor : public CCppMem<SECURITY_DESCRIPTOR>
{
public:
explicit
CSecurityDescriptor(
BOOL bDaclPresent = TRUE,
PACL pDacl = 0,
BOOL bDaclDefaulted = FALSE
) :
CCppMem<SECURITY_DESCRIPTOR>(SECURITY_DESCRIPTOR_MIN_LENGTH)
{
CHECK(::InitializeSecurityDescriptor(
*this,
SECURITY_DESCRIPTOR_REVISION
));
CHECK(::SetSecurityDescriptorDacl(
*this,
bDaclPresent,
pDacl,
bDaclDefaulted
));
}
};
//////////////////////////////////////////////////////////////////////////
//
// CSecurityAttributes
//
// Wrapper class for the SECURITY_ATTRIBUTES struct
//
class CSecurityAttributes : public SECURITY_ATTRIBUTES
{
public:
explicit
CSecurityAttributes(
PSECURITY_DESCRIPTOR pSD,
BOOL bInheritHandle = TRUE
)
{
nLength = sizeof(SECURITY_ATTRIBUTES);
lpSecurityDescriptor = pSD;
bInheritHandle = bInheritHandle;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CTokenPrivileges
//
// Wrapper class for the TOKEN_PRIVILEGES struct
//
#include <pshpack1.h>
template <int N>
struct CTokenPrivileges : public TOKEN_PRIVILEGES
{
CTokenPrivileges()
{
PrivilegeCount = N;
}
LUID_AND_ATTRIBUTES & operator [](int i)
{
ASSERT(i < N);
return Privileges[i];
}
private:
LUID_AND_ATTRIBUTES RemainingPrivileges[N - ANYSIZE_ARRAY];
};
#include <poppack.h>
//////////////////////////////////////////////////////////////////////////
//
// CLuid
//
// Wrapper class for the LUID struct
//
struct CLuid : public LUID
{
CLuid(
LPCTSTR lpSystemName,
LPCTSTR lpName
)
{
CHECK(::LookupPrivilegeValue(
lpSystemName,
lpName,
this
));
}
};
//////////////////////////////////////////////////////////////////////////
//
// CLuidAndAttributes
//
// Wrapper class for the LUID_AND_ATTRIBUTES struct
//
struct CLuidAndAttributes : public LUID_AND_ATTRIBUTES
{
CLuidAndAttributes(
const LUID& _Luid,
DWORD _Attributes
)
{
Luid = _Luid;
Attributes = _Attributes;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CProcessToken
//
// Wrapper class for the process token object
//
class CProcessToken : public CKernelObject<CProcessToken>
{
public:
CProcessToken()
{
}
CProcessToken(
HANDLE ProcessHandle,
DWORD DesiredAccess
)
{
HANDLE hHandle;
CHECK(::OpenProcessToken(
ProcessHandle,
DesiredAccess,
&hHandle
));
Attach(hHandle);
}
VOID
AdjustTokenPrivileges(
BOOL DisableAllPrivileges,
PTOKEN_PRIVILEGES NewState,
DWORD BufferLength = 0,
PTOKEN_PRIVILEGES PreviousState = 0,
PDWORD ReturnLength = 0
) const
{
CHECK(::AdjustTokenPrivileges(
*this,
DisableAllPrivileges,
NewState,
BufferLength,
PreviousState,
ReturnLength
));
CHECK(GetLastError() == ERROR_SUCCESS);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CLoggedOnUser
//
// Wrapper class for the logged on user object
//
class CLoggedOnUser : public CKernelObject<CLoggedOnUser>
{
public:
CLoggedOnUser()
{
}
CLoggedOnUser(
LPTSTR lpszUsername,
LPTSTR lpszDomain,
LPTSTR lpszPassword,
DWORD dwLogonType = LOGON32_LOGON_INTERACTIVE,
DWORD dwLogonProvider = LOGON32_PROVIDER_DEFAULT
)
{
HANDLE hHandle;
CHECK(::LogonUser(
lpszUsername,
lpszDomain,
lpszPassword,
dwLogonType,
dwLogonProvider,
&hHandle
));
Attach(hHandle);
}
VOID
Impersonate() const
{
CHECK(::ImpersonateLoggedOnUser(*this));
}
};
//////////////////////////////////////////////////////////////////////////
//
// CEventSource
//
// Wrapper class for the event source object
//
class CEventSource : public CHandle<HANDLE, CEventSource>
{
typedef CHandle<HANDLE, CEventSource> parent_type;
public:
CEventSource()
{
}
CEventSource(
PCTSTR pUNCServerName,
PCTSTR pSourceName
) :
parent_type(::RegisterEventSource(
pUNCServerName,
pSourceName
))
{
}
void Destroy()
{
::DeregisterEventSource(*this);
}
bool IsValid()
{
return *this != 0;
}
VOID
ReportEvent(
WORD wType,
WORD wCategory,
DWORD dwEventID,
PSID lpUserSid,
WORD wNumStrings,
DWORD dwDataSize,
PCTSTR *pStrings,
PVOID pRawData
) const
{
CHECK(::ReportEvent(
*this,
wType,
wCategory,
dwEventID,
lpUserSid,
wNumStrings,
dwDataSize,
pStrings,
pRawData
));
}
VOID
ReportEventText(
WORD wType,
PCTSTR pString,
DWORD dwEventID
) const
{
PCTSTR pStrings[] = { pString };
ReportEvent(
wType,
0,
dwEventID,
0,
1,
0,
pStrings,
0
);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CKey
//
// Wrapper class for registry key objects and registry APIs
//
class CKey : public CHandle<HKEY, CKey>
{
public:
CKey()
{
}
CKey(
HKEY hKey
)
{
Attach(hKey);
}
CKey(
HKEY hKey,
PCTSTR pSubKey,
REGSAM samDesired = KEY_ALL_ACCESS
)
{
HKEY hHandle;
CHECK_REG(::RegOpenKeyEx(
hKey,
pSubKey,
0,
samDesired,
&hHandle
));
Attach(hHandle);
}
CKey(
PCTSTR pMachineName,
HKEY hKey
)
{
HKEY hHandle;
CHECK_REG(::RegConnectRegistry(
pMachineName,
hKey,
&hHandle
));
Attach(hHandle);
}
CKey(
HKEY hKey,
PCTSTR pSubKey,
PTSTR pClass,
DWORD dwOptions,
REGSAM samDesired = KEY_ALL_ACCESS,
PSECURITY_ATTRIBUTES pSecurityAttributes = 0
)
{
HKEY hHandle;
DWORD dwDisposition;
CHECK_REG(::RegCreateKeyEx(
hKey,
pSubKey,
0,
pClass,
dwOptions,
samDesired,
pSecurityAttributes,
&hHandle,
&dwDisposition
));
Attach(hHandle);
}
void Destroy()
{
::RegCloseKey(*this);
}
bool IsValid()
{
return *this != 0;
}
VOID
RegQueryValueEx(
PTSTR pValueName,
PDWORD pType,
PVOID pData,
PDWORD pcbData
) const
{
CHECK_REG(::RegQueryValueEx(
*this,
pValueName,
0,
pType,
(PBYTE) pData,
pcbData
));
}
VOID
RegSetValueEx(
PTSTR pValueName,
DWORD dwType,
CONST VOID *pData,
DWORD cbData
) const
{
CHECK_REG(::RegSetValueEx(
*this,
pValueName,
0,
dwType,
(PBYTE) pData,
cbData
));
}
BOOL
RegEnumKeyEx(
DWORD dwIndex,
PTSTR pName,
PDWORD pcbName,
PTSTR pClass = 0,
PDWORD pcbClass = 0,
PFILETIME pftLastWriteTime = 0
) const
{
LONG bResult = ::RegEnumKeyEx(
*this,
dwIndex,
pName,
pcbName,
0,
pClass,
pcbClass,
pftLastWriteTime
);
if (bResult == ERROR_NO_MORE_ITEMS)
{
return FALSE;
}
CHECK_REG(bResult);
return TRUE;
}
BOOL
RegEnumValue(
DWORD dwIndex,
PTSTR pValueName,
PDWORD pcbValueName,
PDWORD pType,
PBYTE pData,
PDWORD pcbData
) const
{
LONG bResult = ::RegEnumValue(
*this,
dwIndex,
pValueName,
pcbValueName,
0,
pType,
pData,
pcbData
);
if (bResult == ERROR_NO_MORE_ITEMS)
{
return FALSE;
}
CHECK_REG(bResult);
return TRUE;
}
typedef struct _REG_INFO_KEY
{
DWORD cSubKeys;
DWORD cbMaxSubKeyLen;
DWORD cbMaxClassLen;
DWORD cValues;
DWORD cbMaxValueNameLen;
DWORD cbMaxValueLen;
DWORD cbSecurityDescriptor;
FILETIME ftLastWriteTime;
} REG_INFO_KEY, *PREG_INFO_KEY;
REG_INFO_KEY
RegQueryInfoKey()
{
REG_INFO_KEY rik;
CHECK_REG(::RegQueryInfoKey(
*this,
0,
0,
0,
&rik.cSubKeys,
&rik.cbMaxSubKeyLen,
&rik.cbMaxClassLen,
&rik.cValues,
&rik.cbMaxValueNameLen,
&rik.cbMaxValueLen,
&rik.cbSecurityDescriptor,
&rik.ftLastWriteTime
));
return rik;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CFindFile
//
// Wrapper class for directory search objects
//
class CFindFile : public WIN32_FIND_DATA, public CHandle<HANDLE, CFindFile>
{
public:
CFindFile(
PCTSTR pFileName
)
{
HANDLE hHandle = ::FindFirstFile(
pFileName,
this
);
if (hHandle == INVALID_HANDLE_VALUE)
{
m_bFound = FALSE;
}
else
{
m_bFound = TRUE;
Attach(hHandle);
}
}
void Destroy()
{
::FindClose(*this);
}
bool IsValid()
{
return (HANDLE) *this != INVALID_HANDLE_VALUE;
}
VOID
FindNextFile()
{
m_bFound = ::FindNextFile(
*this,
this
);
CHECK(m_bFound || GetLastError() == ERROR_NO_MORE_FILES);
}
BOOL
Found() const
{
return m_bFound;
}
private:
BOOL m_bFound;
};
//////////////////////////////////////////////////////////////////////////
//
// FileExists
//
// Returns TRUE if the specified file exists
//
inline BOOL FileExists(PCTSTR pName)
{
CFindFile ff(pName);
return ff.Found();
}
//////////////////////////////////////////////////////////////////////////
//
// DirectoryExists
//
// Returns TRUE if the specified directory exists
//
inline BOOL DirectoryExists(PCTSTR pName)
{
TCHAR pRootDir[3];
// change "X:\" to "X:"
if (pName && pName[1] == _T(':') && pName[2] == _T('\\') && pName[3] == _T('\0'))
{
pRootDir[0] = pName[0];
pRootDir[1] = _T(':');
pRootDir[2] = _T('\0');
pName = pRootDir;
}
CFindFile ff(pName);
return ff.Found() && (ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
}
//////////////////////////////////////////////////////////////////////////
//
// GetFileSize
//
// Returns the size of the specified file
//
inline ULARGE_INTEGER GetFileSize(PCTSTR pFileName)
{
CFindFile ff(pFileName);
CHECK(ff.Found());
ULARGE_INTEGER nSize =
{
ff.nFileSizeLow,
ff.nFileSizeHigh
};
return nSize;
}
#ifdef _INC_TOOLHELP32
//////////////////////////////////////////////////////////////////////////
//
// CToolhelp32Snapshot
//
// Wrapper class for the toolhelp snapshot objects
//
class CToolhelp32Snapshot : public CKernelObject<CToolhelp32Snapshot>
{
typedef CKernelObject<CToolhelp32Snapshot> parent_type;
public:
explicit
CToolhelp32Snapshot(
DWORD dwFlags = TH32CS_SNAPALL,
DWORD th32ProcessID = 0
) :
parent_type(CreateToolhelp32Snapshot(
dwFlags,
th32ProcessID
))
{
}
};
//////////////////////////////////////////////////////////////////////////
//
// CFindHeapList, CFindModule, CFindProcess, CFindThread
//
// Wrapper classes for toolhelp find functions
//
// bugbug: this template declaration is better, but VC compiler cannot resolve it yet
//template <class T, BOOL (WINAPI *fnFindFirst)(HANDLE, T *), BOOL (WINAPI *fnFindNext)(HANDLE, T *)>
#define DECLARE_TOOLHELP32_FIND(CLASSNAME, STRUCT, FINDFIRST, FINDNEXT) \
\
class CLASSNAME : public STRUCT \
{ \
public: \
CLASSNAME( \
HANDLE hSnapShot \
) \
{ \
m_hSnapShot = hSnapShot; \
dwSize = sizeof(STRUCT); \
m_bFound = FINDFIRST(m_hSnapShot, this); \
} \
\
VOID \
FindNext() \
{ \
m_bFound = FINDNEXT(m_hSnapShot, this); \
} \
\
BOOL \
IsFound() const \
{ \
return m_bFound; \
} \
\
private: \
HANDLE m_hSnapShot; \
BOOL m_bFound; \
}; \
DECLARE_TOOLHELP32_FIND(CFindHeapList, HEAPLIST32, Heap32ListFirst, Heap32ListNext);
DECLARE_TOOLHELP32_FIND(CFindModule, MODULEENTRY32, Module32First, Module32Next);
DECLARE_TOOLHELP32_FIND(CFindProcess, PROCESSENTRY32, Process32First, Process32Next);
DECLARE_TOOLHELP32_FIND(CFindThread, THREADENTRY32, Thread32First, Thread32Next);
//////////////////////////////////////////////////////////////////////////
//
// FindProcessId
//
// Returns the id of the process specified by name
//
inline DWORD FindProcessId(PCTSTR pProcessName)
{
CToolhelp32Snapshot Snapshot(TH32CS_SNAPPROCESS);
for (CFindProcess pe32(Snapshot); pe32.IsFound(); pe32.FindNext())
{
if (_tcsicmp(FindFileNamePortion(pe32.szExeFile), pProcessName) == 0)
{
return pe32.th32ProcessID;
}
}
return 0;
}
#endif //_INC_TOOLHELP32
//////////////////////////////////////////////////////////////////////////
//
// CFindWindow
//
// Wrapper class for finding child windows
//
class CFindWindow
{
public:
CFindWindow(
HWND hWnd
)
{
m_hChild = ::GetTopWindow(hWnd);
}
VOID
FindNext()
{
m_hChild = ::GetNextWindow(
m_hChild,
GW_HWNDNEXT
);
}
operator HWND() const
{
return m_hChild;
}
BOOL
IsFound() const
{
return m_hChild != 0;
}
private:
HWND m_hChild;
};
#ifdef _WINSVC_
//////////////////////////////////////////////////////////////////////////
//
// CService
//
// Wrapper class for service objects
//
class CService : public CHandle<SC_HANDLE, CService>
{
typedef CHandle<SC_HANDLE, CService> parent_type;
public:
CService()
{
}
CService(
SC_HANDLE hHandle
) :
parent_type(hHandle)
{
}
void Destroy()
{
::CloseServiceHandle(*this);
}
bool IsValid()
{
return *this != 0;
}
VOID
StartService(
DWORD dwNumServiceArgs = 0,
LPCTSTR *lpServiceArgVectors = 0
)
{
if (QueryServiceStatus().dwCurrentState != SERVICE_RUNNING)
{
CHECK(::StartService(
*this,
dwNumServiceArgs,
lpServiceArgVectors
));
while (QueryServiceStatus().dwCurrentState != SERVICE_RUNNING)
{
//bugbug: this might cause a hang
}
}
}
SERVICE_STATUS &
QueryServiceStatus()
{
CHECK(::QueryServiceStatus(*this, &m_ss));
return m_ss;
}
VOID
DeleteService() const
{
CHECK(::DeleteService(*this));
}
VOID
ControlService(
DWORD dwControl
)
{
CHECK(::ControlService(*this, dwControl, &m_ss));
}
VOID
ChangeServiceState(
DWORD dwControl,
DWORD dwNewState
)
{
if (QueryServiceStatus().dwCurrentState != dwNewState)
{
ControlService(dwControl);
while (QueryServiceStatus().dwCurrentState != dwNewState)
{
//bugbug: this might cause a hang
}
}
}
VOID
StopService()
{
ChangeServiceState(SERVICE_CONTROL_STOP, SERVICE_STOPPED);
}
VOID
PauseService()
{
ChangeServiceState(SERVICE_CONTROL_PAUSE, SERVICE_PAUSED);
}
VOID
ContinueService()
{
ChangeServiceState(SERVICE_CONTROL_CONTINUE, SERVICE_RUNNING);
}
friend class CSCManager;
private:
SERVICE_STATUS m_ss;
};
//////////////////////////////////////////////////////////////////////////
//
// CSCManager
//
// Wrapper class for service control manager
//
class CSCManager : public CHandle<SC_HANDLE, CSCManager>
{
typedef CHandle<SC_HANDLE, CSCManager> parent_type;
public:
explicit
CSCManager(
PCTSTR pRemoteComputerName = 0,
PCTSTR pDatabaseName = SERVICES_ACTIVE_DATABASE,
DWORD dwDesiredAccess = SC_MANAGER_ALL_ACCESS
) :
parent_type(OpenSCManager(
pRemoteComputerName,
pDatabaseName,
dwDesiredAccess
))
{
}
void Destroy()
{
CloseServiceHandle(*this);
}
bool IsValid()
{
return *this != 0;
}
public:
SC_HANDLE
CreateService(
PCTSTR pServiceName,
PCTSTR pDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
PCTSTR pBinaryPathName,
PCTSTR pLoadOrderGroup = 0,
PDWORD pdwTagId = 0,
PCTSTR pDependencies = 0,
PCTSTR pServiceStartName = 0,
PCTSTR pPassword = 0
) const
{
return ::CreateService(
*this,
pServiceName,
pDisplayName,
dwDesiredAccess,
dwServiceType,
dwStartType,
dwErrorControl,
pBinaryPathName,
pLoadOrderGroup,
pdwTagId,
pDependencies,
pServiceStartName,
pPassword
);
}
SC_HANDLE
OpenService(
PCTSTR pServiceName,
DWORD dwDesiredAccess = SERVICE_ALL_ACCESS
) const
{
return ::OpenService(
*this,
pServiceName,
dwDesiredAccess
);
}
};
#endif //_WINSVC_
//////////////////////////////////////////////////////////////////////////
//
// CPath
//
// Base class for wrapper classes that deal with path names
//
#ifdef _IOSTREAM_
template <int N> class CPath;
template <int N> std::ostream &operator <<(std::ostream &os, const CPath<N> &rhs);
#endif //_IOSTREAM_
template <int N = MAX_PATH>
class CPath
{
public:
CPath()
{
m_szName[0] = _T('\0');
m_szName[1] = _T('\0');
m_dwLength = 0;
}
CPath(PCTSTR pName)
{
assign(pName);
}
CPath & operator =(PCTSTR pName)
{
return assign(pName);
}
CPath & assign(PCTSTR pName)
{
_tcsncpy(m_szName, pName, N);
FindLength();
return *this;
}
DWORD length() const
{
return m_dwLength;
}
bool empty() const
{
return m_szName[0] == _T('\0');
}
operator PCTSTR() const
{
return m_szName;
}
PCTSTR FileName() const
{
return m_szName + m_dwLength + 1;
}
CPath & operator +=(PCTSTR pName)
{
SetFileName(pName);
FindLength();
return *this;
}
CPath & SetFileName(PCTSTR pName)
{
m_szName[m_dwLength] = _T('\\');
_tcsncpy(m_szName + m_dwLength + 1, pName, N - m_dwLength - 1);
return *this;
}
CPath & StripFileName()
{
m_szName[m_dwLength] = _T('\0');
return *this;
}
void FindLength()
{
m_dwLength = _tcslen(m_szName);
while (m_dwLength && m_szName[m_dwLength-1] == _T('\\'))
{
m_szName[--m_dwLength] = _T('\0');
}
}
//bugbug: just to please the VC5 compiler, drop templates
//template <int M>
bool operator ==(const CPath/*<M>*/ &rhs) const
{
return
m_dwLength == rhs.m_dwLength &&
_tcscmp(m_szName, rhs.m_szName) == 0;
}
//template <int M>
bool operator !=(const CPath/*<M>*/ &rhs) const
{
return !(*this == rhs);
}
//template <int M>
bool operator >(const CPath/*<M>*/ &rhs) const
{
return
m_dwLength > rhs.m_dwLength ||
_tcscmp(m_szName, rhs.m_szName) > 0;
}
//template <int M>
bool operator <=(const CPath/*<M>*/ &rhs) const
{
return !(*this > rhs);
}
//template <int M>
bool operator <(const CPath/*<M>*/ &rhs) const
{
return
m_dwLength < rhs.m_dwLength ||
_tcscmp(m_szName, rhs.m_szName) < 0;
}
//template <int M>
bool operator >=(const CPath/*<M>*/ &rhs) const
{
return !(*this < rhs);
}
#ifdef _IOSTREAM_
friend std::ostream &operator <<(std::ostream &os, const CPath<N> &rhs)
{
return os << m_szName;
}
#endif //_IOSTREAM_
protected:
TCHAR m_szName[N];
DWORD m_dwLength;
};
//////////////////////////////////////////////////////////////////////////
//
// CWindowsDirectory
//
// Wrapper class for the GetWindowsDirectory() API
//
class CWindowsDirectory : public CPath<>
{
public:
CWindowsDirectory()
{
CHECK(::GetWindowsDirectory(
m_szName,
COUNTOF(m_szName)
));
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CSystemWindowsDirectory
//
// Wrapper class for the GetSystemWindowsDirectory() API
//
class CSystemWindowsDirectory : public CPath<>
{
public:
CSystemWindowsDirectory()
{
typedef UINT (WINAPI *PFN)(LPTSTR lpBuffer, UINT uSize);
static PFN pfn = (PFN) GetProcAddress(
::GetModuleHandle(_T("kernel32.dll")),
"GetSystemWindowsDirectory"_AW
);
if (pfn)
{
CHECK((*pfn)(
m_szName,
COUNTOF(m_szName)
));
}
else
{
CHECK(::GetWindowsDirectory(
m_szName,
COUNTOF(m_szName)
));
}
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CSystemDirectory
//
// Wrapper class for the GetSystemDirectory() API
//
class CSystemDirectory : public CPath<>
{
public:
CSystemDirectory()
{
CHECK(::GetSystemDirectory(
m_szName,
COUNTOF(m_szName)
));
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CCurrentDirectory
//
// Wrapper class for the GetCurrentDirectory() API
//
class CCurrentDirectory : public CPath<>
{
public:
CCurrentDirectory()
{
CHECK(::GetCurrentDirectory(
COUNTOF(m_szName),
m_szName
));
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CModuleFileName
//
// Wrapper class for the GetModuleFileName() API
//
class CModuleFileName : public CPath<>
{
public:
CModuleFileName(
HMODULE hModule = 0
)
{
CHECK(::GetModuleFileName(
hModule,
m_szName,
COUNTOF(m_szName)
));
FindLength();
}
};
#ifdef _ICM_H_
//////////////////////////////////////////////////////////////////////////
//
// CColorDirectory
//
// Wrapper class for the GetColorDirectory() API
//
class CColorDirectory : public CPath<>
{
public:
explicit
CColorDirectory(
PCTSTR pMachineName = 0
)
{
m_dwLength = sizeof(m_szName);
CHECK(GetColorDirectory(
pMachineName,
m_szName,
&m_dwLength
));
FindLength();
}
};
#endif //_ICM_H_
//////////////////////////////////////////////////////////////////////////
//
// CComputerName
//
// Wrapper class for the GetComputerName() API
//
class CComputerName : public CPath<2 + MAX_COMPUTERNAME_LENGTH + 1>
{
public:
CComputerName(
BOOL bUNC = FALSE
)
{
if (bUNC)
{
m_dwLength = COUNTOF(m_szName) - 2;
CHECK(::GetComputerName(
m_szName + 2,
&m_dwLength
));
m_szName[0] = '\\';
m_szName[1] = '\\';
}
else
{
m_dwLength = COUNTOF(m_szName);
CHECK(::GetComputerName(
m_szName,
&m_dwLength
));
}
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CFullPathName
//
// Wrapper class for the GetFullPathName() API
//
class CFullPathName : public CPath<>
{
public:
CFullPathName(
PCTSTR pFileName
)
{
if (pFileName && *pFileName)
{
PTSTR pFilePart;
CHECK(::GetFullPathName(
pFileName,
COUNTOF(m_szName),
m_szName,
&pFilePart
));
m_dwLength = (DWORD)(pFilePart - m_szName - 1);
}
}
};
//////////////////////////////////////////////////////////////////////////
//
// CTempFileName
//
// Wrapper class for the GetTempPath() API
//
class CTempPath : public CPath<>
{
public:
CTempPath()
{
CHECK(::GetTempPath(
COUNTOF(m_szName),
m_szName
));
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CTempFileName
//
// Wrapper class for the GetTempFileName() API
//
class CTempFileName : public CPath<>
{
public:
CTempFileName(
PCTSTR pPathName,
PCTSTR pPrefixString,
UINT uUnique = 0
)
{
CHECK(::GetTempFileName(
pPathName,
pPrefixString,
uUnique,
m_szName
));
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CWindowText
//
// Wrapper class for the GetWindowText() API
//
class CWindowText : public CPath<1024> //bugbug
{
public:
CWindowText(
HWND hWnd
)
{
::SetLastError(0);
CHECK(
::GetWindowText(hWnd, m_szName, COUNTOF(m_szName)) ||
::GetLastError() == 0
);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CSafeWindowText
//
// Helper class for the GetClassName() API (that works better on Win9x)
//
class CSafeWindowText : public CPath<1024> //bugbug
{
public:
CSafeWindowText(
HWND hWnd
)
{
WNDPROC pfnWndProc = (WNDPROC) GetWindowLongPtr(
hWnd,
GWLP_WNDPROC
);
CallWindowProc(
pfnWndProc,
hWnd,
WM_GETTEXT,
COUNTOF(m_szName),
(LPARAM) m_szName
);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CClassName
//
// Wrapper class for the GetClassName() API
//
class CClassName : public CPath<1024> //bugbug
{
public:
CClassName(
HWND hWnd
)
{
CHECK(::GetClassName(
hWnd,
m_szName,
COUNTOF(m_szName)
));
}
};
//////////////////////////////////////////////////////////////////////////
//
// CConsoleTitle
//
// Wrapper class for the GetConsoleTitle() API
//
class CConsoleTitle : public CPath<1024> //bugbug
{
public:
CConsoleTitle()
{
CHECK(::GetConsoleTitle(
m_szName,
COUNTOF(m_szName)
));
}
};
//////////////////////////////////////////////////////////////////////////
//
// CUserName
//
// Returns a handle to the console window
//
inline HWND GetConsoleHwnd()
{
HWND hConsoleWnd = 0;
try
{
// read the current console title
CConsoleTitle OldTitle;
// change the title to a supposedly random value
TCHAR szNewTitle[17];
wsprintf(
szNewTitle,
_T("%08x%08x"),
GetTickCount(),
GetCurrentProcessId()
);
SetConsoleTitle(szNewTitle);
Sleep(50);
// try find the window based on this new title
HWND hWnd = FindWindow(0, szNewTitle);
// restore the title
SetConsoleTitle(OldTitle);
Sleep(50);
// compare the title of the window we found against the console title
CWindowText HWndTitle(hWnd);
if (_tcscmp(OldTitle, HWndTitle) == 0)
{
hConsoleWnd = hWnd;
}
}
catch (const CError &)
{
}
return hConsoleWnd;
}
//////////////////////////////////////////////////////////////////////////
//
// CUserName
//
// Wrapper class for the GetUserName API
//
#ifndef UNLEN
#define UNLEN 256
#endif //UNLEN
class CUserName : public CPath<UNLEN + 1>
{
public:
CUserName()
{
m_dwLength = COUNTOF(m_szName);
CHECK(::GetUserName(
m_szName,
&m_dwLength
));
}
};
//////////////////////////////////////////////////////////////////////////
//
// CRegString
//
// Helper class for reading a string with the RegQueryValueEx() API
//
template <int N>
class CRegString : public CPath<N>
{
public:
CRegString()
{
}
CRegString(
HKEY hKey,
PCTSTR pSubKey,
PTSTR pValueName,
BOOL bExpandEnvironmentStrings = TRUE
)
{
CKey Key(
hKey,
pSubKey,
KEY_READ
);
DWORD dwType;
m_dwLength = sizeof(m_szName);
Key.RegQueryValueEx(
pValueName,
&dwType,
m_szName,
&m_dwLength
);
if (dwType == REG_EXPAND_SZ && bExpandEnvironmentStrings)
{
TCHAR szExpanded[N];
CHECK(ExpandEnvironmentStrings(
m_szName,
szExpanded,
COUNTOF(szExpanded)
));
_tcscpy(m_szName, szExpanded);
}
FindLength();
}
// bugbug: Aren't we supposed to inherit this?
CPath<N> &
operator =(
PCTSTR pName
)
{
return CPath<N>::operator =(pName);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CResourceString
//
// Wrapper class for the LoadString() API
//
template <int N>
class CResourceString : public CPath<N>
{
public:
CResourceString()
{
}
explicit
CResourceString(
UINT uID,
HINSTANCE hInstance = 0
)
{
CHECK(m_dwLength = LoadString(
hInstance,
uID,
m_szName,
COUNTOF(m_szName)
));
}
CResourceString(
UINT uID,
HINSTANCE hInstance,
PCTSTR pszDefault
)
{
m_dwLength = LoadString(
hInstance,
uID,
m_szName,
COUNTOF(m_szName)
);
if (m_dwLength == 0)
{
assign(pszDefault);
}
}
};
#ifdef _WINSPOOL_
//////////////////////////////////////////////////////////////////////////
//
// CPrinterDriverDirectory
//
// Wrapper class for the GetPrinterDriverDirectory() API
//
class CPrinterDriverDirectory : public CPath<>
{
public:
explicit
CPrinterDriverDirectory(
PTSTR pName = 0,
PTSTR pEnvironment = 0
)
{
m_dwLength = sizeof(m_szName);
CHECK(::GetPrinterDriverDirectory(
pName,
pEnvironment,
1,
(PBYTE) m_szName,
m_dwLength,
&m_dwLength
));
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CPrintProcessorDirectory
//
// Wrapper class for the GetPrintProcessorDirectory() API
//
class CPrintProcessorDirectory : public CPath<>
{
public:
explicit
CPrintProcessorDirectory(
PTSTR pName = 0,
PTSTR pEnvironment = 0
)
{
m_dwLength = sizeof(m_szName);
CHECK(::GetPrintProcessorDirectory(
pName,
pEnvironment,
1,
(PBYTE) m_szName,
m_dwLength,
&m_dwLength
));
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CDefaultPrinter
//
// Wrapper class for the GetDefaultPrinter() API
//
#ifndef INTERNET_MAX_HOST_NAME_LENGTH
#define INTERNET_MAX_HOST_NAME_LENGTH 256
#endif
class CDefaultPrinter : public CPath<2 + INTERNET_MAX_HOST_NAME_LENGTH + 1 + MAX_PATH + 1>
{
public:
CDefaultPrinter()
{
typedef BOOL (WINAPI *PFN)(LPTSTR, LPDWORD);
static PFN pfnGetDefaultPrinter = (PFN) GetProcAddress(
::GetModuleHandle(_T("winspool.drv")),
"GetDefaultPrinter"_AW
);
m_dwLength = sizeof(m_szName);
if (pfnGetDefaultPrinter)
{
pfnGetDefaultPrinter(
m_szName,
&m_dwLength
);
}
else
{
GetProfileString(
_T("windows"),
_T("device"),
_T(",,,"),
m_szName,
COUNTOF(m_szName)
);
PTSTR pComma = _tcschr(m_szName, ',');
if (pComma)
{
*pComma = _T('\0');
}
}
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CPrinterDefaults
//
// Wrapper class for PRINTER_DEFAULTS struct
//
struct CPrinterDefaults : public PRINTER_DEFAULTS
{
CPrinterDefaults(
PTSTR _pDatatype = 0,
PDEVMODE _pDevMode = 0,
ACCESS_MASK _DesiredAccess = PRINTER_ALL_ACCESS
)
{
pDatatype = _pDatatype;
pDevMode = _pDevMode;
DesiredAccess = _DesiredAccess;
}
};
//////////////////////////////////////////////////////////////////////////
//
// printer_info_to_level, level_to_printer_info
//
// Traits classes to map PRINTER_INFO_XXX to level numbers and vice versa
//
template<class T> struct printer_info_to_level { };
template<> struct printer_info_to_level<PRINTER_INFO_1> { enum { level = 1 }; };
template<> struct printer_info_to_level<PRINTER_INFO_2> { enum { level = 2 }; };
template<> struct printer_info_to_level<PRINTER_INFO_3> { enum { level = 3 }; };
template<> struct printer_info_to_level<PRINTER_INFO_4> { enum { level = 4 }; };
template<> struct printer_info_to_level<PRINTER_INFO_5> { enum { level = 5 }; };
template<> struct printer_info_to_level<PRINTER_INFO_6> { enum { level = 6 }; };
template<> struct printer_info_to_level<PRINTER_INFO_7> { enum { level = 7 }; };
template<> struct printer_info_to_level<PRINTER_INFO_8> { enum { level = 8 }; };
template<> struct printer_info_to_level<PRINTER_INFO_9> { enum { level = 9 }; };
template<int N> struct level_to_printer_info { };
template<> struct level_to_printer_info<1> { typedef PRINTER_INFO_1 struct_type; };
template<> struct level_to_printer_info<2> { typedef PRINTER_INFO_2 struct_type; };
template<> struct level_to_printer_info<3> { typedef PRINTER_INFO_3 struct_type; };
template<> struct level_to_printer_info<4> { typedef PRINTER_INFO_4 struct_type; };
template<> struct level_to_printer_info<5> { typedef PRINTER_INFO_5 struct_type; };
template<> struct level_to_printer_info<6> { typedef PRINTER_INFO_6 struct_type; };
template<> struct level_to_printer_info<7> { typedef PRINTER_INFO_7 struct_type; };
template<> struct level_to_printer_info<8> { typedef PRINTER_INFO_8 struct_type; };
template<> struct level_to_printer_info<9> { typedef PRINTER_INFO_9 struct_type; };
//////////////////////////////////////////////////////////////////////////
//
// CPrinter
//
// Wrapper class for printer objects
//
class CPrinter : public CHandle<HANDLE, CPrinter>
{
typedef CHandle<HANDLE, CPrinter> parent_type;
public:
explicit
CPrinter(
PCTSTR pPrinterName,
const PRINTER_DEFAULTS *pDefault = &CPrinterDefaults()
)
{
HANDLE hHandle;
CHECK(::OpenPrinter(
const_cast<PTSTR>(pPrinterName),
&hHandle,
const_cast<PPRINTER_DEFAULTS>(pDefault)
));
Attach(hHandle);
}
CPrinter(
PTSTR pServerName,
const PRINTER_INFO_2 *pPrinter
) :
parent_type(::AddPrinter(
pServerName,
2,
(PBYTE) pPrinter
))
{
}
void Destroy()
{
::ClosePrinter(*this);
}
bool IsValid()
{
return *this != 0;
}
VOID
Delete() const
{
CHECK(::DeletePrinter(*this));
}
template <class T>
VOID
SetPrinter(T *pPrinterInfo)
{
CHECK(::SetPrinter(
*this,
printer_info_to_level<T>::level,
(PBYTE) pPrinterInfo,
0
));
}
};
//////////////////////////////////////////////////////////////////////////
//
// DeletePrinterDriverExRetry
//
// Helper for DeletePrinterDriverEx() API that implements wait & retry
//
inline
BOOL
DeletePrinterDriverExRetry(
PTSTR pName,
PTSTR pEnvironment,
PTSTR pDriverName,
DWORD dwDeleteFlag,
DWORD dwVersionFlag,
int nMaxRetries = 3,
DWORD dwSleepMilliseconds = 1000
)
{
BOOL bResult = FALSE;
for (
int nRetries = 0;
(bResult = DeletePrinterDriverEx(
pName,
pEnvironment,
pDriverName,
dwDeleteFlag,
dwVersionFlag
)) == FALSE &&
GetLastError() == ERROR_PRINTER_DRIVER_IN_USE &&
nRetries < nMaxRetries;
++nRetries
)
{
Sleep(dwSleepMilliseconds);
}
return bResult;
}
//////////////////////////////////////////////////////////////////////////
//
// AddMonitor
//
// Helper for AddMonitor() API that infers the struct level at compile time
//
template<class T> struct monitor_info_to_level { };
template<> struct monitor_info_to_level<MONITOR_INFO_1> { enum { level = 1 }; };
template<> struct monitor_info_to_level<MONITOR_INFO_2> { enum { level = 2 }; };
template <class T>
inline
BOOL
AddMonitor(
PTSTR pName,
T *pMonitors
)
{
return ::AddMonitor(
pName,
monitor_info_to_level<T>::level,
(PBYTE) pMonitors
);
}
//////////////////////////////////////////////////////////////////////////
//
// CPrinterChangeNotification
//
// Wrapper class for printer change notifications
//
class CPrinterChangeNotification : public CHandle<HANDLE, CPrinter>
{
typedef CHandle<HANDLE, CPrinter> parent_type;
public:
CPrinterChangeNotification(
HANDLE hPrinter,
DWORD fdwFlags,
PPRINTER_NOTIFY_OPTIONS pPrinterNotifyOptions = 0
) :
parent_type(::FindFirstPrinterChangeNotification(
hPrinter,
fdwFlags,
0,
pPrinterNotifyOptions
))
{
}
void Destroy()
{
::FindClosePrinterChangeNotification(*this);
}
bool IsValid()
{
return (HANDLE) *this != INVALID_HANDLE_VALUE;
}
DWORD
FindNext(
PPRINTER_NOTIFY_OPTIONS pPrinterNotifyOptions = 0,
PPRINTER_NOTIFY_INFO *ppPrinterNotifyInfo = 0
)
{
DWORD dwChange;
CHECK(::FindNextPrinterChangeNotification(
*this,
&dwChange,
pPrinterNotifyOptions,
(PVOID *) ppPrinterNotifyInfo
));
return dwChange;
}
};
#endif //_WINSPOOL_
//////////////////////////////////////////////////////////////////////////
//
// CStringFileInfo
//
// Helper class for creating \StringFileInfo\lang-codepage\name type strings
//
class CStringFileInfo : public CPath<80>
{
public:
CStringFileInfo(
WORD wLang,
WORD wCodePage
)
{
_stprintf(
m_szName,
_T("\\StringFileInfo\\%04X%04X"),
wLang,
wCodePage
);
FindLength();
}
CStringFileInfo(
DWORD dwLangCodePage
)
{
_stprintf(
m_szName,
_T("\\StringFileInfo\\%04X%04X"),
LOWORD(dwLangCodePage),
HIWORD(dwLangCodePage)
);
FindLength();
}
};
//////////////////////////////////////////////////////////////////////////
//
// CVersionInfo
//
// Helper class for parsing version resource information
//
class CVersionInfo
{
public:
CVersionInfo(
PCTSTR pFileName = 0
)
{
CModuleFileName ModuleFileName;
if (!pFileName)
{
pFileName = ModuleFileName;
}
DWORD dwVerInfoSize;
DWORD dwHandle;
CHECK(dwVerInfoSize = GetFileVersionInfoSize(
const_cast<PTSTR>(pFileName),
&dwHandle
));
CCppMem<BYTE> VerInfo(dwVerInfoSize);
CHECK(::GetFileVersionInfo(
const_cast<PTSTR>(pFileName),
dwHandle,
dwVerInfoSize,
VerInfo
));
m_VerInfo = VerInfo;
}
PVOID
VerQueryValue(
PCTSTR pSubBlock
) const
{
PVOID pBuffer;
UINT uLen;
CHECK(::VerQueryValue(
m_VerInfo,
const_cast<PTSTR>(pSubBlock),
&pBuffer,
&uLen
));
return pBuffer;
}
VS_FIXEDFILEINFO *GetFixedFileInfo() const
{
return (VS_FIXEDFILEINFO *) VerQueryValue(_T("\\"));
}
PDWORD GetTranslation() const
{
return (PDWORD) VerQueryValue(_T("\\VarFileInfo\\Translation"));
}
PCTSTR
GetStringFileInfo(
WORD wLang,
WORD wCodePage,
PCTSTR pSubBlock
) const
{
return (PCTSTR) VerQueryValue(CStringFileInfo(wLang, wCodePage).SetFileName(pSubBlock));
}
ULARGE_INTEGER
GetFileVersion() const
{
VS_FIXEDFILEINFO *pFixedFileInfo = GetFixedFileInfo();
ULARGE_INTEGER nVersion =
{
pFixedFileInfo->dwFileVersionLS,
pFixedFileInfo->dwFileVersionMS
};
return nVersion;
}
ULARGE_INTEGER
GetProductVersion() const
{
VS_FIXEDFILEINFO *pFixedFileInfo = GetFixedFileInfo();
ULARGE_INTEGER nVersion =
{
pFixedFileInfo->dwProductVersionLS,
pFixedFileInfo->dwProductVersionMS
};
return nVersion;
}
private:
CCppMem<BYTE> m_VerInfo;
};
//////////////////////////////////////////////////////////////////////////
//
// CResource
//
// Wrapper class for FindResourceEx(), LoadResource() and LockResource() APIs
//
class CResource
{
public:
CResource(
HMODULE hModule,
PCTSTR pType,
PCTSTR pName,
WORD wLanguage = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
)
{
HRSRC hResInfo;
CHECK(hResInfo = FindResourceEx(hModule, pType, pName, wLanguage));
HGLOBAL hResData;
CHECK(hResData = LoadResource(hModule, hResInfo));
CHECK(m_pData = LockResource(hResData));
CHECK(m_nSize = SizeofResource(hModule, hResInfo));
}
PVOID Data()
{
return m_pData;
}
DWORD Size()
{
return m_nSize;
}
private:
PVOID m_pData;
DWORD m_nSize;
};
//////////////////////////////////////////////////////////////////////////
//
// CDialogResource
//
// Helper class for parsing a dialog resource
//
class CDialogResource
{
public:
CDialogResource(
HMODULE hModule,
PCTSTR pName,
WORD wLanguage = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
)
{
CResource Dlg(hModule, RT_DIALOG, pName, wLanguage);
ParseDlgResource(Dlg.Data());
}
CDialogResource(
PVOID pDlgResource
)
{
ParseDlgResource(pDlgResource);
}
private:
class CParseDlgResource
{
public:
CParseDlgResource(
PVOID pDlgResource
)
{
Goto(pDlgResource);
}
void
Goto(PVOID pDlgResource)
{
m_pNextValue = (PBYTE) pDlgResource;
}
template <class T>
void Read(T &Value)
{
Value = *(T *) m_pNextValue;
m_pNextValue += sizeof(T);
}
template <>
void Read(PWSTR &pStr)
{
pStr = (PWSTR) m_pNextValue;
if (*pStr == MAXWORD)
{
pStr = (PWSTR) pStr[1];
m_pNextValue += 2 * sizeof(WCHAR);
}
else
{
m_pNextValue += (wcslen(pStr) + 1) * sizeof(WCHAR);
}
}
private:
PBYTE m_pNextValue;
};
private:
void ParseDlgResource(PVOID pDlgResource)
{
ZeroMemory(this, sizeof(*this));
CParseDlgResource Parser(pDlgResource);
Parser.Read(dlgVer);
Parser.Read(signature);
BOOL bIsExTemplate = dlgVer == 1 && signature == MAXWORD;
if (bIsExTemplate)
{
Parser.Read(helpID);
Parser.Read(exStyle);
Parser.Read(style);
}
else
{
Parser.Goto(pDlgResource);
Parser.Read(style);
Parser.Read(exStyle);
}
Parser.Read(cDlgItems);
Parser.Read(x);
Parser.Read(y);
Parser.Read(cx);
Parser.Read(cy);
Parser.Read(menu);
Parser.Read(windowClass);
Parser.Read(title);
if (style & DS_SHELLFONT)
{
if (bIsExTemplate)
{
Parser.Read(pointsize);
Parser.Read(weight);
Parser.Read(italic);
Parser.Read(charset);
Parser.Read(typeface);
}
else
{
Parser.Read(pointsize);
Parser.Read(typeface);
}
}
}
public:
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
PWSTR menu;
PWSTR windowClass;
PWSTR title;
WORD pointsize;
WORD weight;
BYTE italic;
BYTE charset;
PWSTR typeface;
};
//////////////////////////////////////////////////////////////////////////
//
// CStringTable
//
template <int nFirstId, int nLastId>
class CStringTable
{
public:
CStringTable(
HINSTANCE hInstance = GetModuleHandle(0)
)
{
TCHAR szBuffer[4098]; // max length of a resource string
for (int i = 0; i < m_nStrings; ++i)
{
int nLength = LoadString(
hInstance,
i + nFirstId,
szBuffer,
COUNTOF(szBuffer)
);
m_pTable[i] = new TCHAR[nLength + 1];
if (nLength && m_pTable[i])
{
CopyMemory(
m_pTable[i],
szBuffer,
nLength * sizeof(TCHAR)
);
}
}
}
~CStringTable()
{
for (int i = 0; i < m_nStrings; ++i)
{
if (m_pTable[i])
{
delete [] m_pTable[i];
}
}
}
PCTSTR operator[](int i)
{
ASSERT(nFirstId <= i && i <= nLastId);
return m_pTable[i - nFirstId];
}
private:
enum { m_nStrings = nLastId - nFirstId + 1 };
PTSTR m_pTable[m_nStrings];
};
#ifdef _NTSECAPI_
//////////////////////////////////////////////////////////////////////////
//
// CLsaUnicodeString
//
// Wrapper class for LSA_UNICODE_STRING struct
//
class CLsaUnicodeString : public LSA_UNICODE_STRING
{
public:
CLsaUnicodeString(
PWSTR pStr
)
{
if (pStr)
{
Buffer = pStr;
Length = (USHORT) (wcslen(pStr) * sizeof(WCHAR));
MaximumLength = (USHORT) (Length + sizeof(WCHAR));
}
else
{
Buffer = 0;
Length = 0;
MaximumLength = 0;
}
}
};
#endif //_NTSECAPI_
//////////////////////////////////////////////////////////////////////////
//
// COSVersionInfo
//
// Wrapper class for GetVersion() API
//
class COSVersionInfo : public OSVERSIONINFO
{
public:
COSVersionInfo()
{
dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
CHECK(GetVersionEx(this));
}
};
//////////////////////////////////////////////////////////////////////////
//
// COSVersionInfoEx
//
// Wrapper class for GetVersionEx() API
//
class COSVersionInfoEx : public OSVERSIONINFOEX
{
public:
COSVersionInfoEx()
{
dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
CHECK(GetVersionEx((POSVERSIONINFO)this));
}
};
#ifdef _INC_CDERR
//////////////////////////////////////////////////////////////////////////
//
// COpenFileName
//
// Wrapper class for GetOpenFileName() and GetSaveFileName() APIs
//
template <int nFileNameLen = MAX_PATH, int nFileTitleSize = MAX_PATH, int nCustomFilterSize = MAX_PATH>
class COpenFileName : public OPENFILENAME
{
public:
COpenFileName(
HWND hWndOwner = 0,
PCTSTR pFilter = 0,
PCTSTR pInitialDir = 0,
PCTSTR pTitle = 0,
PCTSTR pDefExt = 0,
DWORD dwFlags = 0
)
{
ZeroMemory(this, sizeof(*this));
lStructSize = sizeof(OPENFILENAME);
hwndOwner = hWndOwner;
hInstance = 0;
lpstrFilter = pFilter;
lpstrCustomFilter = m_szCustomFilter;
nMaxCustFilter = COUNTOF(m_szCustomFilter);
nFilterIndex = 1;
lpstrFile = m_szFileName;
nMaxFile = COUNTOF(m_szFileName);
lpstrFileTitle = m_szFileTitle;
nMaxFileTitle = COUNTOF(m_szFileTitle);
lpstrInitialDir = pInitialDir;
lpstrTitle = pTitle;
Flags =
dwFlags |
OFN_EXPLORER |
OFN_HIDEREADONLY |
OFN_OVERWRITEPROMPT |
OFN_FILEMUSTEXIST;
lpstrDefExt = pDefExt;
}
BOOL
GetOpenFileName()
{
BOOL bResult = ::GetOpenFileName(this);
if (!bResult && CommDlgExtendedError() == CDERR_STRUCTSIZE)
{
lStructSize = OPENFILENAME_SIZE_VERSION_400;
bResult = ::GetOpenFileName(this);
}
return bResult;
}
BOOL
GetSaveFileName()
{
BOOL bResult = ::GetSaveFileName(this);
if (!bResult && CommDlgExtendedError() == CDERR_STRUCTSIZE)
{
lStructSize = OPENFILENAME_SIZE_VERSION_400;
bResult = ::GetSaveFileName(this);
}
return bResult;
}
private:
TCHAR m_szFileName[nFileNameLen];
TCHAR m_szFileTitle[nFileTitleSize];
TCHAR m_szCustomFilter[nCustomFilterSize];
};
#endif //_INC_CDERR
#ifdef _SHLOBJ_H_
//////////////////////////////////////////////////////////////////////////
//
// CBrowseInfo
//
// Wrapper class for SHBrowseForFolder() API
//
template <int nPathNameLen = MAX_PATH>
class CBrowseInfo : public BROWSEINFO
{
public:
CBrowseInfo(
HWND _hWndOwner = 0,
UINT _ulFlags = 0
)
{
ZeroMemory(this, sizeof(*this));
hwndOwner = _hWndOwner;
pszDisplayName = m_szPath;
ulFlags = _ulFlags;
}
BOOL
BrowseForFolder()
{
LPITEMIDLIST pidl = SHBrowseForFolder(this);
if (pidl)
{
TCHAR szPath[nPathNameLen];
if (SHGetPathFromIDList(pidl, szPath))
{
_tcscpy(m_szPath, szPath);
}
SHFree(pidl);
return TRUE;
}
return FALSE;
}
private:
TCHAR m_szPath[nPathNameLen];
};
#endif //_SHLOBJ_H_
#ifdef _INC_SETUPAPI
//////////////////////////////////////////////////////////////////////////
//
// CInf
//
// Wrapper class for Inf file parsing object and APIs
//
class CInf : public CHandle<HINF, CInf>
{
typedef CHandle<HINF, CInf> parent_type;
public:
CInf()
{
}
explicit
CInf(
PCTSTR FileName,
PCTSTR InfClass = 0,
DWORD InfStyle = INF_STYLE_WIN4,
PUINT ErrorLine = 0
) :
parent_type(::SetupOpenInfFile(
FileName,
InfClass,
InfStyle,
ErrorLine
))
{
}
public:
void Destroy()
{
::SetupCloseInfFile(*this);
}
bool IsValid()
{
return *this != 0;
}
};
#endif //_INC_SETUPAPI
//////////////////////////////////////////////////////////////////////////
//
// CDisplayWaitCursor
//
// Helper class that displays the wait cursor
//
class CDisplayWaitCursor
{
DISABLE_COPY_CONTRUCTION(CDisplayWaitCursor)
public:
CDisplayWaitCursor()
{
m_hOldCursor = SetCursor(LoadCursor(0, IDC_WAIT));
}
~CDisplayWaitCursor()
{
SetCursor(m_hOldCursor);
}
private:
HCURSOR m_hOldCursor;
};
//////////////////////////////////////////////////////////////////////////
//
// CSystemInfo
//
// Wrapper class for the GetSystemInfo() API
//
class CSystemInfo : public SYSTEM_INFO
{
public:
CSystemInfo()
{
GetSystemInfo(this);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CProc
//
// Wrapper class for the GetProcAddress() API
//
template <class prototype>
class CProc
{
public:
CProc(
prototype pfnDefault = 0
) :
m_pfnProc(pfnDefault)
{
}
CProc(
HMODULE hModule,
PCSTR pProcName
)
{
CHECK(m_pfnProc = (prototype) ::GetProcAddress(
hModule,
pProcName
));
}
CProc(
HMODULE hModule,
PCSTR pProcName,
prototype pfnDefault
)
{
m_pfnProc = (prototype) ::GetProcAddress(
hModule,
pProcName
);
if (m_pfnProc == 0)
{
m_pfnProc = pfnDefault;
}
}
operator prototype() const
{
return m_pfnProc;
}
private:
prototype m_pfnProc;
};
//////////////////////////////////////////////////////////////////////////
//
// DECL_CWINAPI
//
// Creates wrapper classes for fail-safe API address loading
//
#define DECL_CWINAPI(return_type, decl_spec, func_name, args) \
\
class C##func_name : public CProc<return_type (decl_spec *) args> \
{ \
public: \
typedef return_type (decl_spec *prototype) args; \
\
C##func_name() : \
CProc<prototype>(DefaultAPI) \
{ \
} \
\
C##func_name( \
HMODULE hModule, \
PCSTR pProcName = #func_name \
) : \
CProc<prototype>( \
hModule, \
pProcName, \
DefaultAPI \
) \
{ \
} \
\
protected: \
static return_type decl_spec DefaultAPI args \
{ \
::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); \
return 0; \
} \
\
} func_name \
//////////////////////////////////////////////////////////////////////////
//
// CBlob
//
// Contains a binary block of data specified by its start address and size
//
struct CBlob
{
const void *pData;
SIZE_T cbData;
CBlob()
{
}
CBlob(const void *_pData, SIZE_T _cbData)
{
pData = _pData;
cbData = _cbData;
}
};
//////////////////////////////////////////////////////////////////////////
//
// CStrBlob
//
// Contains an ANSI or UNICODE string without a terminating NULL
//
struct CStrBlob : public CBlob
{
explicit CStrBlob(PCSTR pStr)
{
if (pStr)
{
pData = pStr;
cbData = strlen(pStr) * sizeof(CHAR);
}
else
{
pData = "";
cbData = 0;
}
}
explicit CStrBlob(PCWSTR pStr)
{
if (pStr)
{
pData = pStr;
cbData = wcslen(pStr) * sizeof(WCHAR);
}
else
{
pData = "";
cbData = 0;
}
}
};
//////////////////////////////////////////////////////////////////////////
//
// CSzBlob
//
// Contains an ANSI or UNICODE string with a terminating NULL
//
struct CSzBlob : public CStrBlob
{
explicit CSzBlob(PCSTR pStr) : CStrBlob(pStr)
{
cbData += sizeof(CHAR);
}
explicit CSzBlob(PCWSTR pStr) : CStrBlob(pStr)
{
cbData += sizeof(WCHAR);
}
};
//////////////////////////////////////////////////////////////////////////
//
// CMultiSzBlob
//
// Contains a NULL terminated list of ANSI or UNICODE NULL terminated strings
//
struct CMultiSzBlob : public CBlob
{
explicit CMultiSzBlob(PCSTR pStr)
{
if (pStr)
{
pData = pStr;
cbData = (multiszlenA(pStr) + 1) * sizeof(CHAR);
}
else
{
pData = "\0";
cbData = 2 * sizeof(CHAR);
}
}
explicit CMultiSzBlob(PCWSTR pStr)
{
if (pStr)
{
pData = pStr;
cbData = (multiszlenW(pStr) + 1) * sizeof(WCHAR);
}
else
{
pData = L"\0";
cbData = 2 * sizeof(WCHAR);
}
}
};
//////////////////////////////////////////////////////////////////////////
//
// CBufferFill
//
// Helper class for filling in a block of memory in an overflow safe way
//
class CBufferFill
{
public:
CBufferFill(PVOID pBuffer, SIZE_T cbBuffer)
{
m_pTop = (PBYTE) pBuffer;
m_pEnd = (PBYTE) pBuffer + cbBuffer;
}
INT_PTR BytesLeft() const
{
return m_pEnd - m_pTop;
}
PVOID AddTop(const CBlob &Blob)
{
PVOID pDest = m_pTop;
m_pTop += Blob.cbData;
if (BytesLeft() >= 0)
{
CopyMemory(pDest, Blob.pData, Blob.cbData);
}
return pDest;
}
PVOID AddEnd(const CBlob &Blob)
{
m_pEnd -= Blob.cbData;
if (BytesLeft() >= 0)
{
CopyMemory(m_pEnd, Blob.pData, Blob.cbData);
}
return m_pEnd;
}
private:
PBYTE m_pTop;
PBYTE m_pEnd;
};
#if 0 //bugbug: not ready for prime time yet
//////////////////////////////////////////////////////////////////////////
//
// _tstring
//
// Helper class that handles UNICODE to ANSI conversions
//
_STD_BEGIN
class _tstring : public basic_string<TCHAR>
{
public:
_tstring(PCOSTR pStr)
{
ostr = pStr;
}
_tstring &operator =(PCOSTR pStr)
{
ostr = pStr;
return *this;
}
operator PCTSTR() const
{
if (empty())
{
USES_CONVERSION;
assign(T2O(ostr.c_str()));
}
return c_str();
}
operator PCOSTR() const
{
if (ostr.empty())
{
USES_CONVERSION;
ostr = T2O(c_str());
}
return ostr.c_str();
}
private:
basic_string<OCHAR> ostr;
};
_STD_END
#endif
//////////////////////////////////////////////////////////////////////////
//
// CMySimpleCriticalSection
//
// Implementation for a simple critical section class that does not
// handle recursions
//
class CMySimpleCriticalSection
{
public:
CMySimpleCriticalSection()
{
m_lLockCount = -1;
m_hLockHandle = 0;
}
~CMySimpleCriticalSection()
{
if (m_hLockHandle)
{
CloseHandle(m_hLockHandle);
}
}
VOID
Enter()
{
if (InterlockedIncrement(&m_lLockCount) != 0)
{
CheckLockHandle();
WaitForSingleObject(m_hLockHandle, INFINITE);
}
}
VOID
Leave()
{
if (InterlockedDecrement(&m_lLockCount) >= 0)
{
CheckLockHandle();
SetEvent(m_hLockHandle);
}
}
BOOL
TryEnter()
{
return InterlockedCompareExchange(&m_lLockCount, 0, -1) == -1;
}
protected:
VOID
CheckLockHandle()
{
if (!m_hLockHandle)
{
HANDLE hLockHandle;
CHECK(hLockHandle = CreateEvent(0, FALSE, FALSE, 0));
if (InterlockedCompareExchangePointer(&m_hLockHandle, hLockHandle, 0) != 0)
{
// another thread initialized and stored an hLockHandle
// before us, better close ours
CloseHandle(hLockHandle);
}
}
}
protected:
LONG m_lLockCount;
HANDLE m_hLockHandle;
};
//////////////////////////////////////////////////////////////////////////
//
// CMyCriticalSection
//
// Implementation for a full blown critical section class
//
class CMyCriticalSection : public CMySimpleCriticalSection
{
public:
CMyCriticalSection()
{
m_lRecursionCount = 0;
m_dwOwningThreadId = 0;
}
BOOL
Enter(
DWORD dwMilliseconds = INFINITE,
BOOL bAlertable = FALSE
)
{
DWORD dwCurrentThreadId = GetCurrentThreadId();
if (InterlockedIncrement(&m_lLockCount) == 0)
{
m_dwOwningThreadId = dwCurrentThreadId;
m_lRecursionCount = 1;
return TRUE;
}
else
{
if (m_dwOwningThreadId == dwCurrentThreadId)
{
++m_lRecursionCount;
return TRUE;
}
else
{
CheckLockHandle();
DWORD dwWaitResult = WaitForSingleObjectEx(
m_hLockHandle,
dwMilliseconds,
bAlertable
);
if (dwWaitResult == WAIT_OBJECT_0)
{
m_dwOwningThreadId = dwCurrentThreadId;
m_lRecursionCount = 1;
return TRUE;
}
else
{
return FALSE;
}
}
}
}
VOID
Leave()
{
if (--m_lRecursionCount != 0)
{
InterlockedDecrement(&m_lLockCount);
}
else
{
m_dwOwningThreadId = 0;
if (InterlockedDecrement(&m_lLockCount) >= 0)
{
CheckLockHandle();
SetEvent(m_hLockHandle);
}
}
}
BOOL
TryEnter()
{
DWORD dwCurrentThreadId = GetCurrentThreadId();
if (InterlockedCompareExchange(&m_lLockCount, 0, -1) == -1)
{
m_dwOwningThreadId = dwCurrentThreadId;
m_lRecursionCount = 1;
return TRUE;
}
else
{
if (m_dwOwningThreadId == dwCurrentThreadId)
{
InterlockedIncrement(&m_lLockCount);
++m_lRecursionCount;
return TRUE;
}
else
{
return FALSE;
}
}
}
protected:
LONG m_lRecursionCount;
DWORD m_dwOwningThreadId;
};
//////////////////////////////////////////////////////////////////////////
//
// CMultipleWait
//
// Wrapper class for the WaitForMultipleObjectsEx() API
//
class CMultipleWait : public CCppMem<HANDLE>
{
public:
CMultipleWait(
int nCount
) :
m_nCount(nCount),
CCppMem<HANDLE>(nCount)
{
}
DWORD
WaitFor(
BOOL bWaitAll = TRUE,
DWORD dwMilliseconds = INFINITE,
BOOL bAlertable = FALSE
)
{
return WaitForMultipleObjectsEx(
m_nCount,
*this,
bWaitAll,
dwMilliseconds,
bAlertable
);
}
void
Erase(
int nFirstHandle,
int nNumHandles = 1
)
{
m_nCount -= nNumHandles;
MoveData(
*this + nFirstHandle,
*this + nFirstHandle + nNumHandles,
m_nCount - nFirstHandle
);
}
private:
int m_nCount;
};
//////////////////////////////////////////////////////////////////////////
#endif //_WRAPPERS_H_