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;...@@ -2981,33 +2981,35 @@ pub const RTL_QUERY_REGISTRY_DELETE = 0x00000040;
2981/// If the types do not match, the call fails.2981/// If the types do not match, the call fails.
2982pub const RTL_QUERY_REGISTRY_TYPECHECK = 0x00000100;2982pub const RTL_QUERY_REGISTRY_TYPECHECK = 0x00000100;
29832983
2984/// No value type2984pub const REG = struct {
2985pub const REG_NONE = 0;2985 /// No value type
2986/// Unicode nul terminated string2986 pub const NONE: ULONG = 0;
2987pub const REG_SZ = 1;2987 /// Unicode nul terminated string
2988/// Unicode nul terminated string (with environment variable references)2988 pub const SZ: ULONG = 1;
2989pub const REG_EXPAND_SZ = 2;2989 /// Unicode nul terminated string (with environment variable references)
2990/// Free form binary2990 pub const EXPAND_SZ: ULONG = 2;
2991pub const REG_BINARY = 3;2991 /// Free form binary
2992/// 32-bit number2992 pub const BINARY: ULONG = 3;
2993pub const REG_DWORD = 4;2993 /// 32-bit number
2994/// 32-bit number (same as REG_DWORD)2994 pub const DWORD: ULONG = 4;
2995pub const REG_DWORD_LITTLE_ENDIAN = 4;2995 /// 32-bit number (same as REG_DWORD)
2996/// 32-bit number2996 pub const DWORD_LITTLE_ENDIAN: ULONG = 4;
2997pub const REG_DWORD_BIG_ENDIAN = 5;2997 /// 32-bit number
2998/// Symbolic Link (unicode)2998 pub const DWORD_BIG_ENDIAN: ULONG = 5;
2999pub const REG_LINK = 6;2999 /// Symbolic Link (unicode)
3000/// Multiple Unicode strings3000 pub const LINK: ULONG = 6;
3001pub const REG_MULTI_SZ = 7;3001 /// Multiple Unicode strings
3002/// Resource list in the resource map3002 pub const MULTI_SZ: ULONG = 7;
3003pub const REG_RESOURCE_LIST = 8;3003 /// Resource list in the resource map
3004/// Resource list in the hardware description3004 pub const RESOURCE_LIST: ULONG = 8;
3005pub const REG_FULL_RESOURCE_DESCRIPTOR = 9;3005 /// Resource list in the hardware description
3006pub const REG_RESOURCE_REQUIREMENTS_LIST = 10;3006 pub const FULL_RESOURCE_DESCRIPTOR: ULONG = 9;
3007/// 64-bit number3007 pub const RESOURCE_REQUIREMENTS_LIST: ULONG = 10;
3008pub const REG_QWORD = 11;3008 /// 64-bit number
3009/// 64-bit number (same as REG_QWORD)3009 pub const QWORD: ULONG = 11;
3010pub const REG_QWORD_LITTLE_ENDIAN = 11;3010 /// 64-bit number (same as REG_QWORD)
3011 pub const QWORD_LITTLE_ENDIAN: ULONG = 11;
3012};
30113013
3012pub const FILE_NOTIFY_INFORMATION = extern struct {3014pub const FILE_NOTIFY_INFORMATION = extern struct {
3013 NextEntryOffset: DWORD,3015 NextEntryOffset: DWORD,
lib/std/zig/system/windows.zig+58-38
...@@ -5,6 +5,7 @@ const Target = std.Target;...@@ -5,6 +5,7 @@ const Target = std.Target;
55
6pub const WindowsVersion = std.Target.Os.WindowsVersion;6pub const WindowsVersion = std.Target.Os.WindowsVersion;
7pub const PF = std.os.windows.PF;7pub const PF = std.os.windows.PF;
8pub const REG = std.os.windows.REG;
8pub const IsProcessorFeaturePresent = std.os.windows.IsProcessorFeaturePresent;9pub const IsProcessorFeaturePresent = std.os.windows.IsProcessorFeaturePresent;
910
10/// Returns the highest known WindowsVersion deduced from reported runtime information.11/// Returns the highest known WindowsVersion deduced from reported runtime information.
...@@ -92,7 +93,7 @@ const Armv8CpuInfoImpl = struct {...@@ -92,7 +93,7 @@ const Armv8CpuInfoImpl = struct {
92 }93 }
93};94};
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 {
96 const key_name = std.unicode.utf8ToUtf16LeStringLiteral(key);97 const key_name = std.unicode.utf8ToUtf16LeStringLiteral(key);
9798
98 // Originally, I wanted to issue a single call with a more complex table structure such that we99 // 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...@@ -105,37 +106,42 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u
105106
106 const topkey = std.unicode.utf8ToUtf16LeStringLiteral("\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor");107 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 storing109 // Technically, a registry value can be as long as 1MB. However, MS recommends storing
109 // values larger than 2048 in a file rather than directly in the registry, and since we110 // values larger than 2048 bytes in a file rather than directly in the registry, and since we
110 // are only accessing a system hive \Registry\Machine, we stick to MS guidelines.111 // are only accessing a system hive \Registry\Machine, we stick to MS guidelines.
111 // https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-element-size-limits112 // 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
114 const ctx: *anyopaque = blk: {115 const ctx: *anyopaque = blk: {
115 switch (@typeInfo(T)) {116 switch (value_type) {
116 .Int => |int| {117 REG.NONE => unreachable,
117 const bits = int.bits;118
118 var buf: [bits * 8]u8 = undefined;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;
119 break :blk &buf;136 break :blk &buf;
120 },137 },
121 .Pointer => |ptr| switch (ptr.size) {138
122 .Slice => {139 REG.QWORD => {
123 const child = @typeInfo(ptr.child);140 var buf: [8]u8 = undefined;
124 if (child != .Int and child.Int.bits != 8) {141 break :blk &buf;
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 },142 },
138 else => @compileError("Unsupported type " ++ @typeName(T) ++ " as registry value"),143
144 else => unreachable,
139 }145 }
140 };146 };
141147
...@@ -152,7 +158,7 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u...@@ -152,7 +158,7 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u
152 .Flags = std.os.windows.RTL_QUERY_REGISTRY_SUBKEY | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED,158 .Flags = std.os.windows.RTL_QUERY_REGISTRY_SUBKEY | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED,
153 .Name = subkey[0..subkey_len :0],159 .Name = subkey[0..subkey_len :0],
154 .EntryContext = null,160 .EntryContext = null,
155 .DefaultType = std.os.windows.REG_NONE,161 .DefaultType = REG.NONE,
156 .DefaultData = null,162 .DefaultData = null,
157 .DefaultLength = 0,163 .DefaultLength = 0,
158 };164 };
...@@ -162,7 +168,7 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u...@@ -162,7 +168,7 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u
162 .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED,168 .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED,
163 .Name = @intToPtr([*:0]u16, @ptrToInt(key_name)),169 .Name = @intToPtr([*:0]u16, @ptrToInt(key_name)),
164 .EntryContext = ctx,170 .EntryContext = ctx,
165 .DefaultType = std.os.windows.REG_NONE,171 .DefaultType = REG.NONE,
166 .DefaultData = null,172 .DefaultData = null,
167 .DefaultLength = 0,173 .DefaultLength = 0,
168 };174 };
...@@ -186,17 +192,31 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u...@@ -186,17 +192,31 @@ fn getCpuInfoFromRegistry(comptime T: type, core: usize, comptime key: []const u
186 null,192 null,
187 );193 );
188 switch (res) {194 switch (res) {
189 .SUCCESS => switch (@typeInfo(T)) {195 .SUCCESS => switch (value_type) {
190 .Int => {196 REG.NONE => unreachable,
191 const entry = @ptrCast(*align(1) const T, table[1].EntryContext);197
192 return entry.*;198 REG.SZ,
193 },199 REG.EXPAND_SZ,
194 .Pointer => {200 REG.MULTI_SZ,
201 => {
195 const entry = @ptrCast(*align(1) const std.os.windows.UNICODE_STRING, table[1].EntryContext);202 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;
197 const len = try std.unicode.utf16leToUtf8(&identifier_buf, entry.Buffer[0 .. entry.Length / 2]);204 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];
199 },206 },
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
200 else => unreachable,220 else => unreachable,
201 },221 },
202 else => return std.os.windows.unexpectedStatus(res),222 else => return std.os.windows.unexpectedStatus(res),
...@@ -216,11 +236,11 @@ fn detectCpuModelArm64() !*const Target.Cpu.Model {...@@ -216,11 +236,11 @@ fn detectCpuModelArm64() !*const Target.Cpu.Model {
216236
217 var i: usize = 0;237 var i: usize = 0;
218 while (i < cpu_count) : (i += 1) {238 while (i < cpu_count) : (i += 1) {
219 const identifier = try getCpuInfoFromRegistry([]const u8, i, "Identifier");239 const identifier = try getCpuInfoFromRegistry(i, "Identifier", REG.SZ);
220 parser.parseOne(identifier);240 parser.parseOne(identifier);
221241
222 const hex = try getCpuInfoFromRegistry(u64, i, "CP 4000");242 const hex = try getCpuInfoFromRegistry(i, "CP 4000", REG.QWORD);
223 std.log.warn("{d} => {x}", .{ i, hex });243 std.log.warn("{d} => {x}", .{ i, std.fmt.fmtSliceHexLower(hex) });
224 }244 }
225245
226 return parser.finalize() orelse Target.Cpu.Model.generic(.aarch64);246 return parser.finalize() orelse Target.Cpu.Model.generic(.aarch64);