Reading of ri blocks.
Better error handling.
diff --git a/misc/registry.c b/misc/registry.c
index 5c7751e..5533a14 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -674,10 +674,14 @@
#define NT_REG_HEADER_BLOCK_ID 0x66676572 /* regf */
#define NT_REG_POOL_BLOCK_ID 0x6E696268 /* hbin */
-#define NT_REG_KEY_BLOCK_ID 0x6b6e
-#define NT_REG_VALUE_BLOCK_ID 0x6b76
-#define NT_REG_HASH_BLOCK_ID 0x666c
-#define NT_REG_NOHASH_BLOCK_ID 0x696c
+#define NT_REG_KEY_BLOCK_ID 0x6b6e /* nk */
+#define NT_REG_VALUE_BLOCK_ID 0x6b76 /* vk */
+
+/* subblocks of nk */
+#define NT_REG_HASH_BLOCK_ID 0x666c /* lf */
+#define NT_REG_NOHASH_BLOCK_ID 0x696c /* li */
+#define NT_REG_RI_BLOCK_ID 0x6972 /* ri */
+
#define NT_REG_KEY_BLOCK_TYPE 0x20
#define NT_REG_ROOT_KEY_BLOCK_TYPE 0x2c
@@ -757,12 +761,37 @@
hash_rec hash_rec[1];
} nt_lf;
+/*
+ list of subkeys without hash
+
+ li --+-->nk
+ |
+ +-->nk
+ */
typedef struct
{
WORD id; /* 0x00 0x696c */
WORD nr_keys;
DWORD off_nk[1];
-} nt_il;
+} nt_li;
+
+/*
+ this is a intermediate node
+
+ ri --+-->li--+-->nk
+ | +
+ | +-->nk
+ |
+ +-->li--+-->nk
+ +
+ +-->nk
+ */
+typedef struct
+{
+ WORD id; /* 0x00 0x6972 */
+ WORD nr_li; /* 0x02 number off offsets */
+ DWORD off_li[1]; /* 0x04 points to li */
+} nt_ri;
typedef struct
{
@@ -789,7 +818,7 @@
static int _nt_parse_nk(HKEY hkey, char * base, nt_nk * nk, int level);
static int _nt_parse_vk(HKEY hkey, char * base, nt_vk * vk);
-static int _nt_parse_lf(HKEY hkey, char * base, nt_lf * lf, int level);
+static int _nt_parse_lf(HKEY hkey, char * base, int subkeys, nt_lf * lf, int level);
/*
@@ -822,7 +851,7 @@
if (ret) ERR("RegSetValueEx failed (0x%08lx)\n", ret);
return TRUE;
error:
- ERR_(reg)("vk block invalid\n");
+ ERR_(reg)("unknown block found (0x%04x), please report!\n", vk->id);
return FALSE;
}
@@ -835,27 +864,64 @@
* exception: if the id is 'il' there are no hash values and every
* dword is a offset
*/
-static int _nt_parse_lf(HKEY hkey, char * base, nt_lf * lf, int level)
+static int _nt_parse_lf(HKEY hkey, char * base, int subkeys, nt_lf * lf, int level)
{
int i;
if (lf->id == NT_REG_HASH_BLOCK_ID)
{
+ if (subkeys != lf->nr_keys) goto error1;
+
for (i=0; i<lf->nr_keys; i++)
{
if (!_nt_parse_nk(hkey, base, (nt_nk*)(base+lf->hash_rec[i].off_nk+4), level)) goto error;
}
-
}
else if (lf->id == NT_REG_NOHASH_BLOCK_ID)
{
- for (i=0; i<lf->nr_keys; i++)
+ nt_li * li = (nt_li*)lf;
+ if (subkeys != li->nr_keys) goto error1;
+
+ for (i=0; i<li->nr_keys; i++)
{
- if (!_nt_parse_nk(hkey, base, (nt_nk*)(base+((nt_il*)lf)->off_nk[i]+4), level)) goto error;
+ if (!_nt_parse_nk(hkey, base, (nt_nk*)(base+li->off_nk[i]+4), level)) goto error;
}
}
+ else if (lf->id == NT_REG_RI_BLOCK_ID) /* ri */
+ {
+ nt_ri * ri = (nt_ri*)lf;
+ int li_subkeys = 0;
+
+ /* count all subkeys */
+ for (i=0; i<ri->nr_li; i++)
+ {
+ nt_li * li = (nt_li*)(base+ri->off_li[i]+4);
+ if(li->id != NT_REG_NOHASH_BLOCK_ID) goto error2;
+ li_subkeys += li->nr_keys;
+ }
+
+ /* check number */
+ if (subkeys != li_subkeys) goto error1;
+
+ /* loop through the keys */
+ for (i=0; i<ri->nr_li; i++)
+ {
+ nt_li * li = (nt_li*)(base+ri->off_li[i]+4);
+ if (!_nt_parse_lf(hkey, base, li->nr_keys, (nt_lf*)li, level)) goto error;
+ }
+ }
+ else
+ {
+ goto error2;
+ }
+ return TRUE;
+
+error2: ERR("unknown node id 0x%04x, please report!\n", lf->id);
return TRUE;
+error1: ERR_(reg)("registry file corrupt! (inconsistent number of subkeys)\n");
+ return FALSE;
+
error: ERR_(reg)("error reading lf block\n");
return FALSE;
}
@@ -867,9 +933,18 @@
DWORD * vl;
HKEY subkey = hkey;
- if(nk->SubBlockId != NT_REG_KEY_BLOCK_ID) goto error;
+ if(nk->SubBlockId != NT_REG_KEY_BLOCK_ID)
+ {
+ ERR("unknown node id 0x%04x, please report!\n", nk->SubBlockId);
+ goto error;
+ }
+
if((nk->Type!=NT_REG_ROOT_KEY_BLOCK_TYPE) &&
- (((nt_nk*)(base+nk->parent_off+4))->SubBlockId != NT_REG_KEY_BLOCK_ID)) goto error;
+ (((nt_nk*)(base+nk->parent_off+4))->SubBlockId != NT_REG_KEY_BLOCK_ID))
+ {
+ ERR_(reg)("registry file corrupt!\n");
+ goto error;
+ }
/* create the new key */
if(level <= 0)
@@ -883,8 +958,7 @@
if (nk->nr_subkeys)
{
nt_lf * lf = (nt_lf*)(base+nk->lf_off+4);
- if (nk->nr_subkeys != lf->nr_keys) goto error1;
- if (!_nt_parse_lf(subkey, base, lf, level-1)) goto error1;
+ if (!_nt_parse_lf(subkey, base, nk->nr_subkeys, lf, level-1)) goto error1;
}
/* loop trough the value list */
@@ -899,8 +973,7 @@
return TRUE;
error1: RegCloseKey(subkey);
-error: ERR_(reg)("error reading nk block\n");
- return FALSE;
+error: return FALSE;
}
/* end nt loader */