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