ebpf-for-windows/libs/api_common/registry_helper.cpp

235 строки
7.1 KiB
C++

// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
// Contains user mode registry related helper APIs.
#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
#include <codecvt>
#include "api_common.hpp"
#include "ebpf_registry_helper.h"
#define GUID_STRING_LENGTH 38 // not including the null terminator.
static std::wstring
_get_wstring_from_string(std::string text)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring wide = converter.from_bytes(text);
return wide;
}
void
close_registry_key(ebpf_registry_key_t key)
{
ebpf_assert(key);
RegCloseKey(key);
}
_Must_inspect_result_ ebpf_registry_result_t
write_registry_value_binary(
ebpf_registry_key_t key, _In_z_ const wchar_t* value_name, _In_reads_(value_size) uint8_t* value, size_t value_size)
{
ebpf_assert(value_name);
ebpf_assert(value);
return RegSetValueEx(key, value_name, 0, REG_BINARY, value, (DWORD)value_size);
}
_Must_inspect_result_ ebpf_registry_result_t
write_registry_value_wide_string(ebpf_registry_key_t key, _In_z_ const wchar_t* value_name, _In_z_ const wchar_t* value)
{
ebpf_assert(value_name);
ebpf_assert(value);
auto length = (wcslen(value) + 1) * sizeof(wchar_t);
return RegSetValueEx(key, value_name, 0, REG_SZ, (uint8_t*)value, (DWORD)length);
}
_Must_inspect_result_ ebpf_registry_result_t
write_registry_value_ansi_string(ebpf_registry_key_t key, _In_z_ const wchar_t* value_name, _In_z_ const char* value)
{
uint32_t result;
try {
auto wide_string = _get_wstring_from_string(value);
result = write_registry_value_wide_string(key, value_name, wide_string.c_str());
} catch (...) {
result = ERROR_NOT_ENOUGH_MEMORY;
}
return result;
}
_Must_inspect_result_ ebpf_registry_result_t
write_registry_value_dword(ebpf_registry_key_t key, _In_z_ const wchar_t* value_name, uint32_t value)
{
ebpf_assert(key);
return RegSetValueEx(key, value_name, 0, REG_DWORD, (PBYTE)&value, sizeof(value));
}
_Must_inspect_result_ ebpf_registry_result_t
create_registry_key(
ebpf_registry_key_t root_key, _In_z_ const wchar_t* sub_key, uint32_t flags, _Out_ ebpf_registry_key_t* key)
{
*key = nullptr;
if (root_key == nullptr) {
return ERROR_INVALID_PARAMETER;
}
return RegCreateKeyEx(root_key, sub_key, 0, nullptr, 0, flags, nullptr, key, nullptr);
}
_Success_(return == ERROR_SUCCESS) uint32_t open_registry_key(
ebpf_registry_key_t root_key, _In_opt_z_ const wchar_t* sub_key, uint32_t flags, _Out_ ebpf_registry_key_t* key)
{
ebpf_assert(root_key != nullptr);
_Analysis_assume_(root_key != nullptr);
return RegOpenKeyEx(root_key, sub_key, 0, flags, key);
}
_Must_inspect_result_ ebpf_registry_result_t
delete_registry_key(ebpf_registry_key_t root_key, _In_z_ const wchar_t* sub_key)
{
return RegDeleteKeyEx(root_key, sub_key, 0, 0);
}
_Must_inspect_result_ ebpf_registry_result_t
delete_registry_tree(ebpf_registry_key_t root_key, _In_opt_z_ const wchar_t* sub_key)
{
return RegDeleteTree(root_key, sub_key);
}
_Must_inspect_result_ ebpf_registry_result_t
create_registry_key_ansi(
ebpf_registry_key_t root_key, _In_z_ const char* sub_key, uint32_t flags, _Out_ ebpf_registry_key_t* key)
{
uint32_t result;
try {
auto wide_string = _get_wstring_from_string(sub_key);
result = create_registry_key(root_key, wide_string.c_str(), flags, key);
} catch (...) {
result = ERROR_NOT_ENOUGH_MEMORY;
}
return result;
}
_Must_inspect_result_ ebpf_registry_result_t
read_registry_value_string(ebpf_registry_key_t key, _In_z_ const wchar_t* value_name, _Outptr_result_z_ wchar_t** value)
{
uint32_t status = ERROR_SUCCESS;
DWORD type = REG_SZ;
DWORD value_size = 0;
wchar_t* string_value = nullptr;
*value = nullptr;
status = RegQueryValueEx(key, value_name, 0, &type, nullptr, &value_size);
if (status != ERROR_SUCCESS || type != REG_SZ) {
if (type != REG_SZ) {
status = ERROR_INVALID_PARAMETER;
}
return status;
}
string_value = (wchar_t*)ebpf_allocate((value_size + sizeof(wchar_t)));
if (string_value == nullptr) {
return ERROR_NOT_ENOUGH_MEMORY;
}
memset(string_value, 0, value_size + sizeof(wchar_t));
status = RegQueryValueEx(key, value_name, 0, &type, (PBYTE)string_value, &value_size);
if (status != ERROR_SUCCESS) {
goto Exit;
}
*value = string_value;
string_value = nullptr;
Exit:
if (string_value) {
ebpf_free(string_value);
}
return status;
}
_Must_inspect_result_ ebpf_registry_result_t
read_registry_value_dword(ebpf_registry_key_t key, _In_z_ const wchar_t* value_name, _Out_ uint32_t* value)
{
DWORD type = REG_QWORD;
DWORD value_size = sizeof(uint32_t);
return RegQueryValueEx(key, value_name, 0, &type, (PBYTE)value, &value_size);
}
_Must_inspect_result_ ebpf_registry_result_t
read_registry_value_binary(
ebpf_registry_key_t key,
_In_z_ const wchar_t* value_name,
_Out_writes_(value_size) uint8_t* value,
size_t value_size)
{
uint32_t status = NO_ERROR;
DWORD type = REG_BINARY;
DWORD local_value_size = (DWORD)value_size;
status = RegQueryValueEx(key, value_name, 0, &type, value, &local_value_size);
if (status != ERROR_SUCCESS || type != REG_BINARY || local_value_size != value_size) {
if (status != ERROR_SUCCESS) {
status = ERROR_INVALID_PARAMETER;
}
goto Exit;
}
Exit:
return status;
}
_Must_inspect_result_ ebpf_registry_result_t
convert_guid_to_string(_In_ const GUID* guid, _Out_writes_all_(string_size) wchar_t* string, size_t string_size)
{
uint32_t status = ERROR_SUCCESS;
wchar_t* value_name = nullptr;
try {
if (string_size < GUID_STRING_LENGTH + 1) {
return ERROR_INSUFFICIENT_BUFFER;
}
// Convert program type GUID to string.
RPC_STATUS rpc_status = UuidToString(guid, (RPC_WSTR*)&value_name);
if (rpc_status != RPC_S_OK) {
return ERROR_INVALID_PARAMETER;
}
std::wstring value_name_string(value_name);
// UuidToString returns string without braces. Add braces to the resulting string.
value_name_string = L"{" + value_name_string + L"}";
// Copy the buffer to the output string.
memcpy(string, value_name_string.c_str(), GUID_STRING_LENGTH * 2);
string[GUID_STRING_LENGTH] = L'\0';
} catch (...) {
status = ERROR_NOT_ENOUGH_MEMORY;
}
return status;
}
_Must_inspect_result_ ebpf_registry_result_t
convert_string_to_guid(_In_z_ const wchar_t* string, _Out_ GUID* guid)
{
uint32_t status = ERROR_SUCCESS;
// The UUID string read from registry also contains the opening and closing braces.
// Remove those before converting to UUID.
wchar_t truncated_string[GUID_STRING_LENGTH + 1] = {0};
memcpy(truncated_string, string + 1, (wcslen(string) - 2) * sizeof(wchar_t));
// Convert program type string to GUID
auto rpc_status = UuidFromString((RPC_WSTR)truncated_string, guid);
if (rpc_status != RPC_S_OK) {
status = ERROR_INVALID_PARAMETER;
}
return status;
}