2

I am trying to do exactly what is being done over here: How do I GetModuleFileName() if I only have a window handle (hWnd)?

But in java instead of C#.

So far I have managed to this:

public static final int PROCESS_QUERY_INFORMATION = 0x0400;

public interface User32 extends StdCallLibrary {
    User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
    int GetWindowThreadProcessId(HWND hwnd, IntByReference pid);
};

public interface Kernel32 extends StdCallLibrary {
    Kernel32 INSTANCE = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class);
    public Pointer OpenProcess(int dwDesiredAccess, boolean bInheritHandle, int dwProcessId);
    public int GetTickCount();
};

public interface psapi extends StdCallLibrary {
    psapi INSTANCE = (psapi)Native.loadLibrary("psapi", psapi.class);
    int GetModuleFileNameExA (Pointer process, Pointer hModule, byte[] lpString, int nMaxCount);

};


public static String getModuleFilename(HWND hwnd)
{

    byte[] exePathname = new byte[512];

    Pointer zero = new Pointer(0);
    IntByReference pid = new IntByReference();
    User32.INSTANCE.GetWindowThreadProcessId(hwnd, pid);
    System.out.println("PID is " + pid.getValue());

    Pointer process = Kernel32.INSTANCE.OpenProcess(PROCESS_QUERY_INFORMATION, false, pid.getValue());
    int result = psapi.INSTANCE.GetModuleFileNameExA(process, zero, exePathname, 512);
    String text = Native.toString(exePathname).substring(0, result);
    return text;



}

The window handle that is given is valid, and the PID is always printed successfully. "Process" appears to return a value but the "result" is always zero. Could anyone knowledgeable about JNA kindly show me where my mistake is?

EDIT: Finally, SUCCESS! The problem was this line (where the first value had to be 1040):

Pointer process = Kernel32.INSTANCE.OpenProcess(1040, false, pid.getValue());
Community
  • 1
  • 1
David
  • 15,652
  • 26
  • 115
  • 156
  • Interesting. I assume you mean `0x1040`? According to MSDN, this is the union of `PROCESS_QUERY_LIMITED_INFORMATION` and `PROCESS_DUP_HANDLE`. What happens if you just use `0x1000` (removing the `PROCESS_DUP_HANDLE`)? I am guessing it was switching to `PROCESS_QUERY_LIMITED_INFORMATION` that made the difference. – Matt Solnit Sep 23 '11 at 17:06
  • P.S. This is based on http://msdn.microsoft.com/en-us/library/ms684880(v=VS.85).aspx. – Matt Solnit Sep 23 '11 at 17:07

2 Answers2

4

This may not be the reason it's failing, but I think the dwProcessId parameter should be an int, not IntByReference.

See MSDN (http://msdn.microsoft.com/en-us/library/ms684320(v=VS.85).aspx):

HANDLE WINAPI OpenProcess(
  __in  DWORD dwDesiredAccess,
  __in  BOOL bInheritHandle,
  __in  DWORD dwProcessId
);

It's just a regular DWORD.

Also, you can use GetLastError() to return more information about why the function call failed. Finally, this is a long shot, but your declaration of PROCESS_QUERY_INFORMATION is not included in the code snippet -- make sure it has the correct value (0x0400).

Matt Solnit
  • 32,152
  • 8
  • 53
  • 57
  • Thanks! I got one step closer to the solution. Process is now not giving me null. GetModuleFileNameExA is still failing though. – David Sep 23 '11 at 06:59
  • Interesting. GetLastError() returns access is denied. Not after OpenProcess, but after GetModuleFileNameExA – David Sep 23 '11 at 07:29
1

why all the hassle with the process id ??

quoting from the documention of GetModuleFilename():

hModule [in, optional]:

A handle to the loaded module whose path is being requested. If this parameter is NULL, GetModuleFileName retrieves the path of the executable file of the current process.

if you want the module fileName of the current process, just pass NULL as the process id.

if you want the module filename of another process, you need specific access rights before calling OpenProcess(). changing the access rights is described here, and is quite difficult to achieve (it requires a great amount of steps to lookup the privilege name, get the luid of the privilege, adjust the privileges of the token, etc.)

Adrien Plisson
  • 22,486
  • 6
  • 42
  • 73
  • 1
    I have already found a solution by setting 1040 as the first parameter of OpenProcess(). Thanks for your help though :) – David Sep 23 '11 at 07:47