// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows

// Package svc provides everything required to build Windows service.
//
package svc

import (
	"errors"
	"runtime"
	"syscall"
	"unsafe"

	"golang.org/x/sys/windows"
)

// State describes service execution state (Stopped, Running and so on).
type State uint32

const (
	Stopped         = State(windows.SERVICE_STOPPED)
	StartPending    = State(windows.SERVICE_START_PENDING)
	StopPending     = State(windows.SERVICE_STOP_PENDING)
	Running         = State(windows.SERVICE_RUNNING)
	ContinuePending = State(windows.SERVICE_CONTINUE_PENDING)
	PausePending    = State(windows.SERVICE_PAUSE_PENDING)
	Paused          = State(windows.SERVICE_PAUSED)
)

// Cmd represents service state change request. It is sent to a service
// by the service manager, and should be actioned upon by the service.
type Cmd uint32

const (
	Stop                  = Cmd(windows.SERVICE_CONTROL_STOP)
	Pause                 = Cmd(windows.SERVICE_CONTROL_PAUSE)
	Continue              = Cmd(windows.SERVICE_CONTROL_CONTINUE)
	Interrogate           = Cmd(windows.SERVICE_CONTROL_INTERROGATE)
	Shutdown              = Cmd(windows.SERVICE_CONTROL_SHUTDOWN)
	ParamChange           = Cmd(windows.SERVICE_CONTROL_PARAMCHANGE)
	NetBindAdd            = Cmd(windows.SERVICE_CONTROL_NETBINDADD)
	NetBindRemove         = Cmd(windows.SERVICE_CONTROL_NETBINDREMOVE)
	NetBindEnable         = Cmd(windows.SERVICE_CONTROL_NETBINDENABLE)
	NetBindDisable        = Cmd(windows.SERVICE_CONTROL_NETBINDDISABLE)
	DeviceEvent           = Cmd(windows.SERVICE_CONTROL_DEVICEEVENT)
	HardwareProfileChange = Cmd(windows.SERVICE_CONTROL_HARDWAREPROFILECHANGE)
	PowerEvent            = Cmd(windows.SERVICE_CONTROL_POWEREVENT)
	SessionChange         = Cmd(windows.SERVICE_CONTROL_SESSIONCHANGE)
)

// Accepted is used to describe commands accepted by the service.
// Note that Interrogate is always accepted.
type Accepted uint32

const (
	AcceptStop                  = Accepted(windows.SERVICE_ACCEPT_STOP)
	AcceptShutdown              = Accepted(windows.SERVICE_ACCEPT_SHUTDOWN)
	AcceptPauseAndContinue      = Accepted(windows.SERVICE_ACCEPT_PAUSE_CONTINUE)
	AcceptParamChange           = Accepted(windows.SERVICE_ACCEPT_PARAMCHANGE)
	AcceptNetBindChange         = Accepted(windows.SERVICE_ACCEPT_NETBINDCHANGE)
	AcceptHardwareProfileChange = Accepted(windows.SERVICE_ACCEPT_HARDWAREPROFILECHANGE)
	AcceptPowerEvent            = Accepted(windows.SERVICE_ACCEPT_POWEREVENT)
	AcceptSessionChange         = Accepted(windows.SERVICE_ACCEPT_SESSIONCHANGE)
)

// Status combines State and Accepted commands to fully describe running service.
type Status struct {
	State      State
	Accepts    Accepted
	CheckPoint uint32 // used to report progress during a lengthy operation
	WaitHint   uint32 // estimated time required for a pending operation, in milliseconds
	ProcessId  uint32 // if the service is running, the process identifier of it, and otherwise zero
}

// ChangeRequest is sent to the service Handler to request service status change.
type ChangeRequest struct {
	Cmd           Cmd
	EventType     uint32
	EventData     uintptr
	CurrentStatus Status
	Context       uintptr
}

// Handler is the interface that must be implemented to build Windows service.
type Handler interface {

	// Execute will be called by the package code at the start of
	// the service, and the service will exit once Execute completes.
	// Inside Execute you must read service change requests from r and
	// act accordingly. You must keep service control manager up to date
	// about state of your service by writing into s as required.
	// args contains service name followed by argument strings passed
	// to the service.
	// You can provide service exit code in exitCode return parameter,
	// with 0 being "no error". You can also indicate if exit code,
	// if any, is service specific or not by using svcSpecificEC
	// parameter.
	Execute(args []string, r <-chan ChangeRequest, s chan<- Status) (svcSpecificEC bool, exitCode uint32)
}

