r18271: Big change:
[kai/samba.git] / source3 / rpc_parse / parse_samr.c
index e3db7d339cc73d54c6678d2480c2a58c30d357e0..eda3c428a9a3e7909b31959536b74ed890461540 100644 (file)
@@ -7,8 +7,7 @@
  *  Copyright (C) Elrond                            2000,
  *  Copyright (C) Jeremy Allison                    2001,
  *  Copyright (C) Jean François Micouleau      1998-2001,
- *  Copyright (C) Anthony Liguori                   2002,
- *  Copyright (C) Jim McDonough                     2002.
+ *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2002.
  *  
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -26,8 +25,6 @@
  */
 
 #include "includes.h"
-#include "rpc_parse.h"
-#include "nterr.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_PARSE
@@ -94,14 +91,12 @@ inits a SAMR_Q_LOOKUP_DOMAIN structure.
 void init_samr_q_lookup_domain(SAMR_Q_LOOKUP_DOMAIN * q_u,
                               POLICY_HND *pol, char *dom_name)
 {
-       int len_name = strlen(dom_name);
-
        DEBUG(5, ("init_samr_q_lookup_domain\n"));
 
        q_u->connect_pol = *pol;
 
-       init_uni_hdr(&q_u->hdr_domain, len_name);
-       init_unistr2(&q_u->uni_domain, dom_name);
+       init_unistr2(&q_u->uni_domain, dom_name, UNI_FLAGS_NONE);
+       init_uni_hdr(&q_u->hdr_domain, &q_u->uni_domain);
 }
 
 /*******************************************************************
@@ -184,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_unknown_2d(SAMR_Q_UNKNOWN_2D * 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_unknown_2d\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);
@@ -196,13 +191,13 @@ void init_samr_q_unknown_2d(SAMR_Q_UNKNOWN_2D * q_u, POLICY_HND *dom_pol, DOM_SI
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_q_unknown_2d(const char *desc, SAMR_Q_UNKNOWN_2D * 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_unknown_2d");
+       prs_debug(ps, depth, desc, "samr_io_q_remove_sid_foreign_domain");
        depth++;
 
        if(!prs_align(ps))
@@ -224,13 +219,13 @@ BOOL samr_io_q_unknown_2d(const char *desc, SAMR_Q_UNKNOWN_2D * q_u,
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_r_unknown_2d(const char *desc, SAMR_R_UNKNOWN_2D * 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_unknown_2d");
+       prs_debug(ps, depth, desc, "samr_io_r_remove_sid_foreign_domain");
        depth++;
 
        if(!prs_align(ps))
@@ -349,7 +344,7 @@ void init_samr_r_get_usrdom_pwinfo(SAMR_R_GET_USRDOM_PWINFO *r_u, NTSTATUS statu
 {
        DEBUG(5, ("init_samr_r_get_usrdom_pwinfo\n"));
        
-       r_u->unknown_0 = 0x0000;
+       r_u->min_pwd_length = 0x0000;
 
        /*
         * used to be   
@@ -359,7 +354,7 @@ void init_samr_r_get_usrdom_pwinfo(SAMR_R_GET_USRDOM_PWINFO *r_u, NTSTATUS statu
        r_u->unknown_1 = 0x01D1;
        r_u->unknown_1 = 0x0015;
 
-       r_u->unknown_2 = 0x00000000;
+       r_u->password_properties = 0x00000000;
 
        r_u->status = status;
 }
@@ -380,12 +375,13 @@ BOOL samr_io_r_get_usrdom_pwinfo(const char *desc, SAMR_R_GET_USRDOM_PWINFO * r_
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint16("unknown_0", ps, depth, &r_u->unknown_0))
+       if(!prs_uint16("min_pwd_length", ps, depth, &r_u->min_pwd_length))
                return False;
        if(!prs_uint16("unknown_1", ps, depth, &r_u->unknown_1))
                return False;
-       if(!prs_uint32("unknown_2", ps, depth, &r_u->unknown_2))
+       if(!prs_uint32("password_properties", ps, depth, &r_u->password_properties))
                return False;
+
        if(!prs_ntstatus("status   ", ps, depth, &r_u->status))
                return False;
 
@@ -465,10 +461,10 @@ BOOL samr_io_q_query_sec_obj(const char *desc, SAMR_Q_QUERY_SEC_OBJ * q_u,
 reads or writes a structure.
 ********************************************************************/
 
