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