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 } 345