Windows NT 4.0 source code leak
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.

561 lines
11 KiB

4 years ago
  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. extern HANDLE ghMemHeap;
  16. extern HANDLE ghDbgMemHeap;
  17. VBackTrace* gpbtErrLog;
  18. VBackTrace* gpbtTraceLog;
  19. #if DBG
  20. MODULE_DEBUG_INIT( DBG_ERROR|DBG_WARN|DBG_TRACE, DBG_ERROR );
  21. DBG_POINTERS gDbgPointers;
  22. extern VBackTrace* gpbtAlloc;
  23. extern VBackTrace* gpbtFree;
  24. /********************************************************************
  25. Single thread checking.
  26. This is used to verify that a set of functions are called from
  27. only one thread. This is for debugging purposes only.
  28. ********************************************************************/
  29. VOID
  30. vDbgSingleThread(
  31. PDWORD pdwThreadId
  32. )
  33. {
  34. EnterCriticalSection( &gcsBackTrace );
  35. if (!*pdwThreadId) {
  36. *pdwThreadId = (DWORD)GetCurrentThreadId();
  37. }
  38. SPLASSERT( *pdwThreadId == (DWORD)GetCurrentThreadId() );
  39. LeaveCriticalSection( &gcsBackTrace );
  40. }
  41. VOID
  42. vDbgSingleThreadReset(
  43. PDWORD pdwThreadId
  44. )
  45. {
  46. *pdwThreadId = 0;
  47. }
  48. VOID
  49. vDbgSingleThreadNot(
  50. PDWORD pdwThreadId
  51. )
  52. {
  53. SPLASSERT( *pdwThreadId != (DWORD)GetCurrentThreadId() );
  54. }
  55. /********************************************************************
  56. TStatus automated error logging and codepath testing.
  57. ********************************************************************/
  58. TStatusBase&
  59. TStatusBase::
  60. pNoChk(
  61. VOID
  62. )
  63. {
  64. _pszFileA = NULL;
  65. return (TStatusBase&)*this;
  66. }
  67. TStatusBase&
  68. TStatusBase::
  69. pSetInfo(
  70. UINT uDbg,
  71. UINT uLine,
  72. LPCSTR pszFileA,
  73. LPCSTR pszModuleA
  74. )
  75. {
  76. _uDbg = uDbg;
  77. _uLine = uLine;
  78. _pszFileA = pszFileA;
  79. SPLASSERT( pszFileA );
  80. _pszModuleA = pszModuleA;
  81. return (TStatusBase&)*this;
  82. }
  83. DWORD
  84. TStatus::
  85. dwGetStatus(
  86. VOID
  87. )
  88. {
  89. //
  90. // For now, return error code. Later it will return the actual
  91. // error code.
  92. //
  93. return _dwStatus;
  94. }
  95. DWORD
  96. TStatusBase::
  97. operator=(
  98. DWORD dwStatus
  99. )
  100. {
  101. //
  102. // Check if we have an error, and it's not one of the two
  103. // accepted "safe" errors.
  104. //
  105. // If pszFileA is not set, then we can safely ignore the
  106. // error as one the client intended.
  107. //
  108. if( _pszFileA &&
  109. dwStatus != ERROR_SUCCESS &&
  110. dwStatus != _dwStatusSafe1 &&
  111. dwStatus != _dwStatusSafe2 &&
  112. dwStatus != _dwStatusSafe3 ){
  113. #ifdef DBGLOG
  114. //
  115. // An unexpected error occured. Log an error and continue.
  116. //
  117. vDbgLogError( _uDbg,
  118. _uDbgLevel,
  119. _uLine,
  120. _pszFileA,
  121. _pszModuleA,
  122. pszDbgAllocMsgA( "TStatus set to %d\nLine %d, %hs\n",
  123. dwStatus,
  124. _uLine,
  125. _pszFileA ));
  126. #else
  127. DBGMSG( DBG_WARN,
  128. ( "TStatus set to %d\nLine %d, %hs\n",
  129. dwStatus,
  130. _uLine,
  131. _pszFileA ));
  132. #endif
  133. }
  134. return _dwStatus = dwStatus;
  135. }
  136. /********************************************************************
  137. Same, but for BOOLs.
  138. ********************************************************************/
  139. TStatusBBase&
  140. TStatusBBase::
  141. pNoChk(
  142. VOID
  143. )
  144. {
  145. _pszFileA = NULL;
  146. return (TStatusBBase&)*this;
  147. }
  148. TStatusBBase&
  149. TStatusBBase::
  150. pSetInfo(
  151. UINT uDbg,
  152. UINT uLine,
  153. LPCSTR pszFileA,
  154. LPCSTR pszModuleA
  155. )
  156. {
  157. _uDbg = uDbg;
  158. _uLine = uLine;
  159. _pszFileA = pszFileA;
  160. SPLASSERT( pszFileA );
  161. _pszModuleA = pszModuleA;
  162. return (TStatusBBase&)*this;
  163. }
  164. BOOL
  165. TStatusB::
  166. bGetStatus(
  167. VOID
  168. )
  169. {
  170. //
  171. // For now, return error code. Later it will return the actual
  172. // error code.
  173. //
  174. return _bStatus;
  175. }
  176. BOOL
  177. TStatusBBase::
  178. operator=(
  179. BOOL bStatus
  180. )
  181. {
  182. //
  183. // Check if we have an error, and it's not one of the two
  184. // accepted "safe" errors.
  185. //
  186. // If pszFileA is not set, then we can safely ignore the
  187. // error as one the client intended.
  188. //
  189. if( _pszFileA && !bStatus ){
  190. DWORD dwLastError = GetLastError();
  191. if( dwLastError != _dwStatusSafe1 &&
  192. dwLastError != _dwStatusSafe2 &&
  193. dwLastError != _dwStatusSafe3 ){
  194. #ifdef DBGLOG
  195. //
  196. // An unexpected error occured. Log an error and continue.
  197. //
  198. vDbgLogError( _uDbg,
  199. _uDbgLevel,
  200. _uLine,
  201. _pszFileA,
  202. _pszModuleA,
  203. pszDbgAllocMsgA( "TStatusB set to FALSE, LastError = %d\nLine %d, %hs\n",
  204. GetLastError(),
  205. _uLine,
  206. _pszFileA ));
  207. #else
  208. DBGMSG( DBG_WARN,
  209. ( "TStatusB set to FALSE, LastError = %d\nLine %d, %hs\n",
  210. GetLastError(),
  211. _uLine,
  212. _pszFileA ));
  213. #endif
  214. }
  215. }
  216. return _bStatus = bStatus;
  217. }
  218. VOID
  219. vWarnInvalid(
  220. PVOID pvObject,
  221. UINT uDbg,
  222. UINT uLine,
  223. LPCSTR pszFileA,
  224. LPCSTR pszModuleA
  225. )
  226. /*++
  227. Routine Description:
  228. Warns that an object is invalid.
  229. Arguments:
  230. Return Value:
  231. --*/
  232. {
  233. #if DBGLOG
  234. vDbgLogError( uDbg,
  235. DBG_WARN,
  236. uLine,
  237. pszFileA,
  238. pszModuleA,
  239. pszDbgAllocMsgA( "Invalid Object %x LastError = %d\nLine %d, %hs\n",
  240. (DWORD)pvObject,
  241. GetLastError(),
  242. uLine,
  243. pszFileA ));
  244. #else
  245. DBGMSG( DBG_WARN,
  246. ( "Invalid Object %x LastError = %d\nLine %d, %hs\n",
  247. (DWORD)pvObject,
  248. GetLastError(),
  249. uLine,
  250. pszFileA ));
  251. #endif
  252. }
  253. /********************************************************************
  254. Generic Error logging package.
  255. ********************************************************************/
  256. VOID
  257. DbgMsg(
  258. LPCSTR pszMsgFormat,
  259. ...
  260. )
  261. {
  262. CHAR szMsgText[1024];
  263. va_list vargs;
  264. va_start( vargs, pszMsgFormat );
  265. wvsprintfA( szMsgText, pszMsgFormat, vargs );
  266. va_end( vargs );
  267. #ifndef DBGLOG
  268. //
  269. // Prefix the string if the first character isn't a space:
  270. //
  271. if( szMsgText[0] && szMsgText[0] != ' ' ){
  272. OutputDebugStringA( MODULE );
  273. }
  274. #endif
  275. OutputDebugStringA( szMsgText );
  276. }
  277. #ifdef DBGLOG
  278. LPSTR
  279. pszDbgAllocMsgA(
  280. LPCSTR pszMsgFormatA,
  281. ...
  282. )
  283. {
  284. CHAR szMsgTextA[1024];
  285. UINT cbStr;
  286. LPSTR pszMsgA;
  287. va_list vargs;
  288. va_start( vargs, pszMsgFormatA );
  289. __try {
  290. wvsprintfA( szMsgTextA, pszMsgFormatA, vargs );
  291. } __except(( GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
  292. GetExceptionCode() == EXCEPTION_DATATYPE_MISALIGNMENT) ?
  293. EXCEPTION_EXECUTE_HANDLER :
  294. EXCEPTION_CONTINUE_SEARCH ){
  295. OutputDebugStringA( "SPL: <Bad DbgMsg !!> " );
  296. OutputDebugStringA( pszMsgFormatA );
  297. }
  298. va_end( vargs );
  299. cbStr = ( lstrlenA( szMsgTextA ) + 1 ) * sizeof( szMsgTextA[0] );
  300. pszMsgA = (LPSTR)DbgAllocMem( cbStr );
  301. if( pszMsgA ){
  302. CopyMemory( pszMsgA, szMsgTextA, cbStr );
  303. }
  304. return pszMsgA;
  305. }
  306. VOID
  307. vDbgLogError(
  308. UINT uDbg,
  309. UINT uDbgLevel,
  310. UINT uLine,
  311. LPCSTR pszFileA,
  312. LPCSTR pszModuleA,
  313. LPCSTR pszMsgA
  314. )
  315. {
  316. DWORD dwLastError = GetLastError();
  317. VBackTrace* pBackTrace = gpbtTraceLog;
  318. if(( uDbgLevel & DBG_PRINT_MASK & uDbg ) && pszMsgA ){
  319. if( !( uDbgLevel & DBG_NOHEAD )){
  320. OutputDebugStringA( pszModuleA );
  321. }
  322. OutputDebugStringA( pszMsgA );
  323. }
  324. if(( uDbgLevel << DBG_BREAK_SHIFT ) & uDbg ){
  325. DebugBreak();
  326. }
  327. //
  328. // Log the failure.
  329. //
  330. //
  331. // Capture significant errors in separate error log.
  332. //
  333. if( uDbgLevel & DBG_ERRLOG_CAPTURE ){
  334. pBackTrace = gpbtErrLog;
  335. }
  336. pBackTrace->pvCapture( (DWORD)pszMsgA,
  337. uLine | ( uDbgLevel << DBG_BREAK_SHIFT ),
  338. (DWORD)pszFileA );
  339. SetLastError( dwLastError );
  340. }
  341. #endif // def DBGLOG
  342. #endif // DBG
  343. /********************************************************************
  344. Initialization
  345. ********************************************************************/
  346. #if DBG
  347. BOOL
  348. bSplLibInit(
  349. VOID
  350. )
  351. {
  352. BOOL bValid;
  353. bValid = (ghMemHeap = HeapCreate( 0, 1024*4, 0 )) &&
  354. (ghDbgMemHeap = HeapCreate( 0, 1024*4, 0 )) &&
  355. (VBackTrace::bInit( )) &&
  356. (gpbtAlloc = new TBackTraceMem) &&
  357. (gpbtFree = new TBackTraceMem) &&
  358. (gpbtErrLog = new TBackTraceMem( VBackTrace::kString )) &&
  359. (gpbtTraceLog = new TBackTraceMem( VBackTrace::kString )) &&
  360. (MRefCom::gpcsCom = new MCritSec) &&
  361. MRefCom::gpcsCom->bValid();
  362. if( bValid ){
  363. gDbgPointers.pfnAllocBackTrace = &DbgAllocBackTrace;
  364. gDbgPointers.pfnAllocBackTraceMem = &DbgAllocBackTraceMem;
  365. gDbgPointers.pfnFreeBackTrace = &DbgFreeBackTrace;
  366. gDbgPointers.pfnCaptureBackTrace = &DbgCaptureBackTrace;
  367. gDbgPointers.pfnAllocCritSec = &DbgAllocCritSec;
  368. gDbgPointers.pfnFreeCritSec = &DbgFreeCritSec;
  369. gDbgPointers.pfnInsideCritSec = &DbgInsideCritSec;
  370. gDbgPointers.pfnOutsideCritSec = &DbgOutsideCritSec;
  371. gDbgPointers.pfnEnterCritSec = &DbgEnterCritSec;
  372. gDbgPointers.pfnLeaveCritSec = &DbgLeaveCritSec;
  373. gDbgPointers.hMemHeap = ghMemHeap;
  374. gDbgPointers.hDbgMemHeap = ghDbgMemHeap;
  375. gDbgPointers.pbtAlloc = gpbtAlloc;
  376. gDbgPointers.pbtFree = gpbtFree;
  377. gDbgPointers.pbtErrLog = gpbtErrLog;
  378. gDbgPointers.pbtTraceLog = gpbtTraceLog;
  379. }
  380. return bValid;
  381. }
  382. VOID
  383. vSplLibFree(
  384. VOID
  385. )
  386. {
  387. SPLASSERT( MRefCom::gpcsCom->bOutside( ));
  388. delete MRefCom::gpcsCom;
  389. HeapDestroy( ghMemHeap );
  390. HeapDestroy( ghDbgMemHeap );
  391. }
  392. #else
  393. BOOL
  394. bSplLibInit(
  395. VOID
  396. )
  397. {
  398. return ( ghMemHeap = HeapCreate( 0, 1024*4, 0 )) ?
  399. TRUE : FALSE;
  400. }
  401. VOID
  402. vSplLibFree(
  403. VOID
  404. )
  405. {
  406. HeapDestroy( ghMemHeap );
  407. }
  408. #endif
  409. /********************************************************************
  410. Stub these out so non-debug builds will find them.
  411. ********************************************************************/
  412. #if !DBG
  413. #ifdef DBGLOG
  414. LPSTR
  415. pszDbgAllocMsgA(
  416. LPCSTR pszMsgFormatA,
  417. ...
  418. )
  419. {
  420. return NULL;
  421. }
  422. VOID
  423. vDbgLogError(
  424. UINT uDbg,
  425. UINT uDbgLevel,
  426. UINT uLine,
  427. LPCSTR pszFileA,
  428. LPCSTR pszModuleA,
  429. LPCSTR pszMsgA
  430. )
  431. {
  432. }
  433. #else
  434. VOID
  435. vDbgMsg2(
  436. LPCTSTR pszMsgFormat,
  437. ...
  438. )
  439. {
  440. }
  441. #endif // ndef DBGLOG
  442. #endif // !DBG