Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfat16.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: fat16.c 00005 * PURPOSE: Fat16 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 Fat16WriteBootSector(IN HANDLE FileHandle, 00054 IN PFAT16_BOOT_SECTOR BootSector, 00055 IN OUT PFORMAT_CONTEXT Context) 00056 { 00057 IO_STATUS_BLOCK IoStatusBlock; 00058 NTSTATUS Status; 00059 PFAT16_BOOT_SECTOR NewBootSector; 00060 LARGE_INTEGER FileOffset; 00061 00062 /* Allocate buffer for new bootsector */ 00063 NewBootSector = (PFAT16_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 FAT16 BPB to new bootsector */ 00073 memcpy(&NewBootSector->OEMName[0], 00074 &BootSector->OEMName[0], 00075 59); /* FAT16 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 /* Free the new boot sector */ 00101 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector); 00102 00103 return Status; 00104 } 00105 00106 00107 static NTSTATUS 00108 Fat16WriteFAT(IN HANDLE FileHandle, 00109 IN ULONG SectorOffset, 00110 IN PFAT16_BOOT_SECTOR BootSector, 00111 IN OUT PFORMAT_CONTEXT Context) 00112 { 00113 IO_STATUS_BLOCK IoStatusBlock; 00114 NTSTATUS Status; 00115 PUCHAR Buffer; 00116 LARGE_INTEGER FileOffset; 00117 ULONG i; 00118 ULONG Sectors; 00119 00120 /* Allocate buffer */ 00121 Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(), 00122 0, 00123 32 * 1024); 00124 if (Buffer == NULL) 00125 return STATUS_INSUFFICIENT_RESOURCES; 00126 00127 /* Zero the buffer */ 00128 memset(Buffer, 0, 32 * 1024); 00129 00130 /* FAT cluster 0 */ 00131 Buffer[0] = 0xf8; /* Media type */ 00132 Buffer[1] = 0xff; 00133 00134 /* FAT cluster 1 */ 00135 Buffer[2] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */ 00136 Buffer[3] = 0xff; 00137 00138 /* Write first sector of the FAT */ 00139 FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors) * BootSector->BytesPerSector; 00140 Status = NtWriteFile(FileHandle, 00141 NULL, 00142 NULL, 00143 NULL, 00144 &IoStatusBlock, 00145 Buffer, 00146 BootSector->BytesPerSector, 00147 &FileOffset, 00148 NULL); 00149 if (!NT_SUCCESS(Status)) 00150 { 00151 DPRINT("NtWriteFile() failed (Status %lx)\n", Status); 00152 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 00153 return Status; 00154 } 00155 00156 UpdateProgress(Context, 1); 00157 00158 /* Zero the begin of the buffer */ 00159 memset(Buffer, 0, 4); 00160 00161 /* Zero the rest of the FAT */ 00162 Sectors = 32 * 1024 / BootSector->BytesPerSector; 00163 for (i = 1; i < (ULONG)BootSector->FATSectors; i += Sectors) 00164 { 00165 /* Zero some sectors of the FAT */ 00166 FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors + i) * BootSector->BytesPerSector; 00167 00168 if (((ULONG)BootSector->FATSectors - i) <= Sectors) 00169 { 00170 Sectors = (ULONG)BootSector->FATSectors - i; 00171 } 00172 00173 Status = NtWriteFile(FileHandle, 00174 NULL, 00175 NULL, 00176 NULL, 00177 &IoStatusBlock, 00178 Buffer, 00179 Sectors * BootSector->BytesPerSector, 00180 &FileOffset, 00181 NULL); 00182 if (!NT_SUCCESS(Status)) 00183 { 00184 DPRINT("NtWriteFile() failed (Status %lx)\n", Status); 00185 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 00186 return Status; 00187 } 00188 00189 UpdateProgress(Context, Sectors); 00190 } 00191 00192 /* Free the buffer */ 00193 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 00194 00195 return Status; 00196 } 00197 00198 00199 static NTSTATUS 00200 Fat16WriteRootDirectory(IN HANDLE FileHandle, 00201 IN PFAT16_BOOT_SECTOR BootSector, 00202 IN OUT PFORMAT_CONTEXT Context) 00203 { 00204 IO_STATUS_BLOCK IoStatusBlock; 00205 NTSTATUS Status = STATUS_SUCCESS; 00206 PUCHAR Buffer; 00207 LARGE_INTEGER FileOffset; 00208 ULONG FirstRootDirSector; 00209 ULONG RootDirSectors; 00210 ULONG Sectors; 00211 ULONG i; 00212 00213 DPRINT("BootSector->ReservedSectors = %hu\n", BootSector->ReservedSectors); 00214 DPRINT("BootSector->FATSectors = %hu\n", BootSector->FATSectors); 00215 DPRINT("BootSector->SectorsPerCluster = %u\n", BootSector->SectorsPerCluster); 00216 00217 /* Write cluster */ 00218 RootDirSectors = ((BootSector->RootEntries * 32) + 00219 (BootSector->BytesPerSector - 1)) / BootSector->BytesPerSector; 00220 FirstRootDirSector = 00221 BootSector->ReservedSectors + (BootSector->FATCount * BootSector->FATSectors); 00222 00223 DPRINT("RootDirSectors = %lu\n", RootDirSectors); 00224 DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector); 00225 00226 /* Allocate buffer for the cluster */ 00227 Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(), 00228 0, 00229 32 * 1024); 00230 if (Buffer == NULL) 00231 return STATUS_INSUFFICIENT_RESOURCES; 00232 00233 /* Zero the buffer */ 00234 memset(Buffer, 0, 32 * 1024); 00235 00236 Sectors = 32 * 1024 / BootSector->BytesPerSector; 00237 for (i = 0; i < RootDirSectors; i += Sectors) 00238 { 00239 /* Zero some sectors of the root directory */ 00240 FileOffset.QuadPart = (FirstRootDirSector + i) * BootSector->BytesPerSector; 00241 00242 if ((RootDirSectors - i) <= Sectors) 00243 { 00244 Sectors = RootDirSectors - i; 00245 } 00246 00247 Status = NtWriteFile(FileHandle, 00248 NULL, 00249 NULL, 00250 NULL, 00251 &IoStatusBlock, 00252 Buffer, 00253 Sectors * BootSector->BytesPerSector, 00254 &FileOffset, 00255 NULL); 00256 if (!NT_SUCCESS(Status)) 00257 { 00258 DPRINT("NtWriteFile() failed (Status %lx)\n", Status); 00259 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 00260 return Status; 00261 } 00262 00263 UpdateProgress(Context, Sectors); 00264 } 00265 00266 /* Free the buffer */ 00267 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 00268 00269 return Status; 00270 } 00271 00272 00273 NTSTATUS 00274 Fat16Format(IN HANDLE FileHandle, 00275 IN PPARTITION_INFORMATION PartitionInfo, 00276 IN PDISK_GEOMETRY DiskGeometry, 00277 IN PUNICODE_STRING Label, 00278 IN BOOLEAN QuickFormat, 00279 IN ULONG ClusterSize, 00280 IN OUT PFORMAT_CONTEXT Context) 00281 { 00282 FAT16_BOOT_SECTOR BootSector; 00283 OEM_STRING VolumeLabel; 00284 ULONG SectorCount; 00285 ULONG RootDirSectors; 00286 ULONG TmpVal1; 00287 ULONG TmpVal2; 00288 ULONG TmpVal3; 00289 NTSTATUS Status; 00290 00291 /* Calculate cluster size */ 00292 if (ClusterSize == 0) 00293 { 00294 if (PartitionInfo->PartitionLength.QuadPart < 16LL * 1024LL * 1024LL) 00295 { 00296 /* Partition < 16MB ==> 1KB Cluster */ 00297 ClusterSize = 1024; 00298 } 00299 else if (PartitionInfo->PartitionLength.QuadPart < 128LL * 1024LL * 1024LL) 00300 { 00301 /* Partition < 128MB ==> 2KB Cluster */ 00302 ClusterSize = 2048; 00303 } 00304 else if (PartitionInfo->PartitionLength.QuadPart < 256LL * 1024LL * 1024LL) 00305 { 00306 /* Partition < 256MB ==> 4KB Cluster */ 00307 ClusterSize = 4096; 00308 } 00309 else 00310 { 00311 /* Partition >= 256MB (< 512MB) ==> 8KB Cluster */ 00312 ClusterSize = 8192; 00313 } 00314 } 00315 00316 SectorCount = PartitionInfo->PartitionLength.QuadPart >> 00317 GetShiftCount(DiskGeometry->BytesPerSector); /* Use shifting to avoid 64-bit division */ 00318 00319 memset(&BootSector, 0, sizeof(FAT16_BOOT_SECTOR)); 00320 memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8); 00321 BootSector.BytesPerSector = DiskGeometry->BytesPerSector; 00322 BootSector.SectorsPerCluster = ClusterSize / BootSector.BytesPerSector; 00323 BootSector.ReservedSectors = 1; 00324 BootSector.FATCount = 2; 00325 BootSector.RootEntries = 512; 00326 BootSector.Sectors = (SectorCount < 0x10000) ? (unsigned short)SectorCount : 0; 00327 BootSector.Media = 0xf8; 00328 BootSector.FATSectors = 0; /* Set later. See below. */ 00329 BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack; 00330 BootSector.Heads = DiskGeometry->TracksPerCylinder; 00331 BootSector.HiddenSectors = PartitionInfo->HiddenSectors; 00332 BootSector.SectorsHuge = (SectorCount >= 0x10000) ? (unsigned long)SectorCount : 0; 00333 BootSector.Drive = DiskGeometry->MediaType == FixedMedia ? 0x80 : 0x00; 00334 BootSector.ExtBootSignature = 0x29; 00335 BootSector.VolumeID = CalcVolumeSerialNumber(); 00336 if ((Label == NULL) || (Label->Buffer == NULL)) 00337 { 00338 memcpy(&BootSector.VolumeLabel[0], "NO NAME ", 11); 00339 } 00340 else 00341 { 00342 RtlUnicodeStringToOemString(&VolumeLabel, Label, TRUE); 00343 memset(&BootSector.VolumeLabel[0], ' ', 11); 00344 memcpy(&BootSector.VolumeLabel[0], VolumeLabel.Buffer, 00345 VolumeLabel.Length < 11 ? VolumeLabel.Length : 11); 00346 RtlFreeOemString(&VolumeLabel); 00347 } 00348 00349 memcpy(&BootSector.SysType[0], "FAT16 ", 8); 00350 00351 DPRINT("BootSector.SectorsHuge = %lx\n", BootSector.SectorsHuge); 00352 00353 RootDirSectors = ((BootSector.RootEntries * 32) + 00354 (BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector; 00355 00356 /* Calculate number of FAT sectors */ 00357 /* (BootSector.BytesPerSector / 2) FAT entries (16bit) fit into one sector */ 00358 TmpVal1 = SectorCount - (BootSector.ReservedSectors + RootDirSectors); 00359 TmpVal2 = ((BootSector.BytesPerSector / 2) * BootSector.SectorsPerCluster) + BootSector.FATCount; 00360 TmpVal3 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2; 00361 BootSector.FATSectors = (unsigned short)(TmpVal3 & 0xffff); 00362 DPRINT("BootSector.FATSectors = %hu\n", BootSector.FATSectors); 00363 00364 /* Init context data */ 00365 Context->TotalSectorCount = 00366 1 + (BootSector.FATSectors * 2) + RootDirSectors; 00367 00368 Status = Fat16WriteBootSector(FileHandle, 00369 &BootSector, 00370 Context); 00371 if (!NT_SUCCESS(Status)) 00372 { 00373 DPRINT("Fat16WriteBootSector() failed with status 0x%.08x\n", Status); 00374 return Status; 00375 } 00376 00377 /* Write first FAT copy */ 00378 Status = Fat16WriteFAT(FileHandle, 00379 0, 00380 &BootSector, 00381 Context); 00382 if (!NT_SUCCESS(Status)) 00383 { 00384 DPRINT("Fat16WriteFAT() failed with status 0x%.08x\n", Status); 00385 return Status; 00386 } 00387 00388 /* Write second FAT copy */ 00389 Status = Fat16WriteFAT(FileHandle, 00390 (ULONG)BootSector.FATSectors, 00391 &BootSector, 00392 Context); 00393 if (!NT_SUCCESS(Status)) 00394 { 00395 DPRINT("Fat16WriteFAT() failed with status 0x%.08x.\n", Status); 00396 return Status; 00397 } 00398 00399 Status = Fat16WriteRootDirectory(FileHandle, 00400 &BootSector, 00401 Context); 00402 if (!NT_SUCCESS(Status)) 00403 { 00404 DPRINT("Fat16WriteRootDirectory() failed with status 0x%.08x\n", Status); 00405 } 00406 00407 if (!QuickFormat) 00408 { 00409 /* FIXME: Fill remaining sectors */ 00410 } 00411 00412 return Status; 00413 } Generated on Sat May 26 2012 04:35:04 for ReactOS by
1.7.6.1
|