PocketPCのCOMでもやっぱりClassObjectを取得するためには、DLLから DllGetClassObjectをエクスポートする必要がある。 ATL COMの場合は次のようになる。
///////////////////////////////////////////////////////////////////////////// // 要求された型のオブジェクトを作成するためにクラス ファクトリを返します STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { return _Module.GetClassObject(rclsid, riid, ppv); }
ちょっと前に戻ってみると、PocketPCのATLでは、DllMainがない。
単に表示されていないだけなのでしょう。普通のDLLを作ってみたらDllMainがあった。
だいぶ横道にそれたが、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も参照。