[Git][java-team/libjna-java][upstream] New upstream version 5.15.0

Emmanuel Bourg (@ebourg) gitlab at salsa.debian.org
Wed Oct 23 16:17:49 BST 2024



Emmanuel Bourg pushed to branch upstream at Debian Java Maintainers / libjna-java


Commits:
4a7b045e by Emmanuel Bourg at 2024-10-23T17:07:19+02:00
New upstream version 5.15.0
- - - - -


30 changed files:

- CHANGES.md
- README.md
- appveyor.yml
- build.xml
- common.xml
- − contrib/platform/platform.iml
- contrib/platform/src/com/sun/jna/platform/unix/X11.java
- contrib/platform/src/com/sun/jna/platform/win32/GDI32.java
- contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java
- contrib/platform/test/com/sun/jna/platform/mac/IOKitTest.java
- contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java
- contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java
- contrib/platform/test/com/sun/jna/platform/win32/Crypt32Test.java
- contrib/platform/test/com/sun/jna/platform/win32/IPHlpAPITest.java
- contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java
- contrib/platform/test/com/sun/jna/platform/win32/Secur32Test.java
- + contrib/platform/test/com/sun/jna/platform/win32/Secur32_Impersonate_Test.java
- contrib/platform/test/com/sun/jna/platform/win32/Win32ServiceDemo.java
- contrib/platform/test/com/sun/jna/platform/win32/WininetUtilTest.java
- native/Makefile
- native/build.xml
- native/callback.c
- native/dispatch.c
- src/com/sun/jna/CallbackReference.java
- src/com/sun/jna/ELFAnalyser.java
- src/com/sun/jna/Native.java
- src/com/sun/jna/Platform.java
- + test/com/sun/jna/NativeGetNativeLibraryTest.java
- test/com/sun/jna/NativeLibraryTest.java
- test/com/sun/jna/PlatformTest.java


Changes:

=====================================
CHANGES.md
=====================================
@@ -2,6 +2,25 @@ NOTE: as of JNA 4.0, JNA is now dual-licensed under LGPL and AL 2.0 (see LICENSE
 
 NOTE: JNI native support is typically incompatible between minor versions, and almost always incompatible between major versions.
 
+Release 5.15.0
+==============
+
+Features
+--------
+* [#1578](https://github.com/java-native-access/jna/pull/1578): Add support for FreeBSD aarch64 - [@alexdupre](https://github.com/alexdupre).
+* [#1593](https://github.com/java-native-access/jna/pull/1593): Add support for DragonFly BSD x86-64 - [@liweitianux](https://github.com/liweitianux).
+* [#1595](https://github.com/java-native-access/jna/pull/1595): Add `IsProcessorFeaturePresent` to `c.s.j.p.win32.Kernel32` - [@dbwiddis](https://github.com/dbwiddis).
+* [#1602](https://github.com/java-native-access/jna/pull/1602): Add `XMoveWindow`, `XResizeWindow`, `XMoveResizeWindow`, `XRaiseWindow`, `XLowerWindow` X11 calls to `c.s.j.p.unix.X11` - [@vinceh121](https://github.com/vinceh121).
+* [#1613](https://github.com/java-native-access/jna/issues/1613): Added static helper method `Native#getNativeLibrary' for getting the underlying NativeLibrary instance from a Library interface instance or from a "registered" class - [@matthiasblaesing](https://github.com/matthiasblaesing).
+* [#1624](https://github.com/java-native-access/jna/pull/1624): Enable linker build-id for android builds - [@mstyura](https://github.com/mstyura).
+
+Bug Fixes
+---------
+* [#1579](https://github.com/java-native-access/jna/issues/1579): Fix analysis of ELF binary on arm systems running with a java ELF binary without section table headers (java8 on armv7 NAS) - [@matthiasblaesing](https://github.com/matthiasblaesing).
+* [#1586](https://github.com/java-native-access/jna/issues/1586): Fix free_callback JNI weak reference leak - [@xiezhaokun](https://github.com/xiezhaokun).
+* [6486c90d913a413f247eef84742ce3c474738933](https://github.com/java-native-access/jna/commit/6486c90d913a413f247eef84742ce3c474738933): Check CallbackReference#cbstruct for null when checking existing Reference - [@matthiasblaesing](https://github.com/matthiasblaesing).
+* [#1622](https://github.com/java-native-access/jna/issues/1622): Add "linux-riscv64" entry to OSGI Bundle-NativeCode header in MANIFEST.MF  - [@matthiasblaesing](https://github.com/matthiasblaesing).
+
 Release 5.14.0
 ==============
 


=====================================
README.md
=====================================
@@ -7,7 +7,7 @@
 Java Native Access (JNA)
 ========================
 
-The definitive JNA reference (including an overview and usage details) is in the [JavaDoc](http://java-native-access.github.io/jna/5.14.0/javadoc/).  Please read the [overview](http://java-native-access.github.io/jna/5.14.0/javadoc/overview-summary.html#overview_description).  Questions, comments, or exploratory conversations should begin on the [mailing list](http://groups.google.com/group/jna-users), although you may find it easier to find answers to already-solved problems on [StackOverflow](http://stackoverflow.com/questions/tagged/jna).
+The definitive JNA reference (including an overview and usage details) is in the [JavaDoc](http://java-native-access.github.io/jna/5.15.0/javadoc/).  Please read the [overview](http://java-native-access.github.io/jna/5.15.0/javadoc/overview-summary.html#overview_description).  Questions, comments, or exploratory conversations should begin on the [mailing list](http://groups.google.com/group/jna-users), although you may find it easier to find answers to already-solved problems on [StackOverflow](http://stackoverflow.com/questions/tagged/jna).
 
 JNA provides Java programs easy access to native shared libraries without writing anything but Java code - no JNI or native code is required. This functionality is comparable to Windows' Platform/Invoke and Python's ctypes.
 
@@ -32,7 +32,8 @@ JNA is a mature library with dozens of contributors and hundreds of commercial a
 - [VLCJ](https://github.com/caprica/vlcj): Java bindings for libVLC.
 - [SVNKit](http://svnkit.com): Pure Java Subversion client library.
 - [OmegaT Computer-Aided Translation](https://omegat.org/).
-- [IntelliJ IDEA](https://www.jetbrains.com/) by JetBrains.
+- [IntelliJ IDEA](https://www.jetbrains.com/idea) by JetBrains.
+- [Jetbrains Toolbox](https://www.jetbrains.com/toolbox-app/) by JetBrains.
 - [Apache NetBeans IDE](https://netbeans.apache.org/) by Apache Software Foundation.
 - [FileBot Media Renamer](http://www.filebot.net) by Reinhard Pointner.
 - [USB for Java](https://launchpad.net/libusb4j) by Mario Boikov.
@@ -65,12 +66,12 @@ Pre-built platform support may be found [here](https://github.com/java-native-ac
 Download
 ========
 
-Version 5.14.0
+Version 5.15.0
 
 JNA
 ---
 
-[![Maven Central](https://img.shields.io/maven-central/v/net.java.dev.jna/jna.svg?label=Maven%20Central)](https://search.maven.org/artifact/net.java.dev.jna/jna/5.14.0/jar) [jna-5.14.0.jar](https://repo1.maven.org/maven2/net/java/dev/jna/jna/5.14.0/jna-5.14.0.jar) [jna-jpms-5.14.0.jar](https://repo1.maven.org/maven2/net/java/dev/jna/jna-jpms/5.14.0/jna-jpms-5.14.0.jar)
+[![Maven Central](https://img.shields.io/maven-central/v/net.java.dev.jna/jna.svg?label=Maven%20Central)](https://search.maven.org/artifact/net.java.dev.jna/jna/5.15.0/jar) [jna-5.15.0.jar](https://repo1.maven.org/maven2/net/java/dev/jna/jna/5.15.0/jna-5.15.0.jar) [jna-jpms-5.15.0.jar](https://repo1.maven.org/maven2/net/java/dev/jna/jna-jpms/5.15.0/jna-jpms-5.15.0.jar)
 
 This is the core artifact of JNA and contains only the binding library and the
 core helper classes.
@@ -78,7 +79,7 @@ core helper classes.
 JNA Platform
 ------------
 
-[![Maven Central](https://img.shields.io/maven-central/v/net.java.dev.jna/jna-platform.svg?label=Maven%20Central)](https://search.maven.org/artifact/net.java.dev.jna/jna-platform/5.14.0/jar) [jna-platform-5.14.0.jar](https://repo1.maven.org/maven2/net/java/dev/jna/jna-platform/5.14.0/jna-platform-5.14.0.jar) [jna-platform-jpms-5.14.0.jar](https://repo1.maven.org/maven2/net/java/dev/jna/jna-platform-jpms/5.14.0/jna-platform-jpms-5.14.0.jar)
+[![Maven Central](https://img.shields.io/maven-central/v/net.java.dev.jna/jna-platform.svg?label=Maven%20Central)](https://search.maven.org/artifact/net.java.dev.jna/jna-platform/5.15.0/jar) [jna-platform-5.15.0.jar](https://repo1.maven.org/maven2/net/java/dev/jna/jna-platform/5.15.0/jna-platform-5.15.0.jar) [jna-platform-jpms-5.15.0.jar](https://repo1.maven.org/maven2/net/java/dev/jna/jna-platform-jpms/5.15.0/jna-platform-jpms-5.15.0.jar)
 
 This artifact holds cross-platform mappings and mappings for a number of commonly used platform
 functions, including a large number of Win32 mappings as well as a set of utility classes
@@ -146,12 +147,12 @@ Using the Library
 * [Platform Library](https://github.com/java-native-access/jna/blob/master/www/PlatformLibrary.md)
 * [Direct Method Mapping](https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md) (Optimization)
 * [Frequently Asked Questions (FAQ)](https://github.com/java-native-access/jna/blob/master/www/FrequentlyAskedQuestions.md)
-* [Avoiding Crashes](http://java-native-access.github.io/jna/5.14.0/javadoc/overview-summary.html#crash-protection)
+* [Avoiding Crashes](http://java-native-access.github.io/jna/5.15.0/javadoc/overview-summary.html#crash-protection)
 
 Primary Documentation (JavaDoc)
 ===============================
 
-The definitive JNA reference is in the [JavaDoc](http://java-native-access.github.io/jna/5.14.0/javadoc/).
+The definitive JNA reference is in the [JavaDoc](http://java-native-access.github.io/jna/5.15.0/javadoc/).
 
 Developers
 ==========


=====================================
appveyor.yml
=====================================
@@ -40,6 +40,7 @@ for:
       only:
         - TARGET_ARCH: x86_64
     before_build:
+        - cmd: set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
         - cmd: '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64'
     before_test:
         - cmd: net start spooler
@@ -52,6 +53,7 @@ for:
       only:
         - TARGET_ARCH: x86
     before_build:
+        - cmd: set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
         - cmd: '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86'
     before_test:
         - cmd: net start spooler
@@ -64,6 +66,7 @@ for:
       only:
         - TARGET_ARCH: aarch64
     before_build:
+        - cmd: set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
         - cmd: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64_arm64'
     test_script:
         - cmd: echo Skipping tests


=====================================
build.xml
=====================================
@@ -101,16 +101,6 @@
   <target name="compile-single" depends="compile"/>
 
   <!-- Prepare additional ant task -->
-  <path id="maven-ant-tasks.classpath">
-      <pathelement location="lib/animal-sniffer-ant-tasks-1.17.jar" />
-      <pathelement location="lib/maven-ant-tasks-2.1.3.jar" />
-  </path>
-  <typedef resource="org/apache/maven/artifact/ant/antlib.xml"
-           uri="antlib:org.apache.maven.artifact.ant"
-           classpathref="maven-ant-tasks.classpath" />
-  <typedef resource="org/codehaus/mojo/animal_sniffer/antlib.xml"
-           uri="antlib:org.codehaus.mojo.animal_sniffer"
-           classpathref="maven-ant-tasks.classpath" />
 
   <target name="-prepare-anttools">
       <subant antfile="build-ant-tools.xml" buildpath="${basedir}"></subant>
@@ -396,11 +386,18 @@ com/sun/jna/linux-s390x/libjnidispatch.so;
 processor=S390x;osname=linux,
 com/sun/jna/linux-loongarch64/libjnidispatch.so;
 processor=loongarch64;osname=linux,
+com/sun/jna/linux-riscv64/libjnidispatch.so;
+processor=riscv64;osname=linux,
+
+com/sun/jna/dragonflybsd-x86-64/libjnidispatch.so;
+processor=x86-64;osname=dragonflybsd,
 
 com/sun/jna/freebsd-x86/libjnidispatch.so;
 processor=x86;osname=freebsd,
 com/sun/jna/freebsd-x86-64/libjnidispatch.so;
 processor=x86-64;osname=freebsd,
+com/sun/jna/freebsd-aarch64/libjnidispatch.so;
+processor=aarch64;osname=freebsd,
 
 com/sun/jna/openbsd-x86/libjnidispatch.so;
 processor=x86;osname=openbsd,
@@ -526,12 +523,18 @@ osname=macosx;processor=aarch64
       <zipfileset src="${lib.native}/sunos-sparcv9.jar"
                   includes="*jnidispatch*"
                   prefix="com/sun/jna/sunos-sparcv9"/>
+      <zipfileset src="${lib.native}/dragonflybsd-x86-64.jar"
+                  includes="*jnidispatch*"
+                  prefix="com/sun/jna/dragonflybsd-x86-64"/>
       <zipfileset src="${lib.native}/freebsd-x86.jar"
                   includes="*jnidispatch*"
                   prefix="com/sun/jna/freebsd-x86"/>
       <zipfileset src="${lib.native}/freebsd-x86-64.jar"
                   includes="*jnidispatch*"
                   prefix="com/sun/jna/freebsd-x86-64"/>
+      <zipfileset src="${lib.native}/freebsd-aarch64.jar"
+                  includes="*jnidispatch*"
+                  prefix="com/sun/jna/freebsd-aarch64"/>
       <zipfileset src="${lib.native}/openbsd-x86.jar"
                   includes="*jnidispatch*"
                   prefix="com/sun/jna/openbsd-x86"/>
@@ -718,8 +721,10 @@ osname=macosx;processor=aarch64
     <copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/linux-loongarch64.jar" overwrite="true"/>
     <copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/linux-s390x.jar" overwrite="true"/>
     <copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/linux-riscv64.jar" overwrite="true"/>
+    <copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/dragonflybsd-x86-64.jar" overwrite="true"/>
     <copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/freebsd-x86.jar" overwrite="true"/>
     <copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/freebsd-x86-64.jar" overwrite="true"/>
+    <copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/freebsd-aarch64.jar" overwrite="true"/>
     <copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/openbsd-x86.jar" overwrite="true"/>
     <copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/openbsd-x86-64.jar" overwrite="true"/>
     <copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/sunos-x86.jar" overwrite="true"/>
@@ -903,6 +908,7 @@ osname=macosx;processor=aarch64
     </condition>
     <condition property="make" value="gmake">
       <or>
+        <equals arg1="${build.os.name}" arg2="DragonFlyBSD"/>
         <equals arg1="${build.os.name}" arg2="FreeBSD"/>
         <equals arg1="${build.os.name}" arg2="OpenBSD"/>
         <equals arg1="${build.os.name}" arg2="NetBSD"/>
@@ -1393,50 +1399,50 @@ cd ..
     </subant>
   </target>
 
-  <target name="install" depends="dist,-bootstrap-maven" description="Install jna and jna-platform artifacts into local maven repository">
-    <artifact:mvn failonerror="true">
+  <target name="install" depends="dist" description="Install jna and jna-platform artifacts into local maven repository">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-install-plugin:2.5:install-file"/>
       <arg value="-DpomFile=${pom}"/>
       <arg value="-Dfile=${dist-jar}"/>
       <arg value="-Dsources=${maven-sources-jar}"/>
       <arg value="-Djavadoc=${maven-javadoc-jar}"/>
-    </artifact:mvn>
+    </exec>
 
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-install-plugin:2.5:install-file"/>
       <arg value="-DpomFile=${pom}"/>
       <arg value="-Dfile=${dist-aar}"/>
       <arg value="-Dpackaging=aar"/>
-    </artifact:mvn>
+    </exec>
 
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-install-plugin:2.5:install-file"/>
       <arg value="-DpomFile=${pom-jpms}"/>
       <arg value="-Dfile=${dist-jar-jpms}"/>
       <arg value="-Dsources=${maven-sources-jar}"/>
       <arg value="-Djavadoc=${maven-javadoc-jar}"/>
-    </artifact:mvn>
+    </exec>
 
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-install-plugin:2.5:install-file"/>
       <arg value="-DpomFile=${pom-platform}"/>
       <arg value="-Dfile=${platform-jar}"/>
       <arg value="-Dsources=${platform-sources-jar}"/>
       <arg value="-Djavadoc=${platform-javadoc-jar}"/>
-    </artifact:mvn>
+    </exec>
 
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-install-plugin:2.5:install-file"/>
       <arg value="-DpomFile=${pom-platform-jpms}"/>
       <arg value="-Dfile=${platform-jpms-jar}"/>
       <arg value="-Dsources=${platform-sources-jar}"/>
       <arg value="-Djavadoc=${platform-javadoc-jar}"/>
-    </artifact:mvn>
+    </exec>
   </target>
 
   <!-- NOTE: The 'deploy' target works only if the version (jna.version in build.xml) ends in '-SNAPSHOT'. -->
-  <target name="deploy" depends="dist,-bootstrap-maven" description="deploy snapshot version to Maven snapshot repository">
-    <artifact:mvn failonerror="true">
+  <target name="deploy" depends="dist" description="deploy snapshot version to Maven snapshot repository">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy-file"/>
       <arg value="-Durl=${maven-snapshots-repository-url}"/>
       <arg value="-DrepositoryId=${maven-snapshots-repository-id}"/>
@@ -1445,9 +1451,9 @@ cd ..
       <arg value="-Dfiles=${maven-sources-jar},${maven-javadoc-jar},${dist-aar}"/>
       <arg value="-Dtypes=jar,jar,aar"/>
       <arg value="-Dclassifiers=sources,javadoc,"/>
-    </artifact:mvn>
+    </exec>
 
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy-file"/>
       <arg value="-Durl=${maven-snapshots-repository-url}"/>
       <arg value="-DrepositoryId=${maven-snapshots-repository-id}"/>
@@ -1456,9 +1462,9 @@ cd ..
       <arg value="-Dfiles=${platform-sources-jar},${platform-javadoc-jar}"/>
       <arg value="-Dtypes=jar,jar"/>
       <arg value="-Dclassifiers=sources,javadoc"/>
-    </artifact:mvn>
+    </exec>
 
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy-file"/>
       <arg value="-Durl=${maven-snapshots-repository-url}"/>
       <arg value="-DrepositoryId=${maven-snapshots-repository-id}"/>
@@ -1467,9 +1473,9 @@ cd ..
       <arg value="-Dfiles=${maven-sources-jar},${maven-javadoc-jar}"/>
       <arg value="-Dtypes=jar,jar"/>
       <arg value="-Dclassifiers=sources,javadoc"/>
-    </artifact:mvn>
+    </exec>
 
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy-file"/>
       <arg value="-Durl=${maven-snapshots-repository-url}"/>
       <arg value="-DrepositoryId=${maven-snapshots-repository-id}"/>
@@ -1478,15 +1484,15 @@ cd ..
       <arg value="-Dfiles=${platform-sources-jar},${platform-javadoc-jar}"/>
       <arg value="-Dtypes=jar,jar"/>
       <arg value="-Dclassifiers=sources,javadoc"/>
-    </artifact:mvn>
+    </exec>
   </target>
 
 
   <property name="version-maven-gpg-plugin" value="1.4"/>
 
-  <target name="stage" depends="dist,-bootstrap-maven" description="deploy release version to Maven staging repository">
+  <target name="stage" depends="dist" description="deploy release version to Maven staging repository">
     <!-- sign and deploy the jna,  artifact -->
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-gpg-plugin:${version-maven-gpg-plugin}:sign-and-deploy-file"/>
       <arg value="-Durl=${maven-staging-repository-url}"/>
       <arg value="-DrepositoryId=${maven-staging-repository-id}"/>
@@ -1496,10 +1502,10 @@ cd ..
       <arg value="-Dclassifiers=sources,javadoc,"/>
       <arg value="-Dtypes=jar,jar,aar"/>
       <arg value="-Dgpg.useagent=true"/>
-    </artifact:mvn>
+    </exec>
 
     <!-- sign and deploy the platform artifact -->
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-gpg-plugin:${version-maven-gpg-plugin}:sign-and-deploy-file"/>
       <arg value="-Durl=${maven-staging-repository-url}"/>
       <arg value="-DrepositoryId=${maven-staging-repository-id}"/>
@@ -1509,10 +1515,10 @@ cd ..
       <arg value="-Dclassifiers=sources,javadoc"/>
       <arg value="-Dtypes=jar,jar"/>
       <arg value="-Dgpg.useagent=true"/>
-    </artifact:mvn>
+    </exec>
 
     <!-- sign and deploy the jna,  artifact -->
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-gpg-plugin:${version-maven-gpg-plugin}:sign-and-deploy-file"/>
       <arg value="-Durl=${maven-staging-repository-url}"/>
       <arg value="-DrepositoryId=${maven-staging-repository-id}"/>
@@ -1522,10 +1528,10 @@ cd ..
       <arg value="-Dtypes=jar,jar"/>
       <arg value="-Dclassifiers=sources,javadoc"/>
       <arg value="-Dgpg.useagent=true"/>
-    </artifact:mvn>
+    </exec>
 
     <!-- sign and deploy the platform artifact -->
-    <artifact:mvn failonerror="true">
+    <exec executable="mvn" searchpath="true" failonerror="true" failifexecutionfails="true" logError="true">
       <arg value="org.apache.maven.plugins:maven-gpg-plugin:${version-maven-gpg-plugin}:sign-and-deploy-file"/>
       <arg value="-Durl=${maven-staging-repository-url}"/>
       <arg value="-DrepositoryId=${maven-staging-repository-id}"/>
@@ -1535,29 +1541,7 @@ cd ..
       <arg value="-Dtypes=jar,jar"/>
       <arg value="-Dclassifiers=sources,javadoc"/>
       <arg value="-Dgpg.useagent=true"/>
-    </artifact:mvn>
-  </target>
-
-  <target name="-bootstrap-maven">
-      <artifact:remoteRepository id="remote.mavenCentral" url="https://repo1.maven.org/maven2/" />
-      <artifact:dependencies pathId="dependency.dummy">
-          <remoteRepository refid="remote.mavenCentral" />
-          <dependency groupId="org.apache.maven.plugins" artifactId="maven-gpg-plugin" version="1.4" type="maven-plugin"/>
-          <dependency groupId="org.apache.maven.plugins" artifactId="maven-deploy-plugin" version="2.7" type="maven-plugin"/>
-          <dependency groupId="org.apache.maven.plugins" artifactId="maven-install-plugin" version="2.5" type="maven-plugin"/>
-          <dependency groupId="org.apache.maven" artifactId="apache-maven" version="2.0.10" />
-          <dependency groupId="org.apache.maven" artifactId="maven-model" version="2.0.10" />
-          <dependency groupId="org.apache.maven" artifactId="maven-artifact" version="2.0.10" />
-          <dependency groupId="org.apache.maven" artifactId="maven-project" version="2.0.10" />
-          <dependency groupId="org.apache.maven" artifactId="maven-artifact-manager" version="2.0.10" />
-          <dependency groupId="org.apache.maven" artifactId="maven-plugin-registry" version="2.0.10" />
-          <dependency groupId="org.apache.maven" artifactId="maven-plugin-api" version="2.0.10" />
-          <dependency groupId="org.codehaus.plexus" artifactId="plexus-utils" version="3.0.15" />
-      </artifact:dependencies>
-      <artifact:dependencies pathId="dependency.dummy2">
-          <remoteRepository refid="remote.mavenCentral" />
-          <dependency groupId="org.codehaus.plexus" artifactId="plexus-utils" version="1.5.5" />
-      </artifact:dependencies>
+    </exec>
   </target>
 
   <target name="checkstyle">


=====================================
common.xml
=====================================
@@ -9,7 +9,7 @@
 
     <!-- JNA library release version - android versionCode is derived from mjar/minor/revision -->
     <property name="jna.major" value="5"/>
-    <property name="jna.minor" value="14"/>
+    <property name="jna.minor" value="15"/>
     <property name="jna.revision" value="0"/>
     <property name="jna.build" value="0"/> <!--${build.number}-->
     <condition property="version.suffix" value="" else="-SNAPSHOT">
@@ -23,7 +23,7 @@
     <!-- jnidispatch library release version -->
     <property name="jni.major" value="7"/>
     <property name="jni.minor" value="0"/>
-    <property name="jni.revision" value="0"/>
+    <property name="jni.revision" value="2"/>
     <property name="jni.build" value="0"/> <!--${build.number}-->
     <property name="jni.version" value="${jni.major}.${jni.minor}.${jni.revision}"/>
     <property name="jni.md5" value="5fb98531302accd485c534c452dd952a"/>
@@ -99,6 +99,9 @@
     <condition property="os.prefix" value="sunos-${jre.arch}">
       <equals arg1="${build.os.name}" arg2="SunOS"/>
     </condition>
+    <condition property="os.prefix" value="dragonflybsd-${jre.arch}">
+      <equals arg1="${build.os.name}" arg2="DragonFlyBSD"/>
+    </condition>
     <condition property="os.prefix" value="freebsd-${jre.arch}">
       <equals arg1="${build.os.name}" arg2="FreeBSD"/>
     </condition>


=====================================
contrib/platform/platform.iml deleted
=====================================
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-  </component>
-</module>
-


=====================================
contrib/platform/src/com/sun/jna/platform/unix/X11.java
=====================================
@@ -900,6 +900,12 @@ public interface X11 extends Library {
     boolean XTranslateCoordinates(Display display, Window src_w, Window dest_w, int src_x, int src_y,
                                   IntByReference dest_x_return, IntByReference dest_y_return, WindowByReference child_return);
 
+    int XMoveWindow(Display display, Window w, int x, int y);
+    int XResizeWindow(Display display, Window w, int width, int height);
+    int XMoveResizeWindow(Display display, Window w, int x, int y, int width, int height);
+    int XRaiseWindow(Display display, Window w);
+    int XLowerWindow(Display display, Window w);
+
     /*****************************************************************
      * RESERVED RESOURCE AND CONSTANT DEFINITIONS
      *****************************************************************/


=====================================
contrib/platform/src/com/sun/jna/platform/win32/GDI32.java
=====================================
@@ -322,7 +322,7 @@ public interface GDI32 extends StdCallLibrary {
      */
     int GetDeviceCaps(HDC hdc, int nIndex);
 
-    /** The GetDIBits function retrieves the bits fo the specified compatible
+    /** The GetDIBits function retrieves the bits of the specified compatible
      * bitmap and copies them into a buffer as a DIB using the specified
      * format.
      * @param hdc A handle to the device context.


=====================================
contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java
=====================================
@@ -106,6 +106,54 @@ public interface Kernel32 extends StdCallLibrary, WinNT, Wincon {
      */
     int THREAD_PRIORITY_ERROR_RETURN = 0x7FFFFFFF;
 
+    /**
+     * Processor Feature flags
+     */
+    int PF_FLOATING_POINT_PRECISION_ERRATA = 0;
+    int PF_FLOATING_POINT_EMULATED = 1;
+    int PF_COMPARE_EXCHANGE_DOUBLE = 2;
+    int PF_MMX_INSTRUCTIONS_AVAILABLE = 3;
+    int PF_PPC_MOVEMEM_64BIT_OK = 4;
+    int PF_ALPHA_BYTE_INSTRUCTIONS = 5;
+    int PF_XMMI_INSTRUCTIONS_AVAILABLE = 6;
+    int PF_3DNOW_INSTRUCTIONS_AVAILABLE = 7;
+    int PF_RDTSC_INSTRUCTION_AVAILABLE = 8;
+    int PF_PAE_ENABLED = 9;
+    int PF_XMMI64_INSTRUCTIONS_AVAILABLE = 10;
+    int PF_SSE_DAZ_MODE_AVAILABLE = 11;
+    int PF_NX_ENABLED = 12;
+    int PF_SSE3_INSTRUCTIONS_AVAILABLE = 13;
+    int PF_COMPARE_EXCHANGE128 = 14;
+    int PF_COMPARE64_EXCHANGE128 = 15;
+    int PF_CHANNELS_ENABLED = 16;
+    int PF_XSAVE_ENABLED = 17;
+    int PF_ARM_VFP_32_REGISTERS_AVAILABLE = 18;
+    int PF_ARM_NEON_INSTRUCTIONS_AVAILABLE = 19;
+    int PF_SECOND_LEVEL_ADDRESS_TRANSLATION = 20;
+    int PF_VIRT_FIRMWARE_ENABLED = 21;
+    int PF_RDWRFSGSBASE_AVAILABLE = 22;
+    int PF_FASTFAIL_AVAILABLE = 23;
+    int PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE = 24;
+    int PF_ARM_64BIT_LOADSTORE_ATOMIC = 25;
+    int PF_ARM_EXTERNAL_CACHE_AVAILABLE = 26;
+    int PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE = 27;
+    int PF_RDRAND_INSTRUCTION_AVAILABLE = 28;
+    int PF_ARM_V8_INSTRUCTIONS_AVAILABLE = 29;
+    int PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE = 30;
+    int PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE = 31;
+    int PF_RDTSCP_INSTRUCTION_AVAILABLE = 32;
+    int PF_RDPID_INSTRUCTION_AVAILABLE = 33;
+    int PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE = 34;
+    int PF_SSSE3_INSTRUCTIONS_AVAILABLE = 36;
+    int PF_SSE4_1_INSTRUCTIONS_AVAILABLE = 37;
+    int PF_SSE4_2_INSTRUCTIONS_AVAILABLE = 38;
+    int PF_AVX_INSTRUCTIONS_AVAILABLE = 39;
+    int PF_AVX2_INSTRUCTIONS_AVAILABLE = 40;
+    int PF_AVX512F_INSTRUCTIONS_AVAILABLE = 41;
+    int PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE = 43;
+    int PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE = 44;
+    int PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE = 45;
+
     /**
      * Reads data from the specified file or input/output (I/O) device. Reads
      * occur at the position specified by the file pointer if supported by the
@@ -4464,4 +4512,14 @@ public interface Kernel32 extends StdCallLibrary, WinNT, Wincon {
      * </p>
      */
     boolean VirtualUnlock(Pointer lpAddress, SIZE_T dwSize);
+
+    /**
+     * Determines whether the specified processor feature is supported by the current computer.
+     *
+     * @param ProcessorFeature The processor feature to be tested.
+     * @return If the feature is supported, the return value is true. If the feature is not supported, the return value
+     *         is false. If the HAL does not support detection of the feature, whether or not the hardware supports the
+     *         feature, the return value is also false.
+     */
+    boolean IsProcessorFeaturePresent(int ProcessorFeature);
 }


=====================================
contrib/platform/test/com/sun/jna/platform/mac/IOKitTest.java
=====================================
@@ -103,7 +103,8 @@ public class IOKitTest {
         String serialNumberViaUtil = platformExpert.getStringProperty("IOPlatformSerialNumber");
         assertEquals(serialNumber, serialNumberViaUtil);
 
-        assertEquals(12, serialNumber.length());
+        assertTrue("Known serial number lengths are 10 and 12, was: " + serialNumber.length(),
+                serialNumber.length() == 12 || serialNumber.length() == 10);
         // Get all the keys
         dict = platformExpert.createCFProperties();
         assertNotEquals(0, dict.getValueIfPresent(serialKey, null));
@@ -214,7 +215,7 @@ public class IOKitTest {
         int masterPort = IOKitUtil.getMasterPort();
 
         IOService smcService = IOKitUtil.getMatchingService("AppleSMC");
-        assertNotNull(smcService);
+        assumeTrue(smcService != null); // Service is not available on github M1 runners
 
         PointerByReference connPtr = new PointerByReference();
         int taskSelf = SYS.mach_task_self();


=====================================
contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java
=====================================
@@ -1950,12 +1950,14 @@ public class Advapi32Test extends TestCase {
 
         // decrypt a read only file
         file.setWritable(false);
-        assertFalse(Advapi32.INSTANCE.DecryptFile(lpFileName, new DWORD(0)));
-        assertEquals(WinError.ERROR_FILE_READ_ONLY, Kernel32.INSTANCE.GetLastError());
+        boolean successful = Advapi32.INSTANCE.DecryptFile(lpFileName, new DWORD(0));
+        if(! successful) {
+            assertEquals(WinError.ERROR_FILE_READ_ONLY, Kernel32.INSTANCE.GetLastError());
 
-        // decrypt
-        file.setWritable(true);
-        assertTrue(Advapi32.INSTANCE.DecryptFile(lpFileName, new DWORD(0)));
+            // decrypt
+            file.setWritable(true);
+            assertTrue(Advapi32.INSTANCE.DecryptFile(lpFileName, new DWORD(0)));
+        }
 
         file.delete();
     }
@@ -2170,4 +2172,5 @@ public class Advapi32Test extends TestCase {
         // should fail with "the user name or password is incorrect" (error 1326)
         assertEquals("GetLastError() should have returned ERROR_LOGON_FAILURE because the username was bogus.", W32Errors.ERROR_LOGON_FAILURE, Native.getLastError());
     }
+
 }


=====================================
contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java
=====================================
@@ -23,13 +23,18 @@
 package com.sun.jna.platform.win32.COM;
 
 import com.sun.jna.Pointer;
+import com.sun.jna.platform.win32.Guid;
 import com.sun.jna.platform.win32.Ole32;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
+import com.sun.jna.platform.win32.OleAuto;
 import com.sun.jna.platform.win32.Variant;
 import com.sun.jna.platform.win32.Variant.VARIANT;
+import com.sun.jna.platform.win32.WTypes;
 import com.sun.jna.platform.win32.WinDef.LONG;
+import com.sun.jna.platform.win32.WinNT;
+import com.sun.jna.ptr.PointerByReference;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 import org.junit.After;
 import org.junit.Before;
@@ -39,16 +44,41 @@ import static org.junit.Assert.*;
 
 public class ShellApplicationWindowsTest {
 
+    private static final Guid.CLSID CLSID_InternetExplorer = new Guid.CLSID("{0002DF01-0000-0000-C000-000000000046}");
+
     static {
         ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
     }
 
+    private PointerByReference ieApp;
+    private Dispatch ieDispatch;
+
     @Before
     public void setUp() throws Exception {
-        Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
+        WinNT.HRESULT hr;
 
-        // Launch IE in a manner that should ensure it opens even if the system default browser is Chrome, Firefox, or something else.
-        Runtime.getRuntime().exec("cmd /c start iexplore.exe -nohome \"about:blank\"");
+        hr = Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
+        COMUtils.checkRC(hr);
+
+        // IE can not be launched directly anymore - so load it via COM
+
+        ieApp = new PointerByReference();
+        hr = Ole32.INSTANCE
+                .CoCreateInstance(CLSID_InternetExplorer, null, WTypes.CLSCTX_SERVER, IDispatch.IID_IDISPATCH, ieApp);
+        COMUtils.checkRC(hr);
+
+        ieDispatch = new Dispatch(ieApp.getValue());
+        InternetExplorer ie = new InternetExplorer(ieDispatch);
+
+        ie.setProperty("Visible", true);
+        COMUtils.checkRC(hr);
+
+        VARIANT url = new VARIANT("about:blank");
+        VARIANT result = ie.invoke("Navigate", url);
+        OleAuto.INSTANCE.VariantClear(url);
+        OleAuto.INSTANCE.VariantClear(result);
+
+        ieDispatch.Release();
 
         // Even when going to "about:blank", IE still needs a few seconds to start up and add itself to Shell.Application.Windows
         // Removing this delay will cause the test to fail even on the fastest boxes I can find.
@@ -85,6 +115,7 @@ public class ShellApplicationWindowsTest {
     @After
     public void tearDown() throws Exception
     {
+        Ole32.INSTANCE.CoUninitialize();
         Runtime.getRuntime().exec("taskkill.exe /f /im iexplore.exe");
     }
 


=====================================
contrib/platform/test/com/sun/jna/platform/win32/Crypt32Test.java
=====================================
@@ -468,7 +468,6 @@ public class Crypt32Test extends TestCase {
                 assertNotNull(ctx.pCertInfo.Subject);
                 assertFalse(decodeName(ctx.pCertInfo.Issuer).isEmpty());
                 assertFalse(decodeName(ctx.pCertInfo.Subject).isEmpty());
-                assertEquals(decodeName(ctx.pCertInfo.Issuer), decodeName(ctx.pCertInfo.Subject));
                 // System.out.printf("%20s: %s%n", "Issuer", decodeName(ctx.pCertInfo.Issuer));
                 // System.out.printf("%20s: %s%n", "Subject", decodeName(ctx.pCertInfo.Subject));
                 readCertificates++;


=====================================
contrib/platform/test/com/sun/jna/platform/win32/IPHlpAPITest.java
=====================================
@@ -163,26 +163,51 @@ public class IPHlpAPITest {
 
     @Test
     public void testGetUdpStatistics() {
+        // The Math.min constructs when checking dwNoPorts + dwInErrors in
+        // comparison to dwInDatagramsis is used, because at least on
+        // appveyor inconsistent numbers were observed, rendering harder
+        // constaints useless.
+        // Sample:
+        // Datagrams received with errors (332) or no port (2) should be less than inbound datagrams (97).
+
         MIB_UDPSTATS stats = new MIB_UDPSTATS();
         int err = IPHlpAPI.INSTANCE.GetUdpStatistics(stats);
         assertEquals(String.format("Error %d calling GetUdpStatistics.", err), WinError.NO_ERROR, err);
-        assertTrue("Datagrams received with errors or no port should be less than inbound datagrams.",
-                stats.dwNoPorts + stats.dwInErrors <= stats.dwInDatagrams);
+        assertTrue(
+                String.format("Datagrams received with errors (%d) or no port (%d) should be less than inbound datagrams (%d).",
+                    stats.dwNoPorts, stats.dwInErrors, stats.dwInDatagrams
+                ),
+                Math.min(1, stats.dwNoPorts + stats.dwInErrors) <= stats.dwInDatagrams
+        );
 
         // Above should roughly match IPv4 stats with Ex version
         MIB_UDPSTATS stats4 = new MIB_UDPSTATS();
         err = IPHlpAPI.INSTANCE.GetUdpStatisticsEx(stats4, IPHlpAPI.AF_INET);
         assertEquals(String.format("Error %d calling GetUdpStatistics.", err), WinError.NO_ERROR, err);
         assertTrue(
-                "Datagrams received with no port should not decrease between calls to GetUdpStatistics and GetUdpStatisticsEx",
-                stats.dwNoPorts <= stats4.dwNoPorts);
+                String.format(
+                    "Datagrams received with no port should not decrease between calls to GetUdpStatistics (%d) and GetUdpStatisticsEx (%d)",
+                    stats.dwNoPorts,stats4.dwNoPorts
+                ),
+                stats.dwNoPorts <= stats4.dwNoPorts
+        );
         assertTrue(
-                "Datagrams received with errors should not decrease between calls to GetUdpStatistics and GetUdpStatisticsEx",
+                String.format(
+                    "Datagrams received with errors should not decrease between calls to GetUdpStatistics (%d) and GetUdpStatisticsEx (%d)",
+                    stats.dwInErrors, stats4.dwInErrors
+                ),
                 stats.dwInErrors <= stats4.dwInErrors);
-        assertTrue("Datagrams received should not decrease between calls to GetUdpStatistics and GetUdpStatisticsEx",
+        assertTrue(
+                String.format(
+                    "Datagrams received should not decrease between calls to GetUdpStatistics (%d) and GetUdpStatisticsEx (%d)",
+                    stats.dwInDatagrams, stats4.dwInDatagrams
+                ),
                 stats.dwInDatagrams <= stats4.dwInDatagrams);
-        assertTrue("Datagrams received with errors or no port should be less than inbound datagrams.",
-                stats4.dwNoPorts + stats4.dwInErrors <= stats4.dwInDatagrams);
+        assertTrue(
+                String.format("Datagrams received with errors (%d) or no port (%d) should be less than inbound datagrams (%d). (Ex-Version)",
+                    stats4.dwNoPorts, stats4.dwInErrors, stats4.dwInDatagrams
+                ),
+                Math.min(1, stats4.dwNoPorts + stats4.dwInErrors) <= stats4.dwInDatagrams);
     }
 
     @Test


=====================================
contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java
=====================================
@@ -2099,4 +2099,13 @@ public class Kernel32Test extends TestCase {
         final HANDLE selfHandle = Kernel32.INSTANCE.GetCurrentThread();
         assertTrue(Kernel32.INSTANCE.SetThreadPriority(selfHandle, Kernel32.THREAD_PRIORITY_ABOVE_NORMAL));
     }
+
+    public void testIsProcessorFeaturePresent() {
+        // Always returns false for Windows 7 or later
+        assertFalse(Kernel32.INSTANCE.IsProcessorFeaturePresent(Kernel32.PF_FLOATING_POINT_PRECISION_ERRATA));
+        // Always true in 64 bit, requirement to run Windows
+        assertTrue(Kernel32.INSTANCE.IsProcessorFeaturePresent(Kernel32.PF_MMX_INSTRUCTIONS_AVAILABLE));
+        // Invalid values always return false
+        assertFalse(Kernel32.INSTANCE.IsProcessorFeaturePresent(-1));
+    }
 }


=====================================
contrib/platform/test/com/sun/jna/platform/win32/Secur32Test.java
=====================================
@@ -190,84 +190,6 @@ public class Secur32Test extends TestCase {
                 phClientCredential));
     }
 
-    public void testImpersonateRevertSecurityContext() {
-        // client ----------- acquire outbound credential handle
-        CredHandle phClientCredential = new CredHandle();
-        TimeStamp ptsClientExpiry = new TimeStamp();
-        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
-                null, "Negotiate", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
-                null, phClientCredential, ptsClientExpiry));
-        // client ----------- security context
-        CtxtHandle phClientContext = new CtxtHandle();
-        IntByReference pfClientContextAttr = new IntByReference();
-        // server ----------- acquire inbound credential handle
-        CredHandle phServerCredential = new CredHandle();
-        TimeStamp ptsServerExpiry = new TimeStamp();
-        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
-                null, "Negotiate", Sspi.SECPKG_CRED_INBOUND, null, null, null,
-                null, phServerCredential, ptsServerExpiry));
-        // server ----------- security context
-        CtxtHandle phServerContext = new CtxtHandle();
-        ManagedSecBufferDesc pbServerToken = null;
-        IntByReference pfServerContextAttr = new IntByReference();
-        int clientRc = W32Errors.SEC_I_CONTINUE_NEEDED;
-        int serverRc = W32Errors.SEC_I_CONTINUE_NEEDED;
-        do {
-            // client ----------- initialize security context, produce a client token
-            // client token returned is always new
-            ManagedSecBufferDesc pbClientToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
-            if (clientRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
-                // server token is empty the first time
-                ManagedSecBufferDesc pbServerTokenCopy = pbServerToken == null
-                        ? null : new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbServerToken.getBuffer(0).getBytes());
-                clientRc = Secur32.INSTANCE.InitializeSecurityContext(
-                        phClientCredential,
-                        phClientContext.isNull() ? null : phClientContext,
-                        Advapi32Util.getUserName(),
-                        Sspi.ISC_REQ_CONNECTION,
-                        0,
-                        Sspi.SECURITY_NATIVE_DREP,
-                        pbServerTokenCopy,
-                        0,
-                        phClientContext,
-                        pbClientToken,
-                        pfClientContextAttr,
-                        null);
-                assertTrue(clientRc == W32Errors.SEC_I_CONTINUE_NEEDED || clientRc == W32Errors.SEC_E_OK);
-            }
-            // server ----------- accept security context, produce a server token
-            if (serverRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
-                pbServerToken = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
-                ManagedSecBufferDesc pbClientTokenByValue = new ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbClientToken.getBuffer(0).getBytes());
-                serverRc = Secur32.INSTANCE.AcceptSecurityContext(phServerCredential,
-                        phServerContext.isNull() ? null : phServerContext,
-                        pbClientTokenByValue,
-                        Sspi.ISC_REQ_CONNECTION,
-                        Sspi.SECURITY_NATIVE_DREP,
-                        phServerContext,
-                        pbServerToken,
-                        pfServerContextAttr,
-                        ptsServerExpiry);
-                assertTrue(serverRc == W32Errors.SEC_I_CONTINUE_NEEDED || serverRc == W32Errors.SEC_E_OK);
-            }
-        } while (serverRc != W32Errors.SEC_E_OK || clientRc != W32Errors.SEC_E_OK);
-        // impersonate
-        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.ImpersonateSecurityContext(
-                phServerContext));
-        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.RevertSecurityContext(
-                phServerContext));
-        // release server context
-        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
-                phServerContext));
-        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
-                phServerCredential));
-        // release client context
-        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
-                phClientContext));
-        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
-                phClientCredential));
-    }
-
     public void testEnumerateSecurityPackages() {
         IntByReference pcPackages = new IntByReference();
         PSecPkgInfo.ByReference pPackageInfo = new PSecPkgInfo.ByReference();


=====================================
contrib/platform/test/com/sun/jna/platform/win32/Secur32_Impersonate_Test.java
=====================================
@@ -0,0 +1,113 @@
+/* Copyright (c) 2010 Daniel Doubrovkine, All Rights Reserved
+ *
+ * The contents of this file is dual-licensed under 2
+ * alternative Open Source/Free licenses: LGPL 2.1 or later and
+ * Apache License 2.0. (starting with JNA version 4.0.0).
+ *
+ * You can freely decide which license you want to apply to
+ * the project.
+ *
+ * You may obtain a copy of the LGPL License at:
+ *
+ * http://www.gnu.org/licenses/licenses.html
+ *
+ * A copy is also included in the downloadable source code package
+ * containing JNA, in file "LGPL2.1".
+ *
+ * You may obtain a copy of the Apache License at:
+ *
+ * http://www.apache.org/licenses/
+ *
+ * A copy is also included in the downloadable source code package
+ * containing JNA, in file "AL2.0".
+ */
+package com.sun.jna.platform.win32;
+
+import com.sun.jna.ptr.IntByReference;
+import org.junit.Test;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+
+public class Secur32_Impersonate_Test {
+
+    @Test
+    public void testImpersonateRevertSecurityContext() {
+        // client ----------- acquire outbound credential handle
+        Sspi.CredHandle phClientCredential = new Sspi.CredHandle();
+        Sspi.TimeStamp ptsClientExpiry = new Sspi.TimeStamp();
+        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
+                null, "Negotiate", Sspi.SECPKG_CRED_OUTBOUND, null, null, null,
+                null, phClientCredential, ptsClientExpiry));
+        // client ----------- security context
+        Sspi.CtxtHandle phClientContext = new Sspi.CtxtHandle();
+        IntByReference pfClientContextAttr = new IntByReference();
+        // server ----------- acquire inbound credential handle
+        Sspi.CredHandle phServerCredential = new Sspi.CredHandle();
+        Sspi.TimeStamp ptsServerExpiry = new Sspi.TimeStamp();
+        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.AcquireCredentialsHandle(
+                null, "Negotiate", Sspi.SECPKG_CRED_INBOUND, null, null, null,
+                null, phServerCredential, ptsServerExpiry));
+        // server ----------- security context
+        Sspi.CtxtHandle phServerContext = new Sspi.CtxtHandle();
+        SspiUtil.ManagedSecBufferDesc pbServerToken = null;
+        IntByReference pfServerContextAttr = new IntByReference();
+        int clientRc = W32Errors.SEC_I_CONTINUE_NEEDED;
+        int serverRc = W32Errors.SEC_I_CONTINUE_NEEDED;
+        do {
+            // client ----------- initialize security context, produce a client token
+            // client token returned is always new
+            SspiUtil.ManagedSecBufferDesc pbClientToken = new SspiUtil.ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
+            if (clientRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
+                // server token is empty the first time
+                SspiUtil.ManagedSecBufferDesc pbServerTokenCopy = pbServerToken == null
+                        ? null : new SspiUtil.ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbServerToken.getBuffer(0).getBytes());
+                clientRc = Secur32.INSTANCE.InitializeSecurityContext(
+                        phClientCredential,
+                        phClientContext.isNull() ? null : phClientContext,
+                        Advapi32Util.getUserName(),
+                        Sspi.ISC_REQ_CONNECTION,
+                        0,
+                        Sspi.SECURITY_NATIVE_DREP,
+                        pbServerTokenCopy,
+                        0,
+                        phClientContext,
+                        pbClientToken,
+                        pfClientContextAttr,
+                        null);
+                assertTrue(clientRc == W32Errors.SEC_I_CONTINUE_NEEDED || clientRc == W32Errors.SEC_E_OK);
+            }
+            // server ----------- accept security context, produce a server token
+            if (serverRc == W32Errors.SEC_I_CONTINUE_NEEDED) {
+                pbServerToken = new SspiUtil.ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
+                SspiUtil.ManagedSecBufferDesc pbClientTokenByValue = new SspiUtil.ManagedSecBufferDesc(Sspi.SECBUFFER_TOKEN, pbClientToken.getBuffer(0).getBytes());
+                serverRc = Secur32.INSTANCE.AcceptSecurityContext(phServerCredential,
+                        phServerContext.isNull() ? null : phServerContext,
+                        pbClientTokenByValue,
+                        Sspi.ISC_REQ_CONNECTION,
+                        Sspi.SECURITY_NATIVE_DREP,
+                        phServerContext,
+                        pbServerToken,
+                        pfServerContextAttr,
+                        ptsServerExpiry);
+                assertTrue(serverRc == W32Errors.SEC_I_CONTINUE_NEEDED || serverRc == W32Errors.SEC_E_OK);
+            }
+        } while (serverRc != W32Errors.SEC_E_OK || clientRc != W32Errors.SEC_E_OK);
+        // impersonate
+        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.ImpersonateSecurityContext(
+                phServerContext));
+        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.RevertSecurityContext(
+                phServerContext));
+        // release server context
+        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
+                phServerContext));
+        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
+                phServerCredential));
+        // release client context
+        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.DeleteSecurityContext(
+                phClientContext));
+        assertEquals(W32Errors.SEC_E_OK, Secur32.INSTANCE.FreeCredentialsHandle(
+                phClientCredential));
+    }
+}


=====================================
contrib/platform/test/com/sun/jna/platform/win32/Win32ServiceDemo.java
=====================================
@@ -122,7 +122,7 @@ public class Win32ServiceDemo {
             }
         }
 
-        String JAVA_HOME = System.getenv("JAVA_HOME");
+        String JAVA_HOME = System.getProperty("java.home", System.getenv("JAVA_HOME"));
         String javaBinary = "java.exe";
         if(JAVA_HOME != null) {
             javaBinary = "\"" + new File(JAVA_HOME, "\\bin\\java.exe").getAbsolutePath() + "\"";


=====================================
contrib/platform/test/com/sun/jna/platform/win32/WininetUtilTest.java
=====================================
@@ -23,6 +23,12 @@
  */
 package com.sun.jna.platform.win32;
 
+import com.sun.jna.Pointer;
+import com.sun.jna.platform.win32.COM.COMLateBindingObject;
+import com.sun.jna.platform.win32.COM.COMUtils;
+import com.sun.jna.platform.win32.COM.Dispatch;
+import com.sun.jna.platform.win32.COM.IDispatch;
+import com.sun.jna.ptr.PointerByReference;
 import java.util.Map;
 
 import org.junit.After;
@@ -37,13 +43,41 @@ public class WininetUtilTest extends AbstractWin32TestSupport {
         jUnitCore.run(WininetUtilTest.class);
     }
 
+    private static final Guid.CLSID CLSID_InternetExplorer = new Guid.CLSID("{0002DF01-0000-0000-C000-000000000046}");
+
+    private PointerByReference ieApp;
+    private Dispatch ieDispatch;
+
     @Before
     public void setUp() throws Exception {
         // Launch IE in a manner that should ensure it opens even if the system
         // default browser is Chrome, Firefox, or something else.
         // Launching IE to a page ensures there will be content in the WinInet
         // cache.
-        Runtime.getRuntime().exec("cmd /c start iexplore.exe -nomerge -nohome \"http://www.google.com\"");
+        WinNT.HRESULT hr;
+
+        hr = Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
+        COMUtils.checkRC(hr);
+
+        // IE can not be launched directly anymore - so load it via COM
+
+        ieApp = new PointerByReference();
+        hr = Ole32.INSTANCE
+                .CoCreateInstance(CLSID_InternetExplorer, null, WTypes.CLSCTX_SERVER, IDispatch.IID_IDISPATCH, ieApp);
+        COMUtils.checkRC(hr);
+
+        ieDispatch = new Dispatch(ieApp.getValue());
+        LocalLateBinding ie = new LocalLateBinding(ieDispatch);
+
+        ie.setProperty("Visible", true);
+
+        Variant.VARIANT url = new Variant.VARIANT("http://www.google.com");
+        Variant.VARIANT result = ie.invoke("Navigate", url);
+        OleAuto.INSTANCE.VariantClear(url);
+        OleAuto.INSTANCE.VariantClear(result);
+
+        ieDispatch.Release();
+        Ole32.INSTANCE.CoUninitialize();
 
         // There's no easy way to monitor IE and see when it's done loading
         // google.com, so just give it 10 seconds.
@@ -77,6 +111,24 @@ public class WininetUtilTest extends AbstractWin32TestSupport {
     @After
     public void tearDown() throws Exception {
         // only kill the freshly opened Google window, unless someone has two IE windows open to Google.
-        Runtime.getRuntime().exec("taskkill.exe /f /im iexplore.exe /fi \"windowtitle eq Google*\"");
+        Runtime.getRuntime().exec("taskkill.exe /f /im iexplore.exe");
+    }
+
+    private static class LocalLateBinding extends COMLateBindingObject {
+
+        public LocalLateBinding(IDispatch iDispatch) {
+            super(iDispatch);
+        }
+
+        @Override
+        public void setProperty(String propertyName, boolean value) {
+            super.setProperty(propertyName, value);
+        }
+
+        @Override
+        public Variant.VARIANT invoke(String methodName, Variant.VARIANT arg) {
+            return super.invoke(methodName, arg);
+        }
+
     }
 }


=====================================
native/Makefile
=====================================
@@ -15,7 +15,9 @@
 #   Linux (i386/amd64/ppc/arm)
 #   Solaris (i386/amd64/sparc/sparcv9)
 #   AIX (ppc/ppc64)
-#   FreeBSD/OpenBSD/NetBSD (i386/amd64)
+#   DragonFly (x86-64)
+#   FreeBSD (i386/amd64/aarch64)
+#   OpenBSD/NetBSD (i386/amd64)
 #   Android (arm/armv7/aarch64/x86/x86-64/mipsel/mips64el)
 #
 # Built, but with outstanding bugs (not necessarily within JNA):
@@ -45,6 +47,7 @@ OS=$(shell uname | sed -e 's/CYGWIN.*/win32/g' \
                         -e 's/NetBSD/netbsd/g' \
                         -e 's/GNU\/kFreeBSD/kfreebsd/g' \
                         -e 's/FreeBSD/freebsd/g' \
+                        -e 's/DragonFly/dragonfly/g' \
                         -e 's/OpenBSD/openbsd/g' \
                         -e 's/Darwin.*/darwin/g' \
                         -e 's/AIX.*/aix/g' \
@@ -177,7 +180,7 @@ COPT+=-fpic -ffunction-sections -funwind-tables -fno-short-enums
 JAVA_INCLUDES=
 CINCLUDES+=-I"$(NDK_PLATFORM)/arch-$(AARCH)/usr/include" # -I/usr/include
 LIBS=-nostdlib -L"$(NDK_PLATFORM)/arch-$(AARCH)$(ALIBDIR)/" -lgcc -lc -ldl -lm
-LDFLAGS+=-Wl,-shared,-Bsymbolic
+LDFLAGS+=-Wl,-shared,-Bsymbolic -Wl,--build-id=sha1
 FFI_ENV=CPP="$(CPP)" CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG) $(CINCLUDES)" CPPFLAGS="$(CDEFINES) $(CINCLUDES)" LIBS="$(LIBS)" RANLIB="$(RANLIB)"
 FFI_CONFIG=--enable-static --disable-shared --with-pic=yes --host=$(HOST)
 endif
@@ -288,10 +291,14 @@ LDFLAGS+=-Wl,-soname,$@,-Bsymbolic
 endif
 endif
 
-ifneq (,$(findstring bsd,$(OS)))
+ifneq (,$(or $(findstring bsd,$(OS)),$(findstring dragonfly,$(OS))))
 ARCH=$(shell uname -m | sed 's/i.86/i386/g')
 PCFLAGS+=-fPIC
-CINCLUDES+=-I/usr/X11R6/include
+# This is a mess: X11 headers locate in /usr/local/include on FreeBSD and
+# DragonFly, in /usr/X11R7/include on NetBSD, and in /usr/X11R6/include on
+# OpenBSD.
+CINCLUDES+=-I/usr/local/include -I/usr/X11R7/include -I/usr/X11R6/include
+CINCLUDES+=$(X11INC)  # Allow extra X11 include path if necessary.
 LDFLAGS=-o $@ -shared
 CDEFINES+=-DHAVE_PROTECTION -DFFI_MMAP_EXEC_WRIT -DUSE_DEAFULT_LIBNAME_ENCODING
 endif


=====================================
native/build.xml
=====================================
@@ -23,6 +23,9 @@
     <condition property="os.prefix" value="sunos-${jre.arch}">
         <os name="SunOS"/>
     </condition>
+    <condition property="os.prefix" value="dragonflybsd-${jre.arch}">
+        <os name="DragonFlyBSD"/>
+    </condition>
     <condition property="os.prefix" value="freebsd-${jre.arch}">
         <os name="FreeBSD"/>
     </condition>
@@ -347,6 +350,7 @@
         </condition>
         <condition property="make" value="gmake">
             <or>
+                <os name="DragonFlyBSD"/>
                 <os name="FreeBSD"/>
                 <os name="OpenBSD"/>
                 <os name="NetBSD"/>


=====================================
native/callback.c
=====================================
@@ -133,19 +133,19 @@ create_callback(JNIEnv* env, jobject obj, jobject method,
   }
   argc = (*env)->GetArrayLength(env, arg_classes);
 
-  cb = (callback *)malloc(sizeof(callback));
+  cb = (callback *)calloc(1, sizeof(callback));
   cb->closure = ffi_closure_alloc(sizeof(ffi_closure), &cb->x_closure);
   cb->saved_x_closure = cb->x_closure;
   cb->object = (*env)->NewWeakGlobalRef(env, obj);
   cb->methodID = (*env)->FromReflectedMethod(env, method);
 
   cb->vm = vm;
-  cb->arg_types = (ffi_type**)malloc(sizeof(ffi_type*) * argc);
-  cb->java_arg_types = (ffi_type**)malloc(sizeof(ffi_type*) * (argc + 3));
-  cb->arg_jtypes = (char*)malloc(sizeof(char) * argc);
-  cb->conversion_flags = (int *)malloc(sizeof(int) * argc);
+  cb->arg_types = (ffi_type**)calloc(argc, sizeof(ffi_type*));
+  cb->java_arg_types = (ffi_type**)calloc(argc + 3, sizeof(ffi_type*));
+  cb->arg_jtypes = (char*)calloc(argc, sizeof(char));
+  cb->conversion_flags = (int *)calloc(argc, sizeof(int));
   cb->rflag = CVT_DEFAULT;
-  cb->arg_classes = (jobject*)malloc(sizeof(jobject) * argc);
+  cb->arg_classes = (jobject*)calloc(argc, sizeof(jobject));
  
   cb->direct = direct;
   cb->java_arg_types[0] = cb->java_arg_types[1] = cb->java_arg_types[2] = &ffi_type_pointer;
@@ -154,7 +154,7 @@ create_callback(JNIEnv* env, jobject obj, jobject method,
   for (i=0;i < argc;i++) {
     int jtype;
     jclass cls = (*env)->GetObjectArrayElement(env, arg_classes, i);
-    if ((cb->conversion_flags[i] = get_conversion_flag(env, cls)) != CVT_DEFAULT) {
+    if (direct && ((cb->conversion_flags[i] = get_conversion_flag(env, cls)) != CVT_DEFAULT)) {
       cb->arg_classes[i] = (*env)->NewWeakGlobalRef(env, cls);
       cvt = 1;
     }
@@ -163,6 +163,9 @@ create_callback(JNIEnv* env, jobject obj, jobject method,
     }
 
     jtype = get_java_type(env, cls);
+    if((*env)->ExceptionCheck(env)) {
+      goto failure_cleanup;
+    }
     if (jtype == -1) {
       snprintf(msg, sizeof(msg), "Unsupported callback argument at index %d", i);
       throw_type = EIllegalArgument;
@@ -179,7 +182,13 @@ create_callback(JNIEnv* env, jobject obj, jobject method,
         || cb->conversion_flags[i] == CVT_INTEGER_TYPE) {
       jclass ncls;
       ncls = getNativeType(env, cls);
+      if((*env)->ExceptionCheck(env)) {
+        goto failure_cleanup;
+      }
       jtype = get_java_type(env, ncls);
+      if((*env)->ExceptionCheck(env)) {
+        goto failure_cleanup;
+      }
       if (jtype == -1) {
         snprintf(msg, sizeof(msg), "Unsupported NativeMapped callback argument native type at argument %d", i);
         throw_type = EIllegalArgument;
@@ -560,7 +569,7 @@ static TLS_KEY_T tls_thread_data_key;
 static thread_storage* get_thread_storage(JNIEnv* env) {
   thread_storage* tls = (thread_storage *)TLS_GET(tls_thread_data_key);
   if (tls == NULL) {
-    tls = (thread_storage*)malloc(sizeof(thread_storage));
+    tls = (thread_storage*)calloc(1, sizeof(thread_storage));
     if (!tls) {
       throwByName(env, EOutOfMemory, "JNA: Can't allocate thread storage");
     }


=====================================
native/dispatch.c
=====================================
@@ -3497,7 +3497,7 @@ Java_com_sun_jna_Native_registerMethod(JNIEnv *env, jclass UNUSED(ncls),
   const char* sig = newCStringUTF8(env, signature);
   void *code;
   void *closure;
-  method_data* data = malloc(sizeof(method_data));
+  method_data* data = calloc(1, sizeof(method_data));
   ffi_cif* closure_cif = &data->closure_cif;
   int status;
   int i;
@@ -3519,12 +3519,12 @@ Java_com_sun_jna_Native_registerMethod(JNIEnv *env, jclass UNUSED(ncls),
   }
 
   data->throw_last_error = throw_last_error;
-  data->arg_types = malloc(sizeof(ffi_type*) * argc);
-  data->closure_arg_types = malloc(sizeof(ffi_type*) * (argc + 2));
+  data->arg_types = calloc(argc, sizeof(ffi_type*));
+  data->closure_arg_types = calloc(argc + 2, sizeof(ffi_type*));
   data->closure_arg_types[0] = &ffi_type_pointer;
   data->closure_arg_types[1] = &ffi_type_pointer;
   data->closure_method = NULL;
-  data->flags = cvts ? malloc(sizeof(jint)*argc) : NULL;
+  data->flags = cvts ? calloc(argc, sizeof(jint)) : NULL;
   data->rflag = rconversion;
   data->to_native = NULL;
   data->from_native = from_native ? (*env)->NewWeakGlobalRef(env, from_native) : NULL;
@@ -3612,7 +3612,7 @@ Java_com_sun_jna_Native_ffi_1prep_1cif(JNIEnv *env, jclass UNUSED(cls), jint abi
 JNIEXPORT jlong JNICALL
 Java_com_sun_jna_Native_ffi_1prep_1closure(JNIEnv *env, jclass UNUSED(cls), jlong cif, jobject obj)
 {
-  callback* cb = (callback *)malloc(sizeof(callback));
+  callback* cb = (callback *)calloc(1, sizeof(callback));
   ffi_status s;
 
   if ((*env)->GetJavaVM(env, &cb->vm) != JNI_OK) {


=====================================
src/com/sun/jna/CallbackReference.java
=====================================
@@ -508,7 +508,7 @@ public class CallbackReference extends WeakReference<Callback> implements Closea
         Map<Callback, CallbackReference> map = direct ? directCallbackMap : callbackMap;
         synchronized(pointerCallbackMap) {
             CallbackReference cbref = map.get(cb);
-            if (cbref == null) {
+            if (cbref == null || cbref.cbstruct == null) {
                 cbref = new CallbackReference(cb, callingConvention, direct);
                 map.put(cb, cbref);
                 pointerCallbackMap.put(cbref.getTrampoline(),


=====================================
src/com/sun/jna/ELFAnalyser.java
=====================================
@@ -62,6 +62,18 @@ class ELFAnalyser {
     private static final int EI_DATA_BIG_ENDIAN = 2;
     private static final int E_MACHINE_ARM = 0x28;
     private static final int EI_CLASS_64BIT = 2;
+    /**
+     * An undefined, missing, irrelevant, or otherwise meaningless section
+     * reference. For example, a symbol defined relative to section number
+     * SHN_UNDEF is an undefined symbol.
+     */
+    private static final int SHN_UNDEF = 0;
+    /**
+     * An escape value indicating that the actual section header index is too
+     * large to fit in the containing field. The header section index is found
+     * in another location specific to the structure where it appears.
+     */
+    private static final int SHN_XINDEX = 0xffff;
 
     public static ELFAnalyser analyse(String filename) throws IOException {
         ELFAnalyser res = new ELFAnalyser(filename);
@@ -203,7 +215,7 @@ class ELFAnalyser {
 
         for (ELFSectionHeaderEntry eshe : sectionHeaders.getEntries()) {
             if(".ARM.attributes".equals(eshe.getName())) {
-                ByteBuffer armAttributesBuffer = ByteBuffer.allocate(eshe.getSize());
+                ByteBuffer armAttributesBuffer = ByteBuffer.allocate((int) eshe.getSize());
                 armAttributesBuffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
                 raf.getChannel().read(armAttributesBuffer, eshe.getOffset());
                 armAttributesBuffer.rewind();
@@ -236,7 +248,8 @@ class ELFAnalyser {
             long shoff;
             int shentsize;
             int shnum;
-            short shstrndx;
+            int shstrndx;
+            int sectionCount;
             if (_64bit) {
                 shoff = headerData.getLong(0x28);
                 shentsize = headerData.getShort(0x3A);
@@ -249,7 +262,27 @@ class ELFAnalyser {
                 shstrndx = headerData.getShort(0x32);
             }
 
-            int tableLength = shnum * shentsize;
+            ByteBuffer sectionBuffer = ByteBuffer.allocate(shentsize);
+            raf.getChannel().read(sectionBuffer, shoff);
+            ELFSectionHeaderEntry section0 = new ELFSectionHeaderEntry(_64bit, sectionBuffer);
+
+            if (shnum == 0 && shoff != 0) {
+                sectionCount = (int) section0.getSize();
+            } else {
+                sectionCount = shnum;
+            }
+
+            if (shstrndx == SHN_XINDEX) {
+                shstrndx = section0.getLink();
+            }
+
+            int tableLength = sectionCount * shentsize;
+
+            if (tableLength == 0 || shstrndx == SHN_UNDEF) {
+                // There is either no section header table or no section name
+                // string table.
+                return;
+            }
 
             ByteBuffer data = ByteBuffer.allocate(tableLength);
             data.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
@@ -264,7 +297,7 @@ class ELFAnalyser {
             }
 
             ELFSectionHeaderEntry stringTable = entries.get(shstrndx);
-            ByteBuffer stringBuffer = ByteBuffer.allocate(stringTable.getSize());
+            ByteBuffer stringBuffer = ByteBuffer.allocate((int) stringTable.getSize());
             stringBuffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
             raf.getChannel().read(stringBuffer, stringTable.getOffset());
             stringBuffer.rewind();
@@ -297,16 +330,20 @@ class ELFAnalyser {
         private final int nameOffset;
         private String name;
         private final int type;
-        private final int flags;
-        private final int offset;
-        private final int size;
+        private final long flags;
+        private final long addr;
+        private final long offset;
+        private final long size;
+        private final int link;
 
         public ELFSectionHeaderEntry(boolean _64bit, ByteBuffer sectionHeaderData) {
-            this.nameOffset = sectionHeaderData.getInt(0x0);
-            this.type = sectionHeaderData.getInt(0x4);
-            this.flags = (int) (_64bit ? sectionHeaderData.getLong(0x8) : sectionHeaderData.getInt(0x8));
-            this.offset = (int) (_64bit ? sectionHeaderData.getLong(0x18) : sectionHeaderData.getInt(0x10));
-            this.size = (int) (_64bit ? sectionHeaderData.getLong(0x20) : sectionHeaderData.getInt(0x14));
+            this.nameOffset = sectionHeaderData.getInt(0);
+            this.type = sectionHeaderData.getInt(4);
+            this.flags = _64bit ? sectionHeaderData.getLong(8) : sectionHeaderData.getInt(8);
+            this.addr = _64bit ? sectionHeaderData.getLong(16) : sectionHeaderData.getInt(12);
+            this.offset = _64bit ? sectionHeaderData.getLong(24) : sectionHeaderData.getInt(16);
+            this.size = _64bit ? sectionHeaderData.getLong(32) : sectionHeaderData.getInt(20);
+            this.link = sectionHeaderData.getInt(_64bit ? 40 : 24);
         }
 
         public String getName() {
@@ -325,21 +362,46 @@ class ELFAnalyser {
             return type;
         }
 
-        public int getFlags() {
+        public long getFlags() {
             return flags;
         }
 
-        public int getOffset() {
+        public long getOffset() {
             return offset;
         }
 
-        public int getSize() {
+        public long getSize() {
             return size;
         }
 
+        public long getAddr() {
+            return addr;
+        }
+
+        public int getLink() {
+            return link;
+        }
+
         @Override
         public String toString() {
-            return "ELFSectionHeaderEntry{" + "nameIdx=" + nameOffset + ", name=" + name + ", type=" + type + ", flags=" + flags + ", offset=" + offset + ", size=" + size + '}';
+            return String.format("ELFSectionHeaderEntry{"
+                    + "nameOffset=%1$d (0x%1$x)"
+                    + ", name=%2$s"
+                    + ", type=%3$d (0x%3$x)"
+                    + ", flags=%4$d (0x%4$x)"
+                    + ", addr=%5$d (0x%5$x)"
+                    + ", offset=%6$d (0x%6$x)"
+                    + ", size=%7$d (0x%7$x)"
+                    + ", link=%8$d (0x%8$x)}",
+                    nameOffset,
+                    name,
+                    type,
+                    flags,
+                    addr,
+                    offset,
+                    size,
+                    link
+            );
         }
     }
 


=====================================
src/com/sun/jna/Native.java
=====================================
@@ -1326,7 +1326,7 @@ public final class Native implements Version {
             if(Platform.isMac()) {
                 // https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html
                 jnatmp = new File(System.getProperty("user.home"), "Library/Caches/JNA/temp");
-            } else if (Platform.isLinux() || Platform.isSolaris() || Platform.isAIX() || Platform.isFreeBSD() || Platform.isNetBSD() || Platform.isOpenBSD() || Platform.iskFreeBSD()) {
+            } else if (Platform.isLinux() || Platform.isSolaris() || Platform.isAIX() || Platform.isDragonFlyBSD() || Platform.isFreeBSD() || Platform.isNetBSD() || Platform.isOpenBSD() || Platform.iskFreeBSD()) {
                 // https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
                 // The XDG_CACHE_DIR is expected to be per user
                 String xdgCacheEnvironment = System.getenv("XDG_CACHE_HOME");
@@ -1918,6 +1918,52 @@ public final class Native implements Version {
         }
     }
 
+    /**
+     * Get the {@link NativeLibrary} instance that is wrapped by the given
+     * {@link Library} interface instance.
+     *
+     * @param library the {@link Library} interface instance, which was created
+     * by the {@link Native#load Native.load()} method
+     * @return the wrapped {@link NativeLibrary} instance
+     */
+    public static NativeLibrary getNativeLibrary(final Library library) {
+        if(library == null) {
+            throw new IllegalArgumentException("null passed to getNativeLibrary");
+        }
+        if(! Proxy.isProxyClass(library.getClass())) {
+            throw new IllegalArgumentException("library object passed to getNativeLibrary in not a proxy");
+        }
+        final InvocationHandler handler = Proxy.getInvocationHandler(library);
+        if (!(handler instanceof Library.Handler)) {
+            throw new IllegalArgumentException("Object is not a properly initialized Library interface instance");
+        }
+        return ((Library.Handler) handler).getNativeLibrary();
+    }
+
+    /**
+     * Get the {@link NativeLibrary} instance to which the given "registered"
+     * class is bound.
+     *
+     * @param cls the "registered" class, which was previously registered via
+     * the {@link Native#register register()} method
+     * @return the {@link NativeLibrary} instance to which the "registered"
+     * class is bound
+     */
+    public static NativeLibrary getNativeLibrary(final Class<?> cls) {
+        if(cls == null) {
+            throw new IllegalArgumentException("null passed to getNativeLibrary");
+        }
+        final Class<?> mappedClass = findDirectMappedClass(cls);
+        synchronized(registeredClasses) {
+            final NativeLibrary nativeLibrary = registeredLibraries.get(mappedClass);
+            if (nativeLibrary == null) {
+                throw new IllegalArgumentException("Class " + cls.getName() + " is not currently registered");
+            } else {
+                return nativeLibrary;
+            }
+        }
+    }
+
     /* Take note of options used for a given library mapping, to facilitate
      * looking them up later.
      */


=====================================
src/com/sun/jna/Platform.java
=====================================
@@ -42,6 +42,7 @@ public final class Platform {
     public static final int GNU = 9;
     public static final int KFREEBSD = 10;
     public static final int NETBSD = 11;
+    public static final int DRAGONFLYBSD = 12;
 
     /** Whether read-only (final) fields within Structures are supported. */
     public static final boolean RO_FIELDS;
@@ -110,6 +111,9 @@ public final class Platform {
         else if (osName.equalsIgnoreCase("netbsd")) {
             osType = NETBSD;
         }
+        else if (osName.equalsIgnoreCase("dragonflybsd")) {
+            osType = DRAGONFLYBSD;
+        }
         else {
             osType = UNSPECIFIED;
         }
@@ -160,6 +164,9 @@ public final class Platform {
     public static final boolean isSolaris() {
         return osType == SOLARIS;
     }
+    public static final boolean isDragonFlyBSD() {
+        return osType == DRAGONFLYBSD;
+    }
     public static final boolean isFreeBSD() {
         return osType == FREEBSD;
     }
@@ -329,6 +336,9 @@ public final class Platform {
             case Platform.SOLARIS:
                 osPrefix = "sunos-" + arch;
                 break;
+            case Platform.DRAGONFLYBSD:
+                osPrefix = "dragonflybsd-" + arch;
+                break;
             case Platform.FREEBSD:
                 osPrefix = "freebsd-" + arch;
                 break;


=====================================
test/com/sun/jna/NativeGetNativeLibraryTest.java
=====================================
@@ -0,0 +1,94 @@
+/* Copyright (c) 2024 Matthias Bläsing, All Rights Reserved
+ *
+ * The contents of this file is dual-licensed under 2
+ * alternative Open Source/Free licenses: LGPL 2.1 or later and
+ * Apache License 2.0. (starting with JNA version 4.0.0).
+ *
+ * You can freely decide which license you want to apply to
+ * the project.
+ *
+ * You may obtain a copy of the LGPL License at:
+ *
+ * http://www.gnu.org/licenses/licenses.html
+ *
+ * A copy is also included in the downloadable source code package
+ * containing JNA, in file "LGPL2.1".
+ *
+ * You may obtain a copy of the Apache License at:
+ *
+ * http://www.apache.org/licenses/
+ *
+ * A copy is also included in the downloadable source code package
+ * containing JNA, in file "AL2.0".
+ */
+package com.sun.jna;
+
+import java.util.Collections;
+import junit.framework.TestCase;
+
+/**
+ * Check getNativeLibrary functions in Native
+ */
+public class NativeGetNativeLibraryTest extends TestCase {
+
+    private NativeLibrary libUTF8;
+    private TestLib libUTF8Interface;
+
+    @Override
+    protected void setUp() {
+        libUTF8 = NativeLibrary.getInstance("testlib",
+                Collections.singletonMap(Library.OPTION_STRING_ENCODING, "UTF-8"));
+        Native.register(TestLibUTF8.class, libUTF8);
+        libUTF8Interface = Native.load("testlib", TestLib.class,
+                Collections.singletonMap(Library.OPTION_STRING_ENCODING, "UTF-8"));
+    }
+
+    public void testGetNativeLibraryInterface() {
+        NativeLibrary nl = Native.getNativeLibrary(libUTF8Interface);
+        assertTrue(nl instanceof NativeLibrary);
+    }
+
+    public void testGetNativeLibraryDirect() {
+        NativeLibrary nl = Native.getNativeLibrary(TestLibUTF8.class);
+        assertTrue(nl instanceof NativeLibrary);
+        // This only makes sense for the direct case, as that directly wraps
+        // a supplied instance
+        assertEquals(libUTF8, nl);
+    }
+
+    public void testGetNativeLibraryOnUnboundShouldFail() {
+        try {
+            Native.getNativeLibrary(new TestLib() {
+                @Override
+                public String returnStringArgument(Pointer input) {
+                    return "";
+                }
+            });
+            assertTrue("Exception not thrown", false);
+        } catch (IllegalArgumentException ex) {
+            // This should be reached
+        }
+    }
+
+    public void testGetNativeLibraryOnNullShouldFail() {
+        try {
+            Native.getNativeLibrary((Class) null);
+            assertTrue("Exception not thrown", false);
+        } catch (IllegalArgumentException ex) {
+            // This should be reached
+        }
+    }
+
+    public static void main(java.lang.String[] argList) {
+        junit.textui.TestRunner.run(NativeGetNativeLibraryTest.class);
+    }
+
+    private static class TestLibUTF8 implements Library  {
+        native String returnStringArgument(Pointer input);
+    }
+
+    private interface TestLib extends Library {
+        public String returnStringArgument(Pointer input);
+    }
+
+}


=====================================
test/com/sun/jna/NativeLibraryTest.java
=====================================
@@ -48,6 +48,7 @@ public class NativeLibraryTest extends TestCase {
             { Platform.LINUX, "lib", ".so" },
             { Platform.WINDOWS, "", ".dll" },
             { Platform.SOLARIS, "lib", ".so" },
+            { Platform.DRAGONFLYBSD, "lib", ".so" },
             { Platform.FREEBSD, "lib", ".so" },
             { Platform.OPENBSD, "lib", ".so" },
             { Platform.WINDOWSCE, "", ".dll" },


=====================================
test/com/sun/jna/PlatformTest.java
=====================================
@@ -83,6 +83,9 @@ public class PlatformTest extends TestCase {
                     Platform.getNativeLibraryResourcePrefix(Platform.LINUX,
                             "arm", "Linux/Gnu"));
         }
+        assertEquals("Wrong resource path DragonFlyBSD/x86-64", "dragonflybsd-x86-64",
+                     Platform.getNativeLibraryResourcePrefix(Platform.DRAGONFLYBSD,
+                                                             "x86-64", "DragonFlyBSD"));
         assertEquals("Wrong resource path OpenBSD/x86", "openbsd-x86",
                      Platform.getNativeLibraryResourcePrefix(Platform.OPENBSD,
                                                              "x86", "OpenBSD"));



View it on GitLab: https://salsa.debian.org/java-team/libjna-java/-/commit/4a7b045eff453c765f74d560adcf4e2123c9a1d3

-- 
View it on GitLab: https://salsa.debian.org/java-team/libjna-java/-/commit/4a7b045eff453c765f74d560adcf4e2123c9a1d3
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20241023/8018519a/attachment.htm>


More information about the pkg-java-commits mailing list