Since iconv() does not treat null characters as special, this makes it
possible to read node names and value keys with embedded null
characters. which are not displayed at all by Windows Regedit.
---
generator/generator.ml | 19 ++++++++++++++-----
lib/node.c | 24 ++++++++++++++++++++++++
lib/value.c | 9 +++++----
3 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/generator/generator.ml b/generator/generator.ml
index 54e5f0f..1c62129 100755
--- a/generator/generator.ml
+++ b/generator/generator.ml
@@ -179,7 +179,14 @@ C<$$$PROTO.HIV> (other names are possible: it seems to depend
on the
tool or program that created the hive in the first place). You can
only know the \"real\" name of the root node by knowing which registry
file this hive originally comes from, which is knowledge that is
-outside the scope of this library.";
+outside the scope of this library.
+
+The name is recoded to UTF-8 and may contain embedded NUL characters.";
+
+ "node_name_len", (RSize, [AHive; ANode "node"]),
+ "return the length of a node's name",
+ "\
+Return the length of the node name as produced by C<hivex_node_name>.";
"node_timestamp", (RInt64, [AHive; ANode "node"]),
"return the modification time of the node",
@@ -233,13 +240,15 @@ default key.";
"value_key_len", (RSize, [AHive; AValue "val"]),
"return the length of a value's key",
"\
-Return the length of the key (name) of a (key, value) pair. The
-length can legitimately be 0, so errno is the necesary mechanism
-to check for errors.
+Return the length of the key (name) of a (key, value) pair as produced
+by C<hivex_value_key>. The length can legitimately be 0, so errno is
+the necesary mechanism to check for errors.
In the context of Windows Registries, a zero-length name means
that this value is the default key for this node in the tree.
-This is usually written as C<\"(a)\">.";
+This is usually written as C<\"@\">.
+
+The key is recoded to UTF-8 and may contain embedded NUL characters.";
"value_key", (RString, [AHive; AValue "val"]),
"return the key of a (key, value) pair",
diff --git a/lib/node.c b/lib/node.c
index fcd7442..22d1861 100644
--- a/lib/node.c
+++ b/lib/node.c
@@ -96,6 +96,30 @@ hivex_node_name (hive_h *h, hive_node_h node)
}
}
+size_t
+hivex_node_name_len (hive_h *h, hive_node_h node)
+{
+ if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
+ SET_ERRNO (EINVAL, "invalid block or not an 'nk' block");
+ return 0;
+ }
+ struct ntreg_nk_record *nk =
+ (struct ntreg_nk_record *) ((char *) h->addr + node);
+
+ /* nk->name_len is unsigned, 16 bit, so this is safe ... However
+ * we have to make sure the length doesn't exceed the block length.
+ */
+ size_t len = le16toh (nk->name_len);
+ size_t seg_len = block_len (h, node, NULL);
+ if (sizeof (struct ntreg_nk_record) + len - 1 > seg_len) {
+ SET_ERRNO (EFAULT, "node name is too long (%zu, %zu)", len, seg_len);
+ return 0;
+ }
+
+ return _hivex_utf8_strlen (nk->name, len, ! (le16toh (nk->flags) & 0x20));
+}
+
+
static int64_t
timestamp_check (hive_h *h, hive_node_h node, int64_t timestamp)
{
diff --git a/lib/value.c b/lib/value.c
index 3460a8c..65404d7 100644
--- a/lib/value.c
+++ b/lib/value.c
@@ -186,13 +186,14 @@ hivex_value_key_len (hive_h *h, hive_value_h value)
/* vk->name_len is unsigned, 16 bit, so this is safe ... However
* we have to make sure the length doesn't exceed the block length.
*/
- size_t ret = le16toh (vk->name_len);
+ size_t len = le16toh (vk->name_len);
+
size_t seg_len = block_len (h, value, NULL);
- if (sizeof (struct ntreg_vk_record) + ret - 1 > seg_len) {
- SET_ERRNO (EFAULT, "key length is too long (%zu, %zu)", ret, seg_len);
+ if (sizeof (struct ntreg_vk_record) + len - 1 > seg_len) {
+ SET_ERRNO (EFAULT, "key length is too long (%zu, %zu)", len, seg_len);
return 0;
}
- return ret;
+ return _hivex_utf8_strlen (vk->name, len, ! (le16toh (vk->flags) & 0x01));
}
char *
--
1.8.5.2