Index: /test/pyregfi-smoketest.py
===================================================================
--- /test/pyregfi-smoketest.py	(revision 214)
+++ /test/pyregfi-smoketest.py	(revision 215)
@@ -3,8 +3,27 @@
 import sys
 import gc
+import time
 import pyregfi
 
 def usage():
     sys.stderr.write("USAGE: pyregfi-smoketest.py hive1 [hive2 ...]\n")
+
+
+# helper function
+def getCurrentPath(key):
+    if key == None:
+        return ''
+    path = []
+    p = key
+    while p != None:
+        path.append(p.name)
+        if p.is_root():
+            break
+        else:
+            p = p.get_parent()
+    path.reverse()
+    del path[0]
+
+    return path
 
 
@@ -39,4 +58,22 @@
 
 
+# For each key in the hive, this traverses the parent links up to the root, 
+# recording the path as it goes, and then uses the subtree/descend method
+# to find the same key again, verifying it is the same.  This test is currently
+# very slow because no key caching is used.
+def iterParentWalk(hive):
+    i = 1
+    for k in hive:
+        path = getCurrentPath(k)
+        try:
+            hive_iter = hive.subtree(path)
+            if hive_iter.current_key() != k:
+                print("WARNING: k != current_key for path '%s'." % path)
+            else:
+                i += 1
+        except Exception as e:
+            print("WARNING: Could not decend to path '%s'.\nError:\n %s\n%s" % (path,e.args,e))
+    print("   Successfully tested paths on %d keys." % i)
+
 
 if len(sys.argv) < 2:
@@ -44,23 +81,29 @@
     sys.exit(1)
 
+
+tests = [("iterTally",iterTally),("iterParentWalk",iterParentWalk),]
+
 files = []
 for f in sys.argv[1:]:
     files.append((f, open(f,"r+b")))
 
-tests = [("iterTally",iterTally),]
 
+start_time = time.time()
 for hname,fh in files:
     hive = pyregfi.Hive(fh)
     for tname,t in tests:
+        teststart = time.time()
         tstr = "'%s' on '%s'" % (tname,hname)
         print("##BEGIN %s:" % tstr)
         t(hive)
-        print("##END %s; messages:" % tstr)
+        print("##END %s; runtime=%f; messages:" % (tstr, time.time() - teststart))
         print(pyregfi.GetLogMessages())
         print
-    hive = None
+        sys.stdout.flush()
 
+hive = None
 files = None
 tests = None
 gc.collect()
+print("### Tests Completed, runtime: %f ###" % (time.time() -  start_time))
 #print(gc.garbage)
Index: /trunk/include/regfi.h
===================================================================
--- /trunk/include/regfi.h	(revision 214)
+++ /trunk/include/regfi.h	(revision 215)
@@ -666,8 +666,8 @@
   uint8_t* name_raw;
 
-  /** Virutal offset of parent key */
+  /** Virtual offset of parent key */
   uint32_t parent_off;
 
-  /** Virutal offset of classname key */
+  /** Virtual offset of classname key */
   uint32_t classname_off;
   
@@ -952,5 +952,14 @@
 
 
-/* Dispose of previously parsed records */
+/** Fetches a hive's root key.
+ *
+ * @return Returns the root key or NULL on failure.  Key must be freed using
+ *         @ref regfi_free_record.
+ *
+ * @ingroup regfiBase
+ */
+_EXPORT
+const REGFI_NK*       regfi_get_rootkey(REGFI_FILE* file);
+
 
 /** Frees a record previously returned by one of the API functions.
@@ -962,5 +971,5 @@
  * convenience.  Since records returned previously must not be modified by users
  * of the API due to internal caching, these are returned as const, so this
- * function is const to make passing back in easy.
+ * function is const to make passing those records back easy.
  *
  * @ingroup regfiBase
@@ -1110,4 +1119,17 @@
 				uint32_t index);
 
+
+
+/** Uses a key's parent_off reference to retrieve it's parent.
+ *
+ * @param file  the file from which key is derived
+ * @param key   the key whose parent is desired
+ *
+ * @return the requested subkey or NULL on error.
+ *
+ * @ingroup regfiBase
+ */
+_EXPORT
+const REGFI_NK* regfi_get_parentkey(REGFI_FILE* file, const REGFI_NK* key);
 
 
@@ -1345,5 +1367,5 @@
 /******************************************************************************/
 
