2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS VFAT filesystem library
5 * PURPOSE: Fat16 support
6 * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
8 * EK 05/04-2003 Created
12 #define NTOS_MODE_USER
14 #include <ddk/ntddscsi.h>
19 GetShiftCount(ULONG Value
)
32 Fat32WriteBootSector(IN HANDLE FileHandle
,
33 IN PFAT32_BOOT_SECTOR BootSector
)
35 OBJECT_ATTRIBUTES ObjectAttributes
;
36 IO_STATUS_BLOCK IoStatusBlock
;
40 LARGE_INTEGER FileOffset
;
42 /* Allocate buffer for new bootsector */
43 NewBootSector
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
46 if (NewBootSector
== NULL
)
47 return(STATUS_INSUFFICIENT_RESOURCES
);
49 /* Zero the new bootsector */
50 memset(NewBootSector
, 0, SECTORSIZE
);
52 /* Copy FAT32 BPB to new bootsector */
53 memcpy((NewBootSector
+ 3),
54 &BootSector
->OEMName
[0],
55 87); /* FAT32 BPB length (up to (not including) Res2) */
58 FileOffset
.QuadPart
= 0ULL;
59 Status
= NtWriteFile(FileHandle
,
68 if (!NT_SUCCESS(Status
))
70 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
71 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector
);
75 /* Write backup boot sector */
76 if (BootSector
->BootBackup
!= 0x0000)
78 FileOffset
.QuadPart
= (ULONGLONG
)((ULONG
) BootSector
->BootBackup
* SECTORSIZE
);
79 Status
= NtWriteFile(FileHandle
,
88 if (!NT_SUCCESS(Status
))
90 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
91 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector
);
96 /* Free the new boot sector */
97 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector
);
104 Fat32WriteFsInfo(IN HANDLE FileHandle
,
105 IN PFAT32_BOOT_SECTOR BootSector
)
107 OBJECT_ATTRIBUTES ObjectAttributes
;
108 IO_STATUS_BLOCK IoStatusBlock
;
111 PFAT32_FSINFO FsInfo
;
112 LARGE_INTEGER FileOffset
;
114 /* Allocate buffer for new sector */
115 FsInfo
= (PFAT32_FSINFO
)RtlAllocateHeap(RtlGetProcessHeap(),
117 BootSector
->BytesPerSector
);
119 return(STATUS_INSUFFICIENT_RESOURCES
);
121 /* Zero the new sector */
122 memset(FsInfo
, 0, BootSector
->BytesPerSector
);
124 FsInfo
->LeadSig
= 0x41615252;
125 FsInfo
->StrucSig
= 0x61417272;
126 FsInfo
->FreeCount
= 0xffffffff;
127 FsInfo
->NextFree
= 0xffffffff;
128 FsInfo
->TrailSig
= 0xaa550000;
131 FileOffset
.QuadPart
= BootSector
->FSInfoSector
* BootSector
->BytesPerSector
;
132 Status
= NtWriteFile(FileHandle
,
138 BootSector
->BytesPerSector
,
141 if (!NT_SUCCESS(Status
))
143 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
144 RtlFreeHeap(RtlGetProcessHeap(), 0, FsInfo
);
148 /* Free the new sector buffer */
149 RtlFreeHeap(RtlGetProcessHeap(), 0, FsInfo
);
156 Fat32WriteFAT(IN HANDLE FileHandle
,
158 IN PFAT32_BOOT_SECTOR BootSector
)
160 OBJECT_ATTRIBUTES ObjectAttributes
;
161 IO_STATUS_BLOCK IoStatusBlock
;
165 LARGE_INTEGER FileOffset
;
170 /* Allocate buffer */
171 Buffer
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
175 return(STATUS_INSUFFICIENT_RESOURCES
);
177 /* Zero the buffer */
178 memset(Buffer
, 0, 64 * 1024);
181 Buffer
[0] = 0xf8; /* Media type */
186 Buffer
[4] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
191 Buffer
[8] = 0xff; /* End of root directory */
196 /* Write first sector of the FAT */
197 FileOffset
.QuadPart
= (SectorOffset
+ BootSector
->ReservedSectors
) * BootSector
->BytesPerSector
;
198 Status
= NtWriteFile(FileHandle
,
204 BootSector
->BytesPerSector
,
207 if (!NT_SUCCESS(Status
))
209 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
210 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
214 /* Zero the begin of the buffer */
215 memset(Buffer
, 0, 12);
217 /* Zero the rest of the FAT */
218 Sectors
= 64 * 1024 / BootSector
->BytesPerSector
;
219 for (i
= 1; i
< BootSector
->FATSectors32
; i
+= Sectors
)
221 /* Zero some sectors of the FAT */
222 FileOffset
.QuadPart
= (SectorOffset
+ BootSector
->ReservedSectors
+ i
) * BootSector
->BytesPerSector
;
223 Size
= BootSector
->FATSectors32
- i
;
228 Size
*= BootSector
->BytesPerSector
;
229 Status
= NtWriteFile(FileHandle
,
238 if (!NT_SUCCESS(Status
))
240 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
241 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
246 /* Free the buffer */
247 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
254 Fat32WriteRootDirectory(IN HANDLE FileHandle
,
255 IN PFAT32_BOOT_SECTOR BootSector
)
257 OBJECT_ATTRIBUTES ObjectAttributes
;
258 IO_STATUS_BLOCK IoStatusBlock
;
261 LARGE_INTEGER FileOffset
;
262 ULONGLONG FirstDataSector
;
263 ULONGLONG FirstRootDirSector
;
265 /* Allocate buffer for the cluster */
266 Buffer
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
268 BootSector
->SectorsPerCluster
* BootSector
->BytesPerSector
);
270 return(STATUS_INSUFFICIENT_RESOURCES
);
272 /* Zero the buffer */
273 memset(Buffer
, 0, BootSector
->SectorsPerCluster
* BootSector
->BytesPerSector
);
275 DPRINT("BootSector->ReservedSectors = %lu\n", BootSector
->ReservedSectors
);
276 DPRINT("BootSector->FATSectors32 = %lu\n", BootSector
->FATSectors32
);
277 DPRINT("BootSector->RootCluster = %lu\n", BootSector
->RootCluster
);
278 DPRINT("BootSector->SectorsPerCluster = %lu\n", BootSector
->SectorsPerCluster
);
281 FirstDataSector
= BootSector
->ReservedSectors
+
282 (BootSector
->FATCount
* BootSector
->FATSectors32
) + 0 /* RootDirSectors */;
284 DPRINT("FirstDataSector = %lu\n", FirstDataSector
);
286 FirstRootDirSector
= ((BootSector
->RootCluster
- 2) * BootSector
->SectorsPerCluster
) + FirstDataSector
;
287 FileOffset
.QuadPart
= FirstRootDirSector
* BootSector
->BytesPerSector
;
289 DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector
);
290 DPRINT("FileOffset = %lu\n", FileOffset
.QuadPart
);
292 Status
= NtWriteFile(FileHandle
,
298 BootSector
->SectorsPerCluster
* BootSector
->BytesPerSector
,
301 if (!NT_SUCCESS(Status
))
303 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
304 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
308 /* Free the buffer */
309 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
316 Fat32Format (HANDLE FileHandle
,
317 PPARTITION_INFORMATION PartitionInfo
,
318 PDISK_GEOMETRY DiskGeometry
,
319 PUNICODE_STRING Label
,
322 PFMIFSCALLBACK Callback
)
324 FAT32_BOOT_SECTOR BootSector
;
325 ANSI_STRING VolumeLabel
;
326 ULONG RootDirSectors
;
332 /* Calculate cluster size */
333 if (ClusterSize
== 0)
335 if (PartitionInfo
->PartitionLength
.QuadPart
< 8ULL * 1024ULL * 1024ULL * 1024ULL)
337 /* Partition < 8GB ==> 4KB Cluster */
340 else if (PartitionInfo
->PartitionLength
.QuadPart
< 16ULL * 1024ULL * 1024ULL * 1024ULL)
342 /* Partition 8GB - 16GB ==> 8KB Cluster */
345 else if (PartitionInfo
->PartitionLength
.QuadPart
< 32ULL * 1024ULL * 1024ULL * 1024ULL)
347 /* Partition 16GB - 32GB ==> 16KB Cluster */
352 /* Partition >= 32GB ==> 32KB Cluster */
357 memset(&BootSector
, 0, sizeof(FAT32_BOOT_SECTOR
));
358 memcpy(&BootSector
.OEMName
[0], "MSWIN4.1", 8);
359 BootSector
.BytesPerSector
= DiskGeometry
->BytesPerSector
;
360 BootSector
.SectorsPerCluster
= ClusterSize
/ BootSector
.BytesPerSector
;
361 BootSector
.ReservedSectors
= 32;
362 BootSector
.FATCount
= 2;
363 BootSector
.RootEntries
= 0;
364 BootSector
.Sectors
= 0;
365 BootSector
.Media
= 0xf8;
366 BootSector
.FATSectors
= 0;
367 BootSector
.SectorsPerTrack
= DiskGeometry
->SectorsPerTrack
;
368 BootSector
.Heads
= DiskGeometry
->TracksPerCylinder
;
369 BootSector
.HiddenSectors
= DiskGeometry
->SectorsPerTrack
; //PartitionInfo->HiddenSectors; /* FIXME: Hack! */
370 BootSector
.SectorsHuge
= PartitionInfo
->PartitionLength
.QuadPart
>>
371 GetShiftCount(BootSector
.BytesPerSector
); /* Use shifting to avoid 64-bit division */
372 BootSector
.FATSectors32
= 0; /* Set later */
373 BootSector
.ExtFlag
= 0; /* Mirror all FATs */
374 BootSector
.FSVersion
= 0x0000; /* 0:0 */
375 BootSector
.RootCluster
= 2;
376 BootSector
.FSInfoSector
= 1;
377 BootSector
.BootBackup
= 6;
378 BootSector
.Drive
= 0xff; /* No BIOS boot drive available */
379 BootSector
.ExtBootSignature
= 0x29;
380 BootSector
.VolumeID
= 0x45768798; /* FIXME: */
381 if ((Label
== NULL
) || (Label
->Buffer
== NULL
))
383 memcpy(&BootSector
.VolumeLabel
[0], "NO NAME ", 11);
387 RtlUnicodeStringToAnsiString(&VolumeLabel
, Label
, TRUE
);
388 memset(&BootSector
.VolumeLabel
[0], ' ', 11);
389 memcpy(&BootSector
.VolumeLabel
[0], VolumeLabel
.Buffer
,
390 VolumeLabel
.Length
< 11 ? VolumeLabel
.Length
: 11);
391 RtlFreeAnsiString(&VolumeLabel
);
393 memcpy(&BootSector
.SysType
[0], "FAT32 ", 8);
395 RootDirSectors
= ((BootSector
.RootEntries
* 32) +
396 (BootSector
.BytesPerSector
- 1)) / BootSector
.BytesPerSector
;
397 TmpVal1
= BootSector
.SectorsHuge
- (BootSector
.ReservedSectors
+ RootDirSectors
);
398 TmpVal2
= (256 * BootSector
.SectorsPerCluster
) + BootSector
.FATCount
;
399 if (TRUE
/* FAT32 */)
406 TmpVal3
= 0xffffffff;
412 TmpVal2
= ((TmpVal1
- TmpVal2
* BootSector
.FATCount
) / BootSector
.SectorsPerCluster
) + 2;
413 TmpVal2
= (sizeof(ULONG
) * TmpVal2
+ BootSector
.BytesPerSector
- 1) / BootSector
.BytesPerSector
;
415 while (TmpVal3
> TmpVal2
);
416 BootSector
.FATSectors32
= TmpVal2
;
419 Status
= Fat32WriteBootSector(FileHandle
,
421 if (!NT_SUCCESS(Status
))
423 DPRINT("Fat32WriteBootSector() failed with status 0x%.08x\n", Status
);
427 Status
= Fat32WriteFsInfo(FileHandle
,
429 if (!NT_SUCCESS(Status
))
431 DPRINT("Fat32WriteFsInfo() failed with status 0x%.08x\n", Status
);
435 /* Write first FAT copy */
436 Status
= Fat32WriteFAT(FileHandle
,
439 if (!NT_SUCCESS(Status
))
441 DPRINT("Fat32WriteFAT() failed with status 0x%.08x\n", Status
);
445 /* Write second FAT copy */
446 Status
= Fat32WriteFAT(FileHandle
,
447 BootSector
.FATSectors32
,
449 if (!NT_SUCCESS(Status
))
451 DPRINT("Fat32WriteFAT() failed with status 0x%.08x.\n", Status
);
455 Status
= Fat32WriteRootDirectory(FileHandle
,
457 if (!NT_SUCCESS(Status
))
459 DPRINT("Fat32WriteRootDirectory() failed with status 0x%.08x\n", Status
);