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