ReactOS Fundraising Campaign 2012
 
€ 4,060 / € 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

fat32.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:        fat32.c
00005  * PURPOSE:     Fat32 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 Fat32WriteBootSector(IN HANDLE FileHandle,
00054                      IN PFAT32_BOOT_SECTOR BootSector,
00055                      IN OUT PFORMAT_CONTEXT Context)
00056 {
00057     IO_STATUS_BLOCK IoStatusBlock;
00058     NTSTATUS Status;
00059     PFAT32_BOOT_SECTOR NewBootSector;
00060     LARGE_INTEGER FileOffset;
00061 
00062     /* Allocate buffer for new bootsector */
00063     NewBootSector = (PFAT32_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 FAT32 BPB to new bootsector */
00073     memcpy(&NewBootSector->OEMName[0],
00074            &BootSector->OEMName[0],
00075            87); /* FAT32 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     /* Write backup boot sector */
00101     if (BootSector->BootBackup != 0x0000)
00102     {
00103         FileOffset.QuadPart = (ULONGLONG)((ULONG)BootSector->BootBackup * BootSector->BytesPerSector);
00104         Status = NtWriteFile(FileHandle,
00105                              NULL,
00106                              NULL,
00107                              NULL,
00108                              &IoStatusBlock,
00109                              NewBootSector,
00110                              BootSector->BytesPerSector,
00111                              &FileOffset,
00112                              NULL);
00113         if (!NT_SUCCESS(Status))
00114         {
00115             DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00116             RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
00117             return Status;
00118         }
00119 
00120         UpdateProgress(Context, 1);
00121     }
00122 
00123     /* Free the new boot sector */
00124     RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
00125 
00126     return Status;
00127 }
00128 
00129 
00130 static NTSTATUS
00131 Fat32WriteFsInfo(IN HANDLE FileHandle,
00132                  IN PFAT32_BOOT_SECTOR BootSector,
00133                  IN OUT PFORMAT_CONTEXT Context)
00134 {
00135     IO_STATUS_BLOCK IoStatusBlock;
00136     NTSTATUS Status;
00137     PFAT32_FSINFO FsInfo;
00138     LARGE_INTEGER FileOffset;
00139 
00140     /* Allocate buffer for new sector */
00141     FsInfo = (PFAT32_FSINFO)RtlAllocateHeap(RtlGetProcessHeap(),
00142                                             0,
00143                                             BootSector->BytesPerSector);
00144     if (FsInfo == NULL)
00145         return STATUS_INSUFFICIENT_RESOURCES;
00146 
00147     /* Zero the new sector */
00148     memset(FsInfo, 0, BootSector->BytesPerSector);
00149 
00150     FsInfo->LeadSig = 0x41615252;
00151     FsInfo->StrucSig = 0x61417272;
00152     FsInfo->FreeCount = 0xffffffff;
00153     FsInfo->NextFree = 0xffffffff;
00154     FsInfo->TrailSig = 0xaa550000;
00155 
00156     /* Write sector */
00157     FileOffset.QuadPart = BootSector->FSInfoSector * BootSector->BytesPerSector;
00158     Status = NtWriteFile(FileHandle,
00159                          NULL,
00160                          NULL,
00161                          NULL,
00162                          &IoStatusBlock,
00163                          FsInfo,
00164                          BootSector->BytesPerSector,
00165                          &FileOffset,
00166                          NULL);
00167     if (!NT_SUCCESS(Status))
00168     {
00169         DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00170         RtlFreeHeap(RtlGetProcessHeap(), 0, FsInfo);
00171         return Status;
00172     }
00173 
00174     UpdateProgress(Context, 1);
00175 
00176     /* Free the new sector buffer */
00177     RtlFreeHeap(RtlGetProcessHeap(), 0, FsInfo);
00178 
00179     return Status;
00180 }
00181 
00182 
00183 static NTSTATUS
00184 Fat32WriteFAT(IN HANDLE FileHandle,
00185               IN ULONG SectorOffset,
00186               IN PFAT32_BOOT_SECTOR BootSector,
00187               IN OUT PFORMAT_CONTEXT Context)
00188 {
00189     IO_STATUS_BLOCK IoStatusBlock;
00190     NTSTATUS Status;
00191     PUCHAR Buffer;
00192     LARGE_INTEGER FileOffset;
00193     ULONG i;
00194     ULONG Sectors;
00195 
00196     /* Allocate buffer */
00197     Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
00198                                      0,
00199                                      64 * 1024);
00200     if (Buffer == NULL)
00201         return STATUS_INSUFFICIENT_RESOURCES;
00202 
00203     /* Zero the buffer */
00204     memset(Buffer, 0, 64 * 1024);
00205 
00206     /* FAT cluster 0 */
00207     Buffer[0] = 0xf8; /* Media type */
00208     Buffer[1] = 0xff;
00209     Buffer[2] = 0xff;
00210     Buffer[3] = 0x0f;
00211 
00212     /* FAT cluster 1 */
00213     Buffer[4] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
00214     Buffer[5] = 0xff;
00215     Buffer[6] = 0xff;
00216     Buffer[7] = 0x0f;
00217 
00218     /* FAT cluster 2 */
00219     Buffer[8] = 0xff; /* End of root directory */
00220     Buffer[9] = 0xff;
00221     Buffer[10] = 0xff;
00222     Buffer[11] = 0x0f;
00223 
00224     /* Write first sector of the FAT */
00225     FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors) * BootSector->BytesPerSector;
00226     Status = NtWriteFile(FileHandle,
00227                          NULL,
00228                          NULL,
00229                          NULL,
00230                          &IoStatusBlock,
00231                          Buffer,
00232                          BootSector->BytesPerSector,
00233                          &FileOffset,
00234                          NULL);
00235     if (!NT_SUCCESS(Status))
00236     {
00237         DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00238         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00239         return Status;
00240     }
00241 
00242     UpdateProgress(Context, 1);
00243 
00244     /* Zero the begin of the buffer */
00245     memset(Buffer, 0, 12);
00246 
00247     /* Zero the rest of the FAT */
00248     Sectors = 64 * 1024 / BootSector->BytesPerSector;
00249     for (i = 1; i < BootSector->FATSectors32; i += Sectors)
00250     {
00251         /* Zero some sectors of the FAT */
00252         FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors + i) * BootSector->BytesPerSector;
00253 
00254         if ((BootSector->FATSectors32 - i) <= Sectors)
00255         {
00256             Sectors = BootSector->FATSectors32 - i;
00257         }
00258 
00259         Status = NtWriteFile(FileHandle,
00260                              NULL,
00261                              NULL,
00262                              NULL,
00263                              &IoStatusBlock,
00264                              Buffer,
00265                              Sectors * BootSector->BytesPerSector,
00266                              &FileOffset,
00267                              NULL);
00268         if (!NT_SUCCESS(Status))
00269         {
00270             DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00271             RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00272             return Status;
00273         }
00274 
00275         UpdateProgress(Context, Sectors);
00276     }
00277 
00278     /* Free the buffer */
00279     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00280 
00281     return Status;
00282 }
00283 
00284 
00285 static NTSTATUS
00286 Fat32WriteRootDirectory(IN HANDLE FileHandle,
00287                         IN PFAT32_BOOT_SECTOR BootSector,
00288                         IN OUT PFORMAT_CONTEXT Context)
00289 {
00290     IO_STATUS_BLOCK IoStatusBlock;
00291     NTSTATUS Status;
00292     PUCHAR Buffer;
00293     LARGE_INTEGER FileOffset;
00294     ULONGLONG FirstDataSector;
00295     ULONGLONG FirstRootDirSector;
00296 
00297     /* Allocate buffer for the cluster */
00298     Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
00299                                      0,
00300                                      BootSector->SectorsPerCluster * BootSector->BytesPerSector);
00301     if (Buffer == NULL)
00302         return STATUS_INSUFFICIENT_RESOURCES;
00303 
00304     /* Zero the buffer */
00305     memset(Buffer, 0, BootSector->SectorsPerCluster * BootSector->BytesPerSector);
00306 
00307     DPRINT("BootSector->ReservedSectors = %lu\n", BootSector->ReservedSectors);
00308     DPRINT("BootSector->FATSectors32 = %lu\n", BootSector->FATSectors32);
00309     DPRINT("BootSector->RootCluster = %lu\n", BootSector->RootCluster);
00310     DPRINT("BootSector->SectorsPerCluster = %lu\n", BootSector->SectorsPerCluster);
00311 
00312     /* Write cluster */
00313     FirstDataSector = BootSector->ReservedSectors +
00314         (BootSector->FATCount * BootSector->FATSectors32) + 0 /* RootDirSectors */;
00315 
00316     DPRINT("FirstDataSector = %lu\n", FirstDataSector);
00317 
00318     FirstRootDirSector = ((BootSector->RootCluster - 2) * BootSector->SectorsPerCluster) + FirstDataSector;
00319     FileOffset.QuadPart = FirstRootDirSector * BootSector->BytesPerSector;
00320 
00321     DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector);
00322     DPRINT("FileOffset = %lu\n", FileOffset.QuadPart);
00323 
00324     Status = NtWriteFile(FileHandle,
00325                          NULL,
00326                          NULL,
00327                          NULL,
00328                          &IoStatusBlock,
00329                          Buffer,
00330                          BootSector->SectorsPerCluster * BootSector->BytesPerSector,
00331                          &FileOffset,
00332                          NULL);
00333     if (!NT_SUCCESS(Status))
00334     {
00335         DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00336         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00337         return Status;
00338     }
00339 
00340     UpdateProgress(Context, (ULONG)BootSector->SectorsPerCluster);
00341 
00342     /* Free the buffer */
00343     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00344 
00345     return Status;
00346 }
00347 
00348 
00349 NTSTATUS
00350 Fat32Format(IN HANDLE FileHandle,
00351             IN PPARTITION_INFORMATION PartitionInfo,
00352             IN PDISK_GEOMETRY DiskGeometry,
00353             IN PUNICODE_STRING Label,
00354             IN BOOLEAN QuickFormat,
00355             IN ULONG ClusterSize,
00356             IN OUT PFORMAT_CONTEXT Context)
00357 {
00358     FAT32_BOOT_SECTOR BootSector;
00359     OEM_STRING VolumeLabel;
00360     ULONG TmpVal1;
00361     ULONG TmpVal2;
00362     NTSTATUS Status;
00363 
00364     /* Calculate cluster size */
00365     if (ClusterSize == 0)
00366     {
00367         if (PartitionInfo->PartitionLength.QuadPart < 8LL * 1024LL * 1024LL * 1024LL)
00368         {
00369             /* Partition < 8GB ==> 4KB Cluster */
00370             ClusterSize = 4096;
00371         }
00372         else if (PartitionInfo->PartitionLength.QuadPart < 16LL * 1024LL * 1024LL * 1024LL)
00373         {
00374             /* Partition 8GB - 16GB ==> 8KB Cluster */
00375             ClusterSize = 8192;
00376         }
00377         else if (PartitionInfo->PartitionLength.QuadPart < 32LL * 1024LL * 1024LL * 1024LL)
00378         {
00379             /* Partition 16GB - 32GB ==> 16KB Cluster */
00380             ClusterSize = 16384;
00381         }
00382         else
00383         {
00384             /* Partition >= 32GB ==> 32KB Cluster */
00385             ClusterSize = 32768;
00386         }
00387     }
00388 
00389     memset(&BootSector, 0, sizeof(FAT32_BOOT_SECTOR));
00390     memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
00391     BootSector.BytesPerSector = DiskGeometry->BytesPerSector;
00392     BootSector.SectorsPerCluster = ClusterSize / BootSector.BytesPerSector;
00393     BootSector.ReservedSectors = 32;
00394     BootSector.FATCount = 2;
00395     BootSector.RootEntries = 0;
00396     BootSector.Sectors = 0;
00397     BootSector.Media = 0xf8;
00398     BootSector.FATSectors = 0;
00399     BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack;
00400     BootSector.Heads = DiskGeometry->TracksPerCylinder;
00401     BootSector.HiddenSectors = PartitionInfo->HiddenSectors;
00402     BootSector.SectorsHuge = PartitionInfo->PartitionLength.QuadPart >>
00403         GetShiftCount(BootSector.BytesPerSector); /* Use shifting to avoid 64-bit division */
00404     BootSector.FATSectors32 = 0; /* Set later */
00405     BootSector.ExtFlag = 0; /* Mirror all FATs */
00406     BootSector.FSVersion = 0x0000; /* 0:0 */
00407     BootSector.RootCluster = 2;
00408     BootSector.FSInfoSector = 1;
00409     BootSector.BootBackup = 6;
00410     BootSector.Drive = DiskGeometry->MediaType == FixedMedia ? 0x80 : 0x00;
00411     BootSector.ExtBootSignature = 0x29;
00412     BootSector.VolumeID = CalcVolumeSerialNumber ();
00413     if ((Label == NULL) || (Label->Buffer == NULL))
00414     {
00415         memcpy(&BootSector.VolumeLabel[0], "NO NAME    ", 11);
00416     }
00417     else
00418     {
00419         RtlUnicodeStringToOemString(&VolumeLabel, Label, TRUE);
00420         memset(&BootSector.VolumeLabel[0], ' ', 11);
00421         memcpy(&BootSector.VolumeLabel[0], VolumeLabel.Buffer,
00422                VolumeLabel.Length < 11 ? VolumeLabel.Length : 11);
00423         RtlFreeOemString(&VolumeLabel);
00424     }
00425 
00426     memcpy(&BootSector.SysType[0], "FAT32   ", 8);
00427 
00428     /* Calculate number of FAT sectors */
00429     /* (BytesPerSector / 4) FAT entries (32bit) fit into one sector */
00430     TmpVal1 = BootSector.SectorsHuge - BootSector.ReservedSectors;
00431     TmpVal2 = ((BootSector.BytesPerSector / 4) * BootSector.SectorsPerCluster) + BootSector.FATCount;
00432     BootSector.FATSectors32 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
00433     DPRINT("FATSectors32 = %lu\n", BootSector.FATSectors32);
00434 
00435     /* Init context data */
00436     Context->TotalSectorCount =
00437         2 + (BootSector.FATSectors32 * BootSector.FATCount) + BootSector.SectorsPerCluster;
00438 
00439     Status = Fat32WriteBootSector(FileHandle,
00440                                   &BootSector,
00441                                   Context);
00442     if (!NT_SUCCESS(Status))
00443     {
00444         DPRINT("Fat32WriteBootSector() failed with status 0x%.08x\n", Status);
00445         return Status;
00446     }
00447 
00448     Status = Fat32WriteFsInfo(FileHandle,
00449                               &BootSector,
00450                               Context);
00451     if (!NT_SUCCESS(Status))
00452     {
00453         DPRINT("Fat32WriteFsInfo() failed with status 0x%.08x\n", Status);
00454         return Status;
00455     }
00456 
00457     /* Write first FAT copy */
00458     Status = Fat32WriteFAT(FileHandle,
00459                            0,
00460                            &BootSector,
00461                            Context);
00462     if (!NT_SUCCESS(Status))
00463     {
00464       DPRINT("Fat32WriteFAT() failed with status 0x%.08x\n", Status);
00465       return Status;
00466     }
00467 
00468     /* Write second FAT copy */
00469     Status = Fat32WriteFAT(FileHandle,
00470                            BootSector.FATSectors32,
00471                            &BootSector,
00472                            Context);
00473     if (!NT_SUCCESS(Status))
00474     {
00475         DPRINT("Fat32WriteFAT() failed with status 0x%.08x.\n", Status);
00476         return Status;
00477     }
00478 
00479     Status = Fat32WriteRootDirectory(FileHandle,
00480                                      &BootSector,
00481                                      Context);
00482     if (!NT_SUCCESS(Status))
00483     {
00484         DPRINT("Fat32WriteRootDirectory() failed with status 0x%.08x\n", Status);
00485     }
00486 
00487     if (!QuickFormat)
00488     {
00489         /* FIXME: Fill remaining sectors */
00490     }
00491 
00492     return Status;
00493 }
00494 
00495 /* EOF */

Generated on Tue May 22 2012 04:40:27 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.