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