StreamInfo.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / System / IO / Packaging / CompoundFile / StreamInfo.cs / 1305600 / StreamInfo.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  Class for manipulating streams in the container file 
//
// History: 
//  05/13/2002: RogerCh: Initial implementation.
//  06/25/2002: RogerCh: Data space support.
//  07/31/2002: RogerCh: Make obvious that we are using security suppressed interfaces.
//  05/20/2003: RogerCh: Ported to WCP tree. 
//  05/28/2003: RogerCh: Added long name support
// 
//----------------------------------------------------------------------------- 

using System; 
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics; // For Debug.Assert
using System.IO; 
using System.Runtime.InteropServices;
using System.Security; 
using System.Security.Permissions; 

using System.Windows;                 //  SR.Get(SRID.[exception message]) 
using MS.Internal.IO.Packaging.CompoundFile;
using CU = MS.Internal.IO.Packaging.CompoundFile.ContainerUtilities;

using System.IO.Packaging; 
using MS.Internal.WindowsBase;
 
namespace System.IO.Packaging 
{
    ///  
    /// Core information for a StreamInfo object.
    /// 
    internal class StreamInfoCore
    { 
        internal StreamInfoCore(
            string nameStream, 
            string label ) : this( nameStream, label, null ) {;} 

        internal StreamInfoCore( 
            string nameStream,
            string label,
            IStream s )
        { 
            streamName = nameStream;
            dataSpaceLabel = label; 
            safeIStream = s; 
            exposedStream = null;
        } 

        /// 
        /// The compound-file friendly version of streamName.
        ///  
        internal string      streamName;
 
        ///  
        /// A cached reference to the stream object for accessing the data  This
        /// may be null if we haven't had need to open the stream. 
        /// 
        internal IStream safeIStream;

        ///  
        /// The label for the data space definition that is associated with this
        /// stream.  This can only be set at the time of StreamInfo.Create().  A 
        /// null string indicates that we are not in a data space. 
        /// 
        internal string dataSpaceLabel; 

        /// 
        /// This represents visible stream object.  When the stream represented by this StreamInfo is supposed
        /// to go away, this will be reset to null. 
        /// 
        internal object exposedStream; 
    } 

    ///  
    /// Class for manipulating streams in the container file
    /// 
    public class StreamInfo
    { 
        /***********************************************************************/
        // Default values to use for shortcuts 
        const FileMode   defaultFileOpenMode   = FileMode.OpenOrCreate; 
        const FileMode   defaultFileCreateMode = FileMode.Create;
        const string     defaultDataSpace      = null; // Programmatic change-able? 

        /***********************************************************************/
        // Instance values
 
        /// 
        /// A reference back to the parent storage object 
        ///  
        StorageInfo parentStorage;
 
        /// 
        /// Reference to a class that contains our core information.  This is
        /// maintained by our parent storage.
        ///  
        StreamInfoCore core;
 
        ///  
        /// CompoundFileStreamReference for this StreamInfo object
        ///  
        CompoundFileStreamReference _streamReference;

        /// 
        /// We need to rememeber the FileAccess that was used for openning 
        /// in order to provide correct information, we can not used underlying structures,
        /// as the same stream can be subsequently opened in different modes 
        ///  
        private FileAccess openFileAccess;
 
        private CompressionOption _compressionOption;
        private EncryptionOption   _encryptionOption;
        private bool _needToGetTransformInfo = true;
 
        /***********************************************************************/
        // Constructors 
 
        private void BuildStreamInfoRelativeToStorage( StorageInfo parent, string path )
        { 
            parentStorage = parent;
            core = parentStorage.CoreForChildStream( path );
        }
 
        /// 
        /// Creates a new instance relative to the root 
        ///  
        /// The root storage
        /// Path to stream under root storage 
        private StreamInfo( StorageRoot root, string streamPath ) : this((StorageInfo)root, streamPath)
        {
        }
 
        /// 
        /// Creates a new instance relative to the given parent 
        ///  
        /// The parent storage
        /// Path to stream under parent storage 
        internal StreamInfo( StorageInfo parent, string streamName ) : this (parent, streamName, CompressionOption.NotCompressed, EncryptionOption.None)
        {
        }
 

        ///  
        /// Creates a new instance relative to the given parent 
        /// 
        /// The parent storage 
        /// Path to stream under parent storage
        /// CompressionOption
        /// EncryptionOption
        internal StreamInfo( StorageInfo parent, string streamName, CompressionOption compressionOption, 
            EncryptionOption encryptionOption )
        { 
             // Parameter validation 
            CU.CheckAgainstNull( parent, "parent" );
            CU.CheckStringAgainstNullAndEmpty( streamName, "streamName" ); 

            // Parse path relative to given parent.
            BuildStreamInfoRelativeToStorage( parent,
                streamName); 

             _compressionOption = compressionOption; 
            _encryptionOption   = encryptionOption; 
            _streamReference = new CompoundFileStreamReference(this.parentStorage.FullNameInternal, this.core.streamName);
        } 

        /***********************************************************************/
        // Properties
 
        /// 
        /// The CompressionOption on the stream 
        ///  
        public CompressionOption CompressionOption
        { 
            get
            {
                if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed
                { 
                    // The .Net Design Guidelines instruct us not to throw exceptions in property getters.
                    return CompressionOption.NotCompressed; 
                } 

                EnsureTransformInformation(); 

                return _compressionOption;
            }
        } 

        ///  
        /// The EncryptionOption on the stream 
        /// 
        public EncryptionOption EncryptionOption 
        {
            get
            {
                if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed 
                {
                    // The .Net Design Guidelines instruct us not to throw exceptions in property getters. 
                    return EncryptionOption.None; 
                }
 
                EnsureTransformInformation();

                return _encryptionOption;
            } 
        }
 
        ///  
        /// The name of this stream
        ///  
        public string Name
        {
            get
            { 
                if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed
                { 
                    // The .Net Design Guidelines instruct us not to throw exceptions in property getters. 
                    return "";
                } 

                return core.streamName;
            }
        } 

        /***********************************************************************/ 
        // Methods 

        ///  
        /// Opens a stream
        /// 
        /// Stream object to manipulate data
        public Stream GetStream() 
        {
            return GetStream( defaultFileOpenMode, parentStorage.Root.OpenAccess ); 
        } 

        ///  
        /// Opens a stream with the given open mode flags
        /// 
        /// Open mode flags
        /// Stream object to manipulate data 
        public Stream GetStream( FileMode mode )
        { 
            return GetStream( mode, parentStorage.Root.OpenAccess ); 
        }
 
