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

  1. #if !defined(_WINDOWS_BCL_COMMON_H_INCLUDED_)
  2. #define _WINDOWS_BCL_COMMON_H_INCLUDED_
  3. #pragma once
  4. /*++
  5. Copyright (c) 2000 Microsoft Corporation
  6. Module Name:
  7. bcl_common.h
  8. Abstract:
  9. Definitions common to all of the Base Class Libraries
  10. implementation.
  11. Author:
  12. Michael Grier (MGrier) 2/6/2002
  13. Revision History:
  14. --*/
  15. #include <memory.h> // for memcpy
  16. #include <string.h> // for memmove
  17. #include <limits.h> // for CHAR_BIT
  18. namespace BCL {
  19. //
  20. // Macros for error handling in BCL functions
  21. //
  22. // Rather than try to break down the purpose of each, here's a couple of
  23. // examples:
  24. //
  25. // TCallDisposition Foo(int i) { // TCallDisposition indicates internal linkage
  26. // BCL_MAYFAIL_PROLOG // first line of any function that can fail
  27. // int j;
  28. // BCL_PARAMETER_CHECK((i >= 0) && (i <= 100));
  29. // BCL_IFCALLFAILED_EXIT(Bar(i, &j)); // assumes Bar also has internal linkage
  30. // BCL_ASSERT(j >= 0);
  31. // BCL_INTERNAL_ERROR_CHECK(i != j);
  32. // BCL_MAYFAIL_EPILOG_INTERNAL // last line when internal linkage
  33. // }
  34. //
  35. // BOOL Win32ishFoo(int i) {
  36. // BCL_MAYFAIL_PROLOG
  37. // BCL_IFCALLFAILED_EXIT(Foo(i));
  38. // BCL_MAYFAIL_EPILOG_PUBLIC
  39. // }
  40. //
  41. #define BCL_ORIGINATE_ERROR(_error) do { _bcl_cd = (_error); goto Exit; } while (0)
  42. #define BCL_CALLBACK_FAILED do { goto Exit; } while (0)
  43. #if _X86_
  44. #define BCL_DEBUG_BREAK do { __asm { int 3 } } while (0)
  45. #else
  46. #define BCL_DEBUG_BREAK do { DebugBreak(VOID); } while (0)
  47. #endif
  48. #define BCL_ASSERTION_FAILURE_ACTION(_szExpr) BCL_DEBUG_BREAK
  49. #define BCL_ASSERT(_e) do { if (!(_e)) { BCL_ASSERTION_FAILURE_ACTION(#_e); } } while (0)
  50. #define BCL_COMPILE_TIME_ASSERT(_e) typedef char __c_assert[(_e) ? 1 : -1]
  51. #define BCL_INTERNAL_ERROR_FAILURE_ACTION(_szExpr) do { BCL_DEBUG_BREAK; _bcl_cd = TCallDisposition::InternalError_RuntimeCheck(); goto Exit; } while (0)
  52. #define BCL_INTERNAL_ERROR_CHECK(_e) do { if (!(_e)) { BCL_INTERNAL_ERROR_FAILURE_ACTION(#_e); } } while (0)
  53. #define BCL_MAYFAIL_PROLOG \
  54. TCallDisposition _bcl_cd = TCallDisposition::InternalError_EpilogSkipped();
  55. #define BCL_MAYFAIL_EPILOG_INTERNAL \
  56. _bcl_cd = TCallDisposition::Success(); \
  57. if (false) { goto Exit; } \
  58. Exit: \
  59. return _bcl_cd;
  60. #define BCL_MAYFAIL_EPILOG_PUBLIC \
  61. _bcl_cd = TCallDisposition::Success(); \
  62. if (false) { goto Exit; } \
  63. Exit: \
  64. return _bcl_cd.OnPublicReturn();
  65. #define BCL_NOFAIL_PROLOG /* nothing */
  66. #define BCL_NOFAIL_EPILOG /* nothing */
  67. #define BCL_PARAMETER_CHECK_FAILURE_ACTION(_p) do { _bcl_cd = TCallDisposition::BadParameter(); goto Exit; } while (0)
  68. #define BCL_PARAMETER_CHECK(_p) do { if (!(_p)) { BCL_PARAMETER_CHECK_FAILURE_ACTION(_p); } } while (0)
  69. #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)
  70. #define BCL_NUMBER_OF(_x) (sizeof(_x) / sizeof((_x)[0]))
  71. template <typename T, typename TSizeT> class CConstantPointerAndCountPair;
  72. template <typename T, typename TSizeT> class CMutablePointerAndCountPair;
  73. template <typename T, typename TSizeT> class CConstantPointerAndCountRefPair;
  74. template <typename T, typename TSizeT> class CMutablePointerAndCountRefPair;
  75. template <typename T, typename TSizeT>
  76. class CConstantPointerAndCountPair
  77. {
  78. public:
  79. typedef const T *TConstantArray;
  80. typedef T *TMutableArray;
  81. typedef T TPointee;
  82. typedef TSizeT TCount;
  83. inline CConstantPointerAndCountPair() : m_prg(NULL), m_c(0) { }
  84. inline CConstantPointerAndCountPair(TConstantArray prg, TSizeT c) : m_prg(prg), m_c(c) { }
  85. inline CConstantPointerAndCountPair(const CMutablePointerAndCountPair<T, TSizeT> &r) : m_prg(r.m_prg), m_c(r.m_c) { }
  86. inline CConstantPointerAndCountPair(const CConstantPointerAndCountPair &r) : m_prg(r.m_prg), m_c(r.m_c) { }
  87. inline ~CConstantPointerAndCountPair() { }
  88. CConstantPointerAndCountPair &operator =(const CConstantPointerAndCountPair &r)
  89. {
  90. m_prg = r.m_prg;
  91. m_c = r.m_c;
  92. return *this;
  93. }
  94. CConstantPointerAndCountPair &operator =(const CMutablePointerAndCountPair<T, TSizeT> &r)
  95. {
  96. m_prg = r.m_prg;
  97. m_c = r.m_c;
  98. return *this;
  99. }
  100. inline TConstantArray GetPointer() const { return m_prg; }
  101. inline TSizeT GetCount() const { return m_c; }
  102. inline TConstantArray &Pointer() { return m_prg; }
  103. inline TSizeT &Count() { return m_c; }
  104. inline void SetCount(TSizeT c) { m_c = c; }
  105. inline void SetPointer(TConstantArray prg) { m_prg = prg; }
  106. inline void SetPointerAndCount(TConstantArray prg, TSizeT c) { m_prg = prg; m_c = c; }
  107. inline bool Valid() const { return (m_prg != NULL) || (m_c == 0); }
  108. inline CConstantPointerAndCountPair GetOffsetPair(TSizeT n) { return CConstantPointerAndCountPair(m_prg + n, m_c - n); }
  109. protected:
  110. TConstantArray m_prg;
  111. TSizeT m_c;
  112. }; // BCL::CConstantPointerAndCountPair<T, TSizeT>
  113. template <typename T, typename TSizeT>
  114. class CMutablePointerAndCountPair : public CConstantPointerAndCountPair<T, TSizeT>
  115. {
  116. public:
  117. typedef const T *TConstantArray;
  118. typedef T *TMutableArray;
  119. inline CMutablePointerAndCountPair() { }
  120. inline CMutablePointerAndCountPair(TMutableArray prg, TSizeT c) : CConstantPointerAndCountPair<T, TSizeT>(prg, c) { }
  121. inline ~CMutablePointerAndCountPair() { }
  122. using CConstantPointerAndCountPair<T, TSizeT>::Valid;
  123. CMutablePointerAndCountPair &operator =(const CMutablePointerAndCountPair &r)
  124. {
  125. m_prg = r.m_prg;
  126. m_c = r.m_c;
  127. return *this;
  128. }
  129. inline TMutableArray GetPointer() const { return const_cast<TMutableArray>(m_prg); }
  130. inline TSizeT GetCount() const { return m_c; }
  131. inline TMutableArray &Pointer() { return const_cast<TMutableArray &>(m_prg); }
  132. inline TSizeT &Count() { return m_c; }
  133. inline void SetPointer(TMutableArray prg) { m_prg = prg; }
  134. inline void SetCount(TSizeT c) { m_c = c; }
  135. inline void SetPointerAndCount(TMutableArray prg, TSizeT c) { m_prg = prg; m_c = c; }
  136. }; // BCL::CMutablePointerAndCountPair<T, TSizeT>
  137. template <typename T, typename TSizeT>
  138. class CConstantPointerAndCountRefPair
  139. {
  140. public:
  141. typedef const T *TConstantArray;
  142. typedef T *TMutableArray;
  143. typedef T TPointee;
  144. typedef TSizeT TCount;
  145. inline CConstantPointerAndCountRefPair(TConstantArray &rprg, TSizeT &rc) : m_rprg(rprg), m_rc(rc) { }
  146. inline CConstantPointerAndCountRefPair(const CMutablePointerAndCountRefPair<T, TSizeT> &r) : m_rprg(r.m_rprg), m_rc(r.m_rc) { }
  147. inline CConstantPointerAndCountRefPair(const CConstantPointerAndCountRefPair &r) : m_rprg(r.m_rprg), m_rc(r.m_rc) { }
  148. inline ~CConstantPointerAndCountRefPair() { }
  149. inline CConstantPointerAndCountRefPair &operator =(const CConstantPointerAndCountPair<T, TSizeT> &r)
  150. {
  151. m_rprg = r.GetPointer();
  152. m_rc = r.GetCount();
  153. return *this;
  154. }
  155. inline operator CConstantPointerAndCountPair<T, TSizeT>() const { return BCL::CConstantPointerAndCountPair<T, TSizeT>(m_rprg, m_rc); }
  156. inline TConstantArray GetPointer() const { return m_rprg; }
  157. inline TSizeT GetCount() const { return m_rc; }
  158. inline TConstantArray &Pointer() { return m_rprg; }
  159. inline TSizeT &Count() { return m_rc; }
  160. inline void SetCount(TSizeT c) { m_rc = c; }
  161. inline void SetPointer(TConstantArray prg) { m_rprg = prg; }
  162. inline void SetPointerAndCount(TConstantArray prg, TSizeT c) { m_rprg = prg; m_rc = c; }
  163. inline bool Valid() const { return (m_rprg != NULL) || (m_rc == 0); }
  164. inline CConstantPointerAndCountPair GetOffsetPair(TSizeT n) { return CConstantPointerAndCountPair(m_rprg + n, m_rc - n); }
  165. protected:
  166. TConstantArray &m_rprg;
  167. TSizeT &m_rc;
  168. }; // BCL::CConstantPointerAndCountRefPair<T, TSizeT>
  169. template <typename T, typename TSizeT>
  170. class CMutablePointerAndCountRefPair : public CConstantPointerAndCountRefPair<T, TSizeT>
  171. {
  172. public:
  173. typedef const T *TConstantArray;
  174. typedef T *TMutableArray;
  175. inline CMutablePointerAndCountRefPair(TMutableArray &rprg, TSizeT &rc) : CConstantPointerAndCountRefPair<T, TSizeT>(rprg, rc) { }
  176. inline ~CMutablePointerAndCountRefPair() { }
  177. using CConstantPointerAndCountRefPair<T, TSizeT>::Valid;
  178. CMutablePointerAndCountRefPair &operator =(const CMutablePointerAndCountPair &r)
  179. {
  180. m_rprg = r.GetPointer();
  181. m_rc = r.GetCount();
  182. return *this;
  183. }
  184. inline operator CMutablePointerAndCountPair<T, TSizeT>() const { return BCL::CMutablePointerAndCountPair<T, TSizeT>(m_rprg, m_rc); }
  185. inline TMutableArray GetPointer() const { return const_cast<TMutableArray>(m_rprg); }
  186. inline TSizeT GetCount() const { return m_c; }
  187. inline TMutableArray &Pointer() { return const_cast<TMutableArray &>(m_rprg); }
  188. inline TSizeT &Count() { return m_c; }
  189. inline void SetPointer(TMutableArray prg) { m_rprg = prg; }
  190. inline void SetCount(TSizeT c) { m_rc = c; }
  191. inline void SetPointerAndCount(TMutableArray prg, TSizeT c) { m_rprg = prg; m_rc = c; }
  192. }; // BCL::CMutablePointerAndCountRefPair<T, TSizeT>
  193. #pragma intrinsic(memcmp)
  194. #pragma intrinsic(memcpy)
  195. inline
  196. bool
  197. __fastcall
  198. IsMemoryEqual(
  199. const void *pv1,
  200. const void *pv2,
  201. size_t cb
  202. )
  203. {
  204. return (memcmp(pv1, pv2, cb) == 0);
  205. } // BCL::IsMemoryEqual
  206. template <typename T, typename TSizeT>
  207. inline
  208. bool
  209. __fastcall
  210. IsMemoryEqual(
  211. const CConstantPointerAndCountPair<T, TSizeT> &rpair1,
  212. const CConstantPointerAndCountPair<T, TSizeT> &rpair2
  213. )
  214. {
  215. return ((rpair1.GetCount() == rpair2.GetCount()) &&
  216. (BCL::IsMemoryEqual(
  217. rpair1.GetPointer(),
  218. rpair2.GetPointer(),
  219. rpair1.GetCount() * sizeof(T))));
  220. } // BCL::IsMemoryEqual
  221. template <typename TComparisonResult>
  222. inline
  223. TComparisonResult
  224. __fastcall
  225. CompareBytes(
  226. const void *pv1,
  227. const void *pv2,
  228. size_t cb
  229. )
  230. {
  231. int i = memcmp(pv1, pv2, cb);
  232. if (i < 0)
  233. return TComparisonResult::LessThan();
  234. else if (i == 0)
  235. return TComparisonResult::EqualTo();
  236. else
  237. return TComparisonResult::GreaterThan();
  238. } // BCL::CompareBytes
  239. template <typename T, typename TSizeT, typename TComparisonResult>
  240. inline
  241. TComparisonResult
  242. __fastcall
  243. CompareBytes(
  244. const CConstantPointerAndCountPair<T, TSizeT> &rpair1,
  245. const CConstantPointerAndCountPair<T, TSizeT> &rpair2
  246. )
  247. {
  248. TComparisonResult cr = BCL::CompareBytes<TComparisonResult>(
  249. rpair1.GetPointer(),
  250. rpair2.GetPointer(),
  251. ((rpair1.GetCount() < rpair2.GetCount()) ? rpair1.GetCount() : rpair2.GetCount()) * sizeof(T));
  252. if (cr.IsEqualTo())
  253. {
  254. if (rpair1.GetCount() < rpair2.GetCount())
  255. cr.SetLessThan();
  256. else if (rpair1.GetCount() > rpair2.GetCount())
  257. cr.SetGreaterThan();
  258. }
  259. return cr;
  260. } // BCL::CompareBytes
  261. inline
  262. void
  263. __fastcall
  264. CopyBytes(
  265. void *pvDestination,
  266. const void *pvSource,
  267. size_t cbToCopy
  268. )
  269. {
  270. memcpy(pvDestination, pvSource, cbToCopy);
  271. } // BCL::CopyBytes
  272. template <typename T, typename TSizeT>
  273. inline
  274. void
  275. __fastcall
  276. CopyBytes(
  277. const CMutablePointerAndCountPair<T, TSizeT> &rpairOut,
  278. const CConstantPointerAndCountPair<T, TSizeT> &rpairIn
  279. )
  280. {
  281. BCL_ASSERT(rpairOut.GetCount() >= rpairIn.GetCount());
  282. // Be defensive...
  283. BCL::CopyBytes(
  284. rpairOut.GetPointer(),
  285. rpairIn.GetPointer(),
  286. (rpairIn.GetCount() > rpairOut.GetCount()) ? rpairOut.GetCount() : rpairIn.GetCount());
  287. } // BCL::CopyBytes
  288. inline
  289. void
  290. __fastcall
  291. MoveBytes(
  292. void *pvDestination,
  293. const void *pvSource,
  294. size_t cbToCopy
  295. )
  296. {
  297. memmove(pvDestination, pvSource, cbToCopy);
  298. } // BCL::MoveBytes
  299. template <typename T, typename TSizeT>
  300. inline
  301. void
  302. __fastcall
  303. MoveBytes(
  304. const CMutablePointerAndCountPair<T, TSizeT> &rpairOut,
  305. const CConstantPointerAndCountPair<T, TSizeT> &rpairIn
  306. )
  307. {
  308. BCL_ASSERT(rpairOut.GetCount() >= rpairIn.GetCount());
  309. // Be defensive...
  310. BCL::MoveBytes(
  311. rpairOut.GetPointer(),
  312. rpairIn.GetPointer(),
  313. (rpairIn.GetCount() > rpairOut.GetCount()) ? rpairOut.GetCount() : rpairIn.GetCount());
  314. } // BCL::MoveBytes
  315. template <typename T, typename TSizeT>
  316. inline
  317. void
  318. __fastcall
  319. CopyBytesAndAdvance(
  320. CMutablePointerAndCountPair<T, TSizeT> &rpairOut,
  321. const CConstantPointerAndCountPair<T, TSizeT> &rpairIn
  322. )
  323. {
  324. const TSizeT cToCopy = (rpairIn.GetCount() > rpairOut.GetCount()) ? rpairOut.GetCount() : rpairIn.GetCount();
  325. BCL_ASSERT(cToCopy == rpairIn.GetCount());
  326. BCL::CopyBytes(
  327. rpairOut.GetPointer(),
  328. rpairIn.GetPointer(),
  329. cToCopy * sizeof(T));
  330. rpairOut.SetPointerAndCount(rpairOut.GetPointer() + cToCopy, rpairOut.GetCount() - cToCopy);
  331. } // BCL::CopyBytesAndAdvance
  332. template <typename T, typename TCallDisposition>
  333. inline TCallDisposition __fastcall AddWithOverflowCheck(T left, T right, T& output)
  334. {
  335. const T Result = left + right;
  336. if ((Result < left) || (Result < right))
  337. return TCallDisposition::ArithmeticOverflow();
  338. output = Result;
  339. return TCallDisposition::Success();
  340. }
  341. template <typename T, typename TCallDisposition>
  342. inline TCallDisposition __fastcall MultiplyWithOverflowCheck(T factor1, T factor2, T &rproduct)
  343. {
  344. //
  345. // Ok, this is somewhat tricky for SIZE_T. Here's what we'll assume:
  346. //
  347. // We'll assume that we can take each factor and split it into two halves
  348. // by using (CHAR_BITS * sizeof(SIZE_T) / 2). (This of course assumes that
  349. // one or the other is even which is a pretty safe bet.)
  350. //
  351. #define HALF_T_BITS(_t) (CHAR_BIT * sizeof(_t) / 2)
  352. #define HALF_T_MASK(_t) ((1 << HALF_T_BITS(_t)) - 1)
  353. const T lowFactor1 = factor1 & HALF_T_MASK(T);
  354. const T highFactor1 = (factor1 >> HALF_T_BITS(T)) & HALF_T_MASK(T);
  355. const T lowFactor2 = factor2 & HALF_T_MASK(T);
  356. const T highFactor2 = (factor2 >> HALF_T_BITS(T)) & HALF_T_MASK(T);
  357. // If both have non-zero high halves, we definitely have an overflow
  358. if ((highFactor1 != 0) && (highFactor2 != 0))
  359. return TCallDisposition::ArithmeticOverflow();
  360. const T crossproduct1 = (lowFactor1 * highFactor2);
  361. const T crossproduct2 = (lowFactor2 * highFactor1);
  362. const T crossproductsum = (crossproduct1 + crossproduct2);
  363. if ((crossproductsum < crossproduct1) || (crossproductsum < crossproduct2))
  364. return TCallDisposition::ArithmeticOverflow();
  365. // We're going to have to shift the cross product sum by HALF_SIZE_T_BITS
  366. // so let's make sure we don't lose anything.
  367. if ((crossproductsum >> HALF_T_BITS(T)) != 0)
  368. return TCallDisposition::ArithmeticOverflow();
  369. // Ok, we should be OK...
  370. rproduct = (crossproductsum << HALF_T_BITS(T)) + (lowFactor1 * lowFactor2);
  371. return TCallDisposition::Success();
  372. }
  373. }; // namespace BCL
  374. #endif // !defined(_WINDOWS_BCL_COMMON_H_INCLUDED_)