6static wchar_t *get_top_key_string(
const wchar_t *reg_path) {
7 wchar_t *out = calloc(20, WL);
11 wmemset(out, L
'\0', 20);
12 if (!_wcsnicmp(reg_path, L
"HKCU", 4) || !_wcsnicmp(reg_path, L
"HKEY_CURRENT_USER", 17)) {
13 wmemcpy(out, L
"HKEY_CURRENT_USER", 17);
14 }
else if (!_wcsnicmp(reg_path, L
"HKCR", 4) || !_wcsnicmp(reg_path, L
"HKEY_CLASSES_ROOT", 17)) {
15 wmemcpy(out, L
"HKEY_CLASSES_ROOT", 17);
16 }
else if (!_wcsnicmp(reg_path, L
"HKLM", 4) ||
17 !_wcsnicmp(reg_path, L
"HKEY_LOCAL_MACHINE", 18)) {
18 wmemcpy(out, L
"HKEY_LOCAL_MACHINE", 18);
19 }
else if (!_wcsnicmp(reg_path, L
"HKCC", 4) ||
20 !_wcsnicmp(reg_path, L
"HKEY_CURRENT_CONFIG", 19)) {
21 wmemcpy(out, L
"HKEY_CURRENT_CONFIG", 19);
22 }
else if (!_wcsnicmp(reg_path, L
"HKU", 3) || !_wcsnicmp(reg_path, L
"HKEY_USERS", 10)) {
23 wmemcpy(out, L
"HKEY_USERS", 10);
24 }
else if (!_wcsnicmp(reg_path, L
"HKDD", 4) || !_wcsnicmp(reg_path, L
"HKEY_DYN_DATA", 13)) {
25 wmemcpy(out, L
"HKEY_DYN_DATA", 13);
33static wchar_t *escape_for_c(
const wchar_t *input,
bool escape_null,
size_t length) {
34 if (input ==
nullptr || (escape_null && length == 0)) {
38 size_t n_chars = !escape_null ? wcslen(input) : length;
40 size_t new_n_chars = 0;
41 for (i = 0; i < n_chars; i++) {
43 if (input[i] == L
'"' || input[i] == L
'\\' || (escape_null && input[i] == L
'\0')) {
47 wchar_t *out = calloc(new_n_chars + 1, WL);
51 wmemset(out, L
'\0', new_n_chars + 1);
52 if (n_chars == new_n_chars) {
53 wmemcpy(out, input, new_n_chars + 1);
56 for (i = 0, j = 0; i < n_chars && j < new_n_chars; i++, j++) {
57 if (input[i] == L
'"' || input[i] == L
'\\' || (escape_null && input[i] == L
'\0')) {
60 out[j] = (escape_null && input[i] == L
'\0') ? L
'0' : input[i];
65static wchar_t *convert_data_for_c(DWORD reg_type,
const char *data,
size_t data_len) {
66 if (reg_type == REG_BINARY) {
69 size_t n_bin_chars = 7 * data_len;
70 size_t new_len = n_bin_chars + 1;
71 wchar_t *bin = calloc(new_len, WL);
76 wmemset(bin, L
'\0', new_len);
77 for (i = 0, j = 0; i < data_len; i++) {
78 wmemset(conv, L
'\0', 7);
79 _snwprintf(conv, 7, L
"0x%02x%ls", data[i] & 0xFF, i < (data_len - 1) ? L
", " : L
"");
80 wcsncat(bin + j, conv, i < (data_len - 1) ? 6 : 4);
81 j += i < (data_len - 1) ? 6 : 4;
83 size_t s_size = new_len + 4;
84 wchar_t *out = calloc(s_size, WL);
89 wmemset(out, L
'\0', s_size);
90 _snwprintf(out, s_size, L
"{ %ls }", bin);
94 if (reg_type == REG_EXPAND_SZ || reg_type == REG_SZ) {
95 wchar_t *escaped = escape_for_c((
wchar_t *)data,
false, 0);
99 size_t escaped_len = wcslen(escaped);
100 size_t total_size = escaped_len + 1;
101 wchar_t *out = calloc(total_size, WL);
105 wmemset(out, L
'\0', total_size);
106 _snwprintf(out, escaped ? total_size : 5, L
"%ls", escaped ? escaped : L
"NULL");
110 if (reg_type == REG_MULTI_SZ) {
111 wchar_t *w_data = (
wchar_t *)data;
112 size_t w_data_len = (data_len % WL == 0) ? data_len / WL : (data_len / WL) + 1;
113 size_t real_len = determine_multi_sz_size(w_data, w_data_len);
115 wchar_t *escaped = escape_for_c((
wchar_t *)data,
true, real_len);
119 int req_size = _snwprintf(
nullptr, 0, L
"%ls\\0", escaped) + 1;
120 wchar_t *out = calloc((
size_t)req_size, WL);
124 _snwprintf(out, (
size_t)req_size, L
"%ls\\0", escaped);
128 debug_print(L
"Skipping incorrectly stored REG_MULTI_SZ (length = %lu, w_data_len = %lu).\n",
133 if (reg_type == REG_DWORD) {
134 int req_size = _snwprintf(
nullptr, 0, L
"%lu", *(DWORD *)data);
135 wchar_t *out = calloc((
size_t)(req_size + 1), WL);
139 wmemset(out, 0, (
size_t)(req_size + 1));
140 _snwprintf(out, (
size_t)req_size + 1, L
"%lu", *(DWORD *)data);
143 if (reg_type == REG_QWORD) {
144 int req_size = _snwprintf(
nullptr, 0, L
"%llu", *(UINT64 *)data);
145 wchar_t *out = calloc((
size_t)(req_size + 1), WL);
149 wmemset(out, 0, (
size_t)(req_size + 1));
150 _snwprintf(out, (
size_t)(req_size + 1), L
"%llu", *(UINT64 *)data);
157bool do_write_c_reg_code(writer_t *writer,
158 const wchar_t *full_path,
162 unsigned long type) {
164 wchar_t *escaped_key, *escaped_d, *escaped_prop, *top_key_s, *out;
165 escaped_key = escaped_d = escaped_prop = top_key_s = out =
nullptr;
166 wchar_t *first_backslash = wcschr(full_path, L
'\\');
167 if (!first_backslash) {
170 wchar_t *subkey = first_backslash + 1;
171 escaped_key = escape_for_c(subkey,
false, 0);
172 escaped_d = convert_data_for_c(type, value, data_len);
173 escaped_prop = escape_for_c(prop,
false, 0);
174 top_key_s = get_top_key_string(full_path);
175 if (!escaped_key || !top_key_s) {
178 if (type == REG_MULTI_SZ && !escaped_d) {
181 wchar_t reg_type[14];
182 memset(reg_type, 0,
sizeof(reg_type));
185 wcsncpy(reg_type, L
"REG_NONE", 8);
188 wcsncpy(reg_type, L
"REG_BINARY", 10);
191 wcsncpy(reg_type, L
"REG_SZ", 6);
194 wcsncpy(reg_type, L
"REG_EXPAND_SZ", 13);
197 wcsncpy(reg_type, L
"REG_MULTI_SZ", 12);
200 wcsncpy(reg_type, L
"REG_DWORD", 9);
203 wcsncpy(reg_type, L
"REG_QWORD", 9);
209 if (type == REG_DWORD || type == REG_QWORD) {
210 int req_size = _snwprintf(
nullptr,
212 C_REGSETKEYVALUEW_TEMPLATE_NUMERIC,
213 type == REG_DWORD ? L
"d" : L
"q",
217 escaped_prop ? escaped_prop : L
"",
219 type == REG_DWORD ? L
"d" : L
"q",
220 type == REG_DWORD ? KEYWORD_DWORD : KEYWORD_QWORD);
221 out = calloc((
size_t)req_size + 1, WL);
225 wmemset(out, L
'\0', (
size_t)(req_size + 1));
227 (
size_t)(req_size + 1),
228 C_REGSETKEYVALUEW_TEMPLATE_NUMERIC,
229 type == REG_DWORD ? L
"d" : L
"q",
230 escaped_d ? escaped_d : L
"",
233 escaped_prop ? escaped_prop : L
"",
235 type == REG_DWORD ? L
"d" : L
"q",
236 type == REG_DWORD ? KEYWORD_DWORD : KEYWORD_QWORD);
237 }
else if (type == REG_SZ || type == REG_EXPAND_SZ || type == REG_MULTI_SZ) {
238 int req_size = _snwprintf(
nullptr,
240 C_REGSETKEYVALUEW_TEMPLATE_SZ,
243 escaped_prop ? escaped_prop : L
"",
245 escaped_d ? escaped_d : L
"",
247 out = calloc((
size_t)req_size + 1, WL);
251 wmemset(out, L
'\0', (
size_t)req_size + 1);
253 (
size_t)req_size + 1,
254 C_REGSETKEYVALUEW_TEMPLATE_SZ,
257 escaped_prop ? escaped_prop : L
"",
259 escaped_d ? escaped_d : L
"",
261 }
else if (type == REG_NONE) {
262 int req_size = _snwprintf(
nullptr,
264 C_REGSETKEYVALUEW_TEMPLATE_NONE,
267 escaped_prop ? escaped_prop : L
"");
268 out = calloc((
size_t)req_size + 1, WL);
272 wmemset(out, L
'\0', (
size_t)req_size + 1);
274 (
size_t)req_size + 1,
275 C_REGSETKEYVALUEW_TEMPLATE_NONE,
278 escaped_prop ? escaped_prop : L
"");
279 }
else if (type == REG_BINARY) {
280 int req_size = _snwprintf(
nullptr,
282 C_REGSETKEYVALUEW_TEMPLATE_BINARY,
286 escaped_prop ? escaped_prop : L
"",
288 out = calloc((
size_t)req_size + 1, WL);
292 wmemset(out, L
'\0', (
size_t)req_size + 1);
294 (
size_t)req_size + 1,
295 C_REGSETKEYVALUEW_TEMPLATE_BINARY,
299 escaped_prop ? escaped_prop : L
"",
306 ret = write_output(out,
false, writer);
320static wchar_t *convert_data_for_c_sharp(DWORD reg_type,
const char *data,
size_t data_len) {
321 wchar_t *out, *escaped, *strings;
322 out = escaped = strings =
nullptr;
323 if (reg_type == REG_BINARY || reg_type == REG_NONE || reg_type == REG_QWORD ||
324 reg_type == REG_DWORD) {
325 out = convert_data_for_c(reg_type, data, data_len);
331 if (reg_type == REG_SZ || reg_type == REG_EXPAND_SZ) {
332 escaped = convert_data_for_c(reg_type, data, data_len);
336 size_t escaped_len = wcslen(escaped);
337 out = calloc(escaped_len + 3, WL);
341 _snwprintf(out, escaped_len + 3, L
"\"%ls\"", escaped);
344 if (reg_type != REG_MULTI_SZ) {
348 wchar_t *w_data = (
wchar_t *)data;
349 size_t w_data_len = (data_len % WL == 0) ? data_len / WL : (data_len / WL) + 1;
350 size_t real_len = determine_multi_sz_size(w_data, w_data_len);
352 debug_print(L
"Skipping incorrectly stored REG_MULTI_SZ (length = %lu, w_data_len = %lu).\n",
358 size_t strings_size = 0;
359 for (i = 0; i < w_data_len; i++) {
361 if (w_data[i] == L
'"' || w_data[i] == L
'\\') {
363 }
else if (w_data[i] == L
'\0') {
367 size_t total_size = 5 + strings_size;
368 strings = calloc(strings_size + 1, WL);
372 wmemset(strings, L
'\0', strings_size + 1);
374 for (i = 0, j = 1; i < w_data_len - 2 && j < strings_size; i++, j++) {
375 if (w_data[i] == L
'\0') {
377 if (j < (strings_size - 1)) {
384 if (w_data[i] == L
'"' || w_data[i] == L
'\\') {
385 strings[j++] = L
'\\';
387 strings[j] = w_data[i];
389 out = calloc(total_size, WL);
393 _snwprintf(out, total_size - 1, L
"{ %ls\" }", strings);
403bool do_write_c_sharp_reg_code(writer_t *writer,
404 const wchar_t *full_path,
408 unsigned long type) {
410 wchar_t *out, *escaped_key, *escaped_d, *escaped_prop, *top_key_s;
411 out = escaped_key = escaped_d = escaped_prop = top_key_s =
nullptr;
412 wchar_t *first_backslash = wcschr(full_path, L
'\\');
413 if (!first_backslash) {
416 wchar_t *subkey = first_backslash + 1;
417 escaped_key = escape_for_c(subkey,
false, 0);
418 escaped_d = convert_data_for_c_sharp(type, value, data_len);
419 escaped_prop = escape_for_c(prop,
false, 0);
420 top_key_s = get_top_key_string(full_path);
421 if (!escaped_key || !top_key_s) {
424 if (type == REG_MULTI_SZ && !escaped_d) {
427 wchar_t reg_type[33];
428 memset(reg_type, 0,
sizeof(reg_type));
431 wcsncpy(reg_type, L
", RegistryValueKind.None", 24);
434 wcsncpy(reg_type, L
", RegistryValueKind.Binary", 26);
437 wcsncpy(reg_type, L
", RegistryValueKind.ExpandString", 32);
444 wcsncpy(reg_type, L
", RegistryValueKind.DWord", 25);
447 wcsncpy(reg_type, L
", RegistryValueKind.QWord", 25);
453 int req_size = _snwprintf(
nullptr,
455 C_SHARP_REGISTRY_SET_VALUE_TEMPLATE,
458 escaped_prop ? escaped_prop : L
"",
459 escaped_d ? escaped_d :
460 type == REG_NONE ? L
"null" :
463 out = calloc((
size_t)req_size + 1, WL);
467 wmemset(out, L
'\0', (
size_t)req_size + 1);
469 (
size_t)req_size + 1,
470 C_SHARP_REGISTRY_SET_VALUE_TEMPLATE,
473 escaped_prop ? escaped_prop : L
"",
474 escaped_d ? escaped_d :
475 type == REG_NONE ? L
"null" :
478 ret = write_output(out,
false, writer);