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.

905 lines
30 KiB

  1. //====== Assertion/Debug output APIs =================================
  2. #include <platform.h> // for __endexcept
  3. #pragma warning (disable:4096) // '__cdecl' must be used with '...'
  4. #pragma warning (disable:4201) // nonstandard extension used : nameless struct/union
  5. #pragma warning (disable:4115) // named type definition in parentheses
  6. #if defined(DECLARE_DEBUG) && defined(DEBUG)
  7. //
  8. // Declare module-specific debug strings
  9. //
  10. // When including this header in your private header file, do not
  11. // define DECLARE_DEBUG. But do define DECLARE_DEBUG in one of the
  12. // source files in your project, and then include this header file.
  13. //
  14. // You may also define the following:
  15. //
  16. // SZ_DEBUGINI - the .ini file used to set debug flags
  17. // SZ_DEBUGSECTION - the section in the .ini file specific to
  18. // the module component.
  19. // SZ_MODULE - ansi version of the name of your module.
  20. //
  21. //
  22. // (These are deliberately CHAR)
  23. EXTERN_C const CHAR FAR c_szCcshellIniFile[] = SZ_DEBUGINI;
  24. EXTERN_C const CHAR FAR c_szCcshellIniSecDebug[] = SZ_DEBUGSECTION;
  25. EXTERN_C const WCHAR FAR c_wszTrace[] = L"t " TEXTW(SZ_MODULE) L" ";
  26. EXTERN_C const WCHAR FAR c_wszErrorDbg[] = L"err " TEXTW(SZ_MODULE) L" ";
  27. EXTERN_C const WCHAR FAR c_wszWarningDbg[] = L"wn " TEXTW(SZ_MODULE) L" ";
  28. EXTERN_C const WCHAR FAR c_wszAssertMsg[] = TEXTW(SZ_MODULE) L" Assert: ";
  29. EXTERN_C const WCHAR FAR c_wszAssertFailed[] = TEXTW(SZ_MODULE) L" Assert %ls, line %d: (%ls)\r\n";
  30. EXTERN_C const WCHAR FAR c_wszRip[] = TEXTW(SZ_MODULE) L" RIP in %s at %s, line %d: (%s)\r\n";
  31. EXTERN_C const WCHAR FAR c_wszRipNoFn[] = TEXTW(SZ_MODULE) L" RIP at %s, line %d: (%s)\r\n";
  32. // (These are deliberately CHAR)
  33. EXTERN_C const CHAR FAR c_szTrace[] = "t " SZ_MODULE " ";
  34. EXTERN_C const CHAR FAR c_szErrorDbg[] = "err " SZ_MODULE " ";
  35. EXTERN_C const CHAR FAR c_szWarningDbg[] = "wn " SZ_MODULE " ";
  36. EXTERN_C const CHAR FAR c_szAssertMsg[] = SZ_MODULE " Assert: ";
  37. EXTERN_C const CHAR FAR c_szAssertFailed[] = SZ_MODULE " Assert %s, line %d: (%s)\r\n";
  38. EXTERN_C const CHAR FAR c_szRip[] = SZ_MODULE " RIP in %s at %s, line %d: (%s)\r\n";
  39. EXTERN_C const CHAR FAR c_szRipNoFn[] = SZ_MODULE " RIP at %s, line %d: (%s)\r\n";
  40. EXTERN_C const CHAR FAR c_szRipMsg[] = SZ_MODULE " RIP: ";
  41. #endif // DECLARE_DEBUG && DEBUG
  42. #if defined(DECLARE_DEBUG) && defined(PRODUCT_PROF)
  43. EXTERN_C const CHAR FAR c_szCcshellIniFile[] = SZ_DEBUGINI;
  44. EXTERN_C const CHAR FAR c_szCcshellIniSecDebug[] = SZ_DEBUGSECTION;
  45. #endif
  46. #ifdef __cplusplus
  47. extern "C" {
  48. #endif
  49. #if !defined(DECLARE_DEBUG)
  50. //
  51. // Debug macros and validation code
  52. //
  53. #if !defined(UNIX) || (defined(UNIX) && !defined(NOSHELLDEBUG))
  54. // Undefine the macros that we define in case some other header
  55. // might have tried defining these commonly-named macros.
  56. #undef Assert
  57. #undef AssertE
  58. #undef AssertMsg
  59. #undef AssertStrLen
  60. #undef DebugMsg
  61. #undef FullDebugMsg
  62. #undef ASSERT
  63. #undef EVAL
  64. #undef ASSERTMSG // catch people's typos
  65. #undef DBEXEC
  66. #ifdef _ATL_NO_DEBUG_CRT
  67. #undef _ASSERTE // we substitute this ATL macro
  68. #endif
  69. #endif // !UNIX
  70. // Access these globals to determine which debug flags are set.
  71. // These globals are modified by CcshellGetDebugFlags(), which
  72. // reads an .ini file and sets the appropriate flags.
  73. //
  74. // g_dwDumpFlags - bits are application specific. Typically
  75. // used for dumping structures.
  76. // g_dwBreakFlags - uses BF_* flags. The remaining bits are
  77. // application specific. Used to determine
  78. // when to break into the debugger.
  79. // g_qwTraceFlags - uses TF_* flags. The remaining bits are
  80. // application specific. Used to display
  81. // debug trace messages.
  82. // g_dwFuncTraceFlags - bits are application specific. When
  83. // TF_FUNC is set, CcshellFuncMsg uses this
  84. // value to determine which function traces
  85. // to display.
  86. // g_dwProtoype - bits are application specific. Use it for
  87. // anything.
  88. // g_dwProfileCAP - bits are application specific. Used to
  89. // control ICECAP profiling.
  90. //
  91. extern DWORD g_dwDumpFlags;
  92. extern DWORD g_dwBreakFlags;
  93. extern ULONGLONG g_qwTraceFlags;
  94. #ifdef DEBUG
  95. extern DWORD g_dwPrototype;
  96. #else
  97. #define g_dwPrototype 0
  98. #endif
  99. extern DWORD g_dwFuncTraceFlags;
  100. #if defined(DEBUG) || defined(PRODUCT_PROF)
  101. BOOL CcshellGetDebugFlags(void);
  102. #else
  103. #define CcshellGetDebugFlags() 0
  104. #endif
  105. // Break flags for g_dwBreakFlags
  106. #define BF_ASSERT 0x00000001 // Break on assertions
  107. #define BF_ONAPIENTER 0x00000002 // Break on entering an API
  108. #define BF_ONERRORMSG 0x00000004 // Break on TF_ERROR
  109. #define BF_ONWARNMSG 0x00000008 // Break on TF_WARNING
  110. #define BF_THR 0x00000100 // Break when THR() receives a failure
  111. #define BF_RIP 0x00000200 // Break on RIPs
  112. #define BF_LEAKS 0x80000000 // Break on detecting a leak
  113. // Trace flags for g_qwTraceFlags
  114. #define TF_ALWAYS 0xFFFFFFFFFFFFFFFF
  115. #define TF_NEVER 0x00000000
  116. #define TF_WARNING 0x00000001
  117. #define TF_ERROR 0x00000002
  118. #define TF_GENERAL 0x00000004 // Standard messages
  119. #define TF_FUNC 0x00000008 // Trace function calls
  120. #define TF_ATL 0x00000008 // Since TF_FUNC is so-little used, I'm overloading this bit
  121. #define TF_MEMUSAGE 0x0000000100000000
  122. #define TF_KEEP_ALLOCATION_STACKS 0x0000000200000000
  123. // (Upper 28 bits reserved for custom use per-module)
  124. #define TF_CUSTOM1 0x40000000 // Custom messages #1
  125. #define TF_CUSTOM2 0x80000000 // Custom messages #2
  126. // Old, archaic debug flags.
  127. // APPCOMPAT (scotth): the following flags will be phased out over time.
  128. #ifdef DM_TRACE
  129. #undef DM_TRACE
  130. #undef DM_WARNING
  131. #undef DM_ERROR
  132. #endif
  133. #define DM_TRACE TF_GENERAL // OBSOLETE Trace messages
  134. #define DM_WARNING TF_WARNING // OBSOLETE Warning
  135. #define DM_ERROR TF_ERROR // OBSOLETE Error
  136. // Use this macro to declare message text that will be placed
  137. // in the CODE segment (useful if DS is getting full)
  138. //
  139. // Ex: DEBUGTEXT(szMsg, "Invalid whatever: %d");
  140. //
  141. #define DEBUGTEXT(sz, msg) /* ;Internal */ \
  142. static const TCHAR sz[] = msg
  143. #ifndef NOSHELLDEBUG // Others have own versions of these.
  144. #ifdef DEBUG
  145. void AttachUserModeDebugger (void);
  146. #ifdef _X86_
  147. // Use int 3 so we stop immediately in the source
  148. #define DEBUG_BREAK \
  149. { \
  150. static BOOL gAlwaysAssert = FALSE; \
  151. AttachUserModeDebugger(); \
  152. do \
  153. { \
  154. _try \
  155. { \
  156. _asm int 3 \
  157. } \
  158. _except (EXCEPTION_EXECUTE_HANDLER) \
  159. { \
  160. } \
  161. } while (gAlwaysAssert); \
  162. }
  163. #else
  164. #define DEBUG_BREAK \
  165. { \
  166. static BOOL gAlwaysAssert = FALSE; \
  167. AttachUserModeDebugger(); \
  168. do \
  169. { \
  170. _try \
  171. { \
  172. DebugBreak(); \
  173. } \
  174. _except (EXCEPTION_EXECUTE_HANDLER) \
  175. { \
  176. } \
  177. __endexcept \
  178. } while (gAlwaysAssert); \
  179. }
  180. #endif
  181. // Prototypes for debug functions
  182. void CcshellStackEnter(void);
  183. void CcshellStackLeave(void);
  184. void CDECL CcshellFuncMsgW(ULONGLONG mask, LPCSTR pszMsg, ...);
  185. void CDECL CcshellFuncMsgA(ULONGLONG mask, LPCSTR pszMsg, ...);
  186. void CDECL _AssertMsgA(BOOL f, LPCSTR pszMsg, ...);
  187. void CDECL _AssertMsgW(BOOL f, LPCWSTR pszMsg, ...);
  188. void _AssertStrLenA(LPCSTR pszStr, int iLen);
  189. void _AssertStrLenW(LPCWSTR pwzStr, int iLen);
  190. #ifdef UNICODE
  191. #define CcshellFuncMsg CcshellFuncMsgW
  192. #define CcshellAssertMsg CcshellAssertMsgW
  193. #define _AssertMsg _AssertMsgW
  194. #define _AssertStrLen _AssertStrLenW
  195. #else
  196. #define CcshellFuncMsg CcshellFuncMsgA
  197. #define CcshellAssertMsg CcshellAssertMsgA
  198. #define _AssertMsg _AssertMsgA
  199. #define _AssertStrLen _AssertStrLenA
  200. #endif
  201. #endif // DEBUG
  202. // ASSERT(f)
  203. //
  204. // Generates a "Assert file.c, line x (eval)" message if f is NOT true.
  205. //
  206. // Use ASSERT() to check for logic invariance. These are typically considered
  207. // fatal problems, and falls into the 'this should never ever happen'
  208. // category.
  209. //
  210. // Do *not* use ASSERT() to verify successful API calls if the APIs can
  211. // legitimately fail due to low resources. For example, LocalAlloc can
  212. // legally fail, so you shouldn't assert that it will never fail.
  213. //
  214. // The BF_ASSERT bit in g_dwBreakFlags governs whether the function
  215. // performs a DebugBreak().
  216. //
  217. // Default Behavior-
  218. // Retail builds: nothing
  219. // Debug builds: spew and break
  220. // Full debug builds: spew and break
  221. //
  222. #ifdef DEBUG
  223. BOOL CcshellAssertFailedA(LPCSTR szFile, int line, LPCSTR pszEval, BOOL bBreakInside);
  224. BOOL CcshellAssertFailedW(LPCWSTR szFile, int line, LPCWSTR pwszEval, BOOL bBreakInside);
  225. #ifdef UNICODE
  226. #define CcshellAssertFailed CcshellAssertFailedW
  227. #else
  228. #define CcshellAssertFailed CcshellAssertFailedA
  229. #endif
  230. #define ASSERT(f) \
  231. { \
  232. DEBUGTEXT(szFile, TEXT(__FILE__)); \
  233. if (!(f) && CcshellAssertFailed(szFile, __LINE__, TEXT(#f), FALSE)) \
  234. DEBUG_BREAK; \
  235. }
  236. // The old Win95 code used to use "Assert()". We discourage the use
  237. // of this macro now because it is not msdev-friendly.
  238. #ifdef DISALLOW_Assert
  239. #define Assert(f) Dont_use_Assert___Use_ASSERT
  240. #else
  241. #define Assert(f) ASSERT(f)
  242. #endif
  243. #else // DEBUG
  244. #define ASSERT(f)
  245. #define Assert(f)
  246. #endif // DEBUG
  247. // ASSERTMSG(f, szFmt, args...)
  248. //
  249. // Behaves like ASSERT, except it prints the wsprintf-formatted message
  250. // instead of the file and line number.
  251. //
  252. // The sz parameter is always ANSI; AssertMsg correctly converts it
  253. // to unicode if necessary. This is so you don't have to wrap your
  254. // debug strings with TEXT().
  255. //
  256. // The BF_ASSERT bit in g_dwBreakFlags governs whether the function
  257. // performs a DebugBreak().
  258. //
  259. // Default Behavior-
  260. // Retail builds: nothing
  261. // Debug builds: spew and break
  262. // Full debug builds: spew and break
  263. //
  264. #ifdef DEBUG
  265. void CDECL CcshellAssertMsgW(BOOL bAssert, LPCSTR pszMsg, ...);
  266. void CDECL CcshellAssertMsgA(BOOL bAssert, LPCSTR pszMsg, ...);
  267. #ifdef UNICODE
  268. #define CcshellAssertMsg CcshellAssertMsgW
  269. #else
  270. #define CcshellAssertMsg CcshellAssertMsgA
  271. #endif
  272. #define ASSERTMSG CcshellAssertMsg
  273. #else // DEBUG
  274. #define ASSERTMSG 1 ? (void)0 : (void)
  275. #endif // DEBUG
  276. // EVAL(f)
  277. //
  278. // Behaves like ASSERT(). Evaluates the expression (f). The expression
  279. // is always evaluated, even in retail builds. But the macro only asserts
  280. // in the debug build. This macro may be used on logical expressions, eg:
  281. //
  282. // if (EVAL(exp))
  283. // // do something
  284. //
  285. // Do *not* use EVAL() to verify successful API calls if the APIs can
  286. // legitimately fail due to low resources. For example, LocalAlloc can
  287. // legally fail, so you shouldn't assert that it will never fail.
  288. //
  289. // The BF_ASSERT bit in g_dwBreakFlags governs whether the function
  290. // performs a DebugBreak().
  291. //
  292. // Default Behavior-
  293. // Retail builds: nothing
  294. // Debug builds: spew and break
  295. // Full debug builds: spew and break
  296. //
  297. #ifdef DEBUG
  298. #define EVAL(exp) \
  299. ((exp) || (CcshellAssertFailed(TEXT(__FILE__), __LINE__, TEXT(#exp), TRUE), 0))
  300. #else // DEBUG
  301. #define EVAL(exp) ((exp) != 0)
  302. #endif // DEBUG
  303. // RIP(f)
  304. //
  305. // Generates a "RIP at file.c, line x (eval)" message if f is NOT true.
  306. //
  307. // Use RIP() to perform parameter validation, especially when you
  308. // know the function or method may be called by a 3rd party app.
  309. // Typically, RIPs are used to indicate the caller passed in an invalid
  310. // parameter, so the problem is really not in the code itself.
  311. //
  312. // Do *not* use RIP() to verify successful API calls if the APIs can
  313. // legitimately fail due to low resources. For example, LocalAlloc can
  314. // legally fail, so you shouldn't assert that it will never fail.
  315. //
  316. // RIP performs a debugbreak only in the following processes:
  317. //
  318. // explore.exe
  319. // iexplore.exe
  320. // rundll32.exe
  321. // welcome.exe
  322. //
  323. // In any other process, this just spews the debug message, but doesn't stop.
  324. //
  325. // Setting the BF_RIP bit in g_dwBreakFlags will cause the macro to perform
  326. // a DebugBreak() even in non-shell processes.
  327. //
  328. // Default Behavior-
  329. // Retail builds: nothing
  330. // Debug builds: spew (other processes), spew and break (shell processes)
  331. // Full debug builds: spew (other processes), spew and break (shell processes)
  332. //
  333. #ifdef DEBUG
  334. BOOL CcshellRipA(LPCSTR pszFile, int line, LPCSTR pszEval, BOOL bBreakInside);
  335. BOOL CcshellRipW(LPCWSTR pszFile, int line, LPCWSTR pwszEval, BOOL bBreakInside);
  336. BOOL CDECL CcshellRipMsgA(BOOL bRip, LPCSTR pszMsg, ...);
  337. BOOL CDECL CcshellRipMsgW(BOOL bRip, LPCSTR pszMsg, ...);
  338. #ifdef UNICODE
  339. #define CcshellRip CcshellRipW
  340. #define CcshellRipMsg CcshellRipMsgW
  341. #else
  342. #define CcshellRip CcshellRipA
  343. #define CcshellRipMsg CcshellRipMsgA
  344. #endif
  345. #define RIP(f) \
  346. { \
  347. DEBUGTEXT(szFile, TEXT(__FILE__)); \
  348. if (!(f) && CcshellRip(szFile, __LINE__, TEXT(#f), FALSE)) \
  349. { \
  350. DEBUG_BREAK; \
  351. } \
  352. } \
  353. #define RIPMSG CcshellRipMsg
  354. #else // DEBUG
  355. #define RIP(f)
  356. #define RIPMSG 1 ? (void)0 : (void)
  357. #endif // DEBUG
  358. // TraceMsg(dwMask, sz, args...)
  359. //
  360. // Generate wsprintf-formatted message using the specified trace dwMask.
  361. // dwMask may be one of the predefined bits:
  362. //
  363. // TF_ERROR - display "err <MODULE> <string>"
  364. // TF_WARNING - display "wn <MODULE> <string>"
  365. // TF_GENERAL - display "t <MODULE> <string>"
  366. // TF_ALWAYS - display "t <MODULE> <string>" regardless of g_qwTraceFlags.
  367. //
  368. // or it may be a custom bit (any of the upper 28 bits).
  369. //
  370. // The g_qwTraceFlags global governs whether the message is displayed (based
  371. // upon the dwMask parameter).
  372. //
  373. // The sz parameter is always ANSI; TraceMsg correctly converts it
  374. // to unicode if necessary. This is so you don't have to wrap your
  375. // debug strings with TEXT().
  376. //
  377. // In addition to squirting the trace message, you may optionally cause
  378. // the trace message to stop if you need to trace down the source of
  379. // an error. The BF_ONERRORMSG and BF_ONWARNMSG bits may be set in
  380. // g_dwBreakFlags to make TraceMsg stop when a TF_ERROR or TF_WARNING
  381. // message is displayed. But typically these bits are disabled.
  382. //
  383. // Default Behavior-
  384. // Retail builds: nothing
  385. // Debug builds: only TF_ALWAYS and TF_ERROR messages spew
  386. // Full debug builds: spew
  387. //
  388. #ifdef DEBUG
  389. UINT GetStack(UINT nDepth, CHAR *szBuffer, UINT nBufferLength);
  390. void CDECL CcshellDebugMsgW(ULONGLONG mask, LPCSTR pszMsg, ...);
  391. void CDECL CcshellDebugMsgA(ULONGLONG mask, LPCSTR pszMsg, ...);
  392. void CDECL _DebugMsgA(ULONGLONG flag, LPCSTR psz, ...);
  393. void CDECL _DebugMsgW(ULONGLONG flag, LPCWSTR psz, ...);
  394. #ifdef UNICODE
  395. #define CcshellDebugMsg CcshellDebugMsgW
  396. #define _DebugMsg _DebugMsgW
  397. #else
  398. #define CcshellDebugMsg CcshellDebugMsgA
  399. #define _DebugMsg _DebugMsgA
  400. #endif
  401. #define TraceMsgW CcshellDebugMsgW
  402. #define TraceMsgA CcshellDebugMsgA
  403. #define TraceMsg CcshellDebugMsg
  404. // Use TraceMsg instead of DebugMsg. DebugMsg is obsolete.
  405. #ifdef DISALLOW_DebugMsg
  406. #define DebugMsg Dont_use_DebugMsg___Use_TraceMsg
  407. #else
  408. #define DebugMsg _DebugMsg
  409. #endif
  410. #else // DEBUG
  411. #define TraceMsgA 1 ? (void)0 : (void)
  412. #define TraceMsgW 1 ? (void)0 : (void)
  413. #define TraceMsg 1 ? (void)0 : (void)
  414. #define DebugMsg 1 ? (void)0 : (void)
  415. #endif // DEBUG
  416. // THR(pfn)
  417. // TBOOL(pfn)
  418. // TINT(pfn)
  419. // TPTR(pfn)
  420. // TW32(pfn)
  421. //
  422. // These macros are useful to trace failed calls to functions that return
  423. // HRESULTs, BOOLs, ints, or pointers. An example use of this is:
  424. //
  425. // {
  426. // ...
  427. // hres = THR(CoCreateInstance(CLSID_Bar, NULL, CLSCTX_INPROC_SERVER,
  428. // IID_IBar, (LPVOID*)&pbar));
  429. // if (SUCCEEDED(hres))
  430. // ...
  431. // }
  432. //
  433. // If CoCreateInstance failed, you would see spew similar to:
  434. //
  435. // err MODULE THR: Failure of "CoCreateInstance(CLSID_Bar, NULL, CLSCTX_INPROC_SERVER, IID_IBar, (LPVOID*)&pbar)" at foo.cpp, line 100 (0x80004005)
  436. //
  437. // THR keys off of the failure code of the hresult.
  438. // TBOOL considers FALSE to be a failure case.
  439. // TINT considers -1 to be a failure case.
  440. // TPTR considers NULL to be a failure case.
  441. // TW32 keys off the failure code of the Win32 error code.
  442. //
  443. // Set the BF_THR bit in g_dwBreakFlags to stop when these macros see a failure.
  444. //
  445. // Default Behavior-
  446. // Retail builds: nothing
  447. // Debug builds: nothing
  448. // Full debug builds: spew on error
  449. //
  450. #ifdef DEBUG
  451. EXTERN_C HRESULT TraceHR(HRESULT hrTest, LPCSTR pszExpr, LPCSTR pszFile, int iLine);
  452. EXTERN_C BOOL TraceBool(BOOL bTest, LPCSTR pszExpr, LPCSTR pszFile, int iLine);
  453. EXTERN_C int TraceInt(int iTest, LPCSTR pszExpr, LPCSTR pszFile, int iLine);
  454. EXTERN_C LPVOID TracePtr(LPVOID pvTest, LPCSTR pszExpr, LPCSTR pszFile, int iLine);
  455. EXTERN_C DWORD TraceWin32(DWORD dwTest, LPCSTR pszExpr, LPCSTR pszFile, int iLine);
  456. #define THR(x) (TraceHR((x), #x, __FILE__, __LINE__))
  457. #define TBOOL(x) (TraceBool((x), #x, __FILE__, __LINE__))
  458. #define TINT(x) (TraceInt((x), #x, __FILE__, __LINE__))
  459. #define TPTR(x) (TracePtr((x), #x, __FILE__, __LINE__))
  460. #define TW32(x) (TraceWin32((x), #x, __FILE__, __LINE__))
  461. #else // DEBUG
  462. #define THR(x) (x)
  463. #define TBOOL(x) (x)
  464. #define TINT(x) (x)
  465. #define TPTR(x) (x)
  466. #define TW32(x) (x)
  467. #endif // DEBUG
  468. // DBEXEC(flg, expr)
  469. //
  470. // under DEBUG, does "if (flg) expr;" (w/ the usual safe syntax)
  471. // under !DEBUG, does nothing (and does not evaluate either of its args)
  472. //
  473. #ifdef DEBUG
  474. #define DBEXEC(flg, expr) ((flg) ? (expr) : 0)
  475. #else // DEBUG
  476. #define DBEXEC(flg, expr) /*NOTHING*/
  477. #endif // DEBUG
  478. // string and buffer whacking functions
  479. //
  480. #ifdef DEBUG
  481. EXTERN_C void DEBUGWhackPathBufferA(LPSTR psz, UINT cch);
  482. EXTERN_C void DEBUGWhackPathBufferW(LPWSTR psz, UINT cch);
  483. EXTERN_C void DEBUGWhackPathStringA(LPSTR psz, UINT cch);
  484. EXTERN_C void DEBUGWhackPathStringW(LPWSTR psz, UINT cch);
  485. #else // DEBUG
  486. #define DEBUGWhackPathBufferA(psz, cch)
  487. #define DEBUGWhackPathBufferW(psz, cch)
  488. #define DEBUGWhackPathStringA(psz, cch)
  489. #define DEBUGWhackPathStringW(psz, cch)
  490. #endif // DEBUG
  491. #ifdef UNICODE
  492. #define DEBUGWhackPathBuffer DEBUGWhackPathBufferW
  493. #define DEBUGWhackPathString DEBUGWhackPathStringW
  494. #else
  495. #define DEBUGWhackPathBuffer DEBUGWhackPathBufferA
  496. #define DEBUGWhackPathString DEBUGWhackPathStringA
  497. #endif
  498. // Some trickery to map ATL debug macros to ours, so ATL code that stops
  499. // or spews in our code will look like the rest of our squirties.
  500. #ifdef DEBUG
  501. #ifdef _ATL_NO_DEBUG_CRT
  502. // ATL uses _ASSERTE. Map it to ours.
  503. #define _ASSERTE(f) ASSERT(f)
  504. // We map ATLTRACE macros to our functions
  505. void _cdecl ShellAtlTraceA(LPCSTR lpszFormat, ...);
  506. void _cdecl ShellAtlTraceW(LPCWSTR lpszFormat, ...);
  507. #ifdef UNICODE
  508. #define ShellAtlTrace ShellAtlTraceW
  509. #else
  510. #define ShellAtlTrace ShellAtlTraceA
  511. #endif
  512. // These are turned off because they normally don't give
  513. // feedback of error cases and so many fire that they
  514. // swamp out other useful debug spew.
  515. //#define ATLTRACE ShellAtlTrace
  516. #endif
  517. #else // DEBUG
  518. #ifdef _ATL_NO_DEBUG_CRT
  519. // ATL uses _ASSERTE. Map it to ours.
  520. #define _ASSERTE(f)
  521. // We map ATLTRACE macros to our functions
  522. #define ATLTRACE 1 ? (void)0 : (void)
  523. #define ATLTRACE2 1 ? (void)0 : (void)
  524. #endif
  525. #endif // DEBUG
  526. // ------ Stay away from these macros below ----------
  527. // APPCOMPAT (scotth): remove these by 8/15/98. They should not be used anymore.
  528. #ifdef DEBUG
  529. #define AssertE(f) ASSERT(f)
  530. #define AssertMsg _AssertMsg
  531. #define AssertStrLen _AssertStrLen
  532. #define AssertStrLenA _AssertStrLenA
  533. #define AssertStrLenW _AssertStrLenW
  534. #ifdef FULL_DEBUG
  535. #define FullDebugMsg _DebugMsg
  536. #else
  537. #define FullDebugMsg 1 ? (void)0 : (void)
  538. #endif
  539. #define ASSERT_MSGW CcshellAssertMsgW
  540. #define ASSERT_MSGA CcshellAssertMsgA
  541. #define ASSERT_MSG CcshellAssertMsg
  542. #else // DEBUG
  543. #define AssertE(f) (f)
  544. #define AssertMsg 1 ? (void)0 : (void)
  545. #define AssertStrLen(lpStr, iLen)
  546. #define FullDebugMsg 1 ? (void)0 : (void)
  547. #define ASSERT_MSGA 1 ? (void)0 : (void)
  548. #define ASSERT_MSGW 1 ? (void)0 : (void)
  549. #define ASSERT_MSG 1 ? (void)0 : (void)
  550. #endif // DEBUG
  551. // ------ Stay away from these macros above ----------
  552. // It's necessary to find when classes that were designed to be single threaded are used
  553. // across threads so they can be fixed to be multithreaded. These asserts will point
  554. // out such cases.
  555. #ifdef DEBUG
  556. #define ASSERT_SINGLE_THREADED AssertMsg(_dwThreadIDForSingleThreadedAssert == GetCurrentThreadId(), TEXT("MULTI-THREADED BUG: This class is being used by more than one thread, but it's not thread safe."))
  557. #define INIT_SINGLE_THREADED_ASSERT _dwThreadIDForSingleThreadedAssert = GetCurrentThreadId();
  558. #define SINGLE_THREADED_MEMBER_VARIABLE DWORD _dwThreadIDForSingleThreadedAssert;
  559. #else // DEBUG
  560. #define ASSERT_SINGLE_THREADED NULL;
  561. #define INIT_SINGLE_THREADED_ASSERT NULL;
  562. #define SINGLE_THREADED_MEMBER_VARIABLE
  563. #endif // DEBUG
  564. #ifdef DEBUG
  565. #define Dbg_SafeStrA(psz) (SAFECAST(psz, LPCSTR), (psz) ? (psz) : "NULL string")
  566. #define Dbg_SafeStrW(psz) (SAFECAST(psz, LPCWSTR), (psz) ? (psz) : L"NULL string")
  567. #ifdef UNICODE
  568. #define Dbg_SafeStr Dbg_SafeStrW
  569. #else
  570. #define Dbg_SafeStr Dbg_SafeStrA
  571. #endif
  572. #define FUNC_MSG CcshellFuncMsg
  573. // Helpful macro for mapping manifest constants to strings. Assumes
  574. // return string is pcsz. You can use this macro in this fashion:
  575. //
  576. // LPCSTR Dbg_GetFoo(FOO foo)
  577. // {
  578. // LPCTSTR pcsz = TEXT("Unknown <foo>");
  579. // switch (foo)
  580. // {
  581. // STRING_CASE(FOOVALUE1);
  582. // STRING_CASE(FOOVALUE2);
  583. // ...
  584. // }
  585. // return pcsz;
  586. // }
  587. //
  588. #define STRING_CASE(val) case val: pcsz = TEXT(#val); break
  589. // Debug function enter
  590. // DBG_ENTER(flag, fn) -- Generates a function entry debug spew for
  591. // a function
  592. //
  593. #define DBG_ENTER(flagFTF, fn) \
  594. (FUNC_MSG(flagFTF, " > " #fn "()"), \
  595. CcshellStackEnter())
  596. // DBG_ENTER_TYPE(flag, fn, dw, pfnStrFromType) -- Generates a function entry debug
  597. // spew for functions that accept <type>.
  598. //
  599. #define DBG_ENTER_TYPE(flagFTF, fn, dw, pfnStrFromType) \
  600. (FUNC_MSG(flagFTF, " < " #fn "(..., %s, ...)", (LPCTSTR)pfnStrFromType(dw)), \
  601. CcshellStackEnter())
  602. // DBG_ENTER_SZ(flag, fn, sz) -- Generates a function entry debug spew for
  603. // a function that accepts a string as one of its
  604. // parameters.
  605. //
  606. #define DBG_ENTER_SZ(flagFTF, fn, sz) \
  607. (FUNC_MSG(flagFTF, " > " #fn "(..., \"%s\",...)", Dbg_SafeStr(sz)), \
  608. CcshellStackEnter())
  609. // Debug function exit
  610. // DBG_EXIT(flag, fn) -- Generates a function exit debug spew
  611. //
  612. #define DBG_EXIT(flagFTF, fn) \
  613. (CcshellStackLeave(), \
  614. FUNC_MSG(flagFTF, " < " #fn "()"))
  615. // DBG_EXIT_TYPE(flag, fn, dw, pfnStrFromType) -- Generates a function exit debug
  616. // spew for functions that return <type>.
  617. //
  618. #define DBG_EXIT_TYPE(flagFTF, fn, dw, pfnStrFromType) \
  619. (CcshellStackLeave(), \
  620. FUNC_MSG(flagFTF, " < " #fn "() with %s", (LPCTSTR)pfnStrFromType(dw)))
  621. // DBG_EXIT_INT(flag, fn, us) -- Generates a function exit debug spew for
  622. // functions that return an INT.
  623. //
  624. #define DBG_EXIT_INT(flagFTF, fn, n) \
  625. (CcshellStackLeave(), \
  626. FUNC_MSG(flagFTF, " < " #fn "() with %d", (int)(n)))
  627. // DBG_EXIT_BOOL(flag, fn, b) -- Generates a function exit debug spew for
  628. // functions that return a boolean.
  629. //
  630. #define DBG_EXIT_BOOL(flagFTF, fn, b) \
  631. (CcshellStackLeave(), \
  632. FUNC_MSG(flagFTF, " < " #fn "() with %s", (b) ? (LPTSTR)TEXT("TRUE") : (LPTSTR)TEXT("FALSE")))
  633. // DBG_EXIT_UL(flag, fn, ul) -- Generates a function exit debug spew for
  634. // functions that return a ULONG.
  635. //
  636. #ifdef _WIN64
  637. #define DBG_EXIT_UL(flagFTF, fn, ul) \
  638. (CcshellStackLeave(), \
  639. FUNC_MSG(flagFTF, " < " #fn "() with %#016I64x", (ULONG_PTR)(ul)))
  640. #else
  641. #define DBG_EXIT_UL(flagFTF, fn, ul) \
  642. (CcshellStackLeave(), \
  643. FUNC_MSG(flagFTF, " < " #fn "() with %#08lx", (ULONG)(ul)))
  644. #endif // _WIN64
  645. #define DBG_EXIT_DWORD DBG_EXIT_UL
  646. // DBG_EXIT_HRES(flag, fn, hres) -- Generates a function exit debug spew for
  647. // functions that return an HRESULT.
  648. //
  649. #define DBG_EXIT_HRES(flagFTF, fn, hres) DBG_EXIT_TYPE(flagFTF, fn, hres, Dbg_GetHRESULTName)
  650. #else // DEBUG
  651. #define Dbg_SafeStr 1 ? (void)0 : (void)
  652. #define FUNC_MSG 1 ? (void)0 : (void)
  653. #define DBG_ENTER(flagFTF, fn)
  654. #define DBG_ENTER_TYPE(flagFTF, fn, dw, pfn)
  655. #define DBG_ENTER_SZ(flagFTF, fn, sz)
  656. #define DBG_EXIT(flagFTF, fn)
  657. #define DBG_EXIT_INT(flagFTF, fn, n)
  658. #define DBG_EXIT_BOOL(flagFTF, fn, b)
  659. #define DBG_EXIT_UL(flagFTF, fn, ul)
  660. #define DBG_EXIT_DWORD DBG_EXIT_UL
  661. #define DBG_EXIT_TYPE(flagFTF, fn, dw, pfn)
  662. #define DBG_EXIT_HRES(flagFTF, fn, hres)
  663. #endif // DEBUG
  664. // COMPILETIME_ASSERT(f)
  665. //
  666. // Generates a build break at compile time if the constant expression
  667. // is not true. Unlike the "#if" compile-time directive, the expression
  668. // in COMPILETIME_ASSERT() is allowed to use "sizeof".
  669. //
  670. // Compiler magic! If the expression "f" is FALSE, then you get the
  671. // compiler error "Duplicate case expression in switch statement".
  672. //
  673. #define COMPILETIME_ASSERT(f) switch (0) case 0: case f:
  674. #else // NOSHELLDEBUG
  675. #ifdef UNIX
  676. #include <crtdbg.h>
  677. #define ASSERT(f) _ASSERT(f)
  678. #include <mainwin.h>
  679. #define TraceMsg(type, sformat) DebugMessage(0, sformat)
  680. #define TraceMSG(type, sformat, args) DebugMessage(0, sformat, args)
  681. #endif
  682. #endif // NOSHELLDEBUG
  683. //
  684. // Debug dump helper functions
  685. //
  686. #ifdef DEBUG
  687. LPCTSTR Dbg_GetCFName(UINT ucf);
  688. LPCTSTR Dbg_GetHRESULTName(HRESULT hr);
  689. LPCTSTR Dbg_GetREFIIDName(REFIID riid);
  690. LPCTSTR Dbg_GetVTName(VARTYPE vt);
  691. #else
  692. #define Dbg_GetCFName(ucf) (void)0
  693. #define Dbg_GetHRESULTName(hr) (void)0
  694. #define Dbg_GetREFIIDName(riid) (void)0
  695. #define Dbg_GetVTName(vt) (void)0
  696. #endif // DEBUG
  697. // I'm a lazy typist...
  698. #define Dbg_GetHRESULT Dbg_GetHRESULTName
  699. // Parameter validation macros
  700. #include "validate.h"
  701. #endif // DECLARE_DEBUG
  702. #ifdef PRODUCT_PROF
  703. int __stdcall StartCAP(void); // start profiling
  704. int __stdcall StopCAP(void); // stop profiling until StartCAP
  705. int __stdcall SuspendCAP(void); // suspend profiling until ResumeCAP
  706. int __stdcall ResumeCAP(void); // resume profiling
  707. int __stdcall StartCAPAll(void); // process-wide start profiling
  708. int __stdcall StopCAPAll(void); // process-wide stop profiling
  709. int __stdcall SuspendCAPAll(void); // process-wide suspend profiling
  710. int __stdcall ResumeCAPAll(void); // process-wide resume profiling
  711. void __stdcall MarkCAP(long lMark); // write mark to MEA
  712. extern DWORD g_dwProfileCAP;
  713. #else
  714. #define StartCAP() 0
  715. #define StopCAP() 0
  716. #define SuspendCAP() 0
  717. #define ResumeCAP() 0
  718. #define StartCAPAll() 0
  719. #define StopCAPAll() 0
  720. #define SuspendCAPAll() 0
  721. #define ResumeCAPAll() 0
  722. #define MarkCAP(n) 0
  723. #define g_dwProfileCAP 0
  724. #endif
  725. #ifdef __cplusplus
  726. };
  727. #endif