📄 filespy.c
字号:
devName = NLGetAndAllocateObjectName( DeviceObject,
&gFileSpyNameBufferLookasideList );
if (devName == NULL) {
// SPY_LOG_PRINT( SPYDEBUG_DISPLAY_ATTACHMENT_NAMES,
// ("FileSpy!SpyFsNotification: Not attaching to %p, insufficient resources.\n",
// DeviceObject) );
return;
}
// SPY_LOG_PRINT( SPYDEBUG_DISPLAY_ATTACHMENT_NAMES,
// ("FileSpy!SpyFsNotification: %s %p \"%wZ\" (%s)\n",
// (FsActive) ? "Activating file system " : "Deactivating file system",
// DeviceObject,
// &devName->Name,
// GET_DEVICE_TYPE_NAME(DeviceObject->DeviceType)) );
//
// See if we want to ATTACH or DETACH from the given file system.
//
if (FsActive) {
SpyAttachToFileSystemDevice( DeviceObject, devName );
} else {
SpyDetachFromFileSystemDevice( DeviceObject );
}
//
// We're done with name (SpyAttachToFileSystemDevice copies the name to
// the device extension) so free it.
//
NLFreeNameControl( devName, &gFileSpyNameBufferLookasideList );
}
NTSTATUS
SpyPassThrough (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the main dispatch routine for the general purpose file
system driver. It simply passes requests onto the next driver in the
stack, which is presumably a disk file system, while logging any
relevant information if logging is turned on for this DeviceObject.
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:
The function value is the status of the operation.
Note:
This routine passes the I/O request through to the next driver
*without* removing itself from the stack (like sfilter) since it could
want to see the result of this I/O request.
To remain in the stack, we have to copy the caller's parameters to the
next stack location. Note that we do not want to copy the caller's I/O
completion routine into the next stack location, or the caller's routine
will get invoked twice. This is why we NULL out the Completion routine.
If we are logging this device, we set our own Completion routine.
--*/
{
// PRECORD_LIST recordList = NULL;
// KEVENT waitEvent;
NTSTATUS status;
// BOOLEAN syncToDispatch;
ASSERT(IS_FILESPY_DEVICE_OBJECT( 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 );
// }
//
// See if we should log this IRP
//
/* if (SHOULD_LOG( DeviceObject )) {
//
// The ControlDevice is opened, so allocate the Record
// and log the Irp information if we have the memory.
//
recordList = SpyNewRecord(0);
if (NULL != recordList) {
SpyLogIrp( Irp, recordList );
//
// Since we are logging this operation, we want to
// call our completion routine.
//
IoCopyCurrentIrpStackLocationToNext( Irp );
KeInitializeEvent( &waitEvent,
NotificationEvent,
FALSE );
recordList->WaitEvent = &waitEvent;
IoSetCompletionRoutine( Irp,
SpyPassThroughCompletion,
recordList,
TRUE,
TRUE,
TRUE);
} else {
//
// We could not get a record to log with so get this driver out
// of the driver stack and get to the next driver as quickly as
// possible.
//
IoSkipCurrentIrpStackLocation( Irp );
}
} else {*/
//
// We are not logging so get this driver out of the driver stack and
// get to the next driver as quickly as possible.
//
IoSkipCurrentIrpStackLocation( Irp );
// }
//
// Determine if we are syncing back to the dispatch routine. We need to
// do this before calling down because the recordList entry could be free
// upon return.
//
// syncToDispatch = ((NULL != recordList) &&
// (FlagOn(recordList->Flags,RLFL_SYNC_TO_DISPATCH)));
//
// Now call the next file system driver with the request.
//
status = IoCallDriver( ((PFILESPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
Irp );
//
// If we are logging and we need to synchronize back to our dispatch
// routine for completion processing, do it now.
//
/* if (syncToDispatch) {
//
// We are syncing back to the dispatch routine, wait for the operation
// to complete.
//
if (STATUS_PENDING == status) {
status = KeWaitForSingleObject( &waitEvent,
Executive,
KernelMode,
FALSE,
NULL );
ASSERT(STATUS_SUCCESS == status);
}
//
// Verify the completion has actually been run
//
ASSERT(KeReadStateEvent(&waitEvent) ||
!NT_SUCCESS(Irp->IoStatus.Status));
//
// Do completion processing
//
SpyLogIrpCompletion( Irp, recordList );
//
// Continue processing the operation
//
status = Irp->IoStatus.Status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
}*/
return status;
}
NTSTATUS
SpyPassThroughCompletion (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine is the completion routine SpyPassThrough. This is used
to log the information that can only be gathered after the I/O request
has been completed.
Once we are done logging all the information we care about, we append
the record to the gOutputBufferList to be returned to the user.
Note: This routine will only be set if we were trying to log the
specified device when the Irp originated and we were able to
allocate a record to store this logging information.
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.
Context - Pointer to the RECORD_LIST structure in which we store the
information we are logging.
Return Value:
The function value is the status of the operation.
--*/
{
// PRECORD_LIST recordList = (PRECORD_LIST)Context;
ASSERT(IS_FILESPY_DEVICE_OBJECT( DeviceObject ));
UNREFERENCED_PARAMETER( DeviceObject );
UNREFERENCED_PARAMETER( Context );
//
// If the specified debug level is set, output what operation
// we are seeing to the debugger.
//
// if (FlagOn( gFileSpyDebugLevel, SPYDEBUG_TRACE_IRP_OPS )) {
// SpyDumpIrpOperation( FALSE, Irp );
// }
//
// If we are to SYNC back to the dispatch routine, signal the event
// and return
//
/* if (FlagOn(recordList->Flags,RLFL_SYNC_TO_DISPATCH)) {
KeSetEvent( recordList->WaitEvent, IO_NO_INCREMENT, FALSE );
//
// When syncing back to the dispatch routine do not propagate the
// IRP_PENDING flag.
//
return STATUS_MORE_PROCESSING_REQUIRED;
}
//
// Do completion log processing
//
SpyLogIrpCompletion( Irp, recordList );*/
//
// Propagate the IRP pending flag.
//
if (Irp->PendingReturned) {
IoMarkIrpPending( Irp );
}
return STATUS_SUCCESS;
}
NTSTATUS
SpyDispatch (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This function completes all requests on the gControlDeviceObject
(FileSpy's device object) and passes all other requests on to the
SpyPassThrough function.
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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -