dataobject.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / dataobject.cs / 1407647 / dataobject.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: Top-level class for data transfer for drag-drop and clipboard. 
//
// See spec at http://avalon/uis/Data%20Transfer%20clipboard%20dragdrop/Avalon%20Data%20Transfer%20Object.htm 
//
// History:
//  04/26/2002 : susiA      Created
//  06/04/2003 : sangilj    Moved to WCP 
//
//--------------------------------------------------------------------------- 
 

namespace System.Windows 
{
    using System;
    using MS.Win32;
    using System.Collections; 
    using System.Collections.Specialized;
    using System.ComponentModel; 
    using System.Diagnostics; 
    using System.IO;
    using System.Runtime.InteropServices; 
    using System.Runtime.InteropServices.ComTypes;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Security; 
    using System.Security.Permissions;
    using System.Windows.Interop; 
    using System.Windows.Media.Imaging; 
    using System.Text;
    using MS.Internal; 
    using MS.Internal.PresentationCore;                        // SecurityHelper

    using SR=MS.Internal.PresentationCore.SR;
    using SRID=MS.Internal.PresentationCore.SRID; 
    using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject;
 
// PreSharp uses message numbers that the C# compiler doesn't know about. 
// Disable the C# complaints, per the PreSharp documentation.
#pragma warning disable 1634, 1691 

    #region DataObject Class
    /// 
    /// Implements a basic data transfer mechanism. 
    /// 
    public sealed class DataObject : IDataObject, IComDataObject 
    { 
        //-----------------------------------------------------
        // 
        //  Constructors
        //
        //-----------------------------------------------------
 
        #region Constructors
 
        ///  
        /// Initializes a new instance of the dataobject
        /// class, which can store arbitrary data. 
        /// 
        /// 
        ///    Critical: This code creates a data object which is blocked in partial trust
        ///    PublicOK:There is a demand on this call 
        /// 
        [SecurityCritical] 
        public DataObject() 
        {
            SecurityHelper.DemandAllClipboardPermission(); 
            _innerData = new DataStore();
        }

        ///  
        /// Initializes a new instance of the  class, containing the specified data.
        ///  
        ///  
        ///    Critical: This code creates a data object which is blocked in partial trust
        ///    PublicOk - demands appropriate permission 
        /// 
        [SecurityCritical]
        public DataObject(object data)
        { 
            SecurityHelper.DemandAllClipboardPermission();
            if (data == null) 
            { 
                throw new ArgumentNullException("data");
            } 

            IDataObject dataObject = data as IDataObject;

            if (dataObject != null) 
            {
                _innerData = dataObject; 
            } 
            else
            { 
                IComDataObject oleDataObject= data as IComDataObject;

                if (oleDataObject != null)
                { 
                    _innerData = new OleConverter(oleDataObject);
                } 
                else 
                {
                    _innerData = new DataStore(); 
                    SetData(data);
                }
            }
        } 

        ///  
        /// Initializes a new instance of the class, containing the specified data and its 
        /// associated format.
        ///  
        /// 
        ///    Critical: This code creates a data object which is blocked in partial trust
        ///    PublicOK:There is a demand on this call
        ///  
        [SecurityCritical]
        public DataObject(string format, object data) 
        { 
            SecurityHelper.DemandAllClipboardPermission();
            if (format == null) 
            {
                throw new ArgumentNullException("format");
            }
 
            if (format == string.Empty)
            { 
                throw new ArgumentException(SR.Get(SRID.DataObject_EmptyFormatNotAllowed)); 
            }
 
            if (data == null)
            {
                throw new ArgumentNullException("data");
            } 

            _innerData = new DataStore(); 
            SetData(format, data); 
        }
 
        /// 
        /// Initializes a new instance of the class, containing the specified data and its
        /// associated format.
        ///  
        /// 
        ///    Critical: This code creates a data object which is blocked in partial trust 
        ///    PublicOK:There is a demand on this call 
        /// 
        [SecurityCritical] 
        public DataObject(Type format, object data)
        {
            SecurityHelper.DemandAllClipboardPermission();
            if (format == null) 
            {
                throw new ArgumentNullException("format"); 
            } 
            if (data == null)
            { 
                throw new ArgumentNullException("data");
            }
            _innerData = new DataStore();
            SetData(format.FullName, data); 
        }
 
        ///  
        /// Initializes a new instance of the class, containing the specified data and its
        /// associated format. 
        /// 
        /// 
        ///    Critical: This code creates a data object which is blocked in partial trust
        ///    PublicOK:There is a demand on this call 
        /// 
        [SecurityCritical] 
        public DataObject(string format, object data, bool autoConvert) 
        {
            SecurityHelper.DemandAllClipboardPermission(); 
            if (format == null)
            {
                throw new ArgumentNullException("format");
            } 

            if (format == string.Empty) 
            { 
                throw new ArgumentException(SR.Get(SRID.DataObject_EmptyFormatNotAllowed));
            } 

            if (data == null)
            {
                throw new ArgumentNullException("data"); 
            }
 
            _innerData = new DataStore(); 
            SetData(format, data, autoConvert);
        } 

        /// 
        /// Initializes a new instance of the class, with the specified
        ///  
        internal DataObject(System.Windows.IDataObject data)
        { 
            if (data == null) 
            {
                throw new ArgumentNullException("data"); 
            }

            _innerData = data;
        } 

        ///  
        /// Initializes a new instance of the class, with the specified 
        /// 
        internal DataObject(IComDataObject data) 
        {
            if (data == null)
            {
                throw new ArgumentNullException("data"); 
            }
 
            _innerData = new OleConverter(data); 
        }
 
        #endregion Constructors

        //------------------------------------------------------
        // 
        //  Public Methods
        // 
        //----------------------------------------------------- 

        #region Public Methods 

        /// 
        /// Retrieves the data associated with the specified data
        /// format, using an automated conversion parameter to determine whether to convert 
        /// the data to the format.
        ///  
        public object GetData(string format, bool autoConvert) 
        {
            if (format == null) 
            {
                throw new ArgumentNullException("format");
            }
 
            if (format == string.Empty)
            { 
                throw new ArgumentException(SR.Get(SRID.DataObject_EmptyFormatNotAllowed)); 
            }
 
            return _innerData.GetData(format, autoConvert);
        }

        ///  
        /// Retrieves the data associated with the specified data
        /// format. 
        ///  
        public object GetData(string format)
        { 
            if (format == null)
            {
                throw new ArgumentNullException("format");
            } 

            if (format == string.Empty) 
            { 
                throw new ArgumentException(SR.Get(SRID.DataObject_EmptyFormatNotAllowed));
            } 

            return GetData(format, true);
        }
 
        /// 
        /// Retrieves the data associated with the specified class 
        /// type format. 
        /// 
        public object GetData(Type format) 
        {
            if (format == null)
            {
                throw new ArgumentNullException("format"); 
            }
            return GetData(format.FullName); 
        } 

        ///  
        /// Determines whether data stored in this instance is
        /// associated with, or can be converted to, the specified
        /// format.
        ///  
        public bool GetDataPresent(Type format)
        { 
            bool dataPresent; 
            if (format == null)
            { 
                throw new ArgumentNullException("format");
            }
            dataPresent = GetDataPresent(format.FullName);
            return dataPresent; 
        }
 
        ///  
        /// Determines whether data stored in this instance is
        /// associated with the specified format, using an automatic conversion 
        /// parameter to determine whether to convert the data to the format.
        /// 
        public bool GetDataPresent(string format, bool autoConvert)
        { 
            bool dataPresent;
 
            if (format == null) 
            {
                throw new ArgumentNullException("format"); 
            }

            if (format == string.Empty)
            { 
                throw new ArgumentException(SR.Get(SRID.DataObject_EmptyFormatNotAllowed));
            } 
 
            dataPresent = _innerData.GetDataPresent(format, autoConvert);
            return dataPresent; 
        }

        /// 
        /// Determines whether data stored in this instance is 
        /// associated with, or can be converted to, the specified
        /// format. 
        ///  
        public bool GetDataPresent(string format)
        { 
            if (format == null)
            {
                throw new ArgumentNullException("format");
            } 

            if (format == string.Empty) 
            { 
                throw new ArgumentException(SR.Get(SRID.DataObject_EmptyFormatNotAllowed));
            } 

            return GetDataPresent(format, true);
        }
 
        /// 
        /// Gets a list of all formats that data stored in this 
        /// instance is associated with or can be converted to, using an automatic 
        /// conversion parameterto
        /// determine whether to retrieve all formats that the data can be converted to or 
        /// only native data formats.
        /// 
        public string[] GetFormats(bool autoConvert)
        { 
            return _innerData.GetFormats(autoConvert);
        } 
 
        /// 
        /// Gets a list of all formats that data stored in this instance is associated 
        /// with or can be converted to.
        /// 
        public string[] GetFormats()
        { 
            return GetFormats(true);
        } 
 
        /// 
        /// Stores the specified data in 
        /// this instance, using the class of the data for the format.
        /// 
        /// 
        ///    Critical: This code sets a data object which is blocked in partial trust 
        ///    PublicOK:There is a demand on this call
        ///  
        [SecurityCritical] 
        public void SetData(object data)
        { 
            SecurityHelper.DemandAllClipboardPermission();
            if (data == null)
            {
                throw new ArgumentNullException("data"); 
            }
            _innerData.SetData(data); 
        } 

        ///  
        /// Stores the specified data and its associated format in this
        /// instance.
        /// 
        ///  
        ///    Critical: This code sets a data object which is blocked in partial trust
        ///    PublicOK:There is a demand on this call 
        ///  
        [SecurityCritical]
        public void SetData(string format, object data) 
        {
            SecurityHelper.DemandAllClipboardPermission();
            if (format == null)
            { 
                throw new ArgumentNullException("format");
            } 
 
            if (format == string.Empty)
            { 
                throw new ArgumentException(SR.Get(SRID.DataObject_EmptyFormatNotAllowed));
            }

            if (data == null) 
            {
                throw new ArgumentNullException("data"); 
            } 

            _innerData.SetData(format, data); 
        }

        /// 
        /// Stores the specified data and 
        /// its associated class type in this instance.
        ///  
        ///  
        ///    Critical: This code sets a data object which is blocked in partial trust
        ///    PublicOK:There is a demand on this call 
        /// 
        [SecurityCritical]
        public void SetData(Type format, object data)
        { 
            SecurityHelper.DemandAllClipboardPermission();
            if (format == null) 
            { 
                throw new ArgumentNullException("format");
            } 
            if (data == null)
            {
                throw new ArgumentNullException("data");
            } 

            _innerData.SetData(format, data); 
        } 

        ///  
        /// Stores the specified data and its associated format in
        /// this instance, using the automatic conversion parameter
        /// to specify whether the
        /// data can be converted to another format. 
        /// 
        ///  
        ///     Callers must have UIPermission(UIPermissionClipboard.AllClipboard) to call this API. 
        /// 
        ///  
        ///     Critical: This code calls into CriticalSetData
        ///     PublicOK: It filters for formats that we allow
        /// 
        [SecurityCritical] 
        public void SetData(string format, Object data, bool autoConvert)
        { 
            SecurityHelper.DemandAllClipboardPermission(); 
            if (format == null)
            { 
                throw new ArgumentNullException("format");
            }

            if (format == string.Empty) 
            {
                throw new ArgumentException(SR.Get(SRID.DataObject_EmptyFormatNotAllowed)); 
            } 

            CriticalSetData(format, data, autoConvert); 
        }


        ///  
        /// Return true if DataObject contains the audio data. Otherwise, return false.
        ///  
        public bool ContainsAudio() 
        {
            return GetDataPresent(DataFormats.WaveAudio, /*autoConvert*/false); 
        }

        /// 
        /// Return true if DataObject contains the file drop list data. Otherwise, return false. 
        /// 
        public bool ContainsFileDropList() 
        { 
            return GetDataPresent(DataFormats.FileDrop, /*autoConvert*/false);
        } 

        /// 
        /// Return true if DataObject contains the image data. Otherwise, return false.
        ///  
        public bool ContainsImage()
        { 
            return GetDataPresent(DataFormats.Bitmap, /*autoConvert*/false); 
        }
 
        /// 
        /// Return true if DataObject contains the text data. Otherwise, return false.
        /// 
        public bool ContainsText() 
        {
            return ContainsText(TextDataFormat.UnicodeText); 
        } 

        ///  
        /// Return true if DataObject contains the specified text data. Otherwise, return false.
        /// 
        public bool ContainsText(TextDataFormat format)
        { 
            if (!DataFormats.IsValidTextDataFormat(format))
            { 
                throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat)); 
            }
 
