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