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.

598 lines
15 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. TEST.C
  5. Abstract:
  6. Test program for the eventlog service. This program calls the Elf
  7. APIs to test out the operation of the service.
  8. Author:
  9. Rajen Shah (rajens) 05-Aug-1991
  10. Revision History:
  11. --*/
  12. /*----------------------*/
  13. /* INCLUDES */
  14. /*----------------------*/
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <stdio.h> // printf
  19. #include <string.h> // stricmp
  20. #include <stdlib.h>
  21. #include <process.h> // exit
  22. #include <elfcommn.h>
  23. #include <windows.h>
  24. #include <ntiolog.h>
  25. #include <malloc.h>
  26. #include <time.h>
  27. #define READ_BUFFER_SIZE 1024*2 // Use 2K buffer
  28. #define SIZE_DATA_ARRAY 65
  29. //
  30. // Global buffer used to emulate "binary data" when writing an event
  31. // record.
  32. //
  33. ULONG Data[SIZE_DATA_ARRAY];
  34. enum _OPERATION_TYPE {
  35. Invalid,
  36. Clear,
  37. Read,
  38. Write,
  39. LPC
  40. } Operation = Invalid;
  41. ULONG ReadFlags;
  42. ULONG NumberofRecords = 1;
  43. ULONG DelayInMilliseconds = 0;
  44. CHAR DefaultModuleName[] = "System";
  45. PCHAR pModuleName = DefaultModuleName;
  46. // Function prototypes
  47. VOID ParseParms(ULONG argc, PCHAR *argv);
  48. VOID
  49. Initialize (
  50. VOID
  51. )
  52. {
  53. ULONG i;
  54. // Initialize the values in the data buffer.
  55. //
  56. for (i=0; i< SIZE_DATA_ARRAY; i++)
  57. Data[i] = i;
  58. }
  59. VOID
  60. Usage (
  61. VOID
  62. )
  63. {
  64. printf( "usage: \n" );
  65. printf( "-c Clears the specified log\n");
  66. printf( "-rsb Reads nn event log records sequentially backwards\n");
  67. printf( "-rsf nn Reads nn event log records sequentially forwards\n");
  68. printf( "-rrb <record> Reads event log from <record> backwards\n");
  69. printf( "-rrf <record> Reads event log from <record> forwards\n");
  70. printf( "-m <modulename> Module name to use for read/clear\n");
  71. exit(0);
  72. } // Usage
  73. VOID
  74. DisplayEventRecords( PVOID Buffer,
  75. ULONG BufSize,
  76. PULONG NumRecords)
  77. {
  78. PEVENTLOGRECORD pLogRecord;
  79. IO_ERROR_LOG_PACKET UNALIGNED *errorPacket;
  80. NTSTATUS Status;
  81. ANSI_STRING StringA;
  82. UNICODE_STRING StringU;
  83. PWSTR pwString;
  84. PCHAR paString;
  85. ULONG Count = 0;
  86. ULONG Offset = 0;
  87. ULONG i;
  88. UCHAR MessageBuffer[265];
  89. BOOLEAN ioRecord;
  90. pLogRecord = (PEVENTLOGRECORD) Buffer;
  91. if (getenv("TZ") == NULL) {
  92. _putenv("TZ=PDT");
  93. }
  94. while (Offset < BufSize && Count < *NumRecords) {
  95. printf("\nRecord # %lu\n", pLogRecord->RecordNumber);
  96. if (/* pLogRecord->EventType != IO_TYPE_ERROR_MESSAGE || */
  97. pLogRecord->DataLength < sizeof(IO_ERROR_LOG_PACKET)) {
  98. ioRecord = FALSE;
  99. printf("Length: 0x%lx TimeGenerated: 0x%lx EventID: 0x%lx EventType: 0x%x\n",
  100. pLogRecord->Length, pLogRecord->TimeGenerated, pLogRecord->EventID,
  101. pLogRecord->EventType);
  102. printf("NumStrings: 0x%x StringOffset: 0x%lx UserSidLength: 0x%lx TimeWritten: 0x%lx\n",
  103. pLogRecord->NumStrings, pLogRecord->StringOffset,
  104. pLogRecord->UserSidLength, pLogRecord->TimeWritten);
  105. printf("UserSidOffset: 0x%lx DataLength: 0x%lx DataOffset: 0x%lx \n",
  106. pLogRecord->UserSidOffset, pLogRecord->DataLength,
  107. pLogRecord->DataOffset);
  108. } else {
  109. ioRecord = TRUE;
  110. errorPacket = (PIO_ERROR_LOG_PACKET)
  111. ((PCHAR) pLogRecord + pLogRecord->DataOffset);
  112. }
  113. //
  114. // Print out module name
  115. //
  116. pwString = (PWSTR)((LPBYTE) pLogRecord + sizeof(EVENTLOGRECORD));
  117. RtlInitUnicodeString (&StringU, pwString);
  118. RtlUnicodeStringToAnsiString (&StringA, &StringU, TRUE);
  119. printf("ModuleName: %s \t", StringA.Buffer);
  120. RtlFreeAnsiString (&StringA);
  121. //
  122. // Display ComputerName
  123. //
  124. pwString += wcslen(pwString) + 1;
  125. RtlInitUnicodeString (&StringU, pwString);
  126. RtlUnicodeStringToAnsiString (&StringA, &StringU, TRUE);
  127. printf("ComputerName: %s\n",StringA.Buffer);
  128. RtlFreeAnsiString (&StringA);
  129. //
  130. // Display strings
  131. //
  132. pwString = (PWSTR)((LPBYTE)pLogRecord + pLogRecord->StringOffset);
  133. printf("Strings: ");
  134. for (i=0; i<pLogRecord->NumStrings; i++) {
  135. RtlInitUnicodeString (&StringU, pwString);
  136. RtlUnicodeStringToAnsiString (&StringA, &StringU, TRUE);
  137. printf(" %s ",StringA.Buffer);
  138. RtlFreeAnsiString (&StringA);
  139. pwString = (PWSTR)((LPBYTE)pwString + StringU.MaximumLength);
  140. }
  141. printf("\n");
  142. if (ioRecord) {
  143. MessageBuffer[0] = '\0';
  144. FormatMessage(
  145. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
  146. NULL,
  147. errorPacket->ErrorCode,
  148. 0,
  149. MessageBuffer,
  150. 256,
  151. NULL
  152. );
  153. #if 0
  154. printf("Event id: %8lx, => %s",
  155. errorPacket->ErrorCode, MessageBuffer);
  156. #endif
  157. printf(MessageBuffer, errorPacket->DumpData[0], errorPacket->DumpData[1], errorPacket->DumpData[2]);
  158. printf("Major Function code: %2x, IoControlCode: %8x\n",
  159. errorPacket->MajorFunctionCode, errorPacket->IoControlCode);
  160. paString = ctime((time_t *) &pLogRecord->TimeGenerated);
  161. if (pwString != NULL) {
  162. printf("Sequence number: %ld, Time of error: %s",
  163. errorPacket->SequenceNumber, paString);
  164. }
  165. printf("Unique Error Value: %ld, Final Status: %8lx\n",
  166. errorPacket->UniqueErrorValue, errorPacket->FinalStatus);
  167. printf("Device Offset: %08lx%08lx\n",
  168. errorPacket->DeviceOffset.HighPart, errorPacket->DeviceOffset.LowPart);
  169. printf("Dump Data:");
  170. for (i = 0; i < 1 + (errorPacket->DumpDataSize +3)/ 4; i++) {
  171. if (!(i % 4)) {
  172. printf("\n");
  173. }
  174. printf("%08lx ", errorPacket->DumpData[i]);
  175. }
  176. printf("\n");
  177. }
  178. // Get next record
  179. //
  180. Offset += pLogRecord->Length;
  181. pLogRecord = (PEVENTLOGRECORD)((ULONG)Buffer + Offset);
  182. Count++;
  183. }
  184. *NumRecords = Count;
  185. }
  186. NTSTATUS
  187. ReadFromLog ( HANDLE LogHandle,
  188. PVOID Buffer,
  189. PULONG pBytesRead,
  190. ULONG ReadFlag,
  191. ULONG Record
  192. )
  193. {
  194. NTSTATUS Status;
  195. ULONG MinBytesNeeded;
  196. Status = ElfReadEventLogW (
  197. LogHandle,
  198. ReadFlag,
  199. Record,
  200. Buffer,
  201. READ_BUFFER_SIZE,
  202. pBytesRead,
  203. &MinBytesNeeded
  204. );
  205. if (Status == STATUS_NO_MORE_FILES)
  206. printf("Buffer too small. Need %lu bytes min\n", MinBytesNeeded);
  207. return (Status);
  208. }
  209. NTSTATUS
  210. TestReadEventLog (
  211. ULONG Count,
  212. ULONG ReadFlag,
  213. ULONG Record
  214. )
  215. {
  216. NTSTATUS Status, IStatus;
  217. HANDLE LogHandle;
  218. UNICODE_STRING ModuleNameU;
  219. ANSI_STRING ModuleNameA;
  220. ULONG NumRecords, BytesReturned;
  221. PVOID Buffer;
  222. ULONG RecordOffset;
  223. ULONG NumberOfRecords;
  224. ULONG OldestRecord;
  225. printf("Testing ElfReadEventLog API to read %lu entries\n",Count);
  226. Buffer = malloc (READ_BUFFER_SIZE);
  227. //
  228. // Initialize the strings
  229. //
  230. NumRecords = Count;
  231. RtlInitAnsiString(&ModuleNameA, pModuleName);
  232. RtlAnsiStringToUnicodeString(&ModuleNameU, &ModuleNameA, TRUE);
  233. //
  234. // Open the log handle
  235. //
  236. printf("ElfOpenEventLog - ");
  237. Status = ElfOpenEventLogW (
  238. NULL,
  239. &ModuleNameU,
  240. &LogHandle
  241. );
  242. if (!NT_SUCCESS(Status)) {
  243. printf("Error - 0x%lx\n", Status);
  244. } else {
  245. printf("SUCCESS\n");
  246. //
  247. // Get and print record information
  248. //
  249. Status = ElfNumberOfRecords(LogHandle, & NumberOfRecords);
  250. if (NT_SUCCESS(Status)) {
  251. Status = ElfOldestRecord(LogHandle, & OldestRecord);
  252. }
  253. if (!NT_SUCCESS(Status)) {
  254. printf("Query of record information failed with %X", Status);
  255. return(Status);
  256. }
  257. printf("\nThere are %d records in the file, %d is the oldest"
  258. " record number\n", NumberOfRecords, OldestRecord);
  259. RecordOffset = Record;
  260. while (Count && NT_SUCCESS(Status)) {
  261. printf("Read %u records\n", NumRecords);
  262. //
  263. // Read from the log
  264. //
  265. Status = ReadFromLog ( LogHandle,
  266. Buffer,
  267. &BytesReturned,
  268. ReadFlag,
  269. RecordOffset
  270. );
  271. if (NT_SUCCESS(Status)) {
  272. printf("Bytes read = 0x%lx\n", BytesReturned);
  273. NumRecords = Count;
  274. DisplayEventRecords(Buffer, BytesReturned, &NumRecords);
  275. Count -= NumRecords;
  276. }
  277. }
  278. printf("\n");
  279. if (!NT_SUCCESS(Status)) {
  280. if (Status == STATUS_END_OF_FILE) {
  281. printf("Tried to read more records than in log file\n");
  282. }
  283. else {
  284. printf ("Error - 0x%lx. Remaining count %lu\n", Status, Count);
  285. }
  286. } else {
  287. printf ("SUCCESS\n");
  288. }
  289. printf("Calling ElfCloseEventLog\n");
  290. IStatus = ElfCloseEventLog (LogHandle);
  291. }
  292. return (Status);
  293. }
  294. NTSTATUS
  295. TestElfClearLogFile(
  296. VOID
  297. )
  298. {
  299. NTSTATUS Status, IStatus;
  300. HANDLE LogHandle;
  301. UNICODE_STRING BackupU, ModuleNameU;
  302. ANSI_STRING ModuleNameA;
  303. printf("Testing ElfClearLogFile API\n");
  304. //
  305. // Initialize the strings
  306. //
  307. RtlInitAnsiString( &ModuleNameA, pModuleName);
  308. RtlAnsiStringToUnicodeString(&ModuleNameU, &ModuleNameA, TRUE);
  309. //
  310. // Open the log handle
  311. //
  312. printf("Calling ElfOpenEventLog for CLEAR - ");
  313. Status = ElfOpenEventLogW (
  314. NULL,
  315. &ModuleNameU,
  316. &LogHandle
  317. );
  318. if (!NT_SUCCESS(Status)) {
  319. printf("Error - 0x%lx\n", Status);
  320. } else {
  321. printf("SUCCESS\n");
  322. //
  323. // Clear the log file and back it up to "view.log"
  324. //
  325. printf("Calling ElfClearEventLogFile backing up to view.log ");
  326. RtlInitUnicodeString( &BackupU, L"view.log" );
  327. Status = ElfClearEventLogFileW (
  328. LogHandle,
  329. &BackupU
  330. );
  331. if (!NT_SUCCESS(Status)) {
  332. printf ("Error - 0x%lx\n", Status);
  333. } else {
  334. printf ("SUCCESS\n");
  335. }
  336. //
  337. // Now just clear the file without backing it up
  338. //
  339. printf("Calling ElfClearEventLogFile with no backup ");
  340. Status = ElfClearEventLogFileW (
  341. LogHandle,
  342. NULL
  343. );
  344. if (!NT_SUCCESS(Status)) {
  345. printf ("Error - 0x%lx\n", Status);
  346. } else {
  347. printf ("SUCCESS\n");
  348. }
  349. printf("Calling ElfCloseEventLog\n");
  350. IStatus = ElfCloseEventLog (LogHandle);
  351. }
  352. return(Status);
  353. }
  354. VOID
  355. main (
  356. IN SHORT argc,
  357. IN PSZ argv[]
  358. )
  359. {
  360. Initialize(); // Init any data
  361. //
  362. // Parse the command line
  363. //
  364. ParseParms(argc, argv);
  365. if ( Operation == Invalid) {
  366. printf( "Must specify an operation\n");
  367. Usage( );
  368. }
  369. switch (Operation) {
  370. case Clear:
  371. TestElfClearLogFile();
  372. case Read:
  373. if (ReadFlags & EVENTLOG_SEEK_READ) {
  374. TestReadEventLog(1, ReadFlags, NumberofRecords) ;
  375. }
  376. else {
  377. TestReadEventLog(NumberofRecords, ReadFlags, 0) ;
  378. }
  379. break;
  380. }
  381. }
  382. VOID
  383. ParseParms(
  384. ULONG argc,
  385. PCHAR *argv
  386. )
  387. {
  388. ULONG i;
  389. PCHAR pch;
  390. for (i = 1; i < argc; i++) { /* for each argument */
  391. if (*(pch = argv[i]) == '-') {
  392. while (*++pch) {
  393. switch (*pch) {
  394. case 'r':
  395. //
  396. // Different Read options
  397. //
  398. if (Operation != Invalid) {
  399. printf("Only one operation at a time\n");
  400. Usage();
  401. }
  402. Operation = Read;
  403. if (*++pch == 's') {
  404. ReadFlags |= EVENTLOG_SEQUENTIAL_READ;
  405. }
  406. else if (*pch == 'r') {
  407. ReadFlags |= EVENTLOG_SEEK_READ;
  408. }
  409. else {
  410. Usage();
  411. }
  412. if (*++pch == 'f') {
  413. ReadFlags |= EVENTLOG_FORWARDS_READ;
  414. }
  415. else if (*pch == 'b') {
  416. ReadFlags |= EVENTLOG_BACKWARDS_READ;
  417. }
  418. else {
  419. Usage();
  420. }
  421. //
  422. // See if they specified a number of records
  423. //
  424. if (i + 1 < argc && argv[i+1][0] != '-') {
  425. NumberofRecords = atoi(argv[++i]);
  426. if (NumberofRecords == 0) {
  427. Usage();
  428. }
  429. }
  430. break;
  431. case 'c':
  432. if (Operation != Invalid) {
  433. printf("Only one operation at a time\n");
  434. Usage();
  435. }
  436. Operation = Clear;
  437. break;
  438. case 'm':
  439. if (i+1 < argc) {
  440. pModuleName = argv[++i];
  441. }
  442. else {
  443. Usage();
  444. }
  445. break;
  446. case '?':
  447. case 'h':
  448. case 'H':
  449. Usage();
  450. break;
  451. default: /* Invalid options */
  452. printf("Invalid option %c\n\n", *pch);
  453. Usage();
  454. break;
  455. }
  456. }
  457. }
  458. //
  459. // There aren't any non switch parms
  460. else {
  461. Usage();
  462. }
  463. }
  464. }