|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
NtfsExp.h
Abstract:
This module defines the exports from NtOfs.SYS for use exclusively by Transactions and Encryption.
********************************* *No other clients are supported.* *********************************
Author:
Mark Zbikowski [MarkZ] 7-Dec-1995 Jeff Havens [JHavens] Brian Andrew [BrianAn] Gary Kimura [GaryKi] Tom Miller [TomM]
Revision History:
--*/
#ifndef _NTFS_
//
// The MFT Segment Reference is an address in the MFT tagged with
// a circularly reused sequence number set at the time that the MFT
// Segment Reference was valid. Note that this format limits the
// size of the Master File Table to 2**48 segments. So, for
// example, with a 1KB segment size the maximum size of the master
// file would be 2**58 bytes, or 2**28 gigabytes.
//
typedef struct _FILE_REFERENCE {
//
// First a 48 bit segment number.
//
ULONG SegmentNumberLowPart; // offset = 0x000
USHORT SegmentNumberHighPart; // offset = 0x004
//
// Now a 16 bit nonzero sequence number. A value of 0 is
// reserved to allow the possibility of a routine accepting
// 0 as a sign that the sequence number check should be
// repressed.
//
USHORT SequenceNumber; // offset = 0x006
} FILE_REFERENCE, *PFILE_REFERENCE; // sizeof = 0x008
#endif
//
// Big picture view of the interaction between extensions and NtOfs:
//
// NtOfs exports a number of interfaces that give abstract access to
// on-disk structures and attempt to hide, as much as possible, the
// implementation details.
//
// V/Q/X are implemented as DLL's that link to NtOfs.Sys. NtOfs can load
// and function in absence of these DLL's.
//
// All communication between user-mode code and V/Q/X occurs via the
// Nt Io API which is routed through NtOfs. Client code will open either
// an NtOfs Volume, Directory, or File and will issue NtIo calls to the
// resultant handle.
//
// NtOfs will create an IrpContext, decode the file object appropriately,
// and call out to entry points in V/Q/X that are registered at load-time.
//
// V/Q/X will perform whatever actions are necessary utilizing NtOfs exports
// and then return from the original call from NtOfs an NTSTATUS code. NtOfs
// will perform the appropriate CompleteIrp calls, posting for STATUS_PENDING,
// etc.
//
// No exceptions can be raised across the NtOfs export or NtOfs import
// interfaces. All user-buffer access and validation will occur in the
// code that uses it. Since user buffers may disappear at any time, any
// client of these buffers must wrap access to the buffers in an exception
// clause.
//
// V/Q/X may perform activities in threads separate from the original
// requestor. For these cases, NtOfs will provide a means where calls separate
// from a user-mode request can be accepted. Typically, this means "cloning"
// an IrpContext.
//
//
// Opaque handle definitions.
//
//
// ISSUE: Most NtOfs internal routines rely on having an IrpContext passed in
// along with FCB and SCB pointers. Rather than exposing FCB and IrpContext
// as separate contexts, should we wrap these up into a separate structure and
// pass it along?
//
typedef struct _FCB *OBJECT_HANDLE; typedef struct _SCB *ATTRIBUTE_HANDLE; typedef struct _SCB *INDEX_HANDLE; typedef struct _READ_CONTEXT *PREAD_CONTEXT; typedef ULONG SECURITY_ID; typedef struct _CI_CALL_BACK CI_CALL_BACK, *PCI_CALL_BACK; typedef struct _VIEW_CALL_BACK VIEW_CALL_BACK, *PVIEW_CALL_BACK; typedef struct _IRP_CONTEXT *PIRP_CONTEXT;
//
// Map Handle. This structure defines a byte range of the file which is mapped
// or pinned, and stores the Bcb returned from the Cache Manager.
//
typedef struct _MAP_HANDLE {
//
// Range being mapped or pinned
//
LONGLONG FileOffset; ULONG Length;
//
// Virtual address corresponding to FileOffset
//
PVOID Buffer;
//
// Bcb pointer returned from Cache Manager
//
PVOID Bcb;
} MAP_HANDLE, *PMAP_HANDLE;
//
// Quick Index Hint. This is stream offset information returned by
// NtOfsFindRecord, and taken as input to NtOfsUpdateRecord, to allow
// quick updates to index records in the event that they have not
// moved. This structure must always have the same size and alignment
// as QUICK_INDEX in ntfsstru.h.
//
typedef struct _QUICK_INDEX_HINT { LONGLONG HintData[3]; } QUICK_INDEX_HINT, *PQUICK_INDEX_HINT;
//
// Index structures
//
typedef struct { ULONG KeyLength; PVOID Key; } INDEX_KEY, *PINDEX_KEY;
typedef struct { ULONG DataLength; PVOID Data; } INDEX_DATA, *PINDEX_DATA;
typedef struct { INDEX_KEY KeyPart; INDEX_DATA DataPart; } INDEX_ROW, *PINDEX_ROW;
//
// COLLATION_FUNCTION returns LessThan if Key1 precedes Key2
// EqualTo if Key1 is identical to Key2
// GreaterThan if Key1 follows Key2
//
typedef FSRTL_COMPARISON_RESULT (*PCOLLATION_FUNCTION) ( IN PINDEX_KEY Key1, IN PINDEX_KEY Key2, IN PVOID CollationData );
typedef struct _UPCASE_TABLE_AND_KEY {
//
// Pointer to a table of upcased unicode characters indexed by character to
// be upcased.
//
PWCH UpcaseTable;
//
// Size of UpcaseTable in unicode characters
//
ULONG UpcaseTableSize;
//
// Optional addtional pointer.
//
INDEX_KEY Key;
} UPCASE_TABLE_AND_KEY, *PUPCASE_TABLE_AND_KEY;
//
// Wait for new length block used to synchronize a thread with FileSize
// exceeding the specified Length.
//
typedef struct _WAIT_FOR_NEW_LENGTH {
//
// Link words for multiple waiters on the Scb.
//
LIST_ENTRY WaitList;
//
// Set event when FileSize exceeds this length.
//
LONGLONG Length;
//
// Event to set when new length achieved.
//
KEVENT Event;
//
// Irp to complete when new length achieved. (If Irp present, Event is
// ignored.)
//
PIRP Irp;
//
// Stream we are waiting on.
//
ATTRIBUTE_HANDLE Stream;
//
// Status code for operation that caused the new length to be satisfied.
// It may be STATUS_CANCELLED, STATUS_TIMEOUT or STATUS_SUCCESS
// or a request specific status.
//
NTSTATUS Status;
//
// Flags.
//
ULONG Flags;
} WAIT_FOR_NEW_LENGTH, *PWAIT_FOR_NEW_LENGTH;
#define NTFS_WAIT_FLAG_ASYNC (0x00000001)
//
// Standard collation functions for simple indices
//
FSRTL_COMPARISON_RESULT NtOfsCollateUlong ( // Both must be single Ulong
IN PINDEX_KEY Key1, IN PINDEX_KEY Key2, IN PVOID CollationData // Don't care, may be NULL
);
FSRTL_COMPARISON_RESULT NtOfsCollateUlongs ( // Lengths do not have to be equal
IN PINDEX_KEY Key1, IN PINDEX_KEY Key2, IN PVOID CollationData // Don't care, may be NULL
);
FSRTL_COMPARISON_RESULT NtOfsCollateSid ( IN PINDEX_KEY Key1, IN PINDEX_KEY Key2, IN PVOID CollationData // Don't care, may be NULL
);
FSRTL_COMPARISON_RESULT NtOfsCollateUnicode ( IN PINDEX_KEY Key1, IN PINDEX_KEY Key2, IN PVOID CollationData // PUPCASE_TABLE_AND_KEY (with no key)
);
//
// Standard match functions for simple indices
//
NTSTATUS NtOfsMatchAll ( IN PINDEX_ROW IndexRow, IN OUT PVOID MatchData // Don't care, may be NULL
);
NTSTATUS NtOfsMatchUlongExact ( IN PINDEX_ROW IndexRow, // Both must be single Ulong
IN OUT PVOID MatchData // PINDEX_KEY describing Ulong
);
NTSTATUS NtOfsMatchUlongsExact ( // Lengths do not have to be equal
IN PINDEX_ROW IndexRow, IN OUT PVOID MatchData // PINDEX_KEY describing Ulongs
);
NTSTATUS NtOfsMatchUnicodeExpression ( IN PINDEX_ROW IndexRow, IN OUT PVOID MatchData // PUPCASE_TABLE_AND_KEY with Uni expression (must have wildcards)
);
NTSTATUS NtOfsMatchUnicodeString ( IN PINDEX_ROW IndexRow, IN OUT PVOID MatchData // PUPCASE_TABLE_AND_KEY with Uni string (no wildcards)
);
//
// MATCH_FUNCTION returns
// STATUS_SUCCESS if the IndexRow matches
// STATUS_NO_MATCH if the IndexRow does not match, but the enumeration should
// continue
// STATUS_NO_MORE_MATCHES if the IndexRow does not match, and the enumeration
// should terminate
//
typedef NTSTATUS (*PMATCH_FUNCTION) (IN PINDEX_ROW IndexRow, IN OUT PVOID MatchData);
//
// CREATE_OPTIONS - common flags governing creation/opening of objects
//
typedef enum _CREATE_OPTIONS { CREATE_NEW = 0, CREATE_OR_OPEN = 1, OPEN_EXISTING = 2 } CREATE_OPTIONS;
//
// EXCLUSION - Form of exclusion desired when opening an object
//
typedef enum _EXCLUSION { SHARED = 0, EXCLUSIVE } EXCLUSION;
//
// Additional Dos Attribute indicating Content Index status of an object.
// If this is set on a document, it suppresses indexing. It is inherited
// from a parent directory at create time. This is stored in the
// DUPLICATED_INFORMATION structure.
//
#define SUPPRESS_CONTENT_INDEX (0x20000000)
//
// Define the size of the index buffer/bucket for view indexes, in bytes.
//
#define NTOFS_VIEW_INDEX_BUFFER_SIZE (0x1000)
//
// Exported constants.
//
//
// NtOfsContentIndexSystemFile is the repository for all CI related data on the
// disk.
extern FILE_REFERENCE NtOfsContentIndexSystemFile;
#if defined(_NTFSPROC_)
#define NTFSAPI
#else
#define NTFSAPI //DECLSPEC_IMPORT
#endif
////////////////////////////////////////////////////////////////////////////////
//
// Index API - These encapsulate the NtOfs BTree mechanisms.
//
//
// NtOfsCreateIndex creates or opens a named index attribute in an object. The
// ObjectHandle has been acquired exclusive and the returned handle is not
// acquired. The collation data is interpreted only by the CollationFunction.
//
// IndexHandles retain a "seek" position where enumerations (NtOfsReadRecords)
// may continue. This seek position may be updated by the routines as described
// below.
//
// If DeleteCollationData is 1, ExFreePool will be called on CollationData, either
// immediately if the index already exists, or when the index is deleted some time
// after the final close. If NtOfsCreateIndex returns an error, then CollationData
// must be deleted by the caller. If specified as 0, then ColloationData will not
// be deleted.
//
NTFSAPI NTSTATUS NtOfsCreateIndex ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ObjectHandle, IN UNICODE_STRING Name, IN CREATE_OPTIONS CreateOptions, IN ULONG DeleteCollationData, IN ULONG CollationRule, IN PCOLLATION_FUNCTION CollationFunction, IN PVOID CollationData OPTIONAL, OUT INDEX_HANDLE *IndexHandle );
//
// NtOfsFindRecord finds a single record in an index stream for read-only access
// or in preparation for calling NtOfsUpdateRecord.
//
NTFSAPI NTSTATUS NtOfsFindRecord ( IN PIRP_CONTEXT IrpContext, IN INDEX_HANDLE IndexHandle, IN PINDEX_KEY IndexKey, OUT PINDEX_ROW IndexRow, OUT PMAP_HANDLE MapHandle, IN OUT PQUICK_INDEX_HINT QuickIndexHint OPTIONAL );
//
// NtOfsFindRecord finds a single record in an index stream for read-only access
// or in preparation for calling NtOfsUpdateRecord.
//
NTFSAPI NTSTATUS NtOfsFindLastRecord ( IN PIRP_CONTEXT IrpContext, IN INDEX_HANDLE IndexHandle, IN PINDEX_KEY MaxIndexKey, OUT PINDEX_ROW IndexRow, OUT PMAP_HANDLE MapHandle );
//
// NtOfsAddRecords performs bulk, logged inserts into an index. The index will
// be acquired exclusive for this call. Each record added must have a unique
// (with regards to the collation function) key. No maps are currently
// outstanding on this index. If SequentialInsertMode is nonzero, this is a hint
// to the index package to keep all BTree buffers as full as possible, by splitting
// as close to the end of the buffer as possible. If specified as zero, random
// inserts are assumed, and buffers are always split in the middle for better balance.
//
// This call may update the IndexHandle seek position
//
NTFSAPI VOID NtOfsAddRecords ( IN PIRP_CONTEXT IrpContext, IN INDEX_HANDLE IndexHandle, IN ULONG Count, IN PINDEX_ROW IndexRow, IN ULONG SequentialInsertMode );
//
// NtOfsDeleteRecords performs bulk, logged deletion from an index. The index
// will be acquired exclusive for this call. No maps are currently outstanding
// on this index.
//
// This call may update the IndexHandle seek position
//
NTFSAPI VOID NtOfsDeleteRecords ( IN PIRP_CONTEXT IrpContext, IN INDEX_HANDLE IndexHandle, IN ULONG Count, IN PINDEX_KEY IndexKey );
//
// NtOfsReadRecords applies a match function to a block of contiguous records in
// the BTree starting either at a given IndexKey or beginning where it last left
// off.
//
// IndexKey is an optional point at which to begin the enumeration. The
// seek position of IndexHandle is set to return the next logical record
// on the next NtOfsReadRecords call.
//
// NtOfsReadRecords will seek to the appropriate point in the BTree (as defined
// by the IndexKey or saved position and the CollateFunction) and begin calling
// MatchFunction for each record. It continues doing this while MatchFunction
// returns STATUS_SUCCESS. If MatchFunction returns STATUS_NO_MORE_MATCHES,
// NtOfsReadRecords will cache this result and not call MatchFunction again until
// called with a non-NULL IndexKey.
//
// NtOfsReadRecords returns the last status code returned by MatchFunction.
//
// The IndexHandle does not have to be acquired as it is acquired shared for the
// duration of the call. NtOfsReadRecords may
// return with STATUS_SUCCESS without filling the output buffer (say, every 10
// index pages) to reduce lock contention.
//
// NtOfsReadRecords will read up to Count rows, comprising up to BufferLength
// bytes in total and will fill in the Rows[] array for each row returned.
//
// Note that this call is self-synchronized, such that successive calls to
// the routine are guaranteed to make progress through the index and to return
// items in Collation order, in spite of Add and Delete record calls being
// interspersed with Read records calls.
//
NTFSAPI NTSTATUS NtOfsReadRecords ( IN PIRP_CONTEXT IrpContext, IN INDEX_HANDLE IndexHandle, IN OUT PREAD_CONTEXT *ReadContext, IN OPTIONAL PINDEX_KEY IndexKey, IN PMATCH_FUNCTION MatchFunction, IN PVOID MatchData, IN OUT ULONG *Count, OUT PINDEX_ROW Rows, IN ULONG BufferLength, OUT PVOID Buffer );
NTFSAPI VOID NtOfsFreeReadContext ( IN PREAD_CONTEXT ReadContext );
//
// NtOfsUpdateRecord updates a single record in place. It is guaranteed that the
// length of the data/key portion of the record does not change. The index will
// be acquired exclusive for this call.
//
// This call may update the IndexHandle seek position
//
NTFSAPI VOID NtOfsUpdateRecord ( IN PIRP_CONTEXT IrpContext, IN INDEX_HANDLE IndexHandle, IN ULONG Count, IN PINDEX_ROW IndexRow, IN OUT PQUICK_INDEX_HINT QuickIndexHint OPTIONAL, IN OUT PMAP_HANDLE MapHandle OPTIONAL );
//
// NtOfsCloseIndex closes an index handle. The index must not be acquired for this
// call. No outstanding maps are allowed.
//
NTFSAPI VOID NtOfsCloseIndex ( IN PIRP_CONTEXT IrpContext, IN INDEX_HANDLE IndexHandle );
//
// NtOfsDeleteIndex removes an index attribute from an object. The object will be
// acquired exclusive for this call.
//
NTFSAPI VOID NtOfsDeleteIndex ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ObjectHandle, IN INDEX_HANDLE IndexHandle );
////////////////////////////////////////////////////////////////////////////////
//
// Map API - These encapsulate the NtOfs/Cache manager interactions
//
//
// NtOfsInitializeMapHandle initializes a map handle so it can be safely
// released at any time.
//
// NTFSAPI
// VOID
// NtOfsInitializeMapHandle (
// IN PMAP_HANDLE Map
// );
//
#define NtOfsInitializeMapHandle( M ) { (M)->Bcb = NULL; }
//
// NtOfsMapAttribute maps a portion of the specified attribute and returns a pointer
// to the memory. The memory mapped may not span a mapping window. Multiple maps
// are allowed through different handles in different threads. The data is not
// preread nor is the memory pinned.
//
#ifndef _NTFSPROC_
NTFSAPI VOID NtOfsMapAttribute ( IN PIRP_CONTEXT IrpContext, IN ATTRIBUTE_HANDLE Attribute, IN LONGLONG Offset, IN ULONG Length, OUT PVOID *Buffer, OUT PMAP_HANDLE MapHandle );
#else
#ifdef MAPCOUNT_DBG
#define NtOfsMapAttribute(I,S,O,L,B,M) ( \
CcMapData((S)->FileObject, (PLARGE_INTEGER)&(O), (L), TRUE, &(M)->Bcb, (B)), \ (I)->MapCount++, \ (M)->FileOffset = (O), \ (M)->Length = (L), \ (M)->Buffer = *(PVOID *)(B) \ ) #else
#define NtOfsMapAttribute(I,S,O,L,B,M) ( \
CcMapData((S)->FileObject, (PLARGE_INTEGER)&(O), (L), TRUE, &(M)->Bcb, (B)), \ (M)->FileOffset = (O), \ (M)->Length = (L), \ (M)->Buffer = *(PVOID *)(B) \ ) #endif
#endif
//
// NtOfsPreparePinWrite maps and pins a portion of the specified attribute and
// returns a pointer to the memory. This is equivalent to doing a NtOfsMapAttribute
// followed by NtOfsPinRead and NtOfsDirty but is more efficient.
//
#ifndef _NTFSPROC_
NTFSAPI VOID NtOfsPreparePinWrite ( IN PIRP_CONTEXT IrpContext, IN ATTRIBUTE_HANDLE Attribute, IN LONGLONG Offset, IN ULONG Length, OUT PVOID *Buffer, OUT PMAP_HANDLE MapHandle );
#else
#ifdef MAPCOUNT_DBG
#define NtOfsPreparePinWrite(I,S,O,L,B,M) { \
if (((O) + (L)) > (S)->Header.AllocationSize.QuadPart) { \ ExRaiseStatus(STATUS_END_OF_FILE); \ } \ CcPreparePinWrite((S)->FileObject, (PLARGE_INTEGER)&(O), (L), FALSE, TRUE, &(M)->Bcb, (B)); \ (I)->MapCount++; \ (M)->FileOffset = (O); \ (M)->Length = (L); \ (M)->Buffer = (B); \ } #else
#define NtOfsPreparePinWrite(I,S,O,L,B,M) { \
if (((O) + (L)) > (S)->Header.AllocationSize.QuadPart) { \ ExRaiseStatus(STATUS_END_OF_FILE); \ } \ CcPreparePinWrite((S)->FileObject, (PLARGE_INTEGER)&(O), (L), FALSE, TRUE, &(M)->Bcb, (B)); \ (M)->FileOffset = (O); \ (M)->Length = (L); \ (M)->Buffer = (B); \ } #endif
#endif
//
// NtOfsPinRead pins a section of a map and read in all pages from the mapped
// attribute. Offset and Length must describe a byte range which is equal to
// or included by the original mapped range.
//
#ifndef _NTFSPROC_
NTFSAPI VOID NtOfsPinRead( IN PIRP_CONTEXT IrpContext, IN ATTRIBUTE_HANDLE Attribute, IN LONGLONG Offset, IN ULONG Length, OUT PMAP_HANDLE MapHandle );
#else
#ifdef MAPCOUNT_DBG
#define NtOfsPinRead(I,S,O,L,M) { \
ASSERT((M)->Bcb != NULL); \ ASSERT(((O) >= (M)->FileOffset) && (((O) + (L)) <= ((M)->FileOffset + (M)->Length))); \ CcPinMappedData((S)->FileObject, (PLARGE_INTEGER)&(O), (L), TRUE, &(M)->Bcb); \ (I)->MapCount++; \ (M)->FileOffset = (O); \ (M)->Length = (L); \ } #else
#define NtOfsPinRead(I,S,O,L,M) { \
ASSERT((M)->Bcb != NULL); \ ASSERT(((O) >= (M)->FileOffset) && (((O) + (L)) <= ((M)->FileOffset + (M)->Length))); \ CcPinMappedData((S)->FileObject, (PLARGE_INTEGER)&(O), (L), TRUE, &(M)->Bcb); \ (M)->FileOffset = (O); \ (M)->Length = (L); \ } #endif
#endif
//
// NtOfsDirty marks a map as being dirty (eligible for lazy writer access) and
// marks the pages with an optional LSN for coordination with LFS. This call
// is invalid unless the map has been pinned.
//
// NTFSAPI
// NtOfsDirty (
// IN PIRP_CONTEXT IrpContext,
// IN PMAP_HANDLE MapHandle,
// PLSN Lsn OPTIONAL
// );
#define NtOfsDirty(I,M,L) {CcSetDirtyPinnedData((M)->Bcb,(L));}
//
// NtOfsReleaseMap unmaps/unpins a mapped portion of an attribute.
//
#ifndef _NTFSPROC_
NTFSAPI VOID NtOfsReleaseMap ( IN PIRP_CONTEXT IrpContext, IN PMAP_HANDLE MapHandle );
#else
#ifdef MAPCOUNT_DBG
#define NtOfsReleaseMap(IC,M) { \
if ((M)->Bcb != NULL) { \ CcUnpinData((M)->Bcb); \ (IC)->MapCount--; \ (M)->Bcb = NULL; \ } \ } #else
#define NtOfsReleaseMap(IC,M) { \
if ((M)->Bcb != NULL) { \ CcUnpinData((M)->Bcb); \ (M)->Bcb = NULL; \ } \ } #endif
#endif
//
// NtOfsPutData writes data into an attribute in a recoverable fashion. The
// caller must have opened the attribute with LogNonresidentToo.
//
// NtOfsPutData will write the data atomically and update the mapped image,
// subject to the normal lazy commit of the transaction.
//
NTFSAPI VOID NtOfsPutData ( IN PIRP_CONTEXT IrpContext, IN ATTRIBUTE_HANDLE Attribute, IN LONGLONG Offset, IN ULONG Length, IN PVOID Data OPTIONAL );
////////////////////////////////////////////////////////////////////////////////
//
// Attribute API - These encapsulate access to attributes on files/directories
// and summary catalogs
//
//
// NtOfsCreateAttribute will create or open a data attribute and return a handle
// that will allow mapping operations.
//
// For attributes that wish to have logging behavior, LogNonresidentToo must be
// set to true. See the discussion on NtOfsPutData (in the mapping section
// above).
//
NTFSAPI NTSTATUS NtOfsCreateAttribute ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ObjectHandle, IN UNICODE_STRING Name, IN CREATE_OPTIONS CreateOptions, IN ULONG LogNonresidentToo, OUT ATTRIBUTE_HANDLE *AttributeHandle );
//
// NtOfsCreateAttributeEx will create or open an attribute and return a handle
// that will allow mapping operations. If a standard data attribute is to be
// used, call NtOfsCreateAttribute instead. This function is here for callers
// who need to use a different attribute type code.
//
// For attributes that wish to have logging behavior, LogNonresidentToo must be
// set to true. See the discussion on NtOfsPutData (in the mapping section
// above).
//
NTFSAPI NTSTATUS NtOfsCreateAttributeEx ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ObjectHandle, IN UNICODE_STRING Name, IN ULONG AttributeTypeCode, IN CREATE_OPTIONS CreateOptions, IN ULONG LogNonresidentToo, OUT ATTRIBUTE_HANDLE *AttributeHandle );
//
// Valid AttributeTypeCode values for NtOfsCreateAttributeEx:
//
#define $LOGGED_UTILITY_STREAM (0x100)
//
// NtOfsCloseAttribute releases the attribute. The attribute is not acquired. No
// outstanding maps are active.
//
NTFSAPI VOID NtOfsCloseAttribute ( IN PIRP_CONTEXT IrpContext, IN ATTRIBUTE_HANDLE AttributeHandle );
//
// NtOfsDeleteAttribute releases all storage associated with the attribute. The
// object will be acquired exclusive. The attribute will be acquired exclusive.
// No outstanding maps are active.
//
NTFSAPI VOID NtOfsDeleteAttribute ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ObjectHandle, IN ATTRIBUTE_HANDLE AttributeHandle );
//
// NtOfsQueryLength returns the current length of user data within the attribute.
// The attribute may be mapped. The attribute may be acquired.
//
NTFSAPI LONGLONG NtOfsQueryLength ( IN ATTRIBUTE_HANDLE AttributeHandle );
//
// NtOfsSetLength sets the current EOF on the given attribute. The attribute
// may not be mapped to the view containing Length, or any subsequent view.
// The attribute will be acquired exclusive.
//
NTFSAPI VOID NtOfsSetLength ( IN PIRP_CONTEXT IrpContext, IN ATTRIBUTE_HANDLE Attribute, IN LONGLONG Length ); //
// NtOfsWaitForNewLength allows the caller to wait for the specified length to
// be exceeded, or optionally timeout, if the specified Irp has not been cancelled.
//
NTFSAPI NTSTATUS NtOfsWaitForNewLength ( IN ATTRIBUTE_HANDLE Attribute, IN LONGLONG Length, IN ULONG Async, IN PIRP Irp, IN PDRIVER_CANCEL CancelRoutine, IN PLARGE_INTEGER Timeout OPTIONAL );
//
// This routine may be called any time FileSize has changed to wake any threads
// waiting for a particular FileSize change. Or specify WakeAll to unconditionally
// wake all waiters.
//
VOID NtOfsPostNewLength ( IN PIRP_CONTEXT IrpContext OPTIONAL, IN ATTRIBUTE_HANDLE Attribute, IN BOOLEAN WakeAll );
//
// NtOfsDecommit releases storage associated with a range of the attribute. It does
// not change the EOF marker nor does it change the logical position of data within
// the attribute. The range of the attribute being released may be mapped or
// pinned.
//
// Reads from decommitted ranges should return zero (although Query will never read
// from these ranges).
//
// Writes to decommitted pages should fail or be nooped (although Query will never
// write to these ranges).
//
// This call will purge, so none of the views overlapping the specified range may
// be mapped.
//
NTFSAPI VOID NtOfsDecommit ( IN PIRP_CONTEXT IrpContext, IN ATTRIBUTE_HANDLE Attribute, IN LONGLONG Offset, IN LONGLONG Length );
//
// NtOfsFlushAttribute flushes all cached data to the disk and returns upon
// completion. If the attribute is LogNonresidentToo, then only the log file
// is flushed. Optionally, the range may be purged as well. If the attribute
// is purged, then there can be no mapped views.
//
NTFSAPI VOID NtOfsFlushAttribute ( IN PIRP_CONTEXT IrpContext, IN ATTRIBUTE_HANDLE Attribute, IN ULONG Purge );
//
// NtOfsQueryAttributeSecurityId returns the security ID for the attribute if
// present.
//
NTFSAPI VOID NtOfsQueryAttributeSecurityId ( IN PIRP_CONTEXT IrpContext, IN ATTRIBUTE_HANDLE Attribute, OUT SECURITY_ID *SecurityId );
////////////////////////////////////////////////////////////////////////////////
//
// Concurrency control API
//
// As a rule, these routines are not required. All NtOfs routines are
// self-synchronized as atomic actions, or as parts of a top-level action when
// called within a top-level action routine.
//
// ISSUE: In particular, supporting the exclusive access call is an implementation
// problem for Ntfs. Wrapping top-level actions is the best way to preserve
// exclusive access across calls.
//
VOID NtOfsAcquireObjectShared ( HANDLE ObjectHandle );
// VOID
// NtOfsAcquireObjectExclusive (
// HANDLE ObjectHandle
// );
VOID NtOfsReleaseObject ( HANDLE ObjectHandle );
// Debugging routines
BOOLEAN NtOfsIsObjectAcquiredExclusive ( HANDLE ObjectHandle );
BOOLEAN NtOfsIsObjectAcquiredShared ( HANDLE ObjectHandle );
////////////////////////////////////////////////////////////////////////////////
//
// File/Directory/Etc API
//
//
// NtOfsOpenByFileReference opens an object given a file reference. The file is
// assumed to exist; this call cannot be used to create a file. The returned
// handle is acquired according to the input exclusion.
//
NTFSAPI NTSTATUS NtOfsOpenByFileReference ( IN PIRP_CONTEXT IrpContext, IN FILE_REFERENCE FileReference, IN EXCLUSION Exclusion, OUT OBJECT_HANDLE *ObjectHandle );
//
// NtOfsCreateRelativeObject opens or creates an object relative to a specified
// parent object. The parent will be acquired exclusive. The child is opened
// acquired according to the input exclusion.
//
// ISSUE: When creating an object, is the transaction committed before this
// call returns?
//
NTFSAPI NTSTATUS NtOfsCreateRelativeObject ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ParentObjectHandle, IN UNICODE_STRING Name, IN CREATE_OPTIONS CreateOptions, IN EXCLUSION Exclusion, OUT OBJECT_HANDLE *ObjectHandle );
//
// NtOfsCloseObject releases the object handle.
//
NTFSAPI NTSTATUS NtOfsCloseObject ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ObjectHandle );
//
// NtOfsDeleteObject deletes the object. No user-mode handle is attached to
// the object. No attributes are currently open. The object is acquired
// exclusive.
//
NTFSAPI NTSTATUS NtOfsDeleteObject ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ObjectHandle );
//
// NtOfsDeleteAllAttributes deletes all attributes of the object. No attribute
// is open. The object is acquired exclusive.
//
NTFSAPI NTSTATUS NtOfsDeleteAllAttributes ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ObjectHandle );
//
// NtOfsQueryPathFromRoot returns *A* path from the root to a node. In the
// presence of hard links, several paths may exist, however, only one needs
// to be returned. Memory for the file name is provided by the caller.
//
NTFSAPI NTSTATUS NtOfsQueryPathFromRoot ( IN PIRP_CONTEXT IrpContext, IN FILE_REFERENCE FileReference, OUT UNICODE_STRING *PathName );
//
// NtOfsQueryFileName returns the final component in the path name into a
// caller-supplied buffer. In the presence of hard links, several names
// may exist, however, only one needs to be returned.
//
NTFSAPI NTSTATUS NtOfsQueryFileName ( IN PIRP_CONTEXT IrpContext, IN FILE_REFERENCE FileReference, OUT UNICODE_STRING *FileName );
//
// NtOfsQueryFileReferenceFromName returns the file reference named by the path
//
NTFSAPI NTSTATUS NtOfsQueryFileReferenceFromName ( IN PIRP_CONTEXT IrpContext, IN UNICODE_STRING Name, OUT FILE_REFERENCE *FileReference );
//
// This call must be very fast; it is a very common call made by CI/Query.
//
NTFSAPI NTSTATUS NtOfsQueryFileReferenceFromHandle ( IN OBJECT_HANDLE Object, OUT FILE_REFERENCE *FileReference );
//
// NtOfsQueryObjectSecurityId returns the security Id associated with an object.
// The object is acquired shared or exclusive. This call must be very fast
//
NTFSAPI NTSTATUS NtOfsQueryObjectSecurityId ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ObjectHandle, OUT SECURITY_ID *SecurityId );
////////////////////////////////////////////////////////////////////////////////
//
// Scope API
//
//
// NtOfsIsAncestorOf must quickly tell if one file is an ancestor of the given
// child. In the presence of hard links, we may pick a "preferred" path (i.e.
// we don't have to travel to all ancestors). This call must be reasonably fast
// since this is a very frequent call from Query.
//
NTFSAPI NTSTATUS NtOfsIsAncestorOf ( IN PIRP_CONTEXT IrpContext, IN FILE_REFERENCE Ancestor, IN FILE_REFERENCE Child );
//
// NtOfsGetParentFileReferenceFromHandle is used to retrieve the FileReference
// of the parent of the named object. With hard links the "first" parent may
// be chosen. This call needs to be reasonably efficient.
//
NTFSAPI NTSTATUS NtOfsGetParentFileReferenceFromHandle ( IN PIRP_CONTEXT IrpContext, IN OBJECT_HANDLE ChildObject, OUT FILE_REFERENCE *ParentFileReference );
////////////////////////////////////////////////////////////////////////////////
//
// Security API
//
// NtOfs maintains a "per-IrpContext" cache that speeds up security validation.
// Clients clear the cache (at the beginning of a query, say) and then do
// successive probes which may populate the cache.
//
//
// NtOfsClearSecurityCache clears the cache.
//
NTFSAPI NTSTATUS NtOfsClearSecurityCache ( IN PIRP_CONTEXT IrpContext );
//
// NtOfsIsAccessGranted uses the Se routines to validate access and caches the
// result for the specified SecurityId and DesiredAccess. The cache is first
// probed to see if the access can be granted immediately. If the SecurityId is
// not found, the corresponding ACL is retrieved and tested with the supplied
// access state and DesiredAccess. The result of this test is cached and
// returned.
//
NTFSAPI NTSTATUS NtOfsIsAccessGranted ( IN PIRP_CONTEXT IrpContext, IN SECURITY_ID SecurityId, IN ACCESS_MASK DesiredAccess, IN ACCESS_STATE *SecurityAccessState );
////////////////////////////////////////////////////////////////////////////////
//
// Worker thread stuff. Worker threads are needed for building new indexes
//
////////////////////////////////////////////////////////////////////////////////
//
// Miscellaneous information query/set
//
//
// Content Index may need to mark the volume as dirty to allow garbage collection
// of orphan objects by CHKDSK.
//
NTFSAPI NTSTATUS NtOfsMarkVolumeCorrupt ( IN PIRP_CONTEXT IrpContext, IN ULONG NewState, IN ULONG StateMask, OUT ULONG *OldState );
//
// NtOfsQueryVolumeStatistics returns the current capacity and free space on a
// volume. Ci uses this for heuristics to decide on when to trigger master merge,
// when to suppress master merge, etc.
//
NTFSAPI NTSTATUS NtOfsQueryVolumeStatistics ( IN PIRP_CONTEXT IrpContext, OUT LONGLONG *TotalClusters, OUT LONGLONG *FreeClusters );
//
// Query needs to retain some state in the NtOfs Ccb.
//
NTFSAPI NTSTATUS NtOfsQueryHandleState ( IN PIRP_CONTEXT IrpContext, OUT VOID *OldData );
NTFSAPI NTSTATUS NtOfsSetHandleState ( IN PIRP_CONTEXT IrpContext, IN VOID *Data );
//
// Generic unwrapping routines that get access to SCB/IRPC and FCB/IRPC
// pairs.
//
NTFSAPI NTSTATUS NtOfsQueryAttributeHandle ( IN PIRP_CONTEXT IrpContext, OUT ATTRIBUTE_HANDLE *AttributeHandle );
NTFSAPI NTSTATUS NtOfsQueryObjectHandle ( IN PIRP_CONTEXT IrpContext, OUT OBJECT_HANDLE *ObjectHandle );
//
// Create a context in which the caller can perform I/O in separate.
// threads. This means creating an IRP/IRP_CONTEXT. Each IrpContext corresponds
// to one I/O activity at a time. Multiple IrpContexts may be active in a thread
// at a single time.
//
NTFSAPI NTSTATUS NtOfsCloneIrpContext ( IN PIRP_CONTEXT IrpContext, OUT PIRP_CONTEXT *NewIrpContext );
//
// NtOfsCompleteRequest completes an IrpContext that has been previously cloned.
// All other FsCtl Irps are completed by Ntfs.
//
NTFSAPI NTSTATUS NtOfsCompleteRequest ( IN PIRP_CONTEXT IrpContext, NTSTATUS Status );
////////////////////////////////////////////////////////////////////////////////
//
// Iterators. While each iterator is created through a separate API, each one
// must support two operations:
// Next - this fills a buffer with as many records as possible
// Close - this releases the iterator.
//
typedef struct _BASE_FILE_SEGMENT_ITERATOR BASE_FILE_SEGMENT_ITERATOR;
typedef struct _USN_ITERATOR USN_ITERATOR;
//
// The types of iterators are:
//
// Scope iterate over a directory (optionally RECURSIVE)
// (implemented in Query)
// View iterate over the rows in a view with a partial key match
// (implemented in View)
// BaseFileSegment iterate over all base file record segments
// (implemented in NtOfs)
// SummaryCatalog iterate over all rows in a summary catalog
// Usn iterate over all objects with Usn's in a specific range
// (implmented in NtOfs)
//
// Each iteration is passed a buffer which is filled (as much as possible) with
// a packed array of:
// FILE_REFERENCE
// DUPLICATED_INFORMATION
// STAT_INFORMATION
// for each enumerated object. The output length is the length in bytes that
// was filled in with the enumeration request.
NTFSAPI NTSTATUS NtOfsCreateBaseFileSegmentIterator ( IN PIRP_CONTEXT IrpContext, OUT BASE_FILE_SEGMENT_ITERATOR *Iterator );
NTFSAPI NTSTATUS NtOfsNextBaseFileSegmentIteration ( IN PIRP_CONTEXT IrpContext, IN BASE_FILE_SEGMENT_ITERATOR *Iterator, IN OUT ULONG *BufferLength, IN OUT PVOID Buffer );
NTFSAPI NTSTATUS NtOfsCloseBaseFileSegmentIterator ( IN PIRP_CONTEXT IrpContext, IN BASE_FILE_SEGMENT_ITERATOR *Iterator );
NTFSAPI NTSTATUS NtOfsCreateUsnIterator ( IN PIRP_CONTEXT IrpContext, IN USN BeginningUsn, IN USN EndingUsn, OUT USN_ITERATOR *Iterator );
NTFSAPI NTSTATUS NtOfsNextUsnIteration ( IN PIRP_CONTEXT IrpContext, IN USN_ITERATOR *Iterator, IN OUT ULONG *BufferLength, IN OUT PVOID Buffer );
NTFSAPI NTSTATUS NtOfsCloseUsnIterator ( IN PIRP_CONTEXT IrpContext, IN USN_ITERATOR *Iterator );
////////////////////////////////////////////////////////////////////////////////
//
// Infrastructure support.
//
// V/C/X register callbacks with NtOfs when they are loaded. Until they are loaded
// NtOfs will call default routines (that do nothing).
//
typedef enum _NTFS_ADDON_TYPES { Encryption = 3 } NTFS_ADDON_TYPES;
////////////////////////////////////////////////////////////////////////////////
//
// Encryption
//
//
// Stream Create Status for FileDirFlag
//
#define STREAM_NEW_OR_EXIST_MASK 0x000f0000
#define FILE_DIR_TYPE_MASK 0x000000ff
#define FILE_NEW 0x00000001
#define FILE_EXISTING 0x00000002
#define DIRECTORY_NEW 0x00000004
#define DIRECTORY_EXISTING 0x00000008
#define EXISTING_FILE_ENCRYPTED 0x00000010
#define STREAM_NEW 0x00010000
#define STREAM_EXISTING 0x00020000
//
// Encryption flag for EncryptionFlag
//
#define STREAM_ENCRYPTED 0x00000001
#define FILE_ENCRYPTED 0x00000002
//
// Access flags
//
// NB -- These values are NOT arbitrary. Notice also that they are not
// in value order, they are grouped according to their meaning.
// Their values correspond to FILE_READ_DATA, etc. and
// TOKEN_HAS_BACKUP_PRIVILEGE, etc.
//
#define READ_DATA_ACCESS 0x01
#define WRITE_DATA_ACCESS 0x02
#define APPEND_DATA_ACCESS 0x04
#define EXECUTE_ACCESS 0x20
#define READ_ATTRIBUTES_ACCESS 0x80
#define WRITE_ATTRIBUTES_ACCESS 0x100
#define BACKUP_ACCESS 0x08
#define RESTORE_ACCESS 0x10
#define TRAVERSE_ACCESS 0x40
#define MANAGE_VOLUME_ACCESS 0x200
//
// Volume State
//
#define READ_ONLY_VOLUME 0x00000001
typedef NTSTATUS (*ENCRYPTED_FILE_CREATE) ( IN OBJECT_HANDLE FileHdl, IN OBJECT_HANDLE ParentDir OPTIONAL, IN PIO_STACK_LOCATION IrpSp, IN ULONG FileDirFlag, IN ULONG VolumeState, IN PIRP_CONTEXT IrpContext, IN PDEVICE_OBJECT VolDo, IN PVOID FileKeyContext, IN OUT PVOID *PKeyContext, IN OUT ULONG *ContextLength, IN OUT PVOID *PCreateContext, IN OUT PBOOLEAN Reserved );
typedef NTSTATUS (*ENCRYPTED_FILE_PRE_CREATE) ( IN PDEVICE_OBJECT VolDo, IN PIRP Irp, IN PFILE_OBJECT FileObject );
typedef NTSTATUS (*ENCRYPTED_FILE_POST_CREATE) ( IN PDEVICE_OBJECT VolDo, IN PIRP Irp, IN PFILE_OBJECT FileObject, IN NTSTATUS Status, IN OUT PVOID *PCreateContext );
typedef NTSTATUS (*ENCRYPTED_FILE_SYSTEM_CONTROL) ( IN PVOID PInputBuffer OPTIONAL, IN ULONG InputDataLength, OUT PVOID OutputBuffer OPTIONAL, IN OUT ULONG *OutputBufferLength OPTIONAL, IN ULONG EncryptionFlag, IN ULONG AccessFlag, IN ULONG VolumeState, IN ULONG FsControlCode, IN OBJECT_HANDLE FileHdl, IN PIRP_CONTEXT IrpContext, IN PDEVICE_OBJECT VolDo, IN ATTRIBUTE_HANDLE Attribute, IN OUT PVOID *PContext OPTIONAL, IN OUT ULONG *ContextLength OPTIONAL );
typedef NTSTATUS (*ENCRYPTED_FILE_PRE_FILE_SYSTEM_CONTROL) ( IN PDEVICE_OBJECT VolDo, IN PIRP Irp, IN PFILE_OBJECT FileObject );
typedef NTSTATUS (*ENCRYPTED_FILE_READ)( IN OUT PUCHAR InOutBuffer, IN PLARGE_INTEGER Offset, IN ULONG BufferSize, IN PVOID Context );
typedef NTSTATUS (*ENCRYPTED_FILE_WRITE)( IN PUCHAR InBuffer, OUT PUCHAR OutBuffer, IN PLARGE_INTEGER Offset, IN ULONG BufferSize, IN PUCHAR Context );
typedef VOID (*ENCRYPTED_FILE_CLEANUP)( IN OUT PVOID *Context );
#define ENCRYPTION_CURRENT_INTERFACE_VERSION 3
#define ENCRYPTION_ALL_STREAMS 0x00000001
#define ENCRYPTION_ALLOW_COMPRESSION 0x00000002
typedef struct _ENCRYPTION_CALL_BACK { ULONG InterfaceVersion; ULONG ImplementationFlags; ENCRYPTED_FILE_CREATE FileCreate; ENCRYPTED_FILE_PRE_CREATE PreCreate; ENCRYPTED_FILE_POST_CREATE PostCreate; ENCRYPTED_FILE_SYSTEM_CONTROL FileSystemControl_1; ENCRYPTED_FILE_SYSTEM_CONTROL FileSystemControl_2; ENCRYPTED_FILE_PRE_FILE_SYSTEM_CONTROL PreFileSystemControl; ENCRYPTED_FILE_READ AfterReadProcess; ENCRYPTED_FILE_WRITE BeforeWriteProcess; ENCRYPTED_FILE_CLEANUP CleanUp; } ENCRYPTION_CALL_BACK, *PENCRYPTION_CALL_BACK;
//
// NtOfsRegisterCallBacks supplies a call table to NtOfs. Each table has an
// interface version number. If the interface version does not exactly match
// what NtOfs expects, the call will fail.
//
NTFSAPI NTSTATUS NtOfsRegisterCallBacks ( NTFS_ADDON_TYPES NtfsAddonType, PVOID CallBackTable );
|