BitmapDecoder.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / System / Windows / Media / Imaging / BitmapDecoder.cs / 1 / BitmapDecoder.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2003
//
//  File: BitmapDecoder.cs 
//
//----------------------------------------------------------------------------- 
#pragma warning disable 1634, 1691 // Allow suppression of certain presharp messages 

using System; 
using System.IO;
using System.IO.Packaging;
using System.Collections;
using System.Collections.Generic; 
using System.ComponentModel;
using System.ComponentModel.Design.Serialization; 
using System.Collections.ObjectModel; 
using System.Reflection;
using System.Security; 
using System.Security.Permissions;
using System.Text.RegularExpressions;
using MS.Internal;
using MS.Internal.AppModel; 
using MS.Win32.PresentationCore;
using Microsoft.Win32.SafeHandles; 
using System.Diagnostics; 
using System.Windows.Media;
using System.Globalization; 
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Threading;
using System.Windows.Media.Imaging; 
using MS.Internal.PresentationCore;                        // SecurityHelper
using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID; 
using System.Net;
using System.Net.Cache; 
using System.Text;

namespace System.Windows.Media.Imaging
{ 
    #region BitmapDecoder
 
    ///  
    /// BitmapDecoder is a container for bitmap frames.  Each bitmap frame is an BitmapFrame.
    /// Any BitmapFrame it returns are frozen 
    /// be immutable.
    /// 
    public abstract class BitmapDecoder : DispatcherObject
    { 
        #region Constructors
 
        ///  
        ///     Critical: This code has critical static variables isImageDisabledInitialized
        ///     TreatAsASafe: The variables are not exposed 
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        static BitmapDecoder()
        { 
            isImageDisabledInitialized = false;
        } 
        ///  
        /// Default constructor
        ///  
        protected BitmapDecoder()
        {
        }
 
        /// 
        /// Internal constructor 
        ///  
        internal BitmapDecoder(bool isBuiltIn)
        { 
            _isBuiltInDecoder = isBuiltIn;
        }

        ///  
        /// Constructor
        ///  
        ///  
        /// Critical - access critical resource
        ///  
        [SecurityCritical]
        internal BitmapDecoder(
            Uri bitmapUri,
            BitmapCreateOptions createOptions, 
            BitmapCacheOption cacheOption,
            Guid expectedClsId 
            ) 
        {
            Guid clsId = Guid.Empty; 
            bool isOriginalWritable = false;

            if (bitmapUri == null)
            { 
                throw new ArgumentNullException("bitmapUri");
            } 
 
            if ((createOptions & BitmapCreateOptions.IgnoreImageCache) != 0)
            { 
                ImagingCache.RemoveFromDecoderCache(bitmapUri);
            }

            BitmapDecoder decoder = CheckCache(bitmapUri, out clsId); 
            if (decoder != null)
            { 
                _decoderHandle = decoder.InternalDecoder; 
            }
            else 
            {
                _decoderHandle = SetupDecoderFromUriOrStream(
                    bitmapUri,
                    null, 
                    cacheOption,
                    out clsId, 
                    out isOriginalWritable, 
                    out _uriStream,
                    out _unmanagedMemoryStream, 
                    out _safeFilehandle
                    );
            }
 
            if (clsId != expectedClsId)
            { 
                throw new FileFormatException(bitmapUri, SR.Get(SRID.Image_CantDealWithUri)); 
            }
 
            _uri = bitmapUri;
            _createOptions = createOptions;
            _cacheOption = cacheOption;
            _syncObject = _decoderHandle; 
            _isOriginalWritable = isOriginalWritable;
            Initialize(decoder); 
        } 

        ///  
        /// Constructor
        /// 
        /// 
        /// Critical - access critical resource 
        /// 
        [SecurityCritical] 
        internal BitmapDecoder( 
            Stream bitmapStream,
            BitmapCreateOptions createOptions, 
            BitmapCacheOption cacheOption,
            Guid expectedClsId
            )
        { 
            Guid clsId = Guid.Empty;
            bool isOriginalWritable = false; 
 
            if (bitmapStream == null)
            { 
                throw new ArgumentNullException("bitmapStream");
            }

            _decoderHandle = SetupDecoderFromUriOrStream( 
                null,
                bitmapStream, 
                cacheOption, 
                out clsId,
                out isOriginalWritable, 
                out _uriStream,
                out _unmanagedMemoryStream,
                out _safeFilehandle
                ); 

            if (clsId != Guid.Empty && clsId != expectedClsId) 
            { 
                throw new FileFormatException(null, SR.Get(SRID.Image_CantDealWithStream));
            } 

            _stream = bitmapStream;
            _createOptions = createOptions;
            _cacheOption = cacheOption; 
            _syncObject = _decoderHandle;
            _isOriginalWritable = isOriginalWritable; 
            Initialize(null); 
        }
 
        /// 
        /// Constructor
        /// 
        ///  
        /// Critical - access critical resources
        /// TreatAsSafe - All inputs verified 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal BitmapDecoder( 
            SafeMILHandle decoderHandle,
            BitmapDecoder decoder,
            Uri baseUri,
            Uri uri, 
            Stream stream,
            BitmapCreateOptions createOptions, 
            BitmapCacheOption cacheOption, 
            bool insertInDecoderCache,
            bool isOriginalWritable, 
            Stream uriStream,
            UnmanagedMemoryStream unmanagedMemoryStream,
            SafeFileHandle safeFilehandle
            ) 
        {
            _decoderHandle = decoderHandle; 
            _baseUri = baseUri; 
            _uri = uri;
            _stream = stream; 
            _createOptions = createOptions;
            _cacheOption = cacheOption;
            _syncObject = decoderHandle;
            _shouldCacheDecoder = insertInDecoderCache; 
            _isOriginalWritable = isOriginalWritable;
            _uriStream = uriStream; 
            _unmanagedMemoryStream = unmanagedMemoryStream; 
            _safeFilehandle = safeFilehandle;
 
            Initialize(decoder);
        }

        ///  
        /// Create BitmapDecoder from the uri or stream. If both are specified, the uri
        /// is chosen. 
        ///  
        /// 
        /// Critical - Unmanaged code will eventually create a COM object, need to secure it 
        /// TreatAsSafe - All inputs verified
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal static BitmapDecoder CreateFromUriOrStream( 
            Uri baseUri,
            Uri uri, 
            Stream stream, 
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption, 
            RequestCachePolicy uriCachePolicy,
            bool insertInDecoderCache
            )
        { 
            Guid clsId = Guid.Empty;
            bool isOriginalWritable = false; 
            SafeMILHandle decoderHandle = null; 
            BitmapDecoder cachedDecoder = null;
            Uri finalUri = null; 
            Stream uriStream = null;
            UnmanagedMemoryStream unmanagedMemoryStream = null;
            SafeFileHandle safeFilehandle = null;
 
            // check to ensure that images are allowed in partial trust
            DemandIfImageBlocked(); 
 
            if (uri != null)
            { 
                finalUri = (baseUri != null) ?
                               System.Windows.Navigation.BaseUriHelper.GetResolvedUri(baseUri, uri) :
                               uri;
 
                if (insertInDecoderCache)
                { 
                    if ((createOptions & BitmapCreateOptions.IgnoreImageCache) != 0) 
                    {
                        ImagingCache.RemoveFromDecoderCache(finalUri); 
                    }

                    cachedDecoder = CheckCache(
                        finalUri, 
                        out clsId
                        ); 
                } 
            }
 
            // try to retrieve the cached decoder
            if (cachedDecoder != null)
            {
                decoderHandle = cachedDecoder.InternalDecoder; 
            }
            else if ((finalUri != null) && (finalUri.IsAbsoluteUri) && (stream == null) && 
                     ((finalUri.Scheme == Uri.UriSchemeHttp) || 
                      (finalUri.Scheme == Uri.UriSchemeHttps)))
            { 
                return new LateBoundBitmapDecoder(baseUri, uri, stream, createOptions, cacheOption, uriCachePolicy);
            }
            else if ((stream != null) && (!stream.CanSeek))
            { 
                return new LateBoundBitmapDecoder(baseUri, uri, stream, createOptions, cacheOption, uriCachePolicy);
            } 
            else 
            {
                // Create an unmanaged decoder 
                decoderHandle = BitmapDecoder.SetupDecoderFromUriOrStream(
                    finalUri,
                    stream,
                    cacheOption, 
                    out clsId,
                    out isOriginalWritable, 
                    out uriStream, 
                    out unmanagedMemoryStream,
                    out safeFilehandle 
                    );
            }

            BitmapDecoder decoder = null; 

            // Find out the decoder type and wrap it appropriately and return that 
            if (MILGuidData.GUID_ContainerFormatBmp == clsId) 
            {
                decoder = new BmpBitmapDecoder( 
                    decoderHandle,
                    cachedDecoder,
                    baseUri,
                    uri, 
                    stream,
                    createOptions, 
                    cacheOption, 
                    insertInDecoderCache,
                    isOriginalWritable, 
                    uriStream,
                    unmanagedMemoryStream,
                    safeFilehandle
                    ); 
            }
            else if (MILGuidData.GUID_ContainerFormatGif == clsId) 
            { 
                decoder = new GifBitmapDecoder(
                    decoderHandle, 
                    cachedDecoder,
                    baseUri,
                    uri,
                    stream, 
                    createOptions,
                    cacheOption, 
                    insertInDecoderCache, 
                    isOriginalWritable,
                    uriStream, 
                    unmanagedMemoryStream,
                    safeFilehandle
                    );
            } 
            else if (MILGuidData.GUID_ContainerFormatIco == clsId)
            { 
                decoder = new IconBitmapDecoder( 
                    decoderHandle,
                    cachedDecoder, 
                    baseUri,
                    uri,
                    stream,
                    createOptions, 
                    cacheOption,
                    insertInDecoderCache, 
                    isOriginalWritable, 
                    uriStream,
                    unmanagedMemoryStream, 
                    safeFilehandle
                    );
            }
            else if (MILGuidData.GUID_ContainerFormatJpeg == clsId) 
            {
                decoder = new JpegBitmapDecoder( 
                    decoderHandle, 
                    cachedDecoder,
                    baseUri, 
                    uri,
                    stream,
                    createOptions,
                    cacheOption, 
                    insertInDecoderCache,
                    isOriginalWritable, 
                    uriStream, 
                    unmanagedMemoryStream,
                    safeFilehandle 
                    );
            }
            else if (MILGuidData.GUID_ContainerFormatPng == clsId)
            { 
                decoder = new PngBitmapDecoder(
                    decoderHandle, 
                    cachedDecoder, 
                    baseUri,
                    uri, 
                    stream,
                    createOptions,
                    cacheOption,
                    insertInDecoderCache, 
                    isOriginalWritable,
                    uriStream, 
                    unmanagedMemoryStream, 
                    safeFilehandle
                    ); 
            }
            else if (MILGuidData.GUID_ContainerFormatTiff == clsId)
            {
                decoder = new TiffBitmapDecoder( 
                    decoderHandle,
                    cachedDecoder, 
                    baseUri, 
                    uri,
                    stream, 
                    createOptions,
                    cacheOption,
                    insertInDecoderCache,
                    isOriginalWritable, 
                    uriStream,
                    unmanagedMemoryStream, 
                    safeFilehandle 
                    );
            } 
            else if (MILGuidData.GUID_ContainerFormatWmp == clsId)
            {
                decoder = new WmpBitmapDecoder(
                    decoderHandle, 
                    cachedDecoder,
                    baseUri, 
                    uri, 
                    stream,
                    createOptions, 
                    cacheOption,
                    insertInDecoderCache,
                    isOriginalWritable,
                    uriStream, 
                    unmanagedMemoryStream,
                    safeFilehandle 
                    ); 
            }
            else 
            {
                decoder = new UnknownBitmapDecoder(
                    decoderHandle,
                    cachedDecoder, 
                    baseUri,
                    uri, 
                    stream, 
                    createOptions,
                    cacheOption, 
                    insertInDecoderCache,
                    isOriginalWritable,
                    uriStream,
                    unmanagedMemoryStream, 
                    safeFilehandle
                    ); 
            } 

            return decoder; 
        }

        /// 
        /// Create a BitmapDecoder from a Uri with the specified BitmapCreateOptions and 
        /// BitmapCacheOption
        ///  
        /// Uri to decode 
        /// Bitmap Create Options
        /// Bitmap Caching Option 
        public static BitmapDecoder Create(
            Uri bitmapUri,
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption 
            )
        { 
            return Create(bitmapUri, createOptions, cacheOption, null); 
        }
 
        /// 
        /// Create a BitmapDecoder from a Uri with the specified BitmapCreateOptions and
        /// BitmapCacheOption
        ///  
        /// Uri to decode
        /// Bitmap Create Options 
        /// Bitmap Caching Option 
        /// Optional web request cache policy
        public static BitmapDecoder Create( 
            Uri bitmapUri,
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption,
            RequestCachePolicy uriCachePolicy 
            )
        { 
            if (bitmapUri == null) 
            {
                throw new ArgumentNullException("bitmapUri"); 
            }

            return CreateFromUriOrStream(
                null, 
                bitmapUri,
                null, 
                createOptions, 
                cacheOption,
                uriCachePolicy, 
                true
                );
        }
 
        /// 
        /// Create a BitmapDecoder from a Stream with the specified BitmapCreateOptions and 
        /// BitmapCacheOption 
        /// 
        /// Stream to decode 
        /// Bitmap Create Options
        /// Bitmap Caching Option
        public static BitmapDecoder Create(
            Stream bitmapStream, 
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption 
            ) 
        {
            if (bitmapStream == null) 
            {
                throw new ArgumentNullException("bitmapStream");
            }
 
            return CreateFromUriOrStream(
                null, 
                null, 
                bitmapStream,
                createOptions, 
                cacheOption,
                null,
                true
                ); 
        }
 
