diff options
Diffstat (limited to 'private/eventlog/ntsdexts/elfexts.c')
-rw-r--r-- | private/eventlog/ntsdexts/elfexts.c | 767 |
1 files changed, 767 insertions, 0 deletions
diff --git a/private/eventlog/ntsdexts/elfexts.c b/private/eventlog/ntsdexts/elfexts.c new file mode 100644 index 000000000..69fb5f25c --- /dev/null +++ b/private/eventlog/ntsdexts/elfexts.c @@ -0,0 +1,767 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + elfexts.c + +Abstract: + + This function contains the eventlog ntsd debugger extensions + +Author: + + Dan Hinsley (DanHi) 22-May-1993 + +Revision History: + +--*/ + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <windows.h> +#include <ntsdexts.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <malloc.h> +#include <time.h> +#include <elf.h> +#include <elfdef.h> +#include <elfcommn.h> +#include <elfproto.h> +#include <svcs.h> +#include <elfextrn.h> + +//#define DbgPrint(_x_) (lpOutputRoutine) _x_ +#define DbgPrint(_x_) +#define MAX_NAME 256 +#define printf (lpOutputRoutine) +#define GET_DATA(DebugeeAddr, LocalAddr, Length) \ + Status = ReadProcessMemory( \ + GlobalhCurrentProcess, \ + (LPVOID)DebugeeAddr, \ + LocalAddr, \ + Length, \ + NULL \ + ); + +PNTSD_OUTPUT_ROUTINE lpOutputRoutine; +PNTSD_GET_EXPRESSION lpGetExpressionRoutine; +PNTSD_CHECK_CONTROL_C lpCheckControlCRoutine; + +HANDLE GlobalhCurrentProcess; +BOOL Status; + +// +// Initialize the global function pointers +// + +VOID +InitFunctionPointers( + HANDLE hCurrentProcess, + PNTSD_EXTENSION_APIS lpExtensionApis + ) +{ + // + // Load these to speed access if we haven't already + // + + if (!lpOutputRoutine) { + lpOutputRoutine = lpExtensionApis->lpOutputRoutine; + lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine; + lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine; + } + + // + // Stick this in a global + // + + GlobalhCurrentProcess = hCurrentProcess; +} + +LPWSTR +GetUnicodeString( + PUNICODE_STRING pUnicodeString + ) +{ + DWORD Pointer; + UNICODE_STRING UnicodeString; + + GET_DATA(pUnicodeString, &UnicodeString, sizeof(UNICODE_STRING)) + Pointer = (DWORD) UnicodeString.Buffer; + UnicodeString.Buffer = (LPWSTR) LocalAlloc(LMEM_ZEROINIT, + UnicodeString.Length + sizeof(WCHAR)); + GET_DATA(Pointer, UnicodeString.Buffer, UnicodeString.Length) + + return(UnicodeString.Buffer); +} + +DWORD +GetLogFileAddress( + LPSTR LogFileName, + PLOGFILE LogFile + ) +{ + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + DWORD Pointer; + DWORD LogFileAnchor; + LPWSTR ModuleName; + + // + // Convert the string to UNICODE + // + + RtlInitAnsiString(&AnsiString, LogFileName); + RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); + + // + // Walk the logfile list looking for a match + // + + LogFileAnchor = (lpGetExpressionRoutine)("LogFilesHead"); + + GET_DATA(LogFileAnchor, &Pointer, sizeof(DWORD)) + + while (Pointer != LogFileAnchor) { + GET_DATA(Pointer, LogFile, sizeof(LOGFILE)) + ModuleName = GetUnicodeString(LogFile->LogModuleName); + if (!wcsicmp(ModuleName, UnicodeString.Buffer)) { + break; + } + LocalFree(ModuleName); + Pointer = (DWORD) LogFile->FileList.Flink; + } + + RtlFreeUnicodeString(&UnicodeString); + + if (Pointer == LogFileAnchor) { + return(0); + } + else { + LocalFree(ModuleName); + return(Pointer); + } +} + +// +// Dump an individual record +// + +DWORD +DumpRecord( + DWORD Record, + DWORD RecordNumber, + DWORD StartOfFile, + DWORD EndOfFile + ) +{ + DWORD BufferLen; + PCHAR TimeBuffer; + PEVENTLOGRECORD EventLogRecord; + LPWSTR Module; + LPWSTR Computer; + DWORD FirstPiece = 0; + + GET_DATA(Record, &BufferLen, sizeof(DWORD)) + + // + // See if it's a ELF_SKIP_DWORD, and if it is, return the top of the + // file + // + + if (BufferLen == ELF_SKIP_DWORD) { + return(StartOfFile + sizeof(ELF_LOGFILE_HEADER)); + } + + // + // See if it's the EOF record + // + + if (BufferLen == ELFEOFRECORDSIZE) { + return(0); + } + + BufferLen += sizeof(DWORD); // get room for length of next record + EventLogRecord = (PEVENTLOGRECORD) LocalAlloc(LMEM_ZEROINIT, BufferLen); + + // + // If the record wraps, grab it piecemeal + // + + if (EndOfFile && BufferLen + Record > EndOfFile) { + FirstPiece = EndOfFile - Record; + GET_DATA(Record, EventLogRecord, FirstPiece); + GET_DATA((StartOfFile + sizeof(ELF_LOGFILE_HEADER)), + ((PBYTE) EventLogRecord + FirstPiece), BufferLen - FirstPiece) + } + else { + GET_DATA(Record, EventLogRecord, BufferLen) + } + + // + // If it's greater than the starting record, print it out + // + + if (EventLogRecord->RecordNumber >= RecordNumber) { + printf("\nRecord %d is %d [0x%X] bytes long starting at 0x%X\n", + EventLogRecord->RecordNumber, EventLogRecord->Length, + EventLogRecord->Length, Record); + Module = (LPWSTR)(EventLogRecord+1); + Computer = (LPWSTR)((PBYTE) Module + ((wcslen(Module) + 1) * sizeof(WCHAR))); + printf("\tGenerated by %ws from system %ws\n", Module, Computer); + + TimeBuffer = ctime((time_t *)&(EventLogRecord->TimeGenerated)); + if (TimeBuffer) { + printf("\tGenerated at %s", TimeBuffer); + } + else { + printf("\tGenerated time field is blank\n"); + } + TimeBuffer = ctime((time_t *)&(EventLogRecord->TimeWritten)); + if (TimeBuffer) { + printf("\tWritten at %s", TimeBuffer); + } + else { + printf("\tTime written field is blank\n"); + } + + printf("\tEvent Id = %d\n", EventLogRecord->EventID); + printf("\tEventType = "); + switch (EventLogRecord->EventType) { + case EVENTLOG_SUCCESS: + printf("Success\n"); + break; + case EVENTLOG_ERROR_TYPE: + printf("Error\n"); + break; + case EVENTLOG_WARNING_TYPE: + printf("Warning\n"); + break; + case EVENTLOG_INFORMATION_TYPE: + printf("Information\n"); + break; + case EVENTLOG_AUDIT_SUCCESS: + printf("Audit Success\n"); + break; + case EVENTLOG_AUDIT_FAILURE: + printf("Audit Failure\n"); + break; + default: + printf("Invalid value 0x%X\n", EventLogRecord->EventType); + } + printf("\t%d strings at offset 0x%X\n", EventLogRecord->NumStrings, + EventLogRecord->StringOffset); + printf("\t%d bytes of data at offset 0x%X\n", EventLogRecord->DataLength, + EventLogRecord->DataOffset); + } + + if (FirstPiece) { + Record = StartOfFile + sizeof(ELF_LOGFILE_HEADER) + BufferLen - + FirstPiece; + } + else { + Record += EventLogRecord->Length; + } + + LocalFree(EventLogRecord); + return(Record); +} + +// +// Dump a record, or all records, or n records +// + +VOID +record( + HANDLE hCurrentProcess, + HANDLE hCurrentThread, + DWORD dwCurrentPc, + PNTSD_EXTENSION_APIS lpExtensionApis, + LPSTR lpArgumentString + ) +{ + DWORD Pointer; + LOGFILE LogFile; + DWORD StartOfFile; + DWORD EndOfFile = 0; + DWORD RecordNumber = 0; + + InitFunctionPointers(hCurrentProcess, lpExtensionApis); + + // + // Evaluate the argument string to get the address of + // the record to dump. + // + + if (lpArgumentString && *lpArgumentString) { + if (*lpArgumentString == '.') { + if (GetLogFileAddress(lpArgumentString+1, &LogFile) == 0) { + printf("Logfile %s not found\n", lpArgumentString+1); + return; + } + Pointer = ((DWORD) (LogFile.BaseAddress)) + LogFile.BeginRecord; + } + else if (*lpArgumentString == '#') { + RecordNumber = atoi(lpArgumentString + 1); + printf("Dumping records starting at record #%d\n", RecordNumber); + lpArgumentString = NULL; + } + else if (*lpArgumentString) { + Pointer = (lpGetExpressionRoutine)(lpArgumentString); + } + else { + printf("Invalid lead character 0x%02X\n", *lpArgumentString); + return; + } + } + + if (!lpArgumentString || *lpArgumentString) { + if (GetLogFileAddress("system", &LogFile) == 0) { + printf("System Logfile not found\n"); + return; + } + Pointer = ((DWORD) (LogFile.BaseAddress)) + LogFile.BeginRecord; + } + + StartOfFile = (DWORD) LogFile.BaseAddress; + EndOfFile = (DWORD) LogFile.BaseAddress + LogFile.ActualMaxFileSize; + + // + // Dump records starting wherever they told us to + // + + while (Pointer < EndOfFile && Pointer && !(lpCheckControlCRoutine)()) { + Pointer = DumpRecord(Pointer, RecordNumber, StartOfFile, EndOfFile); + } + + + return; +} + +// +// Dump a single LogModule structure if it matches MatchName (NULL matches +// all) +// + +PLIST_ENTRY +DumpLogModule( + HANDLE hCurrentProcess, + DWORD pLogModule, + LPWSTR MatchName + ) +{ + LOGMODULE LogModule; + WCHAR ModuleName[MAX_NAME / sizeof(WCHAR)]; + + GET_DATA(pLogModule, &LogModule, sizeof(LogModule)) + GET_DATA(LogModule.ModuleName, &ModuleName, MAX_NAME) + + if (!MatchName || !wcsicmp(MatchName, ModuleName)) { + printf("\tModule Name %ws\n", ModuleName); + printf("\tModule Atom 0x%X\n", LogModule.ModuleAtom); + printf("\tPointer to LogFile 0x%X\n", LogModule.LogFile); + } + + return (LogModule.ModuleList.Flink); +} + +// +// Dump selected, or all, LogModule structures +// + +VOID +logmodule( + HANDLE hCurrentProcess, + HANDLE hCurrentThread, + DWORD dwCurrentPc, + PNTSD_EXTENSION_APIS lpExtensionApis, + LPSTR lpArgumentString + ) +{ + DWORD pLogModule; + DWORD LogModuleAnchor; + LPWSTR wArgumentString = NULL; + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + + InitFunctionPointers(hCurrentProcess, lpExtensionApis); + UnicodeString.Buffer = NULL; + + // + // Evaluate the argument string to get the address of + // the logmodule to dump. If no parm, dump them all. + // + + if (lpArgumentString && *lpArgumentString == '.') { + lpArgumentString++; + RtlInitAnsiString(&AnsiString, lpArgumentString); + RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); + } + else if (lpArgumentString && *lpArgumentString) { + pLogModule = (lpGetExpressionRoutine)(lpArgumentString); + DumpLogModule(hCurrentProcess, pLogModule, NULL); + return; + } + + LogModuleAnchor = (lpGetExpressionRoutine)("LogModuleHead"); + + GET_DATA(LogModuleAnchor, &pLogModule, sizeof(DWORD)) + + while (pLogModule != LogModuleAnchor && !(lpCheckControlCRoutine)()) { + pLogModule = + (DWORD) DumpLogModule(hCurrentProcess, pLogModule, + UnicodeString.Buffer); + if (!UnicodeString.Buffer) { + printf("\n"); + } + } + if (UnicodeString.Buffer) { + RtlFreeUnicodeString(&UnicodeString); + } + + return; +} + +// +// Dump a single LogFile structure if it matches MatchName (NULL matches +// all) +// + +PLIST_ENTRY +DumpLogFile( + HANDLE hCurrentProcess, + DWORD pLogFile, + LPWSTR MatchName + ) +{ + LOGFILE LogFile; + LPWSTR UnicodeName; + + // + // Get the fixed part of the structure + // + + GET_DATA(pLogFile, &LogFile, sizeof(LogFile)) + + // + // Get the Default module name + // + + UnicodeName = GetUnicodeString(LogFile.LogModuleName); + + // + // See if we're just looking for a particular one. If we are and + // this isn't it, bail out. + // + + if (MatchName && wcsicmp(MatchName, UnicodeName)) { + LocalFree(UnicodeName); + return (LogFile.FileList.Flink); + } + + // + // Otherwise print it out + // + + printf("%ws", UnicodeName); + LocalFree(UnicodeName); + + // + // Now the file name of this logfile + // + + UnicodeName = GetUnicodeString(LogFile.LogFileName); + printf(" : %ws\n", UnicodeName); + LocalFree(UnicodeName); + + if (LogFile.Notifiees.Flink == LogFile.Notifiees.Blink) { + printf("\tNo active ChangeNotifies on this log\n"); + } + else { + printf("\tActive Change Notify! Dump of this list not implemented\n"); + } + + printf("\tReference Count: %d\n\tFlags: ", LogFile.RefCount); + if (LogFile.Flags == 0) { + printf("No flags set "); + } + else { + if (LogFile.Flags & ELF_LOGFILE_HEADER_DIRTY) { + printf("Dirty "); + } + if (LogFile.Flags & ELF_LOGFILE_HEADER_WRAP) { + printf("Wrapped "); + } + if (LogFile.Flags & ELF_LOGFILE_LOGFULL_WRITTEN) { + printf("Logfull Written "); + } + } + printf("\n"); + + printf("\tMax Files Sizes [Cfg:Curr:Next] 0x%X : 0x%X : 0x%X\n", + LogFile.ConfigMaxFileSize, LogFile.ActualMaxFileSize, + LogFile.NextClearMaxFileSize); + + printf("\tRecord Numbers [Oldest:Curr] %d : %d\n", + LogFile.OldestRecordNumber, LogFile.CurrentRecordNumber); + + printf("\tRetention period in days: %d\n", LogFile.Retention / 86400); + + printf("\tBase Address: 0x%X\n", LogFile.BaseAddress); + + printf("\tView size: 0x%X\n", LogFile.ViewSize); + + printf("\tOffset of beginning record: 0x%X\n", LogFile.BeginRecord); + + printf("\tOffset of ending record: 0x%X\n", LogFile.EndRecord); + + return (LogFile.FileList.Flink); +} + +// +// Dump selected, or all, LogFile structures +// + +VOID +logfile( + HANDLE hCurrentProcess, + HANDLE hCurrentThread, + DWORD dwCurrentPc, + PNTSD_EXTENSION_APIS lpExtensionApis, + LPSTR lpArgumentString + ) +{ + DWORD pLogFile; + DWORD LogFileAnchor; + LPWSTR wArgumentString = NULL; + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + BOOL AllocateString = FALSE; + + InitFunctionPointers(hCurrentProcess, lpExtensionApis); + UnicodeString.Buffer = NULL; + + // + // Evaluate the argument string to get the address of + // the logfile to dump. If no parm, dump them all. + // + + if (lpArgumentString && *lpArgumentString) { + if(*lpArgumentString == '.') { + lpArgumentString++; + RtlInitAnsiString(&AnsiString, lpArgumentString); + RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); + } + else { + pLogFile = (lpGetExpressionRoutine)(lpArgumentString); + DumpLogFile(hCurrentProcess, pLogFile, NULL); + return; + } + } + + LogFileAnchor = (lpGetExpressionRoutine)("LogFilesHead"); + + GET_DATA(LogFileAnchor, &pLogFile, sizeof(DWORD)) + + while (pLogFile != LogFileAnchor) { + pLogFile = + (DWORD) DumpLogFile(hCurrentProcess, pLogFile, + UnicodeString.Buffer); + if (!UnicodeString.Buffer) { + printf("\n"); + } + } + + if (UnicodeString.Buffer) { + RtlFreeUnicodeString(&UnicodeString); + } + + return; +} + +// +// Dump a request packet structure +// + +VOID +request( + HANDLE hCurrentProcess, + HANDLE hCurrentThread, + DWORD dwCurrentPc, + PNTSD_EXTENSION_APIS lpExtensionApis, + LPSTR lpArgumentString + ) +{ + ELF_REQUEST_RECORD Request; + DWORD Pointer; + DWORD RecordSize; + WRITE_PKT WritePkt; + READ_PKT ReadPkt; + CLEAR_PKT ClearPkt; + BACKUP_PKT BackupPkt; + LPWSTR FileName; + CHAR Address[18]; + + InitFunctionPointers(hCurrentProcess, lpExtensionApis); + + // + // Evaluate the argument string to get the address of + // the request packet to dump. + // + + if (lpArgumentString && *lpArgumentString) { + Pointer = (lpGetExpressionRoutine)(lpArgumentString); + } + else { + printf("Must supply a request packet address\n"); + return; + } + + GET_DATA(Pointer, &Request, sizeof(ELF_REQUEST_RECORD)) + + switch (Request.Command ) { + case ELF_COMMAND_READ: + printf("\nRead packet\n"); + GET_DATA(Request.Pkt.ReadPkt, &ReadPkt, sizeof(READ_PKT)) + printf("\tLast Seek Position = %d\n", ReadPkt.LastSeekPos); + printf("\tLast Seek Record = %d\n", ReadPkt.LastSeekRecord); + printf("\tStart at record number %d\n", ReadPkt.RecordNumber); + printf("\tRead %d bytes into buffer at 0x%X\n", + ReadPkt.BufferSize, ReadPkt.Buffer); + if (ReadPkt.Flags & ELF_IREAD_UNICODE) { + printf("\tReturn in ANSI\n"); + } + else { + printf("\tReturn in UNICODE\n"); + } + printf("\tRead flags: "); + if (ReadPkt.ReadFlags & EVENTLOG_SEQUENTIAL_READ) { + printf("Sequential "); + } + if (ReadPkt.ReadFlags & EVENTLOG_SEEK_READ) { + printf("Seek "); + } + if (ReadPkt.ReadFlags & EVENTLOG_FORWARDS_READ) { + printf("Forward "); + } + if (ReadPkt.ReadFlags & EVENTLOG_BACKWARDS_READ) { + printf("Backwards "); + } + printf("\n"); + break; + + case ELF_COMMAND_WRITE: + printf("\nWrite packet\n"); + if (Request.Flags == ELF_FORCE_OVERWRITE) { + printf("with ELF_FORCE_OVERWRITE enabled\n"); + } + else { + printf("\n"); + } + GET_DATA(Request.Pkt.WritePkt, &WritePkt, sizeof(WRITE_PKT)) + RecordSize = (WritePkt.Datasize); + DumpRecord((DWORD)WritePkt.Buffer, 0, 0, 0); + break; + + case ELF_COMMAND_CLEAR: + printf("\nClear packet\n"); + GET_DATA(Request.Pkt.ClearPkt, &ClearPkt, sizeof(CLEAR_PKT)) + FileName = GetUnicodeString(ClearPkt.BackupFileName); + printf("Backup filename = %ws\n", FileName); + LocalFree(FileName); + break; + + case ELF_COMMAND_BACKUP: + printf("\nBackup packet\n"); + GET_DATA(Request.Pkt.BackupPkt, &BackupPkt, sizeof(BACKUP_PKT)) + FileName = GetUnicodeString(BackupPkt.BackupFileName); + printf("Backup filename = %ws\n", FileName); + LocalFree(FileName); + break; + + case ELF_COMMAND_WRITE_QUEUED: + printf("\nQueued Write packet\n"); + if (Request.Flags == ELF_FORCE_OVERWRITE) { + printf("with ELF_FORCE_OVERWRITE enabled\n"); + } + else { + printf("\n"); + } + printf("NtStatus = 0x%X\n", Request.Status); + break; + + default: + printf("\nInvalid packet\n"); + } + + printf("\nLogFile for this packet:\n\n"); + itoa((DWORD) Request.LogFile, Address, 16); + logfile(hCurrentProcess, hCurrentThread, dwCurrentPc, lpExtensionApis, + Address); + + printf("\nLogModule for this packet:\n\n"); + itoa((DWORD)Request.Module, Address, 16); + logmodule(hCurrentProcess, hCurrentThread, dwCurrentPc, lpExtensionApis, + Address); + + return; +} + +// +// Online help +// + +VOID +help( + HANDLE hCurrentProcess, + HANDLE hCurrentThread, + DWORD dwCurrentPc, + PNTSD_EXTENSION_APIS lpExtensionApis, + LPSTR lpArgumentString + ) +{ + InitFunctionPointers(hCurrentProcess, lpExtensionApis); + + printf("\nEventlog NTSD Extensions\n"); + + if (!lpArgumentString || *lpArgumentString == '\0' || + *lpArgumentString == '\n' || *lpArgumentString == '\r') { + printf("\tlogmodule - dump a logmodule structure\n"); + printf("\tlogfile - dump a logfile structure\n"); + printf("\trequest - dump a request record\n"); + printf("\trecord - dump a eventlog record\n"); + printf("\n\tEnter help <cmd> for detailed help on a command\n"); + } + else { + if (!stricmp(lpArgumentString, "logmodule")) { + printf("\tlogmodule <arg>, where <arg> can be one of:\n"); + printf("\t\tno argument - dump all logmodule structures\n"); + printf("\t\taddress - dump the logmodule at specified address\n"); + printf("\t\t.string - dump the logmodule with name string\n"); + } + else if (!stricmp(lpArgumentString, "logfile")) { + printf("\tlogfile <arg>, where <arg> can be one of:\n"); + printf("\t\tno argument - dump all logfile structures\n"); + printf("\t\taddress - dump the logfile at specified address\n"); + printf("\t\t.string - dump the logfile with name string\n"); + } + else if (!stricmp(lpArgumentString, "record")) { + printf("\trecord <arg>, where <arg> can be one of:\n"); + printf("\t\tno argument - dump all records in system log\n"); + printf("\t\taddress - dump records starting at specified address\n"); + printf("\t\t.string - dump all records in the <string> log\n"); + printf("\t\t#<nnn> - dumps records starting at nnn in system log\n"); + printf("\t\t#<nnn> .string - dumps records starting at nnn in <string> log\n"); + } + else if (!stricmp(lpArgumentString, "request")) { + printf("\trequest - dump the request record at specified address\n"); + } + else { + printf("\tInvalid command [%s]\n", lpArgumentString); + } + } +} |