How do I set the initial directory of the File Open dialog to a virtual directory?


A customer reported that they had been setting the lpstrInitialDir member of the OPENFILENAME structure to "::{645FF040-5081-101B-9F08-00AA002F954E}" in order to have the dialog's default directory be the Recycle Bin. (I am not making this up.) They reported that this stopped working in Windows Vista and wanted to know why, and what they can do about it.

The lpstrInitialDir is supposed to be the name of a directory. Virtual folders are not directories. It so happened that virtual directories were accepted in Windows XP due to a bug: The file dialog uses the Path­Combine function¹ to combine the current directory with the lpstrInitialDir. The Path­Combine function checks whether the second parameter (lpstrInitialDir) is an absolute or relative path, and in Windows XP it had a bug that if the second parameter's second character was a colon, then it assumed that the path was absolute. It did this without verifying that the first character was a letter.

Windows Vista fixed this bug in the Path­Combine function, which means that if you passed an lpstrInitialDir of "::{...}", the function said, "Oh, you almost fooled me there, but I'm onto you. That is not an absolute path. So I will combine it with the first parameter (the current directory)." The file dialog then says, "Let's go to that folder!", but it can't (because there is no folder called ::{...} in the current directory), so it falls back to the Documents folder.

That explains why the undefined behavior changed. But what's the supported way of setting the initial directory to a virtual directory?

You use the IFile­Dialog interface, which gives you more control over the file open dialog than OPENFILENAME does. In particular, you can use the IFile­Dialog::Set­Default­Folder method.

Here's a Little Program to demonstrate. Remember that Little Programs do little to no error checking. Today's smart pointer library is (rolls dice) nothing! We're going to use raw pointers.

#define STRICT
#define STRICT_TYPED_ITEMIDS
#include <windows.h>
#include <shlobj.h>
#include <knownfolders.h>

int WINAPI WinMain(
    HINSTANCE hinst, HINSTANCE hinstPrev,
    LPSTR lpCmdLine, int nShowCmd)
{
    CCoInitialize init;

    IFileDialog* pfd;
    CoCreateInstance(CLSID_FileOpenDialog, nullptr,
        CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));

    IShellItem* psi;
    SHGetKnownFolderItem(FOLDERID_RecycleBinFolder,
        KF_FLAG_DEFAULT, nullptr, IID_PPV_ARGS(&psi));
    pfd->SetDefaultFolder(psi);
    psi->Release();

    // ... other initialization goes here ...

    pfd->Show(nullptr);

    // ... process the results ...

    pfd->Release();

    return 0;
}

We create the file open dialog and set its default folder to the Recycle Bin. In a real program, there would be additional initialization of the dialog, but in this Little Program, we'll accept all the other defaults. We then show the dialog with no owner (because our program doesn't have a main window). Observe that the default initial directory is the Recycle Bin.

¹ The Path­Combine function has been superseded by the Path­Cch­Combine function and its friends, which support NT-style paths and extra-long paths.

Comments (9)

  1. Boris says:

    Ok, but why was Recycle Bin the default directory? Was this some kind of advanced file restoration dialog?

    1. pc says:

      Hopefully. Might not even need to be that advanced; I could easily imagine a program that stored its data as a series of files and let one delete them within the program easily (something with an interface like an email program, perhaps tracking incoming Widget Orders or To-do List items or whatever). And, to delete it just sends to the built-in Recycle Bin, which seems like perfectly reasonable behavior. Then, rather than having the user dig around in their system’s Recycle Bin themselves, it offers a handy undelete dialog that opens up the Recycle Bin but filtered to the file type the application uses for its documents.

      But since everything’s handled directly with files, it integrates nicely with backups and people transferring items via email or some other means if needed, too.

      I don’t know anything about this particular program, but just “I want a file open dialog defaulting to the Recycle Bin” doesn’t bring up huge red flags for me, since I can see a use for it. And it’s not likely something that has a built-in MSDN sample program.

  2. Kemp says:

    I think I’m missing a piece of information explaining why the original way worked (and why it working is classed as a bug).

    1. skSdnW says:

      It worked because the old open dialog has very limited PIDL support (CDM_GETFOLDERIDLIST etc.). The initial directory looked like a absolute path (?:* drive root) and got passed directly to shell stuff that parses a path and gives you a PIDL. The shell supports ::{CLSID} paths in certain places and the :: path was parsed successfully into a PIDL and the PIDL got used as the initial directory.

      The fact that it worked was an accident and long path fixes in Vista Path* functions probably broke it and so it was less work to say that it is a bug than to add the support back (and document it).

      1. Kemp says:

        Ah, ok, so the translation code was there in the back but it just wasn’t intended to be used through that route. Thanks.

  3. Paul Topping says:

    I’m sure the author chose Recycle Bin as a just an example of a virtual directory to open. It is not a recommendation and nothing was offered pro or con as to whether that is a reasonable thing to do in your own app. Give the guy a break!

    1. DWalker07 says:

      I doubt that. Raymond explicitly says:

      “A customer reported that they had been setting the lpstrInitialDir member of the OPENFILENAME structure to “::{645FF040-5081-101B-9F08-00AA002F954E}” in order to have the dialog’s default directory be the Recycle Bin.”

      This seems clear that the customer (the one calling for support) has some code that wants a dialog’s default directory to be the Recycle Bin. I’m not sure who you mean by “author”; Raymond is the author, and Raymond is not the customer that he mentions.

      1. Kevin says:

        Either that, or the customer was doing something substantially dumber (“Let’s show an open file dialog for the Control Panel!”) and changed it to the Recycle Bin when consulting Microsoft because they did not want to get told “Don’t do that.”

  4. cheong00 says:

    One more example on people who (unintentionally ?) rely on bug behavior.

Skip to main content