        /// 
        /// Opens a stream with the given open mode flags and access flags
        /// 
        /// Open mode flags 
        /// File access flags
        /// Stream object to manipulate data 
        public Stream GetStream( FileMode mode, FileAccess access ) 
        {
            CheckDisposedStatus(); 

            int grfMode = 0;
            IStream openedIStream = null;
 
            openFileAccess = access;
            // becasue of the stream caching mechanism we must adjust FileAccess parameter. 
            // We want to open stream with the widest access posible, in case Package was open in ReadWrite 
            // we need to open stream in ReadWrite even if user explicitly asked us to do ReadOnly/WriteOnly.
            // There is a possibility of a next request coming in as as ReadWrite request, and we would like to 
            // take advanatage of the cached stream by wrapping with appropriate access limitations.
            if (parentStorage.Root.OpenAccess == FileAccess.ReadWrite)
            {
                // Generate the access flags from the access parameter 
                access = FileAccess.ReadWrite;
            } 
 
            // Generate the access flags from the access parameter
            SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess( access, ref grfMode ); 

            // Only SHARE_EXCLUSIVE for now, FileShare issue TBD
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;
 
            CheckAccessMode(grfMode);
 
            // Act based on FileMode 
            switch(mode)
            { 
                case FileMode.Append:
                    throw new ArgumentException(
                        SR.Get(SRID.FileModeUnsupported));
                case FileMode.Create: 
                    // Check to make sure root container is not read-only, and that
                    //  we're not pointlessly trying to create a read-only stream. 
                    CreateTimeReadOnlyCheck(openFileAccess); 

                    // Close down any existing streams floating out there 
                    if (null != core.exposedStream)
                    {
                        ((Stream)(core.exposedStream)).Close();
                    } 
                    core.exposedStream = null;
 
                    if( null != core.safeIStream ) 
                    {
                        // Close out existing stream 
                        ((IDisposable) core.safeIStream).Dispose();
                        core.safeIStream = null;
                    }
 
                    // Cleanup done, create new stream in its place
                    grfMode |= SafeNativeCompoundFileConstants.STGM_CREATE; 
                    openedIStream = CreateStreamOnParentIStorage( 
                            core.streamName,
                        grfMode ); 
                    break;
                case FileMode.CreateNew:
                    throw new ArgumentException(
                        SR.Get(SRID.FileModeUnsupported)); 
                case FileMode.Open:
                    // If we've got a stream, return a CFStream built from its clone 
                    if( null != core.safeIStream ) 
                    {
                        return CFStreamOfClone(openFileAccess); 
                    }

                    // Need to call Open API with NULL open flags
                    openedIStream = OpenStreamOnParentIStorage( 
                            core.streamName,
                        grfMode ); 
                    break; 
                case FileMode.OpenOrCreate:
                    // If we've got a stream, return a CFStream built from its clone 
                    if( null != core.safeIStream )
                    {
                        return CFStreamOfClone(openFileAccess);
                    } 

                    // Skip creation attempt for read-only container or specifying 
                    //  read-only stream 
                    if( FileAccess.Read != parentStorage.Root.OpenAccess &&
                        FileAccess.Read != openFileAccess ) 
                    {
                        // Try creating first.  If it already exists then do an open.  This
                        //  seems ugly but this method involves the fewest number of
                        //  managed/unmanaged transitions. 

                        if( !parentStorage.Exists ) 
                        { 
                            parentStorage.Create();
                        } 
                        int nativeCallErrorCode =
                            parentStorage.SafeIStorage.CreateStream(
                                core.streamName,
                            grfMode, 
                            0,
                            0, 
                            out openedIStream ); 

                        if( SafeNativeCompoundFileConstants.S_OK != nativeCallErrorCode && 
                            SafeNativeCompoundFileConstants.STG_E_FILEALREADYEXISTS != nativeCallErrorCode )
                        {
                            throw new IOException(
                                SR.Get(SRID.UnableToCreateStream), 
                                new COMException(
                                    SR.Get(SRID.NamedAPIFailure, "IStorage.CreateStream"), 
                                    nativeCallErrorCode )); 
                        }
 
                        // Parent storage has changed - invalidate all standing enuemrators
                        parentStorage.InvalidateEnumerators();

                        // else - proceed with open 
                    }
 
                    if( null == openedIStream ) 
                    {
                        // If we make it here, it means the create stream call failed 
                        //  because of a STG_E_FILEALREADYEXISTS
                        //  or container is read-only
                        openedIStream = OpenStreamOnParentIStorage(
                                core.streamName, 
                            grfMode );
                    } 
                    break; 
                case FileMode.Truncate:
                    throw new ArgumentException( 
                        SR.Get(SRID.FileModeUnsupported));
                default:
                    throw new ArgumentException(
                        SR.Get(SRID.FileModeInvalid)); 
            }
 
            core.safeIStream = openedIStream; 

            Stream returnStream = 
                BuildStreamOnUnderlyingIStream( core.safeIStream, openFileAccess, this );

            core.exposedStream = returnStream;
 
            return returnStream;
        } 
 
        /***********************************************************************/
        // Internal/Private functionality 

        /// 
        /// Creates a stream with all default parameters
        ///  
        /// Stream object to manipulate data
        internal Stream Create() 
        { 
            return Create( defaultFileCreateMode, parentStorage.Root.OpenAccess, defaultDataSpace );
        } 

        /// 
        /// Creates a stream with the given create mode
        ///  
        /// Desired create mode
        /// Stream object to manipulate data 
        private Stream Create( FileMode mode ) 
        {
            return Create( mode, parentStorage.Root.OpenAccess, defaultDataSpace ); 
        }

        /// 
        /// Creates a stream encoded in the given data space 
        /// 
        /// Data space label 
        /// Stream object to manipulate data 
        internal Stream Create( string dataSpaceLabel )
        { 
            return Create( defaultFileCreateMode, parentStorage.Root.OpenAccess, dataSpaceLabel );
        }

        ///  
        /// Creates a stream with the given create and access flags
        ///  
        /// Desired create mode flag 
        /// Access flags
        /// Stream object to manipulate data 
        private Stream Create( FileMode mode, FileAccess access )
        {
            return Create( mode, access, defaultDataSpace );
        } 

