64 bit COM Server
От: Ичетник  
Дата: 20.04.06 13:10
Оценка:
Вопрос такой. Есть 32 — битное приложение, которое запускается на 64 битной Windows. Сможет ли оно пользоваться 64 битными COM объектами?

Я подозреваю что нет. Но не могу найти однозначного ответа.
Re: 64 bit COM Server
От: Ivan Россия www.rsdn.ru
Дата: 20.04.06 16:45
Оценка:
Здравствуйте, Ичетник, Вы писали:

И>Вопрос такой. Есть 32 — битное приложение, которое запускается на 64 битной Windows. Сможет ли оно пользоваться 64 битными COM объектами?


И>Я подозреваю что нет. Но не могу найти однозначного ответа.

сможет, если:
— это внепроцессный exe сервер
— если сконфигурировать in-process сервер запускаться в суррогатном процессе через dllhost.exe
Re[2]: 64 bit COM Server
От: Ичетник  
Дата: 23.04.06 19:42
Оценка:
Здравствуйте, Ivan, Вы писали:

I>- если сконфигурировать in-process сервер запускаться в суррогатном процессе через dllhost.exe


Насчет этого пункта. Разъясните чайнику. Как это сделать.
Re[3]: 64 bit COM Server
От: Ivan Россия www.rsdn.ru
Дата: 24.04.06 07:00
Оценка:
Здравствуйте, Ичетник, Вы писали:

И>Насчет этого пункта. Разъясните чайнику. Как это сделать.


— зарегистрировать 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 — предпочтение будет отдано в зависимости от битности клиента и т.п.
Re[2]: 64 bit COM Server
От: Ичетник  
Дата: 24.04.06 07:23
Оценка:
Разобрался... Устанавливать объект надо для обеих областей реестра.
Re[3]: 64 bit COM Server
От: Ivan Россия www.rsdn.ru
Дата: 24.04.06 07:29
Оценка:
Здравствуйте, Ичетник, Вы писали:

И>Разобрался... Устанавливать объект надо для обеих областей реестра.

это не даст возможности x86 клиенту использовать x64 ком сервер. скорее будет возможность одновременно использовать две версии компонента x86/x64 для разных клиентов.

для x86 клиента при такой регистрации будет использована x86 версия компонента, т.к. в 32-битный процесс не может быть загружена 64-битная dll.
Re[4]: 64 bit COM Server
От: Ivan Россия www.rsdn.ru
Дата: 24.04.06 16:52
Оценка: 1 (1)
Здравствуйте, Ivan, Вы писали:

вот кстати, полезная ссылка —
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/html/dcb82ff2-56e4-4c7e-a621-7ffd0f1a9d8e.asp

там есть таблица, объясняющая в каких случаях какой сервер будет запущен, но при несовпадении битности клиента и сервера в любом случае нужно использовать DllSurrogate для in-proc серверов — так как в процесс не может быть загружена dll с другой битностью
Re[5]: 64 bit COM Server
От: Lonely Dog Россия  
Дата: 14.08.08 14:50
Оценка:
Здравствуйте, 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.
Re[6]: 64 bit COM Server
От: Ivan Россия www.rsdn.ru
Дата: 14.08.08 15:35
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>У меня почти такая же проблема, только у меня 64-битный клиент и 32-битный сервер.

LD>Я зарегил сервер в обоих реестрах. (32-бита и 64 бита)

с этого места поподробнее. как удалось 32-битный сервер зарегистрировать в native (x64) ветке реестра ?
Re[7]: 64 bit COM Server
От: Lonely Dog Россия  
Дата: 15.08.08 07:03
Оценка:
Здравствуйте, Ivan, Вы писали:

I>с этого места поподробнее. как удалось 32-битный сервер зарегистрировать в native (x64) ветке реестра ?

Пошел в 32-битную ветку реестра, сделал export to file. Потом в файле поменял HKLM\Software\SysWow64 (или как там это называется)\Classes на HKLM\Software\Clasesses и сделал импорт. Получил регистрацию в двух местах.
Re[8]: 64 bit COM Server
От: Ivan Россия www.rsdn.ru
Дата: 15.08.08 10:44
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>Пошел в 32-битную ветку реестра, сделал export to file. Потом в файле поменял HKLM\Software\SysWow64 (или как там это называется)\Classes на HKLM\Software\Clasesses и сделал импорт. Получил регистрацию в двух местах.


в этом нет необходимости, в результате такой "ручной" регистрации как раз и создается ситуация, когда в native части реестра находится ссылка на x86 модуль, который не может быть загружен в native процесс.

Достаточно зарегистрировать x86 сервер с помощью regsvr32 и добавить в AppID значение DllSurrogate.
Re[9]: 64 bit COM Server
От: Lonely Dog Россия  
Дата: 15.08.08 10:58
Оценка:
Здравствуйте, Ivan, Вы писали:


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.

