1  
     2  
     3  
     4  
     5  
     6  
     7  package mgr
     8  
     9  import (
    10  	"errors"
    11  	"syscall"
    12  	"time"
    13  	"unsafe"
    14  
    15  	"golang.org/x/sys/windows"
    16  )
    17  
    18  const (
    19  	
    20  	NoAction       = windows.SC_ACTION_NONE        
    21  	ComputerReboot = windows.SC_ACTION_REBOOT      
    22  	ServiceRestart = windows.SC_ACTION_RESTART     
    23  	RunCommand     = windows.SC_ACTION_RUN_COMMAND 
    24  )
    25  
    26  
    27  
    28  type RecoveryAction struct {
    29  	Type  int           
    30  	Delay time.Duration 
    31  }
    32  
    33  
    34  
    35  
    36  func (s *Service) SetRecoveryActions(recoveryActions []RecoveryAction, resetPeriod uint32) error {
    37  	if recoveryActions == nil {
    38  		return errors.New("recoveryActions cannot be nil")
    39  	}
    40  	actions := []windows.SC_ACTION{}
    41  	for _, a := range recoveryActions {
    42  		action := windows.SC_ACTION{
    43  			Type:  uint32(a.Type),
    44  			Delay: uint32(a.Delay.Nanoseconds() / 1000000),
    45  		}
    46  		actions = append(actions, action)
    47  	}
    48  	rActions := windows.SERVICE_FAILURE_ACTIONS{
    49  		ActionsCount: uint32(len(actions)),
    50  		Actions:      &actions[0],
    51  		ResetPeriod:  resetPeriod,
    52  	}
    53  	return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
    54  }
    55  
    56  
    57  
    58  
    59  
    60  
    61  func (s *Service) RecoveryActions() ([]RecoveryAction, error) {
    62  	b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  	p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
    67  	if p.Actions == nil {
    68  		return nil, err
    69  	}
    70  
    71  	actions := unsafe.Slice(p.Actions, int(p.ActionsCount))
    72  	var recoveryActions []RecoveryAction
    73  	for _, action := range actions {
    74  		recoveryActions = append(recoveryActions, RecoveryAction{Type: int(action.Type), Delay: time.Duration(action.Delay) * time.Millisecond})
    75  	}
    76  	return recoveryActions, nil
    77  }
    78  
    79  
    80  func (s *Service) ResetRecoveryActions() error {
    81  	actions := make([]windows.SC_ACTION, 1)
    82  	rActions := windows.SERVICE_FAILURE_ACTIONS{
    83  		Actions: &actions[0],
    84  	}
    85  	return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
    86  }
    87  
    88  
    89  
    90  func (s *Service) ResetPeriod() (uint32, error) {
    91  	b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
    92  	if err != nil {
    93  		return 0, err
    94  	}
    95  	p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
    96  	return p.ResetPeriod, nil
    97  }
    98  
    99  
   100  
   101  func (s *Service) SetRebootMessage(msg string) error {
   102  	rActions := windows.SERVICE_FAILURE_ACTIONS{
   103  		RebootMsg: syscall.StringToUTF16Ptr(msg),
   104  	}
   105  	return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
   106  }
   107  
   108  
   109  func (s *Service) RebootMessage() (string, error) {
   110  	b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
   111  	if err != nil {
   112  		return "", err
   113  	}
   114  	p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
   115  	return windows.UTF16PtrToString(p.RebootMsg), nil
   116  }
   117  
   118  
   119  
   120  func (s *Service) SetRecoveryCommand(cmd string) error {
   121  	rActions := windows.SERVICE_FAILURE_ACTIONS{
   122  		Command: syscall.StringToUTF16Ptr(cmd),
   123  	}
   124  	return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
   125  }
   126  
   127  
   128  func (s *Service) RecoveryCommand() (string, error) {
   129  	b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
   130  	if err != nil {
   131  		return "", err
   132  	}
   133  	p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
   134  	return windows.UTF16PtrToString(p.Command), nil
   135  }
   136  
   137  
   138  
   139  
   140  
   141  
   142  func (s *Service) SetRecoveryActionsOnNonCrashFailures(flag bool) error {
   143  	var setting windows.SERVICE_FAILURE_ACTIONS_FLAG
   144  	if flag {
   145  		setting.FailureActionsOnNonCrashFailures = 1
   146  	}
   147  	return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, (*byte)(unsafe.Pointer(&setting)))
   148  }
   149  
   150  
   151  
   152  
   153  
   154  
   155  func (s *Service) RecoveryActionsOnNonCrashFailures() (bool, error) {
   156  	b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG)
   157  	if err != nil {
   158  		return false, err
   159  	}
   160  	p := (*windows.SERVICE_FAILURE_ACTIONS_FLAG)(unsafe.Pointer(&b[0]))
   161  	return p.FailureActionsOnNonCrashFailures != 0, nil
   162  }
   163  
View as plain text