NativeCompoundFileAPIs.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Packaging / CompoundFile / NativeCompoundFileAPIs.cs / 1305600 / NativeCompoundFileAPIs.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  The COM and P/Invoke interop code necessary for the managed compound 
//  file layer to call the existing APIs in OLE32.DLL.
// 
//  Note that not everything is properly ported, for example the SNB type
//  used in several IStorage methods is just ignored.
//
// History: 
//  05/10/2002: RogerCh: Initial creation.
//  07/31/2002: RogerCh: Add LockBytes support, suppress unmanaged code security. 
//  05/20/2003: RogerCh: Ported to WCP tree. 
//  05/28/2003: RogerCh: Removed name checks - now handled by LongNameManager
//  02/10/2006: [....]: Separated the security suppressed interfaces and APIs 
//                  Created the wrapper class that calls unmanaged APIs
//
//-----------------------------------------------------------------------------
 
using System;
using System.IO; 
using System.Runtime.InteropServices; 
using System.Security;
using System.Windows; 

using MS.Internal.Interop;
using MS.Internal.WindowsBase;  // for SecurityHelper
 
using CultureInfo = System.Globalization.CultureInfo;
 
namespace MS.Internal.IO.Packaging.CompoundFile 
{
    //  
    //     Critical:  This class serves as a wrapper on top of several unmanaged CompoundFile
    //      interfaces and API calls. These interfaces and APIs has suppress unamanged
    //      code attribute set.
    //     It is up to this class to ensure that the only calls that can go through must 
    //     be either done in Full Trust or with CompoundFileIOPermission.
    //     This class exposes several internal APIs and interfaces built on top of classes that 
    //     demand the CompoundFileIOPermission and then call through the matching member of 
    //      the unsafe APIs and interfaces.
    //     SecurityTreatAsSafe:  Demands CompoundFileIOPermission before it makes any calls to 
    //      unmanaged APIs
    // 
    [SecurityCritical(SecurityCriticalScope.Everything), SecurityTreatAsSafe]
    internal static class SafeNativeCompoundFileMethods 
    {
        ///  
        /// Utility function to update a grfMode value based on FileAccess. 
        /// 6/12/2002: Fixes bug #4938, 4960, 5096, 4858
        ///  
        /// FileAccess we're translating
        /// Mode flag parameter to modify
        // 
        //     SecurityTreatAsSafe:  Makes NO call to security suppressed unmanaged code 
        // 
        internal static void UpdateModeFlagFromFileAccess( FileAccess access, ref int grfMode ) 
        { 
            // Supporting write-only scenarios container-wide gets tricky and it
            //  is rarely used.  Don't support it for now because of poor 
            //  cost/benefit ratio.
            if( FileAccess.Write == access )
                throw new NotSupportedException(
                    SR.Get(SRID.WriteOnlyUnsupported)); 

            // Generate STGM from FileAccess 
            // STGM_READ is 0x00, so it's "by default" 
            if( (  FileAccess.ReadWrite                == (access &  FileAccess.ReadWrite) )  ||
                ( (FileAccess.Read | FileAccess.Write) == (access & (FileAccess.Read | FileAccess.Write))) ) 
            {
                grfMode |= SafeNativeCompoundFileConstants.STGM_READWRITE;
            }
            else if( FileAccess.Write == (access & FileAccess.Write) ) 
            {
                grfMode |= SafeNativeCompoundFileConstants.STGM_WRITE; 
            } 
            else if( FileAccess.Read != (access & FileAccess.Read))
            { 
                throw new ArgumentException(
                    SR.Get(SRID.FileAccessInvalid));
            }
        } 

        internal static int SafeStgCreateDocfileOnStream( 
            Stream s, 
            int grfMode,
            out IStorage ppstgOpen 
            )
        {
            SecurityHelper.DemandCompoundFileIOPermission();
 
            Invariant.Assert(s != null, "s cannot be null");
 
            UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage; 
            UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream lockByteStream = new UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream(s);
            int result; 

            result = UnsafeNativeCompoundFileMethods.StgCreateDocfileOnILockBytes(
                (UnsafeNativeCompoundFileMethods.UnsafeNativeILockBytes) lockByteStream,
                grfMode, 
                0, // Must be zero
                out storage); 
 
            if (result == SafeNativeCompoundFileConstants.S_OK)
                ppstgOpen = new SafeIStorageImplementation(storage, lockByteStream); 
            else
            {
                ppstgOpen = null;
                lockByteStream.Dispose(); 
            }
 
            return result; 
        }
 
        internal static int SafeStgOpenStorageOnStream(
            Stream s,
            int grfMode,
            out IStorage ppstgOpen 
            )
        { 
            SecurityHelper.DemandCompoundFileIOPermission(); 

            Invariant.Assert(s != null, "s cannot be null"); 

            UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage;
            UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream lockByteStream = new UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream(s);
            int result; 

            result = UnsafeNativeCompoundFileMethods.StgOpenStorageOnILockBytes( 
                (UnsafeNativeCompoundFileMethods.UnsafeNativeILockBytes) lockByteStream, 
                null,
                grfMode, 
                new IntPtr(0), // Pointer to SNB struct, not marshalled, must be null.
                0,
                out storage);
 
            if (result == SafeNativeCompoundFileConstants.S_OK)
                ppstgOpen = new SafeIStorageImplementation(storage); 
            else 
            {
                ppstgOpen = null; 
                lockByteStream.Dispose();
            }

            return result; 

        } 
 
        internal static int SafeStgCreateStorageEx(
            string pwcsName,     //Pointer to path of compound file to create 
            int grfMode,       // Specifies the access mode for opening the storage object
            int stgfmt,        // Specifies the storage file format, 5 is DocFile
            int grfAttrs,      // Reserved; must be zero
            IntPtr pStgOptions,// Pointer to STGOPTIONS, not marshalled, must use NULL. 
            IntPtr reserved2,  // Reserved; must be null
            ref Guid riid,     // Specifies the GUID of the interface pointer 
            out IStorage ppObjectOpen       //Pointer to an interface pointer 
            )
        { 
            SecurityHelper.DemandCompoundFileIOPermission();

            UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage;
            int result; 

            result = UnsafeNativeCompoundFileMethods.StgCreateStorageEx( 
                pwcsName, 
                grfMode,
                stgfmt, 
                grfAttrs,
                pStgOptions,
                reserved2,
                ref riid, 
                out storage);
 
            if (result == SafeNativeCompoundFileConstants.S_OK) 
                ppObjectOpen = new SafeIStorageImplementation(storage);
            else 
                ppObjectOpen = null;

            return result;
        } 

        internal static int SafeStgOpenStorageEx( 
            string pwcsName,     //Pointer to path of compound file to create 
            int grfMode,       // Specifies the access mode for opening the storage object
            int stgfmt,        // Specifies the storage file format, 5 is DocFile 
            int grfAttrs,      // Reserved; must be zero
            IntPtr pStgOptions,// Pointer to STGOPTIONS, not marshalled, must use NULL.
            IntPtr reserved2,  // Reserved; must be null
            ref Guid riid,     // Specifies the GUID of the interface pointer 
            out IStorage ppObjectOpen       //Pointer to an interface pointer
            ) 
        { 
            SecurityHelper.DemandCompoundFileIOPermission();
 
            UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage;
            int result;

            result = UnsafeNativeCompoundFileMethods.StgOpenStorageEx( 
                pwcsName,
                grfMode, 
                stgfmt, 
                grfAttrs,
                pStgOptions, 
                reserved2,
                ref riid,
                out storage);
 
            if (result == SafeNativeCompoundFileConstants.S_OK)
                ppObjectOpen = new SafeIStorageImplementation(storage); 
            else 
                ppObjectOpen = null;
 
            return result;

        }
 
