[PORTCLS]
[reactos.git] / rostests / tests / ntfs / ntfs.c
1 /*
2 * PROJECT: ReactOS NTFS tests/dump
3 * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Query information from NTFS volume using FSCTL and dumps $MFT
5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org>
6 */
7
8 #include <windows.h>
9 #include <stdio.h>
10
11 typedef struct
12 {
13 ULONG Type;
14 USHORT UsaOffset;
15 USHORT UsaCount;
16 ULONGLONG Lsn;
17 } NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER;
18
19 #define NRH_FILE_TYPE 0x454C4946
20
21 typedef struct _FILE_RECORD_HEADER
22 {
23 NTFS_RECORD_HEADER Ntfs;
24 USHORT SequenceNumber;
25 USHORT LinkCount;
26 USHORT AttributeOffset;
27 USHORT Flags;
28 ULONG BytesInUse;
29 ULONG BytesAllocated;
30 ULONGLONG BaseFileRecord;
31 USHORT NextAttributeNumber;
32 } FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;
33
34 typedef enum
35 {
36 AttributeStandardInformation = 0x10,
37 AttributeAttributeList = 0x20,
38 AttributeFileName = 0x30,
39 AttributeObjectId = 0x40,
40 AttributeSecurityDescriptor = 0x50,
41 AttributeVolumeName = 0x60,
42 AttributeVolumeInformation = 0x70,
43 AttributeData = 0x80,
44 AttributeIndexRoot = 0x90,
45 AttributeIndexAllocation = 0xA0,
46 AttributeBitmap = 0xB0,
47 AttributeReparsePoint = 0xC0,
48 AttributeEAInformation = 0xD0,
49 AttributeEA = 0xE0,
50 AttributePropertySet = 0xF0,
51 AttributeLoggedUtilityStream = 0x100,
52 AttributeEnd = 0xFFFFFFFF
53 } ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE;
54
55 typedef struct
56 {
57 ULONG Type;
58 ULONG Length;
59 UCHAR IsNonResident;
60 UCHAR NameLength;
61 USHORT NameOffset;
62 USHORT Flags;
63 USHORT Instance;
64 union
65 {
66 struct
67 {
68 ULONG ValueLength;
69 USHORT ValueOffset;
70 UCHAR Flags;
71 UCHAR Reserved;
72 } Resident;
73 struct
74 {
75 ULONGLONG LowestVCN;
76 ULONGLONG HighestVCN;
77 USHORT MappingPairsOffset;
78 USHORT CompressionUnit;
79 UCHAR Reserved[4];
80 LONGLONG AllocatedSize;
81 LONGLONG DataSize;
82 LONGLONG InitializedSize;
83 LONGLONG CompressedSize;
84 } NonResident;
85 };
86 } NTFS_ATTR_RECORD, *PNTFS_ATTR_RECORD;
87
88 typedef struct
89 {
90 ULONGLONG CreationTime;
91 ULONGLONG ChangeTime;
92 ULONGLONG LastWriteTime;
93 ULONGLONG LastAccessTime;
94 ULONG FileAttribute;
95 ULONG AlignmentOrReserved[3];
96 } STANDARD_INFORMATION, *PSTANDARD_INFORMATION;
97
98 typedef struct
99 {
100 ULONGLONG DirectoryFileReferenceNumber;
101 ULONGLONG CreationTime;
102 ULONGLONG ChangeTime;
103 ULONGLONG LastWriteTime;
104 ULONGLONG LastAccessTime;
105 ULONGLONG AllocatedSize;
106 ULONGLONG DataSize;
107 ULONG FileAttributes;
108 ULONG AlignmentOrReserved;
109 UCHAR NameLength;
110 UCHAR NameType;
111 WCHAR Name[1];
112 } FILENAME_ATTRIBUTE, *PFILENAME_ATTRIBUTE;
113
114 int main(int argc, char **argv)
115 {
116 static WCHAR VolumeName[] = L"\\\\.\\E:";
117 HANDLE VolumeHandle;
118 struct {
119 NTFS_VOLUME_DATA_BUFFER Data;
120 NTFS_EXTENDED_VOLUME_DATA Extended;
121 } VolumeInfo;
122 DWORD LengthReturned;
123 NTFS_FILE_RECORD_INPUT_BUFFER InputBuffer;
124 PNTFS_FILE_RECORD_OUTPUT_BUFFER OutputBuffer;
125 DWORD OutputLength;
126 PFILE_RECORD_HEADER FileRecord;
127 PNTFS_ATTR_RECORD Attribute;
128 DWORD k;
129
130 VolumeHandle = CreateFileW(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
131 if (VolumeHandle == INVALID_HANDLE_VALUE)
132 {
133 fprintf(stderr, "Failed opening volume!\n");
134 return -1;
135 }
136
137 if (!DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &VolumeInfo, sizeof(VolumeInfo), &LengthReturned, NULL))
138 {
139 fprintf(stderr, "Failed requesting volume data!\n");
140 CloseHandle(VolumeHandle);
141 return -1;
142 }
143
144 printf("Using NTFS: %u.%u\n", VolumeInfo.Extended.MajorVersion, VolumeInfo.Extended.MinorVersion);
145
146 InputBuffer.FileReferenceNumber.QuadPart = 0LL;
147 OutputLength = sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER) + VolumeInfo.Data.BytesPerFileRecordSegment;
148 OutputBuffer = malloc(OutputLength);
149 if (OutputBuffer == NULL)
150 {
151 fprintf(stderr, "Allocation failure!\n");
152 CloseHandle(VolumeHandle);
153 }
154
155 if (!DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_FILE_RECORD, &InputBuffer, sizeof(InputBuffer), OutputBuffer, OutputLength, &LengthReturned, NULL))
156 {
157 fprintf(stderr, "Failed opening $MFT!\n");
158 free(OutputBuffer);
159 CloseHandle(VolumeHandle);
160 return -1;
161 }
162
163 if (OutputBuffer->FileReferenceNumber.QuadPart != 0LL)
164 {
165 fprintf(stderr, "Wrong entry read! %I64x\n", OutputBuffer->FileReferenceNumber.QuadPart);
166 free(OutputBuffer);
167 CloseHandle(VolumeHandle);
168 return -1;
169 }
170
171 FileRecord = (PFILE_RECORD_HEADER)OutputBuffer->FileRecordBuffer;
172 if (FileRecord->Ntfs.Type != NRH_FILE_TYPE)
173 {
174 fprintf(stderr, "Wrong type read! %lx\n", FileRecord->Ntfs.Type);
175 free(OutputBuffer);
176 CloseHandle(VolumeHandle);
177 return -1;
178 }
179
180 printf("File record size: %lu. Read file record size: %lu\n", VolumeInfo.Data.BytesPerFileRecordSegment, OutputBuffer->FileRecordLength);
181 printf("SequenceNumber: %u\n", FileRecord->SequenceNumber);
182 printf("LinkCount: %u\n", FileRecord->LinkCount);
183 printf("AttributeOffset: %u\n", FileRecord->AttributeOffset);
184 printf("Flags: %u\n", FileRecord->Flags);
185 printf("BytesInUse: %lu\n", FileRecord->BytesInUse);
186 printf("BytesAllocated: %lu\n", FileRecord->BytesAllocated);
187 printf("BaseFileRecord: %I64x\n", FileRecord->BaseFileRecord);
188 printf("NextAttributeNumber: %u\n", FileRecord->NextAttributeNumber);
189
190 Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
191 while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) &&
192 Attribute->Type != AttributeEnd)
193 {
194 PSTANDARD_INFORMATION StdInfo;
195 PFILENAME_ATTRIBUTE FileName;
196
197 if (!Attribute->IsNonResident)
198 {
199 switch (Attribute->Type)
200 {
201 case AttributeStandardInformation:
202 StdInfo = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
203 printf("\t$STANDARD_INFORMATION:\n");
204 printf("\tCreationTime: %I64u\n", StdInfo->CreationTime);
205 printf("\tChangeTime: %I64u\n", StdInfo->ChangeTime);
206 printf("\tLastWriteTime: %I64u\n", StdInfo->LastWriteTime);
207 printf("\tLastAccessTime: %I64u\n", StdInfo->LastAccessTime);
208 printf("\tFileAttribute: %lu\n", StdInfo->FileAttribute);
209 break;
210
211 case AttributeFileName:
212 FileName = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
213 printf("\t$FILE_NAME:\n");
214 printf("\tDirectoryFileReferenceNumber: %I64u\n", FileName->DirectoryFileReferenceNumber);
215 printf("\tCreationTime: %I64u\n", FileName->CreationTime);
216 printf("\tChangeTime: %I64u\n", FileName->ChangeTime);
217 printf("\tLastWriteTime: %I64u\n", FileName->LastWriteTime);
218 printf("\tLastAccessTime: %I64u\n", FileName->LastAccessTime);
219 printf("\tAllocatedSize: %I64u\n", FileName->AllocatedSize);
220 printf("\tDataSize: %I64u\n", FileName->DataSize);
221 printf("\tFileAttributes: %lu\n", FileName->FileAttributes);
222 printf("\tAlignmentOrReserved: %lu\n", FileName->AlignmentOrReserved);
223 printf("\tNameLength: %u\n", FileName->NameLength);
224 printf("\tNameType: %u\n", FileName->NameType);
225 printf("\tName: ");
226 for (k = 0; k < FileName->NameLength; ++k)
227 {
228 wprintf(L"%C", FileName->Name[k]);
229 }
230 printf("\n");
231 break;
232 }
233 }
234
235 Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length);
236 }
237
238 free(OutputBuffer);
239 CloseHandle(VolumeHandle);
240
241 return 0;
242 }