Index: /trunk/include/regfi.h
===================================================================
--- /trunk/include/regfi.h	(revision 133)
+++ /trunk/include/regfi.h	(revision 134)
@@ -1,8 +1,7 @@
 /*
- * Branched from Samba project, Subversion repository version #6903:
+ * Branched from Samba project Subversion repository, version #6903:
  *   http://viewcvs.samba.org/cgi-bin/viewcvs.cgi/trunk/source/include/regfio.h?rev=6903&view=auto
  *
- * Unix SMB/CIFS implementation.
- * Windows NT registry I/O library
+ * Windows NT (and later) registry parsing library
  *
  * Copyright (C) 2005-2009 Timothy D. Morgan
@@ -11,5 +10,5 @@
  * 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 2 of the License.
+ * the Free Software Foundation; version 3 of the License.
  *
  * This program is distributed in the hope that it will be useful,
@@ -191,5 +190,5 @@
   uint32 cell_size;	/* ((start_offset - end_offset) & 0xfffffff8) */
 
-  SEC_DESC* sec_desc;
+  WINSEC_DESC* sec_desc;
   uint32 hbin_off;	/* offset from beginning of this hbin block */
   
@@ -316,8 +315,8 @@
 int                   regfi_type_str2val(const char* str);
 
-char*                 regfi_get_sacl(SEC_DESC* sec_desc);
-char*                 regfi_get_dacl(SEC_DESC* sec_desc);
-char*                 regfi_get_owner(SEC_DESC* sec_desc);
-char*                 regfi_get_group(SEC_DESC* sec_desc);
+char*                 regfi_get_sacl(WINSEC_DESC* sec_desc);
+char*                 regfi_get_dacl(WINSEC_DESC* sec_desc);
+char*                 regfi_get_owner(WINSEC_DESC* sec_desc);
+char*                 regfi_get_group(WINSEC_DESC* sec_desc);
 
 REGF_FILE*            regfi_open(const char* filename);
Index: /trunk/include/smb_deps.h
===================================================================
--- /trunk/include/smb_deps.h	(revision 133)
+++ /trunk/include/smb_deps.h	(revision 134)
@@ -29,4 +29,5 @@
 #include <stdlib.h>
 #include <stdbool.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <string.h>
@@ -46,12 +47,9 @@
 /* From includes.h */
 
-#define uint8 unsigned char
-#define int16 short
-#define uint16 unsigned short
-#define int32 int
-#define uint32 unsigned int
-
-#define SMB_STRUCT_STAT struct stat
-#define QSORT_CAST (int (*)(const void *, const void *))
+#define uint8  uint8_t
+#define int16  int8_t
+#define uint16 uint16_t
+#define int32  int32_t
+#define uint32 uint32_t
 
 #define MIN(a,b) ((a)<(b)?(a):(b))
@@ -59,17 +57,4 @@
 
 extern int DEBUGLEVEL;
-
-#define DLIST_ADD(list, p) \
-{ \
-        if (!(list)) { \
-		(list) = (p); \
-		(p)->next = (p)->prev = NULL; \
-	} else { \
-		(list)->prev = (p); \
-		(p)->next = (list); \
-		(p)->prev = NULL; \
-		(list) = (p); \
-	}\
-}
 
 /* End of stuff from includes.h */
@@ -84,49 +69,4 @@
 
 /* End of stuff from smb.h */
-
-/* From smb_macros.h */
-
-#define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
-#define SMB_MALLOC_P(type) (type *)malloc_(sizeof(type))
-#define TALLOC_ARRAY(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
-#define TALLOC_ZERO_ARRAY(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
-#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
-
-/* End of stuff from smb_macros.h */
-
-/* From ntdomain.h */
-
-struct uuid {
-       uint32 time_low;
-       uint16 time_mid;
-       uint16 time_hi_and_version;
-       uint8  clock_seq[2];
-       uint8  node[6];
-};
-
-typedef struct _prs_struct {
-	bool io; /* parsing in or out of data stream */
-	/* 
-	 * If the (incoming) data is big-endian. On output we are
-	  * always little-endian.
-	   */ 
-	   bool bigendian_data;
-	   uint8 align; /* data alignment */
-	   bool is_dynamic; /* Do we own this memory or not ? */
-	   uint32 data_offset; /* Current working offset into data. */
-	   uint32 buffer_size; /* Current allocated size of the buffer. */
-	   uint32 grow_size; /* size requested via prs_grow() calls */
-	   char *data_p; /* The buffer itself. */
-	   void *mem_ctx; /* When unmarshalling, use this.... */
-} prs_struct;
-
-#define MARSHALL 0
-#define UNMARSHALL 1
-
-#define RPC_LITTLE_ENDIAN  0
-#define RPC_PARSE_ALIGN    4
-
-/* End of stuff from ntdomain.h */
-
 
 /* From lib/time.c */
@@ -143,46 +83,3 @@
 /* End of stuff from lib/time.c */
 
-/* From rpc_dce.h */
-
-#define MAX_PDU_FRAG_LEN 0x10b8 /* this is what w2k sets */
-
-/* End of stuff from rpc_dce.h */
-
-/* From parse_prs.h */
-
-bool prs_grow(prs_struct *ps, uint32 extra_space);
-bool prs_align(prs_struct *ps);
-bool prs_init(prs_struct *ps, uint32 size, void *ctx, bool io);
-char *prs_mem_get(prs_struct *ps, uint32 extra_size);
-bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32);
-bool prs_uint32s(const char *name, prs_struct *ps, 
-		 int depth, uint32 *data32s, int len);
-bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16);
-bool prs_uint16_pre(const char *name, prs_struct *ps, int depth, 
-		    uint16 *data16, uint32 *offset);
-bool prs_uint16_post(const char *name, prs_struct *ps, int depth, 
-		     uint16 *data16, uint32 ptr_uint16, uint32 start_offset);
-bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8);
-bool prs_uint8s(const char *name, prs_struct *ps, int depth, 
-		uint8* data8s, int len);
-bool prs_set_offset(prs_struct *ps, uint32 offset);
-
-/* End of stuff from parse_prs.h */
-
-
-/* From pstring.h */
-
-#define FSTRING_LEN 256
-typedef char fstring[FSTRING_LEN];
-
-/* End of stuff from pstring.h */
-
-/* From rpc_parse/parse_misc.c */
-
-bool smb_io_uuid(const char *desc, struct uuid *uuid, 
-		 prs_struct *ps, int depth);
-bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth);
-
-/* End of stuff from rpc_parse/parse_misc.c */
-
 #endif /* _SMB_DEPS_H */
Index: /trunk/include/winsec.h
===================================================================
--- /trunk/include/winsec.h	(revision 133)
+++ /trunk/include/winsec.h	(revision 134)
@@ -3,4 +3,8 @@
  * Security Descriptors. See:
  *   http://websvn.samba.org/cgi-bin/viewcvs.cgi/trunk/source/
+ *
+ * Revisions have been made based on information provided by Microsoft
+ * at: 
+ *    http://msdn.microsoft.com/en-us/library/cc230366(PROT.10).aspx
  *
  * Copyright (C) 2005,2009 Timothy D. Morgan
@@ -23,6 +27,10 @@
  */
 
+#ifndef _WINSEC_H
+#define _WINSEC_H
+
 #include <stdlib.h>
 #include <stdbool.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <string.h>
@@ -36,99 +44,121 @@
 
 
-#define MAXSUBAUTHS 15
+/* This is the maximum number of subauths in a SID, as defined here:
+ *   http://msdn.microsoft.com/en-us/library/cc230371(PROT.10).aspx
+ */
+#define WINSEC_MAX_SUBAUTHS 15
 
-#define SEC_DESC_HEADER_SIZE     (2 * sizeof(uint16) + 4 * sizeof(uint32))
-                                 /*thanks for Jim McDonough <jmcd@us.ibm.com>*/
-#define SEC_DESC_DACL_PRESENT    0x0004
-#define SEC_DESC_SACL_PRESENT    0x0010
+#define WINSEC_DESC_HEADER_SIZE     (5 * sizeof(uint32_t))
+#define WINSEC_ACL_HEADER_SIZE      (2 * sizeof(uint32_t))
+#define WINSEC_ACE_MIN_SIZE         16
 
