コード例 #1
0
ファイル: flush.c プロジェクト: Nevermore2015/reactos
static
NTSTATUS
VfatFlushFile(
    PDEVICE_EXTENSION DeviceExt,
    PVFATFCB Fcb)
{
    IO_STATUS_BLOCK IoStatus;
    NTSTATUS Status;

    DPRINT("VfatFlushFile(DeviceExt %p, Fcb %p) for '%wZ'\n", DeviceExt, Fcb, &Fcb->PathNameU);

    CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
    if (IoStatus.Status == STATUS_INVALID_PARAMETER)
    {
        /* FIXME: Caching was possible not initialized */
        IoStatus.Status = STATUS_SUCCESS;
    }

    if (Fcb->Flags & FCB_IS_DIRTY)
    {
        Status = VfatUpdateEntry(Fcb);
        if (!NT_SUCCESS(Status))
        {
            IoStatus.Status = Status;
        }
    }
    return IoStatus.Status;
}
コード例 #2
0
ファイル: flush.c プロジェクト: RPG-7/reactos
/*************************************************************************
*
* Function: Ext2FlushAFile()
*
* Description:
*	Tell the Cache Manager to perform a flush.
*
* Expected Interrupt Level (for execution) :
*
*  IRQL_PASSIVE_LEVEL
*
* Return Value: None
*
*************************************************************************/
void NTAPI Ext2FlushAFile(
PtrExt2NTRequiredFCB	PtrReqdFCB,
PIO_STATUS_BLOCK		PtrIoStatus)
{
	CcFlushCache(&(PtrReqdFCB->SectionObject), NULL, 0, PtrIoStatus);
	return;
}
コード例 #3
0
ファイル: flush.c プロジェクト: Moteesh/reactos
static
NTSTATUS
VfatFlushFile(
    PDEVICE_EXTENSION DeviceExt,
    PVFATFCB Fcb)
{
    IO_STATUS_BLOCK IoStatus;
    NTSTATUS Status;

    DPRINT("VfatFlushFile(DeviceExt %p, Fcb %p) for '%wZ'\n", DeviceExt, Fcb, &Fcb->PathNameU);

    CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
    if (IoStatus.Status == STATUS_INVALID_PARAMETER)
    {
        /* FIXME: Caching was possible not initialized */
        IoStatus.Status = STATUS_SUCCESS;
    }

    ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
    if (BooleanFlagOn(Fcb->Flags, FCB_IS_DIRTY))
    {
        Status = VfatUpdateEntry(DeviceExt, Fcb);
        if (!NT_SUCCESS(Status))
        {
            IoStatus.Status = Status;
        }
    }
    ExReleaseResourceLite(&DeviceExt->DirResource);

    return IoStatus.Status;
}
コード例 #4
0
ファイル: fileinfo.c プロジェクト: bailey27/dokany
VOID FlushFcb(__in PDokanFCB fcb, __in_opt PFILE_OBJECT fileObject) {

  if (fcb == NULL) {
    return;
  }

  if (fcb->SectionObjectPointers.ImageSectionObject != NULL) {
    DDbgPrint("  MmFlushImageSection FileName: %wZ FileCount: %lu.\n",
              &fcb->FileName, fcb->FileCount);
    MmFlushImageSection(&fcb->SectionObjectPointers, MmFlushForWrite);
    DDbgPrint("  MmFlushImageSection done FileName: %wZ FileCount: %lu.\n",
              &fcb->FileName, fcb->FileCount);
  }

  if (fcb->SectionObjectPointers.DataSectionObject != NULL) {
    DDbgPrint("  CcFlushCache FileName: %wZ FileCount: %lu.\n", &fcb->FileName,
              fcb->FileCount);
    ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
    CcFlushCache(&fcb->SectionObjectPointers, NULL, 0, NULL);
    CcPurgeCacheSection(&fcb->SectionObjectPointers, NULL, 0, FALSE);
    if (fileObject != NULL) {
      CcUninitializeCacheMap(fileObject, NULL, NULL);
    }
    ExReleaseResourceLite(&fcb->PagingIoResource);
    DDbgPrint("  CcFlushCache done FileName: %wZ FileCount: %lu.\n",
              &fcb->FileName, fcb->FileCount);
  }
}
コード例 #5
0
ファイル: file.c プロジェクト: LucaBongiorni/winfsp
NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
    UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge)
{
    /*
     * The FileNode must be acquired exclusive (Full) when calling this function.
     */

    PAGED_CODE();

    LARGE_INTEGER FlushOffset;
    PLARGE_INTEGER PFlushOffset = &FlushOffset;
    FSP_FSCTL_FILE_INFO FileInfo;
    IO_STATUS_BLOCK IoStatus = { STATUS_SUCCESS };

    FlushOffset.QuadPart = FlushOffset64;
    if (FILE_WRITE_TO_END_OF_FILE == FlushOffset.LowPart && -1L == FlushOffset.HighPart)
    {
        if (FspFileNodeTryGetFileInfo(FileNode, &FileInfo))
            FlushOffset.QuadPart = FileInfo.FileSize;
        else
            PFlushOffset = 0; /* we don't know how big the file is, so flush it all! */
    }

    /* it is unclear if the Cc* calls below can raise or not; wrap them just in case */
    try
    {
        if (0 != FspMvCcCoherencyFlushAndPurgeCache)
        {
            /* if we are on Win7+ use CcCoherencyFlushAndPurgeCache */
            FspMvCcCoherencyFlushAndPurgeCache(
                &FileNode->NonPaged->SectionObjectPointers, PFlushOffset, FlushLength, &IoStatus,
                FlushAndPurge ? 0 : CC_FLUSH_AND_PURGE_NO_PURGE);

            if (STATUS_CACHE_PAGE_LOCKED == IoStatus.Status)
                IoStatus.Status = STATUS_SUCCESS;
        }
        else
        {
            /* do it the old-fashioned way; non-cached and mmap'ed I/O are non-coherent */
            CcFlushCache(&FileNode->NonPaged->SectionObjectPointers, PFlushOffset, FlushLength, &IoStatus);
            if (NT_SUCCESS(IoStatus.Status))
            {
                if (FlushAndPurge)
                    CcPurgeCacheSection(&FileNode->NonPaged->SectionObjectPointers, PFlushOffset, FlushLength, FALSE);

                IoStatus.Status = STATUS_SUCCESS;
            }
        }
    }
    except (EXCEPTION_EXECUTE_HANDLER)
    {
        IoStatus.Status = GetExceptionCode();
    }

    return IoStatus.Status;
}
コード例 #6
0
ファイル: write.c プロジェクト: layerfsd/ffsfsd
VOID
FFSFloppyFlush(
	IN PVOID Parameter)
{
	PFFS_FLPFLUSH_CONTEXT Context;
	PFILE_OBJECT          FileObject;
	PFFS_FCB              Fcb;
	PFFS_VCB              Vcb;

	Context = (PFFS_FLPFLUSH_CONTEXT) Parameter;
	FileObject = Context->FileObject;
	Fcb = Context->Fcb;
	Vcb = Context->Vcb;

	FFSPrint((DBG_USER, "FFSFloppyFlushing ...\n"));

	IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);

	if (Vcb)
	{
		ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
		ExReleaseResource(&Vcb->PagingIoResource);

		CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
	}

	if (FileObject)
	{
		ASSERT(Fcb == (PFFS_FCB)FileObject->FsContext);

		ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
		ExReleaseResource(&Fcb->PagingIoResource);

		CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL);

		ObDereferenceObject(FileObject);
	}

	IoSetTopLevelIrp(NULL);

	ExFreePool(Parameter);
}
コード例 #7
0
ファイル: write.c プロジェクト: Axure/Ext3Fsd
VOID
Ext2FloppyFlush(IN PVOID Parameter)
{
    PEXT2_FLPFLUSH_CONTEXT Context;
    PFILE_OBJECT           FileObject;
    PEXT2_FCB Fcb;
    PEXT2_VCB Vcb;

    Context = (PEXT2_FLPFLUSH_CONTEXT) Parameter;
    FileObject = Context->FileObject;
    Fcb = Context->Fcb;
    Vcb = Context->Vcb;

    DEBUG(DL_FLP, ("Ext2FloppyFlushing ...\n"));

    IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);

    if (FileObject) {
        ASSERT(Fcb == (PEXT2_FCB)FileObject->FsContext);

        ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
        ExReleaseResourceLite(&Fcb->PagingIoResource);

        CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL);

        ObDereferenceObject(FileObject);
    }

    if (Vcb) {
        ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
        ExReleaseResourceLite(&Vcb->PagingIoResource);

        ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
        Ext2DropBH(Vcb);
        CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
        ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
    }

    IoSetTopLevelIrp(NULL);
    Ext2FreePool(Parameter, EXT2_FLPFLUSH_MAGIC);
}
コード例 #8
0
ファイル: fscontrol.c プロジェクト: luciang/lklvfs
VOID PurgeFile(PLKLFCB fcb, BOOLEAN flush_before_purge)
{
	IO_STATUS_BLOCK iosb;

	ASSERT(fcb);

	if (flush_before_purge)
		CcFlushCache(&fcb->section_object, NULL, 0, &iosb);
	if (fcb->section_object.ImageSectionObject)
		MmFlushImageSection(&fcb->section_object, MmFlushForWrite);
	if (fcb->section_object.DataSectionObject)
		CcPurgeCacheSection(&fcb->section_object, NULL, 0, FALSE);
}
コード例 #9
0
ファイル: fsctl.c プロジェクト: GYGit/reactos
__drv_mustHoldCriticalRegion
NTSTATUS
FFSPurgeFile(
	IN PFFS_FCB Fcb,
	IN BOOLEAN  FlushBeforePurge)
{
	IO_STATUS_BLOCK    IoStatus;

    PAGED_CODE();

	ASSERT(Fcb != NULL);

	ASSERT((Fcb->Identifier.Type == FFSFCB) &&
			(Fcb->Identifier.Size == sizeof(FFS_FCB)));


	if(!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) && FlushBeforePurge &&
			!IsFlagOn(Fcb->Vcb->Flags, VCB_WRITE_PROTECTED))
	{

		FFSPrint((DBG_INFO, "FFSPurgeFile: CcFlushCache on %s.\n", 
					Fcb->AnsiFileName.Buffer));

		ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
		ExReleaseResourceLite(&Fcb->PagingIoResource);

		CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus);

		ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
	}

	if (Fcb->SectionObject.ImageSectionObject)
	{

		FFSPrint((DBG_INFO, "FFSPurgeFile: MmFlushImageSection on %s.\n", 
					Fcb->AnsiFileName.Buffer));

		MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite);
	}

	if (Fcb->SectionObject.DataSectionObject)
	{

		FFSPrint((DBG_INFO, "FFSPurgeFile: CcPurgeCacheSection on %s.\n",
					Fcb->AnsiFileName.Buffer));

		CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
	}

	return STATUS_SUCCESS;
}
コード例 #10
0
ファイル: flush.c プロジェクト: GYGit/reactos
NTSTATUS
Ext2FlushFile (
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_FCB            Fcb,
    IN PEXT2_CCB            Ccb
)
{
    IO_STATUS_BLOCK     IoStatus;

    ASSERT(Fcb != NULL);
    ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
           (Fcb->Identifier.Size == sizeof(EXT2_FCB)));

    _SEH2_TRY {

        /* update timestamp and achieve attribute */
        if (Ccb != NULL) {

            if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {

                LARGE_INTEGER   SysTime;
                KeQuerySystemTime(&SysTime);

                Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
                Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
                Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode);
            }
        }

        if (IsDirectory(Fcb)) {
            IoStatus.Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }

        DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
                        Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));

        CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
        ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);

    } _SEH2_FINALLY {

        /* do cleanup here */
    } _SEH2_END;

    return IoStatus.Status;
}
コード例 #11
0
ファイル: flush.c プロジェクト: Uroc327/ext2fsd
NTSTATUS
Ext2FlushVolume (
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb,
    IN BOOLEAN              bShutDown
)
{
    IO_STATUS_BLOCK    IoStatus;

    DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));

    ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
    ExReleaseResourceLite(&Vcb->PagingIoResource);

    CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);

    return IoStatus.Status;
}
コード例 #12
0
ファイル: cachesub.c プロジェクト: RPG-7/reactos
BOOLEAN
NTAPI
CcFlushImageSection(PSECTION_OBJECT_POINTERS SectionObjectPointer,
                    MMFLUSH_TYPE FlushType)
{
    PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap;
    PNOCC_BCB Bcb;
    PLIST_ENTRY Entry;
    IO_STATUS_BLOCK IOSB;
    BOOLEAN Result = TRUE;

    if (!Map) return TRUE;

    for (Entry = Map->AssociatedBcb.Flink;
         Entry != &Map->AssociatedBcb;
         Entry = Entry->Flink)
    {
        Bcb = CONTAINING_RECORD(Entry, NOCC_BCB, ThisFileList);

        if (!Bcb->Dirty) continue;

        switch (FlushType)
        {
            case MmFlushForDelete:
                CcPurgeCacheSection(SectionObjectPointer,
                                    &Bcb->FileOffset,
                                    Bcb->Length,
                                    FALSE);
                break;
            case MmFlushForWrite:
                CcFlushCache(SectionObjectPointer,
                             &Bcb->FileOffset,
                             Bcb->Length,
                             &IOSB);
                break;
        }
    }

    return Result;
}
コード例 #13
0
ファイル: XixFsdCleanUp.c プロジェクト: JanD1943/ndas4windows
NTSTATUS
XixFsdCommonCleanUp(
	IN PXIFS_IRPCONTEXT pIrpContext
	)
{
	NTSTATUS		RC = STATUS_SUCCESS;
	PXIFS_FCB		pFCB = NULL;
	PXIFS_CCB		pCCB = NULL;
	PXIFS_VCB		pVCB = NULL;
	PFILE_OBJECT	pFileObject = NULL;	
	TYPE_OF_OPEN	TypeOfOpen = UnopenedFileObject;

	PIRP					pIrp = NULL;
	PIO_STACK_LOCATION		pIrpSp = NULL;
	KIRQL					SavedIrql;

	PXIFS_LCB	pLCB = NULL;
	PXIFS_FCB	pParentFCB = NULL;

	BOOLEAN					Wait = FALSE;
	BOOLEAN					VCBAcquired = FALSE;
	BOOLEAN					ParentFCBAcquired = FALSE;
	BOOLEAN					CanWait = FALSE;
	BOOLEAN					AttemptTeardown = FALSE;
	BOOLEAN					SendUnlockNotification = FALSE;

	PAGED_CODE();

	DebugTrace((DEBUG_LEVEL_TRACE), (DEBUG_TARGET_CLEANUP|DEBUG_TARGET_IRPCONTEXT), 
		("Enter XifsdCommonCleanUp pIrpContext(%p)\n", pIrpContext));


	ASSERT_IRPCONTEXT(pIrpContext);

	pIrp = pIrpContext->Irp;
	ASSERT(pIrp);

	// check if open request is releated to file system CDO
	{
		PDEVICE_OBJECT	DeviceObject = pIrpContext->TargetDeviceObject;
		ASSERT(DeviceObject);
		
		if (DeviceObject == XiGlobalData.XifsControlDeviceObject) {
			RC = STATUS_SUCCESS;

			DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CLEANUP), 
					("CDO Device TargetDevide(%p).\n", DeviceObject));
			XixFsdCompleteRequest(pIrpContext,RC,0);
			return(RC);
		}

	}	



	if(pIrpContext->VCB == NULL){

		DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_CLEANUP, 
					("pIrpContext->VCB == NULL.\n"));
		RC = STATUS_SUCCESS;
		XixFsdCompleteRequest(pIrpContext, RC, 0);
		return RC;
	}


	

	pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
	ASSERT(pIrpSp);

	pFileObject = pIrpSp->FileObject;
	ASSERT(pFileObject);

	TypeOfOpen = XixFsdDecodeFileObject(pFileObject, &pFCB, &pCCB);

	if(TypeOfOpen <= StreamFileOpen){
		DebugTrace((DEBUG_LEVEL_TRACE|DEBUG_LEVEL_INFO), DEBUG_TARGET_CLEANUP, 
					("TypeOfOpen <= StreamFileOpen.\n"));
		XixFsdCompleteRequest(pIrpContext, STATUS_SUCCESS, 0);
		return STATUS_SUCCESS;
	}


	CanWait = XifsdCheckFlagBoolean(pIrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT);

	
	if(CanWait == FALSE){
		DebugTrace((DEBUG_LEVEL_TRACE|DEBUG_LEVEL_INFO), (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_IRPCONTEXT), 
					("PostRequest IrpCxt(%p) Irp(%p)\n", pIrpContext, pIrp));
		RC = XixFsdPostRequest(pIrpContext, pIrp);
		return RC;
	}

	ASSERT_FCB(pFCB);
	pVCB = pFCB->PtrVCB;
	ASSERT_VCB(pVCB);




	DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_RESOURCE|DEBUG_TARGET_VCB), 
				("Acquire exclusive pVCB(%p) VCBResource(%p).\n", pVCB, &pVCB->VCBResource));	

	if((TypeOfOpen == UserVolumeOpen)
		&& XifsdCheckFlagBoolean(pFileObject->Flags, FO_FILE_MODIFIED))
	{
		XifsdAcquireVcbExclusive(CanWait, pVCB, FALSE);
		VCBAcquired = TRUE;		
	}


	XifsdAcquireFcbExclusive(CanWait, pFCB, FALSE);		


	DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB), 
					("Acquire exclusive FCB(%p) FCBResource(%p).\n", pFCB, pFCB->FCBResource));

	
	XifsdSetFlag(pFileObject->Flags, FO_CLEANUP_COMPLETE);
	DebugTrace(DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_CLEANUP| DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB), 
					("Set File Object Flags(0x%x)\n", pFileObject->Flags));	



	//IoRemoveShareAccess( pFileObject, &pFCB->FCBShareAccess );

	try{
		switch(TypeOfOpen){
		case UserDirectoryOpen:
			
			if(XifsdCheckFlagBoolean(pCCB->CCBFlags, XIFSD_CCB_FLAG_NOFITY_SET))
			{
				DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, 
					("CompletionFilter Notify CleanUp (%wZ) pCCB(%p)\n", &pFCB->FCBName, pCCB));

				FsRtlNotifyCleanup(pVCB->NotifyIRPSync, &pVCB->NextNotifyIRP, pCCB);

				//DbgPrint("Notify CleanUp (%wZ) pCCB(%p)\n", &pFCB->FCBName, pCCB);

			}


			//DbgPrint("CleanUp (%wZ) pCCB(%p) pCCB->CCBFlags(%x)\n", &pFCB->FCBName, pCCB, pCCB->CCBFlags);


			DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, 
					("!!!!CleanUp (%wZ) pCCB(%p)\n", &pFCB->FCBName, pCCB));


			IoRemoveShareAccess( pFileObject, &pFCB->FCBShareAccess );
			break;
			
		case UserFileOpen:
			//
			//  Coordinate the cleanup operation with the oplock state.
			//  Oplock cleanup operations can always cleanup immediately so no
			//  need to check for STATUS_PENDING.
			//

			FsRtlCheckOplock( &pFCB->FCBOplock,
							  pIrp,
							  pIrpContext,
							  NULL,
							  NULL );

			//
			//  Unlock all outstanding file locks.
			//

			if (pFCB->FCBFileLock != NULL) {

				FsRtlFastUnlockAll( pFCB->FCBFileLock,
									pFileObject,
									IoGetRequestorProcess( pIrp ),
									NULL );
			}



			//
			//  Check the fast io state.
			//

			XifsdLockFcb( pIrpContext, pFCB );
			pFCB->IsFastIoPossible = XixFsdCheckFastIoPossible( pFCB );
			XifsdUnlockFcb( pIrpContext, pFCB );


			/*
			if((pFCB->HasLock != FCB_FILE_LOCK_HAS)
				&& (!XifsdCheckFlagBoolean(pFCB->FCBFlags, XIFSD_FCB_OPEN_WRITE))
				&& XifsdCheckFlagBoolean(pFileObject->Flags, FO_CACHE_SUPPORTED) 
				&& (pFCB->FCBCleanup == 1)
			){
					if(pFCB->SectionObject.DataSectionObject != NULL) 
					{
						
						CcFlushCache(&(pFCB->SectionObject), NULL, 0, NULL);

						ExAcquireResourceSharedLite(pFCB->PagingIoResource, TRUE);
						ExReleaseResourceLite( pFCB->PagingIoResource );
						
						
						CcPurgeCacheSection( &(pFCB->SectionObject),
														NULL,
														0,
														FALSE 
														);	
														
					}			
			
			}
			*/


			
			if(
				XifsdCheckFlagBoolean(pFileObject->Flags, FO_CACHE_SUPPORTED) &&
				(pFCB->FcbNonCachedOpenCount > 1)	&&
				((pFCB->FcbNonCachedOpenCount + 1) ==  pFCB->FCBCleanup)
			)
			{
				if(pFCB->SectionObject.DataSectionObject != NULL) 
				{

					// changed by ILGU HONG for readonly 09052006
					if(!pFCB->PtrVCB->IsVolumeWriteProctected)
						CcFlushCache(&(pFCB->SectionObject), NULL, 0, NULL);
					// changed by ILGU HONG for readonly end
					
					//DbgPrint("CcFlush  1 File(%wZ)\n", &pFCB->FCBFullPath);
					ExAcquireResourceSharedLite(pFCB->PagingIoResource, TRUE);
					ExReleaseResourceLite( pFCB->PagingIoResource );


					CcPurgeCacheSection( &(pFCB->SectionObject),
														NULL,
														0,
														FALSE 
														);					
					

				}	
			}
			
			/*
			else if(pFCB->FCBCleanup == 1 ){
		
				if(XifsdCheckFlagBoolean(pFileObject->Flags, FO_CACHE_SUPPORTED)){
					if(pFCB->SectionObject.DataSectionObject != NULL) 
					{
						CcFlushCache(&(pFCB->SectionObject), NULL, 0, NULL);

						ExAcquireResourceSharedLite(pFCB->PagingIoResource, TRUE);
						ExReleaseResourceLite( pFCB->PagingIoResource );

						CcPurgeCacheSection( &(pFCB->SectionObject),
															NULL,
															0,
															FALSE 
															);					
						

					}
				}

				if(XifsdCheckFlagBoolean(pFCB->FCBFlags,XIFSD_FCB_MODIFIED_FILE)){
					XixFsdUpdateFCB(pFCB);
				}

			}
			*/

			IoRemoveShareAccess( pFileObject, &pFCB->FCBShareAccess );
			//
			//  Cleanup the cache map.
			//
			
			CcUninitializeCacheMap( pFileObject, NULL, NULL );
					
			

			break;
		case UserVolumeOpen:
			break;
		default:
			break;
		}

		


		if((TypeOfOpen == UserDirectoryOpen) || (TypeOfOpen == UserFileOpen)){

			if(pFCB->FCBCleanup == 1 ){
				if(XifsdCheckFlagBoolean(pFCB->FCBFlags,XIFSD_FCB_MODIFIED_FILE)){
					
					// changed by ILGU HONG for readonly 09052006
					if(!pFCB->PtrVCB->IsVolumeWriteProctected){

						XixFsdUpdateFCB(pFCB);

						if(pFCB->WriteStartOffset != -1){

							//DbgPrint("Set Update Information!!!\n");
							XixFsdSendFileChangeRC(
									TRUE,
									pVCB->HostMac, 
									pFCB->LotNumber, 
									pVCB->DiskId, 
									pVCB->PartitionId, 
									pFCB->FileSize.QuadPart, 
									pFCB->RealAllocationSize,
									pFCB->WriteStartOffset
							);
							
							pFCB->WriteStartOffset = -1;
						}
					}
					// changed by ILGU HONG for readonly end

				}


	


			}




			if(XifsdCheckFlagBoolean(pCCB->CCBFlags, XIFSD_CCB_FLAGS_DELETE_ON_CLOSE)){
				
				if(pFCB == pFCB->PtrVCB->RootDirFCB){
					XifsdClearFlag(pCCB->CCBFlags, XIFSD_CCB_FLAGS_DELETE_ON_CLOSE);
					XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
				}else{
					XifsdSetFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
				}
			}

	


			// changed by ILGU HONG for readonly 09082006
			if(XifsdCheckFlagBoolean(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE) && (!pFCB->PtrVCB->IsVolumeWriteProctected) ){
			// changed by ILGU HONG for readonly end
				if(pFCB->FCBCleanup == 1){
					
					//DbgPrint(" !!!Delete Entry From table (%wZ)  .\n", &pFCB->FCBFullPath);

					ASSERT_CCB(pCCB);
					pLCB = pCCB->PtrLCB;

					ASSERT_LCB(pLCB);

					pParentFCB = pLCB->ParentFcb;
					ASSERT_FCB(pParentFCB);					



  					pFCB->FileSize.QuadPart = 0;
					pFCB->ValidDataLength.QuadPart = 0;

					if(pFCB->FCBType == FCB_TYPE_FILE){
						
						XifsdReleaseFcb(TRUE, pFCB);
						XifsdAcquireFcbExclusive(TRUE, pParentFCB, FALSE);
						ParentFCBAcquired = TRUE;
						XifsdAcquireFcbExclusive(TRUE, pFCB, FALSE);
						RC = DeleteParentChild(pIrpContext, pParentFCB, &pLCB->FileName);
						
						if(!NT_SUCCESS(RC)){
							DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
								("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName));
							
							//XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}
						
						XifsdClearFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_DELETE_ON_CLOSE);
						XifsdSetFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_LINK_IS_GONE);
						
						XixFsdRemovePrefix(TRUE, pLCB);

						//
						//  Now Decrement the reference counts for the parent and drop the Vcb.
						//
						XifsdLockVcb(pIrpContext,pVCB);
						DebugTrace( DEBUG_LEVEL_INFO, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT),
									("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", 
									pParentFCB->LotNumber,
									 pVCB->VCBReference,
									 pVCB->VCBUserReference,
									 pParentFCB->FCBReference,
									 pParentFCB->FCBUserReference ));

						XifsdDecRefCount( pParentFCB, 1, 1 );

						DebugTrace( DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT),
									("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", 
									pParentFCB->LotNumber,
									 pVCB->VCBReference,
									 pVCB->VCBUserReference,
									 pParentFCB->FCBReference,
									 pParentFCB->FCBUserReference ));

						XifsdUnlockVcb( pIrpContext, pVCB );
						


						if(!NT_SUCCESS(RC)){
							DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
								("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName));
							
							XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}
						
						

					}else {
						
						RC = XixFsReLoadFileFromFcb(pFCB);
						
						if(!NT_SUCCESS(RC)){
							DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
								("Fail XixFsReLoadFileFromFcb (%wZ)\n", &pFCB->FCBName));
							
							XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}
						
						if(pFCB->ChildCount != 0){
							XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}

						XifsdReleaseFcb(TRUE, pFCB);
						XifsdAcquireFcbExclusive(TRUE, pParentFCB, FALSE);
						ParentFCBAcquired = TRUE;
						
						XifsdAcquireFcbExclusive(TRUE, pFCB, FALSE);

						RC = DeleteParentChild(pIrpContext, pParentFCB, &pLCB->FileName);

						if(!NT_SUCCESS(RC)){
							DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
								("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName));
							
							//ifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}
						

						XifsdClearFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_DELETE_ON_CLOSE);
						XifsdSetFlag(pLCB->LCBFlags, XIFSD_LCB_STATE_LINK_IS_GONE);
						
						
						XixFsdRemovePrefix(TRUE, pLCB);

						//
						//  Now Decrement the reference counts for the parent and drop the Vcb.
						//
						XifsdLockVcb(pIrpContext,pVCB);
						DebugTrace( DEBUG_LEVEL_INFO, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT),
									("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", 
									pParentFCB->LotNumber,
									 pVCB->VCBReference,
									 pVCB->VCBUserReference,
									 pParentFCB->FCBReference,
									 pParentFCB->FCBUserReference ));

						XifsdDecRefCount( pParentFCB, 1, 1 );

						DebugTrace( DEBUG_LEVEL_CRITICAL, (DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_REFCOUNT),
									("XifsdSetRenameInformation, PFcb (%I64d) Vcb %d/%d Fcb %d/%d\n", 
									pParentFCB->LotNumber,
									 pVCB->VCBReference,
									 pVCB->VCBUserReference,
									 pParentFCB->FCBReference,
									 pParentFCB->FCBUserReference ));

						XifsdUnlockVcb( pIrpContext, pVCB );

						
						if(!NT_SUCCESS(RC)){
							DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
								("Fail DeleteParentChild (%wZ)\n", &pLCB->FileName));
							
							XifsdClearFlag(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE);
							RC = STATUS_SUCCESS;
							goto pass_through;
						}
						

						
					}


			
					//XixFsdDeleteUpdateFCB(pFCB);

					XixFsdSendRenameLinkBC(
						TRUE,
						XIFS_SUBTYPE_FILE_DEL,
						pVCB->HostMac,
						pFCB->LotNumber,
						pVCB->DiskId,
						pVCB->PartitionId,
						pFCB->ParentLotNumber,
						0
					);

				}
			}
			

		}


