diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2011-04-05 12:44:34 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2011-04-05 20:01:15 +0100 |
commit | 9e7c6a548353bde925c16434711bcc6208038d83 (patch) | |
tree | b1b46b05e7319a36c38813a3b1eb15eb277ed948 | |
parent | 9b945cfa781a0f25c3b81239e2fcddceeede6e44 (diff) | |
download | libguestfs-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.c | 31 | ||||
-rw-r--r-- | generator/generator_actions.ml | 16 | ||||
-rw-r--r-- | images/guest-aux/windows-system.reg | 6 | ||||
-rw-r--r-- | inspector/example-windows.xml | 1 | ||||
-rw-r--r-- | inspector/virt-inspector.c | 8 | ||||
-rw-r--r-- | inspector/virt-inspector.rng | 2 | ||||
-rw-r--r-- | src/guestfs-internal.h | 1 | ||||
-rw-r--r-- | src/inspect.c | 74 |
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); |