Fixed typos
[reactos.git] / reactos / drivers / fs / vfat / iface.c
1 /* $Id: iface.c,v 1.50 2001/03/06 08:19:58 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/vfat/iface.c
6 * PURPOSE: VFAT Filesystem
7 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
8 * UPDATE HISTORY:
9 * ?? Created
10 * 24-10-1998 Fixed bugs in long filename support
11 * Fixed a bug that prevented unsuccessful file open requests
12 * being reported
13 * Now works with long filenames that span over a sector
14 * boundary
15 * 28-10-1998 Reads entire FAT into memory
16 * VFatReadSector modified to read in more than one sector at a
17 * time
18 * 7-11-1998 Fixed bug that assumed that directory data could be
19 * fragmented
20 * 8-12-1998 Added FAT32 support
21 * Added initial writability functions
22 * WARNING: DO NOT ATTEMPT TO TEST WRITABILITY FUNCTIONS!!!
23 * 12-12-1998 Added basic support for FILE_STANDARD_INFORMATION request
24 *
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include <ddk/ntddk.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34 #include "vfat.h"
35
36 /* GLOBALS *****************************************************************/
37
38 static PDRIVER_OBJECT VfatDriverObject;
39
40 /* FUNCTIONS ****************************************************************/
41
42 static NTSTATUS
43 VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
44 PBOOLEAN RecognizedFS)
45 /*
46 * FUNCTION: Tests if the device contains a filesystem that can be mounted
47 * by this fsd
48 */
49 {
50 BootSector *Boot;
51 NTSTATUS Status;
52
53 Boot = ExAllocatePool(NonPagedPool, 512);
54
55 Status = VfatReadSectors(DeviceToMount, 0, 1, (UCHAR *) Boot);
56 if (!NT_SUCCESS(Status))
57 {
58 return Status;
59 }
60
61 DPRINT("Boot->SysType %.5s\n", Boot->SysType);
62 if (strncmp(Boot->SysType, "FAT12", 5) == 0 ||
63 strncmp(Boot->SysType, "FAT16", 5) == 0 ||
64 strncmp(((struct _BootSector32 *) (Boot))->SysType, "FAT32", 5) == 0)
65 {
66 *RecognizedFS = TRUE;
67 }
68 else
69 {
70 *RecognizedFS = FALSE;
71 }
72
73 ExFreePool(Boot);
74
75 return STATUS_SUCCESS;
76 }
77
78
79 static NTSTATUS
80 VfatMountDevice (PDEVICE_EXTENSION DeviceExt, PDEVICE_OBJECT DeviceToMount)
81 /*
82 * FUNCTION: Mounts the device
83 */
84 {
85 NTSTATUS Status;
86
87 DPRINT("Mounting VFAT device...");
88 DPRINT("DeviceExt %x\n", DeviceExt);
89
90 DeviceExt->Boot = ExAllocatePool(NonPagedPool, 512);
91
92 Status = VfatReadSectors(DeviceToMount, 0, 1, (UCHAR *) DeviceExt->Boot);
93 if (!NT_SUCCESS(Status))
94 {
95 return Status;
96 }
97
98 DeviceExt->FATStart = DeviceExt->Boot->ReservedSectors;
99 DeviceExt->rootDirectorySectors =
100 (DeviceExt->Boot->RootEntries * 32) / DeviceExt->Boot->BytesPerSector;
101 DeviceExt->rootStart =
102 DeviceExt->FATStart +
103 DeviceExt->Boot->FATCount * DeviceExt->Boot->FATSectors;
104 DeviceExt->dataStart =
105 DeviceExt->rootStart + DeviceExt->rootDirectorySectors;
106 DeviceExt->FATEntriesPerSector = DeviceExt->Boot->BytesPerSector / 32;
107 DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster *
108 DeviceExt->Boot->BytesPerSector;
109
110 if (DeviceExt->BytesPerCluster >= PAGESIZE &&
111 (DeviceExt->BytesPerCluster % PAGESIZE) != 0)
112 {
113 DbgPrint("Invalid cluster size\n");
114 KeBugCheck(0);
115 }
116 else if (DeviceExt->BytesPerCluster < PAGESIZE &&
117 (PAGESIZE % DeviceExt->BytesPerCluster) != 0)
118 {
119 DbgPrint("Invalid cluster size2\n");
120 KeBugCheck(0);
121 }
122
123 if (strncmp (DeviceExt->Boot->SysType, "FAT12", 5) == 0)
124 {
125 DbgPrint("FAT12\n");
126 DeviceExt->FatType = FAT12;
127 }
128 else if (strncmp
129 (((struct _BootSector32 *) (DeviceExt->Boot))->SysType, "FAT32",
130 5) == 0)
131 {
132 DbgPrint("FAT32\n");
133 DeviceExt->FatType = FAT32;
134 DeviceExt->rootDirectorySectors = DeviceExt->Boot->SectorsPerCluster;
135 DeviceExt->rootStart =
136 DeviceExt->FATStart + DeviceExt->Boot->FATCount
137 * ((struct _BootSector32 *) (DeviceExt->Boot))->FATSectors32;
138 DeviceExt->dataStart = DeviceExt->rootStart;
139 }
140 else
141 {
142 DbgPrint("FAT16\n");
143 DeviceExt->FatType = FAT16;
144 }
145
146 return STATUS_SUCCESS;
147 }
148
149
150 static NTSTATUS
151 VfatMount (PDEVICE_OBJECT DeviceToMount)
152 /*
153 * FUNCTION: Mount the filesystem
154 */
155 {
156 PDEVICE_OBJECT DeviceObject;
157 PDEVICE_EXTENSION DeviceExt;
158 BOOLEAN RecognizedFS;
159 NTSTATUS Status;
160
161 Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS);
162 if (!NT_SUCCESS(Status))
163 {
164 return Status;
165 }
166
167 if (RecognizedFS == FALSE)
168 {
169 DPRINT("VFAT: Unrecognized Volume\n");
170 return STATUS_UNRECOGNIZED_VOLUME;
171 }
172
173 DPRINT("VFAT: Recognized volume\n");
174
175 Status = IoCreateDevice(VfatDriverObject,
176 sizeof (DEVICE_EXTENSION),
177 NULL,
178 FILE_DEVICE_FILE_SYSTEM,
179 0,
180 FALSE,
181 &DeviceObject);
182 if (!NT_SUCCESS(Status))
183 {
184 return Status;
185 }
186
187 DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
188 DeviceExt = (PVOID) DeviceObject->DeviceExtension;
189 /* use same vpb as device disk */
190 DeviceObject->Vpb = DeviceToMount->Vpb;
191 Status = VfatMountDevice (DeviceExt, DeviceToMount);
192 if (!NT_SUCCESS(Status))
193 {
194 /* FIXME: delete device object */
195 return Status;
196 }
197
198 DeviceObject->Vpb->Flags |= VPB_MOUNTED;
199 DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
200 DeviceToMount);
201 DeviceExt->StreamStorageDevice = IoCreateStreamFileObject(NULL,
202 DeviceExt->StorageDevice);
203 Status = CcInitializeFileCache(DeviceExt->StreamStorageDevice,
204 &DeviceExt->StorageBcb,
205 PAGESIZE);
206 if (!NT_SUCCESS(Status))
207 {
208 /* FIXME: delete device object */
209 return Status;
210 }
211
212 if (DeviceExt->FatType == FAT12)
213 {
214 DeviceExt->Fat12StorageDevice =
215 IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
216 Status = CcInitializeFileCache(DeviceExt->Fat12StorageDevice,
217 &DeviceExt->Fat12StorageBcb,
218 PAGESIZE * 3);
219 if (!NT_SUCCESS(Status))
220 {
221 /* FIXME: delete device object */
222 return Status;
223 }
224 }
225 ExInitializeResourceLite (&DeviceExt->DirResource);
226 ExInitializeResourceLite (&DeviceExt->FatResource);
227
228 KeInitializeSpinLock (&DeviceExt->FcbListLock);
229 InitializeListHead (&DeviceExt->FcbListHead);
230
231 /* read serial number */
232 if (DeviceExt->FatType == FAT12 || DeviceExt->FatType == FAT16)
233 DeviceObject->Vpb->SerialNumber =
234 ((struct _BootSector *) (DeviceExt->Boot))->VolumeID;
235 else if (DeviceExt->FatType == FAT32)
236 DeviceObject->Vpb->SerialNumber =
237 ((struct _BootSector32 *) (DeviceExt->Boot))->VolumeID;
238
239 /* read volume label */
240 ReadVolumeLabel(DeviceExt, DeviceObject->Vpb);
241
242 return STATUS_SUCCESS;
243 }
244
245
246 NTSTATUS STDCALL
247 VfatFileSystemControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
248 /*
249 * FUNCTION: File system control
250 */
251 {
252 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation (Irp);
253 NTSTATUS Status;
254
255 switch (Stack->MinorFunction)
256 {
257 case IRP_MN_USER_FS_REQUEST:
258 DPRINT1("VFAT FSC: IRP_MN_USER_FS_REQUEST\n");
259 Status = STATUS_INVALID_DEVICE_REQUEST;
260 break;
261
262 case IRP_MN_MOUNT_VOLUME:
263 Status = VfatMount(Stack->Parameters.Mount.DeviceObject);
264 break;
265
266 case IRP_MN_VERIFY_VOLUME:
267 DPRINT1("VFAT FSC: IRP_MN_VERIFY_VOLUME\n");
268 Status = STATUS_INVALID_DEVICE_REQUEST;
269 break;
270
271 default:
272 DPRINT1("VFAT FSC: MinorFunction %d\n", Stack->MinorFunction);
273 Status = STATUS_INVALID_DEVICE_REQUEST;
274 break;
275 }
276
277 Irp->IoStatus.Status = Status;
278 Irp->IoStatus.Information = 0;
279
280 IoCompleteRequest (Irp, IO_NO_INCREMENT);
281 return (Status);
282 }
283
284
285 NTSTATUS STDCALL
286 DriverEntry (PDRIVER_OBJECT _DriverObject, PUNICODE_STRING RegistryPath)
287 /*
288 * FUNCTION: Called by the system to initalize the driver
289 * ARGUMENTS:
290 * DriverObject = object describing this driver
291 * RegistryPath = path to our configuration entries
292 * RETURNS: Success or failure
293 */
294 {
295 PDEVICE_OBJECT DeviceObject;
296 UNICODE_STRING DeviceName;
297 NTSTATUS Status;
298
299 DbgPrint("VFAT 0.0.6\n");
300
301 VfatDriverObject = _DriverObject;
302
303 RtlInitUnicodeString(&DeviceName,
304 L"\\Device\\Vfat");
305 Status = IoCreateDevice(VfatDriverObject,
306 0,
307 &DeviceName,
308 FILE_DEVICE_FILE_SYSTEM,
309 0,
310 FALSE,
311 &DeviceObject);
312 if (!NT_SUCCESS(Status))
313 {
314 return (Status);
315 }
316
317 DeviceObject->Flags = DO_DIRECT_IO;
318 VfatDriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatClose;
319 VfatDriverObject->MajorFunction[IRP_MJ_CREATE] = VfatCreate;
320 VfatDriverObject->MajorFunction[IRP_MJ_READ] = VfatRead;
321 VfatDriverObject->MajorFunction[IRP_MJ_WRITE] = VfatWrite;
322 VfatDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
323 VfatFileSystemControl;
324 VfatDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
325 VfatQueryInformation;
326 VfatDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
327 VfatSetInformation;
328 VfatDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
329 VfatDirectoryControl;
330 VfatDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
331 VfatQueryVolumeInformation;
332 VfatDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = VfatShutdown;
333
334 VfatDriverObject->DriverUnload = NULL;
335
336 IoRegisterFileSystem(DeviceObject);
337
338 return STATUS_SUCCESS;
339 }
340
341 /* EOF */