hivex: Collect more statistics about registries.
[libguestfs.git] / hivex / hivex.c
1 /* hivex - Windows Registry "hive" extraction library.
2  * Copyright (C) 2009 Red Hat Inc.
3  * Derived from code by Petter Nordahl-Hagen under a compatible license:
4  *   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
5  * Derived from code by Markus Stephany under a compatible license:
6  *   Copyright (c) 2000-2004, Markus Stephany.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation;
11  * version 2.1 of the License.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * See file LICENSE for the full license.
19  */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include <stddef.h>
27 #include <inttypes.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <iconv.h>
33 #include <sys/mman.h>
34 #include <sys/stat.h>
35 #include <assert.h>
36 #ifdef HAVE_ENDIAN_H
37 #include <endian.h>
38 #endif
39 #ifdef HAVE_BYTESWAP_H
40 #include <byteswap.h>
41 #endif
42
43 #define STREQ(a,b) (strcmp((a),(b)) == 0)
44 #define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0)
45 //#define STRNEQ(a,b) (strcmp((a),(b)) != 0)
46 //#define STRCASENEQ(a,b) (strcasecmp((a),(b)) != 0)
47 #define STREQLEN(a,b,n) (strncmp((a),(b),(n)) == 0)
48 //#define STRCASEEQLEN(a,b,n) (strncasecmp((a),(b),(n)) == 0)
49 //#define STRNEQLEN(a,b,n) (strncmp((a),(b),(n)) != 0)
50 //#define STRCASENEQLEN(a,b,n) (strncasecmp((a),(b),(n)) != 0)
51 //#define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0)
52
53 #if __BYTE_ORDER == __LITTLE_ENDIAN
54 #ifndef be32toh
55 #define be32toh(x) __bswap_32 (x)
56 #endif
57 #ifndef be64toh
58 #define be64toh(x) __bswap_64 (x)
59 #endif
60 #ifndef le16toh
61 #define le16toh(x) (x)
62 #endif
63 #ifndef le32toh
64 #define le32toh(x) (x)
65 #endif
66 #ifndef le64toh
67 #define le64toh(x) (x)
68 #endif
69 #else
70 #ifndef be32toh
71 #define be32toh(x) (x)
72 #endif
73 #ifndef be64toh
74 #define be64toh(x) (x)
75 #endif
76 #ifndef le16toh
77 #define le16toh(x) __bswap_16 (x)
78 #endif
79 #ifndef le32toh
80 #define le32toh(x) __bswap_32 (x)
81 #endif
82 #ifndef le64toh
83 #define le64toh(x) __bswap_64 (x)
84 #endif
85 #endif
86
87 #include "hivex.h"
88
89 static char *windows_utf16_to_utf8 (/* const */ char *input, size_t len);
90
91 struct hive_h {
92   char *filename;
93   int fd;
94   size_t size;
95   int msglvl;
96
97   /* Memory-mapped (readonly) registry file. */
98   union {
99     char *addr;
100     struct ntreg_header *hdr;
101   };
102
103   /* Use a bitmap to store which file offsets are valid (point to a
104    * used block).  We only need to store 1 bit per 32 bits of the file
105    * (because blocks are 4-byte aligned).  We found that the average
106    * block size in a registry file is ~50 bytes.  So roughly 1 in 12
107    * bits in the bitmap will be set, making it likely a more efficient
108    * structure than a hash table.
109    */
110   char *bitmap;
111 #define BITMAP_SET(bitmap,off) (bitmap[(off)>>5] |= 1 << (((off)>>2)&7))
112 #define BITMAP_CLR(bitmap,off) (bitmap[(off)>>5] &= ~ (1 << (((off)>>2)&7)))
113 #define BITMAP_TST(bitmap,off) (bitmap[(off)>>5] & (1 << (((off)>>2)&7)))
114 #define IS_VALID_BLOCK(h,off)               \
115   (((off) & 3) == 0 &&                      \
116    (off) >= 0x1000 &&                       \
117    (off) < (h)->size &&                     \
118    BITMAP_TST((h)->bitmap,(off)))
119
120   /* Fields from the header, extracted from little-endianness hell. */
121   size_t rootoffs;              /* Root key offset (always an nk-block). */
122   size_t endpages;              /* Offset of end of pages. */
123 };
124
125 /* NB. All fields are little endian. */
126 struct ntreg_header {
127   char magic[4];                /* "regf" */
128   uint32_t sequence1;
129   uint32_t sequence2;
130   char last_modified[8];
131   uint32_t major_ver;           /* 1 */
132   uint32_t minor_ver;           /* 3 */
133   uint32_t unknown5;            /* 0 */
134   uint32_t unknown6;            /* 1 */
135   uint32_t offset;              /* offset of root key record - 4KB */
136   uint32_t blocks;              /* pointer AFTER last hbin in file - 4KB */
137   uint32_t unknown7;            /* 1 */
138   /* 0x30 */
139   char name[64];                /* original file name of hive */
140   char unknown_guid1[16];
141   char unknown_guid2[16];
142   /* 0x90 */
143   uint32_t unknown8;
144   char unknown_guid3[16];
145   uint32_t unknown9;
146   /* 0xa8 */
147   char unknown10[340];
148   /* 0x1fc */
149   uint32_t csum;                /* checksum: xor of dwords 0-0x1fb. */
150   /* 0x200 */
151   char unknown11[3528];
152   /* 0xfc8 */
153   char unknown_guid4[16];
154   char unknown_guid5[16];
155   char unknown_guid6[16];
156   uint32_t unknown12;
157   uint32_t unknown13;
158   /* 0x1000 */
159 } __attribute__((__packed__));
160
161 struct ntreg_hbin_page {
162   char magic[4];                /* "hbin" */
163   uint32_t offset_first;        /* offset from 1st block */
164   uint32_t offset_next;         /* offset of next (relative to this) */
165   char unknown[20];
166   /* Linked list of blocks follows here. */
167 } __attribute__((__packed__));
168
169 struct ntreg_hbin_block {
170   int32_t seg_len;              /* length of this block (-ve for used block) */
171   char id[2];                   /* the block type (eg. "nk" for nk record) */
172   /* Block data follows here. */
173 } __attribute__((__packed__));
174
175 #define BLOCK_ID_EQ(h,offs,eqid) \
176   (STREQLEN (((struct ntreg_hbin_block *)((h)->addr + (offs)))->id, (eqid), 2))
177
178 static size_t
179 block_len (hive_h *h, size_t blkoff, int *used)
180 {
181   struct ntreg_hbin_block *block;
182   block = (struct ntreg_hbin_block *) (h->addr + blkoff);
183
184   int32_t len = le32toh (block->seg_len);
185   if (len < 0) {
186     if (used) *used = 1;
187     len = -len;
188   } else {
189     if (used) *used = 0;
190   }
191
192   return (size_t) len;
193 }
194
195 struct ntreg_nk_record {
196   int32_t seg_len;              /* length (always -ve because used) */
197   char id[2];                   /* "nk" */
198   uint16_t flags;
199   char timestamp[12];
200   uint32_t parent;              /* offset of owner/parent */
201   uint32_t nr_subkeys;          /* number of subkeys */
202   uint32_t unknown1;
203   uint32_t subkey_lf;           /* lf record containing list of subkeys */
204   uint32_t unknown2;
205   uint32_t nr_values;           /* number of values */
206   uint32_t vallist;             /* value-list record */
207   uint32_t sk;                  /* offset of sk-record */
208   uint32_t classname;           /* offset of classname record */
209   char unknown3[16];
210   uint32_t unknown4;
211   uint16_t name_len;            /* length of name */
212   uint16_t classname_len;       /* length of classname */
213   char name[1];                 /* name follows here */
214 } __attribute__((__packed__));
215
216 struct ntreg_lf_record {
217   int32_t seg_len;
218   char id[2];                   /* "lf" */
219   uint16_t nr_keys;             /* number of keys in this record */
220   struct {
221     uint32_t offset;            /* offset of nk-record for this subkey */
222     char name[4];               /* first 4 characters of subkey name */
223   } keys[1];
224 } __attribute__((__packed__));
225
226 struct ntreg_ri_record {
227   int32_t seg_len;
228   char id[2];                   /* "ri" */
229   uint16_t nr_offsets;          /* number of pointers to lh records */
230   uint32_t offset[1];           /* list of pointers to lh records */
231 } __attribute__((__packed__));
232
233 /* This has no ID header. */
234 struct ntreg_value_list {
235   int32_t seg_len;
236   uint32_t offset[1];           /* list of pointers to vk records */
237 } __attribute__((__packed__));
238
239 struct ntreg_vk_record {
240   int32_t seg_len;              /* length (always -ve because used) */
241   char id[2];                   /* "vk" */
242   uint16_t name_len;            /* length of name */
243   /* length of the data:
244    * If data_len is <= 4, then it's stored inline.
245    * If data_len is 0x80000000, then it's an inline dword.
246    * Top bit may be set or not set at random.
247    */
248   uint32_t data_len;
249   uint32_t data_offset;         /* pointer to the data (or data if inline) */
250   hive_type data_type;          /* type of the data */
251   uint16_t flags;               /* bit 0 set => key name ASCII,
252                                    bit 0 clr => key name UTF-16.
253                                    Only seen ASCII here in the wild. */
254   uint16_t unknown2;
255   char name[1];                 /* key name follows here */
256 } __attribute__((__packed__));
257
258 hive_h *
259 hivex_open (const char *filename, int flags)
260 {
261   hive_h *h = NULL;
262
263   assert (sizeof (struct ntreg_header) == 0x1000);
264   assert (offsetof (struct ntreg_header, csum) == 0x1fc);
265
266   h = calloc (1, sizeof *h);
267   if (h == NULL)
268     goto error;
269
270   h->msglvl = flags & HIVEX_OPEN_MSGLVL_MASK;
271
272   const char *debug = getenv ("HIVEX_DEBUG");
273   if (debug && STREQ (debug, "1"))
274     h->msglvl = 2;
275
276   if (h->msglvl >= 2)
277     fprintf (stderr, "hivex_open: created handle %p\n", h);
278
279   h->filename = strdup (filename);
280   if (h->filename == NULL)
281     goto error;
282
283   h->fd = open (filename, O_RDONLY);
284   if (h->fd == -1)
285     goto error;
286
287   struct stat statbuf;
288   if (fstat (h->fd, &statbuf) == -1)
289     goto error;
290
291   h->size = statbuf.st_size;
292
293   h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
294   if (h->addr == MAP_FAILED)
295     goto error;
296
297   if (h->msglvl >= 2)
298     fprintf (stderr, "hivex_open: mapped file at %p\n", h->addr);
299
300   /* Check header. */
301   if (h->hdr->magic[0] != 'r' ||
302       h->hdr->magic[1] != 'e' ||
303       h->hdr->magic[2] != 'g' ||
304       h->hdr->magic[3] != 'f') {
305     fprintf (stderr, "hivex: %s: not a Windows NT Registry hive file\n",
306              filename);
307     errno = ENOTSUP;
308     goto error;
309   }
310
311   /* Check major version. */
312   uint32_t major_ver = le32toh (h->hdr->major_ver);
313   if (major_ver != 1) {
314     fprintf (stderr,
315              "hivex: %s: hive file major version %" PRIu32 " (expected 1)\n",
316              filename, major_ver);
317     errno = ENOTSUP;
318     goto error;
319   }
320
321   h->bitmap = calloc (1 + h->size / 32, 1);
322   if (h->bitmap == NULL)
323     goto error;
324
325   /* Header checksum. */
326   uint32_t *daddr = (uint32_t *) h->addr;
327   size_t i;
328   uint32_t sum = 0;
329   for (i = 0; i < 0x1fc / 4; ++i) {
330     sum ^= le32toh (*daddr);
331     daddr++;
332   }
333
334   if (sum != le32toh (h->hdr->csum)) {
335     fprintf (stderr, "hivex: %s: bad checksum in hive header\n", filename);
336     errno = EINVAL;
337     goto error;
338   }
339
340   if (h->msglvl >= 2) {
341     char *name = windows_utf16_to_utf8 (h->hdr->name, 64);
342
343     fprintf (stderr,
344              "hivex_open: header fields:\n"
345              "  file version             %" PRIu32 ".%" PRIu32 "\n"
346              "  sequence nos             %" PRIu32 " %" PRIu32 "\n"
347              "    (sequences nos should match if hive was synched at shutdown)\n"
348              "  original file name       %s\n"
349              "    (only 32 chars are stored, name is probably truncated)\n"
350              "  root offset              0x%x + 0x1000\n"
351              "  end of last page         0x%x + 0x1000 (total file size 0x%zx)\n"
352              "  checksum                 0x%x (calculated 0x%x)\n",
353              major_ver, le32toh (h->hdr->minor_ver),
354              le32toh (h->hdr->sequence1), le32toh (h->hdr->sequence2),
355              name ? name : "(conversion failed)",
356              le32toh (h->hdr->offset),
357              le32toh (h->hdr->blocks), h->size,
358              le32toh (h->hdr->csum), sum);
359     free (name);
360   }
361
362   h->rootoffs = le32toh (h->hdr->offset) + 0x1000;
363   h->endpages = le32toh (h->hdr->blocks) + 0x1000;
364
365   if (h->msglvl >= 2)
366     fprintf (stderr, "hivex_open: root offset = 0x%zx\n", h->rootoffs);
367
368   /* We'll set this flag when we see a block with the root offset (ie.
369    * the root block).
370    */
371   int seen_root_block = 0, bad_root_block = 0;
372
373   /* Collect some stats. */
374   size_t pages = 0;           /* Number of hbin pages read. */
375   size_t smallest_page = SIZE_MAX, largest_page = 0;
376   size_t blocks = 0;          /* Total number of blocks found. */
377   size_t smallest_block = SIZE_MAX, largest_block = 0, blocks_bytes = 0;
378   size_t used_blocks = 0;     /* Total number of used blocks found. */
379   size_t used_size = 0;       /* Total size (bytes) of used blocks. */
380
381   /* Read the pages and blocks.  The aim here is to be robust against
382    * corrupt or malicious registries.  So we make sure the loops
383    * always make forward progress.  We add the address of each block
384    * we read to a hash table so pointers will only reference the start
385    * of valid blocks.
386    */
387   size_t off;
388   struct ntreg_hbin_page *page;
389   for (off = 0x1000; off < h->size; off += le32toh (page->offset_next)) {
390     if (off >= h->endpages)
391       break;
392
393     page = (struct ntreg_hbin_page *) (h->addr + off);
394     if (page->magic[0] != 'h' ||
395         page->magic[1] != 'b' ||
396         page->magic[2] != 'i' ||
397         page->magic[3] != 'n') {
398       fprintf (stderr, "hivex: %s: trailing garbage at end of file (at 0x%zx, after %zu pages)\n",
399                filename, off, pages);
400       errno = ENOTSUP;
401       goto error;
402     }
403
404     size_t page_size = le32toh (page->offset_next);
405     if (h->msglvl >= 2)
406       fprintf (stderr, "hivex_open: page at 0x%zx, size %zu\n", off, page_size);
407     pages++;
408     if (page_size < smallest_page) smallest_page = page_size;
409     if (page_size > largest_page) largest_page = page_size;
410
411     if (le32toh (page->offset_next) <= sizeof (struct ntreg_hbin_page) ||
412         (le32toh (page->offset_next) & 3) != 0) {
413       fprintf (stderr, "hivex: %s: pagesize %d at %zu, bad registry\n",
414                filename, le32toh (page->offset_next), off);
415       errno = ENOTSUP;
416       goto error;
417     }
418
419     /* Read the blocks in this page. */
420     size_t blkoff;
421     struct ntreg_hbin_block *block;
422     size_t seg_len;
423     for (blkoff = off + 0x20;
424          blkoff < off + le32toh (page->offset_next);
425          blkoff += seg_len) {
426       blocks++;
427
428       int is_root = blkoff == h->rootoffs;
429       if (is_root)
430         seen_root_block = 1;
431
432       block = (struct ntreg_hbin_block *) (h->addr + blkoff);
433       int used;
434       seg_len = block_len (h, blkoff, &used);
435       if (seg_len <= 4 || (seg_len & 3) != 0) {
436         fprintf (stderr, "hivex: %s: block size %d at %zu, bad registry\n",
437                  filename, le32toh (block->seg_len), blkoff);
438         errno = ENOTSUP;
439         goto error;
440       }
441
442       if (h->msglvl >= 2)
443         fprintf (stderr, "hivex_open: %s block id %d,%d at 0x%zx size %zu%s\n",
444                  used ? "used" : "free", block->id[0], block->id[1], blkoff,
445                  seg_len, is_root ? " (root)" : "");
446
447       blocks_bytes += seg_len;
448       if (seg_len < smallest_block) smallest_block = seg_len;
449       if (seg_len > largest_block) largest_block = seg_len;
450
451       if (is_root && !used)
452         bad_root_block = 1;
453
454       if (used) {
455         used_blocks++;
456         used_size += seg_len;
457
458         /* Root block must be an nk-block. */
459         if (is_root && (block->id[0] != 'n' || block->id[1] != 'k'))
460           bad_root_block = 1;
461
462         /* Note this blkoff is a valid address. */
463         BITMAP_SET (h->bitmap, blkoff);
464       }
465     }
466   }
467
468   if (!seen_root_block) {
469     fprintf (stderr, "hivex: %s: no root block found\n", filename);
470     errno = ENOTSUP;
471     goto error;
472   }
473
474   if (bad_root_block) {
475     fprintf (stderr, "hivex: %s: bad root block (free or not nk)\n", filename);
476     errno = ENOTSUP;
477     goto error;
478   }
479
480   if (h->msglvl >= 1)
481     fprintf (stderr,
482              "hivex_open: successfully read Windows Registry hive file:\n"
483              "  pages:          %zu [sml: %zu, lge: %zu]\n"
484              "  blocks:         %zu [sml: %zu, avg: %zu, lge: %zu]\n"
485              "  blocks used:    %zu\n"
486              "  bytes used:     %zu\n",
487              pages, smallest_page, largest_page,
488              blocks, smallest_block, blocks_bytes / blocks, largest_block,
489              used_blocks, used_size);
490
491   return h;
492
493  error:;
494   int err = errno;
495   if (h) {
496     free (h->bitmap);
497     if (h->addr && h->size && h->addr != MAP_FAILED)
498       munmap (h->addr, h->size);
499     if (h->fd >= 0)
500       close (h->fd);
501     free (h->filename);
502     free (h);
503   }
504   errno = err;
505   return NULL;
506 }
507
508 int
509 hivex_close (hive_h *h)
510 {
511   int r;
512
513   free (h->bitmap);
514   munmap (h->addr, h->size);
515   r = close (h->fd);
516   free (h->filename);
517   free (h);
518
519   return r;
520 }
521
522 hive_node_h
523 hivex_root (hive_h *h)
524 {
525   hive_node_h ret = h->rootoffs;
526   if (!IS_VALID_BLOCK (h, ret)) {
527     errno = ENOKEY;
528     return 0;
529   }
530   return ret;
531 }
532
533 char *
534 hivex_node_name (hive_h *h, hive_node_h node)
535 {
536   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
537     errno = EINVAL;
538     return NULL;
539   }
540
541   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
542
543   /* AFAIK the node name is always plain ASCII, so no conversion
544    * to UTF-8 is necessary.  However we do need to nul-terminate
545    * the string.
546    */
547
548   /* nk->name_len is unsigned, 16 bit, so this is safe ...  However
549    * we have to make sure the length doesn't exceed the block length.
550    */
551   size_t len = le16toh (nk->name_len);
552   size_t seg_len = block_len (h, node, NULL);
553   if (sizeof (struct ntreg_nk_record) + len - 1 > seg_len) {
554     if (h->msglvl >= 2)
555       fprintf (stderr, "hivex_node_name: returning EFAULT because node name is too long (%zu, %zu)\n",
556               len, seg_len);
557     errno = EFAULT;
558     return NULL;
559   }
560
561   char *ret = malloc (len + 1);
562   if (ret == NULL)
563     return NULL;
564   memcpy (ret, nk->name, len);
565   ret[len] = '\0';
566   return ret;
567 }
568
569 #if 0
570 /* I think the documentation for the sk and classname fields in the nk
571  * record is wrong, or else the offset field is in the wrong place.
572  * Otherwise this makes no sense.  Disabled this for now -- it's not
573  * useful for reading the registry anyway.
574  */
575
576 hive_security_h
577 hivex_node_security (hive_h *h, hive_node_h node)
578 {
579   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
580     errno = EINVAL;
581     return 0;
582   }
583
584   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
585
586   hive_node_h ret = le32toh (nk->sk);
587   ret += 0x1000;
588   if (!IS_VALID_BLOCK (h, ret)) {
589     errno = EFAULT;
590     return 0;
591   }
592   return ret;
593 }
594
595 hive_classname_h
596 hivex_node_classname (hive_h *h, hive_node_h node)
597 {
598   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
599     errno = EINVAL;
600     return 0;
601   }
602
603   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
604
605   hive_node_h ret = le32toh (nk->classname);
606   ret += 0x1000;
607   if (!IS_VALID_BLOCK (h, ret)) {
608     errno = EFAULT;
609     return 0;
610   }
611   return ret;
612 }
613 #endif
614
615 hive_node_h *
616 hivex_node_children (hive_h *h, hive_node_h node)
617 {
618   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
619     errno = EINVAL;
620     return NULL;
621   }
622
623   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
624
625   size_t nr_subkeys_in_nk = le32toh (nk->nr_subkeys);
626
627   /* Deal with the common "no subkeys" case quickly. */
628   hive_node_h *ret;
629   if (nr_subkeys_in_nk == 0) {
630     ret = malloc (sizeof (hive_node_h));
631     if (ret == NULL)
632       return NULL;
633     ret[0] = 0;
634     return ret;
635   }
636
637   /* Arbitrarily limit the number of subkeys we will ever deal with. */
638   if (nr_subkeys_in_nk > 1000000) {
639     errno = ERANGE;
640     return NULL;
641   }
642
643   /* The subkey_lf field can point either to an lf-record, which is
644    * the common case, or if there are lots of subkeys, to an
645    * ri-record.
646    */
647   size_t subkey_lf = le32toh (nk->subkey_lf);
648   subkey_lf += 0x1000;
649   if (!IS_VALID_BLOCK (h, subkey_lf)) {
650     if (h->msglvl >= 2)
651       fprintf (stderr, "hivex_node_children: returning EFAULT because subkey_lf is not a valid block (%zu)\n",
652                subkey_lf);
653     errno = EFAULT;
654     return NULL;
655   }
656
657   struct ntreg_hbin_block *block =
658     (struct ntreg_hbin_block *) (h->addr + subkey_lf);
659
660   /* Points to lf-record?  (Note, also "lh" but that is basically the
661    * same as "lf" as far as we are concerned here).
662    */
663   if (block->id[0] == 'l' && (block->id[1] == 'f' || block->id[1] == 'h')) {
664     struct ntreg_lf_record *lf = (struct ntreg_lf_record *) block;
665
666     /* Check number of subkeys in the nk-record matches number of subkeys
667      * in the lf-record.
668      */
669     size_t nr_subkeys_in_lf = le16toh (lf->nr_keys);
670
671     if (h->msglvl >= 2)
672       fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu, nr_subkeys_in_lf = %zu\n",
673                nr_subkeys_in_nk, nr_subkeys_in_lf);
674
675     if (nr_subkeys_in_nk != nr_subkeys_in_lf) {
676       errno = ENOTSUP;
677       return NULL;
678     }
679
680     size_t len = block_len (h, subkey_lf, NULL);
681     if (8 + nr_subkeys_in_lf * 8 > len) {
682       if (h->msglvl >= 2)
683         fprintf (stderr, "hivex_node_children: returning EFAULT because too many subkeys (%zu, %zu)\n",
684                  nr_subkeys_in_lf, len);
685       errno = EFAULT;
686       return NULL;
687     }
688
689     /* Allocate space for the returned values.  Note that
690      * nr_subkeys_in_lf is limited to a 16 bit value.
691      */
692     ret = malloc ((1 + nr_subkeys_in_lf) * sizeof (hive_node_h));
693     if (ret == NULL)
694       return NULL;
695
696     size_t i;
697     for (i = 0; i < nr_subkeys_in_lf; ++i) {
698       hive_node_h subkey = lf->keys[i].offset;
699       subkey += 0x1000;
700       if (!IS_VALID_BLOCK (h, subkey)) {
701         if (h->msglvl >= 2)
702           fprintf (stderr, "hivex_node_children: returning EFAULT because subkey is not a valid block (0x%zx)\n",
703                    subkey);
704         errno = EFAULT;
705         free (ret);
706         return NULL;
707       }
708       ret[i] = subkey;
709     }
710     ret[i] = 0;
711     return ret;
712   }
713   /* Points to ri-record? */
714   else if (block->id[0] == 'r' && block->id[1] == 'i') {
715     struct ntreg_ri_record *ri = (struct ntreg_ri_record *) block;
716
717     size_t nr_offsets = le16toh (ri->nr_offsets);
718
719     /* Count total number of children. */
720     size_t i, count = 0;
721     for (i = 0; i < nr_offsets; ++i) {
722       hive_node_h offset = ri->offset[i];
723       offset += 0x1000;
724       if (!IS_VALID_BLOCK (h, offset)) {
725         if (h->msglvl >= 2)
726           fprintf (stderr, "hivex_node_children: returning EFAULT because ri-offset is not a valid block (0x%zx)\n",
727                    offset);
728         errno = EFAULT;
729         return NULL;
730       }
731       if (!BLOCK_ID_EQ (h, offset, "lf") && !BLOCK_ID_EQ (h, offset, "lh")) {
732         errno = ENOTSUP;
733         return NULL;
734       }
735
736       struct ntreg_lf_record *lf =
737         (struct ntreg_lf_record *) (h->addr + offset);
738
739       count += le16toh (lf->nr_keys);
740     }
741
742     if (h->msglvl >= 2)
743       fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu, counted = %zu\n",
744                nr_subkeys_in_nk, count);
745
746     if (nr_subkeys_in_nk != count) {
747       errno = ENOTSUP;
748       return NULL;
749     }
750
751     /* Copy list of children.  Note nr_subkeys_in_nk is limited to
752      * something reasonable above.
753      */
754     ret = malloc ((1 + nr_subkeys_in_nk) * sizeof (hive_node_h));
755     if (ret == NULL)
756       return NULL;
757
758     count = 0;
759     for (i = 0; i < nr_offsets; ++i) {
760       hive_node_h offset = ri->offset[i];
761       offset += 0x1000;
762       if (!IS_VALID_BLOCK (h, offset)) {
763         if (h->msglvl >= 2)
764           fprintf (stderr, "hivex_node_children: returning EFAULT because ri-offset is not a valid block (0x%zx)\n",
765                    offset);
766         errno = EFAULT;
767         return NULL;
768       }
769       if (!BLOCK_ID_EQ (h, offset, "lf") && !BLOCK_ID_EQ (h, offset, "lh")) {
770         errno = ENOTSUP;
771         return NULL;
772       }
773
774       struct ntreg_lf_record *lf =
775         (struct ntreg_lf_record *) (h->addr + offset);
776
777       size_t j;
778       for (j = 0; j < le16toh (lf->nr_keys); ++j) {
779         hive_node_h subkey = lf->keys[j].offset;
780         subkey += 0x1000;
781         if (!IS_VALID_BLOCK (h, subkey)) {
782           if (h->msglvl >= 2)
783             fprintf (stderr, "hivex_node_children: returning EFAULT because indirect subkey is not a valid block (0x%zx)\n",
784                      subkey);
785           errno = EFAULT;
786           free (ret);
787           return NULL;
788         }
789         ret[count++] = subkey;
790       }
791     }
792     ret[count] = 0;
793
794     return ret;
795   }
796   else {
797     errno = ENOTSUP;
798     return NULL;
799   }
800 }
801
802 /* Very inefficient, but at least having a separate API call
803  * allows us to make it more efficient in future.
804  */
805 hive_node_h
806 hivex_node_get_child (hive_h *h, hive_node_h node, const char *nname)
807 {
808   hive_node_h *children = NULL;
809   char *name = NULL;
810   hive_node_h ret = 0;
811
812   children = hivex_node_children (h, node);
813   if (!children) goto error;
814
815   size_t i;
816   for (i = 0; children[i] != 0; ++i) {
817     name = hivex_node_name (h, children[i]);
818     if (!name) goto error;
819     if (STRCASEEQ (name, nname)) {
820       ret = children[i];
821       break;
822     }
823     free (name); name = NULL;
824   }
825
826  error:
827   free (children);
828   free (name);
829   return ret;
830 }
831
832 hive_node_h
833 hivex_node_parent (hive_h *h, hive_node_h node)
834 {
835   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
836     errno = EINVAL;
837     return 0;
838   }
839
840   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
841
842   hive_node_h ret = le32toh (nk->parent);
843   ret += 0x1000;
844   if (!IS_VALID_BLOCK (h, ret)) {
845     if (h->msglvl >= 2)
846       fprintf (stderr, "hivex_node_parent: returning EFAULT because parent is not a valid block (0x%zx)\n",
847               ret);
848     errno = EFAULT;
849     return 0;
850   }
851   return ret;
852 }
853
854 hive_value_h *
855 hivex_node_values (hive_h *h, hive_node_h node)
856 {
857   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
858     errno = EINVAL;
859     return 0;
860   }
861
862   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
863
864   size_t nr_values = le32toh (nk->nr_values);
865
866   if (h->msglvl >= 2)
867     fprintf (stderr, "hivex_node_values: nr_values = %zu\n", nr_values);
868
869   /* Deal with the common "no values" case quickly. */
870   hive_node_h *ret;
871   if (nr_values == 0) {
872     ret = malloc (sizeof (hive_node_h));
873     if (ret == NULL)
874       return NULL;
875     ret[0] = 0;
876     return ret;
877   }
878
879   /* Arbitrarily limit the number of values we will ever deal with. */
880   if (nr_values > 100000) {
881     errno = ERANGE;
882     return NULL;
883   }
884
885   /* Get the value list and check it looks reasonable. */
886   size_t vlist_offset = le32toh (nk->vallist);
887   vlist_offset += 0x1000;
888   if (!IS_VALID_BLOCK (h, vlist_offset)) {
889     if (h->msglvl >= 2)
890       fprintf (stderr, "hivex_node_values: returning EFAULT because value list is not a valid block (0x%zx)\n",
891                vlist_offset);
892     errno = EFAULT;
893     return NULL;
894   }
895
896   struct ntreg_value_list *vlist =
897     (struct ntreg_value_list *) (h->addr + vlist_offset);
898
899   size_t len = block_len (h, vlist_offset, NULL);
900   if (4 + nr_values * 4 > len) {
901     if (h->msglvl >= 2)
902       fprintf (stderr, "hivex_node_values: returning EFAULT because value list is too long (%zu, %zu)\n",
903                nr_values, len);
904     errno = EFAULT;
905     return NULL;
906   }
907
908   /* Allocate return array and copy values in. */
909   ret = malloc ((1 + nr_values) * sizeof (hive_node_h));
910   if (ret == NULL)
911     return NULL;
912
913   size_t i;
914   for (i = 0; i < nr_values; ++i) {
915     hive_node_h value = vlist->offset[i];
916     value += 0x1000;
917     if (!IS_VALID_BLOCK (h, value)) {
918       if (h->msglvl >= 2)
919         fprintf (stderr, "hivex_node_values: returning EFAULT because value is not a valid block (0x%zx)\n",
920                  value);
921       errno = EFAULT;
922       free (ret);
923       return NULL;
924     }
925     ret[i] = value;
926   }
927
928   ret[i] = 0;
929   return ret;
930 }
931
932 /* Very inefficient, but at least having a separate API call
933  * allows us to make it more efficient in future.
934  */
935 hive_value_h
936 hivex_node_get_value (hive_h *h, hive_node_h node, const char *key)
937 {
938   hive_value_h *values = NULL;
939   char *name = NULL;
940   hive_value_h ret = 0;
941
942   values = hivex_node_values (h, node);
943   if (!values) goto error;
944
945   size_t i;
946   for (i = 0; values[i] != 0; ++i) {
947     name = hivex_value_key (h, values[i]);
948     if (!name) goto error;
949     if (STRCASEEQ (name, key)) {
950       ret = values[i];
951       break;
952     }
953     free (name); name = NULL;
954   }
955
956  error:
957   free (values);
958   free (name);
959   return ret;
960 }
961
962 char *
963 hivex_value_key (hive_h *h, hive_value_h value)
964 {
965   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
966     errno = EINVAL;
967     return 0;
968   }
969
970   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
971
972   /* AFAIK the key is always plain ASCII, so no conversion to UTF-8 is
973    * necessary.  However we do need to nul-terminate the string.
974    */
975
976   /* vk->name_len is unsigned, 16 bit, so this is safe ...  However
977    * we have to make sure the length doesn't exceed the block length.
978    */
979   size_t len = le16toh (vk->name_len);
980   size_t seg_len = block_len (h, value, NULL);
981   if (sizeof (struct ntreg_vk_record) + len - 1 > seg_len) {
982     if (h->msglvl >= 2)
983       fprintf (stderr, "hivex_value_key: returning EFAULT because key length is too long (%zu, %zu)\n",
984                len, seg_len);
985     errno = EFAULT;
986     return NULL;
987   }
988
989   char *ret = malloc (len + 1);
990   if (ret == NULL)
991     return NULL;
992   memcpy (ret, vk->name, len);
993   ret[len] = '\0';
994   return ret;
995 }
996
997 int
998 hivex_value_type (hive_h *h, hive_value_h value, hive_type *t, size_t *len)
999 {
1000   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
1001     errno = EINVAL;
1002     return -1;
1003   }
1004
1005   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
1006
1007   if (t)
1008     *t = le32toh (vk->data_type);
1009
1010   if (len) {
1011     *len = le32toh (vk->data_len);
1012     if (*len == 0x80000000) {   /* special case */
1013       *len = 4;
1014       if (t) *t = hive_t_dword;
1015     }
1016     *len &= 0x7fffffff;
1017   }
1018
1019   return 0;
1020 }
1021
1022 char *
1023 hivex_value_value (hive_h *h, hive_value_h value,
1024                    hive_type *t_rtn, size_t *len_rtn)
1025 {
1026   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
1027     errno = EINVAL;
1028     return NULL;
1029   }
1030
1031   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
1032
1033   hive_type t;
1034   size_t len;
1035
1036   t = le32toh (vk->data_type);
1037
1038   len = le32toh (vk->data_len);
1039   if (len == 0x80000000) {      /* special case */
1040     len = 4;
1041     t = hive_t_dword;
1042   }
1043   len &= 0x7fffffff;
1044
1045   if (h->msglvl >= 2)
1046     fprintf (stderr, "hivex_value_value: value=0x%zx, t=%d, len=%zu\n",
1047              value, t, len);
1048
1049   if (t_rtn)
1050     *t_rtn = t;
1051   if (len_rtn)
1052     *len_rtn = len;
1053
1054   /* Arbitrarily limit the length that we will read. */
1055   if (len > 1000000) {
1056     errno = ERANGE;
1057     return NULL;
1058   }
1059
1060   char *ret = malloc (len);
1061   if (ret == NULL)
1062     return NULL;
1063
1064   /* If length is <= 4 it's always stored inline. */
1065   if (len <= 4) {
1066     memcpy (ret, (char *) &vk->data_offset, len);
1067     return ret;
1068   }
1069
1070   size_t data_offset = vk->data_offset;
1071   data_offset += 0x1000;
1072   if (!IS_VALID_BLOCK (h, data_offset)) {
1073     if (h->msglvl >= 2)
1074       fprintf (stderr, "hivex_value_value: returning EFAULT because data offset is not a valid block (0x%zx)\n",
1075                data_offset);
1076     errno = EFAULT;
1077     free (ret);
1078     return NULL;
1079   }
1080
1081   /* Check that the declared size isn't larger than the block its in. */
1082   size_t blen = block_len (h, data_offset, NULL);
1083   if (len > blen) {
1084     if (h->msglvl >= 2)
1085       fprintf (stderr, "hivex_value_value: returning EFAULT because data is longer than its block (data 0x%zx, data len %zu, block len %zu)\n",
1086                data_offset, len, blen);
1087     errno = EFAULT;
1088     free (ret);
1089     return NULL;
1090   }
1091
1092   char *data = h->addr + data_offset + 4;
1093   memcpy (ret, data, len);
1094   return ret;
1095 }
1096
1097 static char *
1098 windows_utf16_to_utf8 (/* const */ char *input, size_t len)
1099 {
1100   iconv_t ic = iconv_open ("UTF-8", "UTF-16");
1101   if (ic == (iconv_t) -1)
1102     return NULL;
1103
1104   /* iconv(3) has an insane interface ... */
1105
1106   /* Mostly UTF-8 will be smaller, so this is a good initial guess. */
1107   size_t outalloc = len;
1108
1109  again:;
1110   size_t inlen = len;
1111   size_t outlen = outalloc;
1112   char *out = malloc (outlen + 1);
1113   if (out == NULL) {
1114     int err = errno;
1115     iconv_close (ic);
1116     errno = err;
1117     return NULL;
1118   }
1119   char *inp = input;
1120   char *outp = out;
1121
1122   size_t r = iconv (ic, &inp, &inlen, &outp, &outlen);
1123   if (r == (size_t) -1) {
1124     if (errno == E2BIG) {
1125       size_t prev = outalloc;
1126       /* Try again with a larger output buffer. */
1127       free (out);
1128       outalloc *= 2;
1129       if (outalloc < prev)
1130         return NULL;
1131       goto again;
1132     }
1133     else {
1134       /* Else some conversion failure, eg. EILSEQ, EINVAL. */
1135       int err = errno;
1136       iconv_close (ic);
1137       free (out);
1138       errno = err;
1139       return NULL;
1140     }
1141   }
1142
1143   *outp = '\0';
1144   iconv_close (ic);
1145
1146   return out;
1147 }
1148
1149 char *
1150 hivex_value_string (hive_h *h, hive_value_h value)
1151 {
1152   hive_type t;
1153   size_t len;
1154   char *data = hivex_value_value (h, value, &t, &len);
1155
1156   if (data == NULL)
1157     return NULL;
1158
1159   if (t != hive_t_string && t != hive_t_expand_string && t != hive_t_link) {
1160     free (data);
1161     errno = EINVAL;
1162     return NULL;
1163   }
1164
1165   char *ret = windows_utf16_to_utf8 (data, len);
1166   free (data);
1167   if (ret == NULL)
1168     return NULL;
1169
1170   return ret;
1171 }
1172
1173 static void
1174 free_strings (char **argv)
1175 {
1176   if (argv) {
1177     size_t i;
1178
1179     for (i = 0; argv[i] != NULL; ++i)
1180       free (argv[i]);
1181     free (argv);
1182   }
1183 }
1184
1185 /* Get the length of a UTF-16 format string.  Handle the string as
1186  * pairs of bytes, looking for the first \0\0 pair.
1187  */
1188 static size_t
1189 utf16_string_len_in_bytes (const char *str)
1190 {
1191   size_t ret = 0;
1192
1193   while (str[0] || str[1]) {
1194     str += 2;
1195     ret += 2;
1196   }
1197
1198   return ret;
1199 }
1200
1201 /* http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx */
1202 char **
1203 hivex_value_multiple_strings (hive_h *h, hive_value_h value)
1204 {
1205   hive_type t;
1206   size_t len;
1207   char *data = hivex_value_value (h, value, &t, &len);
1208
1209   if (data == NULL)
1210     return NULL;
1211
1212   if (t != hive_t_multiple_strings) {
1213     free (data);
1214     errno = EINVAL;
1215     return NULL;
1216   }
1217
1218   size_t nr_strings = 0;
1219   char **ret = malloc ((1 + nr_strings) * sizeof (char *));
1220   if (ret == NULL) {
1221     free (data);
1222     return NULL;
1223   }
1224   ret[0] = NULL;
1225
1226   char *p = data;
1227   size_t plen;
1228
1229   while (p < data + len && (plen = utf16_string_len_in_bytes (p)) > 0) {
1230     nr_strings++;
1231     char **ret2 = realloc (ret, (1 + nr_strings) * sizeof (char *));
1232     if (ret2 == NULL) {
1233       free_strings (ret);
1234       free (data);
1235       return NULL;
1236     }
1237     ret = ret2;
1238
1239     ret[nr_strings-1] = windows_utf16_to_utf8 (p, plen);
1240     ret[nr_strings] = NULL;
1241     if (ret[nr_strings-1] == NULL) {
1242       free_strings (ret);
1243       free (data);
1244       return NULL;
1245     }
1246
1247     p += plen + 2 /* skip over UTF-16 \0\0 at the end of this string */;
1248   }
1249
1250   free (data);
1251   return ret;
1252 }
1253
1254 int32_t
1255 hivex_value_dword (hive_h *h, hive_value_h value)
1256 {
1257   hive_type t;
1258   size_t len;
1259   char *data = hivex_value_value (h, value, &t, &len);
1260
1261   if (data == NULL)
1262     return -1;
1263
1264   if ((t != hive_t_dword && t != hive_t_dword_be) || len != 4) {
1265     free (data);
1266     errno = EINVAL;
1267     return -1;
1268   }
1269
1270   int32_t ret = *(int32_t*)data;
1271   free (data);
1272   if (t == hive_t_dword)        /* little endian */
1273     ret = le32toh (ret);
1274   else
1275     ret = be32toh (ret);
1276
1277   return ret;
1278 }
1279
1280 int64_t
1281 hivex_value_qword (hive_h *h, hive_value_h value)
1282 {
1283   hive_type t;
1284   size_t len;
1285   char *data = hivex_value_value (h, value, &t, &len);
1286
1287   if (data == NULL)
1288     return -1;
1289
1290   if (t != hive_t_qword || len != 8) {
1291     free (data);
1292     errno = EINVAL;
1293     return -1;
1294   }
1295
1296   int64_t ret = *(int64_t*)data;
1297   free (data);
1298   ret = le64toh (ret);          /* always little endian */
1299
1300   return ret;
1301 }
1302
1303 int
1304 hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len,
1305              void *opaque, int flags)
1306 {
1307   return hivex_visit_node (h, hivex_root (h), visitor, len, opaque, flags);
1308 }
1309
1310 static int hivex__visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *vtor, char *unvisited, void *opaque, int flags);
1311
1312 int
1313 hivex_visit_node (hive_h *h, hive_node_h node,
1314                   const struct hivex_visitor *visitor, size_t len, void *opaque,
1315                   int flags)
1316 {
1317   struct hivex_visitor vtor;
1318   memset (&vtor, 0, sizeof vtor);
1319
1320   /* Note that len might be larger *or smaller* than the expected size. */
1321   size_t copysize = len <= sizeof vtor ? len : sizeof vtor;
1322   memcpy (&vtor, visitor, copysize);
1323
1324   /* This bitmap records unvisited nodes, so we don't loop if the
1325    * registry contains cycles.
1326    */
1327   char *unvisited = malloc (1 + h->size / 32);
1328   if (unvisited == NULL)
1329     return -1;
1330   memcpy (unvisited, h->bitmap, 1 + h->size / 32);
1331
1332   int r = hivex__visit_node (h, node, &vtor, unvisited, opaque, flags);
1333   free (unvisited);
1334   return r;
1335 }
1336
1337 static int
1338 hivex__visit_node (hive_h *h, hive_node_h node,
1339                    const struct hivex_visitor *vtor, char *unvisited,
1340                    void *opaque, int flags)
1341 {
1342   int skip_bad = flags & HIVEX_VISIT_SKIP_BAD;
1343   char *name = NULL;
1344   hive_value_h *values = NULL;
1345   hive_node_h *children = NULL;
1346   char *key = NULL;
1347   char *str = NULL;
1348   char **strs = NULL;
1349   int i;
1350
1351   /* Return -1 on all callback errors.  However on internal errors,
1352    * check if skip_bad is set and suppress those errors if so.
1353    */
1354   int ret = -1;
1355
1356   if (!BITMAP_TST (unvisited, node)) {
1357     if (h->msglvl >= 2)
1358       fprintf (stderr, "hivex__visit_node: contains cycle: visited node 0x%zx already\n",
1359                node);
1360
1361     errno = ELOOP;
1362     return skip_bad ? 0 : -1;
1363   }
1364   BITMAP_CLR (unvisited, node);
1365
1366   name = hivex_node_name (h, node);
1367   if (!name) return skip_bad ? 0 : -1;
1368   if (vtor->node_start && vtor->node_start (h, opaque, node, name) == -1)
1369     goto error;
1370
1371   values = hivex_node_values (h, node);
1372   if (!values) {
1373     ret = skip_bad ? 0 : -1;
1374     goto error;
1375   }
1376
1377   for (i = 0; values[i] != 0; ++i) {
1378     hive_type t;
1379     size_t len;
1380
1381     if (hivex_value_type (h, values[i], &t, &len) == -1) {
1382       ret = skip_bad ? 0 : -1;
1383       goto error;
1384     }
1385
1386     key = hivex_value_key (h, values[i]);
1387     if (key == NULL) {
1388       ret = skip_bad ? 0 : -1;
1389       goto error;
1390     }
1391
1392     switch (t) {
1393     case hive_t_none:
1394       str = hivex_value_value (h, values[i], &t, &len);
1395       if (str == NULL) {
1396         ret = skip_bad ? 0 : -1;
1397         goto error;
1398       }
1399       if (t != hive_t_none) {
1400         ret = skip_bad ? 0 : -1;
1401         goto error;
1402       }
1403       if (vtor->value_none &&
1404           vtor->value_none (h, opaque, node, values[i], t, len, key, str) == -1)
1405         goto error;
1406       free (str); str = NULL;
1407       break;
1408
1409     case hive_t_string:
1410     case hive_t_expand_string:
1411     case hive_t_link:
1412       str = hivex_value_string (h, values[i]);
1413       if (str == NULL) {
1414         if (errno != EILSEQ && errno != EINVAL) {
1415           ret = skip_bad ? 0 : -1;
1416           goto error;
1417         }
1418         if (vtor->value_string_invalid_utf16) {
1419           str = hivex_value_value (h, values[i], &t, &len);
1420           if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], t, len, key, str) == -1)
1421             goto error;
1422           free (str); str = NULL;
1423         }
1424         break;
1425       }
1426       if (vtor->value_string &&
1427           vtor->value_string (h, opaque, node, values[i], t, len, key, str) == -1)
1428         goto error;
1429       free (str); str = NULL;
1430       break;
1431
1432     case hive_t_dword:
1433     case hive_t_dword_be: {
1434       int32_t i32 = hivex_value_dword (h, values[i]);
1435       if (vtor->value_dword &&
1436           vtor->value_dword (h, opaque, node, values[i], t, len, key, i32) == -1)
1437         goto error;
1438       break;
1439     }
1440
1441     case hive_t_qword: {
1442       int64_t i64 = hivex_value_qword (h, values[i]);
1443       if (vtor->value_qword &&
1444           vtor->value_qword (h, opaque, node, values[i], t, len, key, i64) == -1)
1445         goto error;
1446       break;
1447     }
1448
1449     case hive_t_binary:
1450       str = hivex_value_value (h, values[i], &t, &len);
1451       if (str == NULL) {
1452         ret = skip_bad ? 0 : -1;
1453         goto error;
1454       }
1455       if (t != hive_t_binary) {
1456         ret = skip_bad ? 0 : -1;
1457         goto error;
1458       }
1459       if (vtor->value_binary &&
1460           vtor->value_binary (h, opaque, node, values[i], t, len, key, str) == -1)
1461         goto error;
1462       free (str); str = NULL;
1463       break;
1464
1465     case hive_t_multiple_strings:
1466       strs = hivex_value_multiple_strings (h, values[i]);
1467       if (strs == NULL) {
1468         if (errno != EILSEQ && errno != EINVAL) {
1469           ret = skip_bad ? 0 : -1;
1470           goto error;
1471         }
1472         if (vtor->value_string_invalid_utf16) {
1473           str = hivex_value_value (h, values[i], &t, &len);
1474           if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], t, len, key, str) == -1)
1475             goto error;
1476           free (str); str = NULL;
1477         }
1478         break;
1479       }
1480       if (vtor->value_multiple_strings &&
1481           vtor->value_multiple_strings (h, opaque, node, values[i], t, len, key, strs) == -1)
1482         goto error;
1483       free_strings (strs); strs = NULL;
1484       break;
1485
1486     case hive_t_resource_list:
1487     case hive_t_full_resource_description:
1488     case hive_t_resource_requirements_list:
1489     default:
1490       str = hivex_value_value (h, values[i], &t, &len);
1491       if (str == NULL) {
1492         ret = skip_bad ? 0 : -1;
1493         goto error;
1494       }
1495       if (vtor->value_other &&
1496           vtor->value_other (h, opaque, node, values[i], t, len, key, str) == -1)
1497         goto error;
1498       free (str); str = NULL;
1499       break;
1500     }
1501
1502     free (key); key = NULL;
1503   }
1504
1505   children = hivex_node_children (h, node);
1506   if (children == NULL) {
1507     ret = skip_bad ? 0 : -1;
1508     goto error;
1509   }
1510
1511   for (i = 0; children[i] != 0; ++i) {
1512     if (h->msglvl >= 2)
1513       fprintf (stderr, "hivex__visit_node: %s: visiting subkey %d (0x%zx)\n",
1514                name, i, children[i]);
1515
1516     if (hivex__visit_node (h, children[i], vtor, unvisited, opaque, flags) == -1)
1517       goto error;
1518   }
1519
1520   if (vtor->node_end && vtor->node_end (h, opaque, node, name) == -1)
1521     goto error;
1522
1523   ret = 0;
1524
1525  error:
1526   free (name);
1527   free (values);
1528   free (children);
1529   free (key);
1530   free (str);
1531   free_strings (strs);
1532   return ret;
1533 }