ReactOS 0.4.17-dev-1133-gc25e4fd
files.c File Reference
#include "ntfslib.h"
#include "data.h"
#include "refdata.h"
#include <debug.h>
Include dependency graph for files.c:

Go to the source code of this file.

Classes

struct  MK_RUN
 
struct  MK_REC
 
struct  MK_VIEW_ENTRY
 

Macros

#define NDEBUG
 
#define MREC_MFT   0
 
#define MREC_MFTMIRR   1
 
#define MREC_LOGFILE   2
 
#define MREC_VOLUME   3
 
#define MREC_ATTRDEF   4
 
#define MREC_ROOT   5
 
#define MREC_BITMAP   6
 
#define MREC_BOOT   7
 
#define MREC_BADCLUS   8
 
#define MREC_SECURE   9
 
#define MREC_UPCASE   10
 
#define MREC_EXTEND   11
 
#define MREC_QUOTA   24
 
#define MREC_OBJID   25
 
#define MREC_REPARSE   26
 
#define MREC_RMMETA   27 /* $Extend/$RmMetadata */
 
#define MREC_REPAIR   28 /* $RmMetadata/$Repair */
 
#define MREC_DELETED   29 /* $Extend/$Deleted */
 
#define MREC_TXFLOG   30 /* $RmMetadata/$TxfLog */
 
#define MREC_TXF   31 /* $RmMetadata/$Txf */
 
#define MREC_TOPS   32 /* $TxfLog/$Tops */
 
#define MREC_TXFBLF   33 /* $TxfLog/$TxfLog.blf */
 
#define MREC_CONT1   34 /* $TxfLog/$TxfLogContainer...0001 */
 
#define MREC_CONT2   35 /* $TxfLog/$TxfLogContainer...0002 */
 
#define MREC_COUNT   36 /* records materialized in the build buffer */
 
#define FA_HIDDEN   0x0002u
 
#define FA_SYSTEM   0x0004u
 
#define FA_ARCHIVE   0x0020u
 
#define FA_DIR   0x10000000u /* directory (has $I30) */
 
#define FA_VIEW   0x20000000u /* carries a view index ($Extend children / $Secure) */
 
#define COLL_SID   0x11
 
#define COLL_ULONGS   0x13
 
#define USN_VALUE   1
 
#define HOLE_LCN   (~0ULL)
 
#define WR16(p, o, v)   (*(PUSHORT)((PBYTE)(p) + (o)) = (USHORT)(v))
 
#define WR32(p, o, v)   (*(PULONG)((PBYTE)(p) + (o)) = (ULONG)(v))
 
#define WR64(p, o, v)   (*(PULONGLONG)((PBYTE)(p) + (o)) = (ULONGLONG)(v))
 
#define RD16(p, o)   (*(PUSHORT)((PBYTE)(p) + (o)))
 
#define RD32(p, o)   (*(PULONG)((PBYTE)(p) + (o)))
 
#define ALIGN8(x)   (((x) + 7u) & ~7u)
 
#define REC_BUF(n)   (Mft + (ULONG_PTR)(n) * MFT_RECORD_SIZE)
 

Functions

static ULONG MkSignBytes (IN LONGLONG Value)
 
static ULONG MkEncodeRuns (IN const MK_RUN *Runs, IN ULONG RunCount, OUT PBYTE Out)
 
static VOID MkInit (OUT MK_REC *Rec, IN PBYTE Buf, IN ULONG RecordNumber, IN USHORT Flags)
 
static VOID MkSetHardLinks (IN MK_REC *Rec, IN USHORT Count)
 
static VOID MkAddResident (IN OUT MK_REC *Rec, IN ULONG Type, IN LPCWSTR Name, IN BYTE NameChars, IN BYTE ResidentFlags, IN const VOID *Value, IN ULONG ValueLen)
 
static VOID MkAddNonResident (IN OUT MK_REC *Rec, IN ULONG Type, IN LPCWSTR Name, IN BYTE NameChars, IN USHORT Flags, IN const MK_RUN *Runs, IN ULONG RunCount, IN ULONGLONG HighVcn, IN ULONGLONG AllocSize, IN ULONGLONG RealSize, IN ULONGLONG InitSize)
 
static VOID MkFinalize (IN MK_REC *Rec)
 
static VOID MkStdInfo (OUT PBYTE Out, IN ULONG FileAttributes, IN ULONGLONG Now, IN ULONG SecurityId)
 
static VOID MkStdInfoShort (OUT PBYTE Out, IN ULONG FileAttributes, IN ULONGLONG Now)
 
static ULONG MkFileName (OUT PBYTE Out, IN ULONGLONG ParentRef, IN ULONG FileAttributes, IN ULONGLONG AllocSize, IN ULONGLONG RealSize, IN ULONGLONG Now, IN LPCWSTR Name, IN BYTE Namespace)
 
static USHORT MkExtractFileName (IN const BYTE *RecBuf, OUT PBYTE Out)
 
static ULONG MkEmptyI30Root (OUT PBYTE Out)
 
static ULONG MkLargeI30Root (OUT PBYTE Out)
 
static ULONG MkI30RootWithEntries (OUT PBYTE Out, IN const BYTE *Mft, IN const ULONG *Order, IN ULONG Count)
 
static ULONG MkEmptyViewRoot (OUT PBYTE Out, IN ULONG CollationRule)
 
static ULONG MkLargeViewRoot (OUT PBYTE Out, IN ULONG CollationRule)
 
static ULONG MkViewRootN (OUT PBYTE Out, IN ULONG CollationRule, IN const MK_VIEW_ENTRY *Entries, IN ULONG Count)
 
static ULONG MkSecHash (IN const BYTE *Sd, IN ULONG Len)
 
static VOID MkIndxFixup (IN OUT PBYTE Blk, IN ULONG BlkSize)
 
static VOID MkViewIndxBlock (OUT PBYTE Blk, IN const MK_VIEW_ENTRY *Entries, IN ULONG Count)
 
static VOID MkRootIndxBlock (OUT PBYTE Blk, IN const BYTE *Mft, IN const ULONG *Order, IN ULONG Count)
 
static NTSTATUS WriteAt (IN ULONGLONG Lcn, IN PVOID Buffer, IN ULONG Length)
 
static NTSTATUS WritePatternToClusters (IN ULONGLONG Address, IN ULONG ClustersCount, IN BYTE Pattern)
 
static NTSTATUS WriteZerosToClusters (IN ULONGLONG Address, IN ULONG ClustersCount)
 
static NTSTATUS WriteRegion (IN ULONGLONG Lcn, IN ULONG Clusters, IN const VOID *Content, IN ULONG ContentLen)
 
NTSTATUS WriteMetafiles (VOID)
 

Macro Definition Documentation

◆ ALIGN8

#define ALIGN8 (   x)    (((x) + 7u) & ~7u)

Definition at line 83 of file files.c.

◆ COLL_SID

#define COLL_SID   0x11

Definition at line 66 of file files.c.

◆ COLL_ULONGS

#define COLL_ULONGS   0x13

Definition at line 67 of file files.c.

◆ FA_ARCHIVE

#define FA_ARCHIVE   0x0020u

Definition at line 61 of file files.c.

◆ FA_DIR

#define FA_DIR   0x10000000u /* directory (has $I30) */

Definition at line 62 of file files.c.

◆ FA_HIDDEN

#define FA_HIDDEN   0x0002u

Definition at line 59 of file files.c.

◆ FA_SYSTEM

#define FA_SYSTEM   0x0004u

Definition at line 60 of file files.c.

◆ FA_VIEW

#define FA_VIEW   0x20000000u /* carries a view index ($Extend children / $Secure) */

Definition at line 63 of file files.c.

◆ HOLE_LCN

#define HOLE_LCN   (~0ULL)

Definition at line 72 of file files.c.

◆ MREC_ATTRDEF

#define MREC_ATTRDEF   4

Definition at line 36 of file files.c.

◆ MREC_BADCLUS

#define MREC_BADCLUS   8

Definition at line 40 of file files.c.

◆ MREC_BITMAP

#define MREC_BITMAP   6

Definition at line 38 of file files.c.

◆ MREC_BOOT

#define MREC_BOOT   7

Definition at line 39 of file files.c.

◆ MREC_CONT1

#define MREC_CONT1   34 /* $TxfLog/$TxfLogContainer...0001 */

Definition at line 54 of file files.c.

◆ MREC_CONT2

#define MREC_CONT2   35 /* $TxfLog/$TxfLogContainer...0002 */

Definition at line 55 of file files.c.

◆ MREC_COUNT

#define MREC_COUNT   36 /* records materialized in the build buffer */

Definition at line 56 of file files.c.

◆ MREC_DELETED

#define MREC_DELETED   29 /* $Extend/$Deleted */

Definition at line 49 of file files.c.

◆ MREC_EXTEND

#define MREC_EXTEND   11

Definition at line 43 of file files.c.

◆ MREC_LOGFILE

#define MREC_LOGFILE   2

Definition at line 34 of file files.c.

◆ MREC_MFT

#define MREC_MFT   0

Definition at line 32 of file files.c.

◆ MREC_MFTMIRR

#define MREC_MFTMIRR   1

Definition at line 33 of file files.c.

◆ MREC_OBJID

#define MREC_OBJID   25

Definition at line 45 of file files.c.

◆ MREC_QUOTA

#define MREC_QUOTA   24

Definition at line 44 of file files.c.

◆ MREC_REPAIR

#define MREC_REPAIR   28 /* $RmMetadata/$Repair */

Definition at line 48 of file files.c.

◆ MREC_REPARSE

#define MREC_REPARSE   26

Definition at line 46 of file files.c.

◆ MREC_RMMETA

#define MREC_RMMETA   27 /* $Extend/$RmMetadata */

Definition at line 47 of file files.c.

◆ MREC_ROOT

#define MREC_ROOT   5

Definition at line 37 of file files.c.

◆ MREC_SECURE

#define MREC_SECURE   9

Definition at line 41 of file files.c.

◆ MREC_TOPS

#define MREC_TOPS   32 /* $TxfLog/$Tops */

Definition at line 52 of file files.c.

◆ MREC_TXF

#define MREC_TXF   31 /* $RmMetadata/$Txf */

Definition at line 51 of file files.c.

◆ MREC_TXFBLF

#define MREC_TXFBLF   33 /* $TxfLog/$TxfLog.blf */

Definition at line 53 of file files.c.

◆ MREC_TXFLOG

#define MREC_TXFLOG   30 /* $RmMetadata/$TxfLog */

Definition at line 50 of file files.c.

◆ MREC_UPCASE

#define MREC_UPCASE   10

Definition at line 42 of file files.c.

◆ MREC_VOLUME

#define MREC_VOLUME   3

Definition at line 35 of file files.c.

◆ NDEBUG

#define NDEBUG

Definition at line 24 of file files.c.

◆ RD16

#define RD16 (   p,
  o 
)    (*(PUSHORT)((PBYTE)(p) + (o)))

Definition at line 80 of file files.c.

◆ RD32

#define RD32 (   p,
  o 
)    (*(PULONG)((PBYTE)(p) + (o)))

Definition at line 81 of file files.c.

