mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-08 09:07:44 +00:00
hostinfo: change Windows implementation to directly query version information using API and registry
We replace the cmd.exe invocation with RtlGetNtVersionNumbers for the first three fields. On Windows 10+, we query for the fourth field which is available via the registry. The fourth field is not really documented anywhere; Firefox has been querying it successfully since Windows 10 was released, so we can be pretty confident in its longevity at this point. Fixes https://github.com/tailscale/tailscale/issues/1478 Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This commit is contained in:
parent
1a629a4715
commit
7d8feb2784
@ -103,7 +103,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
|||||||
golang.org/x/sys/cpu from golang.org/x/crypto/blake2b+
|
golang.org/x/sys/cpu from golang.org/x/crypto/blake2b+
|
||||||
LD golang.org/x/sys/unix from tailscale.com/net/netns+
|
LD golang.org/x/sys/unix from tailscale.com/net/netns+
|
||||||
W golang.org/x/sys/windows from golang.org/x/sys/windows/registry+
|
W golang.org/x/sys/windows from golang.org/x/sys/windows/registry+
|
||||||
W golang.org/x/sys/windows/registry from golang.zx2c4.com/wireguard/windows/tunnel/winipcfg
|
W golang.org/x/sys/windows/registry from golang.zx2c4.com/wireguard/windows/tunnel/winipcfg+
|
||||||
golang.org/x/text/secure/bidirule from golang.org/x/net/idna
|
golang.org/x/text/secure/bidirule from golang.org/x/net/idna
|
||||||
golang.org/x/text/transform from golang.org/x/text/secure/bidirule+
|
golang.org/x/text/transform from golang.org/x/text/secure/bidirule+
|
||||||
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
|
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
|
||||||
|
@ -5,10 +5,11 @@
|
|||||||
package hostinfo
|
package hostinfo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
"golang.org/x/sys/windows/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -21,19 +22,37 @@ func osVersionWindows() string {
|
|||||||
if s, ok := winVerCache.Load().(string); ok {
|
if s, ok := winVerCache.Load().(string); ok {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
cmd := exec.Command("cmd", "/c", "ver")
|
major, minor, build := windows.RtlGetNtVersionNumbers()
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
s := fmt.Sprintf("%d.%d.%d", major, minor, build)
|
||||||
out, _ := cmd.Output() // "\nMicrosoft Windows [Version 10.0.19041.388]\n\n"
|
// Windows 11 still uses 10 as its major number internally
|
||||||
s := strings.TrimSpace(string(out))
|
if major == 10 {
|
||||||
s = strings.TrimPrefix(s, "Microsoft Windows [")
|
if ubr, err := getUBR(); err == nil {
|
||||||
s = strings.TrimSuffix(s, "]")
|
s += fmt.Sprintf(".%d", ubr)
|
||||||
|
}
|
||||||
// "Version 10.x.y.z", with "Version" localized. Keep only stuff after the space.
|
|
||||||
if sp := strings.Index(s, " "); sp != -1 {
|
|
||||||
s = s[sp+1:]
|
|
||||||
}
|
}
|
||||||
if s != "" {
|
if s != "" {
|
||||||
winVerCache.Store(s)
|
winVerCache.Store(s)
|
||||||
}
|
}
|
||||||
return s // "10.0.19041.388", ideally
|
return s // "10.0.19041.388", ideally
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getUBR obtains a fourth version field, the "Update Build Revision",
|
||||||
|
// from the registry. This field is only available beginning with Windows 10.
|
||||||
|
func getUBR() (uint32, error) {
|
||||||
|
key, err := registry.OpenKey(registry.LOCAL_MACHINE,
|
||||||
|
`SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE|registry.WOW64_64KEY)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer key.Close()
|
||||||
|
|
||||||
|
val, valType, err := key.GetIntegerValue("UBR")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if valType != registry.DWORD {
|
||||||
|
return 0, registry.ErrUnexpectedType
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint32(val), nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user