Overview
Shortcuts for the main chapters in this article:
- The COM Macro-Architecture Topology
- Some Theory
- Some Practice
- Conclusion
- Bibliography
Purpose
First, I have to define what does "COM Macro-Architecture" mean.
By "Macro"
I do not mean "pre-processor"
or
"script command"
. No, by "Macro"
I am referring to a
high level of observation, also used in financial terminology: "Macro economy"
and "Micro economy" refer to the global economy and the country economy
respectively, where the country being the delimiter.
Because "COM
Architecture" is so huge, I had to split it into two pieces. I defined the
unit of deployment
(from a technical point of view we call it an
Executable file or DLL file) as the delimiter of the split. Therefore we have
the two following groups:
Macro-Architecture
: as a unit of deployment, we will talk
about Client applications and COM Servers.
Micro-Architecture
: inside a unit of deployment we will talk
about running process, COM apartment, thread concurrency and synchronisation,
memory sharing.
I also used the Term
"Topology"
. By
definition, in computer science, Topology is likely to be
the arrangement in
which the nodes of a LAN are connected to each other. Here I wanted to point
out how COM applications (Client & Server) are connected to each other.
This series of articles is just about "Macro-Architecture".
You
will learn how to make COM Server and Client Application. You will see how to
deploy and install them (on local machine and remote machine).
This
series of articles want to be
more practical than theoretical. However,
you can find many good books and articles that go deeper into details in the
bibliography
section.
The series is called "COM Macro-Architecture Topology" and
this is the
main article. It will give you:
- an overview of the relationships between Client applications and COM
Servers.
- all the instructions you need to build your system (Client application and
COM Server).
- all the process you need to install, configure and uninstall your system.
Here are the links to other articles:
Who should read this article ?
I have made the assumption that the
reader:
- should know the C++ language as all code samples are written in C++.
- should have a basic knowledge of COM, such as Client/Server model, COM
Interface, Interface marshalling (Proxy/Stub).
- should have a basic knowledge of Windows NT/2000 security aspect.
- ought to be interested more in COM architecture than in development
aspect.
For this reason, I classified this article as an
Intermediate level.
However, beginners can still read this series
and used the practical section like a tutorial. From my own experience, I have
started to learn COM by practice and then books helped me to put it down and
understand the theory.
I do remind to COM developers who are reading
this series that the main subject is
COM architecture. I am not going to
explain or compare the different COM helper tools, C++ libraries (e.g. ATL) or
even C++ design aspects (e.g. smart pointers or wrapper classes) available to
develop COM Client applications or Servers.
Requirements
All the code in these samples have been written in C++,
using Visual C++ 6.0 (sp4) under Windows 2000.
They also use the Active-X
Template Library (ATL).
Downloading
Demo files - You will find the necessary tools (Executables,
DLLs, Registry configuration and Batch files) to try the different cases. Download
demo project - 127 KB
Source files - You will find all the source code for making
the 3 different COM Servers (Executable, 2DLLs and 1DLL) and the Client
Application. Download
source - 70 KB The project's structure on my computer is like
that:
All the Executable and DLL files are output in the
\Implementation\Bin
directory.
Deployment considerations
Be careful when deploying the components
described in this article.
Take into account these points:
- In order to install them you need to have the Administrator rights (Client
and Server machine).
- Allow the Server to use the identity of the
Interactive user
or a user's account with the Interactive rights (so dialog boxes could be
showed).
- When calling the Server remotely, be sure that the User associated to your
Server is locally logged-on onto the server machine as the Interactive user,
so that the Dialog boxes can appear.
- Using the "Terminal Services Client" does not give you the Interactive
user account, although your account has the Interactive rights (For further
information read [Bi6]).
The
Interactive User is the user currently logged-on the Server machine.
Limitations
Although COM is available in many operating systems, I have
just considered the Windows implementation. This means that some aspects of COM
could have different restrictions based on their operating system implementation
(e.g. the Security, the COM information storage, etc.) .
COM & Infrastructure
Before moving on to practice and building COM
Servers you have to understand how the information you will provide to COM will
be used to bind a Client Application to a COM Server.
Here, I will just talk
about 2 COM Infrastructure points:
Look at the article "
COM
IDs & Registry keys in a nutshell" for information on the registry and
COM vocabulary.
The activation
mechanism is the process used by COM to locate, load and launch a COM Server
(DLL or Executable). The result, if all goes to plan, will be
to instantiate
a COM object or COM class object. As you can understand,
Activation is a
dynamic action and it occurs at runtime.
COM proposed 3 activation
models to bring COM objects into memory (see
[Bi1],
chapter 5 and
[Bi11],
chapter 3):
- Clients can ask COM to bind to the class object or class factory of a
given class (using
CoGetClassObject()
).
- Clients can ask COM to create new instances of a class based on a
CLSID
(using
CoCreateInstance/Ex()
).
- Clients can ask COM to bring a persistent object to life based on the
persistent state of the object (using
CoGetInstanceFromFile()
).
You can also define a custom way to activate your COM object based on
one of these 3 basic activation models.
All these activation models use
the services of the COM Service Control Manager (SCM). The COM SCM is not the
same as the Windows NT or Windows 2000 SCM (used to start logon-independent
processes known as Windows Services). Every host that supports COM has a COM
SCM. His role is to activate the COM objects on a particular machine (locally or
remotely).
Static/Dynamic aspect of a COM server
At this stage you should look at
your COM Server from its
Static and
Dynamic aspect:
- The static aspect of a COM Server is its package: it can be built
as an Executable or as a Dynamic Link Library
(DLL) file.
- The dynamic aspect of a COM Server relates to the Server categories
defined by COM at runtime: In-process and
Out-of-process.
The figure below expresses that
idea:
From a
location point of view, COM Servers that
reside on the client machine are called
"local servers" and the ones that
reside on a remote machine are called
"remote servers".
This figure
points out 3 results:
- A COM Server packaged as an Executable file will
never run as In-process server. It will always run as an Out-of-process
server (locally or remotely).
- A COM Server packaged as a DLL file will run either
as an In-process or as an Out-of-process server (locally or
remotely).
Notice that a DLL COM Server always needs a process to run into.
As In-process server it will be loaded into the Client process
space and as Out-of-process it should be loaded into a Surrogate
process space.
- Only COM Servers use as Out-of-process servers can be called on
remote machine.
Every route leads to a COM Server...
When deploying and installing your
COM Server you must give some information to COM, such as where your component
will be (physically), which COM class object(s) your component provides and so
on.
All these information will allow COM library to answer to Client's
requests about launching and creating COM Server's objects.
Under Windows NT
4.0, COM stores these information on its local configuration database also
called the
Registry. Under Windows 2000 (or v5.0), COM uses a distributed
secured database, i.e. the
Active Directory.
Generally, all COM
servers should support self-registration. This means that:
- the Executable COM Server must check the command line for
these switches:
/RegServer
or -RegServer
: will insert keys in
the registry and register its class factories by calling
CoRegisterClassObject()
.
/UnregServer
or -UnregServer
: will suppress
keys in the registry and unregister its class factories by calling
CoRevokeClassObject()
.
All these 4 switches are
case insensitive.
- the DLL COM Server must export these 2 functions:
DllRegisterServer()
: will insert keys in the registry.
DllUnregisterServer()
: will suppress keys in the registry.
To register a DLL COM Server, you can use the utility
REGSVR32.EXE in the Win32 SDK. This application will call these 2
exported functions to register or unregister the DLL COM server.
To
illustrate the work done by COM in order to bind the Client application and the
COM Server together, let assume the client code is like this:
ISampleClass *psc = NULL;
HRESULT hr = CoGetClassObject(GUID1, CLSTX_ALL,
0, IID_IClassFactory, (void**)&psc);
CoGetClassObject()
provides us an IClassFactory
interface pointer on a class object (i.e. a class factory) associated with the
specified class ID: GUID1.
CoGetClassObject()
takes as its second parameter a bitmask
value that specifies the desired context the client wants to activate the COM
Server: In-process, Out-of-process, locally or remotely.
CLSTX_ALL
is a pre-processor macro defined like this:
#define CLSCTX_ALL (CLSCTX_INPROC_SERVER| \
CLSCTX_INPROC_HANDLER| \
CLSCTX_LOCAL_SERVER| \
CLSCTX_REMOTE_SERVER)
These values are defined in the standard enumeration of CLSCTX
as: typedef enum tagCLSCTX
{ CLSCTX_INPROC_SERVER = 0x1,
CLSCTX_INPROC_HANDLER = 0x2,
CLSCTX_LOCAL_SERVER = 0x4,
CLSCTX_REMOTE_SERVER = 0x10,
...
}CLSCTX;
You can find as well 2 other shortcut macros in the SDK header file
(objbase.h
): #define CLSCTX_INPROC (CLSCTX_INPROC_SERVER|\
CLSCTX_INPROC_HANDLER)
#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER|\
CLSCTX_LOCAL_SERVER|\
CLSCTX_REMOTE_SERVER)
It is worth to know that environments such as Visual Basic
and Visual Java always use CLSTX_ALL
, indicating that any
available implementation will be good ([Bi11],
chapter 3).
Here is the Activation chain used by COM in order
to locate, load and launch the COM Server and return a interface pointer to the
client (look at
[Bi1],
chapter 6,
[Bi3],
chapter 5 and
[Bi11],
chapter 6):
In the figure above, a yellow rectangle indicates a registry key or
subkey under [
HKEY_CLASSES_ROOT\CLSID
] and a green rectangle indicates one under
[
HKEY_CLASSES_ROOT\AppID
].
For simplicity, I have not taken into account the
security aspect. So, let see what happens:
- The client calls
CoGetClassObject()
which gives control to
the COM Service Control Manager (SCM). Because the third
parameter of CoGetClassObject()
is not set with a host name, the
SCM will first look in the local registry for the key:
[HKCR\CLSID\{GUID1}]
- Notice that in Windows 2000, the SCM will look first under the key [
HKEY_CURRENT_USER
] and then
[HKEY_CLASSES_ROOT
] (aliased as [HKCR
]).
- If the key does not exist locally, the SCM will then try to find
information on the Windows 2000 Active Directory and install the component
locally.
- If the key is not available, the call will fail with the
HRESULT
code
REGDB_E_CLASSNOTREG
: CLSID is not properly registered.
This
code error might also indicate that the value you specified in the second
parameter of CoGetClassObject()
is not in the registry.
COM SCM is looking for an In-process
- At this stage, the class ID
GUID1
is available the SCM will then
look for the subkey: [HKCR\CLSID\{GUID1}\InprocServer32]
@="C:\myserver.dll"
If the key is present, it should contain a valid path with a DLL file
name. COM will load the DLL into the client process space, call DllGetClassObject()
to get the
IClassFactory
interface pointer
and return it to the client.
- If this key is not present, then the SCM will look for the subkey:
[HKCR\CLSID\{GUID1}\InprocHandler32]
@="C:\myserver.dll"
Again, if the key is present, it should contain a valid path with a DLL
file name. COM will load the DLL into the client process space, call DllGetClassObject()
to get the
IClassFactory
interface pointer
and return it to the client.
If neither
In-process subkey is
available, the SCM will look for an
Out-of-process activation. After this
stage, the client will always get back an
interface pointer on a proxy.
COM SCM is looking for an Out-of-process locally
- The SCM is now looking on its cache to see whether the requested COM class
object (class factory) is currently registered. If so, the SCM will return a
marshalled interface pointer to the client.
The COM server will register
its class factories with the SCM using the helper function
CoRegisterClassObject()
.
If the server uses the flag REGCLS_SINGLEUSE
, then the SCM will not put the class factory as public
level and so will not be available for subsequent activation request. In fact,
for subsequent activation calls, the SCM will start a new process using the
step #5 and followings.
- If the class factory is not registered in its cache (or has been removed
from the public view of the SCM), this means that there is not any
Out-of-process currently running and providing this class factory as public
level.
Under Windows NT 4.0 or 2000, COM supports 3 process models for
creating servers:
- NT Services.
- Normal processes.
- Surrogate processes. They are used to host DLL servers:
- locally it provides fault isolation and security context.
- remotely it provides remote activation and distributed architecture.
Whatever the process model is used to create a server
process, the server will have 120 seconds (or 30 seconds under Windows NT
service Pack 2 or earlier) to register the requested class factory. If the
server process fails to do so in time, the SCM will fail the client's
activation request ([Bi11],
chapter 6).
When creating a server process, the SCM will first
look for a local service. It will try to get an AppID
:
- by looking under the named value:
[HKCR\CLSID\{GUID1}]
AppID={GUID2}
If it finds a value, e.g. GUID2
, it will look for the named
value under the AppID
root: [HKCR\AppID\{GUID2}]
LocalService="MyService"
- If it can not find the AppID value GUID2 under the key
[HKCR\CLSID\{GUID1}] it takes the class ID value itself GUID1
as an AppID and look under the AppID root:
[HKCR\AppID\{GUID1}]
LocalService="MyService"
In the figure above, GUID1
and GUID2
could have
the same value, but it is preferable if it is not the case.
GUID1
represents the class ID of the COM class factory whilst GUID2
represents the COM Application ID used by the COM class factory.
If a value exists, the (COM) SCM will ask to the Windows SCM to start
the service MyService
. The service will register its class factories
with the SCM using the helper function CoRegisterClassObject()
.
Now, COM can query for the class factory GUID1
and ask it to return a
pointer for the IClassFactory
interface, which is to be marshalled back
to the client.
- If the SCM can not find this named value, then it will try to start a
normal process, so it will look for the subkey:
[HKCR\CLSID\{GUID1}\LocalServer32]
@="C:\myserver.exe"
If a value exists, the SCM will try to launch the local server by using
API functions such as CreateProcess()
or
CreateProcessAsUser()
.
After this step, the SCM could no
start neither a
Local service nor a
Local Server, so it would try
to create an Out-of-process
remotely.
COM SCM is looking
for an Out-of-process remotely
- If the SCM can not find a local server, it will look for the named value:
[HKCR\AppID\{GUID2}]
RemoteServerName="\\MyRemoteComputer"
If this value is available, the activation request will be forwarded to
the SCM on the designated host machine. It is worth noting that although the
client application will only use the CLSCTX_LOCAL_SERVER
flag when
querying the activation, the request will be forwarded to the remote machine
if no local servers are registered.
The remote SCM will,
following steps #4 through #6 (i.e. steps #7.c through #7.e), try to find and
launch a remote server that supports the requested class factory. If it will
succeed it will return a pointer for the IClassFactory
interface, which
is to be marshalled back to the client machine.
- If neither a Local service nor a Local Server could be
launched, then the remote SCM will check for the named value on the remote
machine:
[HKCR\AppID\{GUID2}]
DllSurrogate="C:\MySurrogate.exe"
If this named value exists, the remote SCM will start the Surrogate
process (e.g. MYSURROGATE.EXE) and ask it to load the DLL COM server
designated under the subkey: [HKCR\CLSID\{GUID1}\InprocServer32]
@="C:\myserver.dll"
then it will ask it to return a pointer for the IClassFactory
interface, which is to be marshalled back to the client machine.
If
the named value DllSurrogate is empty: [HKCR\AppID\{GUID2}]
DllSurrogate=""
then the remote SCM will start the default Surrogate process (called
DLLHOST.EXE) and ask it to load the DLL COM server.
Maybe, you are now wondering "
Why the SCM will not try to
create a Surrogate process after step #6 ?"
As I wrote before, there are
three process models. Until step #6, the SCM have tried to create the first two:
NT service and normal process. The last process model is Surrogate process and
it can be used locally to load and activate DLL COM Server as Out-of-process.
Nevertheless to activate this kind of process locally the client application
must explicitly ask it to COM by using the
CLSCTX_LOCAL_SERVER
flag only
instead of the
CLSCTX_ALL
flag.
"
Why ? (again)"
In
order to use the Surrogate process the SCM still need to have the DLL file name
under the subkey
[HKCR\CLSID\{GUID1}\InprocServer32]. That is fine, but
when the client specified
CLSCTX_ALL
, it is specified
CLSCTX_INPROC_SERVER as the same time, the SCM will look first for the
subkey
[HKCR\CLSID\{GUID1}\InprocServer32] and if it exists then it will
launch the COM Server as an In-process server into the client space. In this
situation, the SCM will never reach the named value
DllSurrogate.
Some remarks:
- if on the remote machine the named value RemoteServerName exists
the remote SCM will not consider it when it will be executing a remote
activation. This means that you can not reroute the remote activation into
another machine and so on.
- The third parameter of
CoGetClassObject()
takes as its third
parameter a pointer into a COSERVERINFO
structure. You can use
this structure to explicitly set the remote machine name.
When this
parameter is NULL, the SCM will look for the value named
RemoteServerName in the registry.
In general, you use a security
infrastructure to protect your private data, or any resource, against wrong
hands.
At the beginning, COM did not have a specific security
infrastructure to protect the client or the server application. The release of
Windows NT 4.0 introduced processes and threads security levels and permitted
server processes to be accessed remotely. On the Windows platforms
implementation (particularly NT 4.0 and 2000), the COM security infrastructure
is built by using:
- the operating system features,
- and the RPC security infrastructure (see [Bi11],
chapter 6).
Before to go deeper in the COM Security
Infrastructure, it is useful to have a brief introduction to Windows NT/2000
Security.
The Windows NT/2000 security infrastructure
Windows NT/2000 has a
support for security based on user accounts, groups, and domains. Windows 95/98
security support is lower than Windows NT/2000. In this section I will talk only
about Windows NT/2000 security aspect, for specific Windows 95/98
implementations please refer to the platform documentation.
For the rest of
this section, the word
Windows
will refer as Windows NT/2000 when
there is no need to distinguish between them.
Windows focuses on 2 areas
(
[Bi12],
chapter 18):
- Authentication. Authentication try to answer to the question
"Are you really who you claim to be ?" . One of the most use of
authentication in Windows is when a user try to log on.
- Access control. Access control in Windows allows or
limits certain users access to specific resources or services.
In order to log on to Windows, the user must have a user account. Each
user and user group is identified by a unique value called a Security IDenfier
(
SID). Once the user logged on successfully, Windows associated to the
user an
access token. This access token contains information related to
the user such as the user SID, the list of the groups the user belong to and
other privileges.
Every time a process is started under the session
opened by the user, Windows (by default) associated the user's access token to
it. Then, when the process wants to access a system object (e.g. a thread, a
mutex, or a file) Windows compares the security information attached to it and
the access token of the process. After comparison, Windows grants or denies the
access.
Every system object can contain a Security Descriptor that is
composed of:
- the owner SID.
- the primary group SID to which the user belong to.
- the System Access Control List (SACL), for audit messages
- the Discretionary Access Control List (DACL), for the control
access.
Both types of access control lists (
SACL and
DACL) are lists of Access Control Entries (
ACEs). An ACE contains
the SID of a user or group of user and some type of access (e.g. Read, Write,
Execute, etc.) that is either granted to (
access-allowed ACE) or denied
(
access-denied ACE).
I think it is time to have a picture:
The ACE-Denied entries are always placed in first positions.
In
Windows, the job of
authenticating a user is done by a Security Support
Provider (
SSP). The Win32 API defines a security API called the Security
Support Provider Interface (
SSPI). A
SSP is a DLL that implements
the
SSPI and generally contains common authentication and cryptographic
data schemes.
In Windows NT 4.0, there was only one SSP deliver with the
operating system: the NT LAN Manager Security Support Provider (
NTLM
SSP).
In Windows 2000, there are more:
- NTLM SSP, as in Windows NT 4.0 .
- Kerberos is a more sophisticated authentication protocol than
NTLM SSP.
- Snego for Simple GSS-API Negotiation Mechanism. In fact,
Snego is not really a SSP itself. It is protocol used to negotiate
between real SSPs. It chooses Kerberos if it supported by both sides
(client and server), otherwise it chooses NTLM.
This is an
open architecture as third parties can develop new SSP and install them
without interfering with the existing ones. An application that already uses an
SSP would require few or maybe no modification with a new SSP.
The COM security infrastructure
COM distinguishes between 4 fundamental
aspects of security (
[Bi4]):
- Launch security: Which security users are allowed to create a new
object in a new process ?
=> Protecting the server
machine
- Access security: Which security users are allowed to call an object
?
=> Protecting the object
- Identity: What is the security user of the object itself ?
=> Controlling the object
- Connection policy: Integrity- can messages be altered? Privacy- can
messages be intercepted by others? Authentication- can the object find out or
even assume the identity of the caller?
=> Protecting the
data
These aspects can be set at different levels, i.e. the
security grain:
- Machine-wide security level,
- Application-wide security level (or per-Server basis),
- per-Class basis
- per-Interface basis
- per-Method call basis
Nota:
when talking about the last
3 levels (per-class, per-Interface, and per-method call basis) they are
generally called fined-grain security. You can set the
security information in 2 complementary ways:
- by Configuration. The security informations are stored in the
registry. You can use DCOMCNFG.EXE to set these informations.
Many books explain how to use this tool, such as [Bi3],
chapter 5, [Bi12],
chapter 18, [Bi10],
chapter 10, and the MSDN article [Bi5].
- by Programmation. You can use the COM Security API to set security
information.
By
Configuration you can not set all the security
aspect information, and it is the same with
Programmation. For this
reason, they are complementary.
Settings on the registry are also called the
default settings.
If you set security information on more than
one level, what happens ? In fact, according to the security levels, you can
override the settings of the lower level by a higher level. Here is a figure
pointing out the security level ordered:
An
per-Method security level override a
per-Interface security level, an so on.
And to terminate this
high-level view of COM security model, some of these security informations can
be set only on the client side, only on the server side, or in both sides.
All these parameters and combinations of settings make COM Security a
huge subject by itself, but if you are developing distributed applications you
must look at them.
The COM Macro-Topology
After finishing a COM component, we have to
deploy, install and configure it. There could be many situations to deploy our
components.
By deployment I mean:
- What kind of unit (Executable or DLL) will you use for your Client or your
Server ?
- Where do you copy the Client unit and the Server unit ?
We can
define 3 criterias to determine the COM deployment Architecture, or like I call
it the "COM Macro-Architecture":
- The location (
2
):
- Local means that the Client and the Server are in the same
machine. However maybe not in the same process.
- Remote means that the Client and the Server are not in the same
machine.
- The client (
2
): an Executable or a DLL.
- The COM server (
3
): an executable, DLLs or a DLL merged.
- an Executable. You have to be aware about DCOM Application
security and the Proxy/Stub DLL.
- DLLs. This case corresponds to 2 DLLs : one for the COM Server
itself and one more for the Proxy/Stub DLL.
- DLL with Proxy/Stub merged. only one DLL.
So,
with those 3 criterias there are 12 cases (2 x 2 x 3).
The 12 cases
We will see case by case how to make and install our COM
applications: Client & Server.
Here are the 12 cases:
Here are the picture symbol's legend used in the 12
cases:
Here are the steps to build this case:
- Create the COM Server as an Executable (Look at the "COM
Macro-Architecture Topology (Servers)" article).
- Create the Client application as an Executable (Look at the "COM
Macro-Architecture Topology - Clients" article).
- Copy the server files (Executable and Proxy/Stub DLL) and client file to
the target machine.
- Register the Server using the "Local consideration".
- Launch the Client application and use the COM Server.
The results
are showed in the picture below:
Legend
Some remarks about this deployment architecture:
- Process relation:
- The client application and the COM server objects will never run in the
same process.
- The cardinality of the relation between instances (processes) of a COM
Server and a Client application might be:
- 1 to 1: Each client application could have its own COM Server.
- 1 to n: A COM Server could be shared between many client applications.
- n to 1: A client application could have many COM Servers.
This
depend on the initialisation of the Class Factories in the COM Server (using
the COM API function CoRegisterClassObject()
) but this is out of the
scope of this series.
- COM Security aspect
- You can use DCOMCNFG.EXE to set the different security details
(Access, Launch, User, etc.).
- COM Server Executable can be developed as a Windows Service.
When
you want to uninstall the system (Client application and COM Server):
- Remove the Client application by simply deleting the Client executable
file.
- Unregister the COM Server following the instructions in the article "COM
Macro-Architecture Topology (Servers)".
- Step 9 using the "Local consideration".
- Remove the COM Server files by simply deleting the COM Server executable
file and the Proxy/Stub DLL file.
For this deployment, you can have 2 different
configurations:
- the COM DLL server loaded into the client process. COM refers as this
server as an in-process server.
- the COM DLL server running outside the client process but in the same
machine. COM refers as this server as a (local) out-of-process server.
In-process Server
Here are the steps to build this case:
- Create the COM Server as 2 DLLs (Look at the "COM
Macro-Architecture Topology (Servers)" article).
- Create the Client application as an Executable (Look at the "COM
Macro-Architecture Topology - Clients" article).
- Copy the server files (COM DLL Server and Proxy/Stub DLL) and client file
to the target machine.
- Register the Server using the "Local In-process consideration".
- Launch the Client application and use the COM DLL Server.
The
results are showed in the picture below:
Legend
Some remarks about this deployment architecture:
- Process relation:
- The client application and the COM DLL server will run in the same
process.
- The cardinality of the relation between instances (processes) of a COM DLL
Server and a Client application is:
- 1 to 1: Each client application has its own COM DLL Server. In reality,
the instance of the DLL will be shared between clients' processes. This
means that every global data will be shared as well, so they should be safe
multithreaded. Nevertheless, every runtime instances (heap and stack) will
be part of the client's memory space process.
- COM Security aspect
- A DLL can never run without a process. All the security aspects will be
managed by this process, i.e. the client process.
- Other:
- The client code can access the COM object indirectly (links 1.a, 1.b and
1.c) if they are in different COM apartments or directly (link 2) if they
are in the same, but this matter is out of the scope of this series.
When you want to uninstall the system (Client application
and COM DLL Server):
- Remove the Client application by simply deleting the Client executable
file.
- Unregister the COM DLL Server following the instructions in the article "COM
Macro-Architecture Topology (Servers)".
- Step 9 using the "Local In-process consideration".
- Remove the COM Server files by simply deleting the COM DLL Server file and
the Proxy/Stub DLL file.
Out-of-process Server
Here are the steps to build this case:
- Create the COM Server as 2 DLLs (Look at the "COM
Macro-Architecture Topology (Servers)" article).
- Create the Client application as an Executable (Look at the "COM
Macro-Architecture Topology - Clients" article).
- Copy the server files (COM DLL Server and Proxy/Stub DLL) and client file
to the target machine.
- Register the Server using the "Local Surrogate consideration".
- Launch the Client application and use the COM DLL Server.
The
results are showed in the picture below:
Legend
Some remarks about this deployment architecture:
- Process relation:
- The client application and the COM DLL server will run in the same
process.
- The cardinality of the relation between instances (processes) of a COM DLL
Server and a Client application is:
- 1 to 1: Each client application could have its own COM Server.
- 1 to n: A COM Server could be shared between many client applications.
- n to 1: A client application could have many COM Servers.
The
fact to have many instances of the default Surrogate application
(DLLHOST.EXE) running in the same machine and then of your COM DLL
Server depends on the security values set (see at The
activation mechanism).
- COM Security aspect
- You can use DCOMCNFG.EXE to set the different security details
(Access, Launch, User, etc.).
- Other:
- If in the client code you use flags such as CLSCTX_INPROC_SERVER,
CLSCTX_INPROC_HANDLER, CLSCTX_SERVER or CLSCTX_ALL the
in-process server will be launched first by COM.
When
you want to uninstall the system (Client application and COM DLL Server):
- Remove the Client application by simply deleting the Client executable
file.
- Unregister the COM DLL Server following the instructions in the article "COM
Macro-Architecture Topology (Servers)".
- Step 9 using the "Local Surrogate consideration".
- Remove the COM Server files by simply deleting the COM DLL Server file and
the Proxy/Stub DLL file.
For this deployment, you can have 2 different
configurations:
- the COM DLL server loaded into the client process. COM refers as this
server as an in-process server.
- the COM DLL server running outside the client process but in the same
machine. COM refers as this server as a (local) out-of-process server.
In-process Server
Here are the steps to build this case:
- Create the COM Server as 1 DLL (Look at the "COM
Macro-Architecture Topology (Servers)" article).
- Create the Client application as an Executable (Look at the "COM
Macro-Architecture Topology - Clients" article).
- Copy the server file (this time the COM DLL Server is merged with the
Proxy/Stub code) and the client file to the target machine.
- Register the Server using the "Local In-process consideration".
- Launch the Client application and use the COM DLL Server.
The
results are showed in the picture below:
Legend
Some remarks about this deployment architecture:
- Process relation:
- The client application and the COM DLL server will run in the same
process.
- The cardinality of the relation between instances (processes) of a COM DLL
Server and a Client application is:
- 1 to 1: Each client application has its own COM DLL Server. In reality,
the instance of the DLL will be shared between clients' processes. This
means that every global data will be shared as well, so they should be safe
multithreaded. Nevertheless, every runtime instances (heap and stack) will
be part of the client's memory space process.
- COM Security aspect
- A DLL can never run without a process. All the security aspects will be
managed by this process, i.e. the client process.
- Other:
- The client code can access the COM object indirectly (links 1.a, 1.b and
1.c) if they are in different COM apartments or directly (link 2) if they
are in the same, but this matter is out of the scope of this series.
When you want to uninstall the system (Client application
and COM DLL Server):
- Remove the Client application by simply deleting the Client executable
file.
- Unregister the COM DLL Server following the instructions in the article "COM
Macro-Architecture Topology (Servers)".
- Step 9 using the "Local In-process consideration".
- Remove the COM DLL Server file by simply deleting the file.
Out-of-process Server
Here are the steps to build this case:
- Create the COM Server as 1 DLL (Look at the "COM
Macro-Architecture Topology (Servers)" article).
- Create the Client application as an Executable (Look at the "COM
Macro-Architecture Topology - Clients" article).
- Copy the server file (this time the COM DLL Server is merged with the
Proxy/Stub code) and the client file to the target machine.
- Register the Server using the "Local Surrogate consideration".
- Launch the Client application and use the COM DLL Server.
The
results are showed in the picture below:
Legend
Some remarks about this deployment architecture:
- Process relation:
- The client application and the COM DLL server will run in the same
process.
- The cardinality of the relation between instances (processes) of a COM DLL
Server and a Client application is:
- 1 to 1: Each client application could have its own COM Server.
- 1 to n: A COM Server could be shared between many client applications.
- n to 1: A client application could have many COM Servers.
The
fact to have many instances of the default Surrogate application
(DLLHOST.EXE) running in the same machine and then of your COM DLL
Server depends on the security values set (see at The
activation mechanism).
- COM Security aspect
- You can use DCOMCNFG.EXE to set the different security details
(Access, Launch, User, etc.).
- Other:
- In that configuration, we have lost the benefit to have only one DLL.
Because we want our component to run out-of-process, the client application
still needs the marshalling code (Proxy/Stub code) in its space process.
Therefore, you have to build and install the Proxy/Stub DLL.
- If in the client code you use flags such as CLSCTX_INPROC_SERVER,
CLSCTX_INPROC_HANDLER, CLSCTX_SERVER or CLSCTX_ALL the
in-process server will be launched first by COM.
When
you want to uninstall the system (Client application and COM DLL Server):
- Remove the Client application by simply deleting the Client executable
file.
- Unregister the COM DLL Server following the instructions in the article "COM
Macro-Architecture Topology (Servers)".
- Step 9 using the "Local Surrogate consideration".
- Remove the COM DLL Server file by simply deleting the file.
Here for deployment sake I have made the difference
between Client DLL and Executable, but there are "no differences" from a
functional point a view. I mean the Client code to write is the same in both
cases.
However, with in-process COM Server (DLL) you have to take in account
the COM Apartment consideration, but this is outbound the subject of this
article.
Obviously, if your client is also a COM server, you have to apply
the same rules for the COM server explained before. So:
- For the case 4 refer to the Case
1,
- For the case 5 refer to the Case
2,
- For the case 6 refer to the Case
3.
Here are the steps to build this case:
- Create the COM Server as an Executable (Look at the "COM
Macro-Architecture Topology (Servers)" article).
- Create the Client application as an Executable (Look at the "COM
Macro-Architecture Topology - Clients" article).
- Copy the server files (Executable and Proxy/Stub DLL) to the server
machine (see below as HOST B).
- Copy the server Proxy/Stub DLL and the client application to the client
machine (see below as HOST A).
- Register the Server using the "Remote consideration". There are 2
registrations: one for the Client machine and one for the Server machine.
- Configure the DCOM security aspect of the Server.
- Launch the Client application and use the COM Server.
The results
are showed in the picture below:
Legend
Some remarks about this deployment architecture:
- Process relation:
- The client application and the COM server objects will never run on the
same machine and so in the same process.
- The cardinality of the relation between instances (processes) of a COM
Server and a Client application might be:
- 1 to 1: Each client application could have its own COM Server.
- 1 to n: A COM Server could be shared between many client applications.
- n to 1: A client application could have many COM Servers.
This
depend on the initialisation of the Class Factories in the COM Server (using
the COM API function CoRegisterClassObject()
) but this is out of the
scope of this series.
- COM Security aspect
- You can use DCOMCNFG.EXE to set the different security details
(Access, Launch, User, etc.).
- DCOM aspect
- You have to enable DCOM on both machines: Client and Server. You can use
DCOMCNFG.EXE (on the
Default Properties
tab).
- If you have more than one server machine (many HOST B), you can configure
client machines to use different server machine by simply changing the
"RemoteServerName" value (under the
AppID
key) in the
registry.
You can as well use, in your client application code, the API
function CoCreateInstanceEx()
to determine the machine on which the
object will be instantiated.
- COM Server Executable can be developed as a Windows Service.
When
you want to uninstall the system (Client application and COM Server):
- Unregister the COM Server following the instructions in the article "COM
Macro-Architecture Topology (Servers)". There are 2 unregistrations: one
for the Client machine and one for the Server machine.
- Step 9 using the "Remote consideration".
- On the Client machine, remove the Client application and the Server
Proxy/Stub DLL by simply deleting these files.
- On the Server machine, remove the COM Server files by simply deleting the
COM Server executable file and the Proxy/Stub DLL file.
Here are the steps to build this case:
- Create the COM Server as 2 DLLs (Look at the "COM
Macro-Architecture Topology (Servers)" article).
- Create the Client application as an Executable (Look at the "COM
Macro-Architecture Topology - Clients" article).
- Copy the server files (COM DLL Server and Proxy/Stub DLL) to the server
machine (see below as HOST B).
- Copy the server Proxy/Stub DLL and the client application to the client
machine (see below as HOST A).
- Register the Server using the "Remote consideration". There are 2
registrations: one for the Client machine and one for the Server machine.
- Configure the DCOM security aspect of the Server.
- Launch the Client application and use the COM Server.
The results
are showed in the picture below:
Legend
Some remarks about this deployment architecture:
- Process relation:
- The client application and the COM server objects will never run on the
same machine and so in the same process.
- The cardinality of the relation between instances (processes) of a COM
Server and a Client application might be:
- 1 to 1: Each client application could have its own COM Server.
- 1 to n: A COM Server could be shared between many client applications.
- n to 1: A client application could have many COM Servers.
The
fact to have many instances of the default Surrogate application
(DLLHOST.EXE) running in the same machine and then of your COM DLL
Server depends on the security values set (see at The
activation mechanism).
- COM Security aspect
- You can use DCOMCNFG.EXE to set the different security details
(Access, Launch, User, etc.).
- DCOM aspect
- You have to enable DCOM on both machines: Client and Server. You can use
DCOMCNFG.EXE (on the
Default Properties
tab).
- If you have more than one server machine (many HOST B), you can configure
client machines to use different server machine by simply changing the
"RemoteServerName" value (under the
AppID
key) in the
registry.
You can as well use, in your client application code, the API
function CoCreateInstanceEx() to determine the machine on which the
object will be instantiated.
When you want to uninstall the system
(Client application and COM DLL Server):
- Unregister the COM DLL Server following the instructions in the article "COM
Macro-Architecture Topology (Servers)". There are 2 unregistrations: one
for the Client machine and one for the Server machine.
- Step 9 using the "Remote consideration".
- On the Client machine, remove the Client application and the Server
Proxy/Stub DLL by simply deleting these files.
- On the Server machine, remove the COM Server files by simply deleting the
COM DLL Server file and the Proxy/Stub DLL file.
Here are the steps to build this case:
- Create the COM Server as 1 DLL (Look at the "COM
Macro-Architecture Topology (Servers)" article).
- Create the Client application as an Executable (Look at the "COM
Macro-Architecture Topology - Clients" article).
- Copy the server file (this time the COM DLL Server is merged with the
Proxy/Stub code) to the server machine (see below as HOST B).
- Copy the server Proxy/Stub DLL and the client application to the client
machine (see below as HOST A).
- Register the Server using the "Remote consideration". There are 2
registrations: one for the Client machine and one for the Server machine.
- Configure the DCOM security aspect of the Server.
- Launch the Client application and use the COM Server.
The results
are showed in the picture below:
Legend
Some remarks about this deployment architecture:
- Process relation:
- The client application and the COM server objects will never run on the
same machine and so in the same process.
- The cardinality of the relation between instances (processes) of a COM
Server and a Client application might be:
- 1 to 1: Each client application could have its own COM Server.
- 1 to n: A COM Server could be shared between many client applications.
- n to 1: A client application could have many COM Servers.
The
fact to have many instances of the default Surrogate application
(DLLHOST.EXE) running in the same machine and then of your COM DLL
Server depends on the security values set (see at The
activation mechanism).
- COM Security aspect
- You can use DCOMCNFG.EXE to set the different security details
(Access, Launch, User, etc.).
- DCOM aspect
- You have to enable DCOM on both machines: Client and Server. You can use
DCOMCNFG.EXE (on the
Default Properties
tab).
- If you have more than one server machine (many HOST B), you can configure
client machines to use different server machine by simply changing the
"RemoteServerName" value (under the
AppID
key) in the
registry.
You can as well use, in your client application code, the API
function CoCreateInstanceEx() to determine the machine on which the
object will be instantiated.
When you want to uninstall the system
(Client application and COM DLL Server):
- Unregister the COM DLL Server following the instructions in the article "COM
Macro-Architecture Topology (Servers)". There are 2 unregistrations: one
for the Client machine and one for the Server machine.
- Step 9 using the "Remote consideration".
- On the Client machine, remove the Client application and the Server
Proxy/Stub DLL by simply deleting these files.
- On the Server machine, remove the COM DLL Server file by simply deleting
the file.
Same explanation as for
Case
4,
Case
5 and
Case
6.
The corresponding cases are :
- For the case 10 refer to the Case
7,
- For the case 11 refer to the Case
8,
- For the case 12 refer to the Case
9.
A final question might be:
"
Should I build in-process servers or out-of-process servers ?" (see
[Bi10]).
In
reality it will depend of your requirements and your constraints, but I think
now you have enough information to answer that question by yourself. Main ideas
to keep in mind is that:
- A COM Server as an Executable will never be used as an in-process Server.
- A COM Server as a DLL could be used as both: in-process and out-of-process
Server.
- In-process vs. Out-of-process:
- You can have performance by using in-process server (COM object ought to
share the same apartment of the Client code).
- You can have robustness by using out-of-process server.
- An in-process server will benefit from security privileges of its parent
process.
- An in-process server has its life tight to the client process life.
I hope I have given you an informative overview to "COM
Macro-Architecture". You should have now a good understanding on how to create
and deploy your COM applications locally or remotely and some things you should
consider in building COM application systems.
When I started this series
of articles I have tried to organise my work around a duality idea and I chose
the duality concept of
Macro/Micro
. Now, I maybe release that a
better duality concept would be
Static/Dynamic
:
- The split is still the same: the
unit of deployment
.
- We can use
Static
instead of Macro
, as once a
component is deployed it will not move from its physical location (Host
machine) and unit (Executable or DLL file).
- We can use
Dynamic
instead of Micro
, as at
runtime, when we instantiate our COM objects, we can talk about what it is
happening inside the Application and COM Server (such as Thread, Memory,
Apartment, etc.) and the relation between these instances.
One more
remark about this article: I did not talk about mixing cases, such as local and
remote deployment at the same time (e.g. case 1 and 7). Maybe I will write this
section on a future update.
For my part, I will try to write the
"COM Micro-Architecture" article, or maybe "COM Dynamic-Architecture".
Thanks
I would like to thank Minh, my wife, to her support; Dave Haste
and Anne-Sophie Merot for spending the time to review my article.
- [Bi1]
- Specification for COM,
version 0.9, October 24, 1995.
- [Bi2]
- Inside Distributed COM, Guy Eddon and Henry Eddon, 1998,
Microsoft
Press.
- [Bi3]
- Learning DCOM, Thuan L. Thai, April 1999,
O'Reilly edition.
- [Bi4]
- DCOM Architecture, Markus Horstmann and Mary Kirtland,
July 23, 1997,
MSDN Library.
- [Bi5]
- COM Security in Practice, Rajiv Dulepet,
MSDN Library.
- [Bi6]
- Run Your Applications on a Variety of Desktop Platforms with Terminal
Server, Frank Kim,
Microsoft Interactive Developer, December 1998.
- [Bi7]
- Inside ATL, George Shepherd and Brad King, 1999,
Microsoft Press.
- [Bi8]
- The Rules of the Component Object Model, Charlie Kindel, October 20, 1995,
MSDN Library.
- [Bi9]
- Designing COM Interfaces, Charlie Kindel, October 20, 1995,
MSDN
Library.
- [Bi10]
- ActiveX/COM Q & A, Don Box, 1997,
Question: "I am
building a suite of COM objects that have little or no user interface and will
be called from a variety of client languages, perhaps over a network. Should I
build inproc servers or outofproc servers ?" ,
MSDN Library /
reproduced from Microsoft Systems Journal.
- [Bi11]
- Essential COM, Don Box, 1998,
Addison Wesley.
- [Bi12]
- Inside COM+ Base Services, Guy Eddon and Henry Eddon, 1999,
Microsoft
Press.
- [Bi13]
- The COM and COM+ programming primer, Alan Gordon, 2000,
Prentice Hall
PTR.
- [Bi14]
- COM Security Primer, Part I & II, Jeff Prosise, November 2000,
Codeguru Web
site