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.

1591 lines
50 KiB

  1. #include "stdinc.h"
  2. #include <limits.h>
  3. #include "fusiontrace.h"
  4. #include <stdio.h>
  5. #include "fusionheap.h"
  6. #include "imagehlp.h"
  7. #include "debmacro.h"
  8. #include "util.h"
  9. //
  10. // ISSUE: jonwis 3/12/2002 - We use an awful lot of stack in some places. Whenever we form up
  11. // strings to pass to OutputDebugStringA, we tend to use 256/512-char buffers. However,
  12. // OutputDebugStringA -also- contains a 512-byte buffer in its __except handler when
  13. // no debugger is attached. So, we'll suck up stack like crazy here on the error path,
  14. // which if we're under stress could cause us to fail printing diagnostic information
  15. //
  16. // ISSUE: jonwis 3/12/2002 - Seems like there's three implementations for each of the 'trace failure'
  17. // functions. The one that does the work (takes a FRAME_INFO), the one that takes the
  18. // information in a parameter list and converts into a FRAME_INFO, and the one that takes
  19. // some simple parameter and uses the current FRAME_INFO plus that parameter for tracking.
  20. // What if we collapsed a few of these, or moved them into a header file for inlining
  21. // purposes?
  22. //
  23. // ISSUE: jonwis 3/12/2002 - Seems like there's N copies of code like FusionpTraceWin32FailureNoFormatting,
  24. // each of which are very slightly different (a different param here or there, calling
  25. // a different function, etc.) I wonder if they could be merged into a single function with
  26. // more verbose parameters...
  27. //
  28. #if !defined(FUSION_BREAK_ON_BAD_PARAMETERS)
  29. #define FUSION_BREAK_ON_BAD_PARAMETERS false
  30. #endif // !defined(FUSION_BREAK_ON_BAD_PARAMETERS);
  31. bool g_FusionBreakOnBadParameters = FUSION_BREAK_ON_BAD_PARAMETERS;
  32. //
  33. // ISSUE: jonwis 3/12/2002 - This file handle never gets CreateFile'd or CloseHandle'd anywhere
  34. // in current source. There's a lot of code that relies on this handle being valid or
  35. // invalid to run. Should we maybe get rid of this?
  36. //
  37. static HANDLE s_hFile; // trace file handle
  38. #if DBG
  39. #define FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hr) /* nothing */
  40. #else
  41. bool FusionpSuppressErrorReportInOsSetup(HRESULT hr)
  42. {
  43. //
  44. // Some of these are unfortunately expected (early) in guimode setup, actually
  45. // concurrent with early guimode setup, but not otherwise.
  46. //
  47. if ( hr != HRESULT_FROM_WIN32(ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED)
  48. && hr != HRESULT_FROM_WIN32(ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED)
  49. )
  50. return false;
  51. BOOL fAreWeInOSSetupMode = FALSE;
  52. //
  53. // If we can't determine this, then let the first error through.
  54. //
  55. if (!::FusionpAreWeInOSSetupMode(&fAreWeInOSSetupMode))
  56. return false;
  57. if (!fAreWeInOSSetupMode)
  58. return false;
  59. return true;
  60. }
  61. #define FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hr) if (FusionpSuppressErrorReportInOsSetup(hr)) return;
  62. #endif
  63. // ISSUE-03/26/2002-xiaoyuw
  64. // FusionpGetActiveFrameInfo could call FusionpPopulateFrameInfo after it gets value of ptaf,
  65. // instead of repeat the same code.
  66. bool
  67. __fastcall
  68. FusionpGetActiveFrameInfo(
  69. FRAME_INFO &rFrameInfo
  70. )
  71. {
  72. bool fFoundAnyData = false;
  73. rFrameInfo.pszFile = "";
  74. rFrameInfo.pszFunction = "";
  75. rFrameInfo.nLine = 0;
  76. const PTEB_ACTIVE_FRAME ptaf =
  77. #if FUSION_WIN
  78. ::RtlGetFrame();
  79. #else
  80. NULL;
  81. #endif
  82. const PTEB_ACTIVE_FRAME_EX ptafe =
  83. ((ptaf != NULL) && (ptaf->Flags & TEB_ACTIVE_FRAME_FLAG_EXTENDED)) ?
  84. reinterpret_cast<PTEB_ACTIVE_FRAME_EX>(ptaf) : NULL;
  85. if (ptaf != NULL)
  86. {
  87. if (ptaf->Context != NULL)
  88. {
  89. if (ptaf->Context->FrameName != NULL)
  90. {
  91. rFrameInfo.pszFunction = ptaf->Context->FrameName;
  92. fFoundAnyData = true;
  93. }
  94. if (ptaf->Context->Flags & TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED)
  95. {
  96. const PCTEB_ACTIVE_FRAME_CONTEXT_EX ptafce =
  97. reinterpret_cast<PCTEB_ACTIVE_FRAME_CONTEXT_EX>(ptaf->Context);
  98. if (ptafce->SourceLocation != NULL)
  99. {
  100. rFrameInfo.pszFile = ptafce->SourceLocation;
  101. fFoundAnyData = true;
  102. }
  103. }
  104. }
  105. }
  106. // If this is one of our frames, we can even downcast and get the line number...
  107. if ((ptafe != NULL) && (ptafe->ExtensionIdentifier == (PVOID) (' sxS')))
  108. {
  109. const CFrame *pFrame = static_cast<CFrame *>(ptafe);
  110. if (pFrame->m_nLine != 0)
  111. {
  112. rFrameInfo.nLine = pFrame->m_nLine;
  113. fFoundAnyData = true;
  114. }
  115. }
  116. return fFoundAnyData;
  117. }
  118. bool
  119. __fastcall
  120. FusionpPopulateFrameInfo(
  121. FRAME_INFO &rFrameInfo,
  122. PCTEB_ACTIVE_FRAME ptaf
  123. )
  124. {
  125. bool fFoundAnyData = false;
  126. rFrameInfo.pszFile = "";
  127. rFrameInfo.pszFunction = "";
  128. rFrameInfo.nLine = 0;
  129. const PCTEB_ACTIVE_FRAME_EX ptafe =
  130. ((ptaf != NULL) && (ptaf->Flags & TEB_ACTIVE_FRAME_FLAG_EXTENDED)) ?
  131. reinterpret_cast<PCTEB_ACTIVE_FRAME_EX>(ptaf) : NULL;
  132. if (ptaf != NULL)
  133. {
  134. if (ptaf->Context != NULL)
  135. {
  136. if (ptaf->Context->FrameName != NULL)
  137. {
  138. rFrameInfo.pszFunction = ptaf->Context->FrameName;
  139. fFoundAnyData = true;
  140. }
  141. if (ptaf->Context->Flags & TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED)
  142. {
  143. const PCTEB_ACTIVE_FRAME_CONTEXT_EX ptafce =
  144. reinterpret_cast<PCTEB_ACTIVE_FRAME_CONTEXT_EX>(ptaf->Context);
  145. if (ptafce->SourceLocation != NULL)
  146. {
  147. rFrameInfo.pszFile = ptafce->SourceLocation;
  148. fFoundAnyData = true;
  149. }
  150. }
  151. }
  152. }
  153. // If this is one of our frames, we can even downcast and get the line number...
  154. if ((ptafe != NULL) && (ptafe->ExtensionIdentifier == ((PVOID) (' sxS'))))
  155. {
  156. const CFrame *pFrame = static_cast<const CFrame *>(ptafe);
  157. if (pFrame->m_nLine != 0)
  158. {
  159. rFrameInfo.nLine = pFrame->m_nLine;
  160. fFoundAnyData = true;
  161. }
  162. }
  163. return fFoundAnyData;
  164. }
  165. bool
  166. FusionpPopulateFrameInfo(
  167. FRAME_INFO &rFrameInfo,
  168. PCSTR pszFile,
  169. PCSTR pszFunction,
  170. INT nLine
  171. )
  172. {
  173. bool fFoundAnyData = false;
  174. if (pszFile != NULL)
  175. {
  176. rFrameInfo.pszFile = pszFile;
  177. fFoundAnyData = true;
  178. }
  179. else
  180. rFrameInfo.pszFile = NULL;
  181. if (nLine != 0)
  182. fFoundAnyData = true;
  183. rFrameInfo.nLine = nLine;
  184. if (pszFunction != NULL)
  185. {
  186. rFrameInfo.pszFunction = pszFunction;
  187. fFoundAnyData = true;
  188. }
  189. else
  190. rFrameInfo.pszFunction = NULL;
  191. return fFoundAnyData;
  192. }
  193. int STDAPIVCALLTYPE _DebugTraceA(LPCSTR pszMsg, ...)
  194. {
  195. int iResult;
  196. va_list ap;
  197. va_start(ap, pszMsg);
  198. iResult = _DebugTraceExVaA(0, TRACETYPE_INFO, NOERROR, pszMsg, ap);
  199. va_end(ap);
  200. return iResult;
  201. }
  202. int STDAPICALLTYPE
  203. _DebugTraceVaA(LPCSTR pszMsg, va_list ap)
  204. {
  205. return _DebugTraceExVaA(0, TRACETYPE_INFO, NOERROR, pszMsg, ap);
  206. }
  207. int STDAPIVCALLTYPE
  208. _DebugTraceExA(DWORD dwFlags, TRACETYPE tt, HRESULT hr, LPCSTR pszMsg, ...)
  209. {
  210. int iResult;
  211. va_list ap;
  212. va_start(ap, pszMsg);
  213. iResult = _DebugTraceExVaA(dwFlags, tt, hr, pszMsg, ap);
  214. va_end(ap);
  215. return iResult;
  216. }
  217. int STDAPICALLTYPE
  218. _DebugTraceExVaA(DWORD dwFlags, TRACETYPE tt, HRESULT hr, LPCSTR pszMsg, va_list ap)
  219. {
  220. CSxsPreserveLastError ple;
  221. CHAR szBuffer[512];
  222. CHAR szMsgBuffer[512];
  223. static const char szFormat_Info_NoFunc[] = "%s(%d): Message: \"%s\"\n";
  224. static const char szFormat_Info_Func[] = "%s(%d): Function %s. Message: \"%s\"\n";
  225. static const char szFormat_CallEntry[] = "%s(%d): Entered %s\n";
  226. static const char szFormat_CallExitVoid[] = "%s(%d): Exited %s\n";
  227. static const char szFormat_CallExitHRESULT[] = "%s(%d): Exited %s with HRESULT 0x%08lx\n";
  228. FRAME_INFO FrameInfo;
  229. szMsgBuffer[0] = '\0';
  230. if (pszMsg != NULL)
  231. {
  232. ::_vsnprintf(szMsgBuffer, NUMBER_OF(szMsgBuffer), pszMsg, ap);
  233. szMsgBuffer[NUMBER_OF(szMsgBuffer) - 1] = '\0';
  234. }
  235. ::FusionpGetActiveFrameInfo(FrameInfo);
  236. switch (tt)
  237. {
  238. default:
  239. case TRACETYPE_INFO:
  240. //ISSUE-03/26/2002-xiaoyuw
  241. // FrameInfo.pszFunction is set to be "\0", never NULL by FusionpGetActiveFrameInfo
  242. if (FrameInfo.pszFunction != NULL)
  243. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), szFormat_Info_Func, FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction, szMsgBuffer);
  244. else
  245. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), szFormat_Info_NoFunc, FrameInfo.pszFile, FrameInfo.nLine, szMsgBuffer);
  246. break;
  247. case TRACETYPE_CALL_START:
  248. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), szFormat_CallEntry, FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction);
  249. break;
  250. case TRACETYPE_CALL_EXIT_NOHRESULT:
  251. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), szFormat_CallExitVoid, FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction);
  252. break;
  253. case TRACETYPE_CALL_EXIT_HRESULT:
  254. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), szFormat_CallExitHRESULT, FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction, hr);
  255. break;
  256. }
  257. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  258. ::OutputDebugStringA(szBuffer);
  259. ple.Restore();
  260. return 0;
  261. }
  262. VOID
  263. FusionpTraceAllocFailure(
  264. PCSTR pszFile,
  265. int nLine,
  266. PCSTR pszFunction,
  267. PCSTR pszExpression
  268. )
  269. {
  270. CSxsPreserveLastError ple;
  271. CHAR szBuffer[512];
  272. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), "%s(%d): Memory allocation failed in function %s\n Expression: %s\n", pszFile, nLine, pszFunction, pszExpression);
  273. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  274. ::OutputDebugStringA(szBuffer);
  275. ple.Restore();
  276. }
  277. VOID
  278. FusionpTraceAllocFailure(
  279. PCSTR pszExpression
  280. )
  281. {
  282. FRAME_INFO FrameInfo;
  283. ::FusionpGetActiveFrameInfo(FrameInfo);
  284. ::FusionpTraceAllocFailure(FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction, pszExpression);
  285. }
  286. VOID
  287. FusionpTraceNull(
  288. PCSTR pszFile,
  289. int nLine,
  290. PCSTR pszFunction,
  291. PCSTR pszExpression
  292. )
  293. {
  294. CSxsPreserveLastError ple;
  295. CHAR szBuffer[512];
  296. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), "%s(%d): Expression evaluated to NULL in function %s\n Expression: %s\n", pszFile, nLine, pszFunction, pszExpression);
  297. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  298. ::OutputDebugStringA(szBuffer);
  299. ple.Restore();
  300. }
  301. VOID
  302. FusionpTraceNull(
  303. PCSTR pszExpression
  304. )
  305. {
  306. FRAME_INFO FrameInfo;
  307. ::FusionpGetActiveFrameInfo(FrameInfo);
  308. ::FusionpTraceNull(FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction, pszExpression);
  309. }
  310. VOID
  311. FusionpTraceZero(
  312. PCSTR pszFile,
  313. int nLine,
  314. PCSTR pszFunction,
  315. PCSTR pszExpression
  316. )
  317. {
  318. CSxsPreserveLastError ple;
  319. CHAR szBuffer[512];
  320. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), "%s(%d): Expression evaluated to zero in function %s\n Expression: %s\n", pszFile, nLine, pszFunction, pszExpression);
  321. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  322. ::OutputDebugStringA(szBuffer);
  323. ple.Restore();
  324. }
  325. VOID
  326. FusionpTraceZero(
  327. PCSTR pszExpression
  328. )
  329. {
  330. FRAME_INFO FrameInfo;
  331. ::FusionpGetActiveFrameInfo(FrameInfo);
  332. ::FusionpTraceZero(FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction, pszExpression);
  333. }
  334. VOID
  335. FusionpTraceParameterCheck(
  336. const FRAME_INFO &rFrameInfo,
  337. PCSTR pszExpression
  338. )
  339. {
  340. CSxsPreserveLastError ple;
  341. CHAR szBuffer[512];
  342. ::_snprintf(
  343. szBuffer,
  344. NUMBER_OF(szBuffer),
  345. "%s(%d): Input parameter validation failed in function %s\n Validation expression: %s\n",
  346. rFrameInfo.pszFile,
  347. rFrameInfo.nLine,
  348. rFrameInfo.pszFunction,
  349. pszExpression);
  350. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  351. ::OutputDebugStringA(szBuffer);
  352. if (g_FusionBreakOnBadParameters)
  353. FUSION_DEBUG_BREAK_IN_FREE_BUILD();
  354. ple.Restore();
  355. }
  356. VOID
  357. FusionpTraceParameterCheck(
  358. PCSTR pszFile,
  359. PCSTR pszFunction,
  360. int nLine,
  361. PCSTR pszExpression
  362. )
  363. {
  364. FRAME_INFO FrameInfo;
  365. ::FusionpPopulateFrameInfo(FrameInfo, pszFile, pszFunction, nLine);
  366. ::FusionpTraceParameterCheck(FrameInfo, pszExpression);
  367. }
  368. VOID
  369. FusionpTraceParameterCheck(
  370. PCSTR pszExpression
  371. )
  372. {
  373. FRAME_INFO FrameInfo;
  374. ::FusionpGetActiveFrameInfo(FrameInfo);
  375. ::FusionpTraceParameterCheck(FrameInfo, pszExpression);
  376. }
  377. VOID
  378. FusionpTraceInvalidFlags(
  379. const FRAME_INFO &rFrameInfo,
  380. DWORD dwFlagsPassed,
  381. DWORD dwFlagsExpected
  382. )
  383. {
  384. CSxsPreserveLastError ple;
  385. //
  386. // ISSUE: jonwis 3/12/2002 - Places like this. Why not throttle this back to print only the first
  387. // N characters of the function name and the N last characters of the file name? Then
  388. // we'd at least have a bounded number of characters to print ...
  389. //
  390. CHAR szBuffer[512];
  391. ::_snprintf(
  392. szBuffer,
  393. NUMBER_OF(szBuffer),
  394. "%s(%d): Function %s received invalid flags\n"
  395. " Flags passed: 0x%08lx\n"
  396. " Flags allowed: 0x%08lx\n",
  397. rFrameInfo.pszFile, rFrameInfo.nLine, rFrameInfo.pszFunction,
  398. dwFlagsPassed,
  399. dwFlagsExpected);
  400. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  401. ::OutputDebugStringA(szBuffer);
  402. ple.Restore();
  403. }
  404. VOID
  405. FusionpTraceInvalidFlags(
  406. PCSTR pszFile,
  407. PCSTR pszFunction,
  408. INT nLine,
  409. DWORD dwFlagsPassed,
  410. DWORD dwFlagsExpected
  411. )
  412. {
  413. FRAME_INFO FrameInfo;
  414. ::FusionpPopulateFrameInfo(FrameInfo, pszFile, pszFunction, nLine);
  415. ::FusionpTraceInvalidFlags(FrameInfo, dwFlagsPassed, dwFlagsExpected);
  416. }
  417. VOID
  418. FusionpTraceInvalidFlags(
  419. DWORD dwFlagsPassed,
  420. DWORD dwFlagsExpected
  421. )
  422. {
  423. FRAME_INFO FrameInfo;
  424. ::FusionpGetActiveFrameInfo(FrameInfo);
  425. ::FusionpTraceInvalidFlags(FrameInfo, dwFlagsPassed, dwFlagsExpected);
  426. }
  427. void
  428. FusionpGetProcessImageFileName(
  429. PUNICODE_STRING ProcessImageFileName
  430. )
  431. {
  432. #if !defined(FUSION_WIN)
  433. ProcessImageFileName->Length = 0;
  434. #else
  435. USHORT PrefixLength;
  436. *ProcessImageFileName = NtCurrentPeb()->ProcessParameters->ImagePathName;
  437. if (NT_SUCCESS(RtlFindCharInUnicodeString(
  438. RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
  439. ProcessImageFileName,
  440. &RtlDosPathSeperatorsString,
  441. &PrefixLength)))
  442. {
  443. PrefixLength += sizeof(ProcessImageFileName->Buffer[0]);
  444. ProcessImageFileName->Length = static_cast<USHORT>(ProcessImageFileName->Length - PrefixLength);
  445. ProcessImageFileName->Buffer += PrefixLength / sizeof(ProcessImageFileName->Buffer[0]);
  446. }
  447. #endif
  448. }
  449. class CFusionProcessImageFileName : public UNICODE_STRING
  450. {
  451. public:
  452. CFusionProcessImageFileName()
  453. {
  454. ::FusionpGetProcessImageFileName(this);
  455. }
  456. };
  457. //
  458. // ISSUE: jonwis 3/12/2002 - Any good reason why we copy the CALL_SITE_INFO input struct into a
  459. // local? Also, the call to snprintf to do string copying/concatenation seems very
  460. // overpowering. Any reason that an strncpy won't work? I thought snprintf did a
  461. // lot more work than necessary, up to and including having its own large stack
  462. // buffer(s)...
  463. //
  464. void __fastcall FusionpTraceWin32LastErrorFailureExV(const CALL_SITE_INFO &rCallSiteInfo, PCSTR Format, va_list Args)
  465. {
  466. CSxsPreserveLastError ple;
  467. CHAR Buffer[256];
  468. CALL_SITE_INFO CallSiteInfo = rCallSiteInfo;
  469. CallSiteInfo.pszApiName = Buffer;
  470. SIZE_T i = 1;
  471. Buffer[0] = '\0';
  472. if (rCallSiteInfo.pszApiName != NULL && rCallSiteInfo.pszApiName[0] != '\0')
  473. {
  474. ::_snprintf(Buffer, NUMBER_OF(Buffer) - i, "%s", rCallSiteInfo.pszApiName);
  475. Buffer[NUMBER_OF(Buffer) - 1] = '\0';
  476. i = 1 + ::StringLength(Buffer);
  477. }
  478. if (i < NUMBER_OF(Buffer))
  479. {
  480. ::_vsnprintf(&Buffer[i - 1], NUMBER_OF(Buffer) - i, Format, Args);
  481. Buffer[NUMBER_OF(Buffer) - 1] = '\0';
  482. }
  483. ::FusionpTraceWin32LastErrorFailure(CallSiteInfo);
  484. ple.Restore();
  485. }
  486. //
  487. // See above issue about copying the callsite locally.
  488. //
  489. void __fastcall FusionpTraceWin32LastErrorFailureOriginationExV(const CALL_SITE_INFO &rCallSiteInfo, PCSTR Format, va_list Args)
  490. {
  491. CSxsPreserveLastError ple;
  492. CHAR Buffer[128];
  493. CALL_SITE_INFO CallSiteInfo = rCallSiteInfo;
  494. CallSiteInfo.pszApiName = Buffer;
  495. Buffer[0] = '\0';
  496. ::_vsnprintf(Buffer, NUMBER_OF(Buffer) - 1, Format, Args);
  497. Buffer[NUMBER_OF(Buffer) - 1] = '\0';
  498. ::FusionpTraceWin32LastErrorFailureOrigination(CallSiteInfo);
  499. ple.Restore();
  500. }
  501. void __fastcall FusionpTraceCOMFailure(const CALL_SITE_INFO &rSite, HRESULT hrLastError)
  502. {
  503. CSxsPreserveLastError ple;
  504. CHAR szErrorBuffer[128];
  505. PCSTR pszFormatString = NULL;
  506. const DWORD dwThreadId = ::GetCurrentThreadId();
  507. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrLastError);
  508. CFusionProcessImageFileName ProcessImageFileName;
  509. szErrorBuffer[0] = '\0';
  510. DWORD dwTemp = ::FormatMessageA(
  511. FORMAT_MESSAGE_FROM_SYSTEM |
  512. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  513. NULL, // lpSource - not used with system messages
  514. hrLastError, // dwMessageId
  515. 0, // langid - 0 uses system default search path of languages
  516. szErrorBuffer, // lpBuffer
  517. NUMBER_OF(szErrorBuffer), // nSize
  518. NULL); // Arguments
  519. if (dwTemp == 0)
  520. {
  521. ::_snprintf(
  522. szErrorBuffer,
  523. NUMBER_OF(szErrorBuffer),
  524. "<Untranslatable HRESULT %d (0x%08lx)>",
  525. hrLastError, hrLastError);
  526. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  527. }
  528. if (rSite.pszApiName != NULL)
  529. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] COM Error %d (%s) %s\n";
  530. else
  531. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] COM Error %d (%s)\n";
  532. ::FusionpDbgPrintEx(FUSION_DBG_LEVEL_ERROREXITPATH, pszFormatString, rSite.pszFile, rSite.nLine,
  533. rSite.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName, dwThreadId,
  534. hrLastError, szErrorBuffer, rSite.pszApiName);
  535. ple.Restore();
  536. }
  537. void __fastcall
  538. FusionpTraceWin32LastErrorFailure(
  539. const CALL_SITE_INFO &rSite
  540. )
  541. {
  542. CSxsPreserveLastError ple;
  543. CHAR szErrorBuffer[128];
  544. PCSTR pszFormatString = NULL;
  545. const DWORD dwThreadId = ::GetCurrentThreadId();
  546. const DWORD dwWin32Status = ::FusionpGetLastWin32Error();
  547. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(HRESULT_FROM_WIN32(dwWin32Status));
  548. CFusionProcessImageFileName ProcessImageFileName;
  549. szErrorBuffer[0] = '\0';
  550. DWORD dwTemp = ::FormatMessageA(
  551. FORMAT_MESSAGE_FROM_SYSTEM |
  552. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  553. NULL, // lpSource - not used with system messages
  554. dwWin32Status, // dwMessageId
  555. 0, // langid - 0 uses system default search path of languages
  556. szErrorBuffer, // lpBuffer
  557. NUMBER_OF(szErrorBuffer), // nSize
  558. NULL); // Arguments
  559. if (dwTemp == 0)
  560. {
  561. ::_snprintf(
  562. szErrorBuffer,
  563. NUMBER_OF(szErrorBuffer),
  564. "<Untranslatable Win32 status %d (0x%08lx)>",
  565. dwWin32Status, dwWin32Status);
  566. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  567. }
  568. if (rSite.pszApiName != NULL)
  569. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s) %s\n";
  570. else
  571. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s)\n";
  572. ::FusionpDbgPrintEx(FUSION_DBG_LEVEL_ERROREXITPATH, pszFormatString, rSite.pszFile, rSite.nLine,
  573. rSite.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName, dwThreadId,
  574. dwWin32Status, szErrorBuffer, rSite.pszApiName);
  575. ple.Restore();
  576. }
  577. void __fastcall FusionpTraceCOMFailureOrigination(const CALL_SITE_INFO &rSite, HRESULT hrLastError)
  578. {
  579. CSxsPreserveLastError ple;
  580. CHAR szErrorBuffer[128];
  581. PCSTR pszFormatString = NULL;
  582. const DWORD dwThreadId = ::GetCurrentThreadId();
  583. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrLastError);
  584. CFusionProcessImageFileName ProcessImageFileName;
  585. szErrorBuffer[0] = '\0';
  586. DWORD dwTemp = ::FormatMessageA(
  587. FORMAT_MESSAGE_FROM_SYSTEM |
  588. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  589. NULL, // lpSource - not used with system messages
  590. hrLastError, // dwMessageId
  591. 0, // langid - 0 uses system default search path of languages
  592. szErrorBuffer, // lpBuffer
  593. NUMBER_OF(szErrorBuffer), // nSize
  594. NULL); // Arguments
  595. if (dwTemp == 0)
  596. {
  597. ::_snprintf(
  598. szErrorBuffer,
  599. NUMBER_OF(szErrorBuffer),
  600. "<Untranslatable HRESULT 0x%08lx>",
  601. hrLastError);
  602. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  603. }
  604. if (rSite.pszApiName != NULL)
  605. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s) %s\n";
  606. else
  607. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s)\n";
  608. ::FusionpDbgPrintEx(
  609. FUSION_DBG_LEVEL_ERROR, // FUSION_DBG_LEVEL_ERROR vs. FUSION_DBG_LEVEL_ERROREXITPATH
  610. // is the difference between "origination" or not
  611. // origination always prints in DBG, the point is to get only one line
  612. // or the stack trace only one
  613. pszFormatString,
  614. rSite.pszFile,
  615. rSite.nLine,
  616. rSite.pszFunction,
  617. sizeof(PVOID)*CHAR_BIT,
  618. &ProcessImageFileName,
  619. dwThreadId,
  620. hrLastError,
  621. szErrorBuffer,
  622. rSite.pszApiName);
  623. ple.Restore();}
  624. void
  625. __fastcall
  626. FusionpTraceWin32LastErrorFailureOrigination(
  627. const CALL_SITE_INFO &rSite
  628. )
  629. {
  630. CSxsPreserveLastError ple;
  631. CHAR szErrorBuffer[128];
  632. PCSTR pszFormatString = NULL;
  633. const DWORD dwThreadId = ::GetCurrentThreadId();
  634. const DWORD dwWin32Status = ::FusionpGetLastWin32Error();
  635. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(HRESULT_FROM_WIN32(dwWin32Status));
  636. CFusionProcessImageFileName ProcessImageFileName;
  637. szErrorBuffer[0] = '\0';
  638. DWORD dwTemp = ::FormatMessageA(
  639. FORMAT_MESSAGE_FROM_SYSTEM |
  640. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  641. NULL, // lpSource - not used with system messages
  642. dwWin32Status, // dwMessageId
  643. 0, // langid - 0 uses system default search path of languages
  644. szErrorBuffer, // lpBuffer
  645. NUMBER_OF(szErrorBuffer), // nSize
  646. NULL); // Arguments
  647. if (dwTemp == 0)
  648. {
  649. ::_snprintf(
  650. szErrorBuffer,
  651. NUMBER_OF(szErrorBuffer),
  652. "<Untranslatable Win32 status %d (0x%08lx)>",
  653. dwWin32Status, dwWin32Status);
  654. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  655. }
  656. if (rSite.pszApiName != NULL)
  657. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s) %s\n";
  658. else
  659. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s)\n";
  660. ::FusionpDbgPrintEx(
  661. FUSION_DBG_LEVEL_ERROR, // FUSION_DBG_LEVEL_ERROR vs. FUSION_DBG_LEVEL_ERROREXITPATH
  662. // is the difference between "origination" or not
  663. // origination always prints in DBG, the point is to get only one line
  664. // or the stack trace only one
  665. pszFormatString,
  666. rSite.pszFile,
  667. rSite.nLine,
  668. rSite.pszFunction,
  669. sizeof(PVOID)*CHAR_BIT,
  670. &ProcessImageFileName,
  671. dwThreadId,
  672. dwWin32Status,
  673. szErrorBuffer,
  674. rSite.pszApiName);
  675. ple.Restore();
  676. }
  677. void
  678. FusionpTraceWin32FailureNoFormatting(
  679. const FRAME_INFO &rFrameInfo,
  680. DWORD dwWin32Status,
  681. PCSTR pszMessage
  682. )
  683. {
  684. CSxsPreserveLastError ple;
  685. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(HRESULT_FROM_WIN32(dwWin32Status));
  686. CHAR szErrorBuffer[128];
  687. PCSTR pszFormatString = NULL;
  688. const DWORD dwThreadId = ::GetCurrentThreadId();
  689. CFusionProcessImageFileName ProcessImageFileName;
  690. szErrorBuffer[0] = '\0';
  691. DWORD dwTemp = ::FormatMessageA(
  692. FORMAT_MESSAGE_FROM_SYSTEM |
  693. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  694. NULL, // lpSource - not used with system messages
  695. dwWin32Status, // dwMessageId
  696. 0, // langid - 0 uses system default search path of languages
  697. szErrorBuffer, // lpBuffer
  698. NUMBER_OF(szErrorBuffer), // nSize
  699. NULL); // Arguments
  700. if (dwTemp == 0)
  701. {
  702. ::_snprintf(
  703. szErrorBuffer,
  704. NUMBER_OF(szErrorBuffer),
  705. "<Untranslatable Win32 status %d (0x%08lx)>",
  706. dwWin32Status, dwWin32Status);
  707. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  708. }
  709. if (pszMessage != NULL)
  710. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s) %s\n";
  711. else
  712. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s)\n";
  713. ::FusionpDbgPrintEx(
  714. FUSION_DBG_LEVEL_ERROREXITPATH, pszFormatString, rFrameInfo.pszFile, rFrameInfo.nLine,
  715. rFrameInfo.pszFunction, sizeof(PVOID)*CHAR_BIT, &ProcessImageFileName, dwThreadId, dwWin32Status,
  716. szErrorBuffer, pszMessage
  717. );
  718. ple.Restore();
  719. }
  720. void
  721. FusionpTraceWin32FailureOriginationNoFormatting(
  722. const FRAME_INFO &rFrameInfo,
  723. DWORD dwWin32Status,
  724. PCSTR pszMessage
  725. )
  726. {
  727. CSxsPreserveLastError ple;
  728. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(HRESULT_FROM_WIN32(dwWin32Status));
  729. CHAR szErrorBuffer[128];
  730. PCSTR pszFormatString = NULL;
  731. const DWORD dwThreadId = ::GetCurrentThreadId();
  732. CFusionProcessImageFileName ProcessImageFileName;
  733. szErrorBuffer[0] = '\0';
  734. DWORD dwTemp = ::FormatMessageA(
  735. FORMAT_MESSAGE_FROM_SYSTEM |
  736. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  737. NULL, // lpSource - not used with system messages
  738. dwWin32Status, // dwMessageId
  739. 0, // langid - 0 uses system default search path of languages
  740. szErrorBuffer, // lpBuffer
  741. NUMBER_OF(szErrorBuffer), // nSize
  742. NULL); // Arguments
  743. if (dwTemp == 0)
  744. {
  745. ::_snprintf(
  746. szErrorBuffer,
  747. NUMBER_OF(szErrorBuffer),
  748. "<Untranslatable Win32 status %d (0x%08lx)>",
  749. dwWin32Status, dwWin32Status);
  750. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  751. }
  752. if (pszMessage != NULL)
  753. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s) %s\n";
  754. else
  755. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s)\n";
  756. ::FusionpDbgPrintEx(FUSION_DBG_LEVEL_ERROR, pszFormatString, rFrameInfo.pszFile, rFrameInfo.nLine,
  757. rFrameInfo.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName, dwThreadId,
  758. dwWin32Status, szErrorBuffer, pszMessage);
  759. ple.Restore();
  760. }
  761. void
  762. FusionpTraceWin32Failure(
  763. DWORD dwWin32Status,
  764. LPCSTR pszMsg,
  765. ...
  766. )
  767. {
  768. va_list ap;
  769. va_start(ap, pszMsg);
  770. ::FusionpTraceWin32FailureVa(dwWin32Status, pszMsg, ap);
  771. va_end(ap);
  772. }
  773. void
  774. FusionpTraceWin32FailureVa(
  775. const FRAME_INFO &rFrameInfo,
  776. DWORD dwWin32Status,
  777. LPCSTR pszMsg,
  778. va_list ap
  779. )
  780. {
  781. CSxsPreserveLastError ple;
  782. CHAR szMessageBuffer[128];
  783. szMessageBuffer[0] = '\0';
  784. if (pszMsg != NULL)
  785. ::_vsnprintf(szMessageBuffer, NUMBER_OF(szMessageBuffer), pszMsg, ap);
  786. else
  787. szMessageBuffer[0] = '\0';
  788. szMessageBuffer[NUMBER_OF(szMessageBuffer) - 1] = '\0';
  789. ::FusionpTraceWin32FailureNoFormatting(rFrameInfo, dwWin32Status, szMessageBuffer);
  790. ple.Restore();
  791. }
  792. void
  793. FusionpTraceWin32FailureVa(
  794. DWORD dwWin32Status,
  795. LPCSTR pszMsg,
  796. va_list ap
  797. )
  798. {
  799. FRAME_INFO FrameInfo;
  800. ::FusionpGetActiveFrameInfo(FrameInfo);
  801. ::FusionpTraceWin32FailureVa(FrameInfo, dwWin32Status, pszMsg, ap);
  802. }
  803. void
  804. FusionpTraceWin32FailureVa(
  805. PCSTR pszFile,
  806. PCSTR pszFunction,
  807. INT nLine,
  808. DWORD dwWin32Status,
  809. LPCSTR pszMsg,
  810. va_list ap
  811. )
  812. {
  813. FRAME_INFO FrameInfo;
  814. ::FusionpPopulateFrameInfo(FrameInfo, pszFile, pszFunction, nLine);
  815. ::FusionpTraceWin32FailureVa(FrameInfo, dwWin32Status, pszMsg, ap);
  816. }
  817. void
  818. FusionpTraceCallCOMSuccessfulExit(
  819. HRESULT hrIn,
  820. PCSTR pszFormat,
  821. ...
  822. )
  823. {
  824. va_list ap;
  825. va_start(ap, pszFormat);
  826. ::FusionpTraceCallCOMSuccessfulExitVa(hrIn, pszFormat, ap);
  827. va_end(ap);
  828. }
  829. void
  830. FusionpTraceCallCOMSuccessfulExitSmall(
  831. HRESULT hrIn
  832. )
  833. {
  834. /*
  835. This is a forked version of FusionpTraceCOMSuccessfulExitVaBig that we expect to get called.
  836. This function uses about 256 bytes of stack.
  837. FusionpTraceCOMSuccessfulExitVaBug uses about 1k of stack.
  838. */
  839. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  840. CHAR szErrorBuffer[256];
  841. const DWORD dwThreadId = ::GetCurrentThreadId();
  842. CFusionProcessImageFileName ProcessImageFileName;
  843. szErrorBuffer[0] = '\0';
  844. DWORD dwTemp = ::FormatMessageA(
  845. FORMAT_MESSAGE_FROM_SYSTEM |
  846. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  847. NULL, // lpSource - not used with system messages
  848. hrIn, // dwMessageId
  849. 0, // langid - 0 uses system default search path of languages
  850. szErrorBuffer, // lpBuffer
  851. NUMBER_OF(szErrorBuffer), // nSize
  852. NULL); // Arguments
  853. if (dwTemp == 0)
  854. {
  855. ::_snprintf(
  856. szErrorBuffer,
  857. NUMBER_OF(szErrorBuffer),
  858. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  859. hrIn);
  860. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  861. }
  862. PCSTR pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx\n";
  863. FRAME_INFO FrameInfo;
  864. ::FusionpGetActiveFrameInfo(FrameInfo);
  865. ::FusionpDbgPrintEx(
  866. FUSION_DBG_LEVEL_ENTEREXIT,
  867. pszFormatString,
  868. FrameInfo.pszFile,
  869. FrameInfo.nLine,
  870. FrameInfo.pszFunction,
  871. sizeof(PVOID) * CHAR_BIT,
  872. &ProcessImageFileName,
  873. dwThreadId,
  874. hrIn,
  875. szErrorBuffer);
  876. }
  877. void
  878. FusionpTraceCallCOMSuccessfulExitVaBig(
  879. HRESULT hrIn,
  880. LPCSTR pszMsg,
  881. va_list ap
  882. )
  883. {
  884. /*
  885. This is a forked version of FusionpTraceCOMSuccessfulExitVaSmall that we don't expect to get called.
  886. FusionpTraceCOMSuccessfulExitVaSmall uses about 256 bytes of stack.
  887. This function uses about 1k of stack.
  888. */
  889. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  890. CHAR szMsgBuffer[128];
  891. CHAR szErrorBuffer[128];
  892. CHAR szOutputBuffer[256];
  893. PCSTR pszFormatString = NULL;
  894. const DWORD dwThreadId = ::GetCurrentThreadId();
  895. FRAME_INFO FrameInfo;
  896. CFusionProcessImageFileName ProcessImageFileName;
  897. szMsgBuffer[0] = '\0';
  898. szErrorBuffer[0] = '\0';
  899. szOutputBuffer[0] = '\0';
  900. DWORD dwTemp = ::FormatMessageA(
  901. FORMAT_MESSAGE_FROM_SYSTEM |
  902. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  903. NULL, // lpSource - not used with system messages
  904. hrIn, // dwMessageId
  905. 0, // langid - 0 uses system default search path of languages
  906. szErrorBuffer, // lpBuffer
  907. NUMBER_OF(szErrorBuffer), // nSize
  908. NULL); // Arguments
  909. if (dwTemp == 0)
  910. {
  911. ::_snprintf(
  912. szErrorBuffer,
  913. NUMBER_OF(szErrorBuffer),
  914. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  915. hrIn);
  916. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  917. }
  918. szMsgBuffer[0] = '\0';
  919. if (pszMsg != NULL)
  920. {
  921. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s) %s\n";
  922. ::_vsnprintf(szMsgBuffer, NUMBER_OF(szMsgBuffer), pszMsg, ap);
  923. szMsgBuffer[NUMBER_OF(szMsgBuffer) - 1] = '\0';
  924. }
  925. else
  926. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s)\n";
  927. ::FusionpGetActiveFrameInfo(FrameInfo);
  928. ::_snprintf(szOutputBuffer, NUMBER_OF(szOutputBuffer), pszFormatString, FrameInfo.pszFile,
  929. FrameInfo.nLine, FrameInfo.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName, dwThreadId,
  930. hrIn, szErrorBuffer, szMsgBuffer);
  931. szOutputBuffer[NUMBER_OF(szOutputBuffer) - 1] = '\0';
  932. ::FusionpDbgPrintEx(
  933. FUSION_DBG_LEVEL_ENTEREXIT,
  934. "%s",
  935. szOutputBuffer);
  936. if ((s_hFile != NULL) && (s_hFile != INVALID_HANDLE_VALUE))
  937. {
  938. DWORD cBytesWritten = 0;
  939. if (!::WriteFile(s_hFile, szOutputBuffer, static_cast<DWORD>((::strlen(szOutputBuffer) + 1) * sizeof(CHAR)), &cBytesWritten, NULL))
  940. {
  941. // Avoid infinite loop if s_hFile is trashed...
  942. HANDLE hFileSaved = s_hFile;
  943. s_hFile = NULL;
  944. TRACE_WIN32_FAILURE_ORIGINATION(WriteFile);
  945. s_hFile = hFileSaved;
  946. }
  947. }
  948. }
  949. void
  950. FusionpTraceCallCOMSuccessfulExitVa(
  951. HRESULT hrIn,
  952. LPCSTR pszMsg,
  953. va_list ap
  954. )
  955. {
  956. /*
  957. This function has been split into FusionpTraceCOMSuccessfulExitVaBig and FusionpTraceCOMSuccessfulExitVaSmall, so that
  958. the usual case uses about 768 fewer bytes on the stack.
  959. */
  960. if ((pszMsg == NULL) &&
  961. ((s_hFile == NULL) ||
  962. (s_hFile == INVALID_HANDLE_VALUE)))
  963. {
  964. ::FusionpTraceCallCOMSuccessfulExitVaBig(hrIn, pszMsg, ap);
  965. }
  966. else
  967. {
  968. ::FusionpTraceCallCOMSuccessfulExitSmall(hrIn);
  969. }
  970. }
  971. void
  972. FusionpTraceCOMFailure(
  973. HRESULT hrIn,
  974. LPCSTR pszMsg,
  975. ...
  976. )
  977. {
  978. va_list ap;
  979. va_start(ap, pszMsg);
  980. ::FusionpTraceCOMFailureVa(hrIn, pszMsg, ap);
  981. va_end(ap);
  982. }
  983. void
  984. FusionpTraceCOMFailureSmall(
  985. HRESULT hrIn
  986. )
  987. {
  988. /*
  989. This is a forked version of FusionpTraceCOMFailureVaBig that we expect to get called.
  990. This function uses about 256 bytes of stack.
  991. FusionpTraceCOMFailureVaBug uses about 1k of stack.
  992. */
  993. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  994. CHAR szErrorBuffer[256];
  995. const DWORD dwThreadId = ::GetCurrentThreadId();
  996. CFusionProcessImageFileName ProcessImageFileName;
  997. szErrorBuffer[0] = '\0';
  998. DWORD dwTemp = ::FormatMessageA(
  999. FORMAT_MESSAGE_FROM_SYSTEM |
  1000. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  1001. NULL, // lpSource - not used with system messages
  1002. hrIn, // dwMessageId
  1003. 0, // langid - 0 uses system default search path of languages
  1004. szErrorBuffer, // lpBuffer
  1005. NUMBER_OF(szErrorBuffer), // nSize
  1006. NULL); // Arguments
  1007. if (dwTemp == 0)
  1008. {
  1009. ::_snprintf(
  1010. szErrorBuffer,
  1011. NUMBER_OF(szErrorBuffer),
  1012. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  1013. hrIn);
  1014. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  1015. }
  1016. PCSTR pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx\n";
  1017. FRAME_INFO FrameInfo;
  1018. ::FusionpGetActiveFrameInfo(FrameInfo);
  1019. ::FusionpDbgPrintEx(
  1020. FUSION_DBG_LEVEL_ERROREXITPATH,
  1021. pszFormatString,
  1022. FrameInfo.pszFile,
  1023. FrameInfo.nLine,
  1024. FrameInfo.pszFunction,
  1025. sizeof(PVOID) * CHAR_BIT,
  1026. &ProcessImageFileName,
  1027. dwThreadId,
  1028. hrIn,
  1029. szErrorBuffer);
  1030. }
  1031. void
  1032. FusionpTraceCOMFailureVaBig(
  1033. HRESULT hrIn,
  1034. LPCSTR pszMsg,
  1035. va_list ap
  1036. )
  1037. {
  1038. /*
  1039. This is a forked version of FusionpTraceCOMFailureVaSmall that we don't expect to get called.
  1040. FusionpTraceCOMFailureVaSmall uses about 256 bytes of stack.
  1041. This function uses about 1k of stack.
  1042. */
  1043. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  1044. CHAR szMsgBuffer[256];
  1045. CHAR szErrorBuffer[256];
  1046. CHAR szOutputBuffer[512];
  1047. PCSTR pszFormatString = NULL;
  1048. const DWORD dwThreadId = ::GetCurrentThreadId();
  1049. FRAME_INFO FrameInfo;
  1050. CFusionProcessImageFileName ProcessImageFileName;
  1051. szMsgBuffer[0] = '\0';
  1052. szErrorBuffer[0] = '\0';
  1053. szOutputBuffer[0] = '\0';
  1054. DWORD dwTemp = ::FormatMessageA(
  1055. FORMAT_MESSAGE_FROM_SYSTEM |
  1056. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  1057. NULL, // lpSource - not used with system messages
  1058. hrIn, // dwMessageId
  1059. 0, // langid - 0 uses system default search path of languages
  1060. szErrorBuffer, // lpBuffer
  1061. NUMBER_OF(szErrorBuffer), // nSize
  1062. NULL); // Arguments
  1063. if (dwTemp == 0)
  1064. {
  1065. ::_snprintf(
  1066. szErrorBuffer,
  1067. NUMBER_OF(szErrorBuffer),
  1068. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  1069. hrIn);
  1070. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  1071. }
  1072. szMsgBuffer[0] = '\0';
  1073. if (pszMsg != NULL)
  1074. {
  1075. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s) %s\n";
  1076. ::_vsnprintf(szMsgBuffer, NUMBER_OF(szMsgBuffer), pszMsg, ap);
  1077. szMsgBuffer[NUMBER_OF(szMsgBuffer) - 1] = '\0';
  1078. }
  1079. else
  1080. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s)\n";
  1081. ::FusionpGetActiveFrameInfo(FrameInfo);
  1082. ::_snprintf(szOutputBuffer, NUMBER_OF(szOutputBuffer), pszFormatString, FrameInfo.pszFile,
  1083. FrameInfo.nLine, FrameInfo.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName,
  1084. dwThreadId, hrIn, szErrorBuffer, szMsgBuffer);
  1085. szOutputBuffer[NUMBER_OF(szOutputBuffer) - 1] = '\0';
  1086. ::FusionpDbgPrintEx(
  1087. FUSION_DBG_LEVEL_ERROREXITPATH,
  1088. "%s",
  1089. szOutputBuffer);
  1090. if ((s_hFile != NULL) && (s_hFile != INVALID_HANDLE_VALUE))
  1091. {
  1092. DWORD cBytesWritten = 0;
  1093. if (!::WriteFile(s_hFile, szOutputBuffer, static_cast<DWORD>((::strlen(szOutputBuffer) + 1) * sizeof(CHAR)), &cBytesWritten, NULL))
  1094. {
  1095. // Avoid infinite loop if s_hFile is trashed...
  1096. HANDLE hFileSaved = s_hFile;
  1097. s_hFile = NULL;
  1098. TRACE_WIN32_FAILURE_ORIGINATION(WriteFile);
  1099. s_hFile = hFileSaved;
  1100. }
  1101. }
  1102. }
  1103. void
  1104. FusionpTraceCOMFailureVa(
  1105. HRESULT hrIn,
  1106. LPCSTR pszMsg,
  1107. va_list ap
  1108. )
  1109. {
  1110. /*
  1111. This function has been split into FusionpTraceCOMFailureVaBig and FusionpTraceCOMFailureVaSmall, so that
  1112. the usual case uses about 768 fewer bytes on the stack.
  1113. */
  1114. if ((pszMsg == NULL) &&
  1115. ((s_hFile == NULL) ||
  1116. (s_hFile == INVALID_HANDLE_VALUE)))
  1117. {
  1118. ::FusionpTraceCOMFailureVaBig(hrIn, pszMsg, ap);
  1119. }
  1120. else
  1121. {
  1122. ::FusionpTraceCOMFailureSmall(hrIn);
  1123. }
  1124. }
  1125. void
  1126. FusionpTraceCOMFailureOrigination(
  1127. HRESULT hrIn,
  1128. LPCSTR pszMsg,
  1129. ...
  1130. )
  1131. {
  1132. va_list ap;
  1133. va_start(ap, pszMsg);
  1134. ::FusionpTraceCOMFailureOriginationVa(hrIn, pszMsg, ap);
  1135. va_end(ap);
  1136. }
  1137. void
  1138. FusionpTraceCOMFailureOriginationSmall(
  1139. HRESULT hrIn
  1140. )
  1141. {
  1142. /*
  1143. This is a forked version of FusionpTraceCOMFailureVaBig that we expect to get called.
  1144. This function uses about 256 bytes of stack.
  1145. FusionpTraceCOMFailureVaBug uses about 1k of stack.
  1146. */
  1147. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  1148. CHAR szErrorBuffer[256];
  1149. const DWORD dwThreadId = ::GetCurrentThreadId();
  1150. CFusionProcessImageFileName ProcessImageFileName;
  1151. szErrorBuffer[0] = '\0';
  1152. DWORD dwTemp = ::FormatMessageA(
  1153. FORMAT_MESSAGE_FROM_SYSTEM |
  1154. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  1155. NULL, // lpSource - not used with system messages
  1156. hrIn, // dwMessageId
  1157. 0, // langid - 0 uses system default search path of languages
  1158. szErrorBuffer, // lpBuffer
  1159. NUMBER_OF(szErrorBuffer), // nSize
  1160. NULL); // Arguments
  1161. if (dwTemp == 0)
  1162. {
  1163. ::_snprintf(
  1164. szErrorBuffer,
  1165. NUMBER_OF(szErrorBuffer),
  1166. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  1167. hrIn);
  1168. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  1169. }
  1170. PCSTR pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx\n";
  1171. FRAME_INFO FrameInfo;
  1172. ::FusionpGetActiveFrameInfo(FrameInfo);
  1173. ::FusionpDbgPrintEx(FUSION_DBG_LEVEL_ERROR, pszFormatString, FrameInfo.pszFile,
  1174. FrameInfo.nLine, FrameInfo.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName,
  1175. dwThreadId, hrIn, szErrorBuffer);
  1176. }
  1177. void
  1178. FusionpTraceCOMFailureOriginationVaBig(
  1179. HRESULT hrIn,
  1180. LPCSTR pszMsg,
  1181. va_list ap
  1182. )
  1183. {
  1184. /*
  1185. This is a forked version of FusionpTraceCOMFailureVaSmall that we don't expect to get called.
  1186. FusionpTraceCOMFailureVaSmall uses about 256 bytes of stack.
  1187. This function uses about 1k of stack.
  1188. */
  1189. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  1190. CHAR szMsgBuffer[256];
  1191. CHAR szErrorBuffer[256];
  1192. CHAR szOutputBuffer[512];
  1193. PCSTR pszFormatString = NULL;
  1194. const DWORD dwThreadId = ::GetCurrentThreadId();
  1195. FRAME_INFO FrameInfo;
  1196. CFusionProcessImageFileName ProcessImageFileName;
  1197. szMsgBuffer[0] = '\0';
  1198. szErrorBuffer[0] = '\0';
  1199. szOutputBuffer[0] = '\0';
  1200. DWORD dwTemp = ::FormatMessageA(
  1201. FORMAT_MESSAGE_FROM_SYSTEM |
  1202. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  1203. NULL, // lpSource - not used with system messages
  1204. hrIn, // dwMessageId
  1205. 0, // langid - 0 uses system default search path of languages
  1206. szErrorBuffer, // lpBuffer
  1207. NUMBER_OF(szErrorBuffer), // nSize
  1208. NULL); // Arguments
  1209. if (dwTemp == 0)
  1210. {
  1211. ::_snprintf(
  1212. szErrorBuffer,
  1213. NUMBER_OF(szErrorBuffer),
  1214. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  1215. hrIn);
  1216. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  1217. }
  1218. szMsgBuffer[0] = '\0';
  1219. if (pszMsg != NULL)
  1220. {
  1221. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s) %s\n";
  1222. ::_vsnprintf(szMsgBuffer, NUMBER_OF(szMsgBuffer), pszMsg, ap);
  1223. szMsgBuffer[NUMBER_OF(szMsgBuffer) - 1] = '\0';
  1224. }
  1225. else
  1226. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s)\n";
  1227. ::FusionpGetActiveFrameInfo(FrameInfo);
  1228. ::_snprintf(szOutputBuffer, NUMBER_OF(szOutputBuffer), pszFormatString, FrameInfo.pszFile,
  1229. FrameInfo.nLine, FrameInfo.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName,
  1230. dwThreadId, hrIn, szErrorBuffer, szMsgBuffer);
  1231. szOutputBuffer[NUMBER_OF(szOutputBuffer) - 1] = '\0';
  1232. ::FusionpDbgPrintEx(
  1233. FUSION_DBG_LEVEL_ERROR,
  1234. "%s",
  1235. szOutputBuffer);
  1236. if ((s_hFile != NULL) && (s_hFile != INVALID_HANDLE_VALUE))
  1237. {
  1238. DWORD cBytesWritten = 0;
  1239. if (!::WriteFile(s_hFile, szOutputBuffer, static_cast<DWORD>((::strlen(szOutputBuffer) + 1) * sizeof(CHAR)), &cBytesWritten, NULL))
  1240. {
  1241. // Avoid infinite loop if s_hFile is trashed...
  1242. HANDLE hFileSaved = s_hFile;
  1243. s_hFile = NULL;
  1244. TRACE_WIN32_FAILURE_ORIGINATION(WriteFile);
  1245. s_hFile = hFileSaved;
  1246. }
  1247. }
  1248. }
  1249. void
  1250. __fastcall
  1251. FusionpTraceCOMFailureOrigination(const CALL_SITE_INFO &rSite)
  1252. {
  1253. }
  1254. void
  1255. FusionpTraceCOMFailureOriginationVa(
  1256. HRESULT hrIn,
  1257. LPCSTR pszMsg,
  1258. va_list ap
  1259. )
  1260. {
  1261. /*
  1262. This function has been split into FusionpTraceCOMFailureVaBig and FusionpTraceCOMFailureVaSmall, so that
  1263. the usual case uses about 768 fewer bytes on the stack.
  1264. */
  1265. if ((pszMsg == NULL) &&
  1266. ((s_hFile == NULL) ||
  1267. (s_hFile == INVALID_HANDLE_VALUE)))
  1268. {
  1269. ::FusionpTraceCOMFailureOriginationVaBig(hrIn, pszMsg, ap);
  1270. }
  1271. else
  1272. {
  1273. ::FusionpTraceCOMFailureOriginationSmall(hrIn);
  1274. }
  1275. }
  1276. struct ILogFile;
  1277. void
  1278. FusionpTraceCallEntry()
  1279. {
  1280. FRAME_INFO FrameInfo;
  1281. if (::FusionpGetActiveFrameInfo(FrameInfo))
  1282. {
  1283. ::FusionpDbgPrintEx(
  1284. FUSION_DBG_LEVEL_ENTEREXIT,
  1285. "%s(%d): Entered %s\n",
  1286. FrameInfo.pszFile,
  1287. FrameInfo.nLine,
  1288. FrameInfo.pszFunction);
  1289. }
  1290. }
  1291. void
  1292. FusionpTraceCallExit()
  1293. {
  1294. FRAME_INFO FrameInfo;
  1295. if (::FusionpGetActiveFrameInfo(FrameInfo))
  1296. {
  1297. ::FusionpDbgPrintEx(
  1298. FUSION_DBG_LEVEL_ENTEREXIT,
  1299. "%s(%d): Exited %s\n",
  1300. FrameInfo.pszFile,
  1301. FrameInfo.nLine,
  1302. FrameInfo.pszFunction);
  1303. }
  1304. }
  1305. void
  1306. FusionpTraceCallSuccessfulExitVa(
  1307. PCSTR szFormat,
  1308. va_list ap
  1309. )
  1310. {
  1311. FRAME_INFO FrameInfo;
  1312. if (::FusionpGetActiveFrameInfo(FrameInfo))
  1313. {
  1314. CHAR Buffer[256];
  1315. Buffer[0] = '\0';
  1316. if (szFormat != NULL)
  1317. {
  1318. ::_vsnprintf(Buffer, NUMBER_OF(Buffer), szFormat, ap);
  1319. Buffer[NUMBER_OF(Buffer) - 1] = '\0';
  1320. }
  1321. ::FusionpDbgPrintEx(
  1322. FUSION_DBG_LEVEL_ENTEREXIT,
  1323. "%s(%d): Successfully exiting %s%s%s\n",
  1324. FrameInfo.pszFile,
  1325. FrameInfo.nLine,
  1326. FrameInfo.pszFunction,
  1327. Buffer[0] == '\0' ? "" : " - ",
  1328. Buffer);
  1329. }
  1330. }
  1331. void
  1332. FusionpTraceCallSuccessfulExit(
  1333. PCSTR szFormat,
  1334. ...
  1335. )
  1336. {
  1337. va_list ap;
  1338. va_start(ap, szFormat);
  1339. ::FusionpTraceCallSuccessfulExitVa(szFormat, ap);
  1340. va_end(ap);
  1341. }
  1342. void
  1343. FusionpTraceCallWin32UnsuccessfulExitVa(
  1344. DWORD dwError,
  1345. PCSTR szFormat,
  1346. va_list ap
  1347. )
  1348. {
  1349. FRAME_INFO FrameInfo;
  1350. if (::FusionpGetActiveFrameInfo(FrameInfo))
  1351. {
  1352. ::FusionpTraceWin32FailureVa(
  1353. FrameInfo,
  1354. dwError,
  1355. szFormat,
  1356. ap);
  1357. }
  1358. }
  1359. void
  1360. FusionpTraceCallWin32UnsuccessfulExit(
  1361. DWORD dwError,
  1362. PCSTR szFormat,
  1363. ...
  1364. )
  1365. {
  1366. va_list ap;
  1367. va_start(ap, szFormat);
  1368. ::FusionpTraceCallWin32UnsuccessfulExitVa(dwError, szFormat, ap);
  1369. va_end(ap);
  1370. }
  1371. void
  1372. FusionpTraceCallCOMUnsuccessfulExitVa(
  1373. HRESULT hrError,
  1374. PCSTR szFormat,
  1375. va_list ap
  1376. )
  1377. {
  1378. ::FusionpTraceCOMFailureVa(
  1379. hrError,
  1380. szFormat,
  1381. ap);
  1382. }
  1383. void
  1384. FusionpTraceCallCOMUnsuccessfulExit(
  1385. HRESULT hrError,
  1386. PCSTR szFormat,
  1387. ...
  1388. )
  1389. {
  1390. va_list ap;
  1391. va_start(ap, szFormat);
  1392. ::FusionpTraceCallCOMUnsuccessfulExitVa(hrError, szFormat, ap);
  1393. va_end(ap);
  1394. }