Click here to Skip to main content
15,884,628 members
Articles / Desktop Programming / MFC

C++ Wrapper classes for the COM interfaces of Microsoft XML parser (MSXML)

Rate me:
Please Sign up or sign in to vote.
4.46/5 (32 votes)
1 Jan 20029 min read 591.4K   6.9K   114  
The provided MFC extension DLL provides easy to use wrapper classes for all COM-interfaces of Microsoft's DOM-/SAX implementation.
/********************************************************************
*
* Copyright (C) 2001 Sven Wiegand
* 
* This file is free software; you can redistribute it and/or
* modify, but leave the headers intact and do not remove any 
* copyrights from the source.
*
* If you have further questions, suggestions or bug fixes, please
* let me know
*
*    sven.wiegand@web.de
*
********************************************************************/

#ifndef __INTERFACEWRAPPER_H__
#define __INTERFACEWRAPPER_H__

#include <atlbase.h>
#include <comdef.h>

/**
Thrown if a call to a COM-interface returned a non successfull
HRESULT value. The m_hr member contains the return value that
caused the error.

To throw such an exception you should always use the static
Throw() method or the global AfxThrowComException() function.
Both are creating an instance on the heap and throwing the pointer.

To destruct a catched pointer to a CComException object, call the
Delete() method.

@author Sven Wiegand
*/
class AFX_EXT_CLASS CComException : public CException
{
// construction/destruction
public:
	CComException(HRESULT hr);

// static helpers
public:
	/**
	Constructs a CComException object on the heap and throws the 
	pointer.

	The m_hr attribute of the constructed object will be set to the
	given value.
	*/
	static void Throw(HRESULT hr);

// attributes
public:
	/** Value returned by the COM call causing the exception. */
	HRESULT m_hr;
};


/** Calls CComException::Throw() */
void AFX_EXT_CLASS AfxThrowComException(HRESULT hr);


/**
Base class for all the classes used to implement an interface.

Supports basic IUnknown features like internal reference counting.

@author Sven Wiegand
*/
class AFX_EXT_CLASS CInterfaceImplementationWrapper
{
// construction/destruction
public:
	CInterfaceImplementationWrapper();
	virtual ~CInterfaceImplementationWrapper();

// overridables
public:
	virtual IUnknown* GetInterface() = 0;
	virtual ULONG AddRef();
	virtual ULONG Release();
	virtual HRESULT QueryInterface(REFIID riid, void **ppv);

protected:
	virtual void MethodPrologue();

// attributes
private:
	ULONG m_ulRef;
};


/**
Base class for all the classes used to implement an interface derived
from IDispatch.

Supports basic IDispatch features.

Only works for dual interfaces.

@author Sven Wiegand
*/
class AFX_EXT_CLASS CDispatchInterfaceImplementationWrapper : public CInterfaceImplementationWrapper
{
// construction/destruction
public:
	CDispatchInterfaceImplementationWrapper(REFGUID rguidTypeLibrary, USHORT usVerMajor, USHORT usVerMinor, REFGUID rguidInterface);
	virtual ~CDispatchInterfaceImplementationWrapper();

// overridables
public:
	virtual HRESULT GetTypeInfoCount(UINT *pctinfo);
	virtual HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
	virtual HRESULT GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgid);
	virtual HRESULT Invoke(DISPID id, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);

// attributes
private:
	ITypeInfo *m_pTypeInfo;
};


/**
Base class for all classes that are wrapping a com interface.

@author Sven Wiegand
*/
template<class T>
class AFX_EXT_CLASS CInterfaceCallingWrapper
{
// construction/destruction
public:
	CInterfaceCallingWrapper();

	/**
	Attaches the given interface to this object.

	@param bIncrementRefCount
		Specify TRUE, if the reference count of the given interface
		should be incremented and FALSE otherwise.
	*/
	CInterfaceCallingWrapper(T *p, BOOL bIncrementRefCount = FALSE);

	/**
	Attaches the interface of the given wrapper to this object and
	increments the reference count of the interface.
	*/
	CInterfaceCallingWrapper(const CInterfaceCallingWrapper<T> &iw);

	/**
	Decrements the interfaces reference count.
	*/
	virtual ~CInterfaceCallingWrapper();

// operators
public:
	/** Returns the wrapped interface pointer */
	operator T*();

	/** Returns the dereferenced value of the interface pointer */
	T& operator*();

	/** Returns the address of the interface pointer */
	T** operator&();

	/** Use to access the interface pointer */
	T* operator->();

	/** Same as Attach(p, TRUE);	*/
	T* operator=(T *p);

	/** true if the wrapped interface pointer is NULL false otherwise */
	bool operator!();

// operations
public:
	/** 
	Attaches the specified pointer.

	Will fail if there is already an interface attached to this 
	wrapper. Call Detach() first.

	@param bIncrementRefCount
		Specify TRUE, if the reference count of the given interface
		should be incremented and FALSE otherwise.

	@return
		TRUE if the interface has been attached to the wrapper, FALSE
		if there is already an interface attached.
	*/
	BOOL Attach(T *p, BOOL bIncrementRefCount = FALSE);

	/**
	Returns the member pointer and detaches it from this object by 
	setting it to NULL.

	@param bIncrementRefCount
		Specify TRUE, if the reference count of the given interface
		should be decremented and FALSE otherwise.
	*/
	T* Detach(BOOL bDecrementRefCount = FALSE);

