5 Stimmen

Überprüft Vista die Schnittstellen-IDs bei DCOM-Aufrufen strenger (der Stub hat ungültige Daten erhalten)?

Ich hoffe, jeder wird mir die Länge und die erzählerische Form dieser Frage verzeihen. Ich habe mich entschieden, die Situation ausführlich in meinem Blog zu beschreiben. Später habe ich Joel's Einladung zu dieser Seite gesehen und dachte, ich würde es hier einfügen, um zu sehen, ob jemand Einblick in die Situation hat.

Ich habe eine Anwendung entwickelt, die aus einem Visual Basic Thick Client besteht, der DCOM mit Mittelschicht-COM+ Komponenten spricht, die in C++ mit ATL geschrieben sind. Es läuft in all unseren acht Büros. Jedes Büro beherbergt einen Backend-Server, der die COM+ Anwendung (bestehend aus 18 separaten Komponenten) und den SQLServer enthält. Der SQLServer befindet sich normalerweise auf demselben Backend-Server, muss aber nicht.

Vor Kurzem haben wir den Backend-Server in unserem größten Büro -- New York -- von einem MSC Cluster auf eine neue virtuelle Maschine umgestellt, die auf der VMWare-Technologie ESX gehostet wird. Da sich der Speicherort der COM+ Anwendung vom alten Server auf einen neuen mit einem anderen Namen verschoben hatte, musste ich alle Clients umleiten, um die COM+ Anwendung auf dem neuen Server zu aktivieren. Das Verfahren war altbekannt, da ich im Grunde dasselbe bereits für mehrere meiner kleineren Büros gemacht hatte, die ähnliche Infrastruktur-Upgrades durchlaufen hatten.

Alles schien routinemäßig zu sein und am Montagmorgen lief das gesamte Büro -- etwa 1.000 Windows XP Workstations -- ohne Zwischenfälle auf dem neuen Server. Aber dann kam der Anruf von meiner Mobilgruppe -- es gab einen Anwalt, der von zu Hause aus mit einer VPN-Verbindung arbeitete und nach der Umleitung auf den neuen Server einen seltsamen Fehler erhielt:

Fehler bei FillTreeView2 - Die Stumpfe erhielt falsche Daten.

Hä? Ich hatte diese Fehlermeldung noch nie gesehen. Lag es am neuen Server? Aber alle Workstations im Büro funktionierten einwandfrei. Ich sagte der Mobilgruppe, den Anwalt wieder zurück auf den alten Server zu schalten (der immer noch aktiv war), und der Fehler war verschwunden. Also, wo lag der Unterschied? Es stellte sich heraus, dass dieser Anwalt zu Hause Vista verwendet hat.

Wir verwenden Vista in keinem unserer Büros, aber wir haben einige Anwälte, die zu Hause Vista nutzen (sicherlich einige in meinem New Yorker Büro). Ich auch, und ich habe dieses Problem noch nie gesehen. Um zu bestätigen, dass es ein Problem gab, startete ich meinen Vista-Laptop, wies ihn auf den neuen Server hin und erhielt den gleichen Fehler. Ich wies ihn zurück auf den alten Server, und es funktionierte einwandfrei. Offensichtlich gab es ein Problem mit Vista und den Komponenten auf dem neuen Server -- ein Problem, das offenbar keine Auswirkungen auf XP-Clients zu haben schien. Was könnte es sein?

Nächster Stopp -- das Applikationsfehlerprotokoll auf meinem Laptop. Dies ergab weitere Informationen zum Fehler:

Quelle:        Microsoft-Windows-RPC-Ereignisse
Datum:         02.09.2008 11:56:07 Uhr
Ereignis-ID:   10
Ebene:         Fehler
Computer:      DevLaptop
Beschreibung:  Die Anwendung konnte einen COM-Aufruf nicht abschließen, da eine falsche
Schnittstellen-ID als Parameter übergeben wurde.

Die erwartete Schnittstellen-ID war 00000555-0000-0010-8000-00aa006d2ea4, 
Die zurückgegebene Schnittstellen-ID war 00000556-0000-0010-8000-00aa006d2ea4.

Benutzeraktion - Kontaktieren Sie den Anbieter der Anwendung für eine aktualisierte Version der Anwendung.

Die Schnittstellen-IDs gaben mir den Hinweis, den ich brauchte, um das Rätsel zu lösen. Die "erwartete" Schnittstellen-ID identifiziert die Recordset-Schnittstelle des MDAC -- speziell die Version 2.1 dieser Schnittstelle. Die "zurückgegebene" Schnittstellen-ID entspricht einer späteren Version von Recordset (Version 2.5, die sich von Version 2.1 durch die Hinzufügung eines zusätzlichen Eintrags am Ende der Vtable -- Method Save -- unterscheidet).

Tatsächlich haben meine Komponentenschnittstellen viele Methoden freigelegt, die Recordset als Ausgabeparameter übergeben. Gaben sie also plötzlich eine spätere Version von Recordset zurück -- mit einer anderen Schnittstellen-ID? Es schien sicherlich der Fall zu sein. Und dann dachte ich, warum sollte es wichtig sein. Die Vtable sieht für Clients der älteren Schnittstelle gleich aus. Tatsächlich vermute ich, dass, wenn wir über in-process-COM sprechen würden und nicht über DCOM, diese scheinbar belanglose Impedanzanpassung stillschweigend ignoriert worden und keine Probleme verursacht hätte.

