////////////////////////////////////////////////////////////
//
//	IUnknownを勝手に実装するテンプレートクラス
//
//	2005/04/14 ミュー  http://nwhite.s19.xrea.com/
//
//
////////////////////////////////////////////////////////////
//
//	Tに指定するクラスはメソッド QueryInterfaceImpl を実装している必要があります。
//	これは
//
//		void QueryInterfaceImpl(REFIID riid, LPVOID FAR *ppv)
//
//	のような宣言のメソッドで、内容は
//	"riidを見て使用しているインターフェースのIIDだった場合は、
//	ppvにインターフェースでキャストしたthisを格納する"
//	と言う処理にします。
//
//	実装例）
/*
	//	CMyuIUnknownImpl 用に QueryInterfaceImpl を実装する
	void CHogeClassFactory::QueryInterfaceImpl(REFIID riid, LPVOID FAR *ppv)
	{
		if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
    		*ppv = (IClassFactory*)this;
	}
*/
////////////////////////////////////////////////////////////

#ifndef __MyuIUnknownImpl_H__
#define __MyuIUnknownImpl_H__

//	クラス宣言
template <typename T> class CMyuIUnknownImpl : public T
{
protected:
	ULONG m_nRef;	//	参照カウンタ

public:
	//	コンストラクタ/デストラクタ
	CMyuIUnknownImpl(){}
	virtual ~CMyuIUnknownImpl(){}

	//	QueryInterfaceを実装する
	STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR *ppv)
	{
		*ppv = NULL;

		//	IIDとthisのセットに関してはT側でやる
		T::QueryInterfaceImpl(riid, ppv);

		//	IIDに一致する物はなかったようで
		if( *ppv != NULL )
		{
			AddRef();
			return NOERROR;
		}

		return E_NOINTERFACE;
	}

	//	AddRefを実装する
    STDMETHODIMP_(ULONG) AddRef()
	{
		m_nRef++;
		return m_nRef;
	}

	//	Releaseを実装する
	STDMETHODIMP_(ULONG) Release()
	{
		m_nRef--;
		if( m_nRef == 0 )
		{
			//	参照が無くなったら自分のインスタンスを削除する
			delete this;
			return 0L;	//	m_nRefは存在しないので定数で0を返す
		}
		return m_nRef;
	}
};

#endif//__MyuIUnknownImpl_H__