mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +00:00
Added FAT16 format code.
svn path=/trunk/; revision=5721
This commit is contained in:
parent
dad429cc35
commit
5f04c08330
4 changed files with 583 additions and 152 deletions
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile,v 1.2 2003/08/07 04:03:22 royce Exp $
|
||||
# $Id: Makefile,v 1.3 2003/08/21 15:33:48 ekohl Exp $
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
|
@ -10,6 +10,7 @@ TARGET_NAME = vfatlib
|
|||
TARGET_CFLAGS += -D_DISABLE_TIDENTS
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
fat16.o \
|
||||
vfatlib.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
|
368
reactos/lib/fslib/vfatlib/fat16.c
Normal file
368
reactos/lib/fslib/vfatlib/fat16.c
Normal file
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS VFAT filesystem library
|
||||
* FILE: fat16.c
|
||||
* PURPOSE: Fat16 support
|
||||
* PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
|
||||
* REVISIONS:
|
||||
* EK 05/04-2003 Created
|
||||
*/
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#define NTOS_MODE_USER
|
||||
#include <ntos.h>
|
||||
#include <ddk/ntddscsi.h>
|
||||
#include "vfatlib.h"
|
||||
|
||||
|
||||
static ULONG
|
||||
GetShiftCount(ULONG Value)
|
||||
{
|
||||
ULONG i = 1;
|
||||
while (Value > 0)
|
||||
{
|
||||
i++;
|
||||
Value /= 2;
|
||||
}
|
||||
return i - 2;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
Fat16WriteBootSector(IN HANDLE FileHandle,
|
||||
IN PFAT16_BOOT_SECTOR BootSector)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
UNICODE_STRING Name;
|
||||
NTSTATUS Status;
|
||||
PUCHAR NewBootSector;
|
||||
LARGE_INTEGER FileOffset;
|
||||
|
||||
/* Allocate buffer for new bootsector */
|
||||
NewBootSector = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
SECTORSIZE);
|
||||
if (NewBootSector == NULL)
|
||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||
|
||||
/* Zero the new bootsector */
|
||||
memset(NewBootSector, 0, SECTORSIZE);
|
||||
|
||||
/* Copy FAT16 BPB to new bootsector */
|
||||
memcpy((NewBootSector + 3),
|
||||
&BootSector->OEMName[0],
|
||||
59); /* FAT16 BPB length (up to (not including) Res2) */
|
||||
|
||||
/* Write sector 0 */
|
||||
FileOffset.QuadPart = 0ULL;
|
||||
Status = NtWriteFile(FileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatusBlock,
|
||||
NewBootSector,
|
||||
SECTORSIZE,
|
||||
&FileOffset,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* Free the new boot sector */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
Fat16WriteFAT(IN HANDLE FileHandle,
|
||||
ULONG SectorOffset,
|
||||
IN PFAT16_BOOT_SECTOR BootSector)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
UNICODE_STRING Name;
|
||||
NTSTATUS Status;
|
||||
PUCHAR Buffer;
|
||||
LARGE_INTEGER FileOffset;
|
||||
ULONG i;
|
||||
ULONG Size;
|
||||
ULONG Sectors;
|
||||
|
||||
/* Allocate buffer */
|
||||
Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
32 * 1024);
|
||||
if (Buffer == NULL)
|
||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||
|
||||
/* Zero the buffer */
|
||||
memset(Buffer, 0, 32 * 1024);
|
||||
|
||||
/* FAT cluster 0 */
|
||||
Buffer[0] = 0xf8; /* Media type */
|
||||
Buffer[1] = 0xff;
|
||||
|
||||
/* FAT cluster 1 */
|
||||
Buffer[2] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
|
||||
Buffer[3] = 0xff;
|
||||
|
||||
/* Write first sector of the FAT */
|
||||
FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors) * BootSector->BytesPerSector;
|
||||
Status = NtWriteFile(FileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatusBlock,
|
||||
Buffer,
|
||||
BootSector->BytesPerSector,
|
||||
&FileOffset,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* Zero the begin of the buffer */
|
||||
memset(Buffer, 0, 4);
|
||||
|
||||
/* Zero the rest of the FAT */
|
||||
Sectors = 32 * 1024 / BootSector->BytesPerSector;
|
||||
for (i = 1; i < (ULONG)BootSector->FATSectors; i += Sectors)
|
||||
{
|
||||
/* Zero some sectors of the FAT */
|
||||
FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors + i) * BootSector->BytesPerSector;
|
||||
Size = (ULONG)BootSector->FATSectors - i;
|
||||
if (Size > Sectors)
|
||||
{
|
||||
Size = Sectors;
|
||||
}
|
||||
Size *= BootSector->BytesPerSector;
|
||||
Status = NtWriteFile(FileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatusBlock,
|
||||
Buffer,
|
||||
Size,
|
||||
&FileOffset,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the buffer */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
Fat16WriteRootDirectory(IN HANDLE FileHandle,
|
||||
IN PFAT16_BOOT_SECTOR BootSector)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
NTSTATUS Status;
|
||||
PUCHAR Buffer;
|
||||
LARGE_INTEGER FileOffset;
|
||||
ULONG FirstRootDirSector;
|
||||
ULONG RootDirSectors;
|
||||
ULONG Sectors;
|
||||
ULONG Size;
|
||||
ULONG i;
|
||||
|
||||
DPRINT("BootSector->ReservedSectors = %hu\n", BootSector->ReservedSectors);
|
||||
DPRINT("BootSector->FATSectors = %hu\n", BootSector->FATSectors);
|
||||
DPRINT("BootSector->SectorsPerCluster = %u\n", BootSector->SectorsPerCluster);
|
||||
|
||||
/* Write cluster */
|
||||
RootDirSectors = ((BootSector->RootEntries * 32) +
|
||||
(BootSector->BytesPerSector - 1)) / BootSector->BytesPerSector;
|
||||
FirstRootDirSector =
|
||||
BootSector->ReservedSectors + (BootSector->FATCount * BootSector->FATSectors);
|
||||
|
||||
DPRINT("RootDirSectors = %lu\n", RootDirSectors);
|
||||
DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector);
|
||||
|
||||
/* Allocate buffer for the cluster */
|
||||
Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
32 * 1024);
|
||||
if (Buffer == NULL)
|
||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||
|
||||
/* Zero the buffer */
|
||||
memset(Buffer, 0, 32 * 1024);
|
||||
|
||||
Sectors = 32 * 1024 / BootSector->BytesPerSector;
|
||||
for (i = 1; i < RootDirSectors; i += Sectors)
|
||||
{
|
||||
/* Zero some sectors of the root directory */
|
||||
FileOffset.QuadPart = (FirstRootDirSector + i) * BootSector->BytesPerSector;
|
||||
Size = RootDirSectors - i;
|
||||
if (Size > Sectors)
|
||||
{
|
||||
Size = Sectors;
|
||||
}
|
||||
Size *= BootSector->BytesPerSector;
|
||||
|
||||
Status = NtWriteFile(FileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatusBlock,
|
||||
Buffer,
|
||||
Size,
|
||||
&FileOffset,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the buffer */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
Fat16Format (HANDLE FileHandle,
|
||||
PPARTITION_INFORMATION PartitionInfo,
|
||||
PDISK_GEOMETRY DiskGeometry,
|
||||
PUNICODE_STRING Label,
|
||||
BOOL QuickFormat,
|
||||
DWORD ClusterSize,
|
||||
PFMIFSCALLBACK Callback)
|
||||
{
|
||||
FAT16_BOOT_SECTOR BootSector;
|
||||
ANSI_STRING VolumeLabel;
|
||||
ULONG RootDirSectors;
|
||||
ULONG TmpVal1;
|
||||
ULONG TmpVal2;
|
||||
ULONG TmpVal3;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Calculate cluster size */
|
||||
if (ClusterSize == 0)
|
||||
{
|
||||
if (PartitionInfo->PartitionLength.QuadPart < 16ULL * 1024ULL * 1024ULL)
|
||||
{
|
||||
/* Partition < 16MB ==> 1KB Cluster */
|
||||
ClusterSize = 1024;
|
||||
}
|
||||
else if (PartitionInfo->PartitionLength.QuadPart < 128ULL * 1024ULL * 1024ULL)
|
||||
{
|
||||
/* Partition < 128MB ==> 2KB Cluster */
|
||||
ClusterSize = 2048;
|
||||
}
|
||||
else if (PartitionInfo->PartitionLength.QuadPart < 256ULL * 1024ULL * 1024ULL)
|
||||
{
|
||||
/* Partition < 256MB ==> 4KB Cluster */
|
||||
ClusterSize = 4096;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Partition >= 256MB (< 512MB) ==> 8KB Cluster */
|
||||
ClusterSize = 8192;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&BootSector, 0, sizeof(FAT16_BOOT_SECTOR));
|
||||
memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
|
||||
BootSector.BytesPerSector = DiskGeometry->BytesPerSector;
|
||||
BootSector.SectorsPerCluster = ClusterSize / BootSector.BytesPerSector;
|
||||
BootSector.ReservedSectors = 1;
|
||||
BootSector.FATCount = 2;
|
||||
BootSector.RootEntries = 512;
|
||||
BootSector.Sectors = 0; //(SectorCount < 0x10000) ? SectorCount : 0;
|
||||
BootSector.Media = 0xf8;
|
||||
BootSector.FATSectors = 0; /* Set later. See below. */
|
||||
BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack;
|
||||
BootSector.Heads = DiskGeometry->TracksPerCylinder;
|
||||
BootSector.HiddenSectors = PartitionInfo->HiddenSectors;
|
||||
BootSector.SectorsHuge = PartitionInfo->PartitionLength.QuadPart >>
|
||||
GetShiftCount(BootSector.BytesPerSector); /* Use shifting to avoid 64-bit division */
|
||||
BootSector.Drive = 0xff; /* No BIOS boot drive available */
|
||||
BootSector.ExtBootSignature = 0x29;
|
||||
BootSector.VolumeID = 0x45768798; /* FIXME: */
|
||||
if ((Label == NULL) || (Label->Buffer == NULL))
|
||||
{
|
||||
memcpy(&BootSector.VolumeLabel[0], "NO NAME ", 11);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlUnicodeStringToAnsiString(&VolumeLabel, Label, TRUE);
|
||||
memset(&BootSector.VolumeLabel[0], ' ', 11);
|
||||
memcpy(&BootSector.VolumeLabel[0], VolumeLabel.Buffer,
|
||||
VolumeLabel.Length < 11 ? VolumeLabel.Length : 11);
|
||||
RtlFreeAnsiString(&VolumeLabel);
|
||||
}
|
||||
memcpy(&BootSector.SysType[0], "FAT16 ", 8);
|
||||
|
||||
DPRINT("BootSector.SectorsHuge = %lx\n", BootSector.SectorsHuge);
|
||||
|
||||
RootDirSectors = ((BootSector.RootEntries * 32) +
|
||||
(BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector;
|
||||
|
||||
TmpVal1 = BootSector.SectorsHuge - (BootSector.ReservedSectors + RootDirSectors);
|
||||
TmpVal2 = (256 * BootSector.SectorsPerCluster) + BootSector.FATCount;
|
||||
TmpVal3 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
|
||||
BootSector.FATSectors = (unsigned short)(TmpVal3 & 0xffff);
|
||||
|
||||
DPRINT("BootSector.FATSectors = %hx\n", BootSector.FATSectors);
|
||||
|
||||
Status = Fat16WriteBootSector(FileHandle,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Fat16WriteBootSector() failed with status 0x%.08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Write first FAT copy */
|
||||
Status = Fat16WriteFAT(FileHandle,
|
||||
0,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Fat16WriteFAT() failed with status 0x%.08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Write second FAT copy */
|
||||
Status = Fat16WriteFAT(FileHandle,
|
||||
(ULONG)BootSector.FATSectors,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Fat16WriteFAT() failed with status 0x%.08x.\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = Fat16WriteRootDirectory(FileHandle,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Fat16WriteRootDirectory() failed with status 0x%.08x\n", Status);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
|
@ -29,14 +29,6 @@ GetShiftCount(ULONG Value)
|
|||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
VfatInitialize()
|
||||
{
|
||||
DPRINT("VfatInitialize()\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
VfatWriteBootSector(IN HANDLE FileHandle,
|
||||
IN PFAT32_BOOT_SECTOR BootSector)
|
||||
|
@ -321,6 +313,166 @@ VfatWriteRootDirectory(IN HANDLE FileHandle,
|
|||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
VfatFormatFat32 (HANDLE FileHandle,
|
||||
PPARTITION_INFORMATION PartitionInfo,
|
||||
PDISK_GEOMETRY DiskGeometry,
|
||||
PUNICODE_STRING Label,
|
||||
BOOL QuickFormat,
|
||||
DWORD ClusterSize,
|
||||
PFMIFSCALLBACK Callback)
|
||||
{
|
||||
FAT32_BOOT_SECTOR BootSector;
|
||||
ANSI_STRING VolumeLabel;
|
||||
ULONG RootDirSectors;
|
||||
ULONG TmpVal1;
|
||||
ULONG TmpVal2;
|
||||
ULONG TmpVal3;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Calculate cluster size */
|
||||
if (ClusterSize == 0)
|
||||
{
|
||||
if (PartitionInfo->PartitionLength.QuadPart < 8ULL * 1024ULL * 1024ULL * 1024ULL)
|
||||
{
|
||||
/* Partition < 8GB ==> 4KB Cluster */
|
||||
ClusterSize = 4096;
|
||||
}
|
||||
else if (PartitionInfo->PartitionLength.QuadPart < 16ULL * 1024ULL * 1024ULL * 1024ULL)
|
||||
{
|
||||
/* Partition 8GB - 16GB ==> 8KB Cluster */
|
||||
ClusterSize = 8192;
|
||||
}
|
||||
else if (PartitionInfo->PartitionLength.QuadPart < 32ULL * 1024ULL * 1024ULL * 1024ULL)
|
||||
{
|
||||
/* Partition 16GB - 32GB ==> 16KB Cluster */
|
||||
ClusterSize = 16384;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Partition >= 32GB ==> 32KB Cluster */
|
||||
ClusterSize = 32768;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&BootSector, 0, sizeof(FAT32_BOOT_SECTOR));
|
||||
memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
|
||||
BootSector.BytesPerSector = DiskGeometry->BytesPerSector;
|
||||
BootSector.SectorsPerCluster = ClusterSize / BootSector.BytesPerSector;
|
||||
BootSector.ReservedSectors = 32;
|
||||
BootSector.FATCount = 2;
|
||||
BootSector.RootEntries = 0;
|
||||
BootSector.Sectors = 0;
|
||||
BootSector.Media = 0xf8;
|
||||
BootSector.FATSectors = 0;
|
||||
BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack;
|
||||
BootSector.Heads = DiskGeometry->TracksPerCylinder;
|
||||
BootSector.HiddenSectors = PartitionInfo->HiddenSectors;
|
||||
BootSector.SectorsHuge = PartitionInfo->PartitionLength.QuadPart >>
|
||||
GetShiftCount(BootSector.BytesPerSector); /* Use shifting to avoid 64-bit division */
|
||||
BootSector.FATSectors32 = 0; /* Set later */
|
||||
BootSector.ExtFlag = 0; /* Mirror all FATs */
|
||||
BootSector.FSVersion = 0x0000; /* 0:0 */
|
||||
BootSector.RootCluster = 2;
|
||||
BootSector.FSInfoSector = 1;
|
||||
BootSector.BootBackup = 6;
|
||||
BootSector.Drive = 0xff; /* No BIOS boot drive available */
|
||||
BootSector.ExtBootSignature = 0x29;
|
||||
BootSector.VolumeID = 0x45768798; /* FIXME: */
|
||||
if ((Label == NULL) || (Label->Buffer == NULL))
|
||||
{
|
||||
memcpy(&BootSector.VolumeLabel[0], "NO NAME ", 11);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlUnicodeStringToAnsiString(&VolumeLabel, Label, TRUE);
|
||||
memset(&BootSector.VolumeLabel[0], ' ', 11);
|
||||
memcpy(&BootSector.VolumeLabel[0], VolumeLabel.Buffer,
|
||||
VolumeLabel.Length < 11 ? VolumeLabel.Length : 11);
|
||||
RtlFreeAnsiString(&VolumeLabel);
|
||||
}
|
||||
memcpy(&BootSector.SysType[0], "FAT32 ", 8);
|
||||
|
||||
RootDirSectors = ((BootSector.RootEntries * 32) +
|
||||
(BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector;
|
||||
TmpVal1 = BootSector.SectorsHuge - (BootSector.ReservedSectors + RootDirSectors);
|
||||
TmpVal2 = (256 * BootSector.SectorsPerCluster) + BootSector.FATCount;
|
||||
if (TRUE /* FAT32 */)
|
||||
{
|
||||
TmpVal2 = 0;
|
||||
do
|
||||
{
|
||||
if (TmpVal2 == 0)
|
||||
{
|
||||
TmpVal3 = 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
TmpVal3 = TmpVal2;
|
||||
}
|
||||
TmpVal2 = ((TmpVal1 - TmpVal2 * BootSector.FATCount) / BootSector.SectorsPerCluster) + 2;
|
||||
TmpVal2 = (sizeof(ULONG) * TmpVal2 + BootSector.BytesPerSector - 1) / BootSector.BytesPerSector;
|
||||
}
|
||||
while (TmpVal3 > TmpVal2);
|
||||
BootSector.FATSectors32 = TmpVal2;
|
||||
}
|
||||
|
||||
Status = VfatWriteBootSector(FileHandle,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("VfatWriteBootSector() failed with status 0x%.08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = VfatWriteFsInfo(FileHandle,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("VfatWriteFsInfo() failed with status 0x%.08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Write first FAT copy */
|
||||
Status = VfatWriteFAT(FileHandle,
|
||||
0,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("VfatWriteFAT() failed with status 0x%.08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Write second FAT copy */
|
||||
Status = VfatWriteFAT(FileHandle,
|
||||
BootSector.FATSectors32,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("VfatWriteFAT() failed with status 0x%.08x.\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = VfatWriteRootDirectory(FileHandle,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("VfatWriteRootDirectory() failed with status 0x%.08x\n", Status);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
VfatInitialize()
|
||||
{
|
||||
DPRINT("VfatInitialize()\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
VfatFormat(
|
||||
PUNICODE_STRING DriveRoot,
|
||||
|
@ -336,13 +488,7 @@ VfatFormat(
|
|||
HANDLE FileHandle;
|
||||
SCSI_ADDRESS ScsiAddress;
|
||||
PARTITION_INFORMATION PartitionInfo;
|
||||
FAT32_BOOT_SECTOR BootSector;
|
||||
ANSI_STRING VolumeLabel;
|
||||
NTSTATUS Status;
|
||||
ULONG RootDirSectors;
|
||||
ULONG TmpVal1;
|
||||
ULONG TmpVal2;
|
||||
ULONG TmpVal3;
|
||||
|
||||
DPRINT("VfatFormat(DriveRoot '%S')\n", DriveRoot->Buffer);
|
||||
|
||||
|
@ -428,146 +574,23 @@ VfatFormat(
|
|||
|
||||
if (PartitionInfo.PartitionLength.QuadPart < 512ULL * 1024ULL * 1024ULL)
|
||||
{
|
||||
DPRINT1("FIXME: Partition size is smaller than 512MB - use FAT16\n");
|
||||
NtClose(FileHandle);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
/* Calculate cluster size */
|
||||
if (ClusterSize == 0)
|
||||
{
|
||||
if (PartitionInfo.PartitionLength.QuadPart < 8ULL * 1024ULL * 1024ULL * 1024ULL)
|
||||
{
|
||||
/* Partition < 8GB ==> 4KB Cluster */
|
||||
ClusterSize = 4096;
|
||||
}
|
||||
else if (PartitionInfo.PartitionLength.QuadPart < 16ULL * 1024ULL * 1024ULL * 1024ULL)
|
||||
{
|
||||
/* Partition 8GB - 16GB ==> 8KB Cluster */
|
||||
ClusterSize = 8192;
|
||||
}
|
||||
else if (PartitionInfo.PartitionLength.QuadPart < 32ULL * 1024ULL * 1024ULL * 1024ULL)
|
||||
{
|
||||
/* Partition 16GB - 32GB ==> 16KB Cluster */
|
||||
ClusterSize = 16384;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Partition >= 32GB ==> 32KB Cluster */
|
||||
ClusterSize = 32768;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&BootSector, 0, sizeof(FAT32_BOOT_SECTOR));
|
||||
memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
|
||||
BootSector.BytesPerSector = DiskGeometry.BytesPerSector;
|
||||
BootSector.SectorsPerCluster = ClusterSize / BootSector.BytesPerSector;
|
||||
BootSector.ReservedSectors = 32;
|
||||
BootSector.FATCount = 2;
|
||||
BootSector.RootEntries = 0;
|
||||
BootSector.Sectors = 0;
|
||||
BootSector.Media = 0xf8;
|
||||
BootSector.FATSectors = 0;
|
||||
BootSector.SectorsPerTrack = DiskGeometry.SectorsPerTrack;
|
||||
BootSector.Heads = DiskGeometry.TracksPerCylinder;
|
||||
BootSector.HiddenSectors = DiskGeometry.SectorsPerTrack; //PartitionInfo.HiddenSectors;
|
||||
BootSector.SectorsHuge = PartitionInfo.PartitionLength.QuadPart >>
|
||||
GetShiftCount(BootSector.BytesPerSector); /* Use shifting to avoid 64-bit division */
|
||||
BootSector.FATSectors32 = 0; /* Set later */
|
||||
BootSector.ExtFlag = 0; /* Mirror all FATs */
|
||||
BootSector.FSVersion = 0x0000; /* 0:0 */
|
||||
BootSector.RootCluster = 2;
|
||||
BootSector.FSInfoSector = 1;
|
||||
BootSector.BootBackup = 6;
|
||||
BootSector.Drive = 0xff; /* No BIOS boot drive available */
|
||||
BootSector.ExtBootSignature = 0x29;
|
||||
BootSector.VolumeID = 0x45768798; /* FIXME: */
|
||||
if ((Label == NULL) || (Label->Buffer == NULL))
|
||||
{
|
||||
memcpy(&BootSector.VolumeLabel[0], "NO NAME ", 11);
|
||||
Status = Fat16Format (FileHandle,
|
||||
&PartitionInfo,
|
||||
&DiskGeometry,
|
||||
Label,
|
||||
QuickFormat,
|
||||
ClusterSize,
|
||||
Callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlUnicodeStringToAnsiString(&VolumeLabel, Label, TRUE);
|
||||
memset(&BootSector.VolumeLabel[0], ' ', 11);
|
||||
memcpy(&BootSector.VolumeLabel[0], VolumeLabel.Buffer,
|
||||
VolumeLabel.Length < 11 ? VolumeLabel.Length : 11);
|
||||
RtlFreeAnsiString(&VolumeLabel);
|
||||
}
|
||||
memcpy(&BootSector.SysType[0], "FAT32 ", 8);
|
||||
|
||||
RootDirSectors = ((BootSector.RootEntries * 32) +
|
||||
(BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector;
|
||||
TmpVal1 = BootSector.SectorsHuge - (BootSector.ReservedSectors + RootDirSectors);
|
||||
TmpVal2 = (256 * BootSector.SectorsPerCluster) + BootSector.FATCount;
|
||||
if (TRUE /* FAT32 */)
|
||||
{
|
||||
TmpVal2 = 0;
|
||||
do
|
||||
{
|
||||
if (TmpVal2 == 0)
|
||||
{
|
||||
TmpVal3 = 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
TmpVal3 = TmpVal2;
|
||||
}
|
||||
TmpVal2 = ((TmpVal1 - TmpVal2 * BootSector.FATCount) / BootSector.SectorsPerCluster) + 2;
|
||||
TmpVal2 = (sizeof(ULONG) * TmpVal2 + BootSector.BytesPerSector - 1) / BootSector.BytesPerSector;
|
||||
}
|
||||
while (TmpVal3 > TmpVal2);
|
||||
BootSector.FATSectors32 = TmpVal2;
|
||||
}
|
||||
|
||||
Status = VfatWriteBootSector(FileHandle,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("VfatWriteBootSector() failed with status 0x%.08x\n", Status);
|
||||
NtClose(FileHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = VfatWriteFsInfo(FileHandle,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("VfatWriteFsInfo() failed with status 0x%.08x\n", Status);
|
||||
NtClose(FileHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Write first FAT copy */
|
||||
Status = VfatWriteFAT(FileHandle,
|
||||
0,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("VfatWriteFAT() failed with status 0x%.08x\n", Status);
|
||||
NtClose(FileHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Write second FAT copy */
|
||||
Status = VfatWriteFAT(FileHandle,
|
||||
BootSector.FATSectors32,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("VfatWriteFAT() failed with status 0x%.08x.\n", Status);
|
||||
NtClose(FileHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = VfatWriteRootDirectory(FileHandle,
|
||||
&BootSector);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("VfatWriteRootDirectory() failed with status 0x%.08x\n", Status);
|
||||
NtClose(FileHandle);
|
||||
return Status;
|
||||
Status = VfatFormatFat32 (FileHandle,
|
||||
&PartitionInfo,
|
||||
&DiskGeometry,
|
||||
Label,
|
||||
QuickFormat,
|
||||
ClusterSize,
|
||||
Callback);
|
||||
}
|
||||
|
||||
NtClose(FileHandle);
|
||||
|
|
|
@ -11,6 +11,35 @@
|
|||
|
||||
#define SECTORSIZE 512
|
||||
|
||||
typedef struct _FAT16_BOOT_SECTOR
|
||||
{
|
||||
unsigned char magic0; // 0
|
||||
unsigned char res0; // 1
|
||||
unsigned char magic1; // 2
|
||||
unsigned char OEMName[8]; // 3
|
||||
unsigned short BytesPerSector; // 11
|
||||
unsigned char SectorsPerCluster; // 13
|
||||
unsigned short ReservedSectors; // 14
|
||||
unsigned char FATCount; // 16
|
||||
unsigned short RootEntries; // 17
|
||||
unsigned short Sectors; // 19
|
||||
unsigned char Media; // 21
|
||||
unsigned short FATSectors; // 22
|
||||
unsigned short SectorsPerTrack; // 24
|
||||
unsigned short Heads; // 26
|
||||
unsigned long HiddenSectors; // 28
|
||||
unsigned long SectorsHuge; // 32
|
||||
unsigned char Drive; // 36
|
||||
unsigned char Res1; // 37
|
||||
unsigned char ExtBootSignature; // 38
|
||||
unsigned long VolumeID; // 39
|
||||
unsigned char VolumeLabel[11]; // 43
|
||||
unsigned char SysType[8]; // 54
|
||||
unsigned char Res2[446]; // 62
|
||||
unsigned long Signature1; // 508
|
||||
} __attribute__((packed)) FAT16_BOOT_SECTOR, *PFAT16_BOOT_SECTOR;
|
||||
|
||||
|
||||
typedef struct _FAT32_BOOT_SECTOR
|
||||
{
|
||||
unsigned char magic0; // 0
|
||||
|
@ -56,3 +85,13 @@ typedef struct _FAT32_FSINFO
|
|||
unsigned long Res2[3]; // 496
|
||||
unsigned long TrailSig; // 508
|
||||
} __attribute__((packed)) FAT32_FSINFO, *PFAT32_FSINFO;
|
||||
|
||||
|
||||
NTSTATUS
|
||||
Fat16Format (HANDLE FileHandle,
|
||||
PPARTITION_INFORMATION PartitionInfo,
|
||||
PDISK_GEOMETRY DiskGeometry,
|
||||
PUNICODE_STRING Label,
|
||||
BOOL QuickFormat,
|
||||
DWORD ClusterSize,
|
||||
PFMIFSCALLBACK Callback);
|
||||
|
|
Loading…
Reference in a new issue