📄 filespy.c
字号:
FileCtxPtr2->DeleteOnClose = DeleteOnClose;
ExReleaseFastMutex(&DevExt->FsCtxTableMutex);
IsNeedEncrypt = FALSE;
// we need handle file synchronously
KeWaitForSingleObject(&FileCtxPtr2->Event, Executive, KernelMode, FALSE, NULL);
KeSetEvent(&FileCtxPtr2->Event, IO_NO_INCREMENT, FALSE);
}
*/
if (newName != NULL) {
NLFreeNameControl( newName, &gFileSpyNameBufferLookasideList );
}
// Irp->IoStatus.Status = status;
//IoCompleteRequest(Irp, IO_NO_INCREMENT);
// return status;
//
// This is NOT our gControlDeviceObject, so let SpyPassThrough handle
// it appropriately
//
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->NLExtHeader.AttachedToDeviceObject, Irp);
// 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) {
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 object. We are assuming
// that the file system control device object will have the same type
// as the volume device objects associated with it.
//
status = IoCreateDevice( gFileSpyDriverObject,
sizeof( FILESPY_DEVICE_EXTENSION ),
NULL,
DeviceObject->DeviceType,
0,
FALSE,
&newDeviceObject );
if (!NT_SUCCESS( status )) {
//
// If we can not attach to the volume, then simply skip it.
//
SPY_LOG_PRINT( SPYDEBUG_ERROR,
("FileSpy!SpyFsControlMountVolume: Error creating volume device object, status=%08x\n",
status) );
return SpyPassThrough( DeviceObject, Irp );
}
newDevExt = newDeviceObject->DeviceExtension;
//
// Initialize the name lookup device extension header
//
// We need to save the RealDevice object pointed to by the VPB
// parameter because this VPB may be changed by the underlying
// file system. Both FAT and CDFS may change the VPB address if
// the volume being mounted is one they recognize from a previous
// mount.
//
//
NLInitDeviceExtensionHeader( &newDevExt->NLExtHeader,
newDeviceObject,
pIrpSp->Parameters.MountVolume.Vpb->RealDevice );
newDevExt->Flags = 0;
RtlInitEmptyUnicodeString( &newDevExt->UserNames, NULL, 0 );
//
// Get the name of this device
//
# define MVInsufResMsg "FileSpy!SpyFsControlMountVolume: Error getting device name, insufficient resources, status=%08x\n"
newDeviceName = NLGetAndAllocateObjectName( newDevExt->NLExtHeader.StorageStackDeviceObject,
&gFileSpyNameBufferLookasideList );
if (newDeviceName == NULL) {
//
// Can't allocate space for retrieving the device name. Skip device.
//
SPY_LOG_PRINT( SPYDEBUG_ERROR,
(MVInsufResMsg,
status) );
IoDeleteDevice( newDeviceObject );
return SpyPassThrough( DeviceObject, Irp );
}
//
// Save the name in our device object extension
//
status = NLAllocateAndCopyUnicodeString( &newDevExt->NLExtHeader.DeviceName,
&newDeviceName->Name,
FILESPY_DEVNAME_TAG );
//
// Release name control
//
NLFreeNameControl( newDeviceName, &gFileSpyNameBufferLookasideList );
//
// If we couldn't copy the name we are low on resources, quit now
//
if (!NT_SUCCESS(status)) {
SPY_LOG_PRINT( SPYDEBUG_ERROR,
(MVInsufResMsg,
status) );
IoDeleteDevice( newDeviceObject);
return SpyPassThrough( DeviceObject, Irp );
}
//
// Since we have our own private completion routine we need to
// do our own logging of this operation, do it now.
//
if (SHOULD_LOG( DeviceObject )) {
//
// Lock the IRP if we can
//
recordList = SpyNewRecord(0);
if (recordList) {
SpyLogIrp( Irp, recordList );
}
}
//
// Initialize some useful variables
//
ExInitializeFastMutex(&newDevExt->FsCtxTableMutex);
RtlInitializeGenericTable(&newDevExt->FsCtxTable,
SfGenericCompareRoutine,
SfGenericAllocateRoutine,
SfGenericFreeRoutine,
NULL
);
//
// Send the IRP to the legacy filters. Note that the IRP we are sending
// down is for our CDO, not the new VDO that we have been passing to
// the mini-filters.
//
//
// VERSION NOTE:
//
// On Windows 2000, we cannot simply synchronize back to the dispatch
// routine to do our post-mount processing. We need to do this work at
// passive level, so we will queue that work to a worker thread from
// the completion routine.
//
// For Windows XP and later, we can safely synchronize back to the dispatch
// routine. The code below s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -