Index: /test/pyregfi-smoketest.py
===================================================================
--- /test/pyregfi-smoketest.py	(revision 212)
+++ /test/pyregfi-smoketest.py	(revision 213)
@@ -1,39 +1,67 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import sys
+import gc
 import pyregfi
 
-files = sys.argv[1:]
+def usage():
+    sys.stderr.write("USAGE: pyregfi-smoketest.py hive1 [hive2 ...]\n")
 
 
-def iter_values(key):
-    i = 0
-    for value in key.values():
-        i += 1
-        
-    return i
+# Uses the HiveIterator to walk all keys
+# Gathers various (meaningless) statistics to exercise simple attribute access
+# and to hopefully smoke out any bugs that can be identified by changing stats
+def iterTally(hive):
+    key_count = 0
+    key_lens = 0
+    key_rawlens = 0
+    value_count = 0
+    value_lens = 0
+    value_rawlens = 0
+
+    for k in hive:
+        key_count += 1
+        if k.name != None:
+            key_lens += len(k.name)
+        if k.name_raw != None:
+            key_rawlens += len(k.name_raw)
+
+        for v in k.values:
+            value_count += 1
+            if v.name != None:
+                value_lens += len(v.name)
+            if v.name_raw != None:
+                value_rawlens += len(v.name_raw)
+
+    print("  Counts: keys=%d, values=%d\n" % (key_count, value_count))
+    print("  Total name length: keys=%d, values=%d\n" % (key_lens, value_lens))
+    print("  Total raw name lengths: keys=%d, values=%d\n" % (key_rawlens, value_rawlens))
 
 
-for f in files:
-    rf = pyregfi.RegistryFile(f)
-    iter = rf.TreeIterator()
 
-    num_keys = 0
-    num_values = 0
-    # The iterator now walks the entire registry hive, depth-first
-    for key in iter:
-        #print key.key.keyname
-        num_keys +=1
-        num_values += iter_values(key)
+if len(sys.argv) < 2:
+    usage()
+    sys.exit(1)
 
-    print "keys: %d" % num_keys
-    print "values: %d" % num_values
+files = []
+for f in sys.argv[1:]:
+    files.append((f, open(f,"r+b")))
 
+tests = [("iterTally",iterTally),]
 
-iter = rf.TreeIterator()
-root = iter.current()
-for key in root.subkeys():
-    for subkey in key.subkeys():
-        for subsubkey in subkey.subkeys():
-            print key.key.keyname
+for hname,fh in files:
+    hive = pyregfi.Hive(fh)
+    for tname,t in tests:
+        tstr = "'%s' on '%s'" % (tname,hname)
+        print("##BEGIN %s:" % tstr)
+        t(hive)
+        print("##END %s; messages:" % tstr)
+        print(pyregfi.GetLogMessages())
+        print
+    hive = None
+    gc.collect()
 
+files = None
+tests = None
+gc.collect()
+print gc.garbage
Index: /trunk/lib/regfi.c
===================================================================
--- /trunk/lib/regfi.c	(revision 212)
+++ /trunk/lib/regfi.c	(revision 213)
@@ -1780,5 +1780,5 @@
   }
   ret_val->cur_key = root;
-  talloc_reference(ret_val, root);
+  talloc_reparent(NULL, ret_val, root);
 
   ret_val->key_positions = void_stack_new(REGFI_MAX_DEPTH);
@@ -1834,5 +1834,5 @@
     return false;
   }
-  talloc_reference(i, subkey);
+  talloc_reparent(NULL, i, subkey);
 
   i->cur_key = subkey;
@@ -1920,5 +1920,5 @@
 const REGFI_NK* regfi_iterator_cur_key(REGFI_ITERATOR* i)
 {
-  /* XXX: do we need to add a NULL talloc reference here? */
+  talloc_reference(NULL, i->cur_key);
   return i->cur_key;
 }
Index: /trunk/python/pyregfi/__init__.py
===================================================================
--- /trunk/python/pyregfi/__init__.py	(revision 212)
+++ /trunk/python/pyregfi/__init__.py	(revision 213)
@@ -15,8 +15,8 @@
 
 
-regfi.regfi_alloc.argtypes = [c_int]
+regfi.regfi_alloc.argtypes = [c_int, REGFI_ENCODING]
 regfi.regfi_alloc.restype = POINTER(REGFI_FILE)
 
-regfi.regfi_alloc_cb.argtypes = [POINTER(REGFI_RAW_FILE)]
+regfi.regfi_alloc_cb.argtypes = [POINTER(REGFI_RAW_FILE), REGFI_ENCODING]
 regfi.regfi_alloc_cb.restype = POINTER(REGFI_FILE)
 