        #endregion 

        #region Properties 

        /// 
        /// If there is an palette, return it.
        /// Otherwise, return null. 
        /// 
        ///  
        /// Critical - Access unmanaged code, codecs 
        /// PublicOK - Getting palette data is OK
        ///  
        public virtual BitmapPalette Palette
        {
            [SecurityCritical ]
            get 
            {
                VerifyAccess(); 
                EnsureBuiltInDecoder(); 

                if (!_isPaletteCached) 
                {
                    SafeMILHandle /* IWICBitmapPalette */ paletteHandle = BitmapPalette.CreateInternalPalette();

                    lock (_syncObject) 
                    {
                        int hr = UnsafeNativeMethods.WICBitmapDecoder.CopyPalette( 
                            _decoderHandle, 
                            paletteHandle
                            ); 
                        if (hr != (int)WinCodecErrors.WINCODEC_ERR_PALETTEUNAVAILABLE)
                        {
                            HRESULT.Check(hr);
                            _palette = new BitmapPalette(paletteHandle); 
                        }
                    } 
 
                    _isPaletteCached = true;
                } 

                return _palette;
            }
        } 

        ///  
        /// If there is an embedded color profile, return it. 
        /// Otherwise, return null.
        ///  
        /// 
        /// Critical - Access unmanaged code, codecs
        /// PublicOK - Getting colorcontext data is OK
        ///  
        public virtual ReadOnlyCollection ColorContexts
        { 
            [SecurityCritical ] 
            get
            { 
                return InternalColorContexts;
            }
        }
 
        /// 
        /// If there is a global thumbnail, return it. 
        /// Otherwise, return null. The returned source is frozen. 
        /// 
        ///  
        /// Critical - Access unmanaged code, codecs
        /// PublicOK - Getting thumbnail data is OK
        /// 
        public virtual BitmapSource Thumbnail 
        {
            [SecurityCritical ] 
            get 
            {
                VerifyAccess(); 
                EnsureBuiltInDecoder();

                if (!_isThumbnailCached)
                { 
                    IntPtr /* IWICBitmapSource */ thumbnail = IntPtr.Zero;
 
                    // Check if there is embedded thumbnail or not 
                    lock (_syncObject)
                    { 
                        int hr = UnsafeNativeMethods.WICBitmapDecoder.GetThumbnail(
                            _decoderHandle,
                            out thumbnail
                            ); 
                        if (hr != (int)WinCodecErrors.WINCODEC_ERR_CODECNOTHUMBNAIL)
                        { 
                            HRESULT.Check(hr); 
                        }
                    } 

                    if (thumbnail != IntPtr.Zero)
                    {
                        BitmapSourceSafeMILHandle thumbHandle = new BitmapSourceSafeMILHandle(thumbnail); 
                        SafeMILHandle unmanagedPalette = BitmapPalette.CreateInternalPalette();
                        BitmapPalette palette = null; 
 
                        int hr = UnsafeNativeMethods.WICBitmapSource.CopyPalette(
                                    thumbHandle, 
                                    unmanagedPalette
                                    );
                        if (hr == HRESULT.S_OK)
                        { 
                            palette = new BitmapPalette(unmanagedPalette);
                        } 
 
                        _thumbnail = new UnmanagedBitmapWrapper(
                            BitmapSource.CreateCachedBitmap( 
                                null,
                                thumbHandle,
                                BitmapCreateOptions.PreservePixelFormat,
                                _cacheOption, 
                                palette
                                )); 
                        _thumbnail.Freeze(); 
                    }
 
                    _isThumbnailCached = true;
                }

                return _thumbnail; 
            }
        } 
 
