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