        ///  
        /// Creates a stream with the given parameters 
        /// 
        /// Creation mode 
        /// Access mode
        /// Data space encoding
        /// Stream object to manipulate data
        internal Stream Create( FileMode mode, FileAccess access, string dataSpace ) 
        {
            CheckDisposedStatus(); 
 
            int grfMode = 0;
            IStream createdSafeIStream = null; 
            DataSpaceManager dataSpaceManager = null;

            // Check to make sure root container is not read-only, and that
            //  we're not pointlessly trying to create a read-only stream. 
            CreateTimeReadOnlyCheck( access );
 
            // Check to see if the data space label is valid 
            if( null != dataSpace )
            { 
                if( 0 == dataSpace.Length )
                    throw new ArgumentException(
                        SR.Get(SRID.DataSpaceLabelInvalidEmpty));
 
                dataSpaceManager = parentStorage.Root.GetDataSpaceManager();
                if( !dataSpaceManager.DataSpaceIsDefined( dataSpace ) ) 
                    throw new ArgumentException( 
                        SR.Get(SRID.DataSpaceLabelUndefined));
            } 

            openFileAccess = access;
            // becasue of the stream caching mechanism we must adjust FileAccess parameter.
            // We want to open stream with the widest access posible, in case Package was open in ReadWrite 
            // we need to open stream in ReadWrite even if user explicitly asked us to do ReadOnly/WriteOnly.
            // There is a possibility of a next request coming in as as ReadWrite request, and we would like to 
            // take advanatage of the cached stream by wrapping with appropriate access limitations. 
            if (parentStorage.Root.OpenAccess == FileAccess.ReadWrite)
            { 
                access = FileAccess.ReadWrite;
            }

            // Generate the access flags from the access parameter 
            SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess( access, ref grfMode );
 
            // Only SHARE_EXCLUSIVE for now, FileShare issue TBD 
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;
 
            CheckAccessMode(grfMode);

            // Act based on FileMode
            switch(mode) 
            {
                case FileMode.Create: 
                    // Close down any existing streams floating out there 
                    if (null != core.exposedStream)
                    { 
                        ((Stream)(core.exposedStream)).Close();
                    }
                    core.exposedStream = null;
 
                    if( null != core.safeIStream )
                    { 
                        // Release reference 
                        ((IDisposable) core.safeIStream).Dispose();
                        core.safeIStream = null; 
                    }

                    // Cleanup done, create new stream in its place.
                    grfMode |= SafeNativeCompoundFileConstants.STGM_CREATE; 
                    createdSafeIStream = CreateStreamOnParentIStorage(
                            core.streamName, 
                        grfMode ); 
                    break;
                case FileMode.CreateNew: 
                    // If we've created a CFStream, this fails because stream is already there.
                    if( null != core.safeIStream )
                        throw new IOException(
                            SR.Get(SRID.StreamAlreadyExist)); 

                    // Need to call Create API with NULL create flags 
                    createdSafeIStream = CreateStreamOnParentIStorage( 
                            core.streamName,
                        grfMode ); 
                    break;
                case FileMode.Append:   // None of these are valid in a Create
                case FileMode.Open:
                case FileMode.OpenOrCreate: 
                case FileMode.Truncate:
                default: 
                    throw new ArgumentException( 
                        SR.Get(SRID.FileModeInvalid));
            } 

            core.safeIStream = createdSafeIStream;
            // At this point we passed all previous checks and got the underlying IStream.
            //  Set our data space label to the given label, and the stream to the retrieved stream. 
            core.dataSpaceLabel = dataSpace;
            if( null != dataSpace ) 
            { 
                dataSpaceManager.CreateDataSpaceMapping(
                    new CompoundFileStreamReference( parentStorage.FullNameInternal, core.streamName ), 
                    core.dataSpaceLabel );
            }

            Stream returnStream = 
                BuildStreamOnUnderlyingIStream( core.safeIStream, openFileAccess, this );
 
            _needToGetTransformInfo = false;    // We created stream with the given dataspace setting 
                                                //  so, there is no need to get the dataspace setting
            core.exposedStream = returnStream; 

            return returnStream;
        }
 
        Stream BuildStreamOnUnderlyingIStream(
            IStream underlyingIStream, 
            FileAccess access, 
            StreamInfo parent )
        { 
            Stream rawStream = new CFStream( underlyingIStream, access, parent );

            if( null == core.dataSpaceLabel )
            { 
                // The stream is not transformed in any data space, add buffering and return
                return new BufferedStream( rawStream ); 
            } 
            else
            { 
                // Pass raw stream to data space manager to get real stream
               return parentStorage.Root.GetDataSpaceManager().CreateDataSpaceStream(
                    StreamReference, rawStream);
            } 
        }
 
        ///  
        /// A check against FileAccess.Read at create time.  It should fail if
        ///  the root container is read-only, or if we're pointlessly trying 
        ///  to create a read-only stream.
        /// 
        void CreateTimeReadOnlyCheck( FileAccess access )
        { 
            // Can't create a stream if the root container is read-only
            if( FileAccess.Read == parentStorage.Root.OpenAccess ) 
                throw new IOException( 
                    SR.Get(SRID.CanNotCreateInReadOnly));
 
            // Doesn't make sense to create a new stream just to make it read-only
            if( access == FileAccess.Read )
                throw new ArgumentException(
                    SR.Get(SRID.CanNotCreateAsReadOnly)); 
        }
 
        ///  
        /// Shortcut macro - calls the IStorage::CreateStream method on the parent
        /// storage object. 
        /// 
        IStream CreateStreamOnParentIStorage(
            string name,
            int mode ) 
        {
            IStream createdStream = null; 
            int nativeCallErrorCode = 0; 

            if( !parentStorage.Exists ) 
            {
                parentStorage.Create();
            }
 
            nativeCallErrorCode = parentStorage.SafeIStorage.CreateStream(
                name, 
                mode, 
                0,
                0, 
                out createdStream );

            if( SafeNativeCompoundFileConstants.STG_E_INVALIDFLAG == nativeCallErrorCode )
            { 
                throw new ArgumentException(
                    SR.Get(SRID.StorageFlagsUnsupported)); 
            } 
            else if ( SafeNativeCompoundFileConstants.S_OK != nativeCallErrorCode )
            { 
                throw new IOException(
                    SR.Get(SRID.UnableToCreateStream),
                    new COMException(
                        SR.Get(SRID.NamedAPIFailure, "IStorage.CreateStream"), 
                        nativeCallErrorCode ));
            } 
 
            // Parent storage has changed - invalidate all standing enuemrators
            parentStorage.InvalidateEnumerators(); 

            return createdStream;
        }
 
