DCE RPC enhancements, and SAMR improvements, from Ronnie Sahlberg.
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 29 Jan 2002 09:13:28 +0000 (09:13 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 29 Jan 2002 09:13:28 +0000 (09:13 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@4618 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
packet-dcerpc-ndr.c
packet-dcerpc-nt.c
packet-dcerpc-nt.h
packet-dcerpc-samr.c
packet-dcerpc-samr.h
packet-dcerpc.c
packet-dcerpc.h

diff --git a/AUTHORS b/AUTHORS
index d1c1485241610bd3ff31d6d9be940027cbdd8592..2d3aec64c6b26e2c7df990906878231d46a6a0d1 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -571,9 +571,7 @@ Ronnie Sahlberg <sahlberg[AT]optushome.com.au> {
        NDMPv3 support
        Add time between request and reply as a field to ONC RPC replies
        File handle to file name resolution in NFS and realted protocols
-       In DCE RPC dissector, add support for finding the response that
-           matches a request
-       NDR pointer handling in DCE RPC
+       DCE RPC enhancements
        SAMR updates
 }
 
index 6e5dc2d9e1561b0c5e18c3252609ea8aa23902fd..e0028cf3891526e6e654576362a6bc184ea46be5 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for DCERPC NDR dissection
  * Copyright 2001, Todd Sabin <tas@webspan.net>
  *
- * $Id: packet-dcerpc-ndr.c,v 1.4 2002/01/25 08:35:59 guy Exp $
+ * $Id: packet-dcerpc-ndr.c,v 1.5 2002/01/29 09:13:28 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -50,6 +50,14 @@ dissect_ndr_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                    proto_tree *tree, char *drep, 
                    int hfindex, guint8 *pdata)
 {
+    dcerpc_info *di;
+
+    di=pinfo->private_data;
+    if(di->conformant_run){
+      /* just a run to handle conformant arrays, no scalars to dissect */
+      return offset;
+    }
+
     /* no alignment needed */
     return dissect_dcerpc_uint8 (tvb, offset, pinfo, 
                                  tree, drep, hfindex, pdata);
@@ -60,6 +68,15 @@ dissect_ndr_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                     proto_tree *tree, char *drep, 
                     int hfindex, guint16 *pdata)
 {
+    dcerpc_info *di;
+
+    di=pinfo->private_data;
+    if(di->conformant_run){
+      /* just a run to handle conformant arrays, no scalars to dissect */
+      return offset;
+    }
+
+
     if (offset % 2) {
         offset++;
     }
@@ -72,6 +89,15 @@ dissect_ndr_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                     proto_tree *tree, char *drep, 
                     int hfindex, guint32 *pdata)
 {
+    dcerpc_info *di;
+
+    di=pinfo->private_data;
+    if(di->conformant_run){
+      /* just a run to handle conformant arrays, no scalars to dissect */
+      return offset;
+    }
+
+
     if (offset % 4) {
         offset += 4 - (offset % 4);
     }
@@ -79,12 +105,39 @@ dissect_ndr_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                                   tree, drep, hfindex, pdata);
 }
 
+int
+dissect_ndr_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                    proto_tree *tree, char *drep, 
+                    int hfindex, unsigned char *pdata)
+{
+    dcerpc_info *di;
+
+    di=pinfo->private_data;
+    if(di->conformant_run){
+      /* just a run to handle conformant arrays, no scalars to dissect */
+      return offset;
+    }
+
+    if (offset % 4) {
+        offset += 4 - (offset % 4);
+    }
+    return dissect_dcerpc_uint64 (tvb, offset, pinfo, 
+                                  tree, drep, hfindex, pdata);
+}
+
 int
 dissect_ndr_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                     proto_tree *tree, char *drep, 
                     int hfindex, e_uuid_t *pdata)
 {
     e_uuid_t uuid;
+    dcerpc_info *di;
+
+    di=pinfo->private_data;
+    if(di->conformant_run){
+      /* just a run to handle conformant arrays, no scalars to dissect */
+      return offset;
+    }
 
     /* uuid's are aligned to 4 bytes, due to initial uint32 in struct */
     if (offset % 4) {
@@ -113,6 +166,13 @@ dissect_ndr_ctx_hnd (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                      int hfindex, e_ctx_hnd *pdata)
 {
     e_ctx_hnd ctx_hnd;
+    dcerpc_info *di;
+
+    di=pinfo->private_data;
+    if(di->conformant_run){
+      /* just a run to handle conformant arrays, no scalars to dissect */
+      return offset;
+    }
 
     if (offset % 4) {
         offset += 4 - (offset % 4);
index f4aa4396fe1c7a79fcc1ab1fdce046572de5962c..d4ad0481bf85560c0814b61d5d07511bfdc6d4a7 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for DCERPC over SMB packet disassembly
  * Copyright 2001, Tim Potter <tpot@samba.org>
  *
- * $Id: packet-dcerpc-nt.c,v 1.5 2002/01/25 08:35:59 guy Exp $
+ * $Id: packet-dcerpc-nt.c,v 1.6 2002/01/29 09:13:28 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -393,158 +393,3 @@ int prs_policy_hnd(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 
 
-/* functions to dissect a UNICODE_STRING structure, common to many 
-   NT services
-   struct {
-     short len;
-     short size;
-     [size_is(size/2), length_is(len/2), ptr] unsigned short *string;
-   } UNICODE_STRING;
-
-   these variables can be found in packet-dcerpc-samr.c 
-*/
-extern int hf_nt_str_len;
-extern int hf_nt_str_off;
-extern int hf_nt_str_max_len;
-extern int hf_nt_string_length;
-extern int hf_nt_string_size;
-extern gint ett_nt_unicode_string;
-
-static int
-dissect_ndr_nt_UNICODE_STRING_string (tvbuff_t *tvb, int offset, 
-                             packet_info *pinfo, proto_tree *tree, 
-                             char *drep)
-{
-       guint32 len, off, max_len;
-       guint16 *data16;
-       char *text;
-       int old_offset;
-       dcerpc_info *di;
-       header_field_info *hfi;
-
-       di=pinfo->private_data;
-
-        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_nt_str_len, &len);
-        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_nt_str_off, &off);
-        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_nt_str_max_len, &max_len);
-
-       old_offset=offset;
-       offset = prs_uint16s(tvb, offset, pinfo, tree, max_len, &data16, NULL);
-       text = fake_unicode(data16, max_len);
-
-       hfi = proto_registrar_get_nth(di->hf_index);
-       proto_tree_add_string_format(tree, di->hf_index, 
-               tvb, old_offset, offset-old_offset,
-               text, "%s: %s", hfi->name, text);
-
-       if(tree){
-               proto_item_set_text(tree, "%s: %s", hfi->name, text);
-               proto_item_set_text(tree->parent, "%s: %s", hfi->name, text);
-       }
-       return offset;
-}
-
-int
-dissect_ndr_nt_UNICODE_STRING (tvbuff_t *tvb, int offset, 
-                             packet_info *pinfo, proto_tree *parent_tree, 
-                             char *drep, int hf_index)
-{
-       proto_item *item=NULL;
-       proto_tree *tree=NULL;
-       int old_offset=offset;
-
-       if(parent_tree){
-               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
-                       "Unicode String");
-               tree = proto_item_add_subtree(item, ett_nt_unicode_string);
-       }
-
-        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
-                                     hf_nt_string_length, NULL);
-        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
-                                     hf_nt_string_size, NULL);
-        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                       dissect_ndr_nt_UNICODE_STRING_string, NDR_POINTER_PTR,
-                       hf_index);
-
-       proto_item_set_len(item, offset-old_offset);
-       return offset;
-}
-
-/* functions to dissect a STRING structure, common to many 
-   NT services
-   struct {
-     short len;
-     short size;
-     [size_is(size), length_is(len), ptr] char *string;
-   } STRING;
-*/
-
-static int
-dissect_ndr_nt_STRING_string (tvbuff_t *tvb, int offset, 
-                             packet_info *pinfo, proto_tree *tree, 
-                             char *drep)
-{
-       guint32 len, off, max_len;
-       guint8 *text;
-       int old_offset;
-       dcerpc_info *di;
-       header_field_info *hfi;
-
-       di=pinfo->private_data;
-
-        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_nt_str_len, &len);
-        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_nt_str_off, &off);
-        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_nt_str_max_len, &max_len);
-
-       old_offset=offset;
-       offset = prs_uint8s(tvb, offset, pinfo, tree, max_len, &text, NULL);
-
-       hfi = proto_registrar_get_nth(di->hf_index);
-       proto_tree_add_string_format(tree, di->hf_index, 
-               tvb, old_offset, offset-old_offset,
-               text, "%s: %s", hfi->name, text);
-
-       if(tree){
-               proto_item_set_text(tree, "%s: %s", hfi->name, text);
-               proto_item_set_text(tree->parent, "%s: %s", hfi->name, text);
-       }
-       return offset;
-}
-
-int
-dissect_ndr_nt_STRING (tvbuff_t *tvb, int offset, 
-                             packet_info *pinfo, proto_tree *parent_tree, 
-                             char *drep, int hf_index)
-{
-       proto_item *item=NULL;
-       proto_tree *tree=NULL;
-       int old_offset=offset;
-
-       if(parent_tree){
-               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
-                       "Unicode String");
-               tree = proto_item_add_subtree(item, ett_nt_unicode_string);
-       }
-
-        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
-                                     hf_nt_string_length, NULL);
-        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
-                                     hf_nt_string_size, NULL);
-        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                       dissect_ndr_nt_STRING_string, NDR_POINTER_PTR,
-                       hf_index);
-
-       proto_item_set_len(item, offset-old_offset);
-       return offset;
-}
-
-
-
-
index 48300f0612b4877a29cd0b78a899ddabf0c16f7e..b1472a52cdaa1341b5efc4f206d2766219614921 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for DCERPC over SMB packet disassembly
  * Copyright 2001, Tim Potter <tpot@samba.org>
  *
