StorageRoot.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Base / System / IO / Packaging / CompoundFile / StorageRoot.cs / 1 / StorageRoot.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  The root object for manipulating the WPP container. 
//
// History: 
//  05/10/2002: RogerCh: Initial creation.
//  06/12/2002: RogerCh: Catch & translate COMException from native calls.
//  06/25/2002: RogerCh: Add a constructor to build on top of IStorage.
//  06/28/2002: RogerCh: Add a boolean to avoid infinite loops in data space 
//               manager initialization.
//  07/31/2002: RogerCh: Make obvious that we are using security suppressed interfaces. 
//  05/20/2003: RogerCh: Ported to WCP tree. 
//
//----------------------------------------------------------------------------- 

using System;
using System.IO;
using System.Runtime.InteropServices; 

using System.Windows;    // For exception string lookup table 
 
using MS.Internal;                          // for Invariant
using MS.Internal.IO.Packaging.CompoundFile; 

namespace System.IO.Packaging
{
 
/// 
/// The main container class, one instance per compound file 
///  
internal  class StorageRoot : StorageInfo
{ 
    /***********************************************************************/
    // Default values to use for the StorageRoot.Open shortcuts
    const FileMode   defaultFileMode   = FileMode.OpenOrCreate;
    const FileAccess defaultFileAccess = FileAccess.ReadWrite; 
    const FileShare  defaultFileShare  = FileShare.None;
    const int        defaultSectorSize = 512; 
    const int        stgFormatDocFile  = 5; // STGFMT_DOCFILE 

    /***********************************************************************/ 
    // Instance values

    /// 
    /// The reference to the IStorage root of this container.  This value 
    /// is initialized at Open and zeroed out at Close.  If this value is
    /// zero, it means the object has been disposed. 
    ///  
    IStorage rootIStorage;
 
    /// 
    /// Cached instance to our data space manager
    /// 
    DataSpaceManager dataSpaceManager; 

    ///  
    /// If we know we are in a read-only mode, we know not to do certain things. 
    /// 
    bool containerIsReadOnly; 

    /// 
    /// When data space manager is being initialized, sometimes it trips
    /// actions that would (in other circumstances) require checking the 
    /// data space manager.  To avoid an infinite loop, we break it by knowing
    /// when data space manager is being initialized. 
    ///  
    bool dataSpaceManagerInitializationInProgress;
 
    /***********************************************************************/
    private StorageRoot(IStorage root, bool readOnly )
        : base( root )
    { 
        rootIStorage = root;
        containerIsReadOnly = readOnly; 
        dataSpaceManagerInitializationInProgress = false; 
    }
 
    /// 
    /// The access mode available on this container
    /// 
    internal FileAccess OpenAccess 
    {
        get 
        { 
            CheckRootDisposedStatus();
            if(containerIsReadOnly) 
            {
                return FileAccess.Read;
            }
            else 
            {
                return FileAccess.ReadWrite; 
            } 
        }
    } 

    /// 
    /// Create a container StorageRoot based on the given System.IO.Stream object
    ///  
    /// The new Stream upon which to build the new StorageRoot
    /// New StorageRoot object built on the given Stream 
    internal static StorageRoot CreateOnStream( Stream baseStream ) 
    {
        if (baseStream == null) 
        {
            throw new ArgumentNullException("baseStream");
        }
 
        if( 0 == baseStream.Length )
        { 
            return CreateOnStream( baseStream, FileMode.Create ); 
        }
        else 
        {
            return CreateOnStream( baseStream, FileMode.Open );
        }
    } 

