/*++


Copyright (c) 1991  Microsoft Corporation

Module Name:

    untfs.h

Abstract:

    This module contains basic declarations and definitions for
    the NTFS utilities.  Note that more extensive description
    of the file system structures may be found in ntos\inc\ntfs.h.

Author:

    Bill McJohn     [BillMc]        23-July-1991

Revision History:


IMPORTANT NOTE:

    The NTFS on-disk structure must guarantee natural alignment of all
    arithmetic quantities on disk up to and including quad-word (64-bit)
    numbers.  Therefore, all attribute records are quad-word aligned, etc.

--*/

#if !defined( _UNTFS_DEFN_ )

#define _UNTFS_DEFN_

#define FRIEND friend
#define MIN( a, b ) ( ((a) < (b)) ? (a) : (b) )


// Set up the UNTFS_EXPORT macro for exporting from UNTFS (if the
// source file is a member of UNTFS) or importing from UNTFS (if
// the source file is a client of UNTFS).
//
#if defined ( _AUTOCHECK_ )
#define UNTFS_EXPORT
#elif defined ( _UNTFS_MEMBER_ )
#define UNTFS_EXPORT    __declspec(dllexport)
#else
#define UNTFS_EXPORT    __declspec(dllimport)
#endif



#include "bigint.hxx"
#include "bpb.hxx"

#pragma pack(4)

DEFINE_TYPE( BIG_INT, LCN );
DEFINE_TYPE( BIG_INT, VCN );

DEFINE_TYPE( LARGE_INTEGER, LSN );

// Macros:

#define QuadAlign( n ) \
    (((n) + 7) & ~7 )

#define DwordAlign( n ) \
    (((n) + 3) & ~3 )

#define IsQuadAligned( n ) \
    (((n) & 7) == 0)

#define IsDwordAligned( n ) \
    (((n) & 3) == 0)


// Miscellaneous constants:

// This value represents the number of clusters from the Master
// File Table which are copied to the Master File Table Reflection.

#define REFLECTED_MFT_SEGMENTS  (4)
#define BYTES_IN_BOOT_AREA     (0x2000)

// This value is used in a mapping-pair to indicate that the run
// described by the mapping pair doesn't really exist.  This allows
// NTFS to support sparse files.  Note that the actual values
// are LARGE_INTEGERS; the BIG_INT class manages the conversion.

#define LCN_NOT_PRESENT     -1
#define INVALID_VCN         -1

// This definition is for VCNs that appear in Unions, since an object
// with a constructor (like a BIG_INT) can't appear in a union.

DEFINE_TYPE( LARGE_INTEGER, VCN2 );

//
//  Temporary definitions ****
//

typedef ULONG COLLATION_RULE;
typedef ULONG DISPLAY_RULE;

// This defines the number of bytes to read at one time
// when processing the MFT.

#define MFT_PRIME_SIZE  (32*1024)

//  The compression chunk size is constant for now, at 4KB.
//

#define NTFS_CHUNK_SIZE                  (0x1000)

//
//  This number is actually the log of the number of clusters per compression
//  unit to be stored in a nonresident attribute record header.
//

#define NTFS_CLUSTERS_PER_COMPRESSION    (4)

//
//  Collation Rules
//

//
//  For binary collation, values are collated by a binary compare of their
//  bytes, with the first byte being most significant.
//

#define COLLATION_BINARY                 (0)

//
//  For collation of Ntfs file names, file names are collated as Unicode
//  strings.  See below.
//

#define COLLATION_FILE_NAME              (1)

//
//  For collation of Unicode strings, the strings are collated by their
//  binary Unicode value, with the exception that for characters which may
//  be upcased, the lower case value for that character collates immediately
//  after the upcased value.
//

#define COLLATION_UNICODE_STRING         (2)

#define COLLATION_ULONG                  (16)
#define COLLATION_SID                    (17)
#define COLLATION_SECURITY_HASH          (18)
#define COLLATION_ULONGS                 (19)

//
//  Total number of collation rules
//

#define COLLATION_NUMBER_RULES           (7)


// An MFT_SEGMENT_REFERENCE identifies a cluster in the Master
// File Table by its file number (VCN in Master File Table) and
// sequence number.  If the sequence number is zero, sequence
// number checking is not performed.

typedef struct _MFT_SEGMENT_REFERENCE {

    ULONG LowPart;
    USHORT HighPart;
    USHORT SequenceNumber;

} MFT_SEGMENT_REFERENCE, *PMFT_SEGMENT_REFERENCE;

DEFINE_TYPE( struct _MFT_SEGMENT_REFERENCE, MFT_SEGMENT_REFERENCE );

DEFINE_TYPE( MFT_SEGMENT_REFERENCE, FILE_REFERENCE );

INLINE
BOOLEAN
operator == (
    IN RCMFT_SEGMENT_REFERENCE Left,
    IN RCMFT_SEGMENT_REFERENCE Right
    )
/*++

Routine Description:

    This function tests two segment references for equality.

Arguments:

    Left    --  supplies the left-hand operand
    Right   --  supplies the right-hand operand

Return Value:

    TRUE if they are equal; FALSE if not.

--*/
{
    return( Left.HighPart == Right.HighPart &&
            Left.LowPart == Right.LowPart &&
            Left.SequenceNumber == Right.SequenceNumber );
}



// System file numbers:
//
// The first sixteen entries in the Master File Table are reserved for
// system use.  The following reserved slots have been defined:

