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.

585 lines
14 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: debug.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. /*----------------------------------------------------------------------------
  11. / Title;
  12. / debug.cpp
  13. /
  14. / Authors;
  15. / David De Vorchik (daviddv)
  16. /
  17. / Notes;
  18. / Provides printf style debug output
  19. /----------------------------------------------------------------------------*/
  20. #include "precomp.hxx"
  21. #include "stdio.h"
  22. #pragma hdrstop
  23. #ifdef DEBUG
  24. /*-----------------------------------------------------------------------------
  25. / Locals & helper functions
  26. /----------------------------------------------------------------------------*/
  27. #define GETDEPTH(x) (x)=reinterpret_cast<UINT_PTR>(TlsGetValue (g_dwMargin));
  28. #define SETDEPTH(x) TlsSetValue (g_dwMargin, reinterpret_cast<LPVOID>((x)));
  29. DWORD g_dwMargin=0;
  30. DWORD g_dwTraceMask = 0;
  31. #define MAX_CALL_DEPTH 64
  32. #define BUFFER_SIZE 4096
  33. /*-----------------------------------------------------------------------------
  34. / _indent
  35. / -------
  36. / Output to the debug stream indented by n columns.
  37. /
  38. / In:
  39. / i = column to indent to.
  40. / pString -> string to be indented
  41. /
  42. / Out:
  43. / -
  44. /----------------------------------------------------------------------------*/
  45. void _indent(UINT_PTR i, LPCTSTR pString)
  46. {
  47. TCHAR szIndentBuffer[BUFFER_SIZE];
  48. szIndentBuffer[0] = TEXT('\0');
  49. wsprintf(szIndentBuffer, TEXT("%08x "), GetCurrentThreadId());
  50. for ( ; i > 0 ; i-- )
  51. lstrcat(szIndentBuffer, TEXT(" "));
  52. lstrcat(szIndentBuffer, pString);
  53. lstrcat(szIndentBuffer, TEXT("\n"));
  54. OutputDebugString(szIndentBuffer);
  55. }
  56. /*-----------------------------------------------------------------------------
  57. / DoTraceSetMask
  58. / --------------
  59. / Adjust the trace mask to reflect the state given.
  60. /
  61. / In:
  62. / dwMask = mask for enabling / disable trace output
  63. /
  64. / Out:
  65. / -
  66. /----------------------------------------------------------------------------*/
  67. void DoTraceSetMask(DWORD dwMask)
  68. {
  69. g_dwTraceMask = dwMask;
  70. }
  71. /*-----------------------------------------------------------------------------
  72. / DoTraceEnter
  73. / ------------
  74. / Display the name of the function we are in.
  75. /
  76. / In:
  77. / pName -> function name to be displayed in subsequent trace output.
  78. /
  79. / Out:
  80. / -
  81. /----------------------------------------------------------------------------*/
  82. void DoTraceEnter(DWORD dwMask, LPCTSTR pName)
  83. {
  84. UINT_PTR uDepth=0;
  85. TCHAR szStr[300];
  86. GETDEPTH(uDepth);
  87. uDepth++;
  88. SETDEPTH(uDepth);
  89. if ( !pName )
  90. pName = TEXT("<no name>"); // no function name given
  91. wsprintf (szStr, TEXT("ENTER: %s"), pName);
  92. _indent (uDepth, szStr);
  93. }
  94. /*-----------------------------------------------------------------------------
  95. / DoTraceLeave
  96. / ------------
  97. / On exit from a function, decrement the margin
  98. /
  99. / In:
  100. / -
  101. / Out:
  102. / -
  103. /----------------------------------------------------------------------------*/
  104. void DoTraceLeave(void)
  105. {
  106. UINT_PTR uDepth;
  107. GETDEPTH (uDepth);
  108. uDepth--;
  109. SETDEPTH(uDepth);
  110. }
  111. /*-----------------------------------------------------------------------------
  112. / DoTrace
  113. / -------
  114. / Perform printf formatting to the debugging stream. We indent the output
  115. / and stream the function name as required to give some indication of
  116. / call stack depth.
  117. /
  118. / In:
  119. / pFormat -> printf style formatting string
  120. / ... = arguments as required for the formatting
  121. /
  122. / Out:
  123. / -
  124. /----------------------------------------------------------------------------*/
  125. void DoTrace(LPCTSTR pFormat, ...)
  126. {
  127. va_list va;
  128. TCHAR szTraceBuffer[BUFFER_SIZE];
  129. UINT_PTR uDepth;
  130. GETDEPTH(uDepth);
  131. if ( uDepth < MAX_CALL_DEPTH )
  132. {
  133. va_start(va, pFormat);
  134. wvsprintf(szTraceBuffer, pFormat, va);
  135. va_end(va);
  136. _indent(uDepth+1, szTraceBuffer);
  137. }
  138. }
  139. /*-----------------------------------------------------------------------------
  140. / DoTraceGuid
  141. / -----------
  142. / Given a GUID output it into the debug string, first we try and map it
  143. / to a name (ie. IShellFolder), if that didn't work then we convert it
  144. / to its human readable form.
  145. /
  146. / In:
  147. / pszPrefix -> prefix string
  148. / lpGuid -> guid to be streamed
  149. /
  150. / Out:
  151. / -
  152. /----------------------------------------------------------------------------*/
  153. #ifdef UNICODE
  154. #define MAP_GUID(x) &x, TEXT(""L#x)
  155. #else
  156. #define MAP_GUID(x) &x, TEXT(""#x)
  157. #endif
  158. #define MAP_GUID2(x,y) MAP_GUID(x), MAP_GUID(y)
  159. const struct
  160. {
  161. const GUID* m_pGUID;
  162. LPCTSTR m_pName;
  163. }
  164. _guid_map[] =
  165. {
  166. MAP_GUID(IID_IUnknown),
  167. MAP_GUID(IID_IClassFactory),
  168. MAP_GUID(IID_IDropTarget),
  169. MAP_GUID(IID_IDataObject),
  170. MAP_GUID(IID_IPersist),
  171. MAP_GUID(IID_IPersistStream),
  172. MAP_GUID(IID_IPersistFolder),
  173. MAP_GUID(IID_IPersistFolder2),
  174. MAP_GUID(IID_IPersistFile),
  175. MAP_GUID(IID_IOleWindow),
  176. MAP_GUID2(IID_INewShortcutHookA, IID_INewShortcutHookW),
  177. MAP_GUID(IID_IShellBrowser),
  178. MAP_GUID(IID_IShellView),
  179. MAP_GUID(IID_IContextMenu),
  180. MAP_GUID(IID_IShellIcon),
  181. MAP_GUID(IID_IShellFolder),
  182. MAP_GUID(IID_IShellExtInit),
  183. MAP_GUID(IID_IShellPropSheetExt),
  184. MAP_GUID2(IID_IExtractIconA, IID_IExtractIconW),
  185. MAP_GUID2(IID_IShellLinkA, IID_IShellLinkW),
  186. MAP_GUID2(IID_IShellCopyHookA, IID_IShellCopyHookW),
  187. MAP_GUID2(IID_IFileViewerA, IID_IFileViewerW),
  188. MAP_GUID(IID_ICommDlgBrowser),
  189. MAP_GUID(IID_IEnumIDList),
  190. MAP_GUID(IID_IFileViewerSite),
  191. MAP_GUID(IID_IContextMenu2),
  192. MAP_GUID2(IID_IShellExecuteHookA, IID_IShellExecuteHookW),
  193. MAP_GUID(IID_IPropSheetPage),
  194. MAP_GUID(IID_IShellView2),
  195. MAP_GUID(IID_IUniformResourceLocator),
  196. MAP_GUID(IID_IShellDetails),
  197. MAP_GUID(IID_IShellExtInit),
  198. MAP_GUID(IID_IShellPropSheetExt),
  199. MAP_GUID(IID_IShellIconOverlay),
  200. MAP_GUID(IID_IExtractImage),
  201. MAP_GUID(IID_IExtractImage2),
  202. MAP_GUID(IID_IQueryInfo),
  203. MAP_GUID(IID_IShellDetails3),
  204. MAP_GUID(IID_IShellView2),
  205. MAP_GUID(IID_IShellFolder2),
  206. MAP_GUID(IID_IShellIconOverlay),
  207. MAP_GUID(IID_IMoniker),
  208. MAP_GUID(IID_IStream),
  209. MAP_GUID(IID_ISequentialStream),
  210. MAP_GUID(IID_IPersistFreeThreadedObject),
  211. };
  212. void DoTraceGUID(LPCTSTR pPrefix, REFGUID rGUID)
  213. {
  214. TCHAR szGUID[GUIDSTR_MAX];
  215. TCHAR szBuffer[1024];
  216. LPCTSTR pName = NULL;
  217. size_t i;
  218. UINT_PTR uDepth;
  219. GETDEPTH(uDepth);
  220. if ( uDepth < MAX_CALL_DEPTH )
  221. {
  222. for ( i = 0 ; i < ARRAYSIZE(_guid_map); i++ )
  223. {
  224. if ( IsEqualGUID(rGUID, *_guid_map[i].m_pGUID) )
  225. {
  226. pName = _guid_map[i].m_pName;
  227. break;
  228. }
  229. }
  230. if ( !pName )
  231. {
  232. SHStringFromGUID(rGUID, szGUID, ARRAYSIZE(szGUID));
  233. pName = szGUID;
  234. }
  235. wsprintf(szBuffer, TEXT("%s %s"), pPrefix, pName);
  236. _indent(uDepth+1, szBuffer);
  237. }
  238. }
  239. /*-----------------------------------------------------------------------------
  240. / DoTraceViewMsg
  241. / --------------
  242. / Given a view msg (SFVM_ && DVM_), print out the corresponding text...
  243. /
  244. / In:
  245. / uMsg -> msg to be streamed
  246. / wParam -> wParam value for message
  247. / lParam -> lParam value for message
  248. /
  249. / Out:
  250. / -
  251. /----------------------------------------------------------------------------*/
  252. #ifdef UNICODE
  253. #define MAP_MSG(x) x, TEXT(""L#x)
  254. #else
  255. #define MAP_MSG(x) x, TEXT(""#x)
  256. #endif
  257. const struct
  258. {
  259. UINT m_uMsg;
  260. LPCTSTR m_pName;
  261. }
  262. _view_msg_map[] =
  263. {
  264. MAP_MSG(SFVM_MERGEMENU),
  265. MAP_MSG(SFVM_INVOKECOMMAND),
  266. MAP_MSG(SFVM_GETHELPTEXT),
  267. MAP_MSG(SFVM_GETTOOLTIPTEXT),
  268. MAP_MSG(SFVM_GETBUTTONINFO),
  269. MAP_MSG(SFVM_GETBUTTONS),
  270. MAP_MSG(SFVM_INITMENUPOPUP),
  271. MAP_MSG(SFVM_SELCHANGE),
  272. MAP_MSG(SFVM_DRAWITEM),
  273. MAP_MSG(SFVM_MEASUREITEM),
  274. MAP_MSG(SFVM_EXITMENULOOP),
  275. MAP_MSG(SFVM_PRERELEASE),
  276. MAP_MSG(SFVM_GETCCHMAX),
  277. MAP_MSG(SFVM_FSNOTIFY),
  278. MAP_MSG(SFVM_WINDOWCREATED),
  279. MAP_MSG(SFVM_WINDOWDESTROY),
  280. MAP_MSG(SFVM_REFRESH),
  281. MAP_MSG(SFVM_SETFOCUS),
  282. MAP_MSG(SFVM_QUERYCOPYHOOK),
  283. MAP_MSG(SFVM_NOTIFYCOPYHOOK),
  284. MAP_MSG(SFVM_GETDETAILSOF),
  285. MAP_MSG(SFVM_COLUMNCLICK),
  286. MAP_MSG(SFVM_QUERYFSNOTIFY),
  287. MAP_MSG(SFVM_DEFITEMCOUNT),
  288. MAP_MSG(SFVM_DEFVIEWMODE),
  289. MAP_MSG(SFVM_UNMERGEMENU),
  290. MAP_MSG(SFVM_INSERTITEM),
  291. MAP_MSG(SFVM_DELETEITEM),
  292. MAP_MSG(SFVM_UPDATESTATUSBAR),
  293. MAP_MSG(SFVM_BACKGROUNDENUM),
  294. MAP_MSG(SFVM_GETWORKINGDIR),
  295. MAP_MSG(SFVM_GETCOLSAVESTREAM),
  296. MAP_MSG(SFVM_SELECTALL),
  297. MAP_MSG(SFVM_DIDDRAGDROP),
  298. MAP_MSG(SFVM_SUPPORTSIDENTITY),
  299. MAP_MSG(SFVM_FOLDERISPARENT),
  300. MAP_MSG(SFVM_SETISFV),
  301. MAP_MSG(SFVM_GETVIEWS),
  302. MAP_MSG(SFVM_THISIDLIST),
  303. MAP_MSG(SFVM_GETITEMIDLIST),
  304. MAP_MSG(SFVM_SETITEMIDLIST),
  305. MAP_MSG(SFVM_INDEXOFITEMIDLIST),
  306. MAP_MSG(SFVM_ODFINDITEM),
  307. MAP_MSG(SFVM_HWNDMAIN),
  308. MAP_MSG(SFVM_ADDPROPERTYPAGES),
  309. MAP_MSG(SFVM_BACKGROUNDENUMDONE),
  310. MAP_MSG(SFVM_GETNOTIFY),
  311. MAP_MSG(SFVM_ARRANGE),
  312. MAP_MSG(SFVM_QUERYSTANDARDVIEWS),
  313. MAP_MSG(SFVM_QUERYREUSEEXTVIEW),
  314. MAP_MSG(SFVM_GETSORTDEFAULTS),
  315. MAP_MSG(SFVM_GETEMPTYTEXT),
  316. MAP_MSG(SFVM_GETITEMICONINDEX),
  317. MAP_MSG(SFVM_DONTCUSTOMIZE),
  318. MAP_MSG(SFVM_SIZE),
  319. MAP_MSG(SFVM_GETZONE),
  320. MAP_MSG(SFVM_GETPANE),
  321. MAP_MSG(SFVM_ISOWNERDATA),
  322. MAP_MSG(SFVM_GETODRANGEOBJECT),
  323. MAP_MSG(SFVM_ODCACHEHINT),
  324. MAP_MSG(SFVM_GETHELPTOPIC),
  325. MAP_MSG(SFVM_OVERRIDEITEMCOUNT),
  326. MAP_MSG(SFVM_GETHELPTEXTW),
  327. MAP_MSG(SFVM_GETTOOLTIPTEXTW),
  328. MAP_MSG(SFVM_GETIPERSISTHISTORY),
  329. MAP_MSG(SFVM_GETANIMATION),
  330. };
  331. const struct
  332. {
  333. UINT m_uMsg;
  334. LPCTSTR m_pName;
  335. }
  336. _shcn_msg_map[] =
  337. {
  338. MAP_MSG(SHCNE_RENAMEITEM),
  339. MAP_MSG(SHCNE_CREATE),
  340. MAP_MSG(SHCNE_DELETE),
  341. MAP_MSG(SHCNE_MKDIR),
  342. MAP_MSG(SHCNE_RMDIR),
  343. MAP_MSG(SHCNE_MEDIAINSERTED),
  344. MAP_MSG(SHCNE_MEDIAREMOVED),
  345. MAP_MSG(SHCNE_DRIVEREMOVED),
  346. MAP_MSG(SHCNE_DRIVEADD),
  347. MAP_MSG(SHCNE_NETSHARE),
  348. MAP_MSG(SHCNE_NETUNSHARE),
  349. MAP_MSG(SHCNE_ATTRIBUTES),
  350. MAP_MSG(SHCNE_UPDATEDIR),
  351. MAP_MSG(SHCNE_UPDATEITEM),
  352. MAP_MSG(SHCNE_SERVERDISCONNECT),
  353. MAP_MSG(SHCNE_UPDATEIMAGE),
  354. MAP_MSG(SHCNE_DRIVEADDGUI),
  355. MAP_MSG(SHCNE_RENAMEFOLDER),
  356. MAP_MSG(SHCNE_FREESPACE),
  357. };
  358. void DoTraceViewMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  359. {
  360. LPCTSTR pName = NULL;
  361. TCHAR szBuffer[1024];
  362. TCHAR szTmp[25];
  363. TCHAR szTmp2[25];
  364. size_t i;
  365. UINT_PTR uDepth;
  366. GETDEPTH(uDepth);
  367. if ( uDepth < MAX_CALL_DEPTH )
  368. {
  369. for ( i = 0 ; i < ARRAYSIZE(_view_msg_map); i++ )
  370. {
  371. if ( _view_msg_map[i].m_uMsg == uMsg )
  372. {
  373. pName = _view_msg_map[i].m_pName;
  374. break;
  375. }
  376. }
  377. if (!pName)
  378. {
  379. wsprintf( szTmp, TEXT("SFVM_(%d)"), uMsg );
  380. pName = szTmp;
  381. }
  382. if (uMsg == SFVM_FSNOTIFY)
  383. {
  384. LPCTSTR pEvent = NULL;
  385. for (i= 0; i < ARRAYSIZE(_shcn_msg_map); i++)
  386. {
  387. if ( _shcn_msg_map[i].m_uMsg == uMsg )
  388. {
  389. pEvent = _shcn_msg_map[i].m_pName;
  390. break;
  391. }
  392. }
  393. if (!pEvent)
  394. {
  395. lstrcpy(szTmp2,TEXT("Unknown"));
  396. pEvent = szTmp2;
  397. }
  398. wsprintf(szBuffer, TEXT("%s w(%08X) l(%08X == %s)"), pName, wParam, lParam, pEvent);
  399. _indent(uDepth+1, szBuffer);
  400. }
  401. else
  402. {
  403. wsprintf(szBuffer, TEXT("%s w(%08X) l(%08X)"), pName, wParam, lParam);
  404. _indent(uDepth+1, szBuffer);
  405. }
  406. }
  407. }
  408. const struct
  409. {
  410. UINT m_uMsg;
  411. LPCTSTR m_pName;
  412. }
  413. _menu_msg_map[] =
  414. {
  415. MAP_MSG(DFM_MERGECONTEXTMENU),
  416. MAP_MSG(DFM_INVOKECOMMAND),
  417. MAP_MSG(DFM_ADDREF),
  418. MAP_MSG(DFM_RELEASE),
  419. MAP_MSG(DFM_GETHELPTEXT),
  420. MAP_MSG(DFM_WM_MEASUREITEM),
  421. MAP_MSG(DFM_WM_DRAWITEM),
  422. MAP_MSG(DFM_WM_INITMENUPOPUP),
  423. MAP_MSG(DFM_VALIDATECMD),
  424. MAP_MSG(DFM_MERGECONTEXTMENU_TOP),
  425. MAP_MSG(DFM_GETHELPTEXTW),
  426. MAP_MSG(DFM_INVOKECOMMANDEX),
  427. MAP_MSG(DFM_MAPCOMMANDNAME),
  428. MAP_MSG(DFM_GETDEFSTATICID),
  429. MAP_MSG(DFM_GETVERBW),
  430. };
  431. const struct
  432. {
  433. WPARAM m_uMsg;
  434. LPCTSTR m_pName;
  435. }
  436. _menu_invk_cmd_msg_map[] =
  437. {
  438. MAP_MSG(DFM_CMD_RENAME),
  439. MAP_MSG(DFM_CMD_MODALPROP),
  440. MAP_MSG(DFM_CMD_PASTESPECIAL),
  441. MAP_MSG(DFM_CMD_PASTELINK),
  442. MAP_MSG(DFM_CMD_VIEWDETAILS),
  443. MAP_MSG(DFM_CMD_VIEWLIST),
  444. MAP_MSG(DFM_CMD_PASTE),
  445. MAP_MSG(DFM_CMD_NEWFOLDER),
  446. MAP_MSG(DFM_CMD_PROPERTIES),
  447. MAP_MSG(DFM_CMD_LINK),
  448. MAP_MSG(DFM_CMD_COPY),
  449. MAP_MSG(DFM_CMD_MOVE),
  450. MAP_MSG(DFM_CMD_DELETE),
  451. };
  452. void DoTraceMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  453. {
  454. LPCTSTR pName = NULL;
  455. TCHAR szBuffer[1024];
  456. TCHAR szTmp[25];
  457. size_t i;
  458. UINT_PTR uDepth;
  459. GETDEPTH (uDepth);
  460. if ( uDepth < MAX_CALL_DEPTH )
  461. {
  462. for ( i = 0 ; i < ARRAYSIZE(_menu_msg_map); i++ )
  463. {
  464. if ( _menu_msg_map[i].m_uMsg == uMsg )
  465. {
  466. pName = _menu_msg_map[i].m_pName;
  467. break;
  468. }
  469. }
  470. if (!pName)
  471. {
  472. wsprintf( szTmp, TEXT("DFM_(%d)"), uMsg );
  473. pName = szTmp;
  474. }
  475. if ((uMsg == DFM_INVOKECOMMAND) && (wParam >= DFM_CMD_RENAME))
  476. {
  477. wsprintf(szBuffer, TEXT("%s w(%s) l(%08X)"), pName, _menu_invk_cmd_msg_map[wParam-DFM_CMD_RENAME].m_pName, lParam);
  478. }
  479. else
  480. {
  481. wsprintf(szBuffer, TEXT("%s w(%08X) l(%08X)"), pName, wParam, lParam);
  482. }
  483. _indent(uDepth+1, szBuffer);
  484. }
  485. }
  486. /*-----------------------------------------------------------------------------
  487. / DoTraceAssert
  488. / -------------
  489. / Our assert handler, out faults it the trace mask as enabled assert
  490. / faulting.
  491. /
  492. / In:
  493. / iLine = line
  494. / pFilename -> filename of the file we asserted in
  495. /
  496. / Out:
  497. / -
  498. /----------------------------------------------------------------------------*/
  499. void DoTraceAssert(int iLine, LPTSTR pFilename)
  500. {
  501. TCHAR szBuffer[1024];
  502. UINT_PTR uDepth;
  503. GETDEPTH(uDepth);
  504. wsprintf(szBuffer, TEXT("Assert failed in %s, line %d"), pFilename, iLine);
  505. _indent(uDepth+1, szBuffer);
  506. if ( g_dwTraceMask & TRACE_COMMON_ASSERT )
  507. DebugBreak();
  508. }
  509. #endif