LVM_GETITEMTEXT for x32 and x64 in C
I've been trying to get the text of items in listview another process. I found an awesome tutorial on CodeProject. Thanks to this article I was able to do this on x32. But when try to run on x64, it crashes the application I'm trying to access when SendMessage is called. In the articles comments people had simliar problems because of different pointer sizes. Some people suggested using a x64 compiler which I cant use. I need my program to run on both x32/x64. One guy suggested:
I have the answer. The LVITEM structure is wrong under 64-bit systems. Pointers are 64-bit now, so the text pointer has to be followed by a dummy value, to offset the length member correctly.
I think this would be the best solution, as I could run it for x32 and x64 with one exe. I just have no idea how to do what hes talking about. I have included my code which currently works on x32. If anyone can help me out. That would be awesoem.
LVITEMLVITEM lvi, *_lvi;
char item[512];
char *_item;
unsigned long pid;
HANDLE process;
GetWindowThreadProcessId(procList, &pid);
process = OpenProcess(0x001f0fff, FALSE, pid);
_lvi = (LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM), 0x1000, 4);
_item = (char*)VirtualAllocEx(proc开发者_Go百科ess, NULL, 512, 0x1000, 4);
lvi.cchTextMax = 512;
int r, c;
for (r = 0; r < rowCount; r++)
{
for (c = 0; c < columnCount; c++)
{
lvi.iSubItem = c;
lvi.pszText =_item;
// Insert lvi into programs's memory
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
// Have program write text to in its memory where we told it to
SendMessage(procList, LVM_GETITEMTEXT, (WPARAM)r, (LPARAM)_lvi);
// Get TVITEM back from programs
ReadProcessMemory(process, _item, item, 512, NULL);
}
}
// Clean up the mess we made
VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _item, 0, MEM_RELEASE);
CloseHandle(process);
I don't think you'll be able to achieve this. In a 32 bit process your pointers will be too short. I believe that VirtualAllocEx will fail when called from a 32 bit process and with a 64 bit process handle as its first parameter. I think you would see this if you added error checking to your code.
Your only solution will be to have 2 versions, x86 and x64. That should be no real trouble - usually it can be done with single source.
Sending LVM_GETITEMTEXT message from 32-bit application to 64-bit ListView is actually possible.
I was able to achieve this by using not the original LVITEM (60 bytes long) but LVITEM structure (88 bytes long) with seven 4-byte placeholders inserted between members. It works on my Win7 Pro 64-bit, though I have not tested this approach yet on other machines.
Below is the structure. This is C++, but nothing prevents us from doing the same in .NET.
typedef struct {
UINT mask;
int iItem;
int iSubItem;
UINT state;
UINT stateMask;
int placeholder1;
LPTSTR pszText;
int placeholder11;
int cchTextMax;
int iImage;
LPARAM lParam;
int placeholder2;
#if (_WIN32_IE >= 0x0300)
int iIndent;
#endif
#if (_WIN32_WINNT >= 0x0501)
int iGroupId;
UINT cColumns;
int placeholder3;
UINT puColumns;
int placeholder4;
#endif
#if (_WIN32_WINNT >= 0x0600)
int piColFmt;
int placeholder5;
int iGroup;
int placeholder6;
#endif
} LVITEM64, *LPLVITEM64;
精彩评论