pass_through:

		XifsdLockVcb(pIrpContext, pVCB);
		
		if(XifsdCheckFlagBoolean(pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
		{
			ASSERT(pFCB->FcbNonCachedOpenCount > 0);
			pFCB->FcbNonCachedOpenCount --;
		}

		XifsdDecrementClenupCount(pFCB);


		DebugTrace(DEBUG_LEVEL_ALL, DEBUG_TARGET_ALL,
			("Cleanup  Name(%wZ) FCBLotNumber(%I64d) FCBCleanUp(%ld) VCBCleanup(%ld) pCCB(%p) FileObject(%p)\n", 
			&pFCB->FCBName,
			pFCB->LotNumber, 
			pFCB->FCBCleanup, 
			pVCB->VCBCleanup,
			pCCB,
			pFileObject
			));
			
		XifsdUnlockVcb( pIrpContext, pVCB );

		AttemptTeardown = (pVCB->VCBCleanup == 0 && pVCB->VCBState == XIFSD_VCB_STATE_VOLUME_DISMOUNTED );
		
		if(pFileObject == pVCB->LockVolumeFileObject){
			ASSERT(XifsdCheckFlagBoolean(pVCB->VCBFlags, XIFSD_VCB_FLAGS_VOLUME_LOCKED));
			
			IoAcquireVpbSpinLock(&SavedIrql);
			XifsdClearFlag(pVCB->PtrVPB->Flags, VPB_LOCKED);
			IoReleaseVpbSpinLock( SavedIrql );
			
			XifsdClearFlag(pVCB->VCBFlags, XIFSD_VCB_FLAGS_VOLUME_LOCKED);
			pVCB->LockVolumeFileObject = NULL;
			SendUnlockNotification = TRUE;
			
		}

		

		/*
		if( (pFCB->FCBCleanup == 0) 
				&& (!XifsdCheckFlagBoolean(pFCB->FCBFlags, XIFSD_FCB_DELETE_ON_CLOSE)) ){

			DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_CLEANUP|DEBUG_TARGET_IRPCONTEXT| DEBUG_TARGET_ALL), 
				("CleanUp Release Lot Lock LotNumber(%ld)\n", pFCB->LotNumber));

			XifsdLotUnLock(pVCB, pVCB->TargetDeviceObject, pFCB->LotNumber);
			pFCB->HasLock = FCB_FILE_LOCK_INVALID;
		}
		*/

		//
		//  We must clean up the share access at this time, since we may not
		//  get a Close call for awhile if the file was mapped through this
		//  File Object.
		//

		


	}finally{

		XifsdReleaseFcb(pIrpContext, pFCB);

		if(ParentFCBAcquired) {
			XifsdReleaseFcb(TRUE,pParentFCB);
		}
		

        if (SendUnlockNotification) {

            FsRtlNotifyVolumeEvent( pFileObject, FSRTL_VOLUME_UNLOCK );
        }

  		if (VCBAcquired)  {

			XifsdReleaseVcb( pIrpContext, pVCB);
		}


	}



    if (AttemptTeardown) {
        XifsdAcquireVcbExclusive( CanWait, pVCB, FALSE );

        try {
            
            XixFsdPurgeVolume( pIrpContext, pVCB, FALSE );

        } finally {

            XifsdReleaseVcb( pIrpContext, pVCB );
        }
    }


    //
    //  If this is a normal termination then complete the request
    //

	DebugTrace((DEBUG_LEVEL_TRACE), (DEBUG_TARGET_CLEANUP|DEBUG_TARGET_IRPCONTEXT), 
		("Exit XifsdCommonCleanUp pIrpContext(%p)\n", pIrpContext));

    XixFsdCompleteRequest( pIrpContext, STATUS_SUCCESS, 0 );

    return STATUS_SUCCESS;
}
コード例 #14
0
NTSTATUS
AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
            IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSDeviceExt *pDeviceExt = NULL;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    PFILE_OBJECT pFileObject = NULL;
    AFSFcb *pRootFcb = NULL;
    AFSDeviceExt *pControlDeviceExt = NULL;
    IO_STATUS_BLOCK stIoSB;
    AFSObjectInfoCB *pObjectInfo = NULL;
    AFSFileCleanupCB stFileCleanup;
    ULONG   ulNotificationFlags = 0;

    __try
    {

        if( AFSRDRDeviceObject == NULL)
        {

            //
            // Let this through, it's a cleanup on the library control device
            //

            try_return( ntStatus);
        }

        pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
        pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;

        //
        // Set some initial variables to make processing easier
        //

        pFileObject = pIrpSp->FileObject;

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        if( pFcb == NULL)
        {
            try_return( ntStatus);
        }

        pObjectInfo = pFcb->ObjectInformation;

        pRootFcb = pObjectInfo->VolumeCB->RootFcb;

        RtlZeroMemory( &stFileCleanup,
                       sizeof( AFSFileCleanupCB));

        stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();

        stFileCleanup.Identifier = (ULONGLONG)pFileObject;

        //
        // Perform the cleanup functionality depending on the type of node it is
        //

        switch( pFcb->Header.NodeTypeCode)
        {

            case AFS_ROOT_ALL:
            {

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                  TRUE);

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
                                    &pControlDeviceExt->Specific.Control.DirNotifyList,
                                    pCcb);

                break;
            }

            case AFS_IOCTL_FCB:
            {

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                  TRUE);

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                //
                // Decrement the open child handle count
                //

                if( pObjectInfo->ParentObjectInformation != NULL &&
                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
                {

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
                }

                //
                // And finally, release the Fcb if we acquired it.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                break;
            }

            //
            // This Fcb represents a file
            //

            case AFS_FILE_FCB:
            {

                //
                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                //

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                //
                // If the handle has write permission ...
                //

                if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
                    CcIsFileCached( pIrpSp->FileObject))
                {

                    __try
                    {

                        CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
                                      NULL,
                                      0,
                                      &stIoSB);

                        if( !NT_SUCCESS( stIoSB.Status))
                        {

                            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
                                          AFS_TRACE_LEVEL_ERROR,
                                          "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
                                          &pCcb->FullFileName,
                                          pObjectInfo->FileId.Cell,
                                          pObjectInfo->FileId.Volume,
                                          pObjectInfo->FileId.Vnode,
                                          pObjectInfo->FileId.Unique,
                                          stIoSB.Status,
                                          stIoSB.Information);

                            ntStatus = stIoSB.Status;
                        }
                    }
                    __except( EXCEPTION_EXECUTE_HANDLER)
                    {

                        ntStatus = GetExceptionCode();
                    }
                }

                //
                // Uninitialize the cache map. This call is unconditional.
                //

                AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
                              pFcb,
                              pFileObject);

                CcUninitializeCacheMap( pFileObject,
                                        NULL,
                                        NULL);

                //
                // Unlock all outstanding locks on the file, again, unconditionally
                //

                (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
                                           pFileObject,
                                           IoGetRequestorProcess( Irp),
                                           NULL);

                //
                // Tell the service to unlock all on the file
                //

                ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;

                //
                // Perform some final common processing
                //

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
                {

                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
                }

                stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                {

                    stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;

                    stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
                    {

                        stFileCleanup.CreateTime = pObjectInfo->CreationTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
                    {

                        stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
                    {

                        stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
                    {

                        stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
                    }
                }

                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
                {

                    stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
                }

                //
                // If the count has dropped to zero and there is a pending delete
                // then delete the node
                //

                if( pFcb->OpenHandleCount == 0 &&
                    BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
                {

                    //
                    // Stop anything possibly in process
                    //

                    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
                                  &pFcb->NPFcb->Specific.File.ExtentsResource,
                                  PsGetCurrentThread());

                    AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
                                    TRUE);

                    pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;

                    KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
                                0,
                                FALSE);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
                                  &pFcb->NPFcb->Specific.File.ExtentsResource,
                                  PsGetCurrentThread());

                    AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);

                    //
                    // Before telling the server about the deleted file, tear down all extents for
                    // the file
                    //

                    AFSTearDownFcbExtents( pFcb,
                                           &pCcb->AuthGroup);

                    ntStatus = STATUS_SUCCESS;

                    ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    //
                    // Push the request to the service
                    //

                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                                  &pCcb->AuthGroup,
                                                  &pCcb->DirectoryCB->NameInformation.FileName,
                                                  &pObjectInfo->FileId,
                                                  &stFileCleanup,
                                                  sizeof( AFSFileCleanupCB),
                                                  NULL,
                                                  NULL);

                    if( !NT_SUCCESS( ntStatus) &&
                        ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
                    {

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_ERROR,
                                      "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
                                      &pCcb->FullFileName,
                                      ntStatus);

                        ntStatus = STATUS_SUCCESS;

                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
                    }
                    else
                    {

                        ntStatus = STATUS_SUCCESS;

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
                                      &pCcb->FullFileName,
                                      pCcb->DirectoryCB);

                        SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);

                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);

                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                        pCcb,
                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
                                                        (ULONG)FILE_ACTION_REMOVED);

                        //
                        // Now that the service has the entry has deleted we need to remove it from the parent
                        // tree so another lookup on the node will fail
                        //

                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
                        {

                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                            TRUE);

                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_VERBOSE,
                                          "AFSCleanup DE %p for %wZ removing entry\n",
                                          pCcb->DirectoryCB,
                                          &pCcb->DirectoryCB->NameInformation.FileName);

                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
                                                pCcb->DirectoryCB);

                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                        }
                        else
                        {

                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_VERBOSE,
                                          "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
                                          pCcb->DirectoryCB,
                                          &pCcb->DirectoryCB->NameInformation.FileName);
                        }
                    }
                }
                else
                {

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                    {

                        ULONG ulNotifyFilter = 0;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);

                        ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);

                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                        pCcb,
                                                        (ULONG)ulNotifyFilter,
                                                        (ULONG)FILE_ACTION_MODIFIED);
                    }

                    //
                    // Attempt to flush any dirty extents to the server. This may be a little
                    // aggressive, to flush whenever the handle is closed, but it ensures
                    // coherency.
                    //

                    if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
                        pFcb->Specific.File.ExtentsDirtyCount != 0)
                    {

                        AFSFlushExtents( pFcb,
                                         &pCcb->AuthGroup);
                    }

                    if( pFcb->OpenHandleCount == 0)
                    {

                        //
                        // Wait for any outstanding queued flushes to complete
                        //

                        AFSWaitOnQueuedFlushes( pFcb);

                        ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
                    }

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    //
                    // Push the request to the service
                    //

                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                       &pCcb->AuthGroup,
                                       &pCcb->DirectoryCB->NameInformation.FileName,
                                       &pObjectInfo->FileId,
                                       &stFileCleanup,
                                       sizeof( AFSFileCleanupCB),
                                       NULL,
                                       NULL);
                }

                //
                // Remove the share access at this time since we may not get the close for sometime on this FO.
                //

                IoRemoveShareAccess( pFileObject,
                                     &pFcb->ShareAccess);

                //
                // We don't need the name array after the user closes the handle on the file
                //

                if( pCcb->NameArray != NULL)
                {

                    AFSFreeNameArray( pCcb->NameArray);

                    pCcb->NameArray = NULL;
                }

                //
                // Decrement the open child handle count
                //

                if( pObjectInfo->ParentObjectInformation != NULL)
                {

                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
                }

                //
                // And finally, release the Fcb if we acquired it.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                break;
            }

            //
            // Root or directory node
            //

            case AFS_ROOT_FCB:
            {

                //
                // Set the root Fcb to this node
                //

                pRootFcb = pFcb;

                //
                // Fall through to below
                //
            }

            case AFS_DIRECTORY_FCB:
            {

                //
                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                //

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                  TRUE);

                //
                // Perform some final common processing
                //

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
                {

                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
                }

                stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                {

                    stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
                    {

                        stFileCleanup.CreateTime = pObjectInfo->CreationTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
                    {

                        stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
                    {

                        stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
                    }
                }

                //
                // If the count has dropped to zero and there is a pending delete
                // then delete the node
                //

                if( pFcb->OpenHandleCount == 0 &&
                    BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
                {

                    //
                    // Try to notify the service about the delete
                    //

                    ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    //
                    // Push the request to the service
                    //

                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                                  &pCcb->AuthGroup,
                                                  &pCcb->DirectoryCB->NameInformation.FileName,
                                                  &pObjectInfo->FileId,
                                                  &stFileCleanup,
                                                  sizeof( AFSFileCleanupCB),
                                                  NULL,
                                                  NULL);

                    if( !NT_SUCCESS( ntStatus) &&
                        ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
                    {

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_ERROR,
                                      "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
                                      &pCcb->FullFileName,
                                      ntStatus);

                        ntStatus = STATUS_SUCCESS;

                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
                    }
                    else
                    {

                        ntStatus = STATUS_SUCCESS;

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
                                      &pCcb->FullFileName,
                                      pCcb->DirectoryCB);

                        SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);

                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);

                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                        pCcb,
                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
                                                        (ULONG)FILE_ACTION_REMOVED);

                        //
                        // Now that the service has the entry has deleted we need to remove it from the parent
                        // tree so another lookup on the node will fail
                        //

                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
                        {

                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                            TRUE);

                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
                                                pCcb->DirectoryCB);

                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                        }
                        else
                        {

                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_VERBOSE,
                                          "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
                                          pCcb->DirectoryCB,
                                          &pCcb->DirectoryCB->NameInformation.FileName);
                        }
                    }
                }

                //
                // If there have been any updates to the node then push it to
                // the service
                //

                else
                {

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                    {

                        ULONG ulNotifyFilter = 0;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);

                        if(  pObjectInfo->ParentObjectInformation != NULL)
                        {

                            ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);

                            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                            pCcb,
                                                            (ULONG)ulNotifyFilter,
                                                            (ULONG)FILE_ACTION_MODIFIED);
                        }
                    }

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                       &pCcb->AuthGroup,
                                       &pCcb->DirectoryCB->NameInformation.FileName,
                                       &pObjectInfo->FileId,
                                       &stFileCleanup,
                                       sizeof( AFSFileCleanupCB),
                                       NULL,
                                       NULL);
                }

                //
                // Release the notification for this directory if there is one
                //

                FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
                                    &pControlDeviceExt->Specific.Control.DirNotifyList,
                                    pCcb);

                //
                // Remove the share access at this time since we may not get the close for sometime on this FO.
                //

                IoRemoveShareAccess( pFileObject,
                                     &pFcb->ShareAccess);

                //
                // We don't need the name array after the user closes the handle on the file
                //

                if( pCcb->NameArray != NULL)
                {

                    AFSFreeNameArray( pCcb->NameArray);

                    pCcb->NameArray = NULL;
                }

                //
                // Decrement the open child handle count
                //

                if( pObjectInfo->ParentObjectInformation != NULL)
                {

                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
                }

                //
                // And finally, release the Fcb if we acquired it.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                break;
            }

            case AFS_SYMBOLIC_LINK_FCB:
            case AFS_MOUNT_POINT_FCB:
            case AFS_DFS_LINK_FCB:
            case AFS_INVALID_FCB:
            {

                //
                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                //

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                  TRUE);

                //
                // Perform some final common processing
                //

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
                {

                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
                }

                stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                {

                    stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
                    {

                        stFileCleanup.CreateTime = pObjectInfo->CreationTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
                    {

                        stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
                    {

                        stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
                    }
                }

                //
                // If the count has dropped to zero and there is a pending delete
                // then delete the node
                //

                if( pFcb->OpenHandleCount == 0 &&
                    BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
                {

                    //
                    // Try to notify the service about the delete
                    //

                    ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    //
                    // Push the request to the service
                    //

                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                                  &pCcb->AuthGroup,
                                                  &pCcb->DirectoryCB->NameInformation.FileName,
                                                  &pObjectInfo->FileId,
                                                  &stFileCleanup,
                                                  sizeof( AFSFileCleanupCB),
                                                  NULL,
                                                  NULL);

                    if( !NT_SUCCESS( ntStatus) &&
                        ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
                    {

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_ERROR,
                                      "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
                                      &pCcb->FullFileName,
                                      ntStatus);

                        ntStatus = STATUS_SUCCESS;

                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
                    }
                    else
                    {

                        ntStatus = STATUS_SUCCESS;

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
                                      &pCcb->FullFileName,
                                      pCcb->DirectoryCB);

                        SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);

                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);

                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                        pCcb,
                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
                                                        (ULONG)FILE_ACTION_REMOVED);

                        //
                        // Now that the service has the entry has deleted we need to remove it from the parent
                        // tree so another lookup on the node will fail
                        //

                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
                        {

                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                            TRUE);

                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
                                                pCcb->DirectoryCB);

                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                        }
                        else
                        {

                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_VERBOSE,
                                          "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
                                          pCcb->DirectoryCB,
                                          &pCcb->DirectoryCB->NameInformation.FileName);
                        }
                    }
                }

                //
                // If there have been any updates to the node then push it to
                // the service
                //

                else
                {

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                    {

                        ULONG ulNotifyFilter = 0;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);

                        if(  pObjectInfo->ParentObjectInformation != NULL)
                        {

                            ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);

                            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                            pCcb,
                                                            (ULONG)ulNotifyFilter,
                                                            (ULONG)FILE_ACTION_MODIFIED);
                        }
                    }

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                       &pCcb->AuthGroup,
                                       &pCcb->DirectoryCB->NameInformation.FileName,
                                       &pObjectInfo->FileId,
                                       &stFileCleanup,
                                       sizeof( AFSFileCleanupCB),
                                       NULL,
                                       NULL);
                }

                //
                // Remove the share access at this time since we may not get the close for sometime on this FO.
                //

                IoRemoveShareAccess( pFileObject,
                                     &pFcb->ShareAccess);

                //
                // We don't need the name array after the user closes the handle on the file
                //

                if( pCcb->NameArray != NULL)
                {

                    AFSFreeNameArray( pCcb->NameArray);

                    pCcb->NameArray = NULL;
                }

                //
                // Decrement the open child handle count
                //

                if( pObjectInfo->ParentObjectInformation != NULL)
                {

                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
                }

                //
                // And finally, release the Fcb if we acquired it.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                break;
            }

            case AFS_SPECIAL_SHARE_FCB:
            {

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                //
                // Decrement the open child handle count
                //

                if( pObjectInfo->ParentObjectInformation != NULL &&
                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
                {

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
                }

                //
                // And finally, release the Fcb if we acquired it.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                break;
            }

            default:

                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSCleanup Processing unknown node type %d\n",
                              pFcb->Header.NodeTypeCode);

                break;
        }


