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.

750 lines
18 KiB

  1. /*
  2. * C A L D B G . C
  3. *
  4. * Debugging Utilities
  5. *
  6. * Copyright 1993-1997 Microsoft Corporation. All Rights Reserved.
  7. */
  8. #pragma warning(disable:4206) /* empty source file */
  9. #ifdef DBG
  10. #pragma warning(disable:4001) /* single line comments */
  11. #pragma warning(disable:4001) /* single line comments */
  12. #pragma warning(disable:4050) /* different code attributes */
  13. #pragma warning(disable:4100) /* unreferenced formal parameter */
  14. #pragma warning(disable:4115) /* named type definition in parentheses */
  15. #pragma warning(disable:4115) /* named type definition in parentheses */
  16. #pragma warning(disable:4127) /* conditional expression is constant */
  17. #pragma warning(disable:4201) /* nameless struct/union */
  18. #pragma warning(disable:4206) /* translation unit is empty */
  19. #pragma warning(disable:4209) /* benign typedef redefinition */
  20. #pragma warning(disable:4214) /* bit field types other than int */
  21. #pragma warning(disable:4514) /* unreferenced inline function */
  22. #include <windows.h>
  23. #include <objerror.h>
  24. #include <stdio.h>
  25. #include <stdarg.h>
  26. #include <string.h>
  27. #include <time.h>
  28. #include <lmcons.h>
  29. #include <lmalert.h>
  30. #include <caldbg.h>
  31. // Global debugging indicators -----------------------------------------------
  32. //
  33. // Values for Assert flags
  34. #define ASSERTFLAG_UNINITIALIZED 0xffffffff
  35. #define ASSERTFLAG_DEFAULT 0x00000000
  36. #define ASSERTFLAG_IF_DEBUGGING 0x00000001
  37. #define ASSERTFLAG_POPUP 0x00000002
  38. #define ASSERTFLAG_KD_SAFE 0x00000004
  39. // Values for TraceError() settings (these are NOT flags!)
  40. #define TRACEERROR_UNINITIALIZED 0xffffffff
  41. #define TRACEERROR_NONE 0x00000000
  42. #define TRACEERROR_FAILED_SCODE 0x00000001
  43. #define TRACEERROR_NATURAL 0x00000002
  44. #define TRACEERROR_FAILING_EC 0x00000003
  45. #define TRACEERROR_ALWAYS 0x00000004
  46. // Trace buffer size and popup buffer size
  47. #define TRACE_BUF_SIZE 4096
  48. #define POP_BUF_SIZE 512
  49. static BOOL g_fTraceEnabled = -1;
  50. static BOOL g_fUseEventLog = -1;
  51. static BOOL g_fAssertLeaks = -1;
  52. static DWORD g_dwAssertFlags = ASSERTFLAG_UNINITIALIZED;
  53. static DWORD g_dwDefaultAssertFlags = ASSERTFLAG_DEFAULT;
  54. static DWORD g_dwErrorTraceLevel = TRACEERROR_UNINITIALIZED;
  55. // Debug strings -------------------------------------------------------------
  56. //
  57. const CHAR gc_szDbgEventLog[] = "EventLog";
  58. const CHAR gc_szDbgGeneral[] = "General";
  59. const CHAR gc_szDbgLogFile[] = "LogFile";
  60. const CHAR gc_szDbgTraces[] = "Traces";
  61. const CHAR gc_szDbgUseVirtual[] = "UseVirtual";
  62. const CHAR gc_szDbgDebugTrace[] = "DebugTrace";
  63. const CHAR gc_szDbgErrorTrace[] = "Error";
  64. const CHAR gc_szDbgPopupAsserts[] = "PopupAsserts";
  65. const CHAR gc_szDebugAssert[] = "Debug Assert";
  66. const CHAR gc_cchDebugAssert = sizeof(gc_szDebugAssert) - sizeof(CHAR);
  67. // Debugging routines --------------------------------------------------------
  68. //
  69. typedef BOOL (WINAPI *REPORTEVENT)(HANDLE, WORD, WORD, DWORD, PSID, WORD, DWORD, LPCTSTR *, LPVOID);
  70. typedef HANDLE (WINAPI *REGISTEREVENTSOURCEA)(LPCTSTR, LPCTSTR);
  71. typedef NET_API_STATUS (WINAPI *NAREFN)(TCHAR *, ADMIN_OTHER_INFO *, ULONG, TCHAR *);
  72. #define MAX_LINE 256
  73. // LogIt() -------------------------------------------------------------------
  74. //
  75. VOID
  76. LogIt (LPSTR plpcText, BOOL fUseAlert)
  77. {
  78. LPSTR llpcStr[2];
  79. static HANDLE hEventSource = NULL;
  80. static REPORTEVENT pfnReportEvent = NULL;
  81. static REGISTEREVENTSOURCEA pfnRegisterEventSourceA = NULL;
  82. if (pfnRegisterEventSourceA == NULL)
  83. {
  84. // This handle is not important as the lib will be
  85. // freed on exit (and it's debug only)
  86. //
  87. HINSTANCE lhLib;
  88. lhLib = LoadLibraryA("advapi32.dll");
  89. if (!lhLib)
  90. return;
  91. pfnRegisterEventSourceA = (REGISTEREVENTSOURCEA) GetProcAddress(lhLib, "RegisterEventSourceA");
  92. pfnReportEvent = (REPORTEVENT) GetProcAddress(lhLib, "ReportEventA");
  93. if (!pfnRegisterEventSourceA || !pfnReportEvent)
  94. return;
  95. }
  96. if (!hEventSource)
  97. hEventSource = pfnRegisterEventSourceA(NULL, "Caligula Debug");
  98. llpcStr[0] = "Caligula Debug Log";
  99. llpcStr[1] = plpcText;
  100. pfnReportEvent(hEventSource, /* handle of event source */
  101. EVENTLOG_ERROR_TYPE, /* event type */
  102. 0, /* event category */
  103. 0, /* event ID */
  104. NULL, /* current user's SID */
  105. 2, /* strings in lpszStrings */
  106. 0, /* no bytes of raw data */
  107. llpcStr, /* array of error strings */
  108. NULL); /* no raw data */
  109. // The code for raising an alert was taken from code in the
  110. // admin tree. It needs to be UNICODE
  111. //
  112. if (fUseAlert)
  113. {
  114. BYTE rgb[sizeof(ADMIN_OTHER_INFO) + (sizeof(WCHAR) * MAX_LINE)];
  115. ADMIN_OTHER_INFO * poi = (ADMIN_OTHER_INFO *) rgb;
  116. WCHAR * pch = (WCHAR *)(rgb + sizeof(ADMIN_OTHER_INFO)); /*lint -esym(550,nas) */
  117. NET_API_STATUS nas;
  118. WCHAR wsz[MAX_LINE * 3 + 1];
  119. INT cb, cch;
  120. static NAREFN fnNetAlertRaiseEx = NULL;
  121. // Load the alert library, and as before, unloading is taken
  122. // care of when the DLL goes away.
  123. //
  124. if (!fnNetAlertRaiseEx)
  125. {
  126. HINSTANCE lhLib;
  127. lhLib = LoadLibrary("NETAPI32.DLL");
  128. if (!lhLib)
  129. return;
  130. fnNetAlertRaiseEx = (NAREFN)GetProcAddress(lhLib, "NetAlertRaiseEx");
  131. if (!fnNetAlertRaiseEx)
  132. return;
  133. }
  134. poi->alrtad_errcode = (DWORD) -1;
  135. poi->alrtad_numstrings = 1;
  136. cb = (INT)(strlen(plpcText));
  137. if (MAX_LINE * 3 < cb)
  138. cb = MAX_LINE * 3;
  139. cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, plpcText, cb + 1, wsz, MAX_LINE * 3 + 1);
  140. if (cch)
  141. {
  142. cch--;
  143. if (MAX_LINE <= cch)
  144. cch = MAX_LINE - 1;
  145. memcpy(pch, wsz, cch * sizeof(WCHAR));
  146. pch[cch] = L'\0';
  147. nas = fnNetAlertRaiseEx ((TCHAR *)L"ADMIN",
  148. poi,
  149. sizeof(ADMIN_OTHER_INFO) + (cch + 1) * sizeof(WCHAR),
  150. (TCHAR *)L"Caligula Assert");
  151. }
  152. }
  153. }
  154. // DebugOutputNoCRLFFn() -----------------------------------------------------
  155. //
  156. void DebugOutputNoCRLFFn(char *psz)
  157. {
  158. if (g_fTraceEnabled == -1)
  159. {
  160. g_fTraceEnabled = GetPrivateProfileIntA (gc_szDbgGeneral,
  161. gc_szDbgDebugTrace,
  162. FALSE,
  163. gc_szDbgIni);
  164. g_fUseEventLog = GetPrivateProfileIntA (gc_szDbgGeneral,
  165. gc_szDbgEventLog,
  166. FALSE,
  167. gc_szDbgIni);
  168. }
  169. if (!g_fTraceEnabled)
  170. return;
  171. if (g_fUseEventLog)
  172. LogIt (psz, FALSE);
  173. OutputDebugStringA(psz);
  174. }
  175. // DebugOutputFn() -----------------------------------------------------------
  176. //
  177. void DebugOutputFn(char *psz)
  178. {
  179. static CHAR szCRLF[] = "\r\n";
  180. DebugOutputNoCRLFFn(psz);
  181. //Temporarily disabled until we yank out all the "\n"s from the calling code.
  182. //OutputDebugStringA(szCRLF);
  183. }
  184. // DebugTrapFn() -------------------------------------------------------------
  185. //
  186. typedef struct _MBCONTEXT
  187. {
  188. char * sz1;
  189. char * sz2;
  190. UINT rgf;
  191. int iResult;
  192. } MBCONTEXT;
  193. DWORD WINAPI
  194. MessageBoxFnThreadMain(MBCONTEXT *pmbc)
  195. {
  196. if (g_fUseEventLog)
  197. {
  198. LogIt (pmbc->sz1, TRUE);
  199. pmbc->iResult = IDIGNORE;
  200. }
  201. else
  202. {
  203. pmbc->iResult = MessageBoxA (NULL,
  204. pmbc->sz1,
  205. pmbc->sz2,
  206. pmbc->rgf | MB_SETFOREGROUND);
  207. }
  208. return (0);
  209. }
  210. INT
  211. MessageBoxFn(char *sz1, char *sz2, UINT rgf)
  212. {
  213. HANDLE hThread;
  214. DWORD dwThreadId;
  215. MBCONTEXT mbc;
  216. // To preserve last error over tracing calls
  217. DWORD dwErr = GetLastError();
  218. mbc.sz1 = sz1;
  219. mbc.sz2 = sz2;
  220. mbc.rgf = rgf;
  221. mbc.iResult = IDRETRY;
  222. hThread = CreateThread (NULL,
  223. 0,
  224. (PTHREAD_START_ROUTINE)MessageBoxFnThreadMain,
  225. &mbc,
  226. 0,
  227. &dwThreadId);
  228. if (hThread != NULL)
  229. {
  230. WaitForSingleObject (hThread, INFINITE);
  231. CloseHandle (hThread);
  232. }
  233. SetLastError(dwErr);
  234. return mbc.iResult;
  235. }
  236. // ------------------------------------------------------------------------
  237. // DebugTrapFn
  238. //
  239. // Main Assert/DebugTrap handling routine.
  240. //
  241. // Meanings of the g_dwAssertFlags:
  242. //
  243. //#define ASSERTFLAG_IF_DEBUGGING 0x00000001
  244. //#define ASSERTFLAG_POPUP 0x00000002
  245. //#define ASSERTFLAG_KD_SAFE 0x00000004
  246. //
  247. // 0 -- (default if no inifile or unrecognized value in inifile)
  248. // Default behavior -- DebugBreak() and then dump our strings.
  249. // NOTE: HTTPEXT needs this to remain their default because
  250. // of the way that IIS runs their stress testing. DO NOT CHANGE THIS!
  251. // ASSERTFLAG_IF_DEBUGGING
  252. // -- use MessageBox asserts only if no debugger attached.
  253. // Why not use MessageBox everywhere?
  254. // Because MessageBox lets all the other threads keep going,
  255. // so we lose some amount of the state of the assert.
  256. // If this flag is NOT set, or a debugger is NOT connected,
  257. // we obey the other flags.
  258. // ASSERTFLAG_POPUP
  259. // -- use MessageBox asserts. Our MessageBox has three buttons:
  260. // Abort,Retry,Ignore do "*(0)=1",DebugBreak,go
  261. // ASSERTFLAG_KD_SAFE
  262. // -- use HardCrash instead of DebugBreak
  263. // Use hard-av if debugger is attached.
  264. // (Option for devs with CDB and no KD attached, or for anyone
  265. // who wants to do ALL their debugging in KD! ;-)
  266. // Why not just DebugBreak() if a debugger is attached?
  267. // Because DebugBreak() will catch in the kernel debugger first --
  268. // so if I have a both kd and cdb hooked up, DebugBreak() will
  269. // hit in the kd, even though this is user-mode code.
  270. //
  271. // Alternate code for IsDebuggerPresent()
  272. // peb = NtCurrentPeb();
  273. // if (peb->BeingDebugged) ...
  274. //
  275. INT EXPORTDBG __cdecl
  276. DebugTrapFn (int fFatal, char *pszFile, int iLine, char *pszFormat, ...)
  277. {
  278. char sz[POP_BUF_SIZE];
  279. int cb = POP_BUF_SIZE;
  280. const char * pszT;
  281. int cbT;
  282. int cbWritten;
  283. va_list vl;
  284. int id;
  285. static BOOL s_fBuiltDebugStrings = FALSE;
  286. static char s_rgchMessageBoxTitle[MAX_PATH];
  287. // To preserve last error over tracing calls
  288. DWORD dwErr = GetLastError();
  289. if (ASSERTFLAG_UNINITIALIZED == g_dwAssertFlags)
  290. {
  291. // Check the ini file.
  292. // Pass in our default flags -- if there's no inifile, we'll
  293. // get back our default.
  294. //
  295. g_dwAssertFlags = GetPrivateProfileIntA (gc_szDbgGeneral,
  296. gc_szDbgPopupAsserts,
  297. g_dwDefaultAssertFlags,
  298. gc_szDbgIni);
  299. }
  300. // Check our static flag to see if we've already built the
  301. // title string for our Asserts/DebugTraces.
  302. //
  303. if (!s_fBuiltDebugStrings)
  304. {
  305. char * pch;
  306. int cbDebugStrings = MAX_PATH;
  307. if (gc_cchDbgIni < cbDebugStrings)
  308. {
  309. // Copy including termination
  310. //
  311. memcpy(s_rgchMessageBoxTitle, gc_szDbgIni, gc_cchDbgIni + 1);
  312. cbDebugStrings -= gc_cchDbgIni;
  313. }
  314. else
  315. {
  316. // Copy as much as we can and terminate
  317. //
  318. memcpy(s_rgchMessageBoxTitle, gc_szDbgIni, cbDebugStrings - 1);
  319. s_rgchMessageBoxTitle[MAX_PATH - 1] = '\0';
  320. cbDebugStrings = 1;
  321. }
  322. pch = strchr (s_rgchMessageBoxTitle, '.');
  323. if (pch)
  324. {
  325. cbDebugStrings = MAX_PATH - (INT)(pch - s_rgchMessageBoxTitle) - 1;
  326. *pch = ' ';
  327. }
  328. if (gc_cchDebugAssert < cbDebugStrings)
  329. {
  330. // Copy including termination
  331. //
  332. memcpy(s_rgchMessageBoxTitle + MAX_PATH - cbDebugStrings, gc_szDebugAssert, gc_cchDebugAssert + 1);
  333. }
  334. else
  335. {
  336. memcpy(s_rgchMessageBoxTitle + MAX_PATH - cbDebugStrings, gc_szDebugAssert, cbDebugStrings);
  337. s_rgchMessageBoxTitle[MAX_PATH - 1] = '\0';
  338. }
  339. s_fBuiltDebugStrings = TRUE;
  340. }
  341. // Build the assert strings and dump the first line
  342. //
  343. pszT = "++++ ";
  344. cbT = sizeof("++++ ") - sizeof(char);
  345. if (cbT < cb)
  346. {
  347. memcpy(sz, pszT, cbT + 1);
  348. cb -= cbT;
  349. cbT = (int)(strlen(s_rgchMessageBoxTitle));
  350. if (cbT < cb)
  351. {
  352. memcpy(sz + POP_BUF_SIZE - cb, s_rgchMessageBoxTitle, cbT + 1);
  353. cb -= cbT;
  354. pszT = " (";
  355. cbT = sizeof(" (") - sizeof(char);
  356. if (cbT < cb)
  357. {
  358. char szDateTime[POP_BUF_SIZE];
  359. memcpy(sz + POP_BUF_SIZE - cb, pszT, cbT + 1);
  360. cb -= cbT;
  361. // POP_BUF_SIZE should always be sufficient for the date
  362. //
  363. _strdate (szDateTime);
  364. cbT = (int)(strlen(szDateTime));
  365. if (cbT < cb)
  366. {
  367. memcpy(sz + POP_BUF_SIZE - cb, szDateTime, cbT + 1);
  368. cb -= cbT;
  369. pszT = " ";
  370. cbT = sizeof(" ") - sizeof(char);
  371. if (cbT < cb)
  372. {
  373. memcpy(sz + POP_BUF_SIZE - cb, pszT, cbT + 1);
  374. cb -= cbT;
  375. // POP_BUF_SIZE should always be sufficient for the date
  376. //
  377. _strtime (szDateTime);
  378. cbT = (int)(strlen(szDateTime));
  379. if (cbT < cb)
  380. {
  381. memcpy(sz + POP_BUF_SIZE - cb, szDateTime, cbT + 1);
  382. cb -= cbT;
  383. pszT = ")\n";
  384. cbT = sizeof(")\n") - sizeof(char);
  385. if (cbT < cb)
  386. {
  387. memcpy(sz + POP_BUF_SIZE - cb, pszT, cbT + 1);
  388. }
  389. }
  390. }
  391. }
  392. }
  393. }
  394. }
  395. DebugOutputFn(sz);
  396. // Reset the buffer and fill it once more
  397. //
  398. cb = POP_BUF_SIZE;
  399. va_start(vl, pszFormat);
  400. cbWritten = _vsnprintf(sz, POP_BUF_SIZE, pszFormat, vl);
  401. va_end(vl);
  402. if ((-1 == cbWritten) || (POP_BUF_SIZE == cbWritten))
  403. {
  404. sz[POP_BUF_SIZE - 1] = '\0';
  405. }
  406. else
  407. {
  408. cb -= cbWritten;
  409. cbWritten = _snprintf(sz + POP_BUF_SIZE - cb, cb, "\n[File %s, Line %d]\n\n", pszFile, iLine);
  410. if ((-1 == cbWritten) || (cb == cbWritten))
  411. {
  412. sz[POP_BUF_SIZE - 1] = '\0';
  413. }
  414. }
  415. // Check our assert flags
  416. //
  417. // See if MessageBoxes are desired....
  418. //
  419. // If the "msg-box-if-no-debugger" flag is set,
  420. // and there is no debugger -- give 'em message boxes!
  421. // If they specifically requested message boxes, give 'em message boxes.
  422. //
  423. if (((ASSERTFLAG_IF_DEBUGGING & g_dwAssertFlags) && !IsDebuggerPresent()) ||
  424. (ASSERTFLAG_POPUP & g_dwAssertFlags))
  425. {
  426. // Use MessageBox asserts
  427. //
  428. UINT uiFlags = MB_ABORTRETRYIGNORE;
  429. if (fFatal)
  430. uiFlags |= MB_DEFBUTTON1;
  431. else
  432. uiFlags |= MB_DEFBUTTON3;
  433. DebugOutputFn(sz);
  434. // Always act as if we are a service (why not?)
  435. //
  436. uiFlags |= MB_ICONSTOP | MB_TASKMODAL | MB_SERVICE_NOTIFICATION;
  437. id = MessageBoxFn (sz, s_rgchMessageBoxTitle, uiFlags);
  438. if (id == IDABORT)
  439. {
  440. *((LPBYTE)NULL) = 0;
  441. }
  442. else if (id == IDRETRY)
  443. DebugBreak();
  444. }
  445. else if (ASSERTFLAG_KD_SAFE & g_dwAssertFlags)
  446. {
  447. // Hard-av and then dump our string.
  448. //
  449. *((LPBYTE)NULL) = 0;
  450. DebugOutputFn(sz);
  451. }
  452. else
  453. {
  454. // Do the default behavior:
  455. // DebugBreak() and then dump our string.
  456. //
  457. DebugBreak();
  458. DebugOutputFn(sz);
  459. }
  460. SetLastError(dwErr);
  461. return 0;
  462. }
  463. // DebugTraceFn() ------------------------------------------------------------
  464. //
  465. INT EXPORTDBG __cdecl
  466. DebugTraceFn(char *pszFormat, ...)
  467. {
  468. char sz[TRACE_BUF_SIZE];
  469. int cb;
  470. va_list vl;
  471. // To preserve last error over tracing calls
  472. DWORD dwErr = GetLastError();
  473. if (*pszFormat == '~')
  474. {
  475. pszFormat += 1;
  476. }
  477. va_start(vl, pszFormat);
  478. cb = _vsnprintf(sz, TRACE_BUF_SIZE, pszFormat, vl);
  479. va_end(vl);
  480. if ((-1 == cb) || (TRACE_BUF_SIZE == cb))
  481. {
  482. sz[TRACE_BUF_SIZE - 1] = '\0';
  483. }
  484. DebugOutputFn(sz);
  485. SetLastError(dwErr);
  486. return(0);
  487. }
  488. INT EXPORTDBG __cdecl
  489. DebugTraceNoCRLFFn(char *pszFormat, ...)
  490. {
  491. char sz[TRACE_BUF_SIZE];
  492. int cb;
  493. va_list vl;
  494. // To preserve last error over tracing calls
  495. DWORD dwErr = GetLastError();
  496. va_start(vl, pszFormat);
  497. cb = _vsnprintf(sz, TRACE_BUF_SIZE, pszFormat, vl);
  498. va_end(vl);
  499. if ((-1 == cb) || (TRACE_BUF_SIZE == cb))
  500. {
  501. sz[TRACE_BUF_SIZE - 1] = '\0';
  502. }
  503. DebugOutputNoCRLFFn(sz);
  504. SetLastError(dwErr);
  505. return(0);
  506. }
  507. INT EXPORTDBG __cdecl
  508. DebugTraceCRLFFn(char *pszFormat, ...)
  509. {
  510. char sz[TRACE_BUF_SIZE];
  511. int cb;
  512. va_list vl;
  513. // To preserve last error over tracing calls
  514. DWORD dwErr = GetLastError();
  515. va_start(vl, pszFormat);
  516. cb = _vsnprintf(sz, TRACE_BUF_SIZE, pszFormat, vl);
  517. va_end(vl);
  518. if ((-1 == cb) || (TRACE_BUF_SIZE == cb))
  519. {
  520. sz[TRACE_BUF_SIZE - 1] = '\0';
  521. }
  522. DebugOutputNoCRLFFn(sz);
  523. DebugOutputNoCRLFFn("\r\n");
  524. SetLastError(dwErr);
  525. return(0);
  526. }
  527. // TraceErrorFn() ------------------------------------------------------------
  528. //
  529. INT EXPORTDBG __cdecl
  530. TraceErrorFn (DWORD error, char *pszFunction,
  531. char *pszFile, int iLine,
  532. BOOL fEcTypeError) // defaults to FALSE
  533. {
  534. BOOL fTraceIt = FALSE;
  535. if (TRACEERROR_UNINITIALIZED == g_dwErrorTraceLevel)
  536. {
  537. g_dwErrorTraceLevel = GetPrivateProfileIntA (gc_szDbgGeneral,
  538. gc_szDbgErrorTrace,
  539. FALSE,
  540. gc_szDbgIni);
  541. }
  542. if (TRACEERROR_NONE == g_dwErrorTraceLevel)
  543. return 0;
  544. // Logic for trace error levels:
  545. // Error tracing, like all our tracing, is OFF by default.
  546. // TRACEERROR_NONE -- don't trace errors
  547. // TRACEERROR_FAILED_SCODE -- trace only if FAILED(error)
  548. // TRACEERROR_NATURAL -- if fEcTypeError, use if (error)
  549. // -- if !fEcTypeError, use if (FAILED(error))
  550. // TRACEERROR_FAILING_EC -- trace only if (error)
  551. // TRACEERROR_ALWAYS -- always trace
  552. //
  553. switch (g_dwErrorTraceLevel)
  554. {
  555. case TRACEERROR_FAILED_SCODE:
  556. if (FAILED(error))
  557. fTraceIt = TRUE;
  558. break;
  559. case TRACEERROR_FAILING_EC:
  560. if (0 != error)
  561. fTraceIt = TRUE;
  562. break;
  563. case TRACEERROR_ALWAYS:
  564. fTraceIt = TRUE;
  565. break;
  566. case TRACEERROR_NATURAL:
  567. if (fEcTypeError)
  568. fTraceIt = (0 != error);
  569. else
  570. fTraceIt = (FAILED(error));
  571. break;
  572. default:
  573. break;
  574. }
  575. if (fTraceIt)
  576. {
  577. char pszFormat[] = "%hs Error Trace: 0x%08x from function %hs (%hs line %d)\r\n";
  578. DebugTraceNoCRLFFn (pszFormat, gc_szDbgIni,
  579. error, pszFunction, pszFile, iLine);
  580. }
  581. return 0;
  582. }
  583. #else
  584. #if defined(_AMD64_)
  585. //
  586. // ****** temporary ******
  587. //
  588. int
  589. DebugTrapFn (
  590. int fFatal,
  591. char *pszFile,
  592. int iLine,
  593. char *pszFormat,
  594. ...
  595. )
  596. {
  597. return 0;
  598. }
  599. int
  600. DebugTraceFn (
  601. char *pszFormat,
  602. ...
  603. )
  604. {
  605. return 0;
  606. }
  607. int
  608. DebugTraceCRLFFn (
  609. char *pszFormat,
  610. ...
  611. )
  612. {
  613. return 0;
  614. }
  615. int
  616. DebugTraceNoCRLFFn (
  617. char *pszFormat,
  618. ...
  619. )
  620. {
  621. return 0;
  622. }
  623. #endif
  624. #endif // DBG