        // 
        //     Critical:  This method calls security suppressed unmanaged CompoundFile code. 
        //     ComoundFileIOPermission needs to be demanded to ensure that the only calls 
        //     that can go through must be either done in Full Trust or with under assertion of
        //     CompoundFileIOPermission. 
        //     SecurityTreatAsSafe:  Demands CompoundFileIOPermission before it makes any calls to
        //      unmanaged APIs
        // 
        internal static int SafePropVariantClear(ref PROPVARIANT pvar) 
        {
            SecurityHelper.DemandCompoundFileIOPermission(); 
 
            return UnsafeNativeCompoundFileMethods.PropVariantClear(ref pvar);
        } 

        private class SafeIStorageImplementation : IStorage, IPropertySetStorage, IDisposable
        {
            internal SafeIStorageImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage) 
                    : this(storage, null)
            { 
            } 

            internal SafeIStorageImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage, 
                                                        UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream lockBytesStream)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                if (storage == null)
                { 
                    throw new ArgumentNullException("storage"); 
                }
 
                _unsafeStorage = storage;
                _unsafePropertySetStorage = (UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertySetStorage) _unsafeStorage;
                _unsafeLockByteStream = lockBytesStream;
            } 

            public void Dispose() 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                Dispose(true);
                GC.SuppressFinalize(this);
            }
 
            /// 
            /// Dispose(bool) 
            ///  
            /// 
            protected virtual void Dispose(bool disposing) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                try 
                {
                    if (disposing && (_unsafeStorage != null)) 
                    { 
                        // We only need to release IStorage only not IPropertySetStorage
                        //  since it shares once instance of RCW 
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafeStorage);

                        // If the storage was originally opened on lockbyte implementation
                        //  we need to dispose it as well 
                        if (_unsafeLockByteStream != null)
                        { 
                            _unsafeLockByteStream.Dispose(); 
                        }
                    } 
                }
                finally
                {
                    _unsafeStorage = null; 
                    _unsafePropertySetStorage = null;
                    _unsafeLockByteStream = null; 
                } 
            }
 
            //
            // IStorage Implementation
            //
 
            int IStorage.CreateStream(
                string pwcsName, 
                int grfMode, 
                int reserved1,
                int reserved2, 
                out IStream ppstm )
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                UnsafeNativeCompoundFileMethods.UnsafeNativeIStream stream;
                int result; 
 
                result = _unsafeStorage.CreateStream(
                    pwcsName, 
                    grfMode,
                    reserved1,
                    reserved2,
                    out stream); 

                if (result == SafeNativeCompoundFileConstants.S_OK) 
                { 
                    ppstm = new SafeIStreamImplementation(stream);
                } 
                else
                {
                    ppstm = null;
                } 

                return result; 
            } 

            int IStorage.OpenStream( 
                string pwcsName,
                int reserved1,
                int grfMode,
                int reserved2, 
                out IStream ppstm )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIStream stream; 
                int result;

                result = _unsafeStorage.OpenStream(
                    pwcsName, 
                    reserved1,
                    grfMode, 
                    reserved2, 
                    out stream);
 
                if (result == SafeNativeCompoundFileConstants.S_OK)
                {
                    ppstm = new SafeIStreamImplementation(stream);
                } 
                else
                { 
                    ppstm = null; 
                }
 
                return result;
            }

            int IStorage.CreateStorage( 
                string pwcsName,
                int grfMode, 
                int reserved1, 
                int reserved2,
                out IStorage ppstg ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage; 
                int result;
 
                result = _unsafeStorage.CreateStorage( 
                    pwcsName,
                    grfMode, 
                    reserved1,
                    reserved2,
                    out storage);
 
                if (result == SafeNativeCompoundFileConstants.S_OK)
                { 
                    ppstg = new SafeIStorageImplementation(storage); 
                }
                else 
                {
                    ppstg = null;
                }
 
                return result;
            } 
 
            int IStorage.OpenStorage(
                string pwcsName, 
                IStorage pstgPriority,
                int grfMode,
                IntPtr snbExclude,  // Not properly translated, but must be NULL anyway
                int reserved, 
                out IStorage ppstg )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage; 
                int result;

                result = _unsafeStorage.OpenStorage(
                    pwcsName, 
                    pstgPriority == null ? null : ((SafeIStorageImplementation) pstgPriority)._unsafeStorage,
                    grfMode, 
                    snbExclude, 
                    reserved,
                    out storage); 

                if (result == SafeNativeCompoundFileConstants.S_OK)
                {
                    ppstg = new SafeIStorageImplementation(storage); 
                }
                else 
                { 
                    ppstg = null;
                } 

                return result;
            }
 
            void IStorage.CopyTo(
                int ciidExclude, 
                Guid[] rgiidExclude, 
                IntPtr snbExclude,  // Not properly translated, use NULL to avoid `blow-up
                IStorage ppstg ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                Invariant.Assert(ppstg != null, "ppstg cannot be null"); 

                _unsafeStorage.CopyTo( 
                    ciidExclude, 
                    rgiidExclude,
                    snbExclude, 
                    ((SafeIStorageImplementation) ppstg)._unsafeStorage);
            }

            void IStorage.MoveElementTo( 
                string pwcsName,
                IStorage pstgDest, 
                string pwcsNewName, 
                int grfFlags )
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                Invariant.Assert(pstgDest != null, "pstgDest cannot be null");
 
                _unsafeStorage.MoveElementTo(
                    pwcsName, 
                    ((SafeIStorageImplementation) pstgDest)._unsafeStorage, 
                    pwcsNewName,
                    grfFlags); 
            }

            void IStorage.Commit(
                int grfCommitFlags ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 
 
                _unsafeStorage.Commit(
                    grfCommitFlags); 
            }

            void IStorage.Revert()
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafeStorage.Revert(); 
            }
 
            void IStorage.EnumElements(
                int reserved1,
                IntPtr reserved2,
                int reserved3, 
                out IEnumSTATSTG ppEnum )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATSTG enumSTATSTG; 

                _unsafeStorage.EnumElements(
                    reserved1,
                    reserved2, 
                    reserved3,
                    out enumSTATSTG); 
 
                if (enumSTATSTG != null)
                    ppEnum = new SafeIEnumSTATSTGImplementation(enumSTATSTG); 
                else
                    ppEnum = null;
            }
 
            void IStorage.DestroyElement(
                string pwcsName ) 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafeStorage.DestroyElement(
                    pwcsName);
            }
 
            void IStorage.RenameElement(
                string pwcsOldName, 
                string pwcsNewName ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeStorage.RenameElement(
                    pwcsOldName,
                    pwcsNewName); 
            }
 
            void IStorage.SetElementTimes( 
                string pwcsName,
                System.Runtime.InteropServices.ComTypes.FILETIME pctime, 
                System.Runtime.InteropServices.ComTypes.FILETIME patime,
                System.Runtime.InteropServices.ComTypes.FILETIME pmtime )
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeStorage.SetElementTimes( 
                    pwcsName, 
                    pctime,
                    patime, 
                    pmtime);
            }

            void IStorage.SetClass( 
                ref Guid clsid ) // Hopefully "ref" is how I tell it to use a pointer
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeStorage.SetClass( 
                    ref clsid );
            }

            void IStorage.SetStateBits( 
                int grfStateBits,
                int grfMask ) 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafeStorage.SetStateBits(
                    grfStateBits,
                    grfMask);
            } 

            void IStorage.Stat( 
                out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, 
                int grfStatFlag )
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                _unsafeStorage.Stat(
                    out pstatstg, 
                    grfStatFlag);
            } 
 
            void IPropertySetStorage.Create(
                    ref Guid rfmtid, 
                    ref Guid pclsid,
                    UInt32 grfFlags,
                    UInt32 grfMode,
                    out IPropertyStorage ppprstg 
                    )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertyStorage propertyStorage; 

                _unsafePropertySetStorage.Create(
                    ref rfmtid,
                    ref pclsid, 
                    grfFlags,
                    grfMode, 
                    out propertyStorage 
                    );
 
                if (propertyStorage != null)
                    ppprstg = new SafeIPropertyStorageImplementation(propertyStorage);
                else
                    ppprstg = null; 
            }
 
            int IPropertySetStorage.Open( 
                    ref Guid rfmtid,
                    UInt32 grfMode, 
                    out IPropertyStorage ppprstg
                    )
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertyStorage propertyStorage; 
 
                int hr = _unsafePropertySetStorage.Open(
                    ref rfmtid, 
                    grfMode,
                    out propertyStorage
                    );
 
                if (propertyStorage != null)
                    ppprstg = new SafeIPropertyStorageImplementation(propertyStorage); 
                else 
                    ppprstg = null;
 
                return hr;
            }

            void IPropertySetStorage.Delete( 
                    ref Guid rfmtid
                    ) 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafePropertySetStorage.Delete(
                    ref rfmtid
                    );
            } 

            void IPropertySetStorage.Enum( 
                    out IEnumSTATPROPSETSTG ppenum 
                    )
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSETSTG enumSTATPROPSETSTG;
 
                _unsafePropertySetStorage.Enum(
                    out enumSTATPROPSETSTG 
                    ); 

                if (enumSTATPROPSETSTG != null) 
                    ppenum = new SafeIEnumSTATPROPSETSTGImplementation(enumSTATPROPSETSTG);
                else
                    ppenum = null;
            } 

            private UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertySetStorage _unsafePropertySetStorage; 
            private UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage _unsafeStorage; 
            private UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream _unsafeLockByteStream;
        } 

        private class SafeIStreamImplementation : IStream, IDisposable
        {
            internal SafeIStreamImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIStream stream) 
            {
                _unsafeStream = stream; 
            } 

            public void Dispose() 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                Dispose(true); 
                GC.SuppressFinalize(this);
            } 
 
            protected virtual void Dispose(bool disposing)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                try
                { 
                    if (disposing && (_unsafeStream != null))
                    { 
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafeStream); 
                    }
                } 
                finally
                {
                    _unsafeStream = null;
                } 
            }
 
            // 
            // IStream Implementation
            // 
            void IStream.Read(Byte[] pv, int cb, out int pcbRead)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                if (cb < 0)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "cb", cb.ToString(CultureInfo.InvariantCulture))); 
                }
 
                _unsafeStream.Read(pv, cb, out pcbRead);
            }

            void IStream.Write(Byte[] pv, int cb, out int pcbWritten) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 
 
                if (cb < 0)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "cb", cb.ToString(CultureInfo.InvariantCulture)));
                }

                _unsafeStream.Write(pv, cb, out pcbWritten); 
            }
 
 
            // IStream portion
            void IStream.Seek(long dlibMove, int dwOrigin, out long plibNewPosition) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                if (dwOrigin < 0) 
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "dwOrigin", dwOrigin.ToString(CultureInfo.InvariantCulture))); 
                } 

                if (dlibMove < 0 && dwOrigin == SafeNativeCompoundFileConstants.STREAM_SEEK_SET) 
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "dlibMove", dlibMove.ToString(CultureInfo.InvariantCulture)));
                }
 
                _unsafeStream.Seek(dlibMove, dwOrigin, out plibNewPosition);
            } 
 
            void IStream.SetSize(long libNewSize)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                if (libNewSize < 0)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "libNewSize", libNewSize.ToString(CultureInfo.InvariantCulture)));
                } 
 
                _unsafeStream.SetSize(libNewSize);
            } 

            void IStream.CopyTo(IStream pstm, long cb, out long pcbRead, out long pcbWritten)
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                Invariant.Assert(pstm != null, "pstm cannot be null"); 
 
                if (cb < 0)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "cb", cb.ToString(CultureInfo.InvariantCulture)));
                }

                _unsafeStream.CopyTo(((SafeIStreamImplementation) pstm)._unsafeStream, cb, out pcbRead, out pcbWritten); 
            }
 
            void IStream.Commit(int grfCommitFlags) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeStream.Commit(grfCommitFlags);
            }
 
            void IStream.Revert()
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeStream.Revert(); 
            }

            void IStream.LockRegion(long libOffset, long cb, int dwLockType)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                if (libOffset < 0) 
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "libOffset", libOffset.ToString(CultureInfo.InvariantCulture))); 
                }
                if (cb < 0)
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "cb", cb.ToString(CultureInfo.InvariantCulture))); 
                }
 
                _unsafeStream.LockRegion(libOffset, cb, dwLockType); 
            }
 
            void IStream.UnlockRegion(long libOffset, long cb, int dwLockType)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                if (libOffset < 0)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "libOffset", libOffset.ToString(CultureInfo.InvariantCulture))); 
                }
                if (cb < 0) 
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "cb", cb.ToString(CultureInfo.InvariantCulture)));
                }
 
                _unsafeStream.UnlockRegion(libOffset, cb, dwLockType);
            } 
 
            void IStream.Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                _unsafeStream.Stat(out pstatstg, grfStatFlag);
            } 

            void IStream.Clone(out IStream ppstm) 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                UnsafeNativeCompoundFileMethods.UnsafeNativeIStream stream;

                _unsafeStream.Clone(out stream);
 
                if (stream != null)
                { 
                    ppstm = new SafeIStreamImplementation(stream); 
                }
                else 
                {
                    ppstm = null;
                }
            } 

            private UnsafeNativeCompoundFileMethods.UnsafeNativeIStream _unsafeStream; 
        } 

        private class SafeIEnumSTATPROPSETSTGImplementation : IEnumSTATPROPSETSTG, IDisposable 
        {
            internal SafeIEnumSTATPROPSETSTGImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSETSTG enumSTATPROPSETSTG)
            {
                _unsafeEnumSTATPROPSETSTG = enumSTATPROPSETSTG; 
            }
 
            public void Dispose() 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                Dispose(true);
                GC.SuppressFinalize(this);
            } 

            ///  
            /// Dispose(bool) 
            /// 
            ///  
            protected virtual void Dispose(bool disposing)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                try
                { 
                    if (disposing && (_unsafeEnumSTATPROPSETSTG != null)) 
                    {
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafeEnumSTATPROPSETSTG); 
                    }
                }
                finally
                { 
                    _unsafeEnumSTATPROPSETSTG = null;
                } 
            } 

            // 
            // The caller must allocate an array of celt STATPROPSETSTG structures
            // to receive the results.
            //
            // This method is PreserveSig because it can return a non-0 success 
            // code; S_FALSE => fewer than celt elements were returned.
            // 
            int 
            IEnumSTATPROPSETSTG.Next(
                UInt32 celt, 
                STATPROPSETSTG rgelt,
                out UInt32 pceltFetched
                )
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                return _unsafeEnumSTATPROPSETSTG.Next( 
                    celt,
                    rgelt, 
                    out pceltFetched
                    );
            }
 
            void IEnumSTATPROPSETSTG.Skip(UInt32 celt)
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeEnumSTATPROPSETSTG.Skip(celt); 
            }

            void IEnumSTATPROPSETSTG.Reset()
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafeEnumSTATPROPSETSTG.Reset(); 
            }
 
            void IEnumSTATPROPSETSTG.Clone(out IEnumSTATPROPSETSTG ppenum)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSETSTG enumSTATPROPSETSTG;
 
                _unsafeEnumSTATPROPSETSTG.Clone(out enumSTATPROPSETSTG); 

                if (enumSTATPROPSETSTG != null) 
                    ppenum = new SafeIEnumSTATPROPSETSTGImplementation(enumSTATPROPSETSTG);
                else
                    ppenum = null;
            } 

            private UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSETSTG _unsafeEnumSTATPROPSETSTG; 
        } 

        private class SafeIPropertyStorageImplementation : IPropertyStorage, IDisposable 
        {
            internal SafeIPropertyStorageImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertyStorage propertyStorage)
            {
                _unsafePropertyStorage = propertyStorage; 
            }
 
            public void Dispose() 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                Dispose(true);
                GC.SuppressFinalize(this);
            } 

            ///  
            /// Dispose(bool) 
            /// 
            ///  
            protected virtual void Dispose(bool disposing)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                try
                { 
                    if (disposing && (_unsafePropertyStorage != null)) 
                    {
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafePropertyStorage); 
                    }
                }
                finally
                { 
                    _unsafePropertyStorage = null;
                } 
            } 

            // 
            // We preserve the HRESULT on this method because we need to distinguish
            // between S_OK (we got the properties we asked for) and S_FALSE (none of
            // the properties exist).
            // 
            int IPropertyStorage.ReadMultiple(
                UInt32 cpspec, 
                PROPSPEC[] rgpspec, 
                PROPVARIANT[] rgpropvar
                ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                return _unsafePropertyStorage.ReadMultiple( 
                    cpspec,
                    rgpspec, 
                    rgpropvar 
                    );
            } 

            void IPropertyStorage.WriteMultiple(
                UInt32 cpspec,
                PROPSPEC[] rgpspec, 
                PROPVARIANT[] rgpropvar,
                uint propidNameFirst 
                ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.WriteMultiple(
                    cpspec,
                    rgpspec, 
                    rgpropvar,
                    propidNameFirst 
                    ); 
            }
 
            void IPropertyStorage.DeleteMultiple(
                UInt32 cpspec,
                PROPSPEC[] rgpspec
                ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 
 
                _unsafePropertyStorage.DeleteMultiple(
                    cpspec, 
                    rgpspec
                    );
            }
 
            void IPropertyStorage.ReadPropertyNames(
                UInt32 cpropid, 
                UInt32[] rgpropid, 
                string[] rglpwstrName
                ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                _unsafePropertyStorage.ReadPropertyNames( 
                    cpropid,
                    rgpropid, 
                    rglpwstrName 
                    );
            } 

            void IPropertyStorage.WritePropertyNames(
                UInt32 cpropid,
                UInt32[] rgpropid, 
                string[] rglpwstrName
                ) 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafePropertyStorage.WritePropertyNames(
                    cpropid,
                    rgpropid,
                    rglpwstrName 
                    );
            } 
 
            void IPropertyStorage.DeletePropertyNames(
                UInt32 cpropid, 
                UInt32[] rgpropid
                )
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.DeletePropertyNames( 
                    cpropid, 
                    rgpropid
                    ); 
            }

            void IPropertyStorage.Commit(
                UInt32 grfCommitFlags 
                )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.Commit( 
                    grfCommitFlags
                    );
            }
 
            void IPropertyStorage.Revert()
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.Revert(); 
            }

            void IPropertyStorage.Enum(
                out IEnumSTATPROPSTG ppenum 
                )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