        /// 
        /// Shortcut macro - calls the IStorage::OpenStream method on the parent 
        /// storage object. 
        /// 
        IStream OpenStreamOnParentIStorage( 
            string name,
            int mode )
        {
            IStream openedStream = null; 
            int nativeCallErrorCode = 0;
 
            nativeCallErrorCode = parentStorage.SafeIStorage.OpenStream( 
                name,
                0, 
                mode,
                0,
                out openedStream );
 
            if( SafeNativeCompoundFileConstants.S_OK != nativeCallErrorCode )
            { 
                throw new IOException( 
                    SR.Get(SRID.UnableToOpenStream),
                    new COMException( 
                        SR.Get(SRID.NamedAPIFailure, "IStorage.OpenStream"),
                        nativeCallErrorCode ));
            }
            return openedStream; 
        }
 
        ///  
        /// Deletes the stream specified by this StreamInfo
        ///  
        internal void Delete()
        {
            CheckDisposedStatus();
 
            if( InternalExists() )
            { 
                if( null != core.safeIStream ) 
                {
                    // Close out existing stream 
                    ((IDisposable) core.safeIStream).Dispose();
                    core.safeIStream = null;
                }
                parentStorage.DestroyElement( core.streamName ); 

                // Parent storage has changed - invalidate all standing enuemrators 
                parentStorage.InvalidateEnumerators(); 
            }
            else 
            {
                // If a FileInfo is told to delete a file that does not
                //  exist, nothing happens.  We follow that example here.
            } 
        }
 
        ///  
        /// It is valid to have a StreamInfo class that points to a stream
        /// that does not (yet) exist.  However, it is impossible to perform 
        /// operations on a stream that does not exst, so the methods that
        /// require an existing stream need to be able to check if the stream
        /// exists before trying to perform its operations.
        ///  
        /// Whether "this" stream exists
        internal bool InternalExists() 
        { 
            // If we have a stream, it's pretty obvious that we exist.
            if( null != core.safeIStream ) 
                return true;

            // If parent storage does not exist, we can't possibly exist either
            if( !parentStorage.Exists ) 
                return false;
 
            // At this point we know the parent storage exists, but we don't know 
            //  if we do.  Try to open the stream.
            return SafeNativeCompoundFileConstants.S_OK == parentStorage.SafeIStorage.OpenStream( 
                core.streamName,
                0,
                SafeNativeCompoundFileConstants.STGM_READ | SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE,
                0, 
                out core.safeIStream );
        } 
 
        /// 
        /// Most of the time internal methods that want to do an internal check 
        /// to see if a stream exists is only interested in proceeding if it does.
        /// If it doesn't, abort with an exception.  This implements the little
        /// shortcut.
        ///  
        void VerifyExists()
        { 
            if( !InternalExists() ) 
            {
                throw new IOException( 
                    SR.Get(SRID.StreamNotExist));
            }
            return;
        } 

        // This fixes bug# 4947, a degenerate case of bug #5563 
        private Stream CFStreamOfClone( FileAccess access ) 
        {
            long dummy = 0; 

            IStream cloneStream = null;
            core.safeIStream.Clone( out cloneStream );
            cloneStream.Seek( 0, SafeNativeCompoundFileConstants.STREAM_SEEK_SET, out dummy ); 

            Stream returnStream = 
                BuildStreamOnUnderlyingIStream( cloneStream, access, this ); 

            core.exposedStream = returnStream; 

            return returnStream;
        }
 
        // Check whether this StreamInfo object is still valid.  If not, thrown an
        //  ObjectDisposedException. 
        internal void CheckDisposedStatus() 
        {
            // Check to see if we're still valid. 
            if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed
                throw new ObjectDisposedException(null, SR.Get(SRID.StreamInfoDisposed));
        }
 
        // Check whether this StreamInfo object is still valid.  Return result.
        internal bool StreamInfoDisposed 
        { 
            get
            { 
                // Check to see if we're still valid.
                // Null name in core signifies the core object is disposed.
                // Also check the parent storage.
                return (( null == core.streamName ) || parentStorage.StorageDisposed); 
            }
        } 
 

        // If we opened the IStream but haven't publicly exposed any Streams yet (i.e. InternalExists), 
        // check to make sure the access modes match.
        internal void CheckAccessMode(int grfMode)
        {
            // Do we have an IStream? 
            if( null != core.safeIStream )
            { 
                // Have we exposed it publicly yet? 
                if( null == core.exposedStream )
                { 
                    System.Runtime.InteropServices.ComTypes.STATSTG mySTATs;
                    core.safeIStream.Stat( out mySTATs, SafeNativeCompoundFileConstants.STATFLAG_NONAME );

                    // Do the modes match? 
                    if( grfMode != mySTATs.grfMode )
                    { 
                        // Modes don't match, close out existing stream. 
                        ((IDisposable) core.safeIStream).Dispose();
                        core.safeIStream = null; 
                    }
                }
            }
        } 

        internal CompoundFileStreamReference StreamReference 
        { 
            get
            { 
                return _streamReference;
            }
        }
 
        // Inspect the transforms applied this stream and retreive the compression and
        //  RM encryption options 
        private void EnsureTransformInformation() 
        {
            if (_needToGetTransformInfo && InternalExists()) 
            {
                _encryptionOption = EncryptionOption.None;
                _compressionOption = CompressionOption.NotCompressed;
 
                //If the StreamInfo exists we go on to check if correct transform has been
                //applied to the Stream 
 
                DataSpaceManager dsm = parentStorage.Root.GetDataSpaceManager();
 
                List transforms = dsm.GetTransformsForStreamInfo(this);

                foreach (IDataTransform dataTransform in transforms)
                { 
                    string id = dataTransform.TransformIdentifier as string;
                    if (id != null) 
                    { 
                        id = id.ToUpperInvariant();
 
                        if (String.CompareOrdinal(id,
                            RightsManagementEncryptionTransform.ClassTransformIdentifier.ToUpperInvariant()) == 0
                            &&
                            (dataTransform as RightsManagementEncryptionTransform) != null) 
                        {
                            _encryptionOption = EncryptionOption.RightsManagement; 
                        } 
                        else if (String.CompareOrdinal(id,
                            CompressionTransform.ClassTransformIdentifier.ToUpperInvariant()) == 0 
                            &&
                            (dataTransform as CompressionTransform) != null)
                        {
                            // We don't persist the compression level used during compression process 
                            // When we access the stream, all we can determine is whether it is compressed or not
                            // In all our scenarios, the level we use is Level 9 which is equivalent to Maximum 
                            _compressionOption = CompressionOption.Maximum; 
                        }
                    } 
                }
                _needToGetTransformInfo = false;
            }
        } 
    }
} 
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  Class for manipulating streams in the container file 
//
// History: 
//  05/13/2002: RogerCh: Initial implementation.
//  06/25/2002: RogerCh: Data space support.
//  07/31/2002: RogerCh: Make obvious that we are using security suppressed interfaces.
//  05/20/2003: RogerCh: Ported to WCP tree. 
//  05/28/2003: RogerCh: Added long name support
// 
//----------------------------------------------------------------------------- 

