Выполняет ли Vista более строгую проверку идентификаторов интерфейса в вызовах DCOM?(Заглушка получила неверные данные)?

StackOverflow https://stackoverflow.com/questions/63720

  •  09-06-2019
  •  | 
  •  

Вопрос

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

Я написал и теперь поддерживаю приложение, состоящее из толстого клиента Visual Basic, говорящего на DCOM, и компонентов COM + среднего уровня, написанных на C ++ с использованием ATL.Он работает во всех восьми наших офисах.В каждом офисе размещен внутренний сервер, содержащий приложение COM + (состоящее из 18 отдельных компонентов) и SQLServer.Сервер SQLServer обычно находится на том же внутреннем сервере, но в этом нет необходимости.

Недавно мы перенесли внутренний сервер в нашем крупнейшем офисе в Нью-Йорке из кластера MSC на новую виртуальную машину, размещенную на технологии ESX от VMware.Поскольку местоположение приложения COM + переместилось со старого сервера на новый с другим именем, мне пришлось перенаправить всех клиентов, чтобы они активировали приложение COM + на новом сервере.Процедура была старой, поскольку я проделал практически то же самое для нескольких моих небольших офисов, которые прошли аналогичную модернизацию инфраструктуры.

Все казалось рутинным, и в понедельник утром весь офис - около 1000 рабочих станций с Windows XP - работал без происшествий на новом сервере.Но затем поступил звонок из моей мобильной группы - там был юрист, работающий из дома с VPN-подключением, который получал странную ошибку после перенаправления на новый сервер:

Error on FillTreeView2 - The stub received bad data.

А?Я никогда раньше не видел этого сообщения об ошибке.Это был новый сервер?Но все рабочие станции в офисе работали нормально.Я сказал мобильной группе переключить адвоката обратно на старый сервер (который все еще работал), и ошибка исчезла.Так в чем же была разница?Оказывается, этот юрист запускал Vista дома.

Мы не запускаем Vista ни в одном из наших офисов, но у нас есть несколько юристов, которые запускают Vista дома (наверняка кто-то из них работает в моем офисе в Нью-Йорке).Я тоже так делаю, и я никогда не сталкивался с этой проблемой.Чтобы подтвердить наличие проблемы, я запустил свой ноутбук Vista, указал на новый сервер и получил ту же ошибку.Я вернул его на старый сервер, и он работал нормально.Очевидно, что была какая-то проблема с Vista и компонентами на новом сервере - проблема, которая, похоже, не затронула клиентов XP.Что бы это могло быть?

Следующая остановка - журнал ошибок приложения на моем ноутбуке.Это дало больше информации об ошибке:

Source:        Microsoft-Windows-RPC-Events
Date:          9/2/2008 11:56:07 AM
Event ID:      10
Level:         Error
Computer:      DevLaptop
Description:   Application has failed to complete a COM call because an incorrect
interface ID was passed as a parameter.

The expected Interface ID was 00000555-0000-0010-8000-00aa006d2ea4, 
The Interface ID returned was 00000556-0000-0010-8000-00aa006d2ea4.

User Action - Contact the application vendor for updated version of the application.

Идентификаторы интерфейса дали мне ключ, необходимый для разгадки тайны."Ожидаемый" идентификатор интерфейса идентифицирует интерфейс набора записей MDAC - в частности, версию 2.1 этого интерфейса."Возвращенный" интерфейс соответствует более поздней версии набора записей (версия 2.5, которая отличается от версии 2.1 включением одной дополнительной записи в конце vtable - метода Save).

Действительно, интерфейсы моего компонента предоставляют множество методов, которые передают Recordset в качестве выходного параметра.Итак, они внезапно вернули более позднюю версию набора записей - с другим идентификатором интерфейса?Похоже, так оно и было на самом деле.И тогда я подумал, какое это должно иметь значение.Виртуальная таблица выглядит одинаково для клиентов с более старым интерфейсом.Действительно, я подозреваю, что если бы мы говорили о встроенном COM, а не о DCOM, это, казалось бы, безобидное несоответствие импеданса было бы молчаливо проигнорировано и не вызвало бы никаких проблем.

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

Почему я возвращал другой интерфейс в выходных параметрах из методов на моем новом сервере?

