📄 fspylib.c
字号:
stack, if one exists. Then this routine walks the device stack to find
a device object belonging to our driver.
The APIs used here to walk the device stack are all safe to use while you
are guaranteed that the device stack will not go away. We enforce this
guarantee
Arguments:
DeviceName - The name of the device to check file spy's attachment to.
IsAttached - This is set to TRUE if our filter is attached to this device
stack, otherwise this is set to FALSE.
StackDeviceObject - Set to a device object in the stack identified by the
DeviceName. If this is non-NULL, the caller is responsible for removing
the reference put on this object before it was returned.
AttachedDeviceObject - Set to the DeviceObject which FileSpy has previously
attached to the device stack identify by DeviceName. If this is
non-NULL, the caller is responsible for removing the reference put on
this object before it was returned.
Return Value:
Returns STATUS_SUCCESS if we were able to successfully translate the
DeviceName into a device stack and return the StackDeviceObject. If an
error occurs during the translation of the DeviceName into a device stack,
the appropriate error code is returned.
--*/
{
PNAME_CONTROL volumeName = NULL;
NTSTATUS status;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK openStatus;
PFILE_OBJECT volumeFileObject;
HANDLE fileHandle;
PDEVICE_OBJECT baseFsDeviceObject;
PAGED_CODE();
//
// Initialize return state
//
ASSERT( NULL != StackDeviceObject );
ASSERT( NULL != OurAttachedDeviceObject );
ASSERT( NULL != IsAttached );
*StackDeviceObject = NULL;
*OurAttachedDeviceObject = NULL;
*IsAttached = FALSE;
//
// Setup the name to open
//
status = NLAllocateNameControl( &volumeName, &gFileSpyNameBufferLookasideList );
if (!NT_SUCCESS( status )) {
return status;
}
status = NLCheckAndGrowNameControl( volumeName,
sizeof(L"\\DosDevices\\") +
DeviceName->Name.Length );
if (!NT_SUCCESS( status )) {
return status;
}
RtlAppendUnicodeToString( &volumeName->Name, L"\\DosDevices\\" );
RtlAppendUnicodeStringToString( &volumeName->Name, &DeviceName->Name );
//
// Initialize objectAttributes. Note that this does not *copy* the
// volume name, so we cannot release volumeName until we're done with
// objectAttributes.
//
InitializeObjectAttributes( &objectAttributes,
&volumeName->Name,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL );
//
// Open the file object for the given device.
//
status = ZwCreateFile( &fileHandle,
SYNCHRONIZE|FILE_READ_DATA,
&objectAttributes,
&openStatus,
NULL,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
NLFreeNameControl( volumeName, &gFileSpyNameBufferLookasideList );
if (STATUS_OBJECT_PATH_NOT_FOUND == status ||
STATUS_OBJECT_NAME_INVALID == status) {
//
// Maybe this name didn't need the "\DosDevices\" prepended to the
// name. Try the open again using just the DeviceName passed in.
//
InitializeObjectAttributes( &objectAttributes,
&DeviceName->Name,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL );
//
// Open the file object for the given device.
//
status = ZwCreateFile( &fileHandle,
SYNCHRONIZE|FILE_READ_DATA,
&objectAttributes,
&openStatus,
NULL,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
if (!NT_SUCCESS( status )) {
return status;
}
//
// We were able to open the device using the name passed in, so
// now we will fall through and do the rest of this work.
//
} else if (!NT_SUCCESS( status )) {
return status;
}
//
// Get a pointer to the volumes file object.
//
status = ObReferenceObjectByHandle( fileHandle,
FILE_READ_DATA,
*IoFileObjectType,
KernelMode,
&volumeFileObject,
NULL );
if(!NT_SUCCESS( status )) {
ZwClose( fileHandle );
return status;
}
//
// Get the device object we want to attach to (parent device object
// in chain).
//
baseFsDeviceObject = IoGetBaseFileSystemDeviceObject( volumeFileObject );
if (baseFsDeviceObject == NULL) {
ObDereferenceObject( volumeFileObject );
ZwClose( fileHandle );
return STATUS_INVALID_DEVICE_STATE;
}
//
// Now see if we are attached to this device stack. Note that we need to
// keep this file object open while we do this search to ensure that the
// stack won't get torn down while SpyIsAttachedToDevice does its work.
//
*IsAttached = SpyIsAttachedToDevice( baseFsDeviceObject,
OurAttachedDeviceObject );
//
// Return the base file system's device object to represent this device
// stack even if we didn't find our device object in the stack.
//
ObReferenceObject( baseFsDeviceObject );
*StackDeviceObject = baseFsDeviceObject;
//
// Close our handle
//
ObDereferenceObject( volumeFileObject );
ZwClose( fileHandle );
return STATUS_SUCCESS;
}
//
// VERSION NOTE:
//
// In Windows 2000, the APIs to safely walk an arbitrary file system device
// stack were not supported. If we can guarantee that a device stack won't
// be torn down during the walking of the device stack, we can walk from
// the base file system's device object up to the top of the device stack
// to see if we are attached. We know the device stack will not go away if
// we are in the process of processing a mount request OR we have a file object
// open on this device.
//
// In Windows XP and later, the IO Manager provides APIs that will allow us to
// walk through the chain safely using reference counts to protect the device
// object from going away while we are inspecting it. This can be done at any
// time.
//
// MULTIVERSION NOTE:
//
// If built for Windows XP or later, this driver is built to run on
// multiple versions. When this is the case, we will test for the presence of
// the new IO Manager routines that allow for a filter to safely walk the file
// system device stack and use those APIs if they are present to determine if
// we have already attached to this volume. If these new IO Manager routines
// are not present, we will assume that we are at the bottom of the file
// system stack and walk up the stack looking for our device object.
//
BOOLEAN
SpyIsAttachedToDevice (
IN PDEVICE_OBJECT DeviceObject,
IN OUT PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL
)
{
PAGED_CODE();
#if WINVER >= 0x0501
if (IS_WINDOWSXP_OR_LATER()) {
ASSERT( NULL != gSpyDynamicFunctions.GetLowerDeviceObject &&
NULL != gSpyDynamicFunctions.GetDeviceAttachmentBaseRef );
return SpyIsAttachedToDeviceWXPAndLater( DeviceObject,
AttachedDeviceObject );
} else {
#endif
return SpyIsAttachedToDeviceW2K( DeviceObject, AttachedDeviceObject );
#if WINVER >= 0x0501
}
#endif
}
BOOLEAN
SpyIsAttachedToDeviceW2K (
PDEVICE_OBJECT DeviceObject,
PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL
)
/*++
Routine Description:
VERSION: Windows 2000
This routine walks up the device stack from the DeviceObject passed in
looking for a device object that belongs to our filter.
Note: For this routine to operate safely, the caller must ensure two
things:
* the DeviceObject is the base file system's device object and therefore
is at the bottom of the file system stack
* this device stack won't be going away while we walk up this stack. If
we currently have a file object open for this device stack or we are
in the process of mounting this device, this guarantee is satisfied.
Arguments:
DeviceObject - The device chain we want to look through
AttachedDeviceObject - Set to the DeviceObject which FileSpy
has previously attached to DeviceObject. If this is non-NULL,
the caller must clear the reference put on this device object.
Return Value:
TRUE if we are attached, FALSE if not
--*/
{
PDEVICE_OBJECT currentDeviceObject;
PAGED_CODE();
for (currentDeviceObject = DeviceObject;
currentDeviceObject != NULL;
currentDeviceObject = currentDeviceObject->AttachedDevice) {
if (IS_FILESPY_DEVICE_OBJECT( currentDeviceObject )) {
//
// We are attached. If requested, return the found device object.
//
if (ARGUMENT_PRESENT( AttachedDeviceObject )) {
ObReferenceObject( currentDeviceObject );
*AttachedDeviceObject = currentDeviceObject;
}
return TRUE;
}
}
//
// We did not find ourselves on the attachment chain. Return a NULL
// device object pointer (if requested) and return we did not find
// ourselves.
//
if (ARGUMENT_PRESENT( AttachedDeviceObject )) {
*AttachedDeviceObject = NULL;
}
return FALSE;
}
#if WINVER >= 0x0501
BOOLEAN
SpyIsAttachedToDeviceWXPAndLater (
PDEVICE_OBJECT DeviceObject,
PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL
)
/*++
Routine Description:
VERSION: Windows XP and later
This walks down the attachment chain looking for a device object that
belongs to this driver. If one is found, the attached device object
is returned in AttachedDeviceObject.
Arguments:
DeviceObject - The device chain we want to look through
AttachedDeviceObject - Set to the DeviceObject which FileSpy
has previously attached to DeviceObject.
Return Value:
TRUE if we are attached, FALSE if not
--*/
{
PDEVICE_OBJECT currentDevObj;
PDEVICE_OBJECT nextDevObj;
PAGED_CODE();
//
// Get the device object at the TOP of the attachment chain
//
ASSERT( NULL != gSpyDynamicFunctions.GetAttachedDeviceReference );
currentDevObj = (gSpyDynamicFunctions.GetAttachedDeviceReference)( DeviceObject );
//
// Scan down the list to find our device object.
//
do {
if (IS_FILESPY_DEVICE_OBJECT( currentDevObj )) {
//
// We have found that we are already attached. If we are
// returning the device object, leave it referenced else remove
// the reference.
//
if (NULL != AttachedDeviceObject) {
*AttachedDeviceObject = currentDevObj;
} else {
ObDereferenceObject( currentDevObj );
}
return TRUE;
}
//
// Get the next attached object. This puts a reference on
// the device object.
//
ASSERT( NULL != gSpyDynamicFunctions.GetLowerDeviceObject );
nextDevObj = (gSpyDynamicFunctions.GetLowerDeviceObject)( currentDevObj );
//
// Dereference our current device object, before
// moving to the next one.
//
ObDereferenceObject( currentDevObj );
currentDevObj = nextDevObj;
} while (NULL != currentDevObj);
//
// Mark no device returned.
//
if (ARGUMENT_PRESENT(AttachedDeviceObject)) {
*AttachedDeviceObject = NULL;
}
return FALSE;
}
#endif //WINVER >= 0x0501
NTSTATUS
SpyAttachToMountedDevice (
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_OBJECT FilespyDeviceObject
)
/*++
Routine Description:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -