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.

434 lines
10 KiB

  1. //*************************************************************
  2. //
  3. // Microsoft Confidential. Copyright (c) Microsoft Corporation 1999. All rights reserved
  4. //
  5. // File: RsopDbg.cpp
  6. //
  7. // Description:
  8. //
  9. // History: 8-20-99 leonardm Created
  10. //
  11. //*************************************************************
  12. #include <windows.h>
  13. #include <wchar.h>
  14. #include "RsopUtil.h"
  15. #include "smartptr.h"
  16. #include "RsopDbg.h"
  17. //*************************************************************
  18. //
  19. // Function:
  20. //
  21. // Description:
  22. //
  23. // Parameters:
  24. //
  25. // Return:
  26. //
  27. //*************************************************************
  28. CDebug::CDebug() :
  29. _bInitialized(false)
  30. {
  31. #if DBG
  32. _dwDebugLevel = DEBUG_LEVEL_WARNING | DEBUG_DESTINATION_LOGFILE | DEBUG_DESTINATION_DEBUGGER;
  33. #else
  34. _dwDebugLevel = DEBUG_LEVEL_WARNING | DEBUG_DESTINATION_LOGFILE;
  35. #endif
  36. }
  37. //*************************************************************
  38. //
  39. // Function:
  40. //
  41. // Description:
  42. //
  43. // Parameters:
  44. //
  45. // Return:
  46. //
  47. //*************************************************************
  48. CDebug::CDebug( const WCHAR* sRegPath,
  49. const WCHAR* sKeyName,
  50. const WCHAR* sLogFilename,
  51. const WCHAR* sBackupLogFilename,
  52. bool bResetLogFile)
  53. : _sRegPath(sRegPath),
  54. _sKeyName(sKeyName),
  55. _sLogFilename(sLogFilename),
  56. _sBackupLogFilename(sBackupLogFilename)
  57. {
  58. #if DBG
  59. _dwDebugLevel = DEBUG_LEVEL_WARNING | DEBUG_DESTINATION_LOGFILE | DEBUG_DESTINATION_DEBUGGER;
  60. #else
  61. _dwDebugLevel = DEBUG_LEVEL_WARNING | DEBUG_DESTINATION_LOGFILE;
  62. #endif
  63. Initialize(bResetLogFile);
  64. }
  65. //*************************************************************
  66. //
  67. // Function:
  68. //
  69. // Description:
  70. //
  71. // Parameters:
  72. //
  73. // Return:
  74. //
  75. //*************************************************************
  76. bool CDebug::Initialize( const WCHAR* sRegPath,
  77. const WCHAR* sKeyName,
  78. const WCHAR* sLogFilename,
  79. const WCHAR* sBackupLogFilename,
  80. bool bResetLogFile)
  81. {
  82. if (!xCritSec)
  83. return FALSE;
  84. XEnterCritSec xEnterCS(xCritSec);
  85. _sRegPath = sRegPath;
  86. _sKeyName = sKeyName;
  87. _sLogFilename = sLogFilename;
  88. _sBackupLogFilename = sBackupLogFilename;
  89. return Initialize(bResetLogFile);
  90. }
  91. //*************************************************************
  92. //
  93. // Function:
  94. //
  95. // Description:
  96. //
  97. // Parameters:
  98. //
  99. // Return:
  100. //
  101. //*************************************************************
  102. bool CDebug::Initialize(bool bResetLogFile)
  103. {
  104. //
  105. // reinitialize the default value
  106. //
  107. #if DBG
  108. _dwDebugLevel = DEBUG_LEVEL_WARNING | DEBUG_DESTINATION_LOGFILE | DEBUG_DESTINATION_DEBUGGER;
  109. #else
  110. _dwDebugLevel = DEBUG_LEVEL_WARNING | DEBUG_DESTINATION_LOGFILE;
  111. #endif
  112. _bInitialized = false;
  113. //
  114. // Check the registry for the appropriate debug level.
  115. //
  116. HKEY hKey;
  117. LONG lResult = RegOpenKey (HKEY_LOCAL_MACHINE, _sRegPath, &hKey);
  118. if (lResult == ERROR_SUCCESS)
  119. {
  120. DWORD dwSize = sizeof(_dwDebugLevel);
  121. DWORD dwType;
  122. RegQueryValueEx(hKey,_sKeyName,NULL,&dwType,(LPBYTE)&_dwDebugLevel,&dwSize);
  123. RegCloseKey(hKey);
  124. }
  125. //
  126. // If a new log file has been requested, copy current log file to backup
  127. // file by overwriting then start a new log file.
  128. //
  129. if (bResetLogFile)
  130. {
  131. WCHAR szExpLogFileName[MAX_PATH+1];
  132. WCHAR szExpBackupLogFileName[MAX_PATH+1];
  133. CWString sTmp;
  134. sTmp = L"%systemroot%\\debug\\UserMode\\" + _sLogFilename;
  135. if(!sTmp.ValidString())
  136. {
  137. return false;
  138. }
  139. DWORD dwRet = ExpandEnvironmentStrings( sTmp, szExpLogFileName, MAX_PATH+1);
  140. if ( dwRet == 0 || dwRet > MAX_PATH)
  141. {
  142. return false;
  143. }
  144. sTmp = L"%systemroot%\\debug\\UserMode\\" + _sBackupLogFilename;
  145. if(!sTmp.ValidString())
  146. {
  147. return false;
  148. }
  149. dwRet = ExpandEnvironmentStrings ( sTmp, szExpBackupLogFileName, MAX_PATH+1);
  150. if ( dwRet == 0 || dwRet > MAX_PATH)
  151. {
  152. return false;
  153. }
  154. dwRet = MoveFileEx( szExpLogFileName, szExpBackupLogFileName,
  155. MOVEFILE_REPLACE_EXISTING);
  156. XHandle hFile = CreateFile( szExpLogFileName,
  157. GENERIC_WRITE,
  158. FILE_SHARE_READ,
  159. NULL,
  160. CREATE_ALWAYS,
  161. 0,
  162. NULL);
  163. if(hFile == INVALID_HANDLE_VALUE)
  164. {
  165. return false;
  166. }
  167. }
  168. _bInitialized = true;
  169. return _bInitialized;
  170. }
  171. //*************************************************************
  172. //
  173. // Function:
  174. //
  175. // Description:
  176. //
  177. // Parameters:
  178. //
  179. // Return:
  180. //
  181. //*************************************************************
  182. void CDebug::Msg(DWORD dwMask, LPCTSTR pszMsg, ...)
  183. {
  184. //
  185. // Save the last error code (so the debug output doesn't change it).
  186. //
  187. DWORD dwErrCode = GetLastError();
  188. if(!_bInitialized)
  189. {
  190. return;
  191. }
  192. //
  193. // Display the error message if appropriate
  194. //
  195. bool bDebugOutput = (_dwDebugLevel & 0xFFFF0000 & DEBUG_DESTINATION_DEBUGGER) != 0;
  196. bool bLogfileOutput = (_dwDebugLevel & 0xFFFF0000 & DEBUG_DESTINATION_LOGFILE) != 0;
  197. if(!bDebugOutput && !bLogfileOutput)
  198. {
  199. //
  200. // No output
  201. //
  202. CleanupAndCheckForDbgBreak(dwErrCode, dwMask);
  203. return;
  204. }
  205. //
  206. // Determine the correct amount of debug output
  207. //
  208. bool bOutput;
  209. switch(_dwDebugLevel & 0x0000FFFF)
  210. {
  211. //
  212. // No output
  213. //
  214. case DEBUG_LEVEL_NONE:
  215. bOutput = false;
  216. break;
  217. //
  218. // Asserts and warnings
  219. //
  220. case DEBUG_LEVEL_WARNING:
  221. bOutput = dwMask & (DEBUG_MESSAGE_ASSERT | DEBUG_MESSAGE_WARNING) ? true : false;
  222. break;
  223. //
  224. // Asserts, warnings and verbose
  225. //
  226. case DEBUG_LEVEL_VERBOSE:
  227. bOutput = dwMask & (DEBUG_MESSAGE_ASSERT | DEBUG_MESSAGE_WARNING | DEBUG_MESSAGE_VERBOSE) ? true : false;
  228. break;
  229. //
  230. // No output
  231. //
  232. default:
  233. bOutput = false;
  234. break;
  235. }
  236. if(!bOutput)
  237. {
  238. CleanupAndCheckForDbgBreak(dwErrCode, dwMask);
  239. return;
  240. }
  241. WCHAR* pszMessageLevel;
  242. if((dwMask & 0x0000FFFF) == DEBUG_MESSAGE_ASSERT)
  243. {
  244. pszMessageLevel = L" [ASSERT] ";
  245. }
  246. else if((dwMask & 0x0000FFFF) == DEBUG_MESSAGE_WARNING)
  247. {
  248. pszMessageLevel = L" [WARNING] ";
  249. }
  250. else if((dwMask & 0x0000FFFF) == DEBUG_MESSAGE_VERBOSE)
  251. {
  252. pszMessageLevel = L" [VERBOSE] ";
  253. }
  254. else
  255. {
  256. pszMessageLevel = L" [<Unknown message type>] ";
  257. }
  258. SYSTEMTIME systime;
  259. GetLocalTime (&systime);
  260. WCHAR szDebugTitle[128];
  261. swprintf ( szDebugTitle,
  262. L"[%x.%x] %2d/%02d/%4d %02d:%02d:%02d:%03d ",
  263. GetCurrentProcessId(),
  264. GetCurrentThreadId(),
  265. systime.wMonth, systime.wDay, systime.wYear,
  266. systime.wHour, systime.wMinute, systime.wSecond,systime.wMilliseconds);
  267. const int nDebugBufferWChars = 2048;
  268. XPtrLF<WCHAR>xpDebugBuffer = (LPTSTR) LocalAlloc (LPTR, nDebugBufferWChars * sizeof(WCHAR));
  269. if(!xpDebugBuffer)
  270. {
  271. CleanupAndCheckForDbgBreak(dwErrCode, dwMask);
  272. return;
  273. }
  274. va_list marker;
  275. va_start(marker, pszMsg);
  276. int nChars = wvsprintf(xpDebugBuffer, pszMsg, marker);
  277. if(bDebugOutput)
  278. {
  279. OutputDebugString(szDebugTitle);
  280. OutputDebugString(pszMessageLevel);
  281. OutputDebugString(xpDebugBuffer);
  282. OutputDebugString(L"\r\n");
  283. }
  284. va_end(marker);
  285. if(bLogfileOutput)
  286. {
  287. WCHAR szExpLogFileName[MAX_PATH+1];
  288. CWString sTmp = L"%systemroot%\\debug\\usermode\\" + _sLogFilename;
  289. if(!sTmp.ValidString())
  290. {
  291. return;
  292. }
  293. DWORD dwRet = ExpandEnvironmentStrings ( sTmp, szExpLogFileName, MAX_PATH+1);
  294. if(dwRet == 0 || dwRet > MAX_PATH)
  295. {
  296. CleanupAndCheckForDbgBreak(dwErrCode, dwMask);
  297. return;
  298. }
  299. HANDLE hFile = CreateFile( szExpLogFileName,
  300. GENERIC_WRITE,
  301. FILE_SHARE_READ,
  302. NULL,
  303. OPEN_ALWAYS,
  304. FILE_ATTRIBUTE_NORMAL,
  305. NULL);
  306. XHandle autoCloseHandle(hFile);
  307. if (hFile == INVALID_HANDLE_VALUE)
  308. {
  309. DWORD dwLastError = GetLastError();
  310. CleanupAndCheckForDbgBreak(dwErrCode, dwMask);
  311. return;
  312. }
  313. if(SetFilePointer(hFile, 0, NULL, FILE_END) == INVALID_FILE_SIZE)
  314. {
  315. CleanupAndCheckForDbgBreak(dwErrCode, dwMask);
  316. return;
  317. }
  318. DWORD dwBytesWritten;
  319. WriteFile(hFile, (LPCVOID) szDebugTitle,lstrlen (szDebugTitle) * sizeof(WCHAR),&dwBytesWritten,NULL);
  320. WriteFile(hFile, (LPCVOID) pszMessageLevel,lstrlen (pszMessageLevel) * sizeof(WCHAR),&dwBytesWritten,NULL);
  321. WriteFile(hFile, (LPCVOID) xpDebugBuffer,lstrlen (xpDebugBuffer) * sizeof(WCHAR),&dwBytesWritten,NULL);
  322. WriteFile(hFile, (LPCVOID) L"\r\n",lstrlen (L"\r\n") * sizeof(WCHAR),&dwBytesWritten,NULL);
  323. }
  324. CleanupAndCheckForDbgBreak(dwErrCode, dwMask);
  325. return;
  326. }
  327. //*************************************************************
  328. //
  329. // Function:
  330. //
  331. // Description:
  332. //
  333. // Parameters:
  334. //
  335. // Return:
  336. //
  337. //*************************************************************
  338. void CDebug::CleanupAndCheckForDbgBreak(DWORD dwErrorCode, DWORD dwMask)
  339. {
  340. SetLastError(dwErrorCode);
  341. // Break to the debugger if appropriate
  342. #ifdef DEBUG
  343. if((dwMask & 0x0000FFFF) == DEBUG_MESSAGE_ASSERT)
  344. {
  345. DebugBreak();
  346. }
  347. #endif
  348. }