Update dependencies

This commit is contained in:
bluepython508
2024-11-01 17:33:34 +00:00
parent 033ac0b400
commit 5cdfab398d
3596 changed files with 1033483 additions and 259 deletions

180
vendor/golang.org/x/sys/windows/svc/mgr/config.go generated vendored Normal file
View File

@@ -0,0 +1,180 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package mgr
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
const (
// Service start types.
StartManual = windows.SERVICE_DEMAND_START // the service must be started manually
StartAutomatic = windows.SERVICE_AUTO_START // the service will start by itself whenever the computer reboots
StartDisabled = windows.SERVICE_DISABLED // the service cannot be started
// The severity of the error, and action taken,
// if this service fails to start.
ErrorCritical = windows.SERVICE_ERROR_CRITICAL
ErrorIgnore = windows.SERVICE_ERROR_IGNORE
ErrorNormal = windows.SERVICE_ERROR_NORMAL
ErrorSevere = windows.SERVICE_ERROR_SEVERE
)
// TODO(brainman): Password is not returned by windows.QueryServiceConfig, not sure how to get it.
type Config struct {
ServiceType uint32
StartType uint32
ErrorControl uint32
BinaryPathName string // fully qualified path to the service binary file, can also include arguments for an auto-start service
LoadOrderGroup string
TagId uint32
Dependencies []string
ServiceStartName string // name of the account under which the service should run
DisplayName string
Password string
Description string
SidType uint32 // one of SERVICE_SID_TYPE, the type of sid to use for the service
DelayedAutoStart bool // the service is started after other auto-start services are started plus a short delay
}
func toStringSlice(ps *uint16) []string {
r := make([]string, 0)
p := unsafe.Pointer(ps)
for {
s := windows.UTF16PtrToString((*uint16)(p))
if len(s) == 0 {
break
}
r = append(r, s)
offset := unsafe.Sizeof(uint16(0)) * (uintptr)(len(s)+1)
p = unsafe.Pointer(uintptr(p) + offset)
}
return r
}
// Config retrieves service s configuration paramteres.
func (s *Service) Config() (Config, error) {
var p *windows.QUERY_SERVICE_CONFIG
n := uint32(1024)
for {
b := make([]byte, n)
p = (*windows.QUERY_SERVICE_CONFIG)(unsafe.Pointer(&b[0]))
err := windows.QueryServiceConfig(s.Handle, p, n, &n)
if err == nil {
break
}
if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER {
return Config{}, err
}
if n <= uint32(len(b)) {
return Config{}, err
}
}
b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_DESCRIPTION)
if err != nil {
return Config{}, err
}
p2 := (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0]))
b, err = s.queryServiceConfig2(windows.SERVICE_CONFIG_DELAYED_AUTO_START_INFO)
if err != nil {
return Config{}, err
}
p3 := (*windows.SERVICE_DELAYED_AUTO_START_INFO)(unsafe.Pointer(&b[0]))
delayedStart := false
if p3.IsDelayedAutoStartUp != 0 {
delayedStart = true
}
b, err = s.queryServiceConfig2(windows.SERVICE_CONFIG_SERVICE_SID_INFO)
if err != nil {
return Config{}, err
}
sidType := *(*uint32)(unsafe.Pointer(&b[0]))
return Config{
ServiceType: p.ServiceType,
StartType: p.StartType,
ErrorControl: p.ErrorControl,
BinaryPathName: windows.UTF16PtrToString(p.BinaryPathName),
LoadOrderGroup: windows.UTF16PtrToString(p.LoadOrderGroup),
TagId: p.TagId,
Dependencies: toStringSlice(p.Dependencies),
ServiceStartName: windows.UTF16PtrToString(p.ServiceStartName),
DisplayName: windows.UTF16PtrToString(p.DisplayName),
Description: windows.UTF16PtrToString(p2.Description),
DelayedAutoStart: delayedStart,
SidType: sidType,
}, nil
}
func updateDescription(handle windows.Handle, desc string) error {
d := windows.SERVICE_DESCRIPTION{Description: toPtr(desc)}
return windows.ChangeServiceConfig2(handle,
windows.SERVICE_CONFIG_DESCRIPTION, (*byte)(unsafe.Pointer(&d)))
}
func updateSidType(handle windows.Handle, sidType uint32) error {
return windows.ChangeServiceConfig2(handle, windows.SERVICE_CONFIG_SERVICE_SID_INFO, (*byte)(unsafe.Pointer(&sidType)))
}
func updateStartUp(handle windows.Handle, isDelayed bool) error {
var d windows.SERVICE_DELAYED_AUTO_START_INFO
if isDelayed {
d.IsDelayedAutoStartUp = 1
}
return windows.ChangeServiceConfig2(handle,
windows.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, (*byte)(unsafe.Pointer(&d)))
}
// UpdateConfig updates service s configuration parameters.
func (s *Service) UpdateConfig(c Config) error {
err := windows.ChangeServiceConfig(s.Handle, c.ServiceType, c.StartType,
c.ErrorControl, toPtr(c.BinaryPathName), toPtr(c.LoadOrderGroup),
nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName),
toPtr(c.Password), toPtr(c.DisplayName))
if err != nil {
return err
}
err = updateSidType(s.Handle, c.SidType)
if err != nil {
return err
}
err = updateStartUp(s.Handle, c.DelayedAutoStart)
if err != nil {
return err
}
return updateDescription(s.Handle, c.Description)
}
// queryServiceConfig2 calls Windows QueryServiceConfig2 with infoLevel parameter and returns retrieved service configuration information.
func (s *Service) queryServiceConfig2(infoLevel uint32) ([]byte, error) {
n := uint32(1024)
for {
b := make([]byte, n)
err := windows.QueryServiceConfig2(s.Handle, infoLevel, &b[0], n, &n)
if err == nil {
return b, nil
}
if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER {
return nil, err
}
if n <= uint32(len(b)) {
return nil, err
}
}
}

