StreamInfo.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Base / System / IO / Packaging / CompoundFile / StreamInfo.cs / 1 / 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; 

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; 

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