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.

1844 lines
53 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. #if !defined(FUSION_BREAK_ON_BAD_PARAMETERS)
  10. #define FUSION_BREAK_ON_BAD_PARAMETERS false
  11. #endif // !defined(FUSION_BREAK_ON_BAD_PARAMETERS);
  12. bool g_FusionBreakOnBadParameters = FUSION_BREAK_ON_BAD_PARAMETERS;
  13. static HANDLE s_hFile; // trace file handle
  14. #if DBG
  15. #define FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hr) /* nothing */
  16. #else
  17. bool FusionpSuppressErrorReportInOsSetup(HRESULT hr)
  18. {
  19. //
  20. // Some of these are unfortunately expected (early) in guimode setup, actually
  21. // concurrent with early guimode setup, but not otherwise.
  22. //
  23. if ( hr != HRESULT_FROM_WIN32(ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED)
  24. && hr != HRESULT_FROM_WIN32(ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED)
  25. )
  26. return false;
  27. BOOL fAreWeInOSSetupMode = FALSE;
  28. //
  29. // If we can't determine this, then let the first error through.
  30. //
  31. if (!::FusionpAreWeInOSSetupMode(&fAreWeInOSSetupMode))
  32. return false;
  33. if (!fAreWeInOSSetupMode)
  34. return false;
  35. return true;
  36. }
  37. #define FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hr) if (FusionpSuppressErrorReportInOsSetup(hr)) return;
  38. #endif
  39. bool
  40. __fastcall
  41. FusionpGetActiveFrameInfo(
  42. FRAME_INFO &rFrameInfo
  43. )
  44. {
  45. bool fFoundAnyData = false;
  46. rFrameInfo.pszFile = "";
  47. rFrameInfo.pszFunction = "";
  48. rFrameInfo.nLine = 0;
  49. const PTEB_ACTIVE_FRAME ptaf =
  50. #if FUSION_WIN
  51. ::RtlGetFrame();
  52. #else
  53. NULL;
  54. #endif
  55. const PTEB_ACTIVE_FRAME_EX ptafe =
  56. ((ptaf != NULL) && (ptaf->Flags & TEB_ACTIVE_FRAME_FLAG_EXTENDED)) ?
  57. reinterpret_cast<PTEB_ACTIVE_FRAME_EX>(ptaf) : NULL;
  58. if (ptaf != NULL)
  59. {
  60. if (ptaf->Context != NULL)
  61. {
  62. if (ptaf->Context->FrameName != NULL)
  63. {
  64. rFrameInfo.pszFunction = ptaf->Context->FrameName;
  65. fFoundAnyData = true;
  66. }
  67. if (ptaf->Context->Flags & TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED)
  68. {
  69. const PCTEB_ACTIVE_FRAME_CONTEXT_EX ptafce =
  70. reinterpret_cast<PCTEB_ACTIVE_FRAME_CONTEXT_EX>(ptaf->Context);
  71. if (ptafce->SourceLocation != NULL)
  72. {
  73. rFrameInfo.pszFile = ptafce->SourceLocation;
  74. fFoundAnyData = true;
  75. }
  76. }
  77. }
  78. }
  79. // If this is one of our frames, we can even downcast and get the line number...
  80. if ((ptafe != NULL) && (ptafe->ExtensionIdentifier == (PVOID) (' sxS')))
  81. {
  82. const CFrame *pFrame = static_cast<CFrame *>(ptafe);
  83. if (pFrame->m_nLine != 0)
  84. {
  85. rFrameInfo.nLine = pFrame->m_nLine;
  86. fFoundAnyData = true;
  87. }
  88. }
  89. return fFoundAnyData;
  90. }
  91. bool
  92. __fastcall
  93. FusionpPopulateFrameInfo(
  94. FRAME_INFO &rFrameInfo,
  95. PCTEB_ACTIVE_FRAME ptaf
  96. )
  97. {
  98. bool fFoundAnyData = false;
  99. rFrameInfo.pszFile = "";
  100. rFrameInfo.pszFunction = "";
  101. rFrameInfo.nLine = 0;
  102. const PCTEB_ACTIVE_FRAME_EX ptafe =
  103. ((ptaf != NULL) && (ptaf->Flags & TEB_ACTIVE_FRAME_FLAG_EXTENDED)) ?
  104. reinterpret_cast<PCTEB_ACTIVE_FRAME_EX>(ptaf) : NULL;
  105. if (ptaf != NULL)
  106. {
  107. if (ptaf->Context != NULL)
  108. {
  109. if (ptaf->Context->FrameName != NULL)
  110. {
  111. rFrameInfo.pszFunction = ptaf->Context->FrameName;
  112. fFoundAnyData = true;
  113. }
  114. if (ptaf->Context->Flags & TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED)
  115. {
  116. const PCTEB_ACTIVE_FRAME_CONTEXT_EX ptafce =
  117. reinterpret_cast<PCTEB_ACTIVE_FRAME_CONTEXT_EX>(ptaf->Context);
  118. if (ptafce->SourceLocation != NULL)
  119. {
  120. rFrameInfo.pszFile = ptafce->SourceLocation;
  121. fFoundAnyData = true;
  122. }
  123. }
  124. }
  125. }
  126. // If this is one of our frames, we can even downcast and get the line number...
  127. if ((ptafe != NULL) && (ptafe->ExtensionIdentifier == ((PVOID) (' sxS'))))
  128. {
  129. const CFrame *pFrame = static_cast<const CFrame *>(ptafe);
  130. if (pFrame->m_nLine != 0)
  131. {
  132. rFrameInfo.nLine = pFrame->m_nLine;
  133. fFoundAnyData = true;
  134. }
  135. }
  136. return fFoundAnyData;
  137. }
  138. bool
  139. FusionpPopulateFrameInfo(
  140. FRAME_INFO &rFrameInfo,
  141. PCSTR pszFile,
  142. PCSTR pszFunction,
  143. INT nLine
  144. )
  145. {
  146. bool fFoundAnyData = false;
  147. if (pszFile != NULL)
  148. {
  149. rFrameInfo.pszFile = pszFile;
  150. fFoundAnyData = true;
  151. }
  152. else
  153. rFrameInfo.pszFile = NULL;
  154. if (nLine != 0)
  155. fFoundAnyData = true;
  156. rFrameInfo.nLine = nLine;
  157. if (pszFunction != NULL)
  158. {
  159. rFrameInfo.pszFunction = pszFunction;
  160. fFoundAnyData = true;
  161. }
  162. else
  163. rFrameInfo.pszFunction = NULL;
  164. return fFoundAnyData;
  165. }
  166. int STDAPIVCALLTYPE _DebugTraceA(LPCSTR pszMsg, ...)
  167. {
  168. int iResult;
  169. va_list ap;
  170. va_start(ap, pszMsg);
  171. iResult = _DebugTraceExVaA(0, TRACETYPE_INFO, NOERROR, pszMsg, ap);
  172. va_end(ap);
  173. return iResult;
  174. }
  175. int STDAPICALLTYPE
  176. _DebugTraceVaA(LPCSTR pszMsg, va_list ap)
  177. {
  178. return _DebugTraceExVaA(0, TRACETYPE_INFO, NOERROR, pszMsg, ap);
  179. }
  180. int STDAPIVCALLTYPE
  181. _DebugTraceExA(DWORD dwFlags, TRACETYPE tt, HRESULT hr, LPCSTR pszMsg, ...)
  182. {
  183. int iResult;
  184. va_list ap;
  185. va_start(ap, pszMsg);
  186. iResult = _DebugTraceExVaA(dwFlags, tt, hr, pszMsg, ap);
  187. va_end(ap);
  188. return iResult;
  189. }
  190. int STDAPICALLTYPE
  191. _DebugTraceExVaA(DWORD dwFlags, TRACETYPE tt, HRESULT hr, LPCSTR pszMsg, va_list ap)
  192. {
  193. CSxsPreserveLastError ple;
  194. CHAR szBuffer[512];
  195. CHAR szMsgBuffer[512];
  196. static const char szFormat_Info_NoFunc[] = "%s(%d): Message: \"%s\"\n";
  197. static const char szFormat_Info_Func[] = "%s(%d): Function %s. Message: \"%s\"\n";
  198. static const char szFormat_CallEntry[] = "%s(%d): Entered %s\n";
  199. static const char szFormat_CallExitVoid[] = "%s(%d): Exited %s\n";
  200. static const char szFormat_CallExitHRESULT[] = "%s(%d): Exited %s with HRESULT 0x%08lx\n";
  201. FRAME_INFO FrameInfo;
  202. szMsgBuffer[0] = '\0';
  203. if (pszMsg != NULL)
  204. {
  205. ::_snprintf(szMsgBuffer, NUMBER_OF(szMsgBuffer), pszMsg, ap);
  206. szMsgBuffer[NUMBER_OF(szMsgBuffer) - 1] = '\0';
  207. }
  208. ::FusionpGetActiveFrameInfo(FrameInfo);
  209. switch (tt)
  210. {
  211. default:
  212. case TRACETYPE_INFO:
  213. if (FrameInfo.pszFunction != NULL)
  214. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), szFormat_Info_Func, FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction, szMsgBuffer);
  215. else
  216. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), szFormat_Info_NoFunc, FrameInfo.pszFile, FrameInfo.nLine, szMsgBuffer);
  217. break;
  218. case TRACETYPE_CALL_START:
  219. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), szFormat_CallEntry, FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction);
  220. break;
  221. case TRACETYPE_CALL_EXIT_NOHRESULT:
  222. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), szFormat_CallExitVoid, FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction);
  223. break;
  224. case TRACETYPE_CALL_EXIT_HRESULT:
  225. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), szFormat_CallExitHRESULT, FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction, hr);
  226. break;
  227. }
  228. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  229. ::OutputDebugStringA(szBuffer);
  230. ple.Restore();
  231. return 0;
  232. }
  233. VOID
  234. FusionpTraceAllocFailure(
  235. PCSTR pszFile,
  236. int nLine,
  237. PCSTR pszFunction,
  238. PCSTR pszExpression
  239. )
  240. {
  241. CSxsPreserveLastError ple;
  242. CHAR szBuffer[512];
  243. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), "%s(%d): Memory allocation failed in function %s\n Expression: %s\n", pszFile, nLine, pszFunction, pszExpression);
  244. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  245. ::OutputDebugStringA(szBuffer);
  246. ple.Restore();
  247. }
  248. VOID
  249. FusionpTraceAllocFailure(
  250. PCSTR pszExpression
  251. )
  252. {
  253. FRAME_INFO FrameInfo;
  254. ::FusionpGetActiveFrameInfo(FrameInfo);
  255. ::FusionpTraceAllocFailure(FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction, pszExpression);
  256. }
  257. VOID
  258. FusionpTraceNull(
  259. PCSTR pszFile,
  260. int nLine,
  261. PCSTR pszFunction,
  262. PCSTR pszExpression
  263. )
  264. {
  265. CSxsPreserveLastError ple;
  266. CHAR szBuffer[512];
  267. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), "%s(%d): Expression evaluated to NULL in function %s\n Expression: %s\n", pszFile, nLine, pszFunction, pszExpression);
  268. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  269. ::OutputDebugStringA(szBuffer);
  270. ple.Restore();
  271. }
  272. VOID
  273. FusionpTraceNull(
  274. PCSTR pszExpression
  275. )
  276. {
  277. FRAME_INFO FrameInfo;
  278. ::FusionpGetActiveFrameInfo(FrameInfo);
  279. ::FusionpTraceNull(FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction, pszExpression);
  280. }
  281. VOID
  282. FusionpTraceZero(
  283. PCSTR pszFile,
  284. int nLine,
  285. PCSTR pszFunction,
  286. PCSTR pszExpression
  287. )
  288. {
  289. CSxsPreserveLastError ple;
  290. CHAR szBuffer[512];
  291. ::_snprintf(szBuffer, NUMBER_OF(szBuffer), "%s(%d): Expression evaluated to zero in function %s\n Expression: %s\n", pszFile, nLine, pszFunction, pszExpression);
  292. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  293. ::OutputDebugStringA(szBuffer);
  294. ple.Restore();
  295. }
  296. VOID
  297. FusionpTraceZero(
  298. PCSTR pszExpression
  299. )
  300. {
  301. FRAME_INFO FrameInfo;
  302. ::FusionpGetActiveFrameInfo(FrameInfo);
  303. ::FusionpTraceZero(FrameInfo.pszFile, FrameInfo.nLine, FrameInfo.pszFunction, pszExpression);
  304. }
  305. VOID
  306. FusionpTraceParameterCheck(
  307. const FRAME_INFO &rFrameInfo,
  308. PCSTR pszExpression
  309. )
  310. {
  311. CSxsPreserveLastError ple;
  312. CHAR szBuffer[512];
  313. ::_snprintf(
  314. szBuffer,
  315. NUMBER_OF(szBuffer),
  316. "%s(%d): Input parameter validation failed in function %s\n Validation expression: %s\n",
  317. rFrameInfo.pszFile,
  318. rFrameInfo.nLine,
  319. rFrameInfo.pszFunction,
  320. pszExpression);
  321. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  322. ::OutputDebugStringA(szBuffer);
  323. if (g_FusionBreakOnBadParameters)
  324. FUSION_DEBUG_BREAK_IN_FREE_BUILD();
  325. ple.Restore();
  326. }
  327. VOID
  328. FusionpTraceParameterCheck(
  329. PCSTR pszFile,
  330. PCSTR pszFunction,
  331. int nLine,
  332. PCSTR pszExpression
  333. )
  334. {
  335. FRAME_INFO FrameInfo;
  336. ::FusionpPopulateFrameInfo(FrameInfo, pszFile, pszFunction, nLine);
  337. ::FusionpTraceParameterCheck(FrameInfo, pszExpression);
  338. }
  339. VOID
  340. FusionpTraceParameterCheck(
  341. PCSTR pszExpression
  342. )
  343. {
  344. FRAME_INFO FrameInfo;
  345. ::FusionpGetActiveFrameInfo(FrameInfo);
  346. ::FusionpTraceParameterCheck(FrameInfo, pszExpression);
  347. }
  348. VOID
  349. FusionpTraceInvalidFlags(
  350. const FRAME_INFO &rFrameInfo,
  351. DWORD dwFlagsPassed,
  352. DWORD dwFlagsExpected
  353. )
  354. {
  355. CSxsPreserveLastError ple;
  356. CHAR szBuffer[512];
  357. ::_snprintf(
  358. szBuffer,
  359. NUMBER_OF(szBuffer),
  360. "%s(%d): Function %s received invalid flags\n"
  361. " Flags passed: 0x%08lx\n"
  362. " Flags allowed: 0x%08lx\n",
  363. rFrameInfo.pszFile, rFrameInfo.nLine, rFrameInfo.pszFunction,
  364. dwFlagsPassed,
  365. dwFlagsExpected);
  366. szBuffer[NUMBER_OF(szBuffer) - 1] = '\0';
  367. ::OutputDebugStringA(szBuffer);
  368. ple.Restore();
  369. }
  370. VOID
  371. FusionpTraceInvalidFlags(
  372. PCSTR pszFile,
  373. PCSTR pszFunction,
  374. INT nLine,
  375. DWORD dwFlagsPassed,
  376. DWORD dwFlagsExpected
  377. )
  378. {
  379. FRAME_INFO FrameInfo;
  380. ::FusionpPopulateFrameInfo(FrameInfo, pszFile, pszFunction, nLine);
  381. ::FusionpTraceInvalidFlags(FrameInfo, dwFlagsPassed, dwFlagsExpected);
  382. }
  383. VOID
  384. FusionpTraceInvalidFlags(
  385. DWORD dwFlagsPassed,
  386. DWORD dwFlagsExpected
  387. )
  388. {
  389. FRAME_INFO FrameInfo;
  390. ::FusionpGetActiveFrameInfo(FrameInfo);
  391. ::FusionpTraceInvalidFlags(FrameInfo, dwFlagsPassed, dwFlagsExpected);
  392. }
  393. void
  394. FusionpGetProcessImageFileName(
  395. PUNICODE_STRING ProcessImageFileName
  396. )
  397. {
  398. #if !defined(FUSION_WIN)
  399. ProcessImageFileName->Length = 0;
  400. #else
  401. USHORT PrefixLength;
  402. *ProcessImageFileName = NtCurrentPeb()->ProcessParameters->ImagePathName;
  403. if (NT_SUCCESS(RtlFindCharInUnicodeString(
  404. RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
  405. ProcessImageFileName,
  406. &RtlDosPathSeperatorsString,
  407. &PrefixLength)))
  408. {
  409. PrefixLength += sizeof(ProcessImageFileName->Buffer[0]);
  410. ProcessImageFileName->Length = static_cast<USHORT>(ProcessImageFileName->Length - PrefixLength);
  411. ProcessImageFileName->Buffer += PrefixLength / sizeof(ProcessImageFileName->Buffer[0]);
  412. }
  413. #endif
  414. }
  415. class CFusionProcessImageFileName : public UNICODE_STRING
  416. {
  417. public:
  418. CFusionProcessImageFileName()
  419. {
  420. ::FusionpGetProcessImageFileName(this);
  421. }
  422. };
  423. void __fastcall FusionpTraceWin32LastErrorFailureExV(const CALL_SITE_INFO &rCallSiteInfo, PCSTR Format, va_list Args)
  424. {
  425. CSxsPreserveLastError ple;
  426. CHAR Buffer[256];
  427. CALL_SITE_INFO CallSiteInfo = rCallSiteInfo;
  428. CallSiteInfo.pszApiName = Buffer;
  429. SIZE_T i = 1;
  430. Buffer[0] = '\0';
  431. if (rCallSiteInfo.pszApiName != NULL && rCallSiteInfo.pszApiName[0] != '\0')
  432. {
  433. ::_snprintf(Buffer, NUMBER_OF(Buffer) - i, "%s", rCallSiteInfo.pszApiName);
  434. Buffer[NUMBER_OF(Buffer) - 1] = '\0';
  435. i = 1 + ::StringLength(Buffer);
  436. }
  437. if (i < NUMBER_OF(Buffer))
  438. {
  439. ::_vsnprintf(&Buffer[i - 1], NUMBER_OF(Buffer) - i, Format, Args);
  440. Buffer[NUMBER_OF(Buffer) - 1] = '\0';
  441. }
  442. ::FusionpTraceWin32LastErrorFailure(CallSiteInfo);
  443. ple.Restore();
  444. }
  445. void __fastcall FusionpTraceWin32LastErrorFailureOriginationExV(const CALL_SITE_INFO &rCallSiteInfo, PCSTR Format, va_list Args)
  446. {
  447. CSxsPreserveLastError ple;
  448. CHAR Buffer[128];
  449. CALL_SITE_INFO CallSiteInfo = rCallSiteInfo;
  450. CallSiteInfo.pszApiName = Buffer;
  451. Buffer[0] = '\0';
  452. ::_vsnprintf(Buffer, NUMBER_OF(Buffer) - 1, Format, Args);
  453. Buffer[NUMBER_OF(Buffer) - 1] = '\0';
  454. ::FusionpTraceWin32LastErrorFailureOrigination(CallSiteInfo);
  455. ple.Restore();
  456. }
  457. void __fastcall
  458. FusionpTraceWin32LastErrorFailure(
  459. const CALL_SITE_INFO &rSite
  460. )
  461. {
  462. CSxsPreserveLastError ple;
  463. CHAR szErrorBuffer[128];
  464. PCSTR pszFormatString = NULL;
  465. const DWORD dwThreadId = ::GetCurrentThreadId();
  466. const DWORD dwWin32Status = ::FusionpGetLastWin32Error();
  467. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(HRESULT_FROM_WIN32(dwWin32Status));
  468. CFusionProcessImageFileName ProcessImageFileName;
  469. szErrorBuffer[0] = '\0';
  470. DWORD dwTemp = ::FormatMessageA(
  471. FORMAT_MESSAGE_FROM_SYSTEM |
  472. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  473. NULL, // lpSource - not used with system messages
  474. dwWin32Status, // dwMessageId
  475. 0, // langid - 0 uses system default search path of languages
  476. szErrorBuffer, // lpBuffer
  477. NUMBER_OF(szErrorBuffer), // nSize
  478. NULL); // Arguments
  479. if (dwTemp == 0)
  480. {
  481. ::_snprintf(
  482. szErrorBuffer,
  483. NUMBER_OF(szErrorBuffer),
  484. "<Untranslatable Win32 status %d (0x%08lx)>",
  485. dwWin32Status, dwWin32Status);
  486. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  487. }
  488. if (rSite.pszApiName != NULL)
  489. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s) %s\n";
  490. else
  491. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s)\n";
  492. ::FusionpDbgPrintEx(FUSION_DBG_LEVEL_ERROREXITPATH, pszFormatString, rSite.pszFile, rSite.nLine,
  493. rSite.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName, dwThreadId,
  494. dwWin32Status, szErrorBuffer, rSite.pszApiName);
  495. ple.Restore();
  496. }
  497. void
  498. __fastcall
  499. FusionpTraceWin32LastErrorFailureOrigination(
  500. const CALL_SITE_INFO &rSite
  501. )
  502. {
  503. CSxsPreserveLastError ple;
  504. CHAR szErrorBuffer[128];
  505. PCSTR pszFormatString = NULL;
  506. const DWORD dwThreadId = ::GetCurrentThreadId();
  507. const DWORD dwWin32Status = ::FusionpGetLastWin32Error();
  508. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(HRESULT_FROM_WIN32(dwWin32Status));
  509. CFusionProcessImageFileName ProcessImageFileName;
  510. szErrorBuffer[0] = '\0';
  511. DWORD dwTemp = ::FormatMessageA(
  512. FORMAT_MESSAGE_FROM_SYSTEM |
  513. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  514. NULL, // lpSource - not used with system messages
  515. dwWin32Status, // dwMessageId
  516. 0, // langid - 0 uses system default search path of languages
  517. szErrorBuffer, // lpBuffer
  518. NUMBER_OF(szErrorBuffer), // nSize
  519. NULL); // Arguments
  520. if (dwTemp == 0)
  521. {
  522. ::_snprintf(
  523. szErrorBuffer,
  524. NUMBER_OF(szErrorBuffer),
  525. "<Untranslatable Win32 status %d (0x%08lx)>",
  526. dwWin32Status, dwWin32Status);
  527. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  528. }
  529. if (rSite.pszApiName != NULL)
  530. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s) %s\n";
  531. else
  532. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s)\n";
  533. ::FusionpDbgPrintEx(
  534. FUSION_DBG_LEVEL_ERROR, // FUSION_DBG_LEVEL_ERROR vs. FUSION_DBG_LEVEL_ERROREXITPATH
  535. // is the difference between "origination" or not
  536. // origination always prints in DBG, the point is to get only one line
  537. // or the stack trace only one
  538. pszFormatString,
  539. rSite.pszFile,
  540. rSite.nLine,
  541. rSite.pszFunction,
  542. sizeof(PVOID)*CHAR_BIT,
  543. &ProcessImageFileName,
  544. dwThreadId,
  545. dwWin32Status,
  546. szErrorBuffer,
  547. rSite.pszApiName);
  548. ple.Restore();
  549. }
  550. void
  551. FusionpTraceWin32FailureNoFormatting(
  552. const FRAME_INFO &rFrameInfo,
  553. DWORD dwWin32Status,
  554. PCSTR pszMessage
  555. )
  556. {
  557. CSxsPreserveLastError ple;
  558. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(HRESULT_FROM_WIN32(dwWin32Status));
  559. CHAR szErrorBuffer[128];
  560. PCSTR pszFormatString = NULL;
  561. const DWORD dwThreadId = ::GetCurrentThreadId();
  562. CFusionProcessImageFileName ProcessImageFileName;
  563. szErrorBuffer[0] = '\0';
  564. DWORD dwTemp = ::FormatMessageA(
  565. FORMAT_MESSAGE_FROM_SYSTEM |
  566. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  567. NULL, // lpSource - not used with system messages
  568. dwWin32Status, // dwMessageId
  569. 0, // langid - 0 uses system default search path of languages
  570. szErrorBuffer, // lpBuffer
  571. NUMBER_OF(szErrorBuffer), // nSize
  572. NULL); // Arguments
  573. if (dwTemp == 0)
  574. {
  575. ::_snprintf(
  576. szErrorBuffer,
  577. NUMBER_OF(szErrorBuffer),
  578. "<Untranslatable Win32 status %d (0x%08lx)>",
  579. dwWin32Status, dwWin32Status);
  580. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  581. }
  582. if (pszMessage != NULL)
  583. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s) %s\n";
  584. else
  585. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s)\n";
  586. ::FusionpDbgPrintEx(
  587. FUSION_DBG_LEVEL_ERROREXITPATH, pszFormatString, rFrameInfo.pszFile, rFrameInfo.nLine,
  588. rFrameInfo.pszFunction, sizeof(PVOID)*CHAR_BIT, &ProcessImageFileName, dwThreadId, dwWin32Status,
  589. szErrorBuffer, pszMessage
  590. );
  591. ple.Restore();
  592. }
  593. void
  594. FusionpTraceWin32FailureOriginationNoFormatting(
  595. const FRAME_INFO &rFrameInfo,
  596. DWORD dwWin32Status,
  597. PCSTR pszMessage
  598. )
  599. {
  600. CSxsPreserveLastError ple;
  601. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(HRESULT_FROM_WIN32(dwWin32Status));
  602. CHAR szErrorBuffer[128];
  603. PCSTR pszFormatString = NULL;
  604. const DWORD dwThreadId = ::GetCurrentThreadId();
  605. CFusionProcessImageFileName ProcessImageFileName;
  606. szErrorBuffer[0] = '\0';
  607. DWORD dwTemp = ::FormatMessageA(
  608. FORMAT_MESSAGE_FROM_SYSTEM |
  609. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  610. NULL, // lpSource - not used with system messages
  611. dwWin32Status, // dwMessageId
  612. 0, // langid - 0 uses system default search path of languages
  613. szErrorBuffer, // lpBuffer
  614. NUMBER_OF(szErrorBuffer), // nSize
  615. NULL); // Arguments
  616. if (dwTemp == 0)
  617. {
  618. ::_snprintf(
  619. szErrorBuffer,
  620. NUMBER_OF(szErrorBuffer),
  621. "<Untranslatable Win32 status %d (0x%08lx)>",
  622. dwWin32Status, dwWin32Status);
  623. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  624. }
  625. if (pszMessage != NULL)
  626. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s) %s\n";
  627. else
  628. pszFormatString = "%s(%lu): [function %s %Iubit process %wZ tid 0x%lx] Win32 Error %d (%s)\n";
  629. ::FusionpDbgPrintEx(FUSION_DBG_LEVEL_ERROR, pszFormatString, rFrameInfo.pszFile, rFrameInfo.nLine,
  630. rFrameInfo.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName, dwThreadId,
  631. dwWin32Status, szErrorBuffer, pszMessage);
  632. ple.Restore();
  633. }
  634. void
  635. FusionpTraceWin32Failure(
  636. DWORD dwWin32Status,
  637. LPCSTR pszMsg,
  638. ...
  639. )
  640. {
  641. va_list ap;
  642. va_start(ap, pszMsg);
  643. ::FusionpTraceWin32FailureVa(dwWin32Status, pszMsg, ap);
  644. va_end(ap);
  645. }
  646. #if 0
  647. void
  648. FusionpTraceWin32Failure(
  649. const FRAME_INFO &rFrameInfo,
  650. DWORD dwWin32Status,
  651. LPCSTR pszMsg,
  652. ...
  653. )
  654. {
  655. va_list ap;
  656. va_start(ap, pszMsg);
  657. ::FusionpTraceWin32FailureVa(rFrameInfo, dwWin32Status, pszMsg, ap);
  658. va_end(ap);
  659. }
  660. void
  661. FusionpTraceWin32Failure(
  662. PCSTR pszFile,
  663. PCSTR pszFunction,
  664. INT nLine,
  665. DWORD dwWin32Status,
  666. LPCSTR pszMsg,
  667. ...
  668. )
  669. {
  670. va_list ap;
  671. va_start(ap, pszMsg);
  672. ::FusionpTraceWin32FailureVa(pszFile, pszFunction, nLine, dwWin32Status, pszMsg, ap);
  673. va_end(ap);
  674. }
  675. #endif
  676. void
  677. FusionpTraceWin32FailureVa(
  678. const FRAME_INFO &rFrameInfo,
  679. DWORD dwWin32Status,
  680. LPCSTR pszMsg,
  681. va_list ap
  682. )
  683. {
  684. CSxsPreserveLastError ple;
  685. CHAR szMessageBuffer[128];
  686. szMessageBuffer[0] = '\0';
  687. if (pszMsg != NULL)
  688. ::_vsnprintf(szMessageBuffer, NUMBER_OF(szMessageBuffer), pszMsg, ap);
  689. else
  690. szMessageBuffer[0] = '\0';
  691. szMessageBuffer[NUMBER_OF(szMessageBuffer) - 1] = '\0';
  692. ::FusionpTraceWin32FailureNoFormatting(rFrameInfo, dwWin32Status, szMessageBuffer);
  693. ple.Restore();
  694. }
  695. void
  696. FusionpTraceWin32FailureVa(
  697. DWORD dwWin32Status,
  698. LPCSTR pszMsg,
  699. va_list ap
  700. )
  701. {
  702. FRAME_INFO FrameInfo;
  703. ::FusionpGetActiveFrameInfo(FrameInfo);
  704. ::FusionpTraceWin32FailureVa(FrameInfo, dwWin32Status, pszMsg, ap);
  705. }
  706. void
  707. FusionpTraceWin32FailureVa(
  708. PCSTR pszFile,
  709. PCSTR pszFunction,
  710. INT nLine,
  711. DWORD dwWin32Status,
  712. LPCSTR pszMsg,
  713. va_list ap
  714. )
  715. {
  716. FRAME_INFO FrameInfo;
  717. ::FusionpPopulateFrameInfo(FrameInfo, pszFile, pszFunction, nLine);
  718. ::FusionpTraceWin32FailureVa(FrameInfo, dwWin32Status, pszMsg, ap);
  719. }
  720. void
  721. FusionpTraceCallCOMSuccessfulExit(
  722. HRESULT hrIn,
  723. PCSTR pszFormat,
  724. ...
  725. )
  726. {
  727. va_list ap;
  728. va_start(ap, pszFormat);
  729. ::FusionpTraceCallCOMSuccessfulExitVa(hrIn, pszFormat, ap);
  730. va_end(ap);
  731. }
  732. void
  733. FusionpTraceCallCOMSuccessfulExitSmall(
  734. HRESULT hrIn
  735. )
  736. {
  737. /*
  738. This is a forked version of FusionpTraceCOMSuccessfulExitVaBig that we expect to get called.
  739. This function uses about 256 bytes of stack.
  740. FusionpTraceCOMSuccessfulExitVaBug uses about 1k of stack.
  741. */
  742. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  743. CHAR szErrorBuffer[256];
  744. const DWORD dwThreadId = ::GetCurrentThreadId();
  745. CFusionProcessImageFileName ProcessImageFileName;
  746. szErrorBuffer[0] = '\0';
  747. DWORD dwTemp = ::FormatMessageA(
  748. FORMAT_MESSAGE_FROM_SYSTEM |
  749. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  750. NULL, // lpSource - not used with system messages
  751. hrIn, // dwMessageId
  752. 0, // langid - 0 uses system default search path of languages
  753. szErrorBuffer, // lpBuffer
  754. NUMBER_OF(szErrorBuffer), // nSize
  755. NULL); // Arguments
  756. if (dwTemp == 0)
  757. {
  758. ::_snprintf(
  759. szErrorBuffer,
  760. NUMBER_OF(szErrorBuffer),
  761. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  762. hrIn);
  763. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  764. }
  765. PCSTR pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx\n";
  766. FRAME_INFO FrameInfo;
  767. ::FusionpGetActiveFrameInfo(FrameInfo);
  768. ::FusionpDbgPrintEx(
  769. FUSION_DBG_LEVEL_ENTEREXIT,
  770. pszFormatString,
  771. FrameInfo.pszFile,
  772. FrameInfo.nLine,
  773. FrameInfo.pszFunction,
  774. sizeof(PVOID) * CHAR_BIT,
  775. &ProcessImageFileName,
  776. dwThreadId,
  777. hrIn,
  778. szErrorBuffer);
  779. }
  780. void
  781. FusionpTraceCallCOMSuccessfulExitVaBig(
  782. HRESULT hrIn,
  783. LPCSTR pszMsg,
  784. va_list ap
  785. )
  786. {
  787. /*
  788. This is a forked version of FusionpTraceCOMSuccessfulExitVaSmall that we don't expect to get called.
  789. FusionpTraceCOMSuccessfulExitVaSmall uses about 256 bytes of stack.
  790. This function uses about 1k of stack.
  791. */
  792. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  793. CHAR szMsgBuffer[128];
  794. CHAR szErrorBuffer[128];
  795. CHAR szOutputBuffer[256];
  796. PCSTR pszFormatString = NULL;
  797. const DWORD dwThreadId = ::GetCurrentThreadId();
  798. FRAME_INFO FrameInfo;
  799. CFusionProcessImageFileName ProcessImageFileName;
  800. szMsgBuffer[0] = '\0';
  801. szErrorBuffer[0] = '\0';
  802. szOutputBuffer[0] = '\0';
  803. DWORD dwTemp = ::FormatMessageA(
  804. FORMAT_MESSAGE_FROM_SYSTEM |
  805. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  806. NULL, // lpSource - not used with system messages
  807. hrIn, // dwMessageId
  808. 0, // langid - 0 uses system default search path of languages
  809. szErrorBuffer, // lpBuffer
  810. NUMBER_OF(szErrorBuffer), // nSize
  811. NULL); // Arguments
  812. if (dwTemp == 0)
  813. {
  814. ::_snprintf(
  815. szErrorBuffer,
  816. NUMBER_OF(szErrorBuffer),
  817. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  818. hrIn);
  819. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  820. }
  821. szMsgBuffer[0] = '\0';
  822. if (pszMsg != NULL)
  823. {
  824. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s) %s\n";
  825. ::_snprintf(szMsgBuffer, NUMBER_OF(szMsgBuffer), pszMsg, ap);
  826. szMsgBuffer[NUMBER_OF(szMsgBuffer) - 1] = '\0';
  827. }
  828. else
  829. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s)\n";
  830. ::FusionpGetActiveFrameInfo(FrameInfo);
  831. ::_snprintf(szOutputBuffer, NUMBER_OF(szOutputBuffer), pszFormatString, FrameInfo.pszFile,
  832. FrameInfo.nLine, FrameInfo.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName, dwThreadId,
  833. hrIn, szErrorBuffer, szMsgBuffer);
  834. szOutputBuffer[NUMBER_OF(szOutputBuffer) - 1] = '\0';
  835. ::FusionpDbgPrintEx(
  836. FUSION_DBG_LEVEL_ENTEREXIT,
  837. "%s",
  838. szOutputBuffer);
  839. if ((s_hFile != NULL) && (s_hFile != INVALID_HANDLE_VALUE))
  840. {
  841. DWORD cBytesWritten = 0;
  842. if (!::WriteFile(s_hFile, szOutputBuffer, static_cast<DWORD>((::strlen(szOutputBuffer) + 1) * sizeof(CHAR)), &cBytesWritten, NULL))
  843. {
  844. // Avoid infinite loop if s_hFile is trashed...
  845. HANDLE hFileSaved = s_hFile;
  846. s_hFile = NULL;
  847. TRACE_WIN32_FAILURE_ORIGINATION(WriteFile);
  848. s_hFile = hFileSaved;
  849. }
  850. }
  851. }
  852. void
  853. FusionpTraceCallCOMSuccessfulExitVa(
  854. HRESULT hrIn,
  855. LPCSTR pszMsg,
  856. va_list ap
  857. )
  858. {
  859. /*
  860. This function has been split into FusionpTraceCOMSuccessfulExitVaBig and FusionpTraceCOMSuccessfulExitVaSmall, so that
  861. the usual case uses about 768 fewer bytes on the stack.
  862. */
  863. if ((pszMsg == NULL) &&
  864. ((s_hFile == NULL) ||
  865. (s_hFile == INVALID_HANDLE_VALUE)))
  866. {
  867. ::FusionpTraceCallCOMSuccessfulExitVaBig(hrIn, pszMsg, ap);
  868. }
  869. else
  870. {
  871. ::FusionpTraceCallCOMSuccessfulExitSmall(hrIn);
  872. }
  873. }
  874. void
  875. FusionpTraceCOMFailure(
  876. HRESULT hrIn,
  877. LPCSTR pszMsg,
  878. ...
  879. )
  880. {
  881. va_list ap;
  882. va_start(ap, pszMsg);
  883. ::FusionpTraceCOMFailureVa(hrIn, pszMsg, ap);
  884. va_end(ap);
  885. }
  886. void
  887. FusionpTraceCOMFailureSmall(
  888. HRESULT hrIn
  889. )
  890. {
  891. /*
  892. This is a forked version of FusionpTraceCOMFailureVaBig that we expect to get called.
  893. This function uses about 256 bytes of stack.
  894. FusionpTraceCOMFailureVaBug uses about 1k of stack.
  895. */
  896. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  897. CHAR szErrorBuffer[256];
  898. const DWORD dwThreadId = ::GetCurrentThreadId();
  899. CFusionProcessImageFileName ProcessImageFileName;
  900. szErrorBuffer[0] = '\0';
  901. DWORD dwTemp = ::FormatMessageA(
  902. FORMAT_MESSAGE_FROM_SYSTEM |
  903. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  904. NULL, // lpSource - not used with system messages
  905. hrIn, // dwMessageId
  906. 0, // langid - 0 uses system default search path of languages
  907. szErrorBuffer, // lpBuffer
  908. NUMBER_OF(szErrorBuffer), // nSize
  909. NULL); // Arguments
  910. if (dwTemp == 0)
  911. {
  912. ::_snprintf(
  913. szErrorBuffer,
  914. NUMBER_OF(szErrorBuffer),
  915. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  916. hrIn);
  917. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  918. }
  919. PCSTR pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx\n";
  920. FRAME_INFO FrameInfo;
  921. ::FusionpGetActiveFrameInfo(FrameInfo);
  922. ::FusionpDbgPrintEx(
  923. FUSION_DBG_LEVEL_ERROREXITPATH,
  924. pszFormatString,
  925. FrameInfo.pszFile,
  926. FrameInfo.nLine,
  927. FrameInfo.pszFunction,
  928. sizeof(PVOID) * CHAR_BIT,
  929. &ProcessImageFileName,
  930. dwThreadId,
  931. hrIn,
  932. szErrorBuffer);
  933. }
  934. void
  935. FusionpTraceCOMFailureVaBig(
  936. HRESULT hrIn,
  937. LPCSTR pszMsg,
  938. va_list ap
  939. )
  940. {
  941. /*
  942. This is a forked version of FusionpTraceCOMFailureVaSmall that we don't expect to get called.
  943. FusionpTraceCOMFailureVaSmall uses about 256 bytes of stack.
  944. This function uses about 1k of stack.
  945. */
  946. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  947. CHAR szMsgBuffer[256];
  948. CHAR szErrorBuffer[256];
  949. CHAR szOutputBuffer[512];
  950. PCSTR pszFormatString = NULL;
  951. const DWORD dwThreadId = ::GetCurrentThreadId();
  952. FRAME_INFO FrameInfo;
  953. CFusionProcessImageFileName ProcessImageFileName;
  954. szMsgBuffer[0] = '\0';
  955. szErrorBuffer[0] = '\0';
  956. szOutputBuffer[0] = '\0';
  957. DWORD dwTemp = ::FormatMessageA(
  958. FORMAT_MESSAGE_FROM_SYSTEM |
  959. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  960. NULL, // lpSource - not used with system messages
  961. hrIn, // dwMessageId
  962. 0, // langid - 0 uses system default search path of languages
  963. szErrorBuffer, // lpBuffer
  964. NUMBER_OF(szErrorBuffer), // nSize
  965. NULL); // Arguments
  966. if (dwTemp == 0)
  967. {
  968. ::_snprintf(
  969. szErrorBuffer,
  970. NUMBER_OF(szErrorBuffer),
  971. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  972. hrIn);
  973. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  974. }
  975. szMsgBuffer[0] = '\0';
  976. if (pszMsg != NULL)
  977. {
  978. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s) %s\n";
  979. ::_snprintf(szMsgBuffer, NUMBER_OF(szMsgBuffer), pszMsg, ap);
  980. szMsgBuffer[NUMBER_OF(szMsgBuffer) - 1] = '\0';
  981. }
  982. else
  983. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s)\n";
  984. ::FusionpGetActiveFrameInfo(FrameInfo);
  985. ::_snprintf(szOutputBuffer, NUMBER_OF(szOutputBuffer), pszFormatString, FrameInfo.pszFile,
  986. FrameInfo.nLine, FrameInfo.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName,
  987. dwThreadId, hrIn, szErrorBuffer, szMsgBuffer);
  988. szOutputBuffer[NUMBER_OF(szOutputBuffer) - 1] = '\0';
  989. ::FusionpDbgPrintEx(
  990. FUSION_DBG_LEVEL_ERROREXITPATH,
  991. "%s",
  992. szOutputBuffer);
  993. if ((s_hFile != NULL) && (s_hFile != INVALID_HANDLE_VALUE))
  994. {
  995. DWORD cBytesWritten = 0;
  996. if (!::WriteFile(s_hFile, szOutputBuffer, static_cast<DWORD>((::strlen(szOutputBuffer) + 1) * sizeof(CHAR)), &cBytesWritten, NULL))
  997. {
  998. // Avoid infinite loop if s_hFile is trashed...
  999. HANDLE hFileSaved = s_hFile;
  1000. s_hFile = NULL;
  1001. TRACE_WIN32_FAILURE_ORIGINATION(WriteFile);
  1002. s_hFile = hFileSaved;
  1003. }
  1004. }
  1005. }
  1006. void
  1007. FusionpTraceCOMFailureVa(
  1008. HRESULT hrIn,
  1009. LPCSTR pszMsg,
  1010. va_list ap
  1011. )
  1012. {
  1013. /*
  1014. This function has been split into FusionpTraceCOMFailureVaBig and FusionpTraceCOMFailureVaSmall, so that
  1015. the usual case uses about 768 fewer bytes on the stack.
  1016. */
  1017. if ((pszMsg == NULL) &&
  1018. ((s_hFile == NULL) ||
  1019. (s_hFile == INVALID_HANDLE_VALUE)))
  1020. {
  1021. ::FusionpTraceCOMFailureVaBig(hrIn, pszMsg, ap);
  1022. }
  1023. else
  1024. {
  1025. ::FusionpTraceCOMFailureSmall(hrIn);
  1026. }
  1027. }
  1028. void
  1029. FusionpTraceCOMFailureOrigination(
  1030. HRESULT hrIn,
  1031. LPCSTR pszMsg,
  1032. ...
  1033. )
  1034. {
  1035. va_list ap;
  1036. va_start(ap, pszMsg);
  1037. ::FusionpTraceCOMFailureOriginationVa(hrIn, pszMsg, ap);
  1038. va_end(ap);
  1039. }
  1040. void
  1041. FusionpTraceCOMFailureOriginationSmall(
  1042. HRESULT hrIn
  1043. )
  1044. {
  1045. /*
  1046. This is a forked version of FusionpTraceCOMFailureVaBig that we expect to get called.
  1047. This function uses about 256 bytes of stack.
  1048. FusionpTraceCOMFailureVaBug uses about 1k of stack.
  1049. */
  1050. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  1051. CHAR szErrorBuffer[256];
  1052. const DWORD dwThreadId = ::GetCurrentThreadId();
  1053. CFusionProcessImageFileName ProcessImageFileName;
  1054. szErrorBuffer[0] = '\0';
  1055. DWORD dwTemp = ::FormatMessageA(
  1056. FORMAT_MESSAGE_FROM_SYSTEM |
  1057. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  1058. NULL, // lpSource - not used with system messages
  1059. hrIn, // dwMessageId
  1060. 0, // langid - 0 uses system default search path of languages
  1061. szErrorBuffer, // lpBuffer
  1062. NUMBER_OF(szErrorBuffer), // nSize
  1063. NULL); // Arguments
  1064. if (dwTemp == 0)
  1065. {
  1066. ::_snprintf(
  1067. szErrorBuffer,
  1068. NUMBER_OF(szErrorBuffer),
  1069. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  1070. hrIn);
  1071. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  1072. }
  1073. PCSTR pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx\n";
  1074. FRAME_INFO FrameInfo;
  1075. ::FusionpGetActiveFrameInfo(FrameInfo);
  1076. ::FusionpDbgPrintEx(FUSION_DBG_LEVEL_ERROR, pszFormatString, FrameInfo.pszFile,
  1077. FrameInfo.nLine, FrameInfo.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName,
  1078. dwThreadId, hrIn, szErrorBuffer);
  1079. }
  1080. void
  1081. FusionpTraceCOMFailureOriginationVaBig(
  1082. HRESULT hrIn,
  1083. LPCSTR pszMsg,
  1084. va_list ap
  1085. )
  1086. {
  1087. /*
  1088. This is a forked version of FusionpTraceCOMFailureVaSmall that we don't expect to get called.
  1089. FusionpTraceCOMFailureVaSmall uses about 256 bytes of stack.
  1090. This function uses about 1k of stack.
  1091. */
  1092. FUSIONP_SUPPRESS_ERROR_REPORT_IN_OS_SETUP(hrIn);
  1093. CHAR szMsgBuffer[256];
  1094. CHAR szErrorBuffer[256];
  1095. CHAR szOutputBuffer[512];
  1096. PCSTR pszFormatString = NULL;
  1097. const DWORD dwThreadId = ::GetCurrentThreadId();
  1098. FRAME_INFO FrameInfo;
  1099. CFusionProcessImageFileName ProcessImageFileName;
  1100. szMsgBuffer[0] = '\0';
  1101. szErrorBuffer[0] = '\0';
  1102. szOutputBuffer[0] = '\0';
  1103. DWORD dwTemp = ::FormatMessageA(
  1104. FORMAT_MESSAGE_FROM_SYSTEM |
  1105. FORMAT_MESSAGE_MAX_WIDTH_MASK, // dwFlags
  1106. NULL, // lpSource - not used with system messages
  1107. hrIn, // dwMessageId
  1108. 0, // langid - 0 uses system default search path of languages
  1109. szErrorBuffer, // lpBuffer
  1110. NUMBER_OF(szErrorBuffer), // nSize
  1111. NULL); // Arguments
  1112. if (dwTemp == 0)
  1113. {
  1114. ::_snprintf(
  1115. szErrorBuffer,
  1116. NUMBER_OF(szErrorBuffer),
  1117. "<Untranslatable(non-existed or too long) HRESULT: 0x%08lx>",
  1118. hrIn);
  1119. szErrorBuffer[NUMBER_OF(szErrorBuffer) - 1] = '\0';
  1120. }
  1121. szMsgBuffer[0] = '\0';
  1122. if (pszMsg != NULL)
  1123. {
  1124. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s) %s\n";
  1125. ::_snprintf(szMsgBuffer, NUMBER_OF(szMsgBuffer), pszMsg, ap);
  1126. szMsgBuffer[NUMBER_OF(szMsgBuffer) - 1] = '\0';
  1127. }
  1128. else
  1129. pszFormatString = "%s(%d): [function %s %Iubit process %wZ tid 0x%lx] COM Error 0x%08lx (%s)\n";
  1130. ::FusionpGetActiveFrameInfo(FrameInfo);
  1131. ::_snprintf(szOutputBuffer, NUMBER_OF(szOutputBuffer), pszFormatString, FrameInfo.pszFile,
  1132. FrameInfo.nLine, FrameInfo.pszFunction, sizeof(PVOID) * CHAR_BIT, &ProcessImageFileName,
  1133. dwThreadId, hrIn, szErrorBuffer, szMsgBuffer);
  1134. szOutputBuffer[NUMBER_OF(szOutputBuffer) - 1] = '\0';
  1135. ::FusionpDbgPrintEx(
  1136. FUSION_DBG_LEVEL_ERROR,
  1137. "%s",
  1138. szOutputBuffer);
  1139. if ((s_hFile != NULL) && (s_hFile != INVALID_HANDLE_VALUE))
  1140. {
  1141. DWORD cBytesWritten = 0;
  1142. if (!::WriteFile(s_hFile, szOutputBuffer, static_cast<DWORD>((::strlen(szOutputBuffer) + 1) * sizeof(CHAR)), &cBytesWritten, NULL))
  1143. {
  1144. // Avoid infinite loop if s_hFile is trashed...
  1145. HANDLE hFileSaved = s_hFile;
  1146. s_hFile = NULL;
  1147. TRACE_WIN32_FAILURE_ORIGINATION(WriteFile);
  1148. s_hFile = hFileSaved;
  1149. }
  1150. }
  1151. }
  1152. void
  1153. FusionpTraceCOMFailureOriginationVa(
  1154. HRESULT hrIn,
  1155. LPCSTR pszMsg,
  1156. va_list ap
  1157. )
  1158. {
  1159. /*
  1160. This function has been split into FusionpTraceCOMFailureVaBig and FusionpTraceCOMFailureVaSmall, so that
  1161. the usual case uses about 768 fewer bytes on the stack.
  1162. */
  1163. if ((pszMsg == NULL) &&
  1164. ((s_hFile == NULL) ||
  1165. (s_hFile == INVALID_HANDLE_VALUE)))
  1166. {
  1167. ::FusionpTraceCOMFailureOriginationVaBig(hrIn, pszMsg, ap);
  1168. }
  1169. else
  1170. {
  1171. ::FusionpTraceCOMFailureOriginationSmall(hrIn);
  1172. }
  1173. }
  1174. struct ILogFile;
  1175. // --------------------------------------------------------------------------------
  1176. // TRACEMACROTYPE
  1177. // --------------------------------------------------------------------------------
  1178. typedef enum tagTRACEMACROTYPE {
  1179. TRACE_INFO,
  1180. TRACE_CALL,
  1181. TRACE_RESULT
  1182. } TRACEMACROTYPE;
  1183. // --------------------------------------------------------------------------------
  1184. // These Traces are for c++ only
  1185. // --------------------------------------------------------------------------------
  1186. typedef DWORD SHOWTRACEMASK;
  1187. #define SHOW_TRACE_NONE 0x00000000
  1188. #define SHOW_TRACE_INFO 0x00000001
  1189. #define SHOW_TRACE_CALL 0x00000002
  1190. #define SHOW_TRACE_ALL 0xffffffff
  1191. // --------------------------------------------------------------------------------
  1192. // TRACELOGINFOINFO
  1193. // --------------------------------------------------------------------------------
  1194. typedef struct tagTRACELOGINFO {
  1195. SHOWTRACEMASK dwMask;
  1196. ILogFile *pLog;
  1197. } TRACELOGINFO, *LPTRACELOGINFO;
  1198. // function to make directdb happy
  1199. HRESULT DebugTraceEx(SHOWTRACEMASK dwMask, TRACEMACROTYPE tracetype, LPTRACELOGINFO pLog,
  1200. HRESULT hr, LPSTR pszFile, INT nLine, LPCSTR pszMsg, LPCSTR pszFunc)
  1201. {
  1202. return hr;
  1203. }
  1204. void
  1205. FusionpTraceCallEntry()
  1206. {
  1207. FRAME_INFO FrameInfo;
  1208. if (::FusionpGetActiveFrameInfo(FrameInfo))
  1209. {
  1210. ::FusionpDbgPrintEx(
  1211. FUSION_DBG_LEVEL_ENTEREXIT,
  1212. "%s(%d): Entered %s\n",
  1213. FrameInfo.pszFile,
  1214. FrameInfo.nLine,
  1215. FrameInfo.pszFunction);
  1216. }
  1217. }
  1218. void
  1219. FusionpTraceCallExit()
  1220. {
  1221. FRAME_INFO FrameInfo;
  1222. if (::FusionpGetActiveFrameInfo(FrameInfo))
  1223. {
  1224. ::FusionpDbgPrintEx(
  1225. FUSION_DBG_LEVEL_ENTEREXIT,
  1226. "%s(%d): Exited %s\n",
  1227. FrameInfo.pszFile,
  1228. FrameInfo.nLine,
  1229. FrameInfo.pszFunction);
  1230. }
  1231. }
  1232. void
  1233. FusionpTraceCallSuccessfulExitVa(
  1234. PCSTR szFormat,
  1235. va_list ap
  1236. )
  1237. {
  1238. FRAME_INFO FrameInfo;
  1239. if (::FusionpGetActiveFrameInfo(FrameInfo))
  1240. {
  1241. CHAR Buffer[256];
  1242. Buffer[0] = '\0';
  1243. if (szFormat != NULL)
  1244. {
  1245. ::_vsnprintf(Buffer, NUMBER_OF(Buffer), szFormat, ap);
  1246. Buffer[NUMBER_OF(Buffer) - 1] = '\0';
  1247. }
  1248. ::FusionpDbgPrintEx(
  1249. FUSION_DBG_LEVEL_ENTEREXIT,
  1250. "%s(%d): Successfully exiting %s%s%s\n",
  1251. FrameInfo.pszFile,
  1252. FrameInfo.nLine,
  1253. FrameInfo.pszFunction,
  1254. Buffer[0] == '\0' ? "" : " - ",
  1255. Buffer);
  1256. }
  1257. }
  1258. void
  1259. FusionpTraceCallSuccessfulExit(
  1260. PCSTR szFormat,
  1261. ...
  1262. )
  1263. {
  1264. va_list ap;
  1265. va_start(ap, szFormat);
  1266. ::FusionpTraceCallSuccessfulExitVa(szFormat, ap);
  1267. va_end(ap);
  1268. }
  1269. void
  1270. FusionpTraceCallWin32UnsuccessfulExitVa(
  1271. DWORD dwError,
  1272. PCSTR szFormat,
  1273. va_list ap
  1274. )
  1275. {
  1276. FRAME_INFO FrameInfo;
  1277. if (::FusionpGetActiveFrameInfo(FrameInfo))
  1278. {
  1279. ::FusionpTraceWin32FailureVa(
  1280. FrameInfo,
  1281. dwError,
  1282. szFormat,
  1283. ap);
  1284. }
  1285. }
  1286. void
  1287. FusionpTraceCallWin32UnsuccessfulExit(
  1288. DWORD dwError,
  1289. PCSTR szFormat,
  1290. ...
  1291. )
  1292. {
  1293. va_list ap;
  1294. va_start(ap, szFormat);
  1295. ::FusionpTraceCallWin32UnsuccessfulExitVa(dwError, szFormat, ap);
  1296. va_end(ap);
  1297. }
  1298. void
  1299. FusionpTraceCallCOMUnsuccessfulExitVa(
  1300. HRESULT hrError,
  1301. PCSTR szFormat,
  1302. va_list ap
  1303. )
  1304. {
  1305. ::FusionpTraceCOMFailureVa(
  1306. hrError,
  1307. szFormat,
  1308. ap);
  1309. }
  1310. void
  1311. FusionpTraceCallCOMUnsuccessfulExit(
  1312. HRESULT hrError,
  1313. PCSTR szFormat,
  1314. ...
  1315. )
  1316. {
  1317. va_list ap;
  1318. va_start(ap, szFormat);
  1319. ::FusionpTraceCallCOMUnsuccessfulExitVa(hrError, szFormat, ap);
  1320. va_end(ap);
  1321. }
  1322. #if FUSION_FREEZE_STACK_ENABLED
  1323. BOOL
  1324. FusionpFreezeStack(
  1325. DWORD dwFlags,
  1326. IN PFROZEN_STACK pFrozenStack
  1327. )
  1328. {
  1329. BOOL bSuccess = FALSE;
  1330. PTRACECONTEXT pStackCursor = NULL;
  1331. //
  1332. // If they supplied a frozen stack structure, then start it out as having
  1333. // zero depth.
  1334. //
  1335. if ( pFrozenStack ) pFrozenStack->ulDepth = 0;
  1336. //
  1337. // No frozen stack, or flags != 0 is an error.
  1338. //
  1339. if ( !pFrozenStack || ( dwFlags != 0 ) ) {
  1340. ::SetLastError( ERROR_INVALID_PARAMETER );
  1341. goto Exit;
  1342. }
  1343. //
  1344. // If there's no stack so far, then we're done here.
  1345. //
  1346. if ( !ptcs || !ptcs->m_StackHead )
  1347. {
  1348. bSuccess = TRUE;
  1349. goto Exit;
  1350. }
  1351. if ( pFrozenStack->ulMaxDepth < ptcs->m_StackDepth )
  1352. {
  1353. pFrozenStack->ulMaxDepth = ptcs->m_StackDepth;
  1354. ::SetLastError( ERROR_INSUFFICIENT_BUFFER );
  1355. goto Exit;
  1356. }
  1357. pStackCursor = ptcs->m_StackHead;
  1358. while ( pStackCursor && ( pFrozenStack->ulDepth < pFrozenStack->ulMaxDepth ) )
  1359. {
  1360. pFrozenStack->Contexts[pFrozenStack->ulDepth] = *pStackCursor;
  1361. //
  1362. // This little bit verifies that the pointers we have in the stack frame
  1363. // are really inside our process. We need to do this so that when we go
  1364. // and store them (actually above) for later, we are sure to clear ones
  1365. // that aren't under our control.
  1366. //
  1367. // Since no processes have their base address at NULL, we can use this
  1368. // test to ensure that the basic information has been set up. Cases
  1369. // in which this is not set up include running in sxstest or in
  1370. // another module that doesn't call VirtualQueryEx to find out this
  1371. // information.
  1372. //
  1373. /* if ( g_SxsDllMemoryBasicInformation.BaseAddress != NULL )
  1374. {
  1375. PBYTE pvBase = (PBYTE)g_SxsDllMemoryBasicInformation.AllocationBase;
  1376. PBYTE pvLimit = pvBase + g_SxsDllMemoryBasicInformation.RegionSize;
  1377. #define PTR_IN_RANGE_CHECK( member, parent, target, base, limit ) \
  1378. { PVOID pv = (PVOID)((parent).##member); if ( ( pv < base ) || ( pv > limit ) ) (target).##member = NULL; }
  1379. PTR_IN_RANGE_CHECK( m_szComponentName, *pStackCursor, pFrozenStack->Contexts[pFrozenStack->ulDepth], pvBase, pvLimit )
  1380. PTR_IN_RANGE_CHECK( m_szFile, *pStackCursor, pFrozenStack->Contexts[pFrozenStack->ulDepth], pvBase, pvLimit );
  1381. PTR_IN_RANGE_CHECK( m_szFunctionName, *pStackCursor, pFrozenStack->Contexts[pFrozenStack->ulDepth], pvBase, pvLimit );
  1382. #undef PTR_IN_RANGE_CHECK
  1383. }
  1384. */
  1385. pStackCursor = pStackCursor->m_pCtxOld;
  1386. pFrozenStack->ulDepth++;
  1387. }
  1388. bSuccess = TRUE;
  1389. Exit:
  1390. return bSuccess;
  1391. }
  1392. #endif // FUSION_FREEZE_STACK_ENABLED
  1393. VOID
  1394. FusionpDumpStack(
  1395. IN DWORD dwFlags,
  1396. IN ULONG ulLevel,
  1397. IN PCWSTR pcwszLinePrefix,
  1398. IN ULONG ulStackDepth
  1399. )
  1400. {
  1401. ULONG ulCurrentFrameDepth = 0;
  1402. ULONG ulFormat = FUSIONP_DUMP_STACK_FORMAT_MEDIUM;
  1403. PCTEB_ACTIVE_FRAME ptaf = NULL;
  1404. if (dwFlags == 0)
  1405. {
  1406. dwFlags = FUSIONP_DUMP_STACK_FORMAT_MEDIUM;
  1407. }
  1408. else if ((dwFlags & ~(FUSIONP_DUMP_STACK_FORMAT_MASK)) != 0)
  1409. {
  1410. #if DBG
  1411. OutputDebugStringA("SXS.DLL: Someone called FusionpDumpStack with invalid parameters!\n");
  1412. DebugBreak();
  1413. #endif
  1414. return;
  1415. }
  1416. ulFormat = (dwFlags & FUSIONP_DUMP_STACK_FORMAT_MASK);
  1417. if ((ulFormat != FUSIONP_DUMP_STACK_FORMAT_SHORT) &&
  1418. (ulFormat != FUSIONP_DUMP_STACK_FORMAT_MEDIUM) &&
  1419. (ulFormat != FUSIONP_DUMP_STACK_FORMAT_LONG))
  1420. {
  1421. #if DBG
  1422. OutputDebugStringA("Invalid format passed in call to FusionpDumpStack()\n");
  1423. DebugBreak();
  1424. #endif
  1425. return;
  1426. }
  1427. if (pcwszLinePrefix == NULL)
  1428. pcwszLinePrefix = L"SXS";
  1429. #if FUSION_WIN
  1430. ptaf = ::RtlGetFrame();
  1431. #else
  1432. ptaf = NULL;
  1433. #endif
  1434. while ((ptaf != NULL) && ulStackDepth--)
  1435. {
  1436. FRAME_INFO FrameInfo;
  1437. ::FusionpPopulateFrameInfo(FrameInfo, ptaf);
  1438. switch (dwFlags & FUSIONP_DUMP_STACK_FORMAT_MASK)
  1439. {
  1440. case FUSIONP_DUMP_STACK_FORMAT_SHORT:
  1441. ::FusionpDbgPrintEx(
  1442. ulLevel,
  1443. "%ls: %s\n",
  1444. pcwszLinePrefix,
  1445. FrameInfo.pszFunction);
  1446. break;
  1447. case FUSIONP_DUMP_STACK_FORMAT_MEDIUM:
  1448. ::FusionpDbgPrintEx(
  1449. ulLevel,
  1450. "%ls%s: %s (Line %d)\n",
  1451. pcwszLinePrefix,
  1452. FrameInfo.pszFile,
  1453. FrameInfo.pszFunction,
  1454. FrameInfo.nLine);
  1455. break;
  1456. case FUSIONP_DUMP_STACK_FORMAT_LONG:
  1457. ::FusionpDbgPrintEx(
  1458. ulLevel,
  1459. "%lsFunction %s called from file %s line %d (depth %lu)\n",
  1460. pcwszLinePrefix,
  1461. FrameInfo.pszFunction,
  1462. FrameInfo.pszFile,
  1463. FrameInfo.nLine,
  1464. ulCurrentFrameDepth++);
  1465. break;
  1466. }
  1467. ptaf = ptaf->Previous;
  1468. }
  1469. }
  1470. #if FUSION_ENABLE_FROZEN_STACK
  1471. BOOL
  1472. FusionpOutputFrozenStack(
  1473. DWORD dwFlags,
  1474. PCSTR Prefix,
  1475. PFROZEN_STACK pFrozenStack
  1476. )
  1477. {
  1478. BOOL bSuccess = FALSE;
  1479. if ( !pFrozenStack ) {
  1480. ::SetLastError( ERROR_INVALID_PARAMETER );
  1481. goto Exit;
  1482. }
  1483. if ( !Prefix ) Prefix = "SXS";
  1484. for ( ULONG ul = 0; ul < pFrozenStack->ulDepth; ul++ )
  1485. {
  1486. FusionpDbgPrintEx(
  1487. dwFlags,
  1488. "%s: %s [%s(%d)]\n",
  1489. Prefix,
  1490. pFrozenStack->Contexts[ul].m_StaticTraceContext->m_Function,
  1491. pFrozenStack->Contexts[ul].m_StaticTraceContext->m_File,
  1492. pFrozenStack->Contexts[ul].m_nLine);
  1493. }
  1494. bSuccess = TRUE;
  1495. Exit:
  1496. return bSuccess;
  1497. }
  1498. #endif // FUSION_ENABLE_FROZEN_STACK
  1499. #ifdef _SXS_FUTURE_STACK_FREEZING_WORK
  1500. typedef struct _SUPER_FROZEN_STACK
  1501. {
  1502. SIZE_T cStackFrames;
  1503. SIZE_T cMaxStackFrames;
  1504. STACKFRAME StackFrames[1];
  1505. }
  1506. SUPER_FROZEN_STACK, *PSUPER_FROZEN_STACK;
  1507. BOOL
  1508. pResolveLineFromAddress(
  1509. PIMAGEHLP_LINE Line,
  1510. DWORD_PTR Address,
  1511. DWORD *pOffset
  1512. )
  1513. {
  1514. HPROCESS Proc = GetCurrentProcess();
  1515. DWORD Offset = 0;
  1516. while ( !SymGetLineFromAddr( Proc, Address - Offset, pOffset, Line ) )
  1517. {
  1518. if ( Offset++ == MAX_BACKTRACK )
  1519. {
  1520. return FALSE;
  1521. }
  1522. }
  1523. }
  1524. BOOL
  1525. FusionpPrintSuperFrozenStack(
  1526. PSUPER_FROZEN_STACK pStack
  1527. )
  1528. {
  1529. IMAGEHLP_LINE Line;
  1530. for ( SIZE_T cb = 0; cb < pStack->cStackFrames; cb++ )
  1531. {
  1532. IMAGEHLP_LINE Line;
  1533. IMAGEHLP_SYMBOL Symbol;
  1534. Line.SizeOfStuct = sizeof( Line );
  1535. Symbol.SizeOfStruct = sizeof( Symbol );
  1536. if ( pResolveLineFromAddress(
  1537. &Line,
  1538. pStack->StackFrames[cb].AddrPC.Offset
  1539. &dwOffset
  1540. ) )
  1541. }
  1542. }
  1543. BOOL
  1544. FusionpSuperFreezeStack(
  1545. DWORD dwFlags,
  1546. PSUPER_FROZEN_STACK pStack
  1547. )
  1548. {
  1549. STACKFRAME CurrentStack;
  1550. CONTEXT Context;
  1551. BOOL bOk = FALSE;
  1552. const HANDLE hThisThread = ::GetCurrentThread();
  1553. ULONG ulStackSize = 0;
  1554. BOOL bSuccess = FALSE;
  1555. if ( !pStack || dwFlags )
  1556. {
  1557. ::SetLastError( ERROR_INVALID_PARAMETER );
  1558. goto Exit;
  1559. }
  1560. ZeroMemory( &CurrentStack, sizeof(CurrentStack) );
  1561. ZeroMemory( &Context, sizeof(Context) );
  1562. Context.ContextFlags = CONTEXT_FULL;
  1563. GetThreadContext( hThisThread, &Context );
  1564. CurrentStack.AddrPC.Offset = Context.Eip;
  1565. CurrentStack.AddrPC.Mode = AddrModeFlat;
  1566. CurrentStack.AddrStack.Offset = Context.Esp;
  1567. CurrentStack.AddrStack.Mode = AddrModeFlat;
  1568. CurrentStack.AddrFrame.Offset = Context.Ebp;
  1569. CurrentStack.AddrFrame.Mode = AddrModeFlat;
  1570. pStack->cStackFrames = 0;
  1571. for ( ulStackSize = 0; ; ulStackSize++ )
  1572. {
  1573. bOk = ::StackWalk(
  1574. IMAGE_FILE_MACHINE_I386,
  1575. GetCurrentProcess(),
  1576. hThisThread,
  1577. &CurrentStack,
  1578. &Context,
  1579. NULL,
  1580. SymFunctionTableAccess,
  1581. SymGetModuleBase,
  1582. NULL);
  1583. if ( CurrentStack.AddrPC.Offset == 0 )
  1584. {
  1585. break;
  1586. }
  1587. //
  1588. // Skip the first
  1589. //
  1590. else if ( ulStackSize == 0 )
  1591. {
  1592. continue;
  1593. }
  1594. //
  1595. // If we have space in the stack...
  1596. //
  1597. else if ( pStack->cStackFrames < pStack->cMaxStackFrames )
  1598. {
  1599. pStack->StackFrames[pStack->cStackFrames++] = CurrentStack;
  1600. }
  1601. }
  1602. if ( pStack->cMaxStackFrames < ulStackSize )
  1603. {
  1604. pStack->cMaxStackFrames = ulStackSize;
  1605. pStack->cStackFrames = 0;
  1606. ::SetLastError( ERROR_INSUFFICIENT_BUFFER );
  1607. goto Exit;
  1608. }
  1609. bSuccess = TRUE;
  1610. Exit:
  1611. return bSuccess;
  1612. }
  1613. #endif _SXS_FUTURE_STACK_FREEZING_WORK