Why was the replacement installer for recognized 16-bit installers itself a 32-bit program instead of a 64-bit program?


Even though 64-bit Windows does not support 16-bit applications, there is a special case for 16-bit installers for 32-bit applications. Windows detects this scenario and substitutes a 32-bit replacement installer which replicates the actions of the 16-bit installer. Commenter Karellen is horrified at the fact that the replacement installer is a 32-bit program. "You're writing a program that will run exclusively on 64-bit systems. Why not built it to run natively on the OS it's designed for? Why is this apparently not the "obvious" Right Thing(tm) to do? What am I missing?"

Recall that a science project is a programming project that is technically impressive but ultimately impractical. For example it might be a project that nobody would actually use, or it attempts to add a Gee-Whiz feature that nobody is really clamoring for.

But at least a science project is trying to solve a problem. This proposal doesn't even solve any problems! Indeed, this proposal creates problems. One argument in favor of doing it this way is that it is satisfies some obsessive-compulsive requirement that a 64-bit operating system have no 32-bit components beyond the 32-bit emulation environment itself.

Because! Because you're running a 64-bit system, and running apps native to that system is just more elegant.

Okay, it's not obsessive-compulsive behavior. It's some sort of aesthetic ideal, postulated for its own sake, devoid of practical considerations.

Remember the problem space. We have a bunch of 32-bit applications that use a 16-bit installer. Our goal is to get those applications installed on 64-bit Windows. By making the replacement installer a 32-bit program, you get the emulator to do all the dirty work for you. Things like registry redirection, file system redirection, and 32-bit application compatibility.

Suppose the original installer database says

  • Copy X.DLL file into the %Program­Files%\AppName directory.
  • Copy Y.DLL into the %windir%\System32 directory.
  • If the current version of C:\Program Files\Common Files\Adobe\Acrobat\ActiveX\AcroPDF.dll is 7.5 or higher, then set this registry key.

If you write the replacement installer as a 32-bit program, then other parts of the 32-bit emulation engine do the work for you.

  • The environment manager knows that 64-bit processes get the environment variable Program­Files pointing to C:\Program Files, whereas 32-bit processes get Program­Files pointing to C:\Program Files (x86).
  • The file system redirector knows that if a 32-bit process asks for %windir%\System32, it should really get %windir%\SysWOW64.
  • The registry redirector knows that if a 32-bit process tries to access certain parts of the registry, they should be sent to the Wow­64­32­Node instead.

If you had written the replacement installer as a 64-bit program, you would have to replicate all of these rules and make sure your copy of the rules exactly matched the rules used by the real environment manager, file system redirector, and registry redirector.

Now you have to keep two engines in sync: the 32-bit emulation engine and the 64-bit replacement installer for 32-bit applications. This introduces fragility, because any behavior change in the 32-bit emulation engine must be accompanied by a corresponding change in the 64-bit replacement installer.

Suppose the application compatibility folks add a rule that says, "If a 32-bit installer tries to read the version string from C:\Program Files\Common Files\Adobe\Acrobat\ActiveX\AcroPDF.dll, return the version string from C:\Program Files (x86)\Common Files\Adobe\Acrobat\ActiveX\AcroPDF.dll instead." And suppose that rule is not copied to the 64-bit replacement installer. Congratulations, your 64-bit replacement installer will incorrectly install any program that changes behavior based on the currently-installed version of AcroPDF.

I don't know for sure, but I wouldn't be surprised if some of these installers support plug-ins, so that the application developer can run custom code during installation. It is possible for 16-bit applications to load 32-bit DLLs via a technique known as generic thunking, and the 16-bit stub installer would use a generic thunk to call into the 32-bit DLL to do whatever custom action was required. On the other hand, 64-bit applications cannot load 32-bit DLLs, so if the 64-bit replacement installer encountered a 32-bit DLL plug-in, it would have to run a 32-bit helper application to load the plug-in and call into it. So you didn't escape having a 32-bit component after all.

