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

fat16.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:        fat16.c
00005  * PURPOSE:     Fat16 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 Fat16WriteBootSector(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     UpdateProgress(Context, 1);
00099 
00100     /* Free the new boot sector */
00101     RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
00102 
00103     return Status;
00104 }
00105 
00106 
00107 static NTSTATUS
00108 Fat16WriteFAT(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 Sectors;
00119 
00120     /* Allocate buffer */
00121     Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
00122                                      0,
00123                                      32 * 1024);
00124     if (Buffer == NULL)
00125       return STATUS_INSUFFICIENT_RESOURCES;
00126 
00127     /* Zero the buffer */
00128     memset(Buffer, 0, 32 * 1024);
00129 
00130     /* FAT cluster 0 */
00131     Buffer[0] = 0xf8; /* Media type */
00132     Buffer[1] = 0xff;
00133 
00134     /* FAT cluster 1 */
00135     Buffer[2] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
00136     Buffer[3] = 0xff;
00137 
00138     /* Write first sector of the FAT */
00139     FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors) * BootSector->BytesPerSector;
00140     Status = NtWriteFile(FileHandle,
00141                          NULL,
00142                          NULL,
00143                          NULL,
00144                          &IoStatusBlock,
00145                          Buffer,
00146                          BootSector->BytesPerSector,
00147                          &FileOffset,
00148                          NULL);
00149     if (!NT_SUCCESS(Status))
00150     {
00151         DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00152         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00153         return Status;
00154     }
00155 
00156     UpdateProgress(Context, 1);
00157 
00158     /* Zero the begin of the buffer */
00159     memset(Buffer, 0, 4);
00160 
00161     /* Zero the rest of the FAT */
00162     Sectors = 32 * 1024 / BootSector->BytesPerSector;
00163     for (i = 1; i < (ULONG)BootSector->FATSectors; i += Sectors)
00164     {
00165         /* Zero some sectors of the FAT */
00166         FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors + i) * BootSector->BytesPerSector;
00167 
00168         if (((ULONG)BootSector->FATSectors - i) <= Sectors)
00169         {
00170             Sectors = (ULONG)BootSector->FATSectors - i;
00171         }
00172 
00173         Status = NtWriteFile(FileHandle,
00174                              NULL,
00175                              NULL,
00176                              NULL,
00177                              &IoStatusBlock,
00178                              Buffer,
00179                              Sectors * BootSector->BytesPerSector,
00180                              &FileOffset,
00181                              NULL);
00182         if (!NT_SUCCESS(Status))
00183         {
00184             DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00185             RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00186             return Status;
00187         }
00188 
00189         UpdateProgress(Context, Sectors);
00190     }
00191 
00192     /* Free the buffer */
00193     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00194 
00195     return Status;
00196 }
00197 
00198 
00199 static NTSTATUS
00200 Fat16WriteRootDirectory(IN HANDLE FileHandle,
00201                         IN PFAT16_BOOT_SECTOR BootSector,
00202                         IN OUT PFORMAT_CONTEXT Context)
00203 {
00204     IO_STATUS_BLOCK IoStatusBlock;
00205     NTSTATUS Status = STATUS_SUCCESS;
00206     PUCHAR Buffer;
00207     LARGE_INTEGER FileOffset;
00208     ULONG FirstRootDirSector;
00209     ULONG RootDirSectors;
00210     ULONG Sectors;
00211     ULONG i;
00212 
00213     DPRINT("BootSector->ReservedSectors = %hu\n", BootSector->ReservedSectors);
00214     DPRINT("BootSector->FATSectors = %hu\n", BootSector->FATSectors);
00215     DPRINT("BootSector->SectorsPerCluster = %u\n", BootSector->SectorsPerCluster);
00216 
00217     /* Write cluster */
00218     RootDirSectors = ((BootSector->RootEntries * 32) +
00219         (BootSector->BytesPerSector - 1)) / BootSector->BytesPerSector;
00220     FirstRootDirSector =
00221         BootSector->ReservedSectors + (BootSector->FATCount * BootSector->FATSectors);
00222 
00223     DPRINT("RootDirSectors = %lu\n", RootDirSectors);
00224     DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector);
00225 
00226     /* Allocate buffer for the cluster */
00227     Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
00228                                      0,
00229                                      32 * 1024);
00230     if (Buffer == NULL)
00231         return STATUS_INSUFFICIENT_RESOURCES;
00232 
00233     /* Zero the buffer */
00234     memset(Buffer, 0, 32 * 1024);
00235 
00236     Sectors = 32 * 1024 / BootSector->BytesPerSector;
00237     for (i = 0; i < RootDirSectors; i += Sectors)
00238     {
00239         /* Zero some sectors of the root directory */
00240         FileOffset.QuadPart = (FirstRootDirSector + i) * BootSector->BytesPerSector;
00241 
00242         if ((RootDirSectors - i) <= Sectors)
00243         {
00244             Sectors = RootDirSectors - i;
00245         }
00246 
00247         Status = NtWriteFile(FileHandle,
00248                              NULL,
00249                              NULL,
00250                              NULL,
00251                              &IoStatusBlock,
00252                              Buffer,
00253                              Sectors * BootSector->BytesPerSector,
00254                              &FileOffset,
00255                              NULL);
00256         if (!NT_SUCCESS(Status))
00257         {
00258             DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00259             RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00260             return Status;
00261         }
00262 
00263         UpdateProgress(Context, Sectors);
00264     }
00265 
00266     /* Free the buffer */
00267     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00268 
00269     return Status;
00270 }
00271 
00272 
00273 NTSTATUS
00274 Fat16Format(IN HANDLE FileHandle,
00275             IN PPARTITION_INFORMATION PartitionInfo,
00276             IN PDISK_GEOMETRY DiskGeometry,
00277             IN PUNICODE_STRING Label,
00278             IN BOOLEAN QuickFormat,
00279             IN ULONG ClusterSize,
00280             IN OUT PFORMAT_CONTEXT Context)
00281 {
00282     FAT16_BOOT_SECTOR BootSector;
00283     OEM_STRING VolumeLabel;
00284     ULONG SectorCount;
00285     ULONG RootDirSectors;
00286     ULONG TmpVal1;
00287     ULONG TmpVal2;
00288     ULONG TmpVal3;
00289     NTSTATUS Status;
00290 
00291     /* Calculate cluster size */
00292     if (ClusterSize == 0)
00293     {
00294         if (PartitionInfo->PartitionLength.QuadPart < 16LL * 1024LL * 1024LL)
00295         {
00296             /* Partition < 16MB ==> 1KB Cluster */
00297             ClusterSize = 1024;
00298         }
00299         else if (PartitionInfo->PartitionLength.QuadPart < 128LL * 1024LL * 1024LL)
00300         {
00301             /* Partition < 128MB ==> 2KB Cluster */
00302             ClusterSize = 2048;
00303         }
00304         else if (PartitionInfo->PartitionLength.QuadPart < 256LL * 1024LL * 1024LL)
00305         {
00306             /* Partition < 256MB ==> 4KB Cluster */
00307             ClusterSize = 4096;
00308         }
00309         else
00310         {
00311             /* Partition >= 256MB (< 512MB) ==> 8KB Cluster */
00312             ClusterSize = 8192;
00313         }
00314     }
00315 
00316     SectorCount = PartitionInfo->PartitionLength.QuadPart >>
00317         GetShiftCount(DiskGeometry->BytesPerSector); /* Use shifting to avoid 64-bit division */
00318 
00319     memset(&BootSector, 0, sizeof(FAT16_BOOT_SECTOR));
00320     memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
00321     BootSector.BytesPerSector = DiskGeometry->BytesPerSector;
00322     BootSector.SectorsPerCluster = ClusterSize / BootSector.BytesPerSector;
00323     BootSector.ReservedSectors = 1;
00324     BootSector.FATCount = 2;
00325     BootSector.RootEntries = 512;
00326     BootSector.Sectors = (SectorCount < 0x10000) ? (unsigned short)SectorCount : 0;
00327     BootSector.Media = 0xf8;
00328     BootSector.FATSectors = 0;  /* Set later. See below. */
00329     BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack;
00330     BootSector.Heads = DiskGeometry->TracksPerCylinder;
00331     BootSector.HiddenSectors = PartitionInfo->HiddenSectors;
00332     BootSector.SectorsHuge = (SectorCount >= 0x10000) ? (unsigned long)SectorCount : 0;
00333     BootSector.Drive = DiskGeometry->MediaType == FixedMedia ? 0x80 : 0x00;
00334     BootSector.ExtBootSignature = 0x29;
00335     BootSector.VolumeID = CalcVolumeSerialNumber();
00336     if ((Label == NULL) || (Label->Buffer == NULL))
00337     {
00338         memcpy(&BootSector.VolumeLabel[0], "NO NAME    ", 11);
00339     }
00340     else
00341     {
00342         RtlUnicodeStringToOemString(&VolumeLabel, Label, TRUE);
00343         memset(&BootSector.VolumeLabel[0], ' ', 11);
00344         memcpy(&BootSector.VolumeLabel[0], VolumeLabel.Buffer,
00345                VolumeLabel.Length < 11 ? VolumeLabel.Length : 11);
00346         RtlFreeOemString(&VolumeLabel);
00347     }
00348 
00349     memcpy(&BootSector.SysType[0], "FAT16   ", 8);
00350 
00351     DPRINT("BootSector.SectorsHuge = %lx\n", BootSector.SectorsHuge);
00352 
00353     RootDirSectors = ((BootSector.RootEntries * 32) +
00354         (BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector;
00355 
00356     /* Calculate number of FAT sectors */
00357     /* (BootSector.BytesPerSector / 2) FAT entries (16bit) fit into one sector */
00358     TmpVal1 = SectorCount - (BootSector.ReservedSectors + RootDirSectors);
00359     TmpVal2 = ((BootSector.BytesPerSector / 2) * BootSector.SectorsPerCluster) + BootSector.FATCount;
00360     TmpVal3 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
00361     BootSector.FATSectors = (unsigned short)(TmpVal3 & 0xffff);
00362     DPRINT("BootSector.FATSectors = %hu\n", BootSector.FATSectors);
00363 
00364     /* Init context data */
00365     Context->TotalSectorCount =
00366         1 + (BootSector.FATSectors * 2) + RootDirSectors;
00367 
00368     Status = Fat16WriteBootSector(FileHandle,
00369                                   &BootSector,
00370                                   Context);
00371     if (!NT_SUCCESS(Status))
00372     {
00373         DPRINT("Fat16WriteBootSector() failed with status 0x%.08x\n", Status);
00374         return Status;
00375     }
00376 
00377     /* Write first FAT copy */
00378     Status = Fat16WriteFAT(FileHandle,
00379                            0,
00380                            &BootSector,
00381                            Context);
00382     if (!NT_SUCCESS(Status))
00383     {
00384         DPRINT("Fat16WriteFAT() failed with status 0x%.08x\n", Status);
00385         return Status;
00386     }
00387 
00388     /* Write second FAT copy */
00389     Status = Fat16WriteFAT(FileHandle,
00390                            (ULONG)BootSector.FATSectors,
00391                            &BootSector,
00392                            Context);
00393     if (!NT_SUCCESS(Status))
00394     {
00395        DPRINT("Fat16WriteFAT() failed with status 0x%.08x.\n", Status);
00396         return Status;
00397     }
00398 
00399     Status = Fat16WriteRootDirectory(FileHandle,
00400                                      &BootSector,
00401                                      Context);
00402     if (!NT_SUCCESS(Status))
00403     {
00404         DPRINT("Fat16WriteRootDirectory() failed with status 0x%.08x\n", Status);
00405     }
00406 
00407     if (!QuickFormat)
00408     {
00409         /* FIXME: Fill remaining sectors */
00410     }
00411 
00412     return Status;
00413 }

Generated on Sat May 26 2012 04:35:04 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.