WinAPI EM_STREAMOUT crash



我正试图从另一个程序中获取Richedit控件的文本。

所以我找到了SendMessage的EM_STREAMOUT。

这是我到目前为止的代码(也是来自另一个堆栈溢出主题):

DWORD CALLBACK EditStreamOutCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
std::stringstream *rtf = (std::stringstream*) dwCookie;
rtf->write((char*)pbBuff, cb);
*pcb = cb;
return 0;
}
int main() {
std::stringstream rtf;
EDITSTREAM es = {0};
es.dwCookie = (DWORD_PTR) &rtf;
es.pfnCallback = &EditStreamOutCallback;
SendMessage((HWND) 0x00000000000A06E8, EM_STREAMOUT, SF_RTF, (LPARAM)&es);
}

唯一发生的事情是SendMessage返回0,所以显然没有读取任何字节,而我试图从中获取信息的程序的CPU使用率高达100%。

某些消息(如WM_GETTEXT)是由Windows为您封送的。这就是为什么您可以跨流程边界检索窗口的文本。EM_STREAMIN/OUT不是自动封送的。这就是你的代码崩溃的原因。EDITSTREAM结构和回调代码必须存在于拥有RichEdit的同一进程的地址空间中。

对于许多需要跨越流程边界的非封送处理消息,可以使用VirtualAllocEx()分配输入/输出缓冲区,使用WriteProcessMemory()填充它们,并使用ReadProcessMemory()读取它们。但是,由于EDITSTREAM回调代码也需要在同一进程中,因此最好将整个EM_STREAMOUT逻辑移动到DLL中,然后使用CreateRemoteThread()或其他注入技术将其注入到目标进程中。您可以使用GetWindowThreadProcessId()来获取拥有RichEdit的进程/线程ID。然后,您的DLL可以检索RichEdit数据,并使用您选择的任何IPC(进程间通信)机制将其发送回主应用程序,例如命名管道、mailslot、WM_COPYDATA消息等。

最新更新