OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / sys / windows / svc / mgr / config.go
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         "golang.org/x/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 }