mirror of
https://github.com/reactos/reactos.git
synced 2025-06-20 07:36:05 +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
10 changed files with 973 additions and 32 deletions
|
@ -13,13 +13,431 @@
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* 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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
FatCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
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 */
|
/* EOF */
|
||||||
|
|
|
@ -13,13 +13,342 @@
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* 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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
FatClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
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 */
|
/* EOF */
|
||||||
|
|
|
@ -72,7 +72,9 @@ FatiOpenRootDcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
|
|
||||||
/* Increment counters */
|
/* Increment counters */
|
||||||
Dcb->OpenCount++;
|
Dcb->OpenCount++;
|
||||||
|
Dcb->UncleanCount++;
|
||||||
Vcb->OpenFileCount++;
|
Vcb->OpenFileCount++;
|
||||||
|
if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
|
||||||
|
|
||||||
/* Set success statuses */
|
/* Set success statuses */
|
||||||
Iosb.Status = STATUS_SUCCESS;
|
Iosb.Status = STATUS_SUCCESS;
|
||||||
|
@ -186,7 +188,7 @@ FatiOverwriteFile(PFAT_IRP_CONTEXT IrpContext,
|
||||||
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
|
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
|
||||||
|
|
||||||
// TODO: Actually truncate the file
|
// 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 */
|
/* Release the paging resource */
|
||||||
ExReleaseResourceLite(Fcb->Header.PagingIoResource);
|
ExReleaseResourceLite(Fcb->Header.PagingIoResource);
|
||||||
|
@ -288,6 +290,12 @@ FatiOpenExistingDir(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
Fcb,
|
Fcb,
|
||||||
FatCreateCcb());
|
FatCreateCcb());
|
||||||
|
|
||||||
|
/* Increase counters */
|
||||||
|
Fcb->UncleanCount++;
|
||||||
|
Fcb->OpenCount++;
|
||||||
|
Vcb->OpenFileCount++;
|
||||||
|
if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
|
||||||
|
|
||||||
Iosb.Status = STATUS_SUCCESS;
|
Iosb.Status = STATUS_SUCCESS;
|
||||||
Iosb.Information = FILE_OPENED;
|
Iosb.Information = FILE_OPENED;
|
||||||
|
|
||||||
|
@ -319,6 +327,7 @@ FatiOpenExistingFile(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
PFCB Fcb;
|
PFCB Fcb;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
FF_FILE *FileHandle;
|
FF_FILE *FileHandle;
|
||||||
|
FF_ERROR FfError;
|
||||||
|
|
||||||
/* Check for create file option and fail */
|
/* Check for create file option and fail */
|
||||||
if (CreateDisposition == FILE_CREATE)
|
if (CreateDisposition == FILE_CREATE)
|
||||||
|
@ -341,20 +350,22 @@ FatiOpenExistingFile(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open the file with FullFAT */
|
/* 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)
|
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
|
Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND; // FIXME: A shortcut for now
|
||||||
return Iosb;
|
return Iosb;
|
||||||
}
|
}
|
||||||
|
DPRINT1("Succeeded opening file '%s'\n", AnsiName.Buffer);
|
||||||
|
|
||||||
/* Create a new FCB for this file */
|
/* Create a new FCB for this file */
|
||||||
Fcb = FatCreateFcb(IrpContext, Vcb, ParentDcb, FileHandle);
|
Fcb = FatCreateFcb(IrpContext, Vcb, ParentDcb, FileHandle);
|
||||||
|
|
||||||
// TODO: Check if overwrite is needed
|
// 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 */
|
/* Set context and section object pointers */
|
||||||
FatSetFileObject(FileObject,
|
FatSetFileObject(FileObject,
|
||||||
UserFileOpen,
|
UserFileOpen,
|
||||||
|
@ -365,6 +376,13 @@ FatiOpenExistingFile(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
Iosb.Status = STATUS_SUCCESS;
|
Iosb.Status = STATUS_SUCCESS;
|
||||||
Iosb.Information = FILE_OPENED;
|
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;
|
return Iosb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +415,7 @@ FatiOpenVolume(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
// and opened handles count is not 0
|
// and opened handles count is not 0
|
||||||
//if (!FlagOn(ShareAccess, FILE_SHARE_READ)
|
//if (!FlagOn(ShareAccess, FILE_SHARE_READ)
|
||||||
|
|
||||||
DPRINT1("Exclusive voume open\n");
|
DPRINT1("Exclusive volume open\n");
|
||||||
|
|
||||||
// TODO: Flush the volume
|
// TODO: Flush the volume
|
||||||
VolumeFlushed = TRUE;
|
VolumeFlushed = TRUE;
|
||||||
|
@ -450,6 +468,7 @@ FatiOpenVolume(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
/* Increase direct open count */
|
/* Increase direct open count */
|
||||||
Vcb->DirectOpenCount++;
|
Vcb->DirectOpenCount++;
|
||||||
Vcb->OpenFileCount++;
|
Vcb->OpenFileCount++;
|
||||||
|
if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
|
||||||
|
|
||||||
/* Set no buffering flag */
|
/* Set no buffering flag */
|
||||||
FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
|
FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
|
||||||
|
@ -720,7 +739,7 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
/* Set parent DCB */
|
/* Set parent DCB */
|
||||||
ParentDcb = RelatedDcb;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -1137,6 +1156,12 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
DeleteOnClose,
|
DeleteOnClose,
|
||||||
OpenedAsDos);
|
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;
|
Irp->IoStatus.Information = Iosb.Information;
|
||||||
|
|
||||||
/* Unlock VCB */
|
/* Unlock VCB */
|
||||||
|
|
|
@ -82,9 +82,6 @@ FatCreateRootDcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
ExInitializeFastMutex(&Dcb->HeaderMutex);
|
ExInitializeFastMutex(&Dcb->HeaderMutex);
|
||||||
FsRtlSetupAdvancedHeader(&Dcb->Header, &Dcb->HeaderMutex);
|
FsRtlSetupAdvancedHeader(&Dcb->Header, &Dcb->HeaderMutex);
|
||||||
|
|
||||||
/* Initialize MCB */
|
|
||||||
FsRtlInitializeLargeMcb(&Dcb->Mcb, NonPagedPool);
|
|
||||||
|
|
||||||
/* Set up first cluster field depending on FAT type */
|
/* Set up first cluster field depending on FAT type */
|
||||||
if (TRUE/*FatIsFat32(Vcb)*/)
|
if (TRUE/*FatIsFat32(Vcb)*/)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
|
||||||
RtlZeroMemory(&FatGlobalData, sizeof(FAT_GLOBAL_DATA));
|
RtlZeroMemory(&FatGlobalData, sizeof(FAT_GLOBAL_DATA));
|
||||||
FatGlobalData.DriverObject = DriverObject;
|
FatGlobalData.DriverObject = DriverObject;
|
||||||
FatGlobalData.DiskDeviceObject = DeviceObject;
|
FatGlobalData.DiskDeviceObject = DeviceObject;
|
||||||
|
FatGlobalData.SystemProcess = PsGetCurrentProcess();
|
||||||
|
|
||||||
/* Fill major function handlers */
|
/* Fill major function handlers */
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FatClose;
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FatClose;
|
||||||
|
@ -317,7 +318,7 @@ FatDecodeFileObject(IN PFILE_OBJECT FileObject,
|
||||||
|
|
||||||
TypeOfOpen = (*Ccb == NULL ? DirectoryFile : UserDirectoryOpen);
|
TypeOfOpen = (*Ccb == NULL ? DirectoryFile : UserDirectoryOpen);
|
||||||
|
|
||||||
DPRINT1("Referencing a directory: %wZ\n", &(*FcbOrDcb)->FullFileName);
|
DPRINT("Referencing a directory: %wZ\n", &(*FcbOrDcb)->FullFileName);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* File */
|
/* File */
|
||||||
|
@ -510,4 +511,17 @@ FatMapUserBuffer(PIRP Irp)
|
||||||
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
|
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
FatIsTopLevelIrp(IN PIRP Irp)
|
||||||
|
{
|
||||||
|
if (!IoGetTopLevelIrp())
|
||||||
|
{
|
||||||
|
IoSetTopLevelIrp(Irp);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -36,6 +36,22 @@
|
||||||
ExReleaseResourceLite(&(FatGlobalData.Resource)); \
|
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
|
NTSYSAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -67,6 +83,12 @@ FatReadStreamFile(PVCB Vcb,
|
||||||
PBCB *Bcb,
|
PBCB *Bcb,
|
||||||
PVOID *Buffer);
|
PVOID *Buffer);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
FatCheckForDismount(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
|
PVCB Vcb,
|
||||||
|
IN BOOLEAN Force);
|
||||||
|
|
||||||
/* ----------------------------------------------------------- dir.c */
|
/* ----------------------------------------------------------- dir.c */
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
|
@ -205,6 +227,9 @@ FatSetFileObject(PFILE_OBJECT FileObject,
|
||||||
PVOID FASTCALL
|
PVOID FASTCALL
|
||||||
FatMapUserBuffer(PIRP Irp);
|
FatMapUserBuffer(PIRP Irp);
|
||||||
|
|
||||||
|
BOOLEAN NTAPI
|
||||||
|
FatIsTopLevelIrp(IN PIRP Irp);
|
||||||
|
|
||||||
/* --------------------------------------------------------- fullfat.c */
|
/* --------------------------------------------------------- fullfat.c */
|
||||||
|
|
||||||
FF_T_SINT32
|
FF_T_SINT32
|
||||||
|
@ -284,6 +309,10 @@ FatCreateFcb(
|
||||||
IN PFCB ParentDcb,
|
IN PFCB ParentDcb,
|
||||||
IN FF_FILE *FileHandle);
|
IN FF_FILE *FileHandle);
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
FatDeleteFcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
|
IN PFCB Fcb);
|
||||||
|
|
||||||
IO_STATUS_BLOCK NTAPI
|
IO_STATUS_BLOCK NTAPI
|
||||||
FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
|
FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
IN PFILE_OBJECT FileObject,
|
IN PFILE_OBJECT FileObject,
|
||||||
|
@ -319,6 +348,10 @@ FatRemoveNames(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
PCCB NTAPI
|
PCCB NTAPI
|
||||||
FatCreateCcb();
|
FatCreateCcb();
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
FatDeleteCcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
|
IN PCCB Ccb);
|
||||||
|
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
FatSetFullNameInFcb(PFCB Fcb,
|
FatSetFullNameInFcb(PFCB Fcb,
|
||||||
PUNICODE_STRING Name);
|
PUNICODE_STRING Name);
|
||||||
|
|
|
@ -201,6 +201,10 @@ FatInitializeVcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
goto FatInitializeVcbCleanup;
|
goto FatInitializeVcbCleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Increase internal / residual open counter */
|
||||||
|
InterlockedIncrement((PLONG)&(Vcb->InternalOpenCount));
|
||||||
|
InterlockedIncrement((PLONG)&(Vcb->ResidualOpenCount));
|
||||||
|
|
||||||
/* Set up notifications */
|
/* Set up notifications */
|
||||||
FsRtlNotifyInitializeSync(&Vcb->NotifySync);
|
FsRtlNotifyInitializeSync(&Vcb->NotifySync);
|
||||||
InitializeListHead(&Vcb->NotifyList);
|
InitializeListHead(&Vcb->NotifyList);
|
||||||
|
|
|
@ -19,10 +19,12 @@ typedef FAT_NODE_TYPE *PFAT_NODE_TYPE;
|
||||||
#define FAT_NTC_DCB (CSHORT) 'DF'
|
#define FAT_NTC_DCB (CSHORT) 'DF'
|
||||||
#define FAT_NTC_ROOT_DCB (CSHORT) 'RFD'
|
#define FAT_NTC_ROOT_DCB (CSHORT) 'RFD'
|
||||||
#define FAT_NTC_CCB (CSHORT) 'BCC'
|
#define FAT_NTC_CCB (CSHORT) 'BCC'
|
||||||
|
#define FAT_NTC_IRP_CONTEXT (CSHORT) 'PRI'
|
||||||
|
|
||||||
typedef struct _FAT_GLOBAL_DATA
|
typedef struct _FAT_GLOBAL_DATA
|
||||||
{
|
{
|
||||||
ERESOURCE Resource;
|
ERESOURCE Resource;
|
||||||
|
PEPROCESS SystemProcess;
|
||||||
PDRIVER_OBJECT DriverObject;
|
PDRIVER_OBJECT DriverObject;
|
||||||
PDEVICE_OBJECT DiskDeviceObject;
|
PDEVICE_OBJECT DiskDeviceObject;
|
||||||
LIST_ENTRY VcbListHead;
|
LIST_ENTRY VcbListHead;
|
||||||
|
@ -33,6 +35,7 @@ typedef struct _FAT_GLOBAL_DATA
|
||||||
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks;
|
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks;
|
||||||
CACHE_MANAGER_CALLBACKS CacheMgrNoopCallbacks;
|
CACHE_MANAGER_CALLBACKS CacheMgrNoopCallbacks;
|
||||||
BOOLEAN Win31FileSystem;
|
BOOLEAN Win31FileSystem;
|
||||||
|
BOOLEAN ShutdownStarted;
|
||||||
/* Jan 1, 1980 System Time */
|
/* Jan 1, 1980 System Time */
|
||||||
LARGE_INTEGER DefaultFileTime;
|
LARGE_INTEGER DefaultFileTime;
|
||||||
|
|
||||||
|
@ -82,6 +85,10 @@ typedef struct _FAT_PAGE_CONTEXT
|
||||||
|
|
||||||
typedef struct _FAT_IRP_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;
|
PIRP Irp;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
UCHAR MajorFunction;
|
UCHAR MajorFunction;
|
||||||
|
@ -132,10 +139,15 @@ typedef struct _FAT_METHODS {
|
||||||
PFAT_SETFAT_VALUE_RUN_ROUTINE SetValueRun;
|
PFAT_SETFAT_VALUE_RUN_ROUTINE SetValueRun;
|
||||||
} FAT_METHODS, *PFAT_METHODS;
|
} FAT_METHODS, *PFAT_METHODS;
|
||||||
|
|
||||||
#define VCB_STATE_FLAG_LOCKED 0x01
|
#define VCB_STATE_FLAG_LOCKED 0x001
|
||||||
#define VCB_STATE_FLAG_DIRTY 0x02
|
#define VCB_STATE_FLAG_DIRTY 0x002
|
||||||
#define VCB_STATE_MOUNTED_DIRTY 0x04
|
#define VCB_STATE_MOUNTED_DIRTY 0x004
|
||||||
#define VCB_STATE_CREATE_IN_PROGRESS 0x08
|
#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
|
typedef enum _VCB_CONDITION
|
||||||
{
|
{
|
||||||
|
@ -158,10 +170,11 @@ typedef struct _VCB
|
||||||
ULONG State;
|
ULONG State;
|
||||||
VCB_CONDITION Condition;
|
VCB_CONDITION Condition;
|
||||||
ERESOURCE Resource;
|
ERESOURCE Resource;
|
||||||
|
struct _CLOSE_CONTEXT *CloseContext;
|
||||||
|
|
||||||
/* Direct volume access */
|
/* Direct volume access */
|
||||||
ULONG DirectOpenCount;
|
|
||||||
SHARE_ACCESS ShareAccess;
|
SHARE_ACCESS ShareAccess;
|
||||||
|
PFILE_OBJECT FileObjectWithVcbLocked;
|
||||||
|
|
||||||
/* Notifications support */
|
/* Notifications support */
|
||||||
PNOTIFY_SYNC NotifySync;
|
PNOTIFY_SYNC NotifySync;
|
||||||
|
@ -186,8 +199,13 @@ typedef struct _VCB
|
||||||
struct _FCB *RootDcb;
|
struct _FCB *RootDcb;
|
||||||
|
|
||||||
/* Counters */
|
/* Counters */
|
||||||
ULONG MediaChangeCount;
|
ULONG DirectOpenCount;
|
||||||
ULONG OpenFileCount;
|
ULONG OpenFileCount;
|
||||||
|
ULONG ReadOnlyCount;
|
||||||
|
ULONG InternalOpenCount;
|
||||||
|
ULONG ResidualOpenCount;
|
||||||
|
ULONG DirectAccessOpenCount;
|
||||||
|
ULONG MediaChangeCount;
|
||||||
|
|
||||||
/* FullFAT integration */
|
/* FullFAT integration */
|
||||||
FF_IOMAN *Ioman;
|
FF_IOMAN *Ioman;
|
||||||
|
@ -252,6 +270,7 @@ typedef enum _FCB_CONDITION
|
||||||
#define FCB_STATE_PAGEFILE 0x04
|
#define FCB_STATE_PAGEFILE 0x04
|
||||||
#define FCB_STATE_DELAY_CLOSE 0x08
|
#define FCB_STATE_DELAY_CLOSE 0x08
|
||||||
#define FCB_STATE_TRUNCATE_ON_CLOSE 0x10
|
#define FCB_STATE_TRUNCATE_ON_CLOSE 0x10
|
||||||
|
#define FCB_STATE_DELETE_ON_CLOSE 0x20
|
||||||
|
|
||||||
typedef struct _FCB
|
typedef struct _FCB
|
||||||
{
|
{
|
||||||
|
@ -281,8 +300,6 @@ typedef struct _FCB
|
||||||
FCB_CONDITION Condition;
|
FCB_CONDITION Condition;
|
||||||
/* Share access */
|
/* Share access */
|
||||||
SHARE_ACCESS ShareAccess;
|
SHARE_ACCESS ShareAccess;
|
||||||
/* Mcb mapping Vbo->Lbo */
|
|
||||||
LARGE_MCB Mcb;
|
|
||||||
ULONG FirstCluster;
|
ULONG FirstCluster;
|
||||||
/* Links into FCB Tree */
|
/* Links into FCB Tree */
|
||||||
FCB_NAME_LINK ShortName;
|
FCB_NAME_LINK ShortName;
|
||||||
|
@ -307,6 +324,8 @@ typedef struct _FCB
|
||||||
PKEVENT OutstandingAsyncEvent;
|
PKEVENT OutstandingAsyncEvent;
|
||||||
/* Counters */
|
/* Counters */
|
||||||
ULONG OpenCount;
|
ULONG OpenCount;
|
||||||
|
ULONG UncleanCount;
|
||||||
|
ULONG NonCachedUncleanCount;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
|
@ -318,10 +337,11 @@ typedef struct _FCB
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/* A list of all FCBs/DCBs opened under this DCB */
|
LIST_ENTRY ParentDcbList; /* A list of all FCBs/DCBs opened under this DCB */
|
||||||
LIST_ENTRY ParentDcbList;
|
ULONG DirectoryFileOpenCount; /* Sector-based access to the dir */
|
||||||
|
PFILE_OBJECT DirectoryFile;
|
||||||
/* Directory data stream (just handy to have it). */
|
/* Directory data stream (just handy to have it). */
|
||||||
PFILE_OBJECT StreamFileObject;
|
//PFILE_OBJECT StreamFileObject;
|
||||||
/* Bitmap to search for free dirents. */
|
/* Bitmap to search for free dirents. */
|
||||||
RTL_BITMAP FreeBitmap;
|
RTL_BITMAP FreeBitmap;
|
||||||
/* Names */
|
/* Names */
|
||||||
|
@ -390,6 +410,17 @@ typedef enum _TYPE_OF_OPEN
|
||||||
EaFile
|
EaFile
|
||||||
} TYPE_OF_OPEN;
|
} 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
|
typedef enum _FILE_TIME_INDEX
|
||||||
{
|
{
|
||||||
FileCreationTime = 0,
|
FileCreationTime = 0,
|
||||||
|
@ -402,4 +433,8 @@ typedef enum _FILE_TIME_INDEX
|
||||||
#define CCB_SEARCH_PATTERN_LEGAL_8DOT3 0x02
|
#define CCB_SEARCH_PATTERN_LEGAL_8DOT3 0x02
|
||||||
#define CCB_SEARCH_PATTERN_HAS_WILD_CARD 0x04
|
#define CCB_SEARCH_PATTERN_HAS_WILD_CARD 0x04
|
||||||
#define CCB_DASD_IO 0x10
|
#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;
|
extern FAT_GLOBAL_DATA FatGlobalData;
|
||||||
|
|
|
@ -149,12 +149,74 @@ FatCreateFcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
Fcb->Header.ValidDataLength.LowPart = FileHandle->Filesize;
|
Fcb->Header.ValidDataLength.LowPart = FileHandle->Filesize;
|
||||||
Fcb->FatHandle = FileHandle;
|
Fcb->FatHandle = FileHandle;
|
||||||
|
|
||||||
|
/* Initialize locks */
|
||||||
|
FsRtlInitializeFileLock(&Fcb->Fcb.Lock, NULL, NULL);
|
||||||
|
FsRtlInitializeOplock(&Fcb->Fcb.Oplock);
|
||||||
|
|
||||||
/* Set names */
|
/* Set names */
|
||||||
FatSetFcbNames(IrpContext, Fcb);
|
FatSetFcbNames(IrpContext, Fcb);
|
||||||
|
|
||||||
return 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
|
PCCB
|
||||||
NTAPI
|
NTAPI
|
||||||
FatCreateCcb()
|
FatCreateCcb()
|
||||||
|
@ -172,6 +234,17 @@ FatCreateCcb()
|
||||||
return Ccb;
|
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
|
IO_STATUS_BLOCK
|
||||||
NTAPI
|
NTAPI
|
||||||
FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
|
FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
|
@ -443,8 +516,11 @@ SuccComplete:
|
||||||
ClearFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
|
ClearFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
|
||||||
|
|
||||||
/* Increase counters */
|
/* Increase counters */
|
||||||
|
Fcb->UncleanCount++;
|
||||||
Fcb->OpenCount++;
|
Fcb->OpenCount++;
|
||||||
Vcb->OpenFileCount++;
|
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
|
// TODO: Handle DeleteOnClose and OpenedAsDos by storing those flags in CCB
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
//#define NDEBUG
|
#define NDEBUG
|
||||||
#include "fastfat.h"
|
#include "fastfat.h"
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
@ -77,8 +77,8 @@ FatiQueryFsSizeInfo(PVCB Vcb,
|
||||||
Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
|
Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
|
||||||
Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;
|
Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;
|
||||||
|
|
||||||
DPRINT1("Total %d, free %d, SPC %d, BPS %d\n", Partition->FreeClusterCount,
|
DPRINT1("Total %d, free %d, SPC %d, BPS %d\n", Partition->NumClusters,
|
||||||
Partition->NumClusters, Vcb->Bpb.SectorsPerCluster, Vcb->Bpb.BytesPerSector);
|
Partition->FreeClusterCount, Vcb->Bpb.SectorsPerCluster, Vcb->Bpb.BytesPerSector);
|
||||||
|
|
||||||
return Status;
|
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 */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue