/// <summary>
 ///   Given a StorageInfoCore, clears the enumerators associated with it.
 /// </summary>
 private static void InvalidateEnumerators( StorageInfoCore invalidateCore )
 {
     // It is not enough to simply clear the validEnumerators collection,
     //  we have to clear the individual elements to let them know the
     //  outstanding enumerator is no longer valid.
     foreach( object entry in invalidateCore.validEnumerators.Values )
     {
         ((ArrayList)entry).Clear();
     }
     invalidateCore.validEnumerators.Clear();
 }
    /// <summary>
    /// Respond to a request from a child StorageInfo object to give
    /// it a StorageInfoCore object for the given name.
    /// </summary>
    StorageInfoCore CoreForChildStorage( string storageNname )
    {
        CheckDisposedStatus();
        
        object childElement = core.elementInfoCores[ storageNname ];

        if( null != childElement &&
            null == childElement as StorageInfoCore )
        {
            // Name is already in use, but not as a StorageInfo
            throw new InvalidOperationException(
                SR.Get(SRID.NameAlreadyInUse, storageNname ));
        }
        else if( null == childElement )
        {
            // No such element with the name exist - create one.
            // 
            childElement = new StorageInfoCore( storageNname);
            core.elementInfoCores[ storageNname ] = childElement;
        }

        Debug.Assert( null != childElement as StorageInfoCore,
            "We should have already checked to make sure childElement is either StorageInfoCore, created as one, or thrown an exception if neither is possible");

        return childElement as StorageInfoCore;
    }
    /***********************************************************************/
    // Constructors

    /// <summary>
    /// A constructor for building the root storage.
    /// This should only happen for, well, the root storage!
    /// </summary>
    internal StorageInfo( IStorage safeIStorage )
    {
        core = new StorageInfoCore( null, safeIStorage );
    }
    /// <summary>
    ///     Given a parent and a path under it, step through each of the path
    /// elements and create an intermediate StorageInfo at each step because
    /// a StorageInfo is only meaningful relative to its immediate parent -
    /// multi-step relations can't be represented.
    /// </summary>
    private void BuildStorageInfoRelativeToStorage( StorageInfo parent, string fileName )
    {

        parentStorage = parent;
        core = parent.CoreForChildStorage( fileName );
        rootStorage = parent.Root;
    }
    /// <summary>
    ///  Given a StorageInfoCore, recursively release objects associated with
    /// sub-storages and then releases objects associated with self.    
    /// </summary>
    /// <remarks>
    ///  This didn't used to be a static method - but this caused some problems.
    /// All operations need to be on the given parameter "startCore".  If this
    /// wasn't static, the code had access to the member "core" and that's not
    /// the right StorageInfoCore to use.  This caused some bugs that would have
    /// been avoided if this was static.  To prevent future bugs of similar
    /// nature, I made this static.
    /// </remarks>
    internal static void RecursiveStorageInfoCoreRelease( StorageInfoCore startCore )
    {
        // If the underlying IStorage pointer is null, we never did anything
        //  with this storage or anything under it.  We can halt our recursion
        //  here.
        if( startCore.safeIStorage == null )
            return;

        try
        {
            //////////////////////////////////////////////////////////////////////
            //
            //  Call clean-up code for things on the storage represented by startCore.
            
            //////////////////////////////////////////////////////////////////////
            //
            //  Call clean-up code for things *under* startCore.
            
            // See if we have child storages and streams, and if so, close them
            //  down.
            foreach( object o in startCore.elementInfoCores.Values )
            {
                if( o is StorageInfoCore )
                {
                    RecursiveStorageInfoCoreRelease( (StorageInfoCore)o );
                }
                else if( o is StreamInfoCore )
                {
                    StreamInfoCore streamRelease = (StreamInfoCore)o;

                    try
                    {
                        if (null != streamRelease.exposedStream)
                        {
                            ((Stream)(streamRelease.exposedStream)).Close();
                        }
                        streamRelease.exposedStream = null;
                    }
                    finally
                    {
                        // We need this release and null-out to happen even if we
                        //  ran into problems with the clean-up code above.
                        if( null != streamRelease.safeIStream)
                        {
                            ((IDisposable) streamRelease.safeIStream).Dispose();
                            streamRelease.safeIStream = null;
                        }

                        // Null name in core signifies the core object is disposed
                        ((StreamInfoCore)o).streamName = null;
                    }
                }
            }

            // All child objects freed, clear out the enumerators
            InvalidateEnumerators( startCore );
        }
        finally
        {
            //  We want to make sure this happens even if any of the cleanup
            //  above fails, so that's why it's in a "finally" block here.
            
            //////////////////////////////////////////////////////////////////////
            //
            //  Free unmanaged resources associated with the startCore storage
            
            if( null != startCore.safeIStorage)
            {           
                ((IDisposable) startCore.safeIStorage).Dispose();
                startCore.safeIStorage = null;
            }

            // Null name in core signifies the core object is disposed
            startCore.storageName = null;
        }
    }