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/
Seemingly Similar 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