#if Using_SafeIPropertyStorageImplementation_Enum 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSTG unsafeEnumSTATPROPSTG;

                _unsafePropertyStorage.Enum( 
                    out unsafeEnumSTATPROPSTG
                    ); 
 
                if (unsafeEnumSTATPROPSTG != null)
                    ppenum = new SafeIEnumSTATPROPSTGImplementation(unsafeEnumSTATPROPSTG); 
                else
#endif
                    ppenum = null;
            } 

            void IPropertyStorage.SetTimes( 
                ref System.Runtime.InteropServices.ComTypes.FILETIME pctime, 
                ref System.Runtime.InteropServices.ComTypes.FILETIME patime,
                ref System.Runtime.InteropServices.ComTypes.FILETIME pmtime 
                )
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafePropertyStorage.SetTimes(
                    ref pctime, 
                    ref patime, 
                    ref pmtime
                    ); 
            }

            void IPropertyStorage.SetClass(
                ref Guid clsid 
                )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.SetClass( 
                    ref clsid
                    );
            }
 
            void IPropertyStorage.Stat(
                out STATPROPSETSTG pstatpsstg 
                ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.Stat(
                    out pstatpsstg
                    ); 
            }
 
            private UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertyStorage _unsafePropertyStorage; 
        }
 
#if Using_SafeIPropertyStorageImplementation_Enum
        private class SafeIEnumSTATPROPSTGImplementation : IEnumSTATPROPSTG
        {
            internal SafeIEnumSTATPROPSTGImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSTG enumSTATPROPSTG) 
            {
                _unsafeEnumSTATPROPSTG= enumSTATPROPSTG; 
            } 

            public void Dispose() 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                Dispose(true); 
                GC.SuppressFinalize(this);
            } 
 
            /// 
            /// Dispose(bool) 
            /// 
            /// 
            protected virtual void Dispose(bool disposing)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                try 
                {
                    if (disposing && (_unsafeEnumSTATPROPSTG != null)) 
                    {
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafeEnumSTATPROPSTG);
                    }
                } 
                finally
                { 
                    _unsafeEnumSTATPROPSTG = null; 
                }
            } 

            //
            // The caller must allocate an array of celt STATPROPSTG structures
            // to receive the results. 
            //
            // This method is PreserveSig because it can return a non-0 success 
            // code; S_FALSE => fewer than celt elements were returned. 
            //
            int 
            IEnumSTATPROPSTG.Next(
                UInt32 celt,
                STATPROPSTG rgelt,
                out UInt32 pceltFetched 
                )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                return _unsafeEnumSTATPROPSTG.Next( 
                    celt,
                    rgelt,
                    out pceltFetched
                    ); 
            }
 
            void IEnumSTATPROPSTG.Skip(UInt32 celt) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeEnumSTATPROPSTG.Skip(celt);
            }
 
            void IEnumSTATPROPSTG.Reset()
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeEnumSTATPROPSTG.Reset(); 
            }

            void IEnumSTATPROPSTG.Clone(out IEnumSTATPROPSTG ppenum)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSTG enumSTATPROPSTG; 

                _unsafeEnumSTATPROPSTG.Clone(out enumSTATPROPSTG); 

                if (enumSTATPROPSTG != null)
                    ppenum = new SafeIEnumSTATPROPSTGImplementation(enumSTATPROPSTG);
                else 
                    ppenum = null;
            } 
 
            private UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSTG _unsafeEnumSTATPROPSTG;
        } 