        /// 
        /// If there is a global metadata, return it. 
        /// Otherwise, return null. The returned source is frozen.
        /// 
        /// 
        ///     Critical - Access unmanaged code, codecs 
        ///     Public -
        ///       Getting metadata for images from site of origin or bundled with the application is OK 
        ///       Getting metatdat for images from cross domain servers triggers a demand for site of origin. 
        /// 
        public virtual BitmapMetadata Metadata 
        {
            [SecurityCritical]
            get
            { 
                VerifyAccess();
                EnsureBuiltInDecoder(); 
 
                // Demand Site Of origin on the URI if it passes then this  information is ok to expose
                CheckIfSiteOfOrigin(); 

                if (!_isMetadataCached)
                {
 
                    IntPtr /* IWICMetadataQueryReader */ metadata = IntPtr.Zero;
 
                    lock (_syncObject) 
                    {
                        int hr = UnsafeNativeMethods.WICBitmapDecoder.GetMetadataQueryReader( 
                            _decoderHandle,
                            out metadata
                            );
                        if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION) 
                        {
                            HRESULT.Check(hr); 
                        } 
                    }
 
                    if (metadata != IntPtr.Zero)
                    {
                        SafeMILHandle metadataHandle = new SafeMILHandle(metadata, 0);
 
                        _metadata = new BitmapMetadata(metadataHandle, true, IsMetadataFixedSize, _syncObject);
                        _metadata.Freeze(); 
                    } 

                    _isMetadataCached = true; 
                }

                return _metadata;
            } 
        }
 
        ///  
        /// The info that identifies this codec.
        ///  
        /// 
        /// Critical - Access unmanaged code, codecs
        /// PublicOK - Getting codecinfo data is OK
        ///  
        public virtual BitmapCodecInfo CodecInfo
        { 
            [SecurityCritical ] 
            get
            { 
                VerifyAccess();
                EnsureBuiltInDecoder();

                // There should always be a codec info. 
                if (_codecInfo == null)
                { 
                    SafeMILHandle /* IWICBitmapDecoderInfo */ codecInfoHandle =  new SafeMILHandle(); 

                    HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetDecoderInfo( 
                        _decoderHandle,
                        out codecInfoHandle
                        ));
 
                    _codecInfo = new BitmapCodecInfoInternal(codecInfoHandle);
                } 
 
                return _codecInfo;
            } 
        }

        /// 
        /// Access to the individual frames. All BitmapFrames are frozen. 
        /// 
        public virtual ReadOnlyCollection Frames 
        { 
            get
            { 
                VerifyAccess();
                EnsureBuiltInDecoder();

                if (_frames == null) 
                {
                    SetupFrames(null, null); 
                } 

                if (_readOnlyFrames == null) 
                {
                    _readOnlyFrames = new ReadOnlyCollection(_frames);
                }
 
                return _readOnlyFrames;
            } 
        } 

        ///  
        /// If there is a global preview image, return it.
        /// Otherwise, return null. The returned source is frozen.
        /// 
        ///  
        /// Critical - Access unmanaged code, codecs
        /// PublicOK - Getting preview data is OK 
        ///  
        public virtual BitmapSource Preview
        { 
            [SecurityCritical ]
            get
            {
                VerifyAccess(); 
                EnsureBuiltInDecoder();
 
                if (!_isPreviewCached) 
                {
                    IntPtr /* IWICBitmapSource */ preview = IntPtr.Zero; 

                    lock (_syncObject)
                    {
                        // Check if there is embedded preview or not 
                        int hr = UnsafeNativeMethods.WICBitmapDecoder.GetPreview(
                            _decoderHandle, 
                            out preview 
                            );
                        if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION) 
                        {
                            HRESULT.Check(hr);
                        }
                    } 

                    if (preview != IntPtr.Zero) 
                    { 
                        BitmapSourceSafeMILHandle previewHandle = new BitmapSourceSafeMILHandle(preview);
                        SafeMILHandle unmanagedPalette = BitmapPalette.CreateInternalPalette(); 
                        BitmapPalette palette = null;

                        int hr = UnsafeNativeMethods.WICBitmapSource.CopyPalette(
                                    previewHandle, 
                                    unmanagedPalette
                                    ); 
                        if (hr == HRESULT.S_OK) 
                        {
                            palette = new BitmapPalette(unmanagedPalette); 
                        }

                        _preview = new UnmanagedBitmapWrapper(
                            BitmapSource.CreateCachedBitmap( 
                                null,
                                previewHandle, 
                                BitmapCreateOptions.PreservePixelFormat, 
                                _cacheOption,
                                palette 
                                ));
                        _preview.Freeze();
                    }
 
                    _isPreviewCached = true;
                } 
 
                return _preview;
            } 
        }

        /// 
        /// Returns true if the decoder is downloading content 
        /// 
        public virtual bool IsDownloading 
        { 
            get
            { 
                VerifyAccess();
                EnsureBuiltInDecoder();
                return false;
            } 
        }
 
        ///  
        /// Raised when decoder has completed downloading content
        /// May not be raised for all content. 
        /// 
        public virtual event EventHandler DownloadCompleted
        {
            add 
            {
                VerifyAccess(); 
                EnsureBuiltInDecoder(); 
                _downloadEvent.AddEvent(value);
            } 
            remove
            {
                VerifyAccess();
                EnsureBuiltInDecoder(); 
                _downloadEvent.RemoveEvent(value);
            } 
        } 

        ///  
        /// Raised when download has progressed
        /// May not be raised for all content.
        /// 
        public virtual event EventHandler DownloadProgress 
        {
            add 
            { 
                VerifyAccess();
                EnsureBuiltInDecoder(); 
                _progressEvent.AddEvent(value);
            }
            remove
            { 
                VerifyAccess();
                EnsureBuiltInDecoder(); 
                _progressEvent.RemoveEvent(value); 
            }
        } 

        /// 
        /// Raised when download has failed
        /// May not be raised for all content. 
        /// 
        public virtual event EventHandler DownloadFailed 
        { 
            add
            { 
                VerifyAccess();
                EnsureBuiltInDecoder();
                _failedEvent.AddEvent(value);
            } 
            remove
            { 
                VerifyAccess(); 
                EnsureBuiltInDecoder();
                _failedEvent.RemoveEvent(value); 
            }
        }

        #endregion 

        #region Public Properties 
 
        /// 
        /// Create an in-place bitmap metadata writer. 
        /// 
        public virtual InPlaceBitmapMetadataWriter CreateInPlaceBitmapMetadataWriter()
        {
            VerifyAccess(); 
            EnsureBuiltInDecoder();
 
            CheckOriginalWritable(); 

            // Demand Site Of origin on the URI if it passes then this  information is ok to expose 
            CheckIfSiteOfOrigin();

            return InPlaceBitmapMetadataWriter.CreateFromDecoder(_decoderHandle, _syncObject);
        } 

        #endregion 
 
        #region ToString
 
        /// 
        /// ToString
        /// 
        public override string ToString() 
        {
            VerifyAccess(); 
 
            if (!_isBuiltInDecoder)
            { 
                return base.ToString();
            }

            if (_uri != null) 
            {
                if (_baseUri != null) 
                { 
                    Uri uri = new Uri(_baseUri, _uri);
                    return BindUriHelper.UriToString(uri); 
                }
                else
                {
                    return BindUriHelper.UriToString(_uri); 
                }
            } 
            else 
            {
                return SafeSecurityHelper.IMAGE; 
            }
        }

        #endregion 

        #region Internal Properties 
 
        /// 
        /// Internal Decoder 
        /// 
        internal SafeMILHandle InternalDecoder
        {
            get 
            {
                return _decoderHandle; 
            } 
        }
 
        /// 
        /// Returns whether metadata is fixed size or not.
        /// 
        internal virtual bool IsMetadataFixedSize 
        {
            get 
            { 
                return false;
            } 
        }

        /// 
        /// Synchronization Object.  Any unmanaged PInvoke/call that requires synchronization 
        /// must lock on the [....] object.  This object must be internal or private so as not
        /// to be publicly lockable. 
        ///  
        internal object SyncObject
        { 
            get
            {
                Debug.Assert(_syncObject != null);
                return _syncObject; 
            }
        } 
 
        /// 
        /// If there is an embedded color profile, return it. 
        /// Otherwise, return null.
        /// 
        /// 
        /// Critical - Access unmanaged code, codecs 
        /// TreatAsSafe - Getting colorcontext data is OK
        ///  
        internal ReadOnlyCollection InternalColorContexts 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            {
                VerifyAccess();
                EnsureBuiltInDecoder(); 

                if (!_isColorContextCached) 
                { 

                    // Check if there is colorContext or not 
                    lock (_syncObject)
                    {
                        unsafe
                        { 

                            uint uiCount = 0; 
 
                            int hr = UnsafeNativeMethods.WICBitmapDecoder.GetColorContexts(
                                _decoderHandle, 
                                0,
                                IntPtr.Zero,
                                out uiCount
                                ); 

                            if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION) 
                            { 
                                HRESULT.Check(hr);
                            } 

                            if (uiCount > 0)
                            {
                                List colorContextsList = new List((int)uiCount); 

                                IntPtr* pcolorContextslocal = stackalloc IntPtr[(int)uiCount]; 
                                for (int i = 0; i < uiCount; i++) pcolorContextslocal[i] = IntPtr.Zero; 

                                SafeMILHandle[] colorContextHandles = new SafeMILHandle[uiCount]; 

                                using (FactoryMaker factoryMaker = new FactoryMaker())
                                {
                                    try 
                                    {
                                        for (int i = 0; i < uiCount; i++) 
                                        { 
                                            Guid wicColorContextGuid = MILGuidData.IID_IWICColorContext;
 
                                            HRESULT.Check(UnsafeNativeMethods.WICCodec.CreateColorContext(factoryMaker.ImagingFactoryPtr, out colorContextHandles[i]));

                                            HRESULT.Check(UnsafeNativeMethods.MILUnknown.QueryInterface(colorContextHandles[i], ref wicColorContextGuid, out pcolorContextslocal[i]));
                                        } 

                                    } 
                                    finally 
                                    {
                                        for (int i = 0; i < uiCount; i++) 
                                        {
                                            #pragma warning suppress 6031 // Return value ignored on purpose.
                                            UnsafeNativeMethods.MILUnknown.Release(pcolorContextslocal[i]);
                                        } 
                                    }
                                } 
                                HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetColorContexts( 
                                    _decoderHandle,
                                    uiCount, 
                                    (IntPtr)pcolorContextslocal,
                                    out uiCount
                                    ));
 
                                for (uint i = 0; i < uiCount; i++)
                                { 
                                    colorContextsList.Add(new ColorContext(colorContextHandles[i])); 
                                }
 
                                _readOnlycolorContexts = new ReadOnlyCollection(colorContextsList);
                            }

                            _isColorContextCached = true; 

                        } 
                    } 

                } 

                return _readOnlycolorContexts;
            }
        } 

 
        ///  
        /// Checks whether the underlying source is writable (useful for in-place metadata editing)
        ///  
        internal void CheckOriginalWritable()
        {
            if (!_isOriginalWritable)
            { 
                throw new System.InvalidOperationException(SR.Get(SRID.Image_OriginalStreamReadOnly));
            } 
        } 

        #endregion 

        #region Internal/Private Methods
        /// 
        ///     Critical: This sets and accesses critical members isImageDisabledInitialized,isImageDisabled 
        ///     TreatAsSafe: This code does not expose the variables and is not influenced by external paramaters that do not
        ///     require unmanaged code access permission to set 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private static void DemandIfImageBlocked() 
        {
            if(!isImageDisabledInitialized)
            {
                // a performance optimization to ensure we hit the registry only once in the lifetime of the application 
                isImageDisabled = new SecurityCriticalDataForSet(SafeSecurityHelper.IsFeatureDisabled(SafeSecurityHelper.KeyToRead.MediaImageDisable));
                isImageDisabledInitialized = true; 
            } 
            if (isImageDisabled.Value)
            { 
                // in case the registry key is '1' then demand MediaPermissionImage.AllImage - not granted in Partial Trust
                SecurityHelper.DemandMediaPermission(MediaPermissionAudio.NoAudio,
                                                     MediaPermissionVideo.NoVideo,
                                                     MediaPermissionImage.AllImage); 
            }
            else 
            { 
                // Images are enabled. Then, demand permissions for safe imaging - granted in Partial Trust by default
                SecurityHelper.DemandMediaPermission(MediaPermissionAudio.NoAudio, 
                                                     MediaPermissionVideo.NoVideo,
                                                     MediaPermissionImage.SafeImage);
            }
        } 

        ///  
        /// Critical - Unmanaged code will eventually create a COM object, need to secure it 
        /// 
        [SecurityCritical] 
        internal static SafeMILHandle SetupDecoderFromUriOrStream(
            Uri uri,
            Stream stream,
            BitmapCacheOption cacheOption, 
            out Guid clsId,
            out bool isOriginalWritable, 
            out Stream uriStream, 
            out UnmanagedMemoryStream unmanagedMemoryStream,
            out SafeFileHandle safeFilehandle 
            )
        {
            SafeMILHandle decoderHandle;
            IntPtr decoder = IntPtr.Zero; 
            System.IO.Stream bitmapStream = null;
            string mimeType = String.Empty; 
            // check to ensure that images are allowed in partial trust NOP in full trust 
            DemandIfImageBlocked();
            unmanagedMemoryStream = null; 
            safeFilehandle = null;
            isOriginalWritable = false;
            uriStream = null;
 
            if ((uri != null) && (stream != null))
            { 
                // In this case we expect the Uri to be http(s) 
                Debug.Assert((uri.Scheme == Uri.UriSchemeHttp) || (uri.Scheme == Uri.UriSchemeHttps));
                Debug.Assert(stream.CanSeek); 
            }

            // Uri
            if (uri != null) 
            {
                if (uri.IsAbsoluteUri) 
                { 
                    // In this case we first check to see if the consumer has media permissions for
                    // safe media (Site of Origin + Cross domain) 
                    SecurityHelper.DemandMediaPermission(MediaPermissionAudio.NoAudio,
                                                         MediaPermissionVideo.NoVideo,
                                                         MediaPermissionImage.SiteOfOriginImage) ;
                    // This code path executes only for pack web requests 
                    if (String.Compare(uri.Scheme, PackUriHelper.UriSchemePack, StringComparison.OrdinalIgnoreCase) == 0)
                    { 
                        WebResponse response = WpfWebRequestHelper.CreateRequestAndGetResponse(uri); 
                        mimeType = response.ContentType;
                        bitmapStream = response.GetResponseStream(); 
                        uriStream = bitmapStream;
                    }
                }
 
                if ((bitmapStream == null) || (bitmapStream == System.IO.Stream.Null))
                { 
                    // We didn't get a stream from the pack web request, so we have 
                    // to try to create one ourselves.
                    if (uri.IsAbsoluteUri) 
                    {
                        // The Uri class can't tell if it is a file unless it
                        // has an absolute path.
                        int targetZone = SecurityHelper.MapUrlToZoneWrapper(uri); 
                        if (targetZone == MS.Win32.NativeMethods.URLZONE_LOCAL_MACHINE)
                        { 
                            if (uri.IsFile) 
                            {
                                // FileStream does a demand for us, so no need to do a demand 
                                bitmapStream = new System.IO.FileStream(uri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
                            }
                        }
                        else // Any other zone 
                        {
                            // UNC path for a file which is not http 
                            if (uri.IsFile && uri.IsUnc) // for UNC 
                            {
                                bitmapStream = ProcessUncFiles(uri); 
                            }
                            else if (uri.Scheme == Uri.UriSchemeHttp) // for http
                            {
                                bitmapStream = ProcessHttpFiles(uri,stream); 
                            }
                            else if (uri.Scheme == Uri.UriSchemeHttps) // for https 
                            { 
                                bitmapStream = ProcessHttpsFiles(uri,stream);
                            } 
                            else
                            {
                                // The Uri is a custom Uri. Try to grab the stream from its WebResponse.
                                bitmapStream = WpfWebRequestHelper.CreateRequestAndGetResponseStream(uri); 
                            }
                        } 
                    } 
                    else
                    { 
                        #pragma warning disable 6518
                        // We don't have an absolute URI, so we don't necessarily know
                        // if it is a file, but we'll have to assume it is and try to
                        // create a stream from the original string. 
                        bitmapStream = new System.IO.FileStream(uri.OriginalString, FileMode.Open, FileAccess.Read, FileShare.Read);
                        #pragma warning restore 6518 
                    } 

                    uriStream = bitmapStream; 
                }
            }

            // We need to use the stream created from the Uri. 
            if (bitmapStream != null)
            { 
                stream = bitmapStream; 
            }
            else 
            {
                // Note whether the original stream is writable.
                isOriginalWritable = stream.CanSeek && stream.CanWrite;
            } 

            // Make sure we always use a seekable stream to avoid problems with http Uris etc. 
            stream = GetSeekableStream(stream); 

            if (stream is UnmanagedMemoryStream) 
            {
                unmanagedMemoryStream = stream as UnmanagedMemoryStream;
            }
 
            IntPtr comStream = IntPtr.Zero;
 
            if (stream is System.IO.FileStream) 
            {
                System.IO.FileStream filestream = stream as System.IO.FileStream; 

                try
                {
                    safeFilehandle = filestream.SafeFileHandle; 
                }
                catch 
                { 
                    // If Filestream doesn't support SafeHandle then revert to old code path.
                    safeFilehandle = null; 
                }
            }

            try 
            {
                Guid vendorMicrosoft = new Guid(MILGuidData.GUID_VendorMicrosoft); 
                UInt32 metadataFlags = (uint)WICMetadataCacheOptions.WICMetadataCacheOnDemand; 

                if (cacheOption == BitmapCacheOption.OnLoad) 
                {
                    metadataFlags = (uint)WICMetadataCacheOptions.WICMetadataCacheOnLoad;
                }
 
                // We have a SafeHandle.
                if (safeFilehandle != null) 
                { 
                    using (FactoryMaker myFactory = new FactoryMaker())
                    { 
                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateDecoderFromFileHandle(
                            myFactory.ImagingFactoryPtr,
                            safeFilehandle,
                            ref vendorMicrosoft, 
                            metadataFlags,
                            out decoder 
                            )); 
                    }
                } 
                else
                {
                    comStream = BitmapDecoder.GetIStreamFromStream(ref stream);
 
                    using (FactoryMaker myFactory = new FactoryMaker())
                    { 
 
                        // This does an add-ref on the comStream
                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateDecoderFromStream( 
                            myFactory.ImagingFactoryPtr,
                            comStream,
                            ref vendorMicrosoft,
                            metadataFlags, 
                            out decoder
                            )); 
                    } 
                }
                Debug.Assert(decoder != IntPtr.Zero); 
                decoderHandle = new SafeMILHandle(decoder, 0);
            }
            catch
            { 
                #pragma warning disable 6500
 
                decoderHandle = null; 
                throw;
 
                #pragma warning restore 6500
            }
            finally
            { 
                UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref comStream);
            } 
 
            string decoderMimeTypes;
            clsId = GetCLSIDFromDecoder(decoderHandle, out decoderMimeTypes); 

            // If the mime type of the file does not match the associated decoder,
            // and if we are in a Partial trust scenario, throw!
            if ((mimeType != String.Empty) && 
                (decoderMimeTypes.IndexOf(mimeType, StringComparison.OrdinalIgnoreCase) == -1))
            { 
                try 
                {
                    SecurityHelper.DemandUnmanagedCode(); 
                }
                catch(SecurityException)
                {
                    throw new ArgumentException(SR.Get(SRID.Image_ContentTypeDoesNotMatchDecoder)); 
                }
            } 
 
            return decoderHandle;
        } 

        /// 
        /// Critical: performs an assert for WebPermission potentially outside the site of origin.
        ///  
        [SecurityCritical]
        private static Stream ProcessHttpsFiles(Uri uri, Stream stream) 
        { 
            Stream bitmapStream = stream;
            // This is the condition where the Bitmap has already been downloaded 
            // or the stream is not seekable
            // using async dowload in that case simply return the original stream
            // else you download the stream
            if (bitmapStream == null || !bitmapStream.CanSeek) 
            {
                WebRequest request = null; 
 
                // Block XDomain from apps deployed over HTTPS (For HTTP, LMZ and UNC apps, is ok to access images through HTTPS)
                SecurityHelper.BlockCrossDomainForHttpsApps(uri); 

                // now, we can Assert permissions because we ensured that only apps deployed through non-HTTPS can access XDomain images
                (new WebPermission(NetworkAccess.Connect, BindUriHelper.UriToString(uri))).Assert(); // BlessedAssert
                try 
                {
                    request = WpfWebRequestHelper.CreateRequest(uri); 
                } 
                finally
                { 
                    WebPermission.RevertAssert();
                }

                bitmapStream = WpfWebRequestHelper.GetResponseStream(request); 
            }
            return bitmapStream; 
        } 

        ///  
        ///     Critical: This code elevates and extracts a bitmap stream
        /// 
        [SecurityCritical]
        private static Stream ProcessHttpFiles(Uri uri, Stream stream) 
        {
            WebRequest request = null; 
            Stream bitmapStream =  stream; 
            SecurityHelper.BlockCrossDomainForHttpsApps(uri);
            // Download only if this content is not already downloaded or stream is not seekable 
            if (bitmapStream == null || !bitmapStream.CanSeek)
            {
                // In this case we first check to see if the consumer has media permissions for
                // safe media (Site of Origin + Cross domain), if it 
                // does we assert and run the code that requires the assert
                bool fElevate = false; 
                if (SecurityHelper.CallerHasMediaPermission(MediaPermissionAudio.NoAudio, 
                                                            MediaPermissionVideo.NoVideo,
                                                            MediaPermissionImage.SafeImage)) 
                {
                    fElevate = true;
                }
 
                if (fElevate)
                { 
                    (new WebPermission(NetworkAccess.Connect, BindUriHelper.UriToString(uri))).Assert(); // BlessedAssert 
                }
                try 
                {
                    request = WpfWebRequestHelper.CreateRequest(uri);
                }
                finally 
                {
                    if (fElevate) 
                    { 
                        WebPermission.RevertAssert();
                    } 
                }

                // Download only if this content is not already downloaded or stream is not seekable
                bitmapStream = WpfWebRequestHelper.GetResponseStream(request); 
            }
            return bitmapStream; 
        } 

        ///  
        ///     Critical: This code elevates and extracts a bitmap stream
        /// 
        [SecurityCritical]
        private static Stream ProcessUncFiles(Uri uri) 
        {
            Stream bitmapStream = null; 
 
            // perform checks for UNC content
            SecurityHelper.EnforceUncContentAccessRules(uri); 

            // In this case we first check to see if the consumer has media permissions for
            // safe media (Site of Origin + Cross domain), if it
            // does then we assert else we run the code without the assert 
            bool fElevate = false;
            if (SecurityHelper.CallerHasMediaPermission(MediaPermissionAudio.NoAudio, 
                                                        MediaPermissionVideo.NoVideo, 
                                                        MediaPermissionImage.SafeImage))
            { 
                fElevate = true;
            }

            if(fElevate) 
            {
                // since the code above ensures that safe image permission is granted we 
                // can now do an assert to allow cross domain web request 
                (new FileIOPermission(FileIOPermissionAccess.Read, uri.LocalPath)).Assert(); // BlessedAssert
            } 
            try
            {
                // FileStream does a demand for us, so no need to do a demand
                bitmapStream = new System.IO.FileStream(uri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read); 
            }
            finally 
            { 
                if(fElevate)
                { 
                    FileIOPermission.RevertAssert();
                }
            }
            return bitmapStream; 
        }
 
        ///  
        ///     Critical: This code is used to check and grant access to pixel data and metadata.
        ///     TreatAsSafe: This code does not elevate 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        void CheckIfSiteOfOrigin()
        { 
            string uri = null;
 
            if (CanConvertToString()) 
            {
                // This call returns the URI either as an absolute URI which the user 
                // passed in, in the first place or as the string "image"
                // we only allow this code to succeed in the case of Uri and if it is site of
                // origin or pack:. In all other conditions we fail
 
                uri = ToString();
            } 
 
            SecurityHelper.DemandMediaAccessPermission(uri);
        } 

        /// Returns the decoder's CLSID
        /// 
        /// Critical - access unmanaged code to retrieve CLSID. 
        /// 
        [SecurityCritical] 
        private static Guid GetCLSIDFromDecoder(SafeMILHandle decoderHandle, out string decoderMimeTypes) 
        {
            Guid clsId; 

            // Get the decoder info
            SafeMILHandle decoderInfo = new SafeMILHandle();
            HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetDecoderInfo( 
                decoderHandle,
                out decoderInfo 
                )); 

            // Get CLSID for the decoder 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapCodecInfo.GetContainerFormat(decoderInfo, out clsId));

            StringBuilder mimeTypes = null;
            UInt32 length = 0; 

            // Find the length of the string needed 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapCodecInfo.GetMimeTypes( 
                decoderInfo,
                0, 
                mimeTypes,
                out length
                ));
 
            // get the string back
            if (length > 0) 
            { 
                mimeTypes = new StringBuilder((int)length);
 
                HRESULT.Check(UnsafeNativeMethods.WICBitmapCodecInfo.GetMimeTypes(
                    decoderInfo,
                    length,
                    mimeTypes, 
                    out length
                    )); 
            } 

            if (mimeTypes != null) 
            {
                decoderMimeTypes = mimeTypes.ToString();
            }
            else 
            {
                decoderMimeTypes = String.Empty; 
            } 

            return clsId; 
        }

        /// Return a seekable stream if the current one is not seekable
        private static System.IO.Stream GetSeekableStream(System.IO.Stream bitmapStream) 
        {
            // MIL codecs require the source stream to be seekable. But if 
            // the source stream is an internet stream, it is not seekable. 
            // The data is probably not in the stream yet.
 
            if (bitmapStream.CanSeek)
            {
                return bitmapStream;
            } 

            // If the source is not seekable, we have to download the 
            // stream into a memory stream before we can decode it. 
            // ISSUE-2002/10/03--minliu: later on, if we can make MIL
            // support progressive JPEG etc., we should take out the 
            // hack here and pass the network stream (CConectStream)
            // directly to the unmanaged code

            System.IO.MemoryStream memStream = 
                new System.IO.MemoryStream();
 
            byte[] buffer = new byte[1024]; 
            int read;
 
            // Read all the bytes and write it to a memory stream
            //

 

            do 
            { 
                read = bitmapStream.Read(buffer, 0, 1024);
                if (read <= 0) 
                {
                    break;
                }
                memStream.Write(buffer, 0, read); 
            } while (true);
 
            // Reset the memory stream pointer back to the begining 
            memStream.Seek(0, System.IO.SeekOrigin.Begin);
 
            // Use the new stream

            return memStream;
        } 

        /// Check the cache to see if decoder already exists 
        ///  
        /// Critical - Eventually calls code that calls unmanaged code.
        /// TreatAsSafe - Only checks imaging cache to see object exists 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private static BitmapDecoder CheckCache(
            Uri uri, 
            out Guid clsId
            ) 
        { 
            clsId = Guid.Empty;
            string mimeTypes; 

            if (uri != null)
            {
                WeakReference weakRef = ImagingCache.CheckDecoderCache(uri) as WeakReference; 
                if (weakRef != null)
                { 
                    BitmapDecoder bitmapDecoder = weakRef.Target as BitmapDecoder; 
                    if ((bitmapDecoder != null) && bitmapDecoder.CheckAccess())
                    { 
                        lock (bitmapDecoder.SyncObject)
                        {
                            clsId = GetCLSIDFromDecoder(bitmapDecoder.InternalDecoder, out mimeTypes);
                            return bitmapDecoder; 
                        }
                    } 
                    // Remove from the cache if bitmapDecoder is already been collected 
                    if (bitmapDecoder == null)
                    { 
                        ImagingCache.RemoveFromDecoderCache(uri);
                    }
                }
            } 

            return null; 
        } 

        ///  
        /// Initialize the codec.
        /// 
        /// 
        /// Critical - Will eventually create a COM object, need to secure it 
        /// 
        [SecurityCritical] 
        private void Initialize(BitmapDecoder decoder) 
        {
            _isBuiltInDecoder = true; 

            if (decoder != null)
            {
                SetupFrames(decoder, null); 
                //
                // We need to keep the strong reference to the cached decoder for a few reasons: 
                // 
                //    The application may release the original cached decoder and then keep a
                //    reference to this decoder only, in which case, the cache can be collected. 
                //    This will cause a few undesirable results:
                //    1. The application may choose to decode the same URI again in which case
                //       we will not retrieve it from the cache even though we have a copy already
                //       decoded. 
                //    2. The original cached decoder holds onto the file stream indirectly which if
                //       collected can cause bad behavior if the entire decoder is not loaded into 
                //       memory. 
                //
                _cachedDecoder = decoder; 
            }
            else if ((_createOptions & BitmapCreateOptions.DelayCreation) == 0 && _cacheOption == BitmapCacheOption.OnLoad)
            {
                SetupFrames(null, null); 

                // Its ok to close the stream since the frames are not delay created and caching is immediate 
                CloseStream(); 
            }
 

            if ((_uri != null) && (decoder == null) && _shouldCacheDecoder)
            {
 
                // Add this decoder to the decoder cache
                ImagingCache.AddToDecoderCache( 
                    (_baseUri == null) ? _uri : new Uri(_baseUri, _uri), 
                    new WeakReference(this)
                    ); 
            }
        }

        ///  
        /// Closes the stream if its non-null
        ///  
        ///  
        /// Critical - accesses critical resource _uriStream
        /// TreatAsSafe - doesn't return the uriStream, just closes it which is safe 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void CloseStream()
        { 
            if (_uriStream != null)
            { 
                _uriStream.Close(); 
            }
        } 

        /// 
        /// Sets up the frames collection.
        /// Also, ensures that the frame collection for this decoder 
        /// will contain the same underlying frames as the collection
        /// passed in. This is called by the LateBoundBitmapDecoder 
        ///  
        /// 
        /// Critical - access unmanaged code 
        /// TreatAsSafe - only access number of frames in the bitmap, a safe operation
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void SetupFrames(BitmapDecoder decoder, ReadOnlyCollection frames) 
        {
            uint numFrames = 1; 
 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetFrameCount(_decoderHandle, out numFrames));
 
            _frames = new List((int)numFrames);

            // initialize the list of frames to null.
            // We'll fill it as it's used (pay for play). 
            for (int i = 0; i < (int)numFrames; i++)
            { 
                if (i > 0 && _cacheOption != BitmapCacheOption.OnLoad) 
                {
                    _createOptions |= BitmapCreateOptions.DelayCreation; 
                }

                BitmapFrameDecode bfd = null;
 
                if ((frames != null) && (frames.Count == (i + 1)))
                { 
                    // If we already have a frames collection, get the BitmapFrame from it 
                    bfd = frames[i] as BitmapFrameDecode;
                    bfd.UpdateDecoder(this); 
                }
                else if (decoder == null)
                {
                    // All frames should be frozen. 
                    bfd = new BitmapFrameDecode(
                        i, 
                        null, 
                        _createOptions,
                        _cacheOption, 
                        this
                        );
                    bfd.Freeze();
                } 
                else
                { 
                    // if we are creating from an existing cache, use the frames 
                    // already stored in that cache
                    // All frames should be frozen. 
                    bfd = new BitmapFrameDecode(
                        i,
                        _createOptions,
                        _cacheOption, 
                        decoder.Frames[i] as BitmapFrameDecode
                        ); 
                    bfd.Freeze(); 
                }
 
                _frames.Add(bfd);
            }
        }
 
        /// 
        /// Checks if the decoder is builtin. If not, throw exception 
        ///  
        private void EnsureBuiltInDecoder()
        { 
            if (!_isBuiltInDecoder)
            {
                throw new NotImplementedException();
            } 
        }
 
        ///  
        /// Note, we must hold onto a reference to the managed stream
        /// as long as we are using the unmanaged stream in the decoder. 
        /// This method may create a new managed stream.
        ///

 

 
 

 
        [SecurityCritical]
        private static IntPtr GetIStreamFromStream(ref System.IO.Stream bitmapStream)
        {
            IntPtr  comStream = IntPtr.Zero; 

            // ensure the stream is seekable 
            bool seekable = bitmapStream.CanSeek; 

            if (bitmapStream is UnmanagedMemoryStream) 
            {
                UnmanagedMemoryStream memoryStream = bitmapStream as UnmanagedMemoryStream;
                IntPtr bufferPtr = IntPtr.Zero;
                int length = 0; 

                unsafe 
                { 
                   bufferPtr = (IntPtr) memoryStream.PositionPointer;
                   length = (int) memoryStream.Length; 
                }

                if (bufferPtr != IntPtr.Zero)
                { 
                    comStream = StreamAsIStream.IStreamFrom(bufferPtr, length);
                } 
            } 
            else
            { 
                comStream = StreamAsIStream.IStreamFrom(bitmapStream);

                if (comStream == IntPtr.Zero)
                { 
                    throw new System.InvalidOperationException(
                        SR.Get(SRID.Image_CantDealWithStream)); 
                } 

                // If the stream is not seekable, we must create a 
                // seekable one for the decoder.
                if (!seekable || ((!bitmapStream.CanWrite) && (bitmapStream.Length <= 1048576)))
                {
                    IntPtr memoryStream = StreamAsIStream.IStreamMemoryFrom(comStream); 

                    if (memoryStream != IntPtr.Zero) 
                    { 
                        // we don't need the original stream anymore
                        UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref comStream); 
                        bitmapStream = System.IO.Stream.Null;
                        return memoryStream;
                    }
                    else if (!seekable) 
                    {
                        throw new System.InvalidOperationException( 
                                SR.Get(SRID.Image_CantDealWithStream)); 
                    }
                } 

             }

            if (comStream == IntPtr.Zero) 
            {
                throw new System.InvalidOperationException( 
                SR.Get(SRID.Image_CantDealWithStream)); 
            }
 
            return comStream;
        }

 
        /// Returns whether decoder can be converted to a string
        internal bool CanConvertToString() 
        { 
            return (_uri != null);
        } 

        #endregion

        #region Internal Abstract 

        /// "Seals" the object 
        internal abstract void SealObject(); 

        #endregion 

        #region Data Members

        /// check to see if implementation is internal 
        private bool _isBuiltInDecoder;
 
        /// Internal Decoder 
        private SafeMILHandle _decoderHandle;
 
        /// flag to see if decoder should be inserted in the cache
        private bool _shouldCacheDecoder = true;

        /// flag to see if decoder should be inserted in the cache 
        private bool _isOriginalWritable = false;
 
        /// If the palette is already cached 
        private bool _isPaletteCached;
 
        /// Palette
        private BitmapPalette _palette = null;

        /// If the ColorContext is already cached 
        private bool _isColorContextCached;
 
        /// ColorContexts collection 
        internal ReadOnlyCollection _readOnlycolorContexts;
 
        /// If the thumbnail is already cached
        private bool _isThumbnailCached;

        ///  
        /// Metadata
        ///  
        ///  
        /// Critical - Access only granted if SiteOfOrigin demanded.
        ///  
        [SecurityCritical]
        private BitmapMetadata _metadata;

        /// If the metadata is already cached 
        private bool _isMetadataCached;
 
        /// Thumbnail 
        private BitmapSource _thumbnail = null;
 
        /// CodecInfo
        private BitmapCodecInfo _codecInfo;

        /// If the preview is already cached 
        private bool _isPreviewCached;
 
        /// Preview 
        private BitmapSource _preview = null;
 
        /// Frames collection
        internal List _frames;

        /// Frames collection 
        internal ReadOnlyCollection _readOnlyFrames;
 
        /// Stream 
        internal Stream _stream;
 
        /// Uri
        internal Uri _uri;

        /// Base Uri, only stored internally. Not used for serialization 
        internal Uri _baseUri;
 
        /// Uri Stream -- this is the stream that was created from the passed in Uri 
        /// 
        ///     Critical: Obtained under elevation 
        /// 
        [SecurityCritical]
        internal Stream _uriStream;
 
        /// CreateOptions
        internal BitmapCreateOptions _createOptions; 
 
        /// CacheOption
        internal BitmapCacheOption _cacheOption; 

        /// Event helper for download completed event
        internal UniqueEventHelper _downloadEvent = new UniqueEventHelper();
 
        /// Event helper for download progress event
        internal UniqueEventHelper _progressEvent = new UniqueEventHelper(); 
 
        /// Event helper for download failed event
        internal UniqueEventHelper _failedEvent = new UniqueEventHelper(); 

        /// SyncObject
        private object _syncObject = new Object();
 
        // this is data that we cache as a performance optimization. It is ok to do so since we do not want to
        // handle this key change in the lifetime of this app. 
        private static SecurityCriticalDataForSet isImageDisabled; 
        /// 
        ///     Critical: This variable guards against reinitialization of the cached registry value 
        /// 
        [SecurityCritical]
        private static bool isImageDisabledInitialized;
 
        // For UnmanagedMemoryStream we want to make sure that buffer
        // its pointing to is not getting release until decoder is alive 
        private UnmanagedMemoryStream _unmanagedMemoryStream; 

        ///  
        ///     Critical: This variable guards against closing of the filehandle
        ///      which gets passed to unmanaged decoder.
        /// 
        [SecurityCritical] 
        private SafeFileHandle _safeFilehandle;
 
        private BitmapDecoder _cachedDecoder; 

        #endregion 

    }

    #endregion // BitmapDecoder 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2003
