bf443d7eb45f35f1581279bb6f5f01a22d957a55
[reactos.git] / lib / fslib / vfatlib / vfatlib.c
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS VFAT filesystem library
4  * FILE:        vfatlib.c
5  * PURPOSE:     Main API
6  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * REVISIONS:
8  *   CSH 05/04-2003 Created
9  */
10 #define NDEBUG
11 #include <debug.h>
12 #define NTOS_MODE_USER
13 #include <ntos.h>
14 #include <ddk/ntddscsi.h>
15 #include <fslib/vfatlib.h>
16 #include "vfatlib.h"
17
18
19 NTSTATUS
20 VfatInitialize(VOID)
21 {
22   DPRINT("VfatInitialize()\n");
23
24   return STATUS_SUCCESS;
25 }
26
27
28 NTSTATUS
29 VfatFormat(
30         PUNICODE_STRING  DriveRoot,
31         DWORD  MediaFlag,
32         PUNICODE_STRING  Label,
33         BOOL  QuickFormat,
34         DWORD  ClusterSize,
35         PFMIFSCALLBACK  Callback)
36 {
37   OBJECT_ATTRIBUTES ObjectAttributes;
38   DISK_GEOMETRY DiskGeometry;
39   IO_STATUS_BLOCK Iosb;
40   HANDLE FileHandle;
41   PARTITION_INFORMATION PartitionInfo;
42   NTSTATUS Status;
43
44   DPRINT("VfatFormat(DriveRoot '%wZ')\n", DriveRoot);
45
46   InitializeObjectAttributes(&ObjectAttributes,
47     DriveRoot,
48     0,
49     NULL,
50     NULL);
51
52   Status = NtOpenFile(&FileHandle,
53     FILE_WRITE_ACCESS | FILE_WRITE_ATTRIBUTES,
54     &ObjectAttributes,
55     &Iosb,
56     1,
57     FILE_SYNCHRONOUS_IO_ALERT);
58   if (!NT_SUCCESS(Status))
59     {
60       DPRINT("NtOpenFile() failed with status 0x%.08x\n", Status);
61       return Status;
62     }
63
64   Status = NtDeviceIoControlFile(FileHandle,
65     NULL,
66     NULL,
67     NULL,
68     &Iosb,
69     IOCTL_DISK_GET_DRIVE_GEOMETRY,
70     NULL,
71     0,
72     &DiskGeometry,
73     sizeof(DISK_GEOMETRY));
74   if (!NT_SUCCESS(Status))
75     {
76       DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY failed with status 0x%.08x\n", Status);
77       NtClose(FileHandle);
78       return Status;
79     }
80
81   if (DiskGeometry.MediaType == FixedMedia)
82     {
83       DPRINT("Cylinders %I64d\n", DiskGeometry.Cylinders.QuadPart);
84       DPRINT("TracksPerCylinder %ld\n", DiskGeometry.TracksPerCylinder);
85       DPRINT("SectorsPerTrack %ld\n", DiskGeometry.SectorsPerTrack);
86       DPRINT("BytesPerSector %ld\n", DiskGeometry.BytesPerSector);
87       DPRINT("DiskSize %I64d\n",
88         DiskGeometry.Cylinders.QuadPart *
89         (ULONGLONG)DiskGeometry.TracksPerCylinder *
90         (ULONGLONG)DiskGeometry.SectorsPerTrack *
91         (ULONGLONG)DiskGeometry.BytesPerSector);
92
93       Status = NtDeviceIoControlFile(FileHandle,
94         NULL,
95         NULL,
96         NULL,
97         &Iosb,
98         IOCTL_DISK_GET_PARTITION_INFO,
99         NULL,
100         0,
101         &PartitionInfo,
102         sizeof(PARTITION_INFORMATION));
103       if (!NT_SUCCESS(Status))
104         {
105           DPRINT("IOCTL_DISK_GET_PARTITION_INFO failed with status 0x%.08x\n", Status);
106           NtClose(FileHandle);
107           return Status;
108         }
109
110       /*
111        * FIXME: This is a hack!
112        *        Partitioning software MUST set the correct number of hidden sectors!
113        */
114       PartitionInfo.HiddenSectors = DiskGeometry.SectorsPerTrack;
115     }
116   else
117     {
118       PartitionInfo.PartitionType = 0;
119       PartitionInfo.StartingOffset.QuadPart = 0ULL;
120       PartitionInfo.PartitionLength.QuadPart =
121         DiskGeometry.Cylinders.QuadPart *
122         (ULONGLONG)DiskGeometry.TracksPerCylinder *
123         (ULONGLONG)DiskGeometry.SectorsPerTrack *
124         (ULONGLONG)DiskGeometry.BytesPerSector;
125       PartitionInfo.HiddenSectors = 0;
126       PartitionInfo.PartitionNumber = 0;
127       PartitionInfo.BootIndicator = FALSE;
128       PartitionInfo.RewritePartition = FALSE;
129       PartitionInfo.RecognizedPartition = FALSE;
130     }
131
132   DPRINT("PartitionType 0x%x\n", PartitionInfo.PartitionType);
133   DPRINT("StartingOffset %I64d\n", PartitionInfo.StartingOffset.QuadPart);
134   DPRINT("PartitionLength %I64d\n", PartitionInfo.PartitionLength.QuadPart);
135   DPRINT("HiddenSectors %lu\n", PartitionInfo.HiddenSectors);
136   DPRINT("PartitionNumber %d\n", PartitionInfo.PartitionNumber);
137   DPRINT("BootIndicator 0x%x\n", PartitionInfo.BootIndicator);
138   DPRINT("RewritePartition %d\n", PartitionInfo.RewritePartition);
139   DPRINT("RecognizedPartition %d\n", PartitionInfo.RecognizedPartition);
140
141   if (PartitionInfo.PartitionLength.QuadPart < (4200ULL * 1024ULL))
142     {
143       /* FAT12 (volume is smaller than 4.1MB) */
144       Status = Fat12Format (FileHandle,
145                             &PartitionInfo,
146                             &DiskGeometry,
147                             Label,
148                             QuickFormat,
149                             ClusterSize,
150                             Callback);
151     }
152   else if (PartitionInfo.PartitionLength.QuadPart < (512ULL * 1024ULL * 1024ULL))
153     {
154       /* FAT16 (volume is smaller than 512MB) */
155       Status = Fat16Format (FileHandle,
156                             &PartitionInfo,
157                             &DiskGeometry,
158                             Label,
159                             QuickFormat,
160                             ClusterSize,
161                             Callback);
162     }
163   else
164     {
165       /* FAT32 (volume is 512MB or larger) */
166       Status = Fat32Format (FileHandle,
167                             &PartitionInfo,
168                             &DiskGeometry,
169                             Label,
170                             QuickFormat,
171                             ClusterSize,
172                             Callback);
173     }
174
175   NtClose(FileHandle);
176
177   DPRINT("VfatFormat() done. Status 0x%.08x\n", Status);
178
179   return Status;
180 }
181
182
183 NTSTATUS
184 VfatCleanup(VOID)
185 {
186   DPRINT("VfatCleanup()\n");
187
188   return STATUS_SUCCESS;
189 }