#endif

        private class SafeIEnumSTATSTGImplementation : IEnumSTATSTG, IDisposable
        { 
            internal SafeIEnumSTATSTGImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATSTG enumSTATSTG)
            { 
                _unsafeEnumSTATSTG = enumSTATSTG; 
            }
 
            public void Dispose()
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                Dispose(true);
                GC.SuppressFinalize(this); 
            } 

            ///  
            /// Dispose(bool)
            /// 
            /// 
            protected virtual void Dispose(bool disposing) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 
 
                try
                { 
                    if (disposing && (_unsafeEnumSTATSTG != null))
                    {
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafeEnumSTATSTG);
                    } 
                }
                finally 
                { 
                    _unsafeEnumSTATSTG = null;
                } 
            }

            void IEnumSTATSTG.Next(
                UInt32 celt, 
                out System.Runtime.InteropServices.ComTypes.STATSTG rgelt, // This should really be array, but we're OK if we stick with one item at a time.
                    // Because marshalling an array of structs that have pointers to strings are troublesome. 
                out UInt32 pceltFetched ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                if (celt != 1)
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "celt", celt.ToString(CultureInfo.InvariantCulture))); 
                }
 
                _unsafeEnumSTATSTG.Next( 
                    celt,
                    out rgelt, 
                    out pceltFetched );
            }

            void IEnumSTATSTG.Skip( 
                UInt32 celt )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeEnumSTATSTG.Skip( 
                    celt );
            }

            void IEnumSTATSTG.Reset() 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 
 
                _unsafeEnumSTATSTG.Reset();
            } 

            void IEnumSTATSTG.Clone(
                out IEnumSTATSTG ppenum )
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATSTG enumSTATSTG; 

                _unsafeEnumSTATSTG.Clone( 
                    out enumSTATSTG );

                if (enumSTATSTG != null)
                    ppenum = new SafeIEnumSTATSTGImplementation(enumSTATSTG); 
                else
                    ppenum = null; 
            } 

            private UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATSTG _unsafeEnumSTATSTG; 
        }

    }
} 


