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.

1188 lines
46 KiB

  1. #if !defined(_FUSION_INC_DEBMACRO_H_INCLUDED_)
  2. #define _FUSION_INC_DEBMACRO_H_INCLUDED_
  3. #pragma once
  4. //
  5. // Copyright (c) 1999-2000 Microsoft Corporation
  6. //
  7. // Fusion Debug Macros
  8. //
  9. //
  10. // Sorry but we're way too in bed with C++ constructs etc. You need to author
  11. // C++ source code to interop with this header.
  12. #if !defined(__cplusplus)
  13. #error "You need to build Fusion sources as C++ files"
  14. #endif // !defined(__cplusplus)
  15. #ifndef SZ_COMPNAME
  16. #define SZ_COMPNAME "FUSION: "
  17. #endif
  18. #ifndef WSZ_COMPNAME
  19. #define WSZ_COMPNAME L"FUSION: "
  20. #endif
  21. #if !defined(NT_INCLUDED)
  22. #include "nt.h"
  23. #include "ntrtl.h"
  24. #include "nturtl.h"
  25. #include "windows.h"
  26. #endif
  27. #include "fusionlastwin32error.h"
  28. #undef ASSERT
  29. //
  30. // These definitions are always valid, regardless of whether this is a free
  31. // or checked build.
  32. //
  33. #if !defined(DPFLTR_ERROR_LEVEL)
  34. #define DPFLTR_ERROR_LEVEL 0
  35. #endif
  36. #if !defined(DPFLTR_WARNING_LEVEL)
  37. #define DPFLTR_WARNING_LEVEL 1
  38. #endif
  39. #if !defined(DPFLTR_TRACE_LEVEL)
  40. #define DPFLTR_TRACE_LEVEL 2
  41. #endif
  42. #if !defined(DPFLTR_INFO_LEVEL)
  43. #define DPFLTR_INFO_LEVEL 3
  44. #endif
  45. #if !defined(DPFLTR_MASK)
  46. #define DPFLTR_MASK 0x80000000
  47. #endif
  48. //
  49. // Guidlines:
  50. //
  51. // Use bits 0-15 for general types of issues, e.g. entry/exit tracing,
  52. // dumping heap usage, etc.
  53. //
  54. // Use bits 16-30 for more fusion-specific kinds of topics like
  55. // binding diagnosis, etc.
  56. //
  57. #define FUSION_DBG_LEVEL_INFO (0x00000002 | DPFLTR_MASK)
  58. #define FUSION_DBG_LEVEL_VERBOSE (0x00000004 | DPFLTR_MASK)
  59. #define FUSION_DBG_LEVEL_ENTEREXIT (0x00000008 | DPFLTR_MASK)
  60. #define FUSION_DBG_LEVEL_ERROREXITPATH (0x00000010 | DPFLTR_MASK)
  61. #define FUSION_DBG_LEVEL_CONSTRUCTORS (0x00000020 | DPFLTR_MASK)
  62. #define FUSION_DBG_LEVEL_DESTRUCTORS (0x00000040 | DPFLTR_MASK)
  63. #define FUSION_DBG_LEVEL_REFCOUNTING (0x00000080 | DPFLTR_MASK)
  64. #define FUSION_DBG_LEVEL_HEAPALLOC (0x00000100 | DPFLTR_MASK)
  65. #define FUSION_DBG_LEVEL_HEAPDEALLOC (0x00000200 | DPFLTR_MASK)
  66. #define FUSION_DBG_LEVEL_HEAPDEBUG (0x00000400 | DPFLTR_MASK)
  67. #define FUSION_DBG_LEVEL_MSI_INSTALL (0x00000800 | DPFLTR_MASK)
  68. #define FUSION_DBG_LEVEL_POLICY (0x00010000 | DPFLTR_MASK)
  69. #define FUSION_DBG_LEVEL_HASHTABLE (0x00020000 | DPFLTR_MASK)
  70. #define FUSION_DBG_LEVEL_WFP (0x00040000 | DPFLTR_MASK)
  71. #define FUSION_DBG_LEVEL_ACTCTX (0x00080000 | DPFLTR_MASK)
  72. #define FUSION_DBG_LEVEL_XMLNAMESPACES (0x00100000 | DPFLTR_MASK)
  73. #define FUSION_DBG_LEVEL_XMLTREE (0x00200000 | DPFLTR_MASK)
  74. #define FUSION_DBG_LEVEL_INSTALLATION (0x00400000 | DPFLTR_MASK)
  75. #define FUSION_DBG_LEVEL_PROBING (0x00800000 | DPFLTR_MASK)
  76. #define FUSION_DBG_LEVEL_XMLSTREAM (0x01000000 | DPFLTR_MASK)
  77. #define FUSION_DBG_LEVEL_SETUPLOG (0x02000000 | DPFLTR_MASK)
  78. #define FUSION_DBG_LEVEL_NODEFACTORY (0x04000000 | DPFLTR_MASK)
  79. #define FUSION_DBG_LEVEL_FULLACTCTX (0x08000000 | DPFLTR_MASK)
  80. #define FUSION_DBG_LEVEL_FILECHANGENOT (0x10000000 | DPFLTR_MASK)
  81. #define FUSION_DBG_LEVEL_LOG_ACTCTX (0x20000000 | DPFLTR_MASK)
  82. #define FUSION_DBG_LEVEL_FREEBUILDERROR (0x40000000 | DPFLTR_MASK)
  83. #if DBG
  84. //
  85. // In DBG builds, all error level events are always shown.
  86. //
  87. #define FUSION_DBG_LEVEL_ERROR DPFLTR_ERROR_LEVEL
  88. #else // DBG
  89. //
  90. // In FRE builds, use an explicit mask.
  91. //
  92. #define FUSION_DBG_LEVEL_ERROR FUSION_DBG_LEVEL_FREEBUILDERROR
  93. #endif // DBG
  94. // updated when the user-mode copy of the kernel debugging flags are updated
  95. extern "C" bool g_FusionEnterExitTracingEnabled;
  96. bool
  97. FusionpDbgWouldPrintAtFilterLevel(
  98. ULONG FilterLevel
  99. );
  100. DWORD
  101. FusionpHRESULTToWin32(
  102. HRESULT hr
  103. );
  104. typedef struct _FRAME_INFO
  105. {
  106. PCSTR pszFile;
  107. PCSTR pszFunction;
  108. INT nLine;
  109. } FRAME_INFO, *PFRAME_INFO;
  110. typedef const struct _FRAME_INFO *PCFRAME_INFO;
  111. typedef struct _CALL_SITE_INFO CALL_SITE_INFO, *PCALL_SITE_INFO;
  112. typedef const struct _CALL_SITE_INFO *PCCALL_SITE_INFO;
  113. void __fastcall FusionpTraceWin32LastErrorFailureExV(const CALL_SITE_INFO &rCallSiteInfo, PCSTR Format, va_list Args);
  114. void __fastcall FusionpTraceWin32LastErrorFailureOriginationExV(const CALL_SITE_INFO &rCallSiteInfo, PCSTR Format, va_list Args);
  115. typedef struct _CALL_SITE_INFO
  116. {
  117. PCSTR pszFile;
  118. PCSTR pszFunction;
  119. PCSTR pszApiName;
  120. INT nLine;
  121. void __cdecl TraceWin32LastErrorFailureEx(PCSTR Format, ...) const
  122. { va_list Args; va_start(Args, Format); FusionpTraceWin32LastErrorFailureExV(*this, Format, Args); va_end(Args); }
  123. void __cdecl TraceWin32LastErrorFailureOriginationEx(PCSTR Format, ...) const
  124. { va_list Args; va_start(Args, Format); FusionpTraceWin32LastErrorFailureOriginationExV(*this, Format, Args); va_end(Args); }
  125. } CALL_SITE_INFO, *PCALL_SITE_INFO;
  126. bool
  127. FusionpPopulateFrameInfo(
  128. FRAME_INFO &rFrameInfo,
  129. PCSTR pszFile,
  130. PCSTR pszFunction,
  131. INT nLine
  132. );
  133. bool
  134. __fastcall
  135. FusionpPopulateFrameInfo(
  136. FRAME_INFO &rFrameInfo,
  137. PCTEB_ACTIVE_FRAME ptaf
  138. );
  139. bool
  140. __fastcall
  141. FusionpGetActiveFrameInfo(
  142. FRAME_INFO &rFrameInfo
  143. );
  144. #if _X86_
  145. #define FUSION_DEBUG_BREAK_IN_FREE_BUILD() __asm { int 3 }
  146. #else // _X86_
  147. #define FUSION_DEBUG_BREAK_IN_FREE_BUILD() DebugBreak()
  148. #endif // _X86_
  149. //
  150. // Like FusionpAssertionFailed(), FusionpReportConditionAndBreak() will try to break in; if it's
  151. //
  152. bool FusionpReportConditionAndBreak(PCSTR pszMessage, ...);
  153. #if DBG
  154. // Normal macro for breaking in checked builds; make people use the nasty name
  155. // if they're going to do the nasty thing.
  156. #define FUSION_DEBUG_BREAK() FUSION_DEBUG_BREAK_IN_FREE_BUILD()
  157. //
  158. // Assertion failure reporting internal APIs.
  159. //
  160. // They return true if they were not able to issue the breakpoint; false if they were.
  161. //
  162. bool FusionpAssertionFailed(PCSTR pszExpression, PCSTR pszMessage = NULL, ...);
  163. bool FusionpAssertionFailed(const FRAME_INFO &rFrameInfo, PCSTR pszExpression, PCSTR pszMessage = NULL);
  164. bool FusionpAssertionFailed(PCSTR pszFile, PCSTR pszFunction, INT nLine, PCSTR pszExpression, PCSTR pszMessage = NULL);
  165. //
  166. // Soft assertion failures are really just debug messages, but they should result in
  167. // bugs being filed.
  168. //
  169. VOID FusionpSoftAssertFailed(PCSTR pszExpression, PCSTR pszMessage = NULL);
  170. VOID FusionpSoftAssertFailed(const FRAME_INFO &rFrameInfo, PCSTR pszExpression, PCSTR pszMessage = NULL);
  171. VOID FusionpSoftAssertFailed(PCSTR pszFile, PCSTR pszFunction, INT nLine, PCSTR pszExpression, PCSTR pszMessage = NULL);
  172. #define HARD_ASSERT2_ACTION(_e, _m) \
  173. do \
  174. { \
  175. if (::FusionpAssertionFailed(__FILE__, __FUNCTION__, __LINE__, #_e, (_m))) \
  176. { \
  177. FUSION_DEBUG_BREAK();\
  178. } \
  179. } while (0)
  180. #define HARD_ASSERT2(_e, _m) \
  181. do \
  182. { \
  183. __t.SetLine(__LINE__); \
  184. if (!(_e)) \
  185. HARD_ASSERT2_ACTION(_e, (_m)); \
  186. } while (0)
  187. /*
  188. if (__exists(__t)) \
  189. { \
  190. CNoTraceContextUsedInFrameWithTraceObject x; \
  191. }
  192. */
  193. #define HARD_ASSERT2_NTC(_e, _m) \
  194. do \
  195. { \
  196. if (!(_e)) \
  197. HARD_ASSERT2_ACTION(_e, (_m)); \
  198. } while (0)
  199. // Pick up the locally-scoped trace context by default
  200. #define HARD_ASSERT(_e) HARD_ASSERT2(_e, NULL)
  201. #define HARD_ASSERT_NTC(_e) HARD_ASSERT2_NTC(_e, NULL)
  202. /*-----------------------------------------------------------------------------
  203. VERIFY is like ASSERT, but it evaluates it expression in retail/free builds
  204. too, so you can say VERIFY(CloseHandle(h)) whereas ASSERT(CloseHandle(h))
  205. would fail to close the handle in free builds
  206. VERIFY2 adds a message as well, like VSASSERT or ASSERTMSG, in its second parameter
  207. -----------------------------------------------------------------------------*/
  208. #define HARD_VERIFY(_e) HARD_ASSERT(_e)
  209. #define HARD_VERIFY_NTC(_e) HARD_ASSERT_NTC(_e)
  210. #define HARD_VERIFY2(_e, _m) HARD_ASSERT2(_e, _m)
  211. #define HARD_VERIFY2_NTC(_e, _m) HARD_ASSERT2_NTC(_e, _m)
  212. #define SOFT_ASSERT2(_e, _m) \
  213. do \
  214. { \
  215. __t.SetLine(__LINE__); \
  216. if (!(_e)) \
  217. ::FusionpSoftAssertFailed(__FILE__, __FUNCTION__, __LINE__, #_e, (_m)); \
  218. } while (0)
  219. #define SOFT_ASSERT(_e) SOFT_ASSERT2(_e, NULL)
  220. #define SOFT_ASSERT2_NTC(_e, _m) \
  221. do \
  222. { \
  223. if (!(_e)) \
  224. ::FusionpSoftAssertFailed(__FILE__, __FUNCTION__, __LINE__, #_e, (_m)); \
  225. } while (0)
  226. #define SOFT_ASSERT_NTC(_e) SOFT_ASSERT2_NTC(_e, NULL)
  227. #define SOFT_VERIFY(_e) SOFT_ASSERT(_e)
  228. #define SOFT_VERIFY_NTC(_e) SOFT_ASSERT_NTC(_e)
  229. #define SOFT_VERIFY2(_e, _m) SOFT_ASSERT2(_e, _m)
  230. #define SOFT_VERIFY2_NTC(_e, _m) SOFT_ASSERT2_NTC(_e, _m)
  231. #else // DBG
  232. #define FUSION_DEBUG_BREAK() do { } while (0)
  233. #define HARD_ASSERT(_e) /* nothing */
  234. #define HARD_ASSERT_NTC(_e) /* nothing */
  235. #define HARD_ASSERT2_ACTION(_e, _m) /* nothing */
  236. #define HARD_ASSERT2(_e, _m) /* nothing */
  237. #define HARD_ASSERT2_NTC(_e, _m) /* nothing */
  238. #define HARD_VERIFY(_e) (_e)
  239. #define HARD_VERIFY_NTC(_e) (_e)
  240. #define HARD_VERIFY2(_e, _m) (_e)
  241. #define HARD_VERIFY2_NTC(_e, _m) (_e)
  242. #define SOFT_ASSERT(_expr)
  243. #define SOFT_ASSERT_NTC(_e)
  244. #define SOFT_ASSERT2(_e, _m)
  245. #define SOFT_ASSERT2_NTC(_e, _m)
  246. #define SOFT_VERIFY(_e) (_e)
  247. #define SOFT_VERIFY_NTC(_e) (_e)
  248. #define SOFT_VERIFY2(_e, _m) (_e)
  249. #define SOFT_VERIFY2_NTC(_e, _m) (_e)
  250. #endif // DBG
  251. #define VERIFY(_e) HARD_VERIFY(_e)
  252. #define VERIFY_NTC(_e) HARD_VERIFY_NTC(_e)
  253. #define VERIFY2(_e, _m) HARD_VERIFY2(_e, _m)
  254. #define VERIFY2_NTC(_e, _m) HARD_VERIFY2_NTC(_e, _m)
  255. #define ASSERT(_e) HARD_ASSERT(_e)
  256. #define ASSERT2(_e, _m) HARD_ASSERT2(_e, _m)
  257. #define ASSERT_NTC(_e) HARD_ASSERT_NTC(_e)
  258. #define ASSERT2_NTC(_e, _m) HARD_ASSERT2_NTC(_e, _m)
  259. #define INTERNAL_ERROR2_ACTION(_e, _m) do { HARD_ASSERT2_ACTION(_e, _m); __t.MarkInternalError(); goto Exit; } while (0)
  260. #define INTERNAL_ERROR_CHECK(_e) do { if (!(_e)) { INTERNAL_ERROR2_ACTION(_e, NULL); } } while (0)
  261. #define INTERNAL_ERROR_CHECK2(_e, _m) do { if (!(_e)) { INTERNAL_ERROR2_ACTION(_e, _m); } } while (0)
  262. // There are several win32 errors for out of memory.
  263. // We'll always use FUSION_WIN32_ALLOCFAILED_ERROR so that if we change
  264. // out minds about which one is right we can do it in one place.
  265. #define FUSION_WIN32_ALLOCFAILED_ERROR ERROR_OUTOFMEMORY
  266. /*
  267. This is appropriate in the rare cases when you have __try/__except, which preclude
  268. you from declaring the local FN_TRACE_WIN32 if you are compiling -GX or -EH.
  269. */
  270. #define IFW32FALSE_EXIT_LIGHT(x) do { if (!(x)) { KdPrint(("SXS:"__FUNCTION__" %s failed; GetLastError() = %lu\n", #x, ::GetLastError())); goto Exit; } } while (0)
  271. #if !defined(FUSION_CAPTURE_STACKS)
  272. #if DBG
  273. #define FUSION_CAPTURE_STACKS (1)
  274. #endif // DBG
  275. #endif // !defined(FUSION_CAPTURE_STACKS)
  276. class CNoTraceContextUsedInFrameWithTraceObject
  277. {
  278. private:
  279. CNoTraceContextUsedInFrameWithTraceObject(); // intentionally not implemented
  280. ~CNoTraceContextUsedInFrameWithTraceObject(); // intentionally not implemented
  281. };
  282. typedef struct _SXS_STATIC_TRACE_CONTEXT
  283. {
  284. TEB_ACTIVE_FRAME_CONTEXT_EX m_FrameContext;
  285. INT m_StartLine;
  286. } SXS_STATIC_TRACE_CONTEXT;
  287. typedef struct _SXS_STATIC_RELEASE_TRACE_CONTEXT
  288. {
  289. SXS_STATIC_TRACE_CONTEXT m_TraceContext;
  290. PCSTR m_TypeName;
  291. } SXS_STATIC_RELEASE_TRACE_CONTEXT;
  292. class CFrame;
  293. typedef struct _FROZEN_STACK
  294. {
  295. ULONG ulDepth;
  296. ULONG ulMaxDepth;
  297. CFrame *pContents;
  298. } FROZEN_STACK, *PFROZEN_STACK;
  299. typedef enum _TRACETYPE
  300. {
  301. TRACETYPE_INFO,
  302. TRACETYPE_CALL_START,
  303. TRACETYPE_CALL_EXIT_NOHRESULT,
  304. TRACETYPE_CALL_EXIT_HRESULT,
  305. } TRACETYPE;
  306. extern bool g_FusionBreakOnBadParameters;
  307. /*
  308. MEMORY_BASIC_INFORMATION g_SxsDllMemoryBasicInformation;
  309. */
  310. VOID FusionpConvertCOMFailure(HRESULT & __hr);
  311. int STDAPIVCALLTYPE _DebugTraceA(PCSTR pszMsg, ...);
  312. int STDAPICALLTYPE _DebugTraceVaA(PCSTR pszMsg, va_list ap);
  313. int STDAPIVCALLTYPE _DebugTraceW(PCWSTR pszMsg, ...);
  314. int STDAPICALLTYPE _DebugTraceVaW(PCWSTR pszMsg, va_list ap);
  315. int STDAPIVCALLTYPE _DebugTraceExA(DWORD dwFlags, TRACETYPE tt, HRESULT hr, PCSTR pszMsg, ...);
  316. int STDAPICALLTYPE _DebugTraceExVaA(DWORD dwFlags, TRACETYPE tt, HRESULT hr, PCSTR pszMsg, va_list ap);
  317. int STDAPIVCALLTYPE _DebugTraceExW(DWORD dwFlags, TRACETYPE tt, HRESULT hr, PCWSTR pszMsg, ...);
  318. int STDAPICALLTYPE _DebugTraceExVaW(DWORD dwFlags, TRACETYPE tt, HRESULT hr, PCWSTR pszMsg, va_list ap);
  319. void __fastcall FusionpTraceWin32LastErrorFailure(const CALL_SITE_INFO &rCallSiteInfo);
  320. void __fastcall FusionpTraceWin32LastErrorFailureOrigination(const CALL_SITE_INFO &rCallSiteInfo);
  321. /*
  322. These are never used outside trace.cpp.
  323. void FusionpTraceWin32FailureNoFormatting(const FRAME_INFO &rFrameInfo, DWORD dwWin32Status, PCSTR pszMessage);
  324. void FusionpTraceWin32FailureNoFormatting(DWORD dwWin32Status, PCSTR pszMessage);
  325. void FusionpTraceWin32FailureNoFormatting(PCSTR pszFile, PCSTR pszFunction, INT nLine, DWORD dwWin32Status, PCSTR pszMessage);
  326. void FusionpTraceWin32FailureOriginationNoFormatting(const FRAME_INFO &rFrameInfo, DWORD dwWin32Status, PCSTR pszMessage);
  327. void FusionpTraceWin32FailureOriginationNoFormatting(DWORD dwWin32Status, PCSTR pszMessage);
  328. void FusionpTraceWin32FailureOriginationNoFormatting(PCSTR pszFile, PCSTR pszFunction, INT nLine, DWORD dwWin32Status, PCSTR pszMessage);
  329. void FusionpTraceWin32Failure(const FRAME_INFO &rFrameInfo, DWORD dwWin32Status, PCSTR pszMessage, ...);
  330. void FusionpTraceWin32Failure(DWORD dwWin32Status, PCSTR pszMessage, ...);
  331. void FusionpTraceWin32Failure(PCSTR pszFile, PCSTR pszFunction, INT nLine, DWORD dwWin32Status, PCSTR pszMessage, ...);
  332. */
  333. void FusionpTraceWin32FailureVa(const FRAME_INFO &rFrameInfo, DWORD dwWin32Status, PCSTR pszMsg, va_list ap);
  334. void FusionpTraceWin32FailureVa(DWORD dwWin32Status, PCSTR pszMsg, va_list ap);
  335. void FusionpTraceWin32FailureVa(PCSTR pszFile, PCSTR pszFunction, INT nLine, DWORD dwWin32Status, PCSTR pszMsg, va_list ap);
  336. void FusionpTraceCOMFailure(HRESULT hrIn, PCSTR pszMsg, ...);
  337. void FusionpTraceCOMFailureVa(HRESULT hrIn, PCSTR pszMsg, va_list ap);
  338. void FusionpTraceCOMFailureOrigination(HRESULT hrIn, PCSTR pszMsg, ...);
  339. void FusionpTraceCOMFailureOriginationVa(HRESULT hrIn, PCSTR pszMsg, va_list ap);
  340. void FusionpTraceCallEntry();
  341. void FusionpTraceCallExit();
  342. void FusionpTraceCallCOMSuccessfulExit(HRESULT hrIn, PCSTR szFormat, ...);
  343. void FusionpTraceCallCOMSuccessfulExitVa(HRESULT hrIn, PCSTR szFormat, va_list ap);
  344. void FusionpTraceCallSuccessfulExit(PCSTR szFormat, ...);
  345. void FusionpTraceCallSuccessfulExitVa(PCSTR szFormat, va_list ap);
  346. void FusionpTraceCallWin32UnsuccessfulExit(DWORD dwLastError, PCSTR szFormat, ...);
  347. void FusionpTraceCallWin32UnsuccessfulExitVa(DWORD dwLastError, PCSTR szFormat, va_list ap);
  348. void FusionpTraceCallCOMUnsuccessfulExit(HRESULT hrError, PCSTR szFormat, ...);
  349. void FusionpTraceCallCOMUnsuccessfulExitVa(HRESULT hrError, PCSTR szFormat, va_list ap);
  350. void FusionpTraceAllocFailure(PCSTR pszExpression);
  351. void FusionpTraceInvalidFlags(const FRAME_INFO &rFrameInfo, DWORD dwFlagsPassed, DWORD dwValidFlags);
  352. void FusionpTraceInvalidFlags(PCSTR pszFile, PCSTR pszFunction, INT nLine, DWORD dwFlagsPassed, DWORD dwValidFlags);
  353. void FusionpTraceInvalidFlags(DWORD dwFlagsPassed, DWORD dwValidFlags);
  354. void FusionpTraceNull(PCSTR pszExpression);
  355. void FusionpTraceZero(PCSTR pszExpression);
  356. void FusionpTraceParameterMustNotBeNull(PCSTR pszExpression);
  357. void FusionpTraceParameterCheck(PCSTR pszExpression);
  358. void FusionpTraceParameterCheck(PCSTR pszFile, PCSTR pszFunction, INT nLine, PCSTR pszExpression);
  359. void FusionpTraceParameterCheck(const FRAME_INFO &rFrame, PCSTR pszExpression);
  360. #define FUSIONP_DUMP_STACK_FORMAT_SHORT ( 0x00000001 )
  361. #define FUSIONP_DUMP_STACK_FORMAT_MEDIUM ( 0x00000002 )
  362. #define FUSIONP_DUMP_STACK_FORMAT_LONG ( 0x00000003 )
  363. #define FUSIONP_DUMP_STACK_FORMAT_MASK ( 0x00000003 )
  364. VOID FusionpDumpStack(DWORD dwFlags, ULONG ulLevel, PCWSTR pcwszLinePrefix, ULONG ulDepth);
  365. #if FUSION_ENABLE_FROZEN_STACK
  366. BOOL FusionpFreezeStack(DWORD dwFlags, PFROZEN_STACK pFrozenStack);
  367. BOOL FusionpOutputFrozenStack(DWORD dwFlags, PCSTR Prefix, PFROZEN_STACK pFrozenStack);
  368. #endif
  369. #define TRACEMSG(_paramlist) _DebugTraceA _paramlist
  370. #if DBG
  371. #define DEFINE_CURRENT_FRAME_INFO(_frame) static const FRAME_INFO _frame = { __FILE__, __FUNCTION__, __LINE__ }
  372. #define DBG_TEXT(_x) #_x
  373. #else
  374. #define DEFINE_CURRENT_FRAME_INFO(_frame) static const FRAME_INFO _frame = { __FILE__, "", __LINE__ }
  375. #define DBG_TEXT(_x) ""
  376. #endif
  377. #define DEFINE_CALL_SITE_INFO(_callsite, _apiname) static const CALL_SITE_INFO _callsite = { __FILE__, __FUNCTION__, DBG_TEXT(_apiname), __LINE__ }
  378. #define DEFINE_CALL_SITE_INFO_EX(_callsite) static const CALL_SITE_INFO _callsite = { __FILE__, __FUNCTION__, "", __LINE__ }
  379. #define TRACE_WIN32_FAILURE(_apiname) \
  380. do \
  381. { \
  382. DEFINE_CALL_SITE_INFO(__callsite, _apiname); \
  383. ::FusionpTraceWin32LastErrorFailure(__callsite); \
  384. } while (0)
  385. #define TRACE_WIN32_FAILURE_ORIGINATION(_apiname) \
  386. do \
  387. { \
  388. DEFINE_CALL_SITE_INFO(__callsite, _apiname); \
  389. ::FusionpTraceWin32LastErrorFailureOrigination(__callsite); \
  390. } while (0)
  391. // FusionpTraceWin32Failure(FUSION_DBG_LEVEL_ERROR, __FILE__, __LINE__, __FUNCTION__, ::FusionpGetLastWin32Error(), #_apiname)
  392. #define TRACE_COM_FAILURE(_hresult, _apiname) ::FusionpTraceCOMFailure((_hresult), DBG_TEXT(_apiname))
  393. #define TRACE_COM_FAILURE_ORIGINATION(_hresult, _apiname) ::FusionpTraceCOMFailureOrigination((_hresult), DBG_TEXT(_apiname))
  394. #define TRACE_DUMP_STACK(_includetop) _DebugTraceDumpStack((_includetop))
  395. #define TRACE_ALLOCFAILED(_e) ::FusionpTraceAllocFailure(DBG_TEXT(_e))
  396. #define TRACE_INVALID_FLAGS(_fPassed, _fExpected) ::FusionpTraceInvalidFlags((_fPassed), (_fExpected))
  397. #define TRACE_NULL(_e) ::FusionpTraceNull(DBG_TEXT(_e))
  398. #define TRACE_ZERO(_e) ::FusionpTraceZero(DBG_TEXT(_e))
  399. #define TRACE_PARAMETER_MUST_NOT_BE_NULL(_p) do { ::FusionpTraceParameterMustNotBeNull(DBG_TEXT(_p)); } while (0)
  400. #define TRACE_PARAMETER_CHECK(_e) do { ::FusionpTraceParameterCheck(DBG_TEXT(_e)); } while (0)
  401. //
  402. // on DBG avoid both the code breakpoint on ::FusionpSetLastWin32Error
  403. // and the data write breakpoint on NtCurrentTeb()->LastErrorValue
  404. //
  405. // on !DBG, only avoid the first (perf)
  406. //
  407. #if DBG
  408. // aka Sxsp::FusionpSetLastWin32ErrorAvoidingGratuitousBreakpoints
  409. #define SxspRestoreLastError(x) \
  410. ((void) \
  411. ( \
  412. (NtCurrentTeb()->LastErrorValue != (x)) \
  413. ? (NtCurrentTeb()->LastErrorValue = (x)) \
  414. : 0 \
  415. ))
  416. #else
  417. #define SxspRestoreLastError(x) ((void)((NtCurrentTeb()->LastErrorValue = (x))))
  418. #endif // DBG
  419. class CGlobalFakeTraceContext
  420. {
  421. public:
  422. static inline void SetLastError(DWORD dwLastError) { ::FusionpSetLastWin32Error(dwLastError); }
  423. static inline void ClearLastError() { ::FusionpClearLastWin32Error(); }
  424. };
  425. __declspec(selectany) CGlobalFakeTraceContext g_GlobalFakeTraceContext;
  426. class CFrame : public _TEB_ACTIVE_FRAME_EX
  427. {
  428. friend bool
  429. __fastcall
  430. FusionpGetActiveFrameInfo(
  431. FRAME_INFO &rFrameInfo
  432. );
  433. friend bool
  434. __fastcall
  435. FusionpPopulateFrameInfo(
  436. FRAME_INFO &rFrameInfo,
  437. PCTEB_ACTIVE_FRAME ptaf
  438. );
  439. public:
  440. inline CFrame(const SXS_STATIC_TRACE_CONTEXT &rc)
  441. {
  442. this->BasicFrame.Flags = TEB_ACTIVE_FRAME_FLAG_EXTENDED;
  443. this->BasicFrame.Previous = NULL;
  444. this->BasicFrame.Context = &rc.m_FrameContext.BasicContext;
  445. this->ExtensionIdentifier = (PVOID) (' sxS');
  446. m_nLine = rc.m_StartLine;
  447. }
  448. inline void BaseEnter()
  449. {
  450. #if FUSION_WIN
  451. ::RtlPushFrame(&this->BasicFrame);
  452. #endif // FUSION_WIN
  453. };
  454. inline void SetLine(int nLine) { m_nLine = nLine; }
  455. inline static void SetLastError(PTEB Teb, DWORD dwLastError) { Teb->LastErrorValue = dwLastError; }
  456. inline static void SetLastError(DWORD dwLastError) { ::FusionpSetLastWin32Error(dwLastError); }
  457. inline static DWORD GetLastError() { return ::FusionpGetLastWin32Error(); }
  458. inline static void ClearLastError() { ::FusionpClearLastWin32Error(); }
  459. inline void TraceNull(PCSTR pszExpression) const { ::FusionpTraceNull(pszExpression); }
  460. inline void TraceCOMFailure(HRESULT hrIn, PCSTR pszExpression) const { ::FusionpTraceCOMFailure(hrIn, pszExpression); }
  461. inline HRESULT ConvertCOMFailure(HRESULT hrIn) { ASSERT_NTC(FAILED(hrIn)); ::FusionpConvertCOMFailure(hrIn); ASSERT_NTC(FAILED(hrIn)); return hrIn; }
  462. inline ~CFrame()
  463. {
  464. #if FUSION_WIN
  465. ::RtlPopFrame(&this->BasicFrame);
  466. #endif
  467. }
  468. protected:
  469. int m_nLine;
  470. const SXS_STATIC_TRACE_CONTEXT *GetTraceContext() const { return reinterpret_cast<const SXS_STATIC_TRACE_CONTEXT *>(BasicFrame.Context); }
  471. template <typename T> const T *GetTypedTraceContext() const { return static_cast<const T *>(this->GetTraceContext()); }
  472. private:
  473. CFrame(const CFrame &r); // unimplemented copy constructor
  474. CFrame &operator =(const CFrame &r); // unimplemented assignment operator
  475. };
  476. class CFnTracer : public CFrame
  477. {
  478. public:
  479. inline CFnTracer(
  480. const SXS_STATIC_TRACE_CONTEXT &rsftc,
  481. BOOL fSmartPerThreadData
  482. ) : CFrame(rsftc)
  483. {
  484. }
  485. inline void Enter()
  486. {
  487. CFrame::BaseEnter();
  488. if (g_FusionEnterExitTracingEnabled)
  489. ::FusionpTraceCallEntry();
  490. }
  491. ~CFnTracer()
  492. {
  493. if (g_FusionEnterExitTracingEnabled)
  494. ::FusionpTraceCallExit();
  495. }
  496. void MarkInternalError() { this->SetLastError(ERROR_INTERNAL_ERROR); }
  497. void MarkAllocationFailed() { this->SetLastError(FUSION_WIN32_ALLOCFAILED_ERROR); }
  498. void MarkWin32LastErrorFailure() { ASSERT_NTC(this->GetLastError() != ERROR_SUCCESS); }
  499. void MarkSuccess() { }
  500. void ReturnValue() const { }
  501. protected:
  502. private:
  503. CFnTracer(const CFnTracer &r); // intentionally not implemented
  504. CFnTracer &operator =(const CFnTracer &r); // intentionally not implemented
  505. };
  506. template <typename T> class CFnTracerConstructor : public CFrame
  507. {
  508. public:
  509. CFnTracerConstructor(
  510. const SXS_STATIC_TRACE_CONTEXT &rsftc,
  511. PCSTR szTypeName,
  512. T *pThis
  513. ) : CFrame(rsftc),
  514. m_pThis(pThis),
  515. m_szTypeName(szTypeName)
  516. {
  517. }
  518. inline void Enter()
  519. {
  520. CFrame::BaseEnter();
  521. if (g_FusionEnterExitTracingEnabled)
  522. ::FusionpTraceCallEntry();
  523. }
  524. ~CFnTracerConstructor()
  525. {
  526. if (g_FusionEnterExitTracingEnabled)
  527. ::FusionpTraceCallExit();
  528. }
  529. protected:
  530. const PCSTR m_szTypeName;
  531. T const *m_pThis;
  532. private:
  533. CFnTracerConstructor &operator=(const CFnTracerConstructor &r); // intentionally not implemented
  534. CFnTracerConstructor(const CFnTracerConstructor &r); // intentionally not implemented
  535. };
  536. template <typename T> class CFnTracerDestructor : public CFrame
  537. {
  538. public:
  539. CFnTracerDestructor(
  540. const SXS_STATIC_TRACE_CONTEXT &rsftc,
  541. PCSTR szTypeName,
  542. T *pThis
  543. ) : CFrame(rsftc),
  544. m_pThis(pThis),
  545. m_szTypeName(szTypeName)
  546. {
  547. }
  548. inline void Enter()
  549. {
  550. CFrame::BaseEnter();
  551. if (g_FusionEnterExitTracingEnabled)
  552. ::FusionpTraceCallEntry();
  553. }
  554. ~CFnTracerDestructor()
  555. {
  556. ::FusionpTraceCallExit();
  557. }
  558. protected:
  559. const PCSTR m_szTypeName;
  560. T const *m_pThis;
  561. private:
  562. CFnTracerDestructor &operator=(const CFnTracerDestructor &r); // intentionally not implemented
  563. CFnTracerDestructor(const CFnTracerDestructor &r); // intentionally not implemented
  564. };
  565. template <typename T> class CFnTracerAddRef : public CFrame
  566. {
  567. public:
  568. CFnTracerAddRef(
  569. const SXS_STATIC_TRACE_CONTEXT &rsftc,
  570. PCSTR szTypeName,
  571. T *pThis,
  572. LONG &rlRefCount
  573. ) : CFrame(rsftc),
  574. m_pThis(pThis),
  575. m_rlRefCount(rlRefCount),
  576. m_szTypeName(szTypeName)
  577. {
  578. }
  579. CFnTracerAddRef(
  580. const SXS_STATIC_TRACE_CONTEXT &rsftc,
  581. PCSTR szTypeName,
  582. T *pThis,
  583. ULONG &rlRefCount
  584. ) : CFrame(rsftc),
  585. m_pThis(pThis),
  586. m_rlRefCount(*((LONG *) &rlRefCount)),
  587. m_szTypeName(szTypeName)
  588. {
  589. }
  590. inline void Enter()
  591. {
  592. CFrame::BaseEnter();
  593. if (g_FusionEnterExitTracingEnabled)
  594. ::FusionpTraceCallEntry();
  595. }
  596. ~CFnTracerAddRef()
  597. {
  598. ::FusionpTraceCallExit();
  599. }
  600. protected:
  601. const PCSTR m_szTypeName;
  602. T const *m_pThis;
  603. LONG &m_rlRefCount;
  604. private:
  605. CFnTracerAddRef &operator=(const CFnTracerAddRef &r); // intentionally not implemented
  606. CFnTracerAddRef(const CFnTracerAddRef &r); // intentionally not implemented
  607. };
  608. template <typename T> class CFnTracerRelease : public CFrame
  609. {
  610. public:
  611. CFnTracerRelease(
  612. const SXS_STATIC_RELEASE_TRACE_CONTEXT &rsrtc,
  613. T *pThis,
  614. LONG &rlRefCount
  615. ) : CFrame(rsrtc.m_TraceContext),
  616. m_pThis(pThis),
  617. m_rlRefCount(rlRefCount)
  618. {
  619. }
  620. CFnTracerRelease(
  621. const SXS_STATIC_RELEASE_TRACE_CONTEXT &rsrtc,
  622. T *pThis,
  623. ULONG &rlRefCount
  624. ) : CFrame(rsrtc.m_TraceContext),
  625. m_pThis(pThis),
  626. m_rlRefCount(*((LONG *) &rlRefCount))
  627. {
  628. }
  629. inline void Enter()
  630. {
  631. CFrame::BaseEnter();
  632. if (g_FusionEnterExitTracingEnabled)
  633. ::FusionpTraceCallEntry();
  634. }
  635. ~CFnTracerRelease()
  636. {
  637. if (g_FusionEnterExitTracingEnabled)
  638. ::FusionpTraceCallExit();
  639. }
  640. protected:
  641. T const *m_pThis;
  642. LONG &m_rlRefCount;
  643. private:
  644. CFnTracerRelease &operator=(const CFnTracerRelease &r); // intentionally not implemented
  645. CFnTracerRelease(const CFnTracerRelease &r); // intentionally not implemented
  646. };
  647. class CFnTracerHR : public CFrame
  648. {
  649. public:
  650. CFnTracerHR(
  651. const SXS_STATIC_TRACE_CONTEXT &rsftc,
  652. HRESULT &rhr
  653. ) : CFrame(rsftc),
  654. m_rhr(rhr) { }
  655. inline void Enter()
  656. {
  657. CFrame::BaseEnter();
  658. if (g_FusionEnterExitTracingEnabled)
  659. ::FusionpTraceCallEntry();
  660. }
  661. ~CFnTracerHR()
  662. {
  663. if (g_FusionEnterExitTracingEnabled)
  664. {
  665. const DWORD dwLastError = this->GetLastError();
  666. if (SUCCEEDED(m_rhr))
  667. {
  668. ::FusionpTraceCallCOMSuccessfulExit(m_rhr, NULL);
  669. }
  670. else
  671. {
  672. ::FusionpTraceCallCOMUnsuccessfulExit(m_rhr, NULL);
  673. }
  674. this->SetLastError(dwLastError);
  675. }
  676. }
  677. void MarkInternalError() { m_rhr = HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR); }
  678. void MarkAllocationFailed() { m_rhr = E_OUTOFMEMORY; }
  679. void MarkInvalidParameter() { m_rhr = E_INVALIDARG; }
  680. void MarkWin32LastErrorFailure() { m_rhr = HRESULT_FROM_WIN32(this->GetLastError()); ASSERT_NTC(FAILED(m_rhr)); }
  681. void MarkWin32Failure(DWORD dwErrorCode) { m_rhr = HRESULT_FROM_WIN32(dwErrorCode); ::FusionpConvertCOMFailure(m_rhr); ASSERT_NTC(FAILED(m_rhr)); }
  682. void MarkCOMFailure(HRESULT hr) { ASSERT_NTC(FAILED(hr)); ::FusionpConvertCOMFailure(hr); ASSERT_NTC(FAILED(hr)); m_rhr = hr; }
  683. void MarkSuccess() { m_rhr = NOERROR; }
  684. HRESULT ReturnValue() const { return m_rhr; }
  685. HRESULT &m_rhr;
  686. private:
  687. CFnTracerHR &operator=(const CFnTracerHR &r); // intentionally not implemented
  688. CFnTracerHR(const CFnTracerHR &r); // intentionally not implemented
  689. };
  690. class CFnTracerWin32 : public CFrame
  691. {
  692. public:
  693. inline CFnTracerWin32(
  694. const SXS_STATIC_TRACE_CONTEXT &rsftc,
  695. BOOL &rfSucceeded
  696. ) : CFrame(rsftc),
  697. m_rfSucceeded(rfSucceeded)
  698. {
  699. }
  700. inline void Enter()
  701. {
  702. CFrame::BaseEnter();
  703. if (g_FusionEnterExitTracingEnabled)
  704. ::FusionpTraceCallEntry();
  705. }
  706. inline ~CFnTracerWin32()
  707. {
  708. if (g_FusionEnterExitTracingEnabled)
  709. {
  710. if (m_rfSucceeded)
  711. ::FusionpTraceCallSuccessfulExit(NULL);
  712. else
  713. {
  714. ASSERT_NTC(this->GetLastError() != ERROR_SUCCESS);
  715. ::FusionpTraceCallWin32UnsuccessfulExit(this->GetLastError(), NULL);
  716. }
  717. }
  718. }
  719. inline void MarkInternalError() { this->SetLastError(ERROR_INTERNAL_ERROR); m_rfSucceeded = FALSE; }
  720. inline void MarkAllocationFailed() { this->SetLastError(FUSION_WIN32_ALLOCFAILED_ERROR); m_rfSucceeded = FALSE; }
  721. inline void MarkInvalidParameter() { this->SetLastError(ERROR_INVALID_PARAMETER); m_rfSucceeded = FALSE; }
  722. inline void MarkSuccess() { this->SetLastError(ERROR_SUCCESS); m_rfSucceeded = TRUE; }
  723. inline void MarkWin32LastErrorFailure() { ASSERT_NTC(this->GetLastError() != ERROR_SUCCESS); m_rfSucceeded = FALSE; }
  724. inline void MarkWin32Failure(DWORD dwErrorCode) { ASSERT_NTC(dwErrorCode != ERROR_SUCCESS); this->SetLastError(dwErrorCode); m_rfSucceeded = FALSE; }
  725. void MarkCOMFailure(HRESULT hr) { hr = this->ConvertCOMFailure(hr); this->SetLastError(::FusionpHRESULTToWin32(hr)); m_rfSucceeded = FALSE; }
  726. inline BOOL ReturnValue() const { return m_rfSucceeded; }
  727. BOOL &m_rfSucceeded;
  728. protected:
  729. private:
  730. CFnTracerWin32 &operator=(const CFnTracerWin32 &r); // intentionally not implemented
  731. CFnTracerWin32(const CFnTracerWin32 &r); // intentionally not implemented
  732. };
  733. class CFnTracerReg : public CFrame
  734. {
  735. public:
  736. inline CFnTracerReg(
  737. const SXS_STATIC_TRACE_CONTEXT &rsftc,
  738. LONG &rlError
  739. ) : CFrame(rsftc),
  740. m_rlError(rlError)
  741. {
  742. }
  743. inline void Enter()
  744. {
  745. CFrame::BaseEnter();
  746. if (g_FusionEnterExitTracingEnabled)
  747. ::FusionpTraceCallEntry();
  748. }
  749. ~CFnTracerReg()
  750. {
  751. if (g_FusionEnterExitTracingEnabled)
  752. {
  753. if (m_rlError == ERROR_SUCCESS)
  754. {
  755. ::FusionpTraceCallSuccessfulExit(NULL);
  756. }
  757. else
  758. {
  759. ::FusionpTraceCallWin32UnsuccessfulExit(m_rlError, NULL);
  760. }
  761. }
  762. }
  763. void MarkInternalError() { m_rlError = ERROR_INTERNAL_ERROR; }
  764. void MarkAllocationFailed() { m_rlError = FUSION_WIN32_ALLOCFAILED_ERROR; }
  765. void MarkInvalidParameter() { m_rlError = ERROR_INVALID_PARAMETER; }
  766. LONG ReturnValue() const { return m_rlError; }
  767. LONG &m_rlError;
  768. protected:
  769. private:
  770. CFnTracerReg &operator=(const CFnTracerReg &r); // intentionally not implemented
  771. CFnTracerReg(const CFnTracerReg &r); // intentionally not implemented
  772. };
  773. #define FN_TRACE_EX(_stc, _fsmarttlsusage) CFnTracer __t(_stc, (_fsmarttlsusage)); __t.Enter()
  774. #define FN_TRACE_WIN32_EX(_stc, _fsucceeded) CFnTracerWin32 __t(_stc, _fsucceeded); __t.Enter()
  775. #define FN_TRACE_REG_EX(_stc, _lastError) CFnTracerReg __t(_stc, _lastError); __t.Enter()
  776. #define FN_TRACE_HR_EX(_stc, _hr) CFnTracerHR __t(_stc, _hr); __t.Enter()
  777. #define FN_TRACE_CONSTRUCTOR_EX(_stc, _thistype, _this) CFnTracerConstructor<_thistype> __t(_stc, #_thistype, _this); __t.Enter()
  778. #define FN_TRACE_DESTRUCTOR_EX(_stc, _thistype, _this) CFnTracerDestructor<_thistype> __t(_stc, #_thistype, _this); __t.Enter()
  779. #define FN_TRACE_ADDREF_EX(_stc, _thistype, _this, _var) CFnTracerAddRef<_thistype> __t(_stc, #_thistype, (_this), (_var)); __t.Enter()
  780. #define FN_TRACE_RELEASE_EX(_stc, _thistype, _this, _var) CFnTracerRelease<_thistype> __t(_stc, (_this), (_var)); __t.Enter()
  781. #if !defined(FUSION_DEFAULT_FUNCTION_ENTRY_TRACE_LEVEL)
  782. #define FUSION_DEFAULT_FUNCTION_ENTRY_TRACE_LEVEL (FUSION_DBG_LEVEL_ENTEREXIT)
  783. #endif
  784. #if !defined(FUSION_DEFAULT_FUNCTION_SUCCESSFUL_EXIT_TRACE_LEVEL)
  785. #define FUSION_DEFAULT_FUNCTION_SUCCESSFUL_EXIT_TRACE_LEVEL (FUSION_DBG_LEVEL_ENTEREXIT)
  786. #endif
  787. #if !defined(FUSION_DEFAULT_FUNCTION_UNSUCCESSFUL_EXIT_TRACE_LEVEL)
  788. #define FUSION_DEFAULT_FUNCTION_UNSUCCESSFUL_EXIT_TRACE_LEVEL (FUSION_DBG_LEVEL_ENTEREXIT | FUSION_DBG_LEVEL_ERROREXITPATH)
  789. #endif
  790. #if !defined(FUSION_DEFAULT_CONSTRUCTOR_ENTRY_TRACE_LEVEL)
  791. #define FUSION_DEFAULT_CONSTRUCTOR_ENTRY_TRACE_LEVEL (FUSION_DBG_LEVEL_CONSTRUCTORS)
  792. #endif
  793. #if !defined(FUSION_DEFAULT_CONSTRUCTOR_EXIT_TRACE_LEVEL)
  794. #define FUSION_DEFAULT_CONSTRUCTOR_EXIT_TRACE_LEVEL (FUSION_DBG_LEVEL_CONSTRUCTORS)
  795. #endif
  796. #if !defined(FUSION_DEFAULT_DESTRUCTOR_ENTRY_TRACE_LEVEL)
  797. #define FUSION_DEFAULT_DESTRUCTOR_ENTRY_TRACE_LEVEL (FUSION_DBG_LEVEL_DESTRUCTORS)
  798. #endif
  799. #if !defined(FUSION_DEFAULT_DESTRUCTOR_EXIT_TRACE_LEVEL)
  800. #define FUSION_DEFAULT_DESTRUCTOR_EXIT_TRACE_LEVEL (FUSION_DBG_LEVEL_DESTRUCTORS)
  801. #endif
  802. #if !defined(FUSION_DEFAULT_ADDREF_ENTRY_TRACE_LEVEL)
  803. #define FUSION_DEFAULT_ADDREF_ENTRY_TRACE_LEVEL (FUSION_DBG_LEVEL_REFCOUNTING)
  804. #endif
  805. #if !defined(FUSION_DEFAULT_ADDREF_EXIT_TRACE_LEVEL)
  806. #define FUSION_DEFAULT_ADDREF_EXIT_TRACE_LEVEL (FUSION_DBG_LEVEL_REFCOUNTING)
  807. #endif
  808. #if !defined(FUSION_DEFAULT_RELEASE_ENTRY_TRACE_LEVEL)
  809. #define FUSION_DEFAULT_RELEASE_ENTRY_TRACE_LEVEL (FUSION_DBG_LEVEL_REFCOUNTING)
  810. #endif
  811. #if !defined(FUSION_DEFAULT_RELEASE_EXIT_NONZERO_TRACE_LEVEL)
  812. #define FUSION_DEFAULT_RELEASE_NONZERO_EXIT_TRACE_LEVEL (FUSION_DBG_LEVEL_REFCOUNTING)
  813. #endif
  814. #if !defined(FUSION_DEFAULT_RELEASE_EXIT_ZERO_TRACE_LEVEL)
  815. #define FUSION_DEFAULT_RELEASE_ZERO_EXIT_TRACE_LEVEL (FUSION_DBG_LEVEL_REFCOUNTING)
  816. #endif
  817. //
  818. // #undef and #define FUSION_FACILITY_MASK to any specific additional debug output
  819. // filtering bits you want to set.
  820. //
  821. #if !defined(FUSION_FACILITY_MASK)
  822. #define FUSION_FACILITY_MASK (0)
  823. #endif // !defined(FUSION_FACILITY_MASK)
  824. #define DEFINE_STATIC_TRACE_CONTEXT() static const SXS_STATIC_TRACE_CONTEXT __stc = { { { TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED, __FUNCTION__ }, __FILE__ }, __LINE__ }
  825. #define DEFINE_STATIC_FN_TRACE_CONTEXT() static const SXS_STATIC_TRACE_CONTEXT __stc = { { { TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED, __FUNCTION__ }, __FILE__ }, __LINE__ }
  826. #define DEFINE_STATIC_CONSTRUCTOR_TRACE_CONTEXT() static const SXS_STATIC_TRACE_CONTEXT __stc = { { { TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED, __FUNCTION__ }, __FILE__ }, __LINE__ }
  827. #define DEFINE_STATIC_DESTRUCTOR_TRACE_CONTEXT() static const SXS_STATIC_TRACE_CONTEXT __stc = { { { TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED, __FUNCTION__ }, __FILE__ }, __LINE__ }
  828. #define DEFINE_STATIC_ADDREF_TRACE_CONTEXT() static const SXS_STATIC_TRACE_CONTEXT __stc = { { { TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED, __FUNCTION__ }, __FILE__ }, __LINE__ }
  829. #define DEFINE_STATIC_RELEASE_TRACE_CONTEXT(_thistype) static const SXS_STATIC_RELEASE_TRACE_CONTEXT __stc = { { { { TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED, __FUNCTION__ }, __FILE__ }, __LINE__ }, #_thistype }
  830. #define DEFINE_STATIC_FN_TRACE_CONTEXT2() static const SXS_STATIC_TRACE_CONTEXT __stc = { { { TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED, __FUNCTION__ }, __FILE__ }, __LINE__ }
  831. #define FN_TRACE() DEFINE_STATIC_FN_TRACE_CONTEXT(); FN_TRACE_EX(__stc, , FALSE)
  832. #define FN_TRACE_SMART_TLS() DEFINE_STATIC_FN_TRACE_CONTEXT(); FN_TRACE_EX(__stc, TRUE)
  833. #define FN_TRACE_WIN32(_fsucceeded) DEFINE_STATIC_FN_TRACE_CONTEXT2(); FN_TRACE_WIN32_EX(__stc, _fsucceeded)
  834. #define FN_TRACE_REG(_lastError) DEFINE_STATIC_FN_TRACE_CONTEXT2(); FN_TRACE_REG_EX(__stc, _lastError)
  835. #define FN_TRACE_HR(_hr) DEFINE_STATIC_FN_TRACE_CONTEXT2(); FN_TRACE_HR_EX(__stc, _hr)
  836. #define FN_TRACE_CONSTRUCTOR(_thistype) DEFINE_STATIC_CONSTRUCTOR_TRACE_CONTEXT(); FN_TRACE_CONSTRUCTOR_EX(__stc, _thistype, this)
  837. #define FN_TRACE_DESTRUCTOR(_thistype) DEFINE_STATIC_DESTRUCTOR_TRACE_CONTEXT(); FN_TRACE_DESTRUCTOR_EX(__stc, _thistype, this)
  838. #define FN_TRACE_ADDREF(_thistype, _var) DEFINE_STATIC_ADDREF_TRACE_CONTEXT(); FN_TRACE_ADDREF_EX(__stc, _thistype, this, _var)
  839. #define FN_TRACE_RELEASE(_thistype, _var) DEFINE_STATIC_RELEASE_TRACE_CONTEXT(_thistype); FN_TRACE_RELEASE_EX(__stc, _thistype, this, _var)
  840. #define FN_PROLOG_VOID FN_TRACE();
  841. #define FN_PROLOG_VOID_TLS FN_TRACE_SMART_TLS();
  842. #define FN_PROLOG_WIN32 BOOL __fSuccess = FALSE; FN_TRACE_WIN32(__fSuccess);
  843. #define FN_PROLOG_HR HRESULT __hr = ~static_cast<HRESULT>(0); FN_TRACE_HR(__hr);
  844. // "if (false) { goto Exit; }" here is probably to quash the compiler's warning about
  845. // Exit not being otherwise used.
  846. #define FN_EPILOG if (false) { goto Exit; } __t.MarkSuccess(); Exit: return __t.ReturnValue();
  847. #define TRACED_RELEASE(_var) __t.Release(_var)
  848. #define FN_TRACE_UPDATE_LINE() do { __t.SetLine(__LINE__); } while (0)
  849. #define FUSION_CLEAR_LAST_ERROR() do { __t.ClearLastError(); } while (0)
  850. #define FUSION_SET_LAST_ERROR(_le) do { __t.SetLastError((_le)); } while (0)
  851. #define FUSION_VERIFY_LAST_ERROR_SET() do { ASSERT(::FusionpGetLastWin32Error() != ERROR_SUCCESS); } while (0)
  852. #define LIST_1(x) { x }
  853. #define LIST_2(x, y) { x , y }
  854. #define LIST_3(x, y, z) { x , y , z }
  855. #define LIST_4(a, b, c, d) { a , b , c , d }
  856. #define LIST_5(a, b, c, d, e) { a , b , c , d, e }
  857. /*
  858. for example:
  859. ORIGINATE_WIN32_FAILURE_AND_EXIT_EX(dwLastError, ("%s(%ls)", "GetFileAttributesW", lpFileName));
  860. or
  861. ORIGINATE_WIN32_FAILURE_AND_EXIT_EX(dwLastError, (GetFileAttributesW(%ls)", lpFileName));
  862. */
  863. #define ORIGINATE_WIN32_FAILURE_AND_EXIT_EX(le_, dbgprint_va_) \
  864. do { __t.MarkWin32Failure(le_); TRACE_WIN32_FAILURE_ORIGINATION_EX(dbgprint_va_); goto Exit; } while (0)
  865. #define TRACE_WIN32_FAILURE_EX(dbgprint_va_) do { \
  866. DEFINE_CALL_SITE_INFO_EX(callsite_); callsite_.TraceWin32LastErrorFailureEx dbgprint_va_; } while (0)
  867. #define TRACE_WIN32_FAILURE_ORIGINATION_EX(dbgprint_va_) do { \
  868. DEFINE_CALL_SITE_INFO_EX(callsite_); callsite_.TraceWin32LastErrorFailureOriginationEx dbgprint_va_; } while (0)
  869. #define ORIGINATE_WIN32_FAILURE_AND_EXIT(_x, _le) do { __t.MarkWin32Failure((_le)); TRACE_WIN32_FAILURE_ORIGINATION(_x); goto Exit; } while (0)
  870. #define IFFALSE_ORIGINATE_WIN32_FAILURE_AND_EXIT(_x, _le) do { if (!(_x)) { __t.MarkWin32Failure((_le)); TRACE_WIN32_FAILURE_ORIGINATION(_x); goto Exit; } } while (0)
  871. #define IFINVALIDHANDLE_EXIT_WIN32_TRACE(_x) do { FUSION_CLEAR_LAST_ERROR(); if ((_x) == INVALID_HANDLE_VALUE) { FUSION_VERIFY_LAST_ERROR_SET(); TRACE_WIN32_FAILURE(_x); goto Exit; } } while (0)
  872. /*
  873. for example:
  874. IFW32FALSE_EXIT_EX(f.Win32CreateFile(psz), ("%ls", psz));
  875. */
  876. #define IFW32FALSE_EXIT_EX(_x, dbgprint_va_) \
  877. do { FUSION_CLEAR_LAST_ERROR(); \
  878. if (!(_x)) { FUSION_VERIFY_LAST_ERROR_SET(); \
  879. __t.MarkWin32LastErrorFailure(); \
  880. DEFINE_CALL_SITE_INFO(__callsite, _x); \
  881. __callsite.TraceWin32LastErrorFailureEx dbgprint_va_; \
  882. goto Exit; } } while (0)
  883. #define IFW32FALSE_EXIT(_x) do { FUSION_CLEAR_LAST_ERROR(); if (!(_x)) { FUSION_VERIFY_LAST_ERROR_SET(); __t.MarkWin32LastErrorFailure(); TRACE_WIN32_FAILURE(_x); goto Exit; } } while (0)
  884. #define IFW32FALSE_ORIGINATE_AND_EXIT(_x) do { FUSION_CLEAR_LAST_ERROR(); if (!(_x)) { FUSION_VERIFY_LAST_ERROR_SET(); __t.MarkWin32LastErrorFailure(); TRACE_WIN32_FAILURE_ORIGINATION(_x); goto Exit; } } while (0)
  885. #define IFW32FALSE_EXIT_UNLESS(_x, _unless, _unlessHitFlag) do { FUSION_CLEAR_LAST_ERROR(); (_unlessHitFlag) = false; if (!(_x)) { FUSION_VERIFY_LAST_ERROR_SET(); if (_unless) (_unlessHitFlag) = true; else { TRACE_WIN32_FAILURE(_x); goto Exit; } } } while (0)
  886. #define IFW32FALSE_ORIGINATE_AND_EXIT_UNLESS(_x, _unless, _unlessHitFlag) do { FUSION_CLEAR_LAST_ERROR(); (_unlessHitFlag) = false; if (!(_x)) { FUSION_VERIFY_LAST_ERROR_SET(); if (_unless) (_unlessHitFlag) = true; else { TRACE_WIN32_FAILURE_ORIGINATION(_x); goto Exit; } } } while (0)
  887. #define IFW32FALSE_EXIT_UNLESS2(_x, _unless, _unlessHitFlag) do { static const DWORD _s_rgdwAcceptableLastErrorValues[] = _unless; FUSION_CLEAR_LAST_ERROR(); (_unlessHitFlag) = false; if (!(_x)) { ULONG _i; const DWORD _dwLastError = ::FusionpGetLastWin32Error(); FUSION_VERIFY_LAST_ERROR_SET(); for (_i=0; _i<NUMBER_OF(_s_rgdwAcceptableLastErrorValues); _i++) { if (_dwLastError == _s_rgdwAcceptableLastErrorValues[_i]) { (_unlessHitFlag) = true; break; } } if (_i == NUMBER_OF(_s_rgdwAcceptableLastErrorValues)) { TRACE_WIN32_FAILURE(_x); goto Exit; } } } while (0)
  888. #define IFW32FALSE_EXIT_UNLESS3(_x, _unless, _dwLastError) do { static const DWORD _s_rgdwAcceptableLastErrorValues[] = _unless; FUSION_CLEAR_LAST_ERROR(); (_dwLastError) = NO_ERROR; if (!(_x)) { ULONG _i; _dwLastError = ::FusionpGetLastWin32Error(); FUSION_VERIFY_LAST_ERROR_SET(); for (_i=0; _i<NUMBER_OF(_s_rgdwAcceptableLastErrorValues); _i++) { if (_dwLastError == _s_rgdwAcceptableLastErrorValues[_i]) { break; } } if (_i == NUMBER_OF(_s_rgdwAcceptableLastErrorValues)) { TRACE_WIN32_FAILURE(_x); goto Exit; } } } while (0)
  889. #define IFW32FALSE_ORIGINATE_AND_EXIT_UNLESS2(_x, _unless, _unlessHitFlag) do { static const DWORD _s_rgdwAcceptableLastErrorValues[] = _unless; FUSION_CLEAR_LAST_ERROR(); (_unlessHitFlag) = false; if (!(_x)) { ULONG _i; const DWORD _dwLastError = ::FusionpGetLastWin32Error(); FUSION_VERIFY_LAST_ERROR_SET(); for (_i=0; _i<NUMBER_OF(_s_rgdwAcceptableLastErrorValues); _i++) { if (_dwLastError == _s_rgdwAcceptableLastErrorValues[_i]) { (_unlessHitFlag) = true; break; } } if (_i == NUMBER_OF(_s_rgdwAcceptableLastErrorValues)) { TRACE_WIN32_FAILURE_ORIGINATION(_x); goto Exit; } } } while (0)
  890. #define IFW32FALSE_ORIGINATE_AND_EXIT_UNLESS3(_x, _unless, _dwLastError) do { static const DWORD _s_rgdwAcceptableLastErrorValues[] = _unless; FUSION_CLEAR_LAST_ERROR(); (_dwLastError) = NO_ERROR; if (!(_x)) { ULONG _i; _dwLastError = ::FusionpGetLastWin32Error(); FUSION_VERIFY_LAST_ERROR_SET(); for (_i=0; _i<NUMBER_OF(_s_rgdwAcceptableLastErrorValues); _i++) { if (_dwLastError == _s_rgdwAcceptableLastErrorValues[_i]) { break; } } if (_i == NUMBER_OF(_s_rgdwAcceptableLastErrorValues)) { TRACE_WIN32_FAILURE_ORIGINATION(_x); goto Exit; } } } while (0)
  891. #define IFW32INVALIDHANDLE_EXIT(_x) do { FUSION_CLEAR_LAST_ERROR(); if ((_x) == INVALID_HANDLE_VALUE) { FUSION_VERIFY_LAST_ERROR_SET(); TRACE_WIN32_FAILURE(_x); goto Exit; } } while (0)
  892. #define IFW32INVALIDHANDLE_ORIGINATE_AND_EXIT(_x) do { FUSION_CLEAR_LAST_ERROR(); if ((_x) == INVALID_HANDLE_VALUE) { FUSION_VERIFY_LAST_ERROR_SET(); TRACE_WIN32_FAILURE_ORIGINATION(_x); goto Exit; } } while (0)
  893. #define IFREGFAILED_EXIT(_x) do { LONG __l; __l = (_x); if (__l != ERROR_SUCCESS) { __t.MarkWin32Failure(__l); FusionpSetLastWin32Error(__l); TRACE_WIN32_FAILURE(_x); goto Exit; } } while (0)
  894. #define IFREGFAILED_ORIGINATE_AND_EXIT(_x) do { LONG __l; __l = (_x); if (__l != ERROR_SUCCESS) { __t.MarkWin32Failure(__l); FusionpSetLastWin32Error(__l); TRACE_WIN32_FAILURE_ORIGINATION(_x); goto Exit; } } while (0)
  895. #define IFREGFAILED_EXIT_UNLESS2(_x, _unlessStatuses, _unlessHitFlag) do { LONG _validStatuses[] = _unlessStatuses; LONG __l; (_unlessHitFlag) = false; __l = (_x); if ( __l != ERROR_SUCCESS ) { ULONG i; for ( i = 0; i < NUMBER_OF(_validStatuses); i++ ) if ( _validStatuses[i] == __l ) { (_unlessHitFlag) = true; break; } if (i == NUMBER_OF(_validStatuses)) { FusionpSetLastWin32Error(__l); TRACE_WIN32_FAILURE(_x); goto Exit;}}} while (0)
  896. #define IFREGFAILED_ORIGINATE_AND_EXIT_UNLESS2(_x, _unlessStatuses, _unlessHitFlag) do { LONG _validStatuses[] = _unlessStatuses; LONG __l; (_unlessHitFlag) = false; __l = (_x); if ( __l != ERROR_SUCCESS ) { ULONG i; for ( i = 0; i < NUMBER_OF(_validStatuses); i++ ) if ( _validStatuses[i] == __l ) { (_unlessHitFlag) = true; break; } if (i == NUMBER_OF(_validStatuses)) { FusionpSetLastWin32Error(__l); TRACE_WIN32_FAILURE_ORIGINATION(_x); goto Exit;}}} while (0)
  897. #define IFCOMFAILED_EXIT(_x) do { FUSION_CLEAR_LAST_ERROR(); HRESULT __hr = (_x); if (FAILED(__hr)) { TRACE_COM_FAILURE(__hr, _x); __t.MarkCOMFailure(__hr); goto Exit; } } while (0)
  898. #define IFCOMFAILED_ORIGINATE_AND_EXIT(_x) do { FUSION_CLEAR_LAST_ERROR(); HRESULT __hr = (_x); if (FAILED(__hr)) { TRACE_COM_FAILURE_ORIGINATION(__hr, _x); __t.MarkCOMFailure(__hr); goto Exit; } } while (0)
  899. #define IFFAILED_CONVERTHR_HRTOWIN32_EXIT_TRACE(_x) do { HRESULT __hr = (_x); if (FAILED(__hr)) { FusionpConvertCOMFailure(__hr); TRACE_COM_FAILURE(__hr, _x); FusionpSetLastErrorFromHRESULT(__hr); goto Exit; } } while (0)
  900. #define IFINVALID_FLAGS_EXIT_WIN32_HARD_ASSERT(_f, _fValid) do { HARD_ASSERT(((_f) & ~(_fValid)) == 0); if ((_f) & ~(_fValid)) { TRACE_INVALID_FLAGS(_f, _fValid); ::FusionpSetLastWin32Error(ERROR_INVALID_PARAMETER); goto Exit; } } while (0)
  901. #define IFINVALID_FLAGS_EXIT_WIN32_SOFT_ASSERT(_f, _fValid) do { SOFT_ASSERT(((_f) & ~(_fValid)) == 0); if ((_f) & ~(_fValid)) { TRACE_INVALID_FLAGS(_f, _fValid); ::FusionpSetLastWin32Error(ERROR_INVALID_PARAMETER); goto Exit; } } while (0)
  902. #define IFINVALID_FLAGS_EXIT_COM_HARD_ASSERT(_hr, _f, _fValid) do { HARD_ASSERT(((_f) & ~(_fValid)) == 0); if ((_f) & ~(_fValid)) { TRACE_INVALID_FLAGS(_f, _fValid); _hr = E_INVALIDARG; goto Exit; } } while (0)
  903. #define IFINVALID_FLAGS_EXIT_COM_SOFT_ASSERT(_hr, _f, _fValid) do { SOFT_ASSERT(((_f) & ~(_fValid)) == 0); if ((_f) & ~(_fValid)) { TRACE_INVALID_FLAGS(_f, _fValid); _hr = E_INVALIDARG; goto Exit; } } while (0)
  904. #define IFALLOCFAILED_EXIT(_x) do { if ((_x) == NULL) { TRACE_ALLOCFAILED(_x); __t.MarkAllocationFailed(); goto Exit; } } while (0)
  905. #define IFW32NULL_EXIT(_x) do { FUSION_CLEAR_LAST_ERROR(); if ((_x) == NULL) { TRACE_WIN32_FAILURE_ORIGINATION(_x); FUSION_VERIFY_LAST_ERROR_SET(); goto Exit; } } while (0)
  906. #define IFW32NULL_ORIGINATE_AND_EXIT(_x) do { FUSION_CLEAR_LAST_ERROR(); if ((_x) == NULL) { TRACE_WIN32_FAILURE_ORIGINATION(_x); FUSION_VERIFY_LAST_ERROR_SET(); goto Exit; } } while (0)
  907. #define IFW32NULL_ORIGINATE_AND_EXIT_UNLESS2(_x, _unlessStatuses, _unlessHitFlag) do { DWORD __validStatuses[] = _unlessStatuses; _unlessHitFlag = false; FUSION_CLEAR_LAST_ERROR(); if ((_x) == NULL) { const DWORD __dwLastError = ::FusionpGetLastWin32Error(); ULONG __i; for (__i = 0; __i < NUMBER_OF(__validStatuses); __i++ ) if (__validStatuses[__i] == __dwLastError) { (_unlessHitFlag) = true; break; } if (i == NUMBER_OF(__validStatuses)) { TRACE_WIN32_FAILURE_ORIGINATION(_x); FUSION_VERIFY_LAST_ERROR_SET(); goto Exit; } } } while (0)
  908. #define IFW32ZERO_ORIGINATE_AND_EXIT(_x) do { FUSION_CLEAR_LAST_ERROR(); if ((_x) == 0) { TRACE_WIN32_FAILURE_ORIGINATION(_x); FUSION_VERIFY_LAST_ERROR_SET(); goto Exit; } } while (0)
  909. #define IFW32ZERO_EXIT(_x) do { FUSION_CLEAR_LAST_ERROR(); if ((_x) == 0) { TRACE_NULL(_x); FUSION_VERIFY_LAST_ERROR_SET(); goto Exit; } } while (0)
  910. #define PARAMETER_CHECK(_e) do { if (!(_e)) { __t.SetLine(__LINE__); TRACE_PARAMETER_CHECK(_e); __t.MarkInvalidParameter(); goto Exit; } } while (0)
  911. #define IFINVALID_FLAGS_EXIT_WIN32(_f, _fValid) IFINVALID_FLAGS_EXIT_WIN32_HARD_ASSERT(_f, _fValid)
  912. #define IFINVALID_FLAGS_EXIT_COM(_hr, _f, _fValid) IFINVALID_FLAGS_EXIT_COM_HARD_ASSERT(_hr, _f, _fValid)
  913. #define FN_SUCCESSFUL_EXIT() do { FUSION_CLEAR_LAST_ERROR(); __t.MarkSuccess(); goto Exit; } while (0)
  914. /*
  915. This is not exposed without doing more work wrt "FusionpDbgWouldPrintAtFilterLevel".
  916. ULONG
  917. FusionpvDbgPrintEx(
  918. ULONG Level,
  919. PCSTR Format,
  920. va_list ap
  921. );
  922. */
  923. ULONG
  924. FusionpDbgPrintEx(
  925. ULONG Level,
  926. PCSTR Format,
  927. ...
  928. );
  929. VOID
  930. FusionpDbgPrintBlob(
  931. ULONG Level,
  932. PVOID Data,
  933. SIZE_T Length,
  934. PCWSTR PerLinePrefix
  935. );
  936. void
  937. FusionpGetProcessImageFileName(
  938. PUNICODE_STRING ProcessImageFileName
  939. );
  940. #endif // !defined(_FUSION_INC_DEBMACRO_H_INCLUDED_)