var (
	// These are used by asm code.
	goWaitsH                       uintptr
	cWaitsH                        uintptr
	ssHandle                       uintptr
	sName                          *uint16
	sArgc                          uintptr
	sArgv                          **uint16
	ctlHandlerExProc               uintptr
	cSetEvent                      uintptr
	cWaitForSingleObject           uintptr
	cRegisterServiceCtrlHandlerExW uintptr
)

func init() {
	k := windows.NewLazySystemDLL("kernel32.dll")
	cSetEvent = k.NewProc("SetEvent").Addr()
	cWaitForSingleObject = k.NewProc("WaitForSingleObject").Addr()
	a := windows.NewLazySystemDLL("advapi32.dll")
	cRegisterServiceCtrlHandlerExW = a.NewProc("RegisterServiceCtrlHandlerExW").Addr()
}

type ctlEvent struct {
	cmd       Cmd
	eventType uint32
	eventData uintptr
	context   uintptr
	errno     uint32
}

// service provides access to windows service api.
type service struct {
	name    string
	h       windows.Handle
	cWaits  *event
	goWaits *event
	c       chan ctlEvent
	handler Handler
}

func newService(name string, handler Handler) (*service, error) {
	var s service
	var err error
	s.name = name
	s.c = make(chan ctlEvent)
	s.handler = handler
	s.cWaits, err = newEvent()
	if err != nil {
		return nil, err
	}
	s.goWaits, err = newEvent()
	if err != nil {
		s.cWaits.Close()
		return nil, err
	}
	return &s, nil
}

func (s *service) close() error {
	s.cWaits.Close()
	s.goWaits.Close()
	return nil
}

type exitCode struct {
	isSvcSpecific bool
	errno         uint32
}

func (s *service) updateStatus(status *Status, ec *exitCode) error {
	if s.h == 0 {
		return errors.New("updateStatus with no service status handle")
	}
	var t windows.SERVICE_STATUS
	t.ServiceType = windows.SERVICE_WIN32_OWN_PROCESS
	t.CurrentState = uint32(status.State)
	if status.Accepts&AcceptStop != 0 {
		t.ControlsAccepted |= windows.SERVICE_ACCEPT_STOP
	}
	if status.Accepts&AcceptShutdown != 0 {
		t.ControlsAccepted |= windows.SERVICE_ACCEPT_SHUTDOWN
	}
	if status.Accepts&AcceptPauseAndContinue != 0 {
		t.ControlsAccepted |= windows.SERVICE_ACCEPT_PAUSE_CONTINUE
	}
	if status.Accepts&AcceptParamChange != 0 {
		t.ControlsAccepted |= windows.SERVICE_ACCEPT_PARAMCHANGE
	}
	if status.Accepts&AcceptNetBindChange != 0 {
		t.ControlsAccepted |= windows.SERVICE_ACCEPT_NETBINDCHANGE
	}
	if status.Accepts&AcceptHardwareProfileChange != 0 {
		t.ControlsAccepted |= windows.SERVICE_ACCEPT_HARDWAREPROFILECHANGE
	}
	if status.Accepts&AcceptPowerEvent != 0 {
		t.ControlsAccepted |= windows.SERVICE_ACCEPT_POWEREVENT
	}
	if status.Accepts&AcceptSessionChange != 0 {
		t.ControlsAccepted |= windows.SERVICE_ACCEPT_SESSIONCHANGE
	}
	if ec.errno == 0 {
		t.Win32ExitCode = windows.NO_ERROR
		t.ServiceSpecificExitCode = windows.NO_ERROR
	} else if ec.isSvcSpecific {
		t.Win32ExitCode = uint32(windows.ERROR_SERVICE_SPECIFIC_ERROR)
		t.ServiceSpecificExitCode = ec.errno
	} else {
		t.Win32ExitCode = ec.errno
		t.ServiceSpecificExitCode = windows.NO_ERROR
	}
	t.CheckPoint = status.CheckPoint
	t.WaitHint = status.WaitHint
	return windows.SetServiceStatus(s.h, &t)
}

