What is the IFileOperation
equivalent of
SHFILEOPSTRUCTW op = {hDlg, FO_COPY, directoryFrom, directoryTo, 0, FALSE, NULL, NULL};
int status = SHFileOperationW(&op);
where directoryFrom
is a directory path relative to my working directory and directoryTo
is absolute?
SHCreateItemFromParsingName
to get an IShellItem
? What are parsing names and display names, anyway?SHCreateItemFromParsingName
is appropriate for absolute paths, should I use it in conjunction with GetFullPathNameW
to resolve the relative path or is there a simpler alternative?I am finding the documentation on those topics could be much better.
The Windows Shell is organized into a hierarchy called the Shell namespace: Introduction to the Shell Namespace:
The Shell namespace organizes the file system and other objects managed by the Shell into a single tree-structured hierarchy. Conceptually, it is a larger and more inclusive version of the file system.
What it means is, in the Shell Namespace, there are file system (or what I call "physical", considering possible kernel file systems as physical too) items and virtual items. Example of virtual items are:
All these items are identified using the same system: PIDLs. A PIDL is to a Shell Item what a full file path is to a (physical) file or folder.
Items can also be identified using their Parsing Name which is indirectly defined by IShellFolder::GetDisplayNameOf method and by _SHGDNF enumeration, if the containing folder supports it. Note a PIDL is strictly mandatory (each item has one) while a parsing name is not.
Since Windows Vista, it's recommended to use IShellItem
-based API. And IFileDialog
is also recommended because it supports PIDLs (=> virtual items), not only file system paths.
The pseudo code for SHCreateItemFromParsingName
is more or less:
SHParseDisplayName(name)
=> a PIDL (old PIDL-based API)SHCreateItemFromIDList(pidl)
=> an IShellItemWhich indeed proves that SHCreateItemFromParsingName
could have been called SHCreateItemFromDisplayName
...
Internally, SHParseDisplayName
's code is more or less:
IShellFolder
(desktop is the root of the Shell's namespace)IShellFolder::ParseDisplayName
(name) => a PIDL (relative to desktop which is the same as absolute since desktop is the namespace root)IShellFolder
is the interface implemented by all namespace folders: standard Windows-provided ones and custom ones, serving file system items or virtual items.
Now, IShellFolder::ParseDisplayName
implementation vary. A custom Shell Folder can choose to implement it the way it likes (which can cause issues).
However desktop's IShellFolder
implementation is quite complex and understands file system paths in lieu of display name. The doc says this:
A null-terminated Unicode string with the display name. Because each Shell folder defines its own parsing syntax, the form this string can take may vary. The desktop folder, for instance, accepts paths such as "C:\My Docs\My File.txt". It also will accept references to items in the namespace that have a GUID associated with them using the "::{GUID}" syntax. For example, to retrieve a fully qualified identifier list for the control panel from the desktop folder, you can use the following:
::{CLSID for Control Panel}\::{CLSID for printers folder}