208
vendor/golang.org/x/sys/windows/svc/mgr/mgr.go generated vendored Normal file
View File

@@ -0,0 +1,208 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
// Package mgr can be used to manage Windows service programs.
// It can be used to install and remove them. It can also start,
// stop and pause them. The package can query / change current
// service state and config parameters.
package mgr
import (
"syscall"
"time"
"unicode/utf16"
"unsafe"
"golang.org/x/sys/windows"
)
// Mgr is used to manage Windows service.
type Mgr struct {
Handle windows.Handle
}
// Connect establishes a connection to the service control manager.
func Connect() (*Mgr, error) {
return ConnectRemote("")
}
// ConnectRemote establishes a connection to the
// service control manager on computer named host.
func ConnectRemote(host string) (*Mgr, error) {
var s *uint16
if host != "" {
s = syscall.StringToUTF16Ptr(host)
}
h, err := windows.OpenSCManager(s, nil, windows.SC_MANAGER_ALL_ACCESS)
if err != nil {
return nil, err
}
return &Mgr{Handle: h}, nil
}
// Disconnect closes connection to the service control manager m.
func (m *Mgr) Disconnect() error {
return windows.CloseServiceHandle(m.Handle)
}
type LockStatus struct {
IsLocked bool // Whether the SCM has been locked.
Age time.Duration // For how long the SCM has been locked.
Owner string // The name of the user who has locked the SCM.
}
// LockStatus returns whether the service control manager is locked by
// the system, for how long, and by whom. A locked SCM indicates that
// most service actions will block until the system unlocks the SCM.
func (m *Mgr) LockStatus() (*LockStatus, error) {
bytesNeeded := uint32(unsafe.Sizeof(windows.QUERY_SERVICE_LOCK_STATUS{}) + 1024)
for {
bytes := make([]byte, bytesNeeded)
lockStatus := (*windows.QUERY_SERVICE_LOCK_STATUS)(unsafe.Pointer(&bytes[0]))
err := windows.QueryServiceLockStatus(m.Handle, lockStatus, uint32(len(bytes)), &bytesNeeded)
if err == windows.ERROR_INSUFFICIENT_BUFFER && bytesNeeded >= uint32(unsafe.Sizeof(windows.QUERY_SERVICE_LOCK_STATUS{})) {
continue
}
if err != nil {
return nil, err
}
status := &LockStatus{
IsLocked: lockStatus.IsLocked != 0,
Age: time.Duration(lockStatus.LockDuration) * time.Second,
Owner: windows.UTF16PtrToString(lockStatus.LockOwner),
}
return status, nil
}
}
func toPtr(s string) *uint16 {
if len(s) == 0 {
return nil
}
return syscall.StringToUTF16Ptr(s)
}
// toStringBlock terminates strings in ss with 0, and then
// concatenates them together. It also adds extra 0 at the end.
func toStringBlock(ss []string) *uint16 {
if len(ss) == 0 {
return nil
}
t := ""
for _, s := range ss {
if s != "" {
t += s + "\x00"
}
}
if t == "" {
return nil
}
t += "\x00"
return &utf16.Encode([]rune(t))[0]
}
// CreateService installs new service name on the system.
// The service will be executed by running exepath binary.
// Use config c to specify service parameters.
// Any args will be passed as command-line arguments when
// the service is started; these arguments are distinct from
// the arguments passed to Service.Start or via the "Start
// parameters" field in the service's Properties dialog box.
func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Service, error) {
if c.StartType == 0 {
c.StartType = StartManual
}
if c.ServiceType == 0 {
c.ServiceType = windows.SERVICE_WIN32_OWN_PROCESS
}
s := syscall.EscapeArg(exepath)
for _, v := range args {
s += " " + syscall.EscapeArg(v)
}
h, err := windows.CreateService(m.Handle, toPtr(name), toPtr(c.DisplayName),
windows.SERVICE_ALL_ACCESS, c.ServiceType,
c.StartType, c.ErrorControl, toPtr(s), toPtr(c.LoadOrderGroup),
nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName), toPtr(c.Password))
if err != nil {
return nil, err
}
if c.SidType != windows.SERVICE_SID_TYPE_NONE {
err = updateSidType(h, c.SidType)
if err != nil {
windows.DeleteService(h)
windows.CloseServiceHandle(h)
return nil, err
}
}
if c.Description != "" {
err = updateDescription(h, c.Description)
if err != nil {
windows.DeleteService(h)
windows.CloseServiceHandle(h)
return nil, err
}
}
if c.DelayedAutoStart {
err = updateStartUp(h, c.DelayedAutoStart)
if err != nil {
windows.DeleteService(h)
windows.CloseServiceHandle(h)
return nil, err
}
}
return &Service{Name: name, Handle: h}, nil
}
// OpenService retrieves access to service name, so it can
// be interrogated and controlled.
func (m *Mgr) OpenService(name string) (*Service, error) {
h, err := windows.OpenService(m.Handle, syscall.StringToUTF16Ptr(name), windows.SERVICE_ALL_ACCESS)
if err != nil {
return nil, err
}
return &Service{Name: name, Handle: h}, nil
}
// ListServices enumerates services in the specified
// service control manager database m.
// If the caller does not have the SERVICE_QUERY_STATUS
// access right to a service, the service is silently
// omitted from the list of services returned.
func (m *Mgr) ListServices() ([]string, error) {
var err error
var bytesNeeded, servicesReturned uint32
var buf []byte
for {
var p *byte
if len(buf) > 0 {
p = &buf[0]
}
err = windows.EnumServicesStatusEx(m.Handle, windows.SC_ENUM_PROCESS_INFO,
windows.SERVICE_WIN32, windows.SERVICE_STATE_ALL,
p, uint32(len(buf)), &bytesNeeded, &servicesReturned, nil, nil)
if err == nil {
break
}
if err != syscall.ERROR_MORE_DATA {
return nil, err
}
if bytesNeeded <= uint32(len(buf)) {
return nil, err
}
buf = make([]byte, bytesNeeded)
}
if servicesReturned == 0 {
return nil, nil
}
services := unsafe.Slice((*windows.ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(&buf[0])), int(servicesReturned))
var names []string
for _, s := range services {
name := windows.UTF16PtrToString(s.ServiceName)
names = append(names, name)
}
return names, nil
}

