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.

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