MSWSP: use GuidPropertySet_find_guid() in parse_CFullPropSpec()
[wireshark-wip.git] / epan / dissectors / packet-mswsp.c
blob050824365041e9d8c72471d0c1cab19161da8888
1 /* packet-mswsp.c
2 * Routines for PROTONAME dissection
3 * Copyright 2012, Gregor Beck <gregor.beck@sernet.de>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 /* Include only as needed */
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdbool.h>
36 #include <glib.h>
38 #include <epan/packet.h>
39 #include <epan/prefs.h>
41 #include "packet-smb.h"
42 #include "packet-smb2.h"
44 /* IF PROTO exposes code to other dissectors, then it must be exported
45 in a header file. If not, a header file is not needed at all. */
47 * #include "packet-mswsp.h"
49 #include "mswsp.h"
51 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
53 /* Forward declaration we need below (if using proto_reg_handoff...
54 as a prefs callback) */
55 void proto_reg_handoff_mswsp(void);
57 /* Initialize the protocol and registered fields */
58 static int proto_mswsp = -1;
59 static int hf_mswsp_msg = -1;
60 static int hf_mswsp_hdr = -1;
61 static int hf_mswsp_hdr_msg = -1;
62 static int hf_mswsp_hdr_status = -1;
63 static int hf_mswsp_hdr_checksum = -1;
64 static int hf_mswsp_hdr_reserved = -1;
65 static int hf_mswsp_msg_Connect_Version = -1;
66 static int hf_mswsp_msg_ConnectIn_ClientIsRemote = -1;
67 static int hf_mswsp_msg_ConnectIn_Blob1 = -1;
68 static int hf_mswsp_msg_ConnectIn_Blob2 = -1;
69 static int hf_mswsp_msg_ConnectIn_MachineName = -1;
70 static int hf_mswsp_msg_ConnectIn_UserName = -1;
71 static int hf_mswsp_msg_ConnectIn_PropSets_num = -1;
72 static int hf_mswsp_msg_ConnectIn_ExtPropSets_num = -1;
75 /* Global sample preference ("controls" display of numbers) */
76 static gboolean gPREF_HEX = FALSE;
77 /* Global sample port pref */
78 static guint gPORT_PREF = 1234;
80 /* Initialize the subtree pointers */
81 static gint ett_mswsp = -1;
82 static gint ett_mswsp_hdr = -1;
83 static gint ett_mswsp_msg = -1;
84 static gint ett_mswsp_pad = -1;
86 static gint ett_mswsp_property_restriction = -1;
87 static gint ett_CRestrictionArray = -1;
88 static gint ett_CBaseStorageVariant = -1;
89 static gint ett_CBaseStorageVariant_Vector = -1;
90 static gint ett_CBaseStorageVariant_Array = -1;
91 static gint ett_CDbColId = -1;
92 static gint ett_GUID = -1;
93 static gint ett_CDbProp = -1;
94 static gint ett_CDbPropSet = -1;
95 static gint ett_CDbPropSet_Array = -1;
96 static gint ett_CRestriction = -1;
97 static gint ett_CNodeRestriction = -1;
98 static gint ett_CPropertyRestriction = -1;
99 static gint ett_CCoercionRestriction = -1;
100 static gint ett_CContentRestriction = -1;
101 static gint ett_RANGEBOUNDARY = -1;
102 static gint ett_CRangeCategSpec = -1;
103 static gint ett_CCategSpec = -1;
104 static gint ett_CAggregSpec = -1;
105 static gint ett_CAggregSet = -1;
106 static gint ett_CCategorizationSpec = -1;
107 static gint ett_CAggregSortKey = -1;
108 static gint ett_CSortAggregSet = -1;
109 static gint ett_CInGroupSortAggregSet = -1;
110 static gint ett_CInGroupSortAggregSets = -1;
111 static gint ett_CRowsetProperties = -1;
112 static gint ett_CFullPropSpec = -1;
113 static gint ett_CPidMapper = -1;
114 static gint ett_CSort = -1;
115 static gint ett_CSortSet = -1;
117 /******************************************************************************/
118 struct GuidPropertySet {
119 e_guid_t guid;
120 const char *def;
121 const char *desc;
122 const value_string *id_map;
125 /* 2.2.1.31.1 */
126 static const value_string DBPROPSET_FSCIFRMWRK_EXT_IDS[] = {
127 {0x02, "DBPROP_CI_CATALOG_NAME"},
128 {0x03, "DBPROP_CI_INCLUDE_SCOPES"},
129 {0x04, "DBPROP_CI_SCOPE_FLAGS"},
130 {0x07, "DBPROP_CI_QUERY_TYPE"},
131 {0, NULL}
134 static const value_string DBPROPSET_QUERYEXT_IDS[] = {
135 {0x02, "DBPROP_USECONTENTINDEX"},
136 {0x03, "DBPROP_DEFERNONINDEXEDTRIMMING"},
137 {0x04, "DBPROP_USEEXTENDEDDBTYPES"},
138 {0x05, "DBPROP_IGNORENOISEONLYCLAUSES"},
139 {0x06, "DBPROP_GENERICOPTIONS_STRING"},
140 {0x07, "DBPROP_FIRSTROWS"},
141 {0x08, "DBPROP_DEFERCATALOGVERIFICATION"},
142 {0x0a, "DBPROP_GENERATEPARSETREE"},
143 {0x0c, "DBPROP_FREETEXTANYTERM"},
144 {0x0d, "DBPROP_FREETEXTUSESTEMMING"},
145 {0x0e, "DBPROP_IGNORESBRI"},
146 {0x10, "DBPROP_ENABLEROWSETEVENTS"},
147 {0, NULL}
150 static const value_string DBPROPSET_CIFRMWRKCORE_EXT_IDS[] = {
151 {0x02, "DBPROP_MACHINE"},
152 {0x03, "DBPROP_CLIENT_CLSID"},
153 {0, NULL}
156 static const value_string DBPROPSET_MSIDXS_ROWSETEXT_IDS[] = {
157 {0x02, "MSIDXSPROP_ROWSETQUERYSTATUS"},
158 {0x03, "MSIDXSPROP_COMMAND_LOCALE_STRING"},
159 {0x04, "MSIDXSPROP_QUERY_RESTRICTION"},
160 {0x05, "MSIDXSPROP_PARSE_TREE"},
161 {0x06, "MSIDXSPROP_MAX_RANK"},
162 {0x07, "MSIDXSPROP_RESULTS_FOUND"},
163 {0, NULL}
166 static struct GuidPropertySet GuidPropertySet[] = {
167 {{0xa9bd1526, 0x6a80, 0x11d0, {0x8c, 0x9d, 0x00, 0x20, 0xaf, 0x1d, 0x74, 0x0e}},
168 "DBPROPSET_FSCIFRMWRK_EXT", "File system content index framework",
169 DBPROPSET_FSCIFRMWRK_EXT_IDS},
170 {{0xa7ac77ed, 0xf8d7, 0x11ce, {0xa7, 0x98, 0x00, 0x20, 0xf8, 0x00, 0x80, 0x25}},
171 "DBPROPSET_QUERYEXT", "Query extension",
172 DBPROPSET_QUERYEXT_IDS},
173 {{0xafafaca5, 0xb5d1, 0x11d0, {0x8c, 0x62, 0x00, 0xc0, 0x4f, 0xc2, 0xdb, 0x8d}},
174 "DBPROPSET_CIFRMWRKCORE_EXT", "Content index framework core",
175 DBPROPSET_CIFRMWRKCORE_EXT_IDS},
176 {{0xAA6EE6B0, 0xE828, 0x11D0, {0xB2, 0x3E, 0x00, 0xAA, 0x00, 0x47, 0xFC, 0x01}},
177 "DBPROPSET_MSIDXS_ROWSETEXT", "???",
178 DBPROPSET_MSIDXS_ROWSETEXT_IDS},
181 static struct GuidPropertySet *GuidPropertySet_find_guid(const e_guid_t *guid)
183 unsigned i;
184 for (i=0; i<array_length(GuidPropertySet); i++) {
185 if (guid_cmp(&GuidPropertySet[i].guid, guid) == 0) {
186 return &GuidPropertySet[i];
189 return NULL;
192 /******************************************************************************/
194 static int parse_padding(tvbuff_t *tvb, int offset, int alignment, proto_tree *pad_tree, const char *fmt, ...)
196 if (offset % alignment) {
197 const int padding = alignment - (offset % alignment);
198 va_list ap;
199 proto_item *ti;
200 va_start(ap, fmt);
201 ti = proto_tree_add_text_valist(pad_tree, tvb, offset, padding, fmt, ap);
202 va_end(ap);
204 proto_item_append_text(ti, " (%d)", padding);
205 offset += padding;
207 DISSECTOR_ASSERT((offset % alignment) == 0);
208 return offset;
211 static int parse_guid(tvbuff_t *tvb, int offset, proto_tree *tree, e_guid_t *guid, const char *text)
213 const char *guid_str, *name, *bytes;
214 proto_tree *tr;
215 proto_item *ti;
217 tvb_get_letohguid(tvb, offset, guid);
218 guid_str = guid_to_str(guid);
219 name = guids_get_guid_name(guid);
221 ti = proto_tree_add_text(tree, tvb, offset, 16, "%s: %s {%s}", text, name ? name : "", guid_str);
222 tr = proto_item_add_subtree(ti, ett_GUID);
224 proto_tree_add_text(tr, tvb, offset, 4, "time-low: 0x%08x", guid->data1);
225 offset += 4;
226 proto_tree_add_text(tr, tvb, offset, 2, "time-mid: 0x%04x", guid->data2);
227 offset += 2;
228 proto_tree_add_text(tr, tvb, offset, 2, "time-high-and-version: 0x%04x", guid->data3);
229 offset += 2;
230 proto_tree_add_text(tr, tvb, offset, 1, "clock_seq_hi_and_reserved: 0x%02x", guid->data4[0]);
231 offset += 1;
232 proto_tree_add_text(tr, tvb, offset, 1, "clock_seq_low: 0x%02x", guid->data4[1]);
233 offset += 1;
234 bytes = bytestring_to_str(&guid->data4[2], 6, ':');
235 proto_tree_add_text(tr, tvb, offset, 6, "node: %s", bytes);
236 offset += 6;
238 return offset;
241 /*****************************************************************************************/
242 /* 2.2.1.1 CBaseStorageVariant */
243 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
244 struct CBaseStorageVariant *value, const char *text);
246 /* 2.2.1.2 CFullPropSpec */
247 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pad_tree,
248 struct CFullPropSpec *v, const char *fmt, ...);
250 /* 2.2.1.3 CContentRestriction */
251 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
252 proto_tree *pad_tree, struct CContentRestriction *v,
253 const char *fmt, ...);
254 /* 2.2.1.6 CNodeRestriction */
255 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pad_tree,
256 struct CNodeRestriction *v, const char* fmt, ...);
258 /* 2.2.1.7 CPropertyRestriction */
259 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
260 proto_tree *pad_tree, struct CPropertyRestriction *v,
261 const char *fmt, ...);
263 /* 2.2.1.8 CReuseWhere */
264 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
265 proto_tree *pad_tree _U_, struct CReuseWhere *v,
266 const char *fmt, ...);
268 /* 2.2.1.10 CSort */
269 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
270 proto_tree *pad_tree _U_,
271 const char *fmt, ...);
273 /* 2.2.1.12 CCoercionRestriction */
274 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
275 proto_tree *pad_tree, struct CCoercionRestriction *v,
276 const char *fmt, ...);
277 /* 2.2.1.16 CRestrictionArray */
278 static int parse_CRestrictionArray(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
279 const char *fmt, ...);
281 /* 2.2.1.17 CRestriction */
282 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
283 struct CRestriction *v, const char *fmt, ...);
285 /* 2.2.1.18 CColumnSet */
286 static int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...);
288 /* 2.2.1.20 CCategorizationSpec */
289 static int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
290 proto_tree *parent_tree, proto_tree *pad_tree,
291 const char *fmt, ...);
293 /* 2.2.1.21 CCategSpec */
294 static int parse_CCategSpec(tvbuff_t *tvb, int offset,
295 proto_tree *parent_tree, proto_tree *pad_tree,
296 const char *fmt, ...);
298 /* 2.2.1.22 CRangeCategSpec */
299 static int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
300 proto_tree *parent_tree, proto_tree *pad_tree,
301 const char *fmt, ...);
303 /* 2.2.1.23 RANGEBOUNDARY */
304 static int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
305 proto_tree *pad_tree, const char *fmt, ...);
307 /* 2.2.1.24 CAggregSet */
308 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
309 proto_tree *parent_tree, proto_tree *pad_tree,
310 const char *fmt, ...);
312 /* 2.2.1.25 CAggregSpec */
313 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
314 proto_tree *parent_tree, proto_tree *pad_tree,
315 const char *fmt, ...);
317 /* 2.2.1.26 CSortAggregSet */
318 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
319 proto_tree *parent_tree, proto_tree *pad_tree,
320 const char *fmt, ...);
322 /* 2.2.1.27 CAggregSortKey */
323 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
324 proto_tree *parent_tree, proto_tree *pad_tree,
325 const char *fmt, ...);
327 /* 2.2.1.28 CInGroupSortAggregSets */
328 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
329 proto_tree *parent_tree, proto_tree *pad_tree,
330 const char *fmt, ...);
332 /* 2.2.1.29 CInGroupSortAggregSet */
333 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
334 proto_tree *parent_tree, proto_tree *pad_tree,
335 const char *fmt, ...);
336 /* 2.2.1.30 CDbColId */
337 static int parse_CDbColId(tvbuff_t *tvb, int offset,
338 proto_tree *parent_tree, proto_tree *pad_tree, const char *text);
340 /* 2.2.1.31 CDbProp */
341 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
342 proto_tree *pad_tree, struct GuidPropertySet *propset,
343 const char *fmt, ...);
345 /* 2.2.1.32 CDbPropSet */
346 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
347 proto_tree *pad_tree, const char *fmt, ...);
348 /* 2.2.1.33 CPidMapper */
349 static int parse_CPidMapper(tvbuff_t *tvb, int offset,
350 proto_tree *parent_tree, proto_tree *pad_tree,
351 const char *fmt, ...);
353 /* 2.2.1.41 CRowsetProperties */
354 static int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
355 proto_tree *parent_tree, proto_tree *pad_tree,
356 const char *fmt, ...);
358 /* 2.2.1.43 CSortSet */
359 static int parse_CSortSet(tvbuff_t *tvb, int offset,
360 proto_tree *parent_tree, proto_tree *pad_tree,
361 const char *fmt, ...);
364 2.2.1.4 CInternalPropertyRestriction
365 2.2.1.5 CNatLanguageRestriction
366 2.2.1.9 CScopeRestriction
367 2.2.1.11 CVectorRestriction
368 2.2.1.13 CRelDocRestriction
369 2.2.1.14 CProbRestriction
370 2.2.1.15 CFeedbackRestriction
371 2.2.1.19 CCategorizationSet
372 2.2.1.34 CColumnGroupArray
373 2.2.1.35 CColumnGroup
374 2.2.1.36 SProperty
375 2.2.1.37 CRowSeekAt
376 2.2.1.38 CRowSeekAtRatio
377 2.2.1.39 CRowSeekByBookmark
378 2.2.1.40 CRowSeekNext
379 2.2.1.42 CRowVariant
380 2.2.1.44 CTableColumn
381 2.2.1.45 SERIALIZEDPROPERTYVALUE
382 2.2.1.46 CCompletionCategSp
385 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
386 proto_tree *pad_tree _U_,
387 const char *fmt, ...)
389 guint32 col, ord, ind, lcid;
391 proto_item *item;
392 proto_tree *tree;
394 va_list ap;
396 va_start(ap, fmt);
397 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
398 va_end(ap);
399 tree = proto_item_add_subtree(item, ett_CSort);
401 col = tvb_get_letohl(tvb, offset);
402 proto_tree_add_text(tree, tvb, offset, 4, "column: %u", col);
403 offset += 4;
405 ord = tvb_get_letohl(tvb, offset);
406 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", ord);
407 offset += 4;
409 ind = tvb_get_letohl(tvb, offset);
410 proto_tree_add_text(tree, tvb, offset, 4, "individual: %u", ind);
411 offset += 4;
413 lcid = tvb_get_letohl(tvb, offset);
414 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", lcid);
415 offset += 4;
417 proto_item_set_end(item, tvb, offset);
418 return offset;
421 static int parse_CSortSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
422 proto_tree *pad_tree,
423 const char *fmt, ...)
425 guint32 count, i;
427 proto_item *item;
428 proto_tree *tree;
430 va_list ap;
432 va_start(ap, fmt);
433 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
434 va_end(ap);
435 tree = proto_item_add_subtree(item, ett_CSortSet);
437 count = tvb_get_letohl(tvb, offset);
438 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
439 offset += 4;
441 for (i=0; i<count; i++) {
442 offset = parse_padding(tvb, offset, 4, tree, "padding_sortArray[%u]", i);
443 offset = parse_CSort(tvb, offset, tree, pad_tree, "sortArray[%u]", i);
446 proto_item_set_end(item, tvb, offset);
447 return offset;
451 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset,
452 proto_tree *parent_tree, proto_tree *pad_tree,
453 struct CFullPropSpec *v, const char *fmt, ...)
455 static const value_string KIND[] = {
456 {0, "PRSPEC_LPWSTR"},
457 {1, "PRSPEC_PROPID"},
458 {0, NULL}
461 struct GuidPropertySet *pset;
463 proto_item *item;
464 proto_tree *tree;
465 va_list ap;
467 va_start(ap, fmt);
468 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
469 va_end(ap);
470 tree = proto_item_add_subtree(item, ett_CFullPropSpec);
472 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingPropSet");
474 offset = parse_guid(tvb, offset, tree, &v->guid, "GUID");
475 pset = GuidPropertySet_find_guid(&v->guid);
477 if (pset) {
478 proto_item_append_text(item, " \"%s\" (%s)", pset->desc, pset->def);
479 } else {
480 const char *guid_str = guid_to_str(&v->guid);
481 proto_item_append_text(item, " {%s}", guid_str);
484 v->kind = tvb_get_letohl(tvb, offset);
485 proto_tree_add_text(tree, tvb, offset, 4, "ulKind: %s ", val_to_str(v->kind, KIND, "(Unknown: 0x%x)"));
486 offset += 4;
488 v->u.propid = tvb_get_letohl(tvb, offset);
489 proto_tree_add_text(tree, tvb, offset, 4, "propid: %u ", v->u.propid);
490 offset += 4;
492 if (v->kind == PRSPEC_LPWSTR) {
493 int len = 2*v->u.propid;
494 v->u.name = tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
495 proto_tree_add_text(tree, tvb, offset, len, "name: \"%s\"", v->u.name);
496 proto_item_append_text(item, " \"%s\"", v->u.name);
497 offset += len;
498 } else if (v->kind == PRSPEC_PROPID) {
499 if (pset && pset->id_map) {
500 const char *str = val_to_str(v->u.propid, pset->id_map, "0x%08x");
501 proto_item_append_text(item, " Id: %s", str);
502 } else {
503 proto_item_append_text(item, " 0x%08x", v->u.propid);
505 } else {
506 proto_item_append_text(item, "<INVALID>");
509 proto_item_set_end(item, tvb, offset);
510 return offset;
515 static const value_string PR_VALS[] = {
516 {PRLT, "PRLT"},
517 {PRLE, "PRLE"},
518 {PRGT, "PRGT"},
519 {PRGE, "PRGE"},
520 {PREQ, "PREQ"},
521 {PRNE, "PRNE"},
522 {PRRE, "PRRE"},
523 {PRAllBits, "PRAllBits"},
524 {PRSomeBits, "PRSomeBits"},
525 {PRAll, "PRAll"},
526 {PRSome, "PRSome"},
530 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
531 proto_tree *pad_tree, struct CPropertyRestriction *v,
532 const char *fmt, ...)
534 proto_tree *tree;
535 proto_item *item;
536 const char *str;
537 va_list ap;
539 va_start(ap, fmt);
540 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
541 va_end(ap);
543 tree = proto_item_add_subtree(item, ett_CPropertyRestriction);
545 v->relop = tvb_get_letohl(tvb, offset);
546 str = val_to_str(v->relop, PR_VALS, "0x%04x");
547 proto_tree_add_text(tree, tvb, offset, 4, "relop: %s (0x%04x)",
548 str[0]=='\0' ? "" : str, v->relop);
549 proto_item_append_text(item, " Op: %s", str);
550 offset += 4;
552 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
554 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &v->prval, "prval");
556 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_lcid");
558 v->lcid = tvb_get_letohl(tvb, offset);
559 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", v->lcid);
560 offset += 4;
562 proto_item_set_end(item, tvb, offset);
564 return offset;
567 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
568 proto_tree *pad_tree, struct CCoercionRestriction *v,
569 const char *fmt, ...)
571 proto_tree *tree;
572 proto_item *item;
573 va_list ap;
575 va_start(ap, fmt);
576 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
577 va_end(ap);
579 tree = proto_item_add_subtree(item, ett_CCoercionRestriction);
581 v->value = tvb_get_letohl(tvb, offset);
582 proto_tree_add_text(tree, tvb, offset, 4, "value: %g", (double)v->value);
583 offset += 4;
585 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &v->child, "child");
587 proto_item_set_end(item, tvb, offset);
588 return offset;
591 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
592 proto_tree *pad_tree, struct CContentRestriction *v,
593 const char *fmt, ...)
595 proto_tree *tree;
596 proto_item *item;
597 va_list ap;
598 guint32 cc;
599 const char *str;
602 va_start(ap, fmt);
603 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
604 va_end(ap);
606 tree = proto_item_add_subtree(item, ett_CContentRestriction);
608 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
610 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding1");
612 cc = tvb_get_letohl(tvb, offset);
613 proto_tree_add_text(tree, tvb, offset, 4, "cc: %u", cc);
614 offset += 4;
616 // str = tvb_get_ephemeral_string_enc(tvb, offset, 2*cc, ENC_UTF_16);
617 str = tvb_get_unicode_string(tvb, offset, 2*cc, ENC_LITTLE_ENDIAN);
618 v->phrase = se_strdup(str);
619 proto_tree_add_text(tree, tvb, offset, 2*cc, "phrase: %s", str);
620 offset += 2*cc;
622 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding2");
624 v->lcid = tvb_get_letohl(tvb, offset);
625 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", v->lcid);
626 offset += 4;
628 v->method = tvb_get_letohl(tvb, offset);
629 proto_tree_add_text(tree, tvb, offset, 4, "method: 0x%08x", v->method);
630 offset += 4;
632 proto_item_set_end(item, tvb, offset);
633 return offset;
637 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
638 proto_tree *pad_tree _U_, struct CReuseWhere *v,
639 const char *fmt, ...)
641 proto_item *item;
642 va_list ap;
645 va_start(ap, fmt);
646 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
647 va_end(ap);
649 v->whereId = tvb_get_letohl(tvb, offset);
650 offset += 4;
652 proto_item_append_text(item, " Id: %u", v->whereId);
654 proto_item_set_end(item, tvb, offset);
655 return offset;
658 static value_string RT_VALS[] = {
659 {RTNone, "RTNone"},
660 {RTAnd, "RTAnd"},
661 {RTOr, "RTOr"},
662 {RTNot, "RTNot"},
663 {RTContent, "RTContent"},
664 {RTProperty, "RTProperty"},
665 {RTProximity, "RTProximity"},
666 {RTVector, ""},
667 {RTNatLanguage, "RTNatLanguage"},
668 {RTScope, "RTScope"},
669 {RTCoerce_Add, "RTCoerce_Add"},
670 {RTCoerce_Multiply, "RTCoerce_Multiply"},
671 {RTCoerce_Absolute, "RTCoerce_Absolute"},
672 {RTProb, "RTProb"},
673 {RTFeedback, "RTFeedback"},
674 {RTReldoc, "RTReldoc"},
675 {RTReuseWhere, "RTReuseWhere"},
676 {RTInternalProp, "RTInternalProp"},
677 {RTPhrase, "RTInternalProp"},
680 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
681 struct CRestriction *v, const char *fmt, ...)
683 proto_tree *tree;
684 proto_item *item;
685 const char *str;
686 va_list ap;
688 va_start(ap, fmt);
689 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
690 va_end(ap);
692 tree = proto_item_add_subtree(item, ett_CRestriction);
695 v->ulType = tvb_get_letohl(tvb, offset);
696 str = val_to_str(v->ulType, RT_VALS, "0x%.8x");
697 proto_tree_add_text(tree, tvb, offset, 4, "ulType: %s (0x%.8x)",
698 str[0] == '0' ? "" : str, v->ulType);
699 proto_item_append_text(item, " Type: %s", str);
700 offset += 4;
702 v->Weight = tvb_get_letohl(tvb, offset);
703 proto_tree_add_text(tree, tvb, offset, 4, "Weight: %u", v->ulType);
704 offset += 4;
706 switch(v->ulType) {
707 case RTNone:
708 break;
709 case RTAnd:
710 case RTOr:
711 case RTProximity:
712 case RTPhrase:
714 v->u.RTAnd = ep_alloc(sizeof(struct CNodeRestriction)); //XXX
715 offset = parse_CNodeRestriction(tvb, offset, tree, pad_tree, v->u.RTAnd, "CNodeRestriction");
716 break;
718 case RTNot:
720 v->u.RTNot = ep_alloc(sizeof(struct CRestriction)); //XXX
721 offset = parse_CRestriction(tvb, offset, tree, pad_tree,
722 v->u.RTNot, "CRestriction");
723 break;
725 case RTProperty:
727 v->u.RTProperty = ep_alloc(sizeof(struct CPropertyRestriction)); //XXX
728 offset = parse_CPropertyRestriction(tvb, offset, tree, pad_tree,
729 v->u.RTProperty, "CPropertyRestriction");
730 break;
732 case RTCoerce_Add:
733 case RTCoerce_Multiply:
734 case RTCoerce_Absolute:
736 v->u.RTCoerce_Add = ep_alloc(sizeof(struct CCoercionRestriction)); //XXX
737 offset = parse_CCoercionRestriction(tvb, offset, tree, pad_tree,
738 v->u.RTCoerce_Add, "CCoercionRestriction");
739 break;
741 case RTContent: {
742 v->u.RTContent = ep_alloc(sizeof(struct CContentRestriction)); //XXX
743 offset = parse_CContentRestriction(tvb, offset, tree, pad_tree,
744 v->u.RTContent, "CContentRestriction");
745 break;
747 case RTReuseWhere: {
748 v->u.RTReuseWhere = ep_alloc(sizeof(struct CReuseWhere)); //XXX
749 offset = parse_CReuseWhere(tvb, offset, tree, pad_tree,
750 v->u.RTReuseWhere, "CReuseWhere");
751 break;
753 default:
754 fprintf(stderr, "CRestriciont 0x%08x not Supported\n", v->ulType);
755 proto_item_append_text(item, " Not supported!");
758 proto_item_set_end(item, tvb, offset);
759 return offset;
762 static int parse_CRestrictionArray(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
763 const char *fmt, ...)
765 guint8 present, count;
767 proto_tree *tree;
768 proto_item *item;
769 va_list ap;
771 va_start(ap, fmt);
772 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
773 va_end(ap);
774 tree = proto_item_add_subtree(item, ett_CRestrictionArray);
776 pad_tree = tree; //XXX
778 count = tvb_get_guint8(tvb, offset);
779 proto_tree_add_text(tree, tvb, offset, 1, "count: %u", count);
780 offset += 1;
782 present = tvb_get_guint8(tvb, offset);
783 proto_tree_add_text(tree, tvb, offset, 1, "present: %u", present);
784 offset += 1;
786 if (present) {
787 unsigned i;
788 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCRestrictionPresent");
790 for (i=0; i<count; i++) {
791 struct CRestriction r;
792 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "Restriction[%d]", i);
795 proto_item_set_end(item, tvb, offset);
796 return offset;
799 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
800 proto_tree *pad_tree, struct CNodeRestriction *v,
801 const char *fmt, ...)
803 proto_tree *tree;
804 proto_item *item;
805 unsigned i;
806 va_list ap;
808 va_start(ap, fmt);
809 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
810 va_end(ap);
811 tree = proto_item_add_subtree(item, ett_CNodeRestriction);
813 v->cNode = tvb_get_letohl(tvb, offset);
814 proto_tree_add_text(tree, tvb, offset, 4, "cNode: %u", v->cNode);
815 offset += 4;
817 for (i=0; i<v->cNode; i++) {
818 struct CRestriction r;
819 ZERO_STRUCT(r);
820 // offset = parse_padding(tvb, offset, 4, tree, "padding_paNode[%u]", i); /*at begin or end of loop ????*/
821 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "paNode[%u]", i);
822 offset = parse_padding(tvb, offset, 4, tree, "padding_paNode[%u]", i); /*at begin or end of loop ????*/
824 // offset = parse_padding(tvb, offset, 4, pad_tree, "paNode[%u]", i); /*at begin or end of loop ????*/
827 proto_item_set_end(item, tvb, offset);
828 return offset;
832 /*****************************************************************************************/
834 static int vvalue_tvb_get0(tvbuff_t *tvb _U_, int offset _U_, void *val _U_)
836 return 0;
839 static int vvalue_tvb_get1(tvbuff_t *tvb, int offset, void *val)
841 guint8 *ui1 = (guint8*)val;
842 *ui1 = tvb_get_guint8(tvb, offset);
843 return 1;
846 static int vvalue_tvb_get2(tvbuff_t *tvb , int offset, void *val)
848 guint16 *ui2 = (guint16*)val;
849 *ui2 = tvb_get_letohs(tvb, offset);
850 return 2;
853 static int vvalue_tvb_get4(tvbuff_t *tvb , int offset, void *val)
855 guint32 *ui4 = (guint32*)val;
856 *ui4 = tvb_get_letohl(tvb, offset);
857 return 4;
860 static int vvalue_tvb_get8(tvbuff_t *tvb , int offset, void *val)
862 guint64 *ui8 = (guint64*)val;
863 *ui8 = tvb_get_letoh64(tvb, offset);
864 return 8;
867 static int vvalue_tvb_blob(tvbuff_t *tvb , int offset, void *val)
869 struct data_blob *blob = (struct data_blob*)val;
870 guint32 len = tvb_get_letohl(tvb, offset);
871 const guint8 *data = tvb_get_ptr(tvb, offset + 4, len);
873 blob->size = len;
874 blob->data = se_memdup(data, len);
876 return 4 + len;
879 static int vvalue_tvb_bstr(tvbuff_t *tvb , int offset, void *val)
881 struct data_str *str = (struct data_str*)val;
882 guint32 len = tvb_get_letohl(tvb, offset);
883 const void *ptr = tvb_get_ptr(tvb, offset + 4, len);
885 //XXX this might be UTF-16
886 str->len = len;
887 str->str = se_strndup(ptr, len);
888 return 4 + len;
891 static int vvalue_tvb_lpstr(tvbuff_t *tvb , int offset, void *val)
893 struct data_str *str = (struct data_str*)val;
894 gint len;
896 str->len = tvb_get_letohl(tvb, offset);
897 str->str = tvb_get_seasonal_stringz(tvb, offset + 4, &len);
898 /* XXX test str->len == len */
899 return 4 + len;
902 static int vvalue_tvb_lpwstr(tvbuff_t *tvb , int offset, void *val)
904 struct data_str *str = (struct data_str*)val;
905 gint len;
906 gchar *ptr;
908 str->len = tvb_get_letohl(tvb, offset);
910 ptr = tvb_get_ephemeral_unicode_stringz(tvb, offset + 4, &len, ENC_LITTLE_ENDIAN);
911 str->str = se_strdup (ptr);
913 return 4 + len;
916 static int vvalue_tvb_vector_internal(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type, int num)
918 const int offset_in = offset;
919 const gboolean varsize = (type->size == -1);
920 const int elsize = varsize ? (int)sizeof(struct data_blob) : type->size;
921 guint8 *data = se_alloc(elsize * num);
922 int len, i;
924 val->len = num;
925 val->u.vt_ui1 = data;
926 DISSECTOR_ASSERT((void*)&val->u == ((void*)&val->u.vt_ui1));
928 for (i=0; i<num; i++) {
929 len = type->tvb_get(tvb, offset, data);
930 data += elsize;
931 offset += len;
932 if (varsize && (offset % 4) ) { /* at begin or end of loop ??? */
933 int padding = 4 - (offset % 4);
934 offset += padding;
937 return offset - offset_in;
940 static int vvalue_tvb_vector(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type)
942 const int num = tvb_get_letohl(tvb, offset);
943 return 4 + vvalue_tvb_vector_internal(tvb , offset+4, val, type, num);
946 static void vvalue_strbuf_append_null(emem_strbuf_t *strbuf _U_, void *ptr _U_)
949 static void vvalue_strbuf_append_i1(emem_strbuf_t *strbuf, void *ptr)
951 gint8 i1 = *(gint8*)ptr;
952 ep_strbuf_append_printf(strbuf, "%d", (int)i1);
955 static void vvalue_strbuf_append_i2(emem_strbuf_t *strbuf, void *ptr)
957 gint16 i2 = *(gint16*)ptr;
958 ep_strbuf_append_printf(strbuf, "%d", (int)i2);
961 static void vvalue_strbuf_append_i4(emem_strbuf_t *strbuf, void *ptr)
963 gint32 i4 = *(gint32*)ptr;
964 ep_strbuf_append_printf(strbuf, "%d", i4);
967 static void vvalue_strbuf_append_i8(emem_strbuf_t *strbuf, void *ptr)
969 gint64 i8 = *(gint64*)ptr;
970 ep_strbuf_append_printf(strbuf, "%ld", i8);
973 static void vvalue_strbuf_append_ui1(emem_strbuf_t *strbuf, void *ptr)
975 guint8 ui1 = *(guint8*)ptr;
976 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui1);
979 static void vvalue_strbuf_append_ui2(emem_strbuf_t *strbuf, void *ptr)
981 guint16 ui2 = *(guint16*)ptr;
982 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui2);
985 static void vvalue_strbuf_append_ui4(emem_strbuf_t *strbuf, void *ptr)
987 guint32 ui4 = *(guint32*)ptr;
988 ep_strbuf_append_printf(strbuf, "%d", ui4);
991 static void vvalue_strbuf_append_ui8(emem_strbuf_t *strbuf, void *ptr)
993 guint64 ui8 = *(guint64*)ptr;
994 ep_strbuf_append_printf(strbuf, "%lu", ui8);
997 static void vvalue_strbuf_append_r4(emem_strbuf_t *strbuf, void *ptr)
999 float r4 = *(float*)ptr;
1000 ep_strbuf_append_printf(strbuf, "%g", (double)r4);
1003 static void vvalue_strbuf_append_r8(emem_strbuf_t *strbuf, void *ptr)
1005 double r8 = *(double*)ptr;
1006 ep_strbuf_append_printf(strbuf, "%g", r8);
1009 static void vvalue_strbuf_append_str(emem_strbuf_t *strbuf, void *ptr)
1011 struct data_str *str = (struct data_str*)ptr;
1012 ep_strbuf_append_printf(strbuf, "\"%s\"", str->str);
1015 static void vvalue_strbuf_append_blob(emem_strbuf_t *strbuf, void *ptr)
1017 struct data_blob *blob = (struct data_blob*)ptr;
1018 ep_strbuf_append_printf(strbuf, "size: %d", (int)blob->size);
1021 static void vvalue_strbuf_append_bool(emem_strbuf_t *strbuf, void *ptr)
1023 guint16 val = *(guint*)ptr;
1024 switch (val) {
1025 case 0:
1026 ep_strbuf_append(strbuf, "False");
1027 break;
1028 case 0xffff:
1029 ep_strbuf_append(strbuf, "True");
1030 break;
1031 default:
1032 ep_strbuf_append_printf(strbuf, "Invalid (0x%4x)", val);
1036 static void vvalue_strbuf_append_vector(emem_strbuf_t *strbuf, struct vt_vector val, struct vtype *type)
1038 const int elsize = (type->size == -1) ? (int)sizeof(struct data_blob) : type->size;
1039 unsigned i;
1040 guint8 *data = val.u.vt_ui1;
1041 ep_strbuf_append_c(strbuf, '[');
1042 for (i=0; i<val.len; i++) {
1043 if (i>0) {
1044 ep_strbuf_append_c(strbuf, ',');
1046 type->strbuf_append(strbuf, data);
1047 data += elsize;
1049 ep_strbuf_append_c(strbuf, ']');
1053 static struct vtype VT_TYPE[] = {
1054 {VT_EMPTY, "VT_EMPTY", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
1055 {VT_NULL, "VT_NULL", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
1056 {VT_I2, "VT_I2", 2, vvalue_tvb_get2, vvalue_strbuf_append_i2},
1057 {VT_I4, "VT_I4", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
1058 {VT_R4, "VT_R4", 4, vvalue_tvb_get4, vvalue_strbuf_append_r4},
1059 {VT_R8, "VT_R8", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
1060 {VT_CY, "VT_CY", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1061 {VT_DATE, "VT_DATE", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
1062 // {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_bstr, vvalue_strbuf_append_str},
1063 {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
1064 {VT_ERROR, "VT_ERROR", 8, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1065 {VT_BOOL, "VT_BOOL", 2, vvalue_tvb_get2, vvalue_strbuf_append_bool},
1066 {VT_VARIANT, "VT_VARIANT", -1, NULL, NULL},
1067 {VT_DECIMAL, "VT_DECIMAL", 16, NULL, NULL},
1068 {VT_I1, "VT_I1", 1, vvalue_tvb_get1, vvalue_strbuf_append_i1},
1069 {VT_UI1, "VT_UI1", 1, vvalue_tvb_get1, vvalue_strbuf_append_ui1},
1070 {VT_UI2, "VT_UI2", 2, vvalue_tvb_get2, vvalue_strbuf_append_ui2},
1071 {VT_UI4, "VT_UI4", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1072 {VT_I8, "VT_I8", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1073 {VT_UI8, "VT_UI8", 8, vvalue_tvb_get8, vvalue_strbuf_append_ui8},
1074 {VT_INT, "VT_INT", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
1075 {VT_UINT, "VT_UINT", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1076 {VT_LPSTR, "VT_LPSTR", -1, vvalue_tvb_lpstr, vvalue_strbuf_append_str},
1077 {VT_LPWSTR, "VT_LPWSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
1078 {VT_COMPRESSED_LPWSTR, "VT_COMPRESSED_LPWSTR", -1, NULL, vvalue_strbuf_append_str},
1079 {VT_FILETIME, "VT_FILETIME", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1080 {VT_BLOB, "VT_BLOB", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
1081 {VT_BLOB_OBJECT, "VT_BLOB_OBJECT", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
1082 {VT_CLSID, "VT_CLSID", 16, NULL, NULL},
1085 static struct vtype *vType_get_type(enum vType t) {
1086 unsigned i;
1087 t &= 0xFF;
1088 for (i=0; i<array_length(VT_TYPE); i++) {
1089 if (t == VT_TYPE[i].tag) {
1090 return &VT_TYPE[i];
1093 return NULL;
1096 static char *str_CBaseStorageVariant(struct CBaseStorageVariant *value, gboolean print_type)
1099 emem_strbuf_t *strbuf = ep_strbuf_new(NULL);
1100 if (value == NULL) {
1101 return "<NULL>";
1104 if (value->type == NULL) {
1105 return "<??""?>";
1108 if (print_type) {
1109 ep_strbuf_append(strbuf, value->type->str);
1111 if (value->vType & 0xFF00) {
1112 ep_strbuf_append_printf(strbuf, "[%d]", value->vValue.vt_vector.len);
1114 ep_strbuf_append(strbuf, ": ");
1117 switch (value->vType & 0xFF00) {
1118 case 0:
1119 value->type->strbuf_append(strbuf, &value->vValue);
1120 break;
1121 case VT_ARRAY:
1122 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_array.vData, value->type);
1123 break;
1124 case VT_VECTOR:
1125 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_vector, value->type);
1126 break;
1127 default:
1128 ep_strbuf_append(strbuf, "Invalid");
1131 return strbuf->str;
1134 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree _U_,
1135 struct CBaseStorageVariant *value, const char *text)
1137 int i, len;
1138 proto_item *ti, *ti_type, *ti_val;
1139 proto_tree *tree, *tr;
1140 enum vType baseType, highType;
1142 ZERO_STRUCT(*value);
1144 ti = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1145 tree = proto_item_add_subtree(ti, ett_CBaseStorageVariant);
1147 value->vType = tvb_get_letohs(tvb, offset);
1148 value->type = vType_get_type(value->vType);
1150 ti_type = proto_tree_add_text(tree, tvb, offset, 2, "vType: %s", value->type->str);
1151 offset += 2;
1153 value->vData1 = tvb_get_guint8(tvb, offset);
1154 proto_tree_add_text(tree, tvb, offset, 1, "vData1: %d", value->vData1);
1155 offset += 1;
1157 value->vData2 = tvb_get_guint8(tvb, offset);
1158 proto_tree_add_text(tree, tvb, offset, 1, "vData2: %d", value->vData2);
1159 offset += 1;
1161 baseType = value->vType & 0x00FF;
1162 highType = value->vType & 0xFF00;
1164 if (value->type == NULL) {
1165 goto not_supported;
1168 ti_val = proto_tree_add_text(tree, tvb, offset, 0, "vValue");
1170 switch (highType) {
1171 case VT_EMPTY:
1172 len = value->type->tvb_get(tvb, offset, &value->vValue.vt_single);
1173 offset += len;
1174 break;
1175 case VT_VECTOR:
1176 proto_item_append_text(ti_type, "|VT_VECTOR");
1177 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Vector);
1179 len = vvalue_tvb_vector(tvb, offset, &value->vValue.vt_vector, value->type);
1180 proto_tree_add_text(tr, tvb, offset, 4, "num: %d", value->vValue.vt_vector.len);
1181 offset += len;
1182 break;
1183 case VT_ARRAY: {
1184 guint16 cDims, fFeatures;
1185 guint32 cbElements, cElements, lLbound;
1186 int num = 1;
1188 proto_item_append_text(ti_type, "|VT_ARRAY");
1189 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Array);
1191 cDims = tvb_get_letohs(tvb, offset);
1192 proto_tree_add_text(tr, tvb, offset, 2, "cDims: %d", cDims);
1193 offset += 2;
1195 fFeatures = tvb_get_letohs(tvb, offset);
1196 proto_tree_add_text(tr, tvb, offset, 2, "fFeaturess: %d", fFeatures);
1197 offset += 2;
1199 cbElements = tvb_get_letohl(tvb, offset);
1200 proto_tree_add_text(tr, tvb, offset, 4, "cbElements: %d", cbElements);
1201 offset += 4;
1202 for (i=0; i<cDims; i++) {
1203 cElements = tvb_get_letohl(tvb, offset);
1204 lLbound = tvb_get_letohl(tvb, offset + 4);
1205 proto_tree_add_text(tr, tvb, offset, 8, "Rgsabound[%d]: (%d:%d)", i, cElements, lLbound);
1206 offset += 8;
1207 num *= cElements;
1210 len = vvalue_tvb_vector_internal(tvb , offset, &value->vValue.vt_array.vData, value->type, num);
1211 offset += len;
1212 break;
1214 default:
1215 proto_item_append_text(ti_type, "|0x%x", highType);
1217 proto_item_set_end(ti, tvb, offset);
1218 proto_item_set_end(ti_val, tvb, offset);
1220 proto_item_append_text(ti_val, " %s", str_CBaseStorageVariant(value, false));
1221 proto_item_append_text(ti, " %s", str_CBaseStorageVariant(value, true));
1223 goto done;
1225 not_supported:
1226 proto_item_append_text(ti, ": sorry, vType %02x not handled yet!", (unsigned)value->vType);
1227 done:
1228 return offset;
1231 enum {
1232 DBKIND_GUID_NAME = 0,
1233 DBKIND_GUID_PROPID = 1
1236 static int parse_CDbColId(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree, const char *text)
1238 guint32 eKind, ulId;
1239 e_guid_t guid;
1240 static const char *KIND[] = {"DBKIND_GUID_NAME", "DBKIND_GUID_PROPID"};
1242 proto_item *tree_item = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1243 proto_tree *tree = proto_item_add_subtree(tree_item, ett_CDbColId);
1245 eKind = tvb_get_letohl(tvb, offset);
1246 proto_tree_add_text(tree, tvb, offset, 4, "eKind: %s (%u)", eKind < 2 ? KIND[eKind] : "???", eKind);
1247 offset += 4;
1249 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingGuidAlign");
1251 offset = parse_guid(tvb, offset, tree, &guid, "GUID");
1253 ulId = tvb_get_letohl(tvb, offset);
1254 proto_tree_add_text(tree, tvb, offset, 4, "ulId: %d", ulId);
1255 offset += 4;
1257 if (eKind == DBKIND_GUID_NAME) {
1258 char *name;
1259 int len = ulId; //*2 ???
1260 name = tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
1261 proto_tree_add_text(tree, tvb, offset, len, "vString: \"%s\"", name);
1262 proto_item_append_text(tree_item, " \"%s\"", name);
1263 offset += len;
1264 } else if (eKind == DBKIND_GUID_PROPID) {
1265 proto_item_append_text(tree_item, " %08x", ulId);
1266 } else {
1267 proto_item_append_text(tree_item, "<INVALID>");
1270 proto_item_set_end(tree_item, tvb, offset);
1272 return offset;
1275 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1276 proto_tree *pad_tree, struct GuidPropertySet *propset,
1277 const char *fmt, ...)
1279 static const value_string EMPTY_VS[] = {{0, NULL}};
1280 const value_string *vs = (propset && propset->id_map) ? propset->id_map : EMPTY_VS;
1281 guint32 id, opt, status;
1282 struct CBaseStorageVariant value;
1283 proto_item *item;
1284 proto_tree *tree;
1285 const char *str;
1286 va_list ap;
1288 va_start(ap, fmt);
1289 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1290 va_end(ap);
1292 tree = proto_item_add_subtree(item, ett_CDbProp);
1294 id = tvb_get_letohl(tvb, offset);
1295 str = val_to_str(id, vs, "0x%08x");
1296 proto_tree_add_text(tree, tvb, offset, 4, "Id: %s (0x%08x)", str[0] == '0' ? "" : str, id);
1297 offset += 4;
1298 proto_item_append_text(item, " Id: %s", str);
1300 opt = tvb_get_letohl(tvb, offset);
1301 proto_tree_add_text(tree, tvb, offset, 4, "Options: %08x", opt);
1302 offset += 4;
1304 status = tvb_get_letohl(tvb, offset);
1305 proto_tree_add_text(tree, tvb, offset, 4, "Status: %08x", status);
1306 offset += 4;
1308 offset = parse_CDbColId(tvb, offset, tree, pad_tree, "colid");
1310 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &value, "vValue");
1312 str = str_CBaseStorageVariant(&value, true);
1313 proto_item_append_text(item, " %s", str);
1314 proto_item_set_end(item, tvb, offset);
1316 return offset;
1319 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1320 proto_tree *pad_tree, const char *fmt, ...)
1322 int i, num;
1323 e_guid_t guid;
1324 struct GuidPropertySet *pset;
1325 proto_item *item;
1326 proto_tree *tree;
1327 va_list ap;
1329 va_start(ap, fmt);
1330 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1331 va_end(ap);
1333 tree = proto_item_add_subtree(item, ett_CDbPropSet);
1335 offset = parse_guid(tvb, offset, tree, &guid, "guidPropertySet");
1337 pset = GuidPropertySet_find_guid(&guid);
1339 if (pset) {
1340 proto_item_append_text(item, " \"%s\" (%s)", pset->desc, pset->def);
1341 } else {
1342 const char *guid_str = guid_to_str(&guid);
1343 proto_item_append_text(item, " {%s}", guid_str);
1346 offset = parse_padding(tvb, offset, 4, pad_tree, "guidPropertySet");
1348 num = tvb_get_letohl(tvb, offset);
1349 proto_tree_add_text(tree, tvb, offset, 4, "cProperties: %d", num);
1350 offset += 4;
1351 proto_item_append_text(item, " Num: %d", num);
1353 for (i = 0; i<num; i++) {
1354 offset = parse_padding(tvb, offset, 4, pad_tree, "aProp[%d]", i);
1355 offset = parse_CDbProp(tvb, offset, tree, pad_tree, pset, "aProp[%d]", i);
1358 proto_item_set_end(item, tvb, offset);
1359 return offset;
1362 static int parse_PropertySetArray(tvbuff_t *tvb, int offset, int size_offset,
1363 proto_tree *parent_tree, proto_tree *pad_tree,
1364 const char *fmt, ...)
1366 const int offset_in = offset;
1367 guint32 size, num;
1368 int i;
1369 proto_tree *tree;
1370 proto_item *item;
1371 va_list ap;
1373 va_start(ap, fmt);
1374 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1375 va_end(ap);
1377 tree = proto_item_add_subtree(item, ett_CDbPropSet_Array);
1379 size = tvb_get_letohl(tvb, size_offset);
1380 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_Blob1, tvb,
1381 size_offset, 4, ENC_LITTLE_ENDIAN);
1383 num = tvb_get_letohl(tvb, offset);
1384 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_PropSets_num, tvb,
1385 offset, 4, ENC_LITTLE_ENDIAN);
1386 offset += 4;
1388 for (i = 0; i < (int)num; i++) {
1389 offset = parse_CDbPropSet(tvb, offset, tree, pad_tree, "PropertySet[%d]", i);
1392 proto_item_set_end(item, tvb, offset);
1393 DISSECTOR_ASSERT(offset - offset_in == (int)size);
1394 return offset;
1397 int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...)
1399 guint32 count, v, i;
1400 proto_item *item;
1402 va_list ap;
1404 va_start(ap, fmt);
1405 item = proto_tree_add_text_valist(tree, tvb, offset, 0, fmt, ap);
1406 va_end(ap);
1408 count = tvb_get_letohl(tvb, offset);
1409 offset += 4;
1411 proto_item_append_text(item, " Count %u [", count);
1412 for (i=0; i<count; i++) {
1413 v = tvb_get_letohl(tvb, offset);
1414 offset += 4;
1415 if (i>0) {
1416 proto_item_append_text(item, ",%u", v);
1417 } else {
1418 proto_item_append_text(item, "%u", v);
1421 proto_item_append_text(item, "]");
1422 return offset;
1425 /* 2.2.1.23 RANGEBOUNDARY */
1426 int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1427 proto_tree *pad_tree, const char *fmt, ...)
1429 guint32 ulType;
1430 guint8 labelPresent;
1431 proto_item *item;
1432 proto_tree *tree;
1433 struct CBaseStorageVariant prval;
1434 va_list ap;
1436 va_start(ap, fmt);
1437 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1438 tree = proto_item_add_subtree(item, ett_RANGEBOUNDARY);
1439 va_end(ap);
1441 ulType = tvb_get_letohl(tvb, offset);
1442 proto_tree_add_text(tree, tvb, offset, 4, "ulType 0x%08x", ulType);
1443 proto_item_append_text(item, ": Type 0x%08x", ulType);
1444 offset += 4;
1446 ZERO_STRUCT(prval);
1447 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &prval, "prVal");
1449 labelPresent = tvb_get_guint8(tvb, offset);
1450 proto_tree_add_text(tree, tvb, offset, 1, "labelPresent: %s", labelPresent ? "True" : "False");
1451 offset += 1;
1453 if (labelPresent) {
1454 guint32 ccLabel;
1455 const char *label;
1456 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingLabelPresent");
1458 ccLabel = tvb_get_letohl(tvb, offset);
1459 proto_tree_add_text(tree, tvb, offset, 4, "ccLabel: %u", ccLabel);
1460 offset += 4;
1462 label = tvb_get_unicode_string(tvb, offset, 2*ccLabel, ENC_LITTLE_ENDIAN);
1463 proto_tree_add_text(tree, tvb, offset, 2*ccLabel, "Label: \"%s\"", label);
1464 proto_item_append_text(item, " Label: \"%s\"", label);
1465 offset += 2*ccLabel;
1468 proto_item_append_text(item, " Val: %s", str_CBaseStorageVariant(&prval, true));
1470 proto_item_set_end(item, tvb, offset);
1471 return offset;
1475 /* 2.2.1.22 CRangeCategSpec */
1476 int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
1477 proto_tree *parent_tree, proto_tree *pad_tree,
1478 const char *fmt, ...)
1480 proto_item *item;
1481 proto_tree *tree;
1482 va_list ap;
1483 unsigned i;
1484 guint32 lcid, cRange;
1486 va_start(ap, fmt);
1487 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1488 tree = proto_item_add_subtree(item, ett_CRangeCategSpec);
1489 va_end(ap);
1491 lcid = tvb_get_letohl(tvb, offset);
1492 proto_tree_add_text(tree, tvb, offset, 4, "Lcid 0x%08x", lcid);
1493 offset += 4;
1495 cRange = tvb_get_letohl(tvb, offset);
1496 proto_tree_add_text(tree, tvb, offset, 4, "cRange 0x%08x", cRange);
1497 offset += 4;
1499 for (i=0; i<cRange; i++) {
1500 offset = parse_RANGEBOUNDARY(tvb, offset, tree, pad_tree, "aRangeBegin[%u]", i);
1504 proto_item_set_end(item, tvb, offset);
1505 return offset;
1508 /* 2.2.1.21 CCategSpec */
1509 int parse_CCategSpec(tvbuff_t *tvb, int offset,
1510 proto_tree *parent_tree, proto_tree *pad_tree,
1511 const char *fmt, ...)
1513 proto_item *item;
1514 proto_tree *tree;
1516 va_list ap;
1517 guint32 type;
1519 va_start(ap, fmt);
1520 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1521 tree = proto_item_add_subtree(item, ett_CCategSpec);
1522 va_end(ap);
1524 type = tvb_get_letohl(tvb, offset);
1525 proto_tree_add_text(tree, tvb, offset, 4, "Type 0x%08x", type);
1526 proto_item_append_text(item, " Type %u", type);
1527 offset += 4;
1529 offset = parse_CSort(tvb, offset, tree, pad_tree, "CSort");
1531 offset = parse_CRangeCategSpec(tvb, offset, tree, pad_tree, "CRangeCategSpec");
1533 proto_item_set_end(item, tvb, offset);
1534 return offset;
1537 /* 2.2.1.25 CAggregSpec */
1538 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
1539 proto_tree *parent_tree, proto_tree *pad_tree,
1540 const char *fmt, ...)
1542 proto_item *item;
1543 proto_tree *tree;
1544 va_list ap;
1545 guint8 type;
1546 guint32 ccAlias, idColumn, ulMaxNumToReturn, idRepresentative;
1547 const char *alias;
1549 va_start(ap, fmt);
1550 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1551 tree = proto_item_add_subtree(item, ett_CAggregSpec);
1552 va_end(ap);
1554 type = tvb_get_guint8(tvb, offset);
1555 proto_tree_add_text(tree, tvb, offset, 1, "type: %u", type);
1556 proto_item_append_text(item, "type: %u", type);
1557 offset += 1;
1559 offset = parse_padding(tvb, offset, 4, pad_tree, "padding");
1561 ccAlias = tvb_get_letohl(tvb, offset);
1562 proto_tree_add_text(tree, tvb, offset, 1, "ccAlias: %u", ccAlias);
1563 offset += 4;
1565 alias = tvb_get_unicode_string(tvb, offset, 2*ccAlias, ENC_LITTLE_ENDIAN);
1566 proto_tree_add_text(tree, tvb, offset, 2*ccAlias, "Alias: %s", alias);
1567 offset += 2*ccAlias;
1569 idColumn = tvb_get_letohl(tvb, offset);
1570 proto_tree_add_text(tree, tvb, offset, 1, "idColumn: %u", idColumn);
1571 offset += 4;
1572 /* Optional ???
1573 ulMaxNumToReturn, idRepresentative;
1575 fprintf(stderr, "WARNING, dont know if optional members are present!\n ");
1577 proto_item_set_end(item, tvb, offset);
1578 return offset;
1581 /* 2.2.1.24 CAggregSet */
1582 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
1583 proto_tree *parent_tree, proto_tree *pad_tree,
1584 const char *fmt, ...)
1586 guint32 cCount, i;
1587 proto_item *item;
1588 proto_tree *tree;
1590 va_list ap;
1592 va_start(ap, fmt);
1593 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1594 tree = proto_item_add_subtree(item, ett_CAggregSet);
1595 va_end(ap);
1597 cCount = tvb_get_letohl(tvb, offset);
1598 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1599 offset += 4;
1601 for (i=0; i<cCount; i++) {
1602 /* 2.2.1.25 CAggregSpec */
1603 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "AggregSpecs[%u]", i);
1606 proto_item_set_end(item, tvb, offset);
1607 return offset;
1610 /* 2.2.1.27 CAggregSortKey */
1611 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
1612 proto_tree *parent_tree, proto_tree *pad_tree,
1613 const char *fmt, ...)
1615 guint32 order;
1616 proto_item *item;
1617 proto_tree *tree;
1619 va_list ap;
1621 va_start(ap, fmt);
1622 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1623 tree = proto_item_add_subtree(item, ett_CAggregSortKey);
1624 va_end(ap);
1626 order = tvb_get_letohl(tvb, offset);
1627 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", order);
1628 offset += 4;
1630 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "ColumnSpec");
1632 proto_item_set_end(item, tvb, offset);
1633 return offset;
1637 /* 2.2.1.26 CSortAggregSet */
1638 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
1639 proto_tree *parent_tree, proto_tree *pad_tree,
1640 const char *fmt, ...)
1642 guint32 cCount, i;
1643 proto_item *item;
1644 proto_tree *tree;
1646 va_list ap;
1648 va_start(ap, fmt);
1649 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1650 tree = proto_item_add_subtree(item, ett_CSortAggregSet);
1651 va_end(ap);
1653 cCount = tvb_get_letohl(tvb, offset);
1654 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1655 offset += 4;
1657 for (i=0; i<cCount; i++) {
1658 /* 2.2.1.27 CAggregSortKey */
1659 offset = parse_CAggregSortKey(tvb, offset, tree, pad_tree, "SortKeys[%u]", i);
1662 proto_item_set_end(item, tvb, offset);
1663 return offset;
1666 enum CInGroupSortAggregSet_type {
1667 GroupIdDefault = 0x00, /* The default for all ranges. */
1668 GroupIdMinValue = 0x01, /*The first range in the parent's group.*/
1669 GroupIdNull = 0x02, /*The last range in the parent's group.*/
1670 GroupIdValue = 0x03,
1673 /* 2.2.1.29 CInGroupSortAggregSet */
1674 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
1675 proto_tree *parent_tree, proto_tree *pad_tree,
1676 const char *fmt, ...)
1678 proto_item *item;
1679 proto_tree *tree;
1680 va_list ap;
1681 enum CInGroupSortAggregSet_type type;
1683 va_start(ap, fmt);
1684 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1685 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSet);
1686 va_end(ap);
1688 type = tvb_get_guint8(tvb, offset);
1689 proto_tree_add_text(tree, tvb, offset, 1, "Type: 0x%02x", (unsigned)type);
1690 offset += 1;
1692 offset = parse_padding(tvb, offset, 4, pad_tree, "CInGroupSortAggregSet");
1694 if (type == GroupIdValue) {
1695 struct CBaseStorageVariant id;
1696 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &id, "inGroupId");
1699 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
1701 proto_item_set_end(item, tvb, offset);
1702 return offset;
1706 /* 2.2.1.28 CInGroupSortAggregSets */
1707 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
1708 proto_tree *parent_tree, proto_tree *pad_tree,
1709 const char *fmt, ...)
1711 guint32 cCount, i;
1712 proto_item *item;
1713 proto_tree *tree;
1715 va_list ap;
1717 va_start(ap, fmt);
1718 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1719 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSets);
1720 va_end(ap);
1722 cCount = tvb_get_letohl(tvb, offset);
1723 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1724 offset += 4;
1726 for (i=0; i<cCount; i++) {
1727 /* 2.2.1.29 CInGroupSortAggregSet */
1728 offset = parse_CInGroupSortAggregSet(tvb, offset, tree, pad_tree, "SortSets[%u]", i);
1731 proto_item_set_end(item, tvb, offset);
1732 return offset;
1735 /* 2.2.1.20 CCategorizationSpec */
1736 int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
1737 proto_tree *parent_tree, proto_tree *pad_tree,
1738 const char *fmt, ...)
1740 guint32 cMaxResults;
1741 proto_item *item;
1742 proto_tree *tree;
1744 va_list ap;
1746 va_start(ap, fmt);
1747 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1748 tree = proto_item_add_subtree(item, ett_CCategorizationSpec);
1749 va_end(ap);
1751 /* 2.2.1.18 CColumnSet */
1752 offset = parse_CColumnSet(tvb, offset, tree, "csColumns");
1754 /* 2.2.1.21 CCategSpec */
1755 offset = parse_CCategSpec(tvb, offset, tree, pad_tree, "Spec");
1757 /* 2.2.1.24 CAggregSet */
1758 offset = parse_CAggregSet(tvb, offset, tree, pad_tree, "AggregSet");
1760 /* 2.2.1.26 CSortAggregSet */
1761 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
1763 /* 2.2.1.28 CInGroupSortAggregSets */
1764 offset = parse_CInGroupSortAggregSets(tvb, offset, tree, pad_tree, "InGroupSortAggregSets");
1766 cMaxResults = tvb_get_letohl(tvb, offset);
1767 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", cMaxResults);
1768 offset += 4;
1770 proto_item_set_end(item, tvb, offset);
1771 return offset;
1774 int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
1775 proto_tree *parent_tree, proto_tree *pad_tree _U_,
1776 const char *fmt, ...)
1778 guint32 opt, maxres, timeout;
1779 proto_item *item;
1780 proto_tree *tree;
1782 va_list ap;
1784 va_start(ap, fmt);
1785 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1786 tree = proto_item_add_subtree(item, ett_CRowsetProperties);
1787 va_end(ap);
1789 opt = tvb_get_letohl(tvb, offset);
1790 proto_tree_add_text(tree, tvb, offset, 4, "uBooleanOptions: 0x%08x", opt);
1791 offset += 4;
1793 proto_tree_add_text(tree, tvb, offset, 4, "ulMaxOpenRows (ignored)");
1794 offset += 4;
1796 proto_tree_add_text(tree, tvb, offset, 4, "ulMemoryUsage (ignored)");
1797 offset += 4;
1799 maxres = tvb_get_letohl(tvb, offset);
1800 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", maxres);
1801 offset += 4;
1803 timeout = tvb_get_letohl(tvb, offset);
1804 proto_tree_add_text(tree, tvb, offset, 4, "cCmdTimeout: %u", timeout);
1805 offset += 4;
1807 proto_item_set_end(item, tvb, offset);
1808 return offset;
1811 int parse_CPidMapper(tvbuff_t *tvb, int offset,
1812 proto_tree *parent_tree, proto_tree *pad_tree,
1813 const char *fmt, ...)
1815 proto_item *item;
1816 proto_tree *tree;
1817 va_list ap;
1818 guint32 count, i;
1820 va_start(ap, fmt);
1821 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1822 tree = proto_item_add_subtree(item, ett_CPidMapper);
1823 va_end(ap);
1825 count = tvb_get_letohl(tvb, offset);
1826 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
1827 offset += 4;
1829 offset = parse_padding(tvb, offset, 8, pad_tree, "CPidMapper_PropSpec");
1831 for (i=0; i<count; i++) {
1832 struct CFullPropSpec v;
1833 ZERO_STRUCT(v);
1834 offset = parse_padding(tvb, offset, 4, pad_tree,
1835 "CPidMapper_PropSpec[%u]", i); //at begin or end of loop???
1836 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v, "PropSpec[%u]", i);
1839 proto_item_set_end(item, tvb, offset);
1840 return offset;
1843 /* Code to actually dissect the packets */
1845 static int dissect_CPMConnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
1847 proto_item *ti;
1848 proto_tree *tree;
1849 gint offset = 16;
1850 guint len;
1851 guint32 version;
1853 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
1854 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
1855 proto_item_set_text(ti, "CPMConnect%s", in ? "In" : "Out");
1856 col_append_str(pinfo->cinfo, COL_INFO, "Connect");
1858 version = tvb_get_letohl(tvb, offset);
1859 ti = proto_tree_add_item(tree, hf_mswsp_msg_Connect_Version, tvb,
1860 offset, 4, ENC_LITTLE_ENDIAN);
1861 if (version & 0xffff0000) {
1862 proto_item_append_text(ti, " 64 bit");
1864 switch (version & 0xffff) {
1865 case 0x102:
1866 proto_item_append_text(ti, " w2k8 or vista");
1867 break;
1868 case 0x109:
1869 proto_item_append_text(ti, " XP or w2k3, with Windows Search 4.0");
1870 break;
1871 case 0x700:
1872 proto_item_append_text(ti, " win7 or w2k8r2");
1873 break;
1875 offset += 4;
1877 if (in) {
1878 guint32 blob_size1_off, blob_size2_off;
1879 proto_tree *pad_tree;
1881 ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
1882 pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
1884 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_ClientIsRemote, tvb,
1885 offset, 4, ENC_LITTLE_ENDIAN);
1886 offset += 4;
1888 /* _cbBlob1 */
1889 blob_size1_off = offset;
1890 offset += 4;
1892 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcbBlob2");
1894 /* _cbBlob2 */
1895 blob_size2_off = offset;
1896 offset += 4;
1898 offset = parse_padding(tvb, offset, 16, pad_tree, "_padding");
1900 len = tvb_unicode_strsize(tvb, offset);
1901 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_MachineName, tvb,
1902 offset, len, ENC_UTF_16);
1903 /*This shouldnt be necessary, is this a bug or is there some GUI setting I've missed?*/
1904 proto_item_set_text(ti, "Remote machine: %s",
1905 tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN));
1906 offset += len;
1908 len = tvb_unicode_strsize(tvb, offset);
1909 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_UserName, tvb,
1910 offset, len, ENC_UTF_16);
1911 proto_item_set_text(ti, "User: %s", tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN));
1912 offset += len;
1914 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcPropSets");
1916 offset = parse_PropertySetArray(tvb, offset, blob_size1_off, tree, pad_tree, "PropSets");
1918 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingExtPropset");
1920 offset = parse_PropertySetArray(tvb, offset, blob_size2_off, tree, pad_tree, "ExtPropset");
1922 offset = parse_padding(tvb, offset, 8, pad_tree, "???");
1924 DISSECTOR_ASSERT(offset == (int)tvb_length(tvb));
1926 /* make "Padding" the last item */
1927 proto_tree_move_item(tree, ti, proto_tree_get_parent(pad_tree));
1928 } else {
1931 return tvb_length(tvb);
1934 static int dissect_CPMDisconnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
1936 col_append_str(pinfo->cinfo, COL_INFO, "Disconnect");
1937 return tvb_length(tvb);
1940 static int dissect_CPMCreateQuery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
1942 gint offset = 16;
1943 proto_item *ti;
1944 proto_tree *tree;
1946 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
1947 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
1949 proto_item_set_text(ti, "CPMCreateQuery%s", in ? "In" : "Out");
1950 col_append_str(pinfo->cinfo, COL_INFO, "CreateQuery");
1952 if (in) {
1953 proto_item *ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
1954 proto_tree *pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
1955 guint8 CColumnSetPresent, CRestrictionPresent, CSortSetPresent, CCategorizationSetPresent;
1956 guint32 size = tvb_get_letohl(tvb, offset);
1957 proto_tree_add_text(tree, tvb, offset, 4, "size");
1958 proto_tree_add_text(tree, tvb, offset, size, "ALL");
1959 offset += 4;
1961 CColumnSetPresent = tvb_get_guint8(tvb, offset);
1962 proto_tree_add_text(tree, tvb, offset, 1, "CColumnSetPresent: %s", CColumnSetPresent ? "True" : "False");
1963 offset += 1;
1965 if (CColumnSetPresent) {
1966 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCColumnSetPresent");
1967 offset = parse_CColumnSet(tvb, offset, tree, "CColumnSet");
1970 CRestrictionPresent = tvb_get_guint8(tvb, offset);
1971 proto_tree_add_text(tree, tvb, offset, 1, "CRestrictionPresent: %s", CColumnSetPresent ? "True" : "False");
1972 offset += 1;
1973 if (CRestrictionPresent) {
1974 offset = parse_CRestrictionArray(tvb, offset, tree, pad_tree, "RestrictionArray");
1977 CSortSetPresent = tvb_get_guint8(tvb, offset);
1978 proto_tree_add_text(tree, tvb, offset, 1, "CSortSetPresent: %s", CSortSetPresent ? "True" : "False");
1979 offset += 1;
1980 if (CSortSetPresent) {
1981 offset = parse_padding(tvb, offset, 4, tree, "paddingCSortSetPresent");
1983 proto_tree_add_text(tree, tvb, offset, 8, "XXX");
1984 offset += 8;
1986 offset = parse_CSortSet(tvb, offset, tree, pad_tree, "SortSet");
1989 CCategorizationSetPresent = tvb_get_guint8(tvb, offset);
1990 proto_tree_add_text(tree, tvb, offset, 1, "CCategorizationSetPresent: %s", CCategorizationSetPresent ? "True" : "False");
1991 offset += 1;
1993 if (CCategorizationSetPresent) {
1994 guint32 count, i;
1995 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCCategorizationSetPresent");
1996 /* 2.2.1.19 CCategorizationSet */
1997 count = tvb_get_letohl(tvb, offset);
1998 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
1999 offset += 4;
2000 for (i=0; i<count; i++) {
2001 offset = parse_CCategorizationSpec(tvb, offset, tree, pad_tree, "categories[%u]", i);
2005 offset = parse_padding(tvb, offset, 4, tree, "XXXX"); //XXX
2007 offset = parse_CRowsetProperties(tvb, offset, tree, pad_tree, "RowSetProperties");
2009 offset = parse_CPidMapper(tvb, offset, tree, pad_tree, "PidMapper");
2012 return tvb_length(tvb);
2015 static int dissect_CPMFreeCursor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2017 col_append_str(pinfo->cinfo, COL_INFO, "FreeCursor");
2018 return tvb_length(tvb);
2021 static int dissect_CPMGetRows(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2023 col_append_str(pinfo->cinfo, COL_INFO, "GetRows");
2024 return tvb_length(tvb);
2027 static int dissect_CPMRatioFinished(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2029 col_append_str(pinfo->cinfo, COL_INFO, "RatioFinished");
2030 return tvb_length(tvb);
2033 static int dissect_CPMCompareBmk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2035 col_append_str(pinfo->cinfo, COL_INFO, "CompareBmk");
2036 return tvb_length(tvb);
2039 static int dissect_CPMGetApproximatePosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2041 col_append_str(pinfo->cinfo, COL_INFO, "GetApproximatePosition");
2042 return tvb_length(tvb);
2045 static int dissect_CPMSetBindings(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2047 col_append_str(pinfo->cinfo, COL_INFO, "SetBindings");
2048 return tvb_length(tvb);
2051 static int dissect_CPMGetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2053 col_append_str(pinfo->cinfo, COL_INFO, "GetNotify");
2054 return tvb_length(tvb);
2057 static int dissect_CPMSendNotifyOut(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2059 col_append_str(pinfo->cinfo, COL_INFO, "SendNotify");
2060 return tvb_length(tvb);
2063 static int dissect_CPMGetQueryStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2065 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatus");
2066 return tvb_length(tvb);
2069 static int dissect_CPMCiState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2071 col_append_str(pinfo->cinfo, COL_INFO, "CiState");
2072 return tvb_length(tvb);
2075 static int dissect_CPMFetchValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2077 col_append_str(pinfo->cinfo, COL_INFO, "FetchValue");
2078 return tvb_length(tvb);
2081 static int dissect_CPMGetQueryStatusEx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2083 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatusEx");
2084 return tvb_length(tvb);
2087 static int dissect_CPMRestartPosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2089 col_append_str(pinfo->cinfo, COL_INFO, "RestartPosition");
2090 return tvb_length(tvb);
2093 static int dissect_CPMSetCatState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2095 col_append_str(pinfo->cinfo, COL_INFO, "SetCatState");
2096 return tvb_length(tvb);
2099 static int dissect_CPMGetRowsetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2101 col_append_str(pinfo->cinfo, COL_INFO, "GetRowsetNotify");
2102 return tvb_length(tvb);
2105 static int dissect_CPMFindIndices(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2107 col_append_str(pinfo->cinfo, COL_INFO, "FindIndices");
2108 return tvb_length(tvb);
2111 static int dissect_CPMSetScopePrioritization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2113 col_append_str(pinfo->cinfo, COL_INFO, "SetScopePrioritization");
2114 return tvb_length(tvb);
2117 static int dissect_CPMGetScopeStatistics(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2119 col_append_str(pinfo->cinfo, COL_INFO, "GetScopeStatistics");
2120 return tvb_length(tvb);
2125 dissect_mswsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean in)
2127 static const char *dbg_wait = NULL;
2128 static int wait_frame = -1;
2130 proto_tree *mswsp_tree = NULL;
2131 struct {
2132 guint32 msg;
2133 guint32 status;
2134 guint32 checksum;
2135 guint32 reserved;
2136 } hdr;
2137 int (*fn)(tvbuff_t*, packet_info*, proto_tree*, gboolean);
2139 if (tvb_length(tvb) < 16) {
2140 return 0;
2143 if (dbg_wait == NULL) {
2144 dbg_wait = getenv("DBG_FRAME");
2145 if (dbg_wait == NULL) {
2146 dbg_wait = "no";
2147 } else {
2148 wait_frame = atoi(dbg_wait);
2152 if ((int)pinfo->fd->num == wait_frame) {
2153 static volatile gboolean wait = 1;
2154 while(wait) {
2155 sleep(1);
2159 hdr.msg = tvb_get_letohl(tvb, 0);
2161 switch(hdr.msg) {
2162 case 0xC8:
2163 fn = dissect_CPMConnect;
2164 break;
2165 case 0xC9:
2166 fn = dissect_CPMDisconnect;
2167 break;
2168 case 0xCA:
2169 fn = dissect_CPMCreateQuery;
2170 break;
2171 case 0xCB:
2172 fn = dissect_CPMFreeCursor;
2173 break;
2174 case 0xCC:
2175 fn = dissect_CPMGetRows;
2176 break;
2177 case 0xCD:
2178 fn = dissect_CPMRatioFinished;
2179 break;
2180 case 0xCE:
2181 fn = dissect_CPMCompareBmk;
2182 break;
2183 case 0xCF:
2184 fn = dissect_CPMGetApproximatePosition;
2185 break;
2186 case 0xD0:
2187 fn = dissect_CPMSetBindings;
2188 break;
2189 case 0xD1:
2190 fn = dissect_CPMGetNotify;
2191 break;
2192 case 0xD2:
2193 fn = dissect_CPMSendNotifyOut;
2194 break;
2195 case 0xD7:
2196 fn = dissect_CPMGetQueryStatus;
2197 break;
2198 case 0xD9:
2199 fn = dissect_CPMCiState;
2200 break;
2201 case 0xE4:
2202 fn = dissect_CPMFetchValue;
2203 break;
2204 case 0xE7:
2205 fn = dissect_CPMGetQueryStatusEx;
2206 break;
2207 case 0xE8:
2208 fn = dissect_CPMRestartPosition;
2209 break;
2210 case 0xEC:
2211 fn = dissect_CPMSetCatState;
2212 break;
2213 case 0xF1:
2214 fn = dissect_CPMGetRowsetNotify;
2215 break;
2216 case 0xF2:
2217 fn = dissect_CPMFindIndices;
2218 break;
2219 case 0xF3:
2220 fn = dissect_CPMSetScopePrioritization;
2221 break;
2222 case 0xF4:
2223 fn = dissect_CPMGetScopeStatistics;
2224 break;
2225 default:
2226 return 0;
2229 hdr.status = tvb_get_letohl(tvb, 4);
2230 hdr.checksum = tvb_get_letohl(tvb, 8);
2232 /* col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS-WSP"); */
2233 col_append_str(pinfo->cinfo, COL_PROTOCOL, " WSP");
2234 /* col_clear(pinfo->cinfo, COL_INFO); */
2236 col_set_str(pinfo->cinfo, COL_INFO, "WSP ");
2237 col_append_str(pinfo->cinfo, COL_INFO, in ? "Request: " : "Response: ");
2239 if (tree) {
2240 proto_tree *hdr_tree;
2241 proto_item *ti, *hti;
2243 ti = proto_tree_add_item(tree, proto_mswsp, tvb, 0, -1, ENC_NA);
2244 mswsp_tree = proto_item_add_subtree(ti, ett_mswsp);
2246 hti = proto_tree_add_item(mswsp_tree, hf_mswsp_hdr, tvb, 0, 16, ENC_NA);
2247 hdr_tree = proto_item_add_subtree(hti, ett_mswsp_hdr);
2249 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_msg, tvb,
2250 0, 4, ENC_LITTLE_ENDIAN);
2251 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_status,
2252 tvb, 4, 4, ENC_LITTLE_ENDIAN);
2253 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_checksum,
2254 tvb, 8, 4, ENC_LITTLE_ENDIAN);
2255 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_reserved, tvb,
2256 12, 4, ENC_LITTLE_ENDIAN);
2259 fn(tvb, pinfo, mswsp_tree, in);
2261 /* Return the amount of data this dissector was able to dissect */
2262 return tvb_length(tvb);
2266 /* Register the protocol with Wireshark */
2268 /* this format is require because a script is used to build the C function
2269 that calls all the protocol registration.
2272 void
2273 proto_register_mswsp(void)
2275 module_t *mswsp_module;
2277 /* Setup list of header fields See Section 1.6.1 for details*/
2278 static const value_string msg_ids[] = {
2279 {0x000000C8, "CPMConnect"}, /* In/Out */
2280 {0x000000C9, "CPMDisconnect"},
2281 {0x000000CA, "CPMCreateQuery"}, /* In/Out */
2282 {0x000000CB, "CPMFreeCursor"}, /* In/Out */
2283 {0x000000CC, "CPMGetRows"}, /* In/Out */
2284 {0x000000CD, "CPMRatioFinished"}, /* In/Out */
2285 {0x000000CE, "CPMCompareBmk"}, /* In/Out */
2286 {0x000000CF, "CPMGetApproximatePosition"}, /* In/Out */
2287 {0x000000D0, "CPMSetBindingsIn"},
2288 {0x000000D1, "CPMGetNotify"},
2289 {0x000000D2, "CPMSendNotifyOut"},
2290 {0x000000D7, "CPMGetQueryStatusIn"}, /* In/Out */
2291 {0x000000D9, "CPMCiStateInOut"},
2292 {0x000000E4, "CPMFetchValue"}, /* In/Out */
2293 {0x000000E7, "CPMGetQueryStatusEx"}, /* In/Out */
2294 {0x000000E8, "CPMRestartPositionIn"},
2295 {0x000000EC, "CPMSetCatStateIn"}, /* (not supported) */
2296 {0x000000F1, "CPMGetRowsetNotify"}, /* In/Out */
2297 {0x000000F2, "CPMFindIndices"}, /* In/Out */
2298 {0x000000F3, "CPMSetScopePrioritization"}, /* In/Out */
2299 {0x000000F4, "CPMGetScopeStatistics"}, /* In/Out */
2301 static hf_register_info hf[] = {
2302 { &hf_mswsp_hdr,
2303 { "Header", "mswsp.hdr",
2304 FT_NONE, BASE_NONE , NULL, 0,
2305 "Message header", HFILL }
2307 { &hf_mswsp_hdr_msg,
2308 { "Msg id", "mswsp.hdr.id",
2309 FT_UINT32, BASE_HEX , VALS(msg_ids), 0,
2310 "Message id", HFILL }
2312 { &hf_mswsp_hdr_status,
2313 { "Status", "mswsp.hdr.status",
2314 FT_UINT32, BASE_HEX , NULL, 0,
2315 "Status", HFILL }
2317 { &hf_mswsp_hdr_checksum,
2318 { "checksum", "mswsp.hdr.checksum",
2319 FT_UINT32, BASE_HEX , NULL, 0,
2320 "Checksum", HFILL }
2322 { &hf_mswsp_hdr_reserved,
2323 { "Reserved", "mswsp.hdr.reserved",
2324 FT_UINT32, BASE_HEX , NULL, 0,
2325 "Reserved", HFILL }
2327 { &hf_mswsp_msg,
2328 { "msg", "mswsp.msg",
2329 FT_NONE, BASE_NONE , NULL, 0,
2330 "Message", HFILL }
2332 { &hf_mswsp_msg_Connect_Version,
2333 { "Version", "mswsp.Connect.version",
2334 FT_UINT32, BASE_HEX , NULL, 0,
2335 "Version",HFILL }
2337 { &hf_mswsp_msg_ConnectIn_ClientIsRemote,
2338 { "Remote", "mswsp.ConnectIn.isRemote",
2339 FT_BOOLEAN, BASE_HEX , NULL, 0,
2340 "Client is remote",HFILL }
2342 { &hf_mswsp_msg_ConnectIn_Blob1,
2343 { "Size", "mswsp.ConnectIn.propset.size",
2344 FT_UINT32, BASE_DEC , NULL, 0,
2345 "Size of PropSet fields",HFILL }
2347 { &hf_mswsp_msg_ConnectIn_Blob2,
2348 { "Size", "mswsp.ConnectIn.extpropset.size",
2349 FT_UINT32, BASE_DEC , NULL, 0,
2350 "Size of ExtPropSet fields",HFILL }
2352 { &hf_mswsp_msg_ConnectIn_MachineName,
2353 { "Remote machine", "mswsp.ConnectIn.machine",
2354 FT_STRINGZ, BASE_NONE , NULL, 0,
2355 "Name of remote machine",HFILL }
2357 { &hf_mswsp_msg_ConnectIn_UserName,
2358 { "User", "mswsp.ConnectIn.user",
2359 FT_STRINGZ, BASE_NONE , NULL, 0,
2360 "Name of remote user",HFILL }
2362 { &hf_mswsp_msg_ConnectIn_PropSets_num,
2363 { "Num", "mswsp.ConnectIn.propset.num",
2364 FT_UINT32, BASE_DEC , NULL, 0,
2365 "Number of Property Sets", HFILL }
2367 { &hf_mswsp_msg_ConnectIn_ExtPropSets_num,
2368 { "Num", "mswsp.ConnectIn.extpropset.num",
2369 FT_UINT32, BASE_DEC , NULL, 0,
2370 "Number of extended Property Sets", HFILL }
2375 /* Setup protocol subtree array */
2376 static gint *ett[] = {
2377 &ett_mswsp,
2378 &ett_mswsp_hdr,
2379 &ett_mswsp_msg,
2380 &ett_mswsp_pad,
2381 &ett_mswsp_property_restriction,
2382 &ett_CRestrictionArray,
2383 &ett_CBaseStorageVariant,
2384 &ett_CBaseStorageVariant_Vector,
2385 &ett_CBaseStorageVariant_Array,
2386 &ett_CDbColId,
2387 &ett_GUID,
2388 &ett_CDbProp,
2389 &ett_CDbPropSet,
2390 &ett_CDbPropSet_Array,
2391 &ett_CRestriction,
2392 &ett_CNodeRestriction,
2393 &ett_CPropertyRestriction,
2394 &ett_CCoercionRestriction,
2395 &ett_CContentRestriction,
2396 &ett_RANGEBOUNDARY,
2397 &ett_CRangeCategSpec,
2398 &ett_CCategSpec,
2399 &ett_CAggregSpec,
2400 &ett_CAggregSet,
2401 &ett_CCategorizationSpec,
2402 &ett_CAggregSortKey,
2403 &ett_CSortAggregSet,
2404 &ett_CInGroupSortAggregSet,
2405 &ett_CInGroupSortAggregSets,
2406 &ett_CRowsetProperties,
2407 &ett_CFullPropSpec,
2408 &ett_CPidMapper,
2409 &ett_CSort,
2410 &ett_CSortSet,
2413 int i;
2415 /* Register the protocol name and description */
2416 proto_mswsp = proto_register_protocol("Windows Search Protocol",
2417 "MS-WSP", "mswsp");
2419 /* Required function calls to register the header fields and subtrees used */
2420 proto_register_field_array(proto_mswsp, hf, array_length(hf));
2421 proto_register_subtree_array(ett, array_length(ett));
2423 for (i=0; i<(int)array_length(GuidPropertySet); i++) {
2424 guids_add_guid(&GuidPropertySet[i].guid, GuidPropertySet[i].def);
2428 /* Register preferences module (See Section 2.6 for more on preferences) */
2429 /* (Registration of a prefs callback is not required if there are no */
2430 /* prefs-dependent registration functions (eg: a port pref). */
2431 /* See proto_reg_handoff below. */
2432 /* If a prefs callback is not needed, use NULL instead of */
2433 /* proto_reg_handoff_mswsp in the following). */
2434 mswsp_module = prefs_register_protocol(proto_mswsp,
2435 proto_reg_handoff_mswsp);
2437 /* Register preferences module under preferences subtree.
2438 Use this function instead of prefs_register_protocol if you want to group
2439 preferences of several protocols under one preferences subtree.
2440 Argument subtree identifies grouping tree node name, several subnodes can be
2441 specified using slash '/' (e.g. "OSI/X.500" - protocol preferences will be
2442 accessible under Protocols->OSI->X.500-><PROTOSHORTNAME> preferences node.
2444 /* mswsp_module = prefs_register_protocol_subtree(subtree, */
2445 /* proto_mswsp, proto_reg_handoff_mswsp); */
2447 /* Register a sample preference */
2448 prefs_register_bool_preference(mswsp_module, "show_hex",
2449 "Display numbers in Hex",
2450 "Enable to display numerical values in hexadecimal.",
2451 &gPREF_HEX);
2453 /* Register a sample port preference */
2454 prefs_register_uint_preference(mswsp_module, "tcp.port", "mswsp TCP Port",
2455 " mswsp TCP port if other than the default",
2456 10, &gPORT_PREF);
2459 static int dissect_mswsp_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2460 smb_info_t *si = pinfo->private_data;
2461 gboolean in = si->request;
2463 smb_transact_info_t *tri = (si->sip->extra_info_type == SMB_EI_TRI) ? si->sip->extra_info : NULL;
2464 smb_fid_info_t *fid_info = NULL;
2465 GSList *iter;
2467 fprintf(stderr, "dissect_mswsp_smb %s frame: %d tid: %d op: %02x ",
2468 in ? "Request" : "Response",
2469 pinfo->fd->num, si->tid, si->cmd);
2471 if (tri == NULL) {
2472 fprintf(stderr, " extra_info_type: %d\n", si->sip->extra_info_type);
2473 return 0;
2476 for (iter = si->ct->GSL_fid_info; iter; iter = g_slist_next(iter)) {
2477 smb_fid_info_t *info = iter->data;
2478 if ((info->tid == si->tid) && (info->fid == tri->fid)) {
2479 fid_info = info;
2480 break;
2484 if ((fid_info->fsi == NULL) || (fid_info->fsi->filename == NULL)) {
2485 fprintf(stderr, " no %s\n", fid_info->fsi ? "filename" : "fsi");
2486 return 0;
2489 fprintf(stderr, " file: %s\n", fid_info->fsi->filename);
2491 if (strcasecmp(fid_info->fsi->filename, "\\MsFteWds") != 0) {
2492 return 0;
2495 return dissect_mswsp(tvb, pinfo, tree, in);
2499 static int dissect_mswsp_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2500 smb2_info_t *si = pinfo->private_data;
2501 gboolean in = !(si->flags & SMB2_FLAGS_RESPONSE);
2503 //si->tree->share_type == SMB2_SHARE_TYPE_PIPE
2504 //si->tree->connect_frame
2506 fprintf(stderr, "dissect_mswsp %d <> %d : op %02x %s %s type: %d extra_file: %s\n",
2507 pinfo->fd->num, si->tree ? (int)si->tree->connect_frame : -1,
2508 si->opcode,
2509 pinfo->dcerpc_procedure_name ? pinfo->dcerpc_procedure_name : "<NULL>",
2510 in ? "Request" : "Response", si->tree ? si->tree->share_type : -1,
2511 si->saved ? (si->saved->extra_info_type == SMB2_EI_FILENAME ? (char*)si->saved->extra_info : "<OTHER>") : "<NONE>"
2515 if (strcmp(pinfo->dcerpc_procedure_name, "File: MsFteWds") != 0) {
2516 return 0;
2519 return dissect_mswsp(tvb, pinfo, tree, in);
2524 /* If this dissector uses sub-dissector registration add a registration routine.
2525 This exact format is required because a script is used to find these
2526 routines and create the code that calls these routines.
2528 If this function is registered as a prefs callback (see prefs_register_protocol
2529 above) this function is also called by preferences whenever "Apply" is pressed;
2530 In that case, it should accommodate being called more than once.
2532 Simple form of proto_reg_handoff_mswsp which can be used if there are
2533 no prefs-dependent registration function calls.
2536 void
2537 proto_reg_handoff_mswsp(void)
2539 heur_dissector_add("smb_transact", dissect_mswsp_smb, proto_mswsp);
2540 heur_dissector_add("smb2_heur_subdissectors", dissect_mswsp_smb2, proto_mswsp);
2545 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2547 * Local variables:
2548 * c-basic-offset: 4
2549 * tab-width: 8
2550 * indent-tabs-mode: nil
2551 * End:
2553 * vi: set shiftwidth=4 tabstop=8 expandtab:
2554 * :indentSize=4:tabSize=8:noTabs=true: