📄 filespy.c
字号:
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 );
}
}
//
// 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 shows both methods. Admittedly, the code
// would be simplified if you chose to only use one method or the other,
// but you should be able to easily adapt this for your needs.
//
#if WINVER >= 0x0501
if (IS_WINDOWSXP_OR_LATER()) {
SPY_COMPLETION_CONTEXT_WXP_OR_LATER completionContext;
IoCopyCurrentIrpStackLocationToNext ( Irp );
completionContext.RecordList = recordList;
KeInitializeEvent( &completionContext.WaitEvent,
NotificationEvent,
FALSE );
IoSetCompletionRoutine( Irp,
SpyFsControlCompletion,
&completionContext, //context parameter
TRUE,
TRUE,
TRUE );
status = IoCallDriver( devExt->NLExtHeader.AttachedToDeviceObject, Irp );
//
// Wait for the operation to complete
//
if (STATUS_PENDING == status) {
status = KeWaitForSingleObject( &completionContext.WaitEvent,
Executive,
KernelMode,
FALSE,
NULL );
ASSERT(STATUS_SUCCESS == status);
}
//
// Verify the IoCompleteRequest was called
//
ASSERT(KeReadStateEvent(&completionContext.WaitEvent) ||
!NT_SUCCESS(Irp->IoStatus.Status));
status = SpyFsControlMountVolumeComplete( DeviceObject,
Irp,
newDeviceObject );
} else {
#endif
completionContext = ExAllocatePoolWithTag( NonPagedPool,
sizeof( SPY_COMPLETION_CONTEXT_W2K ),
FILESPY_CONTEXT_TAG );
if (completionContext == NULL) {
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( devExt->NLExtHeader.AttachedToDeviceObject, Irp );
} else {
completionContext->RecordList = recordList;
ExInitializeWorkItem( &completionContext->WorkItem,
SpyFsControlMountVolumeCompleteWorker,
completionContext );
completionContext->DeviceObject = DeviceObject,
completionContext->Irp = Irp;
completionContext->NewDeviceObject = newDeviceObject;
IoCopyCurrentIrpStackLocationToNext ( Irp );
IoSetCompletionRoutine( Irp,
SpyFsControlCompletion,
completionContext, //context parameter
TRUE,
TRUE,
TRUE );
status = IoCallDriver( devExt->NLExtHeader.AttachedToDeviceObject, Irp );
}
#if WINVER >= 0x0501
}
#endif
return status;
}
VOID
SpyFsControlMountVolumeCompleteWorker (
IN PSPY_COMPLETION_CONTEXT_W2K Context
)
/*++
Routine Description:
The worker thread routine that will call our common routine to do the
post-MountVolume work.
Arguments:
Context - The context passed to this worker thread.
Return Value:
None.
--*/
{
SpyFsControlMountVolumeComplete( Context->DeviceObject,
Context->Irp,
Context->NewDeviceObject );
ExFreePoolWithTag( Context, FILESPY_CONTEXT_TAG );
}
NTSTATUS
SpyFsControlMountVolumeComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PDEVICE_OBJECT NewDeviceObject
)
/*++
Routine Description:
This does the post-Mount work and must be done at PASSIVE_LEVEL.
Arguments:
DeviceObject - The device object for this operation,
Irp - The IRP for this operation that we will complete once we are finished
with it.
Return Value:
Returns the status of the mount operation.
--*/
{
PVPB vpb;
PFILESPY_DEVICE_EXTENSION newDevExt = NewDeviceObject->DeviceExtension;
PDEVICE_OBJECT attachedDeviceObject;
NTSTATUS status;
BOOLEAN justAttached = FALSE;
PAGED_CODE();
//
// Get the correct VPB from the real device object saved in our
// device extension. We do this because the VPB in the IRP stack
// may not be the correct VPB when we get here. The underlying
// file system may change VPBs if it detects a volume it has
// mounted previously.
//
vpb = newDevExt->NLExtHeader.StorageStackDeviceObject->Vpb;
//
// See if the mount was successful.
//
if (NT_SUCCESS( Irp->IoStatus.Status )) {
//
// Acquire lock so we can atomically test if we area already attached
// and if not, then attach. This prevents a double attach race
// condition.
//
ExAcquireFastMutex( &gSpyAttachLock );
//
// The mount succeeded. If we are not already attached, attach to the
// device object. Note: one reason we could already be attached is
// if the underlying file system revived a previous mount.
//
if (!SpyIsAttachedToDevice( vpb->DeviceObject,
&attachedDeviceObject )) {
//
// Attach to the new mounted volume. The correct file system
// device object that w
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -