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.
1797 lines
51 KiB
1797 lines
51 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1992, Microsoft Corporation
|
|
//
|
|
// File: fastio.c
|
|
//
|
|
// Contents: Routines to implement Fast IO
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 8/11/93 Milans created
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "dfsprocs.h"
|
|
#include "fsctrl.h"
|
|
#include "fastio.h"
|
|
#include "fcbsup.h"
|
|
|
|
#define Dbg (DEBUG_TRACE_FASTIO)
|
|
|
|
BOOLEAN
|
|
DfsFastIoCheckIfPossible (
|
|
FILE_OBJECT *pFileObject,
|
|
LARGE_INTEGER *pOffset,
|
|
ULONG Length,
|
|
BOOLEAN fWait,
|
|
ULONG LockKey,
|
|
BOOLEAN fCheckForRead,
|
|
IO_STATUS_BLOCK *pIoStatusBlock,
|
|
DEVICE_OBJECT *DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoRead(
|
|
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,
|
|
DEVICE_OBJECT *DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoWrite(
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN ULONG LockKey,
|
|
IN PVOID Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
DEVICE_OBJECT *DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoQueryBasicInfo(
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_BASIC_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
DEVICE_OBJECT *DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoQueryStandardInfo(
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_STANDARD_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
DEVICE_OBJECT *DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoLock(
|
|
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,
|
|
DEVICE_OBJECT *DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoUnlockSingle(
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PLARGE_INTEGER Length,
|
|
PEPROCESS ProcessId,
|
|
ULONG Key,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
DEVICE_OBJECT *DeviceObject
|
|
);
|
|
|
|
|
|
BOOLEAN
|
|
DfsFastIoUnlockAll(
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
PEPROCESS ProcessId,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
DEVICE_OBJECT *DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoUnlockAllByKey(
|
|
IN struct _FILE_OBJECT *FileObject,
|
|
PVOID ProcessId,
|
|
ULONG Key,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
DEVICE_OBJECT *DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoDeviceControl(
|
|
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,
|
|
DEVICE_OBJECT *DeviceObject);
|
|
|
|
VOID
|
|
DfsFastIoDetachDevice(
|
|
IN PDEVICE_OBJECT SourceDevice,
|
|
IN PDEVICE_OBJECT TargetDevice);
|
|
|
|
BOOLEAN
|
|
DfsFastIoQueryNetworkOpenInfo(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject);
|
|
|
|
BOOLEAN
|
|
DfsFastIoMdlRead(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject);
|
|
|
|
BOOLEAN
|
|
DfsFastIoMdlReadComplete(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoPrepareMdlWrite(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoMdlWriteComplete(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoReadCompressed(
|
|
IN PFILE_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 PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
DfsFastIoWriteCompressed(
|
|
IN PFILE_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 PDEVICE_OBJECT DeviceObject);
|
|
|
|
BOOLEAN
|
|
DfsFastIoMdlReadCompleteCompressed(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject);
|
|
|
|
BOOLEAN
|
|
DfsFastIoMdlWriteCompleteCompressed(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject);
|
|
|
|
PFAST_IO_DISPATCH
|
|
DfsFastIoLookup(
|
|
IN FILE_OBJECT *pFileObject,
|
|
IN DEVICE_OBJECT *DeviceObject,
|
|
IN PDEVICE_OBJECT *targetVdo);
|
|
|
|
NTSTATUS
|
|
DfsPreAcquireForSectionSynchronization(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext);
|
|
|
|
NTSTATUS
|
|
DfsPreReleaseForSectionSynchronization(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext);
|
|
|
|
NTSTATUS
|
|
DfsPreAcquireForModWrite(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext);
|
|
|
|
NTSTATUS
|
|
DfsPreReleaseForModWrite(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext);
|
|
|
|
NTSTATUS
|
|
DfsPreAcquireForCcFlush(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext);
|
|
|
|
NTSTATUS
|
|
DfsPreReleaseForCcFlush(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text( PAGE, DfsFastIoCheckIfPossible )
|
|
#pragma alloc_text( PAGE, DfsFastIoRead )
|
|
#pragma alloc_text( PAGE, DfsFastIoWrite )
|
|
#pragma alloc_text( PAGE, DfsFastIoQueryBasicInfo )
|
|
#pragma alloc_text( PAGE, DfsFastIoQueryStandardInfo )
|
|
#pragma alloc_text( PAGE, DfsFastIoLock )
|
|
#pragma alloc_text( PAGE, DfsFastIoUnlockSingle )
|
|
#pragma alloc_text( PAGE, DfsFastIoUnlockAll )
|
|
#pragma alloc_text( PAGE, DfsFastIoUnlockAllByKey )
|
|
#pragma alloc_text( PAGE, DfsFastIoDeviceControl )
|
|
#pragma alloc_text( PAGE, DfsFastIoDetachDevice )
|
|
#pragma alloc_text( PAGE, DfsFastIoQueryNetworkOpenInfo )
|
|
#pragma alloc_text( PAGE, DfsFastIoMdlRead )
|
|
#pragma alloc_text( PAGE, DfsFastIoMdlReadComplete )
|
|
#pragma alloc_text( PAGE, DfsFastIoPrepareMdlWrite )
|
|
#pragma alloc_text( PAGE, DfsFastIoMdlWriteComplete )
|
|
#pragma alloc_text( PAGE, DfsFastIoReadCompressed )
|
|
#pragma alloc_text( PAGE, DfsFastIoWriteCompressed )
|
|
#pragma alloc_text( PAGE, DfsFastIoMdlReadCompleteCompressed )
|
|
#pragma alloc_text( PAGE, DfsFastIoMdlWriteCompleteCompressed )
|
|
#pragma alloc_text( PAGE, DfsFastIoLookup )
|
|
#pragma alloc_text( PAGE, DfsPreAcquireForSectionSynchronization )
|
|
#pragma alloc_text( PAGE, DfsPreReleaseForSectionSynchronization )
|
|
#pragma alloc_text( PAGE, DfsPreAcquireForModWrite )
|
|
#pragma alloc_text( PAGE, DfsPreReleaseForModWrite )
|
|
#pragma alloc_text( PAGE, DfsPreAcquireForCcFlush )
|
|
#pragma alloc_text( PAGE, DfsPreReleaseForCcFlush )
|
|
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
//
|
|
// Note: We don't register the 6 Acquire/Release FastIo Dispatches here
|
|
// because we filter this operations through the FsFilterCallback interface
|
|
// which allows DFS to interop better with file system filters.
|
|
//
|
|
|
|
FAST_IO_DISPATCH FastIoDispatch =
|
|
{
|
|
sizeof(FAST_IO_DISPATCH),
|
|
DfsFastIoCheckIfPossible, // CheckForFastIo
|
|
DfsFastIoRead, // FastIoRead
|
|
DfsFastIoWrite, // FastIoWrite
|
|
DfsFastIoQueryBasicInfo, // FastIoQueryBasicInfo
|
|
DfsFastIoQueryStandardInfo, // FastIoQueryStandardInfo
|
|
DfsFastIoLock, // FastIoLock
|
|
DfsFastIoUnlockSingle, // FastIoUnlockSingle
|
|
DfsFastIoUnlockAll, // FastIoUnlockAll
|
|
DfsFastIoUnlockAllByKey, // FastIoUnlockAllByKey
|
|
NULL, // FastIoDeviceControl
|
|
NULL, // AcquireFileForNtCreateSection
|
|
NULL, // ReleaseFileForNtCreateSection
|
|
DfsFastIoDetachDevice, // FastIoDetachDevice
|
|
DfsFastIoQueryNetworkOpenInfo, // FastIoQueryNetworkOpenInfo
|
|
NULL, // AcquireForModWrite
|
|
DfsFastIoMdlRead, // MdlRead
|
|
DfsFastIoMdlReadComplete, // MdlReadComplete
|
|
DfsFastIoPrepareMdlWrite, // PrepareMdlWrite
|
|
DfsFastIoMdlWriteComplete, // MdlWriteComplete
|
|
DfsFastIoReadCompressed, // FastIoReadCompressed
|
|
DfsFastIoWriteCompressed, // FastIoWriteCompressed
|
|
DfsFastIoMdlReadCompleteCompressed, // MdlReadCompleteCompressed
|
|
DfsFastIoMdlWriteCompleteCompressed,// MdlWriteCompleteCompressed
|
|
NULL, // FastIoQueryOpen
|
|
NULL, // ReleaseForModWrite
|
|
NULL, // AcquireForCcFlush
|
|
NULL, // ReleaseForCcFlush
|
|
};
|
|
|
|
//
|
|
// NOTE: Dfs has been changed to use the FsFilter interfaces to intercept the
|
|
// Acquire/Release calls traditionally supported via the FastIo path
|
|
// to provide better file system filter driver support.
|
|
//
|
|
// By hooking these operations via the FsFilter interfaces, Dfs is able
|
|
// to propogate the additional information provided through these
|
|
// interfaces to file system filters as it redirects the operation to
|
|
// a different driver stack (such as the device stack for
|
|
// LanmanRedirector or WebDavRedirector).
|
|
//
|
|
// This also provides a more consistent interface for these
|
|
// Acquire/Release operations for file system filter drivers. With Dfs
|
|
// supporting this interface, filters will only get called through the
|
|
// FsFilter interfaces for these operations on both local and remote
|
|
// file systems.
|
|
//
|
|
|
|
FS_FILTER_CALLBACKS FsFilterCallbacks =
|
|
{
|
|
sizeof( FS_FILTER_CALLBACKS ),
|
|
0,
|
|
DfsPreAcquireForSectionSynchronization, // PreAcquireForSectionSynchronization
|
|
NULL, // PostAcquireForSectionSynchronization
|
|
DfsPreReleaseForSectionSynchronization, // PreReleaseForSectionSynchronization
|
|
NULL, // PostReleaseForSectionSynchronization
|
|
DfsPreAcquireForCcFlush, // PreAcquireForCcFlush
|
|
NULL, // PostAcquireForCcFlush
|
|
DfsPreReleaseForCcFlush, // PreReleaseForCcFlush
|
|
NULL, // PostReleaseForCcFlush
|
|
DfsPreAcquireForModWrite, // PreAcquireForModWrite
|
|
NULL, // PostAcquireForModWrite
|
|
DfsPreReleaseForModWrite, // PreReleaseForModWrite
|
|
NULL // PostReleaseForModWrite
|
|
};
|
|
|
|
|
|
//
|
|
// Macro to see if a PFAST_IO_DISPATCH has a particular field
|
|
//
|
|
|
|
#define IS_VALID_INDEX(pfio, e) \
|
|
((pfio != NULL) && \
|
|
(pfio->SizeOfFastIoDispatch >= \
|
|
(offsetof(FAST_IO_DISPATCH, e) + sizeof(PVOID))) && \
|
|
(pfio->e != NULL) \
|
|
)
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoLookup
|
|
//
|
|
// Synopsis: Given a file object, this routine will locate the fast IO
|
|
// dispatch table for the underlying provider
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
PFAST_IO_DISPATCH
|
|
DfsFastIoLookup(
|
|
IN FILE_OBJECT *pFileObject,
|
|
IN DEVICE_OBJECT *DeviceObject,
|
|
OUT PDEVICE_OBJECT *targetVdo)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
|
|
*targetVdo = NULL;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoLookup: Entered\n", 0);
|
|
|
|
if (DeviceObject->DeviceType == FILE_DEVICE_DFS) {
|
|
|
|
//
|
|
// In this case we now need to do an DFS_FCB Lookup to figure out where to
|
|
// go from here.
|
|
//
|
|
|
|
TYPE_OF_OPEN TypeOfOpen;
|
|
PDFS_VCB Vcb;
|
|
PDFS_FCB Fcb;
|
|
|
|
TypeOfOpen = DfsDecodeFileObject( pFileObject, &Vcb, &Fcb);
|
|
|
|
DfsDbgTrace(0, Dbg, "Fcb = %08lx\n", Fcb);
|
|
|
|
if (TypeOfOpen == RedirectedFileOpen) {
|
|
|
|
//
|
|
// In this case the target device is in the Fcb itself.
|
|
//
|
|
|
|
*targetVdo = Fcb->TargetDevice;
|
|
|
|
pFastIoTable = (*targetVdo)->DriverObject->FastIoDispatch;
|
|
|
|
DfsDbgTrace(0,Dbg, "DfsFastIoLookup: DvObj: %08lx",DeviceObject);
|
|
DfsDbgTrace(0, Dbg, "TargetVdo %08lx\n", *targetVdo);
|
|
DfsDbgTrace(-1,Dbg, "DfsFastIoLookup: Exit-> %08lx\n",pFastIoTable );
|
|
|
|
return(pFastIoTable);
|
|
|
|
} else {
|
|
|
|
//
|
|
// This can happen for opens against mup device, so its legal
|
|
// to return NULL here. Dont assert (bug 422334)
|
|
//
|
|
|
|
DfsDbgTrace( 0, Dbg, "DfsFastIoLookup: TypeOfOpen = %s\n",
|
|
( (TypeOfOpen == UnopenedFileObject) ? "UnopenedFileObject":
|
|
(TypeOfOpen == LogicalRootDeviceOpen) ? "LogicalRootDeviceOpen":
|
|
"???") );
|
|
|
|
DfsDbgTrace(-1,Dbg, "DfsFastIoLookup: Exit -> %08lx\n", NULL );
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
} else if (DeviceObject->DeviceType == FILE_DEVICE_DFS_FILE_SYSTEM) {
|
|
|
|
DfsDbgTrace(0, Dbg, "DfsFastIoLookup: Dfs File System\n", 0);
|
|
|
|
return( NULL );
|
|
|
|
} else {
|
|
|
|
//
|
|
// This is an unknown device object type and we dont know what to do
|
|
//
|
|
|
|
DfsDbgTrace(-1,Dbg, "DfsFastIoLookup: Exit -> %08lx\n", NULL );
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoCheckIfPossible
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
DfsFastIoCheckIfPossible (
|
|
FILE_OBJECT *pFileObject,
|
|
LARGE_INTEGER *pOffset,
|
|
ULONG Length,
|
|
BOOLEAN fWait,
|
|
ULONG LockKey,
|
|
BOOLEAN fCheckForRead,
|
|
IO_STATUS_BLOCK *pIoStatusBlock,
|
|
PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoCheckIfPossible Enter \n", 0);
|
|
pFastIoTable = DfsFastIoLookup(pFileObject, DeviceObject, &targetVdo);
|
|
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoCheckIfPossible) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoCheckIfPossible(
|
|
pFileObject,
|
|
pOffset,
|
|
Length,
|
|
fWait,
|
|
LockKey,
|
|
fCheckForRead,
|
|
pIoStatusBlock,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoCheckIfPossible Exit \n", 0);
|
|
|
|
return(fPossible);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoRead
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
DfsFastIoRead(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN ULONG LockKey,
|
|
OUT PVOID Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
PDEVICE_OBJECT DeviceObject
|
|
)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoRead Enter \n", 0);
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoRead) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoRead(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
Wait,
|
|
LockKey,
|
|
Buffer,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoRead Exit \n", 0);
|
|
|
|
return(fPossible);
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoWrite
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
DfsFastIoWrite(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN ULONG LockKey,
|
|
IN PVOID Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
PDEVICE_OBJECT DeviceObject
|
|
)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoWrite Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoWrite) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoWrite(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
Wait,
|
|
LockKey,
|
|
Buffer,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoWrite Exit \n", 0);
|
|
|
|
return(fPossible);
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoQueryBasicInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
DfsFastIoQueryBasicInfo(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_BASIC_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoQueryBasicInfo Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoQueryBasicInfo) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoQueryBasicInfo(
|
|
FileObject,
|
|
Wait,
|
|
Buffer,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoQueryBasicInfo Exit \n", 0);
|
|
|
|
return(fPossible);
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoQueryStandardInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
DfsFastIoQueryStandardInfo(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_STANDARD_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoQueryStandardInfo Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoQueryStandardInfo) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoQueryStandardInfo(
|
|
FileObject,
|
|
Wait,
|
|
Buffer,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoQueryStandardInfo Exit \n", 0);
|
|
|
|
return(fPossible);
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoLock
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
DfsFastIoLock(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PLARGE_INTEGER Length,
|
|
PEPROCESS ProcessId,
|
|
ULONG Key,
|
|
BOOLEAN FailImmediately,
|
|
BOOLEAN ExclusiveLock,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
PDEVICE_OBJECT DeviceObject
|
|
)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoLock Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoLock) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoLock(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
ProcessId,
|
|
Key,
|
|
FailImmediately,
|
|
ExclusiveLock,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoLock Exit \n", 0);
|
|
|
|
return(fPossible);
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoUnlockSingle
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
DfsFastIoUnlockSingle(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PLARGE_INTEGER Length,
|
|
PEPROCESS ProcessId,
|
|
ULONG Key,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoUnlockSingle Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoUnlockSingle) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoUnlockSingle(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
ProcessId,
|
|
Key,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoUnlockSingle Exit \n", 0);
|
|
|
|
return(fPossible);
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoUnlockAll
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
DfsFastIoUnlockAll(
|
|
IN PFILE_OBJECT FileObject,
|
|
PEPROCESS ProcessId,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
PDEVICE_OBJECT DeviceObject
|
|
)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoUnlockAll Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoUnlockAll) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoUnlockAll(
|
|
FileObject,
|
|
ProcessId,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoUnlockAll Exit \n", 0);
|
|
|
|
return(fPossible);
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: FastIoUnlockAllByKey
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
DfsFastIoUnlockAllByKey(
|
|
IN PFILE_OBJECT FileObject,
|
|
PVOID ProcessId,
|
|
ULONG Key,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
PDEVICE_OBJECT DeviceObject
|
|
)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoUnlockAllByKey Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoUnlockAllByKey) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoUnlockAllByKey(
|
|
FileObject,
|
|
ProcessId,
|
|
Key,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoUnlockAllByKey Exit \n", 0);
|
|
|
|
return(fPossible);
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoDeviceControl
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
DfsFastIoDeviceControl(
|
|
IN PFILE_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,
|
|
PDEVICE_OBJECT DeviceObject
|
|
)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
TYPE_OF_OPEN TypeOfOpen;
|
|
PDFS_VCB Vcb;
|
|
PDFS_FCB Fcb;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoDeviceControl Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoDeviceControl) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoDeviceControl(
|
|
FileObject,
|
|
Wait,
|
|
InputBuffer,
|
|
InputBufferLength,
|
|
OutputBuffer,
|
|
OutputBufferLength,
|
|
IoControlCode,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoDeviceControl Exit \n", 0);
|
|
|
|
return(fPossible);
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsFastIoDetachDevice, public
|
|
//
|
|
// Synopsis: This routine is a different from the rest of the fast io
|
|
// routines. It is called when a device object is being deleted,
|
|
// and that device object has an attached device. The semantics
|
|
// of this routine are "You attached to a device object that now
|
|
// needs to be deleted; please detach from the said device
|
|
// object."
|
|
//
|
|
// Arguments: [SourceDevice] -- Our device, the one that we created to
|
|
// attach ourselves to the target device.
|
|
// [TargetDevice] -- Their device, the one that we are attached
|
|
// to.
|
|
//
|
|
// Returns: Nothing - we must succeed.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
DfsFastIoDetachDevice(
|
|
IN PDEVICE_OBJECT SourceDevice,
|
|
IN PDEVICE_OBJECT TargetDevice)
|
|
{
|
|
NOTHING;
|
|
}
|
|
|
|
BOOLEAN
|
|
DfsFastIoQueryNetworkOpenInfo(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoQueryNetworkOpenInfo Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoQueryNetworkOpenInfo) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoQueryNetworkOpenInfo(
|
|
FileObject,
|
|
Wait,
|
|
Buffer,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
IoStatus->Status = STATUS_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoQueryNetworkOpenInfo Exit \n", 0);
|
|
|
|
return( fPossible );
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
DfsFastIoMdlRead(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoMdlRead Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, MdlRead) ) {
|
|
|
|
fPossible = pFastIoTable->MdlRead(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
LockKey,
|
|
MdlChain,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FsRtlMdlReadDev(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
LockKey,
|
|
MdlChain,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoMdlRead Exit \n", 0);
|
|
|
|
return( fPossible );
|
|
}
|
|
|
|
BOOLEAN
|
|
DfsFastIoMdlReadComplete(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fResult;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoMdlReadComplete Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, MdlReadComplete) ) {
|
|
|
|
fResult = pFastIoTable->MdlReadComplete(
|
|
FileObject,
|
|
MdlChain,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fResult = FsRtlMdlReadCompleteDev(
|
|
FileObject,
|
|
MdlChain,
|
|
targetVdo);
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoMdlReadComplete Exit \n", 0);
|
|
|
|
return( fResult );
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
DfsFastIoPrepareMdlWrite(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG LockKey,
|
|
OUT PMDL *MdlChain,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoPrepareMdlWrite Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, PrepareMdlWrite) ) {
|
|
|
|
fPossible = pFastIoTable->PrepareMdlWrite(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
LockKey,
|
|
MdlChain,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FsRtlPrepareMdlWriteDev(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
LockKey,
|
|
MdlChain,
|
|
IoStatus,
|
|
targetVdo);
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoPrepareMdlWrite Exit \n", 0);
|
|
|
|
return( fPossible );
|
|
}
|
|
|
|
BOOLEAN
|
|
DfsFastIoMdlWriteComplete(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fResult;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoMdlWriteComplete Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, MdlWriteComplete) ) {
|
|
|
|
fResult = pFastIoTable->MdlWriteComplete(
|
|
FileObject,
|
|
FileOffset,
|
|
MdlChain,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fResult = FsRtlMdlWriteCompleteDev(
|
|
FileObject,
|
|
FileOffset,
|
|
MdlChain,
|
|
targetVdo);
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoMdlWriteComplete Exit \n", 0);
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
BOOLEAN
|
|
DfsFastIoReadCompressed(
|
|
IN PFILE_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 PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoReadCompressed Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoReadCompressed) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoReadCompressed(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
LockKey,
|
|
Buffer,
|
|
MdlChain,
|
|
IoStatus,
|
|
CompressedDataInfo,
|
|
CompressedDataInfoLength,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
IoStatus->Status = STATUS_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoReadCompressed Exit \n", 0);
|
|
|
|
return( fPossible );
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
DfsFastIoWriteCompressed(
|
|
IN PFILE_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 PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fPossible;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoWriteCompressed Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, FastIoWriteCompressed) ) {
|
|
|
|
fPossible = pFastIoTable->FastIoWriteCompressed(
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
LockKey,
|
|
Buffer,
|
|
MdlChain,
|
|
IoStatus,
|
|
CompressedDataInfo,
|
|
CompressedDataInfoLength,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fPossible = FALSE;
|
|
|
|
IoStatus->Status = STATUS_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoWriteCompressed Exit \n", 0);
|
|
|
|
return( fPossible );
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
DfsFastIoMdlReadCompleteCompressed(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fResult;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoMdlReadCompleteCompressed Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, MdlReadCompleteCompressed) ) {
|
|
|
|
fResult = pFastIoTable->MdlReadCompleteCompressed(
|
|
FileObject,
|
|
MdlChain,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fResult = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoMdlReadCompleteCompressed Exit \n", 0);
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
BOOLEAN
|
|
DfsFastIoMdlWriteCompleteCompressed(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PFAST_IO_DISPATCH pFastIoTable;
|
|
PDEVICE_OBJECT targetVdo;
|
|
BOOLEAN fResult;
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsFastIoMdlWriteCompleteCompressed Enter \n", 0);
|
|
|
|
pFastIoTable = DfsFastIoLookup(FileObject, DeviceObject, &targetVdo);
|
|
|
|
if ( IS_VALID_INDEX(pFastIoTable, MdlWriteCompleteCompressed) ) {
|
|
|
|
fResult = pFastIoTable->MdlWriteCompleteCompressed(
|
|
FileObject,
|
|
FileOffset,
|
|
MdlChain,
|
|
targetVdo);
|
|
|
|
} else {
|
|
|
|
fResult = FALSE;
|
|
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsFastIoMdlWriteCompleteCompressed Exit \n", 0);
|
|
|
|
return( fResult );
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsPreAcquireForSectionSynchronization
|
|
//
|
|
// Synopsis: This is the equivalent to FastIoAcquireFileForNtCreateSection.
|
|
// Dfs receives this callback through the FsFilter interfaces
|
|
// of the FsRtl package in the kernel.
|
|
//
|
|
// This is the time to do the work necessary to synchronize
|
|
// for memory-mapped section creation. If this operation
|
|
// should be redirected to an underlying FS, the parameters will
|
|
// be changed accordingly so that the operation is redirect when
|
|
// this callback returns.
|
|
//
|
|
// Arguments: [Data] -- The structure that contains the relevent parameters
|
|
// to this operation, like the FileObject and DeviceObject.
|
|
// [CompletionContext] - Provides a pointer for a context to be
|
|
// past from the pre to post operation. Since Dfs
|
|
// does not need a post operation, this parameter is not
|
|
// used.
|
|
//
|
|
// Returns: STATUS_SUCCESS to continue passing this operation through or
|
|
// to take the default action if there are no more devices in the
|
|
// chain.
|
|
//
|
|
// STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY to denote that the
|
|
// operation has been satisfied by this callback so no further
|
|
// devices in the chain should be called.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
DfsPreAcquireForSectionSynchronization(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext)
|
|
{
|
|
PDEVICE_OBJECT targetVdo;
|
|
PFSRTL_COMMON_FCB_HEADER header;
|
|
PDFS_FCB pFcb;
|
|
NTSTATUS status;
|
|
|
|
UNREFERENCED_PARAMETER( CompletionContext );
|
|
|
|
DfsFastIoLookup( Data->FileObject, Data->DeviceObject, &targetVdo );
|
|
|
|
pFcb = DfsLookupFcb(Data->FileObject);
|
|
|
|
//
|
|
// If we've got a valid pFcb and pFcb->FileObject, we need to switch
|
|
// this operation to the other device stack and file object.
|
|
//
|
|
|
|
if (targetVdo != NULL &&
|
|
pFcb != NULL &&
|
|
pFcb->FileObject != NULL) {
|
|
|
|
IoSetTopLevelIrp( (PIRP) FSRTL_FSP_TOP_LEVEL_IRP );
|
|
|
|
Data->FileObject = pFcb->FileObject;
|
|
Data->DeviceObject = targetVdo;
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
} else if ((header = Data->FileObject->FsContext) && header->Resource) {
|
|
|
|
IoSetTopLevelIrp( (PIRP) FSRTL_FSP_TOP_LEVEL_IRP );
|
|
|
|
ExAcquireResourceExclusiveLite( header->Resource, TRUE );
|
|
|
|
status = STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY;
|
|
|
|
} else {
|
|
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsPreReleaseForSectionSynchronization
|
|
//
|
|
// Synopsis: This is the equivalent to FastIoReleaseFileForNtCreateSection.
|
|
// Dfs receives this callback through the FsFilter interfaces
|
|
// of the FsRtl package in the kernel.
|
|
//
|
|
// This is the time to do the work necessary to end the
|
|
// synchronization operations taken to create a memory-mapped
|
|
// section. If this operation should be redirected to an
|
|
// underlying FS, the parameters will be changed accordingly so
|
|
// that the operation is redirect when this callback returns.
|
|
//
|
|
// Arguments: [Data] -- The structure that contains the relevent parameters
|
|
// to this operation, like the FileObject and DeviceObject.
|
|
// [CompletionContext] - Provides a pointer for a context to be
|
|
// past from the pre to post operation. Since Dfs
|
|
// does not need a post operation, this parameter is not
|
|
// used.
|
|
//
|
|
// Returns: STATUS_SUCCESS to continue passing this operation through or
|
|
// to take the default action if there are no more devices in the
|
|
// chain.
|
|
//
|
|
// STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY to denote that the
|
|
// operation has been satisfied by this callback so no further
|
|
// devices in the chain should be called.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
DfsPreReleaseForSectionSynchronization(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext)
|
|
{
|
|
PDEVICE_OBJECT targetVdo;
|
|
PFSRTL_COMMON_FCB_HEADER header;
|
|
PDFS_FCB pFcb;
|
|
NTSTATUS status;
|
|
|
|
UNREFERENCED_PARAMETER( CompletionContext );
|
|
|
|
DfsFastIoLookup( Data->FileObject, Data->DeviceObject, &targetVdo );
|
|
|
|
pFcb = DfsLookupFcb(Data->FileObject);
|
|
|
|
if (targetVdo != NULL &&
|
|
pFcb != NULL &&
|
|
pFcb->FileObject != NULL) {
|
|
|
|
IoSetTopLevelIrp( (PIRP) NULL );
|
|
Data->DeviceObject = targetVdo;
|
|
status = STATUS_SUCCESS;
|
|
|
|
} else if ((header = Data->FileObject->FsContext) && header->Resource) {
|
|
|
|
IoSetTopLevelIrp( (PIRP) NULL );
|
|
|
|
ExReleaseResourceLite( header->Resource );
|
|
|
|
status = STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY;
|
|
|
|
} else {
|
|
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsPreAcquireForModWrite
|
|
//
|
|
// Synopsis: This is the equivalent to FastIoAcquireForModWrite.
|
|
// Dfs receives this callback through the FsFilter interfaces
|
|
// of the FsRtl package in the kernel.
|
|
//
|
|
// This is the time to do the work necessary to synchronize
|
|
// for modified page writer operations. If this operation
|
|
// should be redirected to an underlying FS, the parameters will
|
|
// be changed accordingly so that the operation is redirect when
|
|
// this callback returns.
|
|
//
|
|
// Arguments: [Data] -- The structure that contains the relevent parameters
|
|
// to this operation, like the FileObject and DeviceObject.
|
|
// [CompletionContext] - Provides a pointer for a context to be
|
|
// past from the pre to post operation. Since Dfs
|
|
// does not need a post operation, this parameter is not
|
|
// used.
|
|
//
|
|
// Returns: STATUS_SUCCESS or STATUS_INVALID_DEVICE_REQUEST for default
|
|
// behavior.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
DfsPreAcquireForModWrite(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext)
|
|
{
|
|
PDEVICE_OBJECT targetVdo;
|
|
NTSTATUS status;
|
|
|
|
UNREFERENCED_PARAMETER( CompletionContext );
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsPreAcquireForModWrite Enter \n", 0);
|
|
|
|
DfsFastIoLookup(Data->FileObject, Data->DeviceObject, &targetVdo);
|
|
|
|
if (targetVdo != NULL) {
|
|
|
|
Data->DeviceObject = targetVdo;
|
|
status = STATUS_SUCCESS;
|
|
|
|
} else {
|
|
|
|
//
|
|
// The lazy write called us because we had the dispatch routine for
|
|
// AcquireFileForModWrite, but the underlying FS did not. So, we
|
|
// return this particular error so that the lazy write knows exactly
|
|
// what happened, and can take the default action.
|
|
//
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsPreAcquireForModWrite Exit \n", 0);
|
|
|
|
return( status );
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsPreReleaseForModWrite
|
|
//
|
|
// Synopsis: This is the equivalent to FastIoReleaseForModWrite.
|
|
// Dfs receives this callback through the FsFilter interfaces
|
|
// of the FsRtl package in the kernel.
|
|
//
|
|
// This is the time to do the work necessary to end the
|
|
// synchronization operations taken to prepare for the modified
|
|
// page writer to do its work. If this operation should be
|
|
// redirected to an underlying FS, the parameters will be changed
|
|
// accordingly so that the operation is redirect when this callback
|
|
// returns.
|
|
//
|
|
// Arguments: [Data] -- The structure that contains the relevent parameters
|
|
// to this operation, like the FileObject and DeviceObject.
|
|
// [CompletionContext] - Provides a pointer for a context to be
|
|
// past from the pre to post operation. Since Dfs
|
|
// does not need a post operation, this parameter is not
|
|
// used.
|
|
//
|
|
// Returns: STATUS_SUCCESS or STATUS_INVALID_DEVICE_REQUEST for default
|
|
// actions.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
DfsPreReleaseForModWrite(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext)
|
|
{
|
|
PDEVICE_OBJECT targetVdo;
|
|
NTSTATUS status;
|
|
|
|
UNREFERENCED_PARAMETER( CompletionContext );
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsPreReleaseForModWrite Enter \n", 0);
|
|
|
|
DfsFastIoLookup(Data->FileObject, Data->DeviceObject, &targetVdo);
|
|
|
|
if (targetVdo != NULL) {
|
|
|
|
Data->DeviceObject = targetVdo;
|
|
status = STATUS_SUCCESS;
|
|
|
|
} else {
|
|
|
|
|
|
//
|
|
// The lazy write called us because we had the dispatch routine for
|
|
// AcquireFileForModWrite, but the underlying FS did not. So, we
|
|
// return this particular error so that the lazy write knows exactly
|
|
// what happened, and can take the default action.
|
|
//
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsPreReleaseForModWrite Exit \n", 0);
|
|
|
|
return( status );
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsPreAcquireForCcFlush
|
|
//
|
|
// Synopsis: This is the equivalent to FastIoAcquireForCcFlush.
|
|
// Dfs receives this callback through the FsFilter interfaces
|
|
// of the FsRtl package in the kernel.
|
|
//
|
|
// This is the time to do the work necessary to synchronize
|
|
// for a CC flush of the given file. If this operation
|
|
// should be redirected to an underlying FS, the parameters will
|
|
// be changed accordingly so that the operation is redirect when
|
|
// this callback returns.
|
|
//
|
|
// Arguments: [Data] -- The structure that contains the relevent parameters
|
|
// to this operation, like the FileObject and DeviceObject.
|
|
// [CompletionContext] - Provides a pointer for a context to be
|
|
// past from the pre to post operation. Since Dfs
|
|
// does not need a post operation, this parameter is not
|
|
// used.
|
|
//
|
|
// Returns: STATUS_SUCCESS or STATUS_INVALID_DEVICE_REQUEST for default
|
|
// actions.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
DfsPreAcquireForCcFlush(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext)
|
|
{
|
|
PDEVICE_OBJECT targetVdo;
|
|
NTSTATUS status;
|
|
|
|
UNREFERENCED_PARAMETER( CompletionContext );
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsPreAcquireForCcFlush Enter \n", 0);
|
|
|
|
DfsFastIoLookup(Data->FileObject, Data->DeviceObject, &targetVdo);
|
|
|
|
if (targetVdo != NULL) {
|
|
|
|
Data->DeviceObject = targetVdo;
|
|
status = STATUS_SUCCESS;
|
|
|
|
} else {
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsPreAcquireForCcFlush Exit \n", 0);
|
|
|
|
return( status );
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsPreReleaseForCcFlush
|
|
//
|
|
// Synopsis: This is the equivalent to FastIoReleaseForCcFlush.
|
|
// Dfs receives this callback through the FsFilter interfaces
|
|
// of the FsRtl package in the kernel.
|
|
//
|
|
// This is the time to do the work necessary to end the
|
|
// synchronization operations taken to prepare for a CC flush
|
|
// of this file. If this operation should be redirected to an
|
|
// underlying FS, the parameters will be changed accordingly so
|
|
// that the operation is redirect when this callback returns.
|
|
//
|
|
// Arguments: [Data] -- The structure that contains the relevent parameters
|
|
// to this operation, like the FileObject and DeviceObject.
|
|
// [CompletionContext] - Provides a pointer for a context to be
|
|
// past from the pre to post operation. Since Dfs
|
|
// does not need a post operation, this parameter is not
|
|
// used.
|
|
//
|
|
// Returns: STATUS_SUCCESS or STATUS_INVALID_DEVICE_REQUEST for default
|
|
// actions.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
DfsPreReleaseForCcFlush(
|
|
IN PFS_FILTER_CALLBACK_DATA Data,
|
|
OUT PVOID *CompletionContext)
|
|
{
|
|
PDEVICE_OBJECT targetVdo;
|
|
NTSTATUS status;
|
|
|
|
UNREFERENCED_PARAMETER( CompletionContext );
|
|
|
|
DfsDbgTrace(+1, Dbg, "DfsPreReleaseForCcFlush Enter \n", 0);
|
|
|
|
DfsFastIoLookup(Data->FileObject, Data->DeviceObject, &targetVdo);
|
|
|
|
if (targetVdo != NULL) {
|
|
|
|
Data->DeviceObject = targetVdo;
|
|
status = STATUS_SUCCESS;
|
|
|
|
} else {
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
DfsDbgTrace(-1, Dbg, "DfsPreReleaseForCcFlush Exit \n", 0);
|
|
|
|
return( status );
|
|
}
|