-/** Loads a key at a given file offset along with associated data structures.
+/** Loads a key and associated data structures given a file offset.
  *
  * XXX: finish documenting
@@ -1353,6 +1375,6 @@
 _EXPORT
 REGFI_NK* regfi_load_key(REGFI_FILE* file, uint32_t offset, 
-			     REGFI_ENCODING output_encoding, 
-			     bool strict);
+                         REGFI_ENCODING output_encoding, 
+                         bool strict);
 
 
@@ -1584,8 +1606,6 @@
 
 /******************************************************************************/
-/*    Private Functions                                                       */
-/******************************************************************************/
-REGFI_NK*             regfi_rootkey(REGFI_FILE* file);
-
+/*    Private (and undocumented) Functions                                    */
+/******************************************************************************/
 off_t                 regfi_raw_seek(REGFI_RAW_FILE* self, 
 				     off_t offset, int whence);
Index: /trunk/lib/regfi.c
===================================================================
--- /trunk/lib/regfi.c	(revision 214)
+++ /trunk/lib/regfi.c	(revision 215)
@@ -1670,5 +1670,5 @@
  * rest of the file if that fails.
  ******************************************************************************/
-REGFI_NK* regfi_rootkey(REGFI_FILE* file)
+const REGFI_NK* regfi_get_rootkey(REGFI_FILE* file)
 {
   REGFI_NK* nk = NULL;
@@ -1695,5 +1695,5 @@
    */
   
-  if(!regfi_read_lock(file, &file->hbins_lock, "regfi_rootkey"))
+  if(!regfi_read_lock(file, &file->hbins_lock, "regfi_get_rootkey"))
     return NULL;
 
@@ -1705,5 +1705,5 @@
   }
 
-  if(!regfi_rw_unlock(file, &file->hbins_lock, "regfi_rootkey"))
+  if(!regfi_rw_unlock(file, &file->hbins_lock, "regfi_get_rootkey"))
     return NULL;
 
@@ -1727,4 +1727,7 @@
 {
   uint32_t num_in_list = 0;
+  if(key == NULL)
+    return 0;
+
   if(key->subkeys != NULL)
     num_in_list = key->subkeys->num_keys;
@@ -1747,4 +1750,7 @@
 {
   uint32_t num_in_list = 0;
+  if(key == NULL)
+    return 0;
+
   if(key->values != NULL)
     num_in_list = key->values->num_values;
@@ -1773,5 +1779,5 @@
     return NULL;
 
-  root = regfi_rootkey(file);
+  root = (REGFI_NK*)regfi_get_rootkey(file);
   if(root == NULL)
   {
@@ -1906,6 +1912,8 @@
 
   if(path[x] == NULL)
+  {
     return true;
-  
+  }
+
   /* XXX: is this the right number of times? */
   for(; x > 0; x--)
@@ -2212,5 +2220,4 @@
 
 
-
 /******************************************************************************
  *****************************************************************************/
@@ -2227,4 +2234,22 @@
   return NULL;  
 }
+
+
+
+/******************************************************************************
+ *****************************************************************************/
+const REGFI_NK* regfi_get_parentkey(REGFI_FILE* file, const REGFI_NK* key)
+{
+  if(key != NULL && key->parent_off != REGFI_OFFSET_NONE)
+  {
+    /*    fprintf(stderr, "key->parent_off=%.8X\n", key->parent_off);*/
+    return regfi_load_key(file, 
+                          key->parent_off+REGFI_REGF_SIZE,
+                          file->string_encoding, true);
+  }
+  
+  return NULL;
+}
+
 
 
Index: /trunk/python/pyregfi/__init__.py
===================================================================
--- /trunk/python/pyregfi/__init__.py	(revision 214)
+++ /trunk/python/pyregfi/__init__.py	(revision 215)
@@ -31,4 +31,7 @@
 regfi.regfi_log_set_mask.restype = c_bool
 
+regfi.regfi_get_rootkey.argtypes = [POINTER(REGFI_FILE)]
+regfi.regfi_get_rootkey.restype = POINTER(REGFI_NK)
+
 regfi.regfi_free_record.argtypes = [c_void_p]
 regfi.regfi_free_record.restype = None
@@ -64,4 +67,7 @@
                                    c_uint32]
 regfi.regfi_get_value.restype = POINTER(REGFI_VK)
+
+regfi.regfi_get_parentkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
+regfi.regfi_get_parentkey.restype = POINTER(REGFI_NK)
 
 regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE), REGFI_ENCODING]