- * $Id: packet-dcerpc-nt.h,v 1.3 2002/01/25 08:35:59 guy Exp $
+ * $Id: packet-dcerpc-nt.h,v 1.4 2002/01/29 09:13:28 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -73,11 +73,4 @@ int prs_push_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 guint32 prs_pop_ptr(GList **ptr_list, char *name);
 
-int dissect_ndr_nt_UNICODE_STRING (tvbuff_t *tvb, int offset, 
-                             packet_info *pinfo, proto_tree *parent_tree, 
-                                  char *drep, int hf_index);
-int dissect_ndr_nt_STRING (tvbuff_t *tvb, int offset, 
-                             packet_info *pinfo, proto_tree *parent_tree, 
-                                  char *drep, int hf_index);
-
 #endif /* packet-dcerpc-nt.h */
index 674a1cdb903557ff9de346653451273cc775371d..212d71236ee7f2ca443bfd63e3c8b749e1a0229a 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for SMB \\PIPE\\samr packet disassembly
  * Copyright 2001, Tim Potter <tpot@samba.org>
  *
- * $Id: packet-dcerpc-samr.c,v 1.4 2002/01/25 08:35:59 guy Exp $
+ * $Id: packet-dcerpc-samr.c,v 1.5 2002/01/29 09:13:28 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "packet-dcerpc-samr.h"
 #include "smb.h"       /* for "NT_errors[]" */
 
+int dissect_nt_sid(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, char *name);
+
 static int proto_dcerpc_samr = -1;
 
 static int hf_samr_hnd = -1;
-static int hf_samr_perms = -1;
+static int hf_samr_group = -1;
 static int hf_samr_rid = -1;
+static int hf_samr_alias = -1;
+static int hf_samr_rid_attrib = -1;
 static int hf_samr_rc = -1;
 static int hf_samr_index = -1;
 static int hf_samr_acct_ctrl = -1;
@@ -47,12 +51,37 @@ static int hf_samr_array_max_count = -1;
 static int hf_samr_level = -1;
 static int hf_samr_start_idx = -1;
 static int hf_samr_max_entries = -1;
+static int hf_samr_entries = -1;
 static int hf_samr_pref_maxsize = -1;
 static int hf_samr_total_size = -1;
 static int hf_samr_ret_size = -1;
 static int hf_samr_acct_name = -1;
 static int hf_samr_full_name = -1;
 static int hf_samr_acct_desc = -1;
+static int hf_samr_server = -1;
+static int hf_samr_domain = -1;
+static int hf_samr_controller = -1;
+static int hf_samr_access = -1;
+static int hf_samr_mask = -1;
+static int hf_samr_crypt_password = -1;
+static int hf_samr_crypt_hash = -1;
+static int hf_samr_lm_change = -1;
+static int hf_samr_attrib = -1;
+static int hf_samr_max_pwd_age = -1;
+static int hf_samr_min_pwd_age = -1;
+static int hf_samr_min_pwd_len = -1;
+static int hf_samr_pwd_history_len = -1;
+static int hf_samr_num_users = -1;
+static int hf_samr_num_groups = -1;
+static int hf_samr_num_aliases = -1;
+static int hf_samr_resume_hnd = -1;
+
+static int hf_samr_unknown_hyper = -1;
+static int hf_samr_unknown_long = -1;
+static int hf_samr_unknown_short = -1;
+static int hf_samr_unknown_char = -1;
+static int hf_samr_unknown_string = -1;
+static int hf_samr_unknown_time = -1;
 
 /* these are used by functions in packet-dcerpc-nt.c */
 int hf_nt_str_len = -1;
@@ -73,28 +102,251 @@ static e_uuid_t uuid_dcerpc_samr = {
 
 static guint16 ver_dcerpc_samr = 1;
 
+
+/* functions to dissect a UNICODE_STRING structure, common to many 
+   NT services
+   struct {
+     short len;
+     short size;
+     [size_is(size/2), length_is(len/2), ptr] unsigned short *string;
+   } UNICODE_STRING;
+
+   these variables can be found in packet-dcerpc-samr.c 
+*/
+extern int hf_nt_str_len;
+extern int hf_nt_str_off;
+extern int hf_nt_str_max_len;
+extern int hf_nt_string_length;
+extern int hf_nt_string_size;
+extern gint ett_nt_unicode_string;
+
+int
+dissect_ndr_nt_UNICODE_STRING_string (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+       guint32 len, off, max_len;
+       guint16 *data16;
+       char *text;
+       int old_offset;
+       header_field_info *hfi;
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /*just a run to handle conformant arrays, nothing to dissect */
+               return offset;
+       }
+
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_nt_str_len, &len);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_nt_str_off, &off);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_nt_str_max_len, &max_len);
+
+       old_offset=offset;
+       offset = prs_uint16s(tvb, offset, pinfo, tree, max_len, &data16, NULL);
+       text = fake_unicode(data16, max_len);
+
+       hfi = proto_registrar_get_nth(di->hf_index);
+       proto_tree_add_string_format(tree, di->hf_index, 
+               tvb, old_offset, offset-old_offset,
+               text, "%s: %s", hfi->name, text);
+
+       if(tree){
+               proto_item_set_text(tree, "%s: %s", hfi->name, text);
+               proto_item_set_text(tree->parent, "%s: %s", hfi->name, text);
+       }
+       return offset;
+}
+
+int
+dissect_ndr_nt_UNICODE_STRING (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree, 
+                             char *drep, int hf_index)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /*just a run to handle conformant arrays, nothing to dissect */
+               return offset;
+       }
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "Unicode String");
+               tree = proto_item_add_subtree(item, ett_nt_unicode_string);
+       }
+
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_nt_string_length, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_nt_string_size, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       dissect_ndr_nt_UNICODE_STRING_string, NDR_POINTER_PTR,
+                       hf_index);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+/* functions to dissect a STRING structure, common to many 
+   NT services
+   struct {
+     short len;
+     short size;
+     [size_is(size), length_is(len), ptr] char *string;
+   } STRING;
+*/
+
 static int
-samr_dissect_gen_open_reply (tvbuff_t *tvb, int offset, 
+dissect_ndr_nt_STRING_string (tvbuff_t *tvb, int offset, 
                              packet_info *pinfo, proto_tree *tree, 
                              char *drep)
 {
-        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
-                                      hf_samr_hnd, NULL);
+       guint32 len, off, max_len;
+       guint8 *text;
+       int old_offset;
+       header_field_info *hfi;
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /*just a run to handle conformant arrays, nothing to dissect */
+               return offset;
+       }
+
         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_samr_rc, NULL);
-        return offset;
+                                     hf_nt_str_len, &len);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_nt_str_off, &off);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_nt_str_max_len, &max_len);
+
+       old_offset=offset;
+       offset = prs_uint8s(tvb, offset, pinfo, tree, max_len, &text, NULL);
+
+       hfi = proto_registrar_get_nth(di->hf_index);
+       proto_tree_add_string_format(tree, di->hf_index, 
+               tvb, old_offset, offset-old_offset,
+               text, "%s: %s", hfi->name, text);
+
+       if(tree){
+               proto_item_set_text(tree, "%s: %s", hfi->name, text);
+               proto_item_set_text(tree->parent, "%s: %s", hfi->name, text);
+       }
+       return offset;
+}
+
+int
+dissect_ndr_nt_STRING (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree, 
+                             char *drep, int hf_index)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /*just a run to handle conformant arrays, nothing to dissect */
+               return offset;
+       }
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "Unicode String");
+               tree = proto_item_add_subtree(item, ett_nt_unicode_string);
+       }
+
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_nt_string_length, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_nt_string_size, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       dissect_ndr_nt_STRING_string, NDR_POINTER_PTR,
+                       hf_index);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+/* This should get fixed both here and in dissect_smb_64bit_time so
+   one can handle both BIG and LITTLE endian encodings 
+ */
+int dissect_smb_64bit_time(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, char *str, int hf_date);
+int
+dissect_ndr_nt_NTTIME (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep, int hf_index)
+{
+       header_field_info *hfi;
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /*just a run to handle conformant arrays, nothing to dissect */
+               return offset;
+       }
+
+       hfi = proto_registrar_get_nth(hf_index);
+
+       offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
+                hfi->name, hf_index);
+       return offset;
+}
+static int
+samr_dissect_SID(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /* just a run to handle conformant arrays, no scalars to dissect */
+               return offset;
+       }
+
+       /* the SID contains a conformant array, first we must eat
+          the 4-byte max_count before we can hand it off */
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_array_max_count, NULL);
+
+       offset = dissect_nt_sid(tvb, pinfo, offset, tree, "Domain");
+       return offset;
 }
 
+
+
+/* above this line, just some general support routines which should be placed
+   in some more generic file common to all NT services dissectors
+*/
+
+
+
+
+
+
 static int
-samr_dissect_close_hnd_rqst (tvbuff_t *tvb, int offset, 
-                              packet_info *pinfo, proto_tree *tree, 
-                              char *drep)
+samr_dissect_context_handle_reply (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
 {
         offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
                                       hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
         return offset;
 }
 
+
 static int
 samr_dissect_open_user_rqst (tvbuff_t *tvb, int offset, 
                              packet_info *pinfo, proto_tree *tree, 
@@ -103,24 +355,75 @@ samr_dissect_open_user_rqst (tvbuff_t *tvb, int offset,
         offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
                                       hf_samr_hnd, NULL);
         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_samr_perms, NULL);
+                                     hf_samr_access, NULL);
         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
                                      hf_samr_rid, NULL);
         return offset;
 }
 
+static int
+samr_dissect_pointer_long(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     di->hf_index, NULL);
+       return offset;
+}
 
 static int
