ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fat12.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS VFAT filesystem library
00004  * FILE:        fat12.c
00005  * PURPOSE:     Fat12 support
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  *              Eric Kohl
00008  * REVISIONS:
00009  *   EK 05/04-2003 Created
00010  */
00011 #include "vfatlib.h"
00012 
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 static ULONG
00017 GetShiftCount(IN ULONG Value)
00018 {
00019     ULONG i = 1;
00020 
00021     while (Value > 0)
00022     {
00023         i++;
00024         Value /= 2;
00025     }
00026 
00027     return i - 2;
00028 }
00029 
00030 
00031 static ULONG
00032 CalcVolumeSerialNumber(VOID)
00033 {
00034     LARGE_INTEGER SystemTime;
00035     TIME_FIELDS TimeFields;
00036     ULONG Serial;
00037     PUCHAR Buffer;
00038 
00039     NtQuerySystemTime(&SystemTime);
00040     RtlTimeToTimeFields(&SystemTime, &TimeFields);
00041 
00042     Buffer = (PUCHAR)&Serial;
00043     Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
00044     Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
00045     Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
00046     Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
00047 
00048     return Serial;
00049 }
00050 
00051 
00052 static NTSTATUS
00053 Fat12WriteBootSector(IN HANDLE FileHandle,
00054                      IN PFAT16_BOOT_SECTOR BootSector,
00055                      IN OUT PFORMAT_CONTEXT Context)
00056 {
00057     IO_STATUS_BLOCK IoStatusBlock;
00058     NTSTATUS Status;
00059     PFAT16_BOOT_SECTOR NewBootSector;
00060     LARGE_INTEGER FileOffset;
00061 
00062     /* Allocate buffer for new bootsector */
00063     NewBootSector = (PFAT16_BOOT_SECTOR)RtlAllocateHeap(RtlGetProcessHeap (),
00064                                             0,
00065                                             BootSector->BytesPerSector);
00066     if (NewBootSector == NULL)
00067         return STATUS_INSUFFICIENT_RESOURCES;
00068 
00069     /* Zero the new bootsector */
00070     memset(NewBootSector, 0, BootSector->BytesPerSector);
00071 
00072     /* Copy FAT16 BPB to new bootsector */
00073     memcpy(&NewBootSector->OEMName[0],
00074            &BootSector->OEMName[0],
00075            59); /* FAT16 BPB length (up to (not including) Res2) */
00076 
00077     /* Write the boot sector signature */
00078     NewBootSector->Signature1 = 0xAA550000;
00079 
00080     /* Write sector 0 */
00081     FileOffset.QuadPart = 0ULL;
00082     Status = NtWriteFile(FileHandle,
00083                          NULL,
00084                          NULL,
00085                          NULL,
00086                          &IoStatusBlock,
00087                          NewBootSector,
00088                          BootSector->BytesPerSector,
00089                          &FileOffset,
00090                          NULL);
00091     if (!NT_SUCCESS(Status))
00092     {
00093         DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00094         RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
00095         return Status;
00096     }
00097 
00098     /* Free the new boot sector */
00099     RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
00100 
00101     UpdateProgress(Context, 1);
00102 
00103     return Status;
00104 }
00105 
00106 
00107 static NTSTATUS
00108 Fat12WriteFAT(IN HANDLE FileHandle,
00109               IN ULONG SectorOffset,
00110               IN PFAT16_BOOT_SECTOR BootSector,
00111               IN OUT PFORMAT_CONTEXT Context)
00112 {
00113     IO_STATUS_BLOCK IoStatusBlock;
00114     NTSTATUS Status;
00115     PUCHAR Buffer;
00116     LARGE_INTEGER FileOffset;
00117     ULONG i;
00118     ULONG Size;
00119     ULONG Sectors;
00120 
00121     /* Allocate buffer */
00122     Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
00123                                      0,
00124                                      32 * 1024);
00125     if (Buffer == NULL)
00126         return STATUS_INSUFFICIENT_RESOURCES;
00127 
00128     /* Zero the buffer */
00129     memset(Buffer, 0, 32 * 1024);
00130 
00131     /* FAT cluster 0 & 1*/
00132     Buffer[0] = 0xf8; /* Media type */
00133     Buffer[1] = 0xff;
00134     Buffer[2] = 0xff;
00135 
00136     /* Write first sector of the FAT */
00137     FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors) * BootSector->BytesPerSector;
00138     Status = NtWriteFile(FileHandle,
00139                          NULL,
00140                          NULL,
00141                          NULL,
00142                          &IoStatusBlock,
00143                          Buffer,
00144                          BootSector->BytesPerSector,
00145                          &FileOffset,
00146                          NULL);
00147     if (!NT_SUCCESS(Status))
00148     {
00149         DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00150         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00151         return Status;
00152     }
00153 
00154     UpdateProgress(Context, 1);
00155 
00156     /* Zero the begin of the buffer */
00157     memset(Buffer, 0, 3);
00158 
00159     /* Zero the rest of the FAT */
00160     Sectors = 32 * 1024 / BootSector->BytesPerSector;
00161     for (i = 1; i < (ULONG)BootSector->FATSectors; i += Sectors)
00162     {
00163         /* Zero some sectors of the FAT */
00164         FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors + i) * BootSector->BytesPerSector;
00165         if (((ULONG)BootSector->FATSectors - i) <= Sectors)
00166         {
00167             Sectors = (ULONG)BootSector->FATSectors - i;
00168         }
00169 
00170         Size = Sectors * BootSector->BytesPerSector;
00171         Status = NtWriteFile(FileHandle,
00172                              NULL,
00173                              NULL,
00174                              NULL,
00175                              &IoStatusBlock,
00176                              Buffer,
00177                              Size,
00178                              &FileOffset,
00179                              NULL);
00180         if (!NT_SUCCESS(Status))
00181         {
00182             DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00183             RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00184             return Status;
00185         }
00186 
00187         UpdateProgress(Context, Sectors);
00188     }
00189 
00190     /* Free the buffer */
00191     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00192 
00193     return Status;
00194 }
00195 
00196 
00197 static NTSTATUS
00198 Fat12WriteRootDirectory(IN HANDLE FileHandle,
00199                         IN PFAT16_BOOT_SECTOR BootSector,
00200                         IN OUT PFORMAT_CONTEXT Context)
00201 {
00202     IO_STATUS_BLOCK IoStatusBlock;
00203     NTSTATUS Status = STATUS_SUCCESS;
00204     PUCHAR Buffer;
00205     LARGE_INTEGER FileOffset;
00206     ULONG FirstRootDirSector;
00207     ULONG RootDirSectors;
00208     ULONG Sectors;
00209     ULONG Size;
00210     ULONG i;
00211 
00212     DPRINT("BootSector->ReservedSectors = %hu\n", BootSector->ReservedSectors);
00213     DPRINT("BootSector->FATSectors = %hu\n", BootSector->FATSectors);
00214     DPRINT("BootSector->SectorsPerCluster = %u\n", BootSector->SectorsPerCluster);
00215 
00216     /* Write cluster */
00217     RootDirSectors = ((BootSector->RootEntries * 32) +
00218         (BootSector->BytesPerSector - 1)) / BootSector->BytesPerSector;
00219     FirstRootDirSector =
00220         BootSector->ReservedSectors + (BootSector->FATCount * BootSector->FATSectors);
00221 
00222     DPRINT("RootDirSectors = %lu\n", RootDirSectors);
00223     DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector);
00224 
00225     /* Allocate buffer for the cluster */
00226     Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
00227                                      0,
00228                                      32 * 1024);
00229     if (Buffer == NULL)
00230         return STATUS_INSUFFICIENT_RESOURCES;
00231 
00232     /* Zero the buffer */
00233     memset(Buffer, 0, 32 * 1024);
00234 
00235     Sectors = 32 * 1024 / BootSector->BytesPerSector;
00236     for (i = 0; i < RootDirSectors; i += Sectors)
00237     {
00238         /* Zero some sectors of the root directory */
00239         FileOffset.QuadPart = (FirstRootDirSector + i) * BootSector->BytesPerSector;
00240 
00241         if ((RootDirSectors - i) <= Sectors)
00242         {
00243             Sectors = RootDirSectors - i;
00244         }
00245 
00246         Size = Sectors * BootSector->BytesPerSector;
00247 
00248         Status = NtWriteFile(FileHandle,
00249                              NULL,
00250                              NULL,
00251                              NULL,
00252                              &IoStatusBlock,
00253                              Buffer,
00254                              Size,
00255                              &FileOffset,
00256                              NULL);
00257         if (!NT_SUCCESS(Status))
00258         {
00259             DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00260             RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00261             return Status;
00262         }
00263 
00264         UpdateProgress(Context, Sectors);
00265     }
00266 
00267     /* Free the buffer */
00268     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00269 
00270     return Status;
00271 }
00272 
00273 
00274 NTSTATUS
00275 Fat12Format(IN HANDLE FileHandle,
00276             IN PPARTITION_INFORMATION PartitionInfo,
00277             IN PDISK_GEOMETRY DiskGeometry,
00278             IN PUNICODE_STRING Label,
00279             IN BOOLEAN QuickFormat,
00280             IN ULONG ClusterSize,
00281             IN OUT PFORMAT_CONTEXT Context)
00282 {
00283     FAT16_BOOT_SECTOR BootSector;
00284     OEM_STRING VolumeLabel;
00285     ULONG SectorCount;
00286     ULONG RootDirSectors;
00287     ULONG TmpVal1;
00288     ULONG TmpVal2;
00289     ULONG TmpVal3;
00290     NTSTATUS Status;
00291 
00292     /* Calculate cluster size */
00293     if (ClusterSize == 0)
00294     {
00295         if (DiskGeometry->MediaType == FixedMedia)
00296         {
00297             /* 4KB Cluster (Harddisk only) */
00298             ClusterSize = 4096;
00299         }
00300         else
00301         {
00302             /* 512 byte cluster (floppy) */
00303             ClusterSize = 512;
00304         }
00305     }
00306 
00307     SectorCount = PartitionInfo->PartitionLength.QuadPart >>
00308         GetShiftCount(DiskGeometry->BytesPerSector); /* Use shifting to avoid 64-bit division */
00309 
00310     DPRINT("SectorCount = %lu\n", SectorCount);
00311 
00312     memset(&BootSector, 0, sizeof(FAT16_BOOT_SECTOR));
00313     memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
00314     BootSector.BytesPerSector = DiskGeometry->BytesPerSector;
00315     BootSector.SectorsPerCluster = ClusterSize / BootSector.BytesPerSector;
00316     BootSector.ReservedSectors = 1;
00317     BootSector.FATCount = 2;
00318     BootSector.RootEntries = 512;
00319     BootSector.Sectors = (SectorCount < 0x10000) ? (unsigned short)SectorCount : 0;
00320     BootSector.Media = 0xf8;
00321     BootSector.FATSectors = 0;  /* Set later. See below. */
00322     BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack;
00323     BootSector.Heads = DiskGeometry->TracksPerCylinder;
00324     BootSector.HiddenSectors = PartitionInfo->HiddenSectors;
00325     BootSector.SectorsHuge = (SectorCount >= 0x10000) ? (unsigned long)SectorCount : 0;
00326     BootSector.Drive = DiskGeometry->MediaType == FixedMedia ? 0x80 : 0x00;
00327     BootSector.ExtBootSignature = 0x29;
00328     BootSector.VolumeID = CalcVolumeSerialNumber();
00329     if ((Label == NULL) || (Label->Buffer == NULL))
00330     {
00331         memcpy(&BootSector.VolumeLabel[0], "NO NAME    ", 11);
00332     }
00333     else
00334     {
00335         RtlUnicodeStringToOemString(&VolumeLabel, Label, TRUE);
00336         memset(&BootSector.VolumeLabel[0], ' ', 11);
00337         memcpy(&BootSector.VolumeLabel[0], VolumeLabel.Buffer,
00338                VolumeLabel.Length < 11 ? VolumeLabel.Length : 11);
00339         RtlFreeOemString(&VolumeLabel);
00340     }
00341 
00342     memcpy(&BootSector.SysType[0], "FAT12   ", 8);
00343 
00344     RootDirSectors = ((BootSector.RootEntries * 32) +
00345         (BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector;
00346 
00347     /* Calculate number of FAT sectors */
00348     /* ((BootSector.BytesPerSector * 2) / 3) FAT entries (12bit) fit into one sector */
00349     TmpVal1 = SectorCount - (BootSector.ReservedSectors + RootDirSectors);
00350     TmpVal2 = (((BootSector.BytesPerSector * 2) / 3) * BootSector.SectorsPerCluster) + BootSector.FATCount;
00351     TmpVal3 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
00352     BootSector.FATSectors = (unsigned short)(TmpVal3 & 0xffff);
00353 
00354     DPRINT("BootSector.FATSectors = %hx\n", BootSector.FATSectors);
00355 
00356     /* Init context data */
00357     Context->TotalSectorCount =
00358         1 + (BootSector.FATSectors * 2) + RootDirSectors;
00359 
00360     Status = Fat12WriteBootSector(FileHandle,
00361                                   &BootSector,
00362                                   Context);
00363     if (!NT_SUCCESS(Status))
00364     {
00365         DPRINT("Fat12WriteBootSector() failed with status 0x%.08x\n", Status);
00366         return Status;
00367     }
00368 
00369     /* Write first FAT copy */
00370     Status = Fat12WriteFAT(FileHandle,
00371                            0,
00372                            &BootSector,
00373                            Context);
00374     if (!NT_SUCCESS(Status))
00375     {
00376         DPRINT("Fat12WriteFAT() failed with status 0x%.08x\n", Status);
00377         return Status;
00378     }
00379 
00380     /* Write second FAT copy */
00381     Status = Fat12WriteFAT(FileHandle,
00382                            (ULONG)BootSector.FATSectors,
00383                            &BootSector,
00384                            Context);
00385     if (!NT_SUCCESS(Status))
00386     {
00387         DPRINT("Fat12WriteFAT() failed with status 0x%.08x.\n", Status);
00388         return Status;
00389     }
00390 
00391     Status = Fat12WriteRootDirectory(FileHandle,
00392                                      &BootSector,
00393                                      Context);
00394     if (!NT_SUCCESS(Status))
00395     {
00396         DPRINT("Fat12WriteRootDirectory() failed with status 0x%.08x\n", Status);
00397     }
00398 
00399     if (!QuickFormat)
00400     {
00401         /* FIXME: Fill remaining sectors */
00402     }
00403 
00404     return Status;
00405 }

Generated on Sun May 27 2012 04:36:14 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.