// 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 COM and P/Invoke interop code necessary for the managed compound 
//  file layer to call the existing APIs in OLE32.DLL.
// 
//  Note that not everything is properly ported, for example the SNB type
//  used in several IStorage methods is just ignored.
//
// History: 
//  05/10/2002: RogerCh: Initial creation.
//  07/31/2002: RogerCh: Add LockBytes support, suppress unmanaged code security. 
//  05/20/2003: RogerCh: Ported to WCP tree. 
//  05/28/2003: RogerCh: Removed name checks - now handled by LongNameManager
//  02/10/2006: [....]: Separated the security suppressed interfaces and APIs 
//                  Created the wrapper class that calls unmanaged APIs
//
//-----------------------------------------------------------------------------
 
using System;
using System.IO; 
using System.Runtime.InteropServices; 
using System.Security;
using System.Windows; 

using MS.Internal.Interop;
using MS.Internal.WindowsBase;  // for SecurityHelper
 
using CultureInfo = System.Globalization.CultureInfo;
 
namespace MS.Internal.IO.Packaging.CompoundFile 
{
    //  
    //     Critical:  This class serves as a wrapper on top of several unmanaged CompoundFile
    //      interfaces and API calls. These interfaces and APIs has suppress unamanged
    //      code attribute set.
    //     It is up to this class to ensure that the only calls that can go through must 
    //     be either done in Full Trust or with CompoundFileIOPermission.
    //     This class exposes several internal APIs and interfaces built on top of classes that 
    //     demand the CompoundFileIOPermission and then call through the matching member of 
    //      the unsafe APIs and interfaces.
    //     SecurityTreatAsSafe:  Demands CompoundFileIOPermission before it makes any calls to 
    //      unmanaged APIs
    // 
    [SecurityCritical(SecurityCriticalScope.Everything), SecurityTreatAsSafe]
    internal static class SafeNativeCompoundFileMethods 
    {
        ///  
        /// Utility function to update a grfMode value based on FileAccess. 
        /// 6/12/2002: Fixes bug #4938, 4960, 5096, 4858
        ///  
        /// FileAccess we're translating
        /// Mode flag parameter to modify
        // 
        //     SecurityTreatAsSafe:  Makes NO call to security suppressed unmanaged code 
        // 
        internal static void UpdateModeFlagFromFileAccess( FileAccess access, ref int grfMode ) 
        { 
            // Supporting write-only scenarios container-wide gets tricky and it
            //  is rarely used.  Don't support it for now because of poor 
            //  cost/benefit ratio.
            if( FileAccess.Write == access )
                throw new NotSupportedException(
                    SR.Get(SRID.WriteOnlyUnsupported)); 

            // Generate STGM from FileAccess 
            // STGM_READ is 0x00, so it's "by default" 
            if( (  FileAccess.ReadWrite                == (access &  FileAccess.ReadWrite) )  ||
                ( (FileAccess.Read | FileAccess.Write) == (access & (FileAccess.Read | FileAccess.Write))) ) 
            {
                grfMode |= SafeNativeCompoundFileConstants.STGM_READWRITE;
            }
            else if( FileAccess.Write == (access & FileAccess.Write) ) 
            {
                grfMode |= SafeNativeCompoundFileConstants.STGM_WRITE; 
            } 
            else if( FileAccess.Read != (access & FileAccess.Read))
            { 
                throw new ArgumentException(
                    SR.Get(SRID.FileAccessInvalid));
            }
        } 

        internal static int SafeStgCreateDocfileOnStream( 
            Stream s, 
            int grfMode,
            out IStorage ppstgOpen 
            )
        {
            SecurityHelper.DemandCompoundFileIOPermission();
 
            Invariant.Assert(s != null, "s cannot be null");
 
            UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage; 
            UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream lockByteStream = new UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream(s);
            int result; 

            result = UnsafeNativeCompoundFileMethods.StgCreateDocfileOnILockBytes(
                (UnsafeNativeCompoundFileMethods.UnsafeNativeILockBytes) lockByteStream,
                grfMode, 
                0, // Must be zero
                out storage); 
 
            if (result == SafeNativeCompoundFileConstants.S_OK)
                ppstgOpen = new SafeIStorageImplementation(storage, lockByteStream); 
            else
            {
                ppstgOpen = null;
                lockByteStream.Dispose(); 
            }
 
            return result; 
        }
 
        internal static int SafeStgOpenStorageOnStream(
            Stream s,
            int grfMode,
            out IStorage ppstgOpen 
            )
        { 
            SecurityHelper.DemandCompoundFileIOPermission(); 

            Invariant.Assert(s != null, "s cannot be null"); 

            UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage;
            UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream lockByteStream = new UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream(s);
            int result; 

            result = UnsafeNativeCompoundFileMethods.StgOpenStorageOnILockBytes( 
                (UnsafeNativeCompoundFileMethods.UnsafeNativeILockBytes) lockByteStream, 
                null,
                grfMode, 
                new IntPtr(0), // Pointer to SNB struct, not marshalled, must be null.
                0,
                out storage);
 
            if (result == SafeNativeCompoundFileConstants.S_OK)
                ppstgOpen = new SafeIStorageImplementation(storage); 
            else 
            {
                ppstgOpen = null; 
                lockByteStream.Dispose();
            }

            return result; 

        } 
 
        internal static int SafeStgCreateStorageEx(
            string pwcsName,     //Pointer to path of compound file to create 
            int grfMode,       // Specifies the access mode for opening the storage object
            int stgfmt,        // Specifies the storage file format, 5 is DocFile
            int grfAttrs,      // Reserved; must be zero
            IntPtr pStgOptions,// Pointer to STGOPTIONS, not marshalled, must use NULL. 
            IntPtr reserved2,  // Reserved; must be null
            ref Guid riid,     // Specifies the GUID of the interface pointer 
            out IStorage ppObjectOpen       //Pointer to an interface pointer 
            )
        { 
            SecurityHelper.DemandCompoundFileIOPermission();

            UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage;
            int result; 

            result = UnsafeNativeCompoundFileMethods.StgCreateStorageEx( 
                pwcsName, 
                grfMode,
                stgfmt, 
                grfAttrs,
                pStgOptions,
                reserved2,
                ref riid, 
                out storage);
 
            if (result == SafeNativeCompoundFileConstants.S_OK) 
                ppObjectOpen = new SafeIStorageImplementation(storage);
            else 
                ppObjectOpen = null;

            return result;
        } 

        internal static int SafeStgOpenStorageEx( 
            string pwcsName,     //Pointer to path of compound file to create 
            int grfMode,       // Specifies the access mode for opening the storage object
            int stgfmt,        // Specifies the storage file format, 5 is DocFile 
            int grfAttrs,      // Reserved; must be zero
            IntPtr pStgOptions,// Pointer to STGOPTIONS, not marshalled, must use NULL.
            IntPtr reserved2,  // Reserved; must be null
            ref Guid riid,     // Specifies the GUID of the interface pointer 
            out IStorage ppObjectOpen       //Pointer to an interface pointer
            ) 
        { 
            SecurityHelper.DemandCompoundFileIOPermission();
 
            UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage;
            int result;

            result = UnsafeNativeCompoundFileMethods.StgOpenStorageEx( 
                pwcsName,
                grfMode, 
                stgfmt, 
                grfAttrs,
                pStgOptions, 
                reserved2,
                ref riid,
                out storage);
 
            if (result == SafeNativeCompoundFileConstants.S_OK)
                ppObjectOpen = new SafeIStorageImplementation(storage); 
            else 
                ppObjectOpen = null;
 
            return result;

        }
 
        // 
        //     Critical:  This method calls security suppressed unmanaged CompoundFile code. 
        //     ComoundFileIOPermission needs to be demanded to ensure that the only calls 
        //     that can go through must be either done in Full Trust or with under assertion of
        //     CompoundFileIOPermission. 
        //     SecurityTreatAsSafe:  Demands CompoundFileIOPermission before it makes any calls to
        //      unmanaged APIs
        // 
        internal static int SafePropVariantClear(ref PROPVARIANT pvar) 
        {
            SecurityHelper.DemandCompoundFileIOPermission(); 
 
            return UnsafeNativeCompoundFileMethods.PropVariantClear(ref pvar);
        } 

        private class SafeIStorageImplementation : IStorage, IPropertySetStorage, IDisposable
        {
            internal SafeIStorageImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage) 
                    : this(storage, null)
            { 
            } 