162
vendor/golang.org/x/sys/windows/svc/mgr/recovery.go generated vendored Normal file
View File

@@ -0,0 +1,162 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package mgr
import (
"errors"
"syscall"
"time"
"unsafe"
"golang.org/x/sys/windows"
)
const (
// Possible recovery actions that the service control manager can perform.
NoAction = windows.SC_ACTION_NONE // no action
ComputerReboot = windows.SC_ACTION_REBOOT // reboot the computer
ServiceRestart = windows.SC_ACTION_RESTART // restart the service
RunCommand = windows.SC_ACTION_RUN_COMMAND // run a command
)
// RecoveryAction represents an action that the service control manager can perform when service fails.
// A service is considered failed when it terminates without reporting a status of SERVICE_STOPPED to the service controller.
type RecoveryAction struct {
Type int // one of NoAction, ComputerReboot, ServiceRestart or RunCommand
Delay time.Duration // the time to wait before performing the specified action
}
// SetRecoveryActions sets actions that service controller performs when service fails and
// the time after which to reset the service failure count to zero if there are no failures, in seconds.
// Specify INFINITE to indicate that service failure count should never be reset.
func (s *Service) SetRecoveryActions(recoveryActions []RecoveryAction, resetPeriod uint32) error {
if recoveryActions == nil {
return errors.New("recoveryActions cannot be nil")
}
actions := []windows.SC_ACTION{}
for _, a := range recoveryActions {
action := windows.SC_ACTION{
Type: uint32(a.Type),
Delay: uint32(a.Delay.Nanoseconds() / 1000000),
}
actions = append(actions, action)
}
rActions := windows.SERVICE_FAILURE_ACTIONS{
ActionsCount: uint32(len(actions)),
Actions: &actions[0],
ResetPeriod: resetPeriod,
}
return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
}
// RecoveryActions returns actions that service controller performs when service fails.
// The service control manager counts the number of times service s has failed since the system booted.
// The count is reset to 0 if the service has not failed for ResetPeriod seconds.
// When the service fails for the Nth time, the service controller performs the action specified in element [N-1] of returned slice.
// If N is greater than slice length, the service controller repeats the last action in the slice.
func (s *Service) RecoveryActions() ([]RecoveryAction, error) {
b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
if err != nil {
return nil, err
}
p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
if p.Actions == nil {
return nil, err
}
actions := unsafe.Slice(p.Actions, int(p.ActionsCount))
var recoveryActions []RecoveryAction
for _, action := range actions {
recoveryActions = append(recoveryActions, RecoveryAction{Type: int(action.Type), Delay: time.Duration(action.Delay) * time.Millisecond})
}
return recoveryActions, nil
}
// ResetRecoveryActions deletes both reset period and array of failure actions.
func (s *Service) ResetRecoveryActions() error {
actions := make([]windows.SC_ACTION, 1)
rActions := windows.SERVICE_FAILURE_ACTIONS{
Actions: &actions[0],
}
return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
}
// ResetPeriod is the time after which to reset the service failure
// count to zero if there are no failures, in seconds.
func (s *Service) ResetPeriod() (uint32, error) {
b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
if err != nil {
return 0, err
}
p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
return p.ResetPeriod, nil
}
// SetRebootMessage sets service s reboot message.
// If msg is "", the reboot message is deleted and no message is broadcast.
func (s *Service) SetRebootMessage(msg string) error {
rActions := windows.SERVICE_FAILURE_ACTIONS{
RebootMsg: syscall.StringToUTF16Ptr(msg),
}
return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
}
// RebootMessage is broadcast to server users before rebooting in response to the ComputerReboot service controller action.
func (s *Service) RebootMessage() (string, error) {
b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
if err != nil {
return "", err
}
p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
return windows.UTF16PtrToString(p.RebootMsg), nil
}
// SetRecoveryCommand sets the command line of the process to execute in response to the RunCommand service controller action.
// If cmd is "", the command is deleted and no program is run when the service fails.
func (s *Service) SetRecoveryCommand(cmd string) error {
rActions := windows.SERVICE_FAILURE_ACTIONS{
Command: syscall.StringToUTF16Ptr(cmd),
}
return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
}
// RecoveryCommand is the command line of the process to execute in response to the RunCommand service controller action. This process runs under the same account as the service.
func (s *Service) RecoveryCommand() (string, error) {
b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
if err != nil {
return "", err
}
p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
return windows.UTF16PtrToString(p.Command), nil
}
// SetRecoveryActionsOnNonCrashFailures sets the failure actions flag. If the
// flag is set to false, recovery actions will only be performed if the service
// terminates without reporting a status of SERVICE_STOPPED. If the flag is set
// to true, recovery actions are also perfomed if the service stops with a
// nonzero exit code.
func (s *Service) SetRecoveryActionsOnNonCrashFailures(flag bool) error {
var setting windows.SERVICE_FAILURE_ACTIONS_FLAG
if flag {
setting.FailureActionsOnNonCrashFailures = 1
}
return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, (*byte)(unsafe.Pointer(&setting)))
}
// RecoveryActionsOnNonCrashFailures returns the current value of the failure
// actions flag. If the flag is set to false, recovery actions will only be
// performed if the service terminates without reporting a status of
// SERVICE_STOPPED. If the flag is set to true, recovery actions are also
// perfomed if the service stops with a nonzero exit code.
func (s *Service) RecoveryActionsOnNonCrashFailures() (bool, error) {
b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG)
if err != nil {
return false, err
}
p := (*windows.SERVICE_FAILURE_ACTIONS_FLAG)(unsafe.Pointer(&b[0]))
return p.FailureActionsOnNonCrashFailures != 0, nil
}

