Example #1
0
VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode)
{
    PAGED_CODE();

    FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
        FspFsvolDeviceExtension(FileNode->FsvolDeviceObject);

    FsRtlUninitializeFileLock(&FileNode->FileLock);

    FsRtlTeardownPerStreamContexts(&FileNode->Header);

    FspMetaCacheInvalidateItem(FsvolDeviceExtension->DirInfoCache, FileNode->NonPaged->DirInfo);
    FspMetaCacheInvalidateItem(FsvolDeviceExtension->SecurityCache, FileNode->Security);

    FspDeviceDereference(FileNode->FsvolDeviceObject);

    if (0 != FileNode->ExternalFileName)
        FspFree(FileNode->ExternalFileName);

    ExDeleteResourceLite(&FileNode->NonPaged->PagingIoResource);
    ExDeleteResourceLite(&FileNode->NonPaged->Resource);
    FspFree(FileNode->NonPaged);

    FspFree(FileNode);
}
Example #2
0
/*
 * @implemented
 */
VOID
NTAPI
FsRtlFreeFileLock(IN PFILE_LOCK FileLock)
{
    /* Uninitialize and free the lock */
    FsRtlUninitializeFileLock(FileLock);
    ExFreeToPagedLookasideList(&FsRtlFileLockLookasideList, FileLock);
}
Example #3
0
VOID
NTAPI
FatDeleteFcb(IN PFAT_IRP_CONTEXT IrpContext,
             IN PFCB Fcb)
{
    DPRINT("FatDeleteFcb %p\n", Fcb);

    if (Fcb->OpenCount != 0)
    {
        DPRINT1("Trying to delete FCB with OpenCount %d\n", Fcb->OpenCount);
        ASSERT(FALSE);
    }

    if ((Fcb->Header.NodeTypeCode == FAT_NTC_DCB) ||
        (Fcb->Header.NodeTypeCode == FAT_NTC_ROOT_DCB))
    {
        /* Make sure it's a valid deletion */
        ASSERT(Fcb->Dcb.DirectoryFileOpenCount == 0);
        ASSERT(IsListEmpty(&Fcb->Dcb.ParentDcbList));
        ASSERT(Fcb->Dcb.DirectoryFile == NULL);
    }
    else
    {
        /* Free locks */
        FsRtlUninitializeFileLock(&Fcb->Fcb.Lock);
        FsRtlUninitializeOplock(&Fcb->Fcb.Oplock);
    }

    /* Release any possible filter contexts */
    FsRtlTeardownPerStreamContexts(&Fcb->Header);

    /* Remove from parents queue */
    if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB)
    {
        RemoveEntryList(&(Fcb->ParentDcbLinks));
    }

    /* Free FullFAT handle */
    if (Fcb->FatHandle) FF_Close(Fcb->FatHandle);

    /* Remove from the splay table */
    if (FlagOn(Fcb->State, FCB_STATE_HAS_NAMES))
        FatRemoveNames(IrpContext, Fcb);

    /* Free file name buffers */
    if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB)
    {
        if (Fcb->FullFileName.Buffer)
            ExFreePool(Fcb->FullFileName.Buffer);
    }

    if (Fcb->ExactCaseLongName.Buffer)
        ExFreePool(Fcb->ExactCaseLongName.Buffer);

    /* Free this FCB, finally */
    ExFreePool(Fcb);
}
Example #4
0
NTSTATUS
AFSInitFcb( IN AFSDirectoryCB  *DirEntry,
            IN OUT AFSFcb     **Fcb)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    AFSFcb *pFcb = NULL;
    AFSNonPagedFcb *pNPFcb = NULL;
    IO_STATUS_BLOCK stIoSb = {0,0};
    BOOLEAN bUninitFileLock = FALSE;
    USHORT  usFcbLength = 0;
    ULONGLONG   ullIndex = 0;
    AFSDirEnumEntry *pDirEnumCB = NULL;
    AFSObjectInfoCB *pObjectInfo = NULL, *pParentObjectInfo = NULL;
    AFSVolumeCB *pVolumeCB = NULL;

    __Enter
    {

        pObjectInfo = DirEntry->ObjectInformation;

        pParentObjectInfo = pObjectInfo->ParentObjectInformation;

        pVolumeCB = pObjectInfo->VolumeCB;

        //
        // Allocate the Fcb and the nonpaged portion of the Fcb.
        //

        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE_2,
                      "AFSInitFcb Initializing fcb for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
                      &DirEntry->NameInformation.FileName,
                      pObjectInfo->FileId.Cell,
                      pObjectInfo->FileId.Volume,
                      pObjectInfo->FileId.Vnode,
                      pObjectInfo->FileId.Unique);

        usFcbLength = sizeof( AFSFcb);

        pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
                                                   usFcbLength,
                                                   AFS_FCB_ALLOCATION_TAG);

        if( pFcb == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitFcb Failed to allocate fcb\n");

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlZeroMemory( pFcb,
                       usFcbLength);

        pFcb->Header.NodeByteSize = usFcbLength;

        pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
                                                             sizeof( AFSNonPagedFcb),
                                                             AFS_FCB_NP_ALLOCATION_TAG);

        if( pNPFcb == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitFcb Failed to allocate non-paged fcb\n");

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlZeroMemory( pNPFcb,
                       sizeof( AFSNonPagedFcb));

        pNPFcb->Size = sizeof( AFSNonPagedFcb);
        pNPFcb->Type = AFS_NON_PAGED_FCB;

        //
        // Initialize the advanced header
        //

        ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);

        FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);

        //
        // OK, initialize the entry
        //

        ExInitializeResourceLite( &pNPFcb->Resource);

        ExInitializeResourceLite( &pNPFcb->PagingResource);

        ExInitializeResourceLite( &pNPFcb->CcbListLock);

        pFcb->Header.Resource = &pNPFcb->Resource;

        pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;

        //
        // Grab the Fcb for processing
        //

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

        AFSAcquireExcl( &pNPFcb->Resource,
                        TRUE);

        pFcb->NPFcb = pNPFcb;

        //
        // Initialize some fields in the Fcb
        //

        pFcb->ObjectInformation = pObjectInfo;

        pObjectInfo->Fcb = pFcb;

        //
        // Set type specific information
        //

        if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
        {

            //
            // Reset the type to a directory type
            //

            pFcb->Header.NodeTypeCode = AFS_DIRECTORY_FCB;

            //
            // Initialize enumeration information
            //

            KeInitializeEvent( &pFcb->NPFcb->Specific.Directory.DirectoryEnumEvent,
                               NotificationEvent,
                               FALSE);
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
        {

            pFcb->Header.NodeTypeCode = AFS_FILE_FCB;

            //
            // Initialize the file specific information
            //

            FsRtlInitializeFileLock( &pFcb->Specific.File.FileLock,
                                     NULL,
                                     NULL);

            bUninitFileLock = TRUE;

            //
            // Initialize the header file sizes to our dir entry information
            //

            pFcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
            pFcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
            pFcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;

            //
            // Initialize the Extents resources and so forth.  The
            // quiescent state is that no one has the extents for
            // IO (do the extents are not busy) and there is no
            // extents request outstanding (and hence the "last
            // one" is complete).
            //
            ExInitializeResourceLite( &pNPFcb->Specific.File.ExtentsResource );

            KeInitializeEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
                               NotificationEvent,
                               TRUE );

            for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
            {
                InitializeListHead(&pFcb->Specific.File.ExtentsLists[i]);
            }

            pNPFcb->Specific.File.DirtyListHead = NULL;
            pNPFcb->Specific.File.DirtyListTail = NULL;

            ExInitializeResourceLite( &pNPFcb->Specific.File.DirtyExtentsListLock);

            KeInitializeEvent( &pNPFcb->Specific.File.FlushEvent,
                               SynchronizationEvent,
                               TRUE);

            KeInitializeEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
                               NotificationEvent,
                               TRUE);
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_SPECIAL_SHARE_NAME)
        {

            pFcb->Header.NodeTypeCode = AFS_SPECIAL_SHARE_FCB;
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_PIOCTL)
        {

            pFcb->Header.NodeTypeCode = AFS_IOCTL_FCB;
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
        {

            pFcb->Header.NodeTypeCode = AFS_SYMBOLIC_LINK_FCB;
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
        {

            pFcb->Header.NodeTypeCode = AFS_MOUNT_POINT_FCB;
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
        {
            pFcb->Header.NodeTypeCode = AFS_DFS_LINK_FCB;
        }
        else
        {
            pFcb->Header.NodeTypeCode = AFS_INVALID_FCB;
        }

        //
        // And return the Fcb
        //

        *Fcb = pFcb;

        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSInitFcb Initialized Fcb %08lX Name %wZ\n",
                      pFcb,
                      &DirEntry->NameInformation.FileName);

try_exit:

        if( !NT_SUCCESS( ntStatus))
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitFcb Failed to initialize fcb Status %08lX\n",
                          ntStatus);

            if( pFcb != NULL)
            {

                if( bUninitFileLock)
                {

                    FsRtlUninitializeFileLock( &pFcb->Specific.File.FileLock);
                }

                if( pNPFcb != NULL)
                {

                    AFSReleaseResource( &pNPFcb->Resource);

                    ExDeleteResourceLite( &pNPFcb->PagingResource);

                    ExDeleteResourceLite( &pNPFcb->CcbListLock);

                    ExDeleteResourceLite( &pNPFcb->Resource);
                }

                AFSExFreePool( pFcb);
            }

            if( pNPFcb != NULL)
            {

                AFSExFreePool( pNPFcb);
            }

            if( Fcb != NULL)
            {

                *Fcb = NULL;
            }
        }
    }

    return ntStatus;
}
Example #5
0
void
AFSRemoveFcb( IN AFSFcb *Fcb)
{

    //
    // Uninitialize the file lock if it is a file
    //

    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                  AFS_TRACE_LEVEL_VERBOSE,
                  "AFSRemoveFcb Removing Fcb %08lX\n",
                  Fcb);

    if( Fcb->Header.NodeTypeCode == AFS_FILE_FCB)
    {

        FsRtlUninitializeFileLock( &Fcb->Specific.File.FileLock);

        //
        // The resource we allocated
        //

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

        ExDeleteResourceLite( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);

    }
    else if( Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
    {


    }

    //
    // Tear down the FM specific contexts
    //

    FsRtlTeardownPerStreamContexts( &Fcb->Header);

    //
    // Delete the resources
    //

    ExDeleteResourceLite( &Fcb->NPFcb->Resource);

    ExDeleteResourceLite( &Fcb->NPFcb->PagingResource);

    ExDeleteResourceLite( &Fcb->NPFcb->CcbListLock);

    //
    // The non paged region
    //

    AFSExFreePool( Fcb->NPFcb);

    //
    // And the Fcb itself, which includes the name
    //

    AFSExFreePool( Fcb);

    return;
}
Example #6
0
VOID
FFSFreeFcb(
	IN PFFS_FCB Fcb)
{
	PFFS_VCB       Vcb;
	ASSERT(Fcb != NULL);

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

	Vcb = Fcb->Vcb;

	FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);

	ExDeleteResourceLite(&Fcb->MainResource);

	ExDeleteResourceLite(&Fcb->PagingIoResource);

	Fcb->FFSMcb->FFSFcb = NULL;

	if(IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
	{
		if (Fcb->FFSMcb)
		{
			FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb);
			FFSFreeMcb(Fcb->FFSMcb);
		}
	}

	if (Fcb->LongName.Buffer)
	{
		ExFreePool(Fcb->LongName.Buffer);
		Fcb->LongName.Buffer = NULL;
	}

