windows: impl some primitives for getting registry keys

This commit is contained in:
Jakub Konka
2022-11-25 22:26:19 +01:00
parent e74b6f0a4b
commit 153afed877
3 changed files with 209 additions and 1 deletions

View File

@@ -2504,6 +2504,7 @@ pub const STANDARD_RIGHTS_READ = READ_CONTROL;
pub const STANDARD_RIGHTS_WRITE = READ_CONTROL;
pub const STANDARD_RIGHTS_EXECUTE = READ_CONTROL;
pub const STANDARD_RIGHTS_REQUIRED = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER;
pub const MAXIMUM_ALLOWED = 0x02000000;
// disposition for NtCreateFile
pub const FILE_SUPERSEDE = 0;
@@ -2872,9 +2873,11 @@ pub const PROV_RSA_FULL = 1;
pub const REGSAM = ACCESS_MASK;
pub const ACCESS_MASK = DWORD;
pub const HKEY = *opaque {};
pub const LSTATUS = LONG;
pub const HKEY = HANDLE;
pub const HKEY_LOCAL_MACHINE: HKEY = @intToPtr(HKEY, 0x80000002);
pub const FILE_NOTIFY_INFORMATION = extern struct {
NextEntryOffset: DWORD,
Action: DWORD,
@@ -4017,3 +4020,187 @@ pub fn IsProcessorFeaturePresent(feature: PF) bool {
if (@enumToInt(feature) >= PROCESSOR_FEATURE_MAX) return false;
return SharedUserData.ProcessorFeatures[@enumToInt(feature)] == 1;
}
pub const KEY_QUERY_VALUE = 0x0001;
/// Open symbolic link.
pub const REG_OPTION_OPEN_LINK: DWORD = 0x8;
inline fn IsPredefKey(hkey: HKEY) bool {
return @ptrToInt(hkey) & 0xF0000000 == 0x80000000;
}
inline fn GetPredefKeyIndex(hkey: HKEY) usize {
return @ptrToInt(hkey) & 0x0FFFFFFF;
}
inline fn ClosePredefKey(hkey: HKEY) void {
if (@ptrToInt(hkey) & 0x1 != 0) {
assert(ntdll.NtClose(hkey) == .SUCCESS);
}
}
const MAX_DEFAULT_HANDLES = 6;
pub const REG_MAX_NAME_SIZE = 256;
pub const RegOpenKeyOpts = struct {
ulOptions: DWORD = 0,
samDesired: ACCESS_MASK = KEY_QUERY_VALUE,
};
/// Pulls existing key from the registry.
pub fn RegOpenKey(hkey: HKEY, lpSubKey: []const u16, opts: RegOpenKeyOpts) !HKEY {
if (IsPredefKey(hkey) and lpSubKey.len == 0) {
return hkey;
}
const key_handle = try MapDefaultKey(hkey);
defer ClosePredefKey(key_handle);
var subkey_string: UNICODE_STRING = undefined;
if (lpSubKey.len == 0 or mem.eql(u16, &[_]u16{'\\'}, lpSubKey)) {
subkey_string = .{
.Length = 0,
.MaximumLength = 0,
.Buffer = @intToPtr([*]u16, @ptrToInt(&[0]u16{})),
};
} else {
const len_bytes = math.cast(u16, lpSubKey.len * 2) orelse return error.NameTooLong;
subkey_string = .{
.Length = len_bytes,
.MaximumLength = len_bytes,
.Buffer = @intToPtr([*]u16, @ptrToInt(lpSubKey.ptr)),
};
}
var attributes: ULONG = OBJ_CASE_INSENSITIVE;
if (opts.ulOptions & REG_OPTION_OPEN_LINK != 0) {
attributes |= OBJ_OPENLINK;
}
var attr = OBJECT_ATTRIBUTES{
.Length = @sizeOf(OBJECT_ATTRIBUTES),
.RootDirectory = key_handle,
.Attributes = attributes,
.ObjectName = &subkey_string,
.SecurityDescriptor = null,
.SecurityQualityOfService = null,
};
var result: HKEY = undefined;
const rc = ntdll.NtOpenKey(
&result,
opts.samDesired,
attr,
);
switch (rc) {
.SUCCESS => return result,
else => return unexpectedStatus(rc),
}
}
pub fn RegCloseKey(hkey: HKEY) void {
if (IsPredefKey(hkey)) return;
assert(ntdll.NtClose(hkey) == .SUCCESS);
}
extern var DefaultHandleHKUDisabled: BOOLEAN;
extern var DefaultHandlesDisabled: BOOLEAN;
extern var DefaultHandleTable: [MAX_DEFAULT_HANDLES]?HANDLE;
fn MapDefaultKey(key: HKEY) !HANDLE {
if (!IsPredefKey(key)) return @intToPtr(HANDLE, @ptrToInt(key) & ~@as(usize, 0x1));
const index = GetPredefKeyIndex(key);
if (index >= MAX_DEFAULT_HANDLES) {
return error.InvalidParameter;
}
const def_disabled = if (key == HKEY_LOCAL_MACHINE) DefaultHandleHKUDisabled else DefaultHandlesDisabled;
var handle: HANDLE = undefined;
var do_open: bool = true;
if (def_disabled != 0) {
const tmp = DefaultHandleTable[index];
if (tmp) |h| {
do_open = false;
handle = h;
}
}
if (do_open) {
handle = try OpenPredefinedKey(index);
}
if (def_disabled == 0) {
handle = @intToPtr(HANDLE, @ptrToInt(handle) | 0x1);
}
return handle;
}
fn OpenPredefinedKey(index: usize) !HANDLE {
switch (index) {
0 => {
// HKEY_CLASSES_ROOT
return error.Unimplemented;
},
1 => {
// HKEY_CURRENT_USER
return error.Unimplemented;
},
2 => {
// HKEY_LOCAL_MACHINE
return OpenLocalMachineKey();
},
3 => {
// HKEY_USERS
return error.Unimplemented;
},
5 => {
// HKEY_CURRENT_CONFIG
return error.Unimplemented;
},
6 => {
// HKEY_DYN_DATA
return error.Unimplemented;
},
else => {
return error.InvalidParameter;
},
}
}
fn OpenLocalMachineKey() !HANDLE {
const path = "\\Registry\\Machine";
var path_u16: [REG_MAX_NAME_SIZE]u16 = undefined;
const path_len_u16 = try std.unicode.utf8ToUtf16Le(&path_u16, path);
const path_len_bytes = @intCast(u16, path_len_u16 * 2);
var key_name = UNICODE_STRING{
.Length = path_len_bytes,
.MaximumLength = path_len_bytes,
.Buffer = @intToPtr([*]u16, @ptrToInt(&path_u16)),
};
var attr = OBJECT_ATTRIBUTES{
.Length = @sizeOf(OBJECT_ATTRIBUTES),
.RootDirectory = null,
.Attributes = OBJ_CASE_INSENSITIVE,
.ObjectName = &key_name,
.SecurityDescriptor = null,
.SecurityQualityOfService = null,
};
var result: HKEY = undefined;
const rc = ntdll.NtOpenKey(
&result,
MAXIMUM_ALLOWED,
attr,
);
switch (rc) {
.SUCCESS => return result,
else => return unexpectedStatus(rc),
}
}

View File

@@ -253,3 +253,9 @@ pub extern "ntdll" fn NtUnlockFile(
Length: *const LARGE_INTEGER,
Key: ?*ULONG,
) callconv(WINAPI) NTSTATUS;
pub extern "ntdll" fn NtOpenKey(
KeyHandle: *HANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: OBJECT_ATTRIBUTES,
) callconv(WINAPI) NTSTATUS;

View File

@@ -2252,4 +2252,19 @@ pub const cpu = struct {
.v8a,
}),
};
pub const microsoft_sq3 = CpuModel{
.name = "microsoft_sq3",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{
.aes,
.crc,
.crypto,
.dotprod,
.fp_armv8,
.lse,
.neon,
.sha2,
}),
};
};