#define MASTER_FILE_TABLE_NUMBER         (0)
#define MASTER_FILE_TABLE2_NUMBER        (1)
#define LOG_FILE_NUMBER                  (2)
#define VOLUME_DASD_NUMBER               (3)
#define ATTRIBUTE_DEF_TABLE_NUMBER       (4)
#define ROOT_FILE_NAME_INDEX_NUMBER      (5)
#define BIT_MAP_FILE_NUMBER              (6)
#define BOOT_FILE_NUMBER                 (7)
#define BAD_CLUSTER_FILE_NUMBER          (8)
#define QUOTA_TABLE_NUMBER               (9)    // for version < 2.0
#define SECURITY_TABLE_NUMBER            (9)    // for version >= 2.0
#define UPCASE_TABLE_NUMBER              (10)
#define EXTEND_TABLE_NUMBER              (11)   // for version >= 2.0

#define MFT_OVERFLOW_FRS_NUMBER          (15)

#define FIRST_USER_FILE_NUMBER           (16)

DEFINE_TYPE( ULONG, ATTRIBUTE_TYPE_CODE );

//
//  System-defined Attribute Type Codes.  For the System-defined attributes,
//  the Unicode Name is exactly equal to the name of the following symbols.
//  For this reason, all of the system-defined attribute names start with "$",
//  to always distinguish them when attribute names are listed, and to reserve
//  a namespace for attributes defined in the future.  I.e., a User-Defined
//  attribute name will never collide with a current or future system-defined
//  attribute name if it does not start with "$".  User attribute numbers
//  should not start until $FIRST_USER_DEFINED_ATTRIBUTE, too allow the
//  potential for upgrading existing volumes with new user-defined attributes
//  in future versions of NTFS.  The tagged attribute list is terminated with
//  a lone-standing $END - the rest of the attribute record does not exist.
//

#define $UNUSED                          (0x0)

#define $STANDARD_INFORMATION            (0x10)
#define $ATTRIBUTE_LIST                  (0x20)
#define $FILE_NAME                       (0x30)
#define $VOLUME_VERSION                  (0x40)
#define $OBJECT_ID                       (0x40)
#define $SECURITY_DESCRIPTOR             (0x50)
#define $VOLUME_NAME                     (0x60)
#define $VOLUME_INFORMATION              (0x70)
#define $DATA                            (0x80)
#define $INDEX_ROOT                      (0x90)
#define $INDEX_ALLOCATION                (0xA0)
#define $BITMAP                          (0xB0)
#define $SYMBOLIC_LINK                   (0xC0)
#define $EA_INFORMATION                  (0xD0)
#define $EA_DATA                         (0xE0)
#define $FIRST_USER_DEFINED_ATTRIBUTE    (0x100)
#define $END                             (0xFFFFFFFF)


//
//  The boot sector is duplicated on the partition.  The first copy is on
//  the first physical sector (LBN == 0) of the partition, and the second
//  copy is at <number sectors on partition> / 2.  If the first copy can
//  not be read when trying to mount the disk, the second copy may be read
//  and has the identical contents.  Format must figure out which cluster
//  the second boot record belongs in, and it must zero all of the other
//  sectors that happen to be in the same cluster.  The boot file minimally
//  contains with two clusters, which are the two clusters which contain the
//  copies of the boot record.  If format knows that some system likes to
//  put code somewhere, then it should also align this requirement to
//  even clusters, and add that to the boot file as well.
//


//
//  Define the boot sector.  Note that MFT2 is exactly three file record
//  segments long, and it mirrors the first three file record segments from
//  the MFT, which are MFT, MFT2 and the Log File.
//
//  The Oem field contains the ASCII characters "NTFS    ".
//
//  The Checksum field is a simple additive checksum of all of the ULONGs
//  which precede the Checksum ULONG.  The rest of the sector is not included
//  in this Checksum.
//

typedef struct _PACKED_BOOT_SECTOR {
    UCHAR Jump[3];                                  //  offset = 0x000
    UCHAR Oem[8];                                   //  offset = 0x003
    PACKED_BIOS_PARAMETER_BLOCK PackedBpb;          //  offset = 0x00B
    UCHAR PhysicalDrive;                            //  offset = 0x024
    UCHAR ReservedForBootCode;                      //  offset = 0x025
    UCHAR Unused[2];                                //  offset = 0x026
    LARGE_INTEGER NumberSectors;                    //  offset = 0x028
    LCN MftStartLcn;                                //  offset = 0x030
    LCN Mft2StartLcn;                               //  offset = 0x038
    CHAR ClustersPerFileRecordSegment;              //  offset = 0x040
    UCHAR Unused1[3];                               //  offset = 0x041
    CHAR DefaultClustersPerIndexAllocationBuffer;   //  offset = 0x044
    UCHAR Unused2[3];                               //  offset = 0x047
    LARGE_INTEGER SerialNumber;                     //  offset = 0x048
    ULONG Checksum;                                 //  offset = 0x050
    UCHAR BootStrap[0x200-0x054];                   //  offset = 0x054
} PACKED_BOOT_SECTOR;                               //  sizeof = 0x200
typedef PACKED_BOOT_SECTOR *PPACKED_BOOT_SECTOR;

//
// If the ClustersPerFileRecordSegment entry is zero, we use the
// following as the size of our frs's regardless of the cluster
// size.
//

#define SMALL_FRS_SIZE  (1024)

//
// If the DefaultClustersPerIndexAllocationBuffer entry is zero,
// we use the following as the size of our buffers regardless of
// the cluster size.
//

#define SMALL_INDEX_BUFFER_SIZE  (4096)



// Update sequence array structures--see ntos\inc\cache.h for
// description.

#define SEQUENCE_NUMBER_STRIDE           (512)

DEFINE_TYPE( USHORT, UPDATE_SEQUENCE_NUMBER );

typedef struct _UNTFS_MULTI_SECTOR_HEADER {

    UCHAR Signature[4];
    USHORT UpdateSequenceArrayOffset;   // byte offset
    USHORT UpdateSequenceArraySize;     // number of Update Sequence Numbers

};

