mirror of
https://github.com/reactos/reactos.git
synced 2025-07-27 20:41:59 +00:00
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
This commit is contained in:
parent
2c21decf9c
commit
d09531b121
14 changed files with 1484 additions and 1195 deletions
|
@ -141,3 +141,67 @@ VfatWriteSectors (IN PDEVICE_OBJECT pDeviceObject,
|
||||||
DPRINT ("Block request succeeded\n");
|
DPRINT ("Block request succeeded\n");
|
||||||
return (STATUS_SUCCESS);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -220,80 +220,60 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
|
||||||
* FUNCTION: Read the volume label
|
* FUNCTION: Read the volume label
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ULONG i = 0;
|
PVOID Context = NULL;
|
||||||
ULONG j;
|
ULONG Offset = 0;
|
||||||
ULONG Size;
|
ULONG DirIndex = 0;
|
||||||
char *block;
|
FATDirEntry* Entry;
|
||||||
ULONG StartingSector;
|
PVFATFCB pFcb;
|
||||||
ULONG NextCluster;
|
LARGE_INTEGER FileOffset;
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
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->VolumeLabel) = 0;
|
||||||
Vpb->VolumeLabelLength = 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
|
NTSTATUS
|
||||||
|
@ -336,9 +316,9 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
|
||||||
if (Parent)
|
if (Parent)
|
||||||
{
|
{
|
||||||
FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Parent->entry);
|
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;
|
isRoot = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -351,8 +331,8 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
|
||||||
isRoot = TRUE;
|
isRoot = TRUE;
|
||||||
if (isRoot)
|
if (isRoot)
|
||||||
{
|
{
|
||||||
if (DeviceExt->FatType == FAT32)
|
if (DeviceExt->FatInfo.FatType == FAT32)
|
||||||
FirstCluster = ((struct _BootSector32*)(DeviceExt->Boot))->RootCluster;
|
FirstCluster = DeviceExt->FatInfo.RootCluster;
|
||||||
else
|
else
|
||||||
FirstCluster = 1;
|
FirstCluster = 1;
|
||||||
|
|
||||||
|
@ -366,9 +346,9 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
Fcb->PathName[0]='\\';
|
Fcb->PathName[0]='\\';
|
||||||
Fcb->ObjectName = &Fcb->PathName[1];
|
Fcb->ObjectName = &Fcb->PathName[1];
|
||||||
Fcb->entry.FileSize = DeviceExt->rootDirectorySectors * BLOCKSIZE;
|
Fcb->entry.FileSize = DeviceExt->FatInfo.rootDirectorySectors * BLOCKSIZE;
|
||||||
Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
|
Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
if (DeviceExt->FatType == FAT32)
|
if (DeviceExt->FatInfo.FatType == FAT32)
|
||||||
{
|
{
|
||||||
Fcb->entry.FirstCluster = ((PUSHORT)FirstCluster)[0];
|
Fcb->entry.FirstCluster = ((PUSHORT)FirstCluster)[0];
|
||||||
Fcb->entry.FirstClusterHigh = ((PUSHORT)FirstCluster)[1];
|
Fcb->entry.FirstClusterHigh = ((PUSHORT)FirstCluster)[1];
|
||||||
|
@ -630,7 +610,11 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
if (Status == STATUS_INVALID_PARAMETER)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
if (Status == STATUS_DELETE_PENDING)
|
if (Status == STATUS_DELETE_PENDING)
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
|
@ -694,7 +678,7 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
ULONG Cluster, NextCluster;
|
ULONG Cluster, NextCluster;
|
||||||
/* FIXME set size to 0 and free clusters */
|
/* FIXME set size to 0 and free clusters */
|
||||||
pFcb->entry.FileSize = 0;
|
pFcb->entry.FileSize = 0;
|
||||||
if (DeviceExt->FatType == FAT32)
|
if (DeviceExt->FatInfo.FatType == FAT32)
|
||||||
Cluster = pFcb->entry.FirstCluster
|
Cluster = pFcb->entry.FirstCluster
|
||||||
+ pFcb->entry.FirstClusterHigh * 65536;
|
+ pFcb->entry.FirstClusterHigh * 65536;
|
||||||
else
|
else
|
||||||
|
@ -726,15 +710,15 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
ULONG CurrentCluster, NextCluster, i;
|
ULONG CurrentCluster, NextCluster, i;
|
||||||
DPRINT("Open an existing paging file\n");
|
DPRINT("Open an existing paging file\n");
|
||||||
pFcb->Flags |= FCB_IS_PAGE_FILE;
|
pFcb->Flags |= FCB_IS_PAGE_FILE;
|
||||||
pFcb->FatChainSize =
|
pFcb->FatChainSize =
|
||||||
((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) / DeviceExt->BytesPerCluster);
|
((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) / DeviceExt->FatInfo.BytesPerCluster);
|
||||||
if (pFcb->FatChainSize)
|
if (pFcb->FatChainSize)
|
||||||
{
|
{
|
||||||
pFcb->FatChain = ExAllocatePool(NonPagedPool,
|
pFcb->FatChain = ExAllocatePool(NonPagedPool,
|
||||||
pFcb->FatChainSize * sizeof(ULONG));
|
pFcb->FatChainSize * sizeof(ULONG));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DeviceExt->FatType == FAT32)
|
if (DeviceExt->FatInfo.FatType == FAT32)
|
||||||
{
|
{
|
||||||
CurrentCluster = pFcb->entry.FirstCluster +
|
CurrentCluster = pFcb->entry.FirstCluster +
|
||||||
pFcb->entry.FirstClusterHigh * 65536;
|
pFcb->entry.FirstClusterHigh * 65536;
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -136,8 +136,8 @@ VfatGetFileDirectoryInformation (PVFATFCB pFcb,
|
||||||
&pInfo->ChangeTime);
|
&pInfo->ChangeTime);
|
||||||
pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize);
|
pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize);
|
||||||
/* Make allocsize a rounded up multiple of BytesPerCluster */
|
/* Make allocsize a rounded up multiple of BytesPerCluster */
|
||||||
AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) /
|
AllocSize = ((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) /
|
||||||
DeviceExt->BytesPerCluster) * DeviceExt->BytesPerCluster;
|
DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.BytesPerCluster;
|
||||||
pInfo->AllocationSize.QuadPart = AllocSize;
|
pInfo->AllocationSize.QuadPart = AllocSize;
|
||||||
pInfo->FileAttributes = pFcb->entry.Attrib;
|
pInfo->FileAttributes = pFcb->entry.Attrib;
|
||||||
|
|
||||||
|
@ -170,8 +170,8 @@ VfatGetFileFullDirectoryInformation (PVFATFCB pFcb,
|
||||||
&pInfo->ChangeTime);
|
&pInfo->ChangeTime);
|
||||||
pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize);
|
pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize);
|
||||||
/* Make allocsize a rounded up multiple of BytesPerCluster */
|
/* Make allocsize a rounded up multiple of BytesPerCluster */
|
||||||
AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) /
|
AllocSize = ((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) /
|
||||||
DeviceExt->BytesPerCluster) * DeviceExt->BytesPerCluster;
|
DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.BytesPerCluster;
|
||||||
pInfo->AllocationSize.QuadPart = AllocSize;
|
pInfo->AllocationSize.QuadPart = AllocSize;
|
||||||
pInfo->FileAttributes = pFcb->entry.Attrib;
|
pInfo->FileAttributes = pFcb->entry.Attrib;
|
||||||
// pInfo->EaSize=;
|
// pInfo->EaSize=;
|
||||||
|
@ -205,8 +205,8 @@ VfatGetFileBothInformation (PVFATFCB pFcb,
|
||||||
&pInfo->ChangeTime);
|
&pInfo->ChangeTime);
|
||||||
pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize);
|
pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize);
|
||||||
/* Make allocsize a rounded up multiple of BytesPerCluster */
|
/* Make allocsize a rounded up multiple of BytesPerCluster */
|
||||||
AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) /
|
AllocSize = ((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) /
|
||||||
DeviceExt->BytesPerCluster) * DeviceExt->BytesPerCluster;
|
DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.BytesPerCluster;
|
||||||
pInfo->AllocationSize.QuadPart = AllocSize;
|
pInfo->AllocationSize.QuadPart = AllocSize;
|
||||||
pInfo->FileAttributes = pFcb->entry.Attrib;
|
pInfo->FileAttributes = pFcb->entry.Attrib;
|
||||||
// pInfo->EaSize=;
|
// pInfo->EaSize=;
|
||||||
|
@ -255,10 +255,11 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
|
||||||
if (!pCcb->DirectorySearchPattern)
|
if (!pCcb->DirectorySearchPattern)
|
||||||
{
|
{
|
||||||
First = TRUE;
|
First = TRUE;
|
||||||
pCcb->DirectorySearchPattern =
|
pCcb->DirectorySearchPattern =
|
||||||
ExAllocatePool(NonPagedPool, pSearchPattern->Length + sizeof(WCHAR));
|
ExAllocatePool(NonPagedPool, pSearchPattern->Length + sizeof(WCHAR));
|
||||||
if (!pCcb->DirectorySearchPattern)
|
if (!pCcb->DirectorySearchPattern)
|
||||||
{
|
{
|
||||||
|
ExReleaseResourceLite(&pFcb->MainResource);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
memcpy(pCcb->DirectorySearchPattern, pSearchPattern->Buffer,
|
memcpy(pCcb->DirectorySearchPattern, pSearchPattern->Buffer,
|
||||||
|
@ -272,12 +273,13 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
|
||||||
pCcb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
|
pCcb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
|
||||||
if (!pCcb->DirectorySearchPattern)
|
if (!pCcb->DirectorySearchPattern)
|
||||||
{
|
{
|
||||||
|
ExReleaseResourceLite(&pFcb->MainResource);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
pCcb->DirectorySearchPattern[0] = L'*';
|
pCcb->DirectorySearchPattern[0] = L'*';
|
||||||
pCcb->DirectorySearchPattern[1] = 0;
|
pCcb->DirectorySearchPattern[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IrpContext->Stack->Flags & SL_INDEX_SPECIFIED)
|
if (IrpContext->Stack->Flags & SL_INDEX_SPECIFIED)
|
||||||
{
|
{
|
||||||
pCcb->Entry = pCcb->CurrentByteOffset.u.LowPart;
|
pCcb->Entry = pCcb->CurrentByteOffset.u.LowPart;
|
||||||
|
@ -369,11 +371,7 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
RC = STATUS_SUCCESS;
|
RC = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
if (IrpContext->Flags & IRPCONTEXT_CANWAIT)
|
ExReleaseResourceLite(&pFcb->MainResource);
|
||||||
{
|
|
||||||
ExReleaseResourceLite(&pFcb->MainResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
return RC;
|
return RC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
* FILE: DirEntry.c
|
||||||
|
@ -20,11 +20,11 @@
|
||||||
|
|
||||||
#include "vfat.h"
|
#include "vfat.h"
|
||||||
|
|
||||||
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \
|
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGESIZE ? \
|
||||||
(pDeviceExt)->BytesPerCluster : PAGESIZE)
|
(pDeviceExt)->FatInfo.BytesPerCluster : PAGESIZE)
|
||||||
|
|
||||||
#define ENTRIES_PER_CACHEPAGE(pDeviceExt) (ENTRIES_PER_SECTOR * \
|
#define ENTRIES_PER_CACHEPAGE(pDeviceExt) (ENTRIES_PER_SECTOR * \
|
||||||
(CACHEPAGESIZE(pDeviceExt) / ((pDeviceExt)->BytesPerSector)))
|
(CACHEPAGESIZE(pDeviceExt) / ((pDeviceExt)->FatInfo.BytesPerSector)))
|
||||||
|
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
|
@ -33,7 +33,7 @@ vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
|
||||||
{
|
{
|
||||||
ULONG cluster;
|
ULONG cluster;
|
||||||
|
|
||||||
if (pDeviceExt->FatType == FAT32)
|
if (pDeviceExt->FatInfo.FatType == FAT32)
|
||||||
{
|
{
|
||||||
cluster = pFatDirEntry->FirstCluster +
|
cluster = pFatDirEntry->FirstCluster +
|
||||||
pFatDirEntry->FirstClusterHigh * 65536;
|
pFatDirEntry->FirstClusterHigh * 65536;
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -31,69 +31,10 @@ vfatIsShortIllegal(char c)
|
||||||
return FALSE;
|
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)
|
NTSTATUS updEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
||||||
/*
|
/*
|
||||||
update an existing FAT entry
|
* update an existing FAT entry
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
PVOID Context;
|
PVOID Context;
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
|
@ -118,9 +59,10 @@ NTSTATUS updEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
Offset.QuadPart = pFcb->dirIndex * sizeof(FATDirEntry);
|
Offset.u.HighPart = 0;
|
||||||
if(CcMapData (pDirFcb->FileObject, &Offset, sizeof(FATDirEntry),
|
Offset.u.LowPart = pFcb->dirIndex * sizeof(FATDirEntry);
|
||||||
TRUE, &Context, &Buffer))
|
if (CcMapData (pDirFcb->FileObject, &Offset, sizeof(FATDirEntry),
|
||||||
|
TRUE, &Context, (PVOID*)&Buffer))
|
||||||
{
|
{
|
||||||
memcpy(Buffer, &pFcb->entry, sizeof(FATDirEntry));
|
memcpy(Buffer, &pFcb->entry, sizeof(FATDirEntry));
|
||||||
CcSetDirtyPinnedData(Context, NULL);
|
CcSetDirtyPinnedData(Context, NULL);
|
||||||
|
@ -128,42 +70,147 @@ NTSTATUS updEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DPRINT1 ("Failed write to \'%S\'.\n", pDirFcb->PathName);
|
DPRINT1 ("Failed write to \'%S\'.\n", pDirFcb->PathName);
|
||||||
vfatReleaseFCB(DeviceExt, pDirFcb);
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||||
return STATUS_SUCCESS;
|
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
|
NTSTATUS
|
||||||
addEntry (PDEVICE_EXTENSION DeviceExt,
|
addEntry (PDEVICE_EXTENSION DeviceExt,
|
||||||
PFILE_OBJECT pFileObject, ULONG RequestedOptions, UCHAR ReqAttr)
|
PFILE_OBJECT pFileObject,
|
||||||
|
ULONG RequestedOptions,
|
||||||
|
UCHAR ReqAttr)
|
||||||
/*
|
/*
|
||||||
create a new FAT entry
|
create a new FAT entry
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
WCHAR DirName[MAX_PATH], *FileName, *PathFileName;
|
WCHAR DirName[MAX_PATH], *FileName, *PathFileName;
|
||||||
VFATFCB FileFcb;
|
VFATFCB FileFcb;
|
||||||
FATDirEntry FatEntry;
|
PVOID Context = NULL;
|
||||||
NTSTATUS status;
|
FATDirEntry *pFatEntry, *pEntry;
|
||||||
FATDirEntry *pEntry;
|
|
||||||
slot *pSlots;
|
slot *pSlots;
|
||||||
ULONG LengthRead, Offset;
|
short nbSlots = 0, nbFree = 0, j, posCar, NameLen;
|
||||||
short nbSlots = 0, nbFree = 0, i, j, posCar, NameLen;
|
PUCHAR Buffer;
|
||||||
PUCHAR Buffer, Buffer2;
|
|
||||||
BOOLEAN needTilde = FALSE, needLong = FALSE;
|
BOOLEAN needTilde = FALSE, needLong = FALSE;
|
||||||
PVFATFCB newFCB;
|
PVFATFCB newFCB;
|
||||||
ULONG CurrentCluster;
|
ULONG CurrentCluster;
|
||||||
LARGE_INTEGER SystemTime, LocalTime;
|
LARGE_INTEGER SystemTime, LocalTime, FileOffset;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PVFATFCB pDirFcb;
|
PVFATFCB pDirFcb;
|
||||||
|
ULONG start, size;
|
||||||
|
long i;
|
||||||
|
|
||||||
PathFileName = pFileObject->FileName.Buffer;
|
PathFileName = pFileObject->FileName.Buffer;
|
||||||
DPRINT ("addEntry: Pathname=%S\n", PathFileName);
|
DPRINT ("addEntry: Pathname=%S\n", PathFileName);
|
||||||
//find last \ in PathFileName
|
//find last \ in PathFileName
|
||||||
posCar = -1;
|
posCar = -1;
|
||||||
for (i = 0; PathFileName[i]; i++)
|
for (i = 0; PathFileName[i]; i++)
|
||||||
if (PathFileName[i] == '\\')
|
{
|
||||||
|
if (PathFileName[i] == L'\\')
|
||||||
|
{
|
||||||
posCar = i;
|
posCar = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (posCar == -1)
|
if (posCar == -1)
|
||||||
|
{
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
FileName = &PathFileName[posCar + 1];
|
FileName = &PathFileName[posCar + 1];
|
||||||
for (NameLen = 0; FileName[NameLen]; NameLen++);
|
for (NameLen = 0; FileName[NameLen]; NameLen++);
|
||||||
// extract directory name from pathname
|
// 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
|
nbSlots = (NameLen + 12) / 13 + 1; //nb of entry needed for long name+normal entry
|
||||||
DPRINT ("NameLen= %d, nbSlots =%d\n", NameLen, nbSlots);
|
DPRINT ("NameLen= %d, nbSlots =%d\n", NameLen, nbSlots);
|
||||||
Buffer =
|
Buffer = ExAllocatePool (NonPagedPool, nbSlots * sizeof (FATDirEntry));
|
||||||
ExAllocatePool (NonPagedPool, (nbSlots + 1) * sizeof (FATDirEntry));
|
RtlZeroMemory (Buffer, nbSlots * sizeof (FATDirEntry));
|
||||||
memset (Buffer, 0, (nbSlots + 1) * sizeof (FATDirEntry));
|
|
||||||
pEntry = (FATDirEntry *) (Buffer + (nbSlots - 1) * sizeof (FATDirEntry));
|
pEntry = (FATDirEntry *) (Buffer + (nbSlots - 1) * sizeof (FATDirEntry));
|
||||||
pSlots = (slot *) Buffer;
|
pSlots = (slot *) Buffer;
|
||||||
// create 8.3 name
|
// create 8.3 name
|
||||||
|
@ -196,21 +242,29 @@ addEntry (PDEVICE_EXTENSION DeviceExt,
|
||||||
// find last point in name
|
// find last point in name
|
||||||
posCar = j = 0;
|
posCar = j = 0;
|
||||||
for (i = 0; FileName[i]; i++)
|
for (i = 0; FileName[i]; i++)
|
||||||
|
{
|
||||||
if (FileName[i] == '.')
|
if (FileName[i] == '.')
|
||||||
{
|
{
|
||||||
posCar = i;
|
posCar = i;
|
||||||
if (i == j)
|
if (i == j)
|
||||||
|
{
|
||||||
j++;
|
j++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!posCar)
|
if (!posCar)
|
||||||
|
{
|
||||||
posCar = i;
|
posCar = i;
|
||||||
|
}
|
||||||
if (posCar < j)
|
if (posCar < j)
|
||||||
{
|
{
|
||||||
posCar = i;
|
posCar = i;
|
||||||
needTilde = TRUE;
|
needTilde = TRUE;
|
||||||
}
|
}
|
||||||
if (posCar > 8)
|
if (posCar > 8)
|
||||||
|
{
|
||||||
needTilde = TRUE;
|
needTilde = TRUE;
|
||||||
|
}
|
||||||
//copy 8 characters max
|
//copy 8 characters max
|
||||||
memset (pEntry, ' ', 11);
|
memset (pEntry, ' ', 11);
|
||||||
for (i = 0, j = 0; j < 8 && i < posCar; i++)
|
for (i = 0, j = 0; j < 8 && i < posCar; i++)
|
||||||
|
@ -223,13 +277,18 @@ addEntry (PDEVICE_EXTENSION DeviceExt,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (FileName[i] == '.')
|
if (FileName[i] == '.')
|
||||||
|
{
|
||||||
needTilde = TRUE;
|
needTilde = TRUE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
pEntry->Filename[j++] = toupper ((char) FileName[i]);
|
pEntry->Filename[j++] = toupper ((char) FileName[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//copy extension
|
//copy extension
|
||||||
if (FileName[posCar])
|
if (FileName[posCar])
|
||||||
|
{
|
||||||
for (j = 0, i = posCar + 1; FileName[i] && j < 3; i++)
|
for (j = 0, i = posCar + 1; FileName[i] && j < 3; i++)
|
||||||
{
|
{
|
||||||
if (vfatIsShortIllegal(FileName[i]))
|
if (vfatIsShortIllegal(FileName[i]))
|
||||||
|
@ -240,13 +299,20 @@ addEntry (PDEVICE_EXTENSION DeviceExt,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (FileName[i] == '.')
|
if (FileName[i] == '.')
|
||||||
|
{
|
||||||
needTilde = TRUE;
|
needTilde = TRUE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
pEntry->Ext[j++] = toupper ((char) (FileName[i] & 0x7F));
|
{
|
||||||
|
pEntry->Ext[j++] = toupper ((char) (FileName[i] & 0x7F));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (FileName[i])
|
if (FileName[i])
|
||||||
|
{
|
||||||
needTilde = TRUE;
|
needTilde = TRUE;
|
||||||
|
}
|
||||||
//find good value for tilde
|
//find good value for tilde
|
||||||
if (needTilde)
|
if (needTilde)
|
||||||
{
|
{
|
||||||
|
@ -254,10 +320,14 @@ addEntry (PDEVICE_EXTENSION DeviceExt,
|
||||||
DPRINT ("searching a good value for tilde\n");
|
DPRINT ("searching a good value for tilde\n");
|
||||||
for (posCar = 0; posCar < 8 && pEntry->Filename[posCar] != ' '; posCar++);
|
for (posCar = 0; posCar < 8 && pEntry->Filename[posCar] != ' '; posCar++);
|
||||||
if (posCar == 0) // ??????????????????????
|
if (posCar == 0) // ??????????????????????
|
||||||
|
{
|
||||||
pEntry->Filename[posCar++] = '_';
|
pEntry->Filename[posCar++] = '_';
|
||||||
|
}
|
||||||
posCar += 2;
|
posCar += 2;
|
||||||
if (posCar > 8)
|
if (posCar > 8)
|
||||||
|
{
|
||||||
posCar = 8;
|
posCar = 8;
|
||||||
|
}
|
||||||
pEntry->Filename[posCar - 2] = '~';
|
pEntry->Filename[posCar - 2] = '~';
|
||||||
pEntry->Filename[posCar - 1] = '1';
|
pEntry->Filename[posCar - 1] = '1';
|
||||||
vfat8Dot3ToString (pEntry->Filename, pEntry->Ext, DirName);
|
vfat8Dot3ToString (pEntry->Filename, pEntry->Ext, DirName);
|
||||||
|
@ -266,15 +336,19 @@ addEntry (PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
DirName[posCar-1] = '0' + i;
|
DirName[posCar-1] = '0' + i;
|
||||||
pEntry->Filename[posCar - 1] = '0' + i;
|
pEntry->Filename[posCar - 1] = '0' + i;
|
||||||
status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL);
|
Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(Status))
|
||||||
break;
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (i == 10)
|
if (i == 10)
|
||||||
{
|
{
|
||||||
posCar++;
|
posCar++;
|
||||||
if (posCar > 8)
|
if (posCar > 8)
|
||||||
|
{
|
||||||
posCar = 8;
|
posCar = 8;
|
||||||
|
}
|
||||||
pEntry->Filename[posCar - 3] = '~';
|
pEntry->Filename[posCar - 3] = '~';
|
||||||
pEntry->Filename[posCar - 2] = '1';
|
pEntry->Filename[posCar - 2] = '1';
|
||||||
pEntry->Filename[posCar - 1] = '0';
|
pEntry->Filename[posCar - 1] = '0';
|
||||||
|
@ -286,38 +360,44 @@ addEntry (PDEVICE_EXTENSION DeviceExt,
|
||||||
DirName[posCar - 2] = '0' + i / 10;
|
DirName[posCar - 2] = '0' + i / 10;
|
||||||
pEntry->Filename[posCar - 1] = '0' + i % 10;
|
pEntry->Filename[posCar - 1] = '0' + i % 10;
|
||||||
pEntry->Filename[posCar - 2] = '0' + i / 10;
|
pEntry->Filename[posCar - 2] = '0' + i / 10;
|
||||||
status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL);
|
Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(Status))
|
||||||
break;
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (i == 100) //FIXME : what to do after 99 tilde ?
|
if (i == 100) //FIXME : what to do after 99 tilde ?
|
||||||
{
|
{
|
||||||
vfatReleaseFCB(DeviceExt, pDirFcb);
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||||
ExFreePool (Buffer);
|
ExFreePool (Buffer);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINT ("check if long name entry needed, needlong=%d\n", needLong);
|
DPRINT ("check if long name entry needed, needlong=%d\n", needLong);
|
||||||
for (i = 0; i < posCar; i++)
|
for (i = 0; i < posCar; i++)
|
||||||
if ((USHORT) 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;
|
DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]);
|
||||||
}
|
|
||||||
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;
|
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)
|
if (needLong == FALSE)
|
||||||
{
|
{
|
||||||
|
@ -337,150 +417,148 @@ addEntry (PDEVICE_EXTENSION DeviceExt,
|
||||||
/* set attributes */
|
/* set attributes */
|
||||||
pEntry->Attrib = ReqAttr;
|
pEntry->Attrib = ReqAttr;
|
||||||
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
||||||
|
{
|
||||||
pEntry->Attrib |= FILE_ATTRIBUTE_DIRECTORY;
|
pEntry->Attrib |= FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
}
|
||||||
/* set dates and times */
|
/* set dates and times */
|
||||||
KeQuerySystemTime (&SystemTime);
|
KeQuerySystemTime (&SystemTime);
|
||||||
ExSystemTimeToLocalTime (&SystemTime, &LocalTime);
|
ExSystemTimeToLocalTime (&SystemTime, &LocalTime);
|
||||||
FsdFileTimeToDosDateTime ((TIME *) & LocalTime,
|
FsdFileTimeToDosDateTime ((TIME *) & LocalTime, &pEntry->CreationDate,
|
||||||
&pEntry->CreationDate, &pEntry->CreationTime);
|
&pEntry->CreationTime);
|
||||||
pEntry->UpdateDate = pEntry->CreationDate;
|
pEntry->UpdateDate = pEntry->CreationDate;
|
||||||
pEntry->UpdateTime = pEntry->CreationTime;
|
pEntry->UpdateTime = pEntry->CreationTime;
|
||||||
pEntry->AccessDate = pEntry->CreationDate;
|
pEntry->AccessDate = pEntry->CreationDate;
|
||||||
|
|
||||||
// calculate checksum for 8.3 name
|
// calculate checksum for 8.3 name
|
||||||
for (pSlots[0].alias_checksum = i = 0; i < 11; i++)
|
for (pSlots[0].alias_checksum = i = 0; i < 11; i++)
|
||||||
{
|
{
|
||||||
pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
|
pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
|
||||||
| ((pSlots[0].alias_checksum & 0xfe) >> 1))
|
| ((pSlots[0].alias_checksum & 0xfe) >> 1))
|
||||||
+ pEntry->Filename[i]);
|
+ pEntry->Filename[i]);
|
||||||
}
|
}
|
||||||
//construct slots and entry
|
//construct slots and entry
|
||||||
for (i = nbSlots - 2; i >= 0; i--)
|
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].id = nbSlots - i - 1;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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
|
//try to find nbSlots contiguous entries frees in directory
|
||||||
for (i = 0, status = STATUS_SUCCESS; status == STATUS_SUCCESS; i++)
|
if (!findDirSpace(DeviceExt, pDirFcb, nbSlots, &start))
|
||||||
{
|
{
|
||||||
status =
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||||
VfatReadFile (DeviceExt, pDirFcb->FileObject,
|
ExFreePool (Buffer);
|
||||||
&FatEntry, sizeof (FATDirEntry),
|
return STATUS_DISK_FULL;
|
||||||
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 (RequestedOptions & FILE_DIRECTORY_FILE)
|
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
||||||
{
|
{
|
||||||
CurrentCluster = 0xffffffff;
|
CurrentCluster = 0xffffffff;
|
||||||
status = NextCluster (DeviceExt, NULL, 0, &CurrentCluster, TRUE);
|
Status = NextCluster (DeviceExt, NULL, 0, &CurrentCluster, TRUE);
|
||||||
if (CurrentCluster == 0xffffffff || !NT_SUCCESS(status))
|
if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
vfatReleaseFCB(DeviceExt, pDirFcb);
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||||
ExFreePool (Buffer);
|
ExFreePool (Buffer);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return status;
|
return Status;
|
||||||
}
|
}
|
||||||
return STATUS_DISK_FULL;
|
return STATUS_DISK_FULL;
|
||||||
}
|
}
|
||||||
// zero the cluster
|
if (DeviceExt->FatInfo.FatType == FAT32)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// free the reserved cluster
|
pEntry->FirstClusterHigh = CurrentCluster >> 16;
|
||||||
WriteCluster(DeviceExt, CurrentCluster, 0);
|
|
||||||
}
|
}
|
||||||
ExFreePool (Buffer);
|
pEntry->FirstCluster = CurrentCluster;
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// FEXME: check status
|
||||||
vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, FileName,
|
vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, FileName, pEntry,
|
||||||
pEntry, Offset / sizeof(FATDirEntry) + nbSlots-1, &newFCB);
|
start + nbSlots - 1, &newFCB);
|
||||||
vfatAttachFCBToFileObject (DeviceExt, newFCB, pFileObject);
|
vfatAttachFCBToFileObject (DeviceExt, newFCB, pFileObject);
|
||||||
|
|
||||||
DPRINT ("new : entry=%11.11s\n", newFCB->entry.Filename);
|
DPRINT ("new : entry=%11.11s\n", newFCB->entry.Filename);
|
||||||
DPRINT ("new : entry=%11.11s\n", pEntry->Filename);
|
DPRINT ("new : entry=%11.11s\n", pEntry->Filename);
|
||||||
|
|
||||||
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
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 ..
|
if (pFatEntry[1].FirstCluster == (DeviceExt->FatInfo.RootCluster & 0xffff) &&
|
||||||
memcpy (pEntry->Filename, ". ", 11);
|
pFatEntry[1].FirstClusterHigh == (DeviceExt->FatInfo.RootCluster >> 16))
|
||||||
status =
|
{
|
||||||
VfatWriteFile (DeviceExt, pFileObject, pEntry, sizeof (FATDirEntry),
|
pFatEntry[1].FirstCluster = 0;
|
||||||
0L, FALSE, FALSE);
|
pFatEntry[1].FirstClusterHigh = 0;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pFatEntry[1].FirstCluster == 1)
|
||||||
|
{
|
||||||
|
pFatEntry[1].FirstCluster = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CcSetDirtyPinnedData(Context, NULL);
|
||||||
|
CcUnpinData(Context);
|
||||||
|
}
|
||||||
vfatReleaseFCB (DeviceExt, pDirFcb);
|
vfatReleaseFCB (DeviceExt, pDirFcb);
|
||||||
ExFreePool (Buffer);
|
ExFreePool (Buffer);
|
||||||
DPRINT ("addentry ok\n");
|
DPRINT ("addentry ok\n");
|
||||||
|
@ -490,8 +568,8 @@ addEntry (PDEVICE_EXTENSION DeviceExt,
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
||||||
/*
|
/*
|
||||||
deleting an existing FAT entry
|
* deleting an existing FAT entry
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
VFATFCB Fcb;
|
VFATFCB Fcb;
|
||||||
PVFATFCB pFcb = NULL, pDirFcb = NULL;
|
PVFATFCB pFcb = NULL, pDirFcb = NULL;
|
||||||
|
@ -502,7 +580,8 @@ delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
||||||
|
|
||||||
DPRINT ("delEntry PathFileName \'%S\'\n", pFileObject->FileName.Buffer);
|
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)
|
if (pFcb != NULL)
|
||||||
{
|
{
|
||||||
vfatReleaseFCB(DeviceExt, pFcb);
|
vfatReleaseFCB(DeviceExt, pFcb);
|
||||||
|
@ -524,18 +603,38 @@ delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
||||||
|
|
||||||
if (NT_SUCCESS(status))
|
if (NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
|
PVOID Context = NULL;
|
||||||
|
LARGE_INTEGER Offset;
|
||||||
|
FATDirEntry* pDirEntry;
|
||||||
DPRINT ("delete entry: %d to %d\n", startEntry, Entry);
|
DPRINT ("delete entry: %d to %d\n", startEntry, Entry);
|
||||||
|
Offset.u.HighPart = 0;
|
||||||
for (i = startEntry; i <= Entry; i++)
|
for (i = startEntry; i <= Entry; i++)
|
||||||
{
|
{
|
||||||
// FIXME: using Cc-functions
|
if (Context == NULL || ((i * sizeof(FATDirEntry)) % PAGESIZE) == 0)
|
||||||
VfatReadFile (DeviceExt, pDirFcb->FileObject, &DirEntry,
|
{
|
||||||
sizeof (FATDirEntry), i * sizeof(FATDirEntry), &Read, FALSE);
|
if (Context)
|
||||||
DirEntry.Filename[0] = 0xe5;
|
{
|
||||||
// FIXME: check status
|
CcSetDirtyPinnedData(Context, NULL);
|
||||||
VfatWriteFile (DeviceExt, pDirFcb->FileObject, &DirEntry,
|
CcUnpinData(Context);
|
||||||
sizeof(FATDirEntry), i * sizeof(FATDirEntry), FALSE, FALSE);
|
}
|
||||||
|
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)
|
while (CurrentCluster && CurrentCluster != 0xffffffff)
|
||||||
{
|
{
|
||||||
GetNextCluster (DeviceExt, CurrentCluster, &NextCluster, FALSE);
|
GetNextCluster (DeviceExt, CurrentCluster, &NextCluster, FALSE);
|
||||||
|
@ -544,6 +643,7 @@ delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
|
||||||
CurrentCluster = NextCluster;
|
CurrentCluster = NextCluster;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
vfatReleaseFCB(DeviceExt, pDirFcb);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -24,8 +24,8 @@
|
||||||
|
|
||||||
#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
|
#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
|
||||||
|
|
||||||
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \
|
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGESIZE ? \
|
||||||
(pDeviceExt)->BytesPerCluster : PAGESIZE)
|
(pDeviceExt)->FatInfo.BytesPerCluster : PAGESIZE)
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
* FUNCTION: Retrieve the next FAT12 cluster from the FAT table
|
* FUNCTION: Retrieve the next FAT12 cluster from the FAT table
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
PUCHAR CBlock;
|
PUSHORT CBlock;
|
||||||
ULONG FATOffset;
|
ULONG FATOffset;
|
||||||
ULONG Entry;
|
ULONG Entry;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -110,22 +110,18 @@ Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
*NextCluster = 0;
|
*NextCluster = 0;
|
||||||
|
|
||||||
Offset.QuadPart = 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;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
CBlock = (PUCHAR)BaseAddress;
|
CBlock = (PUSHORT)(BaseAddress + (CurrentCluster * 12) / 8);
|
||||||
|
|
||||||
FATOffset = (CurrentCluster * 12) / 8; /* first byte containing value */
|
|
||||||
if ((CurrentCluster % 2) == 0)
|
if ((CurrentCluster % 2) == 0)
|
||||||
{
|
{
|
||||||
Entry = CBlock[FATOffset];
|
Entry = *CBlock & 0x0fff;
|
||||||
Entry |= ((CBlock[FATOffset+1] & 0xf)<<8);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Entry = (CBlock[FATOffset] >> 4);
|
Entry = *CBlock >> 4;
|
||||||
Entry |= (CBlock[FATOffset+1] << 4);
|
|
||||||
}
|
}
|
||||||
// DPRINT("Entry %x\n",Entry);
|
// DPRINT("Entry %x\n",Entry);
|
||||||
if (Entry >= 0xff8 && Entry <= 0xfff)
|
if (Entry >= 0xff8 && Entry <= 0xfff)
|
||||||
|
@ -152,15 +148,16 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
ULONG ChunkSize;
|
ULONG ChunkSize;
|
||||||
PVOID Context = 0;
|
PVOID Context = 0;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
|
PUSHORT Block;
|
||||||
|
|
||||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||||
FatLength = DeviceExt->NumberOfClusters * 2;
|
FatLength = (DeviceExt->FatInfo.NumberOfClusters +2 ) * 2;
|
||||||
*Cluster = 0;
|
*Cluster = 0;
|
||||||
StartCluster = DeviceExt->LastAvailableCluster;
|
StartCluster = DeviceExt->LastAvailableCluster;
|
||||||
|
|
||||||
for (j = 0; j < 2; j++)
|
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)
|
if ((i % ChunkSize) == 0 || Context == NULL)
|
||||||
{
|
{
|
||||||
|
@ -169,14 +166,17 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
CcUnpinData(Context);
|
CcUnpinData(Context);
|
||||||
}
|
}
|
||||||
|
CHECKPOINT;
|
||||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||||
{
|
{
|
||||||
DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
|
DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
|
||||||
return STATUS_UNSUCCESSFUL;
|
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);
|
DPRINT("Found available cluster 0x%x\n", i / 2);
|
||||||
DeviceExt->LastAvailableCluster = *Cluster = i / 2;
|
DeviceExt->LastAvailableCluster = *Cluster = i / 2;
|
||||||
|
@ -186,8 +186,12 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
}
|
}
|
||||||
FatLength = StartCluster * 2;
|
FatLength = StartCluster * 2;
|
||||||
StartCluster = 2;
|
StartCluster = 2;
|
||||||
|
if (Context != NULL)
|
||||||
|
{
|
||||||
|
CcUnpinData(Context);
|
||||||
|
Context =NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CcUnpinData(Context);
|
|
||||||
return(STATUS_DISK_FULL);
|
return(STATUS_DISK_FULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,38 +205,35 @@ FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
||||||
ULONG FATOffset;
|
ULONG FATOffset;
|
||||||
ULONG StartCluster;
|
ULONG StartCluster;
|
||||||
ULONG Entry;
|
ULONG Entry;
|
||||||
PUCHAR CBlock;
|
PUSHORT CBlock;
|
||||||
ULONG i, j;
|
ULONG i, j;
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PVOID Context;
|
PVOID Context;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
|
|
||||||
FatLength = DeviceExt->NumberOfClusters;
|
FatLength = DeviceExt->FatInfo.NumberOfClusters + 2;
|
||||||
*Cluster = 0;
|
*Cluster = 0;
|
||||||
StartCluster = DeviceExt->LastAvailableCluster;
|
StartCluster = DeviceExt->LastAvailableCluster;
|
||||||
Offset.QuadPart = 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))
|
||||||
{
|
{
|
||||||
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;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
CBlock = (PUCHAR)BaseAddress;
|
|
||||||
|
|
||||||
for (j = 0; j < 2; j++)
|
for (j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
for (i = StartCluster; i < FatLength; i++)
|
for (i = StartCluster; i < FatLength; i++)
|
||||||
{
|
{
|
||||||
FATOffset = (i * 12) / 8;
|
CBlock = (PUSHORT)(BaseAddress + (i * 12) / 8);
|
||||||
if ((i % 2) == 0)
|
if ((i % 2) == 0)
|
||||||
{
|
{
|
||||||
Entry = CBlock[FATOffset];
|
Entry = *CBlock & 0xfff;
|
||||||
Entry |= ((CBlock[FATOffset + 1] & 0xf) << 8);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Entry = (CBlock[FATOffset] >> 4);
|
Entry = *CBlock >> 4;
|
||||||
Entry |= (CBlock[FATOffset + 1] << 4);
|
|
||||||
}
|
}
|
||||||
if (Entry == 0)
|
if (Entry == 0)
|
||||||
{
|
{
|
||||||
|
@ -256,243 +257,229 @@ FAT32FindAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ULONG FatLength;
|
ULONG FatLength;
|
||||||
ULONG i;
|
ULONG StartCluster;
|
||||||
|
ULONG i, j;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
ULONG ChunkSize;
|
ULONG ChunkSize;
|
||||||
PVOID Context = NULL;
|
PVOID Context = 0;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
ULONG StartCluster;
|
PULONG Block;
|
||||||
|
|
||||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||||
FatLength = DeviceExt->NumberOfClusters * 4;
|
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4;
|
||||||
StartCluster = DeviceExt->LastAvailableCluster;
|
|
||||||
if (StartCluster == 0)
|
|
||||||
{
|
|
||||||
StartCluster = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
*Cluster = 0;
|
*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)
|
for (i = StartCluster * 4; i < FatLength; i += 4, Block++)
|
||||||
{
|
{
|
||||||
Offset.QuadPart = ROUND_DOWN(i, ChunkSize);
|
if ((i % ChunkSize) == 0 || Context == NULL)
|
||||||
if (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);
|
CcUnpinData(Context);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
}
|
||||||
{
|
FatLength = StartCluster * 4;
|
||||||
DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
|
StartCluster = 2;
|
||||||
return STATUS_UNSUCCESSFUL;
|
if (Context != NULL)
|
||||||
}
|
{
|
||||||
}
|
|
||||||
if ((*((PULONG)(BaseAddress + (i % ChunkSize))) & 0x0fffffff) == 0)
|
|
||||||
{
|
|
||||||
DPRINT("Found available cluster 0x%x\n", i / 4);
|
|
||||||
DeviceExt->LastAvailableCluster = *Cluster = i / 4;
|
|
||||||
CcUnpinData(Context);
|
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);
|
return (STATUS_DISK_FULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt,
|
FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
|
||||||
PLARGE_INTEGER Clusters)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Counts free cluster in a FAT12 table
|
* FUNCTION: Counts free cluster in a FAT12 table
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ULONG FATOffset;
|
ULONG FATOffset;
|
||||||
ULONG Entry;
|
ULONG Entry;
|
||||||
PUCHAR CBlock;
|
PVOID BaseAddress;
|
||||||
ULONG ulCount = 0;
|
ULONG ulCount = 0;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
PVOID BaseAddress;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG numberofclusters;
|
ULONG numberofclusters;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
PVOID Context;
|
PVOID Context;
|
||||||
|
PUSHORT CBlock;
|
||||||
|
|
||||||
ExAcquireResourceSharedLite (&DeviceExt->FatResource, TRUE);
|
|
||||||
Offset.QuadPart = 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))
|
||||||
{
|
{
|
||||||
ExReleaseResourceLite (&DeviceExt->FatResource);
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
CBlock = (PUCHAR)BaseAddress;
|
|
||||||
numberofclusters = DeviceExt->NumberOfClusters;
|
numberofclusters = DeviceExt->FatInfo.NumberOfClusters + 2;
|
||||||
|
|
||||||
for (i = 2; i < numberofclusters; i++)
|
for (i = 2; i < numberofclusters; i++)
|
||||||
{
|
{
|
||||||
FATOffset = (i * 12) / 8;
|
CBlock = (PUSHORT)(BaseAddress + (i * 12) / 8);
|
||||||
if ((i % 2) == 0)
|
if ((i % 2) == 0)
|
||||||
{
|
{
|
||||||
Entry = CBlock[FATOffset];
|
Entry = *CBlock & 0x0fff;
|
||||||
Entry |= ((CBlock[FATOffset + 1] & 0xf) << 8);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Entry = (CBlock[FATOffset] >> 4);
|
Entry = *CBlock >> 4;
|
||||||
Entry |= (CBlock[FATOffset + 1] << 4);
|
|
||||||
}
|
}
|
||||||
if (Entry == 0)
|
if (Entry == 0)
|
||||||
ulCount++;
|
ulCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
CcUnpinData(Context);
|
CcUnpinData(Context);
|
||||||
ExReleaseResourceLite (&DeviceExt->FatResource);
|
DeviceExt->AvailableClusters = ulCount;
|
||||||
|
DeviceExt->AvailableClustersValid = TRUE;
|
||||||
Clusters->QuadPart = ulCount;
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt,
|
FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
|
||||||
PLARGE_INTEGER Clusters)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Counts free clusters in a FAT16 table
|
* FUNCTION: Counts free clusters in a FAT16 table
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
PUSHORT Block;
|
PUSHORT Block;
|
||||||
|
PVOID BaseAddress = NULL;
|
||||||
ULONG ulCount = 0;
|
ULONG ulCount = 0;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
ULONG numberofclusters;
|
ULONG ChunkSize;
|
||||||
ULONG numberofsectors;
|
|
||||||
ULONG sector;
|
|
||||||
ULONG forto;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PVOID Context = NULL;
|
||||||
|
LARGE_INTEGER Offset;
|
||||||
|
ULONG FatLength;
|
||||||
|
|
||||||
ExAcquireResourceSharedLite (&DeviceExt->FatResource, TRUE);
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||||
Block = ExAllocatePool (NonPagedPool, BLOCKSIZE);
|
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 2;
|
||||||
|
|
||||||
numberofclusters = ((DeviceExt->Boot->Sectors ? DeviceExt->Boot->Sectors : DeviceExt->Boot->SectorsHuge)-DeviceExt->dataStart)/DeviceExt->Boot->SectorsPerCluster+2;
|
for (i = 4; i< FatLength; i += 2, Block++)
|
||||||
numberofsectors = (numberofclusters + 255) / 256;
|
{
|
||||||
numberofclusters %= 256;
|
if ((i % ChunkSize) == 0 || Context == NULL)
|
||||||
|
|
||||||
for (sector = 0; sector < numberofsectors; sector++)
|
|
||||||
{
|
{
|
||||||
Status = VfatReadSectors(DeviceExt->StorageDevice,
|
DPRINT("%d\n", i/2);
|
||||||
DeviceExt->FATStart + sector,
|
if (Context)
|
||||||
1,
|
|
||||||
(PUCHAR)Block);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
ExFreePool(Block);
|
CcUnpinData(Context);
|
||||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
|
||||||
return(Status);
|
|
||||||
}
|
}
|
||||||
|
Offset.QuadPart = ROUND_DOWN(i, ChunkSize);
|
||||||
if (sector == numberofsectors - 1)
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||||
forto = numberofclusters;
|
|
||||||
else
|
|
||||||
forto = 256;
|
|
||||||
|
|
||||||
for (i = 0; i < forto; i++)
|
|
||||||
{
|
{
|
||||||
if (Block[i] == 0)
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
Block = (PUSHORT)(BaseAddress + i % ChunkSize);
|
||||||
|
}
|
||||||
|
if (*Block == 0)
|
||||||
ulCount++;
|
ulCount++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ExReleaseResourceLite (&DeviceExt->FatResource);
|
|
||||||
|
|
||||||
Clusters->QuadPart = ulCount;
|
DeviceExt->AvailableClusters = ulCount;
|
||||||
ExFreePool(Block);
|
DeviceExt->AvailableClustersValid = TRUE;
|
||||||
|
CcUnpinData(Context);
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt,
|
FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
|
||||||
PLARGE_INTEGER Clusters)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Counts free clusters in a FAT32 table
|
* FUNCTION: Counts free clusters in a FAT32 table
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ULONG sector;
|
|
||||||
PULONG Block;
|
PULONG Block;
|
||||||
|
PVOID BaseAddress = NULL;
|
||||||
ULONG ulCount = 0;
|
ULONG ulCount = 0;
|
||||||
ULONG i,forto;
|
ULONG i;
|
||||||
ULONG numberofclusters;
|
ULONG ChunkSize;
|
||||||
ULONG numberofsectors;
|
|
||||||
NTSTATUS Status;
|
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);
|
for (i = 8; i< FatLength; i += 4, Block++)
|
||||||
|
{
|
||||||
numberofclusters = ((DeviceExt->Boot->Sectors ? DeviceExt->Boot->Sectors : DeviceExt->Boot->SectorsHuge)-DeviceExt->dataStart)/DeviceExt->Boot->SectorsPerCluster+2;
|
if ((i % ChunkSize) == 0 || Context == NULL)
|
||||||
numberofsectors = (numberofclusters +127) / 128;
|
{
|
||||||
numberofclusters %= 128;
|
if (Context)
|
||||||
|
|
||||||
for (sector = 0; sector < numberofsectors; sector++)
|
|
||||||
{
|
|
||||||
Status = VfatReadSectors(DeviceExt->StorageDevice,
|
|
||||||
(ULONG) (DeviceExt->FATStart + sector), 1,
|
|
||||||
(UCHAR *) Block);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
ExFreePool(Block);
|
CcUnpinData(Context);
|
||||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
|
||||||
return(Status);
|
|
||||||
}
|
}
|
||||||
|
Offset.QuadPart = ROUND_DOWN(i, ChunkSize);
|
||||||
if (sector == numberofsectors - 1)
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||||
forto=numberofclusters;
|
|
||||||
else
|
|
||||||
forto=128;
|
|
||||||
for (i = 0; i < forto; i++)
|
|
||||||
{
|
{
|
||||||
if ((Block[i] & 0x0fffffff) == 0)
|
return STATUS_UNSUCCESSFUL;
|
||||||
ulCount++;
|
|
||||||
}
|
}
|
||||||
}
|
Block = (PULONG)(BaseAddress + i % ChunkSize);
|
||||||
ExFreePool (Block);
|
}
|
||||||
ExReleaseResourceLite (&DeviceExt->FatResource);
|
if ((*Block & 0x0fffffff) == 0)
|
||||||
|
ulCount++;
|
||||||
|
}
|
||||||
|
|
||||||
Clusters->QuadPart = ulCount;
|
DeviceExt->AvailableClusters = ulCount;
|
||||||
|
DeviceExt->AvailableClustersValid = TRUE;
|
||||||
|
CcUnpinData(Context);
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
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
|
NTSTATUS
|
||||||
FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
ULONG ClusterToWrite,
|
ULONG ClusterToWrite,
|
||||||
ULONG NewValue)
|
ULONG NewValue,
|
||||||
|
PULONG OldValue)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
|
* FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
|
||||||
*/
|
*/
|
||||||
|
@ -507,7 +494,7 @@ FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
|
|
||||||
Offset.QuadPart = 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;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
@ -518,12 +505,14 @@ FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
NewValue, ClusterToWrite, FATOffset);
|
NewValue, ClusterToWrite, FATOffset);
|
||||||
if ((ClusterToWrite % 2) == 0)
|
if ((ClusterToWrite % 2) == 0)
|
||||||
{
|
{
|
||||||
|
*OldValue = CBlock[FATOffset] + ((CBlock[FATOffset + 1] & 0x0f) << 8);
|
||||||
CBlock[FATOffset] = NewValue;
|
CBlock[FATOffset] = NewValue;
|
||||||
CBlock[FATOffset + 1] &= 0xf0;
|
CBlock[FATOffset + 1] &= 0xf0;
|
||||||
CBlock[FATOffset + 1] |= (NewValue & 0xf00) >> 8;
|
CBlock[FATOffset + 1] |= (NewValue & 0xf00) >> 8;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
*OldValue = (CBlock[FATOffset] >> 4) + (CBlock[FATOffset + 1] << 4);
|
||||||
CBlock[FATOffset] &= 0x0f;
|
CBlock[FATOffset] &= 0x0f;
|
||||||
CBlock[FATOffset] |= (NewValue & 0xf) << 4;
|
CBlock[FATOffset] |= (NewValue & 0xf) << 4;
|
||||||
CBlock[FATOffset + 1] = NewValue >> 4;
|
CBlock[FATOffset + 1] = NewValue >> 4;
|
||||||
|
@ -538,7 +527,8 @@ FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
ULONG ClusterToWrite,
|
ULONG ClusterToWrite,
|
||||||
ULONG NewValue)
|
ULONG NewValue,
|
||||||
|
PULONG OldValue)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
|
* FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
|
||||||
*/
|
*/
|
||||||
|
@ -550,6 +540,7 @@ FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
ULONG ChunkSize;
|
ULONG ChunkSize;
|
||||||
PVOID Context;
|
PVOID Context;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
|
PUSHORT Cluster;
|
||||||
|
|
||||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||||
FATOffset = ClusterToWrite * 2;
|
FATOffset = ClusterToWrite * 2;
|
||||||
|
@ -560,7 +551,9 @@ FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
}
|
}
|
||||||
DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
|
DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
|
||||||
ClusterToWrite);
|
ClusterToWrite);
|
||||||
*((PUSHORT)(BaseAddress + (FATOffset % ChunkSize))) = NewValue;
|
Cluster = ((PUSHORT)(BaseAddress + (FATOffset % ChunkSize)));
|
||||||
|
*OldValue = *Cluster;
|
||||||
|
*Cluster = NewValue;
|
||||||
CcSetDirtyPinnedData(Context, NULL);
|
CcSetDirtyPinnedData(Context, NULL);
|
||||||
CcUnpinData(Context);
|
CcUnpinData(Context);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
|
@ -569,7 +562,8 @@ FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
ULONG ClusterToWrite,
|
ULONG ClusterToWrite,
|
||||||
ULONG NewValue)
|
ULONG NewValue,
|
||||||
|
PULONG OldValue)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Writes a cluster to the FAT32 physical tables
|
* FUNCTION: Writes a cluster to the FAT32 physical tables
|
||||||
*/
|
*/
|
||||||
|
@ -581,6 +575,7 @@ FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
ULONG ChunkSize;
|
ULONG ChunkSize;
|
||||||
PVOID Context;
|
PVOID Context;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
|
PULONG Cluster;
|
||||||
|
|
||||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||||
|
|
||||||
|
@ -592,13 +587,13 @@ FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
}
|
}
|
||||||
DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
|
DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
|
||||||
ClusterToWrite);
|
ClusterToWrite);
|
||||||
*((PULONG)(BaseAddress + (FATOffset % ChunkSize))) = NewValue & 0x0fffffff;
|
Cluster = ((PULONG)(BaseAddress + (FATOffset % ChunkSize)));
|
||||||
|
*OldValue = *Cluster & 0x0fffffff;
|
||||||
|
*Cluster = (*Cluster & 0xf0000000) | (NewValue & 0x0fffffff);
|
||||||
|
|
||||||
CcSetDirtyPinnedData(Context, NULL);
|
CcSetDirtyPinnedData(Context, NULL);
|
||||||
CcUnpinData(Context);
|
CcUnpinData(Context);
|
||||||
|
|
||||||
DPRINT("DeviceExt->Boot->FATSectors %d\n",
|
|
||||||
((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32);
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,19 +607,28 @@ WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
ULONG OldValue;
|
||||||
if (DeviceExt->FatType == FAT16)
|
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
|
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);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,8 +640,8 @@ ClusterToSector(PDEVICE_EXTENSION DeviceExt,
|
||||||
* device
|
* device
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
return DeviceExt->dataStart +
|
return DeviceExt->FatInfo.dataStart +
|
||||||
((Cluster - 2) * DeviceExt->Boot->SectorsPerCluster);
|
((Cluster - 2) * DeviceExt->FatInfo.SectorsPerCluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -654,7 +658,7 @@ VfatRawReadCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
if (FirstCluster == 1)
|
if (FirstCluster == 1)
|
||||||
{
|
{
|
||||||
return VfatReadSectors(DeviceExt->StorageDevice, Cluster,
|
return VfatReadSectors(DeviceExt->StorageDevice, Cluster,
|
||||||
DeviceExt->Boot->SectorsPerCluster * Count, Buffer);
|
DeviceExt->FatInfo.SectorsPerCluster * Count, Buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -662,7 +666,7 @@ VfatRawReadCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
|
|
||||||
Sector = ClusterToSector(DeviceExt, Cluster);
|
Sector = ClusterToSector(DeviceExt, Cluster);
|
||||||
return VfatReadSectors(DeviceExt->StorageDevice, Sector,
|
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)
|
if (FirstCluster == 1)
|
||||||
{
|
{
|
||||||
Status = VfatWriteSectors(DeviceExt->StorageDevice, Cluster,
|
Status = VfatWriteSectors(DeviceExt->StorageDevice, Cluster,
|
||||||
DeviceExt->Boot->SectorsPerCluster * Count, Buffer);
|
DeviceExt->FatInfo.SectorsPerCluster * Count, Buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Sector = ClusterToSector(DeviceExt, Cluster);
|
Sector = ClusterToSector(DeviceExt, Cluster);
|
||||||
|
|
||||||
Status = VfatWriteSectors(DeviceExt->StorageDevice, Sector,
|
Status = VfatWriteSectors(DeviceExt->StorageDevice, Sector,
|
||||||
DeviceExt->Boot->SectorsPerCluster * Count, Buffer);
|
DeviceExt->FatInfo.SectorsPerCluster * Count, Buffer);
|
||||||
}
|
}
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
@ -708,8 +712,8 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
// DPRINT ("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n",
|
DPRINT ("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n",
|
||||||
// DeviceExt, CurrentCluster);
|
DeviceExt, CurrentCluster);
|
||||||
|
|
||||||
if (!Extend)
|
if (!Extend)
|
||||||
{
|
{
|
||||||
|
@ -719,7 +723,7 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
|
ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
|
||||||
}
|
}
|
||||||
|
CHECKPOINT;
|
||||||
/*
|
/*
|
||||||
* If the file hasn't any clusters allocated then we need special
|
* If the file hasn't any clusters allocated then we need special
|
||||||
* handling
|
* handling
|
||||||
|
@ -728,16 +732,18 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
ULONG NewCluster;
|
ULONG NewCluster;
|
||||||
|
|
||||||
if (DeviceExt->FatType == FAT16)
|
if (DeviceExt->FatInfo.FatType == FAT16)
|
||||||
{
|
{
|
||||||
|
CHECKPOINT;
|
||||||
Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster);
|
Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster);
|
||||||
|
CHECKPOINT;
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (DeviceExt->FatType == FAT32)
|
else if (DeviceExt->FatInfo.FatType == FAT32)
|
||||||
{
|
{
|
||||||
Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster);
|
Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -767,11 +773,11 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DeviceExt->FatType == FAT16)
|
if (DeviceExt->FatInfo.FatType == FAT16)
|
||||||
{
|
{
|
||||||
Status = Fat16GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
|
Status = Fat16GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
|
||||||
}
|
}
|
||||||
else if (DeviceExt->FatType == FAT32)
|
else if (DeviceExt->FatInfo.FatType == FAT32)
|
||||||
{
|
{
|
||||||
Status = Fat32GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
|
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 */
|
/* We are after last existing cluster, we must add one to file */
|
||||||
/* Firstly, find the next available open allocation unit */
|
/* Firstly, find the next available open allocation unit */
|
||||||
if (DeviceExt->FatType == FAT16)
|
if (DeviceExt->FatInfo.FatType == FAT16)
|
||||||
{
|
{
|
||||||
Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster);
|
Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -794,7 +800,7 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (DeviceExt->FatType == FAT32)
|
else if (DeviceExt->FatInfo.FatType == FAT32)
|
||||||
{
|
{
|
||||||
Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster);
|
Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -839,7 +845,7 @@ GetNextSector(PDEVICE_EXTENSION DeviceExt,
|
||||||
DPRINT("GetNextSector(DeviceExt %x, CurrentSector %x)\n",
|
DPRINT("GetNextSector(DeviceExt %x, CurrentSector %x)\n",
|
||||||
DeviceExt,
|
DeviceExt,
|
||||||
CurrentSector);
|
CurrentSector);
|
||||||
if (CurrentSector<DeviceExt->dataStart || ((CurrentSector - DeviceExt->dataStart + 1) % DeviceExt -> Boot -> SectorsPerCluster))
|
if (CurrentSector<DeviceExt->FatInfo.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 */
|
/* Basically, if the next sequential sector would be on a cluster border, then we'll need to check in the FAT */
|
||||||
{
|
{
|
||||||
(*NextSector)=CurrentSector+1;
|
(*NextSector)=CurrentSector+1;
|
||||||
|
@ -847,7 +853,7 @@ GetNextSector(PDEVICE_EXTENSION DeviceExt,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CurrentSector = (CurrentSector - DeviceExt->dataStart) / DeviceExt -> Boot -> SectorsPerCluster + 2;
|
CurrentSector = (CurrentSector - DeviceExt->FatInfo.dataStart) / DeviceExt->FatInfo.SectorsPerCluster + 2;
|
||||||
|
|
||||||
Status = GetNextCluster(DeviceExt, CurrentSector, NextSector, Extend);
|
Status = GetNextCluster(DeviceExt, CurrentSector, NextSector, Extend);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
|
|
@ -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
|
* FILE: fcb.c
|
||||||
|
@ -156,7 +156,6 @@ vfatFCBInitializeCache (PVCB vcb, PVFATFCB fcb)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
PFILE_OBJECT fileObject;
|
PFILE_OBJECT fileObject;
|
||||||
ULONG bytesPerCluster;
|
|
||||||
ULONG fileCacheQuantum;
|
ULONG fileCacheQuantum;
|
||||||
PVFATCCB newCCB;
|
PVFATCCB newCCB;
|
||||||
|
|
||||||
|
@ -180,9 +179,8 @@ vfatFCBInitializeCache (PVCB vcb, PVFATFCB fcb)
|
||||||
fcb->pDevExt = vcb;
|
fcb->pDevExt = vcb;
|
||||||
|
|
||||||
|
|
||||||
bytesPerCluster = vcb->Boot->SectorsPerCluster * BLOCKSIZE;
|
fileCacheQuantum = (vcb->FatInfo.BytesPerCluster >= PAGESIZE) ?
|
||||||
fileCacheQuantum = (bytesPerCluster >= PAGESIZE) ?
|
vcb->FatInfo.BytesPerCluster : PAGESIZE;
|
||||||
bytesPerCluster : PAGESIZE;
|
|
||||||
|
|
||||||
status = CcRosInitializeFileCache (fileObject,
|
status = CcRosInitializeFileCache (fileObject,
|
||||||
&fcb->RFCB.Bcb,
|
&fcb->RFCB.Bcb,
|
||||||
|
@ -208,25 +206,25 @@ vfatMakeRootFCB(PDEVICE_EXTENSION pVCB)
|
||||||
|
|
||||||
FCB = vfatNewFCB(L"\\");
|
FCB = vfatNewFCB(L"\\");
|
||||||
memset(FCB->entry.Filename, ' ', 11);
|
memset(FCB->entry.Filename, ' ', 11);
|
||||||
FCB->entry.FileSize = pVCB->rootDirectorySectors * BLOCKSIZE;
|
FCB->entry.FileSize = pVCB->FatInfo.rootDirectorySectors * BLOCKSIZE;
|
||||||
FCB->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
|
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.FirstCluster = FirstCluster & 0xffff;
|
||||||
FCB->entry.FirstClusterHigh = FirstCluster >> 16;
|
FCB->entry.FirstClusterHigh = FirstCluster >> 16;
|
||||||
CurrentCluster = FirstCluster;
|
CurrentCluster = FirstCluster;
|
||||||
|
|
||||||
while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
|
while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
Size += pVCB->BytesPerCluster;
|
Size += pVCB->FatInfo.BytesPerCluster;
|
||||||
Status = NextCluster (pVCB, NULL, FirstCluster, &CurrentCluster, FALSE);
|
Status = NextCluster (pVCB, NULL, FirstCluster, &CurrentCluster, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FCB->entry.FirstCluster = 1;
|
FCB->entry.FirstCluster = 1;
|
||||||
Size = pVCB->rootDirectorySectors * BLOCKSIZE;
|
Size = pVCB->FatInfo.rootDirectorySectors * BLOCKSIZE;
|
||||||
}
|
}
|
||||||
FCB->RefCount = 1;
|
FCB->RefCount = 1;
|
||||||
FCB->dirIndex = 0;
|
FCB->dirIndex = 0;
|
||||||
|
@ -298,14 +296,14 @@ vfatMakeFCBFromDirEntry(PVCB vcb,
|
||||||
FirstCluster = vfatDirEntryGetFirstCluster (vcb, &rcFCB->entry);
|
FirstCluster = vfatDirEntryGetFirstCluster (vcb, &rcFCB->entry);
|
||||||
if (FirstCluster == 1)
|
if (FirstCluster == 1)
|
||||||
{
|
{
|
||||||
Size = vcb->rootDirectorySectors * BLOCKSIZE;
|
Size = vcb->FatInfo.rootDirectorySectors * BLOCKSIZE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CurrentCluster = FirstCluster;
|
CurrentCluster = FirstCluster;
|
||||||
while (CurrentCluster != 0xffffffff)
|
while (CurrentCluster != 0xffffffff)
|
||||||
{
|
{
|
||||||
Size += vcb->BytesPerCluster;
|
Size += vcb->FatInfo.BytesPerCluster;
|
||||||
Status = NextCluster (vcb, NULL, FirstCluster, &CurrentCluster, FALSE);
|
Status = NextCluster (vcb, NULL, FirstCluster, &CurrentCluster, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -317,7 +315,7 @@ vfatMakeFCBFromDirEntry(PVCB vcb,
|
||||||
rcFCB->dirIndex = dirIndex;
|
rcFCB->dirIndex = dirIndex;
|
||||||
rcFCB->RFCB.FileSize.QuadPart = Size;
|
rcFCB->RFCB.FileSize.QuadPart = Size;
|
||||||
rcFCB->RFCB.ValidDataLength.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);
|
// DPRINT1("%S %d %d\n", longName, Size, (ULONG)rcFCB->RFCB.AllocationSize.QuadPart);
|
||||||
vfatFCBInitializeCache (vcb, rcFCB);
|
vfatFCBInitializeCache (vcb, rcFCB);
|
||||||
rcFCB->RefCount++;
|
rcFCB->RefCount++;
|
||||||
|
@ -353,11 +351,10 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
|
||||||
|
|
||||||
if (!(fcb->Flags & FCB_CACHE_INITIALIZED))
|
if (!(fcb->Flags & FCB_CACHE_INITIALIZED))
|
||||||
{
|
{
|
||||||
ULONG bytesPerCluster;
|
|
||||||
ULONG fileCacheQuantum;
|
ULONG fileCacheQuantum;
|
||||||
|
|
||||||
bytesPerCluster = vcb->Boot->SectorsPerCluster * BLOCKSIZE;
|
fileCacheQuantum = (vcb->FatInfo.BytesPerCluster >= PAGESIZE) ?
|
||||||
fileCacheQuantum = (bytesPerCluster >= PAGESIZE) ? bytesPerCluster : PAGESIZE;
|
vcb->FatInfo.BytesPerCluster : PAGESIZE;
|
||||||
status = CcRosInitializeFileCache (fileObject,
|
status = CcRosInitializeFileCache (fileObject,
|
||||||
&fcb->RFCB.Bcb,
|
&fcb->RFCB.Bcb,
|
||||||
fileCacheQuantum);
|
fileCacheQuantum);
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -37,7 +37,7 @@ VfatGetStandardInformation(PVFATFCB FCB,
|
||||||
DeviceExtension = DeviceObject->DeviceExtension;
|
DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
/* PRECONDITION */
|
/* PRECONDITION */
|
||||||
assert (DeviceExtension != NULL);
|
assert (DeviceExtension != NULL);
|
||||||
assert (DeviceExtension->BytesPerCluster != 0);
|
assert (DeviceExtension->FatInfo.BytesPerCluster != 0);
|
||||||
assert (StandardInfo != NULL);
|
assert (StandardInfo != NULL);
|
||||||
assert (FCB != NULL);
|
assert (FCB != NULL);
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
|
||||||
DPRINT ("FsdSetDispositionInformation()\n");
|
DPRINT ("FsdSetDispositionInformation()\n");
|
||||||
|
|
||||||
assert (DeviceExt != NULL);
|
assert (DeviceExt != NULL);
|
||||||
assert (DeviceExt->BytesPerCluster != 0);
|
assert (DeviceExt->FatInfo.BytesPerCluster != 0);
|
||||||
assert (FCB != NULL);
|
assert (FCB != NULL);
|
||||||
|
|
||||||
if (!wcscmp(FCB->PathName, L"\\") || !wcscmp(FCB->ObjectName, L"..")
|
if (!wcscmp(FCB->PathName, L"\\") || !wcscmp(FCB->ObjectName, L"..")
|
||||||
|
|
378
reactos/drivers/fs/vfat/fsctl.c
Normal file
378
reactos/drivers/fs/vfat/fsctl.c
Normal file
|
@ -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 <ddk/ntddk.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -35,355 +35,13 @@
|
||||||
|
|
||||||
/* GLOBALS *****************************************************************/
|
/* GLOBALS *****************************************************************/
|
||||||
|
|
||||||
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \
|
|
||||||
(pDeviceExt)->BytesPerCluster : PAGESIZE)
|
|
||||||
|
|
||||||
static PDRIVER_OBJECT VfatDriverObject;
|
PVFAT_GLOBAL_DATA VfatGlobalData;
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* 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
|
NTSTATUS STDCALL
|
||||||
DriverEntry(PDRIVER_OBJECT _DriverObject,
|
DriverEntry(PDRIVER_OBJECT DriverObject,
|
||||||
PUNICODE_STRING RegistryPath)
|
PUNICODE_STRING RegistryPath)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Called by the system to initalize the driver
|
* FUNCTION: Called by the system to initalize the driver
|
||||||
|
@ -399,14 +57,12 @@ DriverEntry(PDRIVER_OBJECT _DriverObject,
|
||||||
|
|
||||||
DPRINT("VFAT 0.0.6\n");
|
DPRINT("VFAT 0.0.6\n");
|
||||||
|
|
||||||
VfatDriverObject = _DriverObject;
|
|
||||||
|
|
||||||
RtlInitUnicodeString(&DeviceName,
|
RtlInitUnicodeString(&DeviceName,
|
||||||
L"\\Device\\Vfat");
|
L"\\Device\\Vfat");
|
||||||
Status = IoCreateDevice(VfatDriverObject,
|
Status = IoCreateDevice(DriverObject,
|
||||||
0,
|
sizeof(VFAT_GLOBAL_DATA),
|
||||||
&DeviceName,
|
&DeviceName,
|
||||||
FILE_DEVICE_FILE_SYSTEM,
|
FILE_DEVICE_DISK_FILE_SYSTEM,
|
||||||
0,
|
0,
|
||||||
FALSE,
|
FALSE,
|
||||||
&DeviceObject);
|
&DeviceObject);
|
||||||
|
@ -414,32 +70,30 @@ DriverEntry(PDRIVER_OBJECT _DriverObject,
|
||||||
{
|
{
|
||||||
return (Status);
|
return (Status);
|
||||||
}
|
}
|
||||||
|
VfatGlobalData = DeviceObject->DeviceExtension;
|
||||||
|
RtlZeroMemory (VfatGlobalData, sizeof(VFAT_GLOBAL_DATA));
|
||||||
|
VfatGlobalData->DriverObject = DriverObject;
|
||||||
|
VfatGlobalData->DeviceObject = DeviceObject;
|
||||||
|
|
||||||
DeviceObject->Flags = DO_DIRECT_IO;
|
DeviceObject->Flags = DO_DIRECT_IO;
|
||||||
VfatDriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatBuildRequest;
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatBuildRequest;
|
||||||
VfatDriverObject->MajorFunction[IRP_MJ_CREATE] = VfatBuildRequest;
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = VfatBuildRequest;
|
||||||
VfatDriverObject->MajorFunction[IRP_MJ_READ] = VfatBuildRequest;
|
DriverObject->MajorFunction[IRP_MJ_READ] = VfatBuildRequest;
|
||||||
VfatDriverObject->MajorFunction[IRP_MJ_WRITE] = VfatBuildRequest;
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = VfatBuildRequest;
|
||||||
VfatDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
|
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = VfatBuildRequest;
|
||||||
VfatBuildRequest;
|
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = VfatBuildRequest;
|
||||||
VfatDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
|
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = VfatBuildRequest;
|
||||||
VfatBuildRequest;
|
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = VfatBuildRequest;
|
||||||
VfatDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
|
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = VfatBuildRequest;
|
||||||
VfatBuildRequest;
|
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = VfatBuildRequest;
|
||||||
VfatDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
|
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = VfatShutdown;
|
||||||
VfatBuildRequest;
|
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = 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;
|
|
||||||
|
|
||||||
VfatDriverObject->DriverUnload = NULL;
|
DriverObject->DriverUnload = NULL;
|
||||||
|
|
||||||
IoRegisterFileSystem(DeviceObject);
|
IoRegisterFileSystem(DeviceObject);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
||||||
|
|
|
@ -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 = ../../..
|
PATH_TO_TOP = ../../..
|
||||||
|
|
||||||
|
@ -22,7 +22,8 @@ TARGET_OBJECTS = \
|
||||||
shutdown.o \
|
shutdown.o \
|
||||||
string.o \
|
string.o \
|
||||||
volume.o \
|
volume.o \
|
||||||
misc.o
|
misc.o \
|
||||||
|
fsctl.o
|
||||||
|
|
||||||
DEP_OBJECTS = $(TARGET_OBJECTS)
|
DEP_OBJECTS = $(TARGET_OBJECTS)
|
||||||
|
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -121,7 +121,7 @@ NextCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
}
|
}
|
||||||
if (FirstCluster == 1)
|
if (FirstCluster == 1)
|
||||||
{
|
{
|
||||||
(*CurrentCluster) += DeviceExt->Boot->SectorsPerCluster;
|
(*CurrentCluster) += DeviceExt->FatInfo.SectorsPerCluster;
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -176,7 +176,7 @@ OffsetToCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
if (Fcb != NULL && Fcb->Flags & FCB_IS_PAGE_FILE)
|
if (Fcb != NULL && Fcb->Flags & FCB_IS_PAGE_FILE)
|
||||||
{
|
{
|
||||||
ULONG NCluster;
|
ULONG NCluster;
|
||||||
ULONG Offset = FileOffset / DeviceExt->BytesPerCluster;
|
ULONG Offset = FileOffset / DeviceExt->FatInfo.BytesPerCluster;
|
||||||
PULONG FatChain;
|
PULONG FatChain;
|
||||||
int i;
|
int i;
|
||||||
if (Fcb->FatChainSize == 0)
|
if (Fcb->FatChainSize == 0)
|
||||||
|
@ -238,14 +238,14 @@ OffsetToCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
if (FirstCluster == 1)
|
if (FirstCluster == 1)
|
||||||
{
|
{
|
||||||
/* root of FAT16 or FAT12 */
|
/* root of FAT16 or FAT12 */
|
||||||
*Cluster = DeviceExt->rootStart + FileOffset
|
*Cluster = DeviceExt->FatInfo.rootStart + FileOffset
|
||||||
/ (DeviceExt->BytesPerCluster) * DeviceExt->Boot->SectorsPerCluster;
|
/ (DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.SectorsPerCluster;
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CurrentCluster = FirstCluster;
|
CurrentCluster = FirstCluster;
|
||||||
for (i = 0; i < FileOffset / DeviceExt->BytesPerCluster; i++)
|
for (i = 0; i < FileOffset / DeviceExt->FatInfo.BytesPerCluster; i++)
|
||||||
{
|
{
|
||||||
Status = GetNextCluster (DeviceExt, CurrentCluster, &CurrentCluster,
|
Status = GetNextCluster (DeviceExt, CurrentCluster, &CurrentCluster,
|
||||||
Extend);
|
Extend);
|
||||||
|
@ -271,14 +271,14 @@ VfatReadCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
PVOID BaseAddress = NULL;
|
PVOID BaseAddress = NULL;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
if (InternalLength == DeviceExt->BytesPerCluster)
|
if (InternalLength == DeviceExt->FatInfo.BytesPerCluster)
|
||||||
{
|
{
|
||||||
Status = VfatRawReadCluster(DeviceExt, FirstCluster,
|
Status = VfatRawReadCluster(DeviceExt, FirstCluster,
|
||||||
Destination, *CurrentCluster, 1);
|
Destination, *CurrentCluster, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BaseAddress = ExAllocatePool(NonPagedPool, DeviceExt->BytesPerCluster);
|
BaseAddress = ExAllocatePool(NonPagedPool, DeviceExt->FatInfo.BytesPerCluster);
|
||||||
if (BaseAddress == NULL)
|
if (BaseAddress == NULL)
|
||||||
{
|
{
|
||||||
return(STATUS_NO_MEMORY);
|
return(STATUS_NO_MEMORY);
|
||||||
|
@ -318,7 +318,7 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
|
|
||||||
/* PRECONDITION */
|
/* PRECONDITION */
|
||||||
assert (DeviceExt != NULL);
|
assert (DeviceExt != NULL);
|
||||||
assert (DeviceExt->BytesPerCluster != 0);
|
assert (DeviceExt->FatInfo.BytesPerCluster != 0);
|
||||||
assert (FileObject != NULL);
|
assert (FileObject != NULL);
|
||||||
assert (FileObject->FsContext2 != NULL);
|
assert (FileObject->FsContext2 != NULL);
|
||||||
|
|
||||||
|
@ -351,7 +351,7 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = VfatReadSectors(DeviceExt->StorageDevice,
|
Status = VfatReadSectors(DeviceExt->StorageDevice,
|
||||||
DeviceExt->FATStart + ReadOffset / BLOCKSIZE,
|
DeviceExt->FatInfo.FATStart + ReadOffset / BLOCKSIZE,
|
||||||
Length / BLOCKSIZE, Buffer);
|
Length / BLOCKSIZE, Buffer);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -388,9 +388,9 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
if (FirstCluster == 1)
|
if (FirstCluster == 1)
|
||||||
{
|
{
|
||||||
/* root directory of FAT12 or FAT16 */
|
/* 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,
|
Status = OffsetToCluster(DeviceExt,
|
||||||
Fcb,
|
Fcb,
|
||||||
FirstCluster,
|
FirstCluster,
|
||||||
ROUND_DOWN(ReadOffset, DeviceExt->BytesPerCluster),
|
ROUND_DOWN(ReadOffset, DeviceExt->FatInfo.BytesPerCluster),
|
||||||
&CurrentCluster,
|
&CurrentCluster,
|
||||||
FALSE);
|
FALSE);
|
||||||
if (!NT_SUCCESS(Status))
|
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
|
* If the read doesn't begin on a chunk boundary then we need special
|
||||||
* handling
|
* handling
|
||||||
*/
|
*/
|
||||||
if ((ReadOffset % DeviceExt->BytesPerCluster) != 0 )
|
if ((ReadOffset % DeviceExt->FatInfo.BytesPerCluster) != 0 )
|
||||||
{
|
{
|
||||||
TempLength = min (Length, DeviceExt->BytesPerCluster -
|
TempLength = min (Length, DeviceExt->FatInfo.BytesPerCluster -
|
||||||
(ReadOffset % DeviceExt->BytesPerCluster));
|
(ReadOffset % DeviceExt->FatInfo.BytesPerCluster));
|
||||||
Ccb->LastCluster = CurrentCluster;
|
Ccb->LastCluster = CurrentCluster;
|
||||||
Ccb->LastOffset = ROUND_DOWN(ReadOffset, DeviceExt->BytesPerCluster);
|
Ccb->LastOffset = ROUND_DOWN(ReadOffset, DeviceExt->FatInfo.BytesPerCluster);
|
||||||
Status = VfatReadCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster,
|
Status = VfatReadCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster,
|
||||||
Buffer,
|
Buffer,
|
||||||
ReadOffset % DeviceExt->BytesPerCluster,
|
ReadOffset % DeviceExt->FatInfo.BytesPerCluster,
|
||||||
TempLength);
|
TempLength);
|
||||||
if (NT_SUCCESS(Status))
|
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))
|
CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
StartCluster = CurrentCluster;
|
StartCluster = CurrentCluster;
|
||||||
|
@ -453,25 +453,25 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ClusterCount++;
|
ClusterCount++;
|
||||||
BytesDone += DeviceExt->BytesPerCluster;
|
BytesDone += DeviceExt->FatInfo.BytesPerCluster;
|
||||||
Status = NextCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster,
|
Status = NextCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster,
|
||||||
FALSE);
|
FALSE);
|
||||||
}
|
}
|
||||||
while (StartCluster + ClusterCount == CurrentCluster &&
|
while (StartCluster + ClusterCount == CurrentCluster &&
|
||||||
NT_SUCCESS(Status) &&
|
NT_SUCCESS(Status) &&
|
||||||
Length - BytesDone >= DeviceExt->BytesPerCluster);
|
Length - BytesDone >= DeviceExt->FatInfo.BytesPerCluster);
|
||||||
|
|
||||||
DPRINT("Count %d, Start %x Next %x\n", ClusterCount, StartCluster,
|
DPRINT("Count %d, Start %x Next %x\n", ClusterCount, StartCluster,
|
||||||
CurrentCluster);
|
CurrentCluster);
|
||||||
Ccb->LastCluster = StartCluster + (ClusterCount - 1);
|
Ccb->LastCluster = StartCluster + (ClusterCount - 1);
|
||||||
Ccb->LastOffset = ReadOffset +
|
Ccb->LastOffset = ReadOffset +
|
||||||
(ClusterCount - 1) * DeviceExt->BytesPerCluster;
|
(ClusterCount - 1) * DeviceExt->FatInfo.BytesPerCluster;
|
||||||
|
|
||||||
Status = VfatRawReadCluster(DeviceExt, FirstCluster, Buffer,
|
Status = VfatRawReadCluster(DeviceExt, FirstCluster, Buffer,
|
||||||
StartCluster, ClusterCount);
|
StartCluster, ClusterCount);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
ClusterCount *= DeviceExt->BytesPerCluster;
|
ClusterCount *= DeviceExt->FatInfo.BytesPerCluster;
|
||||||
(*LengthRead) = (*LengthRead) + ClusterCount;
|
(*LengthRead) = (*LengthRead) + ClusterCount;
|
||||||
Buffer += ClusterCount;
|
Buffer += ClusterCount;
|
||||||
Length -= ClusterCount;
|
Length -= ClusterCount;
|
||||||
|
@ -485,7 +485,7 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
if (Length > 0 && CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
|
if (Length > 0 && CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
Ccb->LastCluster = CurrentCluster;
|
Ccb->LastCluster = CurrentCluster;
|
||||||
Ccb->LastOffset = ReadOffset + DeviceExt->BytesPerCluster;
|
Ccb->LastOffset = ReadOffset + DeviceExt->FatInfo.BytesPerCluster;
|
||||||
|
|
||||||
Status = VfatReadCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster,
|
Status = VfatReadCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster,
|
||||||
Buffer, 0, Length);
|
Buffer, 0, Length);
|
||||||
|
@ -500,19 +500,19 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
VfatWriteCluster(PDEVICE_EXTENSION DeviceExt,
|
VfatWriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
PVFATFCB Fcb,
|
PVFATFCB Fcb,
|
||||||
ULONG StartOffset,
|
ULONG StartOffset,
|
||||||
ULONG FirstCluster,
|
ULONG FirstCluster,
|
||||||
PULONG CurrentCluster,
|
PULONG CurrentCluster,
|
||||||
PVOID Source,
|
PVOID Source,
|
||||||
ULONG InternalOffset,
|
ULONG InternalOffset,
|
||||||
ULONG InternalLength)
|
ULONG InternalLength)
|
||||||
{
|
{
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
NTSTATUS Status;
|
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)
|
if (BaseAddress == NULL)
|
||||||
{
|
{
|
||||||
return(STATUS_NO_MEMORY);
|
return(STATUS_NO_MEMORY);
|
||||||
|
@ -520,7 +520,7 @@ VfatWriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
BaseAddress = Source;
|
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
|
* If the data in the cache isn't valid or we are bypassing the
|
||||||
|
@ -531,7 +531,7 @@ VfatWriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
*CurrentCluster, 1);
|
*CurrentCluster, 1);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
if (InternalLength != DeviceExt->BytesPerCluster)
|
if (InternalLength != DeviceExt->FatInfo.BytesPerCluster)
|
||||||
{
|
{
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
|
@ -545,7 +545,7 @@ VfatWriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
DPRINT("Writing 0x%x\n", *CurrentCluster);
|
DPRINT("Writing 0x%x\n", *CurrentCluster);
|
||||||
Status = VfatRawWriteCluster(DeviceExt, FirstCluster, BaseAddress,
|
Status = VfatRawWriteCluster(DeviceExt, FirstCluster, BaseAddress,
|
||||||
*CurrentCluster, 1);
|
*CurrentCluster, 1);
|
||||||
if (InternalLength != DeviceExt->BytesPerCluster)
|
if (InternalLength != DeviceExt->FatInfo.BytesPerCluster)
|
||||||
{
|
{
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
|
@ -611,10 +611,10 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
Length = (ULONG)Fcb->RFCB.FileSize.QuadPart - WriteOffset;
|
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,
|
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);
|
Length / BLOCKSIZE, Buffer);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -639,7 +639,7 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
if (FirstCluster == 1)
|
if (FirstCluster == 1)
|
||||||
{
|
{
|
||||||
// root directory of FAT12 od FAT16
|
// 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");
|
DPRINT("Writing over the end of the root directory on FAT12/16\n");
|
||||||
return STATUS_END_OF_FILE;
|
return STATUS_END_OF_FILE;
|
||||||
|
@ -664,7 +664,7 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
Status = OffsetToCluster(DeviceExt,
|
Status = OffsetToCluster(DeviceExt,
|
||||||
Fcb,
|
Fcb,
|
||||||
FirstCluster,
|
FirstCluster,
|
||||||
ROUND_DOWN(WriteOffset, DeviceExt->BytesPerCluster),
|
ROUND_DOWN(WriteOffset, DeviceExt->FatInfo.BytesPerCluster),
|
||||||
&CurrentCluster,
|
&CurrentCluster,
|
||||||
FALSE);
|
FALSE);
|
||||||
if (!NT_SUCCESS(Status) || CurrentCluster == 0xffffffff)
|
if (!NT_SUCCESS(Status) || CurrentCluster == 0xffffffff)
|
||||||
|
@ -673,23 +673,24 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
pCcb->LastCluster = CurrentCluster;
|
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
|
* If the offset in the cluster doesn't fall on the cluster boundary
|
||||||
* then we have to write only from the specified offset
|
* then we have to write only from the specified offset
|
||||||
*/
|
*/
|
||||||
Status = STATUS_SUCCESS;
|
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,
|
Status = VfatWriteCluster(DeviceExt,
|
||||||
Fcb,
|
Fcb,
|
||||||
ROUND_DOWN(WriteOffset, DeviceExt->BytesPerCluster),
|
ROUND_DOWN(WriteOffset, DeviceExt->FatInfo.BytesPerCluster),
|
||||||
FirstCluster,
|
FirstCluster,
|
||||||
&CurrentCluster,
|
&CurrentCluster,
|
||||||
Buffer,
|
Buffer,
|
||||||
WriteOffset % DeviceExt->BytesPerCluster,
|
WriteOffset % DeviceExt->FatInfo.BytesPerCluster,
|
||||||
TempLength);
|
TempLength);
|
||||||
if (NT_SUCCESS(Status))
|
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;
|
StartCluster = CurrentCluster;
|
||||||
Count = 0;
|
Count = 0;
|
||||||
|
@ -710,15 +712,15 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
Status = NextCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster, FALSE);
|
Status = NextCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster, FALSE);
|
||||||
}
|
}
|
||||||
while (StartCluster + Count == CurrentCluster && NT_SUCCESS(Status) &&
|
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->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);
|
Status = VfatRawWriteCluster(DeviceExt, FirstCluster, Buffer, StartCluster, Count);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
Count *= DeviceExt->BytesPerCluster;
|
Count *= DeviceExt->FatInfo.BytesPerCluster;
|
||||||
Buffer += Count;
|
Buffer += Count;
|
||||||
Length -= Count;
|
Length -= Count;
|
||||||
WriteOffset += Count;
|
WriteOffset += Count;
|
||||||
|
@ -796,7 +798,7 @@ NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, PFILE_OBJECT pFileObject
|
||||||
pFcb = ((PVFATCCB) (pFileObject->FsContext2))->pFcb;
|
pFcb = ((PVFATCCB) (pFileObject->FsContext2))->pFcb;
|
||||||
|
|
||||||
DPRINT ("New Size %d, AllocationSize %d, BytesPerCluster %d\n", NewSize,
|
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);
|
FirstCluster = CurrentCluster = vfatDirEntryGetFirstCluster (pDeviceExt, &pFcb->entry);
|
||||||
|
|
||||||
|
@ -817,7 +819,7 @@ NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, PFILE_OBJECT pFileObject
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Status = OffsetToCluster(pDeviceExt, pFcb, FirstCluster,
|
Status = OffsetToCluster(pDeviceExt, pFcb, FirstCluster,
|
||||||
pFcb->RFCB.AllocationSize.QuadPart - pDeviceExt->BytesPerCluster,
|
pFcb->RFCB.AllocationSize.QuadPart - pDeviceExt->FatInfo.BytesPerCluster,
|
||||||
&CurrentCluster, FALSE);
|
&CurrentCluster, FALSE);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -839,7 +841,7 @@ NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, PFILE_OBJECT pFileObject
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = OffsetToCluster(pDeviceExt, pFcb, FirstCluster,
|
Status = OffsetToCluster(pDeviceExt, pFcb, FirstCluster,
|
||||||
ROUND_DOWN(NewSize-1, pDeviceExt->BytesPerCluster),
|
ROUND_DOWN(NewSize-1, pDeviceExt->FatInfo.BytesPerCluster),
|
||||||
&NewCluster, TRUE);
|
&NewCluster, TRUE);
|
||||||
if (!NT_SUCCESS(Status) || NewCluster == 0xffffffff)
|
if (!NT_SUCCESS(Status) || NewCluster == 0xffffffff)
|
||||||
{
|
{
|
||||||
|
@ -864,10 +866,10 @@ NTSTATUS vfatExtendSpace (PDEVICE_EXTENSION pDeviceExt, PFILE_OBJECT pFileObject
|
||||||
if (pFcb->RFCB.AllocationSize.QuadPart == 0)
|
if (pFcb->RFCB.AllocationSize.QuadPart == 0)
|
||||||
{
|
{
|
||||||
pFcb->entry.FirstCluster = FirstCluster;
|
pFcb->entry.FirstCluster = FirstCluster;
|
||||||
if(pDeviceExt->FatType == FAT32)
|
if(pDeviceExt->FatInfo.FatType == FAT32)
|
||||||
pFcb->entry.FirstClusterHigh = FirstCluster >> 16;
|
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)
|
if (pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
{
|
{
|
||||||
pFcb->RFCB.FileSize.QuadPart = pFcb->RFCB.AllocationSize.QuadPart;
|
pFcb->RFCB.FileSize.QuadPart = pFcb->RFCB.AllocationSize.QuadPart;
|
||||||
|
|
|
@ -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 <ddk/ntifs.h>
|
#include <ddk/ntifs.h>
|
||||||
|
|
||||||
|
@ -61,12 +61,13 @@ struct _BootBackupSector
|
||||||
|
|
||||||
typedef struct _BootSector BootSector;
|
typedef struct _BootSector BootSector;
|
||||||
|
|
||||||
struct _FATDirEntry {
|
struct _FATDirEntry
|
||||||
|
{
|
||||||
unsigned char Filename[8], Ext[3], Attrib, Res[2];
|
unsigned char Filename[8], Ext[3], Attrib, Res[2];
|
||||||
unsigned short CreationTime,CreationDate,AccessDate;
|
unsigned short CreationTime,CreationDate,AccessDate;
|
||||||
unsigned short FirstClusterHigh;// higher
|
unsigned short FirstClusterHigh; // higher
|
||||||
unsigned short UpdateTime;//time create/update
|
unsigned short UpdateTime; //time create/update
|
||||||
unsigned short UpdateDate;//date create/update
|
unsigned short UpdateDate; //date create/update
|
||||||
unsigned short FirstCluster;
|
unsigned short FirstCluster;
|
||||||
unsigned long FileSize;
|
unsigned long FileSize;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
@ -76,13 +77,13 @@ typedef struct _FATDirEntry FATDirEntry, FAT_DIR_ENTRY, *PFAT_DIR_ENTRY;
|
||||||
struct _slot
|
struct _slot
|
||||||
{
|
{
|
||||||
unsigned char id; // sequence number for 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 attr; // attribute byte
|
||||||
unsigned char reserved; // always 0
|
unsigned char reserved; // always 0
|
||||||
unsigned char alias_checksum; // checksum for 8.3 alias
|
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
|
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));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,6 +95,27 @@ typedef struct _slot slot;
|
||||||
#define FAT12 (2)
|
#define FAT12 (2)
|
||||||
#define FAT32 (3)
|
#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
|
typedef struct
|
||||||
{
|
{
|
||||||
ERESOURCE DirResource;
|
ERESOURCE DirResource;
|
||||||
|
@ -104,15 +126,23 @@ typedef struct
|
||||||
|
|
||||||
PDEVICE_OBJECT StorageDevice;
|
PDEVICE_OBJECT StorageDevice;
|
||||||
PFILE_OBJECT FATFileObject;
|
PFILE_OBJECT FATFileObject;
|
||||||
BootSector *Boot;
|
FATINFO FatInfo;
|
||||||
int rootDirectorySectors, FATStart, rootStart, dataStart;
|
|
||||||
int BytesPerSector;
|
|
||||||
int FATEntriesPerSector, FATUnit;
|
|
||||||
ULONG BytesPerCluster;
|
|
||||||
ULONG FatType;
|
|
||||||
ULONG LastAvailableCluster;
|
ULONG LastAvailableCluster;
|
||||||
ULONG NumberOfClusters;
|
ULONG AvailableClusters;
|
||||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB;
|
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_CACHE_INITIALIZED 0x0001
|
||||||
#define FCB_DELETE_PENDING 0x0002
|
#define FCB_DELETE_PENDING 0x0002
|
||||||
|
@ -137,11 +167,13 @@ typedef struct _VFATFCB
|
||||||
ULONG dirIndex;
|
ULONG dirIndex;
|
||||||
ERESOURCE PagingIoResource;
|
ERESOURCE PagingIoResource;
|
||||||
ERESOURCE MainResource;
|
ERESOURCE MainResource;
|
||||||
|
ULONG TimerCount;
|
||||||
|
|
||||||
/* Structure members used only for paging files. */
|
/* Structure members used only for paging files. */
|
||||||
ULONG FatChainSize;
|
ULONG FatChainSize;
|
||||||
PULONG FatChain;
|
PULONG FatChain;
|
||||||
} VFATFCB, *PVFATFCB;
|
}
|
||||||
|
VFATFCB, *PVFATFCB;
|
||||||
|
|
||||||
typedef struct _VFATCCB
|
typedef struct _VFATCCB
|
||||||
{
|
{
|
||||||
|
@ -156,7 +188,8 @@ typedef struct _VFATCCB
|
||||||
ULONG LastCluster;
|
ULONG LastCluster;
|
||||||
ULONG LastOffset;
|
ULONG LastOffset;
|
||||||
|
|
||||||
} VFATCCB, *PVFATCCB;
|
}
|
||||||
|
VFATCCB, *PVFATCCB;
|
||||||
|
|
||||||
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
#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 Second:5;
|
||||||
WORD Minute:6;
|
WORD Minute:6;
|
||||||
WORD Hour:5;
|
WORD Hour:5;
|
||||||
} DOSTIME, *PDOSTIME;
|
}
|
||||||
|
DOSTIME, *PDOSTIME;
|
||||||
|
|
||||||
typedef struct __DOSDATE
|
typedef struct __DOSDATE
|
||||||
{
|
{
|
||||||
WORD Day:5;
|
WORD Day:5;
|
||||||
WORD Month:4;
|
WORD Month:4;
|
||||||
WORD Year:5;
|
WORD Year:5;
|
||||||
} DOSDATE, *PDOSDATE;
|
}
|
||||||
|
DOSDATE, *PDOSDATE;
|
||||||
|
|
||||||
#define IRPCONTEXT_CANWAIT 0x0001
|
#define IRPCONTEXT_CANWAIT 0x0001
|
||||||
|
|
||||||
|
@ -194,216 +229,299 @@ typedef struct
|
||||||
}
|
}
|
||||||
VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT;
|
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 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
|
BOOL FsdFileTimeToDosDateTime (TIME *FileTime,
|
||||||
NextCluster(PDEVICE_EXTENSION DeviceExt,
|
WORD *pwDosDate,
|
||||||
PVFATFCB Fcb,
|
WORD *pwDosTime);
|
||||||
ULONG FirstCluster,
|
|
||||||
PULONG CurrentCluster,
|
|
||||||
BOOLEAN Extend);
|
|
||||||
|
|
||||||
/* internal functions in blockdev.c */
|
/* -------------------------------------------------------- create.c */
|
||||||
NTSTATUS
|
|
||||||
VfatReadSectors(IN PDEVICE_OBJECT pDeviceObject,
|
|
||||||
IN ULONG DiskSector,
|
|
||||||
IN ULONG SectorCount,
|
|
||||||
IN UCHAR* Buffer);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext);
|
||||||
VfatWriteSectors(IN PDEVICE_OBJECT pDeviceObject,
|
|
||||||
IN ULONG DiskSector,
|
|
||||||
IN ULONG SectorCount,
|
|
||||||
IN UCHAR* Buffer);
|
|
||||||
|
|
||||||
/* internal functions in dir.c : */
|
NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt,
|
||||||
BOOL FsdDosDateTimeToFileTime(WORD wDosDate,WORD wDosTime, TIME *FileTime);
|
PFILE_OBJECT FileObject,
|
||||||
BOOL FsdFileTimeToDosDateTime(TIME *FileTime,WORD *pwDosDate,WORD *pwDosTime);
|
PWSTR FileName);
|
||||||
|
|
||||||
/* internal functions in iface.c : */
|
NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt,
|
||||||
NTSTATUS
|
PVFATFCB Fcb,
|
||||||
FindFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb,
|
PVFATFCB Parent,
|
||||||
PVFATFCB Parent, PWSTR FileToFind,ULONG *StartSector,ULONG *Entry);
|
PWSTR FileToFind,
|
||||||
NTSTATUS
|
PULONG pDirIndex,
|
||||||
VfatCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject);
|
PULONG pDirIndex2);
|
||||||
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);
|
|
||||||
|
|
||||||
/* internal functions in dirwr.c */
|
VOID vfat8Dot3ToString (PCHAR pBasename,
|
||||||
NTSTATUS
|
PCHAR pExtension,
|
||||||
addEntry(PDEVICE_EXTENSION DeviceExt,
|
PWSTR pName);
|
||||||
PFILE_OBJECT pFileObject,ULONG RequestedOptions,UCHAR ReqAttr);
|
|
||||||
NTSTATUS
|
NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt,
|
||||||
updEntry(PDEVICE_EXTENSION DeviceExt,PFILE_OBJECT pFileObject);
|
PVPB Vpb);
|
||||||
NTSTATUS
|
|
||||||
delEntry(PDEVICE_EXTENSION, PFILE_OBJECT);
|
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);
|
BOOL vfatIsFileNameValid (PWCHAR pFileName);
|
||||||
|
|
||||||
/*
|
/* ----------------------------------------------------------- fat.c */
|
||||||
* 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);
|
|
||||||
|
|
||||||
/* --------------------------------------------------------- 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);
|
ULONG ClusterToSector (PDEVICE_EXTENSION DeviceExt,
|
||||||
NTSTATUS
|
ULONG Cluster);
|
||||||
ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, PVPB Vpb);
|
|
||||||
NTSTATUS
|
|
||||||
VfatOpenFile(PDEVICE_EXTENSION DeviceExt,
|
|
||||||
PFILE_OBJECT FileObject,
|
|
||||||
PWSTR FileName);
|
|
||||||
|
|
||||||
/* ----------------------------------------------- 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,
|
ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
|
||||||
PFAT_DIR_ENTRY pDirEntry);
|
PFAT_DIR_ENTRY pDirEntry);
|
||||||
|
|
||||||
BOOL vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry);
|
BOOL vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry);
|
||||||
|
|
||||||
BOOL vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry);
|
BOOL vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry);
|
||||||
|
|
||||||
BOOL vfatIsDirEntryEndMarker (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,
|
NTSTATUS vfatGetNextDirEntry (PDEVICE_EXTENSION pDeviceExt,
|
||||||
PVFATFCB pDirectoryFCB,
|
PVFATFCB pDirectoryFCB,
|
||||||
ULONG * pDirectoryIndex,
|
ULONG * pDirectoryIndex,
|
||||||
PWSTR pLongFileName,
|
PWSTR pLongFileName,
|
||||||
PFAT_DIR_ENTRY pDirEntry);
|
PFAT_DIR_ENTRY pDirEntry);
|
||||||
|
|
||||||
/* ----------------------------------------------------- FCB Functions */
|
/* ----------------------------------------------------------- fcb.c */
|
||||||
|
|
||||||
PVFATFCB vfatNewFCB (PWCHAR pFileName);
|
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);
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------- 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);
|
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 */
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -62,29 +62,39 @@ FsdGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
FsdGetFsAttributeInformation(PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
|
FsdGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
|
||||||
PULONG BufferLength)
|
PULONG BufferLength)
|
||||||
{
|
{
|
||||||
|
ULONG Length = DeviceExt->FatInfo.FatType == FAT32 ? 10 : 6;
|
||||||
|
|
||||||
DPRINT("FsdGetFsAttributeInformation()\n");
|
DPRINT("FsdGetFsAttributeInformation()\n");
|
||||||
DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
|
DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
|
||||||
DPRINT("BufferLength %lu\n", *BufferLength);
|
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))
|
if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
|
||||||
return STATUS_INFO_LENGTH_MISMATCH;
|
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;
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
|
|
||||||
FsAttributeInfo->FileSystemAttributes =
|
FsAttributeInfo->FileSystemAttributes =
|
||||||
FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
|
FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
|
||||||
FsAttributeInfo->MaximumComponentNameLength = 255;
|
FsAttributeInfo->MaximumComponentNameLength = 255;
|
||||||
FsAttributeInfo->FileSystemNameLength = 6;
|
FsAttributeInfo->FileSystemNameLength = Length;
|
||||||
wcscpy(FsAttributeInfo->FileSystemName, L"FAT");
|
if (DeviceExt->FatInfo.FatType == FAT32)
|
||||||
|
{
|
||||||
|
memcpy(FsAttributeInfo->FileSystemName, L"FAT32", 10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(FsAttributeInfo->FileSystemName, L"FAT", 6);
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT("Finished FsdGetFsAttributeInformation()\n");
|
DPRINT("Finished FsdGetFsAttributeInformation()\n");
|
||||||
|
|
||||||
*BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6);
|
*BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length);
|
||||||
DPRINT("BufferLength %lu\n", *BufferLength);
|
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
|
@ -106,35 +116,11 @@ FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
|
||||||
return(STATUS_BUFFER_OVERFLOW);
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
DeviceExt = DeviceObject->DeviceExtension;
|
DeviceExt = DeviceObject->DeviceExtension;
|
||||||
|
Status = CountAvailableClusters(DeviceExt, &FsSizeInfo->AvailableAllocationUnits);
|
||||||
|
|
||||||
if (DeviceExt->FatType == FAT32)
|
FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->FatInfo.NumberOfClusters;
|
||||||
{
|
FsSizeInfo->SectorsPerAllocationUnit = DeviceExt->FatInfo.SectorsPerCluster;
|
||||||
struct _BootSector32 *BootSect =
|
FsSizeInfo->BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
|
||||||
(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("Finished FsdGetFsSizeInformation()\n");
|
DPRINT("Finished FsdGetFsSizeInformation()\n");
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
|
@ -216,7 +202,8 @@ NTSTATUS VfatQueryVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsAttributeInformation:
|
case FileFsAttributeInformation:
|
||||||
RC = FsdGetFsAttributeInformation(SystemBuffer,
|
RC = FsdGetFsAttributeInformation(IrpContext->DeviceObject->DeviceExtension,
|
||||||
|
SystemBuffer,
|
||||||
&BufferLength);
|
&BufferLength);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue