Index: /trunk/include/compat.h
===================================================================
--- /trunk/include/compat.h	(revision 254)
+++ /trunk/include/compat.h	(revision 254)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2005-2010 Timothy D. Morgan
+ * Copyright (C) 2010 Michael Cohen
+ * Copyright (C) 2005 Gerald (Jerry) Carter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: regfi.h 252 2011-05-08 17:33:49Z tim $
+ */
+
+#ifndef _COMPAT_H
+#define _COMPAT_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
+
+#endif /*_COMPAT_H*/
Index: /trunk/python/pyregfi/winsec.py
===================================================================
--- /trunk/python/pyregfi/winsec.py	(revision 254)
+++ /trunk/python/pyregfi/winsec.py	(revision 254)
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+
+## @package pyregfi.winsec
+# Low-level data structures for winsec library
+#
+
+import sys
+import os
+import uuid
+import ctypes
+import ctypes.util
+from ctypes import *
+import structures
+
+is_win32 = hasattr(ctypes, 'windll')
+WINSEC_MAX_SUBAUTHS = 15
+
+if is_win32:
+    libc = cdll.msvcrt
+else:
+    libc = cdll.LoadLibrary("libc.so.6")
+
+class WINSEC_UUID(Structure):
+    pass
+
+class WINSEC_DOM_SID(Structure):
+    pass
+
+class WINSEC_ACE(Structure):
+    pass
+
+class WINSEC_ACL(Structure):
+    pass
+
+class WINSEC_DESC(Structure):
+    pass
+
+WINSEC_UUID._fields_ = [('time_low', c_uint32),
+                        ('time_mid', c_uint16),
+                        ('time_hi_and_version', c_uint16),
+                        ('clock_seq', c_uint8*2),
+                        ('node', c_uint8*6),
+                        ]
+
+WINSEC_DOM_SID._fields_ = [('sid_rev_num', c_uint8),
+                           ('num_auths', c_uint8),
+                           ('id_auths', c_uint8*6),
+                           ('sub_auths', c_uint32*WINSEC_MAX_SUBAUTHS),
+                           ]
+
+WINSEC_ACE._fields_ = [('type', c_uint8),
+                       ('flags', c_uint8),
+                       ('size', c_uint16),
+                       ('access_mask', c_uint32),
+                       ('obj_flags', c_uint32),
+                       ('obj_guid', POINTER(WINSEC_UUID)),
+                       ('inh_guid', POINTER(WINSEC_UUID)),
+                       ('trustee', POINTER(WINSEC_DOM_SID)),
+                       ]
+
+WINSEC_ACL._fields_ = [('revision', c_uint16),
+                       ('size', c_uint16),
+                       ('num_aces', c_uint32),
+                       ('aces', POINTER(POINTER(WINSEC_ACE))),
+                       ]
+
+WINSEC_DESC._fields_ = [('revision', c_uint8),
+                        ('sbz1', c_uint8),
+                        ('control', c_uint16),
+                        ('off_owner_sid', c_uint32),
+                        ('off_grp_sid', c_uint32),
+                        ('off_sacl', c_uint32),
+                        ('off_dacl', c_uint32),
+                        ('owner_sid', POINTER(WINSEC_DOM_SID)),
+                        ('grp_sid', POINTER(WINSEC_DOM_SID)),
+                        ('sacl', POINTER(WINSEC_ACL)),
+                        ('dacl', POINTER(WINSEC_ACL)),
+                        ]
+
+structures.regfi.winsec_sid2str.argtypes = [POINTER(WINSEC_DOM_SID)]
+structures.regfi.winsec_sid2str.restype = POINTER(c_char)
+
+
+def _guid2uuid(guid):
+    if not guid:
+        return None
+    return uuid.UUID(fields=(guid.contents.time_low,
+                             guid.contents.time_mid,
+                             guid.contents.time_hi_and_version,
+                             guid.contents.clock_seq[0],
+                             guid.contents.clock_seq[1],
+                             guid.contents.node[0]<<40
+                             ^ guid.contents.node[1]<<32
+                             ^ guid.contents.node[2]<<24
+                             ^ guid.contents.node[3]<<16
+                             ^ guid.contents.node[4]<<8
+                             ^ guid.contents.node[5]))
+
+## Represents a Microsoft access control entry, which are elements of access
+#  control lists
+#
+#  @note
+#  This interface is subject to change
+class ACE(object):
+    ## The type of entry as an integer
+    type = 1234
+    
+    ## The flags as an integer
+    flags = 0x1234
+
+    ## The access mask/permissions as an integer
+    access_mask = 0x1234
+
+    ## The trustee's SID as a string
+    trustee = "S-1-2..."
+    
+    ## The object GUID as a Python UUID
+    # May be None
+    object = uuid.UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
+
+    ## The inherited object GUID as a Python UUID
+    # May be None
+    inherited_object = uuid.UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
+
+    def __init__(self, ace):
+        # Just copy all of the values out so we don't need to manage memory
+        self.object = _guid2uuid(ace.obj_guid)
+        self.inherited_object = _guid2uuid(ace.inh_guid)
+
+        c_str = structures.regfi.winsec_sid2str(ace.trustee)
+        self.trustee = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
+        libc.free(c_str)
+
+        self.type = int(ace.type)
+        self.flags = int(ace.flags)
+        self.access_mask = int(ace.access_mask)
+
+
+class SecurityDescriptor(object):
+    ## The security descriptor's owner SID, as a string
+    owner = "S-1-2-..."
+
+    ## The security descriptor's group SID, as a string
+    group = "S-1-2-..."
+
+    ## A list of @ref ACE objects which represents the System ACL
+    # May be None if a sacl isn't defined
+    sacl = []
+
+    ## A list of @ref ACE objects which represents the User ACL
+    # May be None if a dacl isn't defined
+    dacl = []
+
+    def __init__(self, sec_desc):
+        c_str = structures.regfi.winsec_sid2str(sec_desc.owner_sid)
+        self.owner = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
+        libc.free(c_str)
+        
+        c_str = structures.regfi.winsec_sid2str(sec_desc.grp_sid)
+        self.group = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
+        libc.free(c_str)
+
+        # XXX: add checks for NULL pointers
+        self.sacl = None
+        if sec_desc.sacl:
+            self.sacl = []
+            for i in range(0,sec_desc.sacl.contents.num_aces):
+                self.sacl.append(ACE(sec_desc.sacl.contents.aces[i].contents))
+
+        self.dacl = None
+        if sec_desc.dacl:
+            self.dacl = []
+            for i in range(0,sec_desc.dacl.contents.num_aces):
+                self.dacl.append(ACE(sec_desc.dacl.contents.aces[i].contents))
+
+
+# Free class objects used for documentation
+del ACE.type,ACE.flags,ACE.access_mask,ACE.object,ACE.inherited_object
+del SecurityDescriptor.owner,SecurityDescriptor.group,SecurityDescriptor.sacl,SecurityDescriptor.dacl