try_exit:

        if( pFileObject != NULL)
        {

            //
            // Setup the fileobject flags to indicate cleanup is complete.
            //

            SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
        }

        //
        // Complete the request
        //

        AFSCompleteRequest( Irp, ntStatus);
    }
コード例 #15
0
ファイル: write.c プロジェクト: bailey27/dokany
NTSTATUS
DokanDispatchWrite(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) {
  PIO_STACK_LOCATION irpSp;
  PFILE_OBJECT fileObject;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  PEVENT_CONTEXT eventContext;
  ULONG eventLength;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  PVOID buffer;
  BOOLEAN writeToEoF = FALSE;
  BOOLEAN isPagingIo = FALSE;
  BOOLEAN isNonCached = FALSE;
  BOOLEAN isSynchronousIo = FALSE;
  BOOLEAN fcbLocked = FALSE;

  __try {

    DDbgPrint("==> DokanWrite\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    //
    //  If this is a zero length write then return SUCCESS immediately.
    //

    if (irpSp->Parameters.Write.Length == 0) {
      DDbgPrint("  Parameters.Write.Length == 0\n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_DEVICE_REQUEST;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;

    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);

    ccb = fileObject->FsContext2;
    ASSERT(ccb != NULL);

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);

    if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (Irp->MdlAddress) {
      DDbgPrint("  use MdlAddress\n");
      buffer = MmGetSystemAddressForMdlNormalSafe(Irp->MdlAddress);
    } else {
      DDbgPrint("  use UserBuffer\n");
      buffer = Irp->UserBuffer;
    }

    if (buffer == NULL) {
      DDbgPrint("  buffer == NULL\n");
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (irpSp->Parameters.Write.ByteOffset.LowPart ==
            FILE_WRITE_TO_END_OF_FILE &&
        irpSp->Parameters.Write.ByteOffset.HighPart == -1) {
      writeToEoF = TRUE;
    }

    if (Irp->Flags & IRP_PAGING_IO) {
      isPagingIo = TRUE;
    }

    if (Irp->Flags & IRP_NOCACHE) {
      isNonCached = TRUE;
    }

    if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
      isSynchronousIo = TRUE;
    }

    if (!isPagingIo && (fileObject->SectionObjectPointer != NULL) &&
        (fileObject->SectionObjectPointer->DataSectionObject != NULL)) {
      ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
      CcFlushCache(&fcb->SectionObjectPointers,
                   writeToEoF ? NULL : &irpSp->Parameters.Write.ByteOffset,
                   irpSp->Parameters.Write.Length, NULL);
      CcPurgeCacheSection(&fcb->SectionObjectPointers,
                          writeToEoF ? NULL
                                     : &irpSp->Parameters.Write.ByteOffset,
                          irpSp->Parameters.Write.Length, FALSE);
      ExReleaseResourceLite(&fcb->PagingIoResource);
    }

    // Cannot write at end of the file when using paging IO
    if (writeToEoF && isPagingIo) {
      DDbgPrint("  writeToEoF & isPagingIo\n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    // the length of EventContext is sum of length to write and length of file
    // name
    DokanFCBLockRO(fcb);
    fcbLocked = TRUE;
    eventLength = sizeof(EVENT_CONTEXT) + irpSp->Parameters.Write.Length +
                  fcb->FileName.Length;

    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

    // no more memory!
    if (eventContext == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      __leave;
    }

    eventContext->Context = ccb->UserContext;
    // DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

    // When the length is bigger than usual event notitfication buffer,
    // saves pointer in DiverContext to copy EventContext after allocating
    // more bigger memory.
    Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = eventContext;

    if (isPagingIo) {
      DDbgPrint("  Paging IO\n");
      eventContext->FileFlags |= DOKAN_PAGING_IO;
    }
    if (isSynchronousIo) {
      DDbgPrint("  Synchronous IO\n");
      eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO;
    }
    if (isNonCached) {
      DDbgPrint("  Nocache\n");
      eventContext->FileFlags |= DOKAN_NOCACHE;
    }

    // offset of file to write
    eventContext->Operation.Write.ByteOffset =
        irpSp->Parameters.Write.ByteOffset;

    if (writeToEoF) {
      eventContext->FileFlags |= DOKAN_WRITE_TO_END_OF_FILE;
      DDbgPrint("  WriteOffset = end of file\n");
    }

    if (isSynchronousIo &&
        ((irpSp->Parameters.Write.ByteOffset.LowPart ==
          FILE_USE_FILE_POINTER_POSITION) &&
         (irpSp->Parameters.Write.ByteOffset.HighPart == -1))) {
      // NOTE:
      // http://msdn.microsoft.com/en-us/library/ms795960.aspx
      // Do not check IrpSp->Parameters.Write.ByteOffset.QuadPart == 0
      // Probably the document is wrong.
      eventContext->Operation.Write.ByteOffset.QuadPart =
          fileObject->CurrentByteOffset.QuadPart;
    }

    // the size of buffer to write
    eventContext->Operation.Write.BufferLength = irpSp->Parameters.Write.Length;

    // the offset from the begining of structure
    // the contents to write will be copyed to this offset
    eventContext->Operation.Write.BufferOffset =
        FIELD_OFFSET(EVENT_CONTEXT, Operation.Write.FileName[0]) +
        fcb->FileName.Length + sizeof(WCHAR); // adds last null char

    // copies the content to write to EventContext
    RtlCopyMemory((PCHAR)eventContext +
                      eventContext->Operation.Write.BufferOffset,
                  buffer, irpSp->Parameters.Write.Length);

    // copies file name
    eventContext->Operation.Write.FileNameLength = fcb->FileName.Length;
    RtlCopyMemory(eventContext->Operation.Write.FileName, fcb->FileName.Buffer,
                  fcb->FileName.Length);

    // When eventlength is less than event notification buffer,
    // returns it to user-mode using pending event.
    if (eventLength <= EVENT_CONTEXT_MAX_SIZE) {

      DDbgPrint("   Offset %d:%d, Length %d\n",
                irpSp->Parameters.Write.ByteOffset.HighPart,
                irpSp->Parameters.Write.ByteOffset.LowPart,
                irpSp->Parameters.Write.Length);

      // EventContext is no longer needed, clear it
      Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;

      //
      //  We now check whether we can proceed based on the state of
      //  the file oplocks.
      //
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
        status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext,
                                  DokanOplockComplete, DokanPrePostIrp);

        //
        //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
        //  to service an oplock break and we need to leave now.
        //
        if (status != STATUS_SUCCESS) {
          if (status == STATUS_PENDING) {
            DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
          } else {
            DokanFreeEventContext(eventContext);
          }
          __leave;
        }
      }

      // register this IRP to IRP waiting list and make it pending status
      status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

      // Resuests bigger memory
      // eventContext will be freed later using
      // Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT]
    } else {
      // the length at lest file name can be stored
      ULONG requestContextLength = max(
          sizeof(EVENT_CONTEXT), eventContext->Operation.Write.BufferOffset);
      PEVENT_CONTEXT requestContext =
          AllocateEventContext(vcb->Dcb, Irp, requestContextLength, ccb);

      // no more memory!
      if (requestContext == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;
        DokanFreeEventContext(eventContext);
        __leave;
      }

      DDbgPrint("   Offset %d:%d, Length %d (request)\n",
                irpSp->Parameters.Write.ByteOffset.HighPart,
                irpSp->Parameters.Write.ByteOffset.LowPart,
                irpSp->Parameters.Write.Length);

      // copies from begining of EventContext to the end of file name
      RtlCopyMemory(requestContext, eventContext,
                    eventContext->Operation.Write.BufferOffset);
      // puts actual size of RequestContext
      requestContext->Length = requestContextLength;
      // requsts enough size to copy EventContext
      requestContext->Operation.Write.RequestLength = eventLength;

      //
      //  We now check whether we can proceed based on the state of
      //  the file oplocks.
      //
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
        status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, requestContext,
                                  DokanOplockComplete, DokanPrePostIrp);

        //
        //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
        //  to service an oplock break and we need to leave now.
        //
        if (status != STATUS_SUCCESS) {
          if (status == STATUS_PENDING) {
            DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
          } else {
            DokanFreeEventContext(requestContext);
            Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;
            DokanFreeEventContext(eventContext);
          }
          __leave;
        }
      }

      // regiters this IRP to IRP wainting list and make it pending status
      status = DokanRegisterPendingIrp(DeviceObject, Irp, requestContext, 0);
    }

  } __finally {
    if(fcbLocked)
      DokanFCBUnlock(fcb);

    DokanCompleteIrpRequest(Irp, status, 0);

    DDbgPrint("<== DokanWrite\n");
  }

  return status;
}
コード例 #16
0
ファイル: write.c プロジェクト: Axure/Ext3Fsd
NTSTATUS
Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
{
    PEXT2_VCB           Vcb = NULL;
    PEXT2_FCB           Fcb = NULL;
    PEXT2_CCB           Ccb = NULL;
    PFILE_OBJECT        FileObject = NULL;

    PDEVICE_OBJECT      DeviceObject = NULL;

    PIRP                Irp = NULL;
    PIO_STACK_LOCATION  IoStackLocation = NULL;
    PUCHAR              Buffer = NULL;

    LARGE_INTEGER       ByteOffset;
    ULONG               ReturnedLength = 0;
    ULONG               Length;

    NTSTATUS            Status = STATUS_UNSUCCESSFUL;

    BOOLEAN             OpPostIrp = FALSE;
    BOOLEAN             PagingIo = FALSE;
    BOOLEAN             Nocache = FALSE;
    BOOLEAN             SynchronousIo = FALSE;

    BOOLEAN             RecursiveWriteThrough = FALSE;
    BOOLEAN             MainResourceAcquired = FALSE;
    BOOLEAN             PagingIoResourceAcquired = FALSE;

    BOOLEAN             bDeferred = FALSE;
    BOOLEAN             UpdateFileValidSize = FALSE;
    BOOLEAN             FileSizesChanged = FALSE;
    BOOLEAN             rc;


    __try {

        ASSERT(IrpContext);
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;
        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        FileObject = IrpContext->FileObject;
        Fcb = (PEXT2_FCB) FileObject->FsContext;
        Ccb = (PEXT2_CCB) FileObject->FsContext2;
        ASSERT(Fcb);
        ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
               (Fcb->Identifier.Size == sizeof(EXT2_FCB)));

        Irp = IrpContext->Irp;
        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

        Length = IoStackLocation->Parameters.Write.Length;
        ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

        PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
        Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE);
        SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

        if (PagingIo) {
            ASSERT(Nocache);
        }

        DEBUG(DL_INF, ("Ext2WriteFile: %wZ Offset=%I64xh Length=%xh Paging=%xh Nocache=%xh\n",
                       &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));

        if (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        if (IsFileDeleted(Fcb->Mcb) ||
            (IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ) {
            Status = STATUS_FILE_DELETED;
            __leave;
        }

        if (Length == 0) {
            Irp->IoStatus.Information = 0;
            Status = STATUS_SUCCESS;
            __leave;
        }

        if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION &&
            ByteOffset.HighPart == -1) {
            ByteOffset = FileObject->CurrentByteOffset;
        } else if (IsWritingToEof(ByteOffset)) {
            ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
        }

        if (Nocache && !PagingIo &&
            ( (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 (!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 ) ) {

                Status = Ext2LockUserBuffer(
                             IrpContext->Irp,
                             Length,
                             IoReadAccess);

                if (NT_SUCCESS(Status)) {
                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
                    CcDeferWrite( FileObject,
                                  (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite,
                                  IrpContext,
                                  Irp,
                                  Length,
                                  bAgain );
                    bDeferred = TRUE;
                    Status = STATUS_PENDING;
                    __leave;
                }
            }
        }

        if (IsDirectory(Fcb) && !PagingIo) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        if (IsFlagOn(Irp->Flags, IRP_SYNCHRONOUS_PAGING_IO) && !IrpContext->IsTopLevel) {

            PIRP TopIrp;

            TopIrp = IoGetTopLevelIrp();

            if ( (ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG &&
                    NodeType(TopIrp) == IO_TYPE_IRP) {

                PIO_STACK_LOCATION IrpStack;

                IrpStack = IoGetCurrentIrpStackLocation(TopIrp);

                if ((IrpStack->MajorFunction == IRP_MJ_WRITE) &&
                    (IrpStack->FileObject->FsContext == FileObject->FsContext) &&
                    !FlagOn(TopIrp->Flags, IRP_NOCACHE) ) {

                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
                    RecursiveWriteThrough = TRUE;
                }
            }
        }

        if (PagingIo) {

            if (!ExAcquireResourceSharedLite(&Fcb->PagingIoResource, TRUE)) {
                Status = STATUS_PENDING;
                __leave;
            }
            PagingIoResourceAcquired = TRUE;

            if ( (ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) {

                if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {

                    Status = STATUS_SUCCESS;
                    Irp->IoStatus.Information = 0;
                    __leave;

                } else {

                    ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
                    if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart)
                        Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart);
                }

            } else {

                ReturnedLength = Length;
            }

        } else {

            if (!Ext2CheckFileAccess(Vcb, Fcb->Mcb, Ext2FileCanWrite)) {
                Status = STATUS_ACCESS_DENIED;
                __leave;
            }

            if (IsDirectory(Fcb)) {
                __leave;
            }

            if (!ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE)) {
                Status = STATUS_PENDING;
                __leave;
            }
            MainResourceAcquired = TRUE;

            //
            //  Do flushing for such cases
            //
            if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject != NULL)  {

                ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
                ExReleaseResourceLite(&Fcb->PagingIoResource);

                CcFlushCache( &(Fcb->SectionObject),
                              &ByteOffset,
                              CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE),
                              &(Irp->IoStatus));
                ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);

                if (!NT_SUCCESS(Irp->IoStatus.Status)) {
                    Status = Irp->IoStatus.Status;
                    __leave;
                }

                ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
                ExReleaseResourceLite(&Fcb->PagingIoResource);

                CcPurgeCacheSection( &(Fcb->SectionObject),
                                     &(ByteOffset),
                                     CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE),
                                     FALSE );
            }

            if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLockAnchor, Irp)) {
                Status = STATUS_FILE_LOCK_CONFLICT;
                __leave;
            }

            if (Ccb != NULL) {

                Status = FsRtlCheckOplock( &Fcb->Oplock,
                                           Irp,
                                           IrpContext,
                                           Ext2OplockComplete,
                                           Ext2LockIrp );

                if (Status != STATUS_SUCCESS) {
                    OpPostIrp = TRUE;
                    __leave;
                }

                //
                //  Set the flag indicating if Fast I/O is possible
                //

                Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
            }

            //
            //  Extend the inode size when the i/o is beyond the file end ?
            //

            if ((ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) {

                LARGE_INTEGER AllocationSize, Last;

                if (!ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE)) {
                    Status = STATUS_PENDING;
                    __leave;
                }
                PagingIoResourceAcquired = TRUE;

                /* let this irp wait, since it has to be synchronous */
                SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);

                Last.QuadPart = Fcb->Header.AllocationSize.QuadPart;
                AllocationSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);
                AllocationSize.QuadPart = CEILING_ALIGNED(ULONGLONG,
                                          (ULONGLONG)AllocationSize.QuadPart,
                                          (ULONGLONG)BLOCK_SIZE);

                /* tell Ext2ExpandFile to allocate unwritten extent or NULL blocks
                   for indirect files, otherwise we might get gabage data in holes */
                IrpContext->MajorFunction += IRP_MJ_MAXIMUM_FUNCTION;
                Status = Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &AllocationSize);
                IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION;
                if (AllocationSize.QuadPart > Last.QuadPart) {
                    Fcb->Header.AllocationSize.QuadPart = AllocationSize.QuadPart;
                    SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_WRITE);
                }
                ExReleaseResourceLite(&Fcb->PagingIoResource);
                PagingIoResourceAcquired = FALSE;

                if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) {
                    if (NT_SUCCESS(Status)) {
                        DbgBreak();
                        Status = STATUS_UNSUCCESSFUL;
                    }
                    __leave;
                }

                if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) {
                    Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart);
                }

                Fcb->Header.FileSize.QuadPart = Fcb->Inode->i_size = ByteOffset.QuadPart + Length;
                Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);

                if (CcIsFileCached(FileObject)) {
                    CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                }

                FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED;
                FileSizesChanged = TRUE;

                if (Fcb->Header.FileSize.QuadPart >= 0x80000000 &&
                        !IsFlagOn(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
                    SetFlag(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
                    Ext2SaveSuper(IrpContext, Vcb);
                }

                DEBUG(DL_IO, ("Ext2WriteFile: expanding %wZ to FS: %I64xh FA: %I64xh\n",
                              &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
                              Fcb->Header.AllocationSize.QuadPart));
            }

            ReturnedLength = Length;
        }

        if (!Nocache) {

            if (FileObject->PrivateCacheMap == NULL) {
                CcInitializeCacheMap(
                    FileObject,
                    (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
                    FALSE,
                    &Ext2Global->CacheManagerCallbacks,
                    Fcb );

                CcSetReadAheadGranularity(
                    FileObject,
                    READ_AHEAD_GRANULARITY );
            }

            if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {

                CcPrepareMdlWrite(
                    FileObject,
                    &ByteOffset,
                    Length,
                    &Irp->MdlAddress,
                    &Irp->IoStatus );

                Status = Irp->IoStatus.Status;

            } else {

                Buffer = Ext2GetUserBuffer(Irp);
                if (Buffer == NULL) {
                    DbgBreak();
                    Status = STATUS_INVALID_USER_BUFFER;
                    __leave;
                }

                if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {

                    /* let this irp wait, since it has to be synchronous */
                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);

                    rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
                                      &Fcb->Header.ValidDataLength, &ByteOffset);
                    if (!rc) {
                        Status = STATUS_PENDING;
                        DbgBreak();
                        __leave;
                    }
                }

                if (!CcCopyWrite(FileObject, &ByteOffset, Length, Ext2CanIWait(), Buffer)) {
                    if (Ext2CanIWait() || 
                        !CcCopyWrite(FileObject,  &ByteOffset, Length, TRUE, Buffer)) {
                        Status = STATUS_PENDING;
                        DbgBreak();
                        __leave;
                    }
                }

                if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {

                    if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
                        Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
                    } else {
                        if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
                            Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length;
                    }

                    CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    FileSizesChanged = TRUE;
                }

                Status = STATUS_SUCCESS;
            }

            if (NT_SUCCESS(Status)) {
                Irp->IoStatus.Information = Length;
                if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
                    DEBUG(DL_FLP, ("Ext2WriteFile is starting FlushingDpc...\n"));
                    Ext2StartFloppyFlushDpc(Vcb, Fcb, FileObject);
                }
            }

        } else {

            if (!PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {
                if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {

                    /* let this irp wait, since it has to be synchronous */
                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
                    rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
                                      &Fcb->Header.ValidDataLength,
                                      &ByteOffset);
                    if (!rc) {
                        Status = STATUS_PENDING;
                        DbgBreak();
                        __leave;
                    }
                }
            }

            Status = Ext2LockUserBuffer(
                         IrpContext->Irp,
                         Length,
                         IoReadAccess );

            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            Irp->IoStatus.Status = STATUS_SUCCESS;
            Irp->IoStatus.Information = ReturnedLength;

            Status = Ext2WriteInode(
                         IrpContext,
                         Vcb,
                         Fcb->Mcb,
                         (ULONGLONG)(ByteOffset.QuadPart),
                         NULL,
                         ReturnedLength,
                         TRUE,
                         &Length
                     );

            Irp = IrpContext->Irp;

            if (NT_SUCCESS(Status) && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {

                if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {

                    FileSizesChanged = TRUE;

                    if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
                        if (!PagingIo)
                            Fcb->Header.FileSize.QuadPart = ByteOffset.QuadPart + Length;
                        Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
                    } else {
                        if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
                            Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length;
                    }

                    if (!PagingIo && CcIsFileCached(FileObject)) {
                        CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    }

                    DEBUG(DL_IO, ("Ext2WriteFile: %wZ written FS: %I64xh FA: %I64xh BO: %I64xh LEN: %u\n",
                                  &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
                                   Fcb->Header.AllocationSize.QuadPart, ByteOffset.QuadPart, Length));
                }
            }
        }

        if (FileSizesChanged) {
            FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED;
            Ext2NotifyReportChange( IrpContext,  Vcb, Fcb->Mcb,
                                    FILE_NOTIFY_CHANGE_SIZE,
                                    FILE_ACTION_MODIFIED );
        }

    } __finally {

        /*
         *  in case we got excpetions, we need revert MajorFunction
         *  back to IRP_MJ_WRITE. The reason we do this, is to tell
         *  Ext2ExpandFile to allocate unwritten extent or don't add
         *  new blocks for indirect files.
         */
        if (IrpContext->MajorFunction > IRP_MJ_MAXIMUM_FUNCTION)
            IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION;

        if (Irp) {
            if (PagingIoResourceAcquired) {
                ExReleaseResourceLite(&Fcb->PagingIoResource);
            }

            if (MainResourceAcquired) {
                ExReleaseResourceLite(&Fcb->MainResource);
            }
        }

        if (!OpPostIrp && !IrpContext->ExceptionInProgress) {

            if (Irp) {

                if (Status == STATUS_PENDING ||
                        Status == STATUS_CANT_WAIT ) {

                    if (!bDeferred) {
                        Status = Ext2QueueRequest(IrpContext);
                    }

                } else {

                    if (NT_SUCCESS(Status) && !PagingIo) {

                        if (SynchronousIo) {
                            FileObject->CurrentByteOffset.QuadPart =
                                ByteOffset.QuadPart + Irp->IoStatus.Information;
                        }

                        SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                        SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
                    }

                    Ext2CompleteIrpContext(IrpContext, Status);
                }
            } else {
                Ext2FreeIrpContext(IrpContext);
            }
        }
    }

    DEBUG(DL_IO, ("Ext2WriteFile: %wZ written at Offset=%I64xh Length=%xh PagingIo=%d Nocache=%d "
                  "RetLen=%xh VDL=%I64xh FileSize=%I64xh i_size=%I64xh Status=%xh\n",
                  &Fcb->Mcb->ShortName, ByteOffset, Length, PagingIo, Nocache, ReturnedLength,
                  Fcb->Header.ValidDataLength.QuadPart,Fcb->Header.FileSize.QuadPart,
                  Fcb->Inode->i_size, Status));

    return Status;
}
コード例 #17
0
ファイル: cleanup.c プロジェクト: OleStauning/dokanx
NTSTATUS
DokanDispatchCleanup(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
	)

