1 /* packet-dcom-dispatch.c
2  * Routines for DCOM IDispatch
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10 
11 /* see packet-dcom.c for details about DCOM */
12 
13 #include "config.h"
14 
15 
16 #include <epan/packet.h>
17 #include "packet-dcerpc.h"
18 #include "packet-dcom.h"
19 #include "packet-dcom-dispatch.h"
20 
21 void proto_register_dcom_dispatch(void);
22 void proto_reg_handoff_dcom_dispatch(void);
23 
24 static int hf_dispatch_opnum = -1;
25 
26 static int hf_dispatch_riid = -1;
27 static int hf_dispatch_name = -1;
28 static int hf_dispatch_names = -1;
29 static int hf_dispatch_lcid = -1;
30 static int hf_dispatch_id = -1;
31 
32 static int hf_dispatch_arg = -1;
33 static int hf_dispatch_args = -1;
34 static int hf_dispatch_named_args = -1;
35 static int hf_dispatch_varref = -1;
36 static int hf_dispatch_varrefidx = -1;
37 static int hf_dispatch_varrefarg = -1;
38 
39 static int hf_dispatch_varresult = -1;
40 static int hf_dispatch_code = -1;
41 static int hf_dispatch_reserved16 = -1;
42 static int hf_dispatch_source = -1;
43 static int hf_dispatch_description = -1;
44 static int hf_dispatch_help_file = -1;
45 static int hf_dispatch_help_context = -1;
46 static int hf_dispatch_reserved32 = -1;
47 static int hf_dispatch_deferred_fill_in = -1;
48 static int hf_dispatch_arg_err = -1;
49 
50 static int hf_dispatch_tinfo = -1;
51 static int hf_dispatch_itinfo = -1;
52 static int hf_dispatch_dispparams = -1;
53 static int hf_dispatch_excepinfo = -1;
54 static int hf_dispatch_scode = -1;
55 
56 
57 static int hf_dispatch_flags = -1;
58 static int hf_dispatch_flags_method = -1;
59 static int hf_dispatch_flags_propget = -1;
60 static int hf_dispatch_flags_propput = -1;
61 static int hf_dispatch_flags_propputref = -1;
62 
63 #define DISPATCH_FLAGS_METHOD           1
64 #define DISPATCH_FLAGS_PROPGET          2
65 #define DISPATCH_FLAGS_PROPPUT          4
66 #define DISPATCH_FLAGS_PROPPUTREF       8
67 
68 static gint ett_dispatch_flags = -1;
69 static gint ett_dispatch_params = -1;
70 static gint ett_dispatch_excepinfo = -1;
71 
72 static e_guid_t uuid_dispatch = { 0x00020400, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
73 static guint16  ver_dispatch = 0;
74 static gint ett_dispatch = -1;
75 static int proto_dispatch = -1;
76 
77 
78 /*
79  * See:
80  *
81  *    https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c
82  *    https://docs.microsoft.com/en-us/windows/win32/intl/locale-user-default
83  *    https://docs.microsoft.com/en-us/windows/win32/intl/locale-system-default
84  *    https://docs.microsoft.com/en-us/previous-versions/commerce-server/ee796949(v%3Dcs.20)
85  *
86  * and values from cygwin's winnls.h
87  */
88 static const value_string dcom_lcid_vals[] = {
89     { 0x0000, "Language neutral" },
90     { 0x0400, "LOCALE_USER_DEFAULT" },
91     { 0x0409, "English (United States)" },
92     { 0x0800, "LOCALE_SYSTEM_DEFAULT" },
93     { 0,    NULL }
94 };
95 
96 
97 
98 int
dissect_IDispatch_GetTypeInfoCount_resp(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,dcerpc_info * di,guint8 * drep)99 dissect_IDispatch_GetTypeInfoCount_resp(tvbuff_t *tvb, int offset,
100                                         packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
101 {
102     guint32 u32TInfo;
103     guint32 u32HResult;
104 
105 
106     offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);
107 
108     offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
109                                 hf_dispatch_tinfo, &u32TInfo);
110 
111     /* HRESULT of call */
112     offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
113                                   &u32HResult);
114 
115     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
116                     val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
117 
118     return offset;
119 }
120 
121 int
dissect_IDispatch_GetTypeInfo_rqst(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,dcerpc_info * di,guint8 * drep)122 dissect_IDispatch_GetTypeInfo_rqst(tvbuff_t *tvb, int offset,
123                                    packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
124 {
125     guint32 u32TInfo;
126     guint32 u32Lcid;
127 
128     offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep);
129 
130     offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
131                                 hf_dispatch_tinfo, &u32TInfo);
132     offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
133                                 hf_dispatch_lcid, &u32Lcid);
134 
135     return offset;
136 }
137 
138 
139 int
dissect_IDispatch_GetTypeInfo_resp(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,dcerpc_info * di,guint8 * drep)140 dissect_IDispatch_GetTypeInfo_resp(tvbuff_t *tvb, int offset,
141                                    packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
142 {
143     guint32 u32HResult;
144     guint32 u32Pointer;
145 
146 
147     offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);
148 
149     offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep,
150                                          &u32Pointer);
151     if (u32Pointer) {
152         offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, di, drep, hf_dispatch_itinfo, NULL /* XXX */);
153     }
154 
155     /* HRESULT of call */
156     offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
157                                   &u32HResult);
158 
159     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
160                     val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
161 
162     return offset;
163 }
164 
165 
166 int
dissect_IDispatch_GetIDsOfNames_rqst(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,dcerpc_info * di,guint8 * drep)167 dissect_IDispatch_GetIDsOfNames_rqst(tvbuff_t *tvb, int offset,
168                                      packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
169 {
170     e_guid_t riid;
171     guint32  u32Lcid;
172     gchar    szName[1000] = { 0 };
173     guint32  u32Names;
174     guint32  u32ArraySize;
175     guint32  u32Pointer;
176     guint32  u32Tmp;
177     guint32  u32VariableOffset;
178 
179 
180     offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep);
181 
182     offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, di, drep,
183                                hf_dispatch_riid, &riid);
184 
185     offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
186                                             &u32ArraySize);
187 
188     u32VariableOffset = offset + u32ArraySize * 4;
189 
190     u32Tmp = u32ArraySize;
191     while(u32Tmp--) {
192         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep,
193                                              &u32Pointer);
194         if (u32Pointer) {
195             u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, tree, di, drep,
196                                                     hf_dispatch_name, szName, sizeof(szName));
197             col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", szName);
198         }
199     }
200 
201     offset = u32VariableOffset;
202 
203     offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
204                                 hf_dispatch_names, &u32Names);
205 
206     offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
207                                 hf_dispatch_lcid, &u32Lcid);
208 
209     return offset;
210 }
211 
212 
213 
214 int
dissect_IDispatch_GetIDsOfNames_resp(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,dcerpc_info * di,guint8 * drep)215 dissect_IDispatch_GetIDsOfNames_resp(tvbuff_t *tvb, int offset,
216                                      packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
217 {
218     guint32 u32DispId;
219     guint32 u32ArraySize;
220     guint32 u32Tmp;
221     guint32 u32HResult;
222 
223 
224     offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);
225 
226     offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
227                                             &u32ArraySize);
228 
229     u32Tmp = u32ArraySize;
230     while (u32Tmp--) {
231         offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
232                                     hf_dispatch_id, &u32DispId);
233         col_append_fstr(pinfo->cinfo, COL_INFO, " ID=0x%x", u32DispId);
234     }
235 
236     /* HRESULT of call */
237     offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
238                                   &u32HResult);
239 
240     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
241                     val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
242 
243     return offset;
244 }
245 
246 
247 
248 int
dissect_IDispatch_Invoke_rqst(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,dcerpc_info * di,guint8 * drep)249 dissect_IDispatch_Invoke_rqst(tvbuff_t *tvb, int offset,
250                               packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
251 {
252     guint32 u32DispIdMember;
253     e_guid_t riid;
254     guint32 u32Lcid;
255     guint32 u32Flags;
256     guint32 u32Args;
257     guint32 u32NamedArgs;
258     guint32 u32Pointer;
259     guint32 u32Pointer2;
260     guint32 u32ArraySize;
261     guint32 u32VariableOffset;
262     guint32 u32VarRef;
263     guint32 u32VarRefIdx;
264     guint32 u32TmpOffset;
265     guint32 u32SubStart;
266 
267     proto_item *dispparams_item;
268     proto_tree *dispparams_tree;
269     static int * const flags[] = {
270         &hf_dispatch_flags_propputref,
271         &hf_dispatch_flags_propput,
272         &hf_dispatch_flags_propget,
273         &hf_dispatch_flags_method,
274         NULL
275     };
276 
277 
278     offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep);
279 
280     offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
281                                 hf_dispatch_id, &u32DispIdMember);
282     col_append_fstr(pinfo->cinfo, COL_INFO, " ID=0x%x", u32DispIdMember);
283 
284     offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, di, drep,
285                                hf_dispatch_riid, &riid);
286     offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
287                                 hf_dispatch_lcid, &u32Lcid);
288 
289     /* dispatch flags */
290     u32TmpOffset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL, di, drep, -1, &u32Flags);
291 
292     proto_tree_add_bitmask_value(tree, tvb, offset, hf_dispatch_flags,
293                                 ett_dispatch_flags, flags, u32Flags);
294 
295     if (u32Flags & DISPATCH_FLAGS_METHOD) {
296         col_append_str(pinfo->cinfo, COL_INFO, " Method");
297     }
298     if (u32Flags & DISPATCH_FLAGS_PROPGET) {
299         col_append_str(pinfo->cinfo, COL_INFO, " PropertyGet");
300     }
301     if (u32Flags & DISPATCH_FLAGS_PROPPUT) {
302         col_append_str(pinfo->cinfo, COL_INFO, " PropertyPut");
303     }
304     if (u32Flags & DISPATCH_FLAGS_PROPPUTREF) {
305         col_append_str(pinfo->cinfo, COL_INFO, " PropertyPutRef");
306     }
307 
308     offset = u32TmpOffset;
309 
310     dispparams_item = proto_tree_add_item(tree, hf_dispatch_dispparams, tvb, offset, 0, ENC_NA);
311     dispparams_tree = proto_item_add_subtree (dispparams_item, ett_dispatch_params);
312     u32SubStart = offset;
313 
314     /* DISPPARAMS */
315     /* VARIANT rgvarg[u32Args] */
316     offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, dispparams_tree, di, drep,
317                                          &u32Pointer);
318 
319     /* DISPID rgdispidNamedArgs[u32NamedArgs] */
320     offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, dispparams_tree, di, drep,
321                                          &u32Pointer2);
322 
323     offset = dissect_dcom_DWORD(tvb, offset, pinfo, dispparams_tree, di, drep,
324                                 hf_dispatch_args, &u32Args);
325     offset = dissect_dcom_DWORD(tvb, offset, pinfo, dispparams_tree, di, drep,
326                                 hf_dispatch_named_args, &u32NamedArgs);
327 
328     if (u32Pointer) {
329         offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, dispparams_tree, di, drep,
330                                                 &u32ArraySize);
331         u32VariableOffset = offset + u32ArraySize * 4;
332         while(u32ArraySize--) {
333             offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, dispparams_tree, di, drep,
334                                                  &u32Pointer);
335             if (u32Pointer) {
336                 u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, dispparams_tree, di, drep, hf_dispatch_arg);
337             }
338         }
339         offset = u32VariableOffset;
340     }
341 
342     /* DISPID rgdispidNamedArgs[u32NamedArgs] */
343     if (u32Pointer2) {
344         offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, dispparams_tree, di, drep,
345                                                 &u32ArraySize);
346         while(u32ArraySize--) {
347             offset = dissect_dcom_DWORD(tvb, offset, pinfo, dispparams_tree, di, drep,
348                                         hf_dispatch_id, &u32DispIdMember);
349         }
350     }
351 
352     proto_item_append_text(dispparams_item, ", Args: %u NamedArgs: %u", u32Args, u32NamedArgs);
353     proto_item_set_len(dispparams_item, offset - u32SubStart);
354 
355     /* end of DISPPARAMS */
356 
357     /* u32VarRef */
358     offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
359                                 hf_dispatch_varref, &u32VarRef);
360 
361     /* rgVarRefIdx: UINT[u32VarRef] */
362     offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
363                                             &u32ArraySize);
364     while(u32ArraySize--) {
365         offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
366                                     hf_dispatch_varrefidx, &u32VarRefIdx);
367     }
368 
369     /* rgVarRef: VARIANT[u32VarRef] */
370     offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
371                                             &u32ArraySize);
372     u32VariableOffset = offset + u32ArraySize * 4;
373     while(u32ArraySize--) {
374         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep,
375                                              &u32Pointer);
376         if (u32Pointer) {
377             u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, tree, di, drep, hf_dispatch_varrefarg);
378         }
379     }
380 
381     col_append_fstr(pinfo->cinfo, COL_INFO,
382                     " Args=%u NamedArgs=%u VarRef=%u", u32Args, u32NamedArgs, u32VarRef);
383 
384     return u32VariableOffset;
385 }
386 
387 int
dissect_IDispatch_Invoke_resp(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,dcerpc_info * di,guint8 * drep)388 dissect_IDispatch_Invoke_resp(tvbuff_t *tvb, int offset,
389                               packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
390 {
391     guint32 u32Pointer;
392     guint32 u32Pointer2;
393     guint32 u32Pointer3;
394     guint32 u32VariableOffset;
395     guint32 u32ArraySize;
396     guint32 u32SubStart;
397     guint16 u16Code;
398     guint16 u16Reserved;
399     guint32 u32HelpContext;
400     guint32 u32Reserved;
401     guint32 u32DeferredFillIn;
402     guint32 u32ArgErr;
403     guint32 u32HResult;
404     guint32 u32SCode;
405     guint32 u32VarRef;
406     gchar       szName[1000] = { 0 };
407     proto_item *excepinfo_item;
408     proto_tree *excepinfo_tree;
409 
410 
411     offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);
412 
413     offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep,
414                                          &u32Pointer);
415     if (u32Pointer) {
416         offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, di, drep, hf_dispatch_varresult);
417     }
418 
419     /* ExcepInfo */
420     excepinfo_item = proto_tree_add_item(tree, hf_dispatch_excepinfo, tvb, offset, 0, ENC_NA);
421     excepinfo_tree = proto_item_add_subtree (excepinfo_item, ett_dispatch_excepinfo);
422     u32SubStart = offset;
423 
424     offset = dissect_dcom_WORD(tvb, offset, pinfo, excepinfo_tree, di, drep,
425                                hf_dispatch_code, &u16Code);
426     offset = dissect_dcom_WORD(tvb, offset, pinfo, excepinfo_tree, di, drep,
427                                hf_dispatch_reserved16, &u16Reserved);
428     offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, excepinfo_tree, di, drep,
429                                          &u32Pointer);
430     offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, excepinfo_tree, di, drep,
431                                          &u32Pointer2);
432     offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, excepinfo_tree, di, drep,
433                                          &u32Pointer3);
434     offset = dissect_dcom_DWORD(tvb, offset, pinfo, excepinfo_tree, di, drep,
435                                 hf_dispatch_help_context, &u32HelpContext);
436     offset = dissect_dcom_DWORD(tvb, offset, pinfo, excepinfo_tree, di, drep,
437                                 hf_dispatch_reserved32, &u32Reserved);
438     offset = dissect_dcom_DWORD(tvb, offset, pinfo, excepinfo_tree, di, drep,
439                                 hf_dispatch_deferred_fill_in, &u32DeferredFillIn);
440     offset = dissect_dcom_DWORD(tvb, offset, pinfo, excepinfo_tree, di, drep,
441                                 hf_dispatch_scode, &u32SCode);
442 
443     if (u32Pointer) {
444         offset = dissect_dcom_BSTR(tvb, offset, pinfo, excepinfo_tree, di, drep,
445                                    hf_dispatch_source, szName, sizeof(szName));
446     }
447     if (u32Pointer2) {
448         offset = dissect_dcom_BSTR(tvb, offset, pinfo, excepinfo_tree, di, drep,
449                                    hf_dispatch_description, szName, sizeof(szName));
450     }
451     if (u32Pointer3) {
452         offset = dissect_dcom_BSTR(tvb, offset, pinfo, excepinfo_tree, di, drep,
453                                    hf_dispatch_help_file, szName, sizeof(szName));
454     }
455 
456     proto_item_append_text(excepinfo_item, ", SCode: %s",
457                            val_to_str(u32SCode, dcom_hresult_vals, "Unknown (0x%08x)"));
458     proto_item_set_len(excepinfo_item, offset - u32SubStart);
459     /* end of ExcepInfo */
460 
461     offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
462                                 hf_dispatch_arg_err, &u32ArgErr);
463 
464     /* rgVarRef: VARIANT[u32VarRef] */
465     offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
466                                             &u32ArraySize);
467     u32VarRef = u32ArraySize;
468     u32VariableOffset = offset + u32ArraySize * 4;
469     while(u32ArraySize--) {
470         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep,
471                                              &u32Pointer);
472         if (u32Pointer) {
473             u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, tree, di, drep, hf_dispatch_varrefarg);
474         }
475     }
476     offset = u32VariableOffset;
477 
478     /* HRESULT of call */
479     offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
480                                   &u32HResult);
481 
482     col_append_fstr(pinfo->cinfo, COL_INFO, " SCode=%s VarRef=%u -> %s",
483                     val_to_str(u32SCode, dcom_hresult_vals, "Unknown (0x%08x)"),
484                     u32VarRef,
485                     val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
486 
487     return offset;
488 }
489 
490 
491 
492 /* sub dissector table of IDispatch interface */
493 static dcerpc_sub_dissector dispatch_dissectors[] = {
494     { 0, "QueryInterface", NULL, NULL },
495     { 1, "AddRef", NULL, NULL },
496     { 2, "Release", NULL, NULL },
497 
498     { 3, "GetTypeInfoCount", dissect_dcom_simple_rqst, dissect_IDispatch_GetTypeInfoCount_resp },
499     { 4, "GetTypeInfo", dissect_IDispatch_GetTypeInfo_rqst, dissect_IDispatch_GetTypeInfo_resp },
500     { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp },
501     { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp },
502     { 0, NULL, NULL, NULL },
503 };
504 
505 
506 void
proto_register_dcom_dispatch(void)507 proto_register_dcom_dispatch(void)
508 {
509 
510     static hf_register_info hf_dispatch_array[] = {
511         { &hf_dispatch_opnum,
512           { "Operation", "dispatch.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
513 
514         { &hf_dispatch_riid,
515           { "RIID", "dispatch.riid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
516         { &hf_dispatch_name,
517           { "Name", "dispatch.name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
518         { &hf_dispatch_names,
519           { "Names", "dispatch.names", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
520         { &hf_dispatch_lcid,
521           { "LCID", "dispatch.lcid", FT_UINT32, BASE_HEX, VALS(dcom_lcid_vals), 0x0, NULL, HFILL }},
522         { &hf_dispatch_id,
523           { "DispID", "dispatch.id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
524         { &hf_dispatch_flags,
525           { "Flags", "dispatch.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
526 
527         { &hf_dispatch_arg,
528           { "Argument", "dispatch.arg", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
529         { &hf_dispatch_args,
530           { "Args", "dispatch.args", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
531         { &hf_dispatch_named_args,
532           { "NamedArgs", "dispatch.named_args", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
533         { &hf_dispatch_varref,
534           { "VarRef", "dispatch.varref", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
535         { &hf_dispatch_varrefidx,
536           { "VarRefIdx", "dispatch.varrefidx", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
537         { &hf_dispatch_varrefarg,
538           { "VarRef", "dispatch.varrefarg", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
539         { &hf_dispatch_varresult,
540           { "VarResult", "dispatch.varresult", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
541 
542         { &hf_dispatch_flags_method,
543           { "Method", "dispatch.flags_method", FT_BOOLEAN, 32, TFS (&tfs_set_notset), DISPATCH_FLAGS_METHOD, NULL, HFILL }},
544         { &hf_dispatch_flags_propget,
545           { "PropertyGet", "dispatch.flags_propget", FT_BOOLEAN, 32, TFS (&tfs_set_notset), DISPATCH_FLAGS_PROPGET, NULL, HFILL }},
546         { &hf_dispatch_flags_propput,
547           { "PropertyPut", "dispatch.flags_propput", FT_BOOLEAN, 32, TFS (&tfs_set_notset), DISPATCH_FLAGS_PROPPUT, NULL, HFILL }},
548         { &hf_dispatch_flags_propputref,
549           { "PropertyPutRef", "dispatch.flags_propputref", FT_BOOLEAN, 32, TFS (&tfs_set_notset), DISPATCH_FLAGS_PROPPUTREF, NULL, HFILL }},
550 
551         { &hf_dispatch_code,
552           { "Code", "dispatch.code", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
553         { &hf_dispatch_reserved16,
554           { "Reserved", "dispatch.reserved16", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
555         { &hf_dispatch_source,
556           { "Source", "dispatch.source", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
557         { &hf_dispatch_description,
558           { "Description", "dispatch.description", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
559         { &hf_dispatch_help_file,
560           { "HelpFile", "dispatch.help_file", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
561         { &hf_dispatch_help_context,
562           { "HelpContext", "dispatch.help_context", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
563         { &hf_dispatch_reserved32,
564           { "Reserved", "dispatch.reserved32", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
565         { &hf_dispatch_deferred_fill_in,
566           { "DeferredFillIn", "dispatch.deferred_fill_in", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
567         { &hf_dispatch_arg_err,
568           { "ArgErr", "dispatch.arg_err", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
569 
570         { &hf_dispatch_tinfo,
571           { "TInfo", "dispatch.tinfo", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
572         { &hf_dispatch_itinfo,
573           { "TInfo", "dispatch.itinfo", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
574         { &hf_dispatch_dispparams,
575           { "DispParams", "dispatch.dispparams", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
576         { &hf_dispatch_excepinfo,
577           { "ExcepInfo", "dispatch.excepinfo", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
578         { &hf_dispatch_scode,
579           { "SCode", "dispatch.scode", FT_UINT32, BASE_HEX, VALS(dcom_hresult_vals), 0x0, NULL, HFILL }}
580     };
581 
582     static gint *ett[] = {
583         &ett_dispatch,
584         &ett_dispatch_flags,
585         &ett_dispatch_params,
586         &ett_dispatch_excepinfo
587     };
588 
589 
590     /* IDispatch currently only partially implemented */
591     proto_dispatch = proto_register_protocol ("DCOM IDispatch", "IDispatch", "dispatch");
592     proto_register_field_array (proto_dispatch, hf_dispatch_array, array_length (hf_dispatch_array));
593     proto_register_subtree_array (ett, array_length (ett));
594 }
595 
596 
597 void
proto_reg_handoff_dcom_dispatch(void)598 proto_reg_handoff_dcom_dispatch(void)
599 {
600 
601     dcerpc_init_uuid(proto_dispatch, ett_dispatch,
602                      &uuid_dispatch, ver_dispatch,
603                      dispatch_dissectors, hf_dispatch_opnum);
604 }
605 
606 /*
607  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
608  *
609  * Local variables:
610  * c-basic-offset: 4
611  * tab-width: 8
612  * indent-tabs-mode: nil
613  * End:
614  *
615  * vi: set shiftwidth=4 tabstop=8 expandtab:
616  * :indentSize=4:tabSize=8:noTabs=true:
617  */
618