In a 32-bit program, how can I get the Open/Save File Dialogs to show the files in the System32 folder of a 64-bit system?
(Wow64DisableWow64FsRedirection
doesn't work, because for some reason it doesn't work for the dialog, I'm guessing because it's on a different thread. And of course using SysNative
doesn't work because the user isn't aware of what's going on internally; he just wants to see the "actual" files on the computer.)
Here's another way to ask the question:
Does any 32-bit program browse a 64-bit System32
folder from the open file dialog?
This is a common problem with installers. People want to ship a single installer executable for both 32-bit and 64-bit systems, meaning it has to be 32-bit. Yet a 32-bit installer can't put 64-bit executables in the right place. The solution, as described by Raymond Chen is to have a separate 64-bit installer that gets invoked by the 32-bit version on 64-bit machines.
You would create a 64-bit program whose job is to open a common dialog with your app window as owner. On a 64-bit system, you just create the process that opens the dialog, passing it the parameters that you would pass to
GetOpenFileName
or whatever. You could listen for the filenames on stdout or use some other IPC mechanism. Remember to useWow64DisableWow64FsRedirection
when opening the returned files! It may seem clunky to have UI running in another process, but it would be seamless to the users and many web browsers run different tabs or plug-ins in different processes.If you're fine with using Vista or higher, you can use the
IFileDialog
interface which would allow you to add a "Place" for theSysNative
directory. That way your users could still access the files if they need to. There might even be a simple way to redirect things so that when somebody clicks theSystem32
directory you take them toSysNative
instead.I have a working solution for this. It's kind of a hack, but it works.
Brief disclaimer before I show the solution. I mostly agree with Hefferman. It's not meant to be. I don't actually recommend doing this for shipping code. It's something that no 32-bit text editor, word processor (including 32-bit Office), or normal app supports. Normal users on 64-bit systems don't open or save files directly in the system directories. And most non-admin users don't have appropriate permission anyway to be touching files in there anyway. Microsoft redirects the file-system with very good reason for 32-bit apps. Don't try to fight it.
Now on to the solution.
The trick is to have a DLL call Wow64DisableWow64FsRedirection in DllMain for every DLL_THREAD_ATTACH callback.
First create a simple DLL that only has a DllMain and exports a couple of functions: "StartDisableRedirect" and "DisableRedirection".
Have your binary (EXE or DLL) link directly with this DLL. And then right before you call GetOpenFileName, call StartDisableRedirect (such that subsequent threads are not redirected) and DisableRedirect (for the current thread).
I deliberately made a "Start" function such that all DLLs (including system DLLs) were loaded before the hook would actually start processing threads. I didn't want to assume that the DLL implementing Wow64Disable would be loaded before my DLL. You have to be very careful (read: shouldn't) when calling code from DllMain.
I believe that this is simply not possible.
Even if you could get the dialog to show the files, what would their names be when they were returned to your 32 bit process? Sysnative is a bit of a hack and in any case not available on XP 64. This is just a consequence of overloading the system32 name.
Another thought experiment. If it were to be possible, you'd need the thread that does the enumeration to disable redirection. Since that thread is out of your control then there would have to be a published option to disable it. There isn't. It would be no good allowing you to disable redirection from the outside because that would result in DLL load failures when the 32 bit process tried to load shell extensions - you can't disable redirection if you are going to load DLLs because you'll get the wrong ones
I imagine that you are expected to write a 64 bit program if you want to get around this limitation.