Index: trunk/python/pyregfi/__init__.py
===================================================================
--- trunk/python/pyregfi/__init__.py	(revision 204)
+++ trunk/python/pyregfi/__init__.py	(revision 205)
@@ -6,5 +6,5 @@
 import ctypes
 import ctypes.util
-from ctypes import c_char,c_char_p,c_int,POINTER
+from ctypes import c_char,c_char_p,c_int,c_uint16,c_bool,POINTER
 
 regfi = ctypes.CDLL(ctypes.util.find_library('regfi'), use_errno=True)
@@ -17,6 +17,71 @@
 regfi.regfi_alloc_cb.restype = POINTER(REGFI_FILE)
 
+regfi.regfi_free.argtypes = [POINTER(REGFI_FILE)]
+regfi.regfi_free.restype = None
+
 regfi.regfi_log_get_str.argtypes = []
 regfi.regfi_log_get_str.restype = c_char_p
+
+regfi.regfi_log_set_mask.argtypes = [c_uint16]
+regfi.regfi_log_set_mask.restype = c_bool
+
+regfi.regfi_free_record.argtypes = [c_void_p]
+regfi.regfi_free_record.restype = None
+
+regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE), REGFI_ENCODING]
+regfi.regfi_iterator_new.restype = POINTER(REGFI_ITERATOR)
+
+regfi.regfi_iterator_free.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_free.restype = None
+
+regfi.regfi_iterator_down.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_down.restype = c_bool
+
+regfi.regfi_iterator_up.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_up.restype = c_bool
+
+regfi.regfi_iterator_to_root.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_to_root.restype = c_bool
+
+regfi.regfi_iterator_walk_path.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_walk_path.restype = c_bool
+
+regfi.regfi_iterator_cur_key.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_cur_key.restype = POINTER(REGFI_NK)
+
+regfi.regfi_iterator_cur_sk.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_cur_sk.restype = POINTER(REGFI_SK)
+
+regfi.regfi_iterator_first_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_first_subkey.restype = c_bool
+
+regfi.regfi_iterator_cur_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_cur_subkey.restype = POINTER(REGFI_NK)
+
+regfi.regfi_iterator_next_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_next_subkey.restype = c_bool
+
+regfi.regfi_iterator_find_subkey.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
+regfi.regfi_iterator_find_subkey.restype = c_bool
+
+regfi.regfi_iterator_first_value.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_first_value.restype = c_bool
+
+regfi.regfi_iterator_cur_value.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_cur_value.restype = POINTER(REGFI_VK)
+
+regfi.regfi_iterator_next_value.argtypes = [POINTER(REGFI_ITERATOR)]
+regfi.regfi_iterator_next_value.restype = c_bool
+
+regfi.regfi_iterator_find_value.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
+regfi.regfi_iterator_find_value.restype = c_bool
+
+# XXX: possibly move REGFI_ENCODING to file object and eliminate need for ITERATOR here.
+regfi.regfi_iterator_fetch_classname.argtypes = [POINTER(REGFI_ITERATOR), POINTER(REGFI_NK)]
+regfi.regfi_iterator_fetch_classname.restype = POINTER(REGFI_CLASSNAME)
+
+regfi.regfi_iterator_fetch_data.argtypes = [POINTER(REGFI_ITERATOR), POINTER(REGFI_VK)]
+regfi.regfi_iterator_fetch_data.restype = POINTER(REGFI_DATA)
+
 
 regfi.regfi_init.argtypes = []
@@ -25,27 +90,81 @@
 
 
-class Hive(ctypes.Structure):
-    
+def GetLogMessages():
+    return regfi.regfi_log_get_str()
+
+
+class Hive():    
     file = None
     raw_file = None
     
     def __init__(self, fh):
+        # The fileno method may not exist, or it may thrown an exception
+        # when called if the file isn't backed with a descriptor.
+        try:
+            if hasattr(fh, 'fileno'):
+                self.file = regfi.regfi_alloc(fh.fileno())
+                return
+        except:
+            pass
         
-        if hasattr(fh, 'fileno') and 1==0:
-            self.file = regfi.regfi_alloc(fh.fileno())
-        else:
-            self.raw_file = structures.REGFI_RAW_FILE()
-            self.raw_file.fh = fh
-            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)
-            print(regfi.regfi_log_get_str())
+        self.raw_file = structures.REGFI_RAW_FILE()
+        self.raw_file.fh = fh
+        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)
 
     def __getattr__(self, name):
         return getattr(self.file.contents, name)
+    
+    def __del__(self):    
+        regfi.regfi_free(self.file)
+        if self.raw_file != None:
+            regfi.regfi_free(self.file)
+            
 
-    def test(self):
-        print(self.magic)
-        print(self.sequence1)
-        print(self.sequence2)
+    def __iter__(self):
+        return HiveIterator(self)
 