	/**
	Copies the internal pointer to a target pointer. The pointer's 
	reference count is incremented if successful. Returns NULL if the
	wrapped interface pointer is NULL.
	*/
	T* CopyTo();

	/**
	Creates an instance of an object in a type-safe manner.
	*/
	HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL);

	/**
	Creates an instance of an object in a type-safe manner.
	*/
	HRESULT CoCreateInstance(LPCTSTR lpszProgId, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL);

	/**
	Calls QueryInterface() on the internal pointer in a type-safe 
	manner.
	*/
	template<class Q> HRESULT QueryInterface(Q **p)
	{
		return m_p.QueryInterface(p);
	}

	/**
	Calls QueryInterface() on the internal pointer in a type-safe 
	manner.

	@param bThrowException
		If TRUE the method will throw a CComException if the call to 
		QueryInterface() fails, otherwise only a NULL pointer will
		be returned if the call fails.
	*/
	template<class Q> Q* QueryInterface(BOOL bThrowException = TRUE)
	{
		Q	*p = NULL;
		HRESULT	hr = m_p.QueryInterface(&p);
		if (hr != S_OK && bThrowException)
			AfxThrowComException(hr);

		return p;
	}

	/**
	Returns the wrapped interface pointer.
	*/
	T* P();

	/**
	Returns the wrapped interface pointer as const.
	*/
	T* GetP() const;

// attributes
private:
	CComPtr<T> m_p;
};


//-------------------------------------------------------------------
// class CInterfaceCallingWrapper
//-------------------------------------------------------------------

/////////////////////////////////////////////////////////////////////
// construction/destruction

template<class T>
CInterfaceCallingWrapper<T>::CInterfaceCallingWrapper()
{}


template<class T>
CInterfaceCallingWrapper<T>::CInterfaceCallingWrapper(T *p, BOOL bIncrementRefCount /*= FALSE*/)
{
	Attach(p, bIncrementRefCount);
}


template<class T>
CInterfaceCallingWrapper<T>::CInterfaceCallingWrapper(const CInterfaceCallingWrapper<T> &iw)
:	m_p(iw.GetP())
{}


template<class T>
CInterfaceCallingWrapper<T>::~CInterfaceCallingWrapper()
{}

/////////////////////////////////////////////////////////////////////
// operators

template<class T>
CInterfaceCallingWrapper<T>::operator T*()
{
	return m_p;
}


template<class T>
T& CInterfaceCallingWrapper<T>::operator*()
{
	return *m_p;
}


template<class T>
T** CInterfaceCallingWrapper<T>::operator&()
{
	return &m_p;
}


template<class T>
T* CInterfaceCallingWrapper<T>::operator->()
{
	return m_p.p;
}


template<class T>
T* CInterfaceCallingWrapper<T>::operator=(T *p)
{
	Attach(p, TRUE);
	return m_p;
}


template<class T>
bool CInterfaceCallingWrapper<T>::operator!()
{
	return !m_p;
}


/////////////////////////////////////////////////////////////////////
// operations

template<class T>
BOOL CInterfaceCallingWrapper<T>::Attach(T *p, BOOL bIncrementRefCount /*= FALSE*/)
{
	// There is already an interface attached.
	// Call Detach() first.
	ASSERT(!m_p);
	if (m_p)
		return FALSE;

	m_p.Attach(p);
	if (bIncrementRefCount)
		m_p.p->AddRef();

	return TRUE;
}


template<class T>
T* CInterfaceCallingWrapper<T>::Detach(BOOL bDecrementRefCount /*= FALSE*/)
{
	if (bDecrementRefCount)
		m_p.p->Release();

	return m_p.Detach();
}


template<class T>
T* CInterfaceCallingWrapper<T>::CopyTo()
{
	T	*p;
	if (m_p.CopyTo(&p) == S_OK)
		return p;
	else
		return NULL;
}


template<class T>
HRESULT CInterfaceCallingWrapper<T>::CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter /*= NULL*/, DWORD dwClsContext /*= CLSCTX_ALL*/)
{
	return m_p.CoCreateInstance(rclsid, pUnkOuter, dwClsContext);
}


template<class T>
HRESULT CInterfaceCallingWrapper<T>::CoCreateInstance(LPCTSTR lpszProgId, LPUNKNOWN pUnkOuter /*= NULL*/, DWORD dwClsContext /*= CLSCTX_ALL*/)
{
	BSTR		bstrProgId = CString(lpszProgId).AllocSysString();
	HRESULT	hr = m_p.CoCreateInstance(bstrProgId, pUnkOuter, dwClsContext);
	SysFreeString(bstrProgId);
	return hr;
}


template<class T>
T* CInterfaceCallingWrapper<T>::P()
{
	return m_p;
}


template<class T>
T* CInterfaceCallingWrapper<T>::GetP() const
{
	return m_p;
}

#endif //__INTERFACEWRAPPERS_H__

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Germany Germany
Sven Wiegand (1976), IT professional living in Berlin (Germany), develops open source software in his free time. His most successfull project is the LaTeX IDE TeXnicCenter which is distributed under the terms of the GNU-GPL and has more than 100,000 users all about the world.

"The picture shows me with my racing bike on the top of the Roque de los Muchachos (2426m) - the highest point of the canarian island La Palma."

Comments and Discussions