◆ REC_BUF

#define REC_BUF (   n)    (Mft + (ULONG_PTR)(n) * MFT_RECORD_SIZE)

◆ USN_VALUE

#define USN_VALUE   1

Definition at line 70 of file files.c.

◆ WR16

#define WR16 (   p,
  o,
  v 
)    (*(PUSHORT)((PBYTE)(p) + (o)) = (USHORT)(v))

Definition at line 77 of file files.c.

◆ WR32

#define WR32 (   p,
  o,
  v 
)    (*(PULONG)((PBYTE)(p) + (o)) = (ULONG)(v))

Definition at line 78 of file files.c.

◆ WR64

#define WR64 (   p,
  o,
  v 
)    (*(PULONGLONG)((PBYTE)(p) + (o)) = (ULONGLONG)(v))

Definition at line 79 of file files.c.

Function Documentation

◆ MkAddNonResident()

static VOID MkAddNonResident ( IN OUT MK_REC *  Rec,
IN ULONG  Type,
IN LPCWSTR  Name,
IN BYTE  NameChars,
IN USHORT  Flags,
IN const MK_RUN *  Runs,
IN ULONG  RunCount,
IN ULONGLONG  HighVcn,
IN ULONGLONG  AllocSize,
IN ULONGLONG  RealSize,
IN ULONGLONG  InitSize 
)
static

Definition at line 267 of file files.c.

278{
279 PBYTE A = Rec->Buf + Rec->Offset;
280 BYTE MapBuf[64];
281 ULONG MapLen;
282 USHORT DataBase;
283 USHORT MapOff;
284 ULONG AttrLen;
285 ULONG I;
286 BOOLEAN HasCompSize;
287
288 MapLen = MkEncodeRuns(Runs, RunCount, MapBuf);
289
290 /* A compressed (0x0001) or sparse (0x8000) attribute carries an extra
291 * 8-byte "compressed size" field at 0x40, pushing name/runs to 0x48. */
292 HasCompSize = (Flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) != 0;
293 DataBase = (USHORT)(HasCompSize ? 0x48 : 0x40);
294
295 MapOff = (USHORT)ALIGN8((ULONG)DataBase + (ULONG)NameChars * 2);
296 AttrLen = ALIGN8(MapOff + MapLen);
297
298 WR32(A, 0x00, Type);
299 WR32(A, 0x04, AttrLen);
300 A[0x08] = 1; /* non-resident */
301 A[0x09] = NameChars;
302 WR16(A, 0x0A, DataBase); /* name offset */
303 WR16(A, 0x0C, Flags);
304 WR16(A, 0x0E, Rec->NextAttrId++);
305 WR64(A, 0x10, 0); /* starting VCN */
306 WR64(A, 0x18, HighVcn); /* last VCN */
307 WR16(A, 0x20, MapOff);
308 WR16(A, 0x22, 0); /* compression unit */
309 WR32(A, 0x24, 0); /* padding */
310 WR64(A, 0x28, AllocSize);
311 WR64(A, 0x30, RealSize);
312 WR64(A, 0x38, InitSize);
313 if (HasCompSize)
314 WR64(A, 0x40, 0); /* compressed/allocated size (our only sparse stream is all holes) */
315
316 for (I = 0; I < NameChars; I++)
317 WR16(A, DataBase + I * 2, Name[I]);
318 RtlCopyMemory(A + MapOff, MapBuf, MapLen);
319
320 Rec->Offset += AttrLen;
321}
Type
Definition: Type.h:7
unsigned char BOOLEAN
Definition: actypes.h:127
Definition: ehthrow.cxx:93
LPWSTR Name
Definition: desk.c:124
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#define I(s)
@ ATTR_IS_COMPRESSED
Definition: ntfslib.h:350
@ ATTR_IS_SPARSE
Definition: ntfslib.h:352
BYTE * PBYTE
Definition: pedump.c:66
unsigned short USHORT
Definition: pedump.c:61
#define WR16(p, o, v)
Definition: files.c:77
#define WR32(p, o, v)
Definition: files.c:78
#define ALIGN8(x)
Definition: files.c:83
static ULONG MkEncodeRuns(IN const MK_RUN *Runs, IN ULONG RunCount, OUT PBYTE Out)
Definition: files.c:140
#define WR64(p, o, v)
Definition: files.c:79
ULONG Runs
Definition: symtest.c:7
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
unsigned char BYTE
Definition: xxhash.c:193

Referenced by WriteMetafiles().

◆ MkAddResident()

static VOID MkAddResident ( IN OUT MK_REC *  Rec,
IN ULONG  Type,
IN LPCWSTR  Name,
IN BYTE  NameChars,
IN BYTE  ResidentFlags,
IN const VOID *  Value,
IN ULONG  ValueLen 
)
static

Definition at line 231 of file files.c.

238{
239 PBYTE A = Rec->Buf + Rec->Offset;
240 USHORT ValueOff = (USHORT)ALIGN8(0x18u + (ULONG)NameChars * 2);
241 ULONG AttrLen = ALIGN8(ValueOff + ValueLen);
242 ULONG I;
243
244 WR32(A, 0x00, Type);
245 WR32(A, 0x04, AttrLen);
246 A[0x08] = 0; /* resident */
247 A[0x09] = NameChars;
248 WR16(A, 0x0A, 0x18); /* name offset (Windows sets it even if unnamed) */
249 WR16(A, 0x0C, 0); /* flags */
250 WR16(A, 0x0E, Rec->NextAttrId++);
251 WR32(A, 0x10, ValueLen);
252 WR16(A, 0x14, ValueOff);
253 A[0x16] = ResidentFlags;
254 A[0x17] = 0;
255
256 for (I = 0; I < NameChars; I++)
257 WR16(A, 0x18 + I * 2, Name[I]);
258 if (ValueLen > 0)
259 RtlCopyMemory(A + ValueOff, Value, ValueLen);
260
261 Rec->Offset += AttrLen;
262}
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413

Referenced by WriteMetafiles().

◆ MkEmptyI30Root()

static ULONG MkEmptyI30Root ( OUT PBYTE  Out)
static

Definition at line 458 of file files.c.

459{
460 RtlZeroMemory(Out, 0x30);
461 WR32(Out, 0x00, AttributeFileName);
463 WR32(Out, 0x08, INDEX_RECORD_SIZE);
464 Out[0x0C] = (BYTE)LAYOUT.ClustersPerIndexRecord;
465 WR32(Out, 0x10, 0x10); /* entries offset */
466 WR32(Out, 0x14, 0x10 + 0x10); /* index length */
467 WR32(Out, 0x18, 0x10 + 0x10); /* allocated */
468 Out[0x1C] = 0; /* small index */
469 WR16(Out, 0x28, 0x10); /* end entry length */
470 WR16(Out, 0x2C, INDEX_ENTRY_END);
471 return 0x30;
472}
@ Out
#define COLLATION_FILE_NAME
Definition: ntfs.h:228
@ AttributeFileName
Definition: ntfs.h:190
#define INDEX_ENTRY_END
Definition: ntfslib.h:164
#define INDEX_RECORD_SIZE
Definition: ntfslib.h:94
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by WriteMetafiles().

◆ MkEmptyViewRoot()

static ULONG MkEmptyViewRoot ( OUT PBYTE  Out,
IN ULONG  CollationRule 
)
static

Definition at line 548 of file files.c.

550{
551 RtlZeroMemory(Out, 0x30);
552 WR32(Out, 0x00, 0); /* view index (indexed attr type 0) */
553 WR32(Out, 0x04, CollationRule);
554 WR32(Out, 0x08, INDEX_RECORD_SIZE);
555 Out[0x0C] = (BYTE)LAYOUT.ClustersPerIndexRecord;
556 WR32(Out, 0x10, 0x10);
557 WR32(Out, 0x14, 0x10 + 0x10);
558 WR32(Out, 0x18, 0x10 + 0x10);
559 Out[0x1C] = 0;
560 WR16(Out, 0x28, 0x10);
561 WR16(Out, 0x2C, INDEX_ENTRY_END);
562 return 0x30;
563}

Referenced by WriteMetafiles().

◆ MkEncodeRuns()

static ULONG MkEncodeRuns ( IN const MK_RUN *  Runs,
IN ULONG  RunCount,
OUT PBYTE  Out 
)
static

Definition at line 140 of file files.c.

143{
144 ULONG Pos = 0;
145 ULONG Index;
146 ULONGLONG PrevLcn = 0;
147
148 for (Index = 0; Index < RunCount; Index++)
149 {
150 ULONG LenBytes;
151 ULONG OffBytes;
152 LONGLONG LcnDelta;
153 ULONG B;
154 ULONGLONG Len = Runs[Index].Len;
155
156 /* Length is unsigned but stored minimally-signed with a clear top bit. */
157 LenBytes = MkSignBytes((LONGLONG)Len);
158 if (LenBytes == 0)
159 LenBytes = 1;
160 if ((Len >> (LenBytes * 8 - 1)) & 1)
161 LenBytes++;
162
163 if (Runs[Index].Lcn == HOLE_LCN)
164 {
165 OffBytes = 0;
166 LcnDelta = 0;
167 }
168 else
169 {
170 LcnDelta = (LONGLONG)Runs[Index].Lcn - (LONGLONG)PrevLcn;
171 OffBytes = MkSignBytes(LcnDelta);
172 if (OffBytes == 0)
173 OffBytes = 1;
174 PrevLcn = Runs[Index].Lcn;
175 }
176
177 Out[Pos++] = (BYTE)((OffBytes << 4) | (LenBytes & 0x0F));
178 for (B = 0; B < LenBytes; B++)
179 Out[Pos++] = (BYTE)(Len >> (B * 8));
180 for (B = 0; B < OffBytes; B++)
181 Out[Pos++] = (BYTE)((ULONGLONG)LcnDelta >> (B * 8));
182 }
183
184 Out[Pos++] = 0; /* terminator */
185 return Pos;
186}
Definition: ehthrow.cxx:54
#define Len
Definition: deflate.h:82
ush Pos
Definition: deflate.h:92
#define B(row, col)
#define HOLE_LCN
Definition: files.c:72
static ULONG MkSignBytes(IN LONGLONG Value)
Definition: files.c:116
int64_t LONGLONG
Definition: typedefs.h:68
uint64_t ULONGLONG
Definition: typedefs.h:67
_In_ WDFCOLLECTION _In_ ULONG Index

Referenced by MkAddNonResident().

◆ MkExtractFileName()

static USHORT MkExtractFileName ( IN const BYTE *  RecBuf,
OUT PBYTE  Out 
)
static

Definition at line 427 of file files.c.

