mirror of
https://github.com/golang/sys.git
synced 2026-02-09 04:06:04 +03:00
windows: allow determining real version number
Other functions, like GetVersion(), will lie about the OS version depending on various win32 and manifest compatibility shims in place. Calling RtlGetVersion is the proper way to retrieve the true OS version. Change-Id: I2bd6d097dd763df51617cd825dc0ad300abf6212 Reviewed-on: https://go-review.googlesource.com/c/sys/+/182718 Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matt Layher <mdlayher@gmail.com> Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
@@ -295,6 +295,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) = ole32.StringFromGUID2
|
||||
//sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid
|
||||
//sys coTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree
|
||||
//sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion
|
||||
|
||||
// syscall interface implementation for other packages
|
||||
|
||||
@@ -1304,3 +1305,16 @@ func (t Token) KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, e
|
||||
defer coTaskMemFree(unsafe.Pointer(p))
|
||||
return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:]), nil
|
||||
}
|
||||
|
||||
// RtlGetVersion returns the true version of the underlying operating system, ignoring
|
||||
// any manifesting or compatibility layers on top of the win32 layer.
|
||||
func RtlGetVersion() *OsVersionInfoEx {
|
||||
info := &OsVersionInfoEx{}
|
||||
info.osVersionInfoSize = uint32(unsafe.Sizeof(*info))
|
||||
// According to documentation, this function always succeeds.
|
||||
// The function doesn't even check the validity of the
|
||||
// osVersionInfoSize member. Disassembling ntdll.dll indicates
|
||||
// that the documentation is indeed correct about that.
|
||||
_ = rtlGetVersion(info)
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -216,3 +216,10 @@ func TestKnownFolderPath(t *testing.T) {
|
||||
t.Fatalf("Path = %q; want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRtlGetVersion(t *testing.T) {
|
||||
version := windows.RtlGetVersion()
|
||||
if version.MajorVersion < 6 {
|
||||
t.Fatalf("MajorVersion = %d; want >= 6", version.MajorVersion)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1649,3 +1649,17 @@ const (
|
||||
KF_FLAG_SIMPLE_IDLIST = 0x00000100
|
||||
KF_FLAG_ALIAS_ONLY = 0x80000000
|
||||
)
|
||||
|
||||
type OsVersionInfoEx struct {
|
||||
osVersionInfoSize uint32
|
||||
MajorVersion uint32
|
||||
MinorVersion uint32
|
||||
BuildNumber uint32
|
||||
PlatformId uint32
|
||||
CsdVersion [128]uint16
|
||||
ServicePackMajor uint16
|
||||
ServicePackMinor uint16
|
||||
SuiteMask uint16
|
||||
ProductType byte
|
||||
_ byte
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ var (
|
||||
modcrypt32 = NewLazySystemDLL("crypt32.dll")
|
||||
moduser32 = NewLazySystemDLL("user32.dll")
|
||||
modole32 = NewLazySystemDLL("ole32.dll")
|
||||
modntdll = NewLazySystemDLL("ntdll.dll")
|
||||
modws2_32 = NewLazySystemDLL("ws2_32.dll")
|
||||
moddnsapi = NewLazySystemDLL("dnsapi.dll")
|
||||
modiphlpapi = NewLazySystemDLL("iphlpapi.dll")
|
||||
@@ -232,6 +233,7 @@ var (
|
||||
procStringFromGUID2 = modole32.NewProc("StringFromGUID2")
|
||||
procCoCreateGuid = modole32.NewProc("CoCreateGuid")
|
||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||
procRtlGetVersion = modntdll.NewProc("RtlGetVersion")
|
||||
procWSAStartup = modws2_32.NewProc("WSAStartup")
|
||||
procWSACleanup = modws2_32.NewProc("WSACleanup")
|
||||
procWSAIoctl = modws2_32.NewProc("WSAIoctl")
|
||||
@@ -2520,6 +2522,14 @@ func coTaskMemFree(address unsafe.Pointer) {
|
||||
return
|
||||
}
|
||||
|
||||
func rtlGetVersion(info *OsVersionInfoEx) (ret error) {
|
||||
r0, _, _ := syscall.Syscall(procRtlGetVersion.Addr(), 1, uintptr(unsafe.Pointer(info)), 0, 0)
|
||||
if r0 != 0 {
|
||||
ret = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
|
||||
r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
|
||||
if r0 != 0 {
|
||||
|
||||
Reference in New Issue
Block a user