COM/DCOM: Architecture, Workflow, and Troubleshooting

Article Overview and Navigation

1. Introduction to COM and DCOM

The Component Object Model (COM) and its distributed extension, Distributed COM (DCOM), are foundational technologies in the Windows ecosystem, enabling software components to interact seamlessly, regardless of the language they were written in or, in the case of DCOM, their location on a network. For developers working within Windows environments, particularly those dealing with inter-process communication, legacy systems, or enterprise applications, a solid understanding of COM and DCOM architecture, operational flows, and troubleshooting techniques is invaluable.

1.1. What are COM and DCOM? Purpose and Evolution

The Component Object Model (COM) is a binary-interface standard for software components introduced by Microsoft. It is not a programming language but rather a specification that allows pre-compiled software components to interact with each other.1 The primary purpose of COM is to enable the creation of reusable software components that can be developed and evolved independently, yet be easily integrated into larger applications by various clients, even if those clients are written in different programming languages.2 COM defines how components expose their functionality through interfaces, which are strongly-typed contracts.1 This approach promotes modularity and reduces dependencies between software modules.

Distributed COM (DCOM) is a natural extension of COM that allows these software components to communicate across network boundaries, such as Local Area Networks (LANs), Wide Area Networks (WANs), or the Internet.4 DCOM achieves this by leveraging Remote Procedure Call (RPC) mechanisms to make remote objects appear as if they are local to the client application.4 The transition from COM to DCOM was driven by the increasing need for distributed applications, allowing developers to leverage COM's robust component-based architecture for network-enabled scenarios. This evolution meant that the core COM concepts of objects and interfaces were preserved, with DCOM adding the necessary remoting layer.

Historically, COM formed the basis for other Microsoft technologies like Object Linking and Embedding (OLE), used for creating compound documents, and ActiveX, for creating downloadable executable content for web pages. Its influence is still seen in many parts of the Windows operating system and numerous enterprise applications.6

1.2. Benefits and Use Cases

COM and DCOM offer several key benefits:

  • Language Independence: Components can be written in various languages (e.g., C++, Visual Basic, Delphi) and still interoperate, as communication occurs at a binary level through defined interfaces.2
  • Code Reuse: Pre-built and tested components can be reused across multiple applications, reducing development time and improving reliability.1
  • Location Transparency (DCOM): Client applications can interact with COM objects without needing to know whether the object is in the same process, a different process on the same machine, or on a remote machine. DCOM handles the underlying communication complexities.5
  • Process Isolation: Out-of-process COM servers run in their own address space, protecting the client application from crashes in the server and vice-versa.
  • Versioning: COM's interface immutability rules help manage component evolution, allowing new versions of components to be introduced without breaking existing client applications that rely on older interface versions.

Common use cases for COM and DCOM include:

  • Pluggable Components: Developing applications with extensible architectures where new functionality can be added via COM components.
  • Automation: Scripting and controlling applications programmatically, such as automating Microsoft Office applications from scripts or other programs.
  • Inter-Process Communication (IPC): Facilitating communication between different processes running on the same machine.
  • Distributed Enterprise Applications: Building applications where different parts of the application logic reside on different servers, common in multi-tier architectures.5
  • Remote Administration and Management: Many Windows remote administration tools and services, like Windows Management Instrumentation (WMI) and parts of Active Directory management, utilize DCOM for their operation.6 The widespread use of DCOM in core Windows services and enterprise applications implies that developers beyond direct COM component creators might encounter DCOM-related issues. For instance, troubleshooting Active Directory replication, Exchange Server connectivity, or remote WMI queries may involve diagnosing underlying DCOM communication problems. This highlights the broader relevance of DCOM knowledge.

1.3. Core Acronyms and Terminology

Understanding COM and DCOM requires familiarity with several key acronyms and terms. The following table provides a quick reference:

Core COM/DCOM Acronyms and Terminology
Acronym Full Name Brief Description
CLSID Class Identifier A Globally Unique Identifier (GUID) that uniquely identifies a COM class or component type.1
IID Interface Identifier A GUID that uniquely identifies a COM interface.2
AppID Application Identifier A GUID used to group configuration and security settings for one or more DCOM server applications.10
ProgID Programmatic Identifier A human-readable string, like "Excel.Application", that can be mapped to a CLSID.10
VersionIndependentProgID Version Independent ProgID A ProgID that always refers to the latest installed version of a COM component.11
LIBID Library Identifier A GUID that uniquely identifies a type library.10
HRESULT Handle to Result A 32-bit value used in COM to return error and success codes from function calls.14
RPC Remote Procedure Call A protocol that allows a program on one computer to execute code on another computer.4
ORPC Object RPC The RPC protocol extensions used by DCOM for remote object communication.7
IDL Interface Definition Language A language used to describe the interfaces of COM components, their methods, and parameters.4
MIDL Microsoft IDL Compiler The compiler that processes IDL files to generate type libraries, headers, and proxy/stub code.4
TLB Type Library A binary file (.tlb) containing metadata about COM components, interfaces, and methods.4
STA Single-Threaded Apartment A COM threading context where objects are accessed by a single thread, and calls are serialized.15
MTA Multi-Threaded Apartment A COM threading context where objects can be accessed concurrently by multiple threads.15
NTA Neutral-Threaded Apartment A COM threading context allowing objects to be called from any thread without a thread switch.17
SCM Service Control Manager A system service involved in locating and launching COM servers.1

2. Core COM Architecture

The architecture of COM is built upon several fundamental concepts that enable its powerful features of interoperability, versioning, and language independence. Understanding these building blocks is essential for any developer working with COM or DCOM.

2.1. The IUnknown Interface: The Foundation

At the very core of COM lies the IUnknown interface. Every COM interface must, directly or indirectly, inherit from IUnknown.19 It serves as the base contract through which clients can manage the lifetime of an object and discover its other functionalities. IUnknown defines three fundamental methods:

  • QueryInterface(REFIID riid, void **ppvObject): This method is the cornerstone of COM's polymorphism and extensibility. A client calls QueryInterface to ask an object if it supports a specific interface, identified by its Interface Identifier (REFIID, which is a reference to an IID). If the object supports the requested interface, it increments the interface's reference count and returns a pointer to that interface via the ppvObject output parameter. If not, it returns an error (typically E_NOINTERFACE) and sets ppvObject to NULL.19 The ability to query for interfaces at runtime allows components to expose multiple, distinct sets of functionalities and for clients to dynamically adapt to the capabilities of a component. This design is pivotal for COM's flexibility, as it allows components to evolve by adding new interfaces without breaking existing clients that are unaware of these new capabilities.
  • AddRef(): This method increments a per-interface reference count maintained by the COM object.19 Each time a client obtains a new pointer to an interface (e.g., through QueryInterface, or by copying an existing pointer that will have an independent lifetime), it must call AddRef on that pointer. This signals to the object that there is one more reference to it. The return value of AddRef is the new reference count, but Microsoft documentation explicitly states this value should only be used for testing purposes, not for programmatic logic.20
  • Release(): This method decrements the interface reference count.19 When a client has finished using an interface pointer, it must call Release. If the reference count drops to zero, it means no clients are using that interface (or, more accurately, the object itself if all interface reference counts on the object are zero and it uses a per-object reference count). At this point, the object is free to destroy itself and release any resources it holds. This reference counting mechanism is COM's way of managing object lifetimes without relying on a garbage collector.

Callers must adhere to strict rules for AddRef and Release. For example, if a method returns a copy of an interface pointer, it must call AddRef on that pointer before returning it. Similarly, if an interface pointer is passed as an in-out parameter to a method, the caller must AddRef it before the call, and the method is expected to Release the incoming pointer before overwriting it with an outgoing value.20

While IUnknown is fundamental, .NET developers working with COM interop might encounter System.Runtime.InteropServices.ICustomQueryInterface. This allows managed code to provide a custom implementation of QueryInterface, but it has limitations; notably, it cannot be used to customize the behavior for IID_IUnknown itself.21 This underscores the truly foundational and unalterable nature of IUnknown's core contract.

2.2. COM Interfaces: Contracts, IIDs, and v-tables

A COM interface is more than just a collection of functions; it is an immutable, binary contract that defines a set of semantically related operations a COM object can perform.2 It's crucial to understand what a COM interface is not:

  • It is not a C++ class. While a C++ class might be used to implement an interface, the interface definition itself carries no implementation.2
  • It is not an object. It is the means by which clients and objects communicate.2

Each COM interface is uniquely identified at runtime by an Interface Identifier (IID), which is a Globally Unique Identifier (GUID).2 This ensures that interface names are unique across all vendors and components, eliminating the possibility of collisions that could arise with string-based naming schemes.2

When a client obtains an interface pointer to a COM object, what it actually receives is a pointer to a v-table (virtual function table).2 A v-table is an array of function pointers, where each entry in the array points to the actual implementation of an interface method. If an object implements multiple interfaces, it will have multiple v-tables, one for each interface. This v-table mechanism is what enables language independence; as long as a programming language can call functions through pointers and adhere to the v-table layout, it can interact with COM objects. The client calls interface methods by name (in languages like C++ that support this through compiler magic) or by their ordinal position in the v-table. The compiler can use the interface definition (often from a header file generated from IDL) to perform type checking on parameters and return values.2

A critical characteristic of COM interfaces is their immutability.2 Once an interface is defined and published with a specific IID, its definition (the methods, their signatures, and their semantics) cannot be changed. If new functionality needs to be added, or existing functionality modified, a new interface with a new IID must be created. An object can then implement both the old and new interfaces, allowing existing clients to continue using the old interface while new clients can take advantage of the new one. This strict immutability, enforced by unique IIDs, is a cornerstone of COM's versioning strategy and ensures that introducing new component versions doesn't break existing applications.

2.3. COM Objects (Components) and Classes (CLSIDs). Encapsulation.

A COM object, also referred to as a COM component, is an instance of a COM class that provides an implementation for one or more COM interfaces.1 These are the actual entities that clients interact with to perform work.

Each COM class is uniquely identified by a Class Identifier (CLSID), which, like an IID, is a GUID.1 The CLSID ensures that every COM class has a globally unique name, preventing conflicts even if different vendors create classes with the same human-readable name (e.g., "CMyObject").1 Developers can obtain new CLSIDs using tools like uuidgen.exe or functions like CoCreateGuid.1

Encapsulation in COM is achieved strictly through interfaces.1 Clients can only interact with a COM object via the methods exposed by its interfaces. The internal implementation details, data structures, and state of the object are hidden from the client unless explicitly exposed through an interface method.1 This adheres to the object-oriented principle of encapsulation, promoting modularity and reducing coupling between clients and components. The client depends on the contract (the interface), not the specific implementation.