429{
430 ULONG P = RD16(RecBuf, 0x14);
431
432 while ((P + 4) <= MFT_RECORD_SIZE)
433 {
434 ULONG Type = RD32(RecBuf, P);
435 ULONG Len;
436
437 if (Type == (ULONG)AttributeEnd)
438 break;
439 Len = RD32(RecBuf, P + 4);
440 if (Len == 0)
441 break;
442 if ((Type == (ULONG)AttributeFileName) && (RecBuf[P + 8] == 0))
443 {
444 ULONG ValLen = RD32(RecBuf, P + 0x10);
445 USHORT ValOff = RD16(RecBuf, P + 0x14);
446
447 RtlCopyMemory(Out, RecBuf + P + ValOff, ValLen);
448 return (USHORT)ValLen;
449 }
450 P += Len;
451 }
452 return 0;
453}
#define P(row, col)
@ AttributeEnd
Definition: ntfs.h:204
#define MFT_RECORD_SIZE
Definition: ntfslib.h:93
#define RD32(p, o)
Definition: files.c:81
#define RD16(p, o)
Definition: files.c:80

Referenced by MkI30RootWithEntries(), and MkRootIndxBlock().

◆ MkFileName()

static ULONG MkFileName ( OUT PBYTE  Out,
IN ULONGLONG  ParentRef,
IN ULONG  FileAttributes,
IN ULONGLONG  AllocSize,
IN ULONGLONG  RealSize,
IN ULONGLONG  Now,
IN LPCWSTR  Name,
IN BYTE  Namespace 
)
static

Definition at line 391 of file files.c.

399{
400 BYTE NameLen = 0;
401 ULONG I;
402
403 while (Name[NameLen] != L'\0')
404 NameLen++;
405
406 RtlZeroMemory(Out, 0x42 + (ULONG)NameLen * 2);
407 WR64(Out, 0x00, ParentRef);
408 WR64(Out, 0x08, Now);
409 WR64(Out, 0x10, Now);
410 WR64(Out, 0x18, Now);
411 WR64(Out, 0x20, Now);
412 WR64(Out, 0x28, AllocSize);
413 WR64(Out, 0x30, RealSize);
414 WR32(Out, 0x38, FileAttributes);
415 Out[0x40] = NameLen;
416 Out[0x41] = Namespace;
417 for (I = 0; I < NameLen; I++)
418 WR16(Out, 0x42 + I * 2, Name[I]);
419
420 return 0x42 + (ULONG)NameLen * 2;
421}
#define L(x)
Definition: resources.c:13
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE _In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Out_ PIO_STATUS_BLOCK _In_opt_ PLARGE_INTEGER _In_ ULONG FileAttributes
Definition: fltkernel.h:1236
struct tm * Now
Definition: output.c:19

Referenced by WriteMetafiles().

◆ MkFinalize()

static VOID MkFinalize ( IN MK_REC *  Rec)
static

Definition at line 327 of file files.c.

328{
329 PBYTE Buf = Rec->Buf;
330 ULONG Used;
331 USHORT UsaOff;
332 USHORT UsaCount;
333 ULONG Sector;
334
335 WR32(Buf, Rec->Offset, AttributeEnd); /* end marker */
336 WR32(Buf, Rec->Offset + 4, 0);
337 Used = Rec->Offset + 8;
338
339 WR32(Buf, 0x18, Used); /* bytes in use */
340 WR16(Buf, 0x28, Rec->NextAttrId); /* next attr id */
341
342 UsaOff = RD16(Buf, 0x04);
343 UsaCount = RD16(Buf, 0x06);
344 WR16(Buf, UsaOff, USN_VALUE);
345 for (Sector = 0; Sector + 1 < UsaCount; Sector++)
346 {
347 PBYTE Tail = Buf + (Sector + 1) * BYTES_PER_SECTOR - 2;
348
349 WR16(Buf, UsaOff + (Sector + 1) * 2, RD16(Tail, 0));
350 WR16(Tail, 0, USN_VALUE);
351 }
352}
#define BYTES_PER_SECTOR
Definition: volume.c:37
#define USN_VALUE
Definition: files.c:70

Referenced by WriteMetafiles().

◆ MkI30RootWithEntries()

static ULONG MkI30RootWithEntries ( OUT PBYTE  Out,
IN const BYTE *  Mft,
IN const ULONG *  Order,
IN ULONG  Count 
)
static

Definition at line 499 of file files.c.

503{
504 ULONG P;
505 ULONG Index;
506 ULONG IndexLen;
507
508 RtlZeroMemory(Out, 0x20);
509 WR32(Out, 0x00, AttributeFileName);
511 WR32(Out, 0x08, INDEX_RECORD_SIZE);
512 Out[0x0C] = (BYTE)LAYOUT.ClustersPerIndexRecord;
513 WR32(Out, 0x10, 0x10); /* entries offset */
514 Out[0x1C] = 0; /* small index */
515
516 P = 0x20;
517 for (Index = 0; Index < Count; Index++)
518 {
519 BYTE Fn[256];
520 USHORT FnLen = MkExtractFileName(Mft + (ULONG_PTR)Order[Index] * MFT_RECORD_SIZE, Fn);
521 ULONG EntryLen = ALIGN8(0x10u + FnLen);
522
523 RtlZeroMemory(Out + P, EntryLen);
524 WR64(Out, P + 0x00, MFT_REFERENCE(Order[Index]));
525 WR16(Out, P + 0x08, EntryLen);
526 WR16(Out, P + 0x0A, FnLen);
527 WR16(Out, P + 0x0C, 0);
528 WR16(Out, P + 0x0E, 0);
529 RtlCopyMemory(Out + P + 0x10, Fn, FnLen);
530 P += EntryLen;
531 }
532
533 /* End marker */
534 RtlZeroMemory(Out + P, 0x10);
535 WR16(Out, P + 0x08, 0x10);
536 WR16(Out, P + 0x0C, INDEX_ENTRY_END);
537 P += 0x10;
538
539 IndexLen = P - 0x10;
540 WR32(Out, 0x14, IndexLen);
541 WR32(Out, 0x18, IndexLen);
542 return P;
543}
BOOLEAN(* Fn)(ULONG Argc, PCHAR Argv[])
Definition: kdb_cli.c:346
#define MFT_REFERENCE(rec)
Definition: ntfslib.h:177
int Count
Definition: noreturn.cpp:7
static USHORT MkExtractFileName(IN const BYTE *RecBuf, OUT PBYTE Out)
Definition: files.c:427
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by WriteMetafiles().

◆ MkIndxFixup()

static VOID MkIndxFixup ( IN OUT PBYTE  Blk,
IN ULONG  BlkSize 
)
static

Definition at line 656 of file files.c.

658{
659 USHORT UsaCount = (USHORT)(BlkSize / BYTES_PER_SECTOR + 1);
660 ULONG Sector;
661
662 WR16(Blk, 0x28, USN_VALUE);
663 for (Sector = 0; Sector + 1 < UsaCount; Sector++)
664 {
665 PBYTE Tail = Blk + (Sector + 1) * BYTES_PER_SECTOR - 2;
666
667 WR16(Blk, 0x28 + (Sector + 1) * 2, RD16(Tail, 0));
668 WR16(Tail, 0, USN_VALUE);
669 }
670}

Referenced by MkRootIndxBlock(), and MkViewIndxBlock().

◆ MkInit()

static VOID MkInit ( OUT MK_REC *  Rec,
IN PBYTE  Buf,
IN ULONG  RecordNumber,
IN USHORT  Flags 
)
static

Definition at line 193 of file files.c.

197{
198 USHORT UsaCount = (USHORT)(MFT_RECORD_SIZE / BYTES_PER_SECTOR + 1);
199
201 Rec->Buf = Buf;
202 Rec->NextAttrId = 0;
203
204 RtlCopyMemory(Buf + 0x00, "FILE", 4);
205 WR16(Buf, 0x04, 0x30); /* USA offset */
206 WR16(Buf, 0x06, UsaCount); /* USA count */
207 WR64(Buf, 0x08, 0); /* $LogFile LSN */
208 WR16(Buf, 0x10, RECORD_SEQUENCE(RecordNumber)); /* sequence number */
209 WR16(Buf, 0x12, 1); /* hard link count */
210 WR16(Buf, 0x14, 0x38); /* first attribute offset */
211 WR16(Buf, 0x16, Flags);
212 WR32(Buf, 0x1C, MFT_RECORD_SIZE); /* allocated size */
213 WR64(Buf, 0x20, 0); /* base record */
214 WR16(Buf, 0x28, 0); /* next attr id (set at finalize) */
215 WR32(Buf, 0x2C, RecordNumber); /* this record number */
216
217 Rec->Offset = 0x38;
218}
#define RECORD_SEQUENCE(rec)
Definition: ntfslib.h:173

Referenced by WriteMetafiles().

◆ MkLargeI30Root()

static ULONG MkLargeI30Root ( OUT PBYTE  Out)
static

Definition at line 478 of file files.c.

479{
480 RtlZeroMemory(Out, 0x38);
481 WR32(Out, 0x00, AttributeFileName);
483 WR32(Out, 0x08, INDEX_RECORD_SIZE);
484 Out[0x0C] = (BYTE)LAYOUT.ClustersPerIndexRecord;
485 WR32(Out, 0x10, 0x10);
486 WR32(Out, 0x14, 0x10 + 0x18);
487 WR32(Out, 0x18, 0x10 + 0x18);
488 Out[0x1C] = INDEX_NODE_LARGE;
489 WR16(Out, 0x28, 0x18); /* entry length */
491 WR64(Out, 0x30, 0); /* subnode VCN */
492 return 0x38;
493}
#define INDEX_NODE_LARGE
Definition: ntfs.h:239
#define INDEX_ENTRY_NODE
Definition: ntfslib.h:163

Referenced by WriteMetafiles().

◆ MkLargeViewRoot()

static ULONG MkLargeViewRoot ( OUT PBYTE  Out,
IN ULONG  CollationRule 
)
static

Definition at line 568 of file files.c.

570{
571 RtlZeroMemory(Out, 0x38);
572 WR32(Out, 0x00, 0);
573 WR32(Out, 0x04, CollationRule);
574 WR32(Out, 0x08, INDEX_RECORD_SIZE);
575 Out[0x0C] = (BYTE)LAYOUT.ClustersPerIndexRecord;
576 WR32(Out, 0x10, 0x10);
577 WR32(Out, 0x14, 0x10 + 0x18);
578 WR32(Out, 0x18, 0x10 + 0x18);
579 Out[0x1C] = INDEX_NODE_LARGE;
580 WR16(Out, 0x28, 0x18);
582 WR64(Out, 0x30, 0);
583 return 0x38;
584}

Referenced by WriteMetafiles().

◆ MkRootIndxBlock()

static VOID MkRootIndxBlock ( OUT PBYTE  Blk,
IN const BYTE *  Mft,
IN const ULONG *  Order,
IN ULONG  Count 
)
static

Definition at line 725 of file files.c.