-void init_samr_q_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO * q_u,
-                               POLICY_HND *domain_pol, uint16 switch_value)
+void init_samr_q_query_domain_info(SAMR_Q_QUERY_DOMAIN_INFO * q_u,
+                                  POLICY_HND *domain_pol, uint16 switch_value)
 {
-       DEBUG(5, ("samr_init_samr_q_query_dom_info\n"));
+       DEBUG(5, ("samr_init_samr_q_query_domain_info\n"));
 
        q_u->domain_pol = *domain_pol;
        q_u->switch_value = switch_value;
@@ -478,13 +474,13 @@ void init_samr_q_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO * q_u,
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_q_query_dom_info(const char *desc, SAMR_Q_QUERY_DOMAIN_INFO * q_u,
-                             prs_struct *ps, int depth)
+BOOL samr_io_q_query_domain_info(const char *desc, SAMR_Q_QUERY_DOMAIN_INFO * q_u,
+                                prs_struct *ps, int depth)
 {
        if (q_u == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_io_q_query_dom_info");
+       prs_debug(ps, depth, desc, "samr_io_q_query_domain_info");
        depth++;
 
        if(!prs_align(ps))
@@ -499,31 +495,51 @@ BOOL samr_io_q_query_dom_info(const char *desc, SAMR_Q_QUERY_DOMAIN_INFO * q_u,
        return True;
 }
 
-
 /*******************************************************************
 inits a structure.
 ********************************************************************/
 
-void init_unk_info3(SAM_UNK_INFO_3 *u_3, NTTIME nt_logout)
+void init_unk_info1(SAM_UNK_INFO_1 *u_1, uint16 min_pass_len, uint16 pass_hist, 
+                   uint32 password_properties, NTTIME nt_expire, NTTIME nt_min_age)
 {
-       u_3->logout.low = nt_logout.low;
-       u_3->logout.high = nt_logout.high;
+       u_1->min_length_password = min_pass_len;
+       u_1->password_history = pass_hist;
+       
+       if (lp_check_password_script() && *lp_check_password_script()) {
+               password_properties |= DOMAIN_PASSWORD_COMPLEX;
+       }
+       u_1->password_properties = password_properties;
+
+       /* password never expire */
+       u_1->expire = nt_expire;
+
+       /* can change the password now */
+       u_1->min_passwordage = nt_min_age;
+       
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
 
-static BOOL sam_io_unk_info3(const char *desc, SAM_UNK_INFO_3 * u_3,
+static BOOL sam_io_unk_info1(const char *desc, SAM_UNK_INFO_1 * u_1,
                             prs_struct *ps, int depth)
 {
-       if (u_3 == NULL)
-               return False;
+       if (u_1 == NULL)
+         return False;
 
-       prs_debug(ps, depth, desc, "sam_io_unk_info3");
+       prs_debug(ps, depth, desc, "sam_io_unk_info1");
        depth++;
 
-       if(!smb_io_time("logout", &u_3->logout, ps, depth))
+       if(!prs_uint16("min_length_password", ps, depth, &u_1->min_length_password))
+               return False;
+       if(!prs_uint16("password_history", ps, depth, &u_1->password_history))
+               return False;
+       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;
+       if(!smb_io_time("min_passwordage", &u_1->min_passwordage, ps, depth))
                return False;
 
        return True;
@@ -533,31 +549,77 @@ static BOOL sam_io_unk_info3(const char *desc, SAM_UNK_INFO_3 * u_3,
 inits a structure.
 ********************************************************************/
 
-void init_unk_info6(SAM_UNK_INFO_6 * u_6)
+void init_unk_info2(SAM_UNK_INFO_2 * u_2,
+                       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_6->unknown_0 = 0x00000000;
-       u_6->ptr_0 = 1;
-       memset(u_6->padding, 0, sizeof(u_6->padding));  /* 12 bytes zeros */
+       u_2->logout = nt_logout;
+
+       u_2->seq_num = seq_num;
+
+
+       u_2->unknown_4 = 0x00000001;
+       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;
+       u_2->num_local_grps = num_alias;
+
+       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);
+       init_uni_hdr(&u_2->hdr_server, &u_2->uni_server);
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
 
-static BOOL sam_io_unk_info6(const char *desc, SAM_UNK_INFO_6 * u_6,
+static BOOL sam_io_unk_info2(const char *desc, SAM_UNK_INFO_2 * u_2,
                             prs_struct *ps, int depth)
 {
-       if (u_6 == NULL)
+       if (u_2 == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "sam_io_unk_info6");
+       prs_debug(ps, depth, desc, "sam_io_unk_info2");
        depth++;
 
-       if(!prs_uint32("unknown_0", ps, depth, &u_6->unknown_0)) /* 0x0000 0000 */
+       if(!smb_io_time("logout", &u_2->logout, ps, depth))
+               return False;
+       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;
+       if(!smb_io_unihdr("hdr_server", &u_2->hdr_server, ps, depth))
+               return False;
+
+       /* put all the data in here, at the moment, including what the above
+          pointer is referring to
+        */
+
+       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("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;
+       if(!prs_uint32("num_domain_usrs ", ps, depth, &u_2->num_domain_usrs))
+               return False;
+       if(!prs_uint32("num_domain_grps", ps, depth, &u_2->num_domain_grps))
+               return False;
+       if(!prs_uint32("num_local_grps", ps, depth, &u_2->num_local_grps))
+               return False;
+
+       if(!smb_io_unistr2("uni_comment", &u_2->uni_comment, u_2->hdr_comment.buffer, ps, depth))
                return False;
-       if(!prs_uint32("ptr_0", ps, depth, &u_6->ptr_0)) /* pointer to unknown structure */
+       if(!smb_io_unistr2("uni_domain", &u_2->uni_domain, u_2->hdr_domain.buffer, ps, depth))
                return False;
-       if(!prs_uint8s(False, "padding", ps, depth, u_6->padding, sizeof(u_6->padding)))        /* 12 bytes zeros */
+       if(!smb_io_unistr2("uni_server", &u_2->uni_server, u_2->hdr_server.buffer, ps, depth))
                return False;
 
        return True;
@@ -567,25 +629,25 @@ 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_info3(SAM_UNK_INFO_3 *u_3, NTTIME nt_logout)
 {
-       u_7->unknown_0 = 0x0003;
+       u_3->logout = nt_logout;
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
 
-static BOOL sam_io_unk_info7(const char *desc, SAM_UNK_INFO_7 * u_7,
+static BOOL sam_io_unk_info3(const char *desc, SAM_UNK_INFO_3 * u_3,
                             prs_struct *ps, int depth)
 {
-       if (u_7 == NULL)
+       if (u_3 == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "sam_io_unk_info7");
+       prs_debug(ps, depth, desc, "sam_io_unk_info3");
        depth++;
 
-       if(!prs_uint16("unknown_0", ps, depth, &u_7->unknown_0)) /* 0x0003 */
+       if(!smb_io_time("logout", &u_3->logout, ps, depth))
                return False;
 
        return True;
@@ -595,34 +657,29 @@ static BOOL sam_io_unk_info7(const char *desc, SAM_UNK_INFO_7 * u_7,
 inits a structure.
 ********************************************************************/
 
-void init_unk_info12(SAM_UNK_INFO_12 * u_12, NTTIME nt_lock_duration, NTTIME nt_reset_time, uint16 lockout)
+void init_unk_info4(SAM_UNK_INFO_4 * u_4,const char *comment)
 {
-       u_12->duration.low = nt_lock_duration.low;
-       u_12->duration.high = nt_lock_duration.high;
-       u_12->reset_count.low = nt_reset_time.low;
-       u_12->reset_count.high = nt_reset_time.high;
-
-       u_12->bad_attempt_lockout = lockout;
+       init_unistr2(&u_4->uni_comment, comment, UNI_FLAGS_NONE);
+       init_uni_hdr(&u_4->hdr_comment, &u_4->uni_comment);
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
 
-static BOOL sam_io_unk_info12(const char *desc, SAM_UNK_INFO_12 * u_12,
-                             prs_struct *ps, int depth)
+static BOOL sam_io_unk_info4(const char *desc, SAM_UNK_INFO_4 * u_4,
+                            prs_struct *ps, int depth)
 {
-       if (u_12 == NULL)
+       if (u_4 == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "sam_io_unk_info12");
+       prs_debug(ps, depth, desc, "sam_io_unk_info4");
        depth++;
 
-       if(!smb_io_time("duration", &u_12->duration, ps, depth))
-               return False;
-       if(!smb_io_time("reset_count", &u_12->reset_count, ps, depth))
+       if(!smb_io_unihdr("hdr_comment", &u_4->hdr_comment, ps, depth))
                return False;
-       if(!prs_uint16("bad_attempt_lockout", ps, depth, &u_12->bad_attempt_lockout))
+
+       if(!smb_io_unistr2("uni_comment", &u_4->uni_comment, u_4->hdr_comment.buffer, ps, depth))
                return False;
 
        return True;
@@ -631,13 +688,11 @@ static BOOL sam_io_unk_info12(const char *desc, SAM_UNK_INFO_12 * u_12,
 /*******************************************************************
 inits a structure.
 ********************************************************************/
-void init_unk_info5(SAM_UNK_INFO_5 * u_5,const char *server)
-{
-       int len_server = strlen(server);
-
-       init_uni_hdr(&u_5->hdr_server, len_server);
 
-       init_unistr2(&u_5->uni_server, server);
+void init_unk_info5(SAM_UNK_INFO_5 * u_5,const char *domain)
+{
+       init_unistr2(&u_5->uni_domain, domain, UNI_FLAGS_NONE);
+       init_uni_hdr(&u_5->hdr_domain, &u_5->uni_domain);
 }
 
 /*******************************************************************
@@ -653,10 +708,10 @@ static BOOL sam_io_unk_info5(const char *desc, SAM_UNK_INFO_5 * u_5,
        prs_debug(ps, depth, desc, "sam_io_unk_info5");
        depth++;
 
-       if(!smb_io_unihdr("hdr_server", &u_5->hdr_server, ps, depth))
+       if(!smb_io_unihdr("hdr_domain", &u_5->hdr_domain, ps, depth))
                return False;
 
-       if(!smb_io_unistr2("uni_server", &u_5->uni_server, u_5->hdr_server.buffer, ps, depth))
+       if(!smb_io_unistr2("uni_domain", &u_5->uni_domain, u_5->hdr_domain.buffer, ps, depth))
                return False;
 
        return True;
@@ -665,98 +720,153 @@ static BOOL sam_io_unk_info5(const char *desc, SAM_UNK_INFO_5 * u_5,
 /*******************************************************************
 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)
+
+void init_unk_info6(SAM_UNK_INFO_6 * u_6, const char *server)
 {
-       int len_domain = strlen(domain);
-       int len_server = strlen(server);
+       init_unistr2(&u_6->uni_server, server, UNI_FLAGS_NONE);
+       init_uni_hdr(&u_6->hdr_server, &u_6->uni_server);
+}
 
-       u_2->unknown_0 = 0x00000000;
-       u_2->unknown_1 = 0x80000000;
-       u_2->unknown_2 = 0x00000000;
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
 
-       u_2->ptr_0 = 1;
-       init_uni_hdr(&u_2->hdr_domain, len_domain);
-       init_uni_hdr(&u_2->hdr_server, len_server);
+static BOOL sam_io_unk_info6(const char *desc, SAM_UNK_INFO_6 * u_6,
+                            prs_struct *ps, int depth)
+{
+       if (u_6 == NULL)
+               return False;
 
-       u_2->seq_num = seq_num;
-       u_2->unknown_3 = 0x00000000;
+       prs_debug(ps, depth, desc, "sam_io_unk_info6");
+       depth++;
 
-       u_2->unknown_4 = 0x00000001;
-       u_2->unknown_5 = 0x00000003;
-       u_2->unknown_6 = 0x00000001;
-       u_2->num_domain_usrs = num_users;
-       u_2->num_domain_grps = num_groups;
-       u_2->num_local_grps = num_alias;
+       if(!smb_io_unihdr("hdr_server", &u_6->hdr_server, ps, depth))
+               return False;
+
+       if(!smb_io_unistr2("uni_server", &u_6->uni_server, u_6->hdr_server.buffer, ps, depth))
+               return False;
+
+       return True;
+}
 
-       memset(u_2->padding, 0, sizeof(u_2->padding));  /* 12 bytes zeros */
+/*******************************************************************
+inits a structure.
+********************************************************************/
 
-       init_unistr2(&u_2->uni_domain, domain);
-       init_unistr2(&u_2->uni_server, server);
+void init_unk_info7(SAM_UNK_INFO_7 * u_7, uint32 server_role)
+{
+       u_7->server_role = server_role;
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
 
-static BOOL sam_io_unk_info2(const char *desc, SAM_UNK_INFO_2 * u_2,
+static BOOL sam_io_unk_info7(const char *desc, SAM_UNK_INFO_7 * u_7,
                             prs_struct *ps, int depth)
 {
-       if (u_2 == NULL)
+       if (u_7 == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "sam_io_unk_info2");
+       prs_debug(ps, depth, desc, "sam_io_unk_info7");
        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 */
-               return False;
-       if(!prs_uint32("unknown_2", ps, depth, &u_2->unknown_2))        /* 0x0000 0000 */
+       if(!prs_uint16("server_role", ps, depth, &u_7->server_role))
                return False;
 
-       if(!prs_uint32("ptr_0", ps, depth, &u_2->ptr_0))
-               return False;
-       if(!smb_io_unihdr("hdr_domain", &u_2->hdr_domain, ps, depth))
-               return False;
-       if(!smb_io_unihdr("hdr_server", &u_2->hdr_server, ps, depth))
-               return False;
+       return True;
+}
 
-       /* put all the data in here, at the moment, including what the above
-          pointer is referring to
-        */
+/*******************************************************************
+inits a structure.
+********************************************************************/
 
-       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 */
-               return False;
+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 = seq_num;
+}
 
-       if(!prs_uint32("unknown_4 ", ps, depth, &u_2->unknown_4)) /* 0x0000 0001 */
+/*******************************************************************
+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;
-       if(!prs_uint32("unknown_5 ", ps, depth, &u_2->unknown_5)) /* 0x0000 0003 */
+
+       prs_debug(ps, depth, desc, "sam_io_unk_info8");
+       depth++;
+
+       if (!prs_uint64("seq_num", ps, depth, &u_8->seq_num))
                return False;
-       if(!prs_uint32("unknown_6 ", ps, depth, &u_2->unknown_6)) /* 0x0000 0001 */
+
+       if(!smb_io_time("domain_create_time", &u_8->domain_create_time, ps, depth))
                return False;
-       if(!prs_uint32("num_domain_usrs ", ps, depth, &u_2->num_domain_usrs))
+
+       return True;
+}
+
+/*******************************************************************
+inits a structure.
+********************************************************************/
+
+void init_unk_info9(SAM_UNK_INFO_9 * u_9, uint32 unknown)
+{
+       u_9->unknown = unknown;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL sam_io_unk_info9(const char *desc, SAM_UNK_INFO_9 * u_9,
+                            prs_struct *ps, int depth)
+{
+       if (u_9 == NULL)
                return False;
-       if(!prs_uint32("num_domain_grps", ps, depth, &u_2->num_domain_grps))
+
+       prs_debug(ps, depth, desc, "sam_io_unk_info9");
+       depth++;
+
+       if (!prs_uint32("unknown", ps, depth, &u_9->unknown))
                return False;
-       if(!prs_uint32("num_local_grps", ps, depth, &u_2->num_local_grps))
+
+       return True;
+}
+
+/*******************************************************************
+inits a structure.
+********************************************************************/
+
+void init_unk_info12(SAM_UNK_INFO_12 * u_12, NTTIME nt_lock_duration, NTTIME nt_reset_time, uint16 lockout)
+{
+       u_12->duration = nt_lock_duration;
+       u_12->reset_count = nt_reset_time;
+
+       u_12->bad_attempt_lockout = lockout;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL sam_io_unk_info12(const char *desc, SAM_UNK_INFO_12 * u_12,
+                             prs_struct *ps, int depth)
+{
+       if (u_12 == NULL)
                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;
-       }
+       prs_debug(ps, depth, desc, "sam_io_unk_info12");
+       depth++;
 
-       if(!smb_io_unistr2("uni_domain", &u_2->uni_domain, u_2->hdr_domain.buffer, ps, depth))
+       if(!smb_io_time("duration", &u_12->duration, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_server", &u_2->uni_server, u_2->hdr_server.buffer, ps, depth))
+       if(!smb_io_time("reset_count", &u_12->reset_count, ps, depth))
+               return False;
+       if(!prs_uint16("bad_attempt_lockout", ps, depth, &u_12->bad_attempt_lockout))
                return False;
 
        return True;
@@ -766,45 +876,36 @@ static BOOL sam_io_unk_info2(const char *desc, SAM_UNK_INFO_2 * u_2,
 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)
+void init_unk_info13(SAM_UNK_INFO_13 * u_13, uint32 seq_num)
 {
-       u_1->min_length_password = min_pass_len;
-       u_1->password_history = pass_hist;
-       u_1->flag = flag;
-       
-       /* password never expire */
-       u_1->expire.high = nt_expire.high;
-       u_1->expire.low = nt_expire.low;
-       
-       /* can change the password now */
-       u_1->min_passwordage.high = nt_min_age.high;
-       u_1->min_passwordage.low = nt_min_age.low;
-       
+       unix_to_nt_time(&u_13->domain_create_time, 0);
+       u_13->seq_num = seq_num;
+       u_13->unknown1 = 0;
+       u_13->unknown2 = 0;
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
 
-static BOOL sam_io_unk_info1(const char *desc, SAM_UNK_INFO_1 * u_1,
+static BOOL sam_io_unk_info13(const char *desc, SAM_UNK_INFO_13 * u_13,
                             prs_struct *ps, int depth)
 {
-       if (u_1 == NULL)
-         return False;
+       if (u_13 == NULL)
+               return False;
 
-       prs_debug(ps, depth, desc, "sam_io_unk_info1");
+       prs_debug(ps, depth, desc, "sam_io_unk_info13");
        depth++;
 
-       if(!prs_uint16("min_length_password", ps, depth, &u_1->min_length_password))
+       if (!prs_uint64("seq_num", ps, depth, &u_13->seq_num))
                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(!smb_io_time("domain_create_time", &u_13->domain_create_time, ps, depth))
                return False;
-       if(!smb_io_time("expire", &u_1->expire, ps, depth))
+
+       if (!prs_uint32("unknown1", ps, depth, &u_13->unknown1))
                return False;
-       if(!smb_io_time("min_passwordage", &u_1->min_passwordage, ps, depth))
+       if (!prs_uint32("unknown2", ps, depth, &u_13->unknown2))
                return False;
 
        return True;
@@ -814,11 +915,11 @@ static BOOL sam_io_unk_info1(const char *desc, SAM_UNK_INFO_1 * u_1,
 inits a SAMR_R_QUERY_DOMAIN_INFO structure.
 ********************************************************************/
 
-void init_samr_r_query_dom_info(SAMR_R_QUERY_DOMAIN_INFO * r_u,
-                               uint16 switch_value, SAM_UNK_CTR * ctr,
-                               NTSTATUS status)
+void init_samr_r_query_domain_info(SAMR_R_QUERY_DOMAIN_INFO * r_u,
+                                  uint16 switch_value, SAM_UNK_CTR * ctr,
+                                  NTSTATUS status)
 {
-       DEBUG(5, ("init_samr_r_query_dom_info\n"));
+       DEBUG(5, ("init_samr_r_query_domain_info\n"));
 
        r_u->ptr_0 = 0;
        r_u->switch_value = 0;
@@ -835,13 +936,13 @@ void init_samr_r_query_dom_info(SAMR_R_QUERY_DOMAIN_INFO * r_u,
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
-                             prs_struct *ps, int depth)
+BOOL samr_io_r_query_domain_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
+                                prs_struct *ps, int depth)
 {
         if (r_u == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_io_r_query_dom_info");
+       prs_debug(ps, depth, desc, "samr_io_r_query_domain_info");
        depth++;
 
        if(!prs_align(ps))
@@ -857,10 +958,22 @@ BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
                        return False;
 
                switch (r_u->switch_value) {
+               case 0x0d:
+                       if(!sam_io_unk_info13("unk_inf13", &r_u->ctr->info.inf13, ps, depth))
+                               return False;
+                       break;
                case 0x0c:
                        if(!sam_io_unk_info12("unk_inf12", &r_u->ctr->info.inf12, ps, depth))
                                return False;
                        break;
+               case 0x09:
+                       if(!sam_io_unk_info9("unk_inf9",&r_u->ctr->info.inf9, 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;
@@ -873,6 +986,10 @@ BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
                        if(!sam_io_unk_info5("unk_inf5",&r_u->ctr->info.inf5, ps,depth))
                                return False;
                        break;
+               case 0x04:
+                       if(!sam_io_unk_info4("unk_inf4",&r_u->ctr->info.inf4, ps,depth))
+                               return False;
+                       break;
                case 0x03:
                        if(!sam_io_unk_info3("unk_inf3",&r_u->ctr->info.inf3, ps,depth))
                                return False;
@@ -886,7 +1003,7 @@ BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
                                return False;
                        break;
                default:
-                       DEBUG(0, ("samr_io_r_query_dom_info: unknown switch level 0x%x\n",
+                       DEBUG(0, ("samr_io_r_query_domain_info: unknown switch level 0x%x\n",
                                r_u->switch_value));
                        r_u->status = NT_STATUS_INVALID_INFO_CLASS;
                        return False;
@@ -902,6 +1019,21 @@ BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
        return True;
 }
 
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+void init_samr_q_set_sec_obj(SAMR_Q_SET_SEC_OBJ * q_u,
+                            POLICY_HND *pol, uint32 sec_info, SEC_DESC_BUF *buf)
+{
+       DEBUG(5, ("samr_init_samr_q_set_sec_obj\n"));
+
+       q_u->pol = *pol;
+       q_u->sec_info = sec_info;
+       q_u->buf = buf;
+}
+
+
 /*******************************************************************
 reads or writes a SAMR_R_SET_SEC_OBJ structure.
 ********************************************************************/
@@ -985,10 +1117,10 @@ static BOOL sam_io_sam_str1(const char *desc, SAM_STR1 * sam, uint32 acct_buf,
 inits a SAM_ENTRY1 structure.
 ********************************************************************/
 
-static void init_sam_entry1(SAM_ENTRY1 * sam, uint32 user_idx,
-                           uint32 len_sam_name, uint32 len_sam_full,
-                           uint32 len_sam_desc, uint32 rid_user,
-                           uint16 acb_info)
+static void init_sam_entry1(SAM_ENTRY1 *sam, uint32 user_idx,
+                           UNISTR2 *sam_name, UNISTR2 *sam_full,
+                           UNISTR2 *sam_desc, uint32 rid_user,
+                           uint32 acb_info)
 {
        DEBUG(5, ("init_sam_entry1\n"));
 
@@ -998,9 +1130,9 @@ static void init_sam_entry1(SAM_ENTRY1 * sam, uint32 user_idx,
        sam->rid_user = rid_user;
        sam->acb_info = acb_info;
 
-       init_uni_hdr(&sam->hdr_acct_name, len_sam_name);
-       init_uni_hdr(&sam->hdr_user_name, len_sam_full);
-       init_uni_hdr(&sam->hdr_user_desc, len_sam_desc);
+       init_uni_hdr(&sam->hdr_acct_name, sam_name);
+       init_uni_hdr(&sam->hdr_user_name, sam_full);
+       init_uni_hdr(&sam->hdr_user_desc, sam_desc);
 }
 
 /*******************************************************************
@@ -1024,10 +1156,7 @@ static BOOL sam_io_sam_entry1(const char *desc, SAM_ENTRY1 * sam,
 
        if(!prs_uint32("rid_user ", ps, depth, &sam->rid_user))
                return False;
-       if(!prs_uint16("acb_info ", ps, depth, &sam->acb_info))
-               return False;
-
-       if(!prs_align(ps))
+       if(!prs_uint32("acb_info ", ps, depth, &sam->acb_info))
                return False;
 
        if (!smb_io_unihdr("hdr_acct_name", &sam->hdr_acct_name, ps, depth))
@@ -1068,8 +1197,8 @@ static BOOL sam_io_sam_str2(const char *desc, SAM_STR2 * sam, uint32 acct_buf,
 inits a SAM_ENTRY2 structure.
 ********************************************************************/
 static void init_sam_entry2(SAM_ENTRY2 * sam, uint32 user_idx,
-                           uint32 len_sam_name, uint32 len_sam_desc,
-                           uint32 rid_user, uint16 acb_info)
+                           UNISTR2 *sam_name, UNISTR2 *sam_desc,
+                           uint32 rid_user, uint32 acb_info)
 {
        DEBUG(5, ("init_sam_entry2\n"));
 
@@ -1077,8 +1206,8 @@ static void init_sam_entry2(SAM_ENTRY2 * sam, uint32 user_idx,
        sam->rid_user = rid_user;
        sam->acb_info = acb_info;
 
-       init_uni_hdr(&sam->hdr_srv_name, len_sam_name);
-       init_uni_hdr(&sam->hdr_srv_desc, len_sam_desc);
+       init_uni_hdr(&sam->hdr_srv_name, sam_name);
+       init_uni_hdr(&sam->hdr_srv_desc, sam_desc);
 }
 
 /*******************************************************************
@@ -1102,10 +1231,7 @@ static BOOL sam_io_sam_entry2(const char *desc, SAM_ENTRY2 * sam,
 
        if(!prs_uint32("rid_user ", ps, depth, &sam->rid_user))
                return False;
-       if(!prs_uint16("acb_info ", ps, depth, &sam->acb_info))
-               return False;
-
-       if(!prs_align(ps))
+       if(!prs_uint32("acb_info ", ps, depth, &sam->acb_info))
                return False;
 
        if(!smb_io_unihdr("unihdr", &sam->hdr_srv_name, ps, depth))     /* account name unicode string header */
@@ -1145,7 +1271,7 @@ inits a SAM_ENTRY3 structure.
 ********************************************************************/
 
 static void init_sam_entry3(SAM_ENTRY3 * sam, uint32 grp_idx,
-                           uint32 len_grp_name, uint32 len_grp_desc,
+                           UNISTR2 *grp_name, UNISTR2 *grp_desc,
                            uint32 rid_grp)
 {
        DEBUG(5, ("init_sam_entry3\n"));
@@ -1154,8 +1280,8 @@ static void init_sam_entry3(SAM_ENTRY3 * sam, uint32 grp_idx,
        sam->rid_grp = rid_grp;
        sam->attr = 0x07;       /* group rid attributes - gets ignored by nt 4.0 */
 
-       init_uni_hdr(&sam->hdr_grp_name, len_grp_name);
-       init_uni_hdr(&sam->hdr_grp_desc, len_grp_desc);
+       init_uni_hdr(&sam->hdr_grp_name, grp_name);
+       init_uni_hdr(&sam->hdr_grp_desc, grp_desc);
 }
 
 /*******************************************************************
@@ -1269,12 +1395,12 @@ static BOOL sam_io_sam_entry5(const char *desc, SAM_ENTRY5 * sam,
 inits a SAM_ENTRY structure.
 ********************************************************************/
 
-void init_sam_entry(SAM_ENTRY * sam, uint32 len_sam_name, uint32 rid)
+void init_sam_entry(SAM_ENTRY *sam, UNISTR2 *uni2, uint32 rid)
 {
-       DEBUG(10, ("init_sam_entry: %d %d\n", len_sam_name, rid));
+       DEBUG(10, ("init_sam_entry: %d\n", rid));
 
        sam->rid = rid;
-       init_uni_hdr(&sam->hdr_name, len_sam_name);
+       init_uni_hdr(&sam->hdr_name, uni2);
 }
 
 /*******************************************************************
@@ -1306,7 +1432,7 @@ inits a SAMR_Q_ENUM_DOM_USERS structure.
 
 void init_samr_q_enum_dom_users(SAMR_Q_ENUM_DOM_USERS * q_e, POLICY_HND *pol,
                                uint32 start_idx,
-                               uint16 acb_mask, uint16 unk_1, uint32 size)
+                               uint32 acb_mask, uint32 size)
 {
        DEBUG(5, ("init_samr_q_enum_dom_users\n"));
 
@@ -1314,7 +1440,6 @@ void init_samr_q_enum_dom_users(SAMR_Q_ENUM_DOM_USERS * q_e, POLICY_HND *pol,
 
        q_e->start_idx = start_idx;     /* zero indicates lots */
        q_e->acb_mask = acb_mask;
-       q_e->unknown_1 = unk_1;
        q_e->max_size = size;
 }
 
@@ -1339,9 +1464,7 @@ BOOL samr_io_q_enum_dom_users(const char *desc, SAMR_Q_ENUM_DOM_USERS * q_e,
 
        if(!prs_uint32("start_idx", ps, depth, &q_e->start_idx))
                return False;
-       if(!prs_uint16("acb_mask ", ps, depth, &q_e->acb_mask))
-               return False;
-       if(!prs_uint16("unknown_1", ps, depth, &q_e->unknown_1))
+       if(!prs_uint32("acb_mask ", ps, depth, &q_e->acb_mask))
                return False;
 
        if(!prs_uint32("max_size ", ps, depth, &q_e->max_size))
@@ -1408,8 +1531,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) {
@@ -1448,7 +1571,7 @@ inits a SAMR_Q_QUERY_DISPINFO structure.
 
 void init_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO * q_e, POLICY_HND *pol,
                                uint16 switch_level, uint32 start_idx,
-                               uint32 max_entries)
+                               uint32 max_entries, uint32 max_size)
 {
        DEBUG(5, ("init_samr_q_query_dispinfo\n"));
 
@@ -1458,7 +1581,7 @@ void init_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO * q_e, POLICY_HND *pol,
 
        q_e->start_idx = start_idx;
        q_e->max_entries = max_entries;
-       q_e->max_size = 0xffff; /* Not especially useful */
+       q_e->max_size = max_size;
 }
 
 /*******************************************************************
@@ -1499,83 +1622,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, DISP_USER_INFO *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 len_sam_name, len_sam_full, len_sam_desc;
        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].sam;
-               
-               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;
-               }
-                       
-               len_sam_name = strlen(username);
-               len_sam_full = strlen(fullname);
-               len_sam_desc = strlen(acct_desc);
-
-               init_sam_entry1(&sam->sam[i], start_idx + i + 1,
-                               len_sam_name, len_sam_full, len_sam_desc,
-                               user_rid, pdb_get_acct_ctrl(pwd));
-               
-               ZERO_STRUCTP(&sam->str[i].uni_acct_name);
-               ZERO_STRUCTP(&sam->str[i].uni_full_name);
-               ZERO_STRUCTP(&sam->str[i].uni_acct_desc);
-
-               init_unistr2(&sam->str[i].uni_acct_name, pdb_get_username(pwd));
-               init_unistr2(&sam->str[i].uni_full_name, pdb_get_fullname(pwd));
-               init_unistr2(&sam->str[i].uni_acct_desc, pdb_get_acct_desc(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;
@@ -1599,16 +1681,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;
                }
@@ -1634,65 +1712,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, DISP_USER_INFO *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 len_sam_name, len_sam_desc;
        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].sam;
-
-               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;
-               }
-                       
-               len_sam_name = strlen(username);
-               len_sam_desc = strlen(acct_desc);
-         
-               init_sam_entry2(&sam->sam[i], start_idx + i + 1,
-                         len_sam_name, len_sam_desc,
-                         user_rid, pdb_get_acct_ctrl(pwd));
-         
-               ZERO_STRUCTP(&sam->str[i].uni_srv_name);
-               ZERO_STRUCTP(&sam->str[i].uni_srv_desc);
-
-               init_unistr2(&sam->str[i].uni_srv_name, username);
-               init_unistr2(&sam->str[i].uni_srv_desc, pdb_get_acct_desc(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;
@@ -1719,16 +1771,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;
                }
@@ -1753,40 +1801,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, DISP_GROUP_INFO *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 len_sam_name, len_sam_desc;
        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].grp;
-
                DEBUG(11, ("init_sam_dispinfo_3: entry: %d\n",i));
 
-               len_sam_name = strlen(grp->name);
-               len_sam_desc = strlen(grp->comment);
+               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, len_sam_name, len_sam_desc, grp->rid);
-         
-               init_unistr2(&sam->str[i].uni_grp_name, grp->name);
-               init_unistr2(&sam->str[i].uni_grp_desc, grp->comment);
+               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;
@@ -1813,16 +1860,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;
                }
@@ -1847,38 +1890,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, DISP_USER_INFO *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].sam;
+               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;
@@ -1905,16 +1950,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;
                }
@@ -1938,37 +1979,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, DISP_GROUP_INFO *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].grp;
-
                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;
@@ -1995,16 +2035,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;
                }
@@ -2211,20 +2247,15 @@ void init_samr_group_info1(GROUP_INFO1 * gr1,
                           char *acct_name, char *acct_desc,
                           uint32 num_members)
 {
-       int desc_len = acct_desc != NULL ? strlen(acct_desc) : 0;
-       int acct_len = acct_name != NULL ? strlen(acct_name) : 0;
-
        DEBUG(5, ("init_samr_group_info1\n"));
 
-       init_uni_hdr(&gr1->hdr_acct_name, acct_len);
-
-       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_uni_hdr(&gr1->hdr_acct_desc, desc_len);
-
-       init_unistr2(&gr1->uni_acct_name, acct_name);
-       init_unistr2(&gr1->uni_acct_desc, acct_desc);
+       init_unistr2(&gr1->uni_acct_name, acct_name, UNI_FLAGS_NONE);
+       init_uni_hdr(&gr1->hdr_acct_name, &gr1->uni_acct_name);
+       init_unistr2(&gr1->uni_acct_desc, acct_desc, UNI_FLAGS_NONE);
+       init_uni_hdr(&gr1->hdr_acct_desc, &gr1->uni_acct_desc);
 }
 
 /*******************************************************************
@@ -2234,19 +2265,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;
@@ -2265,6 +2301,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.
 ********************************************************************/
@@ -2273,7 +2346,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 ? */
 }
 
 /*******************************************************************
@@ -2291,7 +2364,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;
@@ -2301,14 +2374,13 @@ 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)
 {
-       int acct_len = acct_desc != NULL ? strlen(acct_desc) : 0;
-
        DEBUG(5, ("init_samr_group_info4\n"));
 
-       init_uni_hdr(&gr4->hdr_acct_desc, acct_len);
-       init_unistr2(&gr4->uni_acct_desc, acct_desc);
+       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);
 }
 
 /*******************************************************************
@@ -2324,18 +2396,80 @@ 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,
+                          gr4->hdr_acct_desc.buffer, ps, depth))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+inits a GROUP_INFO5 structure.
+********************************************************************/
+
+void init_samr_group_info5(GROUP_INFO5 * gr5,
+                          char *acct_name, char *acct_desc,
+                          uint32 num_members)
+{
+       DEBUG(5, ("init_samr_group_info5\n"));
+
+       gr5->group_attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT); /* why not | SE_GROUP_ENABLED ? */
+       gr5->num_members = num_members;
+
+       init_unistr2(&gr5->uni_acct_name, acct_name, UNI_FLAGS_NONE);
+       init_uni_hdr(&gr5->hdr_acct_name, &gr5->uni_acct_name);
+       init_unistr2(&gr5->uni_acct_desc, acct_desc, UNI_FLAGS_NONE);
+       init_uni_hdr(&gr5->hdr_acct_desc, &gr5->uni_acct_desc);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_group_info5(const char *desc, GROUP_INFO5 * gr5,
+                        prs_struct *ps, int depth)
+{
+       uint16 dummy = 1;
+
+       if (gr5 == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_group_info5");
+       depth++;
+
+       if(!prs_uint16("level", ps, depth, &dummy))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_unihdr("hdr_acct_name", &gr5->hdr_acct_name, ps, depth))
+               return False;
+
+       if(!prs_uint32("group_attr", ps, depth, &gr5->group_attr))
+               return False;
+       if(!prs_uint32("num_members", ps, depth, &gr5->num_members))
+               return False;
+
+       if(!smb_io_unihdr("hdr_acct_desc", &gr5->hdr_acct_desc, ps, depth))
                return False;
 
-       if(!smb_io_unihdr("hdr_acct_desc", &gr4->hdr_acct_desc, ps, depth))
+       if(!smb_io_unistr2("uni_acct_name", &gr5->uni_acct_name,
+                          gr5->hdr_acct_name.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_acct_desc", &gr4->uni_acct_desc,
-                          gr4->hdr_acct_desc.buffer, ps, depth))
+
+       if(!smb_io_unistr2("uni_acct_desc", &gr5->uni_acct_desc,
+                          gr5->hdr_acct_desc.buffer, ps, depth))
                return False;
 
        return True;
 }
 
+
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
@@ -2344,7 +2478,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;
@@ -2360,6 +2494,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;
@@ -2368,6 +2506,10 @@ static BOOL samr_group_info_ctr(const char *desc, GROUP_INFO_CTR **ctr,
                if(!samr_io_group_info4("group_info4", &(*ctr)->group.info4, ps, depth))
                        return False;
                break;
+       case 5:
+               if(!samr_io_group_info5("group_info5", &(*ctr)->group.info5, ps, depth))
+                       return False;
+               break;
        default:
                DEBUG(0,("samr_group_info_ctr: unsupported switch level\n"));
                break;
@@ -2381,17 +2523,15 @@ 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)
 {
-       int acct_len = acct_desc != NULL ? strlen(acct_desc) : 0;
-
        DEBUG(5, ("init_samr_q_create_dom_group\n"));
 
        q_e->pol = *pol;
 
-       init_uni_hdr(&q_e->hdr_acct_desc, acct_len);
-       init_unistr2(&q_e->uni_acct_desc, acct_desc);
+       init_unistr2(&q_e->uni_acct_desc, acct_desc, UNI_FLAGS_NONE);
+       init_uni_hdr(&q_e->hdr_acct_desc, &q_e->uni_acct_desc);
 
        q_e->access_mask = access_mask;
 }
@@ -2917,7 +3057,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;
                        }
@@ -2933,7 +3073,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;
                        }
@@ -3034,7 +3174,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) {
@@ -3189,8 +3329,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) {
@@ -3328,8 +3468,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) {
@@ -3462,8 +3602,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 && 
@@ -3503,18 +3643,11 @@ inits a ALIAS_INFO1 structure.
 
 void init_samr_alias_info1(ALIAS_INFO1 * al1, char *acct_name, uint32 num_member, char *acct_desc)
 {
-       int acct_len_name = acct_name != NULL ? strlen(acct_name) : 0;
-       int acct_len_desc = acct_desc != NULL ? strlen(acct_desc) : 0;
-
        DEBUG(5, ("init_samr_alias_info1\n"));
 
-       init_uni_hdr(&al1->hdr_acct_name, acct_len_name);
-       init_unistr2(&al1->uni_acct_name, acct_name);
-
-       al1->num_member=num_member;
-
-       init_uni_hdr(&al1->hdr_acct_desc, acct_len_desc);
-       init_unistr2(&al1->uni_acct_desc, acct_desc);
+       init_unistr4(&al1->name, acct_name, UNI_FLAGS_NONE);
+       al1->num_member = num_member;
+       init_unistr4(&al1->description, acct_desc, UNI_FLAGS_NONE);
 }
 
 /*******************************************************************
@@ -3533,22 +3666,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;
@@ -3558,21 +3689,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)
 {
-       int acct_len = acct_desc != NULL ? strlen(acct_desc) : 0;
-
        DEBUG(5, ("init_samr_alias_info3\n"));
 
-       init_uni_hdr(&al3->hdr_acct_desc, acct_len);
-       init_unistr2(&al3->uni_acct_desc, 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)
@@ -3584,10 +3712,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;
@@ -3597,25 +3722,50 @@ 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,
+BOOL samr_io_alias_info2(const char *desc, ALIAS_INFO2 *al2,
                         prs_struct *ps, int depth)
 {
-       if (ctr == NULL)
+       if (al2 == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_alias_info_ctr");
+       prs_debug(ps, depth, desc, "samr_io_alias_info2");
        depth++;
 
-       if(!prs_uint16("switch_value1", ps, depth, &ctr->switch_value1))
+       if(!prs_align(ps))
+               return False;
+
+       if (!prs_unistr4("name", ps, depth, &al2->name))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_alias_info_ctr(const char *desc, prs_struct *ps, int depth, ALIAS_INFO_CTR * ctr)
+{
+       if ( !ctr )
                return False;
-       if(!prs_uint16("switch_value2", ps, depth, &ctr->switch_value2))
+
+       prs_debug(ps, depth, desc, "samr_alias_info_ctr");
+       depth++;
+
+       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;
                break;
+       case 2: 
+               if(!samr_io_alias_info2("alias_info2", &ctr->alias.info2, ps, depth))
+                       return False;
+               break;
        case 3: 
                if(!samr_io_alias_info3("alias_info3", &ctr->alias.info3, ps, depth))
                        return False;
@@ -3633,22 +3783,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");
@@ -3657,10 +3807,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;
@@ -3670,24 +3820,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");
@@ -3696,17 +3845,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;
@@ -3743,7 +3887,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;
@@ -3825,11 +3969,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;
        }
@@ -3900,7 +4044,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;
@@ -4031,7 +4175,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;
@@ -4075,7 +4219,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;
        }
@@ -4156,11 +4300,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;
                }
@@ -4191,7 +4335,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;
                }
@@ -4271,18 +4415,16 @@ 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)
 {
-       int acct_len = acct_desc != NULL ? strlen(acct_desc) : 0;
-
        DEBUG(5, ("init_samr_q_create_dom_alias\n"));
 
        q_u->dom_pol = *hnd;
 
-       init_uni_hdr(&q_u->hdr_acct_desc, acct_len);
-       init_unistr2(&q_u->uni_acct_desc, acct_desc);
+       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;
 }
 
 /*******************************************************************
@@ -4526,6 +4668,9 @@ BOOL samr_io_r_delete_dom_alias(const char *desc, SAMR_R_DELETE_DOM_ALIAS * r_u,
        if(!prs_align(ps))
                return False;
 
+       if(!smb_io_pol_hnd("pol", &r_u->pol, ps, depth))
+               return False;
+
        if(!prs_ntstatus("status", ps, depth, &r_u->status))
                return False;
 
@@ -4598,7 +4743,6 @@ BOOL samr_io_r_query_aliasmem(const char *desc, SAMR_R_QUERY_ALIASMEM * r_u,
                              prs_struct *ps, int depth)
 {
        uint32 i;
-       uint32 ptr_sid[MAX_LOOKUP_SIDS];
 
        if (r_u == NULL)
                return False;
@@ -4614,24 +4758,31 @@ BOOL samr_io_r_query_aliasmem(const char *desc, SAMR_R_QUERY_ALIASMEM * r_u,
        if(!prs_uint32("ptr", ps, depth, &r_u->ptr))
                return False;
 
-       if (r_u->ptr != 0) {
-               SMB_ASSERT_ARRAY(ptr_sid, r_u->num_sids);
-
-               if (r_u->num_sids != 0) {
-                       if(!prs_uint32("num_sids1", ps, depth, &r_u->num_sids1))
-                               return False;
+       if (r_u->ptr != 0 && r_u->num_sids != 0) {
+               uint32 *ptr_sid = NULL;
 
-                       for (i = 0; i < r_u->num_sids1; i++) {
-                               ptr_sid[i] = 1;
-                               if(!prs_uint32("", ps, depth, &ptr_sid[i]))
-                                 return False;
-                       }
+               if(!prs_uint32("num_sids1", ps, depth, &r_u->num_sids1))
+                       return False;
 
-                       for (i = 0; i < r_u->num_sids1; i++) {
-                               if (ptr_sid[i] != 0) {
-                                       if(!smb_io_dom_sid2("", &r_u->sid[i], ps, depth))
-                                               return False;
-                               }
+               ptr_sid = TALLOC_ARRAY(ps->mem_ctx, uint32, r_u->num_sids1);
+               if (!ptr_sid) {
+                       return False;
+               }
+               
+               for (i = 0; i < r_u->num_sids1; i++) {
+                       ptr_sid[i] = 1;
+                       if(!prs_uint32("ptr_sid", ps, depth, &ptr_sid[i]))
+                               return False;
+               }
+               
+               if (UNMARSHALLING(ps)) {
+                       r_u->sid = TALLOC_ARRAY(ps->mem_ctx, DOM_SID2, r_u->num_sids1);
+               }
+               
+               for (i = 0; i < r_u->num_sids1; i++) {
+                       if (ptr_sid[i] != 0) {
+                               if(!smb_io_dom_sid2("sid", &r_u->sid[i], ps, depth))
+                                       return False;
                        }
                }
        }
@@ -4663,16 +4814,15 @@ 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++) {
-               int len_name = name[i] != NULL ? strlen(name[i]) : 0;
-               init_uni_hdr(&q_u->hdr_name[i], len_name);      /* unicode header for user_name */
-               init_unistr2(&q_u->uni_name[i], name[i]);       /* unicode string for machine account */
+               init_unistr2(&q_u->uni_name[i], name[i], UNI_FLAGS_NONE);       /* unicode string for machine account */
+               init_uni_hdr(&q_u->hdr_name[i], &q_u->uni_name[i]);     /* unicode header for user_name */
        }
 
        return NT_STATUS_OK;
@@ -4712,10 +4862,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;
        }
@@ -4739,7 +4887,7 @@ inits a SAMR_R_LOOKUP_NAMES structure.
 
 NTSTATUS init_samr_r_lookup_names(TALLOC_CTX *ctx, SAMR_R_LOOKUP_NAMES * r_u,
                              uint32 num_rids,
-                             uint32 *rid, uint32 *type,
+                             uint32 *rid, enum lsa_SidType *type,
                              NTSTATUS status)
 {
        DEBUG(5, ("init_samr_r_lookup_names\n"));
@@ -4755,9 +4903,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)
@@ -4824,7 +4972,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"));
@@ -4853,7 +5001,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"));
@@ -5008,15 +5156,12 @@ void init_samr_q_create_user(SAMR_Q_CREATE_USER * q_u,
                             const char *name,
                             uint32 acb_info, uint32 access_mask)
 {
-       int len_name;
-       len_name = strlen(name);
-
        DEBUG(5, ("samr_init_samr_q_create_user\n"));
 
        q_u->domain_pol = *pol;
 
-       init_uni_hdr(&q_u->hdr_name, len_name);
-       init_unistr2(&q_u->uni_name, name);
+       init_unistr2(&q_u->uni_name, name, UNI_FLAGS_NONE);
+       init_uni_hdr(&q_u->hdr_name, &q_u->uni_name);
 
        q_u->acb_info = acb_info;
        q_u->access_mask = access_mask;
@@ -5090,7 +5235,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"));
 
@@ -5139,6 +5284,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;
 
@@ -5154,13 +5305,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;
@@ -5172,13 +5323,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))
@@ -5198,12 +5349,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;
 }
@@ -5212,13 +5434,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))
@@ -5231,24 +5453,19 @@ 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)
 {
-       int len_mach_acct;
-
-       DEBUG(5, ("init_sam_user_info11\n"));
+       DEBUG(5, ("init_sam_user_info17\n"));
 
-       len_mach_acct = strlen(mach_acct);
-
-       memcpy(&(usr->expiry), expiry, sizeof(usr->expiry));    /* expiry time or something? */
+       memcpy(&usr->expiry, expiry, sizeof(usr->expiry));      /* expiry time or something? */
        ZERO_STRUCT(usr->padding_1);    /* 0 - padding 24 bytes */
 
-       init_uni_hdr(&usr->hdr_mach_acct, len_mach_acct);       /* unicode header for machine account */
        usr->padding_2 = 0;     /* 0 - padding 4 bytes */
 
        usr->ptr_1 = 1;         /* pointer */
@@ -5273,20 +5490,21 @@ void init_sam_user_info11(SAM_USER_INFO_11 * usr,
        ZERO_STRUCT(usr->padding_7);    /* 0 - padding 16 bytes */
        usr->padding_8 = 0;     /* 0 - padding 4 bytes */
 
-       init_unistr2(&usr->uni_mach_acct, mach_acct);   /* unicode string for machine account */
+       init_unistr2(&usr->uni_mach_acct, mach_acct, UNI_FLAGS_NONE);   /* unicode string for machine account */
+       init_uni_hdr(&usr->hdr_mach_acct, &usr->uni_mach_acct); /* unicode header for machine account */
 }
 
 /*******************************************************************
 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))
@@ -5358,11 +5576,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)
@@ -5395,18 +5608,44 @@ static BOOL sam_io_user_info24(const char *desc, SAM_USER_INFO_24 * usr,
        if (MARSHALLING(ps) && (usr->pw_len != 0)) {
                if (!prs_uint16("pw_len", ps, depth, &usr->pw_len))
                        return False;
+       } else if (UNMARSHALLING(ps)) {
+               if (!prs_uint16("pw_len", ps, depth, &usr->pw_len))
+                       return False;
        }
+
+       return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL sam_io_user_info26(const char *desc, SAM_USER_INFO_26 * usr,
+                              prs_struct *ps, int depth)
+{
+       if (usr == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "sam_io_user_info26");
+       depth++;
+
        if(!prs_align(ps))
                return False;
 
+       if(!prs_uint8s(False, "password", ps, depth, usr->pass, 
+                      sizeof(usr->pass)))
+               return False;
+       
+       if (!prs_uint8("pw_len", ps, depth, &usr->pw_len))
+               return False;
+
        return True;
 }
 
+
 /*************************************************************************
  init_sam_user_info23
 
- unknown_3 = 0x09f8 27fa
- unknown_5 = 0x0001 0000
  unknown_6 = 0x0000 04ec 
 
  *************************************************************************/
@@ -5430,23 +5669,13 @@ 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,
-                       uint32 unknown_5,
-                       char newpass[516], uint32 unknown_6)
-{
-       int len_user_name = user_name != NULL ? user_name->uni_str_len : 0;
-       int len_full_name = full_name != NULL ? full_name->uni_str_len : 0;
-       int len_home_dir = home_dir != NULL ? home_dir->uni_str_len : 0;
-       int len_dir_drive = dir_drive != NULL ? dir_drive->uni_str_len : 0;
-       int len_logon_script = log_scr != NULL ? log_scr->uni_str_len : 0;
-       int len_profile_path = prof_path != NULL ? prof_path->uni_str_len : 0;
-       int len_description = desc != NULL ? desc->uni_str_len : 0;
-       int len_workstations = wkstas != NULL ? wkstas->uni_str_len : 0;
-       int len_unknown_str = unk_str != NULL ? unk_str->uni_str_len : 0;
-       int len_munged_dial = mung_dial != NULL ? mung_dial->uni_str_len : 0;
-
+                       uint16 bad_password_count,
+                       uint16 logon_count,
+                       char newpass[516])
+{
        usr->logon_time = *logon_time;  /* all zeros */
        usr->logoff_time = *logoff_time;        /* all zeros */
        usr->kickoff_time = *kickoff_time;      /* all zeros */
@@ -5454,24 +5683,13 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
        usr->pass_can_change_time = *pass_can_change_time;      /* all zeros */
        usr->pass_must_change_time = *pass_must_change_time;    /* all zeros */
 
-       init_uni_hdr(&usr->hdr_user_name, len_user_name);       /* NULL */
-       init_uni_hdr(&usr->hdr_full_name, len_full_name);
-       init_uni_hdr(&usr->hdr_home_dir, len_home_dir);
-       init_uni_hdr(&usr->hdr_dir_drive, len_dir_drive);
-       init_uni_hdr(&usr->hdr_logon_script, len_logon_script);
-       init_uni_hdr(&usr->hdr_profile_path, len_profile_path);
-       init_uni_hdr(&usr->hdr_acct_desc, len_description);
-       init_uni_hdr(&usr->hdr_workstations, len_workstations);
-       init_uni_hdr(&usr->hdr_unknown_str, len_unknown_str);
-       init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial);
-
        ZERO_STRUCT(usr->nt_pwd);
        ZERO_STRUCT(usr->lm_pwd);
 
        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;
@@ -5482,36 +5700,54 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
                usr->passmustchange=0;
        }
 
-
        ZERO_STRUCT(usr->padding1);
        ZERO_STRUCT(usr->padding2);
 
-       usr->unknown_5 = unknown_5;     /* 0x0001 0000 */
+       usr->bad_password_count = bad_password_count;
+       usr->logon_count = logon_count;
 
        memcpy(usr->pass, newpass, sizeof(usr->pass));
 
        copy_unistr2(&usr->uni_user_name, user_name);
+       init_uni_hdr(&usr->hdr_user_name, &usr->uni_user_name);
+
        copy_unistr2(&usr->uni_full_name, full_name);
+       init_uni_hdr(&usr->hdr_full_name, &usr->uni_full_name);
+
        copy_unistr2(&usr->uni_home_dir, home_dir);
+       init_uni_hdr(&usr->hdr_home_dir, &usr->uni_home_dir);
+
        copy_unistr2(&usr->uni_dir_drive, dir_drive);
+       init_uni_hdr(&usr->hdr_dir_drive, &usr->uni_dir_drive);
+
        copy_unistr2(&usr->uni_logon_script, log_scr);
+       init_uni_hdr(&usr->hdr_logon_script, &usr->uni_logon_script);
+
        copy_unistr2(&usr->uni_profile_path, prof_path);
+       init_uni_hdr(&usr->hdr_profile_path, &usr->uni_profile_path);
+
        copy_unistr2(&usr->uni_acct_desc, desc);
+       init_uni_hdr(&usr->hdr_acct_desc, &usr->uni_acct_desc);
+
        copy_unistr2(&usr->uni_workstations, wkstas);
-       copy_unistr2(&usr->uni_unknown_str, unk_str);
-       copy_unistr2(&usr->uni_munged_dial, mung_dial);
+       init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
+
+       copy_unistr2(&usr->uni_comment, unk_str);
+       init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
 
-       usr->unknown_6 = unknown_6;     /* 0x0000 04ec */
-       usr->padding4 = 0;
+       copy_unistr2(&usr->uni_munged_dial, mung_dial);
+       init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
 
-       memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+       if (hrs) {
+               memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+       } else {
+               ZERO_STRUCT(usr->logon_hrs);
+       }
 }
 
 /*************************************************************************
  init_sam_user_info23
 
- unknown_3 = 0x09f8 27fa
- unknown_5 = 0x0001 0000
  unknown_6 = 0x0000 04ec 
 
  *************************************************************************/
@@ -5528,21 +5764,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,
-                          LOGON_HRS * hrs, uint32 unknown_5,
-                          char newpass[516], uint32 unknown_6)
-{
-       int len_user_name = user_name != NULL ? strlen(user_name) : 0;
-       int len_full_name = full_name != NULL ? strlen(full_name) : 0;
-       int len_home_dir = home_dir != NULL ? strlen(home_dir) : 0;
-       int len_dir_drive = dir_drive != NULL ? strlen(dir_drive) : 0;
-       int len_logon_script = log_scr != NULL ? strlen(log_scr) : 0;
-       int len_profile_path = prof_path != NULL ? strlen(prof_path) : 0;
-       int len_description = desc != NULL ? strlen(desc) : 0;
-       int len_workstations = wkstas != NULL ? strlen(wkstas) : 0;
-       int len_unknown_str = unk_str != NULL ? strlen(unk_str) : 0;
-       int len_munged_dial = mung_dial != NULL ? strlen(mung_dial) : 0;
-
+                          uint32 fields_present, uint16 logon_divs,
+                          LOGON_HRS * hrs, uint16 bad_password_count, uint16 logon_count,
+                          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 */
@@ -5550,24 +5777,13 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
        usr->pass_can_change_time = *pass_can_change_time;      /* all zeros */
        usr->pass_must_change_time = *pass_must_change_time;    /* all zeros */
 
-       init_uni_hdr(&usr->hdr_user_name, len_user_name);       /* NULL */
-       init_uni_hdr(&usr->hdr_full_name, len_full_name);
-       init_uni_hdr(&usr->hdr_home_dir, len_home_dir);
-       init_uni_hdr(&usr->hdr_dir_drive, len_dir_drive);
-       init_uni_hdr(&usr->hdr_logon_script, len_logon_script);
-       init_uni_hdr(&usr->hdr_profile_path, len_profile_path);
-       init_uni_hdr(&usr->hdr_acct_desc, len_description);
-       init_uni_hdr(&usr->hdr_workstations, len_workstations);
-       init_uni_hdr(&usr->hdr_unknown_str, len_unknown_str);
-       init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial);
-
        ZERO_STRUCT(usr->nt_pwd);
        ZERO_STRUCT(usr->lm_pwd);
 
        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;
@@ -5581,25 +5797,48 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
        ZERO_STRUCT(usr->padding1);
        ZERO_STRUCT(usr->padding2);
 
-       usr->unknown_5 = unknown_5;     /* 0x0001 0000 */
+       usr->bad_password_count = bad_password_count;
+       usr->logon_count = logon_count;
 
        memcpy(usr->pass, newpass, sizeof(usr->pass));
 
-       init_unistr2(&usr->uni_user_name, user_name);   /* NULL */
-       init_unistr2(&usr->uni_full_name, full_name);
-       init_unistr2(&usr->uni_home_dir, home_dir);
-       init_unistr2(&usr->uni_dir_drive, dir_drive);
-       init_unistr2(&usr->uni_logon_script, log_scr);
-       init_unistr2(&usr->uni_profile_path, prof_path);
-       init_unistr2(&usr->uni_acct_desc, desc);
-       init_unistr2(&usr->uni_workstations, wkstas);
-       init_unistr2(&usr->uni_unknown_str, unk_str);
-       init_unistr2(&usr->uni_munged_dial, mung_dial);
+       init_unistr2(&usr->uni_user_name, user_name, UNI_FLAGS_NONE);
+       init_uni_hdr(&usr->hdr_user_name, &usr->uni_user_name);
+
+       init_unistr2(&usr->uni_full_name, full_name, UNI_FLAGS_NONE);
+       init_uni_hdr(&usr->hdr_full_name, &usr->uni_full_name);
+
+       init_unistr2(&usr->uni_home_dir, home_dir, UNI_FLAGS_NONE);
+       init_uni_hdr(&usr->hdr_home_dir, &usr->uni_home_dir);
+
+       init_unistr2(&usr->uni_dir_drive, dir_drive, UNI_FLAGS_NONE);
+       init_uni_hdr(&usr->hdr_dir_drive, &usr->uni_dir_drive);
 
-       usr->unknown_6 = unknown_6;     /* 0x0000 04ec */
-       usr->padding4 = 0;
+       init_unistr2(&usr->uni_logon_script, log_scr, UNI_FLAGS_NONE);
+       init_uni_hdr(&usr->hdr_logon_script, &usr->uni_logon_script);
 
-       memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+       init_unistr2(&usr->uni_profile_path, prof_path, UNI_FLAGS_NONE);
+       init_uni_hdr(&usr->hdr_profile_path, &usr->uni_profile_path);
+
+       init_unistr2(&usr->uni_acct_desc, desc, UNI_FLAGS_NONE);
+       init_uni_hdr(&usr->hdr_acct_desc, &usr->uni_acct_desc);
+
+       init_unistr2(&usr->uni_workstations, wkstas, UNI_FLAGS_NONE);
+       init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
+
+       init_unistr2(&usr->uni_comment, unk_str, UNI_FLAGS_NONE);
+       init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
+
+       init_unistr2_from_datablob(&usr->uni_munged_dial, &blob);
+       init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
+
+       data_blob_free(&blob);
+       
+       if (hrs) {
+               memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+       } else {
+               ZERO_STRUCT(usr->logon_hrs);
+       }
 }
 
 /*******************************************************************
@@ -5647,7 +5886,7 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr,
                return False;
        if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth))       /* wkstas user can log on from */
                return False;
-       if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth))        /* unknown string */
+       if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth))        /* unknown string */
                return False;
        if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth))        /* wkstas user can log on from */
                return False;
@@ -5664,7 +5903,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;
@@ -5673,7 +5912,9 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr,
        if(!prs_uint32("ptr_logon_hrs ", ps, depth, &usr->ptr_logon_hrs))
                return False;
 
-       if(!prs_uint32("unknown_5     ", ps, depth, &usr->unknown_5))
+       if(!prs_uint16("bad_password_count     ", ps, depth, &usr->bad_password_count))
+               return False;
+       if(!prs_uint16("logon_count     ", ps, depth, &usr->logon_count))
                return False;
 
        if(!prs_uint8s(False, "padding1      ", ps, depth, usr->padding1, sizeof(usr->padding1)))
@@ -5713,7 +5954,7 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr,
        if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth))        /* worksations user can log on from */
                return False;
 
-       if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth))  /* unknown string */
+       if(!smb_io_unistr2("uni_comment ", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth))      /* unknown string */
                return False;
 
        if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial, usr->hdr_munged_dial.buffer, ps, depth))
@@ -5721,16 +5962,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;
 }
@@ -5782,7 +6016,7 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
                return False;
        if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth))       /* wkstas user can log on from */
                return False;
-       if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth))        /* unknown string */
+       if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth))        /* unknown string */
                return False;
        if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth))        /* wkstas user can log on from */
                return False;
