Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvfatlib.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
1.7.6.1
|