const (
	sysErrSetServiceStatusFailed = uint32(syscall.APPLICATION_ERROR) + iota
	sysErrNewThreadInCallback
)

func (s *service) run() {
	s.goWaits.Wait()
	s.h = windows.Handle(ssHandle)
	argv := (*[100]*int16)(unsafe.Pointer(sArgv))[:sArgc]
	args := make([]string, len(argv))
	for i, a := range argv {
		args[i] = syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(a))[:])
	}

	cmdsToHandler := make(chan ChangeRequest)
	changesFromHandler := make(chan Status)
	exitFromHandler := make(chan exitCode)

	go func() {
		ss, errno := s.handler.Execute(args, cmdsToHandler, changesFromHandler)
		exitFromHandler <- exitCode{ss, errno}
	}()

	ec := exitCode{isSvcSpecific: true, errno: 0}
	outcr := ChangeRequest{
		CurrentStatus: Status{State: Stopped},
	}
	var outch chan ChangeRequest
	inch := s.c
loop:
	for {
		select {
		case r := <-inch:
			if r.errno != 0 {
				ec.errno = r.errno
				break loop
			}
			inch = nil
			outch = cmdsToHandler
			outcr.Cmd = r.cmd
			outcr.EventType = r.eventType
			outcr.EventData = r.eventData
			outcr.Context = r.context
		case outch <- outcr:
			inch = s.c
			outch = nil
		case c := <-changesFromHandler:
			err := s.updateStatus(&c, &ec)
			if err != nil {
				// best suitable error number
				ec.errno = sysErrSetServiceStatusFailed
				if err2, ok := err.(syscall.Errno); ok {
					ec.errno = uint32(err2)
				}
				break loop
			}
			outcr.CurrentStatus = c
		case ec = <-exitFromHandler:
			break loop
		}
	}

	s.updateStatus(&Status{State: Stopped}, &ec)
	s.cWaits.Set()
}

func newCallback(fn interface{}) (cb uintptr, err error) {
	defer func() {
		r := recover()
		if r == nil {
			return
		}
		cb = 0
		switch v := r.(type) {
		case string:
			err = errors.New(v)
		case error:
			err = v
		default:
			err = errors.New("unexpected panic in syscall.NewCallback")
		}
	}()
	return syscall.NewCallback(fn), nil
}

// BUG(brainman): There is no mechanism to run multiple services
// inside one single executable. Perhaps, it can be overcome by
// using RegisterServiceCtrlHandlerEx Windows api.

// Run executes service name by calling appropriate handler function.
func Run(name string, handler Handler) error {
	runtime.LockOSThread()

	tid := windows.GetCurrentThreadId()

	s, err := newService(name, handler)
	if err != nil {
		return err
	}

	ctlHandler := func(ctl, evtype, evdata, context uintptr) uintptr {
		e := ctlEvent{cmd: Cmd(ctl), eventType: uint32(evtype), eventData: evdata, context: context}
		// We assume that this callback function is running on
		// the same thread as Run. Nowhere in MS documentation
		// I could find statement to guarantee that. So putting
		// check here to verify, otherwise things will go bad
		// quickly, if ignored.
		i := windows.GetCurrentThreadId()
		if i != tid {
			e.errno = sysErrNewThreadInCallback
		}
		s.c <- e
		// Always return NO_ERROR (0) for now.
		return windows.NO_ERROR
	}

	var svcmain uintptr
	getServiceMain(&svcmain)
	t := []windows.SERVICE_TABLE_ENTRY{
		{ServiceName: syscall.StringToUTF16Ptr(s.name), ServiceProc: svcmain},
		{ServiceName: nil, ServiceProc: 0},
	}

	goWaitsH = uintptr(s.goWaits.h)
	cWaitsH = uintptr(s.cWaits.h)
	sName = t[0].ServiceName
	ctlHandlerExProc, err = newCallback(ctlHandler)
	if err != nil {
		return err
	}

	go s.run()

	err = windows.StartServiceCtrlDispatcher(&t[0])
	if err != nil {
		return err
	}
	return nil
}

// StatusHandle returns service status handle. It is safe to call this function
// from inside the Handler.Execute because then it is guaranteed to be set.
// This code will have to change once multiple services are possible per process.
func StatusHandle() windows.Handle {
	return windows.Handle(ssHandle)
}
