Index: trunk/SConstruct
===================================================================
--- trunk/SConstruct	(revision 252)
+++ trunk/SConstruct	(revision 253)
@@ -61,5 +61,7 @@
 if sys.version_info[0] == 2:
    install_items.append('pyregfi2-install.log')
-   env.Command('pyregfi2-install.log', ['python/pyregfi/__init__.py', 'python/pyregfi/structures.py'], 
+   env.Command('pyregfi2-install.log', ['python/pyregfi/__init__.py', 
+                                        'python/pyregfi/structures.py', 
+                                        'python/pyregfi/winsec.py'],
                "python pyregfi-distutils.py install | tee pyregfi2-install.log")
 
@@ -67,5 +69,7 @@
 if python_path != '':
    install_items.append('pyregfi3-install.log')
-   env.Command('pyregfi3-install.log', ['python/pyregfi/__init__.py', 'python/pyregfi/structures.py'], 
+   env.Command('pyregfi3-install.log', ['python/pyregfi/__init__.py', 
+                                        'python/pyregfi/structures.py', 
+                                        'python/pyregfi/winsec.py'], 
                "python3 pyregfi-distutils.py install | tee pyregfi3-install.log")
 
Index: trunk/include/lru_cache.h
===================================================================
--- trunk/include/lru_cache.h	(revision 252)
+++ trunk/include/lru_cache.h	(revision 253)
@@ -37,9 +37,6 @@
 #include <talloc.h>
 
-/* GCC-specific macro for library exports */
-#ifdef _EXPORT
-#undef _EXPORT
-#endif
-#define _EXPORT __attribute__((visibility("default")))
+#include "compat.h"
+
 
 struct lru_cache_element;
@@ -74,5 +71,5 @@
  * XXX: finish documenting.
  */
-_EXPORT
+_EXPORT()
 lru_cache* lru_cache_create(uint32_t max_keys, uint32_t secret);
 
@@ -81,5 +78,5 @@
  * XXX: finish documenting.
  */
-_EXPORT
+_EXPORT()
 lru_cache* lru_cache_create_ctx(void* talloc_ctx, uint32_t max_keys, 
 				uint32_t secret, bool talloc_data);
@@ -89,5 +86,5 @@
  * XXX: finish documenting.
  */
-_EXPORT
+_EXPORT()
 void lru_cache_destroy(lru_cache* ht);
 
@@ -96,5 +93,5 @@
  * XXX: finish documenting.
  */
-_EXPORT
+_EXPORT()
 bool lru_cache_update(lru_cache* ht, const void* index, 
 		      uint32_t index_len, void* data);
@@ -106,5 +103,5 @@
  *         If no data was found at index, NULL is returned.
  */
-_EXPORT
+_EXPORT()
 void* lru_cache_find(lru_cache* ht, const void* index, 
 		     uint32_t index_len);
@@ -118,5 +115,5 @@
  *         at index.
  */
-_EXPORT
+_EXPORT()
 bool lru_cache_remove(lru_cache* ht, const void* index, 
 		      uint32_t index_len);
Index: trunk/include/range_list.h
===================================================================
--- trunk/include/range_list.h	(revision 252)
+++ trunk/include/range_list.h	(revision 253)
@@ -38,9 +38,5 @@
 #include <talloc.h>
 
-/* GCC-specific macro for library exports */
-#ifdef _EXPORT
-#undef _EXPORT
-#endif
-#define _EXPORT __attribute__((visibility("default")))
+#include "compat.h"
 
 typedef struct _range_list_element
@@ -65,5 +61,5 @@
  * @return A newly allocated range_list, or NULL if an error occurred.
  */
-_EXPORT
+_EXPORT()
 range_list* range_list_new();
 
@@ -76,5 +72,5 @@
  * @param rl the range_list to be free()d.
  */
-_EXPORT
+_EXPORT()
 void range_list_free(range_list* rl);
 
@@ -86,5 +82,5 @@
  * @return The number of elements currently in the list.
  */
-_EXPORT
+_EXPORT()
 uint32_t range_list_size(const range_list* rl);
 
@@ -106,5 +102,5 @@
  * errors may also be possible.
  */
-_EXPORT
+_EXPORT()
 bool range_list_add(range_list* rl, uint32_t offset, uint32_t length, void* data);
 
@@ -119,5 +115,5 @@
  * @return true if the element was successfully removed, false otherwise.
  */
-_EXPORT
+_EXPORT()
 bool range_list_remove(range_list* rl, uint32_t index);
 
@@ -131,5 +127,5 @@
  *         available.
  */
-_EXPORT
+_EXPORT()
 const range_list_element* range_list_get(const range_list* rl, uint32_t index);
 
@@ -142,5 +138,5 @@
  * @return A matching element index or a negative value if none could be found.
  */
-_EXPORT
+_EXPORT()
 int32_t range_list_find(const range_list* rl, uint32_t offset);
 
@@ -157,5 +153,5 @@
  *        element was never set.
  */
-_EXPORT
+_EXPORT()
 void* range_list_find_data(const range_list* rl, uint32_t offset);
 
@@ -179,5 +175,5 @@
  * @return true if the element was successfully split, false otherwise.
  */
-_EXPORT
+_EXPORT()
 bool range_list_split_element(range_list* rl, uint32_t index, uint32_t offset);
 
@@ -192,5 +188,5 @@
  * @return true if the specified range exists and is complete, false otherwise.
  */
-_EXPORT
+_EXPORT()
 bool range_list_has_range(range_list* rl, uint32_t start, uint32_t length);
 
Index: trunk/include/regfi.h
===================================================================
--- trunk/include/regfi.h	(revision 252)
+++ trunk/include/regfi.h	(revision 253)
@@ -74,23 +74,10 @@
 
 /* regfi headers */
-#include <byteorder.h>
-#include <winsec.h>
-#include <void_stack.h>
-#include <range_list.h>
-#include <lru_cache.h>
-
-/* GCC-specific macro for library exports */
-#ifdef _EXPORT
-#undef _EXPORT
-#endif
-#ifdef REGFI_WIN32
-#define _EXPORT() __declspec(dllexport)
-#else
-#define _EXPORT() __attribute__((visibility("default")))
-#endif
-
-#ifndef EOVERFLOW
-# define EOVERFLOW E2BIG
-#endif
+#include "compat.h"
+#include "byteorder.h"
+#include "winsec.h"
+#include "void_stack.h"
+#include "range_list.h"
+#include "lru_cache.h"
 
 /******************************************************************************/
@@ -1094,4 +1081,40 @@
 
 
+/** Returns the next SK (security) record referenced by the supplied SK record
+ *
+ * @param file the file from which sk is derived
+ * @param sk   the SK record whose next sibling SK record is desired
+ * 
+ * @return A read-only SK structure, or NULL on failure.
+ *
+ * @note
+ * SK records are included in a circular, doubly-linked list.
+ * To iterate over all SK records, be sure to check for the repetition of
+ * the SK record you started with to determine when all have been traversed.
+ *
+ * @ingroup regfiBase
+ */
+_EXPORT()
+const REGFI_SK* regfi_next_sk(REGFI_FILE* file, const REGFI_SK* sk);
+
+
+/** Returns the previous SK (security) record referenced by the supplied SK record
+ *
+ * @param file the file from which sk is derived
+ * @param sk   the SK record whose previous sibling SK record is desired
+ * 
+ * @return A read-only SK structure, or NULL on failure.
+ *
+ * @note
+ * SK records are included in a circular, doubly-linked list.
+ * To iterate over all SK records, be sure to check for the repetition of
+ * the SK record you started with to determine when all have been traversed.
+ *
+ * @ingroup regfiBase
+ */
+_EXPORT()
+const REGFI_SK* regfi_prev_sk(REGFI_FILE* file, const REGFI_SK* sk);
+
+
 /** Retrieves data for a given value.
  *
@@ -1542,5 +1565,5 @@
 _EXPORT()
 const REGFI_SK* regfi_load_sk(REGFI_FILE* file, uint32_t offset,
-				  bool strict);
+                              bool strict);
 
 
Index: trunk/include/void_stack.h
===================================================================
--- trunk/include/void_stack.h	(revision 252)
+++ trunk/include/void_stack.h	(revision 253)
@@ -34,9 +34,5 @@
 #include <talloc.h>
 
-/* GCC-specific macro for library exports */
-#ifdef _EXPORT
-#undef _EXPORT
-#endif
-#define _EXPORT __attribute__((visibility("default")))
+#include "compat.h"
 
 /** XXX: document this. */
@@ -65,5 +61,5 @@
  *         or NULL if an error occurred.
  */
-_EXPORT
+_EXPORT()
 void_stack* void_stack_new(unsigned short max_size);
 
@@ -75,5 +71,5 @@
  * @return a pointer to the duplicate void_stack, or NULL if an error occurred.
  */
-_EXPORT
+_EXPORT()
 void_stack* void_stack_copy(const void_stack* v);
 
@@ -86,5 +82,5 @@
  *         (which will be in reverse order), or NULL if an error occurred.
  */
-_EXPORT
+_EXPORT()
 void_stack* void_stack_copy_reverse(const void_stack* v);
 
@@ -95,5 +91,5 @@
  * @param stack the stack to be free()d.
  */
-_EXPORT
+_EXPORT()
 void void_stack_free(void_stack* stack);
 
@@ -108,5 +104,5 @@
  * @param stack the stack to be free()d.
  */
-_EXPORT
+_EXPORT()
 void void_stack_free_deep(void_stack* stack);
 
@@ -118,5 +114,5 @@
  * @return the number of elements currently on the stack.
  */
-_EXPORT
+_EXPORT()
 unsigned short void_stack_size(const void_stack* stack);
 
@@ -129,5 +125,5 @@
  *         on the stack.
  */
-_EXPORT
+_EXPORT()
 void* void_stack_pop(void_stack* stack);
 
@@ -140,5 +136,5 @@
  * @return true if the element was successfully added, false otherwise.
  */
-_EXPORT
+_EXPORT()
 bool void_stack_push(void_stack* stack, void* e);
 
@@ -151,5 +147,5 @@
  *         no elements exist in the stack.
  */
-_EXPORT
+_EXPORT()
 const void* void_stack_cur(const void_stack* stack);
 
@@ -161,5 +157,5 @@
  * @return a new void_stack_iterator, or NULL if an error occurred.
  */
-_EXPORT
+_EXPORT()
 void_stack_iterator* void_stack_iterator_new(const void_stack* stack);
 
@@ -171,5 +167,5 @@
  * @param iter the void_stack_iterator to be free()d.
  */
-_EXPORT
+_EXPORT()
 void void_stack_iterator_free(void_stack_iterator* iter);
 
@@ -183,5 +179,5 @@
  * @return a pointer to the next element.
  */
-_EXPORT
+_EXPORT()
 const void* void_stack_iterator_next(void_stack_iterator* iter);
 
Index: trunk/include/winsec.h
===================================================================
--- trunk/include/winsec.h	(revision 252)
+++ trunk/include/winsec.h	(revision 253)
@@ -46,11 +46,6 @@
 #include <talloc.h>
 
+#include "compat.h"
 #include "byteorder.h"
-
-/* GCC-specific macro for library exports */
-#ifdef _EXPORT
-#undef _EXPORT
-#endif
-#define _EXPORT __attribute__((visibility("default")))
 
 
@@ -223,5 +218,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 WINSEC_DESC* winsec_parse_descriptor(const uint8_t* buf, uint32_t buf_len);
 
@@ -231,5 +226,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 void winsec_free_descriptor(WINSEC_DESC* desc);
 
@@ -238,5 +233,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 WINSEC_DESC* winsec_parse_desc(void* talloc_ctx,
 			       const uint8_t* buf, uint32_t buf_len);
@@ -246,5 +241,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 WINSEC_ACL* winsec_parse_acl(void* talloc_ctx, 
 			     const uint8_t* buf, uint32_t buf_len);
@@ -254,5 +249,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 WINSEC_ACE* winsec_parse_ace(void* talloc_ctx, 
 			     const uint8_t* buf, uint32_t buf_len);
@@ -262,5 +257,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 WINSEC_DOM_SID* winsec_parse_dom_sid(void* talloc_ctx, 
 				     const uint8_t* buf, uint32_t buf_len);
@@ -270,5 +265,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 WINSEC_UUID* winsec_parse_uuid(void* talloc_ctx, 
 			       const uint8_t* buf, uint32_t buf_len);
@@ -279,5 +274,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 size_t winsec_sid_size(const WINSEC_DOM_SID* sid);
 
@@ -286,5 +281,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 int winsec_sid_compare_auth(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2);
 
@@ -293,5 +288,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 int winsec_sid_compare(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2);
 
@@ -300,5 +295,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 bool winsec_sid_equal(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2);
 
@@ -307,5 +302,12 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
+char* winsec_sid2str(const WINSEC_DOM_SID* sid);
+
+/**
+ *
+ * XXX: finish documenting
+ */
+_EXPORT()
 bool winsec_desc_equal(WINSEC_DESC* s1, WINSEC_DESC* s2);
 
@@ -314,5 +316,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 bool winsec_acl_equal(WINSEC_ACL* s1, WINSEC_ACL* s2);
 
@@ -321,5 +323,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 bool winsec_ace_equal(WINSEC_ACE* s1, WINSEC_ACE* s2);
 
@@ -328,5 +330,5 @@
  * XXX: finish documenting
  */
-_EXPORT
+_EXPORT()
 bool winsec_ace_object(uint8_t type);
 
Index: trunk/lib/regfi.c
===================================================================
--- trunk/lib/regfi.c	(revision 252)
+++ trunk/lib/regfi.c	(revision 253)
@@ -403,26 +403,4 @@
 
 
-char* regfi_sid2str(WINSEC_DOM_SID* sid)
-{
-  uint32_t i, size = WINSEC_MAX_SUBAUTHS*11 + 24;
-  uint32_t left = size;
-  uint8_t comps = sid->num_auths;
-  char* ret_val = malloc(size);
-  
-  if(ret_val == NULL)
-    return NULL;
-
-  if(comps > WINSEC_MAX_SUBAUTHS)
-    comps = WINSEC_MAX_SUBAUTHS;
-
-  left -= sprintf(ret_val, "S-%u-%u", sid->sid_rev_num, sid->id_auth[5]);
-
-  for (i = 0; i < comps; i++) 
-    left -= snprintf(ret_val+(size-left), left, "-%u", sid->sub_auths[i]);
-
-  return ret_val;
-}
-
-
 char* regfi_get_acl(WINSEC_ACL* acl)
 {
@@ -440,5 +418,5 @@
   for (i = 0; i < acl->num_aces && !failed; i++)
   {
-    sid_str = regfi_sid2str(acl->aces[i]->trustee);
+    sid_str = winsec_sid2str(acl->aces[i]->trustee);
     type_str = regfi_ace_type2str(acl->aces[i]->type);
     perms_str = regfi_ace_perms2str(acl->aces[i]->access_mask);
@@ -505,5 +483,5 @@
 char* regfi_get_owner(WINSEC_DESC *sec_desc)
 {
-  return regfi_sid2str(sec_desc->owner_sid);
+  return winsec_sid2str(sec_desc->owner_sid);
 }
 
@@ -511,5 +489,5 @@
 char* regfi_get_group(WINSEC_DESC *sec_desc)
 {
-  return regfi_sid2str(sec_desc->grp_sid);
+  return winsec_sid2str(sec_desc->grp_sid);
 }
 
@@ -1500,4 +1478,6 @@
     }
   }
+  else
+    ret_val = talloc_reference(NULL, ret_val);
 
  unlock:
@@ -2067,4 +2047,26 @@
 
   return regfi_load_sk(file, key->sk_off + REGFI_REGF_SIZE, true);
+}
+
+
+/******************************************************************************
+ *****************************************************************************/
+const REGFI_SK* regfi_next_sk(REGFI_FILE* file, const REGFI_SK* sk)
+{
+  if(sk == NULL || sk->next_sk_off == REGFI_OFFSET_NONE)
+    return NULL;
+
+  return regfi_load_sk(file, sk->next_sk_off + REGFI_REGF_SIZE, true);
+}
+
+
+/******************************************************************************
+ *****************************************************************************/
+const REGFI_SK* regfi_prev_sk(REGFI_FILE* file, const REGFI_SK* sk)
+{
+  if(sk == NULL || sk->prev_sk_off == REGFI_OFFSET_NONE)
+    return NULL;
+
+  return regfi_load_sk(file, sk->prev_sk_off + REGFI_REGF_SIZE, true);
 }
 
Index: trunk/lib/winsec.c
===================================================================
--- trunk/lib/winsec.c	(revision 252)
+++ trunk/lib/winsec.c	(revision 253)
@@ -226,5 +226,7 @@
   ret_val->size = SVAL(buf, 0x2);
   ret_val->access_mask = IVAL(buf, 0x4);
-
+  ret_val->obj_guid = NULL;
+  ret_val->inh_guid = NULL;
+  
   offset = 0x8;
 
@@ -246,6 +248,4 @@
       offset += sizeof(WINSEC_UUID);
     }
