//
// System.ServiceProcess.Win32ServiceController
//
// Author:
// Gert Driesen (drieseng@users.sourceforge.net)
//
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
namespace System.ServiceProcess{
internal class Win32ServiceController : ServiceControllerImpl
{
SERVICE_STATUS_PROCESS _status;
public Win32ServiceController (ServiceController serviceController)
: base (serviceController)
{
}
public override bool CanPauseAndContinue {
get {
if ((int) _status.dwServiceType == 0)
_status = GetServiceStatus (ServiceController.ServiceName,
ServiceController.MachineName);
return (_status.dwControlsAccepted & SERVICE_CONTROL_ACCEPTED.SERVICE_ACCEPT_PAUSE_CONTINUE) != 0;
}
}
public override bool CanShutdown {
get {
if ((int) _status.dwServiceType == 0)
_status = GetServiceStatus (ServiceController.ServiceName,
ServiceController.MachineName);
return (_status.dwControlsAccepted & SERVICE_CONTROL_ACCEPTED.SERVICE_ACCEPT_SHUTDOWN) != 0;
}
}
public override bool CanStop {
get {
if ((int) _status.dwServiceType == 0)
_status = GetServiceStatus (ServiceController.ServiceName,
ServiceController.MachineName);
return (_status.dwControlsAccepted & SERVICE_CONTROL_ACCEPTED.SERVICE_ACCEPT_STOP) != 0;
}
}
public override ServiceController [] DependentServices {
get {
return GetDependentServices (ServiceController.ServiceName,
ServiceController.MachineName);
}
}
public override string DisplayName {
get {
string lookupName = ServiceController.ServiceName;
IntPtr scHandle = IntPtr.Zero;
try {
scHandle = OpenServiceControlManager (ServiceController.MachineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
if (lookupName.Length == 0) {
// if the service name is not available, then
// assume the specified name is in fact already a display
// name
try {
string serviceName = GetServiceName (scHandle,
lookupName);
ServiceController.InternalServiceName = serviceName;
ServiceController.Name = string.Empty;
return lookupName;
} catch (Win32Exception) {
}
}
if (ServiceController.InternalDisplayName.Length == 0)
return GetServiceDisplayName (scHandle, lookupName,
ServiceController.MachineName);
return ServiceController.InternalDisplayName;
} finally {
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
}
}
}
public override string ServiceName {
get {
string lookupName = ServiceController.Name;
if (lookupName.Length == 0)
lookupName = ServiceController.InternalDisplayName;
IntPtr scHandle = IntPtr.Zero;
try {
scHandle = OpenServiceControlManager (ServiceController.MachineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
// assume the specified name is in fact a display name
try {
string serviceName = GetServiceName (scHandle, lookupName);
ServiceController.InternalDisplayName = lookupName;
ServiceController.Name = string.Empty;
return serviceName;
} catch (Win32Exception) {
}
// instead of opening the service to verify whether it exists,
// we'll try to get its displayname and hereby avoid looking
// this up separately
string displayName = GetServiceDisplayName (scHandle,
lookupName, ServiceController.MachineName);
ServiceController.InternalDisplayName = displayName;
ServiceController.Name = string.Empty;
return lookupName;
} finally {
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
}
}
}
public override ServiceController [] ServicesDependedOn {
get {
return GetServiceDependencies (ServiceController.ServiceName,
ServiceController.MachineName);
}
}
public override ServiceType ServiceType {
get {
if ((int) _status.dwServiceType == 0)
_status = GetServiceStatus (ServiceController.ServiceName,
ServiceController.MachineName);
return _status.dwServiceType;
}
}
public override ServiceControllerStatus Status {
get {
if ((int) _status.dwServiceType == 0)
_status = GetServiceStatus (ServiceController.ServiceName,
ServiceController.MachineName);
return _status.dwCurrentState;
}
}
public override void Close ()
{
// clear status cache
_status.dwServiceType = 0;
}
public override void Continue ()
{
string serviceName = ServiceController.ServiceName;
string machineName = ServiceController.MachineName;
IntPtr scHandle = IntPtr.Zero;
IntPtr svcHandle = IntPtr.Zero;
try {
scHandle = OpenServiceControlManager (machineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_PAUSE_CONTINUE);
if (svcHandle == IntPtr.Zero)
throw CreateCannotOpenServiceException (serviceName,
machineName);
SERVICE_STATUS status = new SERVICE_STATUS ();
if (!ControlService (svcHandle, SERVICE_CONTROL_TYPE.SERVICE_CONTROL_CONTINUE, ref status))
throw new InvalidOperationException (string.Format (
CultureInfo.CurrentCulture, "Cannot resume {0} service"
+ " on computer '{1}'.", serviceName, machineName),
new Win32Exception ());
} finally {
if (svcHandle != IntPtr.Zero)
CloseServiceHandle (svcHandle);
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
}
}
public override void Dispose (bool disposing)
{
// we're not keeping any handles open
}
public override void ExecuteCommand (int command)
{
string serviceName = ServiceController.ServiceName;
string machineName = ServiceController.MachineName;
IntPtr scHandle = IntPtr.Zero;
IntPtr svcHandle = IntPtr.Zero;
try {
scHandle = OpenServiceControlManager (machineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
// MSDN: the hService handle must have the SERVICE_USER_DEFINED_CONTROL
// access right
svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_USER_DEFINED_CONTROL);
if (svcHandle == IntPtr.Zero)
throw CreateCannotOpenServiceException (serviceName,
machineName);
SERVICE_STATUS status = new SERVICE_STATUS ();
if (!ControlService (svcHandle, (SERVICE_CONTROL_TYPE) command, ref status))
throw new InvalidOperationException (string.Format (
CultureInfo.CurrentCulture, "Cannot control {0} service"
+ " on computer '{1}'.", serviceName, machineName),
new Win32Exception ());
} finally {
if (svcHandle != IntPtr.Zero)
CloseServiceHandle (svcHandle);
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
}
}
public override ServiceController [] GetDevices ()
{
return GetServices (ServiceController.MachineName,
SERVICE_TYPE.SERVICE_DRIVER, null);
}
public override ServiceController [] GetServices ()
{
return GetServices (ServiceController.MachineName,
SERVICE_TYPE.SERVICE_WIN32, null);
}
public override void Pause ()
{
string serviceName = ServiceController.ServiceName;
string machineName = ServiceController.MachineName;
IntPtr scHandle = IntPtr.Zero;
IntPtr svcHandle = IntPtr.Zero;
try {
scHandle = OpenServiceControlManager (machineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_PAUSE_CONTINUE);
if (svcHandle == IntPtr.Zero)
throw CreateCannotOpenServiceException (serviceName,
machineName);
SERVICE_STATUS status = new SERVICE_STATUS ();
if (!ControlService (svcHandle, SERVICE_CONTROL_TYPE.SERVICE_CONTROL_PAUSE, ref status))
throw new InvalidOperationException (string.Format (
CultureInfo.CurrentCulture, "Cannot pause {0} service"
+ " on computer '{1}'.", serviceName, machineName),
new Win32Exception ());
} finally {
if (svcHandle != IntPtr.Zero)
CloseServiceHandle (svcHandle);
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
}
}
public override void Refresh ()
{
// force refresh of status
_status.dwServiceType = 0;
}
public override void Start (string [] args)
{
string serviceName = ServiceController.ServiceName;
string machineName = ServiceController.MachineName;
IntPtr scHandle = IntPtr.Zero;
IntPtr svcHandle = IntPtr.Zero;
IntPtr [] arguments = new IntPtr [args.Length];
try {
scHandle = OpenServiceControlManager (machineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_START);
if (svcHandle == IntPtr.Zero)
throw CreateCannotOpenServiceException (serviceName,
machineName);
for (int i = 0; i < args.Length; i++) {
string argument = args [i];
arguments [i] = Marshal.StringToHGlobalAnsi (argument);
}
if (!StartService (svcHandle, arguments.Length, arguments))
throw new InvalidOperationException (string.Format (
CultureInfo.CurrentCulture, "Cannot start {0} service"
+ " on computer '{1}'.", serviceName, machineName),
new Win32Exception ());
} finally {
for (int i = 0; i < arguments.Length; i++)
Marshal.FreeHGlobal (arguments [i]);
if (svcHandle != IntPtr.Zero)
CloseServiceHandle (svcHandle);
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
}
}
public override void Stop ()
{
string serviceName = ServiceController.ServiceName;
string machineName = ServiceController.MachineName;
IntPtr scHandle = IntPtr.Zero;
IntPtr svcHandle = IntPtr.Zero;
try {
scHandle = OpenServiceControlManager (machineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_STOP);
if (svcHandle == IntPtr.Zero)
throw CreateCannotOpenServiceException (serviceName,
machineName);
SERVICE_STATUS status = new SERVICE_STATUS ();
if (!ControlService (svcHandle, SERVICE_CONTROL_TYPE.SERVICE_CONTROL_STOP, ref status))
throw new InvalidOperationException (string.Format (
CultureInfo.CurrentCulture, "Cannot stop {0} service"
+ " on computer '{1}'.", serviceName, machineName),
new Win32Exception ());
} finally {
if (svcHandle != IntPtr.Zero)
CloseServiceHandle (svcHandle);
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
}
}
private static ServiceController [] GetDependentServices (string serviceName, string machineName)
{
IntPtr scHandle = IntPtr.Zero;
IntPtr svcHandle = IntPtr.Zero;
IntPtr buffer = IntPtr.Zero;
try {
scHandle = OpenServiceControlManager (machineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_ENUMERATE_DEPENDENTS);
if (svcHandle == IntPtr.Zero)
throw CreateCannotOpenServiceException (serviceName, machineName);
uint bufferSize = 0;
uint bytesNeeded = 0;
uint servicesReturned = 0;
ServiceController [] services;
while (true) {
if (!EnumDependentServices (svcHandle, SERVICE_STATE_REQUEST.SERVICE_STATE_ALL, buffer, bufferSize, out bytesNeeded, out servicesReturned)) {
int err = Marshal.GetLastWin32Error ();
if (err == ERROR_MORE_DATA) {
buffer = Marshal.AllocHGlobal ((int) bytesNeeded);
bufferSize = bytesNeeded;
} else {
throw new Win32Exception (err);
}
} else {
int iPtr = buffer.ToInt32 ();
services = new ServiceController [servicesReturned];
for (int i = 0; i < servicesReturned; i++) {
ENUM_SERVICE_STATUS serviceStatus = (ENUM_SERVICE_STATUS) Marshal.PtrToStructure (
new IntPtr (iPtr), typeof (ENUM_SERVICE_STATUS));
// TODO: use internal ctor that takes displayname too ?
services [i] = new ServiceController (serviceStatus.pServiceName,
machineName);
// move on to the next services
iPtr += ENUM_SERVICE_STATUS.SizeOf;
}
// we're done, so exit the loop
break;
}
}
return services;
} finally {
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
if (svcHandle != IntPtr.Zero)
CloseServiceHandle (svcHandle);
if (buffer != IntPtr.Zero)
Marshal.FreeHGlobal (buffer);
}
}
private static ServiceController [] GetServiceDependencies (string serviceName, string machineName)
{
IntPtr scHandle = IntPtr.Zero;
IntPtr svcHandle = IntPtr.Zero;
IntPtr buffer = IntPtr.Zero;
try {
scHandle = OpenServiceControlManager (machineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_QUERY_CONFIG);
if (svcHandle == IntPtr.Zero)
throw CreateCannotOpenServiceException (serviceName, machineName);
uint bufferSize = 0;
uint bytesNeeded = 0;
ServiceController [] services;
while (true) {
if (!QueryServiceConfig (svcHandle, buffer, bufferSize, out bytesNeeded)) {
int err = Marshal.GetLastWin32Error ();
if (err == ERROR_INSUFFICIENT_BUFFER) {
buffer = Marshal.AllocHGlobal ((int) bytesNeeded);
bufferSize = bytesNeeded;
} else {
throw new Win32Exception (err);
}
} else {
QUERY_SERVICE_CONFIG config = (QUERY_SERVICE_CONFIG) Marshal.PtrToStructure (
buffer, typeof (QUERY_SERVICE_CONFIG));
Hashtable depServices = new Hashtable ();
IntPtr iPtr = config.lpDependencies;
StringBuilder sb = new StringBuilder ();
string currentChar = Marshal.PtrToStringUni (iPtr, 1);
while (currentChar != "\0") {
sb.Append (currentChar);
iPtr = new IntPtr (iPtr.ToInt64 () + Marshal.SystemDefaultCharSize);
currentChar = Marshal.PtrToStringUni (iPtr, 1);
if (currentChar != "\0") {
continue;
}
iPtr = new IntPtr (iPtr.ToInt64 () + Marshal.SystemDefaultCharSize);
currentChar = Marshal.PtrToStringUni (iPtr, 1);
string dependency = sb.ToString ();
if (dependency [0] == SC_GROUP_IDENTIFIER) {
ServiceController [] groupServices = GetServices (
machineName, SERVICE_TYPE.SERVICE_WIN32,
dependency.Substring (1));
foreach (ServiceController sc in groupServices) {
if (!depServices.Contains (sc.ServiceName))
depServices.Add (sc.ServiceName, sc);
}
} else if (!depServices.Contains (dependency)) {
depServices.Add (dependency, new ServiceController (dependency, machineName));
}
sb.Length = 0;
}
services = new ServiceController [depServices.Count];
depServices.Values.CopyTo (services, 0);
break;
}
}
return services;
} finally {
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
if (svcHandle != IntPtr.Zero)
CloseServiceHandle (svcHandle);
if (buffer != IntPtr.Zero)
Marshal.FreeHGlobal (buffer);
}
}
private static string GetServiceDisplayName (IntPtr scHandle, string serviceName, string machineName)
{
StringBuilder buffer = new StringBuilder ();
uint bufferSize = (uint) buffer.Capacity;
while (true) {
if (!GetServiceDisplayName (scHandle, serviceName, buffer, ref bufferSize)) {
int err = Marshal.GetLastWin32Error ();
if (err == ERROR_INSUFFICIENT_BUFFER) {
// allocate additional byte for terminating null char
buffer = new StringBuilder ((int) bufferSize + 1);
bufferSize = (uint) buffer.Capacity;
} else {
throw new InvalidOperationException (string.Format (
CultureInfo.CurrentCulture, "Service {0} was not"
+ " found on computer '{1}'.", serviceName,
machineName), new Win32Exception ());
}
} else {
return buffer.ToString ();
}
}
}
private static string GetServiceName (IntPtr scHandle, string displayName)
{
StringBuilder buffer = new StringBuilder ();
uint bufferSize = (uint) buffer.Capacity;
while (true) {
if (!GetServiceKeyName (scHandle, displayName, buffer, ref bufferSize)) {
int err = Marshal.GetLastWin32Error ();
if (err == ERROR_INSUFFICIENT_BUFFER) {
// allocate additional byte for terminating null char
buffer = new StringBuilder ((int) bufferSize + 1);
bufferSize = (uint) buffer.Capacity;
} else {
throw new Win32Exception ();
}
} else {
return buffer.ToString ();
}
}
}
private static SERVICE_STATUS_PROCESS GetServiceStatus (string serviceName, string machineName)
{
IntPtr scHandle = IntPtr.Zero;
IntPtr svcHandle = IntPtr.Zero;
IntPtr buffer = IntPtr.Zero;
try {
scHandle = OpenServiceControlManager (machineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_QUERY_STATUS);
if (svcHandle == IntPtr.Zero)
throw CreateCannotOpenServiceException (serviceName, machineName);
int bufferSize = 0;
int bytesNeeded = 0;
while (true) {
if (!QueryServiceStatusEx (svcHandle, SC_STATUS_PROCESS_INFO, buffer, bufferSize, out bytesNeeded)) {
int err = Marshal.GetLastWin32Error ();
if (err == ERROR_INSUFFICIENT_BUFFER) {
buffer = Marshal.AllocHGlobal (bytesNeeded);
bufferSize = bytesNeeded;
} else {
throw new Win32Exception (err);
}
} else {
SERVICE_STATUS_PROCESS serviceStatus = (SERVICE_STATUS_PROCESS) Marshal.PtrToStructure (
buffer, typeof (SERVICE_STATUS_PROCESS));
return serviceStatus;
}
}
} finally {
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
if (svcHandle != IntPtr.Zero)
CloseServiceHandle (svcHandle);
if (buffer != IntPtr.Zero)
Marshal.FreeHGlobal (buffer);
}
}
private static ServiceController [] GetServices (string machineName, SERVICE_TYPE serviceType, string group)
{
IntPtr scHandle = IntPtr.Zero;
IntPtr buffer = IntPtr.Zero;
try {
#if NET_2_0
scHandle = OpenServiceControlManager (machineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_ENUMERATE_SERVICE);
#else
scHandle = OpenServiceControlManager (machineName,
SERVICE_MANAGER_RIGHTS.SC_MANAGER_ENUMERATE_SERVICE, true);
#endif
uint bufferSize = 0;
uint bytesNeeded = 0;
uint servicesReturned = 0;
uint resumeHandle = 0;
ServiceController [] services;
while (true) {
if (!EnumServicesStatusEx (scHandle, SC_ENUM_PROCESS_INFO, serviceType, SERVICE_STATE_REQUEST.SERVICE_STATE_ALL, buffer, bufferSize, out bytesNeeded, out servicesReturned, ref resumeHandle, group)) {
int err = Marshal.GetLastWin32Error ();
if (err == ERROR_MORE_DATA) {
buffer = Marshal.AllocHGlobal ((int) bytesNeeded);
bufferSize = bytesNeeded;
} else {
throw new Win32Exception (err);
}
} else {
int iPtr = buffer.ToInt32 ();
services = new ServiceController [servicesReturned];
for (int i = 0; i < servicesReturned; i++) {
ENUM_SERVICE_STATUS_PROCESS serviceStatus = (ENUM_SERVICE_STATUS_PROCESS) Marshal.PtrToStructure (
new IntPtr (iPtr), typeof (ENUM_SERVICE_STATUS_PROCESS));
// TODO: use internal ctor that takes displayname too
services [i] = new ServiceController (serviceStatus.pServiceName,
machineName);
// move on to the next services
iPtr += ENUM_SERVICE_STATUS_PROCESS.SizeOf;
}
// we're done, so exit the loop
break;
}
}
return services;
} finally {
if (scHandle != IntPtr.Zero)
CloseServiceHandle (scHandle);
if (buffer != IntPtr.Zero)
Marshal.FreeHGlobal (buffer);
}
}
private static IntPtr OpenServiceControlManager (string machineName, SERVICE_MANAGER_RIGHTS rights)
{
return OpenServiceControlManager (machineName, rights, false);
}
private static IntPtr OpenServiceControlManager (string machineName, SERVICE_MANAGER_RIGHTS rights, bool ignoreWin32Error)
{
IntPtr scHandle = OpenSCManager (machineName, SERVICES_ACTIVE_DATABASE,
rights);
if (scHandle == IntPtr.Zero) {
string msg = string.Format (CultureInfo.CurrentCulture,
"Cannot open Service Control Manager on computer '{0}'."
+ " This operation might require other priviliges.",
machineName);
if (ignoreWin32Error)
throw new InvalidOperationException (msg);
throw new InvalidOperationException (msg, new Win32Exception ());
}
return scHandle;
}
private static InvalidOperationException CreateCannotOpenServiceException (string serviceName, string machineName)
{
return new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
"Cannot open {0} service on computer '{1}'.", serviceName, machineName),
new Win32Exception ());
}
#region PInvoke declaration
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern void CloseServiceHandle (IntPtr SCHANDLE);
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool ControlService (
IntPtr hService,
SERVICE_CONTROL_TYPE dwControl,
ref SERVICE_STATUS lpServiceStatus);
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool EnumDependentServices (
IntPtr hService,
SERVICE_STATE_REQUEST dwServiceState,
IntPtr lpServices,
uint cbBufSize,
out uint pcbBytesNeeded,
out uint lpServicesReturned);
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool EnumServicesStatusEx (
IntPtr hSCManager,
int InfoLevel,
SERVICE_TYPE dwServiceType,
SERVICE_STATE_REQUEST dwServiceState,
IntPtr lpServices,
uint cbBufSize,
out uint pcbBytesNeeded,
out uint lpServicesReturned,
ref uint lpResumeHandle,
string pszGroupName);
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool GetServiceDisplayName (
IntPtr hSCManager,
string lpServiceName,
StringBuilder lpDisplayName,
ref uint lpcchBuffer);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool GetServiceKeyName (
IntPtr hSCManager,
string lpDisplayName,
StringBuilder lpServiceName,
ref uint lpcchBuffer);
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr OpenSCManager (
string lpMachineName,
string lpSCDB,
SERVICE_MANAGER_RIGHTS scParameter);
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr OpenService (
IntPtr SCHANDLE,
string lpSvcName,
SERVICE_RIGHTS dwNumServiceArgs);
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool QueryServiceConfig (
IntPtr hService,
IntPtr lpServiceConfig,
uint cbBufSize,
out uint pcbBytesNeeded);
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool QueryServiceStatusEx (
IntPtr serviceHandle,
int InfoLevel,
IntPtr lpBuffer,
int cbBufSize,
out int pcbBytesNeeded);
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool StartService (
IntPtr SVHANDLE,
int dwNumServiceArgs,
IntPtr [] lpServiceArgVectors);
private const int SC_ENUM_PROCESS_INFO = 0;
private const char SC_GROUP_IDENTIFIER = '+';
private const int SC_STATUS_PROCESS_INFO = 0;
private const int SERVICE_NO_CHANGE = -1;
private const int ERROR_MORE_DATA = 234;
private const int ERROR_INSUFFICIENT_BUFFER = 122;
private const int STANDARD_RIGHTS_REQUIRED = 0xf0000;
private const string SERVICES_ACTIVE_DATABASE = "ServicesActive";
internal struct QUERY_SERVICE_CONFIG
{
public int dwServiceType;
public int dwStartType;
public int dwErrorControl;
public IntPtr lpBinaryPathName;
public IntPtr lpLoadOrderGroup;
public int dwTagId;
public IntPtr lpDependencies;
public IntPtr lpServiceStartName;
public IntPtr lpDisplayName;
}
[Flags]
private enum SERVICE_RIGHTS
{
SERVICE_QUERY_CONFIG = 1,
SERVICE_CHANGE_CONFIG = 2,
SERVICE_QUERY_STATUS = 4,
SERVICE_ENUMERATE_DEPENDENTS = 8,
SERVICE_START = 16,
SERVICE_STOP = 32,
SERVICE_PAUSE_CONTINUE = 64,
SERVICE_INTERROGATE = 128,
SERVICE_USER_DEFINED_CONTROL = 256,
SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG |
SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP |
SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE |
SERVICE_USER_DEFINED_CONTROL)
}
private enum SERVICE_MANAGER_RIGHTS : uint
{
STANDARD_RIGHTS_READ = 0x20000,
STANDARD_RIGHTS_WRITE = 0x20000,
STANDARD_RIGHTS_EXECUTE = 0x20000,
STANDARD_RIGHTS_ALL = 0x1F0000,
SC_MANAGER_ALL_ACCESS = 0xf003f,
SC_MANAGER_CONNECT = 1,
SC_MANAGER_CREATE_SERVICE = 2,
SC_MANAGER_ENUMERATE_SERVICE = 4,
SC_MANAGER_LOCK = 8,
SC_MANAGER_QUERY_LOCK_STATUS = 16,
SC_MANAGER_MODIFY_BOOT_CONFIG = 32,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000
}
[StructLayout (LayoutKind.Sequential)]
private struct ENUM_SERVICE_STATUS_PROCESS
{
public static readonly int SizeOf = Marshal.SizeOf (typeof (ENUM_SERVICE_STATUS_PROCESS));
[MarshalAs (UnmanagedType.LPWStr)]
public string pServiceName;
[MarshalAs (UnmanagedType.LPWStr)]
public string pDisplayName;
public SERVICE_STATUS_PROCESS ServiceStatus;
}
[StructLayout (LayoutKind.Sequential)]
private struct ENUM_SERVICE_STATUS
{
public static readonly int SizeOf = Marshal.SizeOf (typeof (ENUM_SERVICE_STATUS));
[MarshalAs (UnmanagedType.LPWStr)]
public string pServiceName;
[MarshalAs (UnmanagedType.LPWStr)]
public string pDisplayName;
public SERVICE_STATUS ServiceStatus;
}
[StructLayout (LayoutKind.Sequential)]
private struct SERVICE_STATUS
{
public ServiceType dwServiceType;
public ServiceControllerStatus dwCurrentState;
public SERVICE_CONTROL_ACCEPTED dwControlsAccepted;
public int dwWin32ExitCode;
public int dwServiceSpecificExitCode;
public uint dwCheckPoint;
public uint dwWaitHint;
}
[StructLayout (LayoutKind.Sequential, Pack = 1)]
private struct SERVICE_STATUS_PROCESS
{
public static readonly int SizeOf = Marshal.SizeOf (typeof (SERVICE_STATUS_PROCESS));
public ServiceType dwServiceType;
public ServiceControllerStatus dwCurrentState;
public SERVICE_CONTROL_ACCEPTED dwControlsAccepted;
public int dwWin32ExitCode;
public int dwServiceSpecificExitCode;
public int dwCheckPoint;
public int dwWaitHint;
public int dwProcessId;
public int dwServiceFlags;
}
private enum SERVICE_TYPE
{
SERVICE_KERNEL_DRIVER = 0x1,
SERVICE_FILE_SYSTEM_DRIVER = 0x2,
SERVICE_ADAPTER = 0x4,
SERVICE_RECOGNIZER_DRIVER = 0x8,
SERVICE_DRIVER = (SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER),
SERVICE_WIN32_OWN_PROCESS = 0x10,
SERVICE_WIN32_SHARE_PROCESS = 0x20,
SERVICE_INTERACTIVE_PROCESS = 0x100,
SERVICETYPE_NO_CHANGE = SERVICE_NO_CHANGE,
SERVICE_WIN32 = (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS),
SERVICE_TYPE_ALL = (SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS)
}
private enum SERVICE_START_TYPE
{
SERVICE_BOOT_START = 0x0,
SERVICE_SYSTEM_START = 0x1,
SERVICE_AUTO_START = 0x2,
SERVICE_DEMAND_START = 0x3,
SERVICE_DISABLED = 0x4,
SERVICESTARTTYPE_NO_CHANGE = SERVICE_NO_CHANGE
}
private enum SERVICE_ERROR_CONTROL
{
SERVICE_ERROR_IGNORE = 0x0,
SERVICE_ERROR_NORMAL = 0x1,
SERVICE_ERROR_SEVERE = 0x2,
SERVICE_ERROR_CRITICAL = 0x3,
msidbServiceInstallErrorControlVital = 0x8000,
SERVICEERRORCONTROL_NO_CHANGE = SERVICE_NO_CHANGE
}
private enum SERVICE_STATE_REQUEST
{
SERVICE_ACTIVE = 0x1,
SERVICE_INACTIVE = 0x2,
SERVICE_STATE_ALL = (SERVICE_ACTIVE | SERVICE_INACTIVE)
}
private enum SERVICE_CONTROL_TYPE
{
SERVICE_CONTROL_STOP = 0x1,
SERVICE_CONTROL_PAUSE = 0x2,
SERVICE_CONTROL_CONTINUE = 0x3,
SERVICE_CONTROL_INTERROGATE = 0x4,
SERVICE_CONTROL_SHUTDOWN = 0x5,
SERVICE_CONTROL_PARAMCHANGE = 0x6,
SERVICE_CONTROL_NETBINDADD = 0x7,
SERVICE_CONTROL_NETBINDREMOVE = 0x8,
SERVICE_CONTROL_NETBINDENABLE = 0x9,
SERVICE_CONTROL_NETBINDDISABLE = 0xA,
SERVICE_CONTROL_DEVICEEVENT = 0xB,
SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0xC,
SERVICE_CONTROL_POWEREVENT = 0xD,
SERVICE_CONTROL_SESSIONCHANGE = 0xE
}
[Flags]
private enum SERVICE_CONTROL_ACCEPTED
{
SERVICE_ACCEPT_NONE = 0x0,
SERVICE_ACCEPT_STOP = 0x1,
SERVICE_ACCEPT_PAUSE_CONTINUE = 0x2,
SERVICE_ACCEPT_SHUTDOWN = 0x4,
SERVICE_ACCEPT_PARAMCHANGE = 0x8,
SERVICE_ACCEPT_NETBINDCHANGE = 0x10,
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x20,
SERVICE_ACCEPT_POWEREVENT = 0x40,
SERVICE_ACCEPT_SESSIONCHANGE = 0x80
}
#endregion PInvoke declaration
}
}
|