Skip to content

Commit

Permalink
Merge pull request #1603 from matthiasblaesing/stabilize
Browse files Browse the repository at this point in the history
Stabilisation fixes for JNA (and Tests)
  • Loading branch information
matthiasblaesing authored May 30, 2024
2 parents 40f0a12 + d84bfc4 commit f6670c6
Show file tree
Hide file tree
Showing 50 changed files with 302 additions and 134 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ jobs:
brew update
brew install automake --force
brew install libtool --force
brew install texinfo --force
- name: Checkstyle
if: contains(matrix.os, 'ubuntu') && contains(matrix.java, '8')
run: |
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/native-libraries-macOS.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
brew update
brew install automake --force
brew install libtool --force
brew install texinfo --force
- name: Build native code
run: |
ant -Dos.prefix=darwin-aarch64
Expand Down
2 changes: 1 addition & 1 deletion common.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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="1"/>
<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"/>
Expand Down
13 changes: 8 additions & 5 deletions contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -1950,12 +1950,14 @@ public void testDecryptFile() throws Exception {

// 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();
}
Expand Down Expand Up @@ -2170,4 +2172,5 @@ public void testCreateProcessWithLogonW() {
// 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());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -39,16 +44,41 @@

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.
Expand Down Expand Up @@ -85,6 +115,7 @@ public void testWindowsCount()
@After
public void tearDown() throws Exception
{
Ole32.INSTANCE.CoUninitialize();
Runtime.getRuntime().exec("taskkill.exe /f /im iexplore.exe");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,6 @@ private void enumerateRootCertificates(HCERTSTORE hCertStore) {
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++;
Expand Down
41 changes: 33 additions & 8 deletions contrib/platform/test/com/sun/jna/platform/win32/IPHlpAPITest.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,26 +163,51 @@ public void testGetTcpStatistics() {

@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
Expand Down
78 changes: 0 additions & 78 deletions contrib/platform/test/com/sun/jna/platform/win32/Secur32Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -190,84 +190,6 @@ public void testAcceptSecurityContext() {
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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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));
}
}
Loading

0 comments on commit f6670c6

Please sign in to comment.