Index: /trunk/include/regfi.h
===================================================================
--- /trunk/include/regfi.h	(revision 206)
+++ /trunk/include/regfi.h	(revision 207)
@@ -963,4 +963,34 @@
 
 
+/** Retrieves number of subkeys referenced by this key.
+ *
+ * Number of subkeyss in key structure and subkey list structure could differ,
+ * so this provides a standard/sane way of determining the number.
+ *
+ * @param key  the key whose number of subkeys is desired
+ *
+ * @return Returns the number of subkeys referenced by this key.
+ *
+ * @ingroup regfiBase
+ */
+_EXPORT
+uint32_t regfi_fetch_num_subkeys(const REGFI_NK* key);
+
+
+/** Retrieves number of values referenced by this key.
+ *
+ * Number of values in key structure and value list structure could differ,
+ * so this provides a standard/sane way of determining the number.
+ *
+ * @param key  the key whose number of values is desired
+ *
+ * @return Returns the number of values referenced by this key.
+ *
+ * @ingroup regfiBase
+ */
+_EXPORT
+uint32_t regfi_fetch_num_values(const REGFI_NK* key);
+
+
 /** Retrieves classname for a given key.
  *
@@ -1004,4 +1034,73 @@
 const REGFI_DATA* regfi_fetch_data(REGFI_FILE* file,
 				   const REGFI_VK* value);
+
+
+/** Locates a specific subkey of a given key.
+ *
+ * @param file  the file from which key is derived
+ * @param key   the key whose subkey is desired
+ * @param name  name of the desired subkey
+ * @param index a return value: the index of the desired subkey.
+ *              undefined on error
+ *
+ * @return true if the subkey is found, false if an error occurred or if the
+ *         specified name could not be found. If an error occurs, messages
+ *         will be written explaining the issue. (See regfi_log_get_str.)
+ *
+ * @ingroup regfiBase
+ */
+_EXPORT
+bool regfi_find_subkey(REGFI_FILE* file, const REGFI_NK* key, 
+		       const char* name, uint32_t* index);
+
+
+/** Locates a specific value of a given key.
+ *
+ * @param file  the file from which key is derived
+ * @param key   the key whose value is desired
+ * @param name  name of the desired value
+ * @param index a return value: the index of the desired value.  
+ *              undefined on error
+ *
+ * @return true if the value is found, false if an error occurred or if the
+ *         specified name could not be found. If an error occurs, messages
+ *         will be written explaining the issue. (See regfi_log_get_str.)
+ *
+ * @ingroup regfiBase
+ */
+_EXPORT
+bool regfi_find_value(REGFI_FILE* file, const REGFI_NK* key,
+		      const char* name, uint32_t* index);
+
+
+/** Retrieves a specific subkey of a given key.
+ *
+ * @param file  the file from which key is derived
+ * @param key   the key whose subkey is desired
+ * @param index the index of the desired subkey
+ *
+ * @return the requested subkey or NULL on error.
+ *
+ * @ingroup regfiBase
+ */
+_EXPORT
+const REGFI_NK* regfi_get_subkey(REGFI_FILE* file, const REGFI_NK* key, 
+				 uint32_t index);
+
+
+/** Retrieves a specific value of a given key.
+ *
+ * @param file  the file from which key is derived
+ * @param key   the key whose value is desired
+ * @param index the index of the desired value
+ *
+ * @return the requested value or NULL on error.
+ *
+ * @ingroup regfiBase
+ */
+_EXPORT
+const REGFI_VK* regfi_get_value(REGFI_FILE* file, const REGFI_NK* key, 
+				uint32_t index);
+
 
 
@@ -1166,6 +1265,6 @@
 /** Searches for a subkey with a given name under the current key.
  *
- * @param i           the iterator
- * @param subkey_name subkey name to search for
+ * @param i     the iterator
+ * @param name  subkey name to search for
  *
  * @return True if such a subkey was found, false otherwise.  If a subkey is
@@ -1176,5 +1275,5 @@
  */
 _EXPORT