The interaction model in COM is typically a client/server relationship.1

  • The client is any code that requests and uses a COM object.
  • The server is a module (typically a Dynamic Link Library - DLL, or an Executable - EXE) that houses the COM class implementations and provides objects to clients. When a client wants to create an object, it usually provides the CLSID of the desired class to the COM runtime.1

2.4. Type Libraries and Interface Definition Language (IDL)

While interfaces define the binary contract, Type Libraries (.tlb files) provide rich metadata about COM components, their classes, interfaces, methods, parameters, and data types.3 A type library is a binary file that allows applications and development tools to query this information at runtime.

Type libraries serve several crucial roles:

  1. Interface Discovery: Applications can use a type library to determine which interfaces an object supports and the signatures of its methods.4
  2. Cross-Language Invocation: They facilitate calling COM objects from different programming languages by providing a common description format.4
  3. Automatic Marshalling: The COM/DCOM runtime can use the information in a type library to automatically marshal (package and unpackage) data for interface calls across apartments, processes, or machines, especially for interfaces marked as oleautomation or dual.3

The definitions for interfaces, classes, and type libraries are typically written in Interface Definition Language (IDL).4 IDL is a descriptive language, not an implementation language. An .idl file specifies the "on-the-wire" characteristics of an interface, detailing how data is structured for transmission. An optional Application Configuration File (.acf) can specify local details like binding handles or custom marshalling for complex types.4

Microsoft provides the MIDL compiler (Midl.exe) which processes these .idl (and .acf) files.4 Depending on the IDL content, MIDL can generate:

  • C/C++ header files (.h) declaring the interfaces and data types.
  • Source code for proxy/stub DLLs, which handle marshalling for custom interfaces that are not oleautomation compatible.4
  • The binary type library (.tlb) file itself, if a library block is present in the IDL.4
  • Interface UUID files (_i.c) containing definitions for IIDs and CLSIDs.

2.5. The COM Library (ole32.dll) and Threading Apartments

The COM Library, primarily implemented in ole32.dll (and also involving Rpcss.exe for some services), provides the fundamental runtime services necessary for COM applications to function.15 These services include:

  • Functions for object creation (e.g., CoCreateInstance).
  • Locating component implementations (typically via the registry).
  • Managing inter-process and remote communication (transparent RPC for DCOM).
  • A standard memory allocation mechanism (CoTaskMemAlloc, CoTaskMemFree) for memory shared between components.

A critical concept managed by the COM Library is threading apartments. Apartments are a mechanism by which COM addresses concurrency and thread-safety issues for objects that may not be designed to be freely thread-safe. Each thread that uses COM objects must belong to an apartment. There are three main types of apartments:

  • Single-Threaded Apartment (STA):
    • An STA is associated with a single, specific thread. All method calls to objects residing in an STA are executed on that single thread.15
    • COM serializes incoming calls to objects in an STA using a hidden window and its message queue. This means only one method call can execute on an STA object at any given time.
    • STAs are typically required for components that have a user interface (UI) or use thread-affine resources (e.g., many older UI controls).16
    • A thread enters an STA by calling CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) or the older CoInitialize(NULL) function.15
    • In-process components designed for STAs are registered with the ThreadingModel=Apartment value under their InprocServer32 registry key.17
  • Multi-Threaded Apartment (MTA):
    • An MTA can contain multiple threads. Objects residing in an MTA can be called directly by any thread within that MTA, potentially simultaneously.15
    • MTA objects must therefore be designed to be thread-safe; they are responsible for their own internal synchronization (e.g., using critical sections, mutexes).15
    • A thread enters the process-wide MTA by calling CoInitializeEx(NULL, COINIT_MULTITHREADED).15 There is at most one MTA per process.
    • In-process components designed for MTAs are registered with ThreadingModel=Free.29
  • Neutral-Threaded Apartment (NTA) / ThreadingModel=Neutral:
    • The NTA was introduced with COM+ primarily for server-side components that do not have a UI, aiming to simplify multithreaded programming and improve scalability compared to the traditional MTA, especially in scenarios involving calls from STA clients.17
    • Objects marked as ThreadingModel=Neutral reside in the NTA. The key characteristic of NTA objects is that they can be called by any thread (STA or MTA) within the process without requiring a thread switch into the NTA.17 The method call executes on the caller's thread. This avoids the performance overhead associated with marshalling and thread context switches that occur when an STA thread calls an MTA object directly.
    • Like MTA objects, NTA objects must be thread-safe. There is only one NTA per process.17
    • Components are registered with ThreadingModel=Neutral.17

The ThreadingModel attribute, registered for an in-process component, is crucial. It informs the COM runtime about the component's threading requirements, allowing COM to ensure that the component is created and accessed in a compatible apartment, potentially by using proxies and stubs for marshalling if direct calls are not possible due to apartment mismatches. Components can also be marked as ThreadingModel=Both, indicating they are thread-safe and can be created in an STA or MTA. The choice of apartment model and ThreadingModel registration has profound implications for a component's performance, reentrancy, and interaction with clients and other components. For instance, an STA thread creating an MTA component will involve COM creating a proxy for the STA thread to call, and a stub in the MTA to call the actual object, incurring marshalling overhead even if the component is in-process. The NTA was designed to mitigate such overhead for suitable components.

3. COM Object Lifecycle and Local Activation Workflow

The lifecycle of a COM object, from creation to destruction, and the process by which it is activated locally, involves a coordinated effort between the client application, the COM library, and the COM server. Understanding this workflow is fundamental to diagnosing activation and runtime issues.

3.1. Initializing the COM Library: CoInitializeEx and CoUninitialize

Before a thread can use most COM services, it must initialize the COM library for that thread. This is typically done by calling the CoInitializeEx function.15 The older CoInitialize function can also be used, which is equivalent to calling CoInitializeEx with the COINIT_APARTMENTTHREADED flag.15

CoInitializeEx takes two parameters:

  • pvReserved: This parameter is reserved and must always be NULL.15
  • dwCoInit: This parameter specifies the concurrency model for the thread and is a value from the COINIT enumeration. The most common values are:
    • COINIT_APARTMENTTHREADED: Initializes the thread as part of a Single-Threaded Apartment (STA).15
    • COINIT_MULTITHREADED: Initializes the thread as part of the process's Multi-Threaded Apartment (MTA).15

A thread must call CoInitializeEx (or CoInitialize) at least once before calling other COM library functions (except for memory allocation functions like CoGetMalloc). Subsequent calls to CoInitializeEx on the same thread are allowed as long as they specify the same concurrency model. The first successful call returns S_OK. Subsequent valid calls with the same flag return S_FALSE. If a thread attempts to initialize COM with a different concurrency model than a previous initialization, CoInitializeEx fails and returns RPC_E_CHANGED_MODE.15

Critically, every successful call to CoInitializeEx (including those that return S_FALSE) must be balanced by a corresponding call to CoUninitialize.15 CoUninitialize closes the COM library on the current thread, releases any resources the library maintains for the thread, and forces all RPC connections on the thread to close. Failing to call CoUninitialize can lead to resource leaks and unpredictable behavior, especially when threads terminate. It's important to note that CoInitializeEx and CoUninitialize should not be called from the DllMain function of a DLL, as this can lead to deadlocks or other initialization order problems.15

3.2. Creating COM Objects: The Client's Perspective

Once the COM library is initialized on a thread, the client can create instances of COM objects. There are several ways to do this, with CoCreateInstance being the most common for local objects.

3.2.1. CoCreateInstance: The Common Path

The CoCreateInstance function provides the simplest and most direct way for a client to create a single instance of a COM object on the local machine.1 Its signature is:

HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv);

  • rclsid: The CLSID of the COM class to be instantiated.31
  • pUnkOuter: A pointer to the controlling IUnknown if the object is being created as part of an aggregate. For most use cases, this is NULL, indicating no aggregation.31
  • dwClsContext: Specifies the context in which the server code will run. Common values from the CLSCTX enumeration include:
    • CLSCTX_INPROC_SERVER: The server is a DLL loaded into the client's process.
    • CLSCTX_LOCAL_SERVER: The server is an EXE running in a separate process on the same machine.
    • CLSCTX_REMOTE_SERVER: The server is on a remote machine (used with DCOM).
    • CLSCTX_ALL: A combination of the above, allowing COM to choose the appropriate server type based on registration.31
  • riid: The IID of the interface the client wishes to obtain on the newly created object.31
  • ppv: An output parameter that receives the interface pointer if the call is successful.31

CoCreateInstance conveniently encapsulates a sequence of operations: it first calls CoGetClassObject to get a pointer to the class factory for the specified CLSID, then calls IClassFactory::CreateInstance on that factory to create the object instance, and finally calls Release on the class factory pointer.31

3.2.2. CoGetClassObject and IClassFactory

For scenarios requiring more control, such as creating multiple instances of the same object class or interacting directly with the class factory, clients can use CoGetClassObject.1 Its signature is:

HRESULT CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved, REFIID riid, LPVOID *ppv);

  • rclsid, dwClsContext, ppv: Similar to CoCreateInstance.
  • pvReserved: For local activation, this is typically NULL. For remote activation (DCOM), this parameter can point to a COSERVERINFO structure specifying the remote machine.33
  • riid: Usually IID_IClassFactory, requesting a pointer to the IClassFactory interface.33

A class factory is a COM object that implements the IClassFactory interface (or related interfaces like IClassFactory2 for licensing). Its primary role is to create instances of a specific COM class.1 Each COM server (DLL or EXE) that exposes creatable COM classes must provide a class factory object for each such class.

The IClassFactory interface has two main methods:34

  1. CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObject): This method creates an uninitialized instance of the COM object that the factory serves.34
    • pUnkOuter: Pointer to the controlling IUnknown for aggregation (usually NULL). If non-NULL, riid must be IID_IUnknown.35
    • riid: The IID of the interface desired on the new object.
    • ppvObject: Receives the interface pointer. The server's implementation of CreateInstance is responsible for manufacturing a new object instance and returning the requested interface pointer. The object must be created in an apartment belonging to the server's DCOM resolver and not in a remote apartment.35 After creation, the object typically needs to be initialized via an interface like IPersistStorage, IPersistStream, or IPersistFile.1
  2. LockServer(BOOL fLock): This method allows a client to keep the COM server application loaded in memory, even if no objects are currently instantiated.34
    • fLock = TRUE: Increments an internal lock count on the server.
    • fLock = FALSE: Decrements the lock count. When the lock count and the total object reference count are both zero, the server can shut down. This can improve performance when creating multiple objects in succession by avoiding repeated server load/unload cycles. Calls to LockServer(TRUE) must be balanced with calls to LockServer(FALSE).36

