3#include "io_default_writer.h"
7bool write_output(
wchar_t *out,
bool use_crlf, writer_t *writer) {
9 char *mb_out =
nullptr;
12 (size_t)WideCharToMultiByte(CP_UTF8, 0, out, -1,
nullptr, 0,
nullptr,
nullptr);
16 size_t total_size = req_size + (use_crlf ? 1 : 0);
17 mb_out = malloc(total_size);
21 memset(mb_out, 0, total_size);
22 if (!WideCharToMultiByte(CP_UTF8, 0, out, -1, mb_out, (
int)total_size,
nullptr,
nullptr)) {
24 debug_print(L
"Skipping possibly malformed wide character data.\n");
28 mb_out[total_size - 2] =
'\r';
30 mb_out[total_size - 1] =
'\n';
31 ret = writer->write_output(writer, mb_out, total_size, &written);
38 return ret && written > 0;
41bool do_writes(HKEY hk,
42 long unsigned n_values,
43 const wchar_t *full_path,
44 enum OUTPUT_FORMAT format,
47 wchar_t *value =
nullptr;
51 if (!writer || !full_path) {
59 value = calloc(MAX_VALUE_NAME, WL);
63 if (format == OUTPUT_FORMAT_UNKNOWN) {
66 LSTATUS enum_value_ret = ERROR_SUCCESS;
68 for (i = 0; i < n_values; i++) {
69 data_len =
sizeof(data);
70 wmemset(value, L
'\0', MAX_VALUE_NAME);
71 memset(data, 0, 8192);
72 value_len = MAX_VALUE_NAME * WL;
74 enum_value_ret = RegEnumValue(
75 hk, i, value, (LPDWORD)&value_len, 0, ®_type, (LPBYTE)data, (LPDWORD)&data_len);
76 if (enum_value_ret == ERROR_MORE_DATA) {
79 if (enum_value_ret == ERROR_NO_MORE_ITEMS) {
83 bool write_ret =
false;
85 case OUTPUT_FORMAT_REG:
86 write_ret = do_write_reg_command(writer, full_path, value, data, data_len, reg_type);
89 write_ret = do_write_c_reg_code(writer, full_path, value, data, data_len, reg_type);
91 case OUTPUT_FORMAT_C_SHARP:
93 do_write_c_sharp_reg_code(writer, full_path, value, data, data_len, reg_type);
95 case OUTPUT_FORMAT_POWERSHELL:
97 do_write_powershell_reg_code(writer, full_path, value, data, data_len, reg_type);
115bool write_key_filtered_recursive(HKEY hk,
119 const wchar_t *prior_stem,
120 enum OUTPUT_FORMAT format,
123 wchar_t *ach_key, *full_path;
124 ach_key = full_path =
nullptr;
125 if (depth >= max_depth) {
126 debug_print(L
"%ls: Skipping %ls due to depth limit of %d.\n", prior_stem, stem, max_depth);
131 size_t full_path_len = WL * MAX_KEY_LENGTH;
132 full_path = calloc(MAX_KEY_LENGTH, WL);
136 wmemset(full_path, L
'\0', MAX_KEY_LENGTH);
137 size_t prior_stem_len = wcslen(prior_stem) * WL;
138 size_t stem_len = stem ? wcslen(stem) : 0;
139 if ((prior_stem_len + (stem_len * WL) + 2) > (full_path_len - 2)) {
140 debug_print(L
"%ls: Skipping %ls because of length limitation.\n", prior_stem, stem);
144 memcpy(full_path, prior_stem, prior_stem_len);
146 wcsncat(full_path, L
"\\", 1);
147 wcsncat(full_path, stem, stem_len);
149 if (wcsstr(full_path, L
"Classes\\Extensions\\ContractId\\Windows.BackgroundTasks\\PackageId") ||
150 wcsstr(full_path, L
"CloudStore\\Store\\Cache\\") ||
152 L
"CurrentVersion\\Authentication\\LogonUI\\Notifications\\BackgroundCapability") ||
153 wcsstr(full_path, L
"CurrentVersion\\CloudStore\\Store\\DefaultAccount\\Current\\") ||
154 wcsstr(full_path, L
"Explorer\\ComDlg32\\CIDSizeMRU") ||
155 wcsstr(full_path, L
"Explorer\\ComDlg32\\FirstFolder") ||
156 wcsstr(full_path, L
"Explorer\\ComDlg32\\LastVisitedPidlMRU") ||
157 wcsstr(full_path, L
"Explorer\\ComDlg32\\OpenSavePidlMRU") ||
158 wcsstr(full_path, L
"IrisService\\Cache") ||
159 wcsstr(full_path, L
"Microsoft\\Windows\\Shell\\Bags") ||
160 wcsstr(full_path, L
"Windows\\Shell\\BagMRU") ||
161 wcsstr(full_path, L
"Windows\\Shell\\MuiCache")) {
162 debug_print(L
"%ls: Skipping %ls due to filter.\n", prior_stem, stem);
163 errno = EKEYREJECTED;
166 if (RegOpenKeyEx(hk, stem, 0, KEY_READ, &hk_out) == ERROR_SUCCESS) {
167 DWORD n_sub_keys = 0;
169 LSTATUS ret_code = RegQueryInfoKey(hk_out,
181 if (ret_code != ERROR_SUCCESS) {
182 debug_print(L
"RegQueryInfoKey failed (stem = %ls).\n", stem);
186 size_t ach_key_len = 0;
187 ach_key = calloc(MAX_KEY_LENGTH, WL);
192 for (i = 0; i < n_sub_keys; i++) {
193 ach_key_len = MAX_KEY_LENGTH;
194 wmemset(ach_key, L
'\0', MAX_KEY_LENGTH);
195 ret_code = RegEnumKeyEx(
196 hk_out, i, ach_key, (LPDWORD)&ach_key_len,
nullptr,
nullptr,
nullptr,
nullptr);
197 if (ret_code == ERROR_SUCCESS) {
198 if (!write_key_filtered_recursive(
199 hk_out, ach_key, max_depth, depth + 1, full_path, format, writer)) {
203 debug_print(L
"%ls: Skipping %ls because RegEnumKeyEx() failed.\n",
209 debug_print(L
"%ls: No subkeys in %ls.\n", prior_stem, stem);
212 if (!do_writes(hk_out, n_values, full_path, format, writer)) {
216 debug_print(L
"%ls: No values in %ls.\n", prior_stem, stem);
220 debug_print(L
"%ls: Skipping %ls. Does the location exist?\n", prior_stem, stem);