authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-11-27 13:51:27+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-11-28 17:07:34+01:00
log57bda6524b2dbe69c20f25e99c9b136dd0859297
tree76209fb7e7b42a4a81c8c119029eb252d65f12af
parent49ce86bddf49efcd1de8768d728d77ea1c8849f8

windows: make registry helper generic over value types


2 files changed, 54 insertions(+), 17 deletions(-)

lib/std/os/windows.zig+4
...@@ -3004,6 +3004,10 @@ pub const REG_RESOURCE_LIST = 8;...@@ -3004,6 +3004,10 @@ pub const REG_RESOURCE_LIST = 8;
3004/// Resource list in the hardware description3004/// Resource list in the hardware description
3005pub const REG_FULL_RESOURCE_DESCRIPTOR = 9;3005pub const REG_FULL_RESOURCE_DESCRIPTOR = 9;
3006pub const REG_RESOURCE_REQUIREMENTS_LIST = 10;3006pub const REG_RESOURCE_REQUIREMENTS_LIST = 10;
3007/// 64-bit number
3008pub const REG_QWORD = 11;
3009/// 64-bit number (same as REG_QWORD)
3010pub const REG_QWORD_LITTLE_ENDIAN = 11;
30073011
3008pub const FILE_NOTIFY_INFORMATION = extern struct {3012pub const FILE_NOTIFY_INFORMATION = extern struct {
3009 NextEntryOffset: DWORD,3013 NextEntryOffset: DWORD,
lib/std/zig/system/windows.zig+50-17
...@@ -92,12 +92,7 @@ const Armv8CpuInfoImpl = struct {...@@ -92,12 +92,7 @@ const Armv8CpuInfoImpl = struct {
92 }92 }
93};93};
9494
95fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8) ![]const u8 {95fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u8) !T {
96 // Technically, a registry value can be as long as 16k u16s. However, MS recommends storing
97 // values larger than 2048 in a file rather than directly in the registry, and since we
98 // are only accessing a system hive \Registry\Machine, we stick to MS guidelines.
99 // https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-element-size-limits
100 const max_sz_value = 2048;
101 const key_name = std.unicode.utf8ToUtf16LeStringLiteral(key);96 const key_name = std.unicode.utf8ToUtf16LeStringLiteral(key);
10297
103 // Originally, I wanted to issue a single call with a more complex table structure such that we98 // 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 {...@@ -110,11 +105,38 @@ fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8) ![]const u8 {
110105
111 const topkey = std.unicode.utf8ToUtf16LeStringLiteral("\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor");106 const topkey = std.unicode.utf8ToUtf16LeStringLiteral("\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor");
112107
113 var buf: [max_sz_value]u16 = undefined;108 // Technically, a registry value can be as long as 16k u16s. However, MS recommends storing
114 var buf_uni = std.os.windows.UNICODE_STRING{109 // values larger than 2048 in a file rather than directly in the registry, and since we
115 .Length = buf.len * 2,110 // are only accessing a system hive \Registry\Machine, we stick to MS guidelines.
116 .MaximumLength = buf.len * 2,111 // https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-element-size-limits
117 .Buffer = &buf,112 const max_sz_value = 2048;
113
114 const ctx: *anyopaque = blk: {
115 switch (@typeInfo(T)) {
116 .Int => |int| {
117 const bits = int.bits;
118 var buf: [bits * 8]u8 = undefined;
119 break :blk &buf;
120 },
121 .Pointer => |ptr| switch (ptr.size) {
122 .Slice => {
123 const child = @typeInfo(ptr.child);
124 if (child != .Int and child.Int.bits != 8) {
125 @compileError("Unsupported type " ++ @typeName(T) ++ " as registry value");
126 }
127
128 var buf: [max_sz_value]u16 = undefined;
129 var unicode = std.os.windows.UNICODE_STRING{
130 .Length = buf.len * 2,
131 .MaximumLength = buf.len * 2,
132 .Buffer = &buf,
133 };
134 break :blk &unicode;
135 },
136 else => @compileError("Unsupported type " ++ @typeName(T) ++ " as registry value"),
137 },
138 else => @compileError("Unsupported type " ++ @typeName(T) ++ " as registry value"),
139 }
118 };140 };
119141
120 const max_cpu_buf = 4;142 const max_cpu_buf = 4;
...@@ -139,7 +161,7 @@ fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8) ![]const u8 {...@@ -139,7 +161,7 @@ fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8) ![]const u8 {
139 .QueryRoutine = null,161 .QueryRoutine = null,
140 .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED,162 .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED,
141 .Name = @intToPtr([*:0]u16, @ptrToInt(key_name)),163 .Name = @intToPtr([*:0]u16, @ptrToInt(key_name)),
142 .EntryContext = &buf_uni,164 .EntryContext = ctx,
143 .DefaultType = std.os.windows.REG_NONE,165 .DefaultType = std.os.windows.REG_NONE,
144 .DefaultData = null,166 .DefaultData = null,
145 .DefaultLength = 0,167 .DefaultLength = 0,
...@@ -164,10 +186,18 @@ fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8) ![]const u8 {...@@ -164,10 +186,18 @@ fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8) ![]const u8 {
164 null,186 null,
165 );187 );
166 switch (res) {188 switch (res) {
167 .SUCCESS => {189 .SUCCESS => switch (@typeInfo(T)) {
168 var identifier_buf: [max_sz_value * 2]u8 = undefined;190 .Int => {
169 const len = try std.unicode.utf16leToUtf8(&identifier_buf, buf_uni.Buffer[0 .. buf_uni.Length / 2]);191 const entry = @ptrCast(*align(1) const T, table[1].EntryContext);
170 return identifier_buf[0..len];192 return entry.*;
193 },
194 .Pointer => {
195 const entry = @ptrCast(*align(1) const std.os.windows.UNICODE_STRING, table[1].EntryContext);
196 var identifier_buf: [max_sz_value * 2]u8 = undefined;
197 const len = try std.unicode.utf16leToUtf8(&identifier_buf, entry.Buffer[0 .. entry.Length / 2]);
198 return @as(T, identifier_buf[0..len]);
199 },
200 else => unreachable,
171 },201 },
172 else => return std.os.windows.unexpectedStatus(res),202 else => return std.os.windows.unexpectedStatus(res),
173 }203 }
...@@ -186,8 +216,11 @@ fn detectCpuModelArm64() !*const Target.Cpu.Model {...@@ -186,8 +216,11 @@ fn detectCpuModelArm64() !*const Target.Cpu.Model {
186216
187 var i: usize = 0;217 var i: usize = 0;
188 while (i < cpu_count) : (i += 1) {218 while (i < cpu_count) : (i += 1) {
189 const identifier = try getCpuInfoFromRegistry(i, "Identifier");219 const identifier = try getCpuInfoFromRegistry([]const u8, i, "Identifier");
190 parser.parseOne(identifier);220 parser.parseOne(identifier);
221
222 const hex = try getCpuInfoFromRegistry(u64, i, "CP 4000");
223 std.log.warn("{d} => {x}", .{ i, hex });
191 }224 }
192225
193 return parser.finalize() orelse Target.Cpu.Model.generic(.aarch64);226 return parser.finalize() orelse Target.Cpu.Model.generic(.aarch64);