Модель программирования Component Object Model. Разработка COM-сервера, страница 14

{

m_ref = 0;

m_word = SysAllocString (L"This is MyComTLib speaking");

gObjCount++;

}

CoSay::~CoSay()

{

if (m_word)

SysFreeString(m_word);

gObjCount--;

}

STDMETHODIMP CoSay::QueryInterface(REFIID riid, void** ppv)

{

*ppv = 0;

if (riid == IID_IUnknown)

*ppv = (IUnknown*)this;

else if (riid == IID_ISay)

*ppv = (ISay*)this;

else

return E_NOINTERFACE;

AddRef();

return S_OK;

}

STDMETHODIMP_(ULONG) CoSay::AddRef() { return ++m_ref; }

STDMETHODIMP_(ULONG) CoSay::Release()

{

if (--m_ref==0)

delete this;

return m_ref;

}

STDMETHODIMP CoSay::Say()

{

char buff[MAX_LENGTH];

WideCharToMultiByte (CP_ACP, 0, m_word, -1, buff, MAX_LENGTH, 0, 0);

MessageBox (0, buff, "Interface ISay:", MB_OK);

return S_OK;

}

STDMETHODIMP CoSay::SetWord(BSTR word)

{

SysReAllocString(&m_word, word);

return S_OK;

}

STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppv)

{

if (rclsid != CLSID_CoSay)

return CLASS_E_CLASSNOTAVAILABLE;

CoSayFactory *pCF = new CoSayFactory;

HRESULT hr = pCF->QueryInterface(riid, ppv);

if (FAILED(hr))

delete pCF;

return hr;

}

STDAPI DllCanUnloadNow()

{

return !gLockCount && !gObjCount ? S_OK : S_FALSE;

}

CoSayFactory::CoSayFactory()

{

m_ref = 0;

gObjCount++;

}

CoSayFactory::~CoSayFactory()

{

gObjCount--;

}

STDMETHODIMP CoSayFactory::QueryInterface(REFIID riid, void** ppv)

{

*ppv = 0;

if (riid == IID_IUnknown)

*ppv = (IUnknown*)this;

else if (riid == IID_IClassFactory)

*ppv = (IClassFactory*)this;

else

return E_NOINTERFACE;

AddRef();

return S_OK;

}

STDMETHODIMP_(ULONG) CoSayFactory::AddRef() { return ++m_ref; }

STDMETHODIMP_(ULONG) CoSayFactory::Release()

{

if (--m_ref==0)

delete this;

return m_ref;

}

STDMETHODIMP CoSayFactory::CreateInstance (LPUNKNOWN p, REFIID r, void** pp)

{

if (p) // Мы не поддерживаем аггрегирование

return CLASS_E_NOAGGREGATION;

CoSay *pSay = new CoSay;

HRESULT hr = pSay->QueryInterface (r, pp);

if (FAILED(hr))

delete pSay;

return hr;

}

STDMETHODIMP CoSayFactory::LockServer (BOOL bLock)

{

if (bLock)

++gLockCount;

else

--gLockCount;

return S_OK;

}

Регистрация библиотеки типов

Библиотеку типов также надо регистрировать для того, чтобы клиент мог найти ее в реестре с помощью уникального идентификатора. Введите изменения  в файл MyCom.reg в соответствии со схемой, приведенной ниже, но используя при этом ваши идентификаторы, файловые адреса и имена объектов. Этот шаг чреват ошибками, поэтому будьте чрезвычайно внимательны с файловыми путями, именами объектов и идентификаторами типа GUID. Вспомните о пробелах и правилах переноса.

REGEDIT

HKEY_CLASSES_ROOT\MyCom.CoSay\CLSID = {9B865820-2FFA-11d5-98B4-00E0293F01B2}

HKEY_CLASSES_ROOT\CLSID\{9B865820-2FFA-11d5-98B4-00E0293F01B2} = MyCom.CoSay

HKEY_CLASSES_ROOT\CLSID\{9B865820-2FFA-11d5-98B4-00E0293F01B2}\InprocServer32 = D:\MyComTLib\Debug\MyComTLib.dll

HKEY_CLASSES_ROOT\CLSID\{9B865820-2FFA-11d5-98B4-00E0293F01B2}\TypeLib = {0934DA90-608D-4107-9ECC-C7E828AD0928}

HKEY_CLASSES_ROOT\TypeLib\{0934DA90-608D-4107-9ECC-C7E828AD0928} = MyComTLib

HKEY_CLASSES_ROOT\TypeLib\{0934DA90-608D-4107-9ECC-C7E828AD0928}\1.0\0\Win32 = D:\MyComTLib\Debug\MyComTLib.tlb

Сохраните исправления и зарегистрируйте все перечисленные объекты, дважды щелкнув на файле MyCom.reg в окне Windows File Manager. После этого дайте команду Build4Rebuild Solution.

Разработка клиента с использованием специальных указателей

Создайте новый пустой проект консольного приложения с именем SayTLibClient и вставьте в него новый файл SayTLibClient.cpp. Введите в файл следующий текст, и проследите за тем, чтобы текст директивы #import содержал ваш файловый путь. Кроме того важно, чтобы текст директивы либо вовсе не разрывался переносом на другую строку, либо разрывался по правилам, то есть с использованием символа переноса '\'. После этого запустите проект на выполнение (Ctrl+F5).

#import "C:\MyComTLib\Debug\MyComTLib.tlb" no_namespace named_guids

void main()

{

CoInitialize(0);

ISayPtr pSay(CLSID_CoSay);

pSay->Say();