124
vendor/golang.org/x/sys/windows/svc/mgr/service.go generated vendored Normal file
View File

@@ -0,0 +1,124 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package mgr
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
)
// Service is used to access Windows service.
type Service struct {
Name string
Handle windows.Handle
}
// Delete marks service s for deletion from the service control manager database.
func (s *Service) Delete() error {
return windows.DeleteService(s.Handle)
}
// Close relinquish access to the service s.
func (s *Service) Close() error {
return windows.CloseServiceHandle(s.Handle)
}
// Start starts service s.
// args will be passed to svc.Handler.Execute.
func (s *Service) Start(args ...string) error {
var p **uint16
if len(args) > 0 {
vs := make([]*uint16, len(args))
for i := range vs {
vs[i] = syscall.StringToUTF16Ptr(args[i])
}
p = &vs[0]
}
return windows.StartService(s.Handle, uint32(len(args)), p)
}
// Control sends state change request c to the service s. It returns the most
// recent status the service reported to the service control manager, and an
// error if the state change request was not accepted.
// Note that the returned service status is only set if the status change
// request succeeded, or if it failed with error ERROR_INVALID_SERVICE_CONTROL,
// ERROR_SERVICE_CANNOT_ACCEPT_CTRL, or ERROR_SERVICE_NOT_ACTIVE.
func (s *Service) Control(c svc.Cmd) (svc.Status, error) {
var t windows.SERVICE_STATUS
err := windows.ControlService(s.Handle, uint32(c), &t)
if err != nil &&
err != windows.ERROR_INVALID_SERVICE_CONTROL &&
err != windows.ERROR_SERVICE_CANNOT_ACCEPT_CTRL &&
err != windows.ERROR_SERVICE_NOT_ACTIVE {
return svc.Status{}, err
}
return svc.Status{
State: svc.State(t.CurrentState),
Accepts: svc.Accepted(t.ControlsAccepted),
}, err
}
// Query returns current status of service s.
func (s *Service) Query() (svc.Status, error) {
var t windows.SERVICE_STATUS_PROCESS
var needed uint32
err := windows.QueryServiceStatusEx(s.Handle, windows.SC_STATUS_PROCESS_INFO, (*byte)(unsafe.Pointer(&t)), uint32(unsafe.Sizeof(t)), &needed)
if err != nil {
return svc.Status{}, err
}
return svc.Status{
State: svc.State(t.CurrentState),
Accepts: svc.Accepted(t.ControlsAccepted),
ProcessId: t.ProcessId,
Win32ExitCode: t.Win32ExitCode,
ServiceSpecificExitCode: t.ServiceSpecificExitCode,
}, nil
}
// ListDependentServices returns the names of the services dependent on service s, which match the given status.
func (s *Service) ListDependentServices(status svc.ActivityStatus) ([]string, error) {
var bytesNeeded, returnedServiceCount uint32
var services []windows.ENUM_SERVICE_STATUS
for {
var servicesPtr *windows.ENUM_SERVICE_STATUS
if len(services) > 0 {
servicesPtr = &services[0]
}
allocatedBytes := uint32(len(services)) * uint32(unsafe.Sizeof(windows.ENUM_SERVICE_STATUS{}))
err := windows.EnumDependentServices(s.Handle, uint32(status), servicesPtr, allocatedBytes, &bytesNeeded,
&returnedServiceCount)
if err == nil {
break
}
if err != syscall.ERROR_MORE_DATA {
return nil, err
}
if bytesNeeded <= allocatedBytes {
return nil, err
}
// ERROR_MORE_DATA indicates the provided buffer was too small, run the call again after resizing the buffer
requiredSliceLen := bytesNeeded / uint32(unsafe.Sizeof(windows.ENUM_SERVICE_STATUS{}))
if bytesNeeded%uint32(unsafe.Sizeof(windows.ENUM_SERVICE_STATUS{})) != 0 {
requiredSliceLen += 1
}
services = make([]windows.ENUM_SERVICE_STATUS, requiredSliceLen)
}
if returnedServiceCount == 0 {
return nil, nil
}
// The slice mutated by EnumDependentServices may have a length greater than returnedServiceCount, any elements
// past that should be ignored.
var dependents []string
for i := 0; i < int(returnedServiceCount); i++ {
dependents = append(dependents, windows.UTF16PtrToString(services[i].ServiceName))
}
return dependents, nil
}

