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.

542 lines
9.3 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name :
  4. debugafx.cpp
  5. Abstract:
  6. Debugging routines using AFX/MFC extensions
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "common.h"
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char BASED_CODE THIS_FILE[] = __FILE__;
  21. #endif
  22. #define new DEBUG_NEW
  23. #if defined(_DEBUG) || DBG
  24. int
  25. IISUIFireAssert(
  26. const char * filename,
  27. const char * timestamp,
  28. int linenum,
  29. const char * expr
  30. )
  31. {
  32. char sz[4096];
  33. char * pch = sz;
  34. pch += wsprintfA(pch,
  35. "-------------------------------------------------------------------------------\n"
  36. "ASSERT FAILURE!\n"
  37. "-------------------------------------------------------------------------------\n"
  38. "File:\t\t%s\n"
  39. "Line:\t\t%u\n"
  40. "Time Stamp:\t%s\n"
  41. "-------------------------------------------------------------------------------\n",
  42. filename, linenum, timestamp
  43. );
  44. if (expr)
  45. {
  46. wsprintfA(pch, "Expression:\t%s\n"
  47. "-------------------------------------------------------------------------------\n",
  48. expr
  49. );
  50. }
  51. TRACEEOL(sz);
  52. int nReturn = MessageBoxA(
  53. NULL,
  54. sz,
  55. "ASSERT FAILURE!",
  56. MB_ABORTRETRYIGNORE | MB_DEFBUTTON1 | MB_ICONHAND
  57. );
  58. if (nReturn == IDABORT)
  59. {
  60. exit(-1);
  61. }
  62. //
  63. // Return 1 to break, 0 to ignore
  64. //
  65. return (nReturn == IDRETRY);
  66. }
  67. #endif // _DEBUG || DBG
  68. #if defined(_DEBUG) || DBG
  69. #ifndef _DEBUG
  70. //
  71. // SDK build links with retail MFC. Swiped code from MFC sources. Some
  72. // modifications.
  73. //
  74. COMDLL CDumpContext afxDump;
  75. COMDLL BOOL afxTraceEnabled = TRUE;
  76. void
  77. CDumpContext::OutputString(LPCTSTR lpsz)
  78. {
  79. if (m_pFile == NULL)
  80. {
  81. OutputDebugString(lpsz);
  82. return;
  83. }
  84. m_pFile->Write(lpsz, lstrlen(lpsz)*sizeof(TCHAR));
  85. }
  86. CDumpContext::CDumpContext(CFile * pFile)
  87. {
  88. if (pFile)
  89. {
  90. ASSERT_PTR(pFile);
  91. }
  92. m_pFile = pFile;
  93. m_nDepth = 0;
  94. }
  95. void
  96. CDumpContext::Flush()
  97. {
  98. if (m_pFile)
  99. {
  100. m_pFile->Flush();
  101. }
  102. }
  103. CDumpContext& CDumpContext::operator<<(LPCTSTR lpsz)
  104. {
  105. if (lpsz == NULL)
  106. {
  107. OutputString(_T("(NULL)"));
  108. return *this;
  109. }
  110. if (m_pFile == NULL)
  111. {
  112. TCHAR szBuffer[512];
  113. LPTSTR lpBuf = szBuffer;
  114. while (*lpsz != '\0')
  115. {
  116. if (lpBuf > szBuffer + ARRAY_SIZE(szBuffer) - 3)
  117. {
  118. *lpBuf = '\0';
  119. OutputString(szBuffer);
  120. lpBuf = szBuffer;
  121. }
  122. if (*lpsz == '\n')
  123. {
  124. *lpBuf++ = '\r';
  125. }
  126. *lpBuf++ = *lpsz++;
  127. }
  128. *lpBuf = '\0';
  129. OutputString(szBuffer);
  130. return *this;
  131. }
  132. m_pFile->Write(lpsz, lstrlen(lpsz) * sizeof(TCHAR));
  133. return *this;
  134. }
  135. CDumpContext& CDumpContext::operator<<(BYTE by)
  136. {
  137. TCHAR szBuffer[32];
  138. wsprintf(szBuffer, _T("%d"), (int)by);
  139. OutputString(szBuffer);
  140. return *this;
  141. }
  142. CDumpContext& CDumpContext::operator<<(WORD w)
  143. {
  144. TCHAR szBuffer[32];
  145. wsprintf(szBuffer, _T("%u"), (UINT) w);
  146. OutputString(szBuffer);
  147. return *this;
  148. }
  149. CDumpContext& CDumpContext::operator<<(UINT u)
  150. {
  151. TCHAR szBuffer[32];
  152. wsprintf(szBuffer, _T("0x%X"), u);
  153. OutputString(szBuffer);
  154. return *this;
  155. }
  156. CDumpContext& CDumpContext::operator<<(LONG l)
  157. {
  158. TCHAR szBuffer[32];
  159. wsprintf(szBuffer, _T("%ld"), l);
  160. OutputString(szBuffer);
  161. return *this;
  162. }
  163. CDumpContext& CDumpContext::operator<<(DWORD dw)
  164. {
  165. TCHAR szBuffer[32];
  166. wsprintf(szBuffer, _T("%lu"), dw);
  167. OutputString(szBuffer);
  168. return *this;
  169. }
  170. CDumpContext& CDumpContext::operator<<(int n)
  171. {
  172. TCHAR szBuffer[32];
  173. wsprintf(szBuffer, _T("%d"), n);
  174. OutputString(szBuffer);
  175. return *this;
  176. }
  177. CDumpContext& CDumpContext::operator<<(const CObject * pOb)
  178. {
  179. if (pOb == NULL)
  180. {
  181. *this << _T("NULL");
  182. }
  183. else
  184. {
  185. pOb->Dump(*this);
  186. }
  187. return *this;
  188. }
  189. CDumpContext& CDumpContext::operator<<(const CObject & ob)
  190. {
  191. return *this << &ob;
  192. }
  193. CDumpContext& CDumpContext::operator<<(const void * lp)
  194. {
  195. TCHAR szBuffer[32];
  196. wsprintf(szBuffer, _T("$%p"), lp);
  197. OutputString(szBuffer);
  198. return *this;
  199. }
  200. void
  201. CDumpContext::HexDump(
  202. LPCTSTR lpszLine,
  203. BYTE * pby,
  204. int nBytes,
  205. int nWidth
  206. )
  207. {
  208. ASSERT(nBytes > 0);
  209. ASSERT(nWidth > 0);
  210. ASSERT(AfxIsValidString(lpszLine));
  211. ASSERT(AfxIsValidAddress(pby, nBytes, FALSE));
  212. int nRow = 0;
  213. TCHAR szBuffer[32];
  214. while (nBytes--)
  215. {
  216. if (nRow == 0)
  217. {
  218. wsprintf(szBuffer, lpszLine, pby);
  219. *this << szBuffer;
  220. }
  221. wsprintf(szBuffer, _T(" %02X"), *pby++);
  222. *this << szBuffer;
  223. if (++nRow >= nWidth)
  224. {
  225. *this << _T("\n");
  226. nRow = 0;
  227. }
  228. }
  229. if (nRow != 0)
  230. {
  231. *this << _T("\n");
  232. }
  233. }
  234. /////////////////////////////////////////////////////////////////////////////
  235. #ifdef _UNICODE
  236. CDumpContext & CDumpContext::operator<<(LPCSTR lpsz)
  237. {
  238. if (lpsz == NULL)
  239. {
  240. OutputString(L"(NULL)");
  241. return *this;
  242. }
  243. TCHAR szBuffer[512];
  244. _mbstowcsz(szBuffer, lpsz, ARRAY_SIZE(szBuffer));
  245. return *this << szBuffer;
  246. }
  247. #else //_UNICODE
  248. CDumpContext& CDumpContext::operator<<(LPCWSTR lpsz)
  249. {
  250. if (lpsz == NULL)
  251. {
  252. OutputString("(NULL)");
  253. return *this;
  254. }
  255. char szBuffer[512];
  256. _wcstombsz(szBuffer, lpsz, ARRAY_SIZE(szBuffer));
  257. return *this << szBuffer;
  258. }
  259. #endif //!_UNICODE
  260. //
  261. // End of block of code copied from MFC
  262. //
  263. #endif // _DEBUG
  264. LPCSTR
  265. DbgFmtPgm(
  266. IN LPCSTR szFn,
  267. IN int line
  268. )
  269. /*++
  270. Routine Description:
  271. Format debugging string containing file name and line number. Remove
  272. the path portion of the file name if present.
  273. Arguments:
  274. LPCSTR szFn : File name (ANSI)
  275. int line : Line number
  276. Return Value:
  277. Pointer to the internal buffer
  278. --*/
  279. {
  280. LPCSTR pszTail = szFn + lstrlenA(szFn);
  281. static CHAR szBuff[MAX_PATH + 1];
  282. for ( /**/; pszTail > szFn; --pszTail)
  283. {
  284. if (*pszTail == '\\' || *pszTail == ':')
  285. {
  286. ++pszTail;
  287. break;
  288. }
  289. }
  290. wsprintfA(szBuff, "[%s:%d] ", pszTail, line);
  291. return szBuff;
  292. }
  293. CDumpContext &
  294. operator <<(
  295. IN OUT CDumpContext & out,
  296. IN ENUM_DEBUG_AFX edAfx
  297. )
  298. /*++
  299. Routine Description:
  300. Output debugging control character to the debug context
  301. Arguments:
  302. CDumpContext & out : Output debugging context
  303. edAfx : Control character
  304. Return Value:
  305. Output debugging context reference
  306. --*/
  307. {
  308. static CHAR * szEol = "\r\n";
  309. switch (edAfx)
  310. {
  311. case EDBUG_AFX_EOL:
  312. out << szEol;
  313. break;
  314. default:
  315. break;
  316. }
  317. return out;
  318. }
  319. #ifndef UNICODE
  320. CDumpContext &
  321. operator <<(
  322. IN OUT CDumpContext & out,
  323. IN LPCWSTR pwchStr
  324. )
  325. /*++
  326. Routine Description:
  327. Insert a wide-character string into the output stream. For non-UNICODE only,
  328. as this functions would be handled by the generic 'T' function otherwise.
  329. Arguments:
  330. CDumpContext & out : Output debugging context
  331. pwchStr : Wide character string
  332. Return Value:
  333. Output debugging context reference
  334. --*/
  335. {
  336. size_t cwch ;
  337. if (pwchStr == NULL)
  338. {
  339. out << "<null>";
  340. }
  341. else if ((cwch = ::wcslen(pwchStr )) > 0)
  342. {
  343. CHAR * pszTemp = (LPSTR)AllocMem(cwch + 2);
  344. if (pszTemp != NULL)
  345. {
  346. for (int i = 0; pwchStr[i]; ++i)
  347. {
  348. pszTemp[i] = (CHAR)pwchStr[i];
  349. }
  350. pszTemp[i] = 0;
  351. out << pszTemp;
  352. FreeMem(pszTemp);
  353. }
  354. else
  355. {
  356. out << "<memerr>";
  357. }
  358. }
  359. else
  360. {
  361. out << "\"\"";
  362. }
  363. return out;
  364. }
  365. #endif // UNICODE
  366. CDumpContext &
  367. operator <<(
  368. IN CDumpContext & out,
  369. IN const GUID & guid
  370. )
  371. /*++
  372. Routine Description:
  373. Dump a GUID to the debugger
  374. Arguments:
  375. CDumpContext & out : Output debugging context
  376. GUID & guid : GUID
  377. Return Value:
  378. Output debugging context reference
  379. --*/
  380. {
  381. out << "{ "
  382. << guid.Data1
  383. << ","
  384. << guid.Data2
  385. << ","
  386. << guid.Data3
  387. << ","
  388. << guid.Data4
  389. << "}";
  390. return out;
  391. }
  392. #endif // _DEBUG