]> sourceware.org Git - newlib-cygwin.git/blob - winsup/utils/regtool.cc
cygwin: regtool: encode error messages correctly
[newlib-cygwin.git] / winsup / utils / regtool.cc
1 /* regtool.cc
2
3 This file is part of Cygwin.
4
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <errno.h>
12 #include <ctype.h>
13 #include <wchar.h>
14 #include <getopt.h>
15 #include <locale.h>
16 #define WINVER 0x0502
17 #include <windows.h>
18 #include <sys/cygwin.h>
19 #include <cygwin/version.h>
20 #include "loadlib.h"
21
22 #define DEFAULT_KEY_SEPARATOR '\\'
23
24 #define REG_AUTO -1
25
26 int value_type = REG_AUTO;
27
28 char key_sep = DEFAULT_KEY_SEPARATOR;
29
30 #define LIST_KEYS 0x01
31 #define LIST_VALS 0x02
32 #define LIST_ALL (LIST_KEYS | LIST_VALS)
33
34 static char *prog_name;
35
36 static struct option longopts[] =
37 {
38 {"binary", no_argument, NULL, 'b' },
39 {"dword", no_argument, NULL, 'd' },
40 {"dword-be", no_argument, NULL, 'D' },
41 {"expand-string", no_argument, NULL, 'e' },
42 {"force", no_argument, NULL, 'f' },
43 {"help", no_argument, NULL, 'h' },
44 {"integer", no_argument, NULL, 'i' },
45 {"keys", no_argument, NULL, 'k'},
46 {"list", no_argument, NULL, 'l'},
47 {"multi-string", no_argument, NULL, 'm'},
48 {"none", no_argument, NULL, 'n' },
49 {"postfix", no_argument, NULL, 'p'},
50 {"quiet", no_argument, NULL, 'q'},
51 {"qword", no_argument, NULL, 'Q' },
52 {"string", no_argument, NULL, 's'},
53 {"verbose", no_argument, NULL, 'v'},
54 {"version", no_argument, NULL, 'V'},
55 {"wow64", no_argument, NULL, 'w'},
56 {"wow32", no_argument, NULL, 'W'},
57 {"hex", no_argument, NULL, 'x'},
58 {"key-separator", required_argument, NULL, 'K'},
59 {NULL, 0, NULL, 0}
60 };
61
62 static char opts[] = "bdDefhiklmnpqQsvVwWxK:";
63
64 const char *types[] =
65 {
66 "REG_NONE",
67 "REG_SZ",
68 "REG_EXPAND_SZ",
69 "REG_BINARY",
70 "REG_DWORD",
71 "REG_DWORD_BIG_ENDIAN",
72 "REG_LINK",
73 "REG_MULTI_SZ",
74 "REG_RESOURCE_LIST",
75 "REG_FULL_RESOURCE_DESCRIPTOR",
76 "REG_RESOURCE_REQUIREMENTS_LIST",
77 "REG_QWORD",
78 };
79
80 int listwhat = 0;
81 int postfix = 0;
82 int verbose = 0;
83 int quiet = 0;
84 int hex = 0;
85 DWORD wow64 = 0;
86 DWORD restore_flags = 0;
87 char **argv;
88
89 HKEY key;
90 wchar_t *value;
91
92 static void
93 usage (FILE *where = stderr)
94 {
95 fprintf (where, ""
96 "Usage: %s [OPTION] ACTION KEY [data...]\n"
97 "\n"
98 "View or edit the Win32 registry\n"
99 "\n", prog_name);
100 if (where == stdout)
101 {
102 fprintf (where, ""
103 "Actions:\n"
104 "\n"
105 " add KEY\\SUBKEY add new SUBKEY\n"
106 " check KEY exit 0 if KEY exists, 1 if not\n"
107 " get KEY\\VALUE prints VALUE to stdout\n"
108 " list KEY list SUBKEYs and VALUEs\n"
109 " remove KEY remove KEY\n"
110 " set KEY\\VALUE [data ...] set VALUE\n"
111 " unset KEY\\VALUE removes VALUE from KEY\n"
112 " load KEY\\SUBKEY PATH load hive from PATH into new SUBKEY\n"
113 " unload KEY\\SUBKEY unload hive and remove SUBKEY\n"
114 " save KEY\\SUBKEY PATH save SUBKEY into new file PATH\n"
115 " restore KEY\\SUBKEY PATH restore SUBKEY from file PATH\n"
116 "\n");
117 fprintf (where, ""
118 "Options for 'list' action:\n"
119 "\n"
120 " -k, --keys print only KEYs\n"
121 " -l, --list print only VALUEs\n"
122 " -p, --postfix like ls -p, appends '\\' postfix to KEY names\n"
123 "\n"
124 "Options for 'get' action:\n"
125 "\n"
126 " -b, --binary print data as printable hex bytes\n"
127 " -n, --none print data as stream of bytes as stored in registry\n"
128 " -x, --hex print numerical data as hex numbers\n"
129 "\n"
130 "Options for 'set' action:\n"
131 "\n"
132 " -b, --binary set type to REG_BINARY (hex args or '-')\n"
133 " -d, --dword set type to REG_DWORD\n"
134 " -D, --dword-be set type to REG_DWORD_BIG_ENDIAN\n"
135 " -e, --expand-string set type to REG_EXPAND_SZ\n"
136 " -i, --integer set type to REG_DWORD\n"
137 " -m, --multi-string set type to REG_MULTI_SZ\n"
138 " -n, --none set type to REG_NONE\n"
139 " -Q, --qword set type to REG_QWORD\n"
140 " -s, --string set type to REG_SZ\n"
141 "\n"
142 "Options for 'set' and 'unset' Actions:\n"
143 "\n"
144 " -K<c>, --key-separator[=]<c> set key-value separator to <c> instead of '\\'\n"
145 "\n"
146 "Options for 'restore' action:\n"
147 "\n"
148 " -f, --force restore even if open handles exist at or beneath the location\n"
149 " in the registry hierarchy to which KEY\\SUBKEY points\n"
150 "\n"
151 "Other Options:\n"
152 "\n"
153 " -h, --help output usage information and exit\n"
154 " -q, --quiet no error output, just nonzero return if KEY/VALUE missing\n"
155 " -v, --verbose verbose output, including VALUE contents when applicable\n"
156 " -w, --wow64 access 64 bit registry view (ignored on 32 bit Windows)\n"
157 " -W, --wow32 access 32 bit registry view (ignored on 32 bit Windows)\n"
158 " -V, --version output version information and exit\n"
159 "\n");
160 fprintf (where, ""
161 "KEY is in the format [host]\\prefix\\KEY\\KEY\\VALUE, where host is optional\n"
162 "remote host in either \\\\hostname or hostname: format and prefix is any of:\n"
163 " root HKCR HKEY_CLASSES_ROOT (local only)\n"
164 " config HKCC HKEY_CURRENT_CONFIG (local only)\n"
165 " user HKCU HKEY_CURRENT_USER (local only)\n"
166 " machine HKLM HKEY_LOCAL_MACHINE\n"
167 " users HKU HKEY_USERS\n"
168 "\n"
169 "If the keyname starts with a forward slash ('/'), the forward slash is used\n"
170 "as separator and the backslash can be used as escape character.\n");
171 fprintf (where, ""
172 "Example:\n"
173 "%s list '/machine/SOFTWARE/Classes/MIME/Database/Content Type/audio\\/wav'\n\n", prog_name);
174 }
175 if (where == stderr)
176 fprintf (where,
177 "ACTION is one of add, check, get, list, remove, set, unset, load, unload, save\n"
178 "\n"
179 "Try `%s --help' for more information.\n", prog_name);
180 exit (where == stderr ? 1 : 0);
181 }
182
183 static void
184 print_version ()
185 {
186 printf ("regtool (cygwin) %d.%d.%d\n"
187 "Registry tool\n"
188 "Copyright (C) 2000 - %s Cygwin Authors\n"
189 "This is free software; see the source for copying conditions. There is NO\n"
190 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
191 CYGWIN_VERSION_DLL_MAJOR / 1000,
192 CYGWIN_VERSION_DLL_MAJOR % 1000,
193 CYGWIN_VERSION_DLL_MINOR,
194 strrchr (__DATE__, ' ') + 1);
195 }
196
197 void
198 Fail (unsigned int rv)
199 {
200 wchar_t *buf;
201
202 if (!quiet)
203 {
204 FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER
205 | FORMAT_MESSAGE_FROM_SYSTEM,
206 0, rv, 0, (WCHAR *)& buf, 0, 0);
207 fprintf (stderr, "Error (%d): %ls\n", rv, buf);
208 LocalFree (buf);
209 }
210 exit (1);
211 }
212
213 static struct
214 {
215 const char *string;
216 HKEY key;
217 } wkprefixes[] =
218 {
219 {"root", HKEY_CLASSES_ROOT},
220 {"HKCR", HKEY_CLASSES_ROOT},
221 {"HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT},
222 {"config", HKEY_CURRENT_CONFIG},
223 {"HKCC", HKEY_CURRENT_CONFIG},
224 {"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG},
225 {"user", HKEY_CURRENT_USER},
226 {"HKCU", HKEY_CURRENT_USER},
227 {"HKEY_CURRENT_USER", HKEY_CURRENT_USER},
228 {"machine", HKEY_LOCAL_MACHINE},
229 {"HKLM", HKEY_LOCAL_MACHINE},
230 {"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE},
231 {"users", HKEY_USERS},
232 {"HKU", HKEY_USERS},
233 {"HKEY_USERS", HKEY_USERS},
234 {0, 0}
235 };
236
237 void
238 translate (char *key)
239 {
240 #define isodigit(c) (strchr("01234567", c))
241 #define tooct(c) ((c)-'0')
242 #define tohex(c) (strchr(_hs,tolower(c))-_hs)
243 static char _hs[] = "0123456789abcdef";
244
245 char *d = key;
246 char *s = key;
247 char c;
248
249 while (*s)
250 {
251 if (*s == '\\')
252 switch (*++s)
253 {
254 case 'a':
255 *d++ = '\007';
256 break;
257 case 'b':
258 *d++ = '\b';
259 break;
260 case 'e':
261 *d++ = '\033';
262 break;
263 case 'f':
264 *d++ = '\f';
265 break;
266 case 'n':
267 *d++ = '\n';
268 break;
269 case 'r':
270 *d++ = '\r';
271 break;
272 case 't':
273 *d++ = '\t';
274 break;
275 case 'v':
276 *d++ = '\v';
277 break;
278 case '0':
279 case '1':
280 case '2':
281 case '3':
282 case '4':
283 case '5':
284 case '6':
285 case '7':
286 c = tooct (*s);
287 if (isodigit (s[1]))
288 {
289 c = (c << 3) | tooct (*++s);
290 if (isodigit (s[1]))
291 c = (c << 3) | tooct (*++s);
292 }
293 *d++ = c;
294 break;
295 case 'x':
296 if (!isxdigit (s[1]))
297 c = '0';
298 else
299 {
300 c = tohex (*++s);
301 if (isxdigit (s[1]))
302 c = (c << 4) | tohex (*++s);
303 }
304 *d++ = c;
305 break;
306 default: /* before non-special char: just add the char */
307 *d++ = *s;
308 break;
309 }
310 else if (*s == '/')
311 *d++ = '\\';
312 else
313 *d++ = *s;
314 ++s;
315 }
316 *d = '\0';
317 }
318
319 void
320 find_key (int howmanyparts, REGSAM access, int option = 0)
321 {
322 HKEY base;
323 int rv;
324 char *n = argv[0], *e, *h, c;
325 char* host = NULL;
326 int i;
327 size_t len;
328
329 if (*n == '/')
330 translate (n);
331 if (*n != '\\')
332 {
333 /* expect host:/key/value format */
334 host = (char*) malloc (strlen (n) + 1);
335 host[0] = host [1] = '\\';
336 for (e = n, h = host + 2; *e && *e != ':'; e++, h++)
337 *h = *e;
338 *h = 0;
339 n = e + 1;
340 if (*n == '/')
341 translate (n);
342 }
343 else if (n[0] == '\\' && n[1] == '\\')
344 {
345 /* expect //host/key/value format */
346 host = (char*) malloc (strlen (n) + 1);
347 host[0] = host[1] = '\\';
348 for (e = n + 2, h = host + 2; *e && *e != '\\'; e++, h++)
349 *h = *e;
350 *h = 0;
351 n = e;
352 }
353 while (*n != '\\')
354 n++;
355 *n++ = 0;
356 for (e = n; *e && *e != '\\'; e++);
357 c = *e;
358 *e = 0;
359 for (i = 0; wkprefixes[i].string; i++)
360 if (strcmp (wkprefixes[i].string, n) == 0)
361 break;
362 if (!wkprefixes[i].string)
363 {
364 fprintf (stderr, "Unknown key prefix. Valid prefixes are:\n");
365 for (i = 0; wkprefixes[i].string; i++)
366 fprintf (stderr, "\t%s\n", wkprefixes[i].string);
367 exit (1);
368 }
369
370 n = e;
371 *e = c;
372 while (*n && *n == '\\')
373 n++;
374 e = n + strlen (n);
375 if (howmanyparts > 1)
376 {
377 while (n < e && *e != key_sep)
378 e--;
379 if (*e != key_sep)
380 {
381 key = wkprefixes[i].key;
382 if (value)
383 free (value);
384 len = mbstowcs (NULL, n, 0) + 1;
385 value = (wchar_t *) malloc (len * sizeof (wchar_t));
386 mbstowcs (value, n, len);
387 return;
388 }
389 else
390 {
391 *e = 0;
392 if (value)
393 free (value);
394 len = mbstowcs (NULL, e + 1, 0) + 1;
395 value = (wchar_t *) malloc (len * sizeof (wchar_t));
396 mbstowcs (value, e + 1, len);
397 }
398 }
399 if (host)
400 {
401 rv = RegConnectRegistry (host, wkprefixes[i].key, &base);
402 if (rv != ERROR_SUCCESS)
403 Fail (rv);
404 free (host);
405 }
406 else
407 base = wkprefixes[i].key;
408
409 if (n[0] == 0)
410 key = base;
411 else
412 {
413 len = mbstowcs (NULL, n, 0) + 1;
414 wchar_t name[len];
415 mbstowcs (name, n, len);
416 if (access)
417 {
418 rv = RegOpenKeyExW (base, name, 0, access | wow64, &key);
419 if (option && (rv == ERROR_SUCCESS || rv == ERROR_ACCESS_DENIED))
420 {
421 /* reopen with desired option due to missing option support in
422 RegOpenKeyE */
423 /* FIXME: may create the key in rare cases (e.g. access denied
424 in parent) */
425 HKEY key2;
426 if (RegCreateKeyExW (base, name, 0, NULL, option, access | wow64,
427 NULL, &key2, NULL)
428 == ERROR_SUCCESS)
429 {
430 if (rv == ERROR_SUCCESS)
431 RegCloseKey (key);
432 key = key2;
433 rv = ERROR_SUCCESS;
434 }
435 }
436 if (rv != ERROR_SUCCESS)
437 Fail (rv);
438 }
439 else if (argv[1])
440 {
441 ssize_t len = cygwin_conv_path (CCP_POSIX_TO_WIN_W, argv[1], NULL, 0);
442 wchar_t win32_path[len];
443 cygwin_conv_path (CCP_POSIX_TO_WIN_W, argv[1], win32_path, len);
444 rv = RegLoadKeyW (base, name, win32_path);
445 if (rv != ERROR_SUCCESS)
446 Fail (rv);
447 if (verbose)
448 printf ("key %ls loaded from file %ls\n", name, win32_path);
449 }
450 else
451 {
452 rv = RegUnLoadKeyW (base, name);
453 if (rv != ERROR_SUCCESS)
454 Fail (rv);
455 if (verbose)
456 printf ("key %ls unloaded\n", name);
457 }
458 }
459 }
460
461
462 int
463 cmd_list ()
464 {
465 DWORD num_subkeys, maxsubkeylen, num_values, maxvalnamelen, maxvaluelen;
466 DWORD maxclasslen;
467 wchar_t *subkey_name, *value_name, *class_name, *vd;
468 unsigned char *value_data;
469 DWORD i, j, m, n, t;
470 int v;
471
472 find_key (1, KEY_READ);
473 RegQueryInfoKeyW (key, 0, 0, 0, &num_subkeys, &maxsubkeylen, &maxclasslen,
474 &num_values, &maxvalnamelen, &maxvaluelen, 0, 0);
475
476 subkey_name = (wchar_t *) malloc ((maxsubkeylen + 1) * sizeof (wchar_t));
477 class_name = (wchar_t *) malloc ((maxclasslen + 1) * sizeof (wchar_t));
478 value_name = (wchar_t *) malloc ((maxvalnamelen + 1) * sizeof (wchar_t));
479 value_data = (unsigned char *) malloc (maxvaluelen + 1);
480
481 if (!listwhat)
482 listwhat = LIST_ALL;
483
484 if (listwhat & LIST_KEYS)
485 for (i = 0; i < num_subkeys; i++)
486 {
487 m = (maxsubkeylen + 1) * sizeof (wchar_t);
488 n = (maxclasslen + 1) * sizeof (wchar_t);
489 RegEnumKeyExW (key, i, subkey_name, &m, 0, class_name, &n, 0);
490 printf ("%ls", subkey_name);
491 if (postfix || verbose)
492 fputc (key_sep, stdout);
493
494 if (verbose)
495 printf (" (%ls)", class_name);
496
497 puts ("");
498 }
499
500 if (listwhat & LIST_VALS)
501 for (i = 0; i < num_values; i++)
502 {
503 m = (maxvalnamelen + 1) * sizeof (wchar_t);
504 n = maxvaluelen + 1;
505 RegEnumValueW (key, i, value_name, &m, 0, &t, (BYTE *) value_data, &n);
506 value_data[n] = 0;
507 if (!verbose)
508 printf ("%ls\n", value_name);
509 else
510 {
511 printf ("%ls (%s) = ", value_name, types[t]);
512 switch (t)
513 {
514 case REG_NONE:
515 case REG_BINARY:
516 for (j = 0; j < 8 && j < n; j++)
517 printf ("%02x ", value_data[j]);
518 printf ("\n");
519 break;
520 case REG_DWORD:
521 printf ("0x%08x (%u)\n", *(unsigned int *) value_data,
522 *(unsigned int *) value_data);
523 break;
524 case REG_DWORD_BIG_ENDIAN:
525 v = ((value_data[0] << 24)
526 | (value_data[1] << 16)
527 | (value_data[2] << 8)
528 | (value_data[3]));
529 printf ("0x%08x (%d)\n", v, v);
530 break;
531 case REG_QWORD:
532 printf ("0x%016llx (%llu)\n",
533 *(unsigned long long *) value_data,
534 *(unsigned long long *) value_data);
535 break;
536 case REG_EXPAND_SZ:
537 case REG_SZ:
538 case REG_LINK:
539 printf ("\"%ls\"\n", (wchar_t *) value_data);
540 break;
541 case REG_MULTI_SZ:
542 vd = (wchar_t *) value_data;
543 while (vd && *vd)
544 {
545 printf ("\"%ls\"", vd);
546 vd = vd + wcslen (vd) + 1;
547 if (*vd)
548 printf (", ");
549 }
550 printf ("\n");
551 break;
552 default:
553 printf ("?\n");
554 break;
555 }
556 }
557 }
558 return 0;
559 }
560
561 int
562 cmd_add ()
563 {
564 find_key (2, KEY_ALL_ACCESS);
565 HKEY newkey;
566 DWORD newtype;
567 int rv = RegCreateKeyExW (key, value, 0, NULL, REG_OPTION_NON_VOLATILE,
568 KEY_ALL_ACCESS | wow64, 0, &newkey, &newtype);
569 if (rv != ERROR_SUCCESS)
570 Fail (rv);
571
572 if (verbose)
573 {
574 if (newtype == REG_OPENED_EXISTING_KEY)
575 printf ("Key %ls already exists\n", value);
576 else
577 printf ("Key %ls created\n", value);
578 }
579 return 0;
580 }
581
582 extern "C" {
583 LONG WINAPI (*regDeleteKeyEx)(HKEY, LPCWSTR, REGSAM, DWORD);
584 }
585
586 int
587 cmd_remove ()
588 {
589 DWORD rv;
590
591 find_key (2, KEY_ALL_ACCESS);
592 if (wow64)
593 {
594 HMODULE mod = LoadLibrary ("advapi32.dll");
595 if (mod)
596 regDeleteKeyEx = (LONG WINAPI (*)(HKEY, LPCWSTR, REGSAM, DWORD)) GetProcAddress (mod, "RegDeleteKeyExW");
597 }
598 if (regDeleteKeyEx)
599 rv = (*regDeleteKeyEx) (key, value, wow64, 0);
600 else
601 rv = RegDeleteKeyW (key, value);
602 if (rv != ERROR_SUCCESS)
603 Fail (rv);
604 if (verbose)
605 printf ("subkey %ls deleted\n", value);
606 return 0;
607 }
608
609 int
610 cmd_check ()
611 {
612 find_key (1, KEY_READ);
613 if (verbose)
614 printf ("key %s exists\n", argv[0]);
615 return 0;
616 }
617
618 int
619 cmd_set ()
620 {
621 int i, n, max_n;
622 DWORD v, rv;
623 unsigned long long llval;
624 char *a = argv[1], *data = 0;
625 find_key (2, KEY_ALL_ACCESS);
626
627 if (!a)
628 usage ();
629 if (value_type == REG_AUTO)
630 {
631 char *e;
632 llval = strtoull (a, &e, 0);
633 if (a[0] == '%')
634 value_type = REG_EXPAND_SZ;
635 else if (a[0] && !*e)
636 value_type = llval > 0xffffffffULL ? REG_QWORD : REG_DWORD;
637 else if (argv[2])
638 value_type = REG_MULTI_SZ;
639 else
640 value_type = REG_SZ;
641 }
642
643 switch (value_type)
644 {
645 case REG_NONE:
646 case REG_BINARY:
647 for (n = 0; argv[n+1]; n++)
648 ;
649 if (n == 1 && strcmp (argv[1], "-") == 0)
650 { /* read from stdin */
651 i = n = 0;
652 for (;;)
653 {
654 if (i <= n)
655 {
656 i = n + BUFSIZ;
657 data = (char *) realloc (data, i);
658 }
659 int r = fread (data+n, 1, i-n, stdin);
660 if (r <= 0)
661 break;
662 n += r;
663 }
664 }
665 else if (n > 0)
666 { /* parse hex from argv */
667 data = (char *) malloc (n);
668 for (i = 0; i < n; i++)
669 {
670 char *e;
671 errno = 0;
672 v = strtoul (argv[i+1], &e, 16);
673 if (errno || v > 0xff || *e)
674 {
675 fprintf (stderr, "Invalid hex constant `%s'\n", argv[i+1]);
676 exit (1);
677 }
678 data[i] = (char) v;
679 }
680 }
681 rv = RegSetValueExW (key, value, 0, value_type, (const BYTE *) data, n);
682 break;
683 case REG_DWORD:
684 v = strtoul (a, 0, 0);
685 rv = RegSetValueExW (key, value, 0, REG_DWORD, (const BYTE *) &v,
686 sizeof (v));
687 break;
688 case REG_DWORD_BIG_ENDIAN:
689 v = strtoul (a, 0, 0);
690 v = (((v & 0xff) << 24)
691 | ((v & 0xff00) << 8)
692 | ((v & 0xff0000) >> 8)
693 | ((v & 0xff000000) >> 24));
694 rv = RegSetValueExW (key, value, 0, REG_DWORD_BIG_ENDIAN,
695 (const BYTE *) &v, sizeof (v));
696 break;
697 case REG_QWORD:
698 llval = strtoul (a, 0, 0);
699 rv = RegSetValueExW (key, value, 0, REG_QWORD, (const BYTE *) &llval,
700 sizeof (llval));
701 break;
702 case REG_SZ:
703 case REG_EXPAND_SZ:
704 {
705 n = mbstowcs (NULL, a, 0);
706 wchar_t w[n + 1];
707 mbstowcs (w, a, n + 1);
708 rv = RegSetValueExW (key, value, 0, value_type,
709 (const BYTE *) w, (n + 1) * sizeof (wchar_t));
710 }
711 break;
712 case REG_MULTI_SZ:
713 for (i = 1, max_n = 1; argv[i]; i++)
714 max_n += mbstowcs (NULL, argv[i], 0) + 1;
715 data = (char *) malloc (max_n * sizeof (wchar_t));
716 for (i = 1, n = 0; argv[i]; i++)
717 n += mbstowcs ((wchar_t *) data + n, argv[i], max_n - n) + 1;
718 ((wchar_t *)data)[n] = L'\0';
719 rv = RegSetValueExW (key, value, 0, REG_MULTI_SZ, (const BYTE *) data,
720 (n + 1) * sizeof (wchar_t));
721 break;
722 case REG_AUTO:
723 rv = ERROR_SUCCESS;
724 break;
725 default:
726 rv = ERROR_INVALID_CATEGORY;
727 break;
728 }
729
730 if (data)
731 free(data);
732
733 if (rv != ERROR_SUCCESS)
734 Fail (rv);
735
736 return 0;
737 }
738
739 int
740 cmd_unset ()
741 {
742 find_key (2, KEY_ALL_ACCESS);
743 DWORD rv = RegDeleteValueW (key, value);
744 if (rv != ERROR_SUCCESS)
745 Fail (rv);
746 if (verbose)
747 printf ("value %ls deleted\n", value);
748 return 0;
749 }
750
751 int
752 cmd_get ()
753 {
754 find_key (2, KEY_READ);
755 DWORD vtype, dsize, rv;
756 PBYTE data;
757 wchar_t *vd;
758
759 rv = RegQueryValueExW (key, value, 0, &vtype, 0, &dsize);
760 if (rv != ERROR_SUCCESS)
761 Fail (rv);
762 data = (PBYTE) malloc (dsize + 1);
763 rv = RegQueryValueExW (key, value, 0, &vtype, data, &dsize);
764 if (rv != ERROR_SUCCESS)
765 Fail (rv);
766 if (value_type == REG_BINARY)
767 {
768 for (unsigned i = 0; i < dsize; i++)
769 printf ("%02x%c", (unsigned char)data[i],
770 (i < dsize-1 ? ' ' : '\n'));
771 }
772 else if (value_type == REG_NONE)
773 fwrite (data, dsize, 1, stdout);
774 else
775 switch (vtype)
776 {
777 case REG_NONE:
778 case REG_BINARY:
779 fwrite (data, dsize, 1, stdout);
780 break;
781 case REG_DWORD:
782 printf (hex ? "0x%08x\n" : "%u\n", *(unsigned int *) data);
783 break;
784 case REG_DWORD_BIG_ENDIAN:
785 rv = ((data[0] << 24)
786 | (data[1] << 16)
787 | (data[2] << 8)
788 | (data[3]));
789 printf (hex ? "0x%08x\n" : "%u\n", (unsigned int) rv);
790 break;
791 case REG_QWORD:
792 printf (hex ? "0x%016llx\n" : "%llu\n", *(unsigned long long *) data);
793 break;
794 case REG_SZ:
795 case REG_LINK:
796 printf ("%ls\n", (wchar_t *) data);
797 break;
798 case REG_EXPAND_SZ:
799 if (value_type == REG_EXPAND_SZ) // hack
800 {
801 wchar_t *buf;
802 DWORD bufsize;
803 bufsize = ExpandEnvironmentStringsW ((wchar_t *) data, 0, 0);
804 buf = (wchar_t *) malloc (bufsize + 1);
805 ExpandEnvironmentStringsW ((wchar_t *) data, buf, bufsize + 1);
806 free (data);
807 data = (PBYTE) buf;
808 }
809 printf ("%ls\n", (wchar_t *) data);
810 break;
811 case REG_MULTI_SZ:
812 vd = (wchar_t *) data;
813 while (vd && *vd)
814 {
815 printf ("%ls\n", vd);
816 vd = vd + wcslen (vd) + 1;
817 }
818 break;
819 }
820 return 0;
821 }
822
823 int
824 cmd_load ()
825 {
826 if (!argv[1])
827 {
828 usage ();
829 return 1;
830 }
831 find_key (1, 0);
832 return 0;
833 }
834
835 int
836 cmd_unload ()
837 {
838 if (argv[1])
839 {
840 usage ();
841 return 1;
842 }
843 find_key (1, 0);
844 return 0;
845 }
846
847 int
848 cmd_save ()
849 {
850 if (!argv[1])
851 {
852 usage ();
853 return 1;
854 }
855 /* REG_OPTION_BACKUP_RESTORE is necessary to save /HKLM/SECURITY */
856 find_key (1, KEY_QUERY_VALUE, REG_OPTION_BACKUP_RESTORE);
857 ssize_t len = cygwin_conv_path (CCP_POSIX_TO_WIN_W, argv[1], NULL, 0);
858 wchar_t win32_path[len];
859 cygwin_conv_path (CCP_POSIX_TO_WIN_W, argv[1], win32_path, len);
860 DWORD rv = RegSaveKeyW (key, win32_path, NULL);
861 if (rv != ERROR_SUCCESS)
862 Fail (rv);
863 if (verbose)
864 printf ("key saved to %ls\n", win32_path);
865 return 0;
866 }
867
868 int
869 cmd_restore ()
870 {
871 if (!argv[1])
872 {
873 usage ();
874 return 1;
875 }
876 /* REG_OPTION_BACKUP_RESTORE is necessary to restore /HKLM/SECURITY */
877 find_key (1, KEY_ALL_ACCESS, REG_OPTION_BACKUP_RESTORE);
878 ssize_t len = cygwin_conv_path (CCP_POSIX_TO_WIN_W, argv[1], NULL, 0);
879 wchar_t win32_path[len];
880 cygwin_conv_path (CCP_POSIX_TO_WIN_W, argv[1], win32_path, len);
881 DWORD rv = RegRestoreKeyW (key, win32_path, restore_flags);
882 if (rv != ERROR_SUCCESS)
883 Fail (rv);
884 if (verbose)
885 printf ("key saved to %ls\n", win32_path);
886 return 0;
887 }
888
889 static struct
890 {
891 const char *name;
892 int (*func) ();
893 } commands[] =
894 {
895 {"list", cmd_list},
896 {"add", cmd_add},
897 {"remove", cmd_remove},
898 {"check", cmd_check},
899 {"set", cmd_set},
900 {"unset", cmd_unset},
901 {"get", cmd_get},
902 {"load", cmd_load},
903 {"unload", cmd_unload},
904 {"save", cmd_save},
905 {"restore", cmd_restore},
906 {0, 0}
907 };
908
909 int
910 main (int argc, char **_argv)
911 {
912 int g;
913
914 setlocale (LC_ALL, "");
915
916 prog_name = program_invocation_short_name;
917
918 while ((g = getopt_long (argc, _argv, opts, longopts, NULL)) != EOF)
919 switch (g)
920 {
921 case 'b':
922 value_type = REG_BINARY;
923 break;
924 case 'd':
925 value_type = REG_DWORD;
926 break;
927 case 'D':
928 value_type = REG_DWORD_BIG_ENDIAN;
929 break;
930 case 'e':
931 value_type = REG_EXPAND_SZ;
932 break;
933 case 'f':
934 restore_flags = REG_FORCE_RESTORE;
935 break;
936 case 'k':
937 listwhat |= LIST_KEYS;
938 break;
939 case 'h':
940 usage (stdout);
941 case 'i':
942 value_type = REG_DWORD;
943 break;
944 case 'l':
945 listwhat |= LIST_VALS;
946 break;
947 case 'm':
948 value_type = REG_MULTI_SZ;
949 break;
950 case 'n':
951 value_type = REG_NONE;
952 break;
953 case 'p':
954 postfix++;
955 break;
956 case 'q':
957 quiet++;
958 break;
959 case 'Q':
960 value_type = REG_QWORD;
961 break;
962 case 's':
963 value_type = REG_SZ;
964 break;
965 case 'v':
966 verbose++;
967 break;
968 case 'V':
969 print_version ();
970 exit (0);
971 case 'w':
972 wow64 = KEY_WOW64_64KEY;
973 break;
974 case 'W':
975 wow64 = KEY_WOW64_32KEY;
976 break;
977 case 'x':
978 hex++;
979 break;
980 case 'K':
981 key_sep = *optarg;
982 break;
983 default :
984 fprintf (stderr, "Try `%s --help' for more information.\n",
985 prog_name);
986 return 1;
987 }
988
989 if ((_argv[optind] == NULL) || (_argv[optind+1] == NULL))
990 usage ();
991
992 argv = _argv + optind;
993 int i;
994 for (i = 0; commands[i].name; i++)
995 if (strcmp (commands[i].name, argv[0]) == 0)
996 {
997 argv++;
998 return commands[i].func ();
999 }
1000 usage ();
1001
1002 return 0;
1003 }
This page took 0.079308 seconds and 6 git commands to generate.