I started trying to implement drag-and-drop of virtual files (from a C# 4/WPF app) with this codeproject tutorial. After spending some time trying to figure out a DV_E_FORMATETC error, I figured out I need to support the "Shell IDList Array" data format. But there seems to be next to zero documentation on what this format actually does.
After some searching, I found this page on advanced data transfer which said that a Shell IDList Array was a pointer to a CIDA structure. This CIDA structure then contains the number of PIDLs, and a list of offsets to them. So what the hell is a PIDL? After some more searching, this page sort of implies it's a pointer to an ITEMIDLIST, which itself contains a single member that is a list of SHITEMIDs.
I did some more reading, I still can't tell what multiple PIDLs are for, but there's one SHITEMID for each "level" in the path. At least that's one mystery solved.
My next idea was to try dragging a file from another application with virtual files (WinSCP). I just got a MemoryStream back for this format. At least I know what class to provide for the thing, but that doesn't help at all for explaining what to put in it. I tried examining this MemoryStream based on the formats in the links above, but I've had no success. I just got back garbage data, and one of the 'cb' fields told me it was 18000 bytes long when the whole stream was only 539 bytes.
In addition, upon further reading, this page seems to imply that the data contained in a PIDL actually winds up being a path, and examining the contents of said MemoryStream in a hex editor yielded a path inside my local Temp directory (split into parts, anyway).
It seems that WinSCP just uses a shell extension to handle dropping on explorer, something I really don't want to resort to. However, it has an alternate mode where it aborts the dragdrop until after it transfers to a temp folder - this is acceptable to me, but I haven't the faintest idea how to do it.
My questions are now:
Any help or even links that explain what I should be doing would be greatly appreciated.
Edit: So here's how I actually did it in the end:
I scrapped most of the code from the CodeProject tutorial above, keeping the functions for creating the FileGroupDescriptor. I then reimplemented the .Net IDataObject interface (and actually, I didn't have to use the COM IDataObject interface at all). I then am forced to synchronously download the file in the background, and pass a MemoryStream back out from GetData(). Conveniently, the actual copying is in the background, but the waiting for data is in the foreground. Thanks, explorer. Any reasonably large files are slow, but for now it "works" which is more than I can say for the past few weeks.
I did try passing the PipeStream class I use internally for transfers, but explorer isn't happy with this:
So, I'm not sure the ideal case is actually possible. Still, thanks for all of your help. I'm giving the bounty to JPW because his replies eventually set me on the right path.
I think C# File Browser at http://www.codeproject.com/KB/miscctrl/FileBrowser.aspx is what will help you the most right now.
These articles are invaluable.
C# does Shell, Part 1 at http://www.codeproject.com/KB/shell/csdoesshell1.aspx
C# does Shell, Part 2 at http://www.codeproject.com/KB/shell/csdoesshell2.aspx
C# does Shell, Part 3 at http://www.codeproject.com/KB/shell/csdoesshell3.aspx
C# does Shell, Part 4 at http://www.codeproject.com/KB/shell/csdoesshell4.spx
Edanmo.ShellExtensions is an absolute must have. http://www.mvps.org/emorcillo/en/code/shell/shellextensions.shtml
Note that some of these COM Interfaces are already defined in .NET 2.0. (I have not checked 4.0, but I doubt Microsoft added any additional support for the Shell/COM Interfaces.)
Implementing a Folder View from http://msdn.microsoft.com/en-us/library/cc144092.aspx
Transferring Shell Objects with Drag-and-Drop and the Clipboard from http://msdn.microsoft.com/en-us/library/bb776905.aspx
Implementing the Basic Folder Object Interfaces from http://msdn.microsoft.com/en-us/library/cc144093.aspx
The Complete Idiot's Guide to Writing Shell Extensions - Index, By Michael Dunn, An index of all the articles in the Idiot's Guide from http://www.codeproject.com/KB/shell/shellextguideindex.aspx (These are the articles that helped me the most.)
The Complete Idiot's Guide to Writing Namespace Extensions - Part I at http://www.codeproject.com/kb/shell/namespcextguide1.aspx. Is the what you are looking for?
Disclaimer: I'm neither an expert in Windows Shell programming nor in COM programming, and especially not in COM programming using .NET.
Disclaimer 2: Shell programming is rather complex and Windows Explorer is likely to crash. (Be sure to read the information on MSDN on debugging shell extensions.)
This is what I can provide to answer your questions:
I hope some information will be usefull to you.
Edit: You could also implement QueryGetData and EnumerableFormatEtc appropriately to indicate that your object does not support the format in question. Maybe Windows Explorer tries a different format then.
Edit 2: Though you've already settled on a solution, here is a some more information on how to drag and drop asynchronously (for large files), maybe you (or at least somebody looking for an answer to a simulary problem, who reads this) find it useful: http://msdn.microsoft.com/en-us/library/bb776904(VS.85).aspx#async
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With