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: May 11, 2015 @ 1:00 p.m. ET / 10:00 a.m. PT One of the languages that have always been supported with the Intel® RealSense™ SDK (Software Developer Kit) is JavaScript, specifically so that web-enabled apps could be created. Come hear from Intel Expert Bob Duffy as he reviews his own little "space shooting" game where the orientation of your face controls the aiming reticle to help teach developers how to write apps and games in JavaScript that can use facial and gesture …

  • You may not realize the complexity you could be creating when developing mobile apps – many companies don't initially. You could be doubling your IT costs for development and delivery; not to mention, risking sales, productivity and brand satisfaction. Read this IBM-commissioned Forrester Study to understand the key cost drivers of mobile app delivery -- for both customer-facing and enterprise applications. Find out how you could lower costs and increase success with the right strategy and investment.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date