using System; 
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics; // For Debug.Assert
using System.IO; 
using System.Runtime.InteropServices;
using System.Security; 
using System.Security.Permissions; 

using System.Windows;                 //  SR.Get(SRID.[exception message]) 
using MS.Internal.IO.Packaging.CompoundFile;
using CU = MS.Internal.IO.Packaging.CompoundFile.ContainerUtilities;

using System.IO.Packaging; 
using MS.Internal.WindowsBase;
 
namespace System.IO.Packaging 
{
    ///  
    /// Core information for a StreamInfo object.
    /// 
    internal class StreamInfoCore
    { 
        internal StreamInfoCore(
            string nameStream, 
            string label ) : this( nameStream, label, null ) {;} 

        internal StreamInfoCore( 
            string nameStream,
            string label,
            IStream s )
        { 
            streamName = nameStream;
            dataSpaceLabel = label; 
            safeIStream = s; 
            exposedStream = null;
        } 

        /// 
        /// The compound-file friendly version of streamName.
        ///  
        internal string      streamName;
 
        ///  
        /// A cached reference to the stream object for accessing the data  This
        /// may be null if we haven't had need to open the stream. 
        /// 
        internal IStream safeIStream;

        ///  
        /// The label for the data space definition that is associated with this
        /// stream.  This can only be set at the time of StreamInfo.Create().  A 
        /// null string indicates that we are not in a data space. 
        /// 
        internal string dataSpaceLabel; 

        /// 
        /// This represents visible stream object.  When the stream represented by this StreamInfo is supposed
        /// to go away, this will be reset to null. 
        /// 
        internal object exposedStream; 
    } 

    ///  
    /// Class for manipulating streams in the container file
    /// 
    public class StreamInfo
    { 
        /***********************************************************************/
        // Default values to use for shortcuts 
        const FileMode   defaultFileOpenMode   = FileMode.OpenOrCreate; 
        const FileMode   defaultFileCreateMode = FileMode.Create;
        const string     defaultDataSpace      = null; // Programmatic change-able? 

        /***********************************************************************/
        // Instance values
 
        /// 
        /// A reference back to the parent storage object 
        ///  
        StorageInfo parentStorage;
 
        /// 
        /// Reference to a class that contains our core information.  This is
        /// maintained by our parent storage.
        ///  
        StreamInfoCore core;
 
        ///  
        /// CompoundFileStreamReference for this StreamInfo object
        ///  
        CompoundFileStreamReference _streamReference;

        /// 
        /// We need to rememeber the FileAccess that was used for openning 
        /// in order to provide correct information, we can not used underlying structures,
        /// as the same stream can be subsequently opened in different modes 
        ///  
        private FileAccess openFileAccess;
 
        private CompressionOption _compressionOption;
        private EncryptionOption   _encryptionOption;
        private bool _needToGetTransformInfo = true;
 
        /***********************************************************************/
        // Constructors 
 
        private void BuildStreamInfoRelativeToStorage( StorageInfo parent, string path )
        { 
            parentStorage = parent;
            core = parentStorage.CoreForChildStream( path );
        }
 
        /// 
        /// Creates a new instance relative to the root 
        ///  
        /// The root storage
        /// Path to stream under root storage 
        private StreamInfo( StorageRoot root, string streamPath ) : this((StorageInfo)root, streamPath)
        {
        }
 
        /// 
        /// Creates a new instance relative to the given parent 
        ///  
        /// The parent storage
        /// Path to stream under parent storage 
        internal StreamInfo( StorageInfo parent, string streamName ) : this (parent, streamName, CompressionOption.NotCompressed, EncryptionOption.None)
        {
        }
 

        ///  
        /// Creates a new instance relative to the given parent 
        /// 
        /// The parent storage 
        /// Path to stream under parent storage
        /// CompressionOption
        /// EncryptionOption
        internal StreamInfo( StorageInfo parent, string streamName, CompressionOption compressionOption, 
            EncryptionOption encryptionOption )
        { 
             // Parameter validation 
            CU.CheckAgainstNull( parent, "parent" );
            CU.CheckStringAgainstNullAndEmpty( streamName, "streamName" ); 

            // Parse path relative to given parent.
            BuildStreamInfoRelativeToStorage( parent,
                streamName); 

             _compressionOption = compressionOption; 
            _encryptionOption   = encryptionOption; 
            _streamReference = new CompoundFileStreamReference(this.parentStorage.FullNameInternal, this.core.streamName);
        } 

        /***********************************************************************/
        // Properties
 
        /// 
        /// The CompressionOption on the stream 
        ///  
        public CompressionOption CompressionOption
        { 
            get
            {
                if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed
                { 
                    // The .Net Design Guidelines instruct us not to throw exceptions in property getters.
                    return CompressionOption.NotCompressed; 
                } 

                EnsureTransformInformation(); 

                return _compressionOption;
            }
        } 

        ///  
        /// The EncryptionOption on the stream 
        /// 
        public EncryptionOption EncryptionOption 
        {
            get
            {
                if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed 
                {
                    // The .Net Design Guidelines instruct us not to throw exceptions in property getters. 
                    return EncryptionOption.None; 
                }
 
                EnsureTransformInformation();

                return _encryptionOption;
            } 
        }
 
        ///  
        /// The name of this stream
        ///  
        public string Name
        {
            get
            { 
                if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed
                { 
                    // The .Net Design Guidelines instruct us not to throw exceptions in property getters. 
                    return "";
                } 

                return core.streamName;
            }
        } 

        /***********************************************************************/ 
        // Methods 

        ///  
        /// Opens a stream
        /// 
        /// Stream object to manipulate data
        public Stream GetStream() 
        {
            return GetStream( defaultFileOpenMode, parentStorage.Root.OpenAccess ); 
        } 

        ///  
        /// Opens a stream with the given open mode flags
        /// 
        /// Open mode flags
        /// Stream object to manipulate data 
        public Stream GetStream( FileMode mode )
        { 
            return GetStream( mode, parentStorage.Root.OpenAccess ); 
        }
 