729{
730 ULONG P;
731 ULONG Index;
733
735 RtlCopyMemory(Blk + 0x00, "INDX", 4);
736 WR16(Blk, 0x04, 0x28);
737 WR16(Blk, 0x06, UsaCount);
738 WR64(Blk, 0x08, 0);
739 WR64(Blk, 0x10, 0); /* VCN of this INDX */
740 WR32(Blk, 0x18, 0x28); /* entries offset -> 0x40 */
741 WR32(Blk, 0x20, INDEX_RECORD_SIZE - 0x18);
742 Blk[0x24] = 0; /* leaf */
743
744 P = 0x40;
745 for (Index = 0; Index < Count; Index++)
746 {
747 const BYTE *RecBuf = Mft + (ULONG_PTR)Order[Index] * MFT_RECORD_SIZE;
748 BYTE Fn[256];
749 USHORT FnLen = MkExtractFileName(RecBuf, Fn);
750 ULONG EntryLen = ALIGN8(0x10u + FnLen);
751
752 WR64(Blk, P + 0x00, MFT_REFERENCE(Order[Index]));
753 WR16(Blk, P + 0x08, EntryLen);
754 WR16(Blk, P + 0x0A, FnLen);
755 WR16(Blk, P + 0x0C, 0);
756 WR16(Blk, P + 0x0E, 0);
757 RtlCopyMemory(Blk + P + 0x10, Fn, FnLen);
758 P += EntryLen;
759 }
760
761 WR16(Blk, P + 0x08, 0x10);
762 WR16(Blk, P + 0x0C, INDEX_ENTRY_END);
763 P += 0x10;
764 WR32(Blk, 0x1C, P - 0x18); /* index length */
765
767}
#define ULONG_PTR
Definition: config.h:101
static VOID MkIndxFixup(IN OUT PBYTE Blk, IN ULONG BlkSize)
Definition: files.c:656

Referenced by WriteMetafiles().

◆ MkSecHash()

static ULONG MkSecHash ( IN const BYTE *  Sd,
IN ULONG  Len 
)
static

Definition at line 639 of file files.c.

641{
642 ULONG Hash = 0;
643 ULONG I;
644
645 for (I = 0; I + 4 <= Len; I += 4)
646 {
647 ULONG Dword = RD32(Sd, I);
648 Hash = Dword + ((Hash << 3) | (Hash >> 29));
649 }
650 return Hash;
651}
static int Hash(const char *)
Definition: reader.c:2237

Referenced by WriteMetafiles().

◆ MkSetHardLinks()

static VOID MkSetHardLinks ( IN MK_REC *  Rec,
IN USHORT  Count 
)
static

Definition at line 222 of file files.c.

224{
225 WR16(Rec->Buf, 0x12, Count);
226}

Referenced by WriteMetafiles().

◆ MkSignBytes()

static ULONG MkSignBytes ( IN LONGLONG  Value)
static

Definition at line 116 of file files.c.

117{
118 ULONG Bytes;
119 LONGLONG V;
120
121 if (Value == 0)
122 return 0;
123
124 Bytes = 0;
125 V = Value;
126 do
127 {
128 Bytes++;
129 V >>= 8;
130 }
131 while (!((V == 0) && (((Value >> (Bytes * 8 - 1)) & 1) == 0)) &&
132 !((V == -1) && (((Value >> (Bytes * 8 - 1)) & 1) == 1)));
133
134 return Bytes;
135}
#define V(i, a, b, c, d)
Definition: jaricom.c:29
_In_ UINT Bytes
Definition: mmcopy.h:9

Referenced by MkEncodeRuns().

◆ MkStdInfo()

static VOID MkStdInfo ( OUT PBYTE  Out,
IN ULONG  FileAttributes,
IN ULONGLONG  Now,
IN ULONG  SecurityId 
)
static

Definition at line 359 of file files.c.

363{
364 RtlZeroMemory(Out, 72);
365 WR64(Out, 0x00, Now); /* creation */
366 WR64(Out, 0x08, Now); /* modified */
367 WR64(Out, 0x10, Now); /* mft changed */
368 WR64(Out, 0x18, Now); /* accessed */
369 WR32(Out, 0x20, FileAttributes);
370 WR32(Out, 0x34, SecurityId);
371}

Referenced by WriteMetafiles().

◆ MkStdInfoShort()

static VOID MkStdInfoShort ( OUT PBYTE  Out,
IN ULONG  FileAttributes,
IN ULONGLONG  Now 
)
static

Definition at line 377 of file files.c.

380{
381 RtlZeroMemory(Out, 48);
382 WR64(Out, 0x00, Now);
383 WR64(Out, 0x08, Now);
384 WR64(Out, 0x10, Now);
385 WR64(Out, 0x18, Now);
386 WR32(Out, 0x20, FileAttributes);
387}

Referenced by WriteMetafiles().

◆ MkViewIndxBlock()

static VOID MkViewIndxBlock ( OUT PBYTE  Blk,
IN const MK_VIEW_ENTRY *  Entries,
IN ULONG  Count 
)
static

Definition at line 675 of file files.c.

678{
679 ULONG P;
680 ULONG Index;
682
684 RtlCopyMemory(Blk + 0x00, "INDX", 4);
685 WR16(Blk, 0x04, 0x28); /* USA offset */
686 WR16(Blk, 0x06, UsaCount);
687 WR64(Blk, 0x10, 0); /* VCN */
688 WR32(Blk, 0x18, 0x28); /* entries offset -> 0x40 */
689 WR32(Blk, 0x20, INDEX_RECORD_SIZE - 0x18);
690 Blk[0x24] = 0; /* leaf */
691
692 P = 0x40;
693 for (Index = 0; Index < Count; Index++)
694 {
695 USHORT DataOff = (USHORT)(0x10 + Entries[Index].KeyLen);
696 ULONG EntryLen = ALIGN8((ULONG)DataOff + Entries[Index].DataLen);
697 ULONG Pad;
698
699 WR16(Blk, P + 0x00, DataOff);
700 WR16(Blk, P + 0x02, Entries[Index].DataLen);
701 WR16(Blk, P + 0x08, EntryLen);
702 WR16(Blk, P + 0x0A, Entries[Index].KeyLen);
703 WR16(Blk, P + 0x0C, 0);
704 RtlCopyMemory(Blk + P + 0x10, Entries[Index].Key, Entries[Index].KeyLen);
705 RtlCopyMemory(Blk + P + DataOff, Entries[Index].Data, Entries[Index].DataLen);
706 /* Slack after each $SDH entry's data holds the UTF-16 unit 0x0049 ('I'),
707 * not zero. */
708 for (Pad = (ULONG)DataOff + Entries[Index].DataLen; Pad + 1 < EntryLen; Pad += 2)
709 WR16(Blk, P + Pad, 0x0049);
710 P += EntryLen;
711 }
712
713 WR16(Blk, P + 0x08, 0x10);
714 WR16(Blk, P + 0x0C, INDEX_ENTRY_END);
715 P += 0x10;
716 WR32(Blk, 0x1C, P - 0x18); /* index length */
717
719}
char * Pad(char *Str, char PadChar, ULONG Length)
Definition: cabman.cxx:29
static const ENTRY Entries[]

Referenced by WriteMetafiles().

◆ MkViewRootN()

static ULONG MkViewRootN ( OUT PBYTE  Out,
IN ULONG  CollationRule,
IN const MK_VIEW_ENTRY *  Entries,
IN ULONG  Count 
)
static

Definition at line 591 of file files.c.

595{
596 ULONG P;
597 ULONG Index;
598 ULONG IndexLen;
599
600 RtlZeroMemory(Out, 0x20);
601 WR32(Out, 0x00, 0);
602 WR32(Out, 0x04, CollationRule);
603 WR32(Out, 0x08, INDEX_RECORD_SIZE);
604 Out[0x0C] = (BYTE)LAYOUT.ClustersPerIndexRecord;
605 WR32(Out, 0x10, 0x10);
606 Out[0x1C] = 0;
607
608 P = 0x20;
609 for (Index = 0; Index < Count; Index++)
610 {
611 USHORT DataOff = (USHORT)(0x10 + Entries[Index].KeyLen);
612 ULONG EntryLen = ALIGN8((ULONG)DataOff + Entries[Index].DataLen);
613
614 RtlZeroMemory(Out + P, EntryLen);
615 WR16(Out, P + 0x00, DataOff);
616 WR16(Out, P + 0x02, Entries[Index].DataLen);
617 WR16(Out, P + 0x08, EntryLen);
618 WR16(Out, P + 0x0A, Entries[Index].KeyLen);
619 WR16(Out, P + 0x0C, 0);
620 RtlCopyMemory(Out + P + 0x10, Entries[Index].Key, Entries[Index].KeyLen);
621 RtlCopyMemory(Out + P + DataOff, Entries[Index].Data, Entries[Index].DataLen);
622 P += EntryLen;
623 }
624
625 RtlZeroMemory(Out + P, 0x10);
626 WR16(Out, P + 0x08, 0x10);
627 WR16(Out, P + 0x0C, INDEX_ENTRY_END);
628 P += 0x10;
629
630 IndexLen = P - 0x10;
631 WR32(Out, 0x14, IndexLen);
632 WR32(Out, 0x18, IndexLen);
633 return P;
634}

Referenced by WriteMetafiles().

◆ WriteAt()

static NTSTATUS WriteAt ( IN ULONGLONG  Lcn,
IN PVOID  Buffer,
IN ULONG  Length 
)
static

Definition at line 774 of file files.c.

777{
780
781 Offset.QuadPart = (LONGLONG)Lcn * BYTES_PER_CLUSTER;
784}
Definition: bufpool.h:45
_In_ PIO_STATUS_BLOCK IoStatusBlock
Definition: dispmprt.h:608
#define NULL
Definition: types.h:112
#define BYTES_PER_CLUSTER
Definition: ntfslib.h:72
#define DISK_HANDLE
Definition: ntfslib.h:61
NTSYSAPI NTSTATUS NTAPI NtWriteFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID WriteBuffer, IN ULONG WriteBufferLength, IN PLARGE_INTEGER FileOffset OPTIONAL, IN PULONG LockOperationKey OPTIONAL)
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102

Referenced by WriteMetafiles(), WritePatternToClusters(), and WriteRegion().

◆ WriteMetafiles()

NTSTATUS WriteMetafiles ( VOID  )

Definition at line 872 of file files.c.

