Сущность технологии СОМ. Библиотека программиста | страница 109



hr = CreateFileMoniker(pszFileName, &pmk);

if (SUCCEEDED(hr))

{

// register self in ROT

// саморегистрация в ROT

hr = prot->Register(0, this, pmk, &m_dwReg);

pmk->Release();

}

prot->Release();

}

return hr;

}


Метод IPersistFile::Load нового созданного экземпляра будет вызван диспетчером SCM во время выполнения CoGetInstanceFromFile . В приведенном выше примере для получения указателя на интерфейс IRunningObjectTable в SCM используется API-функция СОМ GetRunningObjectTable. Этот интерфейс затем используется для регистрации своего моникера в ROT, так что последующие вызовы CoGetInstanceFromFile , использующие то же файловое имя, не будут создавать новые объекты, а вместо этого возвратят ссылки на этот объект[3].

Существование File Moniker обусловлено двумя причинами. Во-первых, он нужен, чтобы позволить объектам самим регистрироваться в ROT, чтобы их мог найти CoGetInstanceFromFile. Во-вторых, чтобы скрыть от клиента использование CoGetInstanceFromFile за интерфейсом IMoniker. Реализация File Moniker из BindToObject просто вызывает CoGetInstanceFromFile:


// pseudo-code from OLE32.DLL // псевдокод из OLE32.DLL

STDMETHODIMP FileMoniker::BindToObject(IBindCtx *pbc,

IMoniker *pmkToLeft,

REFIID riid, void **ppv) {

// assume failure – на случай сбоя

*ppv = О;

HRESULT hr = E_FAIL;

if (pmkToLeft == 0) {

// no moniker to left – слева моникеров нет

MULTI_QI mqi = { &riid, 0, 0 };

COSERVERINFO *pcsi;

DWORD grfMode;

DWORD dwClsCtx;

// these three parameters are attributes of the BindCtx

// эти три параметра являются атрибутами BindCtx

this->MyGetFromBindCtx(pbc, &pcsi, &grfMode, &dwClsCtx);

hr = CoGetInstanceFromFile(pcsi, 0, 0, dwClsCtx,

grfMode, this->m_pszFileName,

1, &mqi);

if (SUCCEEDED(hr))

*ppv = mqi.pItf;

} else {

// there's a moniker to the left – слева есть моникер

// ask object to left for IClassActivator

// or IClassFactory

// запрашиваем объект слева от IClassActivator или от

// IClassFactory

}

return hr; }


При таком поведении File Moniker следующая функция, вызывающая CoGetInstanceFromFile


HRESULT GetCornelius(IApe * &rpApe)

{

OLECHAR *pwszObject = OLESTR(\\\\server\\public\\cornelius.chmp);

MULTI_QI mqi = { &IID_IApe, 0, 0 };

HRESULT hr = CoGetInstanceFromFile(0, 0, 0, CLSCTX_SERVER, STCM_READWRITE, pwszObject, 1, &mqi);

if (SUCCEEDED(hr)) rpApe = mqi.pItf;

else rpApe = 0;

return hr;

}


может быть упрощена, если вместо этого использовать вызов CoGetObject:


HRESULT GetCornelius(IApe * &rpApe)

{

OLECHAR *pwszObject = OLESTR(\\\\server\\public\\cornelius.chmp);