-samr_dissect_query_dispinfo_level (tvbuff_t *tvb, int offset, 
+samr_dissect_pointer_STRING(tvbuff_t *tvb, int offset, 
                              packet_info *pinfo, proto_tree *tree, 
                              char *drep)
 {
-        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
-                                     hf_samr_level, NULL);
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /*just a run to handle conformant arrays, nothing to dissect */
+               return offset;
+       }
+
+       offset = dissect_ndr_nt_STRING(tvb, offset, pinfo, tree, drep,
+                       di->hf_index);
+       return offset;
+}
+
+static int
+samr_dissect_pointer_UNICODE_STRING(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /*just a run to handle conformant arrays, nothing to dissect */
+               return offset;
+       }
+
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, tree, drep,
+                       di->hf_index);
+       return offset;
+}
+
+static int
+samr_dissect_pointer_short(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+       dcerpc_info *di;
 
+       di=pinfo->private_data;
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     di->hf_index, NULL);
        return offset;
 }
 
+
 static int
 samr_dissect_query_dispinfo_rqst (tvbuff_t *tvb, int offset, 
                              packet_info *pinfo, proto_tree *tree, 
@@ -128,9 +431,8 @@ samr_dissect_query_dispinfo_rqst (tvbuff_t *tvb, int offset,
 {
         offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
                                       hf_samr_hnd, NULL);
-        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                       samr_dissect_query_dispinfo_level, NDR_POINTER_REF,
-                       -1);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, NULL);
         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
                                      hf_samr_start_idx, NULL);
         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
@@ -467,38 +769,49 @@ samr_dissect_DISPLAY_INFO (tvbuff_t *tvb, int offset,
 }
 
 static int
-samr_dissect_query_dispinfo_total_size (tvbuff_t *tvb, int offset, 
+samr_dissect_query_dispinfo_reply (tvbuff_t *tvb, int offset, 
                              packet_info *pinfo, proto_tree *tree, 
                              char *drep)
 {
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_total_size);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_ret_size);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_DISPLAY_INFO, NDR_POINTER_REF,
+                       -1);
         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_samr_total_size, NULL);
+                                     hf_samr_rc, NULL);
+
        return offset;
 }
+
+
 static int
-samr_dissect_query_dispinfo_ret_size (tvbuff_t *tvb, int offset, 
+samr_dissect_get_display_enumeration_index_rqst(tvbuff_t *tvb, int offset, 
                              packet_info *pinfo, proto_tree *tree, 
                              char *drep)
 {
-        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_samr_ret_size, NULL);
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, NULL);
+       offset = dissect_ndr_nt_STRING(tvb, offset, pinfo, tree, drep,
+                       hf_samr_acct_name);
        return offset;
 }
 
+
 static int
-samr_dissect_query_dispinfo_reply (tvbuff_t *tvb, int offset, 
+samr_dissect_get_display_enumeration_index_reply(tvbuff_t *tvb, int offset, 
                              packet_info *pinfo, proto_tree *tree, 
                              char *drep)
 {
         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                       samr_dissect_query_dispinfo_total_size, NDR_POINTER_REF,
-                       -1);
-        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                       samr_dissect_query_dispinfo_ret_size, NDR_POINTER_REF,
-                       -1);
-        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                       samr_dissect_DISPLAY_INFO, NDR_POINTER_REF,
-                       -1);
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_index);
         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
                                      hf_samr_rc, NULL);
 
@@ -506,126 +819,1654 @@ samr_dissect_query_dispinfo_reply (tvbuff_t *tvb, int offset,
 }
 
 
-static dcerpc_sub_dissector dcerpc_samr_dissectors[] = {
-        { SAMR_CONNECT_ANON, "SAMR_CONNECT_ANON", NULL, samr_dissect_gen_open_reply },
-        { SAMR_CLOSE_HND, "SAMR_CLOSE_HND", samr_dissect_close_hnd_rqst, samr_dissect_gen_open_reply },
-        { SAMR_UNKNOWN_2, "SAMR_UNKNOWN_2", NULL, NULL },
-        { SAMR_QUERY_SEC_OBJECT, "SAMR_QUERY_SEC_OBJECT", NULL, NULL },
-        { SAMR_UNKNOWN_4, "SAMR_UNKNOWN_4", NULL, NULL },
-        { SAMR_LOOKUP_DOMAIN, "SAMR_LOOKUP_DOMAIN", NULL, NULL },
-        { SAMR_ENUM_DOMAINS, "SAMR_ENUM_DOMAINS", NULL, NULL },
-        { SAMR_OPEN_DOMAIN, "SAMR_OPEN_DOMAIN", NULL, samr_dissect_gen_open_reply },
-        { SAMR_QUERY_DOMAIN_INFO, "SAMR_QUERY_DOMAIN_INFO", NULL, NULL },
-        { SAMR_CREATE_DOM_GROUP, "SAMR_CREATE_DOM_GROUP", NULL, NULL },
-        { SAMR_ENUM_DOM_GROUPS, "SAMR_ENUM_DOM_GROUPS", NULL, NULL },
-        { SAMR_ENUM_DOM_USERS, "SAMR_ENUM_DOM_USERS", NULL, NULL },
-        { SAMR_CREATE_DOM_ALIAS, "SAMR_CREATE_DOM_ALIAS", NULL, NULL },
-        { SAMR_ENUM_DOM_ALIASES, "SAMR_ENUM_DOM_ALIASES", NULL, NULL },
-        { SAMR_QUERY_USERALIASES, "SAMR_QUERY_USERALIASES", NULL, NULL },
-        { SAMR_LOOKUP_NAMES, "SAMR_LOOKUP_NAMES", NULL, NULL },
-        { SAMR_LOOKUP_RIDS, "SAMR_LOOKUP_RIDS", NULL, NULL },
-        { SAMR_OPEN_GROUP, "SAMR_OPEN_GROUP", NULL, samr_dissect_gen_open_reply },
-        { SAMR_QUERY_GROUPINFO, "SAMR_QUERY_GROUPINFO", NULL, NULL },
-        { SAMR_SET_GROUPINFO, "SAMR_SET_GROUPINFO", NULL, NULL },
-        { SAMR_ADD_GROUPMEM, "SAMR_ADD_GROUPMEM", NULL, NULL },
-        { SAMR_DELETE_DOM_GROUP, "SAMR_DELETE_DOM_GROUP", NULL, NULL },
-        { SAMR_DEL_GROUPMEM, "SAMR_DEL_GROUPMEM", NULL, NULL },
-        { SAMR_QUERY_GROUPMEM, "SAMR_QUERY_GROUPMEM", NULL, NULL },
-        { SAMR_UNKNOWN_1A, "SAMR_UNKNOWN_1A", NULL, NULL },
-        { SAMR_OPEN_ALIAS, "SAMR_OPEN_ALIAS", NULL, samr_dissect_gen_open_reply },
-        { SAMR_QUERY_ALIASINFO, "SAMR_QUERY_ALIASINFO", NULL, NULL },
-        { SAMR_SET_ALIASINFO, "SAMR_SET_ALIASINFO", NULL, NULL },
-        { SAMR_DELETE_DOM_ALIAS, "SAMR_DELETE_DOM_ALIAS", NULL, NULL },
-        { SAMR_ADD_ALIASMEM, "SAMR_ADD_ALIASMEM", NULL, NULL },
-        { SAMR_DEL_ALIASMEM, "SAMR_DEL_ALIASMEM", NULL, NULL },
-        { SAMR_QUERY_ALIASMEM, "SAMR_QUERY_ALIASMEM", NULL, NULL },
-        { SAMR_OPEN_USER, "SAMR_OPEN_USER", samr_dissect_open_user_rqst, samr_dissect_gen_open_reply },
-        { SAMR_DELETE_DOM_USER, "SAMR_DELETE_DOM_USER", NULL, NULL },
-        { SAMR_QUERY_USERINFO, "SAMR_QUERY_USERINFO", NULL, NULL },
-        { SAMR_SET_USERINFO2, "SAMR_SET_USERINFO2", NULL, NULL },
-        { SAMR_QUERY_USERGROUPS, "SAMR_QUERY_USERGROUPS", NULL, NULL },
-        { SAMR_QUERY_DISPINFO, "SAMR_QUERY_DISPINFO", samr_dissect_query_dispinfo_rqst, samr_dissect_query_dispinfo_reply },
-        { SAMR_UNKNOWN_29, "SAMR_UNKNOWN_29", NULL, NULL },
-        { SAMR_UNKNOWN_2a, "SAMR_UNKNOWN_2a", NULL, NULL },
-        { SAMR_UNKNOWN_2b, "SAMR_UNKNOWN_2b", NULL, NULL },
-        { SAMR_GET_USRDOM_PWINFO, "SAMR_GET_USRDOM_PWINFO", NULL, NULL },
-        { SAMR_UNKNOWN_2D, "SAMR_UNKNOWN_2D", NULL, NULL },
-        { SAMR_UNKNOWN_2e, "SAMR_UNKNOWN_2e", NULL, NULL },
-        { SAMR_UNKNOWN_2f, "SAMR_UNKNOWN_2f", NULL, NULL },
-        { SAMR_QUERY_DISPINFO3, "SAMR_QUERY_DISPINFO3", NULL, NULL },
-        { SAMR_UNKNOWN_31, "SAMR_UNKNOWN_31", NULL, NULL },
-        { SAMR_CREATE_USER, "SAMR_CREATE_USER", NULL, NULL },
-        { SAMR_QUERY_DISPINFO4, "SAMR_QUERY_DISPINFO4", NULL, NULL },
-        { SAMR_ADDMULTI_ALIASMEM, "SAMR_ADDMULTI_ALIASMEM", NULL, NULL },
-        { SAMR_UNKNOWN_35, "SAMR_UNKNOWN_35", NULL, NULL },
-        { SAMR_UNKNOWN_36, "SAMR_UNKNOWN_36", NULL, NULL },
-        { SAMR_CHGPASSWD_USER, "SAMR_CHGPASSWD_USER", NULL, NULL },
-        { SAMR_GET_DOM_PWINFO, "SAMR_GET_DOM_PWINFO", NULL, NULL },
-        { SAMR_CONNECT, "SAMR_CONNECT", NULL, samr_dissect_gen_open_reply },
-        { SAMR_SET_USERINFO, "SAMR_SET_USERINFO", NULL, NULL },
 
-        {0, NULL, NULL,  NULL },
-};
 
