BitmapMetadata.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / System / Windows / Media / Imaging / BitmapMetadata.cs / 1 / BitmapMetadata.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, All Rights Reserved
//
//  File: BitmapMetadata.cs 
//
//----------------------------------------------------------------------------- 
 
using System;
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel; 
using System.ComponentModel.Design.Serialization;
using System.Reflection; 
using MS.Internal; 
using MS.Win32.PresentationCore;
using System.Diagnostics; 
using System.Globalization;
using System.Runtime.InteropServices;
using System.Xml;
using System.IO; 
using System.Security;
using System.Security.Permissions; 
using System.Windows.Media.Imaging; 
using System.Windows.Threading;
using System.Text; 
using MS.Internal.PresentationCore;                        // SecurityHelper

#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
 
namespace System.Windows.Media.Imaging
{ 
    #region BitmapMetadata 

    ///  
    /// Metadata Class for BitmapImage.
    /// 
    public partial class BitmapMetadata : ImageMetadata, IEnumerable, IEnumerable
    { 

        //************************************************************* 
        // 
        //  IWICMetadataBlockReader
        // 
        //*************************************************************

        // Guid: IID_IWICMetadataBlockReader
        [ComImport(), 
         Guid("FEAA2A8D-B3F3-43E4-B25C-D1DE990A1AE1"),
         InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 
        internal interface IWICMetadataBlockReader 
        {
            [PreserveSig] 
            int GetContainerFormat(
                out Guid containerFormat
            );
 
            [PreserveSig]
            int GetCount( 
                out UInt32 count 
            );
 
            [PreserveSig]
            int GetReaderByIndex(
                UInt32 index,
                out IntPtr /* IWICMetadataReader */ ppIMetadataReader 
            );
 
            [PreserveSig] 
            int GetEnumerator(
                out IntPtr /* IEnumUnknown */ pIEnumMetadata 
            );
        }

        //************************************************************** 
        //
        //  IWICMetadataBlockWriter 
        // 
        //*************************************************************
 
        // Guid: IID_IWICMetadataBlockWriter
        [ComImport(),
         Guid("08FB9676-B444-41E8-8DBE-6A53A542BFF1"),
         InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 
        internal interface IWICMetadataBlockWriter : IWICMetadataBlockReader
        { 
            [PreserveSig] 
            new int GetContainerFormat(
                out Guid containerFormat 
            );

            [PreserveSig]
            new int GetCount( 
                out UInt32 count
            ); 
 
            [PreserveSig]
            new int GetReaderByIndex( 
                UInt32 index,
                out IntPtr /* IWICMetadataReader */ ppIMetadataReader
            );
 
            [PreserveSig]
            new int GetEnumerator( 
                out IntPtr /* IEnumUnknown */ pIEnumMetadata 
            );
 
            [PreserveSig]
            int InitializeFromBlockReader(
                IntPtr /* IWICMetadataBlockReader */ pIBlockReader
            ); 

            [PreserveSig] 
            int GetWriterByIndex( 
                UInt32 index,
                out IntPtr /* IWICMetadataWriter */ ppIMetadataWriter 
            );

            [PreserveSig]
            int AddWriter( 
                IntPtr /* IWICMetadataWriter */ pIMetadataWriter
            ); 
 
            [PreserveSig]
            int SetWriterByIndex( 
                UInt32 index,
                IntPtr /* IWICMetadataWriter */ pIMetadataWriter
            );
 
            [PreserveSig]
            int RemoveWriterByIndex( 
                UInt32 index 
            );
        } 

        //**************************************************************
        //
        //  BitmapMetadataBlockWriter 
        //
        //************************************************************** 
 
        [ClassInterface(ClassInterfaceType.None)]
        internal sealed class BitmapMetadataBlockWriter : 
            IWICMetadataBlockWriter,
            IWICMetadataBlockReader
        {
            internal BitmapMetadataBlockWriter(Guid containerFormat, bool fixedSize) 
            {
                _fixedSize = fixedSize; 
                _containerFormat = containerFormat; 
                _metadataBlocks = new ArrayList();
            } 

            /// 
            /// Critical - Accesses unmanaged code
            /// TreatAsSafe - inputs are verified or safe 
            /// 
            [SecurityCritical, SecurityTreatAsSafe] 
            internal BitmapMetadataBlockWriter(BitmapMetadataBlockWriter blockWriter, object syncObject) 
            {
                Guid guidVendor = new Guid(MILGuidData.GUID_VendorMicrosoft); 

                _fixedSize = blockWriter._fixedSize;
                _containerFormat = blockWriter._containerFormat;
                _metadataBlocks = new ArrayList(); 

                ArrayList metadataBlocks = blockWriter.MetadataBlocks; 
 
                using (FactoryMaker factoryMaker = new FactoryMaker())
                { 
                    foreach (SafeMILHandle metadataHandle in metadataBlocks)
                    {
                        lock (syncObject)
                        { 
                            IntPtr pIMetadataWriter = IntPtr.Zero;
 
                            try 
                            {
                                HRESULT.Check(UnsafeNativeMethods.WICComponentFactory.CreateMetadataWriterFromReader( 
                                    factoryMaker.ImagingFactoryPtr,
                                    metadataHandle,
                                    ref guidVendor,
                                    out pIMetadataWriter 
                                ));
 
                                SafeMILHandle metadataWriter = new SafeMILHandle(pIMetadataWriter, 0); 
                                pIMetadataWriter = IntPtr.Zero;
 
                                _metadataBlocks.Add(metadataWriter);
                            }
                            finally
                            { 
                                if (pIMetadataWriter != IntPtr.Zero)
                                { 
                                    #pragma warning suppress 6031 // Return value ignored on purpose. 
                                    UnsafeNativeMethods.MILUnknown.Release(pIMetadataWriter);
                                } 
                            }
                        }
                    }
                } 
            }
 
            public int GetContainerFormat( 
                out Guid containerFormat
            ) 
            {
                containerFormat = _containerFormat;

                return MS.Win32.NativeMethods.S_OK; 
            }
 
            public int GetCount( 
                out UInt32 count
            ) 
            {
                count = (UInt32) _metadataBlocks.Count;

                return MS.Win32.NativeMethods.S_OK; 
            }
 
            ///  
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not
            /// publicly exposed or accessible in any way. 
            /// 
            /// 
            /// Critical - Accesses unmanaged code
            ///  
            [SecurityCritical]
            public int GetReaderByIndex( 
                UInt32 index, 
                out IntPtr /* IWICMetadataReader */ pIMetadataReader
            ) 
            {
                if (index >= _metadataBlocks.Count)
                {
                    pIMetadataReader = IntPtr.Zero; 
                    return (int) WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND;
                } 
 
                SafeMILHandle metadataReader = (SafeMILHandle) _metadataBlocks[(int)index];
 
                Guid wicMetadataReader = MILGuidData.IID_IWICMetadataReader;
                return UnsafeNativeMethods.MILUnknown.QueryInterface(
                    metadataReader,
                    ref wicMetadataReader, 
                    out pIMetadataReader);
            } 
 
            /// 
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not 
            /// publicly exposed or accessible in any way.
            /// 
            /// 
            /// Critical - Accesses unmanaged code 
            /// 
            [SecurityCritical] 
            public int GetEnumerator( 
                out IntPtr /* IEnumUnknown */ pIEnumMetadata
            ) 
            {
                BitmapMetadataBlockWriterEnumerator blockEnumerator;

                blockEnumerator = new BitmapMetadataBlockWriterEnumerator(this); 

                pIEnumMetadata = Marshal.GetComInterfaceForObject( 
                    blockEnumerator, 
                    typeof(System.Windows.Media.Imaging.BitmapMetadata.IEnumUnknown));
 
                return MS.Win32.NativeMethods.S_OK;
            }

            ///  
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not
            /// publicly exposed or accessible in any way. 
            ///  
            /// 
            /// Critical - Accesses unmanaged code 
            /// 
            [SecurityCritical]
            public int InitializeFromBlockReader(
                IntPtr /* IWICMetadataBlockReader */ pIBlockReader 
            )
            { 
                Invariant.Assert(pIBlockReader != IntPtr.Zero); 

                int hr = MS.Win32.NativeMethods.S_OK; 

                UInt32 count = 0;

                Guid guidVendor = new Guid(MILGuidData.GUID_VendorMicrosoft); 

                ArrayList metadataBlocks = new ArrayList(); 
 
                hr = UnsafeNativeMethods.WICMetadataBlockReader.GetCount(
                    pIBlockReader, 
                    out count
                );

                if (HRESULT.Succeeded(hr)) 
                {
                    using (FactoryMaker factoryMaker = new FactoryMaker()) 
                    { 
                        for (UInt32 i=0; i
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not
            /// publicly exposed or accessible in any way. 
            /// 
            ///  
            /// Critical - Accesses unmanaged code 
            /// 
            [SecurityCritical] 
            public int GetWriterByIndex(
                UInt32 index,
                out IntPtr  /* IWICMetadataWriter */ pIMetadataWriter
            ) 
            {
                if (index >= _metadataBlocks.Count) 
                { 
                    pIMetadataWriter = IntPtr.Zero;
                    return (int) WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND; 
                }

                SafeMILHandle metadataWriter = (SafeMILHandle) _metadataBlocks[(int)index];
 
                Guid wicMetadataWriter = MILGuidData.IID_IWICMetadataWriter;
                return UnsafeNativeMethods.MILUnknown.QueryInterface( 
                    metadataWriter, 
                    ref wicMetadataWriter,
                    out pIMetadataWriter); 
            }

            /// 
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not 
            /// publicly exposed or accessible in any way.
            ///  
            ///  
            /// Critical - Accesses unmanaged code
            ///  
            [SecurityCritical]
            public int AddWriter(
                IntPtr /* IWICMetadataWriter */ pIMetadataWriter
            ) 
            {
                if (pIMetadataWriter == IntPtr.Zero) 
                { 
                    return (int) WinCodecErrors.WINCODEC_ERR_INVALIDPARAMETER;
                } 

                if (_fixedSize && _metadataBlocks.Count>0)
                {
                    return (int) WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION; 
                }
 
                SafeMILHandle metadataWriter = new SafeMILHandle(pIMetadataWriter, 0); 

                UnsafeNativeMethods.MILUnknown.AddRef(metadataWriter); 

                _metadataBlocks.Add(metadataWriter);

                return MS.Win32.NativeMethods.S_OK; 
            }
 
            ///  
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not
            /// publicly exposed or accessible in any way. 
            /// 
            /// 
            /// Critical - Accesses unmanaged code
            ///  
            [SecurityCritical]
            public int SetWriterByIndex( 
                UInt32 index, 
                IntPtr /* IWICMetadataWriter */ pIMetadataWriter
            ) 
            {
                if (index >= _metadataBlocks.Count)
                {
                    return (int) WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND; 
                }
 
                if (pIMetadataWriter == IntPtr.Zero) 
                {
                    return (int) WinCodecErrors.WINCODEC_ERR_INVALIDPARAMETER; 
                }

                if (_fixedSize)
                { 
                    return (int) WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION;
                } 
 
                SafeMILHandle metadataWriter = new SafeMILHandle(pIMetadataWriter, 0);
 
                UnsafeNativeMethods.MILUnknown.AddRef(metadataWriter);

                _metadataBlocks[(int)index] = metadataWriter;
 
                return MS.Win32.NativeMethods.S_OK;
            } 
 
            public int RemoveWriterByIndex(
                UInt32 index 
            )
            {
                if (index >= _metadataBlocks.Count)
                { 
                    return (int) WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND;
                } 
 
                if (_fixedSize)
                { 
                    return (int) WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION;
                }

                _metadataBlocks.Remove(index); 

                return MS.Win32.NativeMethods.S_OK; 
            } 

            internal ArrayList MetadataBlocks 
            {
                get
                {
                    return _metadataBlocks; 
                }
            } 
 
            private bool _fixedSize;
            private Guid _containerFormat; 
            private ArrayList _metadataBlocks;
        }

        //************************************************************* 
        //
        //  IEnumUnknown 
        // 
        //**************************************************************
 
        // Guid: IID_IEnumUnknown
        [ComImport(),
         Guid("00000100-0000-0000-C000-000000000046"),
         InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 
        internal interface IEnumUnknown
        { 
            [PreserveSig] 
            int Next(
                UInt32 celt, 
                out IntPtr /* IUnknown ** */ rgelt,
                ref UInt32 pceltFetched
            );
 
            [PreserveSig]
            int Skip( 
                UInt32 celt 
            );
 
            [PreserveSig]
            int Reset();

            [PreserveSig] 
            int Clone(
                ref IntPtr /* IEnumString ** */ ppEnum 
            ); 
        }
 
        //*************************************************************
        //
        //  BitmapMetadataBlockWriterEnumerator
        // 
        //*************************************************************
 
        [ClassInterface(ClassInterfaceType.None)] 
        internal sealed class BitmapMetadataBlockWriterEnumerator : IEnumUnknown
        { 
            internal BitmapMetadataBlockWriterEnumerator(
                BitmapMetadataBlockWriter blockWriter
            )
            { 
                Debug.Assert(blockWriter != null);
                Debug.Assert(blockWriter.MetadataBlocks != null); 
 
                _metadataBlocks = blockWriter.MetadataBlocks;
                _index = 0; 
            }

            /// 
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not 
            /// publicly exposed or accessible in any way.
            ///  
            ///  
            /// Critical - Accesses unmanaged code
            ///  
            [SecurityCritical]
            public int Next(
                UInt32 celt,
                out IntPtr /* IUnknown ** */ rgelt, 
                ref UInt32 pceltFetched
            ) 
            { 
                // This implementation only supports single enumeration.
                if (celt > 1) 
                {
                    rgelt = IntPtr.Zero;
                    pceltFetched = 0;
                    return (int) WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION; 
                }
 
                if (_index >= _metadataBlocks.Count || celt == 0) 
                {
                    rgelt = IntPtr.Zero; 
                    pceltFetched = 0;
                    return MS.Win32.NativeMethods.S_FALSE;
                }
                else 
                {
                    SafeMILHandle metadataHandle = (SafeMILHandle) _metadataBlocks[(int)_index]; 
 
                    Guid wicMetadataReader = MILGuidData.IID_IWICMetadataReader;
                    int hr = UnsafeNativeMethods.MILUnknown.QueryInterface( 
                        metadataHandle,
                        ref wicMetadataReader,
                        out rgelt);
 
                    if (HRESULT.Succeeded(hr))
                    { 
                        pceltFetched = 1; 
                        _index++;
                    } 

                    return hr;
                }
            } 

            ///  
            /// Critical - Accesses unmanaged code 
            /// TreatAsSafe - inputs are verified or safe
            ///  
            [SecurityCritical, SecurityTreatAsSafe]
            public int Skip(
                UInt32 celt
            ) 
            {
                UInt32 newIndex = _index + celt; 
 
                if (newIndex > _metadataBlocks.Count)
                { 
                    _index = (uint) _metadataBlocks.Count;
                    return MS.Win32.NativeMethods.S_FALSE;
                }
                else 
                {
                    _index += celt; 
                    return MS.Win32.NativeMethods.S_OK; 
                }
            } 

            /// 
            /// Critical - Accesses unmanaged code
            /// TreatAsSafe - inputs are verified or safe 
            /// 
            [SecurityCritical, SecurityTreatAsSafe] 
            public int Reset() 
            {
                _index = 0; 
                return MS.Win32.NativeMethods.S_OK;
            }

            ///  
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not
            /// publicly exposed or accessible in any way. 
            ///  
            /// 
            /// Critical - Accesses unmanaged code 
            /// 
            [SecurityCritical]
            public int Clone(
                ref IntPtr /* IEnumUnknown ** */ ppEnum 
            )
            { 
                ppEnum = IntPtr.Zero; 
                return (int) WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION;
            } 

            private ArrayList _metadataBlocks;
            private UInt32 _index;
        } 

        #region Constructors 
 
        /// 
        /// 
        /// 
        /// 
        /// Critical - Accesses unmanaged code
        /// PublicOK - inputs are verified or safe 
        /// 
        [SecurityCritical] 
        public BitmapMetadata(String containerFormat) 
        {
            if (containerFormat == null) 
            {
                throw new System.ArgumentNullException("containerFormat");
            }
 
            Guid guid = new Guid();
 
            // Find the length of the string needed 
            HRESULT.Check(UnsafeNativeMethods.WICCodec.WICMapShortNameToGuid(
                containerFormat, 
                ref guid
                ));

            Init(guid, false, false); 
        }
 
        ///  
        ///
        ///  
        /// 
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - constructor is safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal BitmapMetadata() 
        { 
            _metadataHandle = null;
            _readOnly = true; 
            _fixedSize = false;
            _blockWriter = null;
        }
 
        /// 
        /// 
        ///  
        /// 
        /// Critical - Accesses critical resource 
        /// 
        [SecurityCritical]
        internal BitmapMetadata(
            SafeMILHandle metadataHandle, 
            bool readOnly,
            bool fixedSize, 
            object syncObject 
        )
        { 
            _metadataHandle = metadataHandle;
            _readOnly = readOnly;
            _fixedSize = fixedSize;
            _blockWriter = null; 
            _syncObject = syncObject;
        } 
 
        /// 
        /// 
        /// 
        internal BitmapMetadata(BitmapMetadata bitmapMetadata)
        {
            if (bitmapMetadata == null) 
            {
                throw new System.ArgumentNullException("bitmapMetadata"); 
            } 

            Init(bitmapMetadata.GuidFormat, false, bitmapMetadata._fixedSize); 
        }

        /// 
        /// 
        /// 
        ///  
        /// Critical - Accesses unmanaged code 
        /// TreatAsSafe - inputs are verified or safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void Init(Guid containerFormat, bool readOnly, bool fixedSize)
        {
            int hr = 0; 
            IntPtr /* IWICMetadataQueryWriter */ queryWriter = IntPtr.Zero;
 
            using (FactoryMaker factoryMaker = new FactoryMaker()) 
            {
                Guid vendorMicrosoft = new Guid(MILGuidData.GUID_VendorMicrosoft); 

                // If it's a metadata format, create a Query Writer to wrap it.
                hr = UnsafeNativeMethods.WICImagingFactory.CreateQueryWriter(
                    factoryMaker.ImagingFactoryPtr, 
                    ref containerFormat,
                    ref vendorMicrosoft, 
                    out queryWriter 
                    );
            } 

            if (HRESULT.Succeeded(hr))
            {
                _readOnly = readOnly; 
                _fixedSize = fixedSize;
                _blockWriter = null; 
 
                _metadataHandle = new SafeMILHandle(queryWriter, 0);
                _syncObject = _metadataHandle; 
            }
            else
            {
                InitializeFromBlockWriter(containerFormat, readOnly, fixedSize); 
            }
        } 
 
        /// 
        /// 
        /// 
        /// 
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - inputs are verified or safe 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private void InitializeFromBlockWriter(Guid containerFormat, bool readOnly, bool fixedSize) 
        {
            IntPtr /* IWICMetadataBlockWriter */ blockWriter = IntPtr.Zero; 
            IntPtr /* IWICMetadataQueryWriter */ queryWriter = IntPtr.Zero;

            using (FactoryMaker factoryMaker = new FactoryMaker())
            { 
                try
                { 
                    // Otherwise, simulate a metadata block writer for this imaging container format. 
                    _blockWriter = new BitmapMetadataBlockWriter(containerFormat, fixedSize);
 
                    blockWriter = Marshal.GetComInterfaceForObject(
                        _blockWriter,
                        typeof(System.Windows.Media.Imaging.BitmapMetadata.IWICMetadataBlockWriter));
 
                    HRESULT.Check(UnsafeNativeMethods.WICComponentFactory.CreateQueryWriterFromBlockWriter(
                        factoryMaker.ImagingFactoryPtr, 
                        blockWriter, 
                        ref queryWriter
                    )); 

                    _readOnly = readOnly;
                    _fixedSize = fixedSize;
 
                    _metadataHandle = new SafeMILHandle(queryWriter, 0);
                    queryWriter = IntPtr.Zero; 
 
                    _syncObject = _metadataHandle;
                } 
                finally
                {
                    if (blockWriter != IntPtr.Zero)
                    { 
                        #pragma warning suppress 6031 // Return value ignored on purpose.
                        UnsafeNativeMethods.MILUnknown.Release(blockWriter); 
                    } 
                    if (queryWriter != IntPtr.Zero)
                    { 
                        #pragma warning suppress 6031 // Return value ignored on purpose.
                        UnsafeNativeMethods.MILUnknown.Release(queryWriter);
                    }
                } 
            }
        } 
 
        /// 
        /// 
        /// 
        /// 
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - inputs are verified or safe 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private void InitializeFromBlockWriter(BitmapMetadataBlockWriter sourceBlockWriter, object syncObject) 
        {
            IntPtr /* IWICMetadataBlockWriter */ blockWriter = IntPtr.Zero; 
            IntPtr /* IWICMetadataQueryWriter */ queryWriter = IntPtr.Zero;

            using (FactoryMaker factoryMaker = new FactoryMaker())
            { 
                try
                { 
                    // Otherwise, simulate a metadata block writer for this imaging container format. 
                    _blockWriter = new BitmapMetadataBlockWriter(sourceBlockWriter, syncObject);
 
                    blockWriter = Marshal.GetComInterfaceForObject(
                        _blockWriter,
                        typeof(System.Windows.Media.Imaging.BitmapMetadata.IWICMetadataBlockWriter));
 
                    HRESULT.Check(UnsafeNativeMethods.WICComponentFactory.CreateQueryWriterFromBlockWriter(
                        factoryMaker.ImagingFactoryPtr, 
                        blockWriter, 
                        ref queryWriter
                    )); 

                    _readOnly = false;
                    _fixedSize = false;
 
                    _metadataHandle = new SafeMILHandle(queryWriter, 0);
                    queryWriter = IntPtr.Zero; 
 
                    _syncObject = _metadataHandle;
                } 
                finally
                {
                    if (blockWriter != IntPtr.Zero)
                    { 
                        #pragma warning suppress 6031 // Return value ignored on purpose.
                        UnsafeNativeMethods.MILUnknown.Release(blockWriter); 
                    } 
                    if (queryWriter != IntPtr.Zero)
                    { 
                        #pragma warning suppress 6031 // Return value ignored on purpose.
                        UnsafeNativeMethods.MILUnknown.Release(queryWriter);
                    }
                } 
            }
        } 
 
        /// 
        /// 
        /// 
        /// 
        /// Critical - Accesses unmanaged code and critical resource
        ///  
        [SecurityCritical]
        private void InitializeFromMetadataWriter(SafeMILHandle metadataHandle, object syncObject) 
        { 
            int hr;
            IntPtr queryWriter = IntPtr.Zero; 

            Guid guidVendor = new Guid(MILGuidData.GUID_VendorMicrosoft);

            // Create a query writer for this metadata format 
            try
            { 
                using (FactoryMaker factoryMaker = new FactoryMaker()) 
                {
                    lock (syncObject) 
                    {
                        hr = UnsafeNativeMethods.WICImagingFactory.CreateQueryWriterFromReader(
                            factoryMaker.ImagingFactoryPtr,
                            metadataHandle, 
                            ref guidVendor,
                            out queryWriter); 
                    } 
                }
 
                if (HRESULT.Succeeded(hr))
                {
                    _readOnly = false;
                    _fixedSize = false; 
                    _blockWriter = null;
 
                    _metadataHandle = new SafeMILHandle(queryWriter, 0); 
                    queryWriter = IntPtr.Zero;
 
                    _syncObject = _metadataHandle;
                }
                else if (!HRESULT.IsWindowsCodecError(hr))
                { 
                    HRESULT.Check(hr);
                } 
            } 
            finally
            { 
                if (queryWriter != IntPtr.Zero)
                {
                    #pragma warning suppress 6031 // Return value ignored on purpose.
                    UnsafeNativeMethods.MILUnknown.Release(queryWriter); 
                }
            } 
        } 

        #endregion 

        #region Freezable

        ///  
        ///     Shadows inherited Clone() with a strongly typed
        ///     version for convenience. 
        ///  
        public new BitmapMetadata Clone()
        { 
            return (BitmapMetadata)base.Clone();
        }

        ///  
        /// Implementation of Freezable.CreateInstanceCore.
        ///  
        /// The new Freezable. 
        protected override Freezable CreateInstanceCore()
        { 
            return new BitmapMetadata();
        }

        ///  
        /// Implementation of Freezable.CloneCore.
        ///  
        protected override void CloneCore(Freezable sourceFreezable) 
        {
            BitmapMetadata sourceBitmapMetadata = (BitmapMetadata) sourceFreezable; 
            base.CloneCore(sourceFreezable);

            CopyCommon(sourceBitmapMetadata);
        } 

        ///  
        /// Implementation of Freezable.CloneCurrentValueCore. 
        /// 
        protected override void CloneCurrentValueCore(Freezable sourceFreezable) 
        {
            BitmapMetadata sourceBitmapMetadata = (BitmapMetadata)sourceFreezable;
            base.CloneCurrentValueCore(sourceFreezable);
 
            CopyCommon(sourceBitmapMetadata);
        } 
 

        ///  
        /// Implementation of Freezable.GetAsFrozenCore.
        /// 
        protected override void GetAsFrozenCore(Freezable sourceFreezable)
        { 
            BitmapMetadata sourceBitmapMetadata = (BitmapMetadata)sourceFreezable;
            base.GetAsFrozenCore(sourceFreezable); 
 
            CopyCommon(sourceBitmapMetadata);
        } 


        /// 
        /// Implementation of Freezable.GetCurrentValueAsFrozenCore. 
        /// 
        protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable) 
        { 
            BitmapMetadata sourceBitmapMetadata = (BitmapMetadata)sourceFreezable;
            base.GetCurrentValueAsFrozenCore(sourceFreezable); 

            CopyCommon(sourceBitmapMetadata);
        }
 
        #endregion
 
        ///  
        ///
        ///  
        /// 
        /// Critical - Accesses unmanaged code
        /// PublicOK - inputs are verified or safe
        ///  
        public String Format
        { 
            [SecurityCritical] 
            get
            { 
                EnsureBitmapMetadata();
                StringBuilder format = null;
                UInt32 length = 0;
 
                // This calls EnsureBitmapMetadata()
                Guid guid = GuidFormat; 
 
                // Find the length of the string needed
                lock (_syncObject) 
                {
                    HRESULT.Check(UnsafeNativeMethods.WICCodec.WICMapGuidToShortName(
                        ref guid,
                        0, 
                        format,
                        ref length 
                        )); 

                    Debug.Assert(length >= 0); 

                    // get the string back
                    if (length > 0)
                    { 
                        format = new StringBuilder((int)length);
 
                        HRESULT.Check(UnsafeNativeMethods.WICCodec.WICMapGuidToShortName( 
                            ref guid,
                            length, 
                            format,
                            ref length
                            ));
                    } 
                }
 
                return format.ToString(); 
            }
        } 

        /// 
        ///
        ///  
        /// 
        /// Critical - Accesses unmanaged code 
        /// PublicOK - inputs are verified or safe 
        /// 
        public String Location 
        {
            [SecurityCritical]
            get
            { 
                StringBuilder location = null;
                UInt32 length = 0; 
 
                EnsureBitmapMetadata();
 
                // Find the length of the string needed
                lock (_syncObject)
                {
                    HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryReader.GetLocation( 
                        _metadataHandle,
                        0, 
                        location, 
                        out length
                        )); 

                    Debug.Assert(length >= 0);

                    // get the string back 
                    if (length > 0)
                    { 
                        location = new StringBuilder((int)length); 

                        HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryReader.GetLocation( 
                            _metadataHandle,
                            length,
                            location,
                            out length 
                            ));
                    } 
                } 

                return location.ToString(); 
            }
        }

        #region Properties 

        ///  
        /// 
        /// 
        public bool IsReadOnly 
        {
            get
            {
                EnsureBitmapMetadata(); 

                return _readOnly; 
            } 
        }
 
        /// 
        ///
        /// 
        public bool IsFixedSize 
        {
            get 
            { 
                EnsureBitmapMetadata();
 
                return _fixedSize;
            }
        }
 
        #endregion
 
        #region Query Methods 

        ///  
        ///
        /// 
        /// 
        /// Critical - Accesses unmanaged code 
        /// PublicOK - inputs are verified or safe
        ///  
        [SecurityCritical] 
        public void SetQuery(String query, object value)
        { 
            WritePreamble();

            if (query == null)
            { 
                throw new System.ArgumentNullException("query");
            } 
 
            if (value == null)
            { 
                throw new System.ArgumentNullException("value");
            }

            if (_readOnly) 
            {
                throw new System.InvalidOperationException(SR.Get(SRID.Image_MetadataReadOnly)); 
            } 

            // Store these for debugging stress failures. 
            _setQueryString = query;
            _setQueryValue = value;

            EnsureBitmapMetadata(); 

            PROPVARIANT propVar = new PROPVARIANT(); 
 
            try
            { 
                propVar.Init(value);

                if (propVar.RequiresSyncObject)
                { 
                    BitmapMetadata metadata = value as BitmapMetadata;
                    Invariant.Assert(metadata != null); 
 
                    #pragma warning suppress 6506 // Invariant.Assert(metadata != null);
                    metadata.VerifyAccess(); 

                    #pragma warning suppress 6506 // Invariant.Assert(metadata != null);
                    lock (metadata._syncObject)
                    { 
                        lock (_syncObject)
                        { 
                            HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryWriter.SetMetadataByName( 
                                _metadataHandle,
                                query, 
                                ref propVar
                                ));
                        }
                    } 
                }
                else 
                { 
                    lock (_syncObject)
                    { 
                        HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryWriter.SetMetadataByName(
                            _metadataHandle,
                            query,
                            ref propVar 
                            ));
                    } 
                } 
            }
            finally 
            {
                propVar.Clear();
            }
 
            WritePostscript();
        } 
 
        /// 
        /// 
        /// 
        /// 
        /// Critical - Accesses unmanaged code
        /// PublicOK - inputs are verified or safe 
        /// 
        [SecurityCritical] 
        public object GetQuery(String query) 
        {
            int hr; 

            if (query == null)
            {
                throw new System.ArgumentNullException("query"); 
            }
 
            EnsureBitmapMetadata(); 

            PROPVARIANT propVar = new PROPVARIANT(); 

            try
            {
                propVar.Init(null); 

                lock (_syncObject) 
                { 
                    hr = UnsafeNativeMethods.WICMetadataQueryReader.GetMetadataByName(
                        _metadataHandle, 
                        query,
                        ref propVar
                        );
                } 

                if (hr != (int)WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND) 
                { 
                    HRESULT.Check(hr);
 
                    object objValue = propVar.ToObject(_syncObject);

                    if (IsFrozenInternal)
                    { 
                        BitmapMetadata metadata = objValue as BitmapMetadata;
 
                        if (metadata != null) 
                        {
                            metadata.Freeze(); 
                        }
                    }

                    return objValue; 
                }
            } 
            finally 
            {
                propVar.Clear(); 
            }

            return null;
        } 

        ///  
        /// 
        /// 
        ///  
        /// Critical - Accesses unmanaged code
        /// PublicOK - inputs are verified or safe
        /// 
        [SecurityCritical] 
        public void RemoveQuery(String query)
        { 
            int hr; 

            WritePreamble(); 

            if (query == null)
            {
                throw new System.ArgumentNullException("query"); 
            }
 
            if (_readOnly) 
            {
                throw new System.InvalidOperationException(SR.Get(SRID.Image_MetadataReadOnly)); 
            }

            EnsureBitmapMetadata();
 
            lock (_syncObject)
            { 
                hr = UnsafeNativeMethods.WICMetadataQueryWriter.RemoveMetadataByName( 
                    _metadataHandle,
                    query 
                    );
            }

            if (hr != (int)WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND) 
            {
                HRESULT.Check(hr); 
            } 
        }
 
        /// 
        ///
        /// 
        ///  
        /// Critical - Accesses unmanaged code eventually
        /// TreatAsSafe - inputs are verified or safe 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        IEnumerator IEnumerable.GetEnumerator() 
        {
            EnsureBitmapMetadata();

            return new BitmapMetadataEnumerator(_metadataHandle); 
        }
 
        ///  
        ///
        ///  
        /// 
        /// Critical - Accesses unmanaged code eventually
        /// TreatAsSafe - inputs are verified or safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        IEnumerator IEnumerable.GetEnumerator() 
        { 
            EnsureBitmapMetadata();
 
            return new BitmapMetadataEnumerator(_metadataHandle);
        }

        ///  
        ///
        ///  
        ///  
        /// Critical - Accesses unmanaged code
        /// PublicOK - inputs are verified or safe 
        /// 
        [SecurityCritical]
        public bool ContainsQuery(String query)
        { 
            int hr;
 
            if (query == null) 
            {
                throw new System.ArgumentNullException("query"); 
            }

            EnsureBitmapMetadata();
 
            lock (_syncObject)
            { 
                hr = UnsafeNativeMethods.WICMetadataQueryReader.ContainsMetadataByName( 
                    _metadataHandle,
                    query, 
                    IntPtr.Zero
                    );
            }
 
            if (HRESULT.IsWindowsCodecError(hr))
            { 
                return false; 
            }
            else 
            {
                HRESULT.Check(hr);
            }
 
            return true;
        } 
 
        #endregion
 
        #region Policy-driven Properties

        /// 
        /// Access Author for the image 
        /// 
        public ReadOnlyCollection Author 
        { 
            get
            { 
                String[] strAuthors = GetQuery(policy_Author) as String[];

                return (strAuthors == null) ?
                       null 
                     : new ReadOnlyCollection(strAuthors);
            } 
            set 
            {
                String[] strAuthors = null; 
                if (value != null)
                {
                    strAuthors = new String[value.Count];
                    value.CopyTo(strAuthors, 0); 
                }
 
                SetQuery(policy_Author, strAuthors); 
            }
        } 

        /// 
        /// Access Title for the image
        ///  
        public String Title
        { 
            get 
            {
                return GetQuery(policy_Title) as String; 
            }
            set
            {
                SetQuery(policy_Title, value); 
            }
        } 
 
        /// 
        /// Access Rating for the image 
        /// 
        public int Rating
        {
            get 
            {
                object rating = GetQuery(policy_Rating); 
 
                if (rating != null && rating.GetType() == typeof(ushort))
                { 
                    return System.Convert.ToInt32(rating, CultureInfo.InvariantCulture);
                }

                return 0; 
            }
            set 
            { 
                SetQuery(policy_Rating, System.Convert.ToUInt16(value, CultureInfo.InvariantCulture));
            } 
        }

        /// 
        /// Access Subject for the image 
        /// 
        public String Subject 
        { 
            get
            { 
                return GetQuery(policy_Subject) as String;
            }
            set
            { 
                SetQuery(policy_Subject, value);
            } 
        } 

        ///  
        /// Access Comment for the image
        /// 
        public String Comment
        { 
            get
            { 
                return GetQuery(policy_Comment) as String; 
            }
            set 
            {
                SetQuery(policy_Comment, value);
            }
        } 

        ///  
        /// Access Date Taken for the image 
        /// 
        public String DateTaken 
        {
            get
            {
                object fileTime = GetQuery(policy_DateTaken); 
                if (fileTime != null && fileTime.GetType() == typeof(System.Runtime.InteropServices.ComTypes.FILETIME))
                { 
                    System.Runtime.InteropServices.ComTypes.FILETIME time = (System.Runtime.InteropServices.ComTypes.FILETIME)fileTime; 
                    DateTime dateTime = DateTime.FromFileTime( (((long)time.dwHighDateTime) << 32) + (uint)time.dwLowDateTime );
                    return dateTime.ToString(); 
                }
                return null;
            }
            set 
            {
                DateTime dt = System.Convert.ToDateTime(value, CultureInfo.InvariantCulture); 
                PROPVARIANT propVar= new PROPVARIANT(); 

                propVar.varType = (ushort)VarEnum.VT_FILETIME; 
                long longFileTime = dt.ToFileTime();
                propVar.filetime.dwLowDateTime = (Int32)longFileTime;
                propVar.filetime.dwHighDateTime = (Int32)((longFileTime >> 32) & 0xFFFFFFFF);
 
                object objValue = propVar.ToObject(_syncObject);
 
                SetQuery(policy_DateTaken, objValue); 
            }
        } 

        /// 
        /// Access Application Name for the image
        ///  
        public String ApplicationName
        { 
            get 
            {
                return GetQuery(policy_ApplicationName) as String; 
            }
            set
            {
                SetQuery(policy_ApplicationName, value); 
            }
        } 
 
        /// 
        /// Access Copyright information for the image 
        /// 
        public String Copyright
        {
            get 
            {
                return GetQuery(policy_Copyright) as String; 
            } 
            set
            { 
                SetQuery(policy_Copyright, value);
            }
        }
 
        /// 
        /// Access Camera Manufacturer for the image 
        ///  
        public String CameraManufacturer
        { 
            get
            {
                return GetQuery(policy_CameraManufacturer) as String;
            } 
            set
            { 
                SetQuery(policy_CameraManufacturer, value); 
            }
        } 

        /// 
        /// Access Camera Model for the image
        ///  
        public String CameraModel
        { 
            get 
            {
                return GetQuery(policy_CameraModel) as String; 
            }
            set
            {
                SetQuery(policy_CameraModel, value); 
            }
        } 
 
        /// 
        /// Access Keywords for the image 
        /// 
        public ReadOnlyCollection Keywords
        {
            get 
            {
                String[] strKeywords = GetQuery(policy_Keywords) as String[]; 
 
                return (strKeywords == null) ?
                       null 
                     : new ReadOnlyCollection(strKeywords);
            }
            set
            { 
                String[] strKeywords = null;
                if (value != null) 
                { 
                    strKeywords = new String[value.Count];
                    value.CopyTo(strKeywords, 0); 
                }

                SetQuery(policy_Keywords, strKeywords);
            } 
        }
 
        #endregion 

        #region Private 

        /// 
        /// Implements common copy code for CloneCore(), CloneCurrentValueCore(), GetAsFrozenCore(), and
        /// GetCurrentValueAsFrozenCore() 
        /// 
        ///  
        ///  
        /// Critical - Accesses unmanaged code eventually
        /// TreatAsSafe - inputs are verified or safe 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void CopyCommon(BitmapMetadata sourceBitmapMetadata)
        { 
            BitmapMetadataBlockWriter blockWriter = sourceBitmapMetadata.BlockWriter;
 
            if (blockWriter == null) 
            {
                // If source is a metadata 
                InitializeFromMetadataWriter(sourceBitmapMetadata._metadataHandle, sourceBitmapMetadata._syncObject);
            }

            if (_metadataHandle == null) 
            {
                if (blockWriter != null) 
                { 
                    InitializeFromBlockWriter(blockWriter, sourceBitmapMetadata._syncObject);
                } 
                else
                {
                    InitializeFromBlockWriter(sourceBitmapMetadata.GuidFormat, false, false);
 
                    SetQuery("/", sourceBitmapMetadata);
                } 
            } 

            _fixedSize = sourceBitmapMetadata._fixedSize; 
        }

        /// 
        /// Critical - Accesses unmanaged code 
        /// TreatAsSafe - inputs are verified or safe
        ///  
        internal Guid GuidFormat 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            {
                Guid guid = new Guid();
 
                EnsureBitmapMetadata();
 
                HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryReader.GetContainerFormat( 
                    _metadataHandle,
                    out guid 
                    ));

                return guid;
            } 
        }
 
