It is possible to register both 32-bit and 64-bit versions of the same COM server on 64-bit machine. This leads to several questions such as how are they registered and which one of the two is used. I will try to answer them below. But first, let’s start with an example.
Example
Let’s say we have the a simple COM local server called COM3264Server.exe. There is just one interface called ICoCOM3264Server. Here is the IDL file:
[
object,
uuid(733C70A7-F7EC-4C15-85D2-5CDB14F4110B),
dual,
nonextensible,
pointer_default(unique)
]
interface ICoCOM3264Server : IDispatch{
[id(1), helpstring("Says hello")] HRESULT SayHello(void);
};
[
uuid(2F25FC66-2380-42FD-8476-8B5917FB1BF1),
version(1.0),
]
library COM3264ServerLib
{
importlib("stdole2.tlb");
[
uuid(9268A299-E817-4C5D-8627-C2582B66F16D)
]
coclass CoCOM3264Server
{
[default] interface ICoCOM3264Server;
};
};
The implementation of the method SayHello() is straight forward; it just displays a message box with a text that varies between the two architectures, x64 and x86.
STDMETHODIMP CCoCOM3264Server::SayHello(void)
{
#ifdef _WIN64
::MessageBox(NULL, _T("Hello from 64-bit COM server!"), _T("COM3264Server"), MB_OK);
#else
::MessageBox(NULL, _T("Hello from 32-bit COM server!"), _T("COM3264Server"), MB_OK);
#endif
return S_OK;
}
Registry
When you register the COM server, the 32-bit and 64-bit versions are registered in different parts of the registry. On 64-bit machine, the registry has two views (or modes):
- a native view, for 64-bit application; (e.g. registry path for CLSIDs is HKEY_CLASSES_ROOT\CLSID\)
- a WOW64 view, which enables redirections for 32-bit applications, a process transparent to the user (e.g. registry path for CLSIDs is HKEY_CLASSES_ROOT\Wow6432Node\CLSID\)
Here is the Registry registration of the (native) 64-bit COM server (notice the registry key in the status bar of the editor, and the path to the server executable).

On, the other hand, the 32-bit COM server is registered under the Wow6432 node.

So if both versions are registered in Windows Registry, which one is picked? Well, both the server and the client can specify which architecture to use:
- the COM server can do this via the PreferredServerBitness Registry value
- the client can do this using one of the flags CLSCTX_ACTIVATE_32_BIT_SERVER and CLSCTX_ACTIVATE_64_BIT_SERVER, which overrides the server preference
If neither the client nor the server specifies a preference, then:
- If the computer that hosts the server is running Windows Server 2003 with Service Pack 1 (SP1) or a later system, then COM will try to match the server architecture to the client architecture. In other words, for a 32-bit client, COM will activate a 32-bit server if available; otherwise it will activate a 64-bit version of the server. For a 64-bit client, COM will activate a 64-bit server if available; otherwise it will activate a 32-bit server.
- If the computer that hosts the server is running Windows XP or Windows Server 2003 without SP1 or later installed, then COM will prefer a 64-bit version of the server if available; otherwise it will activate a 32-bit version of the server.
Server Preference
The server can specify its preferred architecture in the PreferredServerBitness value under AppId (available only on 64-bit Windows). This integer value can be:
- 1: Match the server architecture to the client architecture. For example, if the client is 32-bit, use a 32-bit version of the server, if it is available. If not, the client’s activation request will fail.
- 2: Use a 32-bit version of the server. If one does not exist, the client’s activation request will fail.
- 3: Use a 64-bit version of the server. If one does not exist, the client’s activation request will fail.
Here is the value set in Registry to specify the 64-bit architecture.

When you run the client, it launches the 64-bit version and in my example the following window pops-up:

If I change the value to indicate the 32-bit architecture, the other COM server is launched and the displayed message is:

Client Preference
The client code I used so far looked like this:
ICoCOM3264Server* pServer;
HRESULT hr = ::CoCreateInstance(
CLSID_CoCOM3264Server,
NULL,
CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER,
IID_ICoCOM3264Server,
(void**)&pServer);
if(SUCCEEDED(hr))
{
pServer->SayHello();
pServer->Release();
}
However, the 64-bit version of Windows added new flags to the CLSCTX enumeration.
- CLSCTX_ACTIVATE_32_BIT_SERVER: used to activate or connect to a 32-bit version of the server; fail if one is not registered.
- CLSCTX_ACTIVATE_64_BIT_SERVER: used to activate or connect to a 64 bit version of the server; fail if one is not registered.
As I mentioned earlier, if the client uses one of these flags, it overrides the server preference (specified via the PreferredServerBitness Registry value).
In the following example, the client requests the 64-bit COM server:
HRESULT hr = ::CoCreateInstance(
CLSID_CoCOM3264Server,
NULL,
CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER|CLSCTX_ACTIVATE_64_BIT_SERVER,
IID_ICoCOM3264Server,
(void**)&pServer);
And if you run it, no matter what the server specified, the 64-bit COM server is launched.
To read more about the subject see the MSDN links above.
C++, COM, registry, x64 Hits for this post: 10515 .