4 * Extract information from Windows NT registry hives.
8 * Copyright (C) 2016 Eric Biggers
10 * This file is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU Lesser General Public License as published by the Free
12 * Software Foundation; either version 3 of the License, or (at your option) any
15 * This file is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this file; if not, see http://www.gnu.org/licenses/.
30 #include "wimlib/encoding.h"
31 #include "wimlib/endianness.h"
32 #include "wimlib/error.h"
33 #include "wimlib/registry.h"
34 #include "wimlib/util.h"
36 /* Registry hive file header */
38 #define REGF_MAGIC cpu_to_le32(0x66676572) /* "regf" */
41 #define REGF_MAJOR cpu_to_le32(1)
45 le32 root_key_offset; /* Offset, in hbin area, to root nk */
46 le32 total_hbin_size; /* Total size of all hbins */
48 u8 hbin_area[0]; /* Start of hbin area */
54 /* The cell size in bytes, negated for in-use cells */
57 /* Magic characters which identify the cell type */
61 /* NK cell - represents a registry key */
63 #define NK_MAGIC cpu_to_le16(0x6B6E) /* "nk" */
65 #define NK_COMPRESSED_NAME cpu_to_le16(0x0020)
72 le32 subkey_list_offset;
75 le32 value_list_offset;
89 /* LF (or LH) cell - contains a list of subkey references. LF and LH cells are
90 * the same except they use different hashing algorithms. But this
91 * implementation doesn't yet make use of the hashes anyway. */
93 #define LF_MAGIC cpu_to_le16(0x666C) /* "lf" */
94 #define LH_MAGIC cpu_to_le16(0x686C) /* "lh" */
99 le32 subkey_name_hash;
103 /* Value list cell - contains a list of value references */
109 /* VK cell - contains a value's data, or a reference to it */
115 #define REG_NONE cpu_to_le32(0x00000000)
116 #define REG_SZ cpu_to_le32(0x00000001)
117 #define REG_EXPAND_SZ cpu_to_le32(0x00000002)
118 #define REG_BINARY cpu_to_le32(0x00000003)
119 #define REG_DWORD cpu_to_le32(0x00000004)
120 #define REG_DWORD_LITTLE_ENDIAN cpu_to_le32(0x00000004)
121 #define REG_DWORD_BIG_ENDIAN cpu_to_le32(0x00000005)
122 #define REG_LINK cpu_to_le32(0x00000006)
123 #define REG_MULTI_SZ cpu_to_le32(0x00000007)
124 #define REG_RESOURCE_LIST cpu_to_le32(0x00000008)
125 #define REG_FULL_RESOURCE_DESCRIPTOR cpu_to_le32(0x00000009)
126 #define REG_RESOURCE_REQUIREMENTS_LIST cpu_to_le32(0x0000000A)
127 #define REG_QWORD cpu_to_le32(0x0000000B)
128 #define REG_QWORD_LITTLE_ENDIAN cpu_to_le32(0x0000000B)
130 #define VK_COMPRESSED_NAME cpu_to_le16(0x0001)
136 /* Data cell - contains a value's data */
142 static enum hive_status
143 translate_wimlib_error(int ret)
147 if (ret == WIMLIB_ERR_NOMEM)
148 return HIVE_OUT_OF_MEMORY;
149 return HIVE_UNSUPPORTED;
152 /* Compare a UTF-16LE name with a key or value name in the registry. The
153 * comparison is case insensitive. */
155 names_equal(const utf16lechar *name, size_t name_nchars,
156 const void *disk_name, size_t disk_name_size,
160 /* ISO-8859-1 (LATIN1) on-disk */
161 const u8 *p = disk_name;
162 if (disk_name_size != name_nchars)
164 for (size_t i = 0; i < name_nchars; i++)
165 if (upcase[le16_to_cpu(name[i])] != upcase[p[i]])
169 /* UTF-16LE on disk */
171 if (disk_name_size != name_nchars)
173 return !cmp_utf16le_strings(name, name_nchars,
174 disk_name, disk_name_size, true);
178 /* Get a pointer to a cell, with alignment and bounds checking. Returns NULL if
179 * the requested information does not specify a properly aligned, sized, and
182 get_cell_pointer(const struct regf *regf, le32 offset, size_t wanted_size)
184 u32 total = le32_to_cpu(regf->total_hbin_size);
185 u32 offs = le32_to_cpu(offset);
186 const struct cell *cell;
189 if ((offs > total) || (offs & 7) || (wanted_size > total - offs))
192 cell = (const struct cell *)®f->hbin_area[offs];
193 actual_size = le32_to_cpu(cell->size);
194 if (actual_size >= 0) /* Cell not in use? */
196 if (wanted_size > -actual_size) /* Cell too small? */
201 /* Revalidate the cell with its full length. Returns true iff the cell is
204 revalidate_cell(const struct regf *regf, le32 offset, size_t wanted_size)
206 return get_cell_pointer(regf, offset, wanted_size) != NULL;
210 * Given a registry key cell @nk, look up the next component of the key
211 * *key_namep. If found, return HIVE_OK, advance *key_namep past the key name
212 * component, and return the subkey cell in @sub_nk_ret. Otherwise, return
213 * another HIVE_* error code.
215 static enum hive_status
216 lookup_subkey(const struct regf *regf, const utf16lechar **key_namep,
217 const struct nk *nk, const struct nk **sub_nk_ret)
219 const utf16lechar *key_name = *key_namep;
220 size_t key_name_nchars = 0;
222 const struct cell *subkey_list;
224 for (const utf16lechar *p = key_name;
225 *p && *p != cpu_to_le16('\\'); p++)
228 num_subkeys = le32_to_cpu(nk->num_subkeys);
230 if (num_subkeys == 0) /* No subkeys? */
231 return HIVE_KEY_NOT_FOUND;
233 if (num_subkeys > 65536) /* Arbitrary limit */
236 /* Find the subkey list cell. */
237 subkey_list = get_cell_pointer(regf, nk->subkey_list_offset,
238 sizeof(struct cell));
242 if (subkey_list->magic == LF_MAGIC || subkey_list->magic == LH_MAGIC) {
245 /* Handle LF and LH subkey lists. */
247 lf = get_cell_pointer(regf, nk->subkey_list_offset,
249 (num_subkeys * sizeof(lf->subkeys[0])));
253 /* Look for the subkey in the subkey list. */
254 for (size_t i = 0; i < num_subkeys; i++) {
255 const struct nk *sub_nk;
258 sub_nk = get_cell_pointer(regf, lf->subkeys[i].offset,
263 name_size = le16_to_cpu(sub_nk->name_size);
265 if (!revalidate_cell(regf, lf->subkeys[i].offset,
266 sizeof(struct nk) + name_size))
269 if (names_equal(key_name, key_name_nchars,
270 sub_nk->name, name_size,
271 (sub_nk->flags & NK_COMPRESSED_NAME)))
273 key_name += key_name_nchars;
274 while (*key_name == cpu_to_le16('\\'))
276 *key_namep = key_name;
277 *sub_nk_ret = sub_nk;
281 return HIVE_KEY_NOT_FOUND;
284 return HIVE_UNSUPPORTED;
287 /* Find the nk cell for the key named @key_name in the registry hive @regf. */
288 static enum hive_status
289 lookup_key(const struct regf *regf, const tchar *key_name,
290 const struct nk **nk_ret)
293 enum hive_status status;
294 const utf16lechar *key_uname, *key_unamep;
296 nk = get_cell_pointer(regf, regf->root_key_offset, sizeof(struct nk));
300 status = translate_wimlib_error(tstr_get_utf16le(key_name, &key_uname));
301 if (status != HIVE_OK)
303 key_unamep = key_uname;
304 while (*key_unamep) {
305 status = lookup_subkey(regf, &key_unamep, nk, &nk);
306 if (status != HIVE_OK)
312 tstr_put_utf16le(key_uname);
316 /* Find the vk cell for the value named @value_name of the key named @key_name
317 * in the registry hive @regf. */
318 static enum hive_status
319 lookup_value(const struct regf *regf, const tchar *key_name,
320 const tchar *value_name, const struct vk **vk_ret)
322 enum hive_status status;
325 const struct value_list *value_list;
326 const utf16lechar *value_uname;
327 size_t value_uname_nchars;
329 /* Look up the nk cell for the key. */
330 status = lookup_key(regf, key_name, &nk);
331 if (status != HIVE_OK)
334 num_values = le32_to_cpu(nk->num_values);
336 if (num_values == 0) /* No values? */
337 return HIVE_VALUE_NOT_FOUND;
339 if (num_values > 65536) /* Arbitrary limit */
342 value_list = get_cell_pointer(regf, nk->value_list_offset,
343 sizeof(struct value_list) +
345 sizeof(value_list->vk_offsets[0])));
349 /* Look for the value in the value list. */
351 status = translate_wimlib_error(
352 tstr_get_utf16le_and_len(value_name, &value_uname,
353 &value_uname_nchars));
354 if (status != HIVE_OK)
356 value_uname_nchars /= 2;
358 for (size_t i = 0; i < num_values; i++) {
362 status = HIVE_CORRUPT;
363 vk = get_cell_pointer(regf, value_list->vk_offsets[i],
368 name_size = le16_to_cpu(vk->name_size);
370 if (!revalidate_cell(regf, value_list->vk_offsets[i],
371 sizeof(struct vk) + name_size))
374 if (names_equal(value_uname, value_uname_nchars,
376 (vk->flags & VK_COMPRESSED_NAME)))
384 status = HIVE_VALUE_NOT_FOUND;
386 tstr_put_utf16le(value_uname);
391 * Retrieve the data of the value named @value_name of the key named @key_name
392 * in the registry hive @regf. If the value was found, return HIVE_OK and
393 * return the data, its size, and its type in @data_ret, @data_size_ret, and
394 * @data_type_ret. Otherwise, return another HIVE_* error code.
396 static enum hive_status
397 retrieve_value(const struct regf *regf, const tchar *key_name,
398 const tchar *value_name, void **data_ret,
399 size_t *data_size_ret, le32 *data_type_ret)
401 enum hive_status status;
407 /* Find the vk cell. */
408 status = lookup_value(regf, key_name, value_name, &vk);
409 if (status != HIVE_OK)
412 /* Extract the value data from the vk cell (for inline data) or from the
413 * data cell which it references (for non-inline data). */
415 data_size = le32_to_cpu(vk->data_size);
417 is_inline = (data_size & 0x80000000);
418 data_size &= 0x7FFFFFFF;
420 if (data_size > 1048576) /* Arbitrary limit */
426 data = &vk->data_offset;
428 const struct data_cell *data_cell;
430 data_cell = get_cell_pointer(regf, vk->data_offset,
431 sizeof(struct data_cell));
435 if (!revalidate_cell(regf, vk->data_offset,
436 sizeof(struct data_cell) + data_size))
437 return HIVE_UNSUPPORTED; /* Possibly a big data cell */
439 data = data_cell->data;
442 *data_ret = memdup(data, data_size);
444 return HIVE_OUT_OF_MEMORY;
445 *data_size_ret = data_size;
446 *data_type_ret = vk->data_type;
450 /* Validate the registry hive file given in memory as @hive_mem and @hive_size.
451 * If valid, return HIVE_OK. If invalid, return another HIVE_* error code. */
453 hive_validate(const void *hive_mem, size_t hive_size)
455 const struct regf *regf = hive_mem;
457 STATIC_ASSERT(sizeof(struct regf) == 4096);
459 if (hive_size < sizeof(struct regf))
462 if (regf->magic != REGF_MAGIC || regf->major_version != REGF_MAJOR)
463 return HIVE_UNSUPPORTED;
465 if (le32_to_cpu(regf->total_hbin_size) > hive_size - sizeof(struct regf))
471 /* Get a string value from the registry hive file. */
473 hive_get_string(const struct regf *regf, const tchar *key_name,
474 const tchar *value_name, tchar **value_ret)
479 enum hive_status status;
481 /* Retrieve the raw value data. */
482 status = retrieve_value(regf, key_name, value_name,
483 &data, &data_size, &data_type);
484 if (status != HIVE_OK)
487 /* Interpret the data as a string, when possible. */
491 status = translate_wimlib_error(
492 utf16le_to_tstr(data, data_size, value_ret, &data_size));
495 status = HIVE_VALUE_IS_WRONG_TYPE;
502 /* Get a number value from the registry hive file. */
504 hive_get_number(const struct regf *regf, const tchar *key_name,
505 const tchar *value_name, s64 *value_ret)
510 enum hive_status status;
512 /* Retrieve the raw value data. */
513 status = retrieve_value(regf, key_name, value_name,
514 &data, &data_size, &data_type);
515 if (status != HIVE_OK)
518 /* Interpret the data as a number, when possible. */
520 case REG_DWORD_LITTLE_ENDIAN:
521 if (data_size == 4) {
522 *value_ret = le32_to_cpu(*(le32 *)data);
525 status = HIVE_CORRUPT;
528 case REG_DWORD_BIG_ENDIAN:
529 if (data_size == 4) {
530 *value_ret = be32_to_cpu(*(be32 *)data);
533 status = HIVE_CORRUPT;
536 case REG_QWORD_LITTLE_ENDIAN:
537 if (data_size == 8) {
538 *value_ret = le64_to_cpu(*(le64 *)data);
541 status = HIVE_CORRUPT;
545 status = HIVE_VALUE_IS_WRONG_TYPE;
553 /* List the subkeys of the specified registry key. */
555 hive_list_subkeys(const struct regf *regf, const tchar *key_name,
556 tchar ***subkeys_ret)
558 enum hive_status status;
561 const struct cell *subkey_list;
564 /* Look up the nk cell for the key. */
565 status = lookup_key(regf, key_name, &nk);
566 if (status != HIVE_OK)
569 num_subkeys = le32_to_cpu(nk->num_subkeys);
571 if (num_subkeys > 65536) /* Arbitrary limit */
574 /* Prepare the array of subkey names to return. */
575 subkeys = CALLOC(num_subkeys + 1, sizeof(subkeys[0]));
577 return HIVE_OUT_OF_MEMORY;
578 *subkeys_ret = subkeys;
581 if (num_subkeys == 0)
584 /* Find the subkey list cell. */
585 status = HIVE_CORRUPT;
586 subkey_list = get_cell_pointer(regf, nk->subkey_list_offset,
587 sizeof(struct cell));
591 if (subkey_list->magic == LF_MAGIC || subkey_list->magic == LH_MAGIC) {
594 /* Handle LF and LH subkey lists. */
596 status = HIVE_CORRUPT;
597 lf = get_cell_pointer(regf, nk->subkey_list_offset,
599 (num_subkeys * sizeof(lf->subkeys[0])));
603 /* Iterate through the subkey list and gather the subkey names.
605 for (size_t i = 0; i < num_subkeys; i++) {
606 const struct nk *sub_nk;
611 status = HIVE_CORRUPT;
612 sub_nk = get_cell_pointer(regf, lf->subkeys[i].offset,
617 name_size = le16_to_cpu(sub_nk->name_size);
619 if (!revalidate_cell(regf, lf->subkeys[i].offset,
620 sizeof(struct nk) + name_size))
623 if (sub_nk->flags & NK_COMPRESSED_NAME) {
624 status = HIVE_OUT_OF_MEMORY;
625 subkey = MALLOC((name_size + 1) * sizeof(tchar));
628 for (size_t j = 0; j < name_size; j++)
629 subkey[j] = sub_nk->name[j];
630 subkey[name_size] = '\0';
632 status = translate_wimlib_error(
633 utf16le_to_tstr((utf16lechar *)sub_nk->name,
634 name_size, &subkey, &dummy));
635 if (status != HIVE_OK)
643 status = HIVE_UNSUPPORTED;
645 hive_free_subkeys_list(subkeys);
650 hive_free_subkeys_list(tchar **subkeys)
652 for (tchar **p = subkeys; *p; p++)
658 hive_status_to_string(enum hive_status status)
664 return "HIVE_CORRUPT";
665 case HIVE_UNSUPPORTED:
666 return "HIVE_UNSUPPORTED";
667 case HIVE_KEY_NOT_FOUND:
668 return "HIVE_KEY_NOT_FOUND";
669 case HIVE_VALUE_NOT_FOUND:
670 return "HIVE_VALUE_NOT_FOUND";
671 case HIVE_VALUE_IS_WRONG_TYPE:
672 return "HIVE_VALUE_IS_WRONG_TYPE";
673 case HIVE_OUT_OF_MEMORY:
674 return "HIVE_OUT_OF_MEMORY";