commit 0f2a6c87bb7ea131d2d009da36496bda960fa690 Author: Aurélie DELHAIE Date: Wed Jul 30 20:25:07 2025 +0200 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..15014e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.syso +*.exe \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..a71d2fd --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +go build -ldflags -H=windowsgui \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..ade8439 --- /dev/null +++ b/go.mod @@ -0,0 +1,17 @@ +module Win2Linux + +go 1.24 + +require github.com/getlantern/systray v1.2.2 + +require ( + github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 // indirect + github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 // indirect + github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 // indirect + github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 // indirect + github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 // indirect + github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f // indirect + github.com/go-stack/stack v1.8.0 // indirect + github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect + golang.org/x/sys v0.1.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..4c056eb --- /dev/null +++ b/go.sum @@ -0,0 +1,32 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4= +github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY= +github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 h1:6uJ+sZ/e03gkbqZ0kUG6mfKoqDb4XMAzMIwlajq19So= +github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A= +github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 h1:guBYzEaLz0Vfc/jv0czrr2z7qyzTOGC9hiQ0VC+hKjk= +github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7/go.mod h1:zx/1xUUeYPy3Pcmet8OSXLbF47l+3y6hIPpyLWoR9oc= +github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 h1:micT5vkcr9tOVk1FiH8SWKID8ultN44Z+yzd2y/Vyb0= +github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7/go.mod h1:dD3CgOrwlzca8ed61CsZouQS5h5jIzkK9ZWrTcf0s+o= +github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 h1:XYzSdCbkzOC0FDNrgJqGRo8PCMFOBFL9py72DRs7bmc= +github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA= +github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f h1:wrYrQttPS8FHIRSlsrcuKazukx/xqO/PpLZzZXsF+EA= +github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA= +github.com/getlantern/systray v1.2.2 h1:dCEHtfmvkJG7HZ8lS/sLklTH4RKUcIsKrAD9sThoEBE= +github.com/getlantern/systray v1.2.2/go.mod h1:pXFOI1wwqwYXEhLPm9ZGjS2u/vVELeIgNMY5HvhHhcE= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ= +github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= +github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= +github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E= diff --git a/main.go b/main.go new file mode 100644 index 0000000..556541f --- /dev/null +++ b/main.go @@ -0,0 +1,127 @@ +package main + +import ( + _ "embed" + "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 { + key := entry.Key + if desc, ok := entry.Attributes["description"]; ok { + key = desc + } + mCustom := systray.AddMenuItem(key, "Switch to"+key) + go func() { + <-mCustom.ClickedCh + reboot(entry.Attributes["identifier"]) + }() + + } + 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 { + panic(err) + } + 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.SplitN(l, " ", 1) + if len(val) != 2 { + continue + } + entry.Attributes[val[0]] = val[1] + } + entries = append(entries, entry) + } + return entries +} + +func reboot(uuid string) { + if err := exec.Command("bcdedit", "/Set", "{fwbootmgr}", "BootSequence", uuid, "/addFirst").Run(); err != nil { + panic(err) + } + + if err := exec.Command("shutdown", "/r", "/t", "2").Run(); err != nil { + panic(err) + } + + os.Exit(0) +} diff --git a/tray.ico b/tray.ico new file mode 100644 index 0000000..873cd41 Binary files /dev/null and b/tray.ico differ diff --git a/winres/icon.png b/winres/icon.png new file mode 100644 index 0000000..f775aaa Binary files /dev/null and b/winres/icon.png differ diff --git a/winres/icon16.png b/winres/icon16.png new file mode 100644 index 0000000..f2cc9de Binary files /dev/null and b/winres/icon16.png differ diff --git a/winres/winres.json b/winres/winres.json new file mode 100644 index 0000000..8043b9f --- /dev/null +++ b/winres/winres.json @@ -0,0 +1,53 @@ +{ + "RT_GROUP_ICON": { + "APP": { + "0000": [ + "icon.png", + "icon16.png" + ] + } + }, + "RT_MANIFEST": { + "#1": { + "0409": { + "identity": { + "name": "", + "version": "" + }, + "description": "", + "minimum-os": "win10", + "execution-level": "requireAdministrator", + "ui-access": false, + "auto-elevate": false, + "dpi-awareness": "system", + "disable-theming": false, + "disable-window-filtering": false, + "high-resolution-scrolling-aware": false, + "ultra-high-resolution-scrolling-aware": false, + "long-path-aware": false, + "printer-driver-isolation": false, + "gdi-scaling": false, + "segment-heap": false, + "use-common-controls-v6": false + } + } + }, + "RT_VERSION": { + "#1": { + "0000": { + "fixed": { + "file_version": "0.0.1.0", + "product_version": "0.0.1.0" + }, + "info": { + "0409": { + "Comments": "Switch from Windows to Linux", + "CompanyName": "Aurelie Delhaie", + "ProductName": "Win2Linux", + "ProductVersion": "0.0.1.0" + } + } + } + } + } +} \ No newline at end of file