Client/Server connection using DCOM, with anonymous access






4.17/5 (10 votes)
Feb 9, 2005
2 min read

110522

2976
Quick implementation of client/server connection using DCOM.
Introduction
This article will explain implementing a quick client/server connection using DCOM.
Using the code
This article consists of two parts:
- Server side implementation
- Client side implementation
Let's start with server side implementation:
- Start 'New ATL COM Wizard project' with Visual Studio.
- Name it as TestServer.
- Select server type: Service.
- Insert new ATL object: Category-Objects, Objects-Simple Objects.
- Name the interface as
IHello
. - Add method
Beep()
.
Now, we need to turn off the authentication of DCOM server. Open TestServer.rgs from Workspace window and add the following lines just before 'TestServer.EXE':
{ val AccessPermission = b '01000480300000004c000000000000001 400000002001c000100000000021400010000000101000000000001000000000 105000000000005150000007ceb240dfa4f0c2ff89fb474f2030000010500000 0000005150000007ceb240dfa4f0c2ff89fb47401020000' val LaunchPermission = b '01000480300000004c000000000000001 400000002001c000100000000021400010000000101000000000001000000000 105000000000005150000007ceb240dfa4f0c2ff89fb474f2030000010500000 0000005150000007ceb240dfa4f0c2ff89fb47401020000' }
Open testMonitor.cpp, locate Run()
function, and make it look like this:
void CServiceModule::Run() { _Module.dwThreadID = GetCurrentThreadId(); //This means that calls come in on a random RPC thread HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); // This provides a NULL DACL which will allow access to everyone. hr = CoInitializeSecurity( 0, -1, 0, 0, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, 0, 0, 0 ); hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE); ..............
Finally, add the following line to Beep()
method and the server side is ready!!!
MessageBeep(MB_ICONEXCLAMATION);
Now, let's implement the client:
- Start 'New MFC App Wizard, dialog based, name it TestClient.
- Insert Resource, Custom, and name it exactly TYPELIB.
- ID of TYPELIB resource must be 1.
- Open property page for TYPELIB resource and specify path to file as TestServer.tlb.
- Add
#import "..//TestServer/testserver.tlb" no_namespace
line to stdafx.h. - Add
include
s for Afxctl.h, objbase.h and initguid.h to stdafx.h. - Add
_WIN32_DCOM
to preprocessor definitions.
Now, we need to add the actual connection code. Add the following Connect()
function to your app class:
IIHello* CTestClientApp::Connect(CString& strIPAddress, CString& strError) { // register type library CLSID libid; CLSIDFromString (L"{55259785-1985-4DCB-B4BA-FCB7F968DFA4}", &libid); if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), libid)) { AfxMessageBox("Failed to register server's type library"); return NULL; } CLSID clsid; const IID IID_IHELLO = {0xFB57F08C,0x0F91,0x4046, {0x8E,0xF1,0x05,0xD8,0x90,0x4C,0x66,0xF0}}; MULTI_QI mqi = { &IID_IHELLO, 0, 0 }; CLSIDFromString (L"{C7B7C24F-5B72-49D0-962B-FFD650BFFA2B}", &clsid); CoInitialize(0); COAUTHINFO cai = { RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, 0, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, 0, EOAC_NONE}; COSERVERINFO csi = { 0, strIPAddress.AllocSysString(), &cai, 0 }; HRESULT hr = CoCreateInstanceEx(clsid, NULL, CLSCTX_REMOTE_SERVER, &csi, 1, &mqi); if (FAILED(hr)) { TCHAR szError[1024]; FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), szError, 1024, NULL); strError = szError; return FALSE; } return (IIHello*)(mqi.pItf); }
From the code provided above, it can be seen that three GUIDs are needed: LIBID
, CLASSID
, and ITERFACEID
. All of them must be taken from testserver.idl. Our connection code example is a bit hard-coded, but it allows to run the client on any machine without any registration. Server has to be registered before use. Since this is a DCOM server, it can be registered as a service or as a local server. To register the server as a service, type:
testserver /Service
To register the server as a local server, type:
testserver /RegServer
And finally, let's execute Beep()
method on the remote server. To do that, let's just add a handler for the Beep button.
void CTestClientDlg::OnButtonBeep()
{
((CTestClientApp*)AfxGetApp())->m_pHello->Beep();
}
Hope this wasn't boring, but useful :-)
History
- 06/02/2005 - Initial document creation.