@@ -5798,8 +6032,10 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
                return False;
        if(!prs_uint32("acb_info      ", ps, depth, &usr->acb_info))
                return False;
+       if(!prs_uint32("fields_present ", ps, depth, &usr->fields_present))
+               return False;
 
-       if(!prs_uint32s(False, "unknown_6      ", ps, depth, usr->unknown_6, 6))
+       if(!prs_uint32s(False, "unknown_5      ", ps, depth, usr->unknown_5, 5))
                return False;
 
        if(!prs_uint8s(False, "password      ", ps, depth, usr->pass, sizeof(usr->pass)))
@@ -5831,7 +6067,7 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
        if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth))        /* worksations user can log on from */
                return False;
 
-       if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth))  /* unknown string */
+       if(!smb_io_unistr2("uni_comment ", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth))      /* unknown string */
                return False;
 
        if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial, usr->hdr_munged_dial.buffer, ps, depth))
@@ -5840,16 +6076,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;
@@ -5859,8 +6088,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_5 = 0x0002 0000
  unknown_6 = 0x0000 04ec 
 
  *************************************************************************/
@@ -5887,22 +6114,12 @@ 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,
-                          uint32 unknown_5, uint32 unknown_6)
-{
-       int len_user_name = user_name != NULL ? user_name->uni_str_len : 0;
-       int len_full_name = full_name != NULL ? full_name->uni_str_len : 0;
-       int len_home_dir = home_dir != NULL ? home_dir->uni_str_len : 0;
-       int len_dir_drive = dir_drive != NULL ? dir_drive->uni_str_len : 0;
-       int len_logon_script = log_scr != NULL ? log_scr->uni_str_len : 0;
-       int len_profile_path = prof_path != NULL ? prof_path->uni_str_len : 0;
-       int len_description = desc != NULL ? desc->uni_str_len : 0;
-       int len_workstations = wkstas != NULL ? wkstas->uni_str_len : 0;
-       int len_unknown_str = unk_str != NULL ? unk_str->uni_str_len : 0;
-       int len_munged_dial = mung_dial != NULL ? mung_dial->uni_str_len : 0;
-
+                          uint16 bad_password_count,
+                          uint16 logon_count)
+{
        usr->logon_time = *logon_time;
        usr->logoff_time = *logoff_time;
        usr->kickoff_time = *kickoff_time;
@@ -5910,28 +6127,18 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
        usr->pass_can_change_time = *pass_can_change_time;
        usr->pass_must_change_time = *pass_must_change_time;
 
-       init_uni_hdr(&usr->hdr_user_name, len_user_name);
-       init_uni_hdr(&usr->hdr_full_name, len_full_name);
-       init_uni_hdr(&usr->hdr_home_dir, len_home_dir);
-       init_uni_hdr(&usr->hdr_dir_drive, len_dir_drive);
-       init_uni_hdr(&usr->hdr_logon_script, len_logon_script);
-       init_uni_hdr(&usr->hdr_profile_path, len_profile_path);
-       init_uni_hdr(&usr->hdr_acct_desc, len_description);
-       init_uni_hdr(&usr->hdr_workstations, len_workstations);
-       init_uni_hdr(&usr->hdr_unknown_str, len_unknown_str);
-       init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial);
-
        memcpy(usr->lm_pwd, lm_pwd, sizeof(usr->lm_pwd));
        memcpy(usr->nt_pwd, nt_pwd, sizeof(usr->nt_pwd));
 
        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;
