template "NTFS FILE Record"

// X-Ways Software Technology AG
// To be applied to the NTFS Master File Table's (MFT's) FILE records.
// Fix-up bytes (update sequence number) are not processed.

description "To be applied to FILE Records in $MFT"
applies_to disk
sector-aligned

begin
	char[4]	"Signature: FILE"
	uint16	"Offset to update sequence"
	uint16	"Update sequence size in words"
	int64		"Logfile sequence number"
	uint16	"Use/deletion count"
	uint16 	"Hard-link count"
	uint16	"Offset to the first attribute"
	hexadecimal uint16 Flags
	uint32	"Logical size of this record"
	uint32	"Physical size of the record"
	uint32	"Base record (0: itself)"
	move 4 //skipping two unused and re-use count of the base record
	uint16	"ID of next attribute"
	IfGreater "Offset to the first attribute" 55
	move 2
	uint32 "ID of this FILE record"
	EndIf
	goto "Offset to update sequence"
	hex 2	"Update sequence number"
	hex 4 	"Update Sequence Array"  //value correct based on a 1K FILE Record size

	goto "Offset to the first attribute"

	{
		endsection

		hexadecimal uint32 "Attribute type"
		IfEqual "Attribute type" 4294967295
			ExitLoop
		EndIf

		IfEqual "Attribute type" 16 
			section "0x10: $STANDARD_INFORMATION"
		EndIf
		IfEqual "Attribute type" 32 
			section "0x20: $ATTRIBUTE_LIST"
		EndIf
		IfEqual "Attribute type" 48 
			section "0x30: $FILE_NAME"
		EndIf
		IfEqual "Attribute type" 64 
			section "0x40: $OBJECT_ID"
		EndIf
		IfEqual "Attribute type" 80 
			section "0x50: $SECURITY_DESCRIPTOR"
		EndIf
		IfEqual "Attribute type" 96 
			section "0x60: $VOLUME_NAME"
		EndIf
		IfEqual "Attribute type" 112 
			section "0x70: $VOLUME_INFORMATION"
		EndIf
		IfEqual "Attribute type" 128 
			section "0x80: $DATA"
		EndIf
		IfEqual "Attribute type" 144 
			section "0x90: $INDEX_ROOT"
		EndIf
		IfEqual "Attribute type" 160 
			section "0xA0: $INDEX_ALLOCATION"
		EndIf
		IfEqual "Attribute type" 176 
			section "0xB0: $BITMAP"
		EndIf
		IfEqual "Attribute type" 192 
			section "0xC0: $REPARSE_POINT"
		EndIf
		IfEqual "Attribute type" 208 
			section "0xD0: $EA_INFORMATION"
		EndIf
		IfEqual "Attribute type" 224 
			section "0xE0: $EA"
		EndIf
		IfEqual "Attribute type" 256 
			section "0x100: $LUS"
		EndIf


		hexadecimal uint16 "Length of the attribute"
		move 2
		uint8 "0=resident; 1=non-res."
		uint8 "AttrNameLen"
		uint16 "AttrNameOfs"
		hex 2 "Flags"
		uint16 "Attribute ID"

		move -16
		
		ifGreater AttrNameLen 0
			move AttrNameOfs

			char16[AttrNameLen] "Attr. name"	

			move (AttrNameLen*(-2)-AttrNameOfs)
		endif

		IfEqual "Attribute type" 16 //Attribute type 0x10: Standard Information
			move 24
			FileTime "Creation in UTC"
			FileTime "Modification in UTC"
			FileTime "Record change in UTC"
			FileTime "Last access in UTC"
			hexadecimal uint32 Flags
			move 16
			hex 4 "Security ID"
			move -80
		EndIf
		IfEqual "Attribute type" 48 //Attribute type 0x30: Filename
			move 24
			uint32	"Parent FILE record"
			move 2
			uint16	"Parent use/del. count"
			FileTime "Creation in UTC"
			FileTime "Modification in UTC"
			FileTime "Record change in UTC"
			FileTime "Last access in UTC"
			move 0x18
			uint8 "Namelen"
			uint8 "Namespace"
			char16[Namelen] "Filename"
			move -90
			move (Namelen*(-2))
		EndIf
		IfEqual "Attribute type" 64 //Attribute type 0x40: Object ID
			move 24
			GUID	"Object ID"
			move -40
		EndIf

		IfEqual "Attribute type" 80 //Attribute type 0x50: Security Descriptor
			move 28
			uint16 "OfsUID"
			move 2
			uint16 "OfsGID"
			
			move (OfsUID-10)
			hex (OfsGID-OfsUID) "User SID"
			move (OfsGID*(-1)-24)
		EndIf

		IfEqual "Attribute type" 96 //Attribute type 0x60: Volume Name
			move 16
			uint16 "SizeInBytes"
			move 6
			char16[(SizeInBytes/2)] "Volume Label"
			move ((24+SizeInBytes)*(-1))
		EndIf
		IfEqual "Attribute type" 112 //Attribute type 0x70: Volume Information
			move 32
			uint8 "VersionMajor"
			uint8 "VersionMinor"
			hex 2 "Dirty Flags"
			move -36
		EndIf

		move "Length of the attribute"

		IfEqual "Length of the attribute" 0
			ExitLoop
		EndIf
	}[16] //arbitrary number to avoid infinite loops
	
	Goto 0
	Move "Physical size of the record"
end