Windows x64 – All the Same Yet Very Different, Part 6: COM, DLLs and Processes
This is the sixth part of a mini-series on Windows x64, focusing on behind the scene changes in the operating system. In the last article I discussed how 32-bit applications are wrapped up in the WoW64 subsystem. Today we will take a deeper look at some limitations of 64-bit Windows and what they mean in practice. RulesApplication interoperability and execution on Windows x64 is governed by a few simple rules, most of which you already know:
- The kernel cannot execute 32-bit code.
- Support for 16-bit code has been removed.
- The same applies to the OS/2 and Posix subsystems.
- Mixed 32-bit/64-bit processes are not allowed.
Does that sound bad? It certainly adds some complexity.
Mix-ups? Forbidden!
In this post I will focus on rule number 4, which can also be expressed as:
"64-bit applications can only load 64-bit DLLs. 32-bit applications can only load 32-bit DLLs."
Admittedly, the term “DLL” is not entirely correct here. In fact, rule #4 applies to all kinds of modules that can be loaded by a user mode process. Apart from DLLs, OCX files come to mind (those are used for ActiveX controls).
Applying rule #4 to real-world systems reveals several peculiarities which I will try to discuss and explain.
Scripts Using COM Objects
More often than you maybe realize your scripts need the help of DLLs to carry out the tasks they were written for. The underlying technology is called COM (Component Object Model) and has been around for ages. With COM, so-called servers encapsulated in DLLs or OCXs offer their services to any application willing to make use of them. In order to call a function from a COM module, a process locates the module implementing the required interface by its class ID (CLSID) or an easier to remember ProgID (like “DAO.DBEngine” which stands for {00000100-0000-0010-8000-00AA006D2EA4}). Once the CLSID is known, the corresponding module can be found in the following location in the registry: HKEY_CLASSES_ROOT\CLSID\{00000100-0000-0010-8000-00AA006D2EA4}\InprocServer32 points to the file dao360.dll which is a COM server implementing some database functionality.
While this module location mechanism sounds complicated, it is completely opaque to script writers. In Visual Basic Script COM objects are instantiated by calling CreateObject and passing a ProgID. One line of script code causes the OS to look for the DLL containing the desired COM object and to load it into the script engine’s process.
Wait a minute! Didn’t rule #4 state that 64-bit processes can only load 64-bit DLLs? What if only a 32-bit version of a COM DLL is available? In this case the 32-bit version of the script host (WScript.exe or CScript.exe) must be used to execute the script and call the COM object. I recommend you always specify the full path to the script host:
32-bit Script Host: %Systemroot%\SysWOW64\cscript.exe Script-Name 64-bit Script Host:
%Systemroot%\System32\cscript.exe Script-Name
Calling your scripts like this looks ugly and is counter-intuitive, but it works. Until the day you need both a 32-bit and a 64-bit COM DLL in one script…
Internet Explorer Plugins
For reasons you understand very well by now, Windows x64 contains both 32-bit and 64-bit versions of many executables. CScript.exe is one example, Internet Exlorer another. Many web sites require Plugins like Flash. IE Plugins are called ActiveX controls, which is just a fancy name for COM. Sound familiar? 64-bit IE cannot load 32-bit ActiveX controls which are, too, just DLLs or OCX files and more often than not only available in 32-bit versions. In order to use 32-bit Plugins the 32-bit version of Internet Explorer needs to be started:
%Systemdrive%\Program Files (x86)\Internet Explorer\iexplore.exe
Installers and Setup Scripts
Installation routines often need to register COM objects. In many cases this is implemented by calling regsvr32.exe Name-of-COM-DLL. Regsvr32 then loads the DLL and calls the exported function DLLRegisterServer. The problem is obvious: the 32-bit version of regsvr32.exe can only register 32-bit DLLs and vice versa. The appropriate version of regsvr32.exe can be called as follows:
32-bit Script Host: %Systemroot%\SysWOW64\regsvr32.exe Name-of-COM-DLL 64-bit Script Host: %Systemroot%\System32\regsvr32.exe Name-of-COM-DLL
Installers can of course try to load a DLL and call DLLRegisterServer directly, without resorting to regsvr32.exe. In that case you may be out of luck – a 32-bit installer simply cannot call a function from a 64-bit DLL and a 64-bit installer cannot call a function from a 32-bit DLL.
Explorer Add-Ons
Many applications contain Explorer Add-Ons that, for example, extend the context menu of folders or files to offer options for compressing, checking, encrypting, defragmenting (…) the objects selected in Explorer. Again, this works by having Explorer use third-party DLLs provided by the application vendor. The problem is the same as before: your vendor might not provide a 64-bit version of his DLL. In that case, only running the 32-bit version of Explorer helps:
%Systemroot%\SysWOW64\explorer.exe /separate
This concludes today’s article. I may have confused you with System32/SysWOW64, but I promise to explain the meaning of those two directories in the next article, which will cover file system and registry redirection and reflection.