From d09531b121f901e2b1a023142e5e7da977ff85f9 Mon Sep 17 00:00:00 2001 From: Hartmut Birr Date: Mon, 18 Mar 2002 22:37:13 +0000 Subject: [PATCH] All: Changed directory and fat access to pining-interface. Removed unused values from DEVICE_EXTENSION structure. Changed calculation of available and free clusters. Changed mount and type determining procedure. Moved some functions to fsctl.c volume.c: Added FAT32 fs type. dirw.c: Fixed a directory creation bug on FAT32 (Thanks to Eric Kohl). Fixed a directory deletion bug. dir.c: Fixed a dead lock in DoQuery. Fixed some memory leakages. svn path=/trunk/; revision=2737 --- reactos/drivers/fs/vfat/blockdev.c | 64 ++++ reactos/drivers/fs/vfat/create.c | 150 ++++---- reactos/drivers/fs/vfat/dir.c | 28 +- reactos/drivers/fs/vfat/direntry.c | 10 +- reactos/drivers/fs/vfat/dirwr.c | 538 +++++++++++++++++------------ reactos/drivers/fs/vfat/fat.c | 392 ++++++++++----------- reactos/drivers/fs/vfat/fcb.c | 29 +- reactos/drivers/fs/vfat/finfo.c | 6 +- reactos/drivers/fs/vfat/fsctl.c | 378 ++++++++++++++++++++ reactos/drivers/fs/vfat/iface.c | 394 ++------------------- reactos/drivers/fs/vfat/makefile | 5 +- reactos/drivers/fs/vfat/rw.c | 108 +++--- reactos/drivers/fs/vfat/vfat.h | 518 ++++++++++++++++----------- reactos/drivers/fs/vfat/volume.c | 59 ++-- 14 files changed, 1484 insertions(+), 1195 deletions(-) create mode 100644 reactos/drivers/fs/vfat/fsctl.c diff --git a/reactos/drivers/fs/vfat/blockdev.c b/reactos/drivers/fs/vfat/blockdev.c index 7bf65fa0527..bae26a7b636 100644 --- a/reactos/drivers/fs/vfat/blockdev.c +++ b/reactos/drivers/fs/vfat/blockdev.c @@ -141,3 +141,67 @@ VfatWriteSectors (IN PDEVICE_OBJECT pDeviceObject, DPRINT ("Block request succeeded\n"); return (STATUS_SUCCESS); } + +NTSTATUS +VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, + IN ULONG CtlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG pOutputBufferSize) +{ + ULONG OutputBufferSize = 0; + KEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + DPRINT("VfatBlockDeviceIoControl(DeviceObject %x, CtlCode %x, " + "InputBuffer %x, InputBufferSize %x, OutputBuffer %x, " + "POutputBufferSize %x (%x)\n", DeviceObject, CtlCode, + InputBuffer, InputBufferSize, OutputBuffer, pOutputBufferSize, + pOutputBufferSize ? *pOutputBufferSize : 0); + + if (pOutputBufferSize) + { + OutputBufferSize = *pOutputBufferSize; + } + + KeInitializeEvent (&Event, NotificationEvent, FALSE); + + DPRINT("Building device I/O control request ...\n"); + Irp = IoBuildDeviceIoControlRequest(CtlCode, + DeviceObject, + InputBuffer, + InputBufferSize, + OutputBuffer, + OutputBufferSize, + FALSE, + &Event, + &IoStatus); + + if (Irp == NULL) + { + DPRINT("IoBuildDeviceIoControlRequest failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + DPRINT ("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + + DPRINT ("Waiting for IO Operation for %x\n", Irp); + if (Status == STATUS_PENDING) + { + DPRINT ("Operation pending\n"); + KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL); + DPRINT ("Getting IO Status... for %x\n", Irp); + + Status = IoStatus.Status; + } + if (OutputBufferSize) + { + *pOutputBufferSize = OutputBufferSize; + } + DPRINT("Returning Status %x\n", Status); + return Status; +} diff --git a/reactos/drivers/fs/vfat/create.c b/reactos/drivers/fs/vfat/create.c index 833deaaf8db..307e713f4d8 100644 --- a/reactos/drivers/fs/vfat/create.c +++ b/reactos/drivers/fs/vfat/create.c @@ -1,4 +1,4 @@ -/* $Id: create.c,v 1.38 2002/02/08 02:57:09 chorns Exp $ +/* $Id: create.c,v 1.39 2002/03/18 22:37:12 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -220,80 +220,60 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb) * FUNCTION: Read the volume label */ { - ULONG i = 0; - ULONG j; - ULONG Size; - char *block; - ULONG StartingSector; - ULONG NextCluster; - NTSTATUS Status; + PVOID Context = NULL; + ULONG Offset = 0; + ULONG DirIndex = 0; + FATDirEntry* Entry; + PVFATFCB pFcb; + LARGE_INTEGER FileOffset; - Size = DeviceExt->rootDirectorySectors; /* FIXME : in fat32, no limit */ - StartingSector = DeviceExt->rootStart; - NextCluster = 0; - - block = ExAllocatePool (NonPagedPool, BLOCKSIZE); - DPRINT ("ReadVolumeLabel : start at sector %lx, entry %ld\n", StartingSector, i); - for (j = 0; j < Size; j++) - { - /* FIXME: Check status */ - Status = VfatReadSectors (DeviceExt->StorageDevice, StartingSector, 1, block); - if (!NT_SUCCESS(Status)) - { - *(Vpb->VolumeLabel) = 0; - Vpb->VolumeLabelLength = 0; - ExFreePool(block); - return(Status); - } - - for (i = 0; i < ENTRIES_PER_SECTOR; i++) - { - if (IsVolEntry ((PVOID) block, i)) - { - FATDirEntry *test = (FATDirEntry *) block; - - /* copy volume label */ - vfat8Dot3ToVolumeLabel (test[i].Filename, test[i].Ext, Vpb->VolumeLabel); - Vpb->VolumeLabelLength = wcslen (Vpb->VolumeLabel); - - ExFreePool (block); - return (STATUS_SUCCESS); - } - if (IsLastEntry ((PVOID) block, i)) - { - *(Vpb->VolumeLabel) = 0; - Vpb->VolumeLabelLength = 0; - ExFreePool (block); - return (STATUS_UNSUCCESSFUL); - } - } - /* not found in this sector, try next : */ - - /* directory can be fragmented although it is best to keep them - unfragmented.*/ - StartingSector++; - - if (DeviceExt->FatType == FAT32) - { - if (StartingSector == ClusterToSector (DeviceExt, NextCluster + 1)) - { - Status = GetNextCluster (DeviceExt, NextCluster, &NextCluster, - FALSE); - if (NextCluster == 0 || NextCluster == 0xffffffff) - { - *(Vpb->VolumeLabel) = 0; - Vpb->VolumeLabelLength = 0; - ExFreePool (block); - return (STATUS_UNSUCCESSFUL); - } - StartingSector = ClusterToSector (DeviceExt, NextCluster); - } - } - } *(Vpb->VolumeLabel) = 0; Vpb->VolumeLabelLength = 0; - ExFreePool (block); - return (STATUS_UNSUCCESSFUL); + + pFcb = vfatOpenRootFCB (DeviceExt); + + while (TRUE) + { + if (Context == NULL || Offset == ENTRIES_PER_PAGE) + { + if (Offset == ENTRIES_PER_PAGE) + { + Offset = 0; + } + if (Context) + { + CcUnpinData(Context); + } + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = (DirIndex - Offset) * sizeof(FATDirEntry); + if (!CcMapData(pFcb->FileObject, &FileOffset, PAGESIZE, TRUE, &Context, (PVOID*)&Entry)) + { + Context = NULL; + break; + } + } + if (IsVolEntry(Entry, Offset)) + { + /* copy volume label */ + vfat8Dot3ToVolumeLabel (Entry[Offset].Filename, Entry[Offset].Ext, Vpb->VolumeLabel); + Vpb->VolumeLabelLength = wcslen (Vpb->VolumeLabel) * sizeof(WCHAR); + break; + } + if (IsLastEntry(Entry, Offset)) + { + break; + } + Offset++; + DirIndex++; + } + + if (Context) + { + CcUnpinData(Context); + } + vfatReleaseFCB (DeviceExt, pFcb); + + return STATUS_SUCCESS; } NTSTATUS @@ -336,9 +316,9 @@ FindFile (PDEVICE_EXTENSION DeviceExt, if (Parent) { FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Parent->entry); - if (DeviceExt->FatType == FAT32) + if (DeviceExt->FatInfo.FatType == FAT32) { - if (FirstCluster == ((struct _BootSector32*)(DeviceExt->Boot))->RootCluster) + if (FirstCluster == DeviceExt->FatInfo.RootCluster) isRoot = TRUE; } else @@ -351,8 +331,8 @@ FindFile (PDEVICE_EXTENSION DeviceExt, isRoot = TRUE; if (isRoot) { - if (DeviceExt->FatType == FAT32) - FirstCluster = ((struct _BootSector32*)(DeviceExt->Boot))->RootCluster; + if (DeviceExt->FatInfo.FatType == FAT32) + FirstCluster = DeviceExt->FatInfo.RootCluster; else FirstCluster = 1; @@ -366,9 +346,9 @@ FindFile (PDEVICE_EXTENSION DeviceExt, CHECKPOINT; Fcb->PathName[0]='\\'; Fcb->ObjectName = &Fcb->PathName[1]; - Fcb->entry.FileSize = DeviceExt->rootDirectorySectors * BLOCKSIZE; + Fcb->entry.FileSize = DeviceExt->FatInfo.rootDirectorySectors * BLOCKSIZE; Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY; - if (DeviceExt->FatType == FAT32) + if (DeviceExt->FatInfo.FatType == FAT32) { Fcb->entry.FirstCluster = ((PUSHORT)FirstCluster)[0]; Fcb->entry.FirstClusterHigh = ((PUSHORT)FirstCluster)[1]; @@ -630,7 +610,11 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp) Irp->IoStatus.Status = Status; return Status; } - + if (Status == STATUS_INVALID_PARAMETER) + { + Irp->IoStatus.Status = Status; + return Status; + } if (Status == STATUS_DELETE_PENDING) { Irp->IoStatus.Status = Status; @@ -694,7 +678,7 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp) ULONG Cluster, NextCluster; /* FIXME set size to 0 and free clusters */ pFcb->entry.FileSize = 0; - if (DeviceExt->FatType == FAT32) + if (DeviceExt->FatInfo.FatType == FAT32) Cluster = pFcb->entry.FirstCluster + pFcb->entry.FirstClusterHigh * 65536; else @@ -726,15 +710,15 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp) ULONG CurrentCluster, NextCluster, i; DPRINT("Open an existing paging file\n"); pFcb->Flags |= FCB_IS_PAGE_FILE; - pFcb->FatChainSize = - ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) / DeviceExt->BytesPerCluster); + pFcb->FatChainSize = + ((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) / DeviceExt->FatInfo.BytesPerCluster); if (pFcb->FatChainSize) { pFcb->FatChain = ExAllocatePool(NonPagedPool, pFcb->FatChainSize * sizeof(ULONG)); } - if (DeviceExt->FatType == FAT32) + if (DeviceExt->FatInfo.FatType == FAT32) { CurrentCluster = pFcb->entry.FirstCluster + pFcb->entry.FirstClusterHigh * 65536; diff --git a/reactos/drivers/fs/vfat/dir.c b/reactos/drivers/fs/vfat/dir.c index 82b3dee59f9..2d4e954547c 100644 --- a/reactos/drivers/fs/vfat/dir.c +++ b/reactos/drivers/fs/vfat/dir.c @@ -1,5 +1,5 @@ /* - * $Id: dir.c,v 1.23 2002/02/05 21:31:03 hbirr Exp $ + * $Id: dir.c,v 1.24 2002/03/18 22:37:12 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -136,8 +136,8 @@ VfatGetFileDirectoryInformation (PVFATFCB pFcb, &pInfo->ChangeTime); pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize); /* Make allocsize a rounded up multiple of BytesPerCluster */ - AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) / - DeviceExt->BytesPerCluster) * DeviceExt->BytesPerCluster; + AllocSize = ((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) / + DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.BytesPerCluster; pInfo->AllocationSize.QuadPart = AllocSize; pInfo->FileAttributes = pFcb->entry.Attrib; @@ -170,8 +170,8 @@ VfatGetFileFullDirectoryInformation (PVFATFCB pFcb, &pInfo->ChangeTime); pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize); /* Make allocsize a rounded up multiple of BytesPerCluster */ - AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) / - DeviceExt->BytesPerCluster) * DeviceExt->BytesPerCluster; + AllocSize = ((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) / + DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.BytesPerCluster; pInfo->AllocationSize.QuadPart = AllocSize; pInfo->FileAttributes = pFcb->entry.Attrib; // pInfo->EaSize=; @@ -205,8 +205,8 @@ VfatGetFileBothInformation (PVFATFCB pFcb, &pInfo->ChangeTime); pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize); /* Make allocsize a rounded up multiple of BytesPerCluster */ - AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) / - DeviceExt->BytesPerCluster) * DeviceExt->BytesPerCluster; + AllocSize = ((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) / + DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.BytesPerCluster; pInfo->AllocationSize.QuadPart = AllocSize; pInfo->FileAttributes = pFcb->entry.Attrib; // pInfo->EaSize=; @@ -255,10 +255,11 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext) if (!pCcb->DirectorySearchPattern) { First = TRUE; - pCcb->DirectorySearchPattern = + pCcb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, pSearchPattern->Length + sizeof(WCHAR)); if (!pCcb->DirectorySearchPattern) { + ExReleaseResourceLite(&pFcb->MainResource); return STATUS_INSUFFICIENT_RESOURCES; } memcpy(pCcb->DirectorySearchPattern, pSearchPattern->Buffer, @@ -272,12 +273,13 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext) pCcb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR)); if (!pCcb->DirectorySearchPattern) { + ExReleaseResourceLite(&pFcb->MainResource); return STATUS_INSUFFICIENT_RESOURCES; } pCcb->DirectorySearchPattern[0] = L'*'; pCcb->DirectorySearchPattern[1] = 0; - } - + } + if (IrpContext->Stack->Flags & SL_INDEX_SPECIFIED) { pCcb->Entry = pCcb->CurrentByteOffset.u.LowPart; @@ -369,11 +371,7 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext) { RC = STATUS_SUCCESS; } - if (IrpContext->Flags & IRPCONTEXT_CANWAIT) - { - ExReleaseResourceLite(&pFcb->MainResource); - } - + ExReleaseResourceLite(&pFcb->MainResource); return RC; } diff --git a/reactos/drivers/fs/vfat/direntry.c b/reactos/drivers/fs/vfat/direntry.c index bbfda01aa07..910f7906aad 100644 --- a/reactos/drivers/fs/vfat/direntry.c +++ b/reactos/drivers/fs/vfat/direntry.c @@ -1,4 +1,4 @@ -/* $Id: direntry.c,v 1.5 2001/10/10 22:14:34 hbirr Exp $ +/* $Id: direntry.c,v 1.6 2002/03/18 22:37:12 hbirr Exp $ * * * FILE: DirEntry.c @@ -20,11 +20,11 @@ #include "vfat.h" -#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \ - (pDeviceExt)->BytesPerCluster : PAGESIZE) +#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGESIZE ? \ + (pDeviceExt)->FatInfo.BytesPerCluster : PAGESIZE) #define ENTRIES_PER_CACHEPAGE(pDeviceExt) (ENTRIES_PER_SECTOR * \ - (CACHEPAGESIZE(pDeviceExt) / ((pDeviceExt)->BytesPerSector))) + (CACHEPAGESIZE(pDeviceExt) / ((pDeviceExt)->FatInfo.BytesPerSector))) ULONG @@ -33,7 +33,7 @@ vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, { ULONG cluster; - if (pDeviceExt->FatType == FAT32) + if (pDeviceExt->FatInfo.FatType == FAT32) { cluster = pFatDirEntry->FirstCluster + pFatDirEntry->FirstClusterHigh * 65536; diff --git a/reactos/drivers/fs/vfat/dirwr.c b/reactos/drivers/fs/vfat/dirwr.c index 5d5a183a69d..82347c6bb32 100644 --- a/reactos/drivers/fs/vfat/dirwr.c +++ b/reactos/drivers/fs/vfat/dirwr.c @@ -1,4 +1,4 @@ -/* $Id: dirwr.c,v 1.23 2002/01/08 00:49:01 dwelch Exp $ +/* $Id: dirwr.c,v 1.24 2002/03/18 22:37:12 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -31,69 +31,10 @@ vfatIsShortIllegal(char c) return FALSE; } -/* - * Copies a file name into a directory slot (long file name entry) - * and fills trailing slot space with 0xFFFF. This keeps scandisk - * from complaining. - */ -static VOID -FillSlot (slot * Slot, WCHAR * FileName) -{ - BOOLEAN fill = FALSE; - WCHAR *src = FileName; - WCHAR *dst; - int i; - - i = 5; - dst = Slot->name0_4; - while (i-- > 0) - { - if (fill == FALSE) - *dst = *src; - else - *dst = 0xffff; - - if (fill == FALSE && (*src == 0)) - fill = TRUE; - dst++; - src++; - } - - i = 6; - dst = Slot->name5_10; - while (i-- > 0) - { - if (fill == FALSE) - *dst = *src; - else - *dst = 0xffff; - - if (fill == FALSE && (*src == 0)) - fill = TRUE; - dst++; - src++; - } - - i = 2; - dst = Slot->name11_12; - while (i-- > 0) - { - if (fill == FALSE) - *dst = *src; - else - *dst = 0xffff; - - if (fill == FALSE && (*src == 0)) - fill = TRUE; - dst++; - src++; - } -} - NTSTATUS updEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) /* - update an existing FAT entry -*/ + * update an existing FAT entry + */ { PVOID Context; PVOID Buffer; @@ -118,9 +59,10 @@ NTSTATUS updEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) return status; } - Offset.QuadPart = pFcb->dirIndex * sizeof(FATDirEntry); - if(CcMapData (pDirFcb->FileObject, &Offset, sizeof(FATDirEntry), - TRUE, &Context, &Buffer)) + Offset.u.HighPart = 0; + Offset.u.LowPart = pFcb->dirIndex * sizeof(FATDirEntry); + if (CcMapData (pDirFcb->FileObject, &Offset, sizeof(FATDirEntry), + TRUE, &Context, (PVOID*)&Buffer)) { memcpy(Buffer, &pFcb->entry, sizeof(FATDirEntry)); CcSetDirtyPinnedData(Context, NULL); @@ -128,42 +70,147 @@ NTSTATUS updEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) } else DPRINT1 ("Failed write to \'%S\'.\n", pDirFcb->PathName); - vfatReleaseFCB(DeviceExt, pDirFcb); + vfatReleaseFCB(DeviceExt, pDirFcb); return STATUS_SUCCESS; } +BOOLEAN +findDirSpace(PDEVICE_EXTENSION DeviceExt, + PVFATFCB pDirFcb, + ULONG nbSlots, + PULONG start) +{ +/* + * try to find contiguous entries frees in directory, + * extend a directory if is neccesary + */ + LARGE_INTEGER FileOffset; + ULONG i, count, size, nbFree = 0; + FATDirEntry* pFatEntry; + PVOID Context = NULL; + NTSTATUS Status; + FileOffset.QuadPart = 0; + count = pDirFcb->RFCB.FileSize.u.LowPart / sizeof(FATDirEntry); + size = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry); + for (i = 0; i < count; i++, pFatEntry++) + { + if (Context == NULL || (i % size) == 0) + { + if (Context) + { + CcUnpinData(Context); + } + // FIXME: check return value + CcMapData (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, + TRUE, &Context, (PVOID*)&pFatEntry); + FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster; + } + if (vfatIsDirEntryEndMarker(pFatEntry)) + { + break; + } + if (vfatIsDirEntryDeleted(pFatEntry)) + { + nbFree++; + } + else + { + nbFree = 0; + } + if (nbFree == nbSlots) + { + break; + } + } + if (Context) + { + CcUnpinData(Context); + } + if (nbFree == nbSlots) + { + // found enough contiguous free slots + *start = i - nbSlots + 1; + } + else + { + *start = i - nbFree; + if (*start + nbSlots > count) + { + CHECKPOINT; + // extend the directory + if (vfatFCBIsRoot(pDirFcb) && DeviceExt->FatInfo.FatType != FAT32) + { + // We can't extend a root directory on a FAT12/FAT16 partition + return FALSE; + } + Status = vfatExtendSpace (DeviceExt, pDirFcb->FileObject, + pDirFcb->RFCB.FileSize.u.LowPart + DeviceExt->FatInfo.BytesPerCluster); + if (!NT_SUCCESS(Status)) + { + return FALSE; + } + // clear the new dir cluster + FileOffset.u.LowPart = pDirFcb->RFCB.FileSize.QuadPart - + DeviceExt->FatInfo.BytesPerCluster; + CcMapData (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, + TRUE, &Context, (PVOID*)&pFatEntry); + RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster); + } + else if (*start + nbSlots < count) + { + // clear the entry after the last new entry + FileOffset.u.LowPart = (*start + nbSlots) * sizeof(FATDirEntry); + CcMapData (pDirFcb->FileObject, &FileOffset, sizeof(FATDirEntry), + TRUE, &Context, (PVOID*)&pFatEntry); + RtlZeroMemory(pFatEntry, sizeof(FATDirEntry)); + } + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + } + DPRINT ("nbSlots %d nbFree %d, entry number %d\n", nbSlots, nbFree, *start); + return TRUE; +} + NTSTATUS addEntry (PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT pFileObject, ULONG RequestedOptions, UCHAR ReqAttr) + PFILE_OBJECT pFileObject, + ULONG RequestedOptions, + UCHAR ReqAttr) /* create a new FAT entry */ { WCHAR DirName[MAX_PATH], *FileName, *PathFileName; VFATFCB FileFcb; - FATDirEntry FatEntry; - NTSTATUS status; - FATDirEntry *pEntry; + PVOID Context = NULL; + FATDirEntry *pFatEntry, *pEntry; slot *pSlots; - ULONG LengthRead, Offset; - short nbSlots = 0, nbFree = 0, i, j, posCar, NameLen; - PUCHAR Buffer, Buffer2; + short nbSlots = 0, nbFree = 0, j, posCar, NameLen; + PUCHAR Buffer; BOOLEAN needTilde = FALSE, needLong = FALSE; PVFATFCB newFCB; ULONG CurrentCluster; - LARGE_INTEGER SystemTime, LocalTime; + LARGE_INTEGER SystemTime, LocalTime, FileOffset; NTSTATUS Status = STATUS_SUCCESS; PVFATFCB pDirFcb; + ULONG start, size; + long i; PathFileName = pFileObject->FileName.Buffer; DPRINT ("addEntry: Pathname=%S\n", PathFileName); //find last \ in PathFileName posCar = -1; for (i = 0; PathFileName[i]; i++) - if (PathFileName[i] == '\\') + { + if (PathFileName[i] == L'\\') + { posCar = i; + } + } if (posCar == -1) + { return STATUS_UNSUCCESSFUL; + } FileName = &PathFileName[posCar + 1]; for (NameLen = 0; FileName[NameLen]; NameLen++); // extract directory name from pathname @@ -186,9 +233,8 @@ addEntry (PDEVICE_EXTENSION DeviceExt, } nbSlots = (NameLen + 12) / 13 + 1; //nb of entry needed for long name+normal entry DPRINT ("NameLen= %d, nbSlots =%d\n", NameLen, nbSlots); - Buffer = - ExAllocatePool (NonPagedPool, (nbSlots + 1) * sizeof (FATDirEntry)); - memset (Buffer, 0, (nbSlots + 1) * sizeof (FATDirEntry)); + Buffer = ExAllocatePool (NonPagedPool, nbSlots * sizeof (FATDirEntry)); + RtlZeroMemory (Buffer, nbSlots * sizeof (FATDirEntry)); pEntry = (FATDirEntry *) (Buffer + (nbSlots - 1) * sizeof (FATDirEntry)); pSlots = (slot *) Buffer; // create 8.3 name @@ -196,21 +242,29 @@ addEntry (PDEVICE_EXTENSION DeviceExt, // find last point in name posCar = j = 0; for (i = 0; FileName[i]; i++) + { if (FileName[i] == '.') { posCar = i; if (i == j) + { j++; + } } + } if (!posCar) + { posCar = i; + } if (posCar < j) { posCar = i; needTilde = TRUE; } if (posCar > 8) + { needTilde = TRUE; + } //copy 8 characters max memset (pEntry, ' ', 11); for (i = 0, j = 0; j < 8 && i < posCar; i++) @@ -223,13 +277,18 @@ addEntry (PDEVICE_EXTENSION DeviceExt, else { if (FileName[i] == '.') + { needTilde = TRUE; + } else + { pEntry->Filename[j++] = toupper ((char) FileName[i]); + } } } //copy extension if (FileName[posCar]) + { for (j = 0, i = posCar + 1; FileName[i] && j < 3; i++) { if (vfatIsShortIllegal(FileName[i])) @@ -240,13 +299,20 @@ addEntry (PDEVICE_EXTENSION DeviceExt, else { if (FileName[i] == '.') + { needTilde = TRUE; + } else - pEntry->Ext[j++] = toupper ((char) (FileName[i] & 0x7F)); + { + pEntry->Ext[j++] = toupper ((char) (FileName[i] & 0x7F)); + } } } + } if (FileName[i]) + { needTilde = TRUE; + } //find good value for tilde if (needTilde) { @@ -254,10 +320,14 @@ addEntry (PDEVICE_EXTENSION DeviceExt, DPRINT ("searching a good value for tilde\n"); for (posCar = 0; posCar < 8 && pEntry->Filename[posCar] != ' '; posCar++); if (posCar == 0) // ?????????????????????? + { pEntry->Filename[posCar++] = '_'; + } posCar += 2; if (posCar > 8) + { posCar = 8; + } pEntry->Filename[posCar - 2] = '~'; pEntry->Filename[posCar - 1] = '1'; vfat8Dot3ToString (pEntry->Filename, pEntry->Ext, DirName); @@ -266,15 +336,19 @@ addEntry (PDEVICE_EXTENSION DeviceExt, { DirName[posCar-1] = '0' + i; pEntry->Filename[posCar - 1] = '0' + i; - status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL); - if (!NT_SUCCESS(status)) - break; + Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL); + if (!NT_SUCCESS(Status)) + { + break; + } } if (i == 10) { posCar++; if (posCar > 8) + { posCar = 8; + } pEntry->Filename[posCar - 3] = '~'; pEntry->Filename[posCar - 2] = '1'; pEntry->Filename[posCar - 1] = '0'; @@ -286,38 +360,44 @@ addEntry (PDEVICE_EXTENSION DeviceExt, DirName[posCar - 2] = '0' + i / 10; pEntry->Filename[posCar - 1] = '0' + i % 10; pEntry->Filename[posCar - 2] = '0' + i / 10; - status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL); - if (!NT_SUCCESS(status)) - break; + Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL); + if (!NT_SUCCESS(Status)) + { + break; + } } if (i == 100) //FIXME : what to do after 99 tilde ? - { - vfatReleaseFCB(DeviceExt, pDirFcb); - ExFreePool (Buffer); - return STATUS_UNSUCCESSFUL; - } + { + vfatReleaseFCB(DeviceExt, pDirFcb); + ExFreePool (Buffer); + return STATUS_UNSUCCESSFUL; + } } } else { DPRINT ("check if long name entry needed, needlong=%d\n", needLong); for (i = 0; i < posCar; i++) - if ((USHORT) pEntry->Filename[i] != FileName[i]) - { - DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]); - needLong = TRUE; - } - if (FileName[i]) - { - i++; //jump on point char - for (j = 0, i = posCar + 1; FileName[i] && i < posCar + 4; i++) - if ((USHORT) pEntry->Ext[j++] != FileName[i]) - { - DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Filename[i], - FileName[i]); + { + if ((USHORT) pEntry->Filename[i] != FileName[i]) + { + DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]); needLong = TRUE; } } + if (FileName[i]) + { + i++; //jump on point char + for (j = 0, i = posCar + 1; FileName[i] && i < posCar + 4; i++) + { + if ((USHORT) pEntry->Ext[j++] != FileName[i]) + { + DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Filename[i], + FileName[i]); + needLong = TRUE; + } + } + } } if (needLong == FALSE) { @@ -337,150 +417,148 @@ addEntry (PDEVICE_EXTENSION DeviceExt, /* set attributes */ pEntry->Attrib = ReqAttr; if (RequestedOptions & FILE_DIRECTORY_FILE) + { pEntry->Attrib |= FILE_ATTRIBUTE_DIRECTORY; - + } /* set dates and times */ KeQuerySystemTime (&SystemTime); ExSystemTimeToLocalTime (&SystemTime, &LocalTime); - FsdFileTimeToDosDateTime ((TIME *) & LocalTime, - &pEntry->CreationDate, &pEntry->CreationTime); + FsdFileTimeToDosDateTime ((TIME *) & LocalTime, &pEntry->CreationDate, + &pEntry->CreationTime); pEntry->UpdateDate = pEntry->CreationDate; pEntry->UpdateTime = pEntry->CreationTime; pEntry->AccessDate = pEntry->CreationDate; // calculate checksum for 8.3 name for (pSlots[0].alias_checksum = i = 0; i < 11; i++) - { - pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7 - | ((pSlots[0].alias_checksum & 0xfe) >> 1)) - + pEntry->Filename[i]); - } + { + pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7 + | ((pSlots[0].alias_checksum & 0xfe) >> 1)) + + pEntry->Filename[i]); + } //construct slots and entry for (i = nbSlots - 2; i >= 0; i--) + { + DPRINT ("construct slot %d\n", i); + pSlots[i].attr = 0xf; + if (i) { - DPRINT ("construct slot %d\n", i); - pSlots[i].attr = 0xf; - if (i) - pSlots[i].id = nbSlots - i - 1; - else - pSlots[i].id = nbSlots - i - 1 + 0x40; - pSlots[i].alias_checksum = pSlots[0].alias_checksum; -//FIXME pSlots[i].start=; - FillSlot (&pSlots[i], FileName + (nbSlots - i - 2) * 13); + pSlots[i].id = nbSlots - i - 1; } + else + { + pSlots[i].id = nbSlots - i - 1 + 0x40; + } + pSlots[i].alias_checksum = pSlots[0].alias_checksum; +//FIXME pSlots[i].start=; + memcpy (pSlots[i].name0_4, DirName + (nbSlots - i - 2) * 13, 10); + memcpy (pSlots[i].name5_10, DirName + (nbSlots - i - 2) * 13 + 5, 12); + memcpy (pSlots[i].name11_12, DirName + (nbSlots - i - 2) * 13 + 11, 4); + } //try to find nbSlots contiguous entries frees in directory - for (i = 0, status = STATUS_SUCCESS; status == STATUS_SUCCESS; i++) - { - status = - VfatReadFile (DeviceExt, pDirFcb->FileObject, - &FatEntry, sizeof (FATDirEntry), - i * sizeof (FATDirEntry), &LengthRead, FALSE); - if (status == STATUS_END_OF_FILE) - break; - if (!NT_SUCCESS (status)) - { - DPRINT1 ("VfatReadFile failed to read the directory entry\n"); - break; - } - if (LengthRead != sizeof (FATDirEntry)) - { - DPRINT1 ("VfatReadFile did not read a complete directory entry\n"); - break; - } - if (vfatIsDirEntryEndMarker(&FatEntry)) - break; - if (vfatIsDirEntryDeleted(&FatEntry)) - nbFree++; - else - nbFree = 0; - - if (nbFree == nbSlots) - break; - } - DPRINT ("nbSlots %d nbFree %d, entry number %d\n", nbSlots, nbFree, i); + if (!findDirSpace(DeviceExt, pDirFcb, nbSlots, &start)) + { + vfatReleaseFCB(DeviceExt, pDirFcb); + ExFreePool (Buffer); + return STATUS_DISK_FULL; + } if (RequestedOptions & FILE_DIRECTORY_FILE) - { + { CurrentCluster = 0xffffffff; - status = NextCluster (DeviceExt, NULL, 0, &CurrentCluster, TRUE); - if (CurrentCluster == 0xffffffff || !NT_SUCCESS(status)) + Status = NextCluster (DeviceExt, NULL, 0, &CurrentCluster, TRUE); + if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status)) { vfatReleaseFCB(DeviceExt, pDirFcb); ExFreePool (Buffer); - if (!NT_SUCCESS(status)) + if (!NT_SUCCESS(Status)) { - return status; + return Status; } return STATUS_DISK_FULL; } - // zero the cluster - Buffer2 = ExAllocatePool (NonPagedPool, DeviceExt->BytesPerCluster); - memset (Buffer2, 0, DeviceExt->BytesPerCluster); - VfatRawWriteCluster (DeviceExt, 0, Buffer2, CurrentCluster, 1); - ExFreePool (Buffer2); - if (DeviceExt->FatType == FAT32) - { - pEntry->FirstClusterHigh = CurrentCluster >> 16; - pEntry->FirstCluster = CurrentCluster; - } - else - pEntry->FirstCluster = CurrentCluster; - } - if (nbFree == nbSlots) - { //use old slots - Offset = (i - nbSlots + 1) * sizeof (FATDirEntry); - status = - VfatWriteFile (DeviceExt, pDirFcb->FileObject, - Buffer, sizeof (FATDirEntry) * nbSlots, - Offset, FALSE, FALSE); - DPRINT ("VfatWriteFile() returned: %x\n", status); - } - else - { //write at end of directory - Offset = (i - nbFree) * sizeof (FATDirEntry); - status = - VfatWriteFile (DeviceExt, pDirFcb->FileObject, - Buffer, sizeof (FATDirEntry) * (nbSlots + 1), - Offset, FALSE, FALSE); - } - DPRINT ("write entry offset %d status=%x\n", Offset, status); - if (!NT_SUCCESS(status)) - { - vfatReleaseFCB (DeviceExt, pDirFcb); - if (RequestedOptions & FILE_DIRECTORY_FILE) + if (DeviceExt->FatInfo.FatType == FAT32) { - // free the reserved cluster - WriteCluster(DeviceExt, CurrentCluster, 0); + pEntry->FirstClusterHigh = CurrentCluster >> 16; } - ExFreePool (Buffer); - return status; + pEntry->FirstCluster = CurrentCluster; } + size = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry); + if (start / size == (start + nbSlots - 1) / size) + { + // one cluster + CHECKPOINT; + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = start * sizeof(FATDirEntry); + CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FATDirEntry), + TRUE, &Context, (PVOID*)&pFatEntry); + memcpy(pFatEntry, Buffer, nbSlots * sizeof(FATDirEntry)); + } + else + { + // two clusters + CHECKPOINT; + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = start * sizeof(FATDirEntry); + size = DeviceExt->FatInfo.BytesPerCluster - + (start * sizeof(FATDirEntry)) % DeviceExt->FatInfo.BytesPerCluster; + CcMapData (pDirFcb->FileObject, &FileOffset, size, TRUE, + &Context, (PVOID*)&pFatEntry); + memcpy(pFatEntry, Buffer, size); + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + FileOffset.u.LowPart += size; + CcMapData (pDirFcb->FileObject, &FileOffset, + nbSlots * sizeof(FATDirEntry) - size, + TRUE, &Context, (PVOID*)&pFatEntry); + memcpy(pFatEntry, (PVOID)Buffer + size, nbSlots * sizeof(FATDirEntry) - size); + } + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + // FEXME: check status - vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, FileName, - pEntry, Offset / sizeof(FATDirEntry) + nbSlots-1, &newFCB); + vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, FileName, pEntry, + start + nbSlots - 1, &newFCB); vfatAttachFCBToFileObject (DeviceExt, newFCB, pFileObject); DPRINT ("new : entry=%11.11s\n", newFCB->entry.Filename); DPRINT ("new : entry=%11.11s\n", pEntry->Filename); if (RequestedOptions & FILE_DIRECTORY_FILE) + { + FileOffset.QuadPart = 0; + CcMapData (pFileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE, + &Context, (PVOID*)&pFatEntry); + // clear the new directory cluster + RtlZeroMemory (pFatEntry, DeviceExt->FatInfo.BytesPerCluster); + // create '.' and '..' + memcpy (&pFatEntry[0].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11); + memcpy (pFatEntry[0].Filename, ". ", 11); + memcpy (&pFatEntry[1].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11); + memcpy (pFatEntry[1].Filename, ".. ", 11); + pFatEntry[1].FirstCluster = pDirFcb->entry.FirstCluster; + pFatEntry[1].FirstClusterHigh = pDirFcb->entry.FirstClusterHigh; + if (DeviceExt->FatInfo.FatType == FAT32) { - // create . and .. - memcpy (pEntry->Filename, ". ", 11); - status = - VfatWriteFile (DeviceExt, pFileObject, pEntry, sizeof (FATDirEntry), - 0L, FALSE, FALSE); - pEntry->FirstCluster = pDirFcb->entry.FirstCluster; - pEntry->FirstClusterHigh = pDirFcb->entry.FirstClusterHigh; - memcpy (pEntry->Filename, ".. ", 11); - if (pEntry->FirstCluster == 1 && DeviceExt->FatType != FAT32) - pEntry->FirstCluster = 0; - status = - VfatWriteFile (DeviceExt, pFileObject, pEntry, sizeof (FATDirEntry), - sizeof (FATDirEntry), FALSE, FALSE); + if (pFatEntry[1].FirstCluster == (DeviceExt->FatInfo.RootCluster & 0xffff) && + pFatEntry[1].FirstClusterHigh == (DeviceExt->FatInfo.RootCluster >> 16)) + { + pFatEntry[1].FirstCluster = 0; + pFatEntry[1].FirstClusterHigh = 0; + } } + else + { + if (pFatEntry[1].FirstCluster == 1) + { + pFatEntry[1].FirstCluster = 0; + } + } + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + } vfatReleaseFCB (DeviceExt, pDirFcb); ExFreePool (Buffer); DPRINT ("addentry ok\n"); @@ -490,8 +568,8 @@ addEntry (PDEVICE_EXTENSION DeviceExt, NTSTATUS delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) /* - deleting an existing FAT entry -*/ + * deleting an existing FAT entry + */ { VFATFCB Fcb; PVFATFCB pFcb = NULL, pDirFcb = NULL; @@ -502,7 +580,8 @@ delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) DPRINT ("delEntry PathFileName \'%S\'\n", pFileObject->FileName.Buffer); - status = vfatGetFCBForFile(DeviceExt, &pDirFcb, &pFcb, pFileObject->FileName.Buffer); + status = vfatGetFCBForFile(DeviceExt, &pDirFcb, &pFcb, + pFileObject->FileName.Buffer); if (pFcb != NULL) { vfatReleaseFCB(DeviceExt, pFcb); @@ -524,18 +603,38 @@ delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) if (NT_SUCCESS(status)) { + PVOID Context = NULL; + LARGE_INTEGER Offset; + FATDirEntry* pDirEntry; DPRINT ("delete entry: %d to %d\n", startEntry, Entry); + Offset.u.HighPart = 0; for (i = startEntry; i <= Entry; i++) { - // FIXME: using Cc-functions - VfatReadFile (DeviceExt, pDirFcb->FileObject, &DirEntry, - sizeof (FATDirEntry), i * sizeof(FATDirEntry), &Read, FALSE); - DirEntry.Filename[0] = 0xe5; - // FIXME: check status - VfatWriteFile (DeviceExt, pDirFcb->FileObject, &DirEntry, - sizeof(FATDirEntry), i * sizeof(FATDirEntry), FALSE, FALSE); + if (Context == NULL || ((i * sizeof(FATDirEntry)) % PAGESIZE) == 0) + { + if (Context) + { + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + } + Offset.u.LowPart = (i * sizeof(FATDirEntry) / PAGESIZE) * PAGESIZE; + CcMapData (pDirFcb->FileObject, &Offset, PAGESIZE, TRUE, + &Context, (PVOID*)&pDirEntry); + } + pDirEntry[i % (PAGESIZE / sizeof(FATDirEntry))].Filename[0] = 0xe5; + if (i == Entry) + { + CurrentCluster = + vfatDirEntryGetFirstCluster (DeviceExt, + &pDirEntry[i % (PAGESIZE / sizeof(FATDirEntry))]); + } } - CurrentCluster = vfatDirEntryGetFirstCluster (DeviceExt, &DirEntry); + if (Context) + { + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + } + while (CurrentCluster && CurrentCluster != 0xffffffff) { GetNextCluster (DeviceExt, CurrentCluster, &NextCluster, FALSE); @@ -544,6 +643,7 @@ delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) CurrentCluster = NextCluster; } } + vfatReleaseFCB(DeviceExt, pDirFcb); return status; } diff --git a/reactos/drivers/fs/vfat/fat.c b/reactos/drivers/fs/vfat/fat.c index d828519aa0c..9ec2f05f7d2 100644 --- a/reactos/drivers/fs/vfat/fat.c +++ b/reactos/drivers/fs/vfat/fat.c @@ -1,5 +1,5 @@ /* - * $Id: fat.c,v 1.35 2001/11/20 23:40:26 hbirr Exp $ + * $Id: fat.c,v 1.36 2002/03/18 22:37:12 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -24,8 +24,8 @@ #define ROUND_DOWN(N, S) ((N) - ((N) % (S))) -#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \ - (pDeviceExt)->BytesPerCluster : PAGESIZE) +#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGESIZE ? \ + (pDeviceExt)->FatInfo.BytesPerCluster : PAGESIZE) /* FUNCTIONS ****************************************************************/ @@ -98,7 +98,7 @@ Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt, * FUNCTION: Retrieve the next FAT12 cluster from the FAT table */ { - PUCHAR CBlock; + PUSHORT CBlock; ULONG FATOffset; ULONG Entry; NTSTATUS Status; @@ -110,22 +110,18 @@ Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt, *NextCluster = 0; Offset.QuadPart = 0; - if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->Boot->FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress)) + if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress)) { return STATUS_UNSUCCESSFUL; } - CBlock = (PUCHAR)BaseAddress; - - FATOffset = (CurrentCluster * 12) / 8; /* first byte containing value */ + CBlock = (PUSHORT)(BaseAddress + (CurrentCluster * 12) / 8); if ((CurrentCluster % 2) == 0) { - Entry = CBlock[FATOffset]; - Entry |= ((CBlock[FATOffset+1] & 0xf)<<8); + Entry = *CBlock & 0x0fff; } else { - Entry = (CBlock[FATOffset] >> 4); - Entry |= (CBlock[FATOffset+1] << 4); + Entry = *CBlock >> 4; } // DPRINT("Entry %x\n",Entry); if (Entry >= 0xff8 && Entry <= 0xfff) @@ -152,15 +148,16 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, ULONG ChunkSize; PVOID Context = 0; LARGE_INTEGER Offset; + PUSHORT Block; ChunkSize = CACHEPAGESIZE(DeviceExt); - FatLength = DeviceExt->NumberOfClusters * 2; + FatLength = (DeviceExt->FatInfo.NumberOfClusters +2 ) * 2; *Cluster = 0; StartCluster = DeviceExt->LastAvailableCluster; for (j = 0; j < 2; j++) { - for (i = StartCluster * 2; i < FatLength; i += 2) + for (i = StartCluster * 2; i < FatLength; i += 2, Block++) { if ((i % ChunkSize) == 0 || Context == NULL) { @@ -169,14 +166,17 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, { CcUnpinData(Context); } + CHECKPOINT; if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize); return STATUS_UNSUCCESSFUL; } + CHECKPOINT; + Block = (PUSHORT)(BaseAddress + i % ChunkSize); } - if (*((PUSHORT)(BaseAddress + (i % ChunkSize))) == 0) + if (*Block == 0) { DPRINT("Found available cluster 0x%x\n", i / 2); DeviceExt->LastAvailableCluster = *Cluster = i / 2; @@ -186,8 +186,12 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, } FatLength = StartCluster * 2; StartCluster = 2; + if (Context != NULL) + { + CcUnpinData(Context); + Context =NULL; + } } - CcUnpinData(Context); return(STATUS_DISK_FULL); } @@ -201,38 +205,35 @@ FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster) ULONG FATOffset; ULONG StartCluster; ULONG Entry; - PUCHAR CBlock; + PUSHORT CBlock; ULONG i, j; PVOID BaseAddress; NTSTATUS Status; PVOID Context; LARGE_INTEGER Offset; - FatLength = DeviceExt->NumberOfClusters; + FatLength = DeviceExt->FatInfo.NumberOfClusters + 2; *Cluster = 0; StartCluster = DeviceExt->LastAvailableCluster; Offset.QuadPart = 0; - if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->Boot->FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress)) + if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress)) { - DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, DeviceExt->Boot->FATSectors * BLOCKSIZE); + DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, DeviceExt->FatInfo.FATSectors * BLOCKSIZE); return STATUS_UNSUCCESSFUL; } - CBlock = (PUCHAR)BaseAddress; for (j = 0; j < 2; j++) { for (i = StartCluster; i < FatLength; i++) { - FATOffset = (i * 12) / 8; + CBlock = (PUSHORT)(BaseAddress + (i * 12) / 8); if ((i % 2) == 0) { - Entry = CBlock[FATOffset]; - Entry |= ((CBlock[FATOffset + 1] & 0xf) << 8); + Entry = *CBlock & 0xfff; } else { - Entry = (CBlock[FATOffset] >> 4); - Entry |= (CBlock[FATOffset + 1] << 4); + Entry = *CBlock >> 4; } if (Entry == 0) { @@ -256,243 +257,229 @@ FAT32FindAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster) */ { ULONG FatLength; - ULONG i; + ULONG StartCluster; + ULONG i, j; NTSTATUS Status; PVOID BaseAddress; ULONG ChunkSize; - PVOID Context = NULL; + PVOID Context = 0; LARGE_INTEGER Offset; - ULONG StartCluster; + PULONG Block; ChunkSize = CACHEPAGESIZE(DeviceExt); - FatLength = DeviceExt->NumberOfClusters * 4; - StartCluster = DeviceExt->LastAvailableCluster; - if (StartCluster == 0) - { - StartCluster = 2; - } - + FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4; *Cluster = 0; + StartCluster = DeviceExt->LastAvailableCluster; - for (i = StartCluster * 4; i < FatLength; i += 4) + for (j = 0; j < 2; j++) { - if ((i % ChunkSize) == 0 || Context == NULL) - { - Offset.QuadPart = ROUND_DOWN(i, ChunkSize); - if (Context != NULL) + for (i = StartCluster * 4; i < FatLength; i += 4, Block++) + { + if ((i % ChunkSize) == 0 || Context == NULL) { + Offset.QuadPart = ROUND_DOWN(i, ChunkSize); + if (Context != NULL) + { + CcUnpinData(Context); + } + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + { + DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize); + return STATUS_UNSUCCESSFUL; + } + Block = (PULONG)(BaseAddress + i % ChunkSize); + } + + if ((*Block & 0x0fffffff) == 0) + { + DPRINT("Found available cluster 0x%x\n", i / 4); + DeviceExt->LastAvailableCluster = *Cluster = i / 4; CcUnpinData(Context); + return(STATUS_SUCCESS); } - if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) - { - DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize); - return STATUS_UNSUCCESSFUL; - } - } - if ((*((PULONG)(BaseAddress + (i % ChunkSize))) & 0x0fffffff) == 0) - { - DPRINT("Found available cluster 0x%x\n", i / 4); - DeviceExt->LastAvailableCluster = *Cluster = i / 4; + } + FatLength = StartCluster * 4; + StartCluster = 2; + if (Context != NULL) + { CcUnpinData(Context); - return(STATUS_SUCCESS); - } + Context=NULL; + } } - FatLength = StartCluster * 4; - for (i = 8; i < FatLength; i += 4) - { - if ((i % ChunkSize) == 0 || Context == NULL) - { - Offset.QuadPart = ROUND_DOWN(i, ChunkSize); - if (Context != NULL) - { - CcUnpinData(Context); - } - if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) - { - DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize); - return STATUS_UNSUCCESSFUL; - } - } - if ((*((PULONG)(BaseAddress + (i % ChunkSize))) & 0x0fffffff) == 0) - { - DPRINT("Found available cluster 0x%x\n", i / 4); - DeviceExt->LastAvailableCluster = *Cluster = i / 4; - CcUnpinData(Context); - return(STATUS_SUCCESS); - } - } - CcUnpinData(Context); return (STATUS_DISK_FULL); } NTSTATUS -FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER Clusters) +FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt) /* * FUNCTION: Counts free cluster in a FAT12 table */ { ULONG FATOffset; ULONG Entry; - PUCHAR CBlock; + PVOID BaseAddress; ULONG ulCount = 0; ULONG i; - PVOID BaseAddress; NTSTATUS Status; ULONG numberofclusters; LARGE_INTEGER Offset; PVOID Context; + PUSHORT CBlock; - ExAcquireResourceSharedLite (&DeviceExt->FatResource, TRUE); Offset.QuadPart = 0; - if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->Boot->FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress)) + if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress)) { - ExReleaseResourceLite (&DeviceExt->FatResource); return STATUS_UNSUCCESSFUL; } - CBlock = (PUCHAR)BaseAddress; - numberofclusters = DeviceExt->NumberOfClusters; + + numberofclusters = DeviceExt->FatInfo.NumberOfClusters + 2; for (i = 2; i < numberofclusters; i++) { - FATOffset = (i * 12) / 8; + CBlock = (PUSHORT)(BaseAddress + (i * 12) / 8); if ((i % 2) == 0) { - Entry = CBlock[FATOffset]; - Entry |= ((CBlock[FATOffset + 1] & 0xf) << 8); + Entry = *CBlock & 0x0fff; } else { - Entry = (CBlock[FATOffset] >> 4); - Entry |= (CBlock[FATOffset + 1] << 4); + Entry = *CBlock >> 4; } if (Entry == 0) ulCount++; } CcUnpinData(Context); - ExReleaseResourceLite (&DeviceExt->FatResource); - - Clusters->QuadPart = ulCount; + DeviceExt->AvailableClusters = ulCount; + DeviceExt->AvailableClustersValid = TRUE; return(STATUS_SUCCESS); } NTSTATUS -FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER Clusters) +FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt) /* * FUNCTION: Counts free clusters in a FAT16 table */ { PUSHORT Block; + PVOID BaseAddress = NULL; ULONG ulCount = 0; ULONG i; - ULONG numberofclusters; - ULONG numberofsectors; - ULONG sector; - ULONG forto; + ULONG ChunkSize; NTSTATUS Status; + PVOID Context = NULL; + LARGE_INTEGER Offset; + ULONG FatLength; - ExAcquireResourceSharedLite (&DeviceExt->FatResource, TRUE); - Block = ExAllocatePool (NonPagedPool, BLOCKSIZE); + ChunkSize = CACHEPAGESIZE(DeviceExt); + FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 2; - numberofclusters = ((DeviceExt->Boot->Sectors ? DeviceExt->Boot->Sectors : DeviceExt->Boot->SectorsHuge)-DeviceExt->dataStart)/DeviceExt->Boot->SectorsPerCluster+2; - numberofsectors = (numberofclusters + 255) / 256; - numberofclusters %= 256; - - for (sector = 0; sector < numberofsectors; sector++) + for (i = 4; i< FatLength; i += 2, Block++) + { + if ((i % ChunkSize) == 0 || Context == NULL) { - Status = VfatReadSectors(DeviceExt->StorageDevice, - DeviceExt->FATStart + sector, - 1, - (PUCHAR)Block); - if (!NT_SUCCESS(Status)) + DPRINT("%d\n", i/2); + if (Context) { - ExFreePool(Block); - ExReleaseResourceLite(&DeviceExt->FatResource); - return(Status); + CcUnpinData(Context); } - - if (sector == numberofsectors - 1) - forto = numberofclusters; - else - forto = 256; - - for (i = 0; i < forto; i++) + Offset.QuadPart = ROUND_DOWN(i, ChunkSize); + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { - if (Block[i] == 0) + return STATUS_UNSUCCESSFUL; + } + Block = (PUSHORT)(BaseAddress + i % ChunkSize); + } + if (*Block == 0) ulCount++; } - } - ExReleaseResourceLite (&DeviceExt->FatResource); - Clusters->QuadPart = ulCount; - ExFreePool(Block); + DeviceExt->AvailableClusters = ulCount; + DeviceExt->AvailableClustersValid = TRUE; + CcUnpinData(Context); return(STATUS_SUCCESS); } NTSTATUS -FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER Clusters) +FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt) /* * FUNCTION: Counts free clusters in a FAT32 table */ { - ULONG sector; PULONG Block; + PVOID BaseAddress = NULL; ULONG ulCount = 0; - ULONG i,forto; - ULONG numberofclusters; - ULONG numberofsectors; + ULONG i; + ULONG ChunkSize; NTSTATUS Status; + PVOID Context = NULL; + LARGE_INTEGER Offset; + ULONG FatLength; - ExAcquireResourceSharedLite (&DeviceExt->FatResource, TRUE); + ChunkSize = CACHEPAGESIZE(DeviceExt); + FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4; - Block = ExAllocatePool (NonPagedPool, BLOCKSIZE); - - numberofclusters = ((DeviceExt->Boot->Sectors ? DeviceExt->Boot->Sectors : DeviceExt->Boot->SectorsHuge)-DeviceExt->dataStart)/DeviceExt->Boot->SectorsPerCluster+2; - numberofsectors = (numberofclusters +127) / 128; - numberofclusters %= 128; - - for (sector = 0; sector < numberofsectors; sector++) - { - Status = VfatReadSectors(DeviceExt->StorageDevice, - (ULONG) (DeviceExt->FATStart + sector), 1, - (UCHAR *) Block); - if (!NT_SUCCESS(Status)) + for (i = 8; i< FatLength; i += 4, Block++) + { + if ((i % ChunkSize) == 0 || Context == NULL) + { + if (Context) { - ExFreePool(Block); - ExReleaseResourceLite(&DeviceExt->FatResource); - return(Status); + CcUnpinData(Context); } - - if (sector == numberofsectors - 1) - forto=numberofclusters; - else - forto=128; - for (i = 0; i < forto; i++) + Offset.QuadPart = ROUND_DOWN(i, ChunkSize); + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { - if ((Block[i] & 0x0fffffff) == 0) - ulCount++; + return STATUS_UNSUCCESSFUL; } - } - ExFreePool (Block); - ExReleaseResourceLite (&DeviceExt->FatResource); + Block = (PULONG)(BaseAddress + i % ChunkSize); + } + if ((*Block & 0x0fffffff) == 0) + ulCount++; + } - Clusters->QuadPart = ulCount; + DeviceExt->AvailableClusters = ulCount; + DeviceExt->AvailableClustersValid = TRUE; + CcUnpinData(Context); return(STATUS_SUCCESS); } +NTSTATUS +CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER Clusters) +{ + NTSTATUS Status = STATUS_SUCCESS; + ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE); + if (!DeviceExt->AvailableClustersValid) + { + if (DeviceExt->FatInfo.FatType == FAT12) + Status = FAT12CountAvailableClusters(DeviceExt); + else if (DeviceExt->FatInfo.FatType == FAT16) + Status = FAT16CountAvailableClusters(DeviceExt); + else + Status = FAT32CountAvailableClusters(DeviceExt); + } + Clusters->QuadPart = DeviceExt->AvailableClusters; + ExReleaseResourceLite (&DeviceExt->FatResource); + + return Status; +} + + + + + NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, - ULONG NewValue) + ULONG NewValue, + PULONG OldValue) /* * FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables */ @@ -507,7 +494,7 @@ FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, LARGE_INTEGER Offset; Offset.QuadPart = 0; - if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->Boot->FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress)) + if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress)) { return STATUS_UNSUCCESSFUL; } @@ -518,12 +505,14 @@ FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, NewValue, ClusterToWrite, FATOffset); if ((ClusterToWrite % 2) == 0) { + *OldValue = CBlock[FATOffset] + ((CBlock[FATOffset + 1] & 0x0f) << 8); CBlock[FATOffset] = NewValue; CBlock[FATOffset + 1] &= 0xf0; CBlock[FATOffset + 1] |= (NewValue & 0xf00) >> 8; } else { + *OldValue = (CBlock[FATOffset] >> 4) + (CBlock[FATOffset + 1] << 4); CBlock[FATOffset] &= 0x0f; CBlock[FATOffset] |= (NewValue & 0xf) << 4; CBlock[FATOffset + 1] = NewValue >> 4; @@ -538,7 +527,8 @@ FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, - ULONG NewValue) + ULONG NewValue, + PULONG OldValue) /* * FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables */ @@ -550,6 +540,7 @@ FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ChunkSize; PVOID Context; LARGE_INTEGER Offset; + PUSHORT Cluster; ChunkSize = CACHEPAGESIZE(DeviceExt); FATOffset = ClusterToWrite * 2; @@ -560,7 +551,9 @@ FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, } DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset, ClusterToWrite); - *((PUSHORT)(BaseAddress + (FATOffset % ChunkSize))) = NewValue; + Cluster = ((PUSHORT)(BaseAddress + (FATOffset % ChunkSize))); + *OldValue = *Cluster; + *Cluster = NewValue; CcSetDirtyPinnedData(Context, NULL); CcUnpinData(Context); return(STATUS_SUCCESS); @@ -569,7 +562,8 @@ FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, - ULONG NewValue) + ULONG NewValue, + PULONG OldValue) /* * FUNCTION: Writes a cluster to the FAT32 physical tables */ @@ -581,6 +575,7 @@ FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ChunkSize; PVOID Context; LARGE_INTEGER Offset; + PULONG Cluster; ChunkSize = CACHEPAGESIZE(DeviceExt); @@ -592,13 +587,13 @@ FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, } DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset, ClusterToWrite); - *((PULONG)(BaseAddress + (FATOffset % ChunkSize))) = NewValue & 0x0fffffff; + Cluster = ((PULONG)(BaseAddress + (FATOffset % ChunkSize))); + *OldValue = *Cluster & 0x0fffffff; + *Cluster = (*Cluster & 0xf0000000) | (NewValue & 0x0fffffff); CcSetDirtyPinnedData(Context, NULL); CcUnpinData(Context); - DPRINT("DeviceExt->Boot->FATSectors %d\n", - ((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32); return(STATUS_SUCCESS); } @@ -612,19 +607,28 @@ WriteCluster(PDEVICE_EXTENSION DeviceExt, */ { NTSTATUS Status; - - if (DeviceExt->FatType == FAT16) + ULONG OldValue; + ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE); + if (DeviceExt->FatInfo.FatType == FAT16) { - Status = FAT16WriteCluster(DeviceExt, ClusterToWrite, NewValue); + Status = FAT16WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue); } - else if (DeviceExt->FatType == FAT32) + else if (DeviceExt->FatInfo.FatType == FAT32) { - Status = FAT32WriteCluster(DeviceExt, ClusterToWrite, NewValue); + Status = FAT32WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue); } else { - Status = FAT12WriteCluster(DeviceExt, ClusterToWrite, NewValue); + Status = FAT12WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue); } + if (DeviceExt->AvailableClustersValid) + { + if (OldValue && NewValue == 0) + InterlockedIncrement(&DeviceExt->AvailableClusters); + else if (OldValue == 0 && NewValue) + InterlockedDecrement(&DeviceExt->AvailableClusters); + } + ExReleaseResourceLite(&DeviceExt->FatResource); return(Status); } @@ -636,8 +640,8 @@ ClusterToSector(PDEVICE_EXTENSION DeviceExt, * device */ { - return DeviceExt->dataStart + - ((Cluster - 2) * DeviceExt->Boot->SectorsPerCluster); + return DeviceExt->FatInfo.dataStart + + ((Cluster - 2) * DeviceExt->FatInfo.SectorsPerCluster); } NTSTATUS @@ -654,7 +658,7 @@ VfatRawReadCluster(PDEVICE_EXTENSION DeviceExt, if (FirstCluster == 1) { return VfatReadSectors(DeviceExt->StorageDevice, Cluster, - DeviceExt->Boot->SectorsPerCluster * Count, Buffer); + DeviceExt->FatInfo.SectorsPerCluster * Count, Buffer); } else { @@ -662,7 +666,7 @@ VfatRawReadCluster(PDEVICE_EXTENSION DeviceExt, Sector = ClusterToSector(DeviceExt, Cluster); return VfatReadSectors(DeviceExt->StorageDevice, Sector, - DeviceExt->Boot->SectorsPerCluster * Count, Buffer); + DeviceExt->FatInfo.SectorsPerCluster * Count, Buffer); } } @@ -685,14 +689,14 @@ VfatRawWriteCluster(PDEVICE_EXTENSION DeviceExt, if (FirstCluster == 1) { Status = VfatWriteSectors(DeviceExt->StorageDevice, Cluster, - DeviceExt->Boot->SectorsPerCluster * Count, Buffer); + DeviceExt->FatInfo.SectorsPerCluster * Count, Buffer); } else { Sector = ClusterToSector(DeviceExt, Cluster); Status = VfatWriteSectors(DeviceExt->StorageDevice, Sector, - DeviceExt->Boot->SectorsPerCluster * Count, Buffer); + DeviceExt->FatInfo.SectorsPerCluster * Count, Buffer); } return(Status); } @@ -708,8 +712,8 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt, { NTSTATUS Status; -// DPRINT ("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n", -// DeviceExt, CurrentCluster); + DPRINT ("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n", + DeviceExt, CurrentCluster); if (!Extend) { @@ -719,7 +723,7 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt, { ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE); } - + CHECKPOINT; /* * If the file hasn't any clusters allocated then we need special * handling @@ -728,16 +732,18 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt, { ULONG NewCluster; - if (DeviceExt->FatType == FAT16) + if (DeviceExt->FatInfo.FatType == FAT16) { + CHECKPOINT; Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster); + CHECKPOINT; if (!NT_SUCCESS(Status)) { ExReleaseResourceLite(&DeviceExt->FatResource); return(Status); } } - else if (DeviceExt->FatType == FAT32) + else if (DeviceExt->FatInfo.FatType == FAT32) { Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster); if (!NT_SUCCESS(Status)) @@ -767,11 +773,11 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt, return(STATUS_UNSUCCESSFUL); } - if (DeviceExt->FatType == FAT16) + if (DeviceExt->FatInfo.FatType == FAT16) { Status = Fat16GetNextCluster(DeviceExt, CurrentCluster, NextCluster); } - else if (DeviceExt->FatType == FAT32) + else if (DeviceExt->FatInfo.FatType == FAT32) { Status = Fat32GetNextCluster(DeviceExt, CurrentCluster, NextCluster); } @@ -785,7 +791,7 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt, /* We are after last existing cluster, we must add one to file */ /* Firstly, find the next available open allocation unit */ - if (DeviceExt->FatType == FAT16) + if (DeviceExt->FatInfo.FatType == FAT16) { Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster); if (!NT_SUCCESS(Status)) @@ -794,7 +800,7 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt, return(Status); } } - else if (DeviceExt->FatType == FAT32) + else if (DeviceExt->FatInfo.FatType == FAT32) { Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster); if (!NT_SUCCESS(Status)) @@ -839,7 +845,7 @@ GetNextSector(PDEVICE_EXTENSION DeviceExt, DPRINT("GetNextSector(DeviceExt %x, CurrentSector %x)\n", DeviceExt, CurrentSector); - if (CurrentSectordataStart || ((CurrentSector - DeviceExt->dataStart + 1) % DeviceExt -> Boot -> SectorsPerCluster)) + if (CurrentSectorFatInfo.dataStart || ((CurrentSector - DeviceExt->FatInfo.dataStart + 1) % DeviceExt->FatInfo.SectorsPerCluster)) /* Basically, if the next sequential sector would be on a cluster border, then we'll need to check in the FAT */ { (*NextSector)=CurrentSector+1; @@ -847,7 +853,7 @@ GetNextSector(PDEVICE_EXTENSION DeviceExt, } else { - CurrentSector = (CurrentSector - DeviceExt->dataStart) / DeviceExt -> Boot -> SectorsPerCluster + 2; + CurrentSector = (CurrentSector - DeviceExt->FatInfo.dataStart) / DeviceExt->FatInfo.SectorsPerCluster + 2; Status = GetNextCluster(DeviceExt, CurrentSector, NextSector, Extend); if (!NT_SUCCESS(Status)) diff --git a/reactos/drivers/fs/vfat/fcb.c b/reactos/drivers/fs/vfat/fcb.c index 0baee0a7624..c37615644cf 100644 --- a/reactos/drivers/fs/vfat/fcb.c +++ b/reactos/drivers/fs/vfat/fcb.c @@ -1,4 +1,4 @@ -/* $Id: fcb.c,v 1.13 2002/01/15 21:54:51 hbirr Exp $ +/* $Id: fcb.c,v 1.14 2002/03/18 22:37:12 hbirr Exp $ * * * FILE: fcb.c @@ -156,7 +156,6 @@ vfatFCBInitializeCache (PVCB vcb, PVFATFCB fcb) { NTSTATUS status; PFILE_OBJECT fileObject; - ULONG bytesPerCluster; ULONG fileCacheQuantum; PVFATCCB newCCB; @@ -180,9 +179,8 @@ vfatFCBInitializeCache (PVCB vcb, PVFATFCB fcb) fcb->pDevExt = vcb; - bytesPerCluster = vcb->Boot->SectorsPerCluster * BLOCKSIZE; - fileCacheQuantum = (bytesPerCluster >= PAGESIZE) ? - bytesPerCluster : PAGESIZE; + fileCacheQuantum = (vcb->FatInfo.BytesPerCluster >= PAGESIZE) ? + vcb->FatInfo.BytesPerCluster : PAGESIZE; status = CcRosInitializeFileCache (fileObject, &fcb->RFCB.Bcb, @@ -208,25 +206,25 @@ vfatMakeRootFCB(PDEVICE_EXTENSION pVCB) FCB = vfatNewFCB(L"\\"); memset(FCB->entry.Filename, ' ', 11); - FCB->entry.FileSize = pVCB->rootDirectorySectors * BLOCKSIZE; + FCB->entry.FileSize = pVCB->FatInfo.rootDirectorySectors * BLOCKSIZE; FCB->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY; - if (pVCB->FatType == FAT32) + if (pVCB->FatInfo.FatType == FAT32) { - CurrentCluster = FirstCluster = ((struct _BootSector32*)(pVCB->Boot))->RootCluster; + CurrentCluster = FirstCluster = pVCB->FatInfo.RootCluster; FCB->entry.FirstCluster = FirstCluster & 0xffff; FCB->entry.FirstClusterHigh = FirstCluster >> 16; CurrentCluster = FirstCluster; while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status)) { - Size += pVCB->BytesPerCluster; + Size += pVCB->FatInfo.BytesPerCluster; Status = NextCluster (pVCB, NULL, FirstCluster, &CurrentCluster, FALSE); } } else { FCB->entry.FirstCluster = 1; - Size = pVCB->rootDirectorySectors * BLOCKSIZE; + Size = pVCB->FatInfo.rootDirectorySectors * BLOCKSIZE; } FCB->RefCount = 1; FCB->dirIndex = 0; @@ -298,14 +296,14 @@ vfatMakeFCBFromDirEntry(PVCB vcb, FirstCluster = vfatDirEntryGetFirstCluster (vcb, &rcFCB->entry); if (FirstCluster == 1) { - Size = vcb->rootDirectorySectors * BLOCKSIZE; + Size = vcb->FatInfo.rootDirectorySectors * BLOCKSIZE; } else { CurrentCluster = FirstCluster; while (CurrentCluster != 0xffffffff) { - Size += vcb->BytesPerCluster; + Size += vcb->FatInfo.BytesPerCluster; Status = NextCluster (vcb, NULL, FirstCluster, &CurrentCluster, FALSE); } } @@ -317,7 +315,7 @@ vfatMakeFCBFromDirEntry(PVCB vcb, rcFCB->dirIndex = dirIndex; rcFCB->RFCB.FileSize.QuadPart = Size; rcFCB->RFCB.ValidDataLength.QuadPart = Size; - rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->BytesPerCluster); + rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->FatInfo.BytesPerCluster); // DPRINT1("%S %d %d\n", longName, Size, (ULONG)rcFCB->RFCB.AllocationSize.QuadPart); vfatFCBInitializeCache (vcb, rcFCB); rcFCB->RefCount++; @@ -353,11 +351,10 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, if (!(fcb->Flags & FCB_CACHE_INITIALIZED)) { - ULONG bytesPerCluster; ULONG fileCacheQuantum; - bytesPerCluster = vcb->Boot->SectorsPerCluster * BLOCKSIZE; - fileCacheQuantum = (bytesPerCluster >= PAGESIZE) ? bytesPerCluster : PAGESIZE; + fileCacheQuantum = (vcb->FatInfo.BytesPerCluster >= PAGESIZE) ? + vcb->FatInfo.BytesPerCluster : PAGESIZE; status = CcRosInitializeFileCache (fileObject, &fcb->RFCB.Bcb, fileCacheQuantum); diff --git a/reactos/drivers/fs/vfat/finfo.c b/reactos/drivers/fs/vfat/finfo.c index cb4c67b39b1..f73ffb8e1f5 100644 --- a/reactos/drivers/fs/vfat/finfo.c +++ b/reactos/drivers/fs/vfat/finfo.c @@ -1,4 +1,4 @@ -/* $Id: finfo.c,v 1.11 2001/11/02 22:47:36 hbirr Exp $ +/* $Id: finfo.c,v 1.12 2002/03/18 22:37:12 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -37,7 +37,7 @@ VfatGetStandardInformation(PVFATFCB FCB, DeviceExtension = DeviceObject->DeviceExtension; /* PRECONDITION */ assert (DeviceExtension != NULL); - assert (DeviceExtension->BytesPerCluster != 0); + assert (DeviceExtension->FatInfo.BytesPerCluster != 0); assert (StandardInfo != NULL); assert (FCB != NULL); @@ -143,7 +143,7 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject, DPRINT ("FsdSetDispositionInformation()\n"); assert (DeviceExt != NULL); - assert (DeviceExt->BytesPerCluster != 0); + assert (DeviceExt->FatInfo.BytesPerCluster != 0); assert (FCB != NULL); if (!wcscmp(FCB->PathName, L"\\") || !wcscmp(FCB->ObjectName, L"..") diff --git a/reactos/drivers/fs/vfat/fsctl.c b/reactos/drivers/fs/vfat/fsctl.c new file mode 100644 index 00000000000..860402e80fd --- /dev/null +++ b/reactos/drivers/fs/vfat/fsctl.c @@ -0,0 +1,378 @@ +/* $Id: fsctl.c,v 1.1 2002/03/18 22:37:13 hbirr Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/fsctl.c + * PURPOSE: VFAT Filesystem + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS ****************************************************************/ + +#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGESIZE ? \ + (pDeviceExt)->FatInfo.BytesPerCluster : PAGESIZE) + + +static NTSTATUS +VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount, + PBOOLEAN RecognizedFS, + PFATINFO pFatInfo) +{ + NTSTATUS Status; + PARTITION_INFORMATION PartitionInfo; + DISK_GEOMETRY DiskGeometry; + FATINFO FatInfo; + ULONG Size; + ULONG Sectors; + 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)) + { + DPRINT1("VfatBlockDeviceIoControl faild (%x)\n", Status); + return Status; + } +#ifdef DBG + 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 + if (PartitionInfo.PartitionType == PTDOS3xPrimary || + PartitionInfo.PartitionType == PTOLDDOS16Bit || + PartitionInfo.PartitionType == PTDos5xPrimary || + PartitionInfo.PartitionType == PTWin95FAT32 || + PartitionInfo.PartitionType == PTWin95FAT32LBA || + PartitionInfo.PartitionType == PTWin95FAT16LBA) + { + *RecognizedFS = TRUE; + } + } + else if (DiskGeometry.MediaType > Unknown && DiskGeometry.MediaType < RemovableMedia) + { + *RecognizedFS = TRUE; + } + if (*RecognizedFS == FALSE) + { + return STATUS_SUCCESS; + } +ReadSector: + Boot = ExAllocatePool(NonPagedPool, BLOCKSIZE); + if (Boot == NULL) + { + *RecognizedFS=FALSE; + return STATUS_INSUFFICIENT_RESOURCES; + } + Status = VfatReadSectors(DeviceToMount, 0, 1, (PUCHAR) Boot); + 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; + Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge; + 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; + + DPRINT1("Mounting VFAT device...\n"); + + Status = VfatHasFileSystem(DeviceToMount, &RecognizedFS, &DeviceExt->FatInfo); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (DeviceExt->FatInfo.BytesPerCluster >= PAGESIZE && + (DeviceExt->FatInfo.BytesPerCluster % PAGESIZE) != 0) + { + DbgPrint("(%s:%d) Invalid cluster size\n", __FILE__, __LINE__); + KeBugCheck(0); + } + else if (DeviceExt->FatInfo.BytesPerCluster < PAGESIZE && + (PAGESIZE % DeviceExt->FatInfo.BytesPerCluster) != 0) + { + DbgPrint("(%s:%d) Invalid cluster size2\n", __FILE__, __LINE__); + KeBugCheck(0); + } + + 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; + PVFATCCB Ccb = NULL; + LARGE_INTEGER timeout; + + DPRINT("VfatMount(IrpContext %x)\n", IrpContext); + + assert (IrpContext); + + if (IrpContext->DeviceObject != VfatGlobalData->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + goto ByeBye; + } + + Status = VfatHasFileSystem (IrpContext->Stack->Parameters.Mount.DeviceObject, &RecognizedFS, NULL); + 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 */ + DeviceObject->Vpb = IrpContext->Stack->Parameters.Mount.DeviceObject->Vpb; + Status = VfatMountDevice(DeviceExt, IrpContext->Stack->Parameters.Mount.DeviceObject); + if (!NT_SUCCESS(Status)) + { + /* FIXME: delete device object */ + goto ByeBye; + } + +#ifdef DBG + 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 + DeviceObject->Vpb->Flags |= VPB_MOUNTED; + DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject, IrpContext->Stack->Parameters.Mount.DeviceObject); + + DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice); + Fcb = vfatNewFCB(NULL); + if (Fcb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + Ccb = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB); + if (Ccb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + memset(Ccb, 0, sizeof (VFATCCB)); + DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; + DeviceExt->FATFileObject->FsContext = (PVOID) &Fcb->RFCB; + DeviceExt->FATFileObject->FsContext2 = Ccb; + DeviceExt->FATFileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + DeviceExt->FATFileObject->PrivateCacheMap = NULL; + DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb; + Ccb->pFcb = Fcb; + Ccb->PtrFileObject = DeviceExt->FATFileObject; + Fcb->FileObject = DeviceExt->FATFileObject; + Fcb->pDevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice; + + Fcb->Flags = FCB_IS_FAT; + + if (DeviceExt->FatInfo.FatType != FAT12) + { + Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * BLOCKSIZE; + Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->FatInfo.FATSectors * BLOCKSIZE; + Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(DeviceExt->FatInfo.FATSectors * BLOCKSIZE, CACHEPAGESIZE(DeviceExt)); + Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, CACHEPAGESIZE(DeviceExt)); + } + else + { + Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * BLOCKSIZE; + Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->FatInfo.FATSectors * BLOCKSIZE; + Fcb->RFCB.AllocationSize.QuadPart = 2 * PAGESIZE; + Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, 2 * PAGESIZE); + } + if (!NT_SUCCESS (Status)) + { + DbgPrint ("CcRosInitializeFileCache failed\n"); + goto ByeBye; + } + DeviceExt->LastAvailableCluster = 0; + ExInitializeResourceLite(&DeviceExt->DirResource); + ExInitializeResourceLite(&DeviceExt->FatResource); + + KeInitializeSpinLock(&DeviceExt->FcbListLock); + InitializeListHead(&DeviceExt->FcbListHead); + + /* 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) + ExFreePool(Fcb); + if (Ccb) + ExFreePool(Ccb); + if (DeviceObject) + IoDeleteDevice(DeviceObject); + } + return Status; +} + +NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: File system control + */ +{ + + NTSTATUS Status; + + DPRINT("VfatFileSystemControl(IrpContext %x)\n", IrpContext); + + assert (IrpContext); + + switch (IrpContext->MinorFunction) + { + case IRP_MN_USER_FS_REQUEST: + DPRINT("VFAT FSC: IRP_MN_USER_FS_REQUEST\n"); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + + case IRP_MN_MOUNT_VOLUME: + Status = VfatMount(IrpContext); + break; + + case IRP_MN_VERIFY_VOLUME: + DPRINT("VFAT FSC: IRP_MN_VERIFY_VOLUME\n"); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + + default: + DPRINT("VFAT FSC: MinorFunction %d\n", IrpContext->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + IrpContext->Irp->IoStatus.Status = Status; + IrpContext->Irp->IoStatus.Information = 0; + + IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + return (Status); +} + diff --git a/reactos/drivers/fs/vfat/iface.c b/reactos/drivers/fs/vfat/iface.c index d42ee5c8d29..1069359e7f5 100644 --- a/reactos/drivers/fs/vfat/iface.c +++ b/reactos/drivers/fs/vfat/iface.c @@ -1,4 +1,4 @@ -/* $Id: iface.c,v 1.61 2002/02/08 02:57:09 chorns Exp $ +/* $Id: iface.c,v 1.62 2002/03/18 22:37:12 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -35,355 +35,13 @@ /* GLOBALS *****************************************************************/ -#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \ - (pDeviceExt)->BytesPerCluster : PAGESIZE) -static PDRIVER_OBJECT VfatDriverObject; +PVFAT_GLOBAL_DATA VfatGlobalData; /* FUNCTIONS ****************************************************************/ -static NTSTATUS -VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount, - PBOOLEAN RecognizedFS) -/* - * FUNCTION: Tests if the device contains a filesystem that can be mounted - * by this fsd - */ -{ - BootSector *Boot; - NTSTATUS Status; - - Boot = ExAllocatePool(NonPagedPool, 512); - - Status = VfatReadSectors(DeviceToMount, 0, 1, (UCHAR *) Boot); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - DPRINT("Boot->SysType %.5s\n", Boot->SysType); - if (strncmp(Boot->SysType, "FAT12", 5) == 0 || - strncmp(Boot->SysType, "FAT16", 5) == 0 || - strncmp(((struct _BootSector32 *) (Boot))->SysType, "FAT32", 5) == 0) - { - *RecognizedFS = TRUE; - } - else - { - *RecognizedFS = FALSE; - } - - ExFreePool(Boot); - - return(STATUS_SUCCESS); -} - - -static NTSTATUS -VfatMountDevice(PDEVICE_EXTENSION DeviceExt, - PDEVICE_OBJECT DeviceToMount) -/* - * FUNCTION: Mounts the device - */ -{ - NTSTATUS Status; - - DPRINT("Mounting VFAT device..."); - DPRINT("DeviceExt %x\n", DeviceExt); - - DeviceExt->Boot = ExAllocatePool(NonPagedPool, 512); - - Status = VfatReadSectors(DeviceToMount, 0, 1, (UCHAR *) DeviceExt->Boot); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - 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->BytesPerSector = DeviceExt->Boot->BytesPerSector; - DeviceExt->FATEntriesPerSector = DeviceExt->Boot->BytesPerSector / 32; - DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster * - DeviceExt->Boot->BytesPerSector; - - if (DeviceExt->BytesPerCluster >= PAGESIZE && - (DeviceExt->BytesPerCluster % PAGESIZE) != 0) - { - DbgPrint("Invalid cluster size\n"); - KeBugCheck(0); - } - else if (DeviceExt->BytesPerCluster < PAGESIZE && - (PAGESIZE % DeviceExt->BytesPerCluster) != 0) - { - DbgPrint("Invalid cluster size2\n"); - KeBugCheck(0); - } - - if (strncmp (DeviceExt->Boot->SysType, "FAT12", 5) == 0) - { - DPRINT("FAT12\n"); - DeviceExt->FatType = FAT12; - } - else if (strncmp - (((struct _BootSector32 *) (DeviceExt->Boot))->SysType, "FAT32", - 5) == 0) - { - DPRINT("FAT32\n"); - DeviceExt->FatType = FAT32; - DeviceExt->rootDirectorySectors = DeviceExt->Boot->SectorsPerCluster; - DeviceExt->dataStart = DeviceExt->FATStart + DeviceExt->Boot->FATCount - * ((struct _BootSector32 *) (DeviceExt->Boot))->FATSectors32; - DeviceExt->rootStart = ClusterToSector (DeviceExt, - ((struct _BootSector32 *)(DeviceExt->Boot))->RootCluster); - } - else - { - DPRINT("FAT16\n"); - DeviceExt->FatType = FAT16; - } - - 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; - PVFATCCB Ccb = NULL; - - DPRINT("VfatMount(IrpContext %x)\n", IrpContext); - - assert (IrpContext); - - Status = VfatHasFileSystem (IrpContext->Stack->Parameters.Mount.DeviceObject, &RecognizedFS); - 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(VfatDriverObject, - 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 */ - DeviceObject->Vpb = IrpContext->Stack->Parameters.Mount.DeviceObject->Vpb; - Status = VfatMountDevice(DeviceExt, IrpContext->Stack->Parameters.Mount.DeviceObject); - if (!NT_SUCCESS(Status)) - { - /* FIXME: delete device object */ - goto ByeBye; - } - -#ifdef DBG - DbgPrint("BytesPerSector: %d\n", DeviceExt->Boot->BytesPerSector); - DbgPrint("SectorsPerCluster: %d\n", DeviceExt->Boot->SectorsPerCluster); - DbgPrint("ReservedSectors: %d\n", DeviceExt->Boot->ReservedSectors); - DbgPrint("FATCount: %d\n", DeviceExt->Boot->FATCount); - DbgPrint("RootEntries: %d\n", DeviceExt->Boot->RootEntries); - DbgPrint("Sectors: %d\n", DeviceExt->Boot->Sectors); - DbgPrint("FATSectors: %d\n", DeviceExt->Boot->FATSectors); - DbgPrint("SectorsPerTrack: %d\n", DeviceExt->Boot->SectorsPerTrack); - DbgPrint("Heads: %d\n", DeviceExt->Boot->Heads); - DbgPrint("HiddenSectors: %d\n", DeviceExt->Boot->HiddenSectors); - DbgPrint("SectorsHuge: %d\n", DeviceExt->Boot->SectorsHuge); - DbgPrint("RootStart: %d\n", DeviceExt->rootStart); - DbgPrint("DataStart: %d\n", DeviceExt->dataStart); - if (DeviceExt->FatType == FAT32) - { - DbgPrint("FATSectors32: %d\n", - ((struct _BootSector32*)(DeviceExt->Boot))->FATSectors32); - DbgPrint("RootCluster: %d\n", - ((struct _BootSector32*)(DeviceExt->Boot))->RootCluster); - DbgPrint("FSInfoSector: %d\n", - ((struct _BootSector32*)(DeviceExt->Boot))->FSInfoSector); - DbgPrint("BootBackup: %d\n", - ((struct _BootSector32*)(DeviceExt->Boot))->BootBackup); - } -#endif - DeviceObject->Vpb->Flags |= VPB_MOUNTED; - DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject, IrpContext->Stack->Parameters.Mount.DeviceObject); - - DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice); - Fcb = vfatNewFCB(NULL); - if (Fcb == NULL) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto ByeBye; - } - Ccb = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB); - if (Ccb == NULL) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto ByeBye; - } - memset(Ccb, 0, sizeof (VFATCCB)); - DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; - DeviceExt->FATFileObject->FsContext = (PVOID) &Fcb->RFCB; - DeviceExt->FATFileObject->FsContext2 = Ccb; - DeviceExt->FATFileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; - Ccb->pFcb = Fcb; - Ccb->PtrFileObject = DeviceExt->FATFileObject; - Fcb->FileObject = DeviceExt->FATFileObject; - Fcb->pDevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice; - - Fcb->Flags = FCB_IS_FAT; - - if (DeviceExt->Boot->Sectors != 0) - { - DeviceExt->NumberOfClusters = (DeviceExt->Boot->Sectors - DeviceExt->dataStart) - / DeviceExt->Boot->SectorsPerCluster + 2; - } - else - { - DeviceExt->NumberOfClusters = (DeviceExt->Boot->SectorsHuge - DeviceExt->dataStart) - / DeviceExt->Boot->SectorsPerCluster + 2; - } - if (DeviceExt->FatType == FAT32) - { - Fcb->RFCB.FileSize.QuadPart = ((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32 * BLOCKSIZE; - Fcb->RFCB.ValidDataLength.QuadPart = ((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32 * BLOCKSIZE; - Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32 * BLOCKSIZE, CACHEPAGESIZE(DeviceExt)); - Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, CACHEPAGESIZE(DeviceExt)); - } - else - { - if (DeviceExt->FatType == FAT16) - { - Fcb->RFCB.FileSize.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE; - Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE; - Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(DeviceExt->Boot->FATSectors * BLOCKSIZE, CACHEPAGESIZE(DeviceExt)); - Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, CACHEPAGESIZE(DeviceExt)); - } - else - { - Fcb->RFCB.FileSize.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE; - Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE; - Fcb->RFCB.AllocationSize.QuadPart = 2 * PAGESIZE; - Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, 2 * PAGESIZE); - } - } - if (!NT_SUCCESS (Status)) - { - DbgPrint ("CcRosInitializeFileCache failed\n"); - goto ByeBye; - } - - DeviceExt->LastAvailableCluster = 0; - ExInitializeResourceLite(&DeviceExt->DirResource); - ExInitializeResourceLite(&DeviceExt->FatResource); - - KeInitializeSpinLock(&DeviceExt->FcbListLock); - InitializeListHead(&DeviceExt->FcbListHead); - - /* read serial number */ - if (DeviceExt->FatType == FAT12 || DeviceExt->FatType == FAT16) - DeviceObject->Vpb->SerialNumber = - ((struct _BootSector *) (DeviceExt->Boot))->VolumeID; - else if (DeviceExt->FatType == FAT32) - DeviceObject->Vpb->SerialNumber = - ((struct _BootSector32 *) (DeviceExt->Boot))->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) - ExFreePool(Fcb); - if (Ccb) - ExFreePool(Ccb); - if (DeviceObject) - IoDeleteDevice(DeviceObject); - } - return Status; -} - - -NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext) -/* - * FUNCTION: File system control - */ -{ - - NTSTATUS Status; - - DPRINT("VfatFileSystemControl(IrpContext %x)\n", IrpContext); - - assert (IrpContext); - - switch (IrpContext->MinorFunction) - { - case IRP_MN_USER_FS_REQUEST: - DPRINT("VFAT FSC: IRP_MN_USER_FS_REQUEST\n"); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; - - case IRP_MN_MOUNT_VOLUME: - Status = VfatMount(IrpContext); - break; - - case IRP_MN_VERIFY_VOLUME: - DPRINT("VFAT FSC: IRP_MN_VERIFY_VOLUME\n"); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; - - default: - DPRINT("VFAT FSC: MinorFunction %d\n", IrpContext->MinorFunction); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; - } - - IrpContext->Irp->IoStatus.Status = Status; - IrpContext->Irp->IoStatus.Information = 0; - - IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT); - return (Status); -} - - NTSTATUS STDCALL -DriverEntry(PDRIVER_OBJECT _DriverObject, +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* * FUNCTION: Called by the system to initalize the driver @@ -399,14 +57,12 @@ DriverEntry(PDRIVER_OBJECT _DriverObject, DPRINT("VFAT 0.0.6\n"); - VfatDriverObject = _DriverObject; - RtlInitUnicodeString(&DeviceName, L"\\Device\\Vfat"); - Status = IoCreateDevice(VfatDriverObject, - 0, + Status = IoCreateDevice(DriverObject, + sizeof(VFAT_GLOBAL_DATA), &DeviceName, - FILE_DEVICE_FILE_SYSTEM, + FILE_DEVICE_DISK_FILE_SYSTEM, 0, FALSE, &DeviceObject); @@ -414,32 +70,30 @@ DriverEntry(PDRIVER_OBJECT _DriverObject, { return (Status); } + VfatGlobalData = DeviceObject->DeviceExtension; + RtlZeroMemory (VfatGlobalData, sizeof(VFAT_GLOBAL_DATA)); + VfatGlobalData->DriverObject = DriverObject; + VfatGlobalData->DeviceObject = DeviceObject; DeviceObject->Flags = DO_DIRECT_IO; - VfatDriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatBuildRequest; - VfatDriverObject->MajorFunction[IRP_MJ_CREATE] = VfatBuildRequest; - VfatDriverObject->MajorFunction[IRP_MJ_READ] = VfatBuildRequest; - VfatDriverObject->MajorFunction[IRP_MJ_WRITE] = VfatBuildRequest; - VfatDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = - VfatBuildRequest; - VfatDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = - VfatBuildRequest; - VfatDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = - VfatBuildRequest; - VfatDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = - VfatBuildRequest; - VfatDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = - VfatBuildRequest; - VfatDriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = - VfatBuildRequest; - VfatDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = VfatShutdown; - VfatDriverObject->MajorFunction[IRP_MJ_CLEANUP] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_CREATE] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_READ] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_WRITE] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = VfatShutdown; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = VfatBuildRequest; - VfatDriverObject->DriverUnload = NULL; + DriverObject->DriverUnload = NULL; IoRegisterFileSystem(DeviceObject); - return STATUS_SUCCESS; } /* EOF */ + diff --git a/reactos/drivers/fs/vfat/makefile b/reactos/drivers/fs/vfat/makefile index 8031aa30bac..09d900931c0 100644 --- a/reactos/drivers/fs/vfat/makefile +++ b/reactos/drivers/fs/vfat/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.37 2002/01/08 00:49:01 dwelch Exp $ +# $Id: makefile,v 1.38 2002/03/18 22:37:13 hbirr Exp $ PATH_TO_TOP = ../../.. @@ -22,7 +22,8 @@ TARGET_OBJECTS = \ shutdown.o \ string.o \ volume.o \ - misc.o + misc.o \ + fsctl.o DEP_OBJECTS = $(TARGET_OBJECTS) diff --git a/reactos/drivers/fs/vfat/rw.c b/reactos/drivers/fs/vfat/rw.c index af23e51c02d..14c0109ce8d 100644 --- a/reactos/drivers/fs/vfat/rw.c +++ b/reactos/drivers/fs/vfat/rw.c @@ -1,5 +1,5 @@ -/* $Id: rw.c,v 1.38 2002/01/27 03:25:44 dwelch Exp $ +/* $Id: rw.c,v 1.39 2002/03/18 22:37:13 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -121,7 +121,7 @@ NextCluster(PDEVICE_EXTENSION DeviceExt, } if (FirstCluster == 1) { - (*CurrentCluster) += DeviceExt->Boot->SectorsPerCluster; + (*CurrentCluster) += DeviceExt->FatInfo.SectorsPerCluster; return(STATUS_SUCCESS); } else @@ -176,7 +176,7 @@ OffsetToCluster(PDEVICE_EXTENSION DeviceExt, if (Fcb != NULL && Fcb->Flags & FCB_IS_PAGE_FILE) { ULONG NCluster; - ULONG Offset = FileOffset / DeviceExt->BytesPerCluster; + ULONG Offset = FileOffset / DeviceExt->FatInfo.BytesPerCluster; PULONG FatChain; int i; if (Fcb->FatChainSize == 0) @@ -238,14 +238,14 @@ OffsetToCluster(PDEVICE_EXTENSION DeviceExt, if (FirstCluster == 1) { /* root of FAT16 or FAT12 */ - *Cluster = DeviceExt->rootStart + FileOffset - / (DeviceExt->BytesPerCluster) * DeviceExt->Boot->SectorsPerCluster; + *Cluster = DeviceExt->FatInfo.rootStart + FileOffset + / (DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.SectorsPerCluster; return(STATUS_SUCCESS); } else { CurrentCluster = FirstCluster; - for (i = 0; i < FileOffset / DeviceExt->BytesPerCluster; i++) + for (i = 0; i < FileOffset / DeviceExt->FatInfo.BytesPerCluster; i++) { Status = GetNextCluster (DeviceExt, CurrentCluster, &CurrentCluster, Extend); @@ -271,14 +271,14 @@ VfatReadCluster(PDEVICE_EXTENSION DeviceExt, PVOID BaseAddress = NULL; NTSTATUS Status; - if (InternalLength == DeviceExt->BytesPerCluster) + if (InternalLength == DeviceExt->FatInfo.BytesPerCluster) { Status = VfatRawReadCluster(DeviceExt, FirstCluster, Destination, *CurrentCluster, 1); } else { - BaseAddress = ExAllocatePool(NonPagedPool, DeviceExt->BytesPerCluster); + BaseAddress = ExAllocatePool(NonPagedPool, DeviceExt->FatInfo.BytesPerCluster); if (BaseAddress == NULL) { return(STATUS_NO_MEMORY); @@ -318,7 +318,7 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, /* PRECONDITION */ assert (DeviceExt != NULL); - assert (DeviceExt->BytesPerCluster != 0); + assert (DeviceExt->FatInfo.BytesPerCluster != 0); assert (FileObject != NULL); assert (FileObject->FsContext2 != NULL); @@ -351,7 +351,7 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, } Status = VfatReadSectors(DeviceExt->StorageDevice, - DeviceExt->FATStart + ReadOffset / BLOCKSIZE, + DeviceExt->FatInfo.FATStart + ReadOffset / BLOCKSIZE, Length / BLOCKSIZE, Buffer); if (NT_SUCCESS(Status)) { @@ -388,9 +388,9 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, if (FirstCluster == 1) { /* root directory of FAT12 or FAT16 */ - if (ReadOffset + Length > DeviceExt->rootDirectorySectors * BLOCKSIZE) + if (ReadOffset + Length > DeviceExt->FatInfo.rootDirectorySectors * BLOCKSIZE) { - Length = DeviceExt->rootDirectorySectors * BLOCKSIZE - ReadOffset; + Length = DeviceExt->FatInfo.rootDirectorySectors * BLOCKSIZE - ReadOffset; } } @@ -413,7 +413,7 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, Status = OffsetToCluster(DeviceExt, Fcb, FirstCluster, - ROUND_DOWN(ReadOffset, DeviceExt->BytesPerCluster), + ROUND_DOWN(ReadOffset, DeviceExt->FatInfo.BytesPerCluster), &CurrentCluster, FALSE); if (!NT_SUCCESS(Status)) @@ -424,15 +424,15 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, * If the read doesn't begin on a chunk boundary then we need special * handling */ - if ((ReadOffset % DeviceExt->BytesPerCluster) != 0 ) + if ((ReadOffset % DeviceExt->FatInfo.BytesPerCluster) != 0 ) { - TempLength = min (Length, DeviceExt->BytesPerCluster - - (ReadOffset % DeviceExt->BytesPerCluster)); + TempLength = min (Length, DeviceExt->FatInfo.BytesPerCluster - + (ReadOffset % DeviceExt->FatInfo.BytesPerCluster)); Ccb->LastCluster = CurrentCluster; - Ccb->LastOffset = ROUND_DOWN(ReadOffset, DeviceExt->BytesPerCluster); + Ccb->LastOffset = ROUND_DOWN(ReadOffset, DeviceExt->FatInfo.BytesPerCluster); Status = VfatReadCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster, Buffer, - ReadOffset % DeviceExt->BytesPerCluster, + ReadOffset % DeviceExt->FatInfo.BytesPerCluster, TempLength); if (NT_SUCCESS(Status)) { @@ -443,7 +443,7 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, } } - while (Length >= DeviceExt->BytesPerCluster && + while (Length >= DeviceExt->FatInfo.BytesPerCluster && CurrentCluster != 0xffffffff && NT_SUCCESS(Status)) { StartCluster = CurrentCluster; @@ -453,25 +453,25 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, do { ClusterCount++; - BytesDone += DeviceExt->BytesPerCluster; + BytesDone += DeviceExt->FatInfo.BytesPerCluster; Status = NextCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster, FALSE); } while (StartCluster + ClusterCount == CurrentCluster && NT_SUCCESS(Status) && - Length - BytesDone >= DeviceExt->BytesPerCluster); + Length - BytesDone >= DeviceExt->FatInfo.BytesPerCluster); DPRINT("Count %d, Start %x Next %x\n", ClusterCount, StartCluster, CurrentCluster); Ccb->LastCluster = StartCluster + (ClusterCount - 1); Ccb->LastOffset = ReadOffset + - (ClusterCount - 1) * DeviceExt->BytesPerCluster; + (ClusterCount - 1) * DeviceExt->FatInfo.BytesPerCluster; Status = VfatRawReadCluster(DeviceExt, FirstCluster, Buffer, StartCluster, ClusterCount); if (NT_SUCCESS(Status)) { - ClusterCount *= DeviceExt->BytesPerCluster; + ClusterCount *= DeviceExt->FatInfo.BytesPerCluster; (*LengthRead) = (*LengthRead) + ClusterCount; Buffer += ClusterCount; Length -= ClusterCount; @@ -485,7 +485,7 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, if (Length > 0 && CurrentCluster != 0xffffffff && NT_SUCCESS(Status)) { Ccb->LastCluster = CurrentCluster; - Ccb->LastOffset = ReadOffset + DeviceExt->BytesPerCluster; + Ccb->LastOffset = ReadOffset + DeviceExt->FatInfo.BytesPerCluster; Status = VfatReadCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster, Buffer, 0, Length); @@ -500,19 +500,19 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, NTSTATUS VfatWriteCluster(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb, - ULONG StartOffset, - ULONG FirstCluster, - PULONG CurrentCluster, - PVOID Source, - ULONG InternalOffset, - ULONG InternalLength) + ULONG StartOffset, + ULONG FirstCluster, + PULONG CurrentCluster, + PVOID Source, + ULONG InternalOffset, + ULONG InternalLength) { PVOID BaseAddress; NTSTATUS Status; - if (InternalLength != DeviceExt->BytesPerCluster) + if (InternalLength != DeviceExt->FatInfo.BytesPerCluster) { - BaseAddress = ExAllocatePool(NonPagedPool, DeviceExt->BytesPerCluster); + BaseAddress = ExAllocatePool(NonPagedPool, DeviceExt->FatInfo.BytesPerCluster); if (BaseAddress == NULL) { return(STATUS_NO_MEMORY); @@ -520,7 +520,7 @@ VfatWriteCluster(PDEVICE_EXTENSION DeviceExt, } else BaseAddress = Source; - if (InternalLength != DeviceExt->BytesPerCluster) + if (InternalLength != DeviceExt->FatInfo.BytesPerCluster) { /* * If the data in the cache isn't valid or we are bypassing the @@ -531,7 +531,7 @@ VfatWriteCluster(PDEVICE_EXTENSION DeviceExt, *CurrentCluster, 1); if (!NT_SUCCESS(Status)) { - if (InternalLength != DeviceExt->BytesPerCluster) + if (InternalLength != DeviceExt->FatInfo.BytesPerCluster) { ExFreePool(BaseAddress); } @@ -545,7 +545,7 @@ VfatWriteCluster(PDEVICE_EXTENSION DeviceExt, DPRINT("Writing 0x%x\n", *CurrentCluster); Status = VfatRawWriteCluster(DeviceExt, FirstCluster, BaseAddress, *CurrentCluster, 1); - if (InternalLength != DeviceExt->BytesPerCluster) + if (InternalLength != DeviceExt->FatInfo.BytesPerCluster) { ExFreePool(BaseAddress); } @@ -611,10 +611,10 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, Length = (ULONG)Fcb->RFCB.FileSize.QuadPart - WriteOffset; } - for (Count = 0; Count < DeviceExt->Boot->FATCount; Count++) + for (Count = 0; Count < DeviceExt->FatInfo.FATCount; Count++) { Status = VfatWriteSectors(DeviceExt->StorageDevice, - DeviceExt->FATStart + (Count * (ULONG)Fcb->RFCB.FileSize.QuadPart + WriteOffset) / BLOCKSIZE, + DeviceExt->FatInfo.FATStart + (Count * (ULONG)Fcb->RFCB.FileSize.QuadPart + WriteOffset) / BLOCKSIZE, Length / BLOCKSIZE, Buffer); if (!NT_SUCCESS(Status)) { @@ -639,7 +639,7 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, if (FirstCluster == 1) { // root directory of FAT12 od FAT16 - if (WriteOffset + Length > DeviceExt->rootDirectorySectors * BLOCKSIZE) + if (WriteOffset + Length > DeviceExt->FatInfo.rootDirectorySectors * BLOCKSIZE) { DPRINT("Writing over the end of the root directory on FAT12/16\n"); return STATUS_END_OF_FILE; @@ -664,7 +664,7 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, Status = OffsetToCluster(DeviceExt, Fcb, FirstCluster, - ROUND_DOWN(WriteOffset, DeviceExt->BytesPerCluster), + ROUND_DOWN(WriteOffset, DeviceExt->FatInfo.BytesPerCluster), &CurrentCluster, FALSE); if (!NT_SUCCESS(Status) || CurrentCluster == 0xffffffff) @@ -673,23 +673,24 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, return(Status); } pCcb->LastCluster = CurrentCluster; - pCcb->LastOffset = ROUND_DOWN(WriteOffset, DeviceExt->BytesPerCluster); + pCcb->LastOffset = ROUND_DOWN(WriteOffset, DeviceExt->FatInfo.BytesPerCluster); /* * If the offset in the cluster doesn't fall on the cluster boundary * then we have to write only from the specified offset */ Status = STATUS_SUCCESS; - if ((WriteOffset % DeviceExt->BytesPerCluster) != 0) + if ((WriteOffset % DeviceExt->FatInfo.BytesPerCluster) != 0) { - TempLength = min (Length, DeviceExt->BytesPerCluster - (WriteOffset % DeviceExt->BytesPerCluster)); + TempLength = min (Length, DeviceExt->FatInfo.BytesPerCluster + - (WriteOffset % DeviceExt->FatInfo.BytesPerCluster)); Status = VfatWriteCluster(DeviceExt, Fcb, - ROUND_DOWN(WriteOffset, DeviceExt->BytesPerCluster), + ROUND_DOWN(WriteOffset, DeviceExt->FatInfo.BytesPerCluster), FirstCluster, &CurrentCluster, Buffer, - WriteOffset % DeviceExt->BytesPerCluster, + WriteOffset % DeviceExt->FatInfo.BytesPerCluster, TempLength); if (NT_SUCCESS(Status)) { @@ -699,7 +700,8 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, } } - while (Length >= DeviceExt->BytesPerCluster && CurrentCluster != 0xffffffff && NT_SUCCESS(Status)) + while (Length >= DeviceExt->FatInfo.BytesPerCluster && + CurrentCluster != 0xffffffff && NT_SUCCESS(Status)) { StartCluster = CurrentCluster; Count = 0; @@ -710,15 +712,15 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, Status = NextCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster, FALSE); } while (StartCluster + Count == CurrentCluster && NT_SUCCESS(Status) && - Length - Count * DeviceExt->BytesPerCluster >= DeviceExt->BytesPerCluster); + Length - Count * DeviceExt->FatInfo.BytesPerCluster >= DeviceExt->FatInfo.BytesPerCluster); pCcb->LastCluster = StartCluster + (Count - 1); - pCcb->LastOffset = WriteOffset + (Count - 1) * DeviceExt->BytesPerCluster; + pCcb->LastOffset = WriteOffset + (Count - 1) * DeviceExt->FatInfo.BytesPerCluster; Status = VfatRawWriteCluster(DeviceExt, FirstCluster, Buffer, StartCluster, Count); if (NT_SUCCESS(Status)) { - Count *= DeviceExt->BytesPerCluster; + Count *= DeviceExt->FatInfo.BytesPerCluster; Buffer += Count; Length -= Count; WriteOffset += Count; @@ -796,7 +798,7 @@ NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, PFILE_OBJECT pFileObject pFcb = ((PVFATCCB) (pFileObject->FsContext2))->pFcb; DPRINT ("New Size %d, AllocationSize %d, BytesPerCluster %d\n", NewSize, - (ULONG)pFcb->RFCB.AllocationSize.QuadPart, pDeviceExt->BytesPerCluster); + (ULONG)pFcb->RFCB.AllocationSize.QuadPart, pDeviceExt->FatInfo.BytesPerCluster); FirstCluster = CurrentCluster = vfatDirEntryGetFirstCluster (pDeviceExt, &pFcb->entry); @@ -817,7 +819,7 @@ NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, PFILE_OBJECT pFileObject else { Status = OffsetToCluster(pDeviceExt, pFcb, FirstCluster, - pFcb->RFCB.AllocationSize.QuadPart - pDeviceExt->BytesPerCluster, + pFcb->RFCB.AllocationSize.QuadPart - pDeviceExt->FatInfo.BytesPerCluster, &CurrentCluster, FALSE); if (!NT_SUCCESS(Status)) { @@ -839,7 +841,7 @@ NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, PFILE_OBJECT pFileObject } Status = OffsetToCluster(pDeviceExt, pFcb, FirstCluster, - ROUND_DOWN(NewSize-1, pDeviceExt->BytesPerCluster), + ROUND_DOWN(NewSize-1, pDeviceExt->FatInfo.BytesPerCluster), &NewCluster, TRUE); if (!NT_SUCCESS(Status) || NewCluster == 0xffffffff) { @@ -864,10 +866,10 @@ NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, PFILE_OBJECT pFileObject if (pFcb->RFCB.AllocationSize.QuadPart == 0) { pFcb->entry.FirstCluster = FirstCluster; - if(pDeviceExt->FatType == FAT32) + if(pDeviceExt->FatInfo.FatType == FAT32) pFcb->entry.FirstClusterHigh = FirstCluster >> 16; } - pFcb->RFCB.AllocationSize.QuadPart = ROUND_UP(NewSize, pDeviceExt->BytesPerCluster); + pFcb->RFCB.AllocationSize.QuadPart = ROUND_UP(NewSize, pDeviceExt->FatInfo.BytesPerCluster); if (pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY) { pFcb->RFCB.FileSize.QuadPart = pFcb->RFCB.AllocationSize.QuadPart; diff --git a/reactos/drivers/fs/vfat/vfat.h b/reactos/drivers/fs/vfat/vfat.h index 880b4ef182d..f87c9baa73d 100644 --- a/reactos/drivers/fs/vfat/vfat.h +++ b/reactos/drivers/fs/vfat/vfat.h @@ -1,4 +1,4 @@ -/* $Id: vfat.h,v 1.39 2002/02/05 21:31:03 hbirr Exp $ */ +/* $Id: vfat.h,v 1.40 2002/03/18 22:37:13 hbirr Exp $ */ #include @@ -61,12 +61,13 @@ struct _BootBackupSector typedef struct _BootSector BootSector; -struct _FATDirEntry { +struct _FATDirEntry +{ unsigned char Filename[8], Ext[3], Attrib, Res[2]; unsigned short CreationTime,CreationDate,AccessDate; - unsigned short FirstClusterHigh;// higher - unsigned short UpdateTime;//time create/update - unsigned short UpdateDate;//date create/update + unsigned short FirstClusterHigh; // higher + unsigned short UpdateTime; //time create/update + unsigned short UpdateDate; //date create/update unsigned short FirstCluster; unsigned long FileSize; } __attribute__((packed)); @@ -76,13 +77,13 @@ typedef struct _FATDirEntry FATDirEntry, FAT_DIR_ENTRY, *PFAT_DIR_ENTRY; struct _slot { unsigned char id; // sequence number for slot - WCHAR name0_4[5]; // first 5 characters in name + WCHAR name0_4[5]; // first 5 characters in name unsigned char attr; // attribute byte unsigned char reserved; // always 0 unsigned char alias_checksum; // checksum for 8.3 alias - WCHAR name5_10[6]; // 6 more characters in name + WCHAR name5_10[6]; // 6 more characters in name unsigned char start[2]; // starting cluster number - WCHAR name11_12[2]; // last 2 characters in name + WCHAR name11_12[2]; // last 2 characters in name } __attribute__((packed)); @@ -94,6 +95,27 @@ typedef struct _slot slot; #define FAT12 (2) #define FAT32 (3) +#define VCB_VOLUME_LOCKED 0x0001 +#define VCB_DISMOUNT_PENDING 0x0002 + +typedef struct +{ + ULONG VolumeID; + ULONG FATStart; + ULONG FATCount; + ULONG FATSectors; + ULONG rootDirectorySectors; + ULONG rootStart; + ULONG dataStart; + ULONG RootCluster; + ULONG SectorsPerCluster; + ULONG BytesPerSector; + ULONG BytesPerCluster; + ULONG NumberOfClusters; + ULONG FatType; +} +FATINFO, *PFATINFO; + typedef struct { ERESOURCE DirResource; @@ -104,15 +126,23 @@ typedef struct PDEVICE_OBJECT StorageDevice; PFILE_OBJECT FATFileObject; - BootSector *Boot; - int rootDirectorySectors, FATStart, rootStart, dataStart; - int BytesPerSector; - int FATEntriesPerSector, FATUnit; - ULONG BytesPerCluster; - ULONG FatType; + FATINFO FatInfo; ULONG LastAvailableCluster; - ULONG NumberOfClusters; -} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB; + ULONG AvailableClusters; + BOOLEAN AvailableClustersValid; + ULONG Flags; +} +DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB; + +typedef struct +{ + PDRIVER_OBJECT DriverObject; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; +} +VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA; + +extern PVFAT_GLOBAL_DATA VfatGlobalData; #define FCB_CACHE_INITIALIZED 0x0001 #define FCB_DELETE_PENDING 0x0002 @@ -137,11 +167,13 @@ typedef struct _VFATFCB ULONG dirIndex; ERESOURCE PagingIoResource; ERESOURCE MainResource; + ULONG TimerCount; /* Structure members used only for paging files. */ ULONG FatChainSize; PULONG FatChain; -} VFATFCB, *PVFATFCB; +} +VFATFCB, *PVFATFCB; typedef struct _VFATCCB { @@ -156,7 +188,8 @@ typedef struct _VFATCCB ULONG LastCluster; ULONG LastOffset; -} VFATCCB, *PVFATCCB; +} +VFATCCB, *PVFATCCB; #define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) @@ -169,14 +202,16 @@ typedef struct __DOSTIME WORD Second:5; WORD Minute:6; WORD Hour:5; -} DOSTIME, *PDOSTIME; +} +DOSTIME, *PDOSTIME; typedef struct __DOSDATE { WORD Day:5; WORD Month:4; WORD Year:5; -} DOSDATE, *PDOSDATE; +} +DOSDATE, *PDOSDATE; #define IRPCONTEXT_CANWAIT 0x0001 @@ -194,216 +229,299 @@ typedef struct } VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT; +/* ------------------------------------------------------ shutdown.c */ + +NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* -------------------------------------------------------- volume.c */ + +NTSTATUS VfatQueryVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatSetVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); + +/* ------------------------------------------------------ blockdev.c */ + +NTSTATUS VfatReadSectors(IN PDEVICE_OBJECT pDeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN PUCHAR Buffer); + +NTSTATUS VfatWriteSectors(IN PDEVICE_OBJECT pDeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN PUCHAR Buffer); + +NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, + IN ULONG CtlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG pOutputBufferSize); + +/* ----------------------------------------------------------- dir.c */ -/* functions called by i/o manager : */ -NTSTATUS STDCALL -DriverEntry(PDRIVER_OBJECT _DriverObject,PUNICODE_STRING RegistryPath); NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT); -NTSTATUS VfatRead (PVFAT_IRP_CONTEXT); -NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT); -NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT); -NTSTATUS VfatClose (PVFAT_IRP_CONTEXT); -NTSTATUS VfatFileSystemControl (PVFAT_IRP_CONTEXT); -NTSTATUS VfatQueryInformation (PVFAT_IRP_CONTEXT); -NTSTATUS VfatSetInformation (PVFAT_IRP_CONTEXT); -NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT); -NTSTATUS STDCALL -VfatShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp); -NTSTATUS VfatQueryVolumeInformation (PVFAT_IRP_CONTEXT); -NTSTATUS VfatSetVolumeInformation (PVFAT_IRP_CONTEXT); +BOOL FsdDosDateTimeToFileTime (WORD wDosDate, + WORD wDosTime, + TIME *FileTime); -NTSTATUS -NextCluster(PDEVICE_EXTENSION DeviceExt, - PVFATFCB Fcb, - ULONG FirstCluster, - PULONG CurrentCluster, - BOOLEAN Extend); +BOOL FsdFileTimeToDosDateTime (TIME *FileTime, + WORD *pwDosDate, + WORD *pwDosTime); -/* internal functions in blockdev.c */ -NTSTATUS -VfatReadSectors(IN PDEVICE_OBJECT pDeviceObject, - IN ULONG DiskSector, - IN ULONG SectorCount, - IN UCHAR* Buffer); +/* -------------------------------------------------------- create.c */ -NTSTATUS -VfatWriteSectors(IN PDEVICE_OBJECT pDeviceObject, - IN ULONG DiskSector, - IN ULONG SectorCount, - IN UCHAR* Buffer); +NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext); -/* internal functions in dir.c : */ -BOOL FsdDosDateTimeToFileTime(WORD wDosDate,WORD wDosTime, TIME *FileTime); -BOOL FsdFileTimeToDosDateTime(TIME *FileTime,WORD *pwDosDate,WORD *pwDosTime); +NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PWSTR FileName); -/* internal functions in iface.c : */ -NTSTATUS -FindFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb, - PVFATFCB Parent, PWSTR FileToFind,ULONG *StartSector,ULONG *Entry); -NTSTATUS -VfatCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject); -NTSTATUS -VfatOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, - PWSTR FileName); -NTSTATUS -VfatReadFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, - PVOID Buffer, ULONG Length, ULONG ReadOffset, - PULONG LengthRead, ULONG NoCache); -NTSTATUS -VfatWriteFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, - PVOID Buffer, ULONG Length, ULONG WriteOffset, BOOLEAN NoCache, BOOLEAN PageIo); -NTSTATUS -GetNextWriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG FirstCluster, - ULONG CurrentCluster, - PULONG NextCluster); -BOOLEAN -IsDeletedEntry(PVOID Block, ULONG Offset); -BOOLEAN -IsLastEntry(PVOID Block, ULONG Offset); -wchar_t* -vfat_wcsncpy(wchar_t * dest, const wchar_t *src,size_t wcount); +NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt, + PVFATFCB Fcb, + PVFATFCB Parent, + PWSTR FileToFind, + PULONG pDirIndex, + PULONG pDirIndex2); -/* internal functions in dirwr.c */ -NTSTATUS -addEntry(PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT pFileObject,ULONG RequestedOptions,UCHAR ReqAttr); -NTSTATUS -updEntry(PDEVICE_EXTENSION DeviceExt,PFILE_OBJECT pFileObject); -NTSTATUS -delEntry(PDEVICE_EXTENSION, PFILE_OBJECT); +VOID vfat8Dot3ToString (PCHAR pBasename, + PCHAR pExtension, + PWSTR pName); + +NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, + PVPB Vpb); + +BOOLEAN IsDeletedEntry (PVOID Block, + ULONG Offset); + +BOOLEAN IsLastEntry (PVOID Block, + ULONG Offset); + +/* --------------------------------------------------------- close.c */ + +NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatCloseFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject); + +/* ------------------------------------------------------- cleanup.c */ + +NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext); + +/* --------------------------------------------------------- fsctl.c */ + +NTSTATUS VfatFileSystemControl (PVFAT_IRP_CONTEXT IrpContext); + +/* --------------------------------------------------------- finfo.c */ + +NTSTATUS VfatQueryInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatSetInformation (PVFAT_IRP_CONTEXT IrpContext); + +/* --------------------------------------------------------- iface.c */ + +NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath); + +/* --------------------------------------------------------- dirwr.c */ + +NTSTATUS addEntry (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT pFileObject, + ULONG RequestedOptions,UCHAR ReqAttr); + +NTSTATUS updEntry (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT pFileObject); + +NTSTATUS delEntry(PDEVICE_EXTENSION, + PFILE_OBJECT); + +/* -------------------------------------------------------- string.c */ + +VOID vfat_initstr (wchar_t *wstr, + ULONG wsize); + +wchar_t* vfat_wcsncat (wchar_t * dest, + const wchar_t * src, + size_t wstart, + size_t wcount); + +wchar_t* vfat_wcsncpy (wchar_t * dest, + const wchar_t *src, + size_t wcount); + +wchar_t* vfat_movstr (wchar_t *src, + ULONG dpos, + ULONG spos, + ULONG len); + +BOOLEAN wstrcmpi (PWSTR s1, + PWSTR s2); + +BOOLEAN wstrcmpjoki (PWSTR s1, + PWSTR s2); + +PWCHAR vfatGetNextPathElement (PWCHAR pFileName); + +VOID vfatWSubString (PWCHAR pTarget, + const PWCHAR pSource, + size_t pLength); -/* - * String functions - */ -VOID -vfat_initstr(wchar_t *wstr, ULONG wsize); -wchar_t* -vfat_wcsncat(wchar_t * dest, const wchar_t * src,size_t wstart, size_t wcount); -wchar_t* -vfat_wcsncpy(wchar_t * dest, const wchar_t *src,size_t wcount); -wchar_t* -vfat_movstr(wchar_t *src, ULONG dpos, ULONG spos, ULONG len); -BOOLEAN -wstrcmpi(PWSTR s1, PWSTR s2); -BOOLEAN -wstrcmpjoki(PWSTR s1, PWSTR s2); -PWCHAR vfatGetNextPathElement (PWCHAR pFileName); -void vfatWSubString (PWCHAR pTarget, const PWCHAR pSource, size_t pLength); BOOL vfatIsFileNameValid (PWCHAR pFileName); -/* - * functions from fat.c - */ -NTSTATUS -OffsetToCluster(PDEVICE_EXTENSION DeviceExt, - PVFATFCB Fcb, - ULONG FirstCluster, - ULONG FileOffset, - PULONG Cluster, - BOOLEAN Extend); -ULONG -ClusterToSector(PDEVICE_EXTENSION DeviceExt, - ULONG Cluster); -NTSTATUS -GetNextCluster(PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster, - BOOLEAN Extend); -NTSTATUS -GetNextSector(PDEVICE_EXTENSION DeviceExt, - ULONG CurrentSector, - PULONG NextSector, - BOOLEAN Extend); -NTSTATUS -VfatRawReadCluster(PDEVICE_EXTENSION DeviceExt, - ULONG FirstCluster, - PVOID Buffer, - ULONG Cluster, - ULONG Count); -NTSTATUS -VfatRawWriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG FirstCluster, - PVOID Buffer, - ULONG Cluster, - ULONG Count); -NTSTATUS -FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER Clusters); -NTSTATUS -FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER Clusters); -NTSTATUS -FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER Clusters); -NTSTATUS -WriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG ClusterToWrite, - ULONG NewValue); +/* ----------------------------------------------------------- fat.c */ -/* --------------------------------------------------------- create.c */ +NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt, + PVFATFCB Fcb, + ULONG FirstCluster, + ULONG FileOffset, + PULONG Cluster, + BOOLEAN Extend); -void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName); -NTSTATUS -ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, PVPB Vpb); -NTSTATUS -VfatOpenFile(PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT FileObject, - PWSTR FileName); +ULONG ClusterToSector (PDEVICE_EXTENSION DeviceExt, + ULONG Cluster); -/* ----------------------------------------------- DirEntry Functions */ +NTSTATUS GetNextCluster (PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster, + BOOLEAN Extend); + +NTSTATUS GetNextSector (PDEVICE_EXTENSION DeviceExt, + ULONG CurrentSector, + PULONG NextSector, + BOOLEAN Extend); + +NTSTATUS VfatRawReadCluster (PDEVICE_EXTENSION DeviceExt, + ULONG FirstCluster, + PVOID Buffer, + ULONG Cluster, + ULONG Count); + +NTSTATUS VfatRawWriteCluster (PDEVICE_EXTENSION DeviceExt, + ULONG FirstCluster, + PVOID Buffer, + ULONG Cluster, + ULONG Count); + +NTSTATUS CountAvailableClusters (PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER Clusters); + +/* ------------------------------------------------------ direntry.c */ ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, PFAT_DIR_ENTRY pDirEntry); + BOOL vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry); + BOOL vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry); + BOOL vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry); -void vfatGetDirEntryName (PFAT_DIR_ENTRY pDirEntry, PWSTR pEntryName); + +VOID vfatGetDirEntryName (PFAT_DIR_ENTRY pDirEntry, + PWSTR pEntryName); + NTSTATUS vfatGetNextDirEntry (PDEVICE_EXTENSION pDeviceExt, PVFATFCB pDirectoryFCB, ULONG * pDirectoryIndex, PWSTR pLongFileName, PFAT_DIR_ENTRY pDirEntry); -/* ----------------------------------------------------- FCB Functions */ +/* ----------------------------------------------------------- fcb.c */ -PVFATFCB vfatNewFCB (PWCHAR pFileName); -void vfatDestroyFCB (PVFATFCB pFCB); -void vfatGrabFCB (PDEVICE_EXTENSION pVCB, PVFATFCB pFCB); -void vfatReleaseFCB (PDEVICE_EXTENSION pVCB, PVFATFCB pFCB); -void vfatAddFCBToTable (PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB); -PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt, - PWSTR pFileName); -PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB); -PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB); -BOOL vfatFCBIsDirectory (PDEVICE_EXTENSION pVCB, PVFATFCB FCB); -NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, - PVFATFCB fcb, - PFILE_OBJECT fileObject); -NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB, - PVFATFCB parentFCB, - PWSTR elementName, - PVFATFCB * fileFCB); -NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, - PVFATFCB *pParentFCB, - PVFATFCB *pFCB, - const PWSTR pFileName); -NTSTATUS vfatMakeFCBFromDirEntry(PVCB vcb, - PVFATFCB directoryFCB, - PWSTR longName, - PFAT_DIR_ENTRY dirEntry, - ULONG dirIndex, - PVFATFCB * fileFCB); +PVFATFCB vfatNewFCB (PWCHAR pFileName); -/* ------------------------------------------------------------- rw.c */ +VOID vfatDestroyFCB (PVFATFCB pFCB); -NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, PFILE_OBJECT pFileObject, ULONG NewSize); +VOID vfatGrabFCB (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +VOID vfatReleaseFCB (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +VOID vfatAddFCBToTable (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt, + PWSTR pFileName); + +PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB); + +PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB); + +BOOL vfatFCBIsDirectory (PDEVICE_EXTENSION pVCB, + PVFATFCB FCB); + +NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, + PVFATFCB fcb, + PFILE_OBJECT fileObject); + +NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB, + PVFATFCB parentFCB, + PWSTR elementName, + PVFATFCB * fileFCB); + +NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, + PVFATFCB *pParentFCB, + PVFATFCB *pFCB, + const PWSTR pFileName); + +NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb, + PVFATFCB directoryFCB, + PWSTR longName, + PFAT_DIR_ENTRY dirEntry, + ULONG dirIndex, + PVFATFCB * fileFCB); + +/* ------------------------------------------------------------ rw.c */ + +NTSTATUS VfatRead (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, + PFILE_OBJECT pFileObject, + ULONG NewSize); +/* +NTSTATUS VfatWriteFile (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVOID Buffer, + ULONG Length, + ULONG WriteOffset, + BOOLEAN NoCache, + BOOLEAN PageIo); + + +NTSTATUS VfatReadFile (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVOID Buffer, ULONG Length, + ULONG ReadOffset, + PULONG LengthRead, + ULONG NoCache); +*/ + +NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, + PVFATFCB Fcb, + ULONG FirstCluster, + PULONG CurrentCluster, + BOOLEAN Extend); + +/* ----------------------------------------------------------- misc.c */ -/* ------------------------------------------------------------- misc.c */ NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext); -PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp); -VOID VfatFreeIrpContext(PVFAT_IRP_CONTEXT IrpContext); -NTSTATUS STDCALL VfatBuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp); +PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +VOID VfatFreeIrpContext(PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS STDCALL VfatBuildRequest (PDEVICE_OBJECT DeviceObject, + PIRP Irp); +/* +PVOID VfatGetUserBuffer(IN PIRP); + +NTSTATUS VfatLockUserBuffer(IN PIRP, IN ULONG, + IN LOCK_OPERATION); +*/ + +/* EOF */ diff --git a/reactos/drivers/fs/vfat/volume.c b/reactos/drivers/fs/vfat/volume.c index 2044bffbdbf..c22ded39026 100644 --- a/reactos/drivers/fs/vfat/volume.c +++ b/reactos/drivers/fs/vfat/volume.c @@ -1,4 +1,4 @@ -/* $Id: volume.c,v 1.14 2001/11/02 22:47:36 hbirr Exp $ +/* $Id: volume.c,v 1.15 2002/03/18 22:37:13 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -62,29 +62,39 @@ FsdGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject, static NTSTATUS -FsdGetFsAttributeInformation(PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo, +FsdGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt, + PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo, PULONG BufferLength) { + ULONG Length = DeviceExt->FatInfo.FatType == FAT32 ? 10 : 6; + DPRINT("FsdGetFsAttributeInformation()\n"); DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo); DPRINT("BufferLength %lu\n", *BufferLength); - DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6)); + DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length)); if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; - if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6)) + if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length)) return STATUS_BUFFER_OVERFLOW; FsAttributeInfo->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK; FsAttributeInfo->MaximumComponentNameLength = 255; - FsAttributeInfo->FileSystemNameLength = 6; - wcscpy(FsAttributeInfo->FileSystemName, L"FAT"); + FsAttributeInfo->FileSystemNameLength = Length; + if (DeviceExt->FatInfo.FatType == FAT32) + { + memcpy(FsAttributeInfo->FileSystemName, L"FAT32", 10); + } + else + { + memcpy(FsAttributeInfo->FileSystemName, L"FAT", 6); + } DPRINT("Finished FsdGetFsAttributeInformation()\n"); - *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6); + *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length); DPRINT("BufferLength %lu\n", *BufferLength); return(STATUS_SUCCESS); @@ -106,35 +116,11 @@ FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject, return(STATUS_BUFFER_OVERFLOW); DeviceExt = DeviceObject->DeviceExtension; + Status = CountAvailableClusters(DeviceExt, &FsSizeInfo->AvailableAllocationUnits); - if (DeviceExt->FatType == FAT32) - { - struct _BootSector32 *BootSect = - (struct _BootSector32 *) DeviceExt->Boot; - - FsSizeInfo->TotalAllocationUnits.QuadPart = ((BootSect->Sectors ? BootSect->Sectors : BootSect->SectorsHuge)-DeviceExt->dataStart)/BootSect->SectorsPerCluster; - - Status = FAT32CountAvailableClusters(DeviceExt, - &FsSizeInfo->AvailableAllocationUnits); - - FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster; - FsSizeInfo->BytesPerSector = BootSect->BytesPerSector; - } - else - { - struct _BootSector *BootSect = (struct _BootSector *) DeviceExt->Boot; - - FsSizeInfo->TotalAllocationUnits.QuadPart = ((BootSect->Sectors ? BootSect->Sectors : BootSect->SectorsHuge)-DeviceExt->dataStart)/BootSect->SectorsPerCluster; - - if (DeviceExt->FatType == FAT16) - Status = FAT16CountAvailableClusters(DeviceExt, - &FsSizeInfo->AvailableAllocationUnits); - else - Status = FAT12CountAvailableClusters(DeviceExt, - &FsSizeInfo->AvailableAllocationUnits); - FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster; - FsSizeInfo->BytesPerSector = BootSect->BytesPerSector; - } + FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->FatInfo.NumberOfClusters; + FsSizeInfo->SectorsPerAllocationUnit = DeviceExt->FatInfo.SectorsPerCluster; + FsSizeInfo->BytesPerSector = DeviceExt->FatInfo.BytesPerSector; DPRINT("Finished FsdGetFsSizeInformation()\n"); if (NT_SUCCESS(Status)) @@ -216,7 +202,8 @@ NTSTATUS VfatQueryVolumeInformation(PVFAT_IRP_CONTEXT IrpContext) break; case FileFsAttributeInformation: - RC = FsdGetFsAttributeInformation(SystemBuffer, + RC = FsdGetFsAttributeInformation(IrpContext->DeviceObject->DeviceExtension, + SystemBuffer, &BufferLength); break;