ReactOS 0.4.15-dev-7924-g5949c20
fatx.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS VFATX filesystem library
4 * FILE: fatx.c
5 * PURPOSE: Fatx support
6 * PROGRAMMERS:
7 * REVISIONS:
8 */
9
10#include "vfatxlib.h"
11
12#include <ndk/kefuncs.h>
13#include <ndk/rtlfuncs.h>
14
15#define NDEBUG
16#include <debug.h>
17
18static ULONG
20{
21 ULONG i = 1;
22
23 while (Value > 0)
24 {
25 i++;
26 Value /= 2;
27 }
28
29 return i - 2;
30}
31
32
33static ULONG
35{
36 LARGE_INTEGER SystemTime;
38 ULONG Serial;
40
41 NtQuerySystemTime (&SystemTime);
42 RtlTimeToTimeFields (&SystemTime, &TimeFields);
43
44 Buffer = (PUCHAR)&Serial;
45 Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
46 Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
47 Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
48 Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
49
50 return Serial;
51}
52
53
54static NTSTATUS
58{
61 PUCHAR NewBootSector;
63
64 /* Allocate buffer for new bootsector */
65 NewBootSector = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
66 0,
67 sizeof(FATX_BOOT_SECTOR));
68 if (NewBootSector == NULL)
70
71 /* Zero the new bootsector */
72 memset(NewBootSector, 0, sizeof(FATX_BOOT_SECTOR));
73
74 /* Copy FAT16 BPB to new bootsector */
75 memcpy(NewBootSector, BootSector, 18); /* FAT16 BPB length (up to (not including) Res2) */
76
77 /* Write sector 0 */
78 FileOffset.QuadPart = 0ULL;
80 NULL,
81 NULL,
82 NULL,
84 NewBootSector,
85 sizeof(FATX_BOOT_SECTOR),
87 NULL);
88 if (!NT_SUCCESS(Status))
89 {
90 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
91 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
92 return Status;
93 }
94
96
97 /* Free the new boot sector */
98 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
99
100 return Status;
101}
102
103
104static NTSTATUS
107 IN ULONG FATSectors,
109{
114 ULONG i;
115 ULONG Sectors;
116
117 /* Allocate buffer */
118 Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
119 0,
120 32 * 1024);
121 if (Buffer == NULL)
123
124 /* Zero the buffer */
125 memset(Buffer, 0, 32 * 1024);
126
127 /* FAT cluster 0 */
128 Buffer[0] = 0xf8; /* Media type */
129 Buffer[1] = 0xff;
130
131 /* FAT cluster 1 */
132 Buffer[2] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
133 Buffer[3] = 0xff;
134
135 /* Write first sector of the FAT */
136 FileOffset.QuadPart = (SectorOffset * 512) + sizeof(FATX_BOOT_SECTOR);
138 NULL,
139 NULL,
140 NULL,
142 Buffer,
143 512,
144 &FileOffset,
145 NULL);
146 if (!NT_SUCCESS(Status))
147 {
148 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
149 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
150 return Status;
151 }
152
154
155 /* Zero the begin of the buffer */
156 memset(Buffer, 0, 4);
157
158 /* Zero the rest of the FAT */
159 Sectors = 32 * 1024 / 512;
160 for (i = 1; i < FATSectors; i += Sectors)
161 {
162 /* Zero some sectors of the FAT */
163 FileOffset.QuadPart = (SectorOffset + i) * 512 + sizeof(FATX_BOOT_SECTOR) ;
164 if ((FATSectors - i) <= Sectors)
165 {
166 Sectors = FATSectors - i;
167 }
168
170 NULL,
171 NULL,
172 NULL,
174 Buffer,
175 Sectors * 512,
176 &FileOffset,
177 NULL);
178 if (!NT_SUCCESS(Status))
179 {
180 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
181 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
182 return Status;
183 }
184
186 }
187
188 /* Free the buffer */
189 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
190
191 return Status;
192}
193
194static NTSTATUS
197 IN ULONG FATSectors,
199{
204 ULONG i;
205 ULONG Sectors;
206
207 /* Allocate buffer */
208 Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
209 0,
210 64 * 1024);
211 if (Buffer == NULL)
213
214 /* Zero the buffer */
215 memset(Buffer, 0, 64 * 1024);
216
217 /* FAT cluster 0 */
218 Buffer[0] = 0xf8; /* Media type */
219 Buffer[1] = 0xff;
220 Buffer[2] = 0xff;
221 Buffer[3] = 0x0f;
222
223 /* FAT cluster 1 */
224 Buffer[4] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
225 Buffer[5] = 0xff;
226 Buffer[6] = 0xff;
227 Buffer[7] = 0x0f;
228
229 /* Write first sector of the FAT */
230 FileOffset.QuadPart = (SectorOffset * 512) + sizeof(FATX_BOOT_SECTOR);
232 NULL,
233 NULL,
234 NULL,
236 Buffer,
237 512,
238 &FileOffset,
239 NULL);
240 if (!NT_SUCCESS(Status))
241 {
242 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
243 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
244 return Status;
245 }
246
248
249 /* Zero the begin of the buffer */
250 memset(Buffer, 0, 8);
251
252 /* Zero the rest of the FAT */
253 Sectors = 64 * 1024 / 512;
254 for (i = 1; i < FATSectors; i += Sectors)
255 {
256 /* Zero some sectors of the FAT */
257 FileOffset.QuadPart = (SectorOffset + i) * 512 + sizeof(FATX_BOOT_SECTOR);
258
259 if ((FATSectors - i) <= Sectors)
260 {
261 Sectors = FATSectors - i;
262 }
263
265 NULL,
266 NULL,
267 NULL,
269 Buffer,
270 Sectors * 512,
271 &FileOffset,
272 NULL);
273 if (!NT_SUCCESS(Status))
274 {
275 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
276 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
277 return Status;
278 }
279
281 }
282
283 /* Free the buffer */
284 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
285
286 return Status;
287}
288
289static NTSTATUS
291 IN ULONG FATSectors,
293{
298 ULONG FirstRootDirSector;
299 ULONG RootDirSectors;
300
301 /* Write cluster */
302 RootDirSectors = 256 * 64 / 512;
303 FirstRootDirSector = sizeof(FATX_BOOT_SECTOR) / 512 + FATSectors;
304
305 DPRINT("RootDirSectors = %lu\n", RootDirSectors);
306 DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector);
307
308 /* Allocate buffer for the cluster */
309 Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
310 0,
311 RootDirSectors * 512);
312 if (Buffer == NULL)
314
315 /* Zero the buffer */
316 memset(Buffer, 0xff, RootDirSectors * 512);
317
318 /* Zero some sectors of the root directory */
319 FileOffset.QuadPart = FirstRootDirSector * 512;
320
322 NULL,
323 NULL,
324 NULL,
326 Buffer,
327 RootDirSectors * 512,
328 &FileOffset,
329 NULL);
330 if (!NT_SUCCESS(Status))
331 {
332 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
333 }
334
335 /* Free the buffer */
336 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
337
338 return Status;
339}
340
341
345 IN PDISK_GEOMETRY DiskGeometry,
348{
351 ULONG ClusterCount;
352 ULONG RootDirSectors;
353 ULONG FATSectors;
355
356 SectorCount = PartitionInfo->PartitionLength.QuadPart >> GetShiftCount(512); /* Use shifting to avoid 64-bit division */
357
358 memset(&BootSector, 0, sizeof(FATX_BOOT_SECTOR));
359 memcpy(&BootSector.SysType[0], "FATX", 4);
361 BootSector.FATCount = 1;
363 RootDirSectors = 256 * 64 / 512;
364
365 /* Calculate number of FAT sectors */
366 ClusterCount = SectorCount >> GetShiftCount(32);
367
368 if (ClusterCount > 65525)
369 {
370 FATSectors = (((ClusterCount * 4) + 4095) & ~4095) >> GetShiftCount(512);
371 }
372 else
373 {
374 FATSectors = (((ClusterCount * 2) + 4095) & ~4095) >> GetShiftCount(512);
375 }
376 DPRINT("FATSectors = %hu\n", FATSectors);
377
378 /* Init context data */
379 if (QuickFormat)
380 {
381 Context->TotalSectorCount =
382 1 + FATSectors + RootDirSectors;
383 }
384 else
385 {
386 Context->TotalSectorCount = SectorCount;
387 }
388
390 &BootSector,
391 Context);
392 if (!NT_SUCCESS(Status))
393 {
394 DPRINT("FatxWriteBootSector() failed with status 0x%.08x\n", Status);
395 return Status;
396 }
397
398 /* Write first FAT copy */
399 if (ClusterCount > 65525)
400 {
402 0,
403 FATSectors,
404 Context);
405 }
406 else
407 {
409 0,
410 FATSectors,
411 Context);
412 }
413
414 if (!NT_SUCCESS(Status))
415 {
416 DPRINT("FatxWriteFAT() failed with status 0x%.08x\n", Status);
417 return Status;
418 }
419
421 FATSectors,
422 Context);
423 if (!NT_SUCCESS(Status))
424 {
425 DPRINT("FatxWriteRootDirectory() failed with status 0x%.08x\n", Status);
426 }
427
428 if (!QuickFormat)
429 {
430 /* FIXME: Fill remaining sectors */
431 }
432
433 return Status;
434}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
BOOL QuickFormat
Definition: format.c:66
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
#define SectorOffset(L)
Definition: cdprocs.h:1622
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct _FATX_BOOT_SECTOR FATX_BOOT_SECTOR
BOOLEAN RtlTimeToTimeFields(IN PLARGE_INTEGER Time, IN PTIME_FIELDS TimeFields)
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ULL(a, b)
Definition: format_msg.c:27
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
static PTIME_FIELDS TimeFields
Definition: time.c:104
NTSYSAPI NTSTATUS NTAPI NtWriteFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID WriteBuffer, IN ULONG WriteBufferLength, IN PLARGE_INTEGER FileOffset OPTIONAL, IN PULONG LockOperationKey OPTIONAL)
NTSTATUS NTAPI NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
Definition: time.c:483
ULONG SectorCount
Definition: part_xbox.c:31
static NTSTATUS FatxWriteRootDirectory(IN HANDLE FileHandle, IN ULONG FATSectors, IN OUT PFORMAT_CONTEXT Context)
Definition: fatx.c:290
static ULONG GetShiftCount(IN ULONG Value)
Definition: fatx.c:19
static NTSTATUS Fatx16WriteFAT(IN HANDLE FileHandle, IN ULONG SectorOffset, IN ULONG FATSectors, IN OUT PFORMAT_CONTEXT Context)
Definition: fatx.c:105
static NTSTATUS Fatx32WriteFAT(IN HANDLE FileHandle, IN ULONG SectorOffset, IN ULONG FATSectors, IN OUT PFORMAT_CONTEXT Context)
Definition: fatx.c:195
NTSTATUS FatxFormat(IN HANDLE FileHandle, IN PPARTITION_INFORMATION PartitionInfo, IN PDISK_GEOMETRY DiskGeometry, IN BOOLEAN QuickFormat, IN OUT PFORMAT_CONTEXT Context)
Definition: fatx.c:343
static ULONG CalcVolumeSerialNumber(VOID)
Definition: fatx.c:34
static NTSTATUS FatxWriteBootSector(IN HANDLE FileHandle, IN PFATX_BOOT_SECTOR BootSector, IN OUT PFORMAT_CONTEXT Context)
Definition: fatx.c:55
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
BYTE SectorsPerCluster
Definition: fatfs.h:76
USHORT Milliseconds
Definition: env_spec_w32.h:717
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
VOID VfatxUpdateProgress(IN PFORMAT_CONTEXT Context, IN ULONG Increment)
Definition: vfatxlib.c:181
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
unsigned char UCHAR
Definition: xmlstorage.h:181