Don't use tabs in string constants;
[metze/wireshark/wip.git] / epan / dissectors / packet-dcom.c
1 /* packet-dcom.c
2  * Routines for DCOM generics
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 /* A few words about DCOM:
26  *
27  * DCOM uses DCERPC as it's underlying "transport" protocol.
28  *
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")
33  *
34  * DCOM defines itself some interfaces: oxid, remact, remunk and others
35  *
36  * Implemented is currently "only" a static dissection of packet fields
37  * (no "object recognition" included)
38  *
39  * User's of DCOM can define their own interface's using Microsoft IDL.
40  *
41  * Hint: The registered DCOM interface names can be found in the
42  * windows registry at: "HKEY_CLASSES_ROOT\Interface"
43  *
44  *
45  * Ressources on the web:
46  *
47  * "Understanding the DCOM Wire Protocol by Analyzing Network Data Packets"
48  * http:// www.microsoft.com/msj/0398/dcom.htm
49  *
50  * "Distributed Component Object Model Protocol -- DCOM/1.0"
51  * http://www.microsoft.com/com/resources/specs.asp (link is currently down)
52  *
53  */
54
55 /* Files involved dissecting DCOM:
56  *
57  * packet-dcom.c: generic DCOM things (this, that, ...) and
58  *    generic DCOM datatype (DWORD, VARIANT, ...)
59  *
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
66  */
67
68 #ifdef HAVE_CONFIG_H
69 #include "config.h"
70 #endif
71
72 /*
73  * XXX - are the next two includes necessary?
74  */
75 #ifdef HAVE_SYS_TYPES_H
76 # include <sys/types.h>
77 #endif
78
79 #ifdef HAVE_NETINET_IN_H
80 #include <netinet/in.h>
81 #endif
82
83 #ifdef HAVE_WINSOCK2_H
84 #include <winsock2.h>
85 #endif
86
87 #include <string.h>
88
89 #include <glib.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>
96 #include <ctype.h>
97 #include <isprint.h>
98 #include "packet-dcerpc.h"
99 #include "packet-dcom.h"
100
101 static int proto_dcom = -1;
102
103 gboolean dcom_prefs_display_unmarshalling_details = FALSE;
104
105
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;
112
113 static gint ett_dcom_that = -1;
114 static int hf_dcom_that_flags = -1;
115
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;
122
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;
128
129 /* COMVERSION */
130 static int hf_dcom_version_major = -1;
131 static int hf_dcom_version_minor = -1;
132
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;
138
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;
148
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;
156
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;
168
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;
172
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;
185
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;
198
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;
206
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;
221
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} };
225
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} };
231
232 static GList *dcom_machines   = NULL;
233 static GList *dcom_interfaces = NULL;
234
235 static const value_string dcom_thisthat_flag_vals[] = {
236         { 0, "INFO_NULL" },
237         { 1, "INFO_LOCAL" },
238         { 0,  NULL }
239 };
240
241
242
243 void dcom_interface_dump(void) {
244         dcom_machine_t *machine;
245         dcom_object_t *object;
246         dcom_interface_t *interf;
247         GList *machines;
248         GList *objects;
249         GList *interfaces;
250
251
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));
255
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);
259
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));
265                         }
266                 }
267         }
268 }
269
270
271 dcom_interface_t *dcom_interface_find(packet_info *pinfo _U_, const guint8 *ip _U_, e_uuid_t *ipid)
272 {
273         dcom_interface_t *interf;
274         GList *interfaces;
275
276
277         if(memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
278         {
279                 return NULL;
280         }
281
282         for(interfaces = dcom_interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
283                 interf = interfaces->data;
284
285                 if(memcmp(&interf->ipid, ipid, sizeof(e_uuid_t)) == 0) {
286                         return interf;
287                 }
288         }
289
290         return NULL;
291 }
292
293
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)
295 {
296         GList *dcom_iter;
297         dcom_machine_t *machine;
298         dcom_object_t *object;
299         dcom_interface_t *interf;
300
301
302         if( memcmp(iid, &uuid_null, sizeof(uuid_null)) == 0 ||
303             memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
304         {
305                 return NULL;
306         }
307
308         if(oxid == 0 || oid == 0) {
309                 /*g_warning("interface_new#%u", pinfo->fd->num);*/
310
311                 interf = se_alloc(sizeof(dcom_interface_t));
312                 interf->parent = NULL;
313                 interf->private_data = NULL;
314                 interf->first_packet = pinfo->fd->num;
315                 interf->iid = *iid;
316                 interf->ipid = *ipid;
317
318                 dcom_interfaces = g_list_append(dcom_interfaces, interf);
319                 return interf;
320         }
321
322         /* find machine */
323         dcom_iter = dcom_machines;
324         while(dcom_iter != NULL) {
325                 machine = dcom_iter->data;
326                 if(memcmp(machine->ip, ip, 4) == 0) {
327                         break;
328                 }
329                 dcom_iter = g_list_next(dcom_iter);
330         }
331
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);
339         }
340
341         /* find object */
342         dcom_iter = machine->objects;
343         while(dcom_iter != NULL) {
344                 object = dcom_iter->data;
345                 if(object->oid == oid) {
346                         break;
347                 }
348                 dcom_iter = g_list_next(dcom_iter);
349         }
350
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;
358                 object->oid = oid;
359                 object->oxid = oxid;
360
361                 machine->objects = g_list_append(machine->objects, object);
362         }
363
364         /* find interface */
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) {
369                         break;
370                 }
371                 dcom_iter = g_list_next(dcom_iter);
372         }
373
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;
380                 interf->iid = *iid;
381                 interf->ipid = *ipid;
382
383                 object->interfaces = g_list_append(object->interfaces, interf);
384                 dcom_interfaces = g_list_append(dcom_interfaces, interf);
385         }
386
387         return interf;
388 }
389
390
391 /*
392  * Flag bits in connection-oriented PDU header.
393  */
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
405
406
407 typedef enum {
408         WIRESHARK_VT_EMPTY           = 0,
409         WIRESHARK_VT_NULL            = 1,
410         WIRESHARK_VT_I2              = 2,
411         WIRESHARK_VT_I4              = 3,
412         WIRESHARK_VT_R4              = 4,
413         WIRESHARK_VT_R8              = 5,
414         WIRESHARK_VT_CY              = 6,
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,
449
450         WIRESHARK_VT_BSTR_BLOB       = 0x0fff,
451
452         WIRESHARK_VT_VECTOR          = 0x1000,
453         WIRESHARK_VT_ARRAY           = 0x2000,
454         WIRESHARK_VT_BYREF           = 0x4000,
455         WIRESHARK_VT_RESERVED        = 0x8000,
456
457         WIRESHARK_VT_ILLEGAL         = 0xffff,
458         WIRESHARK_VT_ILLEGALMASKED   = 0x0fff,
459         WIRESHARK_VT_TYPEMASK        = 0x0fff
460 } dcom_vartype_t;
461
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"},
484
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"},
500
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"},
504         { 0,          NULL }
505 /* XXX: append more types here */
506 };
507
508
509
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" },
524
525         { 0x80010108, "RPC_E_DISCONNECTED" },
526         { 0x80010113, "RPC_E_INVALID_IPID" },
527         { 0x8001011F, "RPC_E_TIMEOUT" },
528
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" },
536
537         { 0x8002801D, "TYPE_E_LIBNOTREGISTERED" },
538
539         { 0x80040154, "REGDB_E_CLASSNOTREG" },
540         { 0x80040201, "CO_E_FAILEDTOGETSECCTX" },
541
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" },
550
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" },
589
590         { 0x80080004, "CO_E_BAD_PATH" },
591
592         { 0,          NULL }
593 };
594
595 static const value_string dcom_objref_flag_vals[] = {
596         { 0x1, "OBJREF_STANDARD" },
597         { 0x2, "OBJREF_HANDLER" },
598         { 0x4, "OBJREF_CUSTOM" },
599         { 0,   NULL }
600 };
601
602 static const value_string dcom_objref_signature_vals[] = {
603         { 0x574f454d, "MEOW" },
604         { 0,          NULL }
605 };
606
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" },
619         { 0,      NULL }
620 };
621
622 static const value_string dcom_dcerpc_pointer_vals[] = {
623         { 0x72657355, "User" },
624         { 0x42535452, "BSTR" },
625         { 0x00000000, "NULL" },
626         { 0,          NULL }
627 };
628
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"},
634         { 0,      NULL}
635 };
636
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"},
650         { 0,   NULL}
651 };
652
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" },
663         { 0,    NULL }
664 };
665
666 static const value_string dcom_vt_bool_vals[] = {
667         { 0x0000, "FALSE" },
668         { 0xFFFF, "TRUE" },
669         { 0,      NULL }
670 };
671
672
673
674 /* dissect extension to DCOM "this" and "that" */
675 static int
676 dissect_dcom_extent(tvbuff_t *tvb, int offset,
677         packet_info *pinfo, proto_tree *tree, guint8 *drep)
678 {
679         guint32 u32ArraySize;
680         guint32 u32ArraySize2;
681         guint32 u32Pointer;
682         guint32 u32VariableOffset;
683         guint32 u32Idx;
684         guint32 u32SubStart;
685         proto_item *sub_item;
686         proto_tree *sub_tree;
687
688         guint32 u32ArrayCount;
689         guint32 u32ArrayRes;
690
691         guint32 u32ExtentSize;
692         e_uuid_t uuidExtend;
693         const char *uuid_name;
694
695
696         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer);
697
698         if (u32Pointer == 0) {
699                 return offset;
700         }
701
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);
706
707         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer);
708
709         if (u32Pointer == 0) {
710                 return offset;
711         }
712
713         offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep,
714                                                 &u32ArraySize);
715
716         u32VariableOffset = offset + u32ArraySize*4;
717
718         u32Idx = 1;
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;
723
724                 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
725
726                 if(u32Pointer != 0) {
727                         u32VariableOffset = dissect_dcom_DWORD(tvb, u32VariableOffset, pinfo, sub_tree, drep,
728                                                                hf_dcom_extent_size, &u32ExtentSize);
729
730                         dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, NULL, drep,
731                                           hf_dcom_extent_id, &uuidExtend);
732
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)",
738                                                                  uuid_name,
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;
745                         } else {
746                                 u32VariableOffset = dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, sub_tree, drep,
747                                                                       hf_dcom_extent_id, &uuidExtend);
748                         }
749
750
751                         u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, drep,
752                                                                            &u32ArraySize2);
753                         u32VariableOffset = dissect_dcom_nospec_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, u32ArraySize2);
754
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);
759                         } else {
760                                 proto_item_append_text(sub_item, "[%u]: Bytes=%u",
761                                                        u32Idx, u32ArraySize2);
762                         }
763                         proto_item_set_len(sub_item, offset - u32SubStart);
764                 } else {
765                         /* update subtree header */
766                         proto_item_append_text(sub_item, "[%u]: NULL", u32Idx);
767                         proto_item_set_len(sub_item, offset - u32SubStart);
768                 }
769
770                 u32Idx++;
771         }
772
773         return u32VariableOffset;
774 }
775
776
777 /* dissect DCOM "this" (start of every DCOM request) */
778 int
779 dissect_dcom_this(tvbuff_t *tvb, int offset,
780         packet_info *pinfo, proto_tree *tree, guint8 *drep)
781 {
782         guint16 u16VersionMajor;
783         guint16 u16VersionMinor;
784         guint32 u32Flags;
785         guint32 u32Res;
786         e_uuid_t uuidCausality;
787         proto_item *sub_item;
788         proto_tree *sub_tree;
789         guint32 u32SubStart;
790         proto_item *pi;
791         dcerpc_info *info = (dcerpc_info *)pinfo->private_data;
792
793
794         sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
795                                                   "DCOM, ORPCThis");
796         sub_tree = proto_item_add_subtree(sub_item, ett_dcom_this);
797
798         offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, sub_tree, drep,
799                                 &u16VersionMajor, &u16VersionMinor);
800         u32SubStart = offset - 4;
801
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);
806
807         offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep,
808                         hf_dcom_this_cid, &uuidCausality);
809
810         offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, drep);
811
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);
816
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);
822         }
823
824         return offset;
825 }
826
827
828 /* dissect DCOM "that" (start of every DCOM response) */
829 int
830 dissect_dcom_that(tvbuff_t *tvb, int offset,
831         packet_info *pinfo, proto_tree *tree, guint8 *drep) {
832         guint32 u32Flags;
833         proto_item *sub_item;
834         proto_tree *sub_tree;
835         guint32 u32SubStart;
836         proto_item *pi;
837         dcerpc_info *info = (dcerpc_info *)pinfo->private_data;
838
839
840         sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
841                                                   "DCOM, ORPCThat");
842         sub_tree = proto_item_add_subtree(sub_item, ett_dcom_that);
843
844         offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
845                                     hf_dcom_that_flags, &u32Flags);
846         u32SubStart = offset - 4;
847
848         offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, drep);
849
850         /* update subtree header */
851         proto_item_set_len(sub_item, offset - u32SubStart);
852
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);
858         }
859
860         return offset;
861 }
862
863
864 /* dissect simple dcom request, DCOM "this" only */
865 int
866 dissect_dcom_simple_rqst(tvbuff_t *tvb, int offset,
867         packet_info *pinfo, proto_tree *tree, guint8 *drep)
868 {
869
870         offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep);
871
872         return offset;
873 }
874
875
876 /* dissect simple dcom response, DCOM "that" and returned HRESULT only */
877 int
878 dissect_dcom_simple_resp(tvbuff_t *tvb, int offset,
879         packet_info *pinfo, proto_tree *tree, guint8 *drep)
880 {
881         guint32 u32HResult;
882
883
884         offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep);
885
886         offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep,
887                                       &u32HResult);
888
889         col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
890                         val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
891
892
893         return offset;
894 }
895
896
897 /* dissect a dcerpc array size */
898 int
899 dissect_dcom_dcerpc_array_size(tvbuff_t *tvb, gint offset, packet_info *pinfo,
900                        proto_tree *tree, guint8 *drep, guint32 *pu32ArraySize)
901 {
902
903
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 */
907                 tree = NULL;
908         }
909
910         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
911                                                         hf_dcom_array_size, pu32ArraySize);
912
913         return offset;
914 }
915
916
917 /* dissect a dcerpc pointer value */
918 int
919 dissect_dcom_dcerpc_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
920                        proto_tree *tree, guint8 *drep, guint32 *pu32Pointer)
921 {
922
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 */
926                 tree = NULL;
927         }
928
929         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
930                                                                 hf_dcom_pointer_val, pu32Pointer);
931
932         return offset;
933 }
934
935
936 /* mark data as "ToBeDone" */
937 /* XXX: handout data to generic "unknown data" dissector? */
938 extern int
939 dissect_dcom_tobedone_data(tvbuff_t *tvb, int offset,
940         packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int length)
941 {
942         proto_item *item;
943
944
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");
948
949         offset += length;
950
951         return offset;
952 }
953
954
955 /* mark data as "No Specification Available" */
956 /* XXX: handout data to generic "unknown data" dissector? */
957 extern int
958 dissect_dcom_nospec_data(tvbuff_t *tvb, int offset,
959         packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int length)
960 {
961         proto_item *item;
962
963
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");
967
968         offset += length;
969
970         return offset;
971 }
972
973
974 /* dissect an indexed WORD, something like: "FieldName[1]: 0x1234" */
975 int
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)
979 {
980         guint16 u16WORD;
981
982
983         /* dissect the WORD, but don't add to tree */
984         dissect_dcom_WORD(tvb, offset, pinfo, NULL /*tree*/, drep,
985                                         hfindex, &u16WORD);
986
987         if (tree) {
988                 /* special formatted output of indexed value */
989                 proto_tree_add_uint_format(tree, hfindex, tvb, offset, 2, u16WORD,
990                         "%s[%u]: 0x%04x",
991                         proto_registrar_get_name(hfindex),
992                         field_index, u16WORD);
993         }
994
995         offset += 2;
996
997         if (pu16WORD)
998                 *pu16WORD = u16WORD;
999
1000         return offset;
1001 }
1002
1003
1004 /* dissect an indexed DWORD, something like: "FieldName[1]: 0x12345678" */
1005 int
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)
1009 {
1010         guint32 u32DWORD;
1011
1012
1013         /* dissect the DWORD, but don't add to tree */
1014         dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, drep,
1015                                         hfindex, &u32DWORD);
1016
1017         if (tree) {
1018                 /* special formatted output of indexed value */
1019                 proto_tree_add_uint_format(tree, hfindex, tvb, offset, 4, u32DWORD,
1020                         "%s[%u]: 0x%08x",
1021                         proto_registrar_get_name(hfindex),
1022                         field_index, u32DWORD);
1023         }
1024
1025         offset += 4;
1026
1027         if (pu32DWORD)
1028                 *pu32DWORD = u32DWORD;
1029
1030         return offset;
1031 }
1032
1033
1034 /* dissect hresult field of a usual DCOM call (create "raw" item) */
1035 int
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)
1039 {
1040         guint32 u32HResult;
1041
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);
1045
1046         if (tree) {
1047                 /* special formatted output of indexed value */
1048                 *item = proto_tree_add_item (tree, field_index, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
1049         }
1050
1051         if (pu32HResult)
1052                 *pu32HResult = u32HResult;
1053
1054         return offset;
1055 }
1056
1057
1058 /* dissect hresult field of a usual DCOM call (seperate method, because often used) */
1059 int
1060 dissect_dcom_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1061                                          proto_tree *tree, guint8 *drep,
1062                                          guint32 * pu32HResult)
1063 {
1064         guint32 u32HResult;
1065         proto_item *item = NULL;
1066
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);
1070
1071         if (tree) {
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));
1074         }
1075
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)"));
1081         }
1082         if (pu32HResult)
1083                 *pu32HResult = u32HResult;
1084
1085         return offset;
1086 }
1087
1088
1089 /* partial results of indexed DCOM subcalls (e.g.: from a kind of array) */
1090 int
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)
1094 {
1095         guint32 u32HResult;
1096         proto_item *item = NULL;
1097
1098
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);
1102
1103         if (tree) {
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"),
1108                         u32HResult);
1109         }
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)"));
1115         }
1116         if (pu32HResult)
1117                 *pu32HResult = u32HResult;
1118
1119         return offset;
1120 }
1121
1122
1123
1124 int
1125 dissect_dcom_COMVERSION(tvbuff_t *tvb, int offset, packet_info *pinfo,
1126                                                 proto_tree *tree, guint8 *drep,
1127                                                 guint16 * pu16VersionMajor, guint16 * pu16VersionMinor)
1128 {
1129
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);
1134
1135         return offset;
1136 }
1137
1138
1139 int
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)
1142 {
1143         guint32 u32Dims;
1144         guint16 u16Dims;
1145         guint16 u16Features;
1146         guint32 u32ElementSize;
1147         guint32 u32VarType;
1148         guint32 u32Elements;
1149         guint32 u32Pointer;
1150         guint32 u32BoundElements;
1151         guint32 u32LowBound;
1152         gchar cData[100];
1153         guint32 u32ArraySize;
1154         guint32 u32VariableOffset;
1155         guint32 u32Data;
1156         guint16 u16Data;
1157         guint8  u8Data;
1158         guint16 u16Locks;
1159         guint16 u16VarType;
1160         proto_item *sub_item;
1161         proto_tree *sub_tree;
1162         guint32 u32SubStart;
1163         guint32 u32TmpOffset;
1164
1165         proto_item *feature_item;
1166         proto_tree *feature_tree;
1167
1168
1169         /* XXX: which alignment do we need here? */
1170
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;
1174
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);
1177
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);
1182
1183         /* feature flags */
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);
1188         if (feature_tree) {
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);
1200         }
1201         offset = u32TmpOffset;
1202
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);
1214
1215         u32BoundElements = 0;
1216         while(u32Dims--) {
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);
1221         }
1222
1223         offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep, &u32ArraySize);
1224
1225         tvb_ensure_bytes_exist(tvb, offset, u32ArraySize * u32ElementSize);
1226         u32VariableOffset = offset + u32ArraySize * u32ElementSize;
1227
1228         if(sacb) {
1229                 sacb(tvb, offset, pinfo, tree, drep, u32VarType, u32ArraySize);
1230         }
1231
1232         while(u32ArraySize--) {
1233                 switch(u32VarType) {
1234                         case(WIRESHARK_VT_ERROR):
1235                                 offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, drep,
1236                                                                         &u32Data);
1237                                 break;
1238                         case(WIRESHARK_VT_I1):
1239                                 offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, drep,
1240                                                                         hf_dcom_vt_i1, &u8Data);
1241                                 break;
1242                         case(WIRESHARK_VT_I2):
1243                                 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1244                                                                         hf_dcom_vt_i2, &u16Data);
1245                                 break;
1246                         case(WIRESHARK_VT_I4):
1247                                 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1248                                                                         hf_dcom_vt_i4, &u32Data);
1249                                 break;
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;
1255                                 break;
1256                         case(WIRESHARK_VT_BSTR):
1257                                 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1258                                 if (u32Pointer) {
1259                                         u32VariableOffset = dissect_dcom_BSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep,
1260                                                                         hf_dcom_vt_bstr, cData, sizeof(cData) );
1261                                 }
1262                                 break;
1263                         default:
1264                                 /* XXX: other types possible, but still not implemented:
1265                                 VT_UNKNOWN
1266                                 VT_DISPATCH
1267                                 VT_VARIANT
1268                                 VT_RECORD
1269                                 VT_UNKNOWN|VT_RESERVED
1270                                 */
1271                                 u32VariableOffset = dissect_dcom_tobedone_data(tvb, u32VariableOffset, pinfo, sub_tree, drep,
1272                                                                 10000);
1273                 }
1274         }
1275
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)") );
1280
1281         proto_item_set_len(sub_item, u32VariableOffset - u32SubStart);
1282
1283         return u32VariableOffset;
1284 }
1285
1286
1287
1288 int
1289 dissect_dcom_VARTYPE(tvbuff_t *tvb, int offset, packet_info *pinfo,
1290                                         proto_tree *tree, guint8 *drep,
1291                                         guint16 *pu16VarType)
1292 {
1293
1294         offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep,
1295                         hf_dcom_variant_type, pu16VarType);
1296
1297         return offset;
1298 }
1299
1300
1301 int
1302 dissect_dcom_VARIANT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1303                                          proto_tree *tree, guint8 *drep, int hfindex)
1304 {
1305         guint32 u32Size;
1306         guint32 u32RPCRes;
1307         guint16 u16Res;
1308         guint32 u32SubStart;
1309         proto_item *sub_item;
1310         proto_tree *sub_tree;
1311         guint16 u16VarType;
1312         guint32 u32VarType;
1313
1314         guint8  u8Data;
1315         guint16 u16Data;
1316         guint32 u32Data;
1317         gchar cData[500];
1318         guint32 u32Pointer;
1319         gfloat  f32Data;
1320         gdouble f64Data;
1321
1322
1323         /* alignment of 8 needed for a VARIANT */
1324         if (offset % 8) {
1325                 offset += 8 - (offset % 8);
1326         }
1327
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;
1331
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,
1343                                                 &u16VarType);
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);
1350
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);
1354
1355         if (u32VarType & WIRESHARK_VT_BYREF) {
1356                 u32VarType &=~WIRESHARK_VT_BYREF;
1357                 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1358         }
1359
1360         switch (u32VarType) {
1361                 case(WIRESHARK_VT_EMPTY):
1362                         break;
1363                 case(WIRESHARK_VT_BOOL):
1364                         offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, sub_tree, drep,
1365                                                                 hf_dcom_vt_bool, &u16Data);
1366                         break;
1367                 case(WIRESHARK_VT_I1):
1368                         offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, drep,
1369                                                                 hf_dcom_vt_i1, &u8Data);
1370                         break;
1371                 case(WIRESHARK_VT_UI1):
1372                         offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, drep,
1373                                                                 hf_dcom_vt_ui1, &u8Data);
1374                         break;
1375                 case(WIRESHARK_VT_I2):
1376                         offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1377                                                                 hf_dcom_vt_i2, &u16Data);
1378                         break;
1379                 case(WIRESHARK_VT_UI2):
1380                         offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep,
1381                                                                 hf_dcom_vt_ui2, &u16Data);
1382                         break;
1383                 case(WIRESHARK_VT_I4):
1384                         offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1385                                                                 hf_dcom_vt_i4, &u32Data);
1386                         break;
1387                 case(WIRESHARK_VT_UI4):
1388                         offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
1389                                                                 hf_dcom_vt_ui4, &u32Data);
1390                         break;
1391                 case(WIRESHARK_VT_R4):
1392                         offset = dissect_dcom_FLOAT(tvb, offset, pinfo, sub_tree, drep,
1393                                                                 hf_dcom_vt_r4, &f32Data);
1394                         break;
1395                 case(WIRESHARK_VT_R8):
1396                         offset = dissect_dcom_DOUBLE(tvb, offset, pinfo, sub_tree, drep,
1397                                                                 hf_dcom_vt_r8, &f64Data);
1398                         break;
1399                 case(WIRESHARK_VT_DATE):
1400                         offset = dissect_dcom_DATE(tvb, offset, pinfo, sub_tree, drep,
1401                                                                 hf_dcom_vt_date, &f64Data);
1402                         break;
1403                 case(WIRESHARK_VT_BSTR):
1404                         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1405                         if (u32Pointer) {
1406                                 offset = dissect_dcom_BSTR(tvb, offset, pinfo, sub_tree, drep,
1407                                                                 hf_dcom_vt_bstr, cData, sizeof(cData) );
1408                         }
1409                         break;
1410                 case(WIRESHARK_VT_DISPATCH):
1411                         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1412                         if (u32Pointer) {
1413                                 offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, sub_tree, drep,
1414                                                                 hf_dcom_vt_dispatch, NULL); /* XXX - how to handle this? */
1415                         }
1416                         break;
1417                 case(WIRESHARK_VT_ARRAY):
1418                         offset = dissect_dcom_SAFEARRAY(tvb, offset, pinfo, sub_tree, drep,
1419                                                                 0, NULL);
1420                         break;
1421                 case(WIRESHARK_VT_ERROR):
1422                         offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, drep,
1423                                                                 0);
1424                         break;
1425                 case(WIRESHARK_VT_VARIANT):
1426                         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1427                         if (u32Pointer) {
1428                             offset = dissect_dcom_VARIANT(tvb, offset, pinfo, sub_tree, drep,
1429                                                                     hf_dcom_vt_byref /* must be BYREF */);
1430                         }
1431                         break;
1432                 case(WIRESHARK_VT_UNKNOWN):
1433                         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer);
1434                         break;
1435                 default:
1436                         /* XXX: add more types here! */
1437                         offset = dissect_dcom_tobedone_data(tvb, offset, pinfo, sub_tree, drep,
1438                                                         10000);
1439         }
1440
1441         /* update subtree header */
1442         proto_item_append_text(sub_item, ": %s",
1443                 val_to_str(u16VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1444
1445         proto_item_set_len(sub_item, offset - u32SubStart);
1446
1447         return offset;
1448 }
1449
1450
1451 int
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)
1455 {
1456         const gchar *uuid_name;
1457         header_field_info *hfi;
1458         e_uuid_t uuid;
1459
1460
1461         /* get the UUID, but don't put it into the tree */
1462         offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, drep,
1463                                                 hfindex, &uuid);
1464
1465         /* add to the tree */
1466         hfi = proto_registrar_get_nth(hfindex);
1467         uuid_name = guids_get_uuid_name(&uuid);
1468         if(uuid_name) {
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]);
1477         } else {
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",
1480                           hfi->name,
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]);
1486         }
1487
1488         if(pdata != NULL) {
1489                 *pdata = uuid;
1490         }
1491
1492         return offset;
1493 }
1494
1495
1496 int
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)
1500 {
1501         const gchar *uuid_name;
1502         proto_item *pi;
1503         header_field_info *hfi;
1504
1505
1506         /* XXX - this is far from being performance optimized! */
1507
1508         /* get the UUID, but don't put it into the tree */
1509         offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, drep,
1510                                                 hfindex, uuid);
1511
1512         /* look for a registered uuid name */
1513         uuid_name = guids_get_uuid_name(uuid);
1514
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);
1518
1519         if (field_index != -1) {
1520                 proto_item_append_text(pi, "[%u]: ", field_index);
1521         } else {
1522                 proto_item_append_text(pi, ": ");
1523         }
1524
1525         if(uuid_name) {
1526                 proto_item_append_text(pi, "%s (", uuid_name);
1527         }
1528
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]);
1535
1536         if(uuid_name) {
1537                 proto_item_append_text(pi, ")");
1538         }
1539
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 : "???");
1544         } else {
1545                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%s",
1546                         hfi->name, (uuid_name) ? uuid_name : "???");
1547         }
1548
1549         return offset;
1550 }
1551
1552
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 */
1556 static int
1557 dcom_tvb_get_nwstringz0(tvbuff_t *tvb, gint offset, guint32 inLength, gchar *pszStr, guint32 outLength, gboolean *isPrintable)
1558 {
1559         guint32 u32Idx;
1560         guint32 u32IdxA;
1561         guint32 u32IdxW;
1562
1563         guint8  u8Tmp1;
1564         guint8  u8Tmp2;
1565
1566
1567         *isPrintable = TRUE;
1568
1569         /* we must have at least the space for the zero termination */
1570         DISSECTOR_ASSERT(outLength >= 1);
1571
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);
1577
1578                 /* is this the zero termination? */
1579                 if (u8Tmp1 == 0 && u8Tmp2 == 0) {
1580                         u32Idx+=2;
1581                         break;
1582                 }
1583
1584                 /* is this character printable? */
1585                 /* XXX - there are probably more printable chars than isprint() */
1586                 if(!isprint(u8Tmp1) || u8Tmp2 != 0) {
1587                         *isPrintable = FALSE;
1588                 }
1589         }
1590
1591         /* u32Idx now contains the string length in bytes */
1592         /* (including optional zero termination) */
1593
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);
1602                 }
1603         } else {
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));
1609                 }
1610         }
1611
1612         /* zero terminate the string, space must be available */
1613         DISSECTOR_ASSERT(u32IdxA < outLength);
1614         pszStr[u32IdxA] = 0;
1615
1616         return offset + u32Idx;
1617 }
1618
1619
1620 /* dissect a LPWSTR into a given buffer */
1621 /* use FT_STRING for hfindex */
1622 /* u32MaxStr is maximum length of string (including trailing zero) */
1623 int
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)
1627 {
1628         guint32 u32MaxCount;
1629         guint32 u32Offset;
1630         guint32 u32ArraySize;
1631         guint32 u32StrStart;
1632         proto_item *sub_item;
1633         proto_tree *sub_tree;
1634         guint32 u32SubStart;
1635         gboolean isPrintable;
1636
1637
1638         /* alignment of 4 needed */
1639         if (offset % 4) {
1640                 offset += 4 - (offset % 4);
1641         }
1642
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;
1647
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,
1653                         &u32ArraySize);
1654
1655         u32StrStart = offset;
1656         offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1657
1658         proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr);
1659
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),
1664                         field_index,
1665                         isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1666         } else {
1667                 proto_item_append_text(sub_item, "%s%s%s",
1668                                        isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1669         }
1670         proto_item_set_len(sub_item, offset - u32SubStart);
1671
1672         return offset;
1673 }
1674
1675
1676 int
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)
1680 {
1681
1682
1683         return dissect_dcom_indexed_LPWSTR(tvb, offset, pinfo, tree, drep,
1684                                                 hfindex, pszStr, u32MaxStr, -1);
1685 }
1686
1687
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) */
1691 int
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)
1695 {
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;
1705
1706         /* alignment of 4 needed */
1707         if (offset % 4) {
1708                 offset += 4 - (offset % 4);
1709         }
1710
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;
1715
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,
1721                         &u32ArraySize);
1722
1723         u32RealOffset = offset + u32ArraySize*2;
1724
1725         u32StrStart = offset;
1726         offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1727
1728         proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr);
1729
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);
1736
1737         return u32RealOffset;
1738 }
1739
1740
1741 /* dissect an DUALSTRINGARRAY */
1742 int
1743 dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1744                        proto_tree *tree, guint8 *drep, int hfindex, gchar *ip)
1745 {
1746         guint16 u16NumEntries;
1747         guint16 u16SecurityOffset;
1748         gchar   szStr[1000];
1749         guint32 u32MaxStr = sizeof(szStr);
1750         guint32 u32Start;
1751         guint16 u16TowerId;
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;
1766         proto_item *pi;
1767
1768
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);
1772
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);
1779
1780         /* STRINGBINDINGs until first wchar zero */
1781         while ( tvb_get_ntohs(tvb, offset) ) {
1782                 u32StringBindings++;
1783
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;
1787
1788                 offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, drep,
1789                                                         hf_dcom_dualstringarray_string_tower_id, &u16TowerId);
1790                 u32Start = offset;
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);
1795
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)) {
1800
1801                                 /*expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "DUALSTRINGARRAY: IP:%s",
1802                                   ip_to_str( (guint8 *) &curr_ip));*/
1803
1804                                 if(first_ip == 0) {
1805                                         if(ip != NULL) {
1806                                                 memcpy(ip, &curr_ip, sizeof(curr_ip));
1807                                         }
1808                                         first_ip = curr_ip;
1809                                 } else {
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));
1814                                         }
1815                                 }
1816                         }
1817                 }
1818
1819                 proto_item_append_text(subsub_item, "[%u]: TowerId=%s, NetworkAddr=\"%s\"",
1820                         u32StringBindings,
1821                         val_to_str(u16TowerId, dcom_protseq_vals, "Unknown (0x%04x"),
1822                         szStr);
1823                 proto_item_set_len(subsub_item, offset - u32SubSubStart);
1824         }
1825         offset += 2;
1826
1827         /* SECURITYBINDINGs until first wchar zero */
1828         while ( tvb_get_ntohs(tvb, offset) ) {
1829                 u32SecurityBindings++;
1830
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;
1834
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);
1841
1842                 u32Start = offset;
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);
1847
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);
1851         }
1852         offset += 2;
1853
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);
1858
1859         return offset;
1860 }
1861
1862
1863 /* dissect an STDOBJREF */
1864 int
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)
1868 {
1869         guint32 u32Flags;
1870         guint32 u32PublicRefs;
1871         proto_item *sub_item;
1872         proto_tree *sub_tree;
1873         guint32 u32SubStart;
1874
1875
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);
1879
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,
1889                         hf_dcom_oid, oid);
1890         offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep,
1891                         hf_dcom_ipid, ipid);
1892
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);
1897
1898         return offset;
1899 }
1900
1901
1902 /* dissect an OBJREF */
1903 int
1904 dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1905                        proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf)
1906 {
1907         guint32 u32Signature;
1908         guint32 u32Flags;
1909         e_uuid_t iid;
1910         e_uuid_t clsid;
1911         proto_item *sub_item;
1912         proto_tree *sub_tree;
1913         guint32 u32SubStart;
1914         guint32 u32CBExtension;
1915         guint32 u32Size;
1916         guint64 oxid;
1917         guint64 oid;
1918         e_uuid_t ipid;
1919         dcom_interface_t *dcom_if = NULL;
1920         gchar ip[4];
1921
1922
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);
1926
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,
1934                         hf_dcom_iid, &iid);
1935
1936         switch(u32Flags) {
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);
1942                 break;
1943                 case(0x2):      /* handler (untested) */
1944                         offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex,
1945                                                                 &oxid, &oid, &iid);
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);
1950                 break;
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);
1960                 break;
1961         }
1962
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,
1967                                                      (guint8 *) ip,
1968                                                      &iid, oxid, oid, &ipid);
1969                 }
1970         }
1971
1972         if(interf != NULL) {
1973                 *interf = dcom_if;
1974         }
1975
1976         /* append info to subtree header */
1977         proto_item_set_len(sub_item, offset - u32SubStart);
1978
1979         return offset;
1980 }
1981
1982
1983
1984 /* dissect an MInterfacePointer */
1985 int
1986 dissect_dcom_MInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1987                        proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf)
1988 {
1989         guint32 u32CntData;
1990         guint32 u32ArraySize;
1991         proto_item *sub_item;
1992         proto_tree *sub_tree;
1993         guint32 u32SubStart;
1994
1995
1996         if (!hfindex) {
1997                 hfindex = hf_dcom_interface_pointer;
1998         }
1999
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);
2003
2004         offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep,
2005                         hf_dcom_ip_cnt_data, &u32CntData);
2006         u32SubStart = offset - 4;
2007
2008         offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep, &u32ArraySize);
2009
2010         offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex, interf);
2011
2012         /* append info to subtree header */
2013         proto_item_set_len(sub_item, offset - u32SubStart);
2014
2015         return offset;
2016 }
2017
2018
2019 /* dissect a pointer to a MInterfacePointer */
2020 int
2021 dissect_dcom_PMInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2022                        proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf)
2023 {
2024         guint32 u32Pointer;
2025
2026
2027         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer);
2028
2029         if (u32Pointer) {
2030                 offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, drep, hfindex, interf);
2031         } else {
2032                 if(interf != NULL) {
2033                         *interf = NULL;
2034                 }
2035         }
2036
2037         return offset;
2038 }
2039
2040 static void dcom_reinit( void) {
2041
2042         if (dcom_machines != NULL) {
2043                 GList *machines;
2044
2045                 for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
2046                         dcom_machine_t *machine = machines->data;
2047
2048                         if (machine->objects != NULL) {
2049                                 GList *objects;
2050                                 for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
2051                                         dcom_object_t *object = objects->data;
2052
2053                                         if (object->interfaces != NULL) {
2054                                                 GList *interface;
2055                                                 for(interface = object->interfaces; interface != NULL; interface = g_list_next(interface)) {
2056                                                         g_free(interface->data);
2057                                                         interface->data = NULL; /* for good measure */
2058                                                 }
2059                                                 g_list_free(object->interfaces);
2060                                                 object->interfaces = NULL;  /* for good measure */
2061                                         }
2062
2063                                         g_free(objects->data);
2064                                         objects->data = NULL; /* for good measure */
2065                                 }
2066                                 g_list_free(machine->objects);
2067                                 machine->objects = NULL; /* for good measure */
2068                         }
2069
2070                         g_free(machines->data);
2071                         machines->data = NULL; /* for good measure */
2072                 }
2073                 g_list_free(dcom_machines);
2074                 dcom_machines = NULL;
2075         }
2076
2077         /*  The data in dcom_interfaces is se_alloc'd so there's no need to free
2078          *  the data pointers.
2079          */
2080         if (dcom_interfaces != NULL) {
2081                 g_list_free(dcom_interfaces);
2082                 dcom_interfaces = NULL;
2083         }
2084 }
2085
2086
2087 void
2088 proto_register_dcom (void)
2089 {
2090
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 }}
2102         };
2103
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 }}
2107         };
2108
2109         static hf_register_info hf_dcom_extent_array[] = {
2110                 { &hf_dcom_extent,
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 }}
2120         };
2121
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 }},
2127                 { &hf_dcom_hresult,
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 }},
2131                 { &hf_dcom_offset,
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 }},
2139                 { &hf_dcom_nospec,
2140                 { "No Specification Available", "dcom.nospec", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2141                 { &hf_dcom_variant,
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 }}
2157         };
2158
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 }}
2164         };
2165
2166         static hf_register_info hf_dcom_objref_array[] = {
2167                 { &hf_dcom_objref,
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 }},
2173                 { &hf_dcom_iid,
2174                 { "IID", "dcom.iid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2175                 { &hf_dcom_clsid,
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 }}
2183         };
2184
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 }},
2192                 { &hf_dcom_oxid,
2193                 { "OXID", "dcom.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2194                 { &hf_dcom_oid,
2195                 { "OID", "dcom.oid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2196                 { &hf_dcom_ipid,
2197                 { "IPID", "dcom.ipid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2198         };
2199
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 }}
2219         };
2220
2221         static hf_register_info hf_dcom_vt_array[] = {
2222                 { &hf_dcom_vt_bool,
2223                 { "VT_BOOL", "dcom.vt.bool", FT_UINT16, BASE_HEX, VALS(dcom_vt_bool_vals), 0x0, NULL, HFILL }},
2224                 { &hf_dcom_vt_i1,
2225                 { "VT_I1", "dcom.vt.i1", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2226                 { &hf_dcom_vt_i2,
2227                 { "VT_I2", "dcom.vt.i2", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2228                 { &hf_dcom_vt_i4,
2229                 { "VT_I4", "dcom.vt.i4", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2230                 { &hf_dcom_vt_i8,
2231                 { "VT_I8", "dcom.vt.i8", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2232                 { &hf_dcom_vt_ui1,
2233                 { "VT_UI1", "dcom.vt.ui1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2234                 { &hf_dcom_vt_ui2,
2235                 { "VT_UI2", "dcom.vt.ui2", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2236                 { &hf_dcom_vt_ui4,
2237                 { "VT_UI4", "dcom.vt.ui4", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2238                 { &hf_dcom_vt_r4,
2239                 { "VT_R4", "dcom.vt.r4", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2240                 { &hf_dcom_vt_r8,
2241                 { "VT_R8", "dcom.vt.r8", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2242                 { &hf_dcom_vt_date,
2243                 { "VT_DATE", "dcom.vt.date", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2244                 { &hf_dcom_vt_bstr,
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 }}
2250         };
2251
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 }},
2275
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 }}
2298         };
2299
2300         static gint *ett_dcom[] = {
2301                 &ett_dcom_this,
2302                 &ett_dcom_that,
2303                 &ett_dcom_extent,
2304                 &ett_dcom_lpwstr,
2305                 &ett_dcom_interface_pointer,
2306                 &ett_dcom_objref,
2307                 &ett_dcom_stdobjref,
2308                 &ett_dcom_dualstringarray,
2309                 &ett_dcom_dualstringarray_binding,
2310                 &ett_dcom_variant,
2311                 &ett_dcom_safearray,
2312                 &ett_dcom_sa_features
2313         };
2314
2315         module_t *dcom_module;
2316
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));
2331
2332         /* preferences */
2333         dcom_module = prefs_register_protocol(proto_dcom, NULL);
2334
2335         prefs_register_bool_preference(dcom_module, "display_unmarshalling_details",
2336                 "Display DCOM unmarshalling details",
2337                 "Display some DCOM unmarshalled fields "
2338                 "usually hidden",
2339                 &dcom_prefs_display_unmarshalling_details);
2340
2341         register_init_routine(dcom_reinit);
2342 }
2343
2344
2345 void
2346 proto_reg_handoff_dcom (void)
2347 {
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");
2355
2356         /* Currently, we have nothing to register for DCOM */
2357 }