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