ReFS Reference

$STANDARD_INFORMATION ($SI)

$STANDARD_INFORMATION ($SI) is the most forensically important attribute — every file and directory has exactly one, carrying all timestamps, the file attributes, the SecurityId, and the per-file USN link. Structurally it is not an embedded sub-record: it occupies the fixed region of the object’s type-0x10 own-row value (read $SI only from a type-0x10 row). Its layout differs between v3.4 and v3.7+ in a non-backward-compatible way — the same byte offsets mean different things by version, so a parser must know the version first.

Value layout

Common fields (all versions, 0x00–0x57)

OffsetSizeFieldDescription
0x008Creation timeFILETIME (100 ns since 1601-01-01)
0x088Modification timelast content modification
0x108MFT change timelast metadata modification
0x188Last access timenot updated on read by default
0x204File attributesWin32 FILE_ATTRIBUTE_*. Bit 28 (the ReFS directory flag) is masked on Win10, preserved on Win11
0x244Internal flags6-bit field on v3.14+; 0 on v3.4–v3.10 (see Internal flags)
0x288Security IDresolves directly in the security table (OID 0x530)
0x308USN slot — unpopulatedAlways 0 in the type-0x10 $SI (0 non-zero across 32,629 own-rows). The live per-file→journal link is LastUsn at 0x40
0x388DataSize slot — unpopulatedAlways 0 in the type-0x10 $SI (0 non-zero across 32,629 own-rows). The PDB label (LastMftChangeTime) notwithstanding, it carries neither a timestamp nor a size
0x408LastUsnthe file’s last USN = byte offset of its most recent record in $UsnJrnl:$J (8-byte aligned; upper 32 bits always 0). See LastUsn / UsnJournalId
0x488UsnJournalIda FILETIME identifying the journal instance — one distinct value per volume
0x504PackedEaSize / ReparseTagLow16version-dependent: v3.10+ = PackedEaSize (EA size); v3.4–v3.9 = low 16 bits of the ReparseTag
0x544ReparseTagIO_REPARSE_TAG_* (0 if none)

v3.4 extension (Win10) — total 116 bytes (0x74)

OffsetSizeFieldDescription
0x588NextFileId ordinal (ExternalFileId_1)the directory child-creation ordinal (see NextFileId ordinal); non-zero on every v3.4 entry
0x608ExternalFileId_2cross-volume file-identity word; normally 0 same-volume, carries the source-volume id only for cross-volume-copied content. Co-occurs with ExternalFileId_3
0x688ExternalFileId_3the source parent-directory OID; 0 if same-volume
0x704HardLinkCountalways 1 on disk — a resident-layout field; genuine hard links are non-resident and counted by the shared FileId. The increment path exists but is unexercised

v3.7+ extension (Win11) — total 124 bytes (0x7C)

OffsetSizeFieldDescription
0x588NextFileId ordinalthe directory child-creation ordinal; persisted to the own-row only when version < 0x30b (v3.11), so 0 on native v3.14 own-rows while resident files stay populated. See NextFileId ordinal
0x608ExternalFileId_2cross-volume file-identity word; 0 on native v3.7+, non-zero only as upgrade carryover
0x688ExternalFileId_3source parent-directory OID; 0 on native v3.7+, non-zero only as upgrade carryover
0x704HardLinkCountread from FCB+0xb4; always 1 on disk (hard links promote to non-resident, counted by the shared FileId). On a non-resident own-row it reads 0 and is re-sourced from the resident FCB — do not treat 0 as corruption
0x748NextStreamSetIdper-file next-stream-set-ID allocator, base 0xF000; non-zero only on a file owning an extra stream set

The mapper enforces the size: a Win10 driver requires value > 0x73 (≥116 B), a Win11 driver requires value > 0x7b (≥124 B) — which is why a Win11 driver rejects a Win10-sized $SI.

Internal flags

A 6-bit field at $SI+0x24, 0 on v3.4–v3.10, active on v3.14+. Bits 0–3 are computed by RefsComputeStandardInformationInternalFromFcb (from FCB+0x08); bits 4–5 are added by the caller via (FCB[0xf4] << 4) & 0x30.

BitMaskNameFCB sourceNotes
00x01DELETE / DISPOSITIONFCB+0x08 bit 27delete-disposition / EFS transient state — not integrity (the integrity marker is file_attrs 0x8000, never reflected here)
10x02DEDUP_OR_COWFCB+0x08 bit 22dedup / CoW related
20x04FLAG_0xBFCB+0x08 bit 11rarely observed; also set by the link-count-zero path
30x08FLAG_0x1FFCB+0x08 bit 31most common on v3.14 regular files
40x10FCB_F4_BIT0FCB[0xf4] bit 0
50x20SYMLINK_TRUSTFCB[0xf4] bit 1symlink/junction redirection-trust level (IoComputeRedirectionTrustLevel), written only in RefsSetReparsePointInternal for tags 0xa000000c / 0xa0000003

LastUsn / UsnJournalId

