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.

629 lines
12 KiB

  1. //3456789012345678901234567890123456789012345678901234567890123456789012345678
  2. /*++
  3. Copyright (c) 1997 Microsoft Corporation.
  4. Module Name:
  5. logutils.c
  6. Abstract:
  7. Contains functions that deal with ntlog.dll
  8. Author:
  9. Jason Allor (JasonAll) 5/27/97
  10. Revision History:
  11. --*/
  12. #include "logutils.h"
  13. static HANDLE g_hSemaphore;
  14. static ULONG g_ulPass;
  15. static ULONG g_ulFail;
  16. static ULONG g_ulInfo;
  17. /*++
  18. Routine Description: LoadDLLs
  19. Tries to dynamically load ntlog.dll functions
  20. Arguments:
  21. DLLName: the name of the DLL to load, ntlog.dll in this case
  22. Return Value:
  23. void
  24. --*/
  25. void LoadDLLs(IN PTCHAR DLLName)
  26. {
  27. HINSTANCE Library;
  28. //
  29. // Set global handle to logfile to NULL
  30. //
  31. gPnPTestLog = NULL;
  32. //
  33. // Load the engine DLL
  34. //
  35. Library = LoadLibrary(DLLName);
  36. if ((UINT) Library > 32)
  37. {
  38. #ifdef UNICODE
  39. _tlLog = (Dll_tlLog) \
  40. GetProcAddress(Library, "tlLog_W");
  41. _tlCreateLog = (Dll_tlCreateLog) \
  42. GetProcAddress(Library, "tlCreateLog_W");
  43. #else
  44. _tlLog = (Dll_tlLog) \
  45. GetProcAddress(Library, "tlLog_A");
  46. _tlCreateLog = (Dll_tlCreateLog) \
  47. GetProcAddress(Library, "tlCreateLog_A");
  48. #endif
  49. _tlAddParticipant = (Dll_tlAddParticipant) \
  50. GetProcAddress(Library, "tlAddParticipant");
  51. _tlDestroyLog = (Dll_tlDestroyLog) \
  52. GetProcAddress(Library, "tlDestoryLog");
  53. _tlEndVariation = (Dll_tlEndVariation) \
  54. GetProcAddress(Library, "tlEndVariation");
  55. _tlRemoveParticipant = (Dll_tlRemoveParticipant) \
  56. GetProcAddress(Library, "tlRemoveParticipant");
  57. _tlStartVariation = (Dll_tlStartVariation) \
  58. GetProcAddress(Library, "tlStartVariation");
  59. _tlReportStats = (Dll_tlReportStats) \
  60. GetProcAddress(Library, "tlReportStats");
  61. gNtLogLoaded = TRUE;
  62. }
  63. else
  64. {
  65. gNtLogLoaded = FALSE;
  66. }
  67. return;
  68. } // LoadDLLs //
  69. /*++
  70. Routine Description: InitLog
  71. This routine will import the NtLog DLL functions and initialize them
  72. Arguments:
  73. none
  74. Return Value:
  75. HANDLE: handle to the log file
  76. --*/
  77. HANDLE InitLog(IN PTCHAR tszLogName,
  78. IN PTCHAR tszTitle,
  79. IN BOOL bConsole)
  80. {
  81. gPnPTestLog = NULL;
  82. gPnPTestLogFile = NULL;
  83. g_ulPass = 0;
  84. g_ulFail = 0;
  85. g_ulInfo = 0;
  86. //
  87. // Initialize Semaphore
  88. //
  89. g_hSemaphore = CreateSemaphore(NULL, 1, 9999, NULL);
  90. if (g_hSemaphore == NULL)
  91. {
  92. _ftprintf(stderr, TEXT("WARNING! Could not create semaphore!\n"));
  93. }
  94. CreateConsoleWindow(bConsole, tszTitle);
  95. //
  96. // Set up console window for log output
  97. //
  98. g_hConsole = CreateConsoleScreenBuffer(GENERIC_WRITE,
  99. 0,
  100. NULL,
  101. CONSOLE_TEXTMODE_BUFFER,
  102. NULL);
  103. if (g_hConsole == INVALID_HANDLE_VALUE)
  104. {
  105. return INVALID_HANDLE_VALUE;
  106. }
  107. //
  108. // Load ntlog.dll
  109. //
  110. LoadDLLs(TEXT("ntlog.dll"));
  111. if (gNtLogLoaded)
  112. {
  113. g_LogLineLen = NTLOG_LINE_LEN;
  114. gPnPTestLog = _tlCreateLog((LPCWSTR)(tszLogName), LOG_OPTIONS);
  115. if (!gPnPTestLog)
  116. {
  117. _ftprintf(stderr, TEXT("WARNING! Log file could not be created!\n"));
  118. }
  119. else
  120. {
  121. _tlStartVariation(gPnPTestLog);
  122. _tlAddParticipant(gPnPTestLog, 0, 0);
  123. }
  124. }
  125. else
  126. {
  127. SetConsoleActiveScreenBuffer(g_hConsole);
  128. g_LogLineLen = NO_NTLOG_LINE_LEN;
  129. gPnPTestLogFile = _tfopen(tszLogName, TEXT("w"));
  130. if (!gPnPTestLogFile)
  131. {
  132. _ftprintf(stderr, TEXT("WARNING! Log file could not be created!\n"));
  133. }
  134. }
  135. return gPnPTestLog;
  136. } // InitLog //
  137. /*++
  138. Routine Description: ExitLog
  139. Processes clean-up work before exiting the program
  140. Arguments:
  141. none
  142. Return Value:
  143. void
  144. --*/
  145. void ExitLog()
  146. {
  147. double dTotal;
  148. double dPass;
  149. double dFail;
  150. USHORT usPassPerc;
  151. USHORT usFailPerc;
  152. CloseHandle(g_hConsole);
  153. CloseHandle(g_hSemaphore);
  154. if (gNtLogLoaded)
  155. {
  156. if (gPnPTestLog)
  157. {
  158. _tlReportStats(gPnPTestLog);
  159. _tlRemoveParticipant(gPnPTestLog);
  160. _tlEndVariation(gPnPTestLog);
  161. gPnPTestLog = NULL;
  162. }
  163. }
  164. else
  165. {
  166. //
  167. // Print out statistics
  168. //
  169. dTotal = g_ulPass + g_ulFail;
  170. dPass = (double)g_ulPass / dTotal;
  171. dFail = (double)g_ulFail / dTotal;
  172. usPassPerc = (USHORT)(dPass * 100);
  173. usFailPerc = (USHORT)(dFail * 100);
  174. LogBlankLine();
  175. LogBlankLine();
  176. Log(0, INFO, TEXT("Log Statistics:"));
  177. LogBlankLine();
  178. Log(0, INFO, TEXT("Pass: %lu\t%lu%%%%%%%%%%%%%%%"), g_ulPass, usPassPerc);
  179. Log(0, INFO, TEXT("Fail: %lu\t%lu%%%%%%%%%%%%%%%"), g_ulFail, usFailPerc);
  180. Log(0, INFO, TEXT("Total: %lu"), dTotal);
  181. if (gPnPTestLog)
  182. {
  183. fclose(gPnPTestLogFile);
  184. gPnPTestLogFile = NULL;
  185. }
  186. }
  187. } // ExitLog //
  188. /*++
  189. Routine Description: WriteLog
  190. Wrapper function to write to the log
  191. Arguments:
  192. dwLoglevel: specifies the log level such as TLS_INF, TLS_WARN, or TLS_SEV2
  193. tszBuffer: the string to write to the log
  194. Return Value:
  195. void
  196. --*/
  197. void WriteLog(IN DWORD dwLogLevel,
  198. IN PTCHAR tszBuffer)
  199. {
  200. USHORT i;
  201. HANDLE hConsole;
  202. DWORD dwDummy;
  203. TCHAR tszLogLine[2000];
  204. CHAR cszAnsi[2000];
  205. CHAR cszLogLine[2000];
  206. if (gNtLogLoaded)
  207. {
  208. if (gPnPTestLog)
  209. {
  210. _tlLog(gPnPTestLog, dwLogLevel | TL_VARIATION, tszBuffer);
  211. }
  212. }
  213. else
  214. {
  215. //
  216. // Convert tszBuffer to an ANSI string
  217. //
  218. #ifdef UNICODE
  219. _tcscpy(tszLogLine, tszBuffer);
  220. for (i = 0; i < _tcslen(tszBuffer) && i < 1999; i++)
  221. {
  222. cszAnsi[i] = (CHAR)tszLogLine[0];
  223. _tcscpy(tszLogLine, _tcsinc(tszLogLine));
  224. }
  225. cszAnsi[i] = '\0';
  226. #else
  227. strcpy(cszAnsi, tszBuffer);
  228. #endif
  229. switch (dwLogLevel)
  230. {
  231. case INFO:
  232. sprintf(cszLogLine, "INFO ");
  233. g_ulInfo++;
  234. break;
  235. case SEV1:
  236. sprintf(cszLogLine, "SEV1 ");
  237. g_ulFail++;
  238. break;
  239. case SEV2:
  240. sprintf(cszLogLine, "SEV2 ");
  241. g_ulFail++;
  242. break;
  243. case SEV3:
  244. sprintf(cszLogLine, "SEV3 ");
  245. g_ulFail++;
  246. break;
  247. case PASS:
  248. sprintf(cszLogLine, "PASS ");
  249. g_ulPass++;
  250. break;
  251. default:
  252. sprintf(cszLogLine, " ");
  253. }
  254. if (gPnPTestLogFile)
  255. {
  256. sprintf (cszLogLine, "%s%s\n", cszLogLine, cszAnsi);
  257. WaitForSingleObject(g_hSemaphore, INFINITE);
  258. //
  259. // Print to log file
  260. //
  261. fprintf(gPnPTestLogFile, cszLogLine);
  262. fflush(gPnPTestLogFile);
  263. //
  264. // Print to screen
  265. //
  266. WriteFile(g_hConsole,
  267. cszLogLine,
  268. strlen(cszLogLine),
  269. &dwDummy,
  270. NULL);
  271. ReleaseSemaphore(g_hSemaphore, 1, NULL);
  272. }
  273. }
  274. return;
  275. } // WriteLog //
  276. /*++
  277. Routine Description: Log
  278. Wrapper to the Log function. It divides a long string into
  279. shorter strings and puts each one on a separate line to avoid running
  280. over the end of a console window
  281. Arguments:
  282. dFunctionNumber: shows which function this log output is coming from.
  283. Used to track function progress
  284. dwLoglevel: specifies the log level such as TLS_INF, TLS_WARN,
  285. or TLS_SEV2
  286. tszLogString: printf() style format string
  287. Return Value:
  288. void
  289. --*/
  290. void Log(IN double dFunctionNumber,
  291. IN DWORD dwLogLevel,
  292. IN PTCHAR tszLogString,
  293. IN ...)
  294. {
  295. va_list va;
  296. TCHAR tszBuffer[LOG_STRING_LEN];
  297. TCHAR tszBufferToPrint[LOG_STRING_LEN];
  298. TCHAR tszTmpString[LOG_STRING_LEN + LOG_SPACE_LEN];
  299. ULONG ulIndex, i, j;
  300. BOOL boolFirstTime = TRUE;
  301. int iInteger, iFunctionNumber;
  302. double dDecimal;
  303. //
  304. // Prints the list to a buffer
  305. //
  306. va_start(va, tszLogString);
  307. if (!_vsntprintf (tszBuffer, LOG_STRING_LEN, tszLogString, va))
  308. {
  309. _ftprintf(stderr, TEXT("Log: Failed\n"));
  310. ExitLog();
  311. exit(1);
  312. }
  313. va_end(va);
  314. switch (dwLogLevel)
  315. {
  316. case INFO:
  317. SetConsoleTextAttribute(g_hConsole, GREY);
  318. break;
  319. case SEV1:
  320. SetConsoleTextAttribute(g_hConsole, RED);
  321. break;
  322. case SEV2:
  323. SetConsoleTextAttribute(g_hConsole, RED);
  324. break;
  325. case SEV3:
  326. SetConsoleTextAttribute(g_hConsole, RED);
  327. break;
  328. case PASS:
  329. SetConsoleTextAttribute(g_hConsole, GREEN);
  330. break;
  331. default:
  332. SetConsoleTextAttribute(g_hConsole, GREY);
  333. }
  334. while (_tcslen(tszBuffer))
  335. {
  336. ZeroMemory(tszBufferToPrint, LOG_STRING_LEN);
  337. if (_tcslen(tszBuffer) > g_LogLineLen)
  338. {
  339. //
  340. // If the LogString is longer than the console length, start at the
  341. // maximum console length and work backwards until we hit a space
  342. // to find out where to cut off the string
  343. //
  344. for (ulIndex = g_LogLineLen; ulIndex > 0; ulIndex--)
  345. {
  346. if (tszBuffer[ulIndex] == ' ')
  347. {
  348. break;
  349. }
  350. }
  351. //
  352. // index now sits on the last char that we want to print. Create
  353. // two strings - one to print now and one with the leftovers.
  354. //
  355. for (i = 0; i < ulIndex; i++)
  356. {
  357. tszBufferToPrint[i] = tszBuffer[i];
  358. }
  359. ulIndex++;
  360. for (i = 0; i < LOG_STRING_LEN; i++)
  361. {
  362. //
  363. // Shift the remaining string up to the front
  364. //
  365. if (i < LOG_STRING_LEN - ulIndex)
  366. {
  367. tszBuffer[i] = tszBuffer[i + ulIndex];
  368. }
  369. else
  370. {
  371. tszBuffer[i] = '\0';
  372. }
  373. }
  374. }
  375. else
  376. {
  377. //
  378. // Just print out the entire string since it contains no spaces
  379. //
  380. _stprintf(tszBufferToPrint, tszBuffer);
  381. ZeroMemory(tszBuffer, LOG_STRING_LEN);
  382. }
  383. if (boolFirstTime)
  384. {
  385. {
  386. _stprintf(tszTmpString, TEXT("(%.2f) "), dFunctionNumber);
  387. }
  388. _tcscat(tszTmpString, tszBufferToPrint);
  389. _tcscpy(tszBufferToPrint, tszTmpString);
  390. WriteLog(dwLogLevel, tszBufferToPrint);
  391. }
  392. else
  393. {
  394. _stprintf(tszTmpString, TEXT(" "));
  395. _tcscat(tszTmpString, tszBufferToPrint);
  396. _tcscpy(tszBufferToPrint, tszTmpString);
  397. WriteLog(INFO, tszBufferToPrint);
  398. }
  399. boolFirstTime = FALSE;
  400. }
  401. return;
  402. } // Log //
  403. /*++
  404. Routine Description: LogBlankLine
  405. Print a blank line to the log
  406. Arguments:
  407. none
  408. Return Value:
  409. void
  410. --*/
  411. VOID LogBlankLine()
  412. {
  413. SetConsoleTextAttribute(g_hConsole, GREY);
  414. WriteLog(INFO, TEXT(" "));
  415. } // LogBlankLine //
  416. /*++
  417. Routine Description: CreateConsoleWindow
  418. Creates a console window for this process to dump the log output into.
  419. Gives the console window a title and uses this title to get a handle
  420. to the console window. Then disables the cancel button on the window.
  421. Arguments:
  422. bConsole: TRUE if a new console window needs to be created.
  423. FALSE if there is already a console that can be used
  424. tszTitle: title to give the console window
  425. Return Value:
  426. none
  427. --*/
  428. VOID CreateConsoleWindow(IN BOOL bConsole,
  429. IN PTCHAR tszTitle)
  430. {
  431. HWND gConsole;
  432. if (bConsole)
  433. {
  434. //
  435. // Create a console window to dump the log output in
  436. //
  437. if (!AllocConsole())
  438. {
  439. goto RETURN;
  440. }
  441. }
  442. if (!SetConsoleTitle(tszTitle))
  443. {
  444. goto RETURN;
  445. }
  446. RETURN:
  447. return;
  448. } // CreateConsoleWindow //
  449. VOID AddLogParticipant(IN HANDLE hLog)
  450. {
  451. if (gNtLogLoaded)
  452. {
  453. _tlAddParticipant(hLog, 0, 0);
  454. }
  455. } // AddLogParticipant //
  456. VOID RemoveLogParticipant(IN HANDLE hLog)
  457. {
  458. if (gNtLogLoaded)
  459. {
  460. _tlRemoveParticipant(hLog);
  461. }
  462. } // RemoveLogParticipant //