/// <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); } } }