¿Vista realiza una verificación más estricta de los ID de interfaz en las llamadas DCOM?(El fragmento ha recibido datos incorrectos)?

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

  •  09-06-2019
  •  | 
  •  

Pregunta

Espero que todos perdonen la extensión y la forma narrativa de esta pregunta.Decidí describir la situación con cierto detalle en mi blog.Más tarde vi la invitación de Joel a este sitio y pensé en pegarla aquí para ver si alguien tiene alguna idea de la situación.

Escribí, y ahora soporte, una aplicación que consiste en un cliente pesado de Visual Basic que habla DCOM con componentes COM+ de nivel medio escritos en C++ usando ATL.Funciona en nuestras ocho oficinas.Cada oficina alberga un servidor back-end que contiene la aplicación COM+ (que consta de 18 componentes separados) y SQLServer.El SQLServer suele estar en el mismo servidor back-end, pero no es necesario que lo esté.

Recientemente, migramos el servidor back-end de nuestra oficina más grande, Nueva York, de un clúster MSC a una nueva máquina virtual alojada en la tecnología ESX de VMWare.Dado que la ubicación de la aplicación COM+ se había movido del servidor antiguo a uno nuevo con un nombre diferente, tuve que redirigir a todos los clientes para que activaran la aplicación COM+ en el nuevo servidor.El procedimiento era antiguo, ya que había hecho esencialmente lo mismo en varias de mis oficinas más pequeñas que habían pasado por mejoras de infraestructura similares.

Todo parecía rutina y el lunes por la mañana toda la oficina (alrededor de 1.000 estaciones de trabajo con Windows XP) funcionaba sin incidentes en el nuevo servidor.Pero entonces llegó la llamada de mi grupo móvil: había un abogado que trabajaba desde casa con una conexión VPN y recibía un error extraño después de ser redirigido al nuevo servidor:

Error on FillTreeView2 - The stub received bad data.

¿Eh?Nunca antes había visto este mensaje de error.¿Fue el nuevo servidor?Pero todas las estaciones de trabajo de la oficina funcionaban bien.Le dije al grupo móvil que volviera a cambiar el abogado al servidor anterior (que todavía estaba activo) y el error desapareció.Entonces ¿cuál fue la diferencia?Resulta que este abogado manejaba Vista en casa.

No manejamos Vista en ninguna de nuestras oficinas, pero tenemos algunos abogados que manejan Vista en casa (ciertamente algunos en mi oficina de Nueva York).Yo también lo hago y nunca he visto este problema.Para confirmar que había un problema, encendí mi computadora portátil Vista, la apunté al nuevo servidor y obtuve el mismo error.Lo señalé al servidor anterior y funcionó bien.Claramente había algún problema con Vista y los componentes del nuevo servidor, un problema que no parecía afectar a los clientes XP.¿Qué podría ser?

Siguiente parada: el registro de errores de la aplicación en mi computadora portátil.Esto arrojó más información sobre el error:

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.

Los identificadores de la interfaz me proporcionaron la pista que necesitaba para desentrañar el misterio.La identificación de la interfaz "esperada" identifica la interfaz Recordset de MDAC, específicamente la versión 2.1 de esa interfaz.La interfaz "devuelta" corresponde a una versión posterior de Recordset (la versión 2.5, que se diferencia de la versión 2.1 por la inclusión de una entrada adicional al final de vtable: método Guardar).

De hecho, las interfaces de mi componente exponen muchos métodos que pasan Recordset como parámetro de salida.Entonces, ¿de repente estaban devolviendo una versión posterior de Recordset, con una identificación de interfaz diferente?Ciertamente parecía ser el caso.Y luego pensé, ¿por qué debería importar?La vtable tiene el mismo aspecto para los clientes de la interfaz anterior.De hecho, sospecho que si estuviéramos hablando de COM en proceso, y no de DCOM, este desajuste de impedancia aparentemente inofensivo se habría ignorado silenciosamente y no habría causado problemas.

Por supuesto, cuando entran en juego los límites del proceso y de la máquina, hay un proxy y un stub entre el cliente y el servidor.En este caso, estaba usando la clasificación de bibliotecas de tipos con el separador de subprocesos gratuito.Entonces había dos misterios por resolver:

¿Por qué devolvía una interfaz diferente en los parámetros de salida de los métodos en mi nuevo servidor?

