Skip to content

Commit

Permalink
Merge pull request #1294 from matthiasblaesing/application-restart
Browse files Browse the repository at this point in the history
Implement ApplicationRestart functions
matthiasblaesing authored Jan 19, 2021

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 1de0448 + 77c2075 commit ed11ac5
Showing 5 changed files with 189 additions and 4 deletions.
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ Next Release (5.7.0)
Features
--------
* [#1264](https://github.com/java-native-access/jna/pull/1264): Update libffi to v3.3; Add Windows `aarch64` target. - [@tresf](https://github.com/tresf).
* [#1293](https://github.com/java-native-access/jna/issues/1293): Bind part of Windows Application Recovery and Restart API: `RegisterApplicationRestart`, `UnregisterApplicationRestart` and `GetApplicationRestartSettings` in `c.s.j.p.w.Kernel32` - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#1217](https://github.com/java-native-access/jna/pull/1217): Add mappings for AIX `Perfstat` library to `c.s.j.p.unix.aix` - [@dbwiddis](https://github.com/dbwiddis).
* [#1231](https://github.com/java-native-access/jna/pull/1231): The test suite can now be executed on Windows using either ANSI or UNICODE win32 API by passing `-Dw32.ascii=true/false` to ant. Previously, UNICODE was always used. - [@T-Svensson](https://github.com/T-Svensson/)
* [#1237](https://github.com/java-native-access/jna/pull/1237): *Experimental:* Add artifacts that make jna and jna-platform named modules (provide `module-info.class`). The new artifacts are named `jna-jpms.jar` and `jna-platform-jpms.jar` - [@matthiasblaesing](https://github.com/matthiasblaesing).
@@ -16,7 +17,7 @@ Features
* [#1246](https://github.com/java-native-access/jna/pull/1246): Improve performance of `c.s.j.Structure#read` and `c.s.j.Structure#write` - [@joerg1985](https://github.com/joerg1985).
* [#1260](https://github.com/java-native-access/jna/pull/1260): Add mapping for X11 generic events - [@lafoletc](https://github.com/lafoletc).
* [#1265](https://github.com/java-native-access/jna/pull/1265): Add mapping for XQueryExtension - [@lafoletc](https://github.com/lafoletc).
* [#1263](https://github.com/java-native-access/jna/pull/1263): Add LowLevelMouseProc - [@nordiakt](https://github.com/nordiakt)
* [#1263](https://github.com/java-native-access/jna/pull/1263): Add LowLevelMouseProc - [@nordiakt](https://github.com/nordiakt).

Bug Fixes
---------
28 changes: 25 additions & 3 deletions build.xml
Original file line number Diff line number Diff line change
@@ -1453,7 +1453,7 @@ cd ..
</subant>
</target>

<target name="install" depends="dist" description="Install jna and jna-platform artifacts into local maven repository">
<target name="install" depends="dist,-bootstrap-maven" description="Install jna and jna-platform artifacts into local maven repository">
<artifact:mvn failonerror="true">
<arg value="org.apache.maven.plugins:maven-install-plugin:2.5:install-file"/>
<arg value="-DpomFile=${pom}"/>
@@ -1495,7 +1495,7 @@ cd ..
</target>

<!-- NOTE: The 'deploy' target works only if the version (jna.version in build.xml) ends in '-SNAPSHOT'. -->
<target name="deploy" depends="dist" description="deploy snapshot version to Maven snapshot repository">
<target name="deploy" depends="dist,-bootstrap-maven" description="deploy snapshot version to Maven snapshot repository">
<artifact:mvn failonerror="true">
<arg value="org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy-file"/>
<arg value="-Durl=${maven-snapshots-repository-url}"/>
@@ -1522,7 +1522,7 @@ cd ..

<property name="version-maven-gpg-plugin" value="1.4"/>

<target name="stage" depends="dist" description="deploy release version to Maven staging repository">
<target name="stage" depends="dist,-bootstrap-maven" description="deploy release version to Maven staging repository">
<!-- sign and deploy the jna, artifact -->
<artifact:mvn failonerror="true">
<arg value="org.apache.maven.plugins:maven-gpg-plugin:${version-maven-gpg-plugin}:sign-and-deploy-file"/>
@@ -1550,6 +1550,28 @@ cd ..
</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>
</target>

<target name="checkstyle">
<taskdef resource="com/puppycrawl/tools/checkstyle/ant/checkstyle-ant-task.properties"
classpath="lib/checkstyle-8.17-all.jar"/>
1 change: 1 addition & 0 deletions contrib/platform/nbproject/build-impl.xml
Original file line number Diff line number Diff line change
@@ -1336,6 +1336,7 @@ is divided into following sections:
</target>
<target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
<target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/>
<target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-single-method"/>
<target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
<j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
</target>
110 changes: 110 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java
Original file line number Diff line number Diff line change
@@ -4178,4 +4178,114 @@ Pointer VirtualAllocEx(HANDLE hProcess, Pointer lpAddress, SIZE_T dwSize,
* error information, call GetLastError.</p>
*/
boolean VirtualFreeEx( HANDLE hProcess, Pointer lpAddress, SIZE_T dwSize, int dwFreeType);

/**
* Registers the active instance of an application for restart.
*
* <p><strong>Usage Note</strong></p>
*
* <p>The registered callback is only invoked if the default error handling
* of the JVM does not intercept first. It was tested with OpenJDK and
* it was found, that the error handling of the JVM had to be disabled by
* running the process with "-XX:+UseOSErrorReporting".</p>
*
* @param pwzCommandline A pointer to a Unicode string that specifies the
* command-line arguments for the application when it
* is restarted. The maximum size of the command line
* that you can specify is RESTART_MAX_CMD_LINE
* characters. Do not include the name of the
* executable in the command line; this function adds
* it for you.
*
* <p>If this parameter is NULL or an empty string, the previously registered
* command line is removed. If the argument contains spaces, use quotes
* around the argument.</p>
*
* @param dwFlags This parameter can be 0 or one or more of the
* following values.
*
* <table>
* <tr>
* <th>Value</th><th>Meaning</th>
* </tr>
* <tr><td>RESTART_NO_CRASH (1)</td><td>Do not restart the process if it terminates due to an unhandled exception.</td></tr>
* <tr><td>RESTART_NO_HANG (2)</td><td>Do not restart the process if it terminates due to the application not responding.</td></tr>
* <tr><td>RESTART_NO_PATCH (4)</td><td>Do not restart the process if it terminates due to the installation of an update.</td></tr>
* <tr><td>RESTART_NO_REBOOT (8)</td><td>Do not restart the process if the computer is restarted as the result of an update. </td></tr>
* </table>
*
* @return This function returns S_OK on success or one of the following
* error codes.
* <table>
* <tr><th>Return code</th><th>Description</th></tr>
* <tr><td>E_FAIL</td><td>Internal error.</td></tr>
* <tr><td>E_INVALIDARG</td><td>The specified command line is too
* long.</td></tr>
* </table>
*
* @see <A HREF="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-registerapplicationrestart">MSDN Entry</A>
*/
HRESULT RegisterApplicationRestart(char[] pwzCommandline, int dwFlags);

/**
* Removes the active instance of an application from the restart list.
*
* @return This function returns S_OK on success or one of the following
* error codes.
* <table>
* <tr><th>Return code</th><th>Description</th></tr>
* <tr><td>E_FAIL</td><td>Internal error.</td></tr>
* </table>
*
* @see <A HREF="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-unregisterapplicationrestart">MSDN Entry</A>
*/
HRESULT UnregisterApplicationRestart();

/**
* Retrieves the restart information registered for the specified process.
*
* @param hProcess A handle to the process. This handle must have the
* PROCESS_VM_READ access right.
* @param pwzCommandline A pointer to a buffer that receives the restart
* command line specified by the application when it
* called the RegisterApplicationRestart function. The
* maximum size of the command line, in characters, is
* RESTART_MAX_CMD_LINE. Can be NULL if pcchSize is
* zero.
* @param pcchSize On input, specifies the size of the pwzCommandLine
* buffer, in characters.
*
* <p>
* If the buffer is not large enough to receive the command line, the
* function fails with HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) and
* sets this parameter to the required buffer size, in characters.</p>
* <p>
* On output, specifies the size of the buffer that was used.</p>
* <p>
* To determine the required buffer size, set pwzCommandLine to NULL and
* this parameter to zero. The size includes one for the null-terminator
* character. Note that the function returns S_OK, not
* HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) in this case.</p>
*
* @param pdwFlags A pointer to a variable that receives the flags
* specified by the application when it called the
* RegisterApplicationRestart function.
*
* @return This function returns S_OK on success or one of the following
* error codes.
* <table>
* <tr><th>Return code</th><th>Description</th></tr>
* <tr><td>E_INVALIDARG</th><th>One or more parameters are not
* valid.</td></tr>
* <tr><td>HRESULT_FROM_WIN32(ERROR_NOT_FOUND)</th><th>The application did
* not register for restart.</td></tr>
* <tr><td>HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)</th><th>The
* pwzCommandLine buffer is too small. The function returns the required
* buffer size in pcchSize. Use the required size to reallocate the
* buffer.</td></tr>
* </table>
*
* @see <A HREF="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getapplicationrestartsettings">MSDN Entry</A>
*/
HRESULT GetApplicationRestartSettings(HANDLE hProcess, char[] pwzCommandline, IntByReference pcchSize, IntByReference pdwFlags);
}
51 changes: 51 additions & 0 deletions contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java
Original file line number Diff line number Diff line change
@@ -64,6 +64,7 @@
import com.sun.jna.platform.win32.BaseTSD.SIZE_T;
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTRByReference;
import com.sun.jna.platform.win32.COM.COMUtils;
import com.sun.jna.platform.win32.Ntifs.REPARSE_DATA_BUFFER;
import com.sun.jna.platform.win32.Ntifs.SymbolicLinkReparseBuffer;
import com.sun.jna.platform.win32.WinBase.FILETIME;
@@ -84,6 +85,7 @@
import com.sun.jna.platform.win32.WinDef.USHORT;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.platform.win32.WinNT.MEMORY_BASIC_INFORMATION;
import com.sun.jna.platform.win32.WinNT.OSVERSIONINFO;
import com.sun.jna.platform.win32.WinNT.OSVERSIONINFOEX;
@@ -1910,4 +1912,53 @@ public void run() {

assertNull(mutexHandle);
}

public void testApplicationRestart() {
try {
HRESULT insufficientBuffer = W32Errors.HRESULT_FROM_WIN32(WinError.ERROR_INSUFFICIENT_BUFFER);
HRESULT result;
String dummyCommandline = "/restart -f .\\filename.ext";
char[] dummyCommandlineArray = Native.toCharArray(dummyCommandline);
int dummyFlags = 2;
result = Kernel32.INSTANCE.RegisterApplicationRestart(dummyCommandlineArray, dummyFlags);
assertTrue(COMUtils.SUCCEEDED(result));

char[] queriedCommandlineArray = null;
IntByReference queriedSize = new IntByReference();
IntByReference queriedFlags = new IntByReference();

// Query without target buffer to determine required buffer size
result = Kernel32.INSTANCE.GetApplicationRestartSettings(Kernel32.INSTANCE.GetCurrentProcess(), queriedCommandlineArray, queriedSize, queriedFlags);

assertTrue(COMUtils.SUCCEEDED(result));
assertEquals(dummyCommandline.length() + 1, queriedSize.getValue());

// Check error reporting, use insufficient buffer size
queriedCommandlineArray = new char[1];
queriedSize.setValue(queriedCommandlineArray.length);
queriedFlags.setValue(-1);
result = Kernel32.INSTANCE.GetApplicationRestartSettings(Kernel32.INSTANCE.GetCurrentProcess(), queriedCommandlineArray, queriedSize, queriedFlags);

assertTrue(COMUtils.FAILED(result));
assertEquals(insufficientBuffer, result);
assertEquals(dummyCommandline.length() + 1, queriedSize.getValue());

// Now query with the right buffer size
queriedCommandlineArray = new char[queriedSize.getValue()];
queriedSize.setValue(queriedCommandlineArray.length);
queriedFlags.setValue(-1);
result = Kernel32.INSTANCE.GetApplicationRestartSettings(Kernel32.INSTANCE.GetCurrentProcess(), queriedCommandlineArray, queriedSize, queriedFlags);

assertTrue(COMUtils.SUCCEEDED(result));
assertEquals(dummyCommandline.length() + 1, queriedSize.getValue());
assertEquals(dummyFlags, queriedFlags.getValue());
assertEquals(dummyCommandline, Native.toString(queriedCommandlineArray));

result = Kernel32.INSTANCE.UnregisterApplicationRestart();
assertTrue(COMUtils.SUCCEEDED(result));
} finally {
// Last resort if test succeeds partially
Kernel32.INSTANCE.UnregisterApplicationRestart();
}
}
}

0 comments on commit ed11ac5

Please sign in to comment.