diff --git a/CHANGES.md b/CHANGES.md index ec9a48084c..e6a95492ec 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 --------- diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java b/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java index c9453fc187..c68111618a 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java @@ -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; @@ -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). + * + *

+ * This function is mapped to enable accessing function on win32 systems + * only accessible by their ordinal value.

+ * + *

+ * To access functions by their name, please use + * NativeLibrary#getFunction.

+ * + * @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; } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java b/contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java index d8cd9cdd3e..f3a9ade920 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java @@ -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; @@ -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; @@ -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); + } } diff --git a/src/com/sun/jna/Function.java b/src/com/sun/jna/Function.java index cb900a5e6d..17df489406 100644 --- a/src/com/sun/jna/Function.java +++ b/src/com/sun/jna/Function.java @@ -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); } /** @@ -159,7 +159,28 @@ public static Function getFunction(Pointer p) { * Function call flags */ public static Function getFunction(Pointer p, int callFlags) { - return new Function(p, callFlags, null); + return getFunction(p, callFlags, null); + } + + /** + * Obtain a Function 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. + * + *

The allocated instance represents a pointer to the native + * function pointer. + * + * @param p + * Native function pointer + * @param callFlags + * Function call flags + * @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