And the original obsessive-compulsive reason for requiring the replacement installer to be 64-bit was flawed anyway. This is a replacement installer for a 32-bit application. Therefore, the replacement installer is part of the 32-bit emulation environment, so it is allowed to be written as a 32-bit component.

Let's look at the other arguments given for why the replacement installer for a 32-bit application should be written as a 64-bit application.

Because complexity is what will be our undoing in the end, and reducing it wherever we can is always a win.

As we saw above, writing the replacement installer as a 64-bit application introduces complexity. Writing it as a 32-bit application reduces complexity. So this statement itself argues for writing the replacement installer as a 32-bit application.

Because we can't rewrite everything from scratch at once, but we can create clean new code one small piece at a time, preventing an increase to our technical debt where we have the opportunity to do so at negligible incremental cost to just piling on more cruft.

As noted above, the incremental cost is hardly negligible. Indeed, writing the replacement installer as a 64-bit application is not merely more complex, it creates an ongoing support obligation, because any time there is a change to the 32-bit emulation environment, that change needs to be replicated in the 64-bit replacement installer. This is a huge source of technical debt: Fragile coupling between two seemingly-unrelated components.

And writing the replacement installer as a 32-bit application does not create a future obligation to port it to 64 bits when support for 32-bit applications is dropped in some future version of Windows. Because when support for 32-bit applications disappears (as it already has on Server Core), there will be no need to port the replacement installer to 64-bit because there's no point writing an installer for a program that cannot run!

Writing the replacement installer as a 32-bit program was the right call.

