Author: mturk
Date: Tue Jul 19 21:37:40 2011
New Revision: 1148552

URL: http://svn.apache.org/viewvc?rev=1148552&view=rev
Log:
Implement more of win32 Service API

Modified:
    
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Service.java
    
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/ServiceControl.java
    
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Win32.java
    commons/sandbox/runtime/trunk/src/main/native/os/win32/winapi.c

Modified: 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Service.java
URL: 
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Service.java?rev=1148552&r1=1148551&r2=1148552&view=diff
==============================================================================
--- 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Service.java
 (original)
+++ 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Service.java
 Tue Jul 19 21:37:40 2011
@@ -17,6 +17,7 @@
 package org.apache.commons.runtime.platform.windows;
 
 import java.io.Closeable;
+import java.io.File;
 import java.io.IOException;
 import java.util.EnumSet;
 import java.util.List;
@@ -34,7 +35,7 @@ public final class Service implements Cl
     private String  serviceName;
     private String  displayName;
     private int[]   serviceStatusProcess;
-    private long    currentQueryWindow = 0L;
+    private long    prevQueryStatus = 0L;
 
     // Named indexes inside serviceStatusProcess array.
     // They are here just for easier entry access.
@@ -51,6 +52,17 @@ public final class Service implements Cl
     private static final int     startType                  =  9;
     private static final int     errorControl               = 10;
 
+    // Parameters for the ChangeServiceConfig
+    private String      sBinaryPathName     = null;
+    private String      sLoadOrderGroup     = null;
+    private String[]    sDependencies       = null;
+    private String      sServiceStartName   = null;
+    private String      sPassword           = null;
+    private String      sDisplayName        = null;
+    private int         sServiceType        = -1;
+    private int         sStartType          = -1;
+    private int         sErrorControl       = -1;
+
 
     private Service()
     {
@@ -170,12 +182,12 @@ public final class Service implements Cl
     {
         if (handle == 0L)
             return;
-        long now = System.nanoTime();
-        // Use one millisecond query window
+        long now = System.currentTimeMillis();
+        // Use basic millisecond resolution window
         //
-        if (now > (currentQueryWindow + 1000000)) {
+        if (now > prevQueryStatus) {
             Win32.QueryServiceStatusEx(handle, serviceStatusProcess);
-            currentQueryWindow = now;
+            prevQueryStatus = now;
         }
     }
 
@@ -301,4 +313,106 @@ public final class Service implements Cl
         return serviceStatusProcess[serviceFlags];
 
     }
+
+    /**
+     * Sets the fully-qualified path to the service binary file.
+     * <p>
+     * If the path contains a space, it must be quoted so that it is
+     * correctly interpreted. For example,
+     * {@code "d:\\my share\\myservice.exe"} should be specified as
+     * {@code "\"d:\\my share\\myservice.exe\""}.
+     * </p>
+     * <p>
+     * The path can also include arguments for an auto-start service.
+     * For example, {@code "d:\\myshare\\myservice.exe arg1 arg2"}.
+     * These arguments are passed to the service entry point
+     * (typically the main function).
+     * </p>
+     * <p>
+     * If you specify a path on another computer, the share must be accessible
+     * by the computer account of the local computer because this is the 
security
+     * context used in the remote call. However, this requirement allows any
+     * potential vulnerabilities in the remote computer to affect the local
+     * computer. Therefore, it is best to use a local file.
+     *
+     * @param path the fully-qualified path to the service binary file.
+     */
+    public void setBinaryPathName(String path)
+    {
+        if (path.indexOf(' ') == -1)
+            sBinaryPathName = path;
+        else
+            sBinaryPathName = "\"" + path + "\"";
+    }
+
+    public void setBinaryPathName(File path)
+    {
+        setBinaryPathName(path.getPath());
+    }
+
+    /**
+     * Starts a service.
+     *
+     * @param args strings to be passed to the {@code ServiceMain} function for
+     *             the service as arguments.
+     */
+    public void start(String[] args)
+        throws InvalidHandleException, SystemException
+    {
+        if (handle == 0L)
+            throw new InvalidHandleException();
+        int nargs = args == null ? 0 : args.length;
+        int rc = Win32.StartService(handle, nargs, args);
+        if (rc != 0) {
+            if (Status.IS_EACCES(rc))
+                throw new SecurityException(Status.describe(rc));
+            else
+                throw new SystemException(Status.describe(rc));
+        }
+    }
+
+    /**
+     * Sends a control code to a service.
+     *
+     * @param c control code.
+     */
+    public void control(ServiceControl c)
+        throws InvalidHandleException, SystemException
+    {
+        if (handle == 0L)
+            throw new InvalidHandleException();
+        int rc = Win32.ControlService(handle, c.valueOf(), 
serviceStatusProcess);
+        if (rc != 0) {
+            if (Status.IS_EACCES(rc))
+                throw new SecurityException(Status.describe(rc));
+            else
+                throw new SystemException(Status.describe(rc));
+        }
+    }
+
+    /**
+     * Sends a user-defined control code to a service.
+     * <p>
+     * The service defines the action associated with the control code.
+     * The service handle must have the {@code SERVICE_USER_DEFINED_CONTROL}
+     * access right.
+     *
+     * @param c user-defined control code in range {@code 128 to 255}.
+     */
+    public void control(int c)
+        throws InvalidHandleException, SystemException
+    {
+        if (handle == 0L)
+            throw new InvalidHandleException();
+        if (c < 128 || c > 255)
+            throw new IllegalArgumentException("control code must be in range 
from 128 to 255");
+        int rc = Win32.ControlService(handle, c, serviceStatusProcess);
+        if (rc != 0) {
+            if (Status.IS_EACCES(rc))
+                throw new SecurityException(Status.describe(rc));
+            else
+                throw new SystemException(Status.describe(rc));
+        }
+    }
+
 }

Modified: 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/ServiceControl.java
URL: 
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/ServiceControl.java?rev=1148552&r1=1148551&r2=1148552&view=diff
==============================================================================
--- 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/ServiceControl.java
 (original)
+++ 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/ServiceControl.java
 Tue Jul 19 21:37:40 2011
@@ -80,7 +80,7 @@ public enum ServiceControl
             if (e.value == value)
                 return e;
         }
