Instantiating _com_ptr_t objects remotely


.

I was going along, cheerfully using COM with Microsoft's smart pointers when I discovered a glaring omission in the underlying _com_ptr_t code. It turns out that there is no way to use CreateInstance() to instantiate an object remotely. And there is no equivalent member function to CreateInstanceEx().

After a bit of digging around I ended up writing this (partially tested) macro that I believe allows remote or local instantiation of Microsoft's smart COM pointers.

Normally you create an COM instances using Microsoft's Smart Pointers as follows:

m_pMyCOMObj.CreateIntance(CLSID_MyCOMObj);
 

When using this macro, replace the previous code with the following:

HRESULT hr = CreateInstanceEx<IIMyCOMObjPtr>(m_pMyCOMObj, CLSID_MyCOMObj, _T("RemoteHostname"));

This should allow you to connect to your remote host simply by specifying the hostname or IP address in the 3rd argument. Don't forget to check the return value for success.

The code follows:

// This template is used to invoke either local or remote instances of
// C++ builtin smart COM objects.
template <typename ObjPtr>
HRESULT CreateInstanceEx(ObjPtr& output, const CLSID& rclsid, 
	const CString& hostname = _T(""), IUnknown* pOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) 
{
	USES_CONVERSION;
	HRESULT hr;

	if (!hostname.IsEmpty()) {
		// Create Distributed Object

		// Declare some locals
		IUnknown*		pIUnknown;
		COSERVERINFO*	pServerInfo = NULL;
		MULTI_QI		rgmqResults;
		COSERVERINFO	ServerInfo;
		
		// Zero structures
		memset(&rgmqResults, 0, sizeof(rgmqResults));
		memset(&ServerInfo, 0, sizeof(ServerInfo));

		// Initialize data items
		dwClsContext = CLSCTX_REMOTE_SERVER;
		ServerInfo.pwszName = T2W(hostname);
		pServerInfo = &ServerInfo;
		rgmqResults.pIID = &IID_IUnknown;

		// Create the IUnknown object for the remote object object
		hr = CoCreateInstanceEx(rclsid, pOuter, dwClsContext, pServerInfo, 1, &rgmqResults);
		
		// If successful, then get the internal interface we really wanted.
		if (SUCCEEDED(hr)) {
			pIUnknown = rgmqResults.pItf;
			if (SUCCEEDED(hr)) {
				hr = pIUnknown->QueryInterface(ObjPtr::GetIID(), reinterpret_cast<void**>(&output));
			}
			pIUnknown->Release(); // IUnknown has served it's purpose so nuke it.
		}
	} else {
		// It's not remote so use the simpler call.
		hr = CoCreateInstance(rclsid, pOuter, dwClsContext, ObjPtr::GetIID(), reinterpret_cast<void**>(&output));
	}

	return hr;
}

 

Caveats

Don't forget to include _WIN32_DCOM in the preprocessor definitions of your project or you get a syntax error telling you that CoCreateInstanceEx() is not defined. You also need to make sure that OleInit() has been called prior to using the CreateInstanceEx() macro.

Last Modified: October 22, 1998



Comments

  • I can not complile it! -------"T2W"

    Posted by Legacy on 01/23/2002 12:00am

    Originally posted by: Johnnie

    "T2W"

    Reply
  • Good! Noone like to modify reg. The code just I want!!!

    Posted by Legacy on 04/30/2001 12:00am

    Originally posted by: tiger

    Thanx!

    Reply
  • CreateInstance will work with remote objects!

    Posted by Legacy on 05/19/1999 12:00am

    Originally posted by: Carl McClellan

    I found the same problem as you when trying to instantiate a remote object using _com_ptr_t. However, it is not necessary to use CreateInstanceEx() to create a remote object! (remember location transparency!). DCOMCNFG.EXE is all you need to set the location of your COM server. What you need to do is this. Run OLE/COM object viewer and look at the registry entries for your distributed COM server. If you find a registry entry _LocalServer with the a local path\name of your COM server then this is what is probably causing the problem. This entry was put there when you registered the COM server on the client. What you need to do is this

    1) Register the COM server on the client as usual
    2) Use DCOMCNFG.EXE to set the computer on which the COM server will RUN
    3) Delete the COM server on the client after he is registered
    4) Port the type library to the client and change the registry setting (under Typelib) to point to the path\location of the .lib file rather than the .exe file that hosts the com server
    5) REMOVE ANY ENTRY UNDER CLSID FOR YOUR COM OBJECT that indicates _LocalServer

    Now try CreateInstance with your smart pointer and off you go!

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • Hundreds of millions of users have adopted public cloud storage solutions to satisfy their Private Online File Sharing and Collaboration (OFS) needs. With new headlines on cloud privacy issues appearing almost daily, the need to explore private alternatives has never been stronger. Join ESG Senior Analyst Terri McClure and Connected Data in this on-demand webinar to take a look at the business drivers behind OFS adoption, how organizations can benefit from on-premise deployments, and emerging private OFS …

Most Popular Programming Stories

More for Developers

RSS Feeds