[FASTFAT_NEW]

- Implement close and cleanup infrastructure.
- Add necessary FCB and VCB counters.
- Add missing op and file locks initialization.
- A lot of small cleanups, improvements, and other things, bringing fastfat_new much closer to a minimally working state.

svn path=/trunk/; revision=48487
This commit is contained in:
Aleksey Bragin 2010-08-08 10:43:28 +00:00
parent 1dac3daaa1
commit f1a6ba977a
10 changed files with 973 additions and 32 deletions

View file

@ -13,13 +13,431 @@
/* FUNCTIONS ****************************************************************/
/* Last handle to a file object is closed */
NTSTATUS
NTAPI
FatiCleanup(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject;
TYPE_OF_OPEN TypeOfOpen;
PSHARE_ACCESS ShareAccess;
BOOLEAN SendUnlockNotification = FALSE;
PLARGE_INTEGER TruncateSize = NULL;
//LARGE_INTEGER LocalTruncateSize;
BOOLEAN AcquiredVcb = FALSE, AcquiredFcb = FALSE;
NTSTATUS Status;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DPRINT("FatiCleanup\n");
DPRINT("\tIrp = %p\n", Irp);
DPRINT("\t->FileObject = %p\n", IrpSp->FileObject);
FileObject = IrpSp->FileObject;
TypeOfOpen = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
if (TypeOfOpen == UnopenedFileObject)
{
DPRINT1("Unopened File Object\n");
FatCompleteRequest(IrpContext, Irp, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
if (FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE ))
{
/* Just flush the file */
if (FlagOn(Vcb->State, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
FlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED) &&
(TypeOfOpen == UserFileOpen))
{
//Status = FatFlushFile(IrpContext, Fcb, Flush);
//if (!NT_SUCCESS(Status)) FatNormalizeAndRaiseStatus(IrpContext, Status);
UNIMPLEMENTED;
}
FatCompleteRequest(IrpContext, Irp, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
if (TypeOfOpen == UserFileOpen ||
TypeOfOpen == UserDirectoryOpen)
{
ASSERT(Fcb != NULL);
(VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);
AcquiredFcb = TRUE;
/* Set FCB flags according to DELETE_ON_CLOSE */
if (FlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE))
{
ASSERT(FatNodeType(Fcb) != FAT_NTC_ROOT_DCB);
SetFlag(Fcb->State, FCB_STATE_DELETE_ON_CLOSE);
/* Issue a notification */
if (TypeOfOpen == UserDirectoryOpen)
{
FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
&Vcb->NotifyList,
FileObject->FsContext,
NULL,
FALSE,
FALSE,
0,
NULL,
NULL,
NULL);
}
}
/* If file should be deleted, acquire locks */
if ((Fcb->UncleanCount == 1) &&
FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
(Fcb->Condition != FcbBad) &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
{
FatReleaseFcb(IrpContext, Fcb);
AcquiredFcb = FALSE;
(VOID)FatAcquireExclusiveVcb(IrpContext, Vcb);
AcquiredVcb = TRUE;
(VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);
AcquiredFcb = TRUE;
}
}
/* Acquire VCB lock if it was a volume open */
if (TypeOfOpen == UserVolumeOpen)
{
(VOID)FatAcquireExclusiveVcb(IrpContext, Vcb);
AcquiredVcb = TRUE;
}
/* Cleanup all notifications */
if (TypeOfOpen == UserDirectoryOpen)
{
FsRtlNotifyCleanup(Vcb->NotifySync,
&Vcb->NotifyList,
Ccb);
}
if (Fcb)
{
//TODO: FatVerifyFcb
}
switch (TypeOfOpen)
{
case DirectoryFile:
case VirtualVolumeFile:
DPRINT1("Cleanup VirtualVolumeFile/DirectoryFile\n");
ShareAccess = NULL;
break;
case UserVolumeOpen:
DPRINT("Cleanup UserVolumeOpen\n");
if (FlagOn(Ccb->Flags, CCB_COMPLETE_DISMOUNT))
{
FatCheckForDismount( IrpContext, Vcb, TRUE );
} else if (FileObject->WriteAccess &&
FlagOn(FileObject->Flags, FO_FILE_MODIFIED))
{
UNIMPLEMENTED;
}
/* Release the volume and send notification */
if (FlagOn(Vcb->State, VCB_STATE_FLAG_LOCKED) &&
(Vcb->FileObjectWithVcbLocked == FileObject))
{
UNIMPLEMENTED;
SendUnlockNotification = TRUE;
}
ShareAccess = &Vcb->ShareAccess;
break;
case EaFile:
DPRINT1("Cleanup EaFileObject\n");
ShareAccess = NULL;
break;
case UserDirectoryOpen:
DPRINT("Cleanup UserDirectoryOpen\n");
ShareAccess = &Fcb->ShareAccess;
/* Should it be a delayed close? */
if ((Fcb->UncleanCount == 1) &&
(Fcb->OpenCount == 1) &&
(Fcb->Dcb.DirectoryFileOpenCount == 0) &&
!FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
Fcb->Condition == FcbGood)
{
/* Yes, a delayed one */
SetFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
}
if (VcbGood == Vcb->Condition)
{
//FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
//TODO: Actually update dirent
}
if ((Fcb->UncleanCount == 1) &&
(FatNodeType(Fcb) == FAT_NTC_DCB) &&
(FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE)) &&
(Fcb->Condition != FcbBad) &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
{
UNIMPLEMENTED;
}
/* Decrement unclean counter */
ASSERT(Fcb->UncleanCount != 0);
Fcb->UncleanCount--;
break;
case UserFileOpen:
DPRINT("Cleanup UserFileOpen\n");
ShareAccess = &Fcb->ShareAccess;
/* Should it be a delayed close? */
if ((FileObject->SectionObjectPointer->DataSectionObject == NULL) &&
(FileObject->SectionObjectPointer->ImageSectionObject == NULL) &&
(Fcb->UncleanCount == 1) &&
(Fcb->OpenCount == 1) &&
!FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
Fcb->Condition == FcbGood)
{
/* Yes, a delayed one */
SetFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
}
/* Unlock all file locks */
FsRtlFastUnlockAll(&Fcb->Fcb.Lock,
FileObject,
IoGetRequestorProcess(Irp),
NULL);
if (Vcb->Condition == VcbGood)
{
if (Fcb->Condition != FcbBad)
{
//FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
// TODO: Update on-disk structures
}
if (Fcb->UncleanCount == 1 &&
Fcb->Condition != FcbBad)
{
//DELETE_CONTEXT DeleteContext;
/* Should this file be deleted on close? */
if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
{
UNIMPLEMENTED;
}
else
{
if (!FlagOn(Fcb->State, FCB_STATE_PAGEFILE) &&
(Fcb->Header.ValidDataLength.LowPart < Fcb->Header.FileSize.LowPart))
{
#if 0
ULONG ValidDataLength;
ValidDataLength = Fcb->Header.ValidDataLength.LowPart;
if (ValidDataLength < Fcb->ValidDataToDisk) {
ValidDataLength = Fcb->ValidDataToDisk;
}
if (ValidDataLength < Fcb->Header.FileSize.LowPart)
{
FatZeroData( IrpContext,
Vcb,
FileObject,
ValidDataLength,
Fcb->Header.FileSize.LowPart -
ValidDataLength );
Fcb->ValidDataToDisk =
Fcb->Header.ValidDataLength.LowPart =
Fcb->Header.FileSize.LowPart;
if (CcIsFileCached(FileObject))
{
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
}
}
#endif
DPRINT1("Zeroing out data is not implemented\n");
}
}
/* Should the file be truncated on close? */
if (FlagOn(Fcb->State, FCB_STATE_TRUNCATE_ON_CLOSE))
{
if (Vcb->Condition == VcbGood)
{
// TODO: Actually truncate the file allocation
UNIMPLEMENTED;
}
/* Remove truncation flag */
Fcb->State &= ~FCB_STATE_TRUNCATE_ON_CLOSE;
}
/* Check again if it should be deleted */
if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
Fcb->Header.AllocationSize.LowPart == 0)
{
UNIMPLEMENTED;
/*FatNotifyReportChange(IrpContext,
Vcb,
Fcb,
FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_ACTION_REMOVED );*/
}
/* Remove the entry from the splay table if the file was deleted */
if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE))
{
FatRemoveNames(IrpContext, Fcb);
}
}
}
ASSERT(Fcb->UncleanCount != 0);
Fcb->UncleanCount--;
if (!FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
{
ASSERT(Fcb->NonCachedUncleanCount != 0);
Fcb->NonCachedUncleanCount--;
}
if (FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
(Fcb->NonCachedUncleanCount != 0) &&
(Fcb->NonCachedUncleanCount == Fcb->UncleanCount) &&
(Fcb->SectionObjectPointers.DataSectionObject != NULL))
{
CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);
/* Acquire and release PagingIo to get in sync with lazy writer */
ExAcquireResourceExclusiveLite(Fcb->Header.PagingIoResource, TRUE);
ExReleaseResourceLite(Fcb->Header.PagingIoResource);
CcPurgeCacheSection(&Fcb->SectionObjectPointers,
NULL,
0,
FALSE);
}
if (Fcb->Condition == FcbBad)
{
//TruncateSize = &FatLargeZero;
UNIMPLEMENTED;
}
/* Cleanup the cache map */
CcUninitializeCacheMap(FileObject, TruncateSize, NULL);
break;
default:
KeBugCheckEx(FAT_FILE_SYSTEM, __LINE__, (ULONG_PTR)TypeOfOpen, 0, 0);
}
/* Cleanup the share access */
if (ShareAccess)
{
DPRINT("Cleaning up the share access\n");
IoRemoveShareAccess(FileObject, ShareAccess);
}
if (TypeOfOpen == UserFileOpen)
{
/* Update oplocks */
FsRtlCheckOplock(&Fcb->Fcb.Oplock,
Irp,
IrpContext,
NULL,
NULL);
Fcb->Header.IsFastIoPossible = FatIsFastIoPossible(Fcb);
}
/* Set the FO_CLEANUP_COMPLETE flag */
SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
Status = STATUS_SUCCESS;
// TODO: Unpin repinned BCBs
//FatUnpinRepinnedBcbs(IrpContext);
/* Flush the volume if necessary */
if (FlagOn(Vcb->State, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
{
UNIMPLEMENTED;
}
/* Cleanup */
if (AcquiredFcb) FatReleaseFcb(IrpContext, Fcb);
if (AcquiredVcb) FatReleaseVcb(IrpContext, Vcb);
/* Send volume notification */
if (SendUnlockNotification)
FsRtlNotifyVolumeEvent(FileObject, FSRTL_VOLUME_UNLOCK);
return Status;
}
NTSTATUS
NTAPI
FatCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT1("FatCleanup(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
PFAT_IRP_CONTEXT IrpContext;
NTSTATUS Status;
return STATUS_NOT_IMPLEMENTED;
DPRINT("FatCleanup(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
/* FatCleanup works only with a volume device object */
if (DeviceObject == FatGlobalData.DiskDeviceObject)
{
/* Complete the request and return success */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
return STATUS_SUCCESS;
}
/* Enter FsRtl critical region */
FsRtlEnterFileSystem();
/* Build an irp context */
IrpContext = FatBuildIrpContext(Irp, TRUE);
/* Call internal function */
Status = FatiCleanup(IrpContext, Irp);
/* Leave FsRtl critical region */
FsRtlExitFileSystem();
return Status;
}
/* EOF */

View file

@ -13,13 +13,342 @@
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
FatiCommonClose(IN PVCB Vcb,
IN PFCB Fcb,
IN PCCB Ccb,
IN TYPE_OF_OPEN TypeOfOpen,
IN BOOLEAN Wait,
OUT PBOOLEAN VcbDeleted)
{
NTSTATUS Status;
PFCB ParentDcb;
BOOLEAN RecursiveClose, VcbDeletedLv = FALSE;
FAT_IRP_CONTEXT IrpContext;
if (VcbDeleted) *VcbDeleted = FALSE;
if (TypeOfOpen == UnopenedFileObject)
{
DPRINT1("Closing unopened file object\n");
Status = STATUS_SUCCESS;
return Status;
}
RtlZeroMemory(&IrpContext, sizeof(FAT_IRP_CONTEXT));
IrpContext.NodeTypeCode = FAT_NTC_IRP_CONTEXT;
IrpContext.NodeByteSize = sizeof(IrpContext);
IrpContext.MajorFunction = IRP_MJ_CLOSE;
if (Wait) SetFlag(IrpContext.Flags, IRPCONTEXT_CANWAIT);
if (!ExAcquireResourceExclusiveLite(&Vcb->Resource, Wait)) return STATUS_PENDING;
if (Vcb->State & VCB_STATE_FLAG_CLOSE_IN_PROGRESS)
{
RecursiveClose = TRUE;
}
else
{
SetFlag(Vcb->State, VCB_STATE_FLAG_CLOSE_IN_PROGRESS);
RecursiveClose = FALSE;
Vcb->OpenFileCount++;
}
/* Update on-disk structures */
switch (TypeOfOpen)
{
case VirtualVolumeFile:
DPRINT1("Close VirtualVolumeFile\n");
InterlockedDecrement((PLONG)&(Vcb->InternalOpenCount));
InterlockedDecrement((PLONG)&(Vcb->ResidualOpenCount));
Status = STATUS_SUCCESS;
goto close_done;
break;
case UserVolumeOpen:
DPRINT1("Close UserVolumeOpen\n");
Vcb->DirectAccessOpenCount--;
Vcb->OpenFileCount--;
if (FlagOn(Ccb->Flags, CCB_READ_ONLY)) Vcb->ReadOnlyCount--;
FatDeleteCcb(&IrpContext, Ccb);
Status = STATUS_SUCCESS;
goto close_done;
break;
case EaFile:
UNIMPLEMENTED;
break;
case DirectoryFile:
DPRINT1("Close DirectoryFile\n");
InterlockedDecrement((PLONG)&(Fcb->Dcb.DirectoryFileOpenCount));
InterlockedDecrement((PLONG)&(Vcb->InternalOpenCount));
if (FatNodeType(Fcb) == FAT_NTC_ROOT_DCB)
{
InterlockedDecrement((PLONG)&(Vcb->ResidualOpenCount));
}
if (RecursiveClose)
{
Status = STATUS_SUCCESS;
goto close_done;
}
else
{
break;
}
case UserDirectoryOpen:
case UserFileOpen:
DPRINT("Close UserFileOpen/UserDirectoryOpen\n");
if ((FatNodeType(Fcb) == FAT_NTC_DCB) &&
IsListEmpty(&Fcb->Dcb.ParentDcbList) &&
(Fcb->OpenCount == 1) &&
(Fcb->Dcb.DirectoryFile != NULL))
{
PFILE_OBJECT DirectoryFileObject = Fcb->Dcb.DirectoryFile;
DPRINT1("Uninitialize the stream file object\n");
CcUninitializeCacheMap(DirectoryFileObject, NULL, NULL);
Fcb->Dcb.DirectoryFile = NULL;
ObDereferenceObject(DirectoryFileObject);
}
Fcb->OpenCount--;
Vcb->OpenFileCount--;
if (FlagOn(Ccb->Flags, CCB_READ_ONLY)) Vcb->ReadOnlyCount --;
FatDeleteCcb(&IrpContext, Ccb);
break;
default:
KeBugCheckEx(FAT_FILE_SYSTEM, __LINE__, (ULONG_PTR)TypeOfOpen, 0, 0);
}
/* Update in-memory structures */
if (((FatNodeType(Fcb) == FAT_NTC_FCB) &&
(Fcb->OpenCount == 0))
||
((FatNodeType(Fcb) == FAT_NTC_DCB) &&
(IsListEmpty(&Fcb->Dcb.ParentDcbList)) &&
(Fcb->OpenCount == 0) &&
(Fcb->Dcb.DirectoryFileOpenCount == 0)))
{
ParentDcb = Fcb->ParentFcb;
SetFlag(Vcb->State, VCB_STATE_FLAG_DELETED_FCB);
FatDeleteFcb(&IrpContext, Fcb);
while ((FatNodeType(ParentDcb) == FAT_NTC_DCB) &&
IsListEmpty(&ParentDcb->Dcb.ParentDcbList) &&
(ParentDcb->OpenCount == 0) &&
(ParentDcb->Dcb.DirectoryFile != NULL))
{
PFILE_OBJECT DirectoryFileObject;
DirectoryFileObject = ParentDcb->Dcb.DirectoryFile;
DPRINT1("Uninitialize parent Stream Cache Map\n");
CcUninitializeCacheMap(DirectoryFileObject, NULL, NULL);
ParentDcb->Dcb.DirectoryFile = NULL;
ObDereferenceObject(DirectoryFileObject);
if (ParentDcb->Dcb.DirectoryFileOpenCount == 0)
{
PFCB CurrentDcb;
CurrentDcb = ParentDcb;
ParentDcb = CurrentDcb->ParentFcb;
SetFlag(Vcb->State, VCB_STATE_FLAG_DELETED_FCB);
FatDeleteFcb(&IrpContext, CurrentDcb);
}
else
{
break;
}
}
}
Status = STATUS_SUCCESS;
close_done:
/* Closing is done, check if VCB could be closed too */
if (!RecursiveClose)
{
/* One open left - yes, VCB can go away */
if (Vcb->OpenFileCount == 1 &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS)
&& VcbDeleted)
{
FatReleaseVcb(&IrpContext, Vcb );
SetFlag(IrpContext.Flags, IRPCONTEXT_CANWAIT);
FatAcquireExclusiveGlobal(&IrpContext);
FatAcquireExclusiveVcb(&IrpContext, Vcb);
Vcb->OpenFileCount--;
VcbDeletedLv = FatCheckForDismount(&IrpContext, Vcb, FALSE);
FatReleaseGlobal(&IrpContext);
if (VcbDeleted) *VcbDeleted = VcbDeletedLv;
}
else
{
/* Remove extra referenec */
Vcb->OpenFileCount --;
}
/* Clear recursion flag if necessary */
if (!VcbDeletedLv)
{
ClearFlag(Vcb->State, VCB_STATE_FLAG_CLOSE_IN_PROGRESS);
}
}
/* Release VCB if it wasn't deleted */
if (!VcbDeletedLv)
FatReleaseVcb(&IrpContext, Vcb);
return Status;
}
NTSTATUS
NTAPI
FatiClose(IN PFAT_IRP_CONTEXT IrpContext,
IN PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
TYPE_OF_OPEN TypeOfOpen;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
BOOLEAN TopLevel, Wait, VcbDeleted = FALSE;
NTSTATUS Status;
PCLOSE_CONTEXT CloseContext = NULL;
TopLevel = FatIsTopLevelIrp(Irp);
/* Get current IRP stack location */
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Decode incoming file object */
TypeOfOpen = FatDecodeFileObject(IrpSp->FileObject, &Vcb, &Fcb, &Ccb);
/* Set CCB read only flag */
if (Ccb && IsFileObjectReadOnly(IrpSp->FileObject))
SetFlag(Ccb->Flags, CCB_READ_ONLY);
/* It's possible to wait only if we are top level or not a system process */
Wait = TopLevel && (PsGetCurrentProcess() != FatGlobalData.SystemProcess);
/* Call the common handler */
Status = FatiCommonClose(Vcb, Fcb, Ccb, TypeOfOpen, Wait, &VcbDeleted);
if (((TypeOfOpen == UserFileOpen ||
TypeOfOpen == UserDirectoryOpen) &&
(Fcb->State & FCB_STATE_DELAY_CLOSE) &&
!FatGlobalData.ShutdownStarted) ||
Status == STATUS_PENDING)
{
DPRINT1("TODO: Queue a pending close request\n");
}
else
{
/* Close finished right away */
if (TypeOfOpen == VirtualVolumeFile ||
TypeOfOpen == DirectoryFile ||
TypeOfOpen == EaFile)
{
if (TypeOfOpen == VirtualVolumeFile)
{
/* Free close context for the not deleted VCB */
if (!VcbDeleted)
{
CloseContext = Vcb->CloseContext;
Vcb->CloseContext = NULL;
ASSERT(CloseContext != NULL);
}
}
else
{
//CloseContext = FatAllocateCloseContext(Vcb);
DPRINT1("TODO: Allocate close context!\n");
ASSERT(CloseContext != NULL);
}
/* Free close context */
if (CloseContext) ExFreePool(CloseContext);
}
}
/* Complete the request */
FatCompleteRequest(NULL, Irp, Status);
/* Reset the top level IRP if necessary */
if (TopLevel) IoSetTopLevelIrp(NULL);
return Status;
}
NTSTATUS
NTAPI
FatClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT1("FatClose(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
PFAT_IRP_CONTEXT IrpContext;
NTSTATUS Status;
return STATUS_NOT_IMPLEMENTED;
DPRINT("FatClose(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
/* FatClose works only with a volume device object */
if (DeviceObject == FatGlobalData.DiskDeviceObject)
{
/* Complete the request and return success */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
return STATUS_SUCCESS;
}
/* Enter FsRtl critical region */
FsRtlEnterFileSystem();
/* Build an irp context */
IrpContext = FatBuildIrpContext(Irp, TRUE);
/* Call internal function */
Status = FatiClose(IrpContext, Irp);
/* Leave FsRtl critical region */
FsRtlExitFileSystem();
return Status;
}
/* EOF */

View file

@ -72,7 +72,9 @@ FatiOpenRootDcb(IN PFAT_IRP_CONTEXT IrpContext,
/* Increment counters */
Dcb->OpenCount++;
Dcb->UncleanCount++;
Vcb->OpenFileCount++;
if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
/* Set success statuses */
Iosb.Status = STATUS_SUCCESS;
@ -186,7 +188,7 @@ FatiOverwriteFile(PFAT_IRP_CONTEXT IrpContext,
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
// TODO: Actually truncate the file
DPRINT1("TODO: Actually truncate the file with a fullfat handle %x\n", Fcb->FatHandle);
DPRINT1("TODO: Actually truncate file '%wZ' with a fullfat handle %x\n", &Fcb->FullFileName, Fcb->FatHandle);
/* Release the paging resource */
ExReleaseResourceLite(Fcb->Header.PagingIoResource);
@ -288,6 +290,12 @@ FatiOpenExistingDir(IN PFAT_IRP_CONTEXT IrpContext,
Fcb,
FatCreateCcb());
/* Increase counters */
Fcb->UncleanCount++;
Fcb->OpenCount++;
Vcb->OpenFileCount++;
if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
Iosb.Status = STATUS_SUCCESS;
Iosb.Information = FILE_OPENED;
@ -319,6 +327,7 @@ FatiOpenExistingFile(IN PFAT_IRP_CONTEXT IrpContext,
PFCB Fcb;
NTSTATUS Status;
FF_FILE *FileHandle;
FF_ERROR FfError;
/* Check for create file option and fail */
if (CreateDisposition == FILE_CREATE)
@ -341,20 +350,22 @@ FatiOpenExistingFile(IN PFAT_IRP_CONTEXT IrpContext,
}
/* Open the file with FullFAT */
FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, NULL);
FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, &FfError);
if (!FileHandle)
{
DPRINT1("Failed to open file '%s', error %ld\n", AnsiName.Buffer, FfError);
Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND; // FIXME: A shortcut for now
return Iosb;
}
DPRINT1("Succeeded opening file '%s'\n", AnsiName.Buffer);
/* Create a new FCB for this file */
Fcb = FatCreateFcb(IrpContext, Vcb, ParentDcb, FileHandle);
// TODO: Check if overwrite is needed
// This is usual file open branch, without overwriting!
// TODO: This is usual file open branch, without overwriting!
/* Set context and section object pointers */
FatSetFileObject(FileObject,
UserFileOpen,
@ -365,6 +376,13 @@ FatiOpenExistingFile(IN PFAT_IRP_CONTEXT IrpContext,
Iosb.Status = STATUS_SUCCESS;
Iosb.Information = FILE_OPENED;
/* Increase counters */
Fcb->UncleanCount++;
Fcb->OpenCount++;
if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) Fcb->NonCachedUncleanCount++;
if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
return Iosb;
}
@ -397,7 +415,7 @@ FatiOpenVolume(IN PFAT_IRP_CONTEXT IrpContext,
// and opened handles count is not 0
//if (!FlagOn(ShareAccess, FILE_SHARE_READ)
DPRINT1("Exclusive voume open\n");
DPRINT1("Exclusive volume open\n");
// TODO: Flush the volume
VolumeFlushed = TRUE;
@ -450,6 +468,7 @@ FatiOpenVolume(IN PFAT_IRP_CONTEXT IrpContext,
/* Increase direct open count */
Vcb->DirectOpenCount++;
Vcb->OpenFileCount++;
if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
/* Set no buffering flag */
FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
@ -720,7 +739,7 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
/* Set parent DCB */
ParentDcb = RelatedDcb;
DPRINT1("Opening file '%wZ' relatively to '%wZ'\n", &FileName, &ParentDcb->FullFileName);
DPRINT("Opening file '%wZ' relatively to '%wZ'\n", &FileName, &ParentDcb->FullFileName);
}
else
{
@ -1137,6 +1156,12 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
DeleteOnClose,
OpenedAsDos);
/* In case of success set cache supported flag */
if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering)
{
SetFlag(FileObject->Flags, FO_CACHE_SUPPORTED);
}
Irp->IoStatus.Information = Iosb.Information;
/* Unlock VCB */

View file

@ -82,9 +82,6 @@ FatCreateRootDcb(IN PFAT_IRP_CONTEXT IrpContext,
ExInitializeFastMutex(&Dcb->HeaderMutex);
FsRtlSetupAdvancedHeader(&Dcb->Header, &Dcb->HeaderMutex);
/* Initialize MCB */
FsRtlInitializeLargeMcb(&Dcb->Mcb, NonPagedPool);
/* Set up first cluster field depending on FAT type */
if (TRUE/*FatIsFat32(Vcb)*/)
{

View file

@ -42,6 +42,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
RtlZeroMemory(&FatGlobalData, sizeof(FAT_GLOBAL_DATA));
FatGlobalData.DriverObject = DriverObject;
FatGlobalData.DiskDeviceObject = DeviceObject;
FatGlobalData.SystemProcess = PsGetCurrentProcess();
/* Fill major function handlers */
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FatClose;
@ -317,7 +318,7 @@ FatDecodeFileObject(IN PFILE_OBJECT FileObject,
TypeOfOpen = (*Ccb == NULL ? DirectoryFile : UserDirectoryOpen);
DPRINT1("Referencing a directory: %wZ\n", &(*FcbOrDcb)->FullFileName);
DPRINT("Referencing a directory: %wZ\n", &(*FcbOrDcb)->FullFileName);
break;
/* File */
@ -510,4 +511,17 @@ FatMapUserBuffer(PIRP Irp)
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
}
BOOLEAN
NTAPI
FatIsTopLevelIrp(IN PIRP Irp)
{
if (!IoGetTopLevelIrp())
{
IoSetTopLevelIrp(Irp);
return TRUE;
}
return FALSE;
}
/* EOF */

View file

@ -36,6 +36,22 @@
ExReleaseResourceLite(&(FatGlobalData.Resource)); \
}
#define FatIsFastIoPossible(FCB) ((BOOLEAN) \
(((FCB)->Condition != FcbGood || !FsRtlOplockIsFastIoPossible(&(FCB)->Fcb.Oplock)) ? \
FastIoIsNotPossible \
: \
(!FsRtlAreThereCurrentFileLocks(&(FCB)->Fcb.Lock) && \
((FCB)->OutstandingAsyncWrites == 0) && \
!FlagOn((FCB)->Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED) ? \
FastIoIsPossible \
: \
FastIoIsQuestionable \
) \
) \
)
#define IsFileObjectReadOnly(FO) (!((FO)->WriteAccess | (FO)->DeleteAccess))
NTSYSAPI
NTSTATUS
NTAPI
@ -67,6 +83,12 @@ FatReadStreamFile(PVCB Vcb,
PBCB *Bcb,
PVOID *Buffer);
BOOLEAN
NTAPI
FatCheckForDismount(IN PFAT_IRP_CONTEXT IrpContext,
PVCB Vcb,
IN BOOLEAN Force);
/* ----------------------------------------------------------- dir.c */
NTSTATUS NTAPI
@ -205,6 +227,9 @@ FatSetFileObject(PFILE_OBJECT FileObject,
PVOID FASTCALL
FatMapUserBuffer(PIRP Irp);
BOOLEAN NTAPI
FatIsTopLevelIrp(IN PIRP Irp);
/* --------------------------------------------------------- fullfat.c */
FF_T_SINT32
@ -284,6 +309,10 @@ FatCreateFcb(
IN PFCB ParentDcb,
IN FF_FILE *FileHandle);
VOID NTAPI
FatDeleteFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb);
IO_STATUS_BLOCK NTAPI
FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject,
@ -319,6 +348,10 @@ FatRemoveNames(IN PFAT_IRP_CONTEXT IrpContext,
PCCB NTAPI
FatCreateCcb();
VOID NTAPI
FatDeleteCcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PCCB Ccb);
VOID NTAPI
FatSetFullNameInFcb(PFCB Fcb,
PUNICODE_STRING Name);

View file

@ -201,6 +201,10 @@ FatInitializeVcb(IN PFAT_IRP_CONTEXT IrpContext,
goto FatInitializeVcbCleanup;
}
/* Increase internal / residual open counter */
InterlockedIncrement((PLONG)&(Vcb->InternalOpenCount));
InterlockedIncrement((PLONG)&(Vcb->ResidualOpenCount));
/* Set up notifications */
FsRtlNotifyInitializeSync(&Vcb->NotifySync);
InitializeListHead(&Vcb->NotifyList);

View file

@ -14,15 +14,17 @@ typedef FAT_NODE_TYPE *PFAT_NODE_TYPE;
#define FatNodeType(Ptr) (*((PFAT_NODE_TYPE)(Ptr)))
/* Node type codes */
#define FAT_NTC_VCB (CSHORT) '00VF'
#define FAT_NTC_FCB (CSHORT) 'CF'
#define FAT_NTC_DCB (CSHORT) 'DF'
#define FAT_NTC_ROOT_DCB (CSHORT) 'RFD'
#define FAT_NTC_CCB (CSHORT) 'BCC'
#define FAT_NTC_VCB (CSHORT) '00VF'
#define FAT_NTC_FCB (CSHORT) 'CF'
#define FAT_NTC_DCB (CSHORT) 'DF'
#define FAT_NTC_ROOT_DCB (CSHORT) 'RFD'
#define FAT_NTC_CCB (CSHORT) 'BCC'
#define FAT_NTC_IRP_CONTEXT (CSHORT) 'PRI'
typedef struct _FAT_GLOBAL_DATA
{
ERESOURCE Resource;
PEPROCESS SystemProcess;
PDRIVER_OBJECT DriverObject;
PDEVICE_OBJECT DiskDeviceObject;
LIST_ENTRY VcbListHead;
@ -33,6 +35,7 @@ typedef struct _FAT_GLOBAL_DATA
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks;
CACHE_MANAGER_CALLBACKS CacheMgrNoopCallbacks;
BOOLEAN Win31FileSystem;
BOOLEAN ShutdownStarted;
/* Jan 1, 1980 System Time */
LARGE_INTEGER DefaultFileTime;
@ -82,6 +85,10 @@ typedef struct _FAT_PAGE_CONTEXT
typedef struct _FAT_IRP_CONTEXT
{
/* Type and size of this record (must be FAT_NTC_IRP_CONTEXT) */
FAT_NODE_TYPE NodeTypeCode;
CSHORT NodeByteSize;
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
UCHAR MajorFunction;
@ -132,10 +139,15 @@ typedef struct _FAT_METHODS {
PFAT_SETFAT_VALUE_RUN_ROUTINE SetValueRun;
} FAT_METHODS, *PFAT_METHODS;
#define VCB_STATE_FLAG_LOCKED 0x01
#define VCB_STATE_FLAG_DIRTY 0x02
#define VCB_STATE_MOUNTED_DIRTY 0x04
#define VCB_STATE_CREATE_IN_PROGRESS 0x08
#define VCB_STATE_FLAG_LOCKED 0x001
#define VCB_STATE_FLAG_DIRTY 0x002
#define VCB_STATE_MOUNTED_DIRTY 0x004
#define VCB_STATE_CREATE_IN_PROGRESS 0x008
#define VCB_STATE_FLAG_CLOSE_IN_PROGRESS 0x010
#define VCB_STATE_FLAG_DELETED_FCB 0x020
#define VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS 0x040
#define VCB_STATE_FLAG_DEFERRED_FLUSH 0x080
#define VCB_STATE_FLAG_WRITE_PROTECTED 0x100
typedef enum _VCB_CONDITION
{
@ -158,10 +170,11 @@ typedef struct _VCB
ULONG State;
VCB_CONDITION Condition;
ERESOURCE Resource;
struct _CLOSE_CONTEXT *CloseContext;
/* Direct volume access */
ULONG DirectOpenCount;
SHARE_ACCESS ShareAccess;
PFILE_OBJECT FileObjectWithVcbLocked;
/* Notifications support */
PNOTIFY_SYNC NotifySync;
@ -186,8 +199,13 @@ typedef struct _VCB
struct _FCB *RootDcb;
/* Counters */
ULONG MediaChangeCount;
ULONG DirectOpenCount;
ULONG OpenFileCount;
ULONG ReadOnlyCount;
ULONG InternalOpenCount;
ULONG ResidualOpenCount;
ULONG DirectAccessOpenCount;
ULONG MediaChangeCount;
/* FullFAT integration */
FF_IOMAN *Ioman;
@ -252,6 +270,7 @@ typedef enum _FCB_CONDITION
#define FCB_STATE_PAGEFILE 0x04
#define FCB_STATE_DELAY_CLOSE 0x08
#define FCB_STATE_TRUNCATE_ON_CLOSE 0x10
#define FCB_STATE_DELETE_ON_CLOSE 0x20
typedef struct _FCB
{
@ -281,8 +300,6 @@ typedef struct _FCB
FCB_CONDITION Condition;
/* Share access */
SHARE_ACCESS ShareAccess;
/* Mcb mapping Vbo->Lbo */
LARGE_MCB Mcb;
ULONG FirstCluster;
/* Links into FCB Tree */
FCB_NAME_LINK ShortName;
@ -307,6 +324,8 @@ typedef struct _FCB
PKEVENT OutstandingAsyncEvent;
/* Counters */
ULONG OpenCount;
ULONG UncleanCount;
ULONG NonCachedUncleanCount;
union
{
struct
@ -318,10 +337,11 @@ typedef struct _FCB
struct
{
/* A list of all FCBs/DCBs opened under this DCB */
LIST_ENTRY ParentDcbList;
LIST_ENTRY ParentDcbList; /* A list of all FCBs/DCBs opened under this DCB */
ULONG DirectoryFileOpenCount; /* Sector-based access to the dir */
PFILE_OBJECT DirectoryFile;
/* Directory data stream (just handy to have it). */
PFILE_OBJECT StreamFileObject;
//PFILE_OBJECT StreamFileObject;
/* Bitmap to search for free dirents. */
RTL_BITMAP FreeBitmap;
/* Names */
@ -390,6 +410,17 @@ typedef enum _TYPE_OF_OPEN
EaFile
} TYPE_OF_OPEN;
typedef struct _CLOSE_CONTEXT
{
LIST_ENTRY GlobalLinks;
LIST_ENTRY VcbLinks;
PVCB Vcb;
PFCB Fcb;
TYPE_OF_OPEN TypeOfOpen;
BOOLEAN Free;
} CLOSE_CONTEXT, *PCLOSE_CONTEXT;
typedef enum _FILE_TIME_INDEX
{
FileCreationTime = 0,
@ -402,4 +433,8 @@ typedef enum _FILE_TIME_INDEX
#define CCB_SEARCH_PATTERN_LEGAL_8DOT3 0x02
#define CCB_SEARCH_PATTERN_HAS_WILD_CARD 0x04
#define CCB_DASD_IO 0x10
#define CCB_READ_ONLY 0x20
#define CCB_DELETE_ON_CLOSE 0x40
#define CCB_COMPLETE_DISMOUNT 0x80
extern FAT_GLOBAL_DATA FatGlobalData;

View file

@ -149,12 +149,74 @@ FatCreateFcb(IN PFAT_IRP_CONTEXT IrpContext,
Fcb->Header.ValidDataLength.LowPart = FileHandle->Filesize;
Fcb->FatHandle = FileHandle;
/* Initialize locks */
FsRtlInitializeFileLock(&Fcb->Fcb.Lock, NULL, NULL);
FsRtlInitializeOplock(&Fcb->Fcb.Oplock);
/* Set names */
FatSetFcbNames(IrpContext, Fcb);
return Fcb;
}
VOID
NTAPI
FatDeleteFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb)
{
DPRINT("FatDeleteFcb %p\n", Fcb);
if (Fcb->OpenCount != 0)
{
DPRINT1("Trying to delete FCB with OpenCount %d\n", Fcb->OpenCount);
ASSERT(FALSE);
}
if ((Fcb->Header.NodeTypeCode == FAT_NTC_DCB) ||
(Fcb->Header.NodeTypeCode == FAT_NTC_ROOT_DCB))
{
/* Make sure it's a valid deletion */
ASSERT(Fcb->Dcb.DirectoryFileOpenCount == 0);
ASSERT(IsListEmpty(&Fcb->Dcb.ParentDcbList));
ASSERT(Fcb->Dcb.DirectoryFile == NULL);
}
else
{
/* Free locks */
FsRtlUninitializeFileLock(&Fcb->Fcb.Lock);
FsRtlUninitializeOplock(&Fcb->Fcb.Oplock);
}
/* Release any possible filter contexts */
FsRtlTeardownPerStreamContexts(&Fcb->Header);
/* Remove from parents queue */
if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB)
{
RemoveEntryList(&(Fcb->ParentDcbLinks));
}
/* Free FullFAT handle */
if (Fcb->FatHandle) FF_Close(Fcb->FatHandle);
/* Remove from the splay table */
if (FlagOn(Fcb->State, FCB_STATE_HAS_NAMES))
FatRemoveNames(IrpContext, Fcb);
/* Free file name buffers */
if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB)
{
if (Fcb->FullFileName.Buffer)
ExFreePool(Fcb->FullFileName.Buffer);
}
if (Fcb->ExactCaseLongName.Buffer)
ExFreePool(Fcb->ExactCaseLongName.Buffer);
/* Free this FCB, finally */
ExFreePool(Fcb);
}
PCCB
NTAPI
FatCreateCcb()
@ -172,6 +234,17 @@ FatCreateCcb()
return Ccb;
}
VOID
NTAPI
FatDeleteCcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PCCB Ccb)
{
// TODO: Deallocate CCB strings, if any
/* Free the CCB */
ExFreePool(Ccb);
}
IO_STATUS_BLOCK
NTAPI
FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
@ -443,8 +516,11 @@ SuccComplete:
ClearFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
/* Increase counters */
Fcb->UncleanCount++;
Fcb->OpenCount++;
Vcb->OpenFileCount++;
if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) Fcb->NonCachedUncleanCount++;
// TODO: Handle DeleteOnClose and OpenedAsDos by storing those flags in CCB
}

View file

@ -8,7 +8,7 @@
/* INCLUDES *****************************************************************/
//#define NDEBUG
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS ****************************************************************/
@ -77,8 +77,8 @@ FatiQueryFsSizeInfo(PVCB Vcb,
Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;
DPRINT1("Total %d, free %d, SPC %d, BPS %d\n", Partition->FreeClusterCount,
Partition->NumClusters, Vcb->Bpb.SectorsPerCluster, Vcb->Bpb.BytesPerSector);
DPRINT1("Total %d, free %d, SPC %d, BPS %d\n", Partition->NumClusters,
Partition->FreeClusterCount, Vcb->Bpb.SectorsPerCluster, Vcb->Bpb.BytesPerSector);
return Status;
}
@ -228,4 +228,14 @@ FatReadStreamFile(PVCB Vcb,
}
}
BOOLEAN
NTAPI
FatCheckForDismount(IN PFAT_IRP_CONTEXT IrpContext,
PVCB Vcb,
IN BOOLEAN Force)
{
/* We never allow deletion of a volume for now */
return FALSE;
}
/* EOF */