// // 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 } }