Здравствуйте, Ичетник, Вы писали:
И>Вопрос такой. Есть 32 — битное приложение, которое запускается на 64 битной Windows. Сможет ли оно пользоваться 64 битными COM объектами?
И>Я подозреваю что нет. Но не могу найти однозначного ответа.
сможет, если:
— это внепроцессный exe сервер
— если сконфигурировать in-process сервер запускаться в суррогатном процессе через dllhost.exe
Здравствуйте, Ичетник, Вы писали:
И>Насчет этого пункта. Разъясните чайнику. Как это сделать.
— зарегистрировать x64 версию COM сервера (regsvr32 из папки system32). для inproc компонентов в реестре могут одновременно быть зарегистированы и x64 и x86 версии. в данном случае x86 версию регистрировать не нужно.
— в ключе HKCR\Appid\{APPID} создать строковое значение DllSurrogate = "" ({APPID} — это AppID сервера)
— клиент должен допускать создание компонента только в контексте CLSTX_LOCAL_SERVER (т.е. в CoCreateInstance нужно передавать CLSTX_LOCAL_SERVER).
в результате COM сервер будет загружаться в суррогтный 64-битный процесс dllhost
подробнее — см. MSDN по ключевому слову DllSurrogate
P.S. при создании экзмепляра в CoCreateInstance при наличии нескольких вариантов создания инфраструктура COM будет выбирать наиболее близкий к клиенту контекст — т.е inproc/outproc — предпочтение отдается inproc, x86/x64 — предпочтение будет отдано в зависимости от битности клиента и т.п.
Здравствуйте, Ичетник, Вы писали:
И>Разобрался... Устанавливать объект надо для обеих областей реестра.
это не даст возможности x86 клиенту использовать x64 ком сервер. скорее будет возможность одновременно использовать две версии компонента x86/x64 для разных клиентов.
для x86 клиента при такой регистрации будет использована x86 версия компонента, т.к. в 32-битный процесс не может быть загружена 64-битная dll.
там есть таблица, объясняющая в каких случаях какой сервер будет запущен, но при несовпадении битности клиента и сервера в любом случае нужно использовать DllSurrogate для in-proc серверов — так как в процесс не может быть загружена dll с другой битностью
Здравствуйте, Ivan, Вы писали:
I>Здравствуйте, Ivan, Вы писали:
I>вот кстати, полезная ссылка — I>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/html/dcb82ff2-56e4-4c7e-a621-7ffd0f1a9d8e.asp
I>там есть таблица, объясняющая в каких случаях какой сервер будет запущен, но при несовпадении битности клиента и сервера в любом случае нужно использовать DllSurrogate для in-proc серверов — так как в процесс не может быть загружена dll с другой битностью
Добрый день!
У меня почти такая же проблема, только у меня 64-битный клиент и 32-битный сервер.
Я зарегил сервер в обоих реестрах. (32-бита и 64 бита)
В AppId прописал DllSurrogate с пустым значением.
Вызов CoGetClassObject с CLSCTX_ALL из 64-битного клиента возвращает Class not registered.
Вызов CoGetClassObject с CLSCTX_LOCAL_SERVER возвращает левый код, смысл которого в том, что указанное приложение не является приложением win32. Видимо дело в том, что винда пытается загрузить 64-битный dllhost.
Явное прописывание dllhost из SysWow64 (т.е. 32-битного dllhost) или создание параметра PreferredServerBitnnes со значением 2 приводят к тому, что CoGetClassObject долго чего-то ждет, а потом завершается с кодом 0x80080005, т.е. Server execution failed. В журнале событий появляется сообщение о том, что сервер не вызвал CoRegisterClassObject.
Что я не так делаю?
PS: Тестирую в Windows 2003 R2 Enterprise SP2 x64.
Здравствуйте, Lonely Dog, Вы писали:
LD>У меня почти такая же проблема, только у меня 64-битный клиент и 32-битный сервер. LD>Я зарегил сервер в обоих реестрах. (32-бита и 64 бита)
с этого места поподробнее. как удалось 32-битный сервер зарегистрировать в native (x64) ветке реестра ?
Здравствуйте, Ivan, Вы писали:
I>с этого места поподробнее. как удалось 32-битный сервер зарегистрировать в native (x64) ветке реестра ?
Пошел в 32-битную ветку реестра, сделал export to file. Потом в файле поменял HKLM\Software\SysWow64 (или как там это называется)\Classes на HKLM\Software\Clasesses и сделал импорт. Получил регистрацию в двух местах.
Здравствуйте, Lonely Dog, Вы писали:
LD>Пошел в 32-битную ветку реестра, сделал export to file. Потом в файле поменял HKLM\Software\SysWow64 (или как там это называется)\Classes на HKLM\Software\Clasesses и сделал импорт. Получил регистрацию в двух местах.
в этом нет необходимости, в результате такой "ручной" регистрации как раз и создается ситуация, когда в native части реестра находится ссылка на x86 модуль, который не может быть загружен в native процесс.
Достаточно зарегистрировать x86 сервер с помощью regsvr32 и добавить в AppID значение DllSurrogate.
I>Достаточно зарегистрировать x86 сервер с помощью regsvr32 и добавить в AppID значение DllSurrogate.
Я сделал следующее:
1. Есть DllSrv.dll — 32-битный модуль, реализующий простой in-proc com server.
2. Есть TestProj.exe — 64-битный клиент, использующий DllSrv.dll
3. Есть TestProj32.exe — 32-битный клиент, использующий DllSrv.dll
4. Я запустил regsvr32 dllsrv.dll. Он прописался в Wow6432Node\Classes.
5. Запустил regedit.exe и прописал в AppId для DllSrv пустой REG_SZ параметр DllSurrogate.
6. testProj32 отрабатывает успешно.
7. testProj выдает ошибку 0x80040154.
Здравствуйте, Lonely Dog, Вы писали:
LD>У меня почти такая же проблема, только у меня 64-битный клиент и 32-битный сервер.
Решил поискать в инете реализации сурогатных процессов. Думал, найду такую реализацию и пропишу в реестре. Может быть смогу ее по отлаживать и что-нибудь увижу.
Нашел суррогат из книжки про DCOM: http://www.cs.odu.edu/~wild/cs477/Spring99/Programs/DCOM/DLLSurrogate/
Собрал как win32 приложение под 2003 студией и прописал для своего 32-битного компонента в качестве суррогата.
Все заработало. правда только после регистрации его в обоих ветках реестра. Действительно, если в 64-битной ветке ничего не будет, как CoCreateInstance узнает, где искать сервер. Она что, сама полезет в 32-битный реестр?
Далее, я решил проверить, а будет ли работать стандартный суррогат. Оказалось, что он все-таки не работает.
В чем дело, понять не могу. Т.е., с моей версией из книги все OK, а со стандартным проблемы. Ессно, я не могу плюнуть на это и использовать самописный сурогат. Считаю, это не выход.
Здравствуйте, Lonely Dog, Вы писали:
LD>Все заработало. правда только после регистрации его в обоих ветках реестра. Действительно, если в 64-битной ветке ничего не будет, как CoCreateInstance узнает, где искать сервер. Она что, сама полезет в 32-битный реестр?
для того, чтобы COM нормально работал на x64 платформе между native и wow64 ветками реестра существует взаимосвязь.
например, внепроцессные серверы синхронизируются, т.е. нельзя иметь одновременно x86 и x64 внепроцессный сервер
еще один пример — значение DllSurrogate, нельзя установить одновременно в AppID для native и wow64 веток. при установке его в одной ветке — в другой будет автотматически удаляться.
для in-process серверов все еще немного хитрее — при регистрации в wow64 ветке, некоторые значения автоматически создаются в native.
со стороны инфраструктуры COM есть новые флаги, позволяющие контролировать процесс активации. в частности:
CLSCTX_ACTIVATE_32_BIT_SERVER
Activate or connect to a 32-bit version of the server; fail if one is not registered.
CLSCTX_ACTIVATE_64_BIT_SERVER
Activate or connect to a 64 bit version of the server; fail if one is not registered.
да, и еще — DllSurrogate надо устанавливать в HKCR\wow6432node\AppId, а не HKCR\AppID.
интересный эффект, что одновременно в двух ветках это значение установить нельзя — при установке в одной ветке, в другой — актоматически удаляется. но это и правильно — иначе была бы неодназначность при активации CLSCTX_LOCAL_SERVER какой сервер активировать — x86 или x64
Здравствуйте, Ivan, Вы писали:
I>да, и еще — DllSurrogate надо устанавливать в HKCR\wow6432node\AppId, а не HKCR\AppID. I>интересный эффект, что одновременно в двух ветках это значение установить нельзя — при установке в одной ветке, в другой — актоматически удаляется. но это и правильно — иначе была бы неодназначность при активации CLSCTX_LOCAL_SERVER какой сервер активировать — x86 или x64
После того, как зарегил в правильном месте, все заработало.
Спасибо.
Здравствуйте, Lonely Dog, Вы писали:
LD>После того, как зарегил в правильном месте, все заработало. LD>Спасибо.
Иван, есть еще один маленький вопрос.
Пытаюсь создать через CoCreateInstance экземпляр 32-битного сервера в 64-битном фильтре паролей. Фильтр представляет из себя DLL, загружаемую процессом lsass.exe на ранних стадиях загрузки машины. При старте фильтр создает 32-битный объект и получает ошибку RPC server is unavailable. Через какое-то время он снова пытается его создать и все получается. В чем может быть дело? Возможно, надо дождаться какого-нибудь сервиса?
Спасибо.
Здравствуйте, Lonely Dog, Вы писали:
LD>Здравствуйте, Lonely Dog, Вы писали:
LD>>После того, как зарегил в правильном месте, все заработало. LD>>Спасибо.
LD>Иван, есть еще один маленький вопрос. LD>Пытаюсь создать через CoCreateInstance экземпляр 32-битного сервера в 64-битном фильтре паролей. Фильтр представляет из себя DLL, загружаемую процессом lsass.exe на ранних стадиях загрузки машины. При старте фильтр создает 32-битный объект и получает ошибку RPC server is unavailable. Через какое-то время он снова пытается его создать и все получается. В чем может быть дело? Возможно, надо дождаться какого-нибудь сервиса? LD>Спасибо.
Вроде уже сам нашел.
Ожидание RpcLocator, RpcSS, DComLaunch спасает.
Возможно RpcLocator не нужен, завтра буду проверять.