-       usr->unknown_5 = unknown_5;     /* 0x0002 0000 */
+       usr->bad_password_count = bad_password_count;
+       usr->logon_count = logon_count;
 
        if (nt_time_is_zero(pass_must_change_time)) {
                usr->passmustchange=PASS_MUST_CHANGE_AT_NEXT_LOGON;
@@ -5939,46 +6146,58 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
                usr->passmustchange=0;
        }
 
-
        ZERO_STRUCT(usr->padding1);
        ZERO_STRUCT(usr->padding2);
 
        copy_unistr2(&usr->uni_user_name, user_name);
+       init_uni_hdr(&usr->hdr_user_name, &usr->uni_user_name);
+
        copy_unistr2(&usr->uni_full_name, full_name);
+       init_uni_hdr(&usr->hdr_full_name, &usr->uni_full_name);
+
        copy_unistr2(&usr->uni_home_dir, home_dir);
+       init_uni_hdr(&usr->hdr_home_dir, &usr->uni_home_dir);
+
        copy_unistr2(&usr->uni_dir_drive, dir_drive);
+       init_uni_hdr(&usr->hdr_dir_drive, &usr->uni_dir_drive);
+
        copy_unistr2(&usr->uni_logon_script, log_scr);
+       init_uni_hdr(&usr->hdr_logon_script, &usr->uni_logon_script);
+
        copy_unistr2(&usr->uni_profile_path, prof_path);
