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  }