github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/osext/winsvc/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 package mgr 6 7 import ( 8 "chai2010.gopkg/osext/winsvc/winapi" 9 "syscall" 10 "unsafe" 11 ) 12 13 const ( 14 // Service start types 15 StartManual = winapi.SERVICE_DEMAND_START // the service must be started manually 16 StartAutomatic = winapi.SERVICE_AUTO_START // the service will start by itself whenever the computer reboots 17 StartDisabled = winapi.SERVICE_DISABLED // the service cannot be started 18 19 // The severity of the error, and action taken, 20 // if this service fails to start. 21 ErrorCritical = winapi.SERVICE_ERROR_CRITICAL 22 ErrorIgnore = winapi.SERVICE_ERROR_IGNORE 23 ErrorNormal = winapi.SERVICE_ERROR_NORMAL 24 ErrorSevere = winapi.SERVICE_ERROR_SEVERE 25 ) 26 27 // TODO: Password is not returned by winapi.QueryServiceConfig, maybe I should do something about it 28 29 type Config struct { 30 ServiceType uint32 31 StartType uint32 32 ErrorControl uint32 33 BinaryPathName string 34 LoadOrderGroup string 35 TagId uint32 36 Dependencies string 37 ServiceStartName string // name of the account under which the service should run 38 DisplayName string 39 Password string 40 Description string 41 } 42 43 func toString(p *uint16) string { 44 if p == nil { 45 return "" 46 } 47 return syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(p))[:]) 48 } 49 50 func (s *Service) Config() (Config, error) { 51 b := make([]byte, 1024) 52 p := (*winapi.QUERY_SERVICE_CONFIG)(unsafe.Pointer(&b[0])) 53 var l uint32 54 err := winapi.QueryServiceConfig(s.Handle, p, uint32(len(b)), &l) 55 if err != nil { 56 if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER { 57 return Config{}, err 58 } 59 b = make([]byte, l) 60 p = (*winapi.QUERY_SERVICE_CONFIG)(unsafe.Pointer(&b[0])) 61 err = winapi.QueryServiceConfig(s.Handle, p, l, &l) 62 if err != nil { 63 return Config{}, err 64 } 65 } 66 b = make([]byte, 1024) 67 err = winapi.QueryServiceConfig2(s.Handle, 68 winapi.SERVICE_CONFIG_DESCRIPTION, &b[0], uint32(len(b)), &l) 69 if err != nil { 70 if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER { 71 return Config{}, err 72 } 73 b = make([]byte, l) 74 err = winapi.QueryServiceConfig2(s.Handle, 75 winapi.SERVICE_CONFIG_DESCRIPTION, &b[0], uint32(len(b)), &l) 76 if err != nil { 77 return Config{}, err 78 } 79 } 80 p2 := (*winapi.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0])) 81 return Config{ 82 ServiceType: p.ServiceType, 83 StartType: p.StartType, 84 ErrorControl: p.ErrorControl, 85 BinaryPathName: toString(p.BinaryPathName), 86 LoadOrderGroup: toString(p.LoadOrderGroup), 87 TagId: p.TagId, 88 Dependencies: toString(p.Dependencies), 89 ServiceStartName: toString(p.ServiceStartName), 90 DisplayName: toString(p.DisplayName), 91 Description: toString(p2.Description), 92 }, nil 93 } 94 95 func updateDescription(handle syscall.Handle, desc string) error { 96 d := winapi.SERVICE_DESCRIPTION{toPtr(desc)} 97 err := winapi.ChangeServiceConfig2(handle, 98 winapi.SERVICE_CONFIG_DESCRIPTION, (*byte)(unsafe.Pointer(&d))) 99 if err != nil { 100 return err 101 } 102 return nil 103 } 104 105 func (s *Service) UpdateConfig(c Config) error { 106 err := winapi.ChangeServiceConfig(s.Handle, c.ServiceType, c.StartType, 107 c.ErrorControl, toPtr(c.BinaryPathName), toPtr(c.LoadOrderGroup), 108 nil, toPtr(c.Dependencies), toPtr(c.ServiceStartName), 109 toPtr(c.Password), toPtr(c.DisplayName)) 110 if err != nil { 111 return err 112 } 113 err = updateDescription(s.Handle, c.Description) 114 if err != nil { 115 return err 116 } 117 return nil 118 }