Регистрация COM объектов. Часть II. 64-х разрядная специфика
Apr 18, 2007 · CommentsCOMПрограммированиеWindowsWow64
Итак, продолжаем начатое в первой части. 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-х разрядных приложений этого не делают и продолжают нормально работать. В чем же дело? Причина в том, что:
-
Это правило касается только out-of-proc COM компонент;
-
Либо все клиенты данного COM сервера имеют одинаковую с ним разрядность;
-
Либо COM сервер использует интерфейсы, помеченные атрибутом [dual] или [automation].
В остальных случаях без регистрации двух Proxy/Stub DLL не обойтись.
Помимо перенаправления реестра, о котором я говорил выше, wow64 также реализует второй механизм, которой называется отражение реестра (registry reflection).
Нужно сказать, что эти два механизма путают все кому не лень. Каждый раз когда приходит письмо с вопросом об одном их них, приходится догадываться что именно имел ввиду спрашивающий. Неудачное название, в общем. :-)
Отражение реестра заключается в синхронизации некоторых из перенаправляемых ветвей реестра по определённым правилам. Этот механизм не что иное, как способ обеспечить совместимость существующих 32-х битных COM компонент с 64-х разрядных окружением. Каким образом? А вот каким. Посмотрим что происходит при регистрации 32-х битного COM компонента на 64-х разрядной системе.
В случае, если сервер использует raw интерфейсы и собственную Proxy/Stub DLL в реестре регистрируется:
-
Сам COM компонент;
-
Его интерфейсы;
-
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]) регистрация выглядит немного иначе:
При этом вместо Proxy/Stub DLLs регистрируются библиотеки типов, регистрационные данные которых свободно копируются в 64-х ветвь реестра. В результате такой COM компонент может использоваться 64-х битными компонентами безо всяких дополнительных усилий. Конвертация 32-х битной библиотеки типов в 64-х разрядную происходит на лету.
Вывод: дуальные интерфейсы не требуют регистрации 2-х библиотек типов, однако регистрация обоих вариантов библиотеки положительно влияет на производительность.
Механизм отражения реестра достаточно корректно работает и в случаях когда регистрируются оба варианта COM сервера и сопутствующих Proxy/Stub DLL или библиотек типов.
Осталось ответить на последний вопрос – какой способ регистрации считается самым «правильным» с точки зрения взаимодействия 32-х и 64-х разрядных компонент? Ответ – приложение должно регистрировать все необходимые компоненты, включая все варианты Proxy/Stub DLLs и библиотек типов. Иными словами, приложение не должно рассчитывать на вспомогательные механизмы операционной системы, включая отражение реестра, так как их цель – обеспечение совместимости с существующими программами. Именно поэтому, кстати, я не описывал конкретных правил, в соответствии с которыми данные синхронизируются между 32-х и 64-х ветвями реестра. Конкретный набор правил, да и сам механизм отображения реестра может быть изменен или полностью убран из будущих версий Windows.