- Added vfatxlib. Added: trunk/reactos/include/fslib/vfatxlib.h Added: trunk/reactos/lib/fslib/vfatxlib/ Added: trunk/reactos/lib/fslib/vfatxlib/Makefile Added: trunk/reactos/lib/fslib/vfatxlib/fatx.c Added: trunk/reactos/lib/fslib/vfatxlib/vfatxlib.c Added: trunk/reactos/lib/fslib/vfatxlib/vfatxlib.h _____
Added: trunk/reactos/include/fslib/vfatxlib.h --- trunk/reactos/include/fslib/vfatxlib.h 2005-01-25 21:16:19 UTC (rev 13285) +++ trunk/reactos/include/fslib/vfatxlib.h 2005-01-25 22:10:39 UTC (rev 13286) @@ -0,0 +1,24 @@
+/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS VFAT filesystem library + * FILE: include/fslib/vfatlib.h + * PURPOSE: Public definitions for vfat filesystem library + */ +#ifndef __VFATXLIB_H +#define __VFATXLIB_H + +#include <fmifs.h> + +NTSTATUS +VfatxInitialize (VOID); + +NTSTATUS +VfatxCleanup (VOID); + +NTSTATUS +VfatxFormat (PUNICODE_STRING DriveRoot, + ULONG MediaFlag, + BOOLEAN QuickFormat, + PFMIFSCALLBACK Callback); + +#endif /*__VFATLIB_H */ _____
Added: trunk/reactos/lib/fslib/vfatxlib/Makefile --- trunk/reactos/lib/fslib/vfatxlib/Makefile 2005-01-25 21:16:19 UTC (rev 13285) +++ trunk/reactos/lib/fslib/vfatxlib/Makefile 2005-01-25 22:10:39 UTC (rev 13286) @@ -0,0 +1,18 @@
+# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = library + +TARGET_NAME = vfatxlib + +# require os code to explicitly request A/W version of structs/functions +TARGET_CFLAGS += -D_DISABLE_TIDENTS -Wall -Werror + +TARGET_OBJECTS = \ + fatx.o \ + vfatxlib.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk _____
Added: trunk/reactos/lib/fslib/vfatxlib/fatx.c --- trunk/reactos/lib/fslib/vfatxlib/fatx.c 2005-01-25 21:16:19 UTC (rev 13285) +++ trunk/reactos/lib/fslib/vfatxlib/fatx.c 2005-01-25 22:10:39 UTC (rev 13286) @@ -0,0 +1,431 @@
+/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS VFATX filesystem library + * FILE: fatx.c + * PURPOSE: Fatx support + * PROGRAMMERS: Hartmut Birr + * REVISIONS: + */ +#define NDEBUG +#include <debug.h> +#define NTOS_MODE_USER +#include <ntos.h> +#include <ddk/ntddscsi.h> +#include <mem.h> +#include "vfatxlib.h" + + +static ULONG +GetShiftCount(ULONG Value) +{ + ULONG i = 1; + while (Value > 0) + { + i++; + Value /= 2; + } + return i - 2; +} + + +static ULONG +CalcVolumeSerialNumber(VOID) +{ + LARGE_INTEGER SystemTime; + TIME_FIELDS TimeFields; + ULONG Serial; + PUCHAR Buffer; + + NtQuerySystemTime (&SystemTime); + RtlTimeToTimeFields (&SystemTime, &TimeFields); + + Buffer = (PUCHAR)&Serial; + Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF); + Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF); + Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF); + Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF); + + return Serial; +} + + +static NTSTATUS +FatxWriteBootSector (IN HANDLE FileHandle, + IN PFATX_BOOT_SECTOR BootSector, + IN OUT PFORMAT_CONTEXT Context) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + PUCHAR NewBootSector; + LARGE_INTEGER FileOffset; + + /* Allocate buffer for new bootsector */ + NewBootSector = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(FATX_BOOT_SECTOR)); + if (NewBootSector == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + /* Zero the new bootsector */ + memset(NewBootSector, 0, sizeof(FATX_BOOT_SECTOR)); + + /* Copy FAT16 BPB to new bootsector */ + memcpy(NewBootSector, BootSector, 18); /* FAT16 BPB length (up to (not including) Res2) */ + + /* Write sector 0 */ + FileOffset.QuadPart = 0ULL; + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + sizeof(FATX_BOOT_SECTOR), + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector); + return Status; + } + + UpdateProgress (Context, 1); + + /* Free the new boot sector */ + RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector); + + return Status; +} + + +static NTSTATUS +Fatx16WriteFAT (IN HANDLE FileHandle, + IN ULONG SectorOffset, + IN ULONG FATSectors, + IN OUT PFORMAT_CONTEXT Context) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + PUCHAR Buffer; + LARGE_INTEGER FileOffset; + ULONG i; + 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 * 512) + sizeof(FATX_BOOT_SECTOR); + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + 512, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + return(Status); + } + + UpdateProgress (Context, 1); + + /* Zero the begin of the buffer */ + memset(Buffer, 0, 4); + + /* Zero the rest of the FAT */ + Sectors = 32 * 1024 / 512; + for (i = 1; i < FATSectors; i += Sectors) + { + /* Zero some sectors of the FAT */ + FileOffset.QuadPart = (SectorOffset + i) * 512 + sizeof(FATX_BOOT_SECTOR) ; + if ((FATSectors - i) <= Sectors) + { + Sectors = FATSectors - i; + } + + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + Sectors * 512, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + return(Status); + } + + UpdateProgress (Context, Sectors); + } + + /* Free the buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + + return(Status); +} + +static NTSTATUS +Fatx32WriteFAT (IN HANDLE FileHandle, + IN ULONG SectorOffset, + IN ULONG FATSectors, + IN OUT PFORMAT_CONTEXT Context) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + PUCHAR Buffer; + LARGE_INTEGER FileOffset; + ULONG i; + ULONG Sectors; + + /* Allocate buffer */ + Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + 0, + 64 * 1024); + if (Buffer == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + /* Zero the buffer */ + memset(Buffer, 0, 64 * 1024); + + /* FAT cluster 0 */ + Buffer[0] = 0xf8; /* Media type */ + Buffer[1] = 0xff; + Buffer[2] = 0xff; + Buffer[3] = 0x0f; + /* FAT cluster 1 */ + Buffer[4] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */ + Buffer[5] = 0xff; + Buffer[6] = 0xff; + Buffer[7] = 0x0f; + + /* Write first sector of the FAT */ + FileOffset.QuadPart = (SectorOffset * 512) + sizeof(FATX_BOOT_SECTOR); + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + 512, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + return(Status); + } + + UpdateProgress (Context, 1); + + /* Zero the begin of the buffer */ + memset(Buffer, 0, 8); + + /* Zero the rest of the FAT */ + Sectors = 64 * 1024 / 512; + for (i = 1; i < FATSectors; i += Sectors) + { + /* Zero some sectors of the FAT */ + FileOffset.QuadPart = (SectorOffset + i) * 512 + sizeof(FATX_BOOT_SECTOR); + + if ((FATSectors - i) <= Sectors) + { + Sectors = FATSectors - i; + } + + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + Sectors * 512, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + return(Status); + } + + UpdateProgress (Context, Sectors); + } + + /* Free the buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + + return(Status); +} + +static NTSTATUS +FatxWriteRootDirectory (IN HANDLE FileHandle, + IN ULONG FATSectors, + IN OUT PFORMAT_CONTEXT Context) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status = STATUS_SUCCESS; + PUCHAR Buffer; + LARGE_INTEGER FileOffset; + ULONG FirstRootDirSector; + ULONG RootDirSectors; + + /* Write cluster */ + RootDirSectors = 256 * 64 / 512; + FirstRootDirSector = sizeof(FATX_BOOT_SECTOR) / 512 + FATSectors; + + DPRINT("RootDirSectors = %lu\n", RootDirSectors); + DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector); + + /* Allocate buffer for the cluster */ + Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + 0, + RootDirSectors * 512); + if (Buffer == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + /* Zero the buffer */ + memset(Buffer, 0xff, RootDirSectors * 512); + + /* Zero some sectors of the root directory */ + FileOffset.QuadPart = FirstRootDirSector * 512; + + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + RootDirSectors * 512, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + } + + /* Free the buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + + return(Status); +} + + +NTSTATUS +FatxFormat (HANDLE FileHandle, + PPARTITION_INFORMATION PartitionInfo, + PDISK_GEOMETRY DiskGeometry, + BOOLEAN QuickFormat, + PFORMAT_CONTEXT Context) +{ + FATX_BOOT_SECTOR BootSector; + ULONGLONG SectorCount; + ULONG ClusterCount; + ULONG RootDirSectors; + ULONG FATSectors; + + NTSTATUS Status; + + SectorCount = PartitionInfo->PartitionLength.QuadPart >> GetShiftCount(512); /* Use shifting to avoid 64-bit division */ + + memset(&BootSector, 0, sizeof(FATX_BOOT_SECTOR)); + memcpy(&BootSector.SysType[0], "FATX", 4); + BootSector.SectorsPerCluster = 32; + BootSector.FATCount = 1; + BootSector.VolumeID = CalcVolumeSerialNumber(); + RootDirSectors = 256 * 64 / 512; + + /* Calculate number of FAT sectors */ + ClusterCount = SectorCount >> GetShiftCount(32); + + if (ClusterCount > 65525) + { + FATSectors = (((ClusterCount * 4) + 4095) & ~4095) >> GetShiftCount(512); + } + else + { + FATSectors = (((ClusterCount * 2) + 4095) & ~4095) >> GetShiftCount(512); + } + DPRINT("FATSectors = %hu\n", FATSectors); + + /* Init context data */ + if (QuickFormat) + { + Context->TotalSectorCount = + 1 + FATSectors + RootDirSectors; + } + else + { + Context->TotalSectorCount = SectorCount; + } + + Status = FatxWriteBootSector (FileHandle, + &BootSector, + Context); + if (!NT_SUCCESS(Status)) + { + DPRINT("FatxWriteBootSector() failed with status 0x%.08x\n", Status); + return Status; + } + + /* Write first FAT copy */ + if (ClusterCount > 65525) + { + Status = Fatx32WriteFAT (FileHandle, + 0, + FATSectors, + Context); + } + else + { + Status = Fatx16WriteFAT (FileHandle, + 0, + FATSectors, + Context); + } + if (!NT_SUCCESS(Status)) + { + DPRINT("FatxWriteFAT() failed with status 0x%.08x\n", Status); + return Status; + } + + Status = FatxWriteRootDirectory (FileHandle, + FATSectors, + Context); + if (!NT_SUCCESS(Status)) + { + DPRINT("FatxWriteRootDirectory() failed with status 0x%.08x\n", Status); + } + + if (!QuickFormat) + { + /* FIXME: Fill remaining sectors */ + } + + return Status; +} _____
Added: trunk/reactos/lib/fslib/vfatxlib/vfatxlib.c --- trunk/reactos/lib/fslib/vfatxlib/vfatxlib.c 2005-01-25 21:16:19 UTC (rev 13285) +++ trunk/reactos/lib/fslib/vfatxlib/vfatxlib.c 2005-01-25 22:10:39 UTC (rev 13286) @@ -0,0 +1,198 @@
+/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS VFATx filesystem library + * FILE: vfatxlib.c + * PURPOSE: Main API + * PROGRAMMERS: Hartmut Birr + * REVISIONS: + * CSH 05/04-2003 Created + */ +#define NTOS_MODE_USER +#include <ntos.h> +#include <ddk/ntddscsi.h> +#include <fslib/vfatxlib.h> +#include "vfatxlib.h" + +#define NDEBUG +#include <debug.h> + + +NTSTATUS +VfatxInitialize(VOID) +{ + DPRINT("VfatxInitialize()\n"); + + return STATUS_SUCCESS; +} + + +NTSTATUS +VfatxFormat (PUNICODE_STRING DriveRoot, + ULONG MediaFlag, + BOOLEAN QuickFormat, + PFMIFSCALLBACK Callback) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + DISK_GEOMETRY DiskGeometry; + IO_STATUS_BLOCK Iosb; + HANDLE FileHandle; + PARTITION_INFORMATION PartitionInfo; + FORMAT_CONTEXT Context; + NTSTATUS Status; + + DPRINT("VfatxFormat(DriveRoot '%wZ')\n", DriveRoot); + + Context.TotalSectorCount = 0; + Context.CurrentSectorCount = 0; + Context.Callback = Callback; + Context.Success = FALSE; + Context.Percent = 0; + + InitializeObjectAttributes(&ObjectAttributes, + DriveRoot, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + FILE_WRITE_ACCESS | FILE_WRITE_ATTRIBUTES, + &ObjectAttributes, + &Iosb, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_ALERT); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtOpenFile() failed with status 0x%.08x\n", Status); + return Status; + } + + Status = NtDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + sizeof(DISK_GEOMETRY)); + if (!NT_SUCCESS(Status)) + { + DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY failed with status 0x%.08x\n", Status); + NtClose(FileHandle); + return Status; + } + + if (DiskGeometry.MediaType == FixedMedia) + { + DPRINT("Cylinders %I64d\n", DiskGeometry.Cylinders.QuadPart); + DPRINT("TracksPerCylinder %ld\n", DiskGeometry.TracksPerCylinder); + DPRINT("SectorsPerTrack %ld\n", DiskGeometry.SectorsPerTrack); + DPRINT("BytesPerSector %ld\n", DiskGeometry.BytesPerSector); + DPRINT("DiskSize %I64d\n", + DiskGeometry.Cylinders.QuadPart * + (ULONGLONG)DiskGeometry.TracksPerCylinder * + (ULONGLONG)DiskGeometry.SectorsPerTrack * + (ULONGLONG)DiskGeometry.BytesPerSector); + + Status = NtDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_GET_PARTITION_INFO, + NULL, + 0, + &PartitionInfo, + sizeof(PARTITION_INFORMATION)); + if (!NT_SUCCESS(Status)) + { + DPRINT("IOCTL_DISK_GET_PARTITION_INFO failed with status 0x%.08x\n", Status); + NtClose(FileHandle); + return Status; + } + + /* + * FIXME: This is a hack! + * Partitioning software MUST set the correct number of hidden sectors! + */ + PartitionInfo.HiddenSectors = DiskGeometry.SectorsPerTrack; + } + else + { + PartitionInfo.PartitionType = 0; + PartitionInfo.StartingOffset.QuadPart = 0ULL; + PartitionInfo.PartitionLength.QuadPart = + DiskGeometry.Cylinders.QuadPart * + (ULONGLONG)DiskGeometry.TracksPerCylinder * + (ULONGLONG)DiskGeometry.SectorsPerTrack * + (ULONGLONG)DiskGeometry.BytesPerSector; + PartitionInfo.HiddenSectors = 0; + PartitionInfo.PartitionNumber = 0; + PartitionInfo.BootIndicator = FALSE; + PartitionInfo.RewritePartition = FALSE; + PartitionInfo.RecognizedPartition = FALSE; + } + + DPRINT("PartitionType 0x%x\n", PartitionInfo.PartitionType); + DPRINT("StartingOffset %I64d\n", PartitionInfo.StartingOffset.QuadPart); + DPRINT("PartitionLength %I64d\n", PartitionInfo.PartitionLength.QuadPart); + DPRINT("HiddenSectors %lu\n", PartitionInfo.HiddenSectors); + DPRINT("PartitionNumber %d\n", PartitionInfo.PartitionNumber); + DPRINT("BootIndicator 0x%x\n", PartitionInfo.BootIndicator); + DPRINT("RewritePartition %d\n", PartitionInfo.RewritePartition); + DPRINT("RecognizedPartition %d\n", PartitionInfo.RecognizedPartition); + + if (Callback != NULL) + { + Context.Percent = 0; + Callback (PROGRESS, 0, (PVOID)&Context.Percent); + } + + Status = FatxFormat (FileHandle, + &PartitionInfo, + &DiskGeometry, + QuickFormat, + &Context); + NtClose(FileHandle); + + if (Callback != NULL) + { + Context.Success = (BOOLEAN)(NT_SUCCESS(Status)); + Callback (DONE, 0, (PVOID)&Context.Success); + } + + DPRINT("VfatFormat() done. Status 0x%.08x\n", Status); + + return Status; +} + + +NTSTATUS +VfatxCleanup(VOID) +{ + DPRINT("VfatxCleanup()\n"); + + return STATUS_SUCCESS; +} + + +VOID +VfatxUpdateProgress (PFORMAT_CONTEXT Context, + ULONG Increment) +{ + ULONG NewPercent; + + Context->CurrentSectorCount += (ULONGLONG)Increment; + + + NewPercent = (Context->CurrentSectorCount * 100ULL) / Context->TotalSectorCount; + + if (NewPercent > Context->Percent) + { + Context->Percent = NewPercent; + Context->Callback (PROGRESS, 0, &Context->Percent); + } +} + +/* EOF */ _____
Added: trunk/reactos/lib/fslib/vfatxlib/vfatxlib.h --- trunk/reactos/lib/fslib/vfatxlib/vfatxlib.h 2005-01-25 21:16:19 UTC (rev 13285) +++ trunk/reactos/lib/fslib/vfatxlib/vfatxlib.h 2005-01-25 22:10:39 UTC (rev 13286) @@ -0,0 +1,45 @@
+/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS VFAT filesystem library + * FILE: vfatxlib.h + */ +#define NDEBUG +#include <debug.h> +#define NTOS_MODE_USER +#include <ntos.h> +#include <fslib/vfatlib.h> + +typedef struct _FATX_BOOT_SECTOR +{ + unsigned char SysType[4]; // 0 + unsigned long VolumeID; // 4 + unsigned long SectorsPerCluster; // 8 + unsigned short FATCount; // 12 + unsigned long Unknown; // 14 + unsigned char Unused[4078]; // 18 +} __attribute__((packed)) FATX_BOOT_SECTOR, *PFATX_BOOT_SECTOR; + + +typedef struct _FORMAT_CONTEXT +{ + PFMIFSCALLBACK Callback; + ULONG TotalSectorCount; + ULONG CurrentSectorCount; + BOOLEAN Success; + ULONG Percent; +} FORMAT_CONTEXT, *PFORMAT_CONTEXT; + + + +NTSTATUS +FatxFormat (HANDLE FileHandle, + PPARTITION_INFORMATION PartitionInfo, + PDISK_GEOMETRY DiskGeometry, + BOOLEAN QuickFormat, + PFORMAT_CONTEXT Context); + +VOID +UpdateProgress (PFORMAT_CONTEXT Context, + ULONG Increment); + +/* EOF */