/*++

Routine Description:

	This device control dispatcher handles Cleanup IRP.

Arguments:

	DeviceObject - Context for the activity.
	Irp 		 - The device control argument block.

Return Value:

	NTSTATUS

--*/
{
	PDokanVCB			vcb;
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status = STATUS_INVALID_PARAMETER;
	PFILE_OBJECT		fileObject;
	PDokanCCB			ccb = NULL;
	PDokanFCB			fcb = NULL;
	PEVENT_CONTEXT		eventContext;
	ULONG				eventLength;

	//PAGED_CODE();

	__try {

		FsRtlEnterFileSystem();

		DDbgPrint("==> DokanCleanup");
	
		irpSp = IoGetCurrentIrpStackLocation(Irp);
		fileObject = irpSp->FileObject;

		DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
		DokanPrintFileName(fileObject);

		// Cleanup must be success in any case
		if (fileObject == NULL) {
			DDbgPrint("  fileObject == NULL");
			status = STATUS_SUCCESS;
			__leave;
		}

		vcb = DeviceObject->DeviceExtension;
		if (GetIdentifierType(vcb) != VCB ||
			!DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
			status = STATUS_SUCCESS;
			__leave;
		}

		ccb = fileObject->FsContext2;
		ASSERT(ccb != NULL);

		fcb = ccb->Fcb;
		ASSERT(fcb != NULL);

		eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;
		eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

		if (eventContext == NULL) {
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		if (fileObject->SectionObjectPointer != NULL &&
			fileObject->SectionObjectPointer->DataSectionObject != NULL) {
			CcFlushCache(&fcb->SectionObjectPointers, NULL, 0, NULL);
			CcPurgeCacheSection(&fcb->SectionObjectPointers, NULL, 0, FALSE);
			CcUninitializeCacheMap(fileObject, NULL, NULL);
		}
		fileObject->Flags |= FO_CLEANUP_COMPLETE;

		eventContext->Context = ccb->UserContext;
		//DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

		// copy the filename to EventContext from ccb
		eventContext->Cleanup.FileNameLength = fcb->FileName.Length;
		RtlCopyMemory(eventContext->Cleanup.FileName, fcb->FileName.Buffer, fcb->FileName.Length);

		// register this IRP to pending IRP list
		status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

	} __finally {

		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = 0;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		}

		DDbgPrint("<== DokanCleanup");
	
		FsRtlExitFileSystem();
	}

	return status;
}
コード例 #18
0
NTSTATUS
xixfs_FlusVolume(
	IN PXIXFS_IRPCONTEXT IrpContext,
	IN PXIXFS_VCB		pVCB
)
{
	PVOID RestartKey = NULL;
	PXIXFS_FCB ThisFcb = NULL;
	PXIXFS_FCB NextFcb = NULL;
	
	BOOLEAN RemovedFcb = FALSE;
	BOOLEAN	CanWait = FALSE;
	uint32	lockedVcbValue = 0;

	PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Enter  xixfs_FlusVolume\n"));

	ASSERT_EXCLUSIVE_VCB(pVCB);

	CanWait = XIXCORE_TEST_FLAGS(IrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT);

	xixfs_RealCloseFCB(pVCB);

	while (TRUE) {
		
		XifsdLockVcb( IrpContext, pVCB );
		NextFcb = xixfs_FCBTLBGetNextEntry(pVCB, &RestartKey );

		//
		//  Reference the NextFcb if present.
		//

		if (NextFcb != NULL) {

			NextFcb->FCBReference += 1;
		}

		//
		//  If the last Fcb is present then decrement reference count and call teardown
		//  to see if it should be removed.
		//

		if (ThisFcb != NULL) {

			ThisFcb->FCBReference -= 1;

			XifsdUnlockVcb( IrpContext, pVCB );

		} else {

			XifsdUnlockVcb( IrpContext, pVCB );
		}

		//
		//  Break out of the loop if no more Fcb's.
		//

		if (NextFcb == NULL) {

			break;
		}

		//
		//  Move to the next Fcb.
		//

		ThisFcb = NextFcb;

		//
		//  If there is a image section then see if that can be closed.
		//

		if(ThisFcb->XixcoreFcb.FCBType == FCB_TYPE_FILE){
			
			DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO), 
						 ("XifsdPurgeVolume FCB(%I64d) \n", 
						 ThisFcb->XixcoreFcb.LotNumber));
			
			XifsdAcquireFcbExclusive(TRUE, ThisFcb, FALSE);
			//ExAcquireResourceShared(ThisFcb->PagingIoResource, TRUE);


			if(XIXCORE_TEST_FLAGS(ThisFcb->XixcoreFcb.FCBFlags, XIXCORE_FCB_CACHED_FILE)){

				// Added by ILGU HONG for readonly 09052006
				if(!ThisFcb->PtrVCB->XixcoreVcb.IsVolumeWriteProtected){
					CcFlushCache(&ThisFcb->SectionObject, NULL, 0, NULL);
				}
				// Added by ILGU HONG for readonly end
				
			}
			//ExReleaseResource(ThisFcb->PagingIoResource);
			XifsdReleaseFcb(TRUE, ThisFcb);
		}

	}

	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Exit  xixfs_FlusVolume\n"));

	return STATUS_SUCCESS;
}
コード例 #19
0
ファイル: read.c プロジェクト: Corillian/dokany
NTSTATUS
DokanDispatchRead(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

/*++

Routine Description:

        This device control dispatcher handles read IRPs.

Arguments:

        DeviceObject - Context for the activity.
        Irp          - The device control argument block.

Return Value:

        NTSTATUS

--*/
{
  PIO_STACK_LOCATION irpSp;
  PFILE_OBJECT fileObject;
  ULONG bufferLength;
  LARGE_INTEGER byteOffset;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  ULONG readLength = 0;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  PVOID currentAddress = NULL;
  PEVENT_CONTEXT eventContext;
  ULONG eventLength;
  BOOLEAN fcbLocked = FALSE;
  BOOLEAN isPagingIo = FALSE;
  BOOLEAN isSynchronousIo = FALSE;
  BOOLEAN noCache = FALSE;

  __try {

    DDbgPrint("==> DokanRead\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    //
    //  If this is a zero length read then return SUCCESS immediately.
    //
    if (irpSp->Parameters.Read.Length == 0) {
      DDbgPrint("  Parameters.Read.Length == 0 \n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (irpSp->MinorFunction == IRP_MN_COMPLETE) {
      Irp->MdlAddress = NULL;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (fileObject == NULL && Irp->MdlAddress != NULL) {
      DDbgPrint("  Reads by File System Recognizers\n");

      currentAddress = MmGetSystemAddressForMdlNormalSafe(Irp->MdlAddress);
      if (currentAddress == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        __leave;
      }

      // here we could return the bootsector. If we don't have one
      // the requested read lenght must be returned as requested
      readLength = irpSp->Parameters.Read.Length;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_DEVICE_REQUEST;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;
    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_DEVICE_REQUEST;
      __leave;
    }

    bufferLength = irpSp->Parameters.Read.Length;
    if (irpSp->Parameters.Read.ByteOffset.LowPart ==
            FILE_USE_FILE_POINTER_POSITION &&
        irpSp->Parameters.Read.ByteOffset.HighPart == -1) {

      // irpSp->Parameters.Read.ByteOffset == NULL don't need check?

      DDbgPrint("use FileObject ByteOffset\n");

      byteOffset = fileObject->CurrentByteOffset;

    } else {
      byteOffset = irpSp->Parameters.Read.ByteOffset;
    }

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);
    DDbgPrint("  ByteCount:%lu ByteOffset:%I64d\n", bufferLength,
              byteOffset.QuadPart);

    if (bufferLength == 0) {
      status = STATUS_SUCCESS;
      readLength = 0;
      __leave;
    }

    // make a MDL for UserBuffer that can be used later on another thread
    // context
    if (Irp->MdlAddress == NULL) {
      status = DokanAllocateMdl(Irp, irpSp->Parameters.Read.Length);
      if (!NT_SUCCESS(status)) {
        __leave;
      }
    }

    ccb = fileObject->FsContext2;
    ASSERT(ccb != NULL);

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);

    if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) {
      DDbgPrint("   DOKAN_FILE_DIRECTORY %p\n", fcb);
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (Irp->Flags & IRP_PAGING_IO) {
      isPagingIo = TRUE;
    }
    if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
      isSynchronousIo = TRUE;
    }

    if (Irp->Flags & IRP_NOCACHE) {
      noCache = TRUE;
    }

    if (!isPagingIo && (fileObject->SectionObjectPointer != NULL) &&
        (fileObject->SectionObjectPointer->DataSectionObject != NULL)) {
      ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
      CcFlushCache(&fcb->SectionObjectPointers,
                   &irpSp->Parameters.Read.ByteOffset,
                   irpSp->Parameters.Read.Length, NULL);
      ExReleaseResourceLite(&fcb->PagingIoResource);
    }

    DokanFCBLockRO(fcb);
    fcbLocked = TRUE;
    // length of EventContext is sum of file name length and itself
    eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;

    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);
    if (eventContext == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      __leave;
    }

    eventContext->Context = ccb->UserContext;
    // DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

    if (isPagingIo) {
      DDbgPrint("  Paging IO\n");
      eventContext->FileFlags |= DOKAN_PAGING_IO;
    }
    if (isSynchronousIo) {
      DDbgPrint("  Synchronous IO\n");
      eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO;
    }

    if (noCache) {
      DDbgPrint("  Nocache\n");
      eventContext->FileFlags |= DOKAN_NOCACHE;
    }

    // offset of file to read
    eventContext->Operation.Read.ByteOffset = byteOffset;

    // buffer size for read
    // user-mode file system application can return this size
    eventContext->Operation.Read.BufferLength = irpSp->Parameters.Read.Length;

    // copy the accessed file name
    eventContext->Operation.Read.FileNameLength = fcb->FileName.Length;
    RtlCopyMemory(eventContext->Operation.Read.FileName, fcb->FileName.Buffer,
                  fcb->FileName.Length);

    //
    //  We now check whether we can proceed based on the state of
    //  the file oplocks.
    //
    if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext,
                                DokanOplockComplete, DokanPrePostIrp);

      //
      //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
      //  to service an oplock break and we need to leave now.
      //
      if (status != STATUS_SUCCESS) {
        if (status == STATUS_PENDING) {
          DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
        } else {
          DokanFreeEventContext(eventContext);
        }
        __leave;
      }

      //
      // We have to check for read access according to the current
      // state of the file locks, and set FileSize from the Fcb.
      //
      // FsRtlCheckLockForReadAccess does not block.
      if (!FsRtlCheckLockForReadAccess(&fcb->FileLock, Irp)) {
        status = STATUS_FILE_LOCK_CONFLICT;
        __leave;
      }
    }

    // register this IRP to pending IPR list and make it pending status
    status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);
  } __finally {
    if(fcbLocked)
      DokanFCBUnlock(fcb);

    DokanCompleteIrpRequest(Irp, status, readLength);

    DDbgPrint("<== DokanRead\n");
  }

  return status;
}
コード例 #20
0
ファイル: logsup.c プロジェクト: BaoYu0721/WRK-1.2
NTKERNELAPI
BOOLEAN
CcSetPrivateWriteFile(
    PFILE_OBJECT FileObject
    )

