mirror of
https://github.com/golang/sys.git
synced 2026-02-08 11:46:04 +03:00
windows: allow retrieving true version with RtlGetNtVersionNumbers
While RtlGetVersion was added so that users can get the Windows version that isn't affected by manifesting, RtlGetVersion is still stubbed out by the application compatibility layer (aclayers.dll and apphelp.dll) for certain processes, such as msiexec.exe, rendering these functions useless for actually determining the underlying operating system. This matters in the case of msiexec.exe using a custom action DLL to install a kernel driver, which of course is version specific. This is also useful, it turns out, for the C runtime library, in which Microsoft uses this function too. It's existed as a stable interface since Windows XP, has Wine support, and is used in a decent amount of software. Change-Id: If391e43bc6d798eff6803d5a7aa6a179f2b31d88 Reviewed-on: https://go-review.googlesource.com/c/sys/+/188119 Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
@@ -296,6 +296,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid
|
||||
//sys CoTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree
|
||||
//sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion
|
||||
//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers
|
||||
|
||||
// syscall interface implementation for other packages
|
||||
|
||||
@@ -1306,8 +1307,8 @@ func (t Token) KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, e
|
||||
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.
|
||||
// RtlGetVersion returns the version of the underlying operating system, ignoring
|
||||
// manifest semantics but is affected by the application compatibility layer.
|
||||
func RtlGetVersion() *OsVersionInfoEx {
|
||||
info := &OsVersionInfoEx{}
|
||||
info.osVersionInfoSize = uint32(unsafe.Sizeof(*info))
|
||||
@@ -1318,3 +1319,11 @@ func RtlGetVersion() *OsVersionInfoEx {
|
||||
_ = rtlGetVersion(info)
|
||||
return info
|
||||
}
|
||||
|
||||
// RtlGetNtVersionNumbers returns the version of the underlying operating system,
|
||||
// ignoring manifest semantics and the application compatibility layer.
|
||||
func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) {
|
||||
rtlGetNtVersionNumbers(&majorVersion, &minorVersion, &buildNumber)
|
||||
buildNumber &= 0xffff
|
||||
return
|
||||
}
|
||||
|
||||
@@ -219,7 +219,10 @@ func TestKnownFolderPath(t *testing.T) {
|
||||
|
||||
func TestRtlGetVersion(t *testing.T) {
|
||||
version := windows.RtlGetVersion()
|
||||
if version.MajorVersion < 6 {
|
||||
t.Fatalf("MajorVersion = %d; want >= 6", version.MajorVersion)
|
||||
major, minor, build := windows.RtlGetNtVersionNumbers()
|
||||
// Go is not explictly added to the application compatibility database, so
|
||||
// these two functions should return the same thing.
|
||||
if version.MajorVersion != major || version.MinorVersion != minor || version.BuildNumber != build {
|
||||
t.Fatalf("%d.%d.%d != %d.%d.%d", version.MajorVersion, version.MinorVersion, version.BuildNumber, major, minor, build)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,6 +234,7 @@ var (
|
||||
procCoCreateGuid = modole32.NewProc("CoCreateGuid")
|
||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||
procRtlGetVersion = modntdll.NewProc("RtlGetVersion")
|
||||
procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers")
|
||||
procWSAStartup = modws2_32.NewProc("WSAStartup")
|
||||
procWSACleanup = modws2_32.NewProc("WSACleanup")
|
||||
procWSAIoctl = modws2_32.NewProc("WSAIoctl")
|
||||
@@ -2530,6 +2531,11 @@ func rtlGetVersion(info *OsVersionInfoEx) (ret error) {
|
||||
return
|
||||
}
|
||||
|
||||
func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) {
|
||||
syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(majorVersion)), uintptr(unsafe.Pointer(minorVersion)), uintptr(unsafe.Pointer(buildNumber)))
|
||||
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