VirtualBox

source: vbox/trunk/include/iprt/formats/ntfs.h

Last change on this file was 106061, checked in by vboxsync, 8 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.5 KB
Line 
1/* $Id: ntfs.h 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT, NT File System (NTFS).
4 */
5
6/*
7 * Copyright (C) 2017-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37#ifndef IPRT_INCLUDED_formats_ntfs_h
38#define IPRT_INCLUDED_formats_ntfs_h
39#ifndef RT_WITHOUT_PRAGMA_ONCE
40# pragma once
41#endif
42
43#include <iprt/formats/fat.h>
44
45
46/** @defgroup grp_rt_formats_ntfs NT File System (NTFS) structures and definitions
47 * @ingroup grp_rt_formats
48 * @{
49 */
50
51/** Value of the FATBOOTSECTOR::achOemName for an NTFS file system. */
52#define NTFS_OEM_ID_MAGIC "NTFS "
53
54
55/** @name NTFS_MFT_IDX_XXX - Predefined MFT indexes.
56 * @{ */
57#define NTFS_MFT_IDX_MFT 0 /**< The MFT itself. */
58#define NTFS_MFT_IDX_MFT_MIRROR 1 /**< Mirror MFT (partial?). */
59#define NTFS_MFT_IDX_LOG_FILE 2 /**< Journalling log. */
60#define NTFS_MFT_IDX_VOLUME 3 /**< Volume attributes. */
61#define NTFS_MFT_IDX_ATTRIB_DEF 4 /**< Attribute definitions. */
62#define NTFS_MFT_IDX_ROOT 5 /**< The root directory. */
63#define NTFS_MFT_IDX_BITMAP 6 /**< Allocation bitmap. */
64#define NTFS_MFT_IDX_BOOT 7 /**< The boot sector. */
65#define NTFS_MFT_IDX_BAD_CLUSTER 8 /**< Bad cluster table. */
66#define NTFS_MFT_IDX_SECURITY 9 /**< Shared security descriptors (w2k and later). */
67#define NTFS_MFT_IDX_UP_CASE 10 /**< Unicode upper case table. */
68#define NTFS_MFT_IDX_EXTEND 11 /**< Directory containing further system files. */
69#define NTFS_MFT_IDX_FIRST_USER 16 /**< The first user file. */
70/** @} */
71
72/**
73 * NTFS MFT record reference.
74 */
75typedef union NTFSMFTREF
76{
77 /** unsigned 64-bit view. */
78 uint64_t u64;
79 /** unsigned 32-bit view. */
80 uint32_t au32[2];
81 /** unsigned 16-bit view. */
82 uint16_t au16[4];
83
84 /** Structured view. */
85 struct
86 {
87 /** Index of the master file table record. */
88 RT_GCC_EXTENSION uint64_t idxMft : 48;
89 /** MFT record reuse sequence number (for catching dangling references). */
90 RT_GCC_EXTENSION uint64_t uRecReuseSeqNo : 16;
91 } s;
92} NTFSMFTREF;
93AssertCompileSize(NTFSMFTREF, 8);
94/** Pointer to a NTFS MFT record reference. */
95typedef NTFSMFTREF *PNTFSMFTREF;
96/** Pointer to a const NTFS MFT record reference. */
97typedef NTFSMFTREF const *PCNTFSMFTREF;
98
99/** @name NTFSMFTREF_GET_IDX
100 * Gets the MFT index number (host endian) from a MFT reference. */
101/** @name NTFSMFTREF_GET_SEQ
102 * Gets the MFT reuse sequence number (host endian) from a MFT reference. */
103/** @name NTFSMFTREF_SET_IDX
104 * Sets the MFT index number of a MFT reference. */
105/** @name NTFSMFTREF_SET_SEQ
106 * Sets the MFT reuse sequence number of a MFT reference. */
107/** @name NTFSMFTREF_SET
108 * Sets the values of a MFT reference. */
109#ifdef RT_LITTLE_ENDIAN
110# define NTFSMFTREF_GET_IDX(a_pMftRef) ((a_pMftRef)->s.idxMft)
111# define NTFSMFTREF_GET_SEQ(a_pMftRef) ((a_pMftRef)->s.uRecReuseSeqNo)
112# define NTFSMFTREF_SET_SEQ(a_pMftRef, a_uValue) do { (a_pMftRef)->s.uRecReuseSeqNo = (a_uValue); } while (0)
113# define NTFSMFTREF_SET_IDX(a_pMftRef, a_uValue) do { (a_pMftRef)->s.idxMft = (a_uValue); } while (0)
114# define NTFSMFTREF_SET(a_pMftRef, a_idx, a_uSeq) \
115 do { \
116 (a_pMftRef)->s.idxMft = (a_idx); \
117 (a_pMftRef)->s.uRecReuseSeqNo = (a_uSeq); \
118 } while (0)
119#else
120# define NTFSMFTREF_GET_IDX(a_pMftRef) (RT_LE2H_U64((a_pMftRef)->u64) & UINT64_C(0x0000ffffffffffff))
121# define NTFSMFTREF_GET_SEQ(a_pMftRef) RT_LE2H_U16((uint16_t)(a_pMftRef)->u64)
122# define NTFSMFTREF_SET_SEQ(a_pMftRef, a_uValue) do { (a_pMftRef)->au16[3] = RT_H2LE_U16(a_uValue); } while (0)
123# define NTFSMFTREF_SET_IDX(a_pMftRef, a_uValue) \
124 do { \
125 (a_pMftRef)->au32[0] = RT_H2LE_U32((uint32_t)(a_uValue)); \
126 (a_pMftRef)->au16[2] = RT_H2LE_U16((uint16_t)((a_uValue) >> 32)); \
127 } while (0)
128# define NTFSMFTREF_SET(a_pMftRef, a_idx, a_uSeq) \
129 do { \
130 (a_pMftRef)->au32[0] = RT_H2LE_U32((uint32_t)(a_idx)); \
131 (a_pMftRef)->au16[2] = RT_H2LE_U16((uint16_t)((a_idx) >> 32)); \
132 (a_pMftRef)->au16[3] = RT_H2LE_U16((uint16_t)(a_uSeq)); \
133 } while (0)
134#endif
135/** Check that the reference is zero. */
136#define NTFSMFTREF_IS_ZERO(a_pMftRef) ((a_pMftRef)->u64 == 0)
137
138
139/**
140 * NTFS record header.
141 */
142typedef struct NTFSRECHDR
143{
144 /** Magic number (usually ASCII). */
145 uint32_t uMagic;
146 /** Offset of the update sequence array from the start of the record. */
147 uint16_t offUpdateSeqArray;
148 /** Number of entries in the update sequence array. (uint16_t sized entries) */
149 uint16_t cUpdateSeqEntries;
150} NTFSRECHDR;
151AssertCompileSize(NTFSRECHDR, 8);
152/** Pointer to a NTFS record header. */
153typedef NTFSRECHDR *PNTFSRECHDR;
154/** Pointer to a const NTFS record header. */
155typedef NTFSRECHDR const *PCNTFSRECHDR;
156
157/** The multi-sector update sequence stride.
158 * @see https://msdn.microsoft.com/en-us/library/bb470212%28v=vs.85%29.aspx
159 * @see NTFSRECHDR::offUpdateSeqArray, NTFSRECHDR::cUpdateSeqEntries
160 */
161#define NTFS_MULTI_SECTOR_STRIDE 512
162
163
164/**
165 * NTFS file record (in the MFT).
166 */
167typedef struct NTFSRECFILE
168{
169 /** 0x00: Header with NTFSREC_MAGIC_FILE. */
170 NTFSRECHDR Hdr;
171 /** 0x08: Log file sequence number. */
172 uint64_t uLsn;
173 /** 0x10: MFT record reuse sequence number (for dangling MFT references). */
174 uint16_t uRecReuseSeqNo;
175 /** 0x12: Number of hard links. */
176 uint16_t cLinks;
177 /** 0x14: Offset of the first attribute (relative to start of record). */
178 uint16_t offFirstAttrib;
179 /** 0x16: Record flags (NTFSRECFILE_F_XXX). */
180 uint16_t fFlags;
181 /** 0x18: Number of byte in use in this MFT record. */
182 uint32_t cbRecUsed;
183 /** 0x1c: The MFT record size. */
184 uint32_t cbRecSize;
185 /** 0x20: Reference to the base MFT record. */
186 NTFSMFTREF BaseMftRec;
187 /** 0x28: Next attribute instance number. */
188 uint16_t idNextAttrib;
189 /** 0x2a: Padding if NTFS 3.1+, update sequence array if older. */
190 uint16_t uPaddingOrUsa;
191 /** 0x2c: MFT index of this record. */
192 uint32_t idxMftSelf;
193} NTFSRECFILE;
194AssertCompileSize(NTFSRECFILE, 0x30);
195/** Pointer to a NTFS file record. */
196typedef NTFSRECFILE *PNTFSRECFILE;
197/** Pointer to a const NTFS file record. */
198typedef NTFSRECFILE const *PCNTFSRECFILE;
199
200
201/** NTFS 'FILE' record magic value. */
202#define NTFSREC_MAGIC_FILE RT_H2LE_U32_C(UINT32_C(0x454c4946))
203
204/** @name NTFSRECFILE_F_XXX - NTFSRECFILE::fFlags.
205 * @{ */
206/** MFT record is in use. */
207#define NTFSRECFILE_F_IN_USE RT_H2LE_U16_C(UINT16_C(0x0001))
208/** Directory record. */
209#define NTFSRECFILE_F_DIRECTORY RT_H2LE_U16_C(UINT16_C(0x0002))
210/** @} */
211
212
213/** @name NTFS_AT_XXX - Attribute types
214 * @{ */
215#define NTFS_AT_UNUSED RT_H2LE_U32_C(UINT32_C(0x00000000))
216/** NTFSATSTDINFO */
217#define NTFS_AT_STANDARD_INFORMATION RT_H2LE_U32_C(UINT32_C(0x00000010))
218/** NTFSATLISTENTRY */
219#define NTFS_AT_ATTRIBUTE_LIST RT_H2LE_U32_C(UINT32_C(0x00000020))
220/** NTFSATFILENAME */
221#define NTFS_AT_FILENAME RT_H2LE_U32_C(UINT32_C(0x00000030))
222#define NTFS_AT_OBJECT_ID RT_H2LE_U32_C(UINT32_C(0x00000040))
223#define NTFS_AT_SECURITY_DESCRIPTOR RT_H2LE_U32_C(UINT32_C(0x00000050))
224#define NTFS_AT_VOLUME_NAME RT_H2LE_U32_C(UINT32_C(0x00000060))
225/** NTFSATVOLUMEINFO */
226#define NTFS_AT_VOLUME_INFORMATION RT_H2LE_U32_C(UINT32_C(0x00000070))
227#define NTFS_AT_DATA RT_H2LE_U32_C(UINT32_C(0x00000080))
228/** NTFSATINDEXROOT */
229#define NTFS_AT_INDEX_ROOT RT_H2LE_U32_C(UINT32_C(0x00000090))
230#define NTFS_AT_INDEX_ALLOCATION RT_H2LE_U32_C(UINT32_C(0x000000a0))
231#define NTFS_AT_BITMAP RT_H2LE_U32_C(UINT32_C(0x000000b0))
232#define NTFS_AT_REPARSE_POINT RT_H2LE_U32_C(UINT32_C(0x000000c0))
233#define NTFS_AT_EA_INFORMATION RT_H2LE_U32_C(UINT32_C(0x000000d0))
234#define NTFS_AT_EA RT_H2LE_U32_C(UINT32_C(0x000000e0))
235#define NTFS_AT_PROPERTY_SET RT_H2LE_U32_C(UINT32_C(0x000000f0))
236#define NTFS_AT_LOGGED_UTILITY_STREAM RT_H2LE_U32_C(UINT32_C(0x00000100))
237#define NTFS_AT_FIRST_USER_DEFINED RT_H2LE_U32_C(UINT32_C(0x00001000))
238#define NTFS_AT_END RT_H2LE_U32_C(UINT32_C(0xffffffff))
239/** @} */
240
241/** @name NTFS_AF_XXX - Attribute flags.
242 * @{ */
243#define NTFS_AF_COMPR_FMT_NONE RT_H2LE_U16_C(UINT16_C(0x0000))
244/** See RtlCompressBuffer / COMPRESSION_FORMAT_LZNT1. */
245#define NTFS_AF_COMPR_FMT_LZNT1 RT_H2LE_U16_C(UINT16_C(0x0001))
246/** See RtlCompressBuffer / COMPRESSION_FORMAT_XPRESS_HUFF. */
247#define NTFS_AF_COMPR_FMT_XPRESS RT_H2LE_U16_C(UINT16_C(0x0002))
248/** See RtlCompressBuffer / COMPRESSION_FORMAT_XPRESS_HUFF. */
249#define NTFS_AF_COMPR_FMT_XPRESS_HUFF RT_H2LE_U16_C(UINT16_C(0x0003))
250#define NTFS_AF_COMPR_FMT_MASK RT_H2LE_U16_C(UINT16_C(0x00ff))
251#define NTFS_AF_ENCRYPTED RT_H2LE_U16_C(UINT16_C(0x4000))
252#define NTFS_AF_SPARSE RT_H2LE_U16_C(UINT16_C(0x8000))
253/** @} */
254
255/**
256 * NTFS attribute header.
257 *
258 * This has three forms:
259 * - Resident
260 * - Non-resident, no compression
261 * - Non-resident, compressed.
262 *
263 * Each form translates to a different header size.
264 */
265typedef struct NTFSATTRIBHDR
266{
267 /** 0x00: Attribute type (NTFS_AT_XXX). */
268 uint32_t uAttrType;
269 /** 0x04: Length of this attribute (resident part). */
270 uint32_t cbAttrib;
271 /** 0x08: Set (1) if non-resident attribute, 0 if resident. */
272 uint8_t fNonResident;
273 /** 0x09: Attribute name length (can be zero). */
274 uint8_t cwcName;
275 /** 0x0a: Offset of the name string (relative to the start of this header). */
276 uint16_t offName;
277 /** 0x0c: NTFS_AF_XXX. */
278 uint16_t fFlags;
279 /** 0x0e: Attribute instance number. Unique within the MFT record. */
280 uint16_t idAttrib;
281 /** 0x10: Data depending on the fNonResident member value. */
282 union
283 {
284 /** Resident attributes. */
285 struct
286 {
287 /** 0x10: Attribute value length. */
288 uint32_t cbValue;
289 /** 0x14: Offset of the value (relative to the start of this header). */
290 uint16_t offValue;
291 /** 0x16: NTFS_RES_AF_XXX. */
292 uint8_t fFlags;
293 /** 0x17: Reserved. */
294 uint8_t bReserved;
295 } Res;
296
297 /** Non-resident attributes. */
298 struct
299 {
300 /** 0x10: The first virtual cluster containing data.
301 *
302 * This is mainly for internal checking when the run list doesn't fit in one
303 * MFT record. It can also be used to avoid recording a sparse run at the
304 * beginning of the data covered by this attribute record. */
305 int64_t iVcnFirst;
306 /** 0x18: The last virtual cluster containing data (inclusive). */
307 int64_t iVcnLast;
308 /** 0x20: Offset of the mapping pair program. This program gives us a mapping
309 * between VNC and LCN for the attribute value. */
310 uint16_t offMappingPairs;
311 /** 0x22: Power of two compression unit size in clusters (cbCluster << uCompessionUnit).
312 * Zero means uncompressed. */
313 uint8_t uCompressionUnit;
314 /** 0x23: Reserved */
315 uint8_t abReserved[5];
316 /** 0x28: Allocated size (rouneded to cluster).
317 * @note Only set in the first attribute record (iVcnFirst == 0). */
318 int64_t cbAllocated;
319 /** 0x30: The exact length of the data.
320 * @note Only set in the first attribute record (iVcnFirst == 0). */
321 int64_t cbData;
322 /** 0x38: The length of the initialized data. (Not necessarily
323 * rounded up to cluster size.)
324 * @note Only set in the first attribute record (iVcnFirst == 0). */
325 int64_t cbInitialized;
326 /** 0x40: Compressed size if compressed, otherwise absent. */
327 int64_t cbCompressed;
328 } NonRes;
329 } u;
330} NTFSATTRIBHDR;
331AssertCompileSize(NTFSATTRIBHDR, 0x48);
332AssertCompileMemberOffset(NTFSATTRIBHDR, u.Res, 0x10);
333AssertCompileMemberOffset(NTFSATTRIBHDR, u.Res.bReserved, 0x17);
334AssertCompileMemberOffset(NTFSATTRIBHDR, u.NonRes, 0x10);
335AssertCompileMemberOffset(NTFSATTRIBHDR, u.NonRes.cbCompressed, 0x40);
336/** Pointer to a NTFS attribute header. */
337typedef NTFSATTRIBHDR *PNTFSATTRIBHDR;
338/** Pointer to a const NTFS attribute header. */
339typedef NTFSATTRIBHDR const *PCNTFSATTRIBHDR;
340
341/** @name NTFSATTRIBHDR_SIZE_XXX - Attribute header sizes.
342 * @{ */
343/** Attribute header size for resident values. */
344#define NTFSATTRIBHDR_SIZE_RESIDENT (0x18)
345/** Attribute header size for uncompressed non-resident values. */
346#define NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED (0x40)
347/** Attribute header size for compressed non-resident values. */
348#define NTFSATTRIBHDR_SIZE_NONRES_COMPRESSED (0x48)
349/** @} */
350
351/** Get the pointer to the embedded name from an attribute.
352 * @note ASSUMES the caller check that there is a name. */
353#define NTFSATTRIBHDR_GET_NAME(a_pAttrHdr) ( (PRTUTF16)((uintptr_t)(a_pAttrHdr) + (a_pAttrHdr)->offName) )
354
355/** Get the pointer to resident value.
356 * @note ASSUMES the caller checks that it's resident and valid. */
357#define NTFSATTRIBHDR_GET_RES_VALUE_PTR(a_pAttrHdr) ( (uint8_t *)(a_pAttrHdr) + (a_pAttrHdr)->u.Res.offValue )
358
359
360/** @name NTFS_RES_AF_XXX
361 * @{ */
362/** Attribute is referenced in an index. */
363#define NTFS_RES_AF_INDEXED UINT8_C(0x01)
364/** @} */
365
366/**
367 * Attribute list entry (NTFS_AT_ATTRIBUTE_LIST).
368 *
369 * This is used to deal with a file having attributes in more than one MFT
370 * record. A prominent example is an fragment file (unnamed data attribute)
371 * which mapping pairs doesn't fit in a single MFT record.
372 *
373 * This attribute can be non-resident, however it's mapping pair program must
374 * fit in the base MFT record.
375 */
376typedef struct NTFSATLISTENTRY
377{
378 /** 0x00: Attribute type (NTFS_AT_XXX). */
379 uint32_t uAttrType;
380 /** 0x04: Length of this entry. */
381 uint16_t cbEntry;
382 /** 0x06: Attribute name length (zero if none). */
383 uint8_t cwcName;
384 /** 0x07: Name offset. */
385 uint8_t offName;
386 /** 0x08: The first VNC for this part of the attribute value. */
387 int64_t iVcnFirst;
388 /** 0x10: The MFT record holding the actual attribute. */
389 NTFSMFTREF InMftRec;
390 /** 0x18: Attribute instance number. Unique within the MFT record. */
391 uint16_t idAttrib;
392 /** 0x1a: Maybe where the attribute name starts. */
393 RT_FLEXIBLE_ARRAY_EXTENSION
394 RTUTF16 wszName[RT_FLEXIBLE_ARRAY];
395} NTFSATLISTENTRY;
396AssertCompileMemberOffset(NTFSATLISTENTRY, idAttrib, 0x18);
397/** Pointer to a NTFS attribute list entry. */
398typedef NTFSATLISTENTRY *PNTFSATLISTENTRY;
399/** Pointer to a const NTFS attribute list entry. */
400typedef NTFSATLISTENTRY const *PCNTFSATLISTENTRY;
401
402/** Unaligned minimum entry size (no name). */
403#define NTFSATLISTENTRY_SIZE_MINIMAL 0x1a
404
405
406
407/**
408 * NTFS standard file info attribute (NTFS_AT_STANDARD_INFORMATION).
409 */
410typedef struct NTFSATSTDINFO
411{
412 /** 0x00: Creation timestamp. */
413 int64_t iCreationTime;
414 /** 0x08: Last data modification timestamp. */
415 int64_t iLastDataModTime;
416 /** 0x10: Last MFT record modification timestamp. */
417 int64_t iLastMftModTime;
418 /** 0x18: Last access timestamp. */
419 int64_t iLastAccessTime;
420 /** 0x20: File attributes. */
421 uint32_t fFileAttribs;
422 /** 0x24: Maximum number of file versions allowed.
423 * @note NTFS 3.x, padding in 1.2 */
424 uint32_t cMaxFileVersions;
425 /** 0x28: Current file version number.
426 * @note NTFS 3.x, padding in 1.2 */
427 uint32_t uFileVersion;
428 /** 0x2c: Class ID (whatever that is).
429 * @note NTFS 3.x, padding in 1.2 */
430 uint32_t idClass;
431 /** 0x30: Owner ID.
432 * Translated via $Q index in NTFS_MFT_IDX_EXTENDED/$Quota.
433 * @note NTFS 3.x, not present in 1.2 */
434 uint32_t idOwner;
435 /** 0x34: Security ID. Translated via $SII index and $SDS data stream in
436 * NTFS_MFT_IDX_SECURITY.
437 * @note NTFS 3.x, not present in 1.2 */
438 uint32_t idSecurity;
439 /** 0x38: Total quota charged for this file.
440 * @note NTFS 3.x, not present in 1.2 */
441 uint64_t cbQuotaChared;
442 /** 0x40: Last update sequence number, index into $UsnJrnl.
443 * @note NTFS 3.x, not present in 1.2 */
444 uint64_t idxUpdateSequence;
445} NTFSATSTDINFO;
446AssertCompileSize(NTFSATSTDINFO, 0x48);
447/** Pointer to NTFS standard file info. */
448typedef NTFSATSTDINFO *PNTFSATSTDINFO;
449/** Pointer to const NTFS standard file info. */
450typedef NTFSATSTDINFO const *PCNTFSATSTDINFO;
451
452/** The size of NTFSATSTDINFO in NTFS v1.2 and earlier. */
453#define NTFSATSTDINFO_SIZE_NTFS_V12 (0x30)
454
455/** @name NTFS_FA_XXX - NTFS file attributes (host endian).
456 * @{ */
457#define NTFS_FA_READONLY UINT32_C(0x00000001)
458#define NTFS_FA_HIDDEN UINT32_C(0x00000002)
459#define NTFS_FA_SYSTEM UINT32_C(0x00000004)
460#define NTFS_FA_DIRECTORY UINT32_C(0x00000010)
461#define NTFS_FA_ARCHIVE UINT32_C(0x00000020)
462#define NTFS_FA_DEVICE UINT32_C(0x00000040)
463#define NTFS_FA_NORMAL UINT32_C(0x00000080)
464#define NTFS_FA_TEMPORARY UINT32_C(0x00000100)
465#define NTFS_FA_SPARSE_FILE UINT32_C(0x00000200)
466#define NTFS_FA_REPARSE_POINT UINT32_C(0x00000400)
467#define NTFS_FA_COMPRESSED UINT32_C(0x00000800)
468#define NTFS_FA_OFFLINE UINT32_C(0x00001000)
469#define NTFS_FA_NOT_CONTENT_INDEXED UINT32_C(0x00002000)
470#define NTFS_FA_ENCRYPTED UINT32_C(0x00004000)
471#define NTFS_FA_VALID_FLAGS UINT32_C(0x00007fb7)
472#define NTFS_FA_VALID_SET_FLAGS UINT32_C(0x000031a7)
473#define NTFS_FA_DUP_FILE_NAME_INDEX_PRESENT UINT32_C(0x10000000) /**< This means directory apparently. */
474#define NTFS_FA_DUP_VIEW_INDEX_PRESENT UINT32_C(0x20000000) /**< ?? */
475/** @} */
476
477
478
479/**
480 * NTFS filename attribute (NTFS_AT_FILENAME).
481 */
482typedef struct NTFSATFILENAME
483{
484 /** 0x00: The parent directory MFT record. */
485 NTFSMFTREF ParentDirMftRec;
486 /** 0x08: Creation timestamp. */
487 int64_t iCreationTime;
488 /** 0x10: Last data modification timestamp. */
489 int64_t iLastDataModTime;
490 /** 0x18: Last MFT record modification timestamp. */
491 int64_t iLastMftModTime;
492 /** 0x20: Last access timestamp. */
493 int64_t iLastAccessTime;
494 /** 0x28: Allocated disk space for the unnamed data attribute. */
495 int64_t cbAllocated;
496 /** 0x30: Actual size of unnamed data attribute. */
497 int64_t cbData;
498 /** 0x38: File attributes (NTFS_FA_XXX). */
499 uint32_t fFileAttribs;
500 union
501 {
502 /** 0x3c: Packed EA length. */
503 uint16_t cbPackedEas;
504 /** 0x3c: Reparse tag, if no EAs. */
505 uint32_t uReparseTag;
506 } u;
507 /** 0x40: Filename length in unicode chars. */
508 uint8_t cwcFilename;
509 /** 0x41: Filename type (NTFS_FILENAME_T_XXX). */
510 uint8_t fFilenameType;
511 /** 0x42: The filename. */
512 RT_FLEXIBLE_ARRAY_EXTENSION
513 RTUTF16 wszFilename[RT_FLEXIBLE_ARRAY];
514} NTFSATFILENAME;
515AssertCompileMemberOffset(NTFSATFILENAME, cbData, 0x30);
516AssertCompileMemberOffset(NTFSATFILENAME, u.cbPackedEas, 0x3c);
517AssertCompileMemberOffset(NTFSATFILENAME, u.uReparseTag, 0x3c);
518AssertCompileMemberOffset(NTFSATFILENAME, wszFilename, 0x42);
519/** Pointer to a NTFS filename attribute. */
520typedef NTFSATFILENAME *PNTFSATFILENAME;
521/** Pointer to a const NTFS filename attribute. */
522typedef NTFSATFILENAME const *PCNTFSATFILENAME;
523
524/** @name NTFS_FILENAME_T_XXX - filename types
525 * @{ */
526#define NTFS_FILENAME_T_POSIX 0
527#define NTFS_FILENAME_T_WINDOWS 1
528#define NTFS_FILENAME_T_DOS 2
529#define NTFS_FILENAME_T_WINDOWS_AND_DSO 3
530/** @} */
531
532
533/**
534 * NTFS volume information (NTFS_AT_VOLUME_INFORMATION).
535 *
536 * This is found in the special NTFS_MFT_IDX_VOLUME file.
537 */
538typedef struct NTFSATVOLUMEINFO
539{
540 /** 0x00: Reserved bytes. */
541 uint8_t abReserved[8];
542 /** 0x08: Major NTFS version number. */
543 uint8_t uMajorVersion;
544 /** 0x09: Minor NTFS version number. */
545 uint8_t uMinorVersion;
546 /** 0x0a: Volume flags (NTFS_VOLUME_F_XXX) */
547 uint16_t fFlags;
548} NTFSATVOLUMEINFO;
549AssertCompileSize(NTFSATVOLUMEINFO, 12);
550/** Pointer to NTFS volume information. */
551typedef NTFSATVOLUMEINFO *PNTFSATVOLUMEINFO;
552/** Pointer to const NTFS volume information. */
553typedef NTFSATVOLUMEINFO const *PCNTFSATVOLUMEINFO;
554
555/** @name NTFS_VOLUME_F_XXX
556 * @{ */
557#define NTFS_VOLUME_F_DIRTY RT_H2LE_U16_C(0x0001) /**< Volume is dirty. */
558#define NTFS_VOLUME_F_RESIZE_LOG_FILE RT_H2LE_U16_C(0x0002) /**< */
559#define NTFS_VOLUME_F_UPGRADE_ON_MOUNT RT_H2LE_U16_C(0x0004) /**< */
560#define NTFS_VOLUME_F_MOUNTED_ON_NT4 RT_H2LE_U16_C(0x0008) /**< */
561#define NTFS_VOLUME_F_DELETE_USN_UNDERWAY RT_H2LE_U16_C(0x0010) /**< */
562#define NTFS_VOLUME_F_REPAIR_OBJECT_ID RT_H2LE_U16_C(0x0020) /**< */
563#define NTFS_VOLUME_F_CHKDSK_UNDERWAY RT_H2LE_U16_C(0x4000) /**< */
564#define NTFS_VOLUME_F_MODIFIED_BY_CHKDSK RT_H2LE_U16_C(0x8000) /**< */
565
566#define NTFS_VOLUME_F_KNOWN_MASK RT_H2LE_U16_C(0xc03f)
567#define NTFS_VOLUME_F_MOUNT_READONLY_MASK RT_H2LE_U16_C(0xc027)
568/** @} */
569
570
571/** The attribute name used by the index attributes on NTFS directories,
572 * ASCII stirng variant. */
573#define NTFS_DIR_ATTRIBUTE_NAME "$I30"
574
575/**
576 * NTFS index header.
577 *
578 * This is used by NTFSATINDEXROOT and NTFSATINDEXALLOC as a prelude to the
579 * sequence of entries in a node.
580 */
581typedef struct NTFSINDEXHDR
582{
583 /** 0x00: Offset of the first entry relative to this header. */
584 uint32_t offFirstEntry;
585 /** 0x04: Current index size in bytes, including this header. */
586 uint32_t cbUsed;
587 /** 0x08: Number of bytes allocated for the index (including this header). */
588 uint32_t cbAllocated;
589 /** 0x0c: Flags (NTFSINDEXHDR_F_XXX). */
590 uint8_t fFlags;
591 /** 0x0d: Reserved bytes. */
592 uint8_t abReserved[3];
593 /* NTFSIDXENTRYHDR sequence typically follows here */
594} NTFSINDEXHDR;
595AssertCompileSize(NTFSINDEXHDR, 16);
596/** Pointer to a NTFS index header. */
597typedef NTFSINDEXHDR *PNTFSINDEXHDR;
598/** Pointer to a const NTFS index header. */
599typedef NTFSINDEXHDR const *PCNTFSINDEXHDR;
600
601/** @name NTFSINDEXHDR_F_XXX
602 * @{ */
603/** An internal node (as opposed to a leaf node if clear).
604 * This means that the entries will have trailing node references (VCN). */
605#define NTFSINDEXHDR_F_INTERNAL UINT8_C(0x01)
606/** @} */
607
608/** Gets the pointer to the first entry header for an index. */
609#define NTFSINDEXHDR_GET_FIRST_ENTRY(a_pIndexHdr) \
610 ( (PNTFSIDXENTRYHDR)((uint8_t *)(a_pIndexHdr) + RT_LE2H_U32((a_pIndexHdr)->offFirstEntry)) )
611
612
613/**
614 * NTFS index root node (NTFS_AT_INDEX_ROOT).
615 *
616 * This is a generic index structure, but is most prominently used for
617 * implementating directories. The index is structured like B-tree, meaning
618 * each node contains multiple entries, and each entry contains data regardless
619 * of whether it's a leaf node or not.
620 *
621 * The index is sorted in ascending order according to the collation rules
622 * defined by the root node (NTFSATINDEXROOT::uCollationRules, see also (see
623 * NTFS_COLLATION_XXX).
624 *
625 * @note The root directory contains a '.' entry, others don't.
626 */
627typedef struct NTFSATINDEXROOT
628{
629 /** 0x00: The index type (NTFSATINDEXROOT_TYPE_XXX). */
630 uint32_t uType;
631 /** 0x04: The sorting rules to use (NTFS_COLLATION_XXX). */
632 uint32_t uCollationRules;
633 /** 0x08: Number of bytes in
634 * Index node size (in bytes). */
635 uint32_t cbIndexNode;
636 /** 0x0c: Number of node addresses per node.
637 * This sounds weird right? A subnode is generally addressed as a virtual
638 * cluster when cbIndexNode >= cbCluster, but when clusters are large NTFS uses
639 * 512 bytes chunks.
640 *
641 * (You would've thought it would be simpler to just use cbIndexNode as the
642 * addressing unit, maybe storing the log2 here to avoid a ffs call.) */
643 uint8_t cAddressesPerIndexNode;
644 /** 0x0d: Reserved padding or something. */
645 uint8_t abReserved[3];
646 /** 0x10: Index header detailing the entries that follows. */
647 NTFSINDEXHDR Hdr;
648 /* 0x20: NTFSIDXENTRYHDR sequence typically follows here */
649} NTFSATINDEXROOT;
650AssertCompileSize(NTFSATINDEXROOT, 32);
651/** Pointer to a NTFS index root. */
652typedef NTFSATINDEXROOT *PNTFSATINDEXROOT;
653/** Pointer to a const NTFS index root. */
654typedef NTFSATINDEXROOT const *PCNTFSATINDEXROOT;
655
656/** @name NTFSATINDEXROOT_TYPE_XXX
657 * @{ */
658/** View index. */
659#define NTFSATINDEXROOT_TYPE_VIEW RT_H2LE_U32_C(UINT32_C(0x00000000))
660/** Directory index, NTFSATFILENAME follows NTFSINDEXENTRY. */
661#define NTFSATINDEXROOT_TYPE_DIR RT_H2LE_U32_C(UINT32_C(0x00000030))
662/** @} */
663
664/** @name NTFS_COLLATION_XXX - index sorting rules
665 * @{ */
666/** Little endian binary compare (or plain byte compare if you like). */
667#define NTFS_COLLATION_BINARY RT_H2LE_U32_C(UINT32_C(0x00000000))
668/** Same as NTFS_COLLATION_UNICODE_STRING. */
669#define NTFS_COLLATION_FILENAME RT_H2LE_U32_C(UINT32_C(0x00000001))
670/** Compare the uppercased unicode characters. */
671#define NTFS_COLLATION_UNICODE_STRING RT_H2LE_U32_C(UINT32_C(0x00000002))
672
673/** Single little endian 32-bit unsigned integer value as sort key. */
674#define NTFS_COLLATION_UINT32 RT_H2LE_U32_C(UINT32_C(0x00000010))
675/** Little endian SID value as sort key. */
676#define NTFS_COLLATION_SID RT_H2LE_U32_C(UINT32_C(0x00000011))
677/** Two little endian 32-bit unsigned integer values used as sorting key. */
678#define NTFS_COLLATION_UINT32_PAIR RT_H2LE_U32_C(UINT32_C(0x00000012))
679/** Sequence of little endian 32-bit unsigned integer values used as sorting key. */
680#define NTFS_COLLATION_UINT32_SEQ RT_H2LE_U32_C(UINT32_C(0x00000013))
681/** @} */
682
683
684/**
685 * NTFS index non-root node.
686 */
687typedef struct NTFSATINDEXALLOC
688{
689 /** 0x00: Header with NTFSREC_MAGIC_INDEX_ALLOC. */
690 NTFSRECHDR RecHdr;
691 /** 0x08: Log file sequence number. */
692 uint64_t uLsn;
693 /** 0x10: The node address of this node (for consistency checking and
694 * perhaps data reconstruction).
695 * @see NTFSATINDEXROOT::cAddressesPerIndexNode for node addressing. */
696 int64_t iSelfAddress;
697 /** 0x18: Index header detailing the entries that follows. */
698 NTFSINDEXHDR Hdr;
699 /* 0x28: NTFSIDXENTRYHDR sequence typically follows here */
700} NTFSATINDEXALLOC;
701AssertCompileSize(NTFSATINDEXALLOC, 40);
702/** Pointer to a NTFS index non-root node. */
703typedef NTFSATINDEXALLOC *PNTFSATINDEXALLOC;
704/** Pointer to a const NTFS index non-root node. */
705typedef NTFSATINDEXALLOC const *PCNTFSATINDEXALLOC;
706
707/** NTFS 'INDX' attribute magic value (NTFSATINDEXALLOC).
708 * @todo sort out the record / attribute name clash here. */
709#define NTFSREC_MAGIC_INDEX_ALLOC RT_H2LE_U32_C(UINT32_C(0x58444e49))
710
711
712/**
713 * NTFS index entry header.
714 *
715 * Each entry in a node starts with this header. It is immediately followed by
716 * the key data (NTFSIDXENTRYHDR::cbKey). When
717 *
718 */
719typedef struct NTFSIDXENTRYHDR
720{
721 union
722 {
723 /** 0x00: NTFSATINDEXROOT_TYPE_DIR: Reference to the MFT record being indexed here.
724 * @note This is invalid if NTFSIDXENTRYHDR_F_END is set (no key data). */
725 NTFSMFTREF FileMftRec;
726 /** 0x00: NTFSATINDEXROOT_TYPE_VIEW: Go figure later if necessary. */
727 struct
728 {
729 /** 0x00: Offset to the data relative to this header.
730 * @note This is invalid if NTFSIDXENTRYHDR_F_END is set (no key data). */
731 uint16_t offData;
732 /** 0x02: Size of data at offData.
733 * @note This is invalid if NTFSIDXENTRYHDR_F_END is set (no key data). */
734 uint16_t cbData;
735 /** 0x04: Reserved. */
736 uint32_t uReserved;
737 } View;
738 } u;
739
740 /** 0x08: Size of this entry, 8-byte aligned. */
741 uint16_t cbEntry;
742 /** 0x0a: Key length (unaligned). */
743 uint16_t cbKey;
744 /** 0x0c: Entry flags, NTFSIDXENTRYHDR_F_XXX. */
745 uint16_t fFlags;
746 /** 0x0e: Reserved. */
747 uint16_t uReserved;
748} NTFSIDXENTRYHDR;
749AssertCompileSize(NTFSIDXENTRYHDR, 16);
750/** Pointer to a NTFS index entry header. */
751typedef NTFSIDXENTRYHDR *PNTFSIDXENTRYHDR;
752/** Pointer to a const NTFS index entry header. */
753typedef NTFSIDXENTRYHDR const *PCNTFSIDXENTRYHDR;
754
755/** @name NTFSIDXENTRYHDR_F_XXX - NTFSIDXENTRYHDR::fFlags
756 * @{ */
757/** Indicates an internal node (as opposed to a leaf node).
758 * This indicates that there is a 64-bit integer value at the very end of the
759 * entry (NTFSIDXENTRYHDR::cbEntry - 8) giving the virtual cluster number of the
760 * subnode. The subnode and all its decendants contain keys that are lower than
761 * the key in this entry.
762 */
763#define NTFSIDXENTRYHDR_F_INTERNAL RT_H2LE_U16_C(UINT16_C(0x0001))
764/** Set if special end entry in a node.
765 * This does not have any key data, but can point to a subnode with
766 * higher keys. */
767#define NTFSIDXENTRYHDR_F_END RT_H2LE_U16_C(UINT16_C(0x0002))
768/** @} */
769
770/** Gets the pointer to the next index entry header. */
771#define NTFSIDXENTRYHDR_GET_NEXT(a_pEntryHdr) \
772 ( (PNTFSIDXENTRYHDR)((uintptr_t)(a_pEntryHdr) + RT_LE2H_U16((a_pEntryHdr)->cbEntry)) )
773/** Gets the subnode address from an index entry.
774 * @see NTFSATINDEXROOT::cAddressesPerIndexNode for node addressing.
775 * @note Only invoke when NTFSIDXENTRYHDR_F_INTERNAL is set! */
776#define NTFSIDXENTRYHDR_GET_SUBNODE(a_pEntryHdr) \
777 ( *(int64_t *)((uintptr_t)(a_pEntryHdr) + RT_LE2H_U16((a_pEntryHdr)->cbEntry) - sizeof(int64_t)) )
778
779/** @} */
780
781#endif /* !IPRT_INCLUDED_formats_ntfs_h */
782
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette