Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GetProcAddress to allow accessing functions exported by ordinal #705

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Features
* [#680](https://github.com/java-native-access/jna/pull/680): Added `SetCurrentProcessExplicitAppUserModelID` and `GetCurrentProcessExplicitAppUserModelID` to `com.sun.jna.platform.win32.Shell32` for setting the [System.AppUserModel.ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391569.aspx) of the host process - [@rednoah](https://github.com/rednoah).
* [#693](https://github.com/java-native-access/jna/pull/693): Bind DDEML (Dynamic Data Exchange Management Library), add a thread implementation that runs a windows message loop - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#702](https://github.com/java-native-access/jna/pull/702): Added `GetClientRect` to `com/sun/jna/platform/win32/User32` - [@Jonatino](https://github.com/Jonatino).
* [#689](https://github.com/java-native-access/jna/pull/689): Add `GetProcAddress(HMODULE, int)` to `com.sun.jna.platform.win32.Kernel32` - [@matthiasblaesing](https://github.com/matthiasblaesing).

Bug Fixes
---------
Expand Down
22 changes: 22 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package com.sun.jna.platform.win32;

import com.sun.jna.LastErrorException;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
Expand Down Expand Up @@ -3353,4 +3354,25 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName,
* flags.
*/
int SetErrorMode(int umode);

/**
* Retrieves the address of an exported function or variable from the
* specified dynamic-link library (DLL).
*
* <p>
* This function is mapped to enable accessing function on win32 systems
* only accessible by their ordinal value.</p>
*
* <p>
* To access functions by their name, please use
* NativeLibrary#getFunction.</p>
*
* @param hmodule A handle to the DLL module that contains the function or
* variable. The LoadLibrary, LoadLibraryEx,
* LoadPackagedLibrary, or GetModuleHandle function returns
* this handle.
* @param ordinal ordinal value of the function export
* @return address of the exported function
*/
Pointer GetProcAddress(HMODULE hmodule, int ordinal) throws LastErrorException;
}
31 changes: 31 additions & 0 deletions contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package com.sun.jna.platform.win32;

import com.sun.jna.Function;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
Expand All @@ -30,6 +31,7 @@

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.NativeMappedConverter;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
Expand Down Expand Up @@ -1158,4 +1160,33 @@ public void testSetErrorMode() {
// Restore to previous state; 0x0001 is now "previous"
assertEquals(Kernel32.INSTANCE.SetErrorMode(previousMode), 0x0001);
}

/**
* Test that a named function on win32 can be equally resolved by its ordinal
* value.
*
* From link.exe /dump /exports c:\\Windows\\System32\\kernel32.dll
*
* 746 2E9 0004FA20 GetTapeStatus
* 747 2EA 0002DB20 GetTempFileNameA
* 748 2EB 0002DB30 GetTempFileNameW
* 749 2EC 0002DB40 GetTempPathA
* 750 2ED 0002DB50 GetTempPathW
* 751 2EE 00026780 GetThreadContext
*
* The tested function is GetTempPathW which is mapped to the ordinal 750.
*/
public void testGetProcAddress() {
NativeLibrary kernel32Library = NativeLibrary.getInstance("kernel32");
// get module handle needed to resolve function pointer via GetProcAddress
HMODULE kernel32Module = Kernel32.INSTANCE.GetModuleHandle("kernel32");

Function namedFunction = kernel32Library.getFunction("GetTempPathW");
long namedFunctionPointerValue = Pointer.nativeValue(namedFunction);

Pointer ordinalFunction = Kernel32.INSTANCE.GetProcAddress(kernel32Module, 750);
long ordinalFunctionPointerValue = Pointer.nativeValue(ordinalFunction);

assertEquals(namedFunctionPointerValue, ordinalFunctionPointerValue);
}
}
25 changes: 23 additions & 2 deletions src/com/sun/jna/Function.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public static Function getFunction(String libraryName, String functionName, int
* @param p Native function pointer
*/
public static Function getFunction(Pointer p) {
return getFunction(p, 0);
return getFunction(p, 0, null);
}

/**
Expand All @@ -159,7 +159,28 @@ public static Function getFunction(Pointer p) {
* Function <a href="#callflags">call flags</a>
*/
public static Function getFunction(Pointer p, int callFlags) {
return new Function(p, callFlags, null);
return getFunction(p, callFlags, null);
}

/**
* Obtain a <code>Function</code> representing a native
* function pointer. In general, this function should be used by dynamic
* languages; Java code should allow JNA to bind to a specific Callback
* interface instead by defining a return type or Structure field type.
*
* <p>The allocated instance represents a pointer to the native
* function pointer.
*
* @param p
* Native function pointer
* @param callFlags
* Function <a href="#callflags">call flags</a>
* @param encoding
* Encoding to use for conversion between Java and native
* strings.
*/
public static Function getFunction(Pointer p, int callFlags, String encoding) {
return new Function(p, callFlags, encoding);
}

// Keep a reference to the NativeLibrary so it does not get garbage
Expand Down