    ///  
    /// Create a container StorageRoot based on the given System.IO.Stream object 
    /// 
    /// The new Stream upon which to build the new StorageRoot 
    /// The mode (Open or Create) to use on the lock bytes
    /// New StorageRoot object built on the given Stream
    internal static StorageRoot CreateOnStream(Stream baseStream, FileMode mode)
    { 
        if( null == baseStream )
            throw new ArgumentNullException("baseStream"); 
 
        IStorage storageOnStream;
        int returnValue; 
        int openFlags = SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;

        if( baseStream.CanRead )
        { 
            if( baseStream.CanWrite )
            { 
                openFlags |= SafeNativeCompoundFileConstants.STGM_READWRITE; 
            }
            else 
            {
                openFlags |= SafeNativeCompoundFileConstants.STGM_READ;

                if( FileMode.Create == mode ) 
                    throw new ArgumentException(
                        SR.Get(SRID.CanNotCreateContainerOnReadOnlyStream)); 
            } 
        }
        else 
        {
            throw new ArgumentException(
                SR.Get(SRID.CanNotCreateStorageRootOnNonReadableStream));
        } 

        if( FileMode.Create == mode ) 
        { 
            returnValue = SafeNativeCompoundFileMethods.SafeStgCreateDocfileOnStream(
                baseStream, 
                openFlags | SafeNativeCompoundFileConstants.STGM_CREATE,
                out storageOnStream);
        }
        else if( FileMode.Open == mode ) 
        {
            returnValue = SafeNativeCompoundFileMethods.SafeStgOpenStorageOnStream( 
                baseStream, 
                openFlags,
                out storageOnStream ); 
        }
        else
        {
            throw new ArgumentException( 
                SR.Get(SRID.CreateModeMustBeCreateOrOpen));
        } 
 
        switch( (uint) returnValue )
        { 
            case SafeNativeCompoundFileConstants.S_OK:
                return StorageRoot.CreateOnIStorage(
                    storageOnStream );
 
            default:
                throw new IOException( 
                    SR.Get(SRID.UnableToCreateOnStream), 
                    new COMException(
                        SR.Get(SRID.CFAPIFailure), 
                        returnValue));
        }
    }
 
    /// Open a container, given only the path.
    /// Path to container file on local file system 
    /// StorageRoot instance representing the file 
    internal static StorageRoot Open(
        string path ) 
    {
        return Open( path, defaultFileMode, defaultFileAccess, defaultFileShare, defaultSectorSize );
    }
 
    /// Open a container, given path and open mode
    /// Path to container file on local file system 
    /// Access mode, see System.IO.FileMode in .NET SDK 
    /// StorageRoot instance representing the file
    internal static StorageRoot Open( 
        string path,
        FileMode mode )
    {
        return Open( path, mode, defaultFileAccess, defaultFileShare, defaultSectorSize ); 
    }
 
    /// Open a container, given path, open mode, and access flag 
    /// Path to container file on local file system
    /// See System.IO.FileMode in .NET SDK 
    /// See System.IO.FileAccess in .NET SDK
    /// StorageRoot instance representing the file
    internal static StorageRoot Open(
        string path, 
        FileMode mode,
        FileAccess access ) 
    { 
        return Open( path, mode, access, defaultFileShare, defaultSectorSize );
    } 

