From b1c7a7da21696482aef248223fde11a7f1d4b826 Mon Sep 17 00:00:00 2001 From: John Howard Date: Fri, 8 May 2015 14:59:38 -0700 Subject: [PATCH] Windows: Impl pkg\parsers kernel+os Signed-off-by: John Howard --- parsers/kernel/kernel.go | 2 + parsers/kernel/kernel_windows.go | 65 +++++++++++++++++++ ...tingsystem.go => operatingsystem_linux.go} | 0 .../operatingsystem_windows.go | 47 ++++++++++++++ parsers/parsers.go | 8 ++- 5 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 parsers/kernel/kernel_windows.go rename parsers/operatingsystem/{operatingsystem.go => operatingsystem_linux.go} (100%) create mode 100644 parsers/operatingsystem/operatingsystem_windows.go diff --git a/parsers/kernel/kernel.go b/parsers/kernel/kernel.go index 70d0900..5f79306 100644 --- a/parsers/kernel/kernel.go +++ b/parsers/kernel/kernel.go @@ -1,3 +1,5 @@ +// +build !windows + package kernel import ( diff --git a/parsers/kernel/kernel_windows.go b/parsers/kernel/kernel_windows.go new file mode 100644 index 0000000..399d63e --- /dev/null +++ b/parsers/kernel/kernel_windows.go @@ -0,0 +1,65 @@ +package kernel + +import ( + "fmt" + "syscall" + "unsafe" +) + +type KernelVersionInfo struct { + kvi string + major int + minor int + build int +} + +func (k *KernelVersionInfo) String() string { + return fmt.Sprintf("%d.%d %d (%s)", k.major, k.minor, k.build, k.kvi) +} + +func GetKernelVersion() (*KernelVersionInfo, error) { + + var ( + h syscall.Handle + dwVersion uint32 + err error + ) + + KVI := &KernelVersionInfo{"Unknown", 0, 0, 0} + + if err = syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, + syscall.StringToUTF16Ptr(`SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\`), + 0, + syscall.KEY_READ, + &h); err != nil { + return KVI, err + } + defer syscall.RegCloseKey(h) + + var buf [1 << 10]uint16 + var typ uint32 + n := uint32(len(buf) * 2) // api expects array of bytes, not uint16 + + if err = syscall.RegQueryValueEx(h, + syscall.StringToUTF16Ptr("BuildLabEx"), + nil, + &typ, + (*byte)(unsafe.Pointer(&buf[0])), + &n); err != nil { + return KVI, err + } + + KVI.kvi = syscall.UTF16ToString(buf[:]) + + // Important - docker.exe MUST be manifested for this API to return + // the correct information. + if dwVersion, err = syscall.GetVersion(); err != nil { + return KVI, err + } + + KVI.major = int(dwVersion & 0xFF) + KVI.minor = int((dwVersion & 0XFF00) >> 8) + KVI.build = int((dwVersion & 0xFFFF0000) >> 16) + + return KVI, nil +} diff --git a/parsers/operatingsystem/operatingsystem.go b/parsers/operatingsystem/operatingsystem_linux.go similarity index 100% rename from parsers/operatingsystem/operatingsystem.go rename to parsers/operatingsystem/operatingsystem_linux.go diff --git a/parsers/operatingsystem/operatingsystem_windows.go b/parsers/operatingsystem/operatingsystem_windows.go new file mode 100644 index 0000000..c843c6f --- /dev/null +++ b/parsers/operatingsystem/operatingsystem_windows.go @@ -0,0 +1,47 @@ +package operatingsystem + +import ( + "syscall" + "unsafe" +) + +// See https://code.google.com/p/go/source/browse/src/pkg/mime/type_windows.go?r=d14520ac25bf6940785aabb71f5be453a286f58c +// for a similar sample + +func GetOperatingSystem() (string, error) { + + var h syscall.Handle + + // Default return value + ret := "Unknown Operating System" + + if err := syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, + syscall.StringToUTF16Ptr(`SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\`), + 0, + syscall.KEY_READ, + &h); err != nil { + return ret, err + } + defer syscall.RegCloseKey(h) + + var buf [1 << 10]uint16 + var typ uint32 + n := uint32(len(buf) * 2) // api expects array of bytes, not uint16 + + if err := syscall.RegQueryValueEx(h, + syscall.StringToUTF16Ptr("ProductName"), + nil, + &typ, + (*byte)(unsafe.Pointer(&buf[0])), + &n); err != nil { + return ret, err + } + ret = syscall.UTF16ToString(buf[:]) + + return ret, nil +} + +// No-op on Windows +func IsContainerized() (bool, error) { + return false, nil +} diff --git a/parsers/parsers.go b/parsers/parsers.go index 59e294d..8dc4a1d 100644 --- a/parsers/parsers.go +++ b/parsers/parsers.go @@ -2,6 +2,7 @@ package parsers import ( "fmt" + "runtime" "strconv" "strings" ) @@ -10,7 +11,12 @@ import ( func ParseHost(defaultTCPAddr, defaultUnixAddr, addr string) (string, error) { addr = strings.TrimSpace(addr) if addr == "" { - addr = fmt.Sprintf("unix://%s", defaultUnixAddr) + if runtime.GOOS != "windows" { + addr = fmt.Sprintf("unix://%s", defaultUnixAddr) + } else { + // Note - defaultTCPAddr already includes tcp:// prefix + addr = fmt.Sprintf("%s", defaultTCPAddr) + } } addrParts := strings.Split(addr, "://") if len(addrParts) == 1 {