            return GetDataPresent(DataFormats.ConvertToDataFormats(format), /*autoConvert*/false);
        }

        ///  
        /// Get audio data as Stream.
        ///  
        public Stream GetAudioStream() 
        {
            return GetData(DataFormats.WaveAudio, /*autoConvert*/false) as Stream; 
        }

        /// 
        /// Get file drop list data as Stream. 
        /// 
        public StringCollection GetFileDropList() 
        { 
            StringCollection fileDropListCollection;
            string[] fileDropList; 

            fileDropListCollection = new StringCollection();

            fileDropList = GetData(DataFormats.FileDrop, /*autoConvert*/true) as string[]; 
            if (fileDropList != null)
            { 
                fileDropListCollection.AddRange(fileDropList); 
            }
 
            return fileDropListCollection;
        }

        ///  
        /// Get image data as BitmapSource.
        ///  
        public BitmapSource GetImage() 
        {
            return GetData(DataFormats.Bitmap, /*autoConvert*/true) as BitmapSource; 
        }

        /// 
        /// Get text data which is the unicode text. 
        /// 
        public string GetText() 
        { 
            return GetText(TextDataFormat.UnicodeText);
        } 

        /// 
        /// Get text data for the specified data format.
        ///  
        public string GetText(TextDataFormat format)
        { 
            if (!DataFormats.IsValidTextDataFormat(format)) 
            {
                throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat)); 
            }

            string text;
 
            text = (string)GetData(DataFormats.ConvertToDataFormats(format), false);
 
            if (text != null) 
            {
                return text; 
            }

            return string.Empty;
        } 

        ///  
        /// Set the audio data with bytes. 
        /// 
        public void SetAudio(byte[] audioBytes) 
        {
            if (audioBytes == null)
            {
                throw new ArgumentNullException("audioBytes"); 
            }
 
            SetAudio(new MemoryStream(audioBytes)); 
        }
 
        /// 
        /// Set the audio data with Stream.
        /// 
        public void SetAudio(Stream audioStream) 
        {
            if (audioStream == null) 
            { 
                throw new ArgumentNullException("audioStream");
            } 

            SetData(DataFormats.WaveAudio, audioStream, /*autoConvert*/false);
        }
 
        /// 
        /// Set the file drop list data. 
        ///  
        public void SetFileDropList(StringCollection fileDropList)
        { 
            if (fileDropList == null)
            {
                throw new ArgumentNullException("fileDropList");
            } 

            if (fileDropList.Count == 0) 
            { 
                throw new ArgumentException(SR.Get(SRID.DataObject_FileDropListIsEmpty, fileDropList));
            } 

            foreach (string fileDrop in fileDropList)
            {
                try 
                {
                    string filePath = Path.GetFullPath(fileDrop); 
                } 
                catch (ArgumentException e)
                { 
                    throw new ArgumentException(SR.Get(SRID.DataObject_FileDropListHasInvalidFileDropPath, e));
                }
            }
 
            string[] fileDropListStrings;
 
            fileDropListStrings = new string[fileDropList.Count]; 
            fileDropList.CopyTo(fileDropListStrings, 0);
 
            SetData(DataFormats.FileDrop, fileDropListStrings, /*audoConvert*/true);
        }

        ///  
        /// Set the image data with BitmapSource.
        ///  
        public void SetImage(BitmapSource image) 
        {
            if (image == null) 
            {
                throw new ArgumentNullException("image");
            }
 
            SetData(DataFormats.Bitmap, image, /*audoConvert*/true);
        } 
 
        /// 
        /// Set the text data. 
        /// 
        public void SetText(string textData)
        {
            if (textData == null) 
            {
                throw new ArgumentNullException("textData"); 
            } 

            SetText(textData, TextDataFormat.UnicodeText); 
        }

        /// 
        /// Set the text data for the specified text data format. 
        /// 
        public void SetText(string textData, TextDataFormat format) 
        { 
            if (textData == null)
            { 
                throw new ArgumentNullException("textData");
            }

            if (!DataFormats.IsValidTextDataFormat(format)) 
            {
                throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat)); 
            } 

            SetData(DataFormats.ConvertToDataFormats(format), textData, /*audoConvert*/false); 
        }

        /// 
        /// Part of IComDataObject, used to interop with OLE. 
        /// 
        ///  
        ///  
        /// 
        ///  
        /// 
        /// 
        /// Critical - calls into native code to pass through native call
        ///  
        [SecurityCritical]
        int IComDataObject.DAdvise(ref FORMATETC pFormatetc, ADVF advf, IAdviseSink pAdvSink, out int pdwConnection) 
        { 
            if (_innerData is OleConverter)
            { 
                return ((OleConverter)_innerData).OleDataObject.DAdvise(ref pFormatetc, advf, pAdvSink, out pdwConnection);
            }
            pdwConnection = 0;
            return (NativeMethods.E_NOTIMPL); 
        }
 
        ///  
        /// Part of IComDataObject, used to interop with OLE.
        ///  
        /// 
        /// Critical - calls into native code to pass through native call
        /// 
        [SecurityCritical] 
        void IComDataObject.DUnadvise(int dwConnection)
        { 
            if (_innerData is OleConverter) 
            {
                ((OleConverter)_innerData).OleDataObject.DUnadvise(dwConnection); 
                return;
            }

            // Throw the exception NativeMethods.E_NOTIMPL. 
            Marshal.ThrowExceptionForHR(NativeMethods.E_NOTIMPL);
        } 
 
        /// 
        /// Part of IComDataObject, used to interop with OLE. 
        /// 
        /// 
        /// Critical - calls into native code to pass through native call
        ///  
        [SecurityCritical]
        int IComDataObject.EnumDAdvise(out IEnumSTATDATA enumAdvise) 
        { 
            if (_innerData is OleConverter)
            { 
                return ((OleConverter)_innerData).OleDataObject.EnumDAdvise(out enumAdvise);
            }
            enumAdvise = null;
            return (OLE_E_ADVISENOTSUPPORTED); 
        }
 
        //  
        // Part of IComDataObject, used to interop with OLE.
        //  
        /// 
        /// Critical - calls into native code to pass through native call
        /// 
        [SecurityCritical] 
        IEnumFORMATETC IComDataObject.EnumFormatEtc(DATADIR dwDirection)
        { 
            if (_innerData is OleConverter) 
            {
                return ((OleConverter)_innerData).OleDataObject.EnumFormatEtc(dwDirection); 
            }
            if (dwDirection == DATADIR.DATADIR_GET)
            {
                return new FormatEnumerator(this); 
            }
            else 
            { 
                throw new ExternalException(SR.Get(SRID.DataObject_NotImplementedEnumFormatEtc, dwDirection), NativeMethods.E_NOTIMPL);
            } 
        }

        /// 
        /// Part of IComDataObject, used to interop with OLE. 
        /// 
        ///  
        /// Critical - calls into native code to pass through native call 
        /// 
        [SecurityCritical] 
        int IComDataObject.GetCanonicalFormatEtc(ref FORMATETC pformatetcIn, out FORMATETC pformatetcOut)
        {
            pformatetcOut = new FORMATETC();
            pformatetcOut = pformatetcIn; 
            pformatetcOut.ptd = IntPtr.Zero;
 
            if (pformatetcIn.lindex != -1) 
            {
                return DV_E_LINDEX; 
            }

            if (_innerData is OleConverter)
            { 
                return ((OleConverter)_innerData).OleDataObject.GetCanonicalFormatEtc(ref pformatetcIn, out pformatetcOut);
            } 
 
            return DATA_S_SAMEFORMATETC;
        } 

        /// 
        /// Part of IComDataObject, used to interop with OLE.
        ///  
        /// 
        /// Critical - directly access unmanaged memory 
        ///  
        [SecurityCritical]
        void IComDataObject.GetData(ref FORMATETC formatetc, out STGMEDIUM medium) 
        {
            if (_innerData is OleConverter)
            {
                ((OleConverter)_innerData).OleDataObject.GetData(ref formatetc, out medium); 
                return;
            } 
 
            int hr;
 
            hr = DV_E_TYMED;

            medium = new STGMEDIUM();
 
            if (GetTymedUseable(formatetc.tymed))
            { 
                if ((formatetc.tymed & TYMED.TYMED_HGLOBAL) != 0) 
                {
                    medium.tymed = TYMED.TYMED_HGLOBAL; 

                    medium.unionmember = Win32GlobalAlloc(NativeMethods.GMEM_MOVEABLE
                                                           | NativeMethods.GMEM_DDESHARE
                                                           | NativeMethods.GMEM_ZEROINIT, 
                                                          (IntPtr)1);
 
                    hr = OleGetDataUnrestricted(ref formatetc, ref medium, false /* doNotReallocate */); 

                    if (NativeMethods.Failed(hr)) 
                    {
                        Win32GlobalFree(new HandleRef(this, medium.unionmember));
                    }
                } 
                else if ( ( formatetc.tymed & TYMED.TYMED_ISTREAM ) != 0 )
                { 
                    // Checking for the unmanaged code permission. 
                    if ( SecurityHelper.CheckUnmanagedCodePermission() )
                    { 
                        medium.tymed = TYMED.TYMED_ISTREAM;

                        IStream istream = null;
                        hr = Win32CreateStreamOnHGlobal(IntPtr.Zero, true /*deleteOnRelease*/, ref istream); 
                        if ( NativeMethods.Succeeded(hr) )
                        { 
                            medium.unionmember = Marshal.GetComInterfaceForObject(istream, typeof(IStream)); 
                            Marshal.ReleaseComObject(istream);
 
                            hr = OleGetDataUnrestricted(ref formatetc, ref medium, false /* doNotReallocate */);

                            if ( NativeMethods.Failed(hr) )
                            { 
                                Marshal.Release(medium.unionmember);
                            } 
                        } 
                    }
                    else 
                    {
                        hr = NativeMethods.E_FAIL;
                    }
                } 
                else
                { 
                    medium.tymed = formatetc.tymed; 
                    hr = OleGetDataUnrestricted(ref formatetc, ref medium, false /* doNotReallocate */);
                } 
            }

            // Make sure we zero out that pointer if we don't support the format.
            if (NativeMethods.Failed(hr)) 
            {
                medium.unionmember = IntPtr.Zero; 
 
                Marshal.ThrowExceptionForHR(hr);
            } 
        }

        /// 
        /// Part of IComDataObject, used to interop with OLE. 
        /// 
        ///  
        /// Critical - access unmanaged structures 
        /// 
        [SecurityCritical] 
        void IComDataObject.GetDataHere(ref FORMATETC formatetc, ref STGMEDIUM medium)
        {
            // This method is spec'd to accepted only limited number of tymed
            // values, and it does not support multiple OR'd values. 
            if (medium.tymed != TYMED.TYMED_ISTORAGE &&
                medium.tymed != TYMED.TYMED_ISTREAM && 
                medium.tymed != TYMED.TYMED_HGLOBAL && 
                medium.tymed != TYMED.TYMED_FILE)
            { 
                Marshal.ThrowExceptionForHR(DV_E_TYMED);
            }

            int hr = OleGetDataUnrestricted(ref formatetc, ref medium, true /* doNotReallocate */); 
            if (NativeMethods.Failed(hr))
            { 
                Marshal.ThrowExceptionForHR(hr); 
            }
        } 

        /// 
        /// Part of IComDataObject, used to interop with OLE.
        ///  
        /// 
        /// Critical - calls into native code to pass through native call 
        ///  
        [SecurityCritical]
        int IComDataObject.QueryGetData(ref FORMATETC formatetc) 
        {
            if (_innerData is OleConverter)
            {
                return ((OleConverter)_innerData).OleDataObject.QueryGetData(ref formatetc); 
            }
            if (formatetc.dwAspect == DVASPECT.DVASPECT_CONTENT) 
            { 
                if (GetTymedUseable(formatetc.tymed))
                { 
                    if (formatetc.cfFormat == 0)
                    {
                        return NativeMethods.S_FALSE;
                    } 
                    else
                    { 
                        if (!GetDataPresent(DataFormats.GetDataFormat(formatetc.cfFormat).Name)) 
                        {
                            return (DV_E_FORMATETC); 
                        }
                    }
                }
                else 
                {
                    return (DV_E_TYMED); 
                } 
            }
            else 
            {
                return (DV_E_DVASPECT);
            }
 
            return NativeMethods.S_OK;
        } 
 
        /// 
        /// Part of IComDataObject, used to interop with OLE. 
        /// 
        /// 
        /// Critical - calls into native code to pass through native call
        /// PublicOK: This call has a demand blocking it 
        /// 
        [SecurityCritical] 
        void IComDataObject.SetData(ref FORMATETC pFormatetcIn, ref STGMEDIUM pmedium, bool fRelease) 
        {
            SecurityHelper.DemandAllClipboardPermission(); 
            if (_innerData is OleConverter)
            {
                ((OleConverter)_innerData).OleDataObject.SetData(ref pFormatetcIn, ref pmedium, fRelease);
                return; 
            }
 
            Marshal.ThrowExceptionForHR(NativeMethods.E_NOTIMPL); 
        }
 
        //......................................................
        //
        //  Events for Clipboard Extensibility
        // 
        //......................................................
 
        #region Events for Clipboard Extensibility 

        ///  
        ///     Adds a handler for the Copying attached event
        /// 
        /// UIElement or ContentElement that listens to this event
        ///  
        /// A handler for DataObject.Copying event.
        /// The handler is expected to inspect the content of a data object 
        /// passed via event arguments (DataObjectCopyingEventArgs.DataObject) 
        /// and add additional (custom) data format to it.
        /// It's also possible for the handler to change 
        /// the contents of other data formats already put on DataObject
        /// or even remove some of those formats.
        /// All this happens before DataObject is put on
        /// the Clipboard (in copy operation) or before DragDrop 
        /// process starts.
        /// The handler can cancel the whole copying event 
        /// by calling DataObjectCopyingEventArgs.CancelCommand method. 
        /// For the case of Copy a command will be cancelled,
        /// for the case of DragDrop a dragdrop process will be 
        /// terminated in the beginning.
        /// 

        public static void AddCopyingHandler(DependencyObject element, DataObjectCopyingEventHandler handler) 
        {
            UIElement.AddHandler(element, CopyingEvent, handler); 
        } 

        ///  
        ///     Removes a handler for the Copying attached event
        /// 
        /// UIElement or ContentElement that listens to this event
        /// Event Handler to be removed 
        public static void RemoveCopyingHandler(DependencyObject element, DataObjectCopyingEventHandler handler)
        { 
            UIElement.RemoveHandler(element, CopyingEvent, handler); 
        }
 
        /// 
        ///     Adds a handler for the Pasting attached event
        /// 
        /// UIElement or ContentElement that listens to this event 
        /// 
        /// An event handler for a DataObject.Pasting event. 
        /// It is called when ah editor already made a decision 
        /// what format (from available on the Cliipboard)
        /// to apply to selection. With this handler an application 
        /// has a chance to inspect a content of DataObject extracted
        /// from the Clipboard and decide what format to use instead.
        /// There are three options for the handler here:
        /// a) to cancel the whole Paste/Drop event by calling 
        /// DataObjectPastingEventArgs.CancelCommand method,
        /// b) change an editor's choice of format by setting 
        /// new value for DataObjectPastingEventArgs.FormatToApply 
        /// property (the new value is supposed to be understandable
        /// by an editor - it's application's code responsibility 
        /// to act consistently with an editor; example is to
        /// replace "rich text" (xaml) format to "plain text" format -
        /// both understandable by the TextEditor).
        /// c) choose it's own custom format, apply it to a selection 
        /// and cancel a command for the following execution in an
        /// editor by calling DataObjectPastingEventArgs.CancelCommand 
        /// method. This is how custom data formats are expected 
        /// to be pasted.
        /// Note that by changing a content of data formats on DataObject 
        /// an application code does not affect the global Clipboard.
        /// It only affects how an editor pastes this format.
        /// For instance, by parsing xaml data format and making
        /// some changes in it, the handler does not change this xaml 
        /// for the following acts of pasting into the same or another
        /// application. 
        ///  
        public static void AddPastingHandler(DependencyObject element, DataObjectPastingEventHandler handler)
        { 
            UIElement.AddHandler(element, PastingEvent, handler);
        }

        ///  
        ///     Removes a handler for the Pasting attached event
        ///  
        /// UIElement or ContentElement that listens to this event 
        /// Event Handler to be removed
        public static void RemovePastingHandler(DependencyObject element, DataObjectPastingEventHandler handler) 
        {
            UIElement.RemoveHandler(element, PastingEvent, handler);
        }
 
        /// 
        ///     Adds a handler for the SettingData attached event 
        ///  
        /// UIElement or ContentElement that listens to this event
        ///  
        /// A handler for a DataObject.SettingData event.
        /// Te event is fired as part of Copy (or Drag) command
        /// once for each of data formats added to a DataObject.
        /// The purpose of this handler is mostly copy command 
        /// optimization. With the help of it application
        /// can filter some formats from being added to DataObject. 
        /// The other opportunity of doing that exists in 
        /// DataObject.Copying event, which could set all undesirable
        /// formats to null, but in this case the work for data 
        /// conversion is already done, which may be too expensive.
        /// By handling DataObject.SettingData event an application
        /// can prevent from each particular data format conversion.
        /// By calling DataObjectSettingDataEventArgs.CancelCommand 
        /// method the handler tells an editor to skip one particular
        /// data format (identified by DataObjectSettingDataEventArgs.Format 
        /// property). Note that calling CancelCommand method 
        /// for this event does not cancel the whole Copy or Drag
        /// command. 
        /// 
        public static void AddSettingDataHandler(DependencyObject element, DataObjectSettingDataEventHandler handler)
        {
            UIElement.AddHandler(element, SettingDataEvent, handler); 
        }
 
        ///  
        ///     Removes a handler for the SettingData attached event
        ///  
        /// UIElement or ContentElement that listens to this event
        /// Event Handler to be removed
        public static void RemoveSettingDataHandler(DependencyObject element, DataObjectSettingDataEventHandler handler)
        { 
            UIElement.RemoveHandler(element, SettingDataEvent, handler);
        } 
 
        #endregion Events for Clipboard Extensibility
 
        #endregion Public Methods

        //------------------------------------------------------
        // 
        //  Public Properties
        // 
        //------------------------------------------------------ 

        #region Public Properties 

        /// 
        /// The DataObject.Copying event is raised when an editor
        /// has converted a content of selection into all appropriate 
        /// clipboard data formats, collected them all in DataObject
        /// and is ready to put the objet onto the Clipboard 
        /// or ready to start drag operation. 
        /// Application code can inspect DataObject, change, remove or
        /// add some data formats into it and decide whether to proceed 
        /// with the copying or cancel it.
        /// 
        public static readonly RoutedEvent CopyingEvent = //
            EventManager.RegisterRoutedEvent("Copying", // 
                                               RoutingStrategy.Bubble, //
                                               typeof(DataObjectCopyingEventHandler), // 
                                               typeof(DataObject)); // 

        ///  
        /// The DataObject.Pasting event is raised when texteditor
        /// is ready to paste one of data format to the content
        /// during paste operation.
        /// Application can inspect a DataObject, change, remove or add 
        /// data formats and also can decide whether to proceed pasting
        /// or cancel it. 
        ///  
        public static readonly RoutedEvent PastingEvent = //
            EventManager.RegisterRoutedEvent("Pasting", // 
                                               RoutingStrategy.Bubble, //
                                               typeof(DataObjectPastingEventHandler), //
                                               typeof(DataObject)); //
 
        /// 
        /// The DataObject.SettingData event is raised when an editor 
        /// is intended to add one more data format to a DataObject during 
        /// copy operation.
        /// Handlign this event allows for a user to prevent from 
        /// adding undesirable formats, thus improving performance of
        /// copy operations.
        /// 
        public static readonly RoutedEvent SettingDataEvent = // 
            EventManager.RegisterRoutedEvent("SettingData", //
                                               RoutingStrategy.Bubble, // 
                                               typeof(DataObjectSettingDataEventHandler), // 
                                               typeof(DataObject)); //
 
        #endregion Public Properties

        //-----------------------------------------------------
        // 
        //  Internal Methods
        // 
        //------------------------------------------------------ 

        #region Internal Methods 

        /// 
        /// Call Win32 UnsafeNativeMethods.GlobalAlloc() with Win32 error checking.
        ///  
        /// 
        /// Critical - access unmanaged memory directly. 
        ///  
        [SecurityCritical]
        internal static IntPtr Win32GlobalAlloc(int flags, IntPtr bytes) 
        {
            IntPtr win32Pointer = UnsafeNativeMethods.GlobalAlloc(flags, bytes);
            int win32Error = Marshal.GetLastWin32Error();
            if (win32Pointer == IntPtr.Zero) 
            {
                throw new System.ComponentModel.Win32Exception(win32Error); 
            } 

            return win32Pointer; 
        }

        /// 
        /// Call Win32 UnsafeNativeMethods.CreateStreamOnHGlobal() with Win32 error checking. 
        /// 
        ///  
        /// Critical - access unmanaged memory directly. 
        /// 
        [SecurityCritical] 
        private static int Win32CreateStreamOnHGlobal(IntPtr hGlobal, bool fDeleteOnRelease, ref IStream istream)
        {
            int hr = UnsafeNativeMethods.CreateStreamOnHGlobal(hGlobal, fDeleteOnRelease, ref istream);
            if ( NativeMethods.Failed(hr) ) 
            {
                Marshal.ThrowExceptionForHR(hr); 
            } 

            return hr; 
        }

        /// 
        /// Call Win32 UnsafeNativeMethods.GlobalFree() with Win32 error checking. 
        /// 
        ///  
        /// Critical - access unmanaged memory directly. 
        /// 
        [SecurityCritical] 
        internal static void Win32GlobalFree(HandleRef handle)
        {
            IntPtr win32Pointer = UnsafeNativeMethods.GlobalFree(handle);
            int win32Error = Marshal.GetLastWin32Error(); 
            if (win32Pointer != IntPtr.Zero)
            { 
                throw new System.ComponentModel.Win32Exception(win32Error); 
            }
        } 

        /// 
        /// Call Win32 UnsafeNativeMethods.GlobalReAlloc() with Win32 error checking.
        ///  
        /// 
        /// Critical - access unmanaged memory directly. 
        ///  
        [SecurityCritical]
        internal static IntPtr Win32GlobalReAlloc(HandleRef handle, IntPtr bytes, int flags) 
        {
            IntPtr win32Pointer = UnsafeNativeMethods.GlobalReAlloc(handle, bytes, flags);
            int win32Error = Marshal.GetLastWin32Error();
            if (win32Pointer == IntPtr.Zero) 
            {
                throw new System.ComponentModel.Win32Exception(win32Error); 
            } 

            return win32Pointer; 
        }

        /// 
        /// Call Win32 UnsafeNativeMethods.GlobalLock() with Win32 error checking. 
        /// 
        ///  
        /// Critical - access unmanaged memory directly. 
        /// 
        [SecurityCritical] 
        internal static IntPtr Win32GlobalLock(HandleRef handle)
        {
            IntPtr win32Pointer = UnsafeNativeMethods.GlobalLock(handle);
            int win32Error = Marshal.GetLastWin32Error(); 
            if (win32Pointer == IntPtr.Zero)
            { 
                throw new System.ComponentModel.Win32Exception(win32Error); 
            }
 
            return win32Pointer;
        }

        ///  
        /// Call Win32 UnsafeNativeMethods.GlobalUnlock() with Win32 error checking.
        ///  
        ///  
        /// Critical - access unmanaged memory directly.
        ///  
        [SecurityCritical]
        internal static void Win32GlobalUnlock(HandleRef handle)
        {
            bool win32Return = UnsafeNativeMethods.GlobalUnlock(handle); 
            int win32Error = Marshal.GetLastWin32Error();
            if (!win32Return && win32Error != 0) 
            { 
                throw new System.ComponentModel.Win32Exception(win32Error);
            } 
        }

        /// 
        /// Call Win32 UnsafeNativeMethods.GlobalSize() with Win32 error checking. 
        /// 
        ///  
        /// Critical - access unmanaged memory directly. 
        /// 
        [SecurityCritical] 
        internal static IntPtr Win32GlobalSize(HandleRef handle)
        {
            IntPtr win32Pointer = UnsafeNativeMethods.GlobalSize(handle);
 
            int win32Error = Marshal.GetLastWin32Error();
            if (win32Pointer == IntPtr.Zero) 
            { 
                throw new System.ComponentModel.Win32Exception(win32Error);
            } 

            return win32Pointer;
        }
 
        /// 
        /// Call Win32 SafeNativeMethods.SelectObject() with Win32 error checking. 
        ///  
        /// 
        ///     Critical:  This code returns a pointer to a windows GDI object 
        /// 
        [SecurityCritical]
        internal static IntPtr Win32SelectObject(HandleRef handleDC, IntPtr handleObject)
        { 
            IntPtr handleOldObject = UnsafeNativeMethods.SelectObject(handleDC, handleObject);
            if (handleOldObject == IntPtr.Zero) 
            { 
                throw new System.ComponentModel.Win32Exception();
            } 

            return handleOldObject;
        }
 
        /// 
        /// Call Win32 SafeNativeMethods.DeleteObject() with Win32 error checking. 
        ///  
        /// 
        ///     Critical: This code calls into DeleteObject which is critical 
        ///     TreatAsSafe: There is a demand in this code
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        internal static void Win32DeleteObject(HandleRef handleDC) 
        {
            SecurityHelper.DemandUnmanagedCode(); 
            UnsafeNativeMethods.DeleteObject(handleDC); 
        }
 
        /// 
        /// Call Win32 UnsafeNativeMethods.GetDC() with Win32 error checking.
        /// 
        ///  
        /// Critical - access unmanaged memory directly.
        ///  
        [SecurityCritical] 
        internal static IntPtr Win32GetDC(HandleRef handleDC)
        { 
            IntPtr newDC = UnsafeNativeMethods.GetDC(handleDC);
            return newDC;
        }
 
        /// 
        /// Call Win32 UnsafeNativeMethods.CreateCompatibleDC() with Win32 error checking. 
        ///  
        internal static IntPtr Win32CreateCompatibleDC(HandleRef handleDC)
        { 
            IntPtr newDC = UnsafeNativeMethods.CreateCompatibleDC(handleDC);
            return newDC;
        }
 

        ///  
        /// Call Win32 SafeNativeMethods.CreateCompatibleBitmap() with Win32 error checking. 
        /// 
        ///  
        /// Critical - pinvokes into native code with data supplied by the caller.
        /// 
        [SecurityCritical]
        internal static IntPtr Win32CreateCompatibleBitmap(HandleRef handleDC, int width, int height) 
        {
            IntPtr bitmap = UnsafeNativeMethods.CreateCompatibleBitmap(handleDC, width, height); 
            return bitmap; 
        }
 
        /// 
        /// Call Win32 UnsafeNativeMethods.DeleteDC() with Win32 error checking.
        /// 
        internal static void Win32DeleteDC(HandleRef handleDC) 
        {
            UnsafeNativeMethods.DeleteDC(handleDC); 
        } 

        ///  
        /// Call Win32 UnsafeNativeMethods.BitBlt() with Win32 error checking.
        /// 
        /// 
        /// Critical - Writes to unmanaged memory 
        /// 
        [SecurityCritical] 
        internal static void Win32BitBlt(HandleRef handledestination, int width, int height, HandleRef handleSource, int operationCode) 
        {
            bool win32Return = UnsafeNativeMethods.BitBlt(handledestination, 0, 0, width, height, handleSource, 0, 0, operationCode); 
            if (!win32Return)
            {
                throw new System.ComponentModel.Win32Exception();
            } 
        }
 
        ///  
        /// Call Win32 UnsafeNativeMethods.WideCharToMultiByte() with Win32 error checking.
        ///  
        /// 
        /// Critical - writes directly to unmanaged memory.
        /// 
        [SecurityCritical] 
        internal static int Win32WideCharToMultiByte(string wideString, int wideChars, byte[] bytes, int byteCount)
        { 
            int win32Return = UnsafeNativeMethods.WideCharToMultiByte(0 /*CP_ACP*/, 0 /*flags*/, wideString, wideChars, bytes, byteCount, IntPtr.Zero, IntPtr.Zero); 
            int win32Error = Marshal.GetLastWin32Error();
            if (win32Return == 0) 
            {
                throw new System.ComponentModel.Win32Exception(win32Error);
            }
 
            return win32Return;
        } 
 
        /// 
        /// Returns all the "synonyms" for the specified format. 
        /// 
        /// 
        /// Critical - Makes security decision based on unmanaged code permission check.
        /// TreatAsSafe - Exposes no critical data. Never returns DataFormats.StringFormat 
        ///               without unmanaged code permission.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal static string[] GetMappedFormats(string format)
        { 
            //
            if (format == null)
            {
                return null; 
            }
 
            if (IsFormatEqual(format, DataFormats.Text) 
                || IsFormatEqual(format, DataFormats.UnicodeText)
                || IsFormatEqual(format, DataFormats.StringFormat)) 
            {
                string[] arrayFormats;
                // we do this to block copy of the string synonym in partial trust because that
                // requires elevations. This is more of a resource issue than anything else at this point. 
                // We might consider doing this in V2.
                // Also we want to avoid making the serialization code non transparent. 
                if (SecurityHelper.CheckUnmanagedCodePermission()) 
                {
                    arrayFormats = new string[] { 
                                        DataFormats.Text,
                                        DataFormats.UnicodeText,
                                        DataFormats.StringFormat,
                                        }; 
                }
                else 
                { 
                    arrayFormats = new string[] {
                                        DataFormats.Text, 
                                        DataFormats.UnicodeText,
                                        };
                }
                return arrayFormats; 
            }
 
            if (IsFormatEqual(format, DataFormats.FileDrop) 
                || IsFormatEqual(format, DataFormats.FileName)
                || IsFormatEqual(format, DataFormats.FileNameW)) 
            {

                return new string[] {
                                        DataFormats.FileDrop, 
                                        DataFormats.FileNameW,
                                        DataFormats.FileName, 
                }; 
            }
 
            // Get the System.Drawing.Bitmap string instead of getting it from typeof.
            // So we won't load System.Drawing.dll module here.
            if (IsFormatEqual(format, DataFormats.Bitmap)
                //|| IsFormat.Equals(format, DataFormats.Dib) 
                || IsFormatEqual(format, SystemBitmapSourceFormat)
                || IsFormatEqual(format, SystemDrawingBitmapFormat)) 
            { 

                return new string[] { 
                                        DataFormats.Bitmap,
                                        SystemDrawingBitmapFormat,
                                        SystemBitmapSourceFormat
                                        //DataFormats.Dib, 
                };
            } 
 
            if (IsFormatEqual(format, DataFormats.EnhancedMetafile)
                || IsFormatEqual(format, SystemDrawingImagingMetafileFormat)) 
            {
                return new string[] {
                                        DataFormats.EnhancedMetafile,
                                        SystemDrawingImagingMetafileFormat 
                };
            } 
 
            return new String[] { format };
        } 

        #endregion Internal Methods

        //----------------------------------------------------- 
        //
        //  Private Methods 
        // 
        //-----------------------------------------------------
 
        #region Private Methods


        ///  
        /// 
        ///  
        ///  
        ///     Critical: This code circumvents the checks on SetData and can be used to set xaml content on clipboard
        ///  
        [SecurityCritical]
        [FriendAccessAllowed]
        internal void CriticalSetData(string format, Object data, bool autoConvert)
        { 
            if (data == null)
            { 
                throw new ArgumentNullException("data"); 
            }
            _innerData.SetData(format, data, autoConvert); 
        }

        /// 
        /// Behaves like IComDataObject.GetData and IComDataObject.GetDataHere, 
        /// except we make no restrictions TYMED values.
        ///  
        ///  
        /// Critical - access unmanaged structures
        ///  
        [SecurityCritical]
        private int OleGetDataUnrestricted(ref FORMATETC formatetc, ref STGMEDIUM medium, bool doNotReallocate)
        {
            if (_innerData is OleConverter) 
            {
                ((OleConverter)_innerData).OleDataObject.GetDataHere(ref formatetc, ref medium); 
 
                return NativeMethods.S_OK;
            } 

            return GetDataIntoOleStructs(ref formatetc, ref medium, doNotReallocate);
        }
 
        /// 
        /// Retrieves a list of distinct strings from the array. 
        ///  
        private static string[] GetDistinctStrings(string[] formats)
        { 
            ArrayList distinct;
            string[] distinctStrings;

            distinct = new ArrayList(); 
            for (int i=0; i 
        /// Returns true if the tymed is useable.
        ///  
        private bool GetTymedUseable(TYMED tymed) 
        {
            for (int i=0; i
        ///  TreatAsSafe: This API could be public in terms of security as it demands for unmanaged code
        ///  Critical: Does an elevation via a call to unsafe native methods
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private IntPtr GetCompatibleBitmap(object data) 
        { 
            SecurityHelper.DemandUnmanagedCode();
 
            IntPtr hBitmap;
            IntPtr hBitmapNew;
            IntPtr hDC;
            IntPtr sourceDC; 
            IntPtr sourceObject;
            IntPtr destinationDC; 
            IntPtr destinationObject; 

            System.Drawing.Bitmap bitmapData; 

            if (data is BitmapSource)
            {
                // Convert BimapSource to System.Drawing.Bitmap to get Win32 HBITMAP. 
                BitmapEncoder bitmapEncoder;
                Stream bitmapStream; 
 
                bitmapEncoder = new BmpBitmapEncoder();
                bitmapEncoder.Frames.Add(BitmapFrame.Create(data as BitmapSource)); 

                bitmapStream = new MemoryStream();
                bitmapEncoder.Save(bitmapStream);
 
                bitmapData = new System.Drawing.Bitmap(bitmapStream);
            } 
            else 
            {
                // Get Bitmap data from data object. 
                bitmapData = data as System.Drawing.Bitmap;
            }

            if (bitmapData == null) 
            {
                return IntPtr.Zero; 
            } 

            // GDI+ returns a DIBSECTION based HBITMAP. The clipboard deals well 
            // only with bitmaps created using CreateCompatibleBitmap(). So, we
            // convert the DIBSECTION into a compatible bitmap.
            hBitmap = bitmapData.GetHbitmap();
 
            try
            { 
                // Get the screen DC. 
                hDC = Win32GetDC(new HandleRef(this, IntPtr.Zero));
 
                // Create a compatible DC to render the source bitmap.
                sourceDC = Win32CreateCompatibleDC(new HandleRef(this, hDC));

                // Select the original object from the current DC. 
                sourceObject = Win32SelectObject(new HandleRef(this, sourceDC), hBitmap);
 
                // Create a compatible DC and a new compatible bitmap. 
                destinationDC = Win32CreateCompatibleDC(new HandleRef(this, hDC));
 
                // creates a bitmap with the device that is associated with the specified DC.
                hBitmapNew = Win32CreateCompatibleBitmap(new HandleRef(this, hDC), bitmapData.Size.Width, bitmapData.Size.Height);

                // Select the new bitmap into a compatible DC and render the blt the original bitmap. 
                destinationObject = Win32SelectObject(new HandleRef(this, destinationDC), hBitmapNew);
 
                try 
                {
                    // Bit-block transfer of the data onto the rectangle of pixels 
                    // from the specified source device context into a destination device context.
                    Win32BitBlt(new HandleRef(this, destinationDC), bitmapData.Size.Width, bitmapData.Size.Height, new HandleRef(null, sourceDC), /* SRCCOPY */0x00CC0020);
                }
                finally 
                {
                    // Select the old device context. 
                    Win32SelectObject(new HandleRef(this, sourceDC), sourceObject); 
                    Win32SelectObject(new HandleRef(this, destinationDC), destinationObject);
 
                    // Clear the source and destination compatible DCs.
                    Win32DeleteDC(new HandleRef(this, sourceDC));
                    Win32DeleteDC(new HandleRef(this, destinationDC));
                } 
            }
            finally 
            { 
                // Delete the bitmap object.
                Win32DeleteObject(new HandleRef(this, hBitmap)); 
            }

            return hBitmapNew;
        } 

        ///  
        /// Get the enhanced metafile handle from the metafile data object. 
        /// 
        ///  
        ///     Critical:  This code returns a handle to an unmanaged object
        /// 
        [SecurityCritical]
        private IntPtr GetEnhancedMetafileHandle(String format, object data) 
        {
            IntPtr hEnhancedMetafile; 
 
            hEnhancedMetafile = IntPtr.Zero;
 
            if (IsFormatEqual(format, DataFormats.EnhancedMetafile))
            {
                // Get the metafile handle from metafile data object.
                if (AssemblyHelper.IsMetafile(data)) 
                {
                    hEnhancedMetafile = AssemblyHelper.GetHandleFromMetafile(data); 
                } 
                else if (data is MemoryStream)
                { 
                    MemoryStream memoryStream;

                    memoryStream = data as MemoryStream;
                    if (memoryStream != null) 
                    {
                        byte[] buffer; 
 
                        buffer = memoryStream.GetBuffer();
                        if (buffer != null && buffer.Length != 0) 
                        {
                            hEnhancedMetafile = NativeMethods.SetEnhMetaFileBits((uint)buffer.Length, buffer);
                            int win32Error = Marshal.GetLastWin32Error(); // Dance around FxCop
 
                            if (hEnhancedMetafile == IntPtr.Zero)
                            { 
                                // Throw the Win32 exception with GetLastWin32Error. 
                                throw new System.ComponentModel.Win32Exception(win32Error);
                            } 
                        }
                    }
                }
            } 

            return hEnhancedMetafile; 
        } 

        ///  
        /// Populates Ole datastructes from a [....] dataObject. This is the core
        /// of [....] to OLE conversion.
        /// 
        ///  
        /// Critical - calls critical methods (saving objects to streams, etc.),
        ///            deals with unmanaged structures, etc. 
        ///  
        [SecurityCritical]
        private int GetDataIntoOleStructs(ref FORMATETC formatetc, ref STGMEDIUM medium, bool doNotReallocate) 
        {
            int hr;

            hr = DV_E_TYMED; 

            if (GetTymedUseable(formatetc.tymed) && GetTymedUseable(medium.tymed)) 
            { 
                string format;
 
                format = DataFormats.GetDataFormat(formatetc.cfFormat).Name;

                // set the default result with DV_E_FORMATETC.
                hr = DV_E_FORMATETC; 

                if (GetDataPresent(format)) 
                { 
                    object data;
 
                    data = GetData(format);

                    // set the default result with DV_E_TYMED.
                    hr = DV_E_TYMED; 

                    if ((formatetc.tymed & TYMED.TYMED_HGLOBAL) != 0) 
                    { 
                        hr = GetDataIntoOleStructsByTypeMedimHGlobal(format, data, ref medium, doNotReallocate);
                    } 
                    else if ( ( formatetc.tymed & TYMED.TYMED_GDI ) != 0 )
                    {
                        hr = GetDataIntoOleStructsByTypeMediumGDI(format, data, ref medium);
                    } 
                    else if ( ( formatetc.tymed & TYMED.TYMED_ENHMF ) != 0 )
                    { 
                        hr = GetDataIntoOleStructsByTypeMediumEnhancedMetaFile(format, data, ref medium); 
                    }
                    else if ( ( formatetc.tymed & TYMED.TYMED_ISTREAM ) != 0 ) 
                    {
                        hr = GetDataIntoOleStructsByTypeMedimIStream(format, data, ref medium);
                    }
                } 
            }
 
            return hr; 
        }
 
        /// 
        /// Populates Ole data structes from a dataObject that is TYMED_HGLOBAL.
        /// 
        ///  
        /// Critical - calls critical methods (saving objects to streams, etc.),
        ///            deals with unmanaged structures, etc. 
        ///  
        [SecurityCritical]
        private int GetDataIntoOleStructsByTypeMedimHGlobal(string format, object data, ref STGMEDIUM medium, bool doNotReallocate) 
        {
            int hr;

            hr = NativeMethods.E_FAIL; 

            if (data is Stream) 
            { 
                hr = SaveStreamToHandle(medium.unionmember, (Stream)data, doNotReallocate);
            } 
            else if (IsFormatEqual(format, DataFormats.Html)
                || IsFormatEqual(format, DataFormats.Xaml))
            {
                // Save Html and Xaml data string as UTF8 encoding. 
                hr = SaveStringToHandleAsUtf8(medium.unionmember, data.ToString(), doNotReallocate);
            } 
            else if (IsFormatEqual(format, DataFormats.Text) 
                || IsFormatEqual(format, DataFormats.Rtf)
                || IsFormatEqual(format, DataFormats.OemText) 
                || IsFormatEqual(format, DataFormats.CommaSeparatedValue))
            {
                hr = SaveStringToHandle(medium.unionmember, data.ToString(), false /* unicode */, doNotReallocate);
            } 
            else if (IsFormatEqual(format, DataFormats.UnicodeText)||
                     IsFormatEqual(format, DataFormats.ApplicationTrust)) 
            { 
                hr = SaveStringToHandle(medium.unionmember, data.ToString(), true /* unicode */, doNotReallocate);
            } 
            else if (IsFormatEqual(format, DataFormats.FileDrop))
            {
                hr = SaveFileListToHandle(medium.unionmember, (string[])data, doNotReallocate);
            } 
            else if (IsFormatEqual(format, DataFormats.FileName))
            { 
                string[] filelist; 

                filelist = (string[])data; 
                hr = SaveStringToHandle(medium.unionmember, filelist[0], false /* unicode */, doNotReallocate);
            }
            else if (IsFormatEqual(format, DataFormats.FileNameW))
            { 
                string[] filelist;
 
                filelist = (string[])data; 
                hr = SaveStringToHandle(medium.unionmember, filelist[0], true /* unicode */, doNotReallocate);
            } 
            else if (IsFormatEqual(format, DataFormats.Dib)
                && AssemblyHelper.IsImage(data))
            {
                // GDI+ does not properly handle saving to DIB images.  Since the 
                // clipboard will take an HBITMAP and publish a Dib, we don't need
                // to support this. 
                // 
                hr = DV_E_TYMED;
            } 
            else if (IsFormatEqual(format, typeof(BitmapSource).FullName))
            {
                // Save the System.Drawing.Bitmap or BitmapSource data to handle as BitmapSource
                hr = SaveSystemBitmapSourceToHandle(medium.unionmember, data, doNotReallocate); 
            }
            else if (IsFormatEqual(format, typeof(System.Drawing.Bitmap).FullName)) 
            { 
                // Save the System.Drawing.Bitmap or BitmapSource data to handle as System.Drawing.Bitmap
                hr = SaveSystemDrawingBitmapToHandle(medium.unionmember, data, doNotReallocate); 
            }
            else if (IsFormatEqual(format, DataFormats.EnhancedMetafile)
                || AssemblyHelper.IsMetafile(data))
            { 
                // We don't need to support the enhanced metafile for TYMED.TYMED_HGLOBAL,
                // since we directly support TYMED.TYMED_ENHMF. 
                hr = DV_E_TYMED; 
            }
            else if (IsFormatEqual(format, DataFormats.Serializable) 
                || data is ISerializable
                || (data != null && data.GetType().IsSerializable))
            {
                hr = SaveObjectToHandle(medium.unionmember, data, doNotReallocate); 
            }
            else 
            { 
                // Couldn't find the proper data for the current TYMED_HGLOBAL
                hr = DV_E_TYMED; 
            }

            if (hr == NativeMethods.S_OK)
            { 
                medium.tymed = TYMED.TYMED_HGLOBAL;
            } 
 
            return hr;
        } 

        /// 
        /// Populates Ole data structes from a dataObject that is TYMED_ISTREAM.
        ///  
        /// 
        /// Critical - calls critical methods (saving objects to streams, etc.), 
        ///            deals with unmanaged structures, etc. 
        /// 
        [SecurityCritical] 
        private int GetDataIntoOleStructsByTypeMedimIStream(string format, object data, ref STGMEDIUM medium)
        {
            IStream istream = (IStream)( Marshal.GetObjectForIUnknown(medium.unionmember) );
            if ( istream == null ) 
            {
                return NativeMethods.E_INVALIDARG; 
            } 

            int hr = NativeMethods.E_FAIL; 

            try
            {
                // If the format is ISF, we should copy the data from the managed stream to the COM IStream object. 
                if ( format == System.Windows.Ink.StrokeCollection.InkSerializedFormat )
                { 
                    Stream inkStream = data as Stream; 

                    if ( inkStream != null ) 
                    {
                        IntPtr size = (IntPtr)inkStream.Length;

                        byte[] buffer = new byte[NativeMethods.IntPtrToInt32(size)]; 
                        inkStream.Position = 0;
                        inkStream.Read(buffer, 0, NativeMethods.IntPtrToInt32(size)); 
 
                        istream.Write(buffer, NativeMethods.IntPtrToInt32(size), IntPtr.Zero);
                        hr = NativeMethods.S_OK; 
                    }
                }
            }
            finally 
            {
                Marshal.ReleaseComObject(istream); 
            } 

            if ( NativeMethods.Succeeded(hr) ) 
            {
                medium.tymed = TYMED.TYMED_ISTREAM;
            }
 
            return hr;
        } 
 
        /// 
        /// Populates Ole data structes from a dataObject that is TYMED_GDI. 
        /// 
        /// 
        /// Critical - calls critical methods (getting the compatible bitmap),
        ///            deals with unmanaged structures, etc. 
        /// 
        [SecurityCritical] 
        private int GetDataIntoOleStructsByTypeMediumGDI(string format, object data, ref STGMEDIUM medium) 
        {
            int hr; 

            hr = NativeMethods.E_FAIL;

            if (IsFormatEqual(format, DataFormats.Bitmap) 
                && (AssemblyHelper.IsBitmap(data) || IsDataSystemBitmapSource(data)))
            { 
                // Get the bitmap and save it. 
                IntPtr hBitmap;
 
                hBitmap = GetCompatibleBitmap(data);

                if (hBitmap != IntPtr.Zero)
                { 
                    medium.tymed = TYMED.TYMED_GDI;
                    medium.unionmember = hBitmap; 
 
                    hr = NativeMethods.S_OK;
                } 
            }
            else
            {
                // Couldn't find the proper data for the current TYMED_GDI 
                hr = DV_E_TYMED;
            } 
 
            return hr;
        } 

        /// 
        /// Populates Ole data structes from a dataObject that is TYMED_ENHMF.
        ///  
        /// 
        /// Critical - deals with unmanaged structures, etc. 
        ///  
        [SecurityCritical]
        private int GetDataIntoOleStructsByTypeMediumEnhancedMetaFile(string format, object data, ref STGMEDIUM medium) 
        {
            IntPtr hMetafile;
            int hr;
 
            hr = NativeMethods.E_FAIL;
 
            if (IsFormatEqual(format, DataFormats.EnhancedMetafile)) 
            {
                // Get the enhanced metafile handle from the metafile data 
                // and save the metafile handle.
                hMetafile = GetEnhancedMetafileHandle(format, data);

                if (hMetafile != IntPtr.Zero) 
                {
                    medium.tymed = TYMED.TYMED_ENHMF; 
                    medium.unionmember = hMetafile; 

                    hr = NativeMethods.S_OK; 
                }
            }
            else
            { 
                // Couldn't find the proper data for the current TYMED_ENHMF
                hr = DV_E_TYMED; 
            } 

            return hr; 
        }

        /// 
        /// Critical - writes to arbitrary handle (memory) 
        /// 
        [SecurityCritical] 
        private int SaveObjectToHandle(IntPtr handle, Object data, bool doNotReallocate) 
        {
            Stream stream; 
            BinaryWriter binaryWriter;
            BinaryFormatter formatter;

            using (stream = new MemoryStream()) 
            {
                using (binaryWriter = new BinaryWriter(stream)) 
                { 
                    binaryWriter.Write(_serializedObjectID);
 
                    formatter = new BinaryFormatter();

                    formatter.Serialize(stream, data);
                    return SaveStreamToHandle(handle, stream, doNotReallocate); 
                }
            } 
        } 

        ///  
        /// Saves stream out to handle.
        /// 
        /// 
        /// Critical - direct unmanaged memory access 
        /// 
        [SecurityCritical] 
        private int SaveStreamToHandle(IntPtr handle, Stream stream, bool doNotReallocate) 
        {
            IntPtr size; 
            IntPtr ptr;

            if (handle == IntPtr.Zero)
            { 
                return (NativeMethods.E_INVALIDARG);
            } 
 
            size = (IntPtr)stream.Length;
 
            int hr = EnsureMemoryCapacity(ref handle, NativeMethods.IntPtrToInt32(size), doNotReallocate);
            if (NativeMethods.Failed(hr))
            {
                return hr; 
            }
 
            ptr = Win32GlobalLock(new HandleRef(this, handle)); 

            try 
            {
                byte[] bytes;

                bytes = new byte[NativeMethods.IntPtrToInt32(size)]; 
                stream.Position = 0;
                stream.Read(bytes, 0, NativeMethods.IntPtrToInt32(size)); 
                Marshal.Copy(bytes, 0, ptr, NativeMethods.IntPtrToInt32(size)); 
            }
            finally 
            {
                Win32GlobalUnlock(new HandleRef(this, handle));
            }
 
            return NativeMethods.S_OK;
        } 
 
        /// 
        /// Save the System.Drawing.Bitmap or BitmapSource data to handle as BitmapSource. 
        /// 
        /// 
        /// Critical - writes to arbitrary handle (memory)
        ///  
        [SecurityCritical]
        private int SaveSystemBitmapSourceToHandle(IntPtr handle, Object data, bool doNotReallocate) 
        { 
            BitmapSource bitmapSource;
            Stream bitmapStream; 
            BitmapEncoder bitmapEncoder;

            bitmapSource = null;
 
            if (IsDataSystemBitmapSource(data))
            { 
                bitmapSource = (BitmapSource)data; 
            }
            else if (AssemblyHelper.IsBitmap(data)) 
            {
                System.Drawing.Bitmap systemDrawingBitmap;

                systemDrawingBitmap = (System.Drawing.Bitmap)data; 

                // Create BitmapSource instance from System.Drawing.Bitmap 
                bitmapSource = Imaging.CreateBitmapSourceFromHBitmap( 
                    systemDrawingBitmap.GetHbitmap(),
                    IntPtr.Zero, 
                    Int32Rect.Empty,
                    null);
            }
 
            Invariant.Assert(bitmapSource != null);
 
            // Get BitmapSource stream to save it as the handle 
            bitmapEncoder = new BmpBitmapEncoder();
            bitmapEncoder.Frames.Add(BitmapFrame.Create(bitmapSource)); 
            bitmapStream = new MemoryStream();
            bitmapEncoder.Save(bitmapStream);

            return SaveStreamToHandle(handle, bitmapStream, doNotReallocate); 
        }
 
        ///  
        /// Save the System.Drawing.Bitmap or BitmapSource data to handle as System.Drawing.Bitmap.
        ///  
        /// 
        /// Critical - writes to arbitrary handle (memory)
        /// 
        [SecurityCritical] 
        private int SaveSystemDrawingBitmapToHandle(IntPtr handle, Object data, bool doNotReallocate)
        { 
            System.Drawing.Bitmap systemDrawingBitmap; 

            systemDrawingBitmap = null; 

            if (AssemblyHelper.IsBitmap(data))
            {
                systemDrawingBitmap = (System.Drawing.Bitmap)data; 
            }
            else if (IsDataSystemBitmapSource(data)) 
            { 
                Stream bitmapStream;
                BitmapEncoder bitmapEncoder; 

                bitmapEncoder = new BmpBitmapEncoder();
                bitmapEncoder.Frames.Add(BitmapFrame.Create(data as BitmapSource));
                bitmapStream = new MemoryStream(); 
                bitmapEncoder.Save(bitmapStream);
 
                // Create System.Drawing.Bitmap instance from the bitmap stream of BitmapSource 
                systemDrawingBitmap = new System.Drawing.Bitmap(bitmapStream);
            } 

            Invariant.Assert(systemDrawingBitmap != null);

            return SaveObjectToHandle(handle, systemDrawingBitmap, doNotReallocate); 
        }
 
        ///  
        /// Saves a list of files out to the handle in HDROP format.
        ///  
        /// 
        /// Critical - access unmanaged memory directly (write)
        /// 
        [SecurityCritical] 
        private int SaveFileListToHandle(IntPtr handle, string[] files, bool doNotReallocate)
        { 
            IntPtr currentPtr; 
            Int32 baseStructSize;
            Int32 sizeInBytes; 
            IntPtr basePtr;
            int[] structData;

            if (files == null || files.Length < 1) 
            {
                return NativeMethods.S_OK; 
            } 

            if (handle == IntPtr.Zero) 
            {
                return (NativeMethods.E_INVALIDARG);
            }
 
            if (Marshal.SystemDefaultCharSize == 1)
            { 
                Invariant.Assert(false, "Expected the system default char size to be 2 for Unicode systems."); 
                return (NativeMethods.E_INVALIDARG);
            } 

            currentPtr = IntPtr.Zero;
            baseStructSize = FILEDROPBASESIZE;
            sizeInBytes = baseStructSize; 

            // First determine the size of the array 
            for (int i = 0; i < files.Length; i++) 
            {
                sizeInBytes += (files[i].Length + 1) * 2; 
            }

            // Add the extra 2bytes since it is unicode.
            sizeInBytes += 2; 

            int hr = EnsureMemoryCapacity(ref handle, sizeInBytes, doNotReallocate); 
            if (NativeMethods.Failed(hr)) 
            {
                return hr; 
            }

            basePtr = Win32GlobalLock(new HandleRef(this, handle));
 
            try
            { 
                currentPtr = basePtr; 

                // Write out the struct... 
                structData = new int[] { baseStructSize, 0, 0, 0, 0 };

                structData[4] = unchecked((int)0xFFFFFFFF);
 
                Marshal.Copy(structData, 0, currentPtr, structData.Length);
 
                currentPtr = (IntPtr)((long)currentPtr + baseStructSize); 

                // Win32 CopyMemory return void, so we should disable PreSharp 6523 that 
                // expects the Win32 exception with the last error.
#pragma warning disable 6523

                // Write out the strings... 
                for (int i = 0; i < files.Length; i++)
                { 
                    // Write out the each of file as the unicode and increase the pointer. 
                    UnsafeNativeMethods.CopyMemoryW(currentPtr, files[i], files[i].Length * 2);
                    currentPtr = (IntPtr)((long)currentPtr + (files[i].Length * 2)); 

                    // Terminate the each of file string.
                    Marshal.Copy(new char[] { '\0' }, 0, currentPtr, 1);
 
                    // Increase the current pointer by 2 since it is a unicode.
                    currentPtr = (IntPtr)((long)currentPtr + 2); 
                } 

#pragma warning restore 6523 

                // Terminate the string and add 2bytes since it is a unicode.
                Marshal.Copy(new char[] { '\0' }, 0, currentPtr, 1);
            } 
            finally
            { 
                Win32GlobalUnlock(new HandleRef(this, handle)); 
            }
 
            return NativeMethods.S_OK;
        }

        ///  
        /// Save string to handle. If unicode is set to true
        /// then the string is saved as unicode, else it is saves as DBCS. 
        ///  
        /// 
        /// Critical - writes directly to unmanaged memory 
        /// 
        [SecurityCritical]
        private int SaveStringToHandle(IntPtr handle, string str, bool unicode, bool doNotReallocate)
        { 
            if (handle == IntPtr.Zero)
            { 
                return (NativeMethods.E_INVALIDARG); 
            }
 
            if (unicode)
            {
                Int32 byteSize;
                IntPtr ptr; 
                char[] chars;
 
                byteSize = (str.Length*2 + 2); 

                int hr = EnsureMemoryCapacity(ref handle, byteSize, doNotReallocate); 
                if (NativeMethods.Failed(hr))
                {
                    return hr;
                } 

                ptr = Win32GlobalLock(new HandleRef(this, handle)); 
 
                try
                { 
                    chars = str.ToCharArray(0, str.Length);

                    // Win32 CopyMemory return void, so we should disable PreSharp 6523 that
                    // expects the Win32 exception with the last error. 
#pragma warning disable 6523
 
                    UnsafeNativeMethods.CopyMemoryW(ptr, chars, chars.Length * 2); 

#pragma warning restore 6523 

                    // Terminate the string becasue of GlobalReAlloc GMEM_ZEROINIT will zero
                    // out only the bytes it adds to the memory object. It doesn't initialize
                    // any of the memory that existed before the call. 
                    Marshal.Copy(new char[] { '\0' }, 0, (IntPtr)((ulong)ptr + (ulong)chars.Length * 2), 1);
                } 
                finally 
                {
                    Win32GlobalUnlock(new HandleRef(this, handle)); 
                }
            }
            else
            { 
                Int32 pinvokeSize;
                byte[] strBytes; 
                IntPtr ptr; 

                // Convert the unicode text to the ansi multi byte in case of the source unicode is available. 
                // WideCharToMultiByte will throw exception in case of passing 0 size of unicode.
                if (str.Length > 0)
                {
                    pinvokeSize = Win32WideCharToMultiByte(str, str.Length, null, 0); 
                }
                else 
                { 
                    pinvokeSize = 0;
                } 

                strBytes = new byte[pinvokeSize];

                if (pinvokeSize > 0) 
                {
                    Win32WideCharToMultiByte(str, str.Length, strBytes, strBytes.Length); 
                } 

                // Ensure memory allocation and copy multi byte data with the null terminate 
                int hr = EnsureMemoryCapacity(ref handle, pinvokeSize + 1, doNotReallocate);
                if (NativeMethods.Failed(hr))
                {
                    return hr; 
                }
 
                ptr = Win32GlobalLock(new HandleRef(this, handle)); 

                try 
                {
                    // Win32 CopyMemory return void, so we should disable PreSharp 6523 that
                    // expects the Win32 exception with the last error.
#pragma warning disable 6523 

                    UnsafeNativeMethods.CopyMemory(ptr, strBytes, pinvokeSize); 
 
#pragma warning restore 6523
 
                    Marshal.Copy(new byte[] { 0 }, 0, (IntPtr)((long)ptr + pinvokeSize), 1);
                }
                finally
                { 
                    Win32GlobalUnlock(new HandleRef(this, handle));
                } 
            } 

            return NativeMethods.S_OK; 
        }

        /// 
        /// Save string to handle as UTF8 encoding. 
        /// Html and Xaml data format will be save as UTF8 encoding.
        ///  
        ///  
        /// Critical - directly writes to unmanaged memory
        ///  
        [SecurityCritical]
        private int SaveStringToHandleAsUtf8(IntPtr handle, string str, bool doNotReallocate)
        {
            IntPtr pointerUtf8; 
            byte[] utf8Bytes;
            int utf8ByteCount; 
            UTF8Encoding utf8Encoding; 

            if (handle == IntPtr.Zero) 
            {
                return (NativeMethods.E_INVALIDARG);
            }
 
            // Create UTF8Encoding instance to convert the string to UFT8 from GetBytes.
            utf8Encoding = new UTF8Encoding(); 
 
            // Get the byte count to be UTF8 encoding.
            utf8ByteCount = utf8Encoding.GetByteCount(str); 

            // Create byte array and assign UTF8 encoding.
            utf8Bytes = utf8Encoding.GetBytes(str);
 
            int hr = EnsureMemoryCapacity(ref handle, utf8ByteCount + 1, doNotReallocate);
            if (NativeMethods.Failed(hr)) 
            { 
                return hr;
            } 

            pointerUtf8 = Win32GlobalLock(new HandleRef(this, handle));

            try 
            {
                // Win32 CopyMemory return void, so we should disable PreSharp 6523 that 
                // expects the Win32 exception with the last error. 
#pragma warning disable 6523
 
                // Copy UTF8 encoding bytes to the memory.
                UnsafeNativeMethods.CopyMemory(pointerUtf8, utf8Bytes, utf8ByteCount);

#pragma warning restore 6523 

                // Copy the null into the last of memory. 
                Marshal.Copy(new byte[] { 0 }, 0, (IntPtr)((long)pointerUtf8 + utf8ByteCount), 1); 
            }
            finally 
            {
                Win32GlobalUnlock(new HandleRef(this, handle));
            }
 
            return NativeMethods.S_OK;
        } 
 
        /// 
        ///     Return true if data is BitmapSource. 
        /// 
        private static bool IsDataSystemBitmapSource(object data)
        {
            if (data is System.Windows.Media.Imaging.BitmapSource) 
            {
                return true; 
            } 
            else
            { 
                return false;
            }
        }
 
        /// 
        /// Determines if the format/data combination is likely to 
        /// be serialized. This is only likely, because this isn't a 
        /// clone of the logic to determine the serialization code
        /// path. The idea is to determine if the format is likely 
        /// to be serialized and do an early security check. If that
        /// check fails, then we will omit the format from the list
        /// of available clipboard formats.
        /// 
        /// Note: at the time of serialization the correct security
        /// check will be performed, guaranteeing the security of 
        /// the data, however that will cause the clipboard to report 
        /// that there are no valid data items.
        ///  
        /// Clipboard format to check
        /// Clipboard data to check
        /// 
        /// true if the data is likely to be serializated 
        /// through CLR serialization
        ///  
        private static bool IsFormatAndDataSerializable(string format, object data) 
        {
            return 
                (IsFormatNotSupportedInPartialTrust(format))
                 &&
                 (IsFormatEqual(format, DataFormats.Serializable)
                  || data is ISerializable 
                  || (data != null && data.GetType().IsSerializable));
        } 
 
        /// 
        ///     This code is used to determine whether any of the formats in the list here are supported in partial trust. 
        ///     By adding an entry here we are letting consumers set and get data for this format in partial trust.
        /// 
        /// 
        ///  
        private static bool IsFormatNotSupportedInPartialTrust(string format)
        { 
            return (!IsFormatEqual(format, DataFormats.Text) 
                    && !IsFormatEqual(format, DataFormats.OemText)
                    && !IsFormatEqual(format, DataFormats.UnicodeText) 
                    && !IsFormatEqual(format, DataFormats.CommaSeparatedValue)
                    && !IsFormatEqual(format, DataFormats.Xaml)
                    && !IsFormatEqual(format, DataFormats.ApplicationTrust));
        } 
        /// 
        /// Return true if the format string are equal(Case-senstive). 
        ///  
        private static bool IsFormatEqual(string format1, string format2)
        { 
            return (String.CompareOrdinal(format1, format2) == 0);
        }

        ///  
        /// Ensures that a memory block is sized to match a specified byte count.
        ///  
        ///  
        /// Returns a pointer to the original memory block, a re-sized memory block,
        /// or null if the original block has insufficient capacity and doNotReallocate 
        /// is true.
        ///
        /// Returns an HRESULT
        ///  S_OK: success. 
        ///  STG_E_MEDIUMFULL: the original handle lacks capacity and doNotReallocate == true.  handle == null on exit.
        ///  E_OUTOFMEMORY: could not re-size the handle.  handle == null on exit. 
        /// 
        /// If doNotReallocate is false, this method will always realloc the original
        /// handle to fit minimumByteCount tightly. 
        /// 
        /// 
        /// Critical - access the unmanaged memory directly
        ///  
        [SecurityCritical]
        private int EnsureMemoryCapacity(ref IntPtr handle, Int32 minimumByteCount, bool doNotReallocate) 
        { 
            int hr = NativeMethods.S_OK;
 
            if (doNotReallocate)
            {
                int byteCount = NativeMethods.IntPtrToInt32(Win32GlobalSize(new HandleRef(this, handle)));
                if (byteCount < minimumByteCount) 
                {
                    handle = IntPtr.Zero; 
                    hr = STG_E_MEDIUMFULL; 
                }
            } 
            else
            {
                handle = Win32GlobalReAlloc(new HandleRef(this, handle),
                                               (IntPtr)minimumByteCount, 
                                               NativeMethods.GMEM_MOVEABLE
                                                | NativeMethods.GMEM_DDESHARE 
                                                | NativeMethods.GMEM_ZEROINIT); 

                if (handle == IntPtr.Zero) 
                {
                    hr = NativeMethods.E_OUTOFMEMORY;
                }
            } 

            return hr; 
        } 

        ///  
        /// Ensure returning Bitmap(BitmapSource or System.Drawing.Bitmap) data that base
        /// on the passed Bitmap format parameter.
        /// Bitmap data will be converted if the data mismatch with the format in case of
        /// autoConvert is "true", but return null if autoConvert is "false". 
        /// 
        ///  
        /// Critical - call the critical code(BitmapEncoder.Save)which calls unmanaged code. 
        /// TreatAsSafe - Demands unmanaged code permission.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private static object EnsureBitmapDataFromFormat(string format, bool autoConvert, object data)
        {
            object bitmapData = data; 

            if (IsDataSystemBitmapSource(data) && IsFormatEqual(format, SystemDrawingBitmapFormat)) 
            { 
                // Data is BitmapSource, but have the mismatched System.Drawing.Bitmap format
                if (autoConvert) 
                {
                    SecurityHelper.DemandUnmanagedCode();

                    // Convert data from BitmapSource to SystemDrawingBitmap 
                    Stream bitmapStream;
                    BitmapEncoder bitmapEncoder; 
 
                    bitmapEncoder = new BmpBitmapEncoder();
                    bitmapEncoder.Frames.Add(BitmapFrame.Create((BitmapSource)data)); 
                    bitmapStream = new MemoryStream();
                    bitmapEncoder.Save(bitmapStream);

                    // Create System.Drawing.Bitmap instance from the bitmap stream of BitmapSource 
                    bitmapData = new System.Drawing.Bitmap(bitmapStream);
                } 
                else 
                {
                    bitmapData = null; 
                }
            }
            else if (AssemblyHelper.IsBitmap(data) &&
                     (IsFormatEqual(format, DataFormats.Bitmap) || IsFormatEqual(format, SystemBitmapSourceFormat))) 
            {
                // Data is System.Drawing.Bitmap, but have the mismatched BitmapSource format 
                if (autoConvert) 
                {
                    // Convert data from SystemDrawingBitmap to SystemBitmapSource 
                    System.Drawing.Bitmap systemDrawingBitmap;
                    systemDrawingBitmap = (System.Drawing.Bitmap)data;

                    // Create BitmapSource instance from System.Drawing.Bitmap 
                    bitmapData = Imaging.CreateBitmapSourceFromHBitmap(
                        systemDrawingBitmap.GetHbitmap(), 
                        IntPtr.Zero, 
                        Int32Rect.Empty,
                        null); 
                }
                else
                {
                    bitmapData = null; 
                }
            } 
 
            return bitmapData;
        } 

        #endregion Private Methods

        //----------------------------------------------------- 
        //
        //  Private Fields 
        // 
        //------------------------------------------------------
 
        #region Private Fields

        private const string SystemDrawingBitmapFormat = "System.Drawing.Bitmap";
        private const string SystemBitmapSourceFormat = "System.Windows.Media.Imaging.BitmapSource"; 
        private const string SystemDrawingImagingMetafileFormat = "System.Drawing.Imaging.Metafile";
 
        private const int DV_E_FORMATETC     =       unchecked((int)0x80040064); 
        private const int DV_E_LINDEX        =       unchecked((int)0x80040068);
        private const int DV_E_TYMED         =       unchecked((int)0x80040069); 
        private const int DV_E_DVASPECT      =       unchecked((int)0x8004006B);
        private const int OLE_E_NOTRUNNING   =       unchecked((int)0x80040005);
        private const int OLE_E_ADVISENOTSUPPORTED = unchecked((int)0x80040003);
        private const int DATA_S_SAMEFORMATETC =     unchecked((int)0x00040130); 
        private const int STG_E_MEDIUMFULL   =       unchecked((int)0x80030070);
 
        // Const integer base size of the file drop list: "4 + 8 + 4 + 4" 
        private const int FILEDROPBASESIZE   = 20;
 
        // Allowed type medium.
        private static readonly TYMED[] ALLOWED_TYMEDS = new TYMED[]
        {
            TYMED.TYMED_HGLOBAL, 
            TYMED.TYMED_ISTREAM,
            TYMED.TYMED_ENHMF, 
            TYMED.TYMED_MFPICT, 
            TYMED.TYMED_GDI
        }; 


        // Inner data object of IDataObject.
        private System.Windows.IDataObject _innerData; 

        // We use this to identify that a stream is actually a serialized object.  On read, 
        // we don't know if the contents of a stream were saved "raw" or if the stream is really 
        // pointing to a serialized object.  If we saved an object, we prefix it with this
        // guid. 
        //
        // FD9EA796-3B13-4370-A679-56106BB288FB
        //
        private static readonly byte[] _serializedObjectID = new Guid(0xFD9EA796, 0x3B13, 0x4370, 0xA6, 0x79, 0x56, 0x10, 0x6B, 0xB2, 0x88, 0xFB).ToByteArray(); 

        #endregion Private Fields 
 

        #region FormatEnumerator Class 

        /// 
        /// IEnumFORMATETC implementation for DataObject.
        ///  
        private class FormatEnumerator : IEnumFORMATETC
        { 
            //----------------------------------------------------- 
            //
            //  Constructors 
            //
            //------------------------------------------------------

            #region Constructors 

            // Creates a new enumerator instance. 
            internal FormatEnumerator(DataObject dataObject) 
            {
                FORMATETC temp; 
                string[] formats;

                formats = dataObject.GetFormats();
                _formats = new FORMATETC[formats == null ? 0 : formats.Length]; 

                if (formats != null) 
                { 
                    for (int i = 0; i < formats.Length; i++)
                    { 
                        string format;

                        format = formats[i];
                        temp = new FORMATETC(); 
                        temp.cfFormat = (short)DataFormats.GetDataFormat(format).Id;
                        temp.dwAspect = DVASPECT.DVASPECT_CONTENT; 
                        temp.ptd = IntPtr.Zero; 
                        temp.lindex = -1;
 
                        if (IsFormatEqual(format, DataFormats.Bitmap))
                        {
                            temp.tymed = TYMED.TYMED_GDI;
                        } 
                        else if (IsFormatEqual(format, DataFormats.EnhancedMetafile))
                        { 
                            temp.tymed = TYMED.TYMED_ENHMF; 
                        }
                        else 
                        {
                            temp.tymed = TYMED.TYMED_HGLOBAL;
                        }
 
                        _formats[i] = temp;
                    } 
                } 
            }
 
            // Copy constructor.  Used by the Clone method.
            private FormatEnumerator(FormatEnumerator formatEnumerator)
            {
                _formats = formatEnumerator._formats; 
                _current = formatEnumerator._current;
            } 
 
            #endregion Constructors
 
            //------------------------------------------------------
            //
            //  Public Methods
            // 
            //-----------------------------------------------------
 
            #region Public Methods 

            // IEnumFORMATETC.Next implementation. 
            public int Next(int celt, FORMATETC[] rgelt, int[] pceltFetched)
            {
                int fetched = 0;
 
                if (rgelt == null)
                { 
                    return NativeMethods.E_INVALIDARG; 
                }
 
                for (int i = 0; i < celt && _current < _formats.Length; i++)
                {
                    rgelt[i] = _formats[this._current];
                    _current++; 
                    fetched++;
                } 
 
                if (pceltFetched != null)
                { 
                    pceltFetched[0] = fetched;
                }

                return (fetched == celt) ? NativeMethods.S_OK : NativeMethods.S_FALSE; 
            }
 
            // IEnumFORMATETC.Skip implementation. 
            public int Skip(int celt)
            { 
                // Make sure we don't overflow on the skip.
                _current = _current + (int)Math.Min(celt, Int32.MaxValue - _current);

                return (_current < _formats.Length) ? NativeMethods.S_OK : NativeMethods.S_FALSE; 
            }
 
            // IEnumFORMATETC.Reset implementation. 
            public int Reset()
            { 
                _current = 0;
                return NativeMethods.S_OK;
            }
 
            // IEnumFORMATETC.Clone implementation.
            public void Clone(out IEnumFORMATETC ppenum) 
            { 
                ppenum = new FormatEnumerator(this);
            } 

            #endregion Public Methods

            //------------------------------------------------------ 
            //
            //  Private Fields 
            // 
            //-----------------------------------------------------
 
            #region Private Fields

            // List of FORMATETC to enumerate.
            private readonly FORMATETC[] _formats; 

            // Current offset of the enumerator. 
            private int _current; 

            #endregion Private Fields 
        }

        #endregion FormatEnuerator Class
 
        #region OleConverter Class
 
        ///  
        /// OLE Converter.  This class embodies the nastiness required to convert from our
        /// managed types to standard OLE clipboard formats. 
        /// 
        private class OleConverter : IDataObject
        {
 
            //-----------------------------------------------------
            // 
            //  Constructors 
            //
            //----------------------------------------------------- 

            #region Constructors

            public OleConverter(IComDataObject data) 
            {
                _innerData = data; 
            } 

            #endregion Constructors 

            //------------------------------------------------------
            //
            //  Public Methods 
            //
            //----------------------------------------------------- 
 
            #region Public Methods
 
            //=------------------------------------------------------------------------=
            // System.Windows.IDataObject
            //=------------------------------------------------------------------------=
            public Object GetData(string format) 
            {
                return GetData(format, true); 
            } 

            public Object GetData(Type format) 
            {
                return GetData(format.FullName);
            }
 
            public Object GetData(string format, bool autoConvert)
            { 
                return GetData(format, autoConvert, DVASPECT.DVASPECT_CONTENT, -1); 
            }
 
            public bool GetDataPresent(string format)
            {
                return GetDataPresent(format, true);
            } 

            public bool GetDataPresent(Type format) 
            { 
                return GetDataPresent(format.FullName);
            } 

            public bool GetDataPresent(string format, bool autoConvert)
            {
                return GetDataPresent(format, autoConvert, DVASPECT.DVASPECT_CONTENT, -1); 
            }
 
            public string[] GetFormats() 
            {
                return GetFormats(true); 
            }

            public void SetData(Object data)
            { 
                if (data is ISerializable)
                { 
                    SetData(DataFormats.Serializable, data); 
                }
                else 
                {
                    SetData(data.GetType(), data);
                }
            } 

            ///  
            /// Critical - access protected resource (clipboard data) 
            /// TreatAsSafe - demands appropriate permission
            ///  
            [SecurityCritical, SecurityTreatAsSafe]
            public string[] GetFormats(bool autoConvert)
            {
                SecurityHelper.DemandAllClipboardPermission(); 

                IEnumFORMATETC enumFORMATETC; 
                ArrayList formats; 
                string[] temp;
 
                enumFORMATETC = null;
                formats = new ArrayList();

                enumFORMATETC = EnumFormatEtcInner(DATADIR.DATADIR_GET); 

                if (enumFORMATETC != null) 
                { 
                    FORMATETC []formatetc;
                    int[] retrieved; 

                    enumFORMATETC.Reset();

                    formatetc = new FORMATETC[] { new FORMATETC() }; 
                    retrieved = new int[] {1};
 
                    while (retrieved[0] > 0) 
                    {
                        retrieved[0] = 0; 

                        if (enumFORMATETC.Next(1, formatetc, retrieved) == NativeMethods.S_OK && retrieved[0] > 0)
                        {
                            string name; 

                            name = DataFormats.GetDataFormat(formatetc[0].cfFormat).Name; 
                            if (autoConvert) 
                            {
                                string[] mappedFormats; 

                                mappedFormats = GetMappedFormats(name);
                                for (int i=0; i
            /// Returns the data Object we are wrapping 
            /// 
            public IComDataObject OleDataObject 
            { 
                get
                { 
                    SecurityHelper.DemandUnmanagedCode();
                    return _innerData;
                }
            } 

            #endregion Public Properties 
 
            //-----------------------------------------------------
            // 
            //  Internal Fields
            //
            //-----------------------------------------------------
 
            #region Internal Fields
 
            internal IComDataObject _innerData; 

            #endregion Internal Fields 

            //-----------------------------------------------------
            //
            //  Private Methods 
            //
            //------------------------------------------------------ 
 
            #region Private Methods
 
            /// 
            /// Critical - reads from a protected resource (clipboard), calls
            ///            critical code (reading from unmanaged memory)
            /// TreatAsSafe - Demands the all clipboard permission 
            /// 
            [SecurityCritical, SecurityTreatAsSafe] 
            private Object GetData(string format, bool autoConvert, DVASPECT aspect, int index) 
            {
                SecurityHelper.DemandAllClipboardPermission(); 

                Object baseVar;
                Object original;
 
                baseVar = GetDataFromBoundOleDataObject(format, aspect, index);
                original = baseVar; 
 
                if (autoConvert && (baseVar == null || baseVar is MemoryStream))
                { 
                    string[] mappedFormats;

                    mappedFormats = GetMappedFormats(format);
                    if (mappedFormats != null) 
                    {
                        for (int i = 0; i < mappedFormats.Length; i++) 
                        { 
                            if (!IsFormatEqual(format, mappedFormats[i]))
                            { 
                                baseVar = GetDataFromBoundOleDataObject(mappedFormats[i], aspect, index);

                                if (baseVar != null && !(baseVar is MemoryStream))
                                { 
                                    if (IsDataSystemBitmapSource(baseVar) || AssemblyHelper.IsBitmap(baseVar))
                                    { 
                                        // Ensure Bitmap(BitmapSource or System.Drawing.Bitmap) data which 
                                        // match with the requested format.
                                        baseVar = EnsureBitmapDataFromFormat(format, autoConvert, baseVar); 
                                    }

                                    original = null;
                                    break; 
                                }
                            } 
                        } 
                    }
                } 

                if (original != null)
                {
                    return original; 
                }
                else 
                { 
                    return baseVar;
                } 
            }

            /// 
            /// Critical - Calls GetDataPresentInner which is critical because it talks to the 
            ///            native OLE object.
            /// TreatAsSafe - we demand the all clipboard permission 
            ///  
            [SecurityCritical, SecurityTreatAsSafe]
            private bool GetDataPresent(string format, bool autoConvert, DVASPECT aspect, int index) 
            {
                SecurityHelper.DemandAllClipboardPermission();

                bool baseVar; 

                baseVar = GetDataPresentInner(format, aspect, index); 
 
                if (!baseVar && autoConvert)
                { 
                    string[] mappedFormats;

                    mappedFormats = GetMappedFormats(format);
                    if (mappedFormats != null) 
                    {
                        for (int i = 0; i < mappedFormats.Length; i++) 
                        { 
                            if (!IsFormatEqual(format, mappedFormats[i]))
                            { 
                                baseVar = GetDataPresentInner(mappedFormats[i], aspect, index);
                                if (baseVar)
                                {
                                    break; 
                                }
                            } 
                        } 
                    }
                } 
                return baseVar;
            }

            private void SetData(string format, object data, bool autoConvert, DVASPECT aspect, int index) 
            {
                // If we want to support setting data into an OLE data Object, 
                // the code should be here. 
                throw new InvalidOperationException(SR.Get(SRID.DataObject_CannotSetDataOnAFozenOLEDataDbject));
            } 

            /// 
            /// Uses IStream and retrieves the specified format from the bound IComDataObject.
            ///  
            /// 
            /// Critical - access unmanaged memory directly, reads critical resource (clipboard) 
            ///  
            [SecurityCritical]
            private Object GetDataFromOleIStream(string format, DVASPECT aspect, int index) 
            {
                FORMATETC formatetc;
                STGMEDIUM medium;
 
                formatetc = new FORMATETC();
 
                formatetc.cfFormat = (short)DataFormats.GetDataFormat(format).Id; 
                formatetc.dwAspect = aspect;
                formatetc.lindex = index; 
                formatetc.tymed = TYMED.TYMED_ISTREAM;

                object outData = null;
 
                if (NativeMethods.S_OK == QueryGetDataInner(ref formatetc))
                { 
                    GetDataInner(ref formatetc, out medium); 
                    try
                    { 
                        // Check both handle and type of storage medium
                        if (medium.unionmember != IntPtr.Zero && medium.tymed == TYMED.TYMED_ISTREAM)
                        {
                            UnsafeNativeMethods.IStream pStream; 

                            pStream = (UnsafeNativeMethods.IStream)Marshal.GetObjectForIUnknown(medium.unionmember); 
 
                            NativeMethods.STATSTG sstg = new NativeMethods.STATSTG();
                            pStream.Stat(sstg, NativeMethods.STATFLAG_DEFAULT); 
                            int size = (int)sstg.cbSize;

                            IntPtr hglobal = Win32GlobalAlloc(NativeMethods.GMEM_MOVEABLE
                                                               | NativeMethods.GMEM_DDESHARE 
                                                               | NativeMethods.GMEM_ZEROINIT,
                                                              (IntPtr)(size)); 
                            try 
                            {
                                IntPtr ptr = Win32GlobalLock(new HandleRef(this, hglobal)); 

                                try
                                {
                                    // NTRAID:WINDOWS#1449332-2006/01/16-WAYNEZEN, 
                                    // Seek to the beginning of the stream before reading it.
                                    pStream.Seek(0, 0 /* STREAM_SEEK_SET */); 
                                    pStream.Read(ptr, size); 
                                }
                                finally 
                                {
                                    Win32GlobalUnlock(new HandleRef(this, hglobal));
                                }
                                outData = GetDataFromHGLOBAL(format, hglobal); 
                            }
                            finally 
                            { 
                                Win32GlobalFree(new HandleRef(this, hglobal));
                            } 
                        }
                    }
                    finally
                    { 
                        UnsafeNativeMethods.ReleaseStgMedium(ref medium);
                    } 
                } 

                return outData; 
            }


            ///  
            /// Retrieves the specified data type from the specified hglobal.
            ///  
            ///  
            /// Critical - reads data from the clipboard
            ///  
            [SecurityCritical]
            private object GetDataFromHGLOBAL(string format, IntPtr hglobal)
            {
                object data; 

                data = null; 
 
                if (hglobal != IntPtr.Zero)
                { 
                    //=---------------------------------------------------------------=
                    // Convert from OLE to IW objects
                    //=----------------------------------------------------------------=
                    // Add any new formats here... 
                    if (IsFormatEqual(format, DataFormats.Html)
                        || IsFormatEqual(format, DataFormats.Xaml)) 
                    { 
                        // Read string from handle as UTF8 encoding.
                        // ReadStringFromHandleUtf8 will return Unicode string from UTF8 
                        // encoded handle.
                        data = ReadStringFromHandleUtf8(hglobal);
                    }
                    else if (IsFormatEqual(format, DataFormats.Text) 
                        || IsFormatEqual(format, DataFormats.Rtf)
                        || IsFormatEqual(format, DataFormats.OemText) 
                        || IsFormatEqual(format, DataFormats.CommaSeparatedValue)) 
                    {
                        data = ReadStringFromHandle(hglobal, false); 
                    }
                    else if (IsFormatEqual(format, DataFormats.UnicodeText) ||
                             IsFormatEqual(format, DataFormats.ApplicationTrust))
                    { 
                        data = ReadStringFromHandle(hglobal, true);
                    } 
                    else if (IsFormatEqual(format, DataFormats.FileDrop)) 
                    {
                        SecurityHelper.DemandFilePathDiscoveryWriteRead(); 
                        data = (object)ReadFileListFromHandle(hglobal);
                    }
                    else if (IsFormatEqual(format, DataFormats.FileName))
                    { 
                        SecurityHelper.DemandFilePathDiscoveryWriteRead();
                        data = new string[] { ReadStringFromHandle(hglobal, false) }; 
                    } 
                    else if (IsFormatEqual(format, DataFormats.FileNameW))
                    { 
                        SecurityHelper.DemandFilePathDiscoveryWriteRead();
                        data = new string[] { ReadStringFromHandle(hglobal, true) };
                    }
                    else if (IsFormatEqual(format, typeof(BitmapSource).FullName)) 
                    {
                        data = ReadBitmapSourceFromHandle(hglobal); 
                    } 
                    else
                    { 
                        data = ReadObjectFromHandle(hglobal);
                    }

                } 

                return data; 
            } 

            ///  
            /// Uses HGLOBALs and retrieves the specified format from the bound IComDataObject.
            /// 
            /// 
            /// Critical - reads direclty from arbitrary unmanaged memory 
            /// 
            [SecurityCritical] 
            private object GetDataFromOleHGLOBAL(string format, DVASPECT aspect, int index) 
            {
                FORMATETC formatetc; 
                STGMEDIUM medium;
                Object data;

                formatetc = new FORMATETC(); 

                formatetc.cfFormat = (short)DataFormats.GetDataFormat(format).Id; 
                formatetc.dwAspect = aspect; 
                formatetc.lindex = index;
                formatetc.tymed = TYMED.TYMED_HGLOBAL; 

                data = null;

                if (NativeMethods.S_OK == QueryGetDataInner(ref formatetc)) 
                {
                    GetDataInner(ref formatetc, out medium); 
                    try 
                    {
 
                        // Check both handle and type of storage medium
                        if (medium.unionmember != IntPtr.Zero && medium.tymed == TYMED.TYMED_HGLOBAL)
                        {
                            data = GetDataFromHGLOBAL(format, medium.unionmember); 
                        }
                    } 
                    finally 
                    {
                        UnsafeNativeMethods.ReleaseStgMedium(ref medium); 
                    }
                }

                return data; 
            }
 
            ///  
            /// Retrieves the specified format data from the bound IComDataObject, from
            /// other sources that IStream and HGLOBAL... this is really just a place 
            /// to put the "special" formats like BITMAP, ENHMF, etc.
            /// 
            /// 
            /// Critical - calls unmanaged code to access the OLE data object 
            /// 
            [SecurityCritical] 
            private Object GetDataFromOleOther(string format, DVASPECT aspect, int index) 
            {
                FORMATETC formatetc; 
                STGMEDIUM medium;
                TYMED tymed;
                Object data;
 
                formatetc = new FORMATETC();
 
                tymed = (TYMED)0; 

                if (IsFormatEqual(format, DataFormats.Bitmap)) 
                {
                    tymed = TYMED.TYMED_GDI;
                }
                else if (IsFormatEqual(format, DataFormats.EnhancedMetafile)) 
                {
                    tymed = TYMED.TYMED_ENHMF; 
                } 

                if (tymed == (TYMED)0) 
                {
                    return null;
                }
 
                formatetc.cfFormat = (short)DataFormats.GetDataFormat(format).Id;
                formatetc.dwAspect = aspect; 
                formatetc.lindex = index; 
                formatetc.tymed = tymed;
 
                data = null;

                if (NativeMethods.S_OK == QueryGetDataInner(ref formatetc))
                { 
                    GetDataInner(ref formatetc, out medium);
                    try 
                    { 

                        if (medium.unionmember != IntPtr.Zero) 
                        {
                            if (IsFormatEqual(format, DataFormats.Bitmap))
                            //||IsFormatEqual(format, DataFormats.Dib)
                            { 
                                // Get the bitmap from the handle of bitmap.
                                data = GetBitmapSourceFromHbitmap(medium.unionmember); 
                            } 
                            else if (IsFormatEqual(format, DataFormats.EnhancedMetafile))
                            { 
                                // Get the metafile object form the enhanced metafile handle.
                                data = AssemblyHelper.GetMetafileFromHemf(medium.unionmember);
                            }
                        } 
                    }
                    finally 
                    { 
                        UnsafeNativeMethods.ReleaseStgMedium(ref medium);
                    } 
                }

                return data;
            } 

            ///  
            /// Extracts a managed Object from the innerData of the specified 
            /// format. This is the base of the OLE to managed conversion.
            ///  
            /// 
            /// Critical - calls critical code (reading from unmanaged memory)
            /// 
            [SecurityCritical] 
            private Object GetDataFromBoundOleDataObject(string format, DVASPECT aspect, int index)
            { 
                Object data; 

                data = null; 

                data = GetDataFromOleOther(format, aspect, index);
                if (data == null)
                { 
                    data = GetDataFromOleHGLOBAL(format, aspect, index);
                } 
                if (data == null) 
                {
                    data = GetDataFromOleIStream(format, aspect, index); 
                }

                return data;
            } 

            ///  
            /// Creates an Stream from the data stored in handle. 
            /// 
            ///  
            /// Critical - access unmanaged memory directly
            /// 
            [SecurityCritical]
            private Stream ReadByteStreamFromHandle(IntPtr handle, out bool isSerializedObject) 
            {
                IntPtr ptr; 
 
                ptr = Win32GlobalLock(new HandleRef(this, handle));
 
                try
                {
                    Int32 size;
                    byte[] bytes; 
                    int index;
 
                    size = NativeMethods.IntPtrToInt32(Win32GlobalSize(new HandleRef(this, handle))); 
                    bytes = new byte[size];
                    Marshal.Copy(ptr, bytes, 0, size); 
                    index = 0;

                    // The object here can either be a stream or a serialized
                    // object.  We identify a serialized object by writing the 
                    // bytes for the guid serializedObjectID at the front
                    // of the stream.  Check for that here. 
                    // 
                    if (size > _serializedObjectID.Length)
                    { 
                        isSerializedObject = true;
                        for(int i = 0; i < _serializedObjectID.Length; i++)
                        {
                            if (_serializedObjectID[i] != bytes[i]) 
                            {
                                isSerializedObject = false; 
                                break; 
                            }
                        } 

                        // Advance the byte pointer.
                        //
                        if (isSerializedObject) 
                        {
                            index = _serializedObjectID.Length; 
                        } 
                    }
                    else 
                    {
                        isSerializedObject = false;
                    }
 
                    return new MemoryStream(bytes, index, bytes.Length - index);
                } 
                finally 
                {
                    Win32GlobalUnlock(new HandleRef(this, handle)); 
                }
            }

            ///  
            /// Creates a new instance of the Object that has been persisted into the
            /// handle. 
            ///  
            /// 
            /// Critical - directly reads from unmanaged memory 
            /// 
            [SecurityCritical]
            private Object ReadObjectFromHandle(IntPtr handle)
            { 
                object value;
                bool isSerializedObject; 
                Stream stream; 

                value = null; 

                stream = ReadByteStreamFromHandle(handle, out isSerializedObject);

                if (isSerializedObject) 
                {
                    BinaryFormatter formatter; 
 
                    formatter = new BinaryFormatter();
                    value = formatter.Deserialize(stream); 
                }
                else
                {
                    value = stream; 
                }
 
                return value; 
            }
 
            /// 
            /// Creates a new instance of BitmapSource that has been saved to the
            /// handle as the memory stream of BitmapSource.
            ///  
            /// 
            /// Critical - directly reads from unmanaged memory 
            ///  
            [SecurityCritical]
            private BitmapSource ReadBitmapSourceFromHandle(IntPtr handle) 
            {
                Stream bitmapStream;
                BitmapSource bitmapSource;
                bool isSerializedObject; 

                bitmapSource = null; 
 
                // Read the bitmap stream from the handle
                bitmapStream = ReadByteStreamFromHandle(handle, out isSerializedObject); 

                if (bitmapStream != null)
                {
                    // Create BitmapSource instance from the bitmap stream 
                    bitmapSource = (BitmapSource)BitmapFrame.Create(bitmapStream);
                } 
 
                return bitmapSource;
            } 

            /// 
            /// Parses the HDROP format and returns a list of strings using
            /// the DragQueryFile function. 
            /// 
            ///  
            /// Critical - pinvokes into native code with data supplied by the caller. 
            /// 
            [SecurityCritical] 
            private string[] ReadFileListFromHandle(IntPtr hdrop)
            {
                string[] files;
                StringBuilder sb; 
                int count;
 
                files = null; 
                sb = new StringBuilder(NativeMethods.MAX_PATH);
 
                count = UnsafeNativeMethods.DragQueryFile(new HandleRef(this, hdrop), unchecked((int)0xFFFFFFFF), null, 0);
                if (count > 0)
                {
                    files = new string[count]; 

                    for (int i=0; i 
            /// Creates a string from the data stored in handle. If
            /// unicode is set to true, then the string is assume to be unicode,
            /// else DBCS (ASCI) is assumed.
            ///  
            /// 
            /// Critical - directly access unmanaged memory 
            ///  
            [SecurityCritical]
            private unsafe string ReadStringFromHandle(IntPtr handle, bool unicode) 
            {
                string stringData;
                IntPtr ptr;
 
                stringData = null;
 
                ptr = Win32GlobalLock(new HandleRef(this, handle)); 
                try
                { 
                    if (unicode)
                    {
                        stringData = new string((char*)ptr);
                    } 
                    else
                    { 
                        stringData = new string((sbyte*)ptr); 
                    }
                } 
                finally
                {
                    Win32GlobalUnlock(new HandleRef(this, handle));
                } 

                return stringData; 
            } 

            ///  
            /// Creates a string from the data stored in handle as UTF8.
            /// 
            /// 
            /// Critical - reads unmanaged memory directly 
            /// 
            [SecurityCritical] 
            private unsafe string ReadStringFromHandleUtf8(IntPtr handle) 
            {
                string stringData = null; 

                int utf8ByteSize = NativeMethods.IntPtrToInt32(Win32GlobalSize(new HandleRef(this, handle)));

                IntPtr pointerUtf8 = Win32GlobalLock(new HandleRef(this, handle)); 

                try 
                { 
                    int utf8ByteCount;
                    // GlobalSize can return the size of a memory block that may be 
                    // larger than the size requested when the memory was allocated.
                    // So recount the utf8 byte from looking the null terminator.
                    for (utf8ByteCount = 0; utf8ByteCount < utf8ByteSize; utf8ByteCount++)
                    { 
                        // Read the byte from utf8 encoded pointer until get the null terminator.
                        byte endByte = Marshal.ReadByte((IntPtr)((long)pointerUtf8 + utf8ByteCount)); 
 
                        // Break if endByte is the null terminator.
                        if (endByte == '\0') 
                        {
                            break;
                        }
                    } 

                    if (utf8ByteCount > 0) 
                    { 
                        byte[] bytes = new byte[utf8ByteCount];
 
                        // Copy the UTF8 encoded data from memory to the byte array.
                        Marshal.Copy(pointerUtf8, bytes, 0, utf8ByteCount);

                        // Create UTF8Encoding to decode the utf8encoded byte to the string(Unicode). 
                        UTF8Encoding utf8Encoding = new UTF8Encoding();
 
                        // Get the string from the UTF8 encoding bytes. 
                        stringData = utf8Encoding.GetString(bytes, 0, utf8ByteCount);
                    } 
                }
                finally
                {
                    Win32GlobalUnlock(new HandleRef(this, handle)); 
                }
 
                return stringData; 
            }
 
            /// 
            /// Critical - calls unmanaged code to access the OLE data object
            /// 
            [SecurityCritical] 
            private bool GetDataPresentInner(string format, DVASPECT aspect, int index)
            { 
                FORMATETC formatetc; 
                int hr;
 
                formatetc = new FORMATETC();
                formatetc.cfFormat = (short)DataFormats.GetDataFormat(format).Id;
                formatetc.dwAspect = aspect;
                formatetc.lindex = index; 

                for (int i=0; i 
            /// Critical - calls unmanaged code to access the OLE data object
            ///  
            [SecurityCritical]
            private int QueryGetDataInner(ref FORMATETC formatetc)
            {
                int hr; 

                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // BlessedAssert 
 
                try
                { 
                    hr = _innerData.QueryGetData(ref formatetc);
                }
                finally
                { 
                    SecurityPermission.RevertAssert();
                } 
 
                return hr;
            } 

            /// 
            /// Critical - calls unmanaged code to access the OLE data object
            ///  
            [SecurityCritical]
            private void GetDataInner(ref FORMATETC formatetc, out STGMEDIUM medium) 
            { 
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // BlessedAssert
                try 
                {
                        _innerData.GetData(ref formatetc, out medium);
                }
                finally 
                {
                    SecurityPermission.RevertAssert(); 
                } 
            }
 
            /// 
            /// Critical - calls unmanaged code to access the OLE data object
            /// 
            [SecurityCritical] 
            private IEnumFORMATETC EnumFormatEtcInner(DATADIR dwDirection)
            { 
                IEnumFORMATETC enumFORMATETC; 

                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // BlessedAssert 

                try
                {
                    enumFORMATETC = _innerData.EnumFormatEtc(dwDirection); 
                }
                finally 
                { 
                    SecurityPermission.RevertAssert();
                } 

                return enumFORMATETC;

            } 

            ///  
            ///     Get the bitmap from the handle of bitmap(Hbitmap). 
            ///
            ///     We need a separate method to avoid loading the System.Drawing assembly 
            ///     when unnecessary.
            /// 
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            private Object GetBitmapSourceFromHbitmap(IntPtr hbitmap) 
            {
                return Imaging.CreateBitmapSourceFromHBitmap( 
                    hbitmap, 
                    IntPtr.Zero,
                    Int32Rect.Empty, 
                    null);
            }

            #endregion Private Methods 
        }
 
        #endregion OleConverter Class 

 
        #region DataStore Class

        /// 
        /// DataStore 
        /// 
        private class DataStore : IDataObject 
        { 
            //------------------------------------------------------
            // 
            //  Constructors
            //
            //-----------------------------------------------------
 
            #region Constructors
 
            public DataStore() 
            {
            } 

            #endregion Constructors

            //------------------------------------------------------ 
            //
            //  Public Methods 
            // 
            //-----------------------------------------------------
 
            #region Public Methods

            public Object GetData(string format)
            { 
                return GetData(format, true);
            } 
 
            public Object GetData(Type format)
            { 
                return GetData(format.FullName);
            }

            public Object GetData(string format, bool autoConvert) 
            {
                return GetData(format, autoConvert, DVASPECT.DVASPECT_CONTENT, -1); 
            } 

            public bool GetDataPresent(string format) 
            {
                return GetDataPresent(format, true);
            }
 
            public bool GetDataPresent(Type format)
            { 
                return GetDataPresent(format.FullName); 
            }
 
            public bool GetDataPresent(string format, bool autoConvert)
            {
                return GetDataPresent(format, autoConvert, DVASPECT.DVASPECT_CONTENT, -1);
            } 

            public string[] GetFormats() 
            { 
                return GetFormats(true);
            } 

            public string[] GetFormats(bool autoConvert)
            {
                string[] baseVar; 

                //*********************************************************** 
                // important! this is cached security information. It will 
                //            remain valid for this function, but do not
                //            let this value leak outside of this function. 
                //
                bool serializationCheckFailedForThisFunction = false;

                baseVar = new string[_data.Keys.Count]; 

                _data.Keys.CopyTo(baseVar, 0); 
 
                if (autoConvert)
                { 
                    ArrayList formats;
                    string[] temp;

                    formats = new ArrayList(); 

                    for (int baseFormatIndex = 0; baseFormatIndex < baseVar.Length; baseFormatIndex++) 
                    { 
                        DataStoreEntry[] entries;
                        bool canAutoConvert; 

                        entries = (DataStoreEntry[])_data[baseVar[baseFormatIndex]];
                        canAutoConvert = true;
 
                        for (int dataStoreIndex = 0; dataStoreIndex < entries.Length; dataStoreIndex++)
                        { 
                            if (!entries[dataStoreIndex].AutoConvert) 
                            {
                                canAutoConvert = false; 
                                break;
                            }
                        }
 
                        if (canAutoConvert)
                        { 
                            string[] cur; 

                            cur = GetMappedFormats(baseVar[baseFormatIndex]); 
                            for (int mappedFormatIndex = 0; mappedFormatIndex < cur.Length; mappedFormatIndex++)
                            {
                                bool anySerializationFailure = false;
                                for (int dataStoreIndex = 0; 
                                    !anySerializationFailure
                                      && 
                                    dataStoreIndex < entries.Length; 
                                    dataStoreIndex++)
                                { 
                                    if (DataObject.IsFormatAndDataSerializable(cur[mappedFormatIndex], entries[dataStoreIndex].Data))
                                    {
                                        // We only call CallerHasSerializationPermission once per method call
                                        // to avoid the perf hit, and debugging nightmare of m*n exceptions 
                                        // getting thrown on copy
                                        // 
                                        if (serializationCheckFailedForThisFunction 
                                            || !SecurityHelper.CallerHasSerializationPermission())
                                        { 
                                            serializationCheckFailedForThisFunction = true;
                                            anySerializationFailure = true;
                                        }
                                    } 
                                }
                                if (!anySerializationFailure) 
                                { 
                                    formats.Add(cur[mappedFormatIndex]);
                                } 

                            }
                        }
                        else 
                        {
                            bool anySerializationFailure = serializationCheckFailedForThisFunction; 
                            for (int dataStoreIndex = 0; 
                                !anySerializationFailure
                                  && 
                                dataStoreIndex < entries.Length;
                                dataStoreIndex++)
                            {
                                if (DataObject.IsFormatAndDataSerializable(baseVar[baseFormatIndex], entries[dataStoreIndex].Data)) 
                                {
                                    if (!SecurityHelper.CallerHasSerializationPermission()) 
                                    { 
                                        serializationCheckFailedForThisFunction = true;
                                        anySerializationFailure = true; 
                                    }
                                }
                            }
                            if (!anySerializationFailure) 
                            {
                                formats.Add(baseVar[baseFormatIndex]); 
                            } 
                        }
                    } 

                    temp = new string[formats.Count];
                    formats.CopyTo(temp, 0);
                    baseVar = GetDistinctStrings(temp); 
                }
 
                return baseVar; 
            }
 
            public void SetData(Object data)
            {
                if (data is ISerializable
                    && !this._data.ContainsKey(DataFormats.Serializable)) 
                {
 
                    SetData(DataFormats.Serializable, data); 
                }
 
                SetData(data.GetType(), data);
            }

            public void SetData(string format, Object data) 
            {
                SetData(format, data, true); 
            } 

            public void SetData(Type format, Object data) 
            {
                SetData(format.FullName, data);
            }
 
            public void SetData(string format, Object data, bool autoConvert)
            { 
                // We do not have proper support for Dibs, so if the user explicitly asked 
                // for Dib and provided a Bitmap object we can't convert.  Instead, publish as an HBITMAP
                // and let the system provide the conversion for us. 
                //
                if (IsFormatEqual(format, DataFormats.Dib))
                {
                    if (autoConvert && (AssemblyHelper.IsBitmap(data) || IsDataSystemBitmapSource(data))) 
                    {
                        format = DataFormats.Bitmap; 
                    } 
                }
 
                SetData(format, data, autoConvert, DVASPECT.DVASPECT_CONTENT, 0);
            }

            #endregion Public Methods 

            //----------------------------------------------------- 
            // 
            //  Private Methods
            // 
            //------------------------------------------------------

            #region Private Methods
 
            private Object GetData(string format, bool autoConvert, DVASPECT aspect, int index)
            { 
                Object baseVar; 
                Object original;
                DataStoreEntry dataStoreEntry; 

                dataStoreEntry = FindDataStoreEntry(format, aspect, index);

                baseVar = GetDataFromDataStoreEntry(dataStoreEntry, format); 

                original = baseVar; 
 
                if (autoConvert
                    && (dataStoreEntry == null || dataStoreEntry.AutoConvert) 
                    && (baseVar == null || baseVar is MemoryStream))
                {
                    string[] mappedFormats;
 
                    mappedFormats = GetMappedFormats(format);
                    if (mappedFormats != null) 
                    { 
                        for (int i = 0; i < mappedFormats.Length; i++)
                        { 
                            if (!IsFormatEqual(format, mappedFormats[i]))
                            {
                                DataStoreEntry foundDataStoreEntry;
 
                                foundDataStoreEntry = FindDataStoreEntry(mappedFormats[i], aspect, index);
 
                                baseVar = GetDataFromDataStoreEntry(foundDataStoreEntry, mappedFormats[i]); 

                                if (baseVar != null && !(baseVar is MemoryStream)) 
                                {
                                    if (IsDataSystemBitmapSource(baseVar) || AssemblyHelper.IsBitmap(baseVar))
                                    {
                                        // Ensure Bitmap(BitmapSource or System.Drawing.Bitmap) data which 
                                        // match with the requested format.
                                        baseVar = EnsureBitmapDataFromFormat(format, autoConvert, baseVar); 
                                    } 

                                    original = null; 
                                    break;
                                }
                            }
                        } 
                    }
                } 
 
                if (original != null)
                { 
                    return original;
                }
                else
                { 
                    return baseVar;
                } 
            } 

            private bool GetDataPresent(string format, bool autoConvert, DVASPECT aspect, int index) 
            {
                if (!autoConvert)
                {
                    DataStoreEntry[] entries; 
                    DataStoreEntry dse;
                    DataStoreEntry naturalDse; 
 
                    if (!_data.ContainsKey(format))
                    { 
                        return false;
                    }

                    entries = (DataStoreEntry[])_data[format]; 
                    dse = null;
                    naturalDse = null; 
 
                    // Find the entry with the given aspect and index
                    for (int i = 0; i < entries.Length; i++) 
                    {
                        DataStoreEntry entry;

                        entry = entries[i]; 
                        if (entry.Aspect == aspect)
                        { 
                            if (index == -1 || entry.Index == index) 
                            {
                                dse = entry; 
                                break;
                            }
                        }
                        if (entry.Aspect == DVASPECT.DVASPECT_CONTENT && entry.Index == 0) 
                        {
                            naturalDse = entry; 
                        } 
                    }
 
                    // If we couldn't find a specific entry, we'll use
                    // aspect == Content and index == 0.
                    if (dse == null && naturalDse != null)
                    { 
                        dse = naturalDse;
                    } 
 
                    // If we still didn't find data, return false.
                    return (dse != null); 
                }
                else
                {
                    string[] formats; 

                    formats = GetFormats(autoConvert); 
                    for (int i = 0; i < formats.Length; i++) 
                    {
                        if (IsFormatEqual(format, formats[i])) 
                        {
                            return true;
                        }
                    } 
                    return false;
                } 
            } 

            private void SetData(string format, Object data, bool autoConvert, DVASPECT aspect, int index) 
            {
                DataStoreEntry dse;
                DataStoreEntry[] datalist;
 
                dse = new DataStoreEntry(data, autoConvert, aspect, index);
                datalist = (DataStoreEntry[])this._data[format]; 
 
                if (datalist == null)
                { 
                    datalist = (DataStoreEntry[])Array.CreateInstance(typeof(DataStoreEntry), 1);
                }
                else
                { 
                    DataStoreEntry[] newlist;
 
                    newlist = (DataStoreEntry[])Array.CreateInstance(typeof(DataStoreEntry), datalist.Length + 1); 
                    datalist.CopyTo(newlist, 1);
                    datalist = newlist; 
                }

                datalist[0] = dse;
                this._data[format] = datalist; 
            }
 
            private DataStoreEntry FindDataStoreEntry(string format, DVASPECT aspect, int index) 
            {
                DataStoreEntry[] dataStoreEntries; 
                DataStoreEntry dataStoreEntry;
                DataStoreEntry naturalDataStoreEntry;

                dataStoreEntries = (DataStoreEntry[])_data[format]; 
                dataStoreEntry = null;
                naturalDataStoreEntry = null; 
 
                // Find the entry with the given aspect and index
                if (dataStoreEntries != null) 
                {
                    for (int i = 0; i < dataStoreEntries.Length; i++)
                    {
                        DataStoreEntry entry; 

                        entry = dataStoreEntries[i]; 
                        if (entry.Aspect == aspect) 
                        {
                            if (index == -1 || entry.Index == index) 
                            {
                                dataStoreEntry = entry;
                                break;
                            } 
                        }
                        if (entry.Aspect == DVASPECT.DVASPECT_CONTENT && entry.Index == 0) 
                        { 
                            naturalDataStoreEntry = entry;
                        } 
                    }
                }

                // If we couldn't find a specific entry, we'll use 
                // aspect == Content and index == 0.
                if (dataStoreEntry == null && naturalDataStoreEntry != null) 
                { 
                    dataStoreEntry = naturalDataStoreEntry;
                } 

                return dataStoreEntry;
            }
 
            private Object GetDataFromDataStoreEntry(DataStoreEntry dataStoreEntry, string format)
            { 
                Object data; 

                data = null; 
                if (dataStoreEntry != null)
                {
                    data = dataStoreEntry.Data;
                } 

                return data; 
            } 

            #endregion Private Methods 

            //-----------------------------------------------------
            //
            //  Private Fields 
            //
            //------------------------------------------------------ 
 
            #region Private Fields
 
            // Data hash table.
            private Hashtable _data = new Hashtable();

            #endregion Private Fields 

 
            #region DataStoreEntry Class 

            private class DataStoreEntry 
            {
                //------------------------------------------------------
                //
                //  Constructors 
                //
                //----------------------------------------------------- 
 
                #region Constructors
 
                public DataStoreEntry(Object data, bool autoConvert, DVASPECT aspect, int index)
                {
                    this._data = data;
                    this._autoConvert = autoConvert; 
                    this._aspect = aspect;
                    this._index = index; 
                } 

                #endregion Constructors 

                //------------------------------------------------------
                //
                //  Public Properties 
                //
                //----------------------------------------------------- 
 
                #region Public Properties
 
                // Data object property.
                public Object Data
                {
                    get { return _data; } 
                    set { _data = value; }
                } 
 
                // Auto convert proeprty.
                public bool AutoConvert 
                {
                    get { return _autoConvert; }
                }
 
                // Aspect flag property.
                public DVASPECT Aspect 
                { 
                    get { return _aspect; }
                } 

                // Index property.
                public int Index
                { 
                    get { return _index; }
                } 
 
                #endregion Public Properties
 
                //-----------------------------------------------------
                //
                //  Private Fields
                // 
                //-----------------------------------------------------
 
                #region Private Fields 

                private Object _data; 
                private bool _autoConvert;
                private DVASPECT _aspect;
                private int _index;
 
                #endregion Private Fields
            } 
 
            #endregion DataStoreEntry Class
        } 
        #endregion DataStore Class

    }
 
    #endregion DataObject Class
} 

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