Fre*_*abe 2 windows treeview winapi comctl32
我写了一个函数,它可以生成树视图项的文本,即使树视图在远程进程中也是如此.该函数在远程进程中分配两个内存块,填充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;
}
Run Code Online (Sandbox Code Playgroud)
这段代码非常适用于将WC_TREEVIEW类名传递给的普通树视图CreateWindow.但是,我注意到它不适用于MS Common Controls v5(comctl32.ocx)或MS Common Controls v6(mscomctl.ocx)提供的新树.在这些情况下,返回的文本始终为空(缓冲区全为零).我还注意到SendMessage调用返回零(因此// handle error上面的注释表示的错误处理开始).我不清楚这是否真的表示错误,在任何情况下缓冲区都填充了全零.
所有其他树视图消息(如TVM_GETITEMRECT)似乎都运行良好.
有谁知道那是为什么?我尝试使用UNICODE标志(我注意到它TVM_GETITEM被定义为TVM_GETITEMA或TVM_GETITEMW),但这似乎没有帮助.
如果使用UNICODE定义编译,但代码不能按预期工作,但远程进程不是(或反过来).您应首先在句柄上调用IsWindowUnicode,treeView以检查远程端是否需要Unicode消息.
这是必需的,因为在这种情况下,SendMessage执行的标准双向编组是不够的:根据远程端是否是Unicode窗口,您必须发送两个完全不同的窗口消息.如果是Unicode,请将SendMessageW与TVM_GETITEMW一起使用.如果是ANSI,请将SendMessageA与TVM_GETITEMA一起使用.
这适用于所有常用控件,但不适用于基本控件集(使用窗口消息<1024).
我也相信如果代码被编译成64位二进制文件,代码将会中断,但远程进程是32位(或者反过来).这是因为代码将其本地(例如:64位)TVITEM复制到远程进程中,然后期望远程进程在处理TVM_GETITEM(A | W)消息时按预期读取它.但是,结构的大小可能不同(由于指针大小不同).
| 归档时间: |
|
| 查看次数: |
2087 次 |
| 最近记录: |