|
|
/********************************************************************
Copyright (c) 1999-2000 Microsoft Corporation
Module Name: pfrutil.h
Abstract: PFR utility stuff
Revision History: DerekM created 05/01/99
********************************************************************/
#ifndef PFRUTIL_H
#define PFRUTIL_H
// this turns on the manifest mode heap collection
#define MANIFEST_HEAP
// make sure both _DEBUG & DEBUG are defined if one is defined. Otherwise
// the ASSERT macro never does anything
#if defined(_DEBUG) && !defined(DEBUG)
#define DEBUG 1
#endif
#if defined(DEBUG) && !defined(_DEBUG)
#define _DEBUG 1
#endif
#include "dbgtrace.h"
////////////////////////////////////////////////////////////////////////////
// tracing wrappers
// can't call HRESULT_FROM_WIN32 with a fn as a parameter cuz it is a macro
// and evaluates the expression 3 times. This is a particularlly bad thing
// when u don't look at macros first to see what they do.
inline HRESULT ChangeErrToHR(DWORD dwErr) { return HRESULT_FROM_WIN32(dwErr); }
#if defined(NOTRACE)
#define INIT_TRACING
#define TERM_TRACING
#define USE_TRACING(sz)
#define DBG_MSG(sz)
#define TESTHR(hr, fn) \
hr = (fn);
#define TESTBOOL(hr, fn) \
hr = ((fn) ? NOERROR : HRESULT_FROM_WIN32(GetLastError()));
#define TESTERR(hr, fn) \
SetLastError((fn)); \ hr = HRESULT_FROM_WIN32(GetLastError());
#define VALIDATEPARM(hr, expr) \
hr = ((expr) ? E_INVALIDARG : NOERROR);
#define VALIDATEEXPR(hr, expr, hrErr) \
hr = ((expr) ? (hrErr) : NOERROR);
#else
#define INIT_TRACING \
InitAsyncTrace();
#define TERM_TRACING \
TermAsyncTrace();
#define USE_TRACING(sz) \
TraceQuietEnter(sz); \ TraceFunctEntry(sz); \ DWORD __dwtraceGLE = GetLastError(); \
#define DBG_MSG(sz) \
ErrorTrace(0, sz)
#define TESTHR(hr, fn) \
if (FAILED(hr = (fn))) \ { \ __dwtraceGLE = GetLastError(); \ ErrorTrace(0, "%s failed. Err: 0x%08x", #fn, hr); \ SetLastError(__dwtraceGLE); \ } \
#define TESTBOOL(hr, fn) \
hr = NOERROR; \ if ((fn) == FALSE) \ { \ __dwtraceGLE = GetLastError(); \ hr = HRESULT_FROM_WIN32(__dwtraceGLE); \ ErrorTrace(0, "%s failed. Err: 0x%08x", #fn, __dwtraceGLE); \ SetLastError(__dwtraceGLE); \ }
#define TESTERR(hr, fn) \
SetLastError((fn)); \ if (FAILED(hr = HRESULT_FROM_WIN32(GetLastError()))) \ { \ __dwtraceGLE = GetLastError(); \ ErrorTrace(0, "%s failed. Err: %d", #fn, __dwtraceGLE); \ SetLastError(__dwtraceGLE); \ }
#define VALIDATEPARM(hr, expr) \
if (expr) \ { \ ErrorTrace(0, "Invalid parameters passed to %s", \ ___pszFunctionName); \ SetLastError(ERROR_INVALID_PARAMETER); \ hr = E_INVALIDARG; \ } \ else hr = NOERROR;
#define VALIDATEEXPR(hr, expr, hrErr) \
if (expr) \ { \ ErrorTrace(0, "Expression failure %s", #expr); \ hr = (hrErr); \ } \ else hr = NOERROR;
#endif
////////////////////////////////////////////////////////////////////////////
// Memory
#if defined(DEBUG) || defined(_DEBUG)
// this structure must ALWAYS be 8 byte aligned. Add padding to the end if
// it isn't.
struct SMyMemDebug { __int64 hHeap; __int64 cb; DWORD dwTag; DWORD dwChk; }; #endif
extern HANDLE g_hPFPrivateHeap;
// **************************************************************************
inline HANDLE MyHeapCreate(SIZE_T cbInitial = 8192, SIZE_T cbMax = 0) { return HeapCreate(0, cbInitial, cbMax); }
// **************************************************************************
inline BOOL MyHeapDestroy(HANDLE hHeap) { return HeapDestroy(hHeap); }
// **************************************************************************
inline LPVOID MyAlloc(SIZE_T cb, HANDLE hHeap = NULL, BOOL fZero = TRUE) { #if defined(DEBUG) || defined(_DEBUG)
SMyMemDebug *psmmd; LPBYTE pb;
cb += (sizeof(SMyMemDebug) + 4); hHeap = (hHeap != NULL) ? hHeap : GetProcessHeap(); pb = (LPBYTE)HeapAlloc(hHeap, ((fZero) ? HEAP_ZERO_MEMORY : 0), cb); if (pb != NULL) { psmmd = (SMyMemDebug *)pb; psmmd->hHeap = (__int64)hHeap; psmmd->cb = (__int64)cb; psmmd->dwTag = 0xBCBCBCBC; psmmd->dwChk = 0xBCBCBCBC;
// do this cuz it's easier than figuring out the alignment and
// manually converting it to a 4 byte aligned value
*(pb + cb - 4) = 0xBC; *(pb + cb - 3) = 0xBC; *(pb + cb - 2) = 0xBC; *(pb + cb - 1) = 0xBC;
pb = (PBYTE)pb + sizeof(SMyMemDebug); } return pb;
#else
return HeapAlloc(((hHeap != NULL) ? hHeap : GetProcessHeap()), ((fZero) ? HEAP_ZERO_MEMORY : 0), cb); #endif
}
// **************************************************************************
inline LPVOID MyReAlloc(LPVOID pv, SIZE_T cb, HANDLE hHeap = NULL, BOOL fZero = TRUE) { #if defined(DEBUG) || defined(_DEBUG)
SMyMemDebug *psmmd; SIZE_T cbOld; LPBYTE pbNew; LPBYTE pb = (LPBYTE)pv;
// if this is NULL, force a call to HeapReAlloc so that it can set the
// proper error for GLE to fetch
if (pv == NULL) { SetLastError(0); return NULL; }
pb -= sizeof(SMyMemDebug); hHeap = (hHeap != NULL) ? hHeap : GetProcessHeap();
// wrap this in a try block in case the memory was not allocated
// by us or is corrupted- in which case the following could
// cause an AV.
__try { psmmd = (SMyMemDebug *)pb; cbOld = (SIZE_T)psmmd->cb; _ASSERT(psmmd->hHeap == (__int64)hHeap); _ASSERT(psmmd->dwTag == 0xBCBCBCBC); _ASSERT(psmmd->dwChk == 0xBCBCBCBC);
// do this cuz it's easier than figuring out the alignment and
// manually converting it to a 4 byte aligned value
_ASSERT(*(pb + cbOld - 4) == 0xBC); _ASSERT(*(pb + cbOld - 3) == 0xBC); _ASSERT(*(pb + cbOld - 2) == 0xBC); _ASSERT(*(pb + cbOld - 1) == 0xBC);
if (psmmd->hHeap != (__int64)hHeap) hHeap = (HANDLE)(DWORD_PTR)psmmd->hHeap; } __except(EXCEPTION_EXECUTE_HANDLER) { _ASSERT(FALSE); }
hHeap = *((HANDLE *)pb);
cb += (sizeof(SMyMemDebug) + 4); pbNew = (LPBYTE)HeapReAlloc(hHeap, ((fZero) ? HEAP_ZERO_MEMORY : 0), pb, cb); if (pbNew != NULL) { psmmd = (SMyMemDebug *)pb; psmmd->hHeap = (__int64)hHeap; psmmd->cb = (__int64)cb; psmmd->dwTag = 0xBCBCBCBC; psmmd->dwChk = 0xBCBCBCBC;
// do this cuz it's easier than figuring out the alignment and
// manually converting it to a 4 byte aligned value
*(pb + cb - 4) = 0xBC; *(pb + cb - 3) = 0xBC; *(pb + cb - 2) = 0xBC; *(pb + cb - 1) = 0xBC;
pb = (PBYTE)pb + sizeof(SMyMemDebug); }
return pv;
#else
return HeapReAlloc(((hHeap != NULL) ? hHeap : GetProcessHeap()), ((fZero) ? HEAP_ZERO_MEMORY : 0), pv, cb); #endif
}
// **************************************************************************
inline BOOL MyFree(LPVOID pv, HANDLE hHeap = NULL) { #if defined(DEBUG) || defined(_DEBUG)
SMyMemDebug *psmmd; SIZE_T cbOld; HANDLE hAllocHeap; LPBYTE pb = (LPBYTE)pv;
// if this is NULL, force a call to HeapFree so that it can set the
// proper error for GLE to fetch
if (pv == NULL) return TRUE;
pb -= sizeof(SMyMemDebug); hHeap = (hHeap != NULL) ? hHeap : GetProcessHeap();
// wrap this in a try block in case the memory was not allocated
// by us or is corrupted- in which case the following could
// cause an AV.
__try { psmmd = (SMyMemDebug *)pb; cbOld = (SIZE_T)psmmd->cb; _ASSERT(psmmd->hHeap == (__int64)hHeap); _ASSERT(psmmd->dwTag == 0xBCBCBCBC); _ASSERT(psmmd->dwChk == 0xBCBCBCBC);
// do this cuz it's easier than figuring out the alignment and
// manually converting it to a 4 byte aligned value
_ASSERT(*(pb + cbOld - 4) == 0xBC); _ASSERT(*(pb + cbOld - 3) == 0xBC); _ASSERT(*(pb + cbOld - 2) == 0xBC); _ASSERT(*(pb + cbOld - 1) == 0xBC);
if (psmmd->hHeap != (__int64)hHeap) hHeap = (HANDLE)(DWORD_PTR)psmmd->hHeap; } __except(EXCEPTION_EXECUTE_HANDLER) { _ASSERT(FALSE); }
FillMemory(pb, cbOld, 0xCB);
return HeapFree(hHeap, 0, pb);
#else
return HeapFree(((hHeap != NULL) ? hHeap : GetProcessHeap()), 0, pv); #endif
}
////////////////////////////////////////////////////////////////////////////
// useful inlines / defines
// **************************************************************************
inline DWORD MyMax(DWORD a, DWORD b) { return (a > b) ? a : b; }
// **************************************************************************
inline DWORD MyMin(DWORD a, DWORD b) { return (a <= b) ? a : b; }
#define Err2HR(dwErr) HRESULT_FROM_WIN32(dwErr)
#define sizeofSTRW(wsz) sizeof(wsz) / sizeof(WCHAR)
////////////////////////////////////////////////////////////////////////////
// Files
const WCHAR c_wszDirSuffix[] = L".dir00";
HRESULT OpenFileMapped(LPWSTR wszFile, LPVOID *ppvFile, DWORD *pcbFile); HRESULT DeleteTempFile(LPWSTR wszFile); HRESULT MyCallNamedPipe(LPCWSTR wszPipe, LPVOID pvIn, DWORD cbIn, LPVOID pvOut, DWORD cbOut, DWORD *pcbRead, DWORD dwWaitPipe, DWORD dwWaitRead = INFINITE); DWORD CreateTempDirAndFile(LPCWSTR wszTempDir, LPCWSTR wszName, LPWSTR *pwszPath); BOOL DeleteTempDirAndFile(LPCWSTR wszPath, BOOL fFilePresent); #ifdef MANIFEST_HEAP
BOOL DeleteFullAndTriageMiniDumps(LPCWSTR wszPath); #endif // MANIFEST_HEAP
////////////////////////////////////////////////////////////////////////////
// Security
BOOL AllocSD(SECURITY_DESCRIPTOR *psd, DWORD dwOLs, DWORD dwAd, DWORD dwWA); void FreeSD(SECURITY_DESCRIPTOR *psd); BOOL IsUserAnAdmin(HANDLE hToken);
////////////////////////////////////////////////////////////////////////////
// Registry
enum EPFORK { orkWantWrite = 0x1, orkUseWOW64 = 0x2, };
HRESULT OpenRegKey(HKEY hkeyMain, LPCWSTR wszSubKey, DWORD dwOpt, HKEY *phkey); HRESULT ReadRegEntry(HKEY hkey, LPCWSTR szValName, DWORD *pdwType, PBYTE pbBuffer, DWORD *pcbBuffer, PBYTE pbDefault, DWORD cbDefault); HRESULT ReadRegEntry(HKEY *rghkey, DWORD cKeys, LPCWSTR wszValName, DWORD *pdwType, PBYTE pbBuffer, DWORD *pcbBuffer, PBYTE pbDefault, DWORD cbDefault, DWORD *piKey = NULL);
////////////////////////////////////////////////////////////////////////////
// version info
#define APP_WINCOMP 0x1
#define APP_MSAPP 0x2
DWORD IsMicrosoftApp(LPWSTR wszAppPath, PBYTE pbAppInfo, DWORD cbAppInfo);
////////////////////////////////////////////////////////////////////////////
// String
WCHAR *MyStrStrIW(const WCHAR *wcs1, const WCHAR *wcs2); CHAR *MyStrStrIA(const CHAR *cs1, const CHAR *cs2); HRESULT MyURLEncode(LPWSTR wszDest, DWORD cchDest, LPWSTR wszSrc);
////////////////////////////////////////////////////////////////////////////
// CPFGenericClassBase
class CPFGenericClassBase { public: // CPFGenericClassBase(void) {}
// virtual ~CPFGenericClassBase(void) {}
void *operator new(size_t size) { return MyAlloc(size, NULL, FALSE); }
void operator delete(void *pvMem) { if (pvMem != NULL) MyFree(pvMem, NULL); } };
class CPFPrivHeapGenericClassBase { public: // CPFGenericClassBase(void) {}
// virtual ~CPFGenericClassBase(void) {}
void *operator new(size_t size) { return MyAlloc(size, g_hPFPrivateHeap, FALSE); }
void operator delete(void *pvMem) { if (pvMem != NULL) MyFree(pvMem, g_hPFPrivateHeap); } };
////////////////////////////////////////////////////////////////////////////
// CAutoUnlockCS
// This class wrappers a critical section. It will automatically unlock the
// CS when the class destructs (assuming it is locked)
// NOTE: this object is intended to be used only as a local variable of a
// function, not as a global variable or class member.
class CAutoUnlockCS { private: #if defined(DEBUG) || defined(_DEBUG)
DWORD m_dwOwningThread; #endif
CRITICAL_SECTION *m_pcs; DWORD m_cLocks;
public: CAutoUnlockCS(CRITICAL_SECTION *pcs, BOOL fTakeLock = FALSE) { m_pcs = pcs; m_cLocks = 0; #if defined(DEBUG) || defined(_DEBUG)
m_dwOwningThread = 0; #endif
if (fTakeLock) this->Lock(); }
~CAutoUnlockCS(void) { _ASSERT(m_cLocks <= 1); if (m_pcs != NULL) { #if defined(DEBUG) || defined(_DEBUG)
if (m_cLocks > 0) _ASSERT(m_dwOwningThread == GetCurrentThreadId()); #endif
while(m_cLocks > 0) { LeaveCriticalSection(m_pcs); m_cLocks--; } } }
void Lock(void) { if (m_pcs != NULL) { EnterCriticalSection(m_pcs); m_cLocks++; #if defined(DEBUG) || defined(_DEBUG)
m_dwOwningThread = GetCurrentThreadId(); #endif
} }
void Unlock(void) { _ASSERT(m_cLocks > 0); _ASSERT(m_dwOwningThread == GetCurrentThreadId()); if (m_pcs != NULL && m_cLocks > 0) { m_cLocks--; LeaveCriticalSection(m_pcs); } #if defined(DEBUG) || defined(_DEBUG)
if (m_cLocks == 0) m_dwOwningThread = 0; #endif
} };
////////////////////////////////////////////////////////////////////////////
// CAutoUnlockMutex
// This class wrappers a mutex. It will automatically unlock the
// mutex when the class destructs (assuming it is owned)
// NOTE: this object is intended to be used only as a local variable of a
// function, not as a global variable or class member.
class CAutoUnlockMutex { private: #if defined(DEBUG) || defined(_DEBUG)
DWORD m_dwOwningThread; #endif
HANDLE m_hmut; DWORD m_cLocks;
public: CAutoUnlockMutex(HANDLE hmut, BOOL fTakeLock = FALSE) { m_hmut = hmut; m_cLocks = 0; #if defined(DEBUG) || defined(_DEBUG)
m_dwOwningThread = 0; #endif
if (fTakeLock) this->Lock(); }
~CAutoUnlockMutex(void) { _ASSERT(m_cLocks <= 1); if (m_hmut != NULL) { #if defined(DEBUG) || defined(_DEBUG)
if (m_cLocks > 0) _ASSERT(m_dwOwningThread == GetCurrentThreadId()); #endif
while(m_cLocks > 0) { ReleaseMutex(m_hmut); m_cLocks--; } } }
BOOL Lock(DWORD dwTimeout = INFINITE) { if (m_hmut != NULL) { if (WaitForSingleObject(m_hmut, dwTimeout) != WAIT_OBJECT_0) return FALSE;
m_cLocks++; #if defined(DEBUG) || defined(_DEBUG)
m_dwOwningThread = GetCurrentThreadId(); #endif
} return TRUE; }
void Unlock(void) { _ASSERT(m_cLocks > 0); _ASSERT(m_dwOwningThread == GetCurrentThreadId()); if (m_hmut != NULL && m_cLocks > 0) { m_cLocks--; ReleaseMutex(m_hmut); } } };
#endif
|