diff options
Diffstat (limited to 'private/eventlog/test/test.c')
-rw-r--r-- | private/eventlog/test/test.c | 1400 |
1 files changed, 1400 insertions, 0 deletions
diff --git a/private/eventlog/test/test.c b/private/eventlog/test/test.c new file mode 100644 index 000000000..bb996bf8d --- /dev/null +++ b/private/eventlog/test/test.c @@ -0,0 +1,1400 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + TEST.C + +Abstract: + + Test program for the eventlog service. This program calls the Elf + APIs to test out the operation of the service. + +Author: + + Rajen Shah (rajens) 05-Aug-1991 + +Revision History: + + +--*/ +/*----------------------*/ +/* INCLUDES */ +/*----------------------*/ +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <stdio.h> // printf +#include <string.h> // stricmp +#include <stdlib.h> +#include <process.h> // exit +#include <elfcommn.h> +#include <windows.h> +#include <ntiolog.h> +#include <malloc.h> + +#define READ_BUFFER_SIZE 1024*2 // Use 2K buffer + +#define SIZE_DATA_ARRAY 22 + +#define SET_OPERATION(x) \ + if (Operation != Invalid) { \ + printf("Only one operation at a time\n"); \ + Usage(); \ + } \ + Operation = x; + +// +// Global buffer used to emulate "binary data" when writing an event +// record. +// +ULONG Data[SIZE_DATA_ARRAY]; +enum _OPERATION_TYPE { + Invalid, + Clear, + Backup, + Read, + Write, + Notify, + LPC +} Operation = Invalid; +ULONG ReadFlags; +BOOL Verbose = FALSE; +ULONG NumberofRecords = 1; +ULONG DelayInMilliseconds = 0; +CHAR DefaultModuleName[] = "TESTAPP"; +PCHAR pModuleName = DefaultModuleName; +PCHAR pBackupFileName; +ANSI_STRING AnsiString; +UNICODE_STRING ServerName; +BOOL ReadingBackupFile = FALSE; +BOOL ReadingModule = FALSE; +BOOL WriteInvalidRecords = FALSE; +BOOL InvalidUser = FALSE; + +// Function prototypes + +VOID ParseParms(ULONG argc, PCHAR *argv); + +VOID +Initialize ( + VOID + ) +{ + ULONG i; + + // Initialize the values in the data buffer. + // + for (i=0; i< SIZE_DATA_ARRAY; i++) + Data[i] = i; + +} + + +VOID +Usage ( + VOID + ) +{ + printf( "usage: \n" ); + printf( "-c Clears the specified log\n"); + printf( "-b <filename> Backs up the log to file <filename>\n"); + printf( "-f <filename> Filename of backup log to use for read\n"); + printf( "-i Generate invalid SID\n"); + printf( "-l[i] nn Writes nn records thru LPC port [i ==> bad records]\n"); + printf( "-m <modulename> Module name to use for read/clear\n"); + printf( "-n Test out change notify\n"); + printf( "-rsb Reads nn event log records sequentially backwards\n"); + printf( "-rsf nn Reads nn event log records sequentially forwards\n"); + printf( "-rrb <record> Reads event log from <record> backwards\n"); + printf( "-rrf <record> Reads event log from <record> forwards\n"); + printf( "-s <servername> Name of server to remote calls to\n"); + printf( "-t nn Number of milliseconds to delay between read/write" + " (default 0)\n\tOnly used with -l switch\n"); + printf( "-w <count> Writes <count> records\n"); + exit(0); + +} // Usage + + +NTSTATUS +WriteLogEntry ( + HANDLE LogHandle, + ULONG EventID + ) +{ +#define NUM_STRINGS 2 +#define SIZE_TOKEN_BUFFER 512 + + NTSTATUS Status; + USHORT EventType, i; + ULONG DataSize; + PSID pUserSid; + PWSTR Strings[NUM_STRINGS] = {L"StringOne", L"StringTwo"}; + PUNICODE_STRING UStrings[NUM_STRINGS]; + HANDLE hProcess; + HANDLE hToken; + PTOKEN_USER pTokenUser; + DWORD SizeRequired; + + EventType = EVENTLOG_INFORMATION_TYPE; + DataSize = sizeof(ULONG) * SIZE_DATA_ARRAY; + + // + // Get the SID of the current user (process) + // + + pTokenUser = malloc(SIZE_TOKEN_BUFFER); + + if (!InvalidUser) { + hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, + GetCurrentProcessId()); + if (!hProcess) { + printf("Couldn't open the process, rc = %d\n", GetLastError()); + return(STATUS_UNSUCCESSFUL); + } + + if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) { + printf("Couldn't open the token, rc = %d\n", GetLastError()); + CloseHandle(hProcess); + return(STATUS_UNSUCCESSFUL); + } + if (!pTokenUser) { + printf("Couldn't allocate buffer for TokenUser\n"); + CloseHandle(hToken); + CloseHandle(hProcess); + return(STATUS_UNSUCCESSFUL); + } + + if (!GetTokenInformation(hToken, TokenUser, pTokenUser, SIZE_TOKEN_BUFFER, + &SizeRequired)) { + printf("Couldn't get TokenUser information, rc = %d\n", + GetLastError()); + CloseHandle(hToken); + CloseHandle(hProcess); + free(pTokenUser); + return(STATUS_UNSUCCESSFUL); + } + + CloseHandle(hToken); + CloseHandle(hProcess); + } + else { + memset(pTokenUser, 0xFADE, SIZE_TOKEN_BUFFER); + pTokenUser->User.Sid = (PSID)pUserSid; + } + + pUserSid = pTokenUser->User.Sid; + + for (i=0; i< SIZE_DATA_ARRAY; i++) + Data[i] += i; + + // Allocate space for the unicode strings in the array, and + // copy over the strings from Strings[] to that array. + // + for (i=0; i<NUM_STRINGS; i++) { + + UStrings[i] = malloc(sizeof(UNICODE_STRING)); + RtlInitUnicodeString (UStrings[i], Strings[i]); + // force this to be non-null terminated + UStrings[i]->MaximumLength = UStrings[i]->Length; + } + Status = ElfReportEventW ( + LogHandle, + EventType, + 0, // category + EventID, + pUserSid, + NUM_STRINGS, + DataSize, + UStrings, + (PVOID)Data, + 0, // Flags - paired event support + NULL, // RecordNumber | not in product 1 + NULL // TimeWritten - + ); + + for (i=0; i<NUM_STRINGS; i++) + free(UStrings[i]); + + free(pTokenUser); + return (Status); +} + + +VOID +DisplayEventRecords( PVOID Buffer, + ULONG BufSize, + PULONG NumRecords) + +{ + PEVENTLOGRECORD pLogRecord; + LPWSTR pwString; + ULONG Count = 0; + ULONG Offset = 0; + ULONG i; + + pLogRecord = (PEVENTLOGRECORD) Buffer; + + while (Offset < BufSize && Count < *NumRecords) { + + printf("\nRecord # %lu\n", pLogRecord->RecordNumber); + + printf("Length: 0x%lx TimeGenerated: 0x%lx EventID: 0x%lx EventType: 0x%x\n", + pLogRecord->Length, pLogRecord->TimeGenerated, pLogRecord->EventID, + pLogRecord->EventType); + + printf("NumStrings: 0x%x StringOffset: 0x%lx UserSidLength: 0x%lx TimeWritten: 0x%lx\n", + pLogRecord->NumStrings, pLogRecord->StringOffset, + pLogRecord->UserSidLength, pLogRecord->TimeWritten); + + printf("UserSidOffset: 0x%lx DataLength: 0x%lx DataOffset: 0x%lx Category: 0x%lx\n", + pLogRecord->UserSidOffset, pLogRecord->DataLength, + pLogRecord->DataOffset, pLogRecord->EventCategory); + + // + // Print out module name + // + + pwString = (PWSTR)((LPBYTE) pLogRecord + sizeof(EVENTLOGRECORD)); + printf("ModuleName: %ws\n", pwString); + + // + // Display ComputerName + // + pwString += wcslen(pwString) + 1; + printf("ComputerName: %ws\n", pwString); + + // + // Display strings + // + + pwString = (PWSTR)((LPBYTE)pLogRecord + pLogRecord->StringOffset); + + printf("Strings: "); + for (i=0; i<pLogRecord->NumStrings; i++) { + + printf(" %ws ", pwString); + pwString += wcslen(pwString) + 1; + } + + printf("\n"); + + // + // If verbose mode, display binary data (up to 256 bytes) + // BUGBUG - this code will hit an alignment fault on mips. + // + + if (Verbose) { + PULONG pData; + PULONG pEnd; + + if (pLogRecord->DataLength < 80) { + pEnd = (PULONG)((PBYTE) pLogRecord + pLogRecord->DataOffset + + pLogRecord->DataLength); + } + else { + pEnd = (PULONG)((PBYTE) pLogRecord + pLogRecord->DataOffset + + 256); + } + + printf("Data: \n\n"); + for (pData = (PULONG)((PBYTE) pLogRecord + pLogRecord->DataOffset); + pData < pEnd; (PBYTE) pData += 32) { + + printf("\t%08x %08x %08x %08x\n", pData[0], pData[1], pData[2], + pData[3]); + } + } + + // Get next record + // + Offset += pLogRecord->Length; + + pLogRecord = (PEVENTLOGRECORD)((ULONG)Buffer + Offset); + + Count++; + + } + + *NumRecords = Count; + +} + + +NTSTATUS +ReadFromLog ( HANDLE LogHandle, + PVOID Buffer, + PULONG pBytesRead, + ULONG ReadFlag, + ULONG Record + ) +{ + NTSTATUS Status; + ULONG MinBytesNeeded; + + Status = ElfReadEventLogW ( + LogHandle, + ReadFlag, + Record, + Buffer, + READ_BUFFER_SIZE, + pBytesRead, + &MinBytesNeeded + ); + + + if (Status == STATUS_BUFFER_TOO_SMALL) + printf("Buffer too small. Need %lu bytes min\n", MinBytesNeeded); + + return (Status); +} + + +NTSTATUS +TestReadEventLog ( + ULONG Count, + ULONG ReadFlag, + ULONG Record + ) + +{ + NTSTATUS Status, IStatus; + + HANDLE LogHandle; + UNICODE_STRING ModuleNameU; + ANSI_STRING ModuleNameA; + ULONG NumRecords, BytesReturned; + PVOID Buffer; + ULONG RecordOffset; + ULONG NumberOfRecords; + ULONG OldestRecord; + + printf("Testing ElfReadEventLog API to read %lu entries\n",Count); + + Buffer = malloc (READ_BUFFER_SIZE); + + // + // Initialize the strings + // + NumRecords = Count; + RtlInitAnsiString(&ModuleNameA, pModuleName); + RtlAnsiStringToUnicodeString(&ModuleNameU, &ModuleNameA, TRUE); + ModuleNameU.MaximumLength = ModuleNameU.Length; + + // + // Open the log handle + // + + if (ReadingBackupFile) { + printf("ElfOpenBackupEventLog - "); + Status = ElfOpenBackupEventLogW ( + &ServerName, + &ModuleNameU, + &LogHandle + ); + } + else { + printf("ElfOpenEventLog - "); + Status = ElfOpenEventLogW ( + &ServerName, + &ModuleNameU, + &LogHandle + ); + } + + if (!NT_SUCCESS(Status)) { + printf("Error - 0x%lx\n", Status); + + } else { + printf("SUCCESS\n"); + + // + // Get and print record information + // + + Status = ElfNumberOfRecords(LogHandle, & NumberOfRecords); + if (NT_SUCCESS(Status)) { + Status = ElfOldestRecord(LogHandle, & OldestRecord); + } + + if (!NT_SUCCESS(Status)) { + printf("Query of record information failed with %X", Status); + return(Status); + } + + printf("\nThere are %d records in the file, %d is the oldest" + " record number\n", NumberOfRecords, OldestRecord); + + RecordOffset = Record; + + while (Count && NT_SUCCESS(Status)) { + + printf("Read %u records\n", NumRecords); + // + // Read from the log + // + Status = ReadFromLog ( LogHandle, + Buffer, + &BytesReturned, + ReadFlag, + RecordOffset + ); + if (NT_SUCCESS(Status)) { + + printf("Bytes read = 0x%lx\n", BytesReturned); + NumRecords = Count; + DisplayEventRecords(Buffer, BytesReturned, &NumRecords); + Count -= NumRecords; + } + + } + printf("\n"); + + if (!NT_SUCCESS(Status)) { + if (Status == STATUS_END_OF_FILE) { + printf("Tried to read more records than in log file\n"); + } + else { + printf ("Error - 0x%lx. Remaining count %lu\n", Status, Count); + } + } else { + printf ("SUCCESS\n"); + } + + printf("Calling ElfCloseEventLog\n"); + IStatus = ElfCloseEventLog (LogHandle); + } + + return (Status); +} + + +NTSTATUS +TestReportEvent ( + ULONG Count + ) + +{ + NTSTATUS Status, IStatus; + HANDLE LogHandle; + UNICODE_STRING ModuleNameU; + ANSI_STRING ModuleNameA; + ULONG EventID = 99; + + printf("Testing ElfReportEvent API\n"); + + // + // Initialize the strings + // + + RtlInitAnsiString(&ModuleNameA, pModuleName); + RtlAnsiStringToUnicodeString(&ModuleNameU, &ModuleNameA, TRUE); + ModuleNameU.MaximumLength = ModuleNameU.Length; + + // + // Open the log handle + // + printf("Calling ElfRegisterEventSource for WRITE %lu times - ", Count); + Status = ElfRegisterEventSourceW ( + &ServerName, + &ModuleNameU, + &LogHandle + ); + + if (!NT_SUCCESS(Status)) { + printf("Error - 0x%lx\n", Status); + + } else { + printf("SUCCESS\n"); + + while (Count && NT_SUCCESS(Status)) { + + printf("Record # %u \n", Count); + + // + // Write an entry into the log + // + Data[0] = Count; // Make data "unique" + EventID = (EventID + Count) % 100; // Vary the eventids + Status = WriteLogEntry ( LogHandle, EventID ); + Count--; + } + printf("\n"); + + if (!NT_SUCCESS(Status)) { + if (Status == STATUS_LOG_FILE_FULL) { + printf("Log Full\n"); + } + else { + printf ("Error - 0x%lx. Remaining count %lu\n", Status, Count); + } + } else { + printf ("SUCCESS\n"); + } + + printf("Calling ElfDeregisterEventSource\n"); + IStatus = ElfDeregisterEventSource (LogHandle); + } + + return (Status); +} + + +NTSTATUS +TestElfClearLogFile( + VOID + ) + +{ + NTSTATUS Status, IStatus; + HANDLE LogHandle; + UNICODE_STRING BackupU, ModuleNameU; + ANSI_STRING ModuleNameA; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE ClearHandle; + FILE_DISPOSITION_INFORMATION DeleteInfo = {TRUE}; + IO_STATUS_BLOCK IoStatusBlock; + BOOLEAN DontRetry = FALSE; + + printf("Testing ElfClearLogFile API\n"); + // + // Initialize the strings + // + RtlInitAnsiString( &ModuleNameA, pModuleName); + RtlAnsiStringToUnicodeString(&ModuleNameU, &ModuleNameA, TRUE); + ModuleNameU.MaximumLength = ModuleNameU.Length ; + + // + // Open the log handle + // + printf("Calling ElfOpenEventLog for CLEAR - "); + Status = ElfOpenEventLogW ( + &ServerName, + &ModuleNameU, + &LogHandle + ); + + if (!NT_SUCCESS(Status)) { + printf("Error - 0x%lx\n", Status); + + } else { + printf("SUCCESS\n"); + + // + // Clear the log file and back it up to "view.evt" + // + + RtlInitUnicodeString( &BackupU, + L"\\SystemRoot\\System32\\Config\\view.evt" ); + BackupU.MaximumLength = BackupU.Length; +retry: + printf("Calling ElfClearEventLogFile backing up to view.evt "); + Status = ElfClearEventLogFileW ( + LogHandle, + &BackupU + ); + + if (Status == STATUS_OBJECT_NAME_COLLISION) { + if (DontRetry) { + printf("Still can't backup to View.Evt\n"); + } + else { + printf("Failed.\nView.Evt already exists, deleting ...\n"); + + // + // Open the file with delete access + // + + InitializeObjectAttributes( + &ObjectAttributes, + &BackupU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL + ); + + Status = NtOpenFile(&ClearHandle, + GENERIC_READ | DELETE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_DELETE, + FILE_SYNCHRONOUS_IO_NONALERT + ); + + Status = NtSetInformationFile( + ClearHandle, + &IoStatusBlock, + &DeleteInfo, + sizeof(DeleteInfo), + FileDispositionInformation + ); + + if (NT_SUCCESS (Status) ) { + Status = NtClose (ClearHandle); // Discard status + goto retry; + } + + printf("Delete failed 0x%lx\n",Status); + Status = NtClose (ClearHandle); // Discard status + goto JustClear; + } + } + + if (!NT_SUCCESS(Status)) { + printf ("Error - 0x%lx\n", Status); + } else { + printf ("SUCCESS\n"); + } + +JustClear: + + // + // Now just clear the file without backing it up + // + printf("Calling ElfClearEventLogFile with no backup "); + Status = ElfClearEventLogFileW ( + LogHandle, + NULL + ); + + if (!NT_SUCCESS(Status)) { + printf ("Error - 0x%lx\n", Status); + } else { + printf ("SUCCESS\n"); + } + + printf("Calling ElfCloseEventLog\n"); + IStatus = ElfCloseEventLog (LogHandle); + } + + return(Status); +} + + +NTSTATUS +TestElfBackupLogFile( + VOID + ) + +{ + NTSTATUS Status, IStatus; + HANDLE LogHandle; + UNICODE_STRING BackupU, ModuleNameU; + ANSI_STRING AnsiString; + + printf("Testing ElfBackupLogFile API\n"); + + // + // Initialize the strings + // + + RtlInitAnsiString( &AnsiString, pModuleName); + RtlAnsiStringToUnicodeString(&ModuleNameU, &AnsiString, TRUE); + ModuleNameU.MaximumLength = ModuleNameU.Length ; + + // + // Open the log handle + // + + printf("Calling ElfOpenEventLog for BACKUP - "); + Status = ElfOpenEventLogW ( + &ServerName, + &ModuleNameU, + &LogHandle + ); + + if (!NT_SUCCESS(Status)) { + printf("Error - 0x%lx\n", Status); + + } else { + printf("SUCCESS\n"); + + // + // Backup the log file + // + + printf("Calling ElfBackupEventLogFile backing up to %s ", + pBackupFileName); + + RtlInitAnsiString( &AnsiString, pBackupFileName); + RtlAnsiStringToUnicodeString(&BackupU, &AnsiString, TRUE); + BackupU.MaximumLength = BackupU.Length; + + Status = ElfBackupEventLogFileW ( + LogHandle, + &BackupU + ); + + if (!NT_SUCCESS(Status)) { + printf ("Error - 0x%lx\n", Status); + } else { + printf ("SUCCESS\n"); + } + + + printf("Calling ElfCloseEventLog - "); + IStatus = ElfCloseEventLog (LogHandle); + if (NT_SUCCESS(IStatus)) { + printf("Success\n"); + } + else { + printf("Failed with code %X\n", IStatus); + } + } + + return(Status); +} + +#define DRIVER_NAME L"FLOPPY" +#define DEVICE_NAME L"A:" +#define STRING L"Test String" + +// These include the NULL terminator, but is length in chars, not bytes +#define DRIVER_NAME_LENGTH 7 +#define DEVICE_NAME_LENGTH 3 +#define STRING_LENGTH 12 + +#define NUMBER_OF_DATA_BYTES 8 + +VOID +TestLPCWrite( + DWORD NumberOfRecords, + DWORD MillisecondsToDelay + ) +{ + + HANDLE PortHandle; + UNICODE_STRING PortName; + NTSTATUS Status; + SECURITY_QUALITY_OF_SERVICE Qos; + PIO_ERROR_LOG_MESSAGE pIoErrorLogMessage; + DWORD i; + LPWSTR pDestinationString; + PPORT_MESSAGE RequestMessage; + PORT_MESSAGE ReplyMessage; + WORD DataLength; + WORD TotalLength; + INT YorN; + CHAR NumberString[8]; + ULONG MessageId = 1; + DWORD BadType = 0; + + // + // Warn the user about how this test works + // + + printf("\nThis test doesn't end! It will write a number of\n" + "records, then prompt you to write more. This is \n" + "required since it is simulating the system thread\n" + "which never shuts down it's connection\n\n" + "Do you wish to continue with this test (y or n)? "); + + YorN = getc(stdin); + + if (YorN == 'n' || YorN == 'N') { + return; + } + + // + // Initialize the SecurityQualityofService structure + // + + Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); + Qos.ImpersonationLevel = SecurityImpersonation; + Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; + Qos.EffectiveOnly = TRUE; + + // + // Connect to the LPC Port + // + + RtlInitUnicodeString( &PortName, L"\\ErrorLogPort" ); + + Status = NtConnectPort(& PortHandle, + & PortName, + & Qos, + NULL, + NULL, + NULL, + NULL, + NULL + ); + + if (!NT_SUCCESS(Status)) { + printf("Connect to the LPC port failed with RC %X\n", Status); + return; + } + + // + // Allocate the memory for the Message to send to the LPC port. It + // will contain a PORT_MESSAGE followed by an IO_ERROR_LOG_MESSAGE + // followed by Drivername and Devicename UNICODE strings + // + + DataLength = PORT_MAXIMUM_MESSAGE_LENGTH - + (sizeof(IO_ERROR_LOG_MESSAGE) + + DRIVER_NAME_LENGTH * sizeof(WCHAR) + + DEVICE_NAME_LENGTH * sizeof(WCHAR) + + STRING_LENGTH * sizeof(WCHAR)); + TotalLength = PORT_MAXIMUM_MESSAGE_LENGTH + (WORD) sizeof(PORT_MESSAGE); + + RequestMessage = (PPORT_MESSAGE) malloc(TotalLength); + if (RequestMessage == NULL) { + printf("Couldn't alloc %d bytes of memory for message\n", TotalLength); + NtClose(PortHandle); + return; + } + + pIoErrorLogMessage = (PIO_ERROR_LOG_MESSAGE) ((LPBYTE) RequestMessage + + sizeof(PORT_MESSAGE)); + + // + // Initialize the PORT_MESSAGE + // + + RequestMessage->u1.s1.DataLength = PORT_MAXIMUM_MESSAGE_LENGTH; + RequestMessage->u1.s1.TotalLength = TotalLength; + RequestMessage->u2.s2.Type = 0; + RequestMessage->u2.ZeroInit = 0; + RequestMessage->ClientId.UniqueProcess = GetCurrentProcess(); + RequestMessage->ClientId.UniqueThread = GetCurrentThread(); + RequestMessage->MessageId = 0x1234; + + // + // Initialize the IO_ERROR_LOG_MESSAGE + // + + pIoErrorLogMessage->Type = IO_TYPE_ERROR_MESSAGE; + pIoErrorLogMessage->Size = PORT_MAXIMUM_MESSAGE_LENGTH; + pIoErrorLogMessage->DriverNameLength = DRIVER_NAME_LENGTH * sizeof(WCHAR); + NtQuerySystemTime((PTIME) &pIoErrorLogMessage->TimeStamp); + pIoErrorLogMessage->DriverNameOffset = sizeof(IO_ERROR_LOG_MESSAGE) + + DataLength - sizeof(DWORD); + + pIoErrorLogMessage->EntryData.MajorFunctionCode = 1; + pIoErrorLogMessage->EntryData.RetryCount = 5; + pIoErrorLogMessage->EntryData.DumpDataSize = DataLength; + pIoErrorLogMessage->EntryData.NumberOfStrings = 2; + pIoErrorLogMessage->EntryData.StringOffset = sizeof(IO_ERROR_LOG_MESSAGE) + - sizeof(DWORD) + DataLength + + DRIVER_NAME_LENGTH * sizeof(WCHAR); + pIoErrorLogMessage->EntryData.EventCategory = 0; + pIoErrorLogMessage->EntryData.ErrorCode = 0xC0020008; + pIoErrorLogMessage->EntryData.UniqueErrorValue = 0x20008; + pIoErrorLogMessage->EntryData.FinalStatus = 0x1111; + pIoErrorLogMessage->EntryData.SequenceNumber = 1; + pIoErrorLogMessage->EntryData.IoControlCode = 0xFF; + pIoErrorLogMessage->EntryData.DeviceOffset = + RtlConvertUlongToLargeInteger(1); + + for (i = 0; i < DataLength ; i++ ) { + pIoErrorLogMessage->EntryData.DumpData[i] = i; + } + + // + // Copy the strings + // + + pDestinationString = (LPWSTR) ((LPBYTE) pIoErrorLogMessage + + sizeof(IO_ERROR_LOG_MESSAGE) + - sizeof(DWORD) + pIoErrorLogMessage->EntryData.DumpDataSize); + wcscpy(pDestinationString, DRIVER_NAME); + + pDestinationString += DRIVER_NAME_LENGTH; + wcscpy(pDestinationString, DEVICE_NAME); + + pDestinationString += DEVICE_NAME_LENGTH; + wcscpy(pDestinationString, STRING); + + // + // Write the packet as many times as requested, with delay, then ask + // if they want to write more + // + while (NumberOfRecords) { + + printf("\n\nWriting %d records\n", NumberOfRecords); + + while(NumberOfRecords--) { + printf("."); + + // + // Put in a unique message number + // + + RequestMessage->MessageId = MessageId++; + + // + // If they want invalid records, give them invalid records + // + + if (WriteInvalidRecords) { + switch (BadType++) { + case 0: + pIoErrorLogMessage->EntryData.DumpDataSize++; + break; + + case 1: + pIoErrorLogMessage->EntryData.NumberOfStrings++; + break; + + case 2: + pIoErrorLogMessage->EntryData.StringOffset++; + break; + + default: + BadType = 0; + } + } + + Status = NtRequestWaitReplyPort(PortHandle, + RequestMessage, + & ReplyMessage); + + if (!NT_SUCCESS(Status)) { + printf("Request to LPC port failed with RC %X\n", Status); + break; + } + + // + // Delay a little bit, if requested + // + + if (MillisecondsToDelay) { + Sleep(MillisecondsToDelay); + } + } + printf("\nEnter the number of records to write "); + + while (!gets(NumberString) || !(NumberOfRecords = atoi(NumberString))) { + printf("Enter the number of records to write "); + } + } + + // + // Clean up and exit + // + + Status = NtClose(PortHandle); + if (!NT_SUCCESS(Status)) { + printf("Close of Port failed with RC %X\n", Status); + } + + free(RequestMessage); + + return; + +} + + +VOID +TestChangeNotify( + VOID + ) +{ + + HANDLE Event; + UNICODE_STRING ModuleNameU; + ANSI_STRING ModuleNameA; + NTSTATUS Status; + HANDLE LogHandle; + OBJECT_ATTRIBUTES obja; + ULONG NumRecords; + ULONG BytesRead; + ULONG MinBytesNeeded; + PVOID Buffer; + ULONG OldestRecord; + ULONG NumberOfRecords; + + RtlInitAnsiString(&ModuleNameA, pModuleName); + RtlAnsiStringToUnicodeString(&ModuleNameU, &ModuleNameA, TRUE); + ModuleNameU.MaximumLength = ModuleNameU.Length ; + + Buffer = malloc (READ_BUFFER_SIZE); + ASSERT(Buffer); + + // + // Open the log handle + // + + printf("ElfOpenEventLog - "); + Status = ElfOpenEventLogW ( + &ServerName, + &ModuleNameU, + &LogHandle + ); + + if (!NT_SUCCESS(Status)) { + printf("Error - 0x%lx\n", Status); + return; + } + + printf("SUCCESS\n"); + + // + // Create the Event + // + + InitializeObjectAttributes( &obja, NULL, 0, NULL, NULL); + + Status = NtCreateEvent( + &Event, + SYNCHRONIZE | EVENT_QUERY_STATE | EVENT_MODIFY_STATE, + &obja, + SynchronizationEvent, + FALSE + ); + + ASSERT(NT_SUCCESS(Status)); + + // + // Get the read pointer to the end of the log + // + + Status = ElfOldestRecord(LogHandle, & OldestRecord); + ASSERT(NT_SUCCESS(Status)); + Status = ElfNumberOfRecords(LogHandle, & NumberOfRecords); + ASSERT(NT_SUCCESS(Status)); + OldestRecord += NumberOfRecords - 1; + + Status = ElfReadEventLogW ( + LogHandle, + EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ, + OldestRecord, + Buffer, + READ_BUFFER_SIZE, + &BytesRead, + &MinBytesNeeded + ); + + + // + // This one should hit end of file + // + + Status = ElfReadEventLogW ( + LogHandle, + EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, + 0, + Buffer, + READ_BUFFER_SIZE, + &BytesRead, + &MinBytesNeeded + ); + + if (Status != STATUS_END_OF_FILE) { + printf("Hmmm, should have hit EOF (unless there are writes going" + " on elsewhere- %X\n", Status); + } + + // + // Call ElfChangeNotify + // + + Status = ElfChangeNotify(LogHandle, Event); + ASSERT(NT_SUCCESS(Status)); + + // + // Now loop waiting for the event to get toggled + // + + while (1) { + + Status = NtWaitForSingleObject(Event, FALSE, 0); + printf("The change notify event just got kicked\n"); + + // + // Now read the new records + // + + while(1) { + + Status = ElfReadEventLogW ( + LogHandle, + EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, + 0, + Buffer, + READ_BUFFER_SIZE, + &BytesRead, + &MinBytesNeeded + ); + + if (Status == STATUS_END_OF_FILE) { + break; + } + + NumRecords = 0xffff; // should be plenty + DisplayEventRecords (Buffer, BytesRead, &NumRecords); + } + } +} + +VOID +_CRTAPI1 +main ( + IN SHORT argc, + IN PSZ argv[] + ) +{ + + Initialize(); // Init any data + + // + // Parse the command line + // + + ParseParms(argc, argv); + + switch (Operation) { + case Clear: + + TestElfClearLogFile(); + break; + + case Backup: + + TestElfBackupLogFile(); + break; + + case Read: + + if (ReadFlags & EVENTLOG_SEEK_READ) { + TestReadEventLog(1, ReadFlags, NumberofRecords) ; + } + else { + TestReadEventLog(NumberofRecords, ReadFlags, 0) ; + } + break; + + case Write: + + TestReportEvent (NumberofRecords); + break; + + case LPC: + TestLPCWrite(NumberofRecords, DelayInMilliseconds); + break; + + case Notify: + TestChangeNotify(); + break; + + default: + printf("Invalid switch from ParseParms %d\n", Operation); + } +} + + +VOID +ParseParms( + ULONG argc, + PCHAR *argv + ) +{ + + ULONG i; + PCHAR pch; + + for (i = 1; i < argc; i++) { /* for each argument */ + if (*(pch = argv[i]) == '-') { + while (*++pch) { + switch (*pch) { + case 'b': + + SET_OPERATION(Backup) + + // + // Get the file name for backup + // + + if (i+1 < argc) { + pBackupFileName = argv[++i]; + } + else { + Usage(); + } + break; + + case 'c': + + SET_OPERATION(Clear) + + break; + + case 'f': + if (i+1 < argc) { + pModuleName = argv[++i]; + ReadingBackupFile = TRUE; + } + else { + Usage(); + } + break; + + case '?': + case 'h': + case 'H': + Usage(); + break; + + case 'i': + InvalidUser = TRUE; + break; + + case 'l': + + SET_OPERATION(LPC); + + // + // See if they want invalid records + // + + if (*++pch == 'i') { + WriteInvalidRecords = TRUE; + } + + // + // See if they specified a number of records + // + + if (i + 1 < argc && argv[i+1][0] != '-') { + NumberofRecords = atoi(argv[++i]); + if (NumberofRecords == 0) { + Usage(); + } + } + + break; + + case 'm': + if (i+1 < argc) { + pModuleName = argv[++i]; + ReadingModule = TRUE; + } + else { + Usage(); + } + break; + + case 'n': + SET_OPERATION(Notify) + break; + + case 'r': + + SET_OPERATION(Read) + + // + // Different Read options + // + + if (*++pch == 's') { + ReadFlags |= EVENTLOG_SEQUENTIAL_READ; + } + else if (*pch == 'r') { + ReadFlags |= EVENTLOG_SEEK_READ; + } + else { + Usage(); + } + + if (*++pch == 'f') { + ReadFlags |= EVENTLOG_FORWARDS_READ; + } + else if (*pch == 'b') { + ReadFlags |= EVENTLOG_BACKWARDS_READ; + } + else { + Usage(); + } + + // + // See if they specified a number of records + // + + if (i + 1 < argc && argv[i+1][0] != '-') { + NumberofRecords = atoi(argv[++i]); + if (NumberofRecords == 0) { + Usage(); + } + } + + break; + + case 's': + if (i+1 >= argc) { + printf("Must supply a server name with -s\n"); + Usage(); + } + RtlInitAnsiString(&AnsiString, argv[++i]); + RtlAnsiStringToUnicodeString(&ServerName, &AnsiString, + TRUE); + break; + + case 't': + DelayInMilliseconds = atoi(argv[++i]); + break; + + case 'v': + Verbose = TRUE; + break; + + case 'w': + + SET_OPERATION(Write) + + // + // See if they specified a number of records + // + + if (i + 1 < argc && argv[i+1][0] != '-') { + NumberofRecords = atoi(argv[++i]); + if (NumberofRecords == 0) { + Usage(); + } + } + + break; + + default: /* Invalid options */ + printf("Invalid option %c\n\n", *pch); + Usage(); + break; + } + } + } + + // + // There aren't any non switch parms + // + + else { + Usage(); + } + } + + // + // Verify parms are correct + // + + + if ( Operation == Invalid) { + printf( "Must specify an operation\n"); + Usage( ); + } + + if (ReadingBackupFile && ReadingModule) { + printf("-m and -f are mutually exclusive\n"); + Usage(); + } + + if (ReadingBackupFile && Operation == Write) { + printf("You cannot write to a backup log file\n"); + Usage(); + } + if (DelayInMilliseconds && Operation != LPC) { + printf("\n\n-t switch is only used with -l\n\n"); + } +} + |