//
//  File: BitmapDecoder.cs 
//
//----------------------------------------------------------------------------- 
#pragma warning disable 1634, 1691 // Allow suppression of certain presharp messages 

using System; 
using System.IO;
using System.IO.Packaging;
using System.Collections;
using System.Collections.Generic; 
using System.ComponentModel;
using System.ComponentModel.Design.Serialization; 
using System.Collections.ObjectModel; 
using System.Reflection;
using System.Security; 
using System.Security.Permissions;
using System.Text.RegularExpressions;
using MS.Internal;
using MS.Internal.AppModel; 
using MS.Win32.PresentationCore;
using Microsoft.Win32.SafeHandles; 
using System.Diagnostics; 
using System.Windows.Media;
using System.Globalization; 
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Threading;
using System.Windows.Media.Imaging; 
using MS.Internal.PresentationCore;                        // SecurityHelper
using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID; 
using System.Net;
using System.Net.Cache; 
using System.Text;

namespace System.Windows.Media.Imaging
{ 
    #region BitmapDecoder
 
    ///  
    /// BitmapDecoder is a container for bitmap frames.  Each bitmap frame is an BitmapFrame.
    /// Any BitmapFrame it returns are frozen 
    /// be immutable.
    /// 
    public abstract class BitmapDecoder : DispatcherObject
    { 
        #region Constructors
 
