diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-11-27 13:51:27 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-11-28 17:07:34 +0100 |
| commit | 57bda6524b2dbe69c20f25e99c9b136dd0859297 (patch) | |
| tree | 76209fb7e7b42a4a81c8c119029eb252d65f12af /lib | |
| parent | 49ce86bddf49efcd1de8768d728d77ea1c8849f8 (diff) | |
| download | zig-57bda6524b2dbe69c20f25e99c9b136dd0859297.tar.gz zig-57bda6524b2dbe69c20f25e99c9b136dd0859297.zip | |
windows: make registry helper generic over value types
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/os/windows.zig | 4 | ||||
| -rw-r--r-- | lib/std/zig/system/windows.zig | 67 |
2 files changed, 54 insertions, 17 deletions
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 4c2aba206c..06b3cd7d77 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -3004,6 +3004,10 @@ pub const REG_RESOURCE_LIST = 8; /// Resource list in the hardware description pub const REG_FULL_RESOURCE_DESCRIPTOR = 9; pub const REG_RESOURCE_REQUIREMENTS_LIST = 10; +/// 64-bit number +pub const REG_QWORD = 11; +/// 64-bit number (same as REG_QWORD) +pub const REG_QWORD_LITTLE_ENDIAN = 11; pub const FILE_NOTIFY_INFORMATION = extern struct { NextEntryOffset: DWORD, diff --git a/lib/std/zig/system/windows.zig b/lib/std/zig/system/windows.zig index 35005d649b..8294fd5b95 100644 --- a/lib/std/zig/system/windows.zig +++ b/lib/std/zig/system/windows.zig @@ -92,12 +92,7 @@ const Armv8CpuInfoImpl = struct { } }; -fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8) ![]const u8 { - // Technically, a registry value can be as long as 16k u16s. However, MS recommends storing - // values larger than 2048 in a file rather than directly in the registry, and since we - // are only accessing a system hive \Registry\Machine, we stick to MS guidelines. - // https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-element-size-limits - const max_sz_value = 2048; +fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u8) !T { const key_name = std.unicode.utf8ToUtf16LeStringLiteral(key); // Originally, I wanted to issue a single call with a more complex table structure such that we @@ -110,11 +105,38 @@ fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8) ![]const u8 { const topkey = std.unicode.utf8ToUtf16LeStringLiteral("\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor"); - var buf: [max_sz_value]u16 = undefined; - var buf_uni = std.os.windows.UNICODE_STRING{ - .Length = buf.len * 2, - .MaximumLength = buf.len * 2, - .Buffer = &buf, + // Technically, a registry value can be as long as 16k u16s. However, MS recommends storing + // values larger than 2048 in a file rather than directly in the registry, and since we + // are only accessing a system hive \Registry\Machine, we stick to MS guidelines. + // https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-element-size-limits + const max_sz_value = 2048; + + const ctx: *anyopaque = blk: { + switch (@typeInfo(T)) { + .Int => |int| { + const bits = int.bits; + var buf: [bits * 8]u8 = undefined; + break :blk &buf; + }, + .Pointer => |ptr| switch (ptr.size) { + .Slice => { + const child = @typeInfo(ptr.child); + if (child != .Int and child.Int.bits != 8) { + @compileError("Unsupported type " ++ @typeName(T) ++ " as registry value"); + } + + var buf: [max_sz_value]u16 = undefined; + var unicode = std.os.windows.UNICODE_STRING{ + .Length = buf.len * 2, + .MaximumLength = buf.len * 2, + .Buffer = &buf, + }; + break :blk &unicode; + }, + else => @compileError("Unsupported type " ++ @typeName(T) ++ " as registry value"), + }, + else => @compileError("Unsupported type " ++ @typeName(T) ++ " as registry value"), + } }; const max_cpu_buf = 4; @@ -139,7 +161,7 @@ fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8) ![]const u8 { .QueryRoutine = null, .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED, .Name = @intToPtr([*:0]u16, @ptrToInt(key_name)), - .EntryContext = &buf_uni, + .EntryContext = ctx, .DefaultType = std.os.windows.REG_NONE, .DefaultData = null, .DefaultLength = 0, @@ -164,10 +186,18 @@ fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8) ![]const u8 { null, ); switch (res) { - .SUCCESS => { - var identifier_buf: [max_sz_value * 2]u8 = undefined; - const len = try std.unicode.utf16leToUtf8(&identifier_buf, buf_uni.Buffer[0 .. buf_uni.Length / 2]); - return identifier_buf[0..len]; + .SUCCESS => switch (@typeInfo(T)) { + .Int => { + const entry = @ptrCast(*align(1) const T, table[1].EntryContext); + return entry.*; + }, + .Pointer => { + const entry = @ptrCast(*align(1) const std.os.windows.UNICODE_STRING, table[1].EntryContext); + var identifier_buf: [max_sz_value * 2]u8 = undefined; + const len = try std.unicode.utf16leToUtf8(&identifier_buf, entry.Buffer[0 .. entry.Length / 2]); + return @as(T, identifier_buf[0..len]); + }, + else => unreachable, }, else => return std.os.windows.unexpectedStatus(res), } @@ -186,8 +216,11 @@ fn detectCpuModelArm64() !*const Target.Cpu.Model { var i: usize = 0; while (i < cpu_count) : (i += 1) { - const identifier = try getCpuInfoFromRegistry(i, "Identifier"); + const identifier = try getCpuInfoFromRegistry([]const u8, i, "Identifier"); parser.parseOne(identifier); + + const hex = try getCpuInfoFromRegistry(u64, i, "CP 4000"); + std.log.warn("{d} => {x}", .{ i, hex }); } return parser.finalize() orelse Target.Cpu.Model.generic(.aarch64); |