    /// Open a container, given path, open mode, access flag, and sharing settings
    /// Path to container on local file system
    /// See System.IO.FileMode in .NET SDK 
    /// See System.IO.FileAccess in .NET SDK
    /// See System.IO.FileSharing in .NET SDK 
    /// StorageRoot instance representing the file 
    internal static StorageRoot Open(
        string path, 
        FileMode mode,
        FileAccess access,
        FileShare share )
    { 
        return Open( path, mode, access, share, defaultSectorSize );
    } 
    /// Open a container given all the settings 
    /// Path to container on local file system
    /// See System.IO.FileMode in .NET SDK 
    /// See System.IO.FileAccess in .NET SDK
    /// See System.IO.FileShare in .NET SDK
    /// Compound File sector size, must be 512 or 4096
    /// StorageRoot instance representing the file 
    internal static StorageRoot Open(
        string path, 
        FileMode mode, 
        FileAccess access,
        FileShare share, 
        int sectorSize )
    {
        int  grfMode = 0;
        int  returnValue = 0; 

        // Simple path validation 
        ContainerUtilities.CheckStringAgainstNullAndEmpty( path, "Path" ); 

        Guid IID_IStorage = new Guid(0x0000000B,0x0000,0x0000,0xC0,0x00, 
                                     0x00,0x00,0x00,0x00,0x00,0x46);

        IStorage newRootStorage;
 
        ////////////////////////////////////////////////////////////////////
        // Generate STGM from FileMode 
        switch(mode) 
        {
            case FileMode.Append: 
                throw new ArgumentException(
                    SR.Get(SRID.FileModeUnsupported));
            case FileMode.Create:
                grfMode |= SafeNativeCompoundFileConstants.STGM_CREATE; 
                break;
            case FileMode.CreateNew: 
                { 
                    FileInfo existTest = new FileInfo(path);
                    if( existTest.Exists ) 
                    {
                        throw new IOException(
                            SR.Get(SRID.FileAlreadyExists));
                    } 
                }
                goto case FileMode.Create; 
            case FileMode.Open: 
                break;
            case FileMode.OpenOrCreate: 
                {
                    FileInfo existTest = new FileInfo(path);
                    if( existTest.Exists )
                    { 
                        // File exists, use open code path
                        goto case FileMode.Open; 
                    } 
                    else
                    { 
                        // File does not exist, use create code path
                        goto case FileMode.Create;
                    }
                } 
            case FileMode.Truncate:
                throw new ArgumentException( 
                    SR.Get(SRID.FileModeUnsupported)); 
            default:
                throw new ArgumentException( 
                    SR.Get(SRID.FileModeInvalid));
        }

        // Generate the access flags from the access parameter 
        SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess( access, ref grfMode );
 
        // Generate STGM from FileShare 

        // Note: the .NET SDK does not specify the proper behavior in reaction to 
        //  incompatible flags being sent in together.  Should ArgumentException be
        //  thrown?  Or do some values "trump" others?
        if( 0 != (share & FileShare.Inheritable) )
        { 
            throw new ArgumentException(
                SR.Get(SRID.FileShareUnsupported)); 
        } 
        else if( share == FileShare.None ) // FileShare.None is zero, using "&" to check causes unreachable code error
        { 
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;
        }
        else if( share == FileShare.Read )
        { 
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_DENY_WRITE;
        } 
        else if( share == FileShare.Write ) 
        {
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_DENY_READ; // Note that this makes little sense when we don't support combination of flags 
        }
        else if( share == FileShare.ReadWrite )
        {
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_DENY_NONE; 
        }
        else 
        { 
            throw new ArgumentException(
                SR.Get(SRID.FileShareInvalid)); 
        }

        if( 0 != (grfMode & SafeNativeCompoundFileConstants.STGM_CREATE))
        { 
            // STGM_CREATE set, call StgCreateStorageEx.
            returnValue = SafeNativeCompoundFileMethods.SafeStgCreateStorageEx( 
                path, 
                grfMode,
                stgFormatDocFile, 
                0,
                IntPtr.Zero,
                IntPtr.Zero,
                ref IID_IStorage, 
                out newRootStorage );
        } 
        else 
        {
            // STGM_CREATE not set, call StgOpenStorageEx. 
            returnValue = SafeNativeCompoundFileMethods.SafeStgOpenStorageEx(
                path,
                grfMode,
                stgFormatDocFile, 
                0,
                IntPtr.Zero, 
                IntPtr.Zero, 
                ref IID_IStorage,
                out newRootStorage ); 
        }

        switch( returnValue )
        { 
            case SafeNativeCompoundFileConstants.S_OK:
                return StorageRoot.CreateOnIStorage( 
                    newRootStorage ); 
            case SafeNativeCompoundFileConstants.STG_E_FILENOTFOUND:
                throw new FileNotFoundException( 
                    SR.Get(SRID.ContainerNotFound));
            case SafeNativeCompoundFileConstants.STG_E_INVALIDFLAG:
                throw new ArgumentException(
                    SR.Get(SRID.StorageFlagsUnsupported), 
                    new COMException(
                        SR.Get(SRID.CFAPIFailure), 
                        returnValue)); 
            default:
                throw new IOException( 
                    SR.Get(SRID.ContainerCanNotOpen),
                    new COMException(
                        SR.Get(SRID.CFAPIFailure),
                        returnValue)); 
        }
    } 
 
