Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Stabilisation fixes for JNA (and Tests) #1603

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .github/workflows/ci.yaml
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
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
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
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) {
matthiasblaesing marked this conversation as resolved.
Show resolved Hide resolved
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());
}

}
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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will tearDown() still run if this fails? Making sure you don't over- CoUninitialize().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will tearDown() still run if this fails? Making sure you don't over- CoUninitialize().

"fails" would only include an hr of RPC_E_CHANGED_MODE. Both S_OK and S_FALSE require the uninitialize.

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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will not cleanup with a failure, move the release into tearDown()?


// 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
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));
matthiasblaesing marked this conversation as resolved.
Show resolved Hide resolved
// 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
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
Expand Up @@ -190,84 +190,6 @@ public void testAcceptSecurityContext() {
phClientCredential));
}

public void testImpersonateRevertSecurityContext() {
matthiasblaesing marked this conversation as resolved.
Show resolved Hide resolved
// 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
@@ -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));
}
}