private void ExtractFiles() { //Get filenames being dragged log.Debug("Getting filenames"); string[] filenames = DataObjectHelper.GetFilenames(this.innerData); log.DebugFormat("Filenames: {0}", string.Join(",", filenames)); //Get temporary folder log.Debug("Creating temp folder"); string tempPath = FileUtility.GetTempPath(); log.DebugFormat("Temp folder: {0}", tempPath); //Save files to temporary directory tempFilenames = new string[filenames.Length]; for (int fileIndex = 0; fileIndex < filenames.Length; fileIndex++) { tempFilenames[fileIndex] = FileUtility.GetUniqueFilename(Path.Combine(tempPath, filenames[fileIndex])); log.DebugFormat("Extracting file {0}", filenames[fileIndex]); using (FileStream fs = new FileStream(tempFilenames[fileIndex], FileMode.Create)) { DataObjectHelper.ReadFileContents(this.innerData, fileIndex, fs); } } }
public static int DoDragDropHook(NativeMethods.IDataObject pDataObj, NativeMethods.IDropSource pDropSource, uint dwOKEffects, uint[] pdwEffect) { try { log.Info("Drag started"); if (!DataObjectHelper.GetDataPresent(pDataObj, "FileGroupDescriptorW")) { log.Info("No virtual files found -- continuing original drag"); return(NativeMethods.DoDragDrop(pDataObj, pDropSource, dwOKEffects, pdwEffect)); } //Start new drag log.Info("Virtual files found -- starting new drag adding CF_HDROP format"); log.InfoFormat("Files: {0}", string.Join(",", DataObjectHelper.GetFilenames(pDataObj))); NativeMethods.IDataObject newDataObj = new OutlookDataObject(pDataObj); int result = NativeMethods.DoDragDrop(newDataObj, pDropSource, dwOKEffects, pdwEffect); //Get result log.InfoFormat("DoDragDrop result: {0}", result); return(result); } catch (Exception ex) { log.Warn("Dragging error", ex); return(NativeMethods.DRAGDROP_S_CANCEL); } }
public int GetData(ref FORMATETC format, out STGMEDIUM medium) { try { //Get data into passed medium log.DebugFormat("IDataObject.GetData called -- cfFormat {0} dwAspect {1} lindex {2} ptd {3} tymed {4}", format.cfFormat, format.dwAspect, format.lindex, format.ptd, format.tymed); log.DebugFormat("Format name: {0}", System.Windows.Forms.DataFormats.GetFormat((ushort)format.cfFormat).Name); if (format.cfFormat == NativeMethods.CF_HDROP) { medium = new STGMEDIUM(); //Validate index if (format.lindex != -1) { return(NativeMethods.DV_E_LINDEX); } //Validate medium type if (!format.tymed.HasFlag(TYMED.TYMED_HGLOBAL)) { return(NativeMethods.DV_E_TYMED); } //Validate DV aspect if (format.dwAspect != DVASPECT.DVASPECT_CONTENT) { return(NativeMethods.DV_E_DVASPECT); } //Extract files if not already extracted if (tempFilenames == null) { ExtractFiles(); } //Get list of dropped files log.Debug("Setting drop files"); DataObjectHelper.SetDropFiles(ref medium, tempFilenames); FilesDropped = true; return(NativeMethods.S_OK); } else if (format.cfFormat == NativeMethods.CF_TEXT || format.cfFormat == NativeMethods.CF_UNICODETEXT || format.cfFormat == (ushort)DataObjectHelper.GetClipboardFormat("Csv")) { //Do not return text formats -- some applications try to get text before files medium = new STGMEDIUM(); return(NativeMethods.DV_E_FORMATETC); } else { int result = innerData.GetData(format, out medium); log.DebugFormat("Result: {0}", result); return(result); } } catch (Exception ex) { log.Error("Exception in IDataObject.GetData", ex); medium = new STGMEDIUM(); return(NativeMethods.E_UNEXPECTED); } }
public static int DoDragDropHook(NativeMethods.IDataObject pDataObj, IntPtr pDropSource, uint dwOKEffects, out uint pdwEffect) { try { log.Info("Drag started"); if (!DataObjectHelper.GetDataPresent(pDataObj, "FileGroupDescriptorW") && !DataObjectHelper.GetDataPresent(pDataObj, "FileGroupDescriptor")) { log.Info("No virtual files found -- continuing original drag"); return(NativeMethods.DoDragDrop(pDataObj, pDropSource, dwOKEffects, out pdwEffect)); } //Start new drag log.Info("Virtual files found -- starting new drag adding CF_HDROP format"); log.InfoFormat("Files: {0}", string.Join(",", DataObjectHelper.GetFilenames(pDataObj))); OutlookDataObject newDataObj = new OutlookDataObject(pDataObj); int result = NativeMethods.DoDragDrop(newDataObj, pDropSource, dwOKEffects, out pdwEffect); //If files were dropped and drop effect was "move", then override to "copy" so original item is not deleted if (newDataObj.FilesDropped && pdwEffect == NativeMethods.DROPEFFECT_MOVE) { pdwEffect = NativeMethods.DROPEFFECT_COPY; } //Get result log.InfoFormat("DoDragDrop effect: {0} result: {1}", pdwEffect, result); return(result); } catch (Exception ex) { log.Warn("Dragging error", ex); pdwEffect = NativeMethods.DROPEFFECT_NONE; return(NativeMethods.DRAGDROP_S_CANCEL); } }
internal static string[] GetFilenamesAnsi(NativeMethods.IDataObject data) { IntPtr fgdaPtr = IntPtr.Zero; try { //Define FileGroupDescriptor format FORMATETC format = new FORMATETC(); format.cfFormat = (short)System.Windows.Forms.DataFormats.GetFormat("FileGroupDescriptor").Id; format.dwAspect = DVASPECT.DVASPECT_CONTENT; format.lindex = -1; format.ptd = IntPtr.Zero; format.tymed = TYMED.TYMED_ISTREAM | TYMED.TYMED_ISTORAGE | TYMED.TYMED_HGLOBAL; //Query if format exists in data if (data.QueryGetData(format) != NativeMethods.S_OK) { return(null); } //Get data into medium STGMEDIUM medium = new STGMEDIUM(); data.GetData(format, out medium); //Read medium into byte array byte[] bytes; using (MemoryStream stream = new MemoryStream()) { DataObjectHelper.ReadMediumIntoStream(medium, stream); bytes = new byte[stream.Length]; stream.Seek(0, SeekOrigin.Begin); stream.Read(bytes, 0, bytes.Length); } //Copy the file group descriptor into unmanaged memory fgdaPtr = Marshal.AllocHGlobal(bytes.Length); Marshal.Copy(bytes, 0, fgdaPtr, bytes.Length); //Marshal the unmanaged memory to a FILEGROUPDESCRIPTORA struct object fgdObj = Marshal.PtrToStructure(fgdaPtr, typeof(NativeMethods.FILEGROUPDESCRIPTORA)); NativeMethods.FILEGROUPDESCRIPTORA fgd = (NativeMethods.FILEGROUPDESCRIPTORA)fgdObj; //Create an array to store file names string[] filenames = new string[fgd.cItems]; //Get the pointer to the first file descriptor IntPtr fdPtr = (IntPtr)((int)fgdaPtr + Marshal.SizeOf(fgdaPtr)); //Loop for the number of files acording to the file group descriptor for (int fdIndex = 0; fdIndex < fgd.cItems; fdIndex++) { //Marshal the pointer to the file descriptor as a FILEDESCRIPTORA struct object fdObj = Marshal.PtrToStructure(fdPtr, typeof(NativeMethods.FILEDESCRIPTORA)); NativeMethods.FILEDESCRIPTORA fd = (NativeMethods.FILEDESCRIPTORA)fdObj; //Get filename of file descriptor and put in array filenames[fdIndex] = fd.cFileName; //Move the file descriptor pointer to the next file descriptor fdPtr = (IntPtr)((int)fdPtr + Marshal.SizeOf(fd)); } return(filenames); } finally { Marshal.FreeHGlobal(fgdaPtr); } }
public int EnumFormatEtc(DATADIR direction, out IEnumFORMATETC ppenumFormatEtc) { IEnumFORMATETC origEnum = null; try { log.DebugFormat("IDataObject.EnumFormatEtc called -- direction {0}", direction); switch (direction) { case DATADIR.DATADIR_GET: //Get original enumerator int result = innerData.EnumFormatEtc(direction, out origEnum); if (result != NativeMethods.S_OK) { ppenumFormatEtc = null; return(result); } //Enumerate original formats List <FORMATETC> formats = new List <FORMATETC>(); FORMATETC[] buffer = new FORMATETC[] { new FORMATETC() }; while (origEnum.Next(1, buffer, null) == NativeMethods.S_OK) { //Convert format from short to unsigned short ushort cfFormat = (ushort)buffer[0].cfFormat; //Do not return text formats -- some applications try to get text before files if (cfFormat != NativeMethods.CF_TEXT && cfFormat != NativeMethods.CF_UNICODETEXT && cfFormat != (ushort)DataObjectHelper.GetClipboardFormat("Csv")) { formats.Add(buffer[0]); } } //Add CF_HDROP format FORMATETC format = new FORMATETC(); format.cfFormat = NativeMethods.CF_HDROP; format.dwAspect = DVASPECT.DVASPECT_CONTENT; format.lindex = -1; format.ptd = IntPtr.Zero; format.tymed = TYMED.TYMED_HGLOBAL; formats.Add(format); //Return new enumerator for available formats ppenumFormatEtc = new FormatEtcEnumerator(formats.ToArray()); return(NativeMethods.S_OK); case DATADIR.DATADIR_SET: //Return original enumerator return(innerData.EnumFormatEtc(direction, out ppenumFormatEtc)); default: //Invalid direction ppenumFormatEtc = null; return(NativeMethods.E_INVALIDARG); } } catch (Exception ex) { log.Error("Exception in IDataObject.EnumFormatEtc", ex); ppenumFormatEtc = null; return(NativeMethods.E_UNEXPECTED); } finally { //Release all unmanaged objects if (origEnum != null) { Marshal.ReleaseComObject(origEnum); } } }
public int QueryGetData(ref FORMATETC format) { try { log.DebugFormat("IDataObject.QueryGetData called -- cfFormat {0} dwAspect {1} lindex {2} ptd {3} tymed {4}", format.cfFormat, format.dwAspect, format.lindex, format.ptd, format.tymed); log.DebugFormat("Format name: {0}", System.Windows.Forms.DataFormats.GetFormat((ushort)format.cfFormat).Name); if (format.cfFormat == NativeMethods.CF_HDROP) { //Validate index if (format.lindex != -1) { return(NativeMethods.DV_E_LINDEX); } //Validate medium type if (!format.tymed.HasFlag(TYMED.TYMED_HGLOBAL)) { return(NativeMethods.DV_E_TYMED); } //Validate DV aspect if (format.dwAspect != DVASPECT.DVASPECT_CONTENT) { return(NativeMethods.DV_E_DVASPECT); } log.DebugFormat("IDataObject.QueryGetData result: {0}", NativeMethods.S_OK); return(NativeMethods.S_OK); } else if (format.cfFormat == NativeMethods.CF_TEXT || format.cfFormat == NativeMethods.CF_UNICODETEXT || format.cfFormat == (ushort)DataObjectHelper.GetClipboardFormat("Csv")) { //Do not return text formats -- some applications try to get text before files return(NativeMethods.DV_E_FORMATETC); } else { int result = innerData.QueryGetData(format); log.DebugFormat("Result: {0}", result); return(result); } } catch (Exception ex) { log.Error("Exception in IDataObject.QueryGetData", ex); return(NativeMethods.E_UNEXPECTED); } }
internal static string[] GetFilenamesUnicode(NativeMethods.IDataObject data) { log.Debug("Getting filenames (Unicode)"); IntPtr fgdaPtr = IntPtr.Zero; STGMEDIUM medium = new STGMEDIUM(); try { //Define FileGroupDescriptorW format FORMATETC format = new FORMATETC(); format.cfFormat = (short)System.Windows.Forms.DataFormats.GetFormat("FileGroupDescriptorW").Id; format.dwAspect = DVASPECT.DVASPECT_CONTENT; format.lindex = -1; format.ptd = IntPtr.Zero; format.tymed = TYMED.TYMED_ISTREAM | TYMED.TYMED_ISTORAGE | TYMED.TYMED_HGLOBAL; //Query if format exists in data if (data.QueryGetData(format) != NativeMethods.S_OK) { log.Debug("No filenames found"); return(null); } //Get data into medium medium = new STGMEDIUM(); data.GetData(format, out medium); //Read medium into byte array log.Debug("Reading structure into memory stream"); byte[] bytes; using (MemoryStream stream = new MemoryStream()) { DataObjectHelper.ReadMediumIntoStream(medium, stream); bytes = new byte[stream.Length]; stream.Seek(0, SeekOrigin.Begin); stream.Read(bytes, 0, bytes.Length); } //Copy the file group descriptor into unmanaged memory log.Debug("Copying structure into unmanaged memory"); fgdaPtr = Marshal.AllocHGlobal(bytes.Length); if (fgdaPtr == IntPtr.Zero) { throw new OutOfMemoryException(); } Marshal.Copy(bytes, 0, fgdaPtr, bytes.Length); //Marshal the unmanaged memory to a FILEGROUPDESCRIPTORW struct log.Debug("Marshaling unmanaged memory into FILEGROUPDESCRIPTORW struct"); object fgdObj = Marshal.PtrToStructure(fgdaPtr, typeof(NativeMethods.FILEGROUPDESCRIPTORW)); NativeMethods.FILEGROUPDESCRIPTORW fgd = (NativeMethods.FILEGROUPDESCRIPTORW)fgdObj; log.Debug(string.Format("Files found: {0}", fgd.cItems)); //Create an array to store file names string[] filenames = new string[fgd.cItems]; //Get the pointer to the first file descriptor IntPtr fdPtr = IntPtr.Add(fgdaPtr, sizeof(uint)); //Loop for the number of files acording to the file group descriptor for (int fdIndex = 0; fdIndex < fgd.cItems; fdIndex++) { log.DebugFormat("Getting filename {0}", fdIndex); //Marshal the pointer to the file descriptor as a FILEDESCRIPTORW struct object fdObj = Marshal.PtrToStructure(fdPtr, typeof(NativeMethods.FILEDESCRIPTORW)); NativeMethods.FILEDESCRIPTORW fd = (NativeMethods.FILEDESCRIPTORW)fdObj; //Get filename of file descriptor and put in array filenames[fdIndex] = fd.cFileName; //Move the file descriptor pointer to the next file descriptor fdPtr = IntPtr.Add(fdPtr, Marshal.SizeOf(fd)); } log.DebugFormat("Filenames found: {0}", string.Join(", ", filenames)); return(filenames); } finally { //Release all unmanaged objects Marshal.FreeHGlobal(fgdaPtr); if (medium.pUnkForRelease == null) { NativeMethods.ReleaseStgMedium(ref medium); } } }