DEFINE_TYPE( _UNTFS_MULTI_SECTOR_HEADER, UNTFS_MULTI_SECTOR_HEADER );

typedef UPDATE_SEQUENCE_NUMBER UPDATE_SEQUENCE_ARRAY[1];
typedef UPDATE_SEQUENCE_ARRAY *PUPDATE_SEQUENCE_ARRAY;


//
//  File Record Segment.  This is the header that begins every File Record
//  Segment in the Master File Table.
//

typedef struct _FILE_RECORD_SEGMENT_HEADER {

    UNTFS_MULTI_SECTOR_HEADER MultiSectorHeader;
    LSN Lsn;
    USHORT SequenceNumber;
    USHORT ReferenceCount;
    USHORT FirstAttributeOffset;
    USHORT Flags;                   // FILE_xxx flags
    ULONG FirstFreeByte;            // byte-offset
    ULONG BytesAvailable;           // Size of FRS
    FILE_REFERENCE BaseFileRecordSegment;
    USHORT NextAttributeInstance;   // Attribute instance tag for next insert.
    UPDATE_SEQUENCE_ARRAY UpdateArrayForCreateOnly;

};

//
// If the above NextAttributeInstance field exceeds the following
// value, chkdsk will take steps to prevent it from rolling over.
//

#define ATTRIBUTE_INSTANCE_TAG_THRESHOLD        0xf000


DEFINE_TYPE( _FILE_RECORD_SEGMENT_HEADER,   FILE_RECORD_SEGMENT_HEADER );

//
//  FILE_xxx flags.
//

#define FILE_RECORD_SEGMENT_IN_USE       (0x0001)
#define FILE_FILE_NAME_INDEX_PRESENT     (0x0002)
#define FILE_SYSTEM_FILE                 (0x0004)
#define FILE_VIEW_INDEX_PRESENT          (0x0008)

//
//  Define a macro to determine the maximum space available for a
//  single attribute.  For example, this is required when a
//  nonresident attribute has to split into multiple file records -
//  we need to know how much we can squeeze into a single file
//  record.  If this macro has any inaccurracy, it must be in the
//  direction of returning a slightly smaller number than actually
//  required.
//
//      ULONG
//      NtfsMaximumAttributeSize (
//          IN ULONG FileRecordSegmentSize
//          );
//

#define NtfsMaximumAttributeSize(FRSS) (                                               \
    (FRSS) - QuadAlign(sizeof(FILE_RECORD_SEGMENT_HEADER)) -                           \
    QuadAlign((((FRSS) / SEQUENCE_NUMBER_STRIDE) * sizeof(UPDATE_SEQUENCE_NUMBER))) -  \
    QuadAlign(sizeof(ATTRIBUTE_TYPE_CODE))                                             \
)



//
//  Attribute Record.  Logically an attribute has a type, an optional name,
//  and a value, however the storage details make it a little more complicated.
//  For starters, an attribute's value may either be resident in the file
//  record segment itself, on nonresident in a separate data stream.  If it
//  is nonresident, it may actually exist multiple times in multiple file
//  record segments to describe different ranges of VCNs.
//
//  Attribute Records are always aligned on a quad word (64-bit) boundary.
//
//  Note that SIZE_OF_RESIDENT_HEADER and SIZE_OF_NONRESIDENT_HEADER
//  must correspond to the ATTRIBUTE_RECORD_HEADER structure.

#define SIZE_OF_RESIDENT_HEADER 24
#define SIZE_OF_NONRESIDENT_HEADER 64

typedef struct _ATTRIBUTE_RECORD_HEADER {

    ATTRIBUTE_TYPE_CODE TypeCode;
    ULONG RecordLength;
    UCHAR FormCode;
    UCHAR NameLength;       // length in characters
    USHORT NameOffset;      // byte offset from start of record
    USHORT Flags;           // ATTRIBUTE_xxx flags.
    USHORT Instance;        // FRS-unique attribute instance tag

    union {

        //
        //  Resident Form.  Attribute resides in file record segment.
        //

        struct {

            ULONG ValueLength;          // in bytes
            USHORT ValueOffset;         // byte offset from start of record
            UCHAR ResidentFlags;        // RESIDENT_FORM_xxx Flags.
            UCHAR Reserved;

        } Resident;

        //
        //  Nonresident Form.  Attribute resides in separate stream.
        //

        struct {

            VCN2 LowestVcn;
            VCN2 HighestVcn;
            USHORT MappingPairsOffset;  // byte offset from start of record
            UCHAR CompressionUnit;
            UCHAR Reserved[5];
            LARGE_INTEGER AllocatedLength;
            LARGE_INTEGER FileSize;
            LARGE_INTEGER ValidDataLength;
            LARGE_INTEGER TotalAllocated;

            //
            //  Mapping Pairs Array follows, starting at the offset given
            //  above.  See the extended comment in ntfs.h.
            //

        } Nonresident;

    } Form;

};

DEFINE_TYPE( _ATTRIBUTE_RECORD_HEADER, ATTRIBUTE_RECORD_HEADER );


//
//  Attribute Form Codes
//

#define RESIDENT_FORM                    (0x00)
#define NONRESIDENT_FORM                 (0x01)

//
//  Define Attribute Flags
//

#define ATTRIBUTE_FLAG_COMPRESSION_MASK  (0x00FF)

//
//  RESIDENT_FORM_xxx flags
//

//
//  This attribute is indexed.
//

#define RESIDENT_FORM_INDEXED            (0x01)

//
//  The maximum attribute name length is 255 (in chars)
//

#define NTFS_MAX_ATTR_NAME_LEN           (255)


//
// Macros for manipulating mapping pair count byte.
//

INLINE
UCHAR
ComputeMappingPairCountByte(
    IN  UCHAR   VcnLength,
    IN  UCHAR   LcnLength
    )
{
    return VcnLength + 16*LcnLength;
}

