Search code examples
javawinapijava-native-interfacejna

(Converting c# to Java JNA) - GetModuleFileName from hwnd


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());

Solution

  • 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).