Checking in vendor folder for ease of using go get.
This commit is contained in:
parent
7a1251853b
commit
cdb4b5a1d0
3554 changed files with 1270116 additions and 0 deletions
145
vendor/golang.org/x/sys/windows/svc/mgr/config.go
generated
vendored
Normal file
145
vendor/golang.org/x/sys/windows/svc/mgr/config.go
generated
vendored
Normal file
|
@ -0,0 +1,145 @@
|
|||
// 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.
|
||||
|
||||
// +build windows
|
||||
|
||||
package mgr
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"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
|
||||
}
|
||||
|
||||
func toString(p *uint16) string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
return syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(p))[:])
|
||||
}
|
||||
|
||||
func toStringSlice(ps *uint16) []string {
|
||||
if ps == nil {
|
||||
return nil
|
||||
}
|
||||
r := make([]string, 0)
|
||||
for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(ps)); true; i++ {
|
||||
if p[i] == 0 {
|
||||
// empty string marks the end
|
||||
if i <= from {
|
||||
break
|
||||
}
|
||||
r = append(r, string(utf16.Decode(p[from:i])))
|
||||
from = i + 1
|
||||
}
|
||||
}
|
||||
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]))
|
||||
|
||||
return Config{
|
||||
ServiceType: p.ServiceType,
|
||||
StartType: p.StartType,
|
||||
ErrorControl: p.ErrorControl,
|
||||
BinaryPathName: toString(p.BinaryPathName),
|
||||
LoadOrderGroup: toString(p.LoadOrderGroup),
|
||||
TagId: p.TagId,
|
||||
Dependencies: toStringSlice(p.Dependencies),
|
||||
ServiceStartName: toString(p.ServiceStartName),
|
||||
DisplayName: toString(p.DisplayName),
|
||||
Description: toString(p2.Description),
|
||||
}, 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)))
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
162
vendor/golang.org/x/sys/windows/svc/mgr/mgr.go
generated
vendored
Normal file
162
vendor/golang.org/x/sys/windows/svc/mgr/mgr.go
generated
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
// 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.
|
||||
|
||||
// +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"
|
||||
"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)
|
||||
}
|
||||
|
||||
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.ErrorControl == 0 {
|
||||
c.ErrorControl = ErrorNormal
|
||||
}
|
||||
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.Description != "" {
|
||||
err = updateDescription(h, c.Description)
|
||||
if err != nil {
|
||||
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 := (*[1 << 20]windows.ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(&buf[0]))[:servicesReturned]
|
||||
var names []string
|
||||
for _, s := range services {
|
||||
name := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(s.ServiceName))[:])
|
||||
names = append(names, name)
|
||||
}
|
||||
return names, nil
|
||||
}
|
282
vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go
generated
vendored
Normal file
282
vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go
generated
vendored
Normal file
|
@ -0,0 +1,282 @@
|
|||
// 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.
|
||||
|
||||
// +build windows
|
||||
|
||||
package mgr_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
)
|
||||
|
||||
func TestOpenLanManServer(t *testing.T) {
|
||||
m, err := mgr.Connect()
|
||||
if err != nil {
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERROR_ACCESS_DENIED {
|
||||
t.Skip("Skipping test: we don't have rights to manage services.")
|
||||
}
|
||||
t.Fatalf("SCM connection failed: %s", err)
|
||||
}
|
||||
defer m.Disconnect()
|
||||
|
||||
s, err := m.OpenService("LanmanServer")
|
||||
if err != nil {
|
||||
t.Fatalf("OpenService(lanmanserver) failed: %s", err)
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
_, err = s.Config()
|
||||
if err != nil {
|
||||
t.Fatalf("Config failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func install(t *testing.T, m *mgr.Mgr, name, exepath string, c mgr.Config) {
|
||||
// Sometimes it takes a while for the service to get
|
||||
// removed after previous test run.
|
||||
for i := 0; ; i++ {
|
||||
s, err := m.OpenService(name)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
s.Close()
|
||||
|
||||
if i > 10 {
|
||||
t.Fatalf("service %s already exists", name)
|
||||
}
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
}
|
||||
|
||||
s, err := m.CreateService(name, exepath, c)
|
||||
if err != nil {
|
||||
t.Fatalf("CreateService(%s) failed: %v", name, err)
|
||||
}
|
||||
defer s.Close()
|
||||
}
|
||||
|
||||
func depString(d []string) string {
|
||||
if len(d) == 0 {
|
||||
return ""
|
||||
}
|
||||
for i := range d {
|
||||
d[i] = strings.ToLower(d[i])
|
||||
}
|
||||
ss := sort.StringSlice(d)
|
||||
ss.Sort()
|
||||
return strings.Join([]string(ss), " ")
|
||||
}
|
||||
|
||||
func testConfig(t *testing.T, s *mgr.Service, should mgr.Config) mgr.Config {
|
||||
is, err := s.Config()
|
||||
if err != nil {
|
||||
t.Fatalf("Config failed: %s", err)
|
||||
}
|
||||
if should.DisplayName != is.DisplayName {
|
||||
t.Fatalf("config mismatch: DisplayName is %q, but should have %q", is.DisplayName, should.DisplayName)
|
||||
}
|
||||
if should.StartType != is.StartType {
|
||||
t.Fatalf("config mismatch: StartType is %v, but should have %v", is.StartType, should.StartType)
|
||||
}
|
||||
if should.Description != is.Description {
|
||||
t.Fatalf("config mismatch: Description is %q, but should have %q", is.Description, should.Description)
|
||||
}
|
||||
if depString(should.Dependencies) != depString(is.Dependencies) {
|
||||
t.Fatalf("config mismatch: Dependencies is %v, but should have %v", is.Dependencies, should.Dependencies)
|
||||
}
|
||||
return is
|
||||
}
|
||||
|
||||
func testRecoveryActions(t *testing.T, s *mgr.Service, should []mgr.RecoveryAction) {
|
||||
is, err := s.RecoveryActions()
|
||||
if err != nil {
|
||||
t.Fatalf("RecoveryActions failed: %s", err)
|
||||
}
|
||||
if len(should) != len(is) {
|
||||
t.Errorf("recovery action mismatch: contains %v actions, but should have %v", len(is), len(should))
|
||||
}
|
||||
for i, _ := range is {
|
||||
if should[i].Type != is[i].Type {
|
||||
t.Errorf("recovery action mismatch: Type is %v, but should have %v", is[i].Type, should[i].Type)
|
||||
}
|
||||
if should[i].Delay != is[i].Delay {
|
||||
t.Errorf("recovery action mismatch: Delay is %v, but should have %v", is[i].Delay, should[i].Delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testResetPeriod(t *testing.T, s *mgr.Service, should uint32) {
|
||||
is, err := s.ResetPeriod()
|
||||
if err != nil {
|
||||
t.Fatalf("ResetPeriod failed: %s", err)
|
||||
}
|
||||
if should != is {
|
||||
t.Errorf("reset period mismatch: reset period is %v, but should have %v", is, should)
|
||||
}
|
||||
}
|
||||
|
||||
func testSetRecoveryActions(t *testing.T, s *mgr.Service) {
|
||||
r := []mgr.RecoveryAction{
|
||||
mgr.RecoveryAction{
|
||||
Type: mgr.NoAction,
|
||||
Delay: 60000 * time.Millisecond,
|
||||
},
|
||||
mgr.RecoveryAction{
|
||||
Type: mgr.ServiceRestart,
|
||||
Delay: 4 * time.Minute,
|
||||
},
|
||||
mgr.RecoveryAction{
|
||||
Type: mgr.ServiceRestart,
|
||||
Delay: time.Minute,
|
||||
},
|
||||
mgr.RecoveryAction{
|
||||
Type: mgr.RunCommand,
|
||||
Delay: 4000 * time.Millisecond,
|
||||
},
|
||||
}
|
||||
|
||||
// 4 recovery actions with reset period
|
||||
err := s.SetRecoveryActions(r, uint32(10000))
|
||||
if err != nil {
|
||||
t.Fatalf("SetRecoveryActions failed: %v", err)
|
||||
}
|
||||
testRecoveryActions(t, s, r)
|
||||
testResetPeriod(t, s, uint32(10000))
|
||||
|
||||
// Infinite reset period
|
||||
err = s.SetRecoveryActions(r, syscall.INFINITE)
|
||||
if err != nil {
|
||||
t.Fatalf("SetRecoveryActions failed: %v", err)
|
||||
}
|
||||
testRecoveryActions(t, s, r)
|
||||
testResetPeriod(t, s, syscall.INFINITE)
|
||||
|
||||
// nil recovery actions
|
||||
err = s.SetRecoveryActions(nil, 0)
|
||||
if err.Error() != "recoveryActions cannot be nil" {
|
||||
t.Fatalf("SetRecoveryActions failed with unexpected error message of %q", err)
|
||||
}
|
||||
|
||||
// Delete all recovery actions and reset period
|
||||
err = s.ResetRecoveryActions()
|
||||
if err != nil {
|
||||
t.Fatalf("ResetRecoveryActions failed: %v", err)
|
||||
}
|
||||
testRecoveryActions(t, s, nil)
|
||||
testResetPeriod(t, s, 0)
|
||||
}
|
||||
|
||||
func testRebootMessage(t *testing.T, s *mgr.Service, should string) {
|
||||
err := s.SetRebootMessage(should)
|
||||
if err != nil {
|
||||
t.Fatalf("SetRebootMessage failed: %v", err)
|
||||
}
|
||||
is, err := s.RebootMessage()
|
||||
if err != nil {
|
||||
t.Fatalf("RebootMessage failed: %v", err)
|
||||
}
|
||||
if should != is {
|
||||
t.Errorf("reboot message mismatch: message is %q, but should have %q", is, should)
|
||||
}
|
||||
}
|
||||
|
||||
func testRecoveryCommand(t *testing.T, s *mgr.Service, should string) {
|
||||
err := s.SetRecoveryCommand(should)
|
||||
if err != nil {
|
||||
t.Fatalf("SetRecoveryCommand failed: %v", err)
|
||||
}
|
||||
is, err := s.RecoveryCommand()
|
||||
if err != nil {
|
||||
t.Fatalf("RecoveryCommand failed: %v", err)
|
||||
}
|
||||
if should != is {
|
||||
t.Errorf("recovery command mismatch: command is %q, but should have %q", is, should)
|
||||
}
|
||||
}
|
||||
|
||||
func remove(t *testing.T, s *mgr.Service) {
|
||||
err := s.Delete()
|
||||
if err != nil {
|
||||
t.Fatalf("Delete failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMyService(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode - it modifies system services")
|
||||
}
|
||||
|
||||
const name = "myservice"
|
||||
|
||||
m, err := mgr.Connect()
|
||||
if err != nil {
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERROR_ACCESS_DENIED {
|
||||
t.Skip("Skipping test: we don't have rights to manage services.")
|
||||
}
|
||||
t.Fatalf("SCM connection failed: %s", err)
|
||||
}
|
||||
defer m.Disconnect()
|
||||
|
||||
c := mgr.Config{
|
||||
StartType: mgr.StartDisabled,
|
||||
DisplayName: "my service",
|
||||
Description: "my service is just a test",
|
||||
Dependencies: []string{"LanmanServer", "W32Time"},
|
||||
}
|
||||
|
||||
exename := os.Args[0]
|
||||
exepath, err := filepath.Abs(exename)
|
||||
if err != nil {
|
||||
t.Fatalf("filepath.Abs(%s) failed: %s", exename, err)
|
||||
}
|
||||
|
||||
install(t, m, name, exepath, c)
|
||||
|
||||
s, err := m.OpenService(name)
|
||||
if err != nil {
|
||||
t.Fatalf("service %s is not installed", name)
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
c.BinaryPathName = exepath
|
||||
c = testConfig(t, s, c)
|
||||
|
||||
c.StartType = mgr.StartManual
|
||||
err = s.UpdateConfig(c)
|
||||
if err != nil {
|
||||
t.Fatalf("UpdateConfig failed: %v", err)
|
||||
}
|
||||
|
||||
testConfig(t, s, c)
|
||||
|
||||
svcnames, err := m.ListServices()
|
||||
if err != nil {
|
||||
t.Fatalf("ListServices failed: %v", err)
|
||||
}
|
||||
var myserviceIsInstalled bool
|
||||
for _, sn := range svcnames {
|
||||
if sn == name {
|
||||
myserviceIsInstalled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !myserviceIsInstalled {
|
||||
t.Errorf("ListServices failed to find %q service", name)
|
||||
}
|
||||
|
||||
testSetRecoveryActions(t, s)
|
||||
testRebootMessage(t, s, "myservice failed")
|
||||
testRebootMessage(t, s, "") // delete reboot message
|
||||
testRecoveryCommand(t, s, "sc query myservice")
|
||||
testRecoveryCommand(t, s, "") // delete recovery command
|
||||
|
||||
remove(t, s)
|
||||
}
|
135
vendor/golang.org/x/sys/windows/svc/mgr/recovery.go
generated
vendored
Normal file
135
vendor/golang.org/x/sys/windows/svc/mgr/recovery.go
generated
vendored
Normal file
|
@ -0,0 +1,135 @@
|
|||
// 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.
|
||||
|
||||
// +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
|
||||
}
|
||||
|
||||
var recoveryActions []RecoveryAction
|
||||
actions := (*[1024]windows.SC_ACTION)(unsafe.Pointer(p.Actions))[:p.ActionsCount]
|
||||
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 toString(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 toString(p.Command), nil
|
||||
}
|
72
vendor/golang.org/x/sys/windows/svc/mgr/service.go
generated
vendored
Normal file
72
vendor/golang.org/x/sys/windows/svc/mgr/service.go
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
// 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.
|
||||
|
||||
// +build windows
|
||||
|
||||
package mgr
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc"
|
||||
)
|
||||
|
||||
// TODO(brainman): Use EnumDependentServices to enumerate dependent services.
|
||||
|
||||
// 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 servce s.
|
||||
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 {
|
||||
return svc.Status{}, err
|
||||
}
|
||||
return svc.Status{
|
||||
State: svc.State(t.CurrentState),
|
||||
Accepts: svc.Accepted(t.ControlsAccepted),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Query returns current status of service s.
|
||||
func (s *Service) Query() (svc.Status, error) {
|
||||
var t windows.SERVICE_STATUS
|
||||
err := windows.QueryServiceStatus(s.Handle, &t)
|
||||
if err != nil {
|
||||
return svc.Status{}, err
|
||||
}
|
||||
return svc.Status{
|
||||
State: svc.State(t.CurrentState),
|
||||
Accepts: svc.Accepted(t.ControlsAccepted),
|
||||
}, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue