{
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();
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.