1480 lines
35 KiB
C
1480 lines
35 KiB
C
/*++
|
||
|
||
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;
|
||
//
|
||
// 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);
|