1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
//
// AUTHOR
// N. Nielsen
//
// VERSION
// 0.7
//
// LICENSE
// This software is in the public domain.
//
// The software is provided "as is", without warranty of any kind,
// express or implied, including but not limited to the warranties
// of merchantability, fitness for a particular purpose, and
// noninfringement. In no event shall the author(s) be liable for any
// claim, damages, or other liability, whether in an action of
// contract, tort, or otherwise, arising from, out of, or in connection
// with the software or the use or other dealings in the software.
//
// SUPPORT
// Send bug reports to: <nielsen@memberwebs.com>
//
#ifndef __NTFS_H__
#define __NTFS_H__
#include "usuals.h"
#include "stddef.h"
#include "drive.h"
#pragma pack(push, ntfs)
#pragma pack(1)
// WARNING Assumptions:
const uint32 kNTFS_RecordLen = 0x0400;
const char kNTFS_SysId[] = "NTFS ";
struct NTFS_BootSector
{
byte jmp[3]; // Jump to the boot loader routine
char sysId[8]; // System Id: "NTFS "
uint16 bytePerSec; // Bytes per sector
byte secPerClus; // Sectors per cluster
byte padding[7]; // Unused
byte mediaDescriptor; // Media descriptor (a)
byte padding2[2]; // Unused
uint16 secPerTrack; // Sectors per track
uint16 numHeads; // Number of heads
byte padding3[8]; // Unused
uint32 signature; // Always 80 00 80 00
uint64 cSectors; // Number of sectors in the volume
uint64 offMFT; // LCN of VCN 0 of the $MFT
uint64 offMFTMirr; // LCN of VCN 0 of the $MFTMirr
uint32 clusPerMFT; // Clusters per MFT Record (b)
uint32 clusPerIndex; // Clusters per Index Record
uint64 serialNum; // Volume serial number
};
const uint32 kNTFS_RecMagic = 'ELIF';
const uint32 kNTFS_RecEnd = 0xFFFFFFFF;
const uint32 kNTFS_RecHeaderLen = 0x30;
const uint16 kNTFS_RecFlagUse = 0x01;
const uint16 kNTFS_RecFlagDir = 0x02;
struct NTFS_RecordHeader
{
uint32 magic; // Magic number 'FILE'
uint16 offUpdSeq; // Offset to the update sequence
uint16 cwUpdSeq; // Size in words of Update Sequence Number & Array (S)
uint64 logSeqNum; // $LogFile Sequence Number (LSN)
uint16 seqNum; // Sequence number
uint16 cHardlinks; // Hard link count
uint16 x_offUpdSeqArr; // Offset to Update Sequence Array (DON'T THINK SO)
uint16 flags; // Flags
uint32 cbRecord; // Real size of the FILE record
uint32 cbAllocated; // Allocated size of the FILE record
uint64 refBaseRecord; // File reference to the base FILE record
uint16 nextAttrId; // Next Attribute Id
uint16 padding; // (XP) Align to 4 byte boundary
uint32 recordNum; // (XP) Number of this MFT Record
};
const uint16 kNTFS_AttrCompressed = 0x0001;
const uint16 kNTFS_AttrEncrypted = 0x0002;
const uint16 kNTFS_AttrSparse = 0x0004;
struct NTFS_AttribHeader
{
uint32 type; // Attribute Type (e.g. 0x10, 0x60)
uint32 cbAttribute; // Length (including this header)
byte bNonResident; // Non-resident flag
byte cName; // Name length
uint16 offName; // Offset to the Attribute
uint16 flags; // Flags
uint16 idAttribute; // Attribute Id (a)
};
struct NTFS_AttribResident
{
NTFS_AttribHeader header;
uint32 cbAttribData; // Length of the Attribute
uint16 offAttribData; // Offset to the Attribute
byte bIndexed; // Indexed flag
byte padding; // 0x00 Padding
};
struct NTFS_AttribNonResident
{
NTFS_AttribHeader header;
uint64 startVCN; // Starting VCN
uint64 lastVCN; // Last VCN
uint16 offDataRuns; // Offset to the Data Runs
uint16 compUnitSize; // Compression Unit Size (b)
uint32 padding; // Padding
uint64 cbAllocated; // Allocated size of the attribute (c)
uint64 cbAttribData; // Real size of the attribute
uint64 cbInitData; // Initialized data size of the stream (d)
};
const uint32 kNTFS_ATTRIBUTE_LIST = 0x20;
const uint32 kNTFS_FILENAME = 0x30;
const uint32 kNTFS_DATA = 0x80;
const uint32 kNTFS_FileReadOnly = 0x0001;
const uint32 kNTFS_FileHidden = 0x0002;
const uint32 kNTFS_FileSystem = 0x0004;
const uint32 kNTFS_FileArchive = 0x0020;
const uint32 kNTFS_FileDevice = 0x0040;
const uint32 kNTFS_FileNormal = 0x0080;
const uint32 kNTFS_FileTemorary = 0x0100;
const uint32 kNTFS_FileSparse = 0x0200;
const uint32 kNTFS_FileReparse = 0x0400;
const uint32 kNTFS_FileCompressed = 0x0800;
const uint32 kNTFS_FileOffline = 0x1000;
const uint32 kNTFS_FileNotIndexed = 0x2000;
const uint32 kNTFS_FileEncrypted = 0x4000;
const byte kNTFS_NameSpacePOSIX = 0x00;
const byte kNTFS_NameSpaceWIN32 = 0x01;
const byte kNTFS_NameSpaceDOS = 0x02;
const byte kNTFS_NameSpaceWINDOS = 0x03;
const wchar_t kNTFS_MFTName[] = L"$MFT";
struct NTFS_AttrFileName
{
uint64 refParent; // File reference to the parent directory.
uint64 timeCreated; // C Time - File Creation
uint64 timeAltered; // A Time - File Altered
uint64 timeModified; // M Time - MFT Changed
uint64 timeRead; // R Time - File Read
uint64 cbAllocated; // Allocated size of the file
uint64 cbFileSize; // Real size of the file
uint32 flags; // Flags, e.g. Directory, compressed, hidden
uint32 eaReparse; // Used by EAs and Reparse
byte cFileName; // Filename length in characters (L)
byte nameSpace; // Filename namespace
// File Name comes here
};
struct NTFS_AttrListRecord
{
uint32 type; // Type
uint16 cbRecord; // Record length
byte cName; // Name length (N)
byte offName; // Offset to Name (a)
uint64 startVCN; // Starting VCN (b)
uint64 refAttrib; // Base File Reference of the attribute
uint16 idAttribute; // Attribute Id (c)
// Attribute name here
};
#pragma pack(pop, ntfs)
NTFS_AttribHeader* NTFS_FindAttribute(NTFS_RecordHeader* pRecord, uint32 attrType, void* pEnd);
NTFS_AttribHeader* NTFS_NextAttribute(NTFS_AttribHeader* pAttrib, uint32 attrType, void* pEnd);
void* NTFS_GetAttributeData(NTFS_AttribResident* pAttrib, void* pEnd);
bool NTFS_IsBetterNameSpace(byte n1, byte n2);
bool NTFS_DoFixups(byte* pCluster, uint32 cbCluster);
#define NTFS_RefToSector(info, ref) (((ref & 0xFFFFFFFFFFFF) * (kNTFS_RecordLen / kSectorSize)) + (info).firstSector + (info).offMFT)
#define NTFS_MakeFileTime(i64, ft) ((ft).dwLowDateTime = LOWDWORD(i64), (ft).dwHighDateTime = HIGHDWORD(i64))
//
// The record, attribute or whatever was invalid on disk
//
#define ERROR_NTFS_INVALID 10801L
#define ERROR_NTFS_NOTIMPLEMENT 10802L
#endif //__NTFS_H__
|