-#define SEC_ACE_OBJECT_PRESENT              0x00000001 
-#define SEC_ACE_OBJECT_INHERITED_PRESENT    0x00000002
-#define SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT  0x5
-#define SEC_ACE_TYPE_ACCESS_DENIED_OBJECT   0x6
-#define SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT    0x7
-#define SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT    0x8
+/* TODO: Fill in definitions of other flags */
+/* This means offsets contained in the descriptor are relative to the
+ * descriptor's offset.  This had better be true in the registry. 
+ */
+#define WINSEC_DESC_SELF_RELATIVE   0x8000
+#define WINSEC_DESC_SACL_PRESENT    0x0010
+#define WINSEC_DESC_DACL_PRESENT    0x0004
+
+#define WINSEC_ACE_OBJECT_PRESENT              0x00000001 
+#define WINSEC_ACE_OBJECT_INHERITED_PRESENT    0x00000002
+#define WINSEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT  0x5
+#define WINSEC_ACE_TYPE_ACCESS_DENIED_OBJECT   0x6
+#define WINSEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT    0x7
+#define WINSEC_ACE_TYPE_SYSTEM_ALARM_OBJECT    0x8
 
 
-typedef struct sid_info
+typedef struct _winsec_uuid 
 {
-  uint8  sid_rev_num;             /**< SID revision number */
-  uint8  num_auths;               /**< Number of sub-authorities */
-  uint8  id_auth[6];              /**< Identifier Authority */
+       uint32 time_low;
+       uint16 time_mid;
+       uint16 time_hi_and_version;
+       uint8  clock_seq[2];
+       uint8  node[6];
+} WINSEC_UUID;
+
+
+typedef struct _winsec_sid
+{
+  uint8_t  sid_rev_num;             /* SID revision number */
+  uint8_t  num_auths;               /* Number of sub-authorities */
+  uint8_t  id_auth[6];              /* Identifier Authority */
   /*
    *  Pointer to sub-authorities.
    *
-   * @note The values in these uint32's are in *native* byteorder, not
+   * @note The values in these uint32_t's are in *native* byteorder, not
    * neccessarily little-endian...... JRA.
    */
-  uint32 sub_auths[MAXSUBAUTHS];
-} DOM_SID;
+  /* XXX: Make this dynamically allocated? */
+  uint32_t sub_auths[WINSEC_MAX_SUBAUTHS];
+} WINSEC_DOM_SID;
 
 
-typedef struct security_info_info
+typedef struct _winsec_ace
 {
-	uint32 mask;
-
-} SEC_ACCESS;
-
-typedef struct security_ace_info
-{
-	uint8 type;  /* xxxx_xxxx_ACE_TYPE - e.g allowed / denied etc */
-	uint8 flags; /* xxxx_INHERIT_xxxx - e.g OBJECT_INHERIT_ACE */
-	uint16 size;
-
-	SEC_ACCESS info;
+	uint8_t type;  /* xxxx_xxxx_ACE_TYPE - e.g allowed / denied etc */
+	uint8_t flags; /* xxxx_INHERIT_xxxx - e.g OBJECT_INHERIT_ACE */
+	uint16_t size;
+	uint32_t access_mask;
 
 	/* this stuff may be present when type is XXXX_TYPE_XXXX_OBJECT */
-	uint32  obj_flags; /* xxxx_ACE_OBJECT_xxxx e.g present/inherited present etc */
-	struct uuid obj_guid;  /* object GUID */
-	struct uuid inh_guid;  /* inherited object GUID */		
+	uint32_t  obj_flags;   /* xxxx_ACE_OBJECT_xxxx e.g present/inherited present etc */
+	WINSEC_UUID* obj_guid;  /* object GUID */
+	WINSEC_UUID* inh_guid;  /* inherited object GUID */		
         /* eof object stuff */
 
-	DOM_SID trustee;
+	WINSEC_DOM_SID* trustee;
 
-} SEC_ACE;
+} WINSEC_ACE;
 
-typedef struct security_acl_info
+typedef struct _winsec_acl
 {
-	uint16 revision; /* 0x0003 */
-	uint16 size; /* size in bytes of the entire ACL structure */
-	uint32 num_aces; /* number of Access Control Entries */
+	uint16_t revision; /* 0x0003 */
+	uint16_t size;     /* size in bytes of the entire ACL structure */
+	uint32_t num_aces; /* number of Access Control Entries */
 
-	SEC_ACE *ace;
+	WINSEC_ACE** aces;
 
-} SEC_ACL;
+} WINSEC_ACL;
 
-typedef struct security_descriptor_info
+typedef struct _winsec_desc
 {
-	uint16 revision; /* 0x0001 */
-	uint16 type;     /* SEC_DESC_xxxx flags */
+	uint8_t revision; /* 0x01 */
+	uint8_t sbz1;     /* "If the Control field has the RM flag set,
+			   *  then this field contains the resource
+			   *  manager (RM) control value. ... Otherwise,
+			   *  this field is reserved and MUST be set to
+			   *  zero." -- Microsoft.  See reference above.
+			   */
+	uint16_t control; /* WINSEC_DESC_* flags */
 
-	uint32 off_owner_sid; /* offset to owner sid */
-	uint32 off_grp_sid  ; /* offset to group sid */
-	uint32 off_sacl     ; /* offset to system list of permissions */
-	uint32 off_dacl     ; /* offset to list of permissions */
+	uint32_t off_owner_sid; /* offset to owner sid */
+	uint32_t off_grp_sid  ; /* offset to group sid */
+	uint32_t off_sacl     ; /* offset to system list of permissions */
+	uint32_t off_dacl     ; /* offset to list of permissions */
 
-	SEC_ACL *dacl; /* user ACL */
-	SEC_ACL *sacl; /* system ACL */
-	DOM_SID *owner_sid; 
-	DOM_SID *grp_sid;
+	WINSEC_DOM_SID* owner_sid; 
+	WINSEC_DOM_SID* grp_sid;
+	WINSEC_ACL* sacl;       /* system ACL */
+	WINSEC_ACL* dacl;       /* user ACL */
 
-} SEC_DESC;
+} WINSEC_DESC;
 
 
+/* XXX: Need API functions to deallocate these structures */
+WINSEC_DESC* winsec_parse_desc(const uint8_t* buf, uint32_t buf_len);
+WINSEC_ACL* winsec_parse_acl(const uint8_t* buf, uint32_t buf_len);
+WINSEC_ACE* winsec_parse_ace(const uint8_t* buf, uint32_t buf_len);
+WINSEC_DOM_SID* winsec_parse_dom_sid(const uint8_t* buf, uint32_t buf_len);
+WINSEC_UUID* winsec_parse_uuid(const uint8_t* buf, uint32_t buf_len);
 
-bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth);
-bool sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth);
-bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth);
-bool sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth);
-bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth);
+size_t winsec_sid_size(const WINSEC_DOM_SID* sid);
+int winsec_sid_compare_auth(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2);
+int winsec_sid_compare(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2);
+bool winsec_sid_equal(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2);
+bool winsec_desc_equal(WINSEC_DESC* s1, WINSEC_DESC* s2);
+bool winsec_acl_equal(WINSEC_ACL* s1, WINSEC_ACL* s2);
+bool winsec_ace_equal(WINSEC_ACE* s1, WINSEC_ACE* s2);
+bool winsec_ace_object(uint8_t type);
 
-size_t sid_size(const DOM_SID *sid);
-int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2);
-int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2);
-bool sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2);
-bool sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2);
-bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2);
-bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2);
-bool sec_ace_object(uint8 type);
+#endif /* _WINSEC_H */
Index: /trunk/lib/regfi.c
===================================================================
--- /trunk/lib/regfi.c	(revision 133)
+++ /trunk/lib/regfi.c	(revision 134)
@@ -3,6 +3,5 @@
  *   http://viewcvs.samba.org/cgi-bin/viewcvs.cgi/trunk/source/registry/regfio.c?rev=7470&view=auto
  *
