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".
bool g_fDisableRedirect = false;
__declspec(dllexport)
int DisableRedirection()
{
void* pVoid = NULL;
Wow64DisableWow64FsRedirection(&pVoid);
return 0;
}
__declspec(dllexport)
int StartDisableRedirect()
{
g_fDisableRedirect = true;
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
{
void* pVoid = NULL;
if (g_fDisableRedirect)
{
DisableRedirection();
}
break;
}
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
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.
extern int StartDisableRedirect();
extern int DisableRedirection();
void OnFile(HWND hwndParent)
{
StartDisableRedirect();
DisableRedirection();
OPENFILENAME ofn = {};
WCHAR szFile[MAX_PATH*2] = {};
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwndParent;
ofn.lpstrFilter = L"All Files\0*.*\0\0";
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = ARRAYSIZE(szFile);
ofn.Flags = OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST;
::GetOpenFileName(&ofn);
}