-void 
-proto_register_dcerpc_samr(void)
+static int
+samr_dissect_PASSWORD_INFO (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
 {
-        static hf_register_info hf[] = {
-                { &hf_samr_hnd,
-                  { "Context Handle", "samr.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
-                { &hf_samr_perms,
-                  { "Access Mask", "samr.perms", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
-                { &hf_samr_rid,
-                  { "Rid", "samr.rid", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
-                { &hf_samr_rc,
-                  { "Return code", "samr.rc", FT_UINT32, BASE_HEX, VALS (NT_errors), 0x0, "", HFILL }},
+       guint32 count;
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
 
-       { &hf_samr_level,
-               { "Level", "samr.level", FT_UINT16, BASE_DEC, 
-               NULL, 0x0, "Level requested/returned for Information", HFILL }},
-       { &hf_samr_start_idx,
-               { "Start Idx", "samr.start_idx", FT_UINT32, BASE_DEC, 
-               NULL, 0x0, "Start Index for returned Information", HFILL }},
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "Password Info");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
 
-       { &hf_samr_max_entries,
-               { "Max Entries", "samr.max_entries", FT_UINT32, BASE_DEC, 
-               NULL, 0x0, "Maximum number of entries to return", HFILL }},
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_short, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_long, NULL);
 
-       { &hf_samr_pref_maxsize,
-               { "Pref MaxSize", "samr.pref_maxsize", FT_UINT32, BASE_DEC, 
-               NULL, 0x0, "Maximum Size of data to return", HFILL }},
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
 
-       { &hf_samr_total_size,
-               { "Total Size", "samr.total_size", FT_UINT32, BASE_DEC, 
-               NULL, 0x0, "Total size of data", HFILL }},
+static int
+samr_dissect_get_usrdom_pwinfo_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_PASSWORD_INFO, NDR_POINTER_REF,
+                       -1);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
 
-       { &hf_samr_ret_size,
-               { "Returned Size", "samr.ret_size", FT_UINT32, BASE_DEC, 
-               NULL, 0x0, "Number of returned objects in this PDU", HFILL }},
 
-       { &hf_samr_index,
-               { "Index", "samr.index", FT_UINT32, BASE_DEC, 
-               NULL, 0x0, "Index", HFILL }},
 
-       { &hf_samr_acct_ctrl,
-               { "Acct Ctrl", "samr.acct_ctrl", FT_UINT32, BASE_DEC, 
-               NULL, 0x0, "Acct CTRL", HFILL }},
+static int
+samr_dissect_connect2_server(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree, 
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
 
-        { &hf_samr_array_max_count,
-          { "Max Count", "samr.array.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum Count: Number of elements in the array", HFILL }},
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "Server");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
 
-       { &hf_samr_acct_name,
-               { "Account Name", "samr.acct_name", FT_STRING, BASE_NONE,
-               NULL, 0, "Name of Account", HFILL }},
+       offset = dissect_ndr_nt_UNICODE_STRING_string(tvb, offset, pinfo, 
+                       tree, drep);
 
-       { &hf_samr_full_name,
-               { "Full Name", "samr.full_name", FT_STRING, BASE_NONE,
-               NULL, 0, "Full Name of Account", HFILL }},
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_connect2_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_connect2_server, NDR_POINTER_UNIQUE,
+                       hf_samr_server);
+
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_access, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_connect2_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+
+
+
+static int
+samr_dissect_USER_GROUP(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "User Group");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rid, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rid_attrib, NULL);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_USER_GROUP_ARRAY_groups (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+       offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_USER_GROUP);
+
+       return offset;
+}
+
+static int
+samr_dissect_USER_GROUP_ARRAY (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       guint32 count;
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "User_Group Array");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_array_max_count, &count);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_USER_GROUP_ARRAY_groups, NDR_POINTER_UNIQUE,
+                       -1);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_get_groups_for_user_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_USER_GROUP_ARRAY, NDR_POINTER_REF,
+                       -1);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+
+
+static int
+samr_dissect_open_domain_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_access, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_SID, NDR_POINTER_REF,
+                       -1);
+       return offset;
+}
+
+static int
+samr_dissect_open_domain_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+
+
+static int
+samr_dissect_context_handle_SID(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_SID, NDR_POINTER_REF,
+                       -1);
+       return offset;
+}
+
+static int
+samr_dissect_context_handle(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+       return offset;
+}
+
+
+static int
+samr_dissect_rc(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_add_member_to_group_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_group, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rid, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_unknown_3c_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_short, NDR_POINTER_REF,
+                       hf_samr_unknown_short);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+
+
+static int
+samr_dissect_create_alias_in_domain_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, tree, drep,
+                       hf_samr_acct_name);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_access, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_create_alias_in_domain_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rid, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+
+       return offset;
+}
+
+
+static int
+samr_dissect_query_information_alias_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, NULL);
+
+       return offset;
+}
+
+
+static int
+samr_dissect_ALIAS_INFO_1 (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+               tree, drep,
+               hf_samr_acct_name);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rid, NULL);
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+               tree, drep,
+               hf_samr_acct_desc);
+       return offset;
+}
+
+static int
+samr_dissect_ALIAS_INFO (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+       guint16 level;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "AliasInfo");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, &level);
+       switch(level){
+       case 1: 
+               offset = samr_dissect_ALIAS_INFO_1(
+                               tvb, offset, pinfo, tree, drep);
+               break;
+       case 2: 
+               offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+                       tree, drep,
+                       hf_samr_acct_name);
+               break;
+       case 3: 
+               offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+                       tree, drep,
+                       hf_samr_acct_desc);
+               break;
+       }
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_query_information_alias_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_ALIAS_INFO, NDR_POINTER_REF,
+                       -1);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_set_information_alias_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_ALIAS_INFO, NDR_POINTER_REF,
+                       -1);
+       return offset;
+}
+
+
+static int
+samr_dissect_CRYPT_PASSWORD(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+       proto_tree_add_item(tree, hf_samr_crypt_password, tvb, offset, 516,
+               FALSE);
+       return offset;
+}
+
+static int
+samr_dissect_CRYPT_HASH(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+       proto_tree_add_item(tree, hf_samr_crypt_hash, tvb, offset, 16,
+               FALSE);
+       return offset;
+}
+
+
+static int
+samr_dissect_oem_change_password_user2_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_STRING, NDR_POINTER_UNIQUE,
+                       hf_samr_server);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_STRING, NDR_POINTER_REF,
+                       hf_samr_acct_name);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_PASSWORD, NDR_POINTER_UNIQUE,
+                       -1);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+                       -1);
+       return offset;
+}
+
+static int
+samr_dissect_unicode_change_password_user2_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+                       hf_samr_server);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_UNICODE_STRING, NDR_POINTER_REF,
+                       hf_samr_acct_name);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_PASSWORD, NDR_POINTER_UNIQUE,
+                       -1);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+                       -1);
+        offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_lm_change, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_PASSWORD, NDR_POINTER_UNIQUE,
+                       -1);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+                       -1);
+       return offset;
+}
+
+static int
+samr_dissect_unknown_3b_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_short, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+                       hf_samr_unknown_string);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+                       hf_samr_unknown_string);
+       return offset;
+}
+
+
+static int
+samr_dissect_create_user2_in_domain_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, tree, drep,
+                       hf_samr_acct_name);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_acct_ctrl, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_access, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_create_user2_in_domain_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_long, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rid, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_get_display_enumeration_index2_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, NULL);
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, tree, drep,
+                       hf_samr_acct_name);
+       return offset;
+}
+
+static int
+samr_dissect_get_display_enumeration_index2_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_index, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_change_password_user_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_char, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+                       -1);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+                       -1);
+        offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_char, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+                       -1);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+                       -1);
+        offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_char, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+                       -1);
+        offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_char, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+                       -1);
+       return offset;
+}
+
+static int
+samr_dissect_set_member_attributes_of_group_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree, 
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_attrib, NULL);
+       return offset;
+}
+
+
+static int
+samr_dissect_GROUP_INFO_1 (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+               tree, drep,
+               hf_samr_acct_name);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rid, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                       hf_samr_attrib, NULL);
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+               tree, drep,
+               hf_samr_acct_desc);
+       return offset;
+}
+
+static int
+samr_dissect_GROUP_INFO (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+       guint16 level;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "GroupInfo");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, &level);
+       switch(level){
+       case 1: 
+               offset = samr_dissect_GROUP_INFO_1(
+                               tvb, offset, pinfo, tree, drep);
+               break;
+       case 2: 
+               offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+                       tree, drep,
+                       hf_samr_acct_name);
+               break;
+       case 3:
+               offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                        hf_samr_attrib, NULL);
+               break;
+       case 4: 
+               offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+                       tree, drep,
+                       hf_samr_acct_desc);
+               break;
+       }
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_query_information_group_rqst (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_query_information_group_reply (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_GROUP_INFO, NDR_POINTER_REF,
+                       -1);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_set_information_group_rqst (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_GROUP_INFO, NDR_POINTER_REF,
+                       -1);
+       return offset;
+}
+
+
+
+static int
+samr_dissect_get_domain_password_information_rqst (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_STRING, NDR_POINTER_UNIQUE,
+                       hf_samr_domain);
+       return offset;
+}
+
+
+static int
+samr_dissect_DOMAIN_INFO_1(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "DomainInfo_1");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_min_pwd_len, NULL);
+        offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_pwd_history_len, NULL);
+        offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_unknown_long, NULL);
+       offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_max_pwd_age);
+       offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_min_pwd_age);
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_DOMAIN_INFO_2(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "DomainInfo_2");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+       offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_unknown_time);
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, tree, drep,
+                       hf_samr_unknown_string);
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, tree, drep,
+                       hf_samr_domain);
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, tree, drep,
+                       hf_samr_controller);
+       offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_unknown_time);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_long, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_long, NULL);
+        offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_char, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_num_users, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_num_groups, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_num_aliases, NULL);
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_DOMAIN_INFO_8(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "DomainInfo_8");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+       offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_max_pwd_age);
+       offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_min_pwd_age);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_REPLICATION_STATUS(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "Replication Status");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_hyper, NULL);
+        offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_hyper, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_unknown_short, NULL);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_DOMAIN_INFO_11(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "DomainInfo_11");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+       offset = samr_dissect_DOMAIN_INFO_2(
+                       tvb, offset, pinfo, tree, drep);
+       offset = samr_dissect_REPLICATION_STATUS(
+                       tvb, offset, pinfo, tree, drep);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_DOMAIN_INFO_13(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "DomainInfo_13");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+       offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_unknown_time);
+       offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_unknown_time);
+       offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+                                       hf_samr_unknown_time);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+
+static int
+samr_dissect_DOMAIN_INFO (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+       guint16 level;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "DomainInfo");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, &level);
+       switch(level){
+       case 1: 
+               offset = samr_dissect_DOMAIN_INFO_1(
+                               tvb, offset, pinfo, tree, drep);
+               break;
+       case 2: 
+               offset = samr_dissect_DOMAIN_INFO_2(
+                               tvb, offset, pinfo, tree, drep);
+               break;
+
+       case 3:
+               offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+                               hf_samr_unknown_time);
+               break;
+       case 4:
+               offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+                       tree, drep, hf_samr_unknown_string);
+               break;
+
+       case 5:
+               offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+                       tree, drep, hf_samr_domain);
+               break;
+
+       case 6:
+               offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+                       tree, drep, hf_samr_controller);
+               break;
+
+       case 7:
+               offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                       hf_samr_unknown_short, NULL);
+               break;
+       case 8: 
+               offset = samr_dissect_DOMAIN_INFO_8(
+                               tvb, offset, pinfo, tree, drep);
+               break;
+       case 9:
+               offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                       hf_samr_unknown_short, NULL);
+               break;
+       case 11:        
+               offset = samr_dissect_DOMAIN_INFO_11(
+                               tvb, offset, pinfo, tree, drep);
+               break;
+       case 12:
+               offset = samr_dissect_REPLICATION_STATUS(
+                               tvb, offset, pinfo, tree, drep);
+               break;
+       case 13:        
+               offset = samr_dissect_DOMAIN_INFO_13(
+                               tvb, offset, pinfo, tree, drep);
+               break;
+       }
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_query_information_domain_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+       offset = samr_dissect_DOMAIN_INFO(tvb, offset, pinfo, tree, drep);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+
+static int
+samr_dissect_set_information_domain_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_level, NULL);
+       offset = samr_dissect_DOMAIN_INFO(tvb, offset, pinfo, tree, drep);
+       return offset;
+}
+
+
+
+static int
+samr_dissect_lookup_domain_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_SID, NDR_POINTER_REF,
+                       -1);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_PSID(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "SID");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_SID, NDR_POINTER_UNIQUE,
+                       -1);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+
+static int
+samr_dissect_PSID_ARRAY_sids (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+       offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_PSID);
+
+       return offset;
+}
+
+
+static int
+samr_dissect_PSID_ARRAY (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       guint32 count;
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "SID Array");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_array_max_count, &count);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_PSID_ARRAY_sids, NDR_POINTER_UNIQUE,
+                       -1);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+static int
+samr_dissect_pindex(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "SID");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_UNIQUE,
+                       di->hf_index);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+
+static int
+samr_dissect_INDEX_ARRAY_value (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+       offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pindex);
+
+       return offset;
+}
+
+
+static int
+samr_dissect_INDEX_ARRAY (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       guint32 count;
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "SID Array");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_array_max_count, &count);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_INDEX_ARRAY_value, NDR_POINTER_UNIQUE,
+                       di->hf_index);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+
+static int
+samr_dissect_get_alias_membership_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                                      hf_samr_hnd, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_PSID_ARRAY, NDR_POINTER_REF,
+                       -1);
+       return offset;
+}
+
+static int
+samr_dissect_get_alias_membership_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_INDEX_ARRAY, NDR_POINTER_REF,
+                       hf_samr_alias);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+
+static int
+samr_dissect_IDX_AND_NAME(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "IDX_AND_NAME");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                       hf_samr_index, NULL);
+       offset = dissect_ndr_nt_UNICODE_STRING(tvb, offset, pinfo, 
+                       tree, drep, di->hf_index);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+static int
+samr_dissect_IDX_AND_NAME_entry (tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+       offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_IDX_AND_NAME);
+
+       return offset;
+}
+
+
+static int
+samr_dissect_IDX_AND_NAME_ARRAY(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *parent_tree,
+                             char *drep)
+{
+       guint32 count;
+       proto_item *item=NULL;
+       proto_tree *tree=NULL;
+       int old_offset=offset;
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+
+       if(parent_tree){
+               item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+                       "IDX_AND_NAME Array");
+               tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+       }
+
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_array_max_count, &count);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_IDX_AND_NAME_entry, NDR_POINTER_UNIQUE,
+                       di->hf_index);
+
+       proto_item_set_len(item, offset-old_offset);
+       return offset;
+}
+
+
+static int
+samr_dissect_enum_domains_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                       hf_samr_hnd, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_resume_hnd);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                       hf_samr_pref_maxsize, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_enum_domains_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_resume_hnd);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_IDX_AND_NAME_ARRAY, NDR_POINTER_REF,
+                       hf_samr_domain);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_entries);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                                     hf_samr_rc, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_enum_dom_groups_rqst(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+                       hf_samr_hnd, NULL);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_resume_hnd);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                       hf_samr_mask, NULL);
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                       hf_samr_pref_maxsize, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_enum_dom_groups_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_resume_hnd);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_IDX_AND_NAME_ARRAY, NDR_POINTER_REF,
+                       hf_samr_group);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_entries);
+        offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+                       hf_samr_rc, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_enum_dom_alias_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_resume_hnd);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_IDX_AND_NAME_ARRAY, NDR_POINTER_REF,
+                       hf_samr_alias);
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_pointer_long, NDR_POINTER_REF,
+                       hf_samr_entries);
+        offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+                       hf_samr_rc, NULL);
+       return offset;
+}
+
+static int
+samr_dissect_get_members_in_alias_reply(tvbuff_t *tvb, int offset, 
+                             packet_info *pinfo, proto_tree *tree,
+                             char *drep)
+{
+        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+                       samr_dissect_PSID_ARRAY, NDR_POINTER_REF,
+                       -1);
+        offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+                       hf_samr_rc, NULL);
+       return offset;
+}
+
+
+
+
+static dcerpc_sub_dissector dcerpc_samr_dissectors[] = {
+        { SAMR_CONNECT_ANON, "CONNECT_ANON",
+               samr_dissect_connect2_rqst,
+               samr_dissect_context_handle_reply },
+        { SAMR_CLOSE_HND, "CLOSE_HND",
+               samr_dissect_context_handle,
+               samr_dissect_context_handle_reply },
+        { SAMR_UNKNOWN_2, "SAMR_UNKNOWN_2", NULL, NULL },
+        { SAMR_QUERY_SEC_OBJECT, "SAMR_QUERY_SEC_OBJECT", NULL, NULL },
+        { SAMR_SHUTDOWN_SAM_SERVER, "SHUTDOWN_SAM_SERVER",
+               samr_dissect_context_handle,
+               samr_dissect_rc },
+        { SAMR_LOOKUP_DOMAIN, "LOOKUP_DOMAIN",
+               samr_dissect_get_domain_password_information_rqst,
+               samr_dissect_lookup_domain_reply },
+        { SAMR_ENUM_DOMAINS, "ENUM_DOMAINS",
+               samr_dissect_enum_domains_rqst,
+               samr_dissect_enum_domains_reply },
+        { SAMR_OPEN_DOMAIN, "OPEN_DOMAIN",
+               samr_dissect_open_domain_rqst,
+               samr_dissect_open_domain_reply },
+        { SAMR_QUERY_DOMAIN_INFO, "QUERY_INFORMATION_DOMAIN",
+               samr_dissect_query_information_alias_rqst,
+               samr_dissect_query_information_domain_reply },
+        { SAMR_SET_DOMAIN_INFO, "SET_INFORMATION_DOMAIN",
+               samr_dissect_set_information_domain_rqst,
+               samr_dissect_rc },
+        { SAMR_CREATE_DOM_GROUP, "CREATE_GROUP_IN_DOMAIN",
+               samr_dissect_create_alias_in_domain_rqst,
+               samr_dissect_create_alias_in_domain_reply },
+        { SAMR_ENUM_DOM_GROUPS, "ENUM_DOM_GROUPS",
+               samr_dissect_enum_dom_groups_rqst,
+               samr_dissect_enum_dom_groups_reply },
+       { SAMR_CREATE_USER_IN_DOMAIN, "CREATE_USER_IN_DOMAIN",
+               samr_dissect_create_alias_in_domain_rqst,
+               samr_dissect_create_alias_in_domain_reply },
+        { SAMR_ENUM_DOM_USERS, "ENUM_DOM_USERS",
+               samr_dissect_enum_dom_groups_rqst,
+               samr_dissect_enum_dom_groups_reply },
+        { SAMR_CREATE_DOM_ALIAS, "CREATE_ALIAS_IN_DOMAIN",
+               samr_dissect_create_alias_in_domain_rqst,
+               samr_dissect_create_alias_in_domain_reply },
+        { SAMR_ENUM_DOM_ALIASES, "ENUM_DOM_ALIASES",
+               samr_dissect_enum_dom_groups_rqst,
+               samr_dissect_enum_dom_alias_reply },
+        { SAMR_GET_ALIAS_MEMBERSHIP, "GET_ALIAS_MEMBERSHIP",
+               samr_dissect_get_alias_membership_rqst,
+               samr_dissect_get_alias_membership_reply },
+        { SAMR_LOOKUP_NAMES, "SAMR_LOOKUP_NAMES", NULL, NULL },
+        { SAMR_LOOKUP_RIDS, "SAMR_LOOKUP_RIDS", NULL, NULL },
+        { SAMR_OPEN_GROUP, "OPEN_GROUP",
+               samr_dissect_open_user_rqst,
+               samr_dissect_context_handle_reply },
+        { SAMR_QUERY_GROUPINFO, "QUERY_INFORMATION_GROUP",
+               samr_dissect_query_information_group_rqst,
+               samr_dissect_query_information_group_reply },
+        { SAMR_SET_GROUPINFO, "SET_INFORMATION_GROUP",
+               samr_dissect_set_information_group_rqst,
+               samr_dissect_rc },
+        { SAMR_ADD_GROUPMEM, "ADD_MEMBER_TO_GROUP",
+               samr_dissect_add_member_to_group_rqst,
+               samr_dissect_rc },
+        { SAMR_DELETE_DOM_GROUP, "DELETE_DOM_GROUP",
+               samr_dissect_context_handle,
+               samr_dissect_rc },
+        { SAMR_DEL_GROUPMEM, "REMOVE_MEMBER_FROM_GROUP",
+               samr_dissect_add_member_to_group_rqst,
+               samr_dissect_rc },
+        { SAMR_QUERY_GROUPMEM, "SAMR_QUERY_GROUPMEM", NULL, NULL },
+        { SAMR_SET_MEMBER_ATTRIBUTES_OF_GROUP, "SET_MEMBER_ATTRIBUTES_OF_GROUP",
+               samr_dissect_set_member_attributes_of_group_rqst,
+               samr_dissect_rc },
+
+        { SAMR_OPEN_ALIAS, "OPEN_ALIAS",
+               samr_dissect_open_user_rqst,
+               samr_dissect_context_handle_reply },
+        { SAMR_QUERY_ALIASINFO, "QUERY_INFORMATION_ALIAS",
+               samr_dissect_query_information_alias_rqst,
+               samr_dissect_query_information_alias_reply },
+        { SAMR_SET_ALIASINFO, "SET_INFORMATION_ALIAS",
+               samr_dissect_set_information_alias_rqst,
+               samr_dissect_rc },
+        { SAMR_DELETE_DOM_ALIAS, "DELETE_DOM_ALIAS",
+               samr_dissect_context_handle,
+               samr_dissect_rc },
+        { SAMR_ADD_ALIASMEM, "ADD_MEMBER_TO_ALIAS",
+               samr_dissect_context_handle_SID,
+               samr_dissect_rc },
+        { SAMR_DEL_ALIASMEM, "REMOVE_MEMBER_FROM_ALIAS",
+               samr_dissect_context_handle_SID,
+               samr_dissect_rc },
+        { SAMR_GET_MEMBERS_IN_ALIAS, "GET_MEMBERS_IN_ALIAS",
+               samr_dissect_context_handle,
+               samr_dissect_get_members_in_alias_reply },
+        { SAMR_OPEN_USER, "OPEN_USER", 
+               samr_dissect_open_user_rqst, 
+               samr_dissect_context_handle_reply },
+        { SAMR_DELETE_DOM_USER, "DELETE_DOM_USER",
+               samr_dissect_context_handle,
+               samr_dissect_rc },
+        { SAMR_QUERY_USERINFO, "SAMR_QUERY_USERINFO", NULL, NULL },
+        { SAMR_SET_USERINFO2, "SAMR_SET_USERINFO2", NULL, NULL },
+       { SAMR_CHANGE_PASSWORD_USER, "CHANGE_PASSWORD_USER",
+               samr_dissect_change_password_user_rqst,
+               samr_dissect_rc },
+        { SAMR_GET_GROUPS_FOR_USER, "SAMR_GET_GROUPS_FOR_USER",
+               samr_dissect_context_handle,
+               samr_dissect_get_groups_for_user_reply },
+        { SAMR_QUERY_DISPINFO, "QUERY_DISPINFO", 
+               samr_dissect_query_dispinfo_rqst, 
+               samr_dissect_query_dispinfo_reply },
+        { SAMR_GET_DISPLAY_ENUMERATION_INDEX, "GET_DISPLAY_ENUMERATION_INDEX", 
+               samr_dissect_get_display_enumeration_index_rqst, 
+               samr_dissect_get_display_enumeration_index_reply },
+        { SAMR_TEST_PRIVATE_FUNCTIONS_DOMAIN, "TEST_PRIVATE_FUNCTIONS_DOMAIN",
+               samr_dissect_context_handle,
+               samr_dissect_rc },
+        { SAMR_TEST_PRIVATE_FUNCTIONS_USER, "TEST_PRIVATE_FUNCTIONS_USER",
+               samr_dissect_context_handle,
+               samr_dissect_rc },
+        { SAMR_GET_USRDOM_PWINFO, "GET_USRDOM_PWINFO",
+               samr_dissect_context_handle,
+               samr_dissect_get_usrdom_pwinfo_reply },
+        { SAMR_REMOVE_MEMBER_FROM_FOREIGN_DOMAIN, "REMOVE_MEMBER_FROM_FOREIGN_DOMAIN",
+               samr_dissect_context_handle_SID,
+               samr_dissect_rc },
+        { SAMR_QUERY_INFORMATION_DOMAIN2, "QUERY_INFORMATION_DOMAIN2",
+               samr_dissect_query_information_alias_rqst,
+               samr_dissect_query_information_domain_reply },
+        { SAMR_UNKNOWN_2f, "SAMR_UNKNOWN_2f", NULL, NULL },
+        { SAMR_QUERY_DISPINFO2, "QUERY_INFORMATION_DISPLAY2",
+               samr_dissect_query_dispinfo_rqst,
+               samr_dissect_query_dispinfo_reply },
+        { SAMR_GET_DISPLAY_ENUMERATION_INDEX2, "GET_DISPLAY_ENUMERATION_INDEX2",
+               samr_dissect_get_display_enumeration_index2_rqst,
+               samr_dissect_get_display_enumeration_index2_reply },
+        { SAMR_CREATE_USER2_IN_DOMAIN, "CREATE_USER2_IN_DOMAIN",
+               samr_dissect_create_user2_in_domain_rqst,
+               samr_dissect_create_user2_in_domain_reply },
+        { SAMR_QUERY_DISPINFO3, "QUERY_INFORMATION_DISPLAY3",
+               samr_dissect_query_dispinfo_rqst,
+               samr_dissect_query_dispinfo_reply },
+        { SAMR_ADD_MULTIPLE_MEMBERS_TO_ALIAS, "ADD_MULTIPLE_MEMBERS_TO_ALIAS",
+               samr_dissect_get_alias_membership_rqst,
+               samr_dissect_rc },
+        { SAMR_REMOVE_MULTIPLE_MEMBERS_FROM_ALIAS, "REMOVE_MULTIPLE_MEMBERS_FROM_ALIAS",
+               samr_dissect_get_alias_membership_rqst,
+               samr_dissect_rc },
+        { SAMR_OEM_CHANGE_PASSWORD_USER2, "OEM_CHANGE_PASSWORD_USER2",
+               samr_dissect_oem_change_password_user2_rqst,
+               samr_dissect_rc },
+        { SAMR_UNICODE_CHANGE_PASSWORD_USER2, "UNICODE_CHANGE_PASSWORD_USER2",
+               samr_dissect_unicode_change_password_user2_rqst,
+               samr_dissect_rc },
+        { SAMR_GET_DOM_PWINFO, "GET_DOMAIN_PASSWORD_INFORMATION",
+               samr_dissect_get_domain_password_information_rqst,
+               samr_dissect_get_usrdom_pwinfo_reply },
+       { SAMR_CONNECT2, "CONNECT2", 
+               samr_dissect_connect2_rqst,
+               samr_dissect_connect2_reply },
+        { SAMR_SET_USERINFO, "SAMR_SET_USERINFO", NULL, NULL },
+
+        { SAMR_UNKNOWN_3B, "UNKNOWN_3B",
+               samr_dissect_unknown_3b_rqst,
+               samr_dissect_rc },
+        { SAMR_UNKNOWN_3C, "SAMR_UNKNOWN_3C", 
+               samr_dissect_context_handle,
+               samr_dissect_unknown_3c_reply },
+        {0, NULL, NULL,  NULL },
+};
+
+void 
+proto_register_dcerpc_samr(void)
+{
+        static hf_register_info hf[] = {
+                { &hf_samr_hnd,
+                  { "Context Handle", "samr.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
+                { &hf_samr_group,
+                  { "Group", "samr.group", FT_UINT32, BASE_DEC, NULL, 0x0, "Group", HFILL }},
+                { &hf_samr_rid,
+                  { "Rid", "samr.rid", FT_UINT32, BASE_HEX, NULL, 0x0, "RID", HFILL }},
+                { &hf_samr_alias,
+                  { "Alias", "samr.alias", FT_UINT32, BASE_HEX, NULL, 0x0, "Alias", HFILL }},
+                { &hf_samr_rid_attrib,
+                  { "Rid Attrib", "samr.rid.attrib", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+                { &hf_samr_attrib,
+                  { "Attributes", "samr.attr", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+                { &hf_samr_rc,
+                  { "Return code", "samr.rc", FT_UINT32, BASE_HEX, VALS (NT_errors), 0x0, "", HFILL }},
+
+       { &hf_samr_level,
+               { "Level", "samr.level", FT_UINT16, BASE_DEC, 
+               NULL, 0x0, "Level requested/returned for Information", HFILL }},
+       { &hf_samr_start_idx,
+               { "Start Idx", "samr.start_idx", FT_UINT32, BASE_DEC, 
+               NULL, 0x0, "Start Index for returned Information", HFILL }},
+
+       { &hf_samr_entries,
+               { "Entries", "samr.entries", FT_UINT32, BASE_DEC, 
+               NULL, 0x0, "Number of entries to return", HFILL }},
+
+       { &hf_samr_max_entries,
+               { "Max Entries", "samr.max_entries", FT_UINT32, BASE_DEC, 
+               NULL, 0x0, "Maximum number of entries", HFILL }},
+
+       { &hf_samr_pref_maxsize,
+               { "Pref MaxSize", "samr.pref_maxsize", FT_UINT32, BASE_DEC, 
+               NULL, 0x0, "Maximum Size of data to return", HFILL }},
+
+       { &hf_samr_total_size,
+               { "Total Size", "samr.total_size", FT_UINT32, BASE_DEC, 
+               NULL, 0x0, "Total size of data", HFILL }},
+
+       { &hf_samr_ret_size,
+               { "Returned Size", "samr.ret_size", FT_UINT32, BASE_DEC, 
+               NULL, 0x0, "Number of returned objects in this PDU", HFILL }},
+
+       { &hf_samr_index,
+               { "Index", "samr.index", FT_UINT32, BASE_DEC, 
+               NULL, 0x0, "Index", HFILL }},
+
+       { &hf_samr_acct_ctrl,
+               { "Acct Ctrl", "samr.acct_ctrl", FT_UINT32, BASE_DEC, 
+               NULL, 0x0, "Acct CTRL", HFILL }},
+
+        { &hf_samr_array_max_count,
+          { "Max Count", "samr.array.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum Count: Number of elements in the conformant array", HFILL }},
+
+       { &hf_samr_acct_name,
+               { "Account Name", "samr.acct_name", FT_STRING, BASE_NONE,
+               NULL, 0, "Name of Account", HFILL }},
+
+       { &hf_samr_server,
+               { "Server", "samr.server", FT_STRING, BASE_NONE,
+               NULL, 0, "Name of Server", HFILL }},
+
+       { &hf_samr_domain,
+               { "Domain", "samr.domain", FT_STRING, BASE_NONE,
+               NULL, 0, "Name of Domain", HFILL }},
+
+       { &hf_samr_controller,
+               { "DC", "samr.dc", FT_STRING, BASE_NONE,
+               NULL, 0, "Name of Domain Controller", HFILL }},
+
+       { &hf_samr_full_name,
+               { "Full Name", "samr.full_name", FT_STRING, BASE_NONE,
+               NULL, 0, "Full Name of Account", HFILL }},
 
        { &hf_samr_acct_desc,
                { "Account Desc", "samr.acct_desc", FT_STRING, BASE_NONE,
                NULL, 0, "Account Description", HFILL }},
 
+       { &hf_samr_unknown_string,
+               { "Unknwon string", "samr.unknown_string", FT_STRING, BASE_NONE,
+               NULL, 0, "Unknown string. If you know what this is, contact ethereal developers.", HFILL }},
+
+       { &hf_samr_unknown_hyper,
+               { "Unknown hyper", "samr.unknown.hyper", FT_UINT64, BASE_HEX, 
+               NULL, 0x0, "Unknown hyper. If you know what this is, contact ethereal developers.", HFILL }},
+       { &hf_samr_unknown_long,
+               { "Unknown long", "samr.unknown.long", FT_UINT32, BASE_HEX, 
+               NULL, 0x0, "Unknown long. If you know what this is, contact ethereal developers.", HFILL }},
+
+       { &hf_samr_unknown_short,
+               { "Unknown short", "samr.unknown.short", FT_UINT16, BASE_HEX, 
+               NULL, 0x0, "Unknown short. If you know what this is, contact ethereal developers.", HFILL }},
+
+       { &hf_samr_unknown_char,
+               { "Unknown char", "samr.unknown.char", FT_UINT8, BASE_HEX, 
+               NULL, 0x0, "Unknown char. If you know what this is, contact ethereal developers.", HFILL }},
+
+       { &hf_samr_access,
+               { "Access Mask", "samr.access", FT_UINT32, BASE_HEX, 
+               NULL, 0x0, "Access", HFILL }},
+
+       { &hf_samr_mask,
+               { "Mask", "samr.mask", FT_UINT32, BASE_HEX, 
+               NULL, 0x0, "Mask", HFILL }},
+
+       { &hf_samr_crypt_password, {
+               "Password", "samr.crypt_password", FT_BYTES, BASE_HEX,
+               NULL, 0, "Encrypted Password", HFILL }},
+
+       { &hf_samr_crypt_hash, {
+               "Hash", "samr.crypt_hash", FT_BYTES, BASE_HEX,
+               NULL, 0, "Encrypted Hash", HFILL }},
+
+       { &hf_samr_lm_change, {
+               "LM Change", "samr.lm_change", FT_UINT8, BASE_HEX,
+               NULL, 0, "LM Change value", HFILL }},
+
+       { &hf_samr_max_pwd_age,
+               { "Max Pwd Age", "samr.max_pwd_age", FT_RELATIVE_TIME, BASE_NONE,
+               NULL, 0, "Maximum Password Age before it expires", HFILL }},
+
+       { &hf_samr_min_pwd_age,
+               { "Min Pwd Age", "samr.min_pwd_age", FT_RELATIVE_TIME, BASE_NONE,
+               NULL, 0, "Minimum Password Age before it can be changed", HFILL }},
+       { &hf_samr_unknown_time,
+               { "Unknown time", "samr.unknown_time", FT_ABSOLUTE_TIME, BASE_NONE,
+               NULL, 0, "Unknown NT TIME, contact ethereal developers if you know what this is", HFILL }},
+
+       { &hf_samr_min_pwd_len, {
+               "Min Pwd Len", "samr.min_pwd_len", FT_UINT16, BASE_DEC,
+               NULL, 0, "Minimum Password Length", HFILL }},
+       { &hf_samr_pwd_history_len, {
+               "Pwd History Len", "samr.pwd_history_len", FT_UINT16, BASE_DEC,
+               NULL, 0, "Password History Length", HFILL }},
+       { &hf_samr_num_users, {
+               "Num Users", "samr.num_users", FT_UINT32, BASE_DEC,
+               NULL, 0, "Number of users in this domain", HFILL }},
+       { &hf_samr_num_groups, {
+               "Num Groups", "samr.num_groups", FT_UINT32, BASE_DEC,
+               NULL, 0, "Number of groups in this domain", HFILL }},
+       { &hf_samr_num_aliases, {
+               "Num Aliases", "samr.num_aliases", FT_UINT32, BASE_DEC,
+               NULL, 0, "Number of aliases in this domain", HFILL }},
+       { &hf_samr_resume_hnd, {
+               "Resume Hnd", "samr.resume_hnd", FT_UINT32, BASE_DEC,
+               NULL, 0, "Resume handle", HFILL }},
+
+
+
 
 
        /* these are used by packet-dcerpc-nt.c */
index d1faf92e72c58546c6621ea0000122e665eb95d0..92385349aac0fc5e8b76d6249f8526bc33dd2a96 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for SMB \PIPE\samr packet disassembly
  * Copyright 2001, Tim Potter <tpot@samba.org>
  *
- * $Id: packet-dcerpc-samr.h,v 1.3 2001/12/16 20:08:22 guy Exp $
+ * $Id: packet-dcerpc-samr.h,v 1.4 2002/01/29 09:13:28 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #define SAMR_CLOSE_HND         0x01
 #define SAMR_UNKNOWN_2         0x02
 #define SAMR_QUERY_SEC_OBJECT  0x03
-#define SAMR_UNKNOWN_4         0x04
+#define SAMR_SHUTDOWN_SAM_SERVER         0x04
 #define SAMR_LOOKUP_DOMAIN     0x05
 #define SAMR_ENUM_DOMAINS      0x06
 #define SAMR_OPEN_DOMAIN       0x07
 #define SAMR_QUERY_DOMAIN_INFO 0x08
+#define SAMR_SET_DOMAIN_INFO   0x09
 #define SAMR_CREATE_DOM_GROUP  0x0a
 #define SAMR_ENUM_DOM_GROUPS   0x0b
+#define SAMR_CREATE_USER_IN_DOMAIN 0x0c
 #define SAMR_ENUM_DOM_USERS    0x0d
 #define SAMR_CREATE_DOM_ALIAS  0x0e
 #define SAMR_ENUM_DOM_ALIASES  0x0f
-#define SAMR_QUERY_USERALIASES 0x10
+#define SAMR_GET_ALIAS_MEMBERSHIP 0x10
 #define SAMR_LOOKUP_NAMES      0x11
 #define SAMR_LOOKUP_RIDS       0x12
 #define SAMR_OPEN_GROUP        0x13
 #define SAMR_DELETE_DOM_GROUP  0x17
 #define SAMR_DEL_GROUPMEM      0x18
 #define SAMR_QUERY_GROUPMEM    0x19
-#define SAMR_UNKNOWN_1A        0x1a
+#define SAMR_SET_MEMBER_ATTRIBUTES_OF_GROUP        0x1a
 #define SAMR_OPEN_ALIAS        0x1b
 #define SAMR_QUERY_ALIASINFO   0x1c
 #define SAMR_SET_ALIASINFO     0x1d
 #define SAMR_DELETE_DOM_ALIAS  0x1e
 #define SAMR_ADD_ALIASMEM      0x1f
 #define SAMR_DEL_ALIASMEM      0x20
-#define SAMR_QUERY_ALIASMEM    0x21
+#define SAMR_GET_MEMBERS_IN_ALIAS   0x21
 #define SAMR_OPEN_USER         0x22
 #define SAMR_DELETE_DOM_USER   0x23
 #define SAMR_QUERY_USERINFO    0x24
 #define SAMR_SET_USERINFO2     0x25
-#define SAMR_QUERY_USERGROUPS  0x27
+#define SAMR_CHANGE_PASSWORD_USER  0x26
+#define SAMR_GET_GROUPS_FOR_USER  0x27
 #define SAMR_QUERY_DISPINFO    0x28
-#define SAMR_UNKNOWN_29        0x29
-#define SAMR_UNKNOWN_2a        0x2a
-#define SAMR_UNKNOWN_2b        0x2b
+#define SAMR_GET_DISPLAY_ENUMERATION_INDEX        0x29
+#define SAMR_TEST_PRIVATE_FUNCTIONS_DOMAIN        0x2a
+#define SAMR_TEST_PRIVATE_FUNCTIONS_USER        0x2b
 #define SAMR_GET_USRDOM_PWINFO 0x2c
-#define SAMR_UNKNOWN_2D        0x2d
-#define SAMR_UNKNOWN_2e        0x2e
+#define SAMR_REMOVE_MEMBER_FROM_FOREIGN_DOMAIN     0x2d
+#define SAMR_QUERY_INFORMATION_DOMAIN2    0x2e
 #define SAMR_UNKNOWN_2f        0x2f
-#define SAMR_QUERY_DISPINFO3   0x30
-#define SAMR_UNKNOWN_31        0x31
-#define SAMR_CREATE_USER       0x32
-#define SAMR_QUERY_DISPINFO4   0x33
-#define SAMR_ADDMULTI_ALIASMEM 0x34
-#define SAMR_UNKNOWN_35        0x35
-#define SAMR_UNKNOWN_36        0x36
-#define SAMR_CHGPASSWD_USER    0x37
+#define SAMR_QUERY_DISPINFO2   0x30
+#define SAMR_GET_DISPLAY_ENUMERATION_INDEX2        0x31
+#define SAMR_CREATE_USER2_IN_DOMAIN       0x32
+#define SAMR_QUERY_DISPINFO3   0x33
+#define SAMR_ADD_MULTIPLE_MEMBERS_TO_ALIAS 0x34
+#define SAMR_REMOVE_MULTIPLE_MEMBERS_FROM_ALIAS     0x35
+#define SAMR_OEM_CHANGE_PASSWORD_USER2        0x36
+#define SAMR_UNICODE_CHANGE_PASSWORD_USER2    0x37
 #define SAMR_GET_DOM_PWINFO    0x38
-#define SAMR_CONNECT           0x39
+#define SAMR_CONNECT2          0x39
 #define SAMR_SET_USERINFO      0x3A
+#define SAMR_UNKNOWN_3B                0x3B
+#define SAMR_UNKNOWN_3C                0x3C
 
 #endif /* packet-dcerpc-samr.h */
index 0b53fb99ace499b5b4cb729c0cabcfea0b0b3fff..ea70a8c922fc560a9b79c3176236c29eedaa12f1 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for DCERPC packet disassembly
  * Copyright 2001, Todd Sabin <tas@webspan.net>
  *
- * $Id: packet-dcerpc.c,v 1.27 2002/01/25 08:35:59 guy Exp $
+ * $Id: packet-dcerpc.c,v 1.28 2002/01/29 09:13:28 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -170,6 +170,8 @@ static int hf_dcerpc_dg_seqnum = -1;
 static int hf_dcerpc_dg_server_boot = -1;
 static int hf_dcerpc_dg_if_ver = -1;
 static int hf_dcerpc_array_max_count = -1;
+static int hf_dcerpc_array_offset = -1;
+static int hf_dcerpc_array_actual_count = -1;
 
 static gint ett_dcerpc = -1;
 static gint ett_dcerpc_cn_flags = -1;
@@ -388,6 +390,29 @@ dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
     return offset+4;
 }
 
+int
+dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                       proto_tree *tree, char *drep, 
+                       int hfindex, unsigned char *pdata)
+{
+    if(pdata){
+      tvb_memcpy(tvb, pdata, offset, 8);
+      if(drep[0] & 0x10){/* XXX this might be the wrong way around */
+       unsigned char data;
+       data=pdata[0];pdata[0]=pdata[7];pdata[7]=data;
+       data=pdata[1];pdata[1]=pdata[6];pdata[6]=data;
+       data=pdata[2];pdata[2]=pdata[5];pdata[5]=data;
+       data=pdata[3];pdata[3]=pdata[4];pdata[4]=data;
+      }
+    }
+
+    if (tree) {
+        proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
+    }
+
+    return offset+8;
+}
+
 /*
  * a couple simpler things
  */
@@ -425,19 +450,58 @@ dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, char *drep, e_uuid_t *uuid)
 }
 
 
+
 /* NDR arrays */
 /* function to dissect a unidimensional conformant array */
 int 
 dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
-                        proto_tree *tree, char *drep, 
-                        dcerpc_dissect_fnct_t *fnct)
+               proto_tree *tree, char *drep, 
+               dcerpc_dissect_fnct_t *fnct)
 {
        guint32 i, count;
+       dcerpc_info *di;
 
-        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
-                                     hf_dcerpc_array_max_count, &count);
-       for(i=0;i<count;i++){
-               offset = (*fnct)(tvb, offset, pinfo, tree, drep);
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /* conformant run, just dissect the max_count header */
+               di->conformant_run=0;
+               offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                               hf_dcerpc_array_max_count, &di->array_max_count);
+               di->conformant_run=1;
+       } else {
+               /* real run, dissect the elements */
+               for(i=0;i<di->array_max_count;i++){
+                       offset = (*fnct)(tvb, offset, pinfo, tree, drep);
+               }
+       }
+
+       return offset;
+}
+/* function to dissect a unidimensional conformant and varying array */
+int 
+dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+               proto_tree *tree, char *drep, 
+               dcerpc_dissect_fnct_t *fnct)
+{
+       guint32 i, count;
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /* conformant run, just dissect the max_count header */
+               di->conformant_run=0;
+               offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                               hf_dcerpc_array_max_count, &di->array_max_count);
+               offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                               hf_dcerpc_array_offset, &di->array_offset);
+               offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                               hf_dcerpc_array_actual_count, &di->array_actual_count);
+               di->conformant_run=1;
+       } else {
+               /* real run, dissect the elements */
+               for(i=0;i<di->array_actual_count;i++){
+                       offset = (*fnct)(tvb, offset, pinfo, tree, drep);
+               }
        }
 
        return offset;
