Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

470 lines
15 KiB

#if !defined(_WINDOWS_BCL_COMMON_H_INCLUDED_)
#define _WINDOWS_BCL_COMMON_H_INCLUDED_
#pragma once
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
bcl_common.h
Abstract:
Definitions common to all of the Base Class Libraries
implementation.
Author:
Michael Grier (MGrier) 2/6/2002
Revision History:
--*/
#include <memory.h> // for memcpy
#include <string.h> // for memmove
#include <limits.h> // for CHAR_BIT
namespace BCL {
//
// Macros for error handling in BCL functions
//
// Rather than try to break down the purpose of each, here's a couple of
// examples:
//
// TCallDisposition Foo(int i) { // TCallDisposition indicates internal linkage
// BCL_MAYFAIL_PROLOG // first line of any function that can fail
// int j;
// BCL_PARAMETER_CHECK((i >= 0) && (i <= 100));
// BCL_IFCALLFAILED_EXIT(Bar(i, &j)); // assumes Bar also has internal linkage
// BCL_ASSERT(j >= 0);
// BCL_INTERNAL_ERROR_CHECK(i != j);
// BCL_MAYFAIL_EPILOG_INTERNAL // last line when internal linkage
// }
//
// BOOL Win32ishFoo(int i) {
// BCL_MAYFAIL_PROLOG
// BCL_IFCALLFAILED_EXIT(Foo(i));
// BCL_MAYFAIL_EPILOG_PUBLIC
// }
//
#define BCL_ORIGINATE_ERROR(_error) do { _bcl_cd = (_error); goto Exit; } while (0)
#define BCL_CALLBACK_FAILED do { goto Exit; } while (0)
#if _X86_
#define BCL_DEBUG_BREAK do { __asm { int 3 } } while (0)
#else
#define BCL_DEBUG_BREAK do { DebugBreak(VOID); } while (0)
#endif
#define BCL_ASSERTION_FAILURE_ACTION(_szExpr) BCL_DEBUG_BREAK
#define BCL_ASSERT(_e) do { if (!(_e)) { BCL_ASSERTION_FAILURE_ACTION(#_e); } } while (0)
#define BCL_COMPILE_TIME_ASSERT(_e) typedef char __c_assert[(_e) ? 1 : -1]
#define BCL_INTERNAL_ERROR_FAILURE_ACTION(_szExpr) do { BCL_DEBUG_BREAK; _bcl_cd = TCallDisposition::InternalError_RuntimeCheck(); goto Exit; } while (0)
#define BCL_INTERNAL_ERROR_CHECK(_e) do { if (!(_e)) { BCL_INTERNAL_ERROR_FAILURE_ACTION(#_e); } } while (0)
#define BCL_MAYFAIL_PROLOG \
TCallDisposition _bcl_cd = TCallDisposition::InternalError_EpilogSkipped();
#define BCL_MAYFAIL_EPILOG_INTERNAL \
_bcl_cd = TCallDisposition::Success(); \
if (false) { goto Exit; } \
Exit: \
return _bcl_cd;
#define BCL_MAYFAIL_EPILOG_PUBLIC \
_bcl_cd = TCallDisposition::Success(); \
if (false) { goto Exit; } \
Exit: \
return _bcl_cd.OnPublicReturn();
#define BCL_NOFAIL_PROLOG /* nothing */
#define BCL_NOFAIL_EPILOG /* nothing */
#define BCL_PARAMETER_CHECK_FAILURE_ACTION(_p) do { _bcl_cd = TCallDisposition::BadParameter(); goto Exit; } while (0)
#define BCL_PARAMETER_CHECK(_p) do { if (!(_p)) { BCL_PARAMETER_CHECK_FAILURE_ACTION(_p); } } while (0)
#define BCL_IFCALLFAILED_EXIT(_e) do { const TCallDisposition _bcl_cd_temp = (_e); if (_bcl_cd_temp.DidFail()) { _bcl_cd = _bcl_cd_temp; goto Exit; } } while (0)
#define BCL_NUMBER_OF(_x) (sizeof(_x) / sizeof((_x)[0]))
template <typename T, typename TSizeT> class CConstantPointerAndCountPair;
template <typename T, typename TSizeT> class CMutablePointerAndCountPair;
template <typename T, typename TSizeT> class CConstantPointerAndCountRefPair;
template <typename T, typename TSizeT> class CMutablePointerAndCountRefPair;
template <typename T, typename TSizeT>
class CConstantPointerAndCountPair
{
public:
typedef const T *TConstantArray;
typedef T *TMutableArray;
typedef T TPointee;
typedef TSizeT TCount;
inline CConstantPointerAndCountPair() : m_prg(NULL), m_c(0) { }
inline CConstantPointerAndCountPair(TConstantArray prg, TSizeT c) : m_prg(prg), m_c(c) { }
inline CConstantPointerAndCountPair(const CMutablePointerAndCountPair<T, TSizeT> &r) : m_prg(r.m_prg), m_c(r.m_c) { }
inline CConstantPointerAndCountPair(const CConstantPointerAndCountPair &r) : m_prg(r.m_prg), m_c(r.m_c) { }
inline ~CConstantPointerAndCountPair() { }
CConstantPointerAndCountPair &operator =(const CConstantPointerAndCountPair &r)
{
m_prg = r.m_prg;
m_c = r.m_c;
return *this;
}
CConstantPointerAndCountPair &operator =(const CMutablePointerAndCountPair<T, TSizeT> &r)
{
m_prg = r.m_prg;
m_c = r.m_c;
return *this;
}
inline TConstantArray GetPointer() const { return m_prg; }
inline TSizeT GetCount() const { return m_c; }
inline TConstantArray &Pointer() { return m_prg; }
inline TSizeT &Count() { return m_c; }
inline void SetCount(TSizeT c) { m_c = c; }
inline void SetPointer(TConstantArray prg) { m_prg = prg; }
inline void SetPointerAndCount(TConstantArray prg, TSizeT c) { m_prg = prg; m_c = c; }
inline bool Valid() const { return (m_prg != NULL) || (m_c == 0); }
inline CConstantPointerAndCountPair GetOffsetPair(TSizeT n) { return CConstantPointerAndCountPair(m_prg + n, m_c - n); }
protected:
TConstantArray m_prg;
TSizeT m_c;
}; // BCL::CConstantPointerAndCountPair<T, TSizeT>
template <typename T, typename TSizeT>
class CMutablePointerAndCountPair : public CConstantPointerAndCountPair<T, TSizeT>
{
public:
typedef const T *TConstantArray;
typedef T *TMutableArray;
inline CMutablePointerAndCountPair() { }
inline CMutablePointerAndCountPair(TMutableArray prg, TSizeT c) : CConstantPointerAndCountPair<T, TSizeT>(prg, c) { }
inline ~CMutablePointerAndCountPair() { }
using CConstantPointerAndCountPair<T, TSizeT>::Valid;
CMutablePointerAndCountPair &operator =(const CMutablePointerAndCountPair &r)
{
m_prg = r.m_prg;
m_c = r.m_c;
return *this;
}
inline TMutableArray GetPointer() const { return const_cast<TMutableArray>(m_prg); }
inline TSizeT GetCount() const { return m_c; }
inline TMutableArray &Pointer() { return const_cast<TMutableArray &>(m_prg); }
inline TSizeT &Count() { return m_c; }
inline void SetPointer(TMutableArray prg) { m_prg = prg; }
inline void SetCount(TSizeT c) { m_c = c; }
inline void SetPointerAndCount(TMutableArray prg, TSizeT c) { m_prg = prg; m_c = c; }
}; // BCL::CMutablePointerAndCountPair<T, TSizeT>
template <typename T, typename TSizeT>
class CConstantPointerAndCountRefPair
{
public:
typedef const T *TConstantArray;
typedef T *TMutableArray;
typedef T TPointee;
typedef TSizeT TCount;
inline CConstantPointerAndCountRefPair(TConstantArray &rprg, TSizeT &rc) : m_rprg(rprg), m_rc(rc) { }
inline CConstantPointerAndCountRefPair(const CMutablePointerAndCountRefPair<T, TSizeT> &r) : m_rprg(r.m_rprg), m_rc(r.m_rc) { }
inline CConstantPointerAndCountRefPair(const CConstantPointerAndCountRefPair &r) : m_rprg(r.m_rprg), m_rc(r.m_rc) { }
inline ~CConstantPointerAndCountRefPair() { }
inline CConstantPointerAndCountRefPair &operator =(const CConstantPointerAndCountPair<T, TSizeT> &r)
{
m_rprg = r.GetPointer();
m_rc = r.GetCount();
return *this;
}
inline operator CConstantPointerAndCountPair<T, TSizeT>() const { return BCL::CConstantPointerAndCountPair<T, TSizeT>(m_rprg, m_rc); }
inline TConstantArray GetPointer() const { return m_rprg; }
inline TSizeT GetCount() const { return m_rc; }
inline TConstantArray &Pointer() { return m_rprg; }
inline TSizeT &Count() { return m_rc; }
inline void SetCount(TSizeT c) { m_rc = c; }
inline void SetPointer(TConstantArray prg) { m_rprg = prg; }
inline void SetPointerAndCount(TConstantArray prg, TSizeT c) { m_rprg = prg; m_rc = c; }
inline bool Valid() const { return (m_rprg != NULL) || (m_rc == 0); }
inline CConstantPointerAndCountPair GetOffsetPair(TSizeT n) { return CConstantPointerAndCountPair(m_rprg + n, m_rc - n); }
protected:
TConstantArray &m_rprg;
TSizeT &m_rc;
}; // BCL::CConstantPointerAndCountRefPair<T, TSizeT>
template <typename T, typename TSizeT>
class CMutablePointerAndCountRefPair : public CConstantPointerAndCountRefPair<T, TSizeT>
{
public:
typedef const T *TConstantArray;
typedef T *TMutableArray;
inline CMutablePointerAndCountRefPair(TMutableArray &rprg, TSizeT &rc) : CConstantPointerAndCountRefPair<T, TSizeT>(rprg, rc) { }
inline ~CMutablePointerAndCountRefPair() { }
using CConstantPointerAndCountRefPair<T, TSizeT>::Valid;
CMutablePointerAndCountRefPair &operator =(const CMutablePointerAndCountPair &r)
{
m_rprg = r.GetPointer();
m_rc = r.GetCount();
return *this;
}
inline operator CMutablePointerAndCountPair<T, TSizeT>() const { return BCL::CMutablePointerAndCountPair<T, TSizeT>(m_rprg, m_rc); }
inline TMutableArray GetPointer() const { return const_cast<TMutableArray>(m_rprg); }
inline TSizeT GetCount() const { return m_c; }
inline TMutableArray &Pointer() { return const_cast<TMutableArray &>(m_rprg); }
inline TSizeT &Count() { return m_c; }
inline void SetPointer(TMutableArray prg) { m_rprg = prg; }
inline void SetCount(TSizeT c) { m_rc = c; }
inline void SetPointerAndCount(TMutableArray prg, TSizeT c) { m_rprg = prg; m_rc = c; }
}; // BCL::CMutablePointerAndCountRefPair<T, TSizeT>
#pragma intrinsic(memcmp)
#pragma intrinsic(memcpy)
inline
bool
__fastcall
IsMemoryEqual(
const void *pv1,
const void *pv2,
size_t cb
)
{
return (memcmp(pv1, pv2, cb) == 0);
} // BCL::IsMemoryEqual
template <typename T, typename TSizeT>
inline
bool
__fastcall
IsMemoryEqual(
const CConstantPointerAndCountPair<T, TSizeT> &rpair1,
const CConstantPointerAndCountPair<T, TSizeT> &rpair2
)
{
return ((rpair1.GetCount() == rpair2.GetCount()) &&
(BCL::IsMemoryEqual(
rpair1.GetPointer(),
rpair2.GetPointer(),
rpair1.GetCount() * sizeof(T))));
} // BCL::IsMemoryEqual
template <typename TComparisonResult>
inline
TComparisonResult
__fastcall
CompareBytes(
const void *pv1,
const void *pv2,
size_t cb
)
{
int i = memcmp(pv1, pv2, cb);
if (i < 0)
return TComparisonResult::LessThan();
else if (i == 0)
return TComparisonResult::EqualTo();
else
return TComparisonResult::GreaterThan();
} // BCL::CompareBytes
template <typename T, typename TSizeT, typename TComparisonResult>
inline
TComparisonResult
__fastcall
CompareBytes(
const CConstantPointerAndCountPair<T, TSizeT> &rpair1,
const CConstantPointerAndCountPair<T, TSizeT> &rpair2
)
{
TComparisonResult cr = BCL::CompareBytes<TComparisonResult>(
rpair1.GetPointer(),
rpair2.GetPointer(),
((rpair1.GetCount() < rpair2.GetCount()) ? rpair1.GetCount() : rpair2.GetCount()) * sizeof(T));
if (cr.IsEqualTo())
{
if (rpair1.GetCount() < rpair2.GetCount())
cr.SetLessThan();
else if (rpair1.GetCount() > rpair2.GetCount())
cr.SetGreaterThan();
}
return cr;
} // BCL::CompareBytes
inline
void
__fastcall
CopyBytes(
void *pvDestination,
const void *pvSource,
size_t cbToCopy
)
{
memcpy(pvDestination, pvSource, cbToCopy);
} // BCL::CopyBytes
template <typename T, typename TSizeT>
inline
void
__fastcall
CopyBytes(
const CMutablePointerAndCountPair<T, TSizeT> &rpairOut,
const CConstantPointerAndCountPair<T, TSizeT> &rpairIn
)
{
BCL_ASSERT(rpairOut.GetCount() >= rpairIn.GetCount());
// Be defensive...
BCL::CopyBytes(
rpairOut.GetPointer(),
rpairIn.GetPointer(),
(rpairIn.GetCount() > rpairOut.GetCount()) ? rpairOut.GetCount() : rpairIn.GetCount());
} // BCL::CopyBytes
inline
void
__fastcall
MoveBytes(
void *pvDestination,
const void *pvSource,
size_t cbToCopy
)
{
memmove(pvDestination, pvSource, cbToCopy);
} // BCL::MoveBytes
template <typename T, typename TSizeT>
inline
void
__fastcall
MoveBytes(
const CMutablePointerAndCountPair<T, TSizeT> &rpairOut,
const CConstantPointerAndCountPair<T, TSizeT> &rpairIn
)
{
BCL_ASSERT(rpairOut.GetCount() >= rpairIn.GetCount());
// Be defensive...
BCL::MoveBytes(
rpairOut.GetPointer(),
rpairIn.GetPointer(),
(rpairIn.GetCount() > rpairOut.GetCount()) ? rpairOut.GetCount() : rpairIn.GetCount());
} // BCL::MoveBytes
template <typename T, typename TSizeT>
inline
void
__fastcall
CopyBytesAndAdvance(
CMutablePointerAndCountPair<T, TSizeT> &rpairOut,
const CConstantPointerAndCountPair<T, TSizeT> &rpairIn
)
{
const TSizeT cToCopy = (rpairIn.GetCount() > rpairOut.GetCount()) ? rpairOut.GetCount() : rpairIn.GetCount();
BCL_ASSERT(cToCopy == rpairIn.GetCount());
BCL::CopyBytes(
rpairOut.GetPointer(),
rpairIn.GetPointer(),
cToCopy * sizeof(T));
rpairOut.SetPointerAndCount(rpairOut.GetPointer() + cToCopy, rpairOut.GetCount() - cToCopy);
} // BCL::CopyBytesAndAdvance
template <typename T, typename TCallDisposition>
inline TCallDisposition __fastcall AddWithOverflowCheck(T left, T right, T& output)
{
const T Result = left + right;
if ((Result < left) || (Result < right))
return TCallDisposition::ArithmeticOverflow();
output = Result;
return TCallDisposition::Success();
}
template <typename T, typename TCallDisposition>
inline TCallDisposition __fastcall MultiplyWithOverflowCheck(T factor1, T factor2, T &rproduct)
{
//
// Ok, this is somewhat tricky for SIZE_T. Here's what we'll assume:
//
// We'll assume that we can take each factor and split it into two halves
// by using (CHAR_BITS * sizeof(SIZE_T) / 2). (This of course assumes that
// one or the other is even which is a pretty safe bet.)
//
#define HALF_T_BITS(_t) (CHAR_BIT * sizeof(_t) / 2)
#define HALF_T_MASK(_t) ((1 << HALF_T_BITS(_t)) - 1)
const T lowFactor1 = factor1 & HALF_T_MASK(T);
const T highFactor1 = (factor1 >> HALF_T_BITS(T)) & HALF_T_MASK(T);
const T lowFactor2 = factor2 & HALF_T_MASK(T);
const T highFactor2 = (factor2 >> HALF_T_BITS(T)) & HALF_T_MASK(T);
// If both have non-zero high halves, we definitely have an overflow
if ((highFactor1 != 0) && (highFactor2 != 0))
return TCallDisposition::ArithmeticOverflow();
const T crossproduct1 = (lowFactor1 * highFactor2);
const T crossproduct2 = (lowFactor2 * highFactor1);
const T crossproductsum = (crossproduct1 + crossproduct2);
if ((crossproductsum < crossproduct1) || (crossproductsum < crossproduct2))
return TCallDisposition::ArithmeticOverflow();
// We're going to have to shift the cross product sum by HALF_SIZE_T_BITS
// so let's make sure we don't lose anything.
if ((crossproductsum >> HALF_T_BITS(T)) != 0)
return TCallDisposition::ArithmeticOverflow();
// Ok, we should be OK...
rproduct = (crossproductsum << HALF_T_BITS(T)) + (lowFactor1 * lowFactor2);
return TCallDisposition::Success();
}
}; // namespace BCL
#endif // !defined(_WINDOWS_BCL_COMMON_H_INCLUDED_)