Skip to content

Commit

Permalink
Move Windows Service functions from ntservice project to core
Browse files Browse the repository at this point in the history
The ntservice poject contained additional definitions for windows
service related functionality. Unittests are added in the form of a
sample service implementation, that is installed/uninstalled and
invoked.

com.sun.jna.platform.win32.Advapi32:
- StartServiceCtrlDispatcher
- RegisterServiceCtrlHandler
- RegisterServiceCtrlHandlerEx
- SetServiceStatus
- CreateService
- DeleteService

com.sun.jna.platform.win32.Winsvc:
- Handler
- HandlerEx
- SERVICE_MAIN_FUNCTION
- SERVICE_TABLE_ENTRY
- SERVICE_DESCRIPTION
- SERVICE_STATUS_HANDLE

Closes: java-native-access#821
Closes: java-native-access#258
  • Loading branch information
matthiasblaesing committed Aug 13, 2017
1 parent 027fd13 commit e829c3b
Show file tree
Hide file tree
Showing 8 changed files with 1,250 additions and 860 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Features
* [#816](https://github.com/java-native-access/jna/pull/816): Support `boolean[]` in direct mapping - [@ncruces](https://github.com/ncruces).
* [#827](https://github.com/java-native-access/jna/pull/827): Add support for linux-mips64el - [@all7](https://github.com/all7).
* [#845](https://github.com/java-native-access/jna/issues/845): Add support for linux-s390x - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#821](https://github.com/java-native-access/jna/issues/821): Move windows service related functions and structures in ntservice sample project to `com.sun.jna.platform.win32.Advapi32`: `StartServiceCtrlDispatcher`, `RegisterServiceCtrlHandler`, `RegisterServiceCtrlHandlerEx`, `SetServiceStatus`, `CreateService`, `DeleteService` and `com.sun.jna.platform.win32.Winsvc`: `Handler`, `HandlerEx`, `SERVICE_MAIN_FUNCTION`, `SERVICE_TABLE_ENTRY`, `SERVICE_DESCRIPTION`, `SERVICE_STATUS_HANDLE` - [@matthiasblaesing](https://github.com/matthiasblaesing).

Bug Fixes
---------
Expand Down
659 changes: 0 additions & 659 deletions contrib/ntservice/src/jnacontrib/jna/Advapi32.java

This file was deleted.

126 changes: 49 additions & 77 deletions contrib/ntservice/src/jnacontrib/win32/Win32Service.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,35 @@

package jnacontrib.win32;

import jnacontrib.jna.*;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Advapi32;
import com.sun.jna.platform.win32.WinError;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.Winsvc;
import com.sun.jna.platform.win32.Winsvc.HandlerEx;
import com.sun.jna.platform.win32.Winsvc.SC_HANDLE;
import com.sun.jna.platform.win32.Winsvc.SERVICE_DESCRIPTION;
import com.sun.jna.platform.win32.Winsvc.SERVICE_MAIN_FUNCTION;
import com.sun.jna.platform.win32.Winsvc.SERVICE_STATUS;
import com.sun.jna.platform.win32.Winsvc.SERVICE_STATUS_HANDLE;
import com.sun.jna.platform.win32.Winsvc.SERVICE_TABLE_ENTRY;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import jnacontrib.jna.Advapi32.SERVICE_STATUS_HANDLE;
import jnacontrib.jna.Advapi32.SERVICE_TABLE_ENTRY;

/**
* Baseclass for a Win32 service.
*/
public abstract class Win32Service {
private static final Advapi32 advapi32 = Advapi32.INSTANCE;

private final Object waitObject = new Object();

protected String serviceName;
private ServiceMain serviceMain;
private ServiceControl serviceControl;
private SERVICE_STATUS_HANDLE serviceStatusHandle;
private Object waitObject = new Object();

/**
* Creates a new instance of Win32Service.
Expand Down Expand Up @@ -104,85 +110,73 @@ public boolean install(String displayName, String description, String[] dependen
* @param account service account or null for LocalSystem
* @param password password for service account or null
* @param command command line to start the service
* @throws java.lang.Exception
*/
public boolean install(String displayName, String description, String[] dependencies, String account, String password, String command) {
Advapi32 advapi32;
Advapi32.SERVICE_DESCRIPTION desc;
SC_HANDLE service, serviceManager;
boolean success = false;
String dep = "";
StringBuilder dep = new StringBuilder();

if(dependencies != null) {
for(String s : dependencies) {
dep += s + "\0";
dep.append(s);
dep.append("\0");
}
}
dep += "\0";
dep.append("\0");

desc = new Advapi32.SERVICE_DESCRIPTION();
SERVICE_DESCRIPTION desc = new SERVICE_DESCRIPTION();
desc.lpDescription = description;

advapi32 = Advapi32.INSTANCE;
serviceManager = openServiceControlManager(null, Winsvc.SC_MANAGER_ALL_ACCESS);
SC_HANDLE serviceManager = openServiceControlManager(null, Winsvc.SC_MANAGER_ALL_ACCESS);

if(serviceManager != null) {
service = advapi32.CreateService(serviceManager, serviceName, displayName,
SC_HANDLE service = advapi32.CreateService(serviceManager, serviceName, displayName,
Winsvc.SERVICE_ALL_ACCESS, WinNT.SERVICE_WIN32_OWN_PROCESS, WinNT.SERVICE_DEMAND_START,
WinNT.SERVICE_ERROR_NORMAL,
command,
null, null, dep, account, password);
null, null, dep.toString(), account, password);

if(service != null) {
success = advapi32.ChangeServiceConfig2(service, Winsvc.SERVICE_CONFIG_DESCRIPTION, desc);
advapi32.CloseServiceHandle(service);
}
advapi32.CloseServiceHandle(serviceManager);
}
return(success);
return success;
}

/**
* Uninstall the service.
*
* @throws java.lang.Exception
* @return true on success
*/
public boolean uninstall() {
Advapi32 advapi32;
SC_HANDLE serviceManager, service;
boolean success = false;

advapi32 = Advapi32.INSTANCE;
serviceManager = openServiceControlManager(null, Winsvc.SC_MANAGER_ALL_ACCESS);

SC_HANDLE serviceManager = openServiceControlManager(null, Winsvc.SC_MANAGER_ALL_ACCESS);

if(serviceManager != null) {
service = advapi32.OpenService(serviceManager, serviceName, Winsvc.SERVICE_ALL_ACCESS);
SC_HANDLE service = advapi32.OpenService(serviceManager, serviceName, Winsvc.SERVICE_ALL_ACCESS);

if(service != null) {
success = advapi32.DeleteService(service);
advapi32.CloseServiceHandle(service);
}
advapi32.CloseServiceHandle(serviceManager);
}
return(success);
return success;
}

/**
* Ask the ServiceControlManager to start the service.
* @return true on success
*/
public boolean start() {
Advapi32 advapi32;
SC_HANDLE serviceManager, service;
boolean success = false;

advapi32 = Advapi32.INSTANCE;

serviceManager = openServiceControlManager(null, WinNT.GENERIC_EXECUTE);
SC_HANDLE serviceManager = openServiceControlManager(null, WinNT.GENERIC_EXECUTE);

if(serviceManager != null) {
service = advapi32.OpenService(serviceManager, serviceName, WinNT.GENERIC_EXECUTE);
SC_HANDLE service = advapi32.OpenService(serviceManager, serviceName, WinNT.GENERIC_EXECUTE);

if(service != null) {
success = advapi32.StartService(service, 0, null);
Expand All @@ -191,51 +185,42 @@ public boolean start() {
advapi32.CloseServiceHandle(serviceManager);
}

return(success);
return success;
}

/**
* Ask the ServiceControlManager to stop the service.
* @return true on success
*/
public boolean stop() throws Exception {
Advapi32 advapi32;
SC_HANDLE serviceManager, service;
SERVICE_STATUS serviceStatus;
boolean success = false;

advapi32 = Advapi32.INSTANCE;

serviceManager = openServiceControlManager(null, WinNT.GENERIC_EXECUTE);

if(serviceManager != null) {
service = advapi32.OpenService(serviceManager, serviceName, WinNT.GENERIC_EXECUTE);

if(service != null) {
serviceStatus = new SERVICE_STATUS();
success = advapi32.ControlService(service, Winsvc.SERVICE_CONTROL_STOP, serviceStatus);
advapi32.CloseServiceHandle(service);
}
advapi32.CloseServiceHandle(serviceManager);
public boolean stop() {
boolean success = false;

SC_HANDLE serviceManager = openServiceControlManager(null, WinNT.GENERIC_EXECUTE);

if (serviceManager != null) {
SC_HANDLE service = Advapi32.INSTANCE.OpenService(serviceManager, serviceName, WinNT.GENERIC_EXECUTE);

if (service != null) {
SERVICE_STATUS serviceStatus = new SERVICE_STATUS();
success = Advapi32.INSTANCE.ControlService(service, Winsvc.SERVICE_CONTROL_STOP, serviceStatus);
Advapi32.INSTANCE.CloseServiceHandle(service);
}
Advapi32.INSTANCE.CloseServiceHandle(serviceManager);
}

return (success);
}

return(success);
}

/**
* Initialize the service, connect to the ServiceControlManager.
*/
public void init() {
Advapi32 advapi32;
SERVICE_TABLE_ENTRY entry;

serviceMain = new ServiceMain();
advapi32 = Advapi32.INSTANCE;
entry = new Advapi32.SERVICE_TABLE_ENTRY();
SERVICE_TABLE_ENTRY entry = new SERVICE_TABLE_ENTRY();
entry.lpServiceName = serviceName;
entry.lpServiceProc = serviceMain;

advapi32.StartServiceCtrlDispatcher((SERVICE_TABLE_ENTRY[]) entry.toArray(2));
Advapi32.INSTANCE.StartServiceCtrlDispatcher((SERVICE_TABLE_ENTRY[]) entry.toArray(2));
}

/**
Expand All @@ -246,12 +231,7 @@ public void init() {
* @return handle to ServiceControlManager or null when failed
*/
private SC_HANDLE openServiceControlManager(String machine, int access) {
SC_HANDLE handle = null;
Advapi32 advapi32;

advapi32 = Advapi32.INSTANCE;
handle = advapi32.OpenSCManager(machine, null, access);
return(handle);
return advapi32.OpenSCManager(machine, null, access);
}

/**
Expand All @@ -262,11 +242,7 @@ private SC_HANDLE openServiceControlManager(String machine, int access) {
* @param waitHint time to wait
*/
private void reportStatus(int status, int win32ExitCode, int waitHint) {
Advapi32 advapi32;
SERVICE_STATUS serviceStatus;

advapi32 = Advapi32.INSTANCE;
serviceStatus = new SERVICE_STATUS();
SERVICE_STATUS serviceStatus = new SERVICE_STATUS();
serviceStatus.dwServiceType = WinNT.SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwControlsAccepted = Winsvc.SERVICE_ACCEPT_STOP | Winsvc.SERVICE_ACCEPT_SHUTDOWN;
serviceStatus.dwWin32ExitCode = win32ExitCode;
Expand All @@ -290,7 +266,7 @@ private void reportStatus(int status, int win32ExitCode, int waitHint) {
/**
* Implementation of the service main function.
*/
private class ServiceMain implements Advapi32.SERVICE_MAIN_FUNCTION {
private class ServiceMain implements SERVICE_MAIN_FUNCTION {

/**
* Called when the service is starting.
Expand All @@ -299,10 +275,6 @@ private class ServiceMain implements Advapi32.SERVICE_MAIN_FUNCTION {
* @param lpszArgv pointer to arguments
*/
public void callback(int dwArgc, Pointer lpszArgv) {
Advapi32 advapi32;

advapi32 = Advapi32.INSTANCE;

serviceControl = new ServiceControl();
serviceStatusHandle = advapi32.RegisterServiceCtrlHandlerEx(serviceName, serviceControl, null);

Expand Down Expand Up @@ -331,7 +303,7 @@ public void callback(int dwArgc, Pointer lpszArgv) {
/**
* Implementation of the service control function.
*/
private class ServiceControl implements Advapi32.HandlerEx {
private class ServiceControl implements HandlerEx {

/**
* Called when the service get a control code.
Expand Down
Loading

0 comments on commit e829c3b

Please sign in to comment.