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

  • You may already know about some of the benefits of Bluemix, IBM's open platform for developing and deploying mobile and web applications. Check out this webcast that focuses on building an Android application using the MobileData service, with a walk-through of the real process and workflow used to build and link the MobileData service within your application. Join IBM's subject matter experts as they show you the way to build a base application that will jumpstart you into building your own more complex app …

  • Not all enterprise applications are created equal. Sophisticated applications need developer support but other more basic apps do not. With the right tools, everyone is a potential app developer with ideas and a perspective to share. Trends such as low-code development and model driven development are fundamentally changing how and who creates applications. Is your organization ready? Read this report and learn: The seven personas of enterprise app delivery How application ownership is spreading to the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds