[PARTTEST]
[reactos.git] / rostests / tests / parttest / parttest.c
1 /*
2 * PROJECT: ReactOS partitions tests/dump
3 * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Open disk & partition trying to get information about volumes & MBR
5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org>
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <winternl.h>
11
12 #ifndef NT_SUCCESS
13 # define NT_SUCCESS(_Status) (((NTSTATUS)(_Status)) >= 0)
14 #endif
15
16 #define SECTOR_SIZE 512
17 #define BOOT_RECORD_SIGNATURE 0xAA55
18
19 PCWSTR DiskFormat = L"\\Device\\Harddisk%lu\\Partition%lu";
20
21 #include <pshpack1.h>
22 typedef struct {
23 unsigned char magic0, res0, magic1;
24 unsigned char OEMName[8];
25 unsigned short BytesPerSector;
26 unsigned char SectorsPerCluster;
27 unsigned short ReservedSectors;
28 unsigned char FATCount;
29 unsigned short RootEntries, Sectors;
30 unsigned char Media;
31 unsigned short FATSectors, SectorsPerTrack, Heads;
32 unsigned long HiddenSectors, SectorsHuge;
33 unsigned long FATSectors32;
34 unsigned short ExtFlag;
35 unsigned short FSVersion;
36 unsigned long RootCluster;
37 unsigned short FSInfoSector;
38 unsigned short BootBackup;
39 unsigned char Res3[12];
40 unsigned char Drive;
41 unsigned char Res4;
42 unsigned char ExtBootSignature;
43 unsigned long VolumeID;
44 unsigned char VolumeLabel[11], SysType[8];
45 unsigned char Res2[420];
46 unsigned short Signature1;
47 } FATBootSector, *PFATBootSector;
48
49 typedef struct {
50 UCHAR Jump[3];
51 UCHAR OEMID[8];
52 USHORT BytesPerSector;
53 UCHAR SectorsPerCluster;
54 UCHAR Unused0[7];
55 UCHAR MediaId;
56 UCHAR Unused1[2];
57 USHORT SectorsPerTrack;
58 USHORT Heads;
59 UCHAR Unused2[4];
60 UCHAR Unused3[4];
61 USHORT Unknown[2];
62 ULONGLONG SectorCount;
63 ULONGLONG MftLocation;
64 ULONGLONG MftMirrLocation;
65 CHAR ClustersPerMftRecord;
66 UCHAR Unused4[3];
67 CHAR ClustersPerIndexRecord;
68 UCHAR Unused5[3];
69 ULONGLONG SerialNumber;
70 UCHAR Checksum[4];
71 UCHAR BootStrap[426];
72 USHORT EndSector;
73 } NTFSBootSector, *PNTFSBootSector;
74
75 typedef struct {
76 UCHAR BootIndicator;
77 UCHAR StartHead;
78 UCHAR StartSector;
79 UCHAR StartCylinder;
80 UCHAR SystemIndicator;
81 UCHAR EndHead;
82 UCHAR EndSector;
83 UCHAR EndCylinder;
84 ULONG SectorCountBeforePartition;
85 ULONG PartitionSectorCount;
86 } PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY;
87
88 typedef struct {
89 UCHAR MasterBootRecordCodeAndData[0x1B8];
90 ULONG Signature;
91 USHORT Reserved;
92 PARTITION_TABLE_ENTRY PartitionTable[4];
93 USHORT MasterBootRecordMagic;
94 } MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD;
95 #include <poppack.h>
96
97 BOOL CheckAgainstFAT(PFATBootSector Sector)
98 {
99 if (Sector->Signature1 != 0xaa55)
100 {
101 return FALSE;
102 }
103
104 if (Sector->BytesPerSector != 512 &&
105 Sector->BytesPerSector != 1024 &&
106 Sector->BytesPerSector != 2048 &&
107 Sector->BytesPerSector != 4096)
108 {
109 return FALSE;
110 }
111
112 if (Sector->FATCount != 1 &&
113 Sector->FATCount != 2)
114 {
115 return FALSE;
116 }
117
118 if (Sector->Media != 0xf0 &&
119 Sector->Media != 0xf8 &&
120 Sector->Media != 0xf9 &&
121 Sector->Media != 0xfa &&
122 Sector->Media != 0xfb &&
123 Sector->Media != 0xfc &&
124 Sector->Media != 0xfd &&
125 Sector->Media != 0xfe &&
126 Sector->Media != 0xff)
127 {
128 return FALSE;
129 }
130
131 if (Sector->SectorsPerCluster != 1 &&
132 Sector->SectorsPerCluster != 2 &&
133 Sector->SectorsPerCluster != 4 &&
134 Sector->SectorsPerCluster != 8 &&
135 Sector->SectorsPerCluster != 16 &&
136 Sector->SectorsPerCluster != 32 &&
137 Sector->SectorsPerCluster != 64 &&
138 Sector->SectorsPerCluster != 128)
139 {
140 return FALSE;
141 }
142
143 if (Sector->BytesPerSector * Sector->SectorsPerCluster > 32 * 1024)
144 {
145 return FALSE;
146 }
147
148 return TRUE;
149 }
150
151 BOOL CheckAgainstNTFS(PNTFSBootSector Sector)
152 {
153 ULONG k;
154 ULONG ClusterSize;
155
156 /* OEMID: this field must be NTFS */
157 if (RtlCompareMemory(Sector->OEMID, "NTFS ", 8) != 8)
158 {
159 return FALSE;
160 }
161
162 /* Unused0: this field must be COMPLETELY null */
163 for (k = 0; k < 7; k++)
164 {
165 if (Sector->Unused0[k] != 0)
166 {
167 return FALSE;
168 }
169 }
170
171 /* Unused3: this field must be COMPLETELY null */
172 for (k = 0; k < 4; k++)
173 {
174 if (Sector->Unused3[k] != 0)
175 {
176 return FALSE;
177 }
178 }
179
180 /* Check cluster size */
181 ClusterSize = Sector->BytesPerSector * Sector->SectorsPerCluster;
182 if (ClusterSize != 512 && ClusterSize != 1024 &&
183 ClusterSize != 2048 && ClusterSize != 4096 &&
184 ClusterSize != 8192 && ClusterSize != 16384 &&
185 ClusterSize != 32768 && ClusterSize != 65536)
186 {
187 return FALSE;
188 }
189
190 return TRUE;
191 }
192
193 BOOL CheckAgainstMBR(PMASTER_BOOT_RECORD Sector)
194 {
195 if (Sector->MasterBootRecordMagic != BOOT_RECORD_SIGNATURE)
196 {
197 return FALSE;
198 }
199
200 return TRUE;
201 }
202
203 int main(int argc, char ** argv)
204 {
205 HANDLE FileHandle;
206 NTSTATUS Status;
207 OBJECT_ATTRIBUTES ObjectAttributes;
208 IO_STATUS_BLOCK IoStatusBlock;
209 WCHAR Buffer[MAX_PATH];
210 UNICODE_STRING Name;
211 PVOID Sector;
212
213 Sector = malloc(SECTOR_SIZE);
214 if (Sector == NULL)
215 {
216 fprintf(stderr, "Failed allocating memory!\n");
217 return 0;
218 }
219
220 /* We first open disk */
221 swprintf(Buffer, DiskFormat, 0, 0);
222 RtlInitUnicodeString(&Name, Buffer);
223 InitializeObjectAttributes(&ObjectAttributes,
224 &Name,
225 OBJ_CASE_INSENSITIVE,
226 NULL,
227 NULL);
228
229 Status = NtOpenFile(&FileHandle,
230 GENERIC_READ | SYNCHRONIZE,
231 &ObjectAttributes,
232 &IoStatusBlock,
233 0,
234 FILE_SYNCHRONOUS_IO_NONALERT);
235 if (!NT_SUCCESS(Status))
236 {
237 free(Sector);
238 fprintf(stderr, "Failed opening disk! %lx\n", Status);
239 return 0;
240 }
241
242 /* Read first sector of the disk */
243 Status = NtReadFile(FileHandle,
244 NULL,
245 NULL,
246 NULL,
247 &IoStatusBlock,
248 Sector,
249 SECTOR_SIZE,
250 NULL,
251 NULL);
252 NtClose(FileHandle);
253 if (!NT_SUCCESS(Status))
254 {
255 free(Sector);
256 fprintf(stderr, "Failed reading sector 0! %lx\n", Status);
257 return 0;
258 }
259
260 /* Is it FAT? */
261 if (CheckAgainstFAT(Sector))
262 {
263 printf("Sector 0 seems to be FAT boot sector\n");
264 }
265 /* Is it NTFS? */
266 else if (CheckAgainstNTFS(Sector))
267 {
268 printf("Sector 0 seems to be NTFS boot sector\n");
269 }
270 /* Is it MBR? */
271 else if (CheckAgainstMBR(Sector))
272 {
273 printf("Sector 0 might be MBR\n");
274 }
275 /* We don't support anything else */
276 else
277 {
278 printf("Sector 0 not recognized\n");
279 }
280
281 /* Redo it with first partition */
282 swprintf(Buffer, DiskFormat, 0, 1);
283 RtlInitUnicodeString(&Name, Buffer);
284 InitializeObjectAttributes(&ObjectAttributes,
285 &Name,
286 OBJ_CASE_INSENSITIVE,
287 NULL,
288 NULL);
289
290 Status = NtOpenFile(&FileHandle,
291 GENERIC_READ | SYNCHRONIZE,
292 &ObjectAttributes,
293 &IoStatusBlock,
294 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
295 FILE_SYNCHRONOUS_IO_NONALERT);
296 if (!NT_SUCCESS(Status))
297 {
298 free(Sector);
299 fprintf(stderr, "Failed opening partition! %lx\n", Status);
300 return 0;
301 }
302
303 /* Read first sector of the partition */
304 Status = NtReadFile(FileHandle,
305 NULL,
306 NULL,
307 NULL,
308 &IoStatusBlock,
309 Sector,
310 SECTOR_SIZE,
311 NULL,
312 NULL);
313 if (!NT_SUCCESS(Status))
314 {
315 free(Sector);
316 fprintf(stderr, "Failed reading first sector of the partition! %lx\n", Status);
317 return 0;
318 }
319
320 /* Is it FAT? */
321 if (CheckAgainstFAT(Sector))
322 {
323 printf("Seems to be a FAT partittion\n");
324 }
325 /* Is it NTFS? */
326 else if (CheckAgainstNTFS(Sector))
327 {
328 printf("Seems to be a NTFS partition\n");
329 }
330 /* Is it MBR? */
331 else if (CheckAgainstMBR(Sector))
332 {
333 printf("Seems to be MBR\n");
334 }
335 /* We don't support anything else */
336 else
337 {
338 printf("Not recognized\n");
339 }
340
341 free(Sector);
342
343 return 0;
344 }