+       init_uni_hdr(&usr->hdr_profile_path, &usr->uni_profile_path);
+
        copy_unistr2(&usr->uni_acct_desc, desc);
+       init_uni_hdr(&usr->hdr_acct_desc, &usr->uni_acct_desc);
+
        copy_unistr2(&usr->uni_workstations, wkstas);
-       copy_unistr2(&usr->uni_unknown_str, unk_str);
-       copy_unistr2(&usr->uni_munged_dial, mung_dial);
+       init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
 
-       usr->unknown_6 = unknown_6;     /* 0x0000 04ec */
-       usr->padding4 = 0;
+       copy_unistr2(&usr->uni_comment, unk_str);
+       init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
+
+       copy_unistr2(&usr->uni_munged_dial, mung_dial);
+       init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
 
-       memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+       if (hrs) {
+               memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+       } else {
+               ZERO_STRUCT(usr->logon_hrs);
+       }
 }
 
 /*************************************************************************
  init_sam_user_info21
 
- unknown_3 = 0x00ff ffff
- unknown_5 = 0x0002 0000
  unknown_6 = 0x0000 04ec 
 
  *************************************************************************/
 
-NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *domain_sid)
+NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID *domain_sid)
 {
        NTTIME          logon_time, logoff_time, kickoff_time,
                        pass_last_set_time, pass_can_change_time,
                        pass_must_change_time;
-
-       int             len_user_name, len_full_name, len_home_dir,
-                       len_dir_drive, len_logon_script, len_profile_path,
-                       len_description, len_workstations, len_unknown_str,
-                       len_munged_dial;
                        
        const char*             user_name = pdb_get_username(pw);
        const char*             full_name = pdb_get_fullname(pw);
@@ -5989,6 +6208,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;
@@ -5996,17 +6216,11 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
        uint32 group_rid;
        const DOM_SID *group_sid;
 
-       len_user_name    = user_name    != NULL ? strlen(user_name   )+1 : 0;
-       len_full_name    = full_name    != NULL ? strlen(full_name   )+1 : 0;
-       len_home_dir     = home_dir     != NULL ? strlen(home_dir    )+1 : 0;
-       len_dir_drive    = dir_drive    != NULL ? strlen(dir_drive   )+1 : 0;
-       len_logon_script = logon_script != NULL ? strlen(logon_script)+1 : 0;
-       len_profile_path = profile_path != NULL ? strlen(profile_path)+1 : 0;
-       len_description  = description  != NULL ? strlen(description )+1 : 0;
-       len_workstations = workstations != NULL ? strlen(workstations)+1 : 0;
-       len_unknown_str  = 0;
-       len_munged_dial  = munged_dial  != NULL ? strlen(munged_dial )+1 : 0;
-
+       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));
@@ -6024,17 +6238,6 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
        usr->pass_can_change_time  = pass_can_change_time;
        usr->pass_must_change_time = pass_must_change_time;
 
