1094 lines
26 KiB
C
1094 lines
26 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1989-1999 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
fspyLog.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module contains functions used to retrieve and see the log records
|
||
|
recorded by filespy.sys.
|
||
|
|
||
|
// @@BEGIN_DDKSPLIT
|
||
|
Author:
|
||
|
|
||
|
Molly Brown (MollyBro) 21-Apr-1999
|
||
|
|
||
|
// @@END_DDKSPLIT
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
User mode
|
||
|
|
||
|
|
||
|
// @@BEGIN_DDKSPLIT
|
||
|
Revision History:
|
||
|
|
||
|
// @@END_DDKSPLIT
|
||
|
--*/
|
||
|
#include <stdio.h>
|
||
|
#include <windows.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <winioctl.h>
|
||
|
#include "ioTestLog.h"
|
||
|
#include "ioTestLib.h"
|
||
|
|
||
|
#define TIME_BUFFER_LENGTH 20
|
||
|
#define TIME_ERROR L"time error"
|
||
|
|
||
|
#define FlagOn(F,SF) ( \
|
||
|
(((F) & (SF))) \
|
||
|
)
|
||
|
|
||
|
VOID
|
||
|
DumpLogRecord (
|
||
|
PLOG_RECORD pLogRecord,
|
||
|
PLOG_CONTEXT context
|
||
|
)
|
||
|
{
|
||
|
PRECORD_IRP pRecordIrp;
|
||
|
PRECORD_FASTIO pRecordFastIo;
|
||
|
PRECORD_FS_FILTER_OPERATION pRecordFsFilterOp;
|
||
|
ULONG nameLength;
|
||
|
|
||
|
//
|
||
|
// Calculate the length of the name in the log record.
|
||
|
//
|
||
|
|
||
|
nameLength = pLogRecord->Length - SIZE_OF_LOG_RECORD;
|
||
|
|
||
|
//
|
||
|
// A LOG_RECORD could have Irp or FastIo data in it. This
|
||
|
// is denoted in the low-order byte of the RecordType flag.
|
||
|
//
|
||
|
|
||
|
switch (GET_RECORD_TYPE(pLogRecord)) {
|
||
|
case RECORD_TYPE_IRP:
|
||
|
|
||
|
//
|
||
|
// We've got an Irp record, so output this data correctly.
|
||
|
//
|
||
|
pRecordIrp = &(pLogRecord->Record.RecordIrp);
|
||
|
|
||
|
if (context->LogToScreen) {
|
||
|
|
||
|
IrpScreenDump( pLogRecord->DeviceType,
|
||
|
pLogRecord->SequenceNumber,
|
||
|
pLogRecord->Name,
|
||
|
nameLength,
|
||
|
pRecordIrp,
|
||
|
context->VerbosityFlags);
|
||
|
}
|
||
|
|
||
|
if (context->LogToFile) {
|
||
|
|
||
|
IrpFileDump( pLogRecord->DeviceType,
|
||
|
pLogRecord->SequenceNumber,
|
||
|
pLogRecord->Name,
|
||
|
nameLength,
|
||
|
pRecordIrp,
|
||
|
context->OutputFile,
|
||
|
context->VerbosityFlags);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case RECORD_TYPE_FASTIO:
|
||
|
|
||
|
//
|
||
|
// We've got a FastIo record, so output this data correctly.
|
||
|
//
|
||
|
|
||
|
pRecordFastIo = &(pLogRecord->Record.RecordFastIo);
|
||
|
|
||
|
if (context->LogToScreen) {
|
||
|
|
||
|
FastIoScreenDump( pLogRecord->DeviceType,
|
||
|
pLogRecord->SequenceNumber,
|
||
|
pLogRecord->Name,
|
||
|
nameLength,
|
||
|
pRecordFastIo);
|
||
|
}
|
||
|
|
||
|
if (context->LogToFile) {
|
||
|
|
||
|
FastIoFileDump( pLogRecord->DeviceType,
|
||
|
pLogRecord->SequenceNumber,
|
||
|
pLogRecord->Name,
|
||
|
nameLength,
|
||
|
pRecordFastIo,
|
||
|
context->OutputFile);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case RECORD_TYPE_FS_FILTER_OP:
|
||
|
|
||
|
//
|
||
|
// We've got a FsFilter operation record, so output this
|
||
|
// data correctly.
|
||
|
//
|
||
|
|
||
|
pRecordFsFilterOp = &(pLogRecord->Record.RecordFsFilterOp);
|
||
|
|
||
|
if (context->LogToScreen) {
|
||
|
|
||
|
FsFilterOperationScreenDump( pLogRecord->DeviceType,
|
||
|
pLogRecord->SequenceNumber,
|
||
|
pLogRecord->Name,
|
||
|
nameLength,
|
||
|
pRecordFsFilterOp );
|
||
|
|
||
|
}
|
||
|
|
||
|
if (context->LogToFile) {
|
||
|
|
||
|
FsFilterOperationFileDump( pLogRecord->DeviceType,
|
||
|
pLogRecord->SequenceNumber,
|
||
|
pLogRecord->Name,
|
||
|
nameLength,
|
||
|
pRecordFsFilterOp,
|
||
|
context->OutputFile );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
|
||
|
printf("Filmon: Unknown log record type\n");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The RecordType could also designate that we are out of memory
|
||
|
// or hit our program defined memory limit, so check for these
|
||
|
// cases.
|
||
|
//
|
||
|
|
||
|
if (pLogRecord->RecordType & RECORD_TYPE_OUT_OF_MEMORY) {
|
||
|
|
||
|
if (context->LogToScreen) {
|
||
|
|
||
|
printf("M %08X SYSTEM OUT OF MEMORY\n", pLogRecord->SequenceNumber);
|
||
|
}
|
||
|
|
||
|
if (context->LogToFile) {
|
||
|
|
||
|
fprintf(context->OutputFile, "M:\t%u", pLogRecord->SequenceNumber);
|
||
|
}
|
||
|
|
||
|
} else if (pLogRecord->RecordType & RECORD_TYPE_EXCEED_MEMORY_ALLOWANCE) {
|
||
|
|
||
|
if (context->LogToScreen) {
|
||
|
|
||
|
printf("M %08X EXCEEDED MEMORY ALLOWANCE\n", pLogRecord->SequenceNumber);
|
||
|
}
|
||
|
|
||
|
if (context->LogToFile) {
|
||
|
|
||
|
fprintf(context->OutputFile, "M:\t%u", pLogRecord->SequenceNumber);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
DWORD WINAPI
|
||
|
VerifyCurrentLogRecords (
|
||
|
PLOG_CONTEXT Context,
|
||
|
PEXPECTED_OPERATION ExpectedOps
|
||
|
)
|
||
|
{
|
||
|
CHAR buffer[BUFFER_SIZE];
|
||
|
DWORD bytesReturned = 0;
|
||
|
BOOL bResult;
|
||
|
DWORD result;
|
||
|
PLOG_RECORD pLogRecord;
|
||
|
BOOL askForMore = TRUE;
|
||
|
BOOL testPassed = FALSE;
|
||
|
ULONG currentOp = 0;
|
||
|
#ifdef USE_DO_HINT
|
||
|
BOOL keepVerifying = TRUE;
|
||
|
#else
|
||
|
BOOL seenFirstOp = FALSE;
|
||
|
#endif /* USE_DO_HINT */
|
||
|
|
||
|
while (askForMore) {
|
||
|
|
||
|
//
|
||
|
// Check to see if we should shut down
|
||
|
//
|
||
|
|
||
|
if (Context->CleaningUp) {
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Request log data from filespy
|
||
|
//
|
||
|
|
||
|
bResult = DeviceIoControl( Context->Device,
|
||
|
IOTEST_GetLog,
|
||
|
NULL,
|
||
|
0,
|
||
|
buffer,
|
||
|
BUFFER_SIZE,
|
||
|
&bytesReturned,
|
||
|
NULL);
|
||
|
|
||
|
if (!bResult) {
|
||
|
|
||
|
result = GetLastError();
|
||
|
printf("ERROR controlling device: 0x%x\n", result);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Buffer is filled with a series of LOG_RECORD structures, one
|
||
|
// right after another. Each LOG_RECORD says how long it is, so
|
||
|
// we know where the next LOG_RECORD begins.
|
||
|
//
|
||
|
|
||
|
pLogRecord = (PLOG_RECORD) buffer;
|
||
|
|
||
|
//
|
||
|
// Logic to write record to screen and/or file
|
||
|
//
|
||
|
|
||
|
while ((BYTE *) pLogRecord < buffer + bytesReturned) {
|
||
|
|
||
|
PRECORD_IRP pRecordIrp;
|
||
|
|
||
|
DumpLogRecord( pLogRecord, Context );
|
||
|
|
||
|
switch (GET_RECORD_TYPE(pLogRecord)) {
|
||
|
case RECORD_TYPE_IRP:
|
||
|
|
||
|
pRecordIrp = &(pLogRecord->Record.RecordIrp);
|
||
|
|
||
|
#ifdef USE_DO_HINT
|
||
|
if (keepVerifying) {
|
||
|
|
||
|
if (pRecordIrp->IrpMajor == ExpectedOps[currentOp].Op) {
|
||
|
if(pLogRecord->DeviceType != ExpectedOps[currentOp].Device) {
|
||
|
|
||
|
keepVerifying = FALSE;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
currentOp ++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
//
|
||
|
// If we are not using the DeviceObject hint, we expect to
|
||
|
// see log entries from both the TOP and BOTTOM filters
|
||
|
// for each expected operation. So that we don't have to
|
||
|
// redefine the ExpectedOperation array, just ignore the
|
||
|
// device in the array and check to make sure that you see
|
||
|
// a log record for the TOP_FILTER then the BOTTOM_FILTER for
|
||
|
// each operation in the array.
|
||
|
//
|
||
|
|
||
|
if (!seenFirstOp) {
|
||
|
|
||
|
if ((pLogRecord->DeviceType == TOP_FILTER) &&
|
||
|
(pRecordIrp->IrpMajor == ExpectedOps[currentOp].Op)) {
|
||
|
|
||
|
seenFirstOp = TRUE;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if ((pLogRecord->DeviceType == BOTTOM_FILTER) &&
|
||
|
(pRecordIrp->IrpMajor == ExpectedOps[currentOp].Op)) {
|
||
|
|
||
|
seenFirstOp = FALSE;
|
||
|
currentOp ++;
|
||
|
}
|
||
|
}
|
||
|
#endif /* USE_DO_HINT */
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
|
||
|
//
|
||
|
// ignore
|
||
|
//
|
||
|
;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Move to next LOG_RECORD
|
||
|
//
|
||
|
|
||
|
pLogRecord = (PLOG_RECORD) (((BYTE *) pLogRecord) + pLogRecord->Length);
|
||
|
}
|
||
|
|
||
|
if (bytesReturned == 0) {
|
||
|
|
||
|
askForMore = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ExpectedOps[currentOp].Op == IRP_MJ_MAXIMUM_FUNCTION + 1) {
|
||
|
|
||
|
testPassed = TRUE;
|
||
|
}
|
||
|
|
||
|
if (testPassed) {
|
||
|
|
||
|
printf( "User log verification:\tPASSED - Expected operations seen.\n" );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
printf( "User log verification:\tFAILED - Expected operations NOT seen.\n" );
|
||
|
}
|
||
|
|
||
|
return testPassed;
|
||
|
}
|
||
|
|
||
|
DWORD WINAPI
|
||
|
RetrieveLogRecords (
|
||
|
LPVOID lpParameter
|
||
|
)
|
||
|
{
|
||
|
PLOG_CONTEXT context = (PLOG_CONTEXT)lpParameter;
|
||
|
CHAR buffer[BUFFER_SIZE];
|
||
|
DWORD bytesReturned = 0;
|
||
|
BOOL bResult;
|
||
|
DWORD result;
|
||
|
PLOG_RECORD pLogRecord;
|
||
|
|
||
|
printf("Log: Starting up\n");
|
||
|
|
||
|
while (TRUE) {
|
||
|
|
||
|
//
|
||
|
// Check to see if we should shut down
|
||
|
//
|
||
|
|
||
|
if (context->CleaningUp) {
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Request log data from filespy
|
||
|
//
|
||
|
|
||
|
bResult = DeviceIoControl( context->Device,
|
||
|
IOTEST_GetLog,
|
||
|
NULL,
|
||
|
0,
|
||
|
buffer,
|
||
|
BUFFER_SIZE,
|
||
|
&bytesReturned,
|
||
|
NULL);
|
||
|
|
||
|
if (!bResult) {
|
||
|
|
||
|
result = GetLastError();
|
||
|
printf("ERROR controlling device: 0x%x\n", result);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Buffer is filled with a series of LOG_RECORD structures, one
|
||
|
// right after another. Each LOG_RECORD says how long it is, so
|
||
|
// we know where the next LOG_RECORD begins.
|
||
|
//
|
||
|
|
||
|
pLogRecord = (PLOG_RECORD) buffer;
|
||
|
|
||
|
//
|
||
|
// Logic to write record to screen and/or file
|
||
|
//
|
||
|
|
||
|
while ((BYTE *) pLogRecord < buffer + bytesReturned) {
|
||
|
|
||
|
|
||
|
DumpLogRecord( pLogRecord, context );
|
||
|
|
||
|
//
|
||
|
// Move to next LOG_RECORD
|
||
|
//
|
||
|
|
||
|
pLogRecord = (PLOG_RECORD) (((BYTE *) pLogRecord) + pLogRecord->Length);
|
||
|
}
|
||
|
|
||
|
if (bytesReturned == 0) {
|
||
|
|
||
|
Sleep( 500 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
printf("Log: Shutting down\n");
|
||
|
ReleaseSemaphore(context->ShutDown, 1, NULL);
|
||
|
printf("Log: All done\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PrintIrpCode (
|
||
|
UCHAR MajorCode,
|
||
|
UCHAR MinorCode,
|
||
|
ULONG FsControlCode,
|
||
|
FILE *OutputFile,
|
||
|
BOOLEAN PrintMajorCode
|
||
|
)
|
||
|
{
|
||
|
CHAR irpMajorString[OPERATION_NAME_BUFFER_SIZE];
|
||
|
CHAR irpMinorString[OPERATION_NAME_BUFFER_SIZE];
|
||
|
CHAR formatBuf[OPERATION_NAME_BUFFER_SIZE*2];
|
||
|
|
||
|
|
||
|
GetIrpName(MajorCode,MinorCode,FsControlCode,irpMajorString,irpMinorString);
|
||
|
|
||
|
if (OutputFile) {
|
||
|
|
||
|
sprintf(formatBuf, "%s %s", irpMajorString, irpMinorString);
|
||
|
fprintf(OutputFile, "\t%-50s", formatBuf);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if (PrintMajorCode) {
|
||
|
|
||
|
printf("%-31s ", irpMajorString);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if (irpMinorString[0] != 0) {
|
||
|
|
||
|
printf(" %-35s\n",
|
||
|
irpMinorString);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PrintFastIoType (
|
||
|
FASTIO_TYPE Code,
|
||
|
FILE *OutputFile
|
||
|
)
|
||
|
{
|
||
|
CHAR outputString[OPERATION_NAME_BUFFER_SIZE];
|
||
|
|
||
|
GetFastioName(Code,outputString);
|
||
|
|
||
|
if (OutputFile) {
|
||
|
|
||
|
fprintf(OutputFile, "%-50s", outputString);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
printf("%-31s ", outputString);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PrintFsFilterOperation (
|
||
|
UCHAR Operation,
|
||
|
FILE *OutputFile
|
||
|
)
|
||
|
{
|
||
|
CHAR outputString[OPERATION_NAME_BUFFER_SIZE];
|
||
|
|
||
|
GetFsFilterOperationName(Operation,outputString);
|
||
|
|
||
|
if (OutputFile) {
|
||
|
|
||
|
fprintf( OutputFile, "%-50s", outputString );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
printf( "%-31s ", outputString );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ULONG
|
||
|
FormatSystemTime (
|
||
|
SYSTEMTIME *SystemTime,
|
||
|
PWCHAR Buffer,
|
||
|
ULONG BufferLength
|
||
|
)
|
||
|
/*++
|
||
|
Routine Name:
|
||
|
|
||
|
FormatSystemTime
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Formats the values in a SystemTime struct into the buffer
|
||
|
passed in. The resulting string is NULL terminated. The format
|
||
|
for the time is:
|
||
|
hours:minutes:seconds:milliseconds
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SystemTime - the struct to format
|
||
|
Buffer - the buffer to place the formatted time in
|
||
|
BufferLength - the size of the buffer in characters
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The number of characters returned in Buffer.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PWCHAR writePosition;
|
||
|
ULONG returnLength = 0;
|
||
|
|
||
|
writePosition = Buffer;
|
||
|
|
||
|
if (BufferLength < TIME_BUFFER_LENGTH) {
|
||
|
|
||
|
//
|
||
|
// Buffer is too short so exit
|
||
|
//
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
returnLength = swprintf( Buffer,
|
||
|
L"%02d:%02d:%02d:%03d",
|
||
|
SystemTime->wHour,
|
||
|
SystemTime->wMinute,
|
||
|
SystemTime->wSecond,
|
||
|
SystemTime->wMilliseconds);
|
||
|
|
||
|
return returnLength;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
IrpFileDump (
|
||
|
IOTEST_DEVICE_TYPE DeviceType,
|
||
|
ULONG SequenceNumber,
|
||
|
PWCHAR Name,
|
||
|
ULONG NameLength,
|
||
|
PRECORD_IRP RecordIrp,
|
||
|
FILE *File,
|
||
|
ULONG VerbosityFlags
|
||
|
)
|
||
|
/*++
|
||
|
Routine Name:
|
||
|
|
||
|
IrpFileDump
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Prints a Irp log record to the specified file. The output is in a tab
|
||
|
delimited format with the fields in the following order:
|
||
|
|
||
|
SequenceNumber, OriginatingTime, CompletionTime, IrpMajor, IrpMinor,
|
||
|
IrpFlags, NoCache, Paging I/O, Synchronous, Synchronous paging, FileName,
|
||
|
ReturnStatus, FileName
|
||
|
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SequenceNumber - the sequence number for this log record
|
||
|
Name - the name of the file that this Irp relates to
|
||
|
NameLength - the length of Name in bytes
|
||
|
RecordIrp - the Irp record to print
|
||
|
File - the file to print to
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
FILETIME localTime;
|
||
|
SYSTEMTIME systemTime;
|
||
|
WCHAR time[TIME_BUFFER_LENGTH];
|
||
|
|
||
|
switch (DeviceType) {
|
||
|
case TOP_FILTER:
|
||
|
fprintf(File, "TOP\tI\t%08X", SequenceNumber);
|
||
|
break;
|
||
|
case BOTTOM_FILTER:
|
||
|
fprintf(File, "BOT\tI\t%08X", SequenceNumber);
|
||
|
break;
|
||
|
default:
|
||
|
fprintf(File, "UNK\tI\t%08X", SequenceNumber);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert originating time
|
||
|
//
|
||
|
|
||
|
FileTimeToLocalFileTime( (FILETIME *)&(RecordIrp->OriginatingTime), &localTime );
|
||
|
FileTimeToSystemTime( &localTime, &systemTime );
|
||
|
|
||
|
if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
|
||
|
|
||
|
fprintf( File, "\t%-12S", time );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
fprintf( File, "\t%-12S", TIME_ERROR );
|
||
|
}
|
||
|
|
||
|
fprintf( File, "\t%8x.%-4x ", RecordIrp->ProcessId, RecordIrp->ThreadId );
|
||
|
|
||
|
PrintIrpCode( RecordIrp->IrpMajor, RecordIrp->IrpMinor, (ULONG)(ULONG_PTR)RecordIrp->Argument3, File, TRUE );
|
||
|
|
||
|
fprintf( File, "\t%08p", RecordIrp->FileObject );
|
||
|
|
||
|
//
|
||
|
// Interpret set flags
|
||
|
//
|
||
|
|
||
|
fprintf( File, "\t%08lx ", RecordIrp->IrpFlags );
|
||
|
fprintf( File, "%s", (RecordIrp->IrpFlags & IRP_NOCACHE) ? "N":"-" );
|
||
|
fprintf( File, "%s", (RecordIrp->IrpFlags & IRP_PAGING_IO) ? "P":"-" );
|
||
|
fprintf( File, "%s", (RecordIrp->IrpFlags & IRP_SYNCHRONOUS_API) ? "S":"-" );
|
||
|
fprintf( File, "%s", (RecordIrp->IrpFlags & IRP_SYNCHRONOUS_PAGING_IO) ? "Y":"-" );
|
||
|
|
||
|
if (FlagOn( VerbosityFlags, FS_VF_DUMP_PARAMETERS )) {
|
||
|
|
||
|
fprintf( File,
|
||
|
"%p %p %p %p ",
|
||
|
RecordIrp->Argument1,
|
||
|
RecordIrp->Argument2,
|
||
|
RecordIrp->Argument3,
|
||
|
RecordIrp->Argument4 );
|
||
|
|
||
|
if (IRP_MJ_CREATE == RecordIrp->IrpMajor) {
|
||
|
|
||
|
fprintf( File, "DesiredAccess->%08lx ", RecordIrp->DesiredAccess );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fprintf( File, "\t%.*S", NameLength/sizeof(WCHAR), Name );
|
||
|
fprintf( File, "\n" );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
IrpScreenDump (
|
||
|
IOTEST_DEVICE_TYPE DeviceType,
|
||
|
ULONG SequenceNumber,
|
||
|
PWCHAR Name,
|
||
|
ULONG NameLength,
|
||
|
PRECORD_IRP RecordIrp,
|
||
|
ULONG VerbosityFlags
|
||
|
)
|
||
|
/*++
|
||
|
Routine Name:
|
||
|
|
||
|
IrpScreenDump
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Prints a Irp log record to the screen in the following order:
|
||
|
SequenceNumber, OriginatingTime, CompletionTime, IrpMajor, IrpMinor,
|
||
|
IrpFlags, NoCache, Paging I/O, Synchronous, Synchronous paging,
|
||
|
FileName, ReturnStatus, FileName
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SequenceNumber - the sequence number for this log record
|
||
|
Name - the file name to which this Irp relates
|
||
|
NameLength - the length of Name in bytes
|
||
|
RecordIrp - the Irp record to print
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
FILETIME localTime;
|
||
|
SYSTEMTIME systemTime;
|
||
|
WCHAR time[TIME_BUFFER_LENGTH];
|
||
|
|
||
|
switch (DeviceType) {
|
||
|
case TOP_FILTER:
|
||
|
printf("TOP I %08X", SequenceNumber);
|
||
|
break;
|
||
|
case BOTTOM_FILTER:
|
||
|
printf("BOT I %08X", SequenceNumber);
|
||
|
break;
|
||
|
default:
|
||
|
printf("UNK I %08X", SequenceNumber);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert originating time
|
||
|
//
|
||
|
|
||
|
FileTimeToLocalFileTime( (FILETIME *)&(RecordIrp->OriginatingTime), &localTime );
|
||
|
FileTimeToSystemTime( &localTime, &systemTime );
|
||
|
|
||
|
if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
|
||
|
|
||
|
printf( "%-12S ", time );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
printf( "%-12S ", TIME_ERROR );
|
||
|
}
|
||
|
|
||
|
printf( "%8x.%-4x ", RecordIrp->ProcessId, RecordIrp->ThreadId );
|
||
|
|
||
|
PrintIrpCode( RecordIrp->IrpMajor, RecordIrp->IrpMinor, (ULONG)(ULONG_PTR)RecordIrp->Argument3, NULL, TRUE );
|
||
|
|
||
|
printf( "%08p ", RecordIrp->FileObject );
|
||
|
|
||
|
//
|
||
|
// Interpret set flags
|
||
|
//
|
||
|
|
||
|
printf( "%08lx ", RecordIrp->IrpFlags );
|
||
|
printf( "%s", (RecordIrp->IrpFlags & IRP_NOCACHE) ? "N":"-" );
|
||
|
printf( "%s", (RecordIrp->IrpFlags & IRP_PAGING_IO) ? "P":"-" );
|
||
|
printf( "%s", (RecordIrp->IrpFlags & IRP_SYNCHRONOUS_API) ? "S":"-" );
|
||
|
printf( "%s ", (RecordIrp->IrpFlags & IRP_SYNCHRONOUS_PAGING_IO) ? "Y":"-" );
|
||
|
|
||
|
if (FlagOn( VerbosityFlags, FS_VF_DUMP_PARAMETERS )) {
|
||
|
|
||
|
printf( "%p %p %p %p ",
|
||
|
RecordIrp->Argument1,
|
||
|
RecordIrp->Argument2,
|
||
|
RecordIrp->Argument3,
|
||
|
RecordIrp->Argument4 );
|
||
|
|
||
|
if (IRP_MJ_CREATE == RecordIrp->IrpMajor) {
|
||
|
|
||
|
printf( "DesiredAccess->%08lx ", RecordIrp->DesiredAccess );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
printf( "%.*S", NameLength/sizeof(WCHAR), Name );
|
||
|
printf( "\n" );
|
||
|
PrintIrpCode( RecordIrp->IrpMajor, RecordIrp->IrpMinor, (ULONG)(ULONG_PTR)RecordIrp->Argument3, NULL, FALSE );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FastIoFileDump (
|
||
|
IOTEST_DEVICE_TYPE DeviceType,
|
||
|
ULONG SequenceNumber,
|
||
|
PWCHAR Name,
|
||
|
ULONG NameLength,
|
||
|
PRECORD_FASTIO RecordFastIo,
|
||
|
FILE *File
|
||
|
)
|
||
|
/*++
|
||
|
Routine Name:
|
||
|
|
||
|
FastIoFileDump
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Prints a FastIo log record to the specified file. The output is in a tab
|
||
|
delimited format with the fields in the following order:
|
||
|
SequenceNumber, StartTime, CompletionTime, Fast I/O Type, FileName,
|
||
|
Length, Wait, ReturnStatus, FileName
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SequenceNumber - the sequence number for this log record
|
||
|
Name - the name of the file referenced by this Fast I/O operation
|
||
|
NameLength - the length of name in bytes
|
||
|
RecordFastIo - the FastIo record to print
|
||
|
File - the file to print to
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
SYSTEMTIME systemTime;
|
||
|
FILETIME localTime;
|
||
|
WCHAR time[TIME_BUFFER_LENGTH];
|
||
|
|
||
|
switch (DeviceType) {
|
||
|
case TOP_FILTER:
|
||
|
fprintf(File, "TOP\tF\t%08X", SequenceNumber);
|
||
|
break;
|
||
|
case BOTTOM_FILTER:
|
||
|
fprintf(File, "BOT\tF\t%08X", SequenceNumber);
|
||
|
break;
|
||
|
default:
|
||
|
fprintf(File, "UNK\tF\t%08X", SequenceNumber);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert start time
|
||
|
//
|
||
|
|
||
|
FileTimeToLocalFileTime( (FILETIME *)&(RecordFastIo->StartTime), &localTime );
|
||
|
FileTimeToSystemTime( &localTime, &systemTime );
|
||
|
|
||
|
if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
|
||
|
|
||
|
fprintf( File, "\t%-12S", time );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
fprintf( File, "\t%-12S", TIME_ERROR );
|
||
|
}
|
||
|
|
||
|
fprintf( File, "\t%8x.%-4x ", RecordFastIo->ProcessId, RecordFastIo->ThreadId );
|
||
|
|
||
|
fprintf( File, "\t" );
|
||
|
PrintFastIoType( RecordFastIo->Type, File );
|
||
|
|
||
|
fprintf( File, "\t%08p", RecordFastIo->FileObject );
|
||
|
|
||
|
fprintf( File, "\t%s", (RecordFastIo->Wait)?"T":"F" );
|
||
|
fprintf( File, "\t%08x", RecordFastIo->Length );
|
||
|
fprintf( File, "\t%016I64x ", RecordFastIo->FileOffset );
|
||
|
|
||
|
fprintf( File, "\t%.*S", NameLength/sizeof(WCHAR), Name );
|
||
|
fprintf( File, "\n" );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FastIoScreenDump (
|
||
|
IOTEST_DEVICE_TYPE DeviceType,
|
||
|
ULONG SequenceNumber,
|
||
|
PWCHAR Name,
|
||
|
ULONG NameLength,
|
||
|
PRECORD_FASTIO RecordFastIo
|
||
|
)
|
||
|
/*++
|
||
|
Routine Name:
|
||
|
|
||
|
FastIoScreenDump
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Prints a FastIo log record to the screen in the following order:
|
||
|
SequenceNumber, StartTime, CompletionTime, Fast I/O Type, FileName,
|
||
|
Length, Wait, ReturnStatus, FileName
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SequenceNumber - the sequence number for this log record
|
||
|
Name - the name of the file referenced by this Fast I/O operation
|
||
|
NameLength - the length of name in bytes
|
||
|
RecordIrp - the Irp record to print
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
SYSTEMTIME systemTime;
|
||
|
FILETIME localTime;
|
||
|
WCHAR time[TIME_BUFFER_LENGTH];
|
||
|
|
||
|
switch (DeviceType) {
|
||
|
case TOP_FILTER:
|
||
|
printf("TOP F %08X", SequenceNumber);
|
||
|
break;
|
||
|
case BOTTOM_FILTER:
|
||
|
printf("BOT F %08X", SequenceNumber);
|
||
|
break;
|
||
|
default:
|
||
|
printf("UNK F %08X", SequenceNumber);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert start time
|
||
|
//
|
||
|
|
||
|
FileTimeToLocalFileTime( (FILETIME *)&(RecordFastIo->StartTime), &localTime );
|
||
|
FileTimeToSystemTime( &localTime, &systemTime );
|
||
|
|
||
|
if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
|
||
|
|
||
|
printf( "%-12S ", time );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
printf( "%-12S ", TIME_ERROR );
|
||
|
}
|
||
|
|
||
|
printf( "%8x.%-4x ", RecordFastIo->ProcessId, RecordFastIo->ThreadId );
|
||
|
|
||
|
PrintFastIoType( RecordFastIo->Type, NULL );
|
||
|
|
||
|
printf( "%08p ", RecordFastIo->FileObject );
|
||
|
|
||
|
printf( "%s ", (RecordFastIo->Wait)?"T":"F" );
|
||
|
printf( "%08x ", RecordFastIo->Length );
|
||
|
printf( "%016I64x ", RecordFastIo->FileOffset );
|
||
|
|
||
|
printf( "%.*S", NameLength/sizeof(WCHAR), Name );
|
||
|
printf ("\n" );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FsFilterOperationFileDump (
|
||
|
IOTEST_DEVICE_TYPE DeviceType,
|
||
|
ULONG SequenceNumber,
|
||
|
PWCHAR Name,
|
||
|
ULONG NameLength,
|
||
|
PRECORD_FS_FILTER_OPERATION RecordFsFilterOp,
|
||
|
FILE *File
|
||
|
)
|
||
|
/*++
|
||
|
Routine Name:
|
||
|
|
||
|
FsFilterOperationFileDump
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Prints a FsFilterOperation log record to the specified file. The output is in a tab
|
||
|
delimited format with the fields in the following order:
|
||
|
|
||
|
SequenceNumber, OriginatingTime, CompletionTime, ProcessId, ThreadId,
|
||
|
Operation, FileObject, ReturnStatus, FileName
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SequenceNumber - the sequence number for this log record
|
||
|
Name - the name of the file that this operation relates to
|
||
|
NameLength - the length of Name in bytes
|
||
|
RecordFsFilterOp - the FsFilter operation record to print
|
||
|
File - the file to print to
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
FILETIME localTime;
|
||
|
SYSTEMTIME systemTime;
|
||
|
WCHAR time[TIME_BUFFER_LENGTH];
|
||
|
|
||
|
switch (DeviceType) {
|
||
|
case TOP_FILTER:
|
||
|
fprintf(File, "TOP\tO\t%08X", SequenceNumber);
|
||
|
break;
|
||
|
case BOTTOM_FILTER:
|
||
|
fprintf(File, "BOT\tO\t%08X", SequenceNumber);
|
||
|
break;
|
||
|
default:
|
||
|
fprintf(File, "UNK\tO\t%08X", SequenceNumber);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert originating time
|
||
|
//
|
||
|
|
||
|
FileTimeToLocalFileTime( (FILETIME *)&(RecordFsFilterOp->OriginatingTime), &localTime );
|
||
|
FileTimeToSystemTime( &localTime, &systemTime );
|
||
|
|
||
|
if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
|
||
|
|
||
|
fprintf( File, "\t%-12S", time );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
fprintf( File, "\t%-12S", TIME_ERROR );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Output the process and thread id
|
||
|
//
|
||
|
|
||
|
fprintf( File, "\t%8x.%-4x ", RecordFsFilterOp->ProcessId, RecordFsFilterOp->ThreadId );
|
||
|
|
||
|
//
|
||
|
// Output the FsFilter operation parameters
|
||
|
//
|
||
|
|
||
|
PrintFsFilterOperation( RecordFsFilterOp->FsFilterOperation, File );
|
||
|
|
||
|
fprintf( File, "\t%08p", RecordFsFilterOp->FileObject );
|
||
|
fprintf( File, "\t%.*S", NameLength/sizeof(WCHAR), Name );
|
||
|
fprintf( File, "\n" );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FsFilterOperationScreenDump (
|
||
|
IOTEST_DEVICE_TYPE DeviceType,
|
||
|
ULONG SequenceNumber,
|
||
|
PWCHAR Name,
|
||
|
ULONG NameLength,
|
||
|
PRECORD_FS_FILTER_OPERATION RecordFsFilterOp
|
||
|
)
|
||
|
/*++
|
||
|
Routine Name:
|
||
|
|
||
|
FsFilterOperationScreenDump
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Prints a FsFilterOperation log record to the screen in the following order:
|
||
|
|
||
|
SequenceNumber, OriginatingTime, CompletionTime, ProcessId, ThreadId,
|
||
|
Operation, FileObject, ReturnStatus, FileName
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SequenceNumber - the sequence number for this log record
|
||
|
Name - the file name to which this Irp relates
|
||
|
NameLength - the length of name in bytes
|
||
|
RecordFsFilterOp - the FsFilterOperation record to print
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
FILETIME localTime;
|
||
|
SYSTEMTIME systemTime;
|
||
|
WCHAR time[TIME_BUFFER_LENGTH];
|
||
|
|
||
|
switch (DeviceType) {
|
||
|
case TOP_FILTER:
|
||
|
printf("TOP O %08X", SequenceNumber);
|
||
|
break;
|
||
|
case BOTTOM_FILTER:
|
||
|
printf("BOT O %08X", SequenceNumber);
|
||
|
break;
|
||
|
default:
|
||
|
printf("UNK O %08X", SequenceNumber);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert originating time
|
||
|
//
|
||
|
|
||
|
FileTimeToLocalFileTime( (FILETIME *)&(RecordFsFilterOp->OriginatingTime), &localTime );
|
||
|
FileTimeToSystemTime( &localTime, &systemTime );
|
||
|
|
||
|
if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
|
||
|
|
||
|
printf( "%-12S ", time );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
printf( "%-12S ", TIME_ERROR );
|
||
|
}
|
||
|
|
||
|
printf( "%8x.%-4x ", RecordFsFilterOp->ProcessId, RecordFsFilterOp->ThreadId );
|
||
|
|
||
|
PrintFsFilterOperation( RecordFsFilterOp->FsFilterOperation, NULL );
|
||
|
|
||
|
//
|
||
|
// Print FsFilter operation specific values.
|
||
|
//
|
||
|
|
||
|
printf( "%08p ", RecordFsFilterOp->FileObject );
|
||
|
printf( "%.*S", NameLength/sizeof(WCHAR),Name );
|
||
|
printf( "\n" );
|
||
|
}
|
||
|
|