/*++

Routine Description:

    This routine will instruct the cache manager to treat the file as
    a private-write stream, so that a caller can implement a private
    logging mechanism for it.  We will turn on both Mm's modify-no-write
    and our disable-write-behind, and disallow non-aware flush/purge for
    the file.

    Caching must already be initiated on the file.

    This routine is only exported to the kernel.

Arguments:

    FileObject - File to make private-write.

Return Value:

    None.

--*/

{
    PSHARED_CACHE_MAP SharedCacheMap;
    BOOLEAN Disabled;
    KIRQL OldIrql;
    PVACB Vacb;
    ULONG ActivePage;
    ULONG PageIsDirty;

    //
    //  Pick up the file exclusive to synchronize against readahead and
    //  other purge/map activity.
    //

    FsRtlAcquireFileExclusive( FileObject );

    //
    //  Get a pointer to the SharedCacheMap. Be sure to release the FileObject
    //  in case an error condition forces a premature exit.
    //
    
    if ((FileObject->SectionObjectPointer == NULL) ||
    	((SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap) == NULL)){
    	 FsRtlReleaseFile( FileObject );
        return FALSE;
    }
    
    //
    //  Unmap all the views in preparation for making the disable mw call.
    //

    //
    //  We still need to wait for any dangling cache read or writes.
    //
    //  In fact we have to loop and wait because the lazy writer can
    //  sneak in and do an CcGetVirtualAddressIfMapped, and we are not
    //  synchronized.
    //
    //  This is the same bit of code that our purge will do.  We assume
    //  that a private writer has succesfully blocked out other activity.
    //

    //
    //  If there is an active Vacb, then delete it now (before waiting!).
    //

    CcAcquireMasterLock( &OldIrql );
    GetActiveVacbAtDpcLevel( SharedCacheMap, Vacb, ActivePage, PageIsDirty );
    CcReleaseMasterLock( OldIrql );
    
    if (Vacb != NULL) {

        CcFreeActiveVacb( SharedCacheMap, Vacb, ActivePage, PageIsDirty );
    }

    while ((SharedCacheMap->Vacbs != NULL) &&
           !CcUnmapVacbArray( SharedCacheMap, NULL, 0, FALSE )) {

        CcWaitOnActiveCount( SharedCacheMap );
    }

    //
    //  Knock the file down.
    // 

    CcFlushCache( FileObject->SectionObjectPointer, NULL, 0, NULL );

    //
    //  Now the file is clean and unmapped. We can still have a racing
    //  lazy writer, though.
    //
    //  We just wait for the lazy writer queue to drain before disabling
    //  modified write.  There may be a better way to do this by having
    //  an event for the WRITE_QUEUED flag. ?  This would also let us
    //  dispense with the pagingio pick/drop in the FS cache coherency
    //  paths, but there could be reasons why CcFlushCache shouldn't
    //  always do such a block.  Investigate this.
    //
    //  This wait takes on the order of ~.5s avg. case.
    //

    CcAcquireMasterLock( &OldIrql );
    
    if (FlagOn( SharedCacheMap->Flags, WRITE_QUEUED ) ||
        FlagOn( SharedCacheMap->Flags, READ_AHEAD_QUEUED )) {
        
        CcReleaseMasterLock( OldIrql );
        FsRtlReleaseFile( FileObject );
        CcWaitForCurrentLazyWriterActivity();
        FsRtlAcquireFileExclusive( FileObject );

    } else {

        CcReleaseMasterLock( OldIrql );
    }

    //
    //  Now set the flags and return.  We do not set our MODIFIED_WRITE_DISABLED
    //  since we don't want to fully promote this cache map.  Future?
    //

    Disabled = MmDisableModifiedWriteOfSection( FileObject->SectionObjectPointer );

    if (Disabled) {
        CcAcquireMasterLock( &OldIrql );
        SetFlag(SharedCacheMap->Flags, DISABLE_WRITE_BEHIND | PRIVATE_WRITE);
        CcReleaseMasterLock( OldIrql );
    }

    //
    //  Now release the file for regular operation.
    //

    FsRtlReleaseFile( FileObject );

    return Disabled;
}
コード例 #21
0
ファイル: cleanup.c プロジェクト: Uroc327/ext2fsd
NTSTATUS
Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
{
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status = STATUS_SUCCESS;
    PEXT2_VCB       Vcb;
    PFILE_OBJECT    FileObject;
    PEXT2_FCB       Fcb;
    PEXT2_CCB       Ccb;
    PIRP            Irp;
    PEXT2_MCB       Mcb;


    BOOLEAN         VcbResourceAcquired = FALSE;
    BOOLEAN         FcbResourceAcquired = FALSE;
    BOOLEAN         FcbPagingIoResourceAcquired = FALSE;

    __try {

        ASSERT(IrpContext != NULL);
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;
        if (IsExt2FsDevice(DeviceObject))  {
            Status = STATUS_SUCCESS;
            __leave;
        }

        Irp = IrpContext->Irp;
        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        if (!IsVcbInited(Vcb)) {
            Status = STATUS_SUCCESS;
            __leave;
        }

        FileObject = IrpContext->FileObject;
        Fcb = (PEXT2_FCB) FileObject->FsContext;
        if (!Fcb || (Fcb->Identifier.Type != EXT2VCB &&
                     Fcb->Identifier.Type != EXT2FCB)) {
            Status = STATUS_SUCCESS;
            __leave;
        }
        Mcb = Fcb->Mcb;
        Ccb = (PEXT2_CCB) FileObject->FsContext2;

        if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
            Status = STATUS_SUCCESS;
            __leave;
        }

        VcbResourceAcquired =
            ExAcquireResourceExclusiveLite(
                &Vcb->MainResource,
                IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
            );

        if (Fcb->Identifier.Type == EXT2VCB) {

            if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
                    (Vcb->LockFile == FileObject) ) {

                ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
                Vcb->LockFile = NULL;
                Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
            }

            if (Ccb) {
                Ext2DerefXcb(&Vcb->OpenHandleCount);
                Ext2DerefXcb(&Vcb->OpenVolumeCount);
            }

            IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);

            Status = STATUS_SUCCESS;
            __leave;
        }

        ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
               (Fcb->Identifier.Size == sizeof(EXT2_FCB)));

        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 = Ext2FlushFile(IrpContext, Fcb, Ccb);
            }
            __leave;
        }

        if (Ccb == NULL) {
            Status = STATUS_SUCCESS;
            __leave;
        }

        if (IsDirectory(Fcb)) {
            if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE))  {
                SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);

                FsRtlNotifyFullChangeDirectory(
                    Vcb->NotifySync,
                    &Vcb->NotifyList,
                    Ccb,
                    NULL,
                    FALSE,
                    FALSE,
                    0,
                    NULL,
                    NULL,
                    NULL );
            }

            FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);

        }

        ExReleaseResourceLite(&Vcb->MainResource);
        VcbResourceAcquired = FALSE;

        FcbResourceAcquired =
            ExAcquireResourceExclusiveLite(
                &Fcb->MainResource,
                IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
            );

        ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
               (Ccb->Identifier.Size == sizeof(EXT2_CCB)));

        Ext2DerefXcb(&Vcb->OpenHandleCount);
        Ext2DerefXcb(&Fcb->OpenHandleCount);

        if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
            Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
        }

        if (IsDirectory(Fcb)) {

            ext3_release_dir(Fcb->Inode, &Ccb->filp);

        } else {

            if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
                    !IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {

                LARGE_INTEGER   SysTime;
                KeQuerySystemTime(&SysTime);

                Fcb->Inode->i_atime =
                    Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
                Fcb->Mcb->LastAccessTime =
                    Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime);

                Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);

                Ext2NotifyReportChange(
                    IrpContext,
                    Vcb,
                    Fcb->Mcb,
                    FILE_NOTIFY_CHANGE_ATTRIBUTES |
                    FILE_NOTIFY_CHANGE_LAST_WRITE |
                    FILE_NOTIFY_CHANGE_LAST_ACCESS,
                    FILE_ACTION_MODIFIED );
            }

            FsRtlCheckOplock( &Fcb->Oplock,
                              Irp,
                              IrpContext,
                              NULL,
                              NULL );

            Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);

            if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) {
                Fcb->NonCachedOpenCount--;
            }

            if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE))  {
                SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
            }

            //
            // 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) {
