You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1246 lines
31 KiB
1246 lines
31 KiB
/*++
|
|
|
|
Copyright (c) 1998-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
fastio.c
|
|
|
|
Abstract:
|
|
|
|
This module performs the hooks for the fast i/o path.
|
|
|
|
Author:
|
|
|
|
Paul McDaniel (paulmcd) 01-Mar-2000
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
//
|
|
// Private constants.
|
|
//
|
|
|
|
//
|
|
// Private types.
|
|
//
|
|
|
|
//
|
|
// Private prototypes.
|
|
//
|
|
|
|
//
|
|
// linker commands
|
|
//
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
|
|
#pragma alloc_text( PAGE, SrFastIoCheckIfPossible )
|
|
#pragma alloc_text( PAGE, SrFastIoRead )
|
|
#pragma alloc_text( PAGE, SrFastIoWrite )
|
|
#pragma alloc_text( PAGE, SrFastIoQueryBasicInfo )
|
|
#pragma alloc_text( PAGE, SrFastIoQueryStandardInfo )
|
|
#pragma alloc_text( PAGE, SrFastIoLock )
|
|
#pragma alloc_text( PAGE, SrFastIoUnlockSingle )
|
|
#pragma alloc_text( PAGE, SrFastIoUnlockAll )
|
|
#pragma alloc_text( PAGE, SrFastIoUnlockAllByKey )
|
|
#pragma alloc_text( PAGE, SrFastIoDeviceControl )
|
|
#pragma alloc_text( PAGE, SrPreAcquireForSectionSynchronization )
|
|
#pragma alloc_text( PAGE, SrFastIoDetachDevice )
|
|
#pragma alloc_text( PAGE, SrFastIoQueryNetworkOpenInfo )
|
|
#pragma alloc_text( PAGE, SrFastIoMdlRead )
|
|
#pragma alloc_text( PAGE, SrFastIoMdlReadComplete )
|
|
#pragma alloc_text( PAGE, SrFastIoPrepareMdlWrite )
|
|
#pragma alloc_text( PAGE, SrFastIoMdlWriteComplete )
|
|
#pragma alloc_text( PAGE, SrFastIoReadCompressed )
|
|
#pragma alloc_text( PAGE, SrFastIoWriteCompressed )
|
|
#pragma alloc_text( PAGE, SrFastIoMdlReadCompleteCompressed )
|
|
#pragma alloc_text( PAGE, SrFastIoMdlWriteCompleteCompressed )
|
|
#pragma alloc_text( PAGE, SrFastIoQueryOpen )
|
|
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
|
|
//
|
|
// Private globals.
|
|
//
|
|
|
|
//
|
|
// Public globals.
|
|
//
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Define fast I/O procedure prototypes.
|
|
//
|
|
// Fast I/O read and write procedures.
|
|
//
|
|
|
|
BOOLEAN
|
|
SrFastIoCheckIfPossible (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN ULONG LockKey,
|
|
IN BOOLEAN CheckForReadOperation,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Handle calls to Control Device Object
|
|
//
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoCheckIfPossible))
|
|
{
|
|
return pFastIoDispatch->FastIoCheckIfPossible(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
Wait,
|
|
LockKey,
|
|
CheckForReadOperation,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoRead (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN ULONG LockKey,
|
|
OUT PVOID Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoRead))
|
|
{
|
|
return pFastIoDispatch->FastIoRead(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
Wait,
|
|
LockKey,
|
|
Buffer,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoWrite (
|
|
IN struct _FILE_OBJECT *pFileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN ULONG LockKey,
|
|
IN PVOID Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
NTSTATUS eventStatus;
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// See if logging is enabled
|
|
//
|
|
|
|
if (!SR_LOGGING_ENABLED(pExtension) ||
|
|
SR_IS_FS_CONTROL_DEVICE(pExtension))
|
|
{
|
|
goto CallNextDevice;
|
|
}
|
|
|
|
//
|
|
// does this file have a name? skip unnamed files
|
|
//
|
|
|
|
if (FILE_OBJECT_IS_NOT_POTENTIALLY_INTERESTING( pFileObject ))
|
|
{
|
|
goto CallNextDevice;
|
|
}
|
|
|
|
ASSERT(pFileObject->Vpb != NULL);
|
|
|
|
//
|
|
// is this file already closed? it can be the cache manager calling
|
|
// us to do work. we ignore the cache managers work as we monitored
|
|
// everything that happned prior to him seeing it.
|
|
//
|
|
|
|
if (FlagOn(pFileObject->Flags, FO_CLEANUP_COMPLETE))
|
|
{
|
|
goto CallNextDevice;
|
|
}
|
|
|
|
//
|
|
// Fire a notification , SrNotify will check for eligibility
|
|
//
|
|
|
|
eventStatus = SrHandleEvent( pExtension,
|
|
SrEventStreamChange,
|
|
pFileObject,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
CHECK_STATUS(eventStatus);
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
CallNextDevice:
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoWrite))
|
|
{
|
|
return pFastIoDispatch->FastIoWrite( pFileObject,
|
|
FileOffset,
|
|
Length,
|
|
Wait,
|
|
LockKey,
|
|
Buffer,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Fast I/O query basic and standard information procedures.
|
|
//
|
|
|
|
BOOLEAN
|
|
SrFastIoQueryBasicInfo (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_BASIC_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoQueryBasicInfo))
|
|
{
|
|
return pFastIoDispatch->FastIoQueryBasicInfo(
|
|
FileObject,
|
|
Wait,
|
|
Buffer,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoQueryStandardInfo (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_STANDARD_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoQueryStandardInfo))
|
|
{
|
|
return pFastIoDispatch->FastIoQueryStandardInfo(
|
|
FileObject,
|
|
Wait,
|
|
Buffer,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Fast I/O lock and unlock procedures.
|
|
//
|
|
|
|
BOOLEAN
|
|
SrFastIoLock (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PLARGE_INTEGER Length,
|
|
PEPROCESS ProcessId,
|
|
ULONG Key,
|
|
BOOLEAN FailImmediately,
|
|
BOOLEAN ExclusiveLock,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoLock))
|
|
{
|
|
return pFastIoDispatch->FastIoLock(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
ProcessId,
|
|
Key,
|
|
FailImmediately,
|
|
ExclusiveLock,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoUnlockSingle (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PLARGE_INTEGER Length,
|
|
PEPROCESS ProcessId,
|
|
ULONG Key,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoUnlockSingle))
|
|
{
|
|
return pFastIoDispatch->FastIoUnlockSingle(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
ProcessId,
|
|
Key,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoUnlockAll (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
PEPROCESS ProcessId,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoUnlockAll))
|
|
{
|
|
return pFastIoDispatch->FastIoUnlockAll(
|
|
FileObject,
|
|
ProcessId,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoUnlockAllByKey (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
PVOID ProcessId,
|
|
ULONG Key,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoUnlockAllByKey))
|
|
{
|
|
return pFastIoDispatch->FastIoUnlockAllByKey(
|
|
FileObject,
|
|
ProcessId,
|
|
Key,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Fast I/O device control procedure.
|
|
//
|
|
|
|
BOOLEAN
|
|
SrFastIoDeviceControl (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN BOOLEAN Wait,
|
|
IN PVOID InputBuffer OPTIONAL,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer OPTIONAL,
|
|
IN ULONG OutputBufferLength,
|
|
IN ULONG IoControlCode,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoDeviceControl))
|
|
{
|
|
return pFastIoDispatch->FastIoDeviceControl(
|
|
FileObject,
|
|
Wait,
|
|
InputBuffer,
|
|
InputBufferLength,
|
|
OutputBuffer,
|
|
OutputBufferLength,
|
|
IoControlCode,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Define callbacks for NtCreateSection to copy the file if a write section
|
|
// is being created on this file.
|
|
//
|
|
|
|
NTSTATUS
|
|
SrPreAcquireForSectionSynchronization(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext
|
|
)
|
|
{
|
|
NTSTATUS eventStatus;
|
|
PFILE_OBJECT pFileObject;
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
|
|
UNREFERENCED_PARAMETER( CompletionContext );
|
|
ASSERT(Data->Operation == FS_FILTER_ACQUIRE_FOR_SECTION_SYNCHRONIZATION);
|
|
ASSERT(CompletionContext == NULL);
|
|
ASSERT(IS_SR_DEVICE_OBJECT(Data->DeviceObject));
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// get the file object and device object
|
|
//
|
|
|
|
pExtension = Data->DeviceObject->DeviceExtension;
|
|
ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
|
|
|
|
//
|
|
// See if logging is enabled
|
|
//
|
|
|
|
if (!SR_LOGGING_ENABLED(pExtension) ||
|
|
SR_IS_FS_CONTROL_DEVICE(pExtension))
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
pFileObject = Data->FileObject;
|
|
ASSERT(IS_VALID_FILE_OBJECT(pFileObject));
|
|
|
|
//
|
|
// If they don't have write access to the section or the file don't worry
|
|
// about it.
|
|
//
|
|
// Is this file already closed? it can be the cache manager calling
|
|
// us to do work. we ignore the cache managers work as we monitored
|
|
// everything that happned prior to him seeing it.
|
|
//
|
|
|
|
if (!FlagOn(Data->Parameters.AcquireForSectionSynchronization.PageProtection,
|
|
(PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)) ||
|
|
!pFileObject->WriteAccess ||
|
|
FlagOn(pFileObject->Flags, FO_CLEANUP_COMPLETE))
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// does this file have a name? skip unnamed files
|
|
//
|
|
|
|
if (FILE_OBJECT_IS_NOT_POTENTIALLY_INTERESTING( pFileObject ))
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
ASSERT(pFileObject->Vpb != NULL);
|
|
|
|
//
|
|
// yep, fire a notification as if a write just happened.
|
|
// otherwise he can write to the section and we don't see the write
|
|
//
|
|
|
|
eventStatus = SrHandleEvent( pExtension,
|
|
SrEventStreamChange,
|
|
pFileObject,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
CHECK_STATUS(eventStatus);
|
|
|
|
//
|
|
// we never want to fail the acquire, we are just a silent monitor.
|
|
//
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // SrPreAcquireForCreateSection
|
|
|
|
//
|
|
// Define callback for drivers that have device objects attached to lower-
|
|
// level drivers' device objects. This callback is made when the lower-level
|
|
// driver is deleting its device object.
|
|
//
|
|
|
|
VOID
|
|
SrFastIoDetachDevice (
|
|
IN struct _DEVICE_OBJECT *AttachedDevice,
|
|
IN struct _DEVICE_OBJECT *DeviceDeleted
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
|
|
UNREFERENCED_PARAMETER( DeviceDeleted );
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT(IS_SR_DEVICE_OBJECT(AttachedDevice));
|
|
pExtension = AttachedDevice->DeviceExtension;
|
|
|
|
SrTrace(NOTIFY, ("SR!SrFastIoDetachDevice: detaching from %p(%wZ)\n",
|
|
DeviceDeleted,
|
|
pExtension->pNtVolumeName ));
|
|
|
|
//
|
|
// Detach ourselves from the device.
|
|
//
|
|
|
|
ASSERT(pExtension->pTargetDevice == DeviceDeleted);
|
|
|
|
SrDetachDevice(AttachedDevice, TRUE);
|
|
SrDeleteAttachmentDevice(AttachedDevice);
|
|
|
|
NULLPTR(AttachedDevice);
|
|
} // SrFastIoDetachDevice
|
|
|
|
|
|
//
|
|
// This structure is used by the server to quickly get the information needed
|
|
// to service a server open call. It is takes what would be two fast io calls
|
|
// one for basic information and the other for standard information and makes
|
|
// it into one call.
|
|
//
|
|
|
|
BOOLEAN
|
|
SrFastIoQueryNetworkOpenInfo (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT struct _FILE_NETWORK_OPEN_INFORMATION *Buffer,
|
|
OUT struct _IO_STATUS_BLOCK *IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoQueryNetworkOpenInfo))
|
|
{
|
|
return pFastIoDispatch->FastIoQueryNetworkOpenInfo(
|
|
FileObject,
|
|
Wait,
|
|
Buffer,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Define Mdl-based routines for the server to call
|
|
//
|
|
|
|
BOOLEAN
|
|
SrFastIoMdlRead (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, MdlRead))
|
|
{
|
|
return pFastIoDispatch->MdlRead(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
LockKey,
|
|
MdlChain,
|
|
IoStatus,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoMdlReadComplete (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PMDL MdlChain,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, MdlReadComplete))
|
|
{
|
|
return pFastIoDispatch->MdlReadComplete(
|
|
FileObject,
|
|
MdlChain,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoPrepareMdlWrite (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, PrepareMdlWrite))
|
|
{
|
|
return pFastIoDispatch->PrepareMdlWrite(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
LockKey,
|
|
MdlChain,
|
|
IoStatus,
|
|
pExtension->pTargetDevice);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
SrFastIoMdlWriteComplete (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PMDL MdlChain,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, MdlWriteComplete))
|
|
{
|
|
return pFastIoDispatch->MdlWriteComplete(
|
|
FileObject,
|
|
FileOffset,
|
|
MdlChain,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoReadCompressed (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PVOID Buffer,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
|
|
IN ULONG CompressedDataInfoLength,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoReadCompressed))
|
|
{
|
|
return pFastIoDispatch->FastIoReadCompressed(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
LockKey,
|
|
Buffer,
|
|
MdlChain,
|
|
IoStatus,
|
|
CompressedDataInfo,
|
|
CompressedDataInfoLength,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoWriteCompressed (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
IN PVOID Buffer,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
|
|
IN ULONG CompressedDataInfoLength,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoWriteCompressed))
|
|
{
|
|
return pFastIoDispatch->FastIoWriteCompressed(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
LockKey,
|
|
Buffer,
|
|
MdlChain,
|
|
IoStatus,
|
|
CompressedDataInfo,
|
|
CompressedDataInfoLength,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoMdlReadCompleteCompressed (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PMDL MdlChain,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, MdlReadCompleteCompressed))
|
|
{
|
|
return pFastIoDispatch->MdlReadCompleteCompressed(
|
|
FileObject,
|
|
MdlChain,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoMdlWriteCompleteCompressed (
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PMDL MdlChain,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, MdlWriteCompleteCompressed))
|
|
{
|
|
return pFastIoDispatch->MdlWriteCompleteCompressed (
|
|
FileObject,
|
|
FileOffset,
|
|
MdlChain,
|
|
pExtension->pTargetDevice );
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SrFastIoQueryOpen (
|
|
IN struct _IRP *pIrp,
|
|
OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
|
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|
)
|
|
{
|
|
PSR_DEVICE_EXTENSION pExtension;
|
|
PFAST_IO_DISPATCH pFastIoDispatch;
|
|
PIO_STACK_LOCATION pIrpSp;
|
|
BOOLEAN Result;
|
|
|
|
//
|
|
// < dispatch!
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
if (DeviceObject->DeviceExtension)
|
|
{
|
|
ASSERT(IS_SR_DEVICE_OBJECT(DeviceObject));
|
|
pExtension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// call the next device
|
|
//
|
|
|
|
pFastIoDispatch = pExtension->pTargetDevice->
|
|
DriverObject->FastIoDispatch;
|
|
|
|
if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoQueryOpen))
|
|
{
|
|
//
|
|
// normally IoCallDriver would update this field, we should manually
|
|
//
|
|
|
|
pIrpSp = IoGetCurrentIrpStackLocation( pIrp );
|
|
pIrpSp->DeviceObject = pExtension->pTargetDevice;
|
|
|
|
Result = pFastIoDispatch->FastIoQueryOpen ( pIrp,
|
|
NetworkInformation,
|
|
pExtension->pTargetDevice );
|
|
|
|
if (!Result)
|
|
{
|
|
//
|
|
// This is ok, fastioquery does not complete the irp ever, and
|
|
// false means we are about to come down with an MJ_CREATE so
|
|
// we need the proper device object put back in the stack.
|
|
//
|
|
|
|
pIrpSp->DeviceObject = DeviceObject;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|