Index: /trunk/include/regfi.h
===================================================================
--- /trunk/include/regfi.h	(revision 103)
+++ /trunk/include/regfi.h	(revision 104)
@@ -87,4 +87,5 @@
 #define REGFI_VK_MIN_LENGTH     0x14
 #define REGFI_SK_MIN_LENGTH     0x14
+#define REGFI_HASH_LIST_MIN_LENGTH     0x4
 
 /* Flags for the vk records */
@@ -135,20 +136,21 @@
 {
   uint32 nk_off;
-  uint8 keycheck[4];
-} REGF_HASH_REC;
-
-
-typedef struct 
-{
+  uint32 hash;
+} REGF_HASH_LIST_ELEM;
+
+
+typedef struct 
+{
+  uint32 offset;	/* Real offset of this record's cell in the file */
+  uint32 cell_size;	 /* ((start_offset - end_offset) & 0xfffffff8) */
   REGF_HBIN* hbin;       /* pointer to HBIN record (in memory) containing 
 			  * this nk record 
 			  */
-  REGF_HASH_REC* hashes;
   uint32 hbin_off;	 /* offset from beginning of this hbin block */
-  uint32 cell_size;	 /* ((start_offset - end_offset) & 0xfffffff8) */
-  
-  uint8 header[REC_HDR_SIZE];
+  REGF_HASH_LIST_ELEM* hashes;
+  
+  uint8 magic[REC_HDR_SIZE];
   uint16 num_keys;
-} REGF_LF_REC;
+} REGF_HASH_LIST;
 
 
@@ -204,6 +206,6 @@
 
 
-/* Key Name */ 
-typedef struct 
+/* Key Name */
+typedef struct
 {
   uint32 offset;	/* Real offset of this record's cell in the file */
@@ -215,5 +217,5 @@
   REGF_VK_REC** values;
   REGF_SK_REC* sec_desc;
-  REGF_LF_REC subkeys;
+  REGF_HASH_LIST* subkeys;
   
   /* header information */
@@ -382,4 +384,6 @@
 /* Experimental */
 /****************/
+REGF_HASH_LIST* regfi_load_hashlist(REGF_FILE* file, uint32 offset, 
+				    uint32 num_keys, bool strict);
 
 REGF_VK_REC** regfi_load_valuelist(REGF_FILE* file, uint32 offset, 
Index: /trunk/lib/regfi.c
===================================================================
--- /trunk/lib/regfi.c	(revision 103)
+++ /trunk/lib/regfi.c	(revision 104)
@@ -476,76 +476,100 @@
 
 
+
 /*******************************************************************
  *******************************************************************/
-static bool prs_hash_rec( const char *desc, prs_struct *ps, int depth, REGF_HASH_REC *hash )
-{
-  depth++;
-
-  if ( !prs_uint32( "nk_off", ps, depth, &hash->nk_off ))
-    return false;
-  if ( !prs_uint8s("keycheck", ps, depth, hash->keycheck, sizeof( hash->keycheck )) )
-    return false;
-	
-  return true;
-}
-
-
-/*******************************************************************
- *******************************************************************/
-static bool hbin_prs_lf_records(const char *desc, REGF_HBIN *hbin, 
-				int depth, REGF_NK_REC *nk)
-{
-  int i;
-  REGF_LF_REC *lf = &nk->subkeys;
-  uint32 data_size, start_off, end_off;
-
-  depth++;
-
-  /* check if we have anything to do first */
-	
-  if ( nk->num_subkeys == 0 )
-    return true;
-
-  /* move to the LF record */
-
-  if ( !prs_set_offset( &hbin->ps, nk->subkeys_off + HBIN_MAGIC_SIZE - hbin->first_hbin_off ) )
-    return false;
-
-  /* backup and get the data_size */
-	
-  if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
-    return false;
-  start_off = hbin->ps.data_offset;
-  if ( !prs_uint32( "cell_size", &hbin->ps, depth, &lf->cell_size ))
-    return false;
-
-  if(!prs_uint8s("header", &hbin->ps, depth, 
-		 lf->header, sizeof(lf->header)))
-    return false;
-
-  /*fprintf(stdout, "DEBUG: lf->header=%c%c\n", lf->header[0], lf->header[1]);*/
-
-  if ( !prs_uint16( "num_keys", &hbin->ps, depth, &lf->num_keys))
-    return false;
-
-  if ( hbin->ps.io ) {
-    if ( !(lf->hashes = (REGF_HASH_REC*)zcalloc(sizeof(REGF_HASH_REC), lf->num_keys )) )
-      return false;
-  }
-
-  for ( i=0; i<lf->num_keys; i++ ) {
-    if ( !prs_hash_rec( "hash_rec", &hbin->ps, depth, &lf->hashes[i] ) )
-      return false;
-  }
-
-  end_off = hbin->ps.data_offset;
-
-  /* data_size must be divisible by 8 and large enough to hold the original record */
-
-  data_size = ((start_off - end_off) & 0xfffffff8 );
-  /*  if ( data_size > lf->cell_size )*/
-    /*DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, lf->cell_size));*/
-
-  return true;
+REGF_HASH_LIST* regfi_load_hashlist(REGF_FILE* file, uint32 offset, 
+				    uint32 num_keys, bool strict)
+{
+  REGF_HASH_LIST* ret_val;
+  uint32 i, cell_length, length;
+  uint8* hashes;
+  uint8 buf[REGFI_HASH_LIST_MIN_LENGTH];
+  bool unalloc;
+
+  if(!regfi_parse_cell(file->fd, offset, buf, REGFI_HASH_LIST_MIN_LENGTH, 
+		       &cell_length, &unalloc))
+    return NULL;
+
+  ret_val = (REGF_HASH_LIST*)zalloc(sizeof(REGF_HASH_LIST));
+  if(ret_val == NULL)
+    return NULL;
+
+  ret_val->offset = offset;
+  ret_val->cell_size = cell_length;
+
+  if((buf[0] != 'l' || buf[1] != 'f') && (buf[0] != 'l' || buf[1] != 'h')
+     && (buf[0] != 'r' || buf[1] != 'i'))
+  {
+    /*printf("DEBUG: lf->header=%c%c\n", buf[0], buf[1]);*/
+    free(ret_val);
+    return NULL;
+  }
+
+  if(buf[0] == 'r' && buf[1] == 'i')
+  {
+    fprintf(stderr, "WARNING: ignoring encountered \"ri\" record.\n");
+    free(ret_val);
+    return NULL;
+  }
+
+  ret_val->magic[0] = buf[0];
+  ret_val->magic[1] = buf[1];
+
+  ret_val->num_keys = SVAL(buf, 0x2);
+  if(num_keys != ret_val->num_keys)
+  {
+    if(strict)
+    {
+      free(ret_val);
+      return NULL;
+    }
+    /* TODO: Not sure which should be authoritative, the number from the 
+     *       NK record, or the number in the hash list.  Go with the larger
+     *       of the two to ensure all keys are found.  Note the length checks
+     *       on the cell later ensure that there won't be any critical errors.
+     */
+    if(num_keys < ret_val->num_keys)
+      num_keys = ret_val->num_keys;
+    else
+      ret_val->num_keys = num_keys;
+  }
+
+  if(cell_length - REGFI_HASH_LIST_MIN_LENGTH - sizeof(uint32) 
+     < ret_val->num_keys*sizeof(REGF_HASH_LIST_ELEM))
+    return NULL;
+
+  length = sizeof(REGF_HASH_LIST_ELEM)*ret_val->num_keys;
+  ret_val->hashes = (REGF_HASH_LIST_ELEM*)zalloc(length);
+  if(ret_val->hashes == NULL)
+  {
+    free(ret_val);
+    return NULL;
+  }
+
+  hashes = (uint8*)zalloc(length);
+  if(hashes == NULL)
+  {
+    free(ret_val->hashes);
+    free(ret_val);
+    return NULL;
+  }
+
+  if(regfi_read(file->fd, hashes, &length) != 0
+     || length != sizeof(REGF_HASH_LIST_ELEM)*ret_val->num_keys)
+  {
+    free(ret_val->hashes);
+    free(ret_val);
+    return NULL;
+  }
+
+  for (i=0; i < ret_val->num_keys; i++)
+  {
+    ret_val->hashes[i].nk_off = IVAL(hashes, i*sizeof(REGF_HASH_LIST_ELEM));
+    ret_val->hashes[i].hash = IVAL(hashes, i*sizeof(REGF_HASH_LIST_ELEM)+4);
+  }
+  free(hashes);
+
+  return ret_val;
 }
 
@@ -782,7 +806,12 @@
       }
     }
-    
-    if (!hbin_prs_lf_records("lf_rec", sub_hbin, depth, nk))
-      return NULL;
+
+    nk->subkeys = regfi_load_hashlist(file, nk->subkeys_off + REGF_BLOCKSIZE,
+				      nk->num_subkeys, true);
+    if (nk->subkeys == NULL)
+    {
+      /* TODO: temporary hack to get around 'ri' records */
+      nk->num_subkeys = 0;
+    }
   }
 
@@ -1203,5 +1232,5 @@
     return NULL;
 
-  nk_offset = i->cur_key->subkeys.hashes[i->cur_subkey].nk_off;
+  nk_offset = i->cur_key->subkeys->hashes[i->cur_subkey].nk_off;
 
   /* find the HBIN block which should contain the nk record */
@@ -1211,5 +1240,5 @@
     /* XXX: should print out some kind of error message every time here */
     /*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing offset [0x%x]\n", 
-      i->cur_key->subkeys.hashes[i->cur_subkey].nk_off));*/
+      i->cur_key->subkeys->hashes[i->cur_subkey].nk_off));*/
     return NULL;
   }