        ///  
        ///     Critical: This code has critical static variables isImageDisabledInitialized
        ///     TreatAsASafe: The variables are not exposed 
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        static BitmapDecoder()
        { 
            isImageDisabledInitialized = false;
        } 
        ///  
        /// Default constructor
        ///  
        protected BitmapDecoder()
        {
        }
 
        /// 
        /// Internal constructor 
        ///  
        internal BitmapDecoder(bool isBuiltIn)
        { 
            _isBuiltInDecoder = isBuiltIn;
        }

        ///  
        /// Constructor
        ///  
        ///  
        /// Critical - access critical resource
        ///  
        [SecurityCritical]
        internal BitmapDecoder(
            Uri bitmapUri,
            BitmapCreateOptions createOptions, 
            BitmapCacheOption cacheOption,
            Guid expectedClsId 
            ) 
        {
            Guid clsId = Guid.Empty; 
            bool isOriginalWritable = false;

            if (bitmapUri == null)
            { 
                throw new ArgumentNullException("bitmapUri");
            } 
 
            if ((createOptions & BitmapCreateOptions.IgnoreImageCache) != 0)
            { 
                ImagingCache.RemoveFromDecoderCache(bitmapUri);
            }

            BitmapDecoder decoder = CheckCache(bitmapUri, out clsId); 
            if (decoder != null)
            { 
                _decoderHandle = decoder.InternalDecoder; 
            }
            else 
            {
                _decoderHandle = SetupDecoderFromUriOrStream(
                    bitmapUri,
                    null, 
                    cacheOption,
                    out clsId, 
                    out isOriginalWritable, 
                    out _uriStream,
                    out _unmanagedMemoryStream, 
                    out _safeFilehandle
                    );
            }
 
            if (clsId != expectedClsId)
            { 
                throw new FileFormatException(bitmapUri, SR.Get(SRID.Image_CantDealWithUri)); 
            }
 
            _uri = bitmapUri;
            _createOptions = createOptions;
            _cacheOption = cacheOption;
            _syncObject = _decoderHandle; 
            _isOriginalWritable = isOriginalWritable;
            Initialize(decoder); 
        } 

        ///  
        /// Constructor
        /// 
        /// 
        /// Critical - access critical resource 
        /// 
        [SecurityCritical] 
        internal BitmapDecoder( 
            Stream bitmapStream,
            BitmapCreateOptions createOptions, 
            BitmapCacheOption cacheOption,
            Guid expectedClsId
            )
        { 
            Guid clsId = Guid.Empty;
            bool isOriginalWritable = false; 
 
            if (bitmapStream == null)
            { 
                throw new ArgumentNullException("bitmapStream");
            }

            _decoderHandle = SetupDecoderFromUriOrStream( 
                null,
                bitmapStream, 
                cacheOption, 
                out clsId,
                out isOriginalWritable, 
                out _uriStream,
                out _unmanagedMemoryStream,
                out _safeFilehandle
                ); 

            if (clsId != Guid.Empty && clsId != expectedClsId) 
            { 
                throw new FileFormatException(null, SR.Get(SRID.Image_CantDealWithStream));
            } 

            _stream = bitmapStream;
            _createOptions = createOptions;
            _cacheOption = cacheOption; 
            _syncObject = _decoderHandle;
            _isOriginalWritable = isOriginalWritable; 
            Initialize(null); 
        }
 
        /// 
        /// Constructor
        /// 
        ///  
        /// Critical - access critical resources
        /// TreatAsSafe - All inputs verified 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal BitmapDecoder( 
            SafeMILHandle decoderHandle,
            BitmapDecoder decoder,
            Uri baseUri,
            Uri uri, 
            Stream stream,
            BitmapCreateOptions createOptions, 
            BitmapCacheOption cacheOption, 
            bool insertInDecoderCache,
            bool isOriginalWritable, 
            Stream uriStream,
            UnmanagedMemoryStream unmanagedMemoryStream,
            SafeFileHandle safeFilehandle
            ) 
        {
            _decoderHandle = decoderHandle; 
            _baseUri = baseUri; 
            _uri = uri;
            _stream = stream; 
            _createOptions = createOptions;
            _cacheOption = cacheOption;
            _syncObject = decoderHandle;
            _shouldCacheDecoder = insertInDecoderCache; 
            _isOriginalWritable = isOriginalWritable;
            _uriStream = uriStream; 
            _unmanagedMemoryStream = unmanagedMemoryStream; 
            _safeFilehandle = safeFilehandle;
 
            Initialize(decoder);
        }

        ///  
        /// Create BitmapDecoder from the uri or stream. If both are specified, the uri
        /// is chosen. 
        ///  
        /// 
        /// Critical - Unmanaged code will eventually create a COM object, need to secure it 
        /// TreatAsSafe - All inputs verified
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal static BitmapDecoder CreateFromUriOrStream( 
            Uri baseUri,
            Uri uri, 
            Stream stream, 
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption, 
            RequestCachePolicy uriCachePolicy,
            bool insertInDecoderCache
            )
        { 
            Guid clsId = Guid.Empty;
            bool isOriginalWritable = false; 
            SafeMILHandle decoderHandle = null; 
            BitmapDecoder cachedDecoder = null;
            Uri finalUri = null; 
            Stream uriStream = null;
            UnmanagedMemoryStream unmanagedMemoryStream = null;
            SafeFileHandle safeFilehandle = null;
 
            // check to ensure that images are allowed in partial trust
            DemandIfImageBlocked(); 
 
            if (uri != null)
            { 
                finalUri = (baseUri != null) ?
                               System.Windows.Navigation.BaseUriHelper.GetResolvedUri(baseUri, uri) :
                               uri;
 
                if (insertInDecoderCache)
                { 
                    if ((createOptions & BitmapCreateOptions.IgnoreImageCache) != 0) 
                    {
                        ImagingCache.RemoveFromDecoderCache(finalUri); 
                    }

                    cachedDecoder = CheckCache(
                        finalUri, 
                        out clsId
                        ); 
                } 
            }
 
            // try to retrieve the cached decoder
            if (cachedDecoder != null)
            {
                decoderHandle = cachedDecoder.InternalDecoder; 
            }
            else if ((finalUri != null) && (finalUri.IsAbsoluteUri) && (stream == null) && 
                     ((finalUri.Scheme == Uri.UriSchemeHttp) || 
                      (finalUri.Scheme == Uri.UriSchemeHttps)))
            { 
                return new LateBoundBitmapDecoder(baseUri, uri, stream, createOptions, cacheOption, uriCachePolicy);
            }
            else if ((stream != null) && (!stream.CanSeek))
            { 
                return new LateBoundBitmapDecoder(baseUri, uri, stream, createOptions, cacheOption, uriCachePolicy);
            } 
            else 
            {
                // Create an unmanaged decoder 
                decoderHandle = BitmapDecoder.SetupDecoderFromUriOrStream(
                    finalUri,
                    stream,
                    cacheOption, 
                    out clsId,
                    out isOriginalWritable, 
                    out uriStream, 
                    out unmanagedMemoryStream,
                    out safeFilehandle 
                    );
            }

            BitmapDecoder decoder = null; 

            // Find out the decoder type and wrap it appropriately and return that 
            if (MILGuidData.GUID_ContainerFormatBmp == clsId) 
            {
                decoder = new BmpBitmapDecoder( 
                    decoderHandle,
                    cachedDecoder,
                    baseUri,
                    uri, 
                    stream,
                    createOptions, 
                    cacheOption, 
                    insertInDecoderCache,
                    isOriginalWritable, 
                    uriStream,
                    unmanagedMemoryStream,
                    safeFilehandle
                    ); 
            }
            else if (MILGuidData.GUID_ContainerFormatGif == clsId) 
            { 
                decoder = new GifBitmapDecoder(
                    decoderHandle, 
                    cachedDecoder,
                    baseUri,
                    uri,
                    stream, 
                    createOptions,
                    cacheOption, 
                    insertInDecoderCache, 
                    isOriginalWritable,
                    uriStream, 
                    unmanagedMemoryStream,
                    safeFilehandle
                    );
            } 
            else if (MILGuidData.GUID_ContainerFormatIco == clsId)
            { 
                decoder = new IconBitmapDecoder( 
                    decoderHandle,
                    cachedDecoder, 
                    baseUri,
                    uri,
                    stream,
                    createOptions, 
                    cacheOption,
                    insertInDecoderCache, 
                    isOriginalWritable, 
                    uriStream,
                    unmanagedMemoryStream, 
                    safeFilehandle
                    );
            }
            else if (MILGuidData.GUID_ContainerFormatJpeg == clsId) 
            {
                decoder = new JpegBitmapDecoder( 
                    decoderHandle, 
                    cachedDecoder,
                    baseUri, 
                    uri,
                    stream,
                    createOptions,
                    cacheOption, 
                    insertInDecoderCache,
                    isOriginalWritable, 
                    uriStream, 
                    unmanagedMemoryStream,
                    safeFilehandle 
                    );
            }
            else if (MILGuidData.GUID_ContainerFormatPng == clsId)
            { 
                decoder = new PngBitmapDecoder(
                    decoderHandle, 
                    cachedDecoder, 
                    baseUri,
                    uri, 
                    stream,
                    createOptions,
                    cacheOption,
                    insertInDecoderCache, 
                    isOriginalWritable,
                    uriStream, 
                    unmanagedMemoryStream, 
                    safeFilehandle
                    ); 
            }
            else if (MILGuidData.GUID_ContainerFormatTiff == clsId)
            {
                decoder = new TiffBitmapDecoder( 
                    decoderHandle,
                    cachedDecoder, 
                    baseUri, 
                    uri,
                    stream, 
                    createOptions,
                    cacheOption,
                    insertInDecoderCache,
                    isOriginalWritable, 
                    uriStream,
                    unmanagedMemoryStream, 
                    safeFilehandle 
                    );
            } 
            else if (MILGuidData.GUID_ContainerFormatWmp == clsId)
            {
                decoder = new WmpBitmapDecoder(
                    decoderHandle, 
                    cachedDecoder,
                    baseUri, 
                    uri, 
                    stream,
                    createOptions, 
                    cacheOption,
                    insertInDecoderCache,
                    isOriginalWritable,
                    uriStream, 
                    unmanagedMemoryStream,
                    safeFilehandle 
                    ); 
            }
            else 
            {
                decoder = new UnknownBitmapDecoder(
                    decoderHandle,
                    cachedDecoder, 
                    baseUri,
                    uri, 
                    stream, 
                    createOptions,
                    cacheOption, 
                    insertInDecoderCache,
                    isOriginalWritable,
                    uriStream,
                    unmanagedMemoryStream, 
                    safeFilehandle
                    ); 
            } 

            return decoder; 
        }

        /// 
        /// Create a BitmapDecoder from a Uri with the specified BitmapCreateOptions and 
        /// BitmapCacheOption
        ///  
        /// Uri to decode 
        /// Bitmap Create Options
        /// Bitmap Caching Option 
        public static BitmapDecoder Create(
            Uri bitmapUri,
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption 
            )
        { 
            return Create(bitmapUri, createOptions, cacheOption, null); 
        }
 
        /// 
        /// Create a BitmapDecoder from a Uri with the specified BitmapCreateOptions and
        /// BitmapCacheOption
        ///  
        /// Uri to decode
        /// Bitmap Create Options 
        /// Bitmap Caching Option 
        /// Optional web request cache policy
        public static BitmapDecoder Create( 
            Uri bitmapUri,
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption,
            RequestCachePolicy uriCachePolicy 
            )
        { 
            if (bitmapUri == null) 
            {
                throw new ArgumentNullException("bitmapUri"); 
            }

            return CreateFromUriOrStream(
                null, 
                bitmapUri,
                null, 
                createOptions, 
                cacheOption,
                uriCachePolicy, 
                true
                );
        }
 
        /// 
        /// Create a BitmapDecoder from a Stream with the specified BitmapCreateOptions and 
        /// BitmapCacheOption 
        /// 
        /// Stream to decode 
        /// Bitmap Create Options
        /// Bitmap Caching Option
        public static BitmapDecoder Create(
            Stream bitmapStream, 
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption 
            ) 
        {
            if (bitmapStream == null) 
            {
                throw new ArgumentNullException("bitmapStream");
            }
 
            return CreateFromUriOrStream(
                null, 
                null, 
                bitmapStream,
                createOptions, 
                cacheOption,
                null,
                true
                ); 
        }
 
        #endregion 

        #region Properties 

