Say, I can use Wow64DisableWow64FsRedirection API to disable file system redirection, but is there a way to know if the thread is currently being redirected? In other words, is there an API like GetWow64FsRedirection
?

- 20,994
- 29
- 177
- 400
-
If there were such a function, I'd expect it to be in the table of contents at the page you linked. – Mark Ransom May 07 '15 at 19:43
-
I suspect there deliberately isn't because this is a very dangerous function to use, the expectation is that you'll turn it on and off in the same method usually. – Mgetz Oct 25 '18 at 22:31
3 Answers
There is no API function that reports this state. You are expected to remember that you disabled redirection.

- 601,492
- 42
- 1,072
- 1,490
-
Thanks. I'm actually doing it for a logging method (which obviously won't know if that was done.) – c00000fd May 07 '15 at 19:46
-
1Or just call [`GetFinalPathNameByHandle`](https://msdn.microsoft.com/en-us/library/aa364962) on a handle for `%SystemRoot%\System32`. If it's redirected the final path will end at `SysWOW64`. – Eryk Sun May 07 '15 at 19:54
-
Or make the following calls in sequence: `Wow64DisableWow64FsRedirection(&disabled);` `Wow64RevertWow64FsRedirection(disabled);`. The latter call only enables redirection if it was previously enabled. – Eryk Sun May 07 '15 at 21:32
-
@eryksun: Hmm. Interesting. Thanks. You should post it as its own answer and I'll mark it. – c00000fd May 07 '15 at 23:11
Another approach is to check for the existence of the wow32.dll
in the Windows System32 directory (typically C:\Windows\System32
).
On 64-bit systems, this file should reside in the SysWOW64
directory, thus if file redirection is enabled, it will be found.
Similarly, one can check for the nonexistence of wow64.dll
, that resides in the System32 directory on 64-bit systems, and if it's not to be found the redirection is enabled.
The pseudo-code for that would be:
bool IsWow64FileSystemRedirectionEnabled()
{
if (!Is64BitOS()) return false;
if (FileExists(GetSystem32Directory() + "\\wow32.dll")) return true;
return false;
}
Where:

- 1
- 1
-
First off I wouldn't be hard-coding Windows installation path like that. It may not be `c:\Windows` for all you know. Then I'd be doubly-suspicion about relying on the presence of a file to detect a feature. You may be introducing a security bug into your code with this approach. – c00000fd Oct 26 '18 at 06:47
-
Thanks for commenting, as I said - it's a pseudo-code. I've edited the `System32` path, so it won't be misleading. – Dani Kamanovsky Oct 26 '18 at 13:07
-
Regarding the security issue, once an attacker can place a file in System32, he had either taken ownership or has an administrative rights to it. In such case he could perform much more severe damage. Anyway, this technique isn't perfect as it relies on the above specified limitations - but it's relatively fast (as twice as using the [GetFinalPathNameByHandle](https://learn.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfinalpathnamebyhandlea) on a handle for `%SystemRoot%\System32`). – Dani Kamanovsky Oct 26 '18 at 13:45
Sorry, forgot to post a follow-up. As the accepted answer suggests, there's no API to detect that. Too bad, because the information is stored right there in the undocumented section of the thread's TEB
struct. (See my comments in the code.)
The code below will retrieve it.
I have to preface it though by saying that it was obtained by reversing the aforementioned API. So it's a highly undocumented stuff that will probably break in the future versions of the OS. So make sure to put version safeguards before using it. It should be OK for all released versions of Windows though, including Windows 10 build 17134:
enum YESNOERR{
ERR = -1,
NO = 0,
YES = 1,
};
struct PROC_STATS{
BOOL b32BitProcessOn64BitOS;
DWORD dwOS_Major;
DWORD dwOS_Minor;
DWORD dwOS_Build;
PROC_STATS()
{
BOOL (WINAPI *pfnIsWow64Process)(HANDLE, PBOOL);
(FARPROC&)pfnIsWow64Process = ::GetProcAddress(::GetModuleHandle(_T("kernel32.dll")), "IsWow64Process");
BOOL bWow64 = FALSE;
b32BitProcessOn64BitOS = pfnIsWow64Process && pfnIsWow64Process(::GetCurrentProcess(), &bWow64) && bWow64;
LONG (WINAPI *pfnRtlGetVersion)(RTL_OSVERSIONINFOEXW*);
(FARPROC&)pfnRtlGetVersion = ::GetProcAddress(::GetModuleHandle(_T("ntdll.dll")), "RtlGetVersion");
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(osvi);
pfnRtlGetVersion(&osvi);
dwOS_Major = osvi.dwMajorVersion;
dwOS_Minor = osvi.dwMinorVersion;
dwOS_Build = osvi.dwBuildNumber;
}
};
PROC_STATS procStats;
YESNOERR __cdecl GetWow64FsRedirection()
{
//Checks if Wow64 file system redirection is on for the current thread
YESNOERR res = ERR;
__try
{
if(procStats.b32BitProcessOn64BitOS)
{
//Really easy pre-Win10 v.10.0.10041.0
if(procStats.dwOS_Major < 10 ||
(procStats.dwOS_Major == 10 && procStats.dwOS_Build <= 10041))
{
//Win XP, 7, 8.1 & earlier builds of Win10
__asm
{
mov eax, fs:18h ; TEB
mov eax, [eax + 0F70h]
mov eax, [eax + 14C0h]
xor ecx, ecx
test eax, eax ; 0=Wow64FsRedir is on, 1=Off
setz cl
mov [res], ecx
}
}
else
{
//Latest builds of Win10 have a separate WoW TEB block
__asm
{
mov eax, fs:18h ; TEB
mov ecx, [eax + 0FDCh] ; WowTebOffset
test ecx, ecx
jns lbl_no_offset ; it must precede TEB
add eax, ecx
lbl_no_offset:
cmp eax, [eax + 18h] ; pick version of the struct
jz lbl_alt
mov eax, [eax + 14C0h]
jmp lbl_check
lbl_alt:
mov eax, [eax + 0E30h]
lbl_check:
xor ecx, ecx
test eax, eax ; 0=Wow64FsRedir is on, 1=Off
setz cl
mov [res], ecx
}
}
}
else
{
//It's off by default
res = NO;
}
}
__except(1)
{
//Oops, too far in the future -- this no longer works
res = ERR;
}
return res;
}
This is how you can test it:
resWow64FsOn = GetWow64FsRedirection();
_tprintf(L"Wow64FsRedirection=%d\n", resWow64FsOn);
void* pOldV;
if(::Wow64DisableWow64FsRedirection(&pOldV))
{
resWow64FsOn = GetWow64FsRedirection();
_tprintf(L"Wow64FsRedirection=%d\n", resWow64FsOn);
::Wow64RevertWow64FsRedirection(pOldV);
resWow64FsOn = GetWow64FsRedirection();
_tprintf(L"Wow64FsRedirection=%d\n", resWow64FsOn);
}
else
{
_tprintf(L"ERROR: (%d) API Failed\n", ::GetLastError());
}

- 20,994
- 29
- 177
- 400