windows-nt/Source/XPSP1/NT/base/published/ntfsexp.w
2020-09-26 16:20:57 +08:00

1630 lines
43 KiB
OpenEdge ABL
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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
);