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.

1487 lines
38 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. #define READ_BUFFER_SIZE 1024*2 // Use 2K buffer
  27. #define SIZE_DATA_ARRAY 22
  28. #define SET_OPERATION(x) \
  29. if (Operation != Invalid) { \
  30. printf("Only one operation at a time\n"); \
  31. Usage(); \
  32. } \
  33. Operation = x;
  34. //
  35. // Global buffer used to emulate "binary data" when writing an event
  36. // record.
  37. //
  38. ULONG Data[SIZE_DATA_ARRAY];
  39. enum _OPERATION_TYPE {
  40. Invalid,
  41. Clear,
  42. Backup,
  43. Read,
  44. Write,
  45. Notify,
  46. TestFull,
  47. LPC
  48. } Operation = Invalid;
  49. ULONG ReadFlags;
  50. BOOL Verbose = FALSE;
  51. ULONG NumberofRecords = 1;
  52. ULONG DelayInMilliseconds = 0;
  53. CHAR DefaultModuleName[] = "TESTAPP";
  54. PCHAR pModuleName = DefaultModuleName;
  55. PCHAR pBackupFileName;
  56. ANSI_STRING AnsiString;
  57. UNICODE_STRING ServerName;
  58. BOOL ReadingBackupFile = FALSE;
  59. BOOL ReadingModule = FALSE;
  60. BOOL WriteInvalidRecords = FALSE;
  61. BOOL InvalidUser = FALSE;
  62. // Function prototypes
  63. VOID ParseParms(ULONG argc, PCHAR *argv);
  64. VOID
  65. Initialize (
  66. VOID
  67. )
  68. {
  69. ULONG i;
  70. // Initialize the values in the data buffer.
  71. //
  72. for (i=0; i< SIZE_DATA_ARRAY; i++)
  73. Data[i] = i;
  74. }
  75. VOID
  76. Usage (
  77. VOID
  78. )
  79. {
  80. printf( "usage: \n" );
  81. printf( "-c Clears the specified log\n");
  82. printf( "-b <filename> Backs up the log to file <filename>\n");
  83. printf( "-f <filename> Filename of backup log to use for read\n");
  84. printf( "-i Generate invalid SID\n");
  85. printf( "-l[i] nn Writes nn records thru LPC port [i ==> bad records]\n");
  86. printf( "-m <modulename> Module name to use for read/clear\n");
  87. printf( "-n Test out change notify\n");
  88. printf( "-rsb Reads nn event log records sequentially backwards\n");
  89. printf( "-rsf nn Reads nn event log records sequentially forwards\n");
  90. printf( "-rrb <record> Reads event log from <record> backwards\n");
  91. printf( "-rrf <record> Reads event log from <record> forwards\n");
  92. printf( "-s <servername> Name of server to remote calls to\n");
  93. printf( "-t nn Number of milliseconds to delay between read/write"
  94. " (default 0)\n\tOnly used with -l switch\n");
  95. printf( "-w <count> Writes <count> records\n");
  96. printf( "-z Test to see if the logs are full\n");
  97. exit(0);
  98. } // Usage
  99. NTSTATUS
  100. WriteLogEntry (
  101. HANDLE LogHandle,
  102. ULONG EventID
  103. )
  104. {
  105. #define NUM_STRINGS 2
  106. #define SIZE_TOKEN_BUFFER 512
  107. SYSTEMTIME systime;
  108. NTSTATUS Status;
  109. USHORT EventType, i;
  110. ULONG DataSize;
  111. PSID pUserSid = NULL;
  112. PWSTR Strings[NUM_STRINGS] = {L"StringOne", L"StringTwo"};
  113. PUNICODE_STRING UStrings[NUM_STRINGS];
  114. HANDLE hProcess;
  115. HANDLE hToken;
  116. PTOKEN_USER pTokenUser;
  117. DWORD SizeRequired;
  118. EventType = EVENTLOG_INFORMATION_TYPE;
  119. DataSize = sizeof(ULONG) * SIZE_DATA_ARRAY;
  120. //
  121. // Get the SID of the current user (process)
  122. //
  123. pTokenUser = malloc(SIZE_TOKEN_BUFFER);
  124. if (!InvalidUser) {
  125. hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
  126. GetCurrentProcessId());
  127. if (!hProcess) {
  128. printf("Couldn't open the process, rc = %d\n", GetLastError());
  129. return(STATUS_UNSUCCESSFUL);
  130. }
  131. if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
  132. printf("Couldn't open the token, rc = %d\n", GetLastError());
  133. CloseHandle(hProcess);
  134. return(STATUS_UNSUCCESSFUL);
  135. }
  136. if (!pTokenUser) {
  137. printf("Couldn't allocate buffer for TokenUser\n");
  138. CloseHandle(hToken);
  139. CloseHandle(hProcess);
  140. return(STATUS_UNSUCCESSFUL);
  141. }
  142. if (!GetTokenInformation(hToken, TokenUser, pTokenUser, SIZE_TOKEN_BUFFER,
  143. &SizeRequired)) {
  144. printf("Couldn't get TokenUser information, rc = %d\n",
  145. GetLastError());
  146. CloseHandle(hToken);
  147. CloseHandle(hProcess);
  148. free(pTokenUser);
  149. return(STATUS_UNSUCCESSFUL);
  150. }
  151. CloseHandle(hToken);
  152. CloseHandle(hProcess);
  153. }
  154. else {
  155. memset(pTokenUser, 0xFADE, SIZE_TOKEN_BUFFER);
  156. pTokenUser->User.Sid = (PSID)pUserSid;
  157. }
  158. pUserSid = pTokenUser->User.Sid;
  159. for (i=0; i< SIZE_DATA_ARRAY; i++)
  160. Data[i] += i;
  161. // Allocate space for the unicode strings in the array, and
  162. // copy over the strings from Strings[] to that array.
  163. //
  164. for (i=0; i<NUM_STRINGS; i++) {
  165. UStrings[i] = malloc(sizeof(UNICODE_STRING));
  166. RtlInitUnicodeString (UStrings[i], Strings[i]);
  167. UStrings[i]->MaximumLength = UStrings[i]->Length + sizeof(WCHAR);
  168. }
  169. //
  170. // Vary the data sizes.
  171. //
  172. GetLocalTime(&systime);
  173. DataSize = systime.wMilliseconds % sizeof(Data);
  174. printf("\nData Size = %lu\n", DataSize);
  175. Status = ElfReportEventW (
  176. LogHandle,
  177. EventType,
  178. 0, // category
  179. EventID,
  180. pUserSid,
  181. NUM_STRINGS,
  182. DataSize,
  183. UStrings,
  184. (PVOID)Data,
  185. 0, // Flags - paired event support
  186. NULL, // RecordNumber | not in product 1
  187. NULL // TimeWritten -
  188. );
  189. for (i=0; i<NUM_STRINGS; i++)
  190. free(UStrings[i]);
  191. free(pTokenUser);
  192. return (Status);
  193. }
  194. VOID
  195. DisplayEventRecords( PVOID Buffer,
  196. ULONG BufSize,
  197. PULONG NumRecords)
  198. {
  199. PEVENTLOGRECORD pLogRecord;
  200. LPWSTR pwString;
  201. ULONG Count = 0;
  202. ULONG Offset = 0;
  203. ULONG i;
  204. pLogRecord = (PEVENTLOGRECORD) Buffer;
  205. while (Offset < BufSize && Count < *NumRecords) {
  206. printf("\nRecord # %lu\n", pLogRecord->RecordNumber);
  207. printf("Length: 0x%lx TimeGenerated: 0x%lx EventID: 0x%lx EventType: 0x%x\n",
  208. pLogRecord->Length, pLogRecord->TimeGenerated, pLogRecord->EventID,
  209. pLogRecord->EventType);
  210. printf("NumStrings: 0x%x StringOffset: 0x%lx UserSidLength: 0x%lx TimeWritten: 0x%lx\n",
  211. pLogRecord->NumStrings, pLogRecord->StringOffset,
  212. pLogRecord->UserSidLength, pLogRecord->TimeWritten);
  213. printf("UserSidOffset: 0x%lx DataLength: 0x%lx DataOffset: 0x%lx Category: 0x%lx\n",
  214. pLogRecord->UserSidOffset, pLogRecord->DataLength,
  215. pLogRecord->DataOffset, pLogRecord->EventCategory);
  216. //
  217. // Print out module name
  218. //
  219. pwString = (PWSTR)((LPBYTE) pLogRecord + sizeof(EVENTLOGRECORD));
  220. printf("ModuleName: %ws\n", pwString);
  221. //
  222. // Display ComputerName
  223. //
  224. pwString += wcslen(pwString) + 1;
  225. printf("ComputerName: %ws\n", pwString);
  226. //
  227. // Display strings
  228. //
  229. pwString = (PWSTR)((LPBYTE)pLogRecord + pLogRecord->StringOffset);
  230. printf("Strings: ");
  231. for (i=0; i<pLogRecord->NumStrings; i++) {
  232. printf(" %ws ", pwString);
  233. pwString += wcslen(pwString) + 1;
  234. }
  235. printf("\n");
  236. //
  237. // If verbose mode, display binary data (up to 256 bytes)
  238. //
  239. if (Verbose) {
  240. PULONG pData;
  241. PULONG pEnd;
  242. if (pLogRecord->DataLength < 80) {
  243. pEnd = (PULONG)((PBYTE) pLogRecord + pLogRecord->DataOffset +
  244. pLogRecord->DataLength);
  245. }
  246. else {
  247. pEnd = (PULONG)((PBYTE) pLogRecord + pLogRecord->DataOffset +
  248. 256);
  249. }
  250. printf("Data: \n\n");
  251. for (pData = (PULONG)((PBYTE) pLogRecord + pLogRecord->DataOffset);
  252. pData < pEnd; (PBYTE) pData += 32) {
  253. printf("\t%08x %08x %08x %08x\n", pData[0], pData[1], pData[2],
  254. pData[3]);
  255. }
  256. }
  257. // Get next record
  258. //
  259. Offset += pLogRecord->Length;
  260. // pLogRecord = (PEVENTLOGRECORD)((ULONG)Buffer + Offset);
  261. pLogRecord = (PEVENTLOGRECORD)((BYTE *)Buffer + Offset);
  262. Count++;
  263. }
  264. *NumRecords = Count;
  265. }
  266. NTSTATUS
  267. ReadFromLog ( HANDLE LogHandle,
  268. PVOID Buffer,
  269. PULONG pBytesRead,
  270. ULONG ReadFlag,
  271. ULONG Record
  272. )
  273. {
  274. NTSTATUS Status;
  275. ULONG MinBytesNeeded;
  276. Status = ElfReadEventLogW (
  277. LogHandle,
  278. ReadFlag,
  279. Record,
  280. Buffer,
  281. READ_BUFFER_SIZE,
  282. pBytesRead,
  283. &MinBytesNeeded
  284. );
  285. if (Status == STATUS_BUFFER_TOO_SMALL)
  286. printf("Buffer too small. Need %lu bytes min\n", MinBytesNeeded);
  287. return (Status);
  288. }
  289. NTSTATUS
  290. TestReadEventLog (
  291. ULONG Count,
  292. ULONG ReadFlag,
  293. ULONG Record
  294. )
  295. {
  296. NTSTATUS Status, IStatus;
  297. HANDLE LogHandle;
  298. UNICODE_STRING ModuleNameU;
  299. ANSI_STRING ModuleNameA;
  300. ULONG NumRecords, BytesReturned;
  301. PVOID Buffer;
  302. ULONG RecordOffset;
  303. ULONG NumberOfRecords;
  304. ULONG OldestRecord;
  305. printf("Testing ElfReadEventLog API to read %lu entries\n",Count);
  306. Buffer = malloc (READ_BUFFER_SIZE);
  307. //
  308. // Initialize the strings
  309. //
  310. NumRecords = Count;
  311. RtlInitAnsiString(&ModuleNameA, pModuleName);
  312. RtlAnsiStringToUnicodeString(&ModuleNameU, &ModuleNameA, TRUE);
  313. ModuleNameU.MaximumLength = ModuleNameU.Length + sizeof(WCHAR);
  314. //
  315. // Open the log handle
  316. //
  317. if (ReadingBackupFile) {
  318. printf("ElfOpenBackupEventLog - ");
  319. Status = ElfOpenBackupEventLogW (
  320. &ServerName,
  321. &ModuleNameU,
  322. &LogHandle
  323. );
  324. }
  325. else {
  326. printf("ElfOpenEventLog - ");
  327. Status = ElfOpenEventLogW (
  328. &ServerName,
  329. &ModuleNameU,
  330. &LogHandle
  331. );
  332. }
  333. if (!NT_SUCCESS(Status)) {
  334. printf("Error - 0x%lx\n", Status);
  335. } else {
  336. printf("SUCCESS\n");
  337. //
  338. // Get and print record information
  339. //
  340. Status = ElfNumberOfRecords(LogHandle, & NumberOfRecords);
  341. if (NT_SUCCESS(Status)) {
  342. Status = ElfOldestRecord(LogHandle, & OldestRecord);
  343. }
  344. if (!NT_SUCCESS(Status)) {
  345. printf("Query of record information failed with %X", Status);
  346. return(Status);
  347. }
  348. printf("\nThere are %d records in the file, %d is the oldest"
  349. " record number\n", NumberOfRecords, OldestRecord);
  350. RecordOffset = Record;
  351. while (Count && NT_SUCCESS(Status)) {
  352. printf("Read %u records\n", NumRecords);
  353. //
  354. // Read from the log
  355. //
  356. Status = ReadFromLog ( LogHandle,
  357. Buffer,
  358. &BytesReturned,
  359. ReadFlag,
  360. RecordOffset
  361. );
  362. if (NT_SUCCESS(Status)) {
  363. printf("Bytes read = 0x%lx\n", BytesReturned);
  364. NumRecords = Count;
  365. DisplayEventRecords(Buffer, BytesReturned, &NumRecords);
  366. Count -= NumRecords;
  367. }
  368. }
  369. printf("\n");
  370. if (!NT_SUCCESS(Status)) {
  371. if (Status == STATUS_END_OF_FILE) {
  372. printf("Tried to read more records than in log file\n");
  373. }
  374. else {
  375. printf ("Error - 0x%lx. Remaining count %lu\n", Status, Count);
  376. }
  377. } else {
  378. printf ("SUCCESS\n");
  379. }
  380. printf("Calling ElfCloseEventLog\n");
  381. IStatus = ElfCloseEventLog (LogHandle);
  382. }
  383. return (Status);
  384. }
  385. NTSTATUS
  386. TestReportEvent (
  387. ULONG Count
  388. )
  389. {
  390. NTSTATUS Status, IStatus;
  391. HANDLE LogHandle;
  392. UNICODE_STRING ModuleNameU;
  393. ANSI_STRING ModuleNameA;
  394. ULONG EventID = 99;
  395. printf("Testing ElfReportEvent API\n");
  396. //
  397. // Initialize the strings
  398. //
  399. RtlInitAnsiString(&ModuleNameA, pModuleName);
  400. RtlAnsiStringToUnicodeString(&ModuleNameU, &ModuleNameA, TRUE);
  401. ModuleNameU.MaximumLength = ModuleNameU.Length + sizeof(WCHAR);
  402. //
  403. // Open the log handle
  404. //
  405. printf("Calling ElfRegisterEventSource for WRITE %lu times - ", Count);
  406. Status = ElfRegisterEventSourceW (
  407. &ServerName,
  408. &ModuleNameU,
  409. &LogHandle
  410. );
  411. if (!NT_SUCCESS(Status)) {
  412. printf("Error - 0x%lx\n", Status);
  413. } else {
  414. printf("SUCCESS\n");
  415. while (Count && NT_SUCCESS(Status)) {
  416. printf("Record # %u \n", Count);
  417. //
  418. // Write an entry into the log
  419. //
  420. Data[0] = Count; // Make data "unique"
  421. EventID = (EventID + Count) % 100; // Vary the eventids
  422. Status = WriteLogEntry ( LogHandle, EventID );
  423. Count--;
  424. }
  425. printf("\n");
  426. if (!NT_SUCCESS(Status)) {
  427. if (Status == STATUS_LOG_FILE_FULL) {
  428. printf("Log Full\n");
  429. }
  430. else {
  431. printf ("Error - 0x%lx. Remaining count %lu\n", Status, Count);
  432. }
  433. } else {
  434. printf ("SUCCESS\n");
  435. }
  436. printf("Calling ElfDeregisterEventSource\n");
  437. IStatus = ElfDeregisterEventSource (LogHandle);
  438. }
  439. return (Status);
  440. }
  441. NTSTATUS
  442. TestElfClearLogFile(
  443. VOID
  444. )
  445. {
  446. NTSTATUS Status, IStatus;
  447. HANDLE LogHandle;
  448. UNICODE_STRING BackupU, ModuleNameU;
  449. ANSI_STRING ModuleNameA;
  450. OBJECT_ATTRIBUTES ObjectAttributes;
  451. HANDLE ClearHandle;
  452. FILE_DISPOSITION_INFORMATION DeleteInfo = {TRUE};
  453. IO_STATUS_BLOCK IoStatusBlock;
  454. BOOLEAN DontRetry = FALSE;
  455. printf("Testing ElfClearLogFile API\n");
  456. //
  457. // Initialize the strings
  458. //
  459. RtlInitAnsiString( &ModuleNameA, pModuleName);
  460. RtlAnsiStringToUnicodeString(&ModuleNameU, &ModuleNameA, TRUE);
  461. ModuleNameU.MaximumLength = ModuleNameU.Length + sizeof(WCHAR);
  462. //
  463. // Open the log handle
  464. //
  465. printf("Calling ElfOpenEventLog for CLEAR - ");
  466. Status = ElfOpenEventLogW (
  467. &ServerName,
  468. &ModuleNameU,
  469. &LogHandle
  470. );
  471. if (!NT_SUCCESS(Status)) {
  472. printf("Error - 0x%lx\n", Status);
  473. } else {
  474. printf("SUCCESS\n");
  475. //
  476. // Clear the log file and back it up to "view.evt"
  477. //
  478. RtlInitUnicodeString( &BackupU,
  479. L"\\SystemRoot\\System32\\Config\\view.evt" );
  480. BackupU.MaximumLength = BackupU.Length + sizeof(WCHAR);
  481. retry:
  482. printf("Calling ElfClearEventLogFile backing up to view.evt ");
  483. Status = ElfClearEventLogFileW (
  484. LogHandle,
  485. &BackupU
  486. );
  487. if (Status == STATUS_OBJECT_NAME_COLLISION) {
  488. if (DontRetry) {
  489. printf("Still can't backup to View.Evt\n");
  490. }
  491. else {
  492. printf("Failed.\nView.Evt already exists, deleting ...\n");
  493. //
  494. // Open the file with delete access
  495. //
  496. InitializeObjectAttributes(
  497. &ObjectAttributes,
  498. &BackupU,
  499. OBJ_CASE_INSENSITIVE,
  500. NULL,
  501. NULL
  502. );
  503. Status = NtOpenFile(&ClearHandle,
  504. GENERIC_READ | DELETE | SYNCHRONIZE,
  505. &ObjectAttributes,
  506. &IoStatusBlock,
  507. FILE_SHARE_DELETE,
  508. FILE_SYNCHRONOUS_IO_NONALERT
  509. );
  510. Status = NtSetInformationFile(
  511. ClearHandle,
  512. &IoStatusBlock,
  513. &DeleteInfo,
  514. sizeof(DeleteInfo),
  515. FileDispositionInformation
  516. );
  517. if (NT_SUCCESS (Status) ) {
  518. Status = NtClose (ClearHandle); // Discard status
  519. goto retry;
  520. }
  521. printf("Delete failed 0x%lx\n",Status);
  522. Status = NtClose (ClearHandle); // Discard status
  523. goto JustClear;
  524. }
  525. }
  526. if (!NT_SUCCESS(Status)) {
  527. printf ("Error - 0x%lx\n", Status);
  528. } else {
  529. printf ("SUCCESS\n");
  530. }
  531. JustClear:
  532. //
  533. // Now just clear the file without backing it up
  534. //
  535. printf("Calling ElfClearEventLogFile with no backup ");
  536. Status = ElfClearEventLogFileW (
  537. LogHandle,
  538. NULL
  539. );
  540. if (!NT_SUCCESS(Status)) {
  541. printf ("Error - 0x%lx\n", Status);
  542. } else {
  543. printf ("SUCCESS\n");
  544. }
  545. printf("Calling ElfCloseEventLog\n");
  546. IStatus = ElfCloseEventLog (LogHandle);
  547. }
  548. return(Status);
  549. }
  550. NTSTATUS
  551. TestElfBackupLogFile(
  552. VOID
  553. )
  554. {
  555. NTSTATUS Status, IStatus;
  556. HANDLE LogHandle;
  557. UNICODE_STRING BackupU, ModuleNameU;
  558. ANSI_STRING AnsiString;
  559. printf("Testing ElfBackupLogFile API\n");
  560. //
  561. // Initialize the strings
  562. //
  563. RtlInitAnsiString( &AnsiString, pModuleName);
  564. RtlAnsiStringToUnicodeString(&ModuleNameU, &AnsiString, TRUE);
  565. ModuleNameU.MaximumLength = ModuleNameU.Length + sizeof(WCHAR);
  566. //
  567. // Open the log handle
  568. //
  569. printf("Calling ElfOpenEventLog for BACKUP - ");
  570. Status = ElfOpenEventLogW (
  571. &ServerName,
  572. &ModuleNameU,
  573. &LogHandle
  574. );
  575. if (!NT_SUCCESS(Status)) {
  576. printf("Error - 0x%lx\n", Status);
  577. } else {
  578. printf("SUCCESS\n");
  579. //
  580. // Backup the log file
  581. //
  582. printf("Calling ElfBackupEventLogFile backing up to %s ",
  583. pBackupFileName);
  584. RtlInitAnsiString( &AnsiString, pBackupFileName);
  585. RtlAnsiStringToUnicodeString(&BackupU, &AnsiString, TRUE);
  586. BackupU.MaximumLength = BackupU.Length + sizeof(WCHAR);
  587. Status = ElfBackupEventLogFileW (
  588. LogHandle,
  589. &BackupU
  590. );
  591. if (!NT_SUCCESS(Status)) {
  592. printf ("Error - 0x%lx\n", Status);
  593. } else {
  594. printf ("SUCCESS\n");
  595. }
  596. printf("Calling ElfCloseEventLog - ");
  597. IStatus = ElfCloseEventLog (LogHandle);
  598. if (NT_SUCCESS(IStatus)) {
  599. printf("Success\n");
  600. }
  601. else {
  602. printf("Failed with code %X\n", IStatus);
  603. }
  604. }
  605. return(Status);
  606. }
  607. #define DRIVER_NAME L"FLOPPY"
  608. #define DEVICE_NAME L"A:"
  609. #define STRING L"Test String"
  610. // These include the NULL terminator, but is length in chars, not bytes
  611. #define DRIVER_NAME_LENGTH 7
  612. #define DEVICE_NAME_LENGTH 3
  613. #define STRING_LENGTH 12
  614. #define NUMBER_OF_DATA_BYTES 8
  615. VOID
  616. TestLPCWrite(
  617. DWORD NumberOfRecords,
  618. DWORD MillisecondsToDelay
  619. )
  620. {
  621. HANDLE PortHandle;
  622. UNICODE_STRING PortName;
  623. NTSTATUS Status;
  624. SECURITY_QUALITY_OF_SERVICE Qos;
  625. PIO_ERROR_LOG_MESSAGE pIoErrorLogMessage;
  626. DWORD i;
  627. LPWSTR pDestinationString;
  628. PPORT_MESSAGE RequestMessage;
  629. PORT_MESSAGE ReplyMessage;
  630. WORD DataLength;
  631. WORD TotalLength;
  632. INT YorN;
  633. CHAR NumberString[8];
  634. ULONG MessageId = 1;
  635. DWORD BadType = 0;
  636. //
  637. // Warn the user about how this test works
  638. //
  639. printf("\nThis test doesn't end! It will write a number of\n"
  640. "records, then prompt you to write more. This is \n"
  641. "required since it is simulating the system thread\n"
  642. "which never shuts down it's connection\n\n"
  643. "Do you wish to continue with this test (y or n)? ");
  644. YorN = getc(stdin);
  645. if (YorN == 'n' || YorN == 'N') {
  646. return;
  647. }
  648. //
  649. // Initialize the SecurityQualityofService structure
  650. //
  651. Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  652. Qos.ImpersonationLevel = SecurityImpersonation;
  653. Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  654. Qos.EffectiveOnly = TRUE;
  655. //
  656. // Connect to the LPC Port
  657. //
  658. RtlInitUnicodeString( &PortName, L"\\ErrorLogPort" );
  659. Status = NtConnectPort(& PortHandle,
  660. & PortName,
  661. & Qos,
  662. NULL,
  663. NULL,
  664. NULL,
  665. NULL,
  666. NULL
  667. );
  668. if (!NT_SUCCESS(Status)) {
  669. printf("Connect to the LPC port failed with RC %X\n", Status);
  670. return;
  671. }
  672. //
  673. // Allocate the memory for the Message to send to the LPC port. It
  674. // will contain a PORT_MESSAGE followed by an IO_ERROR_LOG_MESSAGE
  675. // followed by Drivername and Devicename UNICODE strings
  676. //
  677. DataLength = PORT_MAXIMUM_MESSAGE_LENGTH -
  678. (sizeof(IO_ERROR_LOG_MESSAGE)
  679. + DRIVER_NAME_LENGTH * sizeof(WCHAR)
  680. + DEVICE_NAME_LENGTH * sizeof(WCHAR)
  681. + STRING_LENGTH * sizeof(WCHAR));
  682. TotalLength = PORT_MAXIMUM_MESSAGE_LENGTH + (WORD) sizeof(PORT_MESSAGE);
  683. RequestMessage = (PPORT_MESSAGE) malloc(TotalLength);
  684. if (RequestMessage == NULL) {
  685. printf("Couldn't alloc %d bytes of memory for message\n", TotalLength);
  686. NtClose(PortHandle);
  687. return;
  688. }
  689. pIoErrorLogMessage = (PIO_ERROR_LOG_MESSAGE) ((LPBYTE) RequestMessage +
  690. sizeof(PORT_MESSAGE));
  691. //
  692. // Initialize the PORT_MESSAGE
  693. //
  694. RequestMessage->u1.s1.DataLength = PORT_MAXIMUM_MESSAGE_LENGTH;
  695. RequestMessage->u1.s1.TotalLength = TotalLength;
  696. RequestMessage->u2.s2.Type = 0;
  697. RequestMessage->u2.ZeroInit = 0;
  698. RequestMessage->ClientId.UniqueProcess = GetCurrentProcess();
  699. RequestMessage->ClientId.UniqueThread = GetCurrentThread();
  700. RequestMessage->MessageId = 0x1234;
  701. //
  702. // Initialize the IO_ERROR_LOG_MESSAGE
  703. //
  704. pIoErrorLogMessage->Type = IO_TYPE_ERROR_MESSAGE;
  705. pIoErrorLogMessage->Size = PORT_MAXIMUM_MESSAGE_LENGTH;
  706. pIoErrorLogMessage->DriverNameLength = DRIVER_NAME_LENGTH * sizeof(WCHAR);
  707. NtQuerySystemTime((PTIME) &pIoErrorLogMessage->TimeStamp);
  708. pIoErrorLogMessage->DriverNameOffset = sizeof(IO_ERROR_LOG_MESSAGE) +
  709. DataLength - sizeof(DWORD);
  710. pIoErrorLogMessage->EntryData.MajorFunctionCode = 1;
  711. pIoErrorLogMessage->EntryData.RetryCount = 5;
  712. pIoErrorLogMessage->EntryData.DumpDataSize = DataLength;
  713. pIoErrorLogMessage->EntryData.NumberOfStrings = 2;
  714. pIoErrorLogMessage->EntryData.StringOffset = sizeof(IO_ERROR_LOG_MESSAGE)
  715. - sizeof(DWORD) + DataLength +
  716. DRIVER_NAME_LENGTH * sizeof(WCHAR);
  717. pIoErrorLogMessage->EntryData.EventCategory = 0;
  718. pIoErrorLogMessage->EntryData.ErrorCode = 0xC0020008;
  719. pIoErrorLogMessage->EntryData.UniqueErrorValue = 0x20008;
  720. pIoErrorLogMessage->EntryData.FinalStatus = 0x1111;
  721. pIoErrorLogMessage->EntryData.SequenceNumber = 1;
  722. pIoErrorLogMessage->EntryData.IoControlCode = 0xFF;
  723. pIoErrorLogMessage->EntryData.DeviceOffset =
  724. RtlConvertUlongToLargeInteger(1);
  725. for (i = 0; i < DataLength ; i++ ) {
  726. pIoErrorLogMessage->EntryData.DumpData[i] = i;
  727. }
  728. //
  729. // Copy the strings
  730. //
  731. pDestinationString = (LPWSTR) ((LPBYTE) pIoErrorLogMessage
  732. + sizeof(IO_ERROR_LOG_MESSAGE)
  733. - sizeof(DWORD) + pIoErrorLogMessage->EntryData.DumpDataSize);
  734. wcscpy(pDestinationString, DRIVER_NAME);
  735. pDestinationString += DRIVER_NAME_LENGTH;
  736. wcscpy(pDestinationString, DEVICE_NAME);
  737. pDestinationString += DEVICE_NAME_LENGTH;
  738. wcscpy(pDestinationString, STRING);
  739. //
  740. // Write the packet as many times as requested, with delay, then ask
  741. // if they want to write more
  742. //
  743. while (NumberOfRecords) {
  744. printf("\n\nWriting %d records\n", NumberOfRecords);
  745. while(NumberOfRecords--) {
  746. printf(".");
  747. //
  748. // Put in a unique message number
  749. //
  750. RequestMessage->MessageId = MessageId++;
  751. //
  752. // If they want invalid records, give them invalid records
  753. //
  754. if (WriteInvalidRecords) {
  755. switch (BadType++) {
  756. case 0:
  757. pIoErrorLogMessage->EntryData.DumpDataSize++;
  758. break;
  759. case 1:
  760. pIoErrorLogMessage->EntryData.NumberOfStrings++;
  761. break;
  762. case 2:
  763. pIoErrorLogMessage->EntryData.StringOffset++;
  764. break;
  765. default:
  766. BadType = 0;
  767. }
  768. }
  769. Status = NtRequestWaitReplyPort(PortHandle,
  770. RequestMessage,
  771. & ReplyMessage);
  772. if (!NT_SUCCESS(Status)) {
  773. printf("Request to LPC port failed with RC %X\n", Status);
  774. break;
  775. }
  776. //
  777. // Delay a little bit, if requested
  778. //
  779. if (MillisecondsToDelay) {
  780. Sleep(MillisecondsToDelay);
  781. }
  782. }
  783. printf("\nEnter the number of records to write ");
  784. while (!gets(NumberString) || !(NumberOfRecords = atoi(NumberString))) {
  785. printf("Enter the number of records to write ");
  786. }
  787. }
  788. //
  789. // Clean up and exit
  790. //
  791. Status = NtClose(PortHandle);
  792. if (!NT_SUCCESS(Status)) {
  793. printf("Close of Port failed with RC %X\n", Status);
  794. }
  795. free(RequestMessage);
  796. return;
  797. }
  798. VOID
  799. TestChangeNotify(
  800. VOID
  801. )
  802. {
  803. HANDLE Event;
  804. UNICODE_STRING ModuleNameU;
  805. ANSI_STRING ModuleNameA;
  806. NTSTATUS Status;
  807. HANDLE LogHandle;
  808. OBJECT_ATTRIBUTES obja;
  809. ULONG NumRecords;
  810. ULONG BytesRead;
  811. ULONG MinBytesNeeded;
  812. PVOID Buffer;
  813. ULONG OldestRecord;
  814. ULONG NumberOfRecords;
  815. RtlInitAnsiString(&ModuleNameA, pModuleName);
  816. RtlAnsiStringToUnicodeString(&ModuleNameU, &ModuleNameA, TRUE);
  817. ModuleNameU.MaximumLength = ModuleNameU.Length + sizeof(WCHAR);
  818. Buffer = malloc (READ_BUFFER_SIZE);
  819. ASSERT(Buffer);
  820. //
  821. // Open the log handle
  822. //
  823. printf("ElfOpenEventLog - ");
  824. Status = ElfOpenEventLogW (
  825. &ServerName,
  826. &ModuleNameU,
  827. &LogHandle
  828. );
  829. if (!NT_SUCCESS(Status)) {
  830. printf("Error - 0x%lx\n", Status);
  831. return;
  832. }
  833. printf("SUCCESS\n");
  834. //
  835. // Create the Event
  836. //
  837. InitializeObjectAttributes( &obja, NULL, 0, NULL, NULL);
  838. Status = NtCreateEvent(
  839. &Event,
  840. SYNCHRONIZE | EVENT_QUERY_STATE | EVENT_MODIFY_STATE,
  841. &obja,
  842. SynchronizationEvent,
  843. FALSE
  844. );
  845. ASSERT(NT_SUCCESS(Status));
  846. //
  847. // Get the read pointer to the end of the log
  848. //
  849. Status = ElfOldestRecord(LogHandle, & OldestRecord);
  850. ASSERT(NT_SUCCESS(Status));
  851. Status = ElfNumberOfRecords(LogHandle, & NumberOfRecords);
  852. ASSERT(NT_SUCCESS(Status));
  853. OldestRecord += NumberOfRecords - 1;
  854. Status = ElfReadEventLogW (
  855. LogHandle,
  856. EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ,
  857. OldestRecord,
  858. Buffer,
  859. READ_BUFFER_SIZE,
  860. &BytesRead,
  861. &MinBytesNeeded
  862. );
  863. //
  864. // This one should hit end of file
  865. //
  866. Status = ElfReadEventLogW (
  867. LogHandle,
  868. EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
  869. 0,
  870. Buffer,
  871. READ_BUFFER_SIZE,
  872. &BytesRead,
  873. &MinBytesNeeded
  874. );
  875. if (Status != STATUS_END_OF_FILE) {
  876. printf("Hmmm, should have hit EOF (unless there are writes going"
  877. " on elsewhere- %X\n", Status);
  878. }
  879. //
  880. // Call ElfChangeNotify
  881. //
  882. Status = ElfChangeNotify(LogHandle, Event);
  883. ASSERT(NT_SUCCESS(Status));
  884. //
  885. // Now loop waiting for the event to get toggled
  886. //
  887. while (1) {
  888. Status = NtWaitForSingleObject(Event, FALSE, 0);
  889. printf("The change notify event just got kicked\n");
  890. //
  891. // Now read the new records
  892. //
  893. while(1) {
  894. Status = ElfReadEventLogW (
  895. LogHandle,
  896. EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
  897. 0,
  898. Buffer,
  899. READ_BUFFER_SIZE,
  900. &BytesRead,
  901. &MinBytesNeeded
  902. );
  903. if (Status == STATUS_END_OF_FILE) {
  904. break;
  905. }
  906. NumRecords = 0xffff; // should be plenty
  907. DisplayEventRecords (Buffer, BytesRead, &NumRecords);
  908. }
  909. }
  910. }
  911. VOID
  912. TestLogFull(
  913. VOID
  914. )
  915. {
  916. HANDLE hLogFile;
  917. BOOL fIsFull;
  918. BOOLEAN fPrevious = FALSE;
  919. DWORD i;
  920. DWORD dwBytesNeeded;
  921. BOOL fIsSecLog;
  922. LPWSTR szLogNames[] = { L"Application", L"Security", L"System" };
  923. for (i = 0; i < sizeof(szLogNames) / sizeof(LPWSTR); i++) {
  924. fIsSecLog = (wcscmp(szLogNames[i], L"Security") == 0);
  925. if (fIsSecLog) {
  926. if (!NT_SUCCESS(RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE,
  927. TRUE,
  928. FALSE,
  929. &fPrevious))) {
  930. printf("RtlAdjustPrivilege FAILED %d\n",
  931. RtlNtStatusToDosError(GetLastError()));
  932. }
  933. }
  934. hLogFile = OpenEventLogW(NULL, szLogNames[i]);
  935. if (hLogFile != NULL) {
  936. if (GetEventLogInformation(hLogFile,
  937. 0, // Log full infolevel
  938. (LPBYTE)&fIsFull,
  939. sizeof(fIsFull),
  940. &dwBytesNeeded)) {
  941. printf("The %ws Log is%sfull\n",
  942. szLogNames[i],
  943. fIsFull ? " " : " not ");
  944. }
  945. else {
  946. printf("GetEventLogInformation FAILED %d for the %ws Log\n",
  947. GetLastError(),
  948. szLogNames[i]);
  949. }
  950. }
  951. else {
  952. printf("OpenEventLog FAILED %d for the %ws Log\n",
  953. GetLastError(),
  954. szLogNames[i]);
  955. }
  956. if (fIsSecLog) {
  957. RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, fPrevious, FALSE, &fPrevious);
  958. }
  959. }
  960. }
  961. VOID
  962. __cdecl
  963. main (
  964. IN SHORT argc,
  965. IN PSZ argv[]
  966. )
  967. {
  968. Initialize(); // Init any data
  969. //
  970. // Parse the command line
  971. //
  972. ParseParms(argc, argv);
  973. switch (Operation) {
  974. case Clear:
  975. TestElfClearLogFile();
  976. break;
  977. case Backup:
  978. TestElfBackupLogFile();
  979. break;
  980. case Read:
  981. if (ReadFlags & EVENTLOG_SEEK_READ) {
  982. TestReadEventLog(1, ReadFlags, NumberofRecords) ;
  983. }
  984. else {
  985. TestReadEventLog(NumberofRecords, ReadFlags, 0) ;
  986. }
  987. break;
  988. case Write:
  989. TestReportEvent (NumberofRecords);
  990. break;
  991. case LPC:
  992. TestLPCWrite(NumberofRecords, DelayInMilliseconds);
  993. break;
  994. case Notify:
  995. TestChangeNotify();
  996. break;
  997. case TestFull:
  998. TestLogFull();
  999. break;
  1000. default:
  1001. printf("Invalid switch from ParseParms %d\n", Operation);
  1002. }
  1003. }
  1004. VOID
  1005. ParseParms(
  1006. ULONG argc,
  1007. PCHAR *argv
  1008. )
  1009. {
  1010. ULONG i;
  1011. PCHAR pch;
  1012. for (i = 1; i < argc; i++) { /* for each argument */
  1013. if (*(pch = argv[i]) == '-') {
  1014. while (*++pch) {
  1015. switch (*pch) {
  1016. case 'b':
  1017. SET_OPERATION(Backup)
  1018. //
  1019. // Get the file name for backup
  1020. //
  1021. if (i+1 < argc) {
  1022. pBackupFileName = argv[++i];
  1023. }
  1024. else {
  1025. Usage();
  1026. }
  1027. break;
  1028. case 'c':
  1029. SET_OPERATION(Clear)
  1030. break;
  1031. case 'f':
  1032. if (i+1 < argc) {
  1033. pModuleName = argv[++i];
  1034. ReadingBackupFile = TRUE;
  1035. }
  1036. else {
  1037. Usage();
  1038. }
  1039. break;
  1040. case '?':
  1041. case 'h':
  1042. case 'H':
  1043. Usage();
  1044. break;
  1045. case 'i':
  1046. InvalidUser = TRUE;
  1047. break;
  1048. case 'l':
  1049. SET_OPERATION(LPC);
  1050. //
  1051. // See if they want invalid records
  1052. //
  1053. if (*++pch == 'i') {
  1054. WriteInvalidRecords = TRUE;
  1055. }
  1056. //
  1057. // See if they specified a number of records
  1058. //
  1059. if (i + 1 < argc && argv[i+1][0] != '-') {
  1060. NumberofRecords = atoi(argv[++i]);
  1061. if (NumberofRecords == 0) {
  1062. Usage();
  1063. }
  1064. }
  1065. break;
  1066. case 'm':
  1067. if (i+1 < argc) {
  1068. pModuleName = argv[++i];
  1069. ReadingModule = TRUE;
  1070. }
  1071. else {
  1072. Usage();
  1073. }
  1074. break;
  1075. case 'n':
  1076. SET_OPERATION(Notify)
  1077. break;
  1078. case 'r':
  1079. SET_OPERATION(Read)
  1080. //
  1081. // Different Read options
  1082. //
  1083. if (*++pch == 's') {
  1084. ReadFlags |= EVENTLOG_SEQUENTIAL_READ;
  1085. }
  1086. else if (*pch == 'r') {
  1087. ReadFlags |= EVENTLOG_SEEK_READ;
  1088. }
  1089. else {
  1090. Usage();
  1091. }
  1092. if (*++pch == 'f') {
  1093. ReadFlags |= EVENTLOG_FORWARDS_READ;
  1094. }
  1095. else if (*pch == 'b') {
  1096. ReadFlags |= EVENTLOG_BACKWARDS_READ;
  1097. }
  1098. else {
  1099. Usage();
  1100. }
  1101. //
  1102. // See if they specified a number of records
  1103. //
  1104. if (i + 1 < argc && argv[i+1][0] != '-') {
  1105. NumberofRecords = atoi(argv[++i]);
  1106. if (NumberofRecords == 0) {
  1107. Usage();
  1108. }
  1109. }
  1110. break;
  1111. case 's':
  1112. if (i+1 >= argc) {
  1113. printf("Must supply a server name with -s\n");
  1114. Usage();
  1115. }
  1116. RtlInitAnsiString(&AnsiString, argv[++i]);
  1117. RtlAnsiStringToUnicodeString(&ServerName, &AnsiString,
  1118. TRUE);
  1119. break;
  1120. case 't':
  1121. DelayInMilliseconds = atoi(argv[++i]);
  1122. break;
  1123. case 'v':
  1124. Verbose = TRUE;
  1125. break;
  1126. case 'w':
  1127. SET_OPERATION(Write)
  1128. //
  1129. // See if they specified a number of records
  1130. //
  1131. if (i + 1 < argc && argv[i+1][0] != '-') {
  1132. NumberofRecords = atoi(argv[++i]);
  1133. if (NumberofRecords == 0) {
  1134. Usage();
  1135. }
  1136. }
  1137. break;
  1138. case 'z':
  1139. SET_OPERATION(TestFull)
  1140. break;
  1141. default: /* Invalid options */
  1142. printf("Invalid option %c\n\n", *pch);
  1143. Usage();
  1144. break;
  1145. }
  1146. }
  1147. }
  1148. //
  1149. // There aren't any non switch parms
  1150. //
  1151. else {
  1152. Usage();
  1153. }
  1154. }
  1155. //
  1156. // Verify parms are correct
  1157. //
  1158. if ( Operation == Invalid) {
  1159. printf( "Must specify an operation\n");
  1160. Usage( );
  1161. }
  1162. if (ReadingBackupFile && ReadingModule) {
  1163. printf("-m and -f are mutually exclusive\n");
  1164. Usage();
  1165. }
  1166. if (ReadingBackupFile && Operation == Write) {
  1167. printf("You cannot write to a backup log file\n");
  1168. Usage();
  1169. }
  1170. if (DelayInMilliseconds && Operation != LPC) {
  1171. printf("\n\n-t switch is only used with -l\n\n");
  1172. }
  1173. }