summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/sys/windows/svc
diff options
context:
space:
mode:
authorkali kaneko (leap communications) <kali@leap.se>2021-04-14 16:54:42 +0200
committerkali kaneko (leap communications) <kali@leap.se>2021-04-14 16:54:42 +0200
commit67a0eb7111d3f89e4a0cb21e43aefe6d87d37e04 (patch)
treec9b18e0da6e06ac165a485ee957b7850adb12e86 /vendor/golang.org/x/sys/windows/svc
parent2e8f2a2e8e83fd89f956cdde886d5d9d808132da (diff)
[pkg] go mod vendor to build debian/ubuntu packages
Diffstat (limited to 'vendor/golang.org/x/sys/windows/svc')
-rw-r--r--vendor/golang.org/x/sys/windows/svc/debug/log.go56
-rw-r--r--vendor/golang.org/x/sys/windows/svc/debug/service.go45
-rw-r--r--vendor/golang.org/x/sys/windows/svc/event.go48
-rw-r--r--vendor/golang.org/x/sys/windows/svc/eventlog/install.go80
-rw-r--r--vendor/golang.org/x/sys/windows/svc/eventlog/log.go70
-rw-r--r--vendor/golang.org/x/sys/windows/svc/go12.c24
-rw-r--r--vendor/golang.org/x/sys/windows/svc/go12.go11
-rw-r--r--vendor/golang.org/x/sys/windows/svc/go13.go31
-rw-r--r--vendor/golang.org/x/sys/windows/svc/mgr/config.go181
-rw-r--r--vendor/golang.org/x/sys/windows/svc/mgr/mgr.go211
-rw-r--r--vendor/golang.org/x/sys/windows/svc/mgr/recovery.go135
-rw-r--r--vendor/golang.org/x/sys/windows/svc/mgr/service.go75
-rw-r--r--vendor/golang.org/x/sys/windows/svc/security.go62
-rw-r--r--vendor/golang.org/x/sys/windows/svc/service.go364
-rw-r--r--vendor/golang.org/x/sys/windows/svc/sys_386.s69
-rw-r--r--vendor/golang.org/x/sys/windows/svc/sys_amd64.s44
-rw-r--r--vendor/golang.org/x/sys/windows/svc/sys_arm.s38
17 files changed, 1544 insertions, 0 deletions
diff --git a/vendor/golang.org/x/sys/windows/svc/debug/log.go b/vendor/golang.org/x/sys/windows/svc/debug/log.go
new file mode 100644
index 0000000..e51ab42
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/debug/log.go
@@ -0,0 +1,56 @@
+// 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 debug
+
+import (
+ "os"
+ "strconv"
+)
+
+// Log interface allows different log implementations to be used.
+type Log interface {
+ Close() error
+ Info(eid uint32, msg string) error
+ Warning(eid uint32, msg string) error
+ Error(eid uint32, msg string) error
+}
+
+// ConsoleLog provides access to the console.
+type ConsoleLog struct {
+ Name string
+}
+
+// New creates new ConsoleLog.
+func New(source string) *ConsoleLog {
+ return &ConsoleLog{Name: source}
+}
+
+// Close closes console log l.
+func (l *ConsoleLog) Close() error {
+ return nil
+}
+
+func (l *ConsoleLog) report(kind string, eid uint32, msg string) error {
+ s := l.Name + "." + kind + "(" + strconv.Itoa(int(eid)) + "): " + msg + "\n"
+ _, err := os.Stdout.Write([]byte(s))
+ return err
+}
+
+// Info writes an information event msg with event id eid to the console l.
+func (l *ConsoleLog) Info(eid uint32, msg string) error {
+ return l.report("info", eid, msg)
+}
+
+// Warning writes an warning event msg with event id eid to the console l.
+func (l *ConsoleLog) Warning(eid uint32, msg string) error {
+ return l.report("warn", eid, msg)
+}
+
+// Error writes an error event msg with event id eid to the console l.
+func (l *ConsoleLog) Error(eid uint32, msg string) error {
+ return l.report("error", eid, msg)
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/debug/service.go b/vendor/golang.org/x/sys/windows/svc/debug/service.go
new file mode 100644
index 0000000..e621b87
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/debug/service.go
@@ -0,0 +1,45 @@
+// 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 debug provides facilities to execute svc.Handler on console.
+//
+package debug
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+
+ "golang.org/x/sys/windows/svc"
+)
+
+// Run executes service name by calling appropriate handler function.
+// The process is running on console, unlike real service. Use Ctrl+C to
+// send "Stop" command to your service.
+func Run(name string, handler svc.Handler) error {
+ cmds := make(chan svc.ChangeRequest)
+ changes := make(chan svc.Status)
+
+ sig := make(chan os.Signal)
+ signal.Notify(sig)
+
+ go func() {
+ status := svc.Status{State: svc.Stopped}
+ for {
+ select {
+ case <-sig:
+ cmds <- svc.ChangeRequest{Cmd: svc.Stop, CurrentStatus: status}
+ case status = <-changes:
+ }
+ }
+ }()
+
+ _, errno := handler.Execute([]string{name}, cmds, changes)
+ if errno != 0 {
+ return syscall.Errno(errno)
+ }
+ return nil
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/event.go b/vendor/golang.org/x/sys/windows/svc/event.go
new file mode 100644
index 0000000..0508e22
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/event.go
@@ -0,0 +1,48 @@
+// 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 svc
+
+import (
+ "errors"
+
+ "golang.org/x/sys/windows"
+)
+
+// event represents auto-reset, initially non-signaled Windows event.
+// It is used to communicate between go and asm parts of this package.
+type event struct {
+ h windows.Handle
+}
+
+func newEvent() (*event, error) {
+ h, err := windows.CreateEvent(nil, 0, 0, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &event{h: h}, nil
+}
+
+func (e *event) Close() error {
+ return windows.CloseHandle(e.h)
+}
+
+func (e *event) Set() error {
+ return windows.SetEvent(e.h)
+}
+
+func (e *event) Wait() error {
+ s, err := windows.WaitForSingleObject(e.h, windows.INFINITE)
+ switch s {
+ case windows.WAIT_OBJECT_0:
+ break
+ case windows.WAIT_FAILED:
+ return err
+ default:
+ return errors.New("unexpected result from WaitForSingleObject")
+ }
+ return nil
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/eventlog/install.go b/vendor/golang.org/x/sys/windows/svc/eventlog/install.go
new file mode 100644
index 0000000..c76a376
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/eventlog/install.go
@@ -0,0 +1,80 @@
+// 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 eventlog
+
+import (
+ "errors"
+
+ "golang.org/x/sys/windows"
+ "golang.org/x/sys/windows/registry"
+)
+
+const (
+ // Log levels.
+ Info = windows.EVENTLOG_INFORMATION_TYPE
+ Warning = windows.EVENTLOG_WARNING_TYPE
+ Error = windows.EVENTLOG_ERROR_TYPE
+)
+
+const addKeyName = `SYSTEM\CurrentControlSet\Services\EventLog\Application`
+
+// Install modifies PC registry to allow logging with an event source src.
+// It adds all required keys and values to the event log registry key.
+// Install uses msgFile as the event message file. If useExpandKey is true,
+// the event message file is installed as REG_EXPAND_SZ value,
+// otherwise as REG_SZ. Use bitwise of log.Error, log.Warning and
+// log.Info to specify events supported by the new event source.
+func Install(src, msgFile string, useExpandKey bool, eventsSupported uint32) error {
+ appkey, err := registry.OpenKey(registry.LOCAL_MACHINE, addKeyName, registry.CREATE_SUB_KEY)
+ if err != nil {
+ return err
+ }
+ defer appkey.Close()
+
+ sk, alreadyExist, err := registry.CreateKey(appkey, src, registry.SET_VALUE)
+ if err != nil {
+ return err
+ }
+ defer sk.Close()
+ if alreadyExist {
+ return errors.New(addKeyName + `\` + src + " registry key already exists")
+ }
+
+ err = sk.SetDWordValue("CustomSource", 1)
+ if err != nil {
+ return err
+ }
+ if useExpandKey {
+ err = sk.SetExpandStringValue("EventMessageFile", msgFile)
+ } else {
+ err = sk.SetStringValue("EventMessageFile", msgFile)
+ }
+ if err != nil {
+ return err
+ }
+ err = sk.SetDWordValue("TypesSupported", eventsSupported)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// InstallAsEventCreate is the same as Install, but uses
+// %SystemRoot%\System32\EventCreate.exe as the event message file.
+func InstallAsEventCreate(src string, eventsSupported uint32) error {
+ return Install(src, "%SystemRoot%\\System32\\EventCreate.exe", true, eventsSupported)
+}
+
+// Remove deletes all registry elements installed by the correspondent Install.
+func Remove(src string) error {
+ appkey, err := registry.OpenKey(registry.LOCAL_MACHINE, addKeyName, registry.SET_VALUE)
+ if err != nil {
+ return err
+ }
+ defer appkey.Close()
+ return registry.DeleteKey(appkey, src)
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/eventlog/log.go b/vendor/golang.org/x/sys/windows/svc/eventlog/log.go
new file mode 100644
index 0000000..46e5153
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/eventlog/log.go
@@ -0,0 +1,70 @@
+// 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 eventlog implements access to Windows event log.
+//
+package eventlog
+
+import (
+ "errors"
+ "syscall"
+
+ "golang.org/x/sys/windows"
+)
+
+// Log provides access to the system log.
+type Log struct {
+ Handle windows.Handle
+}
+
+// Open retrieves a handle to the specified event log.
+func Open(source string) (*Log, error) {
+ return OpenRemote("", source)
+}
+
+// OpenRemote does the same as Open, but on different computer host.
+func OpenRemote(host, source string) (*Log, error) {
+ if source == "" {
+ return nil, errors.New("Specify event log source")
+ }
+ var s *uint16
+ if host != "" {
+ s = syscall.StringToUTF16Ptr(host)
+ }
+ h, err := windows.RegisterEventSource(s, syscall.StringToUTF16Ptr(source))
+ if err != nil {
+ return nil, err
+ }
+ return &Log{Handle: h}, nil
+}
+
+// Close closes event log l.
+func (l *Log) Close() error {
+ return windows.DeregisterEventSource(l.Handle)
+}
+
+func (l *Log) report(etype uint16, eid uint32, msg string) error {
+ ss := []*uint16{syscall.StringToUTF16Ptr(msg)}
+ return windows.ReportEvent(l.Handle, etype, 0, eid, 0, 1, 0, &ss[0], nil)
+}
+
+// Info writes an information event msg with event id eid to the end of event log l.
+// When EventCreate.exe is used, eid must be between 1 and 1000.
+func (l *Log) Info(eid uint32, msg string) error {
+ return l.report(windows.EVENTLOG_INFORMATION_TYPE, eid, msg)
+}
+
+// Warning writes an warning event msg with event id eid to the end of event log l.
+// When EventCreate.exe is used, eid must be between 1 and 1000.
+func (l *Log) Warning(eid uint32, msg string) error {
+ return l.report(windows.EVENTLOG_WARNING_TYPE, eid, msg)
+}
+
+// Error writes an error event msg with event id eid to the end of event log l.
+// When EventCreate.exe is used, eid must be between 1 and 1000.
+func (l *Log) Error(eid uint32, msg string) error {
+ return l.report(windows.EVENTLOG_ERROR_TYPE, eid, msg)
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/go12.c b/vendor/golang.org/x/sys/windows/svc/go12.c
new file mode 100644
index 0000000..6f1be1f
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/go12.c
@@ -0,0 +1,24 @@
+// 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
+// +build !go1.3
+
+// copied from pkg/runtime
+typedef unsigned int uint32;
+typedef unsigned long long int uint64;
+#ifdef _64BIT
+typedef uint64 uintptr;
+#else
+typedef uint32 uintptr;
+#endif
+
+// from sys_386.s or sys_amd64.s
+void ·servicemain(void);
+
+void
+·getServiceMain(uintptr *r)
+{
+ *r = (uintptr)·servicemain;
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/go12.go b/vendor/golang.org/x/sys/windows/svc/go12.go
new file mode 100644
index 0000000..cd8b913
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/go12.go
@@ -0,0 +1,11 @@
+// Copyright 2014 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
+// +build !go1.3
+
+package svc
+
+// from go12.c
+func getServiceMain(r *uintptr)
diff --git a/vendor/golang.org/x/sys/windows/svc/go13.go b/vendor/golang.org/x/sys/windows/svc/go13.go
new file mode 100644
index 0000000..9d7f3ce
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/go13.go
@@ -0,0 +1,31 @@
+// Copyright 2014 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
+// +build go1.3
+
+package svc
+
+import "unsafe"
+
+const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const
+
+// Should be a built-in for unsafe.Pointer?
+func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
+ return unsafe.Pointer(uintptr(p) + x)
+}
+
+// funcPC returns the entry PC of the function f.
+// It assumes that f is a func value. Otherwise the behavior is undefined.
+func funcPC(f interface{}) uintptr {
+ return **(**uintptr)(add(unsafe.Pointer(&f), ptrSize))
+}
+
+// from sys_386.s and sys_amd64.s
+func servicectlhandler(ctl uint32) uintptr
+func servicemain(argc uint32, argv **uint16)
+
+func getServiceMain(r *uintptr) {
+ *r = funcPC(servicemain)
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/config.go b/vendor/golang.org/x/sys/windows/svc/mgr/config.go
new file mode 100644
index 0000000..8431edb
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/mgr/config.go
@@ -0,0 +1,181 @@
+// 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
+ 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 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]))
+
+ 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
+ }
+
+ 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),
+ DelayedAutoStart: delayedStart,
+ }, 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
+ }
+ }
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/mgr.go b/vendor/golang.org/x/sys/windows/svc/mgr/mgr.go
new file mode 100644
index 0000000..33944d0
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/mgr/mgr.go
@@ -0,0 +1,211 @@
+// 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"
+ "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.UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(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.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.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 := (*[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
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go b/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go
new file mode 100644
index 0000000..71ce2b8
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go
@@ -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
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/service.go b/vendor/golang.org/x/sys/windows/svc/mgr/service.go
new file mode 100644
index 0000000..ded1c7a
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/mgr/service.go
@@ -0,0 +1,75 @@
+// 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"
+ "unsafe"
+
+ "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_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,
+ }, nil
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/security.go b/vendor/golang.org/x/sys/windows/svc/security.go
new file mode 100644
index 0000000..6fbc923
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/security.go
@@ -0,0 +1,62 @@
+// 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 svc
+
+import (
+ "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
+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
+ }
+ p := unsafe.Pointer(&gs.Groups[0])
+ groups := (*[2 << 20]windows.SIDAndAttributes)(p)[:gs.GroupCount]
+ for _, g := range groups {
+ if windows.EqualSid(g.Sid, interSid) {
+ return true, nil
+ }
+ if windows.EqualSid(g.Sid, serviceSid) {
+ return false, nil
+ }
+ }
+ return false, nil
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/service.go b/vendor/golang.org/x/sys/windows/svc/service.go
new file mode 100644
index 0000000..ee3d696
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/service.go
@@ -0,0 +1,364 @@
+// 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 svc provides everything required to build Windows service.
+//
+package svc
+
+import (
+ "errors"
+ "runtime"
+ "syscall"
+ "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)
+)
+
+// 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)
+)
+
+// 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
+}
+
+// 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)
+}
+
+var (
+ // These are used by asm code.
+ goWaitsH uintptr
+ cWaitsH uintptr
+ ssHandle uintptr
+ sName *uint16
+ sArgc uintptr
+ sArgv **uint16
+ ctlHandlerExProc uintptr
+ cSetEvent uintptr
+ cWaitForSingleObject uintptr
+ cRegisterServiceCtrlHandlerExW uintptr
+)
+
+func init() {
+ k := windows.NewLazySystemDLL("kernel32.dll")
+ cSetEvent = k.NewProc("SetEvent").Addr()
+ cWaitForSingleObject = k.NewProc("WaitForSingleObject").Addr()
+ a := windows.NewLazySystemDLL("advapi32.dll")
+ cRegisterServiceCtrlHandlerExW = a.NewProc("RegisterServiceCtrlHandlerExW").Addr()
+}
+
+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
+ cWaits *event
+ goWaits *event
+ c chan ctlEvent
+ handler Handler
+}
+
+func newService(name string, handler Handler) (*service, error) {
+ var s service
+ var err error
+ s.name = name
+ s.c = make(chan ctlEvent)
+ s.handler = handler
+ s.cWaits, err = newEvent()
+ if err != nil {
+ return nil, err
+ }
+ s.goWaits, err = newEvent()
+ if err != nil {
+ s.cWaits.Close()
+ return nil, err
+ }
+ return &s, nil
+}
+
+func (s *service) close() error {
+ s.cWaits.Close()
+ s.goWaits.Close()
+ return nil
+}
+
+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 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)
+}
+
+const (
+ sysErrSetServiceStatusFailed = uint32(syscall.APPLICATION_ERROR) + iota
+ sysErrNewThreadInCallback
+)
+
+func (s *service) run() {
+ s.goWaits.Wait()
+ s.h = windows.Handle(ssHandle)
+ argv := (*[100]*int16)(unsafe.Pointer(sArgv))[:sArgc]
+ args := make([]string, len(argv))
+ for i, a := range argv {
+ args[i] = syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(a))[:])
+ }
+
+ cmdsToHandler := make(chan ChangeRequest)
+ changesFromHandler := make(chan Status)
+ exitFromHandler := make(chan exitCode)
+
+ go func() {
+ ss, errno := s.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 := s.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 = s.c
+ outch = nil
+ case c := <-changesFromHandler:
+ err := s.updateStatus(&c, &ec)
+ if err != nil {
+ // best suitable error number
+ ec.errno = sysErrSetServiceStatusFailed
+ if err2, ok := err.(syscall.Errno); ok {
+ ec.errno = uint32(err2)
+ }
+ break loop
+ }
+ outcr.CurrentStatus = c
+ case ec = <-exitFromHandler:
+ break loop
+ }
+ }
+
+ s.updateStatus(&Status{State: Stopped}, &ec)
+ s.cWaits.Set()
+}
+
+func newCallback(fn interface{}) (cb uintptr, err error) {
+ defer func() {
+ r := recover()
+ if r == nil {
+ return
+ }
+ cb = 0
+ switch v := r.(type) {
+ case string:
+ err = errors.New(v)
+ case error:
+ err = v
+ default:
+ err = errors.New("unexpected panic in syscall.NewCallback")
+ }
+ }()
+ return syscall.NewCallback(fn), nil
+}
+
+// BUG(brainman): There is no mechanism to run multiple services
+// inside one single executable. Perhaps, it can be overcome by
+// using RegisterServiceCtrlHandlerEx Windows api.
+
+// Run executes service name by calling appropriate handler function.
+func Run(name string, handler Handler) error {
+ runtime.LockOSThread()
+
+ tid := windows.GetCurrentThreadId()
+
+ s, err := newService(name, handler)
+ if err != nil {
+ return err
+ }
+
+ ctlHandler := func(ctl, evtype, evdata, context uintptr) uintptr {
+ e := ctlEvent{cmd: Cmd(ctl), eventType: uint32(evtype), eventData: evdata, context: context}
+ // We assume that this callback function is running on
+ // the same thread as Run. Nowhere in MS documentation
+ // I could find statement to guarantee that. So putting
+ // check here to verify, otherwise things will go bad
+ // quickly, if ignored.
+ i := windows.GetCurrentThreadId()
+ if i != tid {
+ e.errno = sysErrNewThreadInCallback
+ }
+ s.c <- e
+ // Always return NO_ERROR (0) for now.
+ return windows.NO_ERROR
+ }
+
+ var svcmain uintptr
+ getServiceMain(&svcmain)
+ t := []windows.SERVICE_TABLE_ENTRY{
+ {ServiceName: syscall.StringToUTF16Ptr(s.name), ServiceProc: svcmain},
+ {ServiceName: nil, ServiceProc: 0},
+ }
+
+ goWaitsH = uintptr(s.goWaits.h)
+ cWaitsH = uintptr(s.cWaits.h)
+ sName = t[0].ServiceName
+ ctlHandlerExProc, err = newCallback(ctlHandler)
+ if err != nil {
+ return err
+ }
+
+ go s.run()
+
+ err = windows.StartServiceCtrlDispatcher(&t[0])
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// 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.
+// This code will have to change once multiple services are possible per process.
+func StatusHandle() windows.Handle {
+ return windows.Handle(ssHandle)
+}
diff --git a/vendor/golang.org/x/sys/windows/svc/sys_386.s b/vendor/golang.org/x/sys/windows/svc/sys_386.s
new file mode 100644
index 0000000..c8a583d
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/sys_386.s
@@ -0,0 +1,69 @@
+// 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
+
+// func servicemain(argc uint32, argv **uint16)
+TEXT ·servicemain(SB),7,$0
+ MOVL argc+0(FP), AX
+ MOVL AX, ·sArgc(SB)
+ MOVL argv+4(FP), AX
+ MOVL AX, ·sArgv(SB)
+
+ PUSHL BP
+ PUSHL BX
+ PUSHL SI
+ PUSHL DI
+
+ SUBL $12, SP
+
+ MOVL ·sName(SB), AX
+ MOVL AX, (SP)
+ MOVL $·servicectlhandler(SB), AX
+ MOVL AX, 4(SP)
+ // Set context to 123456 to test issue #25660.
+ MOVL $123456, 8(SP)
+ MOVL ·cRegisterServiceCtrlHandlerExW(SB), AX
+ MOVL SP, BP
+ CALL AX
+ MOVL BP, SP
+ CMPL AX, $0
+ JE exit
+ MOVL AX, ·ssHandle(SB)
+
+ MOVL ·goWaitsH(SB), AX
+ MOVL AX, (SP)
+ MOVL ·cSetEvent(SB), AX
+ MOVL SP, BP
+ CALL AX
+ MOVL BP, SP
+
+ MOVL ·cWaitsH(SB), AX
+ MOVL AX, (SP)
+ MOVL $-1, AX
+ MOVL AX, 4(SP)
+ MOVL ·cWaitForSingleObject(SB), AX
+ MOVL SP, BP
+ CALL AX
+ MOVL BP, SP
+
+exit:
+ ADDL $12, SP
+
+ POPL DI
+ POPL SI
+ POPL BX
+ POPL BP
+
+ MOVL 0(SP), CX
+ ADDL $12, SP
+ JMP CX
+
+// I do not know why, but this seems to be the only way to call
+// ctlHandlerProc on Windows 7.
+
+// func servicectlhandler(ctl uint32, evtype uint32, evdata uintptr, context uintptr) uintptr {
+TEXT ·servicectlhandler(SB),7,$0
+ MOVL ·ctlHandlerExProc(SB), CX
+ JMP CX
diff --git a/vendor/golang.org/x/sys/windows/svc/sys_amd64.s b/vendor/golang.org/x/sys/windows/svc/sys_amd64.s
new file mode 100644
index 0000000..2f7609c
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/sys_amd64.s
@@ -0,0 +1,44 @@
+// 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
+
+// func servicemain(argc uint32, argv **uint16)
+TEXT ·servicemain(SB),7,$0
+ MOVL CX, ·sArgc(SB)
+ MOVQ DX, ·sArgv(SB)
+
+ SUBQ $32, SP // stack for the first 4 syscall params
+
+ MOVQ ·sName(SB), CX
+ MOVQ $·servicectlhandler(SB), DX
+ // BUG(pastarmovj): Figure out a way to pass in context in R8.
+ // Set context to 123456 to test issue #25660.
+ MOVQ $123456, R8
+ MOVQ ·cRegisterServiceCtrlHandlerExW(SB), AX
+ CALL AX
+ CMPQ AX, $0
+ JE exit
+ MOVQ AX, ·ssHandle(SB)
+
+ MOVQ ·goWaitsH(SB), CX
+ MOVQ ·cSetEvent(SB), AX
+ CALL AX
+
+ MOVQ ·cWaitsH(SB), CX
+ MOVQ $4294967295, DX
+ MOVQ ·cWaitForSingleObject(SB), AX
+ CALL AX
+
+exit:
+ ADDQ $32, SP
+ RET
+
+// I do not know why, but this seems to be the only way to call
+// ctlHandlerProc on Windows 7.
+
+// func ·servicectlhandler(ctl uint32, evtype uint32, evdata uintptr, context uintptr) uintptr {
+TEXT ·servicectlhandler(SB),7,$0
+ MOVQ ·ctlHandlerExProc(SB), AX
+ JMP AX
diff --git a/vendor/golang.org/x/sys/windows/svc/sys_arm.s b/vendor/golang.org/x/sys/windows/svc/sys_arm.s
new file mode 100644
index 0000000..33c692a
--- /dev/null
+++ b/vendor/golang.org/x/sys/windows/svc/sys_arm.s
@@ -0,0 +1,38 @@
+// 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
+
+#include "textflag.h"
+
+// func servicemain(argc uint32, argv **uint16)
+TEXT ·servicemain(SB),NOSPLIT|NOFRAME,$0
+ MOVM.DB.W [R4, R14], (R13) // push {r4, lr}
+ MOVW R13, R4
+ BIC $0x7, R13 // alignment for ABI
+
+ MOVW R0, ·sArgc(SB)
+ MOVW R1, ·sArgv(SB)
+
+ MOVW ·sName(SB), R0
+ MOVW ·ctlHandlerExProc(SB), R1
+ MOVW $0, R2
+ MOVW ·cRegisterServiceCtrlHandlerExW(SB), R3
+ BL (R3)
+ CMP $0, R0
+ BEQ exit
+ MOVW R0, ·ssHandle(SB)
+
+ MOVW ·goWaitsH(SB), R0
+ MOVW ·cSetEvent(SB), R1
+ BL (R1)
+
+ MOVW ·cWaitsH(SB), R0
+ MOVW $-1, R1
+ MOVW ·cWaitForSingleObject(SB), R2
+ BL (R2)
+
+exit:
+ MOVW R4, R13 // free extra stack space
+ MOVM.IA.W (R13), [R4, R15] // pop {r4, pc}