2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS VFATX filesystem library
5 * PURPOSE: Fatx support
15 GetShiftCount(ULONG Value
)
28 CalcVolumeSerialNumber(VOID
)
30 LARGE_INTEGER SystemTime
;
31 TIME_FIELDS TimeFields
;
35 NtQuerySystemTime (&SystemTime
);
36 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
38 Buffer
= (PUCHAR
)&Serial
;
39 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
40 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
41 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
42 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
49 FatxWriteBootSector (IN HANDLE FileHandle
,
50 IN PFATX_BOOT_SECTOR BootSector
,
51 IN OUT PFORMAT_CONTEXT Context
)
53 IO_STATUS_BLOCK IoStatusBlock
;
56 LARGE_INTEGER FileOffset
;
58 /* Allocate buffer for new bootsector */
59 NewBootSector
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
61 sizeof(FATX_BOOT_SECTOR
));
62 if (NewBootSector
== NULL
)
63 return(STATUS_INSUFFICIENT_RESOURCES
);
65 /* Zero the new bootsector */
66 memset(NewBootSector
, 0, sizeof(FATX_BOOT_SECTOR
));
68 /* Copy FAT16 BPB to new bootsector */
69 memcpy(NewBootSector
, BootSector
, 18); /* FAT16 BPB length (up to (not including) Res2) */
72 FileOffset
.QuadPart
= 0ULL;
73 Status
= NtWriteFile(FileHandle
,
79 sizeof(FATX_BOOT_SECTOR
),
82 if (!NT_SUCCESS(Status
))
84 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
85 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector
);
89 VfatxUpdateProgress (Context
, 1);
91 /* Free the new boot sector */
92 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector
);
99 Fatx16WriteFAT (IN HANDLE FileHandle
,
100 IN ULONG SectorOffset
,
102 IN OUT PFORMAT_CONTEXT Context
)
104 IO_STATUS_BLOCK IoStatusBlock
;
107 LARGE_INTEGER FileOffset
;
111 /* Allocate buffer */
112 Buffer
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
116 return(STATUS_INSUFFICIENT_RESOURCES
);
118 /* Zero the buffer */
119 memset(Buffer
, 0, 32 * 1024);
122 Buffer
[0] = 0xf8; /* Media type */
126 Buffer
[2] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
129 /* Write first sector of the FAT */
130 FileOffset
.QuadPart
= (SectorOffset
* 512) + sizeof(FATX_BOOT_SECTOR
);
131 Status
= NtWriteFile(FileHandle
,
140 if (!NT_SUCCESS(Status
))
142 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
143 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
147 VfatxUpdateProgress (Context
, 1);
149 /* Zero the begin of the buffer */
150 memset(Buffer
, 0, 4);
152 /* Zero the rest of the FAT */
153 Sectors
= 32 * 1024 / 512;
154 for (i
= 1; i
< FATSectors
; i
+= Sectors
)
156 /* Zero some sectors of the FAT */
157 FileOffset
.QuadPart
= (SectorOffset
+ i
) * 512 + sizeof(FATX_BOOT_SECTOR
) ;
158 if ((FATSectors
- i
) <= Sectors
)
160 Sectors
= FATSectors
- i
;
163 Status
= NtWriteFile(FileHandle
,
172 if (!NT_SUCCESS(Status
))
174 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
175 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
179 VfatxUpdateProgress (Context
, Sectors
);
182 /* Free the buffer */
183 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
189 Fatx32WriteFAT (IN HANDLE FileHandle
,
190 IN ULONG SectorOffset
,
192 IN OUT PFORMAT_CONTEXT Context
)
194 IO_STATUS_BLOCK IoStatusBlock
;
197 LARGE_INTEGER FileOffset
;
201 /* Allocate buffer */
202 Buffer
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
206 return(STATUS_INSUFFICIENT_RESOURCES
);
208 /* Zero the buffer */
209 memset(Buffer
, 0, 64 * 1024);
212 Buffer
[0] = 0xf8; /* Media type */
217 Buffer
[4] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
222 /* Write first sector of the FAT */
223 FileOffset
.QuadPart
= (SectorOffset
* 512) + sizeof(FATX_BOOT_SECTOR
);
224 Status
= NtWriteFile(FileHandle
,
233 if (!NT_SUCCESS(Status
))
235 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
236 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
240 VfatxUpdateProgress (Context
, 1);
242 /* Zero the begin of the buffer */
243 memset(Buffer
, 0, 8);
245 /* Zero the rest of the FAT */
246 Sectors
= 64 * 1024 / 512;
247 for (i
= 1; i
< FATSectors
; i
+= Sectors
)
249 /* Zero some sectors of the FAT */
250 FileOffset
.QuadPart
= (SectorOffset
+ i
) * 512 + sizeof(FATX_BOOT_SECTOR
);
252 if ((FATSectors
- i
) <= Sectors
)
254 Sectors
= FATSectors
- i
;
257 Status
= NtWriteFile(FileHandle
,
266 if (!NT_SUCCESS(Status
))
268 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
269 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
273 VfatxUpdateProgress (Context
, Sectors
);
276 /* Free the buffer */
277 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
283 FatxWriteRootDirectory (IN HANDLE FileHandle
,
285 IN OUT PFORMAT_CONTEXT Context
)
287 IO_STATUS_BLOCK IoStatusBlock
;
288 NTSTATUS Status
= STATUS_SUCCESS
;
290 LARGE_INTEGER FileOffset
;
291 ULONG FirstRootDirSector
;
292 ULONG RootDirSectors
;
295 RootDirSectors
= 256 * 64 / 512;
296 FirstRootDirSector
= sizeof(FATX_BOOT_SECTOR
) / 512 + FATSectors
;
298 DPRINT("RootDirSectors = %lu\n", RootDirSectors
);
299 DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector
);
301 /* Allocate buffer for the cluster */
302 Buffer
= (PUCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
304 RootDirSectors
* 512);
306 return(STATUS_INSUFFICIENT_RESOURCES
);
308 /* Zero the buffer */
309 memset(Buffer
, 0xff, RootDirSectors
* 512);
311 /* Zero some sectors of the root directory */
312 FileOffset
.QuadPart
= FirstRootDirSector
* 512;
314 Status
= NtWriteFile(FileHandle
,
320 RootDirSectors
* 512,
323 if (!NT_SUCCESS(Status
))
325 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
328 /* Free the buffer */
329 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
336 FatxFormat (HANDLE FileHandle
,
337 PPARTITION_INFORMATION PartitionInfo
,
338 PDISK_GEOMETRY DiskGeometry
,
340 PFORMAT_CONTEXT Context
)
342 FATX_BOOT_SECTOR BootSector
;
343 ULONGLONG SectorCount
;
345 ULONG RootDirSectors
;
350 SectorCount
= PartitionInfo
->PartitionLength
.QuadPart
>> GetShiftCount(512); /* Use shifting to avoid 64-bit division */
352 memset(&BootSector
, 0, sizeof(FATX_BOOT_SECTOR
));
353 memcpy(&BootSector
.SysType
[0], "FATX", 4);
354 BootSector
.SectorsPerCluster
= 32;
355 BootSector
.FATCount
= 1;
356 BootSector
.VolumeID
= CalcVolumeSerialNumber();
357 RootDirSectors
= 256 * 64 / 512;
359 /* Calculate number of FAT sectors */
360 ClusterCount
= SectorCount
>> GetShiftCount(32);
362 if (ClusterCount
> 65525)
364 FATSectors
= (((ClusterCount
* 4) + 4095) & ~4095) >> GetShiftCount(512);
368 FATSectors
= (((ClusterCount
* 2) + 4095) & ~4095) >> GetShiftCount(512);
370 DPRINT("FATSectors = %hu\n", FATSectors
);
372 /* Init context data */
375 Context
->TotalSectorCount
=
376 1 + FATSectors
+ RootDirSectors
;
380 Context
->TotalSectorCount
= SectorCount
;
383 Status
= FatxWriteBootSector (FileHandle
,
386 if (!NT_SUCCESS(Status
))
388 DPRINT("FatxWriteBootSector() failed with status 0x%.08x\n", Status
);
392 /* Write first FAT copy */
393 if (ClusterCount
> 65525)
395 Status
= Fatx32WriteFAT (FileHandle
,
402 Status
= Fatx16WriteFAT (FileHandle
,
407 if (!NT_SUCCESS(Status
))
409 DPRINT("FatxWriteFAT() failed with status 0x%.08x\n", Status
);
413 Status
= FatxWriteRootDirectory (FileHandle
,
416 if (!NT_SUCCESS(Status
))
418 DPRINT("FatxWriteRootDirectory() failed with status 0x%.08x\n", Status
);
423 /* FIXME: Fill remaining sectors */