Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Bringing DCOM remoting functionality to Windows CE and .NET CF2.0

, 17 Apr 2006 CPOL
This article shows how to use DCOM on Windows CE 5.0. We will add full DCOM rich error information, and implement a DCOM interface between a Windows XP .NET 2.0 client and Windows CE DCOM server. With this code, it is possible to code .NET remoting alike functionality through DCOM interop.
////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2006 Werner Willemsens
//
////////////////////////////////////////////////////////////////////

#pragma once

#include "message.h"
#include "notifier.h"

extern CNotifier *g_TheNotifier;

template <class T>
class CProxy_IGateEvents :
	public IConnectionPointImpl<T, &__uuidof( _IGateEvents ), CComDynamicUnkArray>,
	public CDummy    
{
	//Warning this class will  be regenerated by the wizard.
public:

	// For debugging connecting clients
	STDMETHODIMP Advise(IUnknown *pUnkSink, DWORD *pdwCookie)
	{
		HRESULT hr = ATL::IConnectionPointImpl<T, &__uuidof( _IGateEvents ), CComDynamicUnkArray>::Advise(pUnkSink, pdwCookie);
		return hr;
	}

	// For debugging disconnecting clients
	STDMETHODIMP Unadvise(IUnknown *pUnkSink, DWORD *pdwCookie)
	{
		HRESULT hr = ATL::IConnectionPointImpl<T, &__uuidof( _IGateEvents ), CComDynamicUnkArray>::Unadvise(pUnkSink, pdwCookie);
		return hr;
	}

	void Fire_Opened(VARIANT *aValue)
	{
		tMsg Msg;

		// Prepare a structure with the snapshotvalue and
		// the function be called from the workerthread
		Msg.m_Dummy = reinterpret_cast<CDummy*>(this);
#pragma warning(disable : 4407)
		Msg.m_Func = (FUNC_VOID)(&CProxy_IGateEvents::DoFire_Opened);
#pragma warning(default : 4407)
		// VariantCopy will do a deep copy for BSTR and ARRAY
		::VariantInit(&Msg.m_vVARIANT);
		::VariantCopy(&Msg.m_vVARIANT, aValue);

		// Add a reference until message has been processed
		this->AddRef();
		g_TheNotifier->Write(&Msg);
	}

	ULONG DoFire_Opened(void *pArgs)
	{
		// Convert to native types
		VARIANT *valueSnapshot = (VARIANT *)pArgs;

		HRESULT hr = DoFire_Opened(valueSnapshot);

		// Remove extra references
		this->Release();
		// Destroy VARIANT, BSTR and ARRAY are also deleted
		::VariantClear(valueSnapshot);

		return hr;
	}

	HRESULT DoFire_Opened(VARIANT *Destination)
	{
		CComVariant varResult;
		T* pT = static_cast<T*>(this);
		int nConnectionIndex;
		CComVariant* pvars = new CComVariant[1];
		int nConnections = m_vec.GetSize();
		
	#ifdef UNDER_CE
		// When passing NULLs in place of puArgErr and pExcepInfo, invoke method is
		// crashing due to un-known reasons.
		EXCEPINFO stExcepInfo;
		unsigned int uiArgErr = 0;
	#endif  // UNDER_CE

		for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
		{
			pT->Lock();
			CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
			pT->Unlock();
			IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
			if (pDispatch != NULL)
			{
				VariantClear(&varResult);
				pvars[0] = *Destination;
				DISPPARAMS disp = { pvars, NULL, 1, 0 };

	#ifdef UNDER_CE
				// Ask for the IDispatch interface. The only IDispatch supported by,
				// the client is the outbound interface of the server.
				IDispatch *pSinkDispatch = NULL;
				HRESULT hResult = pDispatch->QueryInterface(IID_IDispatch,reinterpret_cast<void**>(&pSinkDispatch));
				if (FAILED(hResult)) return hResult;

				// If the threading model is _ATL_APARTMENT_THREADED, the
				// interface pointer of out bound interface obtained from another thread
				// need to be marshalled across the thread.
				#ifdef _ATL_APARTMENT_THREADED

				// Stream into which the interface pointer marshalled for other thread is put into
				IStream *pifStream  = NULL ;

				// Call CoInitializeEx for this particular thread
				hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);

				// Marshal interface pointer into stream
				hResult = CoMarshalInterThreadInterfaceInStream(IID_IDispatch, (IUnknown *)pSinkDispatch, &pifStream);

				// Unmarshal the interface pointer from stream and release the stream.
				hResult = CoGetInterfaceAndReleaseStream(pifStream, IID_IDispatch, (void **)&pSinkDispatch);

				pifStream = NULL ;
				#endif   // ATL_APARTMENT_THREADED

				// Call the invoke method of the client's IDispatch interface.
				// Don't pass NULL in place of puArgErr and pExcepInfo
				hResult = pSinkDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, &stExcepInfo, &uiArgErr);
				pSinkDispatch->Release() ;
	#else   // UNDER_CE
				HRESULT  hr = pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
	#endif  // UNDER_CE
			}
		}
		delete[] pvars;
		return varResult.scode;
	}

};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Werner Willemsens
Team Leader
Belgium Belgium
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141220.1 | Last Updated 17 Apr 2006
Article Copyright 2006 by Werner Willemsens
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid