summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2011-04-05 12:44:34 +0100
committerRichard W.M. Jones <rjones@redhat.com>2011-04-05 20:01:15 +0100
commit9e7c6a548353bde925c16434711bcc6208038d83 (patch)
treeb1b46b05e7319a36c38813a3b1eb15eb277ed948
parent9b945cfa781a0f25c3b81239e2fcddceeede6e44 (diff)
downloadlibguestfs-9e7c6a548353bde925c16434711bcc6208038d83.tar.gz
libguestfs-9e7c6a548353bde925c16434711bcc6208038d83.tar.xz
libguestfs-9e7c6a548353bde925c16434711bcc6208038d83.zip
New API: inspect-get-windows-current-control-set
This returns the actual registry key corresponding to CurrentControlSet (eg. it might be "ControlSet001"). Previously the inspection code was hard-coding ControlSet001. Now we use the correct control set, and also make it available to callers through the API. This commit also updates the virt-dhcp-address example so it uses this new API. virt-inspector displays the current control set when available.
-rw-r--r--examples/virt-dhcp-address.c31
-rw-r--r--generator/generator_actions.ml16
-rw-r--r--images/guest-aux/windows-system.reg6
-rw-r--r--inspector/example-windows.xml1
-rw-r--r--inspector/virt-inspector.c8
-rw-r--r--inspector/virt-inspector.rng2
-rw-r--r--src/guestfs-internal.h1
-rw-r--r--src/inspect.c74
8 files changed, 106 insertions, 33 deletions
diff --git a/examples/virt-dhcp-address.c b/examples/virt-dhcp-address.c
index c075a473..5b68313a 100644
--- a/examples/virt-dhcp-address.c
+++ b/examples/virt-dhcp-address.c
@@ -189,7 +189,7 @@ print_dhcp_address_linux (guestfs_h *g, char *root, const char *logfile)
/* Download the Windows SYSTEM hive and find DHCP configuration in there. */
static void
-print_dhcp_address_windows (guestfs_h *g, char *root_unused)
+print_dhcp_address_windows (guestfs_h *g, char *root_fs)
{
char *system_path;
char tmpfile[] = "/tmp/systemXXXXXX";
@@ -197,8 +197,7 @@ print_dhcp_address_windows (guestfs_h *g, char *root_unused)
hive_h *h;
hive_node_h root, node, *nodes;
hive_value_h value;
- int32_t dword;
- char controlset[] = "ControlSetXXX";
+ char *controlset;
size_t i;
char *p;
@@ -222,6 +221,10 @@ print_dhcp_address_windows (guestfs_h *g, char *root_unused)
free (system_path);
+ controlset = guestfs_inspect_get_windows_current_control_set (g, root_fs);
+ if (controlset == NULL)
+ exit (EXIT_FAILURE);
+
/* Open the hive to parse it. */
h = hivex_open (tmpfile, 0);
err = errno;
@@ -234,31 +237,11 @@ print_dhcp_address_windows (guestfs_h *g, char *root_unused)
exit (EXIT_FAILURE);
}
- /* Navigate to the Select key so we know which ControlSet is in use. */
root = hivex_root (h);
if (root == 0) {
perror ("hivex_root");
exit (EXIT_FAILURE);
}
- node = hivex_node_get_child (h, root, "Select");
- if (node == 0) {
- if (errno != 0)
- perror ("hivex_node_get_child");
- else
- fprintf (stderr, "virt-dhcp-address: HKLM\\System\\Select key not found.");
- exit (EXIT_FAILURE);
- }
- value = hivex_node_get_value (h, node, "Current");
- if (value == 0) {
- if (errno != 0)
- perror ("hivex_node_get_value");
- else
- fprintf (stderr, "virt-dhcp-address: HKLM\\System\\Select Default entry not found.");
- exit (EXIT_FAILURE);
- }
- /* XXX Should check the type. */
- dword = hivex_value_dword (h, value);
- snprintf (controlset, sizeof controlset, "ControlSet%03d", dword);
/* Get ControlSetXXX\Services\Tcpip\Parameters\Interfaces. */
const char *path[] = { controlset, "Services", "Tcpip", "Parameters",
@@ -311,6 +294,8 @@ print_dhcp_address_windows (guestfs_h *g, char *root_unused)
/* Close the hive handle. */
hivex_close (h);
+
+ free (controlset);
}
static int
diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
index a10b7f74..c59964ab 100644
--- a/generator/generator_actions.ml
+++ b/generator/generator_actions.ml
@@ -1451,6 +1451,22 @@ Please read L<guestfs(3)/INSPECTION> for more details.
See also C<guestfs_inspect_get_product_name>,
C<guestfs_inspect_get_major_version>.");
+ ("inspect_get_windows_current_control_set", (RString "controlset", [Device "root"], []), -1, [],
+ [],
+ "get Windows CurrentControlSet of inspected operating system",
+ "\
+This function should only be called with a root device string
+as returned by C<guestfs_inspect_os>.
+
+This returns the Windows CurrentControlSet of the inspected guest.
+The CurrentControlSet is a registry key name such as C<ControlSet001>.
+
+This call assumes that the guest is Windows and that the
+Registry could be examined by inspection. If this is not
+the case then an error is returned.
+
+Please read L<guestfs(3)/INSPECTION> for more details.");
+
]
(* daemon_functions are any functions which cause some action
diff --git a/images/guest-aux/windows-system.reg b/images/guest-aux/windows-system.reg
index 87ae7796..6cb5d324 100644
--- a/images/guest-aux/windows-system.reg
+++ b/images/guest-aux/windows-system.reg
@@ -1,3 +1,9 @@
+[HKEY_LOCAL_MACHINE\SYSTEM\Select]
+"Current"=dword:00000001
+"Default"=dword:00000001
+"Failed"=dword:00000000
+"LastKnownGood"=dword:00000002
+
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001]
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services]
diff --git a/inspector/example-windows.xml b/inspector/example-windows.xml
index 7b3ae743..8e53159a 100644
--- a/inspector/example-windows.xml
+++ b/inspector/example-windows.xml
@@ -10,6 +10,7 @@
<major_version>6</major_version>
<minor_version>1</minor_version>
<windows_systemroot>/Windows</windows_systemroot>
+ <windows_current_control_set>ControlSet001</windows_current_control_set>
<format>installed</format>
<mountpoints>
<mountpoint dev="/dev/sda2">/</mountpoint>
diff --git a/inspector/virt-inspector.c b/inspector/virt-inspector.c
index 4d8e3adc..d016b2dd 100644
--- a/inspector/virt-inspector.c
+++ b/inspector/virt-inspector.c
@@ -416,6 +416,14 @@ output_root (xmlTextWriterPtr xo, char *root)
BAD_CAST str));
free (str);
);
+ DISABLE_GUESTFS_ERRORS_FOR (
+ str = guestfs_inspect_get_windows_current_control_set (g, root);
+ if (str)
+ XMLERROR (-1,
+ xmlTextWriterWriteElement (xo, BAD_CAST "windows_current_control_set",
+ BAD_CAST str));
+ free (str);
+ );
str = guestfs_inspect_get_format (g, root);
if (!str) exit (EXIT_FAILURE);
diff --git a/inspector/virt-inspector.rng b/inspector/virt-inspector.rng
index 8d54facd..7a822e68 100644
--- a/inspector/virt-inspector.rng
+++ b/inspector/virt-inspector.rng
@@ -37,7 +37,7 @@
<element name="major_version"><text/></element>
<element name="minor_version"><text/></element>
<optional><element name="windows_systemroot"><text/></element></optional>
-
+ <optional><element name="windows_current_control_set"><text/></element></optional>
<optional><element name="package_format"><text/></element></optional>
<optional><element name="package_management"><text/></element></optional>
<optional><element name="format"><text/></element></optional>
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 3a63f2e3..b29fa577 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -251,6 +251,7 @@ struct inspect_fs {
char *arch;
char *hostname;
char *windows_systemroot;
+ char *windows_current_control_set;
enum inspect_os_format format;
int is_live_disk;
int is_netinst_disk;
diff --git a/src/inspect.c b/src/inspect.c
index a4f0f987..154207b9 100644
--- a/src/inspect.c
+++ b/src/inspect.c
@@ -25,6 +25,7 @@
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
+#include <errno.h>
#ifdef HAVE_PCRE
#include <pcre.h>
@@ -1612,7 +1613,10 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
int ret = -1;
hive_h *h = NULL;
- hive_value_h *values = NULL;
+ hive_node_h root, node;
+ hive_value_h value, *values = NULL;
+ int32_t dword;
+ size_t i;
if (download_to_tmp (g, system_path, system_local, MAX_REGISTRY_SIZE) == -1)
goto out;
@@ -1623,21 +1627,49 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
goto out;
}
- hive_node_h node = hivex_root (h);
- /* XXX Don't hard-code ControlSet001. The current control set would
- * be another good thing to expose up through the inspection API.
- */
+ root = hivex_root (h);
+ if (root == 0) {
+ perrorf (g, "hivex_root");
+ goto out;
+ }
+
+ /* Get the CurrentControlSet. */
+ errno = 0;
+ node = hivex_node_get_child (h, root, "Select");
+ if (node == 0) {
+ if (errno != 0)
+ perrorf (g, "hivex_node_get_child");
+ else
+ error (g, "hivex: could not locate HKLM\\SYSTEM\\Select");
+ goto out;
+ }
+
+ errno = 0;
+ value = hivex_node_get_value (h, node, "Current");
+ if (value == 0) {
+ if (errno != 0)
+ perrorf (g, "hivex_node_get_value");
+ else
+ error (g, "hivex: HKLM\\System\\Select Default entry not found.");
+ goto out;
+ }
+
+ /* XXX Should check the type. */
+ dword = hivex_value_dword (h, value);
+ fs->windows_current_control_set = safe_asprintf (g, "ControlSet%03d", dword);
+
+ /* Get the hostname. */
const char *hivepath[] =
- { "ControlSet001", "Services", "Tcpip", "Parameters" };
- size_t i;
- for (i = 0;
+ { fs->windows_current_control_set, "Services", "Tcpip", "Parameters" };
+ for (node = root, i = 0;
node != 0 && i < sizeof hivepath / sizeof hivepath[0];
++i) {
node = hivex_node_get_child (h, node, hivepath[i]);
}
if (node == 0) {
- perrorf (g, "hivex: cannot locate HKLM\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters");
+ perrorf (g, "hivex: cannot locate HKLM\\SYSTEM\\%s\\Services\\Tcpip\\Parameters",
+ fs->windows_current_control_set);
goto out;
}
@@ -2011,6 +2043,22 @@ guestfs__inspect_get_windows_systemroot (guestfs_h *g, const char *root)
}
char *
+guestfs__inspect_get_windows_current_control_set (guestfs_h *g,
+ const char *root)
+{
+ struct inspect_fs *fs = search_for_root (g, root);
+ if (!fs)
+ return NULL;
+
+ if (!fs->windows_current_control_set) {
+ error (g, _("not a Windows guest, or CurrentControlSet could not be determined"));
+ return NULL;
+ }
+
+ return safe_strdup (g, fs->windows_current_control_set);
+}
+
+char *
guestfs__inspect_get_format (guestfs_h *g, const char *root)
{
struct inspect_fs *fs = search_for_root (g, root);
@@ -2905,6 +2953,13 @@ guestfs__inspect_get_windows_systemroot (guestfs_h *g, const char *root)
NOT_IMPL(NULL);
}
+char *
+guestfs__inspect_get_windows_current_control_set (guestfs_h *g,
+ const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
char **
guestfs__inspect_get_mountpoints (guestfs_h *g, const char *root)
{
@@ -2978,6 +3033,7 @@ guestfs___free_inspect_info (guestfs_h *g)
free (g->fses[i].arch);
free (g->fses[i].hostname);
free (g->fses[i].windows_systemroot);
+ free (g->fses[i].windows_current_control_set);
size_t j;
for (j = 0; j < g->fses[i].nr_fstab; ++j) {
free (g->fses[i].fstab[j].device);