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

fatx.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS VFATX filesystem library
00004  * FILE:        fatx.c
00005  * PURPOSE:     Fatx support
00006  * PROGRAMMERS: 
00007  * REVISIONS:
00008  */
00009 #include "vfatxlib.h"
00010 
00011 #define NDEBUG
00012 #include <debug.h>
00013 
00014 static ULONG
00015 GetShiftCount(IN ULONG Value)
00016 {
00017     ULONG i = 1;
00018 
00019     while (Value > 0)
00020     {
00021         i++;
00022         Value /= 2;
00023     }
00024 
00025     return i - 2;
00026 }
00027 
00028 
00029 static ULONG
00030 CalcVolumeSerialNumber(VOID)
00031 {
00032     LARGE_INTEGER SystemTime;
00033     TIME_FIELDS TimeFields;
00034     ULONG Serial;
00035     PUCHAR Buffer;
00036 
00037     NtQuerySystemTime (&SystemTime);
00038     RtlTimeToTimeFields (&SystemTime, &TimeFields);
00039 
00040     Buffer = (PUCHAR)&Serial;
00041     Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
00042     Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
00043     Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
00044     Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
00045 
00046     return Serial;
00047 }
00048 
00049 
00050 static NTSTATUS
00051 FatxWriteBootSector(IN HANDLE FileHandle,
00052                     IN PFATX_BOOT_SECTOR BootSector,
00053                     IN OUT PFORMAT_CONTEXT Context)
00054 {
00055     IO_STATUS_BLOCK IoStatusBlock;
00056     NTSTATUS Status;
00057     PUCHAR NewBootSector;
00058     LARGE_INTEGER FileOffset;
00059 
00060     /* Allocate buffer for new bootsector */
00061     NewBootSector = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
00062                                             0,
00063                                             sizeof(FATX_BOOT_SECTOR));
00064     if (NewBootSector == NULL)
00065         return STATUS_INSUFFICIENT_RESOURCES;
00066 
00067     /* Zero the new bootsector */
00068     memset(NewBootSector, 0, sizeof(FATX_BOOT_SECTOR));
00069 
00070     /* Copy FAT16 BPB to new bootsector */
00071     memcpy(NewBootSector, BootSector, 18); /* FAT16 BPB length (up to (not including) Res2) */
00072 
00073     /* Write sector 0 */
00074     FileOffset.QuadPart = 0ULL;
00075     Status = NtWriteFile(FileHandle,
00076                          NULL,
00077                          NULL,
00078                          NULL,
00079                          &IoStatusBlock,
00080                          NewBootSector,
00081                          sizeof(FATX_BOOT_SECTOR),
00082                          &FileOffset,
00083                          NULL);
00084     if (!NT_SUCCESS(Status))
00085     {
00086         DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00087         RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
00088         return Status;
00089     }
00090 
00091     VfatxUpdateProgress(Context, 1);
00092 
00093     /* Free the new boot sector */
00094     RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
00095 
00096     return Status;
00097 }
00098 
00099 
00100 static NTSTATUS
00101 Fatx16WriteFAT(IN HANDLE FileHandle,
00102                IN ULONG SectorOffset,
00103                IN ULONG FATSectors,
00104                IN OUT PFORMAT_CONTEXT Context)
00105 {
00106     IO_STATUS_BLOCK IoStatusBlock;
00107     NTSTATUS Status;
00108     PUCHAR Buffer;
00109     LARGE_INTEGER FileOffset;
00110     ULONG i;
00111     ULONG Sectors;
00112 
00113     /* Allocate buffer */
00114     Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
00115                                      0,
00116                                      32 * 1024);
00117     if (Buffer == NULL)
00118         return STATUS_INSUFFICIENT_RESOURCES;
00119 
00120     /* Zero the buffer */
00121     memset(Buffer, 0, 32 * 1024);
00122 
00123     /* FAT cluster 0 */
00124     Buffer[0] = 0xf8; /* Media type */
00125     Buffer[1] = 0xff;
00126 
00127     /* FAT cluster 1 */
00128     Buffer[2] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
00129     Buffer[3] = 0xff;
00130 
00131     /* Write first sector of the FAT */
00132     FileOffset.QuadPart = (SectorOffset * 512) + sizeof(FATX_BOOT_SECTOR);
00133     Status = NtWriteFile(FileHandle,
00134                          NULL,
00135                          NULL,
00136                          NULL,
00137                          &IoStatusBlock,
00138                          Buffer,
00139                          512,
00140                          &FileOffset,
00141                          NULL);
00142     if (!NT_SUCCESS(Status))
00143     {
00144         DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00145         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00146         return Status;
00147     }
00148 
00149     VfatxUpdateProgress(Context, 1);
00150 
00151     /* Zero the begin of the buffer */
00152     memset(Buffer, 0, 4);
00153 
00154     /* Zero the rest of the FAT */
00155     Sectors = 32 * 1024 / 512;
00156     for (i = 1; i < FATSectors; i += Sectors)
00157     {
00158         /* Zero some sectors of the FAT */
00159         FileOffset.QuadPart = (SectorOffset + i) * 512 + sizeof(FATX_BOOT_SECTOR) ;
00160         if ((FATSectors - i) <= Sectors)
00161         {
00162             Sectors = FATSectors - i;
00163         }
00164 
00165         Status = NtWriteFile(FileHandle,
00166                              NULL,
00167                              NULL,
00168                              NULL,
00169                              &IoStatusBlock,
00170                              Buffer,
00171                              Sectors * 512,
00172                              &FileOffset,
00173                              NULL);
00174         if (!NT_SUCCESS(Status))
00175         {
00176             DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00177             RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00178             return Status;
00179         }
00180 
00181         VfatxUpdateProgress(Context, Sectors);
00182     }
00183 
00184     /* Free the buffer */
00185     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00186 
00187     return Status;
00188 }
00189 
00190 static NTSTATUS
00191 Fatx32WriteFAT(IN HANDLE FileHandle,
00192                IN ULONG SectorOffset,
00193                IN ULONG FATSectors,
00194                IN OUT PFORMAT_CONTEXT Context)
00195 {
00196     IO_STATUS_BLOCK IoStatusBlock;
00197     NTSTATUS Status;
00198     PUCHAR Buffer;
00199     LARGE_INTEGER FileOffset;
00200     ULONG i;
00201     ULONG Sectors;
00202 
00203     /* Allocate buffer */
00204     Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
00205                                      0,
00206                                      64 * 1024);
00207     if (Buffer == NULL)
00208         return STATUS_INSUFFICIENT_RESOURCES;
00209 
00210     /* Zero the buffer */
00211     memset(Buffer, 0, 64 * 1024);
00212 
00213     /* FAT cluster 0 */
00214     Buffer[0] = 0xf8; /* Media type */
00215     Buffer[1] = 0xff;
00216     Buffer[2] = 0xff;
00217     Buffer[3] = 0x0f;
00218 
00219     /* FAT cluster 1 */
00220     Buffer[4] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
00221     Buffer[5] = 0xff;
00222     Buffer[6] = 0xff;
00223     Buffer[7] = 0x0f;
00224 
00225     /* Write first sector of the FAT */
00226     FileOffset.QuadPart = (SectorOffset * 512) + sizeof(FATX_BOOT_SECTOR);
00227     Status = NtWriteFile(FileHandle,
00228                          NULL,
00229                          NULL,
00230                          NULL,
00231                          &IoStatusBlock,
00232                          Buffer,
00233                          512,
00234                          &FileOffset,
00235                          NULL);
00236     if (!NT_SUCCESS(Status))
00237     {
00238         DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00239         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00240         return Status;
00241     }
00242 
00243     VfatxUpdateProgress(Context, 1);
00244 
00245     /* Zero the begin of the buffer */
00246     memset(Buffer, 0, 8);
00247 
00248     /* Zero the rest of the FAT */
00249     Sectors = 64 * 1024 / 512;
00250     for (i = 1; i < FATSectors; i += Sectors)
00251     {
00252         /* Zero some sectors of the FAT */
00253         FileOffset.QuadPart = (SectorOffset + i) * 512 + sizeof(FATX_BOOT_SECTOR);
00254 
00255         if ((FATSectors - i) <= Sectors)
00256         {
00257             Sectors = FATSectors - i;
00258         }
00259 
00260         Status = NtWriteFile(FileHandle,
00261                              NULL,
00262                              NULL,
00263                              NULL,
00264                              &IoStatusBlock,
00265                              Buffer,
00266                              Sectors * 512,
00267                              &FileOffset,
00268                              NULL);
00269         if (!NT_SUCCESS(Status))
00270         {
00271             DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00272             RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00273             return Status;
00274         }
00275 
00276         VfatxUpdateProgress(Context, Sectors);
00277     }
00278 
00279     /* Free the buffer */
00280     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00281 
00282     return Status;
00283 }
00284 
00285 static NTSTATUS
00286 FatxWriteRootDirectory(IN HANDLE FileHandle,
00287                        IN ULONG FATSectors,
00288                        IN OUT PFORMAT_CONTEXT Context)
00289 {
00290     IO_STATUS_BLOCK IoStatusBlock;
00291     NTSTATUS Status = STATUS_SUCCESS;
00292     PUCHAR Buffer;
00293     LARGE_INTEGER FileOffset;
00294     ULONG FirstRootDirSector;
00295     ULONG RootDirSectors;
00296 
00297     /* Write cluster */
00298     RootDirSectors = 256 * 64 / 512;
00299     FirstRootDirSector = sizeof(FATX_BOOT_SECTOR) / 512 + FATSectors;
00300 
00301     DPRINT("RootDirSectors = %lu\n", RootDirSectors);
00302     DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector);
00303 
00304     /* Allocate buffer for the cluster */
00305     Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
00306                                      0,
00307                                      RootDirSectors * 512);
00308     if (Buffer == NULL)
00309         return STATUS_INSUFFICIENT_RESOURCES;
00310 
00311     /* Zero the buffer */
00312     memset(Buffer, 0xff, RootDirSectors * 512);
00313 
00314     /* Zero some sectors of the root directory */
00315     FileOffset.QuadPart = FirstRootDirSector * 512;
00316 
00317     Status = NtWriteFile(FileHandle,
00318                          NULL,
00319                          NULL,
00320                          NULL,
00321                          &IoStatusBlock,
00322                          Buffer,
00323                          RootDirSectors * 512,
00324                          &FileOffset,
00325                          NULL);
00326     if (!NT_SUCCESS(Status))
00327     {
00328         DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
00329     }
00330 
00331     /* Free the buffer */
00332     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00333 
00334     return Status;
00335 }
00336 
00337 
00338 NTSTATUS
00339 FatxFormat(IN HANDLE FileHandle,
00340            IN PPARTITION_INFORMATION PartitionInfo,
00341            IN PDISK_GEOMETRY DiskGeometry,
00342            IN BOOLEAN QuickFormat,
00343            IN OUT PFORMAT_CONTEXT Context)
00344 {
00345     FATX_BOOT_SECTOR BootSector;
00346     ULONGLONG SectorCount;
00347     ULONG ClusterCount;
00348     ULONG RootDirSectors;
00349     ULONG FATSectors;
00350     NTSTATUS Status;
00351 
00352     SectorCount = PartitionInfo->PartitionLength.QuadPart >> GetShiftCount(512); /* Use shifting to avoid 64-bit division */
00353 
00354     memset(&BootSector, 0, sizeof(FATX_BOOT_SECTOR));
00355     memcpy(&BootSector.SysType[0], "FATX", 4);
00356     BootSector.SectorsPerCluster = 32;
00357     BootSector.FATCount = 1;
00358     BootSector.VolumeID = CalcVolumeSerialNumber();
00359     RootDirSectors = 256 * 64 / 512;
00360 
00361     /* Calculate number of FAT sectors */
00362     ClusterCount = SectorCount >> GetShiftCount(32);
00363 
00364     if (ClusterCount > 65525)
00365     {
00366         FATSectors = (((ClusterCount * 4) + 4095) & ~4095) >> GetShiftCount(512);
00367     }
00368     else
00369     {
00370         FATSectors = (((ClusterCount * 2) + 4095) & ~4095) >> GetShiftCount(512);
00371     }
00372     DPRINT("FATSectors = %hu\n", FATSectors);
00373 
00374     /* Init context data */
00375     if (QuickFormat)
00376     {
00377         Context->TotalSectorCount =
00378             1 + FATSectors + RootDirSectors;
00379     }
00380     else
00381     {
00382         Context->TotalSectorCount = SectorCount;
00383     }
00384 
00385     Status = FatxWriteBootSector(FileHandle,
00386                                  &BootSector,
00387                                  Context);
00388     if (!NT_SUCCESS(Status))
00389     {
00390         DPRINT("FatxWriteBootSector() failed with status 0x%.08x\n", Status);
00391         return Status;
00392     }
00393 
00394     /* Write first FAT copy */
00395     if (ClusterCount > 65525)
00396     {
00397         Status = Fatx32WriteFAT(FileHandle,
00398                                 0,
00399                                 FATSectors,
00400                                 Context);
00401     }
00402     else
00403     {
00404         Status = Fatx16WriteFAT(FileHandle,
00405                                 0,
00406                                 FATSectors,
00407                                 Context);
00408     }
00409 
00410     if (!NT_SUCCESS(Status))
00411     {
00412         DPRINT("FatxWriteFAT() failed with status 0x%.08x\n", Status);
00413         return Status;
00414     }
00415 
00416     Status = FatxWriteRootDirectory(FileHandle,
00417                                     FATSectors,
00418                                     Context);
00419     if (!NT_SUCCESS(Status))
00420     {
00421         DPRINT("FatxWriteRootDirectory() failed with status 0x%.08x\n", Status);
00422     }
00423 
00424     if (!QuickFormat)
00425     {
00426         /* FIXME: Fill remaining sectors */
00427     }
00428 
00429     return Status;
00430 }

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