1 /* 2 * PROJECT: ReactOS Setup Library 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Filesystem support functions 5 * COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net) 6 * Copyright 2017-2020 Hermes Belusca-Maito 7 */ 8 9 // 10 // See also: https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/dll/win32/fmifs/init.c;h=e895f5ef9cae4806123f6bbdd3dfed37ec1c8d33;hb=b9db9a4e377a2055f635b2fb69fef4e1750d219c 11 // for how to get FS providers in a dynamic way. In the (near) future we may 12 // consider merging some of this code with us into a fmifs / fsutil / fslib library... 13 // 14 15 /* INCLUDES *****************************************************************/ 16 17 #include "precomp.h" 18 19 #include "partlist.h" 20 #include "fsrec.h" 21 #include "bootcode.h" 22 #include "fsutil.h" 23 24 #include <fslib/vfatlib.h> 25 #include <fslib/btrfslib.h> 26 // #include <fslib/ext2lib.h> 27 // #include <fslib/ntfslib.h> 28 29 #define NDEBUG 30 #include <debug.h> 31 32 33 /* TYPEDEFS *****************************************************************/ 34 35 #include <pshpack1.h> 36 typedef struct _FAT_BOOTSECTOR 37 { 38 UCHAR JumpBoot[3]; // Jump instruction to boot code 39 CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes 40 USHORT BytesPerSector; // Bytes per sector 41 UCHAR SectorsPerCluster; // Number of sectors in a cluster 42 USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) 43 UCHAR NumberOfFats; // Number of FAT tables 44 USHORT RootDirEntries; // Number of root directory entries (fat12/16) 45 USHORT TotalSectors; // Number of total sectors on the drive, 16-bit 46 UCHAR MediaDescriptor; // Media descriptor byte 47 USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) 48 USHORT SectorsPerTrack; // Number of sectors in a track 49 USHORT NumberOfHeads; // Number of heads on the disk 50 ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) 51 ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume 52 UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) 53 UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. 54 UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. 55 ULONG VolumeSerialNumber; // Volume serial number 56 CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory 57 CHAR FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT " 58 59 UCHAR BootCodeAndData[448]; // The remainder of the boot sector 60 61 USHORT BootSectorMagic; // 0xAA55 62 63 } FAT_BOOTSECTOR, *PFAT_BOOTSECTOR; 64 C_ASSERT(sizeof(FAT_BOOTSECTOR) == FAT_BOOTSECTOR_SIZE); 65 66 typedef struct _FAT32_BOOTSECTOR 67 { 68 UCHAR JumpBoot[3]; // Jump instruction to boot code 69 CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes 70 USHORT BytesPerSector; // Bytes per sector 71 UCHAR SectorsPerCluster; // Number of sectors in a cluster 72 USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) 73 UCHAR NumberOfFats; // Number of FAT tables 74 USHORT RootDirEntries; // Number of root directory entries (fat12/16) 75 USHORT TotalSectors; // Number of total sectors on the drive, 16-bit 76 UCHAR MediaDescriptor; // Media descriptor byte 77 USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) 78 USHORT SectorsPerTrack; // Number of sectors in a track 79 USHORT NumberOfHeads; // Number of heads on the disk 80 ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) 81 ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume 82 ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0 83 USHORT ExtendedFlags; // Extended flags (fat32) 84 USHORT FileSystemVersion; // File system version (fat32) 85 ULONG RootDirStartCluster; // Starting cluster of the root directory (fat32) 86 USHORT FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. 87 USHORT BackupBootSector; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6. 88 UCHAR Reserved[12]; // Reserved for future expansion 89 UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) 90 UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. 91 UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. 92 ULONG VolumeSerialNumber; // Volume serial number 93 CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory 94 CHAR FileSystemType[8]; // Always set to the string "FAT32 " 95 96 UCHAR BootCodeAndData[420]; // The remainder of the boot sector 97 98 USHORT BootSectorMagic; // 0xAA55 99 100 } FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR; 101 C_ASSERT(sizeof(FAT32_BOOTSECTOR) == FAT32_BOOTSECTOR_SIZE); 102 103 typedef struct _BTRFS_BOOTSECTOR 104 { 105 UCHAR JumpBoot[3]; 106 UCHAR ChunkMapSize; 107 UCHAR BootDrive; 108 ULONGLONG PartitionStartLBA; 109 UCHAR Fill[1521]; // 1536 - 15 110 USHORT BootSectorMagic; 111 } BTRFS_BOOTSECTOR, *PBTRFS_BOOTSECTOR; 112 C_ASSERT(sizeof(BTRFS_BOOTSECTOR) == BTRFS_BOOTSECTOR_SIZE); 113 114 // TODO: Add more bootsector structures! 115 116 #include <poppack.h> 117 118 119 /* LOCALS *******************************************************************/ 120 121 /** IFS_PROVIDER **/ 122 typedef struct _FILE_SYSTEM 123 { 124 PCWSTR FileSystemName; 125 FORMATEX FormatFunc; 126 CHKDSKEX ChkdskFunc; 127 } FILE_SYSTEM, *PFILE_SYSTEM; 128 129 /* The list of file systems on which we can install ReactOS */ 130 static FILE_SYSTEM RegisteredFileSystems[] = 131 { 132 /* NOTE: The FAT formatter will automatically 133 * determine whether to use FAT12/16 or FAT32. */ 134 { L"FAT" , VfatFormat, VfatChkdsk }, 135 { L"FAT32", VfatFormat, VfatChkdsk }, 136 #if 0 137 { L"FATX" , VfatxFormat, VfatxChkdsk }, 138 { L"NTFS" , NtfsFormat, NtfsChkdsk }, 139 #endif 140 { L"BTRFS", BtrfsFormatEx, BtrfsChkdskEx }, 141 #if 0 142 { L"EXT2" , Ext2Format, Ext2Chkdsk }, 143 { L"EXT3" , Ext2Format, Ext2Chkdsk }, 144 { L"EXT4" , Ext2Format, Ext2Chkdsk }, 145 { L"FFS" , FfsFormat , FfsChkdsk }, 146 { L"REISERFS", ReiserfsFormat, ReiserfsChkdsk }, 147 #endif 148 }; 149 150 151 /* FUNCTIONS ****************************************************************/ 152 153 /** QueryAvailableFileSystemFormat() **/ 154 BOOLEAN 155 GetRegisteredFileSystems( 156 IN ULONG Index, 157 OUT PCWSTR* FileSystemName) 158 { 159 if (Index >= ARRAYSIZE(RegisteredFileSystems)) 160 return FALSE; 161 162 *FileSystemName = RegisteredFileSystems[Index].FileSystemName; 163 164 return TRUE; 165 } 166 167 168 /** GetProvider() **/ 169 static PFILE_SYSTEM 170 GetFileSystemByName( 171 IN PCWSTR FileSystemName) 172 { 173 #if 0 // Reenable when the list of registered FSes will again be dynamic 174 175 PLIST_ENTRY ListEntry; 176 PFILE_SYSTEM_ITEM Item; 177 178 ListEntry = List->ListHead.Flink; 179 while (ListEntry != &List->ListHead) 180 { 181 Item = CONTAINING_RECORD(ListEntry, FILE_SYSTEM_ITEM, ListEntry); 182 if (Item->FileSystemName && 183 (wcsicmp(FileSystemName, Item->FileSystemName) == 0)) 184 { 185 return Item; 186 } 187 188 ListEntry = ListEntry->Flink; 189 } 190 191 #else 192 193 ULONG Count = ARRAYSIZE(RegisteredFileSystems); 194 PFILE_SYSTEM FileSystems = RegisteredFileSystems; 195 196 ASSERT(FileSystems && Count != 0); 197 198 while (Count--) 199 { 200 if (FileSystems->FileSystemName && 201 (wcsicmp(FileSystemName, FileSystems->FileSystemName) == 0)) 202 { 203 return FileSystems; 204 } 205 206 ++FileSystems; 207 } 208 209 #endif 210 211 return NULL; 212 } 213 214 215 /** ChkdskEx() **/ 216 NTSTATUS 217 ChkdskFileSystem_UStr( 218 IN PUNICODE_STRING DriveRoot, 219 IN PCWSTR FileSystemName, 220 IN BOOLEAN FixErrors, 221 IN BOOLEAN Verbose, 222 IN BOOLEAN CheckOnlyIfDirty, 223 IN BOOLEAN ScanDrive, 224 IN PFMIFSCALLBACK Callback) 225 { 226 PFILE_SYSTEM FileSystem; 227 228 FileSystem = GetFileSystemByName(FileSystemName); 229 230 if (!FileSystem || !FileSystem->ChkdskFunc) 231 { 232 // BOOLEAN Argument = FALSE; 233 // Callback(DONE, 0, &Argument); 234 return STATUS_NOT_SUPPORTED; 235 } 236 237 return FileSystem->ChkdskFunc(DriveRoot, 238 FixErrors, 239 Verbose, 240 CheckOnlyIfDirty, 241 ScanDrive, 242 Callback); 243 } 244 245 NTSTATUS 246 ChkdskFileSystem( 247 IN PCWSTR DriveRoot, 248 IN PCWSTR FileSystemName, 249 IN BOOLEAN FixErrors, 250 IN BOOLEAN Verbose, 251 IN BOOLEAN CheckOnlyIfDirty, 252 IN BOOLEAN ScanDrive, 253 IN PFMIFSCALLBACK Callback) 254 { 255 UNICODE_STRING DriveRootU; 256 257 RtlInitUnicodeString(&DriveRootU, DriveRoot); 258 return ChkdskFileSystem_UStr(&DriveRootU, 259 FileSystemName, 260 FixErrors, 261 Verbose, 262 CheckOnlyIfDirty, 263 ScanDrive, 264 Callback); 265 } 266 267 268 /** FormatEx() **/ 269 NTSTATUS 270 FormatFileSystem_UStr( 271 IN PUNICODE_STRING DriveRoot, 272 IN PCWSTR FileSystemName, 273 IN FMIFS_MEDIA_FLAG MediaFlag, 274 IN PUNICODE_STRING Label, 275 IN BOOLEAN QuickFormat, 276 IN ULONG ClusterSize, 277 IN PFMIFSCALLBACK Callback) 278 { 279 PFILE_SYSTEM FileSystem; 280 281 FileSystem = GetFileSystemByName(FileSystemName); 282 283 if (!FileSystem || !FileSystem->FormatFunc) 284 { 285 // BOOLEAN Argument = FALSE; 286 // Callback(DONE, 0, &Argument); 287 return STATUS_NOT_SUPPORTED; 288 } 289 290 return FileSystem->FormatFunc(DriveRoot, 291 MediaFlag, 292 Label, 293 QuickFormat, 294 ClusterSize, 295 Callback); 296 } 297 298 NTSTATUS 299 FormatFileSystem( 300 IN PCWSTR DriveRoot, 301 IN PCWSTR FileSystemName, 302 IN FMIFS_MEDIA_FLAG MediaFlag, 303 IN PCWSTR Label, 304 IN BOOLEAN QuickFormat, 305 IN ULONG ClusterSize, 306 IN PFMIFSCALLBACK Callback) 307 { 308 UNICODE_STRING DriveRootU; 309 UNICODE_STRING LabelU; 310 311 RtlInitUnicodeString(&DriveRootU, DriveRoot); 312 RtlInitUnicodeString(&LabelU, Label); 313 314 return FormatFileSystem_UStr(&DriveRootU, 315 FileSystemName, 316 MediaFlag, 317 &LabelU, 318 QuickFormat, 319 ClusterSize, 320 Callback); 321 } 322 323 324 // 325 // Bootsector routines 326 // 327 328 NTSTATUS 329 InstallFatBootCode( 330 IN PCWSTR SrcPath, // FAT12/16 bootsector source file (on the installation medium) 331 IN HANDLE DstPath, // Where to save the bootsector built from the source + partition information 332 IN HANDLE RootPartition) // Partition holding the (old) FAT12/16 information 333 { 334 NTSTATUS Status; 335 UNICODE_STRING Name; 336 IO_STATUS_BLOCK IoStatusBlock; 337 LARGE_INTEGER FileOffset; 338 BOOTCODE OrigBootSector = {0}; 339 BOOTCODE NewBootSector = {0}; 340 341 /* Allocate and read the current original partition bootsector */ 342 Status = ReadBootCodeByHandle(&OrigBootSector, 343 RootPartition, 344 FAT_BOOTSECTOR_SIZE); 345 if (!NT_SUCCESS(Status)) 346 return Status; 347 348 /* Allocate and read the new bootsector from SrcPath */ 349 RtlInitUnicodeString(&Name, SrcPath); 350 Status = ReadBootCodeFromFile(&NewBootSector, 351 &Name, 352 FAT_BOOTSECTOR_SIZE); 353 if (!NT_SUCCESS(Status)) 354 { 355 FreeBootCode(&OrigBootSector); 356 return Status; 357 } 358 359 /* Adjust the bootsector (copy a part of the FAT12/16 BPB) */ 360 RtlCopyMemory(&((PFAT_BOOTSECTOR)NewBootSector.BootCode)->OemName, 361 &((PFAT_BOOTSECTOR)OrigBootSector.BootCode)->OemName, 362 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) - 363 FIELD_OFFSET(FAT_BOOTSECTOR, OemName)); 364 365 /* Free the original bootsector */ 366 FreeBootCode(&OrigBootSector); 367 368 /* Write the new bootsector to DstPath */ 369 FileOffset.QuadPart = 0ULL; 370 Status = NtWriteFile(DstPath, 371 NULL, 372 NULL, 373 NULL, 374 &IoStatusBlock, 375 NewBootSector.BootCode, 376 NewBootSector.Length, 377 &FileOffset, 378 NULL); 379 380 /* Free the new bootsector */ 381 FreeBootCode(&NewBootSector); 382 383 return Status; 384 } 385 386 NTSTATUS 387 InstallFat32BootCode( 388 IN PCWSTR SrcPath, // FAT32 bootsector source file (on the installation medium) 389 IN HANDLE DstPath, // Where to save the bootsector built from the source + partition information 390 IN HANDLE RootPartition) // Partition holding the (old) FAT32 information 391 { 392 NTSTATUS Status; 393 UNICODE_STRING Name; 394 IO_STATUS_BLOCK IoStatusBlock; 395 LARGE_INTEGER FileOffset; 396 USHORT BackupBootSector = 0; 397 BOOTCODE OrigBootSector = {0}; 398 BOOTCODE NewBootSector = {0}; 399 400 /* Allocate and read the current original partition bootsector */ 401 Status = ReadBootCodeByHandle(&OrigBootSector, 402 RootPartition, 403 FAT32_BOOTSECTOR_SIZE); 404 if (!NT_SUCCESS(Status)) 405 return Status; 406 407 /* Allocate and read the new bootsector (2 sectors) from SrcPath */ 408 RtlInitUnicodeString(&Name, SrcPath); 409 Status = ReadBootCodeFromFile(&NewBootSector, 410 &Name, 411 2 * FAT32_BOOTSECTOR_SIZE); 412 if (!NT_SUCCESS(Status)) 413 { 414 FreeBootCode(&OrigBootSector); 415 return Status; 416 } 417 418 /* Adjust the bootsector (copy a part of the FAT32 BPB) */ 419 RtlCopyMemory(&((PFAT32_BOOTSECTOR)NewBootSector.BootCode)->OemName, 420 &((PFAT32_BOOTSECTOR)OrigBootSector.BootCode)->OemName, 421 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) - 422 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName)); 423 424 /* 425 * We know we copy the boot code to a file only when DstPath != RootPartition, 426 * otherwise the boot code is copied to the specified root partition. 427 */ 428 if (DstPath != RootPartition) 429 { 430 /* Copy to a file: Disable the backup bootsector */ 431 ((PFAT32_BOOTSECTOR)NewBootSector.BootCode)->BackupBootSector = 0; 432 } 433 else 434 { 435 /* Copy to a disk: Get the location of the backup bootsector */ 436 BackupBootSector = ((PFAT32_BOOTSECTOR)OrigBootSector.BootCode)->BackupBootSector; 437 } 438 439 /* Free the original bootsector */ 440 FreeBootCode(&OrigBootSector); 441 442 /* Write the first sector of the new bootcode to DstPath sector 0 */ 443 FileOffset.QuadPart = 0ULL; 444 Status = NtWriteFile(DstPath, 445 NULL, 446 NULL, 447 NULL, 448 &IoStatusBlock, 449 NewBootSector.BootCode, 450 FAT32_BOOTSECTOR_SIZE, 451 &FileOffset, 452 NULL); 453 if (!NT_SUCCESS(Status)) 454 { 455 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 456 FreeBootCode(&NewBootSector); 457 return Status; 458 } 459 460 if (DstPath == RootPartition) 461 { 462 /* Copy to a disk: Write the backup bootsector */ 463 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF)) 464 { 465 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * FAT32_BOOTSECTOR_SIZE); 466 Status = NtWriteFile(DstPath, 467 NULL, 468 NULL, 469 NULL, 470 &IoStatusBlock, 471 NewBootSector.BootCode, 472 FAT32_BOOTSECTOR_SIZE, 473 &FileOffset, 474 NULL); 475 if (!NT_SUCCESS(Status)) 476 { 477 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 478 FreeBootCode(&NewBootSector); 479 return Status; 480 } 481 } 482 } 483 484 /* Write the second sector of the new bootcode to boot disk sector 14 */ 485 // FileOffset.QuadPart = (ULONGLONG)(14 * FAT32_BOOTSECTOR_SIZE); 486 FileOffset.QuadPart = 14 * FAT32_BOOTSECTOR_SIZE; 487 Status = NtWriteFile(DstPath, // or really RootPartition ??? 488 NULL, 489 NULL, 490 NULL, 491 &IoStatusBlock, 492 ((PUCHAR)NewBootSector.BootCode + FAT32_BOOTSECTOR_SIZE), 493 FAT32_BOOTSECTOR_SIZE, 494 &FileOffset, 495 NULL); 496 if (!NT_SUCCESS(Status)) 497 { 498 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 499 } 500 501 /* Free the new bootsector */ 502 FreeBootCode(&NewBootSector); 503 504 return Status; 505 } 506 507 NTSTATUS 508 InstallBtrfsBootCode( 509 IN PCWSTR SrcPath, // BTRFS bootsector source file (on the installation medium) 510 IN HANDLE DstPath, // Where to save the bootsector built from the source + partition information 511 IN HANDLE RootPartition) // Partition holding the (old) BTRFS information 512 { 513 NTSTATUS Status; 514 NTSTATUS LockStatus; 515 UNICODE_STRING Name; 516 IO_STATUS_BLOCK IoStatusBlock; 517 LARGE_INTEGER FileOffset; 518 PARTITION_INFORMATION_EX PartInfo; 519 BOOTCODE NewBootSector = {0}; 520 521 /* Allocate and read the new bootsector from SrcPath */ 522 RtlInitUnicodeString(&Name, SrcPath); 523 Status = ReadBootCodeFromFile(&NewBootSector, 524 &Name, 525 BTRFS_BOOTSECTOR_SIZE); 526 if (!NT_SUCCESS(Status)) 527 return Status; 528 529 /* 530 * The BTRFS driver requires the volume to be locked in order to modify 531 * the first sectors of the partition, even though they are outside the 532 * file-system space / in the reserved area (they are situated before 533 * the super-block at 0x1000) and is in principle allowed by the NT 534 * storage stack. 535 * So we lock here in order to write the bootsector at sector 0. 536 * If locking fails, we ignore and continue nonetheless. 537 */ 538 LockStatus = NtFsControlFile(DstPath, 539 NULL, 540 NULL, 541 NULL, 542 &IoStatusBlock, 543 FSCTL_LOCK_VOLUME, 544 NULL, 545 0, 546 NULL, 547 0); 548 if (!NT_SUCCESS(LockStatus)) 549 { 550 DPRINT1("WARNING: Failed to lock BTRFS volume for writing bootsector! Operations may fail! (Status 0x%lx)\n", LockStatus); 551 } 552 553 /* Obtain partition info and write it to the bootsector */ 554 Status = NtDeviceIoControlFile(RootPartition, 555 NULL, 556 NULL, 557 NULL, 558 &IoStatusBlock, 559 IOCTL_DISK_GET_PARTITION_INFO_EX, 560 NULL, 561 0, 562 &PartInfo, 563 sizeof(PartInfo)); 564 if (!NT_SUCCESS(Status)) 565 { 566 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status); 567 goto Quit; 568 } 569 570 /* Write new bootsector to RootPath */ 571 ((PBTRFS_BOOTSECTOR)NewBootSector.BootCode)->PartitionStartLBA = 572 PartInfo.StartingOffset.QuadPart / SECTORSIZE; 573 574 /* Write sector 0 */ 575 FileOffset.QuadPart = 0ULL; 576 Status = NtWriteFile(DstPath, 577 NULL, 578 NULL, 579 NULL, 580 &IoStatusBlock, 581 NewBootSector.BootCode, 582 NewBootSector.Length, 583 &FileOffset, 584 NULL); 585 if (!NT_SUCCESS(Status)) 586 { 587 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 588 goto Quit; 589 } 590 591 Quit: 592 /* Unlock the volume */ 593 LockStatus = NtFsControlFile(DstPath, 594 NULL, 595 NULL, 596 NULL, 597 &IoStatusBlock, 598 FSCTL_UNLOCK_VOLUME, 599 NULL, 600 0, 601 NULL, 602 0); 603 if (!NT_SUCCESS(LockStatus)) 604 { 605 DPRINT1("Failed to unlock BTRFS volume (Status 0x%lx)\n", LockStatus); 606 } 607 608 /* Free the new bootsector */ 609 FreeBootCode(&NewBootSector); 610 611 return Status; 612 } 613 614 615 // 616 // Formatting routines 617 // 618 619 BOOLEAN 620 PreparePartitionForFormatting( 621 IN struct _PARTENTRY* PartEntry, 622 IN PCWSTR FileSystemName) 623 { 624 UCHAR PartitionType; 625 626 if (!FileSystemName || !*FileSystemName) 627 { 628 DPRINT1("No file system specified?\n"); 629 return FALSE; 630 } 631 632 PartitionType = FileSystemToPartitionType(FileSystemName, 633 &PartEntry->StartSector, 634 &PartEntry->SectorCount); 635 if (PartitionType == PARTITION_ENTRY_UNUSED) 636 { 637 /* Unknown file system */ 638 DPRINT1("Unknown file system '%S'\n", FileSystemName); 639 return FALSE; 640 } 641 642 SetPartitionType(PartEntry, PartitionType); 643 644 /* 645 * Adjust the filesystem name in case of FAT vs. FAT32, according to 646 * the type of partition set by FileSystemToPartitionType(). 647 */ 648 if (wcsicmp(FileSystemName, L"FAT") == 0) 649 { 650 if ((/*PartEntry->*/PartitionType == PARTITION_FAT32) || 651 (/*PartEntry->*/PartitionType == PARTITION_FAT32_XINT13)) 652 { 653 FileSystemName = L"FAT32"; 654 } 655 } 656 657 // 658 // FIXME: Do this now, or after the partition was actually formatted?? 659 // 660 /* Set the new partition's file system proper */ 661 RtlStringCbCopyW(PartEntry->FileSystem, 662 sizeof(PartEntry->FileSystem), 663 FileSystemName); 664 665 return TRUE; 666 } 667 668 /* EOF */ 669