int
dissect_IDispatch_Invoke_rqst(tvbuff_t *tvb, int offset,
                              packet_info *pinfo, proto_tree *tree, guint8 *drep)
{
    guint32 u32DispIdMember;
    e_uuid_t riid;
    guint32 u32Lcid;
    guint32 u32Flags;
    guint32 u32Args;
    guint32 u32NamedArgs;
    guint32 u32Pointer;
    guint32 u32Pointer2;
    guint32 u32ArraySize;
    guint32 u32VariableOffset;
    guint32 u32VarRef;
    guint32 u32VarRefIdx;
    guint32 u32TmpOffset;
    guint32 u32SubStart;

    proto_item *feature_item;
    proto_tree *feature_tree;
    proto_item *dispparams_item;
    proto_tree *dispparams_tree;


    offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep);

    offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep,
                                hf_dispatch_id, &u32DispIdMember);
    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_append_fstr(pinfo->cinfo, COL_INFO, " ID=0x%x", u32DispIdMember);
    }

    offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, drep,
                               hf_dispatch_riid, &riid);
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep,
                                hf_dispatch_lcid, &u32Lcid);

    /* dispatch flags */
    u32TmpOffset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL, drep,
                                      hf_dispatch_flags, &u32Flags);
    feature_item = proto_tree_add_uint (tree, hf_dispatch_flags, tvb, offset, 4, u32Flags);
    feature_tree = proto_item_add_subtree (feature_item, ett_dispatch_flags);
    if (feature_tree) {
        proto_tree_add_boolean (feature_tree, hf_dispatch_flags_propputref, tvb, offset, 4, u32Flags);
        proto_tree_add_boolean (feature_tree, hf_dispatch_flags_propput, tvb, offset, 4, u32Flags);
        proto_tree_add_boolean (feature_tree, hf_dispatch_flags_propget, tvb, offset, 4, u32Flags);
        proto_tree_add_boolean (feature_tree, hf_dispatch_flags_method, tvb, offset, 4, u32Flags);
    }

    if (u32Flags & DISPATCH_FLAGS_METHOD) {
        proto_item_append_text(feature_item, ", Method");
        col_append_str(pinfo->cinfo, COL_INFO, " Method");
    }
    if (u32Flags & DISPATCH_FLAGS_PROPGET) {
        proto_item_append_text(feature_item, ", PropertyGet");
        col_append_str(pinfo->cinfo, COL_INFO, " PropertyGet");
    }
    if (u32Flags & DISPATCH_FLAGS_PROPPUT) {
        proto_item_append_text(feature_item, ", PropertyPut");
        col_append_str(pinfo->cinfo, COL_INFO, " PropertyPut");
    }
    if (u32Flags & DISPATCH_FLAGS_PROPPUTREF) {
        proto_item_append_text(feature_item, ", PropertyPutRef");
        col_append_str(pinfo->cinfo, COL_INFO, " PropertyPutRef");
    }

    offset = u32TmpOffset;

    dispparams_item = proto_tree_add_item(tree, hf_dispatch_dispparams, tvb, offset, 0, FALSE);
    dispparams_tree = proto_item_add_subtree (dispparams_item, ett_dispatch_params);
    u32SubStart = offset;

    /* DISPPARAMS */
    /* VARIANT rgvarg[u32Args] */
    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, dispparams_tree, drep,
                                         &u32Pointer);

    /* DISPID rgdispidNamedArgs[u32NamedArgs] */
    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, dispparams_tree, drep,
                                         &u32Pointer2);

    offset = dissect_dcom_DWORD(tvb, offset, pinfo, dispparams_tree, drep,
                                hf_dispatch_args, &u32Args);
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, dispparams_tree, drep,
                                hf_dispatch_named_args, &u32NamedArgs);

    if (u32Pointer) {
        offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, dispparams_tree, drep,
                                                &u32ArraySize);
        u32VariableOffset = offset + u32ArraySize * 4;
        while(u32ArraySize--) {
            offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, dispparams_tree, drep,
                                                 &u32Pointer);
            if (u32Pointer) {
                u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, dispparams_tree, drep, hf_dispatch_arg);
            }
        }
        offset = u32VariableOffset;
    }

    /* DISPID rgdispidNamedArgs[u32NamedArgs] */
    if (u32Pointer2) {
        offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, dispparams_tree, drep,
                                                &u32ArraySize);
        while(u32ArraySize--) {
            offset = dissect_dcom_DWORD(tvb, offset, pinfo, dispparams_tree, drep,
                                        hf_dispatch_id, &u32DispIdMember);
        }
    }

    proto_item_append_text(dispparams_item, ", Args: %u NamedArgs: %u", u32Args, u32NamedArgs);
    proto_item_set_len(dispparams_item, offset - u32SubStart);

    /* end of DISPPARAMS */

    /* u32VarRef */
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep,
                                hf_dispatch_varref, &u32VarRef);

    /* rgVarRefIdx: UINT[u32VarRef] */
    offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep,
                                            &u32ArraySize);
    while(u32ArraySize--) {
        offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep,
                                    hf_dispatch_varrefidx, &u32VarRefIdx);
    }

    /* rgVarRef: VARIANT[u32VarRef] */
    offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep,
                                            &u32ArraySize);
    u32VariableOffset = offset + u32ArraySize * 4;
    while(u32ArraySize--) {
        offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep,
                                             &u32Pointer);
        if (u32Pointer) {
            u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, tree, drep, hf_dispatch_varrefarg);
        }
    }

    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_append_fstr(pinfo->cinfo, COL_INFO,
                        " Args=%u NamedArgs=%u VarRef=%u", u32Args, u32NamedArgs, u32VarRef);
    }

    return u32VariableOffset;
}
int
dissect_IDispatch_Invoke_resp(tvbuff_t *tvb, int offset,
                              packet_info *pinfo, proto_tree *tree, guint8 *drep)
{
    guint32 u32Pointer;
    guint32 u32Pointer2;
    guint32 u32Pointer3;
    guint32 u32VariableOffset;
    guint32 u32ArraySize;
    guint32 u32SubStart;
    guint16 u16Code;
    guint16 u16Reserved;
    guint32 u32HelpContext;
    guint32 u32Reserved;
    guint32 u32DeferredFillIn;
    guint32 u32ArgErr;
    guint32 u32HResult;
    guint32 u32SCode;
    guint32 u32VarRef;
    gchar       szName[1000] = { 0 };
    proto_item *excepinfo_item;
    proto_tree *excepinfo_tree;


    offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep);

    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep,
                                         &u32Pointer);
    if (u32Pointer) {
        offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, drep, hf_dispatch_varresult);
    }

    /* ExcepInfo */
    excepinfo_item = proto_tree_add_item(tree, hf_dispatch_excepinfo, tvb, offset, 0, FALSE);
    excepinfo_tree = proto_item_add_subtree (excepinfo_item, ett_dispatch_excepinfo);
    u32SubStart = offset;

    offset = dissect_dcom_WORD(tvb, offset, pinfo, excepinfo_tree, drep,
                               hf_dispatch_code, &u16Code);
    offset = dissect_dcom_WORD(tvb, offset, pinfo, excepinfo_tree, drep,
                               hf_dispatch_reserved16, &u16Reserved);
    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, excepinfo_tree, drep,
                                         &u32Pointer);
    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, excepinfo_tree, drep,
                                         &u32Pointer2);
    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, excepinfo_tree, drep,
                                         &u32Pointer3);
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, excepinfo_tree, drep,
                                hf_dispatch_help_context, &u32HelpContext);
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, excepinfo_tree, drep,
                                hf_dispatch_reserved32, &u32Reserved);
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, excepinfo_tree, drep,
                                hf_dispatch_deferred_fill_in, &u32DeferredFillIn);
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, excepinfo_tree, drep,
                                hf_dispatch_scode, &u32SCode);

    if (u32Pointer) {
        offset = dissect_dcom_BSTR(tvb, offset, pinfo, excepinfo_tree, drep,
                                   hf_dispatch_source, szName, sizeof(szName));
    }
    if (u32Pointer2) {
        offset = dissect_dcom_BSTR(tvb, offset, pinfo, excepinfo_tree, drep,
                                   hf_dispatch_description, szName, sizeof(szName));
    }
    if (u32Pointer3) {
        offset = dissect_dcom_BSTR(tvb, offset, pinfo, excepinfo_tree, drep,
                                   hf_dispatch_help_file, szName, sizeof(szName));
    }

    proto_item_append_text(excepinfo_item, ", SCode: %s",
                           val_to_str(u32SCode, dcom_hresult_vals, "Unknown (0x%08x)"));
    proto_item_set_len(excepinfo_item, offset - u32SubStart);
    /* end of ExcepInfo */

    offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep,
                                hf_dispatch_arg_err, &u32ArgErr);

    /* rgVarRef: VARIANT[u32VarRef] */
    offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep,
                                            &u32ArraySize);
    u32VarRef = u32ArraySize;
    u32VariableOffset = offset + u32ArraySize * 4;
    while(u32ArraySize--) {
        offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep,
                                             &u32Pointer);
        if (u32Pointer) {
            u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, tree, drep, hf_dispatch_varrefarg);
        }
    }
    offset = u32VariableOffset;

    /* HRESULT of call */
    offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep,
                                  &u32HResult);

    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_append_fstr(pinfo->cinfo, COL_INFO, " SCode=%s VarRef=%u -> %s",
                        val_to_str(u32SCode, dcom_hresult_vals, "Unknown (0x%08x)"),
                        u32VarRef,
                        val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
    }

    return offset;
}
static int
dissect_remunk_remqueryinterface_resp(tvbuff_t *tvb, int offset,
                                      packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
{
    guint32      u32Pointer;
    guint32      u32ArraySize;
    guint32      u32ItemIdx;
    proto_item  *sub_item;
    proto_tree  *sub_tree;
    guint32      u32HResult;
    guint32      u32SubStart;
    e_uuid_t     iid;
    e_uuid_t     iid_null = DCERPC_UUID_NULL;
    remunk_remqueryinterface_call_t *call = (remunk_remqueryinterface_call_t *)di->call_data->private_data;
    guint64      oxid;
    guint64      oid;
    e_uuid_t     ipid;


    offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);

    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep,
                                         &u32Pointer);
    offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
                                            &u32ArraySize);

    u32ItemIdx = 1;
    while (u32ArraySize--) {
        /* add subtree */
        sub_item = proto_tree_add_item(tree, hf_remunk_qiresult, tvb, offset, 0, ENC_NA);
        sub_tree = proto_item_add_subtree(sub_item, ett_remunk_rqi_result);

        /* REMQIRESULT */
        offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
                                      &u32HResult);
        u32SubStart = offset - 4;
        offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep,
                                             &u32Pointer);

        /* try to read the iid from the request */
        if(call != NULL && u32ItemIdx <= call->iid_count) {
            iid = call->iids[u32ItemIdx-1];
        } else {
            iid = iid_null;
        }

        /* XXX - this doesn't seem to be dependent on the pointer above?!? */
        /*if (u32Pointer) {*/
        offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, 0 /* hfindex */,
                                        &oxid, &oid, &ipid);
        /*}*/

        /* add interface instance to database (we currently only handle IPv4) */
        if(pinfo->net_src.type == AT_IPv4) {
            dcom_interface_new(pinfo,
                               (guint8 *)pinfo->net_src.data,
                               &iid, oxid, oid, &ipid);
        }

        /* update subtree */
        proto_item_append_text(sub_item, "[%u]: %s",
                               u32ItemIdx,
                               val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
        proto_item_set_len(sub_item, offset - u32SubStart);

        /* update column info now */
        col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]",
                        val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)"),
                        u32ItemIdx);
        u32ItemIdx++;
    }

    /* HRESULT of call */
    offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
                                  &u32HResult);

    /* update column info now */
    col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
                    val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)"));

    return offset;
}