?? filespy.c
字號:
)
/*++
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 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.
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.
--*/
{
PDEVICE_EXTENSION pDeviceExtension;
PIO_STACK_LOCATION pIrpStack,pNextIrpSp;
UCHAR loggingFlags = 0;
KIRQL oldIrql;
pDeviceExtension = DeviceObject->DeviceExtension;
pIrpStack = IoGetCurrentIrpStackLocation( Irp );
pNextIrpSp = IoGetNextIrpStackLocation( Irp );
//
// FileSpy needs to consume a stack location if it wants to receive
// a callback on the I/O operation's completion path. FileSpy
// does not change any of the parameters, so just copy the caller's
// parameters (which includes the caller's completion routine)
// to the next stack location. FileSpy then must clear the completion
// routine since we don't want the caller's routine to be called (resulting
// in that completion routine being called twice). FileSpy will set
// its own completion routine in the case that it wants the completion.
//
RtlMoveMemory( pNextIrpSp, pIrpStack, sizeof( IO_STACK_LOCATION ) );
IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE );
if (SHOULD_LOG(DeviceObject)) {
PRECORD_LIST recordList;
//
// The ControlDevice is opened, so allocate the Record
// and log the Irp information if we have the memory.
//
recordList = SpyNewRecord(0);
if (recordList) {
loggingFlags |= LOG_ORIGINATING_IRP;
SpyLogIrp( Irp, loggingFlags, recordList );
//
// Since we are logging this operation, we want to
// see its completion so register our completion
// routine.
//
IoSetCompletionRoutine(
Irp,
SpyPassThroughCompletion,
(PVOID)recordList,
TRUE,
TRUE,
TRUE);
}
}
//
// If this is a IRP_MJ_CLOSE see if the FileObject's name is being
// cached and remove it from the cache if it is. We want to do this
// as long as the ControlDevice is opened so that we purge the
// cache as accurately as possible.
//
ExAcquireSpinLock( &gControlDeviceStateLock, &oldIrql );
if (gControlDeviceState == OPENED) {
if (pIrpStack->MajorFunction == IRP_MJ_CLOSE) {
SpyNameDelete(pIrpStack->FileObject);
}
}
ExReleaseSpinLock( &gControlDeviceStateLock, oldIrql );
//
// Now call the appropriate file system driver with the request.
//
return IoCallDriver( pDeviceExtension->NextDriverDeviceObject, Irp );
}
DBGSTATIC
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 the device object for this driver.
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;
UCHAR loggingFlags = 0;
recordList = (PRECORD_LIST)Context;
if (SHOULD_LOG(DeviceObject))
{
loggingFlags |= LOG_COMPLETION_IRP;
SpyLogIrp( Irp, loggingFlags, recordList );
//
// Add recordList to our gOutputBufferList so that it gets up to
// the user
//
SpyLog(recordList);
} else {
if (recordList) {
//
// Context is set with a RECORD_LIST, but we are no longer
// logging so free this record.
//
SpyFreeRecord(recordList);
}
}
//
// Propogate the IRP pending flag. All completion routines
// need to do this.
//
if (Irp->PendingReturned) {
IoMarkIrpPending( Irp );
}
return STATUS_SUCCESS;
}
DBGSTATIC
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 the device object for this driver.
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().
--*/
{
ULONG status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack;
KIRQL oldIrql;
if (DeviceObject == gControlDeviceObject) {
//
// A request is being made on our device object, gControlDeviceObject.
//
Irp->IoStatus.Information = 0;
irpStack = IoGetCurrentIrpStackLocation( Irp );
switch (irpStack->MajorFunction) {
case IRP_MJ_CLOSE:
SpyCloseControlDevice();
break;
default:
status = STATUS_INVALID_PARAMETER;
}
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 );
}
DBGSTATIC
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 pagable code.
Arguments:
DeviceObject - Pointer to the device object for this driver.
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.
--*/
{
ULONG status = STATUS_SUCCESS;
PIO_STACK_LOCATION pIrpStack;
KIRQL oldIrql;
if (DeviceObject == gControlDeviceObject) {
//
// A CREATE request is being made on our gControlDeviceObject
//
ExAcquireSpinLock( &gControlDeviceStateLock, &oldIrql );
if (gControlDeviceState != CLOSED) {
status = STATUS_DEVICE_ALREADY_ATTACHED;
} else {
gControlDeviceState = OPENED;
}
ExReleaseSpinLock( &gControlDeviceStateLock, oldIrql );
//
// Since this is our gControlDeviceObject, we complete the
// irp here.
//
Irp->IoStatus.Status = status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status;
}
//
//
// This is a CREATE so we need to invalidate the name currently
// stored in the name cache for this FileObject. We need to do
// this as long as our ControlDevice is open so that we keep the
// name cache up-to-date.
//
pIrpStack = IoGetCurrentIrpStackLocation( Irp );
ExAcquireSpinLock( &gControlDeviceStateLock, &oldIrql );
if (gControlDeviceState == OPENED) {
SpyNameDelete(pIrpStack->FileObject);
}
ExReleaseSpinLock( &gControlDeviceStateLock, oldIrql );
// This is NOT our gControlDeviceObject, so let SpyPassThrough handle
// it appropriately
//
return SpyPassThrough( DeviceObject, Irp );
}
DBGSTATIC
BOOLEAN
SpyFastIoCheckIfPossible(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN BOOLEAN CheckForReadOperation,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine is the fast I/O "pass through" routine for checking to see
whether fast I/O is possible for this file.
This function simply invokes the next driver's cooresponding routine, or
returns FALSE if the next driver does not implement the function.
Arguments:
FileObject - Pointer to the file object to be operated on.
FileOffset - Byte offset in the file for the operation.
Length - Length of the operation to be performed.
Wait - Indicates whether or not the caller is willing to wait if the
appropriate locks, etc. cannot be acquired
LockKey - Provides the caller's key for file locks.
CheckForReadOperation - Indicates whether the caller is checking for a
read (TRUE) or a write operation.
IoStatus - Pointer to a variable to receive the I/O status of the
operation.
DeviceObject - Pointer to this driver's device object, the device on
which the operation is to occur.
Return Value:
The function value is TRUE or FALSE based on whether or not fast I/O
is possible for this file.
--*/
{
PDEVICE_OBJECT deviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
BOOLEAN returnValue;
PRECORD_LIST recordList;
BOOLEAN shouldLog;
PAGED_CODE();
if (DeviceObject->DeviceExtension == NULL) {
return FALSE;
}
if (shouldLog = SHOULD_LOG(DeviceObject)) {
//
// Log the necessary information for the start of the Fast I/O
// operation
//
recordList = SpyLogFastIoStart(
CHECK_IF_POSSIBLE,
0,
FileObject,
FileOffset,
Length,
Wait );
}
//
// Pass through logic for this type of Fast I/O
//
deviceObject =
((PDEVICE_EXTENSION) (DeviceObject->DeviceExtension))->
NextDriverDeviceObject;
if (!deviceObject) {
returnValue = FALSE;
goto SpyFastIoCheckIfPossible_Exit;
}
fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoCheckIfPossible )) {
returnValue = (fastIoDispatch->FastIoCheckIfPossible)( FileObject,
FileOffset,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -