github.com/gogf/gkafka@v1.0.1-0.20190702070843-033a14468069/third/golang.org/x/sys/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/gogf/gkafka/third/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  	b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_DESCRIPTION)
    92  	if err != nil {
    93  		return Config{}, err
    94  	}
    95  	p2 := (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0]))
    96  
    97  	return Config{
    98  		ServiceType:      p.ServiceType,
    99  		StartType:        p.StartType,
   100  		ErrorControl:     p.ErrorControl,
   101  		BinaryPathName:   toString(p.BinaryPathName),
   102  		LoadOrderGroup:   toString(p.LoadOrderGroup),
   103  		TagId:            p.TagId,
   104  		Dependencies:     toStringSlice(p.Dependencies),
   105  		ServiceStartName: toString(p.ServiceStartName),
   106  		DisplayName:      toString(p.DisplayName),
   107  		Description:      toString(p2.Description),
   108  	}, nil
   109  }
   110  
   111  func updateDescription(handle windows.Handle, desc string) error {
   112  	d := windows.SERVICE_DESCRIPTION{Description: toPtr(desc)}
   113  	return windows.ChangeServiceConfig2(handle,
   114  		windows.SERVICE_CONFIG_DESCRIPTION, (*byte)(unsafe.Pointer(&d)))
   115  }
   116  
   117  // UpdateConfig updates service s configuration parameters.
   118  func (s *Service) UpdateConfig(c Config) error {
   119  	err := windows.ChangeServiceConfig(s.Handle, c.ServiceType, c.StartType,
   120  		c.ErrorControl, toPtr(c.BinaryPathName), toPtr(c.LoadOrderGroup),
   121  		nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName),
   122  		toPtr(c.Password), toPtr(c.DisplayName))
   123  	if err != nil {
   124  		return err
   125  	}
   126  	return updateDescription(s.Handle, c.Description)
   127  }
   128  
   129  // queryServiceConfig2 calls Windows QueryServiceConfig2 with infoLevel parameter and returns retrieved service configuration information.
   130  func (s *Service) queryServiceConfig2(infoLevel uint32) ([]byte, error) {
   131  	n := uint32(1024)
   132  	for {
   133  		b := make([]byte, n)
   134  		err := windows.QueryServiceConfig2(s.Handle, infoLevel, &b[0], n, &n)
   135  		if err == nil {
   136  			return b, nil
   137  		}
   138  		if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER {
   139  			return nil, err
   140  		}
   141  		if n <= uint32(len(b)) {
   142  			return nil, err
   143  		}
   144  	}
   145  }