INLINE
UCHAR
VcnBytesFromCountByte(
    IN  UCHAR   CountByte
    )
{
    return CountByte%16;
}

INLINE
UCHAR
LcnBytesFromCountByte(
    IN  UCHAR   CountByte
    )
{
    return CountByte/16;
}


//
//  Standard Information Attribute.  This attribute is present in every
//  base file record, and must be resident.
//

typedef struct _STANDARD_INFORMATION {

    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastModificationTime;      // refers to $DATA attribute
    LARGE_INTEGER LastChangeTime;            // any attribute
    LARGE_INTEGER LastAccessTime;
    ULONG FileAttributes;
    ULONG MaximumVersions;
    ULONG VersionNumber;
    ULONG Reserved;

};

DEFINE_TYPE( _STANDARD_INFORMATION, STANDARD_INFORMATION );

typedef struct _STANDARD_INFORMATION2 {

    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastModificationTime;      // refers to $DATA attribute
    LARGE_INTEGER LastChangeTime;            // any attribute
    LARGE_INTEGER LastAccessTime;
    ULONG FileAttributes;
    ULONG MaximumVersions;
    ULONG VersionNumber;
    ULONG ClassId;
    ULONG OwnerId;
    ULONG SecurityId;
    LARGE_INTEGER QuotaCharged;
    LARGE_INTEGER Usn;

};

DEFINE_TYPE( _STANDARD_INFORMATION2, STANDARD_INFORMATION2 );

#define SIZEOF_NEW_STANDARD_INFORMATION  (0x48)

//
//  Define the file attributes, starting with the Fat attributes.
//

#define FAT_DIRENT_ATTR_READ_ONLY        (0x01)
#define FAT_DIRENT_ATTR_HIDDEN           (0x02)
#define FAT_DIRENT_ATTR_SYSTEM           (0x04)
#define FAT_DIRENT_ATTR_VOLUME_ID        (0x08)
#define FAT_DIRENT_ATTR_ARCHIVE          (0x20)
#define FAT_DIRENT_ATTR_DEVICE           (0x40)

#define DUP_FILE_NAME_INDEX_PRESENT      (0x10000000)
#define DUP_VIEW_INDEX_PRESENT           (0x20000000)

//
//  Attribute List.  Because there is not a special header that goes
//  before the list of attribute list entries we do not need to declare
//  an attribute list header
//

//
//  The Attributes List attribute is an ordered-list of quad-word
//  aligned ATTRIBUTE_LIST_ENTRY records.  It is ordered first by
//  Attribute Type Code, and then by Attribute Name (if present).  No two
//  attributes may exist with the same type code, name and LowestVcn.  This
//  also means that at most one occurrence of a given Attribute Type Code
//  without a name may exist.
//
//  To binary search this attribute, it is first necessary to make a quick
//  pass through it and form a list of pointers, since the optional name
//  makes it variable-length.
//

typedef struct _ATTRIBUTE_LIST_ENTRY {

    ATTRIBUTE_TYPE_CODE AttributeTypeCode;
    USHORT RecordLength;                    // length in bytes
    UCHAR AttributeNameLength;              // length in characters
    UCHAR AttributeNameOffset;              // offset from beginning of struct
    VCN LowestVcn;
    MFT_SEGMENT_REFERENCE SegmentReference;
    USHORT Instance;                        // FRS-unique instance tag
    WCHAR AttributeName[1];

};

DEFINE_TYPE( _ATTRIBUTE_LIST_ENTRY, ATTRIBUTE_LIST_ENTRY );

BOOLEAN
operator <= (
    IN  RCATTRIBUTE_LIST_ENTRY  Left,
    IN  RCATTRIBUTE_LIST_ENTRY  Right
    );


typedef struct _DUPLICATED_INFORMATION {

    BIG_INT CreationTime;         // File creation
    BIG_INT LastModificationTime; // Last change of $DATA attribute
    BIG_INT LastChangeTime;       // Last change of any attribute
    BIG_INT LastAccessTime;       // see ntfs.h for notes
    BIG_INT AllocatedLength;      // File allocated size
    BIG_INT FileSize;             // File actual size
    ULONG FileAttributes;
    USHORT PackedEaSize;
    USHORT Reserved;

};

DEFINE_TYPE( _DUPLICATED_INFORMATION, DUPLICATED_INFORMATION );

//
//  This bit is duplicated from the file record, to indicate that
//  this file has a file name index present (is a "directory").
//

#define DUP_FILE_NAME_INDEX_PRESENT      (0x10000000)

//
//  File Name attribute.  A file has one File Name attribute for every
//  directory it is entered into (hard links).
//

typedef struct _FILE_NAME {

    FILE_REFERENCE ParentDirectory;
    DUPLICATED_INFORMATION Info;
    UCHAR FileNameLength;               // length in characters
    UCHAR Flags;                        // FILE_NAME_xxx flags
    WCHAR FileName[1];                  // First character of file name

};

DEFINE_TYPE( _FILE_NAME, FILE_NAME );

// NtfsFileNameGetLength evaluates to the length of a FILE_NAME attribute
// value, which is the FILE_NAME structure plus the length of the name.
// Note that this is the actual length, not the quad-aligned length.

#define NtfsFileNameGetLength(p) ( FIELD_OFFSET( FILE_NAME, FileName ) \
                                    + ((p)->FileNameLength * sizeof( WCHAR )) )

// NtfsFileNameGetName gets the pointer to the name in a FILE_NAME
// structure, which in turn is the value of an NTFS $FILE_NAME attribute.

#define NtfsFileNameGetName(p) ( &((p)->FileName[0]) )


//
//  File Name flags
//

#define FILE_NAME_NTFS                   (0x01)
#define FILE_NAME_DOS                    (0x02)

