File: Core\CSharp\System\Windows\Media\Imaging\BitmapMetadataEnumerator.cs
Project: wpf\src\PresentationCore.csproj (PresentationCore)
//------------------------------------------------------------------------------
//  Microsoft Windows Client Platform
//  Copyright (c) Microsoft Corporation, 2005
//                                             
//  File:       BitmapMetadataEnumerator.cs
//------------------------------------------------------------------------------
 
// Allow suppression of certain presharp messages
#pragma warning disable 1634, 1691
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Diagnostics;
using MS.Internal;
using MS.Internal.PresentationCore;                        // SecurityHelper
using MS.Win32.PresentationCore;
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;
 
namespace System.Windows.Media.Imaging
{
    /// <summary>
    /// An enumerator that iterates over the children of a timeline.
    /// </summary>
    internal struct BitmapMetadataEnumerator : IEnumerator<String>, IEnumerator
    {
        #region External interface
 
        #region IEnumerator interface
 
        #region Properties
 
        /// <summary>
        /// Gets the current element in the collection.
        /// </summary>
        /// <value>
        /// The current element in the collection.
        /// </value>
        /// <SecurityNote>
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - inputs are verified or safe
        /// </SecurityNote>
        object IEnumerator.Current
        {
            [SecurityCritical, SecurityTreatAsSafe]
            get
            {
                return Current;
            }
        }
 
        #endregion // Properties
 
        #region Methods
 
        /// <summary>
        /// Advances the enumerator to the next element of the collection.
        /// </summary>
        /// <returns>
        /// True if the enumerator was successfully advanced to the next element;
        /// false if the enumerator has passed the end of the collection.
        /// </returns>
        /// <SecurityNote>
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - inputs are verified or safe
        /// </SecurityNote>
        [SecurityCritical, SecurityTreatAsSafe]
        public bool MoveNext()
        {
            if (_fStarted && _current == null)
            {
                return false;
            }
 
            _fStarted = true;
            
            IntPtr ppStr = IntPtr.Zero;
            Int32 celtFetched = 0;
 
            try
            {
                int hr = UnsafeNativeMethods.EnumString.Next(
                    _enumeratorHandle,
                    1,
                    ref ppStr,
                    ref celtFetched);
 
                if (HRESULT.IsWindowsCodecError(hr))
                {
                    _current = null;
                    return false;
                }
 
                HRESULT.Check(hr);
 
                if (celtFetched == 0)
                {
                    _current = null;
                    return false;
                }
                else
                {
                    _current = Marshal.PtrToStringUni(ppStr);
                }
            }
            finally
            {
                if (ppStr != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(ppStr);
                    ppStr = IntPtr.Zero;
                }           
            }
 
            return true;
        }
        
        /// <summary>
        /// Sets the enumerator to its initial position, which is before the first element
        /// in the collection.
        /// </summary>
        /// <SecurityNote>
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - inputs are verified or safe
        /// </SecurityNote>
        [SecurityCritical, SecurityTreatAsSafe]
        public void Reset()
        {
            HRESULT.Check(UnsafeNativeMethods.EnumString.Reset(_enumeratorHandle));
 
            _current = null;
            _fStarted = false;
        }
 
        #endregion // Methods
 
        #endregion // IEnumerator interface
 
        #region Properties
        
        /// <summary>
        /// The current timeline referenced by this enumerator.
        /// </summary>
        public String Current
        {
            get
            {
                if (_current == null)
                {
                    if (!_fStarted)
                    {
#pragma warning suppress 56503 // Suppress presharp warning: Follows a pattern similar to Nullable.
                    throw new InvalidOperationException(SR.Get(SRID.Enumerator_NotStarted));
                    }
                    else
                    {
#pragma warning suppress 56503 // Suppress presharp warning: Follows a pattern similar to Nullable.
                    throw new InvalidOperationException(SR.Get(SRID.Enumerator_ReachedEnd));
                    }
                }
 
                return _current;
            }
        }
 
        /// <summary>
        ///
        /// </summary>
        void IDisposable.Dispose()
        {
            // Do nothing - Required by the IEnumerable contract.
        }
 
        #endregion // Properties
 
        #endregion // External interface
 
        #region Internal implementation
 
        #region Construction
 
        /// <summary>
        /// Creates an enumerator iterates over the children of the specified container.
        /// </summary>
        /// <param name="metadataHandle">
        /// Handle to a metadata query reader/writer
        /// </param>
        /// <SecurityNote>
        /// Critical - Accesses unmanaged code
        /// TreatAsSafe - inputs are verified or safe
        /// </SecurityNote>
        [SecurityCritical, SecurityTreatAsSafe]
        internal BitmapMetadataEnumerator(SafeMILHandle metadataHandle)
        {
            Debug.Assert(metadataHandle != null && !metadataHandle.IsInvalid);
 
            HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryReader.GetEnumerator(
                metadataHandle,
                out _enumeratorHandle));
 
            _current = null;
            _fStarted = false;
        }
 
        #endregion // Construction
 
        #region Methods
 
        #endregion // Methods
 
        #region Data
 
        /// <SecurityNote>
        /// Critical - pointer to an unmanaged object that methods are called on.
        /// </SecurityNote>
        [SecurityCritical]
        private SafeMILHandle _enumeratorHandle;
 
        private String _current;
        private bool _fStarted;
 
        #endregion // Data
 
        #endregion // Internal implementation
    }
}