Comments (34)
  1. Kelden says:

    I can imagine there are crazy people who creates 32-bit installers to install 64-bit applications.

  2. dmw says:

    That reminds me of another science project:

    blogs.msdn.com/…/10378851.aspx

  3. Ben Voigt says:

    @Kelden, it is not even that crazy, if the installer performs architecture detection and then installs either the 32-bit or 64-bit binaries as appropriate.

    Of course, that leads to failures in the Windows-server-SKU-without-32-bit-support-installed scenarios, but for many applications, those scenarios represent a trivial fraction of potential users.

  4. Roger Lipscombe says:

    I saw this:

    > It's some sort of aesthetic ideal, postulated for its own sake, devoid of practical considerations.

    …and thought of this:

    > Any run-of-the-mill engineer can design something which is elegant. A good engineer designs systems to be efficient. A great engineer designs them to be effective.

    …from spacecraft.ssl.umd.edu/akins_laws.html, which I was reading this morning.

  5. poizan42 says:

    > On the other hand, 64-bit applications cannot load 32-bit DLLs,

    Well, you can call/jmp to 0x23:(addr of 32-bit code) and from the 32-bit code call ntdll!LdrLoadDll. The Win32 subsystem does not support this, and kernel32.dll refuses to load (which is enforced by hardcoding the name of kernel32.dll inside of ntdll (ntdll!LdrpKernel32DllName)…). So this seems to be a case of Raymond looking at the world with userspace-colored glasses.

    [So you're going to introduce even more complexity by having the 64-bit installer break the rules and do something that the kernel team doesn't support? (On top of that, it will also have to patch the 32-bit DLL in order to do file system redirection, registry redirection, and all the other things that emulation would have done for you. Complex enough for you?) -Raymond]
  6. IanBoyd says:

    What i like about your blog, and it's been happening more and more in recent years, is that you don't simply throw a comment out there. You actually explain it all the way down to the very end, and then come back up.

    Some things that might seem obvious to some developers, and complete unknown to others.

    For example, the post from December 2014 about getting procedure addresses by ordinal. If the ordinal isn't there, it's obviously bad. But it's only obviously bad to me, because i know what a DLL is, what an export is, what exporting by ordinal is, and what the alternative to exporting by ordinal is. So while i didn't need the depth, others can use it.

    On the other hand i knew nothing about Acquire and Release semantics, fibers, SSE, and the intricacies of undefined behavior in a post-modern optimizing compilers. In those cases i appreciate, and need, the depths of knowledge that accompany the blog.

    Sometimes i wonder if you feel silly repeating so much detail on a subject. But the informal nature of a blog and be so much more expressive and helpful than pure documentation.

  7. Joshua says:

    @Raymond: One possible implementation for how folder redirection works is it's inside 32 bit NtDll. If this were in fact the implementation used poizan42 might be on the right track. But it's not there….

  8. Wyatt says:

    I create 32-bit installers to install 64 bit applications just like Ben mentioned above.  I can't imagine the number of problems I'd run into with people trying to run the 64 bit installer on a 32 bit OS.  Of course, most of my files are .NET assemblies marked as Any CPU, but I do have a couple that install with a condition based on the processor architecture because the vendor doesn't have an "Any CPU" version.

  9. DWalker says:

    I'm actually surprised that the 16-bit installers (for 32-bit applications) have survived for so long.  We have had 32-bit programs for how long, now?

    I suppose the reason that the installer-makers have not rewritten the installers as 32-bit installers is because, what, the 16-bit installers work fine and no one wants to update them?

    "Windows detects this scenario and substitutes a 32-bit replacement installer which replicates the actions of the 16-bit installer."  Does this apply to 16-bit installers that weren't even written by Microsoft?  Does Microsoft completely emulate 16-bit installers from other companies (like InstallShield)?  That would seem like a large undertaking.

  10. AndyCadley says:

    @DWalker: The replacement installer engine is for certain versions of the InstallShield and Acme installers, presumably because they were so prevalent at the time.

  11. Mark VY says:

    I have the opposite question: why does 64-bit Windows come with ANY 64-bit programs?  Why not just the kernel and maybe a few utilities like Task Manager?  Does Notepad need several gigs of RAM?  Minesweeper?  The cost to port them was high.  As you once said, Pinball had to be sacrificed.  Things like Internet Explorer need a 32-bit version anyway so plugins work.  This trick doesn't help shell plugins, so many 3rd-party shell plugins go bye-bye.

    To what end?

  12. Yukkuri says:

    Unfortunately there is no chance this explanation will stop people from making future ill-thought-out comments about 'omg Microsoft is doing it wrong!!!111'

  13. Erik F says:

    @Mark VY: Windows Server 2008 R2 and higher made WoW64 optional (see msdn.microsoft.com/…/dd371790(v=vs.85).aspx), so 32-bit stuff wouldn't work there period. I'm sure that it would be fun to run a server where you don't even have basic "taken for granted" tools available!

  14. Myria says:

    I wish that 64-bit Windows allowed us to create LDT entries like the Linux and Mac OS kernels do.  Then I could create my own NTVDM that works on Win64.  Instead, Microsoft made this impossible without patching the NT kernel.  Oh wait, they made that impossible, too.

    @Erik F: WOW64 is only optional in Server Core.  If you have the GUI, WOW64 is mandatory.

  15. DWalker says:

    Thanks for the answers.  Andy: "The replacement installer engine is for certain versions of the InstallShield and Acme installers, presumably because they were so prevalent at the time."  I suppose that "at the time" means when 64-bit Windows was first delivered.  That makes sense.

  16. InstallShield is still pretty damn prevalent.  

    I suspect the other reason there were so many 32-bit applications with 16-bit installers was "why should we buy the new 32-bit version when the old 16-bit one still works?"

  17. poizan42 says:

    > So you're going to introduce even more complexity by having the 64-bit installer break the rules and do something that the kernel team doesn't support?

    No not at all, I was just pointing out that your statement wasn't completely correct. 64-bit applications can in theory load 32-bit dlls – at least native dlls.

    [You may as well say "Of course it's possible. You just install a kernel driver that takes over the CPU and does the thing you want." It's not possible while staying within the rules of the system. -Raymond]
  18. Bekenn says:

    Myria: How do you create an LDT entry on OSX from a 64-bit application?  i386_set_ldt is exported for 64-bit, but doesn't work.

  19. Darran Rowe says:

    @poizan42:

    In theory it is always possible, but there is always a huge problem with pointers and stuff. So that is more impractical than just writing a 32 bit installer.

    There is problems of the stack being in RSP and possibly being high up in the address space, calling convention differences, pointers to memory needing to be in the low 2GB/4GB of the address space and so on.

    @Mark YV:

    But 64 bit applications is more than just address space. Also, we can't be sure what will happen in years to come. 4k resolutions are here where at 32bpp, we can see a fair amount of memory usage per frame. 8k also exists and is coming to more common use, and that seems to be extending things to 48bpp too.

    Also as far as plugins are concerned, things have moved on. I normally use the 64 bit versions of browsers and I have no issues with the plugins I use. So years ago that may have been a major factor, but these days things have changed.

  20. Evan says:

    Also consider that things like ASLR can be much more effective in a 64-bit address space; in a 32-bit space it usually has little enough entropy that brute forcing the locations of things is often a reasonable thing to do. In a 64-bit world brute force goes out the window and you need something like an information disclosure bug or another better technique.

  21. cheong00 says:

    I have a question: I remember that newer server version like Win2012 does not have 32-bit sub-system on it by default (you have to explicitly select it from Windows features), is the installer there 32-bit or 64-bit? Or is that the 32-bit version of installer will be installed and take over when 32-bit subsystem got installed?

  22. Evan says:

    @DWalker: "I'm actually surprised that the 16-bit installers (for 32-bit applications) have survived for so long.  We have had 32-bit programs for how long, now?"

    I suspect it's for programs that were written when 32-bit programs had *not* been around long. There is one 1996 game I've run into this with IIRC. Unfortunately, I guess the mechanism for replacing the installer didn't catch it; fortunately, if memory serves, installing it in a 32-bit VM and copying the installation directory out seemed to work.

  23. @dmw: You might want to re-read this part:

    — henke37: And just leaving it as 32-bit was out of the question then?

    — Raymond: That would have been even more work, because there was at the time no infrastructure in Setup for having 32-bit-only components. (And then automatically uninstalling it when WOW64 was disabled.) And besides, all the people who criticized Windows 95 as "not really a 32-bit operating system because it has some parts in 16-bit" would use the same logic to say that 64-bit Windows is "not really a 64-bit operating system."

  24. xpclient says:

    Microsofties still use the word 'program' once in a while instead of 'app' :O?

  25. Mark VY says:

    Thanks to all the people who gave reasons why my idea might not be quite as good as I thought :)

  26. dmw says:

    @Fleet Command: I read that. But contrary to what Raymond describes, no x64 release prior to Server 2008 R2 (if I recall correctly) even allowed to disable WOW64 in shipping configurations. WOW64 was practically indispensable when 64-bit releases were introduced; everyone relied on existing x86 software, so even the IA64 builds could run it. Now reconsider that project: porting all system components, even games (typically running on client machines) to x64 just in case someone installs without WOW64 (typically only on servers; not possible at all at the time). Wouldn't this classify as a science project by Raymond's standards? And don't you sense "some sort of aesthetic ideal, postulated for its own sake, devoid of practical considerations" in the "not really a 64-bit operating system" part of the comment?

    Anyway, I'm sure the 64-bit porting effort wasn't meant to be a science project. Supposedly requirements have changed during development (towards unconditional inclusion of WOW64); and other than the typical science project, the porting effort was easily dismissed when it prove inefficient. But Raymond usually has strong arguments to justify the decisions he is recounting, and it is always intersting to have the arguments for two seemingly adversary decisions collide :)

    [I forget whether ia64 had WOW64 or not. I doubt axp64 did. There were other practical reasons for porting even if WOW64 existed: To update all the interfaces to 64-bit. Sure, maybe Pinball doesn't have an interface for other programs to use, but lots of other components do. The porting effort made those interfaces were available in 64-bit versions. And it also uncovered places where those interfaces needed to be revised for 64-bit. It was a demonstration proof that 64-bit Windows has a complete API surface. -Raymond]
  27. David Totzke says:

    @Roger Lipscombe Thanks for that link to Akin's Laws.  Love it.

  28. laonianren says:

    In the mid 1990s 16-bit x86 code could run on any Windows platform.  Windows NT running on MIPS and Alpha included WOW and an emulator for 16-bit x86.

    A 16-bit installer stub could detect the platform and launch a 16-bit installer or a 32-bit installer compiled for whatever CPU was present or display a meaningful message if it was unsupported.

    Thus the 16-bit code had a purpose, and didn't become actively unhelpful until 64-bit versions of Windows came along.  So it lingered.

    Though I wonder if the "sorry MIPS isn't supported" message in a typical stub was ever seen by anybody.

  29. James says:

    Was the copy logic really in a 16-bit installer?  I thought these were there just to bootstart the real 32-bit installer when the application had x86 and Alpha installers.  

  30. Richard says:

    This is probably a dumb question, but:

    With 16-bit Windows, the System directory held 16-bit files.

    With 32-bit Windows, System held 16-bit files, and System32 held 32-bit files.

    With 64-bit Windows, System32 holds 64-bit files, and SysWOW64 holds 32-bit files.

    Why not use System64, and leave System32 for 32-bit files?

    [I discussed this several years ago. -Raymond]
  31. Mike Dimmick says:

    IA64 did have WOW64. Early Itanium processors had a form of hardware support for x86, but basically just in-order translation of one x86 instruction to one IA64 instruction bundle for simple instructions, with a microcode ROM for more complex instructions. Significantly it didn't feature out-of-order execution or much instruction-level parallelism, so was far, far slower than the contemporary Pentium III and Pentium 4 designs even just on instructions-per-clock. The PIII and P4 designs were typically clocked 50-100% faster than the Itaniums as well. With an emulator that slow, it was definitely worth having native 64-bit versions of everything possible.

    As I understand it, 64-bit Windows 2000 for Alpha was well underway when Compaq dropped support, after buying Digital. Indeed Raymond mentions a 64-bit Alpha system in this Windows Confidential article: technet.microsoft.com/…/2008.08.windowsconfidential.aspx . I don't know if it supported Alpha-Windows-on-Alpha-Win64, though. There were presumably *some* commercial Alpha32 packages that wouldn't have been immediately ported to 64-bit. (Visual Basic and Visual C++ 6.0 were both released for Alpha.)

    The October 2001 MSDN Library (I still have it installed – it was the last release to support Visual Studio 6.0) has a whole section on building for 64-bit Windows, including a section on Running 32-bit Applications. AMD didn't have working x86-64 hardware until 2003 and Windows didn't appear on x64 until mid-2005.

  32. ender says:

    > Was the copy logic really in a 16-bit installer?  I thought these were there just to bootstart the real 32-bit installer when the application had x86 and Alpha installers.  

    At least with InstallShield it's like this – 16-bit bootstrapper was used to detect the CPU architecture, then run the appropriate installer for the architecture (or whine that whatever you have isn't supported).

  33. @Myria, @dmw: What about Windows Preinstallation/Recovery Environment? I've noticed that the recovery partition on my Windows 7 system doesn't have WoW64 either: despite having a GUI, it can only run 64-bit software.  (And, incidentally, it doesn't have Explorer.)

  34. @laonianren: exactly correct – and 16-bit code could also run on the Win9x platforms, too.

    Not a science project: I was working with customers that had really old programs with 16-bit installers that they needed to install on 64-bit Windows.  But for some reason the emulation for those particular installers didn't work.  That became The Case of the App Install Recorder, which you can read about here:  blogs.msdn.com/…/the-case-of-the-app-install-recorder.aspx

Comments are closed.

Skip to main content