gpt4 book ai didi

windows-vista - Vista 是否对 DCOM 调用中的接口(interface) ID 进行更严格的检查? ( stub 收到坏数据)?

转载 作者:行者123 更新时间:2023-12-04 21:28:09 25 4
gpt4 key购买 nike

我希望每个人都能原谅这个问题的长度和叙述方式。我决定在我的博客中详细描述这种情况。后来我看到了乔尔对这个网站的邀请,我想我会把它贴在这里,看看是否有人对这种情况有任何了解。

我编写并现在支持一个应用程序,该应用程序包含一个 Visual Basic 胖客户端,将 DCOM 与使用 ATL 用 C++ 编写的中间层 COM+ 组件通信。它在我们所有的八个办公室中运行。每个办公室都有一个后端服务器,其中包含 COM+ 应用程序(由 18 个单独的组件组成)和 SQLServer。 SQLServer 通常位于同一后端服务器上,但并非必须如此。

我们最近将我们最大的办公室——纽约——的后端服务器从一个 MSC 集群迁移到了一个托管在 VMWare 的 ESX 技术上的新虚拟机。由于 COM+ 应用程序的位置已从旧服务器移动到具有不同名称的新服务器,因此我必须重定向所有客户端,以便它们在新服务器上激活 COM+ 应用程序。这个过程很老套,因为我对几个经历过类似基础设施升级的小型办公室做了基本相同的事情。

一切似乎都很正常,周一早上,整个办公室——大约 1,000 个 Windows XP 工作站——在新服务器上正常运行,没有发生任何事故。但是后来电话来自我的移动组——有一位在家工作的律师使用 VPN 连接,在重定向到新服务器后出现奇怪的错误:

FillTreeView2 错误 - stub 收到错误数据。

嗯?我以前从未见过此错误消息。是新服务器吗?但是办公室里的所有工作站都运行良好。我告诉移动组将代理切换回旧服务器(仍在运行),错误消失了。那么有什么不同呢?原来这位律师正在家里运行 Vista。

我们不在我们的任何办公室运行 Vista,但我们确实有一些律师在家里运行 Vista(当然有些在我的纽约办公室)。我也是这样,我从来没有见过这个问题。为了确认存在问题,我启动了我的 Vista 笔记本电脑,将其指向新服务器,并得到了同样的错误。我把它指向旧服务器,它运行良好。很明显,Vista 和新服务器上的组件存在一些问题——这个问题似乎不会影响 XP 客户端。会是什么呢?

下一站——我的笔记本电脑上的应用程序错误日志。这产生了有关错误的更多信息:

来源:Microsoft-Windows-RPC-Events
日期:2008 年 9 月 2 日上午 11:56:07
事件 ID:10
级别:错误
电脑:DevLaptop
说明:应用程序无法完成 COM 调用,因为错误
接口(interface) ID 作为参数传递。

预期的接口(interface) ID 是 00000555-0000-0010-8000-00aa006d2ea4,
返回的接口(interface) ID 为 00000556-0000-0010-8000-00aa006d2ea4。

用户操作 - 联系应用程序供应商以获取应用程序的更新版本。

界面 ID 提供了我需要解开谜团的线索。 “预期”接口(interface) ID 标识 MDAC 的 Recordset 接口(interface)——特别是该接口(interface)的 2.1 版。 “返回的”接口(interface)对应于更高版本的 Recordset(2.5 版与 2.1 版的不同之处在于在 vtable 的末尾包含了一个额外的条目——方法 Save)。

实际上,我的组件接口(interface)公开了许多将 Recordset 作为输出参数传递的方法。那么他们是否突然返回了更高版本的 Recordset —— 具有不同的接口(interface) ID?情况确实如此。然后我想,这有什么关系。 vtable 对于旧接口(interface)的客户端来说看起来是一样的。事实上,我怀疑如果我们谈论的是进程内 COM 而不是 DCOM,这种明显无害的阻抗失配会被默默忽略,不会引起任何问题。

