Click here to Skip to main content
14,977,910 members
Articles / Desktop Programming / WTL
Posted 15 Nov 2001


42 bookmarked

Passing C++ classes across DCOM

Rate me:
Please Sign up or sign in to vote.
4.64/5 (10 votes)
15 Nov 20012 min read
Two classes that provide richer interfaces and easier semantics to pass classes via COM/DCOM

Sample Image


Using COM technology to pass simple data like long, int, etc is easy. And what about structured data like C++ classes?

The most developers know the way to pass that. This way is based on passing data using VARIANT as SAFEARRAY. And what does VARIANT mean?

The VARIANT is perhaps the ultimate in general purpose functionality for passing data. But its range of low-level features can be daunting. I did not find a suitable library for the easy use of one in my projects.

To resolve this problem I built two classes to provide richer interfaces and easier semantics. The first class called CDComObj. This class is responsible for Reading/Writing data into/from VARIANT. The second class, CDcomObjArray, is responsible for passing collection of objects across DCOM. By using both of these classes it is easy to implement any C++ class which has ability to pass itself across DCOM.

An Example Using the Objects

Client part:

bool CServerAccessPoint::ServerConnect(CConnection& connObj)
   CComSafeArray conn;
   connObj.Write(conn); // Writing C++ class to VARIANT

   HRESULT hr = m_pDcomServer->Connect(&conn);
   if (FAILED(hr))
     // DO something...
     return false;
   return true;

Server part:

STDMETHODIMP CStreamingSrv::Connect(VARIANT *pConnection)
  CConnection conn;
  conn.Read(pConnection); // Reading C++ class from VARIANT

  return S_OK;

Is not easy?


class CDcomObj  : public CSLObject
  virtual ~CDcomObj();

  virtual void Clear();
  virtual void Copy(const CSLObject& objectSrc);
          void Copy(const CDcomObj& objectSrc);
  virtual bool IsEqual(const CSLObject& objectSrc);

  virtual HRESULT WriteToStream(IStream* pStream);
  virtual HRESULT ReadFromStream(IStream* pStream);

  virtual long ElementSize();
          void Write(VARIANT* pSafeArray);
          void Write(CComSafeArray* safeArray);
  virtual void Write(CComSafeArray* safeArray,long& index);

          void Read(const CLSID& clsid);
          void Read(VARIANT* pSafeArray);
          void Read(CComSafeArray* safeArray);
  virtual void Read(CComSafeArray* safeArray,long& index);
          void ReadValue(const CComVariant& srcValue,CComVariant& destValue);
          void ReadValue(const CComVariant& srcValue,CComPtr<IUNKNOWN>& destValue);
          void ReadValue(const CComVariant& srcValue,IUnknown** destValue);
          void ReadValue(const CComVariant& srcValue,CString& destValue);
          void ReadValue(const CComVariant& srcValue,CComBSTR& destValue);
          void ReadValue(const CComVariant& srcValue,LONG& destValue);
          void ReadValue(const CComVariant& srcValue,CY& destValue);
          void ReadValue(const CComVariant& srcValue,bool& destValue);
          void ReadValue(const CComVariant& srcValue,UINT& destValue);
          void ReadValue(const CComVariant& srcValue,DWORD& destValue);
          void ReadValue(const CComVariant& srcValue,int& destValue);
          void ReadValue(const CComVariant& srcValue,double& destValue);
          void ReadValue(const CComVariant& srcValue,DATETIME_STRUCT& destValue);

          void ProgIDFromCLSID(const CLSID& clsid,CComBSTR& comBSTR);

          const	CLSID	 GetCLSID();
          const	CComBSTR GetLastError();
          const	bool IsModified() const;
          const	bool IsModified(UINT value) const;
          const	UINT GetModified() const;
                void AddModified(UINT uModified);
                void SetModified(UINT uModified);
                void RemoveModified(UINT uModified);
                void ShowError(CString lpszError);

    CComBSTR	m_strCLSID;
    CComBSTR	m_strProgID;
    CComBSTR	m_strObjectName;
    // Specifics
    UINT      m_uModified;
    CComBSTR  m_bstrError;

Using the classes, step by step

The implementation of own DCOM class is very easy.

Step 1: Create your own class derived from CDComObj.

class CConnection  : public CDcomObj

Step 2: Redefine the following virtual member functions :

// Shows how many elements contains your class
virtual long ElementSize()
// Writing class data to VARIANT (SAFEARRAY)
virtual void Write(CComSafeArray* safeArray,long& index);
// Reading class data from VARIANT (SAFEARRAY)
virtual void Read(CComSafeArray* safeArray,long& index);
// Copying data
virtual void Copy(const CSLObject& objectSrc);
// Clear data
virtual void Clear();

The DComObj contains the set of macros. So, redefinitions of mentioned functions is easy

An Example

To demonstrate this technique I built two classes: CConnection and CConnectionArray

class CConnection  : public CDcomObj
  virtual ~CConnection();

  virtual void Clear();
  virtual void Copy(const CSLObject& objectSrc);
  virtual bool IsEqual(const CSLObject& objectSrc);
  virtual long ElementSize();
  virtual void Write(CComSafeArray* safeArray,long& index);
  virtual void Read(CComSafeArray* safeArray,long& index);


  CString   m_strComputerName;
  CString   m_strApplicationName;
  CString   m_strUserName;
  CString   m_strPassword;
  CString   m_strServerName;
  CComBSTR  m_strConnectionHandle;

