Put "WTP" into the Info column for segmented invoke/result PDUs on which
[obnox/wireshark/wip.git] / packet-dcerpc-samr.c
1 /* packet-dcerpc-samr.c
2  * Routines for SMB \PIPE\samr packet disassembly
3  * Copyright 2001,2003 Tim Potter <tpot@samba.org>
4  *   2002 Added all command dissectors  Ronnie Sahlberg
5  *
6  * $Id: packet-dcerpc-samr.c,v 1.99 2003/07/24 20:33:22 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <glib.h>
32 #include <epan/packet.h>
33 #include <string.h>
34 #include "prefs.h"
35 #include "packet-dcerpc.h"
36 #include "packet-dcerpc-nt.h"
37 #include "packet-dcerpc-samr.h"
38 #include "packet-dcerpc-lsa.h"
39 #include "smb.h"        /* for "NT_errors[]" */
40 #include "packet-smb-common.h"
41 #include "crypt-md4.h"
42 #include "crypt-rc4.h"
43
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
46 #endif
47
48 static int proto_dcerpc_samr = -1;
49
50 static int hf_samr_opnum = -1;
51 static int hf_samr_hnd = -1;
52 static int hf_samr_group = -1;
53 static int hf_samr_rid = -1;
54 static int hf_samr_type = -1;
55 static int hf_samr_alias = -1;
56 static int hf_samr_rid_attrib = -1;
57 static int hf_samr_rc = -1;
58 static int hf_samr_index = -1;
59 static int hf_samr_count = -1;
60
61 static int hf_samr_level = -1;
62 static int hf_samr_start_idx = -1;
63 static int hf_samr_max_entries = -1;
64 static int hf_samr_entries = -1;
65 static int hf_samr_pref_maxsize = -1;
66 static int hf_samr_total_size = -1;
67 static int hf_samr_ret_size = -1;
68 static int hf_samr_alias_name = -1;
69 static int hf_samr_group_name = -1;
70 static int hf_samr_acct_name = -1;
71 static int hf_samr_full_name = -1;
72 static int hf_samr_acct_desc = -1;
73 static int hf_samr_home = -1;
74 static int hf_samr_home_drive = -1;
75 static int hf_samr_script = -1;
76 static int hf_samr_workstations = -1;
77 static int hf_samr_profile = -1;
78 static int hf_samr_server = -1;
79 static int hf_samr_domain = -1;
80 static int hf_samr_controller = -1;
81 static int hf_samr_access = -1;
82 static int hf_samr_access_granted = -1;
83 static int hf_samr_crypt_password = -1;
84 static int hf_samr_crypt_hash = -1;
85 static int hf_samr_lm_change = -1;
86 static int hf_samr_lm_passchange_block = -1;
87 static int hf_samr_nt_passchange_block = -1;
88 static int hf_samr_nt_passchange_block_decrypted = -1;
89 static int hf_samr_nt_passchange_block_newpass = -1;
90 static int hf_samr_nt_passchange_block_newpass_len = -1;
91 static int hf_samr_nt_passchange_block_pseudorandom = -1;
92 static int hf_samr_lm_verifier = -1;
93 static int hf_samr_nt_verifier = -1;
94 static int hf_samr_attrib = -1;
95 static int hf_samr_max_pwd_age = -1;
96 static int hf_samr_min_pwd_age = -1;
97 static int hf_samr_min_pwd_len = -1;
98 static int hf_samr_pwd_history_len = -1;
99 static int hf_samr_num_users = -1;
100 static int hf_samr_num_groups = -1;
101 static int hf_samr_num_aliases = -1;
102 static int hf_samr_resume_hnd = -1;
103 static int hf_samr_bad_pwd_count = -1;
104 static int hf_samr_logon_count = -1;
105 static int hf_samr_logon_time = -1;
106 static int hf_samr_logoff_time = -1;
107 static int hf_samr_kickoff_time = -1;
108 static int hf_samr_pwd_last_set_time = -1;
109 static int hf_samr_pwd_can_change_time = -1;
110 static int hf_samr_pwd_must_change_time = -1;
111 static int hf_samr_acct_expiry_time = -1;
112 static int hf_samr_country = -1;
113 static int hf_samr_codepage = -1;
114 static int hf_samr_comment = -1;
115 static int hf_samr_parameters = -1;
116 static int hf_samr_nt_pwd_set = -1;
117 static int hf_samr_lm_pwd_set = -1;
118 static int hf_samr_pwd_expired = -1;
119 static int hf_samr_revision = -1;
120 static int hf_samr_divisions = -1;
121 static int hf_samr_info_type = -1;
122
123 static int hf_samr_unknown_hyper = -1;
124 static int hf_samr_unknown_long = -1;
125 static int hf_samr_unknown_short = -1;
126 static int hf_samr_unknown_char = -1;
127 static int hf_samr_unknown_string = -1;
128 static int hf_samr_unknown_time = -1;
129
130 static int hf_nt_acct_ctrl = -1;
131 static int hf_nt_acb_disabled = -1;
132 static int hf_nt_acb_homedirreq = -1;
133 static int hf_nt_acb_pwnotreq = -1;
134 static int hf_nt_acb_tempdup = -1;
135 static int hf_nt_acb_normal = -1;
136 static int hf_nt_acb_mns = -1;
137 static int hf_nt_acb_domtrust = -1;
138 static int hf_nt_acb_wstrust = -1;
139 static int hf_nt_acb_svrtrust = -1;
140 static int hf_nt_acb_pwnoexp = -1;
141 static int hf_nt_acb_autolock = -1;
142
143 static gint ett_dcerpc_samr = -1;
144 static gint ett_samr_user_dispinfo_1 = -1;
145 static gint ett_samr_user_dispinfo_1_array = -1;
146 static gint ett_samr_user_dispinfo_2 = -1;
147 static gint ett_samr_user_dispinfo_2_array = -1;
148 static gint ett_samr_group_dispinfo = -1;
149 static gint ett_samr_group_dispinfo_array = -1;
150 static gint ett_samr_ascii_dispinfo = -1;
151 static gint ett_samr_ascii_dispinfo_array = -1;
152 static gint ett_samr_display_info = -1;
153 static gint ett_samr_password_info = -1;
154 static gint ett_samr_server = -1;
155 static gint ett_samr_user_group = -1;
156 static gint ett_samr_user_group_array = -1;
157 static gint ett_samr_alias_info = -1;
158 static gint ett_samr_group_info = -1;
159 static gint ett_samr_domain_info_1 = -1;
160 static gint ett_samr_domain_info_2 = -1;
161 static gint ett_samr_domain_info_8 = -1;
162 static gint ett_samr_replication_status = -1;
163 static gint ett_samr_domain_info_11 = -1;
164 static gint ett_samr_domain_info_13 = -1;
165 static gint ett_samr_domain_info = -1;
166 static gint ett_samr_sid_pointer = -1;
167 static gint ett_samr_sid_array = -1;
168 static gint ett_samr_index_array = -1;
169 static gint ett_samr_idx_and_name = -1;
170 static gint ett_samr_idx_and_name_array = -1;
171 static gint ett_samr_logon_hours = -1;
172 static gint ett_samr_logon_hours_hours = -1;
173 static gint ett_samr_user_info_1 = -1;
174 static gint ett_samr_user_info_2 = -1;
175 static gint ett_samr_user_info_3 = -1;
176 static gint ett_samr_user_info_5 = -1;
177 static gint ett_samr_user_info_6 = -1;
178 static gint ett_samr_user_info_18 = -1;
179 static gint ett_samr_user_info_19 = -1;
180 static gint ett_samr_buffer_buffer = -1;
181 static gint ett_samr_buffer = -1;
182 static gint ett_samr_user_info_21 = -1;
183 static gint ett_samr_user_info_22 = -1;
184 static gint ett_samr_user_info_23 = -1;
185 static gint ett_samr_user_info_24 = -1;
186 static gint ett_samr_user_info = -1;
187 static gint ett_samr_member_array_types = -1;
188 static gint ett_samr_member_array_rids = -1;
189 static gint ett_samr_member_array = -1;
190 static gint ett_samr_names = -1;
191 static gint ett_samr_rids = -1;
192 static gint ett_nt_acct_ctrl = -1;
193 static gint ett_samr_sid_and_attributes_array = -1;
194 static gint ett_samr_sid_and_attributes = -1;
195 #ifdef SAMR_UNUSED_HANDLES
196 static gint ett_samr_hnd = -1;
197 #endif
198
199 static e_uuid_t uuid_dcerpc_samr = {
200         0x12345778, 0x1234, 0xabcd,
201         { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xac}
202 };
203
204 static guint16 ver_dcerpc_samr = 1;
205
206 /* Configuration variables */
207 static char *nt_password = NULL;
208
209 /* Dissect connect specific access rights */
210
211 static gint hf_access_connect_connect_to_server = -1;
212 static gint hf_access_connect_shutdown_server = -1;
213 static gint hf_access_connect_initialize_server = -1;
214 static gint hf_access_connect_create_domain = -1;
215 static gint hf_access_connect_enum_domains = -1;
216 static gint hf_access_connect_open_domain = -1;
217
218 static void
219 specific_rights_connect(tvbuff_t *tvb, gint offset, proto_tree *tree,
220                         guint32 access)
221 {
222         proto_tree_add_boolean(
223                 tree, hf_access_connect_open_domain,
224                 tvb, offset, 4, access);
225
226         proto_tree_add_boolean(
227                 tree, hf_access_connect_enum_domains,
228                 tvb, offset, 4, access);
229
230         proto_tree_add_boolean(
231                 tree, hf_access_connect_create_domain,
232                 tvb, offset, 4, access);
233
234         proto_tree_add_boolean(
235                 tree, hf_access_connect_initialize_server,
236                 tvb, offset, 4, access);
237
238         proto_tree_add_boolean(
239                 tree, hf_access_connect_shutdown_server,
240                 tvb, offset, 4, access);
241
242         proto_tree_add_boolean(
243                 tree, hf_access_connect_connect_to_server,
244                 tvb, offset, 4, access);
245 }
246
247 struct access_mask_info samr_connect_access_mask_info = {
248         "SAMR connect",
249         specific_rights_connect,
250         NULL,                       /* Generic rights mapping */
251         NULL                        /* Standard rights mapping */
252 };
253
254 /* Dissect domain specific access rights */
255
256 static gint hf_access_domain_lookup_info1 = -1;
257 static gint hf_access_domain_set_info1 = -1;
258 static gint hf_access_domain_lookup_info2 = -1;
259 static gint hf_access_domain_set_info2 = -1;
260 static gint hf_access_domain_create_user = -1;
261 static gint hf_access_domain_create_group = -1;
262 static gint hf_access_domain_create_alias = -1;
263 static gint hf_access_domain_lookup_alias_by_mem = -1;
264 static gint hf_access_domain_enum_accounts = -1;
265 static gint hf_access_domain_open_account = -1;
266 static gint hf_access_domain_set_info3 = -1;
267
268 static void
269 specific_rights_domain(tvbuff_t *tvb, gint offset, proto_tree *tree,
270                        guint32 access)
271 {
272         proto_tree_add_boolean(
273                 tree, hf_access_domain_set_info3,
274                 tvb, offset, 4, access);
275
276         proto_tree_add_boolean(
277                 tree, hf_access_domain_open_account,
278                 tvb, offset, 4, access);
279
280         proto_tree_add_boolean(
281                 tree, hf_access_domain_enum_accounts,
282                 tvb, offset, 4, access);
283
284         proto_tree_add_boolean(
285                 tree, hf_access_domain_lookup_alias_by_mem,
286                 tvb, offset, 4, access);
287
288         proto_tree_add_boolean(
289                 tree, hf_access_domain_create_alias,
290                 tvb, offset, 4, access);
291
292         proto_tree_add_boolean(
293                 tree, hf_access_domain_create_group,
294                 tvb, offset, 4, access);
295
296         proto_tree_add_boolean(
297                 tree, hf_access_domain_create_user,
298                 tvb, offset, 4, access);
299
300         proto_tree_add_boolean(
301                 tree, hf_access_domain_set_info2,
302                 tvb, offset, 4, access);
303
304         proto_tree_add_boolean(
305                 tree, hf_access_domain_lookup_info2,
306                 tvb, offset, 4, access);
307
308         proto_tree_add_boolean(
309                 tree, hf_access_domain_set_info1,
310                 tvb, offset, 4, access);
311
312         proto_tree_add_boolean(
313                 tree, hf_access_domain_lookup_info1,
314                 tvb, offset, 4, access);
315         }
316
317 struct access_mask_info samr_domain_access_mask_info = {
318         "SAMR domain",
319         specific_rights_domain,
320         NULL,                   /* Generic mapping table */
321         NULL                    /* Standard mapping table */
322 };
323
324 /* Dissect user specific access rights */
325
326 static gint hf_access_user_get_name_etc = -1;
327 static gint hf_access_user_get_locale = -1;
328 static gint hf_access_user_get_loc_com = -1;
329 static gint hf_access_user_get_logoninfo = -1;
330 static gint hf_access_user_get_attributes = -1;
331 static gint hf_access_user_set_attributes = -1;
332 static gint hf_access_user_change_password = -1;
333 static gint hf_access_user_set_password = -1;
334 static gint hf_access_user_get_groups = -1;
335 static gint hf_access_user_get_group_membership = -1;
336 static gint hf_access_user_change_group_membership = -1;
337
338 static void
339 specific_rights_user(tvbuff_t *tvb, gint offset, proto_tree *tree,
340                      guint32 access)
341 {
342         proto_tree_add_boolean(
343                 tree, hf_access_user_change_group_membership,
344                 tvb, offset, 4, access);
345
346         proto_tree_add_boolean(
347                 tree, hf_access_user_get_group_membership,
348                 tvb, offset, 4, access);
349
350         proto_tree_add_boolean(
351                 tree, hf_access_user_get_groups,
352                 tvb, offset, 4, access);
353
354         proto_tree_add_boolean(
355                 tree, hf_access_user_set_password,
356                 tvb, offset, 4, access);
357
358         proto_tree_add_boolean(
359                 tree, hf_access_user_change_password,
360                 tvb, offset, 4, access);
361
362         proto_tree_add_boolean(
363                 tree, hf_access_user_set_attributes,
364                 tvb, offset, 4, access);
365
366         proto_tree_add_boolean(
367                 tree, hf_access_user_get_attributes,
368                 tvb, offset, 4, access);
369
370         proto_tree_add_boolean(
371                 tree, hf_access_user_get_logoninfo,
372                 tvb, offset, 4, access);
373
374         proto_tree_add_boolean(
375                 tree, hf_access_user_get_loc_com,
376                 tvb, offset, 4, access);
377
378         proto_tree_add_boolean(
379                 tree, hf_access_user_get_locale,
380                 tvb, offset, 4, access);
381
382         proto_tree_add_boolean(
383                 tree, hf_access_user_get_name_etc,
384                 tvb, offset, 4, access);
385 }
386
387 struct access_mask_info samr_user_access_mask_info = {
388         "SAMR user",
389         specific_rights_user,
390         NULL,                   /* Generic mapping table */
391         NULL                    /* Standard mapping table */
392 };
393
394 /* Dissect alias specific access rights */
395
396 static gint hf_access_alias_add_member = -1;
397 static gint hf_access_alias_remove_member = -1;
398 static gint hf_access_alias_get_members = -1;
399 static gint hf_access_alias_lookup_info = -1;
400 static gint hf_access_alias_set_info = -1;
401
402 static void
403 specific_rights_alias(tvbuff_t *tvb, gint offset, proto_tree *tree,
404                       guint32 access)
405 {
406         proto_tree_add_boolean(
407                 tree, hf_access_alias_set_info,
408                 tvb, offset, 4, access);
409
410         proto_tree_add_boolean(
411                 tree, hf_access_alias_lookup_info,
412                 tvb, offset, 4, access);
413
414         proto_tree_add_boolean(
415                 tree, hf_access_alias_get_members,
416                 tvb, offset, 4, access);
417
418         proto_tree_add_boolean(
419                 tree, hf_access_alias_remove_member,
420                 tvb, offset, 4, access);
421
422         proto_tree_add_boolean(
423                 tree, hf_access_alias_add_member,
424                 tvb, offset, 4, access);
425 }
426
427 struct access_mask_info samr_alias_access_mask_info = {
428         "SAMR alias",
429         specific_rights_alias,
430         NULL,                   /* Generic mapping table */
431         NULL                    /* Standard mapping table */
432 };
433
434 /* Dissect group specific access rights */
435
436 static gint hf_access_group_lookup_info = -1;
437 static gint hf_access_group_set_info = -1;
438 static gint hf_access_group_add_member = -1;
439 static gint hf_access_group_remove_member = -1;
440 static gint hf_access_group_get_members = -1;
441
442 static void
443 specific_rights_group(tvbuff_t *tvb, gint offset, proto_tree *tree,
444                       guint32 access)
445 {
446         proto_tree_add_boolean(
447                 tree, hf_access_group_get_members,
448                 tvb, offset, 4, access);
449
450         proto_tree_add_boolean(
451                 tree, hf_access_group_remove_member,
452                 tvb, offset, 4, access);
453
454         proto_tree_add_boolean(
455                 tree, hf_access_group_add_member,
456                 tvb, offset, 4, access);
457
458         proto_tree_add_boolean(
459                 tree, hf_access_group_set_info,
460                 tvb, offset, 4, access);
461
462         proto_tree_add_boolean(
463                 tree, hf_access_group_lookup_info,
464                 tvb, offset, 4, access);
465 }
466
467 struct access_mask_info samr_group_access_mask_info = {
468         "SAMR group",
469         specific_rights_group,
470         NULL,                   /* Generic mapping table */
471         NULL                    /* Standard mapping table */
472 };
473
474 int
475 dissect_ndr_nt_SID(tvbuff_t *tvb, int offset, packet_info *pinfo, 
476                    proto_tree *tree, char *drep, int hf_sid)
477 {
478         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
479         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
480         char *sid_str;
481         char *name;
482
483         if(di->hf_index!=-1){
484                 name=proto_registrar_get_name(di->hf_index);
485         } else {
486                 name="Domain";
487         }
488         if(di->conformant_run){
489                 /* just a run to handle conformant arrays, no scalars to dissect */
490                 return offset;
491         }
492
493         /* the SID contains a conformant array, first we must eat
494            the 4-byte max_count before we can hand it off */
495
496         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
497                         hf_samr_count, NULL);
498
499         offset = dissect_nt_sid(tvb, offset, tree, name, &sid_str, hf_sid);
500
501         dcv->private_data = sid_str;
502
503         return offset;
504 }
505 static int
506 dissect_ndr_nt_SID_no_hf(tvbuff_t *tvb, int offset, packet_info *pinfo, 
507                    proto_tree *tree, char *drep)
508 {
509         offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep, -1);
510         return offset;
511 }
512 static int
513 dissect_ndr_nt_SID_hf_through_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo, 
514                    proto_tree *tree, char *drep)
515 {
516         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
517
518         offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep, di->hf_index);
519         return offset;
520 }
521
522
523
524 static const true_false_string tfs_nt_acb_disabled = {
525         "Account is DISABLED",
526         "Account is NOT disabled"
527 };
528 static const true_false_string tfs_nt_acb_homedirreq = {
529         "Homedir is REQUIRED",
530         "Homedir is NOT required"
531 };
532 static const true_false_string tfs_nt_acb_pwnotreq = {
533         "Password is NOT required",
534         "Password is REQUIRED"
535 };
536 static const true_false_string tfs_nt_acb_tempdup = {
537         "This is a TEMPORARY DUPLICATE account",
538         "This is NOT a temporary duplicate account"
539 };
540 static const true_false_string tfs_nt_acb_normal = {
541         "This is a NORMAL USER account",
542         "This is NOT a normal user account"
543 };
544 static const true_false_string tfs_nt_acb_mns = {
545         "This is a MNS account",
546         "This is NOT a mns account"
547 };
548 static const true_false_string tfs_nt_acb_domtrust = {
549         "This is a DOMAIN TRUST account",
550         "This is NOT a domain trust account"
551 };
552 static const true_false_string tfs_nt_acb_wstrust = {
553         "This is a WORKSTATION TRUST account",
554         "This is NOT a workstation trust account"
555 };
556 static const true_false_string tfs_nt_acb_svrtrust = {
557         "This is a SERVER TRUST account",
558         "This is NOT a server trust account"
559 };
560 static const true_false_string tfs_nt_acb_pwnoexp = {
561         "Passwords does NOT expire",
562         "Password will EXPIRE"
563 };
564 static const true_false_string tfs_nt_acb_autolock = {
565         "This account has been AUTO LOCKED",
566         "This account has NOT been auto locked"
567 };
568 int
569 dissect_ndr_nt_acct_ctrl(tvbuff_t *tvb, int offset, packet_info *pinfo,
570                         proto_tree *parent_tree, char *drep)
571 {
572         guint32 mask;
573         proto_item *item = NULL;
574         proto_tree *tree = NULL;
575
576         offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
577                         hf_nt_acct_ctrl, &mask);
578
579         if(parent_tree){
580                 item = proto_tree_add_uint(parent_tree, hf_nt_acct_ctrl,
581                         tvb, offset-4, 4, mask);
582                 tree = proto_item_add_subtree(item, ett_nt_acct_ctrl);
583         }
584
585         proto_tree_add_boolean(tree, hf_nt_acb_autolock,
586                 tvb, offset-4, 4, mask);
587         proto_tree_add_boolean(tree, hf_nt_acb_pwnoexp,
588                 tvb, offset-4, 4, mask);
589         proto_tree_add_boolean(tree, hf_nt_acb_svrtrust,
590                 tvb, offset-4, 4, mask);
591         proto_tree_add_boolean(tree, hf_nt_acb_wstrust,
592                 tvb, offset-4, 4, mask);
593         proto_tree_add_boolean(tree, hf_nt_acb_domtrust,
594                 tvb, offset-4, 4, mask);
595         proto_tree_add_boolean(tree, hf_nt_acb_mns,
596                 tvb, offset-4, 4, mask);
597         proto_tree_add_boolean(tree, hf_nt_acb_normal,
598                 tvb, offset-4, 4, mask);
599         proto_tree_add_boolean(tree, hf_nt_acb_tempdup,
600                 tvb, offset-4, 4, mask);
601         proto_tree_add_boolean(tree, hf_nt_acb_pwnotreq,
602                 tvb, offset-4, 4, mask);
603         proto_tree_add_boolean(tree, hf_nt_acb_homedirreq,
604                 tvb, offset-4, 4, mask);
605         proto_tree_add_boolean(tree, hf_nt_acb_disabled,
606                 tvb, offset-4, 4, mask);
607
608         return offset;
609 }
610
611
612 /* above this line, just some general support routines which should be placed
613    in some more generic file common to all NT services dissectors
614 */
615
616 static int
617 samr_dissect_open_user_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo,
618                             proto_tree *tree, char *drep)
619 {
620         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
621         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
622         guint32 rid;
623
624         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
625                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
626
627         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
628                         hf_samr_access, NULL);
629
630         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
631                         hf_samr_rid, &rid);
632
633         if (check_col(pinfo->cinfo, COL_INFO))
634                 col_append_fstr(pinfo->cinfo, COL_INFO, ", rid 0x%x", rid);
635
636         dcv->private_data = GINT_TO_POINTER(rid);
637
638         return offset;
639 }
640
641 static int
642 samr_dissect_open_user_reply(tvbuff_t *tvb, int offset,
643                              packet_info *pinfo, proto_tree *tree,
644                              char *drep)
645 {
646         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
647         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
648         e_ctx_hnd policy_hnd;
649         proto_item *hnd_item;
650         guint32 status;
651         guint32 rid = GPOINTER_TO_INT(dcv->private_data);
652         char *pol_name;
653
654         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
655                                        hf_samr_hnd, &policy_hnd, &hnd_item,
656                                        TRUE, FALSE);
657
658         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
659                                   hf_samr_rc, &status);
660
661         if (status == 0) {
662                 if (rid)
663                         pol_name = g_strdup_printf("OpenUser(rid 0x%x)", rid);
664                 else
665                         pol_name = g_strdup("OpenUser handle");
666
667                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
668
669                 if (hnd_item != NULL)
670                         proto_item_append_text(hnd_item, ": %s", pol_name);
671
672                 g_free(pol_name);
673         }
674
675         return offset;
676 }
677
678 static int
679 samr_dissect_pointer_long(tvbuff_t *tvb, int offset,
680                              packet_info *pinfo, proto_tree *tree,
681                              char *drep)
682 {
683         dcerpc_info *di;
684
685         di=pinfo->private_data;
686         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
687                                      di->hf_index, NULL);
688         return offset;
689 }
690
691 static int
692 samr_dissect_pointer_STRING(tvbuff_t *tvb, int offset,
693                              packet_info *pinfo, proto_tree *tree,
694                              char *drep)
695 {
696         dcerpc_info *di;
697
698         di=pinfo->private_data;
699         if(di->conformant_run){
700                 /*just a run to handle conformant arrays, nothing to dissect */
701                 return offset;
702         }
703
704         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
705                         di->hf_index, 0);
706         return offset;
707 }
708
709 static int
710 samr_dissect_pointer_short(tvbuff_t *tvb, int offset,
711                              packet_info *pinfo, proto_tree *tree,
712                              char *drep)
713 {
714         dcerpc_info *di;
715
716         di=pinfo->private_data;
717         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
718                                      di->hf_index, NULL);
719         return offset;
720 }
721
722
723 static int
724 samr_dissect_query_dispinfo_rqst(tvbuff_t *tvb, int offset,
725                                  packet_info *pinfo, proto_tree *tree,
726                                  char *drep)
727 {
728         guint16 level;
729         guint32 start_idx;
730
731         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
732                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
733
734         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
735                                      hf_samr_level, &level);
736         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
737                                      hf_samr_start_idx, &start_idx);
738         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
739                                      hf_samr_max_entries, NULL);
740         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
741                                      hf_samr_pref_maxsize, NULL);
742
743         if (check_col(pinfo->cinfo, COL_INFO))
744                 col_append_fstr(
745                         pinfo->cinfo, COL_INFO, ", level %d, start_idx %d", 
746                         level, start_idx);
747
748         return offset;
749 }
750
751 static int
752 samr_dissect_USER_DISPINFO_1(tvbuff_t *tvb, int offset,
753                         packet_info *pinfo, proto_tree *parent_tree,
754                         char *drep)
755 {
756         proto_item *item=NULL;
757         proto_tree *tree=NULL;
758         int old_offset=offset;
759
760         if(parent_tree){
761                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
762                         "User_DispInfo_1");
763                 tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
764         }
765
766         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
767                                 hf_samr_index, NULL);
768         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
769                                 hf_samr_rid, NULL);
770         offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
771         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
772                                 hf_samr_acct_name, 0);
773         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
774                                 hf_samr_full_name, 0);
775         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
776                                 hf_samr_acct_desc, 0);
777
778         proto_item_set_len(item, offset-old_offset);
779         return offset;
780 }
781
782 static int
783 samr_dissect_USER_DISPINFO_1_ARRAY_users(tvbuff_t *tvb, int offset,
784                         packet_info *pinfo, proto_tree *tree,
785                         char *drep)
786 {
787         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
788                         samr_dissect_USER_DISPINFO_1);
789
790         return offset;
791 }
792
793 static int
794 samr_dissect_USER_DISPINFO_1_ARRAY (tvbuff_t *tvb, int offset,
795                              packet_info *pinfo, proto_tree *parent_tree,
796                              char *drep)
797 {
798         guint32 count;
799         proto_item *item=NULL;
800         proto_tree *tree=NULL;
801         int old_offset=offset;
802
803         if(parent_tree){
804                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
805                         "User_DispInfo_1 Array");
806                 tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1_array);
807         }
808
809
810         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
811                                      hf_samr_count, &count);
812         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
813                         samr_dissect_USER_DISPINFO_1_ARRAY_users, NDR_POINTER_PTR,
814                         "USER_DISPINFO_1_ARRAY", -1);
815
816         proto_item_set_len(item, offset-old_offset);
817         return offset;
818 }
819
820
821
822 static int
823 samr_dissect_USER_DISPINFO_2(tvbuff_t *tvb, int offset,
824                         packet_info *pinfo, proto_tree *parent_tree,
825                         char *drep)
826 {
827         proto_item *item=NULL;
828         proto_tree *tree=NULL;
829         int old_offset=offset;
830
831         if(parent_tree){
832                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
833                         "User_DispInfo_2");
834                 tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_2);
835         }
836
837         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
838                         hf_samr_index, NULL);
839         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
840                         hf_samr_rid, NULL);
841         offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
842         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
843                         hf_samr_acct_name, 0);
844         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
845                         hf_samr_acct_desc, 0);
846
847         proto_item_set_len(item, offset-old_offset);
848         return offset;
849 }
850
851 static int
852 samr_dissect_USER_DISPINFO_2_ARRAY_users (tvbuff_t *tvb, int offset,
853                              packet_info *pinfo, proto_tree *tree,
854                              char *drep)
855 {
856         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
857                         samr_dissect_USER_DISPINFO_2);
858
859         return offset;
860 }
861
862 static int
863 samr_dissect_USER_DISPINFO_2_ARRAY (tvbuff_t *tvb, int offset,
864                              packet_info *pinfo, proto_tree *parent_tree,
865                              char *drep)
866 {
867         guint32 count;
868         proto_item *item=NULL;
869         proto_tree *tree=NULL;
870         int old_offset=offset;
871
872         if(parent_tree){
873                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
874                         "User_DispInfo_2 Array");
875                 tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_2_array);
876         }
877
878
879         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
880                                      hf_samr_count, &count);
881         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
882                         samr_dissect_USER_DISPINFO_2_ARRAY_users, NDR_POINTER_PTR,
883                         "USER_DISPINFO_2_ARRAY", -1);
884
885         proto_item_set_len(item, offset-old_offset);
886         return offset;
887 }
888
889 static int
890 samr_dissect_GROUP_DISPINFO(tvbuff_t *tvb, int offset,
891                         packet_info *pinfo, proto_tree *parent_tree,
892                         char *drep)
893 {
894         proto_item *item=NULL;
895         proto_tree *tree=NULL;
896         int old_offset=offset;
897
898         if(parent_tree){
899                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
900                         "Group_DispInfo");
901                 tree = proto_item_add_subtree(item, ett_samr_group_dispinfo);
902         }
903
904
905         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
906                         hf_samr_index, NULL);
907         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
908                         hf_samr_rid, NULL);
909         offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
910         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
911                         hf_samr_acct_name, 0);
912         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
913                         hf_samr_acct_desc, 0);
914
915         proto_item_set_len(item, offset-old_offset);
916         return offset;
917 }
918
919 static int
920 samr_dissect_GROUP_DISPINFO_ARRAY_groups(tvbuff_t *tvb, int offset,
921                         packet_info *pinfo, proto_tree *tree,
922                         char *drep)
923 {
924         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
925                         samr_dissect_GROUP_DISPINFO);
926
927         return offset;
928 }
929
930 static int
931 samr_dissect_GROUP_DISPINFO_ARRAY(tvbuff_t *tvb, int offset,
932                         packet_info *pinfo, proto_tree *parent_tree,
933                         char *drep)
934 {
935         guint32 count;
936         proto_item *item=NULL;
937         proto_tree *tree=NULL;
938         int old_offset=offset;
939
940         if(parent_tree){
941                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
942                         "Group_DispInfo Array");
943                 tree = proto_item_add_subtree(item, ett_samr_group_dispinfo_array);
944         }
945
946         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
947                                      hf_samr_count, &count);
948         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
949                         samr_dissect_GROUP_DISPINFO_ARRAY_groups, NDR_POINTER_PTR,
950                         "GROUP_DISPINFO_ARRAY", -1);
951
952         proto_item_set_len(item, offset-old_offset);
953         return offset;
954 }
955
956
957
958 static int
959 samr_dissect_ASCII_DISPINFO(tvbuff_t *tvb, int offset,
960                         packet_info *pinfo, proto_tree *parent_tree,
961                         char *drep)
962 {
963         proto_item *item=NULL;
964         proto_tree *tree=NULL;
965         int old_offset=offset;
966
967         if(parent_tree){
968                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
969                         "Ascii_DispInfo");
970                 tree = proto_item_add_subtree(item, ett_samr_ascii_dispinfo);
971         }
972
973
974         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
975                         hf_samr_index, NULL);
976         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
977                         hf_samr_rid, NULL);
978         offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
979         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
980                         hf_samr_acct_name, 0);
981         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
982                         hf_samr_acct_desc, 0);
983
984         proto_item_set_len(item, offset-old_offset);
985         return offset;
986 }
987
988 static int
989 samr_dissect_ASCII_DISPINFO_ARRAY_users(tvbuff_t *tvb, int offset,
990                         packet_info *pinfo, proto_tree *tree,
991                         char *drep)
992 {
993         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
994                         samr_dissect_ASCII_DISPINFO);
995
996         return offset;
997 }
998
999 static int
1000 samr_dissect_ASCII_DISPINFO_ARRAY(tvbuff_t *tvb, int offset,
1001                         packet_info *pinfo, proto_tree *parent_tree,
1002                         char *drep)
1003 {
1004         guint32 count;
1005         proto_item *item=NULL;
1006         proto_tree *tree=NULL;
1007         int old_offset=offset;
1008
1009         if(parent_tree){
1010                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
1011                         "Ascii_DispInfo Array");
1012                 tree = proto_item_add_subtree(item, ett_samr_ascii_dispinfo_array);
1013         }
1014
1015         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1016                                      hf_samr_count, &count);
1017         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1018                         samr_dissect_ASCII_DISPINFO_ARRAY_users, NDR_POINTER_PTR,
1019                         "ACSII_DISPINFO_ARRAY", -1);
1020
1021         proto_item_set_len(item, offset-old_offset);
1022         return offset;
1023 }
1024
1025
1026 static int
1027 samr_dissect_DISPLAY_INFO (tvbuff_t *tvb, int offset,
1028                              packet_info *pinfo, proto_tree *parent_tree,
1029                              char *drep)
1030 {
1031         proto_item *item=NULL;
1032         proto_tree *tree=NULL;
1033         int old_offset=offset;
1034         guint16 level;
1035
1036         if(parent_tree){
1037                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
1038                         "DISP_INFO:");
1039                 tree = proto_item_add_subtree(item, ett_samr_display_info);
1040         }
1041
1042         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
1043                                      hf_samr_level, &level);
1044         switch(level){
1045         case 1:
1046                 offset = samr_dissect_USER_DISPINFO_1_ARRAY(
1047                                 tvb, offset, pinfo, tree, drep);
1048                 break;
1049         case 2:
1050                 offset = samr_dissect_USER_DISPINFO_2_ARRAY(
1051                                 tvb, offset, pinfo, tree, drep);
1052                 break;
1053         case 3:
1054                 offset = samr_dissect_GROUP_DISPINFO_ARRAY(
1055                                 tvb, offset, pinfo, tree, drep);
1056                 break;
1057         case 4:
1058                 offset = samr_dissect_ASCII_DISPINFO_ARRAY(
1059                                 tvb, offset, pinfo, tree, drep);
1060                 break;
1061         case 5:
1062                 offset = samr_dissect_ASCII_DISPINFO_ARRAY(
1063                                 tvb, offset, pinfo, tree, drep);
1064                 break;
1065         }
1066
1067         proto_item_set_len(item, offset-old_offset);
1068         return offset;
1069 }
1070
1071 static int
1072 samr_dissect_query_dispinfo_reply(tvbuff_t *tvb, int offset,
1073                                   packet_info *pinfo, proto_tree *tree,
1074                                   char *drep)
1075 {
1076         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1077                         samr_dissect_pointer_long, NDR_POINTER_REF,
1078                         "Total Size", hf_samr_total_size);
1079         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1080                         samr_dissect_pointer_long, NDR_POINTER_REF,
1081                         "Returned Size", hf_samr_ret_size);
1082         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1083                         samr_dissect_DISPLAY_INFO, NDR_POINTER_REF,
1084                         "DISPLAY_INFO:", -1);
1085         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1086                         hf_samr_rc, NULL);
1087
1088         return offset;
1089 }
1090
1091 static int
1092 samr_dissect_get_display_enumeration_index_rqst(tvbuff_t *tvb, int offset,
1093                                                 packet_info *pinfo,
1094                                                 proto_tree *tree,
1095                                                 char *drep)
1096 {
1097         guint16 level;
1098
1099         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1100                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1101
1102         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
1103                                      hf_samr_level, &level);
1104
1105         if (check_col(pinfo->cinfo, COL_INFO))
1106                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1107
1108         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
1109                         hf_samr_acct_name, 0);
1110
1111         return offset;
1112 }
1113
1114 static int
1115 samr_dissect_get_display_enumeration_index_reply(tvbuff_t *tvb, int offset,
1116                              packet_info *pinfo, proto_tree *tree,
1117                              char *drep)
1118 {
1119         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1120                         samr_dissect_pointer_long, NDR_POINTER_REF,
1121                         "Index", hf_samr_index);
1122
1123         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1124                                   hf_samr_rc, NULL);
1125
1126         return offset;
1127 }
1128
1129
1130
1131
1132 static int
1133 samr_dissect_PASSWORD_INFO(tvbuff_t *tvb, int offset,
1134                         packet_info *pinfo, proto_tree *parent_tree,
1135                         char *drep)
1136 {
1137         proto_item *item=NULL;
1138         proto_tree *tree=NULL;
1139         int old_offset=offset;
1140
1141         ALIGN_TO_4_BYTES;  /* strcture starts with short, but is aligned for longs */
1142
1143         if(parent_tree){
1144                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
1145                         "PASSWORD_INFO:");
1146                 tree = proto_item_add_subtree(item, ett_samr_password_info);
1147         }
1148
1149
1150         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
1151                         hf_samr_unknown_short, NULL);
1152         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1153                         hf_samr_unknown_long, NULL);
1154
1155         proto_item_set_len(item, offset-old_offset);
1156         return offset;
1157 }
1158
1159 static int
1160 samr_dissect_get_usrdom_pwinfo_rqst(tvbuff_t *tvb, int offset,
1161                                     packet_info *pinfo, proto_tree *tree,
1162                                     char *drep)
1163 {
1164         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1165                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1166
1167         return offset;
1168 }
1169
1170 static int
1171 samr_dissect_get_usrdom_pwinfo_reply(tvbuff_t *tvb, int offset,
1172                              packet_info *pinfo, proto_tree *tree,
1173                              char *drep)
1174 {
1175         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1176                         samr_dissect_PASSWORD_INFO, NDR_POINTER_REF,
1177                         "PASSWORD_INFO:", -1);
1178
1179         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1180                                   hf_samr_rc, NULL);
1181         return offset;
1182 }
1183
1184 static int
1185 samr_dissect_connect2_rqst(tvbuff_t *tvb, int offset,
1186                            packet_info *pinfo, proto_tree *tree,
1187                            char *drep)
1188 {
1189         offset = dissect_ndr_pointer_cb(
1190                 tvb, offset, pinfo, tree, drep,
1191                 dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
1192                 "Server", hf_samr_server, cb_wstr_postprocess,
1193                 GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
1194
1195         offset = dissect_nt_access_mask(
1196                 tvb, offset, pinfo, tree, drep, hf_samr_access,
1197                 &samr_connect_access_mask_info);
1198
1199         return offset;
1200 }
1201
1202 static int
1203 samr_dissect_connect4_rqst(tvbuff_t *tvb, int offset,
1204                            packet_info *pinfo, proto_tree *tree,
1205                            char *drep)
1206 {
1207         offset = dissect_ndr_pointer_cb(
1208                 tvb, offset, pinfo, tree, drep,
1209                 dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
1210                 "Server", hf_samr_server, cb_wstr_postprocess,
1211                 GINT_TO_POINTER(CB_STR_COL_INFO | 1));
1212
1213         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1214                                      hf_samr_unknown_long, NULL);
1215
1216         offset = dissect_nt_access_mask(
1217                 tvb, offset, pinfo, tree, drep, hf_samr_access,
1218                 &samr_connect_access_mask_info);
1219
1220         return offset;
1221 }
1222
1223 static int
1224 samr_dissect_connect2_reply(tvbuff_t *tvb, int offset,
1225                              packet_info *pinfo, proto_tree *tree,
1226                              char *drep)
1227 {
1228         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1229         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1230         e_ctx_hnd policy_hnd;
1231         proto_item *hnd_item;
1232         guint32 status;
1233         char *server = (char *)dcv->private_data, *pol_name;
1234         
1235         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1236                                        hf_samr_hnd, &policy_hnd, &hnd_item,
1237                                        TRUE, FALSE);
1238
1239         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1240                                   hf_samr_rc, &status);
1241
1242         if (status == 0) {
1243                 if (server)
1244                         pol_name = g_strdup_printf("Connect2(%s)", server);
1245                 else
1246                         pol_name = g_strdup("Connect2 handle");
1247
1248                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
1249
1250                 if (hnd_item != NULL)
1251                         proto_item_append_text(hnd_item, ": %s", pol_name);
1252
1253                 g_free(pol_name);
1254         }
1255
1256         return offset;
1257 }
1258
1259 static int
1260 samr_dissect_connect_anon_rqst(tvbuff_t *tvb, int offset,
1261                                packet_info *pinfo, proto_tree *tree,
1262                                char *drep)
1263 {
1264         char str[2];
1265         guint16 server;
1266
1267         offset=dissect_ndr_uint16(tvb, offset, pinfo, NULL, drep,
1268                         hf_samr_server, &server);
1269         str[0]=server&0xff;
1270         str[1]=0;
1271         proto_tree_add_string_format(tree, hf_samr_server, tvb, offset-2, 2,
1272                 str, "Server: %s", str);
1273
1274         return offset;
1275 }
1276
1277 static int
1278 samr_dissect_connect_anon_reply(tvbuff_t *tvb, int offset,
1279                                 packet_info *pinfo, proto_tree *tree,
1280                                 char *drep)
1281 {
1282         e_ctx_hnd policy_hnd;
1283         proto_item *hnd_item;
1284         guint32 status;
1285
1286         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1287                                        hf_samr_hnd, &policy_hnd, &hnd_item,
1288                                        TRUE, FALSE);
1289
1290         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1291                                   hf_samr_rc, &status);
1292
1293         if (status == 0) {
1294                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo,
1295                                           "ConnectAnon handle");
1296
1297                 if (hnd_item != NULL)
1298                         proto_item_append_text(hnd_item, ": ConnectAnon handle");
1299         }
1300
1301         return offset;
1302 }
1303
1304 static int
1305 samr_dissect_USER_GROUP(tvbuff_t *tvb, int offset,
1306                              packet_info *pinfo, proto_tree *parent_tree,
1307                              char *drep)
1308 {
1309         proto_item *item=NULL;
1310         proto_tree *tree=NULL;
1311         int old_offset=offset;
1312
1313         if(parent_tree){
1314                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
1315                         "USER_GROUP:");
1316                 tree = proto_item_add_subtree(item, ett_samr_user_group);
1317         }
1318
1319         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1320                                      hf_samr_rid, NULL);
1321         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1322                                      hf_samr_rid_attrib, NULL);
1323
1324         proto_item_set_len(item, offset-old_offset);
1325         return offset;
1326 }
1327
1328 static int
1329 samr_dissect_USER_GROUP_ARRAY_groups (tvbuff_t *tvb, int offset,
1330                              packet_info *pinfo, proto_tree *tree,
1331                              char *drep)
1332 {
1333         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
1334                         samr_dissect_USER_GROUP);
1335
1336         return offset;
1337 }
1338
1339 static int
1340 samr_dissect_USER_GROUP_ARRAY(tvbuff_t *tvb, int offset,
1341                         packet_info *pinfo, proto_tree *parent_tree,
1342                         char *drep)
1343 {
1344         guint32 count;
1345         proto_item *item=NULL;
1346         proto_tree *tree=NULL;
1347         int old_offset=offset;
1348
1349         if(parent_tree){
1350                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
1351                         "USER_GROUP_ARRAY");
1352                 tree = proto_item_add_subtree(item, ett_samr_user_group_array);
1353         }
1354
1355         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1356                         hf_samr_count, &count);
1357         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1358                         samr_dissect_USER_GROUP_ARRAY_groups, NDR_POINTER_UNIQUE,
1359                         "USER_GROUP_ARRAY", -1);
1360
1361         proto_item_set_len(item, offset-old_offset);
1362         return offset;
1363 }
1364
1365 static int
1366 samr_dissect_USER_GROUP_ARRAY_ptr(tvbuff_t *tvb, int offset,
1367                         packet_info *pinfo, proto_tree *tree,
1368                         char *drep)
1369 {
1370         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1371                         samr_dissect_USER_GROUP_ARRAY, NDR_POINTER_UNIQUE,
1372                         "USER_GROUP_ARRAY", -1);
1373         return offset;
1374 }
1375
1376 static int
1377 samr_dissect_get_groups_for_user_rqst(tvbuff_t *tvb, int offset,
1378                                       packet_info *pinfo, proto_tree *tree,
1379                                       char *drep)
1380 {
1381         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1382                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1383
1384         return offset;
1385 }
1386
1387 static int
1388 samr_dissect_get_groups_for_user_reply(tvbuff_t *tvb, int offset,
1389                                        packet_info *pinfo, proto_tree *tree,
1390                                        char *drep)
1391 {
1392         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1393                         samr_dissect_USER_GROUP_ARRAY_ptr, NDR_POINTER_REF,
1394                         "USER_GROUP_ARRAY:", -1);
1395
1396         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1397                                   hf_samr_rc, NULL);
1398         return offset;
1399 }
1400
1401
1402 static void append_sid_col_info(packet_info *pinfo, proto_tree *tree _U_, 
1403                                 proto_item *item _U_, tvbuff_t *tvb _U_, 
1404                                 int start_offset _U_, int end_offset _U_, 
1405                                 void *callback_args _U_)
1406 {
1407         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1408         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1409         char *sid_str = dcv->private_data;
1410
1411         if (sid_str && check_col(pinfo->cinfo, COL_INFO))
1412                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", sid_str);
1413 }
1414
1415 static int
1416 samr_dissect_open_domain_rqst(tvbuff_t *tvb, int offset,
1417                               packet_info *pinfo, proto_tree *tree,
1418                               char *drep)
1419 {
1420         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1421                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1422
1423         offset = dissect_nt_access_mask(
1424                 tvb, offset, pinfo, tree, drep, hf_samr_access,
1425                 &samr_domain_access_mask_info);
1426
1427         offset = dissect_ndr_pointer_cb(
1428                 tvb, offset, pinfo, tree, drep, dissect_ndr_nt_SID_no_hf, 
1429                 NDR_POINTER_REF, "SID:", -1, append_sid_col_info, NULL);
1430
1431         return offset;
1432 }
1433
1434 static int
1435 samr_dissect_open_domain_reply(tvbuff_t *tvb, int offset,
1436                              packet_info *pinfo, proto_tree *tree,
1437                              char *drep)
1438 {
1439         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1440         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1441         e_ctx_hnd policy_hnd;
1442         proto_item *hnd_item;
1443         guint32 status;
1444         char *pol_name, *sid_str = (char *)dcv->private_data;
1445
1446         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1447                                        hf_samr_hnd, &policy_hnd, &hnd_item,
1448                                        TRUE, FALSE);
1449
1450         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1451                                   hf_samr_rc, &status);
1452
1453         if (status == 0) {
1454                 if (sid_str) {
1455                         pol_name = g_strdup_printf("OpenDomain(%s)", sid_str);
1456                 } else {
1457                         pol_name = g_strdup("OpenDomain handle");
1458                 }
1459
1460                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
1461
1462                 if (hnd_item != NULL)
1463                         proto_item_append_text(hnd_item, ": %s", pol_name);
1464
1465                 g_free(pol_name);
1466         }
1467
1468         return offset;
1469 }
1470
1471 #if 0
1472 static int
1473 samr_dissect_context_handle_SID(tvbuff_t *tvb, int offset,
1474                              packet_info *pinfo, proto_tree *tree,
1475                              char *drep)
1476 {
1477         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1478                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1479
1480         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1481                         dissect_ndr_nt_SID_no_hf, NDR_POINTER_REF,
1482                         "SID pointer", -1);
1483
1484         return offset;
1485 }
1486 #endif
1487
1488 static int
1489 samr_dissect_add_member_to_group_rqst(tvbuff_t *tvb, int offset,
1490                                       packet_info *pinfo, proto_tree *tree,
1491                                       char *drep)
1492 {
1493         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1494                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1495
1496         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1497                                      hf_samr_group, NULL);
1498
1499         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1500                                      hf_samr_rid, NULL);
1501
1502         return offset;
1503 }
1504
1505 static int
1506 samr_dissect_add_member_to_group_reply(tvbuff_t *tvb, int offset,
1507                                        packet_info *pinfo, proto_tree *tree,
1508                                        char *drep)
1509 {
1510         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1511                                   hf_samr_rc, NULL);
1512
1513         return offset;
1514 }
1515
1516 static int
1517 samr_dissect_unknown_3c_rqst(tvbuff_t *tvb, int offset,
1518                              packet_info *pinfo, proto_tree *tree,
1519                              char *drep)
1520 {
1521         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1522                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1523
1524         return offset;
1525 }
1526
1527 static int
1528 samr_dissect_unknown_3c_reply(tvbuff_t *tvb, int offset,
1529                              packet_info *pinfo, proto_tree *tree,
1530                              char *drep)
1531 {
1532         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1533                         samr_dissect_pointer_short, NDR_POINTER_REF,
1534                         "unknown short", hf_samr_unknown_short);
1535
1536         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1537                                   hf_samr_rc, NULL);
1538         return offset;
1539 }
1540
1541 static int
1542 samr_dissect_create_alias_in_domain_rqst(tvbuff_t *tvb, int offset,
1543                                          packet_info *pinfo, proto_tree *tree,
1544                                          char *drep)
1545 {
1546         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1547                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1548
1549         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1550                         dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
1551                         "Account Name", hf_samr_acct_name);
1552
1553         offset = dissect_nt_access_mask(
1554                 tvb, offset, pinfo, tree, drep, hf_samr_access,
1555                 &samr_alias_access_mask_info);
1556
1557         return offset;
1558 }
1559
1560 static int
1561 samr_dissect_create_alias_in_domain_reply(tvbuff_t *tvb, int offset,
1562                              packet_info *pinfo, proto_tree *tree,
1563                              char *drep)
1564 {
1565         e_ctx_hnd policy_hnd;
1566         proto_item *hnd_item;
1567         guint32 status;
1568
1569         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1570                                        hf_samr_hnd, &policy_hnd, &hnd_item,
1571                                        TRUE, FALSE);
1572
1573         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1574                                      hf_samr_rid, NULL);
1575
1576         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1577                                   hf_samr_rc, &status);
1578
1579         if (status == 0) {
1580                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo,
1581                                           "CreateAlias handle");
1582
1583                 if (hnd_item != NULL)
1584                         proto_item_append_text(hnd_item, ": CreateAlias handle");
1585         }
1586         return offset;
1587 }
1588
1589 static int
1590 samr_dissect_query_information_alias_rqst(tvbuff_t *tvb, int offset,
1591                                           packet_info *pinfo,
1592                                           proto_tree *tree, char *drep)
1593 {
1594         guint16 level;
1595
1596         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1597                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1598
1599         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
1600                         hf_samr_level, &level);
1601
1602         if (check_col(pinfo->cinfo, COL_INFO))
1603                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1604
1605         return offset;
1606 }
1607
1608 static int
1609 samr_dissect_ALIAS_INFO_1 (tvbuff_t *tvb, int offset,
1610                              packet_info *pinfo, proto_tree *tree,
1611                              char *drep)
1612 {
1613         offset = dissect_ndr_counted_string(tvb, offset, pinfo,
1614                 tree, drep, hf_samr_acct_name, 0);
1615         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1616                                      hf_samr_rid, NULL);
1617         offset = dissect_ndr_counted_string(tvb, offset, pinfo,
1618                 tree, drep, hf_samr_acct_desc, 0);
1619         return offset;
1620 }
1621
1622 static int
1623 samr_dissect_ALIAS_INFO(tvbuff_t *tvb, int offset,
1624                         packet_info *pinfo, proto_tree *parent_tree,
1625                         char *drep)
1626 {
1627         proto_item *item=NULL;
1628         proto_tree *tree=NULL;
1629         int old_offset=offset;
1630         guint16 level;
1631
1632         if(parent_tree){
1633                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
1634                         "ALIAS_INFO:");
1635                 tree = proto_item_add_subtree(item, ett_samr_alias_info);
1636         }
1637
1638         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
1639                                      hf_samr_level, &level);
1640         switch(level){
1641         case 1:
1642                 offset = samr_dissect_ALIAS_INFO_1(
1643                                 tvb, offset, pinfo, tree, drep);
1644                 break;
1645         case 2:
1646                 offset = dissect_ndr_counted_string(tvb, offset, pinfo,
1647                         tree, drep, hf_samr_acct_name, 0);
1648                 break;
1649         case 3:
1650                 offset = dissect_ndr_counted_string(tvb, offset, pinfo,
1651                         tree, drep, hf_samr_acct_desc, 0);
1652                 break;
1653         }
1654
1655         proto_item_set_len(item, offset-old_offset);
1656         return offset;
1657 }
1658
1659 static int
1660 samr_dissect_ALIAS_INFO_ptr(tvbuff_t *tvb, int offset,
1661                         packet_info *pinfo, proto_tree *tree,
1662                         char *drep)
1663 {
1664         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1665                         samr_dissect_ALIAS_INFO, NDR_POINTER_UNIQUE,
1666                         "ALIAS_INFO", -1);
1667         return offset;
1668 }
1669
1670 static int
1671 samr_dissect_query_information_alias_reply(tvbuff_t *tvb, int offset,
1672                                            packet_info *pinfo,
1673                                            proto_tree *tree, char *drep)
1674 {
1675         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1676                         samr_dissect_ALIAS_INFO_ptr, NDR_POINTER_REF,
1677                         "ALIAS_INFO:", -1);
1678
1679         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1680                                   hf_samr_rc, NULL);
1681
1682         return offset;
1683 }
1684
1685 static int
1686 samr_dissect_set_information_alias_rqst(tvbuff_t *tvb, int offset,
1687                              packet_info *pinfo, proto_tree *tree,
1688                              char *drep)
1689 {
1690         guint16 level;
1691
1692         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1693                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1694
1695         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
1696                                      hf_samr_level, &level);
1697
1698         if (check_col(pinfo->cinfo, COL_INFO))
1699                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1700
1701         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1702                         samr_dissect_ALIAS_INFO, NDR_POINTER_REF,
1703                         "ALIAS_INFO:", -1);
1704         return offset;
1705 }
1706
1707 static int
1708 samr_dissect_set_information_alias_reply(tvbuff_t *tvb, int offset,
1709                                          packet_info *pinfo, proto_tree *tree,
1710                                          char *drep)
1711 {
1712         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1713                         samr_dissect_ALIAS_INFO_ptr, NDR_POINTER_REF,
1714                         "ALIAS_INFO", -1);
1715
1716         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
1717                                   hf_samr_rc, NULL);
1718         return offset;
1719 }
1720
1721 static int
1722 samr_dissect_CRYPT_PASSWORD(tvbuff_t *tvb, int offset,
1723                         packet_info *pinfo _U_, proto_tree *tree,
1724                         char *drep _U_)
1725 {
1726         dcerpc_info *di;
1727
1728         di=pinfo->private_data;
1729         if(di->conformant_run){
1730                 /* just a run to handle conformant arrays, no scalars to dissect */
1731                 return offset;
1732         }
1733
1734         proto_tree_add_item(tree, hf_samr_crypt_password, tvb, offset, 516,
1735                 TRUE);
1736         offset += 516;
1737         return offset;
1738 }
1739
1740 static int
1741 samr_dissect_CRYPT_HASH(tvbuff_t *tvb, int offset,
1742                         packet_info *pinfo _U_, proto_tree *tree,
1743                         char *drep _U_)
1744 {
1745         dcerpc_info *di;
1746
1747         di=pinfo->private_data;
1748         if(di->conformant_run){
1749                 /* just a run to handle conformant arrays, no scalars to dissect */
1750                 return offset;
1751         }
1752
1753         proto_tree_add_item(tree, hf_samr_crypt_hash, tvb, offset, 16,
1754                 TRUE);
1755         offset += 16;
1756         return offset;
1757 }
1758
1759 #define NT_BLOCK_SIZE 516
1760
1761 static void
1762 samr_dissect_decrypted_NT_PASSCHANGE_BLOCK(tvbuff_t *tvb, int offset,
1763                                  packet_info *pinfo _U_, proto_tree *tree,
1764                                  char *drep _U_)
1765 {
1766   guint32 new_password_len = 0;
1767   guint32 pseudorandom_len = 0;
1768   const char *printable_password;
1769   guint16 bc;
1770   int result_length;
1771
1772   /* The length of the new password is represented in the last four 
1773      octets of the decrypted buffer.  Since the password length cannot
1774      exceed 512, we can check the contents of those bytes to determine 
1775      if decryption was successful.  If the decrypted contents of those 
1776      four bytes is less than 512, then there is a 99% chance that
1777      we decrypted the buffer successfully.  Of course, this isn't good
1778      enough for a security application, (NT uses the "verifier" field 
1779      to come to the same conclusion), but it should be good enough for
1780      our dissector. */
1781   
1782   new_password_len = tvb_get_letohl(tvb, 512);  
1783
1784   if (new_password_len <= 512)
1785     {
1786       /* Decryption successful */
1787       proto_tree_add_text (tree, tvb, offset, -1,
1788                            "Decryption of NT Password Encrypted block successful");
1789
1790       /* Whatever is before the password is pseudorandom data.  We calculate 
1791          the length by examining the password length (at the end), and working
1792          backward */    
1793       pseudorandom_len = NT_BLOCK_SIZE - new_password_len - 4;
1794
1795       /* Pseudorandom data padding up to password */
1796       proto_tree_add_item(tree, hf_samr_nt_passchange_block_pseudorandom, 
1797                           tvb, offset, pseudorandom_len, TRUE);
1798       offset += pseudorandom_len;
1799
1800       /* The new password itself */
1801       bc = new_password_len;
1802       printable_password = get_unicode_or_ascii_string(tvb, &offset,
1803                                                        TRUE,
1804                                                        &result_length,
1805                                                        FALSE, TRUE, &bc);
1806       proto_tree_add_string(tree, hf_samr_nt_passchange_block_newpass,
1807                             tvb, offset, result_length, 
1808                             printable_password);
1809       offset += new_password_len;
1810
1811       /* Length of password */
1812       proto_tree_add_item(tree, hf_samr_nt_passchange_block_newpass_len,
1813                           tvb, offset, 4, TRUE);
1814     }
1815   else
1816     {
1817       /* Decryption failure.  Just show the encrypted block */
1818       proto_tree_add_text (tree, tvb, offset, -1,
1819                            "Decryption of NT Passchange block failed");
1820       
1821       proto_tree_add_item(tree, hf_samr_nt_passchange_block_decrypted, tvb,
1822                           offset, NT_BLOCK_SIZE, TRUE);
1823     }
1824 }
1825
1826 static int
1827 samr_dissect_NT_PASSCHANGE_BLOCK(tvbuff_t *tvb, int offset,
1828                                  packet_info *pinfo _U_, proto_tree *tree,
1829                                  char *drep _U_)
1830 {
1831         dcerpc_info *di;
1832         size_t password_len;
1833         unsigned char *password_unicode;
1834         size_t password_len_unicode;
1835         unsigned char password_md4_hash[16];
1836         guint8 *block;
1837         tvbuff_t *decr_tvb; /* Used to store decrypted buffer */
1838         rc4_state_struct rc4_state;
1839         guint i;
1840         
1841         /* This implements the the algorithm discussed in lkcl -"DCE/RPC 
1842            over SMB" page 257.  Note that this code does not properly support
1843            Unicode. */
1844
1845         di=pinfo->private_data;
1846         if(di->conformant_run){
1847                 /* just a run to handle conformant arrays, no scalars to dissect */
1848                 return offset;
1849         }
1850
1851         /* Put in a protocol tree entry for the encrypted block. */
1852         proto_tree_add_text(tree, tvb, offset, NT_BLOCK_SIZE,
1853             "Encrypted NT Password Block");
1854
1855         if (nt_password[0] != '\0') {
1856                 /* We have an NT password, so we can decrypt the password
1857                    change block. */
1858
1859                 /* Convert the password provided in the Ethereal GUI to Unicode 
1860                    (UCS-2).  Since the input is always ASCII, we can just fake
1861                    it and pad every other byte with a NUL.  If we ever support
1862                    UTF-8 in the GUI, we would have to perform a real UTF-8 to
1863                    UCS-2 conversion */
1864                 password_len = strlen(nt_password);
1865                 password_len_unicode = password_len*2;
1866                 password_unicode = g_malloc(password_len_unicode);
1867                 for (i = 0; i < password_len; i++) {
1868                         password_unicode[i*2] = nt_password[i];
1869                         password_unicode[i*2+1] = 0;
1870                 }
1871
1872                 /* Run MD4 against the resulting Unicode password.  This will
1873                    be used to perform RC4 decryption on the password change
1874                    block.  Then free the Unicode password, as we're done
1875                    with it. */
1876                 crypt_md4(password_md4_hash, password_unicode,
1877                     password_len_unicode);
1878                 g_free(password_unicode);
1879         
1880                 /* Copy the block into a temporary buffer so we can decrypt
1881                    it */
1882                 block = g_malloc(NT_BLOCK_SIZE);
1883                 memset(block, 0, NT_BLOCK_SIZE);
1884                 tvb_memcpy(tvb, block, offset, NT_BLOCK_SIZE);
1885         
1886                 /* RC4 decrypt the block with the old NT password hash */
1887                 crypt_rc4_init(&rc4_state, password_md4_hash, 16);
1888                 crypt_rc4(&rc4_state, block, NT_BLOCK_SIZE);
1889
1890                 /* Show the decrypted buffer in a new window */
1891                 decr_tvb = tvb_new_real_data(block, NT_BLOCK_SIZE,
1892                     NT_BLOCK_SIZE);
1893                 tvb_set_free_cb(decr_tvb, g_free);
1894                 tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
1895                 add_new_data_source(pinfo, decr_tvb,
1896                     "Decrypted NT Password Block");
1897
1898                 /* Dissect the decrypted block */
1899                 samr_dissect_decrypted_NT_PASSCHANGE_BLOCK(decr_tvb, 0, pinfo,
1900                                                            tree, drep);
1901         }
1902         offset += NT_BLOCK_SIZE;
1903         return offset;
1904 }
1905
1906 static int
1907 samr_dissect_LM_PASSCHANGE_BLOCK(tvbuff_t *tvb, int offset,
1908                                  packet_info *pinfo _U_, proto_tree *tree,
1909                                  char *drep _U_)
1910 {
1911         dcerpc_info *di;
1912
1913         /* Right now, this just dumps the output.  In the long term, we can use
1914            the algorithm discussed in lkcl -"DCE/RPC over SMB" page 257 to
1915            actually decrypt the block */
1916
1917         di=pinfo->private_data;
1918         if(di->conformant_run){
1919                 /* just a run to handle conformant arrays, no scalars to dissect */
1920                 return offset;
1921         }
1922
1923         proto_tree_add_item(tree, hf_samr_lm_passchange_block, tvb, offset, 
1924                             516, TRUE);
1925         offset += 516;
1926         return offset;
1927 }
1928
1929 static int
1930 samr_dissect_LM_VERIFIER(tvbuff_t *tvb, int offset,
1931                          packet_info *pinfo _U_, proto_tree *tree,
1932                          char *drep _U_)
1933 {
1934         dcerpc_info *di;
1935
1936         /* Right now, this just dumps the output.  In the long term, we can use
1937            the algorithm discussed in lkcl -"DCE/RPC over SMB" page 257 to
1938            actually validate the verifier */
1939
1940         di=pinfo->private_data;
1941         if(di->conformant_run){
1942                 /* just a run to handle conformant arrays, no scalars to dissect */
1943                 return offset;
1944         }
1945
1946         proto_tree_add_item(tree, hf_samr_lm_verifier, tvb, offset, 16,
1947                 TRUE);
1948         offset += 16;
1949         return offset;
1950 }
1951
1952
1953 static int
1954 samr_dissect_NT_VERIFIER(tvbuff_t *tvb, int offset,
1955                          packet_info *pinfo _U_, proto_tree *tree,
1956                          char *drep _U_)
1957 {
1958         dcerpc_info *di;
1959
1960         /* Right now, this just dumps the output.  In the long term, we can use
1961            the algorithm discussed in lkcl -"DCE/RPC over SMB" page 257 to
1962            actually validate the verifier */
1963
1964         di=pinfo->private_data;
1965         if(di->conformant_run){
1966                 /* just a run to handle conformant arrays, no scalars to dissect */
1967                 return offset;
1968         }
1969
1970         proto_tree_add_item(tree, hf_samr_nt_verifier, tvb, offset, 16,
1971                 TRUE);
1972         offset += 16;
1973         return offset;
1974 }
1975
1976
1977 static int
1978 samr_dissect_oem_change_password_user2_rqst(tvbuff_t *tvb, int offset,
1979                                             packet_info *pinfo,
1980                                             proto_tree *tree, char *drep)
1981 {
1982         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
1983                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
1984
1985         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1986                         samr_dissect_pointer_STRING, NDR_POINTER_UNIQUE,
1987                         "Server", hf_samr_server);
1988
1989         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1990                         samr_dissect_pointer_STRING, NDR_POINTER_REF,
1991                         "Account Name", hf_samr_acct_name);
1992
1993         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1994                         samr_dissect_CRYPT_PASSWORD, NDR_POINTER_UNIQUE,
1995                         "Password", -1);
1996
1997         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1998                         samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
1999                         "Hash", -1);
2000         return offset;
2001 }
2002
2003 static int
2004 samr_dissect_oem_change_password_user2_reply(tvbuff_t *tvb, int offset,
2005                                              packet_info *pinfo,
2006                                              proto_tree *tree, char *drep)
2007 {
2008         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2009                                   hf_samr_rc, NULL);
2010
2011         return offset;
2012 }
2013
2014 static int
2015 samr_dissect_unicode_change_password_user2_rqst(tvbuff_t *tvb, int offset,
2016                                                 packet_info *pinfo,
2017                                                 proto_tree *tree, char *drep)
2018 {
2019         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2020                         samr_dissect_PASSWORD_INFO, NDR_POINTER_REF,
2021                         "PASSWORD_INFO:", -1);
2022
2023         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
2024                         NDR_POINTER_UNIQUE, "Server", hf_samr_server, 0);
2025
2026         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2027                         dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
2028                         "Account Name", hf_samr_acct_name);
2029
2030         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2031                         samr_dissect_NT_PASSCHANGE_BLOCK, NDR_POINTER_UNIQUE,
2032                         "New NT Password Encrypted Block", -1);
2033         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2034                         samr_dissect_NT_VERIFIER, NDR_POINTER_UNIQUE,
2035                         "NT Password Verifier", -1);
2036         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
2037                                      hf_samr_lm_change, NULL);
2038         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2039                         samr_dissect_LM_PASSCHANGE_BLOCK, NDR_POINTER_UNIQUE,
2040                         "New Lan Manager Password Encrypted Block", -1);
2041         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2042                         samr_dissect_LM_VERIFIER, NDR_POINTER_UNIQUE,
2043                         "Lan Manager Password Verifier", -1);
2044         return offset;
2045 }
2046
2047 static int
2048 samr_dissect_unicode_change_password_user2_reply(tvbuff_t *tvb, int offset,
2049                                                  packet_info *pinfo,
2050                                                  proto_tree *tree, char *drep)
2051 {
2052         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2053                                   hf_samr_rc, NULL);
2054
2055         return offset;
2056 }
2057
2058 static int
2059 samr_dissect_unknown_3b_rqst(tvbuff_t *tvb, int offset,
2060                              packet_info *pinfo, proto_tree *tree,
2061                              char *drep)
2062 {
2063         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2064                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
2065
2066         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
2067                                      hf_samr_unknown_short, NULL);
2068         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2069                         dissect_ndr_counted_string_ptr, NDR_POINTER_UNIQUE,
2070                         "Unknown", hf_samr_unknown_string);
2071         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2072                         dissect_ndr_counted_string_ptr, NDR_POINTER_UNIQUE,
2073                         "Unknown", hf_samr_unknown_string);
2074         return offset;
2075 }
2076
2077 static int
2078 samr_dissect_unknown_3b_reply(tvbuff_t *tvb, int offset,
2079                               packet_info *pinfo, proto_tree *tree,
2080                               char *drep)
2081 {
2082         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2083                                   hf_samr_rc, NULL);
2084
2085         return offset;
2086 }
2087
2088 static int
2089 samr_dissect_create_user2_in_domain_rqst(tvbuff_t *tvb, int offset,
2090                                          packet_info *pinfo, proto_tree *tree,
2091                                          char *drep)
2092 {
2093         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2094                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
2095
2096         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2097                         dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
2098                         "Account Name", hf_samr_acct_name);
2099
2100         offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
2101
2102         offset = dissect_nt_access_mask(
2103                 tvb, offset, pinfo, tree, drep, hf_samr_access,
2104                 &samr_user_access_mask_info);
2105
2106         return offset;
2107 }
2108
2109 static int
2110 samr_dissect_create_user2_in_domain_reply(tvbuff_t *tvb, int offset,
2111                              packet_info *pinfo, proto_tree *tree,
2112                              char *drep)
2113 {
2114         e_ctx_hnd policy_hnd;
2115         proto_item *hnd_item;
2116         guint32 status;
2117
2118         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2119                                        hf_samr_hnd, &policy_hnd, &hnd_item,
2120                                        TRUE, FALSE);
2121
2122         offset = dissect_nt_access_mask(
2123                 tvb, offset, pinfo, tree, drep, hf_samr_access_granted,
2124                 &samr_user_access_mask_info);
2125
2126         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2127                                      hf_samr_rid, NULL);
2128
2129         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2130                                   hf_samr_rc, &status);
2131
2132         if (status == 0) {
2133                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo,
2134                                           "CreateUser2 handle");
2135
2136                 if (hnd_item != NULL)
2137                         proto_item_append_text(hnd_item, ": CreateUser2 handle");
2138         }
2139
2140         return offset;
2141 }
2142
2143 static int
2144 samr_dissect_get_display_enumeration_index2_rqst(tvbuff_t *tvb, int offset,
2145                                                  packet_info *pinfo,
2146                                                  proto_tree *tree, char *drep)
2147 {
2148         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2149                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
2150
2151         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
2152                                      hf_samr_level, NULL);
2153         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2154                         dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
2155                         "Account Name", hf_samr_acct_name);
2156         return offset;
2157 }
2158
2159 static int
2160 samr_dissect_get_display_enumeration_index2_reply(tvbuff_t *tvb, int offset,
2161                              packet_info *pinfo, proto_tree *tree,
2162                              char *drep)
2163 {
2164         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2165                                      hf_samr_index, NULL);
2166
2167         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2168                                   hf_samr_rc, NULL);
2169         return offset;
2170 }
2171
2172 static int
2173 samr_dissect_change_password_user_rqst(tvbuff_t *tvb, int offset,
2174                                        packet_info *pinfo, proto_tree *tree,
2175                                        char *drep)
2176 {
2177         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2178                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
2179
2180         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
2181                         hf_samr_unknown_char, NULL);
2182         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2183                         samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
2184                         "Hash", -1);
2185         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2186                         samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
2187                         "Hash", -1);
2188         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
2189                         hf_samr_unknown_char, NULL);
2190         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2191                         samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
2192                         "Hash", -1);
2193         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2194                         samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
2195                         "Hash", -1);
2196         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
2197                         hf_samr_unknown_char, NULL);
2198         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2199                         samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
2200                         "Hash", -1);
2201         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
2202                         hf_samr_unknown_char, NULL);
2203         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2204                         samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
2205                         "Hash", -1);
2206
2207         return offset;
2208 }
2209
2210 static int
2211 samr_dissect_change_password_user_reply(tvbuff_t *tvb, int offset,
2212                                         packet_info *pinfo, proto_tree *tree,
2213                                         char *drep)
2214 {
2215         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2216                                   hf_samr_rc, NULL);
2217
2218         return offset;
2219 }
2220
2221 static int
2222 samr_dissect_set_member_attributes_of_group_rqst(tvbuff_t *tvb, int offset,
2223                                                  packet_info *pinfo,
2224                                                  proto_tree *tree, char *drep)
2225 {
2226         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2227                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
2228
2229         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2230                                      hf_samr_attrib, NULL);
2231         return offset;
2232 }
2233
2234 static int
2235 samr_dissect_set_member_attributes_of_group_reply(tvbuff_t *tvb, int offset,
2236                              packet_info *pinfo, proto_tree *tree,
2237                              char *drep)
2238 {
2239         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2240                                   hf_samr_rc, NULL);
2241
2242         return offset;
2243 }
2244
2245 static int
2246 samr_dissect_GROUP_INFO_1 (tvbuff_t *tvb, int offset,
2247                              packet_info *pinfo, proto_tree *tree,
2248                              char *drep)
2249 {
2250         offset = dissect_ndr_counted_string(tvb, offset, pinfo,
2251                 tree, drep, hf_samr_acct_name, 0);
2252         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2253                                      hf_samr_rid, NULL);
2254         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2255                                         hf_samr_attrib, NULL);
2256         offset = dissect_ndr_counted_string(tvb, offset, pinfo,
2257                 tree, drep, hf_samr_acct_desc, 0);
2258         return offset;
2259 }
2260
2261 static int
2262 samr_dissect_GROUP_INFO(tvbuff_t *tvb, int offset,
2263                         packet_info *pinfo, proto_tree *parent_tree,
2264                         char *drep)
2265 {
2266         proto_item *item=NULL;
2267         proto_tree *tree=NULL;
2268         int old_offset=offset;
2269         guint16 level;
2270
2271         if(parent_tree){
2272                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2273                         "GROUP_INFO:");
2274                 tree = proto_item_add_subtree(item, ett_samr_group_info);
2275         }
2276
2277         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
2278                                      hf_samr_level, &level);
2279         switch(level){
2280         case 1:
2281                 offset = samr_dissect_GROUP_INFO_1(
2282                                 tvb, offset, pinfo, tree, drep);
2283                 break;
2284         case 2:
2285                 offset = dissect_ndr_counted_string(tvb, offset, pinfo,
2286                         tree, drep, hf_samr_acct_name, 0);
2287                 break;
2288         case 3:
2289                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2290                         hf_samr_attrib, NULL);
2291                 break;
2292         case 4:
2293                 offset = dissect_ndr_counted_string(tvb, offset, pinfo,
2294                         tree, drep, hf_samr_acct_desc, 0);
2295                 break;
2296         }
2297
2298         proto_item_set_len(item, offset-old_offset);
2299         return offset;
2300 }
2301
2302 static int
2303 samr_dissect_GROUP_INFO_ptr(tvbuff_t *tvb, int offset,
2304                         packet_info *pinfo, proto_tree *tree,
2305                         char *drep)
2306 {
2307         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2308                         samr_dissect_GROUP_INFO, NDR_POINTER_UNIQUE,
2309                         "GROUP_INFO", -1);
2310         return offset;
2311 }
2312
2313 static int
2314 samr_dissect_query_information_group_rqst(tvbuff_t *tvb, int offset,
2315                                           packet_info *pinfo,
2316                                           proto_tree *tree, char *drep)
2317 {
2318         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2319                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
2320
2321         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
2322                                      hf_samr_level, NULL);
2323
2324         return offset;
2325 }
2326
2327 static int
2328 samr_dissect_query_information_group_reply(tvbuff_t *tvb, int offset,
2329                         packet_info *pinfo, proto_tree *tree,
2330                         char *drep)
2331 {
2332         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2333                         samr_dissect_GROUP_INFO_ptr, NDR_POINTER_REF,
2334                         "GROUP_INFO", -1);
2335
2336         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2337                                   hf_samr_rc, NULL);
2338         return offset;
2339 }
2340
2341 static int
2342 samr_dissect_set_information_group_rqst(tvbuff_t *tvb, int offset,
2343                                         packet_info *pinfo, proto_tree *tree,
2344                                         char *drep)
2345 {
2346         guint16 level;
2347
2348         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2349                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
2350
2351         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
2352                                      hf_samr_level, &level);
2353
2354         if (check_col(pinfo->cinfo, COL_INFO))
2355                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
2356
2357         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2358                         samr_dissect_GROUP_INFO, NDR_POINTER_REF,
2359                         "GROUP_INFO", -1);
2360         return offset;
2361 }
2362
2363 static int
2364 samr_dissect_set_information_group_reply(tvbuff_t *tvb, int offset,
2365                              packet_info *pinfo, proto_tree *tree,
2366                              char *drep)
2367 {
2368         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2369                                   hf_samr_rc, NULL);
2370
2371         return offset;
2372 }
2373
2374 static int
2375 samr_dissect_get_domain_password_information_rqst(tvbuff_t *tvb, int offset,
2376                                                   packet_info *pinfo,
2377                                                   proto_tree *tree,
2378                                                   char *drep)
2379 {
2380         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2381                         samr_dissect_PASSWORD_INFO, NDR_POINTER_REF,
2382                         "PASSWORD_INFO:", -1);
2383
2384         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
2385                         NDR_POINTER_UNIQUE, "Domain", hf_samr_domain, 0);
2386
2387         return offset;
2388 }
2389
2390 static int
2391 samr_dissect_get_domain_password_information_reply(tvbuff_t *tvb, int offset,
2392                                                    packet_info *pinfo,
2393                                                    proto_tree *tree,
2394                                                    char *drep)
2395 {
2396         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2397                         samr_dissect_PASSWORD_INFO, NDR_POINTER_REF,
2398                         "PASSWORD_INFO:", -1);
2399
2400         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2401                                   hf_samr_rc, NULL);
2402
2403         return offset;
2404 }
2405
2406 static int
2407 samr_dissect_DOMAIN_INFO_1(tvbuff_t *tvb, int offset,
2408                              packet_info *pinfo, proto_tree *parent_tree,
2409                              char *drep)
2410 {
2411         proto_item *item=NULL;
2412         proto_tree *tree=NULL;
2413         int old_offset=offset;
2414
2415         ALIGN_TO_4_BYTES;  /* strcture starts with short, but is aligned for longs */
2416
2417         if(parent_tree){
2418                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2419                         "DOMAIN_INFO_1:");
2420                 tree = proto_item_add_subtree(item, ett_samr_domain_info_1);
2421         }
2422
2423         offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
2424                                         hf_samr_min_pwd_len, NULL);
2425         offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
2426                                         hf_samr_pwd_history_len, NULL);
2427         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
2428                                         hf_samr_unknown_long, NULL);
2429         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
2430                                         hf_samr_max_pwd_age);
2431         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
2432                                         hf_samr_min_pwd_age);
2433         proto_item_set_len(item, offset-old_offset);
2434         return offset;
2435 }
2436
2437 static int
2438 samr_dissect_DOMAIN_INFO_2(tvbuff_t *tvb, int offset,
2439                         packet_info *pinfo, proto_tree *parent_tree,
2440                         char *drep)
2441 {
2442         proto_item *item=NULL;
2443         proto_tree *tree=NULL;
2444         int old_offset=offset;
2445
2446         if(parent_tree){
2447                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2448                         "DOMAIN_INFO_2:");
2449                 tree = proto_item_add_subtree(item, ett_samr_domain_info_2);
2450         }
2451
2452         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
2453                         hf_samr_unknown_time);
2454         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
2455                         hf_samr_unknown_string, 0);
2456         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
2457                         hf_samr_domain, 0);
2458         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
2459                         hf_samr_controller, 0);
2460         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
2461                         hf_samr_unknown_time);
2462         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2463                         hf_samr_unknown_long, NULL);
2464         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2465                         hf_samr_unknown_long, NULL);
2466         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
2467                         hf_samr_unknown_char, NULL);
2468         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2469                         hf_samr_num_users, NULL);
2470         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2471                         hf_samr_num_groups, NULL);
2472         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2473                         hf_samr_num_aliases, NULL);
2474
2475         proto_item_set_len(item, offset-old_offset);
2476         return offset;
2477 }
2478
2479 static int
2480 samr_dissect_DOMAIN_INFO_8(tvbuff_t *tvb, int offset,
2481                              packet_info *pinfo, proto_tree *parent_tree,
2482                              char *drep)
2483 {
2484         proto_item *item=NULL;
2485         proto_tree *tree=NULL;
2486         int old_offset=offset;
2487
2488         if(parent_tree){
2489                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2490                         "DOMAIN_INFO_8:");
2491                 tree = proto_item_add_subtree(item, ett_samr_domain_info_8);
2492         }
2493
2494         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
2495                                         hf_samr_max_pwd_age);
2496         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
2497                                         hf_samr_min_pwd_age);
2498
2499         proto_item_set_len(item, offset-old_offset);
2500         return offset;
2501 }
2502
2503 static int
2504 samr_dissect_REPLICATION_STATUS(tvbuff_t *tvb, int offset,
2505                         packet_info *pinfo, proto_tree *parent_tree,
2506                         char *drep)
2507 {
2508         proto_item *item=NULL;
2509         proto_tree *tree=NULL;
2510         int old_offset=offset;
2511
2512         if(parent_tree){
2513                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2514                         "REPLICATION_STATUS:");
2515                 tree = proto_item_add_subtree(item, ett_samr_replication_status);
2516         }
2517
2518         offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
2519                         hf_samr_unknown_hyper, NULL);
2520         offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
2521                         hf_samr_unknown_hyper, NULL);
2522         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
2523                         hf_samr_unknown_short, NULL);
2524
2525         proto_item_set_len(item, offset-old_offset);
2526         return offset;
2527 }
2528
2529 static int
2530 samr_dissect_DOMAIN_INFO_11(tvbuff_t *tvb, int offset,
2531                              packet_info *pinfo, proto_tree *parent_tree,
2532                              char *drep)
2533 {
2534         proto_item *item=NULL;
2535         proto_tree *tree=NULL;
2536         int old_offset=offset;
2537
2538         if(parent_tree){
2539                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2540                         "DOMAIN_INFO_11:");
2541                 tree = proto_item_add_subtree(item, ett_samr_domain_info_11);
2542         }
2543
2544         offset = samr_dissect_DOMAIN_INFO_2(
2545                         tvb, offset, pinfo, tree, drep);
2546         offset = samr_dissect_REPLICATION_STATUS(
2547                         tvb, offset, pinfo, tree, drep);
2548
2549         proto_item_set_len(item, offset-old_offset);
2550         return offset;
2551 }
2552
2553 static int
2554 samr_dissect_DOMAIN_INFO_13(tvbuff_t *tvb, int offset,
2555                              packet_info *pinfo, proto_tree *parent_tree,
2556                              char *drep)
2557 {
2558         proto_item *item=NULL;
2559         proto_tree *tree=NULL;
2560         int old_offset=offset;
2561
2562         if(parent_tree){
2563                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2564                         "DOMAIN_INFO_13:");
2565                 tree = proto_item_add_subtree(item, ett_samr_domain_info_13);
2566         }
2567
2568         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
2569                                         hf_samr_unknown_time);
2570         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
2571                                         hf_samr_unknown_time);
2572         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
2573                                         hf_samr_unknown_time);
2574
2575         proto_item_set_len(item, offset-old_offset);
2576         return offset;
2577 }
2578
2579
2580 static int
2581 samr_dissect_DOMAIN_INFO(tvbuff_t *tvb, int offset,
2582                         packet_info *pinfo, proto_tree *parent_tree,
2583                         char *drep)
2584 {
2585         proto_item *item=NULL;
2586         proto_tree *tree=NULL;
2587         int old_offset=offset;
2588         guint16 level;
2589
2590         if(parent_tree){
2591                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2592                         "DOMAIN_INFO:");
2593                 tree = proto_item_add_subtree(item, ett_samr_domain_info);
2594         }
2595
2596         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
2597                                      hf_samr_level, &level);
2598
2599         ALIGN_TO_4_BYTES;  /* all union arms aligned to 4 bytes, case 7 and 9 need this  */
2600         switch(level){
2601         case 1:
2602                 offset = samr_dissect_DOMAIN_INFO_1(
2603                                 tvb, offset, pinfo, tree, drep);
2604                 break;
2605         case 2:
2606                 offset = samr_dissect_DOMAIN_INFO_2(
2607                                 tvb, offset, pinfo, tree, drep);
2608                 break;
2609
2610         case 3:
2611                 offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
2612                                 hf_samr_unknown_time);
2613                 break;
2614         case 4:
2615                 offset = dissect_ndr_counted_string(tvb, offset, pinfo,
2616                         tree, drep, hf_samr_unknown_string, 0);
2617                 break;
2618
2619         case 5:
2620                 offset = dissect_ndr_counted_string(tvb, offset, pinfo,
2621                         tree, drep, hf_samr_domain, 0);
2622                 break;
2623
2624         case 6:
2625                 offset = dissect_ndr_counted_string(tvb, offset, pinfo,
2626                         tree, drep, hf_samr_controller, 0);
2627                 break;
2628
2629         case 7:
2630                 offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
2631                         hf_samr_unknown_short, NULL);
2632                 break;
2633         case 8:
2634                 offset = samr_dissect_DOMAIN_INFO_8(
2635                                 tvb, offset, pinfo, tree, drep);
2636                 break;
2637         case 9:
2638                 offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
2639                         hf_samr_unknown_short, NULL);
2640                 break;
2641         case 11:
2642                 offset = samr_dissect_DOMAIN_INFO_11(
2643                                 tvb, offset, pinfo, tree, drep);
2644                 break;
2645         case 12:
2646                 offset = samr_dissect_REPLICATION_STATUS(
2647                                 tvb, offset, pinfo, tree, drep);
2648                 break;
2649         case 13:
2650                 offset = samr_dissect_DOMAIN_INFO_13(
2651                                 tvb, offset, pinfo, tree, drep);
2652                 break;
2653         }
2654
2655         proto_item_set_len(item, offset-old_offset);
2656         return offset;
2657 }
2658
2659 static int
2660 samr_dissect_set_information_domain_rqst(tvbuff_t *tvb, int offset,
2661                                          packet_info *pinfo, proto_tree *tree,
2662                                          char *drep)
2663 {
2664         guint16 level;
2665
2666         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2667                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
2668
2669         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
2670                                      hf_samr_level, &level);
2671
2672         if (check_col(pinfo->cinfo, COL_INFO))
2673                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
2674
2675         offset = samr_dissect_DOMAIN_INFO(tvb, offset, pinfo, tree, drep);
2676
2677         return offset;
2678 }
2679
2680 static int
2681 samr_dissect_set_information_domain_reply(tvbuff_t *tvb, int offset,
2682                                           packet_info *pinfo,
2683                                           proto_tree *tree, char *drep)
2684 {
2685         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2686                                   hf_samr_rc, NULL);
2687
2688         return offset;
2689 }
2690
2691 static int
2692 samr_dissect_lookup_domain_rqst(tvbuff_t *tvb, int offset,
2693                                 packet_info *pinfo, proto_tree *tree,
2694                                 char *drep)
2695 {
2696         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2697                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
2698
2699         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2700                         dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
2701                         "Domain", hf_samr_domain);
2702
2703         return offset;
2704 }
2705
2706 static int
2707 samr_dissect_lookup_domain_reply(tvbuff_t *tvb, int offset,
2708                              packet_info *pinfo, proto_tree *tree,
2709                              char *drep)
2710 {
2711         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2712                         dissect_ndr_nt_SID_no_hf, NDR_POINTER_UNIQUE,
2713                         "SID pointer", -1);
2714
2715         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2716                                   hf_samr_rc, NULL);
2717         return offset;
2718 }
2719
2720 int
2721 dissect_ndr_nt_PSID(tvbuff_t *tvb, int offset,
2722                              packet_info *pinfo, proto_tree *parent_tree,
2723                              char *drep, int hf_sid)
2724 {
2725         proto_item *item=NULL;
2726         proto_tree *tree=NULL;
2727         int old_offset=offset;
2728
2729         if(parent_tree){
2730                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2731                         "SID pointer:");
2732                 tree = proto_item_add_subtree(item, ett_samr_sid_pointer);
2733         }
2734
2735         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2736                         dissect_ndr_nt_SID_hf_through_ptr, NDR_POINTER_UNIQUE,
2737                         "SID pointer", hf_sid);
2738
2739         proto_item_set_len(item, offset-old_offset);
2740         return offset;
2741 }
2742 static int
2743 dissect_ndr_nt_PSID_no_hf(tvbuff_t *tvb, int offset,
2744                              packet_info *pinfo, proto_tree *parent_tree,
2745                              char *drep)
2746 {
2747         offset=dissect_ndr_nt_PSID(tvb, offset, pinfo, parent_tree, drep, -1);
2748         return offset;
2749 }
2750
2751 static int
2752 dissect_ndr_nt_PSID_ARRAY_sids (tvbuff_t *tvb, int offset,
2753                              packet_info *pinfo, proto_tree *tree,
2754                              char *drep)
2755 {
2756         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
2757                         dissect_ndr_nt_PSID_no_hf);
2758
2759         return offset;
2760 }
2761
2762
2763 int
2764 dissect_ndr_nt_PSID_ARRAY(tvbuff_t *tvb, int offset,
2765                         packet_info *pinfo, proto_tree *parent_tree,
2766                         char *drep)
2767 {
2768         guint32 count;
2769         proto_item *item=NULL;
2770         proto_tree *tree=NULL;
2771         int old_offset=offset;
2772
2773         if(parent_tree){
2774                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2775                         "SID array:");
2776                 tree = proto_item_add_subtree(item, ett_samr_sid_array);
2777         }
2778
2779         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2780                         hf_samr_count, &count);
2781         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2782                         dissect_ndr_nt_PSID_ARRAY_sids, NDR_POINTER_UNIQUE,
2783                         "PSID_ARRAY", -1);
2784
2785         proto_item_set_len(item, offset-old_offset);
2786         return offset;
2787 }
2788
2789 /* called from NETLOGON but placed here since where are where the hf_fields are defined */
2790 int
2791 dissect_ndr_nt_SID_AND_ATTRIBUTES(tvbuff_t *tvb, int offset,
2792                         packet_info *pinfo, proto_tree *parent_tree,
2793                         char *drep)
2794 {
2795         proto_item *item=NULL;
2796         proto_tree *tree=NULL;
2797
2798         if(parent_tree){
2799                 item = proto_tree_add_text(parent_tree, tvb, offset, 0,
2800                         "SID_AND_ATTRIBUTES:");
2801                 tree = proto_item_add_subtree(item, ett_samr_sid_and_attributes);
2802         }
2803
2804         offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep, -1);
2805
2806         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2807                                      hf_samr_attrib, NULL);
2808
2809         return offset;
2810 }
2811
2812 int
2813 dissect_ndr_nt_SID_AND_ATTRIBUTES_ARRAY(tvbuff_t *tvb, int offset,
2814                         packet_info *pinfo, proto_tree *parent_tree,
2815                         char *drep)
2816 {
2817         proto_item *item=NULL;
2818         proto_tree *tree=NULL;
2819         int old_offset=offset;
2820
2821         if(parent_tree){
2822                 item = proto_tree_add_text(parent_tree, tvb, offset, 0,
2823                         "SID_AND_ATTRIBUTES array:");
2824                 tree = proto_item_add_subtree(item, ett_samr_sid_and_attributes_array);
2825         }
2826
2827         /*offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2828           hf_samr_count, &count); */
2829         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
2830                         dissect_ndr_nt_SID_AND_ATTRIBUTES);
2831
2832         proto_item_set_len(item, offset-old_offset);
2833         return offset;
2834 }
2835
2836
2837 static int
2838 samr_dissect_index(tvbuff_t *tvb, int offset,
2839                              packet_info *pinfo, proto_tree *tree,
2840                              char *drep)
2841 {
2842         dcerpc_info *di;
2843
2844         di=pinfo->private_data;
2845
2846         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2847                         di->hf_index, NULL);
2848
2849         return offset;
2850 }
2851
2852
2853 static int
2854 samr_dissect_INDEX_ARRAY_value (tvbuff_t *tvb, int offset,
2855                              packet_info *pinfo, proto_tree *tree,
2856                              char *drep)
2857 {
2858         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
2859                         samr_dissect_index);
2860
2861         return offset;
2862 }
2863
2864 static char *
2865 plural_ending(const char *string)
2866 {
2867         size_t string_len;
2868
2869         string_len = strlen(string);
2870         if (string_len > 0 && string[string_len - 1] == 's') {
2871                 /* String ends with "s" - pluralize by adding "es" */
2872                 return "es";
2873         } else {
2874                 /* Field name doesn't end with "s" - pluralize by adding "s" */
2875                 return "s";
2876         }
2877 }
2878
2879 static int
2880 samr_dissect_INDEX_ARRAY(tvbuff_t *tvb, int offset,
2881                         packet_info *pinfo, proto_tree *parent_tree,
2882                         char *drep)
2883 {
2884         char *field_name;
2885         guint32 count;
2886         proto_item *item=NULL;
2887         proto_tree *tree=NULL;
2888         int old_offset=offset;
2889         dcerpc_info *di;
2890         char str[256];
2891
2892         di=pinfo->private_data;
2893
2894         field_name = proto_registrar_get_name(di->hf_index);
2895         snprintf(str, 255, "INDEX_ARRAY: %s%s:", field_name,
2896             plural_ending(field_name));
2897         if(parent_tree){
2898                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2899                         "%s", str);
2900                 tree = proto_item_add_subtree(item, ett_samr_index_array);
2901         }
2902
2903         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2904                         hf_samr_count, &count);
2905         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2906                         samr_dissect_INDEX_ARRAY_value, NDR_POINTER_UNIQUE,
2907                         str, di->hf_index);
2908
2909         proto_item_set_len(item, offset-old_offset);
2910         return offset;
2911 }
2912
2913 static int
2914 samr_dissect_get_alias_membership_rqst(tvbuff_t *tvb, int offset,
2915                                        packet_info *pinfo, proto_tree *tree,
2916                                        char *drep)
2917 {
2918         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
2919                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
2920
2921         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2922                         dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
2923                         "PSID_ARRAY:", -1);
2924
2925         return offset;
2926 }
2927
2928 static int
2929 samr_dissect_get_alias_membership_reply(tvbuff_t *tvb, int offset,
2930                              packet_info *pinfo, proto_tree *tree,
2931                              char *drep)
2932 {
2933         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
2934                         samr_dissect_INDEX_ARRAY, NDR_POINTER_REF,
2935                         "INDEX_ARRAY:", hf_samr_alias);
2936
2937         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
2938                                   hf_samr_rc, NULL);
2939
2940         return offset;
2941 }
2942
2943 static int
2944 samr_dissect_IDX_AND_NAME(tvbuff_t *tvb, int offset,
2945                              packet_info *pinfo, proto_tree *parent_tree,
2946                              char *drep)
2947 {
2948         proto_item *item=NULL;
2949         proto_tree *tree=NULL;
2950         int old_offset=offset;
2951         char str[256];
2952         dcerpc_info *di;
2953
2954         di=pinfo->private_data;
2955
2956         snprintf(str, 255, "IDX_AND_NAME: %s:",proto_registrar_get_name(di->hf_index));
2957         if(parent_tree){
2958                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2959                                 "%s",str);
2960                 tree = proto_item_add_subtree(item, ett_samr_idx_and_name);
2961         }
2962
2963         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
2964                         hf_samr_index, NULL);
2965         offset = dissect_ndr_counted_string(tvb, offset, pinfo,
2966                         tree, drep, di->hf_index, 4);
2967
2968         proto_item_set_len(item, offset-old_offset);
2969         return offset;
2970 }
2971
2972 static int
2973 samr_dissect_IDX_AND_NAME_entry (tvbuff_t *tvb, int offset,
2974                              packet_info *pinfo, proto_tree *tree,
2975                              char *drep)
2976 {
2977         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
2978                         samr_dissect_IDX_AND_NAME);
2979
2980         return offset;
2981 }
2982
2983
2984 static int
2985 samr_dissect_IDX_AND_NAME_ARRAY(tvbuff_t *tvb, int offset,
2986                         packet_info *pinfo, proto_tree *parent_tree,
2987                         char *drep)
2988 {
2989         char *field_name;
2990         guint32 count;
2991         proto_item *item=NULL;
2992         proto_tree *tree=NULL;
2993         int old_offset=offset;
2994         dcerpc_info *di;
2995         char str[256];
2996
2997         di=pinfo->private_data;
2998
2999         field_name = proto_registrar_get_name(di->hf_index);
3000
3001         if(parent_tree){
3002                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3003                         "IDX_AND_NAME_ARRAY: %s%s:", field_name,
3004                         plural_ending(field_name));
3005                 tree = proto_item_add_subtree(item, ett_samr_idx_and_name_array);
3006         }
3007
3008
3009         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
3010                         hf_samr_count, &count);
3011         snprintf(str, 255, "IDX_AND_NAME pointer: %s%s:", field_name,
3012             plural_ending(field_name));
3013         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3014                         samr_dissect_IDX_AND_NAME_entry, NDR_POINTER_UNIQUE,
3015                         str, di->hf_index);
3016
3017         proto_item_set_len(item, offset-old_offset);
3018         return offset;
3019 }
3020
3021 static int
3022 samr_dissect_IDX_AND_NAME_ARRAY_ptr(tvbuff_t *tvb, int offset,
3023                         packet_info *pinfo, proto_tree *tree,
3024                         char *drep)
3025 {
3026         char *field_name;
3027         char str[256];
3028         dcerpc_info *di;
3029
3030         di=pinfo->private_data;
3031
3032         field_name = proto_registrar_get_name(di->hf_index);
3033         snprintf(str, 255, "IDX_AND_NAME_ARRAY pointer: %s%s:", field_name,
3034             plural_ending(field_name));
3035         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3036                         samr_dissect_IDX_AND_NAME_ARRAY, NDR_POINTER_UNIQUE,
3037                         str, di->hf_index);
3038         return offset;
3039 }
3040
3041 static int
3042 samr_dissect_enum_domains_rqst(tvbuff_t *tvb, int offset,
3043                                packet_info *pinfo, proto_tree *tree,
3044                                char *drep)
3045 {
3046         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
3047                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
3048
3049         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3050                         samr_dissect_pointer_long, NDR_POINTER_REF,
3051                         "Resume Handle", hf_samr_resume_hnd);
3052
3053         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
3054                         hf_samr_pref_maxsize, NULL);
3055
3056         return offset;
3057 }
3058
3059 static int
3060 samr_dissect_enum_domains_reply(tvbuff_t *tvb, int offset,
3061                              packet_info *pinfo, proto_tree *tree,
3062                              char *drep)
3063 {
3064         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3065                         samr_dissect_pointer_long, NDR_POINTER_REF,
3066                         "Resume Handle:", hf_samr_resume_hnd);
3067
3068         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3069                         samr_dissect_IDX_AND_NAME_ARRAY_ptr, NDR_POINTER_REF,
3070                         "IDX_AND_NAME_ARRAY:", hf_samr_domain);
3071
3072         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3073                         samr_dissect_pointer_long, NDR_POINTER_REF,
3074                         "Entries:", hf_samr_entries);
3075
3076         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
3077                                   hf_samr_rc, NULL);
3078
3079         return offset;
3080 }
3081
3082 static int
3083 samr_dissect_enum_dom_groups_rqst(tvbuff_t *tvb, int offset,
3084                                   packet_info *pinfo, proto_tree *tree,
3085                                   char *drep)
3086 {
3087         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
3088                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
3089
3090         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3091                         samr_dissect_pointer_long, NDR_POINTER_REF,
3092                         "Resume Handle:", hf_samr_resume_hnd);
3093
3094         offset = dissect_ndr_nt_acct_ctrl(
3095                 tvb, offset, pinfo, tree, drep);
3096
3097         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
3098                         hf_samr_pref_maxsize, NULL);
3099
3100         return offset;
3101 }
3102
3103 static int
3104 samr_dissect_enum_dom_groups_reply(tvbuff_t *tvb, int offset,
3105                              packet_info *pinfo, proto_tree *tree,
3106                              char *drep)
3107 {
3108         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3109                         samr_dissect_pointer_long, NDR_POINTER_REF,
3110                         "Resume Handle:", hf_samr_resume_hnd);
3111
3112         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3113                         samr_dissect_IDX_AND_NAME_ARRAY_ptr, NDR_POINTER_REF,
3114                         "IDX_AND_NAME_ARRAY:", hf_samr_group_name);
3115
3116         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3117                         samr_dissect_pointer_long, NDR_POINTER_REF,
3118                         "Entries:", hf_samr_entries);
3119
3120         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
3121                                   hf_samr_rc, NULL);
3122
3123         return offset;
3124 }
3125
3126 static int
3127 samr_dissect_enum_dom_aliases_rqst(tvbuff_t *tvb, int offset,
3128                                  packet_info *pinfo, proto_tree *tree,
3129                                  char *drep)
3130 {
3131         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
3132                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
3133
3134         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3135                         samr_dissect_pointer_long, NDR_POINTER_REF,
3136                         "Resume Handle:", hf_samr_resume_hnd);
3137
3138         offset = dissect_ndr_nt_acct_ctrl(
3139                 tvb, offset, pinfo, tree, drep);
3140
3141         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
3142                         hf_samr_pref_maxsize, NULL);
3143
3144         return offset;
3145 }
3146
3147 static int
3148 samr_dissect_enum_dom_aliases_reply(tvbuff_t *tvb, int offset,
3149                              packet_info *pinfo, proto_tree *tree,
3150                              char *drep)
3151 {
3152         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3153                         samr_dissect_pointer_long, NDR_POINTER_REF,
3154                         "Resume Handle:", hf_samr_resume_hnd);
3155
3156         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3157                         samr_dissect_IDX_AND_NAME_ARRAY_ptr, NDR_POINTER_REF,
3158                         "IDX_AND_NAME_ARRAY:", hf_samr_alias_name);
3159
3160         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3161                         samr_dissect_pointer_long, NDR_POINTER_REF,
3162                         "Entries:", hf_samr_entries);
3163
3164         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
3165                                   hf_samr_rc, NULL);
3166
3167         return offset;
3168 }
3169
3170 static int
3171 samr_dissect_get_members_in_alias_rqst(tvbuff_t *tvb, int offset,
3172                                        packet_info *pinfo, proto_tree *tree,
3173                                        char *drep)
3174 {
3175         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
3176                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
3177
3178         return offset;
3179 }
3180
3181 static int
3182 samr_dissect_get_members_in_alias_reply(tvbuff_t *tvb, int offset,
3183                         packet_info *pinfo, proto_tree *tree,
3184                         char *drep)
3185 {
3186         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3187                         dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
3188                         "PSID_ARRAY:", -1);
3189
3190         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
3191                                   hf_samr_rc, NULL);
3192
3193         return offset;
3194 }
3195
3196 static int
3197 samr_dissect_LOGON_HOURS_entry(tvbuff_t *tvb, int offset,
3198                              packet_info *pinfo, proto_tree *tree,
3199                              char *drep)
3200 {
3201         offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
3202                         hf_samr_unknown_char, NULL);
3203         return offset;
3204 }
3205
3206 static int
3207 samr_dissect_LOGON_HOURS_hours(tvbuff_t *tvb, int offset,
3208                              packet_info *pinfo, proto_tree *parent_tree,
3209                              char *drep)
3210 {
3211         proto_item *item=NULL;
3212         proto_tree *tree=NULL;
3213         int old_offset=offset;
3214
3215         if(parent_tree){
3216                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3217                         "LOGON_HOURS:");
3218                 tree = proto_item_add_subtree(item, ett_samr_logon_hours_hours);
3219         }
3220
3221         offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
3222                         samr_dissect_LOGON_HOURS_entry);
3223
3224         proto_item_set_len(item, offset-old_offset);
3225         return offset;
3226
3227         return offset;
3228 }
3229
3230 int
3231 dissect_ndr_nt_LOGON_HOURS(tvbuff_t *tvb, int offset,
3232                         packet_info *pinfo, proto_tree *parent_tree,
3233                         char *drep)
3234 {
3235         proto_item *item=NULL;
3236         proto_tree *tree=NULL;
3237         int old_offset=offset;
3238
3239         ALIGN_TO_4_BYTES;  /* strcture starts with short, but is aligned for longs */
3240
3241         if(parent_tree){
3242                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3243                         "LOGON_HOURS:");
3244                 tree = proto_item_add_subtree(item, ett_samr_logon_hours);
3245         }
3246
3247         offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
3248                                 hf_samr_divisions, NULL);
3249         /* XXX - is this a bitmask like the "logon hours" field in the
3250            Remote API call "NetUserGetInfo()" with an information level
3251            of 11? */
3252         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3253                         samr_dissect_LOGON_HOURS_hours, NDR_POINTER_UNIQUE,
3254                         "LOGON_HOURS", -1);
3255
3256         proto_item_set_len(item, offset-old_offset);
3257         return offset;
3258 }
3259
3260
3261 static int
3262 samr_dissect_USER_INFO_1(tvbuff_t *tvb, int offset,
3263                         packet_info *pinfo, proto_tree *parent_tree,
3264                         char *drep)
3265 {
3266         proto_item *item=NULL;
3267         proto_tree *tree=NULL;
3268         int old_offset=offset;
3269
3270         if(parent_tree){
3271                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3272                         "USER_INFO_1:");
3273                 tree = proto_item_add_subtree(item, ett_samr_user_info_1);
3274         }
3275
3276         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3277                                 hf_samr_acct_name, 0);
3278         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3279                                 hf_samr_full_name, 0);
3280         offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
3281         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3282                                 hf_samr_home, 0);
3283         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3284                                 hf_samr_script, 0);
3285
3286         proto_item_set_len(item, offset-old_offset);
3287         return offset;
3288 }
3289
3290 static int
3291 samr_dissect_USER_INFO_2(tvbuff_t *tvb, int offset,
3292                         packet_info *pinfo, proto_tree *parent_tree,
3293                         char *drep)
3294 {
3295         proto_item *item=NULL;
3296         proto_tree *tree=NULL;
3297         int old_offset=offset;
3298
3299         if(parent_tree){
3300                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3301                         "USER_INFO_2:");
3302                 tree = proto_item_add_subtree(item, ett_samr_user_info_2);
3303         }
3304
3305         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3306                                 hf_samr_acct_name, 0);
3307         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3308                                 hf_samr_full_name, 0);
3309         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3310                                 hf_samr_bad_pwd_count, NULL);
3311         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3312                                 hf_samr_logon_count, NULL);
3313
3314         proto_item_set_len(item, offset-old_offset);
3315         return offset;
3316 }
3317
3318 static int
3319 samr_dissect_USER_INFO_3(tvbuff_t *tvb, int offset,
3320                         packet_info *pinfo, proto_tree *parent_tree,
3321                         char *drep)
3322 {
3323         proto_item *item=NULL;
3324         proto_tree *tree=NULL;
3325         int old_offset=offset;
3326
3327         if(parent_tree){
3328                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3329                         "USER_INFO_3:");
3330                 tree = proto_item_add_subtree(item, ett_samr_user_info_3);
3331         }
3332
3333         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3334                                 hf_samr_acct_name, 0);
3335         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3336                                 hf_samr_full_name, 0);
3337         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
3338                                 hf_samr_rid, NULL);
3339         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
3340                                 hf_samr_group, NULL);
3341         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3342                                 hf_samr_home, 0);
3343         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3344                                 hf_samr_home_drive, 0);
3345         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3346                                 hf_samr_script, 0);
3347         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3348                                 hf_samr_acct_desc, 0);
3349         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3350                                 hf_samr_workstations, 0);
3351         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3352                                 hf_samr_logon_time);
3353         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3354                                 hf_samr_logoff_time);
3355         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3356                                 hf_samr_pwd_last_set_time);
3357         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3358                                 hf_samr_pwd_can_change_time);
3359         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3360                                 hf_samr_pwd_must_change_time);
3361         offset = dissect_ndr_nt_LOGON_HOURS(tvb, offset, pinfo, tree, drep);
3362         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3363                                 hf_samr_logon_count, NULL);
3364         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3365                                 hf_samr_bad_pwd_count, NULL);
3366         offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
3367
3368         proto_item_set_len(item, offset-old_offset);
3369         return offset;
3370 }
3371
3372 static int
3373 samr_dissect_USER_INFO_5(tvbuff_t *tvb, int offset,
3374                         packet_info *pinfo, proto_tree *parent_tree,
3375                         char *drep)
3376 {
3377         proto_item *item=NULL;
3378         proto_tree *tree=NULL;
3379         int old_offset=offset;
3380
3381         if(parent_tree){
3382                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3383                         "USER_INFO_5:");
3384                 tree = proto_item_add_subtree(item, ett_samr_user_info_5);
3385         }
3386
3387         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3388                                 hf_samr_acct_name, 0);
3389         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3390                                 hf_samr_full_name, 0);
3391         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
3392                                 hf_samr_rid, NULL);
3393         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
3394                                 hf_samr_group, NULL);
3395         offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
3396                                 hf_samr_country, NULL);
3397         offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
3398                                 hf_samr_codepage, NULL);
3399         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3400                                 hf_samr_home, 0);
3401         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3402                                 hf_samr_home_drive, 0);
3403         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3404                                 hf_samr_script, 0);
3405         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3406                                 hf_samr_acct_desc, 0);
3407         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3408                                 hf_samr_workstations, 0);
3409         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3410                                 hf_samr_logon_time);
3411         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3412                                 hf_samr_logoff_time);
3413         offset = dissect_ndr_nt_LOGON_HOURS(tvb, offset, pinfo, tree, drep);
3414         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3415                                 hf_samr_bad_pwd_count, NULL);
3416         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3417                                 hf_samr_logon_count, NULL);
3418         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3419                                 hf_samr_pwd_last_set_time);
3420         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3421                                 hf_samr_acct_expiry_time);
3422         offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
3423
3424         proto_item_set_len(item, offset-old_offset);
3425         return offset;
3426 }
3427
3428 static int
3429 samr_dissect_USER_INFO_6(tvbuff_t *tvb, int offset,
3430                         packet_info *pinfo, proto_tree *parent_tree,
3431                         char *drep)
3432 {
3433         proto_item *item=NULL;
3434         proto_tree *tree=NULL;
3435         int old_offset=offset;
3436
3437         if(parent_tree){
3438                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3439                         "USER_INFO_6:");
3440                 tree = proto_item_add_subtree(item, ett_samr_user_info_6);
3441         }
3442
3443         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3444                                 hf_samr_acct_name, 0);
3445         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3446                                 hf_samr_full_name, 0);
3447
3448         proto_item_set_len(item, offset-old_offset);
3449         return offset;
3450 }
3451
3452 static int
3453 samr_dissect_USER_INFO_18(tvbuff_t *tvb, int offset,
3454                         packet_info *pinfo, proto_tree *parent_tree,
3455                         char *drep)
3456 {
3457         proto_item *item=NULL;
3458         proto_tree *tree=NULL;
3459         int old_offset=offset;
3460
3461         if(parent_tree){
3462                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3463                         "USER_INFO_18:");
3464                 tree = proto_item_add_subtree(item, ett_samr_user_info_18);
3465         }
3466
3467         offset = samr_dissect_CRYPT_HASH(tvb, offset, pinfo, tree, drep);
3468         offset = samr_dissect_CRYPT_HASH(tvb, offset, pinfo, tree, drep);
3469         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
3470                         hf_samr_unknown_char, NULL);
3471         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
3472                         hf_samr_unknown_char, NULL);
3473         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
3474                         hf_samr_unknown_char, NULL);
3475
3476         proto_item_set_len(item, offset-old_offset);
3477         return offset;
3478 }
3479
3480 static int
3481 samr_dissect_USER_INFO_19(tvbuff_t *tvb, int offset,
3482                         packet_info *pinfo, proto_tree *parent_tree,
3483                         char *drep)
3484 {
3485         proto_item *item=NULL;
3486         proto_tree *tree=NULL;
3487         int old_offset=offset;
3488
3489         if(parent_tree){
3490                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3491                         "USER_INFO_19:");
3492                 tree = proto_item_add_subtree(item, ett_samr_user_info_19);
3493         }
3494
3495         offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
3496         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3497                                 hf_samr_logon_time);
3498         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3499                                 hf_samr_logoff_time);
3500         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3501                                 hf_samr_bad_pwd_count, NULL);
3502         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3503                                 hf_samr_logon_count, NULL);
3504
3505         proto_item_set_len(item, offset-old_offset);
3506         return offset;
3507 }
3508
3509 static int
3510 samr_dissect_BUFFER_entry(tvbuff_t *tvb, int offset,
3511                              packet_info *pinfo, proto_tree *tree,
3512                              char *drep)
3513 {
3514         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
3515                         hf_samr_unknown_char, NULL);
3516         return offset;
3517 }
3518
3519
3520 static int
3521 samr_dissect_BUFFER_buffer(tvbuff_t *tvb, int offset,
3522                              packet_info *pinfo, proto_tree *parent_tree,
3523                              char *drep)
3524 {
3525         proto_item *item=NULL;
3526         proto_tree *tree=NULL;
3527         int old_offset=offset;
3528
3529         if(parent_tree){
3530                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3531                         "BUFFER:");
3532                 tree = proto_item_add_subtree(item, ett_samr_buffer_buffer);
3533         }
3534
3535         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
3536                         samr_dissect_BUFFER_entry);
3537
3538         proto_item_set_len(item, offset-old_offset);
3539         return offset;
3540
3541         return offset;
3542 }
3543
3544 static int
3545 samr_dissect_BUFFER(tvbuff_t *tvb, int offset,
3546                         packet_info *pinfo, proto_tree *parent_tree,
3547                         char *drep)
3548 {
3549         proto_item *item=NULL;
3550         proto_tree *tree=NULL;
3551         int old_offset=offset;
3552
3553         if(parent_tree){
3554                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3555                         "BUFFER:");
3556                 tree = proto_item_add_subtree(item, ett_samr_buffer);
3557         }
3558         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
3559                                 hf_samr_count, NULL);
3560         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3561                         samr_dissect_BUFFER_buffer, NDR_POINTER_UNIQUE,
3562                         "BUFFER", -1);
3563
3564         proto_item_set_len(item, offset-old_offset);
3565         return offset;
3566 }
3567
3568 static int
3569 samr_dissect_USER_INFO_21(tvbuff_t *tvb, int offset,
3570                         packet_info *pinfo, proto_tree *parent_tree,
3571                         char *drep)
3572 {
3573         proto_item *item=NULL;
3574         proto_tree *tree=NULL;
3575         int old_offset=offset;
3576
3577         if(parent_tree){
3578                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3579                         "USER_INFO_21:");
3580                 tree = proto_item_add_subtree(item, ett_samr_user_info_21);
3581         }
3582
3583         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3584                                 hf_samr_logon_time);
3585         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3586                                 hf_samr_logoff_time);
3587         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3588                                 hf_samr_kickoff_time);
3589         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3590                                 hf_samr_pwd_last_set_time);
3591         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3592                                 hf_samr_pwd_can_change_time);
3593         offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3594                                 hf_samr_pwd_must_change_time);
3595         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3596                                 hf_samr_acct_name, 2);
3597         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3598                                 hf_samr_full_name, 0);
3599         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3600                                 hf_samr_home, 0);
3601         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3602                                 hf_samr_home_drive, 0);
3603         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3604                                 hf_samr_script, 0);
3605         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3606                                 hf_samr_profile, 0);
3607         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3608                                 hf_samr_acct_desc, 0);
3609         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3610                                 hf_samr_workstations, 0);
3611         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3612                                 hf_samr_comment, 0);
3613         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3614                                 hf_samr_parameters, 0);
3615         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3616                                 hf_samr_unknown_string, 0);
3617         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3618                                 hf_samr_unknown_string, 0);
3619         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
3620                                 hf_samr_unknown_string, 0);
3621         offset = samr_dissect_BUFFER(tvb, offset, pinfo, tree, drep);
3622         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
3623                                 hf_samr_rid, NULL);
3624         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
3625                                 hf_samr_group, NULL);
3626         offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
3627         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
3628                                 hf_samr_unknown_long, NULL);
3629         offset = dissect_ndr_nt_LOGON_HOURS(tvb, offset, pinfo, tree, drep);
3630         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3631                                 hf_samr_bad_pwd_count, NULL);
3632         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3633                                 hf_samr_logon_count, NULL);
3634         offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
3635                                 hf_samr_country, NULL);
3636         offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
3637                                 hf_samr_codepage, NULL);
3638         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
3639                                 hf_samr_nt_pwd_set, NULL);
3640         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
3641                                 hf_samr_lm_pwd_set, NULL);
3642         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
3643                                 hf_samr_pwd_expired, NULL);
3644         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
3645                                 hf_samr_unknown_char, NULL);
3646
3647         proto_item_set_len(item, offset-old_offset);
3648         return offset;
3649 }
3650
3651 static int
3652 samr_dissect_USER_INFO_22(tvbuff_t *tvb, int offset,
3653                         packet_info *pinfo, proto_tree *parent_tree,
3654                         char *drep)
3655 {
3656         proto_item *item=NULL;
3657         proto_tree *tree=NULL;
3658         int old_offset=offset;
3659
3660         if(parent_tree){
3661                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3662                         "USER_INFO_22:");
3663                 tree = proto_item_add_subtree(item, ett_samr_user_info_22);
3664         }
3665
3666         offset = samr_dissect_USER_INFO_21(tvb, offset, pinfo, tree, drep);
3667         offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
3668                         hf_samr_revision, NULL);
3669
3670         proto_item_set_len(item, offset-old_offset);
3671         return offset;
3672 }
3673
3674 static int
3675 samr_dissect_USER_INFO_23(tvbuff_t *tvb, int offset,
3676                         packet_info *pinfo, proto_tree *parent_tree,
3677                         char *drep)
3678 {
3679         proto_item *item=NULL;
3680         proto_tree *tree=NULL;
3681         int old_offset=offset;
3682
3683         if(parent_tree){
3684                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3685                         "USER_INFO_23:");
3686                 tree = proto_item_add_subtree(item, ett_samr_user_info_23);
3687         }
3688
3689         offset = samr_dissect_USER_INFO_21(tvb, offset, pinfo, tree, drep);
3690         offset = samr_dissect_CRYPT_PASSWORD(tvb, offset, pinfo, tree, drep);
3691
3692         proto_item_set_len(item, offset-old_offset);
3693         return offset;
3694 }
3695
3696 static int
3697 samr_dissect_USER_INFO_24(tvbuff_t *tvb, int offset,
3698                         packet_info *pinfo, proto_tree *parent_tree,
3699                         char *drep)
3700 {
3701         proto_item *item=NULL;
3702         proto_tree *tree=NULL;
3703         int old_offset=offset;
3704
3705         if(parent_tree){
3706                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3707                         "USER_INFO_24:");
3708                 tree = proto_item_add_subtree(item, ett_samr_user_info_24);
3709         }
3710
3711         offset = samr_dissect_CRYPT_PASSWORD(tvb, offset, pinfo, tree, drep);
3712         offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
3713                                 hf_samr_unknown_char, NULL);
3714
3715         proto_item_set_len(item, offset-old_offset);
3716         return offset;
3717 }
3718
3719 static int
3720 samr_dissect_USER_INFO (tvbuff_t *tvb, int offset,
3721                              packet_info *pinfo, proto_tree *parent_tree,
3722                              char *drep)
3723 {
3724         proto_item *item=NULL;
3725         proto_tree *tree=NULL;
3726         int old_offset=offset;
3727         guint16 level;
3728
3729         if(parent_tree){
3730                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3731                         "USER_INFO:");
3732                 tree = proto_item_add_subtree(item, ett_samr_user_info);
3733         }
3734         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3735                                      hf_samr_level, &level);
3736
3737         switch(level){
3738         case 1:
3739                 offset = samr_dissect_USER_INFO_1(
3740                                 tvb, offset, pinfo, tree, drep);
3741                 break;
3742         case 2:
3743                 offset = samr_dissect_USER_INFO_2(
3744                                 tvb, offset, pinfo, tree, drep);
3745                 break;
3746         case 3:
3747                 offset = samr_dissect_USER_INFO_3(
3748                                 tvb, offset, pinfo, tree, drep);
3749                 break;
3750         case 4:
3751                 offset = dissect_ndr_nt_LOGON_HOURS(
3752                                 tvb, offset, pinfo, tree, drep);
3753                 break;
3754         case 5:
3755                 offset = samr_dissect_USER_INFO_5(
3756                                 tvb, offset, pinfo, tree, drep);
3757                 break;
3758         case 6:
3759                 offset = samr_dissect_USER_INFO_6(
3760                                 tvb, offset, pinfo, tree, drep);
3761                 break;
3762         case 7:
3763                 offset = dissect_ndr_counted_string(
3764                         tvb, offset, pinfo, tree, drep, hf_samr_full_name, 0);
3765                 break;
3766         case 8:
3767                 offset = dissect_ndr_counted_string(
3768                         tvb, offset, pinfo, tree, drep, hf_samr_acct_desc, 0);
3769                 break;
3770         case 9:
3771                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
3772                                              hf_samr_unknown_long, NULL);
3773                 break;
3774         case 10:
3775                 offset = samr_dissect_USER_INFO_6(
3776                                 tvb, offset, pinfo, tree, drep);
3777                 break;
3778         case 11:
3779                 offset = dissect_ndr_counted_string(
3780                         tvb, offset, pinfo, tree, drep, hf_samr_home, 0);
3781                 break;
3782         case 12:
3783                 offset = dissect_ndr_counted_string(
3784                         tvb, offset, pinfo, tree, drep, hf_samr_home_drive, 0);
3785                 break;
3786         case 13:
3787                 offset = dissect_ndr_counted_string(
3788                         tvb, offset, pinfo, tree, drep, hf_samr_script, 0);
3789                 break;
3790         case 14:
3791                 offset = dissect_ndr_counted_string(
3792                         tvb, offset, pinfo, tree, drep, hf_samr_workstations, 0);
3793                 break;
3794         case 16:
3795                 offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree,
3796                                              drep);
3797                 break;
3798         case 17:
3799                 offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
3800                                         hf_samr_unknown_time);
3801                 break;
3802         case 18:
3803                 offset = samr_dissect_USER_INFO_18(
3804                                 tvb, offset, pinfo, tree, drep);
3805                 break;
3806         case 19:
3807                 offset = samr_dissect_USER_INFO_19(
3808                                 tvb, offset, pinfo, tree, drep);
3809                 break;
3810         case 20:
3811                 offset = dissect_ndr_counted_string(
3812                         tvb, offset, pinfo, tree, drep, hf_samr_profile, 0);
3813                 break;
3814         case 21:
3815                 offset = samr_dissect_USER_INFO_21(
3816                                 tvb, offset, pinfo, tree, drep);
3817                 break;
3818         case 22:
3819                 offset = samr_dissect_USER_INFO_22(
3820                                 tvb, offset, pinfo, tree, drep);
3821                 break;
3822         case 23:
3823                 offset = samr_dissect_USER_INFO_23(
3824                                 tvb, offset, pinfo, tree, drep);
3825                 break;
3826         case 24:
3827                 offset = samr_dissect_USER_INFO_24(
3828                                 tvb, offset, pinfo, tree, drep);
3829                 break;
3830         }
3831
3832         proto_item_set_len(item, offset-old_offset);
3833         return offset;
3834 }
3835
3836 static int
3837 samr_dissect_USER_INFO_ptr(tvbuff_t *tvb, int offset,
3838                         packet_info *pinfo, proto_tree *tree,
3839                         char *drep)
3840 {
3841         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3842                         samr_dissect_USER_INFO, NDR_POINTER_UNIQUE,
3843                         "USER_INFO pointer", -1);
3844         return offset;
3845 }
3846
3847 static int
3848 samr_dissect_set_information_user2_rqst(tvbuff_t *tvb, int offset,
3849                                         packet_info *pinfo, proto_tree *tree,
3850                                         char *drep)
3851 {
3852         guint16 level;
3853
3854         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
3855                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
3856
3857         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3858                         hf_samr_level, &level);
3859
3860         if (check_col(pinfo->cinfo, COL_INFO))
3861                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
3862
3863         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3864                         samr_dissect_USER_INFO, NDR_POINTER_REF,
3865                         "USER_INFO:", -1);
3866
3867         return offset;
3868 }
3869
3870 static int
3871 samr_dissect_set_information_user2_reply(tvbuff_t *tvb, int offset,
3872                                          packet_info *pinfo, proto_tree *tree,
3873                                          char *drep)
3874 {
3875         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
3876                                   hf_samr_rc, NULL);
3877
3878         return offset;
3879 }
3880
3881 static int
3882 samr_dissect_unknown_2f_rqst(tvbuff_t *tvb, int offset,
3883                                  packet_info *pinfo, proto_tree *tree,
3884                                  char *drep)
3885 {
3886         guint16 level;
3887
3888         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
3889                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
3890
3891         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
3892                         hf_samr_level, &level);
3893
3894         if (check_col(pinfo->cinfo, COL_INFO))
3895                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
3896
3897         return offset;
3898 }
3899
3900 static int
3901 samr_dissect_unknown_2f_reply(tvbuff_t *tvb, int offset,
3902                         packet_info *pinfo, proto_tree *tree,
3903                         char *drep)
3904 {
3905         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
3906                         samr_dissect_USER_INFO_ptr, NDR_POINTER_REF,
3907                         "USER_INFO:", -1);
3908
3909         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
3910                         hf_samr_rc, NULL);
3911
3912         return offset;
3913 }
3914
3915 static int
3916 samr_dissect_MEMBER_ARRAY_type(tvbuff_t *tvb, int offset,
3917                         packet_info *pinfo, proto_tree *tree,
3918                         char *drep)
3919 {
3920         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
3921                                 hf_samr_type, NULL);
3922
3923         return offset;
3924 }
3925
3926
3927 static int
3928 samr_dissect_MEMBER_ARRAY_types(tvbuff_t *tvb, int offset,
3929                         packet_info *pinfo, proto_tree *parent_tree,
3930                         char *drep)
3931 {
3932         proto_item *item=NULL;
3933         proto_tree *tree=NULL;
3934         int old_offset=offset;
3935
3936         if(parent_tree){
3937                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3938                         "MEMBER_ARRAY_types:");
3939                 tree = proto_item_add_subtree(item, ett_samr_member_array_types);
3940         }
3941
3942         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
3943                         samr_dissect_MEMBER_ARRAY_type);
3944
3945         proto_item_set_len(item, offset-old_offset);
3946         return offset;
3947
3948         return offset;
3949 }
3950
3951 static int
3952 samr_dissect_MEMBER_ARRAY_rid(tvbuff_t *tvb, int offset,
3953                         packet_info *pinfo, proto_tree *tree,
3954                         char *drep)
3955 {
3956         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
3957                                 hf_samr_rid, NULL);
3958
3959         return offset;
3960 }
3961
3962
3963 static int
3964 samr_dissect_MEMBER_ARRAY_rids(tvbuff_t *tvb, int offset,
3965                         packet_info *pinfo, proto_tree *parent_tree,
3966                         char *drep)
3967 {
3968         proto_item *item=NULL;
3969         proto_tree *tree=NULL;
3970         int old_offset=offset;
3971
3972         if(parent_tree){
3973                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3974                         "MEMBER_ARRAY_rids:");
3975                 tree = proto_item_add_subtree(item, ett_samr_member_array_rids);
3976         }
3977
3978         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
3979                         samr_dissect_MEMBER_ARRAY_rid);
3980
3981         proto_item_set_len(item, offset-old_offset);
3982         return offset;
3983
3984         return offset;
3985 }
3986
3987 static int
3988 samr_dissect_MEMBER_ARRAY(tvbuff_t *tvb, int offset,
3989                         packet_info *pinfo, proto_tree *parent_tree,
3990                         char *drep)
3991 {
3992         guint32 count;
3993         proto_item *item=NULL;
3994         proto_tree *tree=NULL;
3995         int old_offset=offset;
3996
3997         if(parent_tree){
3998                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
3999                         "MEMBER_ARRAY:");
4000                 tree = proto_item_add_subtree(item, ett_samr_member_array);
4001         }
4002
4003         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
4004                         hf_samr_count, &count);
4005         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4006                         samr_dissect_MEMBER_ARRAY_rids, NDR_POINTER_UNIQUE,
4007                         "RIDs", -1);
4008         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4009                         samr_dissect_MEMBER_ARRAY_types, NDR_POINTER_UNIQUE,
4010                         "Types", -1);
4011
4012         proto_item_set_len(item, offset-old_offset);
4013         return offset;
4014 }
4015
4016 static int
4017 samr_dissect_MEMBER_ARRAY_ptr(tvbuff_t *tvb, int offset,
4018                         packet_info *pinfo, proto_tree *tree,
4019                         char *drep)
4020 {
4021         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4022                         samr_dissect_MEMBER_ARRAY, NDR_POINTER_UNIQUE,
4023                         "MEMBER_ARRAY", -1);
4024         return offset;
4025 }
4026
4027 static int
4028 samr_dissect_query_groupmem_rqst(tvbuff_t *tvb, int offset,
4029                                  packet_info *pinfo, proto_tree *tree,
4030                                  char *drep)
4031 {
4032         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4033                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4034
4035         return offset;
4036 }
4037
4038 static int
4039 samr_dissect_query_groupmem_reply(tvbuff_t *tvb, int offset,
4040                         packet_info *pinfo, proto_tree *tree,
4041                         char *drep)
4042 {
4043         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4044                         samr_dissect_MEMBER_ARRAY_ptr, NDR_POINTER_REF,
4045                         "MEMBER_ARRAY:", -1);
4046
4047         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4048                                   hf_samr_rc, NULL);
4049
4050         return offset;
4051 }
4052
4053 static int
4054 samr_dissect_set_sec_object_rqst(tvbuff_t *tvb, int offset,
4055                                  packet_info *pinfo, proto_tree *tree,
4056                                  char *drep)
4057 {
4058         guint32 info_type;
4059
4060         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4061                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4062
4063         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
4064                         hf_samr_info_type, &info_type);
4065
4066         if (check_col(pinfo->cinfo, COL_INFO))
4067                 col_append_fstr(
4068                         pinfo->cinfo, COL_INFO, ", info type %d", info_type);
4069
4070         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4071                 lsa_dissect_LSA_SECURITY_DESCRIPTOR, NDR_POINTER_REF,
4072                 "LSA_SECURITY_DESCRIPTOR pointer: ", -1);
4073
4074         return offset;
4075 }
4076
4077 static int
4078 samr_dissect_set_sec_object_reply(tvbuff_t *tvb, int offset,
4079                                   packet_info *pinfo, proto_tree *tree,
4080                                   char *drep)
4081 {
4082         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4083                                   hf_samr_rc, NULL);
4084
4085         return offset;
4086 }
4087
4088 static int
4089 samr_dissect_query_sec_object_rqst(tvbuff_t *tvb, int offset,
4090                                    packet_info *pinfo, proto_tree *tree,
4091                                    char *drep)
4092 {
4093         guint32 info_type;
4094
4095         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4096                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4097
4098         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
4099                         hf_samr_info_type, &info_type);
4100
4101         if (check_col(pinfo->cinfo, COL_INFO))
4102                 col_append_fstr(
4103                         pinfo->cinfo, COL_INFO, ", info_type %d", info_type);
4104
4105         return offset;
4106 }
4107
4108 static int
4109 samr_dissect_query_sec_object_reply(tvbuff_t *tvb, int offset,
4110                         packet_info *pinfo, proto_tree *tree,
4111                         char *drep)
4112 {
4113         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4114                 lsa_dissect_LSA_SECURITY_DESCRIPTOR, NDR_POINTER_UNIQUE,
4115                 "LSA_SECURITY_DESCRIPTOR pointer: ", -1);
4116
4117         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4118                                   hf_samr_rc, NULL);
4119
4120         return offset;
4121 }
4122
4123 static int
4124 samr_dissect_LOOKUP_NAMES_name(tvbuff_t *tvb, int offset,
4125                         packet_info *pinfo, proto_tree *tree,
4126                         char *drep)
4127 {
4128         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
4129                                 hf_samr_acct_name, 1);
4130         return offset;
4131 }
4132
4133 static int
4134 samr_dissect_LOOKUP_NAMES(tvbuff_t *tvb, int offset,
4135                         packet_info *pinfo, proto_tree *parent_tree,
4136                         char *drep)
4137 {
4138         proto_item *item=NULL;
4139         proto_tree *tree=NULL;
4140         int old_offset=offset;
4141
4142         if(parent_tree){
4143                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
4144                         "NAMES:");
4145                 tree = proto_item_add_subtree(item, ett_samr_names);
4146         }
4147
4148         offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
4149                         samr_dissect_LOOKUP_NAMES_name);
4150
4151         proto_item_set_len(item, offset-old_offset);
4152         return offset;
4153 }
4154
4155
4156 static int
4157 samr_dissect_lookup_names_rqst(tvbuff_t *tvb, int offset,
4158                                packet_info *pinfo, proto_tree *tree,
4159                                char *drep)
4160 {
4161         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4162                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4163
4164         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
4165                         hf_samr_count, NULL);
4166
4167         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4168                         samr_dissect_LOOKUP_NAMES, NDR_POINTER_REF,
4169                         "LOOKUP_NAMES:", -1);
4170
4171         return offset;
4172 }
4173
4174 static int
4175 samr_dissect_lookup_names_reply(tvbuff_t *tvb, int offset,
4176                         packet_info *pinfo, proto_tree *tree,
4177                         char *drep)
4178 {
4179         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4180                         samr_dissect_INDEX_ARRAY, NDR_POINTER_REF,
4181                         "Rids:", hf_samr_rid);
4182
4183         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4184                         samr_dissect_INDEX_ARRAY, NDR_POINTER_REF,
4185                         "Types:", hf_samr_type);
4186
4187         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4188                                   hf_samr_rc, NULL);
4189
4190         return offset;
4191 }
4192
4193 static int
4194 samr_dissect_LOOKUP_RIDS_rid(tvbuff_t *tvb, int offset,
4195                         packet_info *pinfo, proto_tree *tree,
4196                         char *drep)
4197 {
4198         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
4199                                 hf_samr_rid, NULL);
4200
4201         return offset;
4202 }
4203
4204 static int
4205 samr_dissect_LOOKUP_RIDS(tvbuff_t *tvb, int offset,
4206                         packet_info *pinfo, proto_tree *parent_tree,
4207                         char *drep)
4208 {
4209         proto_item *item=NULL;
4210         proto_tree *tree=NULL;
4211         int old_offset=offset;
4212
4213         if(parent_tree){
4214                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
4215                         "RIDS:");
4216                 tree = proto_item_add_subtree(item, ett_samr_rids);
4217         }
4218
4219         offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
4220                         samr_dissect_LOOKUP_RIDS_rid);
4221
4222         proto_item_set_len(item, offset-old_offset);
4223         return offset;
4224 }
4225
4226
4227 static int
4228 samr_dissect_lookup_rids_rqst(tvbuff_t *tvb, int offset,
4229                               packet_info *pinfo, proto_tree *tree,
4230                               char *drep)
4231 {
4232         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4233                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4234
4235         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
4236                         hf_samr_count, NULL);
4237
4238         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4239                         samr_dissect_LOOKUP_RIDS, NDR_POINTER_REF,
4240                         "LOOKUP_RIDS:", -1);
4241
4242         return offset;
4243 }
4244
4245 static int
4246 samr_dissect_UNICODE_STRING_ARRAY_name(tvbuff_t *tvb, int offset,
4247                         packet_info *pinfo, proto_tree *tree,
4248                         char *drep)
4249 {
4250         offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
4251                                 hf_samr_acct_name, 0);
4252         return offset;
4253 }
4254
4255 static int
4256 samr_dissect_UNICODE_STRING_ARRAY_names(tvbuff_t *tvb, int offset,
4257                         packet_info *pinfo, proto_tree *tree,
4258                         char *drep)
4259 {
4260         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
4261                         samr_dissect_UNICODE_STRING_ARRAY_name);
4262         return offset;
4263 }
4264
4265 static int
4266 samr_dissect_UNICODE_STRING_ARRAY(tvbuff_t *tvb, int offset,
4267                         packet_info *pinfo, proto_tree *parent_tree,
4268                         char *drep)
4269 {
4270         proto_item *item=NULL;
4271         proto_tree *tree=NULL;
4272         int old_offset=offset;
4273
4274         if(parent_tree){
4275                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
4276                         "NAMES:");
4277                 tree = proto_item_add_subtree(item, ett_samr_names);
4278         }
4279
4280         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
4281                         hf_samr_count, NULL);
4282
4283         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4284                         samr_dissect_UNICODE_STRING_ARRAY_names, NDR_POINTER_UNIQUE,
4285                         "Strings", -1);
4286
4287         proto_item_set_len(item, offset-old_offset);
4288         return offset;
4289
4290         return offset;
4291 }
4292
4293
4294 static int
4295 samr_dissect_lookup_rids_reply(tvbuff_t *tvb, int offset,
4296                         packet_info *pinfo, proto_tree *tree,
4297                         char *drep)
4298 {
4299         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4300                         samr_dissect_UNICODE_STRING_ARRAY, NDR_POINTER_REF,
4301                         "RIDs:", hf_samr_rid);
4302
4303         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4304                         samr_dissect_INDEX_ARRAY, NDR_POINTER_REF,
4305                         "Types:", hf_samr_type);
4306
4307         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4308                                   hf_samr_rc, NULL);
4309
4310         return offset;
4311 }
4312
4313 static int
4314 samr_dissect_close_hnd_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo,
4315                             proto_tree *tree, char *drep)
4316 {
4317         e_ctx_hnd policy_hnd;
4318         char *name;
4319
4320         offset = dissect_nt_policy_hnd(
4321                 tvb, offset, pinfo, tree, drep, hf_samr_hnd, &policy_hnd, 
4322                 NULL, FALSE, TRUE);
4323
4324         dcerpc_smb_fetch_pol(&policy_hnd, &name, NULL, NULL, pinfo->fd->num);
4325
4326         if (name != NULL && check_col(pinfo->cinfo, COL_INFO))
4327                 col_append_fstr(
4328                         pinfo->cinfo, COL_INFO, ", %s", name);
4329
4330         return offset;
4331 }
4332
4333 static int
4334 samr_dissect_close_hnd_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
4335                              proto_tree *tree, char *drep)
4336 {
4337         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4338                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4339
4340         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4341                         hf_samr_rc, NULL);
4342
4343         return offset;
4344 }
4345
4346 static int
4347 samr_dissect_shutdown_sam_server_rqst(tvbuff_t *tvb, int offset,
4348                                       packet_info *pinfo, proto_tree *tree,
4349                                       char *drep)
4350 {
4351         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4352                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4353
4354         return offset;
4355 }
4356
4357 static int
4358 samr_dissect_shutdown_sam_server_reply(tvbuff_t *tvb, int offset,
4359                                       packet_info *pinfo, proto_tree *tree,
4360                                       char *drep)
4361 {
4362         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4363                                   hf_samr_rc, NULL);
4364
4365         return offset;
4366 }
4367
4368 static int
4369 samr_dissect_delete_dom_group_rqst(tvbuff_t *tvb, int offset,
4370                                    packet_info *pinfo, proto_tree *tree,
4371                                    char *drep)
4372 {
4373         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4374                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4375
4376         return offset;
4377 }
4378
4379 static int
4380 samr_dissect_delete_dom_group_reply(tvbuff_t *tvb, int offset,
4381                                     packet_info *pinfo, proto_tree *tree,
4382                                     char *drep)
4383 {
4384         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4385                                   hf_samr_rc, NULL);
4386
4387         return offset;
4388 }
4389
4390 static int
4391 samr_dissect_remove_member_from_group_rqst(tvbuff_t *tvb, int offset,
4392                                            packet_info *pinfo,
4393                                            proto_tree *tree, char *drep)
4394 {
4395         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4396                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4397
4398         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
4399                                      hf_samr_group, NULL);
4400
4401         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
4402                                      hf_samr_rid, NULL);
4403
4404         return offset;
4405 }
4406
4407 static int
4408 samr_dissect_remove_member_from_group_reply(tvbuff_t *tvb, int offset,
4409                                             packet_info *pinfo,
4410                                             proto_tree *tree, char *drep)
4411 {
4412         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4413                                   hf_samr_rc, NULL);
4414
4415         return offset;
4416 }
4417
4418 static int
4419 samr_dissect_delete_dom_alias_rqst(tvbuff_t *tvb, int offset,
4420                                    packet_info *pinfo, proto_tree *tree,
4421                                    char *drep)
4422 {
4423         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4424                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4425
4426         return offset;
4427 }
4428
4429 static int
4430 samr_dissect_delete_dom_alias_reply(tvbuff_t *tvb, int offset,
4431                                     packet_info *pinfo, proto_tree *tree,
4432                                     char *drep)
4433 {
4434         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4435                                   hf_samr_rc, NULL);
4436
4437         return offset;
4438 }
4439
4440 static int
4441 samr_dissect_add_alias_member_rqst(tvbuff_t *tvb, int offset,
4442                                    packet_info *pinfo, proto_tree *tree,
4443                                    char *drep)
4444 {
4445         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4446                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4447
4448         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4449                         dissect_ndr_nt_SID_no_hf, NDR_POINTER_REF,
4450                         "SID pointer", -1);
4451
4452         return offset;
4453 }
4454
4455 static int
4456 samr_dissect_add_alias_member_reply(tvbuff_t *tvb, int offset,
4457                                     packet_info *pinfo, proto_tree *tree,
4458                                     char *drep)
4459 {
4460         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4461                                   hf_samr_rc, NULL);
4462
4463         return offset;
4464 }
4465
4466 static int
4467 samr_dissect_remove_alias_member_rqst(tvbuff_t *tvb, int offset,
4468                                       packet_info *pinfo, proto_tree *tree,
4469                                       char *drep)
4470 {
4471         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4472                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4473
4474         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4475                         dissect_ndr_nt_SID_no_hf, NDR_POINTER_REF,
4476                         "SID pointer", -1);
4477
4478         return offset;
4479 }
4480
4481 static int
4482 samr_dissect_remove_alias_member_reply(tvbuff_t *tvb, int offset,
4483                                        packet_info *pinfo, proto_tree *tree,
4484                                        char *drep)
4485 {
4486         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4487                                   hf_samr_rc, NULL);
4488
4489         return offset;
4490 }
4491
4492 static int
4493 samr_dissect_delete_dom_user_rqst(tvbuff_t *tvb, int offset,
4494                                   packet_info *pinfo, proto_tree *tree,
4495                                   char *drep)
4496 {
4497         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4498                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4499
4500         return offset;
4501 }
4502
4503 static int
4504 samr_dissect_delete_dom_user_reply(tvbuff_t *tvb, int offset,
4505                                    packet_info *pinfo, proto_tree *tree,
4506                                    char *drep)
4507 {
4508         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4509                                   hf_samr_rc, NULL);
4510
4511         return offset;
4512 }
4513
4514 static int
4515 samr_dissect_test_private_fns_domain_rqst(tvbuff_t *tvb, int offset,
4516                                           packet_info *pinfo, proto_tree *tree,
4517                                           char *drep)
4518 {
4519         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4520                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4521
4522         return offset;
4523 }
4524
4525 static int
4526 samr_dissect_test_private_fns_domain_reply(tvbuff_t *tvb, int offset,
4527                                            packet_info *pinfo,
4528                                            proto_tree *tree, char *drep)
4529 {
4530         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4531                                   hf_samr_rc, NULL);
4532
4533         return offset;
4534 }
4535
4536 static int
4537 samr_dissect_test_private_fns_user_rqst(tvbuff_t *tvb, int offset,
4538                                         packet_info *pinfo, proto_tree *tree,
4539                                         char *drep)
4540 {
4541         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4542                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4543
4544         return offset;
4545 }
4546
4547 static int
4548 samr_dissect_test_private_fns_user_reply(tvbuff_t *tvb, int offset,
4549                                          packet_info *pinfo,
4550                                          proto_tree *tree, char *drep)
4551 {
4552         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4553                                   hf_samr_rc, NULL);
4554
4555         return offset;
4556 }
4557
4558 static int
4559 samr_dissect_remove_member_from_foreign_domain_rqst(tvbuff_t *tvb, int offset,
4560                                                     packet_info *pinfo,
4561                                                     proto_tree *tree,
4562                                                     char *drep)
4563 {
4564         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4565                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4566
4567         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4568                         dissect_ndr_nt_SID_no_hf, NDR_POINTER_REF,
4569                         "SID pointer", -1);
4570
4571         return offset;
4572 }
4573
4574 static int
4575 samr_dissect_remove_member_from_foreign_domain_reply(tvbuff_t *tvb, int offset,
4576                                                      packet_info *pinfo,
4577                                                      proto_tree *tree,
4578                                                      char *drep)
4579 {
4580         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4581                                   hf_samr_rc, NULL);
4582
4583         return offset;
4584 }
4585
4586 static int
4587 samr_dissect_remove_multiple_members_from_alias_rqst(tvbuff_t *tvb,
4588                                                      int offset,
4589                                                      packet_info *pinfo,
4590                                                      proto_tree *tree,
4591                                                      char *drep)
4592 {
4593         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4594                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4595
4596         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4597                         dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
4598                         "PSID_ARRAY:", -1);
4599
4600         return offset;
4601 }
4602
4603 static int
4604 samr_dissect_remove_multiple_members_from_alias_reply(tvbuff_t *tvb,
4605                                                       int offset,
4606                                                       packet_info *pinfo,
4607                                                       proto_tree *tree,
4608                                                       char *drep)
4609 {
4610         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4611                                   hf_samr_rc, NULL);
4612
4613         return offset;
4614 }
4615
4616 static int
4617 samr_dissect_open_group_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo,
4618                             proto_tree *tree, char *drep)
4619 {
4620         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4621         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4622         guint32 rid;
4623
4624         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4625                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4626
4627         offset = dissect_nt_access_mask(
4628                 tvb, offset, pinfo, tree, drep, hf_samr_access,
4629                 &samr_group_access_mask_info);
4630
4631         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
4632                         hf_samr_rid, &rid);
4633
4634         if (check_col(pinfo->cinfo, COL_INFO))
4635                 col_append_fstr(pinfo->cinfo, COL_INFO, ", rid 0x%x", rid);
4636
4637         dcv->private_data = GINT_TO_POINTER(rid);
4638
4639         return offset;
4640 }
4641
4642 static int
4643 samr_dissect_open_group_reply(tvbuff_t *tvb, int offset,
4644                               packet_info *pinfo, proto_tree *tree,
4645                               char *drep)
4646 {
4647         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4648         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4649         guint32 rid = GPOINTER_TO_INT(dcv->private_data);
4650         e_ctx_hnd policy_hnd;
4651         proto_item *hnd_item;
4652         guint32 status;
4653         char *pol_name;
4654
4655         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4656                                        hf_samr_hnd, &policy_hnd, &hnd_item,
4657                                        TRUE, FALSE);
4658
4659         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4660                         hf_samr_rc, &status);
4661
4662         if (status == 0) {
4663                 if (rid)
4664                         pol_name = g_strdup_printf("OpenGroup(rid 0x%x)", rid);
4665                 else
4666                         pol_name = g_strdup("OpenGroup handle");
4667
4668                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
4669
4670                 if (hnd_item != NULL)
4671                         proto_item_append_text(hnd_item, ": %s", pol_name);
4672
4673                 g_free(pol_name);
4674         }
4675
4676         return offset;
4677 }
4678
4679 static int
4680 samr_dissect_open_alias_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo,
4681                              proto_tree *tree, char *drep)
4682 {
4683         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4684         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4685         guint32 rid;
4686
4687         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4688                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4689
4690         offset = dissect_nt_access_mask(
4691                 tvb, offset, pinfo, tree, drep, hf_samr_access,
4692                 &samr_alias_access_mask_info);
4693
4694         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
4695                         hf_samr_rid, &rid);
4696
4697         if (check_col(pinfo->cinfo, COL_INFO))
4698                 col_append_fstr(pinfo->cinfo, COL_INFO, ", rid 0x%x", rid);
4699
4700         dcv->private_data = GINT_TO_POINTER(rid);
4701
4702         return offset;
4703 }
4704
4705 static int
4706 samr_dissect_open_alias_reply(tvbuff_t *tvb, int offset,
4707                               packet_info *pinfo, proto_tree *tree,
4708                               char *drep)
4709 {
4710         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4711         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4712         e_ctx_hnd policy_hnd;
4713         char *pol_name;
4714         proto_item *hnd_item;
4715         guint32 status;
4716         guint32 rid;
4717
4718         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4719                                        hf_samr_hnd, &policy_hnd, &hnd_item,
4720                                        TRUE, FALSE);
4721
4722         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4723                         hf_samr_rc, &status);
4724
4725         if (status == 0) {
4726                 rid = GPOINTER_TO_INT(dcv->private_data);
4727
4728                 if (rid)
4729                         pol_name = g_strdup_printf("OpenAlias(rid 0x%x)", rid);
4730                 else
4731                         pol_name = g_strdup_printf("OpenAlias handle");
4732
4733                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
4734
4735                 if (hnd_item != NULL)
4736                         proto_item_append_text(hnd_item, ": %s", pol_name);
4737
4738                 g_free(pol_name);
4739         }
4740
4741         return offset;
4742 }
4743
4744 static int
4745 samr_dissect_add_multiple_members_to_alias_rqst(tvbuff_t *tvb, int offset,
4746                                                 packet_info *pinfo,
4747                                                 proto_tree *tree, char *drep)
4748 {
4749         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4750                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4751
4752         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4753                         dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
4754                         "PSID_ARRAY:", -1);
4755
4756         return offset;
4757 }
4758
4759 static int
4760 samr_dissect_add_multiple_members_to_alias_reply(tvbuff_t *tvb, int offset,
4761                                                  packet_info *pinfo,
4762                                                  proto_tree *tree, char *drep)
4763 {
4764         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4765                                   hf_samr_rc, NULL);
4766
4767         return offset;
4768 }
4769
4770 static int
4771 samr_dissect_create_group_in_domain_rqst(tvbuff_t *tvb, int offset,
4772                                          packet_info *pinfo, proto_tree *tree,
4773                                          char *drep)
4774 {
4775         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4776                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4777
4778         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4779                         dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
4780                         "Account Name", hf_samr_acct_name);
4781
4782         offset = dissect_nt_access_mask(
4783                 tvb, offset, pinfo, tree, drep, hf_samr_access,
4784                 &samr_group_access_mask_info);
4785
4786         return offset;
4787 }
4788
4789 static int
4790 samr_dissect_create_group_in_domain_reply(tvbuff_t *tvb, int offset,
4791                                           packet_info *pinfo, proto_tree *tree,
4792                                           char *drep)
4793 {
4794         e_ctx_hnd policy_hnd;
4795         proto_item *hnd_item;
4796         guint32 rid;
4797         guint32 status;
4798         char *pol_name;
4799
4800         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4801                                        hf_samr_hnd, &policy_hnd, &hnd_item,
4802                                        TRUE, FALSE);
4803
4804         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
4805                                      hf_samr_rid, &rid);
4806
4807         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4808                                   hf_samr_rc, &status);
4809
4810         if (status == 0) {
4811                 pol_name = g_strdup_printf("CreateGroup(rid 0x%x)", rid);
4812
4813                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
4814
4815                 if (hnd_item != NULL)
4816                         proto_item_append_text(hnd_item, ": %s", pol_name);
4817
4818                 g_free(pol_name);
4819         }
4820
4821         return offset;
4822 }
4823
4824 static int
4825 samr_dissect_query_information_domain_rqst(tvbuff_t *tvb, int offset,
4826                                            packet_info *pinfo,
4827                                            proto_tree *tree, char *drep)
4828 {
4829         guint16 level;
4830
4831         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4832                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4833
4834         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
4835                         hf_samr_level, &level);
4836
4837         if (check_col(pinfo->cinfo, COL_INFO))
4838                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
4839
4840         return offset;
4841 }
4842
4843 static int
4844 samr_dissect_query_information_domain_reply(tvbuff_t *tvb, int offset,
4845                         packet_info *pinfo, proto_tree *tree,
4846                         char *drep)
4847 {
4848         /*
4849          * Yes, in at least one capture with replies from a W2K server,
4850          * this was, indeed, a UNIQUE pointer, not a REF pointer.
4851          */
4852         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4853                         samr_dissect_DOMAIN_INFO, NDR_POINTER_UNIQUE,
4854                         "DOMAIN_INFO pointer", hf_samr_domain);
4855
4856         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4857                         hf_samr_rc, NULL);
4858
4859         return offset;
4860 }
4861
4862 static int
4863 samr_dissect_query_information_user_rqst(tvbuff_t *tvb, int offset,
4864                                           packet_info *pinfo,
4865                                           proto_tree *tree, char *drep)
4866 {
4867         guint16 level;
4868
4869         offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
4870                                        hf_samr_hnd, NULL, NULL, FALSE, FALSE);
4871
4872         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
4873                         hf_samr_level, &level);
4874
4875         if (check_col(pinfo->cinfo, COL_INFO))
4876                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
4877
4878         return offset;
4879 }
4880
4881 static int
4882 samr_dissect_query_information_user_reply(tvbuff_t *tvb, int offset,
4883                                            packet_info *pinfo,
4884                                            proto_tree *tree, char *drep)
4885 {
4886         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
4887                         samr_dissect_USER_INFO_ptr, NDR_POINTER_REF,
4888                         "USER_INFO:", -1);
4889
4890         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
4891                                   hf_samr_rc, NULL);
4892
4893         return offset;
4894 }
4895
4896 static dcerpc_sub_dissector dcerpc_samr_dissectors[] = {
4897         { SAMR_CONNECT, "SamrConnect",
4898                 samr_dissect_connect_anon_rqst,
4899                 samr_dissect_connect_anon_reply },
4900         { SAMR_CLOSE_HND, "Close",
4901                 samr_dissect_close_hnd_rqst,
4902                 samr_dissect_close_hnd_reply },
4903         { SAMR_SET_SEC_OBJECT, "SetSecObject",
4904                 samr_dissect_set_sec_object_rqst,
4905                 samr_dissect_set_sec_object_reply },
4906         { SAMR_QUERY_SEC_OBJECT, "QuerySecObject",
4907                 samr_dissect_query_sec_object_rqst,
4908                 samr_dissect_query_sec_object_reply },
4909         { SAMR_SHUTDOWN_SAM_SERVER, "ShutdownSamServer",
4910                 samr_dissect_shutdown_sam_server_rqst,
4911                 samr_dissect_shutdown_sam_server_reply },
4912         { SAMR_LOOKUP_DOMAIN, "LookupDomain",
4913                 samr_dissect_lookup_domain_rqst,
4914                 samr_dissect_lookup_domain_reply },
4915         { SAMR_ENUM_DOMAINS, "EnumDomains",
4916                 samr_dissect_enum_domains_rqst,
4917                 samr_dissect_enum_domains_reply },
4918         { SAMR_OPEN_DOMAIN, "OpenDomain",
4919                 samr_dissect_open_domain_rqst,
4920                 samr_dissect_open_domain_reply },
4921         { SAMR_QUERY_DOMAIN_INFO, "QueryDomainInfo",
4922                 samr_dissect_query_information_alias_rqst,
4923                 samr_dissect_query_information_domain_reply },
4924         { SAMR_SET_DOMAIN_INFO, "SetDomainInfo",
4925                 samr_dissect_set_information_domain_rqst,
4926                 samr_dissect_set_information_domain_reply },
4927         { SAMR_CREATE_DOM_GROUP, "CreateGroup",
4928                 samr_dissect_create_alias_in_domain_rqst,
4929                 samr_dissect_create_alias_in_domain_reply },
4930         { SAMR_ENUM_DOM_GROUPS, "EnumDomainGroups",
4931                 samr_dissect_enum_dom_groups_rqst,
4932                 samr_dissect_enum_dom_groups_reply },
4933         { SAMR_CREATE_USER_IN_DOMAIN, "CreateUser",
4934                 samr_dissect_create_group_in_domain_rqst,
4935                 samr_dissect_create_group_in_domain_reply },
4936         { SAMR_ENUM_DOM_USERS, "EnumDomainUsers",
4937                 samr_dissect_enum_dom_groups_rqst,
4938                 samr_dissect_enum_dom_groups_reply },
4939         { SAMR_CREATE_DOM_ALIAS, "CreateAlias",
4940                 samr_dissect_create_alias_in_domain_rqst,
4941                 samr_dissect_create_alias_in_domain_reply },
4942         { SAMR_ENUM_DOM_ALIASES, "EnumAliases",
4943                 samr_dissect_enum_dom_aliases_rqst,
4944                 samr_dissect_enum_dom_aliases_reply },
4945         { SAMR_GET_ALIAS_MEMBERSHIP, "GetAliasMem",
4946                 samr_dissect_get_alias_membership_rqst,
4947                 samr_dissect_get_alias_membership_reply },
4948         { SAMR_LOOKUP_NAMES, "LookupNames",
4949                 samr_dissect_lookup_names_rqst,
4950                 samr_dissect_lookup_names_reply },
4951         { SAMR_LOOKUP_RIDS, "LookupRIDs",
4952                 samr_dissect_lookup_rids_rqst,
4953                 samr_dissect_lookup_rids_reply },
4954         { SAMR_OPEN_GROUP, "OpenGroup",
4955                 samr_dissect_open_group_rqst,
4956                 samr_dissect_open_group_reply },
4957         { SAMR_QUERY_GROUPINFO, "QueryGroupInfo",
4958                 samr_dissect_query_information_group_rqst,
4959                 samr_dissect_query_information_group_reply },
4960         { SAMR_SET_GROUPINFO, "SetGroupInfo",
4961                 samr_dissect_set_information_group_rqst,
4962                 samr_dissect_set_information_group_reply },
4963         { SAMR_ADD_GROUPMEM, "AddGroupMem",
4964                 samr_dissect_add_member_to_group_rqst,
4965                 samr_dissect_add_member_to_group_reply },
4966         { SAMR_DELETE_DOM_GROUP, "DeleteDomainGroup",
4967                 samr_dissect_delete_dom_group_rqst,
4968                 samr_dissect_delete_dom_group_reply },
4969         { SAMR_DEL_GROUPMEM, "RemoveGroupMem",
4970                 samr_dissect_remove_member_from_group_rqst,
4971                 samr_dissect_remove_member_from_group_reply },
4972         { SAMR_QUERY_GROUPMEM, "QueryGroupMem",
4973                 samr_dissect_query_groupmem_rqst,
4974                 samr_dissect_query_groupmem_reply },
4975         { SAMR_SET_MEMBER_ATTRIBUTES_OF_GROUP, "SetMemberAttrGroup",
4976                 samr_dissect_set_member_attributes_of_group_rqst,
4977                 samr_dissect_set_member_attributes_of_group_reply },
4978         { SAMR_OPEN_ALIAS, "OpenAlias",
4979                 samr_dissect_open_alias_rqst,
4980                 samr_dissect_open_alias_reply },
4981         { SAMR_QUERY_ALIASINFO, "QueryAliasInfo",
4982                 samr_dissect_query_information_alias_rqst,
4983                 samr_dissect_query_information_alias_reply },
4984         { SAMR_SET_ALIASINFO, "SetAliasInfo",
4985                 samr_dissect_set_information_alias_rqst,
4986                 samr_dissect_set_information_alias_reply },
4987         { SAMR_DELETE_DOM_ALIAS, "DeleteAlias",
4988                 samr_dissect_delete_dom_alias_rqst,
4989                 samr_dissect_delete_dom_alias_reply },
4990         { SAMR_ADD_ALIASMEM, "AddAliasMem",
4991                 samr_dissect_add_alias_member_rqst,
4992                 samr_dissect_add_alias_member_reply },
4993         { SAMR_DEL_ALIASMEM, "RemoveAliasMem",
4994                 samr_dissect_remove_alias_member_rqst,
4995                 samr_dissect_remove_alias_member_reply },
4996         { SAMR_GET_MEMBERS_IN_ALIAS, "GetAliasMem",
4997                 samr_dissect_get_members_in_alias_rqst,
4998                 samr_dissect_get_members_in_alias_reply },
4999         { SAMR_OPEN_USER, "OpenUser",
5000                 samr_dissect_open_user_rqst,
5001                 samr_dissect_open_user_reply },
5002         { SAMR_DELETE_DOM_USER, "DeleteUser",
5003                 samr_dissect_delete_dom_user_rqst,
5004                 samr_dissect_delete_dom_user_reply },
5005         { SAMR_QUERY_USERINFO, "QueryUserInfo",
5006                 samr_dissect_query_information_user_rqst,
5007                 samr_dissect_query_information_user_reply },
5008         { SAMR_SET_USERINFO2, "SetUserInfo2",
5009                 samr_dissect_set_information_user2_rqst,
5010                 samr_dissect_set_information_user2_reply },
5011         { SAMR_CHANGE_PASSWORD_USER, "ChangePassword",
5012                 samr_dissect_change_password_user_rqst,
5013                 samr_dissect_change_password_user_reply },
5014         { SAMR_GET_GROUPS_FOR_USER, "GetGroups",
5015                 samr_dissect_get_groups_for_user_rqst,
5016                 samr_dissect_get_groups_for_user_reply },
5017         { SAMR_QUERY_DISPINFO, "QueryDispinfo",
5018                 samr_dissect_query_dispinfo_rqst,
5019                 samr_dissect_query_dispinfo_reply },
5020         { SAMR_GET_DISPLAY_ENUMERATION_INDEX, "GetDispEnumNDX",
5021                 samr_dissect_get_display_enumeration_index_rqst,
5022                 samr_dissect_get_display_enumeration_index_reply },
5023         { SAMR_TEST_PRIVATE_FUNCTIONS_DOMAIN, "TestPrivateFnsDomain",
5024                 samr_dissect_test_private_fns_domain_rqst,
5025                 samr_dissect_test_private_fns_domain_reply },
5026         { SAMR_TEST_PRIVATE_FUNCTIONS_USER, "TestPrivateFnsUser",
5027                 samr_dissect_test_private_fns_user_rqst,
5028                 samr_dissect_test_private_fns_user_reply },
5029         { SAMR_GET_USRDOM_PWINFO, "GetUserDomPwInfo",
5030                 samr_dissect_get_usrdom_pwinfo_rqst,
5031                 samr_dissect_get_usrdom_pwinfo_reply },
5032         { SAMR_REMOVE_MEMBER_FROM_FOREIGN_DOMAIN, "RemoveMemberForeignDomain",
5033                 samr_dissect_remove_member_from_foreign_domain_rqst,
5034                 samr_dissect_remove_member_from_foreign_domain_reply },
5035         { SAMR_QUERY_INFORMATION_DOMAIN2, "QueryDomInfo2",
5036                 samr_dissect_query_information_domain_rqst,
5037                 samr_dissect_query_information_domain_reply },
5038         { SAMR_UNKNOWN_2f, "Unknown 0x2f",
5039                 samr_dissect_unknown_2f_rqst,
5040                 samr_dissect_unknown_2f_reply },
5041         { SAMR_QUERY_DISPINFO2, "QueryDispinfo2",
5042                 samr_dissect_query_dispinfo_rqst,
5043                 samr_dissect_query_dispinfo_reply },
5044         { SAMR_GET_DISPLAY_ENUMERATION_INDEX2, "GetDispEnumNDX2",
5045                 samr_dissect_get_display_enumeration_index2_rqst,
5046                 samr_dissect_get_display_enumeration_index2_reply },
5047         { SAMR_CREATE_USER2_IN_DOMAIN, "CreateUser2",
5048                 samr_dissect_create_user2_in_domain_rqst,
5049                 samr_dissect_create_user2_in_domain_reply },
5050         { SAMR_QUERY_DISPINFO3, "QueryDispinfo3",
5051                 samr_dissect_query_dispinfo_rqst,
5052                 samr_dissect_query_dispinfo_reply },
5053         { SAMR_ADD_MULTIPLE_MEMBERS_TO_ALIAS, "AddAliasMemMultiple",
5054                 samr_dissect_add_multiple_members_to_alias_rqst,
5055                 samr_dissect_add_multiple_members_to_alias_reply },
5056         { SAMR_REMOVE_MULTIPLE_MEMBERS_FROM_ALIAS, "RemoveAliasMemMultiple",
5057                 samr_dissect_remove_multiple_members_from_alias_rqst,
5058                 samr_dissect_remove_multiple_members_from_alias_reply },
5059         { SAMR_OEM_CHANGE_PASSWORD_USER2, "OEMChangePassword2",
5060                 samr_dissect_oem_change_password_user2_rqst,
5061                 samr_dissect_oem_change_password_user2_reply },
5062         { SAMR_UNICODE_CHANGE_PASSWORD_USER2, "UnicodeChangePassword2",
5063                 samr_dissect_unicode_change_password_user2_rqst,
5064                 samr_dissect_unicode_change_password_user2_reply },
5065         { SAMR_GET_DOM_PWINFO, "GetDomainPasswordInfo",
5066                 samr_dissect_get_domain_password_information_rqst,
5067                 samr_dissect_get_domain_password_information_reply },
5068         { SAMR_CONNECT2, "Connect2",
5069                 samr_dissect_connect2_rqst,
5070                 samr_dissect_connect2_reply },
5071         { SAMR_SET_USERINFO, "SetUserInfo",
5072                 samr_dissect_set_information_user2_rqst,
5073                 samr_dissect_set_information_user2_reply },
5074         { SAMR_UNKNOWN_3B, "Unknown 0x3b",
5075                 samr_dissect_unknown_3b_rqst,
5076                 samr_dissect_unknown_3b_reply },
5077         { SAMR_UNKNOWN_3C, "Unknown 0x3c",
5078                 samr_dissect_unknown_3c_rqst,
5079                 samr_dissect_unknown_3c_reply },
5080         { SAMR_CONNECT4, "Connect4",
5081                 samr_dissect_connect4_rqst,
5082                 samr_dissect_connect2_reply },
5083         {0, NULL, NULL,  NULL }
5084 };
5085
5086 void
5087 proto_register_dcerpc_samr(void)
5088 {
5089         static hf_register_info hf[] = {
5090                 { &hf_samr_opnum,
5091                   { "Operation", "samr.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
5092                 { &hf_samr_hnd,
5093                   { "Context Handle", "samr.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
5094                 { &hf_samr_group,
5095                   { "Group", "samr.group", FT_UINT32, BASE_DEC, NULL, 0x0, "Group", HFILL }},
5096                 { &hf_samr_rid,
5097                   { "Rid", "samr.rid", FT_UINT32, BASE_DEC, NULL, 0x0, "RID", HFILL }},
5098                 { &hf_samr_type,
5099                   { "Type", "samr.type", FT_UINT32, BASE_HEX, NULL, 0x0, "Type", HFILL }},
5100                 { &hf_samr_alias,
5101                   { "Alias", "samr.alias", FT_UINT32, BASE_HEX, NULL, 0x0, "Alias", HFILL }},
5102                 { &hf_samr_rid_attrib,
5103                   { "Rid Attrib", "samr.rid.attrib", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
5104                 { &hf_samr_attrib,
5105                   { "Attributes", "samr.attr", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
5106                 { &hf_samr_rc,
5107                   { "Return code", "samr.rc", FT_UINT32, BASE_HEX, VALS (NT_errors), 0x0, "", HFILL }},
5108
5109         { &hf_samr_level,
5110                 { "Level", "samr.level", FT_UINT16, BASE_DEC,
5111                 NULL, 0x0, "Level requested/returned for Information", HFILL }},
5112         { &hf_samr_start_idx,
5113                 { "Start Idx", "samr.start_idx", FT_UINT32, BASE_DEC,
5114                 NULL, 0x0, "Start Index for returned Information", HFILL }},
5115
5116         { &hf_samr_entries,
5117                 { "Entries", "samr.entries", FT_UINT32, BASE_DEC,
5118                 NULL, 0x0, "Number of entries to return", HFILL }},
5119
5120         { &hf_samr_max_entries,
5121                 { "Max Entries", "samr.max_entries", FT_UINT32, BASE_DEC,
5122                 NULL, 0x0, "Maximum number of entries", HFILL }},
5123
5124         { &hf_samr_pref_maxsize,
5125                 { "Pref MaxSize", "samr.pref_maxsize", FT_UINT32, BASE_DEC,
5126                 NULL, 0x0, "Maximum Size of data to return", HFILL }},
5127
5128         { &hf_samr_total_size,
5129                 { "Total Size", "samr.total_size", FT_UINT32, BASE_DEC,
5130                 NULL, 0x0, "Total size of data", HFILL }},
5131
5132         { &hf_samr_bad_pwd_count,
5133                 { "Bad Pwd Count", "samr.bad_pwd_count", FT_UINT16, BASE_DEC,
5134                 NULL, 0x0, "Number of bad pwd entries for this user", HFILL }},
5135
5136         { &hf_samr_logon_count,
5137                 { "Logon Count", "samr.logon_count", FT_UINT16, BASE_DEC,
5138                 NULL, 0x0, "Number of logons for this user", HFILL }},
5139
5140         { &hf_samr_ret_size,
5141                 { "Returned Size", "samr.ret_size", FT_UINT32, BASE_DEC,
5142                 NULL, 0x0, "Number of returned objects in this PDU", HFILL }},
5143
5144         { &hf_samr_index,
5145                 { "Index", "samr.index", FT_UINT32, BASE_DEC,
5146                 NULL, 0x0, "Index", HFILL }},
5147
5148         { &hf_samr_count,
5149           { "Count", "samr.count", FT_UINT32, BASE_DEC, NULL, 0x0, "Number of elements in following array", HFILL }},
5150
5151         { &hf_samr_alias_name,
5152                 { "Alias Name", "samr.alias_name", FT_STRING, BASE_NONE,
5153                 NULL, 0, "Name of Alias", HFILL }},
5154
5155         { &hf_samr_group_name,
5156                 { "Group Name", "samr.group_name", FT_STRING, BASE_NONE,
5157                 NULL, 0, "Name of Group", HFILL }},
5158
5159         { &hf_samr_acct_name,
5160                 { "Account Name", "samr.acct_name", FT_STRING, BASE_NONE,
5161                 NULL, 0, "Name of Account", HFILL }},
5162
5163         { &hf_samr_server,
5164                 { "Server", "samr.server", FT_STRING, BASE_NONE,
5165                 NULL, 0, "Name of Server", HFILL }},
5166
5167         { &hf_samr_domain,
5168                 { "Domain", "samr.domain", FT_STRING, BASE_NONE,
5169                 NULL, 0, "Name of Domain", HFILL }},
5170
5171         { &hf_samr_controller,
5172                 { "DC", "samr.dc", FT_STRING, BASE_NONE,
5173                 NULL, 0, "Name of Domain Controller", HFILL }},
5174
5175         { &hf_samr_full_name,
5176                 { "Full Name", "samr.full_name", FT_STRING, BASE_NONE,
5177                 NULL, 0, "Full Name of Account", HFILL }},
5178
5179         { &hf_samr_home,
5180                 { "Home", "samr.home", FT_STRING, BASE_NONE,
5181                 NULL, 0, "Home directory for this user", HFILL }},
5182
5183         { &hf_samr_home_drive,
5184                 { "Home Drive", "samr.home_drive", FT_STRING, BASE_NONE,
5185                 NULL, 0, "Home drive for this user", HFILL }},
5186
5187         { &hf_samr_script,
5188                 { "Script", "samr.script", FT_STRING, BASE_NONE,
5189                 NULL, 0, "Login script for this user", HFILL }},
5190
5191         { &hf_samr_workstations,
5192                 { "Workstations", "samr.workstations", FT_STRING, BASE_NONE,
5193                 NULL, 0, "", HFILL }},
5194
5195         { &hf_samr_profile,
5196                 { "Profile", "samr.profile", FT_STRING, BASE_NONE,
5197                 NULL, 0, "Profile for this user", HFILL }},
5198
5199         { &hf_samr_acct_desc,
5200                 { "Account Desc", "samr.acct_desc", FT_STRING, BASE_NONE,
5201                 NULL, 0, "Account Description", HFILL }},
5202
5203         { &hf_samr_comment,
5204                 { "Comment", "samr.comment", FT_STRING, BASE_NONE,
5205                 NULL, 0, "Comment", HFILL }},
5206
5207         { &hf_samr_parameters,
5208                 { "Parameters", "samr.parameters", FT_STRING, BASE_NONE,
5209                 NULL, 0, "Parameters", HFILL }},
5210
5211         { &hf_samr_unknown_string,
5212                 { "Unknown string", "samr.unknown_string", FT_STRING, BASE_NONE,
5213                 NULL, 0, "Unknown string. If you know what this is, contact ethereal developers.", HFILL }},
5214
5215         { &hf_samr_unknown_hyper,
5216                 { "Unknown hyper", "samr.unknown.hyper", FT_UINT64, BASE_HEX,
5217                 NULL, 0x0, "Unknown hyper. If you know what this is, contact ethereal developers.", HFILL }},
5218         { &hf_samr_unknown_long,
5219                 { "Unknown long", "samr.unknown.long", FT_UINT32, BASE_HEX,
5220                 NULL, 0x0, "Unknown long. If you know what this is, contact ethereal developers.", HFILL }},
5221
5222         { &hf_samr_unknown_short,
5223                 { "Unknown short", "samr.unknown.short", FT_UINT16, BASE_HEX,
5224                 NULL, 0x0, "Unknown short. If you know what this is, contact ethereal developers.", HFILL }},
5225
5226         { &hf_samr_unknown_char,
5227                 { "Unknown char", "samr.unknown.char", FT_UINT8, BASE_HEX,
5228                 NULL, 0x0, "Unknown char. If you know what this is, contact ethereal developers.", HFILL }},
5229
5230         { &hf_samr_revision,
5231                 { "Revision", "samr.revision", FT_UINT64, BASE_HEX,
5232                 NULL, 0x0, "Revision number for this structure", HFILL }},
5233
5234         { &hf_samr_nt_pwd_set,
5235                 { "NT Pwd Set", "samr.nt_pwd_set", FT_UINT8, BASE_HEX,
5236                 NULL, 0x0, "Flag indicating whether the NT password has been set", HFILL }},
5237
5238         { &hf_samr_lm_pwd_set,
5239                 { "LM Pwd Set", "samr.lm_pwd_set", FT_UINT8, BASE_HEX,
5240                 NULL, 0x0, "Flag indicating whether the LanManager password has been set", HFILL }},
5241
5242         { &hf_samr_pwd_expired,
5243                 { "Expired flag", "samr.pwd_Expired", FT_UINT8, BASE_HEX,
5244                 NULL, 0x0, "Flag indicating if the password for this account has expired or not", HFILL }},
5245
5246         { &hf_samr_access,
5247                 { "Access Mask", "samr.access", FT_UINT32, BASE_HEX,
5248                 NULL, 0x0, "Access", HFILL }},
5249
5250         { &hf_samr_access_granted,
5251                 { "Access Granted", "samr.access_granted", FT_UINT32, BASE_HEX,
5252                 NULL, 0x0, "Access Granted", HFILL }},
5253
5254         { &hf_samr_crypt_password, {
5255                 "Password", "samr.crypt_password", FT_BYTES, BASE_HEX,
5256                 NULL, 0, "Encrypted Password", HFILL }},
5257
5258         { &hf_samr_crypt_hash, {
5259                 "Hash", "samr.crypt_hash", FT_BYTES, BASE_HEX,
5260                 NULL, 0, "Encrypted Hash", HFILL }},
5261
5262         { &hf_samr_lm_verifier, {
5263                 "Verifier", "samr.lm_password_verifier", FT_BYTES, BASE_HEX,
5264                 NULL, 0, "Lan Manager Password Verifier", HFILL }},
5265
5266         { &hf_samr_nt_verifier, {
5267                 "Verifier", "samr.nt_password_verifier", FT_BYTES, BASE_HEX,
5268                 NULL, 0, "NT Password Verifier", HFILL }},
5269
5270         { &hf_samr_lm_passchange_block, {
5271                 "Encrypted Block", "samr.lm_passchange_block", FT_BYTES, 
5272                 BASE_HEX, NULL, 0, "Lan Manager Password Change Block",
5273                 HFILL }},
5274
5275         { &hf_samr_nt_passchange_block, {
5276                 "Encrypted Block", "samr.nt_passchange_block", FT_BYTES, 
5277                 BASE_HEX, NULL, 0, "NT Password Change Block", HFILL }},
5278
5279         { &hf_samr_nt_passchange_block_decrypted, {
5280                 "Decrypted Block", "samr.nt_passchange_block_decrypted",
5281                 FT_BYTES, BASE_HEX, NULL, 0, 
5282                 "NT Password Change Decrypted Block", HFILL }},
5283
5284         { &hf_samr_nt_passchange_block_newpass, {
5285                 "New NT Password", "samr.nt_passchange_block_new_ntpassword", 
5286                 FT_STRING, BASE_NONE, NULL, 0, "New NT Password", HFILL }},
5287
5288         { &hf_samr_nt_passchange_block_newpass_len, {
5289                 "New NT Unicode Password length", 
5290                 "samr.nt_passchange_block_new_ntpassword_len", FT_UINT32, 
5291                 BASE_DEC, NULL, 0, "New NT Password Unicode Length", HFILL }},
5292
5293         { &hf_samr_nt_passchange_block_pseudorandom, {
5294                 "Pseudorandom data", "samr.nt_passchange_block_pseudorandom",
5295                 FT_BYTES, BASE_HEX, NULL, 0, "Pseudorandom data", HFILL }},
5296
5297         { &hf_samr_lm_change, {
5298                 "LM Change", "samr.lm_change", FT_UINT8, BASE_HEX,
5299                 NULL, 0, "LM Change value", HFILL }},
5300
5301         { &hf_samr_max_pwd_age,
5302                 { "Max Pwd Age", "samr.max_pwd_age", FT_RELATIVE_TIME, BASE_NONE,
5303                 NULL, 0, "Maximum Password Age before it expires", HFILL }},
5304
5305         { &hf_samr_min_pwd_age,
5306                 { "Min Pwd Age", "samr.min_pwd_age", FT_RELATIVE_TIME, BASE_NONE,
5307                 NULL, 0, "Minimum Password Age before it can be changed", HFILL }},
5308         { &hf_samr_unknown_time,
5309                 { "Unknown time", "samr.unknown_time", FT_ABSOLUTE_TIME, BASE_NONE,
5310                 NULL, 0, "Unknown NT TIME, contact ethereal developers if you know what this is", HFILL }},
5311         { &hf_samr_logon_time,
5312                 { "Logon Time", "samr.logon_time", FT_ABSOLUTE_TIME, BASE_NONE,
5313                 NULL, 0, "Time for last time this user logged on", HFILL }},
5314         { &hf_samr_kickoff_time,
5315                 { "Kickoff Time", "samr.kickoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
5316                 NULL, 0, "Time when this user will be kicked off", HFILL }},
5317         { &hf_samr_logoff_time,
5318                 { "Logoff Time", "samr.logoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
5319                 NULL, 0, "Time for last time this user logged off", HFILL }},
5320         { &hf_samr_pwd_last_set_time,
5321                 { "PWD Last Set", "samr.pwd_last_set_time", FT_ABSOLUTE_TIME, BASE_NONE,
5322                 NULL, 0, "Last time this users password was changed", HFILL }},
5323         { &hf_samr_pwd_can_change_time,
5324                 { "PWD Can Change", "samr.pwd_can_change_time", FT_ABSOLUTE_TIME, BASE_NONE,
5325                 NULL, 0, "When this users password may be changed", HFILL }},
5326         { &hf_samr_pwd_must_change_time,
5327                 { "PWD Must Change", "samr.pwd_must_change_time", FT_ABSOLUTE_TIME, BASE_NONE,
5328                 NULL, 0, "When this users password must be changed", HFILL }},
5329         { &hf_samr_acct_expiry_time,
5330                 { "Acct Expiry", "samr.acct_expiry_time", FT_ABSOLUTE_TIME, BASE_NONE,
5331                 NULL, 0, "When this user account expires", HFILL }},
5332
5333         { &hf_samr_min_pwd_len, {
5334                 "Min Pwd Len", "samr.min_pwd_len", FT_UINT16, BASE_DEC,
5335                 NULL, 0, "Minimum Password Length", HFILL }},
5336         { &hf_samr_pwd_history_len, {
5337                 "Pwd History Len", "samr.pwd_history_len", FT_UINT16, BASE_DEC,
5338                 NULL, 0, "Password History Length", HFILL }},
5339         { &hf_samr_num_users, {
5340                 "Num Users", "samr.num_users", FT_UINT32, BASE_DEC,
5341                 NULL, 0, "Number of users in this domain", HFILL }},
5342         { &hf_samr_num_groups, {
5343                 "Num Groups", "samr.num_groups", FT_UINT32, BASE_DEC,
5344                 NULL, 0, "Number of groups in this domain", HFILL }},
5345         { &hf_samr_num_aliases, {
5346                 "Num Aliases", "samr.num_aliases", FT_UINT32, BASE_DEC,
5347                 NULL, 0, "Number of aliases in this domain", HFILL }},
5348         { &hf_samr_info_type, {
5349                 "Info Type", "samr.info_type", FT_UINT32, BASE_DEC,
5350                 NULL, 0, "Information Type", HFILL }},
5351         { &hf_samr_resume_hnd, {
5352                 "Resume Hnd", "samr.resume_hnd", FT_UINT32, BASE_DEC,
5353                 NULL, 0, "Resume handle", HFILL }},
5354         { &hf_samr_country, {
5355                 "Country", "samr.country", FT_UINT16, BASE_DEC,
5356                 VALS(ms_country_codes), 0, "Country setting for this user", HFILL }},
5357         { &hf_samr_codepage, {
5358                 "Codepage", "samr.codepage", FT_UINT16, BASE_DEC,
5359                 NULL, 0, "Codepage setting for this user", HFILL }},
5360         { &hf_samr_divisions, {
5361                 "Divisions", "samr.divisions", FT_UINT16, BASE_DEC,
5362                 NULL, 0, "Number of divisions for LOGON_HOURS", HFILL }},
5363
5364         { &hf_nt_acct_ctrl,
5365                 { "Acct Ctrl", "nt.acct_ctrl", FT_UINT32, BASE_HEX,
5366                 NULL, 0x0, "Acct CTRL", HFILL }},
5367
5368         { &hf_nt_acb_disabled, {
5369                 "", "nt.acb.disabled", FT_BOOLEAN, 32,
5370                 TFS(&tfs_nt_acb_disabled), 0x0001, "If this account is enabled or disabled", HFILL }},
5371
5372         { &hf_nt_acb_homedirreq, {
5373                 "", "nt.acb.homedirreq", FT_BOOLEAN, 32,
5374                 TFS(&tfs_nt_acb_homedirreq), 0x0002, "Is hom,edirs required for this account?", HFILL }},
5375
5376         { &hf_nt_acb_pwnotreq, {
5377                 "", "nt.acb.pwnotreq", FT_BOOLEAN, 32,
5378                 TFS(&tfs_nt_acb_pwnotreq), 0x0004, "If a password is required for this account?", HFILL }},
5379
5380         { &hf_nt_acb_tempdup, {
5381                 "", "nt.acb.tempdup", FT_BOOLEAN, 32,
5382                 TFS(&tfs_nt_acb_tempdup), 0x0008, "If this is a temporary duplicate account", HFILL }},
5383
5384         { &hf_nt_acb_normal, {
5385                 "", "nt.acb.normal", FT_BOOLEAN, 32,
5386                 TFS(&tfs_nt_acb_normal), 0x0010, "If this is a normal user account", HFILL }},
5387
5388         { &hf_nt_acb_mns, {
5389                 "", "nt.acb.mns", FT_BOOLEAN, 32,
5390                 TFS(&tfs_nt_acb_mns), 0x0020, "MNS logon user account", HFILL }},
5391
5392         { &hf_nt_acb_domtrust, {
5393                 "", "nt.acb.domtrust", FT_BOOLEAN, 32,
5394                 TFS(&tfs_nt_acb_domtrust), 0x0040, "Interdomain trust account", HFILL }},
5395
5396         { &hf_nt_acb_wstrust, {
5397                 "", "nt.acb.wstrust", FT_BOOLEAN, 32,
5398                 TFS(&tfs_nt_acb_wstrust), 0x0080, "Workstation trust account", HFILL }},
5399
5400         { &hf_nt_acb_svrtrust, {
5401                 "", "nt.acb.svrtrust", FT_BOOLEAN, 32,
5402                 TFS(&tfs_nt_acb_svrtrust), 0x0100, "Server trust account", HFILL }},
5403
5404         { &hf_nt_acb_pwnoexp, {
5405                 "", "nt.acb.pwnoexp", FT_BOOLEAN, 32,
5406                 TFS(&tfs_nt_acb_pwnoexp), 0x0200, "If this account expires or not", HFILL }},
5407
5408         { &hf_nt_acb_autolock, {
5409                 "", "nt.acb.autolock", FT_BOOLEAN, 32,
5410                 TFS(&tfs_nt_acb_autolock), 0x0400, "If this account has been autolocked", HFILL }},
5411
5412         /* Object specific access rights */
5413
5414         { &hf_access_domain_lookup_info1,
5415           { "Lookup info1", "samr_access_mask.domain_lookup_info1",
5416             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5417             DOMAIN_ACCESS_LOOKUP_INFO_1, "Lookup info1", HFILL }},
5418
5419         { &hf_access_domain_set_info1,
5420           { "Set info1", "samr_access_mask.domain_set_info1",
5421             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5422             DOMAIN_ACCESS_SET_INFO_1, "Set info1", HFILL }},
5423
5424         { &hf_access_domain_lookup_info2,
5425           { "Lookup info2", "samr_access_mask.domain_lookup_info2",
5426             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5427             DOMAIN_ACCESS_LOOKUP_INFO_2, "Lookup info2", HFILL }},
5428
5429         { &hf_access_domain_set_info2,
5430           { "Set info2", "samr_access_mask.domain_set_info2",
5431             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5432             DOMAIN_ACCESS_SET_INFO_2, "Set info2", HFILL }},
5433
5434         { &hf_access_domain_create_user,
5435           { "Create user", "samr_access_mask.domain_create_user",
5436             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5437             DOMAIN_ACCESS_CREATE_USER, "Create user", HFILL }},
5438
5439         { &hf_access_domain_create_group,
5440           { "Create group", "samr_access_mask.domain_create_group",
5441             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5442             DOMAIN_ACCESS_CREATE_GROUP, "Create group", HFILL }},
5443
5444         { &hf_access_domain_create_alias,
5445           { "Create alias", "samr_access_mask.domain_create_alias",
5446             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5447             DOMAIN_ACCESS_CREATE_ALIAS, "Create alias", HFILL }},
5448
5449         { &hf_access_domain_lookup_alias_by_mem,
5450           { "Lookup alias", "samr_access_mask.domain_lookup_alias_by_mem",
5451             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5452             DOMAIN_ACCESS_LOOKUP_ALIAS, "Lookup alias", HFILL }},
5453
5454         { &hf_access_domain_enum_accounts,
5455           { "Enum accounts", "samr_access_mask.domain_enum_accounts",
5456             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5457             DOMAIN_ACCESS_ENUM_ACCOUNTS, "Enum accounts", HFILL }},
5458
5459         { &hf_access_domain_open_account,
5460           { "Open account", "samr_access_mask.domain_open_account",
5461             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5462             DOMAIN_ACCESS_OPEN_ACCOUNT, "Open account", HFILL }},
5463
5464         { &hf_access_domain_set_info3,
5465           { "Set info3", "samr_access_mask.domain_set_info3",
5466             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5467             DOMAIN_ACCESS_SET_INFO_3, "Set info3", HFILL }},
5468
5469         { &hf_access_user_get_name_etc,
5470           { "Get name, etc", "samr_access_mask.user_get_name_etc",
5471             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5472             USER_ACCESS_GET_NAME_ETC, "Get name, etc", HFILL }},
5473
5474         { &hf_access_user_get_locale,
5475           { "Get locale", "samr_access_mask.user_get_locale",
5476             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5477             USER_ACCESS_GET_LOCALE, "Get locale", HFILL }},
5478
5479         { &hf_access_user_get_loc_com,
5480           { "Set loc com", "samr_access_mask.user_set_loc_com",
5481             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5482             USER_ACCESS_SET_LOC_COM, "Set loc com", HFILL }},
5483
5484         { &hf_access_user_get_logoninfo,
5485           { "Get logon info", "samr_access_mask.user_get_logoninfo",
5486             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5487             USER_ACCESS_GET_LOGONINFO, "Get logon info", HFILL }},
5488
5489         { &hf_access_user_get_attributes,
5490           { "Get attributes", "samr_access_mask.user_get_attributes",
5491             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5492             USER_ACCESS_GET_ATTRIBUTES, "Get attributes", HFILL }},
5493
5494         { &hf_access_user_set_attributes,
5495           { "Set attributes", "samr_access_mask.user_set_attributes",
5496             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5497             USER_ACCESS_SET_ATTRIBUTES, "Set attributes", HFILL }},
5498
5499         { &hf_access_user_change_password,
5500           { "Change password", "samr_access_mask.user_change_password",
5501             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5502             USER_ACCESS_CHANGE_PASSWORD, "Change password", HFILL }},
5503
5504         { &hf_access_user_set_password,
5505           { "Set password", "samr_access_mask.user_set_password",
5506             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5507             USER_ACCESS_SET_PASSWORD, "Set password", HFILL }},
5508
5509         { &hf_access_user_get_groups,
5510           { "Get groups", "samr_access_mask.user_get_groups",
5511             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5512             USER_ACCESS_GET_GROUPS, "Get groups", HFILL }},
5513
5514         { &hf_access_user_get_group_membership,
5515           { "Get group membership", "samr_access_mask.user_get_group_membership",
5516             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5517             USER_ACCESS_GET_GROUP_MEMBERSHIP, "Get group membership", HFILL }},
5518
5519         { &hf_access_user_change_group_membership,
5520           { "Change group membership", "samr_access_mask.user_change_group_membership",
5521             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5522             USER_ACCESS_CHANGE_GROUP_MEMBERSHIP, "Change group membership", HFILL }},
5523
5524         { &hf_access_group_lookup_info,
5525           { "Lookup info", "samr_access_mask.group_lookup_info",
5526             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5527             GROUP_ACCESS_LOOKUP_INFO, "Lookup info", HFILL }},
5528
5529         { &hf_access_group_set_info,
5530           { "Get info", "samr_access_mask.group_set_info",
5531             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5532             GROUP_ACCESS_SET_INFO, "Get info", HFILL }},
5533
5534         { &hf_access_group_add_member,
5535           { "Add member", "samr_access_mask.group_add_member",
5536             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5537             GROUP_ACCESS_ADD_MEMBER, "Add member", HFILL }},
5538
5539         { &hf_access_group_remove_member,
5540           { "Remove member", "samr_access_mask.group_remove_member",
5541             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5542             GROUP_ACCESS_REMOVE_MEMBER, "Remove member", HFILL }},
5543
5544         { &hf_access_group_get_members,
5545           { "Get members", "samr_access_mask.group_get_members",
5546             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5547             GROUP_ACCESS_GET_MEMBERS, "Get members", HFILL }},
5548
5549         { &hf_access_alias_add_member,
5550           { "Add member", "samr_access_mask.alias_add_member",
5551             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5552             ALIAS_ACCESS_ADD_MEMBER, "Add member", HFILL }},
5553
5554         { &hf_access_alias_remove_member,
5555           { "Remove member", "samr_access_mask.alias_remove_member",
5556             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5557             ALIAS_ACCESS_REMOVE_MEMBER, "Remove member", HFILL }},
5558
5559         { &hf_access_alias_get_members,
5560           { "Get members", "samr_access_mask.alias_get_members",
5561             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5562             ALIAS_ACCESS_GET_MEMBERS, "Get members", HFILL }},
5563
5564         { &hf_access_alias_lookup_info,
5565           { "Lookup info", "samr_access_mask.alias_lookup_info",
5566             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5567             ALIAS_ACCESS_LOOKUP_INFO, "Lookup info", HFILL }},
5568
5569         { &hf_access_alias_set_info,
5570           { "Set info", "samr_access_mask.alias_set_info",
5571             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5572             ALIAS_ACCESS_SET_INFO, "Set info", HFILL }},
5573
5574         { &hf_access_connect_connect_to_server,
5575           { "Connect to server", "samr_access_mask.connect_connect_to_server",
5576             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5577             SAMR_ACCESS_CONNECT_TO_SERVER, "Connect to server", HFILL }},
5578
5579         { &hf_access_connect_shutdown_server,
5580           { "Shutdown server", "samr_access_mask.connect_shutdown_server",
5581             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5582             SAMR_ACCESS_SHUTDOWN_SERVER, "Shutdown server", HFILL }},
5583
5584         { &hf_access_connect_initialize_server,
5585           { "Initialize server", "samr_access_mask.connect_initialize_server",
5586             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5587             SAMR_ACCESS_INITIALIZE_SERVER, "Initialize server", HFILL }},
5588
5589         { &hf_access_connect_create_domain,
5590           { "Create domain", "samr_access_mask.connect_create_domain",
5591             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5592             SAMR_ACCESS_CREATE_DOMAIN, "Create domain", HFILL }},
5593
5594         { &hf_access_connect_enum_domains,
5595           { "Enum domains", "samr_access_mask.connect_enum_domains",
5596             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5597             SAMR_ACCESS_ENUM_DOMAINS, "Enum domains", HFILL }},
5598
5599         { &hf_access_connect_open_domain,
5600           { "Open domain", "samr_access_mask.connect_open_domain",
5601             FT_BOOLEAN, 32, TFS(&flags_set_truth),
5602             SAMR_ACCESS_OPEN_DOMAIN, "Open domain", HFILL }}
5603
5604         };
5605
5606         static gint *ett[] = {
5607                 &ett_dcerpc_samr,
5608                 &ett_samr_user_dispinfo_1,
5609                 &ett_samr_user_dispinfo_1_array,
5610                 &ett_samr_user_dispinfo_2,
5611                 &ett_samr_user_dispinfo_2_array,
5612                 &ett_samr_group_dispinfo,
5613                 &ett_samr_group_dispinfo_array,
5614                 &ett_samr_ascii_dispinfo,
5615                 &ett_samr_ascii_dispinfo_array,
5616                 &ett_samr_display_info,
5617                 &ett_samr_password_info,
5618                 &ett_samr_server,
5619                 &ett_samr_user_group,
5620                 &ett_samr_user_group_array,
5621                 &ett_samr_alias_info,
5622                 &ett_samr_group_info,
5623                 &ett_samr_domain_info_1,
5624                 &ett_samr_domain_info_2,
5625                 &ett_samr_domain_info_8,
5626                 &ett_samr_replication_status,
5627                 &ett_samr_domain_info_11,
5628                 &ett_samr_domain_info_13,
5629                 &ett_samr_domain_info,
5630                 &ett_samr_sid_pointer,
5631                 &ett_samr_sid_array,
5632                 &ett_samr_index_array,
5633                 &ett_samr_idx_and_name,
5634                 &ett_samr_idx_and_name_array,
5635                 &ett_samr_logon_hours,
5636                 &ett_samr_logon_hours_hours,
5637                 &ett_samr_user_info_1,
5638                 &ett_samr_user_info_2,
5639                 &ett_samr_user_info_3,
5640                 &ett_samr_user_info_5,
5641                 &ett_samr_user_info_6,
5642                 &ett_samr_user_info_18,
5643                 &ett_samr_user_info_19,
5644                 &ett_samr_buffer_buffer,
5645                 &ett_samr_buffer,
5646                 &ett_samr_user_info_21,
5647                 &ett_samr_user_info_22,
5648                 &ett_samr_user_info_23,
5649                 &ett_samr_user_info_24,
5650                 &ett_samr_user_info,
5651                 &ett_samr_member_array_types,
5652                 &ett_samr_member_array_rids,
5653                 &ett_samr_member_array,
5654                 &ett_samr_names,
5655                 &ett_samr_rids,
5656                 &ett_samr_sid_and_attributes_array,
5657                 &ett_samr_sid_and_attributes,
5658                 &ett_nt_acct_ctrl,
5659         };
5660         module_t *dcerpc_samr_module;
5661
5662         proto_dcerpc_samr = proto_register_protocol(
5663                 "Microsoft Security Account Manager", "SAMR", "samr");
5664
5665         proto_register_field_array (proto_dcerpc_samr, hf, array_length (hf));
5666         proto_register_subtree_array(ett, array_length(ett));
5667
5668         dcerpc_samr_module = prefs_register_protocol(proto_dcerpc_samr, NULL);
5669         
5670         prefs_register_string_preference(dcerpc_samr_module, "nt_password",
5671                                          "NT Password",
5672                                          "NT Password (used to verify password changes)",
5673                                          &nt_password);
5674 }
5675
5676 void
5677 proto_reg_handoff_dcerpc_samr(void)
5678 {
5679         header_field_info *hf_info;
5680
5681         /* Register protocol as dcerpc */
5682
5683         dcerpc_init_uuid(proto_dcerpc_samr, ett_dcerpc_samr, &uuid_dcerpc_samr,
5684                          ver_dcerpc_samr, dcerpc_samr_dissectors, hf_samr_opnum);
5685
5686         /* Set opnum strings from subdissector list */
5687
5688         hf_info = proto_registrar_get_nth(hf_samr_opnum);
5689         hf_info->strings = value_string_from_subdissectors(
5690                 dcerpc_samr_dissectors, array_length(dcerpc_samr_dissectors));
5691 }