package main import ( "Win2Linux/pkg/windows" _ "embed" "fmt" "os" "os/exec" "regexp" "strings" "github.com/getlantern/systray" ) //go:generate go-winres make type ( Entry struct { Key string Attributes map[string]string } ) var ( r *regexp.Regexp = regexp.MustCompile(`-+`) ) //go:embed tray.ico var icon []byte type () func main() { systray.Run(onReady, onExit) } func onReady() { entries := list() systray.SetTitle("Win2Linux") systray.SetTooltip("Switch from Windows to Linux") systray.SetIcon(icon) for _, entry := range entries { fmt.Println(entry.Attributes) key := entry.Key uuid := entry.Attributes["identifier"] if desc, ok := entry.Attributes["description"]; ok { key = desc } mCustom := systray.AddMenuItem(key, "Switch to"+key) go func() { <-mCustom.ClickedCh if uuid == "{fwbootmgr}" { rebootToFirmware() return } reboot(uuid) }() } systray.AddSeparator() mQuit := systray.AddMenuItem("Quit", "Quit") go func() { <-mQuit.ClickedCh os.Exit(0) }() } func onExit() { // clean up here } func list() []Entry { cmd := exec.Command("bcdedit", "/enum", "firmware") out, err := cmd.Output() if err != nil { fatal(fmt.Sprintf("failed to run bcdedit: %s\n\nRun this program in administrator mode", err), 1) } return parse(string(out)) } func parse(out string) []Entry { lines := strings.Split(out, "\r\n") section := false lastLine := "" secName := "" a := make(map[string][]string) for _, l := range lines { if !section { if r.Match([]byte(l)) { secName = lastLine section = true } } else { if len(l) != 0 { a[secName] = append(a[secName], l) } else { section = false } } lastLine = l } var entries []Entry for k, sec := range a { entry := Entry{ Key: k, Attributes: make(map[string]string), } for _, l := range sec { l = strings.Join(strings.Fields(l), " ") val := strings.Split(l, " ") if len(val) != 2 { if len(val) > 2 { val[1] = strings.Join(val[1:], " ") } continue } entry.Attributes[val[0]] = val[1] } entries = append(entries, entry) } return entries } func reboot(uuid string) { out, err := exec.Command("bcdedit", "/Set", "{fwbootmgr}", "BootSequence", uuid, "/addFirst").Output() if err != nil { windows.MessageBox(windows.NULL, fmt.Sprintf("failed to execute bcdedit: %s", out), "Win2Linux", windows.MB_OK) return } out, err = exec.Command("shutdown", "/r", "/t", "0").Output() if err != nil { windows.MessageBox(windows.NULL, fmt.Sprintf("failed to restart the computer: %s", out), "Win2Linux", windows.MB_OK) } } func rebootToFirmware() { out, err := exec.Command("shutdown", "/r", "/fw", "/t", "0").Output() if err != nil { windows.MessageBox(windows.NULL, fmt.Sprintf("failed to restart the computer: %s", out), "Win2Linux", windows.MB_OK) } } func fatal(message string, exitCode int) { windows.MessageBox(windows.NULL, message, "Win2Linux", windows.MB_OK) os.Exit(exitCode) }