-    else
-      ret_val->obj_guid = NULL;
 
     if(ret_val->obj_flags & WINSEC_ACE_OBJECT_INHERITED_PRESENT)
@@ -260,6 +260,4 @@
       offset += sizeof(WINSEC_UUID);
     }
-    else
-      ret_val->inh_guid = NULL;
   }
 
@@ -410,4 +408,28 @@
 
 /******************************************************************************
+ ******************************************************************************/
+char* winsec_sid2str(const WINSEC_DOM_SID* sid)
+{
+  uint32_t i, size = WINSEC_MAX_SUBAUTHS*11 + 24;
+  uint32_t left = size;
+  uint8_t comps = sid->num_auths;
+  char* ret_val = malloc(size);
+  
+  if(ret_val == NULL)
+    return NULL;
+
+  if(comps > WINSEC_MAX_SUBAUTHS)
+    comps = WINSEC_MAX_SUBAUTHS;
+
+  left -= sprintf(ret_val, "S-%u-%u", sid->sid_rev_num, sid->id_auth[5]);
+
+  for (i = 0; i < comps; i++) 
+    left -= snprintf(ret_val+(size-left), left, "-%u", sid->sub_auths[i]);
+
+  return ret_val;
+}
+
+
+/******************************************************************************
  * Compares two WINSEC_DESC structures.
  ******************************************************************************/