@@ -122,5 +128,5 @@
     if msgs == None:
         return ''
-    return msgs.decode('ascii')
+    return msgs.decode('utf-8')
 
 
@@ -132,4 +138,16 @@
     for i in range(0,length):
         ret_val[i] = char_pointer[i][0]
+
+    return ret_val
+
+
+def _strlist2charss(str_list):
+    ret_val = []
+    for s in str_list:
+        ret_val.append(s.encode('utf-8', 'replace'))
+
+    ret_val = (c_char_p*(len(str_list)+1))(*ret_val)
+    # Terminate the char** with a NULL pointer
+    ret_val[-1] = 0
 
     return ret_val
@@ -155,11 +173,17 @@
 
     def __init__(self, hive, base):
+        if not hive:
+            raise Exception("Could not create _StructureWrapper,"
+                            + " hive is NULL.  Current log:\n"
+                            + GetLogMessages())
+        if not base:
+            raise Exception("Could not create _StructureWrapper,"
+                            + " base is NULL.  Current log:\n"
+                            + GetLogMessages())
         self._hive = hive
-        # XXX: check for NULL here, throw an exception if so.
         self._base = base
 
     def __del__(self):
         regfi.regfi_free_record(self._base)
-        hive = None
 
     def __getattr__(self, name):
@@ -172,5 +196,4 @@
         return (not self.__eq__(other))
 
-## Registry key 
 class Key(_StructureWrapper):
     pass
@@ -248,5 +271,5 @@
 
         elem = self._get_element(self._hive.file, self._key._base,
-                                c_uint32(self._current))
+                                 c_uint32(self._current))
         self._current += 1
         return self._constructor(self._hive, elem)
@@ -268,4 +291,5 @@
 
 
+## Registry key 
 class Key(_StructureWrapper):
     values = None
@@ -295,5 +319,17 @@
     def fetch_security(self):
         return Security(self._hive,
-                        regfi.regfi_fetch_sk(self._hive.file, self.base))
+                        regfi.regfi_fetch_sk(self._hive.file, self._base))
+
+    def get_parent(self):
+        parent_base = regfi.regfi_get_parentkey(self._hive.file, self._base)
+        if parent_base:
+            return Key(self._hive, parent_base)
+
+        return None
+
+    def is_root(self):
+        # This is quicker than retrieving the root key for comparison and
+        # is more trustworthy than trusting the key's flags.
+        return ((self._hive.root_cell+REGFI_REGF_SIZE) == self.offset)
 
 
@@ -402,4 +438,8 @@
         return HiveIterator(self)
 
+    def get_root(self):
+        return Key(self, regfi.regfi_get_rootkey(self.file))
+
+
     ## Creates a @ref HiveIterator initialized at the specified path in
     #  the hive. 
@@ -479,12 +519,8 @@
 
     def descend(self, path):
-        #set up generator
-        cpath = (bytes(p,'ascii') for p in path) 
-
-        # evaluate generator and create char* array
-        apath = (c_char_p*len(path))(*cpath)
+        cpath = _strlist2charss(path)
 
         # XXX: Use non-generic exception
-        if not regfi.regfi_iterator_walk_path(self.iter,apath):
+        if not regfi.regfi_iterator_walk_path(self.iter, cpath):
             raise Exception('Could not locate path.\n'+GetLogMessages())
 
Index: /trunk/python/pyregfi/structures.py
===================================================================
--- /trunk/python/pyregfi/structures.py	(revision 214)
+++ /trunk/python/pyregfi/structures.py	(revision 215)
@@ -13,4 +13,5 @@
 
 REGFI_DATA_TYPE = c_uint32
+REGFI_REGF_SIZE = 0x1000 
 
 # Registry value data types
