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