-       init_uni_hdr(&usr->hdr_user_name, len_user_name);
-       init_uni_hdr(&usr->hdr_full_name, len_full_name);
-       init_uni_hdr(&usr->hdr_home_dir, len_home_dir);
-       init_uni_hdr(&usr->hdr_dir_drive, len_dir_drive);
-       init_uni_hdr(&usr->hdr_logon_script, len_logon_script);
-       init_uni_hdr(&usr->hdr_profile_path, len_profile_path);
-       init_uni_hdr(&usr->hdr_acct_desc, len_description);
-       init_uni_hdr(&usr->hdr_workstations, len_workstations);
-       init_uni_hdr(&usr->hdr_unknown_str, len_unknown_str);
-       init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial);
-
        ZERO_STRUCT(usr->nt_pwd);
        ZERO_STRUCT(usr->lm_pwd);
 
@@ -6048,6 +6251,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;
        }
 
@@ -6061,6 +6265,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;
        }
 
@@ -6070,18 +6275,19 @@ 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;
-       usr->unknown_5 = pdb_get_unknown_5(pw); /* 0x0002 0000 */
+       usr->bad_password_count = pdb_get_bad_password_count(pw);
+       usr->logon_count = pdb_get_logon_count(pw);
 
        if (pdb_get_pass_must_change_time(pw) == 0) {
                usr->passmustchange=PASS_MUST_CHANGE_AT_NEXT_LOGON;
@@ -6089,29 +6295,51 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
                usr->passmustchange=0;
        }
 
