aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/version
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-05-01 11:14:12 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-05-01 11:14:12 +0200
commitcff4e77bfe62606c19c205e02fd63b3777855392 (patch)
treeec8573073bf68253267ed741b60bf23b8e4554a3 /version
parentui: support clipboard copying for log items (diff)
downloadwireguard-windows-cff4e77bfe62606c19c205e02fd63b3777855392.tar.xz
wireguard-windows-cff4e77bfe62606c19c205e02fd63b3777855392.zip
version: dynamically get file version
Diffstat (limited to 'version')
-rw-r--r--version/debugging_linux.go (renamed from version/os_linux.go)14
-rw-r--r--version/mksyscall.go2
-rw-r--r--version/official_linux.go12
-rw-r--r--version/useragent.go (renamed from version/version.go)6
-rw-r--r--version/version_windows.go83
-rw-r--r--version/zsyscall_windows.go45
6 files changed, 136 insertions, 26 deletions
diff --git a/version/os_linux.go b/version/debugging_linux.go
index 7e5c4f1c..df5dbd2f 100644
--- a/version/os_linux.go
+++ b/version/debugging_linux.go
@@ -5,13 +5,11 @@
package version
-import (
- "bytes"
- "fmt"
- "golang.org/x/sys/unix"
-)
+// For testing the updater package from linux. Debug stuff only.
-// This isn't a Linux program, yes, but having the updater package work across platforms is quite helpful for testing.
+func IsOfficialPath(path string) bool {
+ return true
+}
func utsToStr(u [65]byte) string {
i := bytes.IndexByte(u[:], 0)
@@ -28,3 +26,7 @@ func OsName() string {
}
return fmt.Sprintf("%s %s %s", utsToStr(utsname.Sysname), utsToStr(utsname.Release), utsToStr(utsname.Version))
}
+
+func RunningVersion() string {
+ return "0.0.0.0"
+}
diff --git a/version/mksyscall.go b/version/mksyscall.go
index abd538e5..3c993928 100644
--- a/version/mksyscall.go
+++ b/version/mksyscall.go
@@ -5,4 +5,4 @@
package version
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go os_windows.go
+//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go os_windows.go version_windows.go
diff --git a/version/official_linux.go b/version/official_linux.go
deleted file mode 100644
index d3ca3349..00000000
--- a/version/official_linux.go
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-package version
-
-// For testing the updater package from linux. Debug stuff only.
-
-func IsOfficialPath(path string) bool {
- return true
-}
diff --git a/version/version.go b/version/useragent.go
index 951d2731..321bc0a6 100644
--- a/version/version.go
+++ b/version/useragent.go
@@ -5,16 +5,12 @@
package version
-// #include "../version.h"
-import "C"
import (
"fmt"
"golang.zx2c4.com/wireguard/device"
"runtime"
)
-const WireGuardWindowsVersion = C.WIREGUARD_WINDOWS_VERSION
-
func UserAgent() string {
- return fmt.Sprintf("WireGuard/%s (wireguard-go %s; %s; %s; %s)", WireGuardWindowsVersion, device.WireGuardGoVersion, OsName(), runtime.Version(), runtime.GOARCH)
+ return fmt.Sprintf("WireGuard/%s (wireguard-go %s; %s; %s; %s)", RunningVersion(), device.WireGuardGoVersion, OsName(), runtime.Version(), runtime.GOARCH)
}
diff --git a/version/version_windows.go b/version/version_windows.go
new file mode 100644
index 00000000..e567e7a0
--- /dev/null
+++ b/version/version_windows.go
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package version
+
+import (
+ "errors"
+ "fmt"
+ "golang.org/x/sys/windows"
+ "os"
+ "runtime"
+ "strings"
+ "unsafe"
+)
+
+//sys GetFileVersionInfoSize(filename *uint16, zero *uint32) (size uint32, err error) = version.GetFileVersionInfoSizeW
+//sys GetFileVersionInfo(filename *uint16, zero uint32, size uint32, block *byte) (err error) = version.GetFileVersionInfoW
+//sys VerQueryValue(block *byte, section *uint16, value **byte, size *uint32) (err error) = version.VerQueryValueW
+
+type vsFixedFileInfo struct {
+ Signature uint32
+ StrucVersion uint32
+ FileVersionMS uint32
+ FileVersionLS uint32
+ ProductVersionMS uint32
+ ProductVersionLS uint32
+ FileFlagsMask uint32
+ FileFlags uint32
+ FileOS uint32
+ FileType uint32
+ FileSubtype uint32
+ FileDateMS uint32
+ FileDateLS uint32
+}
+
+const vsFixedFileInfoSignature = 0xFEEF04BD
+
+var cachedVersion string
+
+func RunningVersion() string {
+ if len(cachedVersion) != 0 {
+ return cachedVersion
+ }
+ key16 := []uint16{'\\', 0x00}
+ self, err := os.Executable()
+ if err != nil {
+ panic(err)
+ }
+ self16, err := windows.UTF16PtrFromString(self)
+ if err != nil {
+ panic(err)
+ }
+ var zero uint32
+ size, err := GetFileVersionInfoSize(self16, &zero)
+ if err != nil {
+ panic(err)
+ }
+ buffer := make([]byte, size)
+ err = GetFileVersionInfo(self16, zero, size, &buffer[0])
+ if err != nil {
+ panic(err)
+ }
+ var fixedFileInfo *vsFixedFileInfo
+ err = VerQueryValue(&buffer[0], &key16[0], (**byte)(unsafe.Pointer(&fixedFileInfo)), &size)
+ if err != nil {
+ panic(err)
+ }
+ if uintptr(size) < unsafe.Sizeof(vsFixedFileInfo{}) || fixedFileInfo == nil || fixedFileInfo.Signature != vsFixedFileInfoSignature {
+ panic(errors.New("Incorrect return of VS_FIXEDFILEINFO"))
+ }
+ version := fmt.Sprintf("%d.%d.%d.%d", (fixedFileInfo.FileVersionMS>>16)&0xffff, (fixedFileInfo.FileVersionMS>>0)&0xffff, (fixedFileInfo.FileVersionLS>>16)&0xffff, (fixedFileInfo.FileVersionLS>>0)&0xffff)
+ runtime.KeepAlive(buffer) // The win32 API aliases it in fixedFileInfo, but Go doesn't know that.
+ if strings.HasSuffix(version, ".0") {
+ version = version[:len(version)-2]
+ }
+ if strings.HasSuffix(version, ".0") {
+ version = version[:len(version)-2]
+ }
+ cachedVersion = version
+ return version
+}
diff --git a/version/zsyscall_windows.go b/version/zsyscall_windows.go
index 9f11ce70..ef4e11d7 100644
--- a/version/zsyscall_windows.go
+++ b/version/zsyscall_windows.go
@@ -37,9 +37,13 @@ func errnoErr(e syscall.Errno) error {
}
var (
- modntdll = windows.NewLazySystemDLL("ntdll.dll")
+ modntdll = windows.NewLazySystemDLL("ntdll.dll")
+ modversion = windows.NewLazySystemDLL("version.dll")
- procRtlGetVersion = modntdll.NewProc("RtlGetVersion")
+ procRtlGetVersion = modntdll.NewProc("RtlGetVersion")
+ procGetFileVersionInfoSizeW = modversion.NewProc("GetFileVersionInfoSizeW")
+ procGetFileVersionInfoW = modversion.NewProc("GetFileVersionInfoW")
+ procVerQueryValueW = modversion.NewProc("VerQueryValueW")
)
func rtlGetVersion(versionInfo *osVersionInfo) (nterr uint32) {
@@ -47,3 +51,40 @@ func rtlGetVersion(versionInfo *osVersionInfo) (nterr uint32) {
nterr = uint32(r0)
return
}
+
+func GetFileVersionInfoSize(filename *uint16, zero *uint32) (size uint32, err error) {
+ r0, _, e1 := syscall.Syscall(procGetFileVersionInfoSizeW.Addr(), 2, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(zero)), 0)
+ size = uint32(r0)
+ if size == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func GetFileVersionInfo(filename *uint16, zero uint32, size uint32, block *byte) (err error) {
+ r1, _, e1 := syscall.Syscall6(procGetFileVersionInfoW.Addr(), 4, uintptr(unsafe.Pointer(filename)), uintptr(zero), uintptr(size), uintptr(unsafe.Pointer(block)), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func VerQueryValue(block *byte, section *uint16, value **byte, size *uint32) (err error) {
+ r1, _, e1 := syscall.Syscall6(procVerQueryValueW.Addr(), 4, uintptr(unsafe.Pointer(block)), uintptr(unsafe.Pointer(section)), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(size)), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}