Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Client/Server connection using DCOM, with anonymous access

0.00/5 (No votes)
8 Feb 2005 1  
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:

  1. Start 'New ATL COM Wizard project' with Visual Studio.
  2. Name it as TestServer.
  3. Select server type: Service.
  4. Insert new ATL object: Category-Objects, Objects-Simple Objects.
  5. Name the interface as IHello.
  6. 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:

  1. Start 'New MFC App Wizard, dialog based, name it TestClient.
  2. Insert Resource, Custom, and name it exactly TYPELIB.
  3. ID of TYPELIB resource must be 1.
  4. Open property page for TYPELIB resource and specify path to file as TestServer.tlb.
  5. Add #import "..//TestServer/testserver.tlb" no_namespace line to stdafx.h.
  6. Add includes for Afxctl.h, objbase.h and initguid.h to stdafx.h.
  7. 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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here