1 /* packet-dcom.c
2  * Routines for DCOM generics
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 /* A few words about DCOM:
12  *
13  * DCOM uses DCERPC as its underlying "transport" protocol.
14  *
15  * The DCOM dissectors are called by DCERPC request and response calls.
16  * DCOM uses a small header after the DCERPC calls.
17  * (for a DCERPC request  call it's called "this",
18  *  for a DCERPC response call it's called "that")
19  *
20  * DCOM defines itself some interfaces: oxid, remact, remunk and others
21  *
22  * Implemented is currently "only" a static dissection of packet fields
23  * (no "object recognition" included)
24  *
25  * User's of DCOM can define their own interface's using Microsoft IDL.
26  *
27  * Hint: The registered DCOM interface names can be found in the
28  * windows registry at: "HKEY_CLASSES_ROOT\Interface"
29  *
30  *
31  * Resources on the web:
32  *
33  * "Understanding the DCOM Wire Protocol by Analyzing Network Data Packets"
34  * http:// www.microsoft.com/msj/0398/dcom.htm
35  *
36  * "Distributed Component Object Model Protocol -- DCOM/1.0"
37  * http://www.microsoft.com/com/resources/specs.asp (link is currently down)
38  *
39  */
40 
41 /* Files involved dissecting DCOM:
42  *
43  * packet-dcom.c: generic DCOM things (this, that, ...) and
44  *    generic DCOM datatype (DWORD, VARIANT, ...)
45  *
46  * DCOM common Interfaces:
47  * packet-dcom-oxid.c:	   IOXIDResolver
48  * packet-dcom-remact.c:   IRemoteActivation
49  * packet-dcom-remunk.c:   IRemUnknown, IRemUnknown2
50  * packet-dcom-dispatch.c: IDispatch
51  * packet-dcom-sysact.c:   ISystemActivator
52  * packet-dcom-typeinfo.c: ITypeInfo
53  */
54 
55 #include "config.h"
56 
57 #include <string.h>
58 
59 #include <epan/packet.h>
60 #include <epan/exceptions.h>
61 #include <epan/addr_resolv.h>
62 #include <epan/expert.h>
63 #include <epan/prefs.h>
64 #include "packet-dcerpc.h"
65 #include "packet-dcom.h"
66 
67 void proto_register_dcom (void);
68 void proto_reg_handoff_dcom (void);
69 
70 static int proto_dcom = -1;
71 
72 gboolean dcom_prefs_display_unmarshalling_details = FALSE;
73 
74 
75 static gint ett_dcom_this = -1;
76 /* static int hf_dcom_this_version_major = -1; */
77 /* static int hf_dcom_this_version_minor = -1; */
78 static int hf_dcom_this_flags = -1;
79 static int hf_dcom_this_res = -1;
80 static int hf_dcom_this_cid = -1;
81 
82 static gint ett_dcom_that = -1;
83 static int hf_dcom_that_flags = -1;
84 
85 static gint ett_dcom_extent = -1;
86 static int hf_dcom_extent = -1;
87 static int hf_dcom_extent_array_count = -1;
88 static int hf_dcom_extent_array_res = -1;
89 static int hf_dcom_extent_size = -1;
90 static int hf_dcom_extent_id = -1;
91 
92 static int hf_dcom_hresult = -1;
93 static int hf_dcom_tobedone = -1;
94 static int hf_dcom_nospec = -1;
95 static int hf_dcom_array_size = -1;
96 static int hf_dcom_pointer_val = -1;
97 
98 /* COMVERSION */
99 static int hf_dcom_version_major = -1;
100 static int hf_dcom_version_minor = -1;
101 
102 static gint ett_dcom_lpwstr = -1;
103 static int hf_dcom_max_count = -1;
104 static int hf_dcom_offset = -1;
105 static int hf_dcom_byte_length = -1;
106 /* static int hf_dcom_actual_count = -1; */
107 
108 static gint ett_dcom_objref = -1;
109 static int hf_dcom_objref = -1;
110 static int hf_dcom_objref_signature = -1;
111 static int hf_dcom_objref_flags = -1;
112 int hf_dcom_iid = -1;
113 int hf_dcom_clsid = -1;
114 static int hf_dcom_objref_resolver_address = -1;
115 static int hf_dcom_objref_cbextension = -1;
116 static int hf_dcom_objref_size = -1;
117 
118 static gint ett_dcom_stdobjref = -1;
119 static int hf_dcom_stdobjref = -1;
120 static int hf_dcom_stdobjref_flags = -1;
121 static int hf_dcom_stdobjref_public_refs = -1;
122 int hf_dcom_oxid = -1;
123 int hf_dcom_oid = -1;
124 int hf_dcom_ipid = -1;
125 
126 
127 static gint ett_dcom_custobjref = -1;
128 static int hf_dcom_custobjref = -1;
129 
130 static gint ett_dcom_dualstringarray = -1;
DescribeByoipCidrs(context.Context, *DescribeByoipCidrsInput, ...func(*Options))131 static gint ett_dcom_dualstringarray_binding = -1;
132 static int hf_dcom_dualstringarray_num_entries = -1;
133 static int hf_dcom_dualstringarray_security_offset = -1;
134 static int hf_dcom_dualstringarray_string = -1;
135 static int hf_dcom_dualstringarray_string_network_addr = -1;
136 static int hf_dcom_dualstringarray_string_tower_id = -1;
137 static int hf_dcom_dualstringarray_security = -1;
138 static int hf_dcom_dualstringarray_security_authn_svc = -1;
139 static int hf_dcom_dualstringarray_security_authz_svc = -1;
140 static int hf_dcom_dualstringarray_security_princ_name = -1;
141 
142 static gint ett_dcom_interface_pointer = -1;
143 static int hf_dcom_interface_pointer = -1;
144 static int hf_dcom_ip_cnt_data = -1;
145 
146 static gint ett_dcom_safearray = -1;
147 static int hf_dcom_safearray = -1;
148 static int hf_dcom_sa_dims32 = -1;
149 static int hf_dcom_sa_dims16 = -1;
150 static int hf_dcom_sa_features = -1;
151 static int hf_dcom_sa_element_size = -1;
152 static int hf_dcom_sa_locks = -1;
153 static int hf_dcom_sa_vartype32 = -1;
154 static int hf_dcom_sa_vartype16 = -1;
155 static int hf_dcom_sa_elements = -1;
156 static int hf_dcom_sa_bound_elements = -1;
157 static int hf_dcom_sa_low_bound = -1;
158 
159 static gint ett_dcom_sa_features = -1;
160 static int hf_dcom_sa_features_auto = -1;
161 static int hf_dcom_sa_features_static = -1;
162 static int hf_dcom_sa_features_embedded = -1;
163 static int hf_dcom_sa_features_fixedsize = -1;
164 static int hf_dcom_sa_features_record = -1;
165 static int hf_dcom_sa_features_have_iid = -1;
166 static int hf_dcom_sa_features_have_vartype = -1;
167 static int hf_dcom_sa_features_bstr = -1;
168 static int hf_dcom_sa_features_unknown = -1;
169 static int hf_dcom_sa_features_dispatch = -1;
170 static int hf_dcom_sa_features_variant = -1;
171 
172 static gint ett_dcom_variant = -1;
173 /* static int hf_dcom_variant = -1; */
174 static int hf_dcom_variant_type = -1;
175 static int hf_dcom_variant_size = -1;
176 static int hf_dcom_variant_rpc_res = -1;
177 static int hf_dcom_variant_wres = -1;
178 static int hf_dcom_variant_type32 = -1;
179 
180 static int hf_dcom_vt_bool = -1;
181 static int hf_dcom_vt_i1 = -1;
182 static int hf_dcom_vt_i2 = -1;
183 static int hf_dcom_vt_i4 = -1;
184 static int hf_dcom_vt_i8 = -1;	/* only inside a SAFEARRAY, not in VARIANTs */
185 static int hf_dcom_vt_cy = -1;
186 static int hf_dcom_vt_ui1 = -1;
187 static int hf_dcom_vt_ui2 = -1;
188 static int hf_dcom_vt_ui4 = -1;
189 static int hf_dcom_vt_ui8 = -1;
190 static int hf_dcom_vt_r4 = -1;
191 static int hf_dcom_vt_r8 = -1;
192 static int hf_dcom_vt_date = -1;
193 static int hf_dcom_vt_bstr = -1;
194 static int hf_dcom_vt_byref = -1;
195 static int hf_dcom_vt_dispatch = -1;
196 
197 static expert_field ei_dcom_dissection_incomplete = EI_INIT;
198 static expert_field ei_dcom_no_spec = EI_INIT;
199 static expert_field ei_dcom_hresult_expert = EI_INIT;
200 static expert_field ei_dcom_dualstringarray_mult_ip = EI_INIT;
201 
202 /* this/that extension UUIDs */
203 static e_guid_t uuid_debug_ext =    { 0xf1f19680, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} };
204 static e_guid_t uuid_ext_error_ext ={ 0xf1f19681, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} };
205 
206 /* general DCOM UUIDs */
207 static const e_guid_t ipid_rem_unknown =  { 0x00000131, 0x1234, 0x5678, { 0xCA, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
208 static const e_guid_t iid_unknown =	  { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
209 static const e_guid_t uuid_null =	  { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
210 static const e_guid_t iid_class_factory = { 0x00000001, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
211 static const e_guid_t iid_type_info = { 0x00020401, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
212 static const e_guid_t iid_provide_class_info = { 0xb196b283, 0xbab4, 0x101a, { 0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07} };
213 #if 0
214 static const e_guid_t iid_act_prop_in =   { 0x000001A2, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
215 static const e_guid_t iid_act_prop_out =  { 0x000001A3, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
216 #endif
217 
218 static GList *dcom_machines   = NULL;
219 static GList *dcom_interfaces = NULL;
220 static GList *dcom_marshalers = NULL;
221 
222 static const value_string dcom_thisthat_flag_vals[] = {
223 	{ 0, "INFO_NULL" },
224 	{ 1, "INFO_LOCAL" },
225 	{ 0,  NULL }
226 };
227 
228 #if 0
229 static const value_string dcom_boolean_flag_vals[] = {
230 	{ 0x00000001, "TRUE" },
231 	{ 0x00000000, "FALSE" },
232 	{ 0,  NULL }
233 };
234 #endif
235 
236 #ifdef DEBUG
237 void dcom_interface_dump(void) {
238 	dcom_machine_t *machine;
239 	dcom_object_t *object;
240 	dcom_interface_t *interf;
241 	GList *machines;
242 	GList *objects;
243 	GList *interfaces;
244 
245 
246 	for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
247 		machine = (dcom_machine_t *)machines->data;
248 		/*ws_warning("Machine(#%4u): IP:%s", machine->first_packet, address_to_str(pinfo->pool, &machine->ip));*/
249 
250 		for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
251 			object = (dcom_object_t *)objects->data;
252 			/*ws_warning(" Object(#%4u): OID:0x%" G_GINT64_MODIFIER "x private:%p", object->first_packet, object->oid, object->private_data);*/
253 
254 			for(interfaces = object->interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
255 				interf = (dcom_interface_t *)interfaces->data;
256 				/*ws_warning("  Interface(#%4u): iid:%s",
257 					  interf->first_packet, guids_resolve_guid_to_str(&interf->iid));
258 				ws_warning("   ipid:%s", guids_resolve_guid_to_str(&interf->ipid));*/
259 			}
260 		}
261 	}
262 }
263 #endif
264 
265 dcom_interface_t *dcom_interface_find(packet_info *pinfo _U_, const address *addr _U_, e_guid_t *ipid)
266 {
267 	dcom_interface_t *interf;
268 	GList *interfaces;
269 
270 
271 	if(memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
272 	{
273 		return NULL;
274 	}
275 
276 	for(interfaces = dcom_interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
277 		interf = (dcom_interface_t *)interfaces->data;
278 
279 		if(memcmp(&interf->ipid, ipid, sizeof(e_guid_t)) == 0) {
280 			return interf;
281 		}
282 	}
283 
284 	return NULL;
285 }
286 
287 
288 dcom_interface_t *dcom_interface_new(packet_info *pinfo, const address *addr, e_guid_t *iid, guint64 oxid, guint64 oid, e_guid_t *ipid)
289 {
290 	GList *dcom_iter;
291 	dcom_machine_t *machine;
292 	dcom_object_t *object;
293 	dcom_interface_t *interf;
294 
295 
296 	if( memcmp(iid, &uuid_null, sizeof(uuid_null)) == 0 ||
297 	    memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
298 	{
299 		return NULL;
300 	}
301 
302 	if(oxid == 0 || oid == 0) {
303 		/*ws_warning("interface_new#%u", pinfo->num);*/
304 
305 		interf = wmem_new(wmem_file_scope(), dcom_interface_t);
306 		interf->parent = NULL;
307 		interf->private_data = NULL;
308 		interf->first_packet = pinfo->num;
309 		interf->iid = *iid;
310 		interf->ipid = *ipid;
311 
312 		dcom_interfaces = g_list_append(dcom_interfaces, interf);
313 		return interf;
314 	}
315 
316 	/* find machine */
317 	dcom_iter = dcom_machines;
318 	while(dcom_iter != NULL) {
319 		machine = (dcom_machine_t *)dcom_iter->data;
320 		if(cmp_address(&machine->ip, addr) == 0) {
321 			break;
322 		}
323 		dcom_iter = g_list_next(dcom_iter);
324 	}
325 
326 	/* create new machine if not found */
327 	if(dcom_iter == NULL) {
328 		machine = g_new(dcom_machine_t,1);
329 		copy_address(&machine->ip, addr);
330 		machine->objects = NULL;
331 		machine->first_packet = pinfo->num;
332 		dcom_machines = g_list_append(dcom_machines, machine);
333 	}
334 
335 	/* find object */
336 	dcom_iter = machine->objects;
337 	while(dcom_iter != NULL) {
338 		object = (dcom_object_t *)dcom_iter->data;
339 		if(object->oid == oid) {
340 			break;
341 		}
342 		dcom_iter = g_list_next(dcom_iter);
343 	}
344 
345 	/* create new object if not found */
346 	if(dcom_iter == NULL) {
347 		object = g_new(dcom_object_t,1);
348 		object->parent = machine;
349 		object->interfaces = NULL;
350 		object->private_data = NULL;
351 		object->first_packet = pinfo->num;
352 		object->oid = oid;
353 		object->oxid = oxid;
354 
355 		machine->objects = g_list_append(machine->objects, object);
356 	}
357 
358 	/* find interface */
359 	dcom_iter = object->interfaces;
360 	while(dcom_iter != NULL) {
361 		interf = (dcom_interface_t *)dcom_iter->data;
362 		if(memcmp(&interf->ipid, ipid, sizeof(e_guid_t)) == 0) {
363 			break;
364 		}
365 		dcom_iter = g_list_next(dcom_iter);
366 	}
367 
368 	/* create new interface if not found */
369 	if(dcom_iter == NULL) {
370 		interf = g_new(dcom_interface_t,1);
371 		interf->parent = object;
372 		interf->private_data = NULL;
373 		interf->first_packet = pinfo->num;
374 		interf->iid = *iid;
375 		interf->ipid = *ipid;
376 
377 		object->interfaces = g_list_append(object->interfaces, interf);
378 		dcom_interfaces = g_list_append(dcom_interfaces, interf);
379 	}
380 
381 	return interf;
382 }
383 
384 
385 /*
386  * Flag bits in connection-oriented PDU header.
387  */
388 #define WIRESHARK_FADF_AUTO		0x0001
389 #define WIRESHARK_FADF_STATIC		0x0002
390 #define WIRESHARK_FADF_EMBEDDED		0x0004
391 #define WIRESHARK_FADF_FIXEDSIZE	0x0010
392 #define WIRESHARK_FADF_RECORD		0x0020
393 #define WIRESHARK_FADF_HAVEIID		0x0040
394 #define WIRESHARK_FADF_HAVEVARTYPE	0x0080
395 #define WIRESHARK_FADF_BSTR		0x0100
396 #define WIRESHARK_FADF_UNKNOWN		0x0200
397 #define WIRESHARK_FADF_DISPATCH		0x0400
398 #define WIRESHARK_FADF_VARIANT		0x0800
399 
400 
401 typedef enum {
402 	WIRESHARK_VT_EMPTY	     = 0,
403 	WIRESHARK_VT_NULL	     = 1,
404 	WIRESHARK_VT_I2		     = 2,
405 	WIRESHARK_VT_I4		     = 3,
406 	WIRESHARK_VT_R4		     = 4,
407 	WIRESHARK_VT_R8		     = 5,
408 	WIRESHARK_VT_CY		     = 6,
409 	WIRESHARK_VT_DATE	     = 7,
410 	WIRESHARK_VT_BSTR	     = 8,
411 	WIRESHARK_VT_DISPATCH	     = 9,
412 	WIRESHARK_VT_ERROR	     = 10,
413 	WIRESHARK_VT_BOOL	     = 11,
414 	WIRESHARK_VT_VARIANT	     = 12,
415 	WIRESHARK_VT_UNKNOWN	     = 13,
416 	WIRESHARK_VT_DECIMAL	     = 14,
417 	WIRESHARK_VT_I1		     = 16,
418 	WIRESHARK_VT_UI1	     = 17,
419 	WIRESHARK_VT_UI2	     = 18,
420 	WIRESHARK_VT_UI4	     = 19,
421 	WIRESHARK_VT_I8		     = 20,
422 	WIRESHARK_VT_UI8	     = 21,
423 	WIRESHARK_VT_INT	     = 22,
424 	WIRESHARK_VT_UINT	     = 23,
425 	WIRESHARK_VT_VOID	     = 24,
426 	WIRESHARK_VT_HRESULT	     = 25,
427 	WIRESHARK_VT_PTR	     = 26,
428 	WIRESHARK_VT_SAFEARRAY	     = 27,
429 	WIRESHARK_VT_CARRAY	     = 28,
430 	WIRESHARK_VT_USERDEFINED     = 29,
431 	WIRESHARK_VT_LPSTR	     = 30,
432 	WIRESHARK_VT_LPWSTR	     = 31,
433 	WIRESHARK_VT_RECORD	     = 36,
434 	WIRESHARK_VT_FILETIME	     = 64,
435 	WIRESHARK_VT_BLOB	     = 65,
436 	WIRESHARK_VT_STREAM	     = 66,
437 	WIRESHARK_VT_STORAGE	     = 67,
438 	WIRESHARK_VT_STREAMED_OBJECT = 68,
439 	WIRESHARK_VT_STORED_OBJECT   = 69,
440 	WIRESHARK_VT_BLOB_OBJECT     = 70,
441 	WIRESHARK_VT_CF		     = 71,
442 	WIRESHARK_VT_CLSID	     = 72,
443 
444 	WIRESHARK_VT_BSTR_BLOB	     = 0x0fff,
445 
446 	WIRESHARK_VT_VECTOR	     = 0x1000,
447 	WIRESHARK_VT_ARRAY	     = 0x2000,
448 	WIRESHARK_VT_BYREF	     = 0x4000,
449 	WIRESHARK_VT_RESERVED	     = 0x8000,
450 
451 	WIRESHARK_VT_ILLEGAL	     = 0xffff,
452 	WIRESHARK_VT_ILLEGALMASKED   = 0x0fff,
453 	WIRESHARK_VT_TYPEMASK	     = 0x0fff
454 } dcom_vartype_t;
455 
456 const value_string dcom_variant_type_vals[] = {
457 	{ WIRESHARK_VT_EMPTY,		"VT_EMPTY"},
458 	{ WIRESHARK_VT_NULL,		"VT_NULL"},
459 	{ WIRESHARK_VT_I2,		"VT_I2"},
460 	{ WIRESHARK_VT_I4,		"VT_I4"},
461 	{ WIRESHARK_VT_R4,		"VT_R4"},
462 	{ WIRESHARK_VT_R8,		"VT_R8"},
463 	{ WIRESHARK_VT_CY,		"VT_CY"},
464 	{ WIRESHARK_VT_DATE,		"VT_DATE"},
465 	{ WIRESHARK_VT_BSTR,		"VT_BSTR"},
466 	{ WIRESHARK_VT_DISPATCH,	"VT_DISPATCH"},
467 	{ WIRESHARK_VT_ERROR,		"VT_ERROR"},
468 	{ WIRESHARK_VT_BOOL,		"VT_BOOL"},
469 	{ WIRESHARK_VT_I1,		"VT_I1"},
470 	{ WIRESHARK_VT_UI1,		"VT_UI1"},
471 	{ WIRESHARK_VT_UI2,		"VT_UI2"},
472 	{ WIRESHARK_VT_UI4,		"VT_UI4"},
473 	{ WIRESHARK_VT_I8,		"VT_I8"},
474 	{ WIRESHARK_VT_UI8,		"VT_UI8"},
475 	{ WIRESHARK_VT_ARRAY,		"VT_ARRAY"},
476 	{ WIRESHARK_VT_UNKNOWN,		"VT_UNKNOWN"},
477 	{ WIRESHARK_VT_USERDEFINED,	"VT_USERDEFINED"},
478 	{ WIRESHARK_VT_PTR, 		"VT_PTR"},
479 
480 	/* XXX: this could be done better */
481 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_I2,	     "VT_ARRAY|VT_I2"},
482 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_I4,	     "VT_ARRAY|VT_I4"},
483 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_R4,	     "VT_ARRAY|VT_R4"},
484 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_R8,	     "VT_ARRAY|VT_R8"},
485 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_DATE,    "VT_ARRAY|VT_DATE"},
486 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_BSTR,    "VT_ARRAY|VT_BSTR"},
487 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_ERROR,   "VT_ARRAY|VT_ERROR"},
488 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_BOOL,    "VT_ARRAY|VT_BOOL"},
489 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_I1,	     "VT_ARRAY|VT_I1"},
490 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI1,     "VT_ARRAY|VT_UI1"},
491 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI2,     "VT_ARRAY|VT_UI2"},
492 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI4,     "VT_ARRAY|VT_UI4"},
493 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_I8,	     "VT_ARRAY|VT_I8"},
494 	{ WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI8,     "VT_ARRAY|VT_UI8"},
495 
496 	{ WIRESHARK_VT_BYREF | WIRESHARK_VT_I2,	     "VT_BYREF|VT_I2"},
497 	{ WIRESHARK_VT_BYREF | WIRESHARK_VT_BSTR,    "VT_BYREF|VT_BSTR"},
498 	{ WIRESHARK_VT_BYREF | WIRESHARK_VT_VARIANT, "VT_BYREF|VT_VARIANT"},
499 	{ 0,	      NULL }
500 /* XXX: append more types here */
501 };
502 
503 
504 
505 /* we need an extension mechanism here (be able to append entries by user protocol) */
506 const value_string dcom_hresult_vals[] = {
507 	{ 0x00000000, "S_OK" },
508 	{ 0x00000001, "S_FALSE" },
509 	{ 0x8000FFFF, "E_UNEXPECTED" },
510 	{ 0x80004001, "E_NOTIMPL" },
511 	{ 0x80004002, "E_NOINTERFACE" },
512 	{ 0x80004003, "E_POINTER" },
513 	{ 0x80004004, "E_ABORT" },
514 	{ 0x80004005, "E_FAIL" },
515 	{ 0x80070005, "E_ACCESSDENIED" },
516 	{ 0x80070006, "E_HANDLE" },
517 	{ 0x8007000E, "E_OUTOFMEMORY" },
518 	{ 0x80070057, "E_INVALIDARG" },
519 
520 	{ 0x80010108, "RPC_E_DISCONNECTED" },
521 	{ 0x80010113, "RPC_E_INVALID_IPID" },
522 	{ 0x8001011F, "RPC_E_TIMEOUT" },
523 
524 	{ 0x80020003, "DISP_E_MEMBERNOTFOUND" },
525 	{ 0x80020004, "DISP_E_PARAMNOTFOUND" },
526 	{ 0x80020005, "DISP_E_TYPEMISMATCH" },
527 	{ 0x80020006, "DISP_E_UNKNOWNNAME" },
528 	{ 0x80020008, "DISP_E_BADVARTYPE" },
529 	{ 0x80020009, "DISP_E_EXCEPTION" },
530 	{ 0x8002000A, "DISP_E_OVERFLOW" },
531 
532 	{ 0x8002801D, "TYPE_E_LIBNOTREGISTERED" },
533 
534 	{ 0x80040154, "REGDB_E_CLASSNOTREG" },
535 	{ 0x80040201, "CO_E_FAILEDTOGETSECCTX" },
536 
537 /* following are CBA application specific values */
538 	{ 0x0004CA00, "CBA_S_PERSISTPENDING" },
539 	{ 0x0004CA01, "CBA_S_ESTABLISHING" },
540 	{ 0x0004CA02, "CBA_S_NOCONNECTION" },
541 	{ 0x0004CA03, "CBA_S_VALUEBUFFERED" },
542 	{ 0x0004CA04, "CBA_S_VALUEUNCERTAIN" },
543 	{ 0x0004CA05, "CBA_S_NOCONNECTIONDATA" },
544 	{ 0x0004CA06, "CBA_S_FRAMEEMPTY" },
545 
546 	{ 0x8004CB00, "CBA_E_MALFORMED" },
547 	{ 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
548 	{ 0x8004CB02, "CBA_E_UNKNOWNMEMBER" },
549 	{ 0x8004CB03, "CBA_E_TYPEMISMATCH" },
550 	{ 0x8004CB04, "CBA_E_INVALIDENUMVALUE" },
551 	{ 0x8004CB05, "CBA_E_INVALIDID" },
552 	{ 0x8004CB06, "CBA_E_INVALIDEPSILON" },
553 	{ 0x8004CB07, "CBA_E_INVALIDSUBSTITUTE" },
554 	{ 0x8004CB08, "CBA_E_INVALIDCONNECTION" },
555 	{ 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
556 	{ 0x8004CB0A, "CBA_E_TIMEVALUEUNSUPPORTED" },
557 	{ 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
558 	{ 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
559 	{ 0x8004CB0D, "CBA_E_PERSISTRUNNING" },
560 	{ 0x8004CB0E, "CBA_E_INUSE" },
561 	{ 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
562 	{ 0x8004CB10, "CBA_E_NONACCESSIBLE" },
563 	{ 0x8004CB11, "CBA_E_DEFECT" },
564 	{ 0x8004CB12, "CBA_E_LIMITVIOLATION" },
565 	{ 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
566 	{ 0x8004CB14, "CBA_E_QCNOTAPPLICABLE" },
567 	{ 0x8004CB15, "CBA_E_ACCESSBLOCKED" },
568 	{ 0x8004CB16, "CBA_E_COUNTEXCEEDED" },
569 	{ 0x8004CB17, "CBA_E_SIZEEXCEEDED" },
570 	{ 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
571 	{ 0x8004CB19, "CBA_E_OUTOFACCOPAIRS" },
572 	{ 0x8004CB1A, "CBA_E_ITEMTOOLARGE" },
573 	{ 0x8004CB1B, "CBA_E_CRDATALENGTH" },
574 	{ 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
575 	{ 0x8004CB1D, "CBA_E_CAPACITYEXCEEDED" },
576 	{ 0x8004CB1E, "CBA_E_SUBELEMENTMISMATCH" },
577 	{ 0x8004CB1F, "CBA_E_STATIONFAILURE" },
578 	{ 0x8004CB20, "CBA_E_NOTROUTABLE" },
579 	{ 0x8004CB21, "CBA_E_DISCONNECTRUNNING" },
580 	{ 0x8004CB22, "CBA_E_LOCATIONCHANGED" },
581 	{ 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
582 	{ 0x8004CB24, "CBA_E_LINKFAILURE" },
583 	{ 0x8004CB25, "CBA_E_MODECHANGE" },
584 
585 	{ 0x80080004, "CO_E_BAD_PATH" },
586 
587 	{ 0,	      NULL }
588 };
589 
590 static const value_string dcom_objref_flag_vals[] = {
591 	{ 0x1, "OBJREF_STANDARD" },
592 	{ 0x2, "OBJREF_HANDLER" },
593 	{ 0x4, "OBJREF_CUSTOM" },
594 	{ 0,   NULL }
595 };
596 
597 static const value_string dcom_objref_signature_vals[] = {
598 	{ 0x574f454d, "MEOW" },
599 	{ 0,	      NULL }
600 };
601 
602 /* although flags, they doesn't seem to be used as such */
603 static const value_string dcom_stdobjref_flag_vals[] = {
604 	{ 0x0000, "SORF_NULL" },
605 	{ 0x0001, "SORF_OXRES1" },
606 	{ 0x0020, "SORF_OXRES2" },
607 	{ 0x0040, "SORF_OXRES3" },
608 	{ 0x0080, "SORF_OXRES4" },
609 	{ 0x0100, "SORF_OXRES5" },
610 	{ 0x0200, "SORF_OXRES6" },
611 	{ 0x0400, "SORF_OXRES7" },
612 	{ 0x0800, "SORF_OXRES8" },
613 	{ 0x1000, "SORF_NOPING" },
614 	{ 0,	  NULL }
615 };
616 
617 static const value_string dcom_dcerpc_pointer_vals[] = {
618 	{ 0x72657355, "User" },
619 	{ 0x42535452, "BSTR" },
620 	{ 0x00000000, "NULL" },
621 	{ 0,	      NULL }
622 };
623 
624 static const value_string dcom_dualstringarray_authz[] = {
625 	{ 0x0000, "RPC_C_AUTHZ_NONE" },
626 	{ 0x0001, "RPC_C_AUTHZ_NAME"},
627 	{ 0x0002, "RPC_C_AUTHZ_DCE"},
628 	{ 0xffff, "Default"},
629 	{ 0,	  NULL}
630 };
631 
632 static const value_string dcom_dualstringarray_authn[] = {
633 	{  00, "RPC_C_AUTHN_NONE" },
634 	{   1, "RPC_C_AUTHN_DCE_PRIVATE"},
635 	{   2, "RPC_C_AUTHN_DCE_PUBLIC"},
636 	{   4, "RPC_C_AUTHN_DEC_PUBLIC"},
637 	{   9, "RPC_C_AUTHN_GSS_NEGOTIATE"},
638 	{  10, "RPC_C_AUTH_WINNT"},
639 	{  14, "RPC_C_AUTHN_GSS_SCHANNEL"},
640 	{  16, "RPC_C_AUTHN_GSS_KERBEROS"},
641 	{  17, "RPC_C_AUTHN_MSN"},
642 	{  18, "RPC_C_AUTHN_DPA"},
643 	{ 100, "RPC_C_AUTHN_MQ"},
644 	{ 0xffff, "RPC_C_AUTHN_DEFAULT"},
645 	{ 0,   NULL}
646 };
647 
648 const value_string dcom_protseq_vals[] = {
649 	{ 0x04, "NCACN_DNET_NSP" },
650 	{ 0x07, "NCACN_IP_TCP" },
651 	{ 0x08, "NCADG_IP_UDP" },
652 	{ 0x09, "NCACN_IP" },
653 	{ 0x0C, "NCACN_SPX" },
654 	{ 0x0D, "NCACN_NB_IPX" },
655 	{ 0x0E, "NCADG_IPX" },
656 	{ 0x12, "NCACN_NB_NB" },
657 	{ 0x1F, "NCACN_HTTP" },
658 	{ 0,	NULL }
659 };
660 
661 static const value_string dcom_vt_bool_vals[] = {
662 	{ 0x0000, "FALSE" },
663 	{ 0xFFFF, "TRUE" },
664 	{ 0,	  NULL }
665 };
666 
667 
668 
669 /* dissect extension to DCOM "this" and "that" */
670 static int
671 dissect_dcom_extent(tvbuff_t *tvb, int offset,
672 	packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
673 {
674 	guint32 u32ArraySize;
675 	guint32 u32ArraySize2;
676 	guint32 u32Pointer;
677 	guint32 u32VariableOffset;
678 	guint32 u32Idx;
679 	guint32 u32SubStart;
680 	proto_item *sub_item;
681 	proto_tree *sub_tree;
682 
683 	guint32 u32ArrayCount;
684 	guint32 u32ArrayRes;
685 
686 	guint32 u32ExtentSize;
687 	e_guid_t uuidExtend;
688 	const char *uuid_name;
689 
690 
691 	offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
692 
693 	if (u32Pointer == 0) {
694 		return offset;
695 	}
696 
697 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
698 			hf_dcom_extent_array_count, &u32ArrayCount);
699 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
700 			hf_dcom_extent_array_res, &u32ArrayRes);
701 
702 	offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
703 
704 	if (u32Pointer == 0) {
705 		return offset;
706 	}
707 
708 	offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
709 						&u32ArraySize);
710 
711 	u32VariableOffset = offset + u32ArraySize*4;
712 
713 	u32Idx = 1;
714 	while (u32ArraySize--) {
715 		sub_item = proto_tree_add_item(tree, hf_dcom_extent, tvb, offset, 0, ENC_NA);
716 		sub_tree = proto_item_add_subtree(sub_item, ett_dcom_extent);
717 		u32SubStart = offset;
718 
719 		offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
720 
721 		if(u32Pointer != 0) {
722 			u32VariableOffset = dissect_dcom_DWORD(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
723 							       hf_dcom_extent_size, &u32ExtentSize);
724 
725 			dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, NULL, di, drep,
726 					  hf_dcom_extent_id, &uuidExtend);
727 
728 			/* look for a registered uuid name */
729 			if((uuid_name = guids_get_uuid_name(&uuidExtend, pinfo->pool)) != NULL) {
730 				proto_tree_add_guid_format_value(sub_tree, hf_dcom_extent_id, tvb,
731 								 offset, sizeof(e_guid_t), (e_guid_t *) &uuidExtend,
732 								 "%s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
733 								 uuid_name,
734 								 uuidExtend.data1, uuidExtend.data2, uuidExtend.data3,
735 								 uuidExtend.data4[0], uuidExtend.data4[1],
736 								 uuidExtend.data4[2], uuidExtend.data4[3],
737 								 uuidExtend.data4[4], uuidExtend.data4[5],
738 								 uuidExtend.data4[6], uuidExtend.data4[7]);
739 				u32VariableOffset += 16;
740 			} else {
741 				u32VariableOffset = dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
742 								      hf_dcom_extent_id, &uuidExtend);
743 			}
744 
745 
746 			u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
747 									   &u32ArraySize2);
748 			u32VariableOffset = dissect_dcom_nospec_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, u32ArraySize2);
749 
750 			/* update subtree header */
751 			if(uuid_name != NULL) {
752 				proto_item_append_text(sub_item, "[%u]: %s, Bytes=%u",
753 						       u32Idx, uuid_name, u32ArraySize2);
754 			} else {
755 				proto_item_append_text(sub_item, "[%u]: Bytes=%u",
756 						       u32Idx, u32ArraySize2);
757 			}
758 			proto_item_set_len(sub_item, offset - u32SubStart);
759 		} else {
760 			/* update subtree header */
761 			proto_item_append_text(sub_item, "[%u]: NULL", u32Idx);
762 			proto_item_set_len(sub_item, offset - u32SubStart);
763 		}
764 
765 		u32Idx++;
766 	}
767 
768 	return u32VariableOffset;
769 }
770 
771 
772 /* dissect DCOM "this" (start of every DCOM request) */
773 int
774 dissect_dcom_this(tvbuff_t *tvb, int offset,
775 	packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
776 {
777 	guint16 u16VersionMajor;
778 	guint16 u16VersionMinor;
779 	guint32 u32Flags;
780 	guint32 u32Res;
781 	e_guid_t uuidCausality;
782 	proto_item *sub_item;
783 	proto_tree *sub_tree;
784 	guint32 u32SubStart;
785 	proto_item *pi;
786 
787 	sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
788 						  "DCOM, ORPCThis");
789 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_this);
790 
791 	offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, sub_tree, di, drep,
792 				&u16VersionMajor, &u16VersionMinor);
793 	u32SubStart = offset - 4;
794 
795 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
796 			hf_dcom_this_flags, &u32Flags);
797 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
798 			hf_dcom_this_res, &u32Res);
799 
800 	offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
801 			hf_dcom_this_cid, &uuidCausality);
802 
803 	offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep);
804 
805 	/* update subtree header */
806 	proto_item_append_text(sub_item, ", V%u.%u, Causality ID: %s",
807 		u16VersionMajor, u16VersionMinor, guids_resolve_guid_to_str(&uuidCausality, pinfo->pool));
808 	proto_item_set_len(sub_item, offset - u32SubStart);
809 
810 	if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
811 		pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
812 			(e_guid_t *) &di->call_data->object_uuid,
813 			"Object UUID/IPID: %s", guids_resolve_guid_to_str(&di->call_data->object_uuid, pinfo->pool));
814 		proto_item_set_generated(pi);
815 	}
816 
817 	return offset;
818 }
819 
820 
821 /* dissect DCOM "that" (start of every DCOM response) */
822 int
823 dissect_dcom_that(tvbuff_t *tvb, int offset,
824 	packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) {
825 	guint32 u32Flags;
826 	proto_item *sub_item;
827 	proto_tree *sub_tree;
828 	guint32 u32SubStart;
829 	proto_item *pi;
830 
831 	sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
832 						  "DCOM, ORPCThat");
833 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_that);
834 
835 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
836 				    hf_dcom_that_flags, &u32Flags);
837 	u32SubStart = offset - 4;
838 
839 	offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep);
840 
841 	/* update subtree header */
842 	proto_item_set_len(sub_item, offset - u32SubStart);
843 
844 	if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
845 		pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
846 			(e_guid_t *) &di->call_data->object_uuid,
847 			"Object UUID/IPID: %s", guids_resolve_guid_to_str(&di->call_data->object_uuid, pinfo->pool));
848 		proto_item_set_generated(pi);
849 	}
850 
851 	return offset;
852 }
853 
854 
855 /* dissect simple dcom request, DCOM "this" only */
856 int
857 dissect_dcom_simple_rqst(tvbuff_t *tvb, int offset,
858 	packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
859 {
860 
861 	offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep);
862 
863 	return offset;
864 }
865 
866 
867 /* dissect simple dcom response, DCOM "that" and returned HRESULT only */
868 int
869 dissect_dcom_simple_resp(tvbuff_t *tvb, int offset,
870 	packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
871 {
872 	guint32 u32HResult;
873 
874 
875 	offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);
876 
877 	offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
878 				      &u32HResult);
879 
880 	col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
881 			val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
882 
883 
884 	return offset;
885 }
886 
887 
888 /* dissect a dcerpc array size */
889 int
890 dissect_dcom_dcerpc_array_size(tvbuff_t *tvb, gint offset, packet_info *pinfo,
891 		       proto_tree *tree, dcerpc_info *di, guint8 *drep, guint32 *pu32ArraySize)
892 {
893 
894 
895 	/* en-/disable this by preference setting */
896 	if (!dcom_prefs_display_unmarshalling_details) {
897 		/* this will read in the data, but prevent output to tree */
898 		tree = NULL;
899 	}
900 
901 	offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
902 							hf_dcom_array_size, pu32ArraySize);
903 
904 	return offset;
905 }
906 
907 
908 /* dissect a dcerpc pointer value */
909 int
910 dissect_dcom_dcerpc_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
911 		       proto_tree *tree, dcerpc_info *di, guint8 *drep, guint32 *pu32Pointer)
912 {
913 
914 	/* en-/disable this by preference setting */
915 	if (!dcom_prefs_display_unmarshalling_details) {
916 		/* this will read in the data, but prevent output to tree */
917 		tree = NULL;
918 	}
919 
920 	offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
921 								hf_dcom_pointer_val, pu32Pointer);
922 
923 	return offset;
924 }
925 
926 
927 /* mark data as "ToBeDone" */
928 /* XXX: handout data to generic "unknown data" dissector? */
929 extern int
930 dissect_dcom_tobedone_data(tvbuff_t *tvb, int offset,
931 	packet_info *pinfo, proto_tree *tree, guint8 *drep _U_, int length)
932 {
933 	proto_item *item;
934 
935 
936 	item = proto_tree_add_item(tree, hf_dcom_tobedone, tvb, offset, length, ENC_NA);
937 	proto_item_set_generated(item);
938 	expert_add_info(pinfo, item, &ei_dcom_dissection_incomplete);
939 
940 	offset += length;
941 
942 	return offset;
943 }
944 
945 
946 /* mark data as "No Specification Available" */
947 /* XXX: handout data to generic "unknown data" dissector? */
948 extern int
949 dissect_dcom_nospec_data(tvbuff_t *tvb, int offset,
950 	packet_info *pinfo, proto_tree *tree, guint8 *drep _U_, int length)
951 {
952 	proto_item *item;
953 
954 
955 	item = proto_tree_add_item(tree, hf_dcom_nospec, tvb, offset, length, ENC_NA);
956 	proto_item_set_generated(item);
957 	expert_add_info(pinfo, item, &ei_dcom_no_spec);
958 
959 	offset += length;
960 
961 	return offset;
962 }
963 
964 
965 /* dissect an indexed WORD, something like: "FieldName[1]: 0x1234" */
966 int
967 dissect_dcom_indexed_WORD(tvbuff_t *tvb, int offset,	packet_info *pinfo,
968 					 proto_tree *tree, dcerpc_info *di, guint8 *drep,
969 					 int hfindex, guint16 * pu16WORD, int field_index)
970 {
971 	guint16 u16WORD;
972 
973 
974 	/* dissect the WORD, but don't add to tree */
975 	dissect_dcom_WORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
976 					hfindex, &u16WORD);
977 
978 	if (tree) {
979 		/* special formatted output of indexed value */
980 		proto_tree_add_uint_format(tree, hfindex, tvb, offset, 2, u16WORD,
981 			"%s[%u]: 0x%04x",
982 			proto_registrar_get_name(hfindex),
983 			field_index, u16WORD);
984 	}
985 
986 	offset += 2;
987 
988 	if (pu16WORD)
989 		*pu16WORD = u16WORD;
990 
991 	return offset;
992 }
993 
994 
995 /* dissect an indexed DWORD, something like: "FieldName[1]: 0x12345678" */
996 int
997 dissect_dcom_indexed_DWORD(tvbuff_t *tvb, int offset,	packet_info *pinfo,
998 					 proto_tree *tree, dcerpc_info *di, guint8 *drep,
999 					 int hfindex, guint32 * pu32DWORD, int field_index)
1000 {
1001 	guint32 u32DWORD;
1002 
1003 
1004 	/* dissect the DWORD, but don't add to tree */
1005 	dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1006 					hfindex, &u32DWORD);
1007 
1008 	if (tree) {
1009 		/* special formatted output of indexed value */
1010 		proto_tree_add_uint_format(tree, hfindex, tvb, offset, 4, u32DWORD,
1011 			"%s[%u]: 0x%08x",
1012 			proto_registrar_get_name(hfindex),
1013 			field_index, u32DWORD);
1014 	}
1015 
1016 	offset += 4;
1017 
1018 	if (pu32DWORD)
1019 		*pu32DWORD = u32DWORD;
1020 
1021 	return offset;
1022 }
1023 
1024 
1025 /* dissect hresult field of a usual DCOM call (create "raw" item) */
1026 int
1027 dissect_dcom_HRESULT_item(tvbuff_t *tvb, int offset,	packet_info *pinfo,
1028 					 proto_tree *tree, dcerpc_info *di, guint8 *drep,
1029 					 guint32 * pu32HResult, int field_index, proto_item **item)
1030 {
1031 	guint32 u32HResult;
1032 
1033 	/* dissect the DWORD, but don't add to tree */
1034 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1035 		    field_index, &u32HResult);
1036 
1037 	if (tree) {
1038 		/* special formatted output of indexed value */
1039 		*item = proto_tree_add_item (tree, field_index, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
1040 	}
1041 
1042 	if (pu32HResult)
1043 		*pu32HResult = u32HResult;
1044 
1045 	return offset;
1046 }
1047 
1048 
1049 /* dissect hresult field of a usual DCOM call (separate method, because often used) */
1050 int
1051 dissect_dcom_HRESULT(tvbuff_t *tvb, int offset,	packet_info *pinfo,
1052 					 proto_tree *tree, dcerpc_info *di, guint8 *drep,
1053 					 guint32 * pu32HResult)
1054 {
1055 	guint32 u32HResult;
1056 	proto_item *item = NULL;
1057 
1058 	/* dissect the DWORD, but don't add to tree */
1059 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1060 		    hf_dcom_hresult, &u32HResult);
1061 
1062 	if (tree) {
1063 		/* special formatted output of indexed value */
1064 		item = proto_tree_add_item (tree, hf_dcom_hresult, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
1065 	}
1066 
1067 	/* expert info only if severity is set */
1068 	/* XXX - move this to the callers of this function, to provide a more detailed error output */
1069 	if(u32HResult & 0x80000000) {
1070 		expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s",
1071 			val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
1072 	}
1073 	if (pu32HResult)
1074 		*pu32HResult = u32HResult;
1075 
1076 	return offset;
1077 }
1078 
1079 
1080 /* partial results of indexed DCOM subcalls (e.g.: from a kind of array) */
1081 int
1082 dissect_dcom_indexed_HRESULT(tvbuff_t *tvb, int offset,	packet_info *pinfo,
1083 					 proto_tree *tree, dcerpc_info *di, guint8 *drep,
1084 					 guint32 * pu32HResult, int field_index)
1085 {
1086 	guint32 u32HResult;
1087 	proto_item *item = NULL;
1088 
1089 
1090 	/* dissect the DWORD, but don't add to tree */
1091 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1092 		    hf_dcom_hresult, &u32HResult);
1093 
1094 	if (tree) {
1095 		/* special formatted output of indexed value */
1096 		item = proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset-4, 4, u32HResult,
1097 			"HResult[%u]: %s (0x%08x)", field_index,
1098 			val_to_str_const(u32HResult, dcom_hresult_vals, "Unknown"),
1099 			u32HResult);
1100 	}
1101 	/* expert info only if severity flag is set */
1102 	/* XXX - move this to the callers of this function, to provide a more detailed error output */
1103 	if(u32HResult & 0x80000000) {
1104 		expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s",
1105 			val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
1106 	}
1107 	if (pu32HResult)
1108 		*pu32HResult = u32HResult;
1109 
1110 	return offset;
1111 }
1112 
1113 
1114 
1115 int
1116 dissect_dcom_COMVERSION(tvbuff_t *tvb, int offset, packet_info *pinfo,
1117 						proto_tree *tree, dcerpc_info *di, guint8 *drep,
1118 						guint16	* pu16VersionMajor, guint16 * pu16VersionMinor)
1119 {
1120 
1121 	offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1122 			hf_dcom_version_major, pu16VersionMajor);
1123 	offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1124 			hf_dcom_version_minor, pu16VersionMinor);
1125 
1126 	return offset;
1127 }
1128 
1129 
1130 int
1131 dissect_dcom_SAFEARRAY(tvbuff_t *tvb, int offset, packet_info *pinfo,
1132 						proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex _U_, sa_callback_t sacb)
1133 {
1134 	guint32 u32Dims;
1135 	guint16 u16Dims;
1136 	guint16 u16Features;
1137 	guint32 u32ElementSize;
1138 	guint32 u32VarType;
1139 	guint32 u32Elements;
1140 	guint32 u32Pointer;
1141 	guint32 u32BoundElements;
1142 	guint32 u32LowBound;
1143 	gchar cData[100];
1144 	guint32 u32ArraySize;
1145 	guint32 u32VariableOffset;
1146 	guint32 u32Data;
1147 	guint16 u16Data;
1148 	guint8	u8Data;
1149 	guint16 u16Locks;
1150 	guint16 u16VarType;
1151 	proto_item *sub_item;
1152 	proto_tree *sub_tree;
1153 	guint32 u32SubStart;
1154 	guint32 u32TmpOffset;
1155 
1156 	static int * const features[] = {
1157 		&hf_dcom_sa_features_variant,
1158 		&hf_dcom_sa_features_dispatch,
1159 		&hf_dcom_sa_features_unknown,
1160 		&hf_dcom_sa_features_bstr,
1161 		&hf_dcom_sa_features_have_vartype,
1162 		&hf_dcom_sa_features_have_iid,
1163 		&hf_dcom_sa_features_record,
1164 		&hf_dcom_sa_features_fixedsize,
1165 		&hf_dcom_sa_features_embedded,
1166 		&hf_dcom_sa_features_static,
1167 		&hf_dcom_sa_features_auto,
1168 		NULL
1169 	};
1170 
1171 
1172 	/* XXX: which alignment do we need here? */
1173 
1174 	sub_item = proto_tree_add_item(tree, hf_dcom_safearray, tvb, offset, 0, ENC_NA);
1175 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_safearray);
1176 	u32SubStart = offset;
1177 
1178 	offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1179 	offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1180 
1181 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1182 			hf_dcom_sa_dims32, &u32Dims);
1183 	offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1184 			hf_dcom_sa_dims16, &u16Dims);
1185 
1186 	/* feature flags */
1187 	u32TmpOffset = dissect_dcom_WORD(tvb, offset, pinfo, NULL, di, drep, -1, &u16Features);
1188 
1189 	proto_tree_add_bitmask_value_with_flags(sub_tree, tvb, offset, hf_dcom_sa_features,
1190 								ett_dcom_sa_features, features, u16Features, BMT_NO_APPEND);
1191 	offset = u32TmpOffset;
1192 
1193 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1194 			hf_dcom_sa_element_size, &u32ElementSize);
1195 	offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1196 			hf_dcom_sa_locks, &u16Locks);
1197 	offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1198 			hf_dcom_sa_vartype16, &u16VarType);
1199 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1200 			hf_dcom_sa_vartype32, &u32VarType);
1201 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1202 			hf_dcom_sa_elements, &u32Elements);
1203 	offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1204 
1205 	u32BoundElements = 0;
1206 	while(u32Dims--) {
1207 		offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1208 							hf_dcom_sa_bound_elements, &u32BoundElements);
1209 		offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1210 							hf_dcom_sa_low_bound, &u32LowBound);
1211 	}
1212 
1213 	offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize);
1214 
1215 	tvb_ensure_bytes_exist(tvb, offset, u32ArraySize * u32ElementSize);
1216 	u32VariableOffset = offset + u32ArraySize * u32ElementSize;
1217 
1218 	if(sacb) {
1219 		sacb(tvb, offset, pinfo, tree, di, drep, u32VarType, u32ArraySize);
1220 	}
1221 
1222 	while(u32ArraySize--) {
1223 		switch(u32VarType) {
1224 			case(WIRESHARK_VT_ERROR):
1225 				offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
1226 									&u32Data);
1227 				break;
1228 			case(WIRESHARK_VT_I1):
1229 				offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1230 									hf_dcom_vt_i1, &u8Data);
1231 				break;
1232 			case(WIRESHARK_VT_I2):
1233 				offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1234 									hf_dcom_vt_i2, &u16Data);
1235 				break;
1236 			case(WIRESHARK_VT_I4):
1237 				offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1238 									hf_dcom_vt_i4, &u32Data);
1239 				break;
1240 			case(WIRESHARK_VT_I8):
1241 				offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
1242 									hf_dcom_vt_i8, NULL);
1243 				/* take care of the 8 byte alignment */
1244 				u32VariableOffset = offset;
1245 				break;
1246 			case(WIRESHARK_VT_BSTR):
1247 				offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1248 				if (u32Pointer) {
1249 					u32VariableOffset = dissect_dcom_BSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
1250 									hf_dcom_vt_bstr, cData, sizeof(cData) );
1251 				}
1252 				break;
1253 			default:
1254 				/* XXX: other types possible, but still not implemented:
1255 				VT_UNKNOWN
1256 				VT_DISPATCH
1257 				VT_VARIANT
1258 				VT_RECORD
1259 				VT_UNKNOWN|VT_RESERVED
1260 				*/
1261 				u32VariableOffset = dissect_dcom_tobedone_data(tvb, u32VariableOffset, pinfo, sub_tree, drep,
1262 								10000);
1263 		}
1264 	}
1265 
1266 	/* update subtree header */
1267 	proto_item_append_text(sub_item, ": Elements: %u/%u VarType: %s",
1268 			       u32Elements, u32BoundElements,
1269 			       val_to_str(u32VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1270 
1271 	proto_item_set_len(sub_item, u32VariableOffset - u32SubStart);
1272 
1273 	return u32VariableOffset;
1274 }
1275 
1276 
1277 
1278 int
1279 dissect_dcom_VARTYPE(tvbuff_t *tvb, int offset,	packet_info *pinfo,
1280 					proto_tree *tree, dcerpc_info *di, guint8 *drep,
1281 					guint16 *pu16VarType)
1282 {
1283 
1284 	offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1285 			hf_dcom_variant_type, pu16VarType);
1286 
1287 	return offset;
1288 }
1289 
1290 
1291 int
1292 dissect_dcom_VARIANT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1293 					 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex)
1294 {
1295 	guint32	u32Size;
1296 	guint32 u32RPCRes;
1297 	guint16 u16Res;
1298 	guint32 u32SubStart;
1299 	proto_item *sub_item;
1300 	proto_tree *sub_tree;
1301 	guint16 u16VarType;
1302 	guint32 u32VarType;
1303 
1304 	guint8	u8Data;
1305 	guint16 u16Data;
1306 	guint32 u32Data;
1307 	guint64 u64Data;
1308 	gint64 cyData;
1309 	gchar cData[500];
1310 	guint32 u32Pointer;
1311 	gfloat	f32Data;
1312 	gdouble f64Data;
1313 
1314 
1315 	/* alignment of 8 needed for a VARIANT */
1316 	if (offset % 8) {
1317 		offset += 8 - (offset % 8);
1318 	}
1319 
1320 	sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
1321 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_variant);
1322 	u32SubStart = offset;
1323 
1324 	/* the following size can be VERY confusing:
1325 	 * It is NOT the maximum size of the variant, as one could expect,
1326 	 * but the current size of the variant padded to 8 bytes.
1327 	 * BUT: The following data does not start AFTER this padding,
1328 	 * it starts just after the variant-data (without padding)!!! */
1329 	/* Conclusion: the size given here can be LONGER than the actual size */
1330 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1331 			hf_dcom_variant_size, &u32Size);
1332 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1333 			hf_dcom_variant_rpc_res, &u32RPCRes);
1334 	offset = dissect_dcom_VARTYPE(tvb, offset, pinfo, sub_tree, di, drep,
1335 						&u16VarType);
1336 	offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1337 			hf_dcom_variant_wres, &u16Res);
1338 	offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1339 			hf_dcom_variant_wres, &u16Res);
1340 	offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1341 			hf_dcom_variant_wres, &u16Res);
1342 
1343 	/* 32 bit VarType (slightly different to the 16 bit one) */
1344 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1345 			hf_dcom_variant_type32, &u32VarType);
1346 
1347 	if (u32VarType & WIRESHARK_VT_BYREF) {
1348 		u32VarType &=~WIRESHARK_VT_BYREF;
1349 		offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1350 	}
1351 
1352 	switch (u32VarType) {
1353 		case(WIRESHARK_VT_EMPTY):
1354 			break;
1355 		case(WIRESHARK_VT_BOOL):
1356 			offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, sub_tree, di, drep,
1357 								hf_dcom_vt_bool, &u16Data);
1358 			break;
1359 		case(WIRESHARK_VT_I1):
1360 			offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1361 								hf_dcom_vt_i1, &u8Data);
1362 			break;
1363 		case(WIRESHARK_VT_UI1):
1364 			offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1365 								hf_dcom_vt_ui1, &u8Data);
1366 			break;
1367 		case(WIRESHARK_VT_I2):
1368 			offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1369 								hf_dcom_vt_i2, &u16Data);
1370 			break;
1371 		case(WIRESHARK_VT_UI2):
1372 			offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1373 								hf_dcom_vt_ui2, &u16Data);
1374 			break;
1375 		case(WIRESHARK_VT_I4):
1376 			offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1377 								hf_dcom_vt_i4, &u32Data);
1378 			break;
1379 		case(WIRESHARK_VT_I8):
1380 			offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
1381 								hf_dcom_vt_i8, &u64Data);
1382 			break;
1383 		case(WIRESHARK_VT_CY):
1384 				offset = dissect_dcom_I8(tvb, offset, pinfo, NULL, di, drep,
1385 						0, &cyData);
1386 				proto_tree_add_int64_format(sub_tree, hf_dcom_vt_cy, tvb, offset - 8,
1387 						8, cyData, "%s: %" G_GINT64_FORMAT ".%.04" G_GINT64_FORMAT,
1388 						proto_registrar_get_name(hf_dcom_vt_cy),
1389 						cyData / 10000, ABS(cyData % 10000));
1390 			break;
1391 		case(WIRESHARK_VT_UI4):
1392 			offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1393 								hf_dcom_vt_ui4, &u32Data);
1394 			break;
1395 		case(WIRESHARK_VT_UI8):
1396 			offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
1397 					hf_dcom_vt_ui8, &u64Data);
1398 			break;
1399 		case(WIRESHARK_VT_R4):
1400 			offset = dissect_dcom_FLOAT(tvb, offset, pinfo, sub_tree, di, drep,
1401 								hf_dcom_vt_r4, &f32Data);
1402 			break;
1403 		case(WIRESHARK_VT_R8):
1404 			offset = dissect_dcom_DOUBLE(tvb, offset, pinfo, sub_tree, di, drep,
1405 								hf_dcom_vt_r8, &f64Data);
1406 			break;
1407 		case(WIRESHARK_VT_DATE):
1408 			offset = dissect_dcom_DATE(tvb, offset, pinfo, sub_tree, di, drep,
1409 								hf_dcom_vt_date, &f64Data);
1410 			break;
1411 		case(WIRESHARK_VT_BSTR):
1412 			offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1413 			if (u32Pointer) {
1414 				offset = dissect_dcom_BSTR(tvb, offset, pinfo, sub_tree, di, drep,
1415 								hf_dcom_vt_bstr, cData, sizeof(cData) );
1416 			}
1417 			break;
1418 		case(WIRESHARK_VT_DISPATCH):
1419 			offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1420 			if (u32Pointer) {
1421 				offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, sub_tree, di, drep,
1422 								hf_dcom_vt_dispatch, NULL); /* XXX - how to handle this? */
1423 			}
1424 			break;
1425 		case(WIRESHARK_VT_ARRAY):
1426 			offset = dissect_dcom_SAFEARRAY(tvb, offset, pinfo, sub_tree, di, drep,
1427 								0, NULL);
1428 			break;
1429 		case(WIRESHARK_VT_ERROR):
1430 			offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
1431 								0);
1432 			break;
1433 		case(WIRESHARK_VT_VARIANT):
1434 			offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1435 			if (u32Pointer) {
1436 			    offset = dissect_dcom_VARIANT(tvb, offset, pinfo, sub_tree, di, drep,
1437 								    hf_dcom_vt_byref /* must be BYREF */);
1438 			}
1439 			break;
1440 		case(WIRESHARK_VT_UNKNOWN):
1441 			offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1442 			break;
1443 		default:
1444 			/* XXX: add more types here! */
1445 			offset = dissect_dcom_tobedone_data(tvb, offset, pinfo, sub_tree, drep,
1446 							10000);
1447 	}
1448 
1449 	/* update subtree header */
1450 	proto_item_append_text(sub_item, ": %s",
1451 		val_to_str(u16VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1452 
1453 	proto_item_set_len(sub_item, offset - u32SubStart);
1454 
1455 	return offset;
1456 }
1457 
1458 
1459 int
1460 dissect_dcom_UUID(tvbuff_t *tvb, int offset,
1461 	packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep,
1462 	int hfindex, e_guid_t *pdata)
1463 {
1464 	const gchar *uuid_name;
1465 	header_field_info *hfi;
1466 	e_guid_t uuid;
1467 
1468 
1469 	/* get the UUID, but don't put it into the tree */
1470 	offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep,
1471 						hfindex, &uuid);
1472 
1473 	/* add to the tree */
1474 	hfi = proto_registrar_get_nth(hfindex);
1475 	uuid_name = guids_get_uuid_name(&uuid, pinfo->pool);
1476 	if(uuid_name) {
1477 		proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
1478 			  "%s: %s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
1479 			  hfi->name, uuid_name,
1480 			  uuid.data1, uuid.data2, uuid.data3,
1481 			  uuid.data4[0], uuid.data4[1],
1482 			  uuid.data4[2], uuid.data4[3],
1483 			  uuid.data4[4], uuid.data4[5],
1484 			  uuid.data4[6], uuid.data4[7]);
1485 	} else {
1486 		proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
1487 			  "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1488 			  hfi->name,
1489 			  uuid.data1, uuid.data2, uuid.data3,
1490 			  uuid.data4[0], uuid.data4[1],
1491 			  uuid.data4[2], uuid.data4[3],
1492 			  uuid.data4[4], uuid.data4[5],
1493 			  uuid.data4[6], uuid.data4[7]);
1494 	}
1495 
1496 	if(pdata != NULL) {
1497 		*pdata = uuid;
1498 	}
1499 
1500 	return offset;
1501 }
1502 
1503 
1504 int
1505 dissect_dcom_append_UUID(tvbuff_t *tvb, int offset,
1506 	packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep,
1507 	int hfindex, int field_index, e_guid_t *uuid)
1508 {
1509 	const gchar *uuid_name;
1510 	proto_item *pi;
1511 	header_field_info *hfi;
1512 
1513 
1514 	/* XXX - this is far from being performance optimized! */
1515 
1516 	/* get the UUID, but don't put it into the tree */
1517 	offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep,
1518 						hfindex, uuid);
1519 
1520 	/* look for a registered uuid name */
1521 	uuid_name = guids_get_uuid_name(uuid, pinfo->pool);
1522 
1523 	/* add to the tree */
1524 	hfi = proto_registrar_get_nth(hfindex);
1525 	pi = proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) uuid, "%s", hfi->name);
1526 
1527 	if (field_index != -1) {
1528 		proto_item_append_text(pi, "[%u]: ", field_index);
1529 	} else {
1530 		proto_item_append_text(pi, ": ");
1531 	}
1532 
1533 	if(uuid_name) {
1534 		proto_item_append_text(pi, "%s (", uuid_name);
1535 	}
1536 
1537 	proto_item_append_text(pi, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1538 			  uuid->data1, uuid->data2, uuid->data3,
1539 			  uuid->data4[0], uuid->data4[1],
1540 			  uuid->data4[2], uuid->data4[3],
1541 			  uuid->data4[4], uuid->data4[5],
1542 			  uuid->data4[6], uuid->data4[7]);
1543 
1544 	if(uuid_name) {
1545 		proto_item_append_text(pi, ")");
1546 	}
1547 
1548 	/* update column info now */
1549 	if (field_index != -1) {
1550 		col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]=%s",
1551 			hfi->name, field_index, (uuid_name) ? uuid_name : "???");
1552 	} else {
1553 		col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%s",
1554 			hfi->name, (uuid_name) ? uuid_name : "???");
1555 	}
1556 
1557 	return offset;
1558 }
1559 
1560 
1561 /* get a wide character string from tvb (zero terminated or limited through inLength) */
1562 /* the string will be converted to ASCII if possible or simple hexdump otherwise */
1563 /* outLength is in output bytes including zero termination output */
1564 static int
1565 dcom_tvb_get_nwstringz0(tvbuff_t *tvb, gint offset, guint32 inLength, gchar *pszStr, guint32 outLength, gboolean *isPrintable)
1566 {
1567 	guint32 u32Idx;
1568 	guint32 u32IdxA;
1569 	guint32 u32IdxW;
1570 	guint32 inLengthWithoutNullDelimiter = 0;
1571 
1572 	guint8	u8Tmp1;
1573 	guint8	u8Tmp2;
1574 
1575 
1576 	*isPrintable = TRUE;
1577 	inLengthWithoutNullDelimiter = inLength == 0 ? 0 : inLength -1;
1578 
1579 	/* we must have at least the space for the zero termination */
1580 	DISSECTOR_ASSERT(outLength >= 1);
1581 
1582 	/* determine length and printablility of the string */
1583 	for(u32Idx = 0; u32Idx < inLengthWithoutNullDelimiter; u32Idx+=2) {
1584 		/* the marshalling direction of a WCHAR is fixed! */
1585 		u8Tmp1 = tvb_get_guint8(tvb, offset+u32Idx);
1586 		u8Tmp2 = tvb_get_guint8(tvb, offset+u32Idx+1);
1587 
1588 		/* is this the zero termination? */
1589 		if (u8Tmp1 == 0 && u8Tmp2 == 0) {
1590 			u32Idx+=2;
1591 			break;
1592 		}
1593 
1594 		/* is this character printable? */
1595 		/* 10 = New Line, 13 = Carriage Return */
1596 		/* XXX - there are probably more printable chars than isprint() */
1597 		if(!(g_ascii_isprint(u8Tmp1) || u8Tmp1 == 10 || u8Tmp1 == 13)|| u8Tmp2 != 0) {
1598 			*isPrintable = FALSE;
1599 		}
1600 	}
1601 
1602 	/* u32Idx now contains the string length in bytes */
1603 	/* (including optional zero termination) */
1604 
1605 	/* if this is a printable string? */
1606 	if(*isPrintable == TRUE) {
1607 		/* convert to ascii (every "2nd char") */
1608 		/* XXX - is it possible to convert to UTF8, so the output functions work with it? */
1609 		for(u32IdxA = 0, u32IdxW = 0;
1610 		    u32IdxW < u32Idx && u32IdxA < outLength-2;
1611 		    u32IdxW+=2, u32IdxA++) {
1612 			pszStr[u32IdxA] = tvb_get_guint8(tvb, offset+u32IdxW);
1613 		}
1614 	} else {
1615 		/* convert to hexdump */
1616 		for(u32IdxA = 0, u32IdxW = 0;
1617 		    u32IdxW < u32Idx && u32IdxA < outLength-2;
1618 		    u32IdxW++, u32IdxA+=2) {
1619 			g_snprintf(&pszStr[u32IdxA], 3, "%02X", tvb_get_guint8(tvb, offset+u32IdxW));
1620 		}
1621 	}
1622 
1623 	/* zero terminate the string, space must be available */
1624 	DISSECTOR_ASSERT(u32IdxA < outLength);
1625 	pszStr[u32IdxA] = 0;
1626 
1627 	return offset + u32Idx;
1628 }
1629 
1630 
1631 /* dissect a LPWSTR into a given buffer */
1632 /* use FT_STRING for hfindex */
1633 /* u32MaxStr is maximum length of string (including trailing zero) */
1634 int
1635 dissect_dcom_indexed_LPWSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1636 		       proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex,
1637 					   gchar *pszStr, guint32 u32MaxStr, int field_index)
1638 {
1639 	guint32 u32MaxCount;
1640 	guint32 u32Offset;
1641 	guint32 u32ArraySize;
1642 	guint32 u32StrStart;
1643 	proto_item *sub_item;
1644 	proto_tree *sub_tree;
1645 	guint32 u32SubStart;
1646 	gboolean isPrintable;
1647 
1648 
1649 	/* alignment of 4 needed */
1650 	if (offset % 4) {
1651 		offset += 4 - (offset % 4);
1652 	}
1653 
1654 	/* add subtree item */
1655 	sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
1656 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
1657 	u32SubStart = offset;
1658 
1659 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1660 			hf_dcom_max_count, &u32MaxCount);
1661 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1662 			hf_dcom_offset, &u32Offset);
1663 	offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep,
1664 			&u32ArraySize);
1665 
1666 	u32StrStart = offset;
1667 	offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1668 
1669 	proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr);
1670 
1671 	/* update subtree header */
1672 	if (field_index != -1) {
1673 		proto_item_set_text(sub_item, "%s[%u]: %s%s%s",
1674 			proto_registrar_get_name(hfindex),
1675 			field_index,
1676 			isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1677 	} else {
1678 		proto_item_append_text(sub_item, "%s%s%s",
1679 				       isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1680 	}
1681 	proto_item_set_len(sub_item, offset - u32SubStart);
1682 
1683 	return offset;
1684 }
1685 
1686 
1687 int
1688 dissect_dcom_LPWSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1689 		       proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex,
1690 					   gchar *pszStr, guint32 u32MaxStr)
1691 {
1692 
1693 
1694 	return dissect_dcom_indexed_LPWSTR(tvb, offset, pinfo, tree, di, drep,
1695 						hfindex, pszStr, u32MaxStr, -1);
1696 }
1697 
1698 
1699 /* dissect a BSTR to tree and into a given buffer (use FT_STRING for hfindex) */
1700 /* u32MaxStr is maximum length of string (including trailing zero) */
1701 /* (Hint: the BSTR space is always as long as the maximum size) */
1702 int
1703 dissect_dcom_BSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1704 		       proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex,
1705 					   gchar *pszStr, guint32 u32MaxStr)
1706 {
1707 	guint32 u32MaxCount;
1708 	guint32 u32ArraySize;
1709 	gint strStart, subStart, realOffset;
1710 	proto_item *sub_item;
1711 	proto_tree *sub_tree;
1712 	guint32 u32ByteLength;
1713 	gboolean isPrintable;
1714 
1715 	/* alignment of 4 needed */
1716 	if (offset % 4) {
1717 		offset += 4 - (offset % 4);
1718 	}
1719 
1720 	/* add subtree item */
1721 	sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
1722 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
1723 	subStart = offset;
1724 
1725 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1726 			hf_dcom_max_count, &u32MaxCount);
1727 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1728 			hf_dcom_byte_length, &u32ByteLength);
1729 	offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep,
1730 			&u32ArraySize);
1731 
1732 	if ((guint32)offset + u32ArraySize*2 > G_MAXINT) {
1733 		pszStr[0] = 0;
1734 		return offset;
1735 	}
1736 
1737 	realOffset = offset + u32ArraySize*2;
1738 
1739 	strStart = offset;
1740 	offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1741 
1742 	proto_tree_add_string(sub_tree, hfindex, tvb, strStart, offset - strStart, pszStr);
1743 
1744 	/* update subtree header */
1745 	proto_item_append_text(sub_item, "%s%s%s",
1746 	isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1747 	if (realOffset <= subStart) {
1748 		/* XXX - expert info */
1749 		return offset;
1750 	}
1751 	proto_item_set_len(sub_item, realOffset - subStart);
1752 
1753 	return realOffset;
1754 }
1755 
1756 
1757 /* dissect an DUALSTRINGARRAY */
1758 int
1759 dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1760 		       proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, gchar *ip)
1761 {
1762 	guint16	u16NumEntries;
1763 	guint16	u16SecurityOffset;
1764 	gchar	szStr[1000];
1765 	guint32	u32MaxStr = sizeof(szStr);
1766 	guint32	u32Start;
1767 	guint16 u16TowerId;
1768 	guint16 u16SecurityAuthnSvc;
1769 	guint16 u16SecurityAuthzSvc;
1770 	proto_item *sub_item;
1771 	proto_tree *sub_tree;
1772 	guint32	u32SubStart;
1773 	guint32	u32StringBindings = 0;
1774 	guint32	u32SecurityBindings = 0;
1775 	proto_item *subsub_item;
1776 	proto_tree *subsub_tree;
1777 	guint32	u32SubSubStart;
1778 	gboolean isPrintable;
1779 	guint32 first_ip = 0;
1780 	guint32 curr_ip = 0;
1781 	guint32 ipaddr;
1782 	proto_item *pi;
1783 
1784 
1785 	/* add subtree header */
1786 	sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
1787 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_dualstringarray);
1788 
1789 	offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1790 			hf_dcom_dualstringarray_num_entries, &u16NumEntries);
1791 	/* from here, alignment is ok */
1792 	u32SubStart = offset - 2;
1793 	offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1794 			hf_dcom_dualstringarray_security_offset, &u16SecurityOffset);
1795 
1796 	/* STRINGBINDINGs until first wchar zero */
1797 	while ( tvb_get_ntohs(tvb, offset) ) {
1798 		u32StringBindings++;
1799 
1800 		subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_string, tvb, offset, 0, ENC_NA);
1801 		subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
1802 		u32SubSubStart = offset;
1803 
1804 		offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1805 							hf_dcom_dualstringarray_string_tower_id, &u16TowerId);
1806 		u32Start = offset;
1807 	/* we don't know the (zero terminated) input length, use the buffer length instead */
1808 		offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
1809 		pi = proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_string_network_addr,
1810 			tvb, u32Start, offset - u32Start, szStr);
1811 
1812 	/* convert ip address (if it is dotted decimal) */
1813 	/* XXX - this conversion is ugly */
1814 		if (ws_inet_pton4(szStr, &ipaddr)) {
1815 			if(get_host_ipaddr(szStr, &curr_ip)) {
1816 
1817 				/*expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "DUALSTRINGARRAY: IP:%s",
1818 				  ip_to_str( (guint8 *) &curr_ip));*/
1819 
1820 				if(first_ip == 0) {
1821 					if(ip != NULL) {
1822 						memcpy(ip, &curr_ip, sizeof(curr_ip));
1823 					}
1824 					first_ip = curr_ip;
1825 				} else {
1826 					if(first_ip != curr_ip) {
1827 						address first_ip_addr, curr_ip_addr;
1828 
1829 						set_address(&first_ip_addr, AT_IPv4, 4, &first_ip);
1830 						set_address(&curr_ip_addr, AT_IPv4, 4, &curr_ip);
1831 						expert_add_info_format(pinfo, pi, &ei_dcom_dualstringarray_mult_ip,
1832 								       "DUALSTRINGARRAY: multiple IP's %s %s",
1833 								       address_to_str(pinfo->pool, &first_ip_addr), address_to_str(pinfo->pool, &curr_ip_addr));
1834 					}
1835 				}
1836 			}
1837 		}
1838 
1839 		proto_item_append_text(subsub_item, "[%u]: TowerId=%s, NetworkAddr=\"%s\"",
1840 			u32StringBindings,
1841 			val_to_str(u16TowerId, dcom_protseq_vals, "Unknown (0x%04x"),
1842 			szStr);
1843 		proto_item_set_len(subsub_item, offset - u32SubSubStart);
1844 	}
1845 	offset += 2;
1846 
1847 	/* SECURITYBINDINGs until first wchar zero */
1848 	while ( tvb_get_ntohs(tvb, offset) ) {
1849 		u32SecurityBindings++;
1850 
1851 		subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_security, tvb, offset, 0, ENC_NA);
1852 		subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
1853 		u32SubSubStart = offset;
1854 
1855 		offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1856 			hf_dcom_dualstringarray_security_authn_svc,
1857 						&u16SecurityAuthnSvc);
1858 		offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1859 			hf_dcom_dualstringarray_security_authz_svc,
1860 						&u16SecurityAuthzSvc);
1861 
1862 		u32Start = offset;
1863 	/* we don't know the (zero terminated) input length, use the buffer length instead */
1864 		offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
1865 		proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_security_princ_name,
1866 			tvb, u32Start, offset - u32Start, szStr);
1867 
1868 		proto_item_append_text(subsub_item, "[%u]: AuthnSvc=0x%04x, AuthzSvc=0x%04x, PrincName=\"%s\"",
1869 			u32SecurityBindings, u16SecurityAuthnSvc, u16SecurityAuthzSvc, szStr);
1870 		proto_item_set_len(subsub_item, offset - u32SubSubStart);
1871 	}
1872 	offset += 2;
1873 
1874 	/* append info to subtree header */
1875 	proto_item_append_text(sub_item, ": STRINGBINDINGs=%u, SECURITYBINDINGs=%u",
1876 		u32StringBindings, u32SecurityBindings);
1877 	proto_item_set_len(sub_item, offset - u32SubStart);
1878 
1879 	return offset;
1880 }
1881 
1882 
1883 /* dissect an STDOBJREF */
1884 int
1885 dissect_dcom_STDOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1886 		       proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex _U_,
1887 		       guint64 *oxid, guint64 *oid, e_guid_t *ipid)
1888 {
1889 	guint32	u32Flags;
1890 	guint32	u32PublicRefs;
1891 	proto_item *sub_item;
1892 	proto_tree *sub_tree;
1893 	guint32	u32SubStart;
1894 
1895 
1896 	/* add subtree header */
1897 	sub_item = proto_tree_add_item(tree, hf_dcom_stdobjref, tvb, offset, 0, ENC_NA);
1898 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_stdobjref);
1899 
1900 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1901 			hf_dcom_stdobjref_flags, &u32Flags);
1902 	/* from here, alignment is ok */
1903 	u32SubStart = offset - 4;
1904 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1905 			hf_dcom_stdobjref_public_refs, &u32PublicRefs);
1906 	offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep,
1907 			hf_dcom_oxid, oxid);
1908 	offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep,
1909 			hf_dcom_oid, oid);
1910 	offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
1911 			hf_dcom_ipid, ipid);
1912 
1913 	/* append info to subtree header */
1914 	proto_item_append_text(sub_item, ": PublicRefs=%u IPID=%s",
1915 		u32PublicRefs, guids_resolve_guid_to_str(ipid, pinfo->pool));
1916 	proto_item_set_len(sub_item, offset - u32SubStart);
1917 
1918 	return offset;
1919 }
1920 
1921 
1922 
1923 /*
1924  *
1925  *static void
1926  *print_uuid(const e_guid_t* uuid)
1927 *{
1928  *    proto_tree_add_debug_text(NULL, "UUID:(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)\n",
1929  *            uuid->data1, uuid->data2, uuid->data3,
1930  *            uuid->data4[0], uuid->data4[1],
1931  *            uuid->data4[2], uuid->data4[3],
1932  *            uuid->data4[4], uuid->data4[5],
1933  *            uuid->data4[6], uuid->data4[7]);
1934  *
1935  *    return;
1936  *}
1937  *
1938  */
1939 
1940 int
1941 dcom_register_routine(dcom_dissect_fn_t routine, e_guid_t* uuid)
1942 {
1943 	dcom_marshaler_t *marshaler;
1944 
1945 
1946 	/* check if exists already */
1947 	if (dcom_get_routine_by_uuid(uuid))
1948 		return -1;
1949 
1950 	marshaler = wmem_new(wmem_file_scope(), dcom_marshaler_t);
1951 	if (!marshaler) {
1952 		/*memory error*/
1953 		return -1;
1954 	}
1955 
1956 	marshaler->parent = NULL;
1957 	marshaler->private_data = NULL;
1958 	marshaler->uuid = *uuid;
1959 	marshaler->routine = routine;
1960 
1961 	dcom_marshalers = g_list_append(dcom_marshalers, marshaler);
1962 
1963 	return 0;
1964 }
1965 
1966 
1967 dcom_dissect_fn_t
1968 dcom_get_routine_by_uuid(const e_guid_t* uuid)
1969 {
1970 	dcom_marshaler_t *marsh;
1971 	GList *marshalers;
1972 
1973 	if(memcmp(uuid, &uuid_null, sizeof(uuid_null)) == 0) {
1974 		return NULL;
1975 	}
1976 
1977 	for(marshalers = dcom_marshalers; marshalers!= NULL;
1978 		    marshalers = g_list_next(marshalers)) {
1979 		marsh = (dcom_marshaler_t *)marshalers->data;
1980 		/*print_uuid(&marsh->uuid);*/
1981 		/*print_uuid(uuid);*/
1982 		if(memcmp(&marsh->uuid, uuid, sizeof(e_guid_t)) == 0) {
1983 		    return marsh->routine;
1984 		}
1985 	}
1986 
1987 	return NULL;
1988 }
1989 
1990 /* dissect an CUSTOM */
1991 static int
1992 dissect_dcom_CUSTOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1993 		               proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex,
1994 		               e_guid_t *clsid, e_guid_t *iid)
1995 {
1996 	guint32    u32CBExtension;
1997 	guint32    u32Size;
1998 	guint32    u32SubStart;
1999 	proto_item *sub_item;
2000 	proto_tree *sub_tree;
2001 	dcom_dissect_fn_t routine = NULL;
2002 
2003 
2004 	/* add subtree header */
2005 	hfindex = hf_dcom_custobjref;
2006 	sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_NA);
2007 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_custobjref);
2008 
2009 	u32SubStart = offset;
2010 	offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2011 		    hf_dcom_clsid, clsid);
2012 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2013 		    hf_dcom_objref_cbextension, &u32CBExtension);
2014 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2015 		    hf_dcom_objref_size, &u32Size);
2016 
2017 	/* the following data depends on the iid, get the routine by iid */
2018 	routine = dcom_get_routine_by_uuid(iid);
2019 	if (routine){
2020 		offset = routine(tvb, offset, pinfo, sub_tree, di, drep, 0);
2021 	}
2022 
2023 	/* append info to subtree header */
2024 	/* proto_item_append_text(sub_item, ": ActivationPropertiesIn"); */
2025 	proto_item_set_len(sub_item, offset - u32SubStart);
2026 
2027 	return offset;
2028 }
2029 
2030 /* dissect an OBJREF */
2031 int
2032 dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2033 		       proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, dcom_interface_t **interf)
2034 {
2035 	guint32	u32Signature;
2036 	guint32	u32Flags;
2037 	e_guid_t iid;
2038 	e_guid_t clsid;
2039 	proto_item *sub_item;
2040 	proto_tree *sub_tree;
2041 	guint32	u32SubStart;
2042 	guint64 oxid = 0;
2043 	guint64 oid = 0;
2044 	e_guid_t ipid;
2045 	dcom_interface_t *dcom_if = NULL;
2046 	gchar ip[4];
2047 
2048 	memset(&ipid, 0, sizeof(ipid));
2049 	memset(ip, 0, sizeof(ip));
2050 
2051 	/* add subtree header */
2052 	sub_item = proto_tree_add_item(tree, hf_dcom_objref, tvb, offset, 0, ENC_NA);
2053 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_objref);
2054 
2055 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2056 			hf_dcom_objref_signature, &u32Signature);
2057 	/* from here, alignment is ok */
2058 	u32SubStart = offset - 4;
2059 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2060 			hf_dcom_objref_flags, &u32Flags);
2061 	offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2062 			hf_dcom_iid, &iid);
2063 
2064 	switch(u32Flags) {
2065 		case(0x1):	/* standard */
2066 			offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2067 								&oxid, &oid, &ipid);
2068 			offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep,
2069 								hf_dcom_objref_resolver_address, ip);
2070 		break;
2071 		case(0x2):	/* handler (untested) */
2072 			offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2073 								&oxid, &oid, &iid);
2074 			offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2075 								hf_dcom_clsid, &clsid);
2076 			offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep,
2077 								hf_dcom_objref_resolver_address, ip);
2078 		break;
2079 		case(0x4):	/* custom */
2080 		    offset = dissect_dcom_CUSTOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2081 		                        &clsid, &iid);
2082 		    break;
2083 	}
2084 
2085 	if(u32Flags == 0x1 || u32Flags == 0x2) {
2086 		/* add interface instance to database (we currently only handle IPv4) */
2087 		if(pinfo->net_src.type == AT_IPv4) {
2088 			address addr;
2089 
2090 			set_address(&addr, AT_IPv4, 4, ip);
2091 			dcom_if = dcom_interface_new(pinfo,
2092 						     &addr,
2093 						     &iid, oxid, oid, &ipid);
2094 		}
2095 	}
2096 
2097 	if(interf != NULL) {
2098 		*interf = dcom_if;
2099 	}
2100 
2101 	/* append info to subtree header */
2102 	proto_item_set_len(sub_item, offset - u32SubStart);
2103 
2104 	return offset;
2105 }
2106 
2107 /* dissect an MInterfacePointer */
2108 int
2109 dissect_dcom_MInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2110 		       proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, dcom_interface_t **interf)
2111 {
2112 	guint32	u32CntData;
2113 	guint32	u32ArraySize;
2114 	proto_item *sub_item;
2115 	proto_tree *sub_tree;
2116 	guint32	u32SubStart;
2117 
2118 
2119 	if (!hfindex) {
2120 		hfindex = hf_dcom_interface_pointer;
2121 	}
2122 
2123 	/* add subtree header */
2124 	sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
2125 	sub_tree = proto_item_add_subtree(sub_item, ett_dcom_interface_pointer);
2126 
2127 	offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize);
2128 	u32SubStart = offset - 4; /* should use this trick to deal with align pad if any */
2129 
2130 	offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2131 			hf_dcom_ip_cnt_data, &u32CntData);
2132 
2133 	offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex, interf);
2134 
2135 	/* append info to subtree header */
2136 	proto_item_set_len(sub_item, offset - u32SubStart);
2137 
2138 	return offset;
2139 }
2140 
2141 /* dissect a pointer to a MInterfacePointer */
2142 int
2143 dissect_dcom_PMInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2144 		       proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, dcom_interface_t **interf)
2145 {
2146 	guint32 u32Pointer;
2147 
2148 
2149 	offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
2150 
2151 	if (u32Pointer) {
2152 		offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, di, drep, hfindex, interf);
2153 	} else {
2154 		if(interf != NULL) {
2155 			*interf = NULL;
2156 		}
2157 	}
2158 
2159 	return offset;
2160 }
2161 
2162 static void dcom_cleanup(void) {
2163 	if (dcom_machines != NULL) {
2164 		GList *machines;
2165 
2166 		for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
2167 			dcom_machine_t *machine = (dcom_machine_t *)machines->data;
2168 
2169 			if (machine->objects != NULL) {
2170 				GList *objects;
2171 				for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
2172 					dcom_object_t *object = (dcom_object_t *)objects->data;
2173 
2174 					if (object->interfaces != NULL) {
2175 						GList *interface;
2176 						for(interface = object->interfaces; interface != NULL; interface = g_list_next(interface)) {
2177 							g_free(interface->data);
2178 							interface->data = NULL; /* for good measure */
2179 						}
2180 						g_list_free(object->interfaces);
2181 						object->interfaces = NULL;  /* for good measure */
2182 					}
2183 
2184 					g_free(objects->data);
2185 					objects->data = NULL; /* for good measure */
2186 				}
2187 				g_list_free(machine->objects);
2188 				free_address(&machine->ip);
2189 				machine->objects = NULL; /* for good measure */
2190 			}
2191 
2192 			g_free(machines->data);
2193 			machines->data = NULL; /* for good measure */
2194 		}
2195 		g_list_free(dcom_machines);
2196 		dcom_machines = NULL;
2197 	}
2198 
2199 	/*  The data in dcom_interfaces is wmem_file_scoped so there's no need to free
2200 	 *  the data pointers.
2201 	 */
2202 	if (dcom_interfaces != NULL) {
2203 		g_list_free(dcom_interfaces);
2204 		dcom_interfaces = NULL;
2205 	}
2206 
2207 	/*  The data in dcom_marshalers is wmem_file_scoped so there's no need to free
2208 	 *  the data pointers.
2209 	 */
2210 	if (dcom_marshalers != NULL) {
2211 		g_list_free(dcom_marshalers);
2212 		dcom_marshalers = NULL;
2213 	}
2214 }
2215 
2216 void
2217 proto_register_dcom (void)
2218 {
2219 	static hf_register_info hf_dcom_this_array[] = {
2220 #if 0
2221 		{ &hf_dcom_this_version_major,
2222 		{ "VersionMajor", "dcom.this.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2223 #endif
2224 #if 0
2225 		{ &hf_dcom_this_version_minor,
2226 		{ "VersionMinor", "dcom.this.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2227 #endif
2228 		{ &hf_dcom_this_flags,
2229 		{ "Flags", "dcom.this.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }},
2230 		{ &hf_dcom_this_res,
2231 		{ "Reserved", "dcom.this.res", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2232 		{ &hf_dcom_this_cid,
2233 		{ "Causality ID", "dcom.this.uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2234 	};
2235 
2236 	static hf_register_info hf_dcom_that_array[] = {
2237 		{ &hf_dcom_that_flags,
2238 		{ "Flags", "dcom.that.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }}
2239 	};
2240 
2241 	static hf_register_info hf_dcom_extent_array[] = {
2242 		{ &hf_dcom_extent,
2243 		{ "Extension", "dcom.extent", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2244 		{ &hf_dcom_extent_array_count,
2245 		{ "Extension Count", "dcom.extent.array_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2246 		{ &hf_dcom_extent_array_res,
2247 		{ "Reserved", "dcom.extent.array_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2248 		{ &hf_dcom_extent_size,
2249 		{ "Extension Size", "dcom.extent.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2250 		{ &hf_dcom_extent_id,
2251 		{ "Extension Id", "dcom.extent.id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2252 	};
2253 
2254 	static hf_register_info hf_dcom_array[] = {
2255 		{ &hf_dcom_version_major,
2256 		{ "VersionMajor", "dcom.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2257 		{ &hf_dcom_version_minor,
2258 		{ "VersionMinor", "dcom.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2259 		{ &hf_dcom_hresult,
2260 		{ "HResult", "dcom.hresult", FT_UINT32, BASE_HEX, VALS(dcom_hresult_vals), 0x0, NULL, HFILL }},
2261 		{ &hf_dcom_max_count,
2262 		{ "MaxCount", "dcom.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2263 		{ &hf_dcom_offset,
2264 		{ "Offset", "dcom.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2265 		{ &hf_dcom_byte_length,
2266 		{ "ByteLength", "dcom.byte_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2267 #if 0
2268 		{ &hf_dcom_actual_count,
2269 		{ "ActualCount", "dcom.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2270 #endif
2271 		{ &hf_dcom_tobedone,
2272 		{ "To Be Done", "dcom.tobedone", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2273 		{ &hf_dcom_nospec,
2274 		{ "No Specification Available", "dcom.nospec", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2275 #if 0
2276 		{ &hf_dcom_variant,
2277 		{ "Variant", "dcom.variant", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2278 #endif
2279 		{ &hf_dcom_variant_type,
2280 		{ "VarType", "dcom.variant_type", FT_UINT16, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2281 		{ &hf_dcom_variant_type32,
2282 		{ "VarType32", "dcom.variant_type32", FT_UINT32, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2283 		{ &hf_dcom_variant_size,
2284 		{ "Size", "dcom.variant_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2285 		{ &hf_dcom_variant_rpc_res,
2286 		{ "RPC-Reserved", "dcom.variant_rpc_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2287 		{ &hf_dcom_variant_wres,
2288 		{ "Reserved", "dcom.variant_wres", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2289 		{ &hf_dcom_array_size,
2290 		{ "(ArraySize)", "dcom.array_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2291 		{ &hf_dcom_pointer_val,
2292 		{ "(PointerVal)", "dcom.pointer_val", FT_UINT32, BASE_HEX, VALS(dcom_dcerpc_pointer_vals), 0x0, NULL, HFILL }}
2293 	};
2294 
2295 	static hf_register_info hf_dcom_interface_pointer_array[] = {
2296 		{ &hf_dcom_interface_pointer,
2297 		{ "InterfacePointer", "dcom.ifp", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2298 		{ &hf_dcom_ip_cnt_data,
2299 		{ "CntData", "dcom.ip_cnt_data", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
2300 	};
2301 
2302 	static hf_register_info hf_dcom_objref_array[] = {
2303 		{ &hf_dcom_objref,
2304 		{ "OBJREF", "dcom.objref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2305 		{ &hf_dcom_objref_signature,
2306 		{ "Signature", "dcom.objref.signature", FT_UINT32, BASE_HEX, VALS(dcom_objref_signature_vals), 0x0, NULL, HFILL }},
2307 		{ &hf_dcom_objref_flags,
2308 		{ "Flags", "dcom.objref.flags", FT_UINT32, BASE_HEX, VALS(dcom_objref_flag_vals), 0x0, NULL, HFILL }},
2309 		{ &hf_dcom_iid,
2310 		{ "IID", "dcom.iid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2311 		{ &hf_dcom_clsid,
2312 		{ "CLSID", "dcom.clsid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2313 		{ &hf_dcom_objref_resolver_address,
2314 		{ "ResolverAddress", "dcom.objref.resolver_address", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2315 		{ &hf_dcom_objref_cbextension,
2316 		{ "CBExtension", "dcom.objref.cbextension", FT_UINT32, BASE_DEC, NULL, 0x0, "Size of extension data", HFILL }},
2317 		{ &hf_dcom_objref_size,
2318 		{ "Size", "dcom.objref.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
2319 	};
2320 
2321 	static hf_register_info hf_dcom_stdobjref_array[] = {
2322 		{ &hf_dcom_stdobjref,
2323 		{ "STDOBJREF", "dcom.stdobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2324 		{ &hf_dcom_stdobjref_flags,
2325 		{ "Flags", "dcom.stdobjref.flags", FT_UINT32, BASE_HEX, VALS(dcom_stdobjref_flag_vals), 0x0, NULL, HFILL }},
2326 		{ &hf_dcom_stdobjref_public_refs,
2327 		{ "PublicRefs", "dcom.stdobjref.public_refs", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2328 		{ &hf_dcom_oxid,
2329 		{ "OXID", "dcom.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2330 		{ &hf_dcom_oid,
2331 		{ "OID", "dcom.oid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2332 		{ &hf_dcom_ipid,
2333 		{ "IPID", "dcom.ipid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2334 	};
2335 
2336 	static hf_register_info hf_dcom_custobjref_array[] = {
2337 		{ &hf_dcom_custobjref,
2338 		{ "CUSTOMOBJREF", "dcom.custobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2339 	};
2340 
2341 
2342 	static hf_register_info hf_dcom_dualstringarray_array[] = {
2343 		{ &hf_dcom_dualstringarray_num_entries,
2344 		{ "NumEntries", "dcom.dualstringarray.num_entries", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2345 		{ &hf_dcom_dualstringarray_security_offset,
2346 		{ "SecurityOffset", "dcom.dualstringarray.security_offset", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2347 		{ &hf_dcom_dualstringarray_string,
2348 		{ "StringBinding", "dcom.dualstringarray.string", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2349 		{ &hf_dcom_dualstringarray_string_tower_id,
2350 		{ "TowerId", "dcom.dualstringarray.tower_id", FT_UINT16, BASE_HEX, VALS(dcom_protseq_vals), 0x0, NULL, HFILL }},
2351 		{ &hf_dcom_dualstringarray_string_network_addr,
2352 		{ "NetworkAddr", "dcom.dualstringarray.network_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2353 		{ &hf_dcom_dualstringarray_security,
2354 		{ "SecurityBinding", "dcom.dualstringarray.security", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2355 		{ &hf_dcom_dualstringarray_security_authn_svc,
2356 		{ "AuthnSvc", "dcom.dualstringarray.security_authn_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authn), 0x0, NULL, HFILL }},
2357 		{ &hf_dcom_dualstringarray_security_authz_svc,
2358 		{ "AuthzSvc", "dcom.dualstringarray.security_authz_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authz), 0x0, NULL, HFILL }},
2359 		{ &hf_dcom_dualstringarray_security_princ_name,
2360 		{ "PrincName", "dcom.dualstringarray.security_princ_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2361 	};
2362 
2363 	static hf_register_info hf_dcom_vt_array[] = {
2364 		{ &hf_dcom_vt_bool,
2365 		{ "VT_BOOL", "dcom.vt.bool", FT_UINT16, BASE_HEX, VALS(dcom_vt_bool_vals), 0x0, NULL, HFILL }},
2366 		{ &hf_dcom_vt_i1,
2367 		{ "VT_I1", "dcom.vt.i1", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2368 		{ &hf_dcom_vt_i2,
2369 		{ "VT_I2", "dcom.vt.i2", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2370 		{ &hf_dcom_vt_i4,
2371 		{ "VT_I4", "dcom.vt.i4", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2372 		{ &hf_dcom_vt_i8,
2373 		{ "VT_I8", "dcom.vt.i8", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2374 		{ &hf_dcom_vt_cy,
2375 		{ "VT_CY", "dcom.vt.cy", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2376 		{ &hf_dcom_vt_ui1,
2377 		{ "VT_UI1", "dcom.vt.ui1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2378 		{ &hf_dcom_vt_ui2,
2379 		{ "VT_UI2", "dcom.vt.ui2", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2380 		{ &hf_dcom_vt_ui4,
2381 		{ "VT_UI4", "dcom.vt.ui4", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2382 		{ &hf_dcom_vt_ui8,
2383 		{ "VT_UI8", "dcom.vt.ui8", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2384 		{ &hf_dcom_vt_r4,
2385 		{ "VT_R4", "dcom.vt.r4", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2386 		{ &hf_dcom_vt_r8,
2387 		{ "VT_R8", "dcom.vt.r8", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2388 		{ &hf_dcom_vt_date,
2389 		{ "VT_DATE", "dcom.vt.date", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2390 		{ &hf_dcom_vt_bstr,
2391 		{ "VT_BSTR", "dcom.vt.bstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2392 		{ &hf_dcom_vt_byref,
2393 		{ "BYREF", "dcom.vt.byref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2394 		{ &hf_dcom_vt_dispatch,
2395 		{ "VT_DISPATCH", "dcom.vt.dispatch", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2396 	};
2397 
2398 	static hf_register_info hf_dcom_sa_array[] = {
2399 		{ &hf_dcom_safearray,
2400 		{ "SAFEARRAY", "dcom.sa", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2401 		{ &hf_dcom_sa_dims32,
2402 		{ "Dims32", "dcom.sa.dims32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2403 		{ &hf_dcom_sa_dims16,
2404 		{ "Dims16", "dcom.sa.dims16", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2405 		{ &hf_dcom_sa_features,
2406 		{ "Features", "dcom.sa.features", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2407 		{ &hf_dcom_sa_element_size,
2408 		{ "ElementSize", "dcom.sa.element_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2409 		{ &hf_dcom_sa_locks,
2410 		{ "Locks", "dcom.sa.locks", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2411 		{ &hf_dcom_sa_vartype32,
2412 		{ "VarType32", "dcom.sa.vartype", FT_UINT32, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2413 		{ &hf_dcom_sa_vartype16,
2414 		{ "VarType16", "dcom.sa.vartype", FT_UINT16, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2415 		{ &hf_dcom_sa_elements,
2416 		{ "Elements", "dcom.sa.elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2417 		{ &hf_dcom_sa_bound_elements,
2418 		{ "BoundElements", "dcom.sa.bound_elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2419 		{ &hf_dcom_sa_low_bound,
2420 		{ "LowBound", "dcom.sa.low_bound", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2421 
2422 		{ &hf_dcom_sa_features_auto,
2423 		{ "AUTO", "dcom.sa.features_auto", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_AUTO, NULL, HFILL }},
2424 		{ &hf_dcom_sa_features_static,
2425 		{ "STATIC", "dcom.sa.features_static", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_STATIC, NULL, HFILL }},
2426 		{ &hf_dcom_sa_features_embedded,
2427 		{ "EMBEDDED", "dcom.sa.features_embedded", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_EMBEDDED, NULL, HFILL }},
2428 		{ &hf_dcom_sa_features_fixedsize,
2429 		{ "FIXEDSIZE", "dcom.sa.features_fixedsize", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_FIXEDSIZE, NULL, HFILL }},
2430 		{ &hf_dcom_sa_features_record,
2431 		{ "RECORD", "dcom.sa.features_record", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_RECORD, NULL, HFILL }},
2432 		{ &hf_dcom_sa_features_have_iid,
2433 		{ "HAVEIID", "dcom.sa.features_have_iid", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEIID, NULL, HFILL }},
2434 		{ &hf_dcom_sa_features_have_vartype,
2435 		{ "HAVEVARTYPE", "dcom.sa.features_have_vartype", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEVARTYPE, NULL, HFILL }},
2436 		{ &hf_dcom_sa_features_bstr,
2437 		{ "BSTR", "dcom.sa.features_bstr", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_BSTR, NULL, HFILL }},
2438 		{ &hf_dcom_sa_features_unknown,
2439 		{ "UNKNOWN", "dcom.sa.features_unknown", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_UNKNOWN, NULL, HFILL }},
2440 		{ &hf_dcom_sa_features_dispatch,
2441 		{ "DISPATCH", "dcom.sa.features_dispatch", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_DISPATCH, NULL, HFILL }},
2442 		{ &hf_dcom_sa_features_variant,
2443 		{ "VARIANT", "dcom.sa.features_variant", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_VARIANT, NULL, HFILL }}
2444 	};
2445 
2446 	static gint *ett_dcom[] = {
2447 		&ett_dcom_this,
2448 		&ett_dcom_that,
2449 		&ett_dcom_extent,
2450 		&ett_dcom_lpwstr,
2451 		&ett_dcom_interface_pointer,
2452 		&ett_dcom_objref,
2453 		&ett_dcom_stdobjref,
2454 		&ett_dcom_custobjref,
2455 		&ett_dcom_dualstringarray,
2456 		&ett_dcom_dualstringarray_binding,
2457 		&ett_dcom_variant,
2458 		&ett_dcom_safearray,
2459 		&ett_dcom_sa_features,
2460 	};
2461 
2462 	static ei_register_info ei[] = {
2463 		{ &ei_dcom_dissection_incomplete, { "dcom.dissection_incomplete", PI_UNDECODED, PI_WARN, "Dissection incomplete", EXPFILL }},
2464 		{ &ei_dcom_no_spec, { "dcom.no_spec", PI_UNDECODED, PI_NOTE, "No specification available, dissection not possible", EXPFILL }},
2465 		{ &ei_dcom_hresult_expert, { "dcom.hresult.expert", PI_RESPONSE_CODE, PI_NOTE, "Hresult", EXPFILL }},
2466 		{ &ei_dcom_dualstringarray_mult_ip, { "dcom.dualstringarray.mult_ip", PI_UNDECODED, PI_NOTE, "DUALSTRINGARRAY Multiple IP", EXPFILL }},
2467 	};
2468 
2469 	module_t *dcom_module;
2470 	expert_module_t* expert_dcom;
2471 
2472 	/* currently, the DCOM protocol "itself" has no real protocol dissector */
2473 	/* we only need this, to register some generic elements */
2474 	proto_dcom = proto_register_protocol ("DCOM", "DCOM", "dcom");
2475 	proto_register_field_array(proto_dcom, hf_dcom_this_array, array_length(hf_dcom_this_array));
2476 	proto_register_field_array(proto_dcom, hf_dcom_that_array, array_length(hf_dcom_that_array));
2477 	proto_register_field_array(proto_dcom, hf_dcom_extent_array, array_length(hf_dcom_extent_array));
2478 	proto_register_field_array(proto_dcom, hf_dcom_array, array_length(hf_dcom_array));
2479 	proto_register_field_array(proto_dcom, hf_dcom_objref_array, array_length(hf_dcom_objref_array));
2480 	proto_register_field_array(proto_dcom, hf_dcom_stdobjref_array, array_length(hf_dcom_stdobjref_array));
2481 	proto_register_field_array(proto_dcom, hf_dcom_custobjref_array, array_length(hf_dcom_custobjref_array));
2482 	proto_register_field_array(proto_dcom, hf_dcom_dualstringarray_array, array_length(hf_dcom_dualstringarray_array));
2483 	proto_register_field_array(proto_dcom, hf_dcom_interface_pointer_array, array_length(hf_dcom_interface_pointer_array));
2484 	proto_register_field_array(proto_dcom, hf_dcom_vt_array, array_length(hf_dcom_vt_array));
2485 	proto_register_field_array(proto_dcom, hf_dcom_sa_array, array_length(hf_dcom_sa_array));
2486 	proto_register_subtree_array (ett_dcom, array_length (ett_dcom));
2487 
2488 	expert_dcom = expert_register_protocol(proto_dcom);
2489 	expert_register_field_array(expert_dcom, ei, array_length(ei));
2490 
2491 	/* preferences */
2492 	dcom_module = prefs_register_protocol(proto_dcom, NULL);
2493 
2494 	prefs_register_bool_preference(dcom_module, "display_unmarshalling_details",
2495 		"Display DCOM unmarshalling details",
2496 		"Display some DCOM unmarshalled fields "
2497 		"usually hidden",
2498 		&dcom_prefs_display_unmarshalling_details);
2499 
2500 	register_cleanup_routine(dcom_cleanup);
2501 }
2502 
2503 
2504 void
2505 proto_reg_handoff_dcom (void)
2506 {
2507 	/* register some "well known" UUID's */
2508 	guids_add_uuid(&uuid_debug_ext, "Debug Information Body Extension");
2509 	guids_add_uuid(&uuid_ext_error_ext, "Extended Error Info Body Extension");
2510 	guids_add_uuid(&ipid_rem_unknown, "IRemUnknown");
2511 	guids_add_uuid(&iid_unknown, "IUnknown");
2512 	guids_add_uuid(&uuid_null, "NULL");
2513 	guids_add_uuid(&iid_class_factory, "IClassFactory");
2514 	guids_add_uuid(&iid_type_info, "ITypeInfo");
2515 	guids_add_uuid(&iid_provide_class_info, "IProvideClassInfo");
2516 
2517 	/* Currently, we have nothing to register for DCOM */
2518 }
2519 
2520 /*
2521  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2522  *
2523  * Local variables:
2524  * c-basic-offset: 8
2525  * tab-width: 8
2526  * indent-tabs-mode: t
2527  * End:
2528  *
2529  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2530  * :indentSize=8:tabSize=8:noTabs=false:
2531  */
2532