gpt4 book ai didi

windows - 为什么 TVM_GETITEM 消息在 comctl32.ocx 或 mscomctl.ocx TreeView 上失败?

转载 作者:可可西里 更新时间:2023-11-01 09:42:41 36 4
gpt4 key购买 nike

我编写了一个函数,它可以生成 TreeView 项的文本,即使 TreeView 在远程进程中也是如此。该函数在远程进程中分配两个内存块,填充 TVITEM 结构(已复制到远程进程中),发送 TVM_GETITEM 消息,最后将第二个远程内存块的内容读回本地缓冲区。这是代码:

std::string getTreeViewItemText( HWND treeView, HTREEITEM item )
{
DWORD pid;
::GetWindowThreadProcessId( treeView, &pid );

HANDLE proc = ::OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid );
if ( !proc )
// handle error

TVITEM tvi;
ZeroMemory( &tvi, sizeof(tvi) );

LPVOID tvi_ = ::VirtualAllocEx( proc, NULL, sizeof(tvi), MEM_COMMIT, PAGE_READWRITE);
if ( !tvi_ )
// handle error

TCHAR buffer[100] = { 'X' };

LPVOID txt_ = ::VirtualAllocEx( proc, NULL, sizeof(buffer), MEM_COMMIT, PAGE_READWRITE );
if ( !txt_ )
// handle error

tvi.mask = TVIF_TEXT | TVIF_HANDLE;
tvi.pszText = (LPTSTR)txt_;
tvi.cchTextMax = sizeof(buffer) / sizeof(buffer[0] );
tvi.hItem = item;

if ( !::WriteProcessMemory( proc, tvi_, &tvi, sizeof(tvi), NULL ) )
// handle error

if ( !::SendMessage( treeView, TVM_GETITEM, 0, (LPARAM)tvi_ ) )
// handle error

if ( !::ReadProcessMemory( proc, (LPCVOID)txt_, buffer, sizeof( buffer ), NULL ) )
// handle error

::VirtualFreeEx( proc, tvi_, 0, MEM_RELEASE );

::VirtualFreeEx( proc, txt_, 0, MEM_RELEASE );

::CloseHandle( proc );

return buffer;
}

此代码与将 WC_TREEVIEW 类名传递给 CreateWindow 时获得的普通 TreeView 配合得很好。但是,我注意到它不适用于 MS Common Controls v5 (comctl32.ocx) 或 MS Common Controls v6 (mscomctl.ocx) 提供的较新树。在这些情况下,返回的文本始终为空(缓冲区全为零)。我还注意到 SendMessage 调用返回零(因此开始执行上面的 //handle error 注释表示的错误处理)。我不清楚这是否真的表示错误,无论如何缓冲区都充满了零。

所有其他 TreeView 消息(如 TVM_GETITEMRECT)似乎都运行良好。

有人知道这是为什么吗?我尝试使用 UNICODE 标志(我注意到 TVM_GETITEM 被定义为 TVM_GETITEMATVM_GETITEMW)但这似乎没有帮助.

最佳答案

如果代码是使用定义的 UNICODE 编译的,则代码不会按预期工作,但远程进程不是(或相反)。你应该调用IsWindowUnicode首先在 treeView 句柄上检查远程端是否需要 Unicode 消息。

这是必需的,因为 SendMessage 执行的标准双向编码在这种情况下是不够的:您必须发送两个完全不同的窗口消息,具体取决于远程端是否是 Unicode 窗口。如果它是 Unicode,请将 SendMessageW 与 TVM_GETITEMW 一起使用。如果是 ANSI,请将 SendMessageA 与 TVM_GETITEMA 一起使用。

这适用于所有常用控件,但不适用于基本控件集(使用窗口消息 < 1024)。

我还相信,如果将代码编译成 64 位二进制文​​件,但远程进程是 32 位(或相反),代码将会中断。这是因为代码将它的本地(例如:64 位)TVITEM 复制到远程进程中,然后期望远程进程在处理 TVM_GETITEM(A|W) 消息时按预期读取它。但是,结构的大小可能不同(由于指针大小不同)。

关于windows - 为什么 TVM_GETITEM 消息在 comctl32.ocx 或 mscomctl.ocx TreeView 上失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2244037/

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