$SI+0x40 and $SI+0x48 are the USN change-journal fields — written atomically (both zero or both non-zero), and non-zero only on a volume with an active USN journal (v3.14+):

  • $SI+0x40 = LastUsn — the byte offset of the file’s most recent record in $UsnJrnl:$J, taken from the journal write cursor (VCB+0x3a0) and cached in FCB+0xe0. Always 8-byte aligned.
  • $SI+0x48 = UsnJournalId — a FILETIME identifying the journal instance (VCB+0x388), one distinct value per volume.
  • The pair is gated by FCB bit 23 (“the cached LastUsn is valid for the current journal epoch”: set only when the journal is active and the on-disk UsnJournalId matches the current journal — a stale-epoch check, like NTFS journal-ID validation). Both are written by RefsWriteFcbUsnRecordToJournal.

NextFileId ordinal

$SI+0x58 (also ExternalFileId_1 on v3.4) is the directory child-creation ordinal: a directory’s own-row holds NextFileId = max(child ordinal), and each resident child’s $SI+0x58 is its assigned ordinal. RefsMoveFile (the unified create/rename/link path) increments the parent directory’s NextFileId and stamps the child. It is persisted to the own-row only when version < 0x30b (v3.11) — so on native v3.14 the own-row reads 0 while the object-record payload carries it. A fresh directory starts at 1 (0/1 reserved); child ordinals are near-contiguous from 2. It is not a per-write counter.

The two “0x90"s — $SI is not $I30_INDEX

A common trap: $SI is the type-0x10 own-row’s fixed region, and its schema slot is historically labeled 0x190 / embedded code 0x90. But the embedded type-0x90 sub-record is $I30_INDEX (the directory-index template), a different thing. Read $SI only from a type-0x10 row — a top-level type-0x90 row is $I30_INDEX, not $SI. See $I30_INDEX.

Driver functions

  • RefsMapStandardInfo — maps $SI from a B+-tree row (and enforces the min-size gate)
  • RefsGetStandardInfo / RefsSetStandardInfo — read / write (RefsSetStandardInfo via MsUpdateDataWithRoot)
  • RefsComputeStandardInformationFromFcb — builds $SI from the in-memory FCB state

Forensic value

FieldForensic value
Timestamps (0x00–0x18)the MACB timeline
LastUsn + UsnJournalId (0x40 / 0x48)the file’s last $UsnJrnl:$J offset and the journal instance (v3.14+)
ReparseTag (0x54)symlinks, mount points, WSL / WOF special files
PackedEaSize (0x50, v3.10+)presence of extended attributes
Internal flags (0x24, v3.14+)feature state (dedup / CoW); bit 5 = reparse own-row
NextFileId ordinal (0x58)directory child-creation order (versions < v3.11) — corroborating for timeline reasoning

Timestomping detection. ReFS carries one $SI timestamp set per name. For a single-named file there is no NTFS-style $SI-vs-$FN twin to compare — but a hard-linked file has one independent timestamp copy per name, and a name-scoped timestomp leaves the sibling names at the true birth (the latest Created among the siblings is the authentic one). Comparing a file’s names’ MACB is thus a ReFS-specific tamper check — journal-independent, and stronger than NTFS’s $SI-vs-$FN, where all hard links share one $SI and cannot diverge. For any file, timestomping is also detectable via the metadata-change time ($SI+0x10) (left at the real write moment by the high-level APIs that timestomp tools use), the USN journal (records the edit and the true create time — the stronger anchor), and the volume creation time (a hard lower bound). See Timestomping Detection.

Last access time. ReFS does not update last-access on read by default (RefsDisableLastAccessUpdate defaults to 1). Per-handle suppression bits at CCB+4 (bit 6 access / bit 5 modify / bit 4 change) are the in-driver timestomp-suppression bits, set when a caller supplies an explicit time via SetFileTime.

Raw example

A $STANDARD_INFORMATION value on a v3.14 image (a file created and untouched, so all four stamps match), value-relative offsets:

+0x00:  92 10 67 69 18 e6 dc 01    <- Created   (FILETIME)  2026-05-17 16:15
+0x08:  92 10 67 69 18 e6 dc 01    <- Modified  (FILETIME)
+0x10:  92 10 67 69 18 e6 dc 01    <- Changed   (FILETIME)
+0x18:  92 10 67 69 18 e6 dc 01    <- Accessed  (FILETIME)
+0x20:  00 00 00 00 00 00 00 00
+0x28:  62 9b 9f 0a 01 00 00 00    <- SecurityId 0x10a9f9b62 (resolves in the security table, OID 0x530)

The four 8-byte FILETIMEs sit at 0x00 / 0x08 / 0x10 / 0x18; SecurityId is the u32 at 0x28. (ReFS carries one timestamp set per name — there is no NTFS-style $FILE_NAME duplicate, but a hard-linked file has one such set per name, and those can diverge under a name-scoped timestomp.)

Cross-references

Evidence

The $SI layout, the version split, the internal-flag bits, and the USN / NextFileId resolutions are confirmed in the decompiled driver (RefsComputeStandardInformationFromFcb, RefsComputeStandardInformationInternalFromFcb, RefsWriteFcbUsnRecordToJournal, RefsMoveFile) and raw-disk decoded across the corpus. The per-name MACB timestomp cross-check is proven on disk on a hard-link pair (** / E59**).