authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-29 12:00:58+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-29 12:02:40+01:00
logf072b0c056768648eb56230036dc8c973116d066
tree1330454c68d18f40b8464c126a696655b1e359fb
parent7e6b68a534f840d2d08770a5a77896707271e8ea

target: Implement OS version detection for Windows

Closes #4581

3 files changed, 61 insertions(+), 2 deletions(-)

lib/std/os/windows/bits.zig+13
...@@ -1321,3 +1321,16 @@ pub const PSAPI_WS_WATCH_INFORMATION_EX = extern struct {...@@ -1321,3 +1321,16 @@ pub const PSAPI_WS_WATCH_INFORMATION_EX = extern struct {
1321 Flags: ULONG_PTR,1321 Flags: ULONG_PTR,
1322};1322};
1323pub const PPSAPI_WS_WATCH_INFORMATION_EX = *PSAPI_WS_WATCH_INFORMATION_EX;1323pub const PPSAPI_WS_WATCH_INFORMATION_EX = *PSAPI_WS_WATCH_INFORMATION_EX;
1324
1325pub const OSVERSIONINFOW = extern struct {
1326 dwOSVersionInfoSize: ULONG,
1327 dwMajorVersion: ULONG,
1328 dwMinorVersion: ULONG,
1329 dwBuildNumber: ULONG,
1330 dwPlatformId: ULONG,
1331 szCSDVersion: [128]WCHAR,
1332};
1333pub const POSVERSIONINFOW = *OSVERSIONINFOW;
1334pub const LPOSVERSIONINFOW = *OSVERSIONINFOW;
1335pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW;
1336pub const PRTL_OSVERSIONINFOW = *RTL_OSVERSIONINFOW;
lib/std/os/windows/ntdll.zig+9-1
...@@ -1,6 +1,14 @@...@@ -1,6 +1,14 @@
1usingnamespace @import("bits.zig");1usingnamespace @import("bits.zig");
22
3pub extern "NtDll" fn RtlCaptureStackBackTrace(FramesToSkip: DWORD, FramesToCapture: DWORD, BackTrace: **c_void, BackTraceHash: ?*DWORD) callconv(.Stdcall) WORD;3pub extern "NtDll" fn RtlGetVersion(
4 lpVersionInformation: PRTL_OSVERSIONINFOW,
5) callconv(.Stdcall) NTSTATUS;
6pub extern "NtDll" fn RtlCaptureStackBackTrace(
7 FramesToSkip: DWORD,
8 FramesToCapture: DWORD,
9 BackTrace: **c_void,
10 BackTraceHash: ?*DWORD,
11) callconv(.Stdcall) WORD;
4pub extern "NtDll" fn NtQueryInformationFile(12pub extern "NtDll" fn NtQueryInformationFile(
5 FileHandle: HANDLE,13 FileHandle: HANDLE,
6 IoStatusBlock: *IO_STATUS_BLOCK,14 IoStatusBlock: *IO_STATUS_BLOCK,
lib/std/zig/system.zig+39-1
...@@ -181,6 +181,7 @@ pub const NativeTargetInfo = struct {...@@ -181,6 +181,7 @@ pub const NativeTargetInfo = struct {
181 ProcessFdQuotaExceeded,181 ProcessFdQuotaExceeded,
182 SystemFdQuotaExceeded,182 SystemFdQuotaExceeded,
183 DeviceBusy,183 DeviceBusy,
184 Unexpected,
184 };185 };
185186
186 /// Given a `CrossTarget`, which specifies in detail which parts of the target should be detected187 /// Given a `CrossTarget`, which specifies in detail which parts of the target should be detected
...@@ -221,7 +222,44 @@ pub const NativeTargetInfo = struct {...@@ -221,7 +222,44 @@ pub const NativeTargetInfo = struct {
221 }222 }
222 },223 },
223 .windows => {224 .windows => {
224 // TODO Detect native operating system version.225 var version_info: std.os.windows.RTL_OSVERSIONINFOW = undefined;
226 version_info.dwOSVersionInfoSize = @sizeOf(@TypeOf(version_info));
227
228 const rc = std.os.windows.ntdll.RtlGetVersion(&version_info);
229 switch (rc) {
230 .SUCCESS => {},
231 else => return std.os.windows.unexpectedStatus(rc),
232 }
233
234 // Starting from the system infos build a NTDDI-like version
235 // constant whose format is:
236 // B0 B1 B2 B3
237 // `---` `` ``--> Sub-version (Starting from Windows 10 onwards)
238 // \ `--> Service pack (Always zero in the constants defined)
239 // `--> OS version (Major & minor)
240 const os_ver: u16 = //
241 @intCast(u16, version_info.dwMajorVersion & 0xff) << 8 |
242 @intCast(u16, version_info.dwMinorVersion & 0xff);
243 const sp_ver: u8 = 0;
244 const sub_ver: u8 = if (os_ver >= 0xA000) subver: {
245 // There's no other way to obtain this info beside
246 // checking the build number against a known set of
247 // values
248 for ([_]u32{
249 10240, 10586, 14393, 15063, 16299, 17134, 17763,
250 18362, 18363,
251 }) |build, i| {
252 if (version_info.dwBuildNumber < build)
253 break :subver @truncate(u8, i);
254 }
255 // Unknown subversion, the OS is too new...
256 break :subver 0;
257 } else 0;
258
259 const version: u32 = @as(u32, os_ver) << 16 | @as(u32, sp_ver) << 8 | sub_ver;
260
261 os.version_range.windows.max = @intToEnum(Target.Os.WindowsVersion, version);
262 os.version_range.windows.min = @intToEnum(Target.Os.WindowsVersion, version);
225 },263 },
226 .macosx => {264 .macosx => {
227 // TODO Detect native operating system version.265 // TODO Detect native operating system version.