hivex: allocate_block should update valid block bitmap.
[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 (0x%zx)\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         if (h->msglvl >= 2)
817           fprintf (stderr, "get_children: returning ENOTSUP because ri-record offset does not point to lf/lh (0x%zx)\n",
818                    offset);
819         errno = ENOTSUP;
820         goto error;
821       }
822
823       if (add_to_offset_list (&blocks, offset) == -1)
824         goto error;
825
826       struct ntreg_lf_record *lf =
827         (struct ntreg_lf_record *) (h->addr + offset);
828
829       count += le16toh (lf->nr_keys);
830     }
831
832     if (h->msglvl >= 2)
833       fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu, counted = %zu\n",
834                nr_subkeys_in_nk, count);
835
836     if (nr_subkeys_in_nk != count) {
837       errno = ENOTSUP;
838       goto error;
839     }
840
841     /* Copy list of children.  Note nr_subkeys_in_nk is limited to
842      * something reasonable above.
843      */
844     for (i = 0; i < nr_offsets; ++i) {
845       hive_node_h offset = le32toh (ri->offset[i]);
846       offset += 0x1000;
847       if (!IS_VALID_BLOCK (h, offset)) {
848         if (h->msglvl >= 2)
849           fprintf (stderr, "hivex_node_children: returning EFAULT because ri-offset is not a valid block (0x%zx)\n",
850                    offset);
851         errno = EFAULT;
852         goto error;
853       }
854       if (!BLOCK_ID_EQ (h, offset, "lf") && !BLOCK_ID_EQ (h, offset, "lh")) {
855         if (h->msglvl >= 2)
856           fprintf (stderr, "get_children: returning ENOTSUP because ri-record offset does not point to lf/lh (0x%zx)\n",
857                    offset);
858         errno = ENOTSUP;
859         goto error;
860       }
861
862       struct ntreg_lf_record *lf =
863         (struct ntreg_lf_record *) (h->addr + offset);
864
865       size_t j;
866       for (j = 0; j < le16toh (lf->nr_keys); ++j) {
867         hive_node_h subkey = le32toh (lf->keys[j].offset);
868         subkey += 0x1000;
869         if (!(flags & GET_CHILDREN_NO_CHECK_NK)) {
870           if (!IS_VALID_BLOCK (h, subkey)) {
871             if (h->msglvl >= 2)
872               fprintf (stderr, "hivex_node_children: returning EFAULT because indirect subkey is not a valid block (0x%zx)\n",
873                        subkey);
874             errno = EFAULT;
875             goto error;
876           }
877         }
878         if (add_to_offset_list (&children, subkey) == -1)
879           goto error;
880       }
881     }
882     goto ok;
883   }
884   /* else not supported, set errno and fall through */
885   if (h->msglvl >= 2)
886     fprintf (stderr, "get_children: returning ENOTSUP because subkey block is not lf/lh/ri (0x%zx, %d, %d)\n",
887              subkey_lf, block->id[0], block->id[1]);
888   errno = ENOTSUP;
889  error:
890   free_offset_list (&children);
891   free_offset_list (&blocks);
892   return -1;
893
894  ok:
895   *children_ret = return_offset_list (&children);
896   *blocks_ret = return_offset_list (&blocks);
897   if (!*children_ret || !*blocks_ret)
898     goto error;
899   return 0;
900 }
901
902 hive_node_h *
903 hivex_node_children (hive_h *h, hive_node_h node)
904 {
905   hive_node_h *children;
906   size_t *blocks;
907
908   if (get_children (h, node, &children, &blocks, 0) == -1)
909     return NULL;
910
911   free (blocks);
912   return children;
913 }
914
915 /* Very inefficient, but at least having a separate API call
916  * allows us to make it more efficient in future.
917  */
918 hive_node_h
919 hivex_node_get_child (hive_h *h, hive_node_h node, const char *nname)
920 {
921   hive_node_h *children = NULL;
922   char *name = NULL;
923   hive_node_h ret = 0;
924
925   children = hivex_node_children (h, node);
926   if (!children) goto error;
927
928   size_t i;
929   for (i = 0; children[i] != 0; ++i) {
930     name = hivex_node_name (h, children[i]);
931     if (!name) goto error;
932     if (STRCASEEQ (name, nname)) {
933       ret = children[i];
934       break;
935     }
936     free (name); name = NULL;
937   }
938
939  error:
940   free (children);
941   free (name);
942   return ret;
943 }
944
945 hive_node_h
946 hivex_node_parent (hive_h *h, hive_node_h node)
947 {
948   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
949     errno = EINVAL;
950     return 0;
951   }
952
953   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
954
955   hive_node_h ret = le32toh (nk->parent);
956   ret += 0x1000;
957   if (!IS_VALID_BLOCK (h, ret)) {
958     if (h->msglvl >= 2)
959       fprintf (stderr, "hivex_node_parent: returning EFAULT because parent is not a valid block (0x%zx)\n",
960               ret);
961     errno = EFAULT;
962     return 0;
963   }
964   return ret;
965 }
966
967 static int
968 get_values (hive_h *h, hive_node_h node,
969             hive_value_h **values_ret, size_t **blocks_ret)
970 {
971   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
972     errno = EINVAL;
973     return -1;
974   }
975
976   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
977
978   size_t nr_values = le32toh (nk->nr_values);
979
980   if (h->msglvl >= 2)
981     fprintf (stderr, "hivex_node_values: nr_values = %zu\n", nr_values);
982
983   INIT_OFFSET_LIST (values);
984   INIT_OFFSET_LIST (blocks);
985
986   /* Deal with the common "no values" case quickly. */
987   if (nr_values == 0)
988     goto ok;
989
990   /* Arbitrarily limit the number of values we will ever deal with. */
991   if (nr_values > 100000) {
992     errno = ERANGE;
993     goto error;
994   }
995
996   /* Preallocate space for the values. */
997   if (grow_offset_list (&values, nr_values) == -1)
998     goto error;
999
1000   /* Get the value list and check it looks reasonable. */
1001   size_t vlist_offset = le32toh (nk->vallist);
1002   vlist_offset += 0x1000;
1003   if (!IS_VALID_BLOCK (h, vlist_offset)) {
1004     if (h->msglvl >= 2)
1005       fprintf (stderr, "hivex_node_values: returning EFAULT because value list is not a valid block (0x%zx)\n",
1006                vlist_offset);
1007     errno = EFAULT;
1008     goto error;
1009   }
1010
1011   if (add_to_offset_list (&blocks, vlist_offset) == -1)
1012     goto error;
1013
1014   struct ntreg_value_list *vlist =
1015     (struct ntreg_value_list *) (h->addr + vlist_offset);
1016
1017   size_t len = block_len (h, vlist_offset, NULL);
1018   if (4 + nr_values * 4 > len) {
1019     if (h->msglvl >= 2)
1020       fprintf (stderr, "hivex_node_values: returning EFAULT because value list is too long (%zu, %zu)\n",
1021                nr_values, len);
1022     errno = EFAULT;
1023     goto error;
1024   }
1025
1026   size_t i;
1027   for (i = 0; i < nr_values; ++i) {
1028     hive_node_h value = vlist->offset[i];
1029     value += 0x1000;
1030     if (!IS_VALID_BLOCK (h, value)) {
1031       if (h->msglvl >= 2)
1032         fprintf (stderr, "hivex_node_values: returning EFAULT because value is not a valid block (0x%zx)\n",
1033                  value);
1034       errno = EFAULT;
1035       goto error;
1036     }
1037     if (add_to_offset_list (&values, value) == -1)
1038       goto error;
1039   }
1040
1041  ok:
1042   *values_ret = return_offset_list (&values);
1043   *blocks_ret = return_offset_list (&blocks);
1044   if (!*values_ret || !*blocks_ret)
1045     goto error;
1046   return 0;
1047
1048  error:
1049   free_offset_list (&values);
1050   free_offset_list (&blocks);
1051   return -1;
1052 }
1053
1054 hive_value_h *
1055 hivex_node_values (hive_h *h, hive_node_h node)
1056 {
1057   hive_value_h *values;
1058   size_t *blocks;
1059
1060   if (get_values (h, node, &values, &blocks) == -1)
1061     return NULL;
1062
1063   free (blocks);
1064   return values;
1065 }
1066
1067 /* Very inefficient, but at least having a separate API call
1068  * allows us to make it more efficient in future.
1069  */
1070 hive_value_h
1071 hivex_node_get_value (hive_h *h, hive_node_h node, const char *key)
1072 {
1073   hive_value_h *values = NULL;
1074   char *name = NULL;
1075   hive_value_h ret = 0;
1076
1077   values = hivex_node_values (h, node);
1078   if (!values) goto error;
1079
1080   size_t i;
1081   for (i = 0; values[i] != 0; ++i) {
1082     name = hivex_value_key (h, values[i]);
1083     if (!name) goto error;
1084     if (STRCASEEQ (name, key)) {
1085       ret = values[i];
1086       break;
1087     }
1088     free (name); name = NULL;
1089   }
1090
1091  error:
1092   free (values);
1093   free (name);
1094   return ret;
1095 }
1096
1097 char *
1098 hivex_value_key (hive_h *h, hive_value_h value)
1099 {
1100   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
1101     errno = EINVAL;
1102     return 0;
1103   }
1104
1105   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
1106
1107   /* AFAIK the key is always plain ASCII, so no conversion to UTF-8 is
1108    * necessary.  However we do need to nul-terminate the string.
1109    */
1110
1111   /* vk->name_len is unsigned, 16 bit, so this is safe ...  However
1112    * we have to make sure the length doesn't exceed the block length.
1113    */
1114   size_t len = le16toh (vk->name_len);
1115   size_t seg_len = block_len (h, value, NULL);
1116   if (sizeof (struct ntreg_vk_record) + len - 1 > seg_len) {
1117     if (h->msglvl >= 2)
1118       fprintf (stderr, "hivex_value_key: returning EFAULT because key length is too long (%zu, %zu)\n",
1119                len, seg_len);
1120     errno = EFAULT;
1121     return NULL;
1122   }
1123
1124   char *ret = malloc (len + 1);
1125   if (ret == NULL)
1126     return NULL;
1127   memcpy (ret, vk->name, len);
1128   ret[len] = '\0';
1129   return ret;
1130 }
1131
1132 int
1133 hivex_value_type (hive_h *h, hive_value_h value, hive_type *t, size_t *len)
1134 {
1135   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
1136     errno = EINVAL;
1137     return -1;
1138   }
1139
1140   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
1141
1142   if (t)
1143     *t = le32toh (vk->data_type);
1144
1145   if (len) {
1146     *len = le32toh (vk->data_len);
1147     if (*len == 0x80000000) {   /* special case */
1148       *len = 4;
1149       if (t) *t = hive_t_dword;
1150     }
1151     *len &= 0x7fffffff;
1152   }
1153
1154   return 0;
1155 }
1156
1157 char *
1158 hivex_value_value (hive_h *h, hive_value_h value,
1159                    hive_type *t_rtn, size_t *len_rtn)
1160 {
1161   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
1162     errno = EINVAL;
1163     return NULL;
1164   }
1165
1166   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
1167
1168   hive_type t;
1169   size_t len;
1170
1171   t = le32toh (vk->data_type);
1172
1173   len = le32toh (vk->data_len);
1174   if (len == 0x80000000) {      /* special case */
1175     len = 4;
1176     t = hive_t_dword;
1177   }
1178   len &= 0x7fffffff;
1179
1180   if (h->msglvl >= 2)
1181     fprintf (stderr, "hivex_value_value: value=0x%zx, t=%d, len=%zu\n",
1182              value, t, len);
1183
1184   if (t_rtn)
1185     *t_rtn = t;
1186   if (len_rtn)
1187     *len_rtn = len;
1188
1189   /* Arbitrarily limit the length that we will read. */
1190   if (len > 1000000) {
1191     errno = ERANGE;
1192     return NULL;
1193   }
1194
1195   char *ret = malloc (len);
1196   if (ret == NULL)
1197     return NULL;
1198
1199   /* If length is <= 4 it's always stored inline. */
1200   if (len <= 4) {
1201     memcpy (ret, (char *) &vk->data_offset, len);
1202     return ret;
1203   }
1204
1205   size_t data_offset = le32toh (vk->data_offset);
1206   data_offset += 0x1000;
1207   if (!IS_VALID_BLOCK (h, data_offset)) {
1208     if (h->msglvl >= 2)
1209       fprintf (stderr, "hivex_value_value: returning EFAULT because data offset is not a valid block (0x%zx)\n",
1210                data_offset);
1211     errno = EFAULT;
1212     free (ret);
1213     return NULL;
1214   }
1215
1216   /* Check that the declared size isn't larger than the block its in.
1217    *
1218    * XXX Some apparently valid registries are seen to have this,
1219    * so turn this into a warning and substitute the smaller length
1220    * instead.
1221    */
1222   size_t blen = block_len (h, data_offset, NULL);
1223   if (len > blen - 4 /* subtract 4 for block header */) {
1224     if (h->msglvl >= 2)
1225       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",
1226                data_offset, len, blen);
1227     len = blen - 4;
1228   }
1229
1230   char *data = h->addr + data_offset + 4;
1231   memcpy (ret, data, len);
1232   return ret;
1233 }
1234
1235 static char *
1236 windows_utf16_to_utf8 (/* const */ char *input, size_t len)
1237 {
1238   iconv_t ic = iconv_open ("UTF-8", "UTF-16");
1239   if (ic == (iconv_t) -1)
1240     return NULL;
1241
1242   /* iconv(3) has an insane interface ... */
1243
1244   /* Mostly UTF-8 will be smaller, so this is a good initial guess. */
1245   size_t outalloc = len;
1246
1247  again:;
1248   size_t inlen = len;
1249   size_t outlen = outalloc;
1250   char *out = malloc (outlen + 1);
1251   if (out == NULL) {
1252     int err = errno;
1253     iconv_close (ic);
1254     errno = err;
1255     return NULL;
1256   }
1257   char *inp = input;
1258   char *outp = out;
1259
1260   size_t r = iconv (ic, &inp, &inlen, &outp, &outlen);
1261   if (r == (size_t) -1) {
1262     if (errno == E2BIG) {
1263       size_t prev = outalloc;
1264       /* Try again with a larger output buffer. */
1265       free (out);
1266       outalloc *= 2;
1267       if (outalloc < prev)
1268         return NULL;
1269       goto again;
1270     }
1271     else {
1272       /* Else some conversion failure, eg. EILSEQ, EINVAL. */
1273       int err = errno;
1274       iconv_close (ic);
1275       free (out);
1276       errno = err;
1277       return NULL;
1278     }
1279   }
1280
1281   *outp = '\0';
1282   iconv_close (ic);
1283
1284   return out;
1285 }
1286
1287 char *
1288 hivex_value_string (hive_h *h, hive_value_h value)
1289 {
1290   hive_type t;
1291   size_t len;
1292   char *data = hivex_value_value (h, value, &t, &len);
1293
1294   if (data == NULL)
1295     return NULL;
1296
1297   if (t != hive_t_string && t != hive_t_expand_string && t != hive_t_link) {
1298     free (data);
1299     errno = EINVAL;
1300     return NULL;
1301   }
1302
1303   char *ret = windows_utf16_to_utf8 (data, len);
1304   free (data);
1305   if (ret == NULL)
1306     return NULL;
1307
1308   return ret;
1309 }
1310
1311 static void
1312 free_strings (char **argv)
1313 {
1314   if (argv) {
1315     size_t i;
1316
1317     for (i = 0; argv[i] != NULL; ++i)
1318       free (argv[i]);
1319     free (argv);
1320   }
1321 }
1322
1323 /* Get the length of a UTF-16 format string.  Handle the string as
1324  * pairs of bytes, looking for the first \0\0 pair.
1325  */
1326 static size_t
1327 utf16_string_len_in_bytes (const char *str)
1328 {
1329   size_t ret = 0;
1330
1331   while (str[0] || str[1]) {
1332     str += 2;
1333     ret += 2;
1334   }
1335
1336   return ret;
1337 }
1338
1339 /* http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx */
1340 char **
1341 hivex_value_multiple_strings (hive_h *h, hive_value_h value)
1342 {
1343   hive_type t;
1344   size_t len;
1345   char *data = hivex_value_value (h, value, &t, &len);
1346
1347   if (data == NULL)
1348     return NULL;
1349
1350   if (t != hive_t_multiple_strings) {
1351     free (data);
1352     errno = EINVAL;
1353     return NULL;
1354   }
1355
1356   size_t nr_strings = 0;
1357   char **ret = malloc ((1 + nr_strings) * sizeof (char *));
1358   if (ret == NULL) {
1359     free (data);
1360     return NULL;
1361   }
1362   ret[0] = NULL;
1363
1364   char *p = data;
1365   size_t plen;
1366
1367   while (p < data + len && (plen = utf16_string_len_in_bytes (p)) > 0) {
1368     nr_strings++;
1369     char **ret2 = realloc (ret, (1 + nr_strings) * sizeof (char *));
1370     if (ret2 == NULL) {
1371       free_strings (ret);
1372       free (data);
1373       return NULL;
1374     }
1375     ret = ret2;
1376
1377     ret[nr_strings-1] = windows_utf16_to_utf8 (p, plen);
1378     ret[nr_strings] = NULL;
1379     if (ret[nr_strings-1] == NULL) {
1380       free_strings (ret);
1381       free (data);
1382       return NULL;
1383     }
1384
1385     p += plen + 2 /* skip over UTF-16 \0\0 at the end of this string */;
1386   }
1387
1388   free (data);
1389   return ret;
1390 }
1391
1392 int32_t
1393 hivex_value_dword (hive_h *h, hive_value_h value)
1394 {
1395   hive_type t;
1396   size_t len;
1397   char *data = hivex_value_value (h, value, &t, &len);
1398
1399   if (data == NULL)
1400     return -1;
1401
1402   if ((t != hive_t_dword && t != hive_t_dword_be) || len != 4) {
1403     free (data);
1404     errno = EINVAL;
1405     return -1;
1406   }
1407
1408   int32_t ret = *(int32_t*)data;
1409   free (data);
1410   if (t == hive_t_dword)        /* little endian */
1411     ret = le32toh (ret);
1412   else
1413     ret = be32toh (ret);
1414
1415   return ret;
1416 }
1417
1418 int64_t
1419 hivex_value_qword (hive_h *h, hive_value_h value)
1420 {
1421   hive_type t;
1422   size_t len;
1423   char *data = hivex_value_value (h, value, &t, &len);
1424
1425   if (data == NULL)
1426     return -1;
1427
1428   if (t != hive_t_qword || len != 8) {
1429     free (data);
1430     errno = EINVAL;
1431     return -1;
1432   }
1433
1434   int64_t ret = *(int64_t*)data;
1435   free (data);
1436   ret = le64toh (ret);          /* always little endian */
1437
1438   return ret;
1439 }
1440
1441 /*----------------------------------------------------------------------
1442  * Visiting.
1443  */
1444
1445 int
1446 hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len,
1447              void *opaque, int flags)
1448 {
1449   return hivex_visit_node (h, hivex_root (h), visitor, len, opaque, flags);
1450 }
1451
1452 static int hivex__visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *vtor, char *unvisited, void *opaque, int flags);
1453
1454 int
1455 hivex_visit_node (hive_h *h, hive_node_h node,
1456                   const struct hivex_visitor *visitor, size_t len, void *opaque,
1457                   int flags)
1458 {
1459   struct hivex_visitor vtor;
1460   memset (&vtor, 0, sizeof vtor);
1461
1462   /* Note that len might be larger *or smaller* than the expected size. */
1463   size_t copysize = len <= sizeof vtor ? len : sizeof vtor;
1464   memcpy (&vtor, visitor, copysize);
1465
1466   /* This bitmap records unvisited nodes, so we don't loop if the
1467    * registry contains cycles.
1468    */
1469   char *unvisited = malloc (1 + h->size / 32);
1470   if (unvisited == NULL)
1471     return -1;
1472   memcpy (unvisited, h->bitmap, 1 + h->size / 32);
1473
1474   int r = hivex__visit_node (h, node, &vtor, unvisited, opaque, flags);
1475   free (unvisited);
1476   return r;
1477 }
1478
1479 static int
1480 hivex__visit_node (hive_h *h, hive_node_h node,
1481                    const struct hivex_visitor *vtor, char *unvisited,
1482                    void *opaque, int flags)
1483 {
1484   int skip_bad = flags & HIVEX_VISIT_SKIP_BAD;
1485   char *name = NULL;
1486   hive_value_h *values = NULL;
1487   hive_node_h *children = NULL;
1488   char *key = NULL;
1489   char *str = NULL;
1490   char **strs = NULL;
1491   int i;
1492
1493   /* Return -1 on all callback errors.  However on internal errors,
1494    * check if skip_bad is set and suppress those errors if so.
1495    */
1496   int ret = -1;
1497
1498   if (!BITMAP_TST (unvisited, node)) {
1499     if (h->msglvl >= 2)
1500       fprintf (stderr, "hivex__visit_node: contains cycle: visited node 0x%zx already\n",
1501                node);
1502
1503     errno = ELOOP;
1504     return skip_bad ? 0 : -1;
1505   }
1506   BITMAP_CLR (unvisited, node);
1507
1508   name = hivex_node_name (h, node);
1509   if (!name) return skip_bad ? 0 : -1;
1510   if (vtor->node_start && vtor->node_start (h, opaque, node, name) == -1)
1511     goto error;
1512
1513   values = hivex_node_values (h, node);
1514   if (!values) {
1515     ret = skip_bad ? 0 : -1;
1516     goto error;
1517   }
1518
1519   for (i = 0; values[i] != 0; ++i) {
1520     hive_type t;
1521     size_t len;
1522
1523     if (hivex_value_type (h, values[i], &t, &len) == -1) {
1524       ret = skip_bad ? 0 : -1;
1525       goto error;
1526     }
1527
1528     key = hivex_value_key (h, values[i]);
1529     if (key == NULL) {
1530       ret = skip_bad ? 0 : -1;
1531       goto error;
1532     }
1533
1534     if (vtor->value_any) {
1535       str = hivex_value_value (h, values[i], &t, &len);
1536       if (str == NULL) {
1537         ret = skip_bad ? 0 : -1;
1538         goto error;
1539       }
1540       if (vtor->value_any (h, opaque, node, values[i], t, len, key, str) == -1)
1541         goto error;
1542       free (str); str = NULL;
1543     }
1544     else {
1545       switch (t) {
1546       case hive_t_none:
1547         str = hivex_value_value (h, values[i], &t, &len);
1548         if (str == NULL) {
1549           ret = skip_bad ? 0 : -1;
1550           goto error;
1551         }
1552         if (t != hive_t_none) {
1553           ret = skip_bad ? 0 : -1;
1554           goto error;
1555         }
1556         if (vtor->value_none &&
1557             vtor->value_none (h, opaque, node, values[i], t, len, key, str) == -1)
1558           goto error;
1559         free (str); str = NULL;
1560         break;
1561
1562       case hive_t_string:
1563       case hive_t_expand_string:
1564       case hive_t_link:
1565         str = hivex_value_string (h, values[i]);
1566         if (str == NULL) {
1567           if (errno != EILSEQ && errno != EINVAL) {
1568             ret = skip_bad ? 0 : -1;
1569             goto error;
1570           }
1571           if (vtor->value_string_invalid_utf16) {
1572             str = hivex_value_value (h, values[i], &t, &len);
1573             if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], t, len, key, str) == -1)
1574               goto error;
1575             free (str); str = NULL;
1576           }
1577           break;
1578         }
1579         if (vtor->value_string &&
1580             vtor->value_string (h, opaque, node, values[i], t, len, key, str) == -1)
1581           goto error;
1582         free (str); str = NULL;
1583         break;
1584
1585       case hive_t_dword:
1586       case hive_t_dword_be: {
1587         int32_t i32 = hivex_value_dword (h, values[i]);
1588         if (vtor->value_dword &&
1589             vtor->value_dword (h, opaque, node, values[i], t, len, key, i32) == -1)
1590           goto error;
1591         break;
1592       }
1593
1594       case hive_t_qword: {
1595         int64_t i64 = hivex_value_qword (h, values[i]);
1596         if (vtor->value_qword &&
1597             vtor->value_qword (h, opaque, node, values[i], t, len, key, i64) == -1)
1598           goto error;
1599         break;
1600       }
1601
1602       case hive_t_binary:
1603         str = hivex_value_value (h, values[i], &t, &len);
1604         if (str == NULL) {
1605           ret = skip_bad ? 0 : -1;
1606           goto error;
1607         }
1608         if (t != hive_t_binary) {
1609           ret = skip_bad ? 0 : -1;
1610           goto error;
1611         }
1612         if (vtor->value_binary &&
1613             vtor->value_binary (h, opaque, node, values[i], t, len, key, str) == -1)
1614           goto error;
1615         free (str); str = NULL;
1616         break;
1617
1618       case hive_t_multiple_strings:
1619         strs = hivex_value_multiple_strings (h, values[i]);
1620         if (strs == NULL) {
1621           if (errno != EILSEQ && errno != EINVAL) {
1622             ret = skip_bad ? 0 : -1;
1623             goto error;
1624           }
1625           if (vtor->value_string_invalid_utf16) {
1626             str = hivex_value_value (h, values[i], &t, &len);
1627             if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], t, len, key, str) == -1)
1628               goto error;
1629             free (str); str = NULL;
1630           }
1631           break;
1632         }
1633         if (vtor->value_multiple_strings &&
1634             vtor->value_multiple_strings (h, opaque, node, values[i], t, len, key, strs) == -1)
1635           goto error;
1636         free_strings (strs); strs = NULL;
1637         break;
1638
1639       case hive_t_resource_list:
1640       case hive_t_full_resource_description:
1641       case hive_t_resource_requirements_list:
1642       default:
1643         str = hivex_value_value (h, values[i], &t, &len);
1644         if (str == NULL) {
1645           ret = skip_bad ? 0 : -1;
1646           goto error;
1647         }
1648         if (vtor->value_other &&
1649             vtor->value_other (h, opaque, node, values[i], t, len, key, str) == -1)
1650           goto error;
1651         free (str); str = NULL;
1652         break;
1653       }
1654     }
1655
1656     free (key); key = NULL;
1657   }
1658
1659   children = hivex_node_children (h, node);
1660   if (children == NULL) {
1661     ret = skip_bad ? 0 : -1;
1662     goto error;
1663   }
1664
1665   for (i = 0; children[i] != 0; ++i) {
1666     if (h->msglvl >= 2)
1667       fprintf (stderr, "hivex__visit_node: %s: visiting subkey %d (0x%zx)\n",
1668                name, i, children[i]);
1669
1670     if (hivex__visit_node (h, children[i], vtor, unvisited, opaque, flags) == -1)
1671       goto error;
1672   }
1673
1674   if (vtor->node_end && vtor->node_end (h, opaque, node, name) == -1)
1675     goto error;
1676
1677   ret = 0;
1678
1679  error:
1680   free (name);
1681   free (values);
1682   free (children);
1683   free (key);
1684   free (str);
1685   free_strings (strs);
1686   return ret;
1687 }
1688
1689 /*----------------------------------------------------------------------
1690  * Writing.
1691  */
1692
1693 /* Allocate an hbin (page), extending the malloc'd space if necessary,
1694  * and updating the hive handle fields (but NOT the hive disk header
1695  * -- the hive disk header is updated when we commit).  This function
1696  * also extends the bitmap if necessary.
1697  *
1698  * 'allocation_hint' is the size of the block allocation we would like
1699  * to make.  Normally registry blocks are very small (avg 50 bytes)
1700  * and are contained in standard-sized pages (4KB), but the registry
1701  * can support blocks which are larger than a standard page, in which
1702  * case it creates a page of 8KB, 12KB etc.
1703  *
1704  * Returns:
1705  * > 0 : offset of first usable byte of new page (after page header)
1706  * 0   : error (errno set)
1707  */
1708 static size_t
1709 allocate_page (hive_h *h, size_t allocation_hint)
1710 {
1711   /* In almost all cases this will be 1. */
1712   size_t nr_4k_pages =
1713     1 + (allocation_hint + sizeof (struct ntreg_hbin_page) - 1) / 4096;
1714   assert (nr_4k_pages >= 1);
1715
1716   /* 'extend' is the number of bytes to extend the file by.  Note that
1717    * hives found in the wild often contain slack between 'endpages'
1718    * and the actual end of the file, so we don't always need to make
1719    * the file larger.
1720    */
1721   ssize_t extend = h->endpages + nr_4k_pages * 4096 - h->size;
1722
1723   if (h->msglvl >= 2) {
1724     fprintf (stderr, "allocate_page: current endpages = 0x%zx, current size = 0x%zx\n",
1725              h->endpages, h->size);
1726     fprintf (stderr, "allocate_page: extending file by %zd bytes (<= 0 if no extension)\n",
1727              extend);
1728   }
1729
1730   if (extend > 0) {
1731     size_t oldsize = h->size;
1732     size_t newsize = h->size + extend;
1733     char *newaddr = realloc (h->addr, newsize);
1734     if (newaddr == NULL)
1735       return 0;
1736
1737     size_t oldbitmapsize = 1 + oldsize / 32;
1738     size_t newbitmapsize = 1 + newsize / 32;
1739     char *newbitmap = realloc (h->bitmap, newbitmapsize);
1740     if (newbitmap == NULL) {
1741       free (newaddr);
1742       return 0;
1743     }
1744
1745     h->addr = newaddr;
1746     h->size = newsize;
1747     h->bitmap = newbitmap;
1748
1749     memset (h->addr + oldsize, 0, newsize - oldsize);
1750     memset (h->bitmap + oldbitmapsize, 0, newbitmapsize - oldbitmapsize);
1751   }
1752
1753   size_t offset = h->endpages;
1754   h->endpages += nr_4k_pages * 4096;
1755
1756   if (h->msglvl >= 2)
1757     fprintf (stderr, "allocate_page: new endpages = 0x%zx, new size = 0x%zx\n",
1758              h->endpages, h->size);
1759
1760   /* Write the hbin header. */
1761   struct ntreg_hbin_page *page =
1762     (struct ntreg_hbin_page *) (h->addr + offset);
1763   page->magic[0] = 'h';
1764   page->magic[1] = 'b';
1765   page->magic[2] = 'i';
1766   page->magic[3] = 'n';
1767   page->offset_first = htole32 (offset - 0x1000);
1768   page->page_size = htole32 (nr_4k_pages * 4096);
1769   memset (page->unknown, 0, sizeof (page->unknown));
1770
1771   if (h->msglvl >= 2)
1772     fprintf (stderr, "allocate_page: new page at 0x%zx\n", offset);
1773
1774   /* Offset of first usable byte after the header. */
1775   return offset + sizeof (struct ntreg_hbin_page);
1776 }
1777
1778 /* Allocate a single block, first allocating an hbin (page) at the end
1779  * of the current file if necessary.  NB. To keep the implementation
1780  * simple and more likely to be correct, we do not reuse existing free
1781  * blocks.
1782  *
1783  * seg_len is the size of the block (this INCLUDES the block header).
1784  * The header of the block is initialized to -seg_len (negative to
1785  * indicate used).  id[2] is the block ID (type), eg. "nk" for nk-
1786  * record.  The block bitmap is updated to show this block as valid.
1787  * The rest of the contents of the block will be zero.
1788  *
1789  * Returns:
1790  * > 0 : offset of new block
1791  * 0   : error (errno set)
1792  */
1793 static size_t
1794 allocate_block (hive_h *h, size_t seg_len, const char id[2])
1795 {
1796   if (!h->writable) {
1797     errno = EROFS;
1798     return 0;
1799   }
1800
1801   if (seg_len < 4) {
1802     /* The caller probably forgot to include the header.  Note that
1803      * value lists have no ID field, so seg_len == 4 would be possible
1804      * for them, albeit unusual.
1805      */
1806     if (h->msglvl >= 2)
1807       fprintf (stderr, "allocate_block: refusing too small allocation (%zu), returning ERANGE\n",
1808                seg_len);
1809     errno = ERANGE;
1810     return 0;
1811   }
1812
1813   /* Refuse really large allocations. */
1814   if (seg_len > 1000000) {
1815     if (h->msglvl >= 2)
1816       fprintf (stderr, "allocate_block: refusing large allocation (%zu), returning ERANGE\n",
1817                seg_len);
1818     errno = ERANGE;
1819     return 0;
1820   }
1821
1822   /* Round up allocation to multiple of 8 bytes.  All blocks must be
1823    * on an 8 byte boundary.
1824    */
1825   seg_len = (seg_len + 7) & ~7;
1826
1827   /* Allocate a new page if necessary. */
1828   if (h->endblocks == 0 || h->endblocks + seg_len > h->endpages) {
1829     size_t newendblocks = allocate_page (h, seg_len);
1830     if (newendblocks == 0)
1831       return 0;
1832     h->endblocks = newendblocks;
1833   }
1834
1835   size_t offset = h->endblocks;
1836
1837   if (h->msglvl >= 2)
1838     fprintf (stderr, "allocate_block: new block at 0x%zx, size %zu\n",
1839              offset, seg_len);
1840
1841   struct ntreg_hbin_block *blockhdr =
1842     (struct ntreg_hbin_block *) (h->addr + offset);
1843
1844   blockhdr->seg_len = htole32 (- (int32_t) seg_len);
1845   if (id[0] && id[1] && seg_len >= 6) {
1846     blockhdr->id[0] = id[0];
1847     blockhdr->id[1] = id[1];
1848   }
1849
1850   BITMAP_SET (h->bitmap, offset);
1851
1852   h->endblocks += seg_len;
1853
1854   /* If there is space after the last block in the last page, then we
1855    * have to put a dummy free block header here to mark the rest of
1856    * the page as free.
1857    */
1858   ssize_t rem = h->endpages - h->endblocks;
1859   if (rem > 0) {
1860     if (h->msglvl >= 2)
1861       fprintf (stderr, "allocate_block: marking remainder of page free starting at 0x%zx, size %zd\n",
1862                h->endblocks, rem);
1863
1864     assert (rem >= 4);
1865
1866     blockhdr = (struct ntreg_hbin_block *) (h->addr + h->endblocks);
1867     blockhdr->seg_len = htole32 ((int32_t) rem);
1868   }
1869
1870   return offset;
1871 }
1872
1873 /* 'offset' must point to a valid, used block.  This function marks
1874  * the block unused (by updating the seg_len field) and invalidates
1875  * the bitmap.  It does NOT do this recursively, so to avoid creating
1876  * unreachable used blocks, callers may have to recurse over the hive
1877  * structures.  Also callers must ensure there are no references to
1878  * this block from other parts of the hive.
1879  */
1880 static void
1881 mark_block_unused (hive_h *h, size_t offset)
1882 {
1883   assert (h->writable);
1884   assert (IS_VALID_BLOCK (h, offset));
1885
1886   if (h->msglvl >= 2)
1887     fprintf (stderr, "mark_block_unused: marking 0x%zx unused\n", offset);
1888
1889   struct ntreg_hbin_block *blockhdr =
1890     (struct ntreg_hbin_block *) (h->addr + offset);
1891
1892   size_t seg_len = block_len (h, offset, NULL);
1893   blockhdr->seg_len = htole32 (seg_len);
1894
1895   BITMAP_CLR (h->bitmap, offset);
1896 }
1897
1898 /* Delete all existing values at this node. */
1899 static int
1900 delete_values (hive_h *h, hive_node_h node)
1901 {
1902   assert (h->writable);
1903
1904   hive_value_h *values;
1905   size_t *blocks;
1906   if (get_values (h, node, &values, &blocks) == -1)
1907     return -1;
1908
1909   size_t i;
1910   for (i = 0; blocks[i] != 0; ++i)
1911     mark_block_unused (h, blocks[i]);
1912
1913   free (blocks);
1914
1915   for (i = 0; values[i] != 0; ++i) {
1916     struct ntreg_vk_record *vk =
1917       (struct ntreg_vk_record *) (h->addr + values[i]);
1918
1919     size_t len;
1920     len = le32toh (vk->data_len);
1921     if (len == 0x80000000)      /* special case */
1922       len = 4;
1923     len &= 0x7fffffff;
1924
1925     if (len > 4) {              /* non-inline, so remove data block */
1926       size_t data_offset = le32toh (vk->data_offset);
1927       data_offset += 0x1000;
1928       mark_block_unused (h, data_offset);
1929     }
1930
1931     /* remove vk record */
1932     mark_block_unused (h, values[i]);
1933   }
1934
1935   free (values);
1936
1937   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
1938   nk->nr_values = htole32 (0);
1939   nk->vallist = htole32 (0xffffffff);
1940
1941   return 0;
1942 }
1943
1944 int
1945 hivex_commit (hive_h *h, const char *filename, int flags)
1946 {
1947   if (flags != 0) {
1948     errno = EINVAL;
1949     return -1;
1950   }
1951
1952   if (!h->writable) {
1953     errno = EROFS;
1954     return -1;
1955   }
1956
1957   filename = filename ? : h->filename;
1958   int fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666);
1959   if (fd == -1)
1960     return -1;
1961
1962   /* Update the header fields. */
1963   uint32_t sequence = le32toh (h->hdr->sequence1);
1964   sequence++;
1965   h->hdr->sequence1 = htole32 (sequence);
1966   h->hdr->sequence2 = htole32 (sequence);
1967   /* XXX Ought to update h->hdr->last_modified. */
1968   h->hdr->blocks = htole32 (h->endpages - 0x1000);
1969
1970   /* Recompute header checksum. */
1971   uint32_t sum = header_checksum (h);
1972   h->hdr->csum = htole32 (sum);
1973
1974   if (h->msglvl >= 2)
1975     fprintf (stderr, "hivex_commit: new header checksum: 0x%x\n", sum);
1976
1977   if (full_write (fd, h->addr, h->size) != h->size) {
1978     int err = errno;
1979     close (fd);
1980     errno = err;
1981     return -1;
1982   }
1983
1984   if (close (fd) == -1)
1985     return -1;
1986
1987   return 0;
1988 }
1989
1990 #if 0
1991 hive_node_h
1992 hivex_node_add_child (hive_h *h, hive_node_h parent, const char *name)
1993 {
1994   if (!h->writable) {
1995     errno = EROFS;
1996     return 0;
1997   }
1998
1999   if (!IS_VALID_BLOCK (h, parent) || !BLOCK_ID_EQ (h, parent, "nk")) {
2000     errno = EINVAL;
2001     return -1;
2002   }
2003
2004   if (name == NULL) {
2005     errno = EINVAL;
2006     return -1;
2007   }
2008
2009
2010
2011
2012
2013
2014 }
2015 #endif
2016
2017 /* Decrement the refcount of an sk-record, and if it reaches zero,
2018  * unlink it from the chain and delete it.
2019  */
2020 static int
2021 delete_sk (hive_h *h, size_t sk_offset)
2022 {
2023   if (!IS_VALID_BLOCK (h, sk_offset) || !BLOCK_ID_EQ (h, sk_offset, "sk")) {
2024     if (h->msglvl >= 2)
2025       fprintf (stderr, "delete_sk: not an sk record: 0x%zx\n", sk_offset);
2026     errno = EFAULT;
2027     return -1;
2028   }
2029
2030   struct ntreg_sk_record *sk = (struct ntreg_sk_record *) (h->addr + sk_offset);
2031
2032   if (sk->refcount == 0) {
2033     if (h->msglvl >= 2)
2034       fprintf (stderr, "delete_sk: sk record already has refcount 0: 0x%zx\n",
2035                sk_offset);
2036     errno = EINVAL;
2037     return -1;
2038   }
2039
2040   sk->refcount--;
2041
2042   if (sk->refcount == 0) {
2043     size_t sk_prev_offset = sk->sk_prev;
2044     sk_prev_offset += 0x1000;
2045
2046     size_t sk_next_offset = sk->sk_next;
2047     sk_next_offset += 0x1000;
2048
2049     /* Update sk_prev/sk_next SKs, unless they both point back to this
2050      * cell in which case we are deleting the last SK.
2051      */
2052     if (sk_prev_offset != sk_offset && sk_next_offset != sk_offset) {
2053       struct ntreg_sk_record *sk_prev =
2054         (struct ntreg_sk_record *) (h->addr + sk_prev_offset);
2055       struct ntreg_sk_record *sk_next =
2056         (struct ntreg_sk_record *) (h->addr + sk_next_offset);
2057
2058       sk_prev->sk_next = htole32 (sk_next_offset - 0x1000);
2059       sk_next->sk_prev = htole32 (sk_prev_offset - 0x1000);
2060     }
2061
2062     /* Refcount is zero so really delete this block. */
2063     mark_block_unused (h, sk_offset);
2064   }
2065
2066   return 0;
2067 }
2068
2069 /* Callback from hivex_node_delete_child which is called to delete a
2070  * node AFTER its subnodes have been visited.  The subnodes have been
2071  * deleted but we still have to delete any lf/lh/li/ri records and the
2072  * value list block and values, followed by deleting the node itself.
2073  */
2074 static int
2075 delete_node (hive_h *h, void *opaque, hive_node_h node, const char *name)
2076 {
2077   /* Get the intermediate blocks.  The subkeys have already been
2078    * deleted by this point, so tell get_children() not to check for
2079    * validity of the nk-records.
2080    */
2081   hive_node_h *unused;
2082   size_t *blocks;
2083   if (get_children (h, node, &unused, &blocks, GET_CHILDREN_NO_CHECK_NK) == -1)
2084     return -1;
2085   free (unused);
2086
2087   /* We don't care what's in these intermediate blocks, so we can just
2088    * delete them unconditionally.
2089    */
2090   size_t i;
2091   for (i = 0; blocks[i] != 0; ++i)
2092     mark_block_unused (h, blocks[i]);
2093
2094   free (blocks);
2095
2096   /* Delete the values in the node. */
2097   if (delete_values (h, node) == -1)
2098     return -1;
2099
2100   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
2101
2102   /* If the NK references an SK, delete it. */
2103   size_t sk_offs = le32toh (nk->sk);
2104   if (sk_offs != 0xffffffff) {
2105     sk_offs += 0x1000;
2106     if (delete_sk (h, sk_offs) == -1)
2107       return -1;
2108     nk->sk = htole32 (0xffffffff);
2109   }
2110
2111   /* If the NK references a classname, delete it. */
2112   size_t cl_offs = le32toh (nk->classname);
2113   if (cl_offs != 0xffffffff) {
2114     cl_offs += 0x1000;
2115     mark_block_unused (h, cl_offs);
2116     nk->classname = htole32 (0xffffffff);
2117   }
2118
2119   /* Delete the node itself. */
2120   mark_block_unused (h, node);
2121
2122   return 0;
2123 }
2124
2125 int
2126 hivex_node_delete_child (hive_h *h, hive_node_h node)
2127 {
2128   if (!h->writable) {
2129     errno = EROFS;
2130     return -1;
2131   }
2132
2133   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
2134     errno = EINVAL;
2135     return -1;
2136   }
2137
2138   if (node == hivex_root (h)) {
2139     if (h->msglvl >= 2)
2140       fprintf (stderr, "hivex_node_delete_child: cannot delete root node\n");
2141     errno = EINVAL;
2142     return -1;
2143   }
2144
2145   hive_node_h parent = hivex_node_parent (h, node);
2146   if (parent == 0)
2147     return -1;
2148
2149   /* Delete node and all its children and values recursively. */
2150   static const struct hivex_visitor visitor = { .node_end = delete_node };
2151   if (hivex_visit_node (h, node, &visitor, sizeof visitor, NULL, 0) == -1)
2152     return -1;
2153
2154   /* Delete the link from parent to child.  We need to find the lf/lh
2155    * record which contains the offset and remove the offset from that
2156    * record, then decrement the element count in that record, and
2157    * decrement the overall number of subkeys stored in the parent
2158    * node.
2159    */
2160   hive_node_h *unused;
2161   size_t *blocks;
2162   if (get_children (h, parent, &unused, &blocks, GET_CHILDREN_NO_CHECK_NK)== -1)
2163     return -1;
2164   free (unused);
2165
2166   size_t i, j;
2167   for (i = 0; blocks[i] != 0; ++i) {
2168     struct ntreg_hbin_block *block =
2169       (struct ntreg_hbin_block *) (h->addr + blocks[i]);
2170
2171     if (block->id[0] == 'l' && (block->id[1] == 'f' || block->id[1] == 'h')) {
2172       struct ntreg_lf_record *lf = (struct ntreg_lf_record *) block;
2173
2174       size_t nr_subkeys_in_lf = le16toh (lf->nr_keys);
2175
2176       for (j = 0; j < nr_subkeys_in_lf; ++j)
2177         if (le32toh (lf->keys[j].offset) + 0x1000 == node) {
2178           for (; j < nr_subkeys_in_lf - 1; ++j)
2179             memcpy (&lf->keys[j], &lf->keys[j+1], sizeof (lf->keys[j]));
2180           lf->nr_keys = htole16 (nr_subkeys_in_lf - 1);
2181           goto found;
2182         }
2183     }
2184   }
2185   if (h->msglvl >= 2)
2186     fprintf (stderr, "hivex_node_delete_child: could not find parent to child link\n");
2187   errno = ENOTSUP;
2188   return -1;
2189
2190  found:;
2191   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + parent);
2192   size_t nr_subkeys_in_nk = le32toh (nk->nr_subkeys);
2193   nk->nr_subkeys = htole32 (nr_subkeys_in_nk - 1);
2194
2195   if (h->msglvl >= 2)
2196     fprintf (stderr, "hivex_node_delete_child: updating nr_subkeys in parent 0x%zx to %zu\n",
2197              parent, nr_subkeys_in_nk);
2198
2199   return 0;
2200 }
2201
2202 int
2203 hivex_node_set_values (hive_h *h, hive_node_h node,
2204                        size_t nr_values, const hive_set_value *values,
2205                        int flags)
2206 {
2207   if (!h->writable) {
2208     errno = EROFS;
2209     return -1;
2210   }
2211
2212   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
2213     errno = EINVAL;
2214     return -1;
2215   }
2216
2217   /* Delete all existing values. */
2218   if (delete_values (h, node) == -1)
2219     return -1;
2220
2221   if (nr_values == 0)
2222     return 0;
2223
2224   /* Allocate value list node.  Value lists have no id field. */
2225   static const char nul_id[2] = { 0, 0 };
2226   size_t seg_len =
2227     sizeof (struct ntreg_value_list) + (nr_values - 1) * sizeof (uint32_t);
2228   size_t vallist_offs = allocate_block (h, seg_len, nul_id);
2229   if (vallist_offs == 0)
2230     return -1;
2231
2232   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
2233   nk->nr_values = htole32 (nr_values);
2234   nk->vallist = htole32 (vallist_offs - 0x1000);
2235
2236   struct ntreg_value_list *vallist =
2237     (struct ntreg_value_list *) (h->addr + vallist_offs);
2238
2239   size_t i;
2240   for (i = 0; i < nr_values; ++i) {
2241     /* Allocate vk record to store this (key, value) pair. */
2242     static const char vk_id[2] = { 'v', 'k' };
2243     seg_len = sizeof (struct ntreg_vk_record) + strlen (values[i].key);
2244     size_t vk_offs = allocate_block (h, seg_len, vk_id);
2245     if (vk_offs == 0)
2246       return -1;
2247
2248     vallist->offset[i] = htole32 (vk_offs - 0x1000);
2249
2250     struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + vk_offs);
2251     size_t name_len = strlen (values[i].key);
2252     vk->name_len = htole16 (name_len);
2253     strcpy (vk->name, values[i].key);
2254     vk->data_type = htole32 (values[i].t);
2255     vk->data_len = htole16 (values[i].len);
2256     vk->flags = name_len == 0 ? 0 : 1;
2257
2258     if (values[i].len <= 4)     /* Store data inline. */
2259       memcpy (&vk->data_offset, values[i].value, values[i].len);
2260     else {
2261       size_t offs = allocate_block (h, values[i].len + 4, nul_id);
2262       if (offs == 0)
2263         return -1;
2264       memcpy (h->addr + offs + 4, values[i].value, values[i].len);
2265       vk->data_offset = htole32 (offs - 0x1000);
2266     }
2267
2268     if (name_len * 2 > le32toh (nk->max_vk_name_len))
2269       nk->max_vk_name_len = htole32 (name_len * 2);
2270     if (values[i].len > le32toh (nk->max_vk_data_len))
2271       nk->max_vk_data_len = htole32 (values[i].len);
2272   }
2273
2274   return 0;
2275 }