100
vendor/golang.org/x/sys/windows/svc/security.go generated vendored Normal file
View File

@@ -0,0 +1,100 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package svc
import (
"strings"
"unsafe"
"golang.org/x/sys/windows"
)
func allocSid(subAuth0 uint32) (*windows.SID, error) {
var sid *windows.SID
err := windows.AllocateAndInitializeSid(&windows.SECURITY_NT_AUTHORITY,
1, subAuth0, 0, 0, 0, 0, 0, 0, 0, &sid)
if err != nil {
return nil, err
}
return sid, nil
}
// IsAnInteractiveSession determines if calling process is running interactively.
// It queries the process token for membership in the Interactive group.
// http://stackoverflow.com/questions/2668851/how-do-i-detect-that-my-application-is-running-as-service-or-in-an-interactive-s
//
// Deprecated: Use IsWindowsService instead.
func IsAnInteractiveSession() (bool, error) {
interSid, err := allocSid(windows.SECURITY_INTERACTIVE_RID)
if err != nil {
return false, err
}
defer windows.FreeSid(interSid)
serviceSid, err := allocSid(windows.SECURITY_SERVICE_RID)
if err != nil {
return false, err
}
defer windows.FreeSid(serviceSid)
t, err := windows.OpenCurrentProcessToken()
if err != nil {
return false, err
}
defer t.Close()
gs, err := t.GetTokenGroups()
if err != nil {
return false, err
}
for _, g := range gs.AllGroups() {
if windows.EqualSid(g.Sid, interSid) {
return true, nil
}
if windows.EqualSid(g.Sid, serviceSid) {
return false, nil
}
}
return false, nil
}
// IsWindowsService reports whether the process is currently executing
// as a Windows service.
func IsWindowsService() (bool, error) {
// The below technique looks a bit hairy, but it's actually
// exactly what the .NET framework does for the similarly named function:
// https://github.com/dotnet/extensions/blob/f4066026ca06984b07e90e61a6390ac38152ba93/src/Hosting/WindowsServices/src/WindowsServiceHelpers.cs#L26-L31
// Specifically, it looks up whether the parent process has session ID zero
// and is called "services".
var currentProcess windows.PROCESS_BASIC_INFORMATION
infoSize := uint32(unsafe.Sizeof(currentProcess))
err := windows.NtQueryInformationProcess(windows.CurrentProcess(), windows.ProcessBasicInformation, unsafe.Pointer(&currentProcess), infoSize, &infoSize)
if err != nil {
return false, err
}
var parentProcess *windows.SYSTEM_PROCESS_INFORMATION
for infoSize = uint32((unsafe.Sizeof(*parentProcess) + unsafe.Sizeof(uintptr(0))) * 1024); ; {
parentProcess = (*windows.SYSTEM_PROCESS_INFORMATION)(unsafe.Pointer(&make([]byte, infoSize)[0]))
err = windows.NtQuerySystemInformation(windows.SystemProcessInformation, unsafe.Pointer(parentProcess), infoSize, &infoSize)
if err == nil {
break
} else if err != windows.STATUS_INFO_LENGTH_MISMATCH {
return false, err
}
}
for ; ; parentProcess = (*windows.SYSTEM_PROCESS_INFORMATION)(unsafe.Pointer(uintptr(unsafe.Pointer(parentProcess)) + uintptr(parentProcess.NextEntryOffset))) {
if parentProcess.UniqueProcessID == currentProcess.InheritedFromUniqueProcessId {
return parentProcess.SessionID == 0 && strings.EqualFold("services.exe", parentProcess.ImageName.String()), nil
}
if parentProcess.NextEntryOffset == 0 {
break
}
}
return false, nil
}

