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