// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause

// Windows-specific stuff that can't go in clientupdate.go because it needs
// x/sys/windows.

package clientupdate

import (
	"os/exec"
	"os/user"
	"path/filepath"
	"syscall"

	"golang.org/x/sys/windows"
	"tailscale.com/util/winutil"
	"tailscale.com/util/winutil/authenticode"
)

func init() {
	markTempFileFunc = markTempFileWindows
	verifyAuthenticode = verifyTailscale
	launchTailscaleAsWinGUIUser = launchTailscaleAsGUIUser
}

func markTempFileWindows(name string) error {
	name16 := windows.StringToUTF16Ptr(name)
	return windows.MoveFileEx(name16, nil, windows.MOVEFILE_DELAY_UNTIL_REBOOT)
}

const certSubjectTailscale = "Tailscale Inc."

func verifyTailscale(path string) error {
	return authenticode.Verify(path, certSubjectTailscale)
}

func launchTailscaleAsGUIUser(exePath string) error {
	exePath = filepath.Join(filepath.Dir(exePath), "tailscale-ipn.exe")

	var token windows.Token
	if u, err := user.Current(); err == nil && u.Name == "SYSTEM" {
		sessionID := winutil.WTSGetActiveConsoleSessionId()
		if sessionID != 0xFFFFFFFF {
			if err := windows.WTSQueryUserToken(sessionID, &token); err != nil {
				return err
			}
			defer token.Close()
		}
	}

	cmd := exec.Command(exePath)
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Token:      syscall.Token(token),
		HideWindow: true,
	}
	return cmd.Start()
}