//
//  The maximum file name length is 255 (in chars)
//

#define NTFS_MAX_FILE_NAME_LENGTH       (255)


//
//  The maximum number of links on a file is 1024
//

#define NTFS_MAX_LINK_COUNT             (1024)


// This is the name of all attributes associated with an index
// over $FILE_NAME:

#define FileNameIndexNameData   "$I30"

//
//  Object ID attribute.
//

typedef struct _OBJECT_ID {
    char    x[16];
};

DEFINE_TYPE( _OBJECT_ID, OBJECT_ID );

typedef struct _OBJID_INDEX_ENTRY_VALUE {
    OBJECT_ID               key;
    MFT_SEGMENT_REFERENCE   SegmentReference;
    char                    extraInfo[16];
};

DEFINE_TYPE( _OBJID_INDEX_ENTRY_VALUE, OBJID_INDEX_ENTRY_VALUE );

//
// Object Id File Name to appear in the \$Extend directory
//

#define ObjectIdFileName                "$ObjId"
#define LObjectIdFileName               L"$ObjId"

#define ObjectIdIndexNameData   "$O"


//
//  Volume Version attribute.
//

typedef struct _VOLUME_VERSION {

    ULONG CurrentVersion;
    ULONG MaximumVersions;

};

DEFINE_TYPE( _VOLUME_VERSION, VOLUME_VERSION );


//
//  Security Descriptor attribute.  This is just a normal attribute stream
//  containing a security descriptor as defined by NT security and is
//  really treated pretty opaque by NTFS.
//
#define SecurityIdIndexNameData                 "$SII"
#define SecurityDescriptorHashIndexNameData     "$SDH"
#define SecurityDescriptorStreamNameData        "$SDS"

// Security Descriptor Stream data is organized into chunks of 256K bytes
// and it contains a mirror copy of each security descriptor.  When writing
// to a security descriptor at location X, another copy will be written at
// location (X+256K).  When writing a security descriptor that will
// cross the 256K boundary, the pointer will be advanced by 256K to skip
// over the mirror portion.

#define SecurityDescriptorsBlockSize     (0x40000)       // 256K
#define SecurityDescriptorMaxSize        (0x20000)       // 128K


//  Volume Name attribute.  This attribute is just a normal attribute stream
//  containing the unicode characters that make up the volume label.  It
//  is an attribute of the Volume Dasd File.
//


//
//  Volume Information attribute.  This attribute is only intended to be
//  used on the Volume DASD file.
//

typedef struct _VOLUME_INFORMATION {

    LARGE_INTEGER Reserved;

    //
    //  Major and minor version number of NTFS on this volume, starting
    //  with 1.0.  The major and minor version numbers are set from the
    //  major and minor version of the Format and NTFS implementation for
    //  which they are initialized.  The policy for incementing major and
    //  minor versions will always be decided on a case by case basis, however,
    //  the following two paragraphs attempt to suggest an approximate strategy.
    //
    //  The major version number is incremented if/when a volume format
    //  change is made which requires major structure changes (hopefully
    //  never?).  If an implementation of NTFS sees a volume with a higher
    //  major version number, it should refuse to mount the volume.  If a
    //  newer implementation of NTFS sees an older major version number,
    //  it knows the volume cannot be accessed without performing a one-time
    //  conversion.
    //
    //  The minor version number is incremented if/when minor enhancements
    //  are made to a major version, which potentially support enhanced
    //  functionality through additional file or attribute record fields,
    //  or new system-defined files or attributes.  If an older implementation
    //  of NTFS sees a newer minor version number on a volume, it may issue
    //  some kind of warning, but it will proceed to access the volume - with
    //  presumably some degradation in functionality compared to the version
    //  of NTFS which initialized the volume.  If a newer implementation of
    //  NTFS sees a volume with an older minor version number, it may issue
    //  a warning and proceed.  In this case, it may choose to increment the
    //  minor version number on the volume and begin full or incremental
    //  upgrade of the volume on an as-needed basis.  It may also leave the
    //  minor version number unchanged, until some sort of explicit directive
    //  from the user specifies that the minor version should be updated.
    //

    UCHAR MajorVersion;
    UCHAR MinorVersion;

    //
    //  VOLUME_xxx flags.
    //

    USHORT VolumeFlags;

} VOLUME_INFORMATION;
typedef VOLUME_INFORMATION *PVOLUME_INFORMATION;

//  Current version number:
//
#define NTFS_CURRENT_MAJOR_VERSION  1
#define NTFS_CURRENT_MINOR_VERSION  1

//
//  Volume is dirty
//

#define VOLUME_DIRTY                     (0x0001)
#define VOLUME_RESIZE_LOG_FILE           (0x0002)


//
//  Common Index Header for Index Root and Index Allocation Buffers.
//  This structure is used to locate the Index Entries and describe the free
//  space in either of the two structures above.
//

typedef struct _INDEX_HEADER {

    //
    //  Offset from the start of this structure to the first Index Entry.
    //

    ULONG FirstIndexEntry;

    //
    //  Offset from the start of this structure to the first (quad-word aligned)
    //  free byte.
    //

    ULONG FirstFreeByte;

    //
    //  Total number of bytes available, from the start of this structure.
    //  In the Index Root, this number must always be equal to FirstFreeByte,
    //  as the total attribute record will be grown and shrunk as required.
    //

    ULONG BytesAvailable;

    //
    //  INDEX_xxx flags.
    //

    UCHAR Flags;

    //
    //  Reserved to round up to quad word boundary.
    //

    UCHAR Reserved[3];

} INDEX_HEADER;
typedef INDEX_HEADER *PINDEX_HEADER;

//
//  INDEX_xxx flags
//

//
//  This Index or Index Allocation buffer is an intermediate node, as opposed to
//  a leaf in the Btree.  All Index Entries will have a Vcn down pointer.
//

