VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner) { PAGED_CODE(); FSP_FILE_NODE_GET_FLAGS(); FSP_FILE_NODE_ASSERT_FLAGS_SET(); Owner = (PVOID)((UINT_PTR)Owner | 3); if (Flags & FspFileNodeAcquirePgio) { if (ExIsResourceAcquiredLite(FileNode->Header.PagingIoResource)) ExReleaseResourceLite(FileNode->Header.PagingIoResource); else ExReleaseResourceForThreadLite(FileNode->Header.PagingIoResource, (ERESOURCE_THREAD)Owner); } if (Flags & FspFileNodeAcquireMain) { if (ExIsResourceAcquiredLite(FileNode->Header.Resource)) ExReleaseResourceLite(FileNode->Header.Resource); else ExReleaseResourceForThreadLite(FileNode->Header.Resource, (ERESOURCE_THREAD)Owner); } FSP_FILE_NODE_CLR_FLAGS(); }
__drv_mustHoldCriticalRegion NTSTATUS RfsdPnpCancelRemove ( PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb ) { NTSTATUS Status; PAGED_CODE(); RfsdPrint((DBG_PNP, "RfsdPnpCancelRemove by RfsdPnp ...\n")); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); Status = RfsdUnlockVcb(Vcb, IrpContext->FileObject); ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); IoSkipCurrentIrpStackLocation(IrpContext->Irp); Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp); IrpContext->Irp = NULL; return Status; }
VOID FFSFreeCcb( IN PFFS_CCB Ccb) { ASSERT(Ccb != NULL); ASSERT((Ccb->Identifier.Type == FFSCCB) && (Ccb->Identifier.Size == sizeof(FFS_CCB))); if (Ccb->DirectorySearchPattern.Buffer != NULL) { ExFreePool(Ccb->DirectorySearchPattern.Buffer); } if (FlagOn(Ccb->Flags, CCB_FROM_POOL)) { ExFreePool(Ccb); } else { ExAcquireResourceExclusiveLite( &FFSGlobal->LAResource, TRUE); ExFreeToNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList), Ccb); ExReleaseResourceForThreadLite( &FFSGlobal->LAResource, ExGetCurrentResourceThread()); } }
__drv_mustHoldCriticalRegion VOID FFSFreeMcb( IN PFFS_MCB Mcb) { #ifndef __REACTOS__ PFFS_MCB Parent = Mcb->Parent; #endif PAGED_CODE(); ASSERT(Mcb != NULL); ASSERT((Mcb->Identifier.Type == FFSMCB) && (Mcb->Identifier.Size == sizeof(FFS_MCB))); FFSPrint((DBG_INFO, "FFSFreeMcb: Mcb %S will be freed.\n", Mcb->ShortName.Buffer)); if (Mcb->ShortName.Buffer) ExFreePool(Mcb->ShortName.Buffer); if (FlagOn(Mcb->Flags, MCB_FROM_POOL)) { ExFreePool(Mcb); } else { ExAcquireResourceExclusiveLite( &FFSGlobal->LAResource, TRUE); ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb); ExReleaseResourceForThreadLite( &FFSGlobal->LAResource, ExGetCurrentResourceThread()); } ExAcquireResourceExclusiveLite( &FFSGlobal->CountResource, TRUE); FFSGlobal->McbAllocated--; ExReleaseResourceForThreadLite( &FFSGlobal->CountResource, ExGetCurrentResourceThread()); }
__drv_mustHoldCriticalRegion PFFS_CCB FFSAllocateCcb( VOID) { PFFS_CCB Ccb; PAGED_CODE(); ExAcquireResourceExclusiveLite( &FFSGlobal->LAResource, TRUE); Ccb = (PFFS_CCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList))); ExReleaseResourceForThreadLite( &FFSGlobal->LAResource, ExGetCurrentResourceThread()); if (Ccb == NULL) { Ccb = (PFFS_CCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_CCB), FFS_POOL_TAG); RtlZeroMemory(Ccb, sizeof(FFS_CCB)); SetFlag(Ccb->Flags, CCB_FROM_POOL); } else { RtlZeroMemory(Ccb, sizeof(FFS_CCB)); } if (!Ccb) { return NULL; } Ccb->Identifier.Type = FFSCCB; Ccb->Identifier.Size = sizeof(FFS_CCB); Ccb->CurrentByteOffset = 0; Ccb->DirectorySearchPattern.Length = 0; Ccb->DirectorySearchPattern.MaximumLength = 0; Ccb->DirectorySearchPattern.Buffer = 0; return Ccb; }
__drv_mustHoldCriticalRegion VOID FFSFreeIrpContext( IN PFFS_IRP_CONTEXT IrpContext) { PAGED_CODE(); ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); FFSUnpinRepinnedBcbs(IrpContext); // Return the Irp context record to the region or to pool depending on // its flag if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL)) { IrpContext->Identifier.Type = 0; IrpContext->Identifier.Size = 0; ExFreePool(IrpContext); } else { IrpContext->Identifier.Type = 0; IrpContext->Identifier.Size = 0; ExAcquireResourceExclusiveLite( &FFSGlobal->LAResource, TRUE); ExFreeToNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList), IrpContext); ExReleaseResourceForThreadLite( &FFSGlobal->LAResource, ExGetCurrentResourceThread()); } }
__drv_mustHoldCriticalRegion NTSTATUS RfsdPnpSurpriseRemove ( PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb ) { NTSTATUS Status; KEVENT Event; BOOLEAN bDeleted; PAGED_CODE(); _SEH2_TRY { RfsdPrint((DBG_PNP, "RfsdPnpSupriseRemove by RfsdPnp ...\n")); #if (_WIN32_WINNT >= 0x0500) CcWaitForCurrentLazyWriterActivity(); #endif ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); Status = RfsdLockVcb(Vcb, IrpContext->FileObject); ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); // // Setup the Irp. We'll send it to the lower disk driver. // IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); KeInitializeEvent( &Event, NotificationEvent, FALSE ); IoSetCompletionRoutine( IrpContext->Irp, RfsdPnpCompletionRoutine, &Event, TRUE, TRUE, TRUE ); Status = IoCallDriver( Vcb->TargetDeviceObject, IrpContext->Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); Status = IrpContext->Irp->IoStatus.Status; } ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); RfsdPurgeVolume(Vcb, FALSE); ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); bDeleted = RfsdCheckDismount(IrpContext, Vcb, TRUE); } _SEH2_FINALLY { RfsdCompleteRequest( IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? IO_DISK_INCREMENT : IO_NO_INCREMENT) ); IrpContext->Irp = NULL; } _SEH2_END; return Status; }
NTSTATUS FFSWriteVolume( IN PFFS_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_VCB Vcb = NULL; PFFS_CCB Ccb = NULL; PFFS_FCBVCB FcbOrVcb = NULL; PFILE_OBJECT FileObject = NULL; PDEVICE_OBJECT DeviceObject = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION IoStackLocation = NULL; ULONG Length; LARGE_INTEGER ByteOffset; BOOLEAN PagingIo; BOOLEAN Nocache; BOOLEAN SynchronousIo; BOOLEAN MainResourceAcquired = FALSE; BOOLEAN PagingIoResourceAcquired = FALSE; BOOLEAN bDeferred = FALSE; PUCHAR Buffer = NULL; __try { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); FileObject = IrpContext->FileObject; FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext; ASSERT(FcbOrVcb); if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Ccb = (PFFS_CCB)FileObject->FsContext2; Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); Length = IoStackLocation->Parameters.Write.Length; ByteOffset = IoStackLocation->Parameters.Write.ByteOffset; PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE); Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE); SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE); FFSPrint((DBG_INFO, "FFSWriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n", ByteOffset.QuadPart, Length, PagingIo, Nocache)); if (Length == 0) { Irp->IoStatus.Information = 0; Status = STATUS_SUCCESS; __leave; } // For the case of "Direct Access Storage Device", we // need flush/purge the cache if (Ccb != NULL) { ExAcquireResourceExclusive(&Vcb->MainResource, TRUE); MainResourceAcquired = TRUE; Status = FFSPurgeVolume(Vcb, TRUE); ExReleaseResource(&Vcb->MainResource); MainResourceAcquired = FALSE; if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) { if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) { Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); } } { FFS_BDL BlockArray; if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) || (Length & (SECTOR_SIZE - 1))) { Status = STATUS_INVALID_PARAMETER; __leave; } Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (!NT_SUCCESS(Status)) { __leave; } BlockArray.Irp = NULL; BlockArray.Lba = ByteOffset.QuadPart;; BlockArray.Offset = 0; BlockArray.Length = Length; Status = FFSReadWriteBlocks(IrpContext, Vcb, &BlockArray, Length, 1, FALSE); Irp = IrpContext->Irp; __leave; } } if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) || Length & (SECTOR_SIZE - 1))) { Status = STATUS_INVALID_PARAMETER; __leave; } if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); Status = STATUS_PENDING; __leave; } if (ByteOffset.QuadPart >= Vcb->PartitionInformation.PartitionLength.QuadPart) { Irp->IoStatus.Information = 0; Status = STATUS_END_OF_FILE; __leave; } #if FALSE if (!Nocache) { BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); if (!CcCanIWrite( FileObject, Length, (bWait && bQueue), bAgain)) { SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); CcDeferWrite(FileObject, (PCC_POST_DEFERRED_WRITE)FFSDeferWrite, IrpContext, Irp, Length, bAgain); bDeferred = TRUE; FFSBreakPoint(); Status = STATUS_PENDING; __leave; } } #endif if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) { ExAcquireResourceExclusive(&Vcb->MainResource, TRUE); MainResourceAcquired = TRUE; ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); ExReleaseResource(&Vcb->PagingIoResource); CcFlushCache(&(Vcb->SectionObject), &ByteOffset, Length, &(Irp->IoStatus)); if (!NT_SUCCESS(Irp->IoStatus.Status)) { Status = Irp->IoStatus.Status; __leave; } ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); ExReleaseResource(&Vcb->PagingIoResource); CcPurgeCacheSection(&(Vcb->SectionObject), (PLARGE_INTEGER)&(ByteOffset), Length, FALSE); ExReleaseResource(&Vcb->MainResource); MainResourceAcquired = FALSE; } if (!PagingIo) { if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; __leave; } MainResourceAcquired = TRUE; } else { /* ULONG ResShCnt, ResExCnt; ResShCnt = ExIsResourceAcquiredSharedLite(&Vcb->PagingIoResource); ResExCnt = ExIsResourceAcquiredExclusiveLite(&Vcb->PagingIoResource); FFSPrint((DBG_USER, "PagingIoRes: %xh:%xh Synchronous=%xh\n", ResShCnt, ResExCnt, IrpContext->IsSynchronous)); */ if (Ccb) { if (!ExAcquireResourceSharedLite( &Vcb->PagingIoResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; __leave; } PagingIoResourceAcquired = TRUE; } } if (!Nocache) { if ((ByteOffset.QuadPart + Length) > Vcb->PartitionInformation.PartitionLength.QuadPart ) { Length = (ULONG) ( Vcb->PartitionInformation.PartitionLength.QuadPart - ByteOffset.QuadPart); Length &= ~((ULONG)SECTOR_SIZE - 1); } if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { CcPrepareMdlWrite( Vcb->StreamObj, &ByteOffset, Length, &Irp->MdlAddress, &Irp->IoStatus); Status = Irp->IoStatus.Status; } else { Buffer = FFSGetUserBuffer(Irp); if (Buffer == NULL) { FFSBreakPoint(); Status = STATUS_INVALID_USER_BUFFER; __leave; } if (!CcCopyWrite(Vcb->StreamObj, (PLARGE_INTEGER)(&ByteOffset), Length, TRUE, Buffer)) { Status = STATUS_PENDING; __leave; } Status = Irp->IoStatus.Status; FFSAddMcbEntry(Vcb, ByteOffset.QuadPart, (LONGLONG)Length); } if (NT_SUCCESS(Status)) { Irp->IoStatus.Information = Length; } } else { PFFS_BDL ffs_bdl = NULL; ULONG Blocks = 0; LONGLONG DirtyStart; LONGLONG DirtyLba; LONGLONG DirtyLength; LONGLONG RemainLength; if ((ByteOffset.QuadPart + Length) > Vcb->PartitionInformation.PartitionLength.QuadPart) { Length = (ULONG)( Vcb->PartitionInformation.PartitionLength.QuadPart - ByteOffset.QuadPart); Length &= ~((ULONG)SECTOR_SIZE - 1); } Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (!NT_SUCCESS(Status)) { __leave; } ffs_bdl = ExAllocatePool(PagedPool, (Length / Vcb->BlockSize) * sizeof(FFS_BDL)); if (!ffs_bdl) { Status = STATUS_INSUFFICIENT_RESOURCES; __leave; } DirtyLba = ByteOffset.QuadPart; RemainLength = (LONGLONG)Length; while (RemainLength > 0) { DirtyStart = DirtyLba; if (FFSLookupMcbEntry(Vcb, DirtyStart, &DirtyLba, &DirtyLength, (PLONGLONG)NULL, (PLONGLONG)NULL, (PULONG)NULL)) { if (DirtyLba == -1) { DirtyLba = DirtyStart + DirtyLength; RemainLength = ByteOffset.QuadPart + (LONGLONG)Length - DirtyLba; continue; } ffs_bdl[Blocks].Irp = NULL; ffs_bdl[Blocks].Lba = DirtyLba; ffs_bdl[Blocks].Offset = (ULONG)((LONGLONG)Length + DirtyStart - RemainLength - DirtyLba); if (DirtyLba + DirtyLength > DirtyStart + RemainLength) { ffs_bdl[Blocks].Length = (ULONG)(DirtyStart + RemainLength - DirtyLba); RemainLength = 0; } else { ffs_bdl[Blocks].Length = (ULONG)DirtyLength; RemainLength = (DirtyStart + RemainLength) - (DirtyLba + DirtyLength); } DirtyLba = DirtyStart + DirtyLength; Blocks++; } else { if (Blocks == 0) { if (ffs_bdl) ExFreePool(ffs_bdl); // // Lookup fails at the first time, ie. // no dirty blocks in the run // FFSBreakPoint(); if (RemainLength == (LONGLONG)Length) Status = STATUS_SUCCESS; else Status = STATUS_UNSUCCESSFUL; __leave; } else { break; } } } if (Blocks > 0) { Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, Length, Blocks, FALSE); Irp = IrpContext->Irp; if (NT_SUCCESS(Status)) { ULONG i; for (i = 0; i < Blocks; i++) { FFSRemoveMcbEntry(Vcb, ffs_bdl[i].Lba, ffs_bdl[i].Length); } } if (ffs_bdl) ExFreePool(ffs_bdl); if (!Irp) __leave; } else { if (ffs_bdl) ExFreePool(ffs_bdl); Irp->IoStatus.Information = Length; Status = STATUS_SUCCESS; __leave; } } } __finally { if (PagingIoResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->PagingIoResource, ExGetCurrentResourceThread()); } if (MainResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { if (Irp) { if (Status == STATUS_PENDING) { if(!bDeferred) { Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (NT_SUCCESS(Status)) { Status = FFSQueueRequest(IrpContext); } else { FFSCompleteIrpContext(IrpContext, Status); } } } else { if (NT_SUCCESS(Status)) { if (SynchronousIo && !PagingIo) { FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information; } if (!PagingIo) { SetFlag(FileObject->Flags, FO_FILE_MODIFIED); } } FFSCompleteIrpContext(IrpContext, Status); } } else { FFSFreeIrpContext(IrpContext); } } } return Status; }
__drv_mustHoldCriticalRegion NTSTATUS RfsdCleanup (IN PRFSD_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_SUCCESS; PRFSD_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; PFILE_OBJECT FileObject; PRFSD_FCB Fcb = 0; BOOLEAN FcbResourceAcquired = FALSE; BOOLEAN FcbPagingIoAcquired = FALSE; PRFSD_CCB Ccb; PIRP Irp; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == RFSDICX) && (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; if (DeviceObject == RfsdGlobal->DeviceObject) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == RFSDVCB) && (Vcb->Identifier.Size == sizeof(RFSD_VCB))); if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } #ifdef _MSC_VER #pragma prefast( suppress: 28137, "by design" ) #endif if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, IrpContext->IsSynchronous )) { Status = STATUS_PENDING; _SEH2_LEAVE; } VcbResourceAcquired = TRUE; FileObject = IrpContext->FileObject; Fcb = (PRFSD_FCB) FileObject->FsContext; if (!Fcb) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (Fcb->Identifier.Type == RFSDVCB) { if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && (Vcb->LockFile == FileObject) ) { ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED); Vcb->LockFile = NULL; RfsdClearVpbFlag(Vcb->Vpb, VPB_LOCKED); } Vcb->OpenHandleCount--; if (!Vcb->OpenHandleCount) { IoRemoveShareAccess(FileObject, &Vcb->ShareAccess); } Status = STATUS_SUCCESS; _SEH2_LEAVE; } ASSERT((Fcb->Identifier.Type == RFSDFCB) && (Fcb->Identifier.Size == sizeof(RFSD_FCB))); /* if ( !IsFlagOn(Vcb->Flags, VCB_READ_ONLY) && !IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) */ { #ifdef _MSC_VER #pragma prefast( suppress: 28137, "by design" ) #endif if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, IrpContext->IsSynchronous )) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbResourceAcquired = TRUE; } Ccb = (PRFSD_CCB) FileObject->FsContext2; if (!Ccb) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) { if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) && !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED) ) { Status = RfsdFlushFile(Fcb); } _SEH2_LEAVE; } ASSERT((Ccb->Identifier.Type == RFSDCCB) && (Ccb->Identifier.Size == sizeof(RFSD_CCB))); Irp = IrpContext->Irp; Fcb->OpenHandleCount--; if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED )) { Fcb->NonCachedOpenCount--; } Vcb->OpenFileHandleCount--; if (IsFlagOn(Fcb->Flags, FCB_DELETE_ON_CLOSE)) { SetFlag(Fcb->Flags, FCB_DELETE_PENDING); if (IsDirectory(Fcb)) { FsRtlNotifyFullChangeDirectory( Vcb->NotifySync, &Vcb->NotifyList, Fcb, NULL, FALSE, FALSE, 0, NULL, NULL, NULL ); } } if (IsDirectory(Fcb)) { FsRtlNotifyCleanup( Vcb->NotifySync, &Vcb->NotifyList, Ccb ); } else { // // Drop any byte range locks this process may have on the file. // FsRtlFastUnlockAll( &Fcb->FileLockAnchor, FileObject, IoGetRequestorProcess(Irp), NULL ); // // If there are no byte range locks owned by other processes on the // file the fast I/O read/write functions doesn't have to check for // locks so we set IsFastIoPossible to FastIoIsPossible again. // if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) { if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) { RfsdPrint(( DBG_INFO, ": %-16.16s %-31s %s\n", RfsdGetCurrentProcessName(), "FastIoIsPossible", Fcb->AnsiFileName.Buffer )); Fcb->Header.IsFastIoPossible = FastIoIsPossible; } } } if ( IsFlagOn( FileObject->Flags, FO_CACHE_SUPPORTED) && (Fcb->NonCachedOpenCount != 0) && (Fcb->NonCachedOpenCount == Fcb->ReferenceCount) && (Fcb->SectionObject.DataSectionObject != NULL)) { if( !IsFlagOn(Vcb->Flags, VCB_READ_ONLY) && !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) { CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL); } ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE); ExReleaseResourceLite(&(Fcb->PagingIoResource)); CcPurgeCacheSection( &Fcb->SectionObject, NULL, 0, FALSE ); } if (Fcb->OpenHandleCount == 0) { if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { // // Have to delete this file... // #ifdef _MSC_VER #pragma prefast( suppress: 28137, "by design" ) #endif if (!ExAcquireResourceExclusiveLite( &Fcb->PagingIoResource, IrpContext->IsSynchronous )) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbPagingIoAcquired = TRUE; DbgBreak(); #if DISABLED Status = RfsdDeleteFile(IrpContext, Vcb, Fcb); if (NT_SUCCESS(Status)) { if (IsDirectory(Fcb)) { RfsdNotifyReportChange( IrpContext, Vcb, Fcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_REMOVED ); } else { RfsdNotifyReportChange( IrpContext, Vcb, Fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_REMOVED ); } } #endif if (CcIsFileCached(FileObject)) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); SetFlag(FileObject->Flags, FO_FILE_MODIFIED); } if (FcbPagingIoAcquired) { ExReleaseResourceForThreadLite( &Fcb->PagingIoResource, ExGetCurrentResourceThread() ); FcbPagingIoAcquired = FALSE; } } } if (!IsDirectory(Fcb) && FileObject->PrivateCacheMap) { RfsdPrint((DBG_INFO, "RfsdCleanup: CcUninitializeCacheMap is called for %s.\n", Fcb->AnsiFileName.Buffer )); CcUninitializeCacheMap( FileObject, (PLARGE_INTEGER)(&(Fcb->Header.FileSize)), NULL ); } if (!Fcb->OpenHandleCount) { IoRemoveShareAccess(FileObject, &Fcb->ShareAccess); } RfsdPrint((DBG_INFO, "RfsdCleanup: OpenCount: %u ReferCount: %u %s\n", Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer )); Status = STATUS_SUCCESS; if (FileObject) { SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE); } } _SEH2_FINALLY { if (FcbPagingIoAcquired) { ExReleaseResourceForThreadLite( &Fcb->PagingIoResource, ExGetCurrentResourceThread() ); } if (FcbResourceAcquired) { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread() ); } if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { RfsdQueueRequest(IrpContext); } else { IrpContext->Irp->IoStatus.Status = Status; RfsdCompleteIrpContext(IrpContext, Status); } } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS RfsdVerifyVolume (IN PRFSD_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PRFSD_SUPER_BLOCK rfsd_sb = NULL; PRFSD_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN GlobalResourceAcquired = FALSE; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; ULONG ChangeCount; ULONG dwReturn; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == RFSDICX) && (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == RfsdGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } ExAcquireResourceExclusiveLite( &RfsdGlobal->Resource, TRUE ); GlobalResourceAcquired = TRUE; Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == RFSDVCB) && (Vcb->Identifier.Size == sizeof(RFSD_VCB))); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); VcbResourceAcquired = TRUE; if (!FlagOn(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (!IsMounted(Vcb)) { Status = STATUS_WRONG_VOLUME; _SEH2_LEAVE; } dwReturn = sizeof(ULONG); Status = RfsdDiskIoControl( Vcb->TargetDeviceObject, IOCTL_DISK_CHECK_VERIFY, NULL, 0, &ChangeCount, &dwReturn ); if (ChangeCount != Vcb->ChangeCount) { Status = STATUS_WRONG_VOLUME; _SEH2_LEAVE; } Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); rfsd_sb = RfsdLoadSuper(Vcb, TRUE); // FUTURE: use the volume name and uuid from the extended superblock to make this happen. // NOTE: The magic check will have to use the same thing as mount did! if ((rfsd_sb != NULL) /*&& (rfsd_sb->s_magic == RFSD_SUPER_MAGIC) && (memcmp(rfsd_sb->s_uuid, SUPER_BLOCK->s_uuid, 16) == 0) && (memcmp(rfsd_sb->s_volume_name, SUPER_BLOCK->s_volume_name, 16) ==0)*/) { ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); if (RfsdIsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject)) { SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } else { ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } RfsdPrint((DBG_INFO, "RfsdVerifyVolume: Volume verify succeeded.\n")); Status = STATUS_SUCCESS; } else { Status = STATUS_WRONG_VOLUME; RfsdPurgeVolume(Vcb, FALSE); SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); RfsdPrint((DBG_INFO, "RfsdVerifyVolume: Volume verify failed.\n")); } } _SEH2_FINALLY { if (rfsd_sb) ExFreePool(rfsd_sb); if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); } if (GlobalResourceAcquired) { ExReleaseResourceForThreadLite( &RfsdGlobal->Resource, ExGetCurrentResourceThread() ); } if (!IrpContext->ExceptionInProgress) { RfsdCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS RfsdInvalidateVolumes ( IN PRFSD_IRP_CONTEXT IrpContext ) { NTSTATUS Status; PIRP Irp; PIO_STACK_LOCATION IrpSp; HANDLE Handle; PLIST_ENTRY ListEntry; PFILE_OBJECT FileObject; PDEVICE_OBJECT DeviceObject; BOOLEAN GlobalResourceAcquired = FALSE; LUID Privilege = {SE_TCB_PRIVILEGE, 0}; _SEH2_TRY { Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp); if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode)) { Status = STATUS_PRIVILEGE_NOT_HELD; _SEH2_LEAVE; } if ( #ifndef _GNU_NTIFS_ IrpSp->Parameters.FileSystemControl.InputBufferLength #else ((PEXTENDED_IO_STACK_LOCATION)(IrpSp))-> Parameters.FileSystemControl.InputBufferLength #endif != sizeof(HANDLE)) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer; Status = ObReferenceObjectByHandle( Handle, 0, *IoFileObjectType, KernelMode, (void **)&FileObject, NULL ); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } else { ObDereferenceObject(FileObject); DeviceObject = FileObject->DeviceObject; } RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: FileObject=%xh ...\n", FileObject)); ExAcquireResourceExclusiveLite( &RfsdGlobal->Resource, TRUE ); GlobalResourceAcquired = TRUE; ListEntry = RfsdGlobal->VcbList.Flink; while (ListEntry != &RfsdGlobal->VcbList) { PRFSD_VCB Vcb; Vcb = CONTAINING_RECORD(ListEntry, RFSD_VCB, Next); ListEntry = ListEntry->Flink; RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh...\n", Vcb, Vcb->Vpb)); if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject)) { ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: RfsdPurgeVolume...\n")); RfsdPurgeVolume(Vcb, FALSE); ClearFlag(Vcb->Flags, VCB_MOUNTED); ExReleaseResourceLite(&Vcb->MainResource); // // Vcb is still attached on the list ...... // if (ListEntry->Blink == &Vcb->Next) { RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: RfsdCheckDismount...\n")); RfsdCheckDismount(IrpContext, Vcb, FALSE); } } } } _SEH2_FINALLY { if (GlobalResourceAcquired) { ExReleaseResourceForThreadLite( &RfsdGlobal->Resource, ExGetCurrentResourceThread() ); } RfsdCompleteIrpContext(IrpContext, Status); } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS RfsdPurgeVolume (IN PRFSD_VCB Vcb, IN BOOLEAN FlushBeforePurge ) { PRFSD_FCB Fcb; LIST_ENTRY FcbList; PLIST_ENTRY ListEntry; PFCB_LIST_ENTRY FcbListEntry; PAGED_CODE(); _SEH2_TRY { ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == RFSDVCB) && (Vcb->Identifier.Size == sizeof(RFSD_VCB))); if ( IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) { FlushBeforePurge = FALSE; } FcbListEntry= NULL; InitializeListHead(&FcbList); for (ListEntry = Vcb->FcbList.Flink; ListEntry != &Vcb->FcbList; ListEntry = ListEntry->Flink ) { Fcb = CONTAINING_RECORD(ListEntry, RFSD_FCB, Next); Fcb->ReferenceCount++; RfsdPrint((DBG_INFO, "RfsdPurgeVolume: %s refercount=%xh\n", Fcb->AnsiFileName.Buffer, Fcb->ReferenceCount)); FcbListEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FCB_LIST_ENTRY), RFSD_POOL_TAG); if (FcbListEntry) { FcbListEntry->Fcb = Fcb; InsertTailList(&FcbList, &FcbListEntry->Next); } else { RfsdPrint((DBG_ERROR, "RfsdPurgeVolume: Error allocating FcbListEntry ...\n")); } } while (!IsListEmpty(&FcbList)) { ListEntry = RemoveHeadList(&FcbList); FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next); Fcb = FcbListEntry->Fcb; if (ExAcquireResourceExclusiveLite( &Fcb->MainResource, TRUE )) { RfsdPurgeFile(Fcb, FlushBeforePurge); if (!Fcb->OpenHandleCount && Fcb->ReferenceCount == 1) { RemoveEntryList(&Fcb->Next); RfsdFreeFcb(Fcb); } else { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread()); } } ExFreePool(FcbListEntry); } if (FlushBeforePurge) { ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); ExReleaseResourceLite(&Vcb->PagingIoResource); CcFlushCache(&Vcb->SectionObject, NULL, 0, NULL); } if (Vcb->SectionObject.ImageSectionObject) { MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite); } if (Vcb->SectionObject.DataSectionObject) { CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE); } RfsdPrint((DBG_INFO, "RfsdPurgeVolume: Volume flushed and purged.\n")); } _SEH2_FINALLY { // Nothing } _SEH2_END; return STATUS_SUCCESS; }
PFFS_MCB FFSAllocateMcb( PFFS_VCB Vcb, PUNICODE_STRING FileName, ULONG FileAttr) { PFFS_MCB Mcb = NULL; PLIST_ENTRY List = NULL; ULONG Extra = 0; #define MCB_NUM_SHIFT 0x04 if (FFSGlobal->McbAllocated > (FFSGlobal->MaxDepth << MCB_NUM_SHIFT)) Extra = FFSGlobal->McbAllocated - (FFSGlobal->MaxDepth << MCB_NUM_SHIFT) + FFSGlobal->MaxDepth; FFSPrint((DBG_INFO, "FFSAllocateMcb: CurrDepth=%xh/%xh/%xh FileName=%S\n", FFSGlobal->McbAllocated, FFSGlobal->MaxDepth << MCB_NUM_SHIFT, FFSGlobal->FcbAllocated, FileName->Buffer)); List = Vcb->McbList.Flink; while ((List != &(Vcb->McbList)) && (Extra > 0)) { Mcb = CONTAINING_RECORD(List, FFS_MCB, Link); List = List->Flink; if ((Mcb->Inode != 2) && (Mcb->Child == NULL) && (Mcb->FFSFcb == NULL) && (!IsMcbUsed(Mcb))) { FFSPrint((DBG_INFO, "FFSAllocateMcb: Mcb %S will be freed.\n", Mcb->ShortName.Buffer)); if (FFSDeleteMcbNode(Vcb, Vcb->McbTree, Mcb)) { FFSFreeMcb(Mcb); Extra--; } } } ExAcquireResourceExclusiveLite( &FFSGlobal->LAResource, TRUE); Mcb = (PFFS_MCB)(ExAllocateFromPagedLookasideList( &(FFSGlobal->FFSMcbLookasideList))); ExReleaseResourceForThreadLite( &FFSGlobal->LAResource, ExGetCurrentResourceThread()); if (Mcb == NULL) { Mcb = (PFFS_MCB)ExAllocatePool(PagedPool, sizeof(FFS_MCB)); RtlZeroMemory(Mcb, sizeof(FFS_MCB)); SetFlag(Mcb->Flags, MCB_FROM_POOL); } else { RtlZeroMemory(Mcb, sizeof(FFS_MCB)); } if (!Mcb) { return NULL; } Mcb->Identifier.Type = FFSMCB; Mcb->Identifier.Size = sizeof(FFS_MCB); if (FileName && FileName->Length) { Mcb->ShortName.Length = FileName->Length; Mcb->ShortName.MaximumLength = Mcb->ShortName.Length + 2; Mcb->ShortName.Buffer = ExAllocatePool(PagedPool, Mcb->ShortName.MaximumLength); if (!Mcb->ShortName.Buffer) goto errorout; RtlZeroMemory(Mcb->ShortName.Buffer, Mcb->ShortName.MaximumLength); RtlCopyMemory(Mcb->ShortName.Buffer, FileName->Buffer, Mcb->ShortName.Length); } Mcb->FileAttr = FileAttr; ExAcquireResourceExclusiveLite( &FFSGlobal->CountResource, TRUE); FFSGlobal->McbAllocated++; ExReleaseResourceForThreadLite( &FFSGlobal->CountResource, ExGetCurrentResourceThread()); return Mcb; errorout: if (Mcb) { if (Mcb->ShortName.Buffer) ExFreePool(Mcb->ShortName.Buffer); if (FlagOn(Mcb->Flags, MCB_FROM_POOL)) { ExFreePool(Mcb); } else { ExAcquireResourceExclusiveLite( &FFSGlobal->LAResource, TRUE); ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb); ExReleaseResourceForThreadLite( &FFSGlobal->LAResource, ExGetCurrentResourceThread()); } } return NULL; }
__drv_mustHoldCriticalRegion NTSTATUS FFSVerifyVolume( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_SUPER_BLOCK FFSSb = NULL; PFFS_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN GlobalResourceAcquired = FALSE; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; ULONG ChangeCount; ULONG dwReturn; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } ExAcquireResourceExclusiveLite( &FFSGlobal->Resource, TRUE); GlobalResourceAcquired = TRUE; Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE; if (!FlagOn(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (!IsMounted(Vcb)) { Status = STATUS_WRONG_VOLUME; _SEH2_LEAVE; } dwReturn = sizeof(ULONG); Status = FFSDiskIoControl( Vcb->TargetDeviceObject, IOCTL_DISK_CHECK_VERIFY, NULL, 0, &ChangeCount, &dwReturn); if (ChangeCount != Vcb->ChangeCount) { Status = STATUS_WRONG_VOLUME; _SEH2_LEAVE; } Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); if (((((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS1)) != NULL) && (FFSSb->fs_magic == FS_UFS1_MAGIC)) || (((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS2)) != NULL) && (FFSSb->fs_magic == FS_UFS2_MAGIC))) && (memcmp(FFSSb->fs_id, SUPER_BLOCK->fs_id, 8) == 0) && (memcmp(FFSSb->fs_volname, SUPER_BLOCK->fs_volname, 16) == 0)) { ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); if (FFSIsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject)) { SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } else { ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify succeeded.\n")); Status = STATUS_SUCCESS; } else { Status = STATUS_WRONG_VOLUME; FFSPurgeVolume(Vcb, FALSE); SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify failed.\n")); } } _SEH2_FINALLY { if (FFSSb) ExFreePool(FFSSb); if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (GlobalResourceAcquired) { ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSClose( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_SUCCESS; PFFS_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; PFILE_OBJECT FileObject; PFFS_FCB Fcb = 0; BOOLEAN FcbResourceAcquired = FALSE; PFFS_CCB Ccb; BOOLEAN FreeVcb = FALSE; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } Vcb = (PFFS_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, IrpContext->IsSynchronous)) { FFSPrint((DBG_INFO, "FFSClose: PENDING ... Vcb: %xh/%xh\n", Vcb->OpenFileHandleCount, Vcb->ReferenceCount)); Status = STATUS_PENDING; _SEH2_LEAVE; } VcbResourceAcquired = TRUE; FileObject = IrpContext->FileObject; if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) { Fcb = IrpContext->Fcb; Ccb = IrpContext->Ccb; } else { Fcb = (PFFS_FCB)FileObject->FsContext; if (!Fcb) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } ASSERT(Fcb != NULL); Ccb = (PFFS_CCB)FileObject->FsContext2; } if (Fcb->Identifier.Type == FFSVCB) { Vcb->ReferenceCount--; if (!Vcb->ReferenceCount && FlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { FreeVcb = TRUE; } if (Ccb) { FFSFreeCcb(Ccb); if (FileObject) { FileObject->FsContext2 = Ccb = NULL; } } Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (Fcb->Identifier.Type != FFSFCB || Fcb->Identifier.Size != sizeof(FFS_FCB)) { #if DBG FFSPrint((DBG_ERROR, "FFSClose: Strange IRP_MJ_CLOSE by system!\n")); ExAcquireResourceExclusiveLite( &FFSGlobal->CountResource, TRUE); FFSGlobal->IRPCloseCount++; ExReleaseResourceForThreadLite( &FFSGlobal->CountResource, ExGetCurrentResourceThread()); #endif _SEH2_LEAVE; } ASSERT((Fcb->Identifier.Type == FFSFCB) && (Fcb->Identifier.Size == sizeof(FFS_FCB))); /* if ((!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) && (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE))) */ { if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbResourceAcquired = TRUE; } if (!Ccb) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } ASSERT((Ccb->Identifier.Type == FFSCCB) && (Ccb->Identifier.Size == sizeof(FFS_CCB))); Fcb->ReferenceCount--; Vcb->ReferenceCount--; if (!Vcb->ReferenceCount && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { FreeVcb = TRUE; } FFSPrint((DBG_INFO, "FFSClose: OpenHandleCount: %u ReferenceCount: %u %s\n", Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer)); if (Ccb) { FFSFreeCcb(Ccb); if (FileObject) { FileObject->FsContext2 = Ccb = NULL; } } if (!Fcb->ReferenceCount) { // // Remove Fcb from Vcb->FcbList ... // RemoveEntryList(&Fcb->Next); FFSFreeFcb(Fcb); FcbResourceAcquired = FALSE; } Status = STATUS_SUCCESS; } _SEH2_FINALLY { if (FcbResourceAcquired) { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread()); } if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { FFSQueueCloseRequest(IrpContext); #if 0 /* Status = STATUS_SUCCESS; if (IrpContext->Irp != NULL) { IrpContext->Irp->IoStatus.Status = Status; FFSCompleteRequest( IrpContext->Irp, (BOOLEAN)!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED), (CCHAR) (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)); IrpContext->Irp = NULL; } */ #endif } else { FFSCompleteIrpContext(IrpContext, Status); if (FreeVcb) { ExAcquireResourceExclusiveLite( &FFSGlobal->Resource, TRUE); FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED); FFSRemoveVcb(Vcb); ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); FFSFreeVcb(Vcb); } } } } _SEH2_END; return Status; }
VOID FFSFreeFcb( IN PFFS_FCB Fcb) { PFFS_VCB Vcb; ASSERT(Fcb != NULL); ASSERT((Fcb->Identifier.Type == FFSFCB) && (Fcb->Identifier.Size == sizeof(FFS_FCB))); Vcb = Fcb->Vcb; FsRtlUninitializeFileLock(&Fcb->FileLockAnchor); ExDeleteResourceLite(&Fcb->MainResource); ExDeleteResourceLite(&Fcb->PagingIoResource); Fcb->FFSMcb->FFSFcb = NULL; if(IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) { if (Fcb->FFSMcb) { FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb); FFSFreeMcb(Fcb->FFSMcb); } } if (Fcb->LongName.Buffer) { ExFreePool(Fcb->LongName.Buffer); Fcb->LongName.Buffer = NULL; } #if DBG ExFreePool(Fcb->AnsiFileName.Buffer); #endif if (FS_VERSION == 1) { ExFreePool(Fcb->dinode1); } else { ExFreePool(Fcb->dinode2); } Fcb->Header.NodeTypeCode = (SHORT)0xCCCC; Fcb->Header.NodeByteSize = (SHORT)0xC0C0; if (FlagOn(Fcb->Flags, FCB_FROM_POOL)) { ExFreePool(Fcb); } else { ExAcquireResourceExclusiveLite( &FFSGlobal->LAResource, TRUE); ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb); ExReleaseResourceForThreadLite( &FFSGlobal->LAResource, ExGetCurrentResourceThread()); } #if DBG ExAcquireResourceExclusiveLite( &FFSGlobal->CountResource, TRUE); FFSGlobal->FcbAllocated--; ExReleaseResourceForThreadLite( &FFSGlobal->CountResource, ExGetCurrentResourceThread()); #endif }
__drv_mustHoldCriticalRegion BOOLEAN FFSCheckDismount( IN PFFS_IRP_CONTEXT IrpContext, IN PFFS_VCB Vcb, IN BOOLEAN bForce) { KIRQL Irql; PVPB Vpb = Vcb->Vpb; BOOLEAN bDeleted = FALSE; ULONG UnCleanCount = 0; PAGED_CODE(); ExAcquireResourceExclusiveLite( &FFSGlobal->Resource, TRUE); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE); if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && (IrpContext->RealDevice == Vcb->RealDevice)) { UnCleanCount = 3; } else { UnCleanCount = 2; } IoAcquireVpbSpinLock(&Irql); if ((Vpb->ReferenceCount == UnCleanCount) || bForce) { if ((Vpb->ReferenceCount != UnCleanCount) && bForce) { FFSBreakPoint(); } ClearFlag(Vpb->Flags, VPB_MOUNTED); ClearFlag(Vpb->Flags, VPB_LOCKED); if ((Vcb->RealDevice != Vpb->RealDevice) && #ifdef _MSC_VER #pragma prefast( suppress: 28175, "allowed in file system drivers" ) #endif (Vcb->RealDevice->Vpb == Vpb)) { SetFlag(Vcb->RealDevice->Flags, DO_DEVICE_INITIALIZING); SetFlag(Vpb->Flags, VPB_PERSISTENT); } FFSRemoveVcb(Vcb); ClearFlag(Vpb->Flags, VPB_MOUNTED); SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); Vpb->DeviceObject = NULL; bDeleted = TRUE; } #if 0 else if ((Vpb->RealDevice->Vpb == Vpb) && bForce) { PVPB NewVpb; #define TAG_VPB ' bpV' NewVpb = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, sizeof(VPB), TAG_VPB); NewVpb->Type = IO_TYPE_VPB; NewVpb->Size = sizeof(VPB); NewVpb->RealDevice = Vcb->Vpb->RealDevice; NewVpb->RealDevice->Vpb = NewVpb; NewVpb->Flags = FlagOn(Vcb->Vpb->Flags, VPB_REMOVE_PENDING); NewVpb = NULL; ClearFlag(Vcb->Flags, VCB_MOUNTED); ClearFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); } #endif IoReleaseVpbSpinLock(Irql); ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); if (bDeleted) { #if 0 FFSBreakPoint(); /* XP에서 브레이크 포인트 발생 */ #endif FFSFreeVcb(Vcb); } return bDeleted; }
__drv_mustHoldCriticalRegion NTSTATUS FFSLockVolume( IN PFFS_IRP_CONTEXT IrpContext) { PIO_STACK_LOCATION IrpSp; PDEVICE_OBJECT DeviceObject; PFFS_VCB Vcb = 0; NTSTATUS Status; BOOLEAN VcbResourceAcquired = FALSE; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; Status = STATUS_UNSUCCESSFUL; // // This request is not allowed on the main device object // if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp); #if (_WIN32_WINNT >= 0x0500) CcWaitForCurrentLazyWriterActivity(); #endif ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE; Status = FFSLockVcb(Vcb, IrpSp->FileObject); } _SEH2_FINALLY { if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion BOOLEAN RfsdCheckDismount ( IN PRFSD_IRP_CONTEXT IrpContext, IN PRFSD_VCB Vcb, IN BOOLEAN bForce ) { KIRQL Irql; PVPB Vpb = Vcb->Vpb; BOOLEAN bDeleted = FALSE; ULONG UnCleanCount = 0; PAGED_CODE(); ExAcquireResourceExclusiveLite( &RfsdGlobal->Resource, TRUE ); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && (IrpContext->RealDevice == Vcb->RealDevice)) { UnCleanCount = 3; } else { UnCleanCount = 2; } IoAcquireVpbSpinLock (&Irql); if ((Vpb->ReferenceCount == UnCleanCount) || bForce) { if ((Vpb->ReferenceCount != UnCleanCount) && bForce) { KdPrint(("RfsdCheckDismount: force dismount ...\n")); } ClearFlag( Vpb->Flags, VPB_MOUNTED ); ClearFlag( Vpb->Flags, VPB_LOCKED ); #ifdef _MSC_VER #pragma prefast( suppress: 28175, "allowed in file system drivers" ) #endif if ((Vcb->RealDevice != Vpb->RealDevice) && (Vcb->RealDevice->Vpb == Vpb)) { SetFlag( Vcb->RealDevice->Flags, DO_DEVICE_INITIALIZING ); SetFlag( Vpb->Flags, VPB_PERSISTENT ); } RfsdRemoveVcb(Vcb); ClearFlag(Vpb->Flags, VPB_MOUNTED); SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); Vpb->DeviceObject = NULL; bDeleted = TRUE; } IoReleaseVpbSpinLock(Irql); ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); ExReleaseResourceForThreadLite( &RfsdGlobal->Resource, ExGetCurrentResourceThread() ); if (bDeleted) { KdPrint(("RfsdCheckDismount: now free the vcb ...\n")); RfsdFreeVcb(Vcb); } return bDeleted; }
__drv_mustHoldCriticalRegion NTSTATUS FFSMountVolume( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT MainDeviceObject; BOOLEAN GlobalDataResourceAcquired = FALSE; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; PDEVICE_OBJECT TargetDeviceObject; NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME; PDEVICE_OBJECT VolumeDeviceObject = NULL; PFFS_VCB Vcb; PFFS_SUPER_BLOCK FFSSb = NULL; ULONG dwBytes; DISK_GEOMETRY DiskGeometry; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); MainDeviceObject = IrpContext->DeviceObject; // // Make sure we can wait. // SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); // // This request is only allowed on the main device object // if (MainDeviceObject != FFSGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } ExAcquireResourceExclusiveLite( &(FFSGlobal->Resource), TRUE); GlobalDataResourceAcquired = TRUE; if (FlagOn(FFSGlobal->Flags, FFS_UNLOAD_PENDING)) { Status = STATUS_UNRECOGNIZED_VOLUME; _SEH2_LEAVE; } Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); TargetDeviceObject = IoStackLocation->Parameters.MountVolume.DeviceObject; dwBytes = sizeof(DISK_GEOMETRY); Status = FFSDiskIoControl( TargetDeviceObject, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DiskGeometry, &dwBytes); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } Status = IoCreateDevice( MainDeviceObject->DriverObject, sizeof(FFS_VCB), NULL, FILE_DEVICE_DISK_FILE_SYSTEM, 0, FALSE, &VolumeDeviceObject); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1); if (TargetDeviceObject->AlignmentRequirement > VolumeDeviceObject->AlignmentRequirement) { VolumeDeviceObject->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement; } (IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject = VolumeDeviceObject; Vcb = (PFFS_VCB)VolumeDeviceObject->DeviceExtension; RtlZeroMemory(Vcb, sizeof(FFS_VCB)); Vcb->Identifier.Type = FFSVCB; Vcb->Identifier.Size = sizeof(FFS_VCB); Vcb->TargetDeviceObject = TargetDeviceObject; Vcb->DiskGeometry = DiskGeometry; Status = FFSLoadDiskLabel(TargetDeviceObject, Vcb); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } FFSSb = Vcb->ffs_super_block; Vcb->BlockSize = FFSSb->fs_bsize; Vcb->SectorBits = FFSLog2(SECTOR_SIZE); Status = FFSInitializeVcb(IrpContext, Vcb, FFSSb, TargetDeviceObject, VolumeDeviceObject, IoStackLocation->Parameters.MountVolume.Vpb); if (NT_SUCCESS(Status)) { if (FFSIsMediaWriteProtected(IrpContext, TargetDeviceObject)) { SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } else { ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } SetFlag(Vcb->Flags, VCB_MOUNTED); FFSInsertVcb(Vcb); ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); } } _SEH2_FINALLY { if (GlobalDataResourceAcquired) { ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); } if (!NT_SUCCESS(Status)) { if (FFSSb) { ExFreePool(FFSSb); } if (VolumeDeviceObject) { IoDeleteDevice(VolumeDeviceObject); } } if (!IrpContext->ExceptionInProgress) { if (NT_SUCCESS(Status)) { ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); } FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS RfsdUnlockVolume ( IN PRFSD_IRP_CONTEXT IrpContext ) { PIO_STACK_LOCATION IrpSp; PDEVICE_OBJECT DeviceObject; NTSTATUS Status; PRFSD_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == RFSDICX) && (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == RfsdGlobal->DeviceObject) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == RFSDVCB) && (Vcb->Identifier.Size == sizeof(RFSD_VCB))); ASSERT(IsMounted(Vcb)); IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); VcbResourceAcquired = TRUE; Status = RfsdUnlockVcb(Vcb, IrpSp->FileObject); } _SEH2_FINALLY { if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); } if (!IrpContext->ExceptionInProgress) { RfsdCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSQueryDirectory( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_VCB Vcb = 0; PFILE_OBJECT FileObject; PFFS_FCB Fcb = 0; PFFS_CCB Ccb; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; FILE_INFORMATION_CLASS FileInformationClass; ULONG Length; PUNICODE_STRING FileName; ULONG FileIndex; BOOLEAN RestartScan; BOOLEAN ReturnSingleEntry; BOOLEAN IndexSpecified; PUCHAR Buffer; BOOLEAN FirstQuery; PFFSv1_INODE dinode1 = NULL; PFFSv2_INODE dinode2 = NULL; BOOLEAN FcbResourceAcquired = FALSE; ULONG UsedLength = 0; USHORT InodeFileNameLength; UNICODE_STRING InodeFileName; PFFS_DIR_ENTRY pDir = NULL; ULONG dwBytes; ULONG dwTemp = 0; ULONG dwSize = 0; ULONG dwReturn = 0; BOOLEAN bRun = TRUE; ULONG ByteOffset; PAGED_CODE(); InodeFileName.Buffer = NULL; _SEH2_TRY { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); FileObject = IrpContext->FileObject; Fcb = (PFFS_FCB)FileObject->FsContext; ASSERT(Fcb); // // This request is not allowed on volumes // if (Fcb->Identifier.Type == FFSVCB) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } ASSERT((Fcb->Identifier.Type == FFSFCB) && (Fcb->Identifier.Size == sizeof(FFS_FCB))); if (!IsDirectory(Fcb)) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Ccb = (PFFS_CCB)FileObject->FsContext2; ASSERT(Ccb); ASSERT((Ccb->Identifier.Type == FFSCCB) && (Ccb->Identifier.Size == sizeof(FFS_CCB))); Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); #if !defined(_GNU_NTIFS_) || defined(__REACTOS__) FileInformationClass = IoStackLocation->Parameters.QueryDirectory.FileInformationClass; Length = IoStackLocation->Parameters.QueryDirectory.Length; FileName = IoStackLocation->Parameters.QueryDirectory.FileName; FileIndex = IoStackLocation->Parameters.QueryDirectory.FileIndex; #else // _GNU_NTIFS_ FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.QueryDirectory.FileInformationClass; Length = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.QueryDirectory.Length; FileName = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.QueryDirectory.FileName; FileIndex = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.QueryDirectory.FileIndex; #endif // _GNU_NTIFS_ RestartScan = FlagOn(IoStackLocation->Flags, SL_RESTART_SCAN); ReturnSingleEntry = FlagOn(IoStackLocation->Flags, SL_RETURN_SINGLE_ENTRY); IndexSpecified = FlagOn(IoStackLocation->Flags, SL_INDEX_SPECIFIED); /* if (!Irp->MdlAddress && Irp->UserBuffer) { ProbeForWrite(Irp->UserBuffer, Length, 1); } */ Buffer = FFSGetUserBuffer(Irp); if (Buffer == NULL) { FFSBreakPoint(); Status = STATUS_INVALID_USER_BUFFER; _SEH2_LEAVE; } if (!IrpContext->IsSynchronous) { Status = STATUS_PENDING; _SEH2_LEAVE; } if (!ExAcquireResourceSharedLite( &Fcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbResourceAcquired = TRUE; if (FileName != NULL) { if (Ccb->DirectorySearchPattern.Buffer != NULL) { FirstQuery = FALSE; } else { FirstQuery = TRUE; Ccb->DirectorySearchPattern.Length = Ccb->DirectorySearchPattern.MaximumLength = FileName->Length; Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(PagedPool, FileName->Length, FFS_POOL_TAG); if (Ccb->DirectorySearchPattern.Buffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } Status = RtlUpcaseUnicodeString( &(Ccb->DirectorySearchPattern), FileName, FALSE); if (!NT_SUCCESS(Status)) _SEH2_LEAVE; } } else if (Ccb->DirectorySearchPattern.Buffer != NULL) { FirstQuery = FALSE; FileName = &Ccb->DirectorySearchPattern; } else { FirstQuery = TRUE; Ccb->DirectorySearchPattern.Length = Ccb->DirectorySearchPattern.MaximumLength = 2; Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(PagedPool, 2, FFS_POOL_TAG); if (Ccb->DirectorySearchPattern.Buffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlCopyMemory( Ccb->DirectorySearchPattern.Buffer, L"*\0", 2); } if (!IndexSpecified) { if (RestartScan || FirstQuery) { FileIndex = Fcb->FFSMcb->DeOffset = 0; } else { FileIndex = Ccb->CurrentByteOffset; } } if (FS_VERSION == 1) { dinode1 = (PFFSv1_INODE)ExAllocatePoolWithTag( PagedPool, DINODE1_SIZE, FFS_POOL_TAG); if (dinode1 == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlZeroMemory(Buffer, Length); if (Fcb->dinode1->di_size <= FileIndex) { Status = STATUS_NO_MORE_FILES; _SEH2_LEAVE; } } else { dinode2 = (PFFSv2_INODE)ExAllocatePoolWithTag( PagedPool, DINODE2_SIZE, FFS_POOL_TAG); if (dinode2 == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlZeroMemory(Buffer, Length); if (Fcb->dinode2->di_size <= FileIndex) { Status = STATUS_NO_MORE_FILES; _SEH2_LEAVE; } } pDir = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_DIR_ENTRY), FFS_POOL_TAG); if (!pDir) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } if (FS_VERSION == 1) { dwBytes = 0; dwSize = (ULONG)Fcb->dinode1->di_size - FileIndex - (sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1); ByteOffset = FileIndex; dwTemp = 0; while (bRun && UsedLength < Length && dwBytes < dwSize) { OEM_STRING OemName; RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY)); Status = FFSv1ReadInode( NULL, Vcb, Fcb->dinode1, ByteOffset, (PVOID)pDir, sizeof(FFS_DIR_ENTRY), &dwReturn); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } if (!pDir->d_ino) { if (pDir->d_reclen == 0) { FFSBreakPoint(); _SEH2_LEAVE; } goto ProcessNextEntryv1; } OemName.Buffer = pDir->d_name; OemName.Length = (pDir->d_namlen & 0xff); OemName.MaximumLength = OemName.Length; #if 0 /* // // We could not filter the files: "." and ".." // if ((OemName.Length >) 1 && OemName.Buffer[0] == '.') { if ( OemName.Length == 2 && OemName.Buffer[1] == '.') { } else { goto ProcessNextEntry1; } } */ #endif InodeFileNameLength = (USHORT) RtlOemStringToUnicodeSize(&OemName); InodeFileName.Length = 0; InodeFileName.MaximumLength = InodeFileNameLength + 2; if (InodeFileNameLength <= 0) { break; } InodeFileName.Buffer = ExAllocatePoolWithTag( PagedPool, InodeFileNameLength + 2, FFS_POOL_TAG); if (!InodeFileName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlZeroMemory( InodeFileName.Buffer, InodeFileNameLength + 2); Status = FFSOEMToUnicode(&InodeFileName, &OemName); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } if (FsRtlDoesNameContainWildCards( &(Ccb->DirectorySearchPattern)) ? FsRtlIsNameInExpression( &(Ccb->DirectorySearchPattern), &InodeFileName, TRUE, NULL) : !RtlCompareUnicodeString( &(Ccb->DirectorySearchPattern), &InodeFileName, TRUE)) { dwReturn = FFSProcessDirEntry( Vcb, FileInformationClass, pDir->d_ino, Buffer, UsedLength, Length - UsedLength, (FileIndex + dwBytes), &InodeFileName, ReturnSingleEntry); if (dwReturn <= 0) { bRun = FALSE; } else { dwTemp = UsedLength; UsedLength += dwReturn; } } if (InodeFileName.Buffer != NULL) { ExFreePool(InodeFileName.Buffer); InodeFileName.Buffer = NULL; } ProcessNextEntryv1: if (bRun) { dwBytes +=pDir->d_reclen; Ccb->CurrentByteOffset = FileIndex + dwBytes; } if (UsedLength && ReturnSingleEntry) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } ByteOffset = FileIndex + dwBytes; } } else { dwBytes = 0; dwSize = (ULONG)Fcb->dinode2->di_size - FileIndex - (sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1); ByteOffset = FileIndex; dwTemp = 0; while (bRun && UsedLength < Length && dwBytes < dwSize) { OEM_STRING OemName; RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY)); Status = FFSv2ReadInode( NULL, Vcb, Fcb->dinode2, ByteOffset, (PVOID)pDir, sizeof(FFS_DIR_ENTRY), &dwReturn); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } if (!pDir->d_ino) { if (pDir->d_reclen == 0) { FFSBreakPoint(); _SEH2_LEAVE; } goto ProcessNextEntryv2; } OemName.Buffer = pDir->d_name; OemName.Length = (pDir->d_namlen & 0xff); OemName.MaximumLength = OemName.Length; #if 0 /* // // We could not filter the files: "." and ".." // if ((OemName.Length >) 1 && OemName.Buffer[0] == '.') { if ( OemName.Length == 2 && OemName.Buffer[1] == '.') { } else { goto ProcessNextEntry2; } } */ #endif InodeFileNameLength = (USHORT) RtlOemStringToUnicodeSize(&OemName); InodeFileName.Length = 0; InodeFileName.MaximumLength = InodeFileNameLength + 2; if (InodeFileNameLength <= 0) { break; } InodeFileName.Buffer = ExAllocatePoolWithTag( PagedPool, InodeFileNameLength + 2, FFS_POOL_TAG); if (!InodeFileName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlZeroMemory( InodeFileName.Buffer, InodeFileNameLength + 2); Status = FFSOEMToUnicode(&InodeFileName, &OemName); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } if (FsRtlDoesNameContainWildCards( &(Ccb->DirectorySearchPattern)) ? FsRtlIsNameInExpression( &(Ccb->DirectorySearchPattern), &InodeFileName, TRUE, NULL) : !RtlCompareUnicodeString( &(Ccb->DirectorySearchPattern), &InodeFileName, TRUE)) { dwReturn = FFSProcessDirEntry( Vcb, FileInformationClass, pDir->d_ino, Buffer, UsedLength, Length - UsedLength, (FileIndex + dwBytes), &InodeFileName, ReturnSingleEntry); if (dwReturn <= 0) { bRun = FALSE; } else { dwTemp = UsedLength; UsedLength += dwReturn; } } if (InodeFileName.Buffer != NULL) { ExFreePool(InodeFileName.Buffer); InodeFileName.Buffer = NULL; } ProcessNextEntryv2: if (bRun) { dwBytes +=pDir->d_reclen; Ccb->CurrentByteOffset = FileIndex + dwBytes; } if (UsedLength && ReturnSingleEntry) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } ByteOffset = FileIndex + dwBytes; } } FileIndex += dwBytes; ((PULONG)((PUCHAR)Buffer + dwTemp)) [0] = 0; if (!UsedLength) { if (FirstQuery) { Status = STATUS_NO_SUCH_FILE; } else { Status = STATUS_NO_MORE_FILES; } } else { Status = STATUS_SUCCESS; } } _SEH2_FINALLY { if (FcbResourceAcquired) { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread()); } if (FS_VERSION == 1) { if (dinode1 != NULL) { ExFreePool(dinode1); } } else { if (dinode2 != NULL) { ExFreePool(dinode2); } } if (pDir != NULL) { ExFreePool(pDir); pDir = NULL; } if (InodeFileName.Buffer != NULL) { ExFreePool(InodeFileName.Buffer); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoWriteAccess); if (NT_SUCCESS(Status)) { Status = FFSQueueRequest(IrpContext); } else { FFSCompleteIrpContext(IrpContext, Status); } } else { IrpContext->Irp->IoStatus.Information = UsedLength; FFSCompleteIrpContext(IrpContext, Status); } } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS RfsdMountVolume (IN PRFSD_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT MainDeviceObject; BOOLEAN GlobalDataResourceAcquired = FALSE; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; PDEVICE_OBJECT TargetDeviceObject; NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME; PDEVICE_OBJECT VolumeDeviceObject = NULL; PRFSD_VCB Vcb; PRFSD_SUPER_BLOCK RfsdSb = NULL; ULONG dwBytes; DISK_GEOMETRY DiskGeometry; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == RFSDICX) && (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT))); MainDeviceObject = IrpContext->DeviceObject; // // Make sure we can wait. // SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); // // This request is only allowed on the main device object // if (MainDeviceObject != RfsdGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } ExAcquireResourceExclusiveLite( &(RfsdGlobal->Resource), TRUE ); GlobalDataResourceAcquired = TRUE; if (FlagOn(RfsdGlobal->Flags, RFSD_UNLOAD_PENDING)) { Status = STATUS_UNRECOGNIZED_VOLUME; _SEH2_LEAVE; } Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); TargetDeviceObject = IoStackLocation->Parameters.MountVolume.DeviceObject; dwBytes = sizeof(DISK_GEOMETRY); Status = RfsdDiskIoControl( TargetDeviceObject, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DiskGeometry, &dwBytes ); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } Status = IoCreateDevice( MainDeviceObject->DriverObject, sizeof(RFSD_VCB), NULL, FILE_DEVICE_DISK_FILE_SYSTEM, 0, FALSE, &VolumeDeviceObject ); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1); if (TargetDeviceObject->AlignmentRequirement > VolumeDeviceObject->AlignmentRequirement) { VolumeDeviceObject->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement; } (IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject = VolumeDeviceObject; Vcb = (PRFSD_VCB) VolumeDeviceObject->DeviceExtension; RtlZeroMemory(Vcb, sizeof(RFSD_VCB)); Vcb->Identifier.Type = RFSDVCB; Vcb->Identifier.Size = sizeof(RFSD_VCB); Vcb->TargetDeviceObject = TargetDeviceObject; Vcb->DiskGeometry = DiskGeometry; RfsdSb = RfsdLoadSuper(Vcb, FALSE); if (RfsdSb) { if ( SuperblockContainsMagicKey(RfsdSb) ) { RfsdPrint((DBG_INFO, "Volume of ReiserFS rfsd file system is found.\n")); Status = STATUS_SUCCESS; } else { Status = STATUS_UNRECOGNIZED_VOLUME; } } if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } Vcb->BlockSize = RfsdSb->s_blocksize; // NOTE: FFS also does this here, since LoadGroup is not called in the non-ext2 drivers Vcb->GroupDesc = NULL; // NOTE: GroupDesc is not used for ReiserFS. Setting it to NULL will keep other code from barfing. // Vcb->SectorBits = RFSDLog(SECTOR_SIZE); // NOTE: SectorBits are unused for ReiserFS Status = RfsdInitializeVcb(IrpContext, Vcb, RfsdSb, TargetDeviceObject, VolumeDeviceObject, IoStackLocation->Parameters.MountVolume.Vpb); if (NT_SUCCESS(Status)) { if (RfsdIsMediaWriteProtected(IrpContext, TargetDeviceObject)) { SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } else { ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } SetFlag(Vcb->Flags, VCB_MOUNTED); RfsdInsertVcb(Vcb); ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); } } _SEH2_FINALLY { if (GlobalDataResourceAcquired) { ExReleaseResourceForThreadLite( &RfsdGlobal->Resource, ExGetCurrentResourceThread() ); } if (!NT_SUCCESS(Status)) { if (RfsdSb) { ExFreePool(RfsdSb); } if (VolumeDeviceObject) { IoDeleteDevice(VolumeDeviceObject); } } if (!IrpContext->ExceptionInProgress) { if (NT_SUCCESS(Status)) { ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); } RfsdCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSNotifyChangeDirectory( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; BOOLEAN CompleteRequest; NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_VCB Vcb; PFILE_OBJECT FileObject; PFFS_FCB Fcb = 0; PIRP Irp; PIO_STACK_LOCATION IrpSp; ULONG CompletionFilter; BOOLEAN WatchTree; BOOLEAN bFcbAcquired = FALSE; PUNICODE_STRING FullName; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); // // Always set the wait flag in the Irp context for the original request. // SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); DeviceObject = IrpContext->DeviceObject; if (DeviceObject == FFSGlobal->DeviceObject) { CompleteRequest = TRUE; Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); FileObject = IrpContext->FileObject; Fcb = (PFFS_FCB)FileObject->FsContext; ASSERT(Fcb); if (Fcb->Identifier.Type == FFSVCB) { FFSBreakPoint(); CompleteRequest = TRUE; Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } ASSERT((Fcb->Identifier.Type == FFSFCB) && (Fcb->Identifier.Size == sizeof(FFS_FCB))); if (!IsDirectory(Fcb)) { FFSBreakPoint(); CompleteRequest = TRUE; Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } if (ExAcquireResourceExclusiveLite( &Fcb->MainResource, TRUE)) { bFcbAcquired = TRUE; } else { Status = STATUS_PENDING; _SEH2_LEAVE; } Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp); #if !defined(_GNU_NTIFS_) || defined(__REACTOS__) CompletionFilter = IrpSp->Parameters.NotifyDirectory.CompletionFilter; #else // _GNU_NTIFS_ CompletionFilter = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.NotifyDirectory.CompletionFilter; #endif // _GNU_NTIFS_ WatchTree = IsFlagOn(IrpSp->Flags, SL_WATCH_TREE); if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { Status = STATUS_DELETE_PENDING; _SEH2_LEAVE; } FullName = &Fcb->LongName; if (FullName->Buffer == NULL) { if (!FFSGetFullFileName(Fcb->FFSMcb, FullName)) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } } FsRtlNotifyFullChangeDirectory(Vcb->NotifySync, &Vcb->NotifyList, FileObject->FsContext2, (PSTRING)FullName, WatchTree, FALSE, CompletionFilter, Irp, NULL, NULL); CompleteRequest = FALSE; Status = STATUS_PENDING; /* Currently the driver is read-only but here is an example on how to use the FsRtl-functions to report a change: ANSI_STRING TestString; USHORT FileNamePartLength; RtlInitAnsiString(&TestString, "\\ntifs.h"); FileNamePartLength = 7; FsRtlNotifyReportChange( Vcb->NotifySync, // PNOTIFY_SYNC NotifySync &Vcb->NotifyList, // PLIST_ENTRY NotifyList &TestString, // PSTRING FullTargetName &FileNamePartLength, // PUSHORT FileNamePartLength FILE_NOTIFY_CHANGE_NAME // ULONG FilterMatch ); or ANSI_STRING TestString; RtlInitAnsiString(&TestString, "\\ntifs.h"); FsRtlNotifyFullReportChange( Vcb->NotifySync, // PNOTIFY_SYNC NotifySync &Vcb->NotifyList, // PLIST_ENTRY NotifyList &TestString, // PSTRING FullTargetName 1, // USHORT TargetNameOffset NULL, // PSTRING StreamName OPTIONAL NULL, // PSTRING NormalizedParentName OPTIONAL FILE_NOTIFY_CHANGE_NAME, // ULONG FilterMatch 0, // ULONG Action NULL // PVOID TargetContext ); */ } _SEH2_FINALLY { if (bFcbAcquired) { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { if (!CompleteRequest) { IrpContext->Irp = NULL; } FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS RfsdDismountVolume (IN PRFSD_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PRFSD_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == RFSDICX) && (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == RfsdGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == RFSDVCB) && (Vcb->Identifier.Size == sizeof(RFSD_VCB))); ASSERT(IsMounted(Vcb)); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); VcbResourceAcquired = TRUE; if ( IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { Status = STATUS_VOLUME_DISMOUNTED; _SEH2_LEAVE; } /* if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { RfsdPrint((DBG_ERROR, "RfsdDismount: Volume is not locked.\n")); Status = STATUS_ACCESS_DENIED; _SEH2_LEAVE; } */ #if DISABLED RfsdFlushFiles(Vcb, FALSE); RfsdFlushVolume(Vcb, FALSE); RfsdPurgeVolume(Vcb, TRUE); #endif ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); VcbResourceAcquired = FALSE; RfsdCheckDismount(IrpContext, Vcb, TRUE); RfsdPrint((DBG_INFO, "RfsdDismount: Volume dismount pending.\n")); Status = STATUS_SUCCESS; } _SEH2_FINALLY { if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); } if (!IrpContext->ExceptionInProgress) { RfsdCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
PFFS_IRP_CONTEXT FFSAllocateIrpContext( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStackLocation; PFFS_IRP_CONTEXT IrpContext; ASSERT(DeviceObject != NULL); ASSERT(Irp != NULL); IoStackLocation = IoGetCurrentIrpStackLocation(Irp); ExAcquireResourceExclusiveLite( &FFSGlobal->LAResource, TRUE); IrpContext = (PFFS_IRP_CONTEXT)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList))); ExReleaseResourceForThreadLite( &FFSGlobal->LAResource, ExGetCurrentResourceThread()); if (IrpContext == NULL) { IrpContext = ExAllocatePool(NonPagedPool, sizeof(FFS_IRP_CONTEXT)); // // Zero out the irp context and indicate that it is from pool and // not region allocated // RtlZeroMemory(IrpContext, sizeof(FFS_IRP_CONTEXT)); SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL); } else { // // Zero out the irp context and indicate that it is from zone and // not pool allocated // RtlZeroMemory(IrpContext, sizeof(FFS_IRP_CONTEXT)); } if (!IrpContext) { return NULL; } IrpContext->Identifier.Type = FFSICX; IrpContext->Identifier.Size = sizeof(FFS_IRP_CONTEXT); IrpContext->Irp = Irp; IrpContext->MajorFunction = IoStackLocation->MajorFunction; IrpContext->MinorFunction = IoStackLocation->MinorFunction; IrpContext->DeviceObject = DeviceObject; IrpContext->FileObject = IoStackLocation->FileObject; if (IrpContext->FileObject != NULL) { IrpContext->RealDevice = IrpContext->FileObject->DeviceObject; } else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) { if (IoStackLocation->Parameters.MountVolume.Vpb) { IrpContext->RealDevice = IoStackLocation->Parameters.MountVolume.Vpb->RealDevice; } } if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL || IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL || IrpContext->MajorFunction == IRP_MJ_SHUTDOWN) { IrpContext->IsSynchronous = TRUE; } else if (IrpContext->MajorFunction == IRP_MJ_CLEANUP || IrpContext->MajorFunction == IRP_MJ_CLOSE) { IrpContext->IsSynchronous = FALSE; } #if (_WIN32_WINNT >= 0x0500) else if (IrpContext->MajorFunction == IRP_MJ_PNP) { if (IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) { IrpContext->IsSynchronous = TRUE; } else { IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp); } } #endif //(_WIN32_WINNT >= 0x0500) else { IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp); } #if 0 // // Temporary workaround for a bug in close that makes it reference a // fileobject when it is no longer valid. // if (IrpContext->MajorFunction == IRP_MJ_CLOSE) { IrpContext->IsSynchronous = TRUE; } #endif IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp); IrpContext->ExceptionInProgress = FALSE; return IrpContext; }
NTSTATUS Ext2FsdQueryVolumeInformation (IN PFSD_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; PFSD_VCB Vcb = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp = NULL; FS_INFORMATION_CLASS FsInformationClass; ULONG Length; PVOID SystemBuffer = NULL; BOOLEAN VcbResourceAcquired = FALSE; __try { ASSERT (IrpContext != NULL); ASSERT ((IrpContext->Identifier.Type == ICX) && (IrpContext->Identifier.Size == sizeof (FSD_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; ASSERT (DeviceObject); if (DeviceObject == FsdGlobalData.DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Vcb = (PFSD_VCB) DeviceObject->DeviceExtension; ASSERT (Vcb != NULL); ASSERT ((Vcb->Identifier.Type == VCB) && (Vcb->Identifier.Size == sizeof (FSD_VCB))); if (!ExAcquireResourceSharedLite (&Vcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; __leave; } VcbResourceAcquired = TRUE; Irp = IrpContext->Irp; ASSERT (Irp); IrpSp = IoGetCurrentIrpStackLocation (Irp); ASSERT (IrpSp); FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass; Length = IrpSp->Parameters.QueryVolume.Length; SystemBuffer = Irp->AssociatedIrp.SystemBuffer; ASSERT (SystemBuffer); RtlZeroMemory (SystemBuffer, Length); switch (FsInformationClass) { case FileFsVolumeInformation: { PFILE_FS_VOLUME_INFORMATION Buffer; ULONG VolumeLabelLength; ULONG RequiredLength; if (Length < sizeof (FILE_FS_VOLUME_INFORMATION)) { Status = STATUS_INFO_LENGTH_MISMATCH; __leave; } #ifdef TRACE DbgPrint ("Ext2FsdQueryVolumeInformation : FileFsVolumeInformation\n"); #endif Buffer = (PFILE_FS_VOLUME_INFORMATION) SystemBuffer; Buffer->VolumeCreationTime.QuadPart = 0; Buffer->VolumeSerialNumber = 0xAFFE; //It's a joke! VolumeLabelLength = 4 + 1; //Ext2 doesn't have a volume label, so we take 'ext2' Buffer->VolumeLabelLength = VolumeLabelLength * 2; // I don't know what this means. Buffer->SupportsObjects = FALSE; RequiredLength = sizeof (FILE_FS_VOLUME_INFORMATION) + VolumeLabelLength * 2 - sizeof (WCHAR); if (Length < RequiredLength) { DbgPrint ("Ext2FsdQueryVolumeInformation[1] : L=%i RL=%i\n", Length, RequiredLength); Irp->IoStatus.Information = sizeof (FILE_FS_VOLUME_INFORMATION); Status = STATUS_BUFFER_OVERFLOW; __leave; } FsdCharToWchar (Buffer->VolumeLabel, "ext2", VolumeLabelLength); Irp->IoStatus.Information = RequiredLength; Status = STATUS_SUCCESS; __leave; } case FileFsSizeInformation: { PFILE_FS_SIZE_INFORMATION Buffer; #ifdef TRACE DbgPrint ("Ext2FsdQueryVolumeInformation : FileFsSizeInformation\n"); #endif if (Length < sizeof (FILE_FS_SIZE_INFORMATION)) { Status = STATUS_INFO_LENGTH_MISMATCH; __leave; } Buffer = (PFILE_FS_SIZE_INFORMATION) SystemBuffer; // On a readonly filesystem total size is the size of the // contents and available size is zero Buffer->TotalAllocationUnits.QuadPart = 0; //Vcb->ext2->superblock.s_blocks_count; Buffer->AvailableAllocationUnits.QuadPart = 0; //Vcb->ext2->block_size; Buffer->SectorsPerAllocationUnit = Vcb->ext2->block_size / Vcb->DiskGeometry.BytesPerSector; Buffer->BytesPerSector = Vcb->DiskGeometry.BytesPerSector; Irp->IoStatus.Information = sizeof (FILE_FS_SIZE_INFORMATION); Status = STATUS_SUCCESS; __leave; } case FileFsDeviceInformation: { PFILE_FS_DEVICE_INFORMATION Buffer; #ifdef TRACE DbgPrint ("Ext2FsdQueryVolumeInformation : FileFsDeviceInformation\n"); #endif if (Length < sizeof (FILE_FS_DEVICE_INFORMATION)) { Status = STATUS_INFO_LENGTH_MISMATCH; __leave; } Buffer = (PFILE_FS_DEVICE_INFORMATION) SystemBuffer; Buffer->DeviceType = Vcb->TargetDeviceObject->DeviceType; Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics; SetFlag (Buffer->Characteristics, FILE_READ_ONLY_DEVICE); Irp->IoStatus.Information = sizeof (FILE_FS_DEVICE_INFORMATION); Status = STATUS_SUCCESS; __leave; } case FileFsAttributeInformation: { PFILE_FS_ATTRIBUTE_INFORMATION Buffer; ULONG RequiredLength; #ifdef TRACE DbgPrint ("Ext2FsdQueryVolumeInformation : FileFsAttributeInformation\n"); #endif if (Length < sizeof (FILE_FS_ATTRIBUTE_INFORMATION)) { Status = STATUS_INFO_LENGTH_MISMATCH; __leave; } Buffer = (PFILE_FS_ATTRIBUTE_INFORMATION) SystemBuffer; Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_READ_ONLY_VOLUME; Buffer->MaximumComponentNameLength = EXT2_NAME_LEN; RequiredLength = sizeof (FILE_FS_ATTRIBUTE_INFORMATION) + sizeof (DRIVER_NAME) * 2 - sizeof (WCHAR); if (Length < RequiredLength) { Buffer->FileSystemNameLength = 0; Irp->IoStatus.Information = sizeof (FILE_FS_ATTRIBUTE_INFORMATION); DbgPrint ("Ext2FsdQueryVolumeInformation[1] : L=%i RL=%i\n", Length, RequiredLength); //Status = STATUS_BUFFER_OVERFLOW; //__leave; } else { Buffer->FileSystemNameLength = sizeof (DRIVER_NAME) * 2; FsdCharToWchar (Buffer->FileSystemName, DRIVER_NAME, sizeof (DRIVER_NAME)); Irp->IoStatus.Information = RequiredLength; } Status = STATUS_SUCCESS; __leave; } case FileFsFullSizeInformation: { PFILE_FS_FULL_SIZE_INFORMATION Buffer; #ifdef TRACE DbgPrint ("Ext2FsdQueryVolumeInformation : FileFsFullSizeInformation\n"); #endif if (Length < sizeof (FILE_FS_FULL_SIZE_INFORMATION)) { Status = STATUS_INFO_LENGTH_MISMATCH; __leave; } Buffer = (PFILE_FS_FULL_SIZE_INFORMATION) SystemBuffer; // On a readonly filesystem total size is the size of the // contents and available size is zero Buffer->TotalAllocationUnits.QuadPart = 0; //Vcb->ext2->superblock.s_blocks_count; Buffer->CallerAvailableAllocationUnits.QuadPart = 0; Buffer->ActualAvailableAllocationUnits.QuadPart = 0; Buffer->SectorsPerAllocationUnit = Vcb->ext2->block_size / Vcb->DiskGeometry.BytesPerSector; Buffer->BytesPerSector = Vcb->DiskGeometry.BytesPerSector; Irp->IoStatus.Information = sizeof (FILE_FS_FULL_SIZE_INFORMATION); Status = STATUS_SUCCESS; __leave; } default: Status = STATUS_INVALID_INFO_CLASS; } } __finally { if (VcbResourceAcquired) { ExReleaseResourceForThreadLite (&Vcb->MainResource, ExGetCurrentResourceThread ()); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { FsdQueueRequest (IrpContext); } else { IrpContext->Irp->IoStatus.Status = Status; FsdCompleteRequest (IrpContext->Irp, (CCHAR) (NT_SUCCESS (Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)); Ext2FsdFreeIrpContext (IrpContext); } } } return Status; }
PFFS_FCB FFSv2AllocateFcb( IN PFFS_VCB Vcb, IN PFFS_MCB FFSMcb, IN PFFSv2_INODE dinode2) { PFFS_FCB Fcb; ExAcquireResourceExclusiveLite( &FFSGlobal->LAResource, TRUE); Fcb = (PFFS_FCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList))); ExReleaseResourceForThreadLite( &FFSGlobal->LAResource, ExGetCurrentResourceThread()); if (Fcb == NULL) { Fcb = (PFFS_FCB)ExAllocatePool(NonPagedPool, sizeof(FFS_FCB)); RtlZeroMemory(Fcb, sizeof(FFS_FCB)); SetFlag(Fcb->Flags, FCB_FROM_POOL); } else { RtlZeroMemory(Fcb, sizeof(FFS_FCB)); } if (!Fcb) { return NULL; } Fcb->Identifier.Type = FFSFCB; Fcb->Identifier.Size = sizeof(FFS_FCB); FsRtlInitializeFileLock( &Fcb->FileLockAnchor, NULL, NULL); Fcb->OpenHandleCount = 0; Fcb->ReferenceCount = 0; Fcb->Vcb = Vcb; #if DBG Fcb->AnsiFileName.MaximumLength = (USHORT) RtlxUnicodeStringToOemSize(&(FFSMcb->ShortName)) + 1; Fcb->AnsiFileName.Buffer = (PUCHAR) ExAllocatePool(PagedPool, Fcb->AnsiFileName.MaximumLength); if (!Fcb->AnsiFileName.Buffer) { goto errorout; } RtlZeroMemory(Fcb->AnsiFileName.Buffer, Fcb->AnsiFileName.MaximumLength); FFSUnicodeToOEM(&(Fcb->AnsiFileName), &(FFSMcb->ShortName)); #endif FFSMcb->FileAttr = FILE_ATTRIBUTE_NORMAL; if ((dinode2->di_mode & IFMT) == IFDIR) { SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY); } if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2->di_mode)) { SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY); } Fcb->dinode2 = dinode2; Fcb->FFSMcb = FFSMcb; FFSMcb->FFSFcb = Fcb; RtlZeroMemory(&Fcb->Header, sizeof(FSRTL_COMMON_FCB_HEADER)); Fcb->Header.NodeTypeCode = (USHORT)FFSFCB; Fcb->Header.NodeByteSize = sizeof(FFS_FCB); Fcb->Header.IsFastIoPossible = FastIoIsNotPossible; Fcb->Header.Resource = &(Fcb->MainResource); Fcb->Header.PagingIoResource = &(Fcb->PagingIoResource); { ULONG Totalblocks = (ULONG)(Fcb->dinode2->di_blocks); Fcb->Header.AllocationSize.QuadPart = (((LONGLONG)FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS); } Fcb->Header.FileSize.QuadPart = (LONGLONG)(Fcb->dinode2->di_size); Fcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff); Fcb->SectionObject.DataSectionObject = NULL; Fcb->SectionObject.SharedCacheMap = NULL; Fcb->SectionObject.ImageSectionObject = NULL; ExInitializeResourceLite(&(Fcb->MainResource)); ExInitializeResourceLite(&(Fcb->PagingIoResource)); InsertTailList(&Vcb->FcbList, &Fcb->Next); #if DBG ExAcquireResourceExclusiveLite( &FFSGlobal->CountResource, TRUE); FFSGlobal->FcbAllocated++; ExReleaseResourceForThreadLite( &FFSGlobal->CountResource, ExGetCurrentResourceThread()); #endif return Fcb; #if DBG errorout: #endif if (Fcb) { #if DBG if (Fcb->AnsiFileName.Buffer) ExFreePool(Fcb->AnsiFileName.Buffer); #endif if (FlagOn(Fcb->Flags, FCB_FROM_POOL)) { ExFreePool(Fcb); } else { ExAcquireResourceExclusiveLite( &FFSGlobal->LAResource, TRUE); ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb); ExReleaseResourceForThreadLite( &FFSGlobal->LAResource, ExGetCurrentResourceThread()); } } return NULL; }
NTSTATUS FFSWriteFile( IN PFFS_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_VCB Vcb = NULL; PFFS_FCB Fcb = NULL; PFFS_CCB Ccb = NULL; PFILE_OBJECT FileObject = NULL; PFILE_OBJECT CacheObject; PDEVICE_OBJECT DeviceObject = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION IoStackLocation = NULL; ULONG Length; ULONG ReturnedLength = 0; LARGE_INTEGER ByteOffset; BOOLEAN PagingIo; BOOLEAN Nocache; BOOLEAN SynchronousIo; BOOLEAN MainResourceAcquired = FALSE; BOOLEAN PagingIoResourceAcquired = FALSE; BOOLEAN bNeedExtending = FALSE; BOOLEAN bAppendFile = FALSE; BOOLEAN bDeferred = FALSE; PUCHAR Buffer = NULL; __try { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); FileObject = IrpContext->FileObject; Fcb = (PFFS_FCB)FileObject->FsContext; ASSERT(Fcb); ASSERT((Fcb->Identifier.Type == FFSFCB) && (Fcb->Identifier.Size == sizeof(FFS_FCB))); Ccb = (PFFS_CCB)FileObject->FsContext2; Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); Length = IoStackLocation->Parameters.Write.Length; ByteOffset = IoStackLocation->Parameters.Write.ByteOffset; PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE); Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE); SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE); FFSPrint((DBG_INFO, "FFSWriteFile: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n", ByteOffset.QuadPart, Length, PagingIo, Nocache)); /* if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) { Status = STATUS_FILE_DELETED; __leave; } if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { Status = STATUS_DELETE_PENDING; __leave; } */ if (Length == 0) { Irp->IoStatus.Information = 0; Status = STATUS_SUCCESS; __leave; } if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) || Length & (SECTOR_SIZE - 1))) { Status = STATUS_INVALID_PARAMETER; __leave; } if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); Status = STATUS_PENDING; __leave; } #if FALSE if (!Nocache) { BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); if (!CcCanIWrite( FileObject, Length, (bWait && bQueue), bAgain)) { SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); CcDeferWrite(FileObject, (PCC_POST_DEFERRED_WRITE)FFSDeferWrite, IrpContext, Irp, Length, bAgain); bDeferred = TRUE; FFSBreakPoint(); Status = STATUS_PENDING; __leave; } } #endif if (IsEndOfFile(ByteOffset)) { bAppendFile = TRUE; ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart; } if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) && !PagingIo) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } // // Do flushing for such cases // if (Nocache && !PagingIo && (Fcb->SectionObject.DataSectionObject != NULL)) { ExAcquireResourceExclusive(&Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); MainResourceAcquired = TRUE; ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); ExReleaseResource(&Fcb->PagingIoResource); CcFlushCache(&(Fcb->SectionObject), &ByteOffset, Length, &(Irp->IoStatus)); ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); if (!NT_SUCCESS(Irp->IoStatus.Status)) { Status = Irp->IoStatus.Status; __leave; } ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); ExReleaseResource(&Fcb->PagingIoResource); CcPurgeCacheSection(&(Fcb->SectionObject), (PLARGE_INTEGER)&(ByteOffset), Length, FALSE); ExReleaseResource(&Fcb->MainResource); MainResourceAcquired = FALSE; } if (!PagingIo) { if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; __leave; } MainResourceAcquired = TRUE; } else { /* ULONG ResShCnt, ResExCnt; ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource); ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource); FFSPrint((DBG_USER, "FFSWriteFile: Inode=%xh %S PagingIo: %xh:%xh Synchronous=%xh\n", Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, ResShCnt, ResExCnt, IrpContext->IsSynchronous)); */ if (!ExAcquireResourceSharedLite( &Fcb->PagingIoResource, IrpContext->IsSynchronous)) { Status = STATUS_PENDING; __leave; } PagingIoResourceAcquired = TRUE; } if (!PagingIo) { if (!FsRtlCheckLockForWriteAccess( &Fcb->FileLockAnchor, Irp)) { Status = STATUS_FILE_LOCK_CONFLICT; __leave; } } if (Nocache) { if ((ByteOffset.QuadPart + Length) > Fcb->Header.AllocationSize.QuadPart) { if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) { Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; __leave; } else { if (Length > (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart)) { Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart); } } } } if (!Nocache) { if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) { __leave; } if (FileObject->PrivateCacheMap == NULL) { CcInitializeCacheMap( FileObject, (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize), FALSE, &FFSGlobal->CacheManagerCallbacks, Fcb); CcSetReadAheadGranularity( FileObject, READ_AHEAD_GRANULARITY); CcSetFileSizes( FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); } CacheObject = FileObject; // // Need extending the size of inode ? // if ((bAppendFile) || ((ULONG)(ByteOffset.QuadPart + Length) > (ULONG)(Fcb->Header.FileSize.QuadPart))) { LARGE_INTEGER ExtendSize; LARGE_INTEGER FileSize; bNeedExtending = TRUE; FileSize = Fcb->Header.FileSize; ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length); if (ExtendSize.QuadPart > Fcb->Header.AllocationSize.QuadPart) { if (!FFSExpandFile(IrpContext, Vcb, Fcb, &ExtendSize)) { Status = STATUS_INSUFFICIENT_RESOURCES; __leave; } } { Fcb->Header.FileSize.QuadPart = ExtendSize.QuadPart; Fcb->dinode1->di_size = (ULONG)ExtendSize.QuadPart; } if (FileObject->PrivateCacheMap) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); if (ByteOffset.QuadPart > FileSize.QuadPart) { FFSZeroHoles(IrpContext, Vcb, FileObject, FileSize.QuadPart, ByteOffset.QuadPart - FileSize.QuadPart); } if (Fcb->Header.AllocationSize.QuadPart > ExtendSize.QuadPart) { FFSZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart, Fcb->Header.AllocationSize.QuadPart - ExtendSize.QuadPart); } } if (FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1)) { Status = STATUS_SUCCESS; } FFSNotifyReportChange( IrpContext, Vcb, Fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); } if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { CcPrepareMdlWrite( CacheObject, (&ByteOffset), Length, &Irp->MdlAddress, &Irp->IoStatus); Status = Irp->IoStatus.Status; } else { Buffer = FFSGetUserBuffer(Irp); if (Buffer == NULL) { FFSBreakPoint(); Status = STATUS_INVALID_USER_BUFFER; __leave; } if (!CcCopyWrite( CacheObject, (PLARGE_INTEGER)&ByteOffset, Length, IrpContext->IsSynchronous, Buffer)) { Status = STATUS_PENDING; __leave; } Status = Irp->IoStatus.Status; } if (NT_SUCCESS(Status)) { Irp->IoStatus.Information = Length; if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) { FFSPrint((DBG_USER, "FFSWriteFile is starting FlushingDpc...\n")); FFSStartFloppyFlushDpc(Vcb, Fcb, FileObject); } } } else { ReturnedLength = Length; Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (!NT_SUCCESS(Status)) { __leave; } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = Length; Status = FFSv1WriteInode( IrpContext, Vcb, Fcb->dinode1, (ULONGLONG)(ByteOffset.QuadPart), NULL, Length, TRUE, &ReturnedLength); Irp = IrpContext->Irp; } } __finally { if (PagingIoResourceAcquired) { ExReleaseResourceForThreadLite( &Fcb->PagingIoResource, ExGetCurrentResourceThread()); } if (MainResourceAcquired) { ExReleaseResourceForThreadLite( &Fcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { if (Irp) { if (Status == STATUS_PENDING) { if (!bDeferred) { Status = FFSLockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (NT_SUCCESS(Status)) { Status = FFSQueueRequest(IrpContext); } else { FFSCompleteIrpContext(IrpContext, Status); } } } else { if (NT_SUCCESS(Status)) { if (SynchronousIo && !PagingIo) { FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information; } if (!PagingIo) { SetFlag(FileObject->Flags, FO_FILE_MODIFIED); SetFlag(Fcb->Flags, FCB_FILE_MODIFIED); } } FFSCompleteIrpContext(IrpContext, Status); } } else { FFSFreeIrpContext(IrpContext); } } } return Status; }
__drv_mustHoldCriticalRegion NTSTATUS RfsdPnpQueryRemove ( PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb ) { NTSTATUS Status; KEVENT Event; BOOLEAN bDeleted = FALSE; BOOLEAN VcbAcquired = FALSE; PAGED_CODE(); _SEH2_TRY { RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove by RfsdPnp ...\n")); RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdFlushVolume ...\n")); #if (_WIN32_WINNT >= 0x0500) CcWaitForCurrentLazyWriterActivity(); #endif ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); VcbAcquired = TRUE; RfsdFlushFiles(Vcb, FALSE); RfsdFlushVolume(Vcb, FALSE); RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdLockVcb: Vcb=%xh FileObject=%xh ...\n", Vcb, IrpContext->FileObject)); Status = RfsdLockVcb(Vcb, IrpContext->FileObject); RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdPurgeVolume ...\n")); RfsdPurgeVolume(Vcb, TRUE); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); VcbAcquired = FALSE; IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); KeInitializeEvent( &Event, NotificationEvent, FALSE ); IoSetCompletionRoutine( IrpContext->Irp, RfsdPnpCompletionRoutine, &Event, TRUE, TRUE, TRUE ); RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: Call lower level driver...\n")); Status = IoCallDriver( Vcb->TargetDeviceObject, IrpContext->Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); Status = IrpContext->Irp->IoStatus.Status; } if (NT_SUCCESS(Status)) { RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdCheckDismount ...\n")); bDeleted = RfsdCheckDismount(IrpContext, Vcb, TRUE); RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdFlushVolume bDelted=%xh ...\n", bDeleted)); } ASSERT( !(NT_SUCCESS(Status) && !bDeleted)); } _SEH2_FINALLY { if (VcbAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); } RfsdCompleteRequest( IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? IO_DISK_INCREMENT : IO_NO_INCREMENT) ); IrpContext->Irp = NULL; } _SEH2_END; return Status; }