R – How to allocate memory in another process for windows mobile

compact-frameworkmemory-managementnetwindows-mobile

I'd like to read the contents of another process listview control in windows mobile. To do this, I need a pointer to some free memory to that process in order to put the values there (and then read them from my process). This can be done in normal Windows or Win32 with the VirtualAllocEx function.

However, this function is not supported in windows mobile ! Can you recommend me a way to allocate that memory?

Best Answer

Well, after a lot of search, I believe that I found a working solution. I am not saying that the solution works perfect or works 100% of the time, however I believe that it is the best that can be done with the memory tools that Windows Mobile provides us.

Here's a rough description of the method (if people needed, I can provide full source code): a) Use CreateToolhelp32Snapshot to get information from all running processes

CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS |  TH32CS_SNAPNOHEAPS , 0 );

b) Walk through these processes until you find the one with the listview. You'll have a PROCESSENTRY32 structure for that proccess, let's call it pe32.

PROCESSENTRY32 pe32;
if( !Process32First( hProcessSnap, &pe32 ) ) 
...
do { ... }
while( Process32Next( hProcessSnap, &pe32 ) );

c) Use OpenProcess to get a handle for that process, let's call it hProcess.

HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );

d) Starting from pe32.th32MemoryBase+512 until pe32.th32MemoryBase + 0x02000000 (processses in windows mobile 6 have 32 mb memory space) use the VirtualQuery method to receive information about that region. You'll get a MEMORY_BASIC_INFORMATION structure, let's call it mbi. Memory regions will be incremented by mbi.RegionSize

DWORD dwAddress = pe32.th32MemoryBase + 512;
DWORD dwStopAddress = pe32.th32MemoryBase + 0x02000000; 
while (VirtualQuery((LPVOID)dwAddress, &mbi, sizeof(mbi))) {
 ...
  dwAddress += mbi.RegionSize;
  if (dwAddress >= dwStopAddress) break;
}

e) Check to see if mbi.State == MEM_COMMIT and mbi.Protect == PAGE_READWRITE. If both are true, then you can write to that area. Also, take a look at mbi.RegionSize to see if the memory region is enough for your data. If condition are not met, will to next region. WARNING: You do not know on what you will write. You may break the listview application. More on this later.

if(mbi.State == MEM_COMMIT && mbi.Protect == PAGE_READWRITE ) { ... }

f) Inside the previous if (all conditions met): Declare a pointer that will point to mbi.BaseAddress - pe32.th32MemoryBase:

char * membase2 = (char *)mbi.BaseAddress - pe32.th32MemoryBase ;

g) Now you may read or write the memory of the other process using ReadProcessMemory and WriteProcessMemory! For instance, here's my code for reading the contents of the listview:

LVITEM lvi, *_lvi;
LPWSTR _item;
TCHAR item[128];

_lvi = (LVITEM *) membase2;
_item = (LPWSTR)membase2;
_item += 128;

lvi.iSubItem=1;
lvi.pszText=_item;
lvi.iItem = 0;
lvi.cchTextMax = 64;

WriteProcessMemory(hProcess, _lvi, &lvi, sizeof(LVITEM), NULL);
SendMessage(listHWND, LVM_GETITEMTEXT, (WPARAM)0, (LPARAM)_lvi);
ReadProcessMemory(hProcess, _item, item, 128, NULL);
wprintf(TEXT("%s\n"), item);

h) Final thoughts: The method does work. It has been tested by me. However, you must always take into account the warning I mentioned before: You do not know where you are going to write: The memory you will use commited and you can write to it, however you won't be sure on what you are writing. Of course, this is the memory of the other application so you'll only break it. If that doesn't matter that much, you can the restart it and continue reading its memory! When I tested it, the other application did not crush even once, however it was just closed one or two times. Also, if you cannot get it to work, then try another memory region (step d).