873{
875 PBYTE Mft;
876 PBYTE Val;
879 ULONGLONG ClusterCount = LAYOUT.ClusterCount;
880
881 /* --- $Secure descriptor precompute (blob/$SDS offsets + hashes) ------ */
882 ULONG SdBlobOff[NTFS_DEFAULT_SD_COUNT];
885 ULONG SdsContentLen;
886
887 /* $SDH hash-sorted order of the 8 default descriptors (index i = id 0x100+i). */
888 static const BYTE SdhOrder[NTFS_DEFAULT_SD_COUNT] = { 4, 6, 2, 3, 7, 5, 0, 1 };
889
890 ULONG Blob = 0;
891 ULONG Sds = 0;
892 ULONG i;
893
894 for (i = 0; i < NTFS_DEFAULT_SD_COUNT; i++)
895 {
896 SdBlobOff[i] = Blob;
897 SdSdsOff[i] = Sds;
898 SdHash[i] = MkSecHash(DefaultSds + Blob, DefaultSdLen[i]);
899 Blob += DefaultSdLen[i];
900 Sds = ALIGN_UP_BY(Sds + 0x14 + DefaultSdLen[i], 16);
901 }
902 SdsContentLen = SdSdsOff[NTFS_DEFAULT_SD_COUNT - 1] + 0x14 +
904
905 /* --- Build the MFT in memory (records 0..35) ------------------------ */
906 Mft = RtlAllocateHeap(RtlGetProcessHeap(), 0, MREC_COUNT * MFT_RECORD_SIZE);
907 if (!Mft)
908 {
909 DPRINT1("ERROR: Unable to allocate MFT build buffer!\n");
911 }
913
914 Val = RtlAllocateHeap(RtlGetProcessHeap(), 0, 2048);
915 if (!Val)
916 {
917 DPRINT1("ERROR: Unable to allocate attribute scratch buffer!\n");
918 FREE(Mft);
920 }
921
922 {
923 MK_REC Rec;
924 ULONG Len;
925 MK_RUN Runs[1];
926
927 #define REC_BUF(n) (Mft + (ULONG_PTR)(n) * MFT_RECORD_SIZE)
928
929 /* Record 0: $MFT (large, contiguous $DATA run). */
932 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
934 (ULONGLONG)LAYOUT.MftClusters * C,
935 (ULONGLONG)LAYOUT.MftAllocRecords * MFT_RECORD_SIZE,
938 Runs[0].Lcn = LAYOUT.MftLcn; Runs[0].Len = LAYOUT.MftClusters;
939 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, Runs, 1, LAYOUT.MftClusters - 1,
940 (ULONGLONG)LAYOUT.MftClusters * C,
941 (ULONGLONG)LAYOUT.MftAllocRecords * MFT_RECORD_SIZE,
942 (ULONGLONG)LAYOUT.MftAllocRecords * MFT_RECORD_SIZE);
943 /* $BITMAP (non-resident): one bit per reserved MFT record. */
944 {
945 ULONGLONG MftBmpBytes = ((ULONGLONG)LAYOUT.MftAllocRecords + 7) / 8;
946 Runs[0].Lcn = LAYOUT.MftBitmapLcn; Runs[0].Len = LAYOUT.MftBitmapClusters;
947 MkAddNonResident(&Rec, AttributeBitmap, NULL, 0, 0, Runs, 1, LAYOUT.MftBitmapClusters - 1,
948 (ULONGLONG)LAYOUT.MftBitmapClusters * C, MftBmpBytes, MftBmpBytes);
949 }
950 MkFinalize(&Rec);
951
952 /* Record 1: $MFTMirr. */
955 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
958 Now, L"$MFTMirr", FILE_NAME_WIN32_AND_DOS);
960 Runs[0].Lcn = LAYOUT.MftMirrLcn; Runs[0].Len = LAYOUT.MftMirrClusters;
961 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, Runs, 1, LAYOUT.MftMirrClusters - 1,
962 (ULONGLONG)LAYOUT.MftMirrClusters * C,
965 MkFinalize(&Rec);
966
967 /* Record 2: $LogFile. */
970 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
972 (ULONGLONG)LAYOUT.LogFileClusters * C, (ULONGLONG)LAYOUT.LogFileClusters * C,
973 Now, L"$LogFile", FILE_NAME_WIN32_AND_DOS);
975 Runs[0].Lcn = LAYOUT.LogFileLcn; Runs[0].Len = LAYOUT.LogFileClusters;
976 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, Runs, 1, LAYOUT.LogFileClusters - 1,
977 (ULONGLONG)LAYOUT.LogFileClusters * C, (ULONGLONG)LAYOUT.LogFileClusters * C,
978 (ULONGLONG)LAYOUT.LogFileClusters * C);
979 MkFinalize(&Rec);
980
981 /* Record 3: $Volume. */
983 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM, Now, 0x101);
984 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
986 0, 0, Now, L"$Volume", FILE_NAME_WIN32_AND_DOS);
988 {
989 BYTE VName[128];
990 ULONG VLen = 0;
991 if (LABEL && LABEL->Buffer && LABEL->Length > 0)
992 {
993 VLen = LABEL->Length;
994 if (VLen > 128)
995 VLen = 128;
996 RtlCopyMemory(VName, LABEL->Buffer, VLen);
997 }
998 MkAddResident(&Rec, AttributeVolumeName, NULL, 0, 0, VName, VLen);
999 }
1000 /* $VOLUME_INFORMATION: version 3.1, flags 0 (the 0x80 dirty bit left clear). */
1001 RtlZeroMemory(Val, 12);
1002 Val[0x08] = NTFS_MAJOR_VERSION;
1003 Val[0x09] = NTFS_MINOR_VERSION;
1004 MkAddResident(&Rec, AttributeVolumeInformation, NULL, 0, 0, Val, 12);
1005 MkAddResident(&Rec, AttributeData, NULL, 0, 0, NULL, 0); /* empty $DATA */
1006 MkFinalize(&Rec);
1007
1008 /* Record 4: $AttrDef. */
1011 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1013 (ULONGLONG)LAYOUT.AttrDefClusters * C,
1014 sizeof(ATTRIBUTES_TABLE) - sizeof(ATTRIBUTES_TABLE[0]),
1015 Now, L"$AttrDef", FILE_NAME_WIN32_AND_DOS);
1017 Runs[0].Lcn = LAYOUT.AttrDefLcn; Runs[0].Len = LAYOUT.AttrDefClusters;
1018 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, Runs, 1, LAYOUT.AttrDefClusters - 1,
1019 (ULONGLONG)LAYOUT.AttrDefClusters * C,
1020 sizeof(ATTRIBUTES_TABLE), sizeof(ATTRIBUTES_TABLE));
1021 MkFinalize(&Rec);
1022
1023 /* Record 6: $Bitmap. The stream length must be a multiple of 8 bytes
1024 * (NTFS tracks the cluster bitmap in 64-bit groups); an unaligned length
1025 * gets rounded up and zero-filled by the OS, freeing phantom clusters. */
1026 {
1027 ULONGLONG BitmapBytes = (((ClusterCount + 7) / 8) + 7) & ~7ULL;
1030 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1032 (ULONGLONG)LAYOUT.BitmapClusters * C, BitmapBytes,
1033 Now, L"$Bitmap", FILE_NAME_WIN32_AND_DOS);
1035 Runs[0].Lcn = LAYOUT.BitmapLcn; Runs[0].Len = LAYOUT.BitmapClusters;
1036 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, Runs, 1, LAYOUT.BitmapClusters - 1,
1037 (ULONGLONG)LAYOUT.BitmapClusters * C, BitmapBytes, BitmapBytes);
1038 MkFinalize(&Rec);
1039 }
1040
1041 /* Record 7: $Boot (short STD_INFO + embedded default descriptor 0x100). */
1044 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 48);
1046 (ULONGLONG)LAYOUT.BootClusters * C, 0x2000,
1047 Now, L"$Boot", FILE_NAME_WIN32_AND_DOS);
1050 DefaultSds + SdBlobOff[0], DefaultSdLen[0]);
1051 Runs[0].Lcn = LAYOUT.BootLcn; Runs[0].Len = LAYOUT.BootClusters;
1052 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, Runs, 1, LAYOUT.BootClusters - 1,
1053 (ULONGLONG)LAYOUT.BootClusters * C, 0x2000, 0x2000);
1054 MkFinalize(&Rec);
1055
1056 /* Record 8: $BadClus (empty $DATA + sparse whole-volume $Bad hole). */
1059 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1061 0, 0, Now, L"$BadClus", FILE_NAME_WIN32_AND_DOS);
1063 MkAddResident(&Rec, AttributeData, NULL, 0, 0, NULL, 0);
1064 /* $Bad is a plain (non-sparse) non-resident attribute whose single
1065 * mapping-pair is a hole; alloc/real = whole volume, init = 0. */
1066 Runs[0].Lcn = HOLE_LCN; Runs[0].Len = ClusterCount;
1067 MkAddNonResident(&Rec, AttributeData, L"$Bad", 4, 0, Runs, 1, ClusterCount - 1,
1068 ClusterCount * C, ClusterCount * C, 0);
1069 MkFinalize(&Rec);
1070
1071 /* Record 9: $Secure ($SDS + large $SDH + resident $SII). */
1072 {
1073 BYTE SdsHdr[NTFS_DEFAULT_SD_COUNT][0x14];
1074 BYTE SiiKeys[NTFS_DEFAULT_SD_COUNT][4];
1075 BYTE SdhKeys[NTFS_DEFAULT_SD_COUNT][8];
1077 BYTE ViewRoot[512];
1078
1079 for (i = 0; i < NTFS_DEFAULT_SD_COUNT; i++)
1080 {
1081 ULONG Id = 0x100 + i;
1082 WR32(SdsHdr[i], 0x00, SdHash[i]);
1083 WR32(SdsHdr[i], 0x04, Id);
1084 WR64(SdsHdr[i], 0x08, SdSdsOff[i]);
1085 WR32(SdsHdr[i], 0x10, 0x14 + DefaultSdLen[i]);
1086 WR32(SiiKeys[i], 0, Id);
1087 WR32(SdhKeys[i], 0, SdHash[i]);
1088 WR32(SdhKeys[i], 4, Id);
1089 SiiEnt[i].Key = SiiKeys[i]; SiiEnt[i].KeyLen = 4;
1090 SiiEnt[i].Data = SdsHdr[i]; SiiEnt[i].DataLen = 0x14;
1091 }
1092
1094 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM | FA_VIEW, Now, 0x101);
1095 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1097 0, 0, Now, L"$Secure", FILE_NAME_WIN32_AND_DOS);
1099 /* $DATA:$SDS (non-resident: 8 descriptors + a 256 KiB-offset mirror). */
1100 Runs[0].Lcn = LAYOUT.SdsLcn; Runs[0].Len = LAYOUT.SdsClusters;
1101 MkAddNonResident(&Rec, AttributeData, L"$SDS", 4, 0, Runs, 1, LAYOUT.SdsClusters - 1,
1102 (ULONGLONG)LAYOUT.SdsClusters * C,
1103 (ULONGLONG)NTFS_SDS_MIRROR + SdsContentLen,
1104 (ULONGLONG)NTFS_SDS_MIRROR + SdsContentLen);
1105 /* Attribute order (type, name): $SDH root, $SII root, then $SDH alloc, $SDH bitmap. */
1107 MkAddResident(&Rec, AttributeIndexRoot, L"$SDH", 4, 0, ViewRoot, Len);
1109 MkAddResident(&Rec, AttributeIndexRoot, L"$SII", 4, 0, ViewRoot, Len);
1110 Runs[0].Lcn = LAYOUT.SdhIdxLcn; Runs[0].Len = LAYOUT.SdhIdxClusters;
1111 MkAddNonResident(&Rec, AttributeIndexAllocation, L"$SDH", 4, 0, Runs, 1,
1112 LAYOUT.SdhIdxClusters - 1, (ULONGLONG)LAYOUT.SdhIdxClusters * C,
1114 RtlZeroMemory(Val, 8);
1115 Val[0] = 0x01;
1116 MkAddResident(&Rec, AttributeBitmap, L"$SDH", 4, 0, Val, 8);
1117 MkFinalize(&Rec);
1118 }
1119
1120 /* Record 10: $UpCase (+ $Info CRC stream). */
1123 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1125 sizeof(UPCASE_TABLE), sizeof(UPCASE_TABLE),
1126 Now, L"$UpCase", FILE_NAME_WIN32_AND_DOS);
1128 Runs[0].Lcn = LAYOUT.UpCaseLcn; Runs[0].Len = LAYOUT.UpCaseClusters;
1129 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, Runs, 1, LAYOUT.UpCaseClusters - 1,
1130 (ULONGLONG)LAYOUT.UpCaseClusters * C, sizeof(UPCASE_TABLE), sizeof(UPCASE_TABLE));
1131 MkAddResident(&Rec, AttributeData, L"$Info", 5, 0, UpCaseInfo, sizeof(UpCaseInfo));
1132 MkFinalize(&Rec);
1133
1134 /* ---- $Extend children (build children before their index parents) --- */
1135
1136 /* Record 24: $Quota (default quota entries). */
1137 {
1138 BYTE Qce[64];
1139 BYTE QKey1[4];
1140 BYTE QKey256[4];
1141 BYTE OData[4];
1142 BYTE QIdx[256];
1143 BYTE OIdx[128];
1144 MK_VIEW_ENTRY QEnt[2];
1145 MK_VIEW_ENTRY OEnt[1];
1146
1147 RtlZeroMemory(Qce, sizeof(Qce));
1148 WR32(Qce, 0x00, 2); /* version */
1149 WR32(Qce, 0x04, 1); /* flags */
1150 WR64(Qce, 0x08, 0); /* bytes used */
1151 WR64(Qce, 0x10, Now); /* change time */
1152 WR64(Qce, 0x18, 0xFFFFFFFFFFFFFFFFULL); /* threshold */
1153 WR64(Qce, 0x20, 0xFFFFFFFFFFFFFFFFULL); /* limit */
1154 WR64(Qce, 0x28, 0); /* exceeded time */
1155 RtlCopyMemory(Qce + 48, SidAdmins, 16); /* id 0x100 carries the SID */
1156
1157 WR32(QKey1, 0, 1);
1158 WR32(QKey256, 0, 0x100);
1159 WR32(OData, 0, 0x100);
1160
1161 QEnt[0].Key = QKey1; QEnt[0].KeyLen = 4; QEnt[0].Data = Qce; QEnt[0].DataLen = 48;
1162 QEnt[1].Key = QKey256; QEnt[1].KeyLen = 4; QEnt[1].Data = Qce; QEnt[1].DataLen = 64;
1163 OEnt[0].Key = SidAdmins; OEnt[0].KeyLen = 16; OEnt[0].Data = OData; OEnt[0].DataLen = 4;
1164
1167 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM | FA_VIEW, Now, 0x101);
1168 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1170 0, 0, Now, L"$Quota", FILE_NAME_POSIX);
1172 Len = MkViewRootN(OIdx, COLL_SID, OEnt, 1);
1173 MkAddResident(&Rec, AttributeIndexRoot, L"$O", 2, 0, OIdx, Len);
1174 Len = MkViewRootN(QIdx, COLLATION_NTOFS_ULONG, QEnt, 2);
1175 MkAddResident(&Rec, AttributeIndexRoot, L"$Q", 2, 0, QIdx, Len);
1176 MkFinalize(&Rec);
1177 }
1178
1179 /* Record 25: $ObjId (empty $O). */
1182 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM | FA_VIEW, Now, 0x101);
1183 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1185 0, 0, Now, L"$ObjId", FILE_NAME_POSIX);
1188 MkAddResident(&Rec, AttributeIndexRoot, L"$O", 2, 0, Val, Len);
1189 MkFinalize(&Rec);
1190
1191 /* Record 26: $Reparse (empty $R). */
1194 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM | FA_VIEW, Now, 0x101);
1195 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1197 0, 0, Now, L"$Reparse", FILE_NAME_POSIX);
1200 MkAddResident(&Rec, AttributeIndexRoot, L"$R", 2, 0, Val, Len);
1201 MkFinalize(&Rec);
1202
1203 /* Records 12..15: reserved stubs - in use, 0 hard links, short STD_INFO,
1204 * embedded default descriptor 0x101, empty resident unnamed $DATA. */
1205 for (i = 12; i <= 15; i++)
1206 {
1208 MkSetHardLinks(&Rec, 0);
1210 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 48);
1212 DefaultSds + SdBlobOff[1], DefaultSdLen[1]);
1213 MkAddResident(&Rec, AttributeData, NULL, 0, 0, NULL, 0);
1214 MkFinalize(&Rec);
1215 }
1216
1217 /* ---- $Extend/$RmMetadata TxF subtree ------------------------------ */
1218
1219 /* Record 28: $Repair - empty non-resident $DATA + $DATA:$Config. */
1221 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM, Now, 0x101);
1222 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1224 0, 0, Now, L"$Repair", FILE_NAME_POSIX);
1226 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, NULL, 0, (ULONGLONG)-1, 0, 0, 0);
1227 MkAddResident(&Rec, AttributeData, L"$Config", 7, 0, RepairCfg, sizeof(RepairCfg));
1228 MkFinalize(&Rec);
1229
1230 /* Record 29: $Deleted - empty dir with a pre-allocated (unused) 64 KiB index. */
1233 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM, Now, 0x101);
1234 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1236 0, 0, Now, L"$Deleted", FILE_NAME_POSIX);
1238 Len = MkEmptyI30Root(Val);
1239 MkAddResident(&Rec, AttributeIndexRoot, L"$I30", 4, 0, Val, Len);
1240 Runs[0].Lcn = LAYOUT.DeletedIdxLcn; Runs[0].Len = LAYOUT.DeletedIdxClusters;
1241 MkAddNonResident(&Rec, AttributeIndexAllocation, L"$I30", 4, 0, Runs, 1,
1242 LAYOUT.DeletedIdxClusters - 1, (ULONGLONG)LAYOUT.DeletedIdxClusters * C, 0, 0);
1243 RtlZeroMemory(Val, 8);
1244 MkAddResident(&Rec, AttributeBitmap, L"$I30", 4, 0, Val, 8);
1245 MkFinalize(&Rec);
1246
1247 /* Record 31: $Txf - empty dir + $TXF_DATA. */
1249 MkStdInfo(Val, 0x80000006, Now, 0x102);
1250 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1252 0, 0, Now, L"$Txf", FILE_NAME_POSIX);
1254 Len = MkEmptyI30Root(Val);
1255 MkAddResident(&Rec, AttributeIndexRoot, L"$I30", 4, 0, Val, Len);
1256 MkAddResident(&Rec, AttributeLoggedUtilityStream, L"$TXF_DATA", 9, 0, TxfInfo, sizeof(TxfInfo));
1257 MkFinalize(&Rec);
1258
1259 /* Record 32: $Tops - resident $DATA + $DATA:$T (1 MiB). */
1261 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM, Now, 0x102);
1262 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1264 0, 0, Now, L"$Tops", FILE_NAME_POSIX);
1266 MkAddResident(&Rec, AttributeData, NULL, 0, 0, TopsData, sizeof(TopsData));
1267 Runs[0].Lcn = LAYOUT.TopsTLcn; Runs[0].Len = LAYOUT.TopsTClusters;
1268 MkAddNonResident(&Rec, AttributeData, L"$T", 2, 0, Runs, 1, LAYOUT.TopsTClusters - 1,
1269 (ULONGLONG)LAYOUT.TopsTClusters * C,
1270 (ULONGLONG)LAYOUT.TopsTClusters * C, (ULONGLONG)LAYOUT.TopsTClusters * C);
1271 MkFinalize(&Rec);
1272
1273 /* Record 33: $TxfLog.blf (64 KiB). */
1275 MkStdInfo(Val, FA_ARCHIVE, Now, 0x103);
1276 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1278 (ULONGLONG)LAYOUT.BlfClusters * C, 0, Now, L"$TxfLog.blf", FILE_NAME_POSIX);
1280 Runs[0].Lcn = LAYOUT.BlfLcn; Runs[0].Len = LAYOUT.BlfClusters;
1281 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, Runs, 1, LAYOUT.BlfClusters - 1,
1282 (ULONGLONG)LAYOUT.BlfClusters * C,
1283 (ULONGLONG)LAYOUT.BlfClusters * C, (ULONGLONG)LAYOUT.BlfClusters * C);
1284 MkFinalize(&Rec);
1285
1286 /* Records 34/35: $TxfLogContainer...0001 / ...0002 (2 MiB each). */
1288 MkStdInfo(Val, FA_ARCHIVE, Now, 0x104);
1289 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1291 (ULONGLONG)LAYOUT.Cont1Clusters * C, 0, Now,
1292 L"$TxfLogContainer00000000000000000001", FILE_NAME_POSIX);
1294 Runs[0].Lcn = LAYOUT.Cont1Lcn; Runs[0].Len = LAYOUT.Cont1Clusters;
1295 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, Runs, 1, LAYOUT.Cont1Clusters - 1,
1296 (ULONGLONG)LAYOUT.Cont1Clusters * C,
1297 (ULONGLONG)LAYOUT.Cont1Clusters * C, (ULONGLONG)LAYOUT.Cont1Clusters * C);
1298 MkFinalize(&Rec);
1299
1301 MkStdInfo(Val, FA_ARCHIVE, Now, 0x104);
1302 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1304 (ULONGLONG)LAYOUT.Cont2Clusters * C, 0, Now,
1305 L"$TxfLogContainer00000000000000000002", FILE_NAME_POSIX);
1307 Runs[0].Lcn = LAYOUT.Cont2Lcn; Runs[0].Len = LAYOUT.Cont2Clusters;
1308 MkAddNonResident(&Rec, AttributeData, NULL, 0, 0, Runs, 1, LAYOUT.Cont2Clusters - 1,
1309 (ULONGLONG)LAYOUT.Cont2Clusters * C,
1310 (ULONGLONG)LAYOUT.Cont2Clusters * C, (ULONGLONG)LAYOUT.Cont2Clusters * C);
1311 MkFinalize(&Rec);
1312
1313 /* Record 30: $TxfLog directory, indexing $Tops/$TxfLog.blf/containers. */
1314 {
1315 static const ULONG TxfLogOrder[] = { MREC_TOPS, MREC_TXFBLF, MREC_CONT1, MREC_CONT2 };
1316
1318 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM, Now, 0x102);
1319 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1321 0, 0, Now, L"$TxfLog", FILE_NAME_POSIX);
1323 Len = MkI30RootWithEntries(Val, Mft, TxfLogOrder, ARR_SIZE(TxfLogOrder));
1324 MkAddResident(&Rec, AttributeIndexRoot, L"$I30", 4, 0, Val, Len);
1325 MkFinalize(&Rec);
1326 }
1327
1328 /* Record 27: $RmMetadata directory, indexing $Repair/$Txf/$TxfLog. */
1329 {
1330 static const ULONG RmOrder[] = { MREC_REPAIR, MREC_TXF, MREC_TXFLOG };
1331
1333 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM, Now, 0x102);
1334 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1336 0, 0, Now, L"$RmMetadata", FILE_NAME_POSIX);
1338 Len = MkI30RootWithEntries(Val, Mft, RmOrder, ARR_SIZE(RmOrder));
1339 MkAddResident(&Rec, AttributeIndexRoot, L"$I30", 4, 0, Val, Len);
1340 MkFinalize(&Rec);
1341 }
1342
1343 /* Record 11: $Extend directory, indexing all children (collation order
1344 * $Deleted < $ObjId < $Quota < $Reparse < $RmMetadata). The directory
1345 * bit is set in FILE_NAME but not in STD_INFO. */
1346 {
1347 static const ULONG ExtendOrder[] =
1349
1351 MkStdInfo(Val, FA_HIDDEN | FA_SYSTEM, Now, 0x101);
1352 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 72);
1354 0, 0, Now, L"$Extend", FILE_NAME_WIN32_AND_DOS);
1356 Len = MkI30RootWithEntries(Val, Mft, ExtendOrder, ARR_SIZE(ExtendOrder));
1357 MkAddResident(&Rec, AttributeIndexRoot, L"$I30", 4, 0, Val, Len);
1358 MkFinalize(&Rec);
1359 }
1360
1361 /* Record 5: root "." - large $I30 index + embedded (unique) SD + $TXF_DATA. */
1364 MkAddResident(&Rec, AttributeStandardInformation, NULL, 0, 0, Val, 48);
1366 0, 0, Now, L".", FILE_NAME_WIN32_AND_DOS);
1369 Len = MkLargeI30Root(Val);
1370 MkAddResident(&Rec, AttributeIndexRoot, L"$I30", 4, 0, Val, Len);
1371 Runs[0].Lcn = LAYOUT.RootIdxLcn; Runs[0].Len = LAYOUT.RootIdxClusters;
1372 MkAddNonResident(&Rec, AttributeIndexAllocation, L"$I30", 4, 0, Runs, 1,
1373 LAYOUT.RootIdxClusters - 1, (ULONGLONG)LAYOUT.RootIdxClusters * C,
1375 RtlZeroMemory(Val, 8);
1376 Val[0] = 0x01; /* INDX VCN 0 allocated */
1377 MkAddResident(&Rec, AttributeBitmap, L"$I30", 4, 0, Val, 8);
1378 MkAddResident(&Rec, AttributeLoggedUtilityStream, L"$TXF_DATA", 9, 0,
1379 TxfDataValue, sizeof(TxfDataValue));
1380 MkFinalize(&Rec);
1381
1382 #undef REC_BUF
1383 }
1384
1385 /* --- Emit everything to disk ---------------------------------------- */
1386
1387 /* Zero the whole reserved $MFT region, then lay the 36 built records over
1388 * the start of it. Records 16..23 and 36+ are left zero (no FILE record). */
1389 Status = WriteZerosToClusters(LAYOUT.MftLcn, LAYOUT.MftClusters);
1390 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: clear $MFT (Status %lx)\n", Status); goto done; }
1391
1393 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: write $MFT (Status %lx)\n", Status); goto done; }
1394
1395 /* $MFTMirr = the first four records. */
1396 Status = WriteRegion(LAYOUT.MftMirrLcn, LAYOUT.MftMirrClusters, Mft, MFT_MIRR_COUNT * MFT_RECORD_SIZE);
1397 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: write $MFTMirr (Status %lx)\n", Status); goto done; }
1398
1399 /* $LogFile: fill 0xFF (a driver treats an all-0xFF log as uninitialized). */
1400 Status = WritePatternToClusters(LAYOUT.LogFileLcn, LAYOUT.LogFileClusters, 0xFF);
1401 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: write $LogFile (Status %lx)\n", Status); goto done; }
1402
1403 /* $AttrDef. */
1404 Status = WriteRegion(LAYOUT.AttrDefLcn, LAYOUT.AttrDefClusters, &ATTRIBUTES_TABLE, sizeof(ATTRIBUTES_TABLE));
1405 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: write $AttrDef (Status %lx)\n", Status); goto done; }
1406
1407 /* $UpCase. */
1408 Status = WriteRegion(LAYOUT.UpCaseLcn, LAYOUT.UpCaseClusters, &UPCASE_TABLE, sizeof(UPCASE_TABLE));
1409 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: write $UpCase (Status %lx)\n", Status); goto done; }
1410
1411 /* $Secure:$SDS - the 8 descriptors (16-byte aligned) with a duplicate copy
1412 * of the whole set placed 256 KiB further on. */
1413 {
1414 ULONG Size = LAYOUT.SdsClusters * BYTES_PER_CLUSTER;
1415 PBYTE Buf = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
1416 if (!Buf) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; }
1417 RtlZeroMemory(Buf, Size);
1418 for (i = 0; i < NTFS_DEFAULT_SD_COUNT; i++)
1419 {
1420 ULONG EntryLen = 0x14 + DefaultSdLen[i];
1421 PBYTE E = Buf + SdSdsOff[i];
1422 WR32(E, 0x00, SdHash[i]);
1423 WR32(E, 0x04, 0x100 + i);
1424 WR64(E, 0x08, SdSdsOff[i]);
1425 WR32(E, 0x10, EntryLen);
1426 RtlCopyMemory(E + 0x14, DefaultSds + SdBlobOff[i], DefaultSdLen[i]);
1427 /* The copy is identical to the primary, offset field included (it
1428 * keeps pointing at the primary, not at the copy). */
1429 RtlCopyMemory(Buf + NTFS_SDS_MIRROR + SdSdsOff[i], E, EntryLen);
1430 }
1431 Status = WriteAt(LAYOUT.SdsLcn, Buf, Size);
1432 FREE(Buf);
1433 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: write $SDS (Status %lx)\n", Status); goto done; }
1434 }
1435
1436 /* $Secure:$SDH INDX block (8 entries keyed by {hash,id}, hash order). */
1437 {
1438 BYTE SdsHdr[NTFS_DEFAULT_SD_COUNT][0x14];
1439 BYTE SdhKeys[NTFS_DEFAULT_SD_COUNT][8];
1441 PBYTE Indx;
1442
1443 for (i = 0; i < NTFS_DEFAULT_SD_COUNT; i++)
1444 {
1445 ULONG Id = 0x100 + i;
1446 WR32(SdsHdr[i], 0x00, SdHash[i]);
1447 WR32(SdsHdr[i], 0x04, Id);
1448 WR64(SdsHdr[i], 0x08, SdSdsOff[i]);
1449 WR32(SdsHdr[i], 0x10, 0x14 + DefaultSdLen[i]);
1450 WR32(SdhKeys[i], 0, SdHash[i]);
1451 WR32(SdhKeys[i], 4, Id);
1452 }
1453 for (i = 0; i < NTFS_DEFAULT_SD_COUNT; i++)
1454 {
1455 BYTE J = SdhOrder[i];
1456 SdhEnt[i].Key = SdhKeys[J]; SdhEnt[i].KeyLen = 8;
1457 SdhEnt[i].Data = SdsHdr[J]; SdhEnt[i].DataLen = 0x14;
1458 }
1459
1460 Indx = RtlAllocateHeap(RtlGetProcessHeap(), 0, INDEX_RECORD_SIZE);
1461 if (!Indx) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; }
1463 Status = WriteRegion(LAYOUT.SdhIdxLcn, LAYOUT.SdhIdxClusters, Indx, INDEX_RECORD_SIZE);
1464 FREE(Indx);
1465 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: write $SDH (Status %lx)\n", Status); goto done; }
1466 }
1467
1468 /* $MFT:$BITMAP - records 0..15 and 24..35 in use. */
1469 {
1470 ULONG Size = LAYOUT.MftBitmapClusters * BYTES_PER_CLUSTER;
1471 PBYTE Buf = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
1472 if (!Buf) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; }
1473 RtlZeroMemory(Buf, Size);
1474 Buf[0] = 0xFF; Buf[1] = 0xFF; /* records 0..15 */
1475 Buf[3] = 0xFF; Buf[4] = 0x0F; /* records 24..35 */
1476 Status = WriteAt(LAYOUT.MftBitmapLcn, Buf, Size);
1477 FREE(Buf);
1478 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: write $MFT:$BITMAP (Status %lx)\n", Status); goto done; }
1479 }
1480
1481 /* Cluster $Bitmap: metadata clusters [0, FirstFreeLcn) used, the rest free,
1482 * and the bits past ClusterCount (up to the 8-byte-aligned end) set. */
1483 {
1484 ULONG Size = LAYOUT.BitmapClusters * BYTES_PER_CLUSTER;
1485 ULONGLONG BitmapBytes = (((ClusterCount + 7) / 8) + 7) & ~7ULL;
1486 ULONGLONG BitmapBits = BitmapBytes * 8;
1487 ULONGLONG c;
1488 PBYTE Buf = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
1489 if (!Buf) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; }
1490 RtlZeroMemory(Buf, Size);
1491 for (c = 0; c < LAYOUT.FirstFreeLcn; c++)
1492 Buf[c / 8] |= (1 << (c % 8));
1493 for (c = ClusterCount; c < BitmapBits; c++)
1494 Buf[c / 8] |= (1 << (c % 8));
1495 Status = WriteAt(LAYOUT.BitmapLcn, Buf, Size);
1496 FREE(Buf);
1497 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: write $Bitmap (Status %lx)\n", Status); goto done; }
1498 }
1499
1500 /* Root $I30 INDX block: the system files in collation (uppercased-name)
1501 * order. "$" names (0x24) sort before root's own "." (0x2E), which is last. */
1502 {
1503 static const ULONG RootOrder[] =
1504 {
1508 };
1509 PBYTE Indx = RtlAllocateHeap(RtlGetProcessHeap(), 0, INDEX_RECORD_SIZE);
1510 if (!Indx) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; }
1511 MkRootIndxBlock(Indx, Mft, RootOrder, ARR_SIZE(RootOrder));
1512 Status = WriteRegion(LAYOUT.RootIdxLcn, LAYOUT.RootIdxClusters, Indx, INDEX_RECORD_SIZE);
1513 FREE(Indx);
1514 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: write root index (Status %lx)\n", Status); goto done; }
1515 }
1516
1517 /* Zero the TxF payload streams (CLFS logs are empty on a fresh volume). */
1518 Status = WriteZerosToClusters(LAYOUT.TopsTLcn, LAYOUT.TopsTClusters);
1519 if (NT_SUCCESS(Status)) Status = WriteZerosToClusters(LAYOUT.BlfLcn, LAYOUT.BlfClusters);
1520 if (NT_SUCCESS(Status)) Status = WriteZerosToClusters(LAYOUT.Cont1Lcn, LAYOUT.Cont1Clusters);
1521 if (NT_SUCCESS(Status)) Status = WriteZerosToClusters(LAYOUT.Cont2Lcn, LAYOUT.Cont2Clusters);
1522 if (NT_SUCCESS(Status)) Status = WriteZerosToClusters(LAYOUT.DeletedIdxLcn, LAYOUT.DeletedIdxClusters);
1523 if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: zero TxF payloads (Status %lx)\n", Status); goto done; }
1524
1525done:
1526 FREE(Val);
1527 FREE(Mft);
1528 return Status;
1529}
DWORD Id
#define ALIGN_UP_BY(size, align)
#define FREE(ptr, size)
Definition: auth_des.c:64
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:616
Definition: terminate.cpp:24
const BYTE UPCASE_TABLE[]
Definition: data.h:62
const ATTR_DEF ATTRIBUTES_TABLE[]
Definition: data.h:41
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define COLLATION_NTOFS_ULONG
Definition: ntfs.h:230
@ AttributeVolumeName
Definition: ntfs.h:193
@ AttributeIndexRoot
Definition: ntfs.h:196
@ AttributeStandardInformation
Definition: ntfs.h:188
@ AttributeVolumeInformation
Definition: ntfs.h:194
@ AttributeSecurityDescriptor
Definition: ntfs.h:192
@ AttributeIndexAllocation
Definition: ntfs.h:197
@ AttributeLoggedUtilityStream
Definition: ntfs.h:203
@ AttributeData
Definition: ntfs.h:195
@ AttributeBitmap
Definition: ntfs.h:198
#define COLLATION_NTOFS_SECURITY_HASH
Definition: ntfs.h:232
#define RA_INDEXED
Definition: ntfs.h:266
Status
Definition: gdiplustypes.h:24
const GLubyte * c
Definition: glext.h:8905
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define c
Definition: ke_i.h:80
#define LABEL
Definition: ntfslib.h:64
#define ARR_SIZE(arr)
Definition: ntfslib.h:34
#define FILE_NAME_POSIX
Definition: ntfslib.h:131
#define NTFS_MINOR_VERSION
Definition: ntfslib.h:107
#define FILE_NAME_WIN32_AND_DOS
Definition: ntfslib.h:134
#define MFT_MIRR_COUNT
Definition: ntfslib.h:101
#define NTFS_SDS_MIRROR
Definition: ntfslib.h:245
#define NTFS_SECURITY_ID
Definition: ntfslib.h:110
#define FORMAT_TIME
Definition: ntfslib.h:264
#define NTFS_MAJOR_VERSION
Definition: ntfslib.h:106
@ MFT_RECORD_VIEW_INDEX
Definition: ntfslib.h:327
@ MFT_RECORD_IS_DIRECTORY
Definition: ntfslib.h:325
@ MFT_RECORD_IN_USE
Definition: ntfslib.h:324
@ MFT_RECORD_UNKNOWN1
Definition: ntfslib.h:326
static const BYTE TopsData[100]
Definition: refdata.h:93
static const BYTE TxfDataValue[56]
Definition: refdata.h:86
#define NTFS_DEFAULT_SD_COUNT
Definition: refdata.h:11
static const BYTE UpCaseInfo[32]
Definition: refdata.h:117
static const BYTE RepairCfg[8]
Definition: refdata.h:110
static const BYTE SidAdmins[16]
Definition: refdata.h:112
static const BYTE DefaultSds[716]
Definition: refdata.h:20
static const USHORT DefaultSdLen[NTFS_DEFAULT_SD_COUNT]
Definition: refdata.h:18
static const BYTE RootSdValue[228]
Definition: refdata.h:68
static const BYTE TxfInfo[56]
Definition: refdata.h:103
#define MREC_COUNT
Definition: files.c:56
#define MREC_VOLUME
Definition: files.c:35
#define MREC_DELETED
Definition: files.c:49
#define COLL_SID
Definition: files.c:66
#define MREC_TXF
Definition: files.c:51
#define MREC_SECURE
Definition: files.c:41
static VOID MkStdInfoShort(OUT PBYTE Out, IN ULONG FileAttributes, IN ULONGLONG Now)
Definition: files.c:377
#define MREC_UPCASE
Definition: files.c:42
#define MREC_CONT1
Definition: files.c:54
#define MREC_BADCLUS
Definition: files.c:40
#define MREC_BITMAP
Definition: files.c:38
#define MREC_TXFLOG
Definition: files.c:50
static ULONG MkViewRootN(OUT PBYTE Out, IN ULONG CollationRule, IN const MK_VIEW_ENTRY *Entries, IN ULONG Count)
Definition: files.c:591
static VOID MkRootIndxBlock(OUT PBYTE Blk, IN const BYTE *Mft, IN const ULONG *Order, IN ULONG Count)
Definition: files.c:725
static NTSTATUS WritePatternToClusters(IN ULONGLONG Address, IN ULONG ClustersCount, IN BYTE Pattern)
Definition: files.c:789
#define MREC_MFTMIRR
Definition: files.c:33
#define MREC_ROOT
Definition: files.c:37
static VOID MkStdInfo(OUT PBYTE Out, IN ULONG FileAttributes, IN ULONGLONG Now, IN ULONG SecurityId)
Definition: files.c:359
#define MREC_BOOT
Definition: files.c:39
#define MREC_TXFBLF
Definition: files.c:53
#define MREC_RMMETA
Definition: files.c:47
#define MREC_OBJID
Definition: files.c:45
static ULONG MkI30RootWithEntries(OUT PBYTE Out, IN const BYTE *Mft, IN const ULONG *Order, IN ULONG Count)
Definition: files.c:499
#define MREC_LOGFILE
Definition: files.c:34
#define MREC_REPAIR
Definition: files.c:48
static ULONG MkSecHash(IN const BYTE *Sd, IN ULONG Len)
Definition: files.c:639
#define FA_DIR
Definition: files.c:62
static NTSTATUS WriteAt(IN ULONGLONG Lcn, IN PVOID Buffer, IN ULONG Length)
Definition: files.c:774
#define FA_ARCHIVE
Definition: files.c:61
static ULONG MkLargeI30Root(OUT PBYTE Out)
Definition: files.c:478
#define MREC_REPARSE
Definition: files.c:46
static VOID MkSetHardLinks(IN MK_REC *Rec, IN USHORT Count)
Definition: files.c:222
#define REC_BUF(n)
static ULONG MkLargeViewRoot(OUT PBYTE Out, IN ULONG CollationRule)
Definition: files.c:568
#define FA_SYSTEM
Definition: files.c:60
static ULONG MkEmptyViewRoot(OUT PBYTE Out, IN ULONG CollationRule)
Definition: files.c:548
#define MREC_CONT2
Definition: files.c:55
static ULONG MkEmptyI30Root(OUT PBYTE Out)
Definition: files.c:458
#define MREC_ATTRDEF
Definition: files.c:36
static VOID MkAddResident(IN OUT MK_REC *Rec, IN ULONG Type, IN LPCWSTR Name, IN BYTE NameChars, IN BYTE ResidentFlags, IN const VOID *Value, IN ULONG ValueLen)
Definition: files.c:231
#define MREC_QUOTA
Definition: files.c:44
#define FA_HIDDEN
Definition: files.c:59
static NTSTATUS WriteZerosToClusters(IN ULONGLONG Address, IN ULONG ClustersCount)
Definition: files.c:836
static VOID MkFinalize(IN MK_REC *Rec)
Definition: files.c:327
static VOID MkInit(OUT MK_REC *Rec, IN PBYTE Buf, IN ULONG RecordNumber, IN USHORT Flags)
Definition: files.c:193
#define COLL_ULONGS
Definition: files.c:67
static VOID MkViewIndxBlock(OUT PBYTE Blk, IN const MK_VIEW_ENTRY *Entries, IN ULONG Count)
Definition: files.c:675
#define MREC_MFT
Definition: files.c:32
#define MREC_TOPS
Definition: files.c:52
#define FA_VIEW
Definition: files.c:63
static ULONG MkFileName(OUT PBYTE Out, IN ULONGLONG ParentRef, IN ULONG FileAttributes, IN ULONGLONG AllocSize, IN ULONGLONG RealSize, IN ULONGLONG Now, IN LPCWSTR Name, IN BYTE Namespace)
Definition: files.c:391
#define MREC_EXTEND
Definition: files.c:43
static NTSTATUS WriteRegion(IN ULONGLONG Lcn, IN ULONG Clusters, IN const VOID *Content, IN ULONG ContentLen)
Definition: files.c:845
static VOID MkAddNonResident(IN OUT MK_REC *Rec, IN ULONG Type, IN LPCWSTR Name, IN BYTE NameChars, IN USHORT Flags, IN const MK_RUN *Runs, IN ULONG RunCount, IN ULONGLONG HighVcn, IN ULONGLONG AllocSize, IN ULONGLONG RealSize, IN ULONGLONG InitSize)
Definition: files.c:267
Definition: files.c:95
Definition: files.c:89
Definition: files.c:102
USHORT DataLen
Definition: files.c:106
USHORT KeyLen
Definition: files.c:104
const BYTE * Key
Definition: files.c:103
const BYTE * Data
Definition: files.c:105
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539

