/// <summary> /// Create an OleDataObject from a .NET IDataObject. /// </summary> /// <param name="ido">IDataObject to extract OleDataObject from</param> /// <returns>A new instance of OleDataObject mapped to the inner /// OleDataObject of the specified IDataObject or null if unable /// to extract OleDataObject from IDataObject</returns> public static OleDataObject CreateFrom(IDataObject ido) { // initialize OleDataObject OleDataObject oleDataObject = new OleDataObject(); // attempt to convert to concrete DataObject class DataObject dataObject = ido as DataObject; if (dataObject == null) { return(null); } // To extract an OleDataObject from a DataObject, we first need to // get the "innerData" field of the DataObject. This field is of type // System.Windows.Forms.UnsafeNativeMethods.OleConverter. Next, we // need to get the "innerData" field of the OleConverter, which is of // type System.Windows.Forms.UnsafeNativeMethods.IOleDataObject const string INNER_DATA_FIELD = "innerData"; object innerData = oleDataObject.GetField(dataObject, INNER_DATA_FIELD); object innerInnerData = oleDataObject.GetField(innerData, INNER_DATA_FIELD); // attempt to convert the 'private' ole data object contained in // innerData into an instance of our locally defined IOleDataObject oleDataObject.m_dataObject = innerInnerData as IOleDataObject; if (oleDataObject.m_dataObject != null) { return(oleDataObject); } else { return(null); } }
/// <summary> /// Create an OleDataObject from a .NET IDataObject. /// </summary> /// <param name="ido">IDataObject to extract OleDataObject from</param> /// <returns>A new instance of OleDataObject mapped to the inner /// OleDataObject of the specified IDataObject or null if unable /// to extract OleDataObject from IDataObject</returns> public static OleDataObject CreateFrom(IDataObject ido) { // initialize OleDataObject OleDataObject oleDataObject = new OleDataObject(); // attempt to convert to concrete DataObject class DataObject dataObject = ido as DataObject; if (dataObject == null) { return null; } // To extract an OleDataObject from a DataObject, we first need to // get the "innerData" field of the DataObject. This field is of type // System.Windows.Forms.UnsafeNativeMethods.OleConverter. Next, we // need to get the "innerData" field of the OleConverter, which is of // type System.Windows.Forms.UnsafeNativeMethods.IOleDataObject const string INNER_DATA_FIELD = "innerData"; object innerData = oleDataObject.GetField(dataObject, INNER_DATA_FIELD); object innerInnerData = oleDataObject.GetField(innerData, INNER_DATA_FIELD); // attempt to convert the 'private' ole data object contained in // innerData into an instance of our locally defined IOleDataObject oleDataObject.m_dataObject = innerInnerData as IOleDataObject; if (oleDataObject.m_dataObject != null) { return oleDataObject; } else { return null; } }
/// <summary> /// Create an OleDataObject from a native Ole data object /// </summary> /// <param name="odo">native ole data object</param> /// <returns>newly created OleDataObject</returns> public static OleDataObject CreateFrom(IOleDataObject odo) { OleDataObject oleDataObject = new OleDataObject(); oleDataObject.m_dataObject = odo; return(oleDataObject); }
/// <summary> /// Initialize using file meta-info and the OleDataObject from which /// to fetch the file contents when it is time to write them /// </summary> /// <param name="fileDescriptor"></param> /// <param name="dataObject"></param> /// <param name="fileIndex"></param> private FileItemFromFileContents( FileDescriptor fileDescriptor, OleDataObject oleDataObject, int fileIndex) : base(fileDescriptor.fileName) { this.fileDescriptor = fileDescriptor; this.oleDataObject = oleDataObject; this.fileIndex = fileIndex; }
/// <summary> /// Create an array of FileItem objects based on a data object that contains /// FileContents /// </summary> /// <param name="dataObject">data object containing FileContents</param> /// <returns>Array of FileItem objects. Returns null if the FileContents /// could not be extracted from the passed dataObject</returns> public static FileItem[] CreateArrayFromDataObject(IDataObject dataObject) { try { // get the ole data object OleDataObject oleDataObject = OleDataObject.CreateFrom(dataObject); if (oleDataObject == null) { Debug.Fail("Unable to access OleDataObject!"); return(null); } // get an array of file descriptors specifying the file contents FileDescriptor[] fileDescriptors = FileContentsHelper.GetFileDescriptors(dataObject); // allocate a FileItem object for each descriptor FileItem[] fileItems = new FileItem[fileDescriptors.Length]; // initialize the file items for (int i = 0; i < fileDescriptors.Length; i++) { fileItems[i] = new FileItemFromFileContents( fileDescriptors[i], oleDataObject, i); } // return the file items return(fileItems); } // this is a sketchy operation involving all kinds of interop voodoo, // if we fail in release mode it is likely due to a drop source giving // us invalid or unexpected data -- handle this gracefully while // logging the error catch (Exception e) { Debug.Fail("Unexpected error accessing FileContents", e.Message); return(null); } }
/// <summary> /// Utility function to extract an array of file contents file descriptors from /// an IDataObject instnace /// </summary> /// <param name="dataObject">data object to extract descriptors from</param> /// <returns>array of file descriptors</returns> public static FileDescriptor[] GetFileDescriptors(IDataObject dataObject) { // Use an OleDataObject OleDataObject oleDataObject = OleDataObject.CreateFrom(dataObject); if (oleDataObject == null) { const string message = "DataObject not valid for FileContents!"; Debug.Fail(message); throw new InvalidOperationException(message); } // Try to get the data as FileGroupDescriptorW then try to get it // as FileGroupDescriptor bool bFileNameIsWide; OleStgMediumHGLOBAL stgMedium = (OleStgMediumHGLOBAL)oleDataObject.GetData( DataFormatsEx.FileGroupDescriptorWFormat, TYMED.HGLOBAL); if (stgMedium != null) { bFileNameIsWide = true; } else { stgMedium = (OleStgMediumHGLOBAL)oleDataObject.GetData( DataFormatsEx.FileGroupDescriptorFormat, TYMED.HGLOBAL); if (stgMedium != null) { bFileNameIsWide = false; } else { const string message = "File group descriptor not available!"; Debug.Fail(message); throw new InvalidOperationException(message); } } // Copy the descriptors using ( stgMedium ) { using (HGlobalLock globalMem = new HGlobalLock(stgMedium.Handle)) { // get a pointer to the count IntPtr pCount = globalMem.Memory; // determine the number of file descriptors Int32 count = Marshal.ReadInt32(pCount); // get a pointer to the descriptors IntPtr pDescriptors = new IntPtr(globalMem.Memory.ToInt32() + Marshal.SizeOf(count)); // allocate the array of structures that will be returned FileDescriptor[] descriptors = new FileDescriptor[count]; // determine the sizes of the various data elements const int FILENAME_BUFFER_SIZE = 260; int headerSize = Marshal.SizeOf(typeof(FILEDESCRIPTOR_HEADER)); int fileNameSize = bFileNameIsWide ? FILENAME_BUFFER_SIZE * 2 : FILENAME_BUFFER_SIZE; int totalSize = headerSize + fileNameSize; // iterate through the memory block copying the FILEDESCRIPTOR structures for (int i = 0; i < count; i++) { // determine the addresses of the various data elements IntPtr pAddr = new IntPtr(pDescriptors.ToInt32() + (i * totalSize)); IntPtr pFileNameAddr = new IntPtr(pAddr.ToInt32() + headerSize); // copy the header descriptors[i].header = (FILEDESCRIPTOR_HEADER) Marshal.PtrToStructure(pAddr, typeof(FILEDESCRIPTOR_HEADER)); // copy the file name (use Unicode or Ansi depending upon descriptor type) if (bFileNameIsWide) { descriptors[i].fileName = Marshal.PtrToStringUni(pFileNameAddr); } else { descriptors[i].fileName = Marshal.PtrToStringAnsi(pFileNameAddr); } } // return the descriptors return(descriptors); } } }
/// <summary> /// Create an OleDataObject from a native Ole data object /// </summary> /// <param name="odo">native ole data object</param> /// <returns>newly created OleDataObject</returns> public static OleDataObject CreateFrom(IOleDataObject odo) { OleDataObject oleDataObject = new OleDataObject(); oleDataObject.m_dataObject = odo; return oleDataObject; }
/// <summary> /// Initialize using file meta-info and the OleDataObject from which /// to fetch the file contents when it is time to write them /// </summary> /// <param name="fileDescriptor"></param> /// <param name="dataObject"></param> /// <param name="fileIndex"></param> private FileItemFromFileContents( FileDescriptor fileDescriptor, OleDataObject oleDataObject, int fileIndex) : base(fileDescriptor.fileName) { this.fileDescriptor = fileDescriptor; this.oleDataObject = oleDataObject; this.fileIndex = fileIndex; }