Does this operation work when file system redirection is disabled? The default answer is NO

Date:March 21, 2013 / year-entry #80
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20130321-00/?p=4883
Comments:    23
Summary:A customer reported that when their program called SH­Get­File­Info to get the icon for a folder, the call failed. "It works on some machines but not others. We don't know what the difference is between the working and non-working machines." They included the offending function from their program, but everything in the function looked good....

A customer reported that when their program called SH­Get­File­Info to get the icon for a folder, the call failed. "It works on some machines but not others. We don't know what the difference is between the working and non-working machines." They included the offending function from their program, but everything in the function looked good. The problem was something outside the function itself.

Eventually, the customer confessed that they had called the Wow64­Disable­Wow64­Fs­Redi­rection function to disable file system redirection, and the call to SH­Get­File­Info took place while redirection was disabled. "We found that if we re-enable file system redirection before calling SH­Get­File­Info, then everything works properly."

That's right, because, like impersonation, nothing works when file system redirection is disabled unless it is specifically documented as supporting disabled redirection. This is even called out in the documentation for Wow64­Disable­Wow64­Fs­Redi­rection:

Note  The Wow64­Disable­Wow64­Fs­Redi­rection function affects all file operations performed by the current thread, which can have unintended consequences if file system redirection is disabled for any length of time. For example, DLL loading depends on file system redirection, so disabling file system redirection will cause DLL loading to fail. Also, many feature implementations use delayed loading and will fail while redirection is disabled. The failure state of the initial delay-load operation is persisted, so any subsequent use of the delay-load function will fail even after file system redirection is re-enabled. To avoid these problems, disable file system redirection immediately before calls to specific file I/O functions (such as Create­File) that must not be redirected, and re-enable file system redirection immediately afterward using Wow64­Revert­Wow64­Fs­Redi­rection.

Whenever you use one of these "global solutions to a local problem" types of solutions that change some fundamental behavior of the system, you have to make sure that everybody is on board with your decision.

The local solution would be to use the C:\Windows\Sys­Native virtual directory for files you want to look up in the native system directory rather than the emulated system directory.


