File: Core\CSharp\System\Windows\Clipboard.cs
Project: wpf\src\PresentationCore.csproj (PresentationCore)
//---------------------------------------------------------------------------
//
// <copyright file=Clipboard.cs company=Microsoft>
// Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright>
// 
// Description: Clipboard implementation to provide methods to place/get data from/to the system 
//              clipboard.
//
// See spec at http://avalon/uis/Data%20Transfer%20clipboard%20dragdrop/Avalon%20Clipboard.htm
// 
// History:
//  05/09/2002 : susiA      Created
//  06/16/2003 : sangilj    Moved to WCP
//
//---------------------------------------------------------------------------
 
using MS.Win32;
using MS.Internal;
using MS.Internal.PresentationCore;                        // SecurityHelper
using System.Collections.Specialized;
using System.IO;
using System.Security;
using System.Security.Permissions;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Threading;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
 
using SR = MS.Internal.PresentationCore.SR;
using SRID = MS.Internal.PresentationCore.SRID;
using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject;
 
namespace System.Windows
{
    #region Clipboard class
 
    /// <summary>
    /// Provides methods to place data on and retrieve data from the system clipboard. 
    /// This class cannot be inherited.
    /// </summary>
    public static class Clipboard 
    {
        //------------------------------------------------------
        //
        //  Public Methods
        //
        //------------------------------------------------------
 
        #region Public Methods
 
        /// <summary>
        /// Clear the system clipboard which the clipboard is emptied.
        /// SetDataObject.
        /// </summary>
        /// <SecurityNote>
        /// Critical - access critical data (clipboard information)
        /// PublicOk -  Clearing the clipboard is not inherently unsafe.
        /// </SecurityNote>
        [SecurityCritical]
        public static void Clear()
        {
            // Retry OLE operations several times as mitigation for clipboard locking issues in TS sessions.
            // See Dev10 bug 616223 and VSWhidbey bug 476911.
 
            int i = OleRetryCount;
 
            while (true)
            {
                // Clear the system clipboard by calling OleSetClipboard with null parameter.
                int hr = OleServicesContext.CurrentOleServicesContext.OleSetClipboard(null);
 
                if (NativeMethods.Succeeded(hr))
                {
                    break;
                }
 
                if (--i == 0)
                {
                    Marshal.ThrowExceptionForHR(hr);
                }
 
                Thread.Sleep(OleRetryDelay);
            }
        }
 
        /// <summary>
        /// Return true if Clipboard contains the audio data. Otherwise, return false.
        /// </summary>
        public static bool ContainsAudio()
        {
            return ContainsDataInternal(DataFormats.WaveAudio);
        }
 
        /// <summary>
        /// Return true if Clipboard contains the specified data format. Otherwise, return false.
        /// </summary>
        public static bool ContainsData(string format)
        {
            if (format == null)
            {
                throw new ArgumentNullException("format");
            }
 
            if (format == string.Empty)
            {
                throw new ArgumentException(SR.Get(SRID.DataObject_EmptyFormatNotAllowed));
            }
 
            return ContainsDataInternal(format);
        }
 
        /// <summary>
        /// Return true if Clipboard contains the file drop list format. Otherwise, return false.
        /// </summary>
        public static bool ContainsFileDropList()
        {
            return ContainsDataInternal(DataFormats.FileDrop);
        }
 
        /// <summary>
        /// Return true if Clipboard contains the image format. Otherwise, return false.
        /// </summary>
        public static bool ContainsImage()
        {
            return ContainsDataInternal(DataFormats.Bitmap);
        }
 
        /// <summary>
        /// Return true if Clipboard contains the text data format which is unicode. 
        /// Otherwise, return false.
        /// </summary>
        public static bool ContainsText()
        {
            return ContainsDataInternal(DataFormats.UnicodeText);
        }
 
        /// <summary>
        /// Return true if Clipboard contains the specified text data format which is unicode. 
        /// Otherwise, return false.
        /// </summary>
        public static bool ContainsText(TextDataFormat format)
        {
            if (!DataFormats.IsValidTextDataFormat(format))
            {
                throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat));
            }
 
            return ContainsDataInternal(DataFormats.ConvertToDataFormats(format));
        }
 
        /// <summary>
        /// Permanently renders the contents of the last IDataObject that was set onto the clipboard.
        /// </summary>
        public static void Flush()
        {
            // Retry OLE operations several times as mitigation for clipboard locking issues in TS sessions.
            // See Dev10 bug 616223 and VSWhidbey bug 476911.
 
            int i = OleRetryCount;
 
            while (true)
            {
                int hr = OleServicesContext.CurrentOleServicesContext.OleFlushClipboard();
 
                if (NativeMethods.Succeeded(hr))
                {
                    break;
                }
 
                if (--i == 0)
                {
                    SecurityHelper.ThrowExceptionForHR(hr);
                }
 
                Thread.Sleep(OleRetryDelay);
            }
        }
 
        /// <summary>
        /// Get audio data as Stream from Clipboard.
        /// </summary>
        public static Stream GetAudioStream()
        {
            return GetDataInternal(DataFormats.WaveAudio) as Stream;
        }
 
        /// <summary>
        /// Get data for the specified data format from Clipboard.
        /// </summary>
        public static object GetData(string format)
        {
            if (format == null)
            {
                throw new ArgumentNullException("format");
            }
 
            if (format == string.Empty)
            {
                throw new ArgumentException(SR.Get(SRID.DataObject_EmptyFormatNotAllowed));
            }
 
            return GetDataInternal(format);
        }
 
        /// <summary>
        /// Get the file drop list as StringCollection from Clipboard.
        /// </summary>
        public static StringCollection GetFileDropList()
        {
            StringCollection fileDropListCollection;
            string[] fileDropList;
 
            fileDropListCollection = new StringCollection();
 
            fileDropList = GetDataInternal(DataFormats.FileDrop) as string[];
            if (fileDropList != null)
            {
                fileDropListCollection.AddRange(fileDropList);
            }
 
            return fileDropListCollection;
        }
 
        /// <summary>
        /// Get the image from Clipboard.
        /// </summary>
        public static BitmapSource GetImage()
        {
            return GetDataInternal(DataFormats.Bitmap) as BitmapSource;
        }
 
        /// <summary>
        /// Get text from Clipboard.
        /// </summary>
        public static string GetText()
        {
            return GetText(TextDataFormat.UnicodeText);
        }
 
        /// <summary>
        /// Get text from Clipboard.
        /// </summary>
        public static string GetText(TextDataFormat format)
        {
            if (!DataFormats.IsValidTextDataFormat(format))
            {
                throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat));
            }
 
            string text;
 
            text = (string)GetDataInternal(DataFormats.ConvertToDataFormats(format));
 
            if (text != null)
            {
                return text;
            }
 
            return string.Empty;
        }
 
        /// <summary>
        /// Set the audio data to Clipboard.
        /// </summary>
        public static void SetAudio(byte[] audioBytes)
        {
            if (audioBytes == null)
            {
                throw new ArgumentNullException("audioBytes");
            }
 
            SetAudio(new MemoryStream(audioBytes));
        }
 
        /// <summary>
        /// Set the audio data to Clipboard.
        /// </summary>
        public static void SetAudio(Stream audioStream)
        {
            if (audioStream == null)
            {
                throw new ArgumentNullException("audioStream");
            }
 
            SetDataInternal(DataFormats.WaveAudio, audioStream);
        }
 
        /// <summary>
        /// Set the specified data to Clipboard.
        /// </summary>
        public static void SetData(string format, object data)
        {
            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");
            }
 
            SetDataInternal(format, data);
        }
 
        /// <summary>
        /// Set the file drop list to Clipboard.
        /// </summary>
        public static 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)
                {
                    throw new ArgumentException(SR.Get(SRID.DataObject_FileDropListHasInvalidFileDropPath, fileDropList));
                }
            }
 
            string[] fileDropListStrings;
 
            fileDropListStrings = new string[fileDropList.Count];
            fileDropList.CopyTo(fileDropListStrings, 0);
 
            SetDataInternal(DataFormats.FileDrop, fileDropListStrings);
        }
 
        /// <summary>
        /// Set the image data to Clipboard.
        /// </summary>
        public static void SetImage(BitmapSource image)
        {
            if (image == null)
            {
                throw new ArgumentNullException("image");
            }
 
            SetDataInternal(DataFormats.Bitmap, image);
        }
 
        /// <summary>
        /// Set the text data to Clipboard.
        /// </summary>
        public static void SetText(string text)
        {
            if (text == null)
            {
                throw new ArgumentNullException("text");
            }
 
            SetText(text, TextDataFormat.UnicodeText);
        }
 
        /// <summary>
        /// Set the text data to Clipboard.
        /// </summary>
        public static void SetText(string text, TextDataFormat format)
        {
            if (text == null)
            {
                throw new ArgumentNullException("text");
            }
 
            if (!DataFormats.IsValidTextDataFormat(format))
            {
                throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat));
            }
 
            SetDataInternal(DataFormats.ConvertToDataFormats(format), text);
        }
 
        /// <summary>
        /// Retrieves the data object that is currently on the system clipboard.
        /// </summary>
        /// <remarks>
        ///     Callers must have UIPermission(UIPermissionClipboard.AllClipboard) to call this API.
        /// </remarks>
        /// <SecurityNote>
        /// Critical - access critical data (clipboard information)
        /// PublicOk - demands appropriate permission (AllClipboard)
        /// </SecurityNote>
        [SecurityCritical]
        public static IDataObject GetDataObject() 
        {
            SecurityHelper.DemandAllClipboardPermission();
 
            return GetDataObjectInternal();
        }
 
        /// <summary>
        /// Determines whether the data object previously placed on the clipboard
        /// by the SetDataObject is still on the clipboard.
        /// </summary>
        /// <param name="data">
        /// Data object from the current containing clipboard which the caller
        /// previously placed on the clipboard.
        /// </param>
        public static bool IsCurrent(IDataObject data) 
        {
            bool bReturn;
 
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
 
            bReturn = false;
 
            if (data is IComDataObject)
            {
                int hr;
 
                // Retry OLE operations several times as mitigation for clipboard locking issues in TS sessions.
                // See Dev10 bug 616223 and VSWhidbey bug 476911.
 
                int i = OleRetryCount;
 
                while (true)
                {
                    hr = OleServicesContext.CurrentOleServicesContext.OleIsCurrentClipboard((IComDataObject)data);
 
                    if (NativeMethods.Succeeded(hr) || (--i == 0))
                    {
                        break;
                    }
 
                    Thread.Sleep(OleRetryDelay);
                }
 
                if (hr == NativeMethods.S_OK)
                {
                    bReturn = true;
                }
                else if (!NativeMethods.Succeeded(hr))
                {
                    throw new ExternalException("OleIsCurrentClipboard()", hr);
                }
            }
 
            return bReturn;
        }
 
        /// <summary>
        /// Places nonpersistent data on the system clipboard.
        /// </summary>
        /// <param name="data">
        /// The specific data to be on clipboard.
        /// </param>
        /// <remarks>
        ///     Callers must have UIPermission(UIPermissionClipboard.AllClipboard) to call this API.
        /// </remarks>
        /// <SecurityNote>
        /// Critical - access critical data (clipboard information)
        /// PublicOk - demands appropriate permission (AllClipboard)
        /// </SecurityNote>
        [SecurityCritical]
        public static void SetDataObject(object data) 
        {
            SecurityHelper.DemandAllClipboardPermission();
 
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
 
            SetDataObject(data, false);
        }
 
        /// <summary>
        /// Places data on the system Clipboard and uses copy to specify whether the data 
        /// should remain on the Clipboard after the application exits.
        /// </summary>
        /// <param name="data">
        /// The specific data to be on clipboard.
        /// </param>
        /// <param name="copy">
        /// Specify whether the data should remain on the clipboard after the application exits.
        /// </param>
        /// <remarks>
        ///     Callers must have UIPermission(UIPermissionClipboard.AllClipboard) to call this API.
        /// </remarks>
        /// <SecurityNote>
        /// Critical - calls critical code (set clipboard), and potentially deals 
        ///            with unmanaged pointers
        /// PublicOk - Demands All Clipboard permissions
        /// </SecurityNote>
        [SecurityCritical]
        public static void SetDataObject(object data, bool copy)
        {
            SecurityHelper.DemandAllClipboardPermission();
            CriticalSetDataObject(data,copy);
        }
 
        #endregion Public Methods
 
        #region Internal Methods
 
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
 
        /// <summary>
        /// Determines whether the legacy dangerous clipboard deserialization mode should be used based on the AppContext switch and Device Guard policies.
        /// </summary>
        /// <returns>
        /// If Device Guard is enabled this method returns false, otherwise it returns the AppContext switch value.
        /// </returns>
        internal static bool UseLegacyDangerousClipboardDeserializationMode()
        {
            return !IsDeviceGuardEnabled && CoreAppContextSwitches.EnableLegacyDangerousClipboardDeserializationMode;
        }
 
        /// <summary>
        /// Places data on the system Clipboard and uses copy to specify whether the data 
        /// should remain on the Clipboard after the application exits.
        /// </summary>
        /// <param name="data">
        /// The specific data to be on clipboard.
        /// </param>
        /// <param name="copy">
        /// Specify whether the data should remain on the clipboard after the application exits.
        /// </param>
        /// <SecurityNote>
        /// Critical - calls critical code (set clipboard), and potentially deals 
        ///            with unmanaged pointers
        /// </SecurityNote>
        [SecurityCritical]
        [FriendAccessAllowed]
        internal static void CriticalSetDataObject(object data, bool copy)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
 
            IComDataObject dataObject;
 
            if (data is DataObject)
            {
                dataObject = (DataObject)data;
            }
            else if (data is IComDataObject)
            {
                SecurityHelper.DemandUnmanagedCode();
                dataObject = (IComDataObject)data;
            }
            else
            {
                dataObject = new DataObject(data);
            }
 
            // Retry OLE operations several times as mitigation for clipboard locking issues in TS sessions.
            // See Dev10 bug 616223 and VSWhidbey bug 476911.
 
            int i = OleRetryCount;
 
            while (true)
            {
                // Clear the system clipboard by calling OleSetClipboard with null parameter.
                int hr = OleServicesContext.CurrentOleServicesContext.OleSetClipboard(dataObject);
 
                if (NativeMethods.Succeeded(hr))
                {
                    break;
                }
 
                if (--i == 0)
                {
                    Marshal.ThrowExceptionForHR(hr);
                }
 
                Thread.Sleep(OleRetryDelay);
            }
 
            if (copy)
            {
                // Dev10 bug 835751 - OleSetClipboard and OleFlushClipboard both modify the clipboard
                // and cause notifications to be sent to clipboard listeners. We sleep a bit here to
                // mitigate issues with clipboard listeners (like TS) corrupting the clipboard contents
                // as a result of these two calls being back to back.
                Thread.Sleep(OleFlushDelay);
 
                Flush();
            }
        }
 
        /// <SecurityNote>
        /// Critical - access critical data (clipboard information)
        /// TreatAsSafe: Returning a bool indicating whether there is data on the clipboard is ok
        /// </SecurityNote>
        [SecurityCritical, SecurityTreatAsSafe]
        [FriendAccessAllowed]
        internal static bool IsClipboardPopulated()
        {
            bool isPopulated = false;
            (new UIPermission(UIPermissionClipboard.AllClipboard)).Assert();//BlessedAssert
            try
            {
                isPopulated = (GetDataObjectInternal() != null);
            }
            finally
            {
                UIPermission.RevertAssert();
            }
            return isPopulated;
        }
 
        #endregion Internal Methods
 
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------
 
        #region Private Methods
 
        /// <summary>
        /// Calls IsDynamicCodePolicyEnabled to determine if DeviceGuard is enabled, then caches it so subsequent calls only return the cached value.
        /// </summary>
        private static bool IsDeviceGuardEnabled
        {
            get
            {
                if (_isDeviceGuardEnabled < 0) return false;
                if (_isDeviceGuardEnabled > 0) return true;
 
                bool isDynamicCodePolicyEnabled = IsDynamicCodePolicyEnabled();
                _isDeviceGuardEnabled = isDynamicCodePolicyEnabled ? 1 : -1;
 
                return isDynamicCodePolicyEnabled;
            }
        }
 
        /// <summary>
        /// Loads Wldp.dll and looks for WldpIsDynamicCodePolicyEnabled to determine whether DeviceGuard is enabled.
        /// </summary>
        /// <SecurityNote>
        ///     Critical: Attempts to load unmanaged wldp.dll and attempts to get the proc address of an RS4+ only export.
        ///     TreatAsSafe: Does not return critical data, does not change critical state, does not consume untrusted input.
        /// </SecurityNote>
        [SecuritySafeCritical]
        private static bool IsDynamicCodePolicyEnabled()
        {
            bool isEnabled = false;
 
            IntPtr hModule = IntPtr.Zero;
            try
            {
                hModule = LoadLibraryHelper.SecureLoadLibraryEx(ExternDll.Wldp, IntPtr.Zero, UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_SYSTEM32);
                if (hModule != IntPtr.Zero)
                {
                    IntPtr entryPoint = UnsafeNativeMethods.GetProcAddressNoThrow(new HandleRef(null, hModule), "WldpIsDynamicCodePolicyEnabled");
                    if (entryPoint != IntPtr.Zero)
                    {
                        int hResult = UnsafeNativeMethods.WldpIsDynamicCodePolicyEnabled(out isEnabled);
 
                        if (hResult != NativeMethods.S_OK)
                        {
                            isEnabled = false;
                        }
                    }
                }
            }
            catch
            {
            }
            finally
            {
                if (hModule != IntPtr.Zero)
                {
                    UnsafeNativeMethods.FreeLibrary(hModule);
                }
            }
 
            return isEnabled;
        }
 
        /// <SecurityNote>
        ///     Critical: This method calls into ExtractAppDomainPermissionSetMinusSiteOfOrigin  this is used to make trust decision to 
        ///     copy paste content and is hence important to be tracked. Also it asserts to get to data
        /// </SecurityNote>
        [SecurityCritical]
        private static bool IsDataObjectFromLessPriviligedApplicationDomain(IDataObject dataObjectToApply)
        {
            bool retVal = false;
            object applicationTrust = null;
            // Extract the permission set in case of xaml cut and paste
            // extract permission set if it exists if not data came from full trust app and we do not care
            bool isApplicationTrustFormatPresent = false;
            isApplicationTrustFormatPresent = dataObjectToApply.GetDataPresent(DataFormats.ApplicationTrust, /*autoConvert:*/false);
            if (isApplicationTrustFormatPresent)
            {
                applicationTrust = dataObjectToApply.GetData(DataFormats.ApplicationTrust, /*autoConvert:*/false);
            }
 
            if (applicationTrust != null)
            {
                string applicationTrustText = null;
                // convert to string
                applicationTrustText = applicationTrust.ToString();
 
 
                // Convert string to permission set for getting permission set of source
                PermissionSet permissionSetSource;
                try
                {
                    SecurityElement securityElement = SecurityElement.FromString(applicationTrustText);
                    permissionSetSource = new System.Security.PermissionSet(PermissionState.None);
                    permissionSetSource.FromXml(securityElement);
                }
                catch(XmlSyntaxException)
                {
                    // This is the condition where we have Malformed XML in the clipboard for application trust
                    // here we will fail silently since we do not want to break arbitrary applications
                    // but since we cannot establish the validity of the application trust content we will fall back to
                    // whatever is more secure
                    return  true;
                }
 
                //extract permission set for the current appdomain which is target
                PermissionSet permissionSetDestination = SecurityHelper.ExtractAppDomainPermissionSetMinusSiteOfOrigin();
                //Compare permissions sets
                if (!permissionSetDestination.IsSubsetOf(permissionSetSource))
                {
                    retVal = true; // in case target is not subset of source revert to unicode or text
                }
            }
            return retVal;
        }
 
        /// <SecurityNote>
        /// Critical: This code extracts the DataObject from the clipboard
        /// which can be used to sniff clipboard
        /// </SecurityNote>
        [SecurityCritical]
        private static IDataObject GetDataObjectInternal()
        {
            IDataObject dataObject;
            IComDataObject oleDataObject;
 
            // Retry OLE operations several times as mitigation for clipboard locking issues in TS sessions.
            // See Dev10 bug 616223 and VSWhidbey bug 476911.
 
            int i = OleRetryCount;
 
            while (true)
            {
                oleDataObject = null;
                int hr = OleServicesContext.CurrentOleServicesContext.OleGetClipboard(ref oleDataObject);
 
                if (NativeMethods.Succeeded(hr))
                {
                    break;
                }
 
                if (--i == 0)
                {
                    Marshal.ThrowExceptionForHR(hr);
                }
 
                Thread.Sleep(OleRetryDelay);
            }
 
            if (oleDataObject is IDataObject)
            {
                dataObject = (IDataObject)oleDataObject;
            }
            else if (oleDataObject != null)
            {
                dataObject = new DataObject(oleDataObject);
            }
            else
            {
                dataObject = null;
            }
            // We make this check outside of the loop independant of whether the data is ole data object or IDataObject 
            // Although one is unable to create an OleDataObject in partial trust we still need to ensure that if he did
            // we strip the formats we care about by wrapping in ConstrainedDataObject
            if (dataObject != null)
            {
                // this is the case we are concerend about where content comes from partial trust into full trust
                // in the case where data contained is in one of the two formats: XAML or ApplicationTrust we return a wrapper
                // that blocks access to these
                if (IsDataObjectFromLessPriviligedApplicationDomain(dataObject) &&
                    (dataObject.GetDataPresent(DataFormats.Xaml, /*autoConvert:*/false) ||
                     dataObject.GetDataPresent(DataFormats.ApplicationTrust, /*autoConvert:*/false)))
                {
                    // in this case we set the data object to be a wrapper data object that blocks off
                    // xaml or application trust formats if they exist
                    dataObject = new ConstrainedDataObject(dataObject);
                }
            }
            return dataObject;
        }
 
        /// <summary>
        /// Query the specified data format from Clipboard.
        /// </summary>
        /// <SecurityNote>
        /// Critical - Accesses the clipboard.
        /// TreatAsSafe - We demand clipboard permission. 
 
 
 
        [SecurityCritical, SecurityTreatAsSafe]
        private static bool ContainsDataInternal(string format)
        {
            SecurityHelper.DemandAllClipboardPermission();
            bool isFormatAvailable = false;
 
            if (IsDataFormatAutoConvert(format))
            {
                string[] formats = DataObject.GetMappedFormats(format);
                for (int i = 0; i < formats.Length; i++)
                {
                    if (SafeNativeMethods.IsClipboardFormatAvailable(DataFormats.GetDataFormat(formats[i]).Id))
                    {
                        isFormatAvailable = true;
                        break;
                    }
                }
            }
            else
            {
                isFormatAvailable = SafeNativeMethods.IsClipboardFormatAvailable(DataFormats.GetDataFormat(format).Id);
            }
 
            return isFormatAvailable;
        }
 
        /// <summary>
        /// Get the specified format from Clipboard.
        /// </summary>
        private static object GetDataInternal(string format)
        {
            IDataObject dataObject;
 
            dataObject = Clipboard.GetDataObject();
 
            if (dataObject != null)
            {
                bool autoConvert;
 
                if (IsDataFormatAutoConvert(format))
                {
                    autoConvert = true;
                }
                else
                {
                    autoConvert = false;
                }
 
                return dataObject.GetData(format, autoConvert);
            }
            else
            {
                return null;
            }
        }
 
        /// <summary>
        /// Set the specified data into Clipboard.
        /// </summary>
        private static void SetDataInternal(string format, object data)
        {
            IDataObject dataObject;
            bool autoConvert;
 
            if (IsDataFormatAutoConvert(format))
            {
                autoConvert = true;
            }
            else
            {
                autoConvert = false;
            }
 
            dataObject = new DataObject();
            dataObject.SetData(format, data, autoConvert);
 
            Clipboard.SetDataObject(dataObject, /*copy*/true);
        }
 
        /// <summary>
        /// Check the auto convert for the specified data format.
        /// </summary>
        private static bool IsDataFormatAutoConvert(string format)
        {
            bool autoConvert;
 
            if (String.CompareOrdinal(format, DataFormats.FileDrop) == 0 ||
                String.CompareOrdinal(format, DataFormats.Bitmap) == 0)
            {
                autoConvert = true;
            }
            else
            {
                autoConvert = false;
            }
 
            return autoConvert;
        }
 
        #endregion Private Methods
 
        //------------------------------------------------------
        //
        //  Private Constants
        //
        //------------------------------------------------------
 
        #region Private Constants
 
        /// <summary>
        /// The number of times to retry OLE clipboard operations.
        /// </summary>
        /// <remarks>
        /// This is mitigation for clipboard locking issues in TS sessions. See Dev10 bug 616223 and VSWhidbey bug 476911.
        /// </remarks>
        private const int OleRetryCount = 10;
 
        /// <summary>
        /// The amount of time in milliseconds to sleep between retrying OLE clipboard operations.
        /// </summary>
        /// <remarks>
        /// This is mitigation for clipboard locking issues in TS sessions. See Dev10 bug 616223 and VSWhidbey bug 476911.
        /// </remarks>
        private const int OleRetryDelay = 100;
 
        /// <summary>
        /// The amount of time in milliseconds to sleep before flushing the clipboard after a set.
        /// </summary>
        /// <remarks>
        /// This is mitigation for clipboard listener issues. See Dev10 bug 835751.
        /// </remarks>
        private const int OleFlushDelay = 10;
 
        #endregion Private Constants
 
        private static int _isDeviceGuardEnabled = 0;
    }
 
    #endregion Clipboard class
}