            internal SafeIStorageImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage, 
                                                        UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream lockBytesStream)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                if (storage == null)
                { 
                    throw new ArgumentNullException("storage"); 
                }
 
                _unsafeStorage = storage;
                _unsafePropertySetStorage = (UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertySetStorage) _unsafeStorage;
                _unsafeLockByteStream = lockBytesStream;
            } 

            public void Dispose() 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                Dispose(true);
                GC.SuppressFinalize(this);
            }
 
            /// 
            /// Dispose(bool) 
            ///  
            /// 
            protected virtual void Dispose(bool disposing) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                try 
                {
                    if (disposing && (_unsafeStorage != null)) 
                    { 
                        // We only need to release IStorage only not IPropertySetStorage
                        //  since it shares once instance of RCW 
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafeStorage);

                        // If the storage was originally opened on lockbyte implementation
                        //  we need to dispose it as well 
                        if (_unsafeLockByteStream != null)
                        { 
                            _unsafeLockByteStream.Dispose(); 
                        }
                    } 
                }
                finally
                {
                    _unsafeStorage = null; 
                    _unsafePropertySetStorage = null;
                    _unsafeLockByteStream = null; 
                } 
            }
 
            //
            // IStorage Implementation
            //
 
            int IStorage.CreateStream(
                string pwcsName, 
                int grfMode, 
                int reserved1,
                int reserved2, 
                out IStream ppstm )
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                UnsafeNativeCompoundFileMethods.UnsafeNativeIStream stream;
                int result; 
 
                result = _unsafeStorage.CreateStream(
                    pwcsName, 
                    grfMode,
                    reserved1,
                    reserved2,
                    out stream); 

                if (result == SafeNativeCompoundFileConstants.S_OK) 
                { 
                    ppstm = new SafeIStreamImplementation(stream);
                } 
                else
                {
                    ppstm = null;
                } 

                return result; 
            } 

            int IStorage.OpenStream( 
                string pwcsName,
                int reserved1,
                int grfMode,
                int reserved2, 
                out IStream ppstm )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIStream stream; 
                int result;

                result = _unsafeStorage.OpenStream(
                    pwcsName, 
                    reserved1,
                    grfMode, 
                    reserved2, 
                    out stream);
 
                if (result == SafeNativeCompoundFileConstants.S_OK)
                {
                    ppstm = new SafeIStreamImplementation(stream);
                } 
                else
                { 
                    ppstm = null; 
                }
 
                return result;
            }

            int IStorage.CreateStorage( 
                string pwcsName,
                int grfMode, 
                int reserved1, 
                int reserved2,
                out IStorage ppstg ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage; 
                int result;
 
                result = _unsafeStorage.CreateStorage( 
                    pwcsName,
                    grfMode, 
                    reserved1,
                    reserved2,
                    out storage);
 
                if (result == SafeNativeCompoundFileConstants.S_OK)
                { 
                    ppstg = new SafeIStorageImplementation(storage); 
                }
                else 
                {
                    ppstg = null;
                }
 
                return result;
            } 
 
            int IStorage.OpenStorage(
                string pwcsName, 
                IStorage pstgPriority,
                int grfMode,
                IntPtr snbExclude,  // Not properly translated, but must be NULL anyway
                int reserved, 
                out IStorage ppstg )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage storage; 
                int result;

                result = _unsafeStorage.OpenStorage(
                    pwcsName, 
                    pstgPriority == null ? null : ((SafeIStorageImplementation) pstgPriority)._unsafeStorage,
                    grfMode, 
                    snbExclude, 
                    reserved,
                    out storage); 

                if (result == SafeNativeCompoundFileConstants.S_OK)
                {
                    ppstg = new SafeIStorageImplementation(storage); 
                }
                else 
                { 
                    ppstg = null;
                } 

                return result;
            }
 
            void IStorage.CopyTo(
                int ciidExclude, 
                Guid[] rgiidExclude, 
                IntPtr snbExclude,  // Not properly translated, use NULL to avoid `blow-up
                IStorage ppstg ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                Invariant.Assert(ppstg != null, "ppstg cannot be null"); 

                _unsafeStorage.CopyTo( 
                    ciidExclude, 
                    rgiidExclude,
                    snbExclude, 
                    ((SafeIStorageImplementation) ppstg)._unsafeStorage);
            }

            void IStorage.MoveElementTo( 
                string pwcsName,
                IStorage pstgDest, 
                string pwcsNewName, 
                int grfFlags )
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                Invariant.Assert(pstgDest != null, "pstgDest cannot be null");
 
                _unsafeStorage.MoveElementTo(
                    pwcsName, 
                    ((SafeIStorageImplementation) pstgDest)._unsafeStorage, 
                    pwcsNewName,
                    grfFlags); 
            }

            void IStorage.Commit(
                int grfCommitFlags ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 
 
                _unsafeStorage.Commit(
                    grfCommitFlags); 
            }

            void IStorage.Revert()
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafeStorage.Revert(); 
            }
 
            void IStorage.EnumElements(
                int reserved1,
                IntPtr reserved2,
                int reserved3, 
                out IEnumSTATSTG ppEnum )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATSTG enumSTATSTG; 

                _unsafeStorage.EnumElements(
                    reserved1,
                    reserved2, 
                    reserved3,
                    out enumSTATSTG); 
 
                if (enumSTATSTG != null)
                    ppEnum = new SafeIEnumSTATSTGImplementation(enumSTATSTG); 
                else
                    ppEnum = null;
            }
 
            void IStorage.DestroyElement(
                string pwcsName ) 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafeStorage.DestroyElement(
                    pwcsName);
            }
 
            void IStorage.RenameElement(
                string pwcsOldName, 
                string pwcsNewName ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeStorage.RenameElement(
                    pwcsOldName,
                    pwcsNewName); 
            }
 
            void IStorage.SetElementTimes( 
                string pwcsName,
                System.Runtime.InteropServices.ComTypes.FILETIME pctime, 
                System.Runtime.InteropServices.ComTypes.FILETIME patime,
                System.Runtime.InteropServices.ComTypes.FILETIME pmtime )
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeStorage.SetElementTimes( 
                    pwcsName, 
                    pctime,
                    patime, 
                    pmtime);
            }

            void IStorage.SetClass( 
                ref Guid clsid ) // Hopefully "ref" is how I tell it to use a pointer
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeStorage.SetClass( 
                    ref clsid );
            }

            void IStorage.SetStateBits( 
                int grfStateBits,
                int grfMask ) 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafeStorage.SetStateBits(
                    grfStateBits,
                    grfMask);
            } 

            void IStorage.Stat( 
                out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, 
                int grfStatFlag )
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                _unsafeStorage.Stat(
                    out pstatstg, 
                    grfStatFlag);
            } 
 
            void IPropertySetStorage.Create(
                    ref Guid rfmtid, 
                    ref Guid pclsid,
                    UInt32 grfFlags,
                    UInt32 grfMode,
                    out IPropertyStorage ppprstg 
                    )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertyStorage propertyStorage; 

                _unsafePropertySetStorage.Create(
                    ref rfmtid,
                    ref pclsid, 
                    grfFlags,
                    grfMode, 
                    out propertyStorage 
                    );
 
                if (propertyStorage != null)
                    ppprstg = new SafeIPropertyStorageImplementation(propertyStorage);
                else
                    ppprstg = null; 
            }
 
            int IPropertySetStorage.Open( 
                    ref Guid rfmtid,
                    UInt32 grfMode, 
                    out IPropertyStorage ppprstg
                    )
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertyStorage propertyStorage; 
 
                int hr = _unsafePropertySetStorage.Open(
                    ref rfmtid, 
                    grfMode,
                    out propertyStorage
                    );
 
                if (propertyStorage != null)
                    ppprstg = new SafeIPropertyStorageImplementation(propertyStorage); 
                else 
                    ppprstg = null;
 
                return hr;
            }

            void IPropertySetStorage.Delete( 
                    ref Guid rfmtid
                    ) 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafePropertySetStorage.Delete(
                    ref rfmtid
                    );
            } 

            void IPropertySetStorage.Enum( 
                    out IEnumSTATPROPSETSTG ppenum 
                    )
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSETSTG enumSTATPROPSETSTG;
 
                _unsafePropertySetStorage.Enum(
                    out enumSTATPROPSETSTG 
                    ); 

                if (enumSTATPROPSETSTG != null) 
                    ppenum = new SafeIEnumSTATPROPSETSTGImplementation(enumSTATPROPSETSTG);
                else
                    ppenum = null;
            } 

            private UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertySetStorage _unsafePropertySetStorage; 
            private UnsafeNativeCompoundFileMethods.UnsafeNativeIStorage _unsafeStorage; 
            private UnsafeNativeCompoundFileMethods.UnsafeLockBytesOnStream _unsafeLockByteStream;
        } 

        private class SafeIStreamImplementation : IStream, IDisposable
        {
            internal SafeIStreamImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIStream stream) 
            {
                _unsafeStream = stream; 
            } 

            public void Dispose() 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                Dispose(true); 
                GC.SuppressFinalize(this);
            } 
 
            protected virtual void Dispose(bool disposing)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                try
                { 
                    if (disposing && (_unsafeStream != null))
                    { 
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafeStream); 
                    }
                } 
                finally
                {
                    _unsafeStream = null;
                } 
            }
 
            // 
            // IStream Implementation
            // 
            void IStream.Read(Byte[] pv, int cb, out int pcbRead)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                if (cb < 0)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "cb", cb.ToString(CultureInfo.InvariantCulture))); 
                }
 
                _unsafeStream.Read(pv, cb, out pcbRead);
            }

            void IStream.Write(Byte[] pv, int cb, out int pcbWritten) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 
 
                if (cb < 0)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "cb", cb.ToString(CultureInfo.InvariantCulture)));
                }

                _unsafeStream.Write(pv, cb, out pcbWritten); 
            }
 
 
            // IStream portion
            void IStream.Seek(long dlibMove, int dwOrigin, out long plibNewPosition) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                if (dwOrigin < 0) 
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "dwOrigin", dwOrigin.ToString(CultureInfo.InvariantCulture))); 
                } 

                if (dlibMove < 0 && dwOrigin == SafeNativeCompoundFileConstants.STREAM_SEEK_SET) 
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "dlibMove", dlibMove.ToString(CultureInfo.InvariantCulture)));
                }
 
                _unsafeStream.Seek(dlibMove, dwOrigin, out plibNewPosition);
            } 
 
            void IStream.SetSize(long libNewSize)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                if (libNewSize < 0)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "libNewSize", libNewSize.ToString(CultureInfo.InvariantCulture)));
                } 
 
                _unsafeStream.SetSize(libNewSize);
            } 

            void IStream.CopyTo(IStream pstm, long cb, out long pcbRead, out long pcbWritten)
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                Invariant.Assert(pstm != null, "pstm cannot be null"); 
 
                if (cb < 0)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "cb", cb.ToString(CultureInfo.InvariantCulture)));
                }

                _unsafeStream.CopyTo(((SafeIStreamImplementation) pstm)._unsafeStream, cb, out pcbRead, out pcbWritten); 
            }
 
            void IStream.Commit(int grfCommitFlags) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeStream.Commit(grfCommitFlags);
            }
 
            void IStream.Revert()
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeStream.Revert(); 
            }

            void IStream.LockRegion(long libOffset, long cb, int dwLockType)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                if (libOffset < 0) 
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "libOffset", libOffset.ToString(CultureInfo.InvariantCulture))); 
                }
                if (cb < 0)
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "cb", cb.ToString(CultureInfo.InvariantCulture))); 
                }
 
                _unsafeStream.LockRegion(libOffset, cb, dwLockType); 
            }
 
            void IStream.UnlockRegion(long libOffset, long cb, int dwLockType)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                if (libOffset < 0)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "libOffset", libOffset.ToString(CultureInfo.InvariantCulture))); 
                }
                if (cb < 0) 
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "cb", cb.ToString(CultureInfo.InvariantCulture)));
                }
 
                _unsafeStream.UnlockRegion(libOffset, cb, dwLockType);
            } 
 
            void IStream.Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();

                _unsafeStream.Stat(out pstatstg, grfStatFlag);
            } 

            void IStream.Clone(out IStream ppstm) 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                UnsafeNativeCompoundFileMethods.UnsafeNativeIStream stream;

                _unsafeStream.Clone(out stream);
 
                if (stream != null)
                { 
                    ppstm = new SafeIStreamImplementation(stream); 
                }
                else 
                {
                    ppstm = null;
                }
            } 

            private UnsafeNativeCompoundFileMethods.UnsafeNativeIStream _unsafeStream; 
        } 

        private class SafeIEnumSTATPROPSETSTGImplementation : IEnumSTATPROPSETSTG, IDisposable 
        {
            internal SafeIEnumSTATPROPSETSTGImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSETSTG enumSTATPROPSETSTG)
            {
                _unsafeEnumSTATPROPSETSTG = enumSTATPROPSETSTG; 
            }
 
            public void Dispose() 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                Dispose(true);
                GC.SuppressFinalize(this);
            } 

            ///  
            /// Dispose(bool) 
            /// 
            ///  
            protected virtual void Dispose(bool disposing)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                try
                { 
                    if (disposing && (_unsafeEnumSTATPROPSETSTG != null)) 
                    {
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafeEnumSTATPROPSETSTG); 
                    }
                }
                finally
                { 
                    _unsafeEnumSTATPROPSETSTG = null;
                } 
            } 

            // 
            // The caller must allocate an array of celt STATPROPSETSTG structures
            // to receive the results.
            //
            // This method is PreserveSig because it can return a non-0 success 
            // code; S_FALSE => fewer than celt elements were returned.
            // 
            int 
            IEnumSTATPROPSETSTG.Next(
                UInt32 celt, 
                STATPROPSETSTG rgelt,
                out UInt32 pceltFetched
                )
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                return _unsafeEnumSTATPROPSETSTG.Next( 
                    celt,
                    rgelt, 
                    out pceltFetched
                    );
            }
 
            void IEnumSTATPROPSETSTG.Skip(UInt32 celt)
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeEnumSTATPROPSETSTG.Skip(celt); 
            }

            void IEnumSTATPROPSETSTG.Reset()
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafeEnumSTATPROPSETSTG.Reset(); 
            }
 
            void IEnumSTATPROPSETSTG.Clone(out IEnumSTATPROPSETSTG ppenum)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSETSTG enumSTATPROPSETSTG;
 
                _unsafeEnumSTATPROPSETSTG.Clone(out enumSTATPROPSETSTG); 

                if (enumSTATPROPSETSTG != null) 
                    ppenum = new SafeIEnumSTATPROPSETSTGImplementation(enumSTATPROPSETSTG);
                else
                    ppenum = null;
            } 

            private UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSETSTG _unsafeEnumSTATPROPSETSTG; 
        } 

        private class SafeIPropertyStorageImplementation : IPropertyStorage, IDisposable 
        {
            internal SafeIPropertyStorageImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertyStorage propertyStorage)
            {
                _unsafePropertyStorage = propertyStorage; 
            }
 
            public void Dispose() 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                Dispose(true);
                GC.SuppressFinalize(this);
            } 

            ///  
            /// Dispose(bool) 
            /// 
            ///  
            protected virtual void Dispose(bool disposing)
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                try
                { 
                    if (disposing && (_unsafePropertyStorage != null)) 
                    {
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafePropertyStorage); 
                    }
                }
                finally
                { 
                    _unsafePropertyStorage = null;
                } 
            } 

            // 
            // We preserve the HRESULT on this method because we need to distinguish
            // between S_OK (we got the properties we asked for) and S_FALSE (none of
            // the properties exist).
            // 
            int IPropertyStorage.ReadMultiple(
                UInt32 cpspec, 
                PROPSPEC[] rgpspec, 
                PROPVARIANT[] rgpropvar
                ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                return _unsafePropertyStorage.ReadMultiple( 
                    cpspec,
                    rgpspec, 
                    rgpropvar 
                    );
            } 

            void IPropertyStorage.WriteMultiple(
                UInt32 cpspec,
                PROPSPEC[] rgpspec, 
                PROPVARIANT[] rgpropvar,
                uint propidNameFirst 
                ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.WriteMultiple(
                    cpspec,
                    rgpspec, 
                    rgpropvar,
                    propidNameFirst 
                    ); 
            }
 
            void IPropertyStorage.DeleteMultiple(
                UInt32 cpspec,
                PROPSPEC[] rgpspec
                ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 
 
                _unsafePropertyStorage.DeleteMultiple(
                    cpspec, 
                    rgpspec
                    );
            }
 
            void IPropertyStorage.ReadPropertyNames(
                UInt32 cpropid, 
                UInt32[] rgpropid, 
                string[] rglpwstrName
                ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                _unsafePropertyStorage.ReadPropertyNames( 
                    cpropid,
                    rgpropid, 
                    rglpwstrName 
                    );
            } 

            void IPropertyStorage.WritePropertyNames(
                UInt32 cpropid,
                UInt32[] rgpropid, 
                string[] rglpwstrName
                ) 
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafePropertyStorage.WritePropertyNames(
                    cpropid,
                    rgpropid,
                    rglpwstrName 
                    );
            } 
 
            void IPropertyStorage.DeletePropertyNames(
                UInt32 cpropid, 
                UInt32[] rgpropid
                )
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.DeletePropertyNames( 
                    cpropid, 
                    rgpropid
                    ); 
            }

            void IPropertyStorage.Commit(
                UInt32 grfCommitFlags 
                )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.Commit( 
                    grfCommitFlags
                    );
            }
 
            void IPropertyStorage.Revert()
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.Revert(); 
            }

            void IPropertyStorage.Enum(
                out IEnumSTATPROPSTG ppenum 
                )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

