/// <summary>
        /// Get the Win32 services for the SCM.
        /// </summary>
        /// <param name="service_state">The state of the services to return.</param>
        /// <param name="service_types">The types of services to return.</param>
        /// <param name="throw_on_error">True throw on error.</param>
        /// <returns>The list of services.</returns>
        /// <remarks>SCM must have been opened with EnumerateService access.</remarks>
        public NtResult <IEnumerable <Win32Service> > GetServices(ServiceState service_state, ServiceType service_types, bool throw_on_error)
        {
            SERVICE_STATE state;

            switch (service_state)
            {
            case ServiceState.All:
                state = SERVICE_STATE.SERVICE_STATE_ALL;
                break;

            case ServiceState.Active:
                state = SERVICE_STATE.SERVICE_ACTIVE;
                break;

            case ServiceState.InActive:
                state = SERVICE_STATE.SERVICE_INACTIVE;
                break;

            default:
                throw new ArgumentException("Invalid service state", nameof(service_state));
            }

            List <Win32Service> ret_services = new List <Win32Service>();
            const int           Length       = 32 * 1024;

            using (var buffer = new SafeHGlobalBuffer(Length))
            {
                int resume_handle = 0;
                while (true)
                {
                    bool ret = Win32NativeMethods.EnumServicesStatusEx(_handle, SC_ENUM_TYPE.SC_ENUM_PROCESS_INFO,
                                                                       service_types, 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)
                    {
                        return(error.CreateResultFromDosError <IEnumerable <Win32Service> >(throw_on_error));
                    }

                    ENUM_SERVICE_STATUS_PROCESS[] services = new ENUM_SERVICE_STATUS_PROCESS[services_returned];
                    buffer.ReadArray(0, services, 0, services_returned);
                    ret_services.AddRange(services.Select(s => new Win32Service(_machine_name, s)));
                    if (ret)
                    {
                        break;
                    }
                }
            }
            return(ret_services.CreateResult().Cast <IEnumerable <Win32Service> >());
        }