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

Added changing optional config of W32 services #489

Merged
merged 9 commits into from
Jan 19, 2016
76 changes: 75 additions & 1 deletion contrib/platform/src/com/sun/jna/platform/win32/Advapi32.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.TypeMapper;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WinBase.SECURITY_ATTRIBUTES;
import com.sun.jna.platform.win32.WinBase.FE_EXPORT_FUNC;
Expand Down Expand Up @@ -48,7 +49,7 @@
*/
public interface Advapi32 extends StdCallLibrary {
Advapi32 INSTANCE = (Advapi32) Native.loadLibrary("Advapi32",
Advapi32.class, W32APIOptions.UNICODE_OPTIONS);
Advapi32.class, W32APIOptions.DEFAULT_OPTIONS);

public static final int MAX_KEY_LENGTH = 255;
public static final int MAX_VALUE_NAME = 16383;
Expand Down Expand Up @@ -1175,6 +1176,61 @@ public boolean ReadEventLog(HANDLE hEventLog, int dwReadFlags,
public boolean GetOldestEventLogRecord(HANDLE hEventLog,
IntByReference OldestRecord);


/**
* Changes the optional configuration parameters of a service.
*
* @param hService
* A handle to the service. This handle is returned by the
* OpenService or CreateService function and must have the
* SERVICE_CHANGE_CONFIG access right. For more information,
* see <a
* href="http://msdn.microsoft.com/en-us/library/ms685981.aspx"
* >Service Security and Access Rights</a>.
* If the service controller handles the SC_ACTION_RESTART
* action, hService must have the SERVICE_START access right.
* @param dwInfoLevel
* The configuration information to be changed.
* @param lpInfo
* A pointer to the new value to be set for the configuration
* information. The format of this data depends on the value
* of the dwInfoLevel parameter. If this value is NULL, the
* information remains unchanged.
* @return If the function succeeds, the return value is nonzero.
* If the function fails, the return value is zero. To get extended
* error information, call GetLastError.
*/
public boolean ChangeServiceConfig2(SC_HANDLE hService, int dwInfoLevel,
ChangeServiceConfig2Info lpInfo);

/**
* Retrieves the optional configuration parameters of the specified service.
*
* @param hService
* A handle to the service. This handle is returned by the OpenService or
* CreateService function and must have the SERVICE_QUERY_CONFIG access right. For
* more information, see Service Security and Access Rights.
* @param dwInfoLevel
* The configuration information to be queried.
* @param lpBuffer
* A pointer to the buffer that receives the service configuration information. The
* format of this data depends on the value of the dwInfoLevel parameter.
* The maximum size of this array is 8K bytes. To determine the required size,
* specify NULL for this parameter and 0 for the cbBufSize parameter. The function
* fails and GetLastError returns ERROR_INSUFFICIENT_BUFFER. The pcbBytesNeeded
* parameter receives the needed size.
* @param cbBufSize
* The size of the structure pointed to by the lpBuffer parameter, in bytes.
* @param pcbBytesNeeded
* A pointer to a variable that receives the number of bytes required to store the
* configuration information, if the function fails with ERROR_INSUFFICIENT_BUFFER.
* @return If the function succeeds, the return value is nonzero.
* If the function fails, the return value is zero. To get extended error information,
* call GetLastError.
*/
public boolean QueryServiceConfig2(SC_HANDLE hService, int dwInfoLevel,
Pointer lpBuffer, int cbBufSize, IntByReference pcbBytesNeeded);

/**
* Retrieves the current status of the specified service based on the
* specified information level.
Expand Down Expand Up @@ -1900,4 +1956,22 @@ public int WriteEncryptedFileRaw(FE_IMPORT_FUNC pfImportCallback,
* OpenEncryptedFileRaw function returns the context block.
*/
public void CloseEncryptedFileRaw(Pointer pvContext);

public static abstract class ChangeServiceConfig2Info extends Structure {
public ChangeServiceConfig2Info() {
super();
}

public ChangeServiceConfig2Info(Pointer p) {
super(p);
}

public ChangeServiceConfig2Info(TypeMapper mapper) {
super(mapper);
}

public ChangeServiceConfig2Info(Pointer p, int alignType, TypeMapper mapper) {
super(p, alignType, mapper);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
public interface Crypt32 extends StdCallLibrary {

Crypt32 INSTANCE = (Crypt32) Native.loadLibrary("Crypt32",
Crypt32.class, W32APIOptions.UNICODE_OPTIONS);
Crypt32.class, W32APIOptions.DEFAULT_OPTIONS);

/**
* The CryptProtectData function performs encryption on the data in a DATA_BLOB
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public interface Kernel32 extends WinNT, Wincon {

/** The instance. */
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32",
Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
Kernel32.class, W32APIOptions.DEFAULT_OPTIONS);

/**
* Reads data from the specified file or input/output (I/O) device. Reads
Expand Down
2 changes: 1 addition & 1 deletion contrib/platform/src/com/sun/jna/platform/win32/Msi.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
public interface Msi extends StdCallLibrary {

Msi INSTANCE = (Msi)
Native.loadLibrary("msi", Msi.class, W32APIOptions.UNICODE_OPTIONS);
Native.loadLibrary("msi", Msi.class, W32APIOptions.DEFAULT_OPTIONS);

/**
* The component being requested is disabled on the computer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
public interface Netapi32 extends StdCallLibrary {

Netapi32 INSTANCE = (Netapi32) Native.loadLibrary("Netapi32",
Netapi32.class, W32APIOptions.UNICODE_OPTIONS);
Netapi32.class, W32APIOptions.DEFAULT_OPTIONS);

/**
* Retrieves join status information for the specified computer.
Expand Down
2 changes: 1 addition & 1 deletion contrib/platform/src/com/sun/jna/platform/win32/NtDll.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
public interface NtDll extends StdCallLibrary {

NtDll INSTANCE = (NtDll) Native.loadLibrary("NtDll",
NtDll.class, W32APIOptions.UNICODE_OPTIONS);
NtDll.class, W32APIOptions.DEFAULT_OPTIONS);

/**
* The ZwQueryKey routine provides information about the class of a registry key,
Expand Down
2 changes: 1 addition & 1 deletion contrib/platform/src/com/sun/jna/platform/win32/Ole32.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public interface Ole32 extends StdCallLibrary {

/** The instance. */
Ole32 INSTANCE = (Ole32) Native.loadLibrary("Ole32", Ole32.class,
W32APIOptions.UNICODE_OPTIONS);
W32APIOptions.DEFAULT_OPTIONS);

/**
* Creates a GUID, a unique 128-bit integer used for CLSIDs and interface
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public interface OleAuto extends StdCallLibrary {

/** The instance. */
OleAuto INSTANCE = (OleAuto) Native.loadLibrary("OleAut32", OleAuto.class,
W32APIOptions.UNICODE_OPTIONS);
W32APIOptions.DEFAULT_OPTIONS);

/**
* This function allocates a new string and copies the passed string into
Expand Down
2 changes: 1 addition & 1 deletion contrib/platform/src/com/sun/jna/platform/win32/Pdh.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
*/
public interface Pdh extends StdCallLibrary {
Pdh INSTANCE = (Pdh) Native.loadLibrary("Pdh",
Pdh.class, W32APIOptions.UNICODE_OPTIONS);
Pdh.class, W32APIOptions.DEFAULT_OPTIONS);


/** Maximum counter name length. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* Rasapi32.dll Interface.
*/
public interface Rasapi32 extends StdCallLibrary {
Rasapi32 INSTANCE = (Rasapi32) Native.loadLibrary("Rasapi32", Rasapi32.class, W32APIOptions.UNICODE_OPTIONS);
Rasapi32 INSTANCE = (Rasapi32) Native.loadLibrary("Rasapi32", Rasapi32.class, W32APIOptions.DEFAULT_OPTIONS);

/**
* The RasDial function establishes a RAS connection between a RAS client and a RAS server.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* @author dblock[at]dblock.org
*/
public interface Secur32 extends StdCallLibrary {
Secur32 INSTANCE = (Secur32) Native.loadLibrary("Secur32", Secur32.class, W32APIOptions.UNICODE_OPTIONS);
Secur32 INSTANCE = (Secur32) Native.loadLibrary("Secur32", Secur32.class, W32APIOptions.DEFAULT_OPTIONS);

/**
* Specifies a format for a directory service object name.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
public interface Shell32 extends ShellAPI, StdCallLibrary {

Shell32 INSTANCE = (Shell32) Native.loadLibrary("shell32", Shell32.class,
W32APIOptions.UNICODE_OPTIONS);
W32APIOptions.DEFAULT_OPTIONS);

/**
* This function can be used to copy, move, rename, or delete a file system object.
Expand Down
116 changes: 115 additions & 1 deletion contrib/platform/src/com/sun/jna/platform/win32/W32Service.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,29 @@

package com.sun.jna.platform.win32;

import java.util.List;

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
import com.sun.jna.platform.win32.WinNT.LUID;
import com.sun.jna.platform.win32.WinNT.LUID_AND_ATTRIBUTES;
import com.sun.jna.platform.win32.WinNT.TOKEN_PRIVILEGES;
import com.sun.jna.platform.win32.Winsvc.SC_ACTION;
import com.sun.jna.platform.win32.Winsvc.SC_HANDLE;
import com.sun.jna.platform.win32.Winsvc.SC_STATUS_TYPE;
import com.sun.jna.platform.win32.Winsvc.SERVICE_FAILURE_ACTIONS;
import com.sun.jna.platform.win32.Winsvc.SERVICE_FAILURE_ACTIONS_FLAG;
import com.sun.jna.platform.win32.Winsvc.SERVICE_STATUS_PROCESS;
import com.sun.jna.ptr.IntByReference;


/**
* Win32 Service wrapper
* @author EugineLev
Expand Down Expand Up @@ -46,7 +64,103 @@ public void close() {
_handle = null;
}
}


private void addShutdownPrivilegeToProcess() {
HANDLEByReference hToken = new HANDLEByReference();
LUID luid = new LUID();
Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(),
WinNT.TOKEN_ADJUST_PRIVILEGES, hToken);
Advapi32.INSTANCE.LookupPrivilegeValue("", WinNT.SE_SHUTDOWN_NAME, luid);
TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES(1);
tp.Privileges[0] = new LUID_AND_ATTRIBUTES(luid, new DWORD(WinNT.SE_PRIVILEGE_ENABLED));
Advapi32.INSTANCE.AdjustTokenPrivileges(hToken.getValue(), false, tp, tp.size(), null,
new IntByReference());
}

/**
* Set the failure actions of the specified service. Corresponds to
* <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms681988.aspx">ChangeServiceConfig2</a>
* with parameter dwInfoLevel set to SERVICE_CONFIG_FAILURE_ACTIONS.
*/
public void setFailureActions(List<SC_ACTION> actions, int resetPeriod, String rebootMsg,
String command) {
SERVICE_FAILURE_ACTIONS.ByReference actionStruct = new SERVICE_FAILURE_ACTIONS.ByReference();
actionStruct.dwResetPeriod = resetPeriod;
actionStruct.lpRebootMsg = rebootMsg;
actionStruct.lpCommand = command;
actionStruct.cActions = actions.size();

actionStruct.lpsaActions = new SC_ACTION.ByReference();
SC_ACTION[] actionArray = (SC_ACTION[])actionStruct.lpsaActions.toArray(actions.size());
boolean hasShutdownPrivilege = false;
int i = 0;
for (SC_ACTION action : actions) {
if (!hasShutdownPrivilege && action.type == Winsvc.SC_ACTION_REBOOT) {
addShutdownPrivilegeToProcess();
hasShutdownPrivilege = true;
}
actionArray[i].type = action.type;
actionArray[i].delay = action.delay;
i++;
}

if (!Advapi32.INSTANCE.ChangeServiceConfig2(_handle, Winsvc.SERVICE_CONFIG_FAILURE_ACTIONS,
actionStruct)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
}

private Pointer queryServiceConfig2(int type) {
IntByReference bufferSize = new IntByReference();
Advapi32.INSTANCE.QueryServiceConfig2(_handle, type, Pointer.NULL, 0, bufferSize);

Pointer buffer = new Memory(bufferSize.getValue());

if (!Advapi32.INSTANCE.QueryServiceConfig2(_handle, type, buffer, bufferSize.getValue(),
new IntByReference())) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}

return buffer;
}

/**
* Get the failure actions of the specified service. Corresponds to
* <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms681988.aspx">QueryServiceConfig2</a>
* with parameter dwInfoLevel set to SERVICE_CONFIG_FAILURE_ACTIONS.
*/
public SERVICE_FAILURE_ACTIONS getFailureActions() {
Pointer buffer = queryServiceConfig2(Winsvc.SERVICE_CONFIG_FAILURE_ACTIONS);
SERVICE_FAILURE_ACTIONS result = new SERVICE_FAILURE_ACTIONS(buffer);
return result;
}

/**
* Set the failure action flag of the specified service. Corresponds to
* <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms681988.aspx">ChangeServiceConfig2</a>
* with parameter dwInfoLevel set to SERVICE_CONFIG_FAILURE_ACTIONS_FLAG.
*/
public void setFailureActionsFlag(boolean flagValue) {
SERVICE_FAILURE_ACTIONS_FLAG flag = new SERVICE_FAILURE_ACTIONS_FLAG();
flag.fFailureActionsOnNonCrashFailures = flagValue ? 1 : 0;

if (!Advapi32.INSTANCE.ChangeServiceConfig2(_handle, Winsvc.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG,
flag)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
}

/**
* Get the failure actions flag of the specified service. Corresponds to
* <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms681988.aspx">QueryServiceConfig2</a>
* with parameter dwInfoLevel set to SERVICE_CONFIG_FAILURE_ACTIONS_FLAG.
*/
public boolean getFailureActionsFlag() {
Pointer buffer = queryServiceConfig2(Winsvc.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG);
SERVICE_FAILURE_ACTIONS_FLAG result = new SERVICE_FAILURE_ACTIONS_FLAG(buffer);
return result.fFailureActionsOnNonCrashFailures != 0;
}

/**
* Retrieves the current status of the specified service based on the specified information level.
* @return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public interface Winspool extends StdCallLibrary {
int PRINTER_ENUM_HIDE = 0x01000000;

Winspool INSTANCE = (Winspool) Native.loadLibrary("Winspool.drv",
Winspool.class, W32APIOptions.UNICODE_OPTIONS);
Winspool.class, W32APIOptions.DEFAULT_OPTIONS);

/**
* The EnumPrinters function enumerates available printers, print servers,
Expand Down
Loading