#if EXT2_DEBUG
                    DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n",
                                   Ext2GetCurrentProcessName(),
                                   "FastIoIsPossible",
                                   &Fcb->Mcb->FullName
                                  ));
#endif

                    Fcb->Header.IsFastIoPossible = FastIoIsPossible;
                }
            }

            if (Fcb->OpenHandleCount == 0 &&
                    (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE) ||
                     IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_WRITE)) ) {

                LARGE_INTEGER Size;

                ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
                FcbPagingIoResourceAcquired = TRUE;

                Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
                                                (ULONGLONG)Fcb->Mcb->Inode.i_size,
                                                (ULONGLONG)BLOCK_SIZE);
                if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {

                    Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
                    Fcb->Header.ValidDataLength.QuadPart =
                        Fcb->Header.FileSize.QuadPart = Fcb->Mcb->Inode.i_size;
                    Fcb->Header.AllocationSize = Size;
                    if (CcIsFileCached(FileObject)) {
                        CcSetFileSizes(FileObject,
                                       (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    }
                }
                ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE);
                ExReleaseResourceLite(&Fcb->PagingIoResource);
                FcbPagingIoResourceAcquired = FALSE;
            }
        }

        if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {

            if (Fcb->OpenHandleCount == 0 || (Mcb = Ccb->SymLink)) {

                //
                // Ext2DeleteFile will acquire these lock inside
                //

                if (FcbResourceAcquired) {
                    ExReleaseResourceLite(&Fcb->MainResource);
                    FcbResourceAcquired = FALSE;
                }

                //
                //  this file is to be deleted ...
                //
                if (Ccb->SymLink) {
                    Mcb = Ccb->SymLink;
                    FileObject->DeletePending = FALSE;
                }

                Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);

                if (NT_SUCCESS(Status)) {
                    if (IsMcbDirectory(Mcb)) {
                        Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
                                                FILE_NOTIFY_CHANGE_DIR_NAME,
                                                FILE_ACTION_REMOVED );
                    } else {
                        Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
                                                FILE_NOTIFY_CHANGE_FILE_NAME,
                                                FILE_ACTION_REMOVED );
                    }
                }

                //
                // re-acquire the main resource lock
                //

                FcbResourceAcquired =
                    ExAcquireResourceExclusiveLite(
                        &Fcb->MainResource,
                        IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
                    );

                if (CcIsFileCached(FileObject)) {
                    CcSetFileSizes(FileObject,
                                   (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                }
            }
        }

        if (!IsDirectory(Fcb)) {

            if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
                    (Fcb->NonCachedOpenCount + 1 == 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);
                }

                if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
                    ExReleaseResourceLite(&(Fcb->PagingIoResource));
                }

                CcPurgeCacheSection( &Fcb->SectionObject,
                                     NULL,
                                     0,
                                     FALSE );
            }

            CcUninitializeCacheMap(FileObject, NULL, NULL);
        }

        IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);

        DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
                        Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));

        Status = STATUS_SUCCESS;

        if (FileObject) {
            SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
        }

    } __finally {

        if (FcbPagingIoResourceAcquired) {
            ExReleaseResourceLite(&Fcb->PagingIoResource);
        }

        if (FcbResourceAcquired) {
            ExReleaseResourceLite(&Fcb->MainResource);
        }

        if (VcbResourceAcquired) {
            ExReleaseResourceLite(&Vcb->MainResource);
        }

        if (!IrpContext->ExceptionInProgress) {
            if (Status == STATUS_PENDING) {
                Ext2QueueRequest(IrpContext);
            } else {
                IrpContext->Irp->IoStatus.Status = Status;
                Ext2CompleteIrpContext(IrpContext, Status);
            }
        }
    }

    return Status;
}
コード例 #22
0
ファイル: write.c プロジェクト: layerfsd/ffsfsd
NTSTATUS
FFSv1WriteInode(
	IN PFFS_IRP_CONTEXT     IrpContext,
	IN PFFS_VCB             Vcb,
	IN PFFSv1_INODE         dinode1,
	IN ULONGLONG            offset,
	IN PVOID                Buffer,
	IN ULONG                size,
	IN BOOLEAN              bWriteToDisk,
	OUT PULONG              dwRet)
{
	PFFS_BDL    ffs_bdl = NULL;
	ULONG       blocks, i;
	NTSTATUS    Status = STATUS_UNSUCCESSFUL;
	ULONG       Totalblocks;
	LONGLONG    AllocSize;

	if (dwRet)
	{
		*dwRet = 0;
	}

	Totalblocks = (dinode1->di_blocks);
	AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);

	if ((LONGLONG)offset >= AllocSize)
	{
		FFSPrint((DBG_ERROR, "FFSv1WriteInode: beyond the file range.\n"));
		return STATUS_SUCCESS;
	}

	if ((LONGLONG)offset + size > AllocSize)
	{
		size = (ULONG)(AllocSize - offset);
	}

	blocks = FFSv1BuildBDL(IrpContext, Vcb, dinode1, offset, size, &ffs_bdl);

	if (blocks <= 0)
	{
		return STATUS_SUCCESS;
	}

