Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wow64DisableWow64FsRedirection on 32-bit Windows XP

I'm writing a program in Visual Studio C++ which needs to run natively as a 32-bit process on any computer running Windows XP 32-bit, or any later Windows operating system. This program needs to be able to access the C:\Windows\system32\ folder on a computer, regardless of whether the program is running on a 64-bit or 32-bit system. To do this, I was using Wow64DisableWow64FsRedirection to disable the redirection that Windows typically does to 32-bit processes, sending them to C:\Windows\syswow64. Unfortunately, this breaks compatibility -- though my program can run on Server 2003 and XP x64 edition, the program fails whenever it runs on a 32-bit XP RTM system, giving me this error:

[Program Name] - Entry Point Not Found
  The procedure entry point Wow64DisableWow64FsRedirection could not be located
  in the dynamic link library KERNEL32.dll.

Since the system is 32-bit, the call is obviously superfluous, but I can't figure out a way to determine at runtime whether a system is 64-bit or not, and therefore whether or not to skip the call, without adding another call that itself breaks compatibility, such as IsWow64Process(), which requires XP Service Pack 2.

tl;dr: How can I determine whether a system is 64-bit or 32-bit without using any of the calls that were introduced after the advent of consumer 64-bit Windows.

like image 928
The name's Bob. MS Bob. Avatar asked Aug 20 '14 20:08

The name's Bob. MS Bob.


1 Answers

Go ahead and use Wow64DisableWow64FsRedirection, but don't import it statically. Instead use either dynamic binding (GetProcAddress) or delay-loading, either of which allow you to handle a missing function without crashing (or worse, not even starting, which is the current case).

And just don't worry about the system bitness. If the function is present, call it.

typedef BOOL WINAPI fntype_Wow64DisableWow64FsRedirection(PVOID *OldValue);
auto pfnWow64DisableWow64FsRedirection = (fntype_Wow64DisableWow64FsRedirection*)GetProcAddress(GetModuleHandleA("kernel32.dll"), "Wow64DisableWow64FsRedirection");

if (pfnWow64DisableWow64FsRedirection) {
   // function found, call it via pointer
   PVOID arg;
   (*pfnWow64DisableWow64FsRedirection)(&arg);
}
else {
   // function was missing
}

Now the linker won't find an unresolved symbol named Wow64DisableWow64FsRedirection, so it won't put that function in the import table, and Windows won't go looking for it during process startup.

like image 90
Ben Voigt Avatar answered Nov 04 '22 01:11

Ben Voigt