Here is the implementation of ElementSize() member function

long CConnection::ElementSize()			
  return 6 + CDcomObj::ElementSize();	

The implementation of Write and Read member function you can find here.

void CConnection::Write(CComSafeArray* safeArray,long& index)

void CConnection::Read(CComSafeArray* safeArray,long& index)

For streaming the collection of CConnection objects across DCOM it is enough to define class like here.

class CConnectionArray  : public CDcomObjArray
  CConnectionArray( ccIndex aLimit, ccIndex aDelta , bool shouldDelete = true):
  CDcomObjArray(aLimit,aDelta ,shouldDelete )
  virtual ~CConnectionArray(){}



To avoid MFC at Server side I am using CString object from WTL V.3.1. So, you should download one from Microsoft site. In any case don't forget to setup path to this library in your Compiler: Tools/Options/Directories.

For easy manipulation of SafeArray's, I am using the CComSafeArray class from

The Demo project is demonstrated as follows:

  • Passing C++ class / collection of classes across COM/DCOM.
  • Connection Point Technique

How can you see that?

  1. Register Server by starting StreamingServer.exe with option 'RegServer' : StreamingServer.exe -RegServer.
  2. Start first instance of Client: StreamingClient.exe
  3. Connect to the server as some user
  4. Start another one instance of Client
  5. Connect to server with different user name
  6. After establishing connection you can see list of connected users in any Client
  7. Start another one instance again and list of connected users will grow

What's going on?

  1. Under connection stage the client is sending to the server a C++ class CConnection.
  2. If the server accepted this request it sends a collection of CConnection classes to everything connected clients.


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


About the Author

Eugene Khodakovsky
Software Developer (Senior)
United States United States
No Biography provided

Comments and Discussions

QuestionLicense Pin
Member 896106528-May-12 23:19
MemberMember 896106528-May-12 23:19 
GeneralMissing licence Pin
Frederic Souchu25-Oct-10 22:52
MemberFrederic Souchu25-Oct-10 22:52 
QuestionHow to get it working under .NET Pin
Ben_6625-Apr-06 0:20
MemberBen_6625-Apr-06 0:20 
QuestionStandard way Pin
florin10327-Nov-05 22:14
Memberflorin10327-Nov-05 22:14 
AnswerRe: Standard way Pin
Stupid_Stuart4-Dec-06 10:16
MemberStupid_Stuart4-Dec-06 10:16 
GeneralAny language client Pin
sergeyv20026-Oct-04 10:14
Membersergeyv20026-Oct-04 10:14 
GeneralBooks for COM/DCOM Pin
Suyash15-Apr-04 23:36
MemberSuyash15-Apr-04 23:36 
GeneralRe: Books for COM/DCOM Pin
Snews28-Sep-04 20:09
MemberSnews28-Sep-04 20:09 
Questioncould you Help me ? Pin
BrutusKiller11-Mar-04 1:41
MemberBrutusKiller11-Mar-04 1:41 
AnswerRe: could you Help me ? Pin
Eugene Khodakovsky11-Mar-04 2:05
MemberEugene Khodakovsky11-Mar-04 2:05 
GeneralRe: could you Help me ? Pin
BrutusKiller11-Mar-04 2:22
MemberBrutusKiller11-Mar-04 2:22 
GeneralRe: could you Help me ? Pin
Eugene Khodakovsky11-Mar-04 3:02
MemberEugene Khodakovsky11-Mar-04 3:02 
GeneralRe: could you Help me ? Pin
11-Mar-04 3:38
suss11-Mar-04 3:38 
GeneralRe: could you Help me ? Pin
BrutusKiller15-Mar-04 5:46
MemberBrutusKiller15-Mar-04 5:46 
GeneralRe: could you Help me ? Pin
Eugene Khodakovsky15-Mar-04 6:49
MemberEugene Khodakovsky15-Mar-04 6:49 
GeneralRe: could you Help me ? Pin
BrutusKiller17-Mar-04 0:13
MemberBrutusKiller17-Mar-04 0:13 
GeneralCompile error Pin
stongstong1-Sep-03 15:16
Memberstongstong1-Sep-03 15:16 
GeneralProblem running on Windows NT4 Pin
ronny_12-Mar-03 1:08
Memberronny_12-Mar-03 1:08 
GeneralThis code will not work in MTA configuration Pin
Vic_mx23-Aug-02 21:12
MemberVic_mx23-Aug-02 21:12 
GeneralError 0x80010105 Pin
Bennyf10-Apr-02 23:42
MemberBennyf10-Apr-02 23:42 
GeneralRe: Error 0x80010105 Pin
Eugene Khodakovsky11-Apr-02 3:13
MemberEugene Khodakovsky11-Apr-02 3:13 
GeneralRe: Error 0x80010105 Pin
Bennyf11-Apr-02 18:46
MemberBennyf11-Apr-02 18:46 
GeneralRe: Error 0x80010105 Pin
Tim Smith11-Apr-02 3:40
MemberTim Smith11-Apr-02 3:40 
QuestionAccess is denied? Pin
Bennyf9-Apr-02 21:23
MemberBennyf9-Apr-02 21:23 
AnswerRe: Access is denied? Pin
Eugene Khodakovsky10-Apr-02 3:27
MemberEugene Khodakovsky10-Apr-02 3:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.