Index: trunk/python/pyregfi/__init__.py
===================================================================
--- trunk/python/pyregfi/__init__.py	(revision 252)
+++ trunk/python/pyregfi/__init__.py	(revision 253)
@@ -295,8 +295,42 @@
 
 
-## Registry security record and descriptor
-# XXX: Access to security descriptors not yet implemented
+
+## Represents a registry SK record which contains a security descriptor
+# 
 class Security(_StructureWrapper):
-    pass
+    ## Number of keys referencing this SK record 
+    ref_count = 1
+
+    ## The absolute file offset of the SK record's cell in the Hive file
+    offset = 0xCAFEBABE
+
+    ## The @ref SecurityDescriptor for this SK record
+    descriptor = object()
+
+    def __init__(self, hive, base):
+        super(Security, self).__init__(hive, base)
+        # XXX: add checks for NULL pointers
+        self.descriptor = winsec.SecurityDescriptor(base.contents.sec_desc.contents)
+
+    ## Loads the "previous" Security record in the hive
+    #
+    # @note
+    # SK records are included in a circular, doubly-linked list.
+    # To iterate over all SK records, be sure to check for the repetition of
+    # the SK record you started with to determine when all have been traversed.
+    def next_security(self):
+        return Security(self._hive,
+                        regfi.regfi_next_sk(self._hive.file, self._base))
+
+    ## Loads the "previous" Security record in the hive
+    #
+    # @note
+    # SK records are included in a circular, doubly-linked list.
+    # To iterate over all SK records, be sure to check for the repetition of
+    # the SK record you started with to determine when all have been traversed.
+    def prev_security(self):
+        return Security(self._hive,
+                        regfi.regfi_prev_sk(self._hive.file, self._base))
+
 
 ## Abstract class for ValueList and SubkeyList
