1 /* $Id: iface.c,v 1.55 2001/07/13 10:31:14 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 #define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \
39 (pDeviceExt)->BytesPerCluster : PAGESIZE)
41 static PDRIVER_OBJECT VfatDriverObject
;
43 /* FUNCTIONS ****************************************************************/
46 VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount
,
47 PBOOLEAN RecognizedFS
)
49 * FUNCTION: Tests if the device contains a filesystem that can be mounted
56 Boot
= ExAllocatePool(NonPagedPool
, 512);
58 Status
= VfatReadSectors(DeviceToMount
, 0, 1, (UCHAR
*) Boot
);
59 if (!NT_SUCCESS(Status
))
64 DPRINT("Boot->SysType %.5s\n", Boot
->SysType
);
65 if (strncmp(Boot
->SysType
, "FAT12", 5) == 0 ||
66 strncmp(Boot
->SysType
, "FAT16", 5) == 0 ||
67 strncmp(((struct _BootSector32
*) (Boot
))->SysType
, "FAT32", 5) == 0)
73 *RecognizedFS
= FALSE
;
78 return STATUS_SUCCESS
;
83 VfatMountDevice (PDEVICE_EXTENSION DeviceExt
, PDEVICE_OBJECT DeviceToMount
)
85 * FUNCTION: Mounts the device
90 DPRINT("Mounting VFAT device...");
91 DPRINT("DeviceExt %x\n", DeviceExt
);
93 DeviceExt
->Boot
= ExAllocatePool(NonPagedPool
, 512);
95 Status
= VfatReadSectors(DeviceToMount
, 0, 1, (UCHAR
*) DeviceExt
->Boot
);
96 if (!NT_SUCCESS(Status
))
101 DeviceExt
->FATStart
= DeviceExt
->Boot
->ReservedSectors
;
102 DeviceExt
->rootDirectorySectors
=
103 (DeviceExt
->Boot
->RootEntries
* 32) / DeviceExt
->Boot
->BytesPerSector
;
104 DeviceExt
->rootStart
=
105 DeviceExt
->FATStart
+
106 DeviceExt
->Boot
->FATCount
* DeviceExt
->Boot
->FATSectors
;
107 DeviceExt
->dataStart
=
108 DeviceExt
->rootStart
+ DeviceExt
->rootDirectorySectors
;
109 DeviceExt
->BytesPerSector
= DeviceExt
->Boot
->BytesPerSector
;
110 DeviceExt
->FATEntriesPerSector
= DeviceExt
->Boot
->BytesPerSector
/ 32;
111 DeviceExt
->BytesPerCluster
= DeviceExt
->Boot
->SectorsPerCluster
*
112 DeviceExt
->Boot
->BytesPerSector
;
114 if (DeviceExt
->BytesPerCluster
>= PAGESIZE
&&
115 (DeviceExt
->BytesPerCluster
% PAGESIZE
) != 0)
117 DbgPrint("Invalid cluster size\n");
120 else if (DeviceExt
->BytesPerCluster
< PAGESIZE
&&
121 (PAGESIZE
% DeviceExt
->BytesPerCluster
) != 0)
123 DbgPrint("Invalid cluster size2\n");
127 if (strncmp (DeviceExt
->Boot
->SysType
, "FAT12", 5) == 0)
130 DeviceExt
->FatType
= FAT12
;
133 (((struct _BootSector32
*) (DeviceExt
->Boot
))->SysType
, "FAT32",
137 DeviceExt
->FatType
= FAT32
;
138 DeviceExt
->rootDirectorySectors
= DeviceExt
->Boot
->SectorsPerCluster
;
139 DeviceExt
->rootStart
=
140 DeviceExt
->FATStart
+ DeviceExt
->Boot
->FATCount
141 * ((struct _BootSector32
*) (DeviceExt
->Boot
))->FATSectors32
;
142 DeviceExt
->dataStart
= DeviceExt
->rootStart
;
147 DeviceExt
->FatType
= FAT16
;
150 return STATUS_SUCCESS
;
155 VfatMount (PDEVICE_OBJECT DeviceToMount
)
157 * FUNCTION: Mount the filesystem
160 PDEVICE_OBJECT DeviceObject
;
161 PDEVICE_EXTENSION DeviceExt
;
162 BOOLEAN RecognizedFS
;
165 Status
= VfatHasFileSystem (DeviceToMount
, &RecognizedFS
);
166 if (!NT_SUCCESS(Status
))
171 if (RecognizedFS
== FALSE
)
173 DPRINT("VFAT: Unrecognized Volume\n");
174 return STATUS_UNRECOGNIZED_VOLUME
;
177 DPRINT("VFAT: Recognized volume\n");
179 Status
= IoCreateDevice(VfatDriverObject
,
180 sizeof (DEVICE_EXTENSION
),
182 FILE_DEVICE_FILE_SYSTEM
,
186 if (!NT_SUCCESS(Status
))
191 DeviceObject
->Flags
= DeviceObject
->Flags
| DO_DIRECT_IO
;
192 DeviceExt
= (PVOID
) DeviceObject
->DeviceExtension
;
193 /* use same vpb as device disk */
194 DeviceObject
->Vpb
= DeviceToMount
->Vpb
;
195 Status
= VfatMountDevice (DeviceExt
, DeviceToMount
);
196 if (!NT_SUCCESS(Status
))
198 /* FIXME: delete device object */
202 DeviceObject
->Vpb
->Flags
|= VPB_MOUNTED
;
203 DeviceExt
->StorageDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
205 DeviceExt
->StreamStorageDevice
= IoCreateStreamFileObject(NULL
,
206 DeviceExt
->StorageDevice
);
207 Status
= CcRosInitializeFileCache(DeviceExt
->StreamStorageDevice
,
208 &DeviceExt
->StorageBcb
,
209 CACHEPAGESIZE(DeviceExt
));
210 if (!NT_SUCCESS(Status
))
212 /* FIXME: delete device object */
216 if (DeviceExt
->FatType
== FAT12
)
218 DeviceExt
->Fat12StorageDevice
=
219 IoCreateStreamFileObject(NULL
, DeviceExt
->StorageDevice
);
220 Status
= CcRosInitializeFileCache(DeviceExt
->Fat12StorageDevice
,
221 &DeviceExt
->Fat12StorageBcb
,
223 if (!NT_SUCCESS(Status
))
225 /* FIXME: delete device object */
229 ExInitializeResourceLite (&DeviceExt
->DirResource
);
230 ExInitializeResourceLite (&DeviceExt
->FatResource
);
232 KeInitializeSpinLock (&DeviceExt
->FcbListLock
);
233 InitializeListHead (&DeviceExt
->FcbListHead
);
235 /* read serial number */
236 if (DeviceExt
->FatType
== FAT12
|| DeviceExt
->FatType
== FAT16
)
237 DeviceObject
->Vpb
->SerialNumber
=
238 ((struct _BootSector
*) (DeviceExt
->Boot
))->VolumeID
;
239 else if (DeviceExt
->FatType
== FAT32
)
240 DeviceObject
->Vpb
->SerialNumber
=
241 ((struct _BootSector32
*) (DeviceExt
->Boot
))->VolumeID
;
243 /* read volume label */
244 ReadVolumeLabel(DeviceExt
, DeviceObject
->Vpb
);
246 return STATUS_SUCCESS
;
251 VfatFileSystemControl (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
253 * FUNCTION: File system control
256 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation (Irp
);
259 switch (Stack
->MinorFunction
)
261 case IRP_MN_USER_FS_REQUEST
:
262 DPRINT1("VFAT FSC: IRP_MN_USER_FS_REQUEST\n");
263 Status
= STATUS_INVALID_DEVICE_REQUEST
;
266 case IRP_MN_MOUNT_VOLUME
:
267 Status
= VfatMount(Stack
->Parameters
.Mount
.DeviceObject
);
270 case IRP_MN_VERIFY_VOLUME
:
271 DPRINT1("VFAT FSC: IRP_MN_VERIFY_VOLUME\n");
272 Status
= STATUS_INVALID_DEVICE_REQUEST
;
276 DPRINT1("VFAT FSC: MinorFunction %d\n", Stack
->MinorFunction
);
277 Status
= STATUS_INVALID_DEVICE_REQUEST
;
281 Irp
->IoStatus
.Status
= Status
;
282 Irp
->IoStatus
.Information
= 0;
284 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
290 DriverEntry(PDRIVER_OBJECT _DriverObject
,
291 PUNICODE_STRING RegistryPath
)
293 * FUNCTION: Called by the system to initalize the driver
295 * DriverObject = object describing this driver
296 * RegistryPath = path to our configuration entries
297 * RETURNS: Success or failure
300 PDEVICE_OBJECT DeviceObject
;
301 UNICODE_STRING DeviceName
;
304 DbgPrint("VFAT 0.0.6\n");
306 VfatDriverObject
= _DriverObject
;
308 RtlInitUnicodeString(&DeviceName
,
310 Status
= IoCreateDevice(VfatDriverObject
,
313 FILE_DEVICE_FILE_SYSTEM
,
317 if (!NT_SUCCESS(Status
))
322 DeviceObject
->Flags
= DO_DIRECT_IO
;
323 VfatDriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = VfatClose
;
324 VfatDriverObject
->MajorFunction
[IRP_MJ_CREATE
] = VfatCreate
;
325 VfatDriverObject
->MajorFunction
[IRP_MJ_READ
] = VfatRead
;
326 VfatDriverObject
->MajorFunction
[IRP_MJ_WRITE
] = VfatWrite
;
327 VfatDriverObject
->MajorFunction
[IRP_MJ_FILE_SYSTEM_CONTROL
] =
328 VfatFileSystemControl
;
329 VfatDriverObject
->MajorFunction
[IRP_MJ_QUERY_INFORMATION
] =
330 VfatQueryInformation
;
331 VfatDriverObject
->MajorFunction
[IRP_MJ_SET_INFORMATION
] =
333 VfatDriverObject
->MajorFunction
[IRP_MJ_DIRECTORY_CONTROL
] =
334 VfatDirectoryControl
;
335 VfatDriverObject
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] =
336 VfatQueryVolumeInformation
;
337 VfatDriverObject
->MajorFunction
[IRP_MJ_SET_VOLUME_INFORMATION
] =
338 VfatSetVolumeInformation
;
339 VfatDriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = VfatShutdown
;
340 VfatDriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = VfatCleanup
;
342 VfatDriverObject
->DriverUnload
= NULL
;
344 IoRegisterFileSystem(DeviceObject
);
346 return STATUS_SUCCESS
;