Prevent warning about unused variable in test.
[hivex.git] / lib / hivex.c
1 /* hivex - Windows Registry "hive" extraction library.
2  * Copyright (C) 2009-2011 Red Hat Inc.
3  * Derived from code by Petter Nordahl-Hagen under a compatible license:
4  *   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
5  * Derived from code by Markus Stephany under a compatible license:
6  *   Copyright (c) 2000-2004, Markus Stephany.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation;
11  * version 2.1 of the License.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * See file LICENSE for the full license.
19  */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include <stddef.h>
27 #include <inttypes.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <iconv.h>
33 #include <sys/mman.h>
34 #include <sys/stat.h>
35 #include <assert.h>
36
37 #include "c-ctype.h"
38 #include "full-read.h"
39 #include "full-write.h"
40
41 #define STREQ(a,b) (strcmp((a),(b)) == 0)
42 #define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0)
43 //#define STRNEQ(a,b) (strcmp((a),(b)) != 0)
44 //#define STRCASENEQ(a,b) (strcasecmp((a),(b)) != 0)
45 #define STREQLEN(a,b,n) (strncmp((a),(b),(n)) == 0)
46 //#define STRCASEEQLEN(a,b,n) (strncasecmp((a),(b),(n)) == 0)
47 //#define STRNEQLEN(a,b,n) (strncmp((a),(b),(n)) != 0)
48 //#define STRCASENEQLEN(a,b,n) (strncasecmp((a),(b),(n)) != 0)
49 #define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0)
50
51 #include "hivex.h"
52 #include "byte_conversions.h"
53
54 /* These limits are in place to stop really stupid stuff and/or exploits. */
55 #define HIVEX_MAX_SUBKEYS       15000
56 #define HIVEX_MAX_VALUES        10000
57 #define HIVEX_MAX_VALUE_LEN   1000000
58 #define HIVEX_MAX_ALLOCATION  1000000
59
60 static char *windows_utf16_to_utf8 (/* const */ char *input, size_t len);
61 static size_t utf16_string_len_in_bytes_max (const char *str, size_t len);
62
63 struct hive_h {
64   char *filename;
65   int fd;
66   size_t size;
67   int msglvl;
68   int writable;
69
70   /* Registry file, memory mapped if read-only, or malloc'd if writing. */
71   union {
72     char *addr;
73     struct ntreg_header *hdr;
74   };
75
76   /* Use a bitmap to store which file offsets are valid (point to a
77    * used block).  We only need to store 1 bit per 32 bits of the file
78    * (because blocks are 4-byte aligned).  We found that the average
79    * block size in a registry file is ~50 bytes.  So roughly 1 in 12
80    * bits in the bitmap will be set, making it likely a more efficient
81    * structure than a hash table.
82    */
83   char *bitmap;
84 #define BITMAP_SET(bitmap,off) (bitmap[(off)>>5] |= 1 << (((off)>>2)&7))
85 #define BITMAP_CLR(bitmap,off) (bitmap[(off)>>5] &= ~ (1 << (((off)>>2)&7)))
86 #define BITMAP_TST(bitmap,off) (bitmap[(off)>>5] & (1 << (((off)>>2)&7)))
87 #define IS_VALID_BLOCK(h,off)               \
88   (((off) & 3) == 0 &&                      \
89    (off) >= 0x1000 &&                       \
90    (off) < (h)->size &&                     \
91    BITMAP_TST((h)->bitmap,(off)))
92
93   /* Fields from the header, extracted from little-endianness hell. */
94   size_t rootoffs;              /* Root key offset (always an nk-block). */
95   size_t endpages;              /* Offset of end of pages. */
96   int64_t last_modified;        /* mtime of base block. */
97
98   /* For writing. */
99   size_t endblocks;             /* Offset to next block allocation (0
100                                    if not allocated anything yet). */
101 };
102
103 /* NB. All fields are little endian. */
104 struct ntreg_header {
105   char magic[4];                /* "regf" */
106   uint32_t sequence1;
107   uint32_t sequence2;
108   int64_t last_modified;
109   uint32_t major_ver;           /* 1 */
110   uint32_t minor_ver;           /* 3 */
111   uint32_t unknown5;            /* 0 */
112   uint32_t unknown6;            /* 1 */
113   uint32_t offset;              /* offset of root key record - 4KB */
114   uint32_t blocks;              /* pointer AFTER last hbin in file - 4KB */
115   uint32_t unknown7;            /* 1 */
116   /* 0x30 */
117   char name[64];                /* original file name of hive */
118   char unknown_guid1[16];
119   char unknown_guid2[16];
120   /* 0x90 */
121   uint32_t unknown8;
122   char unknown_guid3[16];
123   uint32_t unknown9;
124   /* 0xa8 */
125   char unknown10[340];
126   /* 0x1fc */
127   uint32_t csum;                /* checksum: xor of dwords 0-0x1fb. */
128   /* 0x200 */
129   char unknown11[3528];
130   /* 0xfc8 */
131   char unknown_guid4[16];
132   char unknown_guid5[16];
133   char unknown_guid6[16];
134   uint32_t unknown12;
135   uint32_t unknown13;
136   /* 0x1000 */
137 } __attribute__((__packed__));
138
139 struct ntreg_hbin_page {
140   char magic[4];                /* "hbin" */
141   uint32_t offset_first;        /* offset from 1st block */
142   uint32_t page_size;           /* size of this page (multiple of 4KB) */
143   char unknown[20];
144   /* Linked list of blocks follows here. */
145 } __attribute__((__packed__));
146
147 struct ntreg_hbin_block {
148   int32_t seg_len;              /* length of this block (-ve for used block) */
149   char id[2];                   /* the block type (eg. "nk" for nk record) */
150   /* Block data follows here. */
151 } __attribute__((__packed__));
152
153 #define BLOCK_ID_EQ(h,offs,eqid) \
154   (STREQLEN (((struct ntreg_hbin_block *)((h)->addr + (offs)))->id, (eqid), 2))
155
156 static size_t
157 block_len (hive_h *h, size_t blkoff, int *used)
158 {
159   struct ntreg_hbin_block *block;
160   block = (struct ntreg_hbin_block *) (h->addr + blkoff);
161
162   int32_t len = le32toh (block->seg_len);
163   if (len < 0) {
164     if (used) *used = 1;
165     len = -len;
166   } else {
167     if (used) *used = 0;
168   }
169
170   return (size_t) len;
171 }
172
173 struct ntreg_nk_record {
174   int32_t seg_len;              /* length (always -ve because used) */
175   char id[2];                   /* "nk" */
176   uint16_t flags;
177   int64_t timestamp;
178   uint32_t unknown1;
179   uint32_t parent;              /* offset of owner/parent */
180   uint32_t nr_subkeys;          /* number of subkeys */
181   uint32_t nr_subkeys_volatile;
182   uint32_t subkey_lf;           /* lf record containing list of subkeys */
183   uint32_t subkey_lf_volatile;
184   uint32_t nr_values;           /* number of values */
185   uint32_t vallist;             /* value-list record */
186   uint32_t sk;                  /* offset of sk-record */
187   uint32_t classname;           /* offset of classname record */
188   uint16_t max_subkey_name_len; /* maximum length of a subkey name in bytes
189                                    if the subkey was reencoded as UTF-16LE */
190   uint16_t unknown2;
191   uint32_t unknown3;
192   uint32_t max_vk_name_len;     /* maximum length of any vk name in bytes
193                                    if the name was reencoded as UTF-16LE */
194   uint32_t max_vk_data_len;     /* maximum length of any vk data in bytes */
195   uint32_t unknown6;
196   uint16_t name_len;            /* length of name */
197   uint16_t classname_len;       /* length of classname */
198   char name[1];                 /* name follows here */
199 } __attribute__((__packed__));
200
201 struct ntreg_lf_record {
202   int32_t seg_len;
203   char id[2];                   /* "lf"|"lh" */
204   uint16_t nr_keys;             /* number of keys in this record */
205   struct {
206     uint32_t offset;            /* offset of nk-record for this subkey */
207     char hash[4];               /* hash of subkey name */
208   } keys[1];
209 } __attribute__((__packed__));
210
211 struct ntreg_ri_record {
212   int32_t seg_len;
213   char id[2];                   /* "ri" */
214   uint16_t nr_offsets;          /* number of pointers to lh records */
215   uint32_t offset[1];           /* list of pointers to lh records */
216 } __attribute__((__packed__));
217
218 /* This has no ID header. */
219 struct ntreg_value_list {
220   int32_t seg_len;
221   uint32_t offset[1];           /* list of pointers to vk records */
222 } __attribute__((__packed__));
223
224 struct ntreg_vk_record {
225   int32_t seg_len;              /* length (always -ve because used) */
226   char id[2];                   /* "vk" */
227   uint16_t name_len;            /* length of name */
228   /* length of the data:
229    * If data_len is <= 4, then it's stored inline.
230    * Top bit is set to indicate inline.
231    */
232   uint32_t data_len;
233   uint32_t data_offset;         /* pointer to the data (or data if inline) */
234   uint32_t data_type;           /* type of the data */
235   uint16_t flags;               /* bit 0 set => key name ASCII,
236                                    bit 0 clr => key name UTF-16.
237                                    Only seen ASCII here in the wild.
238                                    NB: this is CLEAR for default key. */
239   uint16_t unknown2;
240   char name[1];                 /* key name follows here */
241 } __attribute__((__packed__));
242
243 struct ntreg_sk_record {
244   int32_t seg_len;              /* length (always -ve because used) */
245   char id[2];                   /* "sk" */
246   uint16_t unknown1;
247   uint32_t sk_next;             /* linked into a circular list */
248   uint32_t sk_prev;
249   uint32_t refcount;            /* reference count */
250   uint32_t sec_len;             /* length of security info */
251   char sec_desc[1];             /* security info follows */
252 } __attribute__((__packed__));
253
254 static uint32_t
255 header_checksum (const hive_h *h)
256 {
257   uint32_t *daddr = (uint32_t *) h->addr;
258   size_t i;
259   uint32_t sum = 0;
260
261   for (i = 0; i < 0x1fc / 4; ++i) {
262     sum ^= le32toh (*daddr);
263     daddr++;
264   }
265
266   return sum;
267 }
268
269 #define HIVEX_OPEN_MSGLVL_MASK (HIVEX_OPEN_VERBOSE|HIVEX_OPEN_DEBUG)
270
271 hive_h *
272 hivex_open (const char *filename, int flags)
273 {
274   hive_h *h = NULL;
275
276   assert (sizeof (struct ntreg_header) == 0x1000);
277   assert (offsetof (struct ntreg_header, csum) == 0x1fc);
278
279   h = calloc (1, sizeof *h);
280   if (h == NULL)
281     goto error;
282
283   h->msglvl = flags & HIVEX_OPEN_MSGLVL_MASK;
284
285   const char *debug = getenv ("HIVEX_DEBUG");
286   if (debug && STREQ (debug, "1"))
287     h->msglvl = 2;
288
289   if (h->msglvl >= 2)
290     fprintf (stderr, "hivex_open: created handle %p\n", h);
291
292   h->writable = !!(flags & HIVEX_OPEN_WRITE);
293   h->filename = strdup (filename);
294   if (h->filename == NULL)
295     goto error;
296
297   h->fd = open (filename, O_RDONLY | O_CLOEXEC);
298   if (h->fd == -1)
299     goto error;
300
301   struct stat statbuf;
302   if (fstat (h->fd, &statbuf) == -1)
303     goto error;
304
305   h->size = statbuf.st_size;
306
307   if (!h->writable) {
308     h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
309     if (h->addr == MAP_FAILED)
310       goto error;
311
312     if (h->msglvl >= 2)
313       fprintf (stderr, "hivex_open: mapped file at %p\n", h->addr);
314   } else {
315     h->addr = malloc (h->size);
316     if (h->addr == NULL)
317       goto error;
318
319     if (full_read (h->fd, h->addr, h->size) < h->size)
320       goto error;
321
322     /* We don't need the file descriptor along this path, since we
323      * have read all the data.
324      */
325     if (close (h->fd) == -1)
326       goto error;
327     h->fd = -1;
328   }
329
330   /* Check header. */
331   if (h->hdr->magic[0] != 'r' ||
332       h->hdr->magic[1] != 'e' ||
333       h->hdr->magic[2] != 'g' ||
334       h->hdr->magic[3] != 'f') {
335     fprintf (stderr, "hivex: %s: not a Windows NT Registry hive file\n",
336              filename);
337     errno = ENOTSUP;
338     goto error;
339   }
340
341   /* Check major version. */
342   uint32_t major_ver = le32toh (h->hdr->major_ver);
343   if (major_ver != 1) {
344     fprintf (stderr,
345              "hivex: %s: hive file major version %" PRIu32 " (expected 1)\n",
346              filename, major_ver);
347     errno = ENOTSUP;
348     goto error;
349   }
350
351   h->bitmap = calloc (1 + h->size / 32, 1);
352   if (h->bitmap == NULL)
353     goto error;
354
355   /* Header checksum. */
356   uint32_t sum = header_checksum (h);
357   if (sum != le32toh (h->hdr->csum)) {
358     fprintf (stderr, "hivex: %s: bad checksum in hive header\n", filename);
359     errno = EINVAL;
360     goto error;
361   }
362
363   /* Last modified time. */
364   h->last_modified = le64toh ((int64_t) h->hdr->last_modified);
365
366   if (h->msglvl >= 2) {
367     char *name = windows_utf16_to_utf8 (h->hdr->name, 64);
368
369     fprintf (stderr,
370              "hivex_open: header fields:\n"
371              "  file version             %" PRIu32 ".%" PRIu32 "\n"
372              "  sequence nos             %" PRIu32 " %" PRIu32 "\n"
373              "    (sequences nos should match if hive was synched at shutdown)\n"
374              "  last modified            %" PRIu64 "\n"
375              "    (Windows filetime, x 100 ns since 1601-01-01)\n"
376              "  original file name       %s\n"
377              "    (only 32 chars are stored, name is probably truncated)\n"
378              "  root offset              0x%x + 0x1000\n"
379              "  end of last page         0x%x + 0x1000 (total file size 0x%zx)\n"
380              "  checksum                 0x%x (calculated 0x%x)\n",
381              major_ver, le32toh (h->hdr->minor_ver),
382              le32toh (h->hdr->sequence1), le32toh (h->hdr->sequence2),
383              h->last_modified,
384              name ? name : "(conversion failed)",
385              le32toh (h->hdr->offset),
386              le32toh (h->hdr->blocks), h->size,
387              le32toh (h->hdr->csum), sum);
388     free (name);
389   }
390
391   h->rootoffs = le32toh (h->hdr->offset) + 0x1000;
392   h->endpages = le32toh (h->hdr->blocks) + 0x1000;
393
394   if (h->msglvl >= 2)
395     fprintf (stderr, "hivex_open: root offset = 0x%zx\n", h->rootoffs);
396
397   /* We'll set this flag when we see a block with the root offset (ie.
398    * the root block).
399    */
400   int seen_root_block = 0, bad_root_block = 0;
401
402   /* Collect some stats. */
403   size_t pages = 0;           /* Number of hbin pages read. */
404   size_t smallest_page = SIZE_MAX, largest_page = 0;
405   size_t blocks = 0;          /* Total number of blocks found. */
406   size_t smallest_block = SIZE_MAX, largest_block = 0, blocks_bytes = 0;
407   size_t used_blocks = 0;     /* Total number of used blocks found. */
408   size_t used_size = 0;       /* Total size (bytes) of used blocks. */
409
410   /* Read the pages and blocks.  The aim here is to be robust against
411    * corrupt or malicious registries.  So we make sure the loops
412    * always make forward progress.  We add the address of each block
413    * we read to a hash table so pointers will only reference the start
414    * of valid blocks.
415    */
416   size_t off;
417   struct ntreg_hbin_page *page;
418   for (off = 0x1000; off < h->size; off += le32toh (page->page_size)) {
419     if (off >= h->endpages)
420       break;
421
422     page = (struct ntreg_hbin_page *) (h->addr + off);
423     if (page->magic[0] != 'h' ||
424         page->magic[1] != 'b' ||
425         page->magic[2] != 'i' ||
426         page->magic[3] != 'n') {
427       fprintf (stderr, "hivex: %s: trailing garbage at end of file "
428                "(at 0x%zx, after %zu pages)\n",
429                filename, off, pages);
430       errno = ENOTSUP;
431       goto error;
432     }
433
434     size_t page_size = le32toh (page->page_size);
435     if (h->msglvl >= 2)
436       fprintf (stderr, "hivex_open: page at 0x%zx, size %zu\n", off, page_size);
437     pages++;
438     if (page_size < smallest_page) smallest_page = page_size;
439     if (page_size > largest_page) largest_page = page_size;
440
441     if (page_size <= sizeof (struct ntreg_hbin_page) ||
442         (page_size & 0x0fff) != 0) {
443       fprintf (stderr, "hivex: %s: page size %zu at 0x%zx, bad registry\n",
444                filename, page_size, off);
445       errno = ENOTSUP;
446       goto error;
447     }
448
449     /* Read the blocks in this page. */
450     size_t blkoff;
451     struct ntreg_hbin_block *block;
452     size_t seg_len;
453     for (blkoff = off + 0x20;
454          blkoff < off + page_size;
455          blkoff += seg_len) {
456       blocks++;
457
458       int is_root = blkoff == h->rootoffs;
459       if (is_root)
460         seen_root_block = 1;
461
462       block = (struct ntreg_hbin_block *) (h->addr + blkoff);
463       int used;
464       seg_len = block_len (h, blkoff, &used);
465       if (seg_len <= 4 || (seg_len & 3) != 0) {
466         fprintf (stderr, "hivex: %s: block size %" PRIu32 " at 0x%zx,"
467                  " bad registry\n",
468                  filename, le32toh (block->seg_len), blkoff);
469         errno = ENOTSUP;
470         goto error;
471       }
472
473       if (h->msglvl >= 2)
474         fprintf (stderr, "hivex_open: %s block id %d,%d at 0x%zx size %zu%s\n",
475                  used ? "used" : "free", block->id[0], block->id[1], blkoff,
476                  seg_len, is_root ? " (root)" : "");
477
478       blocks_bytes += seg_len;
479       if (seg_len < smallest_block) smallest_block = seg_len;
480       if (seg_len > largest_block) largest_block = seg_len;
481
482       if (is_root && !used)
483         bad_root_block = 1;
484
485       if (used) {
486         used_blocks++;
487         used_size += seg_len;
488
489         /* Root block must be an nk-block. */
490         if (is_root && (block->id[0] != 'n' || block->id[1] != 'k'))
491           bad_root_block = 1;
492
493         /* Note this blkoff is a valid address. */
494         BITMAP_SET (h->bitmap, blkoff);
495       }
496     }
497   }
498
499   if (!seen_root_block) {
500     fprintf (stderr, "hivex: %s: no root block found\n", filename);
501     errno = ENOTSUP;
502     goto error;
503   }
504
505   if (bad_root_block) {
506     fprintf (stderr, "hivex: %s: bad root block (free or not nk)\n", filename);
507     errno = ENOTSUP;
508     goto error;
509   }
510
511   if (h->msglvl >= 1)
512     fprintf (stderr,
513              "hivex_open: successfully read Windows Registry hive file:\n"
514              "  pages:          %zu [sml: %zu, lge: %zu]\n"
515              "  blocks:         %zu [sml: %zu, avg: %zu, lge: %zu]\n"
516              "  blocks used:    %zu\n"
517              "  bytes used:     %zu\n",
518              pages, smallest_page, largest_page,
519              blocks, smallest_block, blocks_bytes / blocks, largest_block,
520              used_blocks, used_size);
521
522   return h;
523
524  error:;
525   int err = errno;
526   if (h) {
527     free (h->bitmap);
528     if (h->addr && h->size && h->addr != MAP_FAILED) {
529       if (!h->writable)
530         munmap (h->addr, h->size);
531       else
532         free (h->addr);
533     }
534     if (h->fd >= 0)
535       close (h->fd);
536     free (h->filename);
537     free (h);
538   }
539   errno = err;
540   return NULL;
541 }
542
543 int
544 hivex_close (hive_h *h)
545 {
546   int r;
547
548   if (h->msglvl >= 1)
549     fprintf (stderr, "hivex_close\n");
550
551   free (h->bitmap);
552   if (!h->writable)
553     munmap (h->addr, h->size);
554   else
555     free (h->addr);
556   if (h->fd >= 0)
557     r = close (h->fd);
558   else
559     r = 0;
560   free (h->filename);
561   free (h);
562
563   return r;
564 }
565
566 /*----------------------------------------------------------------------
567  * Reading.
568  */
569
570 hive_node_h
571 hivex_root (hive_h *h)
572 {
573   hive_node_h ret = h->rootoffs;
574   if (!IS_VALID_BLOCK (h, ret)) {
575     errno = HIVEX_NO_KEY;
576     return 0;
577   }
578   return ret;
579 }
580
581 char *
582 hivex_node_name (hive_h *h, hive_node_h node)
583 {
584   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
585     errno = EINVAL;
586     return NULL;
587   }
588
589   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
590
591   /* AFAIK the node name is always plain ASCII, so no conversion
592    * to UTF-8 is necessary.  However we do need to nul-terminate
593    * the string.
594    */
595
596   /* nk->name_len is unsigned, 16 bit, so this is safe ...  However
597    * we have to make sure the length doesn't exceed the block length.
598    */
599   size_t len = le16toh (nk->name_len);
600   size_t seg_len = block_len (h, node, NULL);
601   if (sizeof (struct ntreg_nk_record) + len - 1 > seg_len) {
602     if (h->msglvl >= 2)
603       fprintf (stderr, "hivex_node_name: returning EFAULT because node name"
604                " is too long (%zu, %zu)\n",
605               len, seg_len);
606     errno = EFAULT;
607     return NULL;
608   }
609
610   char *ret = malloc (len + 1);
611   if (ret == NULL)
612     return NULL;
613   memcpy (ret, nk->name, len);
614   ret[len] = '\0';
615   return ret;
616 }
617
618 static int64_t
619 timestamp_check (hive_h *h, hive_node_h node, int64_t timestamp)
620 {
621   if (timestamp < 0) {
622     if (h->msglvl >= 2)
623       fprintf (stderr, "hivex: timestamp_check: "
624                "negative time reported at %zu: %" PRIi64 "\n",
625                node, timestamp);
626     errno = EINVAL;
627     return -1;
628   }
629
630   return timestamp;
631 }
632
633 int64_t
634 hivex_last_modified (hive_h *h)
635 {
636   return timestamp_check (h, 0, h->last_modified);
637 }
638
639 int64_t
640 hivex_node_timestamp (hive_h *h, hive_node_h node)
641 {
642   int64_t ret;
643
644   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
645     errno = EINVAL;
646     return -1;
647   }
648
649   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
650
651   ret = le64toh (nk->timestamp);
652   return timestamp_check (h, node, ret);
653 }
654
655 #if 0
656 /* I think the documentation for the sk and classname fields in the nk
657  * record is wrong, or else the offset field is in the wrong place.
658  * Otherwise this makes no sense.  Disabled this for now -- it's not
659  * useful for reading the registry anyway.
660  */
661
662 hive_security_h
663 hivex_node_security (hive_h *h, hive_node_h node)
664 {
665   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
666     errno = EINVAL;
667     return 0;
668   }
669
670   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
671
672   hive_node_h ret = le32toh (nk->sk);
673   ret += 0x1000;
674   if (!IS_VALID_BLOCK (h, ret)) {
675     errno = EFAULT;
676     return 0;
677   }
678   return ret;
679 }
680
681 hive_classname_h
682 hivex_node_classname (hive_h *h, hive_node_h node)
683 {
684   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
685     errno = EINVAL;
686     return 0;
687   }
688
689   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
690
691   hive_node_h ret = le32toh (nk->classname);
692   ret += 0x1000;
693   if (!IS_VALID_BLOCK (h, ret)) {
694     errno = EFAULT;
695     return 0;
696   }
697   return ret;
698 }
699 #endif
700
701 /* Structure for returning 0-terminated lists of offsets (nodes,
702  * values, etc).
703  */
704 struct offset_list {
705   size_t *offsets;
706   size_t len;
707   size_t alloc;
708 };
709
710 static void
711 init_offset_list (struct offset_list *list)
712 {
713   list->len = 0;
714   list->alloc = 0;
715   list->offsets = NULL;
716 }
717
718 #define INIT_OFFSET_LIST(name) \
719   struct offset_list name; \
720   init_offset_list (&name)
721
722 /* Preallocates the offset_list, but doesn't make the contents longer. */
723 static int
724 grow_offset_list (struct offset_list *list, size_t alloc)
725 {
726   assert (alloc >= list->len);
727   size_t *p = realloc (list->offsets, alloc * sizeof (size_t));
728   if (p == NULL)
729     return -1;
730   list->offsets = p;
731   list->alloc = alloc;
732   return 0;
733 }
734
735 static int
736 add_to_offset_list (struct offset_list *list, size_t offset)
737 {
738   if (list->len >= list->alloc) {
739     if (grow_offset_list (list, list->alloc ? list->alloc * 2 : 4) == -1)
740       return -1;
741   }
742   list->offsets[list->len] = offset;
743   list->len++;
744   return 0;
745 }
746
747 static void
748 free_offset_list (struct offset_list *list)
749 {
750   free (list->offsets);
751 }
752
753 static size_t *
754 return_offset_list (struct offset_list *list)
755 {
756   if (add_to_offset_list (list, 0) == -1)
757     return NULL;
758   return list->offsets;         /* caller frees */
759 }
760
761 /* Iterate over children, returning child nodes and intermediate blocks. */
762 #define GET_CHILDREN_NO_CHECK_NK 1
763
764 static int
765 get_children (hive_h *h, hive_node_h node,
766               hive_node_h **children_ret, size_t **blocks_ret,
767               int flags)
768 {
769   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
770     errno = EINVAL;
771     return -1;
772   }
773
774   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
775
776   size_t nr_subkeys_in_nk = le32toh (nk->nr_subkeys);
777
778   INIT_OFFSET_LIST (children);
779   INIT_OFFSET_LIST (blocks);
780
781   /* Deal with the common "no subkeys" case quickly. */
782   if (nr_subkeys_in_nk == 0)
783     goto ok;
784
785   /* Arbitrarily limit the number of subkeys we will ever deal with. */
786   if (nr_subkeys_in_nk > HIVEX_MAX_SUBKEYS) {
787     if (h->msglvl >= 2)
788       fprintf (stderr, "hivex: get_children: returning ERANGE because "
789                "nr_subkeys_in_nk > HIVEX_MAX_SUBKEYS (%zu > %d)\n",
790                nr_subkeys_in_nk, HIVEX_MAX_SUBKEYS);
791     errno = ERANGE;
792     goto error;
793   }
794
795   /* Preallocate space for the children. */
796   if (grow_offset_list (&children, nr_subkeys_in_nk) == -1)
797     goto error;
798
799   /* The subkey_lf field can point either to an lf-record, which is
800    * the common case, or if there are lots of subkeys, to an
801    * ri-record.
802    */
803   size_t subkey_lf = le32toh (nk->subkey_lf);
804   subkey_lf += 0x1000;
805   if (!IS_VALID_BLOCK (h, subkey_lf)) {
806     if (h->msglvl >= 2)
807       fprintf (stderr, "hivex_node_children: returning EFAULT"
808                " because subkey_lf is not a valid block (0x%zx)\n",
809                subkey_lf);
810     errno = EFAULT;
811     goto error;
812   }
813
814   if (add_to_offset_list (&blocks, subkey_lf) == -1)
815     goto error;
816
817   struct ntreg_hbin_block *block =
818     (struct ntreg_hbin_block *) (h->addr + subkey_lf);
819
820   /* Points to lf-record?  (Note, also "lh" but that is basically the
821    * same as "lf" as far as we are concerned here).
822    */
823   if (block->id[0] == 'l' && (block->id[1] == 'f' || block->id[1] == 'h')) {
824     struct ntreg_lf_record *lf = (struct ntreg_lf_record *) block;
825
826     /* Check number of subkeys in the nk-record matches number of subkeys
827      * in the lf-record.
828      */
829     size_t nr_subkeys_in_lf = le16toh (lf->nr_keys);
830
831     if (h->msglvl >= 2)
832       fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu,"
833                " nr_subkeys_in_lf = %zu\n",
834                nr_subkeys_in_nk, nr_subkeys_in_lf);
835
836     if (nr_subkeys_in_nk != nr_subkeys_in_lf) {
837       errno = ENOTSUP;
838       goto error;
839     }
840
841     size_t len = block_len (h, subkey_lf, NULL);
842     if (8 + nr_subkeys_in_lf * 8 > len) {
843       if (h->msglvl >= 2)
844         fprintf (stderr, "hivex_node_children: returning EFAULT"
845                  " because too many subkeys (%zu, %zu)\n",
846                  nr_subkeys_in_lf, len);
847       errno = EFAULT;
848       goto error;
849     }
850
851     size_t i;
852     for (i = 0; i < nr_subkeys_in_lf; ++i) {
853       hive_node_h subkey = le32toh (lf->keys[i].offset);
854       subkey += 0x1000;
855       if (!(flags & GET_CHILDREN_NO_CHECK_NK)) {
856         if (!IS_VALID_BLOCK (h, subkey)) {
857           if (h->msglvl >= 2)
858             fprintf (stderr, "hivex_node_children: returning EFAULT"
859                      " because subkey is not a valid block (0x%zx)\n",
860                      subkey);
861           errno = EFAULT;
862           goto error;
863         }
864       }
865       if (add_to_offset_list (&children, subkey) == -1)
866         goto error;
867     }
868     goto ok;
869   }
870   /* Points to ri-record? */
871   else if (block->id[0] == 'r' && block->id[1] == 'i') {
872     struct ntreg_ri_record *ri = (struct ntreg_ri_record *) block;
873
874     size_t nr_offsets = le16toh (ri->nr_offsets);
875
876     /* Count total number of children. */
877     size_t i, count = 0;
878     for (i = 0; i < nr_offsets; ++i) {
879       hive_node_h offset = le32toh (ri->offset[i]);
880       offset += 0x1000;
881       if (!IS_VALID_BLOCK (h, offset)) {
882         if (h->msglvl >= 2)
883           fprintf (stderr, "hivex_node_children: returning EFAULT"
884                    " because ri-offset is not a valid block (0x%zx)\n",
885                    offset);
886         errno = EFAULT;
887         goto error;
888       }
889       if (!BLOCK_ID_EQ (h, offset, "lf") && !BLOCK_ID_EQ (h, offset, "lh")) {
890         if (h->msglvl >= 2)
891           fprintf (stderr, "get_children: returning ENOTSUP"
892                    " because ri-record offset does not point to lf/lh (0x%zx)\n",
893                    offset);
894         errno = ENOTSUP;
895         goto error;
896       }
897
898       if (add_to_offset_list (&blocks, offset) == -1)
899         goto error;
900
901       struct ntreg_lf_record *lf =
902         (struct ntreg_lf_record *) (h->addr + offset);
903
904       count += le16toh (lf->nr_keys);
905     }
906
907     if (h->msglvl >= 2)
908       fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu,"
909                " counted = %zu\n",
910                nr_subkeys_in_nk, count);
911
912     if (nr_subkeys_in_nk != count) {
913       errno = ENOTSUP;
914       goto error;
915     }
916
917     /* Copy list of children.  Note nr_subkeys_in_nk is limited to
918      * something reasonable above.
919      */
920     for (i = 0; i < nr_offsets; ++i) {
921       hive_node_h offset = le32toh (ri->offset[i]);
922       offset += 0x1000;
923       if (!IS_VALID_BLOCK (h, offset)) {
924         if (h->msglvl >= 2)
925           fprintf (stderr, "hivex_node_children: returning EFAULT"
926                    " because ri-offset is not a valid block (0x%zx)\n",
927                    offset);
928         errno = EFAULT;
929         goto error;
930       }
931       if (!BLOCK_ID_EQ (h, offset, "lf") && !BLOCK_ID_EQ (h, offset, "lh")) {
932         if (h->msglvl >= 2)
933           fprintf (stderr, "get_children: returning ENOTSUP"
934                    " because ri-record offset does not point to lf/lh (0x%zx)\n",
935                    offset);
936         errno = ENOTSUP;
937         goto error;
938       }
939
940       struct ntreg_lf_record *lf =
941         (struct ntreg_lf_record *) (h->addr + offset);
942
943       size_t j;
944       for (j = 0; j < le16toh (lf->nr_keys); ++j) {
945         hive_node_h subkey = le32toh (lf->keys[j].offset);
946         subkey += 0x1000;
947         if (!(flags & GET_CHILDREN_NO_CHECK_NK)) {
948           if (!IS_VALID_BLOCK (h, subkey)) {
949             if (h->msglvl >= 2)
950               fprintf (stderr, "hivex_node_children: returning EFAULT"
951                        " because indirect subkey is not a valid block (0x%zx)\n",
952                        subkey);
953             errno = EFAULT;
954             goto error;
955           }
956         }
957         if (add_to_offset_list (&children, subkey) == -1)
958           goto error;
959       }
960     }
961     goto ok;
962   }
963   /* else not supported, set errno and fall through */
964   if (h->msglvl >= 2)
965     fprintf (stderr, "get_children: returning ENOTSUP"
966              " because subkey block is not lf/lh/ri (0x%zx, %d, %d)\n",
967              subkey_lf, block->id[0], block->id[1]);
968   errno = ENOTSUP;
969  error:
970   free_offset_list (&children);
971   free_offset_list (&blocks);
972   return -1;
973
974  ok:
975   *children_ret = return_offset_list (&children);
976   *blocks_ret = return_offset_list (&blocks);
977   if (!*children_ret || !*blocks_ret)
978     goto error;
979   return 0;
980 }
981
982 hive_node_h *
983 hivex_node_children (hive_h *h, hive_node_h node)
984 {
985   hive_node_h *children;
986   size_t *blocks;
987
988   if (get_children (h, node, &children, &blocks, 0) == -1)
989     return NULL;
990
991   free (blocks);
992   return children;
993 }
994
995 /* Very inefficient, but at least having a separate API call
996  * allows us to make it more efficient in future.
997  */
998 hive_node_h
999 hivex_node_get_child (hive_h *h, hive_node_h node, const char *nname)
1000 {
1001   hive_node_h *children = NULL;
1002   char *name = NULL;
1003   hive_node_h ret = 0;
1004
1005   children = hivex_node_children (h, node);
1006   if (!children) goto error;
1007
1008   size_t i;
1009   for (i = 0; children[i] != 0; ++i) {
1010     name = hivex_node_name (h, children[i]);
1011     if (!name) goto error;
1012     if (STRCASEEQ (name, nname)) {
1013       ret = children[i];
1014       break;
1015     }
1016     free (name); name = NULL;
1017   }
1018
1019  error:
1020   free (children);
1021   free (name);
1022   return ret;
1023 }
1024
1025 hive_node_h
1026 hivex_node_parent (hive_h *h, hive_node_h node)
1027 {
1028   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
1029     errno = EINVAL;
1030     return 0;
1031   }
1032
1033   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
1034
1035   hive_node_h ret = le32toh (nk->parent);
1036   ret += 0x1000;
1037   if (!IS_VALID_BLOCK (h, ret)) {
1038     if (h->msglvl >= 2)
1039       fprintf (stderr, "hivex_node_parent: returning EFAULT"
1040                " because parent is not a valid block (0x%zx)\n",
1041               ret);
1042     errno = EFAULT;
1043     return 0;
1044   }
1045   return ret;
1046 }
1047
1048 static int
1049 get_values (hive_h *h, hive_node_h node,
1050             hive_value_h **values_ret, size_t **blocks_ret)
1051 {
1052   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
1053     errno = EINVAL;
1054     return -1;
1055   }
1056
1057   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
1058
1059   size_t nr_values = le32toh (nk->nr_values);
1060
1061   if (h->msglvl >= 2)
1062     fprintf (stderr, "hivex_node_values: nr_values = %zu\n", nr_values);
1063
1064   INIT_OFFSET_LIST (values);
1065   INIT_OFFSET_LIST (blocks);
1066
1067   /* Deal with the common "no values" case quickly. */
1068   if (nr_values == 0)
1069     goto ok;
1070
1071   /* Arbitrarily limit the number of values we will ever deal with. */
1072   if (nr_values > HIVEX_MAX_VALUES) {
1073     if (h->msglvl >= 2)
1074       fprintf (stderr, "hivex: get_values: returning ERANGE"
1075                " because nr_values > HIVEX_MAX_VALUES (%zu > %d)\n",
1076                nr_values, HIVEX_MAX_VALUES);
1077     errno = ERANGE;
1078     goto error;
1079   }
1080
1081   /* Preallocate space for the values. */
1082   if (grow_offset_list (&values, nr_values) == -1)
1083     goto error;
1084
1085   /* Get the value list and check it looks reasonable. */
1086   size_t vlist_offset = le32toh (nk->vallist);
1087   vlist_offset += 0x1000;
1088   if (!IS_VALID_BLOCK (h, vlist_offset)) {
1089     if (h->msglvl >= 2)
1090       fprintf (stderr, "hivex_node_values: returning EFAULT"
1091                " because value list is not a valid block (0x%zx)\n",
1092                vlist_offset);
1093     errno = EFAULT;
1094     goto error;
1095   }
1096
1097   if (add_to_offset_list (&blocks, vlist_offset) == -1)
1098     goto error;
1099
1100   struct ntreg_value_list *vlist =
1101     (struct ntreg_value_list *) (h->addr + vlist_offset);
1102
1103   size_t len = block_len (h, vlist_offset, NULL);
1104   if (4 + nr_values * 4 > len) {
1105     if (h->msglvl >= 2)
1106       fprintf (stderr, "hivex_node_values: returning EFAULT"
1107                " because value list is too long (%zu, %zu)\n",
1108                nr_values, len);
1109     errno = EFAULT;
1110     goto error;
1111   }
1112
1113   size_t i;
1114   for (i = 0; i < nr_values; ++i) {
1115     hive_node_h value = le32toh (vlist->offset[i]);
1116     value += 0x1000;
1117     if (!IS_VALID_BLOCK (h, value)) {
1118       if (h->msglvl >= 2)
1119         fprintf (stderr, "hivex_node_values: returning EFAULT"
1120                  " because value is not a valid block (0x%zx)\n",
1121                  value);
1122       errno = EFAULT;
1123       goto error;
1124     }
1125     if (add_to_offset_list (&values, value) == -1)
1126       goto error;
1127   }
1128
1129  ok:
1130   *values_ret = return_offset_list (&values);
1131   *blocks_ret = return_offset_list (&blocks);
1132   if (!*values_ret || !*blocks_ret)
1133     goto error;
1134   return 0;
1135
1136  error:
1137   free_offset_list (&values);
1138   free_offset_list (&blocks);
1139   return -1;
1140 }
1141
1142 hive_value_h *
1143 hivex_node_values (hive_h *h, hive_node_h node)
1144 {
1145   hive_value_h *values;
1146   size_t *blocks;
1147
1148   if (get_values (h, node, &values, &blocks) == -1)
1149     return NULL;
1150
1151   free (blocks);
1152   return values;
1153 }
1154
1155 /* Very inefficient, but at least having a separate API call
1156  * allows us to make it more efficient in future.
1157  */
1158 hive_value_h
1159 hivex_node_get_value (hive_h *h, hive_node_h node, const char *key)
1160 {
1161   hive_value_h *values = NULL;
1162   char *name = NULL;
1163   hive_value_h ret = 0;
1164
1165   values = hivex_node_values (h, node);
1166   if (!values) goto error;
1167
1168   size_t i;
1169   for (i = 0; values[i] != 0; ++i) {
1170     name = hivex_value_key (h, values[i]);
1171     if (!name) goto error;
1172     if (STRCASEEQ (name, key)) {
1173       ret = values[i];
1174       break;
1175     }
1176     free (name); name = NULL;
1177   }
1178
1179  error:
1180   free (values);
1181   free (name);
1182   return ret;
1183 }
1184
1185 char *
1186 hivex_value_key (hive_h *h, hive_value_h value)
1187 {
1188   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
1189     errno = EINVAL;
1190     return 0;
1191   }
1192
1193   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
1194
1195   /* AFAIK the key is always plain ASCII, so no conversion to UTF-8 is
1196    * necessary.  However we do need to nul-terminate the string.
1197    */
1198
1199   /* vk->name_len is unsigned, 16 bit, so this is safe ...  However
1200    * we have to make sure the length doesn't exceed the block length.
1201    */
1202   size_t len = le16toh (vk->name_len);
1203   size_t seg_len = block_len (h, value, NULL);
1204   if (sizeof (struct ntreg_vk_record) + len - 1 > seg_len) {
1205     if (h->msglvl >= 2)
1206       fprintf (stderr, "hivex_value_key: returning EFAULT"
1207                " because key length is too long (%zu, %zu)\n",
1208                len, seg_len);
1209     errno = EFAULT;
1210     return NULL;
1211   }
1212
1213   char *ret = malloc (len + 1);
1214   if (ret == NULL)
1215     return NULL;
1216   memcpy (ret, vk->name, len);
1217   ret[len] = '\0';
1218   return ret;
1219 }
1220
1221 int
1222 hivex_value_type (hive_h *h, hive_value_h value, hive_type *t, size_t *len)
1223 {
1224   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
1225     errno = EINVAL;
1226     return -1;
1227   }
1228
1229   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
1230
1231   if (t)
1232     *t = le32toh (vk->data_type);
1233
1234   if (len) {
1235     *len = le32toh (vk->data_len);
1236     *len &= 0x7fffffff;         /* top bit indicates if data is stored inline */
1237   }
1238
1239   return 0;
1240 }
1241
1242 char *
1243 hivex_value_value (hive_h *h, hive_value_h value,
1244                    hive_type *t_rtn, size_t *len_rtn)
1245 {
1246   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
1247     errno = EINVAL;
1248     return NULL;
1249   }
1250
1251   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
1252
1253   hive_type t;
1254   size_t len;
1255   int is_inline;
1256
1257   t = le32toh (vk->data_type);
1258
1259   len = le32toh (vk->data_len);
1260   is_inline = !!(len & 0x80000000);
1261   len &= 0x7fffffff;
1262
1263   if (h->msglvl >= 2)
1264     fprintf (stderr, "hivex_value_value: value=0x%zx, t=%d, len=%zu, inline=%d\n",
1265              value, t, len, is_inline);
1266
1267   if (t_rtn)
1268     *t_rtn = t;
1269   if (len_rtn)
1270     *len_rtn = len;
1271
1272   if (is_inline && len > 4) {
1273     errno = ENOTSUP;
1274     return NULL;
1275   }
1276
1277   /* Arbitrarily limit the length that we will read. */
1278   if (len > HIVEX_MAX_VALUE_LEN) {
1279     if (h->msglvl >= 2)
1280       fprintf (stderr, "hivex_value_value: returning ERANGE because data "
1281                "length > HIVEX_MAX_VALUE_LEN (%zu > %d)\n",
1282                len, HIVEX_MAX_SUBKEYS);
1283     errno = ERANGE;
1284     return NULL;
1285   }
1286
1287   char *ret = malloc (len);
1288   if (ret == NULL)
1289     return NULL;
1290
1291   if (is_inline) {
1292     memcpy (ret, (char *) &vk->data_offset, len);
1293     return ret;
1294   }
1295
1296   size_t data_offset = le32toh (vk->data_offset);
1297   data_offset += 0x1000;
1298   if (!IS_VALID_BLOCK (h, data_offset)) {
1299     if (h->msglvl >= 2)
1300       fprintf (stderr, "hivex_value_value: returning EFAULT because data "
1301                "offset is not a valid block (0x%zx)\n",
1302                data_offset);
1303     errno = EFAULT;
1304     free (ret);
1305     return NULL;
1306   }
1307
1308   /* Check that the declared size isn't larger than the block its in.
1309    *
1310    * XXX Some apparently valid registries are seen to have this,
1311    * so turn this into a warning and substitute the smaller length
1312    * instead.
1313    */
1314   size_t blen = block_len (h, data_offset, NULL);
1315   if (len > blen - 4 /* subtract 4 for block header */) {
1316     if (h->msglvl >= 2)
1317       fprintf (stderr, "hivex_value_value: warning: declared data length "
1318                "is longer than the block it is in "
1319                "(data 0x%zx, data len %zu, block len %zu)\n",
1320                data_offset, len, blen);
1321     len = blen - 4;
1322
1323     /* Return the smaller length to the caller too. */
1324     if (len_rtn)
1325       *len_rtn = len;
1326   }
1327
1328   char *data = h->addr + data_offset + 4;
1329   memcpy (ret, data, len);
1330   return ret;
1331 }
1332
1333 static char *
1334 windows_utf16_to_utf8 (/* const */ char *input, size_t len)
1335 {
1336   iconv_t ic = iconv_open ("UTF-8", "UTF-16");
1337   if (ic == (iconv_t) -1)
1338     return NULL;
1339
1340   /* iconv(3) has an insane interface ... */
1341
1342   /* Mostly UTF-8 will be smaller, so this is a good initial guess. */
1343   size_t outalloc = len;
1344
1345  again:;
1346   size_t inlen = len;
1347   size_t outlen = outalloc;
1348   char *out = malloc (outlen + 1);
1349   if (out == NULL) {
1350     int err = errno;
1351     iconv_close (ic);
1352     errno = err;
1353     return NULL;
1354   }
1355   char *inp = input;
1356   char *outp = out;
1357
1358   size_t r = iconv (ic, &inp, &inlen, &outp, &outlen);
1359   if (r == (size_t) -1) {
1360     if (errno == E2BIG) {
1361       int err = errno;
1362       size_t prev = outalloc;
1363       /* Try again with a larger output buffer. */
1364       free (out);
1365       outalloc *= 2;
1366       if (outalloc < prev) {
1367         iconv_close (ic);
1368         errno = err;
1369         return NULL;
1370       }
1371       goto again;
1372     }
1373     else {
1374       /* Else some conversion failure, eg. EILSEQ, EINVAL. */
1375       int err = errno;
1376       iconv_close (ic);
1377       free (out);
1378       errno = err;
1379       return NULL;
1380     }
1381   }
1382
1383   *outp = '\0';
1384   iconv_close (ic);
1385
1386   return out;
1387 }
1388
1389 char *
1390 hivex_value_string (hive_h *h, hive_value_h value)
1391 {
1392   hive_type t;
1393   size_t len;
1394   char *data = hivex_value_value (h, value, &t, &len);
1395
1396   if (data == NULL)
1397     return NULL;
1398
1399   if (t != hive_t_string && t != hive_t_expand_string && t != hive_t_link) {
1400     free (data);
1401     errno = EINVAL;
1402     return NULL;
1403   }
1404
1405   /* Deal with the case where Windows has allocated a large buffer
1406    * full of random junk, and only the first few bytes of the buffer
1407    * contain a genuine UTF-16 string.
1408    *
1409    * In this case, iconv would try to process the junk bytes as UTF-16
1410    * and inevitably find an illegal sequence (EILSEQ).  Instead, stop
1411    * after we find the first \0\0.
1412    *
1413    * (Found by Hilko Bengen in a fresh Windows XP SOFTWARE hive).
1414    */
1415   size_t slen = utf16_string_len_in_bytes_max (data, len);
1416   if (slen < len)
1417     len = slen;
1418
1419   char *ret = windows_utf16_to_utf8 (data, len);
1420   free (data);
1421   if (ret == NULL)
1422     return NULL;
1423
1424   return ret;
1425 }
1426
1427 static void
1428 free_strings (char **argv)
1429 {
1430   if (argv) {
1431     size_t i;
1432
1433     for (i = 0; argv[i] != NULL; ++i)
1434       free (argv[i]);
1435     free (argv);
1436   }
1437 }
1438
1439 /* Get the length of a UTF-16 format string.  Handle the string as
1440  * pairs of bytes, looking for the first \0\0 pair.  Only read up to
1441  * 'len' maximum bytes.
1442  */
1443 static size_t
1444 utf16_string_len_in_bytes_max (const char *str, size_t len)
1445 {
1446   size_t ret = 0;
1447
1448   while (len >= 2 && (str[0] || str[1])) {
1449     str += 2;
1450     ret += 2;
1451     len -= 2;
1452   }
1453
1454   return ret;
1455 }
1456
1457 /* http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx */
1458 char **
1459 hivex_value_multiple_strings (hive_h *h, hive_value_h value)
1460 {
1461   hive_type t;
1462   size_t len;
1463   char *data = hivex_value_value (h, value, &t, &len);
1464
1465   if (data == NULL)
1466     return NULL;
1467
1468   if (t != hive_t_multiple_strings) {
1469     free (data);
1470     errno = EINVAL;
1471     return NULL;
1472   }
1473
1474   size_t nr_strings = 0;
1475   char **ret = malloc ((1 + nr_strings) * sizeof (char *));
1476   if (ret == NULL) {
1477     free (data);
1478     return NULL;
1479   }
1480   ret[0] = NULL;
1481
1482   char *p = data;
1483   size_t plen;
1484
1485   while (p < data + len &&
1486          (plen = utf16_string_len_in_bytes_max (p, data + len - p)) > 0) {
1487     nr_strings++;
1488     char **ret2 = realloc (ret, (1 + nr_strings) * sizeof (char *));
1489     if (ret2 == NULL) {
1490       free_strings (ret);
1491       free (data);
1492       return NULL;
1493     }
1494     ret = ret2;
1495
1496     ret[nr_strings-1] = windows_utf16_to_utf8 (p, plen);
1497     ret[nr_strings] = NULL;
1498     if (ret[nr_strings-1] == NULL) {
1499       free_strings (ret);
1500       free (data);
1501       return NULL;
1502     }
1503
1504     p += plen + 2 /* skip over UTF-16 \0\0 at the end of this string */;
1505   }
1506
1507   free (data);
1508   return ret;
1509 }
1510
1511 int32_t
1512 hivex_value_dword (hive_h *h, hive_value_h value)
1513 {
1514   hive_type t;
1515   size_t len;
1516   char *data = hivex_value_value (h, value, &t, &len);
1517
1518   if (data == NULL)
1519     return -1;
1520
1521   if ((t != hive_t_dword && t != hive_t_dword_be) || len != 4) {
1522     free (data);
1523     errno = EINVAL;
1524     return -1;
1525   }
1526
1527   int32_t ret = *(int32_t*)data;
1528   free (data);
1529   if (t == hive_t_dword)        /* little endian */
1530     ret = le32toh (ret);
1531   else
1532     ret = be32toh (ret);
1533
1534   return ret;
1535 }
1536
1537 int64_t
1538 hivex_value_qword (hive_h *h, hive_value_h value)
1539 {
1540   hive_type t;
1541   size_t len;
1542   char *data = hivex_value_value (h, value, &t, &len);
1543
1544   if (data == NULL)
1545     return -1;
1546
1547   if (t != hive_t_qword || len != 8) {
1548     free (data);
1549     errno = EINVAL;
1550     return -1;
1551   }
1552
1553   int64_t ret = *(int64_t*)data;
1554   free (data);
1555   ret = le64toh (ret);          /* always little endian */
1556
1557   return ret;
1558 }
1559
1560 /*----------------------------------------------------------------------
1561  * Visiting.
1562  */
1563
1564 int
1565 hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len,
1566              void *opaque, int flags)
1567 {
1568   return hivex_visit_node (h, hivex_root (h), visitor, len, opaque, flags);
1569 }
1570
1571 static int hivex__visit_node (hive_h *h, hive_node_h node,
1572                               const struct hivex_visitor *vtor,
1573                               char *unvisited, void *opaque, int flags);
1574
1575 int
1576 hivex_visit_node (hive_h *h, hive_node_h node,
1577                   const struct hivex_visitor *visitor, size_t len, void *opaque,
1578                   int flags)
1579 {
1580   struct hivex_visitor vtor;
1581   memset (&vtor, 0, sizeof vtor);
1582
1583   /* Note that len might be larger *or smaller* than the expected size. */
1584   size_t copysize = len <= sizeof vtor ? len : sizeof vtor;
1585   memcpy (&vtor, visitor, copysize);
1586
1587   /* This bitmap records unvisited nodes, so we don't loop if the
1588    * registry contains cycles.
1589    */
1590   char *unvisited = malloc (1 + h->size / 32);
1591   if (unvisited == NULL)
1592     return -1;
1593   memcpy (unvisited, h->bitmap, 1 + h->size / 32);
1594
1595   int r = hivex__visit_node (h, node, &vtor, unvisited, opaque, flags);
1596   free (unvisited);
1597   return r;
1598 }
1599
1600 static int
1601 hivex__visit_node (hive_h *h, hive_node_h node,
1602                    const struct hivex_visitor *vtor, char *unvisited,
1603                    void *opaque, int flags)
1604 {
1605   int skip_bad = flags & HIVEX_VISIT_SKIP_BAD;
1606   char *name = NULL;
1607   hive_value_h *values = NULL;
1608   hive_node_h *children = NULL;
1609   char *key = NULL;
1610   char *str = NULL;
1611   char **strs = NULL;
1612   int i;
1613
1614   /* Return -1 on all callback errors.  However on internal errors,
1615    * check if skip_bad is set and suppress those errors if so.
1616    */
1617   int ret = -1;
1618
1619   if (!BITMAP_TST (unvisited, node)) {
1620     if (h->msglvl >= 2)
1621       fprintf (stderr, "hivex__visit_node: contains cycle:"
1622                " visited node 0x%zx already\n",
1623                node);
1624
1625     errno = ELOOP;
1626     return skip_bad ? 0 : -1;
1627   }
1628   BITMAP_CLR (unvisited, node);
1629
1630   name = hivex_node_name (h, node);
1631   if (!name) return skip_bad ? 0 : -1;
1632   if (vtor->node_start && vtor->node_start (h, opaque, node, name) == -1)
1633     goto error;
1634
1635   values = hivex_node_values (h, node);
1636   if (!values) {
1637     ret = skip_bad ? 0 : -1;
1638     goto error;
1639   }
1640
1641   for (i = 0; values[i] != 0; ++i) {
1642     hive_type t;
1643     size_t len;
1644
1645     if (hivex_value_type (h, values[i], &t, &len) == -1) {
1646       ret = skip_bad ? 0 : -1;
1647       goto error;
1648     }
1649
1650     key = hivex_value_key (h, values[i]);
1651     if (key == NULL) {
1652       ret = skip_bad ? 0 : -1;
1653       goto error;
1654     }
1655
1656     if (vtor->value_any) {
1657       str = hivex_value_value (h, values[i], &t, &len);
1658       if (str == NULL) {
1659         ret = skip_bad ? 0 : -1;
1660         goto error;
1661       }
1662       if (vtor->value_any (h, opaque, node, values[i], t, len, key, str) == -1)
1663         goto error;
1664       free (str); str = NULL;
1665     }
1666     else {
1667       switch (t) {
1668       case hive_t_none:
1669         str = hivex_value_value (h, values[i], &t, &len);
1670         if (str == NULL) {
1671           ret = skip_bad ? 0 : -1;
1672           goto error;
1673         }
1674         if (t != hive_t_none) {
1675           ret = skip_bad ? 0 : -1;
1676           goto error;
1677         }
1678         if (vtor->value_none &&
1679             vtor->value_none (h, opaque, node, values[i], t, len, key, str) == -1)
1680           goto error;
1681         free (str); str = NULL;
1682         break;
1683
1684       case hive_t_string:
1685       case hive_t_expand_string:
1686       case hive_t_link:
1687         str = hivex_value_string (h, values[i]);
1688         if (str == NULL) {
1689           if (errno != EILSEQ && errno != EINVAL) {
1690             ret = skip_bad ? 0 : -1;
1691             goto error;
1692           }
1693           if (vtor->value_string_invalid_utf16) {
1694             str = hivex_value_value (h, values[i], &t, &len);
1695             if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i],
1696                                                   t, len, key, str) == -1)
1697               goto error;
1698             free (str); str = NULL;
1699           }
1700           break;
1701         }
1702         if (vtor->value_string &&
1703             vtor->value_string (h, opaque, node, values[i],
1704                                 t, len, key, str) == -1)
1705           goto error;
1706         free (str); str = NULL;
1707         break;
1708
1709       case hive_t_dword:
1710       case hive_t_dword_be: {
1711         int32_t i32 = hivex_value_dword (h, values[i]);
1712         if (vtor->value_dword &&
1713             vtor->value_dword (h, opaque, node, values[i],
1714                                t, len, key, i32) == -1)
1715           goto error;
1716         break;
1717       }
1718
1719       case hive_t_qword: {
1720         int64_t i64 = hivex_value_qword (h, values[i]);
1721         if (vtor->value_qword &&
1722             vtor->value_qword (h, opaque, node, values[i],
1723                                t, len, key, i64) == -1)
1724           goto error;
1725         break;
1726       }
1727
1728       case hive_t_binary:
1729         str = hivex_value_value (h, values[i], &t, &len);
1730         if (str == NULL) {
1731           ret = skip_bad ? 0 : -1;
1732           goto error;
1733         }
1734         if (t != hive_t_binary) {
1735           ret = skip_bad ? 0 : -1;
1736           goto error;
1737         }
1738         if (vtor->value_binary &&
1739             vtor->value_binary (h, opaque, node, values[i],
1740                                 t, len, key, str) == -1)
1741           goto error;
1742         free (str); str = NULL;
1743         break;
1744
1745       case hive_t_multiple_strings:
1746         strs = hivex_value_multiple_strings (h, values[i]);
1747         if (strs == NULL) {
1748           if (errno != EILSEQ && errno != EINVAL) {
1749             ret = skip_bad ? 0 : -1;
1750             goto error;
1751           }
1752           if (vtor->value_string_invalid_utf16) {
1753             str = hivex_value_value (h, values[i], &t, &len);
1754             if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i],
1755                                                   t, len, key, str) == -1)
1756               goto error;
1757             free (str); str = NULL;
1758           }
1759           break;
1760         }
1761         if (vtor->value_multiple_strings &&
1762             vtor->value_multiple_strings (h, opaque, node, values[i],
1763                                           t, len, key, strs) == -1)
1764           goto error;
1765         free_strings (strs); strs = NULL;
1766         break;
1767
1768       case hive_t_resource_list:
1769       case hive_t_full_resource_description:
1770       case hive_t_resource_requirements_list:
1771       default:
1772         str = hivex_value_value (h, values[i], &t, &len);
1773         if (str == NULL) {
1774           ret = skip_bad ? 0 : -1;
1775           goto error;
1776         }
1777         if (vtor->value_other &&
1778             vtor->value_other (h, opaque, node, values[i],
1779                                t, len, key, str) == -1)
1780           goto error;
1781         free (str); str = NULL;
1782         break;
1783       }
1784     }
1785
1786     free (key); key = NULL;
1787   }
1788
1789   children = hivex_node_children (h, node);
1790   if (children == NULL) {
1791     ret = skip_bad ? 0 : -1;
1792     goto error;
1793   }
1794
1795   for (i = 0; children[i] != 0; ++i) {
1796     if (h->msglvl >= 2)
1797       fprintf (stderr, "hivex__visit_node: %s: visiting subkey %d (0x%zx)\n",
1798                name, i, children[i]);
1799
1800     if (hivex__visit_node (h, children[i], vtor, unvisited, opaque, flags) == -1)
1801       goto error;
1802   }
1803
1804   if (vtor->node_end && vtor->node_end (h, opaque, node, name) == -1)
1805     goto error;
1806
1807   ret = 0;
1808
1809  error:
1810   free (name);
1811   free (values);
1812   free (children);
1813   free (key);
1814   free (str);
1815   free_strings (strs);
1816   return ret;
1817 }
1818
1819 /*----------------------------------------------------------------------
1820  * Writing.
1821  */
1822
1823 /* Allocate an hbin (page), extending the malloc'd space if necessary,
1824  * and updating the hive handle fields (but NOT the hive disk header
1825  * -- the hive disk header is updated when we commit).  This function
1826  * also extends the bitmap if necessary.
1827  *
1828  * 'allocation_hint' is the size of the block allocation we would like
1829  * to make.  Normally registry blocks are very small (avg 50 bytes)
1830  * and are contained in standard-sized pages (4KB), but the registry
1831  * can support blocks which are larger than a standard page, in which
1832  * case it creates a page of 8KB, 12KB etc.
1833  *
1834  * Returns:
1835  * > 0 : offset of first usable byte of new page (after page header)
1836  * 0   : error (errno set)
1837  */
1838 static size_t
1839 allocate_page (hive_h *h, size_t allocation_hint)
1840 {
1841   /* In almost all cases this will be 1. */
1842   size_t nr_4k_pages =
1843     1 + (allocation_hint + sizeof (struct ntreg_hbin_page) - 1) / 4096;
1844   assert (nr_4k_pages >= 1);
1845
1846   /* 'extend' is the number of bytes to extend the file by.  Note that
1847    * hives found in the wild often contain slack between 'endpages'
1848    * and the actual end of the file, so we don't always need to make
1849    * the file larger.
1850    */
1851   ssize_t extend = h->endpages + nr_4k_pages * 4096 - h->size;
1852
1853   if (h->msglvl >= 2) {
1854     fprintf (stderr, "allocate_page: current endpages = 0x%zx,"
1855              " current size = 0x%zx\n",
1856              h->endpages, h->size);
1857     fprintf (stderr, "allocate_page: extending file by %zd bytes"
1858              " (<= 0 if no extension)\n",
1859              extend);
1860   }
1861
1862   if (extend > 0) {
1863     size_t oldsize = h->size;
1864     size_t newsize = h->size + extend;
1865     char *newaddr = realloc (h->addr, newsize);
1866     if (newaddr == NULL)
1867       return 0;
1868
1869     size_t oldbitmapsize = 1 + oldsize / 32;
1870     size_t newbitmapsize = 1 + newsize / 32;
1871     char *newbitmap = realloc (h->bitmap, newbitmapsize);
1872     if (newbitmap == NULL) {
1873       free (newaddr);
1874       return 0;
1875     }
1876
1877     h->addr = newaddr;
1878     h->size = newsize;
1879     h->bitmap = newbitmap;
1880
1881     memset (h->addr + oldsize, 0, newsize - oldsize);
1882     memset (h->bitmap + oldbitmapsize, 0, newbitmapsize - oldbitmapsize);
1883   }
1884
1885   size_t offset = h->endpages;
1886   h->endpages += nr_4k_pages * 4096;
1887
1888   if (h->msglvl >= 2)
1889     fprintf (stderr, "allocate_page: new endpages = 0x%zx, new size = 0x%zx\n",
1890              h->endpages, h->size);
1891
1892   /* Write the hbin header. */
1893   struct ntreg_hbin_page *page =
1894     (struct ntreg_hbin_page *) (h->addr + offset);
1895   page->magic[0] = 'h';
1896   page->magic[1] = 'b';
1897   page->magic[2] = 'i';
1898   page->magic[3] = 'n';
1899   page->offset_first = htole32 (offset - 0x1000);
1900   page->page_size = htole32 (nr_4k_pages * 4096);
1901   memset (page->unknown, 0, sizeof (page->unknown));
1902
1903   if (h->msglvl >= 2)
1904     fprintf (stderr, "allocate_page: new page at 0x%zx\n", offset);
1905
1906   /* Offset of first usable byte after the header. */
1907   return offset + sizeof (struct ntreg_hbin_page);
1908 }
1909
1910 /* Allocate a single block, first allocating an hbin (page) at the end
1911  * of the current file if necessary.  NB. To keep the implementation
1912  * simple and more likely to be correct, we do not reuse existing free
1913  * blocks.
1914  *
1915  * seg_len is the size of the block (this INCLUDES the block header).
1916  * The header of the block is initialized to -seg_len (negative to
1917  * indicate used).  id[2] is the block ID (type), eg. "nk" for nk-
1918  * record.  The block bitmap is updated to show this block as valid.
1919  * The rest of the contents of the block will be zero.
1920  *
1921  * **NB** Because allocate_block may reallocate the memory, all
1922  * pointers into the memory become potentially invalid.  I really
1923  * love writing in C, can't you tell?
1924  *
1925  * Returns:
1926  * > 0 : offset of new block
1927  * 0   : error (errno set)
1928  */
1929 static size_t
1930 allocate_block (hive_h *h, size_t seg_len, const char id[2])
1931 {
1932   if (!h->writable) {
1933     errno = EROFS;
1934     return 0;
1935   }
1936
1937   if (seg_len < 4) {
1938     /* The caller probably forgot to include the header.  Note that
1939      * value lists have no ID field, so seg_len == 4 would be possible
1940      * for them, albeit unusual.
1941      */
1942     if (h->msglvl >= 2)
1943       fprintf (stderr, "allocate_block: refusing too small allocation (%zu),"
1944                " returning ERANGE\n", seg_len);
1945     errno = ERANGE;
1946     return 0;
1947   }
1948
1949   /* Refuse really large allocations. */
1950   if (seg_len > HIVEX_MAX_ALLOCATION) {
1951     if (h->msglvl >= 2)
1952       fprintf (stderr, "allocate_block: refusing large allocation (%zu),"
1953                " returning ERANGE\n", seg_len);
1954     errno = ERANGE;
1955     return 0;
1956   }
1957
1958   /* Round up allocation to multiple of 8 bytes.  All blocks must be
1959    * on an 8 byte boundary.
1960    */
1961   seg_len = (seg_len + 7) & ~7;
1962
1963   /* Allocate a new page if necessary. */
1964   if (h->endblocks == 0 || h->endblocks + seg_len > h->endpages) {
1965     size_t newendblocks = allocate_page (h, seg_len);
1966     if (newendblocks == 0)
1967       return 0;
1968     h->endblocks = newendblocks;
1969   }
1970
1971   size_t offset = h->endblocks;
1972
1973   if (h->msglvl >= 2)
1974     fprintf (stderr, "allocate_block: new block at 0x%zx, size %zu\n",
1975              offset, seg_len);
1976
1977   struct ntreg_hbin_block *blockhdr =
1978     (struct ntreg_hbin_block *) (h->addr + offset);
1979
1980   memset (blockhdr, 0, seg_len);
1981
1982   blockhdr->seg_len = htole32 (- (int32_t) seg_len);
1983   if (id[0] && id[1] && seg_len >= sizeof (struct ntreg_hbin_block)) {
1984     blockhdr->id[0] = id[0];
1985     blockhdr->id[1] = id[1];
1986   }
1987
1988   BITMAP_SET (h->bitmap, offset);
1989
1990   h->endblocks += seg_len;
1991
1992   /* If there is space after the last block in the last page, then we
1993    * have to put a dummy free block header here to mark the rest of
1994    * the page as free.
1995    */
1996   ssize_t rem = h->endpages - h->endblocks;
1997   if (rem > 0) {
1998     if (h->msglvl >= 2)
1999       fprintf (stderr, "allocate_block: marking remainder of page free"
2000                " starting at 0x%zx, size %zd\n", h->endblocks, rem);
2001
2002     assert (rem >= 4);
2003
2004     blockhdr = (struct ntreg_hbin_block *) (h->addr + h->endblocks);
2005     blockhdr->seg_len = htole32 ((int32_t) rem);
2006   }
2007
2008   return offset;
2009 }
2010
2011 /* 'offset' must point to a valid, used block.  This function marks
2012  * the block unused (by updating the seg_len field) and invalidates
2013  * the bitmap.  It does NOT do this recursively, so to avoid creating
2014  * unreachable used blocks, callers may have to recurse over the hive
2015  * structures.  Also callers must ensure there are no references to
2016  * this block from other parts of the hive.
2017  */
2018 static void
2019 mark_block_unused (hive_h *h, size_t offset)
2020 {
2021   assert (h->writable);
2022   assert (IS_VALID_BLOCK (h, offset));
2023
2024   if (h->msglvl >= 2)
2025     fprintf (stderr, "mark_block_unused: marking 0x%zx unused\n", offset);
2026
2027   struct ntreg_hbin_block *blockhdr =
2028     (struct ntreg_hbin_block *) (h->addr + offset);
2029
2030   size_t seg_len = block_len (h, offset, NULL);
2031   blockhdr->seg_len = htole32 (seg_len);
2032
2033   BITMAP_CLR (h->bitmap, offset);
2034 }
2035
2036 /* Delete all existing values at this node. */
2037 static int
2038 delete_values (hive_h *h, hive_node_h node)
2039 {
2040   assert (h->writable);
2041
2042   hive_value_h *values;
2043   size_t *blocks;
2044   if (get_values (h, node, &values, &blocks) == -1)
2045     return -1;
2046
2047   size_t i;
2048   for (i = 0; blocks[i] != 0; ++i)
2049     mark_block_unused (h, blocks[i]);
2050
2051   free (blocks);
2052
2053   for (i = 0; values[i] != 0; ++i) {
2054     struct ntreg_vk_record *vk =
2055       (struct ntreg_vk_record *) (h->addr + values[i]);
2056
2057     size_t len;
2058     int is_inline;
2059     len = le32toh (vk->data_len);
2060     is_inline = !!(len & 0x80000000); /* top bit indicates is inline */
2061     len &= 0x7fffffff;
2062
2063     if (!is_inline) {           /* non-inline, so remove data block */
2064       size_t data_offset = le32toh (vk->data_offset);
2065       data_offset += 0x1000;
2066       mark_block_unused (h, data_offset);
2067     }
2068
2069     /* remove vk record */
2070     mark_block_unused (h, values[i]);
2071   }
2072
2073   free (values);
2074
2075   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
2076   nk->nr_values = htole32 (0);
2077   nk->vallist = htole32 (0xffffffff);
2078
2079   return 0;
2080 }
2081
2082 int
2083 hivex_commit (hive_h *h, const char *filename, int flags)
2084 {
2085   if (flags != 0) {
2086     errno = EINVAL;
2087     return -1;
2088   }
2089
2090   if (!h->writable) {
2091     errno = EROFS;
2092     return -1;
2093   }
2094
2095   filename = filename ? : h->filename;
2096   int fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666);
2097   if (fd == -1)
2098     return -1;
2099
2100   /* Update the header fields. */
2101   uint32_t sequence = le32toh (h->hdr->sequence1);
2102   sequence++;
2103   h->hdr->sequence1 = htole32 (sequence);
2104   h->hdr->sequence2 = htole32 (sequence);
2105   /* XXX Ought to update h->hdr->last_modified. */
2106   h->hdr->blocks = htole32 (h->endpages - 0x1000);
2107
2108   /* Recompute header checksum. */
2109   uint32_t sum = header_checksum (h);
2110   h->hdr->csum = htole32 (sum);
2111
2112   if (h->msglvl >= 2)
2113     fprintf (stderr, "hivex_commit: new header checksum: 0x%x\n", sum);
2114
2115   if (full_write (fd, h->addr, h->size) != h->size) {
2116     int err = errno;
2117     close (fd);
2118     errno = err;
2119     return -1;
2120   }
2121
2122   if (close (fd) == -1)
2123     return -1;
2124
2125   return 0;
2126 }
2127
2128 /* Calculate the hash for a lf or lh record offset.
2129  */
2130 static void
2131 calc_hash (const char *type, const char *name, char *ret)
2132 {
2133   size_t len = strlen (name);
2134
2135   if (STRPREFIX (type, "lf"))
2136     /* Old-style, not used in current registries. */
2137     memcpy (ret, name, len < 4 ? len : 4);
2138   else {
2139     /* New-style for lh-records. */
2140     size_t i, c;
2141     uint32_t h = 0;
2142     for (i = 0; i < len; ++i) {
2143       c = c_toupper (name[i]);
2144       h *= 37;
2145       h += c;
2146     }
2147     *((uint32_t *) ret) = htole32 (h);
2148   }
2149 }
2150
2151 /* Create a completely new lh-record containing just the single node. */
2152 static size_t
2153 new_lh_record (hive_h *h, const char *name, hive_node_h node)
2154 {
2155   static const char id[2] = { 'l', 'h' };
2156   size_t seg_len = sizeof (struct ntreg_lf_record);
2157   size_t offset = allocate_block (h, seg_len, id);
2158   if (offset == 0)
2159     return 0;
2160
2161   struct ntreg_lf_record *lh = (struct ntreg_lf_record *) (h->addr + offset);
2162   lh->nr_keys = htole16 (1);
2163   lh->keys[0].offset = htole32 (node - 0x1000);
2164   calc_hash ("lh", name, lh->keys[0].hash);
2165
2166   return offset;
2167 }
2168
2169 /* Insert node into existing lf/lh-record at position.
2170  * This allocates a new record and marks the old one as unused.
2171  */
2172 static size_t
2173 insert_lf_record (hive_h *h, size_t old_offs, size_t posn,
2174                   const char *name, hive_node_h node)
2175 {
2176   assert (IS_VALID_BLOCK (h, old_offs));
2177
2178   /* Work around C stupidity.
2179    * http://www.redhat.com/archives/libguestfs/2010-February/msg00056.html
2180    */
2181   int test = BLOCK_ID_EQ (h, old_offs, "lf") || BLOCK_ID_EQ (h, old_offs, "lh");
2182   assert (test);
2183
2184   struct ntreg_lf_record *old_lf =
2185     (struct ntreg_lf_record *) (h->addr + old_offs);
2186   size_t nr_keys = le16toh (old_lf->nr_keys);
2187
2188   nr_keys++; /* in new record ... */
2189
2190   size_t seg_len = sizeof (struct ntreg_lf_record) + (nr_keys-1) * 8;
2191
2192   /* Copy the old_lf->id in case it moves during allocate_block. */
2193   char id[2];
2194   memcpy (id, old_lf->id, sizeof id);
2195
2196   size_t new_offs = allocate_block (h, seg_len, id);
2197   if (new_offs == 0)
2198     return 0;
2199
2200   /* old_lf could have been invalidated by allocate_block. */
2201   old_lf = (struct ntreg_lf_record *) (h->addr + old_offs);
2202
2203   struct ntreg_lf_record *new_lf =
2204     (struct ntreg_lf_record *) (h->addr + new_offs);
2205   new_lf->nr_keys = htole16 (nr_keys);
2206
2207   /* Copy the keys until we reach posn, insert the new key there, then
2208    * copy the remaining keys.
2209    */
2210   size_t i;
2211   for (i = 0; i < posn; ++i)
2212     new_lf->keys[i] = old_lf->keys[i];
2213
2214   new_lf->keys[i].offset = htole32 (node - 0x1000);
2215   calc_hash (new_lf->id, name, new_lf->keys[i].hash);
2216
2217   for (i = posn+1; i < nr_keys; ++i)
2218     new_lf->keys[i] = old_lf->keys[i-1];
2219
2220   /* Old block is unused, return new block. */
2221   mark_block_unused (h, old_offs);
2222   return new_offs;
2223 }
2224
2225 /* Compare name with name in nk-record. */
2226 static int
2227 compare_name_with_nk_name (hive_h *h, const char *name, hive_node_h nk_offs)
2228 {
2229   assert (IS_VALID_BLOCK (h, nk_offs));
2230   assert (BLOCK_ID_EQ (h, nk_offs, "nk"));
2231
2232   /* Name in nk is not necessarily nul-terminated. */
2233   char *nname = hivex_node_name (h, nk_offs);
2234
2235   /* Unfortunately we don't have a way to return errors here. */
2236   if (!nname) {
2237     perror ("compare_name_with_nk_name");
2238     return 0;
2239   }
2240
2241   int r = strcasecmp (name, nname);
2242   free (nname);
2243
2244   return r;
2245 }
2246
2247 hive_node_h
2248 hivex_node_add_child (hive_h *h, hive_node_h parent, const char *name)
2249 {
2250   if (!h->writable) {
2251     errno = EROFS;
2252     return 0;
2253   }
2254
2255   if (!IS_VALID_BLOCK (h, parent) || !BLOCK_ID_EQ (h, parent, "nk")) {
2256     errno = EINVAL;
2257     return 0;
2258   }
2259
2260   if (name == NULL || strlen (name) == 0) {
2261     errno = EINVAL;
2262     return 0;
2263   }
2264
2265   if (hivex_node_get_child (h, parent, name) != 0) {
2266     errno = EEXIST;
2267     return 0;
2268   }
2269
2270   /* Create the new nk-record. */
2271   static const char nk_id[2] = { 'n', 'k' };
2272   size_t seg_len = sizeof (struct ntreg_nk_record) + strlen (name);
2273   hive_node_h node = allocate_block (h, seg_len, nk_id);
2274   if (node == 0)
2275     return 0;
2276
2277   if (h->msglvl >= 2)
2278     fprintf (stderr, "hivex_node_add_child: allocated new nk-record"
2279              " for child at 0x%zx\n", node);
2280
2281   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
2282   nk->flags = htole16 (0x0020); /* key is ASCII. */
2283   nk->parent = htole32 (parent - 0x1000);
2284   nk->subkey_lf = htole32 (0xffffffff);
2285   nk->subkey_lf_volatile = htole32 (0xffffffff);
2286   nk->vallist = htole32 (0xffffffff);
2287   nk->classname = htole32 (0xffffffff);
2288   nk->name_len = htole16 (strlen (name));
2289   strcpy (nk->name, name);
2290
2291   /* Inherit parent sk. */
2292   struct ntreg_nk_record *parent_nk =
2293     (struct ntreg_nk_record *) (h->addr + parent);
2294   size_t parent_sk_offset = le32toh (parent_nk->sk);
2295   parent_sk_offset += 0x1000;
2296   if (!IS_VALID_BLOCK (h, parent_sk_offset) ||
2297       !BLOCK_ID_EQ (h, parent_sk_offset, "sk")) {
2298     if (h->msglvl >= 2)
2299       fprintf (stderr, "hivex_node_add_child: returning EFAULT"
2300                " because parent sk is not a valid block (%zu)\n",
2301                parent_sk_offset);
2302     errno = EFAULT;
2303     return 0;
2304   }
2305   struct ntreg_sk_record *sk =
2306     (struct ntreg_sk_record *) (h->addr + parent_sk_offset);
2307   sk->refcount = htole32 (le32toh (sk->refcount) + 1);
2308   nk->sk = htole32 (parent_sk_offset - 0x1000);
2309
2310   /* Inherit parent timestamp. */
2311   nk->timestamp = parent_nk->timestamp;
2312
2313   /* What I found out the hard way (not documented anywhere): the
2314    * subkeys in lh-records must be kept sorted.  If you just add a
2315    * subkey in a non-sorted position (eg. just add it at the end) then
2316    * Windows won't see the subkey _and_ Windows will corrupt the hive
2317    * itself when it modifies or saves it.
2318    *
2319    * So use get_children() to get a list of intermediate
2320    * lf/lh-records.  get_children() returns these in reading order
2321    * (which is sorted), so we look for the lf/lh-records in sequence
2322    * until we find the key name just after the one we are inserting,
2323    * and we insert the subkey just before it.
2324    *
2325    * The only other case is the no-subkeys case, where we have to
2326    * create a brand new lh-record.
2327    */
2328   hive_node_h *unused;
2329   size_t *blocks;
2330
2331   if (get_children (h, parent, &unused, &blocks, 0) == -1)
2332     return 0;
2333   free (unused);
2334
2335   size_t i, j;
2336   size_t nr_subkeys_in_parent_nk = le32toh (parent_nk->nr_subkeys);
2337   if (nr_subkeys_in_parent_nk == 0) { /* No subkeys case. */
2338     /* Free up any existing intermediate blocks. */
2339     for (i = 0; blocks[i] != 0; ++i)
2340       mark_block_unused (h, blocks[i]);
2341     size_t lh_offs = new_lh_record (h, name, node);
2342     if (lh_offs == 0) {
2343       free (blocks);
2344       return 0;
2345     }
2346
2347     /* Recalculate pointers that could have been invalidated by
2348      * previous call to allocate_block (via new_lh_record).
2349      */
2350     nk = (struct ntreg_nk_record *) (h->addr + node);
2351     parent_nk = (struct ntreg_nk_record *) (h->addr + parent);
2352
2353     if (h->msglvl >= 2)
2354       fprintf (stderr, "hivex_node_add_child: no keys, allocated new"
2355                " lh-record at 0x%zx\n", lh_offs);
2356
2357     parent_nk->subkey_lf = htole32 (lh_offs - 0x1000);
2358   }
2359   else {                        /* Insert subkeys case. */
2360     size_t old_offs = 0, new_offs = 0;
2361     struct ntreg_lf_record *old_lf = NULL;
2362
2363     /* Find lf/lh key name just after the one we are inserting. */
2364     for (i = 0; blocks[i] != 0; ++i) {
2365       if (BLOCK_ID_EQ (h, blocks[i], "lf") ||
2366           BLOCK_ID_EQ (h, blocks[i], "lh")) {
2367         old_offs = blocks[i];
2368         old_lf = (struct ntreg_lf_record *) (h->addr + old_offs);
2369         for (j = 0; j < le16toh (old_lf->nr_keys); ++j) {
2370           hive_node_h nk_offs = le32toh (old_lf->keys[j].offset);
2371           nk_offs += 0x1000;
2372           if (compare_name_with_nk_name (h, name, nk_offs) < 0)
2373             goto insert_it;
2374         }
2375       }
2376     }
2377
2378     /* Insert it at the end.
2379      * old_offs points to the last lf record, set j.
2380      */
2381     assert (old_offs != 0);   /* should never happen if nr_subkeys > 0 */
2382     j = le16toh (old_lf->nr_keys);
2383
2384     /* Insert it. */
2385   insert_it:
2386     if (h->msglvl >= 2)
2387       fprintf (stderr, "hivex_node_add_child: insert key in existing"
2388                " lh-record at 0x%zx, posn %zu\n", old_offs, j);
2389
2390     new_offs = insert_lf_record (h, old_offs, j, name, node);
2391     if (new_offs == 0) {
2392       free (blocks);
2393       return 0;
2394     }
2395
2396     /* Recalculate pointers that could have been invalidated by
2397      * previous call to allocate_block (via insert_lf_record).
2398      */
2399     nk = (struct ntreg_nk_record *) (h->addr + node);
2400     parent_nk = (struct ntreg_nk_record *) (h->addr + parent);
2401
2402     if (h->msglvl >= 2)
2403       fprintf (stderr, "hivex_node_add_child: new lh-record at 0x%zx\n",
2404                new_offs);
2405
2406     /* If the lf/lh-record was directly referenced by the parent nk,
2407      * then update the parent nk.
2408      */
2409     if (le32toh (parent_nk->subkey_lf) + 0x1000 == old_offs)
2410       parent_nk->subkey_lf = htole32 (new_offs - 0x1000);
2411     /* Else we have to look for the intermediate ri-record and update
2412      * that in-place.
2413      */
2414     else {
2415       for (i = 0; blocks[i] != 0; ++i) {
2416         if (BLOCK_ID_EQ (h, blocks[i], "ri")) {
2417           struct ntreg_ri_record *ri =
2418             (struct ntreg_ri_record *) (h->addr + blocks[i]);
2419           for (j = 0; j < le16toh (ri->nr_offsets); ++j)
2420             if (le32toh (ri->offset[j] + 0x1000) == old_offs) {
2421               ri->offset[j] = htole32 (new_offs - 0x1000);
2422               goto found_it;
2423             }
2424         }
2425       }
2426
2427       /* Not found ..  This is an internal error. */
2428       if (h->msglvl >= 2)
2429         fprintf (stderr, "hivex_node_add_child: returning ENOTSUP"
2430                  " because could not find ri->lf link\n");
2431       errno = ENOTSUP;
2432       free (blocks);
2433       return 0;
2434
2435     found_it:
2436       ;
2437     }
2438   }
2439
2440   free (blocks);
2441
2442   /* Update nr_subkeys in parent nk. */
2443   nr_subkeys_in_parent_nk++;
2444   parent_nk->nr_subkeys = htole32 (nr_subkeys_in_parent_nk);
2445
2446   /* Update max_subkey_name_len in parent nk. */
2447   uint16_t max = le16toh (parent_nk->max_subkey_name_len);
2448   if (max < strlen (name) * 2)  /* *2 because "recoded" in UTF16-LE. */
2449     parent_nk->max_subkey_name_len = htole16 (strlen (name) * 2);
2450
2451   return node;
2452 }
2453
2454 /* Decrement the refcount of an sk-record, and if it reaches zero,
2455  * unlink it from the chain and delete it.
2456  */
2457 static int
2458 delete_sk (hive_h *h, size_t sk_offset)
2459 {
2460   if (!IS_VALID_BLOCK (h, sk_offset) || !BLOCK_ID_EQ (h, sk_offset, "sk")) {
2461     if (h->msglvl >= 2)
2462       fprintf (stderr, "delete_sk: not an sk record: 0x%zx\n", sk_offset);
2463     errno = EFAULT;
2464     return -1;
2465   }
2466
2467   struct ntreg_sk_record *sk = (struct ntreg_sk_record *) (h->addr + sk_offset);
2468
2469   if (sk->refcount == 0) {
2470     if (h->msglvl >= 2)
2471       fprintf (stderr, "delete_sk: sk record already has refcount 0: 0x%zx\n",
2472                sk_offset);
2473     errno = EINVAL;
2474     return -1;
2475   }
2476
2477   sk->refcount--;
2478
2479   if (sk->refcount == 0) {
2480     size_t sk_prev_offset = sk->sk_prev;
2481     sk_prev_offset += 0x1000;
2482
2483     size_t sk_next_offset = sk->sk_next;
2484     sk_next_offset += 0x1000;
2485
2486     /* Update sk_prev/sk_next SKs, unless they both point back to this
2487      * cell in which case we are deleting the last SK.
2488      */
2489     if (sk_prev_offset != sk_offset && sk_next_offset != sk_offset) {
2490       struct ntreg_sk_record *sk_prev =
2491         (struct ntreg_sk_record *) (h->addr + sk_prev_offset);
2492       struct ntreg_sk_record *sk_next =
2493         (struct ntreg_sk_record *) (h->addr + sk_next_offset);
2494
2495       sk_prev->sk_next = htole32 (sk_next_offset - 0x1000);
2496       sk_next->sk_prev = htole32 (sk_prev_offset - 0x1000);
2497     }
2498
2499     /* Refcount is zero so really delete this block. */
2500     mark_block_unused (h, sk_offset);
2501   }
2502
2503   return 0;
2504 }
2505
2506 /* Callback from hivex_node_delete_child which is called to delete a
2507  * node AFTER its subnodes have been visited.  The subnodes have been
2508  * deleted but we still have to delete any lf/lh/li/ri records and the
2509  * value list block and values, followed by deleting the node itself.
2510  */
2511 static int
2512 delete_node (hive_h *h, void *opaque, hive_node_h node, const char *name)
2513 {
2514   /* Get the intermediate blocks.  The subkeys have already been
2515    * deleted by this point, so tell get_children() not to check for
2516    * validity of the nk-records.
2517    */
2518   hive_node_h *unused;
2519   size_t *blocks;
2520   if (get_children (h, node, &unused, &blocks, GET_CHILDREN_NO_CHECK_NK) == -1)
2521     return -1;
2522   free (unused);
2523
2524   /* We don't care what's in these intermediate blocks, so we can just
2525    * delete them unconditionally.
2526    */
2527   size_t i;
2528   for (i = 0; blocks[i] != 0; ++i)
2529     mark_block_unused (h, blocks[i]);
2530
2531   free (blocks);
2532
2533   /* Delete the values in the node. */
2534   if (delete_values (h, node) == -1)
2535     return -1;
2536
2537   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
2538
2539   /* If the NK references an SK, delete it. */
2540   size_t sk_offs = le32toh (nk->sk);
2541   if (sk_offs != 0xffffffff) {
2542     sk_offs += 0x1000;
2543     if (delete_sk (h, sk_offs) == -1)
2544       return -1;
2545     nk->sk = htole32 (0xffffffff);
2546   }
2547
2548   /* If the NK references a classname, delete it. */
2549   size_t cl_offs = le32toh (nk->classname);
2550   if (cl_offs != 0xffffffff) {
2551     cl_offs += 0x1000;
2552     mark_block_unused (h, cl_offs);
2553     nk->classname = htole32 (0xffffffff);
2554   }
2555
2556   /* Delete the node itself. */
2557   mark_block_unused (h, node);
2558
2559   return 0;
2560 }
2561
2562 int
2563 hivex_node_delete_child (hive_h *h, hive_node_h node)
2564 {
2565   if (!h->writable) {
2566     errno = EROFS;
2567     return -1;
2568   }
2569
2570   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
2571     errno = EINVAL;
2572     return -1;
2573   }
2574
2575   if (node == hivex_root (h)) {
2576     if (h->msglvl >= 2)
2577       fprintf (stderr, "hivex_node_delete_child: cannot delete root node\n");
2578     errno = EINVAL;
2579     return -1;
2580   }
2581
2582   hive_node_h parent = hivex_node_parent (h, node);
2583   if (parent == 0)
2584     return -1;
2585
2586   /* Delete node and all its children and values recursively. */
2587   static const struct hivex_visitor visitor = { .node_end = delete_node };
2588   if (hivex_visit_node (h, node, &visitor, sizeof visitor, NULL, 0) == -1)
2589     return -1;
2590
2591   /* Delete the link from parent to child.  We need to find the lf/lh
2592    * record which contains the offset and remove the offset from that
2593    * record, then decrement the element count in that record, and
2594    * decrement the overall number of subkeys stored in the parent
2595    * node.
2596    */
2597   hive_node_h *unused;
2598   size_t *blocks;
2599   if (get_children (h, parent, &unused, &blocks, GET_CHILDREN_NO_CHECK_NK)== -1)
2600     return -1;
2601   free (unused);
2602
2603   size_t i, j;
2604   for (i = 0; blocks[i] != 0; ++i) {
2605     struct ntreg_hbin_block *block =
2606       (struct ntreg_hbin_block *) (h->addr + blocks[i]);
2607
2608     if (block->id[0] == 'l' && (block->id[1] == 'f' || block->id[1] == 'h')) {
2609       struct ntreg_lf_record *lf = (struct ntreg_lf_record *) block;
2610
2611       size_t nr_subkeys_in_lf = le16toh (lf->nr_keys);
2612
2613       for (j = 0; j < nr_subkeys_in_lf; ++j)
2614         if (le32toh (lf->keys[j].offset) + 0x1000 == node) {
2615           for (; j < nr_subkeys_in_lf - 1; ++j)
2616             memcpy (&lf->keys[j], &lf->keys[j+1], sizeof (lf->keys[j]));
2617           lf->nr_keys = htole16 (nr_subkeys_in_lf - 1);
2618           goto found;
2619         }
2620     }
2621   }
2622   if (h->msglvl >= 2)
2623     fprintf (stderr, "hivex_node_delete_child: could not find parent"
2624              " to child link\n");
2625   errno = ENOTSUP;
2626   return -1;
2627
2628  found:;
2629   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + parent);
2630   size_t nr_subkeys_in_nk = le32toh (nk->nr_subkeys);
2631   nk->nr_subkeys = htole32 (nr_subkeys_in_nk - 1);
2632
2633   if (h->msglvl >= 2)
2634     fprintf (stderr, "hivex_node_delete_child: updating nr_subkeys"
2635              " in parent 0x%zx to %zu\n", parent, nr_subkeys_in_nk);
2636
2637   return 0;
2638 }
2639
2640 int
2641 hivex_node_set_values (hive_h *h, hive_node_h node,
2642                        size_t nr_values, const hive_set_value *values,
2643                        int flags)
2644 {
2645   if (!h->writable) {
2646     errno = EROFS;
2647     return -1;
2648   }
2649
2650   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
2651     errno = EINVAL;
2652     return -1;
2653   }
2654
2655   /* Delete all existing values. */
2656   if (delete_values (h, node) == -1)
2657     return -1;
2658
2659   if (nr_values == 0)
2660     return 0;
2661
2662   /* Allocate value list node.  Value lists have no id field. */
2663   static const char nul_id[2] = { 0, 0 };
2664   size_t seg_len =
2665     sizeof (struct ntreg_value_list) + (nr_values - 1) * sizeof (uint32_t);
2666   size_t vallist_offs = allocate_block (h, seg_len, nul_id);
2667   if (vallist_offs == 0)
2668     return -1;
2669
2670   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
2671   nk->nr_values = htole32 (nr_values);
2672   nk->vallist = htole32 (vallist_offs - 0x1000);
2673
2674   struct ntreg_value_list *vallist =
2675     (struct ntreg_value_list *) (h->addr + vallist_offs);
2676
2677   size_t i;
2678   for (i = 0; i < nr_values; ++i) {
2679     /* Allocate vk record to store this (key, value) pair. */
2680     static const char vk_id[2] = { 'v', 'k' };
2681     seg_len = sizeof (struct ntreg_vk_record) + strlen (values[i].key);
2682     size_t vk_offs = allocate_block (h, seg_len, vk_id);
2683     if (vk_offs == 0)
2684       return -1;
2685
2686     /* Recalculate pointers that could have been invalidated by
2687      * previous call to allocate_block.
2688      */
2689     nk = (struct ntreg_nk_record *) (h->addr + node);
2690     vallist = (struct ntreg_value_list *) (h->addr + vallist_offs);
2691
2692     vallist->offset[i] = htole32 (vk_offs - 0x1000);
2693
2694     struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + vk_offs);
2695     size_t name_len = strlen (values[i].key);
2696     vk->name_len = htole16 (name_len);
2697     strcpy (vk->name, values[i].key);
2698     vk->data_type = htole32 (values[i].t);
2699     uint32_t len = values[i].len;
2700     if (len <= 4)               /* store it inline => set MSB flag */
2701       len |= 0x80000000;
2702     vk->data_len = htole32 (len);
2703     vk->flags = name_len == 0 ? 0 : 1;
2704
2705     if (values[i].len <= 4)     /* store it inline */
2706       memcpy (&vk->data_offset, values[i].value, values[i].len);
2707     else {
2708       size_t offs = allocate_block (h, values[i].len + 4, nul_id);
2709       if (offs == 0)
2710         return -1;
2711
2712       /* Recalculate pointers that could have been invalidated by
2713        * previous call to allocate_block.
2714        */
2715       nk = (struct ntreg_nk_record *) (h->addr + node);
2716       vallist = (struct ntreg_value_list *) (h->addr + vallist_offs);
2717       vk = (struct ntreg_vk_record *) (h->addr + vk_offs);
2718
2719       memcpy (h->addr + offs + 4, values[i].value, values[i].len);
2720       vk->data_offset = htole32 (offs - 0x1000);
2721     }
2722
2723     if (name_len * 2 > le32toh (nk->max_vk_name_len))
2724       /* * 2 for UTF16-LE "reencoding" */
2725       nk->max_vk_name_len = htole32 (name_len * 2);
2726     if (values[i].len > le32toh (nk->max_vk_data_len))
2727       nk->max_vk_data_len = htole32 (values[i].len);
2728   }
2729
2730   return 0;
2731 }
2732
2733 int
2734 hivex_node_set_value (hive_h *h, hive_node_h node,
2735                       const hive_set_value *val, int flags)
2736 {
2737   hive_value_h *prev_values = hivex_node_values (h, node);
2738   if (prev_values == NULL)
2739     return -1;
2740
2741   int retval = -1;
2742
2743   size_t nr_values = 0;
2744   for (hive_value_h *itr = prev_values; *itr != 0; ++itr)
2745     ++nr_values;
2746
2747   hive_set_value *values = malloc ((nr_values + 1) * (sizeof (hive_set_value)));
2748   if (values == NULL)
2749     goto leave_prev_values;
2750
2751   int alloc_ct = 0;
2752   int idx_of_val = -1;
2753   hive_value_h *prev_val;
2754   for (prev_val = prev_values; *prev_val != 0; ++prev_val) {
2755     size_t len;
2756     hive_type t;
2757
2758     hive_set_value *value = &values[prev_val - prev_values];
2759
2760     char *valval = hivex_value_value (h, *prev_val, &t, &len);
2761     if (valval == NULL) goto leave_partial;
2762
2763     ++alloc_ct;
2764     value->value = valval;
2765     value->t = t;
2766     value->len = len;
2767
2768     char *valkey = hivex_value_key (h, *prev_val);
2769     if (valkey == NULL) goto leave_partial;
2770
2771     ++alloc_ct;
2772     value->key = valkey;
2773
2774     if (STRCASEEQ (valkey, val->key))
2775       idx_of_val = prev_val - prev_values;
2776   }
2777
2778   if (idx_of_val > -1) {
2779     free (values[idx_of_val].key);
2780     free (values[idx_of_val].value);
2781   } else {
2782     idx_of_val = nr_values;
2783     ++nr_values;
2784   }
2785
2786   hive_set_value *value = &values[idx_of_val];
2787   *value = (hive_set_value){
2788     .key = strdup (val->key),
2789     .value = malloc (val->len),
2790     .len = val->len,
2791     .t = val->t
2792   };
2793
2794   if (value->key == NULL || value->value == NULL) goto leave_partial;
2795   memcpy (value->value, val->value, val->len);
2796
2797   retval = hivex_node_set_values (h, node, nr_values, values, 0);
2798
2799  leave_partial:
2800   for (int i = 0; i < alloc_ct; i += 2) {
2801     free (values[i / 2].value);
2802     if (i + 1 < alloc_ct && values[i / 2].key != NULL)
2803       free (values[i / 2].key);
2804   }
2805   free (values);
2806
2807  leave_prev_values:
2808   free (prev_values);
2809   return retval;
2810 }