-        if (value > USER.value)
+        if (value > 127 && value < 256)
             return USER;
         else
             return UNKNOWN;

Modified: 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Win32.java
URL: 
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Win32.java?rev=1148552&r1=1148551&r2=1148552&view=diff
==============================================================================
--- 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Win32.java
 (original)
+++ 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/Win32.java
 Tue Jul 19 21:37:40 2011
@@ -90,6 +90,22 @@ final class Win32
                                                   String[] dependencies,
                                                   String serviceStartName,
                                                   String password);
+    public static native int        ChangeServiceConfig(long svc,
+                                                  int serviceType,
+                                                  int startType,
+                                                  int errorControl,
+                                                  String binaryPathName,
+                                                  String loadOrderGroup,
+                                                  String[] dependencies,
+                                                  String serviceStartName,
+                                                  String password,
+                                                  String displayName);
+    /**
+     * Simplified version of ChangeServiceConfig2 API call
+     * that uses SERVICE_CONFIG_DESCRIPTION infoLevel
+     */
+    public static native int        ChangeServiceConfig2(long svc,
+                                                  String description);
 
     public static final int         HEAP_POINTER            = 1;
     public static final int         SLICE_POINTER           = 2;

Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/winapi.c
URL: 
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/winapi.c?rev=1148552&r1=1148551&r2=1148552&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/winapi.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/winapi.c Tue Jul 19 
21:37:40 2011
@@ -375,3 +375,58 @@ ACR_WIN_EXPORT(jlong, Win32, CreateServi
 
     return P2J(svc);
 }
+
+ACR_WIN_EXPORT(jint, Win32, ChangeServiceConfig)(JNI_STDARGS, jlong hsvc,
+                                            jint stype, jint sstart,
+                                            jint errc, jstring path, jstring 
ldgrp,
+                                            jobjectArray deps, jstring user,
+                                            jstring password, jstring display)
+{
+    int rc = 0;
+    SC_HANDLE svc = J2P(hsvc, SC_HANDLE);
+
+    WITH_DWCS(display) {
+    WITH_DWCS(path) {
+    WITH_DWCS(ldgrp) {
+    WITH_DWCS(user) {
+    WITH_DWCS(password) {
+        wchar_t *wdeps = AcrMszJavaStringArrayW(env, deps);
+        /* Call the real API */
+        if (!ChangeServiceConfigW(svc,
+                                  stype,
+                                  sstart,
+                                  errc,
+                                  J2S(path),
+                                  J2S(ldgrp),
+                                  0,
+                                  wdeps,
+                                  J2S(user),
+                                  J2S(password),
+                                  J2S(display)))
+            rc = ACR_GET_OS_ERROR();
+        AcrFree(wdeps);
+    } DONE_WITH_STR(password);
+    } DONE_WITH_STR(user);
+    } DONE_WITH_STR(ldgrp);
+    } DONE_WITH_STR(path);
+    } DONE_WITH_STR(display);
+
+    return rc;
+}
+
+ACR_WIN_EXPORT(jint, Win32, ChangeServiceConfig2)(JNI_STDARGS, jlong hsvc,
+                                                  jstring description)
+{
+    int rc = 0;
+    SC_HANDLE svc = J2P(hsvc, SC_HANDLE);
+
+    WITH_WSTR(description) {
+        SERVICE_DESCRIPTION desc = { J2S(description) };
+        if (!ChangeServiceConfig2W(svc,
+                                   SERVICE_CONFIG_DESCRIPTION,
+                                   &desc))
+            rc = ACR_GET_OS_ERROR();
+    } DONE_WITH_STR(description);
+
+    return rc;
+}


Reply via email to