Because nearly every aspect of the network protocol is hidden from the COM+ programmer, the most interesting and concrete way to examine the network protocol is to spy on the transmissions between computers during the execution of a COM+ client and component. To do this, you need a special type of software (and/or hardware) popularly known as a lanalyzer. A variety of third-party tools are available, for every need and budget, that let you capture and view network traffic. Network Monitor, a Microsoft utility included with Windows 2000 and Microsoft Systems Management Server, is perhaps the simplest and cheapest way to capture meaningful network traffic. Figure 19-4 shows Network Monitor in action.
Figure 19-4. Using Network Monitor to capture network traffic.
Unfortunately, Network Monitor does not currently support ORPC, so we're forced to look at ORPC through the eyes of RPC. This affliction does not have to be a permanent one: Network Monitor does have a publicly documented interface for building parser dynamic-link libraries (DLLs) that understand a specific network protocol and interpret the captured data in an intelligent manner.1
To turn on Network Monitor's capture facility, simply choose Start from the Capture menu. Then run a COM+ test program to generate the desired network traffic. After the program has completed execution, return to Network Monitor and choose Stop And View from the Capture menu to disable the network capture facility and display the captured packets. Network Monitor is quite clever—rather than simply displaying the raw captured packets, it actually understands many standard network protocols and thus presents the captured data in an intelligent and descriptive format. As far as ORPC-related protocols are concerned, Network Monitor can recognize and comprehend Ethernet, IP, UDP, and RPC. To view only the packets captured for certain network protocols, choose Filter from the Display menu.
To analyze the ORPC protocol, we ran Network Monitor to capture packets as the executable version of the InsideCOM object (which we built in Chapter 13) executed. The client ran on one computer, named Thing1, and was configured to activate the InsideCOM object on a server named Thing2. After calling CoInitializeEx, the client called CoCreateInstanceEx to instantiate the remote object, as shown here:
CoInitializeEx(NULL, COINIT_MULTITHREADED); COSERVERINFO ServerInfo = { 0, L"Thing2", 0, 0 }; MULTI_QI qi = { &IID_IUnknown, NULL, 0 }; CoCreateInstanceEx(CLSID_InsideCOM, NULL, CLSCTX_REMOTE_SERVER, &ServerInfo, 1, &qi); |
The call to CoCreateInstanceEx shown above results in the Service Control Manager (SCM) on Thing1 (the client) calling the IRemoteActivation:: RemoteActivation method on the SCM on Thing2 (the server) to activate the CLSID_InsideCOM object and return the interface pointer identifier (IPID) for IID_IUnknown. Thing1 was configured with an IP address of 199.34.58.3, and Thing2 was configured with an IP address of 199.34.58.4. Figure 19-5 shows how this remote activation translates to the transmission of a network packet as viewed using Network Monitor.
You can see the layering of protocols in the network packet depicted in the figure. In the RPC header, you can see that the interface identifier (IID; labeled A) is B8 4A 9F 4D 1C 7D CF 11 86 1E 00 20 AF 6E 7C 57. Following the rules described in the sidebar above, the actual IID is 4D9F4AB8-7D1C-11CF-861E-0020AF6E7C57—the IRemoteActivation interface.
Figure 19-5. The network packet resulting from an activation request, IRemoteActivation::RemoteActivation, as captured by Network Monitor.
IRemoteActivation is an RPC interface (not a COM+ interface) that is exposed by the SCM on each machine. The SCM on Windows 2000 machines is named rpcss.dll and runs in the svchost.exe surrogate.2 The IRemoteActivation interface has only one method, RemoteActivation, which activates a COM+ object on a remote machine. This powerful feature is missing in pure RPC, in which the server must always be running before the client can connect.3 The IDL definition of the IRemoteActivation interface is shown below.
[ // No object keyword here. Not a COM+ interface! uuid(4d9f4ab8-7d1c-11cf-861e-0020af6e7c57), pointer_default(unique) ] interface IRemoteActivation { const unsigned long MODE_GET_CLASS_OBJECT = 0xffffffff; HRESULT RemoteActivation( [in] handle_t hRpc, [in] ORPCTHIS *ORPCthis, [out] ORPCTHAT *ORPCthat, [in] GUID *Clsid, [in, string, unique] WCHAR *pwszObjectName, [in, unique] MInterfacePointer *pObjectStorage, [in] DWORD ClientImpLevel, [in] DWORD Mode, [in] DWORD Interfaces, [in, unique, size_is(Interfaces)] IID *pIIDs, [in] unsigned short cRequestedProtseqs, [in, size_is(cRequestedProtseqs)] unsigned short RequestedProtseqs[], [out] OXID *pOxid, [out] DUALSTRINGARRAY **ppdsaOxidBindings, [out] IPID *pipidRemUnknown, [out] DWORD *pAuthnHint, [out] COMVERSION *pServerVersion, [out] HRESULT *phr, [out, size_is(Interfaces)] MInterfacePointer **ppInterfaceData, [out, size_is(Interfaces)] HRESULT *pResults ); } |
Through the IRemoteActivation interface, the SCM on one machine contacts the SCM on another machine to request that it activate an object. The client machine's SCM calls the IRemoteActivation::RemoteActivation method of the server's SCM to request activation of the class object identified by the class identifier (CLSID) in the fourth parameter. The RemoteActivation method returns a marshaled interface pointer for the requested object and two special values: the interface pointer identifier (IPID) and the object exporter identifier (OXID). The IPID identifies an interface of an object running in a component. The OXID identifies the RPC string binding4 information needed to connect to the interface specified by an IPID.
The SCM resides at well-known endpoints, one for each supported network protocol. An endpoint identifies the virtual channel through which you are communicating; it is based on the network protocol in use. For example, when you use Transmission Control Protocol (TCP) or UDP, the endpoint is a port number such as 1066; if you use named pipes, the endpoint is a pipe name such as \\pipe\mypipe. The following table shows the endpoints for the SCM when some of the more popular protocols are used.
Protocol String | Description | Endpoint |
---|---|---|
ncadg_ip_udp | Connectionless over UDP/IP | 135 |
ncacn_ip_tcp | Connection-oriented over TCP/IP | 135 |
ncacn_http | Connection-oriented over Hypertext Transfer Protocol (HTTP) | 593 |