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.

1143 lines
48 KiB

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