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