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.

362 lines
8.7 KiB

  1. #include <objbase.h>
  2. #include "rbdebug.h"
  3. BOOL CRBDebug::_fInited = FALSE;
  4. DWORD CRBDebug::_dwFlags = 0;
  5. DWORD CRBDebug::_dwTraceFlags = 0;
  6. TCHAR* CRBDebug::_pszTraceFile = new TCHAR[MAX_PATH];
  7. TCHAR* CRBDebug::_pszModuleName = new TCHAR[MAX_PATH];
  8. HANDLE CRBDebug::_hfileTraceFile = INVALID_HANDLE_VALUE;
  9. TCHAR* CRBDebug::_pszTracePipe = new TCHAR[MAX_PATH];
  10. TCHAR CRBDebug::_szFileAndLine[] = {0};
  11. CRITICAL_SECTION CRBDebug::_cs = {0};
  12. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  13. HRESULT CRBDebug::_InitFile(HKEY hkeyRoot)
  14. {
  15. HRESULT hres = E_FAIL;
  16. HKEY hkeyFile;
  17. if (ERROR_SUCCESS == RegOpenKeyEx(hkeyRoot, TEXT("File"), 0,
  18. MAXIMUM_ALLOWED, &hkeyFile))
  19. {
  20. DWORD dwSize = MAX_PATH * sizeof(TCHAR);
  21. if (ERROR_SUCCESS == RegQueryValueEx(hkeyFile, TEXT("FileName"),
  22. 0, NULL, (PBYTE)_pszTraceFile, &dwSize))
  23. {
  24. _hfileTraceFile = CreateFile(_pszTraceFile,
  25. GENERIC_WRITE, FILE_SHARE_READ, NULL,
  26. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  27. if (INVALID_HANDLE_VALUE != _hfileTraceFile)
  28. {
  29. SetFilePointer(_hfileTraceFile, 0, 0,
  30. FILE_END);
  31. hres = S_OK;
  32. }
  33. }
  34. RegCloseKey(hkeyFile);
  35. }
  36. return hres;
  37. }
  38. HRESULT CRBDebug::_InitPipe(HKEY hkeyRoot)
  39. {
  40. HRESULT hres = S_OK;
  41. HKEY hkeyFile;
  42. TCHAR szMachineName[MAX_PATH];
  43. TCHAR szPipeName[MAX_PATH];
  44. if (ERROR_SUCCESS == RegOpenKeyEx(hkeyRoot, TEXT("Pipe"), 0,
  45. MAXIMUM_ALLOWED, &hkeyFile))
  46. {
  47. DWORD dwSize = sizeof(szMachineName);
  48. if (ERROR_SUCCESS != RegQueryValueEx(hkeyFile, TEXT("MachineName"),
  49. 0, NULL, (PBYTE)szMachineName, &dwSize))
  50. {
  51. lstrcpy(szMachineName, TEXT("."));
  52. }
  53. dwSize = sizeof(szPipeName);
  54. if (ERROR_SUCCESS != RegQueryValueEx(hkeyFile, TEXT("PipeName"),
  55. 0, NULL, (PBYTE)szPipeName, &dwSize))
  56. {
  57. lstrcpy(szPipeName, _pszModuleName);
  58. }
  59. RegCloseKey(hkeyFile);
  60. }
  61. else
  62. {
  63. // Defaults
  64. lstrcpy(szMachineName, TEXT("."));
  65. lstrcpy(szPipeName, _pszModuleName);
  66. }
  67. wsprintf(_pszTracePipe, TEXT("\\\\%s\\pipe\\%s"), szMachineName, szPipeName);
  68. return hres;
  69. }
  70. // static
  71. HRESULT CRBDebug::_Init()
  72. {
  73. HRESULT hres = S_FALSE;
  74. if (!_fInited)
  75. {
  76. // Read the flags
  77. WCHAR szKey[MAX_PATH];
  78. WCHAR szModule[MAX_PATH];
  79. BOOL fKeyExist = FALSE;
  80. hres = E_FAIL;
  81. InitializeCriticalSection(&_cs);
  82. lstrcpy(szKey, L"Software\\Microsoft\\Debug\\");
  83. if (GetModuleFileName(GetModuleHandle(NULL), szModule, MAX_PATH))
  84. {
  85. HKEY hkey;
  86. LONG lSuccess;
  87. int c = lstrlen(szModule);
  88. while (c && (L'\\' != szModule[c]))
  89. {
  90. --c;
  91. }
  92. lstrcpy(_pszModuleName, szModule + c + 1);
  93. lstrcat(szKey, _pszModuleName);
  94. lSuccess = RegOpenKeyEx(HKEY_CURRENT_USER, szKey, 0,
  95. MAXIMUM_ALLOWED, &hkey);
  96. if (ERROR_SUCCESS != lSuccess)
  97. {
  98. lSuccess = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0,
  99. MAXIMUM_ALLOWED, &hkey);
  100. }
  101. if (ERROR_SUCCESS == lSuccess)
  102. {
  103. DWORD dwSize = sizeof(DWORD);
  104. fKeyExist = TRUE;
  105. if (ERROR_SUCCESS == RegQueryValueEx(hkey, L"RBD_FLAGS", 0,
  106. NULL, (PBYTE)&_dwFlags, &dwSize))
  107. {
  108. if (_dwFlags & RBD_TRACE_OUTPUTDEBUG)
  109. {
  110. hres = S_OK;
  111. }
  112. if ((_dwFlags & RBD_TRACE_TOFILE) ||
  113. (_dwFlags & RBD_TRACE_TOFILEANSI))
  114. {
  115. hres = _InitFile(hkey);
  116. if (FAILED(hres))
  117. {
  118. _dwFlags &= ~RBD_TRACE_TOFILE;
  119. }
  120. }
  121. if (_dwFlags & RBD_TRACE_TOPIPE)
  122. {
  123. hres = _InitPipe(hkey);
  124. if (FAILED(hres))
  125. {
  126. _dwFlags &= ~RBD_TRACE_TOPIPE;
  127. }
  128. }
  129. }
  130. else
  131. {
  132. _dwFlags = RBD_TRACE_OUTPUTDEBUG | RBD_ASSERT_STOP;
  133. hres = S_FALSE;
  134. }
  135. if (ERROR_SUCCESS != RegQueryValueEx(hkey, L"TRACE_FLAGS", 0,
  136. NULL, (PBYTE)&_dwTraceFlags, &dwSize))
  137. {
  138. // Default...
  139. _dwTraceFlags = 0;
  140. }
  141. RegCloseKey(hkey);
  142. }
  143. }
  144. if (!fKeyExist)
  145. {
  146. // If we can't find a key for this app then we revert to default
  147. // behavior
  148. _dwFlags = RBD_TRACE_OUTPUTDEBUG | RBD_ASSERT_STOP;
  149. hres = S_FALSE;
  150. }
  151. if (SUCCEEDED(hres))
  152. {
  153. _fInited = TRUE;
  154. }
  155. }
  156. return hres;
  157. }
  158. // static
  159. void __cdecl CRBDebug::TraceMsg(DWORD dwFlags, LPTSTR pszMsg, ...)
  160. {
  161. HRESULT hres = S_OK;
  162. if (!_fInited)
  163. {
  164. hres = _Init();
  165. }
  166. if (SUCCEEDED(hres))
  167. {
  168. if ((_dwTraceFlags & dwFlags) &&
  169. (TF_NOFILEANDLINE != (_dwTraceFlags & dwFlags)))
  170. {
  171. if (!((_dwTraceFlags & TF_NOFILEANDLINE) ||
  172. (dwFlags & TF_NOFILEANDLINE)))
  173. {
  174. // File and line
  175. _Trace(_szFileAndLine);
  176. }
  177. {
  178. TCHAR szBuf[4096];
  179. va_list vArgs;
  180. va_start(vArgs, pszMsg);
  181. wvsprintf(szBuf, pszMsg, vArgs);
  182. va_end(vArgs);
  183. lstrcat(szBuf, TEXT("\r\n"));
  184. _Trace(szBuf);
  185. }
  186. }
  187. }
  188. LeaveCriticalSection(&_cs);
  189. }
  190. // static
  191. void CRBDebug::SetTraceFileAndLine(LPCSTR pszFile, const int iLine)
  192. {
  193. HRESULT hres = S_OK;
  194. if (!_fInited)
  195. {
  196. hres = _Init();
  197. }
  198. EnterCriticalSection(&_cs);
  199. if (SUCCEEDED(hres))
  200. {
  201. LPTSTR pszFinal;
  202. WCHAR szwBuf[MAX_PATH + 12 + 17];
  203. CHAR szBuf[MAX_PATH + 12 + 17];
  204. int c = lstrlenA(pszFile);
  205. LPCSTR pszFileName;
  206. DWORD dwTimeOffset = 0;
  207. while (c && ('\\' != *(pszFile + c)))
  208. {
  209. --c;
  210. }
  211. pszFileName = pszFile + c + 1;
  212. if (_dwTraceFlags & TF_TIME)
  213. {
  214. DWORD dwTick = GetTickCount();
  215. DWORD dwMilliSec = dwTick % 1000;
  216. dwTick -= dwMilliSec;
  217. dwTick /= 1000;
  218. DWORD dwSec = dwTick % 60;
  219. dwTick -= dwSec;
  220. dwTick /= 60;
  221. DWORD dwMin = dwTick % 60;
  222. dwTick -= dwMin;
  223. dwTick /= 60;
  224. DWORD dwHour = dwTick;
  225. wsprintfA(szBuf, "{%04d:%02d:%02d.%03d}", dwHour, dwMin, dwSec,
  226. dwMilliSec);
  227. dwTimeOffset = 16;
  228. }
  229. if (_dwTraceFlags & TF_THREADID)
  230. {
  231. wsprintfA(szBuf + dwTimeOffset, "~0x%08X~[%s, %d]",
  232. GetCurrentThreadId(), pszFileName, iLine);
  233. }
  234. else
  235. {
  236. wsprintfA(szBuf + dwTimeOffset, "[%s, %d] ", pszFileName, iLine);
  237. }
  238. #ifdef UNICODE
  239. pszFinal = szwBuf;
  240. MultiByteToWideChar(CP_ACP, 0, szBuf, lstrlenA(szBuf) + 1, szwBuf,
  241. sizeof(szwBuf) / sizeof(WCHAR));
  242. #else
  243. pszFinal = szBuf;
  244. #endif
  245. lstrcpyn(_szFileAndLine, pszFinal, ARRAYSIZE(_szFileAndLine));
  246. }
  247. }
  248. void CRBDebug::_Trace(LPTSTR pszMsg)
  249. {
  250. if (RBD_TRACE_OUTPUTDEBUG & _dwFlags)
  251. {
  252. OutputDebugString(pszMsg);
  253. }
  254. #ifdef UNICODE
  255. if (RBD_TRACE_TOFILE & _dwFlags)
  256. #else
  257. if ((RBD_TRACE_TOFILE & _dwFlags) || (RBD_TRACE_TOFILEANSI & _dwFlags))
  258. #endif
  259. {
  260. DWORD dwWritten = 0;
  261. WriteFile(_hfileTraceFile, pszMsg, lstrlen(pszMsg) * sizeof(TCHAR),
  262. &dwWritten, NULL);
  263. }
  264. else
  265. {
  266. #ifdef UNICODE
  267. if (RBD_TRACE_TOFILEANSI & _dwFlags)
  268. {
  269. CHAR szBuf[4096];
  270. DWORD dwWritten = 0;
  271. WideCharToMultiByte(CP_ACP, 0, pszMsg,
  272. (lstrlen(pszMsg) + 1) * sizeof(WCHAR), szBuf, sizeof(szBuf), NULL,
  273. NULL);
  274. WriteFile(_hfileTraceFile, szBuf, lstrlenA(szBuf), &dwWritten,
  275. NULL);
  276. }
  277. #endif
  278. }
  279. if (RBD_TRACE_TOPIPE & _dwFlags)
  280. {
  281. CallNamedPipe(_pszTracePipe, pszMsg, lstrlen(pszMsg) * sizeof(TCHAR),
  282. NULL, 0, NULL, NMPWAIT_NOWAIT);
  283. }
  284. }
  285. // static
  286. HRESULT CRBDebug::Init()
  287. {
  288. return CRBDebug::_Init();
  289. }