예제 #1
0
        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);
                }
            }
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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);
            }
        }
예제 #6
0
        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);
                }
            }
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
                }
            }
        }