Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / DataObject.cs / 1458001 / 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;
///
///
/// Implements a basic data transfer mechanism.
///
[
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();
///
///
/// Initializes a new instance of the class, with the specified .
///
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, which can store arbitrary data.
///
///
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, containing the specified 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 and its
/// associated format.
///
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;
}
///
///
/// 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, 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.
///
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 class
/// type 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);
}
///
///
/// Determines whether data stored in this instance is
/// associated with, or can be converted to, the specified
/// 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 the specified format, using an automatic conversion
/// parameter to determine whether to convert the data to the 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, or can be converted to, the specified
/// 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;
}
///
///
/// 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(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.
///
public virtual string[] GetFormats() {
Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check formats:");
return GetFormats(true);
}
// <-- WHIDBEY ADDITIONS
///
///
/// [To be supplied.]
///
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 -->
///
///
/// 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 [....] dataObject. This is the core
/// of [....] 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) {
if (handle != IntPtr.Zero) {
UnsafeNativeMethods.GlobalFree(new HandleRef(null, handle));
}
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;
}
///
///
/// 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, 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.
///
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 class type 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 in
/// this instance, using the class of the data for the format.
///
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);
}
///
///
/// 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;
///
///
/// Implements a basic data transfer mechanism.
///
[
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();
///
///
/// Initializes a new instance of the class, with the specified .
///
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, which can store arbitrary data.
///
///
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, containing the specified 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 and its
/// associated format.
///
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;
}
///
///
/// 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, 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.
///
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 class
/// type 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);
}
///
///
/// Determines whether data stored in this instance is
/// associated with, or can be converted to, the specified
/// 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 the specified format, using an automatic conversion
/// parameter to determine whether to convert the data to the 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, or can be converted to, the specified
/// 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;
}
///
///
/// 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(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.
///
public virtual string[] GetFormats() {
Debug.WriteLineIf(CompModSwitches.DataObject.TraceVerbose, "Check formats:");
return GetFormats(true);
}
// <-- WHIDBEY ADDITIONS
///
///
/// [To be supplied.]
///
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 -->
///
///
/// 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 [....] dataObject. This is the core
/// of [....] 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) {
if (handle != IntPtr.Zero) {
UnsafeNativeMethods.GlobalFree(new HandleRef(null, handle));
}
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;
}
///
///
/// 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, 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.
///
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 class type 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 in
/// this instance, using the class of the data for the format.
///
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);
}
///
///
/// 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
- cookie.cs
- CollaborationHelperFunctions.cs
- SoapObjectWriter.cs
- BinaryWriter.cs
- IisTraceWebEventProvider.cs
- TdsParserHelperClasses.cs
- DescendentsWalkerBase.cs
- RTLAwareMessageBox.cs
- DesignBinding.cs
- PreDigestedSignedInfo.cs
- NamespaceQuery.cs
- OdbcDataAdapter.cs
- RightsManagementEncryptedStream.cs
- GPRECT.cs
- _SSPISessionCache.cs
- CodeAccessPermission.cs
- OperatingSystem.cs
- ExpandoClass.cs
- RsaKeyIdentifierClause.cs
- SpeechUI.cs
- CompositeActivityCodeGenerator.cs
- InvalidWMPVersionException.cs
- DateTime.cs
- MyContact.cs
- UIHelper.cs
- DeploymentSectionCache.cs
- cookiecollection.cs
- StyleXamlParser.cs
- ClientBuildManagerTypeDescriptionProviderBridge.cs
- StateItem.cs
- Boolean.cs
- SeparatorAutomationPeer.cs
- SqlConnectionString.cs
- XPathItem.cs
- DefaultAssemblyResolver.cs
- Helper.cs
- TreeViewImageKeyConverter.cs
- Vector3DAnimationBase.cs
- mactripleDES.cs
- TemplateGroupCollection.cs
- DispatcherOperation.cs
- _Semaphore.cs
- Vector3DIndependentAnimationStorage.cs
- Attributes.cs
- ProgressPage.cs
- HttpWebRequestElement.cs
- InvalidWMPVersionException.cs
- UmAlQuraCalendar.cs
- ToolStripComboBox.cs
- TextTreeNode.cs
- ByteAnimationBase.cs
- FloaterParagraph.cs
- XmlReaderDelegator.cs
- TableLayoutSettings.cs
- Image.cs
- CodePageEncoding.cs
- OutputCacheSettings.cs
- XmlSerializationGeneratedCode.cs
- DataReaderContainer.cs
- Splitter.cs
- CollectionViewGroupInternal.cs
- MenuItemStyleCollection.cs
- DrawingContext.cs
- MonthChangedEventArgs.cs
- PackWebRequest.cs
- NotImplementedException.cs
- RowVisual.cs
- IdnMapping.cs
- ManagementScope.cs
- Axis.cs
- FieldMetadata.cs
- diagnosticsswitches.cs
- Metadata.cs
- CredentialCache.cs
- NumberFunctions.cs
- HashCodeCombiner.cs
- VerticalAlignConverter.cs
- NamedPipeProcessProtocolHandler.cs
- ResourceManagerWrapper.cs
- DataPagerFieldCommandEventArgs.cs
- Vector3DCollection.cs
- StreamGeometry.cs
- Identifier.cs
- InvalidEnumArgumentException.cs
- DataGridViewSelectedRowCollection.cs
- JavaScriptObjectDeserializer.cs
- QueryCreatedEventArgs.cs
- Common.cs
- ZipFileInfo.cs
- ConditionalAttribute.cs
- CompilerTypeWithParams.cs
- SAPIEngineTypes.cs
- TextEvent.cs
- DefaultParameterValueAttribute.cs
- ImageMap.cs
- UnregisterInfo.cs
- CfgParser.cs
- CommandDevice.cs
- ReadWriteSpinLock.cs
- TransactionOptions.cs