    /// 
    /// Clean up this container storage instance 
    /// 
    internal void Close()
    {
        if( null == rootIStorage ) 
            return; // Extraneous calls to Close() are ignored
 
        if( null != dataSpaceManager ) 
        {
            // Tell data space manager to flush all information as necessary 
            dataSpaceManager.Dispose();
            dataSpaceManager = null;
        }
 
        try
        { 
            // Shut down the underlying storage 
            if( !containerIsReadOnly )
                rootIStorage.Commit(0); 
        }
        finally
        {
            // We need these clean up steps to run even if there's a problem 
            //  with the commit above.
            RecursiveStorageInfoCoreRelease( core ); 
 
            rootIStorage = null;
        } 
    }

    /// 
    /// Flush the storage root. 
    /// 
    internal void Flush() 
    { 
        CheckRootDisposedStatus();
 
        // Shut down the underlying storage
        if( !containerIsReadOnly )
            rootIStorage.Commit(0);
    } 

    ///  
    /// Obtains the data space manager object for this instance of the 
    /// container.  Subsequent calls will return reference to the same
    /// object. 
    /// 
    /// Reference to the manager object
    internal DataSpaceManager GetDataSpaceManager()
    { 
        CheckRootDisposedStatus();
        if( null == dataSpaceManager ) 
        { 
            if ( dataSpaceManagerInitializationInProgress )
                return null;  // initialization in progress - abort 

            // Create new instance of data space manager
            dataSpaceManagerInitializationInProgress = true;
            dataSpaceManager = new DataSpaceManager( this ); 
            dataSpaceManagerInitializationInProgress = false;
        } 
 
        return dataSpaceManager;
    } 

    internal IStorage GetRootIStorage()
    {
        return rootIStorage; 
    }
 
    // Check whether this StorageRoot class still has its underlying storage. 
    //  If not, throw an object disposed exception.  This should be checked from
    //  every non-static container external API. 
    internal void CheckRootDisposedStatus()
    {
        if( RootDisposed )
            throw new ObjectDisposedException(null, SR.Get(SRID.StorageRootDisposed)); 
    }
 
    // Check whether this StorageRoot class still has its underlying storage. 
    internal bool RootDisposed
    { 
        get
        {
            return ( null == rootIStorage );
        } 
    }
 
    ///  
    /// This will create a container StorageRoot based on the given IStorage
    /// interface 
    /// 
    /// The new IStorage (RCW) upon which to build the new StorageRoot
    /// New StorageRoot object built on the given IStorage
    private static StorageRoot CreateOnIStorage( IStorage root ) 
    {
        // The root is created by calling unmanaged CompoundFile APIs. The return value from the call is always 
        //  checked to see if is S_OK. If it is S_OK, the root should never be null. However, just to make sure 
        //  call Invariant.Assert
        Invariant.Assert(root != null); 

        System.Runtime.InteropServices.ComTypes.STATSTG rootSTAT;
        bool readOnly;
 
        root.Stat( out rootSTAT, SafeNativeCompoundFileConstants.STATFLAG_NONAME );
 
        readOnly =( SafeNativeCompoundFileConstants.STGM_WRITE != ( rootSTAT.grfMode & SafeNativeCompoundFileConstants.STGM_WRITE ) && 
            SafeNativeCompoundFileConstants.STGM_READWRITE != (rootSTAT.grfMode & SafeNativeCompoundFileConstants.STGM_READWRITE) );
 
        return new StorageRoot( root, readOnly );
    }
}
} 


