0

我尝试使用GetWindowLong API函数在另一个地址空间中获取另一个窗口的windowproc地址(GWL_WNDPROC),但是这个函数返回0并且GetLastErro是5(访问被拒绝)我以管理员身份运行我的程序并再次遇到这个问题,请帮助我?

操作系统:Win7 x86

4

2 回答 2

1

如果您的意思是另一个“过程”,那么这是不允许的。看看这里

于 2013-12-11T14:01:24.160 回答
1

你需要 <Windows via C/C++,第五版>

第 22 章 - DLL 注入和 API 挂钩

使用 Windows Hooks 注入 DLL

https://docs.microsoft.com/en-us/windows/win32/winmsg/hooks

形成上面的书:

假设您要对由另一个进程创建的窗口的实例进行子类化。您可能还记得子类化允许您更改窗口的行为。为此,您只需调用 SetWindowLongPtr 将窗口内存块中的窗口过程地址更改为指向新的(您自己的)WndProc。Platform SDK 文档声明应用程序不能子类化由另一个进程创建的窗口。这并不完全正确。子类化另一个进程的窗口的问题实际上与进程地址空间边界有关。

当您调用 SetWindowLongPtr 子类化窗口时,如下所示,您告诉系统发送或发布到由 hWnd 指定的窗口的所有消息都应定向到 MySubclassProc 而不是窗口的正常窗口过程:

SetWindowLongPtr(hWnd, GWLP_WNDPROC, MySubclassProc);

也就是说,当系统需要向指定窗口的WndProc发送消息时,会先查找地址,然后直接调用WndProc。在此示例中,系统看到 MySubclassProc 函数的地址与窗口相关联,而是直接调用 MySubclassProc。

对由另一个进程创建的窗口进行子类化的问题是子类过程位于另一个地址空间中。图 22-1 显示了窗口过程如何接收消息的简化视图。进程 A 正在运行并创建了一个窗口。User32.dll文件被映射到进程A的地址空间。User32.dll的这个映射负责接收和调度所有发送和发布的消息,发往由进程A中运行的任何线程创建的任何窗口。当User32的这个映射.dll 检测到一条消息,它首先确定窗口的 WndProc 的地址,然后调用它,传递窗口句柄、消息以及 wParam 和 lParam 值。WndProc 处理完该消息后,User32.dll 循环返回并等待另一个窗口消息被处理。

现在假设您的进程是进程 B,并且您想要子类化由进程 A 中的线程创建的窗口。进程 B 中的代码必须首先确定要子类化的窗口的句柄。这可以通过多种方式发生。图 22-1 所示的示例只是简单地调用 FindWindow 来获取所需的窗口。接下来,进程 B 中的线程调用 SetWindowLongPtr 以尝试更改窗口的 WndProc 的地址。请注意,我说的是“尝试”。这个调用什么都不做,只返回 NULL。SetWindowLongPtr 中的代码检查一个进程是否试图更改由另一个进程创建的窗口的 WndProc 地址,并简单地忽略该调用。

如果 SetWindowLongPtr 函数可以改变窗口的 WndProc 怎么办?系统会将 MySubclassProc 的地址与指定的窗口相关联。然后,当这个窗口被发送消息时,进程 A 中的 User32 代码将检索消息,获取 MySubclassProc 的地址,并尝试调用该地址。但是你会有一个大问题。MySubclassProc 将在进程 B 的地址空间中,但进程 A 将是活动进程。显然,如果 User32 调用这个地址,它将调用进程 A 的地址空间中的地址,这可能会导致内存访问冲突。

为避免此问题,您希望系统知道 MySubclassProc 在进程 B 的地址空间中,然后让系统在调用子类过程之前执行上下文切换。Microsoft 未实现此附加功能有几个原因:

应用程序很少需要对由其他进程中的线程创建的窗口进行子类化。大多数应用程序都是它们创建的窗口的子类,Windows 的内存体系结构并不妨碍这一点。

就 CPU 时间而言,切换活动进程非常昂贵。

进程 B 中的线程必须执行 MySubclassProc 中的代码。系统应该尝试使用哪个线程?现有线程还是新线程?

User32.dll 如何能够判断与窗口关联的地址是用于另一个进程中的过程还是在同一进程中?

由于这些问题没有很好的解决方案,Microsoft 决定不允许 SetWindowLongPtr 更改由另一个进程创建的窗口的窗口过程。

但是,您可以对由另一个进程创建的窗口进行子类化——您只需以不同的方式处理它。问题实际上与子类化无关——它与进程地址空间边界有关。如果您能以某种方式将子类过程的代码放入进程 A 的地址空间,则可以轻松调用 SetWindowLongPtr 并将进程 A 的地址传递给 MySubclassProc。我称这种技术“注入”一个 DLL 到一个进程的地址空间。

于 2020-08-20T11:45:48.990 回答