接上
//----------------------------------------------------------------------
//
// FilemonFastIoUnlockSingle
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoUnlockSingle(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length,
PEPROCESS ProcessId,
ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN], errorBuf[ERRORLEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, FastIoUnlockSingle )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoUnlockSingle(
FileObject, FileOffset, Length, ProcessId, Key,
IoStatus, hookExt->FileSystem );
if( FilterDef.logreads &&
hookExt->Hooked ) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_UNLOCK/t%s/tOffset: %d Length: %d/t%s",
FilemonGetProcess( name ), fullPathName,
FileOffset? FileOffset->LowPart : 0, Length ? Length->LowPart : 0,
retval?ErrorString( IoStatus->Status, errorBuf ):"FAILURE" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoUnlockAll
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoUnlockAll(
IN PFILE_OBJECT FileObject,
PEPROCESS ProcessId,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN], errorBuf[ERRORLEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT(hookExt, FastIoUnlockAll ) ) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoUnlockAll(
FileObject, ProcessId, IoStatus, hookExt->FileSystem );
if( FilterDef.logreads &&
hookExt->Hooked ) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_UNLOCK_ALL/t%s/t/t%s",
FilemonGetProcess( name ), fullPathName,
retval?ErrorString( IoStatus->Status, errorBuf ):"FAILURE" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoUnlockAllByKey
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoUnlockAllByKey(
IN PFILE_OBJECT FileObject,
PEPROCESS ProcessId,
ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN], errorBuf[ERRORLEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, FastIoUnlockAllByKey )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoUnlockAllByKey(
FileObject, ProcessId, Key, IoStatus, hookExt->FileSystem );
if( FilterDef.logreads &&
hookExt->Hooked ) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_UNLOCK_ALL_BY_KEY/t%s/t/t%s",
FilemonGetProcess( name ), fullPathName,
retval?ErrorString( IoStatus->Status, errorBuf):"FAILURE" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoQueryNetworkOpenInfo
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoQueryNetworkOpenInfo(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
OUT struct _FILE_NETWORK_OPEN_INFORMATION *Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN], errorBuf[ERRORLEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, FastIoQueryNetworkOpenInfo )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoQueryNetworkOpenInfo(
FileObject, Wait, Buffer, IoStatus, hookExt->FileSystem );
if( FilterDef.logreads &&
hookExt->Hooked ) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_QUERY_NETWORK_OPEN_INFO/t%s/t/t%s",
FilemonGetProcess( name ), fullPathName,
retval ? ErrorString( IoStatus->Status, errorBuf ): "FAILURE" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoAcquireForModWrite
//
//----------------------------------------------------------------------
NTSTATUS
FilemonFastIoAcquireForModWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER EndingOffset,
OUT struct _ERESOURCE **ResourceToRelease,
IN PDEVICE_OBJECT DeviceObject
)
{
NTSTATUS retval = STATUS_NOT_IMPLEMENTED;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, errval[ERRORLEN], name[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, AcquireForModWrite )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->AcquireForModWrite(
FileObject, EndingOffset, ResourceToRelease, hookExt->FileSystem );
if( FilterDef.logwrites &&
hookExt->Hooked ) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_ACQUIRE_FOR_MOD_WRITE/t%s/tEndOffset: %d/t%s",
FilemonGetProcess( name ), fullPathName, EndingOffset,
ErrorString( retval, errval ) );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoMdlRead
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoMdlRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG LockKey,
OUT PMDL *MdlChain,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN], errorBuf[ERRORLEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, MdlRead )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->MdlRead(
FileObject, FileOffset, Length, LockKey, MdlChain,
IoStatus, hookExt->FileSystem );
if( FilterDef.logreads &&
hookExt->Hooked ) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_MDL_READ/t%s/tOffset: %d Length: %d/t%s",
FilemonGetProcess( name ), fullPathName,
FileOffset->LowPart, Length,
retval ? ErrorString( IoStatus->Status, errorBuf ): "FAILURE" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoMdlReadComplete
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoMdlReadComplete(
IN PFILE_OBJECT FileObject,
IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, MdlReadComplete )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = (BOOLEAN) hookExt->FileSystem->DriverObject->FastIoDispatch->MdlReadComplete( FileObject,
MdlChain, hookExt->FileSystem );
if( FilterDef.logreads &&
hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_MDL_READ_COMPLETE/t%s/t/t%s",
FilemonGetProcess( name ), fullPathName, "OK" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoPrepareMdlWrite
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoPrepareMdlWrite(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG LockKey,
OUT PMDL *MdlChain,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN], errorBuf[ERRORLEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
IoStatus->Status = STATUS_NOT_IMPLEMENTED;
IoStatus->Information = 0;
if( FASTIOPRESENT( hookExt, PrepareMdlWrite )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->PrepareMdlWrite(
FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus,
hookExt->FileSystem );
if( FilterDef.logwrites &&
hookExt->Hooked ) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_PREPARE_MDL_WRITE/t%s/tOffset: %d Length: %d/t%s",
FilemonGetProcess( name ), fullPathName,
FileOffset->LowPart, Length,
retval ? ErrorString( IoStatus->Status, errorBuf ): "FAILURE" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoMdlWriteComplete
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoMdlWriteComplete(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, MdlWriteComplete )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->MdlWriteComplete(
FileObject, FileOffset, MdlChain, hookExt->FileSystem );
if( FilterDef.logwrites &&
hookExt->Hooked ) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_MDL_WRITE_COMPLETE/t%s/tOffset: %d/tOK",
FilemonGetProcess( name ), fullPathName, FileOffset->LowPart );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoReadCompressed
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoReadCompressed(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG LockKey,
OUT PVOID Buffer,
OUT PMDL *MdlChain,
OUT PIO_STATUS_BLOCK IoStatus,
OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
IN ULONG CompressedDataInfoLength,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN], errorBuf[ERRORLEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, FastIoReadCompressed )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoReadCompressed(
FileObject, FileOffset, Length, LockKey, Buffer, MdlChain, IoStatus,
CompressedDataInfo, CompressedDataInfoLength, hookExt->FileSystem );
if( FilterDef.logreads &&
hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_READ_COMPRESSED/t%s/tOffset: %d Length: %d/t%s",
FilemonGetProcess( name ), fullPathName,
FileOffset->LowPart, Length,
retval ? ErrorString( IoStatus->Status, errorBuf ) : "FAILURE" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoWriteCompressed
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoWriteCompressed(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG LockKey,
OUT PVOID Buffer,
OUT PMDL *MdlChain,
OUT PIO_STATUS_BLOCK IoStatus,
OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
IN ULONG CompressedDataInfoLength,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN], errorBuf[ERRORLEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, FastIoWriteCompressed )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoWriteCompressed(
FileObject, FileOffset, Length, LockKey, Buffer, MdlChain, IoStatus,
CompressedDataInfo, CompressedDataInfoLength, hookExt->FileSystem );
if( FilterDef.logwrites &&
hookExt->Hooked ) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_WRITE_COMPRESSED/t%s/tOffset: %d Length: %d/t%s",
FilemonGetProcess( name ), fullPathName,
FileOffset->LowPart, Length,
retval ? ErrorString( IoStatus->Status, errorBuf ) : "FAILURE" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoMdlReadCompleteCompressed
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoMdlReadCompleteCompressed(
IN PFILE_OBJECT FileObject,
IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, MdlReadCompleteCompressed )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->MdlReadCompleteCompressed(
FileObject, MdlChain, hookExt->FileSystem );
if( FilterDef.logreads &&
hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_MDL_READ_COMPLETE_COMPRESSED/t%s/t/t%s",
FilemonGetProcess( name ), fullPathName, "OK" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoMdlWriteCompleteCompressed
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoMdlWriteCompleteCompressed(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, MdlWriteCompleteCompressed )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->MdlWriteCompleteCompressed(
FileObject, FileOffset, MdlChain, hookExt->FileSystem );
if( FilterDef.logwrites &&
hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_MDL_WRITE_COMPLETE_COMPRESSED/t%s/tOffset: %d/t%s",
FilemonGetProcess( name ), fullPathName, FileOffset->LowPart, "OK" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoQueryOpen
//
// This call actually passes an IRP!
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoQueryOpen(
IN PIRP Irp,
OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
PFILE_OBJECT FileObject;
CHAR *fullPathName, name[PROCNAMELEN];
PIO_STACK_LOCATION currentIrpStack;
PIO_STACK_LOCATION nextIrpStack;
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return FALSE;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, FastIoQueryOpen )) {
currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
nextIrpStack = IoGetNextIrpStackLocation(Irp);
FileObject = currentIrpStack->FileObject;
//
// copy parametersdo
wn to next level in the stack
//
*nextIrpStack = *currentIrpStack;
nextIrpStack->DeviceObject = hookExt->FileSystem;
IoSetNextIrpStackLocation( Irp );
//
// Get path and timestamp
//
GETPATHNAME(TRUE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoQueryOpen(
Irp, NetworkInformation, hookExt->FileSystem );
//
// Reset the stack location because pre-NT 5.0 checked builds complain
//
Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation++;
if( FilterDef.logreads &&
hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_QUERY_OPEN/t%s/t/t%s",
FilemonGetProcess( name ), fullPathName, retval ? "SUCCESS" : "FAILURE" );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoReleaseForModWrite
//
//----------------------------------------------------------------------
NTSTATUS
FilemonFastIoReleaseForModWrite(
IN PFILE_OBJECT FileObject,
IN struct _ERESOURCE *ResourceToRelease,
IN PDEVICE_OBJECT DeviceObject
)
{
NTSTATUS retval = STATUS_NOT_IMPLEMENTED;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, errval[ERRORLEN], name[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return STATUS_NOT_IMPLEMENTED;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, ReleaseForModWrite )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->ReleaseForModWrite(
FileObject, ResourceToRelease, hookExt->FileSystem );
if( FilterDef.logwrites &&
hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_RELEASE_FOR_MOD_WRITE/t%s/t/t%s",
FilemonGetProcess( name ), fullPathName, ErrorString( retval, errval ));
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoAcquireForCcFlush
//
//----------------------------------------------------------------------
NTSTATUS
FilemonFastIoAcquireForCcFlush(
IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT DeviceObject
)
{
NTSTATUS retval = STATUS_NOT_IMPLEMENTED;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, errval[ERRORLEN], name[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return STATUS_NOT_IMPLEMENTED;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, AcquireForCcFlush )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->AcquireForCcFlush(
FileObject, hookExt->FileSystem );
if( FilterDef.logwrites &&
hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_ACQUIRE_FOR_CC_FLUSH/t%s/t/t%s",
FilemonGetProcess( name ), fullPathName, ErrorString( retval, errval));
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoReleaseForCcFlush
//
//----------------------------------------------------------------------
NTSTATUS
FilemonFastIoReleaseForCcFlush(
IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT DeviceObject
)
{
NTSTATUS retval = STATUS_NOT_IMPLEMENTED;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, errval[ERRORLEN], name[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
if( !DeviceObject ) return STATUS_NOT_IMPLEMENTED;
hookExt = DeviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, ReleaseForCcFlush )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->ReleaseForCcFlush(
FileObject, hookExt->FileSystem );
if( FilterDef.logwrites &&
hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL,
&dateTime, &timeResult,
"%s/tFASTIO_RELEASE_FOR_CC_FLUSH/t%s/t/t%s",
FilemonGetProcess( name ), fullPathName, ErrorString( retval, errval) );
}
FREEPATHNAME();
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoDeviceControl
//
//----------------------------------------------------------------------
BOOLEAN
FilemonFastIoDeviceControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{
BOOLEAN retval = FALSE;
BOOLEAN logMutexReleased;
PHOOK_EXTENSION hookExt;
PLOG_BUF oldLog, savedCurrentLog;
CHAR fullPathName[MAXPATHLEN], name[PROCNAMELEN], errorBuf[ERRORLEN];
KIRQL oldirql;
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
hookExt = DeviceObject->DeviceExtension;
if( hookExt->Type == GUIINTERFACE ) {
//
// Its a message from our GUI!
//
IoStatus->Status = STATUS_SUCCESS;
// Assume success
IoStatus->Information = 0;
// Assume nothing returned
switch ( IoControlCode ) {
case IOCTL_FILEMON_VERSION:
//
// Version #
//
if( OutputBufferLength >= sizeof(ULONG)) {
*(ULONG *)OutputBuffer = FILEMONVERSION;
IoStatus->Information = sizeof(ULONG);
} else
{
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
}
break;
case IOCTL_FILEMON_SETDRIVES:
//
// Hook and/or unhook drives
//
DbgPrint (("Filemon: set drives/n"));
if( InputBufferLength >= sizeof(ULONG) &&
OutputBufferLength >= sizeof(ULONG)) {
*(ULONG *)OutputBuffer = HookDriveSet( *(ULONG *)InputBuffer, DeviceObject->DriverObject );
IoStatus->Information = sizeof(ULONG);
} else
{
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
}
break;
case IOCTL_FILEMON_HOOKSPECIAL:
if( InputBufferLength >= sizeof(FILE_SYSTEM_TYPE )) {
if( !HookSpecialFs( DeviceObject->DriverObject, *(PFILE_SYSTEM_TYPE) InputBuffer )) {
IoStatus->Status = STATUS_UNSUCCESSFUL;
}
} else
{
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
}
break;
case IOCTL_FILEMON_UNHOOKSPECIAL:
if( InputBufferLength >= sizeof(FILE_SYSTEM_TYPE )) {
UnhookSpecialFs( *(PFILE_SYSTEM_TYPE) InputBuffer );
} else
{
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
}
break;
case IOCTL_FILEMON_STOPFILTER:
//
// Turn off logging
//
DbgPrint(("Filemon: stop logging/n"));
FilterOn = FALSE;
break;
case IOCTL_FILEMON_STARTFILTER:
//
// Turn on logging
//
DbgPrint(("Filemon: start logging/n"));
FilterOn = TRUE;
break;
case IOCTL_FILEMON_SETFILTER:
//
// Gui is updating the filter functions
//
DbgPrint(("Filemon: set filter/n"));
if( InputBufferLength >= sizeof(FILTER) ) {
FilterDef = *(PFILTER) InputBuffer;
FilemonUpdateFilters();
} else
{
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
}
break;
case IOCTL_FILEMON_UNLOADQUERY:
#if DBG
//
// Is it possible to unload?
//
KeAcquireSpinLock( &CountMutex, &oldirql );
IoStatus->Information = OutstandingIRPCount;
//
// Any outstanding Irps?
//
if( !OutstandingIRPCount ) {
//
// Nope, sodo
n't process anymore
//
UnloadInProgress = TRUE;
KeReleaseSpinLock( &CountMutex, oldirql );
//
// Stop capturing drives
//
HookDriveSet( 0, DeviceObject->DriverObject );
UnhookSpecialFs( NPFS );
UnhookSpecialFs( MSFS );
//
// Detach from all devices
//
UnloadDetach();
} else
{
KeReleaseSpinLock( &CountMutex, oldirql );
}
#else
// DBG
IoStatus->Information = 1;
#endif // DBG
break;
case IOCTL_FILEMON_ZEROSTATS:
//
// Reset all output buffers
//
DbgPrint (("Filemon: zero stats/n"));
ExAcquireFastMutex( &LogMutex );
while( CurrentLog->Next ) {
//
// Free all but the first output buffer
//
oldLog = CurrentLog->Next;
CurrentLog->Next = oldLog->Next;
ExFreePool( oldLog );
NumLog--;
}
//
// Set the output pointer to the start of the output buffer
//
CurrentLog->Len = 0;
Sequence = 0;
ExReleaseFastMutex( &LogMutex );
break;
case IOCTL_FILEMON_GETSTATS:
//
// Copy the oldest output buffer to the caller
//
DbgPrint (("Filemon: get stats/n"));
//
// If the output buffer is too large to fit into the caller's buffer
//
if( LOGBUFSIZE > OutputBufferLength ) {
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
return FALSE;
}
//
// Probe the output buffer
//
try {
ProbeForWrite( OutputBuffer,
OutputBufferLength,
sizeof( UCHAR ));
} except( EXCEPTION_EXECUTE_HANDLER ) {
IoStatus->Status = STATUS_INVALID_PARAMETER;
return FALSE;
}
//
// We're okay, lock the buffer pool
//
ExAcquireFastMutex( &LogMutex );
if( CurrentLog->Len || CurrentLog->Next ) {
//
// Start output to a new output buffer
//
FilemonAllocateLog();
//
// Fetch the oldest to give to user
//
oldLog = FilemonGetOldestLog();
if( oldLog != CurrentLog ) {
logMutexReleased = TRUE;
ExReleaseFastMutex( &LogMutex );
} else
{
logMutexReleased = FALSE;
}
//
// Copy it to the caller's buffer
//
memcpy( OutputBuffer, oldLog->Data, oldLog->Len );
//
// Return length of copied info
//
IoStatus->Information = oldLog->Len;
//
// Deallocate buffer - unless its the last one
//
if( logMutexReleased ) {
ExFreePool( oldLog );
} else
{
CurrentLog->Len = 0;
ExReleaseFastMutex( &LogMutex );
}
} else
{
//
// There is no unread data
//
ExReleaseFastMutex( &LogMutex );
IoStatus->Information = 0;
}
break;
default:
//
// Unknown control
//
DbgPrint (("Filemon: unknown IRP_MJ_DEVICE_CONTROL/n"));
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
retval = TRUE;
} else
{
//
// Its a call for a file system, so pass it through
//
if( FASTIOPRESENT( hookExt, FastIoDeviceControl ) ) {
FilemonGetFullPath( FALSE, FileObject, hookExt, fullPathName );
TIMESTAMPSTART();
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoDeviceControl(
FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer,
OutputBufferLength, IoControlCode, IoStatus, hookExt->FileSystem );
if(hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL, &dateTime, &timeResult,
"%s/tFASTIO_DEVICE_CONTROL/t%s/tIOCTL: 0x%X/t%s",
FilemonGetProcess( name ), fullPathName,
IoControlCode,
retval ? ErrorString( IoStatus->Status, errorBuf ) : "FAILURE" );
}
}
}
return retval;
}
//----------------------------------------------------------------------
//
// FilemonFastIoAcquireFile
//
//----------------------------------------------------------------------
VOID
FilemonFastIoAcquireFile(
PFILE_OBJECT FileObject
)
{
PDEVICE_OBJECT deviceObject, checkDevice;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
//
// We've got to locate our own device object
//
checkDevice = FileObject->DeviceObject->Vpb->DeviceObject;
while( checkDevice ) {
if( checkDevice->DriverObject == FilemonDriver ) {
//
// Found it
//
deviceObject = checkDevice;
hookExt = deviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, AcquireFileForNtCreateSection )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
hookExt->FileSystem->DriverObject->FastIoDispatch->AcquireFileForNtCreateSection(
FileObject );
if( FilterDef.logreads &&
hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL, &dateTime, &timeResult,
"%s/tFASTIO_ACQUIRE_FILE/t%s/t/tOK", FilemonGetProcess( name ),
fullPathName );
}
FREEPATHNAME();
}
return;
}
checkDevice = checkDevice->AttachedDevice;
}
}
//----------------------------------------------------------------------
//
// FilemonFastIoReleaseFile
//
//----------------------------------------------------------------------
VOID
FilemonFastIoReleaseFile(
PFILE_OBJECT FileObject
)
{
PDEVICE_OBJECT deviceObject, checkDevice;
PHOOK_EXTENSION hookExt;
CHAR *fullPathName, name[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
//
// We've got to locate our own device object
//
checkDevice = FileObject->DeviceObject->Vpb->DeviceObject;
while( checkDevice ) {
if( checkDevice->DriverObject == FilemonDriver ) {
deviceObject = IoGetRelatedDeviceObject( FileObject );
hookExt = deviceObject->DeviceExtension;
if( FASTIOPRESENT( hookExt, ReleaseFileForNtCreateSection )) {
GETPATHNAME(FALSE);
TIMESTAMPSTART();
hookExt->FileSystem->DriverObject->FastIoDispatch->ReleaseFileForNtCreateSection( FileObject );
if( FilterDef.logreads &&
hookExt->Hooked) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL, &dateTime, &timeResult,
"%s/tFASTIO_RELEASE_FILE/t%s/t/tOK", FilemonGetProcess( name ),
fullPathName );
}
FREEPATHNAME();
}
return;
}
checkDevice = checkDevice->AttachedDevice;
}
}
//----------------------------------------------------------------------
//
// FilemonFastIoDetachDevice
//
// We get this call when a device that we have hooked is being deleted.
// This happens when, for example, a floppy is formatted. We have
// to detach from it and delete our device. We should notify the GUI
// that the hook state has changed, but its not worth the trouble.
//
//----------------------------------------------------------------------
VOID
FilemonFastIoDetachDevice(
PDEVICE_OBJECT SourceDevice,
PDEVICE_OBJECT TargetDevice
)
{
PHOOK_EXTENSION hookExt;
ULONG i;
CHAR name[PROCNAMELEN], drive[PROCNAMELEN];
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
LARGE_INTEGER dateTime;
//
// See if a device (like a floppy) is being removed out from under us. If so,
// we have to detach from it before it disappears
//
for( i = 0;
i < 26;
i++ ) {
if( SourceDevice == DriveHookDevices ) {
//
// We've hooked it, so we must detach
//
hookExt = SourceDevice->DeviceExtension;
DbgPrint(("Filemon: Detaching from drive: %c/n",
hookExt->LogicalDrive ));
TIMESTAMPSTART();
sprintf( drive, "%c:", hookExt->LogicalDrive );
if( hookExt->Hooked ) {
TIMESTAMPSTOP();
LogRecord( TRUE, NULL, &dateTime, &timeResult,
"%s/tFASTIO_DETACH_DEVICE/t%s/t/tOK",
FilemonGetProcess( name ), drive );
}
IoDetachDevice( TargetDevice );
IoDeleteDevice( SourceDevice );
DriveHookDevices = NULL;
return;
}
}
//
// It wasn't for us, so pass it on.
//
hookExt = SourceDevice->DeviceExtension;
if( FASTIOPRESENT( hookExt, FastIoDetachDevice )) {
hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoDetachDevice(
SourceDevice, TargetDevice );
}
}
//----------------------------------------------------------------------
// D I S P A T C H A N D H O O K E N T R Y P O I N T S
//----------------------------------------------------------------------
//----------------------------------------------------------------------
//
// FilemonHookDoneWork
//
// Worker routine that simply calls update Log. Since we want
// to avoid using spin locks in order to improve SMP performance
// we need todo
everything at passive. When our completion routine
// is called at dispatch, we queue the update off to a worker thread.
//
//----------------------------------------------------------------------
VOID
FilemonHookDoneWork(
PVOID Context
)
{
PFILEMON_WORK filemonWork = (PFILEMON_WORK) Context;
DbgPrint(("HookWorkRoutine/n"));
LogRecord( FALSE, &filemonWork->Sequence,
NULL,
&filemonWork->TimeResult,
filemonWork->ErrString );
ExFreePool( filemonWork );
}
//----------------------------------------------------------------------
//
// FilemonHookDone
//
// Gets control after a filesystem operation has completed so that
// we can get return status information about it.
//
//----------------------------------------------------------------------
NTSTATUS
FilemonHookDone(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PIO_STACK_LOCATION IrpSp;
#if defined(_IA64_)
ULONG seqNum = (ULONG) ((ULONG_PTR)Context);
#else
ULONG seqNum = (ULONG) Context;
#endif
CHAR errval[ERRORLEN], errString[ERRORLEN];
KIRQL oldirql;
LARGE_INTEGER timeStampStart, timeStampComplete, timeResult;
PFILEMON_WORK filemonWorkContext;
//
// A request completed - look at the result
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
//
// Log the return status in the output buffer. Tag it with the
// sequence number so that the GUI can match it with the IRP input information.
//
if( FilterOn ) {
//
// Quick, get the completion time
//
timeStampStart = IrpSp->Parameters.Read.ByteOffset;
timeStampComplete = KeQueryPerformanceCounter(NULL);
timeResult.QuadPart = timeStampComplete.QuadPart - timeStampStart.QuadPart;
//
// Queue off to a worker thread if we have to
//
if( KeGetCurrentIrql() == DISPATCH_LEVEL ) {
filemonWorkContext = ExAllocatePool( NonPagedPool, sizeof(FILEMON_WORK));
if( filemonWorkContext ) {
filemonWorkContext->Sequence = seqNum;
filemonWorkContext->TimeResult = timeResult;
sprintf( filemonWorkContext->ErrString, "/t/t/t/t%s",
ErrorString( Irp->IoStatus.Status, errval ));
ExInitializeWorkItem( &filemonWorkContext->WorkItem,
FilemonHookDoneWork, filemonWorkContext );
ExQueueWorkItem( &filemonWorkContext->WorkItem, CriticalWorkQueue );
}
} else
{
sprintf( errString, "/t/t/t/t%s", ErrorString( Irp->IoStatus.Status, errval ));
LogRecord( FALSE, &seqNum, NULL, &timeResult, errString );
}
}
#if DBG
//
// We have finished processing an IRP so decrement oustanding IRP count
//
KeAcquireSpinLock( &CountMutex, &oldirql );
OutstandingIRPCount--;
DbgPrint(("-%d: %x/n", OutstandingIRPCount, Irp ));;
if( !OutstandingIRPCount ) FilemonDriver->DriverUnload = FilemonUnload;
KeReleaseSpinLock( &CountMutex, oldirql );
#endif
//
// Now we have to mark Irp as pending if necessary
//
if( Irp->PendingReturned ) {
IoMarkIrpPending( Irp );
}
return Irp->IoStatus.Status;
}
//----------------------------------------------------------------------
//
// FilemonHookRoutine
//
// This routine is the main hook routine where we figure out what
// calls are being sent to the file system.
//
//----------------------------------------------------------------------
NTSTATUS
FilemonHookRoutine(
PDEVICE_OBJECT HookDevice,
IN PIRP Irp
)
{
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
PMOVE_FILE_DATA moveFile;
PQUERY_DIRECTORY queryDirectory;
PFILE_OBJECT FileObject;
PHOOK_EXTENSION hookExt;
LARGE_INTEGER dateTime;
LARGE_INTEGER perfTime;
PCHAR fullPathName = NULL;
BOOLEAN hookCompletion, createPath;
CHAR controlCodeBuffer[ERRORLEN];
CHAR attributeString[ERRORLEN];
CHAR optionString[ERRORLEN];
CHAR name[PROCNAMELEN];
ULONG i;
ANSI_STRING directoryFilter;
PCHAR queryFilter;
ULONG seqNum;
KIRQL oldirql;
//
// Extract the file object from the IRP
//
FileObject = currentIrpStack->FileObject;
//
// Point at the device extension, which contains information on which
// file system this IRP is headed for
//
hookExt = HookDevice->DeviceExtension;
//
// We note open cases so that when we query the file name
// wedo
n't ask the file system for the name (since it won't
// have seen the file object yet).
//
if( currentIrpStack->MajorFunction == IRP_MJ_CREATE ||
currentIrpStack->MajorFunction == IRP_MJ_CREATE_NAMED_PIPE ||
currentIrpStack->MajorFunction == IRP_MJ_CREATE_MAILSLOT ) {
//
// Clear any existing fileobject/name association stored in the
// hash table
//
FilemonFreeHashEntry( FileObject );
createPath = TRUE;
} else
if( currentIrpStack->MajorFunction == IRP_MJ_CLOSE ) {
//
// We treat close as a special case of create for name querying
// since calling into NTFS during a close can result in a deadlock.
//
createPath = TRUE;
} else
if( currentIrpStack->MajorFunction == IRP_MJ_CLEANUP &&
FileObject->Flags &
FO_STREAM_FILE ) {
//
// Treat cleanup of stream file objects as special create case, because
// querying them causes NTFS to screwup on NT 4
//
createPath = TRUE;
} else
{
createPath = FALSE;
}
//
// Allocate a buffer and get the name only if we have to
//
if( FilterOn &&
hookExt->Hooked ) {
GETPATHNAME( createPath );
}
//
// Only log it if it passes the filter
//
if( hookExt->Hooked &&
fullPathName ) {
//
// If measuring absolute time go and get the timestamp.
//
KeQuerySystemTime( &dateTime );
perfTime = KeQueryPerformanceCounter( NULL );
//
// We want to watch this IRP complete
//
seqNum = (ULONG) -1;
hookCompletion = FALSE;
//
// Determine what function we're dealing with
//
FilemonGetProcess( name );
switch( currentIrpStack->MajorFunction ) {
case IRP_MJ_CREATE:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_CREATE/t%s/tAttributes: %s Options: %s",
name, fullPathName,
CreateAttributesString( currentIrpStack->Parameters.Create.FileAttributes,
attributeString ),
CreateOptionsString( currentIrpStack->Parameters.Create.Options,
optionString ));
//
// If its an open-by-id we free the hash entry now so that on the next access to
// the file we'll pick up the file's real name.
//
if( currentIrpStack->Parameters.Create.Options &
FILE_OPEN_BY_FILE_ID ) {
FilemonFreeHashEntry( FileObject );
}
break;
case IRP_MJ_CREATE_NAMED_PIPE:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_CREATE_NAMED_PIPE/t%s/tAttributes: %s Options: %s",
name, fullPathName,
CreateAttributesString( currentIrpStack->Parameters.Create.FileAttributes,
attributeString ),
CreateOptionsString( currentIrpStack->Parameters.Create.Options,
optionString ));
break;
case IRP_MJ_CREATE_MAILSLOT:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_CREATE_MAILSLOT/t%s/tAttributes: %s Options: %s",
name, fullPathName,
CreateAttributesString( currentIrpStack->Parameters.Create.FileAttributes,
attributeString ),
CreateOptionsString( currentIrpStack->Parameters.Create.Options,
optionString ));
break;
case IRP_MJ_READ:
if( FilterDef.logreads ) {
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_READ%c/t%s/tOffset: %d Length: %d",
name,
(Irp->Flags &
IRP_PAGING_IO) ||
(Irp->Flags &
IRP_SYNCHRONOUS_PAGING_IO) ? '*' : ' ',
fullPathName,
currentIrpStack->Parameters.Read.ByteOffset.LowPart,
currentIrpStack->Parameters.Read.Length );
}
break;
case IRP_MJ_WRITE:
if( FilterDef.logwrites ) {
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_WRITE%c/t%s/tOffset: %d Length: %d",
name,
(Irp->Flags &
IRP_PAGING_IO) ||
(Irp->Flags &
IRP_SYNCHRONOUS_PAGING_IO) ? '*' : ' ',
fullPathName,
currentIrpStack->Parameters.Write.ByteOffset.LowPart,
currentIrpStack->Parameters.Write.Length );
}
break;
case IRP_MJ_CLOSE:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_CLOSE%c/t%s/t",
name,
(Irp->Flags &
IRP_PAGING_IO) ||
(Irp->Flags &
IRP_SYNCHRONOUS_PAGING_IO) ? '*' : ' ',
fullPathName );
//
// This fileobject/name association can be discarded now.
//
FilemonFreeHashEntry( FileObject );
break;
case IRP_MJ_FLUSH_BUFFERS:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_FLUSH/t%s/t", name, fullPathName );
break;
case IRP_MJ_QUERY_INFORMATION:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_QUERY_INFORMATION/t%s/t%s",
name, fullPathName,
FileInformation[currentIrpStack->Parameters.QueryFile.FileInformationClass] );
break;
case IRP_MJ_SET_INFORMATION:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_SET_INFORMATION%c/t%s/t%s",
name,
(Irp->Flags &
IRP_PAGING_IO) ||
(Irp->Flags &
IRP_SYNCHRONOUS_PAGING_IO) ? '*' : ' ',
fullPathName,
FileInformation[currentIrpStack->Parameters.SetFile.FileInformationClass] );
//
// If its a rename, cleanup the name association.
//
if( currentIrpStack->Parameters.SetFile.FileInformationClass ==
FileRenameInformation ) {
FilemonFreeHashEntry( FileObject );
}
break;
case IRP_MJ_QUERY_EA:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_QUERY_EA/t%s/t", name, fullPathName );
break;
case IRP_MJ_SET_EA:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_SET_EA/t%s/t", name, fullPathName );
break;
case IRP_MJ_QUERY_VOLUME_INFORMATION:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_QUERY_VOLUME_INFORMATION/t%s/t%s",
name, fullPathName,
VolumeInformation[currentIrpStack->Parameters.QueryVolume.FsInformationClass] );
break;
case IRP_MJ_SET_VOLUME_INFORMATION:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_SET_VOLUME_INFORMATION/t%s/t%s",
name, fullPathName,
VolumeInformation[currentIrpStack->Parameters.QueryVolume.FsInformationClass] );
break;
case IRP_MJ_DIRECTORY_CONTROL:
switch( currentIrpStack->MinorFunction ) {
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_DIRECTORY_CONTROL/t%s/tChange Notify",
name, fullPathName );
break;
case IRP_MN_QUERY_DIRECTORY:
queryDirectory = (PQUERY_DIRECTORY)&currentIrpStack->Parameters;
queryFilter = NULL;
if( queryDirectory->FileName ) {
if( NT_SUCCESS( RtlUnicodeStringToAnsiString( &directoryFilter,
queryDirectory->FileName, TRUE ))) {
queryFilter = ExAllocatePool( PagedPool, directoryFilter.Length + 1 );
if( queryFilter ) {
memcpy( queryFilter, directoryFilter.Buffer, directoryFilter.Length );
queryFilter[ directoryFilter.Length ] = 0;
//
// Massagedo
S-internal wildcards
//
for( i = 0;
i < strlen( queryFilter );
i++ ) {
if( queryFilter == '<' ) queryFilter = '*';
else
if( queryFilter == '>' ) queryFilter = '?';
}
}
RtlFreeAnsiString( &directoryFilter );
}
}
if( queryFilter ) {
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_DIRECTORY_CONTROL/t%s/t%s: %s",
name, fullPathName,
FileInformation[queryDirectory->FileInformationClass],
queryFilter );
ExFreePool( queryFilter );
} else
{
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_DIRECTORY_CONTROL/t%s/t%s",
name, fullPathName,
FileInformation[queryDirectory->FileInformationClass] );
}
break;
default:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_DIRECTORY_CONTROL/t%s/t",
name, fullPathName );
break;
}
break;
case IRP_MJ_FILE_SYSTEM_CONTROL:
switch( currentIrpStack->Parameters.DeviceIoControl.IoControlCode ) {
case FSCTL_MOVE_FILE:
moveFile = (PMOVE_FILE_DATA) Irp->AssociatedIrp.SystemBuffer;
sprintf( optionString, "Vcn: %d Len: %d Target: %d",
moveFile->StartingVcn.LowPart,
moveFile->ClusterCount,
moveFile->StartingLcn.LowPart );
ObReferenceObjectByHandle( moveFile->FileHandle, 0, NULL, KernelMode, &FileObject, NULL );
FilemonGetFullPath( FALSE, FileObject, hookExt, fullPathName );
ObDereferenceObject( FileObject );
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tFSCTL_MOVE_FILE/t%s/t%s",
name, fullPathName, optionString );
break;
default:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/t%s/t%s/t%s",
name,
ControlCodeString( currentIrpStack,
currentIrpStack->Parameters.DeviceIoControl.IoControlCode,
controlCodeBuffer, optionString ),
fullPathName, optionString );
}
break;
case IRP_MJ_SHUTDOWN:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_SHUTDOWN/t/t", name );
break;
case IRP_MJ_LOCK_CONTROL:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_LOCK_CONTROL/t%s/tOffset: %d Length: %d",
name, fullPathName,
((PLOCK_CONTROL)&currentIrpStack->Parameters)->ByteOffset.LowPart,
((PLOCK_CONTROL)&currentIrpStack->Parameters)->Length ?
((PLOCK_CONTROL)&currentIrpStack->Parameters)->Length->LowPart : 0 );
break;
case IRP_MJ_CLEANUP:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_CLEANUP/t%s/t", name, fullPathName );
break;
case IRP_MJ_DEVICE_CONTROL:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_DEVICE_CONTROL/t%s/tIOCTL: 0x%X", name,
fullPathName, currentIrpStack->Parameters.DeviceIoControl.IoControlCode );
break;
case IRP_MJ_QUERY_SECURITY:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_QUERY_SECURITY/t%s/t",
name, fullPathName );
break;
case IRP_MJ_SET_SECURITY:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_SET_SECURITY/t%s/t",
name, fullPathName );
break;
case IRP_MJ_POWER:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_POWER/t%s/tMinor: %x",
name, fullPathName,
currentIrpStack->MinorFunction );
break;
case IRP_MJ_PNP:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/tIRP_MJ_PNP/t%s/t%s",
name, fullPathName,
currentIrpStack->MinorFunction <= IRP_MN_QUERY_LEGACY_BUS_INFORMATION ?
PnpMinorCode[currentIrpStack->MinorFunction] : "New minor code" );
break;
default:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
"%s/t*UNKNOWN* 0x%X/t/t", name, currentIrpStack->MajorFunction );
break;
}
} else
{
//
// Wedo
n't care about this IRP's completion
//
hookCompletion = FALSE;
//
//do
name processing for the sake of keeping the hash table current
//
switch( currentIrpStack->MajorFunction ) {
case IRP_MJ_CLOSE:
//
// This fileobject/name association can be discarded now.
//
FilemonFreeHashEntry( FileObject );
break;
}
}
//
// Free the buffer if we have one
//
if( fullPathName &&
fullPathName != InsufficientResources ) {
ExFreeToNPagedLookasideList( &FullPathLookaside, fullPathName );
}
//
// Copy parametersdo
wn to next level in the stack for the driver below us
//
*nextIrpStack = *currentIrpStack;
#if DBG
//
// If an unload isn't in progress, we should register a completion callback
// so that the IRP's return status can be examined.
//
KeAcquireSpinLock( &CountMutex, &oldirql );
#endif
if( !UnloadInProgress &&
hookCompletion ) {
#if DBG
//
// Increment the outstanding IRP count since this IRP will be headed
// for our completion routine
//
FilemonDriver->DriverUnload = NULL;
OutstandingIRPCount++;
DbgPrint(("+%d: %x/n", OutstandingIRPCount, Irp ));;
#endif // DBG
//
// Grab the time stamp and Log it in the current stack location. This
// is legal since the stack location is ours, and we'redo
ne looking at
// the parameters. This makes it easy to pass this to the completion routine. The
// DiskPerf example in the NT DDK uses this trick.
//
currentIrpStack->Parameters.Read.ByteOffset = perfTime;
#if defined(_IA64_)
IoSetCompletionRoutine( Irp, FilemonHookDone, (PVOID) (ULONG_PTR) seqNum, TRUE, TRUE, TRUE );
#else
IoSetCompletionRoutine( Irp, FilemonHookDone, (PVOID) seqNum, TRUE, TRUE, TRUE );
#endif
} else
{
//
// Set no completion routine
//
IoSetCompletionRoutine( Irp, FilemonHookDone, NULL, FALSE, FALSE, FALSE );
}
#if DBG
KeReleaseSpinLock( &CountMutex, oldirql );
#endif
//
// Return the results of the call to the caller
//
return IoCallDriver( hookExt->FileSystem, Irp );
}
//----------------------------------------------------------------------
//
// FilemonDeviceRoutine
//
// In this routine we handle requests to our own device. The only
// requests we care about handling explicitely are IOCTL commands that
// we will get from the GUI. We also expect to get Create and Close
// commands when the GUI opens and closes communications with us.
//
//----------------------------------------------------------------------
NTSTATUS
FilemonDeviceRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION irpStack;
PVOID inputBuffer;
PVOID outputBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
//
// Go ahead and set the request up as successful
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get the pointer to the input/output buffer and its length
//
inputBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBuffer = Irp->AssociatedIrp.SystemBuffer;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (irpStack->MajorFunction) {
case IRP_MJ_CREATE:
DbgPrint(("Filemon: IRP_MJ_CREATE/n"));
//
// Start the sequence number at 0
//
Sequence = 0;
break;
case IRP_MJ_CLOSE:
DbgPrint(("Filemon: IRP_MJ_CLOSE/n"));
//
// A GUI is closing communication
//
FilterOn = FALSE;
//
// If the GUI has no more references to us, reset the output
// buffers and hash table.
//
FilemonResetLog();
FilemonHashCleanup();
//
// Stop capturing drives
//
HookDriveSet( 0, DeviceObject->DriverObject );
UnhookSpecialFs( NPFS );
UnhookSpecialFs( MSFS );
break;
case IRP_MJ_DEVICE_CONTROL:
//
// This path will never execute because we have registered a
// fast I/O path for device control. That means that the fast I/O entry
// point will ALWAYS be called for Device Control operations
//
DbgPrint (("Filemon: IRP_MJ_DEVICE_CONTROL/n"));
//
// Get output buffer if its passed as an MDL
//
if( Irp->MdlAddress ) {
outputBuffer = MmGetSystemAddressForMdl( Irp->MdlAddress );
}
//
// Its a request from the GUI. Simply call our fast handler.
//
FilemonFastIoDeviceControl( irpStack->FileObject, TRUE,
inputBuffer, inputBufferLength,
outputBuffer, outputBufferLength,
ioControlCode, &Irp->IoStatus, DeviceObject );
break;
}
//
// Complete the IRP
//
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
//----------------------------------------------------------------------
//
// FilemonDispatch
//
// Based on which device the Irp is destined for we call either the
// filesystem filter function, or our own device handling routine.
//
//----------------------------------------------------------------------
NTSTATUS
FilemonDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
//
// Determine if its a request from the GUI to us, or one that is
// directed at a file system driver that we've hooked
//
if( ((PHOOK_EXTENSION) DeviceObject->DeviceExtension)->Type == GUIINTERFACE ) {
return FilemonDeviceRoutine( DeviceObject, Irp );
} else
{
return FilemonHookRoutine( DeviceObject, Irp );
}
}
//----------------------------------------------------------------------
//
// FilemonUnload
//
// Our job isdo
ne - time to leave. Note that this function is
// only called when debugging is on, since in reality it is not safe
// to detach filter devices or unload a filter driver.
//
//----------------------------------------------------------------------
VOID
FilemonUnload(
IN PDRIVER_OBJECT DriverObject
)
{
WCHAR deviceLinkBuffer[] = L"//DosDevices//Filemon";
UNICODE_STRING deviceLinkUnicodeString;
//
// Delete the symbolic link for our GUI device
//
RtlInitUnicodeString( &deviceLinkUnicodeString, deviceLinkBuffer );
IoDeleteSymbolicLink( &deviceLinkUnicodeString );
DbgPrint(("Filemon.SYS: unloading/n"));
//
// The only device object left should be the GUI device, since
// we delete devices in our unload check.
//
IoDeleteDevice( DriverObject->DeviceObject );
DbgPrint(("Filemon.SYS: deleted devices/n"));
//
// Now we can free any memory that is allocated
//
FilemonFreeFilters();
FilemonHashCleanup();
FilemonFreeLog();
ExDeleteNPagedLookasideList( &FullPathLookaside );
//
// Delete the resources
//
ExDeleteResourceLite( &FilterResource );
ExDeleteResourceLite( &HashResource );
DbgPrint(("Filemon.SYS: freed memory/n"));
}
//----------------------------------------------------------------------
//
// DriverEntry
//
// Installable driver initialization. Here we just set ourselves up.
// 驱动入口
//
//----------------------------------------------------------------------
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS ntStatus; // 返回的状态
PDEVICE_OBJECT guiDevice;
WCHAR deviceNameBuffer[] = L"//Device//Filemon";
UNICODE_STRING deviceNameUnicodeString;
WCHAR deviceLinkBuffer[] = L"//DosDevices//Filemon";
UNICODE_STRING deviceLinkUnicodeString;
ULONG i;
DbgPrint (("Filemon.SYS: entering DriverEntry/n"));
//
// 这个是最基础的对象
//
FilemonDriver = DriverObject;
//
// 设置驱动的名称
//
RtlInitUnicodeString (&deviceNameUnicodeString,
deviceNameBuffer );
//
// Create the device used for GUI communications
//
ntStatus = IoCreateDevice ( DriverObject,
sizeof(HOOK_EXTENSION),
&deviceNameUnicodeString,
FILE_DEVICE_FILEMON,
0,
TRUE,
&guiDevice );
//
// If successful, make a symbolic link that allows for the device
// object's access from Win32 programs
//
if(NT_SUCCESS(ntStatus)) {
//
// Mark this as our GUI device
//
((PHOOK_EXTENSION) guiDevice->DeviceExtension)->Type = GUIINTERFACE;
//
// Create a symbolic link that the GUI can specify to gain access
// to this driver/device
//
RtlInitUnicodeString (&deviceLinkUnicodeString,
deviceLinkBuffer );
ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
&deviceNameUnicodeString );
if(!NT_SUCCESS(ntStatus)) {
DbgPrint (("Filemon.SYS: IoCreateSymbolicLink failed/n"));
IoDeleteDevice( guiDevice );
return ntStatus;
}
//
// Create dispatch points for all routines that must be handled.
// All entry points are registered since we might filter a
// file system that processes all of them.
//
for( i = 0;
i <= IRP_MJ_MAXIMUM_FUNCTION;
i++ ) {
DriverObject->MajorFunction = FilemonDispatch;
}
#if DBG
//
// Driver unload is only set if we are debugging Filemon. This is
// because unloading a filter is not really safe - threads could
// be in our fastio routines (or about to enter them), for example,
// and there is no way to tell. When debugging, we can risk the
// occasional unload crash as a trade-off for not having to
// reboot as often.
//
// DriverObject->DriverUnload = FilemonUnload;
#endif // DBG
//
// Set up the Fast I/O dispatch table
//
DriverObject->FastIoDispatch = &FastIOHook;
} else
{
//
// If something went wrong, cleanup the device object anddo
n't load
//
DbgPrint(("Filemon: Failed to create our device!/n"));
return ntStatus;
}
//
// Initialize the name hash table
//
for(i = 0;
i < NUMHASH;
i++ ) HashTable = NULL;
//
// Find the process name offset
//
ProcessNameOffset = FilemonGetProcessNameOffset(); // 进程偏移量
//
// Initialize the synchronization objects
//
#if DBG
KeInitializeSpinLock( &CountMutex );
#endif
ExInitializeFastMutex( &LogMutex );
ExInitializeResourceLite( &FilterResource );
ExInitializeResourceLite( &HashResource );
//
// Initialize a lookaside for file names
//
ExInitializeNPagedLookasideList( &FullPathLookaside, NULL, NULL,
0, MAXPATHLEN, 'mliF', 256 );
//
// Allocate the first output buffer
//
CurrentLog = ExAllocatePool( NonPagedPool, sizeof(*CurrentLog) );
// 申请输出缓冲区
if( !CurrentLog ) {
//
// Oops - we can'tdo
anything without at least one buffer
//
IoDeleteSymbolicLink( &deviceLinkUnicodeString );
IoDeleteDevice( guiDevice );
return STATUS_INSUFFICIENT_RESOURCES;
// 资源不足错误
}
//
// Set the buffer pointer to the start of the buffer just allocated
//
CurrentLog->Len = 0;
CurrentLog->Next = NULL;
NumLog = 1;
return STATUS_SUCCESS;
}