HRESULT CoUnmarshalInterface(
[in] IStream *pStm,
// where to read marshaled state
// откуда читать маршалированное состояние
[in] REFIID riid, // type of ptr being unmaгshaled
// тип демаршалируемого указателя
[out, iid_is(riid)] void **ppv
// where to put unmarshaled ptr
// куда поместить демаршалированный указатель
);
CoUnmarshalInterface просто читает преобразованную в последовательную форму объектную ссылку и возвращает указатель на исходный объект, к которому есть легальный доступ в апартаменте вызывающего потока. Если импортирующий апартамент отличается от того апартамента, который изначально экспортировал интерфейс, то результирующий указатель будет указателем на заместитель. Если по какой-то причине вызов CoUnmarshalInterface осуществлен из исходного апартамента, где располагается объект, то в этом случае будет возвращен указатель на сам объект и не будет создано никакого заместителя. Следующий код переводит маршалированную объектную ссылку в нормальный указатель интерфейса:
HRESULT ReadPtr(HGLOBAL hglobal, IRacer * &rpRacer) {
IStream *pStm = 0; rpRacer = 0;
// wrap block of existing memory passed on input
// заключаем в оболочку блок существующей памяти,
// переданный на вход
HRESULT hr = CreateStreamOnHGlobal(hglobal, FALSE, &pStm);
if (SUCCEEDED(hr)) {
// get a pointer to the object that is legal in this apt.
// получаем указатель на объект, легальный в этом апартаменте
hr = CoUnmarshalInterface(pStm, IID_Iracer, (void**)&rpRacer);
pStm->Release();
}
return hr;
}
Результирующий заместитель будет реализовывать каждый из экспортируемых объектом интерфейсов путем переадресации запросов методов в апартамент объекта.
До появления выпуска СОМ под Windows NT 4.0 формат маршалированной объектной ссылки не был документирован. Для того чтобы позволить сторонним участникам создавать сетевые продукты, совместимые с СОМ, этот формат был документирован для открытого использования в 1996 году и представлен на рассмотрение как проект стандарта для Интернета. На рис. 5.2 показан формат маршалированной объектной ссылки. Заголовок маршалированной объектной ссылки начинается с изысканной сигнатуры «MEOW» (мяу) [3], а поле флагов указывает на выбранную технологию маршалинга (например, стандартный ( standard ), специальный ( custom )), а также IID интерфейса, содержащегося в ссылке. В случае стандартного маршалинга подзаголовок объектной ссылки показывает, сколько внешних ссылок представляет данная маршалированная ссылка.
Этот счетчик внешних ссылок является частью распределенного протокола «сборки мусора» ( garbage collection ) СОМ и не полностью совпадает со счетчиком ссылок AddRef/Release , который может быть реализован объектом. Интересным элементом объектной ссылки является кортеж ( tuple ) OXID/OID/IPID , который единственным образом идентифицируют интерфейсный указатель. Каждому апартаменту в сети во время его создания присваивается уникальный Идентификатор Экспортера Объектов ( Object Exporter Identifier – OXID ). Этот OXID используется для нахождения сетевой или IPC -адресной информации при первом соединении заместителя с объектом. Идентификатор Объекта ( Object Identifier – OID ) единственным образом определяет идентификационную единицу СОМ в сети и использует CoUnmarshalInterface для поддержания правил идентификации СОМ для заместителей. Идентификатор Интерфейсного Указателя ( Interface Pointer Identifier – IPID ) единственным образом определяет интерфейсный указатель в апартаменте и помещается в заголовок каждого последующего запроса метода. IPID используется для эффективной диспетчеризации запросов ORPC на нужный интерфейсный указатель в апартаменте объекта.
Хотя OXID представляют интерес как логические идентификаторы, сами по себе они бесполезны, так как заместителям нужен какой-нибудь механизм IРС или сетевой протокол для связи с апартаментом объекта. Для перевода OXID в полностью квалифицированные адреса сети или IPC в каждой хост-машине, поддерживающей СОМ, существует специальная служба распознавателя OXID ( OXID Resolver – OR ). Под Windows NT 4.0 OR является частью службы RPCSS . Когда апартамент инициализируется впервые, СОМ назначает OXID и регистрирует его с помощью локального OR . Это означает, что каждый OR знает обо всех работающих апартаментах локальной системы. Кроме того, OR следит за каналом локального IPC-порта для каждого апартамента. Когда CoUnmarshalInterface требуется соединить новый заместитель с апартаментом объекта, то для преобразования OXID в действительный адрес сети или IРС используется локальный OR . Если демаршалированный указатель встречается на той же машине, где находится апартамент объекта, то OR просто ищет OXID в своей локальной OXID -таблице и возвращает локальный IPC-адрес. Если же демаршалированный указатель встречается не на той машине, на которой находится объект, то локальный OR сначала проверяет, встречался ли данный OXID ранее, для чего смотрит в специальном кэше, где хранятся недавно распознанные OXID удаленного доступа. Если OXID ранее не встречался, то он передает запрос OR на хост-машину объекта, используя RPC. Отметим, что маршалированная объектная ссылка содержит адрес хост-машины объекта в формате, подходящем для целого ряда сетевых протоколов, так что OR с демаршалированной стороны знает, куда направлять запрос.
Читать дальше