- * Unix SMB/CIFS implementation.
- * Windows NT registry parsing library
+ * Windows NT (and later) registry parsing library
  *
  * Copyright (C) 2005-2009 Timothy D. Morgan
@@ -226,7 +225,7 @@
 
 
-char* regfi_sid2str(DOM_SID* sid)
-{
-  uint32 i, size = MAXSUBAUTHS*11 + 24;
+char* regfi_sid2str(WINSEC_DOM_SID* sid)
+{
+  uint32 i, size = WINSEC_MAX_SUBAUTHS*11 + 24;
   uint32 left = size;
   uint8 comps = sid->num_auths;
@@ -236,6 +235,6 @@
     return NULL;
 
-  if(comps > MAXSUBAUTHS)
-    comps = MAXSUBAUTHS;
+  if(comps > WINSEC_MAX_SUBAUTHS)
+    comps = WINSEC_MAX_SUBAUTHS;
 
   left -= sprintf(ret_val, "S-%u-%u", sid->sid_rev_num, sid->id_auth[5]);
@@ -248,5 +247,5 @@
 
 
-char* regfi_get_acl(SEC_ACL* acl)
+char* regfi_get_acl(WINSEC_ACL* acl)
 {
   uint32 i, extra, size = 0;
@@ -263,8 +262,8 @@
   for (i = 0; i < acl->num_aces && !failed; i++)
   {
-    sid_str = regfi_sid2str(&acl->ace[i].trustee);
-    type_str = regfi_ace_type2str(acl->ace[i].type);
-    perms_str = regfi_ace_perms2str(acl->ace[i].info.mask);
-    flags_str = regfi_ace_flags2str(acl->ace[i].flags);
+    sid_str = regfi_sid2str(acl->aces[i]->trustee);
+    type_str = regfi_ace_type2str(acl->aces[i]->type);
+    perms_str = regfi_ace_perms2str(acl->aces[i]->access_mask);
+    flags_str = regfi_ace_flags2str(acl->aces[i]->flags);
     
     if(flags_str != NULL && perms_str != NULL 
@@ -307,5 +306,5 @@
 
 
-char* regfi_get_sacl(SEC_DESC *sec_desc)
+char* regfi_get_sacl(WINSEC_DESC *sec_desc)
 {
   if (sec_desc->sacl)
@@ -316,5 +315,5 @@
 
 
-char* regfi_get_dacl(SEC_DESC *sec_desc)
+char* regfi_get_dacl(WINSEC_DESC *sec_desc)
 {
   if (sec_desc->dacl)
@@ -325,5 +324,5 @@
 
 
-char* regfi_get_owner(SEC_DESC *sec_desc)
+char* regfi_get_owner(WINSEC_DESC *sec_desc)
 {
   return regfi_sid2str(sec_desc->owner_sid);
@@ -331,5 +330,5 @@
 
 
-char* regfi_get_group(SEC_DESC *sec_desc)
+char* regfi_get_group(WINSEC_DESC *sec_desc)
 {
   return regfi_sid2str(sec_desc->grp_sid);
@@ -447,6 +446,11 @@
 {
   uint32 i,j,k;
-  REGF_SUBKEY_LIST* ret_val = (REGF_SUBKEY_LIST*)zalloc(sizeof(REGF_SUBKEY_LIST));
-  if(ret_val == NULL || lists == NULL)
+  REGF_SUBKEY_LIST* ret_val;
+
+  if(lists == NULL)
+    return NULL;
+  ret_val = (REGF_SUBKEY_LIST*)zalloc(sizeof(REGF_SUBKEY_LIST));
+
+  if(ret_val == NULL)
     return NULL;
   
@@ -457,6 +461,7 @@
     if(lists[i] == NULL)
     {
-      ret_val->num_keys = 0;
-      break;
+      free(ret_val);
+      free(lists);
+      return NULL;
     }
     ret_val->num_keys += lists[i]->num_keys;
@@ -469,4 +474,5 @@
 				     * ret_val->num_keys);
     k=0;
+
     if(ret_val->elements != NULL)
     {
@@ -498,5 +504,5 @@
   REGF_SUBKEY_LIST** sublists;
   REGF_HBIN* sublist_hbin;
-  uint32 i, cell_length, length, num_sublists, off, max_length;
+  uint32 i, cell_length, length, num_sublists, off, max_length, elem_size;
   uint8* hashes;
   uint8 buf[REGFI_SUBKEY_LIST_MIN_LEN];
@@ -541,6 +547,17 @@
       sublists[i] = regfi_load_subkeylist(file, off, 0, max_length, strict);
     }
-    
+    free(hashes);
+
     return regfi_merge_subkeylists(num_sublists, sublists, strict);
+  }
+
+  if(buf[0] == 'l' && buf[1] == 'i')
+    elem_size = sizeof(uint32);
+  else if((buf[0] == 'l') && (buf[1] == 'f' || buf[1] == 'h'))
+    elem_size = sizeof(REGF_SUBKEY_LIST_ELEM);
+  else
+  {
+    /* fprintf(stderr, "DEBUG: lf->header=%c%c\n", buf[0], buf[1]);*/
+    return NULL;
   }
 
@@ -551,12 +568,4 @@
   ret_val->offset = offset;
   ret_val->cell_size = cell_length;
-
-  if((buf[0] != 'l' || buf[1] != 'f') && (buf[0] != 'l' || buf[1] != 'h'))
-  {
-    /*printf("DEBUG: lf->header=%c%c\n", buf[0], buf[1]);*/
-    free(ret_val);
-    return NULL;
-  }
-
   ret_val->magic[0] = buf[0];
   ret_val->magic[1] = buf[1];
@@ -579,9 +588,14 @@
 
   if(cell_length - REGFI_SUBKEY_LIST_MIN_LEN - sizeof(uint32) 
-     < ret_val->num_keys*sizeof(REGF_SUBKEY_LIST_ELEM))
-    return NULL;
-
-  length = sizeof(REGF_SUBKEY_LIST_ELEM)*ret_val->num_keys;
-  ret_val->elements = (REGF_SUBKEY_LIST_ELEM*)zalloc(length);
+     < ret_val->num_keys*elem_size)
+  {
+    free(ret_val);
+    return NULL;
+  }
+
+  length = elem_size*ret_val->num_keys;
+  ret_val->elements 
+    = (REGF_SUBKEY_LIST_ELEM*)zalloc(ret_val->num_keys 
+				     * sizeof(REGF_SUBKEY_LIST_ELEM));
   if(ret_val->elements == NULL)
   {
@@ -599,5 +613,5 @@
 
   if(regfi_read(file->fd, hashes, &length) != 0
-     || length != sizeof(REGF_SUBKEY_LIST_ELEM)*ret_val->num_keys)
+     || length != elem_size*ret_val->num_keys)
   {
     free(ret_val->elements);
@@ -606,8 +620,19 @@
   }
 
-  for (i=0; i < ret_val->num_keys; i++)
-  {
-    ret_val->elements[i].nk_off = IVAL(hashes, i*sizeof(REGF_SUBKEY_LIST_ELEM));
-    ret_val->elements[i].hash = IVAL(hashes, i*sizeof(REGF_SUBKEY_LIST_ELEM)+4);
+  if(buf[0] == 'l' && buf[1] == 'i')
+  {
+    for (i=0; i < ret_val->num_keys; i++)
+    {
+      ret_val->elements[i].nk_off = IVAL(hashes, i*elem_size);
+      ret_val->elements[i].hash = 0;
+    }
+  }
+  else
+  {
+    for (i=0; i < ret_val->num_keys; i++)
+    {
+      ret_val->elements[i].nk_off = IVAL(hashes, i*elem_size);
+      ret_val->elements[i].hash = IVAL(hashes, i*elem_size+4);
+    }
   }
   free(hashes);
@@ -623,9 +648,9 @@
 {
   REGF_SK_REC* ret_val;
+  uint8* sec_desc_buf;
   uint32 cell_length, length;
-  prs_struct ps;
+  /*prs_struct ps;*/
   uint8 sk_header[REGFI_SK_MIN_LENGTH];
   bool unalloc = false;
-
 
   if(!regfi_parse_cell(file->fd, offset, sk_header, REGFI_SK_MIN_LENGTH,
@@ -674,4 +699,5 @@
    * code depends on the ps structure.
    */
+  /*
   if(!prs_init(&ps, ret_val->desc_size, NULL, UNMARSHALL))
   {
@@ -687,14 +713,30 @@
     return NULL;
   }
-
-  /* XXX: call should look more like: */
-  /*if (!(ret_val->sec_desc = winsec_parse_desc(sec_desc_buf, ret_val->desc_size)))*/
-  if (!sec_io_desc("sec_desc", &ret_val->sec_desc, &ps, 0))
-  {
-    free(ret_val);
-    return NULL;
-  }
-
-  free(ps.data_p);
+  */
+
+  sec_desc_buf = (uint8*)zalloc(ret_val->desc_size);
+  if(ret_val == NULL)
+  {
+    free(ret_val);
+    return NULL;
+  }
+
+  length = ret_val->desc_size;
+  if(regfi_read(file->fd, sec_desc_buf, &length) != 0 
+     || length != ret_val->desc_size)
+  {
+    free(ret_val);
+    return NULL;
+  }
+
+  if(!(ret_val->sec_desc = winsec_parse_desc(sec_desc_buf, ret_val->desc_size)))
+  {
+    free(sec_desc_buf);
+    free(ret_val);
+    return NULL;
+  }
+  free(sec_desc_buf);
+
+  /*  free(ps.data_p);*/
 
   return ret_val;
@@ -893,6 +935,7 @@
       off = nk->subkeys_off + REGF_BLOCKSIZE;
       max_length = sub_hbin->block_size + sub_hbin->file_off - off;
-      nk->subkeys = regfi_load_subkeylist(file, off, nk->num_subkeys, 
+      nk->subkeys = regfi_load_subkeylist(file, off, nk->num_subkeys,
 					  max_length, true);
+
       if(nk->subkeys == NULL)
       {
Index: /trunk/lib/smb_deps.c
===================================================================
--- /trunk/lib/smb_deps.c	(revision 133)
+++ /trunk/lib/smb_deps.c	(revision 134)
@@ -142,416 +142,2 @@
 
 /* End of stuff from lib/time.c */
-
-/* From parse_prs.c */
-
-/*******************************************************************
- Attempt, if needed, to grow a data buffer.
- Also depends on the data stream mode (io).
- ********************************************************************/
-bool prs_grow(prs_struct *ps, uint32 extra_space)
-{
-  uint32 new_size;
-  char *new_data;
-  
-  ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space);
-  
-  if(ps->data_offset + extra_space <= ps->buffer_size)
-    return true;
-  
-  /*
-   * We cannot grow the buffer if we're not reading
-   * into the prs_struct, or if we don't own the memory.
-   */
-  
-  if(ps->io || !ps->is_dynamic)
-    return false;
-  
-  /*
-   * Decide how much extra space we really need.
-   */
-  extra_space -= (ps->buffer_size - ps->data_offset);
-  if(ps->buffer_size == 0) 
-  {
-    /*
-     * Ensure we have at least a PDU's length, or extra_space, 
-     * whichever is greater.
-     */  
-    new_size = MAX(MAX_PDU_FRAG_LEN,extra_space);
-    
-    if((new_data = zalloc(new_size)) == NULL)
-      return false;
-  } 
-  else 
-  {
-    /*
-     * If the current buffer size is bigger than the space needed, just 
-     * double it, else add extra_space.
-     */
-    new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space);		
-    
-    if ((new_data = (char*)realloc(ps->data_p, new_size)) == NULL)
-      return false;
-    
-    memset(&new_data[ps->buffer_size], '\0', 
-	   (size_t)(new_size - ps->buffer_size));
-  }
-  ps->buffer_size = new_size;
-  ps->data_p = new_data;
-  
-  return true;
-}
-
-
-/*******************************************************************
- Align a the data_len to a multiple of align bytes - filling with
- zeros.
- ********************************************************************/
-bool prs_align(prs_struct *ps)
-{
-  uint32 mod = ps->data_offset & (ps->align-1);
-  
-  if (ps->align != 0 && mod != 0) 
-  {
-    uint32 extra_space = (ps->align - mod);
-    if(!prs_grow(ps, extra_space))
-      return false;
-    memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space);
-    ps->data_offset += extra_space;
-  }
-  
-  return true;
-}
-
-
-/**
- * Initialise an expandable parse structure.
- *
- * @param size Initial buffer size.  If >0, a new buffer will be
- * created with malloc().
- *
- * @return false if allocation fails, otherwise true.
- **/
-
-bool prs_init(prs_struct *ps, uint32 size, void *ctx, bool io)
-{
-  if(ps == NULL)
-    return false;
-  memset(ps, 0, sizeof(prs_struct));
-
-  ps->io = io;
-  ps->bigendian_data = RPC_LITTLE_ENDIAN;
-  ps->align = RPC_PARSE_ALIGN;
-  ps->is_dynamic = false;
-  ps->data_offset = 0;
-  ps->buffer_size = 0;
-  ps->data_p = NULL;
-  ps->mem_ctx = ctx;
-  
-  if (size != 0) 
-  {
-    ps->buffer_size = size;
-    if((ps->data_p = (char *)zalloc((size_t)size)) == NULL)
-      return false;
-
-    ps->is_dynamic = true; /* We own this memory. */
-  }
-  
-  return true;
-}
-
-
-char *prs_mem_get(prs_struct *ps, uint32 extra_size)
-{
-  if(ps->io) 
-  {
-    /*
-     * If reading, ensure that we can read the requested size item.
-     */
-    if (ps->data_offset + extra_size > ps->buffer_size)
-      return NULL;
-  } 
-  else 
-  {
-    /*
-     * Writing - grow the buffer if needed.
-     */
-    if(!prs_grow(ps, extra_size))
-      return NULL;
-  }
-
-  return &ps->data_p[ps->data_offset];
-}
-
-
-/*******************************************************************
- Stream a uint32.
- ********************************************************************/
-bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32)
-{
-  char *q = prs_mem_get(ps, sizeof(uint32));
-  if (q == NULL)
-    return false;
-  
-  if (ps->io) 
-  {
-    if (ps->bigendian_data)
-      *data32 = RIVAL(q,0);
-    else
-      *data32 = IVAL(q,0);
-  } 
-  else 
-  {
-    if (ps->bigendian_data)
-      RSIVAL(q,0,*data32);
-    else
-      SIVAL(q,0,*data32);
-  }
-  ps->data_offset += sizeof(uint32);
-  
-  return true;
-}
-
-
-/******************************************************************
- Stream an array of uint32s. Length is number of uint32s.
- ********************************************************************/
-bool prs_uint32s(const char *name, prs_struct *ps, 
-		 int depth, uint32 *data32s, int len)
-{
-  int i;
-  char *q = prs_mem_get(ps, len * sizeof(uint32));
-  if (q == NULL)
-    return false;
-  
-  if (ps->io) 
-  {
-    if (ps->bigendian_data) 
-    {
-      for (i = 0; i < len; i++)
-	data32s[i] = RIVAL(q, 4*i);
-    } 
-    else 
-    {
-      for (i = 0; i < len; i++)
-	data32s[i] = IVAL(q, 4*i);
-    }
-  } 
-  else 
-  {
-    if (ps->bigendian_data) 
-    {
-      for (i = 0; i < len; i++)
-	RSIVAL(q, 4*i, data32s[i]);
-    } 
-    else 
-    {
-      for (i = 0; i < len; i++)
-	SIVAL(q, 4*i, data32s[i]);
-    }
-  }
-  ps->data_offset += (len * sizeof(uint32));
-  
-  return true;
-}
-
-
-/*******************************************************************
- Stream a uint16.
- ********************************************************************/
-bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16)
-{
-  char *q = prs_mem_get(ps, sizeof(uint16));
-  if (q == NULL)
-    return false;
-  
-  if (ps->io) 
-  {
-    if (ps->bigendian_data)
-      *data16 = RSVAL(q,0);
-    else
-      *data16 = SVAL(q,0);
-  } 
-  else 
-  {
-    if (ps->bigendian_data)
-      RSSVAL(q,0,*data16);
-    else
-      SSVAL(q,0,*data16);
-  }
-  ps->data_offset += sizeof(uint16);
-  
-  return true;
-}
-
-
-/*******************************************************************
- prs_uint16 wrapper. Call this and it sets up a pointer to where the
- uint16 should be stored, or gets the size if reading.
- ********************************************************************/
-bool prs_uint16_pre(const char *name, prs_struct *ps, int depth, 
-		    uint16 *data16, uint32 *offset)
-{
-  *offset = ps->data_offset;
-  if (ps->io) 
-  {
-    /* reading. */
-    return prs_uint16(name, ps, depth, data16);
-  } 
-  else 
-  {
-    char *q = prs_mem_get(ps, sizeof(uint16));
-    if(q ==NULL)
-      return false;
-    ps->data_offset += sizeof(uint16);
-  }
-  return true;
-}
-
-
-/*******************************************************************
- prs_uint16 wrapper.  call this and it retrospectively stores the size.
- does nothing on reading, as that is already handled by ...._pre()
- ********************************************************************/
-bool prs_uint16_post(const char *name, prs_struct *ps, int depth, 
-		     uint16 *data16, uint32 ptr_uint16, uint32 start_offset)
-{
-  if (!ps->io) 
-  {
-    /* 
-     * Writing - temporarily move the offset pointer.
-     */
-    uint16 data_size = ps->data_offset - start_offset;
-    uint32 old_offset = ps->data_offset;
-    
-    ps->data_offset = ptr_uint16;
-    if(!prs_uint16(name, ps, depth, &data_size)) 
-    {
-      ps->data_offset = old_offset;
-      return false;
-    }
-    ps->data_offset = old_offset;
-  } 
-  else 
-    ps->data_offset = start_offset + (uint32)(*data16);
-
-  return true;
-}
-
-
-/*******************************************************************
- Stream a uint8.
- ********************************************************************/
-bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8)
-{
-  char *q = prs_mem_get(ps, 1);
-  if (q == NULL)
-    return false;
-  
-  if (ps->io)
-    *data8 = CVAL(q,0);
-  else
-    SCVAL(q,0,*data8);
-  
-  ps->data_offset += 1;
-  
-  return true;
-}
-
-
-/******************************************************************
- Stream an array of uint8s. Length is number of uint8s.
- ********************************************************************/
-bool prs_uint8s(const char *name, prs_struct *ps, int depth, 
-		uint8* data8s, int len)
-{
-  int i;
-  char *q = prs_mem_get(ps, len);
-  if (q == NULL)
-    return false;
-  
-  if (ps->io) 
-  {
-    for (i = 0; i < len; i++)
-      data8s[i] = CVAL(q,i);
-  } 
-  else 
-  {
-    for (i = 0; i < len; i++)
-      SCVAL(q, i, data8s[i]);
-  }
-  
-  ps->data_offset += len;
-  
-  return true;
-}
-
-
-/*******************************************************************
- Set the current offset (external interface).
- ********************************************************************/
-bool prs_set_offset(prs_struct *ps, uint32 offset)
-{
-  if(offset <= ps->data_offset) 
-  {
-    ps->data_offset = offset;
-    return true;
-  }
-  
-  if(!prs_grow(ps, offset - ps->data_offset))
-    return false;
-  
-  ps->data_offset = offset;
-  return true;
-}
-
-/* End of stuff from parse_prs.c */
-
-/* From rpc_parse/parse_misc.c */
-
-/*******************************************************************
- Reads or writes a struct uuid
-********************************************************************/
-bool smb_io_uuid(const char *desc, struct uuid *uuid, 
-		 prs_struct *ps, int depth)
-{
-  if (uuid == NULL)
-    return false;
-  depth++;
-  
-  if(!prs_uint32 ("data   ", ps, depth, &uuid->time_low))
-    return false;
-  if(!prs_uint16 ("data   ", ps, depth, &uuid->time_mid))
-    return false;
-  if(!prs_uint16 ("data   ", ps, depth, &uuid->time_hi_and_version))
-    return false;
-  
-  if(!prs_uint8s ("data   ", ps, depth, 
-		  uuid->clock_seq, sizeof(uuid->clock_seq)))
-    return false;
-
-  if(!prs_uint8s ("data   ", ps, depth, uuid->node, sizeof(uuid->node)))
-    return false;
-  
-  return true;
-}
-
-
-/*******************************************************************
- Reads or writes an NTTIME structure.
-********************************************************************/
-bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth)
-{
-  if (nttime == NULL)
-    return false;
-  depth++;
-
-  if(!prs_align(ps))
-    return false;
-	
-  if(!prs_uint32("low ", ps, depth, &nttime->low)) /* low part */
-    return false;
-  if(!prs_uint32("high", ps, depth, &nttime->high)) /* high part */
-    return false;
-
-  return true;
-}
Index: /trunk/lib/winsec.c
===================================================================
--- /trunk/lib/winsec.c	(revision 133)
+++ /trunk/lib/winsec.c	(revision 134)
@@ -28,399 +28,312 @@
 
 
-/*******************************************************************
- * Parses a SEC_DESC structure.
- *******************************************************************/
-bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
-{
-  uint32 old_offset;
-  uint32 max_offset = 0; /* after we're done, move offset to end */
-  uint32 tmp_offset = 0;
-
-  SEC_DESC *psd;
-
-  if (ppsd == NULL || ps == NULL)
-    return false;
-
-  psd = *ppsd;
-  if (psd == NULL) 
-  {
-    if((psd = (SEC_DESC*)zalloc(sizeof(SEC_DESC))) == NULL)
-      return false;
-    *ppsd = psd;
-  }
-
-  depth++;
-
-  /* start of security descriptor stored for back-calc offset purposes */
-  old_offset = ps->data_offset;
-
-  if(!prs_uint16("revision ", ps, depth, &psd->revision)
-     || !prs_uint16("type     ", ps, depth, &psd->type))
-  {
-    free(psd);
-    *ppsd = NULL;
-    return false;
-  }
-
-  if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid)
-     || !prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid)
-     || !prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl)
-     || !prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
-  {
-    free(psd);
-    *ppsd = NULL;    
-    return false;
-  }
-  max_offset = MAX(max_offset, ps->data_offset);
-
-  if (psd->off_owner_sid != 0) 
-  {
-    tmp_offset = ps->data_offset;
-    if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
-    {
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-
-    /* reading */
-    if((psd->owner_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
-    {
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-
-    if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
-    {
-      free(psd->owner_sid);
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-
-    max_offset = MAX(max_offset, ps->data_offset);
-
-    if (!prs_set_offset(ps,tmp_offset))
-    {
-      free(psd->owner_sid);
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-  }
-
-  if (psd->off_grp_sid != 0) 
-  {
-    tmp_offset = ps->data_offset;
-    if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
-    {
-      free(psd->owner_sid);
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-
-    /* reading */
-    if((psd->grp_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
-    {
-      free(psd->owner_sid);
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-
-    if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
-    {
-      free(psd->grp_sid);
-      free(psd->owner_sid);
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-			
-    max_offset = MAX(max_offset, ps->data_offset);
-
-    if (!prs_set_offset(ps,tmp_offset))
-    {
-      free(psd->grp_sid);
-      free(psd->owner_sid);
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-  }
-
-  if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) 
-  {
-    tmp_offset = ps->data_offset;
-    if(!prs_set_offset(ps, old_offset + psd->off_sacl)
-       || !sec_io_acl("sacl", &psd->sacl, ps, depth))
-    {
-      free(psd->grp_sid);
-      free(psd->owner_sid);
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-    max_offset = MAX(max_offset, ps->data_offset);
-    if (!prs_set_offset(ps,tmp_offset))
-    {
-      free(psd->grp_sid);
-      free(psd->owner_sid);
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-  }
-
-  if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) 
-  {
-    tmp_offset = ps->data_offset;
-    if(!prs_set_offset(ps, old_offset + psd->off_dacl)
-       || !sec_io_acl("dacl", &psd->dacl, ps, depth))
-    {
-      free(psd->grp_sid);
-      free(psd->owner_sid);
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-    max_offset = MAX(max_offset, ps->data_offset);
-    if (!prs_set_offset(ps,tmp_offset))
-    {
-      free(psd->grp_sid);
-      free(psd->owner_sid);
-      free(psd);
-      *ppsd = NULL;
-      return false;
-    }
-  }
-
-  if(!prs_set_offset(ps, max_offset))
-  {
-    free(psd->grp_sid);
-    free(psd->owner_sid);
-    free(psd);
-    *ppsd = NULL;
-    return false;
-  }
-
-  return true;
-}
-
-
-/*******************************************************************
- Reads or writes a DOM_SID structure.
-********************************************************************/
-bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth)
-{
-  int i;
-
-  if (sid == NULL)
-    return false;
-  depth++;
-
-  if(!prs_uint8 ("sid_rev_num", ps, depth, &sid->sid_rev_num))
-    return false;
-
-  if(!prs_uint8 ("num_auths  ", ps, depth, &sid->num_auths))
-    return false;
-
-  for (i = 0; i < 6; i++)
-  {
-    fstring tmp;
-    snprintf(tmp, sizeof(tmp) - 1, "id_auth[%d] ", i);
-    if(!prs_uint8 (tmp, ps, depth, &sid->id_auth[i]))
-      return false;
-  }
-
-  /* oops! XXXX should really issue a warning here... */
-  if (sid->num_auths > MAXSUBAUTHS)
-    sid->num_auths = MAXSUBAUTHS;
-
-  if(!prs_uint32s("sub_auths ", ps, depth, 
-		  sid->sub_auths, sid->num_auths))
-  { return false; }
-
-  return true;
-}
-
-
-
-/*******************************************************************
- Reads or writes a SEC_ACCESS structure.
-********************************************************************/
-bool sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
-{
-  if (t == NULL)
-    return false;
-
-  depth++;
-	
-  if(!prs_uint32("mask", ps, depth, &t->mask))
-    return false;
-
-  return true;
-}
-
-
-/*******************************************************************
- Reads or writes a SEC_ACE structure.
-********************************************************************/
-bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
-{
-  uint32 old_offset;
-  uint32 offset_ace_size;
-
-  if (psa == NULL)
-    return false;
-
-  depth++;
-	
-  old_offset = ps->data_offset;
-
-  if(!prs_uint8("type ", ps, depth, &psa->type))
-    return false;
-
-  if(!prs_uint8("flags", ps, depth, &psa->flags))
-    return false;
-
-  if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
-    return false;
-
-  if(!sec_io_access("info ", &psa->info, ps, depth))
-    return false;
-
-  /* check whether object access is present */
-  if (!sec_ace_object(psa->type)) 
-  {
-    if (!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
-      return false;
-  } 
-  else 
-  {
-    if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags))
-      return false;
-
-    if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
-      if (!smb_io_uuid("obj_guid", &psa->obj_guid, ps,depth))
-	return false;
-
-    if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
-      if (!smb_io_uuid("inh_guid", &psa->inh_guid, ps,depth))
-	return false;
-
-    if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
-      return false;
-  }
-
-  if(!prs_uint16_post("size ", ps, depth, &psa->size, 
-		      offset_ace_size, old_offset))
-  { return false; }
-
-  return true;
-}
-
-
-/*******************************************************************
- Reads or writes a SEC_ACL structure.  
-
- First of the xx_io_xx functions that allocates its data structures
- for you as it reads them.
-********************************************************************/
-bool sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
-{
-  unsigned int i;
-  uint32 old_offset;
-  uint32 offset_acl_size;
-  SEC_ACL* psa;
+/******************************************************************************
+ * Parses a WINSEC_DESC structure and substructures.
+ ******************************************************************************/
+WINSEC_DESC* winsec_parse_desc(const uint8_t* buf, uint32_t buf_len)
+{
+  WINSEC_DESC* ret_val;
+
+  if (buf == NULL || buf_len <  WINSEC_DESC_HEADER_SIZE)
+    return NULL;
+
+  if((ret_val = (WINSEC_DESC*)zalloc(sizeof(WINSEC_DESC))) == NULL)
+    return NULL;
+
+  ret_val->revision = buf[0];
+  ret_val->sbz1 = buf[1];
+  ret_val->control = SVAL(buf, 0x2);
+
+  if(!(ret_val->control & WINSEC_DESC_SELF_RELATIVE))
+    fprintf(stderr, "DEBUG: NOT self-relative!\n");
+
+  ret_val->off_owner_sid = IVAL(buf, 0x4);
+  ret_val->off_grp_sid = IVAL(buf, 0x8);
+  ret_val->off_sacl = IVAL(buf, 0xC);
+  ret_val->off_dacl = IVAL(buf, 0x10);
+
+  /* A basic sanity check to ensure our offsets are within our buffer.
+   * Additional length checking is done in secondary parsing functions.
+   */
+  if((ret_val->off_owner_sid >= buf_len)
+     || (ret_val->off_grp_sid >= buf_len)
+     || (ret_val->off_sacl >= buf_len)
+     || (ret_val->off_dacl >= buf_len))
+  {
+    free(ret_val);
+    return NULL;
+  }
+
+  if(ret_val->off_owner_sid != 0)
+  {
+    ret_val->owner_sid = winsec_parse_dom_sid(buf + ret_val->off_owner_sid, 
+					      buf_len - ret_val->off_owner_sid);
+    if(ret_val->owner_sid == NULL)
+    {
+      free(ret_val);
+      return NULL;
+    }
+  }
+
+  if (ret_val->off_grp_sid != 0) 
+  {
+    ret_val->grp_sid = winsec_parse_dom_sid(buf + ret_val->off_grp_sid, 
+					    buf_len - ret_val->off_grp_sid);
+    if(ret_val->grp_sid == NULL)
+    {
+      if(ret_val->owner_sid != NULL)
+	free(ret_val->owner_sid);
+      free(ret_val);
+      return NULL;
+    }
+  }
+
+  if ((ret_val->control & WINSEC_DESC_SACL_PRESENT) && ret_val->off_sacl)
+  {
+    ret_val->sacl = winsec_parse_acl(buf + ret_val->off_sacl,
+				     buf_len - ret_val->off_sacl);
+    if(ret_val->sacl == NULL)
+    {
+      if(ret_val->owner_sid != NULL)
+	free(ret_val->owner_sid);
+      if(ret_val->grp_sid != NULL)
+	free(ret_val->grp_sid);
+      free(ret_val);
+      return NULL;
+    }
+  }
+
+  if ((ret_val->control & WINSEC_DESC_DACL_PRESENT) && ret_val->off_dacl != 0) 
+  {
+    ret_val->dacl = winsec_parse_acl(buf + ret_val->off_dacl,
+				     buf_len - ret_val->off_dacl);
+    if(ret_val->dacl == NULL)
+    {
+      if(ret_val->owner_sid != NULL)
+	free(ret_val->owner_sid);
+      if(ret_val->grp_sid != NULL)
+	free(ret_val->grp_sid);
+      if(ret_val->sacl != NULL)
+	free(ret_val->sacl);
+      free(ret_val);
+      return NULL;
+    }
+  }
+
+  return ret_val;
+}
+
+
+/******************************************************************************
+ * Parses a WINSEC_ACL structure and all substructures.
+ ******************************************************************************/
+WINSEC_ACL* winsec_parse_acl(const uint8_t* buf, uint32_t buf_len)
+{
+  uint32_t i, offset;
+  WINSEC_ACL* ret_val;
 
   /*
    * Note that the size is always a multiple of 4 bytes due to the
-   * nature of the data structure.  Therefore the prs_align() calls
-   * have been removed as they through us off when doing two-layer
-   * marshalling such as in the printing code (RPC_BUFFER).  --jerry
+   * nature of the data structure.
    */
-
-  if (ppsa == NULL || ps == NULL)
-    return false;
-
-  psa = *ppsa;
-
-  if(psa == NULL) 
-  {
-    /*
-     * This is a read and we must allocate the stuct to read into.
-     */
-    if((psa = (SEC_ACL*)zalloc(sizeof(SEC_ACL))) == NULL)
-      return false;
-    *ppsa = psa;
-  }
-
-  depth++;	
-  old_offset = ps->data_offset;
-
-  if(!prs_uint16("revision", ps, depth, &psa->revision)
-     || !prs_uint16_pre("size     ", ps, depth, &psa->size, &offset_acl_size)
-     || !prs_uint32("num_aces ", ps, depth, &psa->num_aces))
-  {
-    free(psa);
-    *ppsa = NULL;
-    return false;
-  }
-
-  /*
-   * Even if the num_aces is zero, allocate memory as there's a difference
+  if (buf == NULL || buf_len < 8)
+    return NULL;
+
+  if((ret_val = (WINSEC_ACL*)zalloc(sizeof(WINSEC_ACL))) == NULL)
+    return NULL;
+  
+  ret_val->revision = SVAL(buf, 0x0);
+  ret_val->size     = SVAL(buf, 0x2);
+  ret_val->num_aces = IVAL(buf, 0x4);
+
+  /* The num_aces can be at most around 4k because anything greater
+   * wouldn't fit in the 16 bit size even if every ace was as small as
+   * possible. 
+   */
+  if((ret_val->size > buf_len) || (ret_val->num_aces > 4095))
+  {
+    free(ret_val);
+    return NULL;
+  }
+
+  /* Even if the num_aces is zero, allocate memory as there's a difference
    * between a non-present DACL (allow all access) and a DACL with no ACE's
    * (allow no access).
    */
-  if((psa->ace = (SEC_ACE*)zcalloc(sizeof(SEC_ACE), psa->num_aces+1)) == NULL)
-  {
-    free(psa);
-    *ppsa = NULL;
-    return false;
-  }
-
-  for (i = 0; i < psa->num_aces; i++) 
-  {
-    fstring tmp;
-    snprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
-    if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
-    {
-      free(psa);
-      *ppsa = NULL;
-      return false;
-    }
-  }
-
-  if(!prs_uint16_post("size     ", ps, depth, &psa->size, 
-		      offset_acl_size, old_offset))
-  { 
-    free(psa);
-    *ppsa = NULL;
-    return false; 
-  }
-
-  return true;
-}
-
-
-/*****************************************************************
- Calculates size of a sid.
-*****************************************************************/  
-size_t sid_size(const DOM_SID *sid)
+  if((ret_val->aces = (WINSEC_ACE**)zcalloc(sizeof(WINSEC_ACE*),
+					   ret_val->num_aces+1)) == NULL)
+  {
+    free(ret_val);
+    return NULL;
+  }
+
+  offset = 8;
+  for(i=0; i < ret_val->num_aces; i++)
+  {
+    ret_val->aces[i] = winsec_parse_ace(buf+offset, buf_len-offset);
+    if(ret_val->aces[i] == NULL)
+    {
+      free(ret_val->aces);
+      free(ret_val);
+      return NULL;
+    }
+
+    offset += ret_val->aces[i]->size;
+    if(offset > buf_len)
+    {
+      free(ret_val->aces);
+      free(ret_val);
+      return NULL;
+    }
+  }
+
+  return ret_val;
+}
+
+
+/******************************************************************************
+ * Parses a WINSEC_ACE structure and all substructures.
+ ******************************************************************************/
+WINSEC_ACE* winsec_parse_ace(const uint8_t* buf, uint32_t buf_len)
+{
+  uint32_t offset;
+  WINSEC_ACE* ret_val;
+
+  if(buf == NULL || buf_len < WINSEC_ACE_MIN_SIZE)
+    return NULL;
+
+  if((ret_val = (WINSEC_ACE*)zalloc(sizeof(WINSEC_ACE))) == NULL)
+    return NULL;
+
+  ret_val->type = buf[0];
+  ret_val->flags = buf[1];
+  ret_val->size = SVAL(buf, 0x2);
+  ret_val->access_mask = IVAL(buf, 0x4);
+
+  offset = 0x8;
+
+  /* check whether object access is present */
+  if (winsec_ace_object(ret_val->type))
+  {
+    ret_val->obj_flags = IVAL(buf, offset);
+    offset += 4;
+
+    if(ret_val->obj_flags & WINSEC_ACE_OBJECT_PRESENT)
+    {
+      ret_val->obj_guid = winsec_parse_uuid(buf+offset, buf_len-offset);
+      if(ret_val->obj_guid == NULL)
+      {
+	free(ret_val);
+	return NULL;
+      }
+      offset += sizeof(WINSEC_UUID);
+    }
+
+    if(ret_val->obj_flags & WINSEC_ACE_OBJECT_INHERITED_PRESENT)
+    {
+      ret_val->inh_guid = winsec_parse_uuid(buf+offset, buf_len-offset);
+      if(ret_val->inh_guid == NULL)
+      {
+	if(ret_val->obj_guid != NULL)
+	  free(ret_val->obj_guid);
+	free(ret_val);
+	return NULL;
+      }
+      offset += sizeof(WINSEC_UUID);
+    }
+  }
+
+  ret_val->trustee = winsec_parse_dom_sid(buf+offset, buf_len-offset);
+  if(ret_val->trustee == NULL)
+  {
+    if(ret_val->obj_guid != NULL)
+      free(ret_val->obj_guid);
+    if(ret_val->inh_guid != NULL)
+      free(ret_val->inh_guid);
+    free(ret_val);
+	return NULL;
+  }
+  
+  return ret_val;
+}
+
+
+/******************************************************************************
+ * Parses a WINSEC_DOM_SID structure.
+ ******************************************************************************/
+WINSEC_DOM_SID* winsec_parse_dom_sid(const uint8_t* buf, uint32_t buf_len)
+{
+  uint32_t i;
+  WINSEC_DOM_SID* ret_val;
+
+  if(buf == NULL || buf_len < 8)
+    return NULL;
+
+  if((ret_val = (WINSEC_DOM_SID*)zalloc(sizeof(WINSEC_DOM_SID))) == NULL)
+    return NULL;
+
+  ret_val->sid_rev_num = buf[0];
+  ret_val->num_auths = buf[1];
+  memcpy(ret_val->id_auth, buf+2, 6);
+
+  /* XXX: should really issue a warning here... */
+  if (ret_val->num_auths > WINSEC_MAX_SUBAUTHS)
+    ret_val->num_auths = WINSEC_MAX_SUBAUTHS;
+
+  if(buf_len < ret_val->num_auths*sizeof(uint32_t)+8)
+  {
+    free(ret_val);
+    return NULL;
+  }
+  
+  for(i=0; i < ret_val->num_auths; i++)
+    ret_val->sub_auths[i] = IVAL(buf, 8+i*sizeof(uint32_t));
+
+  return ret_val;
+}
+
+
+/******************************************************************************
+ * Parses a WINSEC_UUID struct.
+ ******************************************************************************/
+WINSEC_UUID* winsec_parse_uuid(const uint8_t* buf, uint32_t buf_len)
+{
+  WINSEC_UUID* ret_val;
+
+  if(buf == NULL || buf_len < sizeof(WINSEC_UUID))
+    return false;
+
+  if((ret_val = (WINSEC_UUID*)zalloc(sizeof(WINSEC_UUID))) == NULL)
+    return NULL;
+  
+  ret_val->time_low = IVAL(buf, 0x0);
+  ret_val->time_mid = SVAL(buf, 0x4);
+  ret_val->time_hi_and_version = SVAL(buf, 0x6);
+  
+  memcpy(ret_val->clock_seq, buf+0x8, 2);
+  memcpy(ret_val->node, buf+0xB, 6);
+
+  return ret_val;
+}
+
+
+/******************************************************************************
+ * Calculates the size of a SID.
+ ******************************************************************************/
+/*size_t sid_size(const WINSEC_DOM_SID *sid)*/
+size_t winsec_sid_size(const WINSEC_DOM_SID* sid)
 {
   if (sid == NULL)
     return 0;
 
-  return sid->num_auths * sizeof(uint32) + 8;
-}
-
-
-/*****************************************************************
- Compare the auth portion of two sids.
-*****************************************************************/  
-int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
+  return sid->num_auths * sizeof(uint32_t) + 8;
+}
+
+
+/******************************************************************************
+ * Compare the auth portion of two SIDs.
+ ******************************************************************************/
+/*int sid_compare_auth(const WINSEC_DOM_SID *sid1, const WINSEC_DOM_SID *sid2)*/
+int winsec_sid_compare_auth(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2)
 {
   int i;
@@ -444,8 +357,9 @@
 
 
-/*****************************************************************
- Compare two sids.
-*****************************************************************/  
-int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
+/******************************************************************************
+ * Compare two SIDs.
+ ******************************************************************************/
+/*int sid_compare(const WINSEC_DOM_SID *sid1, const WINSEC_DOM_SID *sid2)*/
+int winsec_sid_compare(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2)
 {
   int i;
@@ -466,38 +380,64 @@
       return sid1->sub_auths[i] - sid2->sub_auths[i];
 
-  return sid_compare_auth(sid1, sid2);
-}
-
-
-/*****************************************************************
- Compare two sids.
-*****************************************************************/  
-bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
-{
-  return sid_compare(sid1, sid2) == 0;
-}
-
-
-
-/*******************************************************************
- Check if ACE has OBJECT type.
-********************************************************************/
-bool sec_ace_object(uint8 type)
-{
-  if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
-      type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
-      type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
-      type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
+  return winsec_sid_compare_auth(sid1, sid2);
+}
+
+
+/******************************************************************************
+ * Compare two SIDs.
+ ******************************************************************************/
+bool winsec_sid_equal(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2)
+{
+  return winsec_sid_compare(sid1, sid2) == 0;
+}
+
+
+/******************************************************************************
+ * Compares two WINSEC_DESC structures.
+ ******************************************************************************/
+bool winsec_desc_equal(WINSEC_DESC* s1, WINSEC_DESC* s2)
+{
+  /* Trivial cases */
+  if (!s1 && !s2)
     return true;
-  }
-  return false;
-}
-
-
-/*******************************************************************
- Compares two SEC_ACE structures
-********************************************************************/
-bool sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
-{
+  if (!s1 || !s2)
+    return false;
+
+  /* Check top level stuff */
+  if (s1->revision != s2->revision)
+    return false;
+
+  if (s1->control != s2->control)
+    return false;
+
+  /* Check owner and group */
+  if (!winsec_sid_equal(s1->owner_sid, s2->owner_sid))
+    return false;
+
+  if (!winsec_sid_equal(s1->grp_sid, s2->grp_sid)) 
+    return false;
+
+  /* Check ACLs present in one but not the other */
+  if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
+      (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) 
+  { return false; }
+
+  /* Sigh - we have to do it the hard way by iterating over all
+     the ACEs in the ACLs */
+  if(!winsec_acl_equal(s1->dacl, s2->dacl) || !winsec_acl_equal(s1->sacl, s2->sacl)) 
+    return false;
+
+  return true;
+}
+
+
+
+/******************************************************************************
+ * Compares two WINSEC_ACL structures.
+ ******************************************************************************/
+bool winsec_acl_equal(WINSEC_ACL* s1, WINSEC_ACL* s2)
+{
+  unsigned int i, j;
+
   /* Trivial cases */
   if (!s1 && !s2) 
@@ -507,11 +447,29 @@
 
   /* Check top level stuff */
-  if (s1->type != s2->type || s1->flags != s2->flags ||
-      s1->info.mask != s2->info.mask) 
-  { return false; }
-
-  /* Check SID */
-  if (!sid_equal(&s1->trustee, &s2->trustee))
-    return false;
+  if (s1->revision != s2->revision)
+    return false;
+
+  if (s1->num_aces != s2->num_aces)
+    return false;
+
+  /* The ACEs could be in any order so check each ACE in s1 against 
+     each ACE in s2. */
+
+  for (i = 0; i < s1->num_aces; i++)
+  {
+    bool found = false;
+
+    for (j = 0; j < s2->num_aces; j++) 
+    {
+      if (winsec_ace_equal(s1->aces[i], s2->aces[j])) 
+      {
+	found = true;
+	break;
+      }
+    }
+
+    if (!found)
+      return false;
+  }
 
   return true;
@@ -519,11 +477,9 @@
 
 
-/*******************************************************************
- Compares two SEC_ACL structures
-********************************************************************/
-bool sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
-{
-  unsigned int i, j;
-
+/******************************************************************************
+ * Compares two WINSEC_ACE structures.
+ ******************************************************************************/
+bool winsec_ace_equal(WINSEC_ACE* s1, WINSEC_ACE* s2)
+{
   /* Trivial cases */
   if (!s1 && !s2) 
@@ -533,29 +489,11 @@
 
   /* Check top level stuff */
-  if (s1->revision != s2->revision)
-    return false;
-
-  if (s1->num_aces != s2->num_aces)
-    return false;
-
-  /* The ACEs could be in any order so check each ACE in s1 against 
-     each ACE in s2. */
-
-  for (i = 0; i < s1->num_aces; i++) 
-  {
-    bool found = false;
-
-    for (j = 0; j < s2->num_aces; j++) 
-    {
-      if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) 
-      {
-	found = true;
-	break;
-      }
-    }
-
-    if (!found)
-      return false;
-  }
+  if (s1->type != s2->type || s1->flags != s2->flags ||
+      s1->access_mask != s2->access_mask)
+  { return false; }
+
+  /* Check SID */
+  if (!winsec_sid_equal(s1->trustee, s2->trustee))
+    return false;
 
   return true;
@@ -563,39 +501,15 @@
 
 
-/*******************************************************************
- Compares two SEC_DESC structures
-********************************************************************/
-bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
-{
-  /* Trivial cases */
-  if (!s1 && !s2)
-    return true;
-  if (!s1 || !s2)
-    return false;
-
-  /* Check top level stuff */
-  if (s1->revision != s2->revision)
-    return false;
-
-  if (s1->type!= s2->type)
-    return false;
-
-  /* Check owner and group */
-  if (!sid_equal(s1->owner_sid, s2->owner_sid))
-    return false;
-
-  if (!sid_equal(s1->grp_sid, s2->grp_sid)) 
-    return false;
-
-  /* Check ACLs present in one but not the other */
-  if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
-      (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) 
-  { return false; }
-
-  /* Sigh - we have to do it the hard way by iterating over all
-     the ACEs in the ACLs */
-  if(!sec_acl_equal(s1->dacl, s2->dacl) || !sec_acl_equal(s1->sacl, s2->sacl)) 
-    return false;
-
-  return true;
-}
+/******************************************************************************
+ * Check if ACE has OBJECT type.
+ ******************************************************************************/
+bool winsec_ace_object(uint8_t type)
+{
+  if (type == WINSEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
+      type == WINSEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
+      type == WINSEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
+      type == WINSEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) 
+  { return true; }
+
+  return false;
+}
Index: /trunk/src/common.c
===================================================================
--- /trunk/src/common.c	(revision 133)
+++ /trunk/src/common.c	(revision 134)
@@ -29,5 +29,5 @@
 const char* common_special_chars = ",\"\\";
 
-#define REGLOOKUP_VERSION "0.9.0"
+#define REGLOOKUP_VERSION "0.10.0"
 
 