3.3. Component Registration: The Server's Story and System Configuration

For COM to locate and activate components, they must be registered in the Windows Registry. This registration provides COM with the metadata it needs, such as the mapping from a CLSID to the server file that implements it.

3.3.1. The Windows Registry: The Heart of COM Configuration

The Windows Registry is the central repository for COM component configuration.1

  • HKEY_CLASSES_ROOT (HKCR): This is the primary registry hive that COM consults. HKCR is a merged view of two other locations:10
    • HKEY_LOCAL_MACHINE\Software\Classes (HKLM): Contains default COM registration settings that apply to all users on the local computer.
    • HKEY_CURRENT_USER\Software\Classes (HKCU): Contains COM registration settings that apply only to the currently logged-in interactive user. Settings in HKCU take precedence over those in HKLM.39 This merged view is primarily for backward compatibility. Modern applications, especially those requiring administrator rights or running as services, should generally register components under HKLM for system-wide availability.39
  • Key Registry Paths and Their Significance: The following table summarizes critical COM registry locations and their purpose. This information is indispensable for troubleshooting registration and activation problems, as it demystifies how COM finds and loads components.
Critical COM Registry Paths and Their Significance (under HKCR)
Registry Path (under HKCR) Key Subvalues/Subkeys Purpose/Significance
CLSID\{CLSID_GUID} (Default) (Name), InprocServer32, LocalServer32, ProgID, VersionIndependentProgID, AppID, ThreadingModel (under InprocServer32) Core registration for a COM class. Maps CLSID to server path and threading model.1
ProgID\<Vendor.Component.Version> CLSID subkey (value is CLSID GUID), CurVer subkey Maps a version-specific human-readable ProgID to a CLSID. CurVer points to the ProgID of the current version.10
VersionIndependentProgID\<Vendor.Component> CLSID subkey (value is CLSID GUID), CurVer subkey Maps a version-independent ProgID to a CLSID, typically pointing to the latest version.10
Interface\{IID_GUID} (Default) (Name), NumMethods, ProxyStubClsid32 Registers interface metadata, including the CLSID of the proxy/stub DLL used for marshalling this interface across apartments or processes.10
TypeLib\{LIBID_GUID} Version subkey (e.g., 1.0), Flags, HELPDIR, locale subkey (e.g., 0\win32) with path to .tlb file Registers type libraries, providing metadata for automation and marshalling.10
AppID\{AppID_GUID} (Default) (Name), DllSurrogate, LaunchPermission, AccessPermission, RemoteServerName, RunAs Stores DCOM configuration and security settings for a server application (EXE).10

The InprocServer32 key under a CLSID entry specifies the path to an in-process (DLL) server and its ThreadingModel (e.g., Apartment, Free, Both, Neutral).27, 29 The LocalServer32 key specifies the path to an out-of-process (EXE) server, potentially including command-line arguments like -Embedding which COM appends to indicate activation by COM.27, 41

3.3.2. Server Self-Registration

COM servers are typically responsible for creating their own registry entries.

  • DLL Servers (regsvr32.exe):
    • The regsvr32.exe <dllpath> command-line utility loads the specified DLL and calls its exported DllRegisterServer function.12
    • The DllRegisterServer function contains the code to write all necessary registry keys and values for the COM classes and interfaces implemented in the DLL (e.g., CLSID, ProgID, InprocServer32, ThreadingModel, TypeLib registration).12
    • To unregister, regsvr32.exe /u <dllpath> calls the DLL's DllUnregisterServer function, which should remove the entries created by DllRegisterServer.12
  • EXE Servers (/RegServer, /UnregServer):
    • Out-of-process (EXE) servers typically support command-line arguments for self-registration. Launching the server executable with /RegServer (or sometimes -RegServer) instructs it to create its registry entries, primarily the CLSID key with a LocalServer32 subkey pointing to itself, and ProgID entries.47
    • The /UnregServer (or -UnregServer) argument instructs the EXE to remove its registry entries.47

3.3.3. Registration-Free COM (Side-by-Side Activation)

As an alternative to global registry entries, Windows supports Registration-Free COM. This allows applications to use COM components by deploying them with an application manifest file (XML format) that describes the components and their CLSIDs.37 When an application with such a manifest calls CoCreateInstance, COM first searches the active activation context (derived from the manifest) for the component. If found, it uses the information from the manifest to load the component, bypassing the global registry. If not found in the activation context, COM falls back to the usual registry lookup.37 This is particularly useful for XCOPY deployment and avoiding "DLL Hell" by isolating component dependencies on a per-application basis.

3.3.4. MSI Installer Registration

For robust deployment, Windows Installer (MSI) packages are the preferred method for installing and registering COM components. MSI uses a declarative approach, where COM registration information is stored in various tables within the MSI database.27 Key tables include:

  • Class table: Contains CLSID information, server context, path to the server file (InprocServer32, LocalServer32), ProgID, AppID, and ThreadingModel.27
  • ProgId table: Defines ProgIDs and their associated CLSIDs.
  • TypeLib table: Registers type libraries.
  • AppId table: Configures AppID settings for DCOM.48
  • Registry table: Can be used for other custom registry entries.

The COM server file (DLL or EXE) is typically the key path of its Windows Installer component.49 During installation, Windows Installer actions like RegisterClassInfo and UnregisterClassInfo process these tables to write or remove the COM registration information from the system registry.48 This provides a transactional and reliable way to manage COM component registration and unregistration.

3.4. Local Activation Workflow: CoCreateInstance Internals

The seemingly simple CoCreateInstance call initiates a complex sequence of operations within the COM subsystem. Understanding these internal steps is crucial for troubleshooting activation failures, as the abstraction can otherwise make diagnosis opaque.

  1. Client Call: The client application, after initializing COM on its thread via CoInitializeEx, calls CoCreateInstance(CLSID_Foo, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_IFoo, &pIFoo).
  2. COM Library (ole32.dll) Interception: The call is handled by the COM library loaded in the client's process.
  3. Registration-Free COM Check: If an application manifest defining an activation context is active for the client process, COM first searches this context for CLSID_Foo.37 If found, COM uses the manifest information to locate and load the server, bypassing the registry.
  4. Registry Lookup (Fallback or No Manifest): If not found via Reg-Free COM, the COM library proceeds with registry-based activation. It needs to find the server that implements CLSID_Foo.
  5. SCM Involvement (for Out-of-Process Servers):
    • If CLSCTX_LOCAL_SERVER is specified (or implied by CLSCTX_ALL and no in-process server is found/preferred), the COM library communicates with the local Service Control Manager (SCM). The SCM is a system service (part of services.exe) responsible for locating and launching out-of-process COM servers.1
    • For CLSCTX_INPROC_SERVER, the COM library can often handle loading directly without SCM involvement for the launch itself, though SCM might be queried for registration data.
  6. CLSID Lookup in Registry: The COM library (or SCM) queries the registry, primarily HKCR\CLSID\{CLSID_Foo}.1
  7. Server Type Determination and Loading/Launching:
    • If InprocServer32 subkey exists:
      • COM reads the path to the DLL server from this key's default value.
      • It also reads the ThreadingModel value.
      • The COM library loads the DLL into the client's process address space using LoadLibraryEx.
      • It then calls the DLL's exported DllGetClassObject function, passing CLSID_Foo and IID_IClassFactory, to request a pointer to the class factory object: DllGetClassObject(CLSID_Foo, IID_IClassFactory, &pCF).
    • If LocalServer32 subkey exists (and no suitable in-proc server was used):
      • The SCM reads the path to the EXE server from this key.
      • The SCM checks if an instance of this server EXE is already running and has registered a class factory for CLSID_Foo.
      • If not running, or if the running instance hasn't registered the factory, the SCM launches the server EXE. The command line often includes an -Embedding or /Embedding argument to signal to the server that it's being launched by COM.41
      • The newly launched EXE server, during its startup sequence, is responsible for creating its class factory object(s) and registering them with COM by calling CoRegisterClassObject(CLSID_Foo, pCF_Foo, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegister). This makes the class factory pCF_Foo available to the SCM and, through it, to clients.
      • The SCM obtains the IClassFactory pointer from the registered class objects.
  8. Class Factory Interaction: At this point, COM (either directly for in-proc or via the SCM for out-of-proc) has an IClassFactory* pCF pointer to the class factory for CLSID_Foo.
  9. Object Instantiation: COM calls pCF->CreateInstance(pUnkOuter, riid, &pIFoo) (where pUnkOuter is from the original CoCreateInstance call, usually NULL, and riid is IID_IFoo).31 The class factory's CreateInstance method manufactures a new instance of the Foo object and returns the IFoo interface pointer.
  10. Release Class Factory: COM calls pCF->Release() to release its hold on the class factory.
  11. Return to Client: CoCreateInstance returns the pIFoo interface pointer (now pointing to the actual Foo object or its proxy) to the client application.

This entire intricate process is hidden behind the single CoCreateInstance call. The reliance on correct registry entries is paramount; a missing CLSID key, an incorrect server path in InprocServer32 or LocalServer32, or a server that fails to register its class factory will break this chain, leading to common activation errors such as REGDB_E_CLASSNOTREG or CO_E_SERVER_EXEC_FAILURE. Furthermore, the interaction between the thread's apartment type (set by CoInitializeEx) and the server's registered ThreadingModel is critical. If they are incompatible (e.g., an STA thread trying to directly use an MTA-only in-proc component), COM may need to insert marshalling proxies and stubs even for local calls, which can impact performance or, if proxies are unavailable, lead to errors.

4. DCOM Architecture: Extending COM Across the Network

Distributed COM (DCOM) extends the principles of the Component Object Model to allow objects to communicate across process and machine boundaries. It builds upon COM's foundation by adding the mechanisms necessary for network communication, while striving to maintain location transparency for the client.

4.1. Introduction to DCOM: Principles and Goals

DCOM enables software components to interact as if they were on the same machine, even when they are distributed across a network.5 This is achieved by using an underlying network protocol called Object RPC (ORPC), which is an extension of DCE RPC.4

The primary goal of DCOM is location transparency.5 Ideally, client code written to interact with a COM object should not need to be modified whether that object is local (in-process or out-of-process on the same machine) or remote (on a different machine). DCOM aims to hide the complexities of network communication from the application developer, allowing them to focus on the application logic rather than the intricacies of network programming.5 This transparency is crucial for building scalable and flexible distributed systems where components can be deployed on different machines for performance, security, or organizational reasons.

4.2. Marshalling: The Key to Remote Communication