Почему это повлияло только на клиентов Vista?

Поскольку мое серверное программное обеспечение размещалось на серверах в каждом из моих восьми офисов, я решил попробовать навести свой клиент Vista на все из них последовательно, чтобы увидеть, у кого были проблемы с Vista, а у кого нет.Тест на освещение.Некоторые старые серверы все еще работали с Vista, но более новые - нет.Хотя некоторые из старых серверов все еще работали под управлением Windows 2000, в то время как более новые были 2003 года выпуска, это, похоже, не было проблемой.

После сравнения дат компонентных библиотек DLL оказалось, что всякий раз, когда клиент указывал на серверы с компонентными библиотеками DLL, датированными до 2003 года, Vista была в порядке.Но те, у которых были библиотеки DLL с датами после 2003 года, были проблематичными.Хотите верьте, хотите нет, но за многие годы не было никаких (или, по крайней мере, существенных) изменений в коде серверных компонентов.По-видимому, различия в датах были просто вызваны перекомпиляцией моих компонентов на моих машинах разработки.И оказалось, что одна из таких перекомпиляций произошла в 2003 году.

Загорелась лампочка.При передаче наборов записей обратно с сервера клиенту мои компоненты ATL C ++ ссылаются на интерфейс как _Recordset .Этот символ взят из библиотеки типов, встроенной в msado15.dll.Это строка, которая у меня была в коде C ++:

#import "c:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename ( "EOF", "adoEOF" )

Пусть вас не вводит в заблуждение число 15 в msdad15.dll.По-видимому, эта библиотека DLL не изменила имя в длинной серии версий MDAC.

Когда я в свое время компилировал приложение, версия MDAC была 2.1.Итак, _Recordset скомпилирован с идентификатором интерфейса 2.1, и это интерфейс, возвращаемый серверами, на которых запущены эти компоненты.

Все клиенты используют прокси-сервер приложения COM +, который был сгенерирован (я полагаю) еще в 1999 году.Библиотека типов, которая определяет мои интерфейсы, включает в себя строку:

importlib("msado21.tlb");

это объясняет, почему они ожидают версию 2.1 набора записей в выходных параметрах моего метода.Очевидно, проблема была в моей перекомпиляции 2003 года и в том факте, что на тот момент символ _Recordset больше не соответствовал версии 2.1.Действительно, _Recordset соответствовал версии 2.5 с ее отличным идентификатором интерфейса.Решением для меня было изменить все ссылки с _Recordset на Recordset21 в моем коде на C ++.Я перестроил компоненты и развернул их на новом сервере.Вуаля - клиенты снова казались счастливыми.

В заключение, у меня остаются два мучительных вопроса.

Почему инфраструктура прокси-сервера / заглушки, похоже, ведет себя по-разному с клиентами Vista?Похоже, что Vista проводит более строгую проверку идентификаторов интерфейса, возвращаемых из параметров метода, чем XP.

Как я должен был закодировать это по-другому еще в 1999 году, чтобы этого не произошло?Интерфейсы должны быть неизменяемыми, и когда я перекомпилировался под более новой версией MDAC, я непреднамеренно изменил свой интерфейс, потому что методы теперь возвращали другой интерфейс набора записей в качестве выходного параметра.Насколько я знаю, в библиотеке типов тогда не было символа, зависящего от версии, то есть более поздние версии библиотек типов MDAC определяют Recordset21, но этот символ не был доступен в библиотеке типов 2.1.

Это было полезно?

Решение

Когда Microsoft приняла религию безопасности, DCOM (и лежащий в ее основе RPC) привлек большое внимание, и определенно были внесены изменения для устранения дыр в безопасности, которые привели к более строгому маршалингу.Я удивлен, что вы видите это в Vista, но не в XP, но возможно, что для Vista были добавлены дополнительные проверки.В качестве альтернативы, возможно, что необязательная строгость в XP была сделана обязательной в Vista.

Хотя я недостаточно разбираюсь в MDAC, чтобы знать, могли ли вы предотвратить это, я знаю, что безопасность - одна из немногих областей, где Microsoft готова пожертвовать обратной совместимостью, так что, возможно, вы не смогли бы сделать ничего "лучше" еще в 1999 году.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top