DllGetClassObject

PocketPCのCOMでもやっぱりClassObjectを取得するためには、DLLから DllGetClassObjectをエクスポートする必要がある。 ATL COMの場合は次のようになる。

	/////////////////////////////////////////////////////////////////////////////
	// 要求された型のオブジェクトを作成するためにクラス ファクトリを返します
	
	STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
	{
		return _Module.GetClassObject(rclsid, riid, ppv);
	}

ちょっと前に戻ってみると、PocketPCのATLでは、DllMainがない。

PocketPC ATL
PocketPC ATL


Visual .Net ATL
Visual .Net ATL

単に表示されていないだけなのでしょう。普通のDLLを作ってみたらDllMainがあった。

普通のDLL
Simple Dll

だいぶ横道にそれたが、DllGetClassObjectの中身

	_Module.GetClassObject(rclsid, riid, ppv);
を呼び出すと、
	HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
	{
		return AtlModuleGetClassObject(this, rclsid, riid, ppv);
	}

が呼ばれ、さらに

	ATLINLINE ATLAPI AtlModuleGetClassObject(_ATL_MODULE* pM, REFCLSID rclsid, REFIID riid, LPVOID* ppv)
	{
		ATLASSERT(pM != NULL);
		if (pM == NULL)
			return E_INVALIDARG;
		ATLASSERT(pM->m_pObjMap != NULL);
		_ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
		HRESULT hRes = S_OK;
		if (ppv == NULL)
			return E_POINTER;
		*ppv = NULL;
		while (pEntry->pclsid != NULL)
		{
			if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid))
			{
				if (pEntry->pCF == NULL)
				{
					EnterCriticalSection(&pM->m_csObjMap);
					if (pEntry->pCF == NULL)
						hRes = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, IID_IUnknown, (LPVOID*)&pEntry->pCF);
					LeaveCriticalSection(&pM->m_csObjMap);
				}
				if (pEntry->pCF != NULL)
					hRes = pEntry->pCF->QueryInterface(riid, ppv);
				break;
			}
			pEntry = _NextObjectMapEntry(pM, pEntry);
		}
		if (*ppv == NULL && hRes == S_OK)
			hRes = CLASS_E_CLASSNOTAVAILABLE;
		return hRes;
	}

が呼ばれる。ここでやってることは、まだクラスオブジェクトが作られていなければ作ってキャッシュし、 すでに作られていれば、キャッシュされているクラスオブジェクトを返すことだ。 ATLインターナルp.171も参照。


Valid XHTML 1.0!