当然,当进程和机器边界开始发挥作用时,客户端和服务器之间有一个代理和一个 stub 。在这种情况下,我使用了带有自由线程编码器的类型库编码。所以有两个谜团需要解开:

为什么我在新服务器上的方法的输出参数中返回不同的接口(interface)?

为什么这仅影响 Vista 客户端?

由于我的服务器软件托管在我的八个办公室中的每一个的服务器上,我决定尝试将我的 Vista 客户端依次指向所有这些,以查看哪些与 Vista 有问题,哪些没有。照明测试。一些较旧的服务器仍然可以与 Vista 配合使用,但较新的服务器则不能。尽管一些较旧的服务器仍在运行 Windows 2000,而较新的服务器已在 2003 年运行,但这似乎不是问题。

在比较组件 DLL 的日期后,似乎只要客户端指向具有 2003 Vista 之前的组件 DLL 的服务器就可以了。但是那些具有 2003 年之后日期的 DLL 是有问题的。信不信由你,多年来服务器组件上的代码没有(或至少没有显着的)变化。显然,不同的日期仅仅是由于在我的开发机器上重新编译了我的组件。似乎其中一次重新编译发生在 2003 年。

灯泡继续亮着。当将记录集从服务器传回客户端时,我的 ATL C++ 组件将该接口(interface)称为 _Recordset。此符号来自嵌入在 msado15.dll 中的类型库。这是我在 C++ 代码中的一行:

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

不要被msdad15.dll中的15所欺骗。显然这个 DLL 在 MDAC 版本的长系列中没有改变名称。

当年编译应用程序时,MDAC的版本是2.1。所以 _Recordset 用 2.1 接口(interface) id 编译,这是运行这些组件的服务器返回的接口(interface)。

所有客户端都使用 1999 年生成(我相信)的 COM+ 应用程序代理。定义我的接口(interface)的类型库包括以下行:

importlib("msado21.tlb");

这解释了为什么他们期望在我的方法的输出参数中使用 Recordset 2.1 版。显然,问题出在我 2003 年的重新编译以及当时 _Recordset 符号不再对应于 2.1 版的事实。事实上,_Recordset 对应于 2.5 版本,具有独特的接口(interface) id。我的解决方案是在我的 C++ 代码中将所有引用从 _Recordset 更改为 Recordset21。我重建了组件并将它们部署到新服务器。瞧——客户似乎又高兴了。

总之,我还有两个烦人的问题。

为什么代理/ stub 基础结构与 Vista 客户端的行为似乎不同?与 XP 相比,Vista 似乎对从方法参数返回的接口(interface) ID 进行了更严格的检查。

我应该如何在 1999 年以不同的方式对此进行编码,以免发生这种情况?接口(interface)应该是不可变的,当我在较新版本的 MDAC 下重新编译时,我无意中更改了我的接口(interface),因为这些方法现在返回不同的 Recordset 接口(interface)作为输出参数。据我所知,当时的类型库没有特定于版本的符号——也就是说,更高版本的 MDAC 类型库定义了 Recordset21,但该符号在 2.1 类型库中不可用。

最佳答案

当 Microsoft 获得安全信仰时,DCOM(和底层 RPC)得到了很多关注,并且肯定会进行更改以关闭导致更严格编码(marshal)的安全漏洞。我很惊讶你在 Vista 中看到了这一点,但在 XP 中没有看到,但它可能为 Vista 添加了额外的检查。或者,XP 中的可选严格性可能在 Vista 中成为强制性的。

虽然我对 MDAC 的了解还不够多,无法知道您是否可以阻止这种情况发生,但我确实知道安全性是 Microsoft 非常愿意牺牲向后兼容性的少数几个领域之一,因此您可能什么也做不了”更好”早在 1999 年。

关于windows-vista - Vista 是否对 DCOM 调用中的接口(interface) ID 进行更严格的检查? ( stub 收到坏数据)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63720/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com