257 lines
7.3 KiB
C
257 lines
7.3 KiB
C
//
|
|
// Common defines used in the mars project.
|
|
//
|
|
|
|
#ifndef __MARSDEV_H
|
|
#define __MARSDEV_H
|
|
|
|
|
|
// Number of elements in array
|
|
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
|
|
|
|
// Size of struct up to but not including specified member
|
|
#define STRUCT_SIZE_TO_MEMBER(s,m) ((DWORD_PTR)(&(((s *)0)->m)))
|
|
|
|
// Size of a single member of a structure
|
|
#define SIZEOF_MEMBER(s,m) sizeof(((s *)0)->m)
|
|
|
|
// Size of struct up to and including specified member
|
|
#define STRUCT_SIZE_INCLUDING_MEMBER(s,m) (STRUCT_SIZE_TO_MEMBER(s,m) + SIZEOF_MEMBER(s,m))
|
|
|
|
#define SAFERELEASE(p) if ((p) != NULL) { (p)->Release(); (p) = NULL; } else;
|
|
|
|
// For destructor use -- doesn't NULL pointer
|
|
#define SAFERELEASE2(p) if ((p) != NULL) { (p)->Release();} else;
|
|
|
|
// Do strong typechecking
|
|
#ifdef SAFECAST
|
|
#undef SAFECAST
|
|
#endif
|
|
#define SAFECAST(_src, _type) (static_cast<_type>(_src))
|
|
|
|
//
|
|
// Validation functions.
|
|
//
|
|
|
|
#define IsValidReadPtr(ptr) \
|
|
((ptr) && !IsBadReadPtr((ptr), sizeof(*(ptr))))
|
|
|
|
#define IsValidWritePtr(ptr) \
|
|
((ptr) && !IsBadWritePtr((ptr), sizeof(*(ptr))))
|
|
|
|
#define IsValidStringW(pstr) \
|
|
((pstr) && !IsBadStringPtrW((pstr), (UINT)-1))
|
|
|
|
#define IsValidReadBuffer(ptr, n) \
|
|
((ptr) && !IsBadReadPtr((ptr), sizeof(*(ptr)) * (n)))
|
|
|
|
#define IsValidWriteBuffer(ptr, n) \
|
|
((ptr) && !IsBadWritePtr((ptr), sizeof(*(ptr)) * (n)))
|
|
|
|
#define IsValidInterfacePtr(punk) \
|
|
((punk) && IsValidReadPtr(punk) && \
|
|
!IsBadCodePtr(*((FARPROC*)punk)))
|
|
|
|
#define IsValidFunctionPtr(pfunc) \
|
|
((NULL != pfunc) && \
|
|
!IsBadCodePtr((FARPROC)pfunc))
|
|
|
|
#define IsValidBstr(bstr) \
|
|
((bstr) && IsValidWriteBuffer((BYTE*)(bstr), SysStringByteLen(bstr)))
|
|
|
|
#define IsValidOptionalBstr(bstr) \
|
|
((!bstr) || IsValidBstr(bstr))
|
|
|
|
#define IsValidVariantBoolVal(vb) \
|
|
(VARIANT_FALSE == vb || VARIANT_TRUE == vb)
|
|
|
|
#define IsValidVariantI4(var) \
|
|
(VT_I4 == (var).vt)
|
|
|
|
#define IsValidVariantBstr(var) \
|
|
(VT_BSTR == (var).vt && IsValidBstr((var).bstrVal))
|
|
|
|
#define IsValidVariantMissingOptional(var) \
|
|
(VT_ERROR == (var).vt && DISP_E_PARAMNOTFOUND == (var).scode)
|
|
|
|
#define IsValidFlag(f, fAll) \
|
|
(!((f) & ~(fAll)))
|
|
|
|
BOOL IsValidVariant(VARIANT var);
|
|
BOOL IsValidStringPtrBufferW(LPOLESTR* ppstr, UINT n);
|
|
|
|
|
|
#define IsValidString IsValidStringW
|
|
#define IsValidStringPtrBuffer IsValidStringPtrBufferW
|
|
|
|
//
|
|
// API parameter validation helpers. Use these on public APIs. If a parameter
|
|
// is bad on debug build a RIP message will be generated.
|
|
//
|
|
|
|
#ifdef DEBUG
|
|
|
|
BOOL API_IsValidReadPtr(void* ptr, UINT cbSize);
|
|
BOOL API_IsValidWritePtr(void* ptr, UINT cbSize);
|
|
BOOL API_IsValidStringW(LPCWSTR psz);
|
|
BOOL API_IsValidReadBuffer(void* ptr, UINT cbSize, UINT n);
|
|
BOOL API_IsValidWriteBuffer(void* ptr, UINT cbSize, UINT n);
|
|
BOOL API_IsValidInterfacePtr(IUnknown* punk);
|
|
BOOL API_IsValidFunctionPtr(void *pfunc);
|
|
BOOL API_IsValidVariant(VARIANT var);
|
|
BOOL API_IsValidVariantI4(VARIANT var);
|
|
BOOL API_IsValidVariantBstr(VARIANT var);
|
|
BOOL API_IsValidBstr(BSTR bstr);
|
|
BOOL API_IsValidOptionalBstr(BSTR bstr);
|
|
BOOL API_IsValidFlag(DWORD dwFlag, DWORD dwAllFlags);
|
|
BOOL API_IsValidStringPtrBufferW(LPOLESTR* ppStr, UINT n);
|
|
|
|
#define API_IsValidString API_IsValidStringW
|
|
#define API_IsValidStringPtrBuffer API_IsValidStringPtrBufferW
|
|
|
|
#endif //Debug
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define API_IsValidReadPtr(ptr) \
|
|
API_IsValidReadPtr((ptr), sizeof(*(ptr)))
|
|
|
|
#define API_IsValidWritePtr(ptr) \
|
|
API_IsValidWritePtr((ptr), sizeof(*(ptr)))
|
|
|
|
#define API_IsValidReadBuffer(ptr, n) \
|
|
API_IsValidReadBuffer((ptr), sizeof(*(ptr)), (n))
|
|
|
|
#define API_IsValidWriteBuffer(ptr, n) \
|
|
API_IsValidWriteBuffer((ptr), sizeof(*(ptr)), (n))
|
|
|
|
#else // DEBUG
|
|
|
|
#define API_IsValidReadPtr IsValidReadPtr
|
|
#define API_IsValidWritePtr IsValidWritePtr
|
|
#define API_IsValidString IsValidString
|
|
#define API_IsValidStringW IsValidStringW
|
|
#define API_IsValidReadBuffer IsValidReadBuffer
|
|
#define API_IsValidWriteBuffer IsValidWriteBuffer
|
|
#define API_IsValidInterfacePtr IsValidInterfacePtr
|
|
#define API_IsValidFunctionPtr IsValidFunctionPtr
|
|
#define API_IsValidVariant IsValidVariant
|
|
#define API_IsValidVariantI4 IsValidVariantI4
|
|
#define API_IsValidVariantBstr IsValidVariantBstr
|
|
#define API_IsValidBstr IsValidBstr
|
|
#define API_IsValidOptionalBstr IsValidOptionalBstr
|
|
#define API_IsValidFlag IsValidFlag
|
|
#define API_IsValidStringPtrBuffer IsValidStringPtrBufferW
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
//
|
|
// Function prototypes.
|
|
//
|
|
|
|
BOOL StrEqlW(LPCWSTR psz1, LPCWSTR psz2);
|
|
BOOL StrEqlA(LPCSTR psz1, LPCSTR psz2);
|
|
#define StrEql StrEqlW
|
|
|
|
UINT64 HexStringToUINT64W(LPCWSTR lpwstr);
|
|
|
|
//
|
|
// Macro magic to help define away functions.
|
|
//
|
|
// TO USE:
|
|
//
|
|
// If you don't want a function to be used in the code do the following:
|
|
// #undef funcA
|
|
// #define funcA DON_USE(funcA, funcB)
|
|
//
|
|
// This will result in funcA being redefined to Don_not_use_funcA_use_funcB.
|
|
// A compilation error complaining that Don_not_use_funcA_use_funcB is undefined
|
|
// will be generated whenever anyone tries to use funcA.
|
|
//
|
|
|
|
#define MACRO_CAT(a,b) \
|
|
a##b
|
|
|
|
#define DONT_USE(a,b) \
|
|
MACRO_CAT(Do_not_use_##a,_use_##b)
|
|
|
|
|
|
// return SCRIPT_ERROR upon serious error that shouldn't occur; will break in debug builds
|
|
#ifdef DEBUG
|
|
#define SCRIPT_ERROR E_FAIL
|
|
#else
|
|
#define SCRIPT_ERROR S_FALSE
|
|
#endif
|
|
|
|
#define RECTWIDTH(rc) ((rc).right-(rc).left)
|
|
#define RECTHEIGHT(rc) ((rc).bottom-(rc).top)
|
|
|
|
|
|
HRESULT SanitizeResult(HRESULT hr);
|
|
|
|
|
|
// BITBOOL macros just make using single-bit bools a little safer. You can't nonchalantly assign
|
|
// any "int" value to a bit bool and expect it to always work. "BOOLIFY" it first.
|
|
//
|
|
#define BOOLIFY(expr) (!!(expr))
|
|
|
|
// BUGBUG (scotth): we should probably make this a 'bool', but be careful
|
|
// because the Alpha compiler might not recognize it yet. Talk to AndyP.
|
|
|
|
// This isn't a BOOL because BOOL is signed and the compiler produces
|
|
// sloppy code when testing for a single bit.
|
|
typedef DWORD BITBOOL;
|
|
//
|
|
|
|
#define VARIANT_BOOLIFY(expr) ((expr) ? VARIANT_TRUE : VARIANT_FALSE)
|
|
|
|
|
|
/*
|
|
TraceResult Macros
|
|
|
|
The idea behind these macros is to have one entry and exit point per
|
|
function to reduce errors (primarily bad state / leaks). They generally
|
|
require an HRESULT hr, and an 'exit' label that returns hr and performs
|
|
any cleanup that might be needed.
|
|
|
|
In addition to encouraging a unified exit point, these macros also debug
|
|
spew if something fails (try to only use these macros on things that
|
|
should never fail). This can be extremely useful when something is
|
|
failing many layers deep in the code. To see the spew, you need to set
|
|
TF_TRACERESULT. To break on such failures, set BF_TRACERESULT.
|
|
|
|
Common mistake: you must set hr when you use IF_FAILEXIT as it is not
|
|
automatically set to _hresult (for flexibility).
|
|
*/
|
|
|
|
#define IF_FAILEXIT(_hresult) \
|
|
if (FAILED(_hresult)) { \
|
|
TraceResult(hr); \
|
|
goto exit; \
|
|
} else
|
|
|
|
#define IF_NULLEXIT(_palloc) \
|
|
if (NULL == (_palloc)) { \
|
|
hr = TraceResult(E_OUTOFMEMORY); \
|
|
goto exit; \
|
|
} else
|
|
|
|
#define IF_TRUEEXIT(_expression, _hresult) \
|
|
if (_expression) { \
|
|
hr = TraceResult(_hresult); \
|
|
goto exit; \
|
|
} else
|
|
|
|
#define IF_FALSEEXIT(_expression, _hresult) \
|
|
if (FALSE == _expression) { \
|
|
hr = TraceResult(_hresult); \
|
|
goto exit; \
|
|
} else
|
|
|
|
|
|
#define TraceResult(_hresult) _hresult
|
|
|
|
#endif // __MARSDEV_H
|