user_name_len = strlen(pwd->nt_name);
make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->nt_name, user_name_len);
- make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len,
- user_name_len, 1);
+ make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len);
pw_buf[(*num_entries)].user_rid = pwd->user_rid;
bzero( pw_buf[(*num_entries)].nt_pwd , 16);
/* store the response in the SMB stream */
samr_io_r_enum_dom_users("", &r_e, rdata, 0);
+ if (r_e.sam != NULL)
+ {
+ free(r_e.sam);
+ }
+
+ if (r_e.uni_acct_name != NULL)
+ {
+ free(r_e.uni_acct_name);
+ }
+
DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__));
}
}
/*******************************************************************
- samr_reply_add_groupmem
+ samr_reply_enum_dom_groups
********************************************************************/
static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
prs_struct *rdata)
SAMR_R_ENUM_DOM_GROUPS r_e;
DOMAIN_GRP *grps = NULL;
int num_entries = 0;
- BOOL got_grps = False;
DOM_SID sid;
fstring sid_str;
if (sid_equal(&sid, &global_sam_sid))
{
BOOL ret;
- got_grps = True;
become_root(True);
ret = enumdomgroups(&grps, &num_entries);
unbecome_root(True);
-
if (!ret)
{
r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
}
}
- if (r_e.status == 0 && got_grps)
+ if (r_e.status == 0x0)
{
- make_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, grps, r_e.status);
+ make_samr_r_enum_dom_groups(&r_e, num_entries, grps, r_e.status);
}
/* store the response in the SMB stream */
}
/*******************************************************************
- api_samr_enum_dom_groups
+ api_samr_enum_dom_aliases
********************************************************************/
static void api_samr_enum_dom_groups( uint16 vuid, prs_struct *data, prs_struct *rdata)
{
SAMR_Q_ENUM_DOM_GROUPS q_e;
+
+ /* grab the samr open */
samr_io_q_enum_dom_groups("", &q_e, data, 0);
+
+ /* construct reply. */
samr_reply_enum_dom_groups(&q_e, rdata);
}
prs_struct *rdata)
{
SAMR_R_QUERY_DISPINFO r_e;
- SAM_INFO_CTR ctr;
- SAM_INFO_1 info1;
- SAM_INFO_2 info2;
+ SAM_DISPINFO_CTR ctr;
SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
+ DOMAIN_GRP *grps = NULL;
+ DOMAIN_GRP *sam_grps = NULL;
+ uint32 data_size = 0;
+ uint32 status = 0x0;
+ uint16 acb_mask = ACB_NORMAL;
+ int num_sam_entries = 0;
int num_entries = 0;
- int total_entries = 0;
- BOOL got_pwds;
- uint16 switch_level = 0x0;
-
- ZERO_STRUCT(r_e);
-
- r_e.status = 0x0;
+ int total_entries;
DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
/* find the policy handle. open a policy on it. */
- if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+ if (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1)
{
- r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+ status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
}
- if (r_e.status == 0x0)
+ if (status == 0x0)
{
become_root(True);
- got_pwds = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0);
- unbecome_root(True);
+ /* Get what we need from the password database */
switch (q_u->switch_level)
{
+ case 0x2:
+ {
+ acb_mask = ACB_WSTRUST;
+ /* Fall through */
+ }
case 0x1:
+ case 0x4:
+ {
+ get_sampwd_entries(pass, q_u->start_idx,
+ &total_entries, &num_sam_entries,
+ MAX_SAM_ENTRIES, acb_mask);
+ break;
+ }
+ case 0x3:
+ case 0x5:
{
-
- /* query disp info is for users */
- switch_level = 0x1;
- make_sam_info_1(&info1, ACB_NORMAL,
- q_u->start_idx, num_entries, pass);
+ enumdomgroups(&sam_grps, &num_sam_entries);
+
+ if (q_u->start_idx < num_sam_entries) {
+ grps = sam_grps + q_u->start_idx;
+ num_sam_entries -= q_u->start_idx;
+ } else {
+ num_sam_entries = 0;
+ }
+ break;
+ }
+ }
+
+ unbecome_root(True);
- ctr.sam.info1 = &info1;
+ num_entries = num_sam_entries;
+
+ if (num_entries > q_u->max_entries)
+ {
+ num_entries = q_u->max_entries;
+ }
+
+ if (num_entries > MAX_SAM_ENTRIES)
+ {
+ num_entries = MAX_SAM_ENTRIES;
+ DEBUG(5,("limiting number of entries to %d\n",
+ num_entries));
+ }
+ data_size = q_u->max_size;
+
+ /* Now create reply structure */
+ switch (q_u->switch_level)
+ {
+ case 0x1:
+ {
+ ctr.sam.info1 = malloc(sizeof(SAM_DISPINFO_1));
+ make_sam_dispinfo_1(ctr.sam.info1,
+ &num_entries, &data_size,
+ q_u->start_idx, pass);
break;
}
case 0x2:
{
- /* query disp info is for servers */
- switch_level = 0x2;
- make_sam_info_2(&info2, ACB_WSTRUST,
- q_u->start_idx, num_entries, pass);
-
- ctr.sam.info2 = &info2;
-
+ ctr.sam.info2 = malloc(sizeof(SAM_DISPINFO_2));
+ make_sam_dispinfo_2(ctr.sam.info2,
+ &num_entries, &data_size,
+ q_u->start_idx, pass);
+ break;
+ }
+ case 0x3:
+ {
+ ctr.sam.info3 = malloc(sizeof(SAM_DISPINFO_3));
+ make_sam_dispinfo_3(ctr.sam.info3,
+ &num_entries, &data_size,
+ q_u->start_idx, grps);
+ break;
+ }
+ case 0x4:
+ {
+ ctr.sam.info4 = malloc(sizeof(SAM_DISPINFO_4));
+ make_sam_dispinfo_4(ctr.sam.info4,
+ &num_entries, &data_size,
+ q_u->start_idx, pass);
+ break;
+ }
+ case 0x5:
+ {
+ ctr.sam.info5 = malloc(sizeof(SAM_DISPINFO_5));
+ make_sam_dispinfo_5(ctr.sam.info5,
+ &num_entries, &data_size,
+ q_u->start_idx, grps);
+ break;
+ }
+ default:
+ {
+ ctr.sam.info = NULL;
+ status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
break;
}
}
}
- if (r_e.status == 0 && got_pwds)
+ if ((status == 0) && (num_entries < num_sam_entries))
{
- make_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
+ status = 0x105; /* STATUS_MORE_ENTRIES */
}
+ make_samr_r_query_dispinfo(&r_e, num_entries, data_size,
+ q_u->switch_level, &ctr, status);
+
/* store the response in the SMB stream */
samr_io_r_query_dispinfo("", &r_e, rdata, 0);
- DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
+ /* free malloc'd areas */
+ if (sam_grps != NULL)
+ {
+ free(sam_grps);
+ }
+ if (ctr.sam.info != NULL)
+ {
+ free(ctr.sam.info);
+ }
+
+ DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
}
/*******************************************************************
{
SAMR_Q_QUERY_DISPINFO q_e;
- /* grab the samr open */
samr_io_q_query_dispinfo("", &q_e, data, 0);
-
- /* construct reply. */
samr_reply_query_dispinfo(&q_e, rdata);
}
{
DOM_SID sid;
fstring name;
- unistr2_to_ascii(name, &q_u->uni_name[i], sizeof(name));
+ unistr2_to_ascii(name, &q_u->uni_name[i], sizeof(name)-1);
status = lookup_name(name, &sid, &(type[i]));
if (status == 0x0)
fstring user_name;
fstring wks;
- unistr2_to_ascii(user_name, &q_u->uni_user_name, sizeof(user_name));
- unistr2_to_ascii(wks, &q_u->uni_dest_host, sizeof(wks));
+ unistr2_to_ascii(user_name, &q_u->uni_user_name, sizeof(user_name)-1);
+ unistr2_to_ascii(wks, &q_u->uni_dest_host, sizeof(wks)-1);
DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
}
+/*******************************************************************
+ set_user_info_24
+ ********************************************************************/
+static BOOL set_user_info_24(SAM_USER_INFO_24 *id24, uint32 rid)
+{
+ static struct sam_passwd *pwd;
+ fstring new_pw;
+ if (!decode_pw_buffer(id24->pass, new_pw, sizeof(new_pw), True))
+ {
+ return False;
+ }
+#ifdef DEBUG_PASSWORD
+ DEBUG(0,("New Password: %s\n", new_pw));
+#endif
+#if 0
+ return mod_sam21pwd_entry(&pwd, True);
+#else
+ return True;
+#endif
+}
+
+/*******************************************************************
+ set_user_info_23
+ ********************************************************************/
+static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid)
+{
+ static struct sam_passwd *pwd;
+ fstring new_pw;
+ if (!decode_pw_buffer(id23->pass, new_pw, sizeof(new_pw), True))
+ {
+ return False;
+ }
+#ifdef DEBUG_PASSWORD
+ DEBUG(0,("New Password: %s\n", new_pw));
+#endif
+#if 0
+ return mod_sam21pwd_entry(&pwd, True);
+#else
+ return True;
+#endif
+}
+
/*******************************************************************
api_samr_query_userinfo
********************************************************************/
}
+/*******************************************************************
+ samr_reply_set_userinfo
+ ********************************************************************/
+static void samr_reply_set_userinfo(SAMR_Q_SET_USERINFO *q_u,
+ prs_struct *rdata, uchar user_sess_key[16])
+{
+ SAMR_R_SET_USERINFO r_u;
+
+ uint32 status = 0x0;
+ uint32 rid = 0x0;
+
+ DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__));
+
+ /* search for the handle */
+ if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+ {
+ status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+ }
+
+ /* find the user's rid */
+ if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
+ {
+ status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
+ }
+
+ DEBUG(5,("samr_reply_set_userinfo: rid:0x%x\n", rid));
+
+ /* ok! user info levels (there are lots: see MSDEV help), off we go... */
+ if (status == 0x0)
+ {
+ switch (q_u->switch_value)
+ {
+ case 24:
+ {
+ SAM_USER_INFO_24 *id24 = q_u->info.id24;
+ nt_lm_owf_gen("test", nt_pwd, lm_pwd);
+ SamOEMhash(id24->pass, user_sess_key, True);
+ status = set_user_info_24(id24, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
+ break;
+ }
+
+ case 23:
+ {
+ SAM_USER_INFO_23 *id23 = q_u->info.id23;
+ SamOEMhash(id23->pass, user_sess_key, True);
+ status = set_user_info_23(id23, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
+ break;
+ }
+
+ default:
+ {
+ status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
+
+ break;
+ }
+ }
+ }
+
+ make_samr_r_set_userinfo(&r_u, status);
+
+ /* store the response in the SMB stream */
+ samr_io_r_set_userinfo("", &r_u, rdata, 0);
+
+ DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_set_userinfo
+ ********************************************************************/
+static void api_samr_set_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+ user_struct *vuser = get_valid_user_struct(vuid);
+ SAMR_Q_SET_USERINFO q_u;
+ ZERO_STRUCT(q_u);
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("set user info: sess_key: "));
+ dump_data(100, vuser->dc.user_sess_key, 16);
+#endif
+ samr_io_q_set_userinfo("", &q_u, data, 0);
+ samr_reply_set_userinfo(&q_u, rdata, vuser->dc.user_sess_key);
+
+ if (q_u.info.id != NULL)
+ {
+ free(q_u.info.id);
+ }
+}
+
+
/*******************************************************************
samr_reply_query_usergroups
********************************************************************/
if (status == 0x0)
{
- unistr2_to_ascii(grp.name, &q_u->uni_acct_desc, sizeof(grp.name));
+ unistr2_to_ascii(grp.name, &q_u->uni_acct_desc, sizeof(grp.name)-1);
fstrcpy(grp.comment, "");
grp.rid = 0xffffffff;
if (status == 0x0)
{
- unistr2_to_ascii(grp.name, &q_u->uni_acct_desc, sizeof(grp.name));
+ unistr2_to_ascii(grp.name, &q_u->uni_acct_desc, sizeof(grp.name)-1);
fstrcpy(grp.comment, "");
grp.rid = 0xffffffff;
grp.attr = 0x07;
break;
}
+ case 0x01:
+ {
+ switch_value = 0x1;
+ make_unk_info1(&ctr.info.inf1);
+
+ break;
+ }
default:
{
status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
/*******************************************************************
- samr_reply_unknown_32
+ samr_reply_create_user
********************************************************************/
-static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
- prs_struct *rdata,
- int status)
-{
- int i;
- SAMR_R_UNKNOWN_32 r_u;
-
- /* set up the SAMR unknown_32 response */
- bzero(r_u.pol.data, POL_HND_SIZE);
- if (status == 0)
- {
- for (i = 4; i < POL_HND_SIZE; i++)
- {
- r_u.pol.data[i] = i+1;
- }
- }
-
- make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
- r_u.status = status;
-
- DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
-
- /* store the response in the SMB stream */
- samr_io_r_unknown_32("", &r_u, rdata, 0);
-
- DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
-
-}
-
-/*******************************************************************
- api_samr_unknown_32
- ********************************************************************/
-static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdata)
+static void samr_reply_create_user(SAMR_Q_CREATE_USER *q_u,
+ prs_struct *rdata)
{
- uint32 status = 0;
struct sam_passwd *sam_pass;
- fstring mach_acct;
-
- SAMR_Q_UNKNOWN_32 q_u;
+ fstring user_name;
- /* grab the samr unknown 32 */
- samr_io_q_unknown_32("", &q_u, data, 0);
+ SAMR_R_CREATE_USER r_u;
+ POLICY_HND pol;
+ uint32 status = 0x0;
+ uint32 user_rid = 0xffffffff;
+ BOOL pol_open = False;
/* find the machine account: tell the caller if it exists.
lkclXXXX i have *no* idea if this is a problem or not
reply if the account already exists...
*/
- unistr2_to_ascii(mach_acct, &q_u.uni_mach_acct, sizeof(mach_acct));
+ /* find the policy handle. open a policy on it. */
+ if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
+ {
+ status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+ }
+
+ /* get a (unique) handle. open a policy on it. */
+ if (status == 0x0 && !(pol_open = open_lsa_policy_hnd(&pol)))
+ {
+ status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
- become_root(True);
- sam_pass = getsam21pwntnam(mach_acct);
- unbecome_root(True);
+ unistr2_to_ascii(user_name, &q_u->uni_name, sizeof(user_name)-1);
+
+ sam_pass = getsam21pwntnam(user_name);
if (sam_pass != NULL)
{
- /* machine account exists: say so */
+ /* account exists: say so */
status = 0xC0000000 | NT_STATUS_USER_EXISTS;
}
else
{
- /* this could cause trouble... */
- DEBUG(0,("trouble!\n"));
- status = 0;
+ pstring err_str;
+ pstring msg_str;
+
+ if (!local_password_change(user_name, True,
+ q_u->acb_info | ACB_DISABLED, 0xffff,
+ NULL,
+ err_str, sizeof(err_str),
+ msg_str, sizeof(msg_str)))
+ {
+ DEBUG(0,("%s\n", err_str));
+ status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
+ }
+ else
+ {
+ sam_pass = getsam21pwntnam(user_name);
+ if (sam_pass == NULL)
+ {
+ /* account doesn't exist: say so */
+ status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
+ }
+ else
+ {
+ user_rid = sam_pass->user_rid;
+ }
+ }
+ }
+
+ /* associate the RID with the (unique) handle. */
+ if (status == 0x0 && !set_lsa_policy_samr_rid(&pol, user_rid))
+ {
+ /* oh, whoops. don't know what error message to return, here */
+ status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ if (status != 0 && pol_open)
+ {
+ close_lsa_policy_hnd(&pol);
+ }
+
+ DEBUG(5,("samr_create_user: %d\n", __LINE__));
+
+ make_samr_r_create_user(&r_u, &pol, 0x000703ff, user_rid, status);
+
+ /* store the response in the SMB stream */
+ samr_io_r_create_user("", &r_u, rdata, 0);
+
+ DEBUG(5,("samr_create_user: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_create_user
+ ********************************************************************/
+static void api_samr_create_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+ SAMR_Q_CREATE_USER q_u;
+
+ /* grab the samr unknown 32 */
+ samr_io_q_create_user("", &q_u, data, 0);
+
/* construct reply. */
- samr_reply_unknown_32(&q_u, rdata, status);
+ samr_reply_create_user(&q_u, rdata);
}
samr_reply_open_group(&q_u, rdata);
}
+/*******************************************************************
+ samr_reply_lookup_domain
+ ********************************************************************/
+static void samr_reply_lookup_domain(SAMR_Q_LOOKUP_DOMAIN *q_u,
+ prs_struct *rdata)
+{
+ SAMR_R_LOOKUP_DOMAIN r_u;
+ fstring domain;
+
+ DEBUG(5,("samr_lookup_domain: %d\n", __LINE__));
+
+ r_u.ptr_sid = 0;
+ r_u.status = 0x0;
+
+ /* find the connection policy handle */
+ if (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1)
+ {
+ r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+ }
+
+ if (r_u.status == 0x0)
+ {
+ unistr2_to_ascii(domain, &(q_u->uni_domain), sizeof(domain));
+ DEBUG(5, ("Lookup Domain: %s\n", domain));
+
+ /* check it's one of ours */
+ if (strequal(domain, global_sam_name))
+ {
+ make_dom_sid2(&(r_u.dom_sid), &global_sam_sid);
+ r_u.ptr_sid = 1;
+ }
+ else if (strequal(domain, "BUILTIN"))
+ {
+ make_dom_sid2(&(r_u.dom_sid), &global_sid_S_1_5_20);
+ r_u.ptr_sid = 1;
+ }
+ else
+ {
+ r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ }
+
+ /* store the response in the SMB stream */
+ samr_io_r_lookup_domain("", &r_u, rdata, 0);
+
+ DEBUG(5,("samr_lookup_domain: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ api_samr_lookup_domain
+ ********************************************************************/
+static void api_samr_lookup_domain( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+ SAMR_Q_LOOKUP_DOMAIN q_u;
+ samr_io_q_lookup_domain("", &q_u, data, 0);
+ samr_reply_lookup_domain(&q_u, rdata);
+}
+
/*******************************************************************
array of \PIPE\samr operations
********************************************************************/
{ "SAMR_LOOKUP_NAMES" , SAMR_LOOKUP_NAMES , api_samr_lookup_names },
{ "SAMR_OPEN_USER" , SAMR_OPEN_USER , api_samr_open_user },
{ "SAMR_QUERY_USERINFO" , SAMR_QUERY_USERINFO , api_samr_query_userinfo },
+ { "SAMR_SET_USERINFO" , SAMR_SET_USERINFO , api_samr_set_userinfo },
{ "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info },
{ "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
{ "SAMR_QUERY_DISPINFO" , SAMR_QUERY_DISPINFO , api_samr_query_dispinfo },
+ { "SAMR_QUERY_DISPINFO3" , SAMR_QUERY_DISPINFO3 , api_samr_query_dispinfo },
+ { "SAMR_QUERY_DISPINFO4" , SAMR_QUERY_DISPINFO4 , api_samr_query_dispinfo },
{ "SAMR_QUERY_ALIASINFO" , SAMR_QUERY_ALIASINFO , api_samr_query_aliasinfo },
{ "SAMR_QUERY_GROUPINFO" , SAMR_QUERY_GROUPINFO , api_samr_query_groupinfo },
- { "SAMR_0x32" , SAMR_UNKNOWN_32 , api_samr_unknown_32 },
+ { "SAMR_CREATE_USER" , SAMR_CREATE_USER , api_samr_create_user },
{ "SAMR_LOOKUP_RIDS" , SAMR_LOOKUP_RIDS , api_samr_lookup_rids },
{ "SAMR_UNKNOWN_38" , SAMR_UNKNOWN_38 , api_samr_unknown_38 },
{ "SAMR_CHGPASSWD_USER" , SAMR_CHGPASSWD_USER , api_samr_chgpasswd_user },
{ "SAMR_OPEN_ALIAS" , SAMR_OPEN_ALIAS , api_samr_open_alias },
{ "SAMR_OPEN_GROUP" , SAMR_OPEN_GROUP , api_samr_open_group },
{ "SAMR_OPEN_DOMAIN" , SAMR_OPEN_DOMAIN , api_samr_open_domain },
+ { "SAMR_LOOKUP_DOMAIN" , SAMR_LOOKUP_DOMAIN , api_samr_lookup_domain },
{ "SAMR_UNKNOWN_3" , SAMR_UNKNOWN_3 , api_samr_unknown_3 },
{ "SAMR_UNKNOWN_2C" , SAMR_UNKNOWN_2C , api_samr_unknown_2c },
{ NULL , 0 , NULL }