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

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

Я написал и теперь поддерживаю приложение, которое состоит из толстого клиента 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 этого интерфейса. «Возвращенный» интерфейс соответствует более поздней версии Recordset (версия 2.5, которая отличается от версии 2.1 включением одной дополнительной записи в конце vtable - метода Save).

Действительно, интерфейсы моего компонента предоставляют множество методов, которые передают Recordset в качестве выходного параметра. Неужели они внезапно вернули более позднюю версию Recordset - с другим идентификатором интерфейса? Оказалось, что так оно и есть. А потом я подумал, какое это имеет значение. Таблица vtable выглядит одинаково для клиентов старого интерфейса. В самом деле, я подозреваю, что если бы мы говорили о внутрипроцессном 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 Recordset в выходных параметрах моего метода. Очевидно, проблема была в моей перекомпиляции 2003 года и в том факте, что в то время символ _Recordset больше не соответствовал версии 2.1. Действительно, _Recordset соответствовал версии 2.5 с отдельным идентификатором интерфейса. Решением для меня было изменить все ссылки с _Recordset на Recordset21 в моем коде C ++. Я восстановил компоненты и развернул их на новом сервере. Вуаля - клиенты снова казались счастливыми.

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

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

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


person Howard Pinsley    schedule 15.09.2008    source источник


Ответы (1)


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

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

person Bruce    schedule 18.09.2008