// 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: 
//  The root object for manipulating the WPP container. 
//
// History: 
//  05/10/2002: RogerCh: Initial creation.
//  06/12/2002: RogerCh: Catch & translate COMException from native calls.
//  06/25/2002: RogerCh: Add a constructor to build on top of IStorage.
//  06/28/2002: RogerCh: Add a boolean to avoid infinite loops in data space 
//               manager initialization.
//  07/31/2002: RogerCh: Make obvious that we are using security suppressed interfaces. 
//  05/20/2003: RogerCh: Ported to WCP tree. 
//
//----------------------------------------------------------------------------- 

using System;
using System.IO;
using System.Runtime.InteropServices; 

using System.Windows;    // For exception string lookup table 
 
using MS.Internal;                          // for Invariant
using MS.Internal.IO.Packaging.CompoundFile; 

namespace System.IO.Packaging
{
 
/// 
/// The main container class, one instance per compound file 
///  
internal  class StorageRoot : StorageInfo
{ 
    /***********************************************************************/
    // Default values to use for the StorageRoot.Open shortcuts
    const FileMode   defaultFileMode   = FileMode.OpenOrCreate;
    const FileAccess defaultFileAccess = FileAccess.ReadWrite; 
    const FileShare  defaultFileShare  = FileShare.None;
    const int        defaultSectorSize = 512; 
    const int        stgFormatDocFile  = 5; // STGFMT_DOCFILE 

    /***********************************************************************/ 
    // Instance values

    /// 
    /// The reference to the IStorage root of this container.  This value 
    /// is initialized at Open and zeroed out at Close.  If this value is
    /// zero, it means the object has been disposed. 
    ///  
    IStorage rootIStorage;
 
    /// 
    /// Cached instance to our data space manager
    /// 
    DataSpaceManager dataSpaceManager; 

    ///  
    /// If we know we are in a read-only mode, we know not to do certain things. 
    /// 
    bool containerIsReadOnly; 

    /// 
    /// When data space manager is being initialized, sometimes it trips
    /// actions that would (in other circumstances) require checking the 
    /// data space manager.  To avoid an infinite loop, we break it by knowing
    /// when data space manager is being initialized. 
    ///  
    bool dataSpaceManagerInitializationInProgress;
 
    /***********************************************************************/
    private StorageRoot(IStorage root, bool readOnly )
        : base( root )
    { 
        rootIStorage = root;
        containerIsReadOnly = readOnly; 
        dataSpaceManagerInitializationInProgress = false; 
    }
 
    /// 
    /// The access mode available on this container
    /// 
    internal FileAccess OpenAccess 
    {
        get 
        { 
            CheckRootDisposedStatus();
            if(containerIsReadOnly) 
            {
                return FileAccess.Read;
            }
            else 
            {
                return FileAccess.ReadWrite; 
            } 
        }
    } 

    /// 
    /// Create a container StorageRoot based on the given System.IO.Stream object
    ///  
    /// The new Stream upon which to build the new StorageRoot
    /// New StorageRoot object built on the given Stream 
    internal static StorageRoot CreateOnStream( Stream baseStream ) 
    {
        if (baseStream == null) 
        {
            throw new ArgumentNullException("baseStream");
        }
 
        if( 0 == baseStream.Length )
        { 
            return CreateOnStream( baseStream, FileMode.Create ); 
        }
        else 
        {
            return CreateOnStream( baseStream, FileMode.Open );
        }
    } 

