This function breaks the value name calculation out so the name does
not need to be fetched and immediately thrown away when one only needs
the name.
Signed-off-by: Alex Nelson <ajnelson(a)cs.ucsc.edu>
---
generator/generator.ml | 11 +++++++++++
lib/hivex.c | 37 ++++++++++++++++++++++++++-----------
2 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/generator/generator.ml b/generator/generator.ml
index 8bd944d..48b6e3a 100755
--- a/generator/generator.ml
+++ b/generator/generator.ml
@@ -229,6 +229,17 @@ string C<\"\"> here. The default key is often
written C<\"@\">, but
inside hives that has no meaning and won't give you the
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.
+
+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)\">.";
+
"value_key", (RString, [AHive; AValue "val"]),
"return the key of a (key, value) pair",
"\
diff --git a/lib/hivex.c b/lib/hivex.c
index 4b9fcf0..61177d3 100644
--- a/lib/hivex.c
+++ b/lib/hivex.c
@@ -1189,8 +1189,8 @@ hivex_node_get_value (hive_h *h, hive_node_h node, const char *key)
return ret;
}
-char *
-hivex_value_key (hive_h *h, hive_value_h value)
+size_t
+hivex_value_key_len (hive_h *h, hive_value_h value)
{
if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
errno = EINVAL;
@@ -1199,23 +1199,38 @@ hivex_value_key (hive_h *h, hive_value_h value)
struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
- /* AFAIK the key is always plain ASCII, so no conversion to UTF-8 is
- * necessary. However we do need to nul-terminate the string.
- */
-
/* 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 len = le16toh (vk->name_len);
+ size_t ret = le16toh (vk->name_len);
size_t seg_len = block_len (h, value, NULL);
- if (sizeof (struct ntreg_vk_record) + len - 1 > seg_len) {
+ if (sizeof (struct ntreg_vk_record) + ret - 1 > seg_len) {
if (h->msglvl >= 2)
- fprintf (stderr, "hivex_value_key: returning EFAULT"
+ fprintf (stderr, "hivex_value_key_len: returning EFAULT"
" because key length is too long (%zu, %zu)\n",
- len, seg_len);
+ ret, seg_len);
errno = EFAULT;
- return NULL;
+ return 0;
}
+ return ret;
+}
+
+char *
+hivex_value_key (hive_h *h, hive_value_h value)
+{
+ if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
+
+ /* AFAIK the key is always plain ASCII, so no conversion to UTF-8 is
+ * necessary. However we do need to nul-terminate the string.
+ */
+ size_t len = hivex_value_key_len (h, value);
+ if (errno != 0)
+ return NULL;
char *ret = malloc (len + 1);
if (ret == NULL)
--
1.7.6