#if DBG
	{
		ULONG   dwTotal = 0;
		FFSPrint((DBG_INFO, "FFSv1WriteInode: BDLCount = %xh Size=%xh Off=%xh\n",
					blocks, size, offset));
		for(i = 0; i < blocks; i++)
		{
			FFSPrint((DBG_INFO, "FFSv1WriteInode: Lba=%I64xh Len=%xh Off=%xh\n",
						ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset));
			dwTotal += ffs_bdl[i].Length;
		}

		if (dwTotal != size)
		{
			FFSBreakPoint();
		}

		FFSPrint((DBG_INFO, "FFSv1WriteInode: Total = %xh (WriteToDisk=%x)\n",
					dwTotal, bWriteToDisk));
	}
#endif

	if (bWriteToDisk)
	{

#if 0
		for(i = 0; i < blocks; i++)
		{
			{
				CcFlushCache(&(Vcb->SectionObject),
						(PLARGE_INTEGER)&(ffs_bdl[i].Lba),
						ffs_bdl[i].Length,
						NULL);

				if (Vcb->SectionObject.DataSectionObject != NULL)
				{
					ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
					ExReleaseResource(&Vcb->PagingIoResource);

					CcPurgeCacheSection(&(Vcb->SectionObject),
							(PLARGE_INTEGER)&(ffs_bdl[i].Lba),
							ffs_bdl[i].Length,
							FALSE);
				}
			}
		}
#endif

		// assume offset is aligned.
		Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE);
	}
	else
	{
		for(i = 0; i < blocks; i++)
		{
			if(!FFSSaveBuffer(IrpContext, Vcb, ffs_bdl[i].Lba, ffs_bdl[i].Length, (PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset)))
				goto errorout;
		}

		if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
		{
			FFSPrint((DBG_USER, "FFSv1WriteInode is starting FlushingDpc...\n"));
			FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
		}

		Status = STATUS_SUCCESS;
	}

errorout:

	if (ffs_bdl)
		ExFreePool(ffs_bdl);

	if (NT_SUCCESS(Status))
	{
		if (dwRet) *dwRet = size;
	}

	return Status;
}
コード例 #23
0
ファイル: AFSFlushBuffers.cpp プロジェクト: bagdxk/openafs
NTSTATUS
AFSFlushBuffers( IN PDEVICE_OBJECT LibDeviceObject,
                 IN PIRP Irp)
{

    UNREFERENCED_PARAMETER(LibDeviceObject);
    AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
    NTSTATUS           ntStatus = STATUS_SUCCESS;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
    AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
    AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
    IO_STATUS_BLOCK    iosb = {0};
    BOOLEAN            bReleaseSectionObject = FALSE;

    pIrpSp = IoGetCurrentIrpStackLocation( Irp);

    __Enter
    {

        if( pFcb == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSFlushBuffers Attempted access (%p) when pFcb == NULL\n",
                          Irp));

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }

        if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
            pFcb->Header.NodeTypeCode == AFS_ROOT_ALL )
        {

            //
            // Once we support ADS's on directories we need to perform a flush ehre
            //

            try_return( ntStatus = STATUS_SUCCESS);

        }
        else if (pFcb->Header.NodeTypeCode != AFS_FILE_FCB)
        {
            //
            // Nothing to flush Everything but files are write through
            //
            try_return( ntStatus = STATUS_INVALID_PARAMETER);
        }

	AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSFlushBuffers Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
                      &pFcb->NPFcb->SectionObjectResource,
                      PsGetCurrentThread()));

        AFSAcquireShared( &pFcb->NPFcb->SectionObjectResource,
                          TRUE);

        bReleaseSectionObject = TRUE;

        //
        // The flush consists of two parts.  We firstly flush our
        // cache (if we have one), then we tell the service to write
        // to the remote server
        //
        __try
        {

            CcFlushCache( &pFcb->NPFcb->SectionObjectPointers, NULL, 0, &iosb);

            if (!NT_SUCCESS( iosb.Status ))
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSFlushBuffers CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
                              pFcb->ObjectInformation->FileId.Cell,
                              pFcb->ObjectInformation->FileId.Volume,
                              pFcb->ObjectInformation->FileId.Vnode,
                              pFcb->ObjectInformation->FileId.Unique,
                              iosb.Status,
                              iosb.Information));

                try_return( ntStatus = iosb.Status );
            }
        }
	__except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
        {

            try_return( ntStatus = GetExceptionCode());
        }

	if( !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
	{

	    AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
			  AFS_TRACE_LEVEL_VERBOSE,
			  "AFSFlushBuffers Releasing Fcb SectionObject lock %p SHARED %08lX\n",
			  &pFcb->NPFcb->SectionObjectResource,
			  PsGetCurrentThread()));

	    AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);

	    bReleaseSectionObject = FALSE;

	    //
	    // Now, flush to the server - if there is stuff to do
	    //

	    ntStatus = AFSFlushExtents( pFcb,
					&pCcb->AuthGroup);

	    if( !NT_SUCCESS( ntStatus))
	    {

		AFSReleaseExtentsWithFlush( pFcb,
					    &pCcb->AuthGroup,
					    TRUE);

		ntStatus = STATUS_SUCCESS;
	    }
	}