-bool regfi_iterator_find_subkey(REGFI_ITERATOR* i, const char* subkey_name);
+bool regfi_iterator_find_subkey(REGFI_ITERATOR* i, const char* name);
 
 
@@ -1220,6 +1319,6 @@
 /** Searches for a value with a given name under the current key.
  *
- * @param i          the iterator
- * @param value_name value name to search for
+ * @param i     the iterator
+ * @param name  value name to search for
  *
  * @return True if such a value was found, false otherwise.  If a value is 
@@ -1230,6 +1329,5 @@
  */
 _EXPORT
-bool regfi_iterator_find_value(REGFI_ITERATOR* i, 
-			       const char* value_name);
+bool regfi_iterator_find_value(REGFI_ITERATOR* i, const char* name);
 
 
Index: /trunk/lib/regfi.c
===================================================================
--- /trunk/lib/regfi.c	(revision 206)
+++ /trunk/lib/regfi.c	(revision 207)
@@ -1721,4 +1721,45 @@
 
 
+
+/******************************************************************************
+ *****************************************************************************/
+uint32_t regfi_fetch_num_subkeys(const REGFI_NK* key)
+{
+  uint32_t num_in_list = 0;
+  if(key->subkeys != NULL)
+    num_in_list = key->subkeys->num_keys;
+
+  if(num_in_list != key->num_subkeys)
+  {
+    regfi_log_add(REGFI_LOG_INFO, "Key at offset 0x%.8X contains %d keys in its"
+		  " subkey list but reports %d should be available.", 
+		  key->offset, num_in_list, key->num_subkeys);
+    return (num_in_list < key->num_subkeys)?num_in_list:key->num_subkeys;
+  }
+  
+  return num_in_list;
+}
+
+
+/******************************************************************************
+ *****************************************************************************/
+uint32_t regfi_fetch_num_values(const REGFI_NK* key)
+{
+  uint32_t num_in_list = 0;
+  if(key->values != NULL)
+    num_in_list = key->values->num_values;
+
+  if(num_in_list != key->num_values)
+  {
+    regfi_log_add(REGFI_LOG_INFO, "Key at offset 0x%.8X contains %d values in"
+		  " its value list but reports %d should be available.",
+		  key->offset, num_in_list, key->num_values);
+    return (num_in_list < key->num_values)?num_in_list:key->num_values;
+  }
+  
+  return num_in_list;
+}
+
+
 /******************************************************************************
  *****************************************************************************/
@@ -1836,35 +1877,15 @@
 /******************************************************************************
  *****************************************************************************/
-bool regfi_iterator_find_subkey(REGFI_ITERATOR* i, const char* subkey_name)
-{
-  REGFI_NK* subkey;
-  bool found = false;
-  uint32_t old_subkey = i->cur_subkey;
-
-  if(subkey_name == NULL)
-    return false;
-
-  /* XXX: this alloc/free of each sub key might be a bit excessive */
-  regfi_iterator_first_subkey(i);
-  while((subkey = regfi_iterator_cur_subkey(i)) != NULL && (found == false))
-  {
-    if(subkey->name != NULL 
-       && strcasecmp(subkey->name, subkey_name) == 0)
-      found = true;
-    else
-    {
-      talloc_unlink(NULL, subkey);
-      regfi_iterator_next_subkey(i);
-    }
-  }
-
-  if(found == false)
-  {
-    i->cur_subkey = old_subkey;
-    return false;
-  }
-
-  talloc_unlink(NULL, subkey);
-  return true;
+bool regfi_iterator_find_subkey(REGFI_ITERATOR* i, const char* name)
+{
+  uint32_t new_index;
+
+  if(regfi_find_subkey(i->f, i->cur_key, name, &new_index))
+  {
+    i->cur_subkey = new_index;
+    return true;
+  }
+
+  return false;
 }
 
@@ -1922,5 +1943,5 @@
   
   return ((i->cur_key != NULL) && (i->cur_key->subkeys_off!=REGFI_OFFSET_NONE) 
-	  && (i->cur_subkey < i->cur_key->num_subkeys)); 
+	  && (i->cur_subkey < regfi_fetch_num_subkeys(i->cur_key)));
 }
 