#define INDEX_NODE                       (0x01)


//
//  Index Root attribute.  The index attribute consists of an index
//  header record followed by one or more index entries.
//

typedef struct _INDEX_ROOT {

    ATTRIBUTE_TYPE_CODE IndexedAttributeType;
    COLLATION_RULE CollationRule;
    ULONG BytesPerIndexBuffer;
    UCHAR ClustersPerIndexBuffer;
    UCHAR Reserved[3];

    //
    //  Index Header to describe the Index Entries which follow
    //

    INDEX_HEADER IndexHeader;

} INDEX_ROOT;
typedef INDEX_ROOT *PINDEX_ROOT;

//
//  Index Allocation record is used for non-root clusters of the b-tree
//  Each non root cluster is contained in the data part of the index
//  allocation attribute.  Each cluster starts with an index allocation list
//  header and is followed by one or more index entries.
//

typedef struct _INDEX_ALLOCATION_BUFFER {

    //
    //  Multi-Sector Header as defined by the Cache Manager.  This structure
    //  will always contain the signature "INDX" and a description of the
    //  location and size of the Update Sequence Array.
    //

    UNTFS_MULTI_SECTOR_HEADER MultiSectorHeader;

    //
    //  Log File Sequence Number of last logged update to this Index Allocation
    //  Buffer.
    //

    LSN Lsn;

    VCN ThisVcn;


    //
    //  Index Header to describe the Index Entries which follow
    //

    INDEX_HEADER IndexHeader;

    //
    //  Update Sequence Array to protect multi-sector transfers of the
    //  Index Allocation Bucket.
    //

    UPDATE_SEQUENCE_ARRAY UpdateSequenceArray;

} INDEX_ALLOCATION_BUFFER;
typedef INDEX_ALLOCATION_BUFFER *PINDEX_ALLOCATION_BUFFER;


//
//  Index Entry.  This structure is common to both the resident index list
//  attribute and the Index Allocation records
//

typedef struct _INDEX_ENTRY {

    //
    //  Define a union to distinguish directory indices from view indices
    //

    union {

        //
        //  Reference to file containing the attribute with this
        //  attribute value.
        //

        FILE_REFERENCE FileReference;                               //  offset = 0x000

        //
        //  For views, describe the Data Offset and Length in bytes
        //

        struct {

            USHORT DataOffset;                                      //  offset = 0x000
            USHORT DataLength;                                      //  offset = 0x001
            ULONG ReservedForZero;                                  //  offset = 0x002
        };
    };

    //
    //  Length of this index entry, in bytes.
    //

    USHORT Length;

    //
    //  Length of attribute value, in bytes.  The attribute value immediately
    //  follows this record.
    //

    USHORT AttributeLength;

    //
    //  INDEX_ENTRY_xxx Flags.
    //

    USHORT Flags;

    //
    //  Reserved to round to quad-word boundary.
    //

    USHORT Reserved;

    //
    //  If this Index Entry is an intermediate node in the tree, as determined
    //  by the INDEX_xxx flags, then a VCN  is stored at the end of this
    //  entry at Length - sizeof(VCN).
    //

};

DEFINE_TYPE( _INDEX_ENTRY, INDEX_ENTRY );


#define GetDownpointer( x ) \
            (*((PVCN)((PBYTE)(x) + (x)->Length - sizeof(VCN))))

#define GetIndexEntryValue( x ) \
            ((PBYTE)(x)+sizeof(INDEX_ENTRY))

#define GetNextEntry( x ) \
            ((PINDEX_ENTRY)( (PBYTE)(x)+(x)->Length ))

CONST UCHAR NtfsIndexLeafEndEntrySize = QuadAlign( sizeof(INDEX_ENTRY) );

//
//  INDEX_ENTRY_xxx flags
//

//
//  This entry is currently in the intermediate node form, i.e., it has a
//  Vcn at the end.
//

#define INDEX_ENTRY_NODE                 (0x0001)

//
//  This entry is the special END record for the Index or Index Allocation buffer.
//

#define INDEX_ENTRY_END                  (0x0002)


//
//  Define the struture of the quota data in the quota index.  The key for
//  the quota index is the 32 bit owner id.
//

typedef struct _QUOTA_USER_DATA {
    ULONG QuotaVersion;
    ULONG QuotaFlags;
    ULONGLONG QuotaThreshold;
    ULONGLONG QuotaLimit;
    ULONGLONG QuotaUsed;
    ULONGLONG QuotaChangeTime;
    ULONGLONG QuotaExceededTime;
    SID QuotaSid;
} QUOTA_USER_DATA, *PQUOTA_USER_DATA;

//
//  Define the size of the quota user data structure without the quota SID.
//

#define SIZEOF_QUOTA_USER_DATA FIELD_OFFSET(QUOTA_USER_DATA, QuotaSid)

//
//  Define the current version of the quote user data.
//

#define QUOTA_USER_VERSION 1

//
//  Define the quota flags.
//

#define QUOTA_FLAG_DEFAULT_LIMITS           (0x00000001)
#define QUOTA_FLAG_LIMIT_REACHED            (0x00000002)
#define QUOTA_FLAG_ID_DELETED               (0x00000004)
#define QUOTA_FLAG_USER_MASK                (0x00000007)

//
//  The following flags are only stored in the quota defaults index entry.
//

#define QUOTA_FLAG_TRACKING_ENABLED         (0x00000010)
#define QUOTA_FLAG_ENFORCEMENT_ENABLED      (0x00000020)
#define QUOTA_FLAG_TRACKING_REQUESTED       (0x00000040)
#define QUOTA_FLAG_LOG_THRESHOLD            (0x00000080)
#define QUOTA_FLAG_LOG_LIMIT                (0x00000100)
#define QUOTA_FLAG_OUT_OF_DATE              (0x00000200)
#define QUOTA_FLAG_CORRUPT                  (0x00000400)
#define QUOTA_FLAG_PENDING_DELETES          (0x00000800)

