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

  • This ESG study by Mark Peters evaluated a common industry-standard disk VTl deduplication system (with 15:1 reduction ratio) versus a tape library with LTO-5, drives with full nightly backups, over a five-year period.  The scenarios included replicated systems and offsite tape vaults.  In all circumstances, the TCO for VTL with deduplication ranged from about 2 to 4 times more expensive than the LTO-5 tape library TCO. The paper shares recent ESG research and lots more. 

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds