r13350: Implement rpccli_samr_set_domain_info. Weird that it was not around :-)
[kai/samba.git] / source3 / rpc_parse / parse_samr.c
index 939b652a1e3ba8a91b51411c52de64175fa8336e..87bfcebe2648efdffee2b436de4058ae842d1fa2 100644 (file)
@@ -25,8 +25,6 @@
  */
 
 #include "includes.h"
-#include "rpc_parse.h"
-#include "nterr.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_PARSE
@@ -181,9 +179,9 @@ BOOL samr_io_r_lookup_domain(const char *desc, SAMR_R_LOOKUP_DOMAIN * r_u,
 reads or writes a structure.
 ********************************************************************/
 
-void init_samr_q_remove_user_foreign_domain(SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN * q_u, POLICY_HND *dom_pol, DOM_SID *sid)
+void init_samr_q_remove_sid_foreign_domain(SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN * q_u, POLICY_HND *dom_pol, DOM_SID *sid)
 {
-       DEBUG(5, ("samr_init_samr_q_remove_user_foreign_domain\n"));
+       DEBUG(5, ("samr_init_samr_q_remove_sid_foreign_domain\n"));
 
        q_u->dom_pol = *dom_pol;
        init_dom_sid2(&q_u->sid, sid);
@@ -193,13 +191,13 @@ void init_samr_q_remove_user_foreign_domain(SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN *
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_q_remove_user_foreign_domain(const char *desc, SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN * q_u,
+BOOL samr_io_q_remove_sid_foreign_domain(const char *desc, SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN * q_u,
                          prs_struct *ps, int depth)
 {
        if (q_u == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_io_q_remove_user_foreign_domain");
+       prs_debug(ps, depth, desc, "samr_io_q_remove_sid_foreign_domain");
        depth++;
 
        if(!prs_align(ps))
@@ -221,13 +219,13 @@ BOOL samr_io_q_remove_user_foreign_domain(const char *desc, SAMR_Q_REMOVE_USER_F
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_r_remove_user_foreign_domain(const char *desc, SAMR_R_REMOVE_USER_FOREIGN_DOMAIN * r_u,
+BOOL samr_io_r_remove_sid_foreign_domain(const char *desc, SAMR_R_REMOVE_SID_FOREIGN_DOMAIN * r_u,
                          prs_struct *ps, int depth)
 {
        if (r_u == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_io_r_remove_user_foreign_domain");
+       prs_debug(ps, depth, desc, "samr_io_r_remove_sid_foreign_domain");
        depth++;
 
        if(!prs_align(ps))
@@ -564,9 +562,9 @@ static BOOL sam_io_unk_info6(const char *desc, SAM_UNK_INFO_6 * u_6,
 inits a structure.
 ********************************************************************/
 
-void init_unk_info7(SAM_UNK_INFO_7 * u_7)
+void init_unk_info7(SAM_UNK_INFO_7 * u_7, uint32 server_role)
 {
-       u_7->unknown_0 = 0x0003;
+       u_7->server_role = server_role;
 }
 
 /*******************************************************************
@@ -582,12 +580,46 @@ static BOOL sam_io_unk_info7(const char *desc, SAM_UNK_INFO_7 * u_7,
        prs_debug(ps, depth, desc, "sam_io_unk_info7");
        depth++;
 
-       if(!prs_uint16("unknown_0", ps, depth, &u_7->unknown_0)) /* 0x0003 */
+       if(!prs_uint16("server_role", ps, depth, &u_7->server_role))
                return False;
 
        return True;
 }
 
+/*******************************************************************
+inits a structure.
+********************************************************************/
+
+void init_unk_info8(SAM_UNK_INFO_8 * u_8, uint32 seq_num)
+{
+       unix_to_nt_time(&u_8->domain_create_time, 0);
+       u_8->seq_num.low = seq_num;
+       u_8->seq_num.high = 0x0000;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL sam_io_unk_info8(const char *desc, SAM_UNK_INFO_8 * u_8,
+                            prs_struct *ps, int depth)
+{
+       if (u_8 == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "sam_io_unk_info8");
+       depth++;
+
+       if (!prs_uint64("seq_num", ps, depth, &u_8->seq_num))
+               return False;
+
+       if(!smb_io_time("domain_create_time", &u_8->domain_create_time, ps, depth))
+               return False;
+
+       return True;
+}
+
+
 /*******************************************************************
 inits a structure.
 ********************************************************************/
@@ -662,20 +694,18 @@ inits a structure.
 ********************************************************************/
 
 void init_unk_info2(SAM_UNK_INFO_2 * u_2,
-                       const char *domain, const char *server,
-                       uint32 seq_num, uint32 num_users, uint32 num_groups, uint32 num_alias)
+                       const char *comment, const char *domain, const char *server,
+                       uint32 seq_num, uint32 num_users, uint32 num_groups, uint32 num_alias, NTTIME nt_logout, uint32 server_role)
 {
-       u_2->unknown_0 = 0x00000000;
-       u_2->unknown_1 = 0x80000000;
-       u_2->unknown_2 = 0x00000000;
+       u_2->logout.low = nt_logout.low;
+       u_2->logout.high = nt_logout.high;
 
-       u_2->ptr_0 = 1;
+       u_2->seq_num.low = seq_num;
+       u_2->seq_num.high = 0x00000000;
 
-       u_2->seq_num = seq_num;
-       u_2->unknown_3 = 0x00000000;
 
        u_2->unknown_4 = 0x00000001;
-       u_2->unknown_5 = 0x00000003;
+       u_2->server_role = server_role;
        u_2->unknown_6 = 0x00000001;
        u_2->num_domain_usrs = num_users;
        u_2->num_domain_grps = num_groups;
@@ -683,6 +713,8 @@ void init_unk_info2(SAM_UNK_INFO_2 * u_2,
 
        memset(u_2->padding, 0, sizeof(u_2->padding));  /* 12 bytes zeros */
 
+       init_unistr2(&u_2->uni_comment, comment, UNI_FLAGS_NONE);
+       init_uni_hdr(&u_2->hdr_comment, &u_2->uni_comment);
        init_unistr2(&u_2->uni_domain, domain, UNI_FLAGS_NONE);
        init_uni_hdr(&u_2->hdr_domain, &u_2->uni_domain);
        init_unistr2(&u_2->uni_server, server, UNI_FLAGS_NONE);
@@ -702,14 +734,9 @@ static BOOL sam_io_unk_info2(const char *desc, SAM_UNK_INFO_2 * u_2,
        prs_debug(ps, depth, desc, "sam_io_unk_info2");
        depth++;
 
-       if(!prs_uint32("unknown_0", ps, depth, &u_2->unknown_0)) /* 0x0000 0000 */
-               return False;
-       if(!prs_uint32("unknown_1", ps, depth, &u_2->unknown_1)) /* 0x8000 0000 */
+       if(!smb_io_time("logout", &u_2->logout, ps, depth))
                return False;
-       if(!prs_uint32("unknown_2", ps, depth, &u_2->unknown_2))        /* 0x0000 0000 */
-               return False;
-
-       if(!prs_uint32("ptr_0", ps, depth, &u_2->ptr_0))
+       if(!smb_io_unihdr("hdr_comment", &u_2->hdr_comment, ps, depth))
                return False;
        if(!smb_io_unihdr("hdr_domain", &u_2->hdr_domain, ps, depth))
                return False;
@@ -720,14 +747,12 @@ static BOOL sam_io_unk_info2(const char *desc, SAM_UNK_INFO_2 * u_2,
           pointer is referring to
         */
 
-       if(!prs_uint32("seq_num ", ps, depth, &u_2->seq_num))   /* 0x0000 0099 or 0x1000 0000 */
-               return False;
-       if(!prs_uint32("unknown_3 ", ps, depth, &u_2->unknown_3))       /* 0x0000 0000 */
+       if(!prs_uint64("seq_num ", ps, depth, &u_2->seq_num))
                return False;
 
        if(!prs_uint32("unknown_4 ", ps, depth, &u_2->unknown_4)) /* 0x0000 0001 */
                return False;
-       if(!prs_uint32("unknown_5 ", ps, depth, &u_2->unknown_5)) /* 0x0000 0003 */
+       if(!prs_uint32("server_role ", ps, depth, &u_2->server_role))
                return False;
        if(!prs_uint32("unknown_6 ", ps, depth, &u_2->unknown_6)) /* 0x0000 0001 */
                return False;
@@ -738,15 +763,8 @@ static BOOL sam_io_unk_info2(const char *desc, SAM_UNK_INFO_2 * u_2,
        if(!prs_uint32("num_local_grps", ps, depth, &u_2->num_local_grps))
                return False;
 
-       if (u_2->ptr_0) {
-               /* this was originally marked as 'padding'. It isn't
-                  padding, it is some sort of optional 12 byte
-                  structure. When it is present it contains zeros
-                  !? */
-               if(!prs_uint8s(False, "unknown", ps, depth, u_2->padding,sizeof(u_2->padding)))
-                       return False;
-       }
-
+       if(!smb_io_unistr2("uni_comment", &u_2->uni_comment, u_2->hdr_comment.buffer, ps, depth))
+               return False;
        if(!smb_io_unistr2("uni_domain", &u_2->uni_domain, u_2->hdr_domain.buffer, ps, depth))
                return False;
        if(!smb_io_unistr2("uni_server", &u_2->uni_server, u_2->hdr_server.buffer, ps, depth))
@@ -760,11 +778,11 @@ inits a structure.
 ********************************************************************/
 
 void init_unk_info1(SAM_UNK_INFO_1 *u_1, uint16 min_pass_len, uint16 pass_hist, 
-                   uint32 flag, NTTIME nt_expire, NTTIME nt_min_age)
+                   uint32 password_properties, NTTIME nt_expire, NTTIME nt_min_age)
 {
        u_1->min_length_password = min_pass_len;
        u_1->password_history = pass_hist;
-       u_1->flag = flag;
+       u_1->password_properties = password_properties;
        
        /* password never expire */
        u_1->expire.high = nt_expire.high;
@@ -793,7 +811,7 @@ static BOOL sam_io_unk_info1(const char *desc, SAM_UNK_INFO_1 * u_1,
                return False;
        if(!prs_uint16("password_history", ps, depth, &u_1->password_history))
                return False;
-       if(!prs_uint32("flag", ps, depth, &u_1->flag))
+       if(!prs_uint32("password_properties", ps, depth, &u_1->password_properties))
                return False;
        if(!smb_io_time("expire", &u_1->expire, ps, depth))
                return False;
@@ -854,6 +872,10 @@ BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
                        if(!sam_io_unk_info12("unk_inf12", &r_u->ctr->info.inf12, ps, depth))
                                return False;
                        break;
+               case 0x08:
+                       if(!sam_io_unk_info8("unk_inf8",&r_u->ctr->info.inf8, ps,depth))
+                               return False;
+                       break;
                case 0x07:
                        if(!sam_io_unk_info7("unk_inf7",&r_u->ctr->info.inf7, ps,depth))
                                return False;
@@ -1401,8 +1423,8 @@ BOOL samr_io_r_enum_dom_users(const char *desc, SAMR_R_ENUM_DOM_USERS * r_u,
                        return False;
 
                if (UNMARSHALLING(ps) && (r_u->num_entries2 != 0)) {
-                       r_u->sam = (SAM_ENTRY *)prs_alloc_mem(ps,sizeof(SAM_ENTRY)*r_u->num_entries2);
-                       r_u->uni_acct_name = (UNISTR2 *)prs_alloc_mem(ps,sizeof(UNISTR2)*r_u->num_entries2);
+                       r_u->sam = PRS_ALLOC_MEM(ps,SAM_ENTRY, r_u->num_entries2);
+                       r_u->uni_acct_name = PRS_ALLOC_MEM(ps,UNISTR2, r_u->num_entries2);
                }
 
                if ((r_u->sam == NULL || r_u->uni_acct_name == NULL) && r_u->num_entries2 != 0) {
@@ -1492,75 +1514,42 @@ BOOL samr_io_q_query_dispinfo(const char *desc, SAMR_Q_QUERY_DISPINFO * q_e,
 inits a SAM_DISPINFO_1 structure.
 ********************************************************************/
 
-NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_entries,
-                            uint32 start_idx, SAM_ACCOUNT *disp_user_info,
-                            DOM_SID *domain_sid)
+NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 **sam,
+                            uint32 num_entries, uint32 start_idx,
+                            struct samr_displayentry *entries)
 {
        uint32 i;
 
-       SAM_ACCOUNT *pwd = NULL;
-       ZERO_STRUCTP(sam);
-
        DEBUG(10, ("init_sam_dispinfo_1: num_entries: %d\n", num_entries));
 
        if (num_entries==0)
                return NT_STATUS_OK;
 
-       sam->sam=(SAM_ENTRY1 *)talloc(ctx, num_entries*sizeof(SAM_ENTRY1));
-       if (!sam->sam)
+       *sam = TALLOC_ZERO_ARRAY(ctx, SAM_DISPINFO_1, num_entries);
+       if (*sam == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       sam->str=(SAM_STR1 *)talloc(ctx, num_entries*sizeof(SAM_STR1));
-       if (!sam->str)
+       (*sam)->sam=TALLOC_ARRAY(ctx, SAM_ENTRY1, num_entries);
+       if ((*sam)->sam == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       ZERO_STRUCTP(sam->sam);
-       ZERO_STRUCTP(sam->str);
+       (*sam)->str=TALLOC_ARRAY(ctx, SAM_STR1, num_entries);
+       if ((*sam)->str == NULL)
+               return NT_STATUS_NO_MEMORY;
 
        for (i = 0; i < num_entries ; i++) {
-               const char *username;
-               const char *fullname;
-               const char *acct_desc;
-               uint32 user_rid;
-               const DOM_SID *user_sid;
-               fstring user_sid_string, domain_sid_string;                     
-
-               DEBUG(11, ("init_sam_dispinfo_1: entry: %d\n",i));
-               
-               pwd=&disp_user_info[i+start_idx];
-               
-               username = pdb_get_username(pwd);
-               fullname = pdb_get_fullname(pwd);
-               acct_desc = pdb_get_acct_desc(pwd);
-               
-               if (!username) 
-                       username = "";
-
-               if (!fullname) 
-                       fullname = "";
-               
-               if (!acct_desc) 
-                       acct_desc = "";
-
-               user_sid = pdb_get_user_sid(pwd);
-
-               if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
-                       DEBUG(0, ("init_sam_dispinfo_1: User %s has SID %s, which conflicts with "
-                                 "the domain sid %s.  Failing operation.\n", 
-                                 username, 
-                                 sid_to_string(user_sid_string, user_sid),
-                                 sid_to_string(domain_sid_string, domain_sid)));
-                       return NT_STATUS_UNSUCCESSFUL;
-               }
-                       
-               init_unistr2(&sam->str[i].uni_acct_name, pdb_get_username(pwd), UNI_FLAGS_NONE);
-               init_unistr2(&sam->str[i].uni_full_name, pdb_get_fullname(pwd), UNI_FLAGS_NONE);
-               init_unistr2(&sam->str[i].uni_acct_desc, pdb_get_acct_desc(pwd), UNI_FLAGS_NONE);
-
-               init_sam_entry1(&sam->sam[i], start_idx + i + 1,
-                               &sam->str[i].uni_acct_name, &sam->str[i].uni_full_name, &sam->str[i].uni_acct_desc,
-                               user_rid, pdb_get_acct_ctrl(pwd));
-               
+               init_unistr2(&(*sam)->str[i].uni_acct_name,
+                            entries[i].account_name, UNI_FLAGS_NONE);
+               init_unistr2(&(*sam)->str[i].uni_full_name,
+                            entries[i].fullname, UNI_FLAGS_NONE);
+               init_unistr2(&(*sam)->str[i].uni_acct_desc,
+                            entries[i].description, UNI_FLAGS_NONE);
+
+               init_sam_entry1(&(*sam)->sam[i], start_idx+i+1,
+                               &(*sam)->str[i].uni_acct_name,
+                               &(*sam)->str[i].uni_full_name,
+                               &(*sam)->str[i].uni_acct_desc,
+                               entries[i].rid, entries[i].acct_flags);
        }
 
        return NT_STATUS_OK;
@@ -1584,16 +1573,12 @@ static BOOL sam_io_sam_dispinfo_1(const char *desc, SAM_DISPINFO_1 * sam,
 
        if (UNMARSHALLING(ps) && num_entries > 0) {
 
-               if ((sam->sam = (SAM_ENTRY1 *)
-                    prs_alloc_mem(ps, sizeof(SAM_ENTRY1) *
-                                  num_entries)) == NULL) {
+               if ((sam->sam = PRS_ALLOC_MEM(ps, SAM_ENTRY1, num_entries)) == NULL) {
                        DEBUG(0, ("out of memory allocating SAM_ENTRY1\n"));
                        return False;
                }
 
-               if ((sam->str = (SAM_STR1 *)
-                    prs_alloc_mem(ps, sizeof(SAM_STR1) * 
-                                  num_entries)) == NULL) {
+               if ((sam->str = PRS_ALLOC_MEM(ps, SAM_STR1, num_entries)) == NULL) {
                        DEBUG(0, ("out of memory allocating SAM_STR1\n"));
                        return False;
                }
@@ -1619,58 +1604,39 @@ static BOOL sam_io_sam_dispinfo_1(const char *desc, SAM_DISPINFO_1 * sam,
 inits a SAM_DISPINFO_2 structure.
 ********************************************************************/
 
-NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 num_entries,
-                            uint32 start_idx, SAM_ACCOUNT *disp_user_info, 
-                            DOM_SID *domain_sid )
+NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 **sam,
+                            uint32 num_entries, uint32 start_idx,
+                            struct samr_displayentry *entries)
 {
        uint32 i;
 
-       SAM_ACCOUNT *pwd = NULL;
-       ZERO_STRUCTP(sam);
-
        DEBUG(10, ("init_sam_dispinfo_2: num_entries: %d\n", num_entries));
 
        if (num_entries==0)
                return NT_STATUS_OK;
 
-       if (!(sam->sam=(SAM_ENTRY2 *)talloc(ctx, num_entries*sizeof(SAM_ENTRY2))))
+       *sam = TALLOC_ZERO_ARRAY(ctx, SAM_DISPINFO_2, num_entries);
+       if (*sam == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       if (!(sam->str=(SAM_STR2 *)talloc(ctx, num_entries*sizeof(SAM_STR2))))
+       (*sam)->sam = TALLOC_ARRAY(ctx, SAM_ENTRY2, num_entries);
+       if ((*sam)->sam == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       ZERO_STRUCTP(sam->sam);
-       ZERO_STRUCTP(sam->str);
+       (*sam)->str=TALLOC_ARRAY(ctx, SAM_STR2, num_entries);
+       if ((*sam)->str == NULL)
+               return NT_STATUS_NO_MEMORY;
 
        for (i = 0; i < num_entries; i++) {
-               uint32 user_rid;
-               const DOM_SID *user_sid;
-               const char *username;
-               const char *acct_desc;
-               fstring user_sid_string, domain_sid_string;                     
-
-               DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i));
-               pwd=&disp_user_info[i+start_idx];
-
-               username = pdb_get_username(pwd);
-               acct_desc = pdb_get_acct_desc(pwd);
-               user_sid = pdb_get_user_sid(pwd);
-
-               if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
-                       DEBUG(0, ("init_sam_dispinfo_2: User %s has SID %s, which conflicts with "
-                                 "the domain sid %s.  Failing operation.\n", 
-                                 username, 
-                                 sid_to_string(user_sid_string, user_sid),
-                                 sid_to_string(domain_sid_string, domain_sid)));
-                       return NT_STATUS_UNSUCCESSFUL;
-               }
-                       
-               init_unistr2(&sam->str[i].uni_srv_name, username, UNI_FLAGS_NONE);
-               init_unistr2(&sam->str[i].uni_srv_desc, pdb_get_acct_desc(pwd), UNI_FLAGS_NONE);
-
-               init_sam_entry2(&sam->sam[i], start_idx + i + 1,
-                         &sam->str[i].uni_srv_name, &sam->str[i].uni_srv_desc,
-                         user_rid, pdb_get_acct_ctrl(pwd));
+               init_unistr2(&(*sam)->str[i].uni_srv_name,
+                            entries[i].account_name, UNI_FLAGS_NONE);
+               init_unistr2(&(*sam)->str[i].uni_srv_desc,
+                            entries[i].description, UNI_FLAGS_NONE);
+
+               init_sam_entry2(&(*sam)->sam[i], start_idx + i + 1,
+                               &(*sam)->str[i].uni_srv_name,
+                               &(*sam)->str[i].uni_srv_desc,
+                               entries[i].rid, entries[i].acct_flags);
        }
 
        return NT_STATUS_OK;
@@ -1697,16 +1663,12 @@ static BOOL sam_io_sam_dispinfo_2(const char *desc, SAM_DISPINFO_2 * sam,
 
        if (UNMARSHALLING(ps) && num_entries > 0) {
 
-               if ((sam->sam = (SAM_ENTRY2 *)
-                    prs_alloc_mem(ps, sizeof(SAM_ENTRY2) *
-                                  num_entries)) == NULL) {
+               if ((sam->sam = PRS_ALLOC_MEM(ps, SAM_ENTRY2, num_entries)) == NULL) {
                        DEBUG(0, ("out of memory allocating SAM_ENTRY2\n"));
                        return False;
                }
 
-               if ((sam->str = (SAM_STR2 *)
-                    prs_alloc_mem(ps, sizeof(SAM_STR2) * 
-                                  num_entries)) == NULL) {
+               if ((sam->str = PRS_ALLOC_MEM(ps, SAM_STR2, num_entries)) == NULL) {
                        DEBUG(0, ("out of memory allocating SAM_STR2\n"));
                        return False;
                }
@@ -1731,37 +1693,39 @@ static BOOL sam_io_sam_dispinfo_2(const char *desc, SAM_DISPINFO_2 * sam,
 inits a SAM_DISPINFO_3 structure.
 ********************************************************************/
 
-NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 num_entries,
-                        uint32 start_idx, DOMAIN_GRP *disp_group_info)
+NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 **sam,
+                            uint32 num_entries, uint32 start_idx,
+                            struct samr_displayentry *entries)
 {
        uint32 i;
 
-       ZERO_STRUCTP(sam);
-
        DEBUG(5, ("init_sam_dispinfo_3: num_entries: %d\n", num_entries));
 
        if (num_entries==0)
                return NT_STATUS_OK;
 
-       if (!(sam->sam=(SAM_ENTRY3 *)talloc(ctx, num_entries*sizeof(SAM_ENTRY3))))
+       *sam = TALLOC_ZERO_ARRAY(ctx, SAM_DISPINFO_3, num_entries);
+       if (*sam == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       if (!(sam->str=(SAM_STR3 *)talloc(ctx, num_entries*sizeof(SAM_STR3))))
+       if (!((*sam)->sam=TALLOC_ARRAY(ctx, SAM_ENTRY3, num_entries)))
                return NT_STATUS_NO_MEMORY;
 
-       ZERO_STRUCTP(sam->sam);
-       ZERO_STRUCTP(sam->str);
+       if (!((*sam)->str=TALLOC_ARRAY(ctx, SAM_STR3, num_entries)))
+               return NT_STATUS_NO_MEMORY;
 
        for (i = 0; i < num_entries; i++) {
-               DOMAIN_GRP *grp = &disp_group_info[i+start_idx];
-
                DEBUG(11, ("init_sam_dispinfo_3: entry: %d\n",i));
 
-               init_unistr2(&sam->str[i].uni_grp_name, grp->name, UNI_FLAGS_NONE);
-               init_unistr2(&sam->str[i].uni_grp_desc, grp->comment, UNI_FLAGS_NONE);
+               init_unistr2(&(*sam)->str[i].uni_grp_name,
+                            entries[i].account_name, UNI_FLAGS_NONE);
+               init_unistr2(&(*sam)->str[i].uni_grp_desc,
+                            entries[i].description, UNI_FLAGS_NONE);
 
-               init_sam_entry3(&sam->sam[i], start_idx + i + 1, &sam->str[i].uni_grp_name,
-                               &sam->str[i].uni_grp_desc, grp->rid);
+               init_sam_entry3(&(*sam)->sam[i], start_idx+i+1,
+                               &(*sam)->str[i].uni_grp_name,
+                               &(*sam)->str[i].uni_grp_desc,
+                               entries[i].rid);
        }
 
        return NT_STATUS_OK;
@@ -1788,16 +1752,12 @@ static BOOL sam_io_sam_dispinfo_3(const char *desc, SAM_DISPINFO_3 * sam,
 
        if (UNMARSHALLING(ps) && num_entries > 0) {
 
-               if ((sam->sam = (SAM_ENTRY3 *)
-                    prs_alloc_mem(ps, sizeof(SAM_ENTRY3) *
-                                  num_entries)) == NULL) {
+               if ((sam->sam = PRS_ALLOC_MEM(ps, SAM_ENTRY3, num_entries)) == NULL) {
                        DEBUG(0, ("out of memory allocating SAM_ENTRY3\n"));
                        return False;
                }
 
-               if ((sam->str = (SAM_STR3 *)
-                    prs_alloc_mem(ps, sizeof(SAM_STR3) * 
-                                  num_entries)) == NULL) {
+               if ((sam->str = PRS_ALLOC_MEM(ps, SAM_STR3, num_entries)) == NULL) {
                        DEBUG(0, ("out of memory allocating SAM_STR3\n"));
                        return False;
                }
@@ -1822,38 +1782,40 @@ static BOOL sam_io_sam_dispinfo_3(const char *desc, SAM_DISPINFO_3 * sam,
 inits a SAM_DISPINFO_4 structure.
 ********************************************************************/
 
-NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 *sam, uint32 num_entries,
-                        uint32 start_idx, SAM_ACCOUNT *disp_user_info)
+NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 **sam,
+                            uint32 num_entries, uint32 start_idx,
+                            struct samr_displayentry *entries)
 {
-       uint32 len_sam_name;
        uint32 i;
 
-       SAM_ACCOUNT *pwd = NULL;
-       ZERO_STRUCTP(sam);
-
        DEBUG(5, ("init_sam_dispinfo_4: num_entries: %d\n", num_entries));
 
        if (num_entries==0)
                return NT_STATUS_OK;
 
-       if (!(sam->sam=(SAM_ENTRY4 *)talloc(ctx, num_entries*sizeof(SAM_ENTRY4))))
+       *sam = TALLOC_ZERO_ARRAY(ctx, SAM_DISPINFO_4, num_entries);
+       if (*sam == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       if (!(sam->str=(SAM_STR4 *)talloc(ctx, num_entries*sizeof(SAM_STR4))))
+       (*sam)->sam = TALLOC_ARRAY(ctx, SAM_ENTRY4, num_entries);
+       if ((*sam)->sam == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       ZERO_STRUCTP(sam->sam);
-       ZERO_STRUCTP(sam->str);
+       (*sam)->str=TALLOC_ARRAY(ctx, SAM_STR4, num_entries);
+       if ((*sam)->str == NULL)
+               return NT_STATUS_NO_MEMORY;
 
        for (i = 0; i < num_entries; i++) {
-               DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i));
-               pwd=&disp_user_info[i+start_idx];
+               size_t len_sam_name = strlen(entries[i].account_name);
 
-               len_sam_name = strlen(pdb_get_username(pwd));
+               DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i));
          
-               init_sam_entry4(&sam->sam[i], start_idx + i + 1, len_sam_name);
+               init_sam_entry4(&(*sam)->sam[i], start_idx + i + 1,
+                               len_sam_name);
 
-               init_string2(&sam->str[i].acct_name, pdb_get_username(pwd), len_sam_name+1, len_sam_name);
+               init_string2(&(*sam)->str[i].acct_name,
+                            entries[i].account_name, len_sam_name+1,
+                            len_sam_name);
        }
        
        return NT_STATUS_OK;
@@ -1880,16 +1842,12 @@ static BOOL sam_io_sam_dispinfo_4(const char *desc, SAM_DISPINFO_4 * sam,
 
        if (UNMARSHALLING(ps) && num_entries > 0) {
 
-               if ((sam->sam = (SAM_ENTRY4 *)
-                    prs_alloc_mem(ps, sizeof(SAM_ENTRY4) *
-                                  num_entries)) == NULL) {
+               if ((sam->sam = PRS_ALLOC_MEM(ps, SAM_ENTRY4, num_entries)) == NULL) {
                        DEBUG(0, ("out of memory allocating SAM_ENTRY4\n"));
                        return False;
                }
 
-               if ((sam->str = (SAM_STR4 *)
-                    prs_alloc_mem(ps, sizeof(SAM_STR4) * 
-                                  num_entries)) == NULL) {
+               if ((sam->str = PRS_ALLOC_MEM(ps, SAM_STR4, num_entries)) == NULL) {
                        DEBUG(0, ("out of memory allocating SAM_STR4\n"));
                        return False;
                }
@@ -1913,37 +1871,36 @@ static BOOL sam_io_sam_dispinfo_4(const char *desc, SAM_DISPINFO_4 * sam,
 inits a SAM_DISPINFO_5 structure.
 ********************************************************************/
 
-NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 *sam, uint32 num_entries,
-                        uint32 start_idx, DOMAIN_GRP *disp_group_info)
+NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 **sam,
+                            uint32 num_entries, uint32 start_idx,
+                            struct samr_displayentry *entries)
 {
        uint32 len_sam_name;
        uint32 i;
 
-       ZERO_STRUCTP(sam);
-
        DEBUG(5, ("init_sam_dispinfo_5: num_entries: %d\n", num_entries));
 
        if (num_entries==0)
                return NT_STATUS_OK;
 
-       if (!(sam->sam=(SAM_ENTRY5 *)talloc(ctx, num_entries*sizeof(SAM_ENTRY5))))
+       *sam = TALLOC_ZERO_ARRAY(ctx, SAM_DISPINFO_5, num_entries);
+       if (*sam == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       if (!(sam->str=(SAM_STR5 *)talloc(ctx, num_entries*sizeof(SAM_STR5))))
+       if (!((*sam)->sam=TALLOC_ARRAY(ctx, SAM_ENTRY5, num_entries)))
                return NT_STATUS_NO_MEMORY;
 
-       ZERO_STRUCTP(sam->sam);
-       ZERO_STRUCTP(sam->str);
+       if (!((*sam)->str=TALLOC_ARRAY(ctx, SAM_STR5, num_entries)))
+               return NT_STATUS_NO_MEMORY;
 
        for (i = 0; i < num_entries; i++) {
-               DOMAIN_GRP *grp = &disp_group_info[i+start_idx];
-
                DEBUG(11, ("init_sam_dispinfo_5: entry: %d\n",i));
 
-               len_sam_name = strlen(grp->name);
+               len_sam_name = strlen(entries[i].account_name);
          
-               init_sam_entry5(&sam->sam[i], start_idx + i + 1, len_sam_name);
-               init_string2(&sam->str[i].grp_name, grp->name, len_sam_name+1, len_sam_name);
+               init_sam_entry5(&(*sam)->sam[i], start_idx+i+1, len_sam_name);
+               init_string2(&(*sam)->str[i].grp_name, entries[i].account_name,
+                            len_sam_name+1, len_sam_name);
        }
 
        return NT_STATUS_OK;
@@ -1970,16 +1927,12 @@ static BOOL sam_io_sam_dispinfo_5(const char *desc, SAM_DISPINFO_5 * sam,
 
        if (UNMARSHALLING(ps) && num_entries > 0) {
 
-               if ((sam->sam = (SAM_ENTRY5 *)
-                    prs_alloc_mem(ps, sizeof(SAM_ENTRY5) *
-                                  num_entries)) == NULL) {
+               if ((sam->sam = PRS_ALLOC_MEM(ps, SAM_ENTRY5, num_entries)) == NULL) {
                        DEBUG(0, ("out of memory allocating SAM_ENTRY5\n"));
                        return False;
                }
 
-               if ((sam->str = (SAM_STR5 *)
-                    prs_alloc_mem(ps, sizeof(SAM_STR5) * 
-                                  num_entries)) == NULL) {
+               if ((sam->str = PRS_ALLOC_MEM(ps, SAM_STR5, num_entries)) == NULL) {
                        DEBUG(0, ("out of memory allocating SAM_STR5\n"));
                        return False;
                }
@@ -2188,7 +2141,7 @@ void init_samr_group_info1(GROUP_INFO1 * gr1,
 {
        DEBUG(5, ("init_samr_group_info1\n"));
 
-       gr1->unknown_1 = 0x3;
+       gr1->group_attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT); /* why not | SE_GROUP_ENABLED ? */
        gr1->num_members = num_members;
 
        init_unistr2(&gr1->uni_acct_name, acct_name, UNI_FLAGS_NONE);
@@ -2204,19 +2157,24 @@ reads or writes a structure.
 BOOL samr_io_group_info1(const char *desc, GROUP_INFO1 * gr1,
                         prs_struct *ps, int depth)
 {
+       uint16 dummy = 1;
+
        if (gr1 == NULL)
                return False;
 
        prs_debug(ps, depth, desc, "samr_io_group_info1");
        depth++;
 
+       if(!prs_uint16("level", ps, depth, &dummy))
+               return False;
+
        if(!prs_align(ps))
                return False;
 
        if(!smb_io_unihdr("hdr_acct_name", &gr1->hdr_acct_name, ps, depth))
                return False;
 
-       if(!prs_uint32("unknown_1", ps, depth, &gr1->unknown_1))
+       if(!prs_uint32("group_attr", ps, depth, &gr1->group_attr))
                return False;
        if(!prs_uint32("num_members", ps, depth, &gr1->num_members))
                return False;
@@ -2235,6 +2193,43 @@ BOOL samr_io_group_info1(const char *desc, GROUP_INFO1 * gr1,
        return True;
 }
 
+/*******************************************************************
+inits a GROUP_INFO2 structure.
+********************************************************************/
+
+void init_samr_group_info2(GROUP_INFO2 * gr2, const char *acct_name)
+{
+       DEBUG(5, ("init_samr_group_info2\n"));
+
+       gr2->level = 2;
+       init_unistr2(&gr2->uni_acct_name, acct_name, UNI_FLAGS_NONE);
+       init_uni_hdr(&gr2->hdr_acct_name, &gr2->uni_acct_name);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_group_info2(const char *desc, GROUP_INFO2 *gr2, prs_struct *ps, int depth)
+{
+       if (gr2 == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_group_info2");
+       depth++;
+
+       if(!prs_uint16("hdr_level", ps, depth, &gr2->level))
+               return False;
+
+       if(!smb_io_unihdr("hdr_acct_name", &gr2->hdr_acct_name, ps, depth))
+               return False;
+       if(!smb_io_unistr2("uni_acct_name", &gr2->uni_acct_name,
+                          gr2->hdr_acct_name.buffer, ps, depth))
+               return False;
+
+       return True;
+}
+
 /*******************************************************************
 inits a GROUP_INFO3 structure.
 ********************************************************************/
@@ -2243,7 +2238,7 @@ void init_samr_group_info3(GROUP_INFO3 *gr3)
 {
        DEBUG(5, ("init_samr_group_info3\n"));
 
-       gr3->unknown_1 = 0x3;
+       gr3->group_attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT); /* why not | SE_GROUP_ENABLED ? */
 }
 
 /*******************************************************************
@@ -2261,7 +2256,7 @@ BOOL samr_io_group_info3(const char *desc, GROUP_INFO3 *gr3, prs_struct *ps, int
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("unknown_1", ps, depth, &gr3->unknown_1))
+       if(!prs_uint32("group_attr", ps, depth, &gr3->group_attr))
                return False;
 
        return True;
@@ -2271,10 +2266,11 @@ BOOL samr_io_group_info3(const char *desc, GROUP_INFO3 *gr3, prs_struct *ps, int
 inits a GROUP_INFO4 structure.
 ********************************************************************/
 
-void init_samr_group_info4(GROUP_INFO4 * gr4, char *acct_desc)
+void init_samr_group_info4(GROUP_INFO4 * gr4, const char *acct_desc)
 {
        DEBUG(5, ("init_samr_group_info4\n"));
 
+       gr4->level = 4;
        init_unistr2(&gr4->uni_acct_desc, acct_desc, UNI_FLAGS_NONE);
        init_uni_hdr(&gr4->hdr_acct_desc, &gr4->uni_acct_desc);
 }
@@ -2292,9 +2288,8 @@ BOOL samr_io_group_info4(const char *desc, GROUP_INFO4 * gr4,
        prs_debug(ps, depth, desc, "samr_io_group_info4");
        depth++;
 
-       if(!prs_align(ps))
+       if(!prs_uint16("hdr_level", ps, depth, &gr4->level))
                return False;
-
        if(!smb_io_unihdr("hdr_acct_desc", &gr4->hdr_acct_desc, ps, depth))
                return False;
        if(!smb_io_unistr2("uni_acct_desc", &gr4->uni_acct_desc,
@@ -2312,7 +2307,7 @@ static BOOL samr_group_info_ctr(const char *desc, GROUP_INFO_CTR **ctr,
                                prs_struct *ps, int depth)
 {
        if (UNMARSHALLING(ps))
-               *ctr = (GROUP_INFO_CTR *)prs_alloc_mem(ps,sizeof(GROUP_INFO_CTR));
+               *ctr = PRS_ALLOC_MEM(ps,GROUP_INFO_CTR,1);
 
        if (*ctr == NULL)
                return False;
@@ -2328,6 +2323,10 @@ static BOOL samr_group_info_ctr(const char *desc, GROUP_INFO_CTR **ctr,
                if(!samr_io_group_info1("group_info1", &(*ctr)->group.info1, ps, depth))
                        return False;
                break;
+       case 2:
+               if(!samr_io_group_info2("group_info2", &(*ctr)->group.info2, ps, depth))
+                       return False;
+               break;
        case 3:
                if(!samr_io_group_info3("group_info3", &(*ctr)->group.info3, ps, depth))
                        return False;
@@ -2349,7 +2348,7 @@ inits a SAMR_Q_CREATE_DOM_GROUP structure.
 ********************************************************************/
 
 void init_samr_q_create_dom_group(SAMR_Q_CREATE_DOM_GROUP * q_e,
-                                 POLICY_HND *pol, char *acct_desc,
+                                 POLICY_HND *pol, const char *acct_desc,
                                  uint32 access_mask)
 {
        DEBUG(5, ("init_samr_q_create_dom_group\n"));
@@ -2883,7 +2882,7 @@ BOOL samr_io_r_query_groupmem(const char *desc, SAMR_R_QUERY_GROUPMEM * r_u,
                        if(!prs_uint32("num_rids", ps, depth, &r_u->num_rids))
                                return False;
                        if (UNMARSHALLING(ps) && r_u->num_rids != 0) {
-                               r_u->rid = (uint32 *)prs_alloc_mem(ps,sizeof(r_u->rid[0])*r_u->num_rids);
+                               r_u->rid = PRS_ALLOC_MEM(ps,uint32,r_u->num_rids);
                                if (r_u->rid == NULL)
                                        return False;
                        }
@@ -2899,7 +2898,7 @@ BOOL samr_io_r_query_groupmem(const char *desc, SAMR_R_QUERY_GROUPMEM * r_u,
                                return False;
 
                        if (UNMARSHALLING(ps) && r_u->num_attrs != 0) {
-                               r_u->attr = (uint32 *)prs_alloc_mem(ps,sizeof(r_u->attr[0])*r_u->num_attrs);
+                               r_u->attr = PRS_ALLOC_MEM(ps,uint32,r_u->num_attrs);
                                if (r_u->attr == NULL)
                                        return False;
                        }
@@ -3000,7 +2999,7 @@ BOOL samr_io_gids(const char *desc, uint32 *num_gids, DOM_GID ** gid,
 
        if ((*num_gids) != 0) {
                if (UNMARSHALLING(ps)) {
-                       (*gid) = (DOM_GID *)prs_alloc_mem(ps,sizeof(DOM_GID)*(*num_gids));
+                       (*gid) = PRS_ALLOC_MEM(ps,DOM_GID,*num_gids);
                }
 
                if ((*gid) == NULL) {
@@ -3155,8 +3154,8 @@ BOOL samr_io_r_enum_domains(const char *desc, SAMR_R_ENUM_DOMAINS * r_u,
                        return False;
 
                if (UNMARSHALLING(ps)) {
-                       r_u->sam = (SAM_ENTRY *)prs_alloc_mem(ps,sizeof(SAM_ENTRY)*r_u->num_entries2);
-                       r_u->uni_dom_name = (UNISTR2 *)prs_alloc_mem(ps,sizeof(UNISTR2)*r_u->num_entries2);
+                       r_u->sam = PRS_ALLOC_MEM(ps,SAM_ENTRY,r_u->num_entries2);
+                       r_u->uni_dom_name = PRS_ALLOC_MEM(ps,UNISTR2,r_u->num_entries2);
                }
 
                if ((r_u->sam == NULL || r_u->uni_dom_name == NULL) && r_u->num_entries2 != 0) {
@@ -3294,8 +3293,8 @@ BOOL samr_io_r_enum_dom_groups(const char *desc, SAMR_R_ENUM_DOM_GROUPS * r_u,
                        return False;
 
                if (UNMARSHALLING(ps)) {
-                       r_u->sam = (SAM_ENTRY *)prs_alloc_mem(ps,sizeof(SAM_ENTRY)*r_u->num_entries2);
-                       r_u->uni_grp_name = (UNISTR2 *)prs_alloc_mem(ps,sizeof(UNISTR2)*r_u->num_entries2);
+                       r_u->sam = PRS_ALLOC_MEM(ps,SAM_ENTRY,r_u->num_entries2);
+                       r_u->uni_grp_name = PRS_ALLOC_MEM(ps,UNISTR2,r_u->num_entries2);
                }
 
                if ((r_u->sam == NULL || r_u->uni_grp_name == NULL) && r_u->num_entries2 != 0) {
@@ -3428,8 +3427,8 @@ BOOL samr_io_r_enum_dom_aliases(const char *desc, SAMR_R_ENUM_DOM_ALIASES * r_u,
                        return False;
 
                if (UNMARSHALLING(ps) && (r_u->num_entries2 > 0)) {
-                       r_u->sam = (SAM_ENTRY *)prs_alloc_mem(ps,sizeof(SAM_ENTRY)*r_u->num_entries2);
-                       r_u->uni_grp_name = (UNISTR2 *)prs_alloc_mem(ps,sizeof(UNISTR2)*r_u->num_entries2);
+                       r_u->sam = PRS_ALLOC_MEM(ps,SAM_ENTRY,r_u->num_entries2);
+                       r_u->uni_grp_name = PRS_ALLOC_MEM(ps,UNISTR2,r_u->num_entries2);
                }
 
                if (r_u->num_entries2 != 0 && 
@@ -3471,13 +3470,9 @@ void init_samr_alias_info1(ALIAS_INFO1 * al1, char *acct_name, uint32 num_member
 {
        DEBUG(5, ("init_samr_alias_info1\n"));
 
-       init_unistr2(&al1->uni_acct_name, acct_name, UNI_FLAGS_NONE);
-       init_uni_hdr(&al1->hdr_acct_name, &al1->uni_acct_name);
-
-       al1->num_member=num_member;
-
-       init_unistr2(&al1->uni_acct_desc, acct_desc, UNI_FLAGS_NONE);
-       init_uni_hdr(&al1->hdr_acct_desc, &al1->uni_acct_name);
+       init_unistr4(&al1->name, acct_name, UNI_FLAGS_NONE);
+       al1->num_member = num_member;
+       init_unistr4(&al1->description, acct_desc, UNI_FLAGS_NONE);
 }
 
 /*******************************************************************
@@ -3496,22 +3491,20 @@ BOOL samr_io_alias_info1(const char *desc, ALIAS_INFO1 * al1,
        if(!prs_align(ps))
                return False;
 
-       if(!smb_io_unihdr("hdr_acct_name", &al1->hdr_acct_name, ps, depth))
+       if ( !prs_unistr4_hdr("name", ps, depth, &al1->name) )
                return False;
-       if(!prs_uint32("num_member", ps, depth, &al1->num_member))
+       if ( !prs_uint32("num_member", ps, depth, &al1->num_member) )
                return False;
-       if(!smb_io_unihdr("hdr_acct_desc", &al1->hdr_acct_desc, ps, depth))
+       if ( !prs_unistr4_hdr("description", ps, depth, &al1->description) )
                return False;
 
-       if(!smb_io_unistr2("uni_acct_name", &al1->uni_acct_name,
-                      al1->hdr_acct_name.buffer, ps, depth))
+       if ( !prs_unistr4_str("name", ps, depth, &al1->name) )
                return False;
-
-       if(!prs_align(ps))
+       if ( !prs_align(ps) )
                return False;
-
-       if(!smb_io_unistr2("uni_acct_desc", &al1->uni_acct_desc,
-                      al1->hdr_acct_desc.buffer, ps, depth))
+       if ( !prs_unistr4_str("description", ps, depth, &al1->description) )
+               return False;
+       if ( !prs_align(ps) )
                return False;
 
        return True;
@@ -3521,19 +3514,18 @@ BOOL samr_io_alias_info1(const char *desc, ALIAS_INFO1 * al1,
 inits a ALIAS_INFO3 structure.
 ********************************************************************/
 
-void init_samr_alias_info3(ALIAS_INFO3 * al3, char *acct_desc)
+void init_samr_alias_info3(ALIAS_INFO3 * al3, const char *acct_desc)
 {
        DEBUG(5, ("init_samr_alias_info3\n"));
 
-       init_unistr2(&al3->uni_acct_desc, acct_desc, UNI_FLAGS_NONE);
-       init_uni_hdr(&al3->hdr_acct_desc, &al3->uni_acct_desc);
+       init_unistr4(&al3->description, acct_desc, UNI_FLAGS_NONE);
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_alias_info3(const char *desc, ALIAS_INFO3 * al3,
+BOOL samr_io_alias_info3(const char *desc, ALIAS_INFO3 *al3,
                         prs_struct *ps, int depth)
 {
        if (al3 == NULL)
@@ -3545,10 +3537,7 @@ BOOL samr_io_alias_info3(const char *desc, ALIAS_INFO3 * al3,
        if(!prs_align(ps))
                return False;
 
-       if(!smb_io_unihdr("hdr_acct_desc", &al3->hdr_acct_desc, ps, depth))
-               return False;
-       if(!smb_io_unistr2("uni_acct_desc", &al3->uni_acct_desc,
-                      al3->hdr_acct_desc.buffer, ps, depth))
+       if (!prs_unistr4("description", ps, depth, &al3->description))
                return False;
 
        return True;
@@ -3558,21 +3547,20 @@ BOOL samr_io_alias_info3(const char *desc, ALIAS_INFO3 * al3,
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_alias_info_ctr(const char *desc, ALIAS_INFO_CTR * ctr,
-                        prs_struct *ps, int depth)
+BOOL samr_alias_info_ctr(const char *desc, prs_struct *ps, int depth, ALIAS_INFO_CTR * ctr)
 {
-       if (ctr == NULL)
+       if ( !ctr )
                return False;
 
        prs_debug(ps, depth, desc, "samr_alias_info_ctr");
        depth++;
 
-       if(!prs_uint16("switch_value1", ps, depth, &ctr->switch_value1))
-               return False;
-       if(!prs_uint16("switch_value2", ps, depth, &ctr->switch_value2))
+       if ( !prs_uint16("level", ps, depth, &ctr->level) )
                return False;
 
-       switch (ctr->switch_value1) {
+       if(!prs_align(ps))
+               return False;
+       switch (ctr->level) {
        case 1: 
                if(!samr_io_alias_info1("alias_info1", &ctr->alias.info1, ps, depth))
                        return False;
@@ -3594,22 +3582,22 @@ inits a SAMR_Q_QUERY_ALIASINFO structure.
 ********************************************************************/
 
 void init_samr_q_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO * q_e,
-                                POLICY_HND *pol, uint16 switch_level)
+                                POLICY_HND *pol, uint32 switch_level)
 {
        DEBUG(5, ("init_samr_q_query_aliasinfo\n"));
 
        q_e->pol = *pol;
-       q_e->switch_level = switch_level;
+       q_e->level = switch_level;
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_q_query_aliasinfo(const char *desc, SAMR_Q_QUERY_ALIASINFO * q_e,
+BOOL samr_io_q_query_aliasinfo(const char *desc, SAMR_Q_QUERY_ALIASINFO *in,
                               prs_struct *ps, int depth)
 {
-       if (q_e == NULL)
+       if ( !in )
                return False;
 
        prs_debug(ps, depth, desc, "samr_io_q_query_aliasinfo");
@@ -3618,10 +3606,10 @@ BOOL samr_io_q_query_aliasinfo(const char *desc, SAMR_Q_QUERY_ALIASINFO * q_e,
        if(!prs_align(ps))
                return False;
 
-       if(!smb_io_pol_hnd("pol", &(q_e->pol), ps, depth))
+       if ( !smb_io_pol_hnd("pol", &(in->pol), ps, depth) )
                return False;
 
-       if(!prs_uint16("switch_level", ps, depth, &q_e->switch_level))
+       if ( !prs_uint16("level", ps, depth, &in->level) )
                return False;
 
        return True;
@@ -3631,24 +3619,23 @@ BOOL samr_io_q_query_aliasinfo(const char *desc, SAMR_Q_QUERY_ALIASINFO * q_e,
 inits a SAMR_R_QUERY_ALIASINFO structure.
 ********************************************************************/
 
-void init_samr_r_query_aliasinfo(SAMR_R_QUERY_ALIASINFO * r_u,
+void init_samr_r_query_aliasinfo(SAMR_R_QUERY_ALIASINFO *out,
                                 ALIAS_INFO_CTR * ctr, NTSTATUS status)
 {
        DEBUG(5, ("init_samr_r_query_aliasinfo\n"));
 
-       r_u->ptr = (NT_STATUS_IS_OK(status) && ctr != NULL) ? 1 : 0;
-       r_u->ctr = *ctr;
-       r_u->status = status;
+       out->ctr = ctr;
+       out->status = status;
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_r_query_aliasinfo(const char *desc, SAMR_R_QUERY_ALIASINFO * r_u,
+BOOL samr_io_r_query_aliasinfo(const char *desc, SAMR_R_QUERY_ALIASINFO *out,
                               prs_struct *ps, int depth)
 {
-       if (r_u == NULL)
+       if ( !out )
                return False;
 
        prs_debug(ps, depth, desc, "samr_io_r_query_aliasinfo");
@@ -3657,17 +3644,12 @@ BOOL samr_io_r_query_aliasinfo(const char *desc, SAMR_R_QUERY_ALIASINFO * r_u,
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr", ps, depth, &r_u->ptr))
+       if ( !prs_pointer("alias", ps, depth, (void**)&out->ctr, sizeof(ALIAS_INFO_CTR), (PRS_POINTER_CAST)samr_alias_info_ctr))
                return False;
-
-       if (r_u->ptr != 0) {
-               if(!samr_alias_info_ctr("ctr", &r_u->ctr, ps, depth))
-                       return False;
-       }
-
        if(!prs_align(ps))
                return False;
-       if(!prs_ntstatus("status", ps, depth, &r_u->status))
+
+       if(!prs_ntstatus("status", ps, depth, &out->status))
                return False;
 
        return True;
@@ -3704,7 +3686,7 @@ BOOL samr_io_q_set_aliasinfo(const char *desc, SAMR_Q_SET_ALIASINFO * q_u,
 
        if(!smb_io_pol_hnd("alias_pol", &q_u->alias_pol, ps, depth))
                return False;
-       if(!samr_alias_info_ctr("ctr", &q_u->ctr, ps, depth))
+       if(!samr_alias_info_ctr("ctr", ps, depth, &q_u->ctr))
                return False;
 
        return True;
@@ -3786,11 +3768,11 @@ BOOL samr_io_q_query_useraliases(const char *desc, SAMR_Q_QUERY_USERALIASES * q_
                return False;
 
        if (UNMARSHALLING(ps) && (q_u->num_sids2 != 0)) {
-               q_u->ptr_sid = (uint32 *)prs_alloc_mem(ps,sizeof(q_u->ptr_sid[0])*q_u->num_sids2);
+               q_u->ptr_sid = PRS_ALLOC_MEM(ps,uint32,q_u->num_sids2);
                if (q_u->ptr_sid == NULL)
                        return False;
 
-               q_u->sid = (DOM_SID2 *)prs_alloc_mem(ps, sizeof(q_u->sid[0]) * q_u->num_sids2);
+               q_u->sid = PRS_ALLOC_MEM(ps, DOM_SID2, q_u->num_sids2);
                if (q_u->sid == NULL)
                        return False;
        }
@@ -3861,7 +3843,7 @@ BOOL samr_io_rids(const char *desc, uint32 *num_rids, uint32 **rid,
        if ((*num_rids) != 0) {
                if (UNMARSHALLING(ps)) {
                        /* reading */
-                       (*rid) = (uint32 *)prs_alloc_mem(ps,sizeof(uint32)*(*num_rids));
+                       (*rid) = PRS_ALLOC_MEM(ps,uint32, *num_rids);
                }
                if ((*rid) == NULL)
                        return False;
@@ -3992,7 +3974,7 @@ void init_samr_q_lookup_rids(TALLOC_CTX *ctx, SAMR_Q_LOOKUP_RIDS * q_u,
        q_u->flags = flags;
        q_u->ptr = 0;
        q_u->num_rids2 = num_rids;
-       q_u->rid = (uint32 *)talloc_zero(ctx, num_rids * sizeof(q_u->rid[0]));
+       q_u->rid = TALLOC_ZERO_ARRAY(ctx, uint32, num_rids );
        if (q_u->rid == NULL) {
                q_u->num_rids1 = 0;
                q_u->num_rids2 = 0;
@@ -4036,7 +4018,7 @@ BOOL samr_io_q_lookup_rids(const char *desc, SAMR_Q_LOOKUP_RIDS * q_u,
                return False;
 
        if (UNMARSHALLING(ps) && (q_u->num_rids2 != 0)) {
-               q_u->rid = (uint32 *)prs_alloc_mem(ps, sizeof(q_u->rid[0])*q_u->num_rids2);
+               q_u->rid = PRS_ALLOC_MEM(ps, uint32, q_u->num_rids2);
                if (q_u->rid == NULL)
                        return False;
        }
@@ -4117,11 +4099,11 @@ BOOL samr_io_r_lookup_rids(const char *desc, SAMR_R_LOOKUP_RIDS * r_u,
 
 
                if (UNMARSHALLING(ps) && (r_u->num_names2 != 0)) {
-                       r_u->hdr_name = (UNIHDR *) prs_alloc_mem(ps, r_u->num_names2 * sizeof(r_u->hdr_name[0]));
+                       r_u->hdr_name = PRS_ALLOC_MEM(ps, UNIHDR, r_u->num_names2);
                        if (r_u->hdr_name == NULL)
                                return False;
 
-                       r_u->uni_name = (UNISTR2 *)prs_alloc_mem(ps, r_u->num_names2 * sizeof(r_u->uni_name[0]));
+                       r_u->uni_name = PRS_ALLOC_MEM(ps, UNISTR2, r_u->num_names2);
                        if (r_u->uni_name == NULL)
                                return False;
                }
@@ -4152,7 +4134,7 @@ BOOL samr_io_r_lookup_rids(const char *desc, SAMR_R_LOOKUP_RIDS * r_u,
                        return False;
 
                if (UNMARSHALLING(ps) && (r_u->num_types2 != 0)) {
-                       r_u->type = (uint32 *)prs_alloc_mem(ps, r_u->num_types2 * sizeof(r_u->type[0]));
+                       r_u->type = PRS_ALLOC_MEM(ps, uint32, r_u->num_types2);
                        if (r_u->type == NULL)
                                return False;
                }
@@ -4232,7 +4214,7 @@ inits a SAMR_Q_CREATE_DOM_ALIAS structure.
 ********************************************************************/
 
 void init_samr_q_create_dom_alias(SAMR_Q_CREATE_DOM_ALIAS * q_u,
-                                 POLICY_HND *hnd, char *acct_desc)
+                                 POLICY_HND *hnd, const char *acct_desc)
 {
        DEBUG(5, ("init_samr_q_create_dom_alias\n"));
 
@@ -4241,7 +4223,7 @@ void init_samr_q_create_dom_alias(SAMR_Q_CREATE_DOM_ALIAS * q_u,
        init_unistr2(&q_u->uni_acct_desc, acct_desc, UNI_FLAGS_NONE);
        init_uni_hdr(&q_u->hdr_acct_desc, &q_u->uni_acct_desc);
 
-       q_u->access_mask = 0x001f000f;
+       q_u->access_mask = MAXIMUM_ALLOWED_ACCESS;
 }
 
 /*******************************************************************
@@ -4578,7 +4560,7 @@ BOOL samr_io_r_query_aliasmem(const char *desc, SAMR_R_QUERY_ALIASMEM * r_u,
                if(!prs_uint32("num_sids1", ps, depth, &r_u->num_sids1))
                        return False;
 
-               ptr_sid = talloc(ps->mem_ctx, sizeof(uint32) * r_u->num_sids1);
+               ptr_sid = TALLOC_ARRAY(ps->mem_ctx, uint32, r_u->num_sids1);
                if (!ptr_sid) {
                        return False;
                }
@@ -4590,7 +4572,7 @@ BOOL samr_io_r_query_aliasmem(const char *desc, SAMR_R_QUERY_ALIASMEM * r_u,
                }
                
                if (UNMARSHALLING(ps)) {
-                       r_u->sid = talloc(ps->mem_ctx, r_u->num_sids1 * sizeof(DOM_SID2));
+                       r_u->sid = TALLOC_ARRAY(ps->mem_ctx, DOM_SID2, r_u->num_sids1);
                }
                
                for (i = 0; i < r_u->num_sids1; i++) {
@@ -4628,10 +4610,10 @@ NTSTATUS init_samr_q_lookup_names(TALLOC_CTX *ctx, SAMR_Q_LOOKUP_NAMES * q_u,
        q_u->ptr = 0;
        q_u->num_names2 = num_names;
 
-       if (!(q_u->hdr_name = (UNIHDR *)talloc_zero(ctx, num_names * sizeof(UNIHDR))))
+       if (!(q_u->hdr_name = TALLOC_ZERO_ARRAY(ctx, UNIHDR, num_names)))
                return NT_STATUS_NO_MEMORY;
 
-       if (!(q_u->uni_name = (UNISTR2 *)talloc_zero(ctx, num_names * sizeof(UNISTR2))))
+       if (!(q_u->uni_name = TALLOC_ZERO_ARRAY(ctx, UNISTR2, num_names)))
                return NT_STATUS_NO_MEMORY;
 
        for (i = 0; i < num_names; i++) {
@@ -4676,10 +4658,8 @@ BOOL samr_io_q_lookup_names(const char *desc, SAMR_Q_LOOKUP_NAMES * q_u,
                return False;
 
        if (UNMARSHALLING(ps) && (q_u->num_names2 != 0)) {
-               q_u->hdr_name = (UNIHDR *)prs_alloc_mem(ps, sizeof(UNIHDR) *
-                                                       q_u->num_names2);
-               q_u->uni_name = (UNISTR2 *)prs_alloc_mem(ps, sizeof(UNISTR2) *
-                                                        q_u->num_names2);
+               q_u->hdr_name = PRS_ALLOC_MEM(ps, UNIHDR, q_u->num_names2);
+               q_u->uni_name = PRS_ALLOC_MEM(ps, UNISTR2, q_u->num_names2);
                if (!q_u->hdr_name || !q_u->uni_name)
                        return False;
        }
@@ -4719,9 +4699,9 @@ NTSTATUS init_samr_r_lookup_names(TALLOC_CTX *ctx, SAMR_R_LOOKUP_NAMES * r_u,
                r_u->ptr_rids = 1;
                r_u->num_rids2 = num_rids;
 
-               if (!(r_u->rids = (uint32 *)talloc_zero(ctx, sizeof(uint32)*num_rids)))
+               if (!(r_u->rids = TALLOC_ZERO_ARRAY(ctx, uint32, num_rids)))
                        return NT_STATUS_NO_MEMORY;
-               if (!(r_u->types = (uint32 *)talloc_zero(ctx, sizeof(uint32)*num_rids)))
+               if (!(r_u->types = TALLOC_ZERO_ARRAY(ctx, uint32, num_rids)))
                        return NT_STATUS_NO_MEMORY;
 
                if (!r_u->rids || !r_u->types)
@@ -4788,7 +4768,7 @@ BOOL samr_io_r_lookup_names(const char *desc, SAMR_R_LOOKUP_NAMES * r_u,
                }
 
                if (UNMARSHALLING(ps))
-                       r_u->rids = (uint32 *)prs_alloc_mem(ps, sizeof(uint32)*r_u->num_rids2);
+                       r_u->rids = PRS_ALLOC_MEM(ps, uint32, r_u->num_rids2);
 
                if (!r_u->rids) {
                        DEBUG(0, ("NULL rids in samr_io_r_lookup_names\n"));
@@ -4817,7 +4797,7 @@ BOOL samr_io_r_lookup_names(const char *desc, SAMR_R_LOOKUP_NAMES * r_u,
                }
 
                if (UNMARSHALLING(ps))
-                       r_u->types = (uint32 *)prs_alloc_mem(ps, sizeof(uint32)*r_u->num_types2);
+                       r_u->types = PRS_ALLOC_MEM(ps, uint32, r_u->num_types2);
 
                if (!r_u->types) {
                        DEBUG(0, ("NULL types in samr_io_r_lookup_names\n"));
@@ -5051,7 +5031,7 @@ inits a SAMR_Q_QUERY_USERINFO structure.
 ********************************************************************/
 
 void init_samr_q_query_userinfo(SAMR_Q_QUERY_USERINFO * q_u,
-                               POLICY_HND *hnd, uint16 switch_value)
+                               const POLICY_HND *hnd, uint16 switch_value)
 {
        DEBUG(5, ("init_samr_q_query_userinfo\n"));
 
@@ -5100,6 +5080,12 @@ static BOOL sam_io_logon_hrs(const char *desc, LOGON_HRS * hrs,
        if(!prs_align(ps))
                return False;
 
+       if(!prs_uint32("maxlen", ps, depth, &hrs->max_len))
+               return False;
+
+       if(!prs_uint32("offset", ps, depth, &hrs->offset))
+               return False;
+
        if(!prs_uint32("len  ", ps, depth, &hrs->len))
                return False;
 
@@ -5115,13 +5101,13 @@ static BOOL sam_io_logon_hrs(const char *desc, LOGON_HRS * hrs,
 }
 
 /*******************************************************************
-inits a SAM_USER_INFO_12 structure.
+inits a SAM_USER_INFO_18 structure.
 ********************************************************************/
 
-void init_sam_user_info12(SAM_USER_INFO_12 * usr,
+void init_sam_user_info18(SAM_USER_INFO_18 * usr,
                          const uint8 lm_pwd[16], const uint8 nt_pwd[16])
 {
-       DEBUG(5, ("init_sam_user_info12\n"));
+       DEBUG(5, ("init_sam_user_info18\n"));
 
        usr->lm_pwd_active =
                memcpy(usr->lm_pwd, lm_pwd, sizeof(usr->lm_pwd)) ? 1 : 0;
@@ -5133,13 +5119,13 @@ void init_sam_user_info12(SAM_USER_INFO_12 * usr,
 reads or writes a structure.
 ********************************************************************/
 
-static BOOL sam_io_user_info12(const char *desc, SAM_USER_INFO_12 * u,
+static BOOL sam_io_user_info18(const char *desc, SAM_USER_INFO_18 * u,
                        prs_struct *ps, int depth)
 {
        if (u == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_io_r_user_info12");
+       prs_debug(ps, depth, desc, "samr_io_r_user_info18");
        depth++;
 
        if(!prs_align(ps))
@@ -5159,12 +5145,83 @@ static BOOL sam_io_user_info12(const char *desc, SAM_USER_INFO_12 * u,
 }
 
 /*******************************************************************
-inits a SAM_USER_INFO_10 structure.
+inits a SAM_USER_INFO_7 structure.
+********************************************************************/
+
+void init_sam_user_info7(SAM_USER_INFO_7 * usr, const char *name)
+{
+       DEBUG(5, ("init_sam_user_info7\n"));
+
+       init_unistr2(&usr->uni_name, name, UNI_FLAGS_NONE);     /* unicode string for name */
+       init_uni_hdr(&usr->hdr_name, &usr->uni_name);           /* unicode header for name */
+
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL sam_io_user_info7(const char *desc, SAM_USER_INFO_7 * usr,
+                       prs_struct *ps, int depth)
+{
+       if (usr == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_r_user_info7");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_unihdr("unihdr", &usr->hdr_name, ps, depth))
+               return False;
+
+       if(!smb_io_unistr2("unistr2", &usr->uni_name, True, ps, depth))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+inits a SAM_USER_INFO_9 structure.
+********************************************************************/
+
+void init_sam_user_info9(SAM_USER_INFO_9 * usr, uint32 rid_group)
+{
+       DEBUG(5, ("init_sam_user_info9\n"));
+
+       usr->rid_group = rid_group;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL sam_io_user_info9(const char *desc, SAM_USER_INFO_9 * usr,
+                       prs_struct *ps, int depth)
+{
+       if (usr == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_r_user_info9");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("rid_group", ps, depth, &usr->rid_group))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+inits a SAM_USER_INFO_16 structure.
 ********************************************************************/
 
-void init_sam_user_info10(SAM_USER_INFO_10 * usr, uint32 acb_info)
+void init_sam_user_info16(SAM_USER_INFO_16 * usr, uint32 acb_info)
 {
-       DEBUG(5, ("init_sam_user_info10\n"));
+       DEBUG(5, ("init_sam_user_info16\n"));
 
        usr->acb_info = acb_info;
 }
@@ -5173,13 +5230,13 @@ void init_sam_user_info10(SAM_USER_INFO_10 * usr, uint32 acb_info)
 reads or writes a structure.
 ********************************************************************/
 
-static BOOL sam_io_user_info10(const char *desc, SAM_USER_INFO_10 * usr,
+static BOOL sam_io_user_info16(const char *desc, SAM_USER_INFO_16 * usr,
                        prs_struct *ps, int depth)
 {
        if (usr == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_io_r_user_info10");
+       prs_debug(ps, depth, desc, "samr_io_r_user_info16");
        depth++;
 
        if(!prs_align(ps))
@@ -5192,15 +5249,15 @@ static BOOL sam_io_user_info10(const char *desc, SAM_USER_INFO_10 * usr,
 }
 
 /*******************************************************************
-inits a SAM_USER_INFO_11 structure.
+inits a SAM_USER_INFO_17 structure.
 ********************************************************************/
 
-void init_sam_user_info11(SAM_USER_INFO_11 * usr,
+void init_sam_user_info17(SAM_USER_INFO_17 * usr,
                          NTTIME * expiry,
                          char *mach_acct,
                          uint32 rid_user, uint32 rid_group, uint16 acct_ctrl)
 {
-       DEBUG(5, ("init_sam_user_info11\n"));
+       DEBUG(5, ("init_sam_user_info17\n"));
 
        memcpy(&usr->expiry, expiry, sizeof(usr->expiry));      /* expiry time or something? */
        ZERO_STRUCT(usr->padding_1);    /* 0 - padding 24 bytes */
@@ -5237,13 +5294,13 @@ void init_sam_user_info11(SAM_USER_INFO_11 * usr,
 reads or writes a structure.
 ********************************************************************/
 
-static BOOL sam_io_user_info11(const char *desc, SAM_USER_INFO_11 * usr,
+static BOOL sam_io_user_info17(const char *desc, SAM_USER_INFO_17 * usr,
                        prs_struct *ps, int depth)
 {
        if (usr == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_io_r_unknown_11");
+       prs_debug(ps, depth, desc, "samr_io_r_unknown_17");
        depth++;
 
        if(!prs_align(ps))
@@ -5315,11 +5372,6 @@ static BOOL sam_io_user_info11(const char *desc, SAM_USER_INFO_11 * usr,
 
 /*************************************************************************
  init_sam_user_infoa
-
- unknown_3 = 0x09f8 27fa
- unknown_5 = 0x0001 0000
- unknown_6 = 0x0000 04ec 
-
  *************************************************************************/
 
 void init_sam_user_info24(SAM_USER_INFO_24 * usr, char newpass[516], uint16 pw_len)
@@ -5362,7 +5414,6 @@ static BOOL sam_io_user_info24(const char *desc, SAM_USER_INFO_24 * usr,
 /*************************************************************************
  init_sam_user_info23
 
- unknown_3 = 0x09f8 27fa
  unknown_6 = 0x0000 04ec 
 
  *************************************************************************/
@@ -5386,12 +5437,12 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
                        uint32 user_rid,        /* 0x0000 0000 */
                        uint32 group_rid,
                        uint32 acb_info,
-                       uint32 unknown_3,
+                       uint32 fields_present,
                        uint16 logon_divs,
                        LOGON_HRS * hrs,
                        uint16 bad_password_count,
                        uint16 logon_count,
-                       char newpass[516], uint32 unknown_6)
+                       char newpass[516])
 {
        usr->logon_time = *logon_time;  /* all zeros */
        usr->logoff_time = *logoff_time;        /* all zeros */
@@ -5406,7 +5457,7 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time,   /* all z
        usr->user_rid = user_rid;       /* 0x0000 0000 */
        usr->group_rid = group_rid;
        usr->acb_info = acb_info;
-       usr->unknown_3 = unknown_3;     /* 09f8 27fa */
+       usr->fields_present = fields_present;   /* 09f8 27fa */
 
        usr->logon_divs = logon_divs;   /* should be 168 (hours/week) */
        usr->ptr_logon_hrs = hrs ? 1 : 0;
@@ -5455,16 +5506,12 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
        copy_unistr2(&usr->uni_munged_dial, mung_dial);
        init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
 
-       usr->unknown_6 = unknown_6;     /* 0x0000 04ec */
-       usr->padding4 = 0;
-
        memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
 }
 
 /*************************************************************************
  init_sam_user_info23
 
- unknown_3 = 0x09f8 27fa
  unknown_6 = 0x0000 04ec 
 
  *************************************************************************/
@@ -5481,10 +5528,12 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
                           char *prof_path, const char *desc, char *wkstas,
                           char *unk_str, char *mung_dial, uint32 user_rid,     /* 0x0000 0000 */
                           uint32 group_rid, uint32 acb_info,
-                          uint32 unknown_3, uint16 logon_divs,
+                          uint32 fields_present, uint16 logon_divs,
                           LOGON_HRS * hrs, uint16 bad_password_count, uint16 logon_count,
-                          char newpass[516], uint32 unknown_6)
+                          char newpass[516])
 {
+       DATA_BLOB blob = base64_decode_data_blob(mung_dial);
+       
        usr->logon_time = *logon_time;  /* all zeros */
        usr->logoff_time = *logoff_time;        /* all zeros */
        usr->kickoff_time = *kickoff_time;      /* all zeros */
@@ -5498,7 +5547,7 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time,   /* all z
        usr->user_rid = user_rid;       /* 0x0000 0000 */
        usr->group_rid = group_rid;
        usr->acb_info = acb_info;
-       usr->unknown_3 = unknown_3;     /* 09f8 27fa */
+       usr->fields_present = fields_present;   /* 09f8 27fa */
 
        usr->logon_divs = logon_divs;   /* should be 168 (hours/week) */
        usr->ptr_logon_hrs = hrs ? 1 : 0;
@@ -5544,12 +5593,11 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
        init_unistr2(&usr->uni_unknown_str, unk_str, UNI_FLAGS_NONE);
        init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
 
-       init_unistr2(&usr->uni_munged_dial, mung_dial, UNI_FLAGS_NONE);
+       init_unistr2_from_datablob(&usr->uni_munged_dial, &blob);
        init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
 
-       usr->unknown_6 = unknown_6;     /* 0x0000 04ec */
-       usr->padding4 = 0;
-
+       data_blob_free(&blob);
+       
        memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
 }
 
@@ -5615,7 +5663,7 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr,
        if(!prs_uint32("acb_info      ", ps, depth, &usr->acb_info))
                return False;
 
-       if(!prs_uint32("unknown_3     ", ps, depth, &usr->unknown_3))
+       if(!prs_uint32("fields_present ", ps, depth, &usr->fields_present))
                return False;
        if(!prs_uint16("logon_divs    ", ps, depth, &usr->logon_divs))  /* logon divisions per week */
                return False;
@@ -5674,16 +5722,9 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr,
 
        /* ok, this is only guess-work (as usual) */
        if (usr->ptr_logon_hrs) {
-               if(!prs_uint32("unknown_6     ", ps, depth, &usr->unknown_6))
-                       return False;
-               if(!prs_uint32("padding4      ", ps, depth, &usr->padding4))
-                       return False;
                if(!sam_io_logon_hrs("logon_hrs", &usr->logon_hrs, ps, depth))
                        return False;
-       } else if (UNMARSHALLING(ps)) {
-               usr->unknown_6 = 0;
-               usr->padding4 = 0;
-       }
+       } 
 
        return True;
 }
@@ -5793,16 +5834,9 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
 #if 0 /* JRA - unknown... */
        /* ok, this is only guess-work (as usual) */
        if (usr->ptr_logon_hrs) {
-               if(!prs_uint32("unknown_6     ", ps, depth, &usr->unknown_6))
-                       return False;
-               if(!prs_uint32("padding4      ", ps, depth, &usr->padding4))
-                       return False;
                if(!sam_io_logon_hrs("logon_hrs", &usr->logon_hrs, ps, depth))
                        return False;
-       } else if (UNMARSHALLING(ps)) {
-               usr->unknown_6 = 0;
-               usr->padding4 = 0;
-       }
+       } 
 #endif
 
        return True;
@@ -5812,7 +5846,6 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
 /*************************************************************************
  init_sam_user_info21W
 
- unknown_3 = 0x00ff ffff
  unknown_6 = 0x0000 04ec 
 
  *************************************************************************/
@@ -5839,12 +5872,11 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
                           uint32 user_rid,
                           uint32 group_rid,
                           uint32 acb_info,
-                          uint32 unknown_3,
+                          uint32 fields_present,
                           uint16 logon_divs,
                           LOGON_HRS * hrs,
                           uint16 bad_password_count,
-                          uint16 logon_count,
-                          uint32 unknown_6)
+                          uint16 logon_count)
 {
        usr->logon_time = *logon_time;
        usr->logoff_time = *logoff_time;
@@ -5859,7 +5891,7 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
        usr->user_rid = user_rid;
        usr->group_rid = group_rid;
        usr->acb_info = acb_info;
-       usr->unknown_3 = unknown_3;     /* 0x00ff ffff */
+       usr->fields_present = fields_present;   /* 0x00ff ffff */
 
        usr->logon_divs = logon_divs;   /* should be 168 (hours/week) */
        usr->ptr_logon_hrs = hrs ? 1 : 0;
@@ -5905,16 +5937,12 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
        copy_unistr2(&usr->uni_munged_dial, mung_dial);
        init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
 
-       usr->unknown_6 = unknown_6;     /* 0x0000 04ec */
-       usr->padding4 = 0;
-
        memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
 }
 
 /*************************************************************************
  init_sam_user_info21
 
- unknown_3 = 0x00ff ffff
  unknown_6 = 0x0000 04ec 
 
  *************************************************************************/
@@ -5934,6 +5962,7 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
        const char*             description = pdb_get_acct_desc(pw);
        const char*             workstations = pdb_get_workstations(pw);
        const char*             munged_dial = pdb_get_munged_dial(pw);
+       DATA_BLOB               munged_dial_blob;
 
        uint32 user_rid;
        const DOM_SID *user_sid;
@@ -5941,6 +5970,12 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
        uint32 group_rid;
        const DOM_SID *group_sid;
 
+       if (munged_dial) {
+               munged_dial_blob = base64_decode_data_blob(munged_dial);
+       } else {
+               munged_dial_blob = data_blob(NULL, 0);
+       }
+
        /* Create NTTIME structs */
        unix_to_nt_time (&logon_time,           pdb_get_logon_time(pw));
        unix_to_nt_time (&logoff_time,          pdb_get_logoff_time(pw));
@@ -5970,6 +6005,7 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
                          user_name, 
                          sid_to_string(user_sid_string, user_sid),
                          sid_to_string(domain_sid_string, domain_sid)));
+               data_blob_free(&munged_dial_blob);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
@@ -5983,6 +6019,7 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
                          user_name, 
                          sid_to_string(group_sid_string, group_sid),
                          sid_to_string(domain_sid_string, domain_sid)));
+               data_blob_free(&munged_dial_blob);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
@@ -5992,14 +6029,14 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
 
        /*
          Look at a user on a real NT4 PDC with usrmgr, press
-         'ok'. Then you will see that unknown_3 is set to
+         'ok'. Then you will see that fields_present is set to
          0x08f827fa. Look at the user immediately after that again,
          and you will see that 0x00fffff is returned. This solves
          the problem that you get access denied after having looked
          at the user.
          -- Volker
        */
-       usr->unknown_3 = 0x00ffffff;
+       usr->fields_present = pdb_build_fields_present(pw);
 
        usr->logon_divs = pdb_get_logon_divs(pw); 
        usr->ptr_logon_hrs = pdb_get_hours(pw) ? 1 : 0;
@@ -6042,17 +6079,21 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
        init_unistr2(&usr->uni_unknown_str, NULL, UNI_STR_TERMINATE);
        init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str);
 
-       init_unistr2(&usr->uni_munged_dial, munged_dial, UNI_STR_TERMINATE);
+       init_unistr2_from_datablob(&usr->uni_munged_dial, &munged_dial_blob);
        init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
-
-       usr->unknown_6 = pdb_get_unknown_6(pw);
-       usr->padding4 = 0;
+       data_blob_free(&munged_dial_blob);
 
        if (pdb_get_hours(pw)) {
+               usr->logon_hrs.max_len = 1260;
+               usr->logon_hrs.offset = 0;
                usr->logon_hrs.len = pdb_get_hours_len(pw);
                memcpy(&usr->logon_hrs.hours, pdb_get_hours(pw), MAX_HOURS_LEN);
-       } else
+       } else {
+               usr->logon_hrs.max_len = 1260;
+               usr->logon_hrs.offset = 0;
+               usr->logon_hrs.len = 0;
                memset(&usr->logon_hrs, 0xff, sizeof(usr->logon_hrs));
+       }
 
        return NT_STATUS_OK;
 }
@@ -6119,7 +6160,7 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
        if(!prs_uint32("acb_info      ", ps, depth, &usr->acb_info))
                return False;
 
-       if(!prs_uint32("unknown_3     ", ps, depth, &usr->unknown_3))
+       if(!prs_uint32("fields_present ", ps, depth, &usr->fields_present))
                return False;
        if(!prs_uint16("logon_divs    ", ps, depth, &usr->logon_divs))  /* logon divisions per week */
                return False;
@@ -6165,17 +6206,8 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
 
        /* ok, this is only guess-work (as usual) */
        if (usr->ptr_logon_hrs) {
-               if(!prs_align(ps))
-                       return False;
-               if(!prs_uint32("unknown_6     ", ps, depth, &usr->unknown_6))
-                       return False;
-               if(!prs_uint32("padding4      ", ps, depth, &usr->padding4))
-                       return False;
                if(!sam_io_logon_hrs("logon_hrs", &usr->logon_hrs, ps, depth))
                        return False;
-       } else if (UNMARSHALLING(ps)) {
-               usr->unknown_6 = 0;
-               usr->padding4 = 0;
        }
 
        return True;
@@ -6184,10 +6216,11 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
 void init_sam_user_info20A(SAM_USER_INFO_20 *usr, SAM_ACCOUNT *pw)
 {
        const char *munged_dial = pdb_get_munged_dial(pw);
-
-       init_unistr2(&usr->uni_munged_dial, munged_dial, UNI_STR_TERMINATE);
+       DATA_BLOB blob = base64_decode_data_blob(munged_dial);
+       
+       init_unistr2_from_datablob(&usr->uni_munged_dial, &blob);
        init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
-
+       data_blob_free(&blob);
 }
 
 /*******************************************************************
@@ -6223,22 +6256,22 @@ NTSTATUS make_samr_userinfo_ctr_usr21(TALLOC_CTX *ctx, SAM_USERINFO_CTR * ctr,
                                    uint16 switch_value,
                                    SAM_USER_INFO_21 * usr)
 {
-       DEBUG(5, ("init_samr_userinfo_ctr\n"));
+       DEBUG(5, ("make_samr_userinfo_ctr_usr21\n"));
 
        ctr->switch_value = switch_value;
        ctr->info.id = NULL;
 
        switch (switch_value) {
-       case 0x10:
-               ctr->info.id10 = (SAM_USER_INFO_10 *)talloc_zero(ctx,sizeof(SAM_USER_INFO_10));
-               if (ctr->info.id10 == NULL)
+       case 16:
+               ctr->info.id16 = TALLOC_ZERO_P(ctx,SAM_USER_INFO_16);
+               if (ctr->info.id16 == NULL)
                        return NT_STATUS_NO_MEMORY;
 
-               init_sam_user_info10(ctr->info.id10, usr->acb_info);
+               init_sam_user_info16(ctr->info.id16, usr->acb_info);
                break;
 #if 0
 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
-       case 0x11:
+       case 17:
                {
                        NTTIME expire;
                        info = (void *)&id11;
@@ -6246,8 +6279,8 @@ NTSTATUS make_samr_userinfo_ctr_usr21(TALLOC_CTX *ctx, SAM_USERINFO_CTR * ctr,
                        expire.low = 0xffffffff;
                        expire.high = 0x7fffffff;
 
-                       ctr->info.id = (SAM_USER_INFO_11 *) talloc_zero(ctx,sizeof(*ctr->info.id11));
-                       init_sam_user_info11(ctr->info.id11, &expire,
+                       ctr->info.id = TALLOC_ZERO_P(ctx,SAM_USER_INFO_17);
+                       init_sam_user_info11(ctr->info.id17, &expire,
                                             "BROOKFIELDS$",    /* name */
                                             0x03ef,    /* user rid */
                                             0x201,     /* group rid */
@@ -6256,17 +6289,17 @@ NTSTATUS make_samr_userinfo_ctr_usr21(TALLOC_CTX *ctx, SAM_USERINFO_CTR * ctr,
                        break;
                }
 #endif
-       case 0x12:
-               ctr->info.id12 = (SAM_USER_INFO_12 *)talloc_zero(ctx,sizeof(SAM_USER_INFO_12));
-               if (ctr->info.id12 == NULL)
+       case 18:
+               ctr->info.id18 = TALLOC_ZERO_P(ctx,SAM_USER_INFO_18);
+               if (ctr->info.id18 == NULL)
                        return NT_STATUS_NO_MEMORY;
 
-               init_sam_user_info12(ctr->info.id12, usr->lm_pwd, usr->nt_pwd);
+               init_sam_user_info18(ctr->info.id18, usr->lm_pwd, usr->nt_pwd);
                break;
        case 21:
                {
                        SAM_USER_INFO_21 *cusr;
-                       cusr = (SAM_USER_INFO_21 *)talloc_zero(ctx,sizeof(SAM_USER_INFO_21));
+                       cusr = TALLOC_ZERO_P(ctx,SAM_USER_INFO_21);
                        ctr->info.id21 = cusr;
                        if (ctr->info.id21 == NULL)
                                return NT_STATUS_NO_MEMORY;
@@ -6287,8 +6320,8 @@ NTSTATUS make_samr_userinfo_ctr_usr21(TALLOC_CTX *ctx, SAM_USERINFO_CTR * ctr,
 inits a SAM_USERINFO_CTR structure.
 ********************************************************************/
 
-void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, uchar * sess_key,
-                           uint16 switch_value, void *info)
+static void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, DATA_BLOB *sess_key,
+                                  uint16 switch_value, void *info)
 {
        DEBUG(5, ("init_samr_userinfo_ctr\n"));
 
@@ -6297,17 +6330,19 @@ void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, uchar * sess_key,
 
        switch (switch_value) {
        case 0x18:
-               SamOEMhash(ctr->info.id24->pass, sess_key, 516);
-               dump_data(100, (char *)sess_key, 16);
+               SamOEMhashBlob(ctr->info.id24->pass, 516, sess_key);
+               dump_data(100, (char *)sess_key->data, sess_key->length);
                dump_data(100, (char *)ctr->info.id24->pass, 516);
                break;
        case 0x17:
-               SamOEMhash(ctr->info.id23->pass, sess_key, 516);
-               dump_data(100, (char *)sess_key, 16);
+               SamOEMhashBlob(ctr->info.id23->pass, 516, sess_key);
+               dump_data(100, (char *)sess_key->data, sess_key->length);
                dump_data(100, (char *)ctr->info.id23->pass, 516);
                break;
+       case 0x07:
+               break;
        default:
-               DEBUG(4,("init_samr_userinfo_ctr: unsupported switch level\n"));
+               DEBUG(4,("init_samr_userinfo_ctr: unsupported switch level: %d\n", switch_value));
        }
 }
 
@@ -6325,7 +6360,7 @@ static BOOL samr_io_userinfo_ctr(const char *desc, SAM_USERINFO_CTR **ppctr,
        depth++;
 
        if (UNMARSHALLING(ps)) {
-               ctr = (SAM_USERINFO_CTR *)prs_alloc_mem(ps,sizeof(SAM_USERINFO_CTR));
+               ctr = PRS_ALLOC_MEM(ps,SAM_USERINFO_CTR,1);
                if (ctr == NULL)
                        return False;
                *ppctr = ctr;
@@ -6343,38 +6378,56 @@ static BOOL samr_io_userinfo_ctr(const char *desc, SAM_USERINFO_CTR **ppctr,
        ret = False;
 
        switch (ctr->switch_value) {
-       case 0x10:
+       case 7:
                if (UNMARSHALLING(ps))
-                       ctr->info.id10 = (SAM_USER_INFO_10 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_10));
-               if (ctr->info.id10 == NULL) {
+                       ctr->info.id7 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_7,1);
+               if (ctr->info.id7 == NULL) {
                        DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
                        return False;
                }
-               ret = sam_io_user_info10("", ctr->info.id10, ps, depth);
+               ret = sam_io_user_info7("", ctr->info.id7, ps, depth);
                break;
-       case 0x11:
+       case 9:
                if (UNMARSHALLING(ps))
-                       ctr->info.id11 = (SAM_USER_INFO_11 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_11));
+                       ctr->info.id9 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_9,1);
+               if (ctr->info.id9 == NULL) {
+                       DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
+                       return False;
+               }
+               ret = sam_io_user_info9("", ctr->info.id9, ps, depth);
+               break;
+       case 16:
+               if (UNMARSHALLING(ps))
+                       ctr->info.id16 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_16,1);
+               if (ctr->info.id16 == NULL) {
+                       DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
+                       return False;
+               }
+               ret = sam_io_user_info16("", ctr->info.id16, ps, depth);
+               break;
+       case 17:
+               if (UNMARSHALLING(ps))
+                       ctr->info.id17 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_17,1);
 
-               if (ctr->info.id11 == NULL) {
+               if (ctr->info.id17 == NULL) {
                        DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
                        return False;
                }
-               ret = sam_io_user_info11("", ctr->info.id11, ps, depth);
+               ret = sam_io_user_info17("", ctr->info.id17, ps, depth);
                break;
-       case 0x12:
+       case 18:
                if (UNMARSHALLING(ps))
-                       ctr->info.id12 = (SAM_USER_INFO_12 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_12));
+                       ctr->info.id18 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_18,1);
 
-               if (ctr->info.id12 == NULL) {
+               if (ctr->info.id18 == NULL) {
                        DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
                        return False;
                }
-               ret = sam_io_user_info12("", ctr->info.id12, ps, depth);
+               ret = sam_io_user_info18("", ctr->info.id18, ps, depth);
                break;
        case 20:
                if (UNMARSHALLING(ps))
-                       ctr->info.id20 = (SAM_USER_INFO_20 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_20));
+                       ctr->info.id20 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_20,1);
 
                if (ctr->info.id20 == NULL) {
                        DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
@@ -6384,7 +6437,7 @@ static BOOL samr_io_userinfo_ctr(const char *desc, SAM_USERINFO_CTR **ppctr,
                break;
        case 21:
                if (UNMARSHALLING(ps))
-                       ctr->info.id21 = (SAM_USER_INFO_21 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_21));
+                       ctr->info.id21 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_21,1);
 
                if (ctr->info.id21 == NULL) {
                        DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
@@ -6394,7 +6447,7 @@ static BOOL samr_io_userinfo_ctr(const char *desc, SAM_USERINFO_CTR **ppctr,
                break;
        case 23:
                if (UNMARSHALLING(ps))
-                       ctr->info.id23 = (SAM_USER_INFO_23 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_23));
+                       ctr->info.id23 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_23,1);
 
                if (ctr->info.id23 == NULL) {
                        DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
@@ -6404,7 +6457,7 @@ static BOOL samr_io_userinfo_ctr(const char *desc, SAM_USERINFO_CTR **ppctr,
                break;
        case 24:
                if (UNMARSHALLING(ps))
-                       ctr->info.id24 = (SAM_USER_INFO_24 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_24));
+                       ctr->info.id24 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_24,1);
 
                if (ctr->info.id24 == NULL) {
                        DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
@@ -6414,7 +6467,7 @@ static BOOL samr_io_userinfo_ctr(const char *desc, SAM_USERINFO_CTR **ppctr,
                break;
        case 25:
                if (UNMARSHALLING(ps))
-                       ctr->info.id25 = (SAM_USER_INFO_25 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_25));
+                       ctr->info.id25 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_25,1);
 
                if (ctr->info.id25 == NULL) {
                        DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
@@ -6488,7 +6541,7 @@ inits a SAMR_Q_SET_USERINFO structure.
 ********************************************************************/
 
 void init_samr_q_set_userinfo(SAMR_Q_SET_USERINFO * q_u,
-                             POLICY_HND *hnd,  unsigned char sess_key[16],
+                             const POLICY_HND *hnd, DATA_BLOB *sess_key,
                              uint16 switch_value, void *info)
 {
        DEBUG(5, ("init_samr_q_set_userinfo\n"));
@@ -6562,7 +6615,7 @@ inits a SAMR_Q_SET_USERINFO2 structure.
 ********************************************************************/
 
 void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
-                              POLICY_HND *hnd, unsigned char sess_key[16],
+                              const POLICY_HND *hnd, DATA_BLOB *sess_key,
                               uint16 switch_value, SAM_USERINFO_CTR * ctr)
 {
        DEBUG(5, ("init_samr_q_set_userinfo2\n"));
@@ -6575,12 +6628,12 @@ void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
                q_u->ctr->switch_value = switch_value;
 
        switch (switch_value) {
-       case 0x12:
-               SamOEMhash(ctr->info.id12->lm_pwd, sess_key, 16);
-               SamOEMhash(ctr->info.id12->nt_pwd, sess_key, 16);
-               dump_data(100, (char *)sess_key, 16);
-               dump_data(100, (char *)ctr->info.id12->lm_pwd, 16);
-               dump_data(100, (char *)ctr->info.id12->nt_pwd, 16);
+       case 18:
+               SamOEMhashBlob(ctr->info.id18->lm_pwd, 16, sess_key);
+               SamOEMhashBlob(ctr->info.id18->nt_pwd, 16, sess_key);
+               dump_data(100, (char *)sess_key->data, sess_key->length);
+               dump_data(100, (char *)ctr->info.id18->lm_pwd, 16);
+               dump_data(100, (char *)ctr->info.id18->nt_pwd, 16);
                break;
        }
 }
@@ -6723,7 +6776,7 @@ inits a SAMR_Q_CONNECT4 structure.
 void init_samr_q_connect4(SAMR_Q_CONNECT4 * q_u,
                          char *srv_name, uint32 access_mask)
 {
-       DEBUG(5, ("init_samr_q_connect\n"));
+       DEBUG(5, ("init_samr_q_connect4\n"));
 
        /* make PDC server name \\server */
        q_u->ptr_srv_name = (srv_name != NULL && *srv_name) ? 1 : 0;
@@ -6792,6 +6845,116 @@ BOOL samr_io_r_connect4(const char *desc, SAMR_R_CONNECT4 * r_u,
        return True;
 }
 
+/*******************************************************************
+inits a SAMR_Q_CONNECT5 structure.
+********************************************************************/
+
+void init_samr_q_connect5(SAMR_Q_CONNECT5 * q_u,
+                         char *srv_name, uint32 access_mask)
+{
+       DEBUG(5, ("init_samr_q_connect5\n"));
+
+       /* make PDC server name \\server */
+       q_u->ptr_srv_name = (srv_name != NULL && *srv_name) ? 1 : 0;
+       init_unistr2(&q_u->uni_srv_name, srv_name, UNI_STR_TERMINATE);
+
+       /* example values: 0x0000 0002 */
+       q_u->access_mask = access_mask;
+
+       q_u->level = 1;
+       q_u->info1_unk1 = 3;
+       q_u->info1_unk2 = 0;
+}
+
+/*******************************************************************
+inits a SAMR_R_CONNECT5 structure.
+********************************************************************/
+
+void init_samr_r_connect5(SAMR_R_CONNECT5 * r_u, POLICY_HND *pol, NTSTATUS status)
+{
+       DEBUG(5, ("init_samr_q_connect5\n"));
+
+       r_u->level = 1;
+       r_u->info1_unk1 = 3;
+       r_u->info1_unk2 = 0;
+
+       r_u->connect_pol = *pol;
+       r_u->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_q_connect5(const char *desc, SAMR_Q_CONNECT5 * q_u,
+                       prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_q_connect5");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("ptr_srv_name", ps, depth, &q_u->ptr_srv_name))
+               return False;
+       if(!smb_io_unistr2("", &q_u->uni_srv_name, q_u->ptr_srv_name, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+       if(!prs_uint32("access_mask", ps, depth, &q_u->access_mask))
+               return False;
+
+       if(!prs_uint32("level", ps, depth, &q_u->level))
+               return False;
+       if(!prs_uint32("level", ps, depth, &q_u->level))
+               return False;
+       
+       if(!prs_uint32("info1_unk1", ps, depth, &q_u->info1_unk1))
+               return False;
+       if(!prs_uint32("info1_unk2", ps, depth, &q_u->info1_unk2))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_r_connect5(const char *desc, SAMR_R_CONNECT5 * r_u,
+                       prs_struct *ps, int depth)
+{
+       if (r_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_r_connect5");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("level", ps, depth, &r_u->level))
+               return False;
+       if(!prs_uint32("level", ps, depth, &r_u->level))
+               return False;
+       if(!prs_uint32("info1_unk1", ps, depth, &r_u->info1_unk1))
+               return False;
+       if(!prs_uint32("info1_unk2", ps, depth, &r_u->info1_unk2))
+               return False;
+
+       if(!smb_io_pol_hnd("connect_pol", &r_u->connect_pol, ps, depth))
+               return False;
+
+       if(!prs_ntstatus("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
 /*******************************************************************
 inits a SAMR_Q_CONNECT_ANON structure.
 ********************************************************************/
@@ -6917,16 +7080,11 @@ BOOL samr_io_r_get_dom_pwinfo(const char *desc, SAMR_R_GET_DOM_PWINFO * r_u,
        if(!prs_align(ps))
                return False;
 
-       /*
-        * We need 16 bytes here according to tests.  Don't know
-        * what they are, but the length is important for the singing
-       */
-
-       if(!prs_uint32("unk_0", ps, depth, &r_u->unk_0))
+       if(!prs_uint16("min_pwd_length", ps, depth, &r_u->min_pwd_length))
                return False;
-       if(!prs_uint32("unk_1", ps, depth, &r_u->unk_1))
+       if(!prs_align(ps))
                return False;
-       if(!prs_uint32("unk_2", ps, depth, &r_u->unk_2))
+       if(!prs_uint32("password_properties", ps, depth, &r_u->password_properties))
                return False;
 
        if(!prs_ntstatus("status", ps, depth, &r_u->status))
@@ -6939,7 +7097,7 @@ BOOL samr_io_r_get_dom_pwinfo(const char *desc, SAMR_R_GET_DOM_PWINFO * r_u,
 make a SAMR_ENC_PASSWD structure.
 ********************************************************************/
 
-void init_enc_passwd(SAMR_ENC_PASSWD * pwd, char pass[512])
+void init_enc_passwd(SAMR_ENC_PASSWD * pwd, const char pass[512])
 {
        ZERO_STRUCTP(pwd);
 
@@ -6982,7 +7140,7 @@ BOOL samr_io_enc_passwd(const char *desc, SAMR_ENC_PASSWD * pwd,
 inits a SAMR_ENC_HASH structure.
 ********************************************************************/
 
-void init_enc_hash(SAMR_ENC_HASH * hsh, uchar hash[16])
+void init_enc_hash(SAMR_ENC_HASH * hsh, const uchar hash[16])
 {
        ZERO_STRUCTP(hsh);
 
@@ -7021,15 +7179,15 @@ BOOL samr_io_enc_hash(const char *desc, SAMR_ENC_HASH * hsh,
 }
 
 /*******************************************************************
-inits a SAMR_R_GET_DOM_PWINFO structure.
+inits a SAMR_Q_CHGPASSWD_USER structure.
 ********************************************************************/
 
 void init_samr_q_chgpasswd_user(SAMR_Q_CHGPASSWD_USER * q_u,
-                               char *dest_host, char *user_name,
-                               char nt_newpass[516],
-                               uchar nt_oldhash[16],
-                               char lm_newpass[516],
-                               uchar lm_oldhash[16])
+                               const char *dest_host, const char *user_name,
+                               const uchar nt_newpass[516],
+                               const uchar nt_oldhash[16],
+                               const uchar lm_newpass[516],
+                               const uchar lm_oldhash[16])
 {
        DEBUG(5, ("init_samr_q_chgpasswd_user\n"));
 
@@ -7040,12 +7198,12 @@ void init_samr_q_chgpasswd_user(SAMR_Q_CHGPASSWD_USER * q_u,
        init_unistr2(&q_u->uni_user_name, user_name, UNI_FLAGS_NONE);
        init_uni_hdr(&q_u->hdr_user_name, &q_u->uni_user_name);
 
-       init_enc_passwd(&q_u->nt_newpass, nt_newpass);
+       init_enc_passwd(&q_u->nt_newpass, (const char *)nt_newpass);
        init_enc_hash(&q_u->nt_oldhash, nt_oldhash);
 
        q_u->unknown = 0x01;
 
-       init_enc_passwd(&q_u->lm_newpass, lm_newpass);
+       init_enc_passwd(&q_u->lm_newpass, (const char *)lm_newpass);
        init_enc_hash(&q_u->lm_oldhash, lm_oldhash);
 }
 
@@ -7129,14 +7287,180 @@ BOOL samr_io_r_chgpasswd_user(const char *desc, SAMR_R_CHGPASSWD_USER * r_u,
        return True;
 }
 
+/*******************************************************************
+inits a SAMR_Q_CHGPASSWD3 structure.
+********************************************************************/
+
+void init_samr_q_chgpasswd3(SAMR_Q_CHGPASSWD3 * q_u,
+                           const char *dest_host, const char *user_name,
+                           const uchar nt_newpass[516],
+                           const uchar nt_oldhash[16],
+                           const uchar lm_newpass[516],
+                           const uchar lm_oldhash[16])
+{
+       DEBUG(5, ("init_samr_q_chgpasswd3\n"));
+
+       q_u->ptr_0 = 1;
+       init_unistr2(&q_u->uni_dest_host, dest_host, UNI_FLAGS_NONE);
+       init_uni_hdr(&q_u->hdr_dest_host, &q_u->uni_dest_host);
+
+       init_unistr2(&q_u->uni_user_name, user_name, UNI_FLAGS_NONE);
+       init_uni_hdr(&q_u->hdr_user_name, &q_u->uni_user_name);
+
+       init_enc_passwd(&q_u->nt_newpass, (const char *)nt_newpass);
+       init_enc_hash(&q_u->nt_oldhash, nt_oldhash);
+
+       q_u->lm_change = 0x01;
+
+       init_enc_passwd(&q_u->lm_newpass, (const char *)lm_newpass);
+       init_enc_hash(&q_u->lm_oldhash, lm_oldhash);
+
+       init_enc_passwd(&q_u->password3, NULL);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_q_chgpasswd3(const char *desc, SAMR_Q_CHGPASSWD3 * q_u,
+                         prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_q_chgpasswd3");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("ptr_0", ps, depth, &q_u->ptr_0))
+               return False;
+
+       if(!smb_io_unihdr("", &q_u->hdr_dest_host, ps, depth))
+               return False;
+       if(!smb_io_unistr2("", &q_u->uni_dest_host, q_u->hdr_dest_host.buffer, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+       if(!smb_io_unihdr("", &q_u->hdr_user_name, ps, depth))
+               return False;
+       if(!smb_io_unistr2("", &q_u->uni_user_name, q_u->hdr_user_name.buffer,ps, depth))
+               return False;
+
+       if(!samr_io_enc_passwd("nt_newpass", &q_u->nt_newpass, ps, depth))
+               return False;
+       if(!samr_io_enc_hash("nt_oldhash", &q_u->nt_oldhash, ps, depth))
+               return False;
+
+       if(!prs_uint32("lm_change", ps, depth, &q_u->lm_change))
+               return False;
+
+       if(!samr_io_enc_passwd("lm_newpass", &q_u->lm_newpass, ps, depth))
+               return False;
+       if(!samr_io_enc_hash("lm_oldhash", &q_u->lm_oldhash, ps, depth))
+               return False;
+
+       if(!samr_io_enc_passwd("password3", &q_u->password3, ps, depth))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+inits a SAMR_R_CHGPASSWD3 structure.
+********************************************************************/
+
+void init_samr_r_chgpasswd3(SAMR_R_CHGPASSWD3 * r_u, NTSTATUS status)
+{
+       DEBUG(5, ("init_r_chgpasswd3\n"));
+
+       r_u->status = status;
+}
+
+/*******************************************************************
+ Reads or writes an SAMR_CHANGE_REJECT structure.
+********************************************************************/
+
+BOOL samr_io_change_reject(const char *desc, SAMR_CHANGE_REJECT *reject, prs_struct *ps, int depth)
+{
+       if (reject == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_change_reject");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(UNMARSHALLING(ps))
+               ZERO_STRUCTP(reject);
+       
+       if (!prs_uint32("reject_reason", ps, depth, &reject->reject_reason))
+               return False;
+               
+       if (!prs_uint32("unknown1", ps, depth, &reject->unknown1))
+               return False;
+
+       if (!prs_uint32("unknown2", ps, depth, &reject->unknown2))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_r_chgpasswd3(const char *desc, SAMR_R_CHGPASSWD3 * r_u,
+                         prs_struct *ps, int depth)
+{
+       uint32 ptr_info, ptr_reject;
+       
+       if (r_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_r_chgpasswd3");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("ptr_info", ps, depth, &ptr_info))
+               return False;
+
+       if (ptr_info) {
+
+               /* SAM_UNK_INFO_1 */
+               if(!sam_io_unk_info1("info", &r_u->info, ps, depth))
+                       return False;
+       }
+
+       if(!prs_uint32("ptr_reject", ps, depth, &ptr_reject))
+               return False;
+                            
+       if (ptr_reject) {
+
+               /* SAMR_CHANGE_REJECT */
+               if(!samr_io_change_reject("reject", &r_u->reject, ps, depth))
+                       return False;
+       }
+
+       if(!prs_ntstatus("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
 
-void init_samr_q_unknown_2e(SAMR_Q_UNKNOWN_2E *q_u,
+void init_samr_q_query_domain_info2(SAMR_Q_QUERY_DOMAIN_INFO2 *q_u,
                                POLICY_HND *domain_pol, uint16 switch_value)
 {
-       DEBUG(5, ("init_samr_q_unknown_2e\n"));
+       DEBUG(5, ("init_samr_q_query_domain_info2\n"));
 
        q_u->domain_pol = *domain_pol;
        q_u->switch_value = switch_value;
@@ -7146,13 +7470,13 @@ void init_samr_q_unknown_2e(SAMR_Q_UNKNOWN_2E *q_u,
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_q_unknown_2e(const char *desc, SAMR_Q_UNKNOWN_2E *q_u,
+BOOL samr_io_q_query_domain_info2(const char *desc, SAMR_Q_QUERY_DOMAIN_INFO2 *q_u,
                              prs_struct *ps, int depth)
 {
        if (q_u == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_io_q_unknown_2e");
+       prs_debug(ps, depth, desc, "samr_io_q_query_domain_info2");
        depth++;
 
        if(!prs_align(ps))
@@ -7171,11 +7495,11 @@ BOOL samr_io_q_unknown_2e(const char *desc, SAMR_Q_UNKNOWN_2E *q_u,
 inits a SAMR_R_QUERY_DOMAIN_INFO structure.
 ********************************************************************/
 
-void init_samr_r_samr_unknown_2e(SAMR_R_UNKNOWN_2E * r_u,
+void init_samr_r_samr_query_domain_info2(SAMR_R_QUERY_DOMAIN_INFO2 * r_u,
                                uint16 switch_value, SAM_UNK_CTR * ctr,
                                NTSTATUS status)
 {
-       DEBUG(5, ("init_samr_r_samr_unknown_2e\n"));
+       DEBUG(5, ("init_samr_r_samr_query_domain_info2\n"));
 
        r_u->ptr_0 = 0;
        r_u->switch_value = 0;
@@ -7192,13 +7516,13 @@ void init_samr_r_samr_unknown_2e(SAMR_R_UNKNOWN_2E * r_u,
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_r_samr_unknown_2e(const char *desc, SAMR_R_UNKNOWN_2E * r_u,
+BOOL samr_io_r_samr_query_domain_info2(const char *desc, SAMR_R_QUERY_DOMAIN_INFO2 * r_u,
                              prs_struct *ps, int depth)
 {
         if (r_u == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_io_r_samr_unknown_2e");
+       prs_debug(ps, depth, desc, "samr_io_r_samr_query_domain_info2");
        depth++;
 
        if(!prs_align(ps))
@@ -7243,7 +7567,7 @@ BOOL samr_io_r_samr_unknown_2e(const char *desc, SAMR_R_UNKNOWN_2E * r_u,
                                return False;
                        break;
                default:
-                       DEBUG(0, ("samr_io_r_samr_unknown_2e: unknown switch level 0x%x\n",
+                       DEBUG(0, ("samr_io_r_samr_query_domain_info2: unknown switch level 0x%x\n",
                                r_u->switch_value));
                        r_u->status = NT_STATUS_INVALID_INFO_CLASS;
                        return False;
@@ -7305,8 +7629,10 @@ BOOL samr_io_q_set_domain_info(const char *desc, SAMR_Q_SET_DOMAIN_INFO *q_u,
        if(!prs_align(ps))
                return False;
 
-       if ((q_u->ctr = (SAM_UNK_CTR *)prs_alloc_mem(ps, sizeof(SAM_UNK_CTR))) == NULL)
-               return False;
+       if (UNMARSHALLING(ps)) {
+               if ((q_u->ctr = PRS_ALLOC_MEM(ps, SAM_UNK_CTR, 1)) == NULL)
+                       return False;
+       }
        
        switch (q_u->switch_value) {