Windows ListView LVM_GETITEM iImage 始终为零

Windows ListView LVM_GETITEM iImage is always zero

本文关键字:iImage GETITEM ListView LVM Windows      更新时间:2023-10-16

我正在尝试使用桌面列表视图做一些事情。 我可以使用LVM_GETITEM获取项目的文本,但 iImage 结构成员始终为零,状态也是如此。 我正在运行 Win 7 64,并使用 Dev C++(gcc) 编译为 64。 我还尝试将其编译为 32 位并在 XP 上进行了相同的测试,结果相同......只有文本、图像和状态被分配为零。 我也可以用 ListView_GetItemCount() 获得项目计数没有问题。

HWND progman = FindWindow("progman", NULL);
HWND shell = FindWindowEx(progman, NULL, "shelldll_defview", NULL);
HWND hwndListView = FindWindowEx(shell, NULL, "syslistview32", NULL);
int ct = ListView_GetItemCount(hwndListView);
const DWORD dwBufSize = 1024;       
DWORD dwProcessID;
DWORD dwResult;
HANDLE hProcess;
BYTE *lpRemoteBuffer;
LVITEM lvItem = {0};
BYTE lpLocalBuffer[dwBufSize] = {0};
// Get the process id owning the window
::GetWindowThreadProcessId( hwndListView, &dwProcessID );
// Open the process wih all access (You may not have the rights to do this)
hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessID );
// Allocate a buffer in the remote process
lpRemoteBuffer = (BYTE*)::VirtualAllocEx( hProcess, NULL, dwBufSize,
MEM_COMMIT, PAGE_READWRITE );
// Fill in the LVITEM struct, this is in your own process
// Set the pszText member to somewhere in the remote buffer,
// For the example I used the address imediately following the LVITEM stuct
lvItem.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM|LVIF_STATE;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.cchTextMax = MAX_PATH;
// Point to after LVITEM in the remote buffer
lvItem.pszText = (LPTSTR)(lpRemoteBuffer + sizeof( LVITEM ));
// Copy the local LVITEM to the remote buffer
::WriteProcessMemory( hProcess, (LPVOID)lpRemoteBuffer, &lvItem, sizeof(LVITEM), NULL );
// Send the message
::SendMessage( hwndListView, LVM_GETITEM, 0, (LPARAM)lpRemoteBuffer);
// Read the struct back from the remote process into local buffer
::ReadProcessMemory( hProcess, (LPVOID)lpRemoteBuffer, lpLocalBuffer, dwBufSize, NULL );
//Fix pszText to point to same offset in local buffer
lvItem.pszText = (LPTSTR)(lpLocalBuffer + sizeof( LVITEM ));
MessageBox(hwnd, lvItem.pszText, "", 0);
char txt[10];
ZeroMemory(txt, 10);
MessageBox(hwnd, itoa(lvItem.iImage, txt, 10), "", 0);
MessageBox(hwnd, itoa((int)lvItem.state, txt, 10), "", 0);
// Clean-up
::VirtualFreeEx( hProcess, (LPVOID)lpRemoteBuffer, 0, MEM_RELEASE ); 
::CloseHandle( hProcess );

您正在为文本分配虚拟内存。还必须为 LVITEM 分配虚拟内存。然后将文本内存分配给lvItem.pszText,然后读取两个内存。它必须针对 64 位系统进行 64 位编译。添加更多错误检查。

HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |
     PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
const DWORD dwBufSize = 1024;
void* pbuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
void* pitem = VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
LVITEM lvItem = { 0 };
lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.cchTextMax = MAX_PATH;
lvItem.pszText = (char*)pbuf;
WriteProcessMemory(hProcess, pitem, &lvItem, sizeof(LVITEM), NULL);
if (SendMessage(hwndListView, LVM_GETITEM, 0, (LPARAM)(LVITEM*)(pitem)))
{
    char buf[dwBufSize];
    if (ReadProcessMemory(hProcess, pbuf, buf, dwBufSize, 0))
    {
        OutputDebugString(buf);
        OutputDebugString(", ");
        if (ReadProcessMemory(hProcess, pitem, &lvItem, sizeof(LVITEM), 0))
        {
            _itoa_s(lvItem.iImage, buf, 10);
            OutputDebugString(buf);
            OutputDebugString("n");
        }
    }
}
VirtualFreeEx(hProcess, pitem, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, pbuf, 0, MEM_RELEASE);
CloseHandle(hProcess);