ReactOS 0.4.16-dev-250-g3ecd236
fat16.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS VFAT filesystem library
4 * FILE: fat16.c
5 * PURPOSE: Fat16 support
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Eric Kohl
8 */
9
10/* INCLUDES *******************************************************************/
11
12#include "vfatlib.h"
13
14#define NDEBUG
15#include <debug.h>
16
17
18/* FUNCTIONS ******************************************************************/
19
20static NTSTATUS
24{
27 PFAT16_BOOT_SECTOR NewBootSector;
29
30 /* Allocate buffer for new bootsector */
31 NewBootSector = (PFAT16_BOOT_SECTOR)RtlAllocateHeap(RtlGetProcessHeap(),
32 0,
34 if (NewBootSector == NULL)
36
37 /* Zero the new bootsector */
39
40 /* Copy FAT16 BPB to new bootsector */
41 memcpy(NewBootSector, BootSector,
43 /* FAT16 BPB length (up to (not including) Res2) */
44
45 /* Write the boot sector signature */
46 NewBootSector->Signature1 = 0xAA550000;
47
48 /* Write sector 0 */
49 FileOffset.QuadPart = 0ULL;
51 NULL,
52 NULL,
53 NULL,
55 NewBootSector,
58 NULL);
59 if (!NT_SUCCESS(Status))
60 {
61 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
62 goto done;
63 }
64
66
67done:
68 /* Free the buffer */
69 RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector);
70 return Status;
71}
72
73
74static NTSTATUS
79{
84 ULONG i;
85 ULONG Sectors;
86
87 /* Allocate buffer */
88 Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
89 0,
90 32 * 1024);
91 if (Buffer == NULL)
93
94 /* Zero the buffer */
95 RtlZeroMemory(Buffer, 32 * 1024);
96
97 /* FAT cluster 0 */
98 Buffer[0] = 0xf8; /* Media type */
99 Buffer[1] = 0xff;
100
101 /* FAT cluster 1 */
102 Buffer[2] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */
103 Buffer[3] = 0xff;
104
105 /* Write first sector of the FAT */
108 NULL,
109 NULL,
110 NULL,
112 Buffer,
114 &FileOffset,
115 NULL);
116 if (!NT_SUCCESS(Status))
117 {
118 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
119 goto done;
120 }
121
123
124 /* Zero the begin of the buffer */
126
127 /* Zero the rest of the FAT */
128 Sectors = 32 * 1024 / BootSector->BytesPerSector;
129 for (i = 1; i < (ULONG)BootSector->FATSectors; i += Sectors)
130 {
131 /* Zero some sectors of the FAT */
133
134 if (((ULONG)BootSector->FATSectors - i) <= Sectors)
135 {
136 Sectors = (ULONG)BootSector->FATSectors - i;
137 }
138
140 NULL,
141 NULL,
142 NULL,
144 Buffer,
145 Sectors * BootSector->BytesPerSector,
146 &FileOffset,
147 NULL);
148 if (!NT_SUCCESS(Status))
149 {
150 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
151 goto done;
152 }
153
154 UpdateProgress(Context, Sectors);
155 }
156
157done:
158 /* Free the buffer */
159 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
160 return Status;
161}
162
163
164static NTSTATUS
168{
173 ULONG FirstRootDirSector;
174 ULONG RootDirSectors;
175 ULONG Sectors;
176 ULONG i;
177
178 DPRINT("BootSector->ReservedSectors = %hu\n", BootSector->ReservedSectors);
179 DPRINT("BootSector->FATSectors = %hu\n", BootSector->FATSectors);
180 DPRINT("BootSector->SectorsPerCluster = %u\n", BootSector->SectorsPerCluster);
181
182 /* Write cluster */
183 RootDirSectors = ((BootSector->RootEntries * 32) +
185 FirstRootDirSector =
186 BootSector->ReservedSectors + (BootSector->FATCount * BootSector->FATSectors);
187
188 DPRINT("RootDirSectors = %lu\n", RootDirSectors);
189 DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector);
190
191 /* Allocate buffer for the cluster */
192 Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
193 0,
194 32 * 1024);
195 if (Buffer == NULL)
197
198 /* Zero the buffer */
199 RtlZeroMemory(Buffer, 32 * 1024);
200
201 Sectors = 32 * 1024 / BootSector->BytesPerSector;
202 for (i = 0; i < RootDirSectors; i += Sectors)
203 {
204 /* Zero some sectors of the root directory */
205 FileOffset.QuadPart = (FirstRootDirSector + i) * BootSector->BytesPerSector;
206
207 if ((RootDirSectors - i) <= Sectors)
208 {
209 Sectors = RootDirSectors - i;
210 }
211
213 NULL,
214 NULL,
215 NULL,
217 Buffer,
218 Sectors * BootSector->BytesPerSector,
219 &FileOffset,
220 NULL);
221 if (!NT_SUCCESS(Status))
222 {
223 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
224 goto done;
225 }
226
227 UpdateProgress(Context, Sectors);
228 }
229
230done:
231 /* Free the buffer */
232 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
233 return Status;
234}
235
236
240 IN PDISK_GEOMETRY DiskGeometry,
245{
247 OEM_STRING VolumeLabel;
249 ULONG RootDirSectors;
250 ULONG TmpVal1;
251 ULONG TmpVal2;
252 ULONG TmpVal3;
254
255 /* Calculate cluster size */
256 if (ClusterSize == 0)
257 {
258 if (PartitionInfo->PartitionLength.QuadPart < 16LL * 1024LL * 1024LL)
259 {
260 /* Partition < 16MB ==> 1KB Cluster */
261 ClusterSize = 1024;
262 }
263 else if (PartitionInfo->PartitionLength.QuadPart < 128LL * 1024LL * 1024LL)
264 {
265 /* Partition < 128MB ==> 2KB Cluster */
266 ClusterSize = 2048;
267 }
268 else if (PartitionInfo->PartitionLength.QuadPart < 256LL * 1024LL * 1024LL)
269 {
270 /* Partition < 256MB ==> 4KB Cluster */
271 ClusterSize = 4096;
272 }
273 else
274 {
275 /* Partition >= 256MB (< 512MB) ==> 8KB Cluster */
276 ClusterSize = 8192;
277 }
278 }
279
280 SectorCount = PartitionInfo->PartitionLength.QuadPart >>
281 GetShiftCount(DiskGeometry->BytesPerSector); /* Use shifting to avoid 64-bit division */
282
284 memcpy(&BootSector.OEMName[0], "MSWIN4.1", 8);
285 /* FIXME: Add dummy bootloader for real */
286 BootSector.Jump[0] = 0xeb;
287 BootSector.Jump[1] = 0x3c;
288 BootSector.Jump[2] = 0x90;
289 BootSector.BytesPerSector = DiskGeometry->BytesPerSector;
292 BootSector.FATCount = 2;
294 BootSector.Sectors = (SectorCount < 0x10000) ? (unsigned short)SectorCount : 0;
295 BootSector.Media = 0xf8;
296 BootSector.FATSectors = 0; /* Set later. See below. */
297 BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack;
298 BootSector.Heads = DiskGeometry->TracksPerCylinder;
299 BootSector.HiddenSectors = PartitionInfo->HiddenSectors;
300 BootSector.SectorsHuge = (SectorCount >= 0x10000) ? (unsigned long)SectorCount : 0;
301 BootSector.Drive = (DiskGeometry->MediaType == FixedMedia) ? 0x80 : 0x00;
302 BootSector.ExtBootSignature = 0x29;
304 if ((Label == NULL) || (Label->Buffer == NULL))
305 {
306 memcpy(&BootSector.VolumeLabel[0], "NO NAME ", 11);
307 }
308 else
309 {
310 RtlUnicodeStringToOemString(&VolumeLabel, Label, TRUE);
311 RtlFillMemory(&BootSector.VolumeLabel[0], 11, ' ');
312 memcpy(&BootSector.VolumeLabel[0], VolumeLabel.Buffer,
313 VolumeLabel.Length < 11 ? VolumeLabel.Length : 11);
314 RtlFreeOemString(&VolumeLabel);
315 }
316
317 memcpy(&BootSector.SysType[0], "FAT16 ", 8);
318
319 DPRINT("BootSector.SectorsHuge = %lx\n", BootSector.SectorsHuge);
320
321 RootDirSectors = ((BootSector.RootEntries * 32) +
323
324 /* Calculate number of FAT sectors */
325 /* (BootSector.BytesPerSector / 2) FAT entries (16bit) fit into one sector */
326 TmpVal1 = SectorCount - (BootSector.ReservedSectors + RootDirSectors);
327 TmpVal2 = ((BootSector.BytesPerSector / 2) * BootSector.SectorsPerCluster) + BootSector.FATCount;
328 TmpVal3 = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
329 BootSector.FATSectors = (unsigned short)(TmpVal3 & 0xffff);
330 DPRINT("BootSector.FATSectors = %hu\n", BootSector.FATSectors);
331
332 /* Init context data */
333 Context->TotalSectorCount =
334 1 + (BootSector.FATSectors * 2) + RootDirSectors;
335
336 if (!QuickFormat)
337 {
338 Context->TotalSectorCount += SectorCount;
339
344 Context);
345 if (!NT_SUCCESS(Status))
346 {
347 DPRINT("FatWipeSectors() failed with status 0x%.08x\n", Status);
348 return Status;
349 }
350 }
351
353 &BootSector,
354 Context);
355 if (!NT_SUCCESS(Status))
356 {
357 DPRINT("Fat16WriteBootSector() failed with status 0x%.08x\n", Status);
358 return Status;
359 }
360
361 /* Write first FAT copy */
363 0,
364 &BootSector,
365 Context);
366 if (!NT_SUCCESS(Status))
367 {
368 DPRINT("Fat16WriteFAT() failed with status 0x%.08x\n", Status);
369 return Status;
370 }
371
372 /* Write second FAT copy */
374 (ULONG)BootSector.FATSectors,
375 &BootSector,
376 Context);
377 if (!NT_SUCCESS(Status))
378 {
379 DPRINT("Fat16WriteFAT() failed with status 0x%.08x.\n", Status);
380 return Status;
381 }
382
384 &BootSector,
385 Context);
386 if (!NT_SUCCESS(Status))
387 {
388 DPRINT("Fat16WriteRootDirectory() failed with status 0x%.08x\n", Status);
389 }
390
391 return Status;
392}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
BOOL QuickFormat
Definition: format.c:66
PWCHAR Label
Definition: format.c:70
DWORD ClusterSize
Definition: format.c:67
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 TRUE
Definition: types.h:120
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
static NTSTATUS Fat16WriteBootSector(IN HANDLE FileHandle, IN PFAT16_BOOT_SECTOR BootSector, IN OUT PFORMAT_CONTEXT Context)
Definition: fat16.c:21
static NTSTATUS Fat16WriteFAT(IN HANDLE FileHandle, IN ULONG SectorOffset, IN PFAT16_BOOT_SECTOR BootSector, IN OUT PFORMAT_CONTEXT Context)
Definition: fat16.c:75
NTSTATUS Fat16Format(IN HANDLE FileHandle, IN PPARTITION_INFORMATION PartitionInfo, IN PDISK_GEOMETRY DiskGeometry, IN PUNICODE_STRING Label, IN BOOLEAN QuickFormat, IN ULONG ClusterSize, IN OUT PFORMAT_CONTEXT Context)
Definition: fat16.c:238
static NTSTATUS Fat16WriteRootDirectory(IN HANDLE FileHandle, IN PFAT16_BOOT_SECTOR BootSector, IN OUT PFORMAT_CONTEXT Context)
Definition: fat16.c:165
_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
VOID NTAPI RtlFreeOemString(POEM_STRING OemString)
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599
struct _FAT16_BOOT_SECTOR * PFAT16_BOOT_SECTOR
if(dx< 0)
Definition: linetemp.h:194
#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
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
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)
@ FixedMedia
Definition: ntdddisk.h:383
ULONG SectorCount
Definition: part_xbox.c:31
ULONG GetShiftCount(IN ULONG Value)
Definition: common.c:21
NTSTATUS FatWipeSectors(IN HANDLE FileHandle, IN ULONG TotalSectors, IN ULONG SectorsPerCluster, IN ULONG BytesPerSector, IN OUT PFORMAT_CONTEXT Context)
Definition: common.c:56
ULONG CalcVolumeSerialNumber(VOID)
Definition: common.c:35
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
WORD Heads
Definition: fatfs.h:84
WORD RootEntries
Definition: fatfs.h:79
DWORD HiddenSectors
Definition: fatfs.h:85
WORD SectorsPerTrack
Definition: fatfs.h:83
WORD ReservedSectors
Definition: fatfs.h:77
BYTE SectorsPerCluster
Definition: fatfs.h:76
WORD BytesPerSector
Definition: fatfs.h:75
unsigned long Signature1
Definition: vfatlib.h:51
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
STRING OEM_STRING
Definition: umtypes.h:203
VOID UpdateProgress(PFORMAT_CONTEXT Context, ULONG Increment)
Definition: vfatlib.c:321
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105