#if Using_SafeIPropertyStorageImplementation_Enum 

                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSTG unsafeEnumSTATPROPSTG;

                _unsafePropertyStorage.Enum( 
                    out unsafeEnumSTATPROPSTG
                    ); 
 
                if (unsafeEnumSTATPROPSTG != null)
                    ppenum = new SafeIEnumSTATPROPSTGImplementation(unsafeEnumSTATPROPSTG); 
                else
#endif
                    ppenum = null;
            } 

            void IPropertyStorage.SetTimes( 
                ref System.Runtime.InteropServices.ComTypes.FILETIME pctime, 
                ref System.Runtime.InteropServices.ComTypes.FILETIME patime,
                ref System.Runtime.InteropServices.ComTypes.FILETIME pmtime 
                )
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                _unsafePropertyStorage.SetTimes(
                    ref pctime, 
                    ref patime, 
                    ref pmtime
                    ); 
            }

            void IPropertyStorage.SetClass(
                ref Guid clsid 
                )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.SetClass( 
                    ref clsid
                    );
            }
 
            void IPropertyStorage.Stat(
                out STATPROPSETSTG pstatpsstg 
                ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafePropertyStorage.Stat(
                    out pstatpsstg
                    ); 
            }
 
            private UnsafeNativeCompoundFileMethods.UnsafeNativeIPropertyStorage _unsafePropertyStorage; 
        }
 