        /// 
        /// If there is an palette, return it.
        /// Otherwise, return null. 
        /// 
        ///  
        /// Critical - Access unmanaged code, codecs 
        /// PublicOK - Getting palette data is OK
        ///  
        public virtual BitmapPalette Palette
        {
            [SecurityCritical ]
            get 
            {
                VerifyAccess(); 
                EnsureBuiltInDecoder(); 

                if (!_isPaletteCached) 
                {
                    SafeMILHandle /* IWICBitmapPalette */ paletteHandle = BitmapPalette.CreateInternalPalette();

                    lock (_syncObject) 
                    {
                        int hr = UnsafeNativeMethods.WICBitmapDecoder.CopyPalette( 
                            _decoderHandle, 
                            paletteHandle
                            ); 
                        if (hr != (int)WinCodecErrors.WINCODEC_ERR_PALETTEUNAVAILABLE)
                        {
                            HRESULT.Check(hr);
                            _palette = new BitmapPalette(paletteHandle); 
                        }
                    } 
 
                    _isPaletteCached = true;
                } 

                return _palette;
            }
        } 

        ///  
        /// If there is an embedded color profile, return it. 
        /// Otherwise, return null.
        ///  
        /// 
        /// Critical - Access unmanaged code, codecs
        /// PublicOK - Getting colorcontext data is OK
        ///  
        public virtual ReadOnlyCollection ColorContexts
        { 
            [SecurityCritical ] 
            get
            { 
                return InternalColorContexts;
            }
        }
 
        /// 
        /// If there is a global thumbnail, return it. 
        /// Otherwise, return null. The returned source is frozen. 
        /// 
        ///  
        /// Critical - Access unmanaged code, codecs
        /// PublicOK - Getting thumbnail data is OK
        /// 
        public virtual BitmapSource Thumbnail 
        {
            [SecurityCritical ] 
            get 
            {
                VerifyAccess(); 
                EnsureBuiltInDecoder();

                if (!_isThumbnailCached)
                { 
                    IntPtr /* IWICBitmapSource */ thumbnail = IntPtr.Zero;
 
                    // Check if there is embedded thumbnail or not 
                    lock (_syncObject)
                    { 
                        int hr = UnsafeNativeMethods.WICBitmapDecoder.GetThumbnail(
                            _decoderHandle,
                            out thumbnail
                            ); 
                        if (hr != (int)WinCodecErrors.WINCODEC_ERR_CODECNOTHUMBNAIL)
                        { 
                            HRESULT.Check(hr); 
                        }
                    } 

                    if (thumbnail != IntPtr.Zero)
                    {
                        BitmapSourceSafeMILHandle thumbHandle = new BitmapSourceSafeMILHandle(thumbnail); 
                        SafeMILHandle unmanagedPalette = BitmapPalette.CreateInternalPalette();
                        BitmapPalette palette = null; 
 
                        int hr = UnsafeNativeMethods.WICBitmapSource.CopyPalette(
                                    thumbHandle, 
                                    unmanagedPalette
                                    );
                        if (hr == HRESULT.S_OK)
                        { 
                            palette = new BitmapPalette(unmanagedPalette);
                        } 
 
                        _thumbnail = new UnmanagedBitmapWrapper(
                            BitmapSource.CreateCachedBitmap( 
                                null,
                                thumbHandle,
                                BitmapCreateOptions.PreservePixelFormat,
                                _cacheOption, 
                                palette
                                )); 
                        _thumbnail.Freeze(); 
                    }
 
                    _isThumbnailCached = true;
                }

                return _thumbnail; 
            }
        } 
 