Referenced by NtfsFormat().

◆ WritePatternToClusters()

static NTSTATUS WritePatternToClusters ( IN ULONGLONG  Address,
IN ULONG  ClustersCount,
IN BYTE  Pattern 
)
static

Definition at line 789 of file files.c.

792{
794 ULONG ChunkClusters;
795 ULONG ChunkBytes;
796 ULONG Remaining;
797 ULONGLONG Lcn;
799
800 if (ClustersCount == 0)
801 return STATUS_SUCCESS;
802
803 ChunkClusters = (1024 * 1024) / BYTES_PER_CLUSTER;
804 if (ChunkClusters == 0)
805 ChunkClusters = 1;
806 if (ChunkClusters > ClustersCount)
807 ChunkClusters = ClustersCount;
808 ChunkBytes = ChunkClusters * BYTES_PER_CLUSTER;
809
810 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ChunkBytes);
811 if (!Buffer)
813
814 RtlFillMemory(Buffer, ChunkBytes, Pattern);
815
816 Lcn = Address;
817 Remaining = ClustersCount;
818 while (Remaining > 0)
819 {
820 ULONG ThisClusters = (Remaining < ChunkClusters) ? Remaining : ChunkClusters;
821
822 Status = WriteAt(Lcn, Buffer, ThisClusters * BYTES_PER_CLUSTER);
823 if (!NT_SUCCESS(Status))
824 break;
825
826 Lcn += ThisClusters;
827 Remaining -= ThisClusters;
828 }
829
830 FREE(Buffer);
831 return Status;
832}
static WCHAR Address[46]
Definition: ping.c:68
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:603
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by WriteMetafiles(), and WriteZerosToClusters().

◆ WriteRegion()

static NTSTATUS WriteRegion ( IN ULONGLONG  Lcn,
IN ULONG  Clusters,
IN const VOID *  Content,
IN ULONG  ContentLen 
)
static

Definition at line 845 of file files.c.

849{
850 ULONG Size = Clusters * BYTES_PER_CLUSTER;
853
854 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
855 if (!Buffer)
857
859 if (Content && ContentLen)
860 RtlCopyMemory(Buffer, Content, ContentLen);
861
862 Status = WriteAt(Lcn, Buffer, Size);
863
864 FREE(Buffer);
865 return Status;
866}

Referenced by ConDrvWriteConsoleOutput(), ConDrvWriteConsoleOutputVDM(), IntWriteConsoleOutput(), and WriteMetafiles().

◆ WriteZerosToClusters()

static NTSTATUS WriteZerosToClusters ( IN ULONGLONG  Address,
IN ULONG  ClustersCount 
)
static

Definition at line 836 of file files.c.

838{
839 return WritePatternToClusters(Address, ClustersCount, 0x00);
840}

Referenced by WriteMetafiles().