authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-11-27 14:13:28+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-11-28 17:07:34+01:00
logd64d7aaac7650d79a6f5a5c5d0db6730b6a11b2c
treede2a78212571eae6a327b7c7e2d1e6fc669cc9c2
parent57bda6524b2dbe69c20f25e99c9b136dd0859297

windows: drive the registry helper with actual value set for reg entries


2 files changed, 87 insertions(+), 65 deletions(-)

lib/std/os/windows.zig+29-27
......@@ -2981,33 +2981,35 @@ pub const RTL_QUERY_REGISTRY_DELETE = 0x00000040;
29812981/// If the types do not match, the call fails.
29822982pub const RTL_QUERY_REGISTRY_TYPECHECK = 0x00000100;
29832983
2984/// No value type
2985pub const REG_NONE = 0;
2986/// Unicode nul terminated string
2987pub const REG_SZ = 1;
2988/// Unicode nul terminated string (with environment variable references)
2989pub const REG_EXPAND_SZ = 2;
2990/// Free form binary
2991pub const REG_BINARY = 3;
2992/// 32-bit number
2993pub const REG_DWORD = 4;
2994/// 32-bit number (same as REG_DWORD)
2995pub const REG_DWORD_LITTLE_ENDIAN = 4;
2996/// 32-bit number
2997pub const REG_DWORD_BIG_ENDIAN = 5;
2998/// Symbolic Link (unicode)
2999pub const REG_LINK = 6;
3000/// Multiple Unicode strings
3001pub const REG_MULTI_SZ = 7;
3002/// Resource list in the resource map
3003pub const REG_RESOURCE_LIST = 8;
3004/// Resource list in the hardware description
3005pub const REG_FULL_RESOURCE_DESCRIPTOR = 9;
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;
2984pub const REG = struct {
2985 /// No value type
2986 pub const NONE: ULONG = 0;
2987 /// Unicode nul terminated string
2988 pub const SZ: ULONG = 1;
2989 /// Unicode nul terminated string (with environment variable references)
2990 pub const EXPAND_SZ: ULONG = 2;
2991 /// Free form binary
2992 pub const BINARY: ULONG = 3;
2993 /// 32-bit number
2994 pub const DWORD: ULONG = 4;
2995 /// 32-bit number (same as REG_DWORD)
2996 pub const DWORD_LITTLE_ENDIAN: ULONG = 4;
2997 /// 32-bit number
2998 pub const DWORD_BIG_ENDIAN: ULONG = 5;
2999 /// Symbolic Link (unicode)
3000 pub const LINK: ULONG = 6;
3001 /// Multiple Unicode strings
3002 pub const MULTI_SZ: ULONG = 7;
3003 /// Resource list in the resource map
3004 pub const RESOURCE_LIST: ULONG = 8;
3005 /// Resource list in the hardware description
3006 pub const FULL_RESOURCE_DESCRIPTOR: ULONG = 9;
3007 pub const RESOURCE_REQUIREMENTS_LIST: ULONG = 10;
3008 /// 64-bit number
3009 pub const QWORD: ULONG = 11;
3010 /// 64-bit number (same as REG_QWORD)
3011 pub const QWORD_LITTLE_ENDIAN: ULONG = 11;
3012};
30113013
30123014pub const FILE_NOTIFY_INFORMATION = extern struct {
30133015 NextEntryOffset: DWORD,
lib/std/zig/system/windows.zig+58-38
......@@ -5,6 +5,7 @@ const Target = std.Target;
55
66pub const WindowsVersion = std.Target.Os.WindowsVersion;
77pub const PF = std.os.windows.PF;
8pub const REG = std.os.windows.REG;
89pub const IsProcessorFeaturePresent = std.os.windows.IsProcessorFeaturePresent;
910
1011/// Returns the highest known WindowsVersion deduced from reported runtime information.
......@@ -92,7 +93,7 @@ const Armv8CpuInfoImpl = struct {
9293 }
9394};
9495
95fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u8) !T {
96fn getCpuInfoFromRegistry(core: usize, comptime key: []const u8, value_type: std.os.windows.ULONG) ![]const u8 {
9697 const key_name = std.unicode.utf8ToUtf16LeStringLiteral(key);
9798
9899 // Originally, I wanted to issue a single call with a more complex table structure such that we
......@@ -105,37 +106,42 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u
105106
106107 const topkey = std.unicode.utf8ToUtf16LeStringLiteral("\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor");
107108
108 // Technically, a registry value can be as long as 16k u16s. However, MS recommends storing
109 // values larger than 2048 in a file rather than directly in the registry, and since we
109 // Technically, a registry value can be as long as 1MB. However, MS recommends storing
110 // values larger than 2048 bytes in a file rather than directly in the registry, and since we
110111 // are only accessing a system hive \Registry\Machine, we stick to MS guidelines.
111112 // https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-element-size-limits
112 const max_sz_value = 2048;
113 const max_value_len = 2048;
113114
114115 const ctx: *anyopaque = blk: {
115 switch (@typeInfo(T)) {
116 .Int => |int| {
117 const bits = int.bits;
118 var buf: [bits * 8]u8 = undefined;
116 switch (value_type) {
117 REG.NONE => unreachable,
118
119 REG.SZ,
120 REG.EXPAND_SZ,
121 REG.MULTI_SZ,
122 => {
123 var buf: [max_value_len / 2]u16 = undefined;
124 var unicode = std.os.windows.UNICODE_STRING{
125 .Length = max_value_len,
126 .MaximumLength = max_value_len,
127 .Buffer = &buf,
128 };
129 break :blk &unicode;
130 },
131
132 REG.DWORD,
133 REG.DWORD_BIG_ENDIAN,
134 => {
135 var buf: [4]u8 = undefined;
119136 break :blk &buf;
120137 },
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"),
138
139 REG.QWORD => {
140 var buf: [8]u8 = undefined;
141 break :blk &buf;
137142 },
138 else => @compileError("Unsupported type " ++ @typeName(T) ++ " as registry value"),
143
144 else => unreachable,
139145 }
140146 };
141147
......@@ -152,7 +158,7 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u
152158 .Flags = std.os.windows.RTL_QUERY_REGISTRY_SUBKEY | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED,
153159 .Name = subkey[0..subkey_len :0],
154160 .EntryContext = null,
155 .DefaultType = std.os.windows.REG_NONE,
161 .DefaultType = REG.NONE,
156162 .DefaultData = null,
157163 .DefaultLength = 0,
158164 };
......@@ -162,7 +168,7 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u
162168 .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED,
163169 .Name = @intToPtr([*:0]u16, @ptrToInt(key_name)),
164170 .EntryContext = ctx,
165 .DefaultType = std.os.windows.REG_NONE,
171 .DefaultType = REG.NONE,
166172 .DefaultData = null,
167173 .DefaultLength = 0,
168174 };
......@@ -186,17 +192,31 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u
186192 null,
187193 );
188194 switch (res) {
189 .SUCCESS => switch (@typeInfo(T)) {
190 .Int => {
191 const entry = @ptrCast(*align(1) const T, table[1].EntryContext);
192 return entry.*;
193 },
194 .Pointer => {
195 .SUCCESS => switch (value_type) {
196 REG.NONE => unreachable,
197
198 REG.SZ,
199 REG.EXPAND_SZ,
200 REG.MULTI_SZ,
201 => {
195202 const entry = @ptrCast(*align(1) const std.os.windows.UNICODE_STRING, table[1].EntryContext);
196 var identifier_buf: [max_sz_value * 2]u8 = undefined;
203 var identifier_buf: [max_value_len]u8 = undefined;
197204 const len = try std.unicode.utf16leToUtf8(&identifier_buf, entry.Buffer[0 .. entry.Length / 2]);
198 return @as(T, identifier_buf[0..len]);
205 return identifier_buf[0..len];
199206 },
207
208 REG.DWORD,
209 REG.DWORD_BIG_ENDIAN,
210 REG.QWORD,
211 => {
212 const entry = @ptrCast([*]align(1) const u8, table[1].EntryContext);
213 switch (value_type) {
214 REG.DWORD, REG.DWORD_BIG_ENDIAN => return entry[0..4],
215 REG.QWORD => return entry[0..8],
216 else => unreachable,
217 }
218 },
219
200220 else => unreachable,
201221 },
202222 else => return std.os.windows.unexpectedStatus(res),
......@@ -216,11 +236,11 @@ fn detectCpuModelArm64() !*const Target.Cpu.Model {
216236
217237 var i: usize = 0;
218238 while (i < cpu_count) : (i += 1) {
219 const identifier = try getCpuInfoFromRegistry([]const u8, i, "Identifier");
239 const identifier = try getCpuInfoFromRegistry(i, "Identifier", REG.SZ);
220240 parser.parseOne(identifier);
221241
222 const hex = try getCpuInfoFromRegistry(u64, i, "CP 4000");
223 std.log.warn("{d} => {x}", .{ i, hex });
242 const hex = try getCpuInfoFromRegistry(i, "CP 4000", REG.QWORD);
243 std.log.warn("{d} => {x}", .{ i, std.fmt.fmtSliceHexLower(hex) });
224244 }
225245
226246 return parser.finalize() orelse Target.Cpu.Model.generic(.aarch64);