@@ -464,8 +528,13 @@ typedef struct ndr_pointer_data {
 } ndr_pointer_data_t;
 
 static void
-init_ndr_pointer_list(void)
+init_ndr_pointer_list(packet_info *pinfo)
 {
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       di->conformant_run=0;
+
        while(ndr_pointer_list){
                ndr_pointer_data_t *npd;
        
@@ -504,6 +573,13 @@ dissect_deferred_pointers(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, i
                                tnpd->fnct=NULL;
                                ndr_pointer_list_pos=i+1;
                                di->hf_index=tnpd->hf_index;
+
+                               /* first a run to handle any conformant
+                                  array headers */
+                               di->conformant_run=1;
+                               offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
+                               /* now we dissect the actual pointer */
+                               di->conformant_run=0;
                                offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, drep);
                                break;
                        }
@@ -583,6 +659,16 @@ dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                         proto_tree *tree, char *drep, 
                         dcerpc_dissect_fnct_t *fnct, int type, int hf_index)
 {
+       dcerpc_info *di;
+
+       di=pinfo->private_data;
+       if(di->conformant_run){
+               /* this call was only for dissecting the header for any
+                  embedded conformant array. we will not parse any
+                  pointers in this mode.
+               */
+               return offset;
+       }
 
        /*TOP LEVEL REFERENCE POINTER*/
        if( pointers_are_top_level
@@ -705,6 +791,8 @@ after_ref_id:
        return offset;
 }
 
+
+
 static int
 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
                     proto_tree *dcerpc_tree,
@@ -777,7 +865,7 @@ dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
         pinfo->current_proto = sub_proto->name;
        pinfo->private_data = (void *)info;
 
-       init_ndr_pointer_list();
+       init_ndr_pointer_list(pinfo);
         offset = sub_dissect (tvb, offset, pinfo, sub_tree, drep);
 
         pinfo->current_proto = saved_proto;
@@ -2024,6 +2112,12 @@ proto_register_dcerpc (void)
         { &hf_dcerpc_array_max_count,
           { "Max Count", "dcerpc.array.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum Count: Number of elements in the array", HFILL }},
 
+        { &hf_dcerpc_array_offset,
+          { "Offset", "dcerpc.array.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "Offset for first element in array", HFILL }},
+
+        { &hf_dcerpc_array_actual_count,
+          { "Actual Count", "dcerpc.array.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Actual Count: Actual number of elements in the array", HFILL }},
+
 
     };
     static gint *ett[] = {
index 92ec7e100cabe6be12a74b5a203fc90941ad5cde..941a6868360b56e92b3294558c92c3c6f0c312e0 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-dcerpc.h
  * Copyright 2001, Todd Sabin <tas@webspan.net>
  *
- * $Id: packet-dcerpc.h,v 1.9 2002/01/25 08:35:59 guy Exp $
+ * $Id: packet-dcerpc.h,v 1.10 2002/01/29 09:13:28 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -107,6 +107,9 @@ int dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 int dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                            proto_tree *tree, char *drep, 
                            int hfindex, guint32 *pdata);
+int dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                           proto_tree *tree, char *drep, 
+                           int hfindex, unsigned char *pdata);
 
 
 /*
@@ -121,6 +124,9 @@ int dissect_ndr_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
 int dissect_ndr_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                         proto_tree *tree, char *drep, 
                         int hfindex, guint32 *pdata);
+int dissect_ndr_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                        proto_tree *tree, char *drep, 
+                        int hfindex, unsigned char *pdata);
 int dissect_ndr_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo,
                         proto_tree *tree, char *drep, 
                         int hfindex, e_uuid_t *pdata);
@@ -143,6 +149,12 @@ int dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                         proto_tree *tree, char *drep, 
                         dcerpc_dissect_fnct_t *fnct);
 
+/* dissect a NDR unidimensional conformant and varying array */
+int dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                        proto_tree *tree, char *drep, 
+                        dcerpc_dissect_fnct_t *fnct);
+
+
 
 typedef struct _dcerpc_sub_dissector {
     guint16 num;
@@ -186,6 +198,10 @@ typedef struct _dcerpc_info {
        guint32 call_id;        /* Context id for this call */
        guint16 smb_fid;        /* FID for DCERPC over SMB */
        gboolean request;
+       gboolean conformant_run;
+       guint32 array_max_count;        /* max_count for conformant arrays */
+       guint32 array_offset;
+       guint32 array_actual_count;     
        int hf_index;
        dcerpc_call_value *call_data;
 } dcerpc_info;