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.

697 lines
15 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. Debug.cxx
  6. Abstract:
  7. Debug support
  8. Author:
  9. Albert Ting (AlbertT) 28-May-1994
  10. Revision History:
  11. --*/
  12. #include "spllibp.hxx"
  13. #pragma hdrstop
  14. #include "trace.hxx"
  15. #define DEFAULT_TRACE_TYPE TBackTraceMem
  16. //#define DEFAULT_TRACE_TYPE TBackTraceFile // For tracing to file.
  17. #define DEFAULT_MEM_TRACE_TYPE TBackTraceMem
  18. extern HANDLE ghMemHeap;
  19. extern HANDLE ghDbgMemHeap;
  20. pfCreateThread gpfSafeCreateThread;
  21. #if DBG
  22. UINT gLogFilter = (UINT)-1;
  23. VBackTrace* gpbtErrLog;
  24. VBackTrace* gpbtTraceLog;
  25. MODULE_DEBUG_INIT( DBG_ERROR, DBG_ERROR );
  26. DBG_POINTERS gDbgPointers;
  27. PDBG_POINTERS gpDbgPointers;
  28. extern VBackTrace* gpbtAlloc;
  29. extern VBackTrace* gpbtFree;
  30. /********************************************************************
  31. TStatus automated error logging and codepath testing.
  32. ********************************************************************/
  33. TStatusBase&
  34. TStatusBase::
  35. pNoChk(
  36. VOID
  37. )
  38. {
  39. _pszFileA = NULL;
  40. return (TStatusBase&)*this;
  41. }
  42. TStatusBase&
  43. TStatusBase::
  44. pSetInfo(
  45. UINT uDbg,
  46. UINT uLine,
  47. LPCSTR pszFileA,
  48. LPCSTR pszModuleA
  49. )
  50. {
  51. _uDbg = uDbg;
  52. _uLine = uLine;
  53. _pszFileA = pszFileA;
  54. SPLASSERT( pszFileA );
  55. _pszModuleA = pszModuleA;
  56. return (TStatusBase&)*this;
  57. }
  58. DWORD
  59. TStatus::
  60. dwGetStatus(
  61. VOID
  62. )
  63. {
  64. //
  65. // For now, return error code. Later it will return the actual
  66. // error code.
  67. //
  68. return _dwStatus;
  69. }
  70. DWORD
  71. TStatusBase::
  72. operator=(
  73. DWORD dwStatus
  74. )
  75. {
  76. //
  77. // Check if we have an error, and it's not one of the two
  78. // accepted "safe" errors.
  79. //
  80. // If pszFileA is not set, then we can safely ignore the
  81. // error as one the client intended.
  82. //
  83. if( _pszFileA &&
  84. dwStatus != ERROR_SUCCESS &&
  85. dwStatus != _dwStatusSafe1 &&
  86. dwStatus != _dwStatusSafe2 &&
  87. dwStatus != _dwStatusSafe3 ){
  88. #ifdef DBGLOG
  89. //
  90. // An unexpected error occured. Log an error and continue.
  91. //
  92. vDbgLogError( _uDbg,
  93. _uDbgLevel,
  94. _uLine,
  95. _pszFileA,
  96. _pszModuleA,
  97. pszDbgAllocMsgA( "TStatus set to %d\nLine %d, %hs\n",
  98. dwStatus,
  99. _uLine,
  100. _pszFileA ));
  101. #else
  102. DBGMSG( DBG_WARN,
  103. ( "TStatus set to %d\nLine %d, %hs\n",
  104. dwStatus,
  105. _uLine,
  106. _pszFileA ));
  107. #endif
  108. }
  109. return _dwStatus = dwStatus;
  110. }
  111. /********************************************************************
  112. Same, but for HRESULTs.
  113. ********************************************************************/
  114. TStatusHBase&
  115. TStatusHBase::
  116. pNoChk(
  117. VOID
  118. )
  119. {
  120. _pszFileA = NULL;
  121. return (TStatusH&)*this;
  122. }
  123. TStatusHBase&
  124. TStatusHBase::
  125. pSetInfo(
  126. UINT uDbg,
  127. UINT uLine,
  128. LPCSTR pszFileA,
  129. LPCSTR pszModuleA
  130. )
  131. {
  132. _uDbg = uDbg;
  133. _uLine = uLine;
  134. _pszFileA = pszFileA;
  135. SPLASSERT( pszFileA );
  136. _pszModuleA = pszModuleA;
  137. return (TStatusH&)*this;
  138. }
  139. HRESULT
  140. TStatusHBase::
  141. operator=(
  142. HRESULT hrStatus
  143. )
  144. {
  145. //
  146. // Check if we have an error, and it's not one of the two
  147. // accepted "safe" errors.
  148. //
  149. // If pszFileA is not set, then we can safely ignore the
  150. // error as one the client intended.
  151. //
  152. if( _pszFileA &&
  153. FAILED(hrStatus) &&
  154. hrStatus != _hrStatusSafe1 &&
  155. hrStatus != _hrStatusSafe2 &&
  156. hrStatus != _hrStatusSafe3 ){
  157. #ifdef DBGLOG
  158. //
  159. // An unexpected error occured. Log an error and continue.
  160. //
  161. vDbgLogError( _uDbg,
  162. _uDbgLevel,
  163. _uLine,
  164. _pszFileA,
  165. _pszModuleA,
  166. pszDbgAllocMsgA( "TStatusH set to %x\nLine %d, %hs\n",
  167. hrStatus,
  168. _uLine,
  169. _pszFileA ));
  170. #else
  171. DBGMSG( DBG_WARN,
  172. ( "TStatusH set to %x\nLine %d, %hs\n",
  173. hrStatus,
  174. _uLine,
  175. _pszFileA ));
  176. #endif
  177. }
  178. return _hrStatus = hrStatus;
  179. }
  180. HRESULT
  181. TStatusH::
  182. hrGetStatus(
  183. VOID
  184. )
  185. {
  186. //
  187. // For now, return error code. Later it will return the actual
  188. // error code.
  189. //
  190. return _hrStatus;
  191. }
  192. /********************************************************************
  193. Same, but for BOOLs.
  194. ********************************************************************/
  195. TStatusBBase&
  196. TStatusBBase::
  197. pNoChk(
  198. VOID
  199. )
  200. {
  201. _pszFileA = NULL;
  202. return (TStatusBBase&)*this;
  203. }
  204. TStatusBBase&
  205. TStatusBBase::
  206. pSetInfo(
  207. UINT uDbg,
  208. UINT uLine,
  209. LPCSTR pszFileA,
  210. LPCSTR pszModuleA
  211. )
  212. {
  213. _uDbg = uDbg;
  214. _uLine = uLine;
  215. _pszFileA = pszFileA;
  216. SPLASSERT( pszFileA );
  217. _pszModuleA = pszModuleA;
  218. return (TStatusBBase&)*this;
  219. }
  220. BOOL
  221. TStatusB::
  222. bGetStatus(
  223. VOID
  224. )
  225. {
  226. //
  227. // For now, return error code. Later it will return the actual
  228. // error code.
  229. //
  230. return _bStatus;
  231. }
  232. BOOL
  233. TStatusBBase::
  234. operator=(
  235. BOOL bStatus
  236. )
  237. {
  238. //
  239. // Check if we have an error, and it's not one of the two
  240. // accepted "safe" errors.
  241. //
  242. // If pszFileA is not set, then we can safely ignore the
  243. // error as one the client intended.
  244. //
  245. if( _pszFileA && !bStatus ){
  246. DWORD dwLastError = GetLastError();
  247. if( dwLastError != _dwStatusSafe1 &&
  248. dwLastError != _dwStatusSafe2 &&
  249. dwLastError != _dwStatusSafe3 ){
  250. #ifdef DBGLOG
  251. //
  252. // An unexpected error occured. Log an error and continue.
  253. //
  254. vDbgLogError( _uDbg,
  255. _uDbgLevel,
  256. _uLine,
  257. _pszFileA,
  258. _pszModuleA,
  259. pszDbgAllocMsgA( "TStatusB set to FALSE, LastError = %d\nLine %d, %hs\n",
  260. GetLastError(),
  261. _uLine,
  262. _pszFileA ));
  263. #else
  264. DBGMSG( DBG_WARN,
  265. ( "TStatusB set to FALSE, LastError = %d\nLine %d, %hs\n",
  266. GetLastError(),
  267. _uLine,
  268. _pszFileA ));
  269. #endif
  270. }
  271. }
  272. return _bStatus = bStatus;
  273. }
  274. VOID
  275. vWarnInvalid(
  276. PVOID pvObject,
  277. UINT uDbg,
  278. UINT uLine,
  279. LPCSTR pszFileA,
  280. LPCSTR pszModuleA
  281. )
  282. /*++
  283. Routine Description:
  284. Warns that an object is invalid.
  285. Arguments:
  286. Return Value:
  287. --*/
  288. {
  289. #if DBGLOG
  290. vDbgLogError( uDbg,
  291. DBG_WARN,
  292. uLine,
  293. pszFileA,
  294. pszModuleA,
  295. pszDbgAllocMsgA( "Invalid Object %x LastError = %d\nLine %d, %hs\n",
  296. (ULONG_PTR)pvObject,
  297. GetLastError(),
  298. uLine,
  299. pszFileA ));
  300. #else
  301. DBGMSG( DBG_WARN,
  302. ( "Invalid Object %x LastError = %d\nLine %d, %hs\n",
  303. (DWORD)pvObject,
  304. GetLastError(),
  305. uLine,
  306. pszFileA ));
  307. #endif
  308. }
  309. /********************************************************************
  310. Generic Error logging package.
  311. ********************************************************************/
  312. VOID
  313. DbgMsg(
  314. LPCSTR pszMsgFormat,
  315. ...
  316. )
  317. {
  318. CHAR szMsgText[1024];
  319. va_list vargs;
  320. va_start( vargs, pszMsgFormat );
  321. StringCchVPrintfA( szMsgText, COUNTOF(szMsgText), pszMsgFormat, vargs );
  322. va_end( vargs );
  323. #ifndef DBGLOG
  324. //
  325. // Prefix the string if the first character isn't a space:
  326. //
  327. if( szMsgText[0] && szMsgText[0] != ' ' ){
  328. OutputDebugStringA( MODULE );
  329. }
  330. #endif
  331. OutputDebugStringA( szMsgText );
  332. }
  333. #ifdef DBGLOG
  334. LPSTR
  335. pszDbgAllocMsgA(
  336. LPCSTR pszMsgFormatA,
  337. ...
  338. )
  339. {
  340. CHAR szMsgTextA[1024];
  341. UINT cbStr;
  342. LPSTR pszMsgA;
  343. va_list vargs;
  344. va_start(vargs, pszMsgFormatA);
  345. __try
  346. {
  347. StringCchVPrintfA( szMsgTextA, COUNTOF(szMsgTextA), pszMsgFormatA, vargs );
  348. } __except(( GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
  349. GetExceptionCode() == EXCEPTION_DATATYPE_MISALIGNMENT) ?
  350. EXCEPTION_EXECUTE_HANDLER :
  351. EXCEPTION_CONTINUE_SEARCH )
  352. {
  353. OutputDebugStringA( "SPL: <Bad DbgMsg !!> " );
  354. OutputDebugStringA( pszMsgFormatA );
  355. }
  356. va_end(vargs);
  357. cbStr = ( lstrlenA( szMsgTextA ) + 1 ) * sizeof( szMsgTextA[0] );
  358. pszMsgA = (LPSTR)DbgAllocMem( cbStr );
  359. if( pszMsgA ){
  360. CopyMemory( pszMsgA, szMsgTextA, cbStr );
  361. }
  362. return pszMsgA;
  363. }
  364. VOID
  365. vDbgLogError(
  366. UINT uDbg,
  367. UINT uDbgLevel,
  368. UINT uLine,
  369. LPCSTR pszFileA,
  370. LPCSTR pszModuleA,
  371. LPCSTR pszMsgA
  372. )
  373. {
  374. DWORD dwLastError = GetLastError();
  375. VBackTrace* pBackTrace = gpbtTraceLog;
  376. if(( uDbgLevel & DBG_PRINT_MASK & uDbg ) && pszMsgA ){
  377. if( !( uDbgLevel & DBG_NOHEAD )){
  378. OutputDebugStringA( pszModuleA );
  379. }
  380. OutputDebugStringA( pszMsgA );
  381. }
  382. if(( uDbgLevel << DBG_BREAK_SHIFT ) & uDbg ){
  383. DebugBreak();
  384. }
  385. if( gLogFilter & uDbgLevel )
  386. {
  387. //
  388. // Log the failure.
  389. //
  390. //
  391. // Capture significant errors in separate error log.
  392. //
  393. if( uDbgLevel & DBG_ERRLOG_CAPTURE ){
  394. pBackTrace = gpbtErrLog;
  395. }
  396. if (pBackTrace)
  397. {
  398. pBackTrace->hCapture( (ULONG_PTR)pszMsgA,
  399. uLine | ( uDbgLevel << DBG_BREAK_SHIFT ),
  400. (ULONG_PTR)pszFileA );
  401. }
  402. else
  403. {
  404. //
  405. // Backtracing is not enabled, free the message string that is
  406. // passed in.
  407. //
  408. if(pszMsgA)
  409. {
  410. DbgFreeMem((PVOID)pszMsgA);
  411. }
  412. }
  413. }
  414. else
  415. {
  416. //
  417. // Just free up the memory if this line is not captured
  418. // actually this happens when uDbgLevel == DBG_NONE (0)
  419. //
  420. if( pszMsgA )
  421. {
  422. DbgFreeMem( (PVOID)pszMsgA );
  423. }
  424. }
  425. SetLastError( dwLastError );
  426. }
  427. #endif // def DBGLOG
  428. #endif // DBG
  429. /********************************************************************
  430. Initialization
  431. ********************************************************************/
  432. #if DBG
  433. BOOL
  434. bSplLibInit(
  435. pfCreateThread pfSafeCreateThread
  436. )
  437. {
  438. BOOL bValid;
  439. bValid = (ghMemHeap = HeapCreate( 0, 1024*4, 0 )) &&
  440. (ghDbgMemHeap = HeapCreate( 0, 1024*4, 0 )) &&
  441. (VBackTrace::bInit( )) &&
  442. #ifdef TRACE_ENABLED
  443. (gpbtAlloc = new DEFAULT_MEM_TRACE_TYPE) &&
  444. (gpbtFree = new DEFAULT_MEM_TRACE_TYPE) &&
  445. (gpbtErrLog = new DEFAULT_TRACE_TYPE( VBackTrace::kString )) &&
  446. (gpbtTraceLog = new DEFAULT_TRACE_TYPE( VBackTrace::kString )) &&
  447. #endif
  448. (MRefCom::gpcsCom = new MCritSec) &&
  449. MRefCom::gpcsCom->bValid();
  450. gpfSafeCreateThread = ( pfSafeCreateThread ) ? pfSafeCreateThread : CreateThread;
  451. if( bValid ){
  452. gDbgPointers.pfnAllocBackTrace = &DbgAllocBackTrace;
  453. gDbgPointers.pfnAllocBackTraceMem = &DbgAllocBackTraceMem;
  454. gDbgPointers.pfnAllocBackTraceFile = &DbgAllocBackTraceFile;
  455. gDbgPointers.pfnFreeBackTrace = &DbgFreeBackTrace;
  456. gDbgPointers.pfnCaptureBackTrace = &DbgCaptureBackTrace;
  457. gDbgPointers.pfnAllocCritSec = &DbgAllocCritSec;
  458. gDbgPointers.pfnFreeCritSec = &DbgFreeCritSec;
  459. gDbgPointers.pfnInsideCritSec = &DbgInsideCritSec;
  460. gDbgPointers.pfnOutsideCritSec = &DbgOutsideCritSec;
  461. gDbgPointers.pfnEnterCritSec = &DbgEnterCritSec;
  462. gDbgPointers.pfnLeaveCritSec = &DbgLeaveCritSec;
  463. gDbgPointers.pfnSetAllocFail = &DbgSetAllocFail;
  464. gDbgPointers.hMemHeap = ghMemHeap;
  465. gDbgPointers.hDbgMemHeap = ghDbgMemHeap;
  466. gDbgPointers.pbtAlloc = gpbtAlloc;
  467. gDbgPointers.pbtFree = gpbtFree;
  468. gDbgPointers.pbtErrLog = gpbtErrLog;
  469. gDbgPointers.pbtTraceLog = gpbtTraceLog;
  470. gpDbgPointers = &gDbgPointers;
  471. }
  472. return bValid;
  473. }
  474. VOID
  475. vSplLibFree(
  476. VOID
  477. )
  478. {
  479. SPLASSERT( MRefCom::gpcsCom->bOutside( ));
  480. delete MRefCom::gpcsCom;
  481. VBackTrace::vDone();
  482. if (ghMemHeap)
  483. {
  484. HeapDestroy( ghMemHeap );
  485. ghMemHeap = NULL;
  486. }
  487. if (ghDbgMemHeap)
  488. {
  489. HeapDestroy( ghDbgMemHeap );
  490. ghDbgMemHeap = NULL;
  491. }
  492. }
  493. #else
  494. BOOL
  495. bSplLibInit(
  496. pfCreateThread pfSafeCreateThread
  497. )
  498. {
  499. UINT RetLen;
  500. UINT HeapFragValue = 2;
  501. gpfSafeCreateThread = ( pfSafeCreateThread ) ? pfSafeCreateThread : CreateThread;
  502. ghMemHeap = HeapCreate(0, 1024*4, 0);
  503. if (ghMemHeap)
  504. {
  505. //
  506. // Activate LFH (low fragmentation) for the spooler heap. We don't care if the
  507. // function fails. LFH won't go in effect if certain gflags are set.
  508. //
  509. HeapSetInformation(ghMemHeap,
  510. HeapCompatibilityInformation,
  511. &HeapFragValue,
  512. sizeof(HeapFragValue));
  513. }
  514. return !!ghMemHeap;
  515. }
  516. VOID
  517. vSplLibFree(
  518. VOID
  519. )
  520. {
  521. if (ghMemHeap)
  522. {
  523. HeapDestroy( ghMemHeap );
  524. ghMemHeap = NULL;
  525. }
  526. }
  527. #endif
  528. /********************************************************************
  529. Stub these out so non-debug builds will find them.
  530. ********************************************************************/
  531. #if !DBG
  532. #ifdef DBGLOG
  533. LPSTR
  534. pszDbgAllocMsgA(
  535. LPCSTR pszMsgFormatA,
  536. ...
  537. )
  538. {
  539. return NULL;
  540. }
  541. VOID
  542. vDbgLogError(
  543. UINT uDbg,
  544. UINT uDbgLevel,
  545. UINT uLine,
  546. LPCSTR pszFileA,
  547. LPCSTR pszModuleA,
  548. LPCSTR pszMsgA
  549. )
  550. {
  551. }
  552. #else
  553. VOID
  554. vDbgMsg2(
  555. LPCTSTR pszMsgFormat,
  556. ...
  557. )
  558. {
  559. }
  560. #endif // ndef DBGLOG
  561. #endif // !DBG