|
|
/*++
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" ); }
|