os: Use GetComputerNameEx to get Hostname on win32
The existing Hostname function uses the GetComputerName system
function in windows to determine the hostname. It has some downsides:
- The name is limited to 15 characters.
- The name returned is for NetBIOS, other OS's return a DNS name
This change adds to the internal/syscall/windows package a
GetComputerNameEx function, and related enum constants. They are used
instead of the syscall.ComputerName function to implement os.Hostname
on windows.
Fixes #9982
Change-Id: Idc8782785eb1eea37e64022bd201699ce9c4b39c
Reviewed-on: https://go-review.googlesource.com/5852
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Carlos Castillo <cookieo9@gmail.com>
Reviewed-by: Yasuhiro MATSUMOTO <mattn.jp@gmail.com>
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index c816ff7..a9b4988 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -1140,6 +1140,7 @@
"encoding/base64",
"syscall",
"time",
+ "internal/syscall/windows",
"os",
"reflect",
"fmt",
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index d186a17..7076f43 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -123,7 +123,7 @@
// Operating system access.
"syscall": {"L0", "unicode/utf16"},
"time": {"L0", "syscall"},
- "os": {"L1", "os", "syscall", "time"},
+ "os": {"L1", "os", "syscall", "time", "internal/syscall/windows"},
"path/filepath": {"L2", "os", "syscall"},
"io/ioutil": {"L2", "os", "path/filepath", "time"},
"os/exec": {"L2", "os", "path/filepath", "syscall"},
diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go
index 2541a83..49bfeea 100644
--- a/src/internal/syscall/windows/syscall_windows.go
+++ b/src/internal/syscall/windows/syscall_windows.go
@@ -4,9 +4,7 @@
package windows
-import (
- "syscall"
-)
+import "syscall"
//go:generate go run ../../../syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
@@ -97,3 +95,17 @@
)
//sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizeOfPointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
+
+//sys GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
+
+const (
+ ComputerNameNetBIOS = 0
+ ComputerNameDnsHostname = 1
+ ComputerNameDnsDomain = 2
+ ComputerNameDnsFullyQualified = 3
+ ComputerNamePhysicalNetBIOS = 4
+ ComputerNamePhysicalDnsHostname = 5
+ ComputerNamePhysicalDnsDomain = 6
+ ComputerNamePhysicalDnsFullyQualified = 7
+ ComputerNameMax = 8
+)
diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go
index 90e2034..50c7c51 100644
--- a/src/internal/syscall/windows/zsyscall_windows.go
+++ b/src/internal/syscall/windows/zsyscall_windows.go
@@ -5,10 +5,14 @@
import "unsafe"
import "syscall"
+var _ unsafe.Pointer
+
var (
modiphlpapi = syscall.NewLazyDLL("iphlpapi.dll")
+ modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
+ procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
)
func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizeOfPointer *uint32) (errcode error) {
@@ -18,3 +22,15 @@
}
return
}
+
+func GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nameformat), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
diff --git a/src/os/sys_windows.go b/src/os/sys_windows.go
index 92617de..9490ea6 100644
--- a/src/os/sys_windows.go
+++ b/src/os/sys_windows.go
@@ -4,12 +4,30 @@
package os
-import "syscall"
+import (
+ "internal/syscall/windows"
+ "syscall"
+)
func hostname() (name string, err error) {
- s, e := syscall.ComputerName()
- if e != nil {
- return "", NewSyscallError("ComputerName", e)
+ // Use PhysicalDnsHostname to uniquely identify host in a cluster
+ const format = windows.ComputerNamePhysicalDnsHostname
+
+ n := uint32(64)
+ for {
+ b := make([]uint16, n)
+ err := windows.GetComputerNameEx(format, &b[0], &n)
+ if err == nil {
+ return syscall.UTF16ToString(b[:n]), nil
+ }
+ if err != syscall.ERROR_MORE_DATA {
+ return "", NewSyscallError("ComputerNameEx", err)
+ }
+
+ // If we received a ERROR_MORE_DATA, but n doesn't get larger,
+ // something has gone wrong and we may be in an infinite loop
+ if n <= uint32(len(b)) {
+ return "", NewSyscallError("ComputerNameEx", err)
+ }
}
- return s, nil
}