    ///  
    /// Create a container StorageRoot based on the given System.IO.Stream object 
    /// 
    /// The new Stream upon which to build the new StorageRoot 
    /// The mode (Open or Create) to use on the lock bytes
    /// New StorageRoot object built on the given Stream
    internal static StorageRoot CreateOnStream(Stream baseStream, FileMode mode)
    { 
        if( null == baseStream )
            throw new ArgumentNullException("baseStream"); 
 
        IStorage storageOnStream;
        int returnValue; 
        int openFlags = SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;

        if( baseStream.CanRead )
        { 
            if( baseStream.CanWrite )
            { 
                openFlags |= SafeNativeCompoundFileConstants.STGM_READWRITE; 
            }
            else 
            {
                openFlags |= SafeNativeCompoundFileConstants.STGM_READ;

                if( FileMode.Create == mode ) 
                    throw new ArgumentException(
                        SR.Get(SRID.CanNotCreateContainerOnReadOnlyStream)); 
            } 
        }
        else 
        {
            throw new ArgumentException(
                SR.Get(SRID.CanNotCreateStorageRootOnNonReadableStream));
        } 

        if( FileMode.Create == mode ) 
        { 
            returnValue = SafeNativeCompoundFileMethods.SafeStgCreateDocfileOnStream(
                baseStream, 
                openFlags | SafeNativeCompoundFileConstants.STGM_CREATE,
                out storageOnStream);
        }
        else if( FileMode.Open == mode ) 
        {
            returnValue = SafeNativeCompoundFileMethods.SafeStgOpenStorageOnStream( 
                baseStream, 
                openFlags,
                out storageOnStream ); 
        }
        else
        {
            throw new ArgumentException( 
                SR.Get(SRID.CreateModeMustBeCreateOrOpen));
        } 
 
        switch( (uint) returnValue )
        { 
            case SafeNativeCompoundFileConstants.S_OK:
                return StorageRoot.CreateOnIStorage(
                    storageOnStream );
 
            default:
                throw new IOException( 
                    SR.Get(SRID.UnableToCreateOnStream), 
                    new COMException(
                        SR.Get(SRID.CFAPIFailure), 
                        returnValue));
        }
    }
 
    /// Open a container, given only the path.
    /// Path to container file on local file system 
    /// StorageRoot instance representing the file 
    internal static StorageRoot Open(
        string path ) 
    {
        return Open( path, defaultFileMode, defaultFileAccess, defaultFileShare, defaultSectorSize );
    }
 
    /// Open a container, given path and open mode
    /// Path to container file on local file system 
    /// Access mode, see System.IO.FileMode in .NET SDK 
    /// StorageRoot instance representing the file
    internal static StorageRoot Open( 
        string path,
        FileMode mode )
    {
        return Open( path, mode, defaultFileAccess, defaultFileShare, defaultSectorSize ); 
    }
 
    /// Open a container, given path, open mode, and access flag 
    /// Path to container file on local file system
    /// See System.IO.FileMode in .NET SDK 
    /// See System.IO.FileAccess in .NET SDK
    /// StorageRoot instance representing the file
    internal static StorageRoot Open(
        string path, 
        FileMode mode,
        FileAccess access ) 
    { 
        return Open( path, mode, access, defaultFileShare, defaultSectorSize );
    } 

