Added FAT12 support.
authorEric Kohl <eric.kohl@reactos.org>
Sun, 24 Aug 2003 16:15:31 +0000 (16:15 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 24 Aug 2003 16:15:31 +0000 (16:15 +0000)
Create random volume serial numbers.

svn path=/trunk/; revision=5829

reactos/lib/fslib/vfatlib/Makefile
reactos/lib/fslib/vfatlib/fat12.c [new file with mode: 0644]
reactos/lib/fslib/vfatlib/fat16.c
reactos/lib/fslib/vfatlib/fat32.c
reactos/lib/fslib/vfatlib/vfatlib.c
reactos/lib/fslib/vfatlib/vfatlib.h

index 36f0c19..22384c0 100755 (executable)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.4 2003/08/22 13:53:02 ekohl Exp $
+# $Id: Makefile,v 1.5 2003/08/24 16:15:31 ekohl Exp $
 
 PATH_TO_TOP = ../../..
 
@@ -10,6 +10,7 @@ TARGET_NAME = vfatlib
 TARGET_CFLAGS += -D_DISABLE_TIDENTS
 
 TARGET_OBJECTS = \
+ fat12.o \
  fat16.o \
  fat32.o \
  vfatlib.o
diff --git a/reactos/lib/fslib/vfatlib/fat12.c b/reactos/lib/fslib/vfatlib/fat12.c
new file mode 100644 (file)
index 0000000..679e614
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS VFAT filesystem library
+ * FILE:        fat12.c
+ * PURPOSE:     Fat12 support
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *              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 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
+Fat12WriteBootSector(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
+Fat12WriteFAT(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 & 1*/
+  Buffer[0] = 0xf8; /* Media type */
+  Buffer[1] = 0xff;
+  Buffer[2] = 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, 3);
+
+  /* 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
+Fat12WriteRootDirectory(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
+Fat12Format (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 SectorCount;
+  ULONG RootDirSectors;
+  ULONG TmpVal1;
+  ULONG TmpVal2;
+  ULONG TmpVal3;
+  NTSTATUS Status;
+
+  /* Calculate cluster size */
+  if (ClusterSize == 0)
+    {
+      /* 4KB Cluster (Harddisk only) */
+      ClusterSize = 4096;
+    }
+
+  SectorCount = PartitionInfo->PartitionLength.QuadPart >>
+    GetShiftCount(DiskGeometry->BytesPerSector); /* Use shifting to avoid 64-bit division */
+
+//  SectorCount =
+//    PartitionInfo->PartitionLength.u.LowPart / DiskGeometry->BytesPerSector;
+
+  DPRINT1("SectorCount = %lu\n", SectorCount);
+
+  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 = (SectorCount < 0x10000) ? (unsigned short)SectorCount : 0;
+  BootSector.Media = 0xf8;
+  BootSector.FATSectors = 0;  /* Set later. See below. */
+  BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack;
+  BootSector.Heads = DiskGeometry->TracksPerCylinder;
+  BootSector.HiddenSectors = DiskGeometry->SectorsPerTrack; //PartitionInfo->HiddenSectors; /* FIXME: Hack! */
+  BootSector.SectorsHuge = (SectorCount >= 0x10000) ? (unsigned long)SectorCount : 0;
+  BootSector.Drive = 0xff; /* No BIOS boot drive available */
+  BootSector.ExtBootSignature = 0x29;
+  BootSector.VolumeID = CalcVolumeSerialNumber();
+  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], "FAT12   ", 8);
+
+  RootDirSectors = ((BootSector.RootEntries * 32) +
+    (BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector;
+
+  /* 341 FAT entries (12bit) fit into one 512 byte sector */
+  TmpVal1 = SectorCount - (BootSector.ReservedSectors + RootDirSectors);
+  TmpVal2 = (341 * BootSector.SectorsPerCluster) + BootSector.FATCount;
+  TmpVal3 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
+  BootSector.FATSectors = (unsigned short)(TmpVal3 & 0xffff);
+
+  DPRINT1("BootSector.FATSectors = %hx\n", BootSector.FATSectors);
+
+  Status = Fat12WriteBootSector(FileHandle,
+    &BootSector);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("Fat12WriteBootSector() failed with status 0x%.08x\n", Status);
+      return Status;
+    }
+
+  /* Write first FAT copy */
+  Status = Fat12WriteFAT(FileHandle,
+    0,
+    &BootSector);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("Fat12WriteFAT() failed with status 0x%.08x\n", Status);
+      return Status;
+    }
+
+  /* Write second FAT copy */
+  Status = Fat12WriteFAT(FileHandle,
+    (ULONG)BootSector.FATSectors,
+    &BootSector);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("Fat12WriteFAT() failed with status 0x%.08x.\n", Status);
+      return Status;
+    }
+
+  Status = Fat12WriteRootDirectory(FileHandle,
+    &BootSector);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("Fat12WriteRootDirectory() failed with status 0x%.08x\n", Status);
+    }
+
+  return Status;
+}
index bc54d45..3beb4df 100644 (file)
@@ -3,7 +3,8 @@
  * PROJECT:     ReactOS VFAT filesystem library
  * FILE:        fat16.c
  * PURPOSE:     Fat16 support
- * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *              Eric Kohl (ekohl@rz-online.de)
  * REVISIONS:
  *   EK 05/04-2003 Created
  */
@@ -28,6 +29,27 @@ GetShiftCount(ULONG Value)
 }
 
 
+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
 Fat16WriteBootSector(IN HANDLE FileHandle,
   IN PFAT16_BOOT_SECTOR BootSector)
@@ -254,6 +276,7 @@ Fat16Format (HANDLE  FileHandle,
 {
   FAT16_BOOT_SECTOR BootSector;
   ANSI_STRING VolumeLabel;
+  ULONG SectorCount;
   ULONG RootDirSectors;
   ULONG TmpVal1;
   ULONG TmpVal2;
@@ -285,6 +308,9 @@ Fat16Format (HANDLE  FileHandle,
        }
     }
 
+  SectorCount = PartitionInfo->PartitionLength.QuadPart >>
+    GetShiftCount(DiskGeometry->BytesPerSector); /* Use shifting to avoid 64-bit division */
+
   memset(&BootSector, 0, sizeof(FAT16_BOOT_SECTOR));
   memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
   BootSector.BytesPerSector = DiskGeometry->BytesPerSector;
@@ -292,17 +318,16 @@ Fat16Format (HANDLE  FileHandle,
   BootSector.ReservedSectors = 1;
   BootSector.FATCount = 2;
   BootSector.RootEntries = 512;
-  BootSector.Sectors = 0; //(SectorCount < 0x10000) ? SectorCount : 0;
+  BootSector.Sectors = (SectorCount < 0x10000) ? (unsigned short)SectorCount : 0;
   BootSector.Media = 0xf8;
   BootSector.FATSectors = 0;  /* Set later. See below. */
   BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack;
   BootSector.Heads = DiskGeometry->TracksPerCylinder;
   BootSector.HiddenSectors = DiskGeometry->SectorsPerTrack; //PartitionInfo->HiddenSectors; /* FIXME: Hack! */
-  BootSector.SectorsHuge = PartitionInfo->PartitionLength.QuadPart >>
-    GetShiftCount(BootSector.BytesPerSector); /* Use shifting to avoid 64-bit division */
+  BootSector.SectorsHuge = (SectorCount >= 0x10000) ? (unsigned long)SectorCount : 0;
   BootSector.Drive = 0xff; /* No BIOS boot drive available */
   BootSector.ExtBootSignature = 0x29;
-  BootSector.VolumeID = 0x45768798; /* FIXME: */
+  BootSector.VolumeID = CalcVolumeSerialNumber();
   if ((Label == NULL) || (Label->Buffer == NULL))
     {
       memcpy(&BootSector.VolumeLabel[0], "NO NAME    ", 11);
@@ -322,7 +347,8 @@ Fat16Format (HANDLE  FileHandle,
   RootDirSectors = ((BootSector.RootEntries * 32) +
     (BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector;
 
-  TmpVal1 = BootSector.SectorsHuge - (BootSector.ReservedSectors + RootDirSectors);
+  /* 265 FAT entries (16bit) fit into one 512 byte sector */
+  TmpVal1 = SectorCount - (BootSector.ReservedSectors + RootDirSectors);
   TmpVal2 = (256 * BootSector.SectorsPerCluster) + BootSector.FATCount;
   TmpVal3 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
   BootSector.FATSectors = (unsigned short)(TmpVal3 & 0xffff);
index e44e80c..4db82d7 100644 (file)
@@ -1,9 +1,10 @@
 /*
  * 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)
+ * FILE:        fat32.c
+ * PURPOSE:     Fat32 support
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *              Eric Kohl (ekohl@rz-online.de)
  * REVISIONS:
  *   EK 05/04-2003 Created
  */
@@ -28,6 +29,27 @@ GetShiftCount(ULONG Value)
 }
 
 
+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
 Fat32WriteBootSector(IN HANDLE FileHandle,
   IN PFAT32_BOOT_SECTOR BootSector)
@@ -377,7 +399,7 @@ Fat32Format (HANDLE  FileHandle,
   BootSector.BootBackup = 6;
   BootSector.Drive = 0xff; /* No BIOS boot drive available */
   BootSector.ExtBootSignature = 0x29;
-  BootSector.VolumeID = 0x45768798; /* FIXME: */
+  BootSector.VolumeID = CalcVolumeSerialNumber ();
   if ((Label == NULL) || (Label->Buffer == NULL))
     {
       memcpy(&BootSector.VolumeLabel[0], "NO NAME    ", 11);
@@ -416,6 +438,14 @@ Fat32Format (HANDLE  FileHandle,
       BootSector.FATSectors32 = TmpVal2;
     }
 
+#if 0
+  /* experimental */
+  /* 128 FAT entries (32bit) fit into one 512 byte sector */
+  TmpVal1 = BootSector.SectorsHuge - BootSector.ReservedSectors;
+  TmpVal2 = (128 * BootSector.SectorsPerCluster) + BootSector.FATCount;
+  BootSector.FATSectors32 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
+#endif
+
   Status = Fat32WriteBootSector(FileHandle,
     &BootSector);
   if (!NT_SUCCESS(Status))
index a620775..9bd37ab 100755 (executable)
@@ -129,8 +129,7 @@ VfatFormat(
                                ClusterSize,
                                Callback);
        }
-#if 0
-      else if (PartitionInfo.PartitionType == PARTITION_FAT12)
+      else if (PartitionInfo.PartitionType == PARTITION_FAT_12)
        {
          Status = Fat12Format (FileHandle,
                                &PartitionInfo,
@@ -140,7 +139,6 @@ VfatFormat(
                                ClusterSize,
                                Callback);
        }
-#endif
       else
        {
          Status = Fat16Format (FileHandle,
index 15c4faf..02406cf 100755 (executable)
@@ -87,6 +87,15 @@ typedef struct _FAT32_FSINFO
 } __attribute__((packed)) FAT32_FSINFO, *PFAT32_FSINFO;
 
 
+NTSTATUS
+Fat12Format (HANDLE  FileHandle,
+            PPARTITION_INFORMATION  PartitionInfo,
+            PDISK_GEOMETRY DiskGeometry,
+            PUNICODE_STRING Label,
+            BOOL  QuickFormat,
+            DWORD  ClusterSize,
+            PFMIFSCALLBACK  Callback);
+
 NTSTATUS
 Fat16Format (HANDLE  FileHandle,
             PPARTITION_INFORMATION  PartitionInfo,