@@ -140,5 +140,5 @@
     s = chars_pointer[i]
     while s != None:
-        ret_val.append(s.decode('utf-8'))
+        ret_val.append(s.decode('utf-8', 'replace'))
         i += 1
         s = chars_pointer[i]
@@ -150,5 +150,4 @@
 #  access to base structures  
 class _StructureWrapper(object):
-
     hive = None
     base = None
@@ -161,4 +160,5 @@
     def __del__(self):
         regfi.regfi_free_record(self.base)
+        hive = None
 
     def __getattr__(self, name):
@@ -205,4 +205,7 @@
         self.length = self.fetch_num(key.base)
     
+    def __del__(self):
+        self.key = None
+
     def __len__(self):
         return self.length
@@ -274,5 +277,5 @@
                 ret_val = self.name_raw
             else:
-                ret_val = ret_val.decode('utf-8')
+                ret_val = ret_val.decode('utf-8', 'replace')
                 
         elif name == "name_raw":
@@ -307,5 +310,5 @@
             elif data_struct.type in (REG_SZ, REG_EXPAND_SZ, REG_LINK):
                 # Unicode strings
-                ret_val = data_struct.interpreted.string.decode('utf-8')
+                ret_val = data_struct.interpreted.string.decode('utf-8', 'replace')
             elif data_struct.type in (REG_DWORD, REG_DWORD_BE):
                 # 32 bit integers
@@ -343,5 +346,5 @@
                     ret_val = self.name_raw
                 else:
-                    ret_val = ret_val.decode('utf-8')
+                    ret_val = ret_val.decode('utf-8', 'replace')
 
             elif name == "name_raw":
@@ -370,5 +373,5 @@
         try:
             if hasattr(fh, 'fileno'):
-                self.file = regfi.regfi_alloc(fh.fileno())
+                self.file = regfi.regfi_alloc(fh.fileno(), REGFI_ENCODING_UTF8)
                 return
         except:
@@ -379,5 +382,5 @@
         self.raw_file.seek = seek_cb_type(self.raw_file.cb_seek)
         self.raw_file.read = read_cb_type(self.raw_file.cb_read)
-        self.file = regfi.regfi_alloc_cb(self.raw_file)
+        self.file = regfi.regfi_alloc_cb(self.raw_file, REGFI_ENCODING_UTF8)
 
     def __getattr__(self, name):
@@ -387,6 +390,5 @@
         regfi.regfi_free(self.file)
         if self.raw_file != None:
-            regfi.regfi_free(self.file)
-            
+            self.raw_file = None
 
     def __iter__(self):
@@ -421,6 +423,5 @@
 
     def __init__(self, hive):
-        # REGFI_ENCODING_UTF8==1
-        self.iter = regfi.regfi_iterator_new(hive.file, 1)
+        self.iter = regfi.regfi_iterator_new(hive.file, REGFI_ENCODING_UTF8)
         if self.iter == None:
             raise Exception("Could not create iterator.  Current log:\n"
@@ -432,5 +433,5 @@
 
     def __del__(self):    
-        regfi.regfi_iterator_free(self.iter)        
+        regfi.regfi_iterator_free(self.iter)
 
     def __iter__(self):
@@ -440,5 +441,5 @@
     def __next__(self):
         if self.iteration_root == None:
-            self.iteration_root = self.current_key()            
+            self.iteration_root = self.current_key()
         elif not regfi.regfi_iterator_down(self.iter):
             up_ret = regfi.regfi_iterator_up(self.iter)
Index: /trunk/python/pyregfi/structures.py
===================================================================
--- /trunk/python/pyregfi/structures.py	(revision 212)
+++ /trunk/python/pyregfi/structures.py	(revision 213)
@@ -10,4 +10,6 @@
 # XXX: can we always be sure enums are this size?
 REGFI_ENCODING = c_uint32
+REGFI_ENCODING_UTF8 = 1
+
 REGFI_DATA_TYPE = c_uint32
 
Index: /trunk/src/reglookup.c
===================================================================
--- /trunk/src/reglookup.c	(revision 212)
+++ /trunk/src/reglookup.c	(revision 213)
@@ -406,4 +406,5 @@
       if(cur != root)
       {
+        regfi_free_record(cur);
 	/* We're done with this sub-tree, going up and hitting other branches. */
 	if(!regfi_iterator_up(iter))
@@ -429,4 +430,5 @@
        * Let's move down and print this first sub-tree out. 
        */
+      regfi_free_record(cur);
       if(!regfi_iterator_down(iter))
       {
@@ -443,4 +445,5 @@
     printMsgs(iter->f);
   } while(!((cur == root) && (sub == NULL)));
+  regfi_free_record(root);
 
   if(print_verbose)
