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.

396 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 1993-2001 Microsoft Corporation
  3. Module Name:
  4. log.cpp
  5. Abstract:
  6. This file implements the access to the postmortem log file.
  7. Author:
  8. Wesley Witt (wesw) 1-May-1993
  9. Environment:
  10. User Mode
  11. --*/
  12. #include "pch.cpp"
  13. #define BYTE_ORDER_MARK 0xFEFF
  14. #define MAX_PRINTF_BUF_SIZE (1024 * 4)
  15. enum LOG_TYPE {
  16. LT_ANSI,
  17. LT_UNICODE
  18. };
  19. //
  20. // global variables for this module
  21. //
  22. static HANDLE hFile = NULL;
  23. static DWORD dwStartingPos = 0;
  24. static WCHAR wchBOM = BYTE_ORDER_MARK;
  25. static DWORD dwLogType = LT_ANSI;
  26. void
  27. WriteAnsiCharsToLogFile(
  28. WCHAR *pszUnicode,
  29. DWORD dwCharCount
  30. )
  31. {
  32. char szAnsiBuf[MAX_PRINTF_BUF_SIZE] = {0};
  33. DWORD nCharTranslated;
  34. WCHAR szWcharBuf[MAX_PRINTF_BUF_SIZE] = {0};
  35. nCharTranslated = WideCharToMultiByte(CP_ACP, WC_SEPCHARS | WC_COMPOSITECHECK,
  36. pszUnicode, dwCharCount,
  37. szAnsiBuf, sizeof(szAnsiBuf), NULL, NULL);
  38. WriteFile( hFile, szAnsiBuf, nCharTranslated, &nCharTranslated, NULL );
  39. #if 0
  40. nCharTranslated = MultiByteToWideChar(CP_ACP, WC_SEPCHARS | WC_COMPOSITECHECK,
  41. szAnsiBuf, nCharTranslated,
  42. szWcharBuf, sizeof(szWcharBuf)/sizeof(WCHAR));
  43. WriteFile( hFile, szWcharBuf, nCharTranslated, &nCharTranslated, NULL );
  44. #endif
  45. }
  46. void
  47. __cdecl
  48. lprintf(
  49. DWORD dwFormatId,
  50. ...
  51. )
  52. /*++
  53. Routine Description:
  54. This is function is a printf style function for printing messages
  55. in a message file.
  56. Arguments:
  57. dwFormatId - format id in the message file
  58. ... - var args
  59. Return Value:
  60. None.
  61. --*/
  62. {
  63. _TCHAR buf[MAX_PRINTF_BUF_SIZE] = {0};
  64. DWORD dwCount;
  65. va_list args;
  66. va_start( args, dwFormatId );
  67. dwCount = FormatMessage(
  68. FORMAT_MESSAGE_FROM_HMODULE,
  69. NULL,
  70. dwFormatId,
  71. MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), // Default language
  72. buf,
  73. sizeof(buf) / sizeof(_TCHAR),
  74. &args
  75. );
  76. va_end(args);
  77. if (dwCount == 0) {
  78. // Failure, nothing to write.
  79. return;
  80. }
  81. #ifdef UNICODE
  82. // We currently want all of the output to be in ANSI
  83. if (dwLogType == LT_ANSI) {
  84. WriteAnsiCharsToLogFile(buf, dwCount);
  85. } else {
  86. WriteFile( hFile, buf, dwCount * sizeof(_TCHAR), &dwCount, NULL );
  87. }
  88. #else
  89. WriteFile( hFile, buf, dwCount, &dwCount, NULL );
  90. #endif
  91. return;
  92. }
  93. void
  94. __cdecl
  95. lprintfs(
  96. _TCHAR *format,
  97. ...
  98. )
  99. /*++
  100. Routine Description:
  101. This is function is a printf replacement that writes the output to
  102. the DrWatson log file.
  103. Arguments:
  104. format - print format
  105. ... - var args
  106. Return Value:
  107. None.
  108. --*/
  109. {
  110. _TCHAR buf[MAX_PRINTF_BUF_SIZE] = {0};
  111. int chars;
  112. DWORD cb;
  113. va_list arg_ptr;
  114. va_start(arg_ptr, format);
  115. chars = _vsntprintf(buf, _tsizeof(buf), format, arg_ptr);
  116. buf[_tsizeof(buf) - 1] = 0;
  117. if (chars < 0 || chars == _tsizeof(buf)) {
  118. cb = _tsizeof(buf) - 1;
  119. } else {
  120. cb = chars;
  121. }
  122. va_end(arg_ptr);
  123. Assert( hFile != NULL );
  124. #ifdef UNICODE
  125. // We currently want all of the output to be in ANSI
  126. if (dwLogType == LT_ANSI) {
  127. WriteAnsiCharsToLogFile(buf, cb);
  128. } else {
  129. WriteFile( hFile, buf, cb * sizeof(_TCHAR), &cb, NULL );
  130. }
  131. #else
  132. WriteFile( hFile, buf, cb * sizeof(_TCHAR), &cb, NULL );
  133. #endif
  134. }
  135. void
  136. OpenLogFile(
  137. _TCHAR *szFileName,
  138. BOOL fAppend,
  139. BOOL fVisual
  140. )
  141. /*++
  142. Routine Description:
  143. Opens the DrWatson logfile for reading & writting.
  144. Arguments:
  145. szFileName - logfile name
  146. fAppend - append the new data to the end of the file or
  147. create a new file
  148. fVisual - visual notification
  149. Return Value:
  150. None.
  151. --*/
  152. {
  153. DWORD size;
  154. DWORD Retries = 10;
  155. //
  156. // The log file may be in use by another instance
  157. // of Dr. Watson, so try and open it several times
  158. // with a wait inbetween.
  159. //
  160. for (;;) {
  161. hFile = CreateFile( szFileName,
  162. GENERIC_WRITE | GENERIC_READ,
  163. FILE_SHARE_READ,
  164. NULL,
  165. fAppend ? OPEN_ALWAYS : CREATE_ALWAYS,
  166. FILE_ATTRIBUTE_NORMAL,
  167. NULL
  168. );
  169. if (hFile != INVALID_HANDLE_VALUE) {
  170. break;
  171. }
  172. if (fVisual) {
  173. NonFatalError( LoadRcString(IDS_INVALID_LOGFILE) );
  174. _tgetcwd( szFileName, MAX_PATH );
  175. if (!BrowseForDirectory(NULL, szFileName, MAX_PATH )) {
  176. FatalError( GetLastError(),
  177. LoadRcString(IDS_CANT_OPEN_LOGFILE) );
  178. }
  179. MakeLogFileName( szFileName );
  180. }
  181. else if (Retries-- == 0) {
  182. ExitProcess( 1 );
  183. }
  184. else {
  185. Sleep(1000);
  186. }
  187. }
  188. if (!fAppend || GetLastError() != ERROR_ALREADY_EXISTS) {
  189. //
  190. // The file was just created, so put a header in it.
  191. //
  192. dwLogType = LT_UNICODE;
  193. WriteFile( hFile, &wchBOM, sizeof(_TCHAR), &size, NULL );
  194. lprintfs( _T("\r\n") );
  195. lprintf( MSG_BANNER );
  196. lprintfs( _T("\r\n") );
  197. } else {
  198. #ifdef UNICODE
  199. //
  200. // Check if the file is Unicode or ANSI
  201. //
  202. WCHAR wchHdr = 0;
  203. dwLogType = LT_ANSI;
  204. if (ReadFile( hFile, &wchHdr, sizeof(TCHAR), &size, NULL )) {
  205. if (wchHdr == wchBOM) {
  206. dwLogType = LT_UNICODE;
  207. }
  208. }
  209. #endif
  210. SetFilePointer( hFile, 0, 0, FILE_END );
  211. }
  212. dwStartingPos = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
  213. }
  214. void
  215. CloseLogFile(
  216. void
  217. )
  218. /*++
  219. Routine Description:
  220. Closes the DrWatson logfile & releases the semaphore that
  221. protects it.
  222. Arguments:
  223. None.
  224. Return Value:
  225. None.
  226. --*/
  227. {
  228. CloseHandle( hFile );
  229. }
  230. _TCHAR *
  231. GetLogFileData(
  232. PDWORD pdwLogFileDataSize
  233. )
  234. /*++
  235. Routine Description:
  236. Reads in all of the logfile data that has been written since it was
  237. opened. The data is placed into a buffer allocated by this function.
  238. The caller is responsible for freeing the memory.
  239. Arguments:
  240. pdwLogFileDataSize - pointer to a dword that contains the size
  241. in bytes of the data that is read.
  242. Return Value:
  243. Valid character pointer to the logfile data
  244. NULL - could not read the data.
  245. --*/
  246. {
  247. DWORD dwCurrPos;
  248. _TCHAR *p;
  249. DWORD size;
  250. dwCurrPos = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
  251. *pdwLogFileDataSize = 0;
  252. size = dwCurrPos - dwStartingPos;
  253. p = (_TCHAR *) calloc( size, sizeof(_TCHAR) );
  254. if (p == NULL) {
  255. return NULL;
  256. }
  257. SetFilePointer( hFile, dwStartingPos, NULL, FILE_BEGIN );
  258. if (!ReadFile( hFile, p, size, &size, NULL )) {
  259. free( p );
  260. p = NULL;
  261. size = 0;
  262. }
  263. SetFilePointer( hFile, dwCurrPos, NULL, FILE_BEGIN );
  264. *pdwLogFileDataSize = size;
  265. return p;
  266. }
  267. void
  268. MakeLogFileName(
  269. _TCHAR *szName
  270. )
  271. /*++
  272. Routine Description:
  273. Concatenates the base logfile name on to the string passed in.
  274. Arguments:
  275. szName - buffer for the logfile name.
  276. Return Value:
  277. None.
  278. --*/
  279. {
  280. if (_tcslen(szName) + 16 < MAX_PATH) {
  281. _tcscat( szName, _T("\\drwtsn32.log") );
  282. }
  283. }