@@ -1930,16 +1951,5 @@
 const REGFI_NK* regfi_iterator_cur_subkey(REGFI_ITERATOR* i)
 {
-  uint32_t nk_offset;
-
-  if((i->cur_key != NULL) && (i->cur_key->subkeys_off!=REGFI_OFFSET_NONE) 
-     && (i->cur_subkey < i->cur_key->num_subkeys))
-  {
-    nk_offset = i->cur_key->subkeys->elements[i->cur_subkey].offset;
-
-    return regfi_load_key(i->f, nk_offset+REGFI_REGF_SIZE, 
-			  i->f->string_encoding, true);
-  }
-
-  return NULL;
+  return regfi_get_subkey(i->f, i->cur_key, i->cur_subkey);
 }
 
@@ -1952,5 +1962,5 @@
 
   return ((i->cur_key != NULL) && (i->cur_key->subkeys_off!=REGFI_OFFSET_NONE) 
-	  && (i->cur_subkey < i->cur_key->num_subkeys)); 
+	  && (i->cur_subkey < regfi_fetch_num_subkeys(i->cur_key))); 
 }
 
@@ -1958,37 +1968,15 @@
 /******************************************************************************
  *****************************************************************************/
-bool regfi_iterator_find_value(REGFI_ITERATOR* i, const char* value_name)
-{
-  const REGFI_VK* cur;
-  bool found = false;
-  uint32_t old_value = i->cur_value;
-
-  /* XXX: cur->name can be NULL in the registry.  
-   *      Should we allow for a way to search for that? 
-   */
-  if(value_name == NULL)
-    return false;
-
-  regfi_iterator_first_value(i);
-  while((cur = regfi_iterator_cur_value(i)) != NULL && (found == false))
-  {
-    if((cur->name != NULL)
-       && (strcasecmp(cur->name, value_name) == 0))
-      found = true;
-    else
-    {
-      regfi_free_record(cur);
-      regfi_iterator_next_value(i);
-    }
-  }
-  
-  if(found == false)
-  {
-    i->cur_value = old_value;
-    return false;
-  }
-
-  regfi_free_record(cur);
-  return true;
+bool regfi_iterator_find_value(REGFI_ITERATOR* i, const char* name)
+{
+  uint32_t new_index;
+
+  if(regfi_find_value(i->f, i->cur_key, name, &new_index))
+  {
+    i->cur_value = new_index;
+    return true;
+  }
+
+  return false;
 }
 
@@ -2000,5 +1988,5 @@
   i->cur_value = 0;
   return (i->cur_key->values != NULL && i->cur_key->values->elements != NULL 
-	  && (i->cur_value < i->cur_key->values->num_values));
+	  && (i->cur_value < regfi_fetch_num_values(i->cur_key)));
 }
 
@@ -2008,16 +1996,5 @@
 const REGFI_VK* regfi_iterator_cur_value(REGFI_ITERATOR* i)
 {
-  REGFI_VK* ret_val = NULL;
-  uint32_t voffset;
-
-  if(i->cur_key->values != NULL && i->cur_key->values->elements != NULL 
-     && (i->cur_value < i->cur_key->values->num_values))
-  {
-    voffset = i->cur_key->values->elements[i->cur_value];
-    ret_val = regfi_load_value(i->f, voffset+REGFI_REGF_SIZE, 
-			       i->f->string_encoding, true);
-  }
-
-  return ret_val;
+  return regfi_get_value(i->f, i->cur_key, i->cur_value);
 }
 
@@ -2029,5 +2006,5 @@
   i->cur_value++;
   return (i->cur_key->values != NULL && i->cur_key->values->elements != NULL 
-	  && (i->cur_value < i->cur_key->values->num_values));
+	  && (i->cur_value < regfi_fetch_num_values(i->cur_key)));
 }
 
@@ -2141,4 +2118,112 @@
   
   return ret_val;
+}
+
+
+
+/******************************************************************************
+ *****************************************************************************/
+bool regfi_find_subkey(REGFI_FILE* file, const REGFI_NK* key, 
+		       const char* name, uint32_t* index)
+{
+  const REGFI_NK* cur;
+  uint32_t i;
+  uint32_t num_subkeys = regfi_fetch_num_subkeys(key);
+  bool found = false;
+
+  /* XXX: cur->name can be NULL in the registry.  
+   *      Should we allow for a way to search for that? 
+   */
+  if(name == NULL)
+    return false;
+
+  for(i=0; (i < num_subkeys) && (found == false); i++)
+  {
+    cur = regfi_get_subkey(file, key, i);
+    if(cur == NULL)
+      return false;
+
+    if((cur->name != NULL)
+       && (strcasecmp(cur->name, name) == 0))
+    {
+      found = true;
+      *index = i;
+    }
+
+    regfi_free_record(cur);
+  }
+
+  return found;
+}
+
+
+
+/******************************************************************************
+ *****************************************************************************/
+bool regfi_find_value(REGFI_FILE* file, const REGFI_NK* key, 
+		      const char* name, uint32_t* index)
+{
+  const REGFI_VK* cur;
+  uint32_t i;
+  uint32_t num_values = regfi_fetch_num_values(key);
+  bool found = false;
+
+  /* XXX: cur->name can be NULL in the registry.  
+   *      Should we allow for a way to search for that? 
+   */
+  if(name == NULL)
+    return false;
+
+  for(i=0; (i < num_values) && (found == false); i++)
+  {
+    cur = regfi_get_value(file, key, i);
+    if(cur == NULL)
+      return false;
+
+    if((cur->name != NULL)
+       && (strcasecmp(cur->name, name) == 0))
+    {
+      found = true;
+      *index = i;
+    }
+
+    regfi_free_record(cur);
+  }
+
+  return found;
+}
+
+
+
+/******************************************************************************
+ *****************************************************************************/
+const REGFI_NK* regfi_get_subkey(REGFI_FILE* file, const REGFI_NK* key, 
+				 uint32_t index)
+{
+  if(index < regfi_fetch_num_subkeys(key))
+  {
+    return regfi_load_key(file, 
+			  key->subkeys->elements[index].offset+REGFI_REGF_SIZE,
+			  file->string_encoding, true);
+  }
+
+  return NULL;
+}
+
+
+
+/******************************************************************************
+ *****************************************************************************/
+const REGFI_VK* regfi_get_value(REGFI_FILE* file, const REGFI_NK* key, 
+				uint32_t index)
+{
+  if(index < regfi_fetch_num_values(key))
+  {
+    return regfi_load_value(file, 
+			    key->values->elements[index]+REGFI_REGF_SIZE,
+			    file->string_encoding, true);
+  }
+
+  return NULL;  
 }
 
Index: /trunk/python/pyregfi/__init__.py
===================================================================
--- /trunk/python/pyregfi/__init__.py	(revision 206)
+++ /trunk/python/pyregfi/__init__.py	(revision 207)
@@ -6,5 +6,5 @@
 import ctypes
 import ctypes.util
-from ctypes import c_char,c_char_p,c_int,c_uint16,c_bool,POINTER
+from ctypes import c_char,c_char_p,c_int,c_uint16,c_uint32,c_bool,POINTER
 
 regfi = ctypes.CDLL(ctypes.util.find_library('regfi'), use_errno=True)
@@ -29,4 +29,10 @@
 regfi.regfi_free_record.restype = None
 