    /// Open a container, given path, open mode, access flag, and sharing settings
    /// Path to container on local file system
    /// See System.IO.FileMode in .NET SDK 
    /// See System.IO.FileAccess in .NET SDK
    /// See System.IO.FileSharing in .NET SDK 
    /// StorageRoot instance representing the file 
    internal static StorageRoot Open(
        string path, 
        FileMode mode,
        FileAccess access,
        FileShare share )
    { 
        return Open( path, mode, access, share, defaultSectorSize );
    } 
    /// Open a container given all the settings 
    /// Path to container on local file system
    /// See System.IO.FileMode in .NET SDK 
    /// See System.IO.FileAccess in .NET SDK
    /// See System.IO.FileShare in .NET SDK
    /// Compound File sector size, must be 512 or 4096
    /// StorageRoot instance representing the file 
    internal static StorageRoot Open(
        string path, 
        FileMode mode, 
        FileAccess access,
        FileShare share, 
        int sectorSize )
    {
        int  grfMode = 0;
        int  returnValue = 0; 

        // Simple path validation 
        ContainerUtilities.CheckStringAgainstNullAndEmpty( path, "Path" ); 

        Guid IID_IStorage = new Guid(0x0000000B,0x0000,0x0000,0xC0,0x00, 
                                     0x00,0x00,0x00,0x00,0x00,0x46);

        IStorage newRootStorage;
 
        ////////////////////////////////////////////////////////////////////
        // Generate STGM from FileMode 
        switch(mode) 
        {
            case FileMode.Append: 
                throw new ArgumentException(
                    SR.Get(SRID.FileModeUnsupported));
            case FileMode.Create:
                grfMode |= SafeNativeCompoundFileConstants.STGM_CREATE; 
                break;
            case FileMode.CreateNew: 
                { 
                    FileInfo existTest = new FileInfo(path);
                    if( existTest.Exists ) 
                    {
                        throw new IOException(
                            SR.Get(SRID.FileAlreadyExists));
                    } 
                }
                goto case FileMode.Create; 
            case FileMode.Open: 
                break;
            case FileMode.OpenOrCreate: 
                {
                    FileInfo existTest = new FileInfo(path);
                    if( existTest.Exists )
                    { 
                        // File exists, use open code path
                        goto case FileMode.Open; 
                    } 
                    else
                    { 
                        // File does not exist, use create code path
                        goto case FileMode.Create;
                    }
                } 
            case FileMode.Truncate:
                throw new ArgumentException( 
                    SR.Get(SRID.FileModeUnsupported)); 
            default:
                throw new ArgumentException( 
                    SR.Get(SRID.FileModeInvalid));
        }

        // Generate the access flags from the access parameter 
        SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess( access, ref grfMode );
 
        // Generate STGM from FileShare 

        // Note: the .NET SDK does not specify the proper behavior in reaction to 
        //  incompatible flags being sent in together.  Should ArgumentException be
        //  thrown?  Or do some values "trump" others?
        if( 0 != (share & FileShare.Inheritable) )
        { 
            throw new ArgumentException(
                SR.Get(SRID.FileShareUnsupported)); 
        } 
        else if( share == FileShare.None ) // FileShare.None is zero, using "&" to check causes unreachable code error
        { 
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;
        }
        else if( share == FileShare.Read )
        { 
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_DENY_WRITE;
        } 
        else if( share == FileShare.Write ) 
        {
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_DENY_READ; // Note that this makes little sense when we don't support combination of flags 
        }
        else if( share == FileShare.ReadWrite )
        {
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_DENY_NONE; 
        }
        else 
        { 
            throw new ArgumentException(
                SR.Get(SRID.FileShareInvalid)); 
        }

        if( 0 != (grfMode & SafeNativeCompoundFileConstants.STGM_CREATE))
        { 
            // STGM_CREATE set, call StgCreateStorageEx.
            returnValue = SafeNativeCompoundFileMethods.SafeStgCreateStorageEx( 
                path, 
                grfMode,
                stgFormatDocFile, 
                0,
                IntPtr.Zero,
                IntPtr.Zero,
                ref IID_IStorage, 
                out newRootStorage );
        } 
        else 
        {
            // STGM_CREATE not set, call StgOpenStorageEx. 
            returnValue = SafeNativeCompoundFileMethods.SafeStgOpenStorageEx(
                path,
                grfMode,
                stgFormatDocFile, 
                0,
                IntPtr.Zero, 
                IntPtr.Zero, 
                ref IID_IStorage,
                out newRootStorage ); 
        }

        switch( returnValue )
        { 
            case SafeNativeCompoundFileConstants.S_OK:
                return StorageRoot.CreateOnIStorage( 
                    newRootStorage ); 
            case SafeNativeCompoundFileConstants.STG_E_FILENOTFOUND:
                throw new FileNotFoundException( 
                    SR.Get(SRID.ContainerNotFound));
            case SafeNativeCompoundFileConstants.STG_E_INVALIDFLAG:
                throw new ArgumentException(
                    SR.Get(SRID.StorageFlagsUnsupported), 
                    new COMException(
                        SR.Get(SRID.CFAPIFailure), 
                        returnValue)); 
            default:
                throw new IOException( 
                    SR.Get(SRID.ContainerCanNotOpen),
                    new COMException(
                        SR.Get(SRID.CFAPIFailure),
                        returnValue)); 
        }
    } 
 