//
// Define the quota charge for resident streams.
//

#define QUOTA_RESIDENT_STREAM (1024)

//
//  Define special quota owner ids.
//

#define QUOTA_INVALID_ID        0x00000000
#define QUOTA_DEFAULTS_ID       0x00000001
#define QUOTA_FISRT_USER_ID     0x00000100

//
// Quota File Name to appear in the \$Extend directory
//

#define QuotaFileName                   "$Quota"
#define LQuotaFileName                  L"$Quota"

//
// Quota Index Names
//

#define Sid2UseridQuotaNameData         "$O"
#define Userid2SidQuotaNameData         "$Q"

//
//
//
#define MAXULONGLONG            (0xffffffffffffffff)


//
//  Key structure for Security Hash index
//

typedef struct _SECURITY_HASH_KEY
{
    ULONG   Hash;                           //  Hash value for descriptor
    ULONG   SecurityId;                     //  Security Id (guaranteed unique)
} SECURITY_HASH_KEY, *PSECURITY_HASH_KEY;

//
//  Key structure for Security Id index is simply the SECURITY_ID itself
//

//
//  Header for security descriptors in the security descriptor stream.  This
//  is the data format for all indexes and is part of SharedSecurity
//

typedef struct _SECURITY_DESCRIPTOR_HEADER
{
    SECURITY_HASH_KEY HashKey;              //  Hash value for the descriptor
    ULONGLONG Offset;                       //  offset to beginning of header
    ULONG   Length;                         //  Length in bytes
} SECURITY_DESCRIPTOR_HEADER, *PSECURITY_DESCRIPTOR_HEADER;

typedef struct _SECURITY_ENTRY {
    SECURITY_DESCRIPTOR_HEADER  security_descriptor_header;
    SECURITY_DESCRIPTOR         security;
} SECURITY_ENTRY, *PSECURITY_ENTRY;

#define GETSECURITYDESCRIPTORLENGTH(HEADER)         \
    ((HEADER)->Length - sizeof( SECURITY_DESCRIPTOR_HEADER ))

#define SetSecurityDescriptorLength(HEADER,LENGTH)  \
    ((HEADER)->Length = (LENGTH) + sizeof( SECURITY_DESCRIPTOR_HEADER ))

//
//  Define standard values for well-known security IDs
//

#define SECURITY_ID_INVALID              (0x00000000)
#define SECURITY_ID_FIRST                (0x00000100)


//
//  MFT Bitmap attribute
//
//  The MFT Bitmap is simply a normal attribute stream in which there is
//  one bit to represent the allocation state of each File Record Segment
//  in the MFT.  Bit clear means free, and bit set means allocated.
//
//  Whenever the MFT Data attribute is extended, the MFT Bitmap attribute
//  must also be extended.  If the bitmap is still in a file record segment
//  for the MFT, then it must be extended and the new bits cleared.  When
//  the MFT Bitmap is in the Nonresident form, then the allocation should
//  always be sufficient to store enough bits to describe the MFT, however
//  ValidDataLength insures that newly allocated space to the MFT Bitmap
//  has an initial value of all 0's.  This means that if the MFT Bitmap is
//  extended, the newly represented file record segments are automatically in
//  the free state.
//
//  No structure definition is required; the positional offset of the file
//  record segment is exactly equal to the bit offset of its corresponding
//  bit in the Bitmap.
//

//
//  The utilities attempt to allocate a more disk space than necessary for
//  the initial MFT Bitmap to allow for future growth.
//

#define MFT_BITMAP_INITIAL_SIZE     0x2000              /* bytes of bitmap */


//
//  Symbolic Link attribute  ****TBS
//

typedef struct _SYMBOLIC_LINK {

    LARGE_INTEGER Tbs;

} SYMBOLIC_LINK;
typedef SYMBOLIC_LINK *PSYMBOLIC_LINK;


//
//  Ea Information attribute
//

typedef struct _EA_INFORMATION {

    USHORT PackedEaSize;        // Size of buffer to hold in unpacked form
    USHORT NeedEaCount;         // Count of EA's with NEED_EA bit set
    ULONG UnpackedEaSize;       // Size of buffer to hold in packed form

}  EA_INFORMATION;


typedef EA_INFORMATION *PEA_INFORMATION;

struct PACKED_EA {
    UCHAR   Flag;
    UCHAR   NameSize;
    UCHAR   ValueSize[2];   // Was USHORT.
    CHAR    Name[1];
};

DEFINE_POINTER_TYPES( PACKED_EA );

#define     EA_FLAG_NEED    0x80

//
// SLEAZY_LARGE_INTEGER is used because x86 C8 won't allow us to
// do static init on a union (like LARGE_INTEGER) and we can't use
// BIG_INT for cases where we need to static-init an array with a non-
// default constructor.  The bit pattern must be the same as
// LARGE_INTEGER.
//
typedef struct _SLEAZY_LARGE_INTEGER {
        ULONG LowPart;
        LONG HighPart;
} SLEAZY_LARGE_INTEGER, *PSLEAZY_LARGE_INTEGER;


//
//  Attribute Definition Table
//
//  The following struct defines the columns of this table.  Initially they
//  will be stored as simple records, and ordered by Attribute Type Code.
//