Код создания объекта такой:
  CoInitialize(NULL);
  DLLSrvLib::ITestPtr sp;
  HRESULT hr;
  CComPtr<IClassFactory> spClsFac;
  hr = CoGetClassObject(__uuidof(DLLSrvLib::Test), CLSCTX_ALL, NULL, IID_IClassFactory, (PVOID*)&spClsFac);
  if (FAILED(hr))
  {
    printf("CoGetClassObject failed. 0x%x\n", hr);
    hr = CoGetClassObject(__uuidof(DLLSrvLib::Test), CLSCTX_LOCAL_SERVER, NULL, IID_IClassFactory, (PVOID*)&spClsFac);
    if (FAILED(hr))
    {
      printf("CoGetClassObject failed. 0x%x\n", hr);
      return -1;
    }
  }
  printf("After CoGetClassObject\n");
  CComPtr<IUnknown> spUnk;
  hr = spClsFac->CreateInstance(NULL, IID_IUnknown, (PVOID*)&spUnk);
  if (FAILED(hr))
  {
    printf("CreateInstance1 failed. 0x%x\n", hr);
    return -2;
  }
  printf("After CreateInstance1\n");
  hr = spUnk->QueryInterface(__uuidof(DLLSrvLib::ITest), (PVOID*)&sp);
  if (FAILED(hr))
  {
    printf("CreateInstance2 failed. 0x%x\n", hr);
    return -2;
  }
  printf("After CreateInstance2\n");
  // Дальше испольуем полученный интерфейс.


Оба вызова CoGetClassObject завершаются не удачно.

В чем может быть дело?

Заранее спасибо.
Re[6]: 64 bit COM Server
От: Lonely Dog Россия  
Дата: 15.08.08 13:30
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>У меня почти такая же проблема, только у меня 64-битный клиент и 32-битный сервер.

Решил поискать в инете реализации сурогатных процессов. Думал, найду такую реализацию и пропишу в реестре. Может быть смогу ее по отлаживать и что-нибудь увижу.

Нашел суррогат из книжки про DCOM: http://www.cs.odu.edu/~wild/cs477/Spring99/Programs/DCOM/DLLSurrogate/
Собрал как win32 приложение под 2003 студией и прописал для своего 32-битного компонента в качестве суррогата.
Все заработало. правда только после регистрации его в обоих ветках реестра. Действительно, если в 64-битной ветке ничего не будет, как CoCreateInstance узнает, где искать сервер. Она что, сама полезет в 32-битный реестр?

Далее, я решил проверить, а будет ли работать стандартный суррогат. Оказалось, что он все-таки не работает.

В чем дело, понять не могу. Т.е., с моей версией из книги все OK, а со стандартным проблемы. Ессно, я не могу плюнуть на это и использовать самописный сурогат. Считаю, это не выход.

Заранее спасибо за помощь.
Re[10]: 64 bit COM Server
От: Ivan Россия www.rsdn.ru
Дата: 15.08.08 14:34
Оценка: 1 (1)
Здравствуйте, Lonely Dog, Вы писали:

LD>В чем может быть дело?

LD>Заранее спасибо.

вот так должно сработать:
hr = CoGetClassObject(__uuidof(DLLSrvLib::Test), CLSCTX_ALL | CLSCTX_ACTIVATE_32_BIT_SERVER, NULL, IID_IClassFactory, (PVOID*)&spClsFac);
Re[7]: 64 bit COM Server
От: Ivan Россия www.rsdn.ru
Дата: 15.08.08 14:43
Оценка: 13 (2)
Здравствуйте, 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.

Re[11]: 64 bit COM Server
От: Ivan Россия www.rsdn.ru
Дата: 15.08.08 14:45
Оценка: 13 (2)
Здравствуйте, Ivan, Вы писали:

I>Здравствуйте, Lonely Dog, Вы писали:


LD>>В чем может быть дело?

LD>>Заранее спасибо.

I>вот так должно сработать:

I>
I>hr = CoGetClassObject(__uuidof(DLLSrvLib::Test), CLSCTX_ALL | CLSCTX_ACTIVATE_32_BIT_SERVER, NULL, IID_IClassFactory, (PVOID*)&spClsFac);
I>


да, и еще — DllSurrogate надо устанавливать в HKCR\wow6432node\AppId, а не HKCR\AppID.
интересный эффект, что одновременно в двух ветках это значение установить нельзя — при установке в одной ветке, в другой — актоматически удаляется. но это и правильно — иначе была бы неодназначность при активации CLSCTX_LOCAL_SERVER какой сервер активировать — x86 или x64
Re[12]: 64 bit COM Server
От: Lonely Dog Россия  
Дата: 18.08.08 13:15
Оценка:
Здравствуйте, Ivan, Вы писали:

I>да, и еще — DllSurrogate надо устанавливать в HKCR\wow6432node\AppId, а не HKCR\AppID.

I>интересный эффект, что одновременно в двух ветках это значение установить нельзя — при установке в одной ветке, в другой — актоматически удаляется. но это и правильно — иначе была бы неодназначность при активации CLSCTX_LOCAL_SERVER какой сервер активировать — x86 или x64
После того, как зарегил в правильном месте, все заработало.
Спасибо.
Re[13]: 64 bit COM Server
От: Lonely Dog Россия  
Дата: 18.08.08 14:50
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>После того, как зарегил в правильном месте, все заработало.

LD>Спасибо.

Иван, есть еще один маленький вопрос.
Пытаюсь создать через CoCreateInstance экземпляр 32-битного сервера в 64-битном фильтре паролей. Фильтр представляет из себя DLL, загружаемую процессом lsass.exe на ранних стадиях загрузки машины. При старте фильтр создает 32-битный объект и получает ошибку RPC server is unavailable. Через какое-то время он снова пытается его создать и все получается. В чем может быть дело? Возможно, надо дождаться какого-нибудь сервиса?
Спасибо.
Re[14]: 64 bit COM Server
От: Lonely Dog Россия  
Дата: 18.08.08 15:14
Оценка:
Здравствуйте, 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 не нужен, завтра буду проверять.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.