+
+class HiveIterator():
+    hive = None
+    iter = None
+    root_traversed = False
+
+    def __init__(self, hive):
+        # REGFI_ENCODING_UTF8==1
+        self.iter = regfi.regfi_iterator_new(hive.file, 1)
+        if self.iter == None:
+            raise Exception("Could not create iterator.  Current log:\n"
+                            + GetLogMessages())
+        self.hive = hive
+        
+    def __getattr__(self, name):
+        return getattr(self.file.contents, name)
+
+    def __del__(self):    
+        regfi.regfi_iterator_free(self.iter)        
+
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        if self.root_traversed:
+            self.root_traversed = True
+            
+        elif not regfi.regfi_iterator_down(self.iter):
+            up_ret = regfi.regfi_iterator_up(self.iter)
+            while up_ret and not regfi.regfi_iterator_next_subkey(self.iter):
+                up_ret = regfi.regfi_iterator_up(self.iter)
+
+            if not up_ret:
+                raise StopIteration('')
+            
+            if not regfi.regfi_iterator_down(self.iter):
+                raise Exception('Error traversing iterator downward.'+
+                                ' Current log:\n'+ GetLogMessages())
+
+        regfi.regfi_iterator_first_subkey(self.iter)
+        print(regfi.regfi_iterator_cur_key(self.iter).contents.keyname)
+        return regfi.regfi_iterator_cur_key(self.iter)
+
Index: trunk/python/pyregfi/structures.py
===================================================================
--- trunk/python/pyregfi/structures.py	(revision 204)
+++ trunk/python/pyregfi/structures.py	(revision 205)
@@ -6,8 +6,43 @@
 import ctypes
 import ctypes.util
-from ctypes import c_char,c_int,c_uint8,c_uint16,c_uint32,c_uint64,c_int64,POINTER,c_void_p,c_char_p
-
-
-class REGFI_RAW_FILE(ctypes.Structure):
+from ctypes import *
+
+# XXX: can we always be sure enums are this size?
+REGFI_ENCODING = c_uint32
+REGFI_DATA_TYPE = c_uint32
+
+
+# Prototype everything first so we don't have to worry about reference order
+class REGFI_NTTIME(Structure):
+    pass
+
+class REGFI_VK(Structure):
+    pass
+
+class REGFI_SK(Structure):
+    pass
+
+class REGFI_SUBKEY_LIST(Structure):
+    pass
+
+class REGFI_VALUE_LIST(Structure):
+    pass
+
+class REGFI_CLASSNAME(Structure):
+    pass
+
+class REGFI_DATA(Structure):
+    pass
+
+class REGFI_NK(Structure):
+    pass
+
+class REGFI_ITERATOR(Structure):
+    pass
+
+class REGFI_FILE(Structure):
+    pass
+
+class REGFI_RAW_FILE(Structure):
     fh = None
     
@@ -18,5 +53,5 @@
             traceback.print_exc()
             # XXX: os.EX_IOERR may not be available on Windoze
-            ctypes.set_errno(os.EX_IOERR)
+            set_errno(os.EX_IOERR)
             return -1
 
@@ -28,18 +63,139 @@
             # XXX: anyway to do a readinto() here?
             tmp = self.fh.read(count)
-            ctypes.memmove(buf,tmp,len(tmp))
+            memmove(buf,tmp,len(tmp))
 
         except Exception:
             traceback.print_exc()
             # XXX: os.EX_IOERR may not be available on Windoze
-            ctypes.set_errno(os.EX_IOERR)
+            set_errno(os.EX_IOERR)
             return -1
         return len(tmp)
 
 
-
 # XXX: how can we know for sure the size of off_t and size_t?
