C++ – How to allow 32 bit apps on 64 bit windows to execute 64 bit apps provided in Windows\System32

32-bit64-bitc++vista64windows-vista

Say you have an app, that you want to provide users ability to browse the system32 directory and execute programs in (like telnet).

What is the best method for supporting this when you need to support XP onwards as a client and 2k onwards for server?

Having written all this up I wonder if it's just too much time/effort in providing a browse to do this, where they could just copy it from explorer. Still requires ability to launch.

I have found some discussion on Nynaeve.

So far it seems there are the following options

  1. Create a sysnative folder in windows which will allow you to browse/execute 64 bit. Issues are:
    • only available in Vista/Longhorn, so no support for XP 64
    • leads to different path naming, can't use same path on multiple versions.
    • will be active for whole of windows, not just our app
    • may not (probably is not) appropriate to do when installing the app
    • allows to specify explicitly through path only which version of the app to launch if there is a 32 bit and 64 bit version
  2. Use the windows API to temporarily disable the redirection when showing file lists or executing users run commands. Issues are:
    • Only available on 64 bit – have to mess with GetProcAddress
    • available only under certain service packs
    • must individually identify all locations that this should be implemented
    • user will need to provide seperate information about whether this is a 64 bit app or 32 bit.

If anybody had some example code which displayed a Windows OpenFile dialog (say using MFC CFileDialog) showing nativly for XP/Vista and allowing the viewing of 64 bit system32 directory, that would be awesome.

If anybody had an example of launching the named app, that would also be great!

Edit:
Currently we use CreateProcess for launching the app (which is failing).

err = CreateProcess((wchar_t*)exeName.c_str(), (wchar_t*)cmdLine.c_str(), NULL, NULL, FALSE, CREATE_SEPARATE_WOW_VDM, NULL, workingDir.c_str(), &startupInfo, &processInfo);

Best Solution

I've gone with option 2, For those who might be interested; here is my quick hack at a scoped version of managing the disabling of Wow64 redirection based on notes from MS. Will redirect if the API is available, expects that kernel32.dll is already available.

class Wow64RedirectOff {
    typedef BOOL (WINAPI *FN_Wow64DisableWow64FsRedirection) ( __out PVOID *OldValue );
    typedef BOOL (WINAPI *FN_Wow64RevertWow64FsRedirection) ( __in  PVOID OldValue );

public:
    Wow64RedirectOff() {
        LPFN_Disable = (FN_Wow64DisableWow64FsRedirection)GetProcAddress(
            GetModuleHandle(TEXT("kernel32")),"Wow64DisableWow64FsRedirection");
        if( LPFN_Disable ) {
            LPFN_Disable(&OldValue);
        }
    }

    ~Wow64RedirectOff() {
        if( LPFN_Disable ) {
            FN_Wow64RevertWow64FsRedirection LPFN_Revert = (FN_Wow64RevertWow64FsRedirection)GetProcAddress(
                GetModuleHandle(TEXT("kernel32")),"Wow64RevertWow64FsRedirection");
            if( LPFN_Revert ) {
                LPFN_Revert(OldValue);
            }
        }
    }

private:
    FN_Wow64DisableWow64FsRedirection LPFN_Disable;
    PVOID OldValue; 
};

And thus usage would be

Wow64RedirectOff scopedRedirect;
//CFileOpen
//CreateProcess