DLLs are like children; they need constant attention. A DLL can never run without a parent process nearby to protect it. However, DLL components can be remoted if a surrogate is available to provide round-the-clock supervision and security. COM+ provides a default DLL surrogate (dllhost.exe1) that loves and protects your in-process components when they are away from home. The file dllhost.exe is an executable component that can be remoted and then instructed to load any in-process component, providing the component with a surrogate parent process and security context. Since an in-process component can be remoted using a DLL surrogate, this is where we'll begin our discussion of the COM+ remote infrastructure.
To activate an in-process component in the context of a DLL surrogate, you must configure two settings in the registry. You can add these settings in the component's self-registration code, but for this discussion we'll add the entries by using the following surrogate.reg file:
REGEDIT4 [HKEY_CLASSES_ROOT\CLSID\{10000002-0000-0000-0000-000000000001}] "AppID"="{10000002-0000-0000-0000-000000000001}" [HKEY_CLASSES_ROOT\AppID\{10000002-0000-0000-0000-000000000001}] @="Inside COM+ Sample" "DllSurrogate"="" |
The AppID value in the class identifier (CLSID) section links clients with the component's entry in the application identifier (AppID) section of the registry. In the AppID section, we define the DllSurrogate value, which requests that the in-process component be run inside a surrogate and specifies the name of that surrogate. Since no surrogate name is provided in this case, the system-supplied surrogate, dllhost.exe, is used by default.
An AppID is a 128-bit globally unique identifier (GUID) that groups the configuration and security options for all the coclasses exposed by a COM+ application in one centralized location in the registry: HKEY_CLASSES_ROOT\AppID. To associate a coclass with an AppID, you place the named-value of AppID, which contains the string corresponding to the AppID listed under the AppID subkey, in its CLSID entry in the registry. This mapping sequence is shown in Figure 12-1.
Figure 12-1. The registry mapping of a CLSID to an AppID.
To simplify management of common security and configuration settings, COM+ objects hosted by the same component are grouped together under one AppID. Executables can also be registered under the AppID key in a subkey indicating the module name (for example, component.exe). These subkeys contain an AppID value that indicates the AppID associated with the executable and are used to obtain the default access permissions. The following table shows the valid named-values that can be present in an AppID subkey. Note that you can set most of these values using the Distributed COM Configuration utility (discussed later in this chapter).
AppID Named-Values | Description |
---|---|
AccessPermission | Sets the access control list (ACL) that determines default access permissions |
ActivateAtStorage | Configures the client to activate on the same system as persistent storage |
AuthenticationLevel | Sets the default authentication level |
DllSurrogate | Names the surrogate process used to load DLLs remotely |
LaunchPermission | Sets the ACL that determines who can launch the application |
LocalService | Configures the component to run as a Microsoft Windows NT Service |
RemoteServerName | Names a remote server |
RunAs | Sets an application to run only as a given user |
ServiceParameters | Sets parameters to be passed to LocalService on invocation |
We're almost there, but we still need to change the call to create the object. In the client, you first adjust the CoCreateInstance call to specify a local component. That's right—a local component. Even though our component is still implemented as an in-process component, we call CoCreateInstance to instantiate a local component as shown in the following code. With the addition of the AppID and DllSurrogate information, this code is now legal.
CoCreateInstance(CLSID_InsideCOM, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pUnknown); |
Now it's time to rebuild and run the client. Notice that only messages displayed by the client are visible. Messages from the component are nowhere to be seen because the component is running in the address space of the dllhost surrogate. The dllhost surrogate doesn't display a user interface, so no output messages from the component appear. You can verify that the surrogate is running by displaying the task list and observing that the dllhost.exe process is running.
NOTE
If the HKEY_CLASSES_ROOT\CLSID\{10000002-0000-0000-0000-000000000001}\LocalServer32 registry key is present, you must delete it to run the in-process version of the InsideCOM object within the DLL surrogate.
You might wonder why you'd ever want to run an in-process component in a DLL surrogate. Doing so offers these benefits:
In most cases, to enable remote execution, you run an in-process component under the guidance of a surrogate. To configure existing COM+ components to run remotely, you need not change one iota of code. Because you can specify all the necessary information in the registry, even legacy components written prior to the advent of surrogates can still use these features.
If a client calls CoCreateInstance using the flag CLSCTX_LOCAL_SERVER, the client is not necessarily restricted to local servers—it might in fact end up using a remote server. Here's how the process works: when the Service Control Manager (SCM) tries to activate an executable component, it first checks for the AppID named-value in HKEY_CLASSES_ROOT\CLSID\{YourCLSID} key of the registry. If it finds the AppID named-value, it looks for the same GUID in the HKEY_CLASSES_ROOT\AppID section of the registry, where it might find some of the named-values that specify where and how the component should be activated.
For example, to launch a component on another machine, the RemoteServerName value should indicate the name of the desired computer. When you request an object on a remote machine, the SCM on the local machine contacts the SCM on the remote machine designated by the RemoteServerName value to request that the remote SCM locate and load the component on its machine. In this way, remote capabilities can be configured for legacy clients and components.
To configure a surrogate process to run remotely, you must make sure that all the standard registry entries configured via the component's self-registration routine are present on the client machine, along with the following entries:
REGEDIT4 [HKEY_CLASSES_ROOT\CLSID\{10000002-0000-0000-0000-000000000001}] "AppID"="{10000002-0000-0000-0000-000000000001}" [HKEY_CLASSES_ROOT\AppID\{10000002-0000-0000-0000-000000000001}] @="Inside COM+ Sample" "RemoteServerName"="Remote_Computer_Name" |
These entries specify that when a client looks for the component, the component should actually be run on another machine specified by the RemoteServerName named-value. You need not modify that client's call to CoCreateInstance to specify CLSCTX_REMOTE_SERVER instead of CLSCTX_LOCAL_SERVER. The RemoteServerName entry in the registry provides all the information the SCM needs. The remote computer on which the component actually runs must have the registry configured as before, with the DllSurrogate named-value but not the RemoteServerName named-value. Note that if you have both the DllSurrogate and RemoteServerName entries in the registry, the client's call to CoCreateInstance must specify CLSCTX_REMOTE_SERVER in order to connect with the component remotely. Otherwise, the client will launch the DLL surrogate locally.
The Distributed COM Configuration utility (dcomcnfg.exe) was designed solely to help configure the registry so that legacy clients and components can participate in a distributed environment.2 This utility has four pages: Applications, Default Properties, Default Security, and Default Protocols. The Applications tab shows a list of executable components and allows the user to configure them for remote execution by selecting a component and clicking the Properties button, as shown in Figure 12-2. The other three tabs are used to control default settings for components.
Figure 12-2. Setting the Inside COM+ Sample properties using dcomcnfg.exe.
To entirely disable DCOM on the current machine, you deselect the Enable Distributed COM On This Computer option on the Default Properties tab or set the EnableDCOM value in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE key of the registry to N.
NOTE
Every time the Distributed COM Configuration utility runs, it generates AppIDs in the registry for any coclasses that have a CLSID\LocalServer32 key but not an AppID key.