        /// 
        /// Opens a stream with the given open mode flags and access flags
        /// 
        /// Open mode flags 
        /// File access flags
        /// Stream object to manipulate data 
        public Stream GetStream( FileMode mode, FileAccess access ) 
        {
            CheckDisposedStatus(); 

            int grfMode = 0;
            IStream openedIStream = null;
 
            openFileAccess = access;
            // becasue of the stream caching mechanism we must adjust FileAccess parameter. 
            // We want to open stream with the widest access posible, in case Package was open in ReadWrite 
            // we need to open stream in ReadWrite even if user explicitly asked us to do ReadOnly/WriteOnly.
            // There is a possibility of a next request coming in as as ReadWrite request, and we would like to 
            // take advanatage of the cached stream by wrapping with appropriate access limitations.
            if (parentStorage.Root.OpenAccess == FileAccess.ReadWrite)
            {
                // Generate the access flags from the access parameter 
                access = FileAccess.ReadWrite;
            } 
 
            // Generate the access flags from the access parameter
            SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess( access, ref grfMode ); 

            // Only SHARE_EXCLUSIVE for now, FileShare issue TBD
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;
 
            CheckAccessMode(grfMode);
 
            // Act based on FileMode 
            switch(mode)
            { 
                case FileMode.Append:
                    throw new ArgumentException(
                        SR.Get(SRID.FileModeUnsupported));
                case FileMode.Create: 
                    // Check to make sure root container is not read-only, and that
                    //  we're not pointlessly trying to create a read-only stream. 
                    CreateTimeReadOnlyCheck(openFileAccess); 

                    // Close down any existing streams floating out there 
                    if (null != core.exposedStream)
                    {
                        ((Stream)(core.exposedStream)).Close();
                    } 
                    core.exposedStream = null;
 
                    if( null != core.safeIStream ) 
                    {
                        // Close out existing stream 
                        ((IDisposable) core.safeIStream).Dispose();
                        core.safeIStream = null;
                    }
 
                    // Cleanup done, create new stream in its place
                    grfMode |= SafeNativeCompoundFileConstants.STGM_CREATE; 
                    openedIStream = CreateStreamOnParentIStorage( 
                            core.streamName,
                        grfMode ); 
                    break;
                case FileMode.CreateNew:
                    throw new ArgumentException(
                        SR.Get(SRID.FileModeUnsupported)); 
                case FileMode.Open:
                    // If we've got a stream, return a CFStream built from its clone 
                    if( null != core.safeIStream ) 
                    {
                        return CFStreamOfClone(openFileAccess); 
                    }

                    // Need to call Open API with NULL open flags
                    openedIStream = OpenStreamOnParentIStorage( 
                            core.streamName,
                        grfMode ); 
                    break; 
                case FileMode.OpenOrCreate:
                    // If we've got a stream, return a CFStream built from its clone 
                    if( null != core.safeIStream )
                    {
                        return CFStreamOfClone(openFileAccess);
                    } 

                    // Skip creation attempt for read-only container or specifying 
                    //  read-only stream 
                    if( FileAccess.Read != parentStorage.Root.OpenAccess &&
                        FileAccess.Read != openFileAccess ) 
                    {
                        // Try creating first.  If it already exists then do an open.  This
                        //  seems ugly but this method involves the fewest number of
                        //  managed/unmanaged transitions. 

                        if( !parentStorage.Exists ) 
                        { 
                            parentStorage.Create();
                        } 
                        int nativeCallErrorCode =
                            parentStorage.SafeIStorage.CreateStream(
                                core.streamName,
                            grfMode, 
                            0,
                            0, 
                            out openedIStream ); 

                        if( SafeNativeCompoundFileConstants.S_OK != nativeCallErrorCode && 
                            SafeNativeCompoundFileConstants.STG_E_FILEALREADYEXISTS != nativeCallErrorCode )
                        {
                            throw new IOException(
                                SR.Get(SRID.UnableToCreateStream), 
                                new COMException(
                                    SR.Get(SRID.NamedAPIFailure, "IStorage.CreateStream"), 
                                    nativeCallErrorCode )); 
                        }
 
                        // Parent storage has changed - invalidate all standing enuemrators
                        parentStorage.InvalidateEnumerators();

                        // else - proceed with open 
                    }
 
                    if( null == openedIStream ) 
                    {
                        // If we make it here, it means the create stream call failed 
                        //  because of a STG_E_FILEALREADYEXISTS
                        //  or container is read-only
                        openedIStream = OpenStreamOnParentIStorage(
                                core.streamName, 
                            grfMode );
                    } 
                    break; 
                case FileMode.Truncate:
                    throw new ArgumentException( 
                        SR.Get(SRID.FileModeUnsupported));
                default:
                    throw new ArgumentException(
                        SR.Get(SRID.FileModeInvalid)); 
            }
 
            core.safeIStream = openedIStream; 

            Stream returnStream = 
                BuildStreamOnUnderlyingIStream( core.safeIStream, openFileAccess, this );

            core.exposedStream = returnStream;
 
            return returnStream;
        } 
 
        /***********************************************************************/
        // Internal/Private functionality 

        /// 
        /// Creates a stream with all default parameters
        ///  
        /// Stream object to manipulate data
        internal Stream Create() 
        { 
            return Create( defaultFileCreateMode, parentStorage.Root.OpenAccess, defaultDataSpace );
        } 

        /// 
        /// Creates a stream with the given create mode
        ///  
        /// Desired create mode
        /// Stream object to manipulate data 
        private Stream Create( FileMode mode ) 
        {
            return Create( mode, parentStorage.Root.OpenAccess, defaultDataSpace ); 
        }

        /// 
        /// Creates a stream encoded in the given data space 
        /// 
        /// Data space label 
        /// Stream object to manipulate data 
        internal Stream Create( string dataSpaceLabel )
        { 
            return Create( defaultFileCreateMode, parentStorage.Root.OpenAccess, dataSpaceLabel );
        }

        ///  
        /// Creates a stream with the given create and access flags
        ///  
        /// Desired create mode flag 
        /// Access flags
        /// Stream object to manipulate data 
        private Stream Create( FileMode mode, FileAccess access )
        {
            return Create( mode, access, defaultDataSpace );
        } 

