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.

767 lines
14 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. beta.c
  5. Abstract:
  6. Logging for beta data gathering.
  7. Author:
  8. Jim Schmidt (jimschm) 10-Jun-1998
  9. Revision History:
  10. Jim Schmidt (jimschm) 04-Aug-1998 Config log options
  11. --*/
  12. #include "pch.h"
  13. #include "migutilp.h"
  14. #include "beta.h"
  15. #define BETA_INDENT 12
  16. static HANDLE g_BetaLog = INVALID_HANDLE_VALUE;
  17. static HANDLE g_BetaLogHandle = INVALID_HANDLE_VALUE;
  18. static HANDLE g_ConfigLogHandle = INVALID_HANDLE_VALUE;
  19. static BOOL g_Direct = FALSE;
  20. PCSTR
  21. pBetaFindEndOfLine (
  22. PCSTR Line,
  23. INT Indent
  24. )
  25. {
  26. int Col = 0;
  27. PCSTR LastSpace = NULL;
  28. Indent = 79 - Indent;
  29. while (*Line && Col < Indent) {
  30. if (*Line == ' ') {
  31. LastSpace = Line;
  32. }
  33. if (*Line == '\n') {
  34. LastSpace = Line;
  35. break;
  36. }
  37. Col++;
  38. Line++;
  39. }
  40. if (*Line && !LastSpace) {
  41. LastSpace = Line;
  42. }
  43. if (!(*Line)) {
  44. return Line;
  45. }
  46. return LastSpace + 1;
  47. }
  48. VOID
  49. pBetaPadTitle (
  50. PSTR Title,
  51. INT Indent
  52. )
  53. {
  54. INT i;
  55. PSTR p;
  56. p = strchr (Title, 0);
  57. i = strlen (Title);
  58. while (i < Indent) {
  59. *p = ' ';
  60. p++;
  61. i++;
  62. }
  63. *p = 0;
  64. }
  65. VOID
  66. pBetaHangingIndent (
  67. IN PCSTR UnindentedText,
  68. IN PSTR Buffer,
  69. IN INT Indent,
  70. OUT BOOL *Multiline OPTIONAL
  71. )
  72. {
  73. CHAR IndentedStr[4096];
  74. PCSTR p, s;
  75. PSTR d;
  76. INT i;
  77. if (Multiline) {
  78. *Multiline = FALSE;
  79. }
  80. p = pBetaFindEndOfLine (UnindentedText, Indent);
  81. s = UnindentedText;
  82. d = IndentedStr;
  83. while (TRUE) {
  84. // Copy line from source to dest
  85. while (s < p) {
  86. if (*s == '\r' && *(s + 1) == '\n') {
  87. s++;
  88. }
  89. if (*s == '\n') {
  90. *d++ = '\r';
  91. }
  92. *d++ = *s++;
  93. }
  94. // If another line, prepare an indent
  95. if (*p) {
  96. if (Multiline) {
  97. *Multiline = TRUE;
  98. }
  99. if (*(p - 1) != '\n') {
  100. *d++ = '\r';
  101. *d++ = '\n';
  102. }
  103. for (i = 0 ; i < Indent ; i++) {
  104. *d = ' ';
  105. d++;
  106. }
  107. } else {
  108. break;
  109. }
  110. // Find end of next line
  111. p = pBetaFindEndOfLine (p, Indent);
  112. }
  113. *d = 0;
  114. strcpy (Buffer, IndentedStr);
  115. }
  116. VOID
  117. pSaveMessageToBetaLog (
  118. IN PCSTR Category,
  119. IN PCSTR Text
  120. )
  121. {
  122. CHAR PaddedCategory[256];
  123. CHAR IndentedText[4096];
  124. BOOL Multiline;
  125. if (g_Direct) {
  126. WriteFileStringA (g_BetaLog, "\r\n");
  127. g_Direct = FALSE;
  128. }
  129. strcpy (PaddedCategory, Category);
  130. pBetaPadTitle (PaddedCategory, BETA_INDENT);
  131. WriteFileStringA (g_BetaLog, PaddedCategory);
  132. pBetaHangingIndent (Text, IndentedText, BETA_INDENT, &Multiline);
  133. WriteFileStringA (g_BetaLog, IndentedText);
  134. if (Multiline) {
  135. WriteFileStringA (g_BetaLog, "\r\n\r\n");
  136. } else {
  137. WriteFileStringA (g_BetaLog, "\r\n");
  138. }
  139. DEBUGMSGA ((Category, "%s", Text));
  140. }
  141. VOID
  142. _cdecl
  143. BetaMessageA (
  144. IN PCSTR Category,
  145. IN PCSTR FormatStr,
  146. ... // ANSI args
  147. )
  148. /*++
  149. Routine Description:
  150. BetaMessageA formats the specified string and saves the message to the file
  151. beta.log. The message is formatted with a category in the left column and
  152. text in the right.
  153. Arguments:
  154. Category - Specifies the short text classifying the message
  155. FormatStr - Specifies the sprintf-style format string, in ANSI.
  156. ... - Specifies args for the format string, strings default to ANSI.
  157. Return Value:
  158. none
  159. --*/
  160. {
  161. va_list args;
  162. CHAR Message[4096];
  163. PushError();
  164. va_start (args, FormatStr);
  165. vsprintf (Message, FormatStr, args);
  166. pSaveMessageToBetaLog (Category, Message);
  167. va_end (args);
  168. PopError();
  169. }
  170. VOID
  171. _cdecl
  172. BetaCondMessageA (
  173. IN BOOL Expr,
  174. IN PCSTR Category,
  175. IN PCSTR FormatStr,
  176. ... // ANSI args
  177. )
  178. /*++
  179. Routine Description:
  180. BetaCondMessageA formats the specified string and saves the message to the
  181. file beta.log, if Expr is TRUE. The message is formatted with a category
  182. in the left column and text in the right.
  183. Arguments:
  184. Expr - Specifies non-zero if the message is to be added to the log, or
  185. zero if not.
  186. Category - Specifies the short text classifying the message
  187. FormatStr - Specifies the sprintf-style format string, in ANSI.
  188. ... - Specifies args for the format string, strings default to ANSI.
  189. Return Value:
  190. none
  191. --*/
  192. {
  193. va_list args;
  194. CHAR Message[4096];
  195. if (!Expr) {
  196. return;
  197. }
  198. PushError();
  199. va_start (args, FormatStr);
  200. vsprintf (Message, FormatStr, args);
  201. pSaveMessageToBetaLog (Category, Message);
  202. va_end (args);
  203. PopError();
  204. }
  205. VOID
  206. _cdecl
  207. BetaErrorMessageA (
  208. IN PCSTR Category,
  209. IN PCSTR FormatStr,
  210. ... // ANSI args
  211. )
  212. /*++
  213. Routine Description:
  214. BetaErrorMessageA formats the specified string and saves the message to the
  215. file beta.log. The message is formatted with a category in the left column
  216. and text in the right.
  217. In addition to the message, the current error code is recorded.
  218. Arguments:
  219. Category - Specifies the short text classifying the message
  220. FormatStr - Specifies the sprintf-style format string, in ANSI.
  221. ... - Specifies args for the format string, strings default to ANSI.
  222. Return Value:
  223. none
  224. --*/
  225. {
  226. va_list args;
  227. CHAR Message[4096];
  228. LONG rc;
  229. rc = GetLastError();
  230. va_start (args, FormatStr);
  231. vsprintf (Message, FormatStr, args);
  232. if (rc < 10) {
  233. sprintf (strchr (Message, 0), " [GLE=%u]", rc);
  234. } else {
  235. sprintf (strchr (Message, 0), " [GLE=%u (0%Xh)]", rc, rc);
  236. }
  237. pSaveMessageToBetaLog (Category, Message);
  238. va_end (args);
  239. SetLastError (rc);
  240. }
  241. VOID
  242. _cdecl
  243. BetaMessageW (
  244. IN PCSTR AnsiCategory,
  245. IN PCSTR AnsiFormatStr,
  246. ... // UNICODE args
  247. )
  248. /*++
  249. Routine Description:
  250. BetaMessageW formats the specified string and saves the message to the file
  251. beta.log. The message is formatted with a category in the left column and
  252. text in the right.
  253. Arguments:
  254. Category - Specifies the short text classifying the message
  255. FormatStr - Specifies the sprintf-style format string, in ANSI.
  256. ... - Specifies args for the format string, strings default to UNICODE.
  257. Return Value:
  258. none
  259. --*/
  260. {
  261. va_list args;
  262. WCHAR UnicodeMessage[4096];
  263. PCWSTR UnicodeFormatStr;
  264. PCSTR AnsiMessage;
  265. PushError();
  266. UnicodeFormatStr = ConvertAtoW (AnsiFormatStr);
  267. va_start (args, AnsiFormatStr);
  268. vswprintf (UnicodeMessage, UnicodeFormatStr, args);
  269. FreeConvertedStr (UnicodeFormatStr);
  270. AnsiMessage = ConvertWtoA (UnicodeMessage);
  271. pSaveMessageToBetaLog (AnsiCategory, AnsiMessage);
  272. FreeConvertedStr (AnsiMessage);
  273. va_end (args);
  274. PopError();
  275. }
  276. VOID
  277. _cdecl
  278. BetaCondMessageW (
  279. IN BOOL Expr,
  280. IN PCSTR AnsiCategory,
  281. IN PCSTR AnsiFormatStr,
  282. ... // UNICODE args
  283. )
  284. /*++
  285. Routine Description:
  286. BetaCondMessageW formats the specified string and saves the message to the
  287. file beta.log, if Expr is TRUE. The message is formatted with a category
  288. in the left column and text in the right.
  289. Arguments:
  290. Expr - Specifies non-zero if the message is to be added to the log, or
  291. zero if not.
  292. Category - Specifies the short text classifying the message
  293. FormatStr - Specifies the sprintf-style format string, in ANSI.
  294. ... - Specifies args for the format string, strings default to UNICODE.
  295. Return Value:
  296. none
  297. --*/
  298. {
  299. va_list args;
  300. WCHAR UnicodeMessage[4096];
  301. PCWSTR UnicodeFormatStr;
  302. PCSTR AnsiMessage;
  303. if (!Expr) {
  304. return;
  305. }
  306. PushError();
  307. UnicodeFormatStr = ConvertAtoW (AnsiFormatStr);
  308. va_start (args, AnsiFormatStr);
  309. vswprintf (UnicodeMessage, UnicodeFormatStr, args);
  310. FreeConvertedStr (UnicodeFormatStr);
  311. AnsiMessage = ConvertWtoA (UnicodeMessage);
  312. pSaveMessageToBetaLog (AnsiCategory, AnsiMessage);
  313. FreeConvertedStr (AnsiMessage);
  314. va_end (args);
  315. PopError();
  316. }
  317. VOID
  318. _cdecl
  319. BetaErrorMessageW (
  320. IN PCSTR AnsiCategory,
  321. IN PCSTR AnsiFormatStr,
  322. ... // UNICODE args
  323. )
  324. /*++
  325. Routine Description:
  326. BetaErrorMessageW formats the specified string and saves the message to the
  327. file beta.log. The message is formatted with a category in the left column
  328. and text in the right.
  329. In addition to the message, the current error code is recorded.
  330. Arguments:
  331. Category - Specifies the short text classifying the message
  332. FormatStr - Specifies the sprintf-style format string, in ANSI.
  333. ... - Specifies args for the format string, strings default to UNICODE.
  334. Return Value:
  335. none
  336. --*/
  337. {
  338. va_list args;
  339. WCHAR UnicodeMessage[4096];
  340. PCWSTR UnicodeFormatStr;
  341. PCSTR AnsiMessage;
  342. LONG rc;
  343. rc = GetLastError();
  344. UnicodeFormatStr = ConvertAtoW (AnsiFormatStr);
  345. va_start (args, AnsiFormatStr);
  346. vswprintf (UnicodeMessage, UnicodeFormatStr, args);
  347. if (rc < 10) {
  348. swprintf (wcschr (UnicodeMessage, 0), L" [GLE=%u]", rc);
  349. } else {
  350. swprintf (wcschr (UnicodeMessage, 0), L" [GLE=%u (0%Xh)]", rc, rc);
  351. }
  352. FreeConvertedStr (UnicodeFormatStr);
  353. AnsiMessage = ConvertWtoA (UnicodeMessage);
  354. pSaveMessageToBetaLog (AnsiCategory, AnsiMessage);
  355. FreeConvertedStr (AnsiMessage);
  356. va_end (args);
  357. SetLastError (rc);
  358. }
  359. VOID
  360. BetaCategory (
  361. IN PCSTR Category
  362. )
  363. {
  364. WriteFileStringA (g_BetaLog, "\r\n");
  365. g_Direct = FALSE;
  366. WriteFileStringA (g_BetaLog, Category);
  367. WriteFileStringA (g_BetaLog, ":\r\n\r\n");
  368. }
  369. VOID
  370. BetaLogDirectA (
  371. IN PCSTR Text
  372. )
  373. {
  374. g_Direct = TRUE;
  375. WriteFileStringA (g_BetaLog, Text);
  376. }
  377. VOID
  378. BetaLogDirectW (
  379. IN PCWSTR Text
  380. )
  381. {
  382. PCSTR AnsiText;
  383. AnsiText = ConvertWtoA (Text);
  384. if (AnsiText) {
  385. g_Direct = TRUE;
  386. WriteFileStringA (g_BetaLog, AnsiText);
  387. FreeConvertedStr (AnsiText);
  388. }
  389. }
  390. VOID
  391. BetaLogLineA (
  392. IN PCSTR FormatStr,
  393. ... // ANSI args
  394. )
  395. {
  396. va_list args;
  397. CHAR Message[4096];
  398. PushError();
  399. __try {
  400. va_start (args, FormatStr);
  401. vsprintf (Message, FormatStr, args);
  402. g_Direct = TRUE;
  403. WriteFileStringA (g_BetaLog, Message);
  404. WriteFileStringA (g_BetaLog, "\r\n");
  405. va_end (args);
  406. }
  407. __except (TRUE) {
  408. }
  409. PopError();
  410. }
  411. VOID
  412. BetaLogLineW (
  413. IN PCSTR AnsiFormatStr,
  414. ... // UNICODE args
  415. )
  416. {
  417. va_list args;
  418. WCHAR UnicodeMessage[4096];
  419. PCWSTR UnicodeFormatStr;
  420. PCSTR AnsiMessage;
  421. PushError();
  422. __try {
  423. UnicodeFormatStr = ConvertAtoW (AnsiFormatStr);
  424. va_start (args, AnsiFormatStr);
  425. vswprintf (UnicodeMessage, UnicodeFormatStr, args);
  426. FreeConvertedStr (UnicodeFormatStr);
  427. AnsiMessage = ConvertWtoA (UnicodeMessage);
  428. g_Direct = TRUE;
  429. WriteFileStringA (g_BetaLog, AnsiMessage);
  430. WriteFileStringA (g_BetaLog, "\r\n");
  431. FreeConvertedStr (AnsiMessage);
  432. va_end (args);
  433. }
  434. __except (TRUE) {
  435. }
  436. PopError();
  437. }
  438. VOID
  439. BetaNoWrapA (
  440. IN PCSTR Category,
  441. IN PCSTR FormatStr,
  442. ...
  443. )
  444. {
  445. va_list args;
  446. CHAR Message[4096];
  447. PushError();
  448. BetaCategory (Category);
  449. va_start (args, FormatStr);
  450. vsprintf (Message, FormatStr, args);
  451. g_Direct = TRUE;
  452. WriteFileStringA (g_BetaLog, Message);
  453. WriteFileStringA (g_BetaLog, "\r\n");
  454. va_end (args);
  455. PopError();
  456. }
  457. VOID
  458. BetaNoWrapW (
  459. IN PCSTR Category,
  460. IN PCSTR AnsiFormatStr,
  461. ...
  462. )
  463. {
  464. va_list args;
  465. WCHAR UnicodeMessage[4096];
  466. PCWSTR UnicodeFormatStr;
  467. PCSTR AnsiMessage;
  468. PushError();
  469. BetaCategory (Category);
  470. UnicodeFormatStr = ConvertAtoW (AnsiFormatStr);
  471. va_start (args, AnsiFormatStr);
  472. vswprintf (UnicodeMessage, UnicodeFormatStr, args);
  473. FreeConvertedStr (UnicodeFormatStr);
  474. AnsiMessage = ConvertWtoA (UnicodeMessage);
  475. g_Direct = TRUE;
  476. WriteFileStringA (g_BetaLog, AnsiMessage);
  477. WriteFileStringA (g_BetaLog, "\r\n");
  478. FreeConvertedStr (AnsiMessage);
  479. va_end (args);
  480. PopError();
  481. }
  482. VOID
  483. InitBetaLog (
  484. BOOL EraseExistingLog
  485. )
  486. {
  487. CHAR LogPath[MAX_PATH];
  488. CloseBetaLog();
  489. GetWindowsDirectory (LogPath, MAX_PATH);
  490. strcat (LogPath, "\\beta-upg.log");
  491. g_BetaLogHandle = CreateFile (
  492. LogPath,
  493. GENERIC_WRITE,
  494. 0,
  495. NULL,
  496. EraseExistingLog ? CREATE_ALWAYS : OPEN_ALWAYS,
  497. FILE_ATTRIBUTE_NORMAL,
  498. NULL
  499. );
  500. if (g_BetaLogHandle == INVALID_HANDLE_VALUE) {
  501. DEBUGMSG ((DBG_WHOOPS, "Can't open %s", LogPath));
  502. } else {
  503. SetFilePointer (g_BetaLogHandle, 0, NULL, FILE_END);
  504. }
  505. GetWindowsDirectory (LogPath, MAX_PATH);
  506. strcat (LogPath, "\\config.dmp");
  507. g_ConfigLogHandle = CreateFile (
  508. LogPath,
  509. GENERIC_WRITE,
  510. 0,
  511. NULL,
  512. EraseExistingLog ? CREATE_ALWAYS : OPEN_ALWAYS,
  513. FILE_ATTRIBUTE_NORMAL,
  514. NULL
  515. );
  516. if (g_ConfigLogHandle == INVALID_HANDLE_VALUE) {
  517. DEBUGMSG ((DBG_WHOOPS, "Can't open %s", LogPath));
  518. } else {
  519. SetFilePointer (g_ConfigLogHandle, 0, NULL, FILE_END);
  520. }
  521. g_BetaLog = g_BetaLogHandle;
  522. }
  523. VOID
  524. SelectBetaLog (
  525. BOOL UseBetaLog
  526. )
  527. {
  528. if (!UseBetaLog) {
  529. g_BetaLog = g_ConfigLogHandle;
  530. } else {
  531. g_BetaLog = g_BetaLogHandle;
  532. }
  533. }
  534. VOID
  535. CloseBetaLog (
  536. VOID
  537. )
  538. {
  539. if (g_BetaLogHandle != INVALID_HANDLE_VALUE) {
  540. CloseHandle (g_BetaLogHandle);
  541. g_BetaLogHandle = INVALID_HANDLE_VALUE;
  542. }
  543. if (g_ConfigLogHandle != INVALID_HANDLE_VALUE) {
  544. CloseHandle (g_ConfigLogHandle);
  545. g_ConfigLogHandle = INVALID_HANDLE_VALUE;
  546. }
  547. g_BetaLog = INVALID_HANDLE_VALUE;
  548. }