-
Notifications
You must be signed in to change notification settings - Fork 177
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[RtlGetVersion](https://learn.microsoft.com/en-us/windows/win32/devnotes/rtlgetversion) returns the windows OS version regardless of manifest, so that is preferred over [GetVersion](https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversion). Signed-off-by: Hamza El-Saawy <hamzaelsaawy@microsoft.com>
- Loading branch information
Showing
6 changed files
with
239 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package osversion | ||
|
||
// Windows Client and Server build numbers. | ||
// | ||
// See: | ||
// https://learn.microsoft.com/en-us/windows/release-health/release-information | ||
// https://learn.microsoft.com/en-us/windows/release-health/windows-server-release-info | ||
// https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information | ||
const ( | ||
// RS1 (version 1607, codename "Redstone 1") corresponds to Windows Server | ||
// 2016 (ltsc2016) and Windows 10 (Anniversary Update). | ||
RS1 BuildNumber = 14393 | ||
// V1607 (version 1607, codename "Redstone 1") is an alias for [RS1]. | ||
V1607 = RS1 | ||
// LTSC2016 (Windows Server 2016) is an alias for [RS1]. | ||
LTSC2016 = RS1 | ||
|
||
// RS2 (version 1703, codename "Redstone 2") was a client-only update, and | ||
// corresponds to Windows 10 (Creators Update). | ||
RS2 BuildNumber = 15063 | ||
// V1703 (version 1703, codename "Redstone 2") is an alias for [RS2]. | ||
V1703 = RS2 | ||
|
||
// RS3 (version 1709, codename "Redstone 3") corresponds to Windows Server | ||
// 1709 (Semi-Annual Channel (SAC)), and Windows 10 (Fall Creators Update). | ||
RS3 BuildNumber = 16299 | ||
// V1709 (version 1709, codename "Redstone 3") is an alias for [RS3]. | ||
V1709 = RS3 | ||
|
||
// RS4 (version 1803, codename "Redstone 4") corresponds to Windows Server | ||
// 1803 (Semi-Annual Channel (SAC)), and Windows 10 (April 2018 Update). | ||
RS4 BuildNumber = 17134 | ||
// V1803 (version 1803, codename "Redstone 4") is an alias for [RS4]. | ||
V1803 = RS4 | ||
|
||
// RS5 (version 1809, codename "Redstone 5") corresponds to Windows Server | ||
// 2019 (ltsc2019), and Windows 10 (October 2018 Update). | ||
RS5 BuildNumber = 17763 | ||
// V1809 (version 1809, codename "Redstone 5") is an alias for [RS5]. | ||
V1809 = RS5 | ||
// LTSC2019 (Windows Server 2019) is an alias for [RS5]. | ||
LTSC2019 = RS5 | ||
|
||
// V19H1 (version 1903, codename 19H1) corresponds to Windows Server 1903 (semi-annual | ||
// channel). | ||
V19H1 BuildNumber = 18362 | ||
// V1903 (version 1903) is an alias for [V19H1]. | ||
V1903 = V19H1 | ||
|
||
// V19H2 (version 1909, codename 19H2) corresponds to Windows Server 1909 (semi-annual | ||
// channel). | ||
V19H2 BuildNumber = 18363 | ||
// V1909 (version 1909) is an alias for [V19H2]. | ||
V1909 = V19H2 | ||
|
||
// V20H1 (version 2004, codename 20H1) corresponds to Windows Server 2004 (semi-annual | ||
// channel). | ||
V20H1 BuildNumber = 19041 | ||
// V2004 (version 2004) is an alias for [V20H1]. | ||
V2004 = V20H1 | ||
|
||
// V20H2 corresponds to Windows Server 20H2 (semi-annual channel). | ||
V20H2 BuildNumber = 19042 | ||
|
||
// V21H1 corresponds to Windows Server 21H1 (semi-annual channel). | ||
V21H1 BuildNumber = 19043 | ||
|
||
// V21H2Win10 corresponds to Windows 10 (November 2021 Update). | ||
V21H2Win10 BuildNumber = 19044 | ||
|
||
// V21H2Server corresponds to Windows Server 2022 (ltsc2022). | ||
V21H2Server BuildNumber = 20348 | ||
// LTSC2022 (Windows Server 2022) is an alias for [V21H2Server] | ||
LTSC2022 = V21H2Server | ||
|
||
// V21H2Win11 corresponds to Windows 11 (original release). | ||
V21H2Win11 BuildNumber = 22000 | ||
|
||
// V22H2Win10 corresponds to Windows 10 (2022 Update). | ||
V22H2Win10 BuildNumber = 19045 | ||
|
||
// V22H2Win11 corresponds to Windows 11 (2022 Update). | ||
V22H2Win11 BuildNumber = 22621 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package osversion | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
// Documentation and [OSVERSIONINFO] struct lists fields as DWORDs (uint32), but they | ||
// all packed into a uint32 in GetVersion, so safe to downcast to smallper types | ||
// | ||
//[OSVERSIONINFO]: https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoexw | ||
|
||
type ( | ||
MajorVersion uint8 | ||
MinorVersion uint8 | ||
BuildNumber uint16 | ||
) | ||
|
||
// Version is a wrapper for Windows version information | ||
// | ||
// https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversion | ||
type Version struct { | ||
Major MajorVersion | ||
Minor MinorVersion | ||
Build BuildNumber | ||
} | ||
|
||
func FromPackedVersion(v uint32) Version { | ||
return Version{ | ||
Major: MajorVersion(v & 0xFF), | ||
Minor: MinorVersion(v >> 8 & 0xFF), | ||
Build: BuildNumber(v >> 16), | ||
} | ||
} | ||
|
||
var _ fmt.Stringer = Version{} | ||
|
||
// String returns the OSVersion formatted as a string. | ||
func (v Version) String() string { | ||
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Build) | ||
} | ||
|
||
// Compare compares the current OSVersion to another. | ||
// The result will be 0 if they are equal, -1 the current version is lesser, and +1 otherwise. | ||
func (v Version) Compare(other Version) int { | ||
cmp := func(a, b int) int { | ||
if a > b { | ||
return 1 | ||
} else if a < b { | ||
return -1 | ||
} | ||
return 0 | ||
} | ||
|
||
if c := cmp(int(v.Major), int(other.Major)); c != 0 { | ||
return c | ||
} | ||
if c := cmp(int(v.Minor), int(other.Minor)); c != 0 { | ||
return c | ||
} | ||
return cmp(int(v.Build), int(other.Build)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package osversion | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
) | ||
|
||
func TestCompare(t *testing.T) { | ||
tt := []struct { | ||
a, b Version | ||
res int | ||
}{ | ||
{ | ||
Version{10, 0, RS5}, | ||
Version{10, 0, LTSC2022}, | ||
-1, | ||
}, | ||
{ | ||
Version{6, 1, 9801}, | ||
Version{10, 0, LTSC2022}, | ||
-1, | ||
}, | ||
{ | ||
Version{10, 0, RS5}, | ||
Version{10, 0, RS5}, | ||
0, | ||
}, | ||
{ | ||
Version{10, 0, LTSC2022}, | ||
Version{10, 0, RS5}, | ||
1, | ||
}, | ||
{ | ||
Version{10, 0, LTSC2022}, | ||
Version{6, 1, 9801}, | ||
1, | ||
}, | ||
} | ||
|
||
for _, tc := range tt { | ||
if res := tc.a.Compare(tc.b); res != tc.res { | ||
t.Errorf("(%s).Compare(%s): expected: %d, got: %d", tc.a, tc.b, res, tc.res) | ||
} | ||
} | ||
} | ||
|
||
func TestOSVersionString(t *testing.T) { | ||
v := FromPackedVersion(809042555) | ||
expected := "123.2.12345" | ||
actual := fmt.Sprintf("%s", v) //nolint: gosimple // testing that fmt works | ||
if actual != expected { | ||
t.Errorf("expected: %q, got: %q", expected, actual) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
//go:build windows | ||
|
||
package osversion | ||
|
||
import ( | ||
"sync" | ||
|
||
"golang.org/x/sys/windows" | ||
) | ||
|
||
var ( | ||
v Version | ||
once sync.Once | ||
) | ||
|
||
// Get returns the Windows operating system version. | ||
func Get() Version { | ||
once.Do(func() { | ||
vi := windows.RtlGetVersion() | ||
|
||
v.Major = MajorVersion(vi.MajorVersion) | ||
v.Minor = MinorVersion(vi.MinorVersion) | ||
v.Build = BuildNumber(vi.BuildNumber) | ||
}) | ||
return v | ||
} | ||
|
||
// Build returns the Windows build number. | ||
func Build() BuildNumber { | ||
return Get().Build | ||
} |