        ///  
        /// Creates a stream with the given parameters 
        /// 
        /// Creation mode 
        /// Access mode
        /// Data space encoding
        /// Stream object to manipulate data
        internal Stream Create( FileMode mode, FileAccess access, string dataSpace ) 
        {
            CheckDisposedStatus(); 
 
            int grfMode = 0;
            IStream createdSafeIStream = null; 
            DataSpaceManager dataSpaceManager = null;

            // Check to make sure root container is not read-only, and that
            //  we're not pointlessly trying to create a read-only stream. 
            CreateTimeReadOnlyCheck( access );
 
            // Check to see if the data space label is valid 
            if( null != dataSpace )
            { 
                if( 0 == dataSpace.Length )
                    throw new ArgumentException(
                        SR.Get(SRID.DataSpaceLabelInvalidEmpty));
 
                dataSpaceManager = parentStorage.Root.GetDataSpaceManager();
                if( !dataSpaceManager.DataSpaceIsDefined( dataSpace ) ) 
                    throw new ArgumentException( 
                        SR.Get(SRID.DataSpaceLabelUndefined));
            } 

            openFileAccess = access;
            // becasue of the stream caching mechanism we must adjust FileAccess parameter.
            // We want to open stream with the widest access posible, in case Package was open in ReadWrite 
            // we need to open stream in ReadWrite even if user explicitly asked us to do ReadOnly/WriteOnly.
            // There is a possibility of a next request coming in as as ReadWrite request, and we would like to 
            // take advanatage of the cached stream by wrapping with appropriate access limitations. 
            if (parentStorage.Root.OpenAccess == FileAccess.ReadWrite)
            { 
                access = FileAccess.ReadWrite;
            }

            // Generate the access flags from the access parameter 
            SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess( access, ref grfMode );
 
            // Only SHARE_EXCLUSIVE for now, FileShare issue TBD 
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;
 
            CheckAccessMode(grfMode);

            // Act based on FileMode
            switch(mode) 
            {
                case FileMode.Create: 
                    // Close down any existing streams floating out there 
                    if (null != core.exposedStream)
                    { 
                        ((Stream)(core.exposedStream)).Close();
                    }
                    core.exposedStream = null;
 
                    if( null != core.safeIStream )
                    { 
                        // Release reference 
                        ((IDisposable) core.safeIStream).Dispose();
                        core.safeIStream = null; 
                    }

                    // Cleanup done, create new stream in its place.
                    grfMode |= SafeNativeCompoundFileConstants.STGM_CREATE; 
                    createdSafeIStream = CreateStreamOnParentIStorage(
                            core.streamName, 
                        grfMode ); 
                    break;
                case FileMode.CreateNew: 
                    // If we've created a CFStream, this fails because stream is already there.
                    if( null != core.safeIStream )
                        throw new IOException(
                            SR.Get(SRID.StreamAlreadyExist)); 

                    // Need to call Create API with NULL create flags 
                    createdSafeIStream = CreateStreamOnParentIStorage( 
                            core.streamName,
                        grfMode ); 
                    break;
                case FileMode.Append:   // None of these are valid in a Create
                case FileMode.Open:
                case FileMode.OpenOrCreate: 
                case FileMode.Truncate:
                default: 
                    throw new ArgumentException( 
                        SR.Get(SRID.FileModeInvalid));
            } 

            core.safeIStream = createdSafeIStream;
            // At this point we passed all previous checks and got the underlying IStream.
            //  Set our data space label to the given label, and the stream to the retrieved stream. 
            core.dataSpaceLabel = dataSpace;
            if( null != dataSpace ) 
            { 
                dataSpaceManager.CreateDataSpaceMapping(
                    new CompoundFileStreamReference( parentStorage.FullNameInternal, core.streamName ), 
                    core.dataSpaceLabel );
            }

            Stream returnStream = 
                BuildStreamOnUnderlyingIStream( core.safeIStream, openFileAccess, this );
 
            _needToGetTransformInfo = false;    // We created stream with the given dataspace setting 
                                                //  so, there is no need to get the dataspace setting
            core.exposedStream = returnStream; 

            return returnStream;
        }
 
        Stream BuildStreamOnUnderlyingIStream(
            IStream underlyingIStream, 
            FileAccess access, 
            StreamInfo parent )
        { 
            Stream rawStream = new CFStream( underlyingIStream, access, parent );

            if( null == core.dataSpaceLabel )
            { 
                // The stream is not transformed in any data space, add buffering and return
                return new BufferedStream( rawStream ); 
            } 
            else
            { 
                // Pass raw stream to data space manager to get real stream
               return parentStorage.Root.GetDataSpaceManager().CreateDataSpaceStream(
                    StreamReference, rawStream);
            } 
        }
 
        ///  
        /// A check against FileAccess.Read at create time.  It should fail if
        ///  the root container is read-only, or if we're pointlessly trying 
        ///  to create a read-only stream.
        /// 
        void CreateTimeReadOnlyCheck( FileAccess access )
        { 
            // Can't create a stream if the root container is read-only
            if( FileAccess.Read == parentStorage.Root.OpenAccess ) 
                throw new IOException( 
                    SR.Get(SRID.CanNotCreateInReadOnly));
 
            // Doesn't make sense to create a new stream just to make it read-only
            if( access == FileAccess.Read )
                throw new ArgumentException(
                    SR.Get(SRID.CanNotCreateAsReadOnly)); 
        }
 
        ///  
        /// Shortcut macro - calls the IStorage::CreateStream method on the parent
        /// storage object. 
        /// 
        IStream CreateStreamOnParentIStorage(
            string name,
            int mode ) 
        {
            IStream createdStream = null; 
            int nativeCallErrorCode = 0; 

            if( !parentStorage.Exists ) 
            {
                parentStorage.Create();
            }
 
            nativeCallErrorCode = parentStorage.SafeIStorage.CreateStream(
                name, 
                mode, 
                0,
                0, 
                out createdStream );

            if( SafeNativeCompoundFileConstants.STG_E_INVALIDFLAG == nativeCallErrorCode )
            { 
                throw new ArgumentException(
                    SR.Get(SRID.StorageFlagsUnsupported)); 
            } 
            else if ( SafeNativeCompoundFileConstants.S_OK != nativeCallErrorCode )
            { 
                throw new IOException(
                    SR.Get(SRID.UnableToCreateStream),
                    new COMException(
                        SR.Get(SRID.NamedAPIFailure, "IStorage.CreateStream"), 
                        nativeCallErrorCode ));
            } 
 
            // Parent storage has changed - invalidate all standing enuemrators
            parentStorage.InvalidateEnumerators(); 

            return createdStream;
        }
 
