srvdbg.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. /***********************************************************************
  2. SRVDBG.CPP
  3. Server Debug Support
  4. Copyright (C) 1995 Microsoft Corporation
  5. All rights reserved.
  6. Created on: 05/25/95
  7. ************************************************************************/
  8. //#include "stdafx.h"
  9. #ifndef _WINDOWS_
  10. #define WIN32_LEAN_AND_MEAN
  11. #define STRICT 1
  12. #include <windows.h>
  13. #endif
  14. #include "srvdbg.h"
  15. #include "dbgutil.h"
  16. static HANDLE g_hEventLog = NULL;
  17. BOOL g_fWantInt3 = FALSE;
  18. char g_szDbgModPath[MAX_PATH] = "<Path unknown>";
  19. /***********************************************************************
  20. FUNCTION: SRVDBG_Init
  21. Initialize Server Debugging Support
  22. If NULL is passed for the path, this routine will attempt to
  23. determine the path through GetModuleFileName, which may not be
  24. accurate for DLLs, depending on the calling context of the call
  25. to this routine (won't work for DLLs unless called from ProcessAttach
  26. notification).
  27. Created on: 05/26/95
  28. ************************************************************************/
  29. BOOL SRVDBG_Init(
  30. LPSTR lpszSource,
  31. LPSTR lpszPath)
  32. {
  33. char szKey[ 128 ];
  34. HKEY hk = NULL;
  35. g_fWantInt3 = FALSE;
  36. //
  37. // Check the registry for whether or not we want override the passed in fWantInt3 flag. Stored at DWORD key at:
  38. // HKLM\\System\\CurrentControlSet\Services\\Sentinal\\WantInt3
  39. //
  40. // If a key is missing, it isn't used (i.e. if there's no key in the registry, default to False.
  41. //
  42. wsprintf(szKey, "System\\CurrentControlSet\\Services\\Sentinal");
  43. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, szKey, &hk))
  44. {
  45. BOOL f;
  46. DWORD dw = sizeof(f);
  47. if (ERROR_SUCCESS == RegQueryValueEx(hk, "fWantInt3", NULL, NULL, (LPBYTE) &f, &dw))
  48. {
  49. g_fWantInt3 = f;
  50. }
  51. RegCloseKey(hk);
  52. }
  53. if ( !lpszSource )
  54. return ( FALSE );
  55. if (!lpszPath)
  56. GetModuleFileName(NULL, g_szDbgModPath, sizeof(g_szDbgModPath));
  57. else
  58. lstrcpy(g_szDbgModPath, lpszPath);
  59. Assert(!g_hEventLog);
  60. g_hEventLog = RegisterEventSource( NULL, lpszSource );
  61. return ( g_hEventLog ? TRUE : FALSE );
  62. }
  63. /***********************************************************************
  64. FUNCTION: SRVDBG_Terminate
  65. Terminate Server Debugging Support
  66. Created on: 05/26/95
  67. ************************************************************************/
  68. BOOL SRVDBG_Terminate( void )
  69. {
  70. if ( !g_hEventLog )
  71. return ( FALSE );
  72. BOOL fDeregisterEventSource = DeregisterEventSource( g_hEventLog );
  73. Assert(fDeregisterEventSource);
  74. g_hEventLog = NULL;
  75. return fDeregisterEventSource;
  76. }
  77. /***********************************************************************
  78. FUNCTION: SRVDBG_ClearLog
  79. Clear debug event log. SRVDBG_Init must be called first.
  80. Created on: 05/26/95
  81. ************************************************************************/
  82. BOOL SRVDBG_ClearLog( void )
  83. {
  84. if ( !g_hEventLog )
  85. return ( FALSE );
  86. return ( ClearEventLog( g_hEventLog, NULL ) );
  87. }
  88. /***********************************************************************
  89. FUNCTION: SRVDBG_Error
  90. Definition: Log error event SRVDBG_Init must be called first.
  91. Created on: 12/09/97
  92. Comment: This was a macro before.
  93. ************************************************************************/
  94. void SRVDBG_Error( LPCSTR lpsz )
  95. {
  96. SRVDBG_ReportEvent( SRVDBG_ERROR_TYPE, SRVDBG_ERROR, lpsz, NULL, NULL );
  97. }
  98. /***********************************************************************
  99. FUNCTION: SRVDBG_Error2
  100. Definition: Log error event SRVDBG_Init must be called first.
  101. Created on: 12/09/97
  102. Comment: This was a macro before.
  103. ************************************************************************/
  104. void SRVDBG_Error2( LPCSTR lpsz, LPCSTR lpsz2)
  105. {
  106. SRVDBG_ReportEvent( SRVDBG_ERROR_TYPE, SRVDBG_ERROR, lpsz, lpsz2, NULL );
  107. }
  108. /***********************************************************************
  109. FUNCTION: SRVDBG_Error3
  110. Definition: Log error event SRVDBG_Init must be called first.
  111. Created on: 12/09/97
  112. Comment: This was a macro before.
  113. ************************************************************************/
  114. void SRVDBG_Error3( LPCSTR lpsz, LPCSTR lpsz2, LPCSTR lpsz3)
  115. {
  116. SRVDBG_ReportEvent( SRVDBG_ERROR_TYPE, SRVDBG_ERROR, lpsz, lpsz2, lpsz3 );
  117. }
  118. /***********************************************************************
  119. FUNCTION: SRVDBG_Info
  120. Definition: Log error event SRVDBG_Init must be called first.
  121. Created on: 12/09/97
  122. Comment: This was a macro before.
  123. ************************************************************************/
  124. void SRVDBG_Info( LPCSTR lpsz )
  125. {
  126. SRVDBG_ReportEvent( SRVDBG_INFO_TYPE, SRVDBG_INFO, lpsz, NULL, NULL );
  127. }
  128. /***********************************************************************
  129. FUNCTION: SRVDBG_Info2
  130. Definition: Log error event SRVDBG_Init must be called first.
  131. Created on: 12/09/97
  132. Comment: This was a macro before.
  133. ************************************************************************/
  134. void SRVDBG_Info2( LPCSTR lpsz, LPCSTR lpsz2 )
  135. {
  136. SRVDBG_ReportEvent( SRVDBG_INFO_TYPE, SRVDBG_INFO, lpsz, lpsz2, NULL );
  137. }
  138. /***********************************************************************
  139. FUNCTION: SRVDBG_Info3
  140. Definition: Log error event SRVDBG_Init must be called first.
  141. Created on: 12/09/97
  142. Comment: This was a macro before.
  143. ************************************************************************/
  144. void SRVDBG_Info3( LPCSTR lpsz, LPCSTR lpsz2, LPCSTR lpsz3 )
  145. {
  146. SRVDBG_ReportEvent( SRVDBG_INFO_TYPE, SRVDBG_INFO, lpsz, lpsz2, lpsz3 );
  147. }
  148. /***********************************************************************
  149. FUNCTION: SRVDBG_Warning
  150. Definition: Log error event SRVDBG_Init must be called first.
  151. Created on: 12/09/97
  152. Comment: This was a macro before.
  153. ************************************************************************/
  154. void SRVDBG_Warning( LPCSTR lpsz )
  155. {
  156. SRVDBG_ReportEvent( SRVDBG_WARNING_TYPE, SRVDBG_WARNING, lpsz, NULL, NULL );
  157. }
  158. /***********************************************************************
  159. FUNCTION: SRVDBG_Warning2
  160. Definition: Log error event SRVDBG_Init must be called first.
  161. Created on: 12/09/97
  162. Comment: This was a macro before.
  163. ************************************************************************/
  164. void SRVDBG_Warning2( LPCSTR lpsz, LPCSTR lpsz2 )
  165. {
  166. SRVDBG_ReportEvent( SRVDBG_WARNING_TYPE, SRVDBG_WARNING, lpsz, lpsz2, NULL );
  167. }
  168. /***********************************************************************
  169. FUNCTION: SRVDBG_Warning3
  170. Definition: Log error event SRVDBG_Init must be called first.
  171. Created on: 12/09/97
  172. Comment: This was a macro before.
  173. ************************************************************************/
  174. void SRVDBG_Warning3( LPCSTR lpsz, LPCSTR lpsz2, LPCSTR lpsz3 )
  175. {
  176. SRVDBG_ReportEvent( SRVDBG_WARNING_TYPE, SRVDBG_WARNING, lpsz, lpsz2, lpsz3 );
  177. }
  178. void SRVDBG_ErrorEvt( DWORD IDEvent, LPCSTR lpsz )
  179. {
  180. SRVDBG_ReportEvent( SRVDBG_ERROR_TYPE, IDEvent, lpsz, NULL, NULL );
  181. }
  182. void SRVDBG_WarningEvt( DWORD IDEvent, LPCSTR lpsz )
  183. {
  184. SRVDBG_ReportEvent( SRVDBG_WARNING_TYPE, IDEvent, lpsz, NULL, NULL );
  185. }
  186. void SRVDBG_InfoEvt( DWORD IDEvent, LPCSTR lpsz )
  187. {
  188. SRVDBG_ReportEvent( SRVDBG_INFO_TYPE, IDEvent, lpsz, NULL, NULL );
  189. }
  190. void SRVDBG_Assert( LPCSTR lpsz )
  191. {
  192. SRVDBG_ErrorEvt( SRVDBG_ASSERT, lpsz );
  193. }
  194. /***********************************************************************
  195. FUNCTION: SBRDBG_ReportEvent
  196. Report error, warning, or information. SRVDBG_Init must be called first.
  197. History
  198. Created on: 05/26/95
  199. 06/05/96 cmason Added special support for getting Assert's logged
  200. into the QScript Thread Local Storage trave buffer
  201. so that on Aborts and Exceptions, the Assert will
  202. show up in the dump of the trace buffer.
  203. ************************************************************************/
  204. BOOL SRVDBG_ReportEvent(
  205. WORD fwEventType,
  206. DWORD IDEvent,
  207. LPCSTR lpsz,
  208. LPCSTR lpsz2,
  209. LPCSTR lpsz3)
  210. {
  211. LPCSTR plpszT[5];
  212. WORD cStrings;
  213. BOOL fSuccess;
  214. cStrings = 5;
  215. plpszT[0] = g_szDbgModPath;
  216. plpszT[1] = ""; // was product id
  217. plpszT[2] = lpsz ? lpsz : "";
  218. plpszT[3] = lpsz2 ? lpsz2 : "";
  219. plpszT[4] = lpsz3 ? lpsz3 : "";
  220. #if 0
  221. // go ahead and send the event to anyone watching debug output
  222. for (int i=0; i<cStrings; i++)
  223. {
  224. if (*plpszT[i])
  225. {
  226. if( SRVDBG_ASSERT == IDEvent )
  227. {
  228. TraceN1( "%s ", plpszT[i] );
  229. }
  230. else
  231. {
  232. ODS(plpszT[i]);
  233. ODS(" ");
  234. }
  235. }
  236. }
  237. if( SRVDBG_ASSERT == IDEvent )
  238. {
  239. Trace0( "\r\n" );
  240. }
  241. else
  242. {
  243. ODS("\r\n");
  244. }
  245. #endif
  246. switch ( fwEventType )
  247. {
  248. case SRVDBG_INFO_TYPE:
  249. case SRVDBG_WARNING_TYPE:
  250. break;
  251. case SRVDBG_ERROR_TYPE:
  252. if (g_fWantInt3)
  253. {
  254. //
  255. // 06/13/96 cmason Will only break into a debugger if one is
  256. // running. If not running under a debugger, does nothing.
  257. //
  258. __try
  259. {
  260. _asm { int 3 };
  261. }
  262. __except (EXCEPTION_EXECUTE_HANDLER)
  263. {
  264. }
  265. }
  266. //ExitProcess(1);
  267. break;
  268. }
  269. //
  270. // 05/29/96 cmason Moved check to bottom of function so that Asserts still work even it
  271. // SRVDBG could not init the event log.
  272. // 09/08/96 garrettm If no event source, we try to create one on the fly...
  273. //
  274. if ( !g_hEventLog )
  275. {
  276. HANDLE hLog = RegisterEventSource(NULL, "UNKNOWN");
  277. if (hLog)
  278. {
  279. ReportEvent( hLog, fwEventType, 0, IDEvent, NULL, cStrings, 0, plpszT, NULL );
  280. DeregisterEventSource( hLog );
  281. }
  282. return ( FALSE );
  283. }
  284. fSuccess = ReportEvent( g_hEventLog, fwEventType, 0, IDEvent, NULL,
  285. cStrings, 0, plpszT, NULL );
  286. return ( fSuccess );
  287. }
  288. void SRVDBG_ErrorBinary(LPCSTR lpsz, LPCSTR lpsz2, LPCSTR lpsz3, DWORD dwDataSize, LPVOID lpRawData )
  289. {
  290. SRVDBG_ReportEventBinary(SRVDBG_ERROR_TYPE, SRVDBG_ERROR, lpsz, lpsz2, lpsz3, dwDataSize, (LPVOID)lpRawData);
  291. }
  292. void SRVDBG_WarningBinary( LPCSTR lpsz, LPCSTR lpsz2, LPCSTR lpsz3, DWORD dwDataSize, LPVOID lpRawData )
  293. {
  294. SRVDBG_ReportEventBinary( SRVDBG_WARNING_TYPE, SRVDBG_WARNING, lpsz, lpsz2, lpsz3, dwDataSize, (LPVOID)lpRawData );
  295. }
  296. void SRVDBG_InfoBinary( LPCSTR lpsz, LPCSTR lpsz2, LPCSTR lpsz3, DWORD dwDataSize, LPVOID lpRawData )
  297. {
  298. SRVDBG_ReportEventBinary( SRVDBG_INFO_TYPE, SRVDBG_INFO, lpsz, lpsz2, lpsz3, dwDataSize, (LPVOID)lpRawData );
  299. }
  300. void SRVDBG_RebootMachine()
  301. {
  302. SRVDBG_ReportEvent( SRVDBG_ERROR_TYPE, SRVDBG_ERROR, "Reboot Machine", NULL, NULL );
  303. }
  304. void SRVDBG_RestartService( LPCSTR lpsz )
  305. {
  306. SRVDBG_ReportEvent( SRVDBG_ERROR_TYPE, SRVDBG_ERROR, "Restart Service", lpsz, NULL );
  307. }
  308. /***********************************************************************
  309. FUNCTION: SBRDBG_ReportEventBinary
  310. Report error, warning, or information in binary form.
  311. SRVDBG_Init must be called first.
  312. History
  313. 04/14/97 cmason Created to allow us to log larger pieces of information
  314. than allowed in the Event Log with strings.
  315. ************************************************************************/
  316. BOOL SRVDBG_ReportEventBinary
  317. (
  318. WORD fwEventType,
  319. DWORD IDEvent,
  320. LPCSTR lpsz,
  321. LPCSTR lpsz2,
  322. LPCSTR lpsz3,
  323. DWORD dwDataSize,
  324. LPVOID lpRawData
  325. )
  326. {
  327. const WORD cStrings = 5;
  328. LPCSTR plpszT[cStrings];
  329. BOOL fSuccess;
  330. plpszT[0] = g_szDbgModPath;
  331. plpszT[1] = ""; // was productid
  332. plpszT[2] = lpsz ? lpsz : "";
  333. plpszT[3] = lpsz2 ? lpsz2 : "";
  334. plpszT[4] = lpsz3 ? lpsz3 : "";
  335. // go ahead and send the event to anyone watching debug output
  336. for (int i=0; i < cStrings; i++)
  337. {
  338. if (*plpszT[i])
  339. {
  340. if( SRVDBG_ASSERT == IDEvent )
  341. {
  342. TraceN1( "%s ", plpszT[i] );
  343. }
  344. else
  345. {
  346. ODS(plpszT[i]);
  347. ODS(" ");
  348. }
  349. }
  350. }
  351. if( SRVDBG_ASSERT == IDEvent )
  352. {
  353. Trace0( "\r\n" );
  354. }
  355. else
  356. {
  357. ODS("\r\n");
  358. }
  359. switch ( fwEventType )
  360. {
  361. case SRVDBG_INFO_TYPE:
  362. case SRVDBG_WARNING_TYPE:
  363. break;
  364. case SRVDBG_ERROR_TYPE:
  365. if (g_fWantInt3)
  366. {
  367. //
  368. // 06/13/96 cmason Will only break into a debugger if one is
  369. // running. If not running under a debugger, does nothing.
  370. //
  371. __try
  372. {
  373. _asm { int 3 };
  374. }
  375. __except (EXCEPTION_EXECUTE_HANDLER)
  376. {
  377. }
  378. }
  379. break;
  380. }
  381. //
  382. // 05/29/96 cmason Moved check to bottom of function so that Asserts still work even it
  383. // SRVDBG could not init the event log.
  384. // 09/08/96 garrettm If no event source, we try to create one on the fly...
  385. //
  386. if ( !g_hEventLog )
  387. {
  388. HANDLE hLog = RegisterEventSource(NULL, "UNKNOWN");
  389. if (hLog)
  390. {
  391. ReportEvent( hLog, fwEventType, 0, IDEvent, NULL, cStrings, dwDataSize, plpszT, lpRawData );
  392. DeregisterEventSource( hLog );
  393. }
  394. return ( FALSE );
  395. }
  396. fSuccess = ReportEvent( g_hEventLog, fwEventType, 0, IDEvent, NULL,
  397. cStrings, dwDataSize, plpszT, lpRawData );
  398. return ( fSuccess );
  399. }
  400. /***********************************************************************
  401. ***********************************************************************/
  402. void SRVDBG_DoAssert(
  403. LPCSTR szFile,
  404. int iLine,
  405. LPCSTR szAssert )
  406. {
  407. char szBuf[ 2048 ];
  408. wsprintf( szBuf, "File: %s at line %d\r\n%s", szFile, iLine, szAssert );
  409. SRVDBG_Assert( szBuf );
  410. }
  411. /***********************************************************************
  412. FUNCTION: SRVDBG_LogSystemID
  413. Place an event of some sort (by message ID) into the NT event log.
  414. Created 29-Mar-96 LeoN
  415. ************************************************************************/
  416. BOOL SRVDBG_LogSystemID (
  417. WORD type, // error, warning, info
  418. DWORD messageID, // id of message in module
  419. LPCSTR g_module, // module containing the message
  420. ...
  421. ) {
  422. va_list args;
  423. HMODULE hMod;
  424. char * psz;
  425. hMod = GetModuleHandle (g_module);
  426. if (hMod)
  427. {
  428. DWORD id;
  429. switch (type)
  430. {
  431. case 0:
  432. return TRUE;
  433. case SRVDBG_INFO_TYPE:
  434. id = SRVDBG_INFO;
  435. break;
  436. case SRVDBG_WARNING_TYPE:
  437. id = SRVDBG_WARNING;
  438. break;
  439. default:
  440. case SRVDBG_ERROR_TYPE:
  441. id = SRVDBG_ERROR;
  442. break;
  443. }
  444. va_start(args, g_module);
  445. if (0 == FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  446. | FORMAT_MESSAGE_FROM_HMODULE
  447. | FORMAT_MESSAGE_FROM_SYSTEM,
  448. hMod, messageID, 0,
  449. (char *)(&psz), 16, &args))
  450. {
  451. char sz[200];
  452. wsprintf(sz, "Couldn't find error for id %d", messageID);
  453. SRVDBG_ReportEvent (SRVDBG_ERROR_TYPE, id, sz, g_module, NULL);
  454. }
  455. else
  456. {
  457. SRVDBG_ReportEvent (type, id, psz, NULL, NULL);
  458. LocalFree(psz);
  459. }
  460. va_end(args);
  461. }
  462. else
  463. {
  464. SRVDBG_ReportEvent (SRVDBG_ERROR_TYPE, SRVDBG_ERROR, "Failure Logging Message", g_module, NULL);
  465. }
  466. return TRUE;
  467. }
  468. void LogSystemSZ(WORD type, LPCSTR szMessage )
  469. {
  470. SRVDBG_LogSystemSZ((WORD)type, szMessage);
  471. }
  472. /***********************************************************************
  473. FUNCTION: SRVDBG_LogSystemSZ
  474. Place an event of some sort (by string) into the NT event log.
  475. Created 29-Mar-96 LeoN
  476. ************************************************************************/
  477. BOOL SRVDBG_LogSystemSZ (
  478. WORD type, // error, warning, info
  479. LPCSTR szMessage
  480. ) {
  481. DWORD id;
  482. switch (type)
  483. {
  484. case 0:
  485. return TRUE;
  486. case SRVDBG_INFO_TYPE:
  487. id = SRVDBG_INFO;
  488. break;
  489. case SRVDBG_WARNING_TYPE:
  490. id = SRVDBG_WARNING;
  491. break;
  492. default:
  493. case SRVDBG_ERROR_TYPE:
  494. id = SRVDBG_ERROR;
  495. break;
  496. }
  497. return SRVDBG_ReportEvent (type, id, szMessage, NULL, NULL);
  498. }
  499. extern "C" void DoAssert(
  500. LPCSTR szFile,
  501. int iLine,
  502. LPCSTR szAssert )
  503. {
  504. char szBuf[ 2048 ];
  505. wsprintf( szBuf, "File: %s at line %d\r\n%s", szFile, iLine, szAssert );
  506. SRVDBG_Assert( szBuf );
  507. }
  508. #ifdef DEBUG
  509. // Force Debug initialization early
  510. // #pragma init_seg(compiler)
  511. DebugInfo g_dbi = {
  512. true, // Show trace
  513. -1, // No TLS trace buffer
  514. NULL, // No special trace function
  515. true, // Show asserts
  516. 0, // Assert count
  517. false, // Assert on alloc failure
  518. false, // Stop on Assert
  519. };
  520. /*---------------------------------------------------------------------------
  521. PrivateDbgTraceV
  522. Trace string with va_list arguments. Handle indenting.
  523. Author: kennt
  524. ---------------------------------------------------------------------------*/
  525. static void PrivateDbgTraceV(LPCSTR szFormat, va_list pvargs)
  526. {
  527. char szBuffer[2048+16];
  528. char *psz = szBuffer;
  529. #ifdef CORP_BUILD
  530. psz += wsprintf( psz, "tid(%x): ", GetCurrentThreadId());
  531. #endif
  532. wvsprintf(psz, szFormat, pvargs);
  533. OutputTrace(szBuffer);
  534. }
  535. /*!--------------------------------------------------------------------------
  536. DbgTraceV
  537. Trace string with va_list arguments. Handle indenting.
  538. Author: GaryBu
  539. ---------------------------------------------------------------------------*/
  540. DBG_API(void) DbgTraceV(LPCSTR szFormat, va_list pvargs)
  541. {
  542. PrivateDbgTraceV(szFormat, pvargs);
  543. }
  544. /*!--------------------------------------------------------------------------
  545. DbgTrace
  546. Trace string with args.
  547. Author: suryanr
  548. ---------------------------------------------------------------------------*/
  549. DBG_APIV(void) DbgTrace(LPSTR szFormat, ...)
  550. {
  551. va_list args;
  552. if (g_dbi.fDoTrace)
  553. {
  554. va_start(args, szFormat);
  555. DbgTraceV(szFormat, args);
  556. va_end(args);
  557. }
  558. }
  559. /*---------------------------------------------------------------------------
  560. OutputTrace
  561. OutputDebugString + any local handling
  562. Author: MarkGo
  563. ---------------------------------------------------------------------------*/
  564. DBG_API(void) OutputTrace(LPCTSTR lpBuffer)
  565. {
  566. DbgTraceBuf *ptb;
  567. if (g_dbi.pfnTrace)
  568. g_dbi.pfnTrace(lpBuffer);
  569. else
  570. ODS(lpBuffer);
  571. if (g_dbi.itlsTraceRGB != (DWORD) -1
  572. && (ptb = (DbgTraceBuf *)TlsGetValue(g_dbi.itlsTraceRGB))!=NULL )
  573. {
  574. DWORD cbOut = lstrlen(lpBuffer)+1;
  575. // Buffer the trace output
  576. // Is output larger than buf?
  577. if (cbOut >= ptb->cchBuf)
  578. {
  579. // Copy *last* cchBuf chars
  580. memcpy(ptb->rgch, lpBuffer + (cbOut - ptb->cchBuf), ptb->cchBuf);
  581. ptb->ichStart = 0;
  582. ptb->ichEnd = ptb->cchBuf-1;
  583. }
  584. else
  585. {
  586. // Is output larger than remaining contig space?
  587. if (cbOut > ptb->cchBuf - ptb->ichEnd)
  588. {
  589. memcpy(&(ptb->rgch[ptb->ichEnd]), lpBuffer,
  590. ptb->cchBuf - ptb->ichEnd);
  591. memcpy(ptb->rgch, lpBuffer+(ptb->cchBuf-ptb->ichEnd),
  592. cbOut-(ptb->cchBuf-ptb->ichEnd));
  593. ptb->ichStart = cbOut-(ptb->cchBuf-ptb->ichEnd);
  594. ptb->ichEnd = ptb->ichStart-1;
  595. }
  596. else
  597. {
  598. memcpy(&ptb->rgch[ptb->ichEnd], lpBuffer, cbOut);
  599. if (ptb->ichStart > ptb->ichEnd)
  600. {
  601. ptb->ichEnd += cbOut-1;
  602. ptb->ichStart = ptb->ichEnd+1;
  603. }
  604. else
  605. ptb->ichEnd += cbOut-1;
  606. }
  607. }
  608. }
  609. }
  610. #ifndef FDbgFalse
  611. /*!--------------------------------------------------------------------------
  612. FDbgFalse
  613. Returns false, but insures that debug code page is in memory.
  614. Also makes a handy breakpoint.
  615. Author: MarkGo
  616. ---------------------------------------------------------------------------*/
  617. DBG_API(BOOL) FDbgFalse()
  618. {
  619. return false;
  620. }
  621. #endif
  622. #ifdef __AFX_H__
  623. /*!--------------------------------------------------------------------------
  624. AfxAssertFailedLine
  625. Overrides Afx's assertion handling
  626. Author: GaryBu, kennt, MarkGo
  627. ---------------------------------------------------------------------------*/
  628. BOOL AFXAPI AfxAssertFailedLine(LPCSTR lpszFileName, int nLine)
  629. {
  630. DbgAssert(lpszFileName, nLine, "AFX Assert");
  631. return false;
  632. }
  633. #endif
  634. /*!--------------------------------------------------------------------------
  635. DbgAssert
  636. Display assert dialog.
  637. Author: GaryBu, kennt, MarkGo
  638. ---------------------------------------------------------------------------*/
  639. DBG_APIV(void) DbgAssert(LPCSTR szFile, int iLine, LPCSTR szFmt, ...)
  640. {
  641. va_list arg;
  642. char sz[MAX_PATH*2];
  643. char *pch = sz;
  644. va_start(arg, szFmt);
  645. pch += wvsprintf(sz, szFmt, arg);
  646. va_end(arg);
  647. // Remove trailing newlines...
  648. while (*(pch-1) == '\n' || *(pch-1) == '\r')
  649. --pch;
  650. *pch = 0;
  651. if (g_dbi.fShowAsserts)
  652. {
  653. //
  654. // 03/27/96 cmason Added doing trace output as well as the Event Viewer
  655. // entry for asserts.
  656. // 04/04/96 cmason Removed redundancy of tracing out the assert twice, once
  657. // here and agian inside the SRVDBG code called by DoAssert. The code here
  658. // was first, but the the SRVDBG code traces out more events than just asserts.
  659. //
  660. DbgTrace( "Assert failed: ");
  661. //
  662. // This loggs to the Event Viewer
  663. //
  664. DoAssert(szFile, iLine, sz);
  665. //
  666. // 03/27/96 cmason Added breaking into the debugger if requested.
  667. //
  668. if( g_dbi.fStopOnAssert )
  669. {
  670. //
  671. // This does an Int 3 and is protected by byt __try/__except so
  672. // that nothing happens if a debugger isn't running.
  673. //
  674. DbgStop();
  675. }
  676. }
  677. else
  678. DbgTrace(
  679. "Skipped Assert (ShowAsserts is FALSE):\r\n%s (file %s, line %d)\r\n",
  680. sz, szFile, iLine);
  681. }
  682. /*!--------------------------------------------------------------------------
  683. DbgStop -- causes a break into the debugger if the debugger is running.
  684. -
  685. Author: afx
  686. ---------------------------------------------------------------------------*/
  687. #pragma optimize("qgel", off) // assembler cannot be globally optimized
  688. DBG_API(void) DbgStop()
  689. {
  690. __try
  691. {
  692. _asm { int 3 };
  693. }
  694. __except (EXCEPTION_EXECUTE_HANDLER)
  695. {
  696. }
  697. }
  698. DBG_API(DWORD) DbgSetThreadTraceBuffer(DWORD itlsTrace)
  699. {
  700. DWORD itlsPrev = g_dbi.itlsTraceRGB;
  701. g_dbi.itlsTraceRGB = itlsTrace;
  702. return itlsPrev;
  703. }
  704. DBG_API(const char *) DbgGetTraceBuffer(BOOL fSecondChunk)
  705. {
  706. DbgTraceBuf *ptb;
  707. if (g_dbi.itlsTraceRGB == (DWORD)-1)
  708. return fSecondChunk ? "" : "<No trace information available>\r\n";
  709. if (NULL==(ptb = (DbgTraceBuf *)TlsGetValue(g_dbi.itlsTraceRGB)))
  710. return fSecondChunk ? "" : "<No trace buffer set>\r\n";
  711. if (!fSecondChunk)
  712. {
  713. // Return initial chunk, regardless of wraparound.
  714. return &(ptb->rgch[ptb->ichStart]);
  715. }
  716. // We only have a second chunk in wraparound
  717. if (ptb->ichStart > ptb->ichEnd)
  718. return ptb->rgch;
  719. return "";
  720. }
  721. DBG_API(BOOL) DbgSetTraceBuffer(void *rgbTrace, int cbTrace)
  722. {
  723. DbgTraceBuf *ptb;
  724. if (g_dbi.itlsTraceRGB == (DWORD) -1
  725. || (rgbTrace && cbTrace <= sizeof(DbgTraceBuf)))
  726. return false;
  727. ptb = (DbgTraceBuf *)rgbTrace;
  728. if (ptb)
  729. {
  730. ptb->cchBuf = cbTrace - sizeof(DbgTraceBuf);
  731. ptb->ichStart = ptb->ichEnd = 0;
  732. ptb->rgch[ptb->ichEnd] = '\0';
  733. ptb->rgch[ptb->cchBuf] = '\0';
  734. }
  735. TlsSetValue(g_dbi.itlsTraceRGB, ptb);
  736. return true;
  737. }
  738. #pragma optimize("", on)
  739. #endif //DEBUG
  740. /***********************************************************************
  741. FUNCTION: LoadMsg
  742. Loads a string from the message table and returns it in an allocated
  743. string buffer.
  744. History
  745. Created on: 06/01/95
  746. 04/29/96 cmason Trav#336: Added FORMAT_MESSAGE_MAX_WIDTH_MASK
  747. so that CRLF's must be explicitly specified.
  748. ************************************************************************/
  749. char *LoadMsg(UINT idMsg,
  750. HMODULE hmod) // May be null, in which case app's msg table is used
  751. {
  752. void *pv;
  753. char *pszRet;
  754. DWORD cch;
  755. cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  756. | FORMAT_MESSAGE_IGNORE_INSERTS
  757. | FORMAT_MESSAGE_FROM_HMODULE
  758. | FORMAT_MESSAGE_FROM_SYSTEM
  759. | FORMAT_MESSAGE_MAX_WIDTH_MASK,
  760. hmod, idMsg, 0 /*Default language*/,
  761. (char *)(&pv), 16, NULL);
  762. if ( !cch )
  763. return NULL;
  764. //
  765. // 04/30/96 cmason #336: Removing the trailing space.
  766. //
  767. Assert( ' ' == ((char *)pv)[cch - 1]);
  768. ((char *)pv)[cch - 1] = '\0';
  769. pszRet = new char[cch];
  770. memcpy(pszRet, pv, cch);
  771. LocalFree(pv);
  772. return pszRet;
  773. }