struct ntreg_hbin_page {
char magic[4]; /* "hbin" */
uint32_t offset_first; /* offset from 1st block */
- uint32_t offset_next; /* offset of next (relative to this) */
+ uint32_t page_size; /* size of this page (multiple of 4KB) */
char unknown[20];
/* Linked list of blocks follows here. */
} __attribute__((__packed__));
char name[1]; /* key name follows here */
} __attribute__((__packed__));
+static uint32_t
+header_checksum (hive_h *h)
+{
+ uint32_t *daddr = (uint32_t *) h->addr;
+ size_t i;
+ uint32_t sum = 0;
+
+ for (i = 0; i < 0x1fc / 4; ++i) {
+ sum ^= le32toh (*daddr);
+ daddr++;
+ }
+
+ return sum;
+}
+
hive_h *
hivex_open (const char *filename, int flags)
{
goto error;
/* Header checksum. */
- uint32_t *daddr = (uint32_t *) h->addr;
- size_t i;
- uint32_t sum = 0;
- for (i = 0; i < 0x1fc / 4; ++i) {
- sum ^= le32toh (*daddr);
- daddr++;
- }
-
+ uint32_t sum = header_checksum (h);
if (sum != le32toh (h->hdr->csum)) {
fprintf (stderr, "hivex: %s: bad checksum in hive header\n", filename);
errno = EINVAL;
*/
size_t off;
struct ntreg_hbin_page *page;
- for (off = 0x1000; off < h->size; off += le32toh (page->offset_next)) {
+ for (off = 0x1000; off < h->size; off += le32toh (page->page_size)) {
if (off >= h->endpages)
break;
goto error;
}
- size_t page_size = le32toh (page->offset_next);
+ size_t page_size = le32toh (page->page_size);
if (h->msglvl >= 2)
fprintf (stderr, "hivex_open: page at 0x%zx, size %zu\n", off, page_size);
pages++;
if (page_size < smallest_page) smallest_page = page_size;
if (page_size > largest_page) largest_page = page_size;
- if (le32toh (page->offset_next) <= sizeof (struct ntreg_hbin_page) ||
- (le32toh (page->offset_next) & 3) != 0) {
- fprintf (stderr, "hivex: %s: pagesize %d at %zu, bad registry\n",
- filename, le32toh (page->offset_next), off);
+ if (page_size <= sizeof (struct ntreg_hbin_page) ||
+ (page_size & 0x0fff) != 0) {
+ fprintf (stderr, "hivex: %s: page size %zu at 0x%zx, bad registry\n",
+ filename, page_size, off);
errno = ENOTSUP;
goto error;
}
struct ntreg_hbin_block *block;
size_t seg_len;
for (blkoff = off + 0x20;
- blkoff < off + le32toh (page->offset_next);
+ blkoff < off + page_size;
blkoff += seg_len) {
blocks++;