fix: admin-version in second window on windoof (incl build)
This commit is contained in:
Binary file not shown.
+91
-26
@@ -6,8 +6,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -15,10 +15,23 @@ import (
|
||||
var (
|
||||
shell32 = syscall.NewLazyDLL("shell32.dll")
|
||||
shellExecuteExW = shell32.NewProc("ShellExecuteExW")
|
||||
|
||||
advapi32 = syscall.NewLazyDLL("advapi32.dll")
|
||||
openProcessToken = advapi32.NewProc("OpenProcessToken")
|
||||
getTokenInformation = advapi32.NewProc("GetTokenInformation")
|
||||
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
closeHandle = kernel32.NewProc("CloseHandle")
|
||||
waitForSingleObject = kernel32.NewProc("WaitForSingleObject")
|
||||
)
|
||||
|
||||
const (
|
||||
seeMaskNocloseprocess = 0x00000040
|
||||
tokenQuery = 0x0008
|
||||
tokenElevationClass = 20
|
||||
seeMaskNoCloseProcess = 0x00000040
|
||||
swShow = 1
|
||||
infinite = 0xFFFFFFFF
|
||||
errorCancelled = 1223
|
||||
)
|
||||
|
||||
type shellExecuteInfo struct {
|
||||
@@ -39,6 +52,10 @@ type shellExecuteInfo struct {
|
||||
hProcess uintptr
|
||||
}
|
||||
|
||||
type tokenElevationData struct {
|
||||
TokenIsElevated uint32
|
||||
}
|
||||
|
||||
func getInstallDir() (string, error) {
|
||||
programFiles := os.Getenv("ProgramFiles")
|
||||
|
||||
@@ -50,32 +67,70 @@ func getInstallDir() (string, error) {
|
||||
}
|
||||
|
||||
func platformRunPrivileged(config Config, action string) error {
|
||||
if isWindowsAdmin() {
|
||||
if isWindowsElevated() {
|
||||
return runAction(config, action)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("Für diese Aktion werden Administratorrechte benötigt.")
|
||||
fmt.Print("Jetzt Administratorrechte anfordern? [J/n]: ")
|
||||
|
||||
var answer string
|
||||
if _, err := fmt.Scanln(&answer); err != nil {
|
||||
// Enter ohne Eingabe = Ja
|
||||
answer = ""
|
||||
}
|
||||
|
||||
answer = strings.ToLower(strings.TrimSpace(answer))
|
||||
|
||||
if answer != "" && answer != "j" && answer != "ja" {
|
||||
fmt.Println("Abgebrochen.")
|
||||
return nil
|
||||
}
|
||||
|
||||
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.
|
||||
func isWindowsElevated() bool {
|
||||
var token uintptr
|
||||
|
||||
cmd := exec.Command("net", "session")
|
||||
cmd.Stdout = nil
|
||||
cmd.Stderr = nil
|
||||
ret, _, _ := openProcessToken.Call(
|
||||
uintptr(^uint(0)>>1),
|
||||
tokenQuery,
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
)
|
||||
|
||||
return cmd.Run() == nil
|
||||
if ret == 0 || token == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
defer closeHandle.Call(token)
|
||||
|
||||
var elevation tokenElevationData
|
||||
var returned uint32
|
||||
|
||||
ret, _, _ = getTokenInformation.Call(
|
||||
token,
|
||||
tokenElevationClass,
|
||||
uintptr(unsafe.Pointer(&elevation)),
|
||||
uintptr(unsafe.Sizeof(elevation)),
|
||||
uintptr(unsafe.Pointer(&returned)),
|
||||
)
|
||||
|
||||
if ret == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return elevation.TokenIsElevated != 0
|
||||
}
|
||||
|
||||
func runElevated(action string) error {
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Pfad des Installers konnte nicht ermittelt werden: %w", err)
|
||||
return fmt.Errorf(
|
||||
"Pfad des Installers konnte nicht ermittelt werden: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
verb, err := syscall.UTF16PtrFromString("runas")
|
||||
@@ -95,34 +150,44 @@ func runElevated(action string) error {
|
||||
|
||||
info := shellExecuteInfo{
|
||||
cbSize: uint32(unsafe.Sizeof(shellExecuteInfo{})),
|
||||
fMask: seeMaskNocloseprocess,
|
||||
fMask: seeMaskNoCloseProcess,
|
||||
lpVerb: verb,
|
||||
lpFile: file,
|
||||
lpParameters: parameters,
|
||||
nShow: 1, // SW_SHOWNORMAL
|
||||
nShow: swShow,
|
||||
}
|
||||
|
||||
ret, _, callErr := shellExecuteExW.Call(uintptr(unsafe.Pointer(&info)))
|
||||
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 {
|
||||
if errno, ok := callErr.(syscall.Errno); ok &&
|
||||
errno == errorCancelled {
|
||||
fmt.Println("Administratorrechte wurden nicht erteilt.")
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("Administratorrechte konnten nicht angefordert werden: %w", callErr)
|
||||
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)
|
||||
ret, _, err := waitForSingleObject.Call(
|
||||
uintptr(handle),
|
||||
infinite,
|
||||
)
|
||||
|
||||
if ret == 0xFFFFFFFF {
|
||||
return fmt.Errorf(
|
||||
"auf erhöhte Instanz konnte nicht gewartet werden: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ import (
|
||||
func platformInstallIntegration(installDir string) error {
|
||||
binaryPath := filepath.Join(
|
||||
installDir,
|
||||
"Logof Client",
|
||||
"Logofclient",
|
||||
)
|
||||
|
||||
linkPath := "/usr/local/bin/logofclient"
|
||||
@@ -56,7 +56,7 @@ func platformInstallIntegration(installDir string) error {
|
||||
|
||||
desktopEntry := fmt.Sprintf(`[Desktop Entry]
|
||||
Name=Logof Client
|
||||
Comment=Logof Client
|
||||
Comment=Logofclient
|
||||
Exec=%s
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
||||
+3
-3
@@ -26,7 +26,7 @@ func platformInstallIntegration(installDir string) error {
|
||||
|
||||
shortcutPath := filepath.Join(
|
||||
startMenuDir,
|
||||
"Logof Client.lnk",
|
||||
"Logofclient.lnk",
|
||||
)
|
||||
|
||||
if err := os.MkdirAll(startMenuDir, 0755); err != nil {
|
||||
@@ -58,7 +58,7 @@ func platformRemoveIntegration() error {
|
||||
|
||||
shortcutPath := filepath.Join(
|
||||
startMenuDir,
|
||||
"Logof Client.lnk",
|
||||
"Logofclient.lnk",
|
||||
)
|
||||
|
||||
if err := os.Remove(shortcutPath); err != nil && !os.IsNotExist(err) {
|
||||
@@ -117,7 +117,7 @@ func platformCreateShortcut(
|
||||
}
|
||||
|
||||
// Beschreibung.
|
||||
if _, err := oleutil.PutProperty(shortcut, "Description", "Logof Client"); err != nil {
|
||||
if _, err := oleutil.PutProperty(shortcut, "Description", "Logofclient"); err != nil {
|
||||
return fmt.Errorf("Description konnte nicht gesetzt werden: %w", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user