您现在的位置: IT专家网 > WinSystem子站 > 技巧
XP两种工具在代码中检测并堵塞 GDI 泄漏
Windows 需要一种不太相同的 GDI 泄漏方法,他构建并说明了两种工具,这两种工具旨在检测并消除在 Windows XP、Windows 2000 和 Windows NT 上运行的应用程序中的 GDI 泄漏。
从调试器到调试对象的通信
调试器使用 s_dwInfiltratedThreadID 共享变量来发送一个请求(利用 PostThreadMessage 通过一个简单的 Windows 消息),该请求将由调试对象中的渗透线程来处理。当调试对象通知调试器这样的一个请求已经完成时,需要另一个 s_dwCallingThreadID 共享变量。例如,当用户单击“Take Snapshot!”按钮时,GDIUsage 需要从调试对象收集已分配的 GDI 对象。
GDIUsage 发送一条 TM_GET_LIST 消息给调试对象中的渗透线程,调试对象的值保存在 s_dwInfiltratedThreadID 中。它将执行连同参数 UM_SNAPSHOT_READY 一起发送给 OnGetList 函数,该参数将被用作回调消息被 GDIUsage 主对话框接收。为什么不简单地使用同样的 TM_GET_LIST?答案与共享代码有关。“Take Snapshot!”与“Compare”按钮都需要获得相同的已分配 GDI 对象列表(虽然使用该列表的方法不同),以更新 GDIUsage 用户界面的相应部分。
为了总结一下在前面段落中我已经论述的内容,TM_GET_LIST 线程消息触发对调试对象端 GDI 对象的处理。另外,根据用户定义的两条消息,有两种方法可以更新 GDIUsage 主对话框:UM_SNAPSHOT_READY 与 UM_COMPARE_READY。
渗透线程唤醒并要求 OnGetList 来处理请求。该 CGDITraceApp 方法通过修补的存根枚举出调试对象中检测到的 GDI 分配,并将每个对象的说明(句柄值和类型)按照下面的 GDI_LIST 格式复制到由 m_lpvMem z指向的内存映射文件共享的缓冲区中:
| typedef struct { DWORD dwType; HGDIOBJ hObject; } GDI_ITEM; typedef struct { DWORD dwCount; // count of meaningful GDI_ITEM slots in Items GDI_ITEM Items[]; } GDI_LIST; |
死锁与计时问题
在深入了解远程 GDI 对象的图形显示之前,您应当了解一下可能发生的死锁问题。以前探讨的收集 GDI 对象的技术都是异步的,因为它要依赖调试器和调试对象之间交换的 Windows 消息。如果需要进行强同步通信,可以使用 Win32 事件。例如,渗透线程等待一个有特定名称的事件,当一条消息发送到它的队列中或者事件获得信号通知时,它就调用 MsgWaitForMultipleObjectsEx 来唤醒。在该实现中,用事件来要求线程结束它的生存期,因此不是真正的同步。
另一种需要真正同步行为的情况是,当调试对象加载一个 DLL 时修补 GDI 调用。为了截获 GDI 调用,调试器必须尽快通知渗透线程。否则,调试对象可能在安装截获存根之前就开始分配 GDI 对象。这里是一个不错的实现方案:
1.调试器线程获得通知,通过 WaitForDebugEvent 返回的LOAD_DLL_DEBUG_EVENT 已在调试对象中加载了一个 DLL。
2.OnLoadDLLDebugEvent 重写方法接收 DLL 对应的 hModule,将它保存在一个新的共享变量中,并通过为事件发送信号来请求调试对象为该特定的 DLL 修补 GDI 调用。
3.如果调试对象加载另一个 DLL,为了避免重新进入,OnLoadDLLDebugEvent 等待另一个在调试对象完成其修补工作后的信号通知事件。
4.MsgWaitForMultipleObjectsEx 唤醒调试对象-渗透线程,因为它等待的一个事件已经由信号通知。
5.CGDITraceApp::OnNewDLL 方法为在由共享变量定义的地址处加载的 DLL 重定向 GDI 调用,该共享变量由调试器用 DLL hModule 填充。
6.调试器等待的事件由渗透线程发信号通知。
7.渗透线程调用 MsgWaitForMultipleObjectsEx 等待完成另一个请求。
8.调试器线程继续进行,因为它等待的事件已经由信号通知。
注意,最后两步的顺序号相同,因为它们的代码在由 Windows 调度的两个不同线程中运行。不要指望一个会在另一个之前执行。
- 本文关键词:
- API
- IT技术
- Windows
- Windows XP
- 操作系统