        /// 
        /// If there is a global metadata, return it. 
        /// Otherwise, return null. The returned source is frozen.
        /// 
        /// 
        ///     Critical - Access unmanaged code, codecs 
        ///     Public -
        ///       Getting metadata for images from site of origin or bundled with the application is OK 
        ///       Getting metatdat for images from cross domain servers triggers a demand for site of origin. 
        /// 
        public virtual BitmapMetadata Metadata 
        {
            [SecurityCritical]
            get
            { 
                VerifyAccess();
                EnsureBuiltInDecoder(); 
 
                // Demand Site Of origin on the URI if it passes then this  information is ok to expose
                CheckIfSiteOfOrigin(); 

                if (!_isMetadataCached)
                {
 
                    IntPtr /* IWICMetadataQueryReader */ metadata = IntPtr.Zero;
 
                    lock (_syncObject) 
                    {
                        int hr = UnsafeNativeMethods.WICBitmapDecoder.GetMetadataQueryReader( 
                            _decoderHandle,
                            out metadata
                            );
                        if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION) 
                        {
                            HRESULT.Check(hr); 
                        } 
                    }
 
                    if (metadata != IntPtr.Zero)
                    {
                        SafeMILHandle metadataHandle = new SafeMILHandle(metadata, 0);
 
                        _metadata = new BitmapMetadata(metadataHandle, true, IsMetadataFixedSize, _syncObject);
                        _metadata.Freeze(); 
                    } 

                    _isMetadataCached = true; 
                }

                return _metadata;
            } 
        }
 
        ///  
        /// The info that identifies this codec.
        ///  
        /// 
        /// Critical - Access unmanaged code, codecs
        /// PublicOK - Getting codecinfo data is OK
        ///  
        public virtual BitmapCodecInfo CodecInfo
        { 
            [SecurityCritical ] 
            get
            { 
                VerifyAccess();
                EnsureBuiltInDecoder();

                // There should always be a codec info. 
                if (_codecInfo == null)
                { 
                    SafeMILHandle /* IWICBitmapDecoderInfo */ codecInfoHandle =  new SafeMILHandle(); 

                    HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetDecoderInfo( 
                        _decoderHandle,
                        out codecInfoHandle
                        ));
 
                    _codecInfo = new BitmapCodecInfoInternal(codecInfoHandle);
                } 
 
                return _codecInfo;
            } 
        }

        /// 
        /// Access to the individual frames. All BitmapFrames are frozen. 
        /// 
        public virtual ReadOnlyCollection Frames 
        { 
            get
            { 
                VerifyAccess();
                EnsureBuiltInDecoder();

                if (_frames == null) 
                {
                    SetupFrames(null, null); 
                } 

                if (_readOnlyFrames == null) 
                {
                    _readOnlyFrames = new ReadOnlyCollection(_frames);
                }
 
                return _readOnlyFrames;
            } 
        } 

        ///  
        /// If there is a global preview image, return it.
        /// Otherwise, return null. The returned source is frozen.
        /// 
        ///  
        /// Critical - Access unmanaged code, codecs
        /// PublicOK - Getting preview data is OK 
        ///  
        public virtual BitmapSource Preview
        { 
            [SecurityCritical ]
            get
            {
                VerifyAccess(); 
                EnsureBuiltInDecoder();
 
                if (!_isPreviewCached) 
                {
                    IntPtr /* IWICBitmapSource */ preview = IntPtr.Zero; 

                    lock (_syncObject)
                    {
                        // Check if there is embedded preview or not 
                        int hr = UnsafeNativeMethods.WICBitmapDecoder.GetPreview(
                            _decoderHandle, 
                            out preview 
                            );
                        if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION) 
                        {
                            HRESULT.Check(hr);
                        }
                    } 

                    if (preview != IntPtr.Zero) 
                    { 
                        BitmapSourceSafeMILHandle previewHandle = new BitmapSourceSafeMILHandle(preview);
                        SafeMILHandle unmanagedPalette = BitmapPalette.CreateInternalPalette(); 
                        BitmapPalette palette = null;

                        int hr = UnsafeNativeMethods.WICBitmapSource.CopyPalette(
                                    previewHandle, 
                                    unmanagedPalette
                                    ); 
                        if (hr == HRESULT.S_OK) 
                        {
                            palette = new BitmapPalette(unmanagedPalette); 
                        }

                        _preview = new UnmanagedBitmapWrapper(
                            BitmapSource.CreateCachedBitmap( 
                                null,
                                previewHandle, 
                                BitmapCreateOptions.PreservePixelFormat, 
                                _cacheOption,
                                palette 
                                ));
                        _preview.Freeze();
                    }
 
                    _isPreviewCached = true;
                } 
 
                return _preview;
            } 
        }

        /// 
        /// Returns true if the decoder is downloading content 
        /// 
        public virtual bool IsDownloading 
        { 
            get
            { 
                VerifyAccess();
                EnsureBuiltInDecoder();
                return false;
            } 
        }
 
        ///  
        /// Raised when decoder has completed downloading content
        /// May not be raised for all content. 
        /// 
        public virtual event EventHandler DownloadCompleted
        {
            add 
            {
                VerifyAccess(); 
                EnsureBuiltInDecoder(); 
                _downloadEvent.AddEvent(value);
            } 
            remove
            {
                VerifyAccess();
                EnsureBuiltInDecoder(); 
                _downloadEvent.RemoveEvent(value);
            } 
        } 

        ///  
        /// Raised when download has progressed
        /// May not be raised for all content.
        /// 
        public virtual event EventHandler DownloadProgress 
        {
            add 
            { 
                VerifyAccess();
                EnsureBuiltInDecoder(); 
                _progressEvent.AddEvent(value);
            }
            remove
            { 
                VerifyAccess();
                EnsureBuiltInDecoder(); 
                _progressEvent.RemoveEvent(value); 
            }
        } 

        /// 
        /// Raised when download has failed
        /// May not be raised for all content. 
        /// 
        public virtual event EventHandler DownloadFailed 
        { 
            add
            { 
                VerifyAccess();
                EnsureBuiltInDecoder();
                _failedEvent.AddEvent(value);
            } 
            remove
            { 
                VerifyAccess(); 
                EnsureBuiltInDecoder();
                _failedEvent.RemoveEvent(value); 
            }
        }

        #endregion 

        #region Public Properties 
 
        /// 
        /// Create an in-place bitmap metadata writer. 
        /// 
        public virtual InPlaceBitmapMetadataWriter CreateInPlaceBitmapMetadataWriter()
        {
            VerifyAccess(); 
            EnsureBuiltInDecoder();
 
            CheckOriginalWritable(); 

            // Demand Site Of origin on the URI if it passes then this  information is ok to expose 
            CheckIfSiteOfOrigin();

            return InPlaceBitmapMetadataWriter.CreateFromDecoder(_decoderHandle, _syncObject);
        } 

        #endregion 
 
        #region ToString
 
        /// 
        /// ToString
        /// 
        public override string ToString() 
        {
            VerifyAccess(); 
 
            if (!_isBuiltInDecoder)
            { 
                return base.ToString();
            }

            if (_uri != null) 
            {
                if (_baseUri != null) 
                { 
                    Uri uri = new Uri(_baseUri, _uri);
                    return BindUriHelper.UriToString(uri); 
                }
                else
                {
                    return BindUriHelper.UriToString(_uri); 
                }
            } 
            else 
            {
                return SafeSecurityHelper.IMAGE; 
            }
        }

        #endregion 

        #region Internal Properties 
 
        /// 
        /// Internal Decoder 
        /// 
        internal SafeMILHandle InternalDecoder
        {
            get 
            {
                return _decoderHandle; 
            } 
        }
 
        /// 
        /// Returns whether metadata is fixed size or not.
        /// 
        internal virtual bool IsMetadataFixedSize 
        {
            get 
            { 
                return false;
            } 
        }

        /// 
        /// Synchronization Object.  Any unmanaged PInvoke/call that requires synchronization 
        /// must lock on the [....] object.  This object must be internal or private so as not
        /// to be publicly lockable. 
        ///  
        internal object SyncObject
        { 
            get
            {
                Debug.Assert(_syncObject != null);
                return _syncObject; 
            }
        } 
 
        /// 
        /// If there is an embedded color profile, return it. 
        /// Otherwise, return null.
        /// 
        /// 
        /// Critical - Access unmanaged code, codecs 
        /// TreatAsSafe - Getting colorcontext data is OK
        ///  
        internal ReadOnlyCollection InternalColorContexts 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            {
                VerifyAccess();
                EnsureBuiltInDecoder(); 

                if (!_isColorContextCached) 
                { 

                    // Check if there is colorContext or not 
                    lock (_syncObject)
                    {
                        unsafe
                        { 

                            uint uiCount = 0; 
 
                            int hr = UnsafeNativeMethods.WICBitmapDecoder.GetColorContexts(
                                _decoderHandle, 
                                0,
                                IntPtr.Zero,
                                out uiCount
                                ); 

                            if (hr != (int)WinCodecErrors.WINCODEC_ERR_UNSUPPORTEDOPERATION) 
                            { 
                                HRESULT.Check(hr);
                            } 

                            if (uiCount > 0)
                            {
                                List colorContextsList = new List((int)uiCount); 

                                IntPtr* pcolorContextslocal = stackalloc IntPtr[(int)uiCount]; 
                                for (int i = 0; i < uiCount; i++) pcolorContextslocal[i] = IntPtr.Zero; 

                                SafeMILHandle[] colorContextHandles = new SafeMILHandle[uiCount]; 

                                using (FactoryMaker factoryMaker = new FactoryMaker())
                                {
                                    try 
                                    {
                                        for (int i = 0; i < uiCount; i++) 
                                        { 
                                            Guid wicColorContextGuid = MILGuidData.IID_IWICColorContext;
 
                                            HRESULT.Check(UnsafeNativeMethods.WICCodec.CreateColorContext(factoryMaker.ImagingFactoryPtr, out colorContextHandles[i]));

                                            HRESULT.Check(UnsafeNativeMethods.MILUnknown.QueryInterface(colorContextHandles[i], ref wicColorContextGuid, out pcolorContextslocal[i]));
                                        } 

                                    } 
                                    finally 
                                    {
                                        for (int i = 0; i < uiCount; i++) 
                                        {
                                            #pragma warning suppress 6031 // Return value ignored on purpose.
                                            UnsafeNativeMethods.MILUnknown.Release(pcolorContextslocal[i]);
                                        } 
                                    }
                                } 
                                HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetColorContexts( 
                                    _decoderHandle,
                                    uiCount, 
                                    (IntPtr)pcolorContextslocal,
                                    out uiCount
                                    ));
 
                                for (uint i = 0; i < uiCount; i++)
                                { 
                                    colorContextsList.Add(new ColorContext(colorContextHandles[i])); 
                                }
 
                                _readOnlycolorContexts = new ReadOnlyCollection(colorContextsList);
                            }

                            _isColorContextCached = true; 

                        } 
                    } 

                } 

                return _readOnlycolorContexts;
            }
        } 

 
        ///  
        /// Checks whether the underlying source is writable (useful for in-place metadata editing)
        ///  
        internal void CheckOriginalWritable()
        {
            if (!_isOriginalWritable)
            { 
                throw new System.InvalidOperationException(SR.Get(SRID.Image_OriginalStreamReadOnly));
            } 
        } 

        #endregion 

        #region Internal/Private Methods
        /// 
        ///     Critical: This sets and accesses critical members isImageDisabledInitialized,isImageDisabled 
        ///     TreatAsSafe: This code does not expose the variables and is not influenced by external paramaters that do not
        ///     require unmanaged code access permission to set 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private static void DemandIfImageBlocked() 
        {
            if(!isImageDisabledInitialized)
            {
                // a performance optimization to ensure we hit the registry only once in the lifetime of the application 
                isImageDisabled = new SecurityCriticalDataForSet(SafeSecurityHelper.IsFeatureDisabled(SafeSecurityHelper.KeyToRead.MediaImageDisable));
                isImageDisabledInitialized = true; 
            } 
            if (isImageDisabled.Value)
            { 
                // in case the registry key is '1' then demand MediaPermissionImage.AllImage - not granted in Partial Trust
                SecurityHelper.DemandMediaPermission(MediaPermissionAudio.NoAudio,
                                                     MediaPermissionVideo.NoVideo,
                                                     MediaPermissionImage.AllImage); 
            }
            else 
            { 
                // Images are enabled. Then, demand permissions for safe imaging - granted in Partial Trust by default
                SecurityHelper.DemandMediaPermission(MediaPermissionAudio.NoAudio, 
                                                     MediaPermissionVideo.NoVideo,
                                                     MediaPermissionImage.SafeImage);
            }
        } 

        ///  
        /// Critical - Unmanaged code will eventually create a COM object, need to secure it 
        /// 
        [SecurityCritical] 
        internal static SafeMILHandle SetupDecoderFromUriOrStream(
            Uri uri,
            Stream stream,
            BitmapCacheOption cacheOption, 
            out Guid clsId,
            out bool isOriginalWritable, 
            out Stream uriStream, 
            out UnmanagedMemoryStream unmanagedMemoryStream,
            out SafeFileHandle safeFilehandle 
            )
        {
            SafeMILHandle decoderHandle;
            IntPtr decoder = IntPtr.Zero; 
            System.IO.Stream bitmapStream = null;
            string mimeType = String.Empty; 
            // check to ensure that images are allowed in partial trust NOP in full trust 
            DemandIfImageBlocked();
            unmanagedMemoryStream = null; 
            safeFilehandle = null;
            isOriginalWritable = false;
            uriStream = null;
 
            if ((uri != null) && (stream != null))
            { 
                // In this case we expect the Uri to be http(s) 
                Debug.Assert((uri.Scheme == Uri.UriSchemeHttp) || (uri.Scheme == Uri.UriSchemeHttps));
                Debug.Assert(stream.CanSeek); 
            }

            // Uri
            if (uri != null) 
            {
                if (uri.IsAbsoluteUri) 
                { 
                    // In this case we first check to see if the consumer has media permissions for
                    // safe media (Site of Origin + Cross domain) 
                    SecurityHelper.DemandMediaPermission(MediaPermissionAudio.NoAudio,
                                                         MediaPermissionVideo.NoVideo,
                                                         MediaPermissionImage.SiteOfOriginImage) ;
                    // This code path executes only for pack web requests 
                    if (String.Compare(uri.Scheme, PackUriHelper.UriSchemePack, StringComparison.OrdinalIgnoreCase) == 0)
                    { 
                        WebResponse response = WpfWebRequestHelper.CreateRequestAndGetResponse(uri); 
                        mimeType = response.ContentType;
                        bitmapStream = response.GetResponseStream(); 
                        uriStream = bitmapStream;
                    }
                }
 
                if ((bitmapStream == null) || (bitmapStream == System.IO.Stream.Null))
                { 
                    // We didn't get a stream from the pack web request, so we have 
                    // to try to create one ourselves.
                    if (uri.IsAbsoluteUri) 
                    {
                        // The Uri class can't tell if it is a file unless it
                        // has an absolute path.
                        int targetZone = SecurityHelper.MapUrlToZoneWrapper(uri); 
                        if (targetZone == MS.Win32.NativeMethods.URLZONE_LOCAL_MACHINE)
                        { 
                            if (uri.IsFile) 
                            {
                                // FileStream does a demand for us, so no need to do a demand 
                                bitmapStream = new System.IO.FileStream(uri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
                            }
                        }
                        else // Any other zone 
                        {
                            // UNC path for a file which is not http 
                            if (uri.IsFile && uri.IsUnc) // for UNC 
                            {
                                bitmapStream = ProcessUncFiles(uri); 
                            }
                            else if (uri.Scheme == Uri.UriSchemeHttp) // for http
                            {
                                bitmapStream = ProcessHttpFiles(uri,stream); 
                            }
                            else if (uri.Scheme == Uri.UriSchemeHttps) // for https 
                            { 
                                bitmapStream = ProcessHttpsFiles(uri,stream);
                            } 
                            else
                            {
                                // The Uri is a custom Uri. Try to grab the stream from its WebResponse.
                                bitmapStream = WpfWebRequestHelper.CreateRequestAndGetResponseStream(uri); 
                            }
                        } 
                    } 
                    else
                    { 
                        #pragma warning disable 6518
                        // We don't have an absolute URI, so we don't necessarily know
                        // if it is a file, but we'll have to assume it is and try to
                        // create a stream from the original string. 
                        bitmapStream = new System.IO.FileStream(uri.OriginalString, FileMode.Open, FileAccess.Read, FileShare.Read);
                        #pragma warning restore 6518 
                    } 

                    uriStream = bitmapStream; 
                }
            }

            // We need to use the stream created from the Uri. 
            if (bitmapStream != null)
            { 
                stream = bitmapStream; 
            }
            else 
            {
                // Note whether the original stream is writable.
                isOriginalWritable = stream.CanSeek && stream.CanWrite;
            } 

            // Make sure we always use a seekable stream to avoid problems with http Uris etc. 
            stream = GetSeekableStream(stream); 

            if (stream is UnmanagedMemoryStream) 
            {
                unmanagedMemoryStream = stream as UnmanagedMemoryStream;
            }
 
            IntPtr comStream = IntPtr.Zero;
 
            if (stream is System.IO.FileStream) 
            {
                System.IO.FileStream filestream = stream as System.IO.FileStream; 

                try
                {
                    safeFilehandle = filestream.SafeFileHandle; 
                }
                catch 
                { 
                    // If Filestream doesn't support SafeHandle then revert to old code path.
                    safeFilehandle = null; 
                }
            }

            try 
            {
                Guid vendorMicrosoft = new Guid(MILGuidData.GUID_VendorMicrosoft); 
                UInt32 metadataFlags = (uint)WICMetadataCacheOptions.WICMetadataCacheOnDemand; 

                if (cacheOption == BitmapCacheOption.OnLoad) 
                {
                    metadataFlags = (uint)WICMetadataCacheOptions.WICMetadataCacheOnLoad;
                }
 
                // We have a SafeHandle.
                if (safeFilehandle != null) 
                { 
                    using (FactoryMaker myFactory = new FactoryMaker())
                    { 
                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateDecoderFromFileHandle(
                            myFactory.ImagingFactoryPtr,
                            safeFilehandle,
                            ref vendorMicrosoft, 
                            metadataFlags,
                            out decoder 
                            )); 
                    }
                } 
                else
                {
                    comStream = BitmapDecoder.GetIStreamFromStream(ref stream);
 
                    using (FactoryMaker myFactory = new FactoryMaker())
                    { 
 
                        // This does an add-ref on the comStream
                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateDecoderFromStream( 
                            myFactory.ImagingFactoryPtr,
                            comStream,
                            ref vendorMicrosoft,
                            metadataFlags, 
                            out decoder
                            )); 
                    } 
                }
                Debug.Assert(decoder != IntPtr.Zero); 
                decoderHandle = new SafeMILHandle(decoder, 0);
            }
            catch
            { 
                #pragma warning disable 6500
 
                decoderHandle = null; 
                throw;
 
                #pragma warning restore 6500
            }
            finally
            { 
                UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref comStream);
            } 
 
            string decoderMimeTypes;
            clsId = GetCLSIDFromDecoder(decoderHandle, out decoderMimeTypes); 

            // If the mime type of the file does not match the associated decoder,
            // and if we are in a Partial trust scenario, throw!
            if ((mimeType != String.Empty) && 
                (decoderMimeTypes.IndexOf(mimeType, StringComparison.OrdinalIgnoreCase) == -1))
            { 
                try 
                {
                    SecurityHelper.DemandUnmanagedCode(); 
                }
                catch(SecurityException)
                {
                    throw new ArgumentException(SR.Get(SRID.Image_ContentTypeDoesNotMatchDecoder)); 
                }
            } 
 
            return decoderHandle;
        } 

        /// 
        /// Critical: performs an assert for WebPermission potentially outside the site of origin.
        ///  
        [SecurityCritical]
        private static Stream ProcessHttpsFiles(Uri uri, Stream stream) 
        { 
            Stream bitmapStream = stream;
            // This is the condition where the Bitmap has already been downloaded 
            // or the stream is not seekable
            // using async dowload in that case simply return the original stream
            // else you download the stream
            if (bitmapStream == null || !bitmapStream.CanSeek) 
            {
                WebRequest request = null; 
 
                // Block XDomain from apps deployed over HTTPS (For HTTP, LMZ and UNC apps, is ok to access images through HTTPS)
                SecurityHelper.BlockCrossDomainForHttpsApps(uri); 

                // now, we can Assert permissions because we ensured that only apps deployed through non-HTTPS can access XDomain images
                (new WebPermission(NetworkAccess.Connect, BindUriHelper.UriToString(uri))).Assert(); // BlessedAssert
                try 
                {
                    request = WpfWebRequestHelper.CreateRequest(uri); 
                } 
                finally
                { 
                    WebPermission.RevertAssert();
                }

                bitmapStream = WpfWebRequestHelper.GetResponseStream(request); 
            }
            return bitmapStream; 
        } 

        ///  
        ///     Critical: This code elevates and extracts a bitmap stream
        /// 
        [SecurityCritical]
        private static Stream ProcessHttpFiles(Uri uri, Stream stream) 
        {
            WebRequest request = null; 
            Stream bitmapStream =  stream; 
            SecurityHelper.BlockCrossDomainForHttpsApps(uri);
            // Download only if this content is not already downloaded or stream is not seekable 
            if (bitmapStream == null || !bitmapStream.CanSeek)
            {
                // In this case we first check to see if the consumer has media permissions for
                // safe media (Site of Origin + Cross domain), if it 
                // does we assert and run the code that requires the assert
                bool fElevate = false; 
                if (SecurityHelper.CallerHasMediaPermission(MediaPermissionAudio.NoAudio, 
                                                            MediaPermissionVideo.NoVideo,
                                                            MediaPermissionImage.SafeImage)) 
                {
                    fElevate = true;
                }
 
                if (fElevate)
                { 
                    (new WebPermission(NetworkAccess.Connect, BindUriHelper.UriToString(uri))).Assert(); // BlessedAssert 
                }
                try 
                {
                    request = WpfWebRequestHelper.CreateRequest(uri);
                }
                finally 
                {
                    if (fElevate) 
                    { 
                        WebPermission.RevertAssert();
                    } 
                }

                // Download only if this content is not already downloaded or stream is not seekable
                bitmapStream = WpfWebRequestHelper.GetResponseStream(request); 
            }
            return bitmapStream; 
        } 

        ///  
        ///     Critical: This code elevates and extracts a bitmap stream
        /// 
        [SecurityCritical]
        private static Stream ProcessUncFiles(Uri uri) 
        {
            Stream bitmapStream = null; 
 
            // perform checks for UNC content
            SecurityHelper.EnforceUncContentAccessRules(uri); 

            // In this case we first check to see if the consumer has media permissions for
            // safe media (Site of Origin + Cross domain), if it
            // does then we assert else we run the code without the assert 
            bool fElevate = false;
            if (SecurityHelper.CallerHasMediaPermission(MediaPermissionAudio.NoAudio, 
                                                        MediaPermissionVideo.NoVideo, 
                                                        MediaPermissionImage.SafeImage))
            { 
                fElevate = true;
            }

            if(fElevate) 
            {
                // since the code above ensures that safe image permission is granted we 
                // can now do an assert to allow cross domain web request 
                (new FileIOPermission(FileIOPermissionAccess.Read, uri.LocalPath)).Assert(); // BlessedAssert
            } 
            try
            {
                // FileStream does a demand for us, so no need to do a demand
                bitmapStream = new System.IO.FileStream(uri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read); 
            }
            finally 
            { 
                if(fElevate)
                { 
                    FileIOPermission.RevertAssert();
                }
            }
            return bitmapStream; 
        }
 
        ///  
        ///     Critical: This code is used to check and grant access to pixel data and metadata.
        ///     TreatAsSafe: This code does not elevate 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        void CheckIfSiteOfOrigin()
        { 
            string uri = null;
 
            if (CanConvertToString()) 
            {
                // This call returns the URI either as an absolute URI which the user 
                // passed in, in the first place or as the string "image"
                // we only allow this code to succeed in the case of Uri and if it is site of
                // origin or pack:. In all other conditions we fail
 
                uri = ToString();
            } 
 
            SecurityHelper.DemandMediaAccessPermission(uri);
        } 

        /// Returns the decoder's CLSID
        /// 
        /// Critical - access unmanaged code to retrieve CLSID. 
        /// 
        [SecurityCritical] 
        private static Guid GetCLSIDFromDecoder(SafeMILHandle decoderHandle, out string decoderMimeTypes) 
        {
            Guid clsId; 

            // Get the decoder info
            SafeMILHandle decoderInfo = new SafeMILHandle();
            HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetDecoderInfo( 
                decoderHandle,
                out decoderInfo 
                )); 

            // Get CLSID for the decoder 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapCodecInfo.GetContainerFormat(decoderInfo, out clsId));

            StringBuilder mimeTypes = null;
            UInt32 length = 0; 

            // Find the length of the string needed 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapCodecInfo.GetMimeTypes( 
                decoderInfo,
                0, 
                mimeTypes,
                out length
                ));
 
            // get the string back
            if (length > 0) 
            { 
                mimeTypes = new StringBuilder((int)length);
 
                HRESULT.Check(UnsafeNativeMethods.WICBitmapCodecInfo.GetMimeTypes(
                    decoderInfo,
                    length,
                    mimeTypes, 
                    out length
                    )); 
            } 

            if (mimeTypes != null) 
            {
                decoderMimeTypes = mimeTypes.ToString();
            }
            else 
            {
                decoderMimeTypes = String.Empty; 
            } 

            return clsId; 
        }

        /// Return a seekable stream if the current one is not seekable
        private static System.IO.Stream GetSeekableStream(System.IO.Stream bitmapStream) 
        {
            // MIL codecs require the source stream to be seekable. But if 
            // the source stream is an internet stream, it is not seekable. 
            // The data is probably not in the stream yet.
 
            if (bitmapStream.CanSeek)
            {
                return bitmapStream;
            } 

            // If the source is not seekable, we have to download the 
            // stream into a memory stream before we can decode it. 
            // ISSUE-2002/10/03--minliu: later on, if we can make MIL
            // support progressive JPEG etc., we should take out the 
            // hack here and pass the network stream (CConectStream)
            // directly to the unmanaged code

            System.IO.MemoryStream memStream = 
                new System.IO.MemoryStream();
 
            byte[] buffer = new byte[1024]; 
            int read;
 
            // Read all the bytes and write it to a memory stream
            //

 

            do 
            { 
                read = bitmapStream.Read(buffer, 0, 1024);
                if (read <= 0) 
                {
                    break;
                }
                memStream.Write(buffer, 0, read); 
            } while (true);
 
            // Reset the memory stream pointer back to the begining 
            memStream.Seek(0, System.IO.SeekOrigin.Begin);
 
            // Use the new stream

            return memStream;
        } 

        /// Check the cache to see if decoder already exists 
        ///  
        /// Critical - Eventually calls code that calls unmanaged code.
        /// TreatAsSafe - Only checks imaging cache to see object exists 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private static BitmapDecoder CheckCache(
            Uri uri, 
            out Guid clsId
            ) 
        { 
            clsId = Guid.Empty;
            string mimeTypes; 

            if (uri != null)
            {
                WeakReference weakRef = ImagingCache.CheckDecoderCache(uri) as WeakReference; 
                if (weakRef != null)
                { 
                    BitmapDecoder bitmapDecoder = weakRef.Target as BitmapDecoder; 
                    if ((bitmapDecoder != null) && bitmapDecoder.CheckAccess())
                    { 
                        lock (bitmapDecoder.SyncObject)
                        {
                            clsId = GetCLSIDFromDecoder(bitmapDecoder.InternalDecoder, out mimeTypes);
                            return bitmapDecoder; 
                        }
                    } 
                    // Remove from the cache if bitmapDecoder is already been collected 
                    if (bitmapDecoder == null)
                    { 
                        ImagingCache.RemoveFromDecoderCache(uri);
                    }
                }
            } 

            return null; 
        } 

        ///  
        /// Initialize the codec.
        /// 
        /// 
        /// Critical - Will eventually create a COM object, need to secure it 
        /// 
        [SecurityCritical] 
        private void Initialize(BitmapDecoder decoder) 
        {
            _isBuiltInDecoder = true; 

            if (decoder != null)
            {
                SetupFrames(decoder, null); 
                //
                // We need to keep the strong reference to the cached decoder for a few reasons: 
                // 
                //    The application may release the original cached decoder and then keep a
                //    reference to this decoder only, in which case, the cache can be collected. 
                //    This will cause a few undesirable results:
                //    1. The application may choose to decode the same URI again in which case
                //       we will not retrieve it from the cache even though we have a copy already
                //       decoded. 
                //    2. The original cached decoder holds onto the file stream indirectly which if
                //       collected can cause bad behavior if the entire decoder is not loaded into 
                //       memory. 
                //
                _cachedDecoder = decoder; 
            }
            else if ((_createOptions & BitmapCreateOptions.DelayCreation) == 0 && _cacheOption == BitmapCacheOption.OnLoad)
            {
                SetupFrames(null, null); 

                // Its ok to close the stream since the frames are not delay created and caching is immediate 
                CloseStream(); 
            }
 

            if ((_uri != null) && (decoder == null) && _shouldCacheDecoder)
            {
 
                // Add this decoder to the decoder cache
                ImagingCache.AddToDecoderCache( 
                    (_baseUri == null) ? _uri : new Uri(_baseUri, _uri), 
                    new WeakReference(this)
                    ); 
            }
        }

        ///  
        /// Closes the stream if its non-null
        ///  
        ///  
        /// Critical - accesses critical resource _uriStream
        /// TreatAsSafe - doesn't return the uriStream, just closes it which is safe 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void CloseStream()
        { 
            if (_uriStream != null)
            { 
                _uriStream.Close(); 
            }
        } 

        /// 
        /// Sets up the frames collection.
        /// Also, ensures that the frame collection for this decoder 
        /// will contain the same underlying frames as the collection
        /// passed in. This is called by the LateBoundBitmapDecoder 
        ///  
        /// 
        /// Critical - access unmanaged code 
        /// TreatAsSafe - only access number of frames in the bitmap, a safe operation
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void SetupFrames(BitmapDecoder decoder, ReadOnlyCollection frames) 
        {
            uint numFrames = 1; 
 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetFrameCount(_decoderHandle, out numFrames));
 
            _frames = new List((int)numFrames);

            // initialize the list of frames to null.
            // We'll fill it as it's used (pay for play). 
            for (int i = 0; i < (int)numFrames; i++)
            { 
                if (i > 0 && _cacheOption != BitmapCacheOption.OnLoad) 
                {
                    _createOptions |= BitmapCreateOptions.DelayCreation; 
                }

                BitmapFrameDecode bfd = null;
 
                if ((frames != null) && (frames.Count == (i + 1)))
                { 
                    // If we already have a frames collection, get the BitmapFrame from it 
                    bfd = frames[i] as BitmapFrameDecode;
                    bfd.UpdateDecoder(this); 
                }
                else if (decoder == null)
                {
                    // All frames should be frozen. 
                    bfd = new BitmapFrameDecode(
                        i, 
                        null, 
                        _createOptions,
                        _cacheOption, 
                        this
                        );
                    bfd.Freeze();
                } 
                else
                { 
                    // if we are creating from an existing cache, use the frames 
                    // already stored in that cache
                    // All frames should be frozen. 
                    bfd = new BitmapFrameDecode(
                        i,
                        _createOptions,
                        _cacheOption, 
                        decoder.Frames[i] as BitmapFrameDecode
                        ); 
                    bfd.Freeze(); 
                }
 
                _frames.Add(bfd);
            }
        }
 
        /// 
        /// Checks if the decoder is builtin. If not, throw exception 
        ///  
        private void EnsureBuiltInDecoder()
        { 
            if (!_isBuiltInDecoder)
            {
                throw new NotImplementedException();
            } 
        }
 
        ///  
        /// Note, we must hold onto a reference to the managed stream
        /// as long as we are using the unmanaged stream in the decoder. 
        /// This method may create a new managed stream.
        ///

 

 
 

 
        [SecurityCritical]
        private static IntPtr GetIStreamFromStream(ref System.IO.Stream bitmapStream)
        {
            IntPtr  comStream = IntPtr.Zero; 

            // ensure the stream is seekable 
            bool seekable = bitmapStream.CanSeek; 

            if (bitmapStream is UnmanagedMemoryStream) 
            {
                UnmanagedMemoryStream memoryStream = bitmapStream as UnmanagedMemoryStream;
                IntPtr bufferPtr = IntPtr.Zero;
                int length = 0; 

                unsafe 
                { 
                   bufferPtr = (IntPtr) memoryStream.PositionPointer;
                   length = (int) memoryStream.Length; 
                }

                if (bufferPtr != IntPtr.Zero)
                { 
                    comStream = StreamAsIStream.IStreamFrom(bufferPtr, length);
                } 
            } 
            else
            { 
                comStream = StreamAsIStream.IStreamFrom(bitmapStream);

                if (comStream == IntPtr.Zero)
                { 
                    throw new System.InvalidOperationException(
                        SR.Get(SRID.Image_CantDealWithStream)); 
                } 

                // If the stream is not seekable, we must create a 
                // seekable one for the decoder.
                if (!seekable || ((!bitmapStream.CanWrite) && (bitmapStream.Length <= 1048576)))
                {
                    IntPtr memoryStream = StreamAsIStream.IStreamMemoryFrom(comStream); 

                    if (memoryStream != IntPtr.Zero) 
                    { 
                        // we don't need the original stream anymore
                        UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref comStream); 
                        bitmapStream = System.IO.Stream.Null;
                        return memoryStream;
                    }
                    else if (!seekable) 
                    {
                        throw new System.InvalidOperationException( 
                                SR.Get(SRID.Image_CantDealWithStream)); 
                    }
                } 

             }

            if (comStream == IntPtr.Zero) 
            {
                throw new System.InvalidOperationException( 
                SR.Get(SRID.Image_CantDealWithStream)); 
            }
 
            return comStream;
        }

 
        /// Returns whether decoder can be converted to a string
        internal bool CanConvertToString() 
        { 
            return (_uri != null);
        } 

        #endregion

        #region Internal Abstract 

        /// "Seals" the object 
        internal abstract void SealObject(); 

        #endregion 

        #region Data Members

        /// check to see if implementation is internal 
        private bool _isBuiltInDecoder;
 
        /// Internal Decoder 
        private SafeMILHandle _decoderHandle;
 
        /// flag to see if decoder should be inserted in the cache
        private bool _shouldCacheDecoder = true;

        /// flag to see if decoder should be inserted in the cache 
        private bool _isOriginalWritable = false;
 
        /// If the palette is already cached 
        private bool _isPaletteCached;
 
        /// Palette
        private BitmapPalette _palette = null;

        /// If the ColorContext is already cached 
        private bool _isColorContextCached;
 
        /// ColorContexts collection 
        internal ReadOnlyCollection _readOnlycolorContexts;
 
        /// If the thumbnail is already cached
        private bool _isThumbnailCached;

        ///  
        /// Metadata
        ///  
        ///  
        /// Critical - Access only granted if SiteOfOrigin demanded.
        ///  
        [SecurityCritical]
        private BitmapMetadata _metadata;

        /// If the metadata is already cached 
        private bool _isMetadataCached;
 
        /// Thumbnail 
        private BitmapSource _thumbnail = null;
 
        /// CodecInfo
        private BitmapCodecInfo _codecInfo;

        /// If the preview is already cached 
        private bool _isPreviewCached;
 
        /// Preview 
        private BitmapSource _preview = null;
 
        /// Frames collection
        internal List _frames;

        /// Frames collection 
        internal ReadOnlyCollection _readOnlyFrames;
 
        /// Stream 
        internal Stream _stream;
 
        /// Uri
        internal Uri _uri;

        /// Base Uri, only stored internally. Not used for serialization 
        internal Uri _baseUri;
 
        /// Uri Stream -- this is the stream that was created from the passed in Uri 
        /// 
        ///     Critical: Obtained under elevation 
        /// 
        [SecurityCritical]
        internal Stream _uriStream;
 
        /// CreateOptions
        internal BitmapCreateOptions _createOptions; 
 
        /// CacheOption
        internal BitmapCacheOption _cacheOption; 

        /// Event helper for download completed event
        internal UniqueEventHelper _downloadEvent = new UniqueEventHelper();
 
        /// Event helper for download progress event
        internal UniqueEventHelper _progressEvent = new UniqueEventHelper(); 
 
        /// Event helper for download failed event
        internal UniqueEventHelper _failedEvent = new UniqueEventHelper(); 

        /// SyncObject
        private object _syncObject = new Object();
 
        // this is data that we cache as a performance optimization. It is ok to do so since we do not want to
        // handle this key change in the lifetime of this app. 
        private static SecurityCriticalDataForSet isImageDisabled; 
        /// 
        ///     Critical: This variable guards against reinitialization of the cached registry value 
        /// 
        [SecurityCritical]
        private static bool isImageDisabledInitialized;
 
        // For UnmanagedMemoryStream we want to make sure that buffer
        // its pointing to is not getting release until decoder is alive 
        private UnmanagedMemoryStream _unmanagedMemoryStream; 

        ///  
        ///     Critical: This variable guards against closing of the filehandle
        ///      which gets passed to unmanaged decoder.
        /// 
        [SecurityCritical] 
        private SafeFileHandle _safeFilehandle;
 
        private BitmapDecoder _cachedDecoder; 

        #endregion 

    }

    #endregion // BitmapDecoder 
}
 

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