예제 #1
0
 /// <summary>
 /// Get the security descriptor of the SCM.
 /// </summary>
 /// <returns></returns>
 public static SecurityDescriptor GetScmSecurityDescriptor()
 {
     using (SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(null, null,
                                                                     ServiceControlManagerAccessRights.Connect | ServiceControlManagerAccessRights.ReadControl))
     {
         return(GetServiceSecurityDescriptor(scm, "scm"));
     }
 }
        /// <summary>
        /// Create a new service.
        /// </summary>
        /// <param name="name">The name of the service.</param>
        /// <param name="display_name">The display name for the service.</param>
        /// <param name="service_type">The service type.</param>
        /// <param name="start_type">The service start type.</param>
        /// <param name="error_control">Error control.</param>
        /// <param name="binary_path_name">Path to the service executable.</param>
        /// <param name="load_order_group">Load group order.</param>
        /// <param name="dependencies">List of service dependencies.</param>
        /// <param name="service_start_name">The username for the service.</param>
        /// <param name="password">Password for the username if needed.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The registered service information.</returns>
        public static NtResult <RunningService> CreateService(
            string name,
            string display_name,
            ServiceType service_type,
            ServiceStartType start_type,
            ServiceErrorControl error_control,
            string binary_path_name,
            string load_order_group,
            IEnumerable <string> dependencies,
            string service_start_name,
            SecureString password,
            bool throw_on_error)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException($"'{nameof(name)}' cannot be null or empty", nameof(name));
            }

            if (string.IsNullOrEmpty(binary_path_name))
            {
                throw new ArgumentException($"'{nameof(binary_path_name)}' cannot be null or empty", nameof(binary_path_name));
            }

            using (var scm = Win32NativeMethods.OpenSCManager(null, null,
                                                              ServiceControlManagerAccessRights.Connect | ServiceControlManagerAccessRights.CreateService))
            {
                if (scm.IsInvalid)
                {
                    return(Win32Utils.GetLastWin32Error().CreateResultFromDosError <RunningService>(throw_on_error));
                }

                IntPtr pwd = password != null?Marshal.SecureStringToBSTR(password) : IntPtr.Zero;

                try
                {
                    using (var service = Win32NativeMethods.CreateService(scm, name, display_name, ServiceAccessRights.MaximumAllowed,
                                                                          service_type, start_type, error_control, binary_path_name, load_order_group, null, dependencies.ToMultiString(),
                                                                          string.IsNullOrEmpty(service_start_name) ? null : service_start_name, pwd))
                    {
                        if (service.IsInvalid)
                        {
                            return(Win32Utils.GetLastWin32Error().CreateResultFromDosError <RunningService>(throw_on_error));
                        }
                        return(new RunningService(name, display_name ?? string.Empty, QueryStatus(service)).CreateResult());
                    }
                }
                finally
                {
                    if (pwd != IntPtr.Zero)
                    {
                        Marshal.FreeBSTR(pwd);
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Get the PID of a running service.
        /// </summary>
        /// <param name="name">The name of the service.</param>
        /// <returns>Returns the PID of the running service, or 0 if not running.</returns>
        /// <exception cref="SafeWin32Exception">Thrown on error.</exception>
        public static int GetServiceProcessId(string name)
        {
            using (SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(null, null,
                                                                            ServiceControlManagerAccessRights.Connect)) {
                if (scm.IsInvalid)
                {
                    throw new SafeWin32Exception();
                }

                return(GetServiceProcessId(scm, name));
            }
        }
예제 #4
0
        /// <summary>
        /// Get the information about a service.
        /// </summary>
        /// <param name="name">The name of the service.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The service information.</returns>
        public static NtResult <ServiceInformation> GetServiceInformation(string name, bool throw_on_error)
        {
            using (SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(null, null,
                                                                            ServiceControlManagerAccessRights.Connect)) {
                if (scm.IsInvalid)
                {
                    return(Win32Utils.GetLastWin32Error().CreateResultFromDosError <ServiceInformation>(throw_on_error));
                }

                return(GetServiceSecurityInformation(scm, name, DEFAULT_SECURITY_INFORMATION, throw_on_error));
            }
        }
예제 #5
0
        /// <summary>
        /// Get the information about a service.
        /// </summary>
        /// <param name="name">The name of the service.</param>
        /// <returns>The servicec information.</returns>
        public static ServiceInformation GetServiceInformation(string name)
        {
            using (SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(null, null,
                                                                            ServiceControlManagerAccessRights.Connect | ServiceControlManagerAccessRights.ReadControl))
            {
                if (scm.IsInvalid)
                {
                    throw new SafeWin32Exception();
                }

                return(GetServiceSecurityInformation(scm, name));
            }
        }
예제 #6
0
        /// <summary>
        /// Get the security descriptor of the SCM.
        /// </summary>
        /// <param name="security_information">Parts of the security descriptor to return.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The SCM security descriptor.</returns>
        public static NtResult <SecurityDescriptor> GetScmSecurityDescriptor(SecurityInformation security_information, bool throw_on_error)
        {
            var desired_access = NtSecurity.QuerySecurityAccessMask(security_information).ToSpecificAccess <ServiceControlManagerAccessRights>();

            using (SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(null, null,
                                                                            ServiceControlManagerAccessRights.Connect | desired_access)) {
                if (scm.IsInvalid)
                {
                    return(Win32Utils.GetLastWin32Error().CreateResultFromDosError <SecurityDescriptor>(throw_on_error));
                }
                return(GetServiceSecurityDescriptor(scm, "scm", security_information, throw_on_error));
            }
        }
예제 #7
0
        /// <summary>
        /// Set the SCM security descriptor.
        /// </summary>
        /// <param name="security_descriptor">The security descriptor to set.</param>
        /// <param name="security_information">The parts of the security descriptor to set.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The NT status code.</returns>
        public static NtStatus SetScmSecurityDescriptor(SecurityDescriptor security_descriptor,
                                                        SecurityInformation security_information, bool throw_on_error)
        {
            var desired_access = NtSecurity.SetSecurityAccessMask(security_information).ToSpecificAccess <ServiceControlManagerAccessRights>();

            using (SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(null, null,
                                                                            ServiceControlManagerAccessRights.Connect | desired_access)) {
                if (scm.IsInvalid)
                {
                    return(Win32Utils.GetLastWin32Error().ToNtException(throw_on_error));
                }
                return(SetServiceSecurityDescriptor(scm, security_information, security_descriptor, throw_on_error));
            }
        }
예제 #8
0
        /// <summary>
        /// Get a list of registered services.
        /// </summary>
        /// <returns>A list of running services with process IDs.</returns>
        private static IEnumerable <RunningService> GetServices(SERVICE_STATE service_state)
        {
            using (SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(null, null,
                                                                            ServiceControlManagerAccessRights.Connect | ServiceControlManagerAccessRights.EnumerateService))
            {
                if (scm.IsInvalid)
                {
                    throw new SafeWin32Exception();
                }

                ServiceType service_types = ServiceType.Win32OwnProcess | ServiceType.Win32ShareProcess;
                if (!NtObjectUtils.IsWindows81OrLess)
                {
                    service_types |= ServiceType.UserService;
                }

                const int Length = 32 * 1024;
                using (var buffer = new SafeHGlobalBuffer(Length))
                {
                    int resume_handle = 0;
                    while (true)
                    {
                        bool ret = Win32NativeMethods.EnumServicesStatusEx(scm, SC_ENUM_TYPE.SC_ENUM_PROCESS_INFO, service_types, service_state, buffer,
                                                                           buffer.Length, out int bytes_needed, out int services_returned, ref resume_handle, null);
                        Win32Error error = Win32Utils.GetLastWin32Error();
                        if (!ret && error != Win32Error.ERROR_MORE_DATA)
                        {
                            throw new SafeWin32Exception(error);
                        }

                        ENUM_SERVICE_STATUS_PROCESS[] services = new ENUM_SERVICE_STATUS_PROCESS[services_returned];
                        buffer.ReadArray(0, services, 0, services_returned);
                        foreach (var service in services)
                        {
                            yield return(new RunningService(service));
                        }

                        if (ret)
                        {
                            break;
                        }
                    }
                }
            }
        }
예제 #9
0
        private static NtResult <SafeServiceHandle> OpenService(string name, ServiceAccessRights desired_access, bool throw_on_error)
        {
            using (SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(null, null,
                                                                            ServiceControlManagerAccessRights.Connect)) {
                if (scm.IsInvalid)
                {
                    return(Win32Utils.GetLastWin32Error().CreateResultFromDosError <SafeServiceHandle>(throw_on_error));
                }

                using (var service = Win32NativeMethods.OpenService(scm, name, desired_access)) {
                    if (service.IsInvalid)
                    {
                        return(Win32Utils.GetLastWin32Error().CreateResultFromDosError <SafeServiceHandle>(throw_on_error));
                    }
                    return(service.Detach().CreateResult());
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Get a running service by name.
        /// </summary>
        /// <param name="name">The name of the service.</param>
        /// <returns>The running service.</returns>
        /// <remarks>This will return active and non-active services as well as drivers.</remarks>
        public static RunningService GetService(string name)
        {
            using (SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(null, null,
                                                                            ServiceControlManagerAccessRights.Connect)) {
                if (scm.IsInvalid)
                {
                    throw new SafeWin32Exception();
                }

                using (var service = Win32NativeMethods.OpenService(scm, name,
                                                                    ServiceAccessRights.QueryConfig | ServiceAccessRights.QueryStatus)) {
                    if (service.IsInvalid)
                    {
                        throw new SafeWin32Exception();
                    }
                    return(new RunningService(name, GetServiceDisplayName(service), QueryStatus(service)));
                }
            }
        }
예제 #11
0
        /// <summary>
        /// Get the PIDs of a list of running service.
        /// </summary>
        /// <param name="names">The names of the services.</param>
        /// <returns>Returns the PID of the running service, or 0 if not running.</returns>
        /// <exception cref="SafeWin32Exception">Thrown on error.</exception>
        public static IDictionary <string, int> GetServiceProcessIds(IEnumerable <string> names)
        {
            Dictionary <string, int> result = new Dictionary <string, int>(StringComparer.OrdinalIgnoreCase);

            using (SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(null, null,
                                                                            ServiceControlManagerAccessRights.Connect)) {
                if (scm.IsInvalid)
                {
                    throw new SafeWin32Exception();
                }

                foreach (var name in names)
                {
                    if (!result.ContainsKey(name))
                    {
                        result[name] = GetServiceProcessId(scm, name);
                    }
                }
            }
            return(result);
        }