2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS VFATX filesystem library
5 * PURPOSE: Fatx support
15 GetShiftCount(IN ULONG Value
)
30 CalcVolumeSerialNumber(VOID
)
32 LARGE_INTEGER SystemTime
;
33 TIME_FIELDS TimeFields
;
37 NtQuerySystemTime (&SystemTime
);
38 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
40 Buffer
= (PUCHAR
)&Serial
;
41 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
42 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
43 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
44 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
51 FatxWriteBootSector(IN HANDLE FileHandle
,
52 IN PFATX_BOOT_SECTOR BootSector
,
53 IN OUT PFORMAT_CONTEXT Context
)
55 IO_STATUS_BLOCK IoStatusBlock
;
58 LARGE_INTEGER FileOffset
;
60 /* Allocate buffer for new bootsector */
61 NewBootSector
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
63 sizeof(FATX_BOOT_SECTOR
));
64 if (NewBootSector
== NULL
)
65 return STATUS_INSUFFICIENT_RESOURCES
;
67 /* Zero the new bootsector */
68 memset(NewBootSector
, 0, sizeof(FATX_BOOT_SECTOR
));
70 /* Copy FAT16 BPB to new bootsector */
71 memcpy(NewBootSector
, BootSector
, 18); /* FAT16 BPB length (up to (not including) Res2) */
74 FileOffset
.QuadPart
= 0ULL;
75 Status
= NtWriteFile(FileHandle
,
81 sizeof(FATX_BOOT_SECTOR
),
84 if (!NT_SUCCESS(Status
))
86 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
87 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector
);
91 VfatxUpdateProgress(Context
, 1);
93 /* Free the new boot sector */
94 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector
);
101 Fatx16WriteFAT(IN HANDLE FileHandle
,
102 IN ULONG SectorOffset
,
104 IN OUT PFORMAT_CONTEXT Context
)
106 IO_STATUS_BLOCK IoStatusBlock
;
109 LARGE_INTEGER FileOffset
;
113 /* Allocate buffer */
114 Buffer
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
118 return STATUS_INSUFFICIENT_RESOURCES
;
120 /* Zero the buffer */
121 memset(Buffer
, 0, 32 * 1024);
124 Buffer
[0] = 0xf8; /* Media type */
128 Buffer
[2] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
131 /* Write first sector of the FAT */
132 FileOffset
.QuadPart
= (SectorOffset
* 512) + sizeof(FATX_BOOT_SECTOR
);
133 Status
= NtWriteFile(FileHandle
,
142 if (!NT_SUCCESS(Status
))
144 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
145 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
149 VfatxUpdateProgress(Context
, 1);
151 /* Zero the begin of the buffer */
152 memset(Buffer
, 0, 4);
154 /* Zero the rest of the FAT */
155 Sectors
= 32 * 1024 / 512;
156 for (i
= 1; i
< FATSectors
; i
+= Sectors
)
158 /* Zero some sectors of the FAT */
159 FileOffset
.QuadPart
= (SectorOffset
+ i
) * 512 + sizeof(FATX_BOOT_SECTOR
) ;
160 if ((FATSectors
- i
) <= Sectors
)
162 Sectors
= FATSectors
- i
;
165 Status
= NtWriteFile(FileHandle
,
174 if (!NT_SUCCESS(Status
))
176 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
177 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
181 VfatxUpdateProgress(Context
, Sectors
);
184 /* Free the buffer */
185 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
191 Fatx32WriteFAT(IN HANDLE FileHandle
,
192 IN ULONG SectorOffset
,
194 IN OUT PFORMAT_CONTEXT Context
)
196 IO_STATUS_BLOCK IoStatusBlock
;
199 LARGE_INTEGER FileOffset
;
203 /* Allocate buffer */
204 Buffer
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
208 return STATUS_INSUFFICIENT_RESOURCES
;
210 /* Zero the buffer */
211 memset(Buffer
, 0, 64 * 1024);
214 Buffer
[0] = 0xf8; /* Media type */
220 Buffer
[4] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
225 /* Write first sector of the FAT */
226 FileOffset
.QuadPart
= (SectorOffset
* 512) + sizeof(FATX_BOOT_SECTOR
);
227 Status
= NtWriteFile(FileHandle
,
236 if (!NT_SUCCESS(Status
))
238 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
239 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
243 VfatxUpdateProgress(Context
, 1);
245 /* Zero the begin of the buffer */
246 memset(Buffer
, 0, 8);
248 /* Zero the rest of the FAT */
249 Sectors
= 64 * 1024 / 512;
250 for (i
= 1; i
< FATSectors
; i
+= Sectors
)
252 /* Zero some sectors of the FAT */
253 FileOffset
.QuadPart
= (SectorOffset
+ i
) * 512 + sizeof(FATX_BOOT_SECTOR
);
255 if ((FATSectors
- i
) <= Sectors
)
257 Sectors
= FATSectors
- i
;
260 Status
= NtWriteFile(FileHandle
,
269 if (!NT_SUCCESS(Status
))
271 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
272 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
276 VfatxUpdateProgress(Context
, Sectors
);
279 /* Free the buffer */
280 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
286 FatxWriteRootDirectory(IN HANDLE FileHandle
,
288 IN OUT PFORMAT_CONTEXT Context
)
290 IO_STATUS_BLOCK IoStatusBlock
;
291 NTSTATUS Status
= STATUS_SUCCESS
;
293 LARGE_INTEGER FileOffset
;
294 ULONG FirstRootDirSector
;
295 ULONG RootDirSectors
;
298 RootDirSectors
= 256 * 64 / 512;
299 FirstRootDirSector
= sizeof(FATX_BOOT_SECTOR
) / 512 + FATSectors
;
301 DPRINT("RootDirSectors = %lu\n", RootDirSectors
);
302 DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector
);
304 /* Allocate buffer for the cluster */
305 Buffer
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
307 RootDirSectors
* 512);
309 return STATUS_INSUFFICIENT_RESOURCES
;
311 /* Zero the buffer */
312 memset(Buffer
, 0xff, RootDirSectors
* 512);
314 /* Zero some sectors of the root directory */
315 FileOffset
.QuadPart
= FirstRootDirSector
* 512;
317 Status
= NtWriteFile(FileHandle
,
323 RootDirSectors
* 512,
326 if (!NT_SUCCESS(Status
))
328 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
331 /* Free the buffer */
332 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
339 FatxFormat(IN HANDLE FileHandle
,
340 IN PPARTITION_INFORMATION PartitionInfo
,
341 IN PDISK_GEOMETRY DiskGeometry
,
342 IN BOOLEAN QuickFormat
,
343 IN OUT PFORMAT_CONTEXT Context
)
345 FATX_BOOT_SECTOR BootSector
;
346 ULONGLONG SectorCount
;
348 ULONG RootDirSectors
;
352 SectorCount
= PartitionInfo
->PartitionLength
.QuadPart
>> GetShiftCount(512); /* Use shifting to avoid 64-bit division */
354 memset(&BootSector
, 0, sizeof(FATX_BOOT_SECTOR
));
355 memcpy(&BootSector
.SysType
[0], "FATX", 4);
356 BootSector
.SectorsPerCluster
= 32;
357 BootSector
.FATCount
= 1;
358 BootSector
.VolumeID
= CalcVolumeSerialNumber();
359 RootDirSectors
= 256 * 64 / 512;
361 /* Calculate number of FAT sectors */
362 ClusterCount
= SectorCount
>> GetShiftCount(32);
364 if (ClusterCount
> 65525)
366 FATSectors
= (((ClusterCount
* 4) + 4095) & ~4095) >> GetShiftCount(512);
370 FATSectors
= (((ClusterCount
* 2) + 4095) & ~4095) >> GetShiftCount(512);
372 DPRINT("FATSectors = %hu\n", FATSectors
);
374 /* Init context data */
377 Context
->TotalSectorCount
=
378 1 + FATSectors
+ RootDirSectors
;
382 Context
->TotalSectorCount
= SectorCount
;
385 Status
= FatxWriteBootSector(FileHandle
,
388 if (!NT_SUCCESS(Status
))
390 DPRINT("FatxWriteBootSector() failed with status 0x%.08x\n", Status
);
394 /* Write first FAT copy */
395 if (ClusterCount
> 65525)
397 Status
= Fatx32WriteFAT(FileHandle
,
404 Status
= Fatx16WriteFAT(FileHandle
,
410 if (!NT_SUCCESS(Status
))
412 DPRINT("FatxWriteFAT() failed with status 0x%.08x\n", Status
);
416 Status
= FatxWriteRootDirectory(FileHandle
,
419 if (!NT_SUCCESS(Status
))
421 DPRINT("FatxWriteRootDirectory() failed with status 0x%.08x\n", Status
);
426 /* FIXME: Fill remaining sectors */