0

The following code fails to find LoadLibraryW

private static FOREIGN_THREAD_START_ROUTINE getLoadLibraryWAddress() throws Win32Exception {
    HMODULE module = Kernel32.INSTANCE.GetModuleHandle("KERNEL32");
    if(module == null) {
        Win32Exception.throwWithLastError("Failed to find KERNEL32 module");
    }

    FOREIGN_THREAD_START_ROUTINE address = Kernel32MissingFunctions.INSTANCE.GetProcAddress(module, "LoadLibraryW");
    if(address == null) {
        Win32Exception.throwWithLastError("Failed to find LoadLibraryW in KERNEL32 module");
    }
    return address;
}

where GetProcAddress is declared as following:

public interface Kernel32MissingFunctions extends StdCallLibrary {

    Kernel32MissingFunctions INSTANCE = (Kernel32MissingFunctions) Native.loadLibrary("kernel32",
            Kernel32MissingFunctions.class, W32APIOptions.UNICODE_OPTIONS);

    public static final int MEM_RELEASE = 0x8000;

    public LPVOID VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, long dwSize, int flAllocationType, int flProtect);

    public int VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, long dwSize, int dwFreeType);

    public FOREIGN_THREAD_START_ROUTINE GetProcAddress(HMODULE hModule, String lpProcName);
}

Does anyone know why? What is my mistake? Thanks!

Ethon
  • 93
  • 2
  • 12
  • What is the last error being reported when `GetProcAddress()` returns null? And why are you declaring `GetProcAddress()` to return a `FOREIGN_THREAD_START_ROUTINE`? That is NOT what the real `GetProcAddress()` actually returns. It returns a `FARPROC`, which is essentially just a pointer, and so would be `LPVOID` in JNA. You would then type-cast the pointer when you need to actually call the function. – Remy Lebeau Aug 04 '16 at 21:33
  • 4
    Are you passing an ANSI string as the seciond argument to the native `GetProcAddress` call? Unlike other WIndows API funkcions, `GetProcAddress` has no unicode version since names of exported functions are written using ANSI characters. – Martin Drab Aug 04 '16 at 23:55

1 Answers1

0

Martin Drab was right. Using W32APIOptions.UNICODE_OPTIONS passed an Unicode string to the Ansi function. Changing the interfaces as following fixed the problem:

public interface Kernel32MissingFunctions extends StdCallLibrary {

    Kernel32MissingFunctions INSTANCE = (Kernel32MissingFunctions) Native.loadLibrary("kernel32",
            Kernel32MissingFunctions.class, W32APIOptions.ASCII_OPTIONS);

    public static final int MEM_RELEASE = 0x8000;

    public LPVOID VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, long dwSize, int flAllocationType, int flProtect);

    public int VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, long dwSize, int dwFreeType);

    public LPVOID GetProcAddress(HMODULE hModule, String lpProcName);
}
Ethon
  • 93
  • 2
  • 12