~sinzui/ubuntu/vivid/juju-core/vivid-1.24.6

« back to all changes in this revision

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

  • Committer: Curtis Hovey
  • Date: 2015-09-30 14:14:54 UTC
  • mfrom: (1.1.34)
  • Revision ID: curtis@hovey.name-20150930141454-o3ldf23dzyjio6c0
Backport of 1.24.6 from wily. (LP: #1500916)

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
 
8
 
 
9
import (
 
10
        "syscall"
 
11
        "unicode/utf16"
 
12
        "unsafe"
 
13
 
 
14
        "github.com/gabriel-samfira/sys/windows"
 
15
)
 
16
 
 
17
const (
 
18
        // Service start types.
 
19
        StartManual    = windows.SERVICE_DEMAND_START // the service must be started manually
 
20
        StartAutomatic = windows.SERVICE_AUTO_START   // the service will start by itself whenever the computer reboots
 
21
        StartDisabled  = windows.SERVICE_DISABLED     // the service cannot be started
 
22
 
 
23
        // The severity of the error, and action taken,
 
24
        // if this service fails to start.
 
25
        ErrorCritical = windows.SERVICE_ERROR_CRITICAL
 
26
        ErrorIgnore   = windows.SERVICE_ERROR_IGNORE
 
27
        ErrorNormal   = windows.SERVICE_ERROR_NORMAL
 
28
        ErrorSevere   = windows.SERVICE_ERROR_SEVERE
 
29
)
 
30
 
 
31
// TODO(brainman): Password is not returned by windows.QueryServiceConfig, not sure how to get it.
 
32
 
 
33
type Config struct {
 
34
        ServiceType      uint32
 
35
        StartType        uint32
 
36
        ErrorControl     uint32
 
37
        BinaryPathName   string // fully qualified path to the service binary file, can also include arguments for an auto-start service
 
38
        LoadOrderGroup   string
 
39
        TagId            uint32
 
40
        Dependencies     []string
 
41
        ServiceStartName string // name of the account under which the service should run
 
42
        DisplayName      string
 
43
        Password         string
 
44
        Description      string
 
45
}
 
46
 
 
47
func toString(p *uint16) string {
 
48
        if p == nil {
 
49
                return ""
 
50
        }
 
51
        return syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(p))[:])
 
52
}
 
53
 
 
54
func toStringSlice(ps *uint16) []string {
 
55
        if ps == nil {
 
56
                return nil
 
57
        }
 
58
        r := make([]string, 0)
 
59
        for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(ps)); true; i++ {
 
60
                if p[i] == 0 {
 
61
                        // empty string marks the end
 
62
                        if i <= from {
 
63
                                break
 
64
                        }
 
65
                        r = append(r, string(utf16.Decode(p[from:i])))
 
66
                        from = i + 1
 
67
                }
 
68
        }
 
69
        return r
 
70
}
 
71
 
 
72
// Config retrieves service s configuration paramteres.
 
73
func (s *Service) Config() (Config, error) {
 
74
        var p *windows.QUERY_SERVICE_CONFIG
 
75
        n := uint32(1024)
 
76
        for {
 
77
                b := make([]byte, n)
 
78
                p = (*windows.QUERY_SERVICE_CONFIG)(unsafe.Pointer(&b[0]))
 
79
                err := windows.QueryServiceConfig(s.Handle, p, n, &n)
 
80
                if err == nil {
 
81
                        break
 
82
                }
 
83
                if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER {
 
84
                        return Config{}, err
 
85
                }
 
86
                if n <= uint32(len(b)) {
 
87
                        return Config{}, err
 
88
                }
 
89
        }
 
90
 
 
91
        var p2 *windows.SERVICE_DESCRIPTION
 
92
        n = uint32(1024)
 
93
        for {
 
94
                b := make([]byte, n)
 
95
                p2 = (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0]))
 
96
                err := windows.QueryServiceConfig2(s.Handle,
 
97
                        windows.SERVICE_CONFIG_DESCRIPTION, &b[0], n, &n)
 
98
                if err == nil {
 
99
                        break
 
100
                }
 
101
                if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER {
 
102
                        return Config{}, err
 
103
                }
 
104
                if n <= uint32(len(b)) {
 
105
                        return Config{}, err
 
106
                }
 
107
        }
 
108
 
 
109
        return Config{
 
110
                ServiceType:      p.ServiceType,
 
111
                StartType:        p.StartType,
 
112
                ErrorControl:     p.ErrorControl,
 
113
                BinaryPathName:   toString(p.BinaryPathName),
 
114
                LoadOrderGroup:   toString(p.LoadOrderGroup),
 
115
                TagId:            p.TagId,
 
116
                Dependencies:     toStringSlice(p.Dependencies),
 
117
                ServiceStartName: toString(p.ServiceStartName),
 
118
                DisplayName:      toString(p.DisplayName),
 
119
                Description:      toString(p2.Description),
 
120
        }, nil
 
121
}
 
122
 
 
123
func updateDescription(handle windows.Handle, desc string) error {
 
124
        d := windows.SERVICE_DESCRIPTION{toPtr(desc)}
 
125
        return windows.ChangeServiceConfig2(handle,
 
126
                windows.SERVICE_CONFIG_DESCRIPTION, (*byte)(unsafe.Pointer(&d)))
 
127
}
 
128
 
 
129
// UpdateConfig updates service s configuration parameters.
 
130
func (s *Service) UpdateConfig(c Config) error {
 
131
        err := windows.ChangeServiceConfig(s.Handle, c.ServiceType, c.StartType,
 
132
                c.ErrorControl, toPtr(c.BinaryPathName), toPtr(c.LoadOrderGroup),
 
133
                nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName),
 
134
                toPtr(c.Password), toPtr(c.DisplayName))
 
135
        if err != nil {
 
136
                return err
 
137
        }
 
138
        return updateDescription(s.Handle, c.Description)
 
139
}