+regfi.regfi_fetch_num_subkeys.argtypes = [POINTER(REGFI_NK)]
+regfi.regfi_fetch_num_subkeys.restype = c_uint32
+
+regfi.regfi_fetch_num_values.argtypes = [POINTER(REGFI_NK)]
+regfi.regfi_fetch_num_values.restype = c_uint32
+
 regfi.regfi_fetch_classname.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
 regfi.regfi_fetch_classname.restype = POINTER(REGFI_CLASSNAME)
@@ -38,4 +44,20 @@
 regfi.regfi_fetch_data.restype = POINTER(REGFI_DATA)
 
+regfi.regfi_find_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
+                                    c_char_p, POINTER(c_uint32)]
+regfi.regfi_find_subkey.restype = c_bool
+
+regfi.regfi_find_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
+                                    c_char_p, POINTER(c_uint32)]
+regfi.regfi_find_value.restype = c_bool
+
+regfi.regfi_get_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
+                                   c_uint32]
+regfi.regfi_get_subkey.restype = POINTER(REGFI_NK)
+
+regfi.regfi_get_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
+                                   c_uint32]
+regfi.regfi_get_value.restype = POINTER(REGFI_VK)
+
 regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE), REGFI_ENCODING]
 regfi.regfi_iterator_new.restype = POINTER(REGFI_ITERATOR)
@@ -83,4 +105,7 @@
 regfi.regfi_iterator_find_value.restype = c_bool
 
+
+
+regfi.regfi_get_value
 
 regfi.regfi_init.argtypes = []
@@ -93,12 +118,14 @@
     if msgs == None:
         return ''
-    return msgs
+    return msgs.decode('ascii')
 
 
 class _StructureWrapper():
     "Handles memory management and proxies attribute access to base structures"
+    hive = None
     base = None
 
-    def __init__(self, base):
+    def __init__(self, hive, base):
+        self.hive = hive
         # XXX: check for NULL here, throw an exception if so.
         self.base = base
@@ -117,15 +144,65 @@
 
 
-class Key(_StructureWrapper):
-    pass
-
 class Value(_StructureWrapper):
     pass
 
+
 class Data(_StructureWrapper):
     pass
 
+
 class Security(_StructureWrapper):
     pass
+
+
+class _ValueList():
+    hive = None
+    key = None
+    length = None
+    current = None
+
+    def __init__(self, key):
+        self.hive = key.hive
+        # XXX: check for NULL here, throw an exception if so.
+        self.key = key
+        self.length = regfi.regfi_fetch_num_values(key.base)
+    
+    def __len__(self):
+        return self.length
+
+    def __getitem__(self, name):
+        index = c_uint32()
+        # XXX: need to do any funky unicode conversions on name?
+        if regfi.regfi_find_value(self.hive.file, self.key.base,
+                                  create_string_buffer(name), byref(index)):
+            return Value(hive,
+                         regfi.regfi_get_value(hive.file, key.base, index))
+        raise KeyError('')
+
+    def __iter__(self):
+        self.current = 0
+        return self
+    
+    def __next__(self):
+        if self.current >= self.length:
+            raise StopIteration('')
+
+        vk = regfi.regfi_get_value(self.hive.file, self.key.base,
+                                   c_uint32(self.current))
+        self.current += 1
+        return vk.contents
+    
+
+class Key(_StructureWrapper):
+    values = None
+
+    def __init__(self, hive, base):
+        super(Key, self).__init__(hive, base)
+        self.values = _ValueList(self)
+
+    def fetch_security(self):
+        return Security(self.hive,
+                        regfi.regfi_fetch_sk(self.hive.file, self.base))
+
 
 class Hive():    
@@ -229,3 +306,3 @@
 
     def current_key(self):
-        return Key(regfi.regfi_iterator_cur_key(self.iter))
+        return Key(self.hive, regfi.regfi_iterator_cur_key(self.iter))
