28 if (!_wcsnicmp(reg_path, L
"HKCU", 4) || !_wcsnicmp(reg_path, L
"HKEY_CURRENT_USER", 17)) {
29 return HKEY_CURRENT_USER;
31 if (!_wcsnicmp(reg_path, L
"HKCR", 4) || !_wcsnicmp(reg_path, L
"HKEY_CLASSES_ROOT", 17)) {
32 return HKEY_CLASSES_ROOT;
34 if (!_wcsnicmp(reg_path, L
"HKLM", 4) || !_wcsnicmp(reg_path, L
"HKEY_LOCAL_MACHINE", 18)) {
35 return HKEY_LOCAL_MACHINE;
37 if (!_wcsnicmp(reg_path, L
"HKCC", 4) || !_wcsnicmp(reg_path, L
"HKEY_CURRENT_CONFIG", 19)) {
38 return HKEY_CURRENT_CONFIG;
40 if (!_wcsnicmp(reg_path, L
"HKU", 3) || !_wcsnicmp(reg_path, L
"HKEY_USERS", 10)) {
43 if (!_wcsnicmp(reg_path, L
"HKDD", 4) || !_wcsnicmp(reg_path, L
"HKEY_DYN_DATA", 13)) {
50int wmain(
int argc,
wchar_t *argv[]) {
52 int ret = EXIT_SUCCESS;
53 HKEY starting_key = HKEY_CURRENT_USER;
57 char *as_char =
nullptr;
58 wchar_t *argv0 = argv[0];
59 wchar_t *deploy_key =
nullptr;
60 wchar_t *format =
nullptr;
61 wchar_t *output_dir =
nullptr;
62 wchar_t *output_file =
nullptr;
63 bool output_dir_specified =
false;
65 if (ARG_LONG(
"deploy-key"))
67 deploy_key = ARG_VAL();
69 else if (ARG_LONG(
"commit"))
case 'c': {
73 else if (ARG_LONG(
"debug"))
case 'd': {
77 else if (ARG_LONG(
"output-file"))
case 'f': {
78 output_file = ARG_VAL();
80 else if (ARG_LONG(
"output-dir"))
case 'o': {
81 output_dir = ARG_VAL();
82 output_dir_specified =
true;
84 else if (ARG_LONG(
"format"))
case 'F': {
87 else if (ARG_LONG(
"max-depth"))
case 'm': {
88 wchar_t *val = ARG_VAL();
89 size_t w_len = wcslen(val);
90 as_char = malloc(w_len + 1);
92 fprintf(stderr,
"Memory error.\n");
95 memset(as_char, 0, w_len + 1);
96 wcstombs(as_char, val, w_len);
97 max_depth = atoi(as_char);
99 else if (ARG_LONG(
"help"))
case 'h':
101 PathStripPath(argv0);
102 wprintf(L
"Usage: %ls [OPTION...] [REG_PATH]\n", argv0);
103 wprintf(L
"\nIf a path to a value name is specified, the output directory argument is "
104 L
"ignored and the line is printed to\nstandard output.\n\n");
106 puts(
" -F, --format=FORMAT Format to output. Options: c, cs, c#, ps, ps1, "
107 "powershell, reg. Default: reg.");
108 puts(
" -K, --deploy-key Deploy key for committing.");
109 puts(
" -c, --commit Commit changes.");
110 puts(
" -d, --debug Enable debug logging.");
111 puts(
" -f, --output-file Output filename.");
112 puts(
" -m, --max-depth=INT Set maximum depth.");
113 puts(
" -o, --output-dir Output directory.");
114 puts(
" -h, --help Display this help and exit.");
120 L
"%ls: invalid option '%ls'\n"
121 L
"Try '%s --help' for more information.\n",
129 wchar_t *reg_path = *argv;
130 enum OUTPUT_FORMAT output_format_e =
131 (!format || !_wcsicmp(L
"reg", format)) ? OUTPUT_FORMAT_REG :
132 (!_wcsicmp(L
"c#", format) || !_wcsicmp(L
"cs", format) || !_wcsicmp(L
"csharp", format)) ?
133 OUTPUT_FORMAT_C_SHARP :
134 (!_wcsicmp(L
"powershell", format) || !_wcsicmp(L
"ps", format) ||
135 !_wcsicmp(L
"ps1", format)) ?
136 OUTPUT_FORMAT_POWERSHELL :
137 (format[0] == L
'c' || format[0] == L
'C') ? OUTPUT_FORMAT_C :
138 OUTPUT_FORMAT_UNKNOWN;
139 if (output_format_e == OUTPUT_FORMAT_UNKNOWN) {
140 fwprintf(stderr, L
"Unknown format specified: %ls\n", format);
144 size_t len = wcslen(reg_path);
146 (reg_path[len - 1] == L
'\\' && reg_path[len - 2] == L
':') || reg_path[len - 1] == L
':';
147 if (reg_path[len - 1] == L
'\\' && reg_path[len - 2] == L
':') {
148 reg_path[len - 2] = L
'\0';
149 }
else if (reg_path[len - 1] == L
':') {
150 reg_path[len - 1] = L
'\0';
154 fwprintf(stderr, L
"Invalid top-level key in '%ls'.\n", reg_path);
158 wchar_t *subkey = wcschr(reg_path, L
'\\') + 1;
159 if (RegOpenKeyEx(top_key, subkey, 0, KEY_READ, &starting_key) != ERROR_SUCCESS) {
161 ret = export_single_value(top_key, reg_path, output_format_e,
nullptr) ?
169 output_dir = calloc(MAX_PATH, WL);
171 fprintf(stderr,
"Failed to allocate memory.\n");
174 wmemset(output_dir, L
'\0', MAX_PATH);
175 if (SUCCEEDED(SHGetFolderPath(
nullptr, CSIDL_APPDATA,
nullptr, 0, output_dir))) {
176 PathAppend(output_dir, L
"prefs-export");
178 output_dir[MAX_PATH - 1] = L
'\0';
180 debug_print_enabled = debug;
181 bool success = save_preferences(
185 output_file ? output_file :
186 (output_format_e == OUTPUT_FORMAT_C ? L
"exec-reg.c" :
187 output_format_e == OUTPUT_FORMAT_POWERSHELL ? L
"exec-reg.ps1" :
188 output_format_e == OUTPUT_FORMAT_C_SHARP ? L
"exec-reg.cs" :
196 fwprintf(stderr, L
"Error occurred. Possibilities:\n");
197 DWORD last_win_error = GetLastError();
198 wchar_t p_message_buf[8192];
199 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
202 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
203 (LPTSTR)&p_message_buf,
206 fprintf(stderr,
"POSIX (%d): %s\n", errno, strerror(errno));
207 fwprintf(stderr, L
"Windows (%lu): %ls", last_win_error, p_message_buf);
215 if (!output_dir_specified) {
static HKEY get_top_key(wchar_t *reg_path)
Gets the HKEY pointer for the first part of a registry path.
int wmain(int argc, wchar_t *argv[])
Entry point.