Where are the Windows system DLLs stored?

In the time of Windows 3.1, the system DLLs were stored in the  \Windows\System directory.  These are the DLLs that provide the foundation for the Windows system and application APIs.  Then came Windows for Workgroups 3.11 with the first vestiges of 32-bit and Microsoft invented \Windows\System32.  Okay, this makes sense.  If a same name DLL exists for both 16-bit and 32-bit, there’s a place to put it for both.  When the application loads a named system DLL, the loader can go and find the right one theoretically using PATH differences for 16 vs. 32 bit applications.

The application doesn’t require a change unless it is fully qualifying the path to the DLLs, which I’ll note that all applications should do.   I could get into the fact that even if applications do fully qualify the names of system DLLs, the OS ignores that and loads them from the system space no matter what the application says.  Let’s march on.

Along comes Windows 95 who continues the 32-bit tradition of using \windows\system32 for the majority of the system components and Windows NT 3.51 does it the same.  The 32-bit system stuff is in \Windows\System32, the 16-bit stuff is in \Windows\system.

Where the train wrecks

Microsoft implements Win64 with Windows 2000 64-bit, and they place all the 64-bit stuff into System32 directory and invent \Windows\SysWOW64 to hold all the stuff that used to be in System32.

WHAT !!!  The “System32” directory holds all the 64-bit components!

What happened to the \Windows\System64 directory?

There’s more

Programs used to be installed to “\Program files” and now 32-bit programs are installed to “\Program files(x86)” and 64-bit programs are installed to “\Program files”.  What is the possible value in this?

It would at least be logical to have the 32-bit programs be where they have always been and put the 64-bit into “\Program files(x64)”.  There’s more – the applications don’t exactly know they are installing or using a separate space.  This done both via redirection and changing of the APIs that tell programs where the \Program files directory is located.  It gives a different answer based on the bitness of the calling application.

Why do this?

I guess there’s a desire here to have both 32-bit and 64-bit versions of the same application installed on the same machine at the same time, but the concept of having separate directories for application storage is still mysterious.

The OS knows the bitness of any .EXE just by looking at it; this is stored inside the PE header so there’s no obvious need to store these in different directory trees.

More likely: It permitted a quicker port to 64-bit because it allowed LOTS of Windows code that had hard coded the path to SYSTEM32 to continue to work without change.  Note two things, the API that applications use to query the location of key system directories does not have an call to query the location of the System directory.  It can query \Program files and \Windows, but it does not have a similar API call to get the location of the Windows “system” directory.

The environment variables that have existed since the beginning of time also do not provide a pointer to the system/system32/system64 directory.  Example even on Windows 7 64-bit, WINDIR and SYSTEMROOT both point to C:\Windows, but there is NO environment variable defined to point to C:\Windows\System32.

It gets worse.

Separate 32 and 64 bit registry spaces

In 32-bit Windows, the registry space for machine level application configuration data is stored in HKLM\Software\CompanyName\AppName, let’s just call that HKLM\Software.

In 64-bit Windows, the application specific storage in the registry is reflected into two different registry hives.  The 64-bit stuff is stored in HKLM\Software, which I’m actually fine with so long as the 32-bit stuff is stored there.

Bazaar comings…

The 32-bit application config registry is MOVED to HKLM\Software\Wow6432Node.

I understand that this is backed by a separate registry hive to reduce the size of the individual registries resulting in more efficient access for something.  Yeah, fine.  There’s too much stuff in the registry to start with and yes, it needs some work.

Wow6432Node“.  Wow == “Windows on Windows”, so I guess this translates to Windows 64-bit, Windows 32-bit node.  I’m sure that made sense somewhere and it would make more sense if the convention was actually consistent across registry and file system.  Shouldn’t this be HKLM\Software\Syswow64?

Where should your application’s settings go?

Put on your app developer hat.  Are you 32-bit or 64-bit?  Where do you expect your settings to be stored?  Do you CARE that the OS has different spaces for 32 and 64 bit?

What if you’re a really big application or an actual system component yourself?  Like, say Citrix XenApp.  Are you 32-bit or 64-bit?  The answer is “yes”.

Even if you wanted to move everything to true 64-bit execution, you’d have a transition period that would go on for a number of releases.  For Citrix, this goes back to at least Presentation Server 4.0 and is still underway for XenApp 6.0.   We’re really not stressed to move everything to 64-bit, there’s no need except for the things that really NEED to be 64-bit, like device drivers.

Registry reflection on Win64.

If a 32-bit application does registry stuff to HKLM\Software, the system itself will redirect the registry operation to HKLM\Software\Wow6432Node.  The exact same source code running as a 32 or 64-bit application will access different registry space.

You can turn this behavior off by adding bits to the options space of the various registry APIs.   The option bits are titled KEY_WOW64_64KEY and KEY_WOW64_32KEY.  To figure out which one does what, consult this Microsoft documentation.

Say 90% of your program is 32-bit and the other 10% is 64-bit, and say all of your program components need to access COMMON program configuration settings.  You absolutely MUST store the settings in a space that is readable by both 32-bit and 64-bit.  To achieve this, you can tell the various Registry APIs that you want to access a specific registry area; the 32-bit apps can access the 64-bit registry and the 64-bit apps can access the 32.

What’s the point of this post

Back in Windows 2000, the first XenApp (Presentation Server) releases were created to support 64-bit Windows.  We made a big high level decision that ALL of the configuration settings shall be stored in the 32-bit space, all of the time.

Could we have gone with the 64-bit space?  Sure, it was 6 of one vs. a half dozen of the other.  Going with the 32-bit space resulted in less code change as only the 64-bit components had to be changed to use the 32-bit hive – and I’ll add, ignore the 64-bit.

It’s a number of years later now and I’m not sure if this hard rule is still universally respected, but for App Streaming at least, all of the settings are supposed to be in HKLM\Software[WOW6432Node]\Citrix\Rade.  Only occasionally do we SLIP and let one get out in the 64-bit space.  When that happens, it is surely followed by a slew of CPRs to get the settings back where they are supposed to be.

Two hives are really one

There’s this concept that there are separate program areas for 64-bit and 32-bit applications, but most application programmers have no choice but to use only one.  This makes the decision to have separate hives look suspect in retrospect.

I expect there are really good architectural reasons why Microsoft kernel team had to go with this bazaar architecture.  I mean good ones – I don’t accept that it permitted less code to be changed; grep is really good at finding occurrences of “system32” and sed will change them to system64.  Enhance the system to define APIs for querying the location of the “System” directory and most of this would have taken care of itself without having to have a system that looks very much like a hack that got out the door.

If you have a link to a good description of the rationale, please post in a comment.  Oh – don’t put the actual link in the comment though because comments with links are presently blocked by the blog system.

Joe Nord