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.

598 lines
15 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992
  5. //
  6. // File: debug.cxx
  7. //
  8. // Contents: Debugging routines
  9. //
  10. // History: 07-Mar-92 DrewB Created
  11. //
  12. //---------------------------------------------------------------
  13. #include <dfhead.cxx>
  14. #pragma hdrstop
  15. #if DBG == 1
  16. #include <stdarg.h>
  17. #include <dfdeb.hxx>
  18. #include <logfile.hxx>
  19. #include <df32.hxx>
  20. //+-------------------------------------------------------------
  21. //
  22. // Function: DfDebug, public
  23. //
  24. // Synopsis: Sets debugging level
  25. //
  26. //---------------------------------------------------------------
  27. DECLARE_INFOLEVEL(ol);
  28. #define LOGFILENAME L"logfile.txt"
  29. static CGlobalFileStream *_pgfstLogFiles = NULL;
  30. WCHAR gwcsLogFile[] = LOGFILENAME;
  31. STDAPI_(void) DfDebug(ULONG ulLevel, ULONG ulMSFLevel)
  32. {
  33. #if DBG == 1
  34. olInfoLevel = ulLevel;
  35. SetInfoLevel(ulMSFLevel);
  36. _SetWin4InfoLevel(ulLevel | ulMSFLevel);
  37. olDebugOut((DEB_ITRACE, "\n-- DfDebug(0x%lX, 0x%lX)\n",
  38. ulLevel, ulMSFLevel));
  39. #endif
  40. }
  41. // Resource limits
  42. static LONG lResourceLimits[CDBRESOURCES] =
  43. {
  44. 0x7fffffff, // DBR_MEMORY
  45. 0x7fffffff, // DBR_XSCOMMITS
  46. 0x0, // DBR_FAILCOUNT
  47. 0x0, // DBR_FAILLIMIT
  48. 0x0, // DBR_FAILTYPES
  49. 0x0, // DBRQ_MEMORY_ALLOCATED
  50. 0x0, // DBRI_ALLOC_LIST
  51. 0x0, // DBRI_LOGFILE_LIST
  52. 0x0, // DBRF_LOGGING
  53. 0x0, // DBRQ_HEAPS
  54. 0x0 // DBRF_SIFTENABLE
  55. };
  56. #define CBRESOURCES sizeof(lResourceLimits)
  57. #define RESLIMIT(n) lResourceLimits[n]
  58. #define TAKEMTX
  59. #define RELEASEMTX
  60. //+---------------------------------------------------------------------------
  61. //
  62. // Function: DfSetResLimit, public
  63. //
  64. // Synopsis: Sets a resource limit
  65. //
  66. // History: 24-Nov-92 DrewB Created
  67. //
  68. //----------------------------------------------------------------------------
  69. STDAPI_(void) DfSetResLimit(UINT iRes, LONG lLimit)
  70. {
  71. TAKEMTX;
  72. RESLIMIT(iRes) = lLimit;
  73. RELEASEMTX;
  74. }
  75. //+---------------------------------------------------------------------------
  76. //
  77. // Function: DfGetResLimit, public
  78. //
  79. // Synopsis: Gets a resource limit
  80. //
  81. // History: 24-Nov-92 DrewB Created
  82. //
  83. //----------------------------------------------------------------------------
  84. STDAPI_(LONG) DfGetResLimit(UINT iRes)
  85. {
  86. // Doesn't need serialization
  87. return RESLIMIT(iRes);
  88. }
  89. STDAPI_(void) DfSetFailureType(LONG lTypes)
  90. {
  91. RESLIMIT(DBR_FAILTYPES) = lTypes;
  92. return;
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // Function: HaveResource, private
  97. //
  98. // Synopsis: Checks to see if a resource limit is exceeded
  99. // and consumes resource if not
  100. //
  101. // History: 24-Nov-92 DrewB Created
  102. //
  103. //----------------------------------------------------------------------------
  104. BOOL HaveResource(UINT iRes, LONG lRequest)
  105. {
  106. if (RESLIMIT(DBRF_SIFTENABLE) == FALSE)
  107. return TRUE;
  108. if (RESLIMIT(iRes) >= lRequest)
  109. {
  110. TAKEMTX;
  111. RESLIMIT(iRes) -= lRequest;
  112. RELEASEMTX;
  113. return TRUE;
  114. }
  115. return FALSE;
  116. }
  117. //+---------------------------------------------------------------------------
  118. //
  119. // Function: ModifyResLimit, private
  120. //
  121. // Synopsis: Adds to a resource limit
  122. //
  123. // History: 24-Nov-92 DrewB Created
  124. //
  125. //----------------------------------------------------------------------------
  126. LONG ModifyResLimit(UINT iRes, LONG lChange)
  127. {
  128. LONG l;
  129. TAKEMTX;
  130. RESLIMIT(iRes) += lChange;
  131. l = RESLIMIT(iRes);
  132. RELEASEMTX;
  133. return l;
  134. }
  135. //+-------------------------------------------------------------------------
  136. //
  137. // Function: SimulateFailure
  138. //
  139. // Synopsis: Check for simulated failure
  140. //
  141. // Effects: Tracks failure count
  142. //
  143. // Arguments: [failure] -- failure type
  144. //
  145. // Returns: TRUE if call should fail, FALSE if call should succeed
  146. //
  147. // Modifies: RESLIMIT(DBR_FAILCOUNT)
  148. //
  149. // Algorithm: Increment failure count, fail if count has succeeded
  150. // limit
  151. //
  152. // History: 21-Jan-93 AlexT Created
  153. //
  154. //--------------------------------------------------------------------------
  155. BOOL SimulateFailure(DBFAILURE failure)
  156. {
  157. LONG l;
  158. BOOL fFail;
  159. // We don't special case failure types, yet.
  160. if (RESLIMIT(DBRF_SIFTENABLE) != FALSE &&
  161. (failure & RESLIMIT(DBR_FAILTYPES)))
  162. {
  163. TAKEMTX;
  164. RESLIMIT(DBR_FAILCOUNT)++;
  165. l = RESLIMIT(DBR_FAILLIMIT);
  166. fFail = RESLIMIT(DBR_FAILCOUNT) >= l;
  167. RELEASEMTX;
  168. if (l == 0)
  169. {
  170. // We're not simulating any failures; just tracking them
  171. return(FALSE);
  172. }
  173. return fFail;
  174. }
  175. else
  176. {
  177. return FALSE;
  178. }
  179. }
  180. //+--------------------------------------------------------------
  181. //
  182. // Class: CChecksumBlock (cb)
  183. //
  184. // Purpose: Holds a memory block that is being checksummed
  185. //
  186. // Interface: See below
  187. //
  188. // History: 08-Apr-92 DrewB Created
  189. //
  190. //---------------------------------------------------------------
  191. class CChecksumBlock
  192. {
  193. public:
  194. CChecksumBlock(char *pszName,
  195. void *pvAddr,
  196. ULONG cBytes,
  197. DWORD dwFlags,
  198. CChecksumBlock *pcbNext,
  199. CChecksumBlock *pcbPrev);
  200. ~CChecksumBlock(void);
  201. char *_pszName;
  202. void *_pvAddr;
  203. ULONG _cBytes;
  204. DWORD _dwFlags;
  205. CChecksumBlock *_pcbNext, *_pcbPrev;
  206. ULONG _ulChecksum;
  207. };
  208. // Global list of checksummed blocks
  209. static CChecksumBlock *pcbChkBlocks = NULL;
  210. //+--------------------------------------------------------------
  211. //
  212. // Member: CChecksumBlock::CChecksumBlock, private
  213. //
  214. // Synopsis: Ctor
  215. //
  216. // Arguments: [pszName] - Block name
  217. // [pvAddr] - Starting addr
  218. // [cBytes] - Length
  219. // [dwFlags] - Type flags
  220. // [pcbNext] - Next checksum block
  221. //
  222. // History: 08-Apr-92 DrewB Created
  223. //
  224. //---------------------------------------------------------------
  225. CChecksumBlock::CChecksumBlock(char *pszName,
  226. void *pvAddr,
  227. ULONG cBytes,
  228. DWORD dwFlags,
  229. CChecksumBlock *pcbNext,
  230. CChecksumBlock *pcbPrev)
  231. {
  232. ULONG i;
  233. char *pc;
  234. olVerify(_pszName = new char[strlen(pszName)+1]);
  235. StringCchCopyA (_pszName, strlen(pszName)+1, pszName);
  236. _pvAddr = pvAddr;
  237. _cBytes = cBytes;
  238. _dwFlags = dwFlags;
  239. _pcbNext = pcbNext;
  240. if (pcbNext)
  241. pcbNext->_pcbPrev = this;
  242. _pcbPrev = pcbPrev;
  243. if (pcbPrev)
  244. pcbPrev->_pcbNext = this;
  245. _ulChecksum = 0;
  246. pc = (char *)pvAddr;
  247. for (i = 0; i<cBytes; i++)
  248. _ulChecksum += *pc++;
  249. }
  250. //+--------------------------------------------------------------
  251. //
  252. // Member: CChecksumBlock::~CChecksumBlock, private
  253. //
  254. // Synopsis: Dtor
  255. //
  256. // History: 08-Apr-92 DrewB Created
  257. //
  258. //---------------------------------------------------------------
  259. CChecksumBlock::~CChecksumBlock(void)
  260. {
  261. delete _pszName;
  262. }
  263. //+--------------------------------------------------------------
  264. //
  265. // Function: DbgChkBlocks, private
  266. //
  267. // Synopsis: Verify checksums on all current blocks
  268. //
  269. // Arguments: [dwFlags] - Types of blocks to check
  270. // [pszFile] - File check was called from
  271. // [iLine] - Line in file
  272. //
  273. // History: 08-Apr-92 DrewB Created
  274. //
  275. //---------------------------------------------------------------
  276. void DbgChkBlocks(DWORD dwFlags, char *pszFile, int iLine)
  277. {
  278. CChecksumBlock *pcb;
  279. for (pcb = pcbChkBlocks; pcb; pcb = pcb->_pcbNext)
  280. if (pcb->_dwFlags & dwFlags)
  281. {
  282. ULONG i, ulSum = 0;
  283. char *pc;
  284. for (pc = (char *)pcb->_pvAddr, i = 0; i<pcb->_cBytes; i++)
  285. ulSum += *pc++;
  286. if (ulSum != pcb->_ulChecksum)
  287. olDebugOut((DEB_ERROR, "* Bad checksum %s:%d '%s' %p:%lu *\n",
  288. pszFile, iLine, pcb->_pszName,
  289. pcb->_pvAddr, pcb->_cBytes));
  290. else if (dwFlags & DBG_VERBOSE)
  291. olDebugOut((DEB_ERROR, "* Checksum passed %s:%d"
  292. " '%s' %p:%lu *\n",
  293. pszFile, iLine, pcb->_pszName,
  294. pcb->_pvAddr, pcb->_cBytes));
  295. }
  296. }
  297. //+--------------------------------------------------------------
  298. //
  299. // Function: DbgAddChkBlock, private
  300. //
  301. // Synopsis: Adds a checksum block
  302. //
  303. // Arguments: [pszName] - Name of block
  304. // [pvAddr] - Starting addr
  305. // [cBytes] - Length
  306. // [dwFlags] - Type flags
  307. //
  308. // History: 08-Apr-92 DrewB Created
  309. //
  310. //---------------------------------------------------------------
  311. void DbgAddChkBlock(char *pszName,
  312. void *pvAddr,
  313. ULONG cBytes,
  314. DWORD dwFlags)
  315. {
  316. CChecksumBlock *pcb;
  317. olVerify(pcb = new CChecksumBlock(pszName, pvAddr, cBytes,
  318. dwFlags, pcbChkBlocks, NULL));
  319. pcbChkBlocks = pcb;
  320. }
  321. //+--------------------------------------------------------------
  322. //
  323. // Function: DbgFreeChkBlock, private
  324. //
  325. // Synopsis: Removes a block from the list
  326. //
  327. // Arguments: [pvAddr] - Block's check address
  328. //
  329. // History: 10-Apr-92 DrewB Created
  330. //
  331. //---------------------------------------------------------------
  332. void DbgFreeChkBlock(void *pvAddr)
  333. {
  334. CChecksumBlock *pcb;
  335. for (pcb = pcbChkBlocks; pcb; pcb = pcb->_pcbNext)
  336. if (pcb->_pvAddr == pvAddr)
  337. {
  338. if (pcb->_pcbPrev)
  339. pcb->_pcbPrev->_pcbNext = pcb->_pcbNext;
  340. else
  341. pcbChkBlocks = pcb->_pcbNext;
  342. if (pcb->_pcbNext)
  343. pcb->_pcbNext->_pcbPrev = pcb->_pcbPrev;
  344. delete pcb;
  345. return;
  346. }
  347. }
  348. //+--------------------------------------------------------------
  349. //
  350. // Function: DbgFreeChkBlocks, private
  351. //
  352. // Synopsis: Frees all checksum blocks
  353. //
  354. // History: 08-Apr-92 DrewB Created
  355. //
  356. //---------------------------------------------------------------
  357. void DbgFreeChkBlocks(void)
  358. {
  359. CChecksumBlock *pcb;
  360. while (pcbChkBlocks)
  361. {
  362. pcb = pcbChkBlocks->_pcbNext;
  363. delete pcbChkBlocks;
  364. pcbChkBlocks = pcb;
  365. }
  366. }
  367. static CGlobalFileStream *g_pDebugLogGlobalFileStream = NULL;
  368. inline CGlobalFileStream *GetGlobalFileStream()
  369. {
  370. return g_pDebugLogGlobalFileStream;
  371. }
  372. inline void SetGlobalFileStream(CGlobalFileStream *pgfst)
  373. {
  374. g_pDebugLogGlobalFileStream = pgfst;
  375. }
  376. #ifdef MULTIHEAP
  377. static CFileStream *g_pDebugLogFileStream = NULL;
  378. #endif
  379. SCODE GetLogFile(CFileStream **pfs)
  380. #ifdef MULTIHEAP
  381. {
  382. // Do not use shared memory to write log files
  383. SCODE sc = S_OK;
  384. if (GetGlobalFileStream() == NULL)
  385. {
  386. g_pDebugLogGlobalFileStream = ::new CGlobalFileStream
  387. (NULL, 0, LOGFILEDFFLAGS, LOGFILESTARTFLAGS);
  388. SetGlobalFileStream (g_pDebugLogGlobalFileStream);
  389. g_pDebugLogFileStream = ::new CFileStream (NULL);
  390. }
  391. g_pDebugLogFileStream->InitFromGlobal(GetGlobalFileStream());
  392. *pfs = g_pDebugLogFileStream;
  393. return sc;
  394. }
  395. #else
  396. {
  397. SCODE sc = S_OK;
  398. CFileStream *pfsLoop = NULL;
  399. *pfs = NULL;
  400. if (GetGlobalFileStream() == NULL)
  401. {
  402. IMalloc *pMalloc;
  403. olHChk(DfCreateSharedAllocator(&pMalloc));
  404. SetGlobalFileStream(new (pMalloc) CGlobalFileStream(pMalloc,
  405. 0, LOGFILEDFFLAGS,
  406. LOGFILESTARTFLAGS));
  407. pMalloc->Release();
  408. }
  409. if (GetGlobalFileStream() != NULL)
  410. {
  411. pfsLoop = GetGlobalFileStream()->Find(GetCurrentContextId());
  412. if (pfsLoop == NULL)
  413. {
  414. IMalloc *pMalloc;
  415. olHChk(DfCreateSharedAllocator(&pMalloc));
  416. pfsLoop = new (pMalloc) CFileStream(pMalloc);
  417. pMalloc->Release();
  418. if (pfsLoop != NULL)
  419. pfsLoop->InitFromGlobal(GetGlobalFileStream());
  420. }
  421. }
  422. EH_Err:
  423. *pfs = pfsLoop;
  424. return sc;
  425. }
  426. #endif // MULIHEAP
  427. SCODE _FreeLogFile(void)
  428. {
  429. #ifdef MULTIHEAP
  430. if (GetGlobalFileStream())
  431. {
  432. g_pDebugLogFileStream->RemoveFromGlobal();
  433. memset (g_pDebugLogGlobalFileStream, 0, sizeof(CContextList));
  434. ::delete g_pDebugLogFileStream;
  435. ::delete g_pDebugLogGlobalFileStream;
  436. SetGlobalFileStream (NULL);
  437. }
  438. return S_OK;
  439. #else
  440. CFileStream *pfsLoop = NULL;
  441. if (GetGlobalFileStream())
  442. pfsLoop = GetGlobalFileStream()->Find(GetCurrentContextId());
  443. if (pfsLoop != NULL)
  444. {
  445. pfsLoop->vRelease();
  446. GetGlobalFileStream()->Release();
  447. SetGlobalFileStream(NULL);
  448. return S_OK;
  449. }
  450. return STG_E_UNKNOWN;
  451. #endif
  452. }
  453. long cLogNestings = 0;
  454. void OutputLogfileMessage(char const *format, ...)
  455. {
  456. int length;
  457. char achPreFormat[] = "PID[%lx] TID[%lx] ";
  458. char achBuffer[256];
  459. ULONG cbWritten;
  460. CFileStream *pfs = NULL;
  461. va_list arglist;
  462. STATSTG stat;
  463. if (cLogNestings > 0)
  464. return;
  465. TAKEMTX;
  466. cLogNestings++;
  467. va_start(arglist, format);
  468. GetLogFile(&pfs);
  469. if (NULL != pfs)
  470. {
  471. pfs->InitFile(gwcsLogFile);
  472. pfs->Stat(&stat, STATFLAG_NONAME);
  473. if (DfGetResLimit(DBRF_LOGGING) & DFLOG_PIDTID)
  474. {
  475. // Prepare prefix string
  476. StringCbPrintfA(achBuffer, sizeof(achBuffer), "PID[%8lx] TID[%8lx] ",
  477. GetCurrentProcessId(), GetCurrentThreadId());
  478. // length does not include NULL terminator
  479. length = (int) strlen(achBuffer);
  480. pfs->WriteAt(stat.cbSize, achBuffer, length, &cbWritten);
  481. stat.cbSize.LowPart += cbWritten;
  482. }
  483. // Write caller data to logfile
  484. StringCbVPrintfA(achBuffer, sizeof(achBuffer), format, arglist);
  485. length = (int) strlen(achBuffer);
  486. for (int i = 0; i < length; i++)
  487. {
  488. if (((achBuffer[i] < 32) || (achBuffer[i] > 127)) &&
  489. (achBuffer[i] != '\n') && (achBuffer[i] != '\t'))
  490. {
  491. achBuffer[i] = '.';
  492. }
  493. }
  494. pfs->WriteAt(stat.cbSize, achBuffer, length, &cbWritten);
  495. }
  496. cLogNestings--;
  497. RELEASEMTX;
  498. }
  499. #endif // DBG == 1