        ///  
        /// Critical - Accesses critical resource
        ///  
        internal SafeMILHandle InternalMetadataHandle
        {
            [SecurityCritical]
            get 
            {
                return _metadataHandle; 
            } 
        }
 
        internal object SyncObject
        {
            get
            { 
                return _syncObject;
            } 
        } 

        internal BitmapMetadataBlockWriter BlockWriter 
        {
            get
            {
                return _blockWriter; 
            }
        } 
 
        /// 
        /// Critical - Accesses critical resource 
        /// TreatAsSafe - there are no inputs
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void EnsureBitmapMetadata() 
        {
            ReadPreamble(); 
 
            if (_metadataHandle == null)
            { 
                throw new System.InvalidOperationException(SR.Get(SRID.Image_MetadataInitializationIncomplete));
            }
        }
 
        #endregion
 
        private const String policy_Author = "System.Author"; 
        private const String policy_Title = "System.Title";
        private const String policy_Subject = "System.Subject"; 
        private const String policy_Comment = "System.Comment";
        private const String policy_Keywords = "System.Keywords";
        private const String policy_DateTaken = "System.Photo.DateTaken";
        private const String policy_ApplicationName = "System.ApplicationName"; 
        private const String policy_Copyright = "System.Copyright";
        private const String policy_CameraManufacturer = "System.Photo.CameraManufacturer"; 
        private const String policy_CameraModel = "System.Photo.CameraModel"; 
        private const String policy_Rating = "System.SimpleRating";
 
