|
String Binding Moniker Author: Frank Rem Assumed knowledge: This article assumes you are familiar with COM Monikers and DCE/MS RPC. Introduction: I will first describe the implementation of the DCE RPC server on Linux. Then I will describe the moniker. And finally the VB client that uses the moniker to talk to the RPC server. I will not discuss monikers in general. RPC Server The RPC server is an executable file that runs on Linux. It is built from 2 files: calculator.idl and calculator.c. The idl will be used at the client side as well. The idl file looks as follows:
[
uuid(4d9f4ab8-7d1c-11cf-861e-0020af6e7c57),
pointer_default(unique)
]
interface ICalculator
{
long Add(
[in] handle_t binding_h ,
[in] long a, [in] long b, [out] long* sum );
}
The file calculator.c implements the methods Add and main. Inside main, the RPC server is launched after which execution blocks inside rpc_server_listen. The RPC run-time will dispatch incoming calls to the method Add.
#include
Note that I never check status. I tested this on Red Hat Linux release 5.2 in combination with Free DCE 1.2.2. After you launch the server, the string binding will be displayed:
[frank@study sbmoniker]$ ./calculator
String binding = ncacn_ip_tcp:192.168.0.2[1112]
Listening...
Moniker
The SB moniker is packaged as a DLL. COM will load it into the client process when the moniker is needed to resolve a string binding to a connection with the RPC server. The moniker is implemented by the class CoSBMoniker. This class creates an instance of CCalculatorProxy when it is asked to resolve a string binding. The class CCalculatorProxy implements the connection by forwarding COM calls to the RPC server. I will now discuss both classes in turn. CoSBMonikerThis class derives from the template CComMoniker [2]. This gives me default implementations of the interfaces IPersist, IPersistStream, IMoniker, IParseDisplayName, IROTData and IMarshal. I only override the implementation of IMoniker.
class ATL_NO_VTABLE CoSBMoniker :
public CComObjectRootEx
IMoniker::ParseDisplayName checks whether the string starts with the correct display name. The remaining part of the display name (after the colon) is the actual string binding. This part is copied to the member variable m_szStringBinding. When the method IMoniker::BindToObject is called, m_szStringBinding is used to resolve the string to a binding handle. For this, the helper method CalculatorProxyFromStringBinding is called. This method creates an instance of CCalculatorProxy.
STDMETHODIMP CoSBMoniker::BindToObject(
IBindCtx* pbc,
IMoniker* pmkToLeft,
REFIID riidResult,
void** ppvResult)
{
if ( !ppvResult ) return E_POINTER;
if ( pmkToLeft ) return E_UNEXPECTED;
return CalculatorProxyFromStringBinding( riidResult, ppvResult );
}
HRESULT CoSBMoniker::CalculatorProxyFromStringBinding(
REFIID riid,
void** ppv)
{
if ( !ppv ) return E_POINTER;
if ( !m_szStringBinding ) return E_UNEXPECTED;
handle_t hBinding;
RPC_STATUS status;
status = RpcBindingFromStringBinding(
( unsigned char* ) m_szStringBinding,
&hBinding );
if ( status != RPC_S_OK ) return E_FAIL;
CComObject
The moniker resolves the string binding to an instance of CCalculatorProxy inside
CSBMoniker::BindToObject as shown in the previous section. CCalculatorProxy holds the binding
handle of the RPC server and provides a method for each method of the interface of the RPC server. The implementation of CCalculatorProxy is very trivial. The class is generated using the ATL Wizard after which all (one, in this case) methods of the RPC interface are added:
#include "calculator.h"
STDMETHOD(Add)(long a, long b, long* sum)
{
if ( !sum ) return E_POINTER;
::Add( m_hBinding, a, b, sum );
return S_OK;
}
The included file calculator.h is generated in a custom build step as follows:
midl /osf calculator.idl
This generates calculator.h and calculator_c.c. The last file is added to the project. The file calculator.idl is the same one as used at the server-side. Visual Basic ClientThe VB client runs on a Windows machine where the moniker has been registered. It will use the string binding moniker to obtain a connection to the RPC server. The form of the VB client consists of 4 text boxes and 1 button. The text boxes contain the string binding, the arguments a and b and the result sum. The button invokes CreateObject followed by Add(a,b).
Private Sub Add_Click()
Dim obj
Set obj = CreateObject( "frem.stringbinding.1:" & txtSB.Text)
txtSum.Text = obj.Add(CLng(txtA.Text), CLng(txtB.Text))
End Sub
The CreateObject call is resolved to the following steps: 1. COM searches the registry for the class object that goes with frem.stringbinding.1. 2. COM asks the class object for an implementation of IMoniker. 3. The class object returns an instance of CoSBMoniker. 4. CoSBMoniker::ParseDisplayName is called. 5. CoSBMoniker::BindToObject is called. 6. The moniker returns an instance of CCalculatorProxy. 7. The moniker is released. ConclusionsThe String Binding Moniker can be a very useful building block in a system consisting of both Windows and UNIX platforms. Imagine your UNIX legacy code being wrapped as a COM object that can be invoked from an easily written VB client running on Windows. It certainly is a cheap alternative compared to a full-blown UNIX COM implementation. Although not shown here, the String Binding Moniker can be generalized by resolving the string binding to an implementation of IDispatch instead of a custom interface. If the RPC server implements IDispatch as well, only one moniker has to be developed that handles any interface. Of course there is a performance penalty. Furthermore passing interface pointers to the RPC server will require unmarshal functionality on Linux. I will present this kind of functionality in another article. References[1] Free DCE RPC: https://www.bu.edu/~jrd/FreeDCE [2] CComMoniker: https://www.sellsbrothers.com/tools#basicmk Thanks go to the authors of Free DCE (Jim Doyle e.a.) and CComMoniker (Tim Ewald, Chris Sells
and Don Box). Further Reading
Author: Frank Rem - [email protected] Frank will soon have his own site at Author Central - contribute to iDevResource.com and you can have one too! © 2000 IDevResource.com Contribute to IDR: To contribute an article to IDR, a click here.
|
|