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

  • Savvy enterprises are discovering that the cloud holds the power to transform IT processes and support business objectives. IT departments can use the cloud to redefine the continuum of development and operations—a process that is becoming known as DevOps. Download the Executive Brief DevOps: Why IT Operations Managers Should Care About the Cloud—prepared by Frost & Sullivan and sponsored by IBM—to learn how IBM SmartCloud Application services provide a robust platform that streamlines …

  • Live Event Date: August 14, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Data protection has long been considered "overhead" by many organizations in the past, many chalking it up to an insurance policy or an extended warranty you may never use. The realities of today make data protection a must-have, as we live in a data driven society. The digital assets we create, share, and collaborate with others on must be managed and protected for many purposes. Check out this upcoming eSeminar and join eVault Chief Technology …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds