mirror of
https://github.com/golang/sys.git
synced 2026-02-09 12:16:04 +03:00
One thing the newer notification API does not do is automatically provide the service exit code in its notifier response. It requires querying manually. Unfortunately, we weren't propagating this information up from the lower level struct, so this commit copys that information over. Change-Id: I70c683007ce34ffab6196329acefc8443f921ebe Reviewed-on: https://go-review.googlesource.com/c/sys/+/274577 Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com> Trust: Alex Brainman <alex.brainman@gmail.com> Trust: Jason A. Donenfeld <Jason@zx2c4.com>
78 lines
2.0 KiB
Go
78 lines
2.0 KiB
Go
// 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,
|
|
Win32ExitCode: t.Win32ExitCode,
|
|
ServiceSpecificExitCode: t.ServiceSpecificExitCode,
|
|
}, nil
|
|
}
|