Skip to content

Commit ae99fab

Browse files
authored
Merge pull request #4585 from LemonBoy/fix-4581
target: Implement OS version detection for Windows
2 parents f082e25 + 278f0f8 commit ae99fab

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

lib/std/os/windows/bits.zig

+13
Original file line numberDiff line numberDiff line change
@@ -1493,3 +1493,16 @@ pub const PSAPI_WS_WATCH_INFORMATION_EX = extern struct {
14931493
Flags: ULONG_PTR,
14941494
};
14951495
pub const PPSAPI_WS_WATCH_INFORMATION_EX = *PSAPI_WS_WATCH_INFORMATION_EX;
1496+
1497+
pub const OSVERSIONINFOW = extern struct {
1498+
dwOSVersionInfoSize: ULONG,
1499+
dwMajorVersion: ULONG,
1500+
dwMinorVersion: ULONG,
1501+
dwBuildNumber: ULONG,
1502+
dwPlatformId: ULONG,
1503+
szCSDVersion: [128]WCHAR,
1504+
};
1505+
pub const POSVERSIONINFOW = *OSVERSIONINFOW;
1506+
pub const LPOSVERSIONINFOW = *OSVERSIONINFOW;
1507+
pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW;
1508+
pub const PRTL_OSVERSIONINFOW = *RTL_OSVERSIONINFOW;

lib/std/os/windows/ntdll.zig

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
usingnamespace @import("bits.zig");
22

3-
pub extern "NtDll" fn RtlCaptureStackBackTrace(FramesToSkip: DWORD, FramesToCapture: DWORD, BackTrace: **c_void, BackTraceHash: ?*DWORD) callconv(.Stdcall) WORD;
3+
pub extern "NtDll" fn RtlGetVersion(
4+
lpVersionInformation: PRTL_OSVERSIONINFOW,
5+
) callconv(.Stdcall) NTSTATUS;
6+
pub extern "NtDll" fn RtlCaptureStackBackTrace(
7+
FramesToSkip: DWORD,
8+
FramesToCapture: DWORD,
9+
BackTrace: **c_void,
10+
BackTraceHash: ?*DWORD,
11+
) callconv(.Stdcall) WORD;
412
pub extern "NtDll" fn NtQueryInformationFile(
513
FileHandle: HANDLE,
614
IoStatusBlock: *IO_STATUS_BLOCK,

lib/std/zig/system.zig

+38-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,44 @@ pub const NativeTargetInfo = struct {
221221
}
222222
},
223223
.windows => {
224-
// TODO Detect native operating system version.
224+
var version_info: std.os.windows.RTL_OSVERSIONINFOW = undefined;
225+
version_info.dwOSVersionInfoSize = @sizeOf(@TypeOf(version_info));
226+
227+
switch (std.os.windows.ntdll.RtlGetVersion(&version_info)) {
228+
.SUCCESS => {},
229+
else => unreachable,
230+
}
231+
232+
// Starting from the system infos build a NTDDI-like version
233+
// constant whose format is:
234+
// B0 B1 B2 B3
235+
// `---` `` ``--> Sub-version (Starting from Windows 10 onwards)
236+
// \ `--> Service pack (Always zero in the constants defined)
237+
// `--> OS version (Major & minor)
238+
const os_ver: u16 = //
239+
@intCast(u16, version_info.dwMajorVersion & 0xff) << 8 |
240+
@intCast(u16, version_info.dwMinorVersion & 0xff);
241+
const sp_ver: u8 = 0;
242+
const sub_ver: u8 = if (os_ver >= 0x0A00) subver: {
243+
// There's no other way to obtain this info beside
244+
// checking the build number against a known set of
245+
// values
246+
const known_build_numbers = [_]u32{
247+
10240, 10586, 14393, 15063, 16299, 17134, 17763,
248+
18362, 18363,
249+
};
250+
var last_idx: usize = 0;
251+
for (known_build_numbers) |build, i| {
252+
if (version_info.dwBuildNumber >= build)
253+
last_idx = i;
254+
}
255+
break :subver @truncate(u8, last_idx);
256+
} else 0;
257+
258+
const version: u32 = @as(u32, os_ver) << 16 | @as(u32, sp_ver) << 8 | sub_ver;
259+
260+
os.version_range.windows.max = @intToEnum(Target.Os.WindowsVersion, version);
261+
os.version_range.windows.min = @intToEnum(Target.Os.WindowsVersion, version);
225262
},
226263
.macosx => {
227264
var product_version: [32]u8 = undefined;

0 commit comments

Comments
 (0)