1 /* $Id: iface.c,v 1.50 2001/03/06 08:19:58 ekohl Exp $
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)
10 * 24-10-1998 Fixed bugs in long filename support
11 * Fixed a bug that prevented unsuccessful file open requests
13 * Now works with long filenames that span over a sector
15 * 28-10-1998 Reads entire FAT into memory
16 * VFatReadSector modified to read in more than one sector at a
18 * 7-11-1998 Fixed bug that assumed that directory data could be
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
27 /* INCLUDES *****************************************************************/
29 #include <ddk/ntddk.h>
36 /* GLOBALS *****************************************************************/
38 static PDRIVER_OBJECT VfatDriverObject
;
40 /* FUNCTIONS ****************************************************************/
43 VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount
,
44 PBOOLEAN RecognizedFS
)
46 * FUNCTION: Tests if the device contains a filesystem that can be mounted
53 Boot
= ExAllocatePool(NonPagedPool
, 512);
55 Status
= VfatReadSectors(DeviceToMount
, 0, 1, (UCHAR
*) Boot
);
56 if (!NT_SUCCESS(Status
))
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)
70 *RecognizedFS
= FALSE
;
75 return STATUS_SUCCESS
;
80 VfatMountDevice (PDEVICE_EXTENSION DeviceExt
, PDEVICE_OBJECT DeviceToMount
)
82 * FUNCTION: Mounts the device
87 DPRINT("Mounting VFAT device...");
88 DPRINT("DeviceExt %x\n", DeviceExt
);
90 DeviceExt
->Boot
= ExAllocatePool(NonPagedPool
, 512);
92 Status
= VfatReadSectors(DeviceToMount
, 0, 1, (UCHAR
*) DeviceExt
->Boot
);
93 if (!NT_SUCCESS(Status
))
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
;
110 if (DeviceExt
->BytesPerCluster
>= PAGESIZE
&&
111 (DeviceExt
->BytesPerCluster
% PAGESIZE
) != 0)
113 DbgPrint("Invalid cluster size\n");
116 else if (DeviceExt
->BytesPerCluster
< PAGESIZE
&&
117 (PAGESIZE
% DeviceExt
->BytesPerCluster
) != 0)
119 DbgPrint("Invalid cluster size2\n");
123 if (strncmp (DeviceExt
->Boot
->SysType
, "FAT12", 5) == 0)
126 DeviceExt
->FatType
= FAT12
;
129 (((struct _BootSector32
*) (DeviceExt
->Boot
))->SysType
, "FAT32",
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
;
143 DeviceExt
->FatType
= FAT16
;
146 return STATUS_SUCCESS
;
151 VfatMount (PDEVICE_OBJECT DeviceToMount
)
153 * FUNCTION: Mount the filesystem
156 PDEVICE_OBJECT DeviceObject
;
157 PDEVICE_EXTENSION DeviceExt
;
158 BOOLEAN RecognizedFS
;
161 Status
= VfatHasFileSystem (DeviceToMount
, &RecognizedFS
);
162 if (!NT_SUCCESS(Status
))
167 if (RecognizedFS
== FALSE
)
169 DPRINT("VFAT: Unrecognized Volume\n");
170 return STATUS_UNRECOGNIZED_VOLUME
;
173 DPRINT("VFAT: Recognized volume\n");
175 Status
= IoCreateDevice(VfatDriverObject
,
176 sizeof (DEVICE_EXTENSION
),
178 FILE_DEVICE_FILE_SYSTEM
,
182 if (!NT_SUCCESS(Status
))
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
))
194 /* FIXME: delete device object */
198 DeviceObject
->Vpb
->Flags
|= VPB_MOUNTED
;
199 DeviceExt
->StorageDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
201 DeviceExt
->StreamStorageDevice
= IoCreateStreamFileObject(NULL
,
202 DeviceExt
->StorageDevice
);
203 Status
= CcInitializeFileCache(DeviceExt
->StreamStorageDevice
,
204 &DeviceExt
->StorageBcb
,
206 if (!NT_SUCCESS(Status
))
208 /* FIXME: delete device object */
212 if (DeviceExt
->FatType
== FAT12
)
214 DeviceExt
->Fat12StorageDevice
=
215 IoCreateStreamFileObject(NULL
, DeviceExt
->StorageDevice
);
216 Status
= CcInitializeFileCache(DeviceExt
->Fat12StorageDevice
,
217 &DeviceExt
->Fat12StorageBcb
,
219 if (!NT_SUCCESS(Status
))
221 /* FIXME: delete device object */
225 ExInitializeResourceLite (&DeviceExt
->DirResource
);
226 ExInitializeResourceLite (&DeviceExt
->FatResource
);
228 KeInitializeSpinLock (&DeviceExt
->FcbListLock
);
229 InitializeListHead (&DeviceExt
->FcbListHead
);
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
;
239 /* read volume label */
240 ReadVolumeLabel(DeviceExt
, DeviceObject
->Vpb
);
242 return STATUS_SUCCESS
;
247 VfatFileSystemControl (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
249 * FUNCTION: File system control
252 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation (Irp
);
255 switch (Stack
->MinorFunction
)
257 case IRP_MN_USER_FS_REQUEST
:
258 DPRINT1("VFAT FSC: IRP_MN_USER_FS_REQUEST\n");
259 Status
= STATUS_INVALID_DEVICE_REQUEST
;
262 case IRP_MN_MOUNT_VOLUME
:
263 Status
= VfatMount(Stack
->Parameters
.Mount
.DeviceObject
);
266 case IRP_MN_VERIFY_VOLUME
:
267 DPRINT1("VFAT FSC: IRP_MN_VERIFY_VOLUME\n");
268 Status
= STATUS_INVALID_DEVICE_REQUEST
;
272 DPRINT1("VFAT FSC: MinorFunction %d\n", Stack
->MinorFunction
);
273 Status
= STATUS_INVALID_DEVICE_REQUEST
;
277 Irp
->IoStatus
.Status
= Status
;
278 Irp
->IoStatus
.Information
= 0;
280 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
286 DriverEntry (PDRIVER_OBJECT _DriverObject
, PUNICODE_STRING RegistryPath
)
288 * FUNCTION: Called by the system to initalize the driver
290 * DriverObject = object describing this driver
291 * RegistryPath = path to our configuration entries
292 * RETURNS: Success or failure
295 PDEVICE_OBJECT DeviceObject
;
296 UNICODE_STRING DeviceName
;
299 DbgPrint("VFAT 0.0.6\n");
301 VfatDriverObject
= _DriverObject
;
303 RtlInitUnicodeString(&DeviceName
,
305 Status
= IoCreateDevice(VfatDriverObject
,
308 FILE_DEVICE_FILE_SYSTEM
,
312 if (!NT_SUCCESS(Status
))
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
] =
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
;
334 VfatDriverObject
->DriverUnload
= NULL
;
336 IoRegisterFileSystem(DeviceObject
);
338 return STATUS_SUCCESS
;