#if Using_SafeIPropertyStorageImplementation_Enum
        private class SafeIEnumSTATPROPSTGImplementation : IEnumSTATPROPSTG
        {
            internal SafeIEnumSTATPROPSTGImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSTG enumSTATPROPSTG) 
            {
                _unsafeEnumSTATPROPSTG= enumSTATPROPSTG; 
            } 

            public void Dispose() 
            {
                SecurityHelper.DemandCompoundFileIOPermission();

                Dispose(true); 
                GC.SuppressFinalize(this);
            } 
 
            /// 
            /// Dispose(bool) 
            /// 
            /// 
            protected virtual void Dispose(bool disposing)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                try 
                {
                    if (disposing && (_unsafeEnumSTATPROPSTG != null)) 
                    {
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafeEnumSTATPROPSTG);
                    }
                } 
                finally
                { 
                    _unsafeEnumSTATPROPSTG = null; 
                }
            } 

            //
            // The caller must allocate an array of celt STATPROPSTG structures
            // to receive the results. 
            //
            // This method is PreserveSig because it can return a non-0 success 
            // code; S_FALSE => fewer than celt elements were returned. 
            //
            int 
            IEnumSTATPROPSTG.Next(
                UInt32 celt,
                STATPROPSTG rgelt,
                out UInt32 pceltFetched 
                )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                return _unsafeEnumSTATPROPSTG.Next( 
                    celt,
                    rgelt,
                    out pceltFetched
                    ); 
            }
 
            void IEnumSTATPROPSTG.Skip(UInt32 celt) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeEnumSTATPROPSTG.Skip(celt);
            }
 
            void IEnumSTATPROPSTG.Reset()
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeEnumSTATPROPSTG.Reset(); 
            }

            void IEnumSTATPROPSTG.Clone(out IEnumSTATPROPSTG ppenum)
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSTG enumSTATPROPSTG; 

                _unsafeEnumSTATPROPSTG.Clone(out enumSTATPROPSTG); 

                if (enumSTATPROPSTG != null)
                    ppenum = new SafeIEnumSTATPROPSTGImplementation(enumSTATPROPSTG);
                else 
                    ppenum = null;
            } 
 
            private UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATPROPSTG _unsafeEnumSTATPROPSTG;
        } 
#endif

        private class SafeIEnumSTATSTGImplementation : IEnumSTATSTG, IDisposable
        { 
            internal SafeIEnumSTATSTGImplementation(UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATSTG enumSTATSTG)
            { 
                _unsafeEnumSTATSTG = enumSTATSTG; 
            }
 
            public void Dispose()
            {
                SecurityHelper.DemandCompoundFileIOPermission();
 
                Dispose(true);
                GC.SuppressFinalize(this); 
            } 

            ///  
            /// Dispose(bool)
            /// 
            /// 
            protected virtual void Dispose(bool disposing) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 
 
                try
                { 
                    if (disposing && (_unsafeEnumSTATSTG != null))
                    {
                        MS.Win32.UnsafeNativeMethods.SafeReleaseComObject((object) _unsafeEnumSTATSTG);
                    } 
                }
                finally 
                { 
                    _unsafeEnumSTATSTG = null;
                } 
            }

            void IEnumSTATSTG.Next(
                UInt32 celt, 
                out System.Runtime.InteropServices.ComTypes.STATSTG rgelt, // This should really be array, but we're OK if we stick with one item at a time.
                    // Because marshalling an array of structs that have pointers to strings are troublesome. 
                out UInt32 pceltFetched ) 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 

                if (celt != 1)
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidArgumentValue, "celt", celt.ToString(CultureInfo.InvariantCulture))); 
                }
 
                _unsafeEnumSTATSTG.Next( 
                    celt,
                    out rgelt, 
                    out pceltFetched );
            }

            void IEnumSTATSTG.Skip( 
                UInt32 celt )
            { 
                SecurityHelper.DemandCompoundFileIOPermission(); 

                _unsafeEnumSTATSTG.Skip( 
                    celt );
            }

            void IEnumSTATSTG.Reset() 
            {
                SecurityHelper.DemandCompoundFileIOPermission(); 
 
                _unsafeEnumSTATSTG.Reset();
            } 

            void IEnumSTATSTG.Clone(
                out IEnumSTATSTG ppenum )
            { 
                SecurityHelper.DemandCompoundFileIOPermission();
 
                UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATSTG enumSTATSTG; 

                _unsafeEnumSTATSTG.Clone( 
                    out enumSTATSTG );

                if (enumSTATSTG != null)
                    ppenum = new SafeIEnumSTATSTGImplementation(enumSTATSTG); 
                else
                    ppenum = null; 
            } 

            private UnsafeNativeCompoundFileMethods.UnsafeNativeIEnumSTATSTG _unsafeEnumSTATSTG; 
        }

    }
} 


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