        /// 
        /// Critical - pointer to an unmanaged object that methods are called on.
        /// 
        [SecurityCritical] 
        private SafeMILHandle _metadataHandle;
 
        private BitmapMetadataBlockWriter _blockWriter; 

        private bool _readOnly; 
        private bool _fixedSize;

        // Stores the last query -- this is for debugging stress failures
        private object _setQueryValue; 
        private string _setQueryString;
 
        private object _syncObject = new Object(); 
    }
 
    #endregion
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, All Rights Reserved
//
//  File: BitmapMetadata.cs 
//
//----------------------------------------------------------------------------- 
 
using System;
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel; 
using System.ComponentModel.Design.Serialization;
using System.Reflection; 
using MS.Internal; 
using MS.Win32.PresentationCore;
using System.Diagnostics; 
using System.Globalization;
using System.Runtime.InteropServices;
using System.Xml;
using System.IO; 
using System.Security;
using System.Security.Permissions; 
using System.Windows.Media.Imaging; 
using System.Windows.Threading;
using System.Text; 
using MS.Internal.PresentationCore;                        // SecurityHelper

#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
 
namespace System.Windows.Media.Imaging
{ 
    #region BitmapMetadata 

    ///  
    /// Metadata Class for BitmapImage.
    /// 
    public partial class BitmapMetadata : ImageMetadata, IEnumerable, IEnumerable
    { 

