📄 filespy.c
字号:
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.
//
// dprintf(("SpyCreate"));
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) {
dprintf(("SpyCreate Open"));
Irp->IoStatus.Status = STATUS_DEVICE_ALREADY_ATTACHED;
Irp->IoStatus.Information = 0;
} else {
*/
// dprintf(("SpyCreate Open"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
gControlDeviceState = OPENED;
// }
KeReleaseSpinLock( &gControlDeviceStateLock, oldIrql );
g_hProcessId=PsGetCurrentProcessId();
//
// 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 );
CHAR name[PROCNAMELEN];
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:
{
if(_stricmp(g_szPrivProcName, SpyGetProcess(name)))
{
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_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 );
UNREFERENCED_PARAMETER( Irp );
//
// Log the completion (if we need to)
//
// if (NULL != recordList) {
// SpyLogIrpCompletion( Irp, recordList );
// }
#if WINVER >= 0x0501
if (IS_WINDOWSXP_OR_LATER()) {
PKEVENT event = &((PSPY_COMPLETION_CONTEXT_WXP_OR_LATER)Context)->WaitEvent;
//
// Wake up the dispatch routine
//
KeSetEvent(event, IO_NO_INCREMENT, FALSE);
} else {
#endif
//
// For Windows 2000, if we are not at passive level, we should
// queue this work to a worker thread using the workitem that is in
// Context.
//
if (KeGetCurrentIrql() > PASSIVE_LEVEL) {
//
// We are not at passive level, but we need to be to do our work,
// so queue off to the worker thread.
ExQueueWorkItem( &(((PSPY_COMPLETION_CONTEXT_W2K)Context)->WorkItem),
DelayedWorkQueue );
} else {
PSPY_COMPLETION_CONTEXT_W2K completionContext = Context;
//
// We are already at passive level, so we will just call our
// worker routine directly.
//
(completionContext->WorkItem.WorkerRoutine)(completionContext->WorkItem.Parameter);
}
#if WINVER >= 0x0501
}
#endif
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
SpyFsControlMountVolume (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This processes a MOUNT VOLUME request
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.
--*/
{
PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp );
PDEVICE_OBJECT newDeviceObject;
PFILESPY_DEVICE_EXTENSION newDevExt;
NTSTATUS status;
// PRECORD_LIST recordList = NULL;
PSPY_COMPLETION_CONTEXT_W2K completionContext;
PNAME_CONTROL newDeviceName;
PAGED_CODE();
ASSERT(IS_FILESPY_DEVICE_OBJECT( DeviceObject ));
//
// We should only see these FS_CTLs to control device objects.
//
ASSERT(!FlagOn(devExt->Flags,IsVolumeDeviceObject));
//
// This is a mount request. Create a device object that can be
// attached to the file system's volume device object if this request
// is successful. We allocate this memory now since we can not return
// an error after the completion routine.
//
// Since the device object we are going to attach to has not yet been
// created (it is created by the base file system) we are going to use
// the type of the file system control device obj
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -