2 * Routines for DCOM generics
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 /* A few words about DCOM:
27 * DCOM uses DCERPC as it's underlying "transport" protocol.
29 * The DCOM dissectors are called by DCERPC request and response calls.
30 * DCOM uses a small header after the DCERPC calls.
31 * (for a DCERPC request call it's called "this",
32 * for a DCERPC response call it's called "that")
34 * DCOM defines itself some interfaces: oxid, remact, remunk and others
36 * Implemented is currently "only" a static dissection of packet fields
37 * (no "object recognition" included)
39 * User's of DCOM can define their own interface's using Microsoft IDL.
41 * Hint: The registered DCOM interface names can be found in the
42 * windows registry at: "HKEY_CLASSES_ROOT\Interface"
45 * Ressources on the web:
47 * "Understanding the DCOM Wire Protocol by Analyzing Network Data Packets"
48 * http:// www.microsoft.com/msj/0398/dcom.htm
50 * "Distributed Component Object Model Protocol -- DCOM/1.0"
51 * http://www.microsoft.com/com/resources/specs.asp (link is currently down)
55 /* Files involved dissecting DCOM:
57 * packet-dcom.c: generic DCOM things (this, that, ...) and
58 * generic DCOM datatype (DWORD, VARIANT, ...)
60 * DCOM common Interfaces:
61 * packet-dcom-oxid.c: IOXIDResolver
62 * packet-dcom-remact.c: IRemoteActivation
63 * packet-dcom-remunk.c: IRemUnknown, IRemUnknown2
64 * packet-dcom-dispatch.c: IDispatch
65 * packet-dcom-sysact.c: ISystemActivator
73 * XXX - are the next two includes necessary?
75 #ifdef HAVE_SYS_TYPES_H
76 # include <sys/types.h>
79 #ifdef HAVE_NETINET_IN_H
80 #include <netinet/in.h>
83 #ifdef HAVE_WINSOCK2_H
90 #include <epan/packet.h>
91 #include <epan/emem.h>
92 #include <epan/addr_resolv.h>
93 #include <wsutil/inet_aton.h>
94 #include <epan/expert.h>
95 #include <epan/prefs.h>
98 #include "packet-dcerpc.h"
99 #include "packet-dcom.h"
101 static int proto_dcom = -1;
103 gboolean dcom_prefs_display_unmarshalling_details = FALSE;
106 static gint ett_dcom_this = -1;
107 static int hf_dcom_this_version_major = -1;
108 static int hf_dcom_this_version_minor = -1;
109 static int hf_dcom_this_flags = -1;
110 static int hf_dcom_this_res = -1;
111 static int hf_dcom_this_cid = -1;
113 static gint ett_dcom_that = -1;
114 static int hf_dcom_that_flags = -1;
116 static gint ett_dcom_extent = -1;
117 static int hf_dcom_extent = -1;
118 static int hf_dcom_extent_array_count = -1;
119 static int hf_dcom_extent_array_res = -1;
120 static int hf_dcom_extent_size = -1;
121 static int hf_dcom_extent_id = -1;
123 static int hf_dcom_hresult = -1;
124 static int hf_dcom_tobedone = -1;
125 static int hf_dcom_nospec = -1;
126 static int hf_dcom_array_size = -1;
127 static int hf_dcom_pointer_val = -1;
130 static int hf_dcom_version_major = -1;
131 static int hf_dcom_version_minor = -1;
133 static gint ett_dcom_lpwstr = -1;
134 static int hf_dcom_max_count = -1;
135 static int hf_dcom_offset = -1;
136 static int hf_dcom_byte_length = -1;
137 static int hf_dcom_actual_count = -1;
139 static gint ett_dcom_objref = -1;
140 static int hf_dcom_objref = -1;
141 static int hf_dcom_objref_signature = -1;
142 static int hf_dcom_objref_flags = -1;
143 int hf_dcom_iid = -1;
144 int hf_dcom_clsid = -1;
145 static int hf_dcom_objref_resolver_address = -1;
146 static int hf_dcom_objref_cbextension = -1;
147 static int hf_dcom_objref_size = -1;
149 static gint ett_dcom_stdobjref = -1;
150 static int hf_dcom_stdobjref = -1;
151 static int hf_dcom_stdobjref_flags = -1;
152 static int hf_dcom_stdobjref_public_refs = -1;
153 int hf_dcom_oxid = -1;
154 int hf_dcom_oid = -1;
155 int hf_dcom_ipid = -1;
157 static gint ett_dcom_dualstringarray = -1;
158 static gint ett_dcom_dualstringarray_binding = -1;
159 static int hf_dcom_dualstringarray_num_entries = -1;
160 static int hf_dcom_dualstringarray_security_offset = -1;
161 static int hf_dcom_dualstringarray_string = -1;
162 static int hf_dcom_dualstringarray_string_network_addr = -1;
163 static int hf_dcom_dualstringarray_string_tower_id = -1;
164 static int hf_dcom_dualstringarray_security = -1;
165 static int hf_dcom_dualstringarray_security_authn_svc = -1;
166 static int hf_dcom_dualstringarray_security_authz_svc = -1;
167 static int hf_dcom_dualstringarray_security_princ_name = -1;
169 static gint ett_dcom_interface_pointer = -1;
170 static int hf_dcom_interface_pointer = -1;
171 static int hf_dcom_ip_cnt_data = -1;
173 static gint ett_dcom_safearray = -1;
174 static int hf_dcom_safearray = -1;
175 static int hf_dcom_sa_dims32 = -1;
176 static int hf_dcom_sa_dims16 = -1;
177 static int hf_dcom_sa_features = -1;
178 static int hf_dcom_sa_element_size = -1;
179 static int hf_dcom_sa_locks = -1;
180 static int hf_dcom_sa_vartype32 = -1;
181 static int hf_dcom_sa_vartype16 = -1;
182 static int hf_dcom_sa_elements = -1;
183 static int hf_dcom_sa_bound_elements = -1;
184 static int hf_dcom_sa_low_bound = -1;
186 static gint ett_dcom_sa_features = -1;
187 static int hf_dcom_sa_features_auto = -1;
188 static int hf_dcom_sa_features_static = -1;
189 static int hf_dcom_sa_features_embedded = -1;
190 static int hf_dcom_sa_features_fixedsize = -1;
191 static int hf_dcom_sa_features_record = -1;
192 static int hf_dcom_sa_features_have_iid = -1;
193 static int hf_dcom_sa_features_have_vartype = -1;
194 static int hf_dcom_sa_features_bstr = -1;
195 static int hf_dcom_sa_features_unknown = -1;
196 static int hf_dcom_sa_features_dispatch = -1;
197 static int hf_dcom_sa_features_variant = -1;
199 static gint ett_dcom_variant = -1;
200 static int hf_dcom_variant = -1;
201 static int hf_dcom_variant_type = -1;
202 static int hf_dcom_variant_size = -1;
203 static int hf_dcom_variant_rpc_res = -1;
204 static int hf_dcom_variant_wres = -1;
205 static int hf_dcom_variant_type32 = -1;
207 static int hf_dcom_vt_bool = -1;
208 static int hf_dcom_vt_i1 = -1;
209 static int hf_dcom_vt_i2 = -1;
210 static int hf_dcom_vt_i4 = -1;
211 static int hf_dcom_vt_i8 = -1; /* only inside a SAFEARRAY, not in VARIANTs */
212 static int hf_dcom_vt_ui1 = -1;
213 static int hf_dcom_vt_ui2 = -1;
214 static int hf_dcom_vt_ui4 = -1;
215 static int hf_dcom_vt_r4 = -1;
216 static int hf_dcom_vt_r8 = -1;
217 static int hf_dcom_vt_date = -1;
218 static int hf_dcom_vt_bstr = -1;
219 static int hf_dcom_vt_byref = -1;
220 static int hf_dcom_vt_dispatch = -1;
222 /* this/that extension UUIDs */
223 static e_uuid_t uuid_debug_ext = { 0xf1f19680, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} };
224 static e_uuid_t uuid_ext_error_ext ={ 0xf1f19681, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} };
226 /* general DCOM UUIDs */
227 static const e_uuid_t ipid_rem_unknown = { 0x00000131, 0x1234, 0x5678, { 0xCA, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
228 static const e_uuid_t iid_unknown = { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
229 static const e_uuid_t uuid_null = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
230 static const e_uuid_t iid_class_factory = { 0x00000001, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
232 static GList *dcom_machines = NULL;
233 static GList *dcom_interfaces = NULL;
235 static const value_string dcom_thisthat_flag_vals[] = {
243 void dcom_interface_dump(void) {
244 dcom_machine_t *machine;
245 dcom_object_t *object;
246 dcom_interface_t *interf;
252 for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
253 machine = machines->data;
254 g_warning("Machine(#%4u): IP:%s", machine->first_packet, ip_to_str(machine->ip));
256 for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
257 object = objects->data;
258 g_warning(" Object(#%4u): OID:0x%" G_GINT64_MODIFIER "x private:%p", object->first_packet, object->oid, object->private_data);
260 for(interfaces = object->interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
261 interf = interfaces->data;
262 g_warning(" Interface(#%4u): iid:%s",
263 interf->first_packet, guids_resolve_uuid_to_str(&interf->iid));
264 g_warning(" ipid:%s", guids_resolve_uuid_to_str(&interf->ipid));
271 dcom_interface_t *dcom_interface_find(packet_info *pinfo _U_, const guint8 *ip _U_, e_uuid_t *ipid)
273 dcom_interface_t *interf;
277 if(memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
282 for(interfaces = dcom_interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
283 interf = interfaces->data;
285 if(memcmp(&interf->ipid, ipid, sizeof(e_uuid_t)) == 0) {
294 dcom_interface_t *dcom_interface_new(packet_info *pinfo, const guint8 *ip, e_uuid_t *iid, guint64 oxid, guint64 oid, e_uuid_t *ipid)
297 dcom_machine_t *machine;
298 dcom_object_t *object;
299 dcom_interface_t *interf;
302 if( memcmp(iid, &uuid_null, sizeof(uuid_null)) == 0 ||
303 memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
308 if(oxid == 0 || oid == 0) {
309 /*g_warning("interface_new#%u", pinfo->fd->num);*/
311 interf = se_alloc(sizeof(dcom_interface_t));
312 interf->parent = NULL;
313 interf->private_data = NULL;
314 interf->first_packet = pinfo->fd->num;
316 interf->ipid = *ipid;
318 dcom_interfaces = g_list_append(dcom_interfaces, interf);
323 dcom_iter = dcom_machines;
324 while(dcom_iter != NULL) {
325 machine = dcom_iter->data;
326 if(memcmp(machine->ip, ip, 4) == 0) {
329 dcom_iter = g_list_next(dcom_iter);
332 /* create new machine if not found */
333 if(dcom_iter == NULL) {
334 machine = g_malloc(sizeof(dcom_machine_t));
335 memcpy(machine->ip, ip, 4);
336 machine->objects = NULL;
337 machine->first_packet = pinfo->fd->num;
338 dcom_machines = g_list_append(dcom_machines, machine);
342 dcom_iter = machine->objects;
343 while(dcom_iter != NULL) {
344 object = dcom_iter->data;
345 if(object->oid == oid) {
348 dcom_iter = g_list_next(dcom_iter);
351 /* create new object if not found */
352 if(dcom_iter == NULL) {
353 object = g_malloc(sizeof(dcom_object_t));
354 object->parent = machine;
355 object->interfaces = NULL;
356 object->private_data = NULL;
357 object->first_packet = pinfo->fd->num;
361 machine->objects = g_list_append(machine->objects, object);
365 dcom_iter = object->interfaces;
366 while(dcom_iter != NULL) {
367 interf = dcom_iter->data;
368 if(memcmp(&interf->ipid, ipid, sizeof(e_uuid_t)) == 0) {
371 dcom_iter = g_list_next(dcom_iter);
374 /* create new interface if not found */
375 if(dcom_iter == NULL) {
376 interf = g_malloc(sizeof(dcom_interface_t));
377 interf->parent = object;
378 interf->private_data = NULL;
379 interf->first_packet = pinfo->fd->num;
381 interf->ipid = *ipid;
383 object->interfaces = g_list_append(object->interfaces, interf);
384 dcom_interfaces = g_list_append(dcom_interfaces, interf);
392 * Flag bits in connection-oriented PDU header.
394 #define WIRESHARK_FADF_AUTO 0x0001
395 #define WIRESHARK_FADF_STATIC 0x0002
396 #define WIRESHARK_FADF_EMBEDDED 0x0004
397 #define WIRESHARK_FADF_FIXEDSIZE 0x0010
398 #define WIRESHARK_FADF_RECORD 0x0020
399 #define WIRESHARK_FADF_HAVEIID 0x0040
400 #define WIRESHARK_FADF_HAVEVARTYPE 0x0080
401 #define WIRESHARK_FADF_BSTR 0x0100
402 #define WIRESHARK_FADF_UNKNOWN 0x0200
403 #define WIRESHARK_FADF_DISPATCH 0x0400
404 #define WIRESHARK_FADF_VARIANT 0x0800
408 WIRESHARK_VT_EMPTY = 0,
409 WIRESHARK_VT_NULL = 1,
415 WIRESHARK_VT_DATE = 7,
416 WIRESHARK_VT_BSTR = 8,
417 WIRESHARK_VT_DISPATCH = 9,
418 WIRESHARK_VT_ERROR = 10,
419 WIRESHARK_VT_BOOL = 11,
420 WIRESHARK_VT_VARIANT = 12,
421 WIRESHARK_VT_UNKNOWN = 13,
422 WIRESHARK_VT_DECIMAL = 14,
423 WIRESHARK_VT_I1 = 16,
424 WIRESHARK_VT_UI1 = 17,
425 WIRESHARK_VT_UI2 = 18,
426 WIRESHARK_VT_UI4 = 19,
427 WIRESHARK_VT_I8 = 20,
428 WIRESHARK_VT_UI8 = 21,
429 WIRESHARK_VT_INT = 22,
430 WIRESHARK_VT_UINT = 23,
431 WIRESHARK_VT_VOID = 24,
432 WIRESHARK_VT_HRESULT = 25,
433 WIRESHARK_VT_PTR = 26,
434 WIRESHARK_VT_SAFEARRAY = 27,
435 WIRESHARK_VT_CARRAY = 28,
436 WIRESHARK_VT_USERDEFINED = 29,
437 WIRESHARK_VT_LPSTR = 30,
438 WIRESHARK_VT_LPWSTR = 31,
439 WIRESHARK_VT_RECORD = 36,
440 WIRESHARK_VT_FILETIME = 64,
441 WIRESHARK_VT_BLOB = 65,
442 WIRESHARK_VT_STREAM = 66,
443 WIRESHARK_VT_STORAGE = 67,
444 WIRESHARK_VT_STREAMED_OBJECT = 68,
445 WIRESHARK_VT_STORED_OBJECT = 69,
446 WIRESHARK_VT_BLOB_OBJECT = 70,
447 WIRESHARK_VT_CF = 71,
448 WIRESHARK_VT_CLSID = 72,
450 WIRESHARK_VT_BSTR_BLOB = 0x0fff,
452 WIRESHARK_VT_VECTOR = 0x1000,
453 WIRESHARK_VT_ARRAY = 0x2000,
454 WIRESHARK_VT_BYREF = 0x4000,
455 WIRESHARK_VT_RESERVED = 0x8000,
457 WIRESHARK_VT_ILLEGAL = 0xffff,
458 WIRESHARK_VT_ILLEGALMASKED = 0x0fff,
459 WIRESHARK_VT_TYPEMASK = 0x0fff
462 const value_string dcom_variant_type_vals[] = {
463 { WIRESHARK_VT_EMPTY, "VT_EMPTY"},
464 { WIRESHARK_VT_NULL, "VT_NULL"},
465 { WIRESHARK_VT_I2, "VT_I2"},
466 { WIRESHARK_VT_I4, "VT_I4"},
467 { WIRESHARK_VT_R4, "VT_R4"},
468 { WIRESHARK_VT_R8, "VT_R8"},
469 { WIRESHARK_VT_CY, "VT_CY"},
470 { WIRESHARK_VT_DATE, "VT_DATE"},
471 { WIRESHARK_VT_BSTR, "VT_BSTR"},
472 { WIRESHARK_VT_DISPATCH, "VT_DISPATCH"},
473 { WIRESHARK_VT_ERROR, "VT_ERROR"},
474 { WIRESHARK_VT_BOOL, "VT_BOOL"},
475 { WIRESHARK_VT_I1, "VT_I1"},
476 { WIRESHARK_VT_UI1, "VT_UI1"},
477 { WIRESHARK_VT_UI2, "VT_UI2"},
478 { WIRESHARK_VT_UI4, "VT_UI4"},
479 { WIRESHARK_VT_I8, "VT_I8"},
480 { WIRESHARK_VT_UI8, "VT_UI8"},
481 { WIRESHARK_VT_ARRAY, "VT_ARRAY"},
482 { WIRESHARK_VT_UNKNOWN, "VT_UNKNOWN"},
483 { WIRESHARK_VT_USERDEFINED, "VT_USERDEFINED"},
485 /* XXX: this could be done better */
486 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I2, "VT_ARRAY|VT_I2"},
487 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I4, "VT_ARRAY|VT_I4"},
488 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_R4, "VT_ARRAY|VT_R4"},
489 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_R8, "VT_ARRAY|VT_R8"},
490 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_DATE, "VT_ARRAY|VT_DATE"},
491 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_BSTR, "VT_ARRAY|VT_BSTR"},
492 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_ERROR, "VT_ARRAY|VT_ERROR"},
493 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_BOOL, "VT_ARRAY|VT_BOOL"},
494 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I1, "VT_ARRAY|VT_I1"},
495 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI1, "VT_ARRAY|VT_UI1"},
496 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI2, "VT_ARRAY|VT_UI2"},
497 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI4, "VT_ARRAY|VT_UI4"},
498 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I8, "VT_ARRAY|VT_I8"},
499 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI8, "VT_ARRAY|VT_UI8"},
501 { WIRESHARK_VT_BYREF | WIRESHARK_VT_I2, "VT_BYREF|VT_I2"},
502 { WIRESHARK_VT_BYREF | WIRESHARK_VT_BSTR, "VT_BYREF|VT_BSTR"},
503 { WIRESHARK_VT_BYREF | WIRESHARK_VT_VARIANT, "VT_BYREF|VT_VARIANT"},
505 /* XXX: append more types here */
510 /* we need an extension mechanism here (be able to append entries by user protocol) */
511 const value_string dcom_hresult_vals[] = {
512 { 0x00000000, "S_OK" },
513 { 0x00000001, "S_FALSE" },
514 { 0x8000FFFF, "E_UNEXPECTED" },
515 { 0x80004001, "E_NOTIMPL" },
516 { 0x80004002, "E_NOINTERFACE" },
517 { 0x80004003, "E_POINTER" },
518 { 0x80004004, "E_ABORT" },
519 { 0x80004005, "E_FAIL" },
520 { 0x80070005, "E_ACCESSDENIED" },
521 { 0x80070006, "E_HANDLE" },
522 { 0x8007000E, "E_OUTOFMEMORY" },
523 { 0x80070057, "E_INVALIDARG" },
525 { 0x80010108, "RPC_E_DISCONNECTED" },
526 { 0x80010113, "RPC_E_INVALID_IPID" },
527 { 0x8001011F, "RPC_E_TIMEOUT" },
529 { 0x80020003, "DISP_E_MEMBERNOTFOUND" },
530 { 0x80020004, "DISP_E_PARAMNOTFOUND" },
531 { 0x80020005, "DISP_E_TYPEMISMATCH" },
532 { 0x80020006, "DISP_E_UNKNOWNNAME" },
533 { 0x80020008, "DISP_E_BADVARTYPE" },
534 { 0x80020009, "DISP_E_EXCEPTION" },
535 { 0x8002000A, "DISP_E_OVERFLOW" },
537 { 0x8002801D, "TYPE_E_LIBNOTREGISTERED" },
539 { 0x80040154, "REGDB_E_CLASSNOTREG" },
540 { 0x80040201, "CO_E_FAILEDTOGETSECCTX" },
542 /* following are CBA application specific values */
543 { 0x0004CA00, "CBA_S_PERSISTPENDING" },
544 { 0x0004CA01, "CBA_S_ESTABLISHING" },
545 { 0x0004CA02, "CBA_S_NOCONNECTION" },
546 { 0x0004CA03, "CBA_S_VALUEBUFFERED" },
547 { 0x0004CA04, "CBA_S_VALUEUNCERTAIN" },
548 { 0x0004CA05, "CBA_S_NOCONNECTIONDATA" },
549 { 0x0004CA06, "CBA_S_FRAMEEMPTY" },
551 { 0x8004CB00, "CBA_E_MALFORMED" },
552 { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
553 { 0x8004CB02, "CBA_E_UNKNOWNMEMBER" },
554 { 0x8004CB03, "CBA_E_TYPEMISMATCH" },
555 { 0x8004CB04, "CBA_E_INVALIDENUMVALUE" },
556 { 0x8004CB05, "CBA_E_INVALIDID" },
557 { 0x8004CB06, "CBA_E_INVALIDEPSILON" },
558 { 0x8004CB07, "CBA_E_INVALIDSUBSTITUTE" },
559 { 0x8004CB08, "CBA_E_INVALIDCONNECTION" },
560 { 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
561 { 0x8004CB0A, "CBA_E_TIMEVALUEUNSUPPORTED" },
562 { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
563 { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
564 { 0x8004CB0D, "CBA_E_PERSISTRUNNING" },
565 { 0x8004CB0E, "CBA_E_INUSE" },
566 { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
567 { 0x8004CB10, "CBA_E_NONACCESSIBLE" },
568 { 0x8004CB11, "CBA_E_DEFECT" },
569 { 0x8004CB12, "CBA_E_LIMITVIOLATION" },
570 { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
571 { 0x8004CB14, "CBA_E_QCNOTAPPLICABLE" },
572 { 0x8004CB15, "CBA_E_ACCESSBLOCKED" },
573 { 0x8004CB16, "CBA_E_COUNTEXCEEDED" },
574 { 0x8004CB17, "CBA_E_SIZEEXCEEDED" },
575 { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
576 { 0x8004CB19, "CBA_E_OUTOFACCOPAIRS" },
577 { 0x8004CB1A, "CBA_E_ITEMTOOLARGE" },
578 { 0x8004CB1B, "CBA_E_CRDATALENGTH" },
579 { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
580 { 0x8004CB1D, "CBA_E_CAPACITYEXCEEDED" },
581 { 0x8004CB1E, "CBA_E_SUBELEMENTMISMATCH" },
582 { 0x8004CB1F, "CBA_E_STATIONFAILURE" },
583 { 0x8004CB20, "CBA_E_NOTROUTABLE" },
584 { 0x8004CB21, "CBA_E_DISCONNECTRUNNING" },
585 { 0x8004CB22, "CBA_E_LOCATIONCHANGED" },
586 { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
587 { 0x8004CB24, "CBA_E_LINKFAILURE" },
588 { 0x8004CB25, "CBA_E_MODECHANGE" },
590 { 0x80080004, "CO_E_BAD_PATH" },
595 static const value_string dcom_objref_flag_vals[] = {
596 { 0x1, "OBJREF_STANDARD" },
597 { 0x2, "OBJREF_HANDLER" },
598 { 0x4, "OBJREF_CUSTOM" },
602 static const value_string dcom_objref_signature_vals[] = {
603 { 0x574f454d, "MEOW" },
607 /* although flags, they doesn't seem to be used as such */
608 static const value_string dcom_stdobjref_flag_vals[] = {
609 { 0x0000, "SORF_NULL" },
610 { 0x0001, "SORF_OXRES1" },
611 { 0x0020, "SORF_OXRES2" },
612 { 0x0040, "SORF_OXRES3" },
613 { 0x0080, "SORF_OXRES4" },
614 { 0x0100, "SORF_OXRES5" },
615 { 0x0200, "SORF_OXRES6" },
616 { 0x0400, "SORF_OXRES7" },
617 { 0x0800, "SORF_OXRES8" },
618 { 0x1000, "SORF_NOPING" },
622 static const value_string dcom_dcerpc_pointer_vals[] = {
623 { 0x72657355, "User" },
624 { 0x42535452, "BSTR" },
625 { 0x00000000, "NULL" },
629 static const value_string dcom_dualstringarray_authz[] = {
630 { 0x0000, "RPC_C_AUTHZ_NONE" },
631 { 0x0001, "RPC_C_AUTHZ_NAME"},
632 { 0x0002, "RPC_C_AUTHZ_DCE"},
633 { 0xffff, "Default"},
637 static const value_string dcom_dualstringarray_authn[] = {
638 { 00, "RPC_C_AUTHN_NONE" },
639 { 1, "RPC_C_AUTHN_DCE_PRIVATE"},
640 { 2, "RPC_C_AUTHN_DCE_PUBLIC"},
641 { 4, "RPC_C_AUTHN_DEC_PUBLIC"},
642 { 9, "RPC_C_AUTHN_GSS_NEGOTIATE"},
643 { 10, "RPC_C_AUTH_WINNT"},
644 { 14, "RPC_C_AUTHN_GSS_SCHANNEL"},
645 { 16, "RPC_C_AUTHN_GSS_KERBEROS"},
646 { 17, "RPC_C_AUTHN_MSN"},
647 { 18, "RPC_C_AUTHN_DPA"},
648 { 100, "RPC_C_AUTHN_MQ"},
649 { 0xffff, "RPC_C_AUTHN_DEFAULT"},
653 const value_string dcom_protseq_vals[] = {
654 { 0x04, "NCACN_DNET_NSP" },
655 { 0x07, "NCACN_IP_TCP" },
656 { 0x08, "NCADG_IP_UDP" },
657 { 0x09, "NCACN_IP" },
658 { 0x0C, "NCACN_SPX" },
659 { 0x0D, "NCACN_NB_IPX" },
660 { 0x0E, "NCADG_IPX" },
661 { 0x12, "NCACN_NB_NB" },
662 { 0x1F, "NCACN_HTTP" },
666 static const value_string dcom_vt_bool_vals[] = {
674 /* dissect extension to DCOM "this" and "that" */
676 dissect_dcom_extent(tvbuff_t *tvb, int offset,
677 packet_info *pinfo, proto_tree *tree, guint8 *drep)
679 guint32 u32ArraySize;
680 guint32 u32ArraySize2;
682 guint32 u32VariableOffset;
685 proto_item *sub_item;
686 proto_tree *sub_tree;
688 guint32 u32ArrayCount;
691 guint32 u32ExtentSize;
693 const char *uuid_name;
696 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer);
698 if (u32Pointer == 0) {
702 offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep,
703 hf_dcom_extent_array_count, &u32ArrayCount);
704 offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep,
705 hf_dcom_extent_array_res, &u32ArrayRes);
707 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer);
709 if (u32Pointer == 0) {
713 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep,
716 u32VariableOffset = offset + u32ArraySize*4;
719 while (u32ArraySize--) {
720 sub_item = proto_tree_add_item(tree, hf_dcom_extent, tvb, offset, 0, ENC_NA);
721 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_extent);
722 u32SubStart = offset;
724 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
726 if(u32Pointer != 0) {
727 u32VariableOffset = dissect_dcom_DWORD(tvb, u32VariableOffset, pinfo, sub_tree, drep,
728 hf_dcom_extent_size, &u32ExtentSize);
730 dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, NULL, drep,
731 hf_dcom_extent_id, &uuidExtend);
733 /* look for a registered uuid name */
734 if((uuid_name = guids_get_uuid_name(&uuidExtend)) != NULL) {
735 proto_tree_add_guid_format_value(sub_tree, hf_dcom_extent_id, tvb,
736 offset, sizeof(e_uuid_t), (e_guid_t *) &uuidExtend,
737 "%s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
739 uuidExtend.Data1, uuidExtend.Data2, uuidExtend.Data3,
740 uuidExtend.Data4[0], uuidExtend.Data4[1],
741 uuidExtend.Data4[2], uuidExtend.Data4[3],
742 uuidExtend.Data4[4], uuidExtend.Data4[5],
743 uuidExtend.Data4[6], uuidExtend.Data4[7]);
744 u32VariableOffset += 16;
746 u32VariableOffset = dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, sub_tree, drep,
747 hf_dcom_extent_id, &uuidExtend);
751 u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, drep,
753 u32VariableOffset = dissect_dcom_nospec_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, u32ArraySize2);
755 /* update subtree header */
756 if(uuid_name != NULL) {
757 proto_item_append_text(sub_item, "[%u]: %s, Bytes=%u",
758 u32Idx, uuid_name, u32ArraySize2);
760 proto_item_append_text(sub_item, "[%u]: Bytes=%u",
761 u32Idx, u32ArraySize2);
763 proto_item_set_len(sub_item, offset - u32SubStart);
765 /* update subtree header */
766 proto_item_append_text(sub_item, "[%u]: NULL", u32Idx);
767 proto_item_set_len(sub_item, offset - u32SubStart);
773 return u32VariableOffset;
777 /* dissect DCOM "this" (start of every DCOM request) */
779 dissect_dcom_this(tvbuff_t *tvb, int offset,
780 packet_info *pinfo, proto_tree *tree, guint8 *drep)
782 guint16 u16VersionMajor;
783 guint16 u16VersionMinor;
786 e_uuid_t uuidCausality;
787 proto_item *sub_item;
788 proto_tree *sub_tree;
791 dcerpc_info *info = (dcerpc_info *)pinfo->private_data;
794 sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
796 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_this);
798 offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, sub_tree, drep,
799 &u16VersionMajor, &u16VersionMinor);
800 u32SubStart = offset - 4;
802 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
803 hf_dcom_this_flags, &u32Flags);
804 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
805 hf_dcom_this_res, &u32Res);
807 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep,
808 hf_dcom_this_cid, &uuidCausality);
810 offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, drep);
812 /* update subtree header */
813 proto_item_append_text(sub_item, ", V%u.%u, Causality ID: %s",
814 u16VersionMajor, u16VersionMinor, guids_resolve_uuid_to_str(&uuidCausality));
815 proto_item_set_len(sub_item, offset - u32SubStart);
817 if(memcmp(&info->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
818 pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
819 (e_guid_t *) &info->call_data->object_uuid,
820 "Object UUID/IPID: %s", guids_resolve_uuid_to_str(&info->call_data->object_uuid));
821 PROTO_ITEM_SET_GENERATED(pi);
828 /* dissect DCOM "that" (start of every DCOM response) */
830 dissect_dcom_that(tvbuff_t *tvb, int offset,
831 packet_info *pinfo, proto_tree *tree, guint8 *drep) {
833 proto_item *sub_item;
834 proto_tree *sub_tree;
837 dcerpc_info *info = (dcerpc_info *)pinfo->private_data;
840 sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
842 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_that);
844 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
845 hf_dcom_that_flags, &u32Flags);
846 u32SubStart = offset - 4;
848 offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, drep);
850 /* update subtree header */
851 proto_item_set_len(sub_item, offset - u32SubStart);
853 if(memcmp(&info->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
854 pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
855 (e_guid_t *) &info->call_data->object_uuid,
856 "Object UUID/IPID: %s", guids_resolve_uuid_to_str(&info->call_data->object_uuid));
857 PROTO_ITEM_SET_GENERATED(pi);
864 /* dissect simple dcom request, DCOM "this" only */
866 dissect_dcom_simple_rqst(tvbuff_t *tvb, int offset,
867 packet_info *pinfo, proto_tree *tree, guint8 *drep)
870 offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep);
876 /* dissect simple dcom response, DCOM "that" and returned HRESULT only */
878 dissect_dcom_simple_resp(tvbuff_t *tvb, int offset,
879 packet_info *pinfo, proto_tree *tree, guint8 *drep)
884 offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep);
886 offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep,
889 col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
890 val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
897 /* dissect a dcerpc array size */
899 dissect_dcom_dcerpc_array_size(tvbuff_t *tvb, gint offset, packet_info *pinfo,
900 proto_tree *tree, guint8 *drep, guint32 *pu32ArraySize)
904 /* en-/disable this by preference setting */
905 if (!dcom_prefs_display_unmarshalling_details) {
906 /* this will read in the data, but prevent output to tree */
910 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
911 hf_dcom_array_size, pu32ArraySize);
917 /* dissect a dcerpc pointer value */
919 dissect_dcom_dcerpc_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
920 proto_tree *tree, guint8 *drep, guint32 *pu32Pointer)
923 /* en-/disable this by preference setting */
924 if (!dcom_prefs_display_unmarshalling_details) {
925 /* this will read in the data, but prevent output to tree */
929 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
930 hf_dcom_pointer_val, pu32Pointer);
936 /* mark data as "ToBeDone" */
937 /* XXX: handout data to generic "unknown data" dissector? */
939 dissect_dcom_tobedone_data(tvbuff_t *tvb, int offset,
940 packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int length)
945 item = proto_tree_add_item(tree, hf_dcom_tobedone, tvb, offset, length, ENC_NA);
946 PROTO_ITEM_SET_GENERATED(item);
947 expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN, "Dissection incomplete");
955 /* mark data as "No Specification Available" */
956 /* XXX: handout data to generic "unknown data" dissector? */
958 dissect_dcom_nospec_data(tvbuff_t *tvb, int offset,
959 packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int length)
964 item = proto_tree_add_item(tree, hf_dcom_nospec, tvb, offset, length, ENC_NA);
965 PROTO_ITEM_SET_GENERATED(item);
966 expert_add_info_format(pinfo, item, PI_UNDECODED, PI_NOTE, "No specification available, dissection not possible");
974 /* dissect an indexed WORD, something like: "FieldName[1]: 0x1234" */
976 dissect_dcom_indexed_WORD(tvbuff_t *tvb, int offset, packet_info *pinfo,
977 proto_tree *tree, guint8 *drep,
978 int hfindex, guint16 * pu16WORD, int field_index)
983 /* dissect the WORD, but don't add to tree */
984 dissect_dcom_WORD(tvb, offset, pinfo, NULL /*tree*/, drep,
988 /* special formatted output of indexed value */
989 proto_tree_add_uint_format(tree, hfindex, tvb, offset, 2, u16WORD,
991 proto_registrar_get_name(hfindex),
992 field_index, u16WORD);
1004 /* dissect an indexed DWORD, something like: "FieldName[1]: 0x12345678" */
1006 dissect_dcom_indexed_DWORD(tvbuff_t *tvb, int offset, packet_info *pinfo,
1007 proto_tree *tree, guint8 *drep,
1008 int hfindex, guint32 * pu32DWORD, int field_index)
1013 /* dissect the DWORD, but don't add to tree */
1014 dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, drep,
1015 hfindex, &u32DWORD);
1018 /* special formatted output of indexed value */
1019 proto_tree_add_uint_format(tree, hfindex, tvb, offset, 4, u32DWORD,
1021 proto_registrar_get_name(hfindex),
1022 field_index, u32DWORD);
1028 *pu32DWORD = u32DWORD;
1034 /* dissect hresult field of a usual DCOM call (create "raw" item) */
1036 dissect_dcom_HRESULT_item(tvbuff_t *tvb, int offset, packet_info *pinfo,
1037 proto_tree *tree, guint8 *drep,
1038 guint32 * pu32HResult, int field_index, proto_item **item)
1042 /* dissect the DWORD, but don't add to tree */
1043 offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, drep,
1044 field_index, &u32HResult);
1047 /* special formatted output of indexed value */
1048 *item = proto_tree_add_item (tree, field_index, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
1052 *pu32HResult = u32HResult;
1058 /* dissect hresult field of a usual DCOM call (seperate method, because often used) */
1060 dissect_dcom_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1061 proto_tree *tree, guint8 *drep,
1062 guint32 * pu32HResult)
1065 proto_item *item = NULL;
1067 /* dissect the DWORD, but don't add to tree */
1068 offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, drep,
1069 hf_dcom_hresult, &u32HResult);
1072 /* special formatted output of indexed value */
1073 item = proto_tree_add_item (tree, hf_dcom_hresult, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
1076 /* expert info only if severity is set */
1077 /* XXX - move this to the callers of this function, to provide a more detailed error output */
1078 if(u32HResult & 0x80000000) {
1079 expert_add_info_format(pinfo, item, PI_RESPONSE_CODE, PI_NOTE, "Hresult: %s",
1080 val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
1083 *pu32HResult = u32HResult;
1089 /* partial results of indexed DCOM subcalls (e.g.: from a kind of array) */
1091 dissect_dcom_indexed_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1092 proto_tree *tree, guint8 *drep,
1093 guint32 * pu32HResult, int field_index)
1096 proto_item *item = NULL;
1099 /* dissect the DWORD, but don't add to tree */
1100 offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, drep,
1101 hf_dcom_hresult, &u32HResult);
1104 /* special formatted output of indexed value */
1105 item = proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset-4, 4, u32HResult,
1106 "HResult[%u]: %s (0x%08x)", field_index,
1107 val_to_str(u32HResult, dcom_hresult_vals, "Unknown"),
1110 /* expert info only if severity flag is set */
1111 /* XXX - move this to the callers of this function, to provide a more detailed error output */
1112 if(u32HResult & 0x80000000) {
1113 expert_add_info_format(pinfo, item, PI_RESPONSE_CODE, PI_NOTE, "Hresult: %s",
1114 val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
1117 *pu32HResult = u32HResult;
1125 dissect_dcom_COMVERSION(tvbuff_t *tvb, int offset, packet_info *pinfo,
1126 proto_tree *tree, guint8 *drep,
1127 guint16 * pu16VersionMajor, guint16 * pu16VersionMinor)
1130 offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep,
1131 hf_dcom_version_major, pu16VersionMajor);
1132 offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep,
1133 hf_dcom_version_minor, pu16VersionMinor);
1140 dissect_dcom_SAFEARRAY(tvbuff_t *tvb, int offset, packet_info *pinfo,
1141 proto_tree *tree, guint8 *drep, int hfindex _U_, sa_callback_t sacb)
1145 guint16 u16Features;
1146 guint32 u32ElementSize;
1148 guint32 u32Elements;
1150 guint32 u32BoundElements;
1151 guint32 u32LowBound;
1153 guint32 u32ArraySize;
1154 guint32 u32VariableOffset;
1160 proto_item *sub_item;
1161 proto_tree *sub_tree;
1162 guint32 u32SubStart;
1163 guint32 u32TmpOffset;
1165 proto_item *feature_item;
1166 proto_tree *feature_tree;
1169 /* XXX: which alignment do we need here? */
1171 sub_item = proto_tree_add_item(tree, hf_dcom_safearray, tvb, offset, 0, ENC_NA);
1172 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_safearray);
1173 u32SubStart = offset;
1175 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1176 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1178 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1179 hf_dcom_sa_dims32, &u32Dims);
1180 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1181 hf_dcom_sa_dims16, &u16Dims);
1184 u32TmpOffset = dissect_dcom_WORD(tvb, offset, pinfo, NULL, drep,
1185 hf_dcom_sa_features, &u16Features);
1186 feature_item = proto_tree_add_uint (sub_tree, hf_dcom_sa_features, tvb, offset, 2, u16Features);
1187 feature_tree = proto_item_add_subtree (feature_item, ett_dcom_sa_features);
1189 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_variant, tvb, offset, 2, u16Features);
1190 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_dispatch, tvb, offset, 2, u16Features);
1191 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_unknown, tvb, offset, 2, u16Features);
1192 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_bstr, tvb, offset, 2, u16Features);
1193 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_have_vartype, tvb, offset, 2, u16Features);
1194 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_have_iid, tvb, offset, 2, u16Features);
1195 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_record, tvb, offset, 2, u16Features);
1196 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_fixedsize, tvb, offset, 2, u16Features);
1197 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_embedded, tvb, offset, 2, u16Features);
1198 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_static, tvb, offset, 2, u16Features);
1199 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_auto, tvb, offset, 2, u16Features);
1201 offset = u32TmpOffset;
1203 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1204 hf_dcom_sa_element_size, &u32ElementSize);
1205 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1206 hf_dcom_sa_locks, &u16Locks);
1207 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1208 hf_dcom_sa_vartype16, &u16VarType);
1209 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1210 hf_dcom_sa_vartype32, &u32VarType);
1211 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1212 hf_dcom_sa_elements, &u32Elements);
1213 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1215 u32BoundElements = 0;
1217 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1218 hf_dcom_sa_bound_elements, &u32BoundElements);
1219 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1220 hf_dcom_sa_low_bound, &u32LowBound);
1223 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep, &u32ArraySize);
1225 tvb_ensure_bytes_exist(tvb, offset, u32ArraySize * u32ElementSize);
1226 u32VariableOffset = offset + u32ArraySize * u32ElementSize;
1229 sacb(tvb, offset, pinfo, tree, drep, u32VarType, u32ArraySize);
1232 while(u32ArraySize--) {
1233 switch(u32VarType) {
1234 case(WIRESHARK_VT_ERROR):
1235 offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, drep,
1238 case(WIRESHARK_VT_I1):
1239 offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, drep,
1240 hf_dcom_vt_i1, &u8Data);
1242 case(WIRESHARK_VT_I2):
1243 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1244 hf_dcom_vt_i2, &u16Data);
1246 case(WIRESHARK_VT_I4):
1247 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1248 hf_dcom_vt_i4, &u32Data);
1250 case(WIRESHARK_VT_I8):
1251 offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, drep,
1252 hf_dcom_vt_i8, NULL);
1253 /* take care of the 8 byte alignment */
1254 u32VariableOffset = offset;
1256 case(WIRESHARK_VT_BSTR):
1257 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1259 u32VariableOffset = dissect_dcom_BSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep,
1260 hf_dcom_vt_bstr, cData, sizeof(cData) );
1264 /* XXX: other types possible, but still not implemented:
1269 VT_UNKNOWN|VT_RESERVED
1271 u32VariableOffset = dissect_dcom_tobedone_data(tvb, u32VariableOffset, pinfo, sub_tree, drep,
1276 /* update subtree header */
1277 proto_item_append_text(sub_item, ": Elements: %u/%u VarType: %s",
1278 u32Elements, u32BoundElements,
1279 val_to_str(u32VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1281 proto_item_set_len(sub_item, u32VariableOffset - u32SubStart);
1283 return u32VariableOffset;
1289 dissect_dcom_VARTYPE(tvbuff_t *tvb, int offset, packet_info *pinfo,
1290 proto_tree *tree, guint8 *drep,
1291 guint16 *pu16VarType)
1294 offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep,
1295 hf_dcom_variant_type, pu16VarType);
1302 dissect_dcom_VARIANT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1303 proto_tree *tree, guint8 *drep, int hfindex)
1308 guint32 u32SubStart;
1309 proto_item *sub_item;
1310 proto_tree *sub_tree;
1323 /* alignment of 8 needed for a VARIANT */
1325 offset += 8 - (offset % 8);
1328 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
1329 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_variant);
1330 u32SubStart = offset;
1332 /* the following size can be VERY confusing:
1333 * It is NOT the maximum size of the variant, as one could expect,
1334 * but the current size of the variant padded to 8 bytes.
1335 * BUT: The following data does not start AFTER this padding,
1336 * it starts just after the variant-data (without padding)!!! */
1337 /* Conclusion: the size given here can be LONGER than the actual size */
1338 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1339 hf_dcom_variant_size, &u32Size);
1340 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1341 hf_dcom_variant_rpc_res, &u32RPCRes);
1342 offset = dissect_dcom_VARTYPE(tvb, offset, pinfo, sub_tree, drep,
1344 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1345 hf_dcom_variant_wres, &u16Res);
1346 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1347 hf_dcom_variant_wres, &u16Res);
1348 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1349 hf_dcom_variant_wres, &u16Res);
1351 /* 32 bit VarType (slightly different to the 16 bit one) */
1352 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1353 hf_dcom_variant_type32, &u32VarType);
1355 if (u32VarType & WIRESHARK_VT_BYREF) {
1356 u32VarType &=~WIRESHARK_VT_BYREF;
1357 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1360 switch (u32VarType) {
1361 case(WIRESHARK_VT_EMPTY):
1363 case(WIRESHARK_VT_BOOL):
1364 offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, sub_tree, drep,
1365 hf_dcom_vt_bool, &u16Data);
1367 case(WIRESHARK_VT_I1):
1368 offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, drep,
1369 hf_dcom_vt_i1, &u8Data);
1371 case(WIRESHARK_VT_UI1):
1372 offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, drep,
1373 hf_dcom_vt_ui1, &u8Data);
1375 case(WIRESHARK_VT_I2):
1376 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1377 hf_dcom_vt_i2, &u16Data);
1379 case(WIRESHARK_VT_UI2):
1380 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1381 hf_dcom_vt_ui2, &u16Data);
1383 case(WIRESHARK_VT_I4):
1384 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1385 hf_dcom_vt_i4, &u32Data);
1387 case(WIRESHARK_VT_UI4):
1388 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1389 hf_dcom_vt_ui4, &u32Data);
1391 case(WIRESHARK_VT_R4):
1392 offset = dissect_dcom_FLOAT(tvb, offset, pinfo, sub_tree, drep,
1393 hf_dcom_vt_r4, &f32Data);
1395 case(WIRESHARK_VT_R8):
1396 offset = dissect_dcom_DOUBLE(tvb, offset, pinfo, sub_tree, drep,
1397 hf_dcom_vt_r8, &f64Data);
1399 case(WIRESHARK_VT_DATE):
1400 offset = dissect_dcom_DATE(tvb, offset, pinfo, sub_tree, drep,
1401 hf_dcom_vt_date, &f64Data);
1403 case(WIRESHARK_VT_BSTR):
1404 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1406 offset = dissect_dcom_BSTR(tvb, offset, pinfo, sub_tree, drep,
1407 hf_dcom_vt_bstr, cData, sizeof(cData) );
1410 case(WIRESHARK_VT_DISPATCH):
1411 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1413 offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, sub_tree, drep,
1414 hf_dcom_vt_dispatch, NULL); /* XXX - how to handle this? */
1417 case(WIRESHARK_VT_ARRAY):
1418 offset = dissect_dcom_SAFEARRAY(tvb, offset, pinfo, sub_tree, drep,
1421 case(WIRESHARK_VT_ERROR):
1422 offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, drep,
1425 case(WIRESHARK_VT_VARIANT):
1426 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1428 offset = dissect_dcom_VARIANT(tvb, offset, pinfo, sub_tree, drep,
1429 hf_dcom_vt_byref /* must be BYREF */);
1432 case(WIRESHARK_VT_UNKNOWN):
1433 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1436 /* XXX: add more types here! */
1437 offset = dissect_dcom_tobedone_data(tvb, offset, pinfo, sub_tree, drep,
1441 /* update subtree header */
1442 proto_item_append_text(sub_item, ": %s",
1443 val_to_str(u16VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1445 proto_item_set_len(sub_item, offset - u32SubStart);
1452 dissect_dcom_UUID(tvbuff_t *tvb, int offset,
1453 packet_info *pinfo, proto_tree *tree, guint8 *drep,
1454 int hfindex, e_uuid_t *pdata)
1456 const gchar *uuid_name;
1457 header_field_info *hfi;
1461 /* get the UUID, but don't put it into the tree */
1462 offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, drep,
1465 /* add to the tree */
1466 hfi = proto_registrar_get_nth(hfindex);
1467 uuid_name = guids_get_uuid_name(&uuid);
1469 proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
1470 "%s: %s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
1471 hfi->name, uuid_name,
1472 uuid.Data1, uuid.Data2, uuid.Data3,
1473 uuid.Data4[0], uuid.Data4[1],
1474 uuid.Data4[2], uuid.Data4[3],
1475 uuid.Data4[4], uuid.Data4[5],
1476 uuid.Data4[6], uuid.Data4[7]);
1478 proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
1479 "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1481 uuid.Data1, uuid.Data2, uuid.Data3,
1482 uuid.Data4[0], uuid.Data4[1],
1483 uuid.Data4[2], uuid.Data4[3],
1484 uuid.Data4[4], uuid.Data4[5],
1485 uuid.Data4[6], uuid.Data4[7]);
1497 dissect_dcom_append_UUID(tvbuff_t *tvb, int offset,
1498 packet_info *pinfo, proto_tree *tree, guint8 *drep,
1499 int hfindex, int field_index, e_uuid_t *uuid)
1501 const gchar *uuid_name;
1503 header_field_info *hfi;
1506 /* XXX - this is far from being performance optimized! */
1508 /* get the UUID, but don't put it into the tree */
1509 offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, drep,
1512 /* look for a registered uuid name */
1513 uuid_name = guids_get_uuid_name(uuid);
1515 /* add to the tree */
1516 hfi = proto_registrar_get_nth(hfindex);
1517 pi = proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) uuid, "%s", hfi->name);
1519 if (field_index != -1) {
1520 proto_item_append_text(pi, "[%u]: ", field_index);
1522 proto_item_append_text(pi, ": ");
1526 proto_item_append_text(pi, "%s (", uuid_name);
1529 proto_item_append_text(pi, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1530 uuid->Data1, uuid->Data2, uuid->Data3,
1531 uuid->Data4[0], uuid->Data4[1],
1532 uuid->Data4[2], uuid->Data4[3],
1533 uuid->Data4[4], uuid->Data4[5],
1534 uuid->Data4[6], uuid->Data4[7]);
1537 proto_item_append_text(pi, ")");
1540 /* update column info now */
1541 if (field_index != -1) {
1542 col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]=%s",
1543 hfi->name, field_index, (uuid_name) ? uuid_name : "???");
1545 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%s",
1546 hfi->name, (uuid_name) ? uuid_name : "???");
1553 /* get a wide character string from tvb (zero terminated or limited through inLength) */
1554 /* the string will be converted to ASCII if possible or simple hexdump otherwise */
1555 /* outLength is in output bytes including zero termination output */
1557 dcom_tvb_get_nwstringz0(tvbuff_t *tvb, gint offset, guint32 inLength, gchar *pszStr, guint32 outLength, gboolean *isPrintable)
1567 *isPrintable = TRUE;
1569 /* we must have at least the space for the zero termination */
1570 DISSECTOR_ASSERT(outLength >= 1);
1572 /* determine length and printablility of the string */
1573 for(u32Idx = 0; u32Idx < inLength-1; u32Idx+=2) {
1574 /* the marshalling direction of a WCHAR is fixed! */
1575 u8Tmp1 = tvb_get_guint8(tvb, offset+u32Idx);
1576 u8Tmp2 = tvb_get_guint8(tvb, offset+u32Idx+1);
1578 /* is this the zero termination? */
1579 if (u8Tmp1 == 0 && u8Tmp2 == 0) {
1584 /* is this character printable? */
1585 /* XXX - there are probably more printable chars than isprint() */
1586 if(!isprint(u8Tmp1) || u8Tmp2 != 0) {
1587 *isPrintable = FALSE;
1591 /* u32Idx now contains the string length in bytes */
1592 /* (including optional zero termination) */
1594 /* if this is a printable string? */
1595 if(*isPrintable == TRUE) {
1596 /* convert to ascii (every "2nd char") */
1597 /* XXX - is it possible to convert to UTF8, so the output functions work with it? */
1598 for(u32IdxA = 0, u32IdxW = 0;
1599 u32IdxW < u32Idx && u32IdxA < outLength-2;
1600 u32IdxW+=2, u32IdxA++) {
1601 pszStr[u32IdxA] = tvb_get_guint8(tvb, offset+u32IdxW);
1604 /* convert to hexdump */
1605 for(u32IdxA = 0, u32IdxW = 0;
1606 u32IdxW < u32Idx && u32IdxA < outLength-2;
1607 u32IdxW++, u32IdxA+=2) {
1608 g_snprintf(&pszStr[u32IdxA], 3, "%02X", tvb_get_guint8(tvb, offset+u32IdxW));
1612 /* zero terminate the string, space must be available */
1613 DISSECTOR_ASSERT(u32IdxA < outLength);
1614 pszStr[u32IdxA] = 0;
1616 return offset + u32Idx;
1620 /* dissect a LPWSTR into a given buffer */
1621 /* use FT_STRING for hfindex */
1622 /* u32MaxStr is maximum length of string (including trailing zero) */
1624 dissect_dcom_indexed_LPWSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1625 proto_tree *tree, guint8 *drep, int hfindex,
1626 gchar *pszStr, guint32 u32MaxStr, int field_index)
1628 guint32 u32MaxCount;
1630 guint32 u32ArraySize;
1631 guint32 u32StrStart;
1632 proto_item *sub_item;
1633 proto_tree *sub_tree;
1634 guint32 u32SubStart;
1635 gboolean isPrintable;
1638 /* alignment of 4 needed */
1640 offset += 4 - (offset % 4);
1643 /* add subtree item */
1644 sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
1645 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
1646 u32SubStart = offset;
1648 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1649 hf_dcom_max_count, &u32MaxCount);
1650 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1651 hf_dcom_offset, &u32Offset);
1652 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep,
1655 u32StrStart = offset;
1656 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1658 proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr);
1660 /* update subtree header */
1661 if (field_index != -1) {
1662 proto_item_set_text(sub_item, "%s[%u]: %s%s%s",
1663 proto_registrar_get_name(hfindex),
1665 isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1667 proto_item_append_text(sub_item, "%s%s%s",
1668 isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1670 proto_item_set_len(sub_item, offset - u32SubStart);
1677 dissect_dcom_LPWSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1678 proto_tree *tree, guint8 *drep, int hfindex,
1679 gchar *pszStr, guint32 u32MaxStr)
1683 return dissect_dcom_indexed_LPWSTR(tvb, offset, pinfo, tree, drep,
1684 hfindex, pszStr, u32MaxStr, -1);
1688 /* dissect a BSTR to tree and into a given buffer (use FT_STRING for hfindex) */
1689 /* u32MaxStr is maximum length of string (including trailing zero) */
1690 /* (Hint: the BSTR space is always as long as the maximum size) */
1692 dissect_dcom_BSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1693 proto_tree *tree, guint8 *drep, int hfindex,
1694 gchar *pszStr, guint32 u32MaxStr)
1696 guint32 u32MaxCount;
1697 guint32 u32ArraySize;
1698 guint32 u32StrStart;
1699 proto_item *sub_item;
1700 proto_tree *sub_tree;
1701 guint32 u32SubStart;
1702 guint32 u32ByteLength;
1703 guint32 u32RealOffset;
1704 gboolean isPrintable;
1706 /* alignment of 4 needed */
1708 offset += 4 - (offset % 4);
1711 /* add subtree item */
1712 sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
1713 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
1714 u32SubStart = offset;
1716 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1717 hf_dcom_max_count, &u32MaxCount);
1718 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1719 hf_dcom_byte_length, &u32ByteLength);
1720 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep,
1723 u32RealOffset = offset + u32ArraySize*2;
1725 u32StrStart = offset;
1726 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1728 proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr);
1730 /* update subtree header */
1731 proto_item_append_text(sub_item, "%s%s%s",
1732 isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1733 if ((int) (u32RealOffset - u32SubStart) <= 0)
1734 THROW(ReportedBoundsError);
1735 proto_item_set_len(sub_item, u32RealOffset - u32SubStart);
1737 return u32RealOffset;
1741 /* dissect an DUALSTRINGARRAY */
1743 dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1744 proto_tree *tree, guint8 *drep, int hfindex, gchar *ip)
1746 guint16 u16NumEntries;
1747 guint16 u16SecurityOffset;
1749 guint32 u32MaxStr = sizeof(szStr);
1752 guint16 u16SecurityAuthnSvc;
1753 guint16 u16SecurityAuthzSvc;
1754 proto_item *sub_item;
1755 proto_tree *sub_tree;
1756 guint32 u32SubStart;
1757 guint32 u32StringBindings = 0;
1758 guint32 u32SecurityBindings = 0;
1759 proto_item *subsub_item;
1760 proto_tree *subsub_tree;
1761 guint32 u32SubSubStart;
1762 gboolean isPrintable;
1763 guint32 first_ip = 0;
1764 guint32 curr_ip = 0;
1765 struct in_addr ipaddr;
1769 /* add subtree header */
1770 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
1771 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_dualstringarray);
1773 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1774 hf_dcom_dualstringarray_num_entries, &u16NumEntries);
1775 /* from here, alignment is ok */
1776 u32SubStart = offset - 2;
1777 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1778 hf_dcom_dualstringarray_security_offset, &u16SecurityOffset);
1780 /* STRINGBINDINGs until first wchar zero */
1781 while ( tvb_get_ntohs(tvb, offset) ) {
1782 u32StringBindings++;
1784 subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_string, tvb, offset, 0, ENC_NA);
1785 subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
1786 u32SubSubStart = offset;
1788 offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, drep,
1789 hf_dcom_dualstringarray_string_tower_id, &u16TowerId);
1791 /* we don't know the (zero terminated) input length, use the buffer length instead */
1792 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
1793 pi = proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_string_network_addr,
1794 tvb, u32Start, offset - u32Start, szStr);
1796 /* convert ip address (if it is dotted decimal) */
1797 /* XXX - this conversion is ugly */
1798 if (inet_aton(szStr, &ipaddr)) {
1799 if(get_host_ipaddr(szStr, &curr_ip)) {
1801 /*expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "DUALSTRINGARRAY: IP:%s",
1802 ip_to_str( (guint8 *) &curr_ip));*/
1806 memcpy(ip, &curr_ip, sizeof(curr_ip));
1810 if(first_ip != curr_ip) {
1811 expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_NOTE,
1812 "DUALSTRINGARRAY: multiple IP's %s %s",
1813 ip_to_str( (guint8 *) &first_ip), ip_to_str( (guint8 *) &curr_ip));
1819 proto_item_append_text(subsub_item, "[%u]: TowerId=%s, NetworkAddr=\"%s\"",
1821 val_to_str(u16TowerId, dcom_protseq_vals, "Unknown (0x%04x"),
1823 proto_item_set_len(subsub_item, offset - u32SubSubStart);
1827 /* SECURITYBINDINGs until first wchar zero */
1828 while ( tvb_get_ntohs(tvb, offset) ) {
1829 u32SecurityBindings++;
1831 subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_security, tvb, offset, 0, ENC_NA);
1832 subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
1833 u32SubSubStart = offset;
1835 offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, drep,
1836 hf_dcom_dualstringarray_security_authn_svc,
1837 &u16SecurityAuthnSvc);
1838 offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, drep,
1839 hf_dcom_dualstringarray_security_authz_svc,
1840 &u16SecurityAuthzSvc);
1843 /* we don't know the (zero terminated) input length, use the buffer length instead */
1844 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
1845 proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_security_princ_name,
1846 tvb, u32Start, offset - u32Start, szStr);
1848 proto_item_append_text(subsub_item, "[%u]: AuthnSvc=0x%04x, AuthzSvc=0x%04x, PrincName=\"%s\"",
1849 u32SecurityBindings, u16SecurityAuthnSvc, u16SecurityAuthzSvc, szStr);
1850 proto_item_set_len(subsub_item, offset - u32SubSubStart);
1854 /* append info to subtree header */
1855 proto_item_append_text(sub_item, ": STRINGBINDINGs=%u, SECURITYBINDINGs=%u",
1856 u32StringBindings, u32SecurityBindings);
1857 proto_item_set_len(sub_item, offset - u32SubStart);
1863 /* dissect an STDOBJREF */
1865 dissect_dcom_STDOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1866 proto_tree *tree, guint8 *drep, int hfindex _U_,
1867 guint64 *oxid, guint64 *oid, e_uuid_t *ipid)
1870 guint32 u32PublicRefs;
1871 proto_item *sub_item;
1872 proto_tree *sub_tree;
1873 guint32 u32SubStart;
1876 /* add subtree header */
1877 sub_item = proto_tree_add_item(tree, hf_dcom_stdobjref, tvb, offset, 0, ENC_NA);
1878 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_stdobjref);
1880 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1881 hf_dcom_stdobjref_flags, &u32Flags);
1882 /* from here, alignment is ok */
1883 u32SubStart = offset - 4;
1884 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1885 hf_dcom_stdobjref_public_refs, &u32PublicRefs);
1886 offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, drep,
1887 hf_dcom_oxid, oxid);
1888 offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, drep,
1890 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep,
1891 hf_dcom_ipid, ipid);
1893 /* append info to subtree header */
1894 proto_item_append_text(sub_item, ": PublicRefs=%u IPID=%s",
1895 u32PublicRefs, guids_resolve_uuid_to_str(ipid));
1896 proto_item_set_len(sub_item, offset - u32SubStart);
1902 /* dissect an OBJREF */
1904 dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1905 proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf)
1907 guint32 u32Signature;
1911 proto_item *sub_item;
1912 proto_tree *sub_tree;
1913 guint32 u32SubStart;
1914 guint32 u32CBExtension;
1919 dcom_interface_t *dcom_if = NULL;
1923 /* add subtree header */
1924 sub_item = proto_tree_add_item(tree, hf_dcom_objref, tvb, offset, 0, ENC_NA);
1925 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_objref);
1927 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1928 hf_dcom_objref_signature, &u32Signature);
1929 /* from here, alignment is ok */
1930 u32SubStart = offset - 4;
1931 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1932 hf_dcom_objref_flags, &u32Flags);
1933 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep,
1937 case(0x1): /* standard */
1938 offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex,
1939 &oxid, &oid, &ipid);
1940 offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, drep,
1941 hf_dcom_objref_resolver_address, ip);
1943 case(0x2): /* handler (untested) */
1944 offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex,
1946 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep,
1947 hf_dcom_clsid, &clsid);
1948 offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, drep,
1949 hf_dcom_objref_resolver_address, ip);
1951 case(0x4): /* custom */
1952 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep,
1953 hf_dcom_clsid, &clsid);
1954 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1955 hf_dcom_objref_cbextension, &u32CBExtension);
1956 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1957 hf_dcom_objref_size, &u32Size);
1958 /* the following data depends on the CLSID, no docs available on this */
1959 offset = dissect_dcom_nospec_data(tvb, offset, pinfo, sub_tree, drep, u32Size);
1963 if(u32Flags == 0x1 || u32Flags == 0x2) {
1964 /* add interface instance to database (we currently only handle IPv4) */
1965 if(pinfo->net_src.type == AT_IPv4) {
1966 dcom_if = dcom_interface_new(pinfo,
1968 &iid, oxid, oid, &ipid);
1972 if(interf != NULL) {
1976 /* append info to subtree header */
1977 proto_item_set_len(sub_item, offset - u32SubStart);
1984 /* dissect an MInterfacePointer */
1986 dissect_dcom_MInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1987 proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf)
1990 guint32 u32ArraySize;
1991 proto_item *sub_item;
1992 proto_tree *sub_tree;
1993 guint32 u32SubStart;
1997 hfindex = hf_dcom_interface_pointer;
2000 /* add subtree header */
2001 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
2002 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_interface_pointer);
2004 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
2005 hf_dcom_ip_cnt_data, &u32CntData);
2006 u32SubStart = offset - 4;
2008 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep, &u32ArraySize);
2010 offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex, interf);
2012 /* append info to subtree header */
2013 proto_item_set_len(sub_item, offset - u32SubStart);
2019 /* dissect a pointer to a MInterfacePointer */
2021 dissect_dcom_PMInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2022 proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf)
2027 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer);
2030 offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, drep, hfindex, interf);
2032 if(interf != NULL) {
2040 static void dcom_reinit( void) {
2042 if (dcom_machines != NULL) {
2045 for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
2046 dcom_machine_t *machine = machines->data;
2048 if (machine->objects != NULL) {
2050 for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
2051 dcom_object_t *object = objects->data;
2053 if (object->interfaces != NULL) {
2055 for(interface = object->interfaces; interface != NULL; interface = g_list_next(interface)) {
2056 g_free(interface->data);
2057 interface->data = NULL; /* for good measure */
2059 g_list_free(object->interfaces);
2060 object->interfaces = NULL; /* for good measure */
2063 g_free(objects->data);
2064 objects->data = NULL; /* for good measure */
2066 g_list_free(machine->objects);
2067 machine->objects = NULL; /* for good measure */
2070 g_free(machines->data);
2071 machines->data = NULL; /* for good measure */
2073 g_list_free(dcom_machines);
2074 dcom_machines = NULL;
2077 /* The data in dcom_interfaces is se_alloc'd so there's no need to free
2078 * the data pointers.
2080 if (dcom_interfaces != NULL) {
2081 g_list_free(dcom_interfaces);
2082 dcom_interfaces = NULL;
2088 proto_register_dcom (void)
2091 static hf_register_info hf_dcom_this_array[] = {
2092 { &hf_dcom_this_version_major,
2093 { "VersionMajor", "dcom.this.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2094 { &hf_dcom_this_version_minor,
2095 { "VersionMinor", "dcom.this.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2096 { &hf_dcom_this_flags,
2097 { "Flags", "dcom.this.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }},
2098 { &hf_dcom_this_res,
2099 { "Reserved", "dcom.this.res", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2100 { &hf_dcom_this_cid,
2101 { "Causality ID", "dcom.this.uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2104 static hf_register_info hf_dcom_that_array[] = {
2105 { &hf_dcom_that_flags,
2106 { "Flags", "dcom.that.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }}
2109 static hf_register_info hf_dcom_extent_array[] = {
2111 { "Extension", "dcom.extent", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2112 { &hf_dcom_extent_array_count,
2113 { "Extension Count", "dcom.extent.array_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2114 { &hf_dcom_extent_array_res,
2115 { "Reserved", "dcom.extent.array_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2116 { &hf_dcom_extent_size,
2117 { "Extension Size", "dcom.extent.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2118 { &hf_dcom_extent_id,
2119 { "Extension Id", "dcom.extent.id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2122 static hf_register_info hf_dcom_array[] = {
2123 { &hf_dcom_version_major,
2124 { "VersionMajor", "dcom.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2125 { &hf_dcom_version_minor,
2126 { "VersionMinor", "dcom.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2128 { "HResult", "dcom.hresult", FT_UINT32, BASE_HEX, VALS(dcom_hresult_vals), 0x0, NULL, HFILL }},
2129 { &hf_dcom_max_count,
2130 { "MaxCount", "dcom.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2132 { "Offset", "dcom.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2133 { &hf_dcom_byte_length,
2134 { "ByteLength", "dcom.byte_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2135 { &hf_dcom_actual_count,
2136 { "ActualCount", "dcom.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2137 { &hf_dcom_tobedone,
2138 { "To Be Done", "dcom.tobedone", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2140 { "No Specification Available", "dcom.nospec", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2142 { "Variant", "dcom.variant", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2143 { &hf_dcom_variant_type,
2144 { "VarType", "dcom.variant_type", FT_UINT16, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2145 { &hf_dcom_variant_type32,
2146 { "VarType32", "dcom.variant_type32", FT_UINT32, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2147 { &hf_dcom_variant_size,
2148 { "Size", "dcom.variant_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2149 { &hf_dcom_variant_rpc_res,
2150 { "RPC-Reserved", "dcom.variant_rpc_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2151 { &hf_dcom_variant_wres,
2152 { "Reserved", "dcom.variant_wres", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2153 { &hf_dcom_array_size,
2154 { "(ArraySize)", "dcom.array_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2155 { &hf_dcom_pointer_val,
2156 { "(PointerVal)", "dcom.pointer_val", FT_UINT32, BASE_HEX, VALS(dcom_dcerpc_pointer_vals), 0x0, NULL, HFILL }}
2159 static hf_register_info hf_dcom_interface_pointer_array[] = {
2160 { &hf_dcom_interface_pointer,
2161 { "InterfacePointer", "dcom.ifp", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2162 { &hf_dcom_ip_cnt_data,
2163 { "CntData", "dcom.ip_cnt_data", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
2166 static hf_register_info hf_dcom_objref_array[] = {
2168 { "OBJREF", "dcom.objref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2169 { &hf_dcom_objref_signature,
2170 { "Signature", "dcom.objref.signature", FT_UINT32, BASE_HEX, VALS(dcom_objref_signature_vals), 0x0, NULL, HFILL }},
2171 { &hf_dcom_objref_flags,
2172 { "Flags", "dcom.objref.flags", FT_UINT32, BASE_HEX, VALS(dcom_objref_flag_vals), 0x0, NULL, HFILL }},
2174 { "IID", "dcom.iid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2176 { "CLSID", "dcom.clsid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2177 { &hf_dcom_objref_resolver_address,
2178 { "ResolverAddress", "dcom.objref.resolver_address", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2179 { &hf_dcom_objref_cbextension,
2180 { "CBExtension", "dcom.objref.cbextension", FT_UINT32, BASE_DEC, NULL, 0x0, "Size of extension data", HFILL }},
2181 { &hf_dcom_objref_size,
2182 { "Size", "dcom.objref.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
2185 static hf_register_info hf_dcom_stdobjref_array[] = {
2186 { &hf_dcom_stdobjref,
2187 { "STDOBJREF", "dcom.stdobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2188 { &hf_dcom_stdobjref_flags,
2189 { "Flags", "dcom.stdobjref.flags", FT_UINT32, BASE_HEX, VALS(dcom_stdobjref_flag_vals), 0x0, NULL, HFILL }},
2190 { &hf_dcom_stdobjref_public_refs,
2191 { "PublicRefs", "dcom.stdobjref.public_refs", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2193 { "OXID", "dcom.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2195 { "OID", "dcom.oid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2197 { "IPID", "dcom.ipid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2200 static hf_register_info hf_dcom_dualstringarray_array[] = {
2201 { &hf_dcom_dualstringarray_num_entries,
2202 { "NumEntries", "dcom.dualstringarray.num_entries", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2203 { &hf_dcom_dualstringarray_security_offset,
2204 { "SecurityOffset", "dcom.dualstringarray.security_offset", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2205 { &hf_dcom_dualstringarray_string,
2206 { "StringBinding", "dcom.dualstringarray.string", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2207 { &hf_dcom_dualstringarray_string_tower_id,
2208 { "TowerId", "dcom.dualstringarray.tower_id", FT_UINT16, BASE_HEX, VALS(dcom_protseq_vals), 0x0, NULL, HFILL }},
2209 { &hf_dcom_dualstringarray_string_network_addr,
2210 { "NetworkAddr", "dcom.dualstringarray.network_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2211 { &hf_dcom_dualstringarray_security,
2212 { "SecurityBinding", "dcom.dualstringarray.security", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2213 { &hf_dcom_dualstringarray_security_authn_svc,
2214 { "AuthnSvc", "dcom.dualstringarray.security_authn_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authn), 0x0, NULL, HFILL }},
2215 { &hf_dcom_dualstringarray_security_authz_svc,
2216 { "AuthzSvc", "dcom.dualstringarray.security_authz_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authz), 0x0, NULL, HFILL }},
2217 { &hf_dcom_dualstringarray_security_princ_name,
2218 { "PrincName", "dcom.dualstringarray.security_princ_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2221 static hf_register_info hf_dcom_vt_array[] = {
2223 { "VT_BOOL", "dcom.vt.bool", FT_UINT16, BASE_HEX, VALS(dcom_vt_bool_vals), 0x0, NULL, HFILL }},
2225 { "VT_I1", "dcom.vt.i1", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2227 { "VT_I2", "dcom.vt.i2", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2229 { "VT_I4", "dcom.vt.i4", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2231 { "VT_I8", "dcom.vt.i8", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2233 { "VT_UI1", "dcom.vt.ui1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2235 { "VT_UI2", "dcom.vt.ui2", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2237 { "VT_UI4", "dcom.vt.ui4", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2239 { "VT_R4", "dcom.vt.r4", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2241 { "VT_R8", "dcom.vt.r8", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2243 { "VT_DATE", "dcom.vt.date", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2245 { "VT_BSTR", "dcom.vt.bstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2246 { &hf_dcom_vt_byref,
2247 { "BYREF", "dcom.vt.byref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2248 { &hf_dcom_vt_dispatch,
2249 { "VT_DISPATCH", "dcom.vt.dispatch", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2252 static hf_register_info hf_dcom_sa_array[] = {
2253 { &hf_dcom_safearray,
2254 { "SAFEARRAY", "dcom.sa", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2255 { &hf_dcom_sa_dims32,
2256 { "Dims32", "dcom.sa.dims32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2257 { &hf_dcom_sa_dims16,
2258 { "Dims16", "dcom.sa.dims16", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2259 { &hf_dcom_sa_features,
2260 { "Features", "dcom.sa.features", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2261 { &hf_dcom_sa_element_size,
2262 { "ElementSize", "dcom.sa.element_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2263 { &hf_dcom_sa_locks,
2264 { "Locks", "dcom.sa.locks", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2265 { &hf_dcom_sa_vartype32,
2266 { "VarType32", "dcom.sa.vartype", FT_UINT32, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2267 { &hf_dcom_sa_vartype16,
2268 { "VarType16", "dcom.sa.vartype", FT_UINT16, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2269 { &hf_dcom_sa_elements,
2270 { "Elements", "dcom.sa.elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2271 { &hf_dcom_sa_bound_elements,
2272 { "BoundElements", "dcom.sa.bound_elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2273 { &hf_dcom_sa_low_bound,
2274 { "LowBound", "dcom.sa.low_bound", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2276 { &hf_dcom_sa_features_auto,
2277 { "AUTO", "dcom.sa.features_auto", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_AUTO, NULL, HFILL }},
2278 { &hf_dcom_sa_features_static,
2279 { "STATIC", "dcom.sa.features_static", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_STATIC, NULL, HFILL }},
2280 { &hf_dcom_sa_features_embedded,
2281 { "EMBEDDED", "dcom.sa.features_embedded", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_EMBEDDED, NULL, HFILL }},
2282 { &hf_dcom_sa_features_fixedsize,
2283 { "FIXEDSIZE", "dcom.sa.features_fixedsize", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_FIXEDSIZE, NULL, HFILL }},
2284 { &hf_dcom_sa_features_record,
2285 { "RECORD", "dcom.sa.features_record", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_RECORD, NULL, HFILL }},
2286 { &hf_dcom_sa_features_have_iid,
2287 { "HAVEIID", "dcom.sa.features_have_iid", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEIID, NULL, HFILL }},
2288 { &hf_dcom_sa_features_have_vartype,
2289 { "HAVEVARTYPE", "dcom.sa.features_have_vartype", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEVARTYPE, NULL, HFILL }},
2290 { &hf_dcom_sa_features_bstr,
2291 { "BSTR", "dcom.sa.features_bstr", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_BSTR, NULL, HFILL }},
2292 { &hf_dcom_sa_features_unknown,
2293 { "UNKNOWN", "dcom.sa.features_unknown", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_UNKNOWN, NULL, HFILL }},
2294 { &hf_dcom_sa_features_dispatch,
2295 { "DISPATCH", "dcom.sa.features_dispatch", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_DISPATCH, NULL, HFILL }},
2296 { &hf_dcom_sa_features_variant,
2297 { "VARIANT", "dcom.sa.features_variant", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_VARIANT, NULL, HFILL }}
2300 static gint *ett_dcom[] = {
2305 &ett_dcom_interface_pointer,
2307 &ett_dcom_stdobjref,
2308 &ett_dcom_dualstringarray,
2309 &ett_dcom_dualstringarray_binding,
2311 &ett_dcom_safearray,
2312 &ett_dcom_sa_features
2315 module_t *dcom_module;
2317 /* currently, the DCOM protocol "itself" has no real protocol dissector */
2318 /* we only need this, to register some generic elements */
2319 proto_dcom = proto_register_protocol ("DCOM", "DCOM", "dcom");
2320 proto_register_field_array(proto_dcom, hf_dcom_this_array, array_length(hf_dcom_this_array));
2321 proto_register_field_array(proto_dcom, hf_dcom_that_array, array_length(hf_dcom_that_array));
2322 proto_register_field_array(proto_dcom, hf_dcom_extent_array, array_length(hf_dcom_extent_array));
2323 proto_register_field_array(proto_dcom, hf_dcom_array, array_length(hf_dcom_array));
2324 proto_register_field_array(proto_dcom, hf_dcom_objref_array, array_length(hf_dcom_objref_array));
2325 proto_register_field_array(proto_dcom, hf_dcom_stdobjref_array, array_length(hf_dcom_stdobjref_array));
2326 proto_register_field_array(proto_dcom, hf_dcom_dualstringarray_array, array_length(hf_dcom_dualstringarray_array));
2327 proto_register_field_array(proto_dcom, hf_dcom_interface_pointer_array, array_length(hf_dcom_interface_pointer_array));
2328 proto_register_field_array(proto_dcom, hf_dcom_vt_array, array_length(hf_dcom_vt_array));
2329 proto_register_field_array(proto_dcom, hf_dcom_sa_array, array_length(hf_dcom_sa_array));
2330 proto_register_subtree_array (ett_dcom, array_length (ett_dcom));
2333 dcom_module = prefs_register_protocol(proto_dcom, NULL);
2335 prefs_register_bool_preference(dcom_module, "display_unmarshalling_details",
2336 "Display DCOM unmarshalling details",
2337 "Display some DCOM unmarshalled fields "
2339 &dcom_prefs_display_unmarshalling_details);
2341 register_init_routine(dcom_reinit);
2346 proto_reg_handoff_dcom (void)
2348 /* register some "well known" UUID's */
2349 guids_add_uuid(&uuid_debug_ext, "Debug Information Body Extension");
2350 guids_add_uuid(&uuid_ext_error_ext, "Extended Error Info Body Extension");
2351 guids_add_uuid(&ipid_rem_unknown, "IRemUnknown");
2352 guids_add_uuid(&iid_unknown, "IUnknown");
2353 guids_add_uuid(&uuid_null, "NULL");
2354 guids_add_uuid(&iid_class_factory, "IClassFactory");
2356 /* Currently, we have nothing to register for DCOM */