315
vendor/golang.org/x/sys/windows/svc/service.go generated vendored Normal file
View File

@@ -0,0 +1,315 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
// Package svc provides everything required to build Windows service.
package svc
import (
"errors"
"sync"
"unsafe"
"golang.org/x/sys/windows"
)
// State describes service execution state (Stopped, Running and so on).
type State uint32
const (
Stopped = State(windows.SERVICE_STOPPED)
StartPending = State(windows.SERVICE_START_PENDING)
StopPending = State(windows.SERVICE_STOP_PENDING)
Running = State(windows.SERVICE_RUNNING)
ContinuePending = State(windows.SERVICE_CONTINUE_PENDING)
PausePending = State(windows.SERVICE_PAUSE_PENDING)
Paused = State(windows.SERVICE_PAUSED)
)
// Cmd represents service state change request. It is sent to a service
// by the service manager, and should be actioned upon by the service.
type Cmd uint32
const (
Stop = Cmd(windows.SERVICE_CONTROL_STOP)
Pause = Cmd(windows.SERVICE_CONTROL_PAUSE)
Continue = Cmd(windows.SERVICE_CONTROL_CONTINUE)
Interrogate = Cmd(windows.SERVICE_CONTROL_INTERROGATE)
Shutdown = Cmd(windows.SERVICE_CONTROL_SHUTDOWN)
ParamChange = Cmd(windows.SERVICE_CONTROL_PARAMCHANGE)
NetBindAdd = Cmd(windows.SERVICE_CONTROL_NETBINDADD)
NetBindRemove = Cmd(windows.SERVICE_CONTROL_NETBINDREMOVE)
NetBindEnable = Cmd(windows.SERVICE_CONTROL_NETBINDENABLE)
NetBindDisable = Cmd(windows.SERVICE_CONTROL_NETBINDDISABLE)
DeviceEvent = Cmd(windows.SERVICE_CONTROL_DEVICEEVENT)
HardwareProfileChange = Cmd(windows.SERVICE_CONTROL_HARDWAREPROFILECHANGE)
PowerEvent = Cmd(windows.SERVICE_CONTROL_POWEREVENT)
SessionChange = Cmd(windows.SERVICE_CONTROL_SESSIONCHANGE)
PreShutdown = Cmd(windows.SERVICE_CONTROL_PRESHUTDOWN)
)
// Accepted is used to describe commands accepted by the service.
// Note that Interrogate is always accepted.
type Accepted uint32
const (
AcceptStop = Accepted(windows.SERVICE_ACCEPT_STOP)
AcceptShutdown = Accepted(windows.SERVICE_ACCEPT_SHUTDOWN)
AcceptPauseAndContinue = Accepted(windows.SERVICE_ACCEPT_PAUSE_CONTINUE)
AcceptParamChange = Accepted(windows.SERVICE_ACCEPT_PARAMCHANGE)
AcceptNetBindChange = Accepted(windows.SERVICE_ACCEPT_NETBINDCHANGE)
AcceptHardwareProfileChange = Accepted(windows.SERVICE_ACCEPT_HARDWAREPROFILECHANGE)
AcceptPowerEvent = Accepted(windows.SERVICE_ACCEPT_POWEREVENT)
AcceptSessionChange = Accepted(windows.SERVICE_ACCEPT_SESSIONCHANGE)
AcceptPreShutdown = Accepted(windows.SERVICE_ACCEPT_PRESHUTDOWN)
)
// ActivityStatus allows for services to be selected based on active and inactive categories of service state.
type ActivityStatus uint32
const (
Active = ActivityStatus(windows.SERVICE_ACTIVE)
Inactive = ActivityStatus(windows.SERVICE_INACTIVE)
AnyActivity = ActivityStatus(windows.SERVICE_STATE_ALL)
)
// Status combines State and Accepted commands to fully describe running service.
type Status struct {
State State
Accepts Accepted
CheckPoint uint32 // used to report progress during a lengthy operation
WaitHint uint32 // estimated time required for a pending operation, in milliseconds
ProcessId uint32 // if the service is running, the process identifier of it, and otherwise zero
Win32ExitCode uint32 // set if the service has exited with a win32 exit code
ServiceSpecificExitCode uint32 // set if the service has exited with a service-specific exit code
}
// StartReason is the reason that the service was started.
type StartReason uint32
const (
StartReasonDemand = StartReason(windows.SERVICE_START_REASON_DEMAND)
StartReasonAuto = StartReason(windows.SERVICE_START_REASON_AUTO)
StartReasonTrigger = StartReason(windows.SERVICE_START_REASON_TRIGGER)
StartReasonRestartOnFailure = StartReason(windows.SERVICE_START_REASON_RESTART_ON_FAILURE)
StartReasonDelayedAuto = StartReason(windows.SERVICE_START_REASON_DELAYEDAUTO)
)
// ChangeRequest is sent to the service Handler to request service status change.
type ChangeRequest struct {
Cmd Cmd
EventType uint32
EventData uintptr
CurrentStatus Status
Context uintptr
}
// Handler is the interface that must be implemented to build Windows service.
type Handler interface {
// Execute will be called by the package code at the start of
// the service, and the service will exit once Execute completes.
// Inside Execute you must read service change requests from r and
// act accordingly. You must keep service control manager up to date
// about state of your service by writing into s as required.
// args contains service name followed by argument strings passed
// to the service.
// You can provide service exit code in exitCode return parameter,
// with 0 being "no error". You can also indicate if exit code,
// if any, is service specific or not by using svcSpecificEC
// parameter.
Execute(args []string, r <-chan ChangeRequest, s chan<- Status) (svcSpecificEC bool, exitCode uint32)
}
type ctlEvent struct {
cmd Cmd
eventType uint32
eventData uintptr
context uintptr
errno uint32
}
// service provides access to windows service api.
type service struct {
name string
h windows.Handle
c chan ctlEvent
handler Handler
}
type exitCode struct {
isSvcSpecific bool
errno uint32
}
func (s *service) updateStatus(status *Status, ec *exitCode) error {
if s.h == 0 {
return errors.New("updateStatus with no service status handle")
}
var t windows.SERVICE_STATUS
t.ServiceType = windows.SERVICE_WIN32_OWN_PROCESS
t.CurrentState = uint32(status.State)
if status.Accepts&AcceptStop != 0 {
t.ControlsAccepted |= windows.SERVICE_ACCEPT_STOP
}
if status.Accepts&AcceptShutdown != 0 {
t.ControlsAccepted |= windows.SERVICE_ACCEPT_SHUTDOWN
}
if status.Accepts&AcceptPauseAndContinue != 0 {
t.ControlsAccepted |= windows.SERVICE_ACCEPT_PAUSE_CONTINUE
}
if status.Accepts&AcceptParamChange != 0 {
t.ControlsAccepted |= windows.SERVICE_ACCEPT_PARAMCHANGE
}
if status.Accepts&AcceptNetBindChange != 0 {
t.ControlsAccepted |= windows.SERVICE_ACCEPT_NETBINDCHANGE
}
if status.Accepts&AcceptHardwareProfileChange != 0 {
t.ControlsAccepted |= windows.SERVICE_ACCEPT_HARDWAREPROFILECHANGE
}
if status.Accepts&AcceptPowerEvent != 0 {
t.ControlsAccepted |= windows.SERVICE_ACCEPT_POWEREVENT
}
if status.Accepts&AcceptSessionChange != 0 {
t.ControlsAccepted |= windows.SERVICE_ACCEPT_SESSIONCHANGE
}
if status.Accepts&AcceptPreShutdown != 0 {
t.ControlsAccepted |= windows.SERVICE_ACCEPT_PRESHUTDOWN
}
if ec.errno == 0 {
t.Win32ExitCode = windows.NO_ERROR
t.ServiceSpecificExitCode = windows.NO_ERROR
} else if ec.isSvcSpecific {
t.Win32ExitCode = uint32(windows.ERROR_SERVICE_SPECIFIC_ERROR)
t.ServiceSpecificExitCode = ec.errno
} else {
t.Win32ExitCode = ec.errno
t.ServiceSpecificExitCode = windows.NO_ERROR
}
t.CheckPoint = status.CheckPoint
t.WaitHint = status.WaitHint
return windows.SetServiceStatus(s.h, &t)
}
var (
initCallbacks sync.Once
ctlHandlerCallback uintptr
serviceMainCallback uintptr
)
func ctlHandler(ctl, evtype, evdata, context uintptr) uintptr {
e := ctlEvent{cmd: Cmd(ctl), eventType: uint32(evtype), eventData: evdata, context: 123456} // Set context to 123456 to test issue #25660.
theService.c <- e
return 0
}
var theService service // This is, unfortunately, a global, which means only one service per process.
// serviceMain is the entry point called by the service manager, registered earlier by
// the call to StartServiceCtrlDispatcher.
func serviceMain(argc uint32, argv **uint16) uintptr {
handle, err := windows.RegisterServiceCtrlHandlerEx(windows.StringToUTF16Ptr(theService.name), ctlHandlerCallback, 0)
if sysErr, ok := err.(windows.Errno); ok {
return uintptr(sysErr)
} else if err != nil {
return uintptr(windows.ERROR_UNKNOWN_EXCEPTION)
}
theService.h = handle
defer func() {
theService.h = 0
}()
args16 := unsafe.Slice(argv, int(argc))
args := make([]string, len(args16))
for i, a := range args16 {
args[i] = windows.UTF16PtrToString(a)
}
cmdsToHandler := make(chan ChangeRequest)
changesFromHandler := make(chan Status)
exitFromHandler := make(chan exitCode)
go func() {
ss, errno := theService.handler.Execute(args, cmdsToHandler, changesFromHandler)
exitFromHandler <- exitCode{ss, errno}
}()
ec := exitCode{isSvcSpecific: true, errno: 0}
outcr := ChangeRequest{
CurrentStatus: Status{State: Stopped},
}
var outch chan ChangeRequest
inch := theService.c
loop:
for {
select {
case r := <-inch:
if r.errno != 0 {
ec.errno = r.errno
break loop
}
inch = nil
outch = cmdsToHandler
outcr.Cmd = r.cmd
outcr.EventType = r.eventType
outcr.EventData = r.eventData
outcr.Context = r.context
case outch <- outcr:
inch = theService.c
outch = nil
case c := <-changesFromHandler:
err := theService.updateStatus(&c, &ec)
if err != nil {
ec.errno = uint32(windows.ERROR_EXCEPTION_IN_SERVICE)
if err2, ok := err.(windows.Errno); ok {
ec.errno = uint32(err2)
}
break loop
}
outcr.CurrentStatus = c
case ec = <-exitFromHandler:
break loop
}
}
theService.updateStatus(&Status{State: Stopped}, &ec)
return windows.NO_ERROR
}
// Run executes service name by calling appropriate handler function.
func Run(name string, handler Handler) error {
initCallbacks.Do(func() {
ctlHandlerCallback = windows.NewCallback(ctlHandler)
serviceMainCallback = windows.NewCallback(serviceMain)
})
theService.name = name
theService.handler = handler
theService.c = make(chan ctlEvent)
t := []windows.SERVICE_TABLE_ENTRY{
{ServiceName: windows.StringToUTF16Ptr(theService.name), ServiceProc: serviceMainCallback},
{ServiceName: nil, ServiceProc: 0},
}
return windows.StartServiceCtrlDispatcher(&t[0])
}
// StatusHandle returns service status handle. It is safe to call this function
// from inside the Handler.Execute because then it is guaranteed to be set.
func StatusHandle() windows.Handle {
return theService.h
}
// DynamicStartReason returns the reason why the service was started. It is safe
// to call this function from inside the Handler.Execute because then it is
// guaranteed to be set.
func DynamicStartReason() (StartReason, error) {
var allocReason *uint32
err := windows.QueryServiceDynamicInformation(theService.h, windows.SERVICE_DYNAMIC_INFORMATION_LEVEL_START_REASON, unsafe.Pointer(&allocReason))
if err != nil {
return 0, err
}
reason := StartReason(*allocReason)
windows.LocalFree(windows.Handle(unsafe.Pointer(allocReason)))
return reason, nil
}