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