For DCOM to achieve location transparency, it must have a way to transmit method calls and their parameters from the client process to the server process (which might be on a different machine) and return results. This process is known as marshalling.3 Marshalling involves:

  1. Packaging the interface method identifier and all its parameters (including in, out, and in-out parameters) into a standardized, network-transmissible format on the client side.
  2. Transmitting this packaged data over the network to the server.
  3. Unpackaging (unmarshalling) the data on the server side, reconstructing the method call, and invoking the actual method on the server object.
  4. After the server method executes, marshalling any return values and out parameters on the server side.
  5. Transmitting this data back to the client.
  6. Unmarshalling the results on the client side and returning them to the client code.

This entire process is typically handled by COM-provided or generated infrastructure, making it largely transparent to the client and server object implementations.

4.2.1. Proxies and Stubs

The core components responsible for marshalling in DCOM are proxies and stubs.3

  • Proxy: A proxy is an object that resides in the client's process space. It has the same interface as the actual remote object. When the client calls a method on what it believes to be the remote object, it is, in fact, calling a method on this local proxy. The proxy's implementation of that method is responsible for marshalling the call parameters and forwarding them to the server where the actual object resides.23
  • Stub: A stub is an object that resides in the server's process space. It receives the marshalled data from the client's proxy. The stub unmarshals this data, reconstructs the original method call arguments, and then calls the corresponding method on the actual server object. After the server object's method completes, the stub marshals any return values and out parameters and sends them back to the client-side proxy.23 The client-side proxy then unmarshals these results and returns them to the client application.

The proxy-stub pair effectively creates a communication channel that makes the remote method invocation appear as a local call to both the client and the server object. The existence and operation of proxies and stubs are generally hidden from the application developer when using standard marshalling.

4.2.2. Standard vs. Custom Marshalling

COM provides two main approaches to marshalling:

  • Standard Marshalling: This is the most common approach. COM can automatically handle the marshalling for interfaces if it has enough information about them. This information can come from:
    • Type Libraries: For interfaces that are "OLE Automation compatible" (typically those defined with the oleautomation or dual attribute in IDL), COM's "Automation marshaller" can use the type library metadata to marshal parameters.3 This is very convenient as it doesn't require a separate proxy/stub DLL for these interfaces.
    • Proxy/Stub DLLs: For custom interfaces that are not OLE Automation compatible, or when type library marshalling is not used, a dedicated proxy/stub DLL is required. This DLL contains the interface-specific proxy and stub code generated by the MIDL compiler from the IDL definition of the interface.4 This DLL must be registered on both the client and server machines.
  • Custom Marshalling: For advanced scenarios, COM allows a component to take complete control over the marshalling process by implementing the IMarshal interface. This might be done for performance optimization with very specific data types, or when data needs to be marshalled in a non-standard way (e.g., passing object references by value rather than by proxy). Custom marshalling is significantly more complex to implement and is generally not needed for typical DCOM applications.

The effectiveness of DCOM's location transparency is entirely reliant on this marshalling infrastructure. If the necessary marshalling information (e.g., a registered type library for an automation interface, or a registered proxy/stub DLL for a custom interface) is missing on either the client or server side, remote calls will fail, often with errors like E_NOINTERFACE or RPC errors, even if network connectivity to the server is otherwise fine.

4.2.3. Role of Type Libraries in Marshalling

As mentioned, type libraries play a significant role in standard marshalling.3 When an interface is defined in IDL and marked as oleautomation (or is a dispinterface or dual interface), the MIDL compiler includes sufficient information in the generated type library for the COM runtime's universal marshaller (also known as the Automation marshaller) to handle the marshalling of parameters for that interface's methods. This eliminates the need for a separate, interface-specific proxy/stub DLL for such interfaces.

However, if an interface is a custom interface (derived directly from IUnknown or another custom interface, and not marked oleautomation), the type library alone is generally not sufficient for marshalling across process or machine boundaries. In such cases, developers must use the MIDL compiler to generate a proxy/stub DLL from the IDL definition.4 This DLL contains the specific code to marshal and unmarshal the parameters for each method of that custom interface. This proxy/stub DLL must then be registered on both the client and server machines under the HKCR\Interface\{IID_of_custom_interface}\ProxyStubClsid32 key, pointing to the CLSID of the proxy/stub implementation. The marshalling process itself introduces overhead, particularly for network calls. The amount of data, its complexity, and the efficiency of the marshaller can affect DCOM application performance.

5. DCOM Workflow: Remote Object Activation and Communication

Activating and communicating with a COM object on a remote machine involves a more complex workflow than local activation, introducing network communication, remote security checks, and coordination between services on both the client and server machines.

5.1. Client-Side Remote Activation

The primary function used by clients to create COM objects on remote machines is CoCreateInstanceEx.31 This function extends CoCreateInstance by allowing the client to specify the target server and request multiple interfaces in a single call, reducing network round trips.

The syntax for CoCreateInstanceEx is:

HRESULT CoCreateInstanceEx(REFCLSID Clsid, IUnknown *punkOuter, DWORD dwClsCtx, COSERVERINFO *pServerInfo, DWORD dwCount, MULTI_QI *pResults);

