1 /* $Id: iface.c,v 1.58 2001/10/10 22:18:58 hbirr 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
,
84 PDEVICE_OBJECT DeviceToMount
)
86 * FUNCTION: Mounts the device
91 DPRINT("Mounting VFAT device...");
92 DPRINT("DeviceExt %x\n", DeviceExt
);
94 DeviceExt
->Boot
= ExAllocatePool(NonPagedPool
, 512);
96 Status
= VfatReadSectors(DeviceToMount
, 0, 1, (UCHAR
*) DeviceExt
->Boot
);
97 if (!NT_SUCCESS(Status
))
102 DeviceExt
->FATStart
= DeviceExt
->Boot
->ReservedSectors
;
103 DeviceExt
->rootDirectorySectors
=
104 (DeviceExt
->Boot
->RootEntries
* 32) / DeviceExt
->Boot
->BytesPerSector
;
105 DeviceExt
->rootStart
=
106 DeviceExt
->FATStart
+
107 DeviceExt
->Boot
->FATCount
* DeviceExt
->Boot
->FATSectors
;
108 DeviceExt
->dataStart
=
109 DeviceExt
->rootStart
+ DeviceExt
->rootDirectorySectors
;
110 DeviceExt
->BytesPerSector
= DeviceExt
->Boot
->BytesPerSector
;
111 DeviceExt
->FATEntriesPerSector
= DeviceExt
->Boot
->BytesPerSector
/ 32;
112 DeviceExt
->BytesPerCluster
= DeviceExt
->Boot
->SectorsPerCluster
*
113 DeviceExt
->Boot
->BytesPerSector
;
115 if (DeviceExt
->BytesPerCluster
>= PAGESIZE
&&
116 (DeviceExt
->BytesPerCluster
% PAGESIZE
) != 0)
118 DbgPrint("Invalid cluster size\n");
121 else if (DeviceExt
->BytesPerCluster
< PAGESIZE
&&
122 (PAGESIZE
% DeviceExt
->BytesPerCluster
) != 0)
124 DbgPrint("Invalid cluster size2\n");
128 if (strncmp (DeviceExt
->Boot
->SysType
, "FAT12", 5) == 0)
131 DeviceExt
->FatType
= FAT12
;
134 (((struct _BootSector32
*) (DeviceExt
->Boot
))->SysType
, "FAT32",
138 DeviceExt
->FatType
= FAT32
;
139 DeviceExt
->rootDirectorySectors
= DeviceExt
->Boot
->SectorsPerCluster
;
140 DeviceExt
->dataStart
= DeviceExt
->FATStart
+ DeviceExt
->Boot
->FATCount
141 * ((struct _BootSector32
*) (DeviceExt
->Boot
))->FATSectors32
;
142 DeviceExt
->rootStart
= ClusterToSector (DeviceExt
,
143 ((struct _BootSector32
*)(DeviceExt
->Boot
))->RootCluster
);
148 DeviceExt
->FatType
= FAT16
;
151 return(STATUS_SUCCESS
);
156 VfatMount (PDEVICE_OBJECT DeviceToMount
)
158 * FUNCTION: Mount the filesystem
161 PDEVICE_OBJECT DeviceObject
;
162 PDEVICE_EXTENSION DeviceExt
;
163 BOOLEAN RecognizedFS
;
168 Status
= VfatHasFileSystem (DeviceToMount
, &RecognizedFS
);
169 if (!NT_SUCCESS(Status
))
174 if (RecognizedFS
== FALSE
)
176 DPRINT("VFAT: Unrecognized Volume\n");
177 return(STATUS_UNRECOGNIZED_VOLUME
);
180 DPRINT("VFAT: Recognized volume\n");
182 Status
= IoCreateDevice(VfatDriverObject
,
183 sizeof (DEVICE_EXTENSION
),
185 FILE_DEVICE_FILE_SYSTEM
,
189 if (!NT_SUCCESS(Status
))
194 DeviceObject
->Flags
= DeviceObject
->Flags
| DO_DIRECT_IO
;
195 DeviceExt
= (PVOID
) DeviceObject
->DeviceExtension
;
196 /* use same vpb as device disk */
197 DeviceObject
->Vpb
= DeviceToMount
->Vpb
;
198 Status
= VfatMountDevice(DeviceExt
,
200 if (!NT_SUCCESS(Status
))
202 /* FIXME: delete device object */
207 DbgPrint("BytesPerSector: %d\n", DeviceExt
->Boot
->BytesPerSector
);
208 DbgPrint("SectorsPerCluster: %d\n", DeviceExt
->Boot
->SectorsPerCluster
);
209 DbgPrint("ReservedSectors: %d\n", DeviceExt
->Boot
->ReservedSectors
);
210 DbgPrint("FATCount: %d\n", DeviceExt
->Boot
->FATCount
);
211 DbgPrint("RootEntries: %d\n", DeviceExt
->Boot
->RootEntries
);
212 DbgPrint("Sectors: %d\n", DeviceExt
->Boot
->Sectors
);
213 DbgPrint("FATSectors: %d\n", DeviceExt
->Boot
->FATSectors
);
214 DbgPrint("SectorsPerTrack: %d\n", DeviceExt
->Boot
->SectorsPerTrack
);
215 DbgPrint("Heads: %d\n", DeviceExt
->Boot
->Heads
);
216 DbgPrint("HiddenSectors: %d\n", DeviceExt
->Boot
->HiddenSectors
);
217 DbgPrint("SectorsHuge: %d\n", DeviceExt
->Boot
->SectorsHuge
);
218 DbgPrint("RootStart: %d\n", DeviceExt
->rootStart
);
219 DbgPrint("DataStart: %d\n", DeviceExt
->dataStart
);
220 if (DeviceExt
->FatType
== FAT32
)
222 DbgPrint("FATSectors32: %d\n",
223 ((struct _BootSector32
*)(DeviceExt
->Boot
))->FATSectors32
);
224 DbgPrint("RootCluster: %d\n",
225 ((struct _BootSector32
*)(DeviceExt
->Boot
))->RootCluster
);
226 DbgPrint("FSInfoSector: %d\n",
227 ((struct _BootSector32
*)(DeviceExt
->Boot
))->FSInfoSector
);
228 DbgPrint("BootBackup: %d\n",
229 ((struct _BootSector32
*)(DeviceExt
->Boot
))->BootBackup
);
232 DeviceObject
->Vpb
->Flags
|= VPB_MOUNTED
;
233 DeviceExt
->StorageDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
236 DeviceExt
->FATFileObject
= IoCreateStreamFileObject(NULL
, DeviceExt
->StorageDevice
);
237 Fcb
= vfatNewFCB(NULL
);
240 return STATUS_INSUFFICIENT_RESOURCES
;
242 Ccb
= ExAllocatePoolWithTag (NonPagedPool
, sizeof (VFATCCB
), TAG_CCB
);
245 return STATUS_INSUFFICIENT_RESOURCES
;
247 memset(Ccb
, 0, sizeof (VFATCCB
));
248 DeviceExt
->FATFileObject
->Flags
= DeviceExt
->FATFileObject
->Flags
| FO_FCB_IS_VALID
| FO_DIRECT_CACHE_PAGING_READ
;
249 DeviceExt
->FATFileObject
->FsContext
= (PVOID
) &Fcb
->RFCB
;
250 DeviceExt
->FATFileObject
->FsContext2
= Ccb
;
252 Ccb
->PtrFileObject
= DeviceExt
->FATFileObject
;
253 Fcb
->FileObject
= DeviceExt
->FATFileObject
;
254 Fcb
->pDevExt
= (PDEVICE_EXTENSION
)DeviceExt
->StorageDevice
;
256 Fcb
->Flags
= FCB_IS_FAT
;
258 if (DeviceExt
->FatType
== FAT32
)
260 Fcb
->RFCB
.FileSize
.QuadPart
= ((struct _BootSector32
*)DeviceExt
->Boot
)->FATSectors32
* BLOCKSIZE
;
261 Fcb
->RFCB
.ValidDataLength
.QuadPart
= ((struct _BootSector32
*)DeviceExt
->Boot
)->FATSectors32
* BLOCKSIZE
;
262 Fcb
->RFCB
.AllocationSize
.QuadPart
= ROUND_UP(((struct _BootSector32
*)DeviceExt
->Boot
)->FATSectors32
* BLOCKSIZE
, CACHEPAGESIZE(DeviceExt
));
263 Status
= CcRosInitializeFileCache(DeviceExt
->FATFileObject
, &Fcb
->RFCB
.Bcb
, CACHEPAGESIZE(DeviceExt
));
267 if (DeviceExt
->FatType
== FAT16
)
269 Fcb
->RFCB
.FileSize
.QuadPart
= DeviceExt
->Boot
->FATSectors
* BLOCKSIZE
;
270 Fcb
->RFCB
.ValidDataLength
.QuadPart
= DeviceExt
->Boot
->FATSectors
* BLOCKSIZE
;
271 Fcb
->RFCB
.AllocationSize
.QuadPart
= ROUND_UP(DeviceExt
->Boot
->FATSectors
* BLOCKSIZE
, CACHEPAGESIZE(DeviceExt
));
272 Status
= CcRosInitializeFileCache(DeviceExt
->FATFileObject
, &Fcb
->RFCB
.Bcb
, CACHEPAGESIZE(DeviceExt
));
276 Fcb
->RFCB
.FileSize
.QuadPart
= DeviceExt
->Boot
->FATSectors
* BLOCKSIZE
;
277 Fcb
->RFCB
.ValidDataLength
.QuadPart
= DeviceExt
->Boot
->FATSectors
* BLOCKSIZE
;
278 Fcb
->RFCB
.AllocationSize
.QuadPart
= 2 * PAGESIZE
;
279 Status
= CcRosInitializeFileCache(DeviceExt
->FATFileObject
, &Fcb
->RFCB
.Bcb
, 2 * PAGESIZE
);
282 if (!NT_SUCCESS (Status
))
284 DbgPrint ("CcRosInitializeFileCache failed\n");
286 // FIXME: delete device object
291 ExInitializeResourceLite(&DeviceExt
->DirResource
);
292 ExInitializeResourceLite(&DeviceExt
->FatResource
);
294 KeInitializeSpinLock(&DeviceExt
->FcbListLock
);
295 InitializeListHead(&DeviceExt
->FcbListHead
);
297 /* read serial number */
298 if (DeviceExt
->FatType
== FAT12
|| DeviceExt
->FatType
== FAT16
)
299 DeviceObject
->Vpb
->SerialNumber
=
300 ((struct _BootSector
*) (DeviceExt
->Boot
))->VolumeID
;
301 else if (DeviceExt
->FatType
== FAT32
)
302 DeviceObject
->Vpb
->SerialNumber
=
303 ((struct _BootSector32
*) (DeviceExt
->Boot
))->VolumeID
;
305 /* read volume label */
306 ReadVolumeLabel(DeviceExt
, DeviceObject
->Vpb
);
308 return(STATUS_SUCCESS
);
313 VfatFileSystemControl(PDEVICE_OBJECT DeviceObject
,
316 * FUNCTION: File system control
319 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation (Irp
);
322 switch (Stack
->MinorFunction
)
324 case IRP_MN_USER_FS_REQUEST
:
325 DPRINT1("VFAT FSC: IRP_MN_USER_FS_REQUEST\n");
326 Status
= STATUS_INVALID_DEVICE_REQUEST
;
329 case IRP_MN_MOUNT_VOLUME
:
330 Status
= VfatMount(Stack
->Parameters
.Mount
.DeviceObject
);
333 case IRP_MN_VERIFY_VOLUME
:
334 DPRINT1("VFAT FSC: IRP_MN_VERIFY_VOLUME\n");
335 Status
= STATUS_INVALID_DEVICE_REQUEST
;
339 DPRINT1("VFAT FSC: MinorFunction %d\n", Stack
->MinorFunction
);
340 Status
= STATUS_INVALID_DEVICE_REQUEST
;
344 Irp
->IoStatus
.Status
= Status
;
345 Irp
->IoStatus
.Information
= 0;
347 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
353 DriverEntry(PDRIVER_OBJECT _DriverObject
,
354 PUNICODE_STRING RegistryPath
)
356 * FUNCTION: Called by the system to initalize the driver
358 * DriverObject = object describing this driver
359 * RegistryPath = path to our configuration entries
360 * RETURNS: Success or failure
363 PDEVICE_OBJECT DeviceObject
;
364 UNICODE_STRING DeviceName
;
367 DbgPrint("VFAT 0.0.6\n");
369 VfatDriverObject
= _DriverObject
;
371 RtlInitUnicodeString(&DeviceName
,
373 Status
= IoCreateDevice(VfatDriverObject
,
376 FILE_DEVICE_FILE_SYSTEM
,
380 if (!NT_SUCCESS(Status
))
385 DeviceObject
->Flags
= DO_DIRECT_IO
;
386 VfatDriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = VfatClose
;
387 VfatDriverObject
->MajorFunction
[IRP_MJ_CREATE
] = VfatCreate
;
388 VfatDriverObject
->MajorFunction
[IRP_MJ_READ
] = VfatRead
;
389 VfatDriverObject
->MajorFunction
[IRP_MJ_WRITE
] = VfatWrite
;
390 VfatDriverObject
->MajorFunction
[IRP_MJ_FILE_SYSTEM_CONTROL
] =
391 VfatFileSystemControl
;
392 VfatDriverObject
->MajorFunction
[IRP_MJ_QUERY_INFORMATION
] =
393 VfatQueryInformation
;
394 VfatDriverObject
->MajorFunction
[IRP_MJ_SET_INFORMATION
] =
396 VfatDriverObject
->MajorFunction
[IRP_MJ_DIRECTORY_CONTROL
] =
397 VfatDirectoryControl
;
398 VfatDriverObject
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] =
399 VfatQueryVolumeInformation
;
400 VfatDriverObject
->MajorFunction
[IRP_MJ_SET_VOLUME_INFORMATION
] =
401 VfatSetVolumeInformation
;
402 VfatDriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = VfatShutdown
;
403 VfatDriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = VfatCleanup
;
405 VfatDriverObject
->DriverUnload
= NULL
;
407 IoRegisterFileSystem(DeviceObject
);
409 return STATUS_SUCCESS
;