X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fhivex.c;h=4b9fcf0512a80a1184417ce9ed541fae9b3440d3;hb=96f1edbae1ed41ec1c4e558060b7b33b6b749ea4;hp=b1f6ea69954ae794d4ed7b19b19092d1db151c14;hpb=c22ed5a6cb58aff70bf74df5b7c1edd33d796ef4;p=hivex.git diff --git a/lib/hivex.c b/lib/hivex.c index b1f6ea6..4b9fcf0 100644 --- a/lib/hivex.c +++ b/lib/hivex.c @@ -1,5 +1,5 @@ /* hivex - Windows Registry "hive" extraction library. - * Copyright (C) 2009-2010 Red Hat Inc. + * Copyright (C) 2009-2011 Red Hat Inc. * Derived from code by Petter Nordahl-Hagen under a compatible license: * Copyright (c) 1997-2007 Petter Nordahl-Hagen. * Derived from code by Markus Stephany under a compatible license: @@ -38,10 +38,6 @@ #include "full-read.h" #include "full-write.h" -#ifndef O_CLOEXEC -#define O_CLOEXEC 0 -#endif - #define STREQ(a,b) (strcmp((a),(b)) == 0) #define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0) //#define STRNEQ(a,b) (strcmp((a),(b)) != 0) @@ -62,7 +58,6 @@ #define HIVEX_MAX_ALLOCATION 1000000 static char *windows_utf16_to_utf8 (/* const */ char *input, size_t len); -static size_t utf16_string_len_in_bytes (const char *str); static size_t utf16_string_len_in_bytes_max (const char *str, size_t len); struct hive_h { @@ -98,6 +93,7 @@ struct hive_h { /* Fields from the header, extracted from little-endianness hell. */ size_t rootoffs; /* Root key offset (always an nk-block). */ size_t endpages; /* Offset of end of pages. */ + int64_t last_modified; /* mtime of base block. */ /* For writing. */ size_t endblocks; /* Offset to next block allocation (0 @@ -109,7 +105,7 @@ struct ntreg_header { char magic[4]; /* "regf" */ uint32_t sequence1; uint32_t sequence2; - char last_modified[8]; + int64_t last_modified; uint32_t major_ver; /* 1 */ uint32_t minor_ver; /* 3 */ uint32_t unknown5; /* 0 */ @@ -178,7 +174,7 @@ struct ntreg_nk_record { int32_t seg_len; /* length (always -ve because used) */ char id[2]; /* "nk" */ uint16_t flags; - char timestamp[8]; + int64_t timestamp; uint32_t unknown1; uint32_t parent; /* offset of owner/parent */ uint32_t nr_subkeys; /* number of subkeys */ @@ -298,9 +294,16 @@ hivex_open (const char *filename, int flags) if (h->filename == NULL) goto error; +#ifdef O_CLOEXEC h->fd = open (filename, O_RDONLY | O_CLOEXEC); +#else + h->fd = open (filename, O_RDONLY); +#endif if (h->fd == -1) goto error; +#ifndef O_CLOEXEC + fcntl (h->fd, F_SETFD, FD_CLOEXEC); +#endif struct stat statbuf; if (fstat (h->fd, &statbuf) == -1) @@ -322,6 +325,13 @@ hivex_open (const char *filename, int flags) if (full_read (h->fd, h->addr, h->size) < h->size) goto error; + + /* We don't need the file descriptor along this path, since we + * have read all the data. + */ + if (close (h->fd) == -1) + goto error; + h->fd = -1; } /* Check header. */ @@ -357,6 +367,9 @@ hivex_open (const char *filename, int flags) goto error; } + /* Last modified time. */ + h->last_modified = le64toh ((int64_t) h->hdr->last_modified); + if (h->msglvl >= 2) { char *name = windows_utf16_to_utf8 (h->hdr->name, 64); @@ -365,6 +378,8 @@ hivex_open (const char *filename, int flags) " file version %" PRIu32 ".%" PRIu32 "\n" " sequence nos %" PRIu32 " %" PRIu32 "\n" " (sequences nos should match if hive was synched at shutdown)\n" + " last modified %" PRIu64 "\n" + " (Windows filetime, x 100 ns since 1601-01-01)\n" " original file name %s\n" " (only 32 chars are stored, name is probably truncated)\n" " root offset 0x%x + 0x1000\n" @@ -372,6 +387,7 @@ hivex_open (const char *filename, int flags) " checksum 0x%x (calculated 0x%x)\n", major_ver, le32toh (h->hdr->minor_ver), le32toh (h->hdr->sequence1), le32toh (h->hdr->sequence2), + h->last_modified, name ? name : "(conversion failed)", le32toh (h->hdr->offset), le32toh (h->hdr->blocks), h->size, @@ -415,7 +431,8 @@ hivex_open (const char *filename, int flags) page->magic[1] != 'b' || page->magic[2] != 'i' || page->magic[3] != 'n') { - fprintf (stderr, "hivex: %s: trailing garbage at end of file (at 0x%zx, after %zu pages)\n", + fprintf (stderr, "hivex: %s: trailing garbage at end of file " + "(at 0x%zx, after %zu pages)\n", filename, off, pages); errno = ENOTSUP; goto error; @@ -453,7 +470,8 @@ hivex_open (const char *filename, int flags) int used; seg_len = block_len (h, blkoff, &used); if (seg_len <= 4 || (seg_len & 3) != 0) { - fprintf (stderr, "hivex: %s: block size %" PRIu32 " at 0x%zx, bad registry\n", + fprintf (stderr, "hivex: %s: block size %" PRIu32 " at 0x%zx," + " bad registry\n", filename, le32toh (block->seg_len), blkoff); errno = ENOTSUP; goto error; @@ -542,7 +560,10 @@ hivex_close (hive_h *h) munmap (h->addr, h->size); else free (h->addr); - r = close (h->fd); + if (h->fd >= 0) + r = close (h->fd); + else + r = 0; free (h->filename); free (h); @@ -558,7 +579,7 @@ hivex_root (hive_h *h) { hive_node_h ret = h->rootoffs; if (!IS_VALID_BLOCK (h, ret)) { - errno = ENOKEY; + errno = HIVEX_NO_KEY; return 0; } return ret; @@ -586,7 +607,8 @@ hivex_node_name (hive_h *h, hive_node_h node) size_t seg_len = block_len (h, node, NULL); if (sizeof (struct ntreg_nk_record) + len - 1 > seg_len) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_name: returning EFAULT because node name is too long (%zu, %zu)\n", + fprintf (stderr, "hivex_node_name: returning EFAULT because node name" + " is too long (%zu, %zu)\n", len, seg_len); errno = EFAULT; return NULL; @@ -600,6 +622,43 @@ hivex_node_name (hive_h *h, hive_node_h node) return ret; } +static int64_t +timestamp_check (hive_h *h, hive_node_h node, int64_t timestamp) +{ + if (timestamp < 0) { + if (h->msglvl >= 2) + fprintf (stderr, "hivex: timestamp_check: " + "negative time reported at %zu: %" PRIi64 "\n", + node, timestamp); + errno = EINVAL; + return -1; + } + + return timestamp; +} + +int64_t +hivex_last_modified (hive_h *h) +{ + return timestamp_check (h, 0, h->last_modified); +} + +int64_t +hivex_node_timestamp (hive_h *h, hive_node_h node) +{ + int64_t ret; + + if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) { + errno = EINVAL; + return -1; + } + + struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node); + + ret = le64toh (nk->timestamp); + return timestamp_check (h, node, ret); +} + #if 0 /* I think the documentation for the sk and classname fields in the nk * record is wrong, or else the offset field is in the wrong place. @@ -733,7 +792,8 @@ get_children (hive_h *h, hive_node_h node, /* Arbitrarily limit the number of subkeys we will ever deal with. */ if (nr_subkeys_in_nk > HIVEX_MAX_SUBKEYS) { if (h->msglvl >= 2) - fprintf (stderr, "hivex: get_children: returning ERANGE because nr_subkeys_in_nk > HIVEX_MAX_SUBKEYS (%zu > %d)\n", + fprintf (stderr, "hivex: get_children: returning ERANGE because " + "nr_subkeys_in_nk > HIVEX_MAX_SUBKEYS (%zu > %d)\n", nr_subkeys_in_nk, HIVEX_MAX_SUBKEYS); errno = ERANGE; goto error; @@ -751,7 +811,8 @@ get_children (hive_h *h, hive_node_h node, subkey_lf += 0x1000; if (!IS_VALID_BLOCK (h, subkey_lf)) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_children: returning EFAULT because subkey_lf is not a valid block (0x%zx)\n", + fprintf (stderr, "hivex_node_children: returning EFAULT" + " because subkey_lf is not a valid block (0x%zx)\n", subkey_lf); errno = EFAULT; goto error; @@ -775,7 +836,8 @@ get_children (hive_h *h, hive_node_h node, size_t nr_subkeys_in_lf = le16toh (lf->nr_keys); if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu, nr_subkeys_in_lf = %zu\n", + fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu," + " nr_subkeys_in_lf = %zu\n", nr_subkeys_in_nk, nr_subkeys_in_lf); if (nr_subkeys_in_nk != nr_subkeys_in_lf) { @@ -786,7 +848,8 @@ get_children (hive_h *h, hive_node_h node, size_t len = block_len (h, subkey_lf, NULL); if (8 + nr_subkeys_in_lf * 8 > len) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_children: returning EFAULT because too many subkeys (%zu, %zu)\n", + fprintf (stderr, "hivex_node_children: returning EFAULT" + " because too many subkeys (%zu, %zu)\n", nr_subkeys_in_lf, len); errno = EFAULT; goto error; @@ -799,7 +862,8 @@ get_children (hive_h *h, hive_node_h node, if (!(flags & GET_CHILDREN_NO_CHECK_NK)) { if (!IS_VALID_BLOCK (h, subkey)) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_children: returning EFAULT because subkey is not a valid block (0x%zx)\n", + fprintf (stderr, "hivex_node_children: returning EFAULT" + " because subkey is not a valid block (0x%zx)\n", subkey); errno = EFAULT; goto error; @@ -823,14 +887,16 @@ get_children (hive_h *h, hive_node_h node, offset += 0x1000; if (!IS_VALID_BLOCK (h, offset)) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_children: returning EFAULT because ri-offset is not a valid block (0x%zx)\n", + fprintf (stderr, "hivex_node_children: returning EFAULT" + " because ri-offset is not a valid block (0x%zx)\n", offset); errno = EFAULT; goto error; } if (!BLOCK_ID_EQ (h, offset, "lf") && !BLOCK_ID_EQ (h, offset, "lh")) { if (h->msglvl >= 2) - fprintf (stderr, "get_children: returning ENOTSUP because ri-record offset does not point to lf/lh (0x%zx)\n", + fprintf (stderr, "get_children: returning ENOTSUP" + " because ri-record offset does not point to lf/lh (0x%zx)\n", offset); errno = ENOTSUP; goto error; @@ -846,7 +912,8 @@ get_children (hive_h *h, hive_node_h node, } if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu, counted = %zu\n", + fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu," + " counted = %zu\n", nr_subkeys_in_nk, count); if (nr_subkeys_in_nk != count) { @@ -862,14 +929,16 @@ get_children (hive_h *h, hive_node_h node, offset += 0x1000; if (!IS_VALID_BLOCK (h, offset)) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_children: returning EFAULT because ri-offset is not a valid block (0x%zx)\n", + fprintf (stderr, "hivex_node_children: returning EFAULT" + " because ri-offset is not a valid block (0x%zx)\n", offset); errno = EFAULT; goto error; } if (!BLOCK_ID_EQ (h, offset, "lf") && !BLOCK_ID_EQ (h, offset, "lh")) { if (h->msglvl >= 2) - fprintf (stderr, "get_children: returning ENOTSUP because ri-record offset does not point to lf/lh (0x%zx)\n", + fprintf (stderr, "get_children: returning ENOTSUP" + " because ri-record offset does not point to lf/lh (0x%zx)\n", offset); errno = ENOTSUP; goto error; @@ -885,7 +954,8 @@ get_children (hive_h *h, hive_node_h node, if (!(flags & GET_CHILDREN_NO_CHECK_NK)) { if (!IS_VALID_BLOCK (h, subkey)) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_children: returning EFAULT because indirect subkey is not a valid block (0x%zx)\n", + fprintf (stderr, "hivex_node_children: returning EFAULT" + " because indirect subkey is not a valid block (0x%zx)\n", subkey); errno = EFAULT; goto error; @@ -899,7 +969,8 @@ get_children (hive_h *h, hive_node_h node, } /* else not supported, set errno and fall through */ if (h->msglvl >= 2) - fprintf (stderr, "get_children: returning ENOTSUP because subkey block is not lf/lh/ri (0x%zx, %d, %d)\n", + fprintf (stderr, "get_children: returning ENOTSUP" + " because subkey block is not lf/lh/ri (0x%zx, %d, %d)\n", subkey_lf, block->id[0], block->id[1]); errno = ENOTSUP; error: @@ -972,7 +1043,8 @@ hivex_node_parent (hive_h *h, hive_node_h node) ret += 0x1000; if (!IS_VALID_BLOCK (h, ret)) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_parent: returning EFAULT because parent is not a valid block (0x%zx)\n", + fprintf (stderr, "hivex_node_parent: returning EFAULT" + " because parent is not a valid block (0x%zx)\n", ret); errno = EFAULT; return 0; @@ -1006,7 +1078,8 @@ get_values (hive_h *h, hive_node_h node, /* Arbitrarily limit the number of values we will ever deal with. */ if (nr_values > HIVEX_MAX_VALUES) { if (h->msglvl >= 2) - fprintf (stderr, "hivex: get_values: returning ERANGE because nr_values > HIVEX_MAX_VALUES (%zu > %d)\n", + fprintf (stderr, "hivex: get_values: returning ERANGE" + " because nr_values > HIVEX_MAX_VALUES (%zu > %d)\n", nr_values, HIVEX_MAX_VALUES); errno = ERANGE; goto error; @@ -1021,7 +1094,8 @@ get_values (hive_h *h, hive_node_h node, vlist_offset += 0x1000; if (!IS_VALID_BLOCK (h, vlist_offset)) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_values: returning EFAULT because value list is not a valid block (0x%zx)\n", + fprintf (stderr, "hivex_node_values: returning EFAULT" + " because value list is not a valid block (0x%zx)\n", vlist_offset); errno = EFAULT; goto error; @@ -1036,7 +1110,8 @@ get_values (hive_h *h, hive_node_h node, size_t len = block_len (h, vlist_offset, NULL); if (4 + nr_values * 4 > len) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_values: returning EFAULT because value list is too long (%zu, %zu)\n", + fprintf (stderr, "hivex_node_values: returning EFAULT" + " because value list is too long (%zu, %zu)\n", nr_values, len); errno = EFAULT; goto error; @@ -1044,11 +1119,12 @@ get_values (hive_h *h, hive_node_h node, size_t i; for (i = 0; i < nr_values; ++i) { - hive_node_h value = vlist->offset[i]; + hive_node_h value = le32toh (vlist->offset[i]); value += 0x1000; if (!IS_VALID_BLOCK (h, value)) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_values: returning EFAULT because value is not a valid block (0x%zx)\n", + fprintf (stderr, "hivex_node_values: returning EFAULT" + " because value is not a valid block (0x%zx)\n", value); errno = EFAULT; goto error; @@ -1134,7 +1210,8 @@ hivex_value_key (hive_h *h, hive_value_h value) size_t seg_len = block_len (h, value, NULL); if (sizeof (struct ntreg_vk_record) + len - 1 > seg_len) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_value_key: returning EFAULT because key length is too long (%zu, %zu)\n", + fprintf (stderr, "hivex_value_key: returning EFAULT" + " because key length is too long (%zu, %zu)\n", len, seg_len); errno = EFAULT; return NULL; @@ -1207,7 +1284,8 @@ hivex_value_value (hive_h *h, hive_value_h value, /* Arbitrarily limit the length that we will read. */ if (len > HIVEX_MAX_VALUE_LEN) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_value_value: returning ERANGE because data length > HIVEX_MAX_VALUE_LEN (%zu > %d)\n", + fprintf (stderr, "hivex_value_value: returning ERANGE because data " + "length > HIVEX_MAX_VALUE_LEN (%zu > %d)\n", len, HIVEX_MAX_SUBKEYS); errno = ERANGE; return NULL; @@ -1226,7 +1304,8 @@ hivex_value_value (hive_h *h, hive_value_h value, data_offset += 0x1000; if (!IS_VALID_BLOCK (h, data_offset)) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_value_value: returning EFAULT because data offset is not a valid block (0x%zx)\n", + fprintf (stderr, "hivex_value_value: returning EFAULT because data " + "offset is not a valid block (0x%zx)\n", data_offset); errno = EFAULT; free (ret); @@ -1242,7 +1321,9 @@ hivex_value_value (hive_h *h, hive_value_h value, size_t blen = block_len (h, data_offset, NULL); if (len > blen - 4 /* subtract 4 for block header */) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_value_value: warning: declared data length is longer than the block it is in (data 0x%zx, data len %zu, block len %zu)\n", + fprintf (stderr, "hivex_value_value: warning: declared data length " + "is longer than the block it is in " + "(data 0x%zx, data len %zu, block len %zu)\n", data_offset, len, blen); len = blen - 4; @@ -1363,28 +1444,15 @@ free_strings (char **argv) } /* Get the length of a UTF-16 format string. Handle the string as - * pairs of bytes, looking for the first \0\0 pair. + * pairs of bytes, looking for the first \0\0 pair. Only read up to + * 'len' maximum bytes. */ static size_t -utf16_string_len_in_bytes (const char *str) -{ - size_t ret = 0; - - while (str[0] || str[1]) { - str += 2; - ret += 2; - } - - return ret; -} - -/* As for utf16_string_len_in_bytes but only read up to a maximum length. */ -static size_t utf16_string_len_in_bytes_max (const char *str, size_t len) { size_t ret = 0; - while (len > 0 && (str[0] || str[1])) { + while (len >= 2 && (str[0] || str[1])) { str += 2; ret += 2; len -= 2; @@ -1421,7 +1489,8 @@ hivex_value_multiple_strings (hive_h *h, hive_value_h value) char *p = data; size_t plen; - while (p < data + len && (plen = utf16_string_len_in_bytes (p)) > 0) { + while (p < data + len && + (plen = utf16_string_len_in_bytes_max (p, data + len - p)) > 0) { nr_strings++; char **ret2 = realloc (ret, (1 + nr_strings) * sizeof (char *)); if (ret2 == NULL) { @@ -1506,7 +1575,9 @@ hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len, return hivex_visit_node (h, hivex_root (h), visitor, len, opaque, flags); } -static int hivex__visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *vtor, char *unvisited, void *opaque, int flags); +static int hivex__visit_node (hive_h *h, hive_node_h node, + const struct hivex_visitor *vtor, + char *unvisited, void *opaque, int flags); int hivex_visit_node (hive_h *h, hive_node_h node, @@ -1554,7 +1625,8 @@ hivex__visit_node (hive_h *h, hive_node_h node, if (!BITMAP_TST (unvisited, node)) { if (h->msglvl >= 2) - fprintf (stderr, "hivex__visit_node: contains cycle: visited node 0x%zx already\n", + fprintf (stderr, "hivex__visit_node: contains cycle:" + " visited node 0x%zx already\n", node); errno = ELOOP; @@ -1627,14 +1699,16 @@ hivex__visit_node (hive_h *h, hive_node_h node, } if (vtor->value_string_invalid_utf16) { str = hivex_value_value (h, values[i], &t, &len); - if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], t, len, key, str) == -1) + if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], + t, len, key, str) == -1) goto error; free (str); str = NULL; } break; } if (vtor->value_string && - vtor->value_string (h, opaque, node, values[i], t, len, key, str) == -1) + vtor->value_string (h, opaque, node, values[i], + t, len, key, str) == -1) goto error; free (str); str = NULL; break; @@ -1643,7 +1717,8 @@ hivex__visit_node (hive_h *h, hive_node_h node, case hive_t_dword_be: { int32_t i32 = hivex_value_dword (h, values[i]); if (vtor->value_dword && - vtor->value_dword (h, opaque, node, values[i], t, len, key, i32) == -1) + vtor->value_dword (h, opaque, node, values[i], + t, len, key, i32) == -1) goto error; break; } @@ -1651,7 +1726,8 @@ hivex__visit_node (hive_h *h, hive_node_h node, case hive_t_qword: { int64_t i64 = hivex_value_qword (h, values[i]); if (vtor->value_qword && - vtor->value_qword (h, opaque, node, values[i], t, len, key, i64) == -1) + vtor->value_qword (h, opaque, node, values[i], + t, len, key, i64) == -1) goto error; break; } @@ -1667,7 +1743,8 @@ hivex__visit_node (hive_h *h, hive_node_h node, goto error; } if (vtor->value_binary && - vtor->value_binary (h, opaque, node, values[i], t, len, key, str) == -1) + vtor->value_binary (h, opaque, node, values[i], + t, len, key, str) == -1) goto error; free (str); str = NULL; break; @@ -1681,14 +1758,16 @@ hivex__visit_node (hive_h *h, hive_node_h node, } if (vtor->value_string_invalid_utf16) { str = hivex_value_value (h, values[i], &t, &len); - if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], t, len, key, str) == -1) + if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], + t, len, key, str) == -1) goto error; free (str); str = NULL; } break; } if (vtor->value_multiple_strings && - vtor->value_multiple_strings (h, opaque, node, values[i], t, len, key, strs) == -1) + vtor->value_multiple_strings (h, opaque, node, values[i], + t, len, key, strs) == -1) goto error; free_strings (strs); strs = NULL; break; @@ -1703,7 +1782,8 @@ hivex__visit_node (hive_h *h, hive_node_h node, goto error; } if (vtor->value_other && - vtor->value_other (h, opaque, node, values[i], t, len, key, str) == -1) + vtor->value_other (h, opaque, node, values[i], + t, len, key, str) == -1) goto error; free (str); str = NULL; break; @@ -1778,9 +1858,11 @@ allocate_page (hive_h *h, size_t allocation_hint) ssize_t extend = h->endpages + nr_4k_pages * 4096 - h->size; if (h->msglvl >= 2) { - fprintf (stderr, "allocate_page: current endpages = 0x%zx, current size = 0x%zx\n", + fprintf (stderr, "allocate_page: current endpages = 0x%zx," + " current size = 0x%zx\n", h->endpages, h->size); - fprintf (stderr, "allocate_page: extending file by %zd bytes (<= 0 if no extension)\n", + fprintf (stderr, "allocate_page: extending file by %zd bytes" + " (<= 0 if no extension)\n", extend); } @@ -1865,8 +1947,8 @@ allocate_block (hive_h *h, size_t seg_len, const char id[2]) * for them, albeit unusual. */ if (h->msglvl >= 2) - fprintf (stderr, "allocate_block: refusing too small allocation (%zu), returning ERANGE\n", - seg_len); + fprintf (stderr, "allocate_block: refusing too small allocation (%zu)," + " returning ERANGE\n", seg_len); errno = ERANGE; return 0; } @@ -1874,8 +1956,8 @@ allocate_block (hive_h *h, size_t seg_len, const char id[2]) /* Refuse really large allocations. */ if (seg_len > HIVEX_MAX_ALLOCATION) { if (h->msglvl >= 2) - fprintf (stderr, "allocate_block: refusing large allocation (%zu), returning ERANGE\n", - seg_len); + fprintf (stderr, "allocate_block: refusing large allocation (%zu)," + " returning ERANGE\n", seg_len); errno = ERANGE; return 0; } @@ -1921,8 +2003,8 @@ allocate_block (hive_h *h, size_t seg_len, const char id[2]) ssize_t rem = h->endpages - h->endblocks; if (rem > 0) { if (h->msglvl >= 2) - fprintf (stderr, "allocate_block: marking remainder of page free starting at 0x%zx, size %zd\n", - h->endblocks, rem); + fprintf (stderr, "allocate_block: marking remainder of page free" + " starting at 0x%zx, size %zd\n", h->endblocks, rem); assert (rem >= 4); @@ -2200,7 +2282,8 @@ hivex_node_add_child (hive_h *h, hive_node_h parent, const char *name) return 0; if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_add_child: allocated new nk-record for child at 0x%zx\n", node); + fprintf (stderr, "hivex_node_add_child: allocated new nk-record" + " for child at 0x%zx\n", node); struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node); nk->flags = htole16 (0x0020); /* key is ASCII. */ @@ -2220,7 +2303,8 @@ hivex_node_add_child (hive_h *h, hive_node_h parent, const char *name) if (!IS_VALID_BLOCK (h, parent_sk_offset) || !BLOCK_ID_EQ (h, parent_sk_offset, "sk")) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_add_child: returning EFAULT because parent sk is not a valid block (%zu)\n", + fprintf (stderr, "hivex_node_add_child: returning EFAULT" + " because parent sk is not a valid block (%zu)\n", parent_sk_offset); errno = EFAULT; return 0; @@ -2231,7 +2315,7 @@ hivex_node_add_child (hive_h *h, hive_node_h parent, const char *name) nk->sk = htole32 (parent_sk_offset - 0x1000); /* Inherit parent timestamp. */ - memcpy (nk->timestamp, parent_nk->timestamp, sizeof (parent_nk->timestamp)); + nk->timestamp = parent_nk->timestamp; /* What I found out the hard way (not documented anywhere): the * subkeys in lh-records must be kept sorted. If you just add a @@ -2274,7 +2358,8 @@ hivex_node_add_child (hive_h *h, hive_node_h parent, const char *name) parent_nk = (struct ntreg_nk_record *) (h->addr + parent); if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_add_child: no keys, allocated new lh-record at 0x%zx\n", lh_offs); + fprintf (stderr, "hivex_node_add_child: no keys, allocated new" + " lh-record at 0x%zx\n", lh_offs); parent_nk->subkey_lf = htole32 (lh_offs - 0x1000); } @@ -2306,7 +2391,8 @@ hivex_node_add_child (hive_h *h, hive_node_h parent, const char *name) /* Insert it. */ insert_it: if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_add_child: insert key in existing lh-record at 0x%zx, posn %zu\n", old_offs, j); + fprintf (stderr, "hivex_node_add_child: insert key in existing" + " lh-record at 0x%zx, posn %zu\n", old_offs, j); new_offs = insert_lf_record (h, old_offs, j, name, node); if (new_offs == 0) { @@ -2347,7 +2433,8 @@ hivex_node_add_child (hive_h *h, hive_node_h parent, const char *name) /* Not found .. This is an internal error. */ if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_add_child: returning ENOTSUP because could not find ri->lf link\n"); + fprintf (stderr, "hivex_node_add_child: returning ENOTSUP" + " because could not find ri->lf link\n"); errno = ENOTSUP; free (blocks); return 0; @@ -2540,7 +2627,8 @@ hivex_node_delete_child (hive_h *h, hive_node_h node) } } if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_delete_child: could not find parent to child link\n"); + fprintf (stderr, "hivex_node_delete_child: could not find parent" + " to child link\n"); errno = ENOTSUP; return -1; @@ -2550,8 +2638,8 @@ hivex_node_delete_child (hive_h *h, hive_node_h node) nk->nr_subkeys = htole32 (nr_subkeys_in_nk - 1); if (h->msglvl >= 2) - fprintf (stderr, "hivex_node_delete_child: updating nr_subkeys in parent 0x%zx to %zu\n", - parent, nr_subkeys_in_nk); + fprintf (stderr, "hivex_node_delete_child: updating nr_subkeys" + " in parent 0x%zx to %zu\n", parent, nr_subkeys_in_nk); return 0; } @@ -2651,7 +2739,7 @@ hivex_node_set_values (hive_h *h, hive_node_h node, int hivex_node_set_value (hive_h *h, hive_node_h node, - const hive_set_value *val, int flags) + const hive_set_value *val, int flags) { hive_value_h *prev_values = hivex_node_values (h, node); if (prev_values == NULL) @@ -2717,8 +2805,7 @@ hivex_node_set_value (hive_h *h, hive_node_h node, leave_partial: for (int i = 0; i < alloc_ct; i += 2) { - if (values[i / 2].value != NULL) - free (values[i / 2].value); + free (values[i / 2].value); if (i + 1 < alloc_ct && values[i / 2].key != NULL) free (values[i / 2].key); }