-
        ZERO_STRUCT(usr->padding1);
        ZERO_STRUCT(usr->padding2);
 
-       init_unistr2(&usr->uni_user_name, user_name);
-       init_unistr2(&usr->uni_full_name, full_name);
-       init_unistr2(&usr->uni_home_dir, home_dir);
-       init_unistr2(&usr->uni_dir_drive, dir_drive);
-       init_unistr2(&usr->uni_logon_script, logon_script);
-       init_unistr2(&usr->uni_profile_path, profile_path);
-       init_unistr2(&usr->uni_acct_desc, description);
-       init_unistr2(&usr->uni_workstations, workstations);
-       init_unistr2(&usr->uni_unknown_str, NULL);
-       init_unistr2(&usr->uni_munged_dial, munged_dial);
+       init_unistr2(&usr->uni_user_name, user_name, UNI_STR_TERMINATE);
+       init_uni_hdr(&usr->hdr_user_name, &usr->uni_user_name);
+
+       init_unistr2(&usr->uni_full_name, full_name, UNI_STR_TERMINATE);
+       init_uni_hdr(&usr->hdr_full_name, &usr->uni_full_name);
+
+       init_unistr2(&usr->uni_home_dir, home_dir, UNI_STR_TERMINATE);
+       init_uni_hdr(&usr->hdr_home_dir, &usr->uni_home_dir);
+
+       init_unistr2(&usr->uni_dir_drive, dir_drive, UNI_STR_TERMINATE);
+       init_uni_hdr(&usr->hdr_dir_drive, &usr->uni_dir_drive);
+
+       init_unistr2(&usr->uni_logon_script, logon_script, UNI_STR_TERMINATE);
+       init_uni_hdr(&usr->hdr_logon_script, &usr->uni_logon_script);
+
+       init_unistr2(&usr->uni_profile_path, profile_path, UNI_STR_TERMINATE);
+       init_uni_hdr(&usr->hdr_profile_path, &usr->uni_profile_path);
+
+       init_unistr2(&usr->uni_acct_desc, description, UNI_STR_TERMINATE);
+       init_uni_hdr(&usr->hdr_acct_desc, &usr->uni_acct_desc);
+
+       init_unistr2(&usr->uni_workstations, workstations, UNI_STR_TERMINATE);
+       init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations);
+
+       init_unistr2(&usr->uni_comment, NULL, UNI_STR_TERMINATE);
+       init_uni_hdr(&usr->hdr_comment, &usr->uni_comment);
 
-       usr->unknown_6 = pdb_get_unknown_6(pw);
-       usr->padding4 = 0;
+       init_unistr2_from_datablob(&usr->uni_munged_dial, &munged_dial_blob);
+       init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
+       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;
 }
@@ -6161,7 +6389,7 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
                return False;
        if(!smb_io_unihdr("hdr_workstations", &usr->hdr_workstations, ps, depth))       /* wkstas user can log on from */
                return False;
-       if(!smb_io_unihdr("hdr_unknown_str ", &usr->hdr_unknown_str, ps, depth))        /* unknown string */
+       if(!smb_io_unihdr("hdr_comment ", &usr->hdr_comment, ps, depth))        /* unknown string */
                return False;
        if(!smb_io_unihdr("hdr_munged_dial ", &usr->hdr_munged_dial, ps, depth))        /* wkstas user can log on from */
                return False;
@@ -6178,7 +6406,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;
@@ -6187,7 +6415,9 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
        if(!prs_uint32("ptr_logon_hrs ", ps, depth, &usr->ptr_logon_hrs))
                return False;
 
-       if(!prs_uint32("unknown_5     ", ps, depth, &usr->unknown_5))
+       if(!prs_uint16("bad_password_count     ", ps, depth, &usr->bad_password_count))
+               return False;
+       if(!prs_uint16("logon_count     ", ps, depth, &usr->logon_count))
                return False;
 
        if(!prs_uint8s(False, "padding1      ", ps, depth, usr->padding1, sizeof(usr->padding1)))
@@ -6199,54 +6429,50 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
 
        /* here begins pointed-to data */
 