#if DBG    
	ExFreePool(Fcb->AnsiFileName.Buffer);
#endif

	if (FS_VERSION == 1)
	{
		ExFreePool(Fcb->dinode1);
	}
	else
	{
		ExFreePool(Fcb->dinode2);
	}

	Fcb->Header.NodeTypeCode = (SHORT)0xCCCC;
	Fcb->Header.NodeByteSize = (SHORT)0xC0C0;

	if (FlagOn(Fcb->Flags, FCB_FROM_POOL))
	{
		ExFreePool(Fcb);
	}
	else
	{
		ExAcquireResourceExclusiveLite(
				&FFSGlobal->LAResource,
				TRUE);

		ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb);

		ExReleaseResourceForThreadLite(
				&FFSGlobal->LAResource,
				ExGetCurrentResourceThread());
	}

#if DBG

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->CountResource,
			TRUE);

	FFSGlobal->FcbAllocated--;

	ExReleaseResourceForThreadLite(
			&FFSGlobal->CountResource,
			ExGetCurrentResourceThread());
#endif

}
Example #7
0
/*
    This routine walks through the tree to RootDir & kills all unreferenced
    structures....
    imho, Useful feature
 */
ULONG
UDFCleanUpFcbChain(
    IN PVCB Vcb,
    IN PUDF_FILE_INFO fi,
    IN ULONG TreeLength,
    IN BOOLEAN VcbAcquired
    )
{
    PtrUDFFCB      Fcb = NULL;
    PtrUDFFCB      ParentFcb = NULL;
    PUDF_FILE_INFO ParentFI;
    UDFNTRequiredFCB* NtReqFcb;
    ULONG CleanCode;
    LONG RefCount, ComRefCount;
    BOOLEAN Delete = FALSE;
    ULONG          ret_val = 0;

    ValidateFileInfo(fi);
    AdPrint(("UDFCleanUpFcbChain\n"));

    ASSERT(TreeLength);

    // we can't process Tree until we can acquire Vcb
    if(!VcbAcquired)
        UDFAcquireResourceShared(&(Vcb->VCBResource),TRUE);

    // cleanup parent chain (if any & unused)
    while(fi) {

        // acquire parent
        if((ParentFI = fi->ParentFile)) {
            ASSERT(fi->Fcb);
            ParentFcb = fi->Fcb->ParentFcb;
            ASSERT(ParentFcb);
            ASSERT(ParentFcb->NTRequiredFCB);
            UDF_CHECK_PAGING_IO_RESOURCE(ParentFcb->NTRequiredFCB);
            UDFAcquireResourceExclusive(&(ParentFcb->NTRequiredFCB->MainResource),TRUE);
        } else {
            // we get to RootDir, it has no parent
            if(!VcbAcquired)
                UDFAcquireResourceShared(&(Vcb->VCBResource),TRUE);
        }
        Fcb = fi->Fcb;
        ASSERT(Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_FCB);

        NtReqFcb = Fcb->NTRequiredFCB;
        ASSERT(NtReqFcb->CommonFCBHeader.NodeTypeCode == UDF_NODE_TYPE_NT_REQ_FCB);

        // acquire current file/dir
        // we must assure that no more threads try to re-use this object
#ifdef UDF_DBG
        _SEH2_TRY {
#endif // UDF_DBG
            UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
            UDFAcquireResourceExclusive(&(NtReqFcb->MainResource),TRUE);
#ifdef UDF_DBG
        } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
            BrutePoint();
            if(ParentFI) {
                UDF_CHECK_PAGING_IO_RESOURCE(ParentFcb->NTRequiredFCB);
                UDFReleaseResource(&(ParentFcb->NTRequiredFCB->MainResource));
            } else {
                if(!VcbAcquired)
                    UDFReleaseResource(&(Vcb->VCBResource));
            }
            break;
        } _SEH2_END;
#endif // UDF_DBG
        ASSERT_REF((Fcb->ReferenceCount > fi->RefCount) || !TreeLength);
        // If we haven't pass through all files opened
        // in UDFCommonCreate before target file (TreeLength specfies
        // the number of such files) dereference them.
        // Otherwise we'll just check if the file has no references.
#ifdef UDF_DBG
        if(Fcb) {
            if(TreeLength) {
                ASSERT(Fcb->ReferenceCount);
                ASSERT(NtReqFcb->CommonRefCount);
                RefCount = UDFInterlockedDecrement((PLONG)&(Fcb->ReferenceCount));
                ComRefCount = UDFInterlockedDecrement((PLONG)&(NtReqFcb->CommonRefCount));
            }
        } else {
            BrutePoint();
        }
        if(TreeLength)
            TreeLength--;
        ASSERT(Fcb->OpenHandleCount <= Fcb->ReferenceCount);
#else
        if(TreeLength) {
            RefCount = UDFInterlockedDecrement((PLONG)&(Fcb->ReferenceCount));
            ComRefCount = UDFInterlockedDecrement((PLONG)&(NtReqFcb->CommonRefCount));
            TreeLength--;
        }
#endif

/*        if(Fcb && Fcb->FCBName && Fcb->FCBName->ObjectName.Buffer) {
            AdPrint(("    %ws (%x)\n",
                       Fcb->FCBName->ObjectName.Buffer,Fcb->ReferenceCount));
        } else if (Fcb) {
            AdPrint(("    ??? (%x)\n",Fcb->ReferenceCount));
        } else {
            AdPrint(("    ??? (??)\n"));
        }*/
        // ...and delete if it has gone

        if(!RefCount && !Fcb->OpenHandleCount) {
            // no more references... current file/dir MUST DIE!!!
            BOOLEAN AutoInherited = UDFIsAStreamDir(fi) || UDFIsAStream(fi);

            if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) {
                // do nothing
            } else
#ifndef UDF_READ_ONLY_BUILD
            if(Delete) {
/*                if(!(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
                    // set file size to zero (for UdfInfo package)
                    // we should not do this for directories
                    UDFResizeFile__(Vcb, fi, 0);
                }*/
                UDFReferenceFile__(fi);
                ASSERT(Fcb->ReferenceCount < fi->RefCount);
                UDFFlushFile__(Vcb, fi);
                UDFUnlinkFile__(Vcb, fi, TRUE);
                UDFCloseFile__(Vcb, fi);
                ASSERT(Fcb->ReferenceCount == fi->RefCount);
                Fcb->FCBFlags |= UDF_FCB_DELETED;
                Delete = FALSE;
            } else
#endif //UDF_READ_ONLY_BUILD
            if(!(Fcb->FCBFlags & UDF_FCB_DELETED)) {
                UDFFlushFile__(Vcb, fi);
            } else {
//                BrutePoint();
            }
#ifndef UDF_READ_ONLY_BUILD
            // check if we should try to delete Parent for the next time
            if(Fcb->FCBFlags & UDF_FCB_DELETE_PARENT)
                Delete = TRUE;
#endif //UDF_READ_ONLY_BUILD

            // remove references to OS-specific structures
            // to let UDF_INFO release FI & Co
            fi->Fcb = NULL;
            if(!ComRefCount) {
                // CommonFcb is also completly dereferenced
                // Kill it!
                fi->Dloc->CommonFcb = NULL;
            }

            if((CleanCode = UDFCleanUpFile__(Vcb, fi))) {
                // Check, if we can uninitialize & deallocate CommonFcb part
                // kill some cross links
                Fcb->FileInfo = NULL;
                // release allocated resources
                if(CleanCode & UDF_FREE_DLOC) {
                    // Obviously, it is a good time & place to release
                    // CommonFcb structure

//                    NtReqFcb->NtReqFCBFlags &= ~UDF_NTREQ_FCB_VALID;
                    // Unitialize byte-range locks support structure
                    FsRtlUninitializeFileLock(&(NtReqFcb->FileLock));
                    // Remove resources
                    UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
                    UDFReleaseResource(&(NtReqFcb->MainResource));
                    if(NtReqFcb->CommonFCBHeader.Resource) {
                        UDFDeleteResource(&(NtReqFcb->MainResource));
                        UDFDeleteResource(&(NtReqFcb->PagingIoResource));
                    }
                    NtReqFcb->CommonFCBHeader.Resource =
                    NtReqFcb->CommonFCBHeader.PagingIoResource = NULL;
                    UDFDeassignAcl(NtReqFcb, AutoInherited);
                    KdPrint(("UDFReleaseNtReqFCB: %x\n", NtReqFcb));
#ifdef DBG
//                    NtReqFcb->FileObject->FsContext2 = NULL;
//                    ASSERT(NtReqFcb->FileObject);
/*                    if(NtReqFcb->FileObject) {
                        ASSERT(!NtReqFcb->FileObject->FsContext2);
                        NtReqFcb->FileObject->FsContext = NULL;
                        NtReqFcb->FileObject->SectionObjectPointer = NULL;
                    }*/
#endif //DBG
                    MyFreePool__(NtReqFcb);
                    ret_val |= UDF_CLOSE_NTREQFCB_DELETED;
                } else {
                    // we usually get here when the file has some opened links
                    UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
                    UDFReleaseResource(&(NtReqFcb->MainResource));
                }
                // remove some references & free Fcb structure
                Fcb->NTRequiredFCB = NULL;
                Fcb->ParentFcb = NULL;
                UDFCleanUpFCB(Fcb);
                MyFreePool__(fi);
                ret_val |= UDF_CLOSE_FCB_DELETED;
                // get pointer to parent FCB
                fi = ParentFI;
                // free old parent's resource...
                if(fi) {
                    UDF_CHECK_PAGING_IO_RESOURCE(ParentFcb->NTRequiredFCB);
                    UDFReleaseResource(&(ParentFcb->NTRequiredFCB->MainResource));
                } else {
                    if(!VcbAcquired)
                        UDFReleaseResource(&(Vcb->VCBResource));
                }
            } else {
                // Stop cleaning up

                // Restore pointers
                fi->Fcb = Fcb;
                fi->Dloc->CommonFcb = NtReqFcb;
                // free all acquired resources
                UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
                UDFReleaseResource(&(NtReqFcb->MainResource));
                fi = ParentFI;
                if(fi) {
                    UDF_CHECK_PAGING_IO_RESOURCE(ParentFcb->NTRequiredFCB);
                    UDFReleaseResource(&(ParentFcb->NTRequiredFCB->MainResource));
                } else {
                    if(!VcbAcquired)
                        UDFReleaseResource(&(Vcb->VCBResource));
                }
                // If we have dereferenced all parents 'associated'
                // with input file & current file is still in use
                // then it isn't worth walking down the tree
                // 'cause in this case all the rest files are also used
                if(!TreeLength)
                    break;
//                AdPrint(("Stop on referenced File/Dir\n"));
            }
        } else {
            // we get to referenced file/dir. Stop search & release resource
            UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
            UDFReleaseResource(&(NtReqFcb->MainResource));
            if(ParentFI) {
                UDF_CHECK_PAGING_IO_RESOURCE(ParentFcb->NTRequiredFCB);
                UDFReleaseResource(&(ParentFcb->NTRequiredFCB->MainResource));
            } else {
                if(!VcbAcquired)
                    UDFReleaseResource(&(Vcb->VCBResource));
            }
            Delete = FALSE;
            if(!TreeLength)
                break;
            fi = ParentFI;
        }
    }
    if(fi) {
        Fcb = fi->Fcb;
        for(;TreeLength && fi;TreeLength--) {
            if(Fcb) {
                ParentFcb = Fcb->ParentFcb;
                ASSERT(Fcb->ReferenceCount);
                ASSERT(Fcb->NTRequiredFCB->CommonRefCount);
                ASSERT_REF(Fcb->ReferenceCount > fi->RefCount);
                UDFInterlockedDecrement((PLONG)&(Fcb->ReferenceCount));
                UDFInterlockedDecrement((PLONG)&(Fcb->NTRequiredFCB->CommonRefCount));
#ifdef UDF_DBG
            } else {
                BrutePoint();
#endif
            }
            Fcb = ParentFcb;
        }
    }
    if(!VcbAcquired)
        UDFReleaseResource(&(Vcb->VCBResource));
    return ret_val;

} // end UDFCleanUpFcbChain()