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