/* hivex - Windows Registry "hive" extraction library.
- * Copyright (C) 2009 Red Hat Inc.
+ * Copyright (C) 2009-2010 Red Hat Inc.
* Derived from code by Petter Nordahl-Hagen under a compatible license:
* Copyright (c) 1997-2007 Petter Nordahl-Hagen.
* Derived from code by Markus Stephany under a compatible license:
#include <sys/mman.h>
#include <sys/stat.h>
#include <assert.h>
-#ifdef HAVE_ENDIAN_H
-#include <endian.h>
-#endif
-#ifdef HAVE_BYTESWAP_H
-#include <byteswap.h>
+
+#include "full-read.h"
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
#endif
#define STREQ(a,b) (strcmp((a),(b)) == 0)
//#define STRCASENEQLEN(a,b,n) (strncasecmp((a),(b),(n)) != 0)
//#define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0)
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#ifndef be32toh
-#define be32toh(x) __bswap_32 (x)
-#endif
-#ifndef be64toh
-#define be64toh(x) __bswap_64 (x)
-#endif
-#ifndef le16toh
-#define le16toh(x) (x)
-#endif
-#ifndef le32toh
-#define le32toh(x) (x)
-#endif
-#ifndef le64toh
-#define le64toh(x) (x)
-#endif
-#else
-#ifndef be32toh
-#define be32toh(x) (x)
-#endif
-#ifndef be64toh
-#define be64toh(x) (x)
-#endif
-#ifndef le16toh
-#define le16toh(x) __bswap_16 (x)
-#endif
-#ifndef le32toh
-#define le32toh(x) __bswap_32 (x)
-#endif
-#ifndef le64toh
-#define le64toh(x) __bswap_64 (x)
-#endif
-#endif
-
#include "hivex.h"
+#include "byte_conversions.h"
static char *windows_utf16_to_utf8 (/* const */ char *input, size_t len);
int fd;
size_t size;
int msglvl;
+ int writable;
- /* Memory-mapped (readonly) registry file. */
+ /* Registry file, memory mapped if read-only, or malloc'd if writing. */
union {
char *addr;
struct ntreg_header *hdr;
char id[2]; /* "nk" */
uint16_t flags;
char timestamp[8];
- char unknown0[4];
+ uint32_t unknown1;
uint32_t parent; /* offset of owner/parent */
uint32_t nr_subkeys; /* number of subkeys */
- uint32_t unknown1;
+ uint32_t nr_subkeys_volatile;
uint32_t subkey_lf; /* lf record containing list of subkeys */
- uint32_t unknown2;
+ uint32_t subkey_lf_volatile;
uint32_t nr_values; /* number of values */
uint32_t vallist; /* value-list record */
uint32_t sk; /* offset of sk-record */
uint32_t classname; /* offset of classname record */
- char unknown3[16];
- uint32_t unknown4;
+ uint16_t max_subkey_name_len; /* maximum length of a subkey name in bytes
+ if the subkey was reencoded as UTF-16LE */
+ uint16_t unknown2;
+ uint32_t unknown3;
+ uint32_t max_vk_name_len; /* maximum length of any vk name in bytes
+ if the name was reencoded as UTF-16LE */
+ uint32_t max_vk_data_len; /* maximum length of any vk data in bytes */
+ uint32_t unknown6;
uint16_t name_len; /* length of name */
uint16_t classname_len; /* length of classname */
char name[1]; /* name follows here */
uint32_t data_type; /* type of the data */
uint16_t flags; /* bit 0 set => key name ASCII,
bit 0 clr => key name UTF-16.
- Only seen ASCII here in the wild. */
+ Only seen ASCII here in the wild.
+ NB: this is CLEAR for default key. */
uint16_t unknown2;
char name[1]; /* key name follows here */
} __attribute__((__packed__));
static uint32_t
-header_checksum (hive_h *h)
+header_checksum (const hive_h *h)
{
uint32_t *daddr = (uint32_t *) h->addr;
size_t i;
if (h->msglvl >= 2)
fprintf (stderr, "hivex_open: created handle %p\n", h);
+ h->writable = !!(flags & HIVEX_OPEN_WRITE);
h->filename = strdup (filename);
if (h->filename == NULL)
goto error;
- h->fd = open (filename, O_RDONLY);
+ h->fd = open (filename, O_RDONLY | O_CLOEXEC);
if (h->fd == -1)
goto error;
h->size = statbuf.st_size;
- h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
- if (h->addr == MAP_FAILED)
- goto error;
+ if (!h->writable) {
+ h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
+ if (h->addr == MAP_FAILED)
+ goto error;
- if (h->msglvl >= 2)
- fprintf (stderr, "hivex_open: mapped file at %p\n", h->addr);
+ if (h->msglvl >= 2)
+ fprintf (stderr, "hivex_open: mapped file at %p\n", h->addr);
+ } else {
+ h->addr = malloc (h->size);
+ if (h->addr == NULL)
+ goto error;
+
+ if (full_read (h->fd, h->addr, h->size) < h->size)
+ goto error;
+ }
/* Check header. */
if (h->hdr->magic[0] != 'r' ||
int err = errno;
if (h) {
free (h->bitmap);
- if (h->addr && h->size && h->addr != MAP_FAILED)
- munmap (h->addr, h->size);
+ if (h->addr && h->size && h->addr != MAP_FAILED) {
+ if (!h->writable)
+ munmap (h->addr, h->size);
+ else
+ free (h->addr);
+ }
if (h->fd >= 0)
close (h->fd);
free (h->filename);
int r;
free (h->bitmap);
- munmap (h->addr, h->size);
+ if (!h->writable)
+ munmap (h->addr, h->size);
+ else
+ free (h->addr);
r = close (h->fd);
free (h->filename);
free (h);