* regtool.cc (options): Add 'binary'.

(usage): Document 'load|unload|save' and '-b'.
	(find_key): Add 'options' parameter, add load/unload.
	(cmd_set): Add KT_BINARY case.
	(cmd_get): Add hex output in KT_BINARY case.
	(cmd_load): New function.
	(cmd_unload): New function.
	(set_privilege): New function.
	(cmd_save): New function.
	(commands): Add load, unload and save.
	(main): Add '-b'
	* utils.sgml (regtool): Document it.
This commit is contained in:
Corinna Vinschen 2006-03-03 09:43:35 +00:00
parent dff8cd7700
commit 17c8ac3992
3 changed files with 212 additions and 11 deletions

View File

@ -1,3 +1,18 @@
2006-03-03 Christian Franke <franke@computer.org>
* regtool.cc (options): Add 'binary'.
(usage): Document 'load|unload|save' and '-b'.
(find_key): Add 'options' parameter, add load/unload.
(cmd_set): Add KT_BINARY case.
(cmd_get): Add hex output in KT_BINARY case.
(cmd_load): New function.
(cmd_unload): New function.
(set_privilege): New function.
(cmd_save): New function.
(commands): Add load, unload and save.
(main): Add '-b'
* utils.sgml (regtool): Document it.
2006-02-17 Corinna Vinschen <corinna@vinschen.de> 2006-02-17 Corinna Vinschen <corinna@vinschen.de>
* cygpath.cc (get_long_name): Load GetLongPathNameA instead of incorrect * cygpath.cc (get_long_name): Load GetLongPathNameA instead of incorrect

View File

