768 lines
21 KiB
C
768 lines
21 KiB
C
|
/*++
|
||
|
|
||
|
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 <svcsp.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);
|
||
|
}
|
||
|
}
|
||
|
}
|