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

vfatlib.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:        lib\fslib\vfatlib\vfatlib.c
00005  * PURPOSE:     Main API
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  * REVISIONS:
00008  *   CSH 05/04-2003 Created
00009  */
00010 #include "vfatlib.h"
00011 
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 PFMIFSCALLBACK ChkdskCallback = NULL;
00016 PVOID FsCheckMemQueue;
00017 ULONG FsCheckFlags;
00018 ULONG FsCheckTotalFiles;
00019 
00020 NTSTATUS
00021 NTAPI
00022 VfatFormat(IN PUNICODE_STRING DriveRoot,
00023            IN FMIFS_MEDIA_FLAG MediaFlag,
00024            IN PUNICODE_STRING Label,
00025            IN BOOLEAN QuickFormat,
00026            IN ULONG ClusterSize,
00027            IN PFMIFSCALLBACK Callback)
00028 {
00029     OBJECT_ATTRIBUTES ObjectAttributes;
00030     DISK_GEOMETRY DiskGeometry;
00031     IO_STATUS_BLOCK Iosb;
00032     HANDLE FileHandle;
00033     PARTITION_INFORMATION PartitionInfo;
00034     FORMAT_CONTEXT Context;
00035     NTSTATUS Status, LockStatus;
00036 
00037     DPRINT("VfatFormat(DriveRoot '%wZ')\n", DriveRoot);
00038 
00039     Context.TotalSectorCount = 0;
00040     Context.CurrentSectorCount = 0;
00041     Context.Callback = Callback;
00042     Context.Success = FALSE;
00043     Context.Percent = 0;
00044 
00045     InitializeObjectAttributes(&ObjectAttributes,
00046                                DriveRoot,
00047                                0,
00048                                NULL,
00049                                NULL);
00050 
00051     Status = NtOpenFile(&FileHandle,
00052                         FILE_GENERIC_READ | FILE_GENERIC_WRITE,
00053                         &ObjectAttributes,
00054                         &Iosb,
00055                         FILE_SHARE_READ,
00056                         FILE_SYNCHRONOUS_IO_ALERT);
00057     if (!NT_SUCCESS(Status))
00058     {
00059         DPRINT1("NtOpenFile() failed with status 0x%.08x\n", Status);
00060         return Status;
00061     }
00062 
00063     Status = NtDeviceIoControlFile(FileHandle,
00064                                    NULL,
00065                                    NULL,
00066                                    NULL,
00067                                    &Iosb,
00068                                    IOCTL_DISK_GET_DRIVE_GEOMETRY,
00069                                    NULL,
00070                                    0,
00071                                    &DiskGeometry,
00072                                    sizeof(DISK_GEOMETRY));
00073     if (!NT_SUCCESS(Status))
00074     {
00075         DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY failed with status 0x%.08x\n", Status);
00076         NtClose(FileHandle);
00077         return Status;
00078     }
00079 
00080     if (DiskGeometry.MediaType == FixedMedia)
00081     {
00082         DPRINT("Cylinders %I64d\n", DiskGeometry.Cylinders.QuadPart);
00083         DPRINT("TracksPerCylinder %ld\n", DiskGeometry.TracksPerCylinder);
00084         DPRINT("SectorsPerTrack %ld\n", DiskGeometry.SectorsPerTrack);
00085         DPRINT("BytesPerSector %ld\n", DiskGeometry.BytesPerSector);
00086         DPRINT("DiskSize %I64d\n",
00087                DiskGeometry.Cylinders.QuadPart *
00088                (ULONGLONG)DiskGeometry.TracksPerCylinder *
00089                (ULONGLONG)DiskGeometry.SectorsPerTrack *
00090                (ULONGLONG)DiskGeometry.BytesPerSector);
00091 
00092         Status = NtDeviceIoControlFile(FileHandle,
00093                                        NULL,
00094                                        NULL,
00095                                        NULL,
00096                                        &Iosb,
00097                                        IOCTL_DISK_GET_PARTITION_INFO,
00098                                        NULL,
00099                                        0,
00100                                        &PartitionInfo,
00101                                        sizeof(PARTITION_INFORMATION));
00102         if (!NT_SUCCESS(Status))
00103         {
00104             DPRINT("IOCTL_DISK_GET_PARTITION_INFO failed with status 0x%.08x\n", Status);
00105             NtClose(FileHandle);
00106             return Status;
00107         }
00108 
00109         /*
00110          * FIXME: This is a hack!
00111          *        Partitioning software MUST set the correct number of hidden sectors!
00112          */
00113         PartitionInfo.HiddenSectors = DiskGeometry.SectorsPerTrack;
00114     }
00115     else
00116     {
00117         PartitionInfo.PartitionType = 0;
00118         PartitionInfo.StartingOffset.QuadPart = 0ULL;
00119         PartitionInfo.PartitionLength.QuadPart =
00120             DiskGeometry.Cylinders.QuadPart *
00121             (ULONGLONG)DiskGeometry.TracksPerCylinder *
00122             (ULONGLONG)DiskGeometry.SectorsPerTrack *
00123             (ULONGLONG)DiskGeometry.BytesPerSector;
00124         PartitionInfo.HiddenSectors = 0;
00125         PartitionInfo.PartitionNumber = 0;
00126         PartitionInfo.BootIndicator = FALSE;
00127         PartitionInfo.RewritePartition = FALSE;
00128         PartitionInfo.RecognizedPartition = FALSE;
00129     }
00130     
00131     /* If it already has a FAT FS, we'll use that type.
00132      * If it doesn't, we will determine the FAT type based on size and offset */
00133     if (PartitionInfo.PartitionType != PARTITION_FAT_12 &&
00134         PartitionInfo.PartitionType != PARTITION_FAT_16 &&
00135         PartitionInfo.PartitionType != PARTITION_HUGE &&
00136         PartitionInfo.PartitionType != PARTITION_XINT13 &&
00137         PartitionInfo.PartitionType != PARTITION_FAT32 &&
00138         PartitionInfo.PartitionType != PARTITION_FAT32_XINT13)
00139     {
00140         /* Determine the correct type based upon size and offset (copied from usetup) */
00141         if (PartitionInfo.PartitionLength.QuadPart < (4200LL * 1024LL))
00142         {
00143             /* FAT12 CHS partition (disk is smaller than 4.1MB) */
00144             PartitionInfo.PartitionType = PARTITION_FAT_12;
00145         }
00146         else if (PartitionInfo.StartingOffset.QuadPart < (1024LL * 255LL * 63LL * 512LL))
00147         {
00148             /* Partition starts below the 8.4GB boundary ==> CHS partition */
00149             
00150             if (PartitionInfo.PartitionLength.QuadPart < (32LL * 1024LL * 1024LL))
00151             {
00152                 /* FAT16 CHS partition (partiton size < 32MB) */
00153                 PartitionInfo.PartitionType = PARTITION_FAT_16;
00154             }
00155             else if (PartitionInfo.PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
00156             {
00157                 /* FAT16 CHS partition (partition size < 512MB) */
00158                 PartitionInfo.PartitionType = PARTITION_HUGE;
00159             }
00160             else
00161             {
00162                 /* FAT32 CHS partition (partition size >= 512MB) */
00163                 PartitionInfo.PartitionType = PARTITION_FAT32;
00164             }
00165         }
00166         else
00167         {
00168             /* Partition starts above the 8.4GB boundary ==> LBA partition */
00169             
00170             if (PartitionInfo.PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
00171             {
00172                 /* FAT16 LBA partition (partition size < 512MB) */
00173                 PartitionInfo.PartitionType = PARTITION_XINT13;
00174             }
00175             else
00176             {
00177                 /* FAT32 LBA partition (partition size >= 512MB) */
00178                 PartitionInfo.PartitionType = PARTITION_FAT32_XINT13;
00179             }
00180         }
00181     }
00182 
00183     DPRINT("PartitionType 0x%x\n", PartitionInfo.PartitionType);
00184     DPRINT("StartingOffset %I64d\n", PartitionInfo.StartingOffset.QuadPart);
00185     DPRINT("PartitionLength %I64d\n", PartitionInfo.PartitionLength.QuadPart);
00186     DPRINT("HiddenSectors %lu\n", PartitionInfo.HiddenSectors);
00187     DPRINT("PartitionNumber %d\n", PartitionInfo.PartitionNumber);
00188     DPRINT("BootIndicator 0x%x\n", PartitionInfo.BootIndicator);
00189     DPRINT("RewritePartition %d\n", PartitionInfo.RewritePartition);
00190     DPRINT("RecognizedPartition %d\n", PartitionInfo.RecognizedPartition);
00191 
00192     if (Callback != NULL)
00193     {
00194         Context.Percent = 0;
00195         Callback (PROGRESS, 0, (PVOID)&Context.Percent);
00196     }
00197 
00198     LockStatus = NtFsControlFile(FileHandle,
00199                                  NULL,
00200                                  NULL,
00201                                  NULL,
00202                                  &Iosb,
00203                                  FSCTL_LOCK_VOLUME,
00204                                  NULL,
00205                                  0,
00206                                  NULL,
00207                                  0);
00208     if (!NT_SUCCESS(LockStatus))
00209     {
00210         DPRINT1("WARNING: Failed to lock volume for formatting! Format may fail! (Status: 0x%x)\n", LockStatus);
00211     }
00212 
00213     if (PartitionInfo.PartitionType == PARTITION_FAT_12)
00214     {
00215         /* FAT12 */
00216         Status = Fat12Format(FileHandle,
00217                              &PartitionInfo,
00218                              &DiskGeometry,
00219                              Label,
00220                              QuickFormat,
00221                              ClusterSize,
00222                              &Context);
00223     }
00224     else if (PartitionInfo.PartitionType == PARTITION_FAT_16 ||
00225              PartitionInfo.PartitionType == PARTITION_HUGE ||
00226              PartitionInfo.PartitionType == PARTITION_XINT13)
00227     {
00228         /* FAT16 */
00229         Status = Fat16Format(FileHandle,
00230                              &PartitionInfo,
00231                              &DiskGeometry,
00232                              Label,
00233                              QuickFormat,
00234                              ClusterSize,
00235                              &Context);
00236     }
00237     else if (PartitionInfo.PartitionType == PARTITION_FAT32 ||
00238              PartitionInfo.PartitionType == PARTITION_FAT32_XINT13)
00239     {
00240         /* FAT32 */
00241         Status = Fat32Format(FileHandle,
00242                              &PartitionInfo,
00243                              &DiskGeometry,
00244                              Label,
00245                              QuickFormat,
00246                              ClusterSize,
00247                              &Context);
00248     }
00249     else
00250     {
00251         Status = STATUS_INVALID_PARAMETER;
00252     }
00253 
00254     LockStatus = NtFsControlFile(FileHandle,
00255                                  NULL,
00256                                  NULL,
00257                                  NULL,
00258                                  &Iosb,
00259                                  FSCTL_UNLOCK_VOLUME,
00260                                  NULL,
00261                                  0,
00262                                  NULL,
00263                                  0);
00264     if (!NT_SUCCESS(LockStatus))
00265     {
00266         DPRINT1("Failed to unlock volume (Status: 0x%x)\n", LockStatus);
00267     }
00268 
00269     NtClose(FileHandle);
00270 
00271     if (Callback != NULL)
00272     {
00273         Context.Success = (BOOLEAN)(NT_SUCCESS(Status));
00274         Callback (DONE, 0, (PVOID)&Context.Success);
00275     }
00276 
00277     DPRINT("VfatFormat() done. Status 0x%.08x\n", Status);
00278 
00279     return Status;
00280 }
00281 
00282 
00283 VOID
00284 UpdateProgress(PFORMAT_CONTEXT Context,
00285                ULONG Increment)
00286 {
00287     ULONG NewPercent;
00288 
00289     Context->CurrentSectorCount += (ULONGLONG)Increment;
00290 
00291 
00292     NewPercent = (Context->CurrentSectorCount * 100ULL) / Context->TotalSectorCount;
00293 
00294     if (NewPercent > Context->Percent)
00295     {
00296         Context->Percent = NewPercent;
00297         if (Context->Callback != NULL)
00298         {
00299             Context->Callback (PROGRESS, 0, &Context->Percent);
00300         }
00301     }
00302 }
00303 
00304 
00305 VOID
00306 VfatPrint(PCHAR Format, ...)
00307 {
00308     TEXTOUTPUT TextOut;
00309     CHAR TextBuf[512];
00310     va_list valist;
00311 
00312     va_start(valist, Format);
00313     _vsnprintf(TextBuf, sizeof(TextBuf), Format, valist);
00314     va_end(valist);
00315 
00316     /* Prepare parameters */
00317     TextOut.Lines = 1;
00318     TextOut.Output = TextBuf;
00319 
00320     /* Do the callback */
00321     if (ChkdskCallback)
00322         ChkdskCallback(OUTPUT, 0, &TextOut);
00323 }
00324 
00325 
00326 NTSTATUS
00327 WINAPI
00328 VfatChkdsk(IN PUNICODE_STRING DriveRoot,
00329            IN BOOLEAN FixErrors,
00330            IN BOOLEAN Verbose,
00331            IN BOOLEAN CheckOnlyIfDirty,
00332            IN BOOLEAN ScanDrive,
00333            IN PFMIFSCALLBACK Callback)
00334 {
00335 #if 0
00336     BOOLEAN verify;
00337     BOOLEAN salvage_files;
00338 #endif
00339     //ULONG free_clusters;
00340     //DOS_FS fs;
00341 
00342     /* Store callback pointer */
00343     ChkdskCallback = Callback;
00344     FsCheckMemQueue = NULL;
00345 
00346     /* Set parameters */
00347     FsCheckFlags = 0;
00348     if (Verbose)
00349         FsCheckFlags |= FSCHECK_VERBOSE;
00350 
00351     FsCheckTotalFiles = 0;
00352 
00353 #if 0
00354     verify = TRUE;
00355     salvage_files = TRUE;
00356 
00357     /* Open filesystem */
00358     fs_open(DriveRoot,FixErrors);
00359 
00360     if (CheckOnlyIfDirty && !fs_isdirty())
00361     {
00362         /* No need to check FS */
00363         return fs_close(FALSE);
00364     }
00365 
00366     read_boot(&fs);
00367     if (verify)
00368         VfatPrint("Starting check/repair pass.\n");
00369 
00370     while (read_fat(&fs), scan_root(&fs))
00371         qfree(&FsCheckMemQueue);
00372 
00373     if (ScanDrive)
00374         fix_bad(&fs);
00375 
00376     if (salvage_files)
00377         reclaim_file(&fs);
00378     else
00379         reclaim_free(&fs);
00380 
00381     free_clusters = update_free(&fs);
00382     file_unused();
00383     qfree(&FsCheckMemQueue);
00384     if (verify)
00385     {
00386         VfatPrint("Starting verification pass.\n");
00387         read_fat(&fs);
00388         scan_root(&fs);
00389         reclaim_free(&fs);
00390         qfree(&FsCheckMemQueue);
00391     }
00392 
00393     if (fs_changed())
00394     {
00395         if (FixErrors)
00396         {
00397             if (FsCheckFlags & FSCHECK_INTERACTIVE)
00398                 FixErrors = get_key("yn","Perform changes ? (y/n)") == 'y';
00399             else
00400                 VfatPrint("Performing changes.\n");
00401         }
00402         else
00403         {
00404             VfatPrint("Leaving file system unchanged.\n");
00405         }
00406     }
00407 
00408     VfatPrint("%wZ: %u files, %lu/%lu clusters\n", DriveRoot,
00409         FsCheckTotalFiles, fs.clusters - free_clusters, fs.clusters );
00410 
00411     if (FixErrors)
00412     {
00413         /* Dismount the volume */
00414         fs_dismount();
00415 
00416         /* Unlock the volume */
00417         fs_lock(FALSE);
00418     }
00419 
00420     /* Close the volume */
00421     return fs_close(FixErrors) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
00422 #else
00423     return STATUS_SUCCESS;
00424 #endif
00425 }
00426 
00427 /* EOF */

Generated on Fri May 25 2012 04:34:41 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.