        //************************************************************* 
        // 
        //  IWICMetadataBlockReader
        // 
        //*************************************************************

        // Guid: IID_IWICMetadataBlockReader
        [ComImport(), 
         Guid("FEAA2A8D-B3F3-43E4-B25C-D1DE990A1AE1"),
         InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 
        internal interface IWICMetadataBlockReader 
        {
            [PreserveSig] 
            int GetContainerFormat(
                out Guid containerFormat
            );
 
            [PreserveSig]
            int GetCount( 
                out UInt32 count 
            );
 
            [PreserveSig]
            int GetReaderByIndex(
                UInt32 index,
                out IntPtr /* IWICMetadataReader */ ppIMetadataReader 
            );
 
            [PreserveSig] 
            int GetEnumerator(
                out IntPtr /* IEnumUnknown */ pIEnumMetadata 
            );
        }

        //************************************************************** 
        //
        //  IWICMetadataBlockWriter 
        // 
        //*************************************************************
 
        // Guid: IID_IWICMetadataBlockWriter
        [ComImport(),
         Guid("08FB9676-B444-41E8-8DBE-6A53A542BFF1"),
         InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 
        internal interface IWICMetadataBlockWriter : IWICMetadataBlockReader
        { 
            [PreserveSig] 
            new int GetContainerFormat(
                out Guid containerFormat 
            );

            [PreserveSig]
            new int GetCount( 
                out UInt32 count
            ); 
 
            [PreserveSig]
            new int GetReaderByIndex( 
                UInt32 index,
                out IntPtr /* IWICMetadataReader */ ppIMetadataReader
            );
 
            [PreserveSig]
            new int GetEnumerator( 
                out IntPtr /* IEnumUnknown */ pIEnumMetadata 
            );
 
            [PreserveSig]
            int InitializeFromBlockReader(
                IntPtr /* IWICMetadataBlockReader */ pIBlockReader
            ); 

            [PreserveSig] 
            int GetWriterByIndex( 
                UInt32 index,
                out IntPtr /* IWICMetadataWriter */ ppIMetadataWriter 
            );

            [PreserveSig]
            int AddWriter( 
                IntPtr /* IWICMetadataWriter */ pIMetadataWriter
            ); 
 
            [PreserveSig]
            int SetWriterByIndex( 
                UInt32 index,
                IntPtr /* IWICMetadataWriter */ pIMetadataWriter
            );
 
            [PreserveSig]
            int RemoveWriterByIndex( 
                UInt32 index 
            );
        } 

        //**************************************************************
        //
        //  BitmapMetadataBlockWriter 
        //
        //************************************************************** 
 
        [ClassInterface(ClassInterfaceType.None)]
        internal sealed class BitmapMetadataBlockWriter : 
            IWICMetadataBlockWriter,
            IWICMetadataBlockReader
        {
            internal BitmapMetadataBlockWriter(Guid containerFormat, bool fixedSize) 
            {
                _fixedSize = fixedSize; 
                _containerFormat = containerFormat; 
                _metadataBlocks = new ArrayList();
            } 

            /// 
            /// Critical - Accesses unmanaged code
            /// TreatAsSafe - inputs are verified or safe 
            /// 
            [SecurityCritical, SecurityTreatAsSafe] 
            internal BitmapMetadataBlockWriter(BitmapMetadataBlockWriter blockWriter, object syncObject) 
            {
                Guid guidVendor = new Guid(MILGuidData.GUID_VendorMicrosoft); 

                _fixedSize = blockWriter._fixedSize;
                _containerFormat = blockWriter._containerFormat;
                _metadataBlocks = new ArrayList(); 

                ArrayList metadataBlocks = blockWriter.MetadataBlocks; 
 
                using (FactoryMaker factoryMaker = new FactoryMaker())
                { 
                    foreach (SafeMILHandle metadataHandle in metadataBlocks)
                    {
                        lock (syncObject)
                        { 
                            IntPtr pIMetadataWriter = IntPtr.Zero;
 
                            try 
                            {
                                HRESULT.Check(UnsafeNativeMethods.WICComponentFactory.CreateMetadataWriterFromReader( 
                                    factoryMaker.ImagingFactoryPtr,
                                    metadataHandle,
                                    ref guidVendor,
                                    out pIMetadataWriter 
                                ));
 
                                SafeMILHandle metadataWriter = new SafeMILHandle(pIMetadataWriter, 0); 
                                pIMetadataWriter = IntPtr.Zero;
 
                                _metadataBlocks.Add(metadataWriter);
                            }
                            finally
                            { 
                                if (pIMetadataWriter != IntPtr.Zero)
                                { 
                                    #pragma warning suppress 6031 // Return value ignored on purpose. 
                                    UnsafeNativeMethods.MILUnknown.Release(pIMetadataWriter);
                                } 
                            }
                        }
                    }
                } 
            }
 
            public int GetContainerFormat( 
                out Guid containerFormat
            ) 
            {
                containerFormat = _containerFormat;

                return MS.Win32.NativeMethods.S_OK; 
            }
 
            public int GetCount( 
                out UInt32 count
            ) 
            {
                count = (UInt32) _metadataBlocks.Count;

                return MS.Win32.NativeMethods.S_OK; 
            }
 
            ///  
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not
            /// publicly exposed or accessible in any way. 
            /// 
            /// 
            /// Critical - Accesses unmanaged code
            ///  
            [SecurityCritical]
            public int GetReaderByIndex( 
                UInt32 index, 
                out IntPtr /* IWICMetadataReader */ pIMetadataReader
            ) 
            {
                if (index >= _metadataBlocks.Count)
                {
                    pIMetadataReader = IntPtr.Zero; 
                    return (int) WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND;
                } 
 
                SafeMILHandle metadataReader = (SafeMILHandle) _metadataBlocks[(int)index];
 
                Guid wicMetadataReader = MILGuidData.IID_IWICMetadataReader;
                return UnsafeNativeMethods.MILUnknown.QueryInterface(
                    metadataReader,
                    ref wicMetadataReader, 
                    out pIMetadataReader);
            } 
 
            /// 
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not 
            /// publicly exposed or accessible in any way.
            /// 
            /// 
            /// Critical - Accesses unmanaged code 
            /// 
            [SecurityCritical] 
            public int GetEnumerator( 
                out IntPtr /* IEnumUnknown */ pIEnumMetadata
            ) 
            {
                BitmapMetadataBlockWriterEnumerator blockEnumerator;

                blockEnumerator = new BitmapMetadataBlockWriterEnumerator(this); 

                pIEnumMetadata = Marshal.GetComInterfaceForObject( 
                    blockEnumerator, 
                    typeof(System.Windows.Media.Imaging.BitmapMetadata.IEnumUnknown));
 
                return MS.Win32.NativeMethods.S_OK;
            }

            ///  
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not
            /// publicly exposed or accessible in any way. 
            ///  
            /// 
            /// Critical - Accesses unmanaged code 
            /// 
            [SecurityCritical]
            public int InitializeFromBlockReader(
                IntPtr /* IWICMetadataBlockReader */ pIBlockReader 
            )
            { 
                Invariant.Assert(pIBlockReader != IntPtr.Zero); 

                int hr = MS.Win32.NativeMethods.S_OK; 

                UInt32 count = 0;

                Guid guidVendor = new Guid(MILGuidData.GUID_VendorMicrosoft); 

                ArrayList metadataBlocks = new ArrayList(); 
 
                hr = UnsafeNativeMethods.WICMetadataBlockReader.GetCount(
                    pIBlockReader, 
                    out count
                );

                if (HRESULT.Succeeded(hr)) 
                {
                    using (FactoryMaker factoryMaker = new FactoryMaker()) 
                    { 
                        for (UInt32 i=0; i
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not
            /// publicly exposed or accessible in any way. 
            /// 
            ///  
            /// Critical - Accesses unmanaged code 
            /// 
            [SecurityCritical] 
            public int GetWriterByIndex(
                UInt32 index,
                out IntPtr  /* IWICMetadataWriter */ pIMetadataWriter
            ) 
            {
                if (index >= _metadataBlocks.Count) 
                { 
                    pIMetadataWriter = IntPtr.Zero;
                    return (int) WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND; 
                }

                SafeMILHandle metadataWriter = (SafeMILHandle) _metadataBlocks[(int)index];
 
                Guid wicMetadataWriter = MILGuidData.IID_IWICMetadataWriter;
                return UnsafeNativeMethods.MILUnknown.QueryInterface( 
                    metadataWriter, 
                    ref wicMetadataWriter,
                    out pIMetadataWriter); 
            }

            /// 
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not 
            /// publicly exposed or accessible in any way.
            ///  
            ///  
            /// Critical - Accesses unmanaged code
            ///  
            [SecurityCritical]
            public int AddWriter(
                IntPtr /* IWICMetadataWriter */ pIMetadataWriter
            ) 
            {
                if (pIMetadataWriter == IntPtr.Zero) 
                { 
                    return (int) WinCodecErrors.WINCODEC_ERR_INVALIDPARAMETER;
                } 

                if (_fixedSize && _metadataBlocks.Count>0)
                {
                    return (int) WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION; 
                }
 
                SafeMILHandle metadataWriter = new SafeMILHandle(pIMetadataWriter, 0); 

                UnsafeNativeMethods.MILUnknown.AddRef(metadataWriter); 

                _metadataBlocks.Add(metadataWriter);

                return MS.Win32.NativeMethods.S_OK; 
            }
 
            ///  
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not
            /// publicly exposed or accessible in any way. 
            /// 
            /// 
            /// Critical - Accesses unmanaged code
            ///  
            [SecurityCritical]
            public int SetWriterByIndex( 
                UInt32 index, 
                IntPtr /* IWICMetadataWriter */ pIMetadataWriter
            ) 
            {
                if (index >= _metadataBlocks.Count)
                {
                    return (int) WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND; 
                }
 
                if (pIMetadataWriter == IntPtr.Zero) 
                {
                    return (int) WinCodecErrors.WINCODEC_ERR_INVALIDPARAMETER; 
                }

                if (_fixedSize)
                { 
                    return (int) WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION;
                } 
 
                SafeMILHandle metadataWriter = new SafeMILHandle(pIMetadataWriter, 0);
 
                UnsafeNativeMethods.MILUnknown.AddRef(metadataWriter);

                _metadataBlocks[(int)index] = metadataWriter;
 
                return MS.Win32.NativeMethods.S_OK;
            } 
 
            public int RemoveWriterByIndex(
                UInt32 index 
            )
            {
                if (index >= _metadataBlocks.Count)
                { 
                    return (int) WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND;
                } 
 
                if (_fixedSize)
                { 
                    return (int) WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION;
                }

                _metadataBlocks.Remove(index); 

                return MS.Win32.NativeMethods.S_OK; 
            } 

            internal ArrayList MetadataBlocks 
            {
                get
                {
                    return _metadataBlocks; 
                }
            } 
 
            private bool _fixedSize;
            private Guid _containerFormat; 
            private ArrayList _metadataBlocks;
        }

        //************************************************************* 
        //
        //  IEnumUnknown 
        // 
        //**************************************************************
 
        // Guid: IID_IEnumUnknown
        [ComImport(),
         Guid("00000100-0000-0000-C000-000000000046"),
         InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 
        internal interface IEnumUnknown
        { 
            [PreserveSig] 
            int Next(
                UInt32 celt, 
                out IntPtr /* IUnknown ** */ rgelt,
                ref UInt32 pceltFetched
            );
 
            [PreserveSig]
            int Skip( 
                UInt32 celt 
            );
 
            [PreserveSig]
            int Reset();

            [PreserveSig] 
            int Clone(
                ref IntPtr /* IEnumString ** */ ppEnum 
            ); 
        }
 
        //*************************************************************
        //
        //  BitmapMetadataBlockWriterEnumerator
        // 
        //*************************************************************
 
        [ClassInterface(ClassInterfaceType.None)] 
        internal sealed class BitmapMetadataBlockWriterEnumerator : IEnumUnknown
        { 
            internal BitmapMetadataBlockWriterEnumerator(
                BitmapMetadataBlockWriter blockWriter
            )
            { 
                Debug.Assert(blockWriter != null);
                Debug.Assert(blockWriter.MetadataBlocks != null); 
 
                _metadataBlocks = blockWriter.MetadataBlocks;
                _index = 0; 
            }

            /// 
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not 
            /// publicly exposed or accessible in any way.
            ///  
            ///  
            /// Critical - Accesses unmanaged code
            ///  
            [SecurityCritical]
            public int Next(
                UInt32 celt,
                out IntPtr /* IUnknown ** */ rgelt, 
                ref UInt32 pceltFetched
            ) 
            { 
                // This implementation only supports single enumeration.
                if (celt > 1) 
                {
                    rgelt = IntPtr.Zero;
                    pceltFetched = 0;
                    return (int) WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION; 
                }
 
                if (_index >= _metadataBlocks.Count || celt == 0) 
                {
                    rgelt = IntPtr.Zero; 
                    pceltFetched = 0;
                    return MS.Win32.NativeMethods.S_FALSE;
                }
                else 
                {
                    SafeMILHandle metadataHandle = (SafeMILHandle) _metadataBlocks[(int)_index]; 
 
                    Guid wicMetadataReader = MILGuidData.IID_IWICMetadataReader;
                    int hr = UnsafeNativeMethods.MILUnknown.QueryInterface( 
                        metadataHandle,
                        ref wicMetadataReader,
                        out rgelt);
 
                    if (HRESULT.Succeeded(hr))
                    { 
                        pceltFetched = 1; 
                        _index++;
                    } 

                    return hr;
                }
            } 

            ///  
            /// Critical - Accesses unmanaged code 
            /// TreatAsSafe - inputs are verified or safe
            ///  
            [SecurityCritical, SecurityTreatAsSafe]
            public int Skip(
                UInt32 celt
            ) 
            {
                UInt32 newIndex = _index + celt; 
 
                if (newIndex > _metadataBlocks.Count)
                { 
                    _index = (uint) _metadataBlocks.Count;
                    return MS.Win32.NativeMethods.S_FALSE;
                }
                else 
                {
                    _index += celt; 
                    return MS.Win32.NativeMethods.S_OK; 
                }
            } 

            /// 
            /// Critical - Accesses unmanaged code
            /// TreatAsSafe - inputs are verified or safe 
            /// 
            [SecurityCritical, SecurityTreatAsSafe] 
            public int Reset() 
            {
                _index = 0; 
                return MS.Win32.NativeMethods.S_OK;
            }

            ///  
            /// This method is part of an interface that is only called by way of WindowsCodec.  It is not
            /// publicly exposed or accessible in any way. 
            ///  
            /// 
            /// Critical - Accesses unmanaged code 
            /// 
            [SecurityCritical]
            public int Clone(
                ref IntPtr /* IEnumUnknown ** */ ppEnum 
            )
            { 
                ppEnum = IntPtr.Zero; 
                return (int) WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION;
            } 

            private ArrayList _metadataBlocks;
            private UInt32 _index;
        } 

        #region Constructors 
 
        /// 
        /// 
        /// 
        /// 
        /// Critical - Accesses unmanaged code
        /// PublicOK - inputs are verified or safe 
        /// 
        [SecurityCritical] 
        public BitmapMetadata(String containerFormat) 
        {
            if (containerFormat == null) 
            {
                throw new System.ArgumentNullException("containerFormat");
            }
 
            Guid guid = new Guid();
 
            // Find the length of the string needed 
            HRESULT.Check(UnsafeNativeMethods.WICCodec.WICMapShortNameToGuid(
                containerFormat, 
                ref guid
                ));

            Init(guid, false, false); 
        }
 
        ///  
        ///
        ///  
        /// 
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - constructor is safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal BitmapMetadata() 
        { 
            _metadataHandle = null;
            _readOnly = true; 
            _fixedSize = false;
            _blockWriter = null;
        }
 
        /// 
        /// 
        ///  
        /// 
        /// Critical - Accesses critical resource 
        /// 
        [SecurityCritical]
        internal BitmapMetadata(
            SafeMILHandle metadataHandle, 
            bool readOnly,
            bool fixedSize, 
            object syncObject 
        )
        { 
            _metadataHandle = metadataHandle;
            _readOnly = readOnly;
            _fixedSize = fixedSize;
            _blockWriter = null; 
            _syncObject = syncObject;
        } 
 
        /// 
        /// 
        /// 
        internal BitmapMetadata(BitmapMetadata bitmapMetadata)
        {
            if (bitmapMetadata == null) 
            {
                throw new System.ArgumentNullException("bitmapMetadata"); 
            } 

            Init(bitmapMetadata.GuidFormat, false, bitmapMetadata._fixedSize); 
        }

        /// 
        /// 
        /// 
        ///  
        /// Critical - Accesses unmanaged code 
        /// TreatAsSafe - inputs are verified or safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void Init(Guid containerFormat, bool readOnly, bool fixedSize)
        {
            int hr = 0; 
            IntPtr /* IWICMetadataQueryWriter */ queryWriter = IntPtr.Zero;
 
            using (FactoryMaker factoryMaker = new FactoryMaker()) 
            {
                Guid vendorMicrosoft = new Guid(MILGuidData.GUID_VendorMicrosoft); 

                // If it's a metadata format, create a Query Writer to wrap it.
                hr = UnsafeNativeMethods.WICImagingFactory.CreateQueryWriter(
                    factoryMaker.ImagingFactoryPtr, 
                    ref containerFormat,
                    ref vendorMicrosoft, 
                    out queryWriter 
                    );
            } 

            if (HRESULT.Succeeded(hr))
            {
                _readOnly = readOnly; 
                _fixedSize = fixedSize;
                _blockWriter = null; 
 
                _metadataHandle = new SafeMILHandle(queryWriter, 0);
                _syncObject = _metadataHandle; 
            }
            else
            {
                InitializeFromBlockWriter(containerFormat, readOnly, fixedSize); 
            }
        } 
 
        /// 
        /// 
        /// 
        /// 
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - inputs are verified or safe 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private void InitializeFromBlockWriter(Guid containerFormat, bool readOnly, bool fixedSize) 
        {
            IntPtr /* IWICMetadataBlockWriter */ blockWriter = IntPtr.Zero; 
            IntPtr /* IWICMetadataQueryWriter */ queryWriter = IntPtr.Zero;

            using (FactoryMaker factoryMaker = new FactoryMaker())
            { 
                try
                { 
                    // Otherwise, simulate a metadata block writer for this imaging container format. 
                    _blockWriter = new BitmapMetadataBlockWriter(containerFormat, fixedSize);
 
                    blockWriter = Marshal.GetComInterfaceForObject(
                        _blockWriter,
                        typeof(System.Windows.Media.Imaging.BitmapMetadata.IWICMetadataBlockWriter));
 
                    HRESULT.Check(UnsafeNativeMethods.WICComponentFactory.CreateQueryWriterFromBlockWriter(
                        factoryMaker.ImagingFactoryPtr, 
                        blockWriter, 
                        ref queryWriter
                    )); 

                    _readOnly = readOnly;
                    _fixedSize = fixedSize;
 
                    _metadataHandle = new SafeMILHandle(queryWriter, 0);
                    queryWriter = IntPtr.Zero; 
 
                    _syncObject = _metadataHandle;
                } 
                finally
                {
                    if (blockWriter != IntPtr.Zero)
                    { 
                        #pragma warning suppress 6031 // Return value ignored on purpose.
                        UnsafeNativeMethods.MILUnknown.Release(blockWriter); 
                    } 
                    if (queryWriter != IntPtr.Zero)
                    { 
                        #pragma warning suppress 6031 // Return value ignored on purpose.
                        UnsafeNativeMethods.MILUnknown.Release(queryWriter);
                    }
                } 
            }
        } 
 
        /// 
        /// 
        /// 
        /// 
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - inputs are verified or safe 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private void InitializeFromBlockWriter(BitmapMetadataBlockWriter sourceBlockWriter, object syncObject) 
        {
            IntPtr /* IWICMetadataBlockWriter */ blockWriter = IntPtr.Zero; 
            IntPtr /* IWICMetadataQueryWriter */ queryWriter = IntPtr.Zero;

            using (FactoryMaker factoryMaker = new FactoryMaker())
            { 
                try
                { 
                    // Otherwise, simulate a metadata block writer for this imaging container format. 
                    _blockWriter = new BitmapMetadataBlockWriter(sourceBlockWriter, syncObject);
 
                    blockWriter = Marshal.GetComInterfaceForObject(
                        _blockWriter,
                        typeof(System.Windows.Media.Imaging.BitmapMetadata.IWICMetadataBlockWriter));
 
                    HRESULT.Check(UnsafeNativeMethods.WICComponentFactory.CreateQueryWriterFromBlockWriter(
                        factoryMaker.ImagingFactoryPtr, 
                        blockWriter, 
                        ref queryWriter
                    )); 

                    _readOnly = false;
                    _fixedSize = false;
 
                    _metadataHandle = new SafeMILHandle(queryWriter, 0);
                    queryWriter = IntPtr.Zero; 
 
                    _syncObject = _metadataHandle;
                } 
                finally
                {
                    if (blockWriter != IntPtr.Zero)
                    { 
                        #pragma warning suppress 6031 // Return value ignored on purpose.
                        UnsafeNativeMethods.MILUnknown.Release(blockWriter); 
                    } 
                    if (queryWriter != IntPtr.Zero)
                    { 
                        #pragma warning suppress 6031 // Return value ignored on purpose.
                        UnsafeNativeMethods.MILUnknown.Release(queryWriter);
                    }
                } 
            }
        } 
 
        /// 
        /// 
        /// 
        /// 
        /// Critical - Accesses unmanaged code and critical resource
        ///  
        [SecurityCritical]
        private void InitializeFromMetadataWriter(SafeMILHandle metadataHandle, object syncObject) 
        { 
            int hr;
            IntPtr queryWriter = IntPtr.Zero; 

            Guid guidVendor = new Guid(MILGuidData.GUID_VendorMicrosoft);

            // Create a query writer for this metadata format 
            try
            { 
                using (FactoryMaker factoryMaker = new FactoryMaker()) 
                {
                    lock (syncObject) 
                    {
                        hr = UnsafeNativeMethods.WICImagingFactory.CreateQueryWriterFromReader(
                            factoryMaker.ImagingFactoryPtr,
                            metadataHandle, 
                            ref guidVendor,
                            out queryWriter); 
                    } 
                }
 
                if (HRESULT.Succeeded(hr))
                {
                    _readOnly = false;
                    _fixedSize = false; 
                    _blockWriter = null;
 
                    _metadataHandle = new SafeMILHandle(queryWriter, 0); 
                    queryWriter = IntPtr.Zero;
 
                    _syncObject = _metadataHandle;
                }
                else if (!HRESULT.IsWindowsCodecError(hr))
                { 
                    HRESULT.Check(hr);
                } 
            } 
            finally
            { 
                if (queryWriter != IntPtr.Zero)
                {
                    #pragma warning suppress 6031 // Return value ignored on purpose.
                    UnsafeNativeMethods.MILUnknown.Release(queryWriter); 
                }
            } 
        } 

        #endregion 

        #region Freezable

        ///  
        ///     Shadows inherited Clone() with a strongly typed
        ///     version for convenience. 
        ///  
        public new BitmapMetadata Clone()
        { 
            return (BitmapMetadata)base.Clone();
        }

        ///  
        /// Implementation of Freezable.CreateInstanceCore.
        ///  
        /// The new Freezable. 
        protected override Freezable CreateInstanceCore()
        { 
            return new BitmapMetadata();
        }

        ///  
        /// Implementation of Freezable.CloneCore.
        ///  
        protected override void CloneCore(Freezable sourceFreezable) 
        {
            BitmapMetadata sourceBitmapMetadata = (BitmapMetadata) sourceFreezable; 
            base.CloneCore(sourceFreezable);

            CopyCommon(sourceBitmapMetadata);
        } 

        ///  
        /// Implementation of Freezable.CloneCurrentValueCore. 
        /// 
        protected override void CloneCurrentValueCore(Freezable sourceFreezable) 
        {
            BitmapMetadata sourceBitmapMetadata = (BitmapMetadata)sourceFreezable;
            base.CloneCurrentValueCore(sourceFreezable);
 
            CopyCommon(sourceBitmapMetadata);
        } 
 

        ///  
        /// Implementation of Freezable.GetAsFrozenCore.
        /// 
        protected override void GetAsFrozenCore(Freezable sourceFreezable)
        { 
            BitmapMetadata sourceBitmapMetadata = (BitmapMetadata)sourceFreezable;
            base.GetAsFrozenCore(sourceFreezable); 
 
            CopyCommon(sourceBitmapMetadata);
        } 


        /// 
        /// Implementation of Freezable.GetCurrentValueAsFrozenCore. 
        /// 
        protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable) 
        { 
            BitmapMetadata sourceBitmapMetadata = (BitmapMetadata)sourceFreezable;
            base.GetCurrentValueAsFrozenCore(sourceFreezable); 

            CopyCommon(sourceBitmapMetadata);
        }
 
        #endregion
 
        ///  
        ///
        ///  
        /// 
        /// Critical - Accesses unmanaged code
        /// PublicOK - inputs are verified or safe
        ///  
        public String Format
        { 
            [SecurityCritical] 
            get
            { 
                EnsureBitmapMetadata();
                StringBuilder format = null;
                UInt32 length = 0;
 
                // This calls EnsureBitmapMetadata()
                Guid guid = GuidFormat; 
 
                // Find the length of the string needed
                lock (_syncObject) 
                {
                    HRESULT.Check(UnsafeNativeMethods.WICCodec.WICMapGuidToShortName(
                        ref guid,
                        0, 
                        format,
                        ref length 
                        )); 

                    Debug.Assert(length >= 0); 

                    // get the string back
                    if (length > 0)
                    { 
                        format = new StringBuilder((int)length);
 
                        HRESULT.Check(UnsafeNativeMethods.WICCodec.WICMapGuidToShortName( 
                            ref guid,
                            length, 
                            format,
                            ref length
                            ));
                    } 
                }
 
                return format.ToString(); 
            }
        } 

        /// 
        ///
        ///  
        /// 
        /// Critical - Accesses unmanaged code 
        /// PublicOK - inputs are verified or safe 
        /// 
        public String Location 
        {
            [SecurityCritical]
            get
            { 
                StringBuilder location = null;
                UInt32 length = 0; 
 
                EnsureBitmapMetadata();
 
                // Find the length of the string needed
                lock (_syncObject)
                {
                    HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryReader.GetLocation( 
                        _metadataHandle,
                        0, 
                        location, 
                        out length
                        )); 

                    Debug.Assert(length >= 0);

                    // get the string back 
                    if (length > 0)
                    { 
                        location = new StringBuilder((int)length); 

                        HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryReader.GetLocation( 
                            _metadataHandle,
                            length,
                            location,
                            out length 
                            ));
                    } 
                } 

                return location.ToString(); 
            }
        }

        #region Properties 

        ///  
        /// 
        /// 
        public bool IsReadOnly 
        {
            get
            {
                EnsureBitmapMetadata(); 

                return _readOnly; 
            } 
        }
 
        /// 
        ///
        /// 
        public bool IsFixedSize 
        {
            get 
            { 
                EnsureBitmapMetadata();
 
                return _fixedSize;
            }
        }
 
        #endregion
 
        #region Query Methods 

        ///  
        ///
        /// 
        /// 
        /// Critical - Accesses unmanaged code 
        /// PublicOK - inputs are verified or safe
        ///  
        [SecurityCritical] 
        public void SetQuery(String query, object value)
        { 
            WritePreamble();

            if (query == null)
            { 
                throw new System.ArgumentNullException("query");
            } 
 
            if (value == null)
            { 
                throw new System.ArgumentNullException("value");
            }

            if (_readOnly) 
            {
                throw new System.InvalidOperationException(SR.Get(SRID.Image_MetadataReadOnly)); 
            } 

            // Store these for debugging stress failures. 
            _setQueryString = query;
            _setQueryValue = value;

            EnsureBitmapMetadata(); 

            PROPVARIANT propVar = new PROPVARIANT(); 
 
            try
            { 
                propVar.Init(value);

                if (propVar.RequiresSyncObject)
                { 
                    BitmapMetadata metadata = value as BitmapMetadata;
                    Invariant.Assert(metadata != null); 
 
                    #pragma warning suppress 6506 // Invariant.Assert(metadata != null);
                    metadata.VerifyAccess(); 

                    #pragma warning suppress 6506 // Invariant.Assert(metadata != null);
                    lock (metadata._syncObject)
                    { 
                        lock (_syncObject)
                        { 
                            HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryWriter.SetMetadataByName( 
                                _metadataHandle,
                                query, 
                                ref propVar
                                ));
                        }
                    } 
                }
                else 
                { 
                    lock (_syncObject)
                    { 
                        HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryWriter.SetMetadataByName(
                            _metadataHandle,
                            query,
                            ref propVar 
                            ));
                    } 
                } 
            }
            finally 
            {
                propVar.Clear();
            }
 
            WritePostscript();
        } 
 
        /// 
        /// 
        /// 
        /// 
        /// Critical - Accesses unmanaged code
        /// PublicOK - inputs are verified or safe 
        /// 
        [SecurityCritical] 
        public object GetQuery(String query) 
        {
            int hr; 

            if (query == null)
            {
                throw new System.ArgumentNullException("query"); 
            }
 
            EnsureBitmapMetadata(); 

            PROPVARIANT propVar = new PROPVARIANT(); 

            try
            {
                propVar.Init(null); 

                lock (_syncObject) 
                { 
                    hr = UnsafeNativeMethods.WICMetadataQueryReader.GetMetadataByName(
                        _metadataHandle, 
                        query,
                        ref propVar
                        );
                } 

                if (hr != (int)WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND) 
                { 
                    HRESULT.Check(hr);
 
                    object objValue = propVar.ToObject(_syncObject);

                    if (IsFrozenInternal)
                    { 
                        BitmapMetadata metadata = objValue as BitmapMetadata;
 
                        if (metadata != null) 
                        {
                            metadata.Freeze(); 
                        }
                    }

                    return objValue; 
                }
            } 
            finally 
            {
                propVar.Clear(); 
            }

            return null;
        } 

        ///  
        /// 
        /// 
        ///  
        /// Critical - Accesses unmanaged code
        /// PublicOK - inputs are verified or safe
        /// 
        [SecurityCritical] 
        public void RemoveQuery(String query)
        { 
            int hr; 

            WritePreamble(); 

            if (query == null)
            {
                throw new System.ArgumentNullException("query"); 
            }
 
            if (_readOnly) 
            {
                throw new System.InvalidOperationException(SR.Get(SRID.Image_MetadataReadOnly)); 
            }

            EnsureBitmapMetadata();
 
            lock (_syncObject)
            { 
                hr = UnsafeNativeMethods.WICMetadataQueryWriter.RemoveMetadataByName( 
                    _metadataHandle,
                    query 
                    );
            }

            if (hr != (int)WinCodecErrors.WINCODEC_ERR_PROPERTYNOTFOUND) 
            {
                HRESULT.Check(hr); 
            } 
        }
 
        /// 
        ///
        /// 
        ///  
        /// Critical - Accesses unmanaged code eventually
        /// TreatAsSafe - inputs are verified or safe 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        IEnumerator IEnumerable.GetEnumerator() 
        {
            EnsureBitmapMetadata();

            return new BitmapMetadataEnumerator(_metadataHandle); 
        }
 
        ///  
        ///
        ///  
        /// 
        /// Critical - Accesses unmanaged code eventually
        /// TreatAsSafe - inputs are verified or safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        IEnumerator IEnumerable.GetEnumerator() 
        { 
            EnsureBitmapMetadata();
 
            return new BitmapMetadataEnumerator(_metadataHandle);
        }

        ///  
        ///
        ///  
        ///  
        /// Critical - Accesses unmanaged code
        /// PublicOK - inputs are verified or safe 
        /// 
        [SecurityCritical]
        public bool ContainsQuery(String query)
        { 
            int hr;
 
            if (query == null) 
            {
                throw new System.ArgumentNullException("query"); 
            }

            EnsureBitmapMetadata();
 
            lock (_syncObject)
            { 
                hr = UnsafeNativeMethods.WICMetadataQueryReader.ContainsMetadataByName( 
                    _metadataHandle,
                    query, 
                    IntPtr.Zero
                    );
            }
 
            if (HRESULT.IsWindowsCodecError(hr))
            { 
                return false; 
            }
            else 
            {
                HRESULT.Check(hr);
            }
 
            return true;
        } 
 
        #endregion
 
        #region Policy-driven Properties

        /// 
        /// Access Author for the image 
        /// 
        public ReadOnlyCollection Author 
        { 
            get
            { 
                String[] strAuthors = GetQuery(policy_Author) as String[];

                return (strAuthors == null) ?
                       null 
                     : new ReadOnlyCollection(strAuthors);
            } 
            set 
            {
                String[] strAuthors = null; 
                if (value != null)
                {
                    strAuthors = new String[value.Count];
                    value.CopyTo(strAuthors, 0); 
                }
 
                SetQuery(policy_Author, strAuthors); 
            }
        } 

        /// 
        /// Access Title for the image
        ///  
        public String Title
        { 
            get 
            {
                return GetQuery(policy_Title) as String; 
            }
            set
            {
                SetQuery(policy_Title, value); 
            }
        } 
 
        /// 
        /// Access Rating for the image 
        /// 
        public int Rating
        {
            get 
            {
                object rating = GetQuery(policy_Rating); 
 
                if (rating != null && rating.GetType() == typeof(ushort))
                { 
                    return System.Convert.ToInt32(rating, CultureInfo.InvariantCulture);
                }

                return 0; 
            }
            set 
            { 
                SetQuery(policy_Rating, System.Convert.ToUInt16(value, CultureInfo.InvariantCulture));
            } 
        }

        /// 
        /// Access Subject for the image 
        /// 
        public String Subject 
        { 
            get
            { 
                return GetQuery(policy_Subject) as String;
            }
            set
            { 
                SetQuery(policy_Subject, value);
            } 
        } 

        ///  
        /// Access Comment for the image
        /// 
        public String Comment
        { 
            get
            { 
                return GetQuery(policy_Comment) as String; 
            }
            set 
            {
                SetQuery(policy_Comment, value);
            }
        } 

        ///  
        /// Access Date Taken for the image 
        /// 
        public String DateTaken 
        {
            get
            {
                object fileTime = GetQuery(policy_DateTaken); 
                if (fileTime != null && fileTime.GetType() == typeof(System.Runtime.InteropServices.ComTypes.FILETIME))
                { 
                    System.Runtime.InteropServices.ComTypes.FILETIME time = (System.Runtime.InteropServices.ComTypes.FILETIME)fileTime; 
                    DateTime dateTime = DateTime.FromFileTime( (((long)time.dwHighDateTime) << 32) + (uint)time.dwLowDateTime );
                    return dateTime.ToString(); 
                }
                return null;
            }
            set 
            {
                DateTime dt = System.Convert.ToDateTime(value, CultureInfo.InvariantCulture); 
                PROPVARIANT propVar= new PROPVARIANT(); 

                propVar.varType = (ushort)VarEnum.VT_FILETIME; 
                long longFileTime = dt.ToFileTime();
                propVar.filetime.dwLowDateTime = (Int32)longFileTime;
                propVar.filetime.dwHighDateTime = (Int32)((longFileTime >> 32) & 0xFFFFFFFF);
 
                object objValue = propVar.ToObject(_syncObject);
 
                SetQuery(policy_DateTaken, objValue); 
            }
        } 

        /// 
        /// Access Application Name for the image
        ///  
        public String ApplicationName
        { 
            get 
            {
                return GetQuery(policy_ApplicationName) as String; 
            }
            set
            {
                SetQuery(policy_ApplicationName, value); 
            }
        } 
 
        /// 
        /// Access Copyright information for the image 
        /// 
        public String Copyright
        {
            get 
            {
                return GetQuery(policy_Copyright) as String; 
            } 
            set
            { 
                SetQuery(policy_Copyright, value);
            }
        }
 
        /// 
        /// Access Camera Manufacturer for the image 
        ///  
        public String CameraManufacturer
        { 
            get
            {
                return GetQuery(policy_CameraManufacturer) as String;
            } 
            set
            { 
                SetQuery(policy_CameraManufacturer, value); 
            }
        } 

        /// 
        /// Access Camera Model for the image
        ///  
        public String CameraModel
        { 
            get 
            {
                return GetQuery(policy_CameraModel) as String; 
            }
            set
            {
                SetQuery(policy_CameraModel, value); 
            }
        } 
 
        /// 
        /// Access Keywords for the image 
        /// 
        public ReadOnlyCollection Keywords
        {
            get 
            {
                String[] strKeywords = GetQuery(policy_Keywords) as String[]; 
 
                return (strKeywords == null) ?
                       null 
                     : new ReadOnlyCollection(strKeywords);
            }
            set
            { 
                String[] strKeywords = null;
                if (value != null) 
                { 
                    strKeywords = new String[value.Count];
                    value.CopyTo(strKeywords, 0); 
                }

                SetQuery(policy_Keywords, strKeywords);
            } 
        }
 
        #endregion 

        #region Private 

        /// 
        /// Implements common copy code for CloneCore(), CloneCurrentValueCore(), GetAsFrozenCore(), and
        /// GetCurrentValueAsFrozenCore() 
        /// 
        ///  
        ///  
        /// Critical - Accesses unmanaged code eventually
        /// TreatAsSafe - inputs are verified or safe 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void CopyCommon(BitmapMetadata sourceBitmapMetadata)
        { 
            BitmapMetadataBlockWriter blockWriter = sourceBitmapMetadata.BlockWriter;
 
            if (blockWriter == null) 
            {
                // If source is a metadata 
                InitializeFromMetadataWriter(sourceBitmapMetadata._metadataHandle, sourceBitmapMetadata._syncObject);
            }

            if (_metadataHandle == null) 
            {
                if (blockWriter != null) 
                { 
                    InitializeFromBlockWriter(blockWriter, sourceBitmapMetadata._syncObject);
                } 
                else
                {
                    InitializeFromBlockWriter(sourceBitmapMetadata.GuidFormat, false, false);
 
                    SetQuery("/", sourceBitmapMetadata);
                } 
            } 

            _fixedSize = sourceBitmapMetadata._fixedSize; 
        }

        /// 
        /// Critical - Accesses unmanaged code 
        /// TreatAsSafe - inputs are verified or safe
        ///  
        internal Guid GuidFormat 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            {
                Guid guid = new Guid();
 
                EnsureBitmapMetadata();
 
                HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryReader.GetContainerFormat( 
                    _metadataHandle,
                    out guid 
                    ));

                return guid;
            } 
        }
 
