authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-11-25 22:26:19+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-11-28 17:07:34+01:00
log153afed877e6f9a068d5db61f42cdb872c72aeab
tree4d2dbd2e99a8b0b87578162bc5ecae6ab7b9842d
parente74b6f0a4bb86d5186ccc47ffd096f2ebfb29bc1

windows: impl some primitives for getting registry keys


3 files changed, 209 insertions(+), 1 deletions(-)

lib/std/os/windows.zig+188-1
......@@ -2504,6 +2504,7 @@ pub const STANDARD_RIGHTS_READ = READ_CONTROL;
25042504pub const STANDARD_RIGHTS_WRITE = READ_CONTROL;
25052505pub const STANDARD_RIGHTS_EXECUTE = READ_CONTROL;
25062506pub const STANDARD_RIGHTS_REQUIRED = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER;
2507pub const MAXIMUM_ALLOWED = 0x02000000;
25072508
25082509// disposition for NtCreateFile
25092510pub const FILE_SUPERSEDE = 0;
......@@ -2872,9 +2873,11 @@ pub const PROV_RSA_FULL = 1;
28722873
28732874pub const REGSAM = ACCESS_MASK;
28742875pub const ACCESS_MASK = DWORD;
2875pub const HKEY = *opaque {};
28762876pub const LSTATUS = LONG;
28772877
2878pub const HKEY = HANDLE;
2879pub const HKEY_LOCAL_MACHINE: HKEY = @intToPtr(HKEY, 0x80000002);
2880
28782881pub const FILE_NOTIFY_INFORMATION = extern struct {
28792882 NextEntryOffset: DWORD,
28802883 Action: DWORD,
......@@ -4017,3 +4020,187 @@ pub fn IsProcessorFeaturePresent(feature: PF) bool {
40174020 if (@enumToInt(feature) >= PROCESSOR_FEATURE_MAX) return false;
40184021 return SharedUserData.ProcessorFeatures[@enumToInt(feature)] == 1;
40194022}
4023
4024pub const KEY_QUERY_VALUE = 0x0001;
4025
4026/// Open symbolic link.
4027pub const REG_OPTION_OPEN_LINK: DWORD = 0x8;
4028
4029inline fn IsPredefKey(hkey: HKEY) bool {
4030 return @ptrToInt(hkey) & 0xF0000000 == 0x80000000;
4031}
4032
4033inline fn GetPredefKeyIndex(hkey: HKEY) usize {
4034 return @ptrToInt(hkey) & 0x0FFFFFFF;
4035}
4036
4037inline fn ClosePredefKey(hkey: HKEY) void {
4038 if (@ptrToInt(hkey) & 0x1 != 0) {
4039 assert(ntdll.NtClose(hkey) == .SUCCESS);
4040 }
4041}
4042
4043const MAX_DEFAULT_HANDLES = 6;
4044pub const REG_MAX_NAME_SIZE = 256;
4045
4046pub const RegOpenKeyOpts = struct {
4047 ulOptions: DWORD = 0,
4048 samDesired: ACCESS_MASK = KEY_QUERY_VALUE,
4049};
4050
4051/// Pulls existing key from the registry.
4052pub fn RegOpenKey(hkey: HKEY, lpSubKey: []const u16, opts: RegOpenKeyOpts) !HKEY {
4053 if (IsPredefKey(hkey) and lpSubKey.len == 0) {
4054 return hkey;
4055 }
4056
4057 const key_handle = try MapDefaultKey(hkey);
4058 defer ClosePredefKey(key_handle);
4059
4060 var subkey_string: UNICODE_STRING = undefined;
4061 if (lpSubKey.len == 0 or mem.eql(u16, &[_]u16{'\\'}, lpSubKey)) {
4062 subkey_string = .{
4063 .Length = 0,
4064 .MaximumLength = 0,
4065 .Buffer = @intToPtr([*]u16, @ptrToInt(&[0]u16{})),
4066 };
4067 } else {
4068 const len_bytes = math.cast(u16, lpSubKey.len * 2) orelse return error.NameTooLong;
4069 subkey_string = .{
4070 .Length = len_bytes,
4071 .MaximumLength = len_bytes,
4072 .Buffer = @intToPtr([*]u16, @ptrToInt(lpSubKey.ptr)),
4073 };
4074 }
4075
4076 var attributes: ULONG = OBJ_CASE_INSENSITIVE;
4077 if (opts.ulOptions & REG_OPTION_OPEN_LINK != 0) {
4078 attributes |= OBJ_OPENLINK;
4079 }
4080
4081 var attr = OBJECT_ATTRIBUTES{
4082 .Length = @sizeOf(OBJECT_ATTRIBUTES),
4083 .RootDirectory = key_handle,
4084 .Attributes = attributes,
4085 .ObjectName = &subkey_string,
4086 .SecurityDescriptor = null,
4087 .SecurityQualityOfService = null,
4088 };
4089
4090 var result: HKEY = undefined;
4091 const rc = ntdll.NtOpenKey(
4092 &result,
4093 opts.samDesired,
4094 attr,
4095 );
4096 switch (rc) {
4097 .SUCCESS => return result,
4098 else => return unexpectedStatus(rc),
4099 }
4100}
4101
4102pub fn RegCloseKey(hkey: HKEY) void {
4103 if (IsPredefKey(hkey)) return;
4104 assert(ntdll.NtClose(hkey) == .SUCCESS);
4105}
4106
4107extern var DefaultHandleHKUDisabled: BOOLEAN;
4108extern var DefaultHandlesDisabled: BOOLEAN;
4109extern var DefaultHandleTable: [MAX_DEFAULT_HANDLES]?HANDLE;
4110
4111fn MapDefaultKey(key: HKEY) !HANDLE {
4112 if (!IsPredefKey(key)) return @intToPtr(HANDLE, @ptrToInt(key) & ~@as(usize, 0x1));
4113
4114 const index = GetPredefKeyIndex(key);
4115 if (index >= MAX_DEFAULT_HANDLES) {
4116 return error.InvalidParameter;
4117 }
4118
4119 const def_disabled = if (key == HKEY_LOCAL_MACHINE) DefaultHandleHKUDisabled else DefaultHandlesDisabled;
4120
4121 var handle: HANDLE = undefined;
4122 var do_open: bool = true;
4123
4124 if (def_disabled != 0) {
4125 const tmp = DefaultHandleTable[index];
4126 if (tmp) |h| {
4127 do_open = false;
4128 handle = h;
4129 }
4130 }
4131
4132 if (do_open) {
4133 handle = try OpenPredefinedKey(index);
4134 }
4135
4136 if (def_disabled == 0) {
4137 handle = @intToPtr(HANDLE, @ptrToInt(handle) | 0x1);
4138 }
4139
4140 return handle;
4141}
4142
4143fn OpenPredefinedKey(index: usize) !HANDLE {
4144 switch (index) {
4145 0 => {
4146 // HKEY_CLASSES_ROOT
4147 return error.Unimplemented;
4148 },
4149 1 => {
4150 // HKEY_CURRENT_USER
4151 return error.Unimplemented;
4152 },
4153 2 => {
4154 // HKEY_LOCAL_MACHINE
4155 return OpenLocalMachineKey();
4156 },
4157 3 => {
4158 // HKEY_USERS
4159 return error.Unimplemented;
4160 },
4161 5 => {
4162 // HKEY_CURRENT_CONFIG
4163 return error.Unimplemented;
4164 },
4165 6 => {
4166 // HKEY_DYN_DATA
4167 return error.Unimplemented;
4168 },
4169 else => {
4170 return error.InvalidParameter;
4171 },
4172 }
4173}
4174
4175fn OpenLocalMachineKey() !HANDLE {
4176 const path = "\\Registry\\Machine";
4177 var path_u16: [REG_MAX_NAME_SIZE]u16 = undefined;
4178 const path_len_u16 = try std.unicode.utf8ToUtf16Le(&path_u16, path);
4179 const path_len_bytes = @intCast(u16, path_len_u16 * 2);
4180
4181 var key_name = UNICODE_STRING{
4182 .Length = path_len_bytes,
4183 .MaximumLength = path_len_bytes,
4184 .Buffer = @intToPtr([*]u16, @ptrToInt(&path_u16)),
4185 };
4186
4187 var attr = OBJECT_ATTRIBUTES{
4188 .Length = @sizeOf(OBJECT_ATTRIBUTES),
4189 .RootDirectory = null,
4190 .Attributes = OBJ_CASE_INSENSITIVE,
4191 .ObjectName = &key_name,
4192 .SecurityDescriptor = null,
4193 .SecurityQualityOfService = null,
4194 };
4195
4196 var result: HKEY = undefined;
4197 const rc = ntdll.NtOpenKey(
4198 &result,
4199 MAXIMUM_ALLOWED,
4200 attr,
4201 );
4202 switch (rc) {
4203 .SUCCESS => return result,
4204 else => return unexpectedStatus(rc),
4205 }
4206}
lib/std/os/windows/ntdll.zig+6
......@@ -253,3 +253,9 @@ pub extern "ntdll" fn NtUnlockFile(
253253 Length: *const LARGE_INTEGER,
254254 Key: ?*ULONG,
255255) callconv(WINAPI) NTSTATUS;
256
257pub extern "ntdll" fn NtOpenKey(
258 KeyHandle: *HANDLE,
259 DesiredAccess: ACCESS_MASK,
260 ObjectAttributes: OBJECT_ATTRIBUTES,
261) callconv(WINAPI) NTSTATUS;
lib/std/target/aarch64.zig+15
......@@ -2252,4 +2252,19 @@ pub const cpu = struct {
22522252 .v8a,
22532253 }),
22542254 };
2255
2256 pub const microsoft_sq3 = CpuModel{
2257 .name = "microsoft_sq3",
2258 .llvm_name = "generic",
2259 .features = featureSet(&[_]Feature{
2260 .aes,
2261 .crc,
2262 .crypto,
2263 .dotprod,
2264 .fp_armv8,
2265 .lse,
2266 .neon,
2267 .sha2,
2268 }),
2269 };
22552270};