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.

383 lines
10 KiB

  1. #include "pch.h"
  2. #include "stdio.h"
  3. #pragma hdrstop
  4. #ifdef DSUI_DEBUG
  5. LONG g_cDepth = -1;
  6. DWORD g_dwTraceMask = 0;
  7. #define MAX_CALL_DEPTH 64
  8. struct
  9. {
  10. BOOL m_fTracedYet : 1;
  11. LPCTSTR m_pFunctionName;
  12. DWORD m_dwMask;
  13. }
  14. g_CallStack[MAX_CALL_DEPTH];
  15. #define BUFFER_SIZE 4096
  16. static TCHAR szIndentBuffer[BUFFER_SIZE];
  17. static TCHAR szTraceBuffer[BUFFER_SIZE];
  18. /*-----------------------------------------------------------------------------
  19. / _indent
  20. / -------
  21. / Output to the debug stream indented by n columns.
  22. /
  23. / In:
  24. / i = column to indent to.
  25. / pString -> string to be indented
  26. /
  27. / Out:
  28. / -
  29. /----------------------------------------------------------------------------*/
  30. void _indent(LONG i, LPCTSTR pString)
  31. {
  32. szIndentBuffer[0] = TEXT('\0');
  33. wnsprintf(szIndentBuffer, ARRAYSIZE(szIndentBuffer), TEXT("%08x "), GetCurrentThreadId());
  34. for ( ; i > 0 ; i-- )
  35. StrCatBuff(szIndentBuffer, TEXT(" "), ARRAYSIZE(szIndentBuffer));
  36. StrCatBuff(szIndentBuffer, pString, ARRAYSIZE(szIndentBuffer));
  37. StrCatBuff(szIndentBuffer, TEXT("\n"), ARRAYSIZE(szIndentBuffer));
  38. OutputDebugString(szIndentBuffer);
  39. }
  40. /*-----------------------------------------------------------------------------
  41. / _output_proc_name
  42. / -----------------
  43. / Handle the output of a procedure name, including indenting and handling
  44. / the opening braces.
  45. /
  46. / In:
  47. / iCallDepth = callstack depth, defines the indent and the name index
  48. / to be extracted.
  49. / fOpenBrace = suffix with opening brace.
  50. / Out:
  51. / -
  52. /----------------------------------------------------------------------------*/
  53. void _output_proc_name(LONG iCallDepth)
  54. {
  55. _indent(iCallDepth, g_CallStack[iCallDepth].m_pFunctionName);
  56. }
  57. /*-----------------------------------------------------------------------------
  58. / _trace_prolog
  59. / -------------
  60. / Handle the prolog to a prefix string, including outputting the
  61. / function name if we haven't already.
  62. /
  63. / In:
  64. / iDepth = depth in the call stack
  65. / fForce = ignore flags
  66. /
  67. / Out:
  68. / BOOL if trace output should be made
  69. /----------------------------------------------------------------------------*/
  70. BOOL _trace_prolog(LONG iDepth, BOOL fForce)
  71. {
  72. if ( (g_dwTraceMask & g_CallStack[iDepth].m_dwMask) || fForce )
  73. {
  74. if ( iDepth > 0 )
  75. {
  76. if ( !g_CallStack[iDepth-1].m_fTracedYet )
  77. _trace_prolog(iDepth-1, TRUE);
  78. }
  79. if ( !g_CallStack[iDepth].m_fTracedYet )
  80. {
  81. _output_proc_name(iDepth);
  82. g_CallStack[iDepth].m_fTracedYet = TRUE;
  83. }
  84. return TRUE;
  85. }
  86. return FALSE;
  87. }
  88. /*-----------------------------------------------------------------------------
  89. / DoTraceSetMask
  90. / --------------
  91. / Adjust the trace mask to reflect the state given.
  92. /
  93. / In:
  94. / dwMask = mask for enabling / disable trace output
  95. /
  96. / Out:
  97. / -
  98. /----------------------------------------------------------------------------*/
  99. EXTERN_C void DoTraceSetMask(DWORD dwMask)
  100. {
  101. g_dwTraceMask = dwMask;
  102. }
  103. /*-----------------------------------------------------------------------------
  104. / DoTraceSetMaskFromCLSID
  105. / -----------------------
  106. / Pick up the TraceMask value from the given CLSID value and
  107. / set the trace mask using that.
  108. /
  109. / In:
  110. / clsid = CLSID to query the value from
  111. /
  112. / Out:
  113. / -
  114. /----------------------------------------------------------------------------*/
  115. EXTERN_C void DoTraceSetMaskFromCLSID(REFCLSID rCLSID)
  116. {
  117. HKEY hKey = NULL;
  118. if ( SUCCEEDED(GetKeyForCLSID(rCLSID, NULL, &hKey)) )
  119. {
  120. DWORD dwTraceMask;
  121. DWORD cbTraceMask = SIZEOF(dwTraceMask);
  122. DWORD dwType = REG_DWORD;
  123. if ( ERROR_SUCCESS == RegQueryValueEx(hKey, TEXT("TraceMask"), NULL, &dwType, (LPBYTE)&dwTraceMask, &cbTraceMask) )
  124. {
  125. if (dwType == REG_DWORD)
  126. {
  127. TraceSetMask(dwTraceMask);
  128. }
  129. }
  130. RegCloseKey(hKey);
  131. }
  132. }
  133. /*-----------------------------------------------------------------------------
  134. / DoTraceEnter
  135. / ------------
  136. / Set the debugging call stack up to indicate which function we are in.
  137. /
  138. / In:
  139. / pName -> function name to be displayed in subsequent trace output.
  140. /
  141. / Out:
  142. / -
  143. /----------------------------------------------------------------------------*/
  144. EXTERN_C void DoTraceEnter(DWORD dwMask, LPCTSTR pName)
  145. {
  146. g_cDepth++;
  147. if ( g_cDepth < MAX_CALL_DEPTH )
  148. {
  149. if ( !pName )
  150. pName = TEXT("<no name>"); // no function name given
  151. g_CallStack[g_cDepth].m_fTracedYet = FALSE;
  152. g_CallStack[g_cDepth].m_pFunctionName = pName;
  153. g_CallStack[g_cDepth].m_dwMask = dwMask;
  154. if ( (g_cDepth > 0) && ( g_cDepth < MAX_CALL_DEPTH ) )
  155. _trace_prolog(g_cDepth-1, FALSE);
  156. }
  157. }
  158. /*-----------------------------------------------------------------------------
  159. / DoTraceLeave
  160. / ------------
  161. / On exit from a function this will adjust the function stack pointer to
  162. / point to our previous function. If no trace output has been made then
  163. / we will output the function name on a single line (to indicate we went somewhere).
  164. /
  165. / In:
  166. / -
  167. / Out:
  168. / -
  169. /----------------------------------------------------------------------------*/
  170. EXTERN_C void DoTraceLeave(void)
  171. {
  172. if ( ( g_cDepth >= 0 ) && ( g_cDepth <= MAX_CALL_DEPTH ) )
  173. _trace_prolog(g_cDepth, FALSE);
  174. if ( !g_cDepth && g_CallStack[0].m_fTracedYet )
  175. OutputDebugString(TEXT("\n"));
  176. g_cDepth = max(g_cDepth-1, -1); // account for underflow
  177. }
  178. /*-----------------------------------------------------------------------------
  179. / DoTraceGetCurrentFn
  180. / -------------------
  181. / Peek the top of the call stack and return the current function name
  182. / pointer, or NULL if not defined.
  183. /
  184. / In:
  185. / Out:
  186. / LPCTSTR
  187. /----------------------------------------------------------------------------*/
  188. EXTERN_C LPCTSTR DoTraceGetCurrentFn(VOID)
  189. {
  190. return g_CallStack[g_cDepth].m_pFunctionName;
  191. }
  192. /*-----------------------------------------------------------------------------
  193. / DoTrace
  194. / -------
  195. / Perform printf formatting to the debugging stream. We indent the output
  196. / and stream the function name as required to give some indication of
  197. / call stack depth.
  198. /
  199. / In:
  200. / pFormat -> printf style formatting string
  201. / ... = arguments as required for the formatting
  202. /
  203. / Out:
  204. / -
  205. /----------------------------------------------------------------------------*/
  206. EXTERN_C void DoTrace(LPCTSTR pFormat, ...)
  207. {
  208. va_list va;
  209. if ( ( g_cDepth >= 0 ) && ( g_cDepth < MAX_CALL_DEPTH ) )
  210. {
  211. if ( _trace_prolog(g_cDepth, FALSE) )
  212. {
  213. va_start(va, pFormat);
  214. wvnsprintf(szTraceBuffer, ARRAYSIZE(szTraceBuffer), pFormat, va);
  215. va_end(va);
  216. _indent(g_cDepth+1, szTraceBuffer);
  217. }
  218. }
  219. }
  220. /*-----------------------------------------------------------------------------
  221. / DoTraceGuid
  222. / -----------
  223. / Given a GUID output it into the debug string, first we try and map it
  224. / to a name (ie. IShellFolder), if that didn't work then we convert it
  225. / to its human readable form.
  226. /
  227. / In:
  228. / pszPrefix -> prefix string
  229. / lpGuid -> guid to be streamed
  230. /
  231. / Out:
  232. / -
  233. /----------------------------------------------------------------------------*/
  234. #ifdef UNICODE
  235. #define MAP_GUID(x) &x, TEXT(""L#x)
  236. #else
  237. #define MAP_GUID(x) &x, TEXT(""#x)
  238. #endif
  239. #define MAP_GUID2(x,y) MAP_GUID(x), MAP_GUID(y)
  240. const struct
  241. {
  242. const GUID* m_pGUID;
  243. LPCTSTR m_pName;
  244. }
  245. _guid_map[] =
  246. {
  247. MAP_GUID(IID_IUnknown),
  248. MAP_GUID(IID_IClassFactory),
  249. MAP_GUID(IID_IDropTarget),
  250. MAP_GUID(IID_IDataObject),
  251. MAP_GUID(IID_IPersist),
  252. MAP_GUID(IID_IOleWindow),
  253. MAP_GUID2(IID_INewShortcutHookA, IID_INewShortcutHookW),
  254. MAP_GUID(IID_IShellBrowser),
  255. MAP_GUID(IID_IShellView),
  256. MAP_GUID(IID_IContextMenu),
  257. MAP_GUID(IID_IShellIcon),
  258. MAP_GUID(IID_IShellFolder),
  259. MAP_GUID(IID_IShellExtInit),
  260. MAP_GUID(IID_IShellPropSheetExt),
  261. MAP_GUID(IID_IPersistFolder),
  262. MAP_GUID2(IID_IExtractIconA, IID_IExtractIconW),
  263. MAP_GUID2(IID_IShellLinkA, IID_IShellLinkW),
  264. MAP_GUID2(IID_IShellCopyHookA, IID_IShellCopyHookW),
  265. MAP_GUID2(IID_IFileViewerA, IID_IFileViewerW),
  266. MAP_GUID(IID_ICommDlgBrowser),
  267. MAP_GUID(IID_IEnumIDList),
  268. MAP_GUID(IID_IFileViewerSite),
  269. MAP_GUID(IID_IContextMenu2),
  270. MAP_GUID2(IID_IShellExecuteHookA, IID_IShellExecuteHookW),
  271. MAP_GUID(IID_IPropSheetPage),
  272. MAP_GUID(IID_IShellView2),
  273. MAP_GUID(IID_IUniformResourceLocator),
  274. };
  275. EXTERN_C void DoTraceGUID(LPCTSTR pPrefix, REFGUID rGUID)
  276. {
  277. TCHAR szGUID[GUIDSTR_MAX];
  278. TCHAR szBuffer[1024];
  279. LPCTSTR pName = NULL;
  280. int i;
  281. if ( ( g_cDepth >= 0 ) && ( g_cDepth < MAX_CALL_DEPTH ) )
  282. {
  283. if ( _trace_prolog(g_cDepth, FALSE) )
  284. {
  285. for ( i = 0 ; i < ARRAYSIZE(_guid_map); i++ )
  286. {
  287. if ( IsEqualGUID(rGUID, *_guid_map[i].m_pGUID) )
  288. {
  289. pName = _guid_map[i].m_pName;
  290. break;
  291. }
  292. }
  293. if ( !pName )
  294. {
  295. GetStringFromGUID(rGUID, szGUID, ARRAYSIZE(szGUID));
  296. pName = szGUID;
  297. }
  298. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), TEXT("%s %s"), pPrefix, pName);
  299. _indent(g_cDepth+1, szBuffer);
  300. }
  301. }
  302. }
  303. /*-----------------------------------------------------------------------------
  304. / DoTraceAssert
  305. / -------------
  306. / Our assert handler, out faults it the trace mask as enabled assert
  307. / faulting.
  308. /
  309. / In:
  310. / iLine = line
  311. / pFilename -> filename of the file we asserted in
  312. /
  313. / Out:
  314. / -
  315. /----------------------------------------------------------------------------*/
  316. EXTERN_C void DoTraceAssert(int iLine, LPTSTR pFilename)
  317. {
  318. TCHAR szBuffer[1024];
  319. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), TEXT("Assert failed in %s, line %d"), pFilename, iLine);
  320. _trace_prolog(g_cDepth, TRUE); // nb: TRUE asserts always displabed
  321. _indent(g_cDepth+1, szBuffer);
  322. if ( g_dwTraceMask & TRACE_COMMON_ASSERT )
  323. DebugBreak();
  324. }
  325. #endif