clipboard.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / clipboard.cs / 1471291 / clipboard.cs

                            //---------------------------------------------------------------------------- 
//
// 
// Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 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

    /// 
    /// Provides methods to place data on and retrieve data from the system clipboard. 
    /// This class cannot be inherited.
    ///  
    public static class Clipboard 
    {
        //----------------------------------------------------- 
        //
        //  Public Methods
        //
        //----------------------------------------------------- 

        #region Public Methods 
 
        /// 
        /// Clear the system clipboard which the clipboard is emptied. 
        /// SetDataObject.
        /// 
        /// 
        /// Critical - access critical data (clipboard information) 
        /// PublicOk -  Clearing the clipboard is not inherently unsafe.
        ///  
        [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);
            } 
        }
 
        ///  
        /// Return true if Clipboard contains the audio data. Otherwise, return false.
        ///  
        public static bool ContainsAudio()
        {
            return ContainsDataInternal(DataFormats.WaveAudio);
        } 

        ///  
        /// Return true if Clipboard contains the specified data format. Otherwise, return false. 
        /// 
        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);
        } 

        ///  
        /// Return true if Clipboard contains the file drop list format. Otherwise, return false. 
        /// 
        public static bool ContainsFileDropList() 
        {
            return ContainsDataInternal(DataFormats.FileDrop);
        }
 
        /// 
        /// Return true if Clipboard contains the image format. Otherwise, return false. 
        ///  
        public static bool ContainsImage()
        { 
            return ContainsDataInternal(DataFormats.Bitmap);
        }

        ///  
        /// Return true if Clipboard contains the text data format which is unicode.
        /// Otherwise, return false. 
        ///  
        public static bool ContainsText()
        { 
            return ContainsDataInternal(DataFormats.UnicodeText);
        }

        ///  
        /// Return true if Clipboard contains the specified text data format which is unicode.
        /// Otherwise, return false. 
        ///  
        public static bool ContainsText(TextDataFormat format)
        { 
            if (!DataFormats.IsValidTextDataFormat(format))
            {
                throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat));
            } 

            return ContainsDataInternal(DataFormats.ConvertToDataFormats(format)); 
        } 

        ///  
        /// Get audio data as Stream from Clipboard.
        /// 
        public static Stream GetAudioStream()
        { 
            return GetDataInternal(DataFormats.WaveAudio) as Stream;
        } 
 
        /// 
        /// Get data for the specified data format from Clipboard. 
        /// 
        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);
        } 
 
        /// 
        /// Get the file drop list as StringCollection from Clipboard. 
        /// 
        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; 
        } 

        ///  
        /// Get the image from Clipboard.
        /// 
        public static BitmapSource GetImage()
        { 
            return GetDataInternal(DataFormats.Bitmap) as BitmapSource;
        } 
 
        /// 
        /// Get text from Clipboard. 
        /// 
        public static string GetText()
        {
            return GetText(TextDataFormat.UnicodeText); 
        }
 
        ///  
        /// Get text from Clipboard.
        ///  
        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;
        } 

        /// 
        /// Set the audio data to Clipboard.
        ///  
        public static void SetAudio(byte[] audioBytes)
        { 
            if (audioBytes == null) 
            {
                throw new ArgumentNullException("audioBytes"); 
            }

            SetAudio(new MemoryStream(audioBytes));
        } 

        ///  
        /// Set the audio data to Clipboard. 
        /// 
        public static void SetAudio(Stream audioStream) 
        {
            if (audioStream == null)
            {
                throw new ArgumentNullException("audioStream"); 
            }
 
            SetDataInternal(DataFormats.WaveAudio, audioStream); 
        }
 
        /// 
        /// Set the specified data to Clipboard.
        /// 
        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);
        } 

        ///  
        /// Set the file drop list to Clipboard. 
        /// 
        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);
        }
 
        /// 
        /// Set the image data to Clipboard. 
        ///  
        public static void SetImage(BitmapSource image)
        { 
            if (image == null)
            {
                throw new ArgumentNullException("image");
            } 

            SetDataInternal(DataFormats.Bitmap, image); 
        } 

        ///  
        /// Set the text data to Clipboard.
        /// 
        public static void SetText(string text)
        { 
            if (text == null)
            { 
                throw new ArgumentNullException("text"); 
            }
 
            SetText(text, TextDataFormat.UnicodeText);
        }

        ///  
        /// Set the text data to Clipboard.
        ///  
        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);
        }

        ///  
        /// Retrieves the data object that is currently on the system clipboard.
        ///  
        ///  
        ///     Callers must have UIPermission(UIPermissionClipboard.AllClipboard) to call this API.
        ///  
        /// 
        /// Critical - access critical data (clipboard information)
        /// PublicOk - demands appropriate permission (AllClipboard)
        ///  
        [SecurityCritical]
        public static IDataObject GetDataObject() 
        { 
            SecurityHelper.DemandAllClipboardPermission();
 
            return GetDataObjectInternal();
        }

        ///  
        /// Determines whether the data object previously placed on the clipboard
        /// by the SetDataObject is still on the clipboard. 
        ///  
        /// 
        /// Data object from the current containing clipboard which the caller 
        /// previously placed on the clipboard.
        /// 
        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; 
        }

        /// 
        /// Places nonpersistent data on the system clipboard. 
        /// 
        ///  
        /// The specific data to be on clipboard. 
        /// 
        ///  
        ///     Callers must have UIPermission(UIPermissionClipboard.AllClipboard) to call this API.
        /// 
        /// 
        /// Critical - access critical data (clipboard information) 
        /// PublicOk - demands appropriate permission (AllClipboard)
        ///  
        [SecurityCritical] 
        public static void SetDataObject(object data)
        { 
            SecurityHelper.DemandAllClipboardPermission();

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

        /// 
        /// Places data on the system Clipboard and uses copy to specify whether the data
        /// should remain on the Clipboard after the application exits. 
        /// 
        ///  
        /// The specific data to be on clipboard. 
        /// 
        ///  
        /// Specify whether the data should remain on the clipboard after the application exits.
        /// 
        /// 
        ///     Callers must have UIPermission(UIPermissionClipboard.AllClipboard) to call this API. 
        /// 
        ///  
        /// Critical - calls critical code (set clipboard), and potentially deals 
        ///            with unmanaged pointers
        /// PublicOk - Demands All Clipboard permissions 
        /// 
        [SecurityCritical]
        public static void SetDataObject(object data, bool copy)
        { 
            SecurityHelper.DemandAllClipboardPermission();
            CriticalSetDataObject(data,copy); 
        } 

        #endregion Public Methods 

        #region Internal Methods

        //------------------------------------------------------ 
        //
        //  Internal Methods 
        // 
        //-----------------------------------------------------
        ///  
        /// Places data on the system Clipboard and uses copy to specify whether the data
        /// should remain on the Clipboard after the application exits.
        /// 
        ///  
        /// The specific data to be on clipboard.
        ///  
        ///  
        /// Specify whether the data should remain on the clipboard after the application exits.
        ///  
        /// 
        /// Critical - calls critical code (set clipboard), and potentially deals
        ///            with unmanaged pointers
        ///  
        [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)
            { 
                i = OleRetryCount;

                while (true)
                { 
                    int hr = OleServicesContext.CurrentOleServicesContext.OleFlushClipboard();
 
                    if (NativeMethods.Succeeded(hr)) 
                    {
                        break; 
                    }

                    if (--i == 0)
                    { 
                        Marshal.ThrowExceptionForHR(hr);
                    } 
 
                    Thread.Sleep(OleRetryDelay);
                } 
            }
        }

        ///  
        /// Critical - access critical data (clipboard information)
        /// TreatAsSafe: Returning a bool indicating whether there is data on the clipboard is ok 
        ///  
        [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 
 
        /// 
        ///     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
        /// 
        [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; 
        }
 
        ///  
        /// Critical: This code extracts the DataObject from the clipboard
        /// which can be used to sniff clipboard 
        /// 
        [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; 
        } 

        ///  
        /// Query the specified data format from Clipboard.
        /// 
        /// 
        /// 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;
        } 
 
        /// 
        /// Get the specified format from Clipboard. 
        /// 
        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; 
            }
        } 

        /// 
        /// Set the specified data into Clipboard.
        ///  
        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); 
        }
 
        ///  
        /// Check the auto convert for the specified data format.
        ///  
        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
 
        /// 
        /// The number of times to retry OLE clipboard operations.
        /// 
        ///  
        /// This is mitigation for clipboard locking issues in TS sessions. See Dev10 bug 616223 and VSWhidbey bug 476911.
        ///  
        private const int OleRetryCount = 10; 

        ///  
        /// The amount of time in milliseconds to sleep between retrying OLE clipboard operations.
        /// 
        /// 
        /// This is mitigation for clipboard locking issues in TS sessions. See Dev10 bug 616223 and VSWhidbey bug 476911. 
        /// 
        private const int OleRetryDelay = 100; 
 
        #endregion Private Constants
    } 

    #endregion Clipboard class
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
// Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 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

    /// 
    /// Provides methods to place data on and retrieve data from the system clipboard. 
    /// This class cannot be inherited.
    ///  
    public static class Clipboard 
    {
        //----------------------------------------------------- 
        //
        //  Public Methods
        //
        //----------------------------------------------------- 

        #region Public Methods 
 
        /// 
        /// Clear the system clipboard which the clipboard is emptied. 
        /// SetDataObject.
        /// 
        /// 
        /// Critical - access critical data (clipboard information) 
        /// PublicOk -  Clearing the clipboard is not inherently unsafe.
        ///  
        [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);
            } 
        }
 
        ///  
        /// Return true if Clipboard contains the audio data. Otherwise, return false.
        ///  
        public static bool ContainsAudio()
        {
            return ContainsDataInternal(DataFormats.WaveAudio);
        } 

        ///  
        /// Return true if Clipboard contains the specified data format. Otherwise, return false. 
        /// 
        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);
        } 

        ///  
        /// Return true if Clipboard contains the file drop list format. Otherwise, return false. 
        /// 
        public static bool ContainsFileDropList() 
        {
            return ContainsDataInternal(DataFormats.FileDrop);
        }
 
        /// 
        /// Return true if Clipboard contains the image format. Otherwise, return false. 
        ///  
        public static bool ContainsImage()
        { 
            return ContainsDataInternal(DataFormats.Bitmap);
        }

        ///  
        /// Return true if Clipboard contains the text data format which is unicode.
        /// Otherwise, return false. 
        ///  
        public static bool ContainsText()
        { 
            return ContainsDataInternal(DataFormats.UnicodeText);
        }

        ///  
        /// Return true if Clipboard contains the specified text data format which is unicode.
        /// Otherwise, return false. 
        ///  
        public static bool ContainsText(TextDataFormat format)
        { 
            if (!DataFormats.IsValidTextDataFormat(format))
            {
                throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat));
            } 

            return ContainsDataInternal(DataFormats.ConvertToDataFormats(format)); 
        } 

        ///  
        /// Get audio data as Stream from Clipboard.
        /// 
        public static Stream GetAudioStream()
        { 
            return GetDataInternal(DataFormats.WaveAudio) as Stream;
        } 
 
        /// 
        /// Get data for the specified data format from Clipboard. 
        /// 
        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);
        } 
 
        /// 
        /// Get the file drop list as StringCollection from Clipboard. 
        /// 
        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; 
        } 

        ///  
        /// Get the image from Clipboard.
        /// 
        public static BitmapSource GetImage()
        { 
            return GetDataInternal(DataFormats.Bitmap) as BitmapSource;
        } 
 
        /// 
        /// Get text from Clipboard. 
        /// 
        public static string GetText()
        {
            return GetText(TextDataFormat.UnicodeText); 
        }
 
        ///  
        /// Get text from Clipboard.
        ///  
        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;
        } 

        /// 
        /// Set the audio data to Clipboard.
        ///  
        public static void SetAudio(byte[] audioBytes)
        { 
            if (audioBytes == null) 
            {
                throw new ArgumentNullException("audioBytes"); 
            }

            SetAudio(new MemoryStream(audioBytes));
        } 

        ///  
        /// Set the audio data to Clipboard. 
        /// 
        public static void SetAudio(Stream audioStream) 
        {
            if (audioStream == null)
            {
                throw new ArgumentNullException("audioStream"); 
            }
 
            SetDataInternal(DataFormats.WaveAudio, audioStream); 
        }
 
        /// 
        /// Set the specified data to Clipboard.
        /// 
        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);
        } 

        ///  
        /// Set the file drop list to Clipboard. 
        /// 
        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);
        }
 
        /// 
        /// Set the image data to Clipboard. 
        ///  
        public static void SetImage(BitmapSource image)
        { 
            if (image == null)
            {
                throw new ArgumentNullException("image");
            } 

            SetDataInternal(DataFormats.Bitmap, image); 
        } 

        ///  
        /// Set the text data to Clipboard.
        /// 
        public static void SetText(string text)
        { 
            if (text == null)
            { 
                throw new ArgumentNullException("text"); 
            }
 
            SetText(text, TextDataFormat.UnicodeText);
        }

        ///  
        /// Set the text data to Clipboard.
        ///  
        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);
        }

        ///  
        /// Retrieves the data object that is currently on the system clipboard.
        ///  
        ///  
        ///     Callers must have UIPermission(UIPermissionClipboard.AllClipboard) to call this API.
        ///  
        /// 
        /// Critical - access critical data (clipboard information)
        /// PublicOk - demands appropriate permission (AllClipboard)
        ///  
        [SecurityCritical]
        public static IDataObject GetDataObject() 
        { 
            SecurityHelper.DemandAllClipboardPermission();
 
            return GetDataObjectInternal();
        }

        ///  
        /// Determines whether the data object previously placed on the clipboard
        /// by the SetDataObject is still on the clipboard. 
        ///  
        /// 
        /// Data object from the current containing clipboard which the caller 
        /// previously placed on the clipboard.
        /// 
        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; 
        }

        /// 
        /// Places nonpersistent data on the system clipboard. 
        /// 
        ///  
        /// The specific data to be on clipboard. 
        /// 
        ///  
        ///     Callers must have UIPermission(UIPermissionClipboard.AllClipboard) to call this API.
        /// 
        /// 
        /// Critical - access critical data (clipboard information) 
        /// PublicOk - demands appropriate permission (AllClipboard)
        ///  
        [SecurityCritical] 
        public static void SetDataObject(object data)
        { 
            SecurityHelper.DemandAllClipboardPermission();

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

        /// 
        /// Places data on the system Clipboard and uses copy to specify whether the data
        /// should remain on the Clipboard after the application exits. 
        /// 
        ///  
        /// The specific data to be on clipboard. 
        /// 
        ///  
        /// Specify whether the data should remain on the clipboard after the application exits.
        /// 
        /// 
        ///     Callers must have UIPermission(UIPermissionClipboard.AllClipboard) to call this API. 
        /// 
        ///  
        /// Critical - calls critical code (set clipboard), and potentially deals 
        ///            with unmanaged pointers
        /// PublicOk - Demands All Clipboard permissions 
        /// 
        [SecurityCritical]
        public static void SetDataObject(object data, bool copy)
        { 
            SecurityHelper.DemandAllClipboardPermission();
            CriticalSetDataObject(data,copy); 
        } 

        #endregion Public Methods 

        #region Internal Methods

        //------------------------------------------------------ 
        //
        //  Internal Methods 
        // 
        //-----------------------------------------------------
        ///  
        /// Places data on the system Clipboard and uses copy to specify whether the data
        /// should remain on the Clipboard after the application exits.
        /// 
        ///  
        /// The specific data to be on clipboard.
        ///  
        ///  
        /// Specify whether the data should remain on the clipboard after the application exits.
        ///  
        /// 
        /// Critical - calls critical code (set clipboard), and potentially deals
        ///            with unmanaged pointers
        ///  
        [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)
            { 
                i = OleRetryCount;

                while (true)
                { 
                    int hr = OleServicesContext.CurrentOleServicesContext.OleFlushClipboard();
 
                    if (NativeMethods.Succeeded(hr)) 
                    {
                        break; 
                    }

                    if (--i == 0)
                    { 
                        Marshal.ThrowExceptionForHR(hr);
                    } 
 
                    Thread.Sleep(OleRetryDelay);
                } 
            }
        }

        ///  
        /// Critical - access critical data (clipboard information)
        /// TreatAsSafe: Returning a bool indicating whether there is data on the clipboard is ok 
        ///  
        [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 
 
        /// 
        ///     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
        /// 
        [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; 
        }
 
        ///  
        /// Critical: This code extracts the DataObject from the clipboard
        /// which can be used to sniff clipboard 
        /// 
        [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; 
        } 

        ///  
        /// Query the specified data format from Clipboard.
        /// 
        /// 
        /// 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;
        } 
 
        /// 
        /// Get the specified format from Clipboard. 
        /// 
        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; 
            }
        } 

        /// 
        /// Set the specified data into Clipboard.
        ///  
        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); 
        }
 
        ///  
        /// Check the auto convert for the specified data format.
        ///  
        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
 
        /// 
        /// The number of times to retry OLE clipboard operations.
        /// 
        ///  
        /// This is mitigation for clipboard locking issues in TS sessions. See Dev10 bug 616223 and VSWhidbey bug 476911.
        ///  
        private const int OleRetryCount = 10; 

        ///  
        /// The amount of time in milliseconds to sleep between retrying OLE clipboard operations.
        /// 
        /// 
        /// This is mitigation for clipboard locking issues in TS sessions. See Dev10 bug 616223 and VSWhidbey bug 476911. 
        /// 
        private const int OleRetryDelay = 100; 
 
        #endregion Private Constants
    } 

    #endregion Clipboard 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