Регистрация COM объектов. Часть II. 64-х разрядная специфика

Итак, продолжаем начатое в первой части. 64-х разрядные версии Windows не разрешают смешивать 32-х и 64-х битный код в пределах одного процесса. В результате этого ограничения некоторые ветви реестра были также разделены на 32-х и 64-х разрядные. В частности, были разделены ключи, отвечающие за регистрацию COM компонент. Этот механизм называется перенаправлением реестра (registry redirection) и реализуется средствами Wow64. Механизм более или менее прозрачен для приложений в том смысле, что и 32-x и 64-х битные приложения используют одинаковые пути вида «HKEY_CLASSES_ROOT\Classes{…}», но работают, в конечном итоге, с разными ключами.

Практически вышесказанное означает, что 64-х битные версии системы поддерживают как 32-х так и 64-х разрядные COM компоненты, а также то, что 32-х и 64-х битные компоненты регистрируются отдельно. По большому счету 32-х и 64-х разрядные окружения можно рассматривать как разные компьютеры. Например, чтобы 32-х битный клиент и 64-х битный сервер могли общаться друг с другом, каждый из них должен использовать Proxy/Stub DLL соответствующей разрядности. Единственная разница между сценариями, когда клиент и сервер разнесены по разным машинам и когда они установлены на одном и том же компьютере, но имеют разную разрядность, – это протокол, используемый для передачи RPC сообщений.

Интересное, но не всегда очевидное следствие этого, – при установке COM компонента также должны регистрироваться две (32-х и 64-х битные) Proxy/Stub DLL, иначе компонент не будет доступен для клиентов с «неправильной» разрядностью. Замечу, что большинство 32-х разрядных приложений этого не делают и продолжают нормально работать. В чем же дело? Причина в том, что:

  1. Это правило касается только out-of-proc COM компонент;

  2. Либо все клиенты данного COM сервера имеют одинаковую с ним разрядность;

  3. Либо COM сервер использует интерфейсы, помеченные атрибутом [dual] или [automation].

В остальных случаях без регистрации двух Proxy/Stub DLL не обойтись.

Помимо перенаправления реестра, о котором я говорил выше, wow64 также реализует второй механизм, которой называется отражение реестра (registry reflection).

Нужно сказать, что эти два механизма путают все кому не лень. Каждый раз когда приходит письмо с вопросом об одном их них, приходится догадываться что именно имел ввиду спрашивающий. Неудачное название, в общем. :-)

Отражение реестра заключается в синхронизации некоторых из перенаправляемых ветвей реестра по определённым правилам. Этот механизм не что иное, как способ обеспечить совместимость существующих 32-х битных COM компонент с 64-х разрядных окружением. Каким образом? А вот каким. Посмотрим что происходит при регистрации 32-х битного COM компонента на 64-х разрядной системе.

Регистрация COM сервера, использующего raw интерфейсы

В случае, если сервер использует raw интерфейсы и собственную Proxy/Stub DLL в реестре регистрируется:

  1. Сам COM компонент;

  2. Его интерфейсы;

  3. Proxy/Stub DLLs.

Wow64 отражает (копирует) эти данные в соответствующие 64-битные ключи. При этом регистрация Proxy/Stub DLL не копируется, так как Proxy и Stub представляют собой не что иное как in-proc COM компонент, т.е. 32-х разрядная Proxy/Stub DLL всё равно не может быть загружена в 64-х битный процесс. Сам объект, тем не менее, может быть создан 64-х битным клиентом.

Вывод: raw интерфейсы требует регистрации 2-х Proxy/Stub DLL.

В случае, если сервер использует дуальные интерфейсы (помеченные атрибутом [dual] или [automation]) регистрация выглядит немного иначе:

Регистрация COM сервера, использующего дуальные интерфейсы

При этом вместо Proxy/Stub DLLs регистрируются библиотеки типов, регистрационные данные которых свободно копируются в 64-х ветвь реестра. В результате такой COM компонент может использоваться 64-х битными компонентами безо всяких дополнительных усилий. Конвертация 32-х битной библиотеки типов в 64-х разрядную происходит на лету.

Вывод: дуальные интерфейсы не требуют регистрации 2-х библиотек типов, однако регистрация обоих вариантов библиотеки положительно влияет на производительность.

Механизм отражения реестра достаточно корректно работает и в случаях когда регистрируются оба варианта COM сервера и сопутствующих Proxy/Stub DLL или библиотек типов.

Осталось ответить на последний вопрос – какой способ регистрации считается самым «правильным» с точки зрения взаимодействия 32-х и 64-х разрядных компонент? Ответ – приложение должно регистрировать все необходимые компоненты, включая все варианты Proxy/Stub DLLs и библиотек типов. Иными словами, приложение не должно рассчитывать на вспомогательные механизмы операционной системы, включая отражение реестра, так как их цель – обеспечение совместимости с существующими программами. Именно поэтому, кстати, я не описывал конкретных правил, в соответствии с которыми данные синхронизируются между 32-х и 64-х ветвями реестра. Конкретный набор правил, да и сам механизм отображения реестра может быть изменен или полностью убран из будущих версий Windows.

comments powered by Disqus