Natürlich, wenn Prozess- und Maschinengrenzen ins Spiel kommen, gibt es ein Proxy und einen Stub zwischen Client und Server. In diesem Fall habe ich Typbibliothekenmarshaling mit dem freigegebenen Thread-Marshaller verwendet. Es gab also zwei Rätsel zu lösen:

Warum gab ich von den Methoden auf meinem neuen Server verschiedene Schnittstellen in den Ausgabeparametern zurück?

Warum hat das nur Vista-Clients betroffen?

Da meine Server-Software auf Servern in jedem meiner acht Büros gehostet wurde, entschied ich mich, meinen Vista-Client nacheinander auf alle zu richten, um zu sehen, welche Probleme mit Vista hatten und welche nicht. Eine aufschlussreiche Test. Einige der älteren Server funktionierten noch mit Vista, während die neueren das nicht taten. Obwohl einige der älteren Server immer noch mit Windows 2000 liefen, während die neueren auf 2003 waren, schien das nicht das Problem zu sein.

Nach Vergleich der Datumsangaben der Komponenten-DLLs schien es, dass, wann immer der Client auf Server zeigte, deren Komponenten-DLLs vor 2003 datiert waren, Vista in Ordnung war. Aber diejenigen, die DLLs mit Daten nach 2003 hatten, waren problematisch. Glauben Sie es oder nicht, es gab keine (oder zumindest keine wesentlichen) Änderungen am Code auf den Serverkomponenten seit vielen Jahren. Offenbar waren die unterschiedlichen Daten einfach auf Neuübersetzungen meiner Komponenten auf meinen Entwicklungsrechnern zurückzuführen. Und es schien, dass eine dieser Neuübersetzungen 2003 stattfand.

Der Groschen fiel. Beim Zurückgeben von Recordsets vom Server an den Client verwenden meine ATL C++-Komponenten die Schnittstelle _Recordset. Dieses Symbol stammt aus der in msado15.dll eingebetteten Typbibliothek. Das war die Zeile im C++-Code, die ich hatte:

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

Lassen Sie sich nicht von der 15 in msdad15.dll täuschen. Anscheinend hat sich der Name dieser DLL in der langen Serie von MDAC-Versionen nicht geändert.

Als ich die Anwendung damals kompiliert habe, war die Version von MDAC 2.1. Also wurde _Recordset mit der 2.1-Schnittstellen-ID kompiliert und das ist die Schnittstelle, die von den Servern zurückgegeben wird, die diese Komponenten ausführen.

Alle Clients verwenden den COM+ Anwendungsproxy, der (ich glaube) 1999 generiert wurde. Die Typbibliothek, die meine Schnittstellen definiert, enthält die Zeile:

importlib("msado21.tlb");

was erklärt, warum sie eine Version 2.1 von Recordset in den Ausgabeparametern meiner Methoden erwarten. Offensichtlich lag das Problem an meiner Neuübersetzung von 2003 und daran, dass zu diesem Zeitpunkt das Symbol _Recordset nicht mehr der 2.1-Version entsprach. Tatsächlich entsprach _Recordset der 2.5-Version mit ihrer eigenen Schnittstellen-ID. Die Lösung für mich war, alle Verweise von _Recordset in Recordset21 in meinem C++-Code zu ändern. Ich habe die Komponenten neu erstellt und auf den neuen Server bereitgestellt. Voilà -- die Clients schienen wieder zufrieden zu sein.

Zusammenfassend bleiben für mich zwei quälende Fragen.

Warum scheint die Proxy/Stub-Infrastruktur sich mit Vista-Clients anders zu verhalten? Es scheint, dass Vista strengere Überprüfungen der Schnittstellen-IDs vornimmt, die von den Methodenparametern zurückkommen als XP.

Wie hätte ich das damals 1999 anders codieren sollen, damit dies nicht passiert wäre? Schnittstellen sollen unveränderlich sein und als ich unter einer neueren Version von MDAC neu übersetzt habe, habe ich unbeabsichtigt meine Schnittstelle geändert, weil die Methoden jetzt eine andere Recordset-Schnittstelle als Ausgabeparameter zurückgeben haben. Soweit ich weiß, hatte die Typbibliothek damals kein versionspezifisches Symbol -- das heißt, spätere Versionen der MDAC-Typbibliotheken definieren Recordset21, aber dieses Symbol war damals nicht in der 2.1-Typbibliothek verfügbar.

2voto

Bruce Punkte 7824

Als Microsoft die Sicherheitsreligion annahm, erhielt DCOM (und das zugrunde liegende RPC) viel Aufmerksamkeit, und es wurden definitiv Änderungen vorgenommen, um Sicherheitslücken zu schließen, die zu strengerem Marshalling führten. Ich bin überrascht, dass du das in Vista siehst, aber nicht in XP, aber es ist möglich, dass zusätzliche Überprüfungen für Vista hinzugefügt wurden. Alternativ ist es möglich, dass die optionale Strenge in XP in Vista obligatorisch wurde.

Obwohl ich nicht genug über MDAC weiß, um zu wissen, ob du dies hättest verhindern können, weiß ich, dass Sicherheit eines der wenigen Bereiche ist, in denen Microsoft ziemlich bereit ist, die Abwärtskompatibilität zu opfern. Es ist also möglich, dass du damals 1999 nichts "Besseres" hättest tun können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X