fn getString(
key: Key,
gpa: Allocator,
entry: ValueEntry,
comptime result_encoding: enum { wtf16, wtf8 },
) error{ OutOfMemory, ValueNameNotFound, NotAString, StringNotFound }!(switch (result_encoding) {
.wtf8 => []u8,
.wtf16 => []u16,
}) {
const num_data_bytes = windows.MAX_PATH * 2;
const stack_buf_len = @sizeOf(windows.KEY.VALUE.PARTIAL_INFORMATION) + num_data_bytes;
var stack_info_buf: [stack_buf_len]u8 align(@alignOf(windows.KEY.VALUE.PARTIAL_INFORMATION)) = undefined;
var result_len: windows.ULONG = undefined;
const rc = windows.ntdll.NtQueryValueKey(
key.handle,
switch (entry) {
.name => |name| @constCast(&windows.UNICODE_STRING.init(name)),
.default => @constCast(&windows.UNICODE_STRING.empty),
},
.Partial,
&stack_info_buf,
stack_buf_len,
&result_len,
);
var heap_info_buf: ?[]align(@alignOf(windows.KEY.VALUE.PARTIAL_INFORMATION)) u8 = null;
defer if (heap_info_buf) |buf| gpa.free(buf);
const info: *const windows.KEY.VALUE.PARTIAL_INFORMATION = switch (rc) {
.SUCCESS => @ptrCast(&stack_info_buf),
.BUFFER_OVERFLOW, .BUFFER_TOO_SMALL => heap_info: {
heap_info_buf = try gpa.alignedAlloc(u8, .of(windows.KEY.VALUE.PARTIAL_INFORMATION), result_len);
const heap_rc = windows.ntdll.NtQueryValueKey(
key.handle,
switch (entry) {
.name => |name| @constCast(&windows.UNICODE_STRING.init(name)),
.default => @constCast(&windows.UNICODE_STRING.empty),
},
.Partial,
heap_info_buf.?.ptr,
@intCast(heap_info_buf.?.len),
&result_len,
);
switch (heap_rc) {
.SUCCESS => break :heap_info @ptrCast(heap_info_buf.?.ptr),
.OBJECT_NAME_NOT_FOUND => return error.ValueNameNotFound,
else => return error.StringNotFound,
}
},
.OBJECT_NAME_NOT_FOUND => return error.ValueNameNotFound,
else => return error.StringNotFound,
};
switch (info.Type) {
.SZ => {},
else => return error.NotAString,
}
const data_wtf16_with_nul = @as([*]const u16, @ptrCast(@alignCast(info.data())))[0..@divExact(info.DataLength, 2)];
const data_wtf16 = std.mem.trimEnd(u16, data_wtf16_with_nul, L("\x00"));
switch (result_encoding) {
.wtf16 => return gpa.dupe(u16, data_wtf16),
.wtf8 => return std.unicode.wtf16LeToWtf8Alloc(gpa, data_wtf16),
}
}