¿Por qué esto afectó sólo a los clientes de Vista?

Como el software de mi servidor estaba alojado en servidores en cada una de mis ocho oficinas, decidí intentar apuntar mi cliente Vista a todas ellas en secuencia para ver cuáles tenían problemas con Vista y cuáles no.Prueba de iluminación.Algunos de los servidores más antiguos todavía funcionaban con Vista, pero los más nuevos no.Aunque algunos de los servidores más antiguos todavía ejecutaban Windows 2000 mientras que los más nuevos ejecutaban Windows 2003, ese no parecía ser el problema.

Después de comparar las fechas de los componentes DLL, parecía que siempre que el cliente apuntaba a servidores con componentes DLL con fecha anterior a 2003, Vista estaba bien.Pero aquellos que tenían archivos DLL con fechas posteriores a 2003 eran problemáticos.Lo creas o no, no hubo (o al menos no hubo cambios significativos) en el código de los componentes del servidor durante muchos años.Aparentemente, las diferentes fechas se debieron simplemente a recompilaciones de mis componentes en mi(s) máquina(s) de desarrollo.Y parecía que una de esas recompilaciones ocurrió en 2003.

La bombilla se encendió.Al pasar conjuntos de registros del servidor al cliente, mis componentes ATL C++ se refieren a la interfaz como _Recordset.Este símbolo proviene de la biblioteca de tipos integrada en msado15.dll.Esta es la línea que tenía en el código C++:

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

No se deje engañar por el número 15 en msdad15.dll.Al parecer, esta DLL no ha cambiado de nombre en la larga serie de versiones de MDAC.

Cuando compilé la aplicación en el pasado, la versión de MDAC era 2.1.Entonces _Recordset se compiló con la identificación de la interfaz 2.1 y esa es la interfaz devuelta por los servidores que ejecutan esos componentes.

Todos los clientes utilizan el proxy de aplicación COM+ que se generó (creo) en 1999.La biblioteca de tipos que define mis interfaces incluye la línea:

importlib("msado21.tlb");

lo que explica por qué esperan la versión 2.1 de Recordset en los parámetros de salida de mi método.Claramente el problema estaba en mi recompilación de 2003 y en el hecho de que en ese momento el símbolo _Recordset ya no correspondía a la versión 2.1.De hecho, _Recordset correspondía a la versión 2.5 con su identificación de interfaz distintiva.La solución para mí fue cambiar todas las referencias de _Recordset a Recordset21 en mi código C++.Reconstruí los componentes y los implementé en el nuevo servidor.Voila, los clientes parecían felices otra vez.

En conclusión, todavía me quedan dos preguntas persistentes.

¿Por qué la infraestructura proxy/stub parece comportarse de manera diferente con los clientes Vista?Parece que Vista está haciendo controles más estrictos de los identificadores de interfaz que provienen de los parámetros del método que XP.

¿Cómo debería haber codificado esto de manera diferente en 1999 para que esto no hubiera sucedido?Se supone que las interfaces son inmutables y cuando volví a compilar con una versión más reciente de MDAC, sin darme cuenta cambié mi interfaz porque los métodos ahora devolvían una interfaz Recordset diferente como parámetro de salida.Hasta donde yo sé, la biblioteca de tipos en aquel entonces no tenía un símbolo específico de la versión; es decir, las versiones posteriores de las bibliotecas de tipos MDAC definen Recordset21, pero ese símbolo no estaba disponible en la biblioteca de tipos 2.1.

¿Fue útil?

Solución

Cuando Microsoft adoptó la religión de la seguridad, DCOM (y el RPC subyacente) recibieron mucha atención y definitivamente se realizaron cambios para cerrar los agujeros de seguridad que resultaron en una clasificación más estricta.Me sorprende que vea esto en Vista pero no en XP, pero es posible que se hayan agregado comprobaciones adicionales para Vista.Alternativamente, es posible que el rigor opcional en XP se haya hecho obligatorio en Vista.

Si bien no sé lo suficiente sobre MDAC para saber si se podría haber evitado esto, sí sé que la seguridad es una de las pocas áreas en las que Microsoft está bastante dispuesto a sacrificar la compatibilidad con versiones anteriores, por lo que es posible que no se haya podido hacer nada. mejor" allá por 1999.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top