ReactOS  0.4.14-dev-552-g2fad488
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 
18 static 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 
33 static ULONG
35 {
36  LARGE_INTEGER SystemTime;
38  ULONG Serial;
39  PUCHAR Buffer;
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 
54 static 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),
86  &FileOffset,
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 
104 static NTSTATUS
107  IN ULONG FATSectors,
109 {
112  PUCHAR Buffer;
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,
141  &IoStatusBlock,
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,
173  &IoStatusBlock,
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 
185  VfatxUpdateProgress(Context, Sectors);
186  }
187 
188  /* Free the buffer */
189  RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
190 
191  return Status;
192 }
193 
194 static NTSTATUS
197  IN ULONG FATSectors,
199 {
202  PUCHAR Buffer;
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,
235  &IoStatusBlock,
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,
268  &IoStatusBlock,
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 
280  VfatxUpdateProgress(Context, Sectors);
281  }
282 
283  /* Free the buffer */
284  RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
285 
286  return Status;
287 }
288 
289 static NTSTATUS
291  IN ULONG FATSectors,
293 {
296  PUCHAR Buffer;
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,
325  &IoStatusBlock,
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 
342 NTSTATUS
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;
362  BootSector.VolumeID = CalcVolumeSerialNumber();
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 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define IN
Definition: typedefs.h:38
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
struct _FATX_BOOT_SECTOR FATX_BOOT_SECTOR
BYTE SectorsPerCluster
Definition: fatfs.h:76
static ULONG GetShiftCount(IN ULONG Value)
Definition: fatx.c:19
static NTSTATUS FatxWriteBootSector(IN HANDLE FileHandle, IN PFATX_BOOT_SECTOR BootSector, IN OUT PFORMAT_CONTEXT Context)
Definition: fatx.c:55
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
static ULONG CalcVolumeSerialNumber(VOID)
Definition: fatx.c:34
struct _BootSector BootSector
Definition: vfat.h:108
HANDLE FileHandle
Definition: stats.c:38
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
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 NTSTATUS Fatx16WriteFAT(IN HANDLE FileHandle, IN ULONG SectorOffset, IN ULONG FATSectors, IN OUT PFORMAT_CONTEXT Context)
Definition: fatx.c:105
#define SectorOffset(L)
Definition: cdprocs.h:1632
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
USHORT Milliseconds
Definition: env_spec_w32.h:717
BOOL QuickFormat
Definition: format.c:66
#define ULL(a, b)
Definition: format_msg.c:27
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
BOOLEAN RtlTimeToTimeFields(IN PLARGE_INTEGER Time, IN PTIME_FIELDS TimeFields)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t ULONGLONG
Definition: typedefs.h:65
VOID VfatxUpdateProgress(IN PFORMAT_CONTEXT Context, IN ULONG Increment)
Definition: vfatxlib.c:168
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2101
unsigned char UCHAR
Definition: xmlstorage.h:181
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)
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
ULONG SectorCount
Definition: part_xbox.c:32
Status
Definition: gdiplustypes.h:24
static NTSTATUS FatxWriteRootDirectory(IN HANDLE FileHandle, IN ULONG FATSectors, IN OUT PFORMAT_CONTEXT Context)
Definition: fatx.c:290
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:151
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS NTAPI NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
Definition: time.c:417
static NTSTATUS Fatx32WriteFAT(IN HANDLE FileHandle, IN ULONG SectorOffset, IN ULONG FATSectors, IN OUT PFORMAT_CONTEXT Context)
Definition: fatx.c:195
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
static PTIME_FIELDS TimeFields
Definition: time.c:104
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define memset(x, y, z)
Definition: compat.h:39