2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS VFAT filesystem library
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 05/04-2003 Created
12 #define NTOS_MODE_USER
14 #include <ddk/ntddscsi.h>
15 #include <fslib/vfatlib.h>
20 GetShiftCount(ULONG Value)
35 DPRINT("VfatInitialize()\n");
37 return STATUS_SUCCESS;
41 VfatWriteBootSector(IN HANDLE FileHandle,
42 IN PFAT32_BOOT_SECTOR BootSector)
44 OBJECT_ATTRIBUTES ObjectAttributes;
45 IO_STATUS_BLOCK IoStatusBlock;
49 LARGE_INTEGER FileOffset;
51 /* Allocate buffer for new bootsector */
52 NewBootSector = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
55 if (NewBootSector == NULL)
56 return(STATUS_INSUFFICIENT_RESOURCES);
58 /* Zero the new bootsector */
59 memset(NewBootSector, 0, SECTORSIZE);
61 /* Copy FAT32 BPB to new bootsector */
62 memcpy((NewBootSector + 3),
63 &BootSector->OEMName[0],
64 87); /* FAT32 BPB length (up to (not including) Res2) */
67 FileOffset.QuadPart = 0ULL;
68 Status = NtWriteFile(FileHandle,
77 if (!NT_SUCCESS(Status))
79 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
80 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
84 /* Write backup boot sector */
85 if (BootSector->BootBackup != 0x0000)
87 FileOffset.QuadPart = (ULONGLONG)((ULONG) BootSector->BootBackup * SECTORSIZE);
88 Status = NtWriteFile(FileHandle,
97 if (!NT_SUCCESS(Status))
99 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
100 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
105 /* Free the new boot sector */
106 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
113 VfatWriteFsInfo(IN HANDLE FileHandle,
114 IN PFAT32_BOOT_SECTOR BootSector)
116 OBJECT_ATTRIBUTES ObjectAttributes;
117 IO_STATUS_BLOCK IoStatusBlock;
120 PFAT32_FSINFO FsInfo;
121 LARGE_INTEGER FileOffset;
123 /* Allocate buffer for new sector */
124 FsInfo = (PFAT32_FSINFO)RtlAllocateHeap(RtlGetProcessHeap(),
126 BootSector->BytesPerSector);
128 return(STATUS_INSUFFICIENT_RESOURCES);
130 /* Zero the new sector */
131 memset(FsInfo, 0, BootSector->BytesPerSector);
133 FsInfo->LeadSig = 0x41615252;
134 FsInfo->StrucSig = 0x61417272;
135 FsInfo->FreeCount = 0xffffffff;
136 FsInfo->NextFree = 0xffffffff;
139 FileOffset.QuadPart = BootSector->FSInfoSector * BootSector->BytesPerSector;
140 Status = NtWriteFile(FileHandle,
146 BootSector->BytesPerSector,
149 if (!NT_SUCCESS(Status))
151 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
152 RtlFreeHeap(RtlGetProcessHeap(), 0, FsInfo);
156 /* Free the new sector buffer */
157 RtlFreeHeap(RtlGetProcessHeap(), 0, FsInfo);
164 VfatWriteFAT(IN HANDLE FileHandle,
166 IN PFAT32_BOOT_SECTOR BootSector)
168 OBJECT_ATTRIBUTES ObjectAttributes;
169 IO_STATUS_BLOCK IoStatusBlock;
173 LARGE_INTEGER FileOffset;
176 /* Allocate buffer */
177 Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
179 BootSector->BytesPerSector);
181 return(STATUS_INSUFFICIENT_RESOURCES);
183 /* Zero the buffer */
184 memset(Buffer, 0, BootSector->BytesPerSector);
187 Buffer[0] = 0xf8; /* Media type */
192 Buffer[4] = 0xcf; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
197 Buffer[8] = 0xff; /* End of root directory */
202 /* Write first sector of the FAT */
203 FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors) * BootSector->BytesPerSector;
204 Status = NtWriteFile(FileHandle,
210 BootSector->BytesPerSector,
213 if (!NT_SUCCESS(Status))
215 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
216 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
220 /* Zero the buffer */
221 memset(Buffer, 0, BootSector->BytesPerSector);
223 /* Zero the rest of the FAT */
224 for (i = 1; i < BootSector->FATSectors32 - 1; i++)
226 /* Zero one sector of the FAT */
227 FileOffset.QuadPart = (SectorOffset + BootSector->ReservedSectors + i) * BootSector->BytesPerSector;
228 Status = NtWriteFile(FileHandle,
234 BootSector->BytesPerSector,
237 if (!NT_SUCCESS(Status))
239 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
240 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
245 /* Free the buffer */
246 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
253 VfatWriteRootDirectory(IN HANDLE FileHandle,
254 IN PFAT32_BOOT_SECTOR BootSector)
256 OBJECT_ATTRIBUTES ObjectAttributes;
257 IO_STATUS_BLOCK IoStatusBlock;
260 LARGE_INTEGER FileOffset;
261 ULONGLONG FirstDataSector;
262 ULONGLONG FirstRootDirSector;
264 /* Allocate buffer for the cluster */
265 Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
267 BootSector->SectorsPerCluster * BootSector->BytesPerSector);
269 return(STATUS_INSUFFICIENT_RESOURCES);
271 /* Zero the buffer */
272 memset(Buffer, 0, BootSector->SectorsPerCluster * BootSector->BytesPerSector);
274 DPRINT("BootSector->ReservedSectors = %lu\n", BootSector->ReservedSectors);
275 DPRINT("BootSector->FATSectors32 = %lu\n", BootSector->FATSectors32);
276 DPRINT("BootSector->RootCluster = %lu\n", BootSector->RootCluster);
277 DPRINT("BootSector->SectorsPerCluster = %lu\n", BootSector->SectorsPerCluster);
280 FirstDataSector = BootSector->ReservedSectors +
281 (BootSector->FATCount * BootSector->FATSectors32) + 0 /* RootDirSectors */;
283 DPRINT("FirstDataSector = %lu\n", FirstDataSector);
285 FirstRootDirSector = ((BootSector->RootCluster - 2) * BootSector->SectorsPerCluster) + FirstDataSector;
286 FileOffset.QuadPart = FirstRootDirSector * BootSector->BytesPerSector;
288 DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector);
289 DPRINT("FileOffset = %lu\n", FileOffset.QuadPart);
291 Status = NtWriteFile(FileHandle,
297 BootSector->SectorsPerCluster * BootSector->BytesPerSector,
300 if (!NT_SUCCESS(Status))
302 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
303 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
307 /* Free the buffer */
308 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
316 PUNICODE_STRING DriveRoot,
318 PUNICODE_STRING Label,
321 PFMIFSCALLBACK Callback)
323 OBJECT_ATTRIBUTES ObjectAttributes;
324 DISK_GEOMETRY DiskGeometry;
325 IO_STATUS_BLOCK Iosb;
327 SCSI_ADDRESS ScsiAddress;
328 PARTITION_INFORMATION PartitionInfo;
329 FAT32_BOOT_SECTOR BootSector;
330 ANSI_STRING VolumeLabel;
332 ULONG RootDirSectors;
336 DPRINT("VfatFormat(DriveRoot '%S')\n", DriveRoot->Buffer);
338 InitializeObjectAttributes(&ObjectAttributes,
344 Status = NtOpenFile(&FileHandle,
345 FILE_WRITE_ACCESS | FILE_WRITE_ATTRIBUTES,
349 FILE_SYNCHRONOUS_IO_ALERT);
350 if (!NT_SUCCESS(Status))
352 DPRINT("NtOpenFile() failed with status 0x%.08x\n", Status);
356 Status = NtDeviceIoControlFile(FileHandle,
361 IOCTL_DISK_GET_DRIVE_GEOMETRY,
365 sizeof(DISK_GEOMETRY));
366 if (!NT_SUCCESS(Status))
368 DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY failed with status 0x%.08x\n", Status);
373 if (DiskGeometry.MediaType == FixedMedia)
375 DPRINT("Cylinders %d\n", DiskGeometry.Cylinders.QuadPart);
376 DPRINT("TracksPerCylinder %d\n", DiskGeometry.TracksPerCylinder);
377 DPRINT("SectorsPerTrack %d\n", DiskGeometry.SectorsPerTrack);
378 DPRINT("BytesPerSector %d\n", DiskGeometry.BytesPerSector);
379 DPRINT("DiskSize %d\n",
380 DiskGeometry.Cylinders.QuadPart *
381 (ULONGLONG)DiskGeometry.TracksPerCylinder *
382 (ULONGLONG)DiskGeometry.SectorsPerTrack *
383 (ULONGLONG)DiskGeometry.BytesPerSector);
385 Status = NtDeviceIoControlFile(FileHandle,
390 IOCTL_DISK_GET_PARTITION_INFO,
394 sizeof(PARTITION_INFORMATION));
395 if (!NT_SUCCESS(Status))
397 DPRINT("IOCTL_DISK_GET_PARTITION_INFO failed with status 0x%.08x\n", Status);
402 DPRINT("PartitionType 0x%x\n", PartitionInfo.PartitionType);
403 DPRINT("StartingOffset %d\n", PartitionInfo.StartingOffset);
404 DPRINT("PartitionLength %d\n", PartitionInfo.PartitionLength);
405 DPRINT("HiddenSectors %d\n", PartitionInfo.HiddenSectors);
406 DPRINT("PartitionNumber %d\n", PartitionInfo.PartitionNumber);
407 DPRINT("BootIndicator 0x%x\n", PartitionInfo.BootIndicator);
408 DPRINT("RewritePartition %d\n", PartitionInfo.RewritePartition);
409 DPRINT("RecognizedPartition %d\n", PartitionInfo.RecognizedPartition);
413 DPRINT1("FIXME: Removable media is not supported\n");
418 memset(&BootSector, 0, sizeof(FAT32_BOOT_SECTOR));
419 memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
420 BootSector.BytesPerSector = DiskGeometry.BytesPerSector;
421 BootSector.SectorsPerCluster = 4096 / BootSector.BytesPerSector; // 4KB clusters /* FIXME: */
422 BootSector.ReservedSectors = 32;
423 BootSector.FATCount = 2;
424 BootSector.RootEntries = 0;
425 BootSector.Sectors = 0;
426 BootSector.Media = 0xf8;
427 BootSector.FATSectors = 0;
428 BootSector.SectorsPerTrack = DiskGeometry.SectorsPerTrack;
429 BootSector.Heads = DiskGeometry.TracksPerCylinder;
430 BootSector.HiddenSectors = 63; /* FIXME: */
431 BootSector.SectorsHuge = PartitionInfo.PartitionLength.QuadPart >>
432 GetShiftCount(BootSector.BytesPerSector); /* Use shifting to avoid 64-bit division */
433 BootSector.FATSectors32 = 0; /* Set later */
434 BootSector.ExtFlag = 0; /* Mirror all FATs */
435 BootSector.FSVersion = 0x0000; /* 0:0 */
436 BootSector.RootCluster = 2;
437 BootSector.FSInfoSector = 1;
438 BootSector.BootBackup = 6;
439 BootSector.Drive = 0xff; /* No BIOS boot drive available */ //0x80; /* FIXME: */
440 BootSector.ExtBootSignature = 0x29;
441 BootSector.VolumeID = 0x45768798; /* FIXME: */
442 if ((Label == NULL) || (Label->Buffer == NULL))
444 memcpy(&BootSector.VolumeLabel[0], "NO NAME ", 11);
448 RtlUnicodeStringToAnsiString(&VolumeLabel, Label, TRUE);
449 memset(&BootSector.VolumeLabel[0], ' ', 11);
450 memcpy(&BootSector.VolumeLabel[0], VolumeLabel.Buffer,
451 VolumeLabel.Length < 11 ? VolumeLabel.Length : 11);
452 RtlFreeAnsiString(&VolumeLabel);
454 memcpy(&BootSector.SysType[0], "FAT32 ", 8);
456 RootDirSectors = ((BootSector.RootEntries * 32) +
457 (BootSector.BytesPerSector - 1)) / BootSector.BytesPerSector;
458 TmpVal1 = BootSector.SectorsHuge - (BootSector.ReservedSectors + RootDirSectors);
459 TmpVal2 = (256 * BootSector.SectorsPerCluster) + BootSector.FATCount;
460 if (TRUE /* FAT32 */)
463 BootSector.FATSectors = 0;
464 BootSector.FATSectors32 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
467 Status = VfatWriteBootSector(FileHandle,
469 if (!NT_SUCCESS(Status))
471 DPRINT("VfatWriteBootSector() failed with status 0x%.08x\n", Status);
476 Status = VfatWriteFsInfo(FileHandle,
478 if (!NT_SUCCESS(Status))
480 DPRINT("VfatWriteFsInfo() failed with status 0x%.08x\n", Status);
485 /* Write first FAT copy */
486 Status = VfatWriteFAT(FileHandle,
489 if (!NT_SUCCESS(Status))
491 DPRINT("VfatWriteFAT() failed with status 0x%.08x\n", Status);
496 /* Write second FAT copy */
497 Status = VfatWriteFAT(FileHandle,
498 BootSector.FATSectors32,
500 if (!NT_SUCCESS(Status))
502 DPRINT("VfatWriteFAT() failed with status 0x%.08x.\n", Status);
507 Status = VfatWriteRootDirectory(FileHandle,
509 if (!NT_SUCCESS(Status))
511 DPRINT("VfatWriteRootDirectory() failed with status 0x%.08x\n", Status);
518 DPRINT("VfatFormat() done. Status 0x%.08x\n", Status);
527 DPRINT("VfatCleanup()\n");
529 return STATUS_SUCCESS;