Фабрика классов
Реализацию тел заявленных методов вставьте в файл МуСоm.срр. Здесь мы вынуждены повторяться, вновь прокручивая логику управления временем жизни объектов СОМ:
//========== Фабрика классов CoSayFactory::CoSayFactory() { m_ref = 0; gObjCount++; } CoSayFactory::-CoSayFactory() { gObjCount--; } //====== Методы lUnknown HRESULT _ stdcall CoSayFactory ::QueryInterface(REFIID riid, void** ppv) { *ppv = 0; //=== На сей раз обойдемся без шаблона static_cast<> if (riid == IID_IUnknown) *ppv = (lUnknown*)this; else if (riid == IID_IClassFactory) *ppv = (IClassFactory*)this; else return E_NOINTERFACE; AddRef(); return S_OK; } ULONG _stdcall CoSayFactory:rAddRef() { return ++m_ref; } ULONG _stdcall CoSayFactory::Release() { if (--m_ref==0) delete this; return m_ref; //====== Методы интерфейса IClassFactory HRESULT _ stdcall CoSayFactory::CreateInstance (LPUNKNOWN pUnk, REFIID riid, void** ppv) { // Этот параметр управляет аггрегированием // объектов СОМ, которое мы не поддерживаем if (pUnk) return CLASS_E_NOAGGREGATION; //== Создание нового объекта и запрос его интерфейса CoSay *pSay = new CoSay; HRESULT hr = pSay › Query!nterface (riid, ppv); if (FAILED (hr)) delete pSay; return hr; //=== Управление счетчиком фиксаций сервера в памяти HRESULT _ stdcall CoSayFactory::LockServer(BOOL bLock) { if (bLock) // Если TRUE, то увеличиваем счетчик ++gLockCount; else // Иначе – уменьшаем --gLockCount; return S_OK; }
Мы должны также изменить алгоритм функции DllGetciassObject, которая теперь создает объект фабрики классов и запрашивает один из двух возможных интерфейсов (lUnknown, IClassFactory):
STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppv) { if (rclsid!= CLSID_CoSay) return CLASS_E_CLASSNOTAVAILABLE; CoSayFactory *pCF = new CoSayFactory; HRESULT hr = pCF › Query!nterface(riid, ppv); if (FAILED(hr)) delete pCF; return hr; }