@ -1,6 +1,6 @@
/* regtool.cc /* regtool.cc
Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat Inc. Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -10,15 +10,17 @@ details. */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#include <ctype.h> #include <ctype.h>
#include <getopt.h> #include <getopt.h>
#include <windows.h> #include <windows.h>
#include <sys/cygwin.h>
#define DEFAULT_KEY_SEPARATOR '\\' #define DEFAULT_KEY_SEPARATOR '\\'
enum enum
{ {
KT_AUTO, KT_INT, KT_STRING, KT_EXPAND, KT_MULTI KT_AUTO, KT_BINARY, KT_INT, KT_STRING, KT_EXPAND, KT_MULTI
} key_type = KT_AUTO; } key_type = KT_AUTO;
char key_sep = DEFAULT_KEY_SEPARATOR; char key_sep = DEFAULT_KEY_SEPARATOR;
@ -32,6 +34,7 @@ static char *prog_name;
static struct option longopts[] = static struct option longopts[] =
{ {
{"binary", no_argument, NULL, 'b' },
{"expand-string", no_argument, NULL, 'e' }, {"expand-string", no_argument, NULL, 'e' },
{"help", no_argument, NULL, 'h' }, {"help", no_argument, NULL, 'h' },
{"integer", no_argument, NULL, 'i' }, {"integer", no_argument, NULL, 'i' },
@ -47,7 +50,7 @@ static struct option longopts[] =
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
static char opts[] = "ehiklmpqsvVK:"; static char opts[] = "behiklmpqsvVK:";
int listwhat = 0; int listwhat = 0;
int postfix = 0; int postfix = 0;
@ -62,7 +65,7 @@ static void
usage (FILE *where = stderr) usage (FILE *where = stderr)
{ {
fprintf (where, "" fprintf (where, ""
"Usage: %s [OPTION] (add | check | get | list | remove | unset) KEY\n" "Usage: %s [OPTION] (add|check|get|list|remove|unset|load|unload|save) KEY\n"
"View or edit the Win32 registry\n" "View or edit the Win32 registry\n"
"\n" "\n"
"", prog_name); "", prog_name);
@ -76,6 +79,9 @@ usage (FILE *where = stderr)
" remove KEY remove KEY\n" " remove KEY remove KEY\n"
" set KEY\\VALUE [data ...] set VALUE\n" " set KEY\\VALUE [data ...] set VALUE\n"
" unset KEY\\VALUE removes VALUE from KEY\n" " unset KEY\\VALUE removes VALUE from KEY\n"
" load KEY\\SUBKEY PATH load hive from PATH into new SUBKEY\n"
" unload KEY\\SUBKEY unload hive and remove SUBKEY\n"
" save KEY\\SUBKEY PATH save SUBKEY into new hive PATH\n"
"\n"); "\n");
fprintf (where, "" fprintf (where, ""
"Options for 'list' Action:\n" "Options for 'list' Action:\n"
@ -83,7 +89,11 @@ usage (FILE *where = stderr)
" -l, --list print only VALUEs\n" " -l, --list print only VALUEs\n"
" -p, --postfix like ls -p, appends '\\' postfix to KEY names\n" " -p, --postfix like ls -p, appends '\\' postfix to KEY names\n"
"\n" "\n"
"Options for 'get' Action:\n"
" -b, --binary print REG_BINARY data as hex bytes\n"
"\n"
"Options for 'set' Action:\n" "Options for 'set' Action:\n"
" -b, --binary set type to REG_BINARY (hex args or '-')\n"
" -e, --expand-string set type to REG_EXPAND_SZ\n" " -e, --expand-string set type to REG_EXPAND_SZ\n"
" -i, --integer set type to REG_DWORD\n" " -i, --integer set type to REG_DWORD\n"
" -m, --multi-string set type to REG_MULTI_SZ\n" " -m, --multi-string set type to REG_MULTI_SZ\n"
@ -265,7 +275,7 @@ translate (char *key)
} }
void void
find_key (int howmanyparts, REGSAM access) find_key (int howmanyparts, REGSAM access, int option = 0)
{ {
HKEY base; HKEY base;
int rv; int rv;
@ -347,11 +357,46 @@ find_key (int howmanyparts, REGSAM access)
if (n[0] == 0) if (n[0] == 0)
key = base; key = base;
else else
{
if (access)
{ {
rv = RegOpenKeyEx (base, n, 0, access, &key); rv = RegOpenKeyEx (base, n, 0, access, &key);
if (option && (rv == ERROR_SUCCESS || rv == ERROR_ACCESS_DENIED))
{
/* reopen with desired option due to missing option support in RegOpenKeyE */
/* FIXME: may create the key in rare cases (e.g. access denied in parent) */
HKEY key2;
if (RegCreateKeyEx (base, n, 0, NULL, option, access, NULL, &key2, NULL)
== ERROR_SUCCESS)
{
if (rv == ERROR_SUCCESS)
RegCloseKey (key);
key = key2;
rv = ERROR_SUCCESS;
}
}
if (rv != ERROR_SUCCESS) if (rv != ERROR_SUCCESS)
Fail (rv); Fail (rv);
} }
else if (argv[1])
{
char win32_path[MAX_PATH];
cygwin_conv_to_win32_path (argv[1], win32_path);
rv = RegLoadKey (base, n, win32_path);
if (rv != ERROR_SUCCESS)
Fail (rv);
if (verbose)
printf ("key %s loaded from file %s\n", n, win32_path);
}
else
{
rv = RegUnLoadKey (base, n);
if (rv != ERROR_SUCCESS)
Fail (rv);
if (verbose)
printf ("key %s unloaded\n", n);
}
}
//printf("key `%s' value `%s'\n", n, value); //printf("key `%s' value `%s'\n", n, value);
} }
@ -491,7 +536,7 @@ cmd_set ()
{ {
int i, n; int i, n;
DWORD v, rv; DWORD v, rv;
char *a = argv[1], *data; char *a = argv[1], *data = 0;
find_key (2, KEY_ALL_ACCESS); find_key (2, KEY_ALL_ACCESS);
if (key_type == KT_AUTO) if (key_type == KT_AUTO)
@ -510,6 +555,43 @@ cmd_set ()
switch (key_type) switch (key_type)
{ {
case KT_BINARY:
for (n = 0; argv[n+1]; n++)
;
if (n == 1 && strcmp (argv[1], "-") == 0)
{ /* read from stdin */
i = n = 0;
for (;;)
{
if (i <= n)
{
i = n + BUFSIZ;
data = (char *) realloc (data, i);
}
int r = fread (data+n, 1, i-n, stdin);
if (r <= 0)
break;
n += r;
}
}
else if (n > 0)
{ /* parse hex from argv */
data = (char *) malloc (n);
for (i = 0; i < n; i++)
{
char *e;
errno = 0;
v = strtoul (argv[i+1], &e, 16);
if (errno || v > 0xff || *e)
{
fprintf (stderr, "Invalid hex constant `%s'\n", argv[i+1]);
exit (1);
}
data[i] = (char) v;
}
}
rv = RegSetValueEx (key, value, 0, REG_BINARY, (const BYTE *) data, n);
break;
case KT_INT: case KT_INT:
v = strtoul (a, 0, 0); v = strtoul (a, 0, 0);
rv = RegSetValueEx (key, value, 0, REG_DWORD, (const BYTE *) &v, rv = RegSetValueEx (key, value, 0, REG_DWORD, (const BYTE *) &v,
@ -543,6 +625,9 @@ cmd_set ()
break; break;
} }
if (data)
free(data);
if (rv != ERROR_SUCCESS) if (rv != ERROR_SUCCESS)
Fail (rv); Fail (rv);
@ -577,6 +662,13 @@ cmd_get ()
switch (vtype) switch (vtype)
{ {
case REG_BINARY: case REG_BINARY:
if (key_type == KT_BINARY)
{
for (unsigned i = 0; i < dsize; i++)
printf ("%02x%c", (unsigned char)data[i],
(i < dsize-1 ? ' ' : '\n'));
}
else
fwrite (data, dsize, 1, stdout); fwrite (data, dsize, 1, stdout);
break; break;
case REG_DWORD: case REG_DWORD:
@ -610,6 +702,72 @@ cmd_get ()
return 0; return 0;
} }
int
cmd_load ()
{
if (!argv[1])
{
usage ();
return 1;
}
find_key (1, 0);
return 0;
}
int
cmd_unload ()
{
if (argv[1])
{
usage ();
return 1;
}
find_key (1, 0);
return 0;
}
DWORD
set_privilege (const char * name)
{
TOKEN_PRIVILEGES tp;
if (!LookupPrivilegeValue (NULL, name, &tp.Privileges[0].Luid))
return GetLastError ();
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
HANDLE t;
/* OpenProcessToken does not work here, because main thread has its own
impersonation token */
if (!OpenThreadToken (GetCurrentThread (), TOKEN_ADJUST_PRIVILEGES, FALSE, &t))
return GetLastError ();
AdjustTokenPrivileges (t, FALSE, &tp, 0, NULL, NULL);
DWORD rv = GetLastError ();
CloseHandle (t);
return rv;
}
int
cmd_save ()
{
if (!argv[1])
{
usage ();
return 1;
}
/* try to set SeBackupPrivilege, let RegSaveKey report the error */
set_privilege (SE_BACKUP_NAME);
/* REG_OPTION_BACKUP_RESTORE is necessary to save /HKLM/SECURITY */
find_key (1, KEY_QUERY_VALUE, REG_OPTION_BACKUP_RESTORE);
char win32_path[MAX_PATH];
cygwin_conv_to_win32_path (argv[1], win32_path);
DWORD rv = RegSaveKey (key, win32_path, NULL);
if (rv != ERROR_SUCCESS)
Fail (rv);
if (verbose)
printf ("key saved to %s\n", win32_path);
return 0;
}
struct struct
{ {
const char *name; const char *name;
@ -623,6 +781,9 @@ struct
{"set", cmd_set}, {"set", cmd_set},
{"unset", cmd_unset}, {"unset", cmd_unset},
{"get", cmd_get}, {"get", cmd_get},
{"load", cmd_load},
{"unload", cmd_unload},
{"save", cmd_save},
{0, 0} {0, 0}
}; };
@ -642,6 +803,9 @@ main (int argc, char **_argv)
while ((g = getopt_long (argc, _argv, opts, longopts, NULL)) != EOF) while ((g = getopt_long (argc, _argv, opts, longopts, NULL)) != EOF)
switch (g) switch (g)
{ {
case 'b':
key_type = KT_BINARY;
break;
case 'e': case 'e':
key_type = KT_EXPAND; key_type = KT_EXPAND;
break; break;

View File

@ -1023,7 +1023,7 @@ option.
<sect2 id="regtool"><title>regtool</title> <sect2 id="regtool"><title>regtool</title>
<screen> <screen>
Usage: regtool.exe [OPTION] (add | check | get | list | remove | unset) KEY Usage: regtool [OPTION] (add|check|get|list|remove|unset|load|unload|save) KEY
View or edit the Win32 registry View or edit the Win32 registry
Actions: Actions:
@ -1034,13 +1034,20 @@ Actions:
remove KEY remove KEY remove KEY remove KEY
set KEY\VALUE [data ...] set VALUE set KEY\VALUE [data ...] set VALUE
unset KEY\VALUE removes VALUE from KEY unset KEY\VALUE removes VALUE from KEY
load KEY\SUBKEY PATH load hive from PATH into new SUBKEY
unload KEY\SUBKEY unload hive and remove SUBKEY
save KEY\SUBKEY PATH save SUBKEY into new hive PATH
Options for 'list' Action: Options for 'list' Action:
-k, --keys print only KEYs -k, --keys print only KEYs
-l, --list print only VALUEs -l, --list print only VALUEs
-p, --postfix like ls -p, appends '\' postfix to KEY names -p, --postfix like ls -p, appends '\' postfix to KEY names
Options for 'get' Action:
-b, --binary print REG_BINARY data as hex bytes
Options for 'set' Action: Options for 'set' Action:
-b, --binary set type to REG_BINARY (hex args or '-')
-e, --expand-string set type to REG_EXPAND_SZ -e, --expand-string set type to REG_EXPAND_SZ
-i, --integer set type to REG_DWORD -i, --integer set type to REG_DWORD
-m, --multi-string set type to REG_MULTI_SZ -m, --multi-string set type to REG_MULTI_SZ
@ -1109,6 +1116,10 @@ accidentally removing too much.
</para> </para>
<para>The <literal>set</literal> action sets a value within a key. <para>The <literal>set</literal> action sets a value within a key.
<literal>-b</literal> means it's binary data (REG_BINARY).
The binary values are specified as hex bytes in the argument list.
If the argument is <literal>'-'</literal>, binary data is read
from stdin instead.
<literal>-e</literal> means it's an expanding string (REG_EXPAND_SZ) <literal>-e</literal> means it's an expanding string (REG_EXPAND_SZ)
that contains embedded environment variables. that contains embedded environment variables.
<literal>-i</literal> means the value is an integer (REG_DWORD). <literal>-i</literal> means the value is an integer (REG_DWORD).
@ -1122,6 +1133,17 @@ a regular string.
The <literal>unset</literal> action removes a value from a key. The <literal>unset</literal> action removes a value from a key.
</para> </para>
<para>The <literal>load</literal> action adds a new subkey and loads
the contents of a registry hive into it.
The parent key must be HKEY_LOCAL_MACHINE or HKEY_USERS.
The <literal>unload</literal> action unloads the file and removes
the subkey.
</para>
<para>The <literal>save</literal> action saves a subkey into a
registry hive.
</para>
<para> <para>
By default, the last "\" or "/" is assumed to be the separator between the By default, the last "\" or "/" is assumed to be the separator between the
key and the value. You can use the <literal>-K</literal> option to provide key and the value. You can use the <literal>-K</literal> option to provide