-seek_cb_type = ctypes.CFUNCTYPE(c_int64, POINTER(REGFI_RAW_FILE), c_uint64, c_int, use_errno=True)
-read_cb_type = ctypes.CFUNCTYPE(c_int64, POINTER(REGFI_RAW_FILE), POINTER(c_char), c_uint64, use_errno=True)
+seek_cb_type = CFUNCTYPE(c_int64, POINTER(REGFI_RAW_FILE), c_uint64, c_int, use_errno=True)
+read_cb_type = CFUNCTYPE(c_int64, POINTER(REGFI_RAW_FILE), POINTER(c_char), c_uint64, use_errno=True)
+
+
+REGFI_NTTIME._fields_ = [('low', c_uint32),
+                         ('high', c_uint32)]
+
+REGFI_VK._fields_ = [('offset', c_uint32),
+                     ('cell_size', c_uint32),
+                     ('valuename', c_char_p),
+                     ('valuename_raw', POINTER(c_char)),
+                     ('name_length', c_uint16),
+                     ('hbin_off', c_uint32),
+                     ('data_size', c_uint32),
+                     ('data_off', c_uint32),
+                     ('type', REGFI_DATA_TYPE),
+                     ('magic', c_char * 2),
+                     ('flags', c_uint16),
+                     ('unknown1', c_uint16),
+                     ('data_in_offset', c_bool),
+                     ]
+
+
+REGFI_SK._fields_ = [('offset', c_uint32),
+                     ('cell_size', c_uint32),
+                     ('sec_desc', c_void_p), #XXX
+                     ('hbin_off', c_uint32),
+                     ('prev_sk_off', c_uint32),
+                     ('next_sk_off', c_uint32),
+                     ('ref_count', c_uint32),
+                     ('desc_size', c_uint32),
+                     ('unknown_tag', c_uint16),
+                     ('magic', c_char * 2),
+                     ]
+
+
+REGFI_NK._fields_ = [('offset', c_uint32),
+                     ('cell_size', c_uint32),
+                     ('values', POINTER(REGFI_VALUE_LIST)),
+                     ('subkeys', POINTER(REGFI_SUBKEY_LIST)),
+                     ('flags', c_uint16),
+                     ('magic', c_char * 2),
+                     ('mtime', REGFI_NTTIME),
+                     ('name_length', c_uint16),
+                     ('classname_length', c_uint16),
+                     ('keyname', c_char_p),
+                     ('keyname_raw', POINTER(c_char)),
+                     ('parent_off', c_uint32),
+                     ('classname_off', c_uint32),
+                     ('max_bytes_subkeyname', c_uint32),
+                     ('max_bytes_subkeyclassname', c_uint32),
+                     ('max_bytes_valuename', c_uint32),
+                     ('max_bytes_value', c_uint32),
+                     ('unknown1', c_uint32),
+                     ('unknown2', c_uint32),
+                     ('unknown3', c_uint32),
+                     ('unk_index', c_uint32),
+                     ('num_subkeys', c_uint32),
+                     ('subkeys_off', c_uint32),
+                     ('num_values', c_uint32),
+                     ('values_off', c_uint32),
+                     ('sk_off', c_uint32),
+                     ]
+
+
+REGFI_SUBKEY_LIST._fields_ = [('offset', c_uint32),
+                              ('cell_size', c_uint32),
+                              ('num_children', c_uint32),
+                              ('num_keys', c_uint32),
+                              ('elements', c_void_p),
+                              ('magic', c_char * 2),
+                              ('recursive_type', c_bool),
+                              ]
+
+
+REGFI_VALUE_LIST._fields_ = [('offset', c_uint32),
+                             ('cell_size', c_uint32),
+                             ('num_children', c_uint32),
+                             ('num_values', c_uint32),
+                             ('elements', c_void_p),
+                             ]
+
+REGFI_CLASSNAME._fields_ = [('offset', c_uint32),
+                            ('interpreted', c_char_p),
+                            ('raw', POINTER(c_char)),
+                            ('size', c_uint16),
+                            ]
+
+
+class REGFI_DATA__interpreted(Union):
+    _fields_ = [('none',POINTER(c_char)),
+                ('string', c_char_p),
+                ('expand_string', c_char_p),
+                ('binary',POINTER(c_char)),
+                ('dword', c_uint32),
+                ('dword_be', c_uint32),
+                ('link', c_char_p),
+                ('multiple_string', POINTER(c_char_p)),
+                ('qword', c_uint64),
+                ('resource_list',POINTER(c_char)),
+                ('full_resource_descriptor',POINTER(c_char)),
+                ('resource_requirements_list',POINTER(c_char)),
+                ]    
+REGFI_DATA._fields_ = [('offset', c_uint32),
+                       ('type', REGFI_DATA_TYPE),
+                       ('size', c_uint32),
+                       ('raw', POINTER(c_char)),
+                       ('interpreted_size', c_uint32),
+                       ('interpreted', REGFI_DATA__interpreted),
+                       ]
+
+   
+REGFI_FILE._fields_ = [('magic', c_char * 4),
+                       ('sequence1', c_uint32),
+                       ('sequence2', c_uint32),
+                       ('mtime', REGFI_NTTIME),
+                       ('major_version', c_uint32),
+                       ('minor_version', c_uint32),
+                       ('type', c_uint32),
+                       ('format', c_uint32),
+                       ('root_cell', c_uint32),
+                       ('last_block', c_uint32),
+                       ('cluster', c_uint32),
+                       ]
 
 
@@ -50,20 +206,2 @@
                            ('state', c_void_p),
                            ]
-
-
-class REGFI_FILE(ctypes.Structure):
-    _fields_ = [('magic', c_char * 4),
-                ('sequence1', c_uint32),
-                ('sequence2', c_uint32),
-                ('mtime', c_uint64),
-                ('major_version', c_uint32),
-                ('minor_version', c_uint32),
-                ('type', c_uint32),
-                ('format', c_uint32),
-                ('root_cell', c_uint32),
-                ('last_block', c_uint32),
-                ('cluster', c_uint32),
-                ]
-
-
-