    /// 
    /// Clean up this container storage instance 
    /// 
    internal void Close()
    {
        if( null == rootIStorage ) 
            return; // Extraneous calls to Close() are ignored
 
        if( null != dataSpaceManager ) 
        {
            // Tell data space manager to flush all information as necessary 
            dataSpaceManager.Dispose();
            dataSpaceManager = null;
        }
 
        try
        { 
            // Shut down the underlying storage 
            if( !containerIsReadOnly )
                rootIStorage.Commit(0); 
        }
        finally
        {
            // We need these clean up steps to run even if there's a problem 
            //  with the commit above.
            RecursiveStorageInfoCoreRelease( core ); 
 
            rootIStorage = null;
        } 
    }

    /// 
    /// Flush the storage root. 
    /// 
    internal void Flush() 
    { 
        CheckRootDisposedStatus();
 
        // Shut down the underlying storage
        if( !containerIsReadOnly )
            rootIStorage.Commit(0);
    } 

    ///  
    /// Obtains the data space manager object for this instance of the 
    /// container.  Subsequent calls will return reference to the same
    /// object. 
    /// 
    /// Reference to the manager object
    internal DataSpaceManager GetDataSpaceManager()
    { 
        CheckRootDisposedStatus();
        if( null == dataSpaceManager ) 
        { 
            if ( dataSpaceManagerInitializationInProgress )
                return null;  // initialization in progress - abort 

            // Create new instance of data space manager
            dataSpaceManagerInitializationInProgress = true;
            dataSpaceManager = new DataSpaceManager( this ); 
            dataSpaceManagerInitializationInProgress = false;
        } 
 
        return dataSpaceManager;
    } 

    internal IStorage GetRootIStorage()
    {
        return rootIStorage; 
    }
 
    // Check whether this StorageRoot class still has its underlying storage. 
    //  If not, throw an object disposed exception.  This should be checked from
    //  every non-static container external API. 
    internal void CheckRootDisposedStatus()
    {
        if( RootDisposed )
            throw new ObjectDisposedException(null, SR.Get(SRID.StorageRootDisposed)); 
    }
 
    // Check whether this StorageRoot class still has its underlying storage. 
    internal bool RootDisposed
    { 
        get
        {
            return ( null == rootIStorage );
        } 
    }
 
    ///  
    /// This will create a container StorageRoot based on the given IStorage
    /// interface 
    /// 
    /// The new IStorage (RCW) upon which to build the new StorageRoot
    /// New StorageRoot object built on the given IStorage
    private static StorageRoot CreateOnIStorage( IStorage root ) 
    {
        // The root is created by calling unmanaged CompoundFile APIs. The return value from the call is always 
        //  checked to see if is S_OK. If it is S_OK, the root should never be null. However, just to make sure 
        //  call Invariant.Assert
        Invariant.Assert(root != null); 

        System.Runtime.InteropServices.ComTypes.STATSTG rootSTAT;
        bool readOnly;
 
        root.Stat( out rootSTAT, SafeNativeCompoundFileConstants.STATFLAG_NONAME );
 
        readOnly =( SafeNativeCompoundFileConstants.STGM_WRITE != ( rootSTAT.grfMode & SafeNativeCompoundFileConstants.STGM_WRITE ) && 
            SafeNativeCompoundFileConstants.STGM_READWRITE != (rootSTAT.grfMode & SafeNativeCompoundFileConstants.STGM_READWRITE) );
 
        return new StorageRoot( root, readOnly );
    }
}
} 


// 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