@@ -1038,2 +1072,3 @@
 del Key.name,Key.name_raw,Key.offset,Key.modified,Key.flags
 del Hive.root,Hive.modified,Hive.sequence1,Hive.sequence2,Hive.major_version,Hive.minor_version
+del Security.ref_count,Security.offset,Security.descriptor
Index: trunk/python/pyregfi/structures.py
===================================================================
--- trunk/python/pyregfi/structures.py	(revision 252)
+++ trunk/python/pyregfi/structures.py	(revision 253)
@@ -21,4 +21,6 @@
 REGFI_DATA_TYPE = c_uint32
 REGFI_NTTIME = c_uint64
+
+REGFI_REGF_SIZE = 0x1000
 
 # Prototype everything first so we don't have to worry about reference order
@@ -94,4 +96,6 @@
 read_cb_type = CB_FACTORY(c_int64, POINTER(REGFI_RAW_FILE), POINTER(c_char), c_size_t, use_errno=True)
 
+
+from winsec import *
 
 REGFI_VK._fields_ = [('offset', c_uint32),
@@ -113,5 +117,5 @@
 REGFI_SK._fields_ = [('offset', c_uint32),
                      ('cell_size', c_uint32),
-                     ('sec_desc', c_void_p), #XXX
+                     ('sec_desc', POINTER(WINSEC_DESC)),
                      ('hbin_off', c_uint32),
                      ('prev_sk_off', c_uint32),
@@ -261,4 +265,10 @@
 regfi.regfi_fetch_sk.restype = POINTER(REGFI_SK)
 
+regfi.regfi_next_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_SK)]
+regfi.regfi_next_sk.restype = POINTER(REGFI_SK)
+
+regfi.regfi_prev_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_SK)]
+regfi.regfi_prev_sk.restype = POINTER(REGFI_SK)
+
 regfi.regfi_fetch_data.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_VK)]
 regfi.regfi_fetch_data.restype = POINTER(REGFI_DATA)
@@ -283,5 +293,5 @@
 regfi.regfi_get_parentkey.restype = POINTER(REGFI_NK)
 
-regfi.regfi_nt2unix_time.argtypes = [POINTER(REGFI_NTTIME)]
+regfi.regfi_nt2unix_time.argtypes = [REGFI_NTTIME]
 regfi.regfi_nt2unix_time.restype = c_double
 
