2000-12-29 13:45:01 +00:00
|
|
|
/* $Id: iface.c,v 1.44 2000/12/29 13:45:01 ekohl Exp $
|
1999-12-04 20:58:45 +00:00
|
|
|
*
|
1998-10-05 04:00:59 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: services/fs/vfat/iface.c
|
|
|
|
* PURPOSE: VFAT Filesystem
|
|
|
|
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
1998-10-31 15:54:07 +00:00
|
|
|
* UPDATE HISTORY:
|
1999-12-11 21:14:49 +00:00
|
|
|
* ?? Created
|
|
|
|
* 24-10-1998 Fixed bugs in long filename support
|
|
|
|
* Fixed a bug that prevented unsuccessful file open requests being reported
|
|
|
|
* Now works with long filenames that span over a sector boundary
|
|
|
|
* 28-10-1998 Reads entire FAT into memory
|
|
|
|
* VFatReadSector modified to read in more than one sector at a time
|
|
|
|
* 7-11-1998 Fixed bug that assumed that directory data could be fragmented
|
|
|
|
* 8-12-1998 Added FAT32 support
|
|
|
|
* Added initial writability functions
|
|
|
|
* WARNING: DO NOT ATTEMPT TO TEST WRITABILITY FUNCTIONS!!!
|
|
|
|
* 12-12-1998 Added basic support for FILE_STANDARD_INFORMATION request
|
|
|
|
*
|
|
|
|
*/
|
1998-12-20 19:41:39 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
/* INCLUDES *****************************************************************/
|
1998-12-20 19:41:39 +00:00
|
|
|
|
2000-02-21 22:44:37 +00:00
|
|
|
#include <ddk/ntddk.h>
|
1999-12-11 21:14:49 +00:00
|
|
|
#include <wchar.h>
|
1998-12-20 19:41:39 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
#define NDEBUG
|
2000-06-29 23:35:53 +00:00
|
|
|
#include <debug.h>
|
1998-10-05 04:00:59 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
#include "vfat.h"
|
1998-12-20 19:41:39 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
/* GLOBALS *****************************************************************/
|
1998-10-05 04:00:59 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
static PDRIVER_OBJECT VfatDriverObject;
|
1998-10-05 04:00:59 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
1999-06-27 23:06:50 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
BOOLEAN FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount)
|
1998-12-30 18:43:27 +00:00
|
|
|
/*
|
1999-12-11 21:14:49 +00:00
|
|
|
* FUNCTION: Tests if the device contains a filesystem that can be mounted
|
|
|
|
* by this fsd
|
1998-12-30 18:43:27 +00:00
|
|
|
*/
|
1998-10-05 04:00:59 +00:00
|
|
|
{
|
1999-12-11 21:14:49 +00:00
|
|
|
BootSector* Boot;
|
1999-03-19 05:55:55 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
Boot = ExAllocatePool(NonPagedPool,512);
|
|
|
|
|
|
|
|
VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)Boot);
|
1999-12-22 14:48:30 +00:00
|
|
|
|
|
|
|
DPRINT("Boot->SysType %.5s\n", Boot->SysType);
|
1999-12-11 21:14:49 +00:00
|
|
|
if (strncmp(Boot->SysType,"FAT12",5)==0 ||
|
|
|
|
strncmp(Boot->SysType,"FAT16",5)==0 ||
|
|
|
|
strncmp(((struct _BootSector32 *)(Boot))->SysType,"FAT32",5)==0)
|
1999-01-20 13:05:53 +00:00
|
|
|
{
|
1999-12-11 21:14:49 +00:00
|
|
|
ExFreePool(Boot);
|
|
|
|
return(TRUE);
|
1999-01-20 13:05:53 +00:00
|
|
|
}
|
1999-12-11 21:14:49 +00:00
|
|
|
ExFreePool(Boot);
|
|
|
|
return(FALSE);
|
1998-10-05 04:00:59 +00:00
|
|
|
}
|
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
NTSTATUS FsdMountDevice(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PDEVICE_OBJECT DeviceToMount)
|
1998-12-30 18:43:27 +00:00
|
|
|
/*
|
1999-12-11 21:14:49 +00:00
|
|
|
* FUNCTION: Mounts the device
|
1998-12-30 18:43:27 +00:00
|
|
|
*/
|
1998-10-05 04:00:59 +00:00
|
|
|
{
|
1999-12-11 21:14:49 +00:00
|
|
|
DPRINT("Mounting VFAT device...");
|
|
|
|
DPRINT("DeviceExt %x\n",DeviceExt);
|
1998-10-05 04:00:59 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
DeviceExt->Boot = ExAllocatePool(NonPagedPool,512);
|
|
|
|
VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)DeviceExt->Boot);
|
1998-10-05 04:00:59 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
DPRINT("DeviceExt->Boot->BytesPerSector %x\n",
|
|
|
|
DeviceExt->Boot->BytesPerSector);
|
1999-03-19 05:55:55 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
DeviceExt->FATStart=DeviceExt->Boot->ReservedSectors;
|
|
|
|
DeviceExt->rootDirectorySectors=
|
|
|
|
(DeviceExt->Boot->RootEntries*32)/DeviceExt->Boot->BytesPerSector;
|
|
|
|
DeviceExt->rootStart=
|
|
|
|
DeviceExt->FATStart+DeviceExt->Boot->FATCount*DeviceExt->Boot->FATSectors;
|
|
|
|
DeviceExt->dataStart=DeviceExt->rootStart+DeviceExt->rootDirectorySectors;
|
|
|
|
DeviceExt->FATEntriesPerSector=DeviceExt->Boot->BytesPerSector/32;
|
|
|
|
DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster *
|
|
|
|
DeviceExt->Boot->BytesPerSector;
|
1998-10-05 04:00:59 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
if (strncmp(DeviceExt->Boot->SysType,"FAT12",5)==0)
|
|
|
|
{
|
|
|
|
DeviceExt->FatType = FAT12;
|
|
|
|
}
|
|
|
|
else if (strncmp(((struct _BootSector32 *)(DeviceExt->Boot))->SysType,"FAT32",5)==0)
|
|
|
|
{
|
|
|
|
DeviceExt->FatType = FAT32;
|
|
|
|
DeviceExt->rootDirectorySectors=DeviceExt->Boot->SectorsPerCluster;
|
|
|
|
DeviceExt->rootStart=
|
|
|
|
DeviceExt->FATStart+DeviceExt->Boot->FATCount
|
|
|
|
*((struct _BootSector32 *)( DeviceExt->Boot))->FATSectors32;
|
|
|
|
DeviceExt->dataStart=DeviceExt->rootStart;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DeviceExt->FatType = FAT16;
|
|
|
|
}
|
1998-10-31 15:54:07 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
// with FAT32 it's not a good idea to load always fat in memory
|
|
|
|
// because on a 8GB partition with 2 KO clusters, the fat = 8 MO
|
|
|
|
if(DeviceExt->FatType!=FAT32)
|
|
|
|
{
|
|
|
|
DeviceExt->FAT = ExAllocatePool(NonPagedPool, BLOCKSIZE*DeviceExt->Boot->FATSectors);
|
|
|
|
VFATReadSectors(DeviceToMount, DeviceExt->FATStart, DeviceExt->Boot->FATSectors, (UCHAR *)DeviceExt->FAT);
|
|
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
1998-10-05 04:00:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount)
|
1998-12-30 18:43:27 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Mount the filesystem
|
|
|
|
*/
|
1998-10-05 04:00:59 +00:00
|
|
|
{
|
|
|
|
PDEVICE_OBJECT DeviceObject;
|
|
|
|
PDEVICE_EXTENSION DeviceExt;
|
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
IoCreateDevice(VfatDriverObject,
|
1998-10-05 04:00:59 +00:00
|
|
|
sizeof(DEVICE_EXTENSION),
|
|
|
|
NULL,
|
|
|
|
FILE_DEVICE_FILE_SYSTEM,
|
|
|
|
0,
|
|
|
|
FALSE,
|
|
|
|
&DeviceObject);
|
|
|
|
DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
|
|
|
|
DeviceExt = (PVOID)DeviceObject->DeviceExtension;
|
1998-12-30 18:43:27 +00:00
|
|
|
// use same vpb as device disk
|
|
|
|
DeviceObject->Vpb=DeviceToMount->Vpb;
|
1998-10-05 04:00:59 +00:00
|
|
|
FsdMountDevice(DeviceExt,DeviceToMount);
|
1998-12-30 18:43:27 +00:00
|
|
|
DeviceObject->Vpb->Flags |= VPB_MOUNTED;
|
1998-10-05 04:00:59 +00:00
|
|
|
DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
|
|
|
|
DeviceToMount);
|
1999-12-11 21:14:49 +00:00
|
|
|
ExInitializeResourceLite(&DeviceExt->DirResource);
|
|
|
|
ExInitializeResourceLite(&DeviceExt->FatResource);
|
|
|
|
|
|
|
|
KeInitializeSpinLock(&DeviceExt->FcbListLock);
|
|
|
|
InitializeListHead(&DeviceExt->FcbListHead);
|
|
|
|
|
1999-05-13 18:02:24 +00:00
|
|
|
/* read serial number */
|
1999-05-05 11:23:46 +00:00
|
|
|
if (DeviceExt->FatType == FAT12 || DeviceExt->FatType == FAT16)
|
1999-05-13 18:02:24 +00:00
|
|
|
DeviceObject->Vpb->SerialNumber =
|
|
|
|
((struct _BootSector *)(DeviceExt->Boot))->VolumeID;
|
1999-05-05 11:23:46 +00:00
|
|
|
else if (DeviceExt->FatType == FAT32)
|
1999-05-13 18:02:24 +00:00
|
|
|
DeviceObject->Vpb->SerialNumber =
|
|
|
|
((struct _BootSector32 *)(DeviceExt->Boot))->VolumeID;
|
|
|
|
|
|
|
|
/* read volume label */
|
|
|
|
ReadVolumeLabel (DeviceExt, DeviceObject->Vpb);
|
1999-05-05 11:23:46 +00:00
|
|
|
|
1999-01-04 12:08:54 +00:00
|
|
|
return(STATUS_SUCCESS);
|
1998-10-05 04:00:59 +00:00
|
|
|
}
|
|
|
|
|
2000-09-12 10:12:13 +00:00
|
|
|
NTSTATUS STDCALL FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
1998-12-30 18:43:27 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: File system control
|
|
|
|
*/
|
1998-10-05 04:00:59 +00:00
|
|
|
{
|
|
|
|
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
1998-12-20 19:41:39 +00:00
|
|
|
// PVPB vpb = Stack->Parameters.Mount.Vpb;
|
1998-10-05 04:00:59 +00:00
|
|
|
PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
|
|
|
|
NTSTATUS Status;
|
1998-12-20 19:41:39 +00:00
|
|
|
|
1999-05-29 00:15:17 +00:00
|
|
|
// DPRINT("VFAT FSC\n");
|
|
|
|
DbgPrint("VFAT FSC\n");
|
1998-10-05 04:00:59 +00:00
|
|
|
|
1999-01-05 12:04:08 +00:00
|
|
|
/* FIXME: should make sure that this is actually a mount request! */
|
|
|
|
|
1998-10-05 04:00:59 +00:00
|
|
|
if (FsdHasFileSystem(DeviceToMount))
|
|
|
|
{
|
1999-12-22 14:48:30 +00:00
|
|
|
DPRINT("VFAT: Recognized volume\n");
|
1998-10-05 04:00:59 +00:00
|
|
|
Status = FsdMount(DeviceToMount);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1998-10-31 15:54:07 +00:00
|
|
|
DPRINT("VFAT: Unrecognized Volume\n");
|
1998-10-05 04:00:59 +00:00
|
|
|
Status = STATUS_UNRECOGNIZED_VOLUME;
|
|
|
|
}
|
1998-12-20 19:41:39 +00:00
|
|
|
|
1998-10-05 04:00:59 +00:00
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
Irp->IoStatus.Information = 0;
|
1999-03-19 05:55:55 +00:00
|
|
|
|
1998-10-05 04:00:59 +00:00
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT _DriverObject,
|
|
|
|
PUNICODE_STRING RegistryPath)
|
1998-10-05 04:00:59 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Called by the system to initalize the driver
|
|
|
|
* ARGUMENTS:
|
|
|
|
* DriverObject = object describing this driver
|
|
|
|
* RegistryPath = path to our configuration entries
|
|
|
|
* RETURNS: Success or failure
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
PDEVICE_OBJECT DeviceObject;
|
|
|
|
NTSTATUS ret;
|
1999-12-11 21:14:49 +00:00
|
|
|
UNICODE_STRING DeviceName;
|
1998-10-05 04:00:59 +00:00
|
|
|
|
1999-03-19 05:55:55 +00:00
|
|
|
DbgPrint("VFAT 0.0.6\n");
|
1999-12-11 21:14:49 +00:00
|
|
|
|
|
|
|
VfatDriverObject = _DriverObject;
|
1998-10-05 04:00:59 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
RtlInitUnicodeString(&DeviceName, L"\\Device\\Vfat");
|
|
|
|
ret = IoCreateDevice(VfatDriverObject,0,&DeviceName,
|
1998-10-05 04:00:59 +00:00
|
|
|
FILE_DEVICE_FILE_SYSTEM,0,FALSE,&DeviceObject);
|
|
|
|
if (ret!=STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
1999-01-05 12:04:08 +00:00
|
|
|
DeviceObject->Flags = DO_DIRECT_IO;
|
1999-12-11 21:14:49 +00:00
|
|
|
VfatDriverObject->MajorFunction[IRP_MJ_CLOSE] = FsdClose;
|
|
|
|
VfatDriverObject->MajorFunction[IRP_MJ_CREATE] = FsdCreate;
|
|
|
|
VfatDriverObject->MajorFunction[IRP_MJ_READ] = FsdRead;
|
|
|
|
VfatDriverObject->MajorFunction[IRP_MJ_WRITE] = FsdWrite;
|
|
|
|
VfatDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
|
1998-10-05 04:00:59 +00:00
|
|
|
FsdFileSystemControl;
|
1999-12-11 21:14:49 +00:00
|
|
|
VfatDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
|
1998-12-20 19:41:39 +00:00
|
|
|
FsdQueryInformation;
|
1999-12-11 21:14:49 +00:00
|
|
|
VfatDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
|
|
|
|
VfatSetInformation;
|
|
|
|
VfatDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
|
1998-12-30 18:43:27 +00:00
|
|
|
FsdDirectoryControl;
|
1999-12-11 21:14:49 +00:00
|
|
|
VfatDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
|
|
|
|
VfatQueryVolumeInformation;
|
2000-12-29 13:45:01 +00:00
|
|
|
VfatDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] =
|
|
|
|
VfatShutdown;
|
1998-12-30 18:43:27 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
VfatDriverObject->DriverUnload = NULL;
|
1998-10-05 04:00:59 +00:00
|
|
|
|
|
|
|
IoRegisterFileSystem(DeviceObject);
|
|
|
|
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|