Key parameters for remote activation:

  • Clsid: The CLSID of the object to be created remotely.51
  • dwClsCtx: Must include CLSCTX_REMOTE_SERVER to indicate remote activation.51 Aggregation (punkOuter!= NULL) is not supported for cross-process or cross-computer activation.51
  • pServerInfo: A pointer to a COSERVERINFO structure that specifies details about the remote server.51
    • The COSERVERINFO structure is crucial for remote activation.53 Its members include:
      • pwszName: A string containing the name of the remote computer (e.g., "MyRemoteServer", "192.168.1.100").52
      • pAuthInfo: A pointer to a COAUTHINFO structure, allowing the client to specify custom authentication information for the activation call. If NULL, default activation security is used.53 If pServerInfo is NULL in the CoCreateInstanceEx call, COM attempts to determine the remote server based on registry settings (specifically, the RemoteServerName value associated with the component's AppID on the client machine) or defaults to the local computer if CLSCTX_REMOTE_SERVER is not the only context specified or if no remote configuration is found.51
  • dwCount and pResults: Used for requesting multiple interfaces (MULTI_QI) simultaneously.51

CoCreateInstanceEx, much like its local counterpart, encapsulates the steps of connecting to the class object (this time on the remote server), creating an instance via IClassFactory::CreateInstance, and releasing the class factory.51

Implicit Remote Activation using RemoteServerName and AppID:

If a client calls CoCreateInstance with CLSCTX_REMOTE_SERVER (or CLSCTX_ALL where remote is chosen) or CoCreateInstanceEx with a NULL pServerInfo, COM on the client machine can use local registry settings to determine the target server. This is known as client-side DCOM configuration:

  1. COM looks up HKCR\CLSID\{CLSID_GUID}\AppID to find the Application Identifier (AppID) associated with the requested CLSID.40
  2. It then consults HKCR\AppID\{AppID_GUID}\RemoteServerName.44
  3. If the RemoteServerName value exists and specifies a server name, COM will direct the activation request to that server. This allows administrators to redirect COM activations without modifying client code.

5.2. Server-Side Remote Activation: The SCM and DCOM Services

When a remote activation request reaches the server machine, several system services orchestrate the process of locating, launching (if necessary), and providing access to the COM server.

  • The Service Control Manager (SCM - services.exe) on Client and Server:
    • On the client side, when CoCreateInstanceEx is called with remote parameters, the client's COM library (ole32.dll) communicates with the local SCM (which runs within services.exe). This local SCM then forwards the activation request, via RPC, to the SCM on the target remote server specified in COSERVERINFO or by the RemoteServerName registry value.1
    • The SCM on the server machine receives this incoming activation request.
  • RPC Subsystem (RpcSs) and rpcss.dll:
    • The Remote Procedure Call (RPC) Subsystem service (RpcSs) is fundamental for all DCOM communication. It is hosted in svchost.exe and its core logic often resides in rpcss.dll.54
    • RpcSs manages RPC endpoints, listens for incoming remote procedure calls, and dispatches them to the appropriate server processes. It facilitates the communication between the client-side SCM and the server-side SCM, and subsequently between the client and the actual DCOM server process.
  • DCOM Server Process Launcher (DcomLaunch service):
    • This service, with the technical name DcomLaunch and display name "DCOM Server Process Launcher," is critical for activating out-of-process COM servers.54
    • It is hosted by svchost.exe -k DcomLaunch54, and like RpcSs, its functionality is closely tied to rpcss.dll.55
    • The server-side SCM delegates the task of launching COM server executables to the DcomLaunch service.38
    • When an activation request for an out-of-process server is received, DcomLaunch checks the server's AppID configuration in the registry for launch permissions and the path to the server executable (LocalServer32). If permissions allow and the server is not already running and registered appropriately, DcomLaunch starts the server process, typically under the identity specified in the AppID's RunAs value or the system default if not specified.38

Simplified Interaction Flow for Remote EXE Server Activation:

The remote activation process is a sophisticated sequence of interactions:

  1. Client application calls CoCreateInstanceEx(CLSID_RemoteFoo,..., pServerInfo_Target,..., IID_IFoo, &pIFoo).
  2. Client-side ole32.dll contacts the local SCM (services.exe).
  3. The local SCM makes an RPC call to the SCM (services.exe) on the remote server specified by pServerInfo_Target->pwszName.
  4. The remote SCM receives the activation request. It looks up HKCR\CLSID\{CLSID_RemoteFoo} to find its associated AppID.
  5. The remote SCM consults HKCR\AppID\{AppID_GUID} to verify launch permissions against the client's identity and to get the server's executable path from the LocalServer32 key under the CLSID.
  6. The remote SCM instructs the DcomLaunch service (via RpcSs) on the server machine to launch the COM server application.
  7. The DcomLaunch service performs another check of launch permissions. If permitted, it starts the server EXE (e.g., RemoteServer.exe -Embedding). The server process is typically launched under the security context defined by its RunAs registry setting or system defaults.
  8. The newly started remote server EXE creates its class factory for CLSID_RemoteFoo and registers it with the remote SCM/DcomLaunch by calling CoRegisterClassObject().
  9. A marshalled pointer to this remote class factory is then returned through the chain of SCMs back to the client-side ole32.dll.
  10. The client-side ole32.dll (or client code if CoGetClassObject was used directly) now has a proxy to the remote class factory. It calls IClassFactory::CreateInstance() on this proxy.
  11. This call is marshalled and sent to the remote server, where the stub for the class factory invokes the actual CreateInstance method. The COM object instance is created in the remote server's process.
  12. An interface pointer to the newly created remote object (specifically, a proxy to it) is marshalled back to the client.
  13. CoCreateInstanceEx returns this proxy interface pointer (pIFoo) to the client application.

This intricate orchestration underscores the complexity behind DCOM's seemingly transparent remote activation. A failure at any step—network connectivity, SCM communication, service availability on the server (DcomLaunch, RpcSs), registry misconfiguration, or insufficient DCOM security permissions—can lead to activation failure.

5.3. Network Communication: Ports and Protocols

DCOM relies on RPC for its network communication, which involves a specific port usage pattern:

  • The RPC Endpoint Mapper (EPM) on TCP Port 135:
    • When a DCOM client initiates a connection to a remote server, it first contacts the RPC Endpoint Mapper service on the server machine. The EPM listens on the well-known TCP port 135.8
    • The client queries the EPM to find out which dynamic port the specific DCOM server application (or service it needs) is listening on. The EPM maintains a database of registered RPC interfaces and the dynamic ports their server processes are using.
  • Dynamic RPC Ports:
    • DCOM server applications, upon starting, register their RPC endpoints with the local EPM. They are typically assigned a dynamic port from a high range (e.g., 49152-65535 in modern Windows versions; older systems might use 1024-5000).8
    • Once the client receives the dynamic port number from the EPM via port 135, it disconnects from port 135 and establishes a new, direct connection to the DCOM server on that specific dynamic port. All subsequent DCOM communication for that object interaction occurs over this dynamic port.

This two-step connection process (initial contact on port 135, then communication on a dynamic port) is a common source of DCOM connectivity problems, especially with firewalls. Firewalls between the client and server must be configured to allow inbound traffic on TCP port 135 and on the entire range of dynamic RPC ports that DCOM servers might use.56 If port 135 is blocked, the client cannot reach the EPM. If port 135 is open but the specific dynamic port used by the target DCOM server is blocked, the client will resolve the endpoint but then fail to connect to the server itself. Administrators often restrict the dynamic RPC port range on servers and configure firewalls accordingly to limit the attack surface while still enabling DCOM.

6. DCOM Security Model

DCOM incorporates a comprehensive security model to control access to remote objects. This model is built upon standard Windows security features and involves authentication, authorization, and impersonation. Misconfiguration of DCOM security is a very common source of DCOM errors.

6.1. Overview: Authentication, Authorization, Impersonation

The DCOM security model revolves around three core concepts:

  • Authentication: This is the process of verifying the identity of the client attempting to connect to the DCOM server and, conversely, the server to the client. DCOM leverages underlying Windows security providers for authentication. In a domain environment, Kerberos is typically used. In workgroup environments or for legacy systems, NTLMSSP (NT LAN Manager Security Support Provider) might be used.59 The choice of provider and the success of authentication depend on factors like network configuration, domain trust relationships, and correct credential handling.
  • Authorization: Once a client's identity is authenticated, authorization determines what actions that client is permitted to perform. For DCOM, this primarily involves:
    • Launch Permissions: Who is allowed to start the COM server process if it's not already running.
    • Access Permissions: Who is allowed to call methods on an already running COM object. These permissions are typically defined using Access Control Lists (ACLs) associated with the DCOM server application's AppID.37
  • Impersonation: This allows a DCOM server to perform operations or access resources on behalf of the client, using the client's security context.59 This is powerful but requires careful control. The level of impersonation granted to the server by the client determines the extent to which the server can act as the client.

6.2. Key Security Settings (Primarily configured via AppID in Registry or DCOMCNFG)

DCOM security settings are largely configured at the application level using its AppID. These settings are stored in the registry under HKCR\AppID\{AppID_GUID} and can be managed using the DCOMCNFG.exe utility.

  • LaunchPermission: This is an ACL stored in the registry that specifies which users or groups are allowed to launch the COM server application if it is not already running.37 When a remote activation request arrives, the SCM (or DcomLaunch service) on the server checks the client's identity against this ACL before starting the server process.
  • AccessPermission: This is an ACL that specifies which users or groups are allowed to make calls to the interfaces of an already running COM object.37 This check is typically performed by the COM runtime within the server process when a client attempts to connect or make a method call.
  • Authentication Level: This setting determines the degree of security applied to DCOM calls, primarily focusing on ensuring the authenticity of the caller and the integrity/privacy of the data. Common levels, as described in sources like 59, include:
DCOM Authentication Levels
Level Name Constant (RPC_C_AUTHN_LEVEL_*) Description of Protection
None NONE No authentication occurs. (Highly discouraged for security reasons).
Connect CONNECT Authenticates credentials only when the client establishes the connection to the server.
Call CALL Authenticates credentials at the beginning of every remote procedure call.
Packet PKT Authenticates credentials and verifies that all data packets are received (i.e., none are missing).
Packet Integrity PKT_INTEGRITY Authenticates credentials, verifies all data is received, and ensures that the data has not been modified in transit.
Packet Privacy PKT_PRIVACY Authenticates credentials, verifies data integrity, and encrypts the call arguments and results.

The DCOM hardening changes for CVE-2021-26414 mandate a minimum activation authentication level of RPC_C_AUTHN_LEVEL_PKT_INTEGRITY for DCOM servers.67

  • Impersonation Level: This setting, typically determined by the client, dictates what the server is allowed to do while acting under the client's security context.60
DCOM Impersonation Levels
Impersonation Level Constant (Security*) Server Capabilities in Client's Context
Anonymous SecurityAnonymous The server cannot impersonate or even identify the client.
Identify SecurityIdentification The server can obtain the client's identity (e.g., security token) and privileges but cannot impersonate the client to access resources. (Default for DCOM).
Impersonate SecurityImpersonation The server can impersonate the client's security context on the local system where the server is running. It can access local resources as the client.
Delegate SecurityDelegation The server can impersonate the client's security context on remote systems. This allows the server to access network resources on other machines as the client. Requires Kerberos delegation to be configured.

The interplay between these settings is crucial. For example, even if a client has AccessPermission, if the authentication level is too low for the server's requirements, the call might still fail.

6.3. Configuring DCOM Security

DCOM security can be configured programmatically (e.g., using CoInitializeSecurity by the server and CoSetProxyBlanket by the client) or administratively. The most common administrative tool is DCOMCNFG.exe.

  • DCOMCNFG.exe Utility: This utility provides a graphical interface to modify DCOM settings stored in the registry.60 It allows configuration of both machine-wide defaults and application-specific settings (tied to AppIDs).
DCOMCNFG.exe Configuration Areas
DCOMCNFG Tab/Section Configurable Settings Impact/Purpose
Default Properties Tab Enable Distributed COM on this computer, Default Authentication Level, Default Impersonation Level Sets machine-wide defaults for DCOM enablement and the baseline security levels for applications that don't specify their own.68
Default Security Tab Default Access Permissions, Default Launch and Activation Permissions, Default Configuration Permissions Sets machine-wide ACLs for access, launch, and configuration if an application's AppID doesn't define its own.68
Applications Tab (Select an application, click Properties) Allows configuration of settings specific to a registered AppID, overriding machine defaults for that application.64
↳ General Tab (App Properties) Application Name, Path Displays general information about the selected DCOM application.
↳ Location Tab (App Properties) Run application on this computer, Run application on the following computer (RemoteServerName) Specifies where the COM server should be activated (locally or on a specific remote machine).64
↳ Security Tab (App Properties) Custom Launch and Activation Permissions, Custom Access Permissions, Custom Configuration Permissions Defines specific ACLs for launch, access, and configuration for this AppID, overriding machine defaults.64
↳ Identity Tab (App Properties) Interactive user, Launching user, This user (specific account) Specifies the user account under which the DCOM server process will run.64 This is the RunAs setting.
↳ Endpoints Tab (App Properties) DCOM protocols and endpoints Configures specific network protocols and endpoints the server will use.68
Default Protocols Tab List of network protocols available to DCOM, order of priority Defines which network protocols DCOM will attempt to use and in what order.68
  • Registry Settings (under HKCR\AppID\{AppID_GUID}): DCOMCNFG.exe primarily manipulates registry values under the AppID key of a DCOM application.46 Key values include:
    • LaunchPermission and AccessPermission: Store the ACLs in a binary format.
    • AuthenticationLevel: Specifies the minimum authentication level required by the server.
    • RunAs: Stores the user account under which the server process should run. If set to "Interactive User", it runs as the currently logged-on user (problematic for services).
    • RemoteServerName: For client-side configuration, specifies the remote server to activate the object on.
    • DllSurrogate: Specifies a surrogate EXE process (like dllhost.exe) to host an in-process DLL server, allowing it to run as an out-of-process DCOM server.

The complexity of DCOM security, with its multiple layers and configuration points, makes it a frequent source of issues. A common problem is an E_ACCESSDENIED error, which could stem from incorrect LaunchPermission, AccessPermission, a mismatch in authentication levels, or the server's RunAs identity lacking necessary OS privileges. Understanding the hierarchy (AppID settings override machine defaults) is vital. If an application's AppID is configured, those settings apply; otherwise, the machine-wide defaults are used. Overly permissive machine defaults can pose security risks.

6.4. Recent DCOM Hardening (CVE-2021-26414)

Microsoft has implemented significant security hardening changes for DCOM related to CVE-2021-26414, which addressed a DCOM remote protocol security feature bypass vulnerability.67 These changes were rolled out in phases, with the final phase (starting March 14, 2023) making the hardening permanently enabled without an option to disable it via registry settings.67

The key impact of this hardening is the enforcement of a higher minimum authentication level for DCOM server activations:

  • DCOM servers now require incoming activation requests to use an authentication level of at least RPC_C_AUTHN_LEVEL_PKT_INTEGRITY.67 This level ensures that the client's identity is authenticated and that the communication has not been tampered with.
  • To aid compatibility, Microsoft introduced a client-side patch that automatically raises the authentication level of non-anonymous DCOM activation requests from Windows-based clients to at least RPC_C_AUTHN_LEVEL_PKT_INTEGRITY.67 This helps many existing clients meet the new server-side requirement without modification.
  • The registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole\AppCompat\RequireIntegrityActivationAuthenticationLevel was used during the transition phases to enable/disable the hardening. However, it now defaults to enabled and cannot be overridden to disable the hardening.67
  • New DCOM error events (Event IDs 10036, 10037, 10038) are logged in the System event log on the server if it detects a DCOM client attempting activation with an authentication level below RPC_C_AUTHN_LEVEL_PKT_INTEGRITY.67 These logs are crucial for identifying client applications that may need updates to work with hardened DCOM servers.

These changes underscore that DCOM security is an evolving landscape. Developers and administrators must ensure their DCOM applications (both client and server sides) are configured to meet these enhanced security requirements to avoid activation failures. Testing applications against these new security baselines is essential.

7. Troubleshooting COM and DCOM

Troubleshooting COM and DCOM issues can be challenging due to the many layers involved: component registration, process activation, inter-process communication, network connectivity, and security. A systematic approach, coupled with the right tools, is essential.

7.1. Understanding HRESULT Error Codes

COM functions and methods return HRESULT values to indicate success or failure. An HRESULT is a 32-bit integer with a specific structure:

  • Severity bit (S): The most significant bit. 0 indicates success, 1 indicates failure.
  • Facility code: Identifies the area or system component that generated the error (e.g., FACILITY_WIN32, FACILITY_ITF for interface-specific errors).
  • Error code: A 16-bit code specific to the facility.14

The following table lists common HRESULTs encountered in COM/DCOM development, their meanings, and initial troubleshooting pointers. This table can serve as a quick reference to decode errors and guide initial diagnostic efforts.

Common HRESULT Error Codes
HRESULT Value (Hex) Symbolic Name Brief Description Common Causes / Initial Troubleshooting Steps
0x00000000 S_OK Operation successful. N/A - Indicates success.
0x80004002 E_NOINTERFACE The requested interface is not supported by the object. Server doesn't implement the riid. Proxy/stub DLL for the interface might be missing or not registered (check HKCR\Interface\{IID}\ProxyStubClsid32). Client requested an interface the object simply doesn't expose.14
0x80070005 E_ACCESSDENIED General access denied. DCOM security: Incorrect LaunchPermission or AccessPermission on server's AppID. Authentication failure. RunAs identity lacks OS permissions. Firewall blocking. Recent DCOM hardening (CVE-2021-26414) issues.14
0x80040154 REGDB_E_CLASSNOTREG Class not registered. Component not installed/registered. CLSID key missing/corrupt in registry. InprocServer32 or LocalServer32 path incorrect. 32-bit/64-bit mismatch (e.g., 32-bit DLL in 64-bit process without proper configuration, check Wow6432Node).31
0x80080005 CO_E_SERVER_EXEC_FAILURE Server execution failed. Out-of-process (EXE) server failed to start or crashed during startup. Server did not call CoRegisterClassObject. RunAs identity permissions issue. Missing server dependencies. Resource exhaustion on server.70
0x800706BA RPC_S_SERVER_UNAVAILABLE The RPC server is unavailable. DCOM: Network connectivity issue (ping, DNS). Firewall blocking port 135 or dynamic RPC ports. RpcSs or DcomLaunch service not running on server. DCOM disabled on server. Name resolution failure.70
0x80004003 E_POINTER Invalid pointer argument passed to a method. Client passed a NULL or invalid pointer where a valid one was expected.14
0x80004005 E_FAIL Unspecified failure. Generic error; often requires deeper debugging or checking server-side event logs for more specific errors.14
0x8007000E E_OUTOFMEMORY Failed to allocate necessary memory. System or process is out of memory.14
0x80070057 E_INVALIDARG One or more arguments are not valid. Client passed an invalid argument to a COM method.14

7.2. Common Local COM Issues

Even without network distribution, local COM components can encounter several issues:

  • Registration Problems (REGDB_E_CLASSNOTREG - 0x80040154):
    • Verification: Ensure the CLSID key exists under HKCR\CLSID\. For in-process servers, check that InprocServer32 has a valid path to the DLL and a correct ThreadingModel value. For out-of-process servers, verify LocalServer32 points to the correct EXE.71
    • Registration Status: Confirm the component was registered using regsvr32.exe (for DLLs) or by the EXE server itself (e.g., via /RegServer) or by a Windows Installer package.12
    • 32-bit/64-bit Mismatches: A common pitfall on 64-bit Windows. If a 32-bit application tries to load a 64-bit COM DLL (or vice-versa) directly, it will fail. 32-bit COM components on a 64-bit system are registered under HKCR\Wow6432Node\CLSID\.12 A 64-bit process looking for a 32-bit in-process server will not find it in the standard registry view unless it specifically looks in the Wow6432Node or if the client is also 32-bit. For IIS, application pools might need to be configured to "Enable 32-Bit Applications" if they host 32-bit COM components.71
  • Interface Not Found (E_NOINTERFACE - 0x80004002):
    • Implementation: The server object genuinely does not implement the interface requested by the client in QueryInterface or CoCreateInstance.
    • Proxy/Stub Issues: For custom interfaces used across COM apartments (even in-process) or processes, a proxy/stub DLL is needed for marshalling. If this DLL is not registered (i.e., HKCR\Interface\{IID_Requested}\ProxyStubClsid32 is missing or points to an invalid CLSID) or the DLL file itself is missing, E_NOINTERFACE can result because COM cannot create the necessary proxy to marshal the interface pointer.
  • Server Execution Failures (CO_E_SERVER_EXEC_FAILURE - 0x80080005):
    • Server Crash: The out-of-process (EXE) server might be crashing immediately upon launch. Check the Application Event Log on the machine where the server is supposed to run for any error reports related to the server executable.75
    • Permissions: The identity under which the EXE server is configured to run (via its AppID's RunAs setting or system defaults) may lack the necessary operating system permissions (e.g., "Log on as a batch job" or "Log on as a service" if applicable, or rights to access its own files/registry keys).75
    • Missing Dependencies: The server EXE or one of its dependent DLLs might be missing or inaccessible.
    • Resource Issues: The system might be too low on resources (memory, handles) for the server to start.75
    • Failure to Register Class Factory: The server EXE launched but failed to call CoRegisterClassObject successfully within the timeout period expected by COM.
  • Permission Denied (E_ACCESSDENIED - 0x80070005):
    • Even for local out-of-process components, if they run under a different user identity than the client, DCOM security settings (LaunchPermission, AccessPermission for the server's AppID) can come into play. Ensure the client's identity has the necessary rights.

7.3. Common DCOM Issues

When COM objects are distributed across a network, a new set of potential problems arises:

  • RPC Server Unavailable (RPC_S_SERVER_UNAVAILABLE - 0x800706BA): This is a very common DCOM error indicating the client could not establish communication with the RPC service on the server machine.
    • Network Connectivity: Perform basic network checks. Can the client ping the server by name and IP address? Are there network outages or routing issues?.77
    • Firewalls: This is a primary suspect. Firewalls on the client, server, or intermediate network devices might be blocking:
      • TCP port 135 (used by the client to contact the server's RPC Endpoint Mapper).56
      • The dynamic RPC port range used by the DCOM server for actual communication (e.g., 49152-65535 on modern Windows).56
    • Name Resolution: The client must be able to resolve the server's hostname (specified in COSERVERINFO or RemoteServerName registry key) to an IP address. DNS or NetBIOS name resolution failures will prevent the client from even attempting to connect.77 Use tools like nslookup or ping -a to test.
    • Server-Side Services: Ensure the following services are running on the DCOM server machine:
      • Remote Procedure Call (RPC) (service name RpcSs).76
      • DCOM Server Process Launcher (service name DcomLaunch).76
    • DCOM Disabled: DCOM might be disabled on the server. Check the registry value HKLM\Software\Microsoft\Ole\EnableDCOM. It should be set to 'Y'.78
  • Security Configuration Problems (E_ACCESSDENIED, Launch/Activation failures): These errors often point to misconfigured DCOM security settings on the server.
    • LaunchPermission: The client's authenticated identity (or ANONYMOUS LOGON if authentication level is None or authentication fails) is not granted "Remote Launch" and "Remote Activation" rights in the DCOM server's AppID security settings (configured via DCOMCNFG.exe or registry).60
    • AccessPermission: The client's identity is not granted "Remote Access" rights in the server's AppID settings, preventing method calls on an already running object.60
    • Authentication Failures:
      • The client and server cannot agree on an authentication protocol (Kerberos, NTLM).
      • The client attempts to authenticate at a level lower than what the server requires (e.g., server hardened for CVE-2021-26414 requires RPC_C_AUTHN_LEVEL_PKT_INTEGRITY).59
      • Kerberos specific issues: Missing or incorrect Service Principal Names (SPNs) for the server, client or server clock skew preventing Kerberos ticket validation.
    • RunAs Identity Issues: The user account specified in the DCOM server's AppID RunAs setting (or the default identity if not specified) might lack necessary privileges on the server machine (e.g., "Log on as a service", "Act as part of the operating system", or permissions to access required files/registry keys).
    • Registry Permissions: Incorrect ownership or permissions on critical DCOM registry keys like HKLM\SOFTWARE\Microsoft\Ole can prevent the system from reading or applying DCOM security settings.85

A systematic approach is vital for DCOM troubleshooting. The initial HRESULT often guides the investigation. For example, RPC_S_SERVER_UNAVAILABLE points towards network or server-side service issues, while E_ACCESSDENIED in a DCOM context usually indicates DCOM security misconfigurations on the server. It's crucial to distinguish whether the problem lies with the client, the server, or the intervening network, using tools on both ends to gather comprehensive diagnostic data.

7.4. Essential Troubleshooting Tools and Techniques

A developer's toolkit for COM/DCOM troubleshooting should include several utilities:

  • Event Viewer (eventvwr.msc):
    • Always the first place to check on both client and server.
    • System Log: Look for DCOM errors (Source: DistributedCOM, often with Event IDs like 10000, 10005, 10006, 10009, 10010, 10016). Recent DCOM hardening changes log specific events like 10036-10038 for authentication level issues.67 Also check for RPC errors.
    • Application Log: Look for crashes or errors reported by the COM server application itself or related client applications.86
    • Security Log: Audit failures (e.g., logon failures for the RunAs identity, NTLM/Kerberos authentication failures) can provide clues for E_ACCESSDENIED errors.66
  • DCOMCNFG.exe:
    • Use this utility on the server (and sometimes client for RemoteServerName checks) to inspect and modify:
      • Machine-wide default security settings (Default Properties & Default Security tabs).
      • Application-specific (AppID) settings: LaunchPermission and AccessPermission, Authentication Level, Identity (RunAs user), and Location (Endpoints).60
    • Verify that the correct users/groups (e.g., Everyone, Authenticated Users, specific service accounts, ANONYMOUS LOGON if applicable) have the necessary permissions (Local/Remote Launch, Local/Remote Activation, Local/Remote Access). Ensure SYSTEM has permissions.65
  • Process Monitor (ProcMon.exe from Sysinternals):
    • Invaluable for diagnosing registration issues, file/registry access problems, and permission denials at the OS level.66
    • Filters:
      • Filter by process name (client EXE, server EXE, dllhost.exe for surrogates, svchost.exe for DcomLaunch/RpcSs).
      • Filter for registry operations (RegOpenKey, RegQueryValue) on paths like HKCR\CLSID, HKCR\AppID, HKCR\Interface, HKLM\Software\Microsoft\Ole. Look for NAME NOT FOUND (missing key/value) or ACCESS DENIED results.
      • Filter for file system operations (CreateFile) on server DLL/EXE paths. Look for PATH NOT FOUND or ACCESS DENIED.
    • Enable "Show Resolved File Paths" and "Enable Boot Logging" (for issues during startup).88
  • Process Explorer (ProcExp.exe from Sysinternals):
    • Identify which process is hosting an out-of-process COM server (e.g., find MyServer.exe or the dllhost.exe instance running your DllSurrogate-hosted component).90
    • View loaded DLLs (Ctrl+D or View -> Lower Pane View -> DLLs) for a process to confirm that the correct version of a COM server DLL or its proxy/stub DLL is loaded.90
    • Inspect process handles (Ctrl+H or View -> Lower Pane View -> Handles) for network connections (RPC ports), event objects, or other synchronization primitives used by COM.
    • Examine thread stacks (double-click process, Threads tab, select thread, click Stack) to see where threads are spending time, potentially identifying hangs or high CPU usage within COM calls.90 Requires symbols to be configured.
  • Network Monitor (NetMon.exe - deprecated, or Wireshark):
    • Essential for DCOM network issues. Capture traffic on both client and server.8
    • Filters:
      • tcp.port == 135 (for EPM traffic).
      • ip.addr == <server_ip> and ip.addr == <client_ip> (to isolate conversation).
      • Wireshark display filters: dcerpc (for general RPC), dcom (for DCOM-specific ORPC messages like IOXIDResolver or IRemoteActivation).93
    • Look for: Successful TCP handshake to port 135, EPM response with dynamic port, successful TCP handshake to dynamic port, RPC bind requests/responses, DCOM method calls, and any network-level errors or resets.
  • Registry Editor (regedit.exe):
    • Manually inspect COM registry keys identified as problematic by other tools or error messages. Check for existence, correct paths, ThreadingModel, AppID values, LaunchPermission/AccessPermission (though binary ACLs are hard to read directly, their presence/absence can be noted).
  • Services Console (services.msc):
    • Verify that DCOM Server Process Launcher, Remote Procedure Call (RPC), and RPC Endpoint Mapper services are running and set to their correct startup type (usually Automatic) on both client (for some aspects) and especially server machines.76
  • wbemtest.exe (WMI Tester):
    • While for WMI, it's useful for testing basic DCOM remote connectivity and security to a server, as WMI relies heavily on DCOM. Attempt to connect to a remote server's WMI namespace (e.g., \\servername\root\cimv2).58 Failures here often indicate underlying DCOM/RPC issues.

Differences in operating system versions, patch levels, installed software, security policies (Group Policy), and 32-bit versus 64-bit architectures between development, testing, and production environments are frequent causes of the "it works on my machine" syndrome with COM/DCOM. These environmental differences can lead to subtle variations in registry settings or DCOM security configurations, causing unexpected failures in some environments but not others. This underscores the importance of testing in environments that closely mirror production.

Effective troubleshooting often requires a combination of these tools. For example, an E_ACCESSDENIED in the Event Log might lead to checking DCOMCNFG. If permissions appear correct there, Process Monitor might reveal that the server's RunAs identity is being denied access to a critical file or registry key at the OS level, a detail not visible in DCOMCNFG alone.

8. Conclusion and Best Practices

COM and DCOM, despite their age, remain integral to many Windows applications and system services. Their architecture, while powerful, introduces complexities, particularly in distributed scenarios and security configurations. For developers, a thorough grasp of their core principles, activation workflows, and common pitfalls is essential for building robust applications and effectively troubleshooting issues.

8.1. Recap of Key Concepts

The Component Object Model (COM) provides a binary standard for software interoperability, enabling language independence and code reuse through well-defined interfaces. IUnknown forms the bedrock, offering lifetime management via reference counting (AddRef/Release) and interface discovery (QueryInterface). Interfaces, identified by unique IIDs, are immutable contracts implemented by COM objects (instances of CLSID-identified classes). Type libraries and IDL describe these contracts, facilitating cross-language use and marshalling. Threading apartments (STA, MTA, NTA) manage concurrency for components.

Distributed COM (DCOM) extends this model across networks using Object RPC (ORPC). Location transparency is a key DCOM goal, achieved through marshalling via proxies and stubs, which package and unpackage method calls and parameters. Activation of remote objects involves client-side functions like CoCreateInstanceEx, server-side services like the SCM and DCOM Server Process Launcher, and network communication protocols relying on the RPC Endpoint Mapper (port 135) and dynamic RPC ports.

The Windows Registry is central to both COM and DCOM, storing configuration data for CLSIDs, ProgIDs, AppIDs, Interfaces, and Type Libraries. DCOM security is multifaceted, involving authentication, authorization (LaunchPermission, AccessPermission), and impersonation, primarily configured via AppIDs and the DCOMCNFG utility. Recent DCOM hardening has further emphasized secure configurations, notably requiring higher authentication levels.

8.2. Recommendations for Developers Working with COM/DCOM

To navigate the complexities of COM and DCOM successfully, developers should adhere to the following best practices:

  1. Master IUnknown: Deeply understand reference counting rules (AddRef, Release) to prevent memory leaks or premature object destruction. Always balance calls.
  2. Design Clear Interfaces: Define interfaces that are granular, cohesive, and semantically clear. Remember that interfaces are immutable; new versions require new IIDs. Use IDL and generate type libraries to provide rich metadata.
  3. Choose Threading Models Wisely: Select the appropriate threading model (Apartment, Free, Both, Neutral) for in-process components based on their thread-safety characteristics and intended use. Be aware of cross-apartment marshalling implications.
  4. Implement Robust Registration: Ensure components correctly implement DllRegisterServer/DllUnregisterServer (for DLLs) or handle /RegServer//UnregServer (for EXEs). For deployed applications, rely on Windows Installer (MSI) for proper registration and unregistration.
  5. Secure DCOM Applications:
    • Carefully configure AppID security settings on the server:
      • Define explicit LaunchPermission and AccessPermission ACLs. Avoid overly permissive settings like "Everyone" in production unless absolutely necessary and understood.
      • Choose an appropriate RunAs identity for the server process, granting it only the necessary privileges (Principle of Least Privilege).
      • Set an appropriate AuthenticationLevel (e.g., RPC_C_AUTHN_LEVEL_PKT_INTEGRITY as a minimum post-hardening).
    • Understand client-side impersonation levels and their implications.
  6. Address Firewall Configuration: When deploying DCOM applications, ensure that firewalls (both host-based and network) are configured to allow traffic on TCP port 135 (RPC EPM) and the necessary dynamic RPC port range used by DCOM servers. Consider restricting the dynamic port range on servers for better security.
  7. Use Unique GUIDs: Always generate new, unique GUIDs for all CLSIDs, IIDs, AppIDs, and LIBIDs for your components to prevent conflicts.
  8. Test Thoroughly: Test DCOM applications under realistic network conditions, security configurations (including different user accounts and authentication levels), and across different Windows versions and patch levels.
  9. Stay Informed on Security: Keep abreast of security advisories and hardening changes from Microsoft (like CVE-2021-26414) that may affect DCOM behavior and require configuration updates.
  10. Leverage Troubleshooting Tools Systematically: Become proficient with tools like Event Viewer, DCOMCNFG, Process Monitor, Process Explorer, and network analyzers (Wireshark). Adopt a methodical approach to diagnosing issues, starting from HRESULT codes and progressively examining registration, local activation, network connectivity, and remote security layers.

By adhering to these practices and developing a solid understanding of the underlying architecture, developers can harness the power of COM and DCOM while minimizing the challenges associated with their deployment and maintenance.

Works Cited

  1. COM Technical Overview - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/com-technical-overview
  2. Interface Pointers and Interfaces - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/interface-pointers-and-interfaces
  3. saravanesh.files.wordpress.com, accessed May 18, 2025, https://saravanesh.files.wordpress.com/2007/09/understanding-com.pdf
  4. COM, DCOM, and Type Libraries - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/midl/com-dcom-and-type-libraries
  5. www.softwaretoolbox.com, accessed May 18, 2025, https://www.softwaretoolbox.com/dcom/dcom-technical-overview.pdf
  6. Blog Windows is and always will be a Potatoland - r-tec IT Security GmbH, accessed May 18, 2025, https://www.r-tec.net/r-tec-blog-windows-is-and-always-will-be-a-potatoland.html
  7. [MS-DCOM]: Overview | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dcom/86b9cf84-df2e-4f0b-ac22-1b957627e1ca
  8. Restrict Active Directory RPC traffic to a specific port - Windows Server | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/restrict-ad-rpc-traffic-to-specific-port
  9. Remote Service Control Manager Handle - Threat Hunter Playbook, accessed May 18, 2025, https://threathunterplaybook.com/hunts/windows/190826-RemoteSCMHandle/notebook.html
  10. COM IDs & Registry keys in a nutshell - CodeProject, accessed May 18, 2025, https://www.codeproject.com/Articles/1265/COM-IDs-Registry-keys-in-a-nutshell
  11. COM Registry Keys - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/com-registry-keys
  12. windows - What does regsvr32 do? - Server Fault, accessed May 18, 2025, https://serverfault.com/questions/835433/what-does-regsvr32-do
  13. VersionIndependentProgID - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/versionindependentprogid
  14. HRESULT Error Codes | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/shows/inside/hresult
  15. CoInitializeEx function (combaseapi.h) - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializeex
  16. COM+ Threading Models - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/cossdk/com--threading-models
  17. Neutral Apartments - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/cossdk/neutral-apartments
  18. The Neutral Threaded Apartment - COM & .NET Component ..., accessed May 18, 2025, https://www.oreilly.com/library/view/com-net/0596001037/ch05s08.html
  19. IUnknown | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/cpp/atl/iunknown?view=msvc-170
  20. IUnknown::AddRef - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-addref
  21. ICustomQueryInterface Interface (System.Runtime.InteropServices) | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.icustomqueryinterface?view=net-9.0
  22. Encapsulation in object-oriented programming - Unity Learn, accessed May 18, 2025, https://learn.unity.com/pathway/junior-programmer/unit/apply-object-oriented-principles/tutorial/encapsulation-in-object-oriented-programming-2
  23. MARSHAL - Standard Marshaling of Custom Interfaces - Lesson 12, accessed May 18, 2025, https://techshelps.github.io/MSDN/COM/comsamp/marshal.htm
  24. MIDL not generating tlb - Stack Overflow, accessed May 18, 2025, https://stackoverflow.com/questions/77984480/midl-not-generating-tlb
  25. The COM Library - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/the-com-library
  26. STAThreadAttribute Class (System) - Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/hr-hr/dotnet/api/system.stathreadattribute?view=net-9.0&viewFallbackFrom=net-9.0-pp
  27. Class Table - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/msi/class-table
  28. Registering and Unregistering a Snap-in - Learn Microsoft, accessed May 18, 2025, https://learn.microsoft.com/en-us/previous-versions/windows/desktop/mmc/registering-and-unregistering-a-snap-in
  29. InprocServer32 - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/inprocserver32
  30. comtypes/comtypes/__init__.py at main · enthought/comtypes - GitHub, accessed May 18, 2025, https://github.com/enthought/comtypes/blob/master/comtypes/__init__.py
  31. CoCreateInstance function (combaseapi.h) - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cocreateinstance
  32. CLSCTX (wtypesbase.h) - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/api/wtypesbase/ne-wtypesbase-clsctx
  33. CoGetClassObject function (combaseapi.h) - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cogetclassobject
  34. IClassFactory - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iclassfactory
  35. IClassFactory::CreateInstance - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iclassfactory-createinstance
  36. IClassFactory::LockServer - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iclassfactory-lockserver
  37. Creating Registration-Free COM Objects - Win32 apps - Learn Microsoft, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/sbscs/creating-registration-free-com-objects
  38. DCOM timeout error (TSTheme) - WinDoh - WordPress.com, accessed May 18, 2025, https://windoh.wordpress.com/2012/05/30/dcom-timeout-error-tstheme/
  39. HKEY_CLASSES_ROOT Key - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/sysinfo/hkey-classes-root-key
  40. CLSID Key - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/clsid-key-hklm
  41. LocalServer32 - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/localserver32
  42. Interface Key - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/interface-key
  43. Registry information - CloudBees Documentation, accessed May 18, 2025, https://docs.cloudbees.com/docs/cloudbees-build-acceleration/latest/configuration-guide/registry-info
  44. Win32_DCOMApplicationSetting - powershell.one, accessed May 18, 2025, https://powershell.one/wmi/root/cimv2/win32_dcomapplicationsetting
  45. Manipulating of registry classes with Advanced Installer, accessed May 18, 2025, https://www.advancedinstaller.com/application-packaging-training/msi-advanced/ebook/registry-classes-with-advanced-installer.html
  46. AppID Key - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/appid-key
  47. windows 7 - What actually happens during /regserver & /unregserver ..., accessed May 18, 2025, https://superuser.com/questions/1164298/what-actually-happens-during-regserver-unregserver
  48. AppId Table - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/msi/appid-table
  49. MSI Package Definition and Resources - MSI Packaging ebook, accessed May 18, 2025, https://www.advancedinstaller.com/application-packaging-training/msi/ebook/definition-structure.html
  50. Windows Installer Components - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/msi/windows-installer-components
  51. CoCreateInstanceEx function (combaseapi.h) - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cocreateinstanceex
  52. accessed January 1, 1970, https://learn.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-cocreateinstanceex
  53. COSERVERINFO (objidlbase.h) - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/api/objidlbase/ns-objidlbase-coserverinfo
  54. DCOM Server Process Launcher - rpcss.dll - Program Information - Bleeping Computer, accessed May 18, 2025, https://www.bleepingcomputer.com/startups/25732/rpcss.dll/
  55. DCOM Server Process Launcher - Windows 11 Service - batcmd.com, accessed May 18, 2025, https://batcmd.com/windows/11/services/dcomlaunch/
  56. RPC error troubleshooting guidance - Windows Client - Learn Microsoft, accessed May 18, 2025, https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/rpc-errors-troubleshooting
  57. Configure firewall settings for DPM | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/system-center/dpm/configure-firewall-settings-for-dpm?view=sc-dpm-2025
  58. Port Scanning Issue - Active, couldn't classify: No WMI connection - ServiceNow, accessed May 18, 2025, https://www.servicenow.com/community/itom-forum/port-scanning-issue-active-couldn-t-classify-no-wmi-connection/m-p/3198404
  59. Authentication - AVEVA™ Documentation, accessed May 18, 2025, https://docs.aveva.com/bundle/dcom-security-and-configuration/page/1011066.html
  60. Setting System-Wide Security Using DCOMCNFG - Win32 apps ..., accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/setting-machine-wide-security-using-dcomcnfg
  61. LaunchPermission - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/launchpermission
  62. AccessPermission - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/accesspermission
  63. Impersonation Levels (Authorization) - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/secauthz/impersonation-levels
  64. Setting Process-Wide Security Using DCOMCNFG - Win32 apps | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/com/setting-processwide-security-using-dcomcnfg
  65. WMI: Windows Management Instrumentation - FAQ 1847 - GraphPad, accessed May 18, 2025, https://www.graphpad.com/support/faq/wmi-windows-management-instrumentation/
  66. Scenario guide: Troubleshoot WMI connectivity and access issues - Windows Server, accessed May 18, 2025, https://learn.microsoft.com/en-us/troubleshoot/windows-server/system-management-components/scenario-guide-troubleshoot-wmi-connectivity-access-issues
  67. KB5004442—Manage changes for Windows DCOM Server Security ..., accessed May 18, 2025, https://support.microsoft.com/en-us/topic/kb5004442-manage-changes-for-windows-dcom-server-security-feature-bypass-cve-2021-26414-f1400b52-c141-43d2-941e-37ed901c769c
  68. DCOMCNFG | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/cpp/atl/dcomcnfg?view=msvc-170
  69. Windows Cluster, Change to DCOM "Launch and Activation" configuration last after boot, accessed May 18, 2025, https://learn.microsoft.com/en-us/answers/a/1957588
  70. OPC Common Questions - COM ErrorCodes | PDF | Component ..., accessed May 18, 2025, https://www.scribd.com/document/102712101/OPC-Common-Questions-COM-ErrorCodes
  71. How to solve COM Exception Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))? - Stack Overflow, accessed May 18, 2025, https://stackoverflow.com/questions/1496214/how-to-solve-com-exception-class-not-registered-exception-from-hresult-0x80040
  72. Error System.Runtime.InteropServices.COMException (0x80040154) when reinstalling apps from Microsoft Store after Windows update, accessed May 18, 2025, https://answers.microsoft.com/en-us/windows/forum/all/error-systemruntimeinteropservicescomexception/77dba496-d20b-4965-b944-097974962b36
  73. What are the prerequisites for using Azure.Communication.Calling.WindowsClient, accessed May 18, 2025, https://learn.microsoft.com/en-us/answers/questions/2169528/what-are-the-prerequisites-for-using-azure-communi
  74. accessed January 1, 1970, https://stackoverflow.com/questions/1496214/how-to-solve-com-exception-class-not-registered-exception-from-hresult-0x80040154-regdb_e_classnotreg
  75. c# - Server execution failed (Exception from HRESULT: 0x80080005 ..., accessed May 18, 2025, https://stackoverflow.com/questions/22062284/server-execution-failed-exception-from-hresult-0x80080005-co-e-server-exec-fa
  76. How to fix an “RPC server is unavailable” error | Proton VPN, accessed May 18, 2025, https://protonvpn.com/support/rpc-server-unavailable
  77. Error the RPC server is unavailable - Windows - Learn Microsoft, accessed May 18, 2025, https://learn.microsoft.com/en-us/troubleshoot/windows-server/user-profiles-and-logon/not-log-on-error-rpc-server-unavailable
  78. Error 0x800706ba during certificate enrollment - Windows Server - Learn Microsoft, accessed May 18, 2025, https://learn.microsoft.com/en-us/troubleshoot/windows-server/certificates-and-public-key-infrastructure-pki/error-0x800706ba-certificate-enrollment
  79. The RPC server is unavailable. 0x800706ba (WIN32: 1722 RPC_S_SERVER_UNAVAILABLE) - Microsoft Q&A, accessed May 18, 2025, https://learn.microsoft.com/en-us/answers/questions/743186/the-rpc-server-is-unavailable-0x800706ba-(win32-17
  80. accessed January 1, 1970, https://learn.microsoft.com/en-us/windows/win32/rpc/troubleshooting-rpc-errors
  81. Common HRESULT Values - Win32 apps - Learn Microsoft, accessed May 18, 2025, https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
  82. Windows Server Troubleshooting: "The RPC server is unavailable" - Threat Intel Taste, accessed May 18, 2025, https://mcselles.wordpress.com/2016/03/02/windows-server-troubleshooting-the-rpc-server-is-unavailable/
  83. Troubleshoot domain controller deployment - Windows Server | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/troubleshoot-domain-controller-deployment
  84. Trouble on server 2022 with DNS and Netbios - Microsoft Q&A, accessed May 18, 2025, https://learn.microsoft.com/en-us/answers/questions/2187748/trouble-on-server-2022-with-dns-and-netbios
  85. How to fix the error Unable to Configure DCOM Permissions ..., accessed May 18, 2025, https://learn.microsoft.com/en-us/answers/questions/1189516/how-to-fix-the-error-unable-to-configure-dcom-perm
  86. Troubleshoot Start menu errors - Windows Client | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/troubleshoot/windows-client/shell-experience/troubleshoot-start-menu-errors
  87. Troubleshoot agent connectivity issues - Operations Manager | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/troubleshoot/system-center/scom/troubleshoot-agent-connectivity-issues
  88. How to find what/who changes the registry value - Learn Microsoft, accessed May 18, 2025, https://learn.microsoft.com/en-us/answers/questions/1168387/how-to-find-what-who-changes-the-registry-value
  89. Process Monitor - Sysinternals | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/sysinternals/downloads/procmon
  90. Troubleshoot issues using Process Explorer - Windows Server | Microsoft Learn, accessed May 18, 2025, https://learn.microsoft.com/en-us/troubleshoot/windows-server/support-tools/troubleshoot-issues-process-explorer
  91. Using Process Explorer to list dlls running under Outlook.exe - Learn Microsoft, accessed May 18, 2025, https://learn.microsoft.com/en-us/outlook/troubleshoot/performance/using-process-explorer-to-list-dlls-running-under-outlook-exe
  92. accessed January 1, 1970, https://learn.microsoft.com/en-us/sysinternals/downloads/procexp
  93. DCOM - Wireshark Wiki, accessed May 18, 2025, https://wiki.wireshark.org/DCOM
  94. Display Filter Reference: DCOM - Wireshark, accessed May 18, 2025, https://www.wireshark.org/docs/dfref/d/dcom.html