|
|
/*++
Copyright (C) Microsoft Corporation, 1996 - 2001 (c) 1998 Seagate Software, Inc. All rights reserved.
Module Name:
RpFsa.h
Abstract:
Contains function declarations and structures for the File System Filter for Remote Storage
Author:
Rick Winter
Environment:
Kernel mode
Revision History:
X-13 108353 Michael C. Johnson 3-May-2001 When checking a file to determine the type of recall also check a the potential target disk to see whether or not it is writable. This is necessary now that we have read-only NTFS volumes.
X-12 365077 Michael C. Johnson 1-May-2001 Revert to previous form of RsOpenTarget() with extra access parameter to allow us to apply the desired access bypassing the access check.
X-11 194325 Michael C. Johnson 1-Mar-2001 Clean up RsMountCompletion() and RsLoadFsCompletion() to ensure they don't call routines such as IoDeleteDevice() if not running at PASSIVE_LEVEL.
Add in memory trace mechanism in preparation for attempts to flush out lingering reparse point deletion troubles.
X-10 326345 Michael C. Johnson 26-Feb-2001 Only send a single RP_RECALL_WAITING to the fsa on any one file object. Use the new flag RP_NOTIFICATION_SENT to record when notification has been done.
--*/
/* Defines */
// memory allocation Tags for debug usage
#define RP_RQ_TAG 'SFSR' // Recall queue
#define RP_FN_TAG 'NFSR' // File name cache
#define RP_SE_TAG 'ESSR' // Security info
#define RP_WQ_TAG 'QWSR' // Work queue
#define RP_QI_TAG 'IQSR' // Work Q info
#define RP_LT_TAG 'TLSR' // Long term memory
#define RP_IO_TAG 'OISR' // IOCTL queue
#define RP_FO_TAG 'OFSR' // File Object Queue
#define RP_VO_TAG 'OVSR' // Validate Queue
#define RP_ER_TAG 'RESR' // Error log data
#define RP_CC_TAG 'CCSR' // Cache buffers
#define RP_US_TAG 'SUSR' // Usn record
#define RP_CX_TAG 'CCSR' // Completion context
#define RP_TC_TAG 'CTSR' // Trace control block
#define RP_TE_TAG 'ETSR' // Trace entry buffer
#define RP_RD_TAG 'DRSR' // Root directory path
//
// Device extension for the RsFilter device object
//
typedef enum _RP_VOLUME_WRITE_STATUS { RsVolumeStatusUnknown = 0, // No attempt has been made to determine volume writeability
// or attempt to determine volume writeability failed
RsVolumeStatusReadOnly, // volume is readonly
RsVolumeStatusReadWrite // Volume is writeable
} RP_VOLUME_WRITE_STATUS;
typedef struct _DEVICE_EXTENSION { CSHORT Type; CSHORT Size; PDEVICE_OBJECT FileSystemDeviceObject;
PDEVICE_OBJECT RealDeviceObject;
BOOLEAN Attached;
BOOLEAN AttachedToNtfsControlDevice;
volatile RP_VOLUME_WRITE_STATUS WriteStatus;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
#define RSFILTER_PARAMS_KEY L"RsFilter\\Parameters"
#define RS_TRACE_LEVEL_VALUE_NAME L"TraceLevel"
#define RS_TRACE_LEVEL_DEFAULT 0
extern PDEVICE_OBJECT FsDeviceObject;
// Fsa validate job registry entry location
#define FSA_VALIDATE_LOG_KEY_NAME L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Remote_Storage_File_System_Agent\\Validate"
#define FT_VOL_LEN 32
/* First guess at device name length */ #define AV_DEV_OBJ_NAME_SIZE (40 * sizeof(wchar_t))
/* Space for a NULL and a delimiter */ #define AV_NAME_OVERHEAD (2 * sizeof(wchar_t))
#define RP_NTFS_NAME L"\\FileSystem\\NTFS"
// FILE_HSM_ACTION_ACCESS is any access that requires HSM action (delete or recall or both)
#ifdef WHEN_WE_HANDLE_DELETE
#define FILE_HSM_ACTION_ACCESS (FILE_READ_DATA | FILE_WRITE_DATA | FILE_EXECUTE | DELETE)
#else
#define FILE_HSM_ACTION_ACCESS (FILE_READ_DATA | FILE_WRITE_DATA | FILE_EXECUTE)
#endif
/* FILE_HSM_RECALL_ACCESS is any access that allows the data to be read. */
#define FILE_HSM_RECALL_ACCESS (FILE_READ_DATA | FILE_WRITE_DATA | FILE_EXECUTE)
//
// Timeout and retry values when waiting for the FSA to issue an IOCTL
// Represents the amount of time - under multiple concurrent recall situations -
// that an app will have to wait before the i/o it issued completes with
// STATUS_FILE_IS_OFFLINE because RsFilter couldn't get any IOCTLs to
// communicate with the FSA
//
#define RP_WAIT_FOR_FSA_IO_TIMEOUT -((LONGLONG) 4800000000) // 8 minutes
/* Module ID defines for error/event logging */
#define AV_MODULE_RPFILTER 1
#define AV_MODULE_RPFILFUN 2
#define AV_MODULE_RPSEC 3
#define AV_MODULE_RPZW 4
#define AV_MODULE_RPCACHE 5
#define AV_BUFFER_SIZE 1024
#ifndef BooleanFlagOn
#define BooleanFlagOn(F,SF) ( (BOOLEAN)(((F) & (SF)) != 0) )
#endif
#define AV_FT_TICKS_PER_SECOND ((LONGLONG) 10000000)
#define AV_FT_TICKS_PER_MINUTE ((LONGLONG) ((LONGLONG) 60 * AV_FT_TICKS_PER_SECOND))
#define AV_FT_TICKS_PER_HOUR ((LONGLONG) ((LONGLONG) 60 * AV_FT_TICKS_PER_MINUTE))
//
// The filter ID tracks recalls and no-recalls as follows:
// The id is a longlong where the highest order bit identifies the type of recall
// (no-recall or recall). The remaining part of the high order long identifies the
// read RP_IRP_QUEUE entry (for no-recall) or the file object entry (for recall).
// The lower long identifies the file context entry.
//
#define RP_TYPE_RECALL (ULONGLONG) 0x8000000000000000
#define RP_CONTEXT_MASK (ULONGLONG) 0x00000000ffffffff
#define RP_READ_MASK 0x7fffffff
#define RP_FILE_MASK (ULONGLONG) 0xffffffff00000000
typedef struct _RP_CREATE_INFO { PIRP irp; PIO_STACK_LOCATION irpSp; POBJECT_NAME_INFORMATION str; ULONG options; //
// Reparse point data
//
RP_DATA rpData; LONGLONG fileId; LONGLONG objIdHi; LONGLONG objIdLo; ULONG serial; ULONG action; ULONG desiredAccess; } RP_CREATE_INFO, *PRP_CREATE_INFO;
typedef struct _RP_PENDING_CREATE { //
// Filter id
//
ULONGLONG filterId; //
//
//
PRP_CREATE_INFO qInfo; //
// Event used to signal irp completion
//
KEVENT irpCompleteEvent; //
// File object for irp
//
PFILE_OBJECT fileObject; //
// Device object for irp
//
PDEVICE_OBJECT deviceObject; //
// Open options
//
ULONG options;
//
// Indicates if oplocks should not be granted (to CI for instance..)
//
#define RP_PENDING_NO_OPLOCK 0x1
//
// Indicates if IRP should be sent down again
//
#define RP_PENDING_RESEND_IRP 0x2
//
// Indicates if we should wait for irp to complete
//
#define RP_PENDING_WAIT_FOR_EVENT 0x4
//
// Indicates if this is a recall
//
#define RP_PENDING_IS_RECALL 0x8
//
// Indicates if we should reset the offline attribute of the file
//
#define RP_PENDING_RESET_OFFLINE 0x10
ULONG flags; } RP_PENDING_CREATE, *PRP_PENDING_CREATE;
#define RP_IRP_NO_RECALL 1
typedef struct _RP_IRP_QUEUE { LIST_ENTRY list; PIRP irp; PDEVICE_EXTENSION deviceExtension; ULONG flags; //
// For regular read and write, offset and length
// denote the offset and length within the file
// For no-recall reads, offset and length would
// denote the offset/length within the cacheBuffer
//
ULONGLONG offset; ULONGLONG length; //
// These fields are used only for no-recall reads
// filterId for no-recall (see filterid description)
ULONGLONG readId; ULONGLONG recallOffset; ULONGLONG recallLength; //
// User buffer for data from read-no-recall
//
PVOID userBuffer; //
// Cache block buffer for no recall data
//
PVOID cacheBuffer; } RP_IRP_QUEUE, *PRP_IRP_QUEUE;
//
// Structure tracking the no-recall master IRP and associated irps
//
typedef struct _RP_NO_RECALL_MASTER_IRP { LIST_ENTRY AssocIrps; PIRP MasterIrp; } RP_NO_RECALL_MASTER_IRP, *PRP_NO_RECALL_MASTER_IRP;
//
// User security info structure: this is required for HSM
// to do the pop-up for clients indicating the file is being recalled
//
typedef struct _RP_USER_SECURITY_INFO { //
// Sid info
//
PCHAR userInfo; ULONG userInfoLen; LUID userAuthentication; LUID userInstance; LUID tokenSourceId; //
// Token source info for user
//
CHAR tokenSource[TOKEN_SOURCE_LENGTH]; //
// Indicates if this was opened by user with admin privileges
//
BOOLEAN isAdmin; //
// Indicates if this is a local proc
//
BOOLEAN localProc;
} RP_USER_SECURITY_INFO, *PRP_USER_SECURITY_INFO;
//
// Associated macro for above
//
#define RsFreeUserSecurityInfo(UserSecurityInfo) { \
if (UserSecurityInfo) { \ if (UserSecurityInfo->userInfo) { \ ExFreePool(UserSecurityInfo->userInfo); \ } \ ExFreePool(UserSecurityInfo); \ } \ }
//
// The file object entry keeps track of an open instance of a file.
// For each NTFS file object there is one of these (if the file has an HSM tag)
// This structure points to a FS_CONTEXT entry for which there is one for each file.
// For instance if 3 clients open \\server\share\foo there will be 3 file object
// structures and they will all point to the same FS_CONTEXT structure.
//
// The file objects we are tracking will have a pointer to one of there structures attached via
// FsRtlInsertFilterContext. From there one can find the file context entry via the pointer to it.
//
typedef struct _RP_FILE_OBJ { //
// Link to next file object
//
LIST_ENTRY list; //
// File object itself
//
PFILE_OBJECT fileObj; //
// Device object
//
PDEVICE_OBJECT devObj; //
// Pointer to the RP_FILE_CONTEXT entry - there's one such entry for every *file*
//
PVOID fsContext; //
// Resource protecting this entry
//
ERESOURCE resource; //
// Spin lock protecting read/write IRP queues
//
KSPIN_LOCK qLock; //
// Pending read IRP queue
//
LIST_ENTRY readQueue; //
// Pending write IRP queue
//
LIST_ENTRY writeQueue; //
// File create options specified when opening it
//
ULONG openOptions; //
// File desired access spcecified when opening it
//
ULONG desiredAccess; //
// Flags (descriptions below)
//
ULONG flags; //
// Object id
//
LONGLONG objIdHi; LONGLONG objIdLo; //
// File Id if available
//
LONGLONG fileId; //
// Unique ID we generate for the file object
//
ULONGLONG filterId; //
// Recall action flags (see rpio.h - RP_RECALL_ACTION..)
//
ULONG recallAction; PRP_USER_SECURITY_INFO userSecurityInfo; } RP_FILE_OBJ, *PRP_FILE_OBJ;
//
// RP_FILE_OBJ Flags
//
//
// File was not opened for read or write access
//
#define RP_NO_DATA_ACCESS 1
//
// Opener is admin equivalent
//
#define RP_OPEN_BY_ADMIN 2
//
// Opened by local process
//
#define RP_OPEN_LOCAL 4
//
// Recall waiting notification already sent
//
#define RP_NOTIFICATION_SENT 8
//
// Recall state
//
typedef enum _RP_RECALL_STATE { RP_RECALL_INVALID = -1, RP_RECALL_NOT_RECALLED, RP_RECALL_STARTED, RP_RECALL_COMPLETED } RP_RECALL_STATE, *PRP_RECALL_STATE;
//
// Filter context for RsFilter:
// Since filter contexts are attached to the SCB (stream control block) we need to use
// the instance ID to indicate which file object we are interested in. We attach this
// structure to and use myFileObjEntry to point to the RP_FILE_OBJ struct that
// represents this file object.
//
typedef struct _RP_FILTER_CONTEXT { FSRTL_PER_STREAM_CONTEXT context; PVOID myFileObjEntry; } RP_FILTER_CONTEXT, *PRP_FILTER_CONTEXT;
//
// File context: one per *file*
//
typedef struct _RP_FILE_CONTEXT { //
// Links to next/prev file (hanging off RsFileObjQHead)
//
LIST_ENTRY list; //
// Lock protecting file object queue
//
KSPIN_LOCK qLock; //
// Queue of all related file object entries
//
LIST_ENTRY fileObjects; //
// Recalled data is written using this file object
//
PFILE_OBJECT fileObjectToWrite; //
// Handle for the file object we use to write to
//
HANDLE handle;
PDEVICE_OBJECT devObj;
PDEVICE_OBJECT FilterDeviceObject;
//
// Unicode name of file
//
POBJECT_NAME_INFORMATION uniName; //
// From the file object - unique file identifier
//
PVOID fsContext; //
// Buffer to write out to file
//
PVOID nextWriteBuffer; //
// Size of next write to the file (of recall data)
//
ULONG nextWriteSize; //
// Lock protecting this entry
//
ERESOURCE resource; //
// This notification event is signalled when recall completes for this file
//
KEVENT recallCompletedEvent; //
// File id if available
//
LONGLONG fileId; //
// Size in bytes of recall needed
//
LARGE_INTEGER recallSize; //
// All bytes up to this offset have been recalled
//
LARGE_INTEGER currentOffset; //
// Lower half of filter id (unique per file)
//
ULONGLONG filterId; //
// filterId for last completion
//
ULONGLONG lastRecallCompletionFilterId; //
// Volume serial number
//
ULONG serial; //
// If the recall is complete this is the status
//
NTSTATUS recallStatus; //
// Recall state
//
RP_RECALL_STATE state; //
// Flags (see below for description)
//
ULONG flags; //
// Reference count for the file context
//
ULONG refCount; //
// Usn of the file
//
USN usn; //
// Tracks create section lock
//
LONG createSectionLock; //
// Reparse point data
//
RP_DATA rpData;
} RP_FILE_CONTEXT, *PRP_FILE_CONTEXT;
//
// RP_FILE_CONTEXT Flags
//
// We have seen a write to this file
#define RP_FILE_WAS_WRITTEN 1
#define RP_FILE_INITIALIZED 2
#define RP_FILE_REPARSE_POINT_DELETED 4
/*++
VOID RsInitializeFileContextQueueLock()
Routine Description
Initializes lock guarding the file context queue
Arguments
none
Return Value
none
--*/ #define RsInitializeFileContextQueueLock() { \
DebugTrace((DPFLTR_RSFILTER_ID, DBG_LOCK,"RsFilter: RsInitializeFileContextQueueLock.\n"));\ ExInitializeFastMutex(&RsFileContextQueueLock); \ }
/*++
VOID RsAcquireFileContextQueueLock()
Routine Description
Acquire lock guarding the file context queue
Arguments
none
Return Value
none
--*/ #define RsAcquireFileContextQueueLock() { \
ExAcquireFastMutex(&RsFileContextQueueLock); \ DebugTrace((DPFLTR_RSFILTER_ID, DBG_LOCK, "RsFilter: RsAcquireFileContextQueueLock.\n"));\ }
/*++
VOID RsReleaseFileContextQueueLock()
Routine Description
Release lock guarding the file context queue
Arguments
none
Return Value
none
--*/ #define RsReleaseFileContextQueueLock() { \
DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsReleaseFileContextQueueLock.\n"));\ ExReleaseFastMutex(&RsFileContextQueueLock); \ }
/*++
VOID RsAcquireFileObjectLockExclusive()
Routine Description
Acquire lock guarding a file object entry
Arguments
none
Return Value
none
--*/ #define RsAcquireFileObjectEntryLockExclusive(entry) { \
DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsAcquireFileObjectEntryLockExclusive Waiting (%x).\n", entry));\ FsRtlEnterFileSystem(); \ ExAcquireResourceExclusiveLite(&(entry)->resource, TRUE); \ DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsAcquireFileObjectEntryLockExclusive Owned (%x).\n", entry));\ }
/*++
VOID RsAcquireFileObjectEntryLockShared()
Routine Description
Acquire lock guarding a file object entry
Arguments
none
Return Value
none
--*/ #define RsAcquireFileObjectEntryLockShared(entry) { \
DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsAcquireFileObjectEntryLockShared Waiting (%x).\n", entry));\ FsRtlEnterFileSystem(); \ ExAcquireResourceSharedLite(&(entry)->resource, TRUE); \ DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsAcquireFileObjectEntryLockShared Owned (%x).\n", entry));\ }
/*++
VOID RsReleaseFileObjectEntryLock()
Routine Description
Release lock guarding a file object entry
Arguments
none
Return Value
none
--*/ #define RsReleaseFileObjectEntryLock(entry) { \
DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsReleaseFileObjectEntryLock (%x).\n", entry));\ ExReleaseResourceLite(&(entry)->resource); \ FsRtlExitFileSystem(); \ }
/*++
VOID RsAcquireFileContextEntryLockExclusive()
Routine Description
Acquire lock guarding a file context entry
Arguments
none
Return Value
none
--*/ #define RsAcquireFileContextEntryLockExclusive(entry) { \
DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsAcquireFileContextEntryLockExclusive Waiting (%x).\n", entry));\ FsRtlEnterFileSystem(); \ ExAcquireResourceExclusiveLite(&(entry)->resource, TRUE); \ DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsAcquireFileContextEntryLockExclusive Owned (%x).\n", entry));\ }
/*++
VOID RsAcquireFileContextEntryLockShared()
Routine Description
Acquire lock guarding a file context entry
Arguments
none
Return Value
none
--*/ #define RsAcquireFileContextEntryLockShared(entry) { \
DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsAcquireFileContextEntryLockShared Waiting (%x).\n", entry));\ FsRtlEnterFileSystem(); \ ExAcquireResourceSharedLite(&(entry)->resource, TRUE); \ DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsAcquireFileContextEntryLockShared Owned (%x).\n", entry));\ }
/*++
VOID RsReleaseFileContextEntryLock()
Routine Description
Release lock guarding a file context entry
Arguments
none
Return Value
none
--*/ #define RsReleaseFileContextEntryLock(entry) { \
DebugTrace((DPFLTR_RSFILTER_ID,DBG_LOCK, "RsFilter: RsReleaseFileContextEntryLock. (%x)\n", entry));\ ExReleaseResourceLite(&(entry)->resource); \ FsRtlExitFileSystem(); \ }
/*++
VOID RsGetValidateLock(PKIRQL irql)
Routine Description:
Get a lock on the validate queue
Arguments: Place to save irql
Return Value: None
--*/ #define RsGetValidateLock(irql) ExAcquireSpinLock(&RsValidateQueueLock, irql)
/*++
VOID RsPutValidateLock(KIRQL oldIrql)
Routine Description:
Free a lock on the validate queue
Arguments: Saved irql
Return Value: None
--*/
#define RsPutValidateLock(oldIrql) ExReleaseSpinLock(&RsValidateQueueLock, oldIrql)
/*++
VOID RsGetIoLock(PKIRQL irql)
Routine Description:
Lock the IO queue
Arguments:
Variable to receive current irql
Return Value:
0
Note:
--*/
#define RsGetIoLock(irql) ExAcquireSpinLock(&RsIoQueueLock, irql)
/*++
VOID RsPutIoLock(KIRQL oldIrql)
Routine Description:
Unlock the IO queue
Arguments:
oldIrql - Saved irql
Return Value:
0
Note:
--*/
#define RsPutIoLock(oldIrql) ExReleaseSpinLock(&RsIoQueueLock, oldIrql)
#define RP_IS_NO_RECALL_OPTION(OpenOptions) \
(RsNoRecallDefault?!((OpenOptions) & FILE_OPEN_NO_RECALL) : ((OpenOptions) & FILE_OPEN_NO_RECALL))
#define RP_SET_NO_RECALL_OPTION(OpenOptions) \
(RsNoRecallDefault ? ((OpenOptions) &= ~FILE_OPEN_NO_RECALL):((OpenOptions) |= FILE_OPEN_NO_RECALL))
#define RP_RESET_NO_RECALL_OPTION(OpenOptions) \
(RsNoRecallDefault ?((OpenOptions) |= FILE_OPEN_NO_RECALL) : ((OpenOptions) &= ~FILE_OPEN_NO_RECALL))
#define RP_IS_NO_RECALL(Entry) \
(RP_IS_NO_RECALL_OPTION((Entry)->openOptions) && !(((PRP_FILE_CONTEXT) (Entry)->fsContext)->flags & RP_FILE_WAS_WRITTEN))
#define RP_SET_NO_RECALL(Entry) \
RP_SET_NO_RECALL_OPTION((Entry)->openOptions)
#define RP_RESET_NO_RECALL(Entry) \
RP_RESET_NO_RECALL_OPTION(Entry->openOptions)
typedef struct _RP_VALIDATE_INFO { LIST_ENTRY list; LARGE_INTEGER lastSetTime; // Last time a RP was set.
ULONG serial; // Volume serial number
} RP_VALIDATE_INFO, *PRP_VALIDATE_INFO;
typedef struct _AV_ERR { ULONG line; ULONG file; ULONG code; WCHAR string[1]; /* Actual size will vary */ } AV_ERR, *PAV_ERR;
//
// Possible create flags:
//
#define SF_FILE_CREATE_PATH 1
#define SF_FILE_CREATE_ID 2
#define SF_FILE_READ 3
typedef enum _RP_FILE_BUF_STATE { RP_FILE_BUF_INVALID=0, RP_FILE_BUF_IO, RP_FILE_BUF_VALID, RP_FILE_BUF_ERROR } RP_FILE_BUF_STATE, *PRP_FILE_BUF_STATE;
//
// Define the cache buffer structure
//
typedef struct _RP_FILE_BUF { //
// IRPs waiting on this block
//
LIST_ENTRY WaitQueue; //
// Volume serial number for the volume on which the file
// this block maps to resides
//
ULONG VolumeSerial; //
// File id uniquely indicating which file this block
// belongs to
//
ULONGLONG FileId; //
// Block number this buffer maps to
//
ULONGLONG Block; //
// Lock for the buffer
//
ERESOURCE Lock; //
// Links in the hash queue this buffer belongs
//
LIST_ENTRY BucketLinks; //
// Links in the lru list
//
LIST_ENTRY LruLinks; //
// Indicates the current buffer state
//
RP_FILE_BUF_STATE State; //
// If i/o completed with errors, this is useful
//
NTSTATUS IoStatus; //
// Actual buffer contents themselves
//
PUCHAR Data; //
// Usn used to validate block
//
LONGLONG Usn;
} RP_FILE_BUF, *PRP_FILE_BUF;
//
// The hash bucket structure
//
typedef struct _RP_CACHE_BUCKET { //
// Link to the head of the entries in this bucket
//
LIST_ENTRY FileBufHead;
} RP_CACHE_BUCKET, *PRP_CACHE_BUCKET;
//
// Cache LRU structure
//
typedef struct _RP_CACHE_LRU { //
// Pointer to head of LRU
//
LIST_ENTRY FileBufHead; //
// Lock structure for protecting the LRU
//
FAST_MUTEX Lock; //
// Total number of buffers in the cache
//
//
ULONG TotalCount; //
// Number of buffers in LRU (just for bookkeeping)
//
ULONG LruCount; //
// Counting semaphore used to signal availability (and number)
// of buffers in LRU
//
KSEMAPHORE AvailableSemaphore;
} RP_CACHE_LRU, *PRP_CACHE_LRU;
//
// Completion Context used by Mount and LoadFs completion routines.
//
typedef struct _RP_COMPLETION_CONTEXT { LIST_ENTRY leQueueHead; PIO_WORKITEM pIoWorkItem; PIRP pIrp; PIO_WORKITEM_ROUTINE prtnWorkItemRoutine; union { struct { PVPB pvpbOriginalVpb; PDEVICE_OBJECT pdoRealDevice; PDEVICE_OBJECT pdoNewFilterDevice; } Mount;
struct { PVOID pvDummy; } LoadFs; } Parameters; } RP_COMPLETION_CONTEXT, *PRP_COMPLETION_CONTEXT;
//
// Some utility macros
//
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) > (b) ? (b) : (a))
//
// Debug support
//
#define DBG_INFO DPFLTR_INFO_LEVEL
#define DBG_ERROR DPFLTR_ERROR_LEVEL
#define DBG_VERBOSE DPFLTR_TRACE_LEVEL
#define DBG_LOCK DPFLTR_TRACE_LEVEL
#define DebugTrace(MSG) DbgPrintEx MSG
//
// Function prototypes
//
NTSTATUS RsAddQueue(IN ULONG Serial, OUT PULONGLONG RecallId, IN ULONG OpenOption, IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DevObj, IN PDEVICE_OBJECT FilterDeviceObject, IN PRP_DATA PhData, IN LARGE_INTEGER RecallStart, IN LARGE_INTEGER RecallSize, IN LONGLONG FileId, IN LONGLONG ObjIdHi, IN LONGLONG ObjIdLo, IN ULONG DesiredAccess, IN PRP_USER_SECURITY_INFO UserSecurityInfo);
NTSTATUS RsAddFileObj(IN PFILE_OBJECT fileObj, IN PDEVICE_OBJECT FilterDeviceObject, IN RP_DATA *phData, IN ULONG openOption);
NTSTATUS RsQueueCancel(IN ULONGLONG filterId);
NTSTATUS RsMakeContext(IN PFILE_OBJECT fileObj, OUT PRP_FILE_CONTEXT *context);
NTSTATUS RsReleaseFileContext(IN PRP_FILE_CONTEXT context);
NTSTATUS RsFreeFileObject(IN PLIST_ENTRY FilterContext);
PRP_FILE_CONTEXT RsAcquireFileContext(IN ULONGLONG FilterId, IN BOOLEAN Exclusive);
VOID RsReleaseFileObject(IN PRP_FILE_OBJ entry);
NTSTATUS RsGenerateDevicePath(IN PDEVICE_OBJECT deviceObject, OUT POBJECT_NAME_INFORMATION *nameInfo );
NTSTATUS RsGenerateFullPath(IN POBJECT_NAME_INFORMATION fileName, IN PDEVICE_OBJECT deviceObject, OUT POBJECT_NAME_INFORMATION *nameInfo );
ULONG RsRemoveQueue(IN PFILE_OBJECT fileObj);
NTSTATUS RsCompleteRecall(IN PDEVICE_OBJECT DeviceObject, IN ULONGLONG FilterId, IN NTSTATUS Status, IN ULONG RecallAction, IN BOOLEAN CancellableRead);
NTSTATUS RsCompleteReads(IN PRP_FILE_CONTEXT Context);
NTSTATUS RsPreserveDates(IN PRP_FILE_CONTEXT Context);
NTSTATUS RsMarkUsn(IN PRP_FILE_CONTEXT Context);
NTSTATUS RsOpenTarget(IN PRP_FILE_CONTEXT Context, IN ULONG OpenAccess, IN ULONG AdditionalAccess, OUT HANDLE *Handle, OUT PFILE_OBJECT *FileObject);
ULONG RsIsNoRecall(IN PFILE_OBJECT fileObj, OUT PRP_DATA *rpData);
NTSTATUS RsPartialData(IN PDEVICE_OBJECT DeviceObject, IN ULONGLONG filterId, IN NTSTATUS status, IN CHAR *buffer, IN ULONG bytesRead, IN ULONGLONG offset);
NTSTATUS RsPartialWrite(IN PDEVICE_OBJECT DeviceObject, IN PRP_FILE_CONTEXT Context, IN CHAR *Buffer, IN ULONG BufLen, IN ULONGLONG Offset);
NTSTATUS RsDoWrite(IN PDEVICE_OBJECT DeviceObject, IN PRP_FILE_CONTEXT Context);
NTSTATUS RsQueueRecall(IN ULONGLONG filterId, IN ULONGLONG recallStart, IN ULONGLONG recallSize);
NTSTATUS RsQueueNoRecall(IN PFILE_OBJECT FileObject, IN PIRP Irp, IN ULONGLONG RecallStart, IN ULONGLONG RecallSize, IN ULONG BufferOffset, IN ULONG BufferLength, IN PRP_FILE_BUF CacheBuffer, IN PVOID UserBuffer);
NTSTATUS RsQueueNoRecallOpen(IN PRP_FILE_OBJ entry, IN ULONGLONG filterId, IN ULONGLONG offset, IN ULONGLONG size); NTSTATUS RsQueueRecallOpen(IN PRP_FILE_CONTEXT Context, IN PRP_FILE_OBJ Entry, IN ULONGLONG FilterId, IN ULONGLONG Offset, IN ULONGLONG Size, IN ULONG Command);
NTSTATUS RsGetFileInfo(IN PRP_FILE_OBJ Entry, IN PDEVICE_OBJECT DeviceObject);
NTSTATUS RsGetFileId(IN PRP_FILE_OBJ entry, IN PDEVICE_OBJECT DeviceObject);
NTSTATUS RsGetFileName(IN PRP_FILE_OBJ entry, IN PDEVICE_OBJECT DeviceObject);
NTSTATUS RsCloseFile(IN ULONGLONG filterId);
NTSTATUS RsCleanupFileObject(IN ULONGLONG filterId);
NTSTATUS RsCompleteIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
NTSTATUS RsCheckRead(IN PIRP irp, IN PFILE_OBJECT fileObject, IN PDEVICE_EXTENSION deviceExtension);
NTSTATUS RsCheckWrite(IN PIRP irp, IN PFILE_OBJECT fileObject, IN PDEVICE_EXTENSION deviceExtension);
NTSTATUS RsFailAllRequests(IN PRP_FILE_CONTEXT Context, IN BOOLEAN Norecall);
NTSTATUS RsCompleteAllRequests( IN PRP_FILE_CONTEXT Context, IN PRP_FILE_OBJ Entry, IN NTSTATUS Status );
NTSTATUS RsWriteReparsePointData(IN PRP_FILE_CONTEXT Context);
NTSTATUS RsTruncateFile(IN PRP_FILE_CONTEXT Context);
NTSTATUS RsSetEndOfFile(IN PRP_FILE_CONTEXT Context, IN ULONGLONG size);
BOOLEAN RsIsFastIoPossible(IN PFILE_OBJECT fileObj);
PIRP RsGetFsaRequest(VOID);
PRP_FILE_OBJ RsFindQueue(IN ULONGLONG filterId);
NTSTATUS RsAddIo(IN PIRP irp);
PIRP RsRemoveIo(VOID);
VOID RsCompleteRead(IN PRP_IRP_QUEUE Irp, IN BOOLEAN unlock);
BOOLEAN RsIsFileObj(IN PFILE_OBJECT fileObj, IN BOOLEAN returnContextData, OUT PRP_DATA *rpData, OUT POBJECT_NAME_INFORMATION *str, OUT LONGLONG *fileId, OUT LONGLONG *objIdHi, OUT LONGLONG *objIdLo, OUT ULONG *options, OUT ULONGLONG *filterId, OUT USN *usn);
VOID RsCancelRecalls(VOID);
VOID RsCancelIo(VOID);
VOID RsLogValidateNeeded(IN ULONG serial);
BOOLEAN RsAddValidateObj(IN ULONG serial, IN LARGE_INTEGER cTime); BOOLEAN RsRemoveValidateObj(IN ULONG serial);
NTSTATUS RsQueueValidate(IN ULONG serial);
ULONG RsTerminate(VOID);
NTSTATUS RsGetRecallInfo(IN OUT PRP_MSG Msg, OUT PULONG_PTR InfoSize, IN KPROCESSOR_MODE RequestorMode);
VOID RsCancelReadRecall(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); VOID RsCancelWriteRecall(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID RsLogError(IN ULONG line, IN ULONG file, IN ULONG code, IN NTSTATUS ioError, IN PIO_STACK_LOCATION irpSp, IN WCHAR *msgString);
ULONG RsGetReparseData(IN PFILE_OBJECT fileObject, IN PDEVICE_OBJECT deviceObject, OUT PRP_DATA rpData);
NTSTATUS RsCheckVolumeReadOnly (IN PDEVICE_OBJECT FilterDeviceObject, IN OUT PBOOLEAN pbReturnedFlagReadOnly);
NTSTATUS RsQueryValueKey ( IN PUNICODE_STRING KeyName, IN PUNICODE_STRING ValueName, IN OUT PULONG ValueLength, IN OUT PKEY_VALUE_FULL_INFORMATION *KeyValueInformation, IN OUT PBOOLEAN DeallocateKeyValue);
NTSTATUS RsCacheInitialize( VOID );
VOID RsCacheFsaPartialData( IN PRP_IRP_QUEUE ReadIo, IN PUCHAR Buffer, IN ULONGLONG Offset, IN ULONG Length, IN NTSTATUS Status );
VOID RsCacheFsaIoComplete( IN PRP_IRP_QUEUE ReadIo, IN NTSTATUS Status );
NTSTATUS RsGetNoRecallData( IN PFILE_OBJECT FileObject, IN PIRP Irp, IN USN Usn, IN LONGLONG FileOffset, IN LONGLONG Length, IN PUCHAR UserBuffer );
LONG RsExceptionFilter( IN WCHAR *FunctionName, IN PEXCEPTION_POINTERS ExceptionPointer);
NTSTATUS RsTruncateOnClose( IN PRP_FILE_CONTEXT Context );
NTSTATUS RsSetPremigratedState(IN PRP_FILE_CONTEXT Context);
NTSTATUS RsDeleteReparsePoint(IN PRP_FILE_CONTEXT Context); NTSTATUS RsSetResetAttributes(IN PFILE_OBJECT FileObject, IN ULONG SetAttributes, IN ULONG ResetAttributes); BOOLEAN RsSetCancelRoutine(IN PIRP Irp, IN PDRIVER_CANCEL CancelRoutine); BOOLEAN RsClearCancelRoutine ( IN PIRP Irp ); NTSTATUS RsGetFileUsn(IN PRP_FILE_CONTEXT Context, IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT FilterDeviceObject); VOID RsInterlockedRemoveEntryList(PLIST_ENTRY Entry, PKSPIN_LOCK Lock); VOID RsGetUserInfo( IN PSECURITY_SUBJECT_CONTEXT SubjectContext, OUT PRP_USER_SECURITY_INFO UserSecurityInfo);
typedef enum _RpModuleCode { ModRpFilter = 100 ,ModRpFilfun ,ModRpCache ,ModRpzw ,ModRpSec } RpModuleCode;
typedef struct _RP_TRACE_ENTRY { RpModuleCode ModuleCode; USHORT usLineNumber; USHORT usIrql; LARGE_INTEGER Timestamp; ULONG_PTR Value1; ULONG_PTR Value2; ULONG_PTR Value3; ULONG_PTR Value4; } RP_TRACE_ENTRY, *PRP_TRACE_ENTRY;
typedef struct _RP_TRACE_CONTROL_BLOCK { KSPIN_LOCK Lock; PRP_TRACE_ENTRY EntryBuffer; ULONG EntryMaximum; ULONG EntryNext; } RP_TRACE_CONTROL_BLOCK, *PRP_TRACE_CONTROL_BLOCK;
#define RsTrace0(_ModuleCode) RsTrace4 ((_ModuleCode), 0, 0, 0, 0)
#define RsTrace1(_ModuleCode, _Value1) RsTrace4 ((_ModuleCode), (_Value1), 0, 0, 0)
#define RsTrace2(_ModuleCode, _Value1, _Value2) RsTrace4 ((_ModuleCode), (_Value1), (_Value2), 0, 0)
#define RsTrace3(_ModuleCode, _Value1, _Value2, _Value3) RsTrace4 ((_ModuleCode), (_Value1), (_Value2), (_Value3), 0)
#if DBG
#define RsTrace4(_ModuleCode, _Value1, _Value2, _Value3, _Value4) RsTraceAddEntry ((_ModuleCode), \
((USHORT)(__LINE__)), \ ((ULONG_PTR)(_Value1)), \ ((ULONG_PTR)(_Value2)), \ ((ULONG_PTR)(_Value3)), \ ((ULONG_PTR)(_Value4))) #else
#define RsTrace4(_ModuleCode, _Value1, _Value2, _Value3, _Value4)
#endif
#if DBG
#define DEFAULT_TRACE_ENTRIES (0x4000)
#else
#define DEFAULT_TRACE_ENTRIES (0)
#endif
VOID RsTraceAddEntry (RpModuleCode ModuleCode, USHORT usLineNumber, ULONG_PTR Value1, ULONG_PTR Value2, ULONG_PTR Value3, ULONG_PTR Value4);
NTSTATUS RsTraceInitialize (ULONG ulRequestedTraceEntries);
extern PRP_TRACE_CONTROL_BLOCK RsTraceControlBlock; extern ULONG RsDefaultTraceEntries;
NTSTATUS RsLookupContext (PFILE_OBJECT pFileObject, PRP_FILE_OBJ *pReturnedRpFileObject, PRP_FILE_CONTEXT *pReturnedRpFileContext);
|