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.

491 lines
12 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. log.cpp
  5. Abstract:
  6. This module contains routines to log errors, warnings and info in the asr
  7. log file at %systemroot%\repair\asr.log
  8. Author:
  9. Guhan Suriyanarayanan (guhans) 10-Jul-2000
  10. Environment:
  11. User-mode only.
  12. Revision History:
  13. 10-Jul-2000 guhans
  14. Initial creation
  15. --*/
  16. #include <stdio.h>
  17. #include <windows.h>
  18. #include <assert.h>
  19. #include "log.h"
  20. #define ASRSFGEN_ASR_ERROR_FILE_PATH L"%SystemRoot%\\repair\\asr.err"
  21. #define ASRSFGEN_ASR_LOG_FILE_PATH L"%SystemRoot%\\repair\\asr.log"
  22. //
  23. // ----
  24. // Data global to this module
  25. // ----
  26. //
  27. BOOL Gbl_IsAsrEnabled = FALSE;
  28. PWSTR Gbl_AsrErrorFilePath = NULL;
  29. HANDLE Gbl_AsrLogFileHandle = NULL;
  30. //
  31. // ----
  32. // Function implementations
  33. // ----
  34. //
  35. VOID
  36. AsrpLogMessage(
  37. IN CONST _MesgLevel Level,
  38. IN CONST PCSTR Message
  39. )
  40. /*++
  41. Routine Description:
  42. Logs the message to the asr log file, and the asr error file if needed.
  43. Note that AsrpInitialiseLogFile must have been called once before this
  44. routine is used.
  45. Arguments:
  46. Level - An enum specifying the level of the message being logged. If
  47. Level is set to s_Warning or s_Error, the Message is logged to the
  48. asr error file in addition to the asr log file.
  49. Message - The Message being logged. This routine will add in the time-
  50. stamp at the beginning of each message.
  51. Return Values:
  52. None. If the log file couldn't be found, the message isn't logged.
  53. --*/
  54. {
  55. SYSTEMTIME Time;
  56. DWORD bytesWritten = 0;
  57. char buffer[4196];
  58. GetLocalTime(&Time);
  59. //
  60. // This needs to be fixed by the year 2100.
  61. //
  62. sprintf(buffer, "[%02hu%02hu%02hu %02hu%02hu%02hu sfgen] %s%s\r\n",
  63. Time.wYear % 2000, Time.wMonth, Time.wDay,
  64. Time.wHour, Time.wMinute, Time.wSecond,
  65. ((s_Error == Level) ? "(ERROR) " :
  66. (s_Warning == Level ? "(warning) " : "")),
  67. Message
  68. );
  69. OutputDebugStringA(buffer);
  70. if (Gbl_AsrLogFileHandle) {
  71. WriteFile(Gbl_AsrLogFileHandle,
  72. buffer,
  73. (strlen(buffer) * sizeof(char)),
  74. &bytesWritten,
  75. NULL
  76. );
  77. }
  78. //
  79. // If this is a fatal error, we need to add to the error log.
  80. //
  81. if (((s_Error == Level) || (s_Warning == Level)) &&
  82. (Gbl_AsrErrorFilePath)
  83. ) {
  84. WCHAR buffer2[4196];
  85. HANDLE hFile = NULL;
  86. //
  87. // Open the error log
  88. //
  89. hFile = CreateFileW(
  90. Gbl_AsrErrorFilePath, // lpFileName
  91. GENERIC_WRITE | GENERIC_READ, // dwDesiredAccess
  92. FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode
  93. NULL, // lpSecurityAttributes
  94. OPEN_ALWAYS, // dwCreationFlags
  95. FILE_FLAG_WRITE_THROUGH, // dwFlagsAndAttributes
  96. NULL // hTemplateFile
  97. );
  98. if ((!hFile) || (INVALID_HANDLE_VALUE == hFile)) {
  99. return;
  100. }
  101. wsprintf(buffer2, L"\r\n[%04hu/%02hu/%02hu %02hu:%02hu:%02hu AsrSFGen] %ws%S\r\n",
  102. Time.wYear, Time.wMonth, Time.wDay,
  103. Time.wHour, Time.wMinute, Time.wSecond,
  104. ((s_Error == Level) ? L"(ERROR) " :
  105. (s_Warning == Level ? L"(warning) " : L"")),
  106. Message
  107. );
  108. //
  109. // Move to the end of file
  110. //
  111. SetFilePointer(hFile, 0L, NULL, FILE_END);
  112. //
  113. // Add our error string
  114. //
  115. WriteFile(hFile,
  116. buffer2,
  117. (wcslen(buffer2) * sizeof(WCHAR)),
  118. &bytesWritten,
  119. NULL
  120. );
  121. //
  122. // And we're done
  123. //
  124. CloseHandle(hFile);
  125. }
  126. }
  127. VOID
  128. AsrpPrintDbgMsg(
  129. IN CONST _MesgLevel Level,
  130. IN CONST PCSTR FormatString,
  131. ...
  132. )
  133. /*++
  134. Description:
  135. This prints a debug message AND makes the appropriate entries in the log
  136. and error files.
  137. Arguments:
  138. Level - Message Level (info, warning or error)
  139. FormatString - Formatted Message String to be printed. The expanded
  140. string should fit in a buffer of 4096 characters (including the
  141. terminating null character).
  142. Return Values:
  143. None
  144. --*/
  145. {
  146. char str[4096]; // the message better fit in this
  147. va_list arglist;
  148. va_start(arglist, FormatString);
  149. wvsprintfA(str, FormatString, arglist);
  150. va_end(arglist);
  151. AsrpLogMessage(Level, str);
  152. }
  153. PWSTR // must be freed by caller
  154. AsrpExpandEnvStrings(
  155. IN CONST PCWSTR OriginalString
  156. )
  157. /*++
  158. Routine Description:
  159. Expands any environment variables in the original string, replacing them
  160. with their defined values, and returns a pointer to a buffer containing
  161. the result.
  162. Arguments:
  163. OriginalString - Pointer to a null-terminated string that contains
  164. environment variables of the form %variableName%. For each such
  165. reference, the %variableName% portion is replaced with the current
  166. value of that environment variable.
  167. The replacement rules are the same as those used by the command
  168. interpreter. Case is ignored when looking up the environment-
  169. variable name. If the name is not found, the %variableName%
  170. portion is left undisturbed.
  171. Return Values:
  172. If this routine succeeds, the return value is a pointer to a buffer
  173. containing a copy of OriginalString after all environment-variable
  174. name substitutions have been performed. The caller is responsible
  175. for de-allocating this memory using HeapFree(GetProcessHeap(),...)
  176. when it is no longer needed.
  177. If the function fails, the return value is NULL. To get extended error
  178. information, call GetLastError.
  179. --*/
  180. {
  181. BOOL result = FALSE;
  182. UINT cchRequiredSize = 0,
  183. cchSize = MAX_PATH + 1; // start with a reasonable default
  184. PWSTR expandedString = NULL;
  185. DWORD status = ERROR_SUCCESS;
  186. HANDLE hHeap = GetProcessHeap();
  187. //
  188. // Allocate some memory for the destination string
  189. //
  190. expandedString = (PWSTR) HeapAlloc(
  191. hHeap,
  192. HEAP_ZERO_MEMORY,
  193. (cchSize * sizeof(WCHAR))
  194. );
  195. ErrExitCode(!expandedString, status, ERROR_NOT_ENOUGH_MEMORY);
  196. //
  197. // Try expanding. If the buffer isn't big enough, we'll re-allocate.
  198. //
  199. cchRequiredSize = ExpandEnvironmentStringsW(OriginalString,
  200. expandedString,
  201. cchSize
  202. );
  203. if (cchRequiredSize > cchSize) {
  204. //
  205. // Buffer wasn't big enough; free and re-allocate as needed
  206. //
  207. HeapFree(hHeap, 0L, expandedString);
  208. cchSize = cchRequiredSize + 1;
  209. expandedString = (PWSTR) HeapAlloc(
  210. hHeap,
  211. HEAP_ZERO_MEMORY,
  212. (cchSize * sizeof(WCHAR))
  213. );
  214. ErrExitCode(!expandedString, status, ERROR_NOT_ENOUGH_MEMORY);
  215. cchRequiredSize = ExpandEnvironmentStringsW(OriginalString,
  216. expandedString,
  217. cchSize
  218. );
  219. if (cchRequiredSize > cchSize) {
  220. SetLastError(ERROR_BAD_ENVIRONMENT);
  221. }
  222. }
  223. if ((0 == cchRequiredSize) || (cchRequiredSize > cchSize)) {
  224. //
  225. // Either the function failed, or the buffer wasn't big enough
  226. // even on the second try.
  227. //
  228. if (expandedString) {
  229. HeapFree(hHeap, 0L, expandedString);
  230. expandedString = NULL;
  231. }
  232. }
  233. EXIT:
  234. return expandedString;
  235. }
  236. VOID
  237. AsrpInitialiseErrorFile(
  238. VOID
  239. )
  240. /*++
  241. Description:
  242. Creates an empty ASR error file at %systemroot%\repair\asr.err, and
  243. initialises Gbl_AsrErrorFilePath with the full path to asr.err. This
  244. routine must be called once before AsrPrintDbgMsg is used.
  245. Arguments:
  246. None
  247. Return Values:
  248. None
  249. --*/
  250. {
  251. HANDLE errorFileHandle = NULL;
  252. //
  253. // Get full path to the error file.
  254. //
  255. Gbl_AsrErrorFilePath = AsrpExpandEnvStrings(ASRSFGEN_ASR_ERROR_FILE_PATH);
  256. if (!Gbl_AsrErrorFilePath) {
  257. return;
  258. }
  259. //
  260. // Create an empty file (append to it if it already exists), and close it
  261. // immediately
  262. //
  263. errorFileHandle = CreateFileW(
  264. Gbl_AsrErrorFilePath, // lpFileName
  265. GENERIC_WRITE, // dwDesiredAccess
  266. FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode
  267. NULL, // lpSecurityAttributes
  268. OPEN_ALWAYS, // dwCreationFlags
  269. FILE_FLAG_WRITE_THROUGH, // dwFlagsAndAttributes
  270. NULL // hTemplateFile
  271. );
  272. if ((errorFileHandle) && (INVALID_HANDLE_VALUE != errorFileHandle)) {
  273. CloseHandle(errorFileHandle);
  274. }
  275. }
  276. VOID
  277. AsrpInitialiseLogFiles(
  278. VOID
  279. )
  280. /*++
  281. Description:
  282. This creates an ASR log file at %systemroot%\repair\asr.log, and
  283. initialises Gbl_AsrLogFileHandle. It also initialises the ASR error file
  284. by calling AsrInitialiseErrorFile().
  285. This routine must be called once before AsrPrintDbgMsg is used.
  286. Arguments:
  287. None
  288. Return Values:
  289. None
  290. --*/
  291. {
  292. PWSTR asrLogFilePath = NULL;
  293. HANDLE hHeap = GetProcessHeap();
  294. DWORD bytesWritten;
  295. AsrpInitialiseErrorFile();
  296. Gbl_AsrLogFileHandle = NULL;
  297. //
  298. // Get full path to the error file.
  299. //
  300. asrLogFilePath = AsrpExpandEnvStrings(ASRSFGEN_ASR_LOG_FILE_PATH);
  301. if (!asrLogFilePath) {
  302. return;
  303. }
  304. //
  305. // Create an empty file (over-write it if it already exists).
  306. //
  307. Gbl_AsrLogFileHandle = CreateFileW(
  308. asrLogFilePath, // lpFileName
  309. GENERIC_WRITE | GENERIC_READ, // dwDesiredAccess
  310. FILE_SHARE_READ, // dwShareMode: nobody else should write to the log file while we are
  311. NULL, // lpSecurityAttributes
  312. OPEN_ALWAYS, // dwCreationFlags
  313. FILE_FLAG_WRITE_THROUGH, // dwFlagsAndAttributes: write through so we flush
  314. NULL // hTemplateFile
  315. );
  316. if ((Gbl_AsrLogFileHandle) && (INVALID_HANDLE_VALUE != Gbl_AsrLogFileHandle)) {
  317. //
  318. // Move to the end of file
  319. //
  320. SetFilePointer(Gbl_AsrLogFileHandle, 0L, NULL, FILE_END);
  321. WriteFile(Gbl_AsrLogFileHandle, "\r\n",
  322. (strlen("\r\n") * sizeof(char)), &bytesWritten,NULL);
  323. AsrpPrintDbgMsg(s_Info, "****** Entering asrsfgen.exe. ASR log at %ws", asrLogFilePath);
  324. }
  325. else {
  326. AsrpPrintDbgMsg(s_Error,
  327. "******* Unable to create/open ASR log file at %ws (0x%x)",
  328. asrLogFilePath, GetLastError()
  329. );
  330. }
  331. if (asrLogFilePath) {
  332. HeapFree(hHeap, 0L, asrLogFilePath);
  333. asrLogFilePath = NULL;
  334. }
  335. }
  336. VOID
  337. AsrpCloseLogFiles(
  338. VOID
  339. )
  340. /*++
  341. Description:
  342. This closes the ASR error and log file at %systemroot%\repair\, and
  343. frees the global variables associated with them.
  344. This must be called during clean-up. AsrpPrintDbgMesg() will have no
  345. effect after this routine is called.
  346. Arguments:
  347. None
  348. Return Values:
  349. None
  350. --*/
  351. {
  352. AsrpPrintDbgMsg(s_Info, "****** Exiting asrsfgen.exe.");
  353. //
  354. // Clean up global values
  355. //
  356. if (Gbl_AsrErrorFilePath) {
  357. HeapFree(GetProcessHeap(), 0L, Gbl_AsrErrorFilePath);
  358. Gbl_AsrErrorFilePath = NULL;
  359. }
  360. if ((Gbl_AsrLogFileHandle) && (INVALID_HANDLE_VALUE != Gbl_AsrLogFileHandle)) {
  361. CloseHandle(Gbl_AsrLogFileHandle);
  362. Gbl_AsrLogFileHandle = NULL;
  363. }
  364. }