views:

363

answers:

4

Hello

I want to be able to select which item is selected in another program's list view(I don't have access to its code). Actually, it is an SysListView32, which I assume is the same. I already have the following code, which unfortunely despite compiling, seems to do nothing (although SendMessage() returns 1).

process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, 0xD14); 

 _lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE); 

 lvi.state = LVIS_SELECTED | LVIS_FOCUSED;
 lvi.stateMask = LVIS_SELECTED | LVIS_FOCUSED; 

 WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL); 
 int abc = ::SendMessage((HWND)0x00050D30, LVM_SETITEMSTATE, (WPARAM)2, (LPARAM)_lvi); 
 VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
A: 

How are you initializing the rest of the members of the source LV_ITEM that is being copyied into the target process's memory? Are you including the LVIF_STATE flag in the source LV_ITEM's "mask" member? If not, then the ListView will ignore the "state" and "stateMask" values that you are trying to specify.

Remy Lebeau - TeamB
Not really: LVM_SETITEMSTATE specifies that the item's state will be changed. For this message the .mask is ignored.
Rom
A: 

If you get stuck, there is an open source project called AutoHotKey that can create scripts that can easily select items in lists, etc.

A: 

You have to reserve address space before committing memory. You can do both at once by changing MEM_COMMIT to MEM_RESERVE|MEM_COMMIT

Michael Dunn
+1  A: 

The following code works like a charm for me:

HANDLE hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, 0x0000c130);
LPVOID epLvi = VirtualAllocEx(hProcess, NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

LVITEM lvi;
lvi.state = LVIS_FOCUSED | LVIS_SELECTED;
lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
SIZE_T cbWritten = 0;
WriteProcessMemory(hProcess, epLvi, &lvi, sizeof(lvi), &cbWritten);
DWORD dw = SendMessage((HWND)0x00020C4C, LVM_SETITEMSTATE, 1, (LPARAM)epLvi);

VirtualFreeEx(hProcess, epLvi, 4096, MEM_DECOMMIT | MEM_RELEASE);
CloseHandle(hProcess);

There are several reasons why your code might not work:

  • as Michael Dunn mentioned, you need to reserve and commit the address space. Interesting is that your example only attempts to MEM_COMMIT the memory, but then MEM_RELEASE's it (which is opposite to MEM_RESERVE);
  • you might have not enough privileges to the process which owns the window;
  • your process and the target process might be of a different bitness. Some structure size tricks might be required in this case.

If all that doesn't work, I'd recommend trying a different approach: IAccessible might be helpful here. Usual disclaimers here: messing with other processes windows and address space requires careful approach and should be avoided if possible.

Rom