mirror of
https://github.com/reactos/reactos.git
synced 2024-07-22 20:28:08 +00:00
[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:
parent
1dac3daaa1
commit
f1a6ba977a
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)*/)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue