3 Copyright 2000, 2001, 2002, 2003, 2004 Red Hat Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
17 #define DEFAULT_KEY_SEPARATOR '\\'
21 KT_AUTO
, KT_INT
, KT_STRING
, KT_EXPAND
, KT_MULTI
24 char key_sep
= DEFAULT_KEY_SEPARATOR
;
26 #define LIST_KEYS 0x01
27 #define LIST_VALS 0x02
28 #define LIST_ALL (LIST_KEYS | LIST_VALS)
30 static const char version
[] = "$Revision$";
31 static char *prog_name
;
33 static struct option longopts
[] =
35 {"expand-string", no_argument
, NULL
, 'e' },
36 {"help", no_argument
, NULL
, 'h' },
37 {"integer", no_argument
, NULL
, 'i' },
38 {"keys", no_argument
, NULL
, 'k'},
39 {"list", no_argument
, NULL
, 'l'},
40 {"multi-string", no_argument
, NULL
, 'm'},
41 {"postfix", no_argument
, NULL
, 'p'},
42 {"quiet", no_argument
, NULL
, 'q'},
43 {"string", no_argument
, NULL
, 's'},
44 {"verbose", no_argument
, NULL
, 'v'},
45 {"version", no_argument
, NULL
, 'V'},
46 {"key-separator", required_argument
, NULL
, 'K'},
50 static char opts
[] = "ehiklmpqsvVK:";
62 usage (FILE *where
= stderr
)
65 "Usage: %s [OPTION] (add | check | get | list | remove | unset) KEY\n"
66 "View or edit the Win32 registry\n"
72 " add KEY\\SUBKEY add new SUBKEY\n"
73 " check KEY exit 0 if KEY exists, 1 if not\n"
74 " get KEY\\VALUE prints VALUE to stdout\n"
75 " list KEY list SUBKEYs and VALUEs\n"
76 " remove KEY remove KEY\n"
77 " set KEY\\VALUE [data ...] set VALUE\n"
78 " unset KEY\\VALUE removes VALUE from KEY\n"
81 "Options for 'list' Action:\n"
82 " -k, --keys print only KEYs\n"
83 " -l, --list print only VALUEs\n"
84 " -p, --postfix like ls -p, appends '\\' postfix to KEY names\n"
86 "Options for 'set' Action:\n"
87 " -e, --expand-string set type to REG_EXPAND_SZ\n"
88 " -i, --integer set type to REG_DWORD\n"
89 " -m, --multi-string set type to REG_MULTI_SZ\n"
90 " -s, --string set type to REG_SZ\n"
92 "Options for 'set' and 'unset' Actions:\n"
93 " -K<c>, --key-separator[=]<c> set key separator to <c> instead of '\\'\n"
96 " -h, --help output usage information and exit\n"
97 " -q, --quiet no error output, just nonzero return if KEY/VALUE missing\n"
98 " -v, --verbose verbose output, including VALUE contents when applicable\n"
99 " -V, --version output version information and exit\n"
104 "KEY is in the format [host]\\prefix\\KEY\\KEY\\VALUE, where host is optional\n"
105 "remote host in either \\\\hostname or hostname: format and prefix is any of:\n"
106 " root HKCR HKEY_CLASSES_ROOT (local only)\n"
107 " config HKCC HKEY_CURRENT_CONFIG (local only)\n"
108 " user HKCU HKEY_CURRENT_USER (local only)\n"
109 " machine HKLM HKEY_LOCAL_MACHINE\n"
110 " users HKU HKEY_USERS\n"
112 "If the keyname starts with a forward slash ('/'), the forward slash is used\n"
113 "as separator and the backslash can be used as escape character.\n");
116 "%s list '/machine/SOFTWARE/Classes/MIME/Database/Content Type/audio\\/wav'\n", prog_name
);
119 fprintf (where
, "Try '%s --help' for more information.\n", prog_name
);
120 exit (where
== stderr
? 1 : 0);
126 const char *v
= strchr (version
, ':');
136 len
= strchr (v
, ' ') - v
;
141 Copyright 2000, 2001, 2002 Red Hat, Inc.\n\
143 ", prog_name
, len
, v
, __DATE__
);
152 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
153 | FORMAT_MESSAGE_FROM_SYSTEM
,
154 0, rv
, 0, (CHAR
*) & buf
, 0, 0);
155 fprintf (stderr
, "Error (%ld): %s\n", rv
, buf
);
167 {"root", HKEY_CLASSES_ROOT
},
168 {"HKCR", HKEY_CLASSES_ROOT
},
169 {"HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT
},
170 {"config", HKEY_CURRENT_CONFIG
},
171 {"HKCC", HKEY_CURRENT_CONFIG
},
172 {"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG
},
173 {"user", HKEY_CURRENT_USER
},
174 {"HKCU", HKEY_CURRENT_USER
},
175 {"HKEY_CURRENT_USER", HKEY_CURRENT_USER
},
176 {"machine", HKEY_LOCAL_MACHINE
},
177 {"HKLM", HKEY_LOCAL_MACHINE
},
178 {"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE
},
179 {"users", HKEY_USERS
},
181 {"HKEY_USERS", HKEY_USERS
},
186 translate (char *key
)
188 #define isodigit(c) (strchr("01234567", c))
189 #define tooct(c) ((c)-'0')
190 #define tohex(c) (strchr(_hs,tolower(c))-_hs)
191 static char _hs
[] = "0123456789abcdef";
237 c
= (c
<< 3) | tooct (*++s
);
239 c
= (c
<< 3) | tooct (*++s
);
244 if (!isxdigit (s
[1]))
250 c
= (c
<< 4) | tohex (*++s
);
254 default: /* before non-special char: just add the char */
268 find_key (int howmanyparts
, REGSAM access
)
272 char *n
= argv
[0], *e
, *h
, c
;
279 /* expect host:/key/value format */
280 host
= (char*) malloc (strlen (n
) + 1);
281 host
[0] = host
[1] = '\\';
282 for (e
= n
, h
= host
+ 2; *e
&& *e
!= ':'; e
++, h
++)
289 else if (n
[0] == '\\' && n
[1] == '\\')
291 /* expect //host/key/value format */
292 host
= (char*) malloc (strlen (n
) + 1);
293 host
[0] = host
[1] = '\\';
294 for (e
= n
+ 2, h
= host
+ 2; *e
&& *e
!= '\\'; e
++, h
++)
302 for (e
= n
; *e
&& *e
!= '\\'; e
++);
305 for (i
= 0; wkprefixes
[i
].string
; i
++)
306 if (strcmp (wkprefixes
[i
].string
, n
) == 0)
308 if (!wkprefixes
[i
].string
)
310 fprintf (stderr
, "Unknown key prefix. Valid prefixes are:\n");
311 for (i
= 0; wkprefixes
[i
].string
; i
++)
312 fprintf (stderr
, "\t%s\n", wkprefixes
[i
].string
);
318 while (*n
&& *n
== '\\')
321 if (howmanyparts
> 1)
323 while (n
< e
&& *e
!= key_sep
)
327 key
= wkprefixes
[i
].key
;
339 rv
= RegConnectRegistry (host
, wkprefixes
[i
].key
, &base
);
340 if (rv
!= ERROR_SUCCESS
)
345 base
= wkprefixes
[i
].key
;
351 rv
= RegOpenKeyEx (base
, n
, 0, access
, &key
);
352 if (rv
!= ERROR_SUCCESS
)
355 //printf("key `%s' value `%s'\n", n, value);
362 DWORD num_subkeys
, maxsubkeylen
, num_values
, maxvalnamelen
, maxvaluelen
;
364 char *subkey_name
, *value_name
, *class_name
;
365 unsigned char *value_data
, *vd
;
369 find_key (1, KEY_READ
);
370 RegQueryInfoKey (key
, 0, 0, 0, &num_subkeys
, &maxsubkeylen
, &maxclasslen
,
371 &num_values
, &maxvalnamelen
, &maxvaluelen
, 0, 0);
373 subkey_name
= (char *) malloc (maxsubkeylen
+ 1);
374 class_name
= (char *) malloc (maxclasslen
+ 1);
375 value_name
= (char *) malloc (maxvalnamelen
+ 1);
376 value_data
= (unsigned char *) malloc (maxvaluelen
+ 1);
381 if (listwhat
& LIST_KEYS
)
382 for (i
= 0; i
< num_subkeys
; i
++)
384 m
= maxsubkeylen
+ 1;
386 RegEnumKeyEx (key
, i
, subkey_name
, &m
, 0, class_name
, &n
, 0);
387 printf ("%s%s", subkey_name
, (postfix
|| verbose
) ? "\\" : "");
390 printf (" (%s)", class_name
);
395 if (listwhat
& LIST_VALS
)
396 for (i
= 0; i
< num_values
; i
++)
398 m
= maxvalnamelen
+ 1;
400 RegEnumValue (key
, i
, value_name
, &m
, 0, &t
, (BYTE
*) value_data
, &n
);
402 printf ("%s\n", value_name
);
405 printf ("%s = ", value_name
);
409 for (j
= 0; j
< 8 && j
< n
; j
++)
410 printf ("%02x ", value_data
[j
]);
414 printf ("0x%08lx (%lu)\n", *(DWORD
*) value_data
,
415 *(DWORD
*) value_data
);
417 case REG_DWORD_BIG_ENDIAN
:
418 v
= ((value_data
[0] << 24)
419 | (value_data
[1] << 16)
420 | (value_data
[2] << 8) | (value_data
[3]));
421 printf ("0x%08x (%d)\n", v
, v
);
425 printf ("\"%s\"\n", value_data
);
431 printf ("\"%s\"", vd
);
432 vd
= vd
+ strlen ((const char *) vd
) + 1;
439 printf ("? (type %d)\n", (int) t
);
449 find_key (2, KEY_ALL_ACCESS
);
452 int rv
= RegCreateKeyEx (key
, value
, 0, (char *) "", REG_OPTION_NON_VOLATILE
,
453 KEY_ALL_ACCESS
, 0, &newkey
, &newtype
);
454 if (rv
!= ERROR_SUCCESS
)
459 if (newtype
== REG_OPENED_EXISTING_KEY
)
460 printf ("Key %s already exists\n", value
);
462 printf ("Key %s created\n", value
);
470 find_key (2, KEY_ALL_ACCESS
);
471 DWORD rv
= RegDeleteKey (key
, value
);
472 if (rv
!= ERROR_SUCCESS
)
475 printf ("subkey %s deleted\n", value
);
482 find_key (1, KEY_READ
);
484 printf ("key %s exists\n", argv
[0]);
493 char *a
= argv
[1], *data
;
494 find_key (2, KEY_ALL_ACCESS
);
496 if (key_type
== KT_AUTO
)
501 key_type
= KT_EXPAND
;
502 else if (a
[0] && !*e
)
507 key_type
= KT_STRING
;
513 v
= strtoul (a
, 0, 0);
514 rv
= RegSetValueEx (key
, value
, 0, REG_DWORD
, (const BYTE
*) &v
,
518 rv
= RegSetValueEx (key
, value
, 0, REG_SZ
, (const BYTE
*) a
, strlen (a
));
521 rv
= RegSetValueEx (key
, value
, 0, REG_EXPAND_SZ
, (const BYTE
*) a
,
525 for (i
= 1, n
= 1; argv
[i
]; i
++)
526 n
+= strlen (argv
[i
]) + 1;
527 data
= (char *) malloc (n
);
528 for (i
= 1, n
= 0; argv
[i
]; i
++)
530 strcpy (data
+ n
, argv
[i
]);
531 n
+= strlen (argv
[i
]) + 1;
534 rv
= RegSetValueEx (key
, value
, 0, REG_MULTI_SZ
, (const BYTE
*) data
,
541 rv
= ERROR_INVALID_CATEGORY
;
545 if (rv
!= ERROR_SUCCESS
)
554 find_key (2, KEY_ALL_ACCESS
);
555 DWORD rv
= RegDeleteValue (key
, value
);
556 if (rv
!= ERROR_SUCCESS
)
559 printf ("value %s deleted\n", value
);
566 find_key (2, KEY_READ
);
567 DWORD vtype
, dsize
, rv
;
569 rv
= RegQueryValueEx (key
, value
, 0, &vtype
, 0, &dsize
);
570 if (rv
!= ERROR_SUCCESS
)
573 data
= (char *) malloc (dsize
);
574 rv
= RegQueryValueEx (key
, value
, 0, &vtype
, (BYTE
*) data
, &dsize
);
575 if (rv
!= ERROR_SUCCESS
)
580 fwrite (data
, dsize
, 0, stdout
);
583 printf ("%lu\n", *(DWORD
*) data
);
586 printf ("%s\n", data
);
589 if (key_type
== KT_EXPAND
) // hack
593 bufsize
= ExpandEnvironmentStrings (data
, 0, 0);
594 buf
= (char *) malloc (bufsize
+ 1);
595 ExpandEnvironmentStrings (data
, buf
, bufsize
+ 1);
598 printf ("%s\n", data
);
605 vd
= vd
+ strlen ((const char *) vd
) + 1;
620 {"remove", cmd_remove
},
621 {"check", cmd_check
},
623 {"unset", cmd_unset
},
629 main (int argc
, char **_argv
)
633 prog_name
= strrchr (_argv
[0], '/');
634 if (prog_name
== NULL
)
635 prog_name
= strrchr (_argv
[0], '\\');
636 if (prog_name
== NULL
)
637 prog_name
= _argv
[0];
641 while ((g
= getopt_long (argc
, _argv
, opts
, longopts
, NULL
)) != EOF
)
645 key_type
= KT_EXPAND
;
648 listwhat
|= LIST_KEYS
;
656 listwhat
|= LIST_VALS
;
668 key_type
= KT_STRING
;
683 if ((_argv
[optind
] == NULL
) || (_argv
[optind
+1] == NULL
))
686 argv
= _argv
+ optind
;
688 for (i
= 0; commands
[i
].name
; i
++)
689 if (strcmp (commands
[i
].name
, argv
[0]) == 0)
692 return commands
[i
].func ();