37DLL_EXPORT
bool save_preferences(
bool commit,
38 const wchar_t *deploy_key,
39 const wchar_t *output_dir,
40 const wchar_t *output_file,
43 const wchar_t *specified_path,
44 enum OUTPUT_FORMAT format,
46 bool using_default_writer, writer_was_setup, writer_was_torn_down;
47 using_default_writer = writer_was_setup = writer_was_torn_down =
false;
48 if (!writer || !writer->write_output) {
49 debug_print(L
"Using default writer.");
50 writer = get_default_writer();
51 using_default_writer =
true;
54 wchar_t full_output_dir[MAX_PATH];
55 bool writing_to_stdout = !wcscmp(L
"-", output_file);
56 if (!_wfullpath(full_output_dir, output_dir, MAX_PATH)) {
59 if (!writing_to_stdout) {
60 debug_print(L
"Output directory: %ls\n", full_output_dir);
62 debug_print(L
"Writing to standard output.\n");
64 if (!writing_to_stdout && !create_dir_recursive(full_output_dir)) {
67 PathAppend(full_output_dir, output_file);
68 full_output_dir[MAX_PATH - 1] = L
'\0';
69 if (writer->setup && !writer->setup(writer, writing_to_stdout, full_output_dir)) {
72 writer_was_setup =
true;
73 const wchar_t *prior_stem = hk == HKEY_CLASSES_ROOT ? L
"HKCR" :
74 hk == HKEY_CURRENT_CONFIG ? L
"HKCC" :
75 hk == HKEY_CURRENT_USER ? L
"HKCU" :
76 hk == HKEY_LOCAL_MACHINE ? L
"HKLM" :
77 hk == HKEY_USERS ? L
"HKU" :
78 hk == HKEY_DYN_DATA ? L
"HKDD" :
80 if (format == OUTPUT_FORMAT_C) {
82 writer->write_output(writer, C_PREAMBLE, (DWORD)SIZEOF_C_PREAMBLE, &written);
84 ret = write_key_filtered_recursive(hk,
nullptr, max_depth, 0, prior_stem, format, writer);
85 if (writer_was_setup && writer->teardown) {
86 writer->teardown(writer);
87 writer_was_torn_down =
true;
89 if (ret && commit && !writing_to_stdout) {
90 git_commit(output_dir, deploy_key);
96 if (!writer_was_torn_down && writer_was_setup && writer->teardown) {
97 writer->teardown(writer);
99 if (using_default_writer) {
105DLL_EXPORT
bool export_single_value(HKEY top_key,
106 const wchar_t *reg_path,
107 enum OUTPUT_FORMAT format,
109 bool using_default_writer, writer_was_setup;
110 using_default_writer = writer_was_setup =
false;
111 if (!writer || !writer->write_output) {
112 debug_print(L
"Using default writer.");
113 writer = get_default_writer();
114 using_default_writer =
true;
117 wchar_t *m_reg_path =
nullptr;
118 wchar_t *value_name =
nullptr;
119 char *data =
nullptr;
124 size_t reg_path_len = wcslen(reg_path) + 1;
125 m_reg_path = calloc(reg_path_len, WL);
129 wmemcpy(m_reg_path, reg_path, reg_path_len);
130 wchar_t *first_backslash = wcschr(m_reg_path, L
'\\');
131 if (!first_backslash) {
135 wchar_t *subkey = first_backslash + 1;
136 HKEY starting_key = HKEY_CURRENT_USER;
137 wchar_t *last_backslash = wcsrchr(m_reg_path,
'\\');
138 wchar_t *value_name_p = last_backslash + 1;
139 size_t value_name_len = wcslen(value_name_p) + 1;
140 value_name = calloc(value_name_len, WL);
144 wmemset(value_name, L
'\0', value_name_len);
145 wmemcpy(value_name, value_name_p, value_name_len);
146 *last_backslash = L
'\0';
147 if (RegOpenKeyEx(top_key, subkey, 0, KEY_READ, &starting_key) != ERROR_SUCCESS) {
148 debug_print(L
"Invalid subkey: '%ls'.\n", subkey);
151 size_t buf_size = 8192;
152 data = malloc(buf_size);
156 DWORD reg_type = REG_NONE;
157 LSTATUS reg_query_value_ret = RegQueryValueEx(
158 starting_key, value_name,
nullptr, ®_type, (LPBYTE)data, (LPDWORD)&buf_size);
159 if (reg_query_value_ret == ERROR_MORE_DATA) {
160 debug_print(L
"Value too large (%ls\\%ls).\n", subkey, value_name);
163 if (reg_query_value_ret != ERROR_SUCCESS) {
164 debug_print(L
"Invalid value name '%ls'.\n", value_name);
167 if (writer->setup && !writer->setup(writer,
true,
nullptr)) {
170 writer_was_setup =
true;
172 case OUTPUT_FORMAT_REG:
173 if (!do_write_reg_command(writer, reg_path, value_name, data, buf_size, reg_type)) {
177 case OUTPUT_FORMAT_C:
178 if (!do_write_c_reg_code(writer, reg_path, value_name, data, buf_size, reg_type)) {
182 case OUTPUT_FORMAT_C_SHARP:
183 if (!do_write_c_sharp_reg_code(writer, reg_path, value_name, data, buf_size, reg_type)) {
187 case OUTPUT_FORMAT_POWERSHELL:
188 if (!do_write_powershell_reg_code(writer, reg_path, value_name, data, buf_size, reg_type)) {
200 if (writer_was_setup && writer->teardown) {
201 writer->teardown(writer);
203 if (using_default_writer) {