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 typedef struct _NTFS_BOOTSECTOR
118 USHORT BytesPerSector
;
119 UCHAR SectorsPerCluster
;
123 USHORT SectorsPerTrack
;
128 ULONGLONG SectorCount
;
129 ULONGLONG MftLocation
;
130 ULONGLONG MftMirrLocation
;
131 CHAR ClustersPerMftRecord
;
133 CHAR ClustersPerIndexRecord
;
135 ULONGLONG SerialNumber
;
137 UCHAR BootStrap
[426];
139 UCHAR BootCodeAndData
[7680]; // The remainder of the boot sector (8192 - 512)
140 } NTFS_BOOTSECTOR
, *PNTFS_BOOTSECTOR
;
141 C_ASSERT(sizeof(NTFS_BOOTSECTOR
) == NTFS_BOOTSECTOR_SIZE
);
143 // TODO: Add more bootsector structures!
148 /* LOCALS *******************************************************************/
151 typedef struct _FILE_SYSTEM
153 PCWSTR FileSystemName
;
154 PULIB_FORMAT FormatFunc
;
155 PULIB_CHKDSK ChkdskFunc
;
156 } FILE_SYSTEM
, *PFILE_SYSTEM
;
158 /* The list of file systems on which we can install ReactOS */
159 static FILE_SYSTEM RegisteredFileSystems
[] =
161 /* NOTE: The FAT formatter will automatically
162 * determine whether to use FAT12/16 or FAT32. */
163 { L
"FAT" , VfatFormat
, VfatChkdsk
},
164 { L
"FAT32", VfatFormat
, VfatChkdsk
},
166 { L
"FATX" , VfatxFormat
, VfatxChkdsk
},
167 { L
"NTFS" , NtfsFormat
, NtfsChkdsk
},
169 { L
"BTRFS", BtrfsFormat
, BtrfsChkdsk
},
171 { L
"EXT2" , Ext2Format
, Ext2Chkdsk
},
172 { L
"EXT3" , Ext2Format
, Ext2Chkdsk
},
173 { L
"EXT4" , Ext2Format
, Ext2Chkdsk
},
178 /* FUNCTIONS ****************************************************************/
180 /** QueryAvailableFileSystemFormat() **/
182 GetRegisteredFileSystems(
184 OUT PCWSTR
* FileSystemName
)
186 if (Index
>= ARRAYSIZE(RegisteredFileSystems
))
189 *FileSystemName
= RegisteredFileSystems
[Index
].FileSystemName
;
195 /** GetProvider() **/
198 IN PCWSTR FileSystemName
)
200 #if 0 // Reenable when the list of registered FSes will again be dynamic
202 PLIST_ENTRY ListEntry
;
203 PFILE_SYSTEM_ITEM Item
;
205 ListEntry
= List
->ListHead
.Flink
;
206 while (ListEntry
!= &List
->ListHead
)
208 Item
= CONTAINING_RECORD(ListEntry
, FILE_SYSTEM_ITEM
, ListEntry
);
209 if (Item
->FileSystemName
&&
210 (wcsicmp(FileSystemName
, Item
->FileSystemName
) == 0))
215 ListEntry
= ListEntry
->Flink
;
220 ULONG Count
= ARRAYSIZE(RegisteredFileSystems
);
221 PFILE_SYSTEM FileSystems
= RegisteredFileSystems
;
223 ASSERT(FileSystems
&& Count
!= 0);
227 if (FileSystems
->FileSystemName
&&
228 (wcsicmp(FileSystemName
, FileSystems
->FileSystemName
) == 0))
244 ChkdskFileSystem_UStr(
245 IN PUNICODE_STRING DriveRoot
,
246 IN PCWSTR FileSystemName
,
247 IN BOOLEAN FixErrors
,
249 IN BOOLEAN CheckOnlyIfDirty
,
250 IN BOOLEAN ScanDrive
,
251 IN PFMIFSCALLBACK Callback
)
253 PFILE_SYSTEM FileSystem
;
257 FileSystem
= GetFileSystemByName(FileSystemName
);
259 if (!FileSystem
|| !FileSystem
->ChkdskFunc
)
262 // Callback(DONE, 0, &Success);
263 return STATUS_NOT_SUPPORTED
;
266 Status
= STATUS_SUCCESS
;
267 Success
= FileSystem
->ChkdskFunc(DriveRoot
,
279 DPRINT1("ChkdskFunc() failed with Status 0x%lx\n", Status
);
281 // Callback(DONE, 0, &Success);
289 IN PCWSTR FileSystemName
,
290 IN BOOLEAN FixErrors
,
292 IN BOOLEAN CheckOnlyIfDirty
,
293 IN BOOLEAN ScanDrive
,
294 IN PFMIFSCALLBACK Callback
)
296 UNICODE_STRING DriveRootU
;
298 RtlInitUnicodeString(&DriveRootU
, DriveRoot
);
299 return ChkdskFileSystem_UStr(&DriveRootU
,
311 FormatFileSystem_UStr(
312 IN PUNICODE_STRING DriveRoot
,
313 IN PCWSTR FileSystemName
,
314 IN FMIFS_MEDIA_FLAG MediaFlag
,
315 IN PUNICODE_STRING Label
,
316 IN BOOLEAN QuickFormat
,
317 IN ULONG ClusterSize
,
318 IN PFMIFSCALLBACK Callback
)
320 PFILE_SYSTEM FileSystem
;
322 BOOLEAN BackwardCompatible
= FALSE
; // Default to latest FS versions.
323 MEDIA_TYPE MediaType
;
325 FileSystem
= GetFileSystemByName(FileSystemName
);
327 if (!FileSystem
|| !FileSystem
->FormatFunc
)
330 // Callback(DONE, 0, &Success);
331 return STATUS_NOT_SUPPORTED
;
334 /* Set the BackwardCompatible flag in case we format with older FAT12/16 */
335 if (wcsicmp(FileSystemName
, L
"FAT") == 0)
336 BackwardCompatible
= TRUE
;
337 // else if (wcsicmp(FileSystemName, L"FAT32") == 0)
338 // BackwardCompatible = FALSE;
340 /* Convert the FMIFS MediaFlag to a NT MediaType */
341 // FIXME: Actually covert all the possible flags.
345 MediaType
= F5_320_1024
; // FIXME: This is hardfixed!
347 case FMIFS_REMOVABLE
:
348 MediaType
= RemovableMedia
;
351 MediaType
= FixedMedia
;
354 DPRINT1("Unknown FMIFS MediaFlag %d, converting 1-to-1 to NT MediaType\n",
356 MediaType
= (MEDIA_TYPE
)MediaFlag
;
360 Success
= FileSystem
->FormatFunc(DriveRoot
,
368 DPRINT1("FormatFunc() failed\n");
370 // Callback(DONE, 0, &Success);
372 return (Success
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
378 IN PCWSTR FileSystemName
,
379 IN FMIFS_MEDIA_FLAG MediaFlag
,
381 IN BOOLEAN QuickFormat
,
382 IN ULONG ClusterSize
,
383 IN PFMIFSCALLBACK Callback
)
385 UNICODE_STRING DriveRootU
;
386 UNICODE_STRING LabelU
;
388 RtlInitUnicodeString(&DriveRootU
, DriveRoot
);
389 RtlInitUnicodeString(&LabelU
, Label
);
391 return FormatFileSystem_UStr(&DriveRootU
,
402 // Bootsector routines
407 IN PCWSTR SrcPath
, // FAT12/16 bootsector source file (on the installation medium)
408 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
409 IN HANDLE RootPartition
) // Partition holding the (old) FAT12/16 information
413 IO_STATUS_BLOCK IoStatusBlock
;
414 LARGE_INTEGER FileOffset
;
415 BOOTCODE OrigBootSector
= {0};
416 BOOTCODE NewBootSector
= {0};
418 /* Allocate and read the current original partition bootsector */
419 Status
= ReadBootCodeByHandle(&OrigBootSector
,
421 FAT_BOOTSECTOR_SIZE
);
422 if (!NT_SUCCESS(Status
))
425 /* Allocate and read the new bootsector from SrcPath */
426 RtlInitUnicodeString(&Name
, SrcPath
);
427 Status
= ReadBootCodeFromFile(&NewBootSector
,
429 FAT_BOOTSECTOR_SIZE
);
430 if (!NT_SUCCESS(Status
))
432 FreeBootCode(&OrigBootSector
);
436 /* Adjust the bootsector (copy a part of the FAT12/16 BPB) */
437 RtlCopyMemory(&((PFAT_BOOTSECTOR
)NewBootSector
.BootCode
)->OemName
,
438 &((PFAT_BOOTSECTOR
)OrigBootSector
.BootCode
)->OemName
,
439 FIELD_OFFSET(FAT_BOOTSECTOR
, BootCodeAndData
) -
440 FIELD_OFFSET(FAT_BOOTSECTOR
, OemName
));
442 /* Free the original bootsector */
443 FreeBootCode(&OrigBootSector
);
445 /* Write the new bootsector to DstPath */
446 FileOffset
.QuadPart
= 0ULL;
447 Status
= NtWriteFile(DstPath
,
452 NewBootSector
.BootCode
,
453 NewBootSector
.Length
,
457 /* Free the new bootsector */
458 FreeBootCode(&NewBootSector
);
464 InstallFat32BootCode(
465 IN PCWSTR SrcPath
, // FAT32 bootsector source file (on the installation medium)
466 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
467 IN HANDLE RootPartition
) // Partition holding the (old) FAT32 information
471 IO_STATUS_BLOCK IoStatusBlock
;
472 LARGE_INTEGER FileOffset
;
473 USHORT BackupBootSector
= 0;
474 BOOTCODE OrigBootSector
= {0};
475 BOOTCODE NewBootSector
= {0};
477 /* Allocate and read the current original partition bootsector */
478 Status
= ReadBootCodeByHandle(&OrigBootSector
,
480 FAT32_BOOTSECTOR_SIZE
);
481 if (!NT_SUCCESS(Status
))
484 /* Allocate and read the new bootsector (2 sectors) from SrcPath */
485 RtlInitUnicodeString(&Name
, SrcPath
);
486 Status
= ReadBootCodeFromFile(&NewBootSector
,
488 2 * FAT32_BOOTSECTOR_SIZE
);
489 if (!NT_SUCCESS(Status
))
491 FreeBootCode(&OrigBootSector
);
495 /* Adjust the bootsector (copy a part of the FAT32 BPB) */
496 RtlCopyMemory(&((PFAT32_BOOTSECTOR
)NewBootSector
.BootCode
)->OemName
,
497 &((PFAT32_BOOTSECTOR
)OrigBootSector
.BootCode
)->OemName
,
498 FIELD_OFFSET(FAT32_BOOTSECTOR
, BootCodeAndData
) -
499 FIELD_OFFSET(FAT32_BOOTSECTOR
, OemName
));
502 * We know we copy the boot code to a file only when DstPath != RootPartition,
503 * otherwise the boot code is copied to the specified root partition.
505 if (DstPath
!= RootPartition
)
507 /* Copy to a file: Disable the backup bootsector */
508 ((PFAT32_BOOTSECTOR
)NewBootSector
.BootCode
)->BackupBootSector
= 0;
512 /* Copy to a disk: Get the location of the backup bootsector */
513 BackupBootSector
= ((PFAT32_BOOTSECTOR
)OrigBootSector
.BootCode
)->BackupBootSector
;
516 /* Free the original bootsector */
517 FreeBootCode(&OrigBootSector
);
519 /* Write the first sector of the new bootcode to DstPath sector 0 */
520 FileOffset
.QuadPart
= 0ULL;
521 Status
= NtWriteFile(DstPath
,
526 NewBootSector
.BootCode
,
527 FAT32_BOOTSECTOR_SIZE
,
530 if (!NT_SUCCESS(Status
))
532 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
533 FreeBootCode(&NewBootSector
);
537 if (DstPath
== RootPartition
)
539 /* Copy to a disk: Write the backup bootsector */
540 if ((BackupBootSector
!= 0x0000) && (BackupBootSector
!= 0xFFFF))
542 FileOffset
.QuadPart
= (ULONGLONG
)((ULONG
)BackupBootSector
* FAT32_BOOTSECTOR_SIZE
);
543 Status
= NtWriteFile(DstPath
,
548 NewBootSector
.BootCode
,
549 FAT32_BOOTSECTOR_SIZE
,
552 if (!NT_SUCCESS(Status
))
554 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
555 FreeBootCode(&NewBootSector
);
561 /* Write the second sector of the new bootcode to boot disk sector 14 */
562 // FileOffset.QuadPart = (ULONGLONG)(14 * FAT32_BOOTSECTOR_SIZE);
563 FileOffset
.QuadPart
= 14 * FAT32_BOOTSECTOR_SIZE
;
564 Status
= NtWriteFile(DstPath
, // or really RootPartition ???
569 ((PUCHAR
)NewBootSector
.BootCode
+ FAT32_BOOTSECTOR_SIZE
),
570 FAT32_BOOTSECTOR_SIZE
,
573 if (!NT_SUCCESS(Status
))
575 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
578 /* Free the new bootsector */
579 FreeBootCode(&NewBootSector
);
585 InstallBtrfsBootCode(
586 IN PCWSTR SrcPath
, // BTRFS bootsector source file (on the installation medium)
587 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
588 IN HANDLE RootPartition
) // Partition holding the (old) BTRFS information
593 IO_STATUS_BLOCK IoStatusBlock
;
594 LARGE_INTEGER FileOffset
;
595 PARTITION_INFORMATION_EX PartInfo
;
596 BOOTCODE NewBootSector
= {0};
598 /* Allocate and read the new bootsector from SrcPath */
599 RtlInitUnicodeString(&Name
, SrcPath
);
600 Status
= ReadBootCodeFromFile(&NewBootSector
,
602 BTRFS_BOOTSECTOR_SIZE
);
603 if (!NT_SUCCESS(Status
))
607 * The BTRFS driver requires the volume to be locked in order to modify
608 * the first sectors of the partition, even though they are outside the
609 * file-system space / in the reserved area (they are situated before
610 * the super-block at 0x1000) and is in principle allowed by the NT
612 * So we lock here in order to write the bootsector at sector 0.
613 * If locking fails, we ignore and continue nonetheless.
615 LockStatus
= NtFsControlFile(DstPath
,
625 if (!NT_SUCCESS(LockStatus
))
627 DPRINT1("WARNING: Failed to lock BTRFS volume for writing bootsector! Operations may fail! (Status 0x%lx)\n", LockStatus
);
630 /* Obtain partition info and write it to the bootsector */
631 Status
= NtDeviceIoControlFile(RootPartition
,
636 IOCTL_DISK_GET_PARTITION_INFO_EX
,
641 if (!NT_SUCCESS(Status
))
643 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status
);
647 /* Write new bootsector to RootPath */
648 ((PBTRFS_BOOTSECTOR
)NewBootSector
.BootCode
)->PartitionStartLBA
=
649 PartInfo
.StartingOffset
.QuadPart
/ SECTORSIZE
;
652 FileOffset
.QuadPart
= 0ULL;
653 Status
= NtWriteFile(DstPath
,
658 NewBootSector
.BootCode
,
659 NewBootSector
.Length
,
662 if (!NT_SUCCESS(Status
))
664 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
669 /* Unlock the volume */
670 LockStatus
= NtFsControlFile(DstPath
,
680 if (!NT_SUCCESS(LockStatus
))
682 DPRINT1("Failed to unlock BTRFS volume (Status 0x%lx)\n", LockStatus
);
685 /* Free the new bootsector */
686 FreeBootCode(&NewBootSector
);
693 IN PCWSTR SrcPath
, // NTFS bootsector source file (on the installation medium)
694 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
695 IN HANDLE RootPartition
) // Partition holding the (old) NTFS information
699 IO_STATUS_BLOCK IoStatusBlock
;
700 LARGE_INTEGER FileOffset
;
701 BOOTCODE OrigBootSector
= {0};
702 BOOTCODE NewBootSector
= {0};
704 /* Allocate and read the current original partition bootsector */
705 Status
= ReadBootCodeByHandle(&OrigBootSector
, RootPartition
, NTFS_BOOTSECTOR_SIZE
);
706 if (!NT_SUCCESS(Status
))
708 DPRINT1("InstallNtfsBootCode: Status %lx\n", Status
);
712 /* Allocate and read the new bootsector (16 sectors) from SrcPath */
713 RtlInitUnicodeString(&Name
, SrcPath
);
714 Status
= ReadBootCodeFromFile(&NewBootSector
, &Name
, NTFS_BOOTSECTOR_SIZE
);
715 if (!NT_SUCCESS(Status
))
717 DPRINT1("InstallNtfsBootCode: Status %lx\n", Status
);
718 FreeBootCode(&OrigBootSector
);
722 /* Adjust the bootsector (copy a part of the NTFS BPB) */
723 RtlCopyMemory(&((PNTFS_BOOTSECTOR
)NewBootSector
.BootCode
)->OEMID
,
724 &((PNTFS_BOOTSECTOR
)OrigBootSector
.BootCode
)->OEMID
,
725 FIELD_OFFSET(NTFS_BOOTSECTOR
, BootStrap
) - FIELD_OFFSET(NTFS_BOOTSECTOR
, OEMID
));
728 FileOffset
.QuadPart
= 0ULL;
729 Status
= NtWriteFile(DstPath
,
734 NewBootSector
.BootCode
,
735 NewBootSector
.Length
,
738 if (!NT_SUCCESS(Status
))
740 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
745 /* Free the new bootsector */
746 FreeBootCode(&NewBootSector
);
753 // Formatting routines
758 IN PPARTENTRY PartEntry
,
759 IN BOOLEAN FixErrors
,
761 IN BOOLEAN CheckOnlyIfDirty
,
762 IN BOOLEAN ScanDrive
,
763 IN PFMIFSCALLBACK Callback
)
766 PDISKENTRY DiskEntry
= PartEntry
->DiskEntry
;
767 // UNICODE_STRING PartitionRootPath;
768 WCHAR PartitionRootPath
[MAX_PATH
]; // PathBuffer
770 ASSERT(PartEntry
->IsPartitioned
&& PartEntry
->PartitionNumber
!= 0);
772 /* HACK: Do not try to check a partition with an unknown filesystem */
773 if (!*PartEntry
->FileSystem
)
775 PartEntry
->NeedsCheck
= FALSE
;
776 return STATUS_SUCCESS
;
779 /* Set PartitionRootPath */
780 RtlStringCchPrintfW(PartitionRootPath
, ARRAYSIZE(PartitionRootPath
),
781 L
"\\Device\\Harddisk%lu\\Partition%lu",
782 DiskEntry
->DiskNumber
,
783 PartEntry
->PartitionNumber
);
784 DPRINT("PartitionRootPath: %S\n", PartitionRootPath
);
786 /* Check the partition */
787 Status
= ChkdskFileSystem(PartitionRootPath
,
788 PartEntry
->FileSystem
,
794 if (!NT_SUCCESS(Status
))
797 PartEntry
->NeedsCheck
= FALSE
;
798 return STATUS_SUCCESS
;
803 IN PPARTENTRY PartEntry
,
804 IN PCWSTR FileSystemName
,
805 IN FMIFS_MEDIA_FLAG MediaFlag
,
807 IN BOOLEAN QuickFormat
,
808 IN ULONG ClusterSize
,
809 IN PFMIFSCALLBACK Callback
)
812 PDISKENTRY DiskEntry
= PartEntry
->DiskEntry
;
814 // UNICODE_STRING PartitionRootPath;
815 WCHAR PartitionRootPath
[MAX_PATH
]; // PathBuffer
817 ASSERT(PartEntry
->IsPartitioned
&& PartEntry
->PartitionNumber
!= 0);
819 if (!FileSystemName
|| !*FileSystemName
)
821 DPRINT1("No file system specified?\n");
822 return STATUS_UNRECOGNIZED_VOLUME
;
826 * Prepare the partition for formatting (for MBR disks, reset the
827 * partition type), and adjust the filesystem name in case of FAT
828 * vs. FAT32, depending on the geometry of the partition.
831 // FIXME: Do this only if QuickFormat == FALSE? What about FAT handling?
834 * Retrieve a partition type as a hint only. It will be used to determine
835 * whether to actually use FAT12/16 or FAT32 filesystem, depending on the
836 * geometry of the partition. If the partition resides on an MBR disk,
837 * the partition style will be reset to this value as well, unless the
840 PartitionType
= FileSystemToMBRPartitionType(FileSystemName
,
841 PartEntry
->StartSector
.QuadPart
,
842 PartEntry
->SectorCount
.QuadPart
);
843 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
845 /* Unknown file system */
846 DPRINT1("Unknown file system '%S'\n", FileSystemName
);
847 return STATUS_UNRECOGNIZED_VOLUME
;
850 /* Reset the MBR partition type, unless this is an OEM partition */
851 if (DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
)
853 if (!IsOEMPartition(PartEntry
->PartitionType
))
854 SetMBRPartitionType(PartEntry
, PartitionType
);
858 * Adjust the filesystem name in case of FAT vs. FAT32, according to
859 * the type of partition returned by FileSystemToMBRPartitionType().
861 if (wcsicmp(FileSystemName
, L
"FAT") == 0)
863 if ((PartitionType
== PARTITION_FAT32
) ||
864 (PartitionType
== PARTITION_FAT32_XINT13
))
866 FileSystemName
= L
"FAT32";
870 /* Commit the partition changes to the disk */
871 Status
= WritePartitions(DiskEntry
);
872 if (!NT_SUCCESS(Status
))
874 DPRINT1("WritePartitions(disk %lu) failed, Status 0x%08lx\n",
875 DiskEntry
->DiskNumber
, Status
);
876 return STATUS_PARTITION_FAILURE
;
879 /* Set PartitionRootPath */
880 RtlStringCchPrintfW(PartitionRootPath
, ARRAYSIZE(PartitionRootPath
),
881 L
"\\Device\\Harddisk%lu\\Partition%lu",
882 DiskEntry
->DiskNumber
,
883 PartEntry
->PartitionNumber
);
884 DPRINT("PartitionRootPath: %S\n", PartitionRootPath
);
886 /* Format the partition */
887 Status
= FormatFileSystem(PartitionRootPath
,
894 if (!NT_SUCCESS(Status
))
898 // TODO: Here, call a partlist.c function that update the actual
899 // FS name and the label fields of the volume.
901 PartEntry
->FormatState
= Formatted
;
903 /* Set the new partition's file system proper */
904 RtlStringCbCopyW(PartEntry
->FileSystem
,
905 sizeof(PartEntry
->FileSystem
),
908 PartEntry
->New
= FALSE
;
910 return STATUS_SUCCESS
;