typedef struct _ATTRIBUTE_DEFINITION_COLUMNS {

    //
    //  Unicode attribute name.
    //

    WCHAR AttributeName[64];

    //
    //  Attribute Type Code.
    //

    ATTRIBUTE_TYPE_CODE AttributeTypeCode;

    //
    //  Default Display Rule for this attribute
    //

    DISPLAY_RULE DisplayRule;

    //
    //  Default Collation rule
    //

    COLLATION_RULE CollationRule;

    //
    //  ATTRIBUTE_DEF_xxx flags
    //

    ULONG Flags;

    //
    //  Minimum Length for attribute, if present.
    //

    SLEAZY_LARGE_INTEGER MinimumLength;

    //
    //  Maximum Length for attribute.
    //

    SLEAZY_LARGE_INTEGER MaximumLength;

} ATTRIBUTE_DEFINITION_COLUMNS;

DEFINE_POINTER_TYPES( ATTRIBUTE_DEFINITION_COLUMNS );

//
//  ATTRIBUTE_DEF_xxx flags
//

//
//  This flag is set if the attribute may be indexed.
//

#define ATTRIBUTE_DEF_INDEXABLE          (0x00000002)

//
//  This flag is set if the attribute may occur more than once, such as is
//  allowed for the File Name attribute.
//

#define ATTRIBUTE_DEF_DUPLICATES_ALLOWED (0x00000004)

//
//  This flag is set if the value of the attribute may not be entirely
//  null, i.e., all binary 0's.
//

#define ATTRIBUTE_DEF_MAY_NOT_BE_NULL    (0x00000008)

//
// This attribute must be indexed, and no two attributes may exist with
// the same value in the same file record segment.
//

#define ATTRIBUTE_DEF_MUST_BE_INDEXED    (0x00000010)

//
// This attribute must be named, and no two attributes may exist with
// the same name in the same file record segment.
//

#define ATTRIBUTE_DEF_MUST_BE_NAMED      (0x00000020)

//
// This attribute must be in the Resident Form.
//

#define ATTRIBUTE_DEF_MUST_BE_RESIDENT   (0x00000040)

//
//  Modifications to this attribute should be logged even if the
//  attribute is nonresident.
//

#define ATTRIBUTE_DEF_LOG_NONRESIDENT    (0X00000080)

//
//  The remaining stuff in this file describes some of the lfs data
//  structures; some of these are used by chkdsk, and some are used
//  only by diskedit.
//

typedef struct _MULTI_SECTOR_HEADER {

    //
    // Space for a four-character signature
    //

    UCHAR Signature[4];

    //
    // Offset to Update Sequence Array, from start of structure.  The Update
    // Sequence Array must end before the last USHORT in the first "sector"
    // of size SEQUENCE_NUMBER_STRIDE.  (I.e., with the current constants,
    // the sum of the next two fields must be <= 510.)
    //

    USHORT UpdateSequenceArrayOffset;

    //
    // Size of Update Sequence Array (from above formula)
    //

    USHORT UpdateSequenceArraySize;

} MULTI_SECTOR_HEADER, *PMULTI_SECTOR_HEADER;


typedef struct _LFS_RESTART_PAGE_HEADER {

    //
    //  Cache multisector protection header.
    //

    MULTI_SECTOR_HEADER MultiSectorHeader;

    //
    //  This is the last Lsn found by checkdisk for this volume.
    //

    LSN ChkDskLsn;

    //
    //

    ULONG SystemPageSize;
    ULONG LogPageSize;

    //
    //  Lfs restart area offset.  This is the offset from the start of this
    //  structure to the Lfs restart area.
    //

    USHORT RestartOffset;

    USHORT MinorVersion;
    USHORT MajorVersion;

    //
    // Update Sequence Array.  Used to protect the page blcok.
    //

    UPDATE_SEQUENCE_ARRAY UpdateSequenceArray;

} LFS_RESTART_PAGE_HEADER, *PLFS_RESTART_PAGE_HEADER;

//
//  Log Client Record.  A log client record exists for each client user of
//  the log file.  One of these is in each Lfs restart area.
//

#define LFS_NO_CLIENT                           0xffff
#define LFS_CLIENT_NAME_MAX                     64

typedef struct _LFS_CLIENT_RECORD {

    //
    //  Oldest Lsn.  This is the oldest Lsn that this client requires to
    //  be in the log file.
    //

    LSN OldestLsn;

    //
    //  Client Restart Lsn.  This is the Lsn of the latest client restart
    //  area written to the disk.  A reserved Lsn will indicate that no
    //  restart area exists for this client.
    //

    LSN ClientRestartLsn;

    //
    //
    //  Previous/Next client area.  These are the indexes into an array of
    //  Log Client Records for the previous and next client records.
    //

    USHORT PrevClient;
    USHORT NextClient;

    //
    //  Sequence Number.  Incremented whenever this record is reused.  This
    //  will happen whenever a client opens (reopens) the log file and has
    //  no current restart area.

    USHORT SeqNumber;

    //
    //  Alignment field.
    //

    USHORT AlignWord;

    //
    //  Align the entire record.
    //

    ULONG AlignDWord;

    //
    //  The following fields are used to describe the client name.  A client
    //  name consists of at most 32 Unicode character (64 bytes).  The Log
    //  file service will treat client names as case sensitive.
    //

    ULONG ClientNameLength;

    WCHAR ClientName[LFS_CLIENT_NAME_MAX];

} LFS_CLIENT_RECORD, *PLFS_CLIENT_RECORD;

typedef struct _LFS_RESTART_AREA {

    LSN CurrentLsn;
    USHORT LogClients;
    USHORT ClientFreeList;
    USHORT ClientInUseList;

    USHORT Flags;
    ULONG SeqNumberBits;
    USHORT RestartAreaLength;
    USHORT ClientArrayOffset;
    LONGLONG FileSize;
    ULONG LastLsnDataLength;
    USHORT RecordHeaderLength;
    USHORT LogPageDataOffset;
    LFS_CLIENT_RECORD LogClientArray[1];

} LFS_RESTART_AREA, *PLFS_RESTART_AREA;

#pragma pack()

#endif //  _UNTFS_DEFN_