Comments (23)
  1. John says:

    What if you're performing a lengthy process that touches a lot of files, perhaps enumerating some section of the file system?  How expensive is it to call the Disable/Revert pair for every single file access?

    [If you're doing a lot of work with each file, then the cost of the disable/revert is unlikely to be a bottleneck. If you're just opening the file, reading 1 byte, then closing it, then you may as well leave redirection enabled. The problem is if you open the file then call out to external code while redirection is still enabled. -Raymond]
  2. Joshua says:

    [The local solution would be to use the C:WindowsSys­Native virtual directory for files you want to look up in the native system directory rather than the emulated system directory.]

    Requires a patch for Windows Server 2003 x64 that is not on Windows Update and is marked as not redistributable.

    support.microsoft.com/…/942589

  3. Mordachai says:

    This is the sort of information that desperately needs to be included with all such "global solutions!"  Disparaging developers for foolishly using global solutions to local problems when there isn't information discussing a better, local alternative, is a bit like blaming foreigners for not knowing nuances of local custom.  How would anyone know about C:WindowsSysNative?  I'd never heard of it before now, having been a Windows developer for about 16 years (not that I've had need to use Wow64DisableWow64FsRedirection either, so maybe if I had I'd have stumbled upon it – though I notice that the MSDN documentation for Wow64DisableWow64FsRedirection fails to mention C:WindowsSysNative).

    [The MSDN local solution is to disable redirection, open the file, then re-enable it. The SysNative solution is a clever trick. You won't go wrong following the MSDN-recommended solution. (For example, if you are on a platform where the SysNative trick doesn't work.) -Raymond]
  4. @Joshua says:

    [Requires a patch for Windows Server 2003 x64 that is not on Windows Update and is marked as not redistributable.]

    So what? Mark it as a dependency in your MSI and link the Support Ticket (which you were somehow able to find) for your legacy customers to apply. What is so hard about this? Solutions to these problems have been well known for years, its amazing the amount of laziness on developers parts to help themselves out, instead its a game of how can we blame Microsoft for our own shortcomings?

  5. 12BitSlab says:

    @ @Joshua:

    That was a little harch wasn't it?  I didn't see where Joshua was critical of anyone.  I read that more as an FYI for the readers.

  6. Joshua says:

    I see that 12BitSlab understands that I too have the social skills of a thermonuclear device.

  7. Entegy says:

    On the very tangentially related subject of file systems, I've been trying to find the post where Raymond describes why C:Documents and Settings gets Access Denied on Vista/7/8. I know why, but I'm trying to find the post for reference. I could have sworn he posted about it and I see he references it in a response here (blogs.msdn.com/…/9900082.aspx) but I just cannot find this post!

    [Because it's on the other site. -Raymond]
  8. alegr1 says:

    I suppose, TheFunctionWithSuperLongName just sets a flag in the thread block (offset in FS:), and is so cheap that you can flip it around your CreateFile calls all day long.

  9. John says:

    @alegr1:  That's what I assumed as well, but you know what happens when you assume.  Although in this case it turns out to be correct.

  10. Entegy says:

    [Because it's on the other site. -Raymond]

    …Well that explains it. Doesn't help when I was restricting searches to just this blog. Thanks Raymond!

  11. Killer{R} says:

    WOW64 as it was implemented is an epic overarchitecture designed to solve minor problems by cost of major mess of overcomplication that subsequently caused major problems.

  12. JM says:

    "Wow64­Disable­Wow64­Fs­Redi­rection" (along with its siblings) is a strong contender in the "most awkwardly named function" competition. It's not just long, it's redundant and arrhythmical.

  13. Daniel Neely says:

    @Joshua

    Just do what 99% of competent programmers who didn't read this blog and don't know about the SysNative trick would do:  See that redirect is disabled on a per thread basis and move whatever needs to be done without it to a new thread that doesn't do anything else.

  14. Nobody says:

    Of course, that the redirection happens at all could be considered a global solution to a local problem.  "Say, we have a few apps that are broken.  I know, I'll fix this by changing how the filesystem works from underneath them!"  I guess somebody took a look at this question and either didn't see that this is a weird thing to do, or they made the assesment that the benefits outweigh the ickiness.

    [32-bit applications run in an emulator. This is part of the emulation – hiding the 64-bit system from them. -Raymond]
  15. AC says:

    Does Explorer itself disable the redirection and display you the "real" filesystem?

  16. Neil says:

    @AC: Explorer is 64-bit so doesn't have to worry about Wow64 redirection.

    I wonder why C:Windowssystem64 was not used in the first place, but it's too late to worry about that now.

    [I thought I explained this already. It would break all batch files which hard-coded C:WindowsSystem32. -Raymond]
  17. alegr1 says:

    @JM:

    Re: the "most awkwardly named function" competition, how about a function named disable_periodic_flows()? I kid you not.

  18. "WOW64 as it was implemented is an epic overarchitecture designed to solve minor problems by cost of major mess of overcomplication that subsequently caused major problems."

    Minor problems?  IA64 still had a 32-bit layer, and it failed.  Alpha, MIPS builds of Windows NT that had no x86 emulation layers at all?  Failed.

    64-bit Windows would be a historical footnote if it didn't have a 32-bit compatibility layer.

    "See that redirect is disabled on a per thread basis and move whatever needs to be done without it to a new thread that doesn't do anything else."

    Seriously?  Make the program multi-threaded over this?  Just do what MSDN says: switch it off, open the file, revert it.  Leaving it turned off for an entire thread is just asking for it – sooner or later, someone's going to do something complicated in the thread and make a mess.  The MSDN approach is nice: especially with a comment, it's very clear to the reader how localized the operation is and nobody's going to mess it up by accident.

  19. dave says:

    Alpha, MIPS builds of Windows NT that had no x86 emulation layers at all?  Failed.

    Hmm, I see to remember running x86 code on an Alpha workstation around the time of NT 3.1.

    Maybe it was a DEC-internal thing.

  20. Joshua says:

    C:WindowsSystem32

    %PATH% hates your guts. It turned out that having a separate /bin and /lib was an idea so far ahead of its time that nobody grasped it, probably not even the UNIX guys.

  21. Killer{R} says:

    /*Minor problems?  IA64 still had a 32-bit layer, and it failed./*

    I already wrote at some comment couple of years ago other way how WOW64 could be implemented – leave 32 system binaries and registry and put all 64 bit stuff into _new_ folders – system64 and new KEY_LOCAL_MACHINE contant definition for x64 part of SDK that would contain own Software subkey and same hive mounted ad 'SYSTEM' subkey (or even using registry symlinks). At least this would be more logical and natural instead of moving 32bits into syswow64 and doing context-dependent redirections cuz its more declarative approach while every given path point to same location, but not redirected. The only minor (of course IMHO) problem with this solution that when somebody need to port 32 bit app to 64 bit- you need to query if there any hardcoded file path references and used hardcoded  integer constant instead of HKEY_LOCAL_MACHINE.

    So this would not break x86 code more than existing wow64, this theoretically would make process of porting x32->x64 a bit more complicated (if you use hardcoded C:WindowsSystem32 or prefer to write (HKEY)0x80000002 instead of HKEY_LOCAL_MACHINE. Is anybody here doing so)? And all his things BTW could be checked by simple static code analyzer or even by app verifier.

    /*This is part of the emulation – hiding the 64-bit system from them*/

    but:

    1) 32 bit apps still see some 64 binaries in %WINDIR% and C:Program Files

    2) they see but can't touch 64 processes

    3) Finally, MS added functionality for emulator to disable emulation

  22. ender says:

    [Hmm, I see to remember running x86 code on an Alpha workstation around the time of NT 3.1.]

    Non-x86 NT included an x86 emulator for 16-bit Windows and DOS programs, but you couldn't run 32-bit x86 Windows programs with it. At some point FX!32 was released for Alpha, which allowed Windows NT on Alpha to run 32-bit x86 programs.

  23. Medinoc says:

    How does SysNative work? It seems it only exists in WOW64, but even then it's invisible in file dialogs opened in C:Windows (you have to type explicitly its name to enter it) despite my machine being configured to display "super-hidden" files…

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index