feat: splitting platforms and maybe fixing shortcut installations as well as admin privileges
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
//go:build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
shell32 = syscall.NewLazyDLL("shell32.dll")
|
||||
shellExecuteExW = shell32.NewProc("ShellExecuteExW")
|
||||
)
|
||||
|
||||
const (
|
||||
seeMaskNocloseprocess = 0x00000040
|
||||
)
|
||||
|
||||
type shellExecuteInfo struct {
|
||||
cbSize uint32
|
||||
fMask uint32
|
||||
hwnd uintptr
|
||||
lpVerb *uint16
|
||||
lpFile *uint16
|
||||
lpParameters *uint16
|
||||
lpDirectory *uint16
|
||||
nShow int32
|
||||
hInstApp uintptr
|
||||
lpIDList uintptr
|
||||
lpClass *uint16
|
||||
hkeyClass uintptr
|
||||
dwHotKey uint32
|
||||
hIcon uintptr
|
||||
hProcess uintptr
|
||||
}
|
||||
|
||||
func getInstallDir() (string, error) {
|
||||
programFiles := os.Getenv("ProgramFiles")
|
||||
|
||||
if programFiles == "" {
|
||||
return "", errors.New("ProgramFiles ist nicht gesetzt")
|
||||
}
|
||||
|
||||
return filepath.Join(programFiles, "logofclient"), nil
|
||||
}
|
||||
|
||||
func platformRunPrivileged(config Config, action string) error {
|
||||
if isWindowsAdmin() {
|
||||
return runAction(config, action)
|
||||
}
|
||||
|
||||
return runElevated(action)
|
||||
}
|
||||
|
||||
func isWindowsAdmin() bool {
|
||||
// Ein einfacher und robuster Test:
|
||||
// Versuch, in das Windows-Systemverzeichnis zu schreiben.
|
||||
//
|
||||
// Da wir dort natürlich nichts verändern wollen, verwenden wir
|
||||
// stattdessen "net session". Der Befehl funktioniert nur mit
|
||||
// Administratorrechten.
|
||||
|
||||
cmd := exec.Command("net", "session")
|
||||
cmd.Stdout = nil
|
||||
cmd.Stderr = nil
|
||||
|
||||
return cmd.Run() == nil
|
||||
}
|
||||
|
||||
func runElevated(action string) error {
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Pfad des Installers konnte nicht ermittelt werden: %w", err)
|
||||
}
|
||||
|
||||
verb, err := syscall.UTF16PtrFromString("runas")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, err := syscall.UTF16PtrFromString(exe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parameters, err := syscall.UTF16PtrFromString(action)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info := shellExecuteInfo{
|
||||
cbSize: uint32(unsafe.Sizeof(shellExecuteInfo{})),
|
||||
fMask: seeMaskNocloseprocess,
|
||||
lpVerb: verb,
|
||||
lpFile: file,
|
||||
lpParameters: parameters,
|
||||
nShow: 1, // SW_SHOWNORMAL
|
||||
}
|
||||
|
||||
ret, _, callErr := shellExecuteExW.Call(uintptr(unsafe.Pointer(&info)))
|
||||
|
||||
if ret == 0 {
|
||||
// ERROR_CANCELLED = 1223:
|
||||
// Benutzer hat den UAC-Dialog abgebrochen.
|
||||
if errno, ok := callErr.(syscall.Errno); ok && errno == 1223 {
|
||||
fmt.Println("Administratorrechte wurden nicht erteilt.")
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("Administratorrechte konnten nicht angefordert werden: %w", callErr)
|
||||
}
|
||||
|
||||
// Auf die erhöhte Instanz warten.
|
||||
if info.hProcess != 0 {
|
||||
handle := syscall.Handle(info.hProcess)
|
||||
defer syscall.CloseHandle(handle)
|
||||
|
||||
_, err := syscall.WaitForSingleObject(handle, syscall.INFINITE)
|
||||
if err != nil {
|
||||
return fmt.Errorf("auf erhöhte Instanz konnte nicht gewartet werden: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user