        ///  
        /// Critical - Accesses critical resource
        ///  
        internal SafeMILHandle InternalMetadataHandle
        {
            [SecurityCritical]
            get 
            {
                return _metadataHandle; 
            } 
        }
 
        internal object SyncObject
        {
            get
            { 
                return _syncObject;
            } 
        } 

        internal BitmapMetadataBlockWriter BlockWriter 
        {
            get
            {
                return _blockWriter; 
            }
        } 
 
        /// 
        /// Critical - Accesses critical resource 
        /// TreatAsSafe - there are no inputs
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void EnsureBitmapMetadata() 
        {
            ReadPreamble(); 
 
            if (_metadataHandle == null)
            { 
                throw new System.InvalidOperationException(SR.Get(SRID.Image_MetadataInitializationIncomplete));
            }
        }
 
        #endregion
 
        private const String policy_Author = "System.Author"; 
        private const String policy_Title = "System.Title";
        private const String policy_Subject = "System.Subject"; 
        private const String policy_Comment = "System.Comment";
        private const String policy_Keywords = "System.Keywords";
        private const String policy_DateTaken = "System.Photo.DateTaken";
        private const String policy_ApplicationName = "System.ApplicationName"; 
        private const String policy_Copyright = "System.Copyright";
        private const String policy_CameraManufacturer = "System.Photo.CameraManufacturer"; 
        private const String policy_CameraModel = "System.Photo.CameraModel"; 
        private const String policy_Rating = "System.SimpleRating";
 
        /// 
        /// Critical - pointer to an unmanaged object that methods are called on.
        /// 
        [SecurityCritical] 
        private SafeMILHandle _metadataHandle;
 
        private BitmapMetadataBlockWriter _blockWriter; 

        private bool _readOnly; 
        private bool _fixedSize;

        // Stores the last query -- this is for debugging stress failures
        private object _setQueryValue; 
        private string _setQueryString;
 
        private object _syncObject = new Object(); 
    }
 
    #endregion
}

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