-       if(!smb_io_unistr2("uni_user_name   ", &usr->uni_user_name,usr->hdr_user_name.buffer, ps, depth))       /* username unicode string */
+       if(!smb_io_unistr2("uni_user_name   ", &usr->uni_user_name,usr->hdr_user_name.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_full_name   ", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth))      /* user's full name unicode string */
+       if(!smb_io_unistr2("uni_full_name   ", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_home_dir    ", &usr->uni_home_dir, usr->hdr_home_dir.buffer, ps, depth))        /* home directory unicode string */
+       if(!smb_io_unistr2("uni_home_dir    ", &usr->uni_home_dir, usr->hdr_home_dir.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_dir_drive   ", &usr->uni_dir_drive, usr->hdr_dir_drive.buffer, ps, depth))      /* home directory drive unicode string */
+       if(!smb_io_unistr2("uni_dir_drive   ", &usr->uni_dir_drive, usr->hdr_dir_drive.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_logon_script", &usr->uni_logon_script, usr->hdr_logon_script.buffer, ps, depth))        /* logon script unicode string */
+       if(!smb_io_unistr2("uni_logon_script", &usr->uni_logon_script, usr->hdr_logon_script.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_profile_path", &usr->uni_profile_path, usr->hdr_profile_path.buffer, ps, depth))        /* profile path unicode string */
+       if(!smb_io_unistr2("uni_profile_path", &usr->uni_profile_path, usr->hdr_profile_path.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_acct_desc   ", &usr->uni_acct_desc, usr->hdr_acct_desc.buffer, ps, depth))      /* user desc unicode string */
+       if(!smb_io_unistr2("uni_acct_desc   ", &usr->uni_acct_desc, usr->hdr_acct_desc.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth))        /* worksations user can log on from */
+       if(!smb_io_unistr2("uni_workstations", &usr->uni_workstations, usr->hdr_workstations.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_unknown_str ", &usr->uni_unknown_str, usr->hdr_unknown_str.buffer, ps, depth))  /* unknown string */
+       if(!smb_io_unistr2("uni_comment", &usr->uni_comment, usr->hdr_comment.buffer, ps, depth))
                return False;
-       if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial,usr->hdr_munged_dial.buffer, ps, depth))   /* worksations user can log on from */
+       if(!smb_io_unistr2("uni_munged_dial ", &usr->uni_munged_dial,usr->hdr_munged_dial.buffer, ps, depth))
                return False;
 
        /* 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 (usr->ptr_logon_hrs) {
                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;
 }
 
-void init_sam_user_info20A(SAM_USER_INFO_20 *usr, SAM_ACCOUNT *pw)
+void init_sam_user_info20A(SAM_USER_INFO_20 *usr, struct samu *pw)
 {
-       int             len_munged_dial;
-       const char*             munged_dial = pdb_get_munged_dial(pw);
+       const char *munged_dial = pdb_get_munged_dial(pw);
+       DATA_BLOB blob;
 
-       len_munged_dial  = munged_dial  != NULL ? strlen(munged_dial )+1 : 0;
-       init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial);
-       init_unistr2(&usr->uni_munged_dial, munged_dial);
+       if (munged_dial) {
+               blob = base64_decode_data_blob(munged_dial);
+       } else {
+               blob = data_blob(NULL, 0);
+       }
 
+       init_unistr2_from_datablob(&usr->uni_munged_dial, &blob);
+       init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
+       data_blob_free(&blob);
 }
 
 /*******************************************************************
@@ -6282,22 +6508,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;
@@ -6305,8 +6531,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 */
@@ -6315,17 +6541,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;
@@ -6346,8 +6572,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"));
 
@@ -6356,17 +6582,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));
        }
 }
 
@@ -6384,7 +6612,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;
@@ -6402,38 +6630,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.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_info7("", ctr->info.id7, ps, depth);
+               break;
+       case 9:
+               if (UNMARSHALLING(ps))
+                       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.id10 = (SAM_USER_INFO_10 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_10));
-               if (ctr->info.id10 == NULL) {
+                       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_info10("", ctr->info.id10, ps, depth);
+               ret = sam_io_user_info16("", ctr->info.id16, ps, depth);
                break;
-       case 0x11:
+       case 17:
                if (UNMARSHALLING(ps))
-                       ctr->info.id11 = (SAM_USER_INFO_11 *)prs_alloc_mem(ps,sizeof(SAM_USER_INFO_11));
+                       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"));
@@ -6443,7 +6689,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"));
@@ -6453,7 +6699,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"));
@@ -6463,7 +6709,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"));
@@ -6473,7 +6719,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"));
@@ -6481,6 +6727,16 @@ static BOOL samr_io_userinfo_ctr(const char *desc, SAM_USERINFO_CTR **ppctr,
                }
                ret = sam_io_user_info25("", ctr->info.id25, ps, depth);
                break;
+       case 26:
+               if (UNMARSHALLING(ps))
+                       ctr->info.id26 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_26,1);
+
+               if (ctr->info.id26 == NULL) {
+                       DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
+                       return False;
+               }
+               ret = sam_io_user_info26("", ctr->info.id26, ps,  depth);
+               break;
        default:
                DEBUG(2, ("samr_io_userinfo_ctr: unknown switch level 0x%x\n", ctr->switch_value));
                ret = False;
@@ -6547,7 +6803,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"));
@@ -6621,7 +6877,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"));
@@ -6630,16 +6886,15 @@ void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
        q_u->switch_value = switch_value;
        q_u->ctr = ctr;
 
-       if (q_u->ctr != NULL)
-               q_u->ctr->switch_value = switch_value;
+       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;
        }
 }
@@ -6711,13 +6966,11 @@ inits a SAMR_Q_CONNECT structure.
 void init_samr_q_connect(SAMR_Q_CONNECT * q_u,
                         char *srv_name, uint32 access_mask)
 {
-       int len_srv_name = strlen(srv_name);
-
        DEBUG(5, ("init_samr_q_connect\n"));
 
        /* make PDC server name \\server */
-       q_u->ptr_srv_name = len_srv_name > 0 ? 1 : 0;
-       init_unistr2(&q_u->uni_srv_name, srv_name);
+       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;
@@ -6784,13 +7037,11 @@ inits a SAMR_Q_CONNECT4 structure.
 void init_samr_q_connect4(SAMR_Q_CONNECT4 * q_u,
                          char *srv_name, uint32 access_mask)
 {
-       int len_srv_name = strlen(srv_name);
-
-       DEBUG(5, ("init_samr_q_connect\n"));
+       DEBUG(5, ("init_samr_q_connect4\n"));
 
        /* make PDC server name \\server */
-       q_u->ptr_srv_name = len_srv_name > 0 ? 1 : 0;
-       init_unistr2(&q_u->uni_srv_name, srv_name);
+       q_u->ptr_srv_name = (srv_name != NULL && *srv_name) ? 1 : 0;
+       init_unistr2(&q_u->uni_srv_name, srv_name, UNI_STR_TERMINATE);
 
        /* Only value we've seen, possibly an address type ? */
        q_u->unk_0 = 2;
@@ -6855,6 +7106,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.
 ********************************************************************/
@@ -6865,8 +7226,7 @@ void init_samr_q_connect_anon(SAMR_Q_CONNECT_ANON * q_u)
 
        q_u->ptr = 1;
        q_u->unknown_0 = 0x5c;  /* server name (?!!) */
-       q_u->unknown_1 = 0x01;
-       q_u->access_mask = 0x20;
+       q_u->access_mask = MAXIMUM_ALLOWED_ACCESS;
 }
 
 /*******************************************************************
@@ -6887,9 +7247,11 @@ BOOL samr_io_q_connect_anon(const char *desc, SAMR_Q_CONNECT_ANON * q_u,
 
        if(!prs_uint32("ptr      ", ps, depth, &q_u->ptr))
                return False;
-       if(!prs_uint16("unknown_0", ps, depth, &q_u->unknown_0))
-               return False;
-       if(!prs_uint16("unknown_1", ps, depth, &q_u->unknown_1))
+       if (q_u->ptr) {
+               if(!prs_uint16("unknown_0", ps, depth, &q_u->unknown_0))
+                       return False;
+       }
+       if(!prs_align(ps))
                return False;
        if(!prs_uint32("access_mask", ps, depth, &q_u->access_mask))
                return False;
@@ -6929,13 +7291,11 @@ inits a SAMR_Q_GET_DOM_PWINFO structure.
 void init_samr_q_get_dom_pwinfo(SAMR_Q_GET_DOM_PWINFO * q_u,
                                char *srv_name)
 {
-       int len_srv_name = strlen(srv_name);
-
        DEBUG(5, ("init_samr_q_get_dom_pwinfo\n"));
 
        q_u->ptr = 1;
-       init_uni_hdr(&q_u->hdr_srv_name, len_srv_name);
-       init_unistr2(&q_u->uni_srv_name, srv_name);
+       init_unistr2(&q_u->uni_srv_name, srv_name, UNI_FLAGS_NONE);
+       init_uni_hdr(&q_u->hdr_srv_name, &q_u->uni_srv_name);
 }
 
 /*******************************************************************
@@ -6982,16 +7342,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))
@@ -7004,7 +7359,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);
 
@@ -7047,7 +7402,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);
 
@@ -7086,33 +7441,31 @@ 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])
 {
-       int len_dest_host = strlen(dest_host);
-       int len_user_name = strlen(user_name);
-
        DEBUG(5, ("init_samr_q_chgpasswd_user\n"));
 
        q_u->ptr_0 = 1;
-       init_uni_hdr(&q_u->hdr_dest_host, len_dest_host);
-       init_unistr2(&q_u->uni_dest_host, dest_host);
-       init_uni_hdr(&q_u->hdr_user_name, len_user_name);
-       init_unistr2(&q_u->uni_user_name, user_name);
+       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_enc_passwd(&q_u->nt_newpass, nt_newpass);
+       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->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);
 }
 
@@ -7169,7 +7522,7 @@ inits a SAMR_R_CHGPASSWD_USER structure.
 
 void init_samr_r_chgpasswd_user(SAMR_R_CHGPASSWD_USER * r_u, NTSTATUS status)
 {
-       DEBUG(5, ("init_r_chgpasswd_user\n"));
+       DEBUG(5, ("init_samr_r_chgpasswd_user\n"));
 
        r_u->status = status;
 }
@@ -7196,14 +7549,190 @@ 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_chgpasswd_user3(SAMR_Q_CHGPASSWD_USER3 * 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_chgpasswd_user3\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_chgpasswd_user3(const char *desc, SAMR_Q_CHGPASSWD_USER3 * q_u,
+                              prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_q_chgpasswd_user3");
+       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_CHGPASSWD_USER3 structure.
+********************************************************************/
+
+void init_samr_r_chgpasswd_user3(SAMR_R_CHGPASSWD_USER3 *r_u, NTSTATUS status, 
+                                SAMR_CHANGE_REJECT *reject, SAM_UNK_INFO_1 *info)
+{
+       DEBUG(5, ("init_samr_r_chgpasswd_user3\n"));
+
+       r_u->status = status;
+       r_u->info = 0;
+       r_u->ptr_info = 0;
+       r_u->reject = 0;
+       r_u->ptr_reject = 0;
+
+       if (info) {
+               r_u->info = info;
+               r_u->ptr_info = 1;
+       }
+       if (reject && (reject->reject_reason != Undefined)) {
+               r_u->reject = reject;
+               r_u->ptr_reject = 1;
+       }
+}
+
+/*******************************************************************
+ 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_chgpasswd_user3(const char *desc, SAMR_R_CHGPASSWD_USER3 *r_u,
+                              prs_struct *ps, int depth)
+{
+       if (r_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "samr_io_r_chgpasswd_user3");
+       depth++;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_uint32("ptr_info", ps, depth, &r_u->ptr_info))
+               return False;
+
+       if (r_u->ptr_info && r_u->info != NULL) {
+               /* SAM_UNK_INFO_1 */
+               if (!sam_io_unk_info1("info", r_u->info, ps, depth))
+                       return False;
+       }
+
+       if (!prs_uint32("ptr_reject", ps, depth, &r_u->ptr_reject))
+               return False;
+                            
+       if (r_u->ptr_reject && r_u->reject != NULL) {
+               /* 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;
@@ -7213,13 +7742,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))
@@ -7238,11 +7767,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,
-                               uint16 switch_value, SAM_UNK_CTR * ctr,
-                               NTSTATUS status)
+void init_samr_r_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_query_domain_info2\n"));
 
        r_u->ptr_0 = 0;
        r_u->switch_value = 0;
@@ -7259,13 +7788,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,
-                             prs_struct *ps, int depth)
+BOOL samr_io_r_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_query_domain_info2");
        depth++;
 
        if(!prs_align(ps))
@@ -7281,10 +7810,22 @@ BOOL samr_io_r_samr_unknown_2e(const char *desc, SAMR_R_UNKNOWN_2E * r_u,
                        return False;
 
                switch (r_u->switch_value) {
+               case 0x0d:
+                       if(!sam_io_unk_info13("unk_inf13", &r_u->ctr->info.inf13, ps, depth))
+                               return False;
+                       break;
                case 0x0c:
                        if(!sam_io_unk_info12("unk_inf12", &r_u->ctr->info.inf12, ps, depth))
                                return False;
                        break;
+               case 0x09:
+                       if(!sam_io_unk_info9("unk_inf9",&r_u->ctr->info.inf9, 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;
@@ -7297,6 +7838,10 @@ BOOL samr_io_r_samr_unknown_2e(const char *desc, SAMR_R_UNKNOWN_2E * r_u,
                        if(!sam_io_unk_info5("unk_inf5",&r_u->ctr->info.inf5, ps,depth))
                                return False;
                        break;
+               case 0x04:
+                       if(!sam_io_unk_info4("unk_inf4",&r_u->ctr->info.inf4, ps,depth))
+                               return False;
+                       break;
                case 0x03:
                        if(!sam_io_unk_info3("unk_inf3",&r_u->ctr->info.inf3, ps,depth))
                                return False;
@@ -7310,7 +7855,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_query_domain_info2: unknown switch level 0x%x\n",
                                r_u->switch_value));
                        r_u->status = NT_STATUS_INVALID_INFO_CLASS;
                        return False;
@@ -7372,8 +7917,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) {