In-Context 挂钩函数预防措施
出于性能原因,客户端开发人员注册上下文挂钩函数。 但是,由于这些挂钩函数映射到服务器的地址空间,客户端和服务器开发人员必须采取预防措施,以确保事件处理顺利进行。
客户端开发人员的预防措施
客户端开发人员应注意以下问题:
- 上下文挂钩函数不应使用大量处理器时间,因为挂钩函数必须在服务器应用程序继续之前返回。
- 触发事件后,在调用挂钩函数时,与事件关联的窗口可能不再存在。 客户端必须验证与事件关联的窗口是否仍然存在,然后再执行与该事件相关的任何其他作。 为了确保窗口仍然存在,客户端使用 Microsoft Win32 IsWindow 函数。
- 如果挂钩函数在其中定义挂钩函数的 DLL 链接到另一个 DLL,客户端开发人员必须确保系统加载另一个 DLL。 如果隐式链接(使用 .def 文件和导入),则其他 DLL 必须位于 Windows 目录或其中一个系统目录(如 Windows\System、Windows\System32 或 Windows\SysWOW64) 中。 如果显式链接(使用 LoadLibrary),则必须在调用 LoadLibrary中指定附加 DLL 所在的目录的完整路径。
- 当包含挂钩函数的 DLL 加载到 16 位应用程序中时,上下文中挂钩函数可能会导致堆栈溢出。 出现此问题的原因是,16 位应用程序使用的固定堆栈大小不够大,无法容纳导致调用挂钩函数的系统函数调用链。
服务器开发人员的预防措施
服务器开发人员需要注意客户端应用程序可能会注册上下文中的挂钩函数。 当服务器调用 NotifyWinEvent时,必须准备好处理 WM_GETOBJECT 和其他 IAccessible 方法。
接口指针无效
当客户端在上下文挂钩函数中调用 AccessibleObjectFromEvent 时,返回的 IAccessible 接口指针直接指向服务器地址空间中的代码。 如果客户端使用此指针调用接口属性,则组件对象模型 (COM) 库不涉及封送处理(打包和跨进程边界发送接口参数)或取消组合(已跨进程边界发送的解包参数),并且不会检测对象是否被销毁。
如果客户端将接口属性调用销毁的对象,则无效的接口指针将导致服务器的地址空间中的常规保护错误,除非服务器检测到这种情况。
为了防止接口指针无效,服务器 创建代理对象 包装可访问对象并监视可访问对象的生命周期。 例如,当客户端调用 IAccessible 属性以获取有关对象的信息时,代理将检查可访问对象是否仍然可用,如果是,则会将客户端的请求转发到可访问对象。 如果已销毁可访问对象,代理会将错误返回到客户端。