        /// 
        /// Shortcut macro - calls the IStorage::OpenStream method on the parent 
        /// storage object. 
        /// 
        IStream OpenStreamOnParentIStorage( 
            string name,
            int mode )
        {
            IStream openedStream = null; 
            int nativeCallErrorCode = 0;
 
            nativeCallErrorCode = parentStorage.SafeIStorage.OpenStream( 
                name,
                0, 
                mode,
                0,
                out openedStream );
 
            if( SafeNativeCompoundFileConstants.S_OK != nativeCallErrorCode )
            { 
                throw new IOException( 
                    SR.Get(SRID.UnableToOpenStream),
                    new COMException( 
                        SR.Get(SRID.NamedAPIFailure, "IStorage.OpenStream"),
                        nativeCallErrorCode ));
            }
            return openedStream; 
        }
 
        ///  
        /// Deletes the stream specified by this StreamInfo
        ///  
        internal void Delete()
        {
            CheckDisposedStatus();
 
            if( InternalExists() )
            { 
                if( null != core.safeIStream ) 
                {
                    // Close out existing stream 
                    ((IDisposable) core.safeIStream).Dispose();
                    core.safeIStream = null;
                }
                parentStorage.DestroyElement( core.streamName ); 

                // Parent storage has changed - invalidate all standing enuemrators 
                parentStorage.InvalidateEnumerators(); 
            }
            else 
            {
                // If a FileInfo is told to delete a file that does not
                //  exist, nothing happens.  We follow that example here.
            } 
        }
 
        ///  
        /// It is valid to have a StreamInfo class that points to a stream
        /// that does not (yet) exist.  However, it is impossible to perform 
        /// operations on a stream that does not exst, so the methods that
        /// require an existing stream need to be able to check if the stream
        /// exists before trying to perform its operations.
        ///  
        /// Whether "this" stream exists
        internal bool InternalExists() 
        { 
            // If we have a stream, it's pretty obvious that we exist.
            if( null != core.safeIStream ) 
                return true;

            // If parent storage does not exist, we can't possibly exist either
            if( !parentStorage.Exists ) 
                return false;
 
            // At this point we know the parent storage exists, but we don't know 
            //  if we do.  Try to open the stream.
            return SafeNativeCompoundFileConstants.S_OK == parentStorage.SafeIStorage.OpenStream( 
                core.streamName,
                0,
                SafeNativeCompoundFileConstants.STGM_READ | SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE,
                0, 
                out core.safeIStream );
        } 
 
        /// 
        /// Most of the time internal methods that want to do an internal check 
        /// to see if a stream exists is only interested in proceeding if it does.
        /// If it doesn't, abort with an exception.  This implements the little
        /// shortcut.
        ///  
        void VerifyExists()
        { 
            if( !InternalExists() ) 
            {
                throw new IOException( 
                    SR.Get(SRID.StreamNotExist));
            }
            return;
        } 

        // This fixes bug# 4947, a degenerate case of bug #5563 
        private Stream CFStreamOfClone( FileAccess access ) 
        {
            long dummy = 0; 

            IStream cloneStream = null;
            core.safeIStream.Clone( out cloneStream );
            cloneStream.Seek( 0, SafeNativeCompoundFileConstants.STREAM_SEEK_SET, out dummy ); 

            Stream returnStream = 
                BuildStreamOnUnderlyingIStream( cloneStream, access, this ); 

            core.exposedStream = returnStream; 

            return returnStream;
        }
 
        // Check whether this StreamInfo object is still valid.  If not, thrown an
        //  ObjectDisposedException. 
        internal void CheckDisposedStatus() 
        {
            // Check to see if we're still valid. 
            if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed
                throw new ObjectDisposedException(null, SR.Get(SRID.StreamInfoDisposed));
        }
 
        // Check whether this StreamInfo object is still valid.  Return result.
        internal bool StreamInfoDisposed 
        { 
            get
            { 
                // Check to see if we're still valid.
                // Null name in core signifies the core object is disposed.
                // Also check the parent storage.
                return (( null == core.streamName ) || parentStorage.StorageDisposed); 
            }
        } 
 

        // If we opened the IStream but haven't publicly exposed any Streams yet (i.e. InternalExists), 
        // check to make sure the access modes match.
        internal void CheckAccessMode(int grfMode)
        {
            // Do we have an IStream? 
            if( null != core.safeIStream )
            { 
                // Have we exposed it publicly yet? 
                if( null == core.exposedStream )
                { 
                    System.Runtime.InteropServices.ComTypes.STATSTG mySTATs;
                    core.safeIStream.Stat( out mySTATs, SafeNativeCompoundFileConstants.STATFLAG_NONAME );

                    // Do the modes match? 
                    if( grfMode != mySTATs.grfMode )
                    { 
                        // Modes don't match, close out existing stream. 
                        ((IDisposable) core.safeIStream).Dispose();
                        core.safeIStream = null; 
                    }
                }
            }
        } 

        internal CompoundFileStreamReference StreamReference 
        { 
            get
            { 
                return _streamReference;
            }
        }
 
        // Inspect the transforms applied this stream and retreive the compression and
        //  RM encryption options 
        private void EnsureTransformInformation() 
        {
            if (_needToGetTransformInfo && InternalExists()) 
            {
                _encryptionOption = EncryptionOption.None;
                _compressionOption = CompressionOption.NotCompressed;
 
                //If the StreamInfo exists we go on to check if correct transform has been
                //applied to the Stream 
 
                DataSpaceManager dsm = parentStorage.Root.GetDataSpaceManager();
 
                List transforms = dsm.GetTransformsForStreamInfo(this);

                foreach (IDataTransform dataTransform in transforms)
                { 
                    string id = dataTransform.TransformIdentifier as string;
                    if (id != null) 
                    { 
                        id = id.ToUpperInvariant();
 
                        if (String.CompareOrdinal(id,
                            RightsManagementEncryptionTransform.ClassTransformIdentifier.ToUpperInvariant()) == 0
                            &&
                            (dataTransform as RightsManagementEncryptionTransform) != null) 
                        {
                            _encryptionOption = EncryptionOption.RightsManagement; 
                        } 
                        else if (String.CompareOrdinal(id,
                            CompressionTransform.ClassTransformIdentifier.ToUpperInvariant()) == 0 
                            &&
                            (dataTransform as CompressionTransform) != null)
                        {
                            // We don't persist the compression level used during compression process 
                            // When we access the stream, all we can determine is whether it is compressed or not
                            // In all our scenarios, the level we use is Level 9 which is equivalent to Maximum 
                            _compressionOption = CompressionOption.Maximum; 
                        }
                    } 
                }
                _needToGetTransformInfo = false;
            }
        } 
    }
} 
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK