r1766: we do not have smb_read_error in samba4
[samba.git] / source4 / build / pidl / packet-dcerpc-eparser.c
index 4762ac9278c904ae50e7c18fc3a574c7395334c7..bf2b6e798169af810bbc00de9dccd19ab7c327c1 100644 (file)
@@ -3,6 +3,7 @@
 #endif
 
 #include "tvbuff.h"
+#include <string.h>
 
 #include "packet-dcerpc.h"
 #include "packet-dcerpc-nt.h"
@@ -12,6 +13,9 @@ static int hf_string4_len = -1;
 static int hf_string4_offset = -1;
 static int hf_string4_len2 = -1;
 static int hf_string_data = -1;
+static int hf_subtree_list = -1;
+
+static gint ett_array = -1;
 
 /* Create a ndr_pull structure from data stored in a tvb at a given offset. */
 
@@ -53,11 +57,18 @@ void ndr_pull_level(struct e_ndr_pull *ndr, proto_tree *tree, int hf,
                tree, ndr->drep, hf, data);
 }
 
-void ndr_pull_NTSTATUS(struct e_ndr_pull *ndr, proto_tree *tree, int hf)
+void ndr_pull_NTSTATUS(struct e_ndr_pull *ndr, proto_tree *tree, int hf, gNTSTATUS *data)
 {
        ndr->offset = dissect_ntstatus(
                ndr->tvb, ndr->offset, ndr->pinfo,
-               tree, ndr->drep, hf, NULL);
+               tree, ndr->drep, hf, data);
+}
+
+void ndr_pull_WERROR(struct e_ndr_pull *ndr, proto_tree *tree, int hf, gWERROR *data)
+{
+       ndr->offset = dissect_werror(
+               ndr->tvb, ndr->offset, ndr->pinfo,
+               tree, ndr->drep, hf, data);
 }
 
 void ndr_pull_uint8(struct e_ndr_pull *ndr, proto_tree *tree, int hf, 
@@ -100,6 +111,37 @@ void ndr_pull_uint64(struct e_ndr_pull *ndr, proto_tree *tree, int hf,
                tree, ndr->drep, hf, data);     
 }
 
+void ndr_pull_DATA_BLOB(struct e_ndr_pull *ndr, proto_tree *tree, int hf, gDATA_BLOB *h)
+{
+       guint32 length;
+
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return;
+       }
+
+       if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
+               if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+                       length = NDR_ALIGN(ndr, 2);
+               } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
+                       length = NDR_ALIGN(ndr, 4);
+               } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
+                       length = NDR_ALIGN(ndr, 8);
+               }
+               if (ndr->data_size - ndr->offset < length) {
+                       length = ndr->data_size - ndr->offset;
+               }
+       } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
+               length = ndr->data_size - ndr->offset;
+       } else {
+               ndr_pull_uint32(ndr, &length);
+       }
+
+       h->data = g_malloc(length);
+       proto_tree_add_bytes(tree, hf_bytes_data, ndr->tvb, ndr->offset, length, h->data);
+       
+    ndr->offset += length;
+}
+
 void ndr_pull_string(struct e_ndr_pull *ndr, proto_tree *tree, int ndr_flags)
 {
        guint32 len1, ofs, len2;
@@ -317,6 +359,7 @@ void ndr_pull_HYPER_T(struct e_ndr_pull *ndr, proto_tree *tree, int hf,
 void ndr_pull_dom_sid2(struct e_ndr_pull *ndr, proto_tree *tree, int flags)
 {
        guint32 num_auths;
+
        if (!(flags & NDR_SCALARS)) {
                return;
        }
@@ -337,9 +380,9 @@ void ndr_pull_align(struct e_ndr_pull *ndr, int size)
        }
 }
 
-void ndr_pull_subcontext_flags_fn(struct e_ndr_pull *ndr, proto_tree *tree,
-                                 size_t sub_size,
-                                 void (*fn)(struct e_ndr_pull *, 
+void ndr_pull_subcontext_flags_fn(struct e_ndr_pull *ndr,
+                                 proto_tree *tree, size_t sub_size,
+                                 void (*fn)(struct e_ndr_pull *,
                                             proto_tree *tree, int ndr_flags))
 {
        struct e_ndr_pull ndr2;
@@ -445,7 +488,7 @@ void ndr_pull_set_offset(struct e_ndr_pull *ndr, guint32 ofs)
 static int hf_relative_ofs = -1;
 
 void ndr_pull_relative(struct e_ndr_pull *ndr, proto_tree *tree,
-                      void (*fn)(struct e_ndr_pull *, 
+                      void (*fn)(struct e_ndr_pull *,
                                  proto_tree *tree, int ndr_flags))
 {
        struct e_ndr_pull ndr2;
@@ -506,6 +549,18 @@ void ndr_pull_array_uint8(struct e_ndr_pull *ndr, proto_tree *tree, int hf,
        }       
 }
 
+void ndr_pull_array_uint16(struct e_ndr_pull *ndr, proto_tree *tree, int hf, 
+                         int ndr_flags, guint32 n)
+{
+       guint32 i;
+       if (!(ndr_flags & NDR_SCALARS)) {
+               return;
+       }
+       for (i=0;i<n;i++) {
+               ndr_pull_uint16(ndr, tree, hf, NULL);
+       }       
+}
+
 void ndr_pull_array_uint32(struct e_ndr_pull *ndr, proto_tree *tree, int hf, 
                           int ndr_flags, guint32 n)
 {
@@ -523,17 +578,78 @@ void ndr_pull_array(struct e_ndr_pull *ndr, proto_tree *tree, int ndr_flags,
                                                   proto_tree *tree,
                                                   int ndr_flags))
 {
+       proto_tree **subtrees;
        int i;
+
+       subtrees = (proto_tree **)g_malloc(sizeof(proto_tree **) * count);
+
        if (!(ndr_flags & NDR_SCALARS)) goto buffers;
        for (i=0;i<count;i++) {
-               pull_fn(ndr, tree, NDR_SCALARS);
+               proto_item *item;
+               item = proto_tree_add_text(tree, ndr->tvb, ndr->offset, 0, "Array entry");
+               subtrees[i] = proto_item_add_subtree(item, ett_array);
+
+               if ((ndr_flags & (NDR_SCALARS|NDR_BUFFERS)) == (NDR_SCALARS|NDR_BUFFERS))
+                       pull_fn(ndr, subtrees[i], NDR_SCALARS);
+               else
+                       pull_fn(ndr, tree, NDR_SCALARS);
+
        }
        if (!(ndr_flags & NDR_BUFFERS)) goto done;
 buffers:
        for (i=0;i<count;i++) {
-               pull_fn(ndr, tree, NDR_BUFFERS);
+               if ((ndr_flags & (NDR_SCALARS|NDR_BUFFERS)) == (NDR_SCALARS|NDR_BUFFERS))
+                       pull_fn(ndr, subtrees[i], NDR_BUFFERS);
+               else
+                       pull_fn(ndr, tree, NDR_BUFFERS);
        }
- done: ;
+ done: 
+       g_free(subtrees);
+}
+
+struct subtree_info {
+       char *name;
+       proto_tree *subtree;
+};
+
+proto_tree *get_subtree(proto_tree *tree, char *name, struct e_ndr_pull *ndr,
+                       gint ett)
+{
+       GSList *list, *l;
+       proto_item *item;
+       struct subtree_info *info;
+
+       /* Get current list value */
+
+       if (!tree)
+               return NULL;
+
+       list = (GSList *)tree->user_data;
+
+       /* Look for name */
+
+       for (l = list; l; l = g_slist_next(l)) {
+               info = l->data;
+               
+               if (strcmp(name, info->name) == 0)
+                       return info->subtree;
+       }
+       
+       /* Create new subtree entry */
+       
+       info = (struct subtree_info *)g_malloc(sizeof(struct subtree_info));
+       
+       info->name = g_strdup(name);
+       item = proto_tree_add_text(tree, ndr->tvb, ndr->offset, 0, name);
+       info->subtree = proto_item_add_subtree(item, ett);
+
+       /* Don't forget to add new list head */
+
+       list = g_slist_append(list, info);
+
+       tree->user_data = list;
+
+       return info->subtree;
 }
 
 void proto_register_eparser(void)
@@ -546,10 +662,14 @@ void proto_register_eparser(void)
        { &hf_subcontext_size_2, { "Subcontext size2", "eparser.subcontext_size2", FT_UINT16, BASE_DEC, NULL, 0x0, "Subcontext size2", HFILL }},
        { &hf_subcontext_size_4, { "Subcontext size4", "eparser.subcontext_size4", FT_UINT16, BASE_DEC, NULL, 0x0, "Subcontext size4", HFILL }},
        { &hf_relative_ofs, { "Relative offset", "eparser.relative_offset", FT_UINT32, BASE_DEC, NULL, 0x0, "Relative offset", HFILL }},
+       { &hf_subtree_list, { "Subtree list", "", FT_UINT64, BASE_DEC, NULL, 0, "", HFILL }},
+       };
+       static gint *ett[] = {
+               &ett_array,
        };
-
        int proto_dcerpc;
        
        proto_dcerpc = proto_get_id_by_filter_name("dcerpc");
        proto_register_field_array(proto_dcerpc, hf, array_length(hf));
+       proto_register_subtree_array(ett, array_length(ett));
 }