~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/gabriel-samfira/sys/windows/svc/mgr/mgr.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012 The Go Authors. All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
// +build windows
 
6
 
 
7
// Package mgr can be used to manage Windows service programs.
 
8
// It can be used to install and remove them. It can also start,
 
9
// stop and pause them. The package can query / change current
 
10
// service state and config parameters.
 
11
//
 
12
package mgr
 
13
 
 
14
import (
 
15
        "syscall"
 
16
        "unicode/utf16"
 
17
 
 
18
        "github.com/gabriel-samfira/sys/windows"
 
19
)
 
20
 
 
21
// Mgr is used to manage Windows service.
 
22
type Mgr struct {
 
23
        Handle windows.Handle
 
24
}
 
25
 
 
26
// Connect establishes a connection to the service control manager.
 
27
func Connect() (*Mgr, error) {
 
28
        return ConnectRemote("")
 
29
}
 
30
 
 
31
// ConnectRemote establishes a connection to the
 
32
// service control manager on computer named host.
 
33
func ConnectRemote(host string) (*Mgr, error) {
 
34
        var s *uint16
 
35
        if host != "" {
 
36
                s = syscall.StringToUTF16Ptr(host)
 
37
        }
 
38
        h, err := windows.OpenSCManager(s, nil, windows.SC_MANAGER_ALL_ACCESS)
 
39
        if err != nil {
 
40
                return nil, err
 
41
        }
 
42
        return &Mgr{Handle: h}, nil
 
43
}
 
44
 
 
45
// Disconnect closes connection to the service control manager m.
 
46
func (m *Mgr) Disconnect() error {
 
47
        return windows.CloseServiceHandle(m.Handle)
 
48
}
 
49
 
 
50
func toPtr(s string) *uint16 {
 
51
        if len(s) == 0 {
 
52
                return nil
 
53
        }
 
54
        return syscall.StringToUTF16Ptr(s)
 
55
}
 
56
 
 
57
// toStringBlock terminates strings in ss with 0, and then
 
58
// concatenates them together. It also adds extra 0 at the end.
 
59
func toStringBlock(ss []string) *uint16 {
 
60
        if len(ss) == 0 {
 
61
                return nil
 
62
        }
 
63
        t := ""
 
64
        for _, s := range ss {
 
65
                if s != "" {
 
66
                        t += s + "\x00"
 
67
                }
 
68
        }
 
69
        if t == "" {
 
70
                return nil
 
71
        }
 
72
        t += "\x00"
 
73
        return &utf16.Encode([]rune(t))[0]
 
74
}
 
75
 
 
76
// CreateService installs new service name on the system.
 
77
// The service will be executed by running exepath binary.
 
78
// Use config c to specify service parameters.
 
79
// If service StartType is set to StartAutomatic,
 
80
// args will be passed to svc.Handle.Execute.
 
81
func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Service, error) {
 
82
        if c.StartType == 0 {
 
83
                c.StartType = StartManual
 
84
        }
 
85
        if c.ErrorControl == 0 {
 
86
                c.ErrorControl = ErrorNormal
 
87
        }
 
88
        s := syscall.EscapeArg(exepath)
 
89
        for _, v := range args {
 
90
                s += " " + syscall.EscapeArg(v)
 
91
        }
 
92
        h, err := windows.CreateService(m.Handle, toPtr(name), toPtr(c.DisplayName),
 
93
                windows.SERVICE_ALL_ACCESS, windows.SERVICE_WIN32_OWN_PROCESS,
 
94
                c.StartType, c.ErrorControl, toPtr(s), toPtr(c.LoadOrderGroup),
 
95
                nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName), toPtr(c.Password))
 
96
        if err != nil {
 
97
                return nil, err
 
98
        }
 
99
        if c.Description != "" {
 
100
                err = updateDescription(h, c.Description)
 
101
                if err != nil {
 
102
                        return nil, err
 
103
                }
 
104
        }
 
105
        return &Service{Name: name, Handle: h}, nil
 
106
}
 
107
 
 
108
// OpenService retrieves access to service name, so it can
 
109
// be interrogated and controlled.
 
110
func (m *Mgr) OpenService(name string) (*Service, error) {
 
111
        h, err := windows.OpenService(m.Handle, syscall.StringToUTF16Ptr(name), windows.SERVICE_ALL_ACCESS)
 
112
        if err != nil {
 
113
                return nil, err
 
114
        }
 
115
        return &Service{Name: name, Handle: h}, nil
 
116
}