📄 filespy.c
字号:
Arguments:
DeviceObject - Pointer to device object Filespy attached to the file system
filter stack for the volume receiving this I/O request.
Irp - Pointer to the request packet representing the I/O request.
Return Value:
If this is a request on the gControlDeviceObject, STATUS_SUCCESS
will be returned unless the device is already attached. In that case,
STATUS_DEVICE_ALREADY_ATTACHED is returned.
If this is a request on a device other than the gControlDeviceObject,
the function will return the value of SpyPassThrough().
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
//
// File systems should NEVER receive power IRPs
//
ASSERT(irpStack->MajorFunction != IRP_MJ_POWER);
if (DeviceObject == gControlDeviceObject) {
//
// If the specified debug level is set, output what operation
// we are seeing to the debugger.
//
if (FlagOn( gFileSpyDebugLevel, SPYDEBUG_TRACE_IRP_OPS )) {
SpyDumpIrpOperation( TRUE, Irp );
}
//
// A request is being made on our control device object
//
Irp->IoStatus.Information = 0;
switch (irpStack->MajorFunction) {
case IRP_MJ_DEVICE_CONTROL:
//
// This is a private device control IRP for our control device.
// Pass the parameter information along to the common routine
// use to service these requests.
//
// All of FileSpy's IOCTLs are buffered, therefore both the
// input and output buffer are represented by the
// Irp->AssociatedIrp.SystemBuffer.
//
status = SpyCommonDeviceIoControl( Irp->AssociatedIrp.SystemBuffer,
irpStack->Parameters.DeviceIoControl.InputBufferLength,
Irp->AssociatedIrp.SystemBuffer,
irpStack->Parameters.DeviceIoControl.OutputBufferLength,
irpStack->Parameters.DeviceIoControl.IoControlCode,
&Irp->IoStatus );
break;
case IRP_MJ_CLEANUP:
//
// This is the cleanup that we will see when all references
// to a handle opened to FileSpy's control device object are
// cleaned up. We don't have to do anything here since we
// wait until the actual IRP_MJ_CLOSE to clean up the name
// cache. Just complete the IRP successfully.
//
status = STATUS_SUCCESS;
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
}
Irp->IoStatus.Status = status;
//
// We have completed all processing for this IRP, so tell the
// I/O Manager. This IRP will not be passed any further down
// the stack since no drivers below FileSpy care about this
// I/O operation that was directed to FileSpy.
//
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status;
}
return SpyPassThrough( DeviceObject, Irp );
}
NTSTATUS
SpyCreate (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the routine that is associated with IRP_MJ_CREATE IRP. If the
DeviceObject is the ControlDevice, we do the creation work for the
ControlDevice and complete the IRP. Otherwise, we pass through
this IRP for another device to complete.
Note: Some of the code in this function duplicates the functions
SpyDispatch and SpyPassThrough, but a design decision was made that
it was worth the code duplication to break out the IRP handlers
that can be pageable code.
Arguments:
DeviceObject - Pointer to device object Filespy attached to the file system
filter stack for the volume receiving this I/O request.
Irp - Pointer to the request packet representing the I/O request.
Return Value:
If DeviceObject == gControlDeviceObject, then this function will
complete the Irp and return the status of that completion. Otherwise,
this function returns the result of calling SpyPassThrough.
--*/
{
NTSTATUS status;
KIRQL oldIrql;
//
// See if they want to open the control device object for the filter.
// This will only allow one thread to have this object open at a time.
// All other requests will be failed.
//
if (DeviceObject == gControlDeviceObject) {
//
// If the specified debug level is set, output what operation
// we are seeing to the debugger.
//
if (FlagOn( gFileSpyDebugLevel, SPYDEBUG_TRACE_IRP_OPS )) {
SpyDumpIrpOperation( TRUE, Irp );
}
//
// A CREATE request is being made on our gControlDeviceObject.
// See if someone else has it open. If so, disallow this open.
//
KeAcquireSpinLock( &gControlDeviceStateLock, &oldIrql );
if (gControlDeviceState != CLOSED) {
Irp->IoStatus.Status = STATUS_DEVICE_ALREADY_ATTACHED;
Irp->IoStatus.Information = 0;
} else {
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
gControlDeviceState = OPENED;
}
KeReleaseSpinLock( &gControlDeviceStateLock, oldIrql );
//
// Since this is our gControlDeviceObject, we complete the
// IRP here.
//
status = Irp->IoStatus.Status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status;
}
ASSERT( IS_FILESPY_DEVICE_OBJECT( DeviceObject ) );
//
// This is NOT our gControlDeviceObject, so let SpyPassThrough handle
// it appropriately
//
return SpyPassThrough( DeviceObject, Irp );
}
NTSTATUS
SpyClose (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the routine that is associated with IRP_MJ_CLOSE IRP. If the
DeviceObject is the ControlDevice, we do the necessary cleanup and
complete the IRP. Otherwise, we pass through this IRP for another device
to complete.
Arguments:
DeviceObject - Pointer to device object Filespy attached to the file system
filter stack for the volume receiving this I/O request.
Irp - Pointer to the request packet representing the I/O request.
Return Value:
If DeviceObject == gControlDeviceObject, then this function will
complete the Irp and return the status of that completion. Otherwise,
this function returns the result of calling SpyPassThrough.
--*/
{
PAGED_CODE();
//
// See if they are closing the control device object for the filter.
//
if (DeviceObject == gControlDeviceObject) {
//
// If the specified debug level is set, output what operation
// we are seeing to the debugger.
//
if (FlagOn( gFileSpyDebugLevel, SPYDEBUG_TRACE_IRP_OPS )) {
SpyDumpIrpOperation( TRUE, Irp );
}
//
// A CLOSE request is being made on our gControlDeviceObject.
// Cleanup state.
//
SpyCloseControlDevice();
//
// We have completed all processing for this IRP, so tell the
// I/O Manager. This IRP will not be passed any further down
// the stack since no drivers below FileSpy care about this
// I/O operation that was directed to FileSpy.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
ASSERT( IS_FILESPY_DEVICE_OBJECT( DeviceObject ) );
//
// Log (if it is turned on) and pass the request on.
//
return SpyPassThrough( DeviceObject, Irp );
}
NTSTATUS
SpyFsControl (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is invoked whenever an I/O Request Packet (IRP) w/a major
function code of IRP_MJ_FILE_SYSTEM_CONTROL is encountered. For most
IRPs of this type, the packet is simply passed through. However, for
some requests, special processing is required.
Arguments:
DeviceObject - Pointer to the device object for this driver.
Irp - Pointer to the request packet representing the I/O request.
Return Value:
The function value is the status of the operation.
--*/
{
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp );
PAGED_CODE();
//
// If this is for our control device object, fail the operation
//
if (gControlDeviceObject == DeviceObject) {
//
// If the specified debug level is set, output what operation
// we are seeing to the debugger.
//
if (FlagOn( gFileSpyDebugLevel, SPYDEBUG_TRACE_IRP_OPS )) {
SpyDumpIrpOperation( TRUE, Irp );
}
//
// If this device object is our control device object rather than
// a mounted volume device object, then this is an invalid request.
//
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_INVALID_DEVICE_REQUEST;
}
ASSERT(IS_FILESPY_DEVICE_OBJECT( DeviceObject ));
//
// Process the minor function code.
//
switch (pIrpSp->MinorFunction) {
case IRP_MN_MOUNT_VOLUME:
return SpyFsControlMountVolume ( DeviceObject, Irp );
case IRP_MN_LOAD_FILE_SYSTEM:
return SpyFsControlLoadFileSystem ( DeviceObject, Irp );
case IRP_MN_USER_FS_REQUEST:
{
switch (pIrpSp->Parameters.FileSystemControl.FsControlCode) {
case FSCTL_DISMOUNT_VOLUME:
{
PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
SPY_LOG_PRINT( SPYDEBUG_DISPLAY_ATTACHMENT_NAMES,
("FILESPY!SpyFsControl: Dismounting volume %p \"%wZ\"\n",
devExt->NLExtHeader.AttachedToDeviceObject,
&devExt->NLExtHeader.DeviceName) );
break;
}
}
break;
}
}
//
// This is a regular FSCTL that we need to let the filters see
// Just do the callbacks for all the filters & passthrough
//
return SpyPassThrough( DeviceObject, Irp );
}
NTSTATUS
SpyFsControlCompletion (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine is invoked for the completion of a mount/LoadFS request. This
will load the IRP and then signal the waiting dispatch routine.
Arguments:
DeviceObject - Pointer to this driver's device object that was attached to
the file system device object
Irp - Pointer to the IRP that was just completed.
Context - Pointer to the device object allocated during the down path so
we wouldn't have to deal with errors here.
Return Value:
The return value is always STATUS_SUCCESS.
--*/
{
PRECORD_LIST recordList = ((PSPY_COMPLETION_CONTEXT)Context)->RecordList;
ASSERT(IS_FILESPY_DEVICE_OBJECT( DeviceObject ));
UNREFERENCED_PARAMETER( DeviceObject );
//
// Log the completion (if we need to)
//
if (NULL != recordList) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -