Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / WinForms / Managed / System / WinForms / DataObject.cs / 1 / DataObject.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ namespace System.Windows.Forms { using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization; using System.Text; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Collections.Specialized; using System.Diagnostics; using System; using Microsoft.Win32; using System.Collections; using System.ComponentModel; using System.IO; using System.Drawing; using System.Windows.Forms; using System.Security; using System.Security.Permissions; using System.Reflection; using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject; using System.Globalization; ////// /// [ ClassInterface(ClassInterfaceType.None) ] public class DataObject : IDataObject, IComDataObject { private static readonly string CF_DEPRECATED_FILENAME = "FileName"; private static readonly string CF_DEPRECATED_FILENAMEW = "FileNameW"; 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 = 0x00040130; private static readonly TYMED[] ALLOWED_TYMEDS = new TYMED [] { TYMED.TYMED_HGLOBAL, TYMED.TYMED_ISTREAM, TYMED.TYMED_ENHMF, TYMED.TYMED_MFPICT, TYMED.TYMED_GDI}; private IDataObject innerData = null; // 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. // private static readonly byte[] serializedObjectID = new Guid("FD9EA796-3B13-4370-A679-56106BB288FB").ToByteArray(); ///Implements a basic data transfer mechanism. ////// /// internal DataObject(IDataObject data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Constructed DataObject based on IDataObject"); innerData = data; Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); } ///Initializes a new instance of the ///class, with the specified . /// /// internal DataObject(IComDataObject data) { if (data is DataObject) { innerData = data as IDataObject; } else { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Constructed DataObject based on IComDataObject"); innerData = new OleConverter(data); } Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); } ///Initializes a new instance of the ///class, with the specified . /// /// public DataObject() { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Constructed DataObject standalone"); innerData = new DataStore(); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); } ////// Initializes a new instance of the ////// class, which can store arbitrary data. /// /// /// public DataObject(object data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Constructed DataObject base on Object: " + data.ToString()); if (data is IDataObject && !Marshal.IsComObject(data)) { innerData = (IDataObject)data; } else if (data is IComDataObject) { innerData = new OleConverter((IComDataObject)data); } else { innerData = new DataStore(); SetData(data); } Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); } ///Initializes a new instance of the ///class, containing the specified data. /// /// public DataObject(string format, object data) : this() { SetData(format, data); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); } private IntPtr GetCompatibleBitmap(Bitmap bm) { // 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. // IntPtr hBitmap = bm.GetHbitmap(); // Get the screen DC. // IntPtr hDC = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); // Create a compatible DC to render the source bitmap. // IntPtr dcSrc = UnsafeNativeMethods.CreateCompatibleDC(new HandleRef(null, hDC)); IntPtr srcOld = SafeNativeMethods.SelectObject(new HandleRef(null, dcSrc), new HandleRef(bm, hBitmap)); // Create a compatible DC and a new compatible bitmap. // IntPtr dcDest = UnsafeNativeMethods.CreateCompatibleDC(new HandleRef(null, hDC)); IntPtr hBitmapNew = SafeNativeMethods.CreateCompatibleBitmap(new HandleRef(null, hDC), bm.Size.Width, bm.Size.Height); // Select the new bitmap into a compatible DC and render the blt the original bitmap. // IntPtr destOld = SafeNativeMethods.SelectObject(new HandleRef(null, dcDest), new HandleRef(null, hBitmapNew)); SafeNativeMethods.BitBlt(new HandleRef(null, dcDest), 0, 0, bm.Size.Width, bm.Size.Height, new HandleRef(null, dcSrc), 0, 0, 0x00CC0020); // Clear the source and destination compatible DCs. // SafeNativeMethods.SelectObject(new HandleRef(null, dcSrc), new HandleRef(null, srcOld)); SafeNativeMethods.SelectObject(new HandleRef(null, dcDest), new HandleRef(null, destOld)); UnsafeNativeMethods.DeleteCompatibleDC(new HandleRef(null, dcSrc)); UnsafeNativeMethods.DeleteCompatibleDC(new HandleRef(null, dcDest)); UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, hDC)); SafeNativeMethods.DeleteObject(new HandleRef(bm, hBitmap)); return hBitmapNew; } ///Initializes a new instance of the ///class, containing the specified data and its /// associated format. /// /// public virtual object GetData(string format, bool autoConvert) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Request data: " + format + ", " + autoConvert.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); return innerData.GetData(format, autoConvert); } ///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 virtual object GetData(string format) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Request data: " + format); return GetData(format, true); } ///Retrieves the data associated with the specified data /// format. ////// /// public virtual object GetData(Type format) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Request data: " + format.FullName); Debug.Assert(format != null, "Must specify a format type"); if (format == null) { return null; } return GetData(format.FullName); } ///Retrieves the data associated with the specified class /// type format. ////// /// public virtual bool GetDataPresent(Type format) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check data: " + format.FullName); Debug.Assert(format != null, "Must specify a format type"); if (format == null) { return false; } bool b = GetDataPresent(format.FullName); Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, " ret: " + b.ToString()); return b; } ///Determines whether data stored in this instance is /// associated with, or can be converted to, the specified /// format. ////// /// public virtual bool GetDataPresent(string format, bool autoConvert) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check data: " + format + ", " + autoConvert.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); bool b = innerData.GetDataPresent(format, autoConvert); Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, " ret: " + b.ToString()); return b; } ///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 virtual bool GetDataPresent(string format) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check data: " + format); bool b = GetDataPresent(format, true); Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, " ret: " + b.ToString()); return b; } ///Determines whether data stored in this instance is /// associated with, or can be converted to, the specified /// format. ////// /// public virtual string[] GetFormats(bool autoConvert) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check formats: " + autoConvert.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); return innerData.GetFormats(autoConvert); } ///Gets a list of all formats that data stored in this /// instance is associated with or can be converted to, using an automatic /// conversion parameter ///to /// determine whether to retrieve all formats that the data can be converted to or /// only native data formats. /// /// public virtual string[] GetFormats() { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check formats:"); return GetFormats(true); } // <-- WHIDBEY ADDITIONS ///Gets a list of all formats that data stored in this instance is associated /// with or can be converted to. ////// /// public virtual bool ContainsAudio() { return GetDataPresent(DataFormats.WaveAudio, false); } ///[To be supplied.] ////// /// public virtual bool ContainsFileDropList() { return GetDataPresent(DataFormats.FileDrop, true); } ///[To be supplied.] ////// /// public virtual bool ContainsImage() { return GetDataPresent(DataFormats.Bitmap, true); } ///[To be supplied.] ////// /// public virtual bool ContainsText() { return ContainsText(TextDataFormat.UnicodeText); } ///[To be supplied.] ////// /// public virtual bool ContainsText(TextDataFormat format) { //valid values are 0x0 to 0x4 if (!ClientUtils.IsEnumValid(format, (int)format, (int)TextDataFormat.Text, (int)TextDataFormat.CommaSeparatedValue)){ throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat)); } return GetDataPresent(ConvertToDataFormats(format), false); } ///[To be supplied.] ////// /// public virtual Stream GetAudioStream() { return GetData(DataFormats.WaveAudio, false) as Stream; } ///[To be supplied.] ////// /// public virtual StringCollection GetFileDropList() { StringCollection retVal = new StringCollection(); string[] strings = GetData(DataFormats.FileDrop, true) as string[]; if (strings != null) { retVal.AddRange(strings); } return retVal; } ///[To be supplied.] ////// /// public virtual Image GetImage() { return GetData(DataFormats.Bitmap, true) as Image; } ///[To be supplied.] ////// /// public virtual string GetText() { return GetText(TextDataFormat.UnicodeText); } ///[To be supplied.] ////// /// public virtual string GetText(TextDataFormat format) { //valid values are 0x0 to 0x4 if (!ClientUtils.IsEnumValid(format, (int)format, (int)TextDataFormat.Text, (int)TextDataFormat.CommaSeparatedValue)){ throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat)); } string text = GetData(ConvertToDataFormats(format), false) as string; if (text != null) { return text; } return String.Empty; } ///[To be supplied.] ////// /// public virtual void SetAudio(byte[] audioBytes) { if (audioBytes == null) { throw new ArgumentNullException("audioBytes"); } SetAudio(new MemoryStream(audioBytes)); } ///[To be supplied.] ////// /// public virtual void SetAudio(Stream audioStream) { if (audioStream == null) { throw new ArgumentNullException("audioStream"); } SetData(DataFormats.WaveAudio, false, audioStream); } ///[To be supplied.] ////// /// public virtual void SetFileDropList(StringCollection filePaths) { if (filePaths == null) { throw new ArgumentNullException("filePaths"); } string[] strings = new string[filePaths.Count]; filePaths.CopyTo(strings, 0); SetData(DataFormats.FileDrop, true, strings); } ///[To be supplied.] ////// /// public virtual void SetImage(Image image) { if (image == null) { throw new ArgumentNullException("image"); } SetData(DataFormats.Bitmap, true, image); } ///[To be supplied.] ////// /// public virtual void SetText(string textData) { SetText(textData, TextDataFormat.UnicodeText); } ///[To be supplied.] ////// /// public virtual void SetText(string textData, TextDataFormat format) { if (String.IsNullOrEmpty(textData)) { throw new ArgumentNullException("textData"); } //valid values are 0x0 to 0x4 if (!ClientUtils.IsEnumValid(format, (int)format, (int)TextDataFormat.Text, (int)TextDataFormat.CommaSeparatedValue)) { throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat)); } SetData(ConvertToDataFormats(format), false, textData); } private static string ConvertToDataFormats(TextDataFormat format) { switch (format) { case TextDataFormat.UnicodeText: return DataFormats.UnicodeText; case TextDataFormat.Rtf: return DataFormats.Rtf; case TextDataFormat.Html: return DataFormats.Html; case TextDataFormat.CommaSeparatedValue: return DataFormats.CommaSeparatedValue; } return DataFormats.UnicodeText; } // END - WHIDBEY ADDITIONS --> ///[To be supplied.] ////// /// Retrieves a list of distinct strings from the array. /// private static string[] GetDistinctStrings(string[] formats) { ArrayList distinct = new ArrayList(); for (int i=0; i/// /// Returns all the "synonyms" for the specified format. /// private static string[] GetMappedFormats(string format) { if (format == null) { return null; } if (format.Equals(DataFormats.Text) || format.Equals(DataFormats.UnicodeText) || format.Equals(DataFormats.StringFormat)) { return new string[] { DataFormats.StringFormat, DataFormats.UnicodeText, DataFormats.Text, }; } if (format.Equals(DataFormats.FileDrop) || format.Equals(CF_DEPRECATED_FILENAME) || format.Equals(CF_DEPRECATED_FILENAMEW)) { return new string[] { DataFormats.FileDrop, CF_DEPRECATED_FILENAMEW, CF_DEPRECATED_FILENAME, }; } if (format.Equals(DataFormats.Bitmap) || format.Equals((typeof(Bitmap)).FullName)) { return new string[] { (typeof(Bitmap)).FullName, DataFormats.Bitmap, }; } /*gpr if (format.Equals(DataFormats.EnhancedMetafile) || format.Equals((typeof(Metafile)).FullName)) { return new string[] {DataFormats.EnhancedMetafile, (typeof(Metafile)).FullName}; } */ return new String[] {format}; } /* ////// /// Returns all distinct "synonyms" for the each of the formats. /// private static string[] GetMappedFormats(string[] formats) { ArrayList allChoices = new ArrayList(); for (int i=0; i/// /// Returns true if the tymed is useable. /// ///private bool GetTymedUseable(TYMED tymed) { for (int i=0; i /// /// Populates Ole datastructes from a WinForms dataObject. This is the core /// of WinForms to OLE conversion. /// ///private void GetDataIntoOleStructs(ref FORMATETC formatetc, ref STGMEDIUM medium) { if (GetTymedUseable(formatetc.tymed) && GetTymedUseable(medium.tymed)) { string format = DataFormats.GetFormat(formatetc.cfFormat).Name; if (GetDataPresent(format)) { Object data = GetData(format); if ((formatetc.tymed & TYMED.TYMED_HGLOBAL) != 0) { int hr = SaveDataToHandle(data, format, ref medium); if (NativeMethods.Failed(hr)) { Marshal.ThrowExceptionForHR(hr); } } else if ((formatetc.tymed & TYMED.TYMED_GDI) != 0) { if (format.Equals(DataFormats.Bitmap) && data is Bitmap) { // save bitmap // Bitmap bm = (Bitmap)data; if (bm != null) { medium.unionmember = GetCompatibleBitmap(bm); // gpr: Does this get properly disposed? } } } /* gpr else if ((formatetc.tymed & TYMED.TYMED_ENHMF) != 0) { if (format.Equals(DataFormats.EnhancedMetafile) && data is Metafile) { // save metafile Metafile mf = (Metafile)data; if (mf != null) { medium.unionmember = mf.Handle; } } } */ else { Marshal.ThrowExceptionForHR (DV_E_TYMED); } } else { Marshal.ThrowExceptionForHR (DV_E_FORMATETC); } } else { Marshal.ThrowExceptionForHR (DV_E_TYMED); } } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] int IComDataObject.DAdvise(ref FORMATETC pFormatetc, ADVF advf, IAdviseSink pAdvSink, out int pdwConnection) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "DAdvise"); 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. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] void IComDataObject.DUnadvise(int dwConnection) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "DUnadvise"); if (innerData is OleConverter) { ((OleConverter)innerData).OleDataObject.DUnadvise(dwConnection); return; } Marshal.ThrowExceptionForHR(NativeMethods.E_NOTIMPL); } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] int IComDataObject.EnumDAdvise(out IEnumSTATDATA enumAdvise) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "EnumDAdvise"); 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. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] IEnumFORMATETC IComDataObject.EnumFormatEtc(DATADIR dwDirection) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "EnumFormatEtc: " + dwDirection.ToString()); if (innerData is OleConverter) { return ((OleConverter)innerData).OleDataObject.EnumFormatEtc(dwDirection); } if (dwDirection == DATADIR.DATADIR_GET) { return new FormatEnumerator(this); } else { throw new ExternalException(SR.GetString(SR.ExternalException), NativeMethods.E_NOTIMPL); } } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] int IComDataObject.GetCanonicalFormatEtc(ref FORMATETC pformatetcIn, out FORMATETC pformatetcOut) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "GetCanonicalFormatEtc"); if (innerData is OleConverter) { return ((OleConverter)innerData).OleDataObject.GetCanonicalFormatEtc(ref pformatetcIn, out pformatetcOut); } pformatetcOut = new FORMATETC(); return (DATA_S_SAMEFORMATETC); } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] void IComDataObject.GetData(ref FORMATETC formatetc, out STGMEDIUM medium) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "GetData"); if (innerData is OleConverter) { ((OleConverter)innerData).OleDataObject.GetData(ref formatetc, out medium); return; } medium = new STGMEDIUM(); if (GetTymedUseable(formatetc.tymed)) { if ((formatetc.tymed & TYMED.TYMED_HGLOBAL) != 0) { medium.tymed = TYMED.TYMED_HGLOBAL; medium.unionmember = UnsafeNativeMethods.GlobalAlloc(NativeMethods.GMEM_MOVEABLE | NativeMethods.GMEM_DDESHARE | NativeMethods.GMEM_ZEROINIT, 1); if (medium.unionmember == IntPtr.Zero) { throw new OutOfMemoryException(); } try { ((IComDataObject)this).GetDataHere(ref formatetc, ref medium); } catch { UnsafeNativeMethods.GlobalFree(new HandleRef(medium, medium.unionmember)); medium.unionmember = IntPtr.Zero; throw; } } else { medium.tymed = formatetc.tymed; ((IComDataObject)this).GetDataHere(ref formatetc, ref medium); } } else { Marshal.ThrowExceptionForHR(DV_E_TYMED); } } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] void IComDataObject.GetDataHere(ref FORMATETC formatetc, ref STGMEDIUM medium) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "GetDataHere"); if (innerData is OleConverter) { ((OleConverter)innerData).OleDataObject.GetDataHere(ref formatetc, ref medium); } else { GetDataIntoOleStructs(ref formatetc, ref medium); } } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] int IComDataObject.QueryGetData(ref FORMATETC formatetc) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "QueryGetData"); 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) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "QueryGetData::returning S_FALSE because cfFormat == 0"); return NativeMethods.S_FALSE; } else { if (!GetDataPresent(DataFormats.GetFormat(formatetc.cfFormat).Name)) { return (DV_E_FORMATETC); } } } else { return (DV_E_TYMED); } } else { return (DV_E_DVASPECT); } #if DEBUG int format = formatetc.cfFormat; Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "QueryGetData::cfFormat " + format.ToString(CultureInfo.InvariantCulture) + " found"); #endif return NativeMethods.S_OK; } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] void IComDataObject.SetData(ref FORMATETC pFormatetcIn, ref STGMEDIUM pmedium, bool fRelease) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "SetData"); if (innerData is OleConverter) { ((OleConverter)innerData).OleDataObject.SetData(ref pFormatetcIn, ref pmedium, fRelease); return; } // throw new NotImplementedException(); } private int SaveDataToHandle(object data, string format, ref STGMEDIUM medium) { int hr = NativeMethods.E_FAIL; if (data is Stream) { hr = SaveStreamToHandle(ref medium.unionmember, (Stream)data); } else if (format.Equals(DataFormats.Text) || format.Equals(DataFormats.Rtf) || format.Equals(DataFormats.Html) || format.Equals(DataFormats.OemText)) { hr = SaveStringToHandle(medium.unionmember, data.ToString(), false); } else if (format.Equals(DataFormats.UnicodeText)) { hr = SaveStringToHandle(medium.unionmember, data.ToString(), true); } else if (format.Equals(DataFormats.FileDrop)) { hr = SaveFileListToHandle(medium.unionmember, (string[])data); } else if (format.Equals(CF_DEPRECATED_FILENAME)) { string[] filelist = (string[])data; hr = SaveStringToHandle(medium.unionmember, filelist[0], false); } else if (format.Equals(CF_DEPRECATED_FILENAMEW)) { string[] filelist = (string[])data; hr = SaveStringToHandle(medium.unionmember, filelist[0], true); } else if (format.Equals(DataFormats.Dib) && data is Image) { // 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; // SaveImageToHandle(ref medium.unionmember, (Image)data); } else if (format.Equals(DataFormats.Serializable) || data is ISerializable || (data != null && data.GetType().IsSerializable)) { hr = SaveObjectToHandle(ref medium.unionmember, data); } return hr; } /* private int SaveImageToHandle(ref IntPtr handle, Image data) { MemoryStream stream = new MemoryStream(); data.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); return SaveStreamToHandle(ref handle, stream); } */ private int SaveObjectToHandle(ref IntPtr handle, Object data) { Stream stream = new MemoryStream(); BinaryWriter bw = new BinaryWriter(stream); bw.Write(serializedObjectID); SaveObjectToHandleSerializer(stream, data); return SaveStreamToHandle(ref handle, stream); } [ SecurityPermissionAttribute(SecurityAction.Assert, Flags=SecurityPermissionFlag.SerializationFormatter) ] private static void SaveObjectToHandleSerializer(Stream stream, Object data) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, data); } /// /// /// Saves stream out to handle. /// ///private int SaveStreamToHandle(ref IntPtr handle, Stream stream) { int size = (int)stream.Length; handle = UnsafeNativeMethods.GlobalAlloc(NativeMethods.GMEM_MOVEABLE | NativeMethods.GMEM_DDESHARE, size); if (handle == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(null, handle)); if (ptr == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } try { byte[] bytes = new byte[size]; stream.Position = 0; stream.Read(bytes, 0, size); Marshal.Copy(bytes, 0, ptr, size); } finally { UnsafeNativeMethods.GlobalUnlock(new HandleRef(null, handle)); } return NativeMethods.S_OK; } /// /// /// Saves a list of files out to the handle in HDROP format. /// ///private int SaveFileListToHandle(IntPtr handle, string[] files) { if (files == null) { return NativeMethods.S_OK; } else if (files.Length < 1) { return NativeMethods.S_OK; } if (handle == IntPtr.Zero) { return (NativeMethods.E_INVALIDARG); } bool unicode = (Marshal.SystemDefaultCharSize != 1); IntPtr currentPtr = IntPtr.Zero; int baseStructSize = 4 + 8 + 4 + 4; int sizeInBytes = baseStructSize; // First determine the size of the array // if (unicode) { for (int i=0; i /// /// Save string to handle. If unicode is set to true /// then the string is saved as Unicode, else it is saves as DBCS. /// ///private int SaveStringToHandle(IntPtr handle, string str, bool unicode) { if (handle == IntPtr.Zero) { return (NativeMethods.E_INVALIDARG); } IntPtr newHandle = IntPtr.Zero; if (unicode) { int byteSize = (str.Length*2 + 2); newHandle = UnsafeNativeMethods.GlobalReAlloc(new HandleRef(null, handle), byteSize, NativeMethods.GMEM_MOVEABLE | NativeMethods.GMEM_DDESHARE | NativeMethods.GMEM_ZEROINIT); if (newHandle == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(null, newHandle)); if (ptr == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } // NOTE: DllLib.copy(char[]...) converts to ANSI on Windows 95... char[] chars = str.ToCharArray(0, str.Length); UnsafeNativeMethods.CopyMemoryW(ptr, chars, chars.Length*2); //NativeMethods.CopyMemoryW(ptr, string, string.Length()*2); } else { int pinvokeSize = UnsafeNativeMethods.WideCharToMultiByte(0 /*CP_ACP*/, 0, str, str.Length, null, 0, IntPtr.Zero, IntPtr.Zero); byte[] strBytes = new byte[pinvokeSize]; UnsafeNativeMethods.WideCharToMultiByte(0 /*CP_ACP*/, 0, str, str.Length, strBytes, strBytes.Length, IntPtr.Zero, IntPtr.Zero); newHandle = UnsafeNativeMethods.GlobalReAlloc(new HandleRef(null, handle), pinvokeSize + 1, NativeMethods.GMEM_MOVEABLE | NativeMethods.GMEM_DDESHARE | NativeMethods.GMEM_ZEROINIT); if (newHandle == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(null, newHandle)); if (ptr == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } UnsafeNativeMethods.CopyMemory(ptr, strBytes, pinvokeSize); Marshal.Copy(new byte[] {0}, 0, (IntPtr)((long)ptr+pinvokeSize), 1); } if (newHandle != IntPtr.Zero) { UnsafeNativeMethods.GlobalUnlock(new HandleRef(null, newHandle)); } return NativeMethods.S_OK; } /// /// /// public virtual void SetData(string format, bool autoConvert, Object data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Set data: " + format + ", " + autoConvert.ToString() + ", " + data.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); innerData.SetData(format, autoConvert, 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. ////// /// public virtual void SetData(string format, object data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Set data: " + format + ", " + data.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); innerData.SetData(format, data); } ///Stores the specified data and its associated format in this /// instance. ////// /// public virtual void SetData(Type format, object data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Set data: " + format.FullName + ", " + data.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); innerData.SetData(format, data); } ///Stores the specified data and /// its /// associated class type in this instance. ////// /// public virtual void SetData(object data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Set data: " + data.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); innerData.SetData(data); } ///Stores the specified data in /// this instance, using the class of the data for the format. ////// /// Part of IComDataObject, used to interop with OLE. /// ///private class FormatEnumerator : IEnumFORMATETC { internal IDataObject parent = null; internal ArrayList formats = new ArrayList(); internal int current = 0; public FormatEnumerator(IDataObject parent) : this(parent, parent.GetFormats()) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "FormatEnumerator: Constructed: " + parent.ToString()); } public FormatEnumerator(IDataObject parent, FORMATETC[] formats) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "FormatEnumerator: Constructed: " + parent.ToString() + ", FORMATETC[]" + formats.Length.ToString(CultureInfo.InvariantCulture)); this.formats.Clear(); this.parent = parent; current = 0; if (formats != null) { for (int i=0; i 0) { FORMATETC current = (FORMATETC)formats[this.current]; rgelt[0].cfFormat = current.cfFormat; rgelt[0].tymed = current.tymed; rgelt[0].dwAspect = DVASPECT.DVASPECT_CONTENT; rgelt[0].ptd = IntPtr.Zero; rgelt[0].lindex = -1; if (pceltFetched != null) { pceltFetched[0] = 1; } this.current++; } else { if (pceltFetched != null) { pceltFetched[0] = 0; } return NativeMethods.S_FALSE; } return NativeMethods.S_OK; } public int Skip(int celt) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "FormatEnumerator: Skip"); if (current + celt >= this.formats.Count) { return NativeMethods.S_FALSE; } current += celt; return NativeMethods.S_OK; } public int Reset() { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "FormatEnumerator: Reset"); current = 0; return NativeMethods.S_OK; } public void Clone(out IEnumFORMATETC ppenum) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "FormatEnumerator: Clone"); FORMATETC[] temp = new FORMATETC[formats.Count]; formats.CopyTo(temp, 0); ppenum = new FormatEnumerator(parent, temp); } } /// /// /// OLE Converter. This class embodies the nastiness required to convert from our /// managed types to standard OLE clipboard formats. /// private class OleConverter : IDataObject { internal IComDataObject innerData; public OleConverter(IComDataObject data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "OleConverter: Constructed OleConverter"); innerData = data; } ////// /// Returns the data Object we are wrapping /// ///public IComDataObject OleDataObject { get { return innerData; } } /// /// /// Uses IStream and retrieves the specified format from the bound IComDataObject. /// ///private Object GetDataFromOleIStream(string format) { FORMATETC formatetc = new FORMATETC(); STGMEDIUM medium = new STGMEDIUM(); formatetc.cfFormat = (short)DataFormats.GetFormat(format).Id; formatetc.dwAspect = DVASPECT.DVASPECT_CONTENT; formatetc.lindex = -1; formatetc.tymed = TYMED.TYMED_ISTREAM; medium.tymed = TYMED.TYMED_ISTREAM; // Limit the # of exceptions we may throw below. if (NativeMethods.S_OK != QueryGetData(ref formatetc)){ return null; } try { IntSecurity.UnmanagedCode.Assert(); try { innerData.GetData(ref formatetc, out medium); } finally { CodeAccessPermission.RevertAssert(); } } catch { return null; } if (medium.unionmember != IntPtr.Zero) { UnsafeNativeMethods.IStream pStream = (UnsafeNativeMethods.IStream)Marshal.GetObjectForIUnknown(medium.unionmember); Marshal.Release(medium.unionmember); NativeMethods.STATSTG sstg = new NativeMethods.STATSTG(); pStream.Stat(sstg, NativeMethods.STATFLAG_DEFAULT ); int size = (int)sstg.cbSize; IntPtr hglobal = UnsafeNativeMethods.GlobalAlloc(NativeMethods.GMEM_MOVEABLE | NativeMethods.GMEM_DDESHARE | NativeMethods.GMEM_ZEROINIT, size); IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(innerData, hglobal)); pStream.Read(ptr, size); UnsafeNativeMethods.GlobalUnlock(new HandleRef(innerData, hglobal)); return GetDataFromHGLOBLAL(format, hglobal); } return null; } /// /// /// Retrieves the specified form from the specified hglobal. /// ///private Object GetDataFromHGLOBLAL(string format, IntPtr hglobal) { Object data = null; if (hglobal != IntPtr.Zero) { //=---------------------------------------------------------------= // Convert from OLE to IW objects //=---------------------------------------------------------------= // Add any new formats here... if (format.Equals(DataFormats.Text) || format.Equals(DataFormats.Rtf) || format.Equals(DataFormats.Html) || format.Equals(DataFormats.OemText)) { data = ReadStringFromHandle(hglobal, false); } else if (format.Equals(DataFormats.UnicodeText)) { data = ReadStringFromHandle(hglobal, true); } else if (format.Equals(DataFormats.FileDrop)) { data = (Object)ReadFileListFromHandle(hglobal); } else if (format.Equals(CF_DEPRECATED_FILENAME)) { data = new string[] {ReadStringFromHandle(hglobal, false)}; } else if (format.Equals(CF_DEPRECATED_FILENAMEW)) { data = new string[] {ReadStringFromHandle(hglobal, true)}; } else { data = ReadObjectFromHandle(hglobal); /* spb - 93835 dib support is a mess if (format.Equals(DataFormats.Dib) && data is Stream) { data = new Bitmap((Stream)data); } */ } UnsafeNativeMethods.GlobalFree(new HandleRef(null, hglobal)); } return data; } /// /// /// Uses HGLOBALs and retrieves the specified format from the bound IComDatabject. /// ///private Object GetDataFromOleHGLOBAL(string format) { Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); FORMATETC formatetc = new FORMATETC(); STGMEDIUM medium = new STGMEDIUM(); formatetc.cfFormat = (short)DataFormats.GetFormat(format).Id; formatetc.dwAspect = DVASPECT.DVASPECT_CONTENT; formatetc.lindex = -1; formatetc.tymed = TYMED.TYMED_HGLOBAL; medium.tymed = TYMED.TYMED_HGLOBAL; object data = null; if (NativeMethods.S_OK == QueryGetData(ref formatetc)) { try { IntSecurity.UnmanagedCode.Assert(); try { innerData.GetData(ref formatetc, out medium); } finally { CodeAccessPermission.RevertAssert(); } if (medium.unionmember != IntPtr.Zero) { data = GetDataFromHGLOBLAL(format, medium.unionmember); } } catch { } } 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. /// ///private Object GetDataFromOleOther(string format) { Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); FORMATETC formatetc = new FORMATETC(); STGMEDIUM medium = new STGMEDIUM(); TYMED tymed = (TYMED)0; if (format.Equals(DataFormats.Bitmap)) { tymed = TYMED.TYMED_GDI; } else if (format.Equals(DataFormats.EnhancedMetafile)) { tymed = TYMED.TYMED_ENHMF; } if (tymed == (TYMED)0) { return null; } formatetc.cfFormat = (short)DataFormats.GetFormat(format).Id; formatetc.dwAspect = DVASPECT.DVASPECT_CONTENT; formatetc.lindex = -1; formatetc.tymed = tymed; medium.tymed = tymed; Object data = null; if (NativeMethods.S_OK == QueryGetData(ref formatetc)) { try { IntSecurity.UnmanagedCode.Assert(); try { innerData.GetData(ref formatetc, out medium); } finally { CodeAccessPermission.RevertAssert(); } } catch { } } if (medium.unionmember != IntPtr.Zero) { if (format.Equals(DataFormats.Bitmap) //||format.Equals(DataFormats.Dib)) ) { // as/urt 140870 -- GDI+ doesn't own this HBITMAP, but we can't // delete it while the object is still around. So we have to do the really expensive // thing of cloning the image so we can release the HBITMAP. // //This bitmap is created by the com object which originally copied the bitmap to tbe //clipboard. We call Add here, since DeleteObject calls Remove. System.Internal.HandleCollector.Add(medium.unionmember, NativeMethods.CommonHandles.GDI); Image clipboardImage = null; IntSecurity.ObjectFromWin32Handle.Assert(); try { clipboardImage = Image.FromHbitmap(medium.unionmember); } finally { CodeAccessPermission.RevertAssert(); } if (clipboardImage != null) { Image firstImage = clipboardImage; clipboardImage = (Image)clipboardImage.Clone(); SafeNativeMethods.DeleteObject(new HandleRef(null, medium.unionmember)); firstImage.Dispose(); } data = clipboardImage; } /* gpr: else if (format.Equals(DataFormats.EnhancedMetafile)) { data = new Metafile(medium.unionmember); } */ } return data; } /// /// /// Extracts a managed Object from the innerData of the specified /// format. This is the base of the OLE to managed conversion. /// ///private Object GetDataFromBoundOleDataObject(string format) { Object data = null; try { data = GetDataFromOleOther(format); if (data == null) { data = GetDataFromOleHGLOBAL(format); } if (data == null) { data = GetDataFromOleIStream(format); } } catch (Exception e) { Debug.Fail(e.ToString()); } return data; } /// /// /// Creates an Stream from the data stored in handle. /// ///private Stream ReadByteStreamFromHandle(IntPtr handle, out bool isSerializedObject) { IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(null, handle)); if (ptr == IntPtr.Zero){ throw new ExternalException(SR.GetString(SR.ExternalException), NativeMethods.E_OUTOFMEMORY); } try { int size = UnsafeNativeMethods.GlobalSize(new HandleRef(null, handle)); byte[] bytes = new byte[size]; Marshal.Copy(ptr, bytes, 0, size); int 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 { UnsafeNativeMethods.GlobalUnlock(new HandleRef(null, handle)); } } /// /// /// Creates a new instance of the Object that has been persisted into the /// handle. /// ///private Object ReadObjectFromHandle(IntPtr handle) { object value = null; bool isSerializedObject; Stream stream = ReadByteStreamFromHandle(handle, out isSerializedObject); if (isSerializedObject) { value = ReadObjectFromHandleDeserializer(stream); } else { value = stream; } return value; } [ SecurityPermissionAttribute(SecurityAction.Assert, Flags=SecurityPermissionFlag.SerializationFormatter) ] private static Object ReadObjectFromHandleDeserializer(Stream stream) { BinaryFormatter formatter = new BinaryFormatter(); formatter.AssemblyFormat = FormatterAssemblyStyle.Simple; return formatter.Deserialize(stream); } /// /// /// Parses the HDROP format and returns a list of strings using /// the DragQueryFile function. /// ///private string[] ReadFileListFromHandle(IntPtr hdrop) { string[] files = null; StringBuilder sb = new StringBuilder(NativeMethods.MAX_PATH); int count = UnsafeNativeMethods.DragQueryFile(new HandleRef(null, hdrop), unchecked((int)0xFFFFFFFF), null, 0); if (count > 0) { files = new string[count]; for (int i=0; i charlen) { s = s.Substring(0, charlen); } // SECREVIEW : do we really need to do this? // string fullPath = Path.GetFullPath(s); Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileIO(" + fullPath + ") Demanded"); new FileIOPermission(FileIOPermissionAccess.PathDiscovery, fullPath).Demand(); files[i] = s; } } return files; } /// /// /// 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. /// ///private unsafe string ReadStringFromHandle(IntPtr handle, bool unicode) { string stringData = null; IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(null, handle)); try { if (unicode) { stringData = new string((char*)ptr); } else { stringData = new string((sbyte*)ptr); } } finally { UnsafeNativeMethods.GlobalUnlock(new HandleRef(null, handle)); } return stringData; } //=------------------------------------------------------------------------= // IDataObject //=-----------------------------------------------------------------------= public virtual Object GetData(string format, bool autoConvert) { Object baseVar = GetDataFromBoundOleDataObject(format); Object original = baseVar; if (autoConvert && (baseVar == null || baseVar is MemoryStream)) { string[] mappedFormats = GetMappedFormats(format); if (mappedFormats != null) { for (int i=0; i 0) { retrieved[0] = 0; try { enumFORMATETC.Next(1, formatetc, retrieved); } catch { } if (retrieved[0] > 0) { string name = DataFormats.GetFormat(formatetc[0].cfFormat).Name; if (autoConvert) { string[] mappedFormats = GetMappedFormats(name); for (int i=0; i /// /// private class DataStore : IDataObject { private class DataStoreEntry { public Object data; public bool autoConvert; public DataStoreEntry(Object data, bool autoConvert) { this.data = data; this.autoConvert = autoConvert; } } private Hashtable data = new Hashtable(BackCompatibleStringComparer.Default); public DataStore() { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "DataStore: Constructed DataStore"); } public virtual Object GetData(string format, bool autoConvert) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "DataStore: GetData: " + format + ", " + autoConvert.ToString()); DataStoreEntry dse = (DataStoreEntry)data[format]; Object baseVar = null; if (dse != null) { baseVar = dse.data; } Object original = baseVar; if (autoConvert && (dse == null || dse.autoConvert) && (baseVar == null || baseVar is MemoryStream)) { string[] mappedFormats = GetMappedFormats(format); if (mappedFormats != null) { for (int i=0; i// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ namespace System.Windows.Forms { using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization; using System.Text; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Collections.Specialized; using System.Diagnostics; using System; using Microsoft.Win32; using System.Collections; using System.ComponentModel; using System.IO; using System.Drawing; using System.Windows.Forms; using System.Security; using System.Security.Permissions; using System.Reflection; using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject; using System.Globalization; /// /// /// [ ClassInterface(ClassInterfaceType.None) ] public class DataObject : IDataObject, IComDataObject { private static readonly string CF_DEPRECATED_FILENAME = "FileName"; private static readonly string CF_DEPRECATED_FILENAMEW = "FileNameW"; 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 = 0x00040130; private static readonly TYMED[] ALLOWED_TYMEDS = new TYMED [] { TYMED.TYMED_HGLOBAL, TYMED.TYMED_ISTREAM, TYMED.TYMED_ENHMF, TYMED.TYMED_MFPICT, TYMED.TYMED_GDI}; private IDataObject innerData = null; // 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. // private static readonly byte[] serializedObjectID = new Guid("FD9EA796-3B13-4370-A679-56106BB288FB").ToByteArray(); ///Implements a basic data transfer mechanism. ////// /// internal DataObject(IDataObject data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Constructed DataObject based on IDataObject"); innerData = data; Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); } ///Initializes a new instance of the ///class, with the specified . /// /// internal DataObject(IComDataObject data) { if (data is DataObject) { innerData = data as IDataObject; } else { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Constructed DataObject based on IComDataObject"); innerData = new OleConverter(data); } Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); } ///Initializes a new instance of the ///class, with the specified . /// /// public DataObject() { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Constructed DataObject standalone"); innerData = new DataStore(); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); } ////// Initializes a new instance of the ////// class, which can store arbitrary data. /// /// /// public DataObject(object data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Constructed DataObject base on Object: " + data.ToString()); if (data is IDataObject && !Marshal.IsComObject(data)) { innerData = (IDataObject)data; } else if (data is IComDataObject) { innerData = new OleConverter((IComDataObject)data); } else { innerData = new DataStore(); SetData(data); } Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); } ///Initializes a new instance of the ///class, containing the specified data. /// /// public DataObject(string format, object data) : this() { SetData(format, data); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); } private IntPtr GetCompatibleBitmap(Bitmap bm) { // 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. // IntPtr hBitmap = bm.GetHbitmap(); // Get the screen DC. // IntPtr hDC = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); // Create a compatible DC to render the source bitmap. // IntPtr dcSrc = UnsafeNativeMethods.CreateCompatibleDC(new HandleRef(null, hDC)); IntPtr srcOld = SafeNativeMethods.SelectObject(new HandleRef(null, dcSrc), new HandleRef(bm, hBitmap)); // Create a compatible DC and a new compatible bitmap. // IntPtr dcDest = UnsafeNativeMethods.CreateCompatibleDC(new HandleRef(null, hDC)); IntPtr hBitmapNew = SafeNativeMethods.CreateCompatibleBitmap(new HandleRef(null, hDC), bm.Size.Width, bm.Size.Height); // Select the new bitmap into a compatible DC and render the blt the original bitmap. // IntPtr destOld = SafeNativeMethods.SelectObject(new HandleRef(null, dcDest), new HandleRef(null, hBitmapNew)); SafeNativeMethods.BitBlt(new HandleRef(null, dcDest), 0, 0, bm.Size.Width, bm.Size.Height, new HandleRef(null, dcSrc), 0, 0, 0x00CC0020); // Clear the source and destination compatible DCs. // SafeNativeMethods.SelectObject(new HandleRef(null, dcSrc), new HandleRef(null, srcOld)); SafeNativeMethods.SelectObject(new HandleRef(null, dcDest), new HandleRef(null, destOld)); UnsafeNativeMethods.DeleteCompatibleDC(new HandleRef(null, dcSrc)); UnsafeNativeMethods.DeleteCompatibleDC(new HandleRef(null, dcDest)); UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, hDC)); SafeNativeMethods.DeleteObject(new HandleRef(bm, hBitmap)); return hBitmapNew; } ///Initializes a new instance of the ///class, containing the specified data and its /// associated format. /// /// public virtual object GetData(string format, bool autoConvert) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Request data: " + format + ", " + autoConvert.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); return innerData.GetData(format, autoConvert); } ///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 virtual object GetData(string format) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Request data: " + format); return GetData(format, true); } ///Retrieves the data associated with the specified data /// format. ////// /// public virtual object GetData(Type format) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Request data: " + format.FullName); Debug.Assert(format != null, "Must specify a format type"); if (format == null) { return null; } return GetData(format.FullName); } ///Retrieves the data associated with the specified class /// type format. ////// /// public virtual bool GetDataPresent(Type format) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check data: " + format.FullName); Debug.Assert(format != null, "Must specify a format type"); if (format == null) { return false; } bool b = GetDataPresent(format.FullName); Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, " ret: " + b.ToString()); return b; } ///Determines whether data stored in this instance is /// associated with, or can be converted to, the specified /// format. ////// /// public virtual bool GetDataPresent(string format, bool autoConvert) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check data: " + format + ", " + autoConvert.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); bool b = innerData.GetDataPresent(format, autoConvert); Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, " ret: " + b.ToString()); return b; } ///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 virtual bool GetDataPresent(string format) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check data: " + format); bool b = GetDataPresent(format, true); Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, " ret: " + b.ToString()); return b; } ///Determines whether data stored in this instance is /// associated with, or can be converted to, the specified /// format. ////// /// public virtual string[] GetFormats(bool autoConvert) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check formats: " + autoConvert.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); return innerData.GetFormats(autoConvert); } ///Gets a list of all formats that data stored in this /// instance is associated with or can be converted to, using an automatic /// conversion parameter ///to /// determine whether to retrieve all formats that the data can be converted to or /// only native data formats. /// /// public virtual string[] GetFormats() { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check formats:"); return GetFormats(true); } // <-- WHIDBEY ADDITIONS ///Gets a list of all formats that data stored in this instance is associated /// with or can be converted to. ////// /// public virtual bool ContainsAudio() { return GetDataPresent(DataFormats.WaveAudio, false); } ///[To be supplied.] ////// /// public virtual bool ContainsFileDropList() { return GetDataPresent(DataFormats.FileDrop, true); } ///[To be supplied.] ////// /// public virtual bool ContainsImage() { return GetDataPresent(DataFormats.Bitmap, true); } ///[To be supplied.] ////// /// public virtual bool ContainsText() { return ContainsText(TextDataFormat.UnicodeText); } ///[To be supplied.] ////// /// public virtual bool ContainsText(TextDataFormat format) { //valid values are 0x0 to 0x4 if (!ClientUtils.IsEnumValid(format, (int)format, (int)TextDataFormat.Text, (int)TextDataFormat.CommaSeparatedValue)){ throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat)); } return GetDataPresent(ConvertToDataFormats(format), false); } ///[To be supplied.] ////// /// public virtual Stream GetAudioStream() { return GetData(DataFormats.WaveAudio, false) as Stream; } ///[To be supplied.] ////// /// public virtual StringCollection GetFileDropList() { StringCollection retVal = new StringCollection(); string[] strings = GetData(DataFormats.FileDrop, true) as string[]; if (strings != null) { retVal.AddRange(strings); } return retVal; } ///[To be supplied.] ////// /// public virtual Image GetImage() { return GetData(DataFormats.Bitmap, true) as Image; } ///[To be supplied.] ////// /// public virtual string GetText() { return GetText(TextDataFormat.UnicodeText); } ///[To be supplied.] ////// /// public virtual string GetText(TextDataFormat format) { //valid values are 0x0 to 0x4 if (!ClientUtils.IsEnumValid(format, (int)format, (int)TextDataFormat.Text, (int)TextDataFormat.CommaSeparatedValue)){ throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat)); } string text = GetData(ConvertToDataFormats(format), false) as string; if (text != null) { return text; } return String.Empty; } ///[To be supplied.] ////// /// public virtual void SetAudio(byte[] audioBytes) { if (audioBytes == null) { throw new ArgumentNullException("audioBytes"); } SetAudio(new MemoryStream(audioBytes)); } ///[To be supplied.] ////// /// public virtual void SetAudio(Stream audioStream) { if (audioStream == null) { throw new ArgumentNullException("audioStream"); } SetData(DataFormats.WaveAudio, false, audioStream); } ///[To be supplied.] ////// /// public virtual void SetFileDropList(StringCollection filePaths) { if (filePaths == null) { throw new ArgumentNullException("filePaths"); } string[] strings = new string[filePaths.Count]; filePaths.CopyTo(strings, 0); SetData(DataFormats.FileDrop, true, strings); } ///[To be supplied.] ////// /// public virtual void SetImage(Image image) { if (image == null) { throw new ArgumentNullException("image"); } SetData(DataFormats.Bitmap, true, image); } ///[To be supplied.] ////// /// public virtual void SetText(string textData) { SetText(textData, TextDataFormat.UnicodeText); } ///[To be supplied.] ////// /// public virtual void SetText(string textData, TextDataFormat format) { if (String.IsNullOrEmpty(textData)) { throw new ArgumentNullException("textData"); } //valid values are 0x0 to 0x4 if (!ClientUtils.IsEnumValid(format, (int)format, (int)TextDataFormat.Text, (int)TextDataFormat.CommaSeparatedValue)) { throw new InvalidEnumArgumentException("format", (int)format, typeof(TextDataFormat)); } SetData(ConvertToDataFormats(format), false, textData); } private static string ConvertToDataFormats(TextDataFormat format) { switch (format) { case TextDataFormat.UnicodeText: return DataFormats.UnicodeText; case TextDataFormat.Rtf: return DataFormats.Rtf; case TextDataFormat.Html: return DataFormats.Html; case TextDataFormat.CommaSeparatedValue: return DataFormats.CommaSeparatedValue; } return DataFormats.UnicodeText; } // END - WHIDBEY ADDITIONS --> ///[To be supplied.] ////// /// Retrieves a list of distinct strings from the array. /// private static string[] GetDistinctStrings(string[] formats) { ArrayList distinct = new ArrayList(); for (int i=0; i/// /// Returns all the "synonyms" for the specified format. /// private static string[] GetMappedFormats(string format) { if (format == null) { return null; } if (format.Equals(DataFormats.Text) || format.Equals(DataFormats.UnicodeText) || format.Equals(DataFormats.StringFormat)) { return new string[] { DataFormats.StringFormat, DataFormats.UnicodeText, DataFormats.Text, }; } if (format.Equals(DataFormats.FileDrop) || format.Equals(CF_DEPRECATED_FILENAME) || format.Equals(CF_DEPRECATED_FILENAMEW)) { return new string[] { DataFormats.FileDrop, CF_DEPRECATED_FILENAMEW, CF_DEPRECATED_FILENAME, }; } if (format.Equals(DataFormats.Bitmap) || format.Equals((typeof(Bitmap)).FullName)) { return new string[] { (typeof(Bitmap)).FullName, DataFormats.Bitmap, }; } /*gpr if (format.Equals(DataFormats.EnhancedMetafile) || format.Equals((typeof(Metafile)).FullName)) { return new string[] {DataFormats.EnhancedMetafile, (typeof(Metafile)).FullName}; } */ return new String[] {format}; } /* ////// /// Returns all distinct "synonyms" for the each of the formats. /// private static string[] GetMappedFormats(string[] formats) { ArrayList allChoices = new ArrayList(); for (int i=0; i/// /// Returns true if the tymed is useable. /// ///private bool GetTymedUseable(TYMED tymed) { for (int i=0; i /// /// Populates Ole datastructes from a WinForms dataObject. This is the core /// of WinForms to OLE conversion. /// ///private void GetDataIntoOleStructs(ref FORMATETC formatetc, ref STGMEDIUM medium) { if (GetTymedUseable(formatetc.tymed) && GetTymedUseable(medium.tymed)) { string format = DataFormats.GetFormat(formatetc.cfFormat).Name; if (GetDataPresent(format)) { Object data = GetData(format); if ((formatetc.tymed & TYMED.TYMED_HGLOBAL) != 0) { int hr = SaveDataToHandle(data, format, ref medium); if (NativeMethods.Failed(hr)) { Marshal.ThrowExceptionForHR(hr); } } else if ((formatetc.tymed & TYMED.TYMED_GDI) != 0) { if (format.Equals(DataFormats.Bitmap) && data is Bitmap) { // save bitmap // Bitmap bm = (Bitmap)data; if (bm != null) { medium.unionmember = GetCompatibleBitmap(bm); // gpr: Does this get properly disposed? } } } /* gpr else if ((formatetc.tymed & TYMED.TYMED_ENHMF) != 0) { if (format.Equals(DataFormats.EnhancedMetafile) && data is Metafile) { // save metafile Metafile mf = (Metafile)data; if (mf != null) { medium.unionmember = mf.Handle; } } } */ else { Marshal.ThrowExceptionForHR (DV_E_TYMED); } } else { Marshal.ThrowExceptionForHR (DV_E_FORMATETC); } } else { Marshal.ThrowExceptionForHR (DV_E_TYMED); } } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] int IComDataObject.DAdvise(ref FORMATETC pFormatetc, ADVF advf, IAdviseSink pAdvSink, out int pdwConnection) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "DAdvise"); 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. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] void IComDataObject.DUnadvise(int dwConnection) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "DUnadvise"); if (innerData is OleConverter) { ((OleConverter)innerData).OleDataObject.DUnadvise(dwConnection); return; } Marshal.ThrowExceptionForHR(NativeMethods.E_NOTIMPL); } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] int IComDataObject.EnumDAdvise(out IEnumSTATDATA enumAdvise) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "EnumDAdvise"); 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. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] IEnumFORMATETC IComDataObject.EnumFormatEtc(DATADIR dwDirection) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "EnumFormatEtc: " + dwDirection.ToString()); if (innerData is OleConverter) { return ((OleConverter)innerData).OleDataObject.EnumFormatEtc(dwDirection); } if (dwDirection == DATADIR.DATADIR_GET) { return new FormatEnumerator(this); } else { throw new ExternalException(SR.GetString(SR.ExternalException), NativeMethods.E_NOTIMPL); } } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] int IComDataObject.GetCanonicalFormatEtc(ref FORMATETC pformatetcIn, out FORMATETC pformatetcOut) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "GetCanonicalFormatEtc"); if (innerData is OleConverter) { return ((OleConverter)innerData).OleDataObject.GetCanonicalFormatEtc(ref pformatetcIn, out pformatetcOut); } pformatetcOut = new FORMATETC(); return (DATA_S_SAMEFORMATETC); } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] void IComDataObject.GetData(ref FORMATETC formatetc, out STGMEDIUM medium) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "GetData"); if (innerData is OleConverter) { ((OleConverter)innerData).OleDataObject.GetData(ref formatetc, out medium); return; } medium = new STGMEDIUM(); if (GetTymedUseable(formatetc.tymed)) { if ((formatetc.tymed & TYMED.TYMED_HGLOBAL) != 0) { medium.tymed = TYMED.TYMED_HGLOBAL; medium.unionmember = UnsafeNativeMethods.GlobalAlloc(NativeMethods.GMEM_MOVEABLE | NativeMethods.GMEM_DDESHARE | NativeMethods.GMEM_ZEROINIT, 1); if (medium.unionmember == IntPtr.Zero) { throw new OutOfMemoryException(); } try { ((IComDataObject)this).GetDataHere(ref formatetc, ref medium); } catch { UnsafeNativeMethods.GlobalFree(new HandleRef(medium, medium.unionmember)); medium.unionmember = IntPtr.Zero; throw; } } else { medium.tymed = formatetc.tymed; ((IComDataObject)this).GetDataHere(ref formatetc, ref medium); } } else { Marshal.ThrowExceptionForHR(DV_E_TYMED); } } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] void IComDataObject.GetDataHere(ref FORMATETC formatetc, ref STGMEDIUM medium) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "GetDataHere"); if (innerData is OleConverter) { ((OleConverter)innerData).OleDataObject.GetDataHere(ref formatetc, ref medium); } else { GetDataIntoOleStructs(ref formatetc, ref medium); } } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] int IComDataObject.QueryGetData(ref FORMATETC formatetc) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "QueryGetData"); 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) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "QueryGetData::returning S_FALSE because cfFormat == 0"); return NativeMethods.S_FALSE; } else { if (!GetDataPresent(DataFormats.GetFormat(formatetc.cfFormat).Name)) { return (DV_E_FORMATETC); } } } else { return (DV_E_TYMED); } } else { return (DV_E_DVASPECT); } #if DEBUG int format = formatetc.cfFormat; Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "QueryGetData::cfFormat " + format.ToString(CultureInfo.InvariantCulture) + " found"); #endif return NativeMethods.S_OK; } // // Part of IComDataObject, used to interop with OLE. // ///// /// // SecReview : Vs# 416823 : Need to Demand UMC as IComDataObject is now public interface. // This exposes security hole where the IComDataObject implementation can be used to bypass UMC security to call Win32 functions. [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] void IComDataObject.SetData(ref FORMATETC pFormatetcIn, ref STGMEDIUM pmedium, bool fRelease) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "SetData"); if (innerData is OleConverter) { ((OleConverter)innerData).OleDataObject.SetData(ref pFormatetcIn, ref pmedium, fRelease); return; } // throw new NotImplementedException(); } private int SaveDataToHandle(object data, string format, ref STGMEDIUM medium) { int hr = NativeMethods.E_FAIL; if (data is Stream) { hr = SaveStreamToHandle(ref medium.unionmember, (Stream)data); } else if (format.Equals(DataFormats.Text) || format.Equals(DataFormats.Rtf) || format.Equals(DataFormats.Html) || format.Equals(DataFormats.OemText)) { hr = SaveStringToHandle(medium.unionmember, data.ToString(), false); } else if (format.Equals(DataFormats.UnicodeText)) { hr = SaveStringToHandle(medium.unionmember, data.ToString(), true); } else if (format.Equals(DataFormats.FileDrop)) { hr = SaveFileListToHandle(medium.unionmember, (string[])data); } else if (format.Equals(CF_DEPRECATED_FILENAME)) { string[] filelist = (string[])data; hr = SaveStringToHandle(medium.unionmember, filelist[0], false); } else if (format.Equals(CF_DEPRECATED_FILENAMEW)) { string[] filelist = (string[])data; hr = SaveStringToHandle(medium.unionmember, filelist[0], true); } else if (format.Equals(DataFormats.Dib) && data is Image) { // 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; // SaveImageToHandle(ref medium.unionmember, (Image)data); } else if (format.Equals(DataFormats.Serializable) || data is ISerializable || (data != null && data.GetType().IsSerializable)) { hr = SaveObjectToHandle(ref medium.unionmember, data); } return hr; } /* private int SaveImageToHandle(ref IntPtr handle, Image data) { MemoryStream stream = new MemoryStream(); data.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); return SaveStreamToHandle(ref handle, stream); } */ private int SaveObjectToHandle(ref IntPtr handle, Object data) { Stream stream = new MemoryStream(); BinaryWriter bw = new BinaryWriter(stream); bw.Write(serializedObjectID); SaveObjectToHandleSerializer(stream, data); return SaveStreamToHandle(ref handle, stream); } [ SecurityPermissionAttribute(SecurityAction.Assert, Flags=SecurityPermissionFlag.SerializationFormatter) ] private static void SaveObjectToHandleSerializer(Stream stream, Object data) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, data); } /// /// /// Saves stream out to handle. /// ///private int SaveStreamToHandle(ref IntPtr handle, Stream stream) { int size = (int)stream.Length; handle = UnsafeNativeMethods.GlobalAlloc(NativeMethods.GMEM_MOVEABLE | NativeMethods.GMEM_DDESHARE, size); if (handle == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(null, handle)); if (ptr == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } try { byte[] bytes = new byte[size]; stream.Position = 0; stream.Read(bytes, 0, size); Marshal.Copy(bytes, 0, ptr, size); } finally { UnsafeNativeMethods.GlobalUnlock(new HandleRef(null, handle)); } return NativeMethods.S_OK; } /// /// /// Saves a list of files out to the handle in HDROP format. /// ///private int SaveFileListToHandle(IntPtr handle, string[] files) { if (files == null) { return NativeMethods.S_OK; } else if (files.Length < 1) { return NativeMethods.S_OK; } if (handle == IntPtr.Zero) { return (NativeMethods.E_INVALIDARG); } bool unicode = (Marshal.SystemDefaultCharSize != 1); IntPtr currentPtr = IntPtr.Zero; int baseStructSize = 4 + 8 + 4 + 4; int sizeInBytes = baseStructSize; // First determine the size of the array // if (unicode) { for (int i=0; i /// /// Save string to handle. If unicode is set to true /// then the string is saved as Unicode, else it is saves as DBCS. /// ///private int SaveStringToHandle(IntPtr handle, string str, bool unicode) { if (handle == IntPtr.Zero) { return (NativeMethods.E_INVALIDARG); } IntPtr newHandle = IntPtr.Zero; if (unicode) { int byteSize = (str.Length*2 + 2); newHandle = UnsafeNativeMethods.GlobalReAlloc(new HandleRef(null, handle), byteSize, NativeMethods.GMEM_MOVEABLE | NativeMethods.GMEM_DDESHARE | NativeMethods.GMEM_ZEROINIT); if (newHandle == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(null, newHandle)); if (ptr == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } // NOTE: DllLib.copy(char[]...) converts to ANSI on Windows 95... char[] chars = str.ToCharArray(0, str.Length); UnsafeNativeMethods.CopyMemoryW(ptr, chars, chars.Length*2); //NativeMethods.CopyMemoryW(ptr, string, string.Length()*2); } else { int pinvokeSize = UnsafeNativeMethods.WideCharToMultiByte(0 /*CP_ACP*/, 0, str, str.Length, null, 0, IntPtr.Zero, IntPtr.Zero); byte[] strBytes = new byte[pinvokeSize]; UnsafeNativeMethods.WideCharToMultiByte(0 /*CP_ACP*/, 0, str, str.Length, strBytes, strBytes.Length, IntPtr.Zero, IntPtr.Zero); newHandle = UnsafeNativeMethods.GlobalReAlloc(new HandleRef(null, handle), pinvokeSize + 1, NativeMethods.GMEM_MOVEABLE | NativeMethods.GMEM_DDESHARE | NativeMethods.GMEM_ZEROINIT); if (newHandle == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(null, newHandle)); if (ptr == IntPtr.Zero) { return (NativeMethods.E_OUTOFMEMORY); } UnsafeNativeMethods.CopyMemory(ptr, strBytes, pinvokeSize); Marshal.Copy(new byte[] {0}, 0, (IntPtr)((long)ptr+pinvokeSize), 1); } if (newHandle != IntPtr.Zero) { UnsafeNativeMethods.GlobalUnlock(new HandleRef(null, newHandle)); } return NativeMethods.S_OK; } /// /// /// public virtual void SetData(string format, bool autoConvert, Object data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Set data: " + format + ", " + autoConvert.ToString() + ", " + data.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); innerData.SetData(format, autoConvert, 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. ////// /// public virtual void SetData(string format, object data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Set data: " + format + ", " + data.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); innerData.SetData(format, data); } ///Stores the specified data and its associated format in this /// instance. ////// /// public virtual void SetData(Type format, object data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Set data: " + format.FullName + ", " + data.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); innerData.SetData(format, data); } ///Stores the specified data and /// its /// associated class type in this instance. ////// /// public virtual void SetData(object data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Set data: " + data.ToString()); Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); innerData.SetData(data); } ///Stores the specified data in /// this instance, using the class of the data for the format. ////// /// Part of IComDataObject, used to interop with OLE. /// ///private class FormatEnumerator : IEnumFORMATETC { internal IDataObject parent = null; internal ArrayList formats = new ArrayList(); internal int current = 0; public FormatEnumerator(IDataObject parent) : this(parent, parent.GetFormats()) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "FormatEnumerator: Constructed: " + parent.ToString()); } public FormatEnumerator(IDataObject parent, FORMATETC[] formats) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "FormatEnumerator: Constructed: " + parent.ToString() + ", FORMATETC[]" + formats.Length.ToString(CultureInfo.InvariantCulture)); this.formats.Clear(); this.parent = parent; current = 0; if (formats != null) { for (int i=0; i 0) { FORMATETC current = (FORMATETC)formats[this.current]; rgelt[0].cfFormat = current.cfFormat; rgelt[0].tymed = current.tymed; rgelt[0].dwAspect = DVASPECT.DVASPECT_CONTENT; rgelt[0].ptd = IntPtr.Zero; rgelt[0].lindex = -1; if (pceltFetched != null) { pceltFetched[0] = 1; } this.current++; } else { if (pceltFetched != null) { pceltFetched[0] = 0; } return NativeMethods.S_FALSE; } return NativeMethods.S_OK; } public int Skip(int celt) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "FormatEnumerator: Skip"); if (current + celt >= this.formats.Count) { return NativeMethods.S_FALSE; } current += celt; return NativeMethods.S_OK; } public int Reset() { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "FormatEnumerator: Reset"); current = 0; return NativeMethods.S_OK; } public void Clone(out IEnumFORMATETC ppenum) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "FormatEnumerator: Clone"); FORMATETC[] temp = new FORMATETC[formats.Count]; formats.CopyTo(temp, 0); ppenum = new FormatEnumerator(parent, temp); } } /// /// /// OLE Converter. This class embodies the nastiness required to convert from our /// managed types to standard OLE clipboard formats. /// private class OleConverter : IDataObject { internal IComDataObject innerData; public OleConverter(IComDataObject data) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "OleConverter: Constructed OleConverter"); innerData = data; } ////// /// Returns the data Object we are wrapping /// ///public IComDataObject OleDataObject { get { return innerData; } } /// /// /// Uses IStream and retrieves the specified format from the bound IComDataObject. /// ///private Object GetDataFromOleIStream(string format) { FORMATETC formatetc = new FORMATETC(); STGMEDIUM medium = new STGMEDIUM(); formatetc.cfFormat = (short)DataFormats.GetFormat(format).Id; formatetc.dwAspect = DVASPECT.DVASPECT_CONTENT; formatetc.lindex = -1; formatetc.tymed = TYMED.TYMED_ISTREAM; medium.tymed = TYMED.TYMED_ISTREAM; // Limit the # of exceptions we may throw below. if (NativeMethods.S_OK != QueryGetData(ref formatetc)){ return null; } try { IntSecurity.UnmanagedCode.Assert(); try { innerData.GetData(ref formatetc, out medium); } finally { CodeAccessPermission.RevertAssert(); } } catch { return null; } if (medium.unionmember != IntPtr.Zero) { UnsafeNativeMethods.IStream pStream = (UnsafeNativeMethods.IStream)Marshal.GetObjectForIUnknown(medium.unionmember); Marshal.Release(medium.unionmember); NativeMethods.STATSTG sstg = new NativeMethods.STATSTG(); pStream.Stat(sstg, NativeMethods.STATFLAG_DEFAULT ); int size = (int)sstg.cbSize; IntPtr hglobal = UnsafeNativeMethods.GlobalAlloc(NativeMethods.GMEM_MOVEABLE | NativeMethods.GMEM_DDESHARE | NativeMethods.GMEM_ZEROINIT, size); IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(innerData, hglobal)); pStream.Read(ptr, size); UnsafeNativeMethods.GlobalUnlock(new HandleRef(innerData, hglobal)); return GetDataFromHGLOBLAL(format, hglobal); } return null; } /// /// /// Retrieves the specified form from the specified hglobal. /// ///private Object GetDataFromHGLOBLAL(string format, IntPtr hglobal) { Object data = null; if (hglobal != IntPtr.Zero) { //=---------------------------------------------------------------= // Convert from OLE to IW objects //=---------------------------------------------------------------= // Add any new formats here... if (format.Equals(DataFormats.Text) || format.Equals(DataFormats.Rtf) || format.Equals(DataFormats.Html) || format.Equals(DataFormats.OemText)) { data = ReadStringFromHandle(hglobal, false); } else if (format.Equals(DataFormats.UnicodeText)) { data = ReadStringFromHandle(hglobal, true); } else if (format.Equals(DataFormats.FileDrop)) { data = (Object)ReadFileListFromHandle(hglobal); } else if (format.Equals(CF_DEPRECATED_FILENAME)) { data = new string[] {ReadStringFromHandle(hglobal, false)}; } else if (format.Equals(CF_DEPRECATED_FILENAMEW)) { data = new string[] {ReadStringFromHandle(hglobal, true)}; } else { data = ReadObjectFromHandle(hglobal); /* spb - 93835 dib support is a mess if (format.Equals(DataFormats.Dib) && data is Stream) { data = new Bitmap((Stream)data); } */ } UnsafeNativeMethods.GlobalFree(new HandleRef(null, hglobal)); } return data; } /// /// /// Uses HGLOBALs and retrieves the specified format from the bound IComDatabject. /// ///private Object GetDataFromOleHGLOBAL(string format) { Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); FORMATETC formatetc = new FORMATETC(); STGMEDIUM medium = new STGMEDIUM(); formatetc.cfFormat = (short)DataFormats.GetFormat(format).Id; formatetc.dwAspect = DVASPECT.DVASPECT_CONTENT; formatetc.lindex = -1; formatetc.tymed = TYMED.TYMED_HGLOBAL; medium.tymed = TYMED.TYMED_HGLOBAL; object data = null; if (NativeMethods.S_OK == QueryGetData(ref formatetc)) { try { IntSecurity.UnmanagedCode.Assert(); try { innerData.GetData(ref formatetc, out medium); } finally { CodeAccessPermission.RevertAssert(); } if (medium.unionmember != IntPtr.Zero) { data = GetDataFromHGLOBLAL(format, medium.unionmember); } } catch { } } 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. /// ///private Object GetDataFromOleOther(string format) { Debug.Assert(innerData != null, "You must have an innerData on all DataObjects"); FORMATETC formatetc = new FORMATETC(); STGMEDIUM medium = new STGMEDIUM(); TYMED tymed = (TYMED)0; if (format.Equals(DataFormats.Bitmap)) { tymed = TYMED.TYMED_GDI; } else if (format.Equals(DataFormats.EnhancedMetafile)) { tymed = TYMED.TYMED_ENHMF; } if (tymed == (TYMED)0) { return null; } formatetc.cfFormat = (short)DataFormats.GetFormat(format).Id; formatetc.dwAspect = DVASPECT.DVASPECT_CONTENT; formatetc.lindex = -1; formatetc.tymed = tymed; medium.tymed = tymed; Object data = null; if (NativeMethods.S_OK == QueryGetData(ref formatetc)) { try { IntSecurity.UnmanagedCode.Assert(); try { innerData.GetData(ref formatetc, out medium); } finally { CodeAccessPermission.RevertAssert(); } } catch { } } if (medium.unionmember != IntPtr.Zero) { if (format.Equals(DataFormats.Bitmap) //||format.Equals(DataFormats.Dib)) ) { // as/urt 140870 -- GDI+ doesn't own this HBITMAP, but we can't // delete it while the object is still around. So we have to do the really expensive // thing of cloning the image so we can release the HBITMAP. // //This bitmap is created by the com object which originally copied the bitmap to tbe //clipboard. We call Add here, since DeleteObject calls Remove. System.Internal.HandleCollector.Add(medium.unionmember, NativeMethods.CommonHandles.GDI); Image clipboardImage = null; IntSecurity.ObjectFromWin32Handle.Assert(); try { clipboardImage = Image.FromHbitmap(medium.unionmember); } finally { CodeAccessPermission.RevertAssert(); } if (clipboardImage != null) { Image firstImage = clipboardImage; clipboardImage = (Image)clipboardImage.Clone(); SafeNativeMethods.DeleteObject(new HandleRef(null, medium.unionmember)); firstImage.Dispose(); } data = clipboardImage; } /* gpr: else if (format.Equals(DataFormats.EnhancedMetafile)) { data = new Metafile(medium.unionmember); } */ } return data; } /// /// /// Extracts a managed Object from the innerData of the specified /// format. This is the base of the OLE to managed conversion. /// ///private Object GetDataFromBoundOleDataObject(string format) { Object data = null; try { data = GetDataFromOleOther(format); if (data == null) { data = GetDataFromOleHGLOBAL(format); } if (data == null) { data = GetDataFromOleIStream(format); } } catch (Exception e) { Debug.Fail(e.ToString()); } return data; } /// /// /// Creates an Stream from the data stored in handle. /// ///private Stream ReadByteStreamFromHandle(IntPtr handle, out bool isSerializedObject) { IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(null, handle)); if (ptr == IntPtr.Zero){ throw new ExternalException(SR.GetString(SR.ExternalException), NativeMethods.E_OUTOFMEMORY); } try { int size = UnsafeNativeMethods.GlobalSize(new HandleRef(null, handle)); byte[] bytes = new byte[size]; Marshal.Copy(ptr, bytes, 0, size); int 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 { UnsafeNativeMethods.GlobalUnlock(new HandleRef(null, handle)); } } /// /// /// Creates a new instance of the Object that has been persisted into the /// handle. /// ///private Object ReadObjectFromHandle(IntPtr handle) { object value = null; bool isSerializedObject; Stream stream = ReadByteStreamFromHandle(handle, out isSerializedObject); if (isSerializedObject) { value = ReadObjectFromHandleDeserializer(stream); } else { value = stream; } return value; } [ SecurityPermissionAttribute(SecurityAction.Assert, Flags=SecurityPermissionFlag.SerializationFormatter) ] private static Object ReadObjectFromHandleDeserializer(Stream stream) { BinaryFormatter formatter = new BinaryFormatter(); formatter.AssemblyFormat = FormatterAssemblyStyle.Simple; return formatter.Deserialize(stream); } /// /// /// Parses the HDROP format and returns a list of strings using /// the DragQueryFile function. /// ///private string[] ReadFileListFromHandle(IntPtr hdrop) { string[] files = null; StringBuilder sb = new StringBuilder(NativeMethods.MAX_PATH); int count = UnsafeNativeMethods.DragQueryFile(new HandleRef(null, hdrop), unchecked((int)0xFFFFFFFF), null, 0); if (count > 0) { files = new string[count]; for (int i=0; i charlen) { s = s.Substring(0, charlen); } // SECREVIEW : do we really need to do this? // string fullPath = Path.GetFullPath(s); Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileIO(" + fullPath + ") Demanded"); new FileIOPermission(FileIOPermissionAccess.PathDiscovery, fullPath).Demand(); files[i] = s; } } return files; } /// /// /// 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. /// ///private unsafe string ReadStringFromHandle(IntPtr handle, bool unicode) { string stringData = null; IntPtr ptr = UnsafeNativeMethods.GlobalLock(new HandleRef(null, handle)); try { if (unicode) { stringData = new string((char*)ptr); } else { stringData = new string((sbyte*)ptr); } } finally { UnsafeNativeMethods.GlobalUnlock(new HandleRef(null, handle)); } return stringData; } //=------------------------------------------------------------------------= // IDataObject //=-----------------------------------------------------------------------= public virtual Object GetData(string format, bool autoConvert) { Object baseVar = GetDataFromBoundOleDataObject(format); Object original = baseVar; if (autoConvert && (baseVar == null || baseVar is MemoryStream)) { string[] mappedFormats = GetMappedFormats(format); if (mappedFormats != null) { for (int i=0; i 0) { retrieved[0] = 0; try { enumFORMATETC.Next(1, formatetc, retrieved); } catch { } if (retrieved[0] > 0) { string name = DataFormats.GetFormat(formatetc[0].cfFormat).Name; if (autoConvert) { string[] mappedFormats = GetMappedFormats(name); for (int i=0; i /// /// private class DataStore : IDataObject { private class DataStoreEntry { public Object data; public bool autoConvert; public DataStoreEntry(Object data, bool autoConvert) { this.data = data; this.autoConvert = autoConvert; } } private Hashtable data = new Hashtable(BackCompatibleStringComparer.Default); public DataStore() { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "DataStore: Constructed DataStore"); } public virtual Object GetData(string format, bool autoConvert) { Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "DataStore: GetData: " + format + ", " + autoConvert.ToString()); DataStoreEntry dse = (DataStoreEntry)data[format]; Object baseVar = null; if (dse != null) { baseVar = dse.data; } Object original = baseVar; if (autoConvert && (dse == null || dse.autoConvert) && (baseVar == null || baseVar is MemoryStream)) { string[] mappedFormats = GetMappedFormats(format); if (mappedFormats != null) { for (int i=0; i
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- NativeMethods.cs
- HttpWebResponse.cs
- InternalRelationshipCollection.cs
- EventHandlersDesigner.cs
- DataAdapter.cs
- CustomLineCap.cs
- log.cs
- CodeThrowExceptionStatement.cs
- ToolBar.cs
- ImageDrawing.cs
- StaticExtension.cs
- OpenTypeCommon.cs
- ExpressionVisitor.cs
- ActionFrame.cs
- ZoneLinkButton.cs
- Closure.cs
- initElementDictionary.cs
- MatrixTransform.cs
- PeerCollaboration.cs
- UserControlFileEditor.cs
- ApplicationContext.cs
- FlowDocumentPage.cs
- AsymmetricKeyExchangeDeformatter.cs
- SynchronizationLockException.cs
- ServiceBuildProvider.cs
- EnumValAlphaComparer.cs
- DataObjectCopyingEventArgs.cs
- TextTreeExtractElementUndoUnit.cs
- GPPOINTF.cs
- SendReply.cs
- CodeStatement.cs
- SqlFunctions.cs
- Debugger.cs
- TextEditorThreadLocalStore.cs
- TableRow.cs
- IndexOutOfRangeException.cs
- ConstraintEnumerator.cs
- CapabilitiesAssignment.cs
- FlowDocumentView.cs
- ApplicationContext.cs
- ConfigurationStrings.cs
- IconHelper.cs
- SqlServer2KCompatibilityAnnotation.cs
- _SSPIWrapper.cs
- DataGridrowEditEndingEventArgs.cs
- IpcServerChannel.cs
- Triplet.cs
- returneventsaver.cs
- OleDbInfoMessageEvent.cs
- XPathExpr.cs
- OAVariantLib.cs
- ParameterEditorUserControl.cs
- ExpressionNode.cs
- Accessible.cs
- DataRowComparer.cs
- ButtonBaseAdapter.cs
- PeerNodeTraceRecord.cs
- StringFormat.cs
- Rss20FeedFormatter.cs
- TraceProvider.cs
- WebResponse.cs
- FrameworkContentElement.cs
- SecurityTokenAuthenticator.cs
- NumberFormatInfo.cs
- UpdateCompiler.cs
- Selection.cs
- GeometryModel3D.cs
- WrappedIUnknown.cs
- PriorityChain.cs
- CalendarButton.cs
- UIElementParaClient.cs
- BorderGapMaskConverter.cs
- XPathExpr.cs
- SafeFileMapViewHandle.cs
- TemplateBuilder.cs
- DataComponentGenerator.cs
- OrderedHashRepartitionStream.cs
- ToolStripSeparator.cs
- Persist.cs
- RadioButtonPopupAdapter.cs
- KeySpline.cs
- AnimationException.cs
- ipaddressinformationcollection.cs
- _PooledStream.cs
- NestPullup.cs
- UrlAuthorizationModule.cs
- SingleResultAttribute.cs
- InfoCardRSAPKCS1KeyExchangeFormatter.cs
- DigestTraceRecordHelper.cs
- DomNameTable.cs
- RoutedEvent.cs
- UrlMappingCollection.cs
- BufferAllocator.cs
- SR.cs
- XPathNavigatorKeyComparer.cs
- CodeDesigner.cs
- AxisAngleRotation3D.cs
- InvokeProviderWrapper.cs
- AutomationEventArgs.cs
- DataServiceHostFactory.cs