2 * PROJECT: ReactOS Setup Library
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Filesystem Format and ChkDsk support functions.
5 * COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
6 * Copyright 2017-2020 Hermes Belusca-Maito
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...
15 /* INCLUDES *****************************************************************/
24 #include <fslib/vfatlib.h>
25 #include <fslib/btrfslib.h>
26 // #include <fslib/ext2lib.h>
27 // #include <fslib/ntfslib.h>
33 /* TYPEDEFS *****************************************************************/
36 typedef struct _FAT_BOOTSECTOR
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 "
59 UCHAR BootCodeAndData
[448]; // The remainder of the boot sector
61 USHORT BootSectorMagic
; // 0xAA55
63 } FAT_BOOTSECTOR
, *PFAT_BOOTSECTOR
;
64 C_ASSERT(sizeof(FAT_BOOTSECTOR
) == FAT_BOOTSECTOR_SIZE
);
66 typedef struct _FAT32_BOOTSECTOR
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 "
96 UCHAR BootCodeAndData
[420]; // The remainder of the boot sector
98 USHORT BootSectorMagic
; // 0xAA55
100 } FAT32_BOOTSECTOR
, *PFAT32_BOOTSECTOR
;
101 C_ASSERT(sizeof(FAT32_BOOTSECTOR
) == FAT32_BOOTSECTOR_SIZE
);
103 typedef struct _BTRFS_BOOTSECTOR
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
);
114 // TODO: Add more bootsector structures!
119 /* LOCALS *******************************************************************/
122 typedef struct _FILE_SYSTEM
124 PCWSTR FileSystemName
;
125 PULIB_FORMAT FormatFunc
;
126 PULIB_CHKDSK ChkdskFunc
;
127 } FILE_SYSTEM
, *PFILE_SYSTEM
;
129 /* The list of file systems on which we can install ReactOS */
130 static FILE_SYSTEM RegisteredFileSystems
[] =
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
},
137 { L
"FATX" , VfatxFormat
, VfatxChkdsk
},
138 { L
"NTFS" , NtfsFormat
, NtfsChkdsk
},
140 { L
"BTRFS", BtrfsFormat
, BtrfsChkdsk
},
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
},
151 /* FUNCTIONS ****************************************************************/
153 /** QueryAvailableFileSystemFormat() **/
155 GetRegisteredFileSystems(
157 OUT PCWSTR
* FileSystemName
)
159 if (Index
>= ARRAYSIZE(RegisteredFileSystems
))
162 *FileSystemName
= RegisteredFileSystems
[Index
].FileSystemName
;
168 /** GetProvider() **/
171 IN PCWSTR FileSystemName
)
173 #if 0 // Reenable when the list of registered FSes will again be dynamic
175 PLIST_ENTRY ListEntry
;
176 PFILE_SYSTEM_ITEM Item
;
178 ListEntry
= List
->ListHead
.Flink
;
179 while (ListEntry
!= &List
->ListHead
)
181 Item
= CONTAINING_RECORD(ListEntry
, FILE_SYSTEM_ITEM
, ListEntry
);
182 if (Item
->FileSystemName
&&
183 (wcsicmp(FileSystemName
, Item
->FileSystemName
) == 0))
188 ListEntry
= ListEntry
->Flink
;
193 ULONG Count
= ARRAYSIZE(RegisteredFileSystems
);
194 PFILE_SYSTEM FileSystems
= RegisteredFileSystems
;
196 ASSERT(FileSystems
&& Count
!= 0);
200 if (FileSystems
->FileSystemName
&&
201 (wcsicmp(FileSystemName
, FileSystems
->FileSystemName
) == 0))
217 ChkdskFileSystem_UStr(
218 IN PUNICODE_STRING DriveRoot
,
219 IN PCWSTR FileSystemName
,
220 IN BOOLEAN FixErrors
,
222 IN BOOLEAN CheckOnlyIfDirty
,
223 IN BOOLEAN ScanDrive
,
224 IN PFMIFSCALLBACK Callback
)
226 PFILE_SYSTEM FileSystem
;
230 FileSystem
= GetFileSystemByName(FileSystemName
);
232 if (!FileSystem
|| !FileSystem
->ChkdskFunc
)
235 // Callback(DONE, 0, &Success);
236 return STATUS_NOT_SUPPORTED
;
239 Status
= STATUS_SUCCESS
;
240 Success
= FileSystem
->ChkdskFunc(DriveRoot
,
252 DPRINT1("ChkdskFunc() failed with Status 0x%lx\n", Status
);
254 // Callback(DONE, 0, &Success);
262 IN PCWSTR FileSystemName
,
263 IN BOOLEAN FixErrors
,
265 IN BOOLEAN CheckOnlyIfDirty
,
266 IN BOOLEAN ScanDrive
,
267 IN PFMIFSCALLBACK Callback
)
269 UNICODE_STRING DriveRootU
;
271 RtlInitUnicodeString(&DriveRootU
, DriveRoot
);
272 return ChkdskFileSystem_UStr(&DriveRootU
,
284 FormatFileSystem_UStr(
285 IN PUNICODE_STRING DriveRoot
,
286 IN PCWSTR FileSystemName
,
287 IN FMIFS_MEDIA_FLAG MediaFlag
,
288 IN PUNICODE_STRING Label
,
289 IN BOOLEAN QuickFormat
,
290 IN ULONG ClusterSize
,
291 IN PFMIFSCALLBACK Callback
)
293 PFILE_SYSTEM FileSystem
;
295 BOOLEAN BackwardCompatible
= FALSE
; // Default to latest FS versions.
296 MEDIA_TYPE MediaType
;
298 FileSystem
= GetFileSystemByName(FileSystemName
);
300 if (!FileSystem
|| !FileSystem
->FormatFunc
)
303 // Callback(DONE, 0, &Success);
304 return STATUS_NOT_SUPPORTED
;
307 /* Set the BackwardCompatible flag in case we format with older FAT12/16 */
308 if (wcsicmp(FileSystemName
, L
"FAT") == 0)
309 BackwardCompatible
= TRUE
;
310 // else if (wcsicmp(FileSystemName, L"FAT32") == 0)
311 // BackwardCompatible = FALSE;
313 /* Convert the FMIFS MediaFlag to a NT MediaType */
314 // FIXME: Actually covert all the possible flags.
318 MediaType
= F5_320_1024
; // FIXME: This is hardfixed!
320 case FMIFS_REMOVABLE
:
321 MediaType
= RemovableMedia
;
324 MediaType
= FixedMedia
;
327 DPRINT1("Unknown FMIFS MediaFlag %d, converting 1-to-1 to NT MediaType\n",
329 MediaType
= (MEDIA_TYPE
)MediaFlag
;
333 Success
= FileSystem
->FormatFunc(DriveRoot
,
341 DPRINT1("FormatFunc() failed\n");
343 // Callback(DONE, 0, &Success);
345 return (Success
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
351 IN PCWSTR FileSystemName
,
352 IN FMIFS_MEDIA_FLAG MediaFlag
,
354 IN BOOLEAN QuickFormat
,
355 IN ULONG ClusterSize
,
356 IN PFMIFSCALLBACK Callback
)
358 UNICODE_STRING DriveRootU
;
359 UNICODE_STRING LabelU
;
361 RtlInitUnicodeString(&DriveRootU
, DriveRoot
);
362 RtlInitUnicodeString(&LabelU
, Label
);
364 return FormatFileSystem_UStr(&DriveRootU
,
375 // Bootsector routines
380 IN PCWSTR SrcPath
, // FAT12/16 bootsector source file (on the installation medium)
381 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
382 IN HANDLE RootPartition
) // Partition holding the (old) FAT12/16 information
386 IO_STATUS_BLOCK IoStatusBlock
;
387 LARGE_INTEGER FileOffset
;
388 BOOTCODE OrigBootSector
= {0};
389 BOOTCODE NewBootSector
= {0};
391 /* Allocate and read the current original partition bootsector */
392 Status
= ReadBootCodeByHandle(&OrigBootSector
,
394 FAT_BOOTSECTOR_SIZE
);
395 if (!NT_SUCCESS(Status
))
398 /* Allocate and read the new bootsector from SrcPath */
399 RtlInitUnicodeString(&Name
, SrcPath
);
400 Status
= ReadBootCodeFromFile(&NewBootSector
,
402 FAT_BOOTSECTOR_SIZE
);
403 if (!NT_SUCCESS(Status
))
405 FreeBootCode(&OrigBootSector
);
409 /* Adjust the bootsector (copy a part of the FAT12/16 BPB) */
410 RtlCopyMemory(&((PFAT_BOOTSECTOR
)NewBootSector
.BootCode
)->OemName
,
411 &((PFAT_BOOTSECTOR
)OrigBootSector
.BootCode
)->OemName
,
412 FIELD_OFFSET(FAT_BOOTSECTOR
, BootCodeAndData
) -
413 FIELD_OFFSET(FAT_BOOTSECTOR
, OemName
));
415 /* Free the original bootsector */
416 FreeBootCode(&OrigBootSector
);
418 /* Write the new bootsector to DstPath */
419 FileOffset
.QuadPart
= 0ULL;
420 Status
= NtWriteFile(DstPath
,
425 NewBootSector
.BootCode
,
426 NewBootSector
.Length
,
430 /* Free the new bootsector */
431 FreeBootCode(&NewBootSector
);
437 InstallFat32BootCode(
438 IN PCWSTR SrcPath
, // FAT32 bootsector source file (on the installation medium)
439 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
440 IN HANDLE RootPartition
) // Partition holding the (old) FAT32 information
444 IO_STATUS_BLOCK IoStatusBlock
;
445 LARGE_INTEGER FileOffset
;
446 USHORT BackupBootSector
= 0;
447 BOOTCODE OrigBootSector
= {0};
448 BOOTCODE NewBootSector
= {0};
450 /* Allocate and read the current original partition bootsector */
451 Status
= ReadBootCodeByHandle(&OrigBootSector
,
453 FAT32_BOOTSECTOR_SIZE
);
454 if (!NT_SUCCESS(Status
))
457 /* Allocate and read the new bootsector (2 sectors) from SrcPath */
458 RtlInitUnicodeString(&Name
, SrcPath
);
459 Status
= ReadBootCodeFromFile(&NewBootSector
,
461 2 * FAT32_BOOTSECTOR_SIZE
);
462 if (!NT_SUCCESS(Status
))
464 FreeBootCode(&OrigBootSector
);
468 /* Adjust the bootsector (copy a part of the FAT32 BPB) */
469 RtlCopyMemory(&((PFAT32_BOOTSECTOR
)NewBootSector
.BootCode
)->OemName
,
470 &((PFAT32_BOOTSECTOR
)OrigBootSector
.BootCode
)->OemName
,
471 FIELD_OFFSET(FAT32_BOOTSECTOR
, BootCodeAndData
) -
472 FIELD_OFFSET(FAT32_BOOTSECTOR
, OemName
));
475 * We know we copy the boot code to a file only when DstPath != RootPartition,
476 * otherwise the boot code is copied to the specified root partition.
478 if (DstPath
!= RootPartition
)
480 /* Copy to a file: Disable the backup bootsector */
481 ((PFAT32_BOOTSECTOR
)NewBootSector
.BootCode
)->BackupBootSector
= 0;
485 /* Copy to a disk: Get the location of the backup bootsector */
486 BackupBootSector
= ((PFAT32_BOOTSECTOR
)OrigBootSector
.BootCode
)->BackupBootSector
;
489 /* Free the original bootsector */
490 FreeBootCode(&OrigBootSector
);
492 /* Write the first sector of the new bootcode to DstPath sector 0 */
493 FileOffset
.QuadPart
= 0ULL;
494 Status
= NtWriteFile(DstPath
,
499 NewBootSector
.BootCode
,
500 FAT32_BOOTSECTOR_SIZE
,
503 if (!NT_SUCCESS(Status
))
505 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
506 FreeBootCode(&NewBootSector
);
510 if (DstPath
== RootPartition
)
512 /* Copy to a disk: Write the backup bootsector */
513 if ((BackupBootSector
!= 0x0000) && (BackupBootSector
!= 0xFFFF))
515 FileOffset
.QuadPart
= (ULONGLONG
)((ULONG
)BackupBootSector
* FAT32_BOOTSECTOR_SIZE
);
516 Status
= NtWriteFile(DstPath
,
521 NewBootSector
.BootCode
,
522 FAT32_BOOTSECTOR_SIZE
,
525 if (!NT_SUCCESS(Status
))
527 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
528 FreeBootCode(&NewBootSector
);
534 /* Write the second sector of the new bootcode to boot disk sector 14 */
535 // FileOffset.QuadPart = (ULONGLONG)(14 * FAT32_BOOTSECTOR_SIZE);
536 FileOffset
.QuadPart
= 14 * FAT32_BOOTSECTOR_SIZE
;
537 Status
= NtWriteFile(DstPath
, // or really RootPartition ???
542 ((PUCHAR
)NewBootSector
.BootCode
+ FAT32_BOOTSECTOR_SIZE
),
543 FAT32_BOOTSECTOR_SIZE
,
546 if (!NT_SUCCESS(Status
))
548 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
551 /* Free the new bootsector */
552 FreeBootCode(&NewBootSector
);
558 InstallBtrfsBootCode(
559 IN PCWSTR SrcPath
, // BTRFS bootsector source file (on the installation medium)
560 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
561 IN HANDLE RootPartition
) // Partition holding the (old) BTRFS information
566 IO_STATUS_BLOCK IoStatusBlock
;
567 LARGE_INTEGER FileOffset
;
568 PARTITION_INFORMATION_EX PartInfo
;
569 BOOTCODE NewBootSector
= {0};
571 /* Allocate and read the new bootsector from SrcPath */
572 RtlInitUnicodeString(&Name
, SrcPath
);
573 Status
= ReadBootCodeFromFile(&NewBootSector
,
575 BTRFS_BOOTSECTOR_SIZE
);
576 if (!NT_SUCCESS(Status
))
580 * The BTRFS driver requires the volume to be locked in order to modify
581 * the first sectors of the partition, even though they are outside the
582 * file-system space / in the reserved area (they are situated before
583 * the super-block at 0x1000) and is in principle allowed by the NT
585 * So we lock here in order to write the bootsector at sector 0.
586 * If locking fails, we ignore and continue nonetheless.
588 LockStatus
= NtFsControlFile(DstPath
,
598 if (!NT_SUCCESS(LockStatus
))
600 DPRINT1("WARNING: Failed to lock BTRFS volume for writing bootsector! Operations may fail! (Status 0x%lx)\n", LockStatus
);
603 /* Obtain partition info and write it to the bootsector */
604 Status
= NtDeviceIoControlFile(RootPartition
,
609 IOCTL_DISK_GET_PARTITION_INFO_EX
,
614 if (!NT_SUCCESS(Status
))
616 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status
);
620 /* Write new bootsector to RootPath */
621 ((PBTRFS_BOOTSECTOR
)NewBootSector
.BootCode
)->PartitionStartLBA
=
622 PartInfo
.StartingOffset
.QuadPart
/ SECTORSIZE
;
625 FileOffset
.QuadPart
= 0ULL;
626 Status
= NtWriteFile(DstPath
,
631 NewBootSector
.BootCode
,
632 NewBootSector
.Length
,
635 if (!NT_SUCCESS(Status
))
637 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
642 /* Unlock the volume */
643 LockStatus
= NtFsControlFile(DstPath
,
653 if (!NT_SUCCESS(LockStatus
))
655 DPRINT1("Failed to unlock BTRFS volume (Status 0x%lx)\n", LockStatus
);
658 /* Free the new bootsector */
659 FreeBootCode(&NewBootSector
);
666 // Formatting routines
671 IN PPARTENTRY PartEntry
,
672 IN BOOLEAN FixErrors
,
674 IN BOOLEAN CheckOnlyIfDirty
,
675 IN BOOLEAN ScanDrive
,
676 IN PFMIFSCALLBACK Callback
)
679 PDISKENTRY DiskEntry
= PartEntry
->DiskEntry
;
680 // UNICODE_STRING PartitionRootPath;
681 WCHAR PartitionRootPath
[MAX_PATH
]; // PathBuffer
683 ASSERT(PartEntry
->IsPartitioned
&& PartEntry
->PartitionNumber
!= 0);
685 /* HACK: Do not try to check a partition with an unknown filesystem */
686 if (!*PartEntry
->FileSystem
)
688 PartEntry
->NeedsCheck
= FALSE
;
689 return STATUS_SUCCESS
;
692 /* Set PartitionRootPath */
693 RtlStringCchPrintfW(PartitionRootPath
, ARRAYSIZE(PartitionRootPath
),
694 L
"\\Device\\Harddisk%lu\\Partition%lu",
695 DiskEntry
->DiskNumber
,
696 PartEntry
->PartitionNumber
);
697 DPRINT("PartitionRootPath: %S\n", PartitionRootPath
);
699 /* Check the partition */
700 Status
= ChkdskFileSystem(PartitionRootPath
,
701 PartEntry
->FileSystem
,
707 if (!NT_SUCCESS(Status
))
710 PartEntry
->NeedsCheck
= FALSE
;
711 return STATUS_SUCCESS
;
716 IN PPARTENTRY PartEntry
,
717 IN PCWSTR FileSystemName
,
718 IN FMIFS_MEDIA_FLAG MediaFlag
,
720 IN BOOLEAN QuickFormat
,
721 IN ULONG ClusterSize
,
722 IN PFMIFSCALLBACK Callback
)
725 PDISKENTRY DiskEntry
= PartEntry
->DiskEntry
;
727 // UNICODE_STRING PartitionRootPath;
728 WCHAR PartitionRootPath
[MAX_PATH
]; // PathBuffer
730 ASSERT(PartEntry
->IsPartitioned
&& PartEntry
->PartitionNumber
!= 0);
732 if (!FileSystemName
|| !*FileSystemName
)
734 DPRINT1("No file system specified?\n");
735 return STATUS_UNRECOGNIZED_VOLUME
;
739 * Prepare the partition for formatting (for MBR disks, reset the
740 * partition type), and adjust the filesystem name in case of FAT
741 * vs. FAT32, depending on the geometry of the partition.
744 // FIXME: Do this only if QuickFormat == FALSE? What about FAT handling?
747 * Retrieve a partition type as a hint only. It will be used to determine
748 * whether to actually use FAT12/16 or FAT32 filesystem, depending on the
749 * geometry of the partition. If the partition resides on an MBR disk,
750 * the partition style will be reset to this value as well, unless the
753 PartitionType
= FileSystemToMBRPartitionType(FileSystemName
,
754 PartEntry
->StartSector
.QuadPart
,
755 PartEntry
->SectorCount
.QuadPart
);
756 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
758 /* Unknown file system */
759 DPRINT1("Unknown file system '%S'\n", FileSystemName
);
760 return STATUS_UNRECOGNIZED_VOLUME
;
763 /* Reset the MBR partition type, unless this is an OEM partition */
764 if (DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
)
766 if (!IsOEMPartition(PartEntry
->PartitionType
))
767 SetMBRPartitionType(PartEntry
, PartitionType
);
771 * Adjust the filesystem name in case of FAT vs. FAT32, according to
772 * the type of partition returned by FileSystemToMBRPartitionType().
774 if (wcsicmp(FileSystemName
, L
"FAT") == 0)
776 if ((PartitionType
== PARTITION_FAT32
) ||
777 (PartitionType
== PARTITION_FAT32_XINT13
))
779 FileSystemName
= L
"FAT32";
783 /* Commit the partition changes to the disk */
784 Status
= WritePartitions(DiskEntry
);
785 if (!NT_SUCCESS(Status
))
787 DPRINT1("WritePartitions(disk %lu) failed, Status 0x%08lx\n",
788 DiskEntry
->DiskNumber
, Status
);
789 return STATUS_PARTITION_FAILURE
;
792 /* Set PartitionRootPath */
793 RtlStringCchPrintfW(PartitionRootPath
, ARRAYSIZE(PartitionRootPath
),
794 L
"\\Device\\Harddisk%lu\\Partition%lu",
795 DiskEntry
->DiskNumber
,
796 PartEntry
->PartitionNumber
);
797 DPRINT("PartitionRootPath: %S\n", PartitionRootPath
);
799 /* Format the partition */
800 Status
= FormatFileSystem(PartitionRootPath
,
807 if (!NT_SUCCESS(Status
))
811 // TODO: Here, call a partlist.c function that update the actual
812 // FS name and the label fields of the volume.
814 PartEntry
->FormatState
= Formatted
;
816 /* Set the new partition's file system proper */
817 RtlStringCbCopyW(PartEntry
->FileSystem
,
818 sizeof(PartEntry
->FileSystem
),
821 PartEntry
->New
= FALSE
;
823 return STATUS_SUCCESS
;