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.

447 lines
11 KiB

  1. //*************************************************************
  2. //
  3. // Debugging functions
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1995
  7. // All rights reserved
  8. //
  9. //*************************************************************
  10. #include "common.hxx"
  11. HINSTANCE ghDllInstance = 0;
  12. //
  13. // Global Variable containing the debugging level. The debug level can be
  14. // modified by both the debug init routine and the event logging init
  15. // routine. Debugging can be enabled even on retail systems through
  16. // registry settings.
  17. //
  18. DWORD gDebugLevel = DL_NONE;
  19. DWORD gDebugBreak = 0;
  20. LOADSTRINGW * pfnLoadStringW = 0;
  21. //
  22. // Debug strings
  23. //
  24. const WCHAR cwszAppMgmt[] = L"APPMGMT (%x.%x) %02d:%02d:%02d:%03d ";
  25. const WCHAR cwszLogTime[] = L"%02d-%02d %02d:%02d:%02d:%03d ";
  26. const WCHAR cwszLogfile[] = L"%SystemRoot%\\Debug\\UserMode\\appmgmt.log";
  27. const WCHAR cwszOldLogfile[] = L"%SystemRoot%\\Debug\\UserMode\\appmgmt.bak";
  28. const WCHAR cwszCRLF[] = L"\r\n";
  29. const char cszCRLF[] = "\r\n";
  30. //*************************************************************
  31. //
  32. // InitDebugSupport()
  33. //
  34. // Sets the debugging level.
  35. // Also checks the registry for a debugging level.
  36. //
  37. //*************************************************************
  38. void InitDebugSupport( DWORD DebugMode )
  39. {
  40. HKEY hKey;
  41. DWORD Size;
  42. DWORD Type;
  43. BOOL bVerbose;
  44. DWORD Status;
  45. BOOL bStatus;
  46. #if DBG
  47. gDebugLevel = DL_NORMAL;
  48. #else
  49. gDebugLevel = DL_NONE;
  50. #endif
  51. gDebugBreak = 0;
  52. Status = RegOpenKeyEx(
  53. HKEY_LOCAL_MACHINE,
  54. DIAGNOSTICS_KEY,
  55. 0,
  56. KEY_READ,
  57. &hKey );
  58. bVerbose = FALSE;
  59. if ( ERROR_SUCCESS == Status )
  60. {
  61. Size = sizeof(bVerbose);
  62. Status = RegQueryValueEx(
  63. hKey,
  64. DIAGNOSTICS_POLICY_VALUE,
  65. NULL,
  66. &Type,
  67. (LPBYTE) &bVerbose,
  68. &Size );
  69. if ( (ERROR_SUCCESS == Status) && (Type != REG_DWORD) )
  70. bVerbose = FALSE;
  71. Size = sizeof(gDebugLevel);
  72. Status = RegQueryValueEx(
  73. hKey,
  74. DEBUG_KEY_NAME,
  75. NULL,
  76. NULL,
  77. (LPBYTE) &gDebugLevel,
  78. &Size );
  79. if (ERROR_SUCCESS != Status)
  80. {
  81. RegCloseKey(hKey);
  82. return;
  83. }
  84. Size = sizeof(gDebugBreak);
  85. Status = RegQueryValueEx(
  86. hKey,
  87. DEBUGBREAK_KEY_NAME,
  88. NULL,
  89. NULL,
  90. (LPBYTE) &gDebugBreak,
  91. &Size );
  92. RegCloseKey(hKey);
  93. if (ERROR_SUCCESS != Status)
  94. {
  95. return;
  96. }
  97. }
  98. if ( bVerbose )
  99. gDebugLevel |= DL_VERBOSE | DL_EVENTLOG;
  100. if ( gDebugLevel & DL_LOGFILE )
  101. {
  102. WCHAR wszLogFile[MAX_PATH];
  103. WCHAR wszOldLogFile[MAX_PATH];
  104. WIN32_FILE_ATTRIBUTE_DATA FileData;
  105. BOOL bStatusLog;
  106. bStatusLog = GetDebugLogFileName( wszLogFile, sizeof( wszLogFile ) / sizeof( WCHAR ) );
  107. if ( ! bStatusLog )
  108. {
  109. return;
  110. }
  111. if ( DebugMode != DEBUGMODE_POLICY )
  112. return;
  113. bStatusLog = GetFileAttributesEx( wszLogFile, GetFileExInfoStandard, &FileData );
  114. if ( ! bStatusLog )
  115. return;
  116. //
  117. // If the existing log file is more than 50K then we will rename it to a backup
  118. // copy to prevent huge bloating, otherwise we continue to use it.
  119. //
  120. if ( FileData.nFileSizeLow < (50 * 1024) )
  121. return;
  122. Status = ExpandEnvironmentStrings( cwszOldLogfile, wszOldLogFile, sizeof(wszOldLogFile) / sizeof(WCHAR) );
  123. if ( (0 == Status) || (Status > ( sizeof(wszOldLogFile) / sizeof(WCHAR) )) )
  124. return;
  125. DeleteFile( wszOldLogFile );
  126. MoveFile( wszLogFile, wszOldLogFile );
  127. }
  128. }
  129. BOOL DebugLevelOn( DWORD mask )
  130. {
  131. BOOL bOutput = FALSE;
  132. if ( gDebugLevel & DL_VERBOSE )
  133. bOutput = TRUE;
  134. else if ( gDebugLevel & DL_NORMAL )
  135. bOutput = ! (mask & DM_VERBOSE);
  136. #if DBG
  137. else // DL_NONE
  138. bOutput = (mask & DM_ASSERT);
  139. #endif
  140. return bOutput;
  141. }
  142. //*************************************************************
  143. //
  144. // _DebugMsg()
  145. //
  146. // Displays debug messages based on the debug level
  147. // and type of debug message.
  148. //
  149. // Parameters :
  150. // mask - debug message type
  151. // MsgID - debug message id from resource file
  152. // ... - variable number of parameters
  153. //
  154. //*************************************************************
  155. void _DebugMsg(DWORD mask, DWORD MsgID, ...)
  156. {
  157. if ( ! DebugLevelOn( mask ) )
  158. return;
  159. BOOL bEventLogOK;
  160. WCHAR wszDebugTitle[64];
  161. WCHAR wszDebugBuffer[2048]; // Hopefully this will be big enough!
  162. WCHAR wszMsg[MAX_PATH];
  163. va_list VAList;
  164. SYSTEMTIME systime;
  165. bEventLogOK = ! (mask & DM_NO_EVENTLOG);
  166. if ( ! LoadLoadString() )
  167. return;
  168. va_start(VAList, MsgID);
  169. if ( ! ghDllInstance )
  170. ghDllInstance = LoadLibrary( L"appmgmts.dll" );
  171. //
  172. // Event log message ids are in the 100s to 400s, verbose strings are in the
  173. // 1000s to 3000s. For event log messages we must call FormatMessage. For
  174. // other verbose debug output, we use LoadString to get the string resource.
  175. //
  176. if ( MsgID >= 1000 )
  177. {
  178. if ( ! (*pfnLoadStringW)( ghDllInstance, MsgID, wszMsg, MAX_PATH) )
  179. return;
  180. (void) StringCchVPrintf(wszDebugBuffer, sizeof(wszDebugBuffer)/sizeof(wszDebugBuffer[0]), wszMsg, VAList);
  181. }
  182. else
  183. {
  184. DWORD CharsWritten;
  185. CharsWritten = FormatMessage(
  186. FORMAT_MESSAGE_FROM_HMODULE,
  187. ghDllInstance,
  188. MsgID,
  189. 0,
  190. wszDebugBuffer,
  191. sizeof(wszDebugBuffer) / sizeof(WCHAR),
  192. &VAList );
  193. if ( 0 == CharsWritten )
  194. return;
  195. }
  196. va_end(VAList);
  197. GetLocalTime( &systime );
  198. (void) StringCchPrintf( wszDebugTitle,
  199. sizeof(wszDebugTitle)/sizeof(wszDebugTitle[0]),
  200. cwszAppMgmt,
  201. GetCurrentProcessId(),
  202. GetCurrentThreadId(),
  203. systime.wHour,
  204. systime.wMinute,
  205. systime.wSecond,
  206. systime.wMilliseconds);
  207. if ( ! (gDebugLevel & DL_NODBGOUT) )
  208. {
  209. OutputDebugString( wszDebugTitle );
  210. OutputDebugString( wszDebugBuffer );
  211. OutputDebugString( cwszCRLF );
  212. }
  213. if ( gDebugLevel & DL_LOGFILE )
  214. {
  215. WCHAR* wszLogFile;
  216. HANDLE hFile;
  217. wszLogFile = new WCHAR[ MAX_PATH ];
  218. if ( wszLogFile && GetDebugLogFileName( wszLogFile, MAX_PATH ) )
  219. {
  220. hFile = OpenUnicodeLogFile(wszLogFile);
  221. if ( hFile != INVALID_HANDLE_VALUE )
  222. {
  223. if ( SetFilePointer (hFile, 0, NULL, FILE_END) != 0xFFFFFFFF )
  224. {
  225. DWORD Size;
  226. WriteFile(
  227. hFile,
  228. (LPCVOID) wszDebugBuffer,
  229. lstrlen(wszDebugBuffer) * sizeof(WCHAR),
  230. &Size,
  231. NULL );
  232. WriteFile(
  233. hFile,
  234. (LPCVOID) cwszCRLF,
  235. lstrlen(cwszCRLF) * sizeof(WCHAR),
  236. &Size,
  237. NULL );
  238. }
  239. }
  240. CloseHandle (hFile);
  241. delete [] wszLogFile;
  242. }
  243. }
  244. if ( bEventLogOK && (gDebugLevel & DL_EVENTLOG) )
  245. ((CEventsBase *)gpEvents)->Report( EVENT_APPMGMT_VERBOSE, FALSE, 1, wszDebugBuffer );
  246. #if DBG
  247. if ( mask & DM_ASSERT )
  248. DebugBreak();
  249. #endif
  250. }
  251. void LogTime()
  252. {
  253. if ( ! (gDebugLevel & DL_LOGFILE) )
  254. return;
  255. WCHAR wszDebugBuffer[64];
  256. SYSTEMTIME systime;
  257. HANDLE hFile;
  258. WCHAR wszLogFile[MAX_PATH];
  259. BOOL bStatus;
  260. bStatus = GetDebugLogFileName( wszLogFile, sizeof( wszLogFile ) / sizeof( WCHAR ) );
  261. if ( ! bStatus )
  262. {
  263. return;
  264. }
  265. GetLocalTime( &systime );
  266. (void) StringCchPrintf( wszDebugBuffer,
  267. sizeof(wszDebugBuffer)/sizeof(wszDebugBuffer[0]),
  268. cwszLogTime,
  269. systime.wMonth,
  270. systime.wDay,
  271. systime.wHour,
  272. systime.wMinute,
  273. systime.wSecond,
  274. systime.wMilliseconds);
  275. hFile = OpenUnicodeLogFile(wszLogFile);
  276. if ( INVALID_HANDLE_VALUE == hFile )
  277. return;
  278. if ( SetFilePointer (hFile, 0, NULL, FILE_END) != 0xFFFFFFFF )
  279. {
  280. DWORD Size;
  281. WriteFile(
  282. hFile,
  283. (LPCVOID) wszDebugBuffer,
  284. lstrlen(wszDebugBuffer) * sizeof(WCHAR),
  285. &Size,
  286. NULL );
  287. WriteFile(
  288. hFile,
  289. (LPCVOID) cwszCRLF,
  290. lstrlen(cwszCRLF) * sizeof(WCHAR),
  291. &Size,
  292. NULL );
  293. }
  294. CloseHandle (hFile);
  295. }
  296. HANDLE
  297. OpenUnicodeLogFile (LPCTSTR lpszFilePath)
  298. {
  299. HANDLE hFile;
  300. DWORD Status;
  301. DWORD dwWritten;
  302. Status = ERROR_SUCCESS;
  303. hFile = CreateFile(
  304. lpszFilePath,
  305. FILE_WRITE_DATA | FILE_APPEND_DATA,
  306. FILE_SHARE_READ,
  307. NULL,
  308. OPEN_EXISTING,
  309. FILE_ATTRIBUTE_NORMAL,
  310. NULL);
  311. if ( INVALID_HANDLE_VALUE == hFile )
  312. {
  313. Status = GetLastError();
  314. }
  315. if ( ERROR_FILE_NOT_FOUND == Status )
  316. {
  317. //
  318. // The file doesn't exist, so we'll try to create it
  319. // with the byte order marker
  320. //
  321. hFile = CreateFile(
  322. lpszFilePath,
  323. FILE_WRITE_DATA | FILE_APPEND_DATA,
  324. FILE_SHARE_READ,
  325. NULL,
  326. OPEN_ALWAYS,
  327. FILE_ATTRIBUTE_NORMAL,
  328. NULL);
  329. if ( INVALID_HANDLE_VALUE != hFile )
  330. {
  331. BOOL bWritten;
  332. //
  333. // Add the unicode byte order marker to the beginning of the file
  334. // so that APIs know for sure that it is a unicode file.
  335. //
  336. bWritten = WriteFile(
  337. hFile,
  338. L"\xfeff\r\n",
  339. 4 * sizeof(WCHAR),
  340. &dwWritten,
  341. NULL);
  342. if ( ! bWritten )
  343. {
  344. CloseHandle( hFile );
  345. }
  346. }
  347. }
  348. return hFile;
  349. }
  350. BOOL
  351. GetDebugLogFileName( WCHAR* wszLogFile, LONG cchLogFile )
  352. {
  353. LONG Status;
  354. Status = ExpandEnvironmentStrings( cwszLogfile, wszLogFile, MAX_PATH );
  355. if ( (0 == Status) || (Status > cchLogFile) )
  356. {
  357. return FALSE;
  358. }
  359. return TRUE;
  360. }