2002-05-23 09:53:26 +00:00
|
|
|
/*
|
|
|
|
* ReactOS kernel
|
|
|
|
* Copyright (C) 2002 ReactOS Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
2003-10-11 17:51:56 +00:00
|
|
|
/* $Id: fsctl.c,v 1.24 2003/10/11 17:51:56 hbirr Exp $
|
2002-03-18 22:37:13 +00:00
|
|
|
*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
2003-10-11 17:51:56 +00:00
|
|
|
* FILE: drivers/fs/vfat/fsctl.c
|
2002-03-18 22:37:13 +00:00
|
|
|
* PURPOSE: VFAT Filesystem
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include <ddk/ntddk.h>
|
|
|
|
#include <wchar.h>
|
|
|
|
|
2003-08-07 11:47:33 +00:00
|
|
|
#include <ntos.h>
|
|
|
|
|
2002-09-08 10:23:54 +00:00
|
|
|
#define NDEBUG
|
2002-03-18 22:37:13 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
#include "vfat.h"
|
|
|
|
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2002-10-01 19:27:25 +00:00
|
|
|
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \
|
|
|
|
(pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE)
|
2002-03-18 22:37:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
|
|
|
|
PBOOLEAN RecognizedFS,
|
|
|
|
PFATINFO pFatInfo)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PARTITION_INFORMATION PartitionInfo;
|
|
|
|
DISK_GEOMETRY DiskGeometry;
|
|
|
|
FATINFO FatInfo;
|
|
|
|
ULONG Size;
|
|
|
|
ULONG Sectors;
|
2002-06-26 18:36:41 +00:00
|
|
|
LARGE_INTEGER Offset;
|
2002-03-18 22:37:13 +00:00
|
|
|
struct _BootSector* Boot;
|
|
|
|
|
|
|
|
*RecognizedFS = FALSE;
|
|
|
|
|
|
|
|
Size = sizeof(DISK_GEOMETRY);
|
|
|
|
Status = VfatBlockDeviceIoControl(DeviceToMount,
|
|
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&DiskGeometry,
|
|
|
|
&Size);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
if (DiskGeometry.MediaType == FixedMedia)
|
|
|
|
{
|
|
|
|
// We have found a hard disk
|
|
|
|
Size = sizeof(PARTITION_INFORMATION);
|
|
|
|
Status = VfatBlockDeviceIoControl(DeviceToMount,
|
|
|
|
IOCTL_DISK_GET_PARTITION_INFO,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&PartitionInfo,
|
|
|
|
&Size);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2002-05-05 20:19:14 +00:00
|
|
|
DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
|
2002-03-18 22:37:13 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2002-05-05 20:19:14 +00:00
|
|
|
#ifndef NDEBUG
|
2002-03-18 22:37:13 +00:00
|
|
|
DbgPrint("Partition Information:\n");
|
|
|
|
DbgPrint("StartingOffset %u\n", PartitionInfo.StartingOffset.QuadPart / 512);
|
|
|
|
DbgPrint("PartitionLength %u\n", PartitionInfo.PartitionLength.QuadPart / 512);
|
|
|
|
DbgPrint("HiddenSectors %u\n", PartitionInfo.HiddenSectors);
|
|
|
|
DbgPrint("PartitionNumber %u\n", PartitionInfo.PartitionNumber);
|
|
|
|
DbgPrint("PartitionType %u\n", PartitionInfo.PartitionType);
|
|
|
|
DbgPrint("BootIndicator %u\n", PartitionInfo.BootIndicator);
|
|
|
|
DbgPrint("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
|
|
|
|
DbgPrint("RewritePartition %u\n", PartitionInfo.RewritePartition);
|
|
|
|
#endif
|
2002-05-29 21:41:41 +00:00
|
|
|
if (PartitionInfo.PartitionType == PARTITION_FAT_12 ||
|
|
|
|
PartitionInfo.PartitionType == PARTITION_FAT_16 ||
|
|
|
|
PartitionInfo.PartitionType == PARTITION_HUGE ||
|
|
|
|
PartitionInfo.PartitionType == PARTITION_FAT32 ||
|
|
|
|
PartitionInfo.PartitionType == PARTITION_FAT32_XINT13 ||
|
|
|
|
PartitionInfo.PartitionType == PARTITION_XINT13)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
*RecognizedFS = TRUE;
|
|
|
|
}
|
|
|
|
}
|
2002-05-28 09:25:09 +00:00
|
|
|
else if (DiskGeometry.MediaType > Unknown && DiskGeometry.MediaType <= RemovableMedia)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
*RecognizedFS = TRUE;
|
|
|
|
}
|
|
|
|
if (*RecognizedFS == FALSE)
|
|
|
|
{
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2002-06-26 18:36:41 +00:00
|
|
|
|
|
|
|
Boot = ExAllocatePool(NonPagedPool, DiskGeometry.BytesPerSector);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (Boot == NULL)
|
|
|
|
{
|
|
|
|
*RecognizedFS=FALSE;
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
2002-06-26 18:36:41 +00:00
|
|
|
Offset.QuadPart = 0;
|
|
|
|
Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
FatInfo.VolumeID = Boot->VolumeID;
|
|
|
|
FatInfo.FATStart = Boot->ReservedSectors;
|
|
|
|
FatInfo.FATCount = Boot->FATCount;
|
|
|
|
FatInfo.FATSectors = Boot->FATSectors ? Boot->FATSectors : ((struct _BootSector32*) Boot)->FATSectors32;
|
|
|
|
FatInfo.BytesPerSector = Boot->BytesPerSector;
|
|
|
|
FatInfo.SectorsPerCluster = Boot->SectorsPerCluster;
|
|
|
|
FatInfo.BytesPerCluster = FatInfo.BytesPerSector * FatInfo.SectorsPerCluster;
|
|
|
|
FatInfo.rootDirectorySectors = ((Boot->RootEntries * 32) + Boot->BytesPerSector - 1) / Boot->BytesPerSector;
|
|
|
|
FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
|
|
|
|
FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
|
2002-05-05 20:19:14 +00:00
|
|
|
FatInfo.Sectors = Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge;
|
2002-03-18 22:37:13 +00:00
|
|
|
Sectors -= Boot->ReservedSectors + FatInfo.FATCount * FatInfo.FATSectors + FatInfo.rootDirectorySectors;
|
|
|
|
FatInfo.NumberOfClusters = Sectors / Boot->SectorsPerCluster;
|
|
|
|
if (FatInfo.NumberOfClusters < 4085)
|
|
|
|
{
|
|
|
|
DPRINT("FAT12\n");
|
|
|
|
FatInfo.FatType = FAT12;
|
|
|
|
}
|
|
|
|
else if (FatInfo.NumberOfClusters >= 65525)
|
|
|
|
{
|
|
|
|
DPRINT("FAT32\n");
|
|
|
|
FatInfo.FatType = FAT32;
|
|
|
|
FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster;
|
|
|
|
FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster);
|
|
|
|
FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT("FAT16\n");
|
|
|
|
FatInfo.FatType = FAT16;
|
|
|
|
}
|
|
|
|
if (pFatInfo)
|
|
|
|
{
|
|
|
|
*pFatInfo = FatInfo;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ExFreePool(Boot);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
VfatMountDevice(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PDEVICE_OBJECT DeviceToMount)
|
|
|
|
/*
|
|
|
|
* FUNCTION: Mounts the device
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
BOOLEAN RecognizedFS;
|
|
|
|
|
2002-05-05 20:19:14 +00:00
|
|
|
DPRINT("Mounting VFAT device...\n");
|
2002-03-18 22:37:13 +00:00
|
|
|
|
|
|
|
Status = VfatHasFileSystem(DeviceToMount, &RecognizedFS, &DeviceExt->FatInfo);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
2002-10-01 19:27:25 +00:00
|
|
|
if (DeviceExt->FatInfo.BytesPerCluster >= PAGE_SIZE &&
|
|
|
|
(DeviceExt->FatInfo.BytesPerCluster % PAGE_SIZE) != 0)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
DbgPrint("(%s:%d) Invalid cluster size\n", __FILE__, __LINE__);
|
2003-07-21 21:53:53 +00:00
|
|
|
KEBUGCHECK(0);
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
2002-10-01 19:27:25 +00:00
|
|
|
else if (DeviceExt->FatInfo.BytesPerCluster < PAGE_SIZE &&
|
|
|
|
(PAGE_SIZE % DeviceExt->FatInfo.BytesPerCluster) != 0)
|
2002-03-18 22:37:13 +00:00
|
|
|
{
|
|
|
|
DbgPrint("(%s:%d) Invalid cluster size2\n", __FILE__, __LINE__);
|
2003-07-21 21:53:53 +00:00
|
|
|
KEBUGCHECK(0);
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
VfatMount (PVFAT_IRP_CONTEXT IrpContext)
|
|
|
|
/*
|
|
|
|
* FUNCTION: Mount the filesystem
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
PDEVICE_OBJECT DeviceObject = NULL;
|
|
|
|
PDEVICE_EXTENSION DeviceExt = NULL;
|
|
|
|
BOOLEAN RecognizedFS;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PVFATFCB Fcb = NULL;
|
2002-05-05 20:19:14 +00:00
|
|
|
PVFATFCB VolumeFcb = NULL;
|
2002-03-18 22:37:13 +00:00
|
|
|
PVFATCCB Ccb = NULL;
|
2003-06-24 21:34:41 +00:00
|
|
|
PDEVICE_OBJECT DeviceToMount;
|
2003-10-11 17:51:56 +00:00
|
|
|
UNICODE_STRING NameU;
|
2002-03-18 22:37:13 +00:00
|
|
|
|
|
|
|
DPRINT("VfatMount(IrpContext %x)\n", IrpContext);
|
|
|
|
|
|
|
|
assert (IrpContext);
|
|
|
|
|
|
|
|
if (IrpContext->DeviceObject != VfatGlobalData->DeviceObject)
|
|
|
|
{
|
|
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
|
2003-06-24 21:34:41 +00:00
|
|
|
DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
|
|
|
|
|
|
|
|
Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS, NULL);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (RecognizedFS == FALSE)
|
|
|
|
{
|
|
|
|
DPRINT("VFAT: Unrecognized Volume\n");
|
|
|
|
Status = STATUS_UNRECOGNIZED_VOLUME;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("VFAT: Recognized volume\n");
|
|
|
|
Status = IoCreateDevice(VfatGlobalData->DriverObject,
|
|
|
|
sizeof (DEVICE_EXTENSION),
|
|
|
|
NULL,
|
|
|
|
FILE_DEVICE_FILE_SYSTEM,
|
|
|
|
0,
|
|
|
|
FALSE,
|
|
|
|
&DeviceObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
|
|
|
|
DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
|
|
|
|
DeviceExt = (PVOID) DeviceObject->DeviceExtension;
|
|
|
|
RtlZeroMemory(DeviceExt, sizeof(DEVICE_EXTENSION));
|
|
|
|
|
|
|
|
/* use same vpb as device disk */
|
2003-06-24 21:34:41 +00:00
|
|
|
DeviceObject->Vpb = DeviceToMount->Vpb;
|
|
|
|
Status = VfatMountDevice(DeviceExt, DeviceToMount);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* FIXME: delete device object */
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
|
2002-05-05 20:19:14 +00:00
|
|
|
#ifndef NDEBUG
|
2002-03-18 22:37:13 +00:00
|
|
|
DbgPrint("BytesPerSector: %d\n", DeviceExt->FatInfo.BytesPerSector);
|
|
|
|
DbgPrint("SectorsPerCluster: %d\n", DeviceExt->FatInfo.SectorsPerCluster);
|
|
|
|
DbgPrint("FATCount: %d\n", DeviceExt->FatInfo.FATCount);
|
|
|
|
DbgPrint("FATSectors: %d\n", DeviceExt->FatInfo.FATSectors);
|
|
|
|
DbgPrint("RootStart: %d\n", DeviceExt->FatInfo.rootStart);
|
|
|
|
DbgPrint("DataStart: %d\n", DeviceExt->FatInfo.dataStart);
|
|
|
|
if (DeviceExt->FatInfo.FatType == FAT32)
|
|
|
|
{
|
|
|
|
DbgPrint("RootCluster: %d\n", DeviceExt->FatInfo.RootCluster);
|
|
|
|
}
|
|
|
|
#endif
|
2002-05-23 09:53:26 +00:00
|
|
|
|
2003-06-24 21:34:41 +00:00
|
|
|
DeviceExt->StorageDevice = DeviceToMount;
|
2002-05-23 09:53:26 +00:00
|
|
|
DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
|
|
|
|
DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
|
|
|
|
DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
|
|
|
|
DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
|
|
|
|
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
|
|
|
|
DPRINT("FsDeviceObject %lx\n", DeviceObject);
|
2002-03-18 22:37:13 +00:00
|
|
|
|
|
|
|
DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
|
2003-10-11 17:51:56 +00:00
|
|
|
RtlInitUnicodeStringFromLiteral(&NameU, L"\\$$Fat$$");
|
|
|
|
Fcb = vfatNewFCB(&NameU);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (Fcb == NULL)
|
|
|
|
{
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
Ccb = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (Ccb == NULL)
|
|
|
|
{
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
2003-10-11 17:51:56 +00:00
|
|
|
|
2002-03-18 22:37:13 +00:00
|
|
|
memset(Ccb, 0, sizeof (VFATCCB));
|
|
|
|
DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
|
2003-02-13 22:24:19 +00:00
|
|
|
DeviceExt->FATFileObject->FsContext = Fcb;
|
2002-03-18 22:37:13 +00:00
|
|
|
DeviceExt->FATFileObject->FsContext2 = Ccb;
|
2003-06-07 Casper S. Hornstrup <chorns@users.sourceforge.net>
Changes for compiling with w32api
* include/ddk/cctypes.h (PREACTOS_COMMON_FCB_HEADER): Remove.
(FSRTL_COMMON_FCB_HEADER): Add.
* include/ddk/iotypes.h (FILE_OBJECT): Rename field
SectionObjectPointers to SectionObjectPointer.
* ntoskrnl/cc/copy.c, ntoskrnl/cc/misc.c, ntoskrnl/cc/pin.c,
ntoskrnl/cc/view.c, ntoskrnl/io/rawfs.c, ntoskrnl/mm/section.c,
drivers/fs/cdfs/cleanup.c, drivers/fs/cdfs/fcb.c,
drivers/fs/cdfs/fsctl.c, drivers/fs/ntfs/fcb.c, drivers/fs/ntfs/fsctl.c,
drivers/fs/vfat/close.c, drivers/fs/vfat/create.c,
drivers/fs/vfat/finfo.c, drivers/fs/vfat/fcb.c, drivers/fs/vfat/fsctl.c:
Use new FILE_OBJECT structure.
* drivers/fs/cdfs/cdfs.h, drivers/fs/ntfs/ntfs.h, drivers/fs/vfat/vfat.h:
Use new FSRTL_COMMON_FCB_HEADER structure.
* drivers/net/afd/include/afd.h (FSRTL_COMMON_FCB_HEADER): Remove.
* include/ddk/ketypes.h (KQUEUE): Match w32api structure.
* ntoskrnl/ke/queue.c, ntoskrnl/ke/wait.c: Use new structure.
* ntoskrnl/ke/spinlock.c (KeAcquireSpinLockAtDpcLevel,
KeReleaseSpinLockFromDpcLevel): Undefine before declaring.
svn path=/trunk/; revision=4865
2003-06-07 11:34:36 +00:00
|
|
|
DeviceExt->FATFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
|
2002-03-18 22:37:13 +00:00
|
|
|
DeviceExt->FATFileObject->PrivateCacheMap = NULL;
|
|
|
|
DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb;
|
|
|
|
Fcb->FileObject = DeviceExt->FATFileObject;
|
|
|
|
|
|
|
|
Fcb->Flags = FCB_IS_FAT;
|
|
|
|
|
2002-06-26 18:36:41 +00:00
|
|
|
Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector;
|
2002-06-07 16:53:18 +00:00
|
|
|
Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize;
|
|
|
|
Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize;
|
|
|
|
|
2002-03-18 22:37:13 +00:00
|
|
|
if (DeviceExt->FatInfo.FatType != FAT12)
|
|
|
|
{
|
2003-02-13 22:24:19 +00:00
|
|
|
Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, CACHEPAGESIZE(DeviceExt));
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-02-13 22:24:19 +00:00
|
|
|
Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, 2 * PAGE_SIZE);
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
|
|
|
if (!NT_SUCCESS (Status))
|
|
|
|
{
|
|
|
|
DbgPrint ("CcRosInitializeFileCache failed\n");
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
2003-02-09 18:02:56 +00:00
|
|
|
DeviceExt->LastAvailableCluster = 2;
|
2002-03-18 22:37:13 +00:00
|
|
|
ExInitializeResourceLite(&DeviceExt->DirResource);
|
|
|
|
ExInitializeResourceLite(&DeviceExt->FatResource);
|
|
|
|
|
|
|
|
InitializeListHead(&DeviceExt->FcbListHead);
|
2003-10-11 17:51:56 +00:00
|
|
|
RtlInitUnicodeStringFromLiteral(&NameU, L"\\$$Volume$$");
|
2002-03-18 22:37:13 +00:00
|
|
|
|
2003-10-11 17:51:56 +00:00
|
|
|
VolumeFcb = vfatNewFCB(&NameU);
|
2002-05-05 20:19:14 +00:00
|
|
|
if (VolumeFcb == NULL)
|
|
|
|
{
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
VolumeFcb->Flags = FCB_IS_VOLUME;
|
2002-06-26 18:36:41 +00:00
|
|
|
VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
|
2002-05-05 20:19:14 +00:00
|
|
|
VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;
|
|
|
|
VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize;
|
|
|
|
DeviceExt->VolumeFcb = VolumeFcb;
|
|
|
|
|
2003-02-09 18:02:56 +00:00
|
|
|
ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE);
|
|
|
|
InsertHeadList(&VfatGlobalData->VolumeListHead, &DeviceExt->VolumeListEntry);
|
|
|
|
ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);
|
|
|
|
|
2002-03-18 22:37:13 +00:00
|
|
|
/* read serial number */
|
|
|
|
DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID;
|
|
|
|
|
|
|
|
/* read volume label */
|
|
|
|
ReadVolumeLabel(DeviceExt, DeviceObject->Vpb);
|
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
ByeBye:
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
// cleanup
|
|
|
|
if (DeviceExt && DeviceExt->FATFileObject)
|
|
|
|
ObDereferenceObject (DeviceExt->FATFileObject);
|
|
|
|
if (Fcb)
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
vfatDestroyFCB(Fcb);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (Ccb)
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
vfatDestroyCCB(Ccb);
|
2002-03-18 22:37:13 +00:00
|
|
|
if (DeviceObject)
|
|
|
|
IoDeleteDevice(DeviceObject);
|
2002-05-05 20:19:14 +00:00
|
|
|
if (VolumeFcb)
|
|
|
|
vfatDestroyFCB(VolumeFcb);
|
2002-03-18 22:37:13 +00:00
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2002-04-10 09:58:45 +00:00
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
VfatVerify (PVFAT_IRP_CONTEXT IrpContext)
|
|
|
|
/*
|
2003-06-24 21:34:41 +00:00
|
|
|
* FUNCTION: Verify the filesystem
|
2002-04-10 09:58:45 +00:00
|
|
|
*/
|
|
|
|
{
|
2003-06-24 21:34:41 +00:00
|
|
|
PDEVICE_OBJECT DeviceToVerify;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2002-04-10 09:58:45 +00:00
|
|
|
DPRINT("VfatVerify(IrpContext %x)\n", IrpContext);
|
|
|
|
|
2003-06-24 21:34:41 +00:00
|
|
|
DeviceToVerify = IrpContext->Stack->Parameters.VerifyVolume.DeviceObject;
|
|
|
|
Status = VfatBlockDeviceIoControl(DeviceToVerify,
|
|
|
|
IOCTL_DISK_CHECK_VERIFY,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("VfatBlockDeviceIoControl() failed (Status %lx)\n", Status);
|
|
|
|
|
|
|
|
/* FIXME: Compare volume label */
|
2002-04-10 09:58:45 +00:00
|
|
|
|
2003-06-24 21:34:41 +00:00
|
|
|
DPRINT1(" returning STATUS_WRONG_VOLUME\n");
|
|
|
|
|
|
|
|
return STATUS_WRONG_VOLUME;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
2002-04-10 09:58:45 +00:00
|
|
|
}
|
|
|
|
|
2003-06-24 21:34:41 +00:00
|
|
|
|
2003-05-11 09:51:26 +00:00
|
|
|
static NTSTATUS
|
|
|
|
VfatGetVolumeBitmap(PVFAT_IRP_CONTEXT IrpContext)
|
|
|
|
{
|
|
|
|
DPRINT("VfatGetVolumeBitmap (IrpContext %x)\n", IrpContext);
|
|
|
|
|
|
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
}
|
|
|
|
|
2003-06-24 21:34:41 +00:00
|
|
|
|
2003-05-11 09:51:26 +00:00
|
|
|
static NTSTATUS
|
|
|
|
VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext)
|
|
|
|
{
|
2003-08-27 21:28:08 +00:00
|
|
|
PIO_STACK_LOCATION Stack;
|
2003-05-11 09:51:26 +00:00
|
|
|
LARGE_INTEGER Vcn;
|
|
|
|
PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers;
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
ULONG MaxExtentCount;
|
|
|
|
PVFATFCB Fcb;
|
|
|
|
PDEVICE_EXTENSION DeviceExt;
|
|
|
|
ULONG FirstCluster;
|
|
|
|
ULONG CurrentCluster;
|
|
|
|
ULONG LastCluster;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("VfatGetRetrievalPointers(IrpContext %x)\n", IrpContext);
|
|
|
|
|
|
|
|
DeviceExt = IrpContext->DeviceExt;
|
|
|
|
FileObject = IrpContext->FileObject;
|
|
|
|
Stack = IrpContext->Stack;
|
|
|
|
if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(LARGE_INTEGER) ||
|
|
|
|
Stack->Parameters.DeviceIoControl.Type3InputBuffer == NULL)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
if (IrpContext->Irp->UserBuffer == NULL ||
|
|
|
|
Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GET_RETRIEVAL_DESCRIPTOR) + sizeof(MAPPING_PAIR))
|
|
|
|
{
|
|
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Fcb = FileObject->FsContext;
|
|
|
|
|
|
|
|
ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);
|
|
|
|
|
|
|
|
Vcn = *(PLARGE_INTEGER)Stack->Parameters.DeviceIoControl.Type3InputBuffer;
|
|
|
|
RetrievalPointers = IrpContext->Irp->UserBuffer;
|
|
|
|
|
|
|
|
MaxExtentCount = ((Stack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(GET_RETRIEVAL_DESCRIPTOR)) / sizeof(MAPPING_PAIR));
|
|
|
|
|
|
|
|
|
2003-08-10 20:01:16 +00:00
|
|
|
if (Vcn.QuadPart >= Fcb->RFCB.AllocationSize.QuadPart / DeviceExt->FatInfo.BytesPerCluster)
|
2003-05-11 09:51:26 +00:00
|
|
|
{
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
|
|
|
|
CurrentCluster = FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Fcb->entry);
|
|
|
|
Status = OffsetToCluster(DeviceExt, FirstCluster,
|
|
|
|
Vcn.u.LowPart * DeviceExt->FatInfo.BytesPerCluster,
|
|
|
|
&CurrentCluster, FALSE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
|
|
|
|
RetrievalPointers->StartVcn = Vcn.QuadPart;
|
|
|
|
RetrievalPointers->NumberOfPairs = 0;
|
|
|
|
RetrievalPointers->Pair[0].Lcn = CurrentCluster - 2;
|
|
|
|
LastCluster = 0;
|
|
|
|
while (CurrentCluster != 0xffffffff && RetrievalPointers->NumberOfPairs < MaxExtentCount)
|
|
|
|
{
|
|
|
|
|
|
|
|
LastCluster = CurrentCluster;
|
|
|
|
Status = NextCluster(DeviceExt, CurrentCluster, &CurrentCluster, FALSE);
|
|
|
|
Vcn.QuadPart++;
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LastCluster + 1 != CurrentCluster)
|
|
|
|
{
|
|
|
|
RetrievalPointers->Pair[RetrievalPointers->NumberOfPairs].Vcn = Vcn.QuadPart;
|
|
|
|
RetrievalPointers->NumberOfPairs++;
|
|
|
|
if (RetrievalPointers->NumberOfPairs < MaxExtentCount)
|
|
|
|
{
|
|
|
|
RetrievalPointers->Pair[RetrievalPointers->NumberOfPairs].Lcn = CurrentCluster - 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IrpContext->Irp->IoStatus.Information = sizeof(GET_RETRIEVAL_DESCRIPTOR) + sizeof(MAPPING_PAIR) * RetrievalPointers->NumberOfPairs;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
ByeBye:
|
|
|
|
ExReleaseResourceLite(&Fcb->MainResource);
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
VfatMoveFile(PVFAT_IRP_CONTEXT IrpContext)
|
|
|
|
{
|
|
|
|
DPRINT("VfatMoveFile(IrpContext %x)\n", IrpContext);
|
|
|
|
|
|
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
}
|
2002-04-10 09:58:45 +00:00
|
|
|
|
2003-08-27 21:28:08 +00:00
|
|
|
static NTSTATUS
|
|
|
|
VfatRosQueryLcnMapping(PVFAT_IRP_CONTEXT IrpContext)
|
|
|
|
{
|
|
|
|
PDEVICE_EXTENSION DeviceExt;
|
|
|
|
PROS_QUERY_LCN_MAPPING LcnQuery;
|
|
|
|
PIO_STACK_LOCATION Stack;
|
|
|
|
|
|
|
|
DPRINT("VfatGetRetrievalPointers(IrpContext %x)\n", IrpContext);
|
|
|
|
|
|
|
|
DeviceExt = IrpContext->DeviceExt;
|
|
|
|
Stack = IrpContext->Stack;
|
|
|
|
if (IrpContext->Irp->AssociatedIrp.SystemBuffer == NULL ||
|
|
|
|
Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ROS_QUERY_LCN_MAPPING))
|
|
|
|
{
|
|
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
|
|
}
|
|
|
|
LcnQuery = (PROS_QUERY_LCN_MAPPING)(IrpContext->Irp->AssociatedIrp.SystemBuffer);
|
|
|
|
LcnQuery->LcnDiskOffset.QuadPart = DeviceExt->FatInfo.dataStart * DeviceExt->FatInfo.BytesPerSector;
|
|
|
|
IrpContext->Irp->IoStatus.Information = sizeof(ROS_QUERY_LCN_MAPPING);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2002-03-18 22:37:13 +00:00
|
|
|
NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
|
|
|
|
/*
|
|
|
|
* FUNCTION: File system control
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("VfatFileSystemControl(IrpContext %x)\n", IrpContext);
|
|
|
|
|
|
|
|
assert (IrpContext);
|
2003-05-11 09:51:26 +00:00
|
|
|
assert (IrpContext->Irp);
|
|
|
|
assert (IrpContext->Stack);
|
|
|
|
|
|
|
|
IrpContext->Irp->IoStatus.Information = 0;
|
2002-03-18 22:37:13 +00:00
|
|
|
|
|
|
|
switch (IrpContext->MinorFunction)
|
|
|
|
{
|
|
|
|
case IRP_MN_USER_FS_REQUEST:
|
2003-05-11 09:51:26 +00:00
|
|
|
switch(IrpContext->Stack->Parameters.DeviceIoControl.IoControlCode)
|
|
|
|
{
|
|
|
|
case FSCTL_GET_VOLUME_BITMAP:
|
|
|
|
Status = VfatGetVolumeBitmap(IrpContext);
|
|
|
|
break;
|
|
|
|
case FSCTL_GET_RETRIEVAL_POINTERS:
|
|
|
|
Status = VfatGetRetrievalPointers(IrpContext);
|
|
|
|
break;
|
|
|
|
case FSCTL_MOVE_FILE:
|
|
|
|
Status = VfatMoveFile(IrpContext);
|
|
|
|
break;
|
2003-08-27 21:28:08 +00:00
|
|
|
case FSCTL_ROS_QUERY_LCN_MAPPING:
|
|
|
|
Status = VfatRosQueryLcnMapping(IrpContext);
|
|
|
|
break;
|
2003-05-11 09:51:26 +00:00
|
|
|
default:
|
|
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_MOUNT_VOLUME:
|
|
|
|
Status = VfatMount(IrpContext);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_VERIFY_VOLUME:
|
2002-04-10 09:58:45 +00:00
|
|
|
Status = VfatVerify(IrpContext);
|
2002-03-18 22:37:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
DPRINT("VFAT FSC: MinorFunction %d\n", IrpContext->MinorFunction);
|
|
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
IrpContext->Irp->IoStatus.Status = Status;
|
|
|
|
|
|
|
|
IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
|
|
|
|
VfatFreeIrpContext(IrpContext);
|
|
|
|
return (Status);
|
|
|
|
}
|
|
|
|
|