try_exit:

        if ( bReleaseSectionObject)
        {

	    AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSFlushBuffers Releasing Fcb SectionObject lock %p SHARED %08lX\n",
                          &pFcb->NPFcb->SectionObjectResource,
                          PsGetCurrentThread()));

            AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
        }

        AFSCompleteRequest( Irp, ntStatus);
    }

    return ntStatus;
}
コード例 #24
0
ファイル: fsctl.c プロジェクト: reactos/reactos
__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;
}
コード例 #25
0
ファイル: write.c プロジェクト: layerfsd/ffsfsd
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;
}
コード例 #26
0
ファイル: fileinfo.c プロジェクト: Corillian/dokany
NTSTATUS
DokanDispatchSetInformation(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) {

  NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  PIO_STACK_LOCATION irpSp;
  PVOID buffer;
  PFILE_OBJECT fileObject;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  ULONG eventLength;
  PFILE_OBJECT targetFileObject;
  PEVENT_CONTEXT eventContext;
  BOOLEAN isPagingIo = FALSE;
  BOOLEAN fcbLocked = FALSE;
  PFILE_END_OF_FILE_INFORMATION pInfoEoF = NULL;

  vcb = DeviceObject->DeviceExtension;

  __try {
    DDbgPrint("==> DokanSetInformationn\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    ccb = (PDokanCCB)fileObject->FsContext2;
    ASSERT(ccb != NULL);

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);

    buffer = Irp->AssociatedIrp.SystemBuffer;

    if (Irp->Flags & IRP_PAGING_IO) {
      isPagingIo = TRUE;
    }

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);

    switch (irpSp->Parameters.SetFile.FileInformationClass) {
    case FileAllocationInformation:
      DDbgPrint(
          "  FileAllocationInformation %lld\n",
          ((PFILE_ALLOCATION_INFORMATION)buffer)->AllocationSize.QuadPart);
      break;
    case FileBasicInformation:
      DDbgPrint("  FileBasicInformation\n");
      break;
    case FileDispositionInformation:
      DDbgPrint("  FileDispositionInformation\n");
      break;
    case FileEndOfFileInformation:
      if ((fileObject->SectionObjectPointer != NULL) &&
          (fileObject->SectionObjectPointer->DataSectionObject != NULL)) {

        pInfoEoF = (PFILE_END_OF_FILE_INFORMATION)buffer;

        if (!MmCanFileBeTruncated(fileObject->SectionObjectPointer,
                                  &pInfoEoF->EndOfFile)) {
          status = STATUS_USER_MAPPED_FILE;
          __leave;
        }

        if (!isPagingIo) {
          ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
          CcFlushCache(&fcb->SectionObjectPointers, NULL, 0, NULL);
          CcPurgeCacheSection(&fcb->SectionObjectPointers, NULL, 0, FALSE);
          ExReleaseResourceLite(&fcb->PagingIoResource);
        }
      }
      DDbgPrint("  FileEndOfFileInformation %lld\n",
                ((PFILE_END_OF_FILE_INFORMATION)buffer)->EndOfFile.QuadPart);
      break;
    case FileLinkInformation:
      DDbgPrint("  FileLinkInformation\n");
      break;
    case FilePositionInformation: {
      PFILE_POSITION_INFORMATION posInfo;

      posInfo = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
      ASSERT(posInfo != NULL);

      DDbgPrint("  FilePositionInformation %lld\n",
                posInfo->CurrentByteOffset.QuadPart);
      fileObject->CurrentByteOffset = posInfo->CurrentByteOffset;

      status = STATUS_SUCCESS;

      __leave;
    } break;
    case FileRenameInformation:
      DDbgPrint("  FileRenameInformation\n");
      break;
    case FileValidDataLengthInformation:
      DDbgPrint("  FileValidDataLengthInformation\n");
      break;
    default:
      DDbgPrint("  unknown type:%d\n",
                irpSp->Parameters.SetFile.FileInformationClass);
      break;
    }

    //
    // when this IRP is not handled in swich case
    //

    // calcurate the size of EVENT_CONTEXT
    // it is sum of file name length and size of FileInformation
    DokanFCBLockRW(fcb);
    fcbLocked = TRUE;
    eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length +
                  irpSp->Parameters.SetFile.Length;

    targetFileObject = irpSp->Parameters.SetFile.FileObject;

    if (targetFileObject) {
      DDbgPrint("  FileObject Specified %wZ\n", &(targetFileObject->FileName));
      eventLength += targetFileObject->FileName.Length;
    }

    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

    if (eventContext == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      __leave;
    }

    eventContext->Context = ccb->UserContext;

    eventContext->Operation.SetFile.FileInformationClass =
        irpSp->Parameters.SetFile.FileInformationClass;

    // the size of FileInformation
    eventContext->Operation.SetFile.BufferLength =
        irpSp->Parameters.SetFile.Length;

    // the offset from begining of structure to fill FileInfo
    eventContext->Operation.SetFile.BufferOffset =
        FIELD_OFFSET(EVENT_CONTEXT, Operation.SetFile.FileName[0]) +
        fcb->FileName.Length + sizeof(WCHAR); // the last null char

    BOOLEAN isRenameOrLink = irpSp->Parameters.SetFile.FileInformationClass ==
        FileRenameInformation ||
        irpSp->Parameters.SetFile.FileInformationClass == FileLinkInformation;

    if (!isRenameOrLink) {
        // copy FileInformation
        RtlCopyMemory(
            (PCHAR)eventContext + eventContext->Operation.SetFile.BufferOffset,
            Irp->AssociatedIrp.SystemBuffer, irpSp->Parameters.SetFile.Length);
    }

    if (isRenameOrLink) {
      // We need to hanle FileRenameInformation separetly because the structure
      // of FILE_RENAME_INFORMATION
      // has HANDLE type field, which size is different in 32 bit and 64 bit
      // environment.
      // This cases problems when driver is 64 bit and user mode library is 32
      // bit.
      PFILE_RENAME_INFORMATION renameInfo =
          (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
      PDOKAN_RENAME_INFORMATION renameContext = (PDOKAN_RENAME_INFORMATION)(
          (PCHAR)eventContext + eventContext->Operation.SetFile.BufferOffset);

      // This code assumes FILE_RENAME_INFORMATION and FILE_LINK_INFORMATION
      // have
      // the same typse and fields.
      ASSERT(sizeof(FILE_RENAME_INFORMATION) == sizeof(FILE_LINK_INFORMATION));

      renameContext->ReplaceIfExists = renameInfo->ReplaceIfExists;
      renameContext->FileNameLength = renameInfo->FileNameLength;
      RtlCopyMemory(renameContext->FileName, renameInfo->FileName,
                    renameInfo->FileNameLength);

      if (targetFileObject != NULL) {
        // if Parameters.SetFile.FileObject is specified, replase
        // FILE_RENAME_INFO's file name by
        // FileObject's file name. The buffer size is already adjusted.

        DDbgPrint("  renameContext->FileNameLength %d\n",
            renameContext->FileNameLength);
        DDbgPrint("  renameContext->FileName %ws\n", renameContext->FileName);
        RtlZeroMemory(renameContext->FileName, renameContext->FileNameLength);

        PFILE_OBJECT parentFileObject = targetFileObject->RelatedFileObject;
        if (parentFileObject != NULL) {
            RtlCopyMemory(renameContext->FileName,
                parentFileObject->FileName.Buffer,
                parentFileObject->FileName.Length);

            RtlStringCchCatW(renameContext->FileName, NTSTRSAFE_MAX_CCH, L"\\");
            RtlStringCchCatW(renameContext->FileName, NTSTRSAFE_MAX_CCH, targetFileObject->FileName.Buffer);
            renameContext->FileNameLength = targetFileObject->FileName.Length + 
                parentFileObject->FileName.Length + sizeof(WCHAR);
        } else {
            RtlCopyMemory(renameContext->FileName,
                targetFileObject->FileName.Buffer,
                targetFileObject->FileName.Length);
            renameContext->FileNameLength = targetFileObject->FileName.Length;
        }
      }

      if (irpSp->Parameters.SetFile.FileInformationClass ==
          FileRenameInformation) {
        DDbgPrint("   rename: %wZ => %ls, FileCount = %u\n", fcb->FileName,
                  renameContext->FileName, (ULONG)fcb->FileCount);
      }
    }

    // copy the file name
    eventContext->Operation.SetFile.FileNameLength = fcb->FileName.Length;
    RtlCopyMemory(eventContext->Operation.SetFile.FileName,
                  fcb->FileName.Buffer, fcb->FileName.Length);

    // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
    status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext,
                              DokanOplockComplete, DokanPrePostIrp);

    //
    //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
    //  to service an oplock break and we need to leave now.
    //
    if (status != STATUS_SUCCESS) {
      if (status == STATUS_PENDING) {
        DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
      } else {
        DokanFreeEventContext(eventContext);
      }
      __leave;
    }

    // register this IRP to waiting IRP list and make it pending status
    status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

  } __finally {
    if(fcbLocked)
      DokanFCBUnlock(fcb);

    DokanCompleteIrpRequest(Irp, status, 0);

    DDbgPrint("<== DokanSetInformation\n");
  }

  return status;
}
コード例 #27
0
ファイル: cleanup.c プロジェクト: GYGit/reactos
__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;
}
コード例 #28
0
ファイル: write.c プロジェクト: Axure/Ext3Fsd
NTSTATUS
Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;

    PEXT2_VCB           Vcb = NULL;
    PEXT2_CCB           Ccb = NULL;
    PEXT2_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 = FALSE;
    BOOLEAN             Nocache = FALSE;
    BOOLEAN             SynchronousIo = FALSE;
    BOOLEAN             MainResourceAcquired = FALSE;

    BOOLEAN             bDeferred = FALSE;

    PUCHAR              Buffer = NULL;
    PEXT2_EXTENT        Chain = NULL;
    EXT2_EXTENT         BlockArray;

    __try {

        ASSERT(IrpContext);
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;
        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        FileObject = IrpContext->FileObject;
        FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
        ASSERT(FcbOrVcb);

        if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        Ccb = (PEXT2_CCB) FileObject->FsContext2;
        Irp = IrpContext->Irp;
        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

        Length = IoStackLocation->Parameters.Write.Length;
        ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

        PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
        Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL);
        SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

        if (PagingIo) {
            ASSERT(Nocache);
        }

        DEBUG(DL_INF, ("Ext2WriteVolume: 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;
        }

        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 (!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 ) ) {

                Status = Ext2LockUserBuffer(
                             IrpContext->Irp,
                             Length,
                             IoReadAccess);
                if (NT_SUCCESS(Status)) {
                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
                    CcDeferWrite( FileObject,
                                  (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite,
                                  IrpContext,
                                  Irp,
                                  Length,
                                  bAgain );

                    bDeferred = TRUE;
                    Status = STATUS_PENDING;

                    __leave;
                }
            }
        }

        /*
         * User direct volume access
         */

        if (Ccb != NULL && !PagingIo) {

            if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) {

                if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
                    Status = Ext2PurgeVolume( Vcb, TRUE);
                }

                SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE);
            }

            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);
                }
            }

        } else if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL))  {

            ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
            MainResourceAcquired = TRUE;

            ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
            ExReleaseResourceLite(&Vcb->PagingIoResource);

            CcFlushCache( &(Vcb->SectionObject),
                          &ByteOffset,
                          Length,
                          &(Irp->IoStatus));

            if (!NT_SUCCESS(Irp->IoStatus.Status))  {
                Status = Irp->IoStatus.Status;
                __leave;
            }

            ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
            ExReleaseResourceLite(&Vcb->PagingIoResource);

            CcPurgeCacheSection( &(Vcb->SectionObject),
                                 (PLARGE_INTEGER)&(ByteOffset),
                                 Length,
                                 FALSE );

            ExReleaseResourceLite(&Vcb->MainResource);
            MainResourceAcquired = FALSE;
        }

        if ( (ByteOffset.QuadPart + Length) > Vcb->Header.FileSize.QuadPart) {
            Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
        }

        if (!Nocache) {

            if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {

                CcPrepareMdlWrite (
                    Vcb->Volume,
                    &ByteOffset,
                    Length,
                    &Irp->MdlAddress,
                    &Irp->IoStatus );

                Status = Irp->IoStatus.Status;

            } else {

                Buffer = Ext2GetUserBuffer(Irp);
                if (Buffer == NULL) {
                    DbgBreak();

                    Status = STATUS_INVALID_USER_BUFFER;
                    __leave;
                }

                if (!CcCopyWrite( Vcb->Volume,
                                  (PLARGE_INTEGER)(&ByteOffset),
                                  Length,
                                  TRUE,
                                  Buffer )) {
                    Status = STATUS_PENDING;
                    __leave;
                }

                Status = Irp->IoStatus.Status;
                Ext2AddVcbExtent(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
            }

            if (NT_SUCCESS(Status)) {
                Irp->IoStatus.Information = Length;
            }

        } else if (PagingIo) {

            LONGLONG            DirtyStart;
            LONGLONG            DirtyLba;
            LONGLONG            DirtyLength;
            LONGLONG            RemainLength;

            PEXT2_EXTENT        Extent = NULL;
            PEXT2_EXTENT        List = NULL;

            Length &= ~((ULONG)SECTOR_SIZE - 1);

            Status = Ext2LockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            DirtyLba = ByteOffset.QuadPart;
            RemainLength = (LONGLONG) Length;

            ASSERT(Length >= SECTOR_SIZE);

            while (RemainLength > 0) {

                DirtyStart = DirtyLba;
                ASSERT(DirtyStart >= ByteOffset.QuadPart);
                ASSERT(DirtyStart <= ByteOffset.QuadPart + Length);

                if (Ext2LookupVcbExtent(Vcb, DirtyStart, &DirtyLba, &DirtyLength)) {

                    if (DirtyLba == -1) {

                        DirtyLba = DirtyStart + DirtyLength;
                        if (ByteOffset.QuadPart + Length > DirtyLba) {
                            RemainLength = ByteOffset.QuadPart + Length - DirtyLba;
                            ASSERT(DirtyStart >= ByteOffset.QuadPart);
                            ASSERT(DirtyStart <= ByteOffset.QuadPart + Length);
                        } else {
                            RemainLength = 0;
                        }
                        continue;
                    }

                    ASSERT(DirtyLba <= DirtyStart);
                    Extent = Ext2AllocateExtent();

                    if (!Extent) {
                        DEBUG(DL_ERR, ( "Ex2WriteVolume: failed to allocate Extent\n"));
                        Status = STATUS_INSUFFICIENT_RESOURCES;
                        __leave;
                    }

                    Extent->Irp = NULL;
                    Extent->Lba = DirtyLba;
                    Extent->Offset = (ULONG)( DirtyStart + Length -
                                              RemainLength - DirtyLba );
                    ASSERT(Extent->Offset <= Length);

                    if (DirtyLba + DirtyLength >= DirtyStart + RemainLength) {
                        Extent->Length = (ULONG)( DirtyLba +
                                                  RemainLength -
                                                  DirtyStart );
                        ASSERT(Extent->Length <= Length);
                        RemainLength = 0;
                    } else {
                        Extent->Length = (ULONG)(DirtyLength + DirtyLba - DirtyStart);
                        RemainLength =  (DirtyStart + RemainLength) -
                                        (DirtyLba + DirtyLength);
                        ASSERT(RemainLength <= (LONGLONG)Length);
                        ASSERT(Extent->Length <= Length);
                    }

                    ASSERT(Extent->Length >= SECTOR_SIZE);
                    DirtyLba = DirtyStart + DirtyLength;

                    if (List) {
                        List->Next = Extent;
                        List = Extent;
                    } else {
                        Chain = List = Extent;
                    }

                } else {

                    if (RemainLength > SECTOR_SIZE) {
                        DirtyLba = DirtyStart + SECTOR_SIZE;
                        RemainLength -= SECTOR_SIZE;
                    } else {
                        RemainLength = 0;
                    }
                }
            }

            if (Chain) {
                Status = Ext2ReadWriteBlocks(IrpContext,
                                             Vcb,
                                             Chain,
                                             Length );
                Irp = IrpContext->Irp;

                if (NT_SUCCESS(Status)) {
                    for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
                        Ext2RemoveVcbExtent(Vcb, Extent->Lba, Extent->Length);
                    }
                }

                if (!Irp) {
                    __leave;
                }

            } else {

                Irp->IoStatus.Information = Length;
                Status = STATUS_SUCCESS;
                __leave;
            }

        } else {

            Length &= ~((ULONG)SECTOR_SIZE - 1);

            Status = Ext2LockUserBuffer(
                         IrpContext->Irp,
                         Length,
                         IoWriteAccess );

            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            BlockArray.Irp = NULL;
            BlockArray.Lba = ByteOffset.QuadPart;
            BlockArray.Offset = 0;
            BlockArray.Length = Length;
            BlockArray.Next = NULL;

            Status = Ext2ReadWriteBlocks(IrpContext,
                                         Vcb,
                                         &BlockArray,
                                         Length );

            if (NT_SUCCESS(Status)) {
                Irp->IoStatus.Information = Length;
            }

            Irp = IrpContext->Irp;
            if (!Irp) {
                __leave;
            }
        }

    } __finally {

        if (MainResourceAcquired) {
            ExReleaseResourceLite(&Vcb->MainResource);
        }

        if (!IrpContext->ExceptionInProgress) {

            if (Irp) {

                if (Status == STATUS_PENDING) {

                    if (!bDeferred) {
                        Status = Ext2LockUserBuffer(
                                     IrpContext->Irp,
                                     Length,
                                     IoReadAccess );

                        if (NT_SUCCESS(Status)) {
                            Status = Ext2QueueRequest(IrpContext);
                        } else {
                            Ext2CompleteIrpContext(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);
                        }
                    }

                    Ext2CompleteIrpContext(IrpContext, Status);
                }

            } else {

                Ext2FreeIrpContext(IrpContext);
            }
        }

        if (Chain) {
            Ext2DestroyExtentChain(Chain);
        }
    }

    return Status;
}
コード例 #29
0
ファイル: write.c プロジェクト: layerfsd/ffsfsd
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;

}
コード例 #30
0
ファイル: read.c プロジェクト: jrfl/ext2fsd
NTSTATUS
Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;

    PEXT2_VCB           Vcb = NULL;
    PEXT2_FCB           Fcb = NULL;
    PEXT2_CCB           Ccb = NULL;
    PFILE_OBJECT        FileObject = NULL;

    PDEVICE_OBJECT      DeviceObject = NULL;

    PIRP                Irp = NULL;
    PIO_STACK_LOCATION  IoStackLocation = NULL;

    ULONG               Length;
    ULONG               ReturnedLength = 0;
    LARGE_INTEGER       ByteOffset;

    BOOLEAN             OpPostIrp = FALSE;
    BOOLEAN             PagingIo;
    BOOLEAN             Nocache;
    BOOLEAN             SynchronousIo;
    BOOLEAN             MainResourceAcquired = FALSE;
    BOOLEAN             PagingIoResourceAcquired = FALSE;

    PUCHAR              Buffer;

    __try {

        ASSERT(IrpContext);
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;
        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        FileObject = IrpContext->FileObject;
        Fcb = (PEXT2_FCB) FileObject->FsContext;
        ASSERT(Fcb);
        ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
               (Fcb->Identifier.Size == sizeof(EXT2_FCB)));

        Ccb = (PEXT2_CCB) FileObject->FsContext2;

        Irp = IrpContext->Irp;
        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

        Length = IoStackLocation->Parameters.Read.Length;
        ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;

        PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
        Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE);
        SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

        if (PagingIo) {
            ASSERT(Nocache);
        }

        DEBUG(DL_INF, ("Ext2ReadFile: reading %wZ Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
                       &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));

        if ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ||
            IsFileDeleted(Fcb->Mcb)) {
            Status = STATUS_FILE_DELETED;
            __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;
            DbgBreak();
            __leave;
        }

        if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
            ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
            Status = STATUS_PENDING;
            DbgBreak();
            __leave;
        }

        if (!PagingIo && Nocache && (FileObject->SectionObjectPointer->DataSectionObject != NULL)) {
            CcFlushCache( FileObject->SectionObjectPointer,
                          &ByteOffset,
                          Length,
                          &Irp->IoStatus );

            if (!NT_SUCCESS(Irp->IoStatus.Status)) {
                __leave;
            }
        }

        ReturnedLength = Length;

        if (PagingIo) {

            if (!ExAcquireResourceSharedLite(
                        &Fcb->PagingIoResource,
                        IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
                Status = STATUS_PENDING;
                __leave;
            }
            PagingIoResourceAcquired = TRUE;

        } else {

            if (Nocache) {

                if (!ExAcquireResourceExclusiveLite(
                            &Fcb->MainResource,
                            IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
                    Status = STATUS_PENDING;
                    __leave;
                }
                MainResourceAcquired = TRUE;

            } else {

                if (!ExAcquireResourceSharedLite(
                            &Fcb->MainResource,
                            IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
                    Status = STATUS_PENDING;
                    __leave;
                }
                MainResourceAcquired = TRUE;
            }

            if (!FsRtlCheckLockForReadAccess(
                        &Fcb->FileLockAnchor,
                        Irp         )) {
                Status = STATUS_FILE_LOCK_CONFLICT;
                __leave;
            }
        }

        if ((ByteOffset.QuadPart + (LONGLONG)Length) > Fcb->Header.FileSize.QuadPart) {
            if (ByteOffset.QuadPart >= Fcb->Header.FileSize.QuadPart) {
                Irp->IoStatus.Information = 0;
                Status = STATUS_END_OF_FILE;
                __leave;
            }
            ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
        }


        if (!IsDirectory(Fcb) && Ccb != NULL) {

            Status = FsRtlCheckOplock( &Fcb->Oplock,
                                       Irp,
                                       IrpContext,
                                       Ext2OplockComplete,
                                       Ext2LockIrp );

            if (Status != STATUS_SUCCESS) {
                OpPostIrp = TRUE;
                __leave;
            }

            //
            //  Set the flag indicating if Fast I/O is possible
            //

            Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
        }

        if (!Nocache) {

            if (IsDirectory(Fcb)) {
                __leave;
            }

            if (FileObject->PrivateCacheMap == NULL) {
                CcInitializeCacheMap(
                        FileObject,
                        (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
                        FALSE,
                        &Ext2Global->CacheManagerCallbacks,
                        Fcb );
                CcSetReadAheadGranularity(
                        FileObject,
                        READ_AHEAD_GRANULARITY );
            }

            if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
                CcMdlRead(
                    FileObject,
                    (&ByteOffset),
                    ReturnedLength,
                    &Irp->MdlAddress,
                    &Irp->IoStatus );

                Status = Irp->IoStatus.Status;

            } else {

                Buffer = Ext2GetUserBuffer(Irp);
                if (Buffer == NULL) {
                    Status = STATUS_INVALID_USER_BUFFER;
                    DbgBreak();
                    __leave;
                }

                if (!CcCopyRead(FileObject, &ByteOffset, ReturnedLength,
                                Ext2CanIWait(), Buffer, &Irp->IoStatus)) {

                    if (Ext2CanIWait() || !CcCopyRead(FileObject, &ByteOffset,
                                                      ReturnedLength, TRUE,
                                                      Buffer, &Irp->IoStatus)) {
                        Status = STATUS_PENDING;
                        DbgBreak();
                        __leave;
                    }
                }
                Status = Irp->IoStatus.Status;
            }

        } else {

            ULONG   BytesRead = ReturnedLength;
            PUCHAR  SystemVA  = Ext2GetUserBuffer(IrpContext->Irp);

            if (ByteOffset.QuadPart + BytesRead > Fcb->Header.ValidDataLength.QuadPart) {

                if (ByteOffset.QuadPart >= Fcb->Header.ValidDataLength.QuadPart) {
                    if (SystemVA) {
                        SafeZeroMemory(SystemVA, Length);
                    }
                    Irp->IoStatus.Information = ReturnedLength;
                    Status = STATUS_SUCCESS;
                    __leave;
                } else {
                    BytesRead = (ULONG)(Fcb->Header.ValidDataLength.QuadPart - ByteOffset.QuadPart);
                    if (SystemVA) {
                        SafeZeroMemory(SystemVA + BytesRead, Length - BytesRead);
                    }
                }
            }

            Status = Ext2LockUserBuffer(
                         IrpContext->Irp,
                         BytesRead,
                         IoReadAccess );

            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            Status = Ext2ReadInode(
                         IrpContext,
                         Vcb,
                         Fcb->Mcb,
                         ByteOffset.QuadPart,
                         NULL,
                         BytesRead,
                         TRUE,
                         NULL );

            /* we need re-queue this request in case STATUS_CANT_WAIT
               and fail it in other failure cases  */
            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            /* pended by low level device */
            if (Status == STATUS_PENDING) {
                IrpContext->Irp = Irp = NULL;
                __leave;
            }

            Irp = IrpContext->Irp;
            ASSERT(Irp);
            Status = Irp->IoStatus.Status;

            if (!NT_SUCCESS(Status)) {
                Ext2NormalizeAndRaiseStatus(IrpContext, Status);
            }
        }

        Irp->IoStatus.Information = ReturnedLength;

    } __finally {

        if (Irp) {
            if (PagingIoResourceAcquired) {
                ExReleaseResourceLite(&Fcb->PagingIoResource);
            }

            if (MainResourceAcquired) {
                ExReleaseResourceLite(&Fcb->MainResource);
            }
        }

        if (!OpPostIrp && !IrpContext->ExceptionInProgress) {

            if (Irp) {
                if ( Status == STATUS_PENDING ||
                     Status == STATUS_CANT_WAIT) {

                    Status = Ext2LockUserBuffer(
                                 IrpContext->Irp,
                                 Length,
                                 IoWriteAccess );

                    if (NT_SUCCESS(Status)) {
                        Status = Ext2QueueRequest(IrpContext);
                    } else {
                        Ext2CompleteIrpContext(IrpContext, Status);
                    }
                } else {
                    if (NT_SUCCESS(Status)) {
                        if (!PagingIo) {
                            if (SynchronousIo) {
                                FileObject->CurrentByteOffset.QuadPart =
                                    ByteOffset.QuadPart + Irp->IoStatus.Information;
                            }
                            FileObject->Flags |= FO_FILE_FAST_IO_READ;
                        }
                    }

                    Ext2CompleteIrpContext(IrpContext, Status);
                }

            } else {

                Ext2FreeIrpContext(IrpContext);
            }
        }
    }

    DEBUG(DL_IO, ("Ext2ReadFile: %wZ fetch at Off=%I64xh Len=%xh Paging=%xh Nocache=%xh Returned=%xh Status=%xh\n",
                  &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache, ReturnedLength, Status));
    return Status;

}