📄 filemon.c
字号:
"FileFsQuotaSetInformation",
"FileFsControlQueryInformation",
"FileFsControlSetInformation",
"FileFsMaximumInformation",
};
//
// These are Win2K Plug-and-Play minor IRP codes
//
CHAR *PnpMinorCode[] = {
"IRP_MN_START_DEVICE",
"IRP_MN_QUERY_REMOVE_DEVICE",
"IRP_MN_REMOVE_DEVICE",
"IRP_MN_CANCEL_REMOVE_DEVICE",
"IRP_MN_STOP_DEVICE",
"IRP_MN_QUERY_STOP_DEVICE",
"IRP_MN_CANCEL_STOP_DEVICE",
"IRP_MN_QUERY_DEVICE_RELATIONS",
"IRP_MN_QUERY_INTERFACE",
"IRP_MN_QUERY_CAPABILITIES",
"IRP_MN_QUERY_RESOURCES",
"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
"IRP_MN_QUERY_DEVICE_TEXT",
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
"IRP_MN_READ_CONFIG",
"IRP_MN_WRITE_CONFIG",
"IRP_MN_EJECT",
"IRP_MN_SET_LOCK",
"IRP_MN_QUERY_ID",
"IRP_MN_QUERY_PNP_DEVICE_STATE",
"IRP_MN_QUERY_BUS_INFORMATION",
"IRP_MN_DEVICE_USAGE_NOTIFICATION",
"IRP_MN_SURPRISE_REMOVAL",
"IRP_MN_QUERY_LEGACY_BUS_INFORMATION",
};
#define MAX_NTFS_METADATA_FILE 11
CHAR *NtfsMetadataFileNames[] = {
"$Mft",
"$MftMirr",
"$LogFile",
"$Volume",
"$AttrDef",
"$Root",
"$Bitmap",
"$Boot",
"$BadClus",
"$Secure",
"$UpCase",
"$Extend"
};
//
// This Filemon's Fast I/O dispatch table. Note that NT assumes that
// file system drivers support some Fast I/O calls, so this table must
// be present for an file system filter driver
//
FAST_IO_DISPATCH FastIOHook = {
sizeof(FAST_IO_DISPATCH),
FilemonFastIoCheckifPossible,
FilemonFastIoRead,
FilemonFastIoWrite,
FilemonFastIoQueryBasicInfo,
FilemonFastIoQueryStandardInfo,
FilemonFastIoLock,
FilemonFastIoUnlockSingle,
FilemonFastIoUnlockAll,
FilemonFastIoUnlockAllByKey,
FilemonFastIoDeviceControl,
FilemonFastIoAcquireFile,
FilemonFastIoReleaseFile,
FilemonFastIoDetachDevice,
//
// new for NT 4.0
//
FilemonFastIoQueryNetworkOpenInfo,
FilemonFastIoAcquireForModWrite,
FilemonFastIoMdlRead,
FilemonFastIoMdlReadComplete,
FilemonFastIoPrepareMdlWrite,
FilemonFastIoMdlWriteComplete,
FilemonFastIoReadCompressed,
FilemonFastIoWriteCompressed,
FilemonFastIoMdlReadCompleteCompressed,
FilemonFastIoMdlWriteCompleteCompressed,
FilemonFastIoQueryOpen,
FilemonFastIoReleaseForModWrite,
FilemonFastIoAcquireForCcFlush,
FilemonFastIoReleaseForCcFlush
};
//----------------------------------------------------------------------
// P A T T E R N M A T C H I N G R O U T I N E S
//----------------------------------------------------------------------
//----------------------------------------------------------------------
//
// MatchOkay
//
// Only thing left after compare is more mask. This routine makes
// sure that its a valid wild card ending so that its really a match.
//
//----------------------------------------------------------------------
BOOLEAN
MatchOkay(
PCHAR Pattern
)
{
//
// If pattern isn't empty, it must be a wildcard
//
if( *Pattern && *Pattern != '*' ) {
return FALSE;
}
//
// Matched
//
return TRUE;
}
//----------------------------------------------------------------------
//
// MatchWithPattern
//
// Performs nifty wildcard comparison.
//
//----------------------------------------------------------------------
BOOLEAN
MatchWithPattern(
PCHAR Pattern,
PCHAR Name
)
{
char matchchar;
//
// End of pattern?
//
if( !*Pattern ) {
return FALSE;
}
//
// If we hit a wild card, do recursion
//
if( *Pattern == '*' ) {
Pattern++;
while( *Name && *Pattern ) {
matchchar = *Name;
if( matchchar >= 'a' &&
matchchar <= 'z' ) {
matchchar -= 'a' - 'A';
}
//
// See if this substring matches
//
if( *Pattern == matchchar ) {
if( MatchWithPattern( Pattern+1, Name+1 )) {
return TRUE;
}
}
//
// Try the next substring
//
Name++;
}
//
// See if match condition was met
//
return MatchOkay( Pattern );
}
//
// Do straight compare until we hit a wild card
//
while( *Name && *Pattern != '*' ) {
matchchar = *Name;
if( matchchar >= 'a' &&
matchchar <= 'z' ) {
matchchar -= 'a' - 'A';
}
if( *Pattern == matchchar ) {
Pattern++;
Name++;
} else {
return FALSE;
}
}
//
// If not done, recurse
//
if( *Name ) {
return MatchWithPattern( Pattern, Name );
}
//
// Make sure its a match
//
return MatchOkay( Pattern );
}
//----------------------------------------------------------------------
// B U F F E R M A N A G E M E N T
//----------------------------------------------------------------------
//----------------------------------------------------------------------
//
// FilemonFreeLog
//
// Frees all the data output buffers that we have currently allocated.
//
//----------------------------------------------------------------------
VOID
FilemonFreeLog(
VOID
)
{
PLOG_BUF prev;
//
// Just traverse the list of allocated output buffers
//
while( CurrentLog ) {
prev = CurrentLog->Next;
ExFreePool( CurrentLog );
CurrentLog = prev;
}
}
//----------------------------------------------------------------------
//
// FilemonAllocateLog
//
// Called when the current buffer has filled up. This allocates a new
// buffer and stick it at the head (newest) entry of our buffer list.
//
//----------------------------------------------------------------------
void
FilemonAllocateLog(
VOID
)
{
PLOG_BUF prev = CurrentLog, newLog;
//
// If we've already allocated the allowed number of buffers, just
// reuse the current one. This will result in output records being
// lost, but it takes ALOT of file system activity to cause this.
//
if( MaxLog == NumLog ) {
DbgPrint(("Filemon ***** Dropping records at sequence number %d\n", Sequence ));
CurrentLog->Len = 0;
return;
}
DbgPrint(("FilemonAllocateLog: num: %d max: %d\n", NumLog, MaxLog ));
//
// If the output buffer we currently are using is empty, just
// use it.
//
if( !CurrentLog->Len ) {
return;
}
//
// Allocate a new output buffer
//
newLog = ExAllocatePool( NonPagedPool, sizeof(*CurrentLog) );
if( newLog ) {
//
// Allocation was successful so add the buffer to the list
// of allocated buffers and increment the buffer count.
//
CurrentLog = newLog;
CurrentLog->Len = 0;
CurrentLog->Next = prev;
NumLog++;
} else {
//
// The allocation failed - just reuse the current buffer
//
CurrentLog->Len = 0;
}
}
//----------------------------------------------------------------------
//
// FilemonGetOldestLog
//
// Traverse the list of allocated buffers to find the last one, which
// will be the oldest (as we want to return the oldest data to the GUI
// first).
//
//----------------------------------------------------------------------
PLOG_BUF
FilemonGetOldestLog(
VOID
)
{
PLOG_BUF ptr = CurrentLog, prev = NULL;
//
// Traverse the list
//
while( ptr->Next ) {
ptr = (prev = ptr)->Next;
}
//
// Remove the buffer from the list
//
if( prev ) {
prev->Next = NULL;
NumLog--;
}
return ptr;
}
//----------------------------------------------------------------------
//
// FilemonResetLog
//
// When a GUI instance has close communication (exited), but the driver
// can't unload due to oustdanding IRPs, all the output buffers except
// one are all deallocated so that the memory footprint is shrunk as much
// as possible.
//
//----------------------------------------------------------------------
VOID
FilemonResetLog(
VOID
)
{
PLOG_BUF current, next;
ExAcquireFastMutex( &LogMutex );
//
// Traverse the list of output buffers
//
current = CurrentLog->Next;
while( current ) {
//
// Free the buffer
//
next = current->Next;
ExFreePool( current );
current = next;
}
//
// Move the output pointer in the buffer that's being kept
// the start of the buffer.
//
NumLog = 1;
CurrentLog->Len = 0;
CurrentLog->Next = NULL;
ExReleaseFastMutex( &LogMutex );
}
//----------------------------------------------------------------------
//
// LogRecord
//
// This "printfs" a string into an output buffer.
//
//----------------------------------------------------------------------
BOOLEAN
LogRecord(
BOOLEAN ProcessFilters,
PULONG SeqNum,
PLARGE_INTEGER dateTime,
PLARGE_INTEGER perfTime,
const CHAR * format,
...
)
{
PENTRY Entry;
int len;
ULONG recordSequence;
va_list arg_ptr;
static CHAR text[MAXPATHLEN];
BOOLEAN passedFilters = FALSE;
//
// If no GUI is there to receive the output or if no filtering is desired, don't bother
//
if( !FilterOn ) {
return FALSE;
}
//
// Lock the output buffer and Log.
//
ExAcquireFastMutex( &LogMutex );
//
// Send text out as debug output This is x86 specific.
//
#define A (&format)
DbgPrint(( (char *)format, A[1], A[2], A[3], A[4], A[5], A[6] ));
DbgPrint(( "\n" ));
#undef A
//
// Vsprintf to determine the length of the buffer
//
va_start( arg_ptr, format );
len = vsprintf( text, format, arg_ptr );
va_end( arg_ptr );
//
// ULONG align for Alpha
//
len += 4; len &= 0xFFFFFFFC;
//
// Only log it if it passes the filters. Note that IRP completion
// passes a false for ProcessFilters because if we've logged
// the initial action, we have to go ahead and log the completion.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -