Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get nonsense from GetModuleFileNameEx on 64-bit Windows 8?

I have this

function NazwaProcesu(const uchwyt: Thandle): string;
var
  pid: DWORD;
  hProcess: Thandle;
  sciezka: array [0..MAX_PATH - 1] of char;
begin
  GetWindowThreadProcessId(uchwyt, pid);
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE, pid);
  if hProcess <> 0 then
    try
      GetModuleFileNameEx(hProcess, 0, sciezka, MAX_PATH)
    finally
      Result := sciezka;
      CloseHandle(hProcess);
    end;
end;

On windows 7 32 bit no problems. On Win 8 x64 i have this:

enter image description here

where last 3 entries should be explorer.exe, i guess. Thanks for help.

like image 721
mca64 Avatar asked Jul 31 '14 15:07

mca64


2 Answers

After modifications:

function NazwaProcesu(const uchwyt: Thandle): string;
type
  TQueryFullProcessImageName = function(hProcess: Thandle; dwFlags: DWORD; lpExeName: PChar; nSize: PDWORD): BOOL; stdcall;
var
  pid: DWORD;
  hProcess: Thandle;
  sciezka: array [0 .. MAX_PATH - 1] of Char;
  QueryFullProcessImageName: TQueryFullProcessImageName;
  nSize: cardinal;
begin
  Result := '';
  GetWindowThreadProcessId(uchwyt, pid);
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, pid);
  if hProcess <> 0 then
    try
      if GetModuleFileNameEX(hProcess, 0, sciezka, MAX_PATH) <> 0 then Result := sciezka
      else if Win32MajorVersion >= 6 then
      begin
        nSize := MAX_PATH;
        ZeroMemory(@sciezka, MAX_PATH);
        @QueryFullProcessImageName := GetProcAddress(GetModuleHandle('kernel32'), 'QueryFullProcessImageNameW');
        if Assigned(QueryFullProcessImageName) then
          if QueryFullProcessImageName(hProcess, 0, sciezka, @nSize) then Result := sciezka
      end;
    finally
      CloseHandle(hProcess);
    end;
end;

enter image description here

like image 36
mca64 Avatar answered Nov 15 '22 03:11

mca64


As far as I am aware, this approach will fail to retrieve 64 bit process information when the code is executed in a 32 bit process. This sort of problem is common when running inside the WOW64 emulator and the cleanest way to avoid such issues is to run the code outside of the WOW64 emulator. That is, run your code in a 64 bit process.

Other possible ways to work around this, if you cannot re-compile as 64 bit are:

  1. Use a separate 64 bit process, and some IPC, to retrieve the information.
  2. Use WMI to get the module file name.
  3. Use QueryFullProcessImageName.

Another point that I always like to stress, is that error checking is important. You fail to check for errors when you call GetModuleFileNameEx. The calls are clearly failing which is why you end up with an uninitialized text buffer. Always check Windows API calls for errors.

like image 181
David Heffernan Avatar answered Nov 15 '22 02:11

David Heffernan