Richard
Richard

Reputation: 425

ReadProcessMemory() Returning 0 ERROR_PARTIAL_COPY

#include <Windows.h>
#include <iostream>
#include <vector>
#include <TlHelp32.h>
#include <tchar.h>

using namespace std;

DWORD GetModuleBase(LPSTR lpModuleName, DWORD dwProcessId)
{
   MODULEENTRY32 lpModuleEntry = {0};
   HANDLE hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId );

   if(!hSnapShot)
      return NULL;
   lpModuleEntry.dwSize = sizeof(lpModuleEntry);
   BOOL bModule = Module32First( hSnapShot, &lpModuleEntry );
   while(bModule)
   {
      if(!strcmp( lpModuleEntry.szModule, lpModuleName ) )
      {
         CloseHandle( hSnapShot );
         return (DWORDLONG)lpModuleEntry.modBaseAddr;
      }
      bModule = Module32Next( hSnapShot, &lpModuleEntry );
   }
   CloseHandle( hSnapShot );
   return NULL;
}


int main() {
    DWORD pID;
    DWORDLONG off1, off2;
    DWORDLONG baseAddress;
    char moduleName[] = _T("AoE2DE_s.exe");
    HWND hGameWindow;
    HANDLE pHandle;

    //Get Handles
    hGameWindow = FindWindow(NULL, "Age of Empires II: Definitive Edition");
    cout << "Game Window: " << hGameWindow << std::endl;
    GetWindowThreadProcessId(hGameWindow, &pID);
    cout << "Process ID: " << pID << std::endl;
    pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);

    cout << "Process Handle: " << std::hex << pHandle << std::endl;

    //Get Client Base Addy
    DWORDLONG clientBase = GetModuleBase(moduleName, pID);
    cout << "Client Base: " << clientBase << std::endl;
    ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), NULL);
    DWORD lastError = GetLastError();
    cout << "Error: " << lastError << std::endl;
    cout << "Base Address: " << std::hex << baseAddress << std::endl;
    ReadProcessMemory(pHandle, (LPCVOID)(baseAddress + 0x18), &off1, sizeof(DWORDLONG), NULL);
    cout << "After Offset 1: " << std::hex << off1 << std::endl;
    ReadProcessMemory(pHandle, (LPCVOID)(off1 + 0x9230), &off2, sizeof(DWORDLONG), NULL);
    cout << "After Final Offset: " << off2 << std::endl;
    cin.get();
}

The error occurs on this line: ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), NULL);

Application output for debugging purposes:

Game Window: 0x1307c2
Process ID: 11988
Process Handle: 0xec
Client Base: cc640000
Error: 12b
Base Address: 0
After Offset 1: 401519
After Final Offset: 8

Not sure how it is failing here, I'm somewhat new to this. Everything else goes through perfectly without error's but fails on the first ReadProcessMemory() if someone can help bring the solution for this to light I would be grateful.

Upvotes: 0

Views: 613

Answers (1)

Surt
Surt

Reputation: 16119

ReadProcessMemory is defined like this:

BOOL ReadProcessMemory(
  HANDLE  hProcess,
  LPCVOID lpBaseAddress,
  LPVOID  lpBuffer,
  SIZE_T  nSize,
  SIZE_T  *lpNumberOfBytesRead
);

If it returns zero then there has been an error, and only in that case GetLastError will return a meaningfull error number.

So correct usage would be:

SIZE_T readBytes;
if (!ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), &readBytes)) {
  DWORD lastError = GetLastError();
  cout << "ReadProcessMemory failed: Error: " << lastError << " read " << readBytes << std::endl;
}
else
{
  cout << "ReadProcessMemory succeeded"; << std::endl;
  cout << "Base Address: " << std::hex << baseAddress << std::endl;
}

Upvotes: 2

Related Questions