/* At the moment, pull just the ProductName and version numbers from * the registry. In future there is a case for making many more * registry fields available to callers. */ static int check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs) { int ret = -1; int r; size_t len = strlen (fs->windows_systemroot) + 64; char software[len]; snprintf (software, len, "%s/system32/config/software", fs->windows_systemroot); CLEANUP_FREE char *software_path = guestfs_case_sensitive_path (g, software); if (!software_path) return -1; r = guestfs_is_file (g, software_path); if (r == -1) return -1; /* If the software hive doesn't exist, just accept that we cannot * find product_name etc. */ if (r == 0) return 0; int64_t node; const char *hivepath[] = { "Microsoft", "Windows NT", "CurrentVersion" }; size_t i; CLEANUP_FREE_HIVEX_VALUE_LIST struct guestfs_hivex_value_list *values = NULL; if (guestfs_hivex_open (g, software_path, GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1) return -1; node = guestfs_hivex_root (g); for (i = 0; node > 0 && i < sizeof hivepath / sizeof hivepath[0]; ++i) node = guestfs_hivex_node_get_child (g, node, hivepath[i]); if (node == -1) goto out; if (node == 0) { perrorf (g, "hivex: cannot locate HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"); goto out; } values = guestfs_hivex_node_values (g, node); for (i = 0; i < values->len; ++i) { int64_t value = values->val[i].hivex_value_h; CLEANUP_FREE char *key = guestfs_hivex_value_key (g, value); if (key == NULL) goto out; if (STRCASEEQ (key, "ProductName")) { fs->product_name = guestfs_hivex_value_utf8 (g, value); if (!fs->product_name) goto out; } else if (STRCASEEQ (key, "CurrentVersion")) { CLEANUP_FREE char *version = guestfs_hivex_value_utf8 (g, value); if (!version) goto out; char *major, *minor; if (match2 (g, version, re_windows_version, &major, &minor)) { fs->major_version = guestfs___parse_unsigned_int (g, major); free (major); if (fs->major_version == -1) { free (minor); goto out; } fs->minor_version = guestfs___parse_unsigned_int (g, minor); free (minor); if (fs->minor_version == -1) goto out; } } else if (STRCASEEQ (key, "InstallationType")) { fs->product_variant = guestfs_hivex_value_utf8 (g, value); if (!fs->product_variant) goto out; } } ret = 0; out: guestfs_hivex_close (g); return ret; }
static int check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs) { int r; size_t len = strlen (fs->windows_systemroot) + 64; char system[len]; snprintf (system, len, "%s/system32/config/system", fs->windows_systemroot); CLEANUP_FREE char *system_path = guestfs_case_sensitive_path (g, system); if (!system_path) return -1; r = guestfs_is_file (g, system_path); if (r == -1) return -1; /* If the system hive doesn't exist, just accept that we cannot * find hostname etc. */ if (r == 0) return 0; int ret = -1; int64_t root, node, value; CLEANUP_FREE_HIVEX_VALUE_LIST struct guestfs_hivex_value_list *values = NULL; CLEANUP_FREE_HIVEX_VALUE_LIST struct guestfs_hivex_value_list *values2 = NULL; int32_t dword; size_t i, count; CLEANUP_FREE void *buf = NULL; size_t buflen; const char *hivepath[] = { NULL /* current control set */, "Services", "Tcpip", "Parameters" }; if (guestfs_hivex_open (g, system_path, GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1) goto out; root = guestfs_hivex_root (g); if (root == 0) goto out; /* Get the CurrentControlSet. */ node = guestfs_hivex_node_get_child (g, root, "Select"); if (node == -1) goto out; if (node == 0) { error (g, "hivex: could not locate HKLM\\SYSTEM\\Select"); goto out; } value = guestfs_hivex_node_get_value (g, node, "Current"); if (value == -1) goto out; if (value == 0) { error (g, "hivex: HKLM\\System\\Select Default entry not found"); goto out; } /* XXX Should check the type. */ buf = guestfs_hivex_value_value (g, value, &buflen); if (buflen != 4) { error (g, "hivex: HKLM\\System\\Select\\Current expected to be DWORD"); goto out; } dword = le32toh (*(int32_t *)buf); fs->windows_current_control_set = safe_asprintf (g, "ControlSet%03d", dword); /* Get the drive mappings. * This page explains the contents of HKLM\System\MountedDevices: * http://www.goodells.net/multiboot/partsigs.shtml */ node = guestfs_hivex_node_get_child (g, root, "MountedDevices"); if (node == -1) goto out; if (node == 0) /* Not found: skip getting drive letter mappings (RHBZ#803664). */ goto skip_drive_letter_mappings; values = guestfs_hivex_node_values (g, node); /* Count how many DOS drive letter mappings there are. This doesn't * ignore removable devices, so it overestimates, but that doesn't * matter because it just means we'll allocate a few bytes extra. */ for (i = count = 0; i < values->len; ++i) { CLEANUP_FREE char *key = guestfs_hivex_value_key (g, values->val[i].hivex_value_h); if (key == NULL) goto out; if (STRCASEEQLEN (key, "\\DosDevices\\", 12) && c_isalpha (key[12]) && key[13] == ':') count++; } fs->drive_mappings = safe_calloc (g, 2*count + 1, sizeof (char *)); for (i = count = 0; i < values->len; ++i) { int64_t v = values->val[i].hivex_value_h; CLEANUP_FREE char *key = guestfs_hivex_value_key (g, v); if (key == NULL) goto out; if (STRCASEEQLEN (key, "\\DosDevices\\", 12) && c_isalpha (key[12]) && key[13] == ':') { /* Get the binary value. Is it a fixed disk? */ CLEANUP_FREE char *blob = NULL; char *device; size_t len; int64_t type; type = guestfs_hivex_value_type (g, v); blob = guestfs_hivex_value_value (g, v, &len); if (blob != NULL && type == 3 && len == 12) { /* Try to map the blob to a known disk and partition. */ device = map_registry_disk_blob (g, blob); if (device != NULL) { fs->drive_mappings[count++] = safe_strndup (g, &key[12], 1); fs->drive_mappings[count++] = device; } } } } skip_drive_letter_mappings:; /* Get the hostname. */ hivepath[0] = fs->windows_current_control_set; for (node = root, i = 0; node > 0 && i < sizeof hivepath / sizeof hivepath[0]; ++i) { node = guestfs_hivex_node_get_child (g, node, hivepath[i]); } if (node == -1) goto out; if (node == 0) { perrorf (g, "hivex: cannot locate HKLM\\SYSTEM\\%s\\Services\\Tcpip\\Parameters", fs->windows_current_control_set); goto out; } values2 = guestfs_hivex_node_values (g, node); if (values2 == NULL) goto out; for (i = 0; i < values2->len; ++i) { int64_t v = values2->val[i].hivex_value_h; CLEANUP_FREE char *key = guestfs_hivex_value_key (g, v); if (key == NULL) goto out; if (STRCASEEQ (key, "Hostname")) { fs->hostname = guestfs_hivex_value_utf8 (g, v); if (!fs->hostname) goto out; } /* many other interesting fields here ... */ } ret = 0; out: guestfs_hivex_close (g); return ret; }
/* At the moment, pull just the ProductName and version numbers from * the registry. In future there is a case for making many more * registry fields available to callers. */ static int check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs) { int ret = -1; int r; CLEANUP_FREE char *software = safe_asprintf (g, "%s/system32/config/software", fs->windows_systemroot); CLEANUP_FREE char *software_path = guestfs_case_sensitive_path (g, software); if (!software_path) return -1; r = guestfs_is_file (g, software_path); if (r == -1) return -1; /* If the software hive doesn't exist, just accept that we cannot * find product_name etc. */ if (r == 0) return 0; int64_t node; const char *hivepath[] = { "Microsoft", "Windows NT", "CurrentVersion" }; size_t i; CLEANUP_FREE_HIVEX_VALUE_LIST struct guestfs_hivex_value_list *values = NULL; bool ignore_currentversion = false; if (guestfs_hivex_open (g, software_path, GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1) return -1; node = guestfs_hivex_root (g); for (i = 0; node > 0 && i < sizeof hivepath / sizeof hivepath[0]; ++i) node = guestfs_hivex_node_get_child (g, node, hivepath[i]); if (node == -1) goto out; if (node == 0) { perrorf (g, "hivex: cannot locate HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"); goto out; } values = guestfs_hivex_node_values (g, node); for (i = 0; i < values->len; ++i) { int64_t value = values->val[i].hivex_value_h; CLEANUP_FREE char *key = guestfs_hivex_value_key (g, value); if (key == NULL) goto out; if (STRCASEEQ (key, "ProductName")) { fs->product_name = guestfs_hivex_value_utf8 (g, value); if (!fs->product_name) goto out; } else if (STRCASEEQ (key, "CurrentMajorVersionNumber")) { size_t vsize; int64_t vtype = guestfs_hivex_value_type (g, value); CLEANUP_FREE char *vbuf = guestfs_hivex_value_value (g, value, &vsize); if (vbuf == NULL) goto out; if (vtype != 4 || vsize != 4) { error (g, "hivex: expected CurrentVersion\\%s to be a DWORD field", "CurrentMajorVersionNumber"); goto out; } fs->version.v_major = le32toh (*(int32_t *)vbuf); /* Ignore CurrentVersion if we see it after this key. */ ignore_currentversion = true; } else if (STRCASEEQ (key, "CurrentMinorVersionNumber")) { size_t vsize; int64_t vtype = guestfs_hivex_value_type (g, value); CLEANUP_FREE char *vbuf = guestfs_hivex_value_value (g, value, &vsize); if (vbuf == NULL) goto out; if (vtype != 4 || vsize != 4) { error (g, "hivex: expected CurrentVersion\\%s to be a DWORD field", "CurrentMinorVersionNumber"); goto out; } fs->version.v_minor = le32toh (*(int32_t *)vbuf); /* Ignore CurrentVersion if we see it after this key. */ ignore_currentversion = true; } else if (!ignore_currentversion && STRCASEEQ (key, "CurrentVersion")) { CLEANUP_FREE char *version = guestfs_hivex_value_utf8 (g, value); if (!version) goto out; if (guestfs_int_version_from_x_y_re (g, &fs->version, version, re_windows_version) == -1) goto out; } else if (STRCASEEQ (key, "InstallationType")) { fs->product_variant = guestfs_hivex_value_utf8 (g, value); if (!fs->product_variant) goto out; } } ret = 0; out: guestfs_hivex_close (g); return ret; }