diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index 923644b64..f9ba6cf40 100644 --- a/lib/std/os/windows/bits.zig +++ b/lib/std/os/windows/bits.zig @@ -1493,3 +1493,16 @@ pub const PSAPI_WS_WATCH_INFORMATION_EX = extern struct { Flags: ULONG_PTR, }; pub const PPSAPI_WS_WATCH_INFORMATION_EX = *PSAPI_WS_WATCH_INFORMATION_EX; + +pub const OSVERSIONINFOW = extern struct { + dwOSVersionInfoSize: ULONG, + dwMajorVersion: ULONG, + dwMinorVersion: ULONG, + dwBuildNumber: ULONG, + dwPlatformId: ULONG, + szCSDVersion: [128]WCHAR, +}; +pub const POSVERSIONINFOW = *OSVERSIONINFOW; +pub const LPOSVERSIONINFOW = *OSVERSIONINFOW; +pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW; +pub const PRTL_OSVERSIONINFOW = *RTL_OSVERSIONINFOW; diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig index e98a2e6a8..49e60803b 100644 --- a/lib/std/os/windows/ntdll.zig +++ b/lib/std/os/windows/ntdll.zig @@ -1,6 +1,14 @@ usingnamespace @import("bits.zig"); -pub extern "NtDll" fn RtlCaptureStackBackTrace(FramesToSkip: DWORD, FramesToCapture: DWORD, BackTrace: **c_void, BackTraceHash: ?*DWORD) callconv(.Stdcall) WORD; +pub extern "NtDll" fn RtlGetVersion( + lpVersionInformation: PRTL_OSVERSIONINFOW, +) callconv(.Stdcall) NTSTATUS; +pub extern "NtDll" fn RtlCaptureStackBackTrace( + FramesToSkip: DWORD, + FramesToCapture: DWORD, + BackTrace: **c_void, + BackTraceHash: ?*DWORD, +) callconv(.Stdcall) WORD; pub extern "NtDll" fn NtQueryInformationFile( FileHandle: HANDLE, IoStatusBlock: *IO_STATUS_BLOCK, diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index df50b4a4c..38a90f4c6 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -221,7 +221,44 @@ pub const NativeTargetInfo = struct { } }, .windows => { - // TODO Detect native operating system version. + var version_info: std.os.windows.RTL_OSVERSIONINFOW = undefined; + version_info.dwOSVersionInfoSize = @sizeOf(@TypeOf(version_info)); + + switch (std.os.windows.ntdll.RtlGetVersion(&version_info)) { + .SUCCESS => {}, + else => unreachable, + } + + // Starting from the system infos build a NTDDI-like version + // constant whose format is: + // B0 B1 B2 B3 + // `---` `` ``--> Sub-version (Starting from Windows 10 onwards) + // \ `--> Service pack (Always zero in the constants defined) + // `--> OS version (Major & minor) + const os_ver: u16 = // + @intCast(u16, version_info.dwMajorVersion & 0xff) << 8 | + @intCast(u16, version_info.dwMinorVersion & 0xff); + const sp_ver: u8 = 0; + const sub_ver: u8 = if (os_ver >= 0x0A00) subver: { + // There's no other way to obtain this info beside + // checking the build number against a known set of + // values + const known_build_numbers = [_]u32{ + 10240, 10586, 14393, 15063, 16299, 17134, 17763, + 18362, 18363, + }; + var last_idx: usize = 0; + for (known_build_numbers) |build, i| { + if (version_info.dwBuildNumber >= build) + last_idx = i; + } + break :subver @truncate(u8, last_idx); + } else 0; + + const version: u32 = @as(u32, os_ver) << 16 | @as(u32, sp_ver) << 8 | sub_ver; + + os.version_range.windows.max = @intToEnum(Target.Os.WindowsVersion, version); + os.version_range.windows.min = @intToEnum(Target.Os.WindowsVersion, version); }, .macosx => { var product_version: [32]u8 = undefined;