github.com/ie310mu/ie310go/forks/golang.org/x/sys@v0.0.0-20190821095322-9a46783d4de5/windows/svc/mgr/config.go (about) 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/ie310mu/ie310go/forks/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 SidType uint32 // one of SERVICE_SID_TYPE, the type of sid to use for the service 46 } 47 48 func toString(p *uint16) string { 49 if p == nil { 50 return "" 51 } 52 return syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(p))[:]) 53 } 54 55 func toStringSlice(ps *uint16) []string { 56 if ps == nil { 57 return nil 58 } 59 r := make([]string, 0) 60 for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(ps)); true; i++ { 61 if p[i] == 0 { 62 // empty string marks the end 63 if i <= from { 64 break 65 } 66 r = append(r, string(utf16.Decode(p[from:i]))) 67 from = i + 1 68 } 69 } 70 return r 71 } 72 73 // Config retrieves service s configuration paramteres. 74 func (s *Service) Config() (Config, error) { 75 var p *windows.QUERY_SERVICE_CONFIG 76 n := uint32(1024) 77 for { 78 b := make([]byte, n) 79 p = (*windows.QUERY_SERVICE_CONFIG)(unsafe.Pointer(&b[0])) 80 err := windows.QueryServiceConfig(s.Handle, p, n, &n) 81 if err == nil { 82 break 83 } 84 if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER { 85 return Config{}, err 86 } 87 if n <= uint32(len(b)) { 88 return Config{}, err 89 } 90 } 91 92 b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_DESCRIPTION) 93 if err != nil { 94 return Config{}, err 95 } 96 p2 := (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0])) 97 98 return Config{ 99 ServiceType: p.ServiceType, 100 StartType: p.StartType, 101 ErrorControl: p.ErrorControl, 102 BinaryPathName: toString(p.BinaryPathName), 103 LoadOrderGroup: toString(p.LoadOrderGroup), 104 TagId: p.TagId, 105 Dependencies: toStringSlice(p.Dependencies), 106 ServiceStartName: toString(p.ServiceStartName), 107 DisplayName: toString(p.DisplayName), 108 Description: toString(p2.Description), 109 }, nil 110 } 111 112 func updateDescription(handle windows.Handle, desc string) error { 113 d := windows.SERVICE_DESCRIPTION{Description: toPtr(desc)} 114 return windows.ChangeServiceConfig2(handle, 115 windows.SERVICE_CONFIG_DESCRIPTION, (*byte)(unsafe.Pointer(&d))) 116 } 117 118 func updateSidType(handle windows.Handle, sidType uint32) error { 119 return windows.ChangeServiceConfig2(handle, windows.SERVICE_CONFIG_SERVICE_SID_INFO, (*byte)(unsafe.Pointer(&sidType))) 120 } 121 122 // UpdateConfig updates service s configuration parameters. 123 func (s *Service) UpdateConfig(c Config) error { 124 err := windows.ChangeServiceConfig(s.Handle, c.ServiceType, c.StartType, 125 c.ErrorControl, toPtr(c.BinaryPathName), toPtr(c.LoadOrderGroup), 126 nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName), 127 toPtr(c.Password), toPtr(c.DisplayName)) 128 if err != nil { 129 return err 130 } 131 err = updateSidType(s.Handle, c.SidType) 132 if err != nil { 133 return err 134 } 135 return updateDescription(s.Handle, c.Description) 136 } 137 138 // queryServiceConfig2 calls Windows QueryServiceConfig2 with infoLevel parameter and returns retrieved service configuration information. 139 func (s *Service) queryServiceConfig2(infoLevel uint32) ([]byte, error) { 140 n := uint32(1024) 141 for { 142 b := make([]byte, n) 143 err := windows.QueryServiceConfig2(s.Handle, infoLevel, &b[0], n, &n) 144 if err == nil { 145 return b, nil 146 } 147 if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER { 148 return nil, err 149 } 150 if n <= uint32(len(b)) { 151 return nil, err 152 } 153 } 154 }