eBPF for Windows
ebpf_registry_helper.h
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation
2 // SPDX-License-Identifier: MIT
3 
4 #pragma once
5 
6 #include "framework.h"
7 
8 #define __return_type NTSTATUS
9 #define _SUCCESS STATUS_SUCCESS
10 #define IS_SUCCESS(x) (NT_SUCCESS(x))
11 
12 #define REG_CREATE_FLAGS 0
13 #define GUID_STRING_LENGTH 38 // not including the null terminator.
14 
15 typedef _Return_type_success_(NT_SUCCESS(return )) uint32_t ebpf_registry_result_t;
16 
17 typedef HANDLE ebpf_registry_key_t;
18 
19 static void
21 {
22  ZwClose(key);
23 }
24 
25 static NTSTATUS
26 convert_guid_to_string(_In_ const GUID* guid, _Out_writes_all_(string_length) wchar_t* string, size_t string_length)
27 {
28  UNICODE_STRING unicode_string = {0};
29 
30  NTSTATUS status = RtlStringFromGUID(guid, &unicode_string);
31  if (status != STATUS_SUCCESS) {
32  goto Exit;
33  }
34 
35  if (string_length < GUID_STRING_LENGTH + 1) {
36  status = STATUS_BUFFER_TOO_SMALL;
37  goto Exit;
38  }
39 
40  __analysis_assume(unicode_string.MaximumLength >= GUID_STRING_LENGTH * sizeof(wchar_t));
41  __analysis_assume(unicode_string.Buffer != NULL);
42 
43  // Copy the buffer to the output string.
44  memcpy(string, unicode_string.Buffer, GUID_STRING_LENGTH * sizeof(wchar_t));
45  string[GUID_STRING_LENGTH] = L'\0';
46 
47 Exit:
48  if (unicode_string.Buffer != NULL) {
49  RtlFreeUnicodeString(&unicode_string);
50  }
51  return status;
52 }
53 
54 static _Must_inspect_result_ ebpf_registry_result_t
56  ebpf_registry_key_t key, _In_z_ const wchar_t* value_name, _In_reads_(value_size) uint8_t* value, size_t value_size)
57 {
58  UNICODE_STRING unicode_value_name;
59 
60  RtlInitUnicodeString(&unicode_value_name, value_name);
61  return ZwSetValueKey(key, &unicode_value_name, 0, REG_BINARY, value, (ULONG)value_size);
62 }
63 
64 static _Must_inspect_result_ ebpf_registry_result_t
65 write_registry_value_ansi_string(ebpf_registry_key_t key, _In_z_ const wchar_t* value_name, _In_z_ const char* value)
66 {
67  NTSTATUS status;
68  UNICODE_STRING unicode_value;
69  UNICODE_STRING unicode_value_name;
70 
71  ANSI_STRING ansi_string;
72  RtlInitAnsiString(&ansi_string, value);
73 
74  status = RtlAnsiStringToUnicodeString(&unicode_value, &ansi_string, TRUE);
75  if (!NT_SUCCESS(status)) {
76  goto Exit;
77  }
78  RtlInitUnicodeString(&unicode_value_name, value_name);
79 
80  status = ZwSetValueKey(key, &unicode_value_name, 0, REG_SZ, unicode_value.Buffer, unicode_value.Length);
81  RtlFreeUnicodeString(&unicode_value);
82 
83 Exit:
84  return status;
85 }
86 
87 static _Must_inspect_result_ ebpf_registry_result_t
88 write_registry_value_dword(ebpf_registry_key_t key, _In_z_ const wchar_t* value_name, uint32_t value)
89 {
90  UNICODE_STRING unicode_name;
91  RtlInitUnicodeString(&unicode_name, value_name);
92  return ZwSetValueKey(key, &unicode_name, 0, REG_DWORD, &value, sizeof(uint32_t));
93 }
94 
95 static _Must_inspect_result_ ebpf_registry_result_t
97  ebpf_registry_key_t root_key, _In_z_ const wchar_t* sub_key, uint32_t flags, _Out_ ebpf_registry_key_t* key)
98 {
99  NTSTATUS status = STATUS_SUCCESS;
100  UNICODE_STRING registry_path;
101  OBJECT_ATTRIBUTES object_attributes = {0};
102 
103  UNREFERENCED_PARAMETER(flags);
104 
105  RtlInitUnicodeString(&registry_path, sub_key);
106  InitializeObjectAttributes(
107  &object_attributes, &registry_path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, root_key, NULL);
108 
109  status = ZwCreateKey(key, KEY_WRITE, &object_attributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
110 
111  return status;
112 }
113 
114 static _Must_inspect_result_ ebpf_registry_result_t
116  ebpf_registry_key_t root_key, _In_z_ const char* sub_key, uint32_t flags, _Out_ ebpf_registry_key_t* key)
117 {
118  NTSTATUS status = STATUS_SUCCESS;
119  UNICODE_STRING registry_path;
120  OBJECT_ATTRIBUTES object_attributes = {0};
121  ANSI_STRING ansi_string;
122  RtlInitAnsiString(&ansi_string, sub_key);
123 
124  UNREFERENCED_PARAMETER(flags);
125  *key = NULL;
126 
127  status = RtlAnsiStringToUnicodeString(&registry_path, &ansi_string, TRUE);
128  if (!NT_SUCCESS(status)) {
129  goto Exit;
130  }
131 
132  InitializeObjectAttributes(
133  &object_attributes, &registry_path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, root_key, NULL);
134 
135  status = ZwCreateKey(key, KEY_WRITE, &object_attributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
136  RtlFreeUnicodeString(&registry_path);
137 
138 Exit:
139  return status;
140 }
uint8_t GUID[16]
Definition: ebpf_windows.h:13
HANDLE ebpf_registry_key_t
Definition: ebpf_registry_helper.h:17
uint32_t ebpf_registry_result_t
Definition: ebpf_registry_helper.h:15
#define GUID_STRING_LENGTH
Definition: ebpf_registry_helper.h:13
_Must_inspect_result_ ebpf_registry_result_t create_registry_key_ansi(ebpf_registry_key_t root_key, const char *sub_key, uint32_t flags, ebpf_registry_key_t *key)
void close_registry_key(ebpf_registry_key_t key)
_Must_inspect_result_ ebpf_registry_result_t convert_guid_to_string(const GUID *guid, _Out_writes_all_(string_size) wchar_t *string, size_t string_size)
_Must_inspect_result_ ebpf_registry_result_t write_registry_value_dword(ebpf_registry_key_t key, const wchar_t *value_name, uint32_t value)
_Must_inspect_result_ ebpf_registry_result_t write_registry_value_ansi_string(ebpf_registry_key_t key, const wchar_t *value_name, const char *value)
_Must_inspect_result_ ebpf_registry_result_t write_registry_value_binary(ebpf_registry_key_t key, const wchar_t *value_name, _In_reads_(value_size) uint8_t *value, size_t value_size)
_Must_inspect_result_ ebpf_registry_result_t create_registry_key(ebpf_registry_key_t root_key, const wchar_t *sub_key, uint32_t flags, ebpf_registry_key_t *key)