Alex Nelson
2011-Dec-13 05:59 UTC
[Libguestfs] [hivex] [PATCH 1/2] hivex: Expose hive major and minor version
The major and minor version were being reported in a debug message. This patch adds the version information to the ABI and reports with hivexml. Signed-off-by: Alex Nelson <ajnelson at cs.ucsc.edu> --- generator/generator.ml | 10 ++++++++++ lib/hivex.c | 32 +++++++++++++++++++++++++++----- xml/hivexml.c | 24 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/generator/generator.ml b/generator/generator.ml index 065c25d..fc7b483 100755 --- a/generator/generator.ml +++ b/generator/generator.ml @@ -159,6 +159,16 @@ but instead are lost. See L<hivex(3)/WRITING TO HIVE FILES>."; "\ Return root node of the hive. All valid hives must contain a root node."; + "major_version", (RInt32, [AHive]), + "return the major version of the hive", + "\ +Return major version stored in the hive header, -1 on error."; + + "minor_version", (RInt32, [AHive]), + "return the minor version of the hive", + "\ +Return minor version stored in the hive header, -1 on error."; + "last_modified", (RInt64, [AHive]), "return the modification time from the header of the hive", "\ diff --git a/lib/hivex.c b/lib/hivex.c index bf1a860..455202f 100644 --- a/lib/hivex.c +++ b/lib/hivex.c @@ -64,7 +64,7 @@ struct ntreg_header { uint32_t sequence2; int64_t last_modified; uint32_t major_ver; /* 1 */ - uint32_t minor_ver; /* 3 */ + uint32_t minor_ver; /* Seen as 3 in XP, 5 in Vista */ uint32_t unknown5; /* 0 */ uint32_t unknown6; /* 1 */ uint32_t offset; /* offset of root key record - 4KB */ @@ -303,7 +303,7 @@ hivex_open (const char *filename, int flags) } /* Check major version. */ - uint32_t major_ver = le32toh (h->hdr->major_ver); + int32_t major_ver = hivex_major_version (h); if (major_ver != 1) { fprintf (stderr, "hivex: %s: hive file major version %" PRIu32 " (expected 1)\n", @@ -312,6 +312,16 @@ hivex_open (const char *filename, int flags) goto error; } + /* Check minor version; if unable to decode, terminate. */ + int32_t minor_ver = hivex_minor_version (h); + if (minor_ver < 0) { + fprintf (stderr, + "hivex: %s: could not decode hive minor version\n", + filename); + errno = EINVAL; + goto error; + } + h->bitmap = calloc (1 + h->size / 32, 1); if (h->bitmap == NULL) goto error; @@ -328,11 +338,11 @@ hivex_open (const char *filename, int flags) h->last_modified = le64toh ((int64_t) h->hdr->last_modified); if (h->msglvl >= 2) { - char *name = windows_utf16_to_utf8 (h->hdr->name, 64); + char *name = hivex_name (h); fprintf (stderr, "hivex_open: header fields:\n" - " file version %" PRIu32 ".%" PRIu32 "\n" + " file version %" PRIi32 ".%" PRIi32 "\n" " sequence nos %" PRIu32 " %" PRIu32 "\n" " (sequences nos should match if hive was synched at shutdown)\n" " last modified %" PRIu64 "\n" @@ -342,7 +352,7 @@ hivex_open (const char *filename, int flags) " root offset 0x%x + 0x1000\n" " end of last page 0x%x + 0x1000 (total file size 0x%zx)\n" " checksum 0x%x (calculated 0x%x)\n", - major_ver, le32toh (h->hdr->minor_ver), + major_ver, minor_ver, le32toh (h->hdr->sequence1), le32toh (h->hdr->sequence2), h->last_modified, name ? name : "(conversion failed)", @@ -624,6 +634,18 @@ hivex_last_modified (hive_h *h) return timestamp_check (h, 0, h->last_modified); } +int32_t +hivex_major_version (hive_h *h) +{ + return (h && h->hdr) ? (int32_t) le32toh (h->hdr->major_ver) : -1; +} + +int32_t +hivex_minor_version (hive_h *h) +{ + return (h && h->hdr) ? (int32_t) le32toh (h->hdr->minor_ver) : -1; +} + int64_t hivex_node_timestamp (hive_h *h, hive_node_h node) { diff --git a/xml/hivexml.c b/xml/hivexml.c index d38e9d4..3a4d9b7 100644 --- a/xml/hivexml.c +++ b/xml/hivexml.c @@ -136,6 +136,30 @@ main (int argc, char *argv[]) XML_CHECK (xmlTextWriterStartDocument, (writer, NULL, "utf-8", NULL)); XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "hive")); + /* Report the version. */ + int32_t hive_major_version = hivex_major_version (h); + int32_t hive_minor_version = hivex_minor_version (h); + if (hive_major_version < 0) { + fprintf (stderr, _("hive_major_version: failed to determine major version\n")); + exit (EXIT_FAILURE); + } else if (hive_minor_version < 0) { + fprintf (stderr, _("hive_minor_version: failed to determine minor version\n")); + exit (EXIT_FAILURE); + } else { + char *hive_version_buf = (char *) calloc (8, sizeof (char)); + if (hive_version_buf == NULL) { + fprintf (stderr, _("calloc: failed to allocate version buffer\n")); + exit (EXIT_FAILURE); + } else { + snprintf (hive_version_buf, 8, "%" PRIu32 ".%" PRIu32, hive_major_version, hive_minor_version); + XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "hive_version")); + XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST hive_version_buf)); + XML_CHECK (xmlTextWriterEndAttribute, (writer)); + free (hive_version_buf); + hive_version_buf = NULL; + } + } + int64_t hive_mtime = hivex_last_modified (h); if (hive_mtime >= 0) { char *timebuf = filetime_to_8601 (hive_mtime); -- 1.7.6.4
Richard W.M. Jones
2012-Jan-05 14:00 UTC
[Libguestfs] [hivex] [PATCH 1/2] hivex: Expose hive major and minor version
On Mon, Dec 12, 2011 at 09:59:18PM -0800, Alex Nelson wrote:> The major and minor version were being reported in a debug message. > This patch adds the version information to the ABI and reports with > hivexml. > + "major_version", (RInt32, [AHive]), > + "return the major version of the hive", > + "\ > +Return major version stored in the hive header, -1 on error.";You don't need to say what it returns on error, since the generator will do this. That's the theory. Unfortunately the generated code for RInt32 is wrong; although the only existing function that returns RInt32 (hivex_value_dword) returns -1 on error *and* sets errno, the generator doesn't document this. You'll need a small and simple patch to the generator to fix this.> + /* Check minor version; if unable to decode, terminate. */ > + int32_t minor_ver = hivex_minor_version (h); > + if (minor_ver < 0) { > + fprintf (stderr, > + "hivex: %s: could not decode hive minor version\n", > + filename); > + errno = EINVAL; > + goto error;hivex_major_version should set the errno (see below), so you shouldn't set it here ...> +int32_t > +hivex_major_version (hive_h *h) > +{ > + return (h && h->hdr) ? (int32_t) le32toh (h->hdr->major_ver) : -1; > +}I think these two functions should set errno on error, so: int32_t hivex_major_version (hive_h *h) { if (!h || !h->hdr) { errno = EINVAL; return -1; } return le32toh (h->hdr->major_ver); } Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/
Apparently Analagous Threads
- [Hivex] [PATCH v3] Report last-modified time of hive root and nodes
- [hivex] [PATCH 2/2] hivex: Expose embedded hive file name
- [Hivex][PATCH v2] Report last-modified time of hive root and nodes
- [PATCH] Report last-modified time of hive root and nodes
- [PATCH] hivex: Add byte runs for nodes and values