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.
2566 lines
83 KiB
2566 lines
83 KiB
/*++
|
|
|
|
Copyright (c) 1997-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sip.h
|
|
|
|
Abstract:
|
|
|
|
Private data structure definitions for the Single Instance Store.
|
|
|
|
Author:
|
|
|
|
Bill Bolosky [bolosky] July 1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _SIp_
|
|
#define _SIp_
|
|
|
|
|
|
#include "ntifs.h"
|
|
#include "ntdddisk.h"
|
|
#include "ntddscsi.h"
|
|
#include "ntiologc.h"
|
|
#include "stdio.h"
|
|
#include "stdlib.h"
|
|
#include "string.h"
|
|
|
|
#include "sis.h"
|
|
|
|
//
|
|
// Enable these warnings in the code.
|
|
//
|
|
|
|
#pragma warning(error:4100) // Unreferenced formal parameter
|
|
#pragma warning(error:4101) // Unreferenced local variable
|
|
|
|
//
|
|
// Debug definitions
|
|
//
|
|
|
|
#define ENABLE_LOGGING 0 // enable support for transaction logging and failure recovery
|
|
#define ENABLE_PARTIAL_FINAL_COPY 0 // enable copying out only into allocated ranges
|
|
#define INTERRUPTABLE_FINAL_COPY 1 // allow final copies (in cow.c) to stop in progress
|
|
#define TIMING 0 // timing instrumentation (should be off in most builds)
|
|
#define RANDOMLY_FAILING_MALLOC 0 // debugging code to test what happens when ExAllocatePool fails randomly (off in most builds)
|
|
#define COUNTING_MALLOC 0 // debugging code to track dynamic memory usage (off in most builds)
|
|
|
|
|
|
#ifndef INLINE
|
|
#define INLINE __inline
|
|
#endif
|
|
|
|
|
|
//
|
|
// this is a COPY of ntfs\nodetype.h data. this MUST be cleaned up
|
|
// NTRAID#65193-2000/03/10-nealch Remove NTFS_NTC_SCB_DATA definition
|
|
//
|
|
#define NTFS_NTC_SCB_DATA ((CSHORT)0x0705)
|
|
|
|
//
|
|
// Memory Pool tags used by SIS.
|
|
//
|
|
|
|
// BsiS - BreakEvent in a perFO
|
|
// CsiS - CSFile objects
|
|
// FsiS - per file object
|
|
// LsiS - per link objects
|
|
// SsiS - SCB
|
|
|
|
#define SIS_POOL_TAG ' siS' // anything else
|
|
|
|
|
|
//
|
|
// Local name buffer size (in WCHAR's)
|
|
//
|
|
|
|
#define MAX_DEVNAME_LENGTH 256
|
|
|
|
|
|
//
|
|
// Our local DbgPrintEx() filter flag values
|
|
//
|
|
|
|
#define DPFLTR_VOLNAME_TRACE_LEVEL 31 // trace volume name
|
|
#define DPFLTR_FSCONTROL_TRACE_LEVEL 30 // trace FSCONTROL's (0x00000400)
|
|
#define DPFLTR_DISMOUNT_TRACE_LEVEL 29 // trace DISMOUNTS (0x08000000)
|
|
|
|
//
|
|
// Internal debug information
|
|
//
|
|
|
|
#if DBG
|
|
extern PVOID BJBMagicFsContext;
|
|
extern unsigned BJBDebug;
|
|
// BJB Debug Bits 0x00000001 Print all SiClose calls
|
|
// 0x00000002 Print all create completions
|
|
// 0x00000004 Print when SipIsFileObjectSIS allocates a new perFO
|
|
// 0x00000008 Intentionally fail copies of alternate streams
|
|
// 0x00000010 Prints in siinfo
|
|
// 0x00000020 Prints all scbs going through cleanup
|
|
// 0x00000040 Prints all filenames coming into create
|
|
// 0x00000080 Always fail opens as if DELETE_IN_PROGRESS
|
|
// 0x00000100 Allow opens with bogus checksum
|
|
// 0x00000200 Print out CS file checksum info
|
|
// 0x00000400 Breakpoint when SiFsControl is called with an unknown control code
|
|
// 0x00000800 Prints in copyfile
|
|
// 0x00001000 Print all fscontrol calls
|
|
// 0x00002000 Print stuff related to complete-if-oplocked
|
|
// 0x00004000 Print all reads
|
|
// 0x00008000 Print all writes
|
|
// 0x00010000 Print setEof calls
|
|
// 0x00020000 Print stuff in TrimLog code
|
|
// 0x00040000 Print out unexpected cleanups
|
|
// 0x00080000 Assert on volume check initiation
|
|
// 0x00100000 Print newly opened dirty files
|
|
// 0x00200000 Disable final copy (for testing purposes)
|
|
// 0x00400000 Don't check security in LINK_FILES fsctl.
|
|
// 0x00800000 Intentionally fail SET_REPARSE_POINT calls
|
|
// 0x01000000 Intentionally fail final copy
|
|
// 0x02000000 Don't Print out all intentionally failed mallocs
|
|
// 0x04000000 Always post filter context freed callbacks
|
|
// 0x08000000 Print on dismount actions
|
|
// 0x10000000 Open with FILE_SHARE_WRITE attribute
|
|
|
|
// 0x0817fa77 Value to set if you want all debug prints
|
|
#endif // DBG
|
|
|
|
|
|
// IoFileObjectType is a data import, and hence is a pointer in this module's
|
|
// import address table referring to the actual variable in ntoskrnl.exe.
|
|
//
|
|
|
|
extern POBJECT_TYPE *IoFileObjectType; // shouldn't this come from somewhere else??
|
|
|
|
#define GCH_MARK_POINT_STRLEN 80
|
|
#define GCH_MARK_POINT_ROLLOVER 512
|
|
extern LONG GCHEnableFastIo;
|
|
extern LONG GCHEnableMarkPoint;
|
|
extern LONG GCHMarkPointNext;
|
|
extern CHAR GCHMarkPointStrings[GCH_MARK_POINT_ROLLOVER][GCH_MARK_POINT_STRLEN];
|
|
extern KSPIN_LOCK MarkPointSpinLock[1];
|
|
|
|
#if DBG
|
|
#define SIS_MARK_POINT() SipMarkPoint(__FILE__, __LINE__)
|
|
#define SIS_MARK_POINT_ULONG(value) SipMarkPointUlong(__FILE__, __LINE__, (ULONG_PTR)(value));
|
|
#else
|
|
#define SIS_MARK_POINT()
|
|
#define SIS_MARK_POINT_ULONG(value)
|
|
#endif
|
|
|
|
#if TIMING
|
|
#define SIS_TIMING_POINT_SET(n) SipTimingPoint(__FILE__, __LINE__, n)
|
|
#define SIS_TIMING_POINT() SipTimingPoint(__FILE__, __LINE__, 0)
|
|
|
|
//
|
|
// Timimg classes. These can be enabled and disabled dynamically.
|
|
// They must be limited to 0-31. Class 0 is resrved for the
|
|
// "unnamed" class, and is accessed by using SIS_TIMING_POINT()
|
|
// (ie., by not specifying a class in the timing point).
|
|
//
|
|
#define SIS_TIMING_CLASS_CREATE 1
|
|
#define SIS_TIMING_CLASS_COPYFILE 2
|
|
|
|
#else // TIMING
|
|
#define SIS_TIMING_POINT_SET(n)
|
|
#define SIS_TIMING_POINT()
|
|
#endif // TIMING
|
|
|
|
#if RANDOMLY_FAILING_MALLOC
|
|
#define ExAllocatePoolWithTag(poolType, size, tag) SipRandomlyFailingExAllocatePoolWithTag((poolType),(size),(tag),__FILE__,__LINE__)
|
|
|
|
VOID *
|
|
SipRandomlyFailingExAllocatePoolWithTag(
|
|
IN POOL_TYPE PoolType,
|
|
IN ULONG NumberOfBytes,
|
|
IN ULONG Tag,
|
|
IN PCHAR File,
|
|
IN ULONG Line);
|
|
|
|
VOID
|
|
SipInitFailingMalloc(void);
|
|
|
|
#elif COUNTING_MALLOC
|
|
//
|
|
// This is the definition of ExAllocatePoolWithTag for COUNTING_MALLOC and not RANDOMLY_FAILING_MALLOC.
|
|
// If both are on, the user calls RANDOMLY_FAILING_MALLOC, which in turn calls the counting malloc
|
|
// directly.
|
|
//
|
|
#define ExAllocatePoolWithTag(poolType, size, tag) SipCountingExAllocatePoolWithTag((poolType),(size),(tag), __FILE__, __LINE__)
|
|
#endif // RANDOMLY_FAILING_MALLOC / COUNTING_MALLOC
|
|
|
|
#if COUNTING_MALLOC
|
|
#define ExFreePool(p) SipCountingExFreePool((p))
|
|
|
|
VOID *
|
|
SipCountingExAllocatePoolWithTag(
|
|
IN POOL_TYPE PoolType,
|
|
IN ULONG NumberOfBytes,
|
|
IN ULONG Tag,
|
|
IN PCHAR File,
|
|
IN ULONG Line);
|
|
|
|
VOID
|
|
SipCountingExFreePool(
|
|
PVOID p);
|
|
|
|
VOID
|
|
SipInitCountingMalloc(void);
|
|
|
|
VOID
|
|
SipDumpCountingMallocStats(void);
|
|
#endif // COUNTING_MALLOC
|
|
|
|
#if DBG
|
|
|
|
#undef ASSERT
|
|
#undef ASSERTMSG
|
|
|
|
VOID
|
|
SipAssert(
|
|
PVOID FailedAssertion,
|
|
PVOID FileName,
|
|
ULONG LineNumber,
|
|
PCHAR Message
|
|
);
|
|
|
|
#define ASSERT( exp ) \
|
|
((!(exp)) ? SipAssert( #exp, __FILE__, __LINE__, NULL ) : ((void)0))
|
|
|
|
#define ASSERTMSG( msg, exp ) \
|
|
((!(exp)) ? SipAssert( #exp, __FILE__, __LINE__, msg ) : ((void)0))
|
|
|
|
#endif // DBG
|
|
|
|
#ifndef IsEqualGUID
|
|
#define IsEqualGUID(guid1, guid2) (!memcmp((guid1),(guid2), sizeof(GUID)))
|
|
#endif // IsEqualGUID
|
|
|
|
|
|
//
|
|
// Used to change ownership of a resource
|
|
//
|
|
|
|
#define MAKE_RESOURCE_OWNER(X) (((ERESOURCE_THREAD)(X)) | 0x3)
|
|
|
|
|
|
extern PDRIVER_OBJECT FsDriverObject;
|
|
extern PDEVICE_OBJECT FsNtfsDeviceObject;
|
|
extern PDEVICE_OBJECT SisControlDeviceObject;
|
|
|
|
//
|
|
// Splay tree support.
|
|
//
|
|
|
|
//
|
|
// The comparison function takes as input a pointer to a user defined
|
|
// key structure, and a pointer to a tree node. It returns the results
|
|
// of comparing the key and the node.
|
|
//
|
|
|
|
typedef
|
|
LONG
|
|
(NTAPI *PSIS_TREE_COMPARE_ROUTINE) (
|
|
PVOID Key,
|
|
PVOID Node
|
|
);
|
|
|
|
typedef struct _SIS_TREE {
|
|
|
|
PRTL_SPLAY_LINKS TreeRoot;
|
|
PSIS_TREE_COMPARE_ROUTINE CompareRoutine;
|
|
|
|
} SIS_TREE, *PSIS_TREE;
|
|
|
|
//
|
|
// Define the device extension structure for this driver's extensions.
|
|
//
|
|
|
|
typedef struct _DEVICE_EXTENSION *PDEVICE_EXTENSION;
|
|
|
|
//
|
|
// SIS structure for a common store file opened by SIS.
|
|
//
|
|
typedef struct _SIS_CS_FILE {
|
|
//
|
|
// This structure is stored in a splay tree. The splay links must be first.
|
|
//
|
|
RTL_SPLAY_LINKS Links;
|
|
|
|
//
|
|
// Count of the number of SIS_PER_LINKs that reference this common store file. Protected by
|
|
// the CSFileSpinLock in the device extension.
|
|
//
|
|
unsigned RefCount;
|
|
|
|
//
|
|
// A spin lock to protect some of the fields here.
|
|
//
|
|
KSPIN_LOCK SpinLock[1];
|
|
|
|
//
|
|
// The file object for the actual NTFS common store file.
|
|
//
|
|
PFILE_OBJECT UnderlyingFileObject;
|
|
HANDLE UnderlyingFileHandle;
|
|
|
|
//
|
|
// A handle and file object for the backpointer stream. This also contains the contents
|
|
// checksum.
|
|
//
|
|
HANDLE BackpointerStreamHandle;
|
|
PFILE_OBJECT BackpointerStreamFileObject;
|
|
|
|
//
|
|
// Various one-bit flags. Protected by SpinLock.
|
|
//
|
|
ULONG Flags;
|
|
|
|
#define CSFILE_NTFSID_SET 0x00000001 // Is CSFileNtfsId set in the structure?
|
|
#define CSFILE_FLAG_DELETED 0x00000002 // The common store contents have been deleted
|
|
#define CSFILE_NEVER_HAD_A_REFERENCE 0x00000004 // Is this a newly created CS file that has never had a reference to it?
|
|
#define CSFILE_FLAG_CORRUPT 0x00000008 // The backpointer stream is corrupt
|
|
|
|
//
|
|
// The size of the file.
|
|
//
|
|
LARGE_INTEGER FileSize;
|
|
|
|
//
|
|
// The SIS common store file id (which is also the name of the file within the
|
|
// common store directory).
|
|
//
|
|
CSID CSid;
|
|
|
|
//
|
|
// The NTFS file index for the common store file.
|
|
//
|
|
LARGE_INTEGER CSFileNtfsId;
|
|
|
|
//
|
|
// The checksum for the contents of the common store file.
|
|
//
|
|
LONGLONG Checksum;
|
|
|
|
//
|
|
// A cache of recently validated backpointers for this file and an index that
|
|
// represents the next entry to overwrite.
|
|
//
|
|
#define SIS_CS_BACKPOINTER_CACHE_SIZE 5
|
|
SIS_BACKPOINTER BackpointerCache[SIS_CS_BACKPOINTER_CACHE_SIZE];
|
|
ULONG BPCacheNextSlot;
|
|
|
|
PDEVICE_OBJECT DeviceObject;
|
|
|
|
//
|
|
// The number of entries allocated to the backpointer stream. Note that this
|
|
// is NOT the same as the file reference count, as some of these entries may
|
|
// be deallocated. Note also that this count is not necessarily 100% accurate,
|
|
// but rather may refer to anywhere in the last sector of the file.
|
|
//
|
|
ULONG BPStreamEntries;
|
|
|
|
//
|
|
// A resource for controlling access to the backpoionter stream.
|
|
//
|
|
ERESOURCE BackpointerResource[1];
|
|
|
|
KMUTANT UFOMutant[1];
|
|
} SIS_CS_FILE, *PSIS_CS_FILE;
|
|
|
|
//
|
|
// The per-link-file object. There is one of these for each open SIS link file
|
|
// in the system, regardless of the number of times that link file is opened.
|
|
// This is roughly analogous to an FCB in NTFS.
|
|
//
|
|
typedef struct _SIS_PER_LINK {
|
|
//
|
|
// This structure is stored in a splay tree. The splay links must be first.
|
|
//
|
|
RTL_SPLAY_LINKS Links;
|
|
|
|
//
|
|
// Pointer to the SIS_CS_FILE object for this link file.
|
|
//
|
|
PSIS_CS_FILE CsFile;
|
|
|
|
//
|
|
// The index of this link file.
|
|
//
|
|
LINK_INDEX Index;
|
|
|
|
//
|
|
// The NTFS file index for the link file object.
|
|
//
|
|
LARGE_INTEGER LinkFileNtfsId;
|
|
|
|
//
|
|
// Reference count (number of SCB objects that point at this link object).
|
|
//
|
|
ULONG RefCount;
|
|
|
|
//
|
|
// Various 1-bit long things
|
|
//
|
|
ULONG Flags;
|
|
|
|
//
|
|
// The thread that's doing the copy-on-write operation on this file.
|
|
//
|
|
PETHREAD COWingThread;
|
|
|
|
|
|
KSPIN_LOCK SpinLock[1];
|
|
|
|
//
|
|
// We keep track of the count of threads executing delete or undelete requests in order to
|
|
// make sure that we only have one kind of request in the system at a time. We need to
|
|
// serialize them so that we're sure what NTFS thinks the delete disposition is when it
|
|
// comes time to delete a file. If we need to block, we set the SIS_PER_LINK_DELETE_WAITERS
|
|
// flag and wait on perLink->Event. If the count is non-zero, it represents undeletes if
|
|
// and only if the SIS_PER_LINK_UNDELETE_IN_PROGRESS flag is set.
|
|
//
|
|
ULONG PendingDeleteCount;
|
|
|
|
//
|
|
// An event that's set when the final copy is completed if there
|
|
// are any final copy waiters.
|
|
//
|
|
KEVENT Event[1];
|
|
|
|
//
|
|
// An event used to serialize delete operations.
|
|
//
|
|
KEVENT DeleteEvent[1];
|
|
|
|
} SIS_PER_LINK, *PSIS_PER_LINK;
|
|
|
|
//
|
|
// Values for the SIS_PER_LINK Flags field.
|
|
//
|
|
#define SIS_PER_LINK_BACKPOINTER_GONE 0x00000001 // Have we removed the backpointer for this file
|
|
#define SIS_PER_LINK_FINAL_COPY 0x00000002 // A final copy is in progress (or finished)
|
|
#define SIS_PER_LINK_FINAL_COPY_DONE 0x00000004 // A final copy is finished
|
|
#define SIS_PER_LINK_DIRTY 0x00000008 // Has a write ever been done to any stream of this link?
|
|
#define SIS_PER_LINK_FINAL_COPY_WAITERS 0x00000010 // Are any threads blocked waiting final copy to be cleared
|
|
#define SIS_PER_LINK_OVERWRITTEN 0x00000020 // File's entire contents have been modified
|
|
#define SIS_PER_LINK_FILE_DELETED 0x00000040 // Has the file been deleted by SetInformationFile, delete-on-close or rename over?
|
|
#define SIS_PER_LINK_DELETE_DISPOSITION_SET 0x00000080 // Does NTFS think that the delete disposition is set on this file?
|
|
#define SIS_PER_LINK_DELETE_WAITERS 0x00000100 // Is anyone waiting for PendingDeleteCount to get to zero?
|
|
#define SIS_PER_LINK_UNDELETE_IN_PROGRESS 0x00000200 // Set iff PendingDeleteCount represents undelete operations
|
|
#define SIS_PER_LINK_FINAL_DELETE_IN_PROGRESS 0x00000400 // We've sent what we think is the final delete to NTFS; don't allow creates
|
|
#define SIS_PER_LINK_BACKPOINTER_VERIFIED 0x00000800 // Have we assured that this per link has a CSFile backpointer
|
|
|
|
typedef struct _SIS_FILTER_CONTEXT {
|
|
//
|
|
// This structure must start off with an FSRTL_FILTER_CONTEXT in order to be able
|
|
// to use the FsRtlFilterContext routines.
|
|
//
|
|
FSRTL_PER_STREAM_CONTEXT ContextCtrl;
|
|
|
|
//
|
|
// The primary scb. There may be other scb's associated with this filter
|
|
// context (identified via the perFO's), but they must all be defunct,
|
|
// i.e. marked SIS_PER_LINK_CAN_IGNORE. New file objects always attach
|
|
// to the primary scb.
|
|
//
|
|
struct _SIS_SCB *primaryScb;
|
|
|
|
//
|
|
// Linked list of all the perFO's associated with this file.
|
|
//
|
|
struct _SIS_PER_FILE_OBJECT *perFOs;
|
|
|
|
//
|
|
// Number of perFO's attached to this filter context.
|
|
//
|
|
ULONG perFOCount;
|
|
|
|
// Counting for OpLocks.
|
|
ULONG UncleanCount;
|
|
|
|
//
|
|
// A fast mutex to protect the filter context.
|
|
//
|
|
FAST_MUTEX FastMutex[1];
|
|
|
|
#if DBG
|
|
//
|
|
// The owner of the fast mutex.
|
|
//
|
|
ERESOURCE_THREAD MutexHolder;
|
|
#endif
|
|
|
|
} SIS_FILTER_CONTEXT, *PSIS_FILTER_CONTEXT;
|
|
|
|
typedef struct _SIS_PER_FILE_OBJECT {
|
|
//
|
|
// A pointer to the filter context for this file.
|
|
//
|
|
struct _SIS_FILTER_CONTEXT *fc;
|
|
|
|
//
|
|
// A pointer to the SCB holding the reference for this file.
|
|
//
|
|
struct _SIS_SCB *referenceScb;
|
|
|
|
//
|
|
// A pointer back to the file object that refers to this perFO.
|
|
//
|
|
PFILE_OBJECT fileObject;
|
|
|
|
//
|
|
// 1-bit stuff
|
|
//
|
|
ULONG Flags;
|
|
#define SIS_PER_FO_UNCLEANUP 0x00000001 // do we expect to see a cleanup on this perFO?
|
|
#define SIS_PER_FO_DELETE_ON_CLOSE 0x00000002 // The file was opened delete-on-close
|
|
#define SIS_PER_FO_OPBREAK 0x00000004 // This file was opened COMPLETE_IF_OPLOCKED,
|
|
// it returned STATUS_OPLOCK_BREAK_IN_PROGRESS,
|
|
// and the oplock break hasn't yet been acked.
|
|
#define SIS_PER_FO_OPBREAK_WAITERS 0x00000008 // Is anyone wating for the opbreak to complete?
|
|
#define SIS_PER_FO_OPEN_REPARSE 0x00000010 // Was this per-FO opened FILE_OPEN_REPARSE_POINT
|
|
|
|
#if DBG
|
|
#define SIS_PER_FO_NO_CREATE 0x80000000 // Was this perFO allocated by SipIsFileObjectSIS
|
|
#define SIS_PER_FO_CLEANED_UP 0x40000000 // Has this perFO already come through cleanup?
|
|
#endif // DBG
|
|
|
|
//
|
|
// A spin lock to protect the flags
|
|
//
|
|
KSPIN_LOCK SpinLock[1];
|
|
|
|
//
|
|
// Linked list pointers for the perFOs associated
|
|
// with a particular filter context.
|
|
//
|
|
struct _SIS_PER_FILE_OBJECT *Next, *Prev;
|
|
|
|
//
|
|
// An event that's used for opbreak waiters. Only alloated when SIS_PER_FO_OPBREAK
|
|
// is set.
|
|
//
|
|
PKEVENT BreakEvent;
|
|
|
|
#if DBG
|
|
//
|
|
// The FsContext (NTFS scb) for the file object pointed to by
|
|
// this perFO.
|
|
//
|
|
PVOID FsContext;
|
|
|
|
//
|
|
// If this was allocated by SipIsFileObjectSIS, then the file and line number
|
|
// of the call that allocated it.
|
|
//
|
|
PCHAR AllocatingFilename;
|
|
ULONG AllocatingLineNumber;
|
|
#endif // DBG
|
|
|
|
|
|
} SIS_PER_FILE_OBJECT, *PSIS_PER_FILE_OBJECT;
|
|
|
|
//
|
|
// Reference types for references held to SCBs.
|
|
//
|
|
|
|
typedef enum _SCB_REFERENCE_TYPE {
|
|
RefsLookedUp = 0, // NB: the code assumes this is the first reference type
|
|
RefsPerFO,
|
|
RefsPredecessorScb,
|
|
RefsFinalCopy,
|
|
RefsCOWRequest,
|
|
RefsRead,
|
|
RefsWrite,
|
|
RefsWriteCompletion,
|
|
RefsReadCompletion,
|
|
RefsEnumeration,
|
|
RefsFinalCopyRetry,
|
|
RefsFc,
|
|
NumScbReferenceTypes
|
|
} SCB_REFERENCE_TYPE, *PSCB_REFERENCE_TYPE;
|
|
|
|
#if DBG
|
|
extern ULONG totalScbReferences;
|
|
extern ULONG totalScbReferencesByType[];
|
|
#endif // DBG
|
|
|
|
//
|
|
// The SCB for a SIS-owned file. These are one per stream for a particular link file.
|
|
// They are pointed to by FileObject->FsContext.
|
|
//
|
|
typedef struct _SIS_SCB {
|
|
RTL_SPLAY_LINKS Links;
|
|
|
|
// Need something to contain the stream name.
|
|
|
|
PSIS_PER_LINK PerLink;
|
|
|
|
//
|
|
// List of predecessor scb's. Any SCB's that are predecessors must be
|
|
// defunct (ie., have CAN_IGNORE set).
|
|
//
|
|
struct _SIS_SCB *PredecessorScb;
|
|
|
|
//
|
|
// Reference count (number of file objects that point to this SCB structure)
|
|
//
|
|
ULONG RefCount;
|
|
|
|
//
|
|
// All scb's are on a volume global list for enumeration during volume check.
|
|
//
|
|
LIST_ENTRY ScbList;
|
|
|
|
//
|
|
// The first byte that must be from the copied file rather than from the
|
|
// underlying file. scb->Ranges is only maintained up to this address.
|
|
// This starts out at the size of the underlying file at copy-on-write time,
|
|
// and gets reduced if the file is truncated, but not increased if its
|
|
// extended.
|
|
//
|
|
LONGLONG SizeBackedByUnderlyingFile;
|
|
|
|
//
|
|
// The count of failed final copy retries.
|
|
//
|
|
ULONG ConsecutiveFailedFinalCopies;
|
|
|
|
//
|
|
// Various 1-bit things
|
|
//
|
|
ULONG Flags;
|
|
#define SIS_SCB_MCB_INITIALIZED 0x00000001
|
|
#define SIS_SCB_INITIALIZED 0x00000004 // is the SCB itself initialized
|
|
#define SIS_SCB_ANYTHING_IN_COPIED_FILE 0x00000008 // Is there possibly something in the copied file or its data section?
|
|
#define SIS_SCB_RANGES_INITIALIZED 0x00000010 // Have we checked allocated ranges for this file?
|
|
#define SIS_SCB_BACKING_FILE_OPENED_DIRTY 0x00000020 // did the backing file stream have anything in it when it was opened?
|
|
|
|
//
|
|
// A fast mutex to protect the SCB.
|
|
//
|
|
FAST_MUTEX FastMutex[1];
|
|
|
|
// File locking structures
|
|
FILE_LOCK FileLock;
|
|
|
|
//
|
|
// A large MCB to use for the written/faulted ranges.
|
|
//
|
|
LARGE_MCB Ranges[1];
|
|
|
|
#if DBG
|
|
//
|
|
// The owner of the fast mutex.
|
|
//
|
|
ERESOURCE_THREAD MutexHolder;
|
|
|
|
//
|
|
// A count of references by type.
|
|
//
|
|
|
|
ULONG referencesByType[NumScbReferenceTypes];
|
|
#endif // DBG
|
|
|
|
} SIS_SCB, *PSIS_SCB;
|
|
|
|
//
|
|
// A request to open a common store file. The caller must hold
|
|
// the UFOMutant for this file. Status is returned in openStatus
|
|
// and then event is set. It's the caller's responsibility to
|
|
// initialize the event and then deallocate the SI_OPEN_CS_FILE
|
|
// after it's completed.
|
|
//
|
|
typedef struct _SI_OPEN_CS_FILE {
|
|
WORK_QUEUE_ITEM workQueueItem[1];
|
|
PSIS_CS_FILE CSFile;
|
|
NTSTATUS openStatus;
|
|
BOOLEAN openByName;
|
|
KEVENT event[1];
|
|
} SI_OPEN_CS_FILE, *PSI_OPEN_CS_FILE;
|
|
|
|
//
|
|
// A request to close a handle(s) in the PsInitialProcess context. (sent to a worker thread)
|
|
//
|
|
typedef struct _SI_CLOSE_HANDLES {
|
|
WORK_QUEUE_ITEM workQueueItem[1];
|
|
HANDLE handle1;
|
|
HANDLE handle2; OPTIONAL
|
|
NTSTATUS status;
|
|
PERESOURCE resourceToRelease; OPTIONAL
|
|
ERESOURCE_THREAD resourceThreadId; OPTIONAL
|
|
} SI_CLOSE_HANDLES, *PSI_CLOSE_HANDLES;
|
|
|
|
//
|
|
// A request to allocate more index space for a particular device.
|
|
//
|
|
typedef struct _SI_ALLOCATE_INDICES {
|
|
WORK_QUEUE_ITEM workQueueItem[1];
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
} SI_ALLOCATE_INDICES, *PSI_ALLOCATE_INDICES;
|
|
|
|
typedef struct _SI_COPY_THREAD_REQUEST {
|
|
LIST_ENTRY listEntry[1];
|
|
PSIS_SCB scb;
|
|
BOOLEAN fromCleanup;
|
|
} SI_COPY_THREAD_REQUEST, *PSI_COPY_THREAD_REQUEST;
|
|
|
|
typedef struct _SI_FSP_REQUEST {
|
|
WORK_QUEUE_ITEM workQueueItem[1];
|
|
PIRP Irp;
|
|
PDEVICE_OBJECT DeviceObject;
|
|
ULONG Flags;
|
|
} SI_FSP_REQUEST, *PSI_FSP_REQUEST;
|
|
|
|
#define FSP_REQUEST_FLAG_NONE 0x00000000 // Just a define so that we don't have to use "0" in calls
|
|
#define FSP_REQUEST_FLAG_WRITE_RETRY 0x00000001
|
|
|
|
typedef struct _RW_COMPLETION_UPDATE_RANGES_CONTEXT {
|
|
WORK_QUEUE_ITEM workQueueItem[1];
|
|
PSIS_SCB scb;
|
|
LARGE_INTEGER offset;
|
|
ULONG length;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
BOOLEAN NonCached;
|
|
} RW_COMPLETION_UPDATE_RANGES_CONTEXT, *PRW_COMPLETION_UPDATE_RANGES_CONTEXT;
|
|
|
|
typedef struct _SIS_CREATE_CS_FILE_REQUEST {
|
|
WORK_QUEUE_ITEM workQueueItem[1];
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PCSID CSid;
|
|
PFILE_OBJECT srcFileObject;
|
|
PLARGE_INTEGER NtfsId;
|
|
PKEVENT abortEvent;
|
|
PLONGLONG CSFileChecksum;
|
|
KEVENT doneEvent[1];
|
|
NTSTATUS status;
|
|
} SIS_CREATE_CS_FILE_REQUEST, *PSIS_CREATE_CS_FILE_REQUEST;
|
|
|
|
|
|
#ifndef COPYFILE_SIS_LINK // This is in ntioapi.h; leaving this here conditionally allows for compiling with both old and new ntioapi.h
|
|
//
|
|
// FSCTL_SIS_COPYFILE support
|
|
// Source and destination file names are passed in the FileNameBuffer.
|
|
// Both strings are null terminated, with the source name starting at
|
|
// the beginning of FileNameBuffer, and the destination name immediately
|
|
// following. Length fields include terminating nulls.
|
|
//
|
|
|
|
typedef struct _SI_COPYFILE {
|
|
ULONG SourceFileNameLength;
|
|
ULONG DestinationFileNameLength;
|
|
ULONG Flags;
|
|
WCHAR FileNameBuffer[1]; // NB: Code in the filter requires that this is the final field
|
|
} SI_COPYFILE, *PSI_COPYFILE;
|
|
#endif // COPYFILE_SIS_LINK
|
|
|
|
#define COPYFILE_SIS_LINK 0x0001 // Copy only if source is SIS
|
|
#define COPYFILE_SIS_REPLACE 0x0002 // Replace destination if it exists, otherwise don't.
|
|
#define COPYFILE_SIS_FLAGS 0x0003
|
|
// NB: in DBG systems, the high bit is reserved for "checkpoint log"
|
|
|
|
//
|
|
// Macro to test if this is my device object
|
|
//
|
|
|
|
#define IS_MY_DEVICE_OBJECT(_devObj) \
|
|
(((_devObj)->DriverObject == FsDriverObject) && \
|
|
((_devObj)->DeviceExtension != NULL))
|
|
|
|
//
|
|
// Macro to test if this is my control device object
|
|
//
|
|
|
|
#define IS_MY_CONTROL_DEVICE_OBJECT(_devObj) \
|
|
(((_devObj) == SisControlDeviceObject) ? \
|
|
(ASSERT(((_devObj)->DriverObject == FsDriverObject) && \
|
|
((_devObj)->DeviceExtension == NULL)), TRUE) : \
|
|
FALSE)
|
|
|
|
//
|
|
// Macro to test for device types we want to attach to
|
|
//
|
|
|
|
#define IS_DESIRED_DEVICE_TYPE(_type) \
|
|
((_type) == FILE_DEVICE_DISK_FILE_SYSTEM)
|
|
|
|
|
|
//#define SIS_DEVICE_TYPE /*(CSHORT)*/0xbb00
|
|
|
|
typedef struct _DEVICE_EXTENSION {
|
|
PDEVICE_OBJECT AttachedToDeviceObject/*FileSystemDeviceObject*/;
|
|
PDEVICE_OBJECT RealDeviceObject;
|
|
|
|
//
|
|
// A pointer to the device object associated with this extension
|
|
//
|
|
|
|
PDEVICE_OBJECT DeviceObject;
|
|
|
|
//
|
|
// A list of all of the SIS device extensions in the system.
|
|
//
|
|
|
|
LIST_ENTRY DevExtLink;
|
|
|
|
//
|
|
// The absolute pathname of the common store directory. This includes
|
|
// the trailing "\"
|
|
//
|
|
|
|
UNICODE_STRING CommonStorePathname;
|
|
|
|
//
|
|
// The absolute pathname of the filesystem root. This does include
|
|
// a trailing "\"
|
|
//
|
|
|
|
UNICODE_STRING FilesystemRootPathname;
|
|
|
|
#if DBG
|
|
//
|
|
// A cached copy of the name of the device we are attached to.
|
|
// - If it is a file system device object it will be the name of that
|
|
// device object.
|
|
// - If it is a mounted volume device object it will be the name of the
|
|
// real device object (since mounted volume device objects don't have
|
|
// names).
|
|
//
|
|
|
|
UNICODE_STRING Name;
|
|
#endif
|
|
|
|
//
|
|
// A count of outstanding final copy retries for this volume. When this
|
|
// count starts getting too large, we reduce the number of times
|
|
// that we retry final copies in order to preserve memory.
|
|
//
|
|
ULONG OutstandingFinalCopyRetries;
|
|
|
|
//
|
|
// The volume sector size and the "bytes per file record." Bytes per file
|
|
// record is a number that's big enough that any file with
|
|
// this allocation size is guaranteed to not be a resident attribute.
|
|
// We store BytesPerFileRecordSegment in a large integer for convenience,
|
|
// because we need to pass it into a call that takes a large integer
|
|
// argument.
|
|
//
|
|
ULONG FilesystemVolumeSectorSize;
|
|
LARGE_INTEGER FilesystemBytesPerFileRecordSegment;
|
|
|
|
//
|
|
// A handle to \SIS Common Store\GrovelerFile. This is used
|
|
// for two purposes. First, it is used when we need a handle
|
|
// to do open-by-id; for that purpose any handle on the
|
|
// volume will do. Second, it is used to check for security
|
|
// on the FSCTL_LINK_FILES fsctl. Any calls on any file
|
|
// other than the one opened by GrovelerFileHandle will
|
|
// fail; in this way, we can prevent non-privileged users
|
|
// from making this call.
|
|
//
|
|
|
|
HANDLE GrovelerFileHandle;
|
|
PFILE_OBJECT GrovelerFileObject;
|
|
|
|
//
|
|
// Various 1 bit flags related to this volume, and a spin lock to protect them.
|
|
//
|
|
KSPIN_LOCK FlagsLock[1];
|
|
ULONG Flags;
|
|
#define SIP_EXTENSION_FLAG_PHASE_2_STARTED 0x00000001 // Phase 2 initialization is started
|
|
#define SIP_EXTENSION_FLAG_VCHECK_EXCLUSIVE 0x00000002 // In volume check backpointer resource exclusive phase
|
|
#define SIP_EXTENSION_FLAG_VCHECK_PENDING 0x00000004 // A volume check is pending
|
|
#define SIP_EXTENSION_FLAG_VCHECK_NODELETE 0x00000008 // In volume check no-delete phase
|
|
#define SIP_EXTENSION_FLAG_CORRUPT_MAXINDEX 0x00000010 // invalid maxindex--volume check is fixing it
|
|
|
|
#define SIP_EXTENSION_FLAG_INITED_CDO 0x40000000 // inited as control device object
|
|
#define SIP_EXTENSION_FLAG_INITED_VDO 0x80000000 // inited as volume device object
|
|
|
|
//
|
|
// The splay tree for per-link structures for this volume.
|
|
//
|
|
SIS_TREE PerLinkTree[1];
|
|
|
|
//
|
|
// Spin lock for accessing the per-link list. Ordered before the CSFileSpinLock.
|
|
//
|
|
KSPIN_LOCK PerLinkSpinLock[1];
|
|
|
|
//
|
|
// A splay tree and spin lock for the common store file stuructures, just like the per-link ones above.
|
|
// The spin lock is ordered after the PerLinkSpinLock, meaning that once we have the
|
|
// CSFileSpinLock, we cannot try to acquire the PerLinkSpinLock (but do not necessarily need
|
|
// to hold it in the first place).
|
|
//
|
|
SIS_TREE CSFileTree[1];
|
|
KSPIN_LOCK CSFileSpinLock[1];
|
|
|
|
//
|
|
// A resource that protects against a race between the handles being closed on a CS file after
|
|
// the last reference goes away, and someone re-opening a reference to that CS file. Everyone
|
|
// closing a CS file takes this resource shared. When an opener gets a sharing violation on the
|
|
// backpointer stream, it takes the resource exclusively and retries.
|
|
//
|
|
ERESOURCE CSFileHandleResource[1];
|
|
|
|
//
|
|
// The splay tree for SCBs
|
|
//
|
|
SIS_TREE ScbTree[1];
|
|
KSPIN_LOCK ScbSpinLock[1];
|
|
|
|
//
|
|
// Doubly linked list of all scb structures for this volume.
|
|
//
|
|
LIST_ENTRY ScbList;
|
|
|
|
//
|
|
// State for the LINK_INDEX value generator for this volume. Keep track of how many are allocated (ie., we've
|
|
// recorded on the disk that they can't be used) and how many are actually used now. Must hold the
|
|
// IndexSpinLock to access these variables.
|
|
//
|
|
LINK_INDEX MaxAllocatedIndex;
|
|
LINK_INDEX MaxUsedIndex;
|
|
KSPIN_LOCK IndexSpinLock[1];
|
|
|
|
//
|
|
// Control for the index allocator. If there are no unused, allocated indices, a thread sets the
|
|
// IndexAllocationInProgress flag, clears the event, queues up the allocator and blocks
|
|
// on the IndexEvent (a Notification event). Any subequent threads just block on the event.
|
|
// The allocator gets new indices, updates the variable and sets the event. When the
|
|
// waiting threads wake up, they just retry the allocation.
|
|
//
|
|
BOOLEAN IndexAllocationInProgress;
|
|
KEVENT IndexEvent[1];
|
|
|
|
//
|
|
// A handle (in the PsInitialSystemProcess context) to the index file. Only accessed by the index allocator.
|
|
//
|
|
HANDLE IndexHandle;
|
|
HANDLE IndexFileEventHandle;
|
|
PKEVENT IndexFileEvent;
|
|
|
|
//
|
|
// The status that came back from the attempt to allocate new indices.
|
|
//
|
|
NTSTATUS IndexStatus;
|
|
|
|
#if ENABLE_LOGGING
|
|
//
|
|
// Stuff for the SIS log file. A handle in the PsInitialSystemProcessContext as well as an object
|
|
// that we reference to the file for use in other contexts.
|
|
//
|
|
HANDLE LogFileHandle;
|
|
PFILE_OBJECT LogFileObject;
|
|
KMUTANT LogFileMutant[1];
|
|
LARGE_INTEGER LogWriteOffset;
|
|
LARGE_INTEGER PreviousLogWriteOffset; // The logwriteoffset from when the trimmer last ran.
|
|
#endif // ENABLE_LOGGING
|
|
|
|
//
|
|
// Phase 2 initialization takes place after the mount has completed when we can do full-fledged
|
|
// ZwCreateFile calls and whatnot. This flag indicates whether it's happened. Once it's set,
|
|
// it can never be cleared.
|
|
//
|
|
BOOLEAN Phase2InitializationComplete;
|
|
KEVENT Phase2DoneEvent[1];
|
|
|
|
//
|
|
// The thread that's handing phase2 initialization.
|
|
//
|
|
HANDLE Phase2ThreadId;
|
|
|
|
//
|
|
// The number of backpointer entries per sector (sectorSize / sizeof(SIS_BACKPOINTER).
|
|
//
|
|
ULONG BackpointerEntriesPerSector;
|
|
|
|
//
|
|
// Taken when a link index collision is being repaired.
|
|
//
|
|
KMUTEX CollisionMutex[1];
|
|
|
|
//
|
|
// A resource that's used to mediate access to the GrovelerFileObject. This needs to
|
|
// be taken shared to assure that the GrovelerFileObject isn't messed with. When the volume
|
|
// is dismounted, the dismount code takes it exclusively in order to blow away the GrovelerFileObject.
|
|
//
|
|
ERESOURCE GrovelerFileObjectResource[1];
|
|
|
|
} DEVICE_EXTENSION;
|
|
|
|
//
|
|
// The spin lock used to maintain the list of device extensions.
|
|
//
|
|
|
|
extern KSPIN_LOCK DeviceExtensionListLock;
|
|
extern LIST_ENTRY DeviceExtensionListHead;
|
|
|
|
//
|
|
// Global stuff for the log trimmer. This uses a timer to fire a DPC, which in turn queues up the real
|
|
// log trimmer on a worker thread. The trimmer then reschedules the DPC when it's done.
|
|
//
|
|
extern KTIMER LogTrimTimer[1];
|
|
extern KDPC LogTrimDpc[1];
|
|
extern WORK_QUEUE_ITEM LogTrimWorkItem[1];
|
|
#define LOG_TRIM_TIMER_INTERVAL -10 * 1000 * 1000 * 60 // 1 minute trim interval
|
|
|
|
//
|
|
// Mutex for interlocking device attachments
|
|
//
|
|
|
|
extern FAST_MUTEX SisDeviceAttachLock;
|
|
|
|
//
|
|
// Offsets used for the SCB ranges
|
|
//
|
|
#define FAULTED_OFFSET 1000
|
|
#define WRITTEN_OFFSET 2000
|
|
|
|
//
|
|
// A macro to get SIS out of the driver stack. This should be called from
|
|
// a dispatch routine when we don't want to hear about this particular Irp
|
|
// again. It is morally equivalent to calling SiPassThrough, only without
|
|
// the procedure call overhead. Note that the return in this macro returns
|
|
// from the caller's function, not just from the "macro function."
|
|
//
|
|
#define SipDirectPassThroughAndReturn(DeviceObject,Irp) \
|
|
{ \
|
|
(Irp)->CurrentLocation++; \
|
|
(Irp)->Tail.Overlay.CurrentStackLocation++; \
|
|
\
|
|
return IoCallDriver( \
|
|
((PDEVICE_EXTENSION)((DeviceObject)->DeviceExtension))->AttachedToDeviceObject, \
|
|
(Irp)); \
|
|
}
|
|
|
|
//
|
|
// This function assures that phase 2 initialization is complete for a volume. It might
|
|
// block, but only during initialization.
|
|
//
|
|
#define SipCheckPhase2(deviceExtension) \
|
|
((deviceExtension)->Phase2InitializationComplete ? \
|
|
TRUE : SipHandlePhase2((deviceExtension)))
|
|
|
|
//
|
|
// Test to see if this file object is our primary device object rather than
|
|
// an actual filesystem device. If so, then complete the irp and return from the
|
|
// calling function.
|
|
//
|
|
|
|
#define SipHandleControlDeviceObject(DeviceObject,Irp) \
|
|
{ \
|
|
if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) { \
|
|
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; \
|
|
Irp->IoStatus.Information = 0; \
|
|
\
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT); \
|
|
\
|
|
return STATUS_INVALID_DEVICE_REQUEST; \
|
|
} \
|
|
}
|
|
|
|
//
|
|
// A debugging routine to determine if a SCB is held exclusively. Does NOT assert
|
|
// that it's held by the current thread, just that it's held by someone
|
|
//
|
|
#if DBG && defined (_X86_)
|
|
#define SipAssertScbHeld(scb) \
|
|
{ \
|
|
ASSERT((scb)->MutexHolder != 0); \
|
|
}
|
|
#else // DBG
|
|
#define SipAssertScbHeld(scb)
|
|
#endif // DBG
|
|
|
|
//
|
|
// A debugging routine to determine if a SCB is held exclusively by a particular thread.
|
|
//
|
|
#if DBG && defined (_X86_)
|
|
#define SipAssertScbHeldByThread(scb,thread) \
|
|
{ \
|
|
ASSERT((scb)->MutexHolder == (thread)); \
|
|
}
|
|
#else // DBG
|
|
#define SipAssertScbHeldByThread(scb,thread)
|
|
#endif // DBG
|
|
|
|
//
|
|
// Acquire a filter context exclusively
|
|
//
|
|
#if DBG
|
|
#define SipAcquireFc(fc) \
|
|
{ \
|
|
ExAcquireFastMutex((fc)->FastMutex); \
|
|
(fc)->MutexHolder = ExGetCurrentResourceThread(); \
|
|
}
|
|
#else DBG
|
|
#define SipAcquireFc(fc) \
|
|
{ \
|
|
ExAcquireFastMutex((fc)->FastMutex); \
|
|
}
|
|
#endif // DBG
|
|
|
|
//
|
|
// Release a filter context
|
|
//
|
|
#if DBG
|
|
#define SipReleaseFc(fc) \
|
|
{ \
|
|
(fc)->MutexHolder = 0; \
|
|
ExReleaseFastMutex((fc)->FastMutex); \
|
|
}
|
|
#else // DBG
|
|
#define SipReleaseFc(fc) \
|
|
{ \
|
|
ExReleaseFastMutex((fc)->FastMutex); \
|
|
}
|
|
#endif // DBG
|
|
|
|
//
|
|
// Acquire an SCB exclusively
|
|
//
|
|
#if DBG
|
|
#define SipAcquireScb(scb) \
|
|
{ \
|
|
ExAcquireFastMutex((scb)->FastMutex); \
|
|
(scb)->MutexHolder = ExGetCurrentResourceThread(); \
|
|
}
|
|
#else DBG
|
|
#define SipAcquireScb(scb) \
|
|
{ \
|
|
ExAcquireFastMutex((scb)->FastMutex); \
|
|
}
|
|
#endif // DBG
|
|
|
|
//
|
|
// Release a SCB
|
|
//
|
|
#if DBG
|
|
#define SipReleaseScb(scb) \
|
|
{ \
|
|
(scb)->MutexHolder = 0; \
|
|
ExReleaseFastMutex((scb)->FastMutex); \
|
|
}
|
|
#else // DBG
|
|
#define SipReleaseScb(scb) \
|
|
{ \
|
|
ExReleaseFastMutex((scb)->FastMutex); \
|
|
}
|
|
#endif // DBG
|
|
|
|
//
|
|
// A header for any log entry in the SIS log file.
|
|
//
|
|
typedef struct _SIS_LOG_HEADER {
|
|
//
|
|
// A magic number. This needs to be first for the log reading code.
|
|
//
|
|
ULONG Magic;
|
|
|
|
//
|
|
// The type of the log record (ie., copy-on-write, COW completed, etc.)
|
|
//
|
|
USHORT Type;
|
|
|
|
//
|
|
// The size of the log record, including the size of the header record itself.
|
|
//
|
|
USHORT Size;
|
|
|
|
//
|
|
// An SIS index unique to this log record. This is here to help insure log
|
|
// consistency. First, all log records must be in ascending index order.
|
|
// Second, all log records will look slightly different because they
|
|
// will have different indices, and so will have different checksums, making
|
|
// stale log records more likely to be detected.
|
|
//
|
|
LINK_INDEX Index;
|
|
|
|
//
|
|
// A checksum of the log record, including the header. When the checksum is
|
|
// computed, the checksum field is set to zero.
|
|
//
|
|
LARGE_INTEGER Checksum;
|
|
|
|
} SIS_LOG_HEADER, *PSIS_LOG_HEADER;
|
|
|
|
#define SIS_LOG_HEADER_MAGIC 0xfeedf1eb
|
|
|
|
//
|
|
// The various types of log records
|
|
//
|
|
#define SIS_LOG_TYPE_TEST 1
|
|
#define SIS_LOG_TYPE_REFCOUNT_UPDATE 2
|
|
|
|
//
|
|
// Possible values for UpdateType in SipPrepareRefcountChange and in the
|
|
// SIS_LOG_REFCOUNT_UPDATE log record.
|
|
//
|
|
#define SIS_REFCOUNT_UPDATE_LINK_DELETED 2
|
|
#define SIS_REFCOUNT_UPDATE_LINK_CREATED 3
|
|
#define SIS_REFCOUNT_UPDATE_LINK_OVERWRITTEN 4
|
|
|
|
//
|
|
// A common store file reference count update, either because of a new copy or
|
|
// a deletion. copies-on-write are handled with different log records.
|
|
//
|
|
typedef struct _SIS_LOG_REFCOUNT_UPDATE {
|
|
//
|
|
// What type of update is this (create, delete or overwrite?)
|
|
//
|
|
ULONG UpdateType;
|
|
|
|
//
|
|
// If this is a delete, is the link file going away, or has it been
|
|
// overwritten/final copied?
|
|
//
|
|
BOOLEAN LinkFileBeingDeleted;
|
|
|
|
//
|
|
// The NTFS file Id of the link file.
|
|
//
|
|
LARGE_INTEGER LinkFileNtfsId;
|
|
|
|
//
|
|
// The link and common store indices for this link
|
|
//
|
|
LINK_INDEX LinkIndex;
|
|
CSID CSid;
|
|
} SIS_LOG_REFCOUNT_UPDATE, *PSIS_LOG_REFCOUNT_UPDATE;
|
|
|
|
//
|
|
// Enums for the code that keeps track of whether ranges of a file
|
|
// are written, faulted or untouched.
|
|
//
|
|
typedef enum _SIS_RANGE_DIRTY_STATE {
|
|
Clean,
|
|
Mixed,
|
|
Dirty}
|
|
SIS_RANGE_DIRTY_STATE, *PSIS_RANGE_DIRTY_STATE;
|
|
|
|
typedef enum _SIS_RANGE_STATE {
|
|
Untouched,
|
|
Faulted,
|
|
Written}
|
|
SIS_RANGE_STATE, *PSIS_RANGE_STATE;
|
|
|
|
|
|
extern LIST_ENTRY CopyList[];
|
|
extern KSPIN_LOCK CopyListLock[];
|
|
extern KSEMAPHORE CopySemaphore[];
|
|
|
|
typedef struct _SCB_KEY {
|
|
LINK_INDEX Index;
|
|
} SCB_KEY, *PSCB_KEY;
|
|
|
|
typedef struct _PER_LINK_KEY {
|
|
LINK_INDEX Index;
|
|
} PER_LINK_KEY, *PPER_LINK_KEY;
|
|
|
|
typedef struct _CS_FILE_KEY {
|
|
CSID CSid;
|
|
} CS_FILE_KEY, *PCS_FILE_KEY;
|
|
|
|
//
|
|
// Following macro is used to initialize UNICODE strings, stolen from ntfsstru.h
|
|
//
|
|
|
|
#ifndef CONSTANT_UNICODE_STRING
|
|
#define CONSTANT_UNICODE_STRING(s) { sizeof( s ) - sizeof( WCHAR ), sizeof( s ), s }
|
|
#endif
|
|
|
|
extern const UNICODE_STRING NtfsDataString;
|
|
|
|
//
|
|
// Miscellaneous support macros (stolen from private\ntos\cntfs\ntfsproc.h).
|
|
//
|
|
// ULONG_PTR
|
|
// WordAlign (
|
|
// IN ULONG_PTR Pointer
|
|
// );
|
|
//
|
|
// ULONG_PTR
|
|
// LongAlign (
|
|
// IN ULONG_PTR Pointer
|
|
// );
|
|
//
|
|
// ULONG_PTR
|
|
// QuadAlign (
|
|
// IN ULONG_PTR Pointer
|
|
// );
|
|
//
|
|
// UCHAR
|
|
// CopyUchar1 (
|
|
// IN PUCHAR Destination,
|
|
// IN PUCHAR Source
|
|
// );
|
|
//
|
|
// UCHAR
|
|
// CopyUchar2 (
|
|
// IN PUSHORT Destination,
|
|
// IN PUCHAR Source
|
|
// );
|
|
//
|
|
// UCHAR
|
|
// CopyUchar4 (
|
|
// IN PULONG Destination,
|
|
// IN PUCHAR Source
|
|
// );
|
|
//
|
|
// PVOID
|
|
// Add2Ptr (
|
|
// IN PVOID Pointer,
|
|
// IN ULONG Increment
|
|
// );
|
|
//
|
|
// ULONG
|
|
// PtrOffset (
|
|
// IN PVOID BasePtr,
|
|
// IN PVOID OffsetPtr
|
|
// );
|
|
//
|
|
|
|
#define WordAlign(P) ( \
|
|
((((ULONG_PTR)(P)) + 1) & (-2)) \
|
|
)
|
|
|
|
#define LongAlign(P) ( \
|
|
((((ULONG_PTR)(P)) + 3) & (-4)) \
|
|
)
|
|
|
|
#define QuadAlign(P) ( \
|
|
((((ULONG_PTR)(P)) + 7) & (-8)) \
|
|
)
|
|
|
|
#define IsWordAligned(P) ((ULONG_PTR)(P) == WordAlign( (P) ))
|
|
|
|
#define IsLongAligned(P) ((ULONG_PTR)(P) == LongAlign( (P) ))
|
|
|
|
#define IsQuadAligned(P) ((ULONG_PTR)(P) == QuadAlign( (P) ))
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Functions Prototypes
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Routines in SIINIT.C
|
|
//
|
|
|
|
VOID
|
|
SipCleanupDeviceExtension(
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
NTSTATUS
|
|
SipMountCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
);
|
|
|
|
NTSTATUS
|
|
SipLoadFsCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
);
|
|
|
|
VOID
|
|
SipFsNotification(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN BOOLEAN FsActive
|
|
);
|
|
|
|
NTSTATUS
|
|
SipInitializeDeviceExtension(
|
|
IN PDEVICE_OBJECT deviceObject
|
|
);
|
|
|
|
VOID
|
|
SipUninitializeDeviceExtension(
|
|
IN PDEVICE_OBJECT deviceObject
|
|
);
|
|
|
|
VOID
|
|
SipGetBaseDeviceObjectName(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PUNICODE_STRING Name
|
|
);
|
|
|
|
VOID
|
|
SipGetObjectName(
|
|
IN PVOID Object,
|
|
IN OUT PUNICODE_STRING Name
|
|
);
|
|
|
|
#if DBG
|
|
VOID
|
|
SipCacheDeviceName (
|
|
IN PDEVICE_OBJECT OurDeviceObject
|
|
);
|
|
#endif
|
|
//
|
|
// ROutines in SIFASTIO.C
|
|
//
|
|
|
|
BOOLEAN
|
|
SiFastIoCheckIfPossible(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Wait,
|
|
IN ULONG LockKey,
|
|
IN BOOLEAN CheckForReadOperation,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoRead(
|
|
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,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoWrite(
|
|
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,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoQueryBasicInfo(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_BASIC_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoQueryStandardInfo(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_STANDARD_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoLock(
|
|
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,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoUnlockSingle(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PLARGE_INTEGER Length,
|
|
PEPROCESS ProcessId,
|
|
ULONG Key,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoUnlockAll(
|
|
IN PFILE_OBJECT FileObject,
|
|
PEPROCESS ProcessId,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoUnlockAllByKey(
|
|
IN PFILE_OBJECT FileObject,
|
|
PVOID ProcessId,
|
|
ULONG Key,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoDeviceControl(
|
|
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,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
VOID
|
|
SiFastIoDetachDevice(
|
|
IN PDEVICE_OBJECT SourceDevice,
|
|
IN PDEVICE_OBJECT TargetDevice
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoQueryNetworkOpenInfo(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN BOOLEAN Wait,
|
|
OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoMdlRead(
|
|
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
|
|
SiFastIoMdlReadComplete(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoPrepareMdlWrite(
|
|
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
|
|
SiFastIoMdlWriteComplete(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoReadCompressed(
|
|
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 PCOMPRESSED_DATA_INFO CompressedDataInfo,
|
|
IN ULONG CompressedDataInfoLength,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoWriteCompressed(
|
|
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 PCOMPRESSED_DATA_INFO CompressedDataInfo,
|
|
IN ULONG CompressedDataInfoLength,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoMdlReadCompleteCompressed(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoMdlWriteCompleteCompressed(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PMDL MdlChain,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
BOOLEAN
|
|
SiFastIoQueryOpen(
|
|
IN PIRP Irp,
|
|
OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
|
|
|
|
//
|
|
// Declarations for various SIS internal/external functions.
|
|
//
|
|
|
|
|
|
BOOLEAN
|
|
SipAttachedToDevice (
|
|
IN PDEVICE_OBJECT DeviceObject);
|
|
|
|
NTSTATUS
|
|
SipAttachToMountedDevice(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PDEVICE_OBJECT NewDeviceObject,
|
|
IN PDEVICE_OBJECT RealDeviceObject);
|
|
|
|
|
|
|
|
VOID
|
|
SipInitializeTree (
|
|
IN PSIS_TREE Tree,
|
|
IN PSIS_TREE_COMPARE_ROUTINE CompareRoutine);
|
|
|
|
|
|
PVOID
|
|
SipInsertElementTree (
|
|
IN PSIS_TREE Tree,
|
|
IN PVOID Node,
|
|
IN PVOID Key);
|
|
|
|
|
|
VOID
|
|
SipDeleteElementTree (
|
|
IN PSIS_TREE Tree,
|
|
IN PVOID Node);
|
|
|
|
PVOID
|
|
SipLookupElementTree (
|
|
IN PSIS_TREE Tree,
|
|
IN PVOID Key);
|
|
|
|
LONG
|
|
SipScbTreeCompare (
|
|
IN PVOID Key,
|
|
IN PVOID Node);
|
|
|
|
LONG
|
|
SipPerLinkTreeCompare (
|
|
IN PVOID Key,
|
|
IN PVOID Node);
|
|
|
|
LONG
|
|
SipCSFileTreeCompare (
|
|
IN PVOID Key,
|
|
IN PVOID Node);
|
|
|
|
VOID
|
|
SipReferenceScb(
|
|
IN PSIS_SCB scb,
|
|
IN SCB_REFERENCE_TYPE referenceType);
|
|
|
|
VOID
|
|
SipDereferenceScb(
|
|
IN PSIS_SCB scb,
|
|
IN SCB_REFERENCE_TYPE referenceType);
|
|
|
|
#if DBG
|
|
VOID
|
|
SipTransferScbReferenceType(
|
|
IN PSIS_SCB scb,
|
|
IN SCB_REFERENCE_TYPE oldReferenceType,
|
|
IN SCB_REFERENCE_TYPE newReferenceType);
|
|
#else // DBG
|
|
#define SipTransferScbReferenceType(scb,oldReferenceType,newReferenceType) // We don't track reference types in free builds
|
|
#endif // DBG
|
|
|
|
PSIS_SCB
|
|
SipLookupScb(
|
|
IN PLINK_INDEX PerLinkIndex,
|
|
IN PCSID CSid,
|
|
IN PLARGE_INTEGER LinkFileNtfsId,
|
|
IN PLARGE_INTEGER CSFileNtfsId OPTIONAL,
|
|
IN PUNICODE_STRING StreamName,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PETHREAD RequestingThread OPTIONAL,
|
|
OUT PBOOLEAN FinalCopyInProgress,
|
|
OUT PBOOLEAN LinkIndexCollision);
|
|
|
|
PSIS_PER_LINK
|
|
SipLookupPerLink(
|
|
IN PLINK_INDEX PerLinkIndex,
|
|
IN PCSID CSid,
|
|
IN PLARGE_INTEGER LinkFileNtfsId,
|
|
IN PLARGE_INTEGER CSFileNtfsId OPTIONAL,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PETHREAD RequestingThread OPTIONAL,
|
|
OUT PBOOLEAN FinalCopyInProgress);
|
|
|
|
VOID
|
|
SipReferencePerLink(
|
|
IN PSIS_PER_LINK PerLink);
|
|
|
|
VOID
|
|
SipDereferencePerLink(
|
|
IN PSIS_PER_LINK PerLink);
|
|
|
|
PSIS_SCB
|
|
SipEnumerateScbList(
|
|
PDEVICE_EXTENSION deviceExtension,
|
|
PSIS_SCB prevScb);
|
|
|
|
VOID
|
|
SipUpdateLinkIndex(
|
|
PSIS_SCB Scb,
|
|
PLINK_INDEX LinkIndex);
|
|
|
|
PSIS_CS_FILE
|
|
SipLookupCSFile(
|
|
IN PCSID CSid,
|
|
IN PLARGE_INTEGER CSFileNtfsId OPTIONAL,
|
|
IN PDEVICE_OBJECT DeviceObject);
|
|
|
|
VOID
|
|
SipReferenceCSFile(
|
|
IN PSIS_CS_FILE CSFile);
|
|
|
|
VOID
|
|
SipDereferenceCSFile(
|
|
IN PSIS_CS_FILE CsFile);
|
|
|
|
NTSTATUS
|
|
SiPrePostIrp(
|
|
IN OUT PIRP Irp);
|
|
|
|
NTSTATUS
|
|
SipLockUserBuffer(
|
|
IN OUT PIRP Irp,
|
|
IN LOCK_OPERATION Operation,
|
|
IN ULONG BufferLength);
|
|
|
|
NTSTATUS
|
|
SipPostRequest(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
IN ULONG Flags);
|
|
|
|
VOID
|
|
SiCopyThreadStart(
|
|
IN PVOID parameter);
|
|
|
|
NTSTATUS
|
|
SipPrepareCSRefcountChange(
|
|
IN PSIS_CS_FILE CSFile,
|
|
IN OUT PLINK_INDEX LinkIndex,
|
|
IN PLARGE_INTEGER LinkFileNtfsId,
|
|
IN ULONG UpdateType);
|
|
|
|
NTSTATUS
|
|
SipCompleteCSRefcountChangeForThread(
|
|
IN OUT PSIS_PER_LINK PerLink,
|
|
IN PLINK_INDEX LinkIndex,
|
|
IN PSIS_CS_FILE CSFile,
|
|
IN BOOLEAN Success,
|
|
IN BOOLEAN Increment,
|
|
IN ERESOURCE_THREAD thread);
|
|
|
|
NTSTATUS
|
|
SipCompleteCSRefcountChange(
|
|
IN OUT PSIS_PER_LINK PerLink,
|
|
IN PLINK_INDEX LinkIndex,
|
|
IN PSIS_CS_FILE CSFile,
|
|
IN BOOLEAN Success,
|
|
IN BOOLEAN Increment);
|
|
|
|
NTSTATUS
|
|
SipDeleteCSFile(
|
|
PSIS_CS_FILE CSFile);
|
|
|
|
NTSTATUS
|
|
SipAllocateIndex(
|
|
IN PDEVICE_EXTENSION DeviceExtension,
|
|
OUT PLINK_INDEX Index);
|
|
|
|
NTSTATUS
|
|
SipGetMaxUsedIndex(
|
|
IN PDEVICE_EXTENSION DeviceExtension,
|
|
OUT PLINK_INDEX Index);
|
|
|
|
NTSTATUS
|
|
SipIndexToFileName(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PCSID CSid,
|
|
IN ULONG appendBytes,
|
|
IN BOOLEAN mayAllocate,
|
|
OUT PUNICODE_STRING fileName);
|
|
|
|
BOOLEAN
|
|
SipFileNameToIndex(
|
|
IN PUNICODE_STRING fileName,
|
|
OUT PCSID CSid);
|
|
|
|
BOOLEAN
|
|
SipIndicesFromReparseBuffer(
|
|
IN PREPARSE_DATA_BUFFER reparseBuffer,
|
|
OUT PCSID CSid,
|
|
OUT PLINK_INDEX LinkIndex,
|
|
OUT PLARGE_INTEGER CSFileNtfsId,
|
|
OUT PLARGE_INTEGER LinkFileNtfsId,
|
|
OUT PLONGLONG CSFileChecksum OPTIONAL,
|
|
OUT PBOOLEAN EligibleForPartialFinalCopy OPTIONAL,
|
|
OUT PBOOLEAN ReparseBufferCorrupt OPTIONAL);
|
|
|
|
BOOLEAN
|
|
SipIndicesIntoReparseBuffer(
|
|
OUT PREPARSE_DATA_BUFFER reparseBuffer,
|
|
IN PCSID CSid,
|
|
IN PLINK_INDEX LinkIndex,
|
|
IN PLARGE_INTEGER CSFileNtfsId,
|
|
IN PLARGE_INTEGER LinkFileNtfsId,
|
|
IN PLONGLONG CSFileChecksum,
|
|
IN BOOLEAN EligibleForPartialFinalCopy);
|
|
|
|
NTSTATUS
|
|
SipCompleteCopy(
|
|
IN PSIS_SCB scb,
|
|
IN BOOLEAN fromCleanup);
|
|
|
|
NTSTATUS
|
|
SipCloseHandles(
|
|
IN HANDLE handle1,
|
|
IN HANDLE handle2 OPTIONAL,
|
|
IN OUT PERESOURCE resourceToRelease OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SiPassThrough(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SiCreate(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SiOtherCreates (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SiClose(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SiCleanup(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SiRead(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SiWrite(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SiSetInfo(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SiQueryInfo(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SiFsControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SiLockControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
SiOplockCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
);
|
|
|
|
VOID
|
|
SipOpenLinkFile(
|
|
IN PVOID Parameter
|
|
);
|
|
|
|
VOID
|
|
SipChangeCSRefcountWork(
|
|
IN PVOID Parameter
|
|
);
|
|
|
|
BOOLEAN
|
|
SiAcquireForLazyWrite(
|
|
IN PVOID Context,
|
|
IN BOOLEAN Wait
|
|
);
|
|
|
|
VOID
|
|
SiReleaseFromLazyWrite(
|
|
IN PVOID Context
|
|
);
|
|
|
|
BOOLEAN
|
|
SiAcquireForReadAhead(
|
|
IN PVOID Context,
|
|
IN BOOLEAN Wait
|
|
);
|
|
|
|
VOID
|
|
SiReleaseFromReadAhead(
|
|
IN PVOID Context
|
|
);
|
|
|
|
NTSTATUS
|
|
SipOpenBackpointerStream(
|
|
IN PSIS_CS_FILE csFile,
|
|
IN ULONG CreateDisposition
|
|
);
|
|
|
|
NTSTATUS
|
|
SipOpenCSFileWork(
|
|
IN PSIS_CS_FILE CSFile,
|
|
IN BOOLEAN openByName,
|
|
IN BOOLEAN volCheck,
|
|
IN BOOLEAN openForDelete,
|
|
OUT PHANDLE openedFileHandle OPTIONAL
|
|
);
|
|
|
|
VOID
|
|
SipOpenCSFile(
|
|
IN OUT PSI_OPEN_CS_FILE openRequest
|
|
);
|
|
|
|
VOID
|
|
SiThreadCreateNotifyRoutine(
|
|
IN HANDLE ProcessId,
|
|
IN HANDLE ThreadId,
|
|
IN BOOLEAN Create
|
|
);
|
|
|
|
VOID
|
|
SipCloseHandlesWork(
|
|
IN PVOID parameter
|
|
);
|
|
|
|
NTSTATUS
|
|
SipQueryInformationFile(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONG InformationClass,
|
|
IN ULONG Length,
|
|
OUT PVOID Information,
|
|
OUT PULONG ReturnedLength OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SipQueryInformationFileUsingGenericDevice(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONG InformationClass,
|
|
IN ULONG Length,
|
|
OUT PVOID Information,
|
|
OUT PULONG ReturnedLength OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SipSetInformationFile(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN FILE_INFORMATION_CLASS FileInformationClass,
|
|
IN ULONG Length,
|
|
IN PVOID FileInformation
|
|
);
|
|
|
|
NTSTATUS
|
|
SipSetInformationFileUsingGenericDevice(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN FILE_INFORMATION_CLASS FileInformationClass,
|
|
IN ULONG Length,
|
|
IN PVOID FileInformation
|
|
);
|
|
|
|
NTSTATUS
|
|
SipCommonCreate(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN BOOLEAN Wait
|
|
);
|
|
|
|
NTSTATUS
|
|
SipCommonRead(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN BOOLEAN Wait
|
|
);
|
|
|
|
NTSTATUS
|
|
SipCommonSetInfo(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN BOOLEAN Wait
|
|
);
|
|
|
|
NTSTATUS
|
|
SipCommonQueryInfo(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN BOOLEAN Wait
|
|
);
|
|
|
|
NTSTATUS
|
|
SipCommonLockControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN BOOLEAN Wait
|
|
);
|
|
|
|
NTSTATUS
|
|
SipCommonCleanup(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN BOOLEAN Wait
|
|
);
|
|
|
|
NTSTATUS
|
|
SipFsCopyFile(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp);
|
|
|
|
NTSTATUS
|
|
SipInitialCopy(
|
|
PSIS_PER_FILE_OBJECT perFO);
|
|
|
|
NTSTATUS
|
|
SipBltRange(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN HANDLE sourceHandle,
|
|
IN OUT HANDLE dstHandle,
|
|
IN LONGLONG startingOffset,
|
|
IN LONGLONG length,
|
|
IN HANDLE copyEventHandle,
|
|
IN PKEVENT copyEvent,
|
|
IN PKEVENT oplockEvent,
|
|
OUT PLONGLONG checksum);
|
|
|
|
NTSTATUS
|
|
SipBltRange(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN HANDLE sourceHandle,
|
|
IN OUT HANDLE dstHandle,
|
|
IN LONGLONG startingOffset,
|
|
IN LONGLONG length,
|
|
IN HANDLE copyEventHandle,
|
|
IN PKEVENT copyEvent,
|
|
IN PKEVENT oplockEvent,
|
|
OUT PLONGLONG checksum);
|
|
|
|
NTSTATUS
|
|
SipBltRangeByObject(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PFILE_OBJECT srcFileObject,
|
|
IN OUT HANDLE dstHandle,
|
|
IN LONGLONG startingOffset,
|
|
IN LONGLONG length,
|
|
IN HANDLE copyEventHandle,
|
|
IN PKEVENT copyEvent,
|
|
IN PKEVENT oplockEvent,
|
|
OUT PLONGLONG checksum);
|
|
|
|
NTSTATUS
|
|
SipComputeCSChecksum(
|
|
IN PSIS_CS_FILE csFile,
|
|
IN OUT PLONGLONG csFileChecksum,
|
|
HANDLE eventHandle,
|
|
PKEVENT event);
|
|
|
|
NTSTATUS
|
|
SipCompleteCopyWork(
|
|
IN PSIS_SCB scb,
|
|
IN HANDLE eventHandle,
|
|
IN PKEVENT event,
|
|
IN BOOLEAN fromCleanup);
|
|
|
|
NTSTATUS
|
|
SipMakeLogEntry(
|
|
IN OUT PDEVICE_EXTENSION deviceExtension,
|
|
IN USHORT type,
|
|
IN USHORT size,
|
|
IN PVOID record);
|
|
|
|
#if ENABLE_LOGGING
|
|
VOID
|
|
SipAcquireLog(
|
|
IN OUT PDEVICE_EXTENSION deviceExtension);
|
|
|
|
VOID
|
|
SipReleaseLog(
|
|
IN OUT PDEVICE_EXTENSION deviceExtension);
|
|
#endif // ENABLE_LOGGING
|
|
|
|
VOID
|
|
SipComputeChecksum(
|
|
IN PVOID buffer,
|
|
IN ULONG size,
|
|
IN OUT PLONGLONG checksum);
|
|
|
|
NTSTATUS
|
|
SipOpenLogFile(
|
|
IN OUT PDEVICE_EXTENSION deviceExtension);
|
|
|
|
VOID
|
|
SipDrainLogFile(
|
|
PDEVICE_EXTENSION deviceExtension);
|
|
|
|
BOOLEAN
|
|
SipHandlePhase2(
|
|
PDEVICE_EXTENSION deviceExtension);
|
|
|
|
VOID
|
|
SipClearLogFile(
|
|
PDEVICE_EXTENSION deviceExtension);
|
|
|
|
NTSTATUS
|
|
SiCheckOplock (
|
|
IN POPLOCK Oplock,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp);
|
|
|
|
NTSTATUS
|
|
SiCheckOplockWithWait (
|
|
IN POPLOCK Oplock,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp);
|
|
|
|
VOID
|
|
SipProcessCowLogRecord(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PVOID logRecord,
|
|
IN OUT PVOID *cowReplayPointer);
|
|
|
|
VOID
|
|
SipProcessCowDoneLogRecord(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PVOID logRecord,
|
|
IN OUT PVOID *cowReplayPointer);
|
|
|
|
NTSTATUS
|
|
SipFinalCopy(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PLARGE_INTEGER linkFileNtfsId,
|
|
IN OUT PSIS_SCB scb,
|
|
IN HANDLE copyEventHandle,
|
|
IN PKEVENT event);
|
|
|
|
VOID
|
|
SipCowAllLogRecordsSent(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN OUT PVOID *cowReplayPointer);
|
|
|
|
NTSTATUS
|
|
SipCreateEvent(
|
|
IN EVENT_TYPE eventType,
|
|
OUT PHANDLE eventHandle,
|
|
OUT PKEVENT *event);
|
|
|
|
VOID
|
|
SipMarkPoint(
|
|
IN PCHAR pszFile,
|
|
IN ULONG nLine
|
|
);
|
|
|
|
VOID
|
|
SipMarkPointUlong(
|
|
IN PCHAR pszFile,
|
|
IN ULONG nLine,
|
|
IN ULONG_PTR value
|
|
);
|
|
|
|
NTSTATUS
|
|
SipLinkFiles(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
SipCreateCSFile(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
OUT PCSID CSid,
|
|
IN HANDLE SrcHandle,
|
|
OUT PLARGE_INTEGER NtfsId,
|
|
IN PKEVENT oplockEvent OPTIONAL,
|
|
OUT PLONGLONG CSFileChecksum
|
|
);
|
|
|
|
VOID
|
|
SipCreateCSFileWork(
|
|
PVOID parameter
|
|
);
|
|
|
|
VOID
|
|
SipAddRangeToFaultedList(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PSIS_SCB scb,
|
|
IN PLARGE_INTEGER offset,
|
|
IN LONGLONG length
|
|
);
|
|
|
|
NTSTATUS
|
|
SipAddRangeToWrittenList(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PSIS_SCB scb,
|
|
IN PLARGE_INTEGER offset,
|
|
IN LONGLONG length
|
|
);
|
|
|
|
SIS_RANGE_DIRTY_STATE
|
|
SipGetRangeDirty(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PSIS_SCB scb,
|
|
IN PLARGE_INTEGER offset,
|
|
IN LONGLONG length,
|
|
IN BOOLEAN faultedIsDirty
|
|
);
|
|
|
|
BOOLEAN
|
|
SipGetRangeEntry(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PSIS_SCB scb,
|
|
IN LONGLONG startingOffset,
|
|
OUT PLONGLONG length,
|
|
OUT PSIS_RANGE_STATE state);
|
|
|
|
typedef enum {
|
|
FindAny, // find active or defunct scb
|
|
FindActive // find only active scb
|
|
} SIS_FIND_TYPE;
|
|
|
|
#if DBG
|
|
|
|
#define SipIsFileObjectSIS(fileObject, DeviceObject, findType, perFO, scb) \
|
|
SipIsFileObjectSISInternal(fileObject, DeviceObject, findType, perFO, scb, __FILE__, __LINE__)
|
|
|
|
BOOLEAN
|
|
SipIsFileObjectSISInternal(
|
|
IN PFILE_OBJECT fileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN SIS_FIND_TYPE findType,
|
|
OUT PSIS_PER_FILE_OBJECT *perFO OPTIONAL,
|
|
OUT PSIS_SCB *scbReturn OPTIONAL,
|
|
IN PCHAR fileName,
|
|
IN ULONG fileLine
|
|
);
|
|
|
|
#else // DBG
|
|
|
|
BOOLEAN
|
|
SipIsFileObjectSIS(
|
|
IN PFILE_OBJECT fileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN SIS_FIND_TYPE findType,
|
|
OUT PSIS_PER_FILE_OBJECT *perFO OPTIONAL,
|
|
OUT PSIS_SCB *scbReturn OPTIONAL
|
|
);
|
|
|
|
#endif // DBG
|
|
|
|
NTSTATUS
|
|
SipClaimFileObject(
|
|
IN OUT PFILE_OBJECT fileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PSIS_SCB scb
|
|
);
|
|
|
|
VOID
|
|
SipUnclaimFileObject(
|
|
IN OUT PFILE_OBJECT fileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PSIS_SCB scb
|
|
);
|
|
|
|
PSIS_PER_FILE_OBJECT
|
|
SipAllocatePerFO(
|
|
IN PSIS_FILTER_CONTEXT fc,
|
|
IN PFILE_OBJECT fileObject,
|
|
IN PSIS_SCB scb,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
OUT PBOOLEAN newPerFO OPTIONAL
|
|
);
|
|
|
|
PSIS_PER_FILE_OBJECT
|
|
SipCreatePerFO(
|
|
IN PFILE_OBJECT fileObject,
|
|
IN PSIS_SCB scb,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
VOID
|
|
SipDeallocatePerFO(
|
|
IN OUT PSIS_PER_FILE_OBJECT perFO,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
NTSTATUS
|
|
SipInitializePrimaryScb(
|
|
IN PSIS_SCB primaryScb,
|
|
IN PSIS_SCB defunctScb,
|
|
IN PFILE_OBJECT fileObject,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
NTSTATUS
|
|
SipFsControlFile(
|
|
IN PFILE_OBJECT fileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONG ioControlCode,
|
|
IN PVOID inputBuffer,
|
|
IN ULONG inputBufferLength,
|
|
OUT PVOID outputBuffer,
|
|
IN ULONG outputBufferLength,
|
|
OUT PULONG returnedOutputBufferLength OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SipFsControlFileUsingGenericDevice(
|
|
IN PFILE_OBJECT fileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONG ioControlCode,
|
|
IN PVOID inputBuffer,
|
|
IN ULONG inputBufferLength,
|
|
OUT PVOID outputBuffer,
|
|
IN ULONG outputBufferLength,
|
|
OUT PULONG returnedOutputBufferLength OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SipFlushBuffersFile(
|
|
IN PFILE_OBJECT fileObject,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
NTSTATUS
|
|
SipAcquireUFO(
|
|
IN PSIS_CS_FILE CSFile/*,
|
|
IN BOOLEAN Wait*/);
|
|
|
|
VOID
|
|
SipReleaseUFO(
|
|
IN PSIS_CS_FILE CSFile);
|
|
|
|
NTSTATUS
|
|
SipAcquireCollisionLock(
|
|
IN PDEVICE_EXTENSION DeviceExtension);
|
|
|
|
VOID
|
|
SipReleaseCollisionLock(
|
|
IN PDEVICE_EXTENSION DeviceExtension);
|
|
|
|
VOID
|
|
SipTruncateScb(
|
|
IN OUT PSIS_SCB scb,
|
|
IN LONGLONG newLength);
|
|
|
|
NTSTATUS
|
|
SipOpenFileById(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PLARGE_INTEGER linkFileNtfsId,
|
|
IN ACCESS_MASK desiredAccess,
|
|
IN ULONG shareAccess,
|
|
IN ULONG createOptions,
|
|
OUT PHANDLE openedFileHandle);
|
|
|
|
NTSTATUS
|
|
SipWriteFile(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
OUT PIO_STATUS_BLOCK Iosb,
|
|
IN PVOID Buffer,
|
|
IN ULONG Length,
|
|
IN PLARGE_INTEGER ByteOffset);
|
|
|
|
BOOLEAN
|
|
SipAssureNtfsIdValid(
|
|
IN PSIS_PER_FILE_OBJECT PerFO,
|
|
IN OUT PSIS_PER_LINK PerLink);
|
|
|
|
BOOLEAN
|
|
SipAbort(
|
|
IN PKEVENT event
|
|
);
|
|
|
|
VOID
|
|
SipBeginDeleteModificationOperation(
|
|
IN OUT PSIS_PER_LINK perLink,
|
|
IN BOOLEAN delete);
|
|
|
|
VOID
|
|
SipEndDeleteModificationOperation(
|
|
IN OUT PSIS_PER_LINK perLink,
|
|
IN BOOLEAN delete);
|
|
|
|
NTSTATUS
|
|
SiCompleteLockIrpRoutine(
|
|
IN PVOID Context,
|
|
IN PIRP Irp);
|
|
|
|
PVOID
|
|
SipMapUserBuffer(
|
|
IN OUT PIRP Irp);
|
|
|
|
|
|
NTSTATUS
|
|
SipAssureCSFileOpen(
|
|
IN PSIS_CS_FILE CSFile);
|
|
|
|
NTSTATUS
|
|
SipCheckVolume(
|
|
IN OUT PDEVICE_EXTENSION deviceExtension);
|
|
|
|
NTSTATUS
|
|
SipCheckBackpointer(
|
|
IN PSIS_PER_LINK PerLink,
|
|
IN BOOLEAN Exclusive,
|
|
OUT PBOOLEAN foundMatch OPTIONAL);
|
|
|
|
NTSTATUS
|
|
SipAddBackpointer(
|
|
IN PSIS_CS_FILE CSFile,
|
|
IN PLINK_INDEX LinkFileIndex,
|
|
IN PLARGE_INTEGER LinkFileNtfsId);
|
|
|
|
NTSTATUS
|
|
SipRemoveBackpointer(
|
|
IN PSIS_CS_FILE CSFile,
|
|
IN PLINK_INDEX LinkIndex,
|
|
IN PLARGE_INTEGER LinkFileNtfsId,
|
|
OUT PBOOLEAN ReferencesRemain);
|
|
|
|
NTSTATUS
|
|
SiDeleteAndSetCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context);
|
|
|
|
VOID
|
|
SiTrimLogs(
|
|
IN PVOID parameter);
|
|
|
|
VOID
|
|
SiLogTrimDpcRoutine(
|
|
IN PKDPC dpc,
|
|
IN PVOID context,
|
|
IN PVOID systemArg1,
|
|
IN PVOID systemArg2);
|
|
|
|
VOID
|
|
SipProcessRefcountUpdateLogRecord(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PSIS_LOG_REFCOUNT_UPDATE logRecord);
|
|
|
|
NTSTATUS
|
|
SipAssureMaxIndexFileOpen(
|
|
IN PDEVICE_EXTENSION deviceExtension);
|
|
|
|
VOID
|
|
SipDereferenceObject(
|
|
IN PVOID object);
|
|
|
|
BOOLEAN
|
|
SipAcquireBackpointerResource(
|
|
IN PSIS_CS_FILE CSFile,
|
|
IN BOOLEAN Exclusive,
|
|
IN BOOLEAN Wait);
|
|
|
|
VOID
|
|
SipHandoffBackpointerResource(
|
|
IN PSIS_CS_FILE CSFile);
|
|
|
|
VOID
|
|
SipReleaseBackpointerResource(
|
|
IN PSIS_CS_FILE CSFile);
|
|
|
|
NTSTATUS
|
|
SipPrepareRefcountChangeAndAllocateNewPerLink(
|
|
IN PSIS_CS_FILE CSFile,
|
|
IN PLARGE_INTEGER LinkFileFileId,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
OUT PLINK_INDEX newLinkIndex,
|
|
OUT PSIS_PER_LINK *perLink,
|
|
OUT PBOOLEAN prepared);
|
|
|
|
#if TIMING
|
|
VOID
|
|
SipTimingPoint(
|
|
IN PCHAR file,
|
|
IN ULONG line,
|
|
IN ULONG n);
|
|
|
|
VOID
|
|
SipDumpTimingInfo();
|
|
|
|
VOID
|
|
SipClearTimingInfo();
|
|
|
|
VOID
|
|
SipInitializeTiming();
|
|
#endif // TIMING
|
|
|
|
#if DBG
|
|
VOID
|
|
SipCheckpointLog();
|
|
#endif // DBG
|
|
#endif _SIp_
|