HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-mswsp.c
blob3a0a43bd9cb9c8ebec418cd5b4499a03c2cce751
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 static int parse_padding(tvbuff_t *tvb, int offset, int alignment, proto_tree *pad_tree, const char *fmt, ...)
119 if (offset % alignment) {
120 const int padding = alignment - (offset % alignment);
121 va_list ap;
122 proto_item *ti;
123 va_start(ap, fmt);
124 ti = proto_tree_add_text_valist(pad_tree, tvb, offset, padding, fmt, ap);
125 va_end(ap);
127 proto_item_append_text(ti, " (%d)", padding);
128 offset += padding;
130 DISSECTOR_ASSERT((offset % alignment) == 0);
131 return offset;
134 static int parse_guid(tvbuff_t *tvb, int offset, proto_tree *tree, e_guid_t *guid, const char *text)
136 const char *guid_str, *name, *bytes;
137 proto_tree *tr;
138 proto_item *ti;
140 tvb_get_letohguid(tvb, offset, guid);
141 guid_str = guid_to_str(guid);
142 name = guids_get_guid_name(guid);
144 ti = proto_tree_add_text(tree, tvb, offset, 16, "%s: %s {%s}", text, name ? name : "", guid_str);
145 tr = proto_item_add_subtree(ti, ett_GUID);
147 proto_tree_add_text(tr, tvb, offset, 4, "time-low: 0x%08x", guid->data1);
148 offset += 4;
149 proto_tree_add_text(tr, tvb, offset, 2, "time-mid: 0x%04x", guid->data2);
150 offset += 2;
151 proto_tree_add_text(tr, tvb, offset, 2, "time-high-and-version: 0x%04x", guid->data3);
152 offset += 2;
153 proto_tree_add_text(tr, tvb, offset, 1, "clock_seq_hi_and_reserved: 0x%02x", guid->data4[0]);
154 offset += 1;
155 proto_tree_add_text(tr, tvb, offset, 1, "clock_seq_low: 0x%02x", guid->data4[1]);
156 offset += 1;
157 bytes = bytestring_to_str(&guid->data4[2], 6, ':');
158 proto_tree_add_text(tr, tvb, offset, 6, "node: %s", bytes);
159 offset += 6;
161 return offset;
164 /*****************************************************************************************/
165 /* 2.2.1.1 CBaseStorageVariant */
166 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
167 struct CBaseStorageVariant *value, const char *text);
169 /* 2.2.1.2 CFullPropSpec */
170 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pad_tree,
171 struct CFullPropSpec *v, const char *fmt, ...);
173 /* 2.2.1.3 CContentRestriction */
174 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
175 proto_tree *pad_tree, struct CContentRestriction *v,
176 const char *fmt, ...);
177 /* 2.2.1.6 CNodeRestriction */
178 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pad_tree,
179 struct CNodeRestriction *v, const char* fmt, ...);
181 /* 2.2.1.7 CPropertyRestriction */
182 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
183 proto_tree *pad_tree, struct CPropertyRestriction *v,
184 const char *fmt, ...);
186 /* 2.2.1.8 CReuseWhere */
187 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
188 proto_tree *pad_tree _U_, struct CReuseWhere *v,
189 const char *fmt, ...);
191 /* 2.2.1.10 CSort */
192 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
193 proto_tree *pad_tree _U_,
194 const char *fmt, ...);
196 /* 2.2.1.12 CCoercionRestriction */
197 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
198 proto_tree *pad_tree, struct CCoercionRestriction *v,
199 const char *fmt, ...);
200 /* 2.2.1.16 CRestrictionArray */
201 static int parse_CRestrictionArray(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
202 const char *fmt, ...);
204 /* 2.2.1.17 CRestriction */
205 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
206 struct CRestriction *v, const char *fmt, ...);
208 /* 2.2.1.18 CColumnSet */
209 static int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...);
211 /* 2.2.1.20 CCategorizationSpec */
212 static int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
213 proto_tree *parent_tree, proto_tree *pad_tree,
214 const char *fmt, ...);
216 /* 2.2.1.21 CCategSpec */
217 static int parse_CCategSpec(tvbuff_t *tvb, int offset,
218 proto_tree *parent_tree, proto_tree *pad_tree,
219 const char *fmt, ...);
221 /* 2.2.1.22 CRangeCategSpec */
222 static int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
223 proto_tree *parent_tree, proto_tree *pad_tree,
224 const char *fmt, ...);
226 /* 2.2.1.23 RANGEBOUNDARY */
227 static int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
228 proto_tree *pad_tree, const char *fmt, ...);
230 /* 2.2.1.24 CAggregSet */
231 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
232 proto_tree *parent_tree, proto_tree *pad_tree,
233 const char *fmt, ...);
235 /* 2.2.1.25 CAggregSpec */
236 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
237 proto_tree *parent_tree, proto_tree *pad_tree,
238 const char *fmt, ...);
240 /* 2.2.1.26 CSortAggregSet */
241 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
242 proto_tree *parent_tree, proto_tree *pad_tree,
243 const char *fmt, ...);
245 /* 2.2.1.27 CAggregSortKey */
246 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
247 proto_tree *parent_tree, proto_tree *pad_tree,
248 const char *fmt, ...);
250 /* 2.2.1.28 CInGroupSortAggregSets */
251 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
252 proto_tree *parent_tree, proto_tree *pad_tree,
253 const char *fmt, ...);
255 /* 2.2.1.29 CInGroupSortAggregSet */
256 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
257 proto_tree *parent_tree, proto_tree *pad_tree,
258 const char *fmt, ...);
259 /* 2.2.1.30 CDbColId */
260 static int parse_CDbColId(tvbuff_t *tvb, int offset,
261 proto_tree *parent_tree, proto_tree *pad_tree, const char *text);
263 /* 2.2.1.31 CDbProp */
264 struct GuidPropertySet;
265 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
266 proto_tree *pad_tree, struct GuidPropertySet *propset,
267 const char *fmt, ...);
269 /* 2.2.1.32 CDbPropSet */
270 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
271 proto_tree *pad_tree, const char *fmt, ...);
272 /* 2.2.1.33 CPidMapper */
273 static int parse_CPidMapper(tvbuff_t *tvb, int offset,
274 proto_tree *parent_tree, proto_tree *pad_tree,
275 const char *fmt, ...);
277 /* 2.2.1.41 CRowsetProperties */
278 static int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
279 proto_tree *parent_tree, proto_tree *pad_tree,
280 const char *fmt, ...);
282 /* 2.2.1.43 CSortSet */
283 static int parse_CSortSet(tvbuff_t *tvb, int offset,
284 proto_tree *parent_tree, proto_tree *pad_tree,
285 const char *fmt, ...);
288 2.2.1.4 CInternalPropertyRestriction
289 2.2.1.5 CNatLanguageRestriction
290 2.2.1.9 CScopeRestriction
291 2.2.1.11 CVectorRestriction
292 2.2.1.13 CRelDocRestriction
293 2.2.1.14 CProbRestriction
294 2.2.1.15 CFeedbackRestriction
295 2.2.1.19 CCategorizationSet
296 2.2.1.34 CColumnGroupArray
297 2.2.1.35 CColumnGroup
298 2.2.1.36 SProperty
299 2.2.1.37 CRowSeekAt
300 2.2.1.38 CRowSeekAtRatio
301 2.2.1.39 CRowSeekByBookmark
302 2.2.1.40 CRowSeekNext
303 2.2.1.42 CRowVariant
304 2.2.1.44 CTableColumn
305 2.2.1.45 SERIALIZEDPROPERTYVALUE
306 2.2.1.46 CCompletionCategSp
309 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
310 proto_tree *pad_tree _U_,
311 const char *fmt, ...)
313 guint32 col, ord, ind, lcid;
315 proto_item *item;
316 proto_tree *tree;
318 va_list ap;
320 va_start(ap, fmt);
321 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
322 va_end(ap);
323 tree = proto_item_add_subtree(item, ett_CSort);
325 col = tvb_get_letohl(tvb, offset);
326 proto_tree_add_text(tree, tvb, offset, 4, "column: %u", col);
327 offset += 4;
329 ord = tvb_get_letohl(tvb, offset);
330 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", ord);
331 offset += 4;
333 ind = tvb_get_letohl(tvb, offset);
334 proto_tree_add_text(tree, tvb, offset, 4, "individual: %u", ind);
335 offset += 4;
337 lcid = tvb_get_letohl(tvb, offset);
338 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", lcid);
339 offset += 4;
341 proto_item_set_end(item, tvb, offset);
342 return offset;
345 static int parse_CSortSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
346 proto_tree *pad_tree,
347 const char *fmt, ...)
349 guint32 count, i;
351 proto_item *item;
352 proto_tree *tree;
354 va_list ap;
356 va_start(ap, fmt);
357 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
358 va_end(ap);
359 tree = proto_item_add_subtree(item, ett_CSortSet);
361 count = tvb_get_letohl(tvb, offset);
362 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
363 offset += 4;
365 for (i=0; i<count; i++) {
366 offset = parse_padding(tvb, offset, 4, tree, "padding_sortArray[%u]", i);
367 offset = parse_CSort(tvb, offset, tree, pad_tree, "sortArray[%u]", i);
370 proto_item_set_end(item, tvb, offset);
371 return offset;
375 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset,
376 proto_tree *parent_tree, proto_tree *pad_tree,
377 struct CFullPropSpec *v, const char *fmt, ...)
379 static const value_string KIND[] = {
380 {0, "PRSPEC_LPWSTR"},
381 {1, "PRSPEC_PROPID"},
382 {0, NULL}
385 const char *guid_str;
386 proto_item *item;
387 proto_tree *tree;
388 va_list ap;
390 va_start(ap, fmt);
391 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
392 va_end(ap);
393 tree = proto_item_add_subtree(item, ett_CFullPropSpec);
395 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingPropSet");
397 offset = parse_guid(tvb, offset, tree, &v->guid, "GUID");
398 guid_str = guids_resolve_guid_to_str(&v->guid );
399 proto_item_append_text(item, " {%s}", guid_str);
401 v->kind = tvb_get_letohl(tvb, offset);
402 proto_tree_add_text(tree, tvb, offset, 4, "ulKind: %s ", val_to_str(v->kind, KIND, "(Unknown: 0x%x)"));
403 offset += 4;
405 v->u.propid = tvb_get_letohl(tvb, offset);
406 proto_tree_add_text(tree, tvb, offset, 4, "propid: %u ", v->u.propid);
407 offset += 4;
409 if (v->kind == PRSPEC_LPWSTR) {
410 int len = 2*v->u.propid;
411 v->u.name = tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
412 proto_tree_add_text(tree, tvb, offset, len, "name: \"%s\"", v->u.name);
413 proto_item_append_text(item, " \"%s\"", v->u.name);
414 offset += len;
415 } else if (v->kind == PRSPEC_PROPID) {
416 proto_item_append_text(item, " 0x%08x", v->u.propid);
417 } else {
418 proto_item_append_text(item, "<INVALID>");
421 proto_item_set_end(item, tvb, offset);
422 return offset;
427 static const value_string PR_VALS[] = {
428 {PRLT, "PRLT"},
429 {PRLE, "PRLE"},
430 {PRGT, "PRGT"},
431 {PRGE, "PRGE"},
432 {PREQ, "PREQ"},
433 {PRNE, "PRNE"},
434 {PRRE, "PRRE"},
435 {PRAllBits, "PRAllBits"},
436 {PRSomeBits, "PRSomeBits"},
437 {PRAll, "PRAll"},
438 {PRSome, "PRSome"},
442 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
443 proto_tree *pad_tree, struct CPropertyRestriction *v,
444 const char *fmt, ...)
446 proto_tree *tree;
447 proto_item *item;
448 const char *str;
449 va_list ap;
451 va_start(ap, fmt);
452 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
453 va_end(ap);
455 tree = proto_item_add_subtree(item, ett_CPropertyRestriction);
457 v->relop = tvb_get_letohl(tvb, offset);
458 str = val_to_str(v->relop, PR_VALS, "0x%04x");
459 proto_tree_add_text(tree, tvb, offset, 4, "relop: %s (0x%04x)",
460 str[0]=='\0' ? "" : str, v->relop);
461 proto_item_append_text(item, " Op: %s", str);
462 offset += 4;
464 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
466 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &v->prval, "prval");
468 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_lcid");
470 v->lcid = tvb_get_letohl(tvb, offset);
471 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", v->lcid);
472 offset += 4;
474 proto_item_set_end(item, tvb, offset);
476 return offset;
479 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
480 proto_tree *pad_tree, struct CCoercionRestriction *v,
481 const char *fmt, ...)
483 proto_tree *tree;
484 proto_item *item;
485 va_list ap;
487 va_start(ap, fmt);
488 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
489 va_end(ap);
491 tree = proto_item_add_subtree(item, ett_CCoercionRestriction);
493 v->value = tvb_get_letohl(tvb, offset);
494 proto_tree_add_text(tree, tvb, offset, 4, "value: %g", (double)v->value);
495 offset += 4;
497 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &v->child, "child");
499 proto_item_set_end(item, tvb, offset);
500 return offset;
503 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
504 proto_tree *pad_tree, struct CContentRestriction *v,
505 const char *fmt, ...)
507 proto_tree *tree;
508 proto_item *item;
509 va_list ap;
510 guint32 cc;
511 const char *str;
514 va_start(ap, fmt);
515 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
516 va_end(ap);
518 tree = proto_item_add_subtree(item, ett_CContentRestriction);
520 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
522 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding1");
524 cc = tvb_get_letohl(tvb, offset);
525 proto_tree_add_text(tree, tvb, offset, 4, "cc: %u", cc);
526 offset += 4;
528 // str = tvb_get_ephemeral_string_enc(tvb, offset, 2*cc, ENC_UTF_16);
529 str = tvb_get_unicode_string(tvb, offset, 2*cc, ENC_LITTLE_ENDIAN);
530 v->phrase = se_strdup(str);
531 proto_tree_add_text(tree, tvb, offset, 2*cc, "phrase: %s", str);
532 offset += 2*cc;
534 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding2");
536 v->lcid = tvb_get_letohl(tvb, offset);
537 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", v->lcid);
538 offset += 4;
540 v->method = tvb_get_letohl(tvb, offset);
541 proto_tree_add_text(tree, tvb, offset, 4, "method: 0x%08x", v->method);
542 offset += 4;
544 proto_item_set_end(item, tvb, offset);
545 return offset;
549 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
550 proto_tree *pad_tree _U_, struct CReuseWhere *v,
551 const char *fmt, ...)
553 proto_item *item;
554 va_list ap;
557 va_start(ap, fmt);
558 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
559 va_end(ap);
561 v->whereId = tvb_get_letohl(tvb, offset);
562 offset += 4;
564 proto_item_append_text(item, " Id: %u", v->whereId);
566 proto_item_set_end(item, tvb, offset);
567 return offset;
570 static value_string RT_VALS[] = {
571 {RTNone, "RTNone"},
572 {RTAnd, "RTAnd"},
573 {RTOr, "RTOr"},
574 {RTNot, "RTNot"},
575 {RTContent, "RTContent"},
576 {RTProperty, "RTProperty"},
577 {RTProximity, "RTProximity"},
578 {RTVector, ""},
579 {RTNatLanguage, "RTNatLanguage"},
580 {RTScope, "RTScope"},
581 {RTCoerce_Add, "RTCoerce_Add"},
582 {RTCoerce_Multiply, "RTCoerce_Multiply"},
583 {RTCoerce_Absolute, "RTCoerce_Absolute"},
584 {RTProb, "RTProb"},
585 {RTFeedback, "RTFeedback"},
586 {RTReldoc, "RTReldoc"},
587 {RTReuseWhere, "RTReuseWhere"},
588 {RTInternalProp, "RTInternalProp"},
589 {RTPhrase, "RTInternalProp"},
592 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
593 struct CRestriction *v, const char *fmt, ...)
595 proto_tree *tree;
596 proto_item *item;
597 const char *str;
598 va_list ap;
600 va_start(ap, fmt);
601 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
602 va_end(ap);
604 tree = proto_item_add_subtree(item, ett_CRestriction);
607 v->ulType = tvb_get_letohl(tvb, offset);
608 str = val_to_str(v->ulType, RT_VALS, "0x%.8x");
609 proto_tree_add_text(tree, tvb, offset, 4, "ulType: %s (0x%.8x)",
610 str[0] == '0' ? "" : str, v->ulType);
611 proto_item_append_text(item, " Type: %s", str);
612 offset += 4;
614 v->Weight = tvb_get_letohl(tvb, offset);
615 proto_tree_add_text(tree, tvb, offset, 4, "Weight: %u", v->ulType);
616 offset += 4;
618 switch(v->ulType) {
619 case RTNone:
620 break;
621 case RTAnd:
622 case RTOr:
623 case RTProximity:
624 case RTPhrase:
626 v->u.RTAnd = ep_alloc(sizeof(struct CNodeRestriction)); //XXX
627 offset = parse_CNodeRestriction(tvb, offset, tree, pad_tree, v->u.RTAnd, "CNodeRestriction");
628 break;
630 case RTNot:
632 v->u.RTNot = ep_alloc(sizeof(struct CRestriction)); //XXX
633 offset = parse_CRestriction(tvb, offset, tree, pad_tree,
634 v->u.RTNot, "CRestriction");
635 break;
637 case RTProperty:
639 v->u.RTProperty = ep_alloc(sizeof(struct CPropertyRestriction)); //XXX
640 offset = parse_CPropertyRestriction(tvb, offset, tree, pad_tree,
641 v->u.RTProperty, "CPropertyRestriction");
642 break;
644 case RTCoerce_Add:
645 case RTCoerce_Multiply:
646 case RTCoerce_Absolute:
648 v->u.RTCoerce_Add = ep_alloc(sizeof(struct CCoercionRestriction)); //XXX
649 offset = parse_CCoercionRestriction(tvb, offset, tree, pad_tree,
650 v->u.RTCoerce_Add, "CCoercionRestriction");
651 break;
653 case RTContent: {
654 v->u.RTContent = ep_alloc(sizeof(struct CContentRestriction)); //XXX
655 offset = parse_CContentRestriction(tvb, offset, tree, pad_tree,
656 v->u.RTContent, "CContentRestriction");
657 break;
659 case RTReuseWhere: {
660 v->u.RTReuseWhere = ep_alloc(sizeof(struct CReuseWhere)); //XXX
661 offset = parse_CReuseWhere(tvb, offset, tree, pad_tree,
662 v->u.RTReuseWhere, "CReuseWhere");
663 break;
665 default:
666 fprintf(stderr, "CRestriciont 0x%08x not Supported\n", v->ulType);
667 proto_item_append_text(item, " Not supported!");
670 proto_item_set_end(item, tvb, offset);
671 return offset;
674 static int parse_CRestrictionArray(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
675 const char *fmt, ...)
677 guint8 present, count;
679 proto_tree *tree;
680 proto_item *item;
681 va_list ap;
683 va_start(ap, fmt);
684 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
685 va_end(ap);
686 tree = proto_item_add_subtree(item, ett_CRestrictionArray);
688 pad_tree = tree; //XXX
690 count = tvb_get_guint8(tvb, offset);
691 proto_tree_add_text(tree, tvb, offset, 1, "count: %u", count);
692 offset += 1;
694 present = tvb_get_guint8(tvb, offset);
695 proto_tree_add_text(tree, tvb, offset, 1, "present: %u", present);
696 offset += 1;
698 if (present) {
699 unsigned i;
700 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCRestrictionPresent");
702 for (i=0; i<count; i++) {
703 struct CRestriction r;
704 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "Restriction[%d]", i);
707 proto_item_set_end(item, tvb, offset);
708 return offset;
711 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
712 proto_tree *pad_tree, struct CNodeRestriction *v,
713 const char *fmt, ...)
715 proto_tree *tree;
716 proto_item *item;
717 unsigned i;
718 va_list ap;
720 va_start(ap, fmt);
721 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
722 va_end(ap);
723 tree = proto_item_add_subtree(item, ett_CNodeRestriction);
725 v->cNode = tvb_get_letohl(tvb, offset);
726 proto_tree_add_text(tree, tvb, offset, 4, "cNode: %u", v->cNode);
727 offset += 4;
729 for (i=0; i<v->cNode; i++) {
730 struct CRestriction r;
731 ZERO_STRUCT(r);
732 // offset = parse_padding(tvb, offset, 4, tree, "padding_paNode[%u]", i); /*at begin or end of loop ????*/
733 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "paNode[%u]", i);
734 offset = parse_padding(tvb, offset, 4, tree, "padding_paNode[%u]", i); /*at begin or end of loop ????*/
736 // offset = parse_padding(tvb, offset, 4, pad_tree, "paNode[%u]", i); /*at begin or end of loop ????*/
739 proto_item_set_end(item, tvb, offset);
740 return offset;
744 /*****************************************************************************************/
746 static int vvalue_tvb_get0(tvbuff_t *tvb _U_, int offset _U_, void *val _U_)
748 return 0;
751 static int vvalue_tvb_get1(tvbuff_t *tvb, int offset, void *val)
753 guint8 *ui1 = (guint8*)val;
754 *ui1 = tvb_get_guint8(tvb, offset);
755 return 1;
758 static int vvalue_tvb_get2(tvbuff_t *tvb , int offset, void *val)
760 guint16 *ui2 = (guint16*)val;
761 *ui2 = tvb_get_letohs(tvb, offset);
762 return 2;
765 static int vvalue_tvb_get4(tvbuff_t *tvb , int offset, void *val)
767 guint32 *ui4 = (guint32*)val;
768 *ui4 = tvb_get_letohl(tvb, offset);
769 return 4;
772 static int vvalue_tvb_get8(tvbuff_t *tvb , int offset, void *val)
774 guint64 *ui8 = (guint64*)val;
775 *ui8 = tvb_get_letoh64(tvb, offset);
776 return 8;
779 static int vvalue_tvb_blob(tvbuff_t *tvb , int offset, void *val)
781 struct data_blob *blob = (struct data_blob*)val;
782 guint32 len = tvb_get_letohl(tvb, offset);
783 const guint8 *data = tvb_get_ptr(tvb, offset + 4, len);
785 blob->size = len;
786 blob->data = se_memdup(data, len);
788 return 4 + len;
791 static int vvalue_tvb_bstr(tvbuff_t *tvb , int offset, void *val)
793 struct data_str *str = (struct data_str*)val;
794 guint32 len = tvb_get_letohl(tvb, offset);
795 const void *ptr = tvb_get_ptr(tvb, offset + 4, len);
797 //XXX this might be UTF-16
798 str->len = len;
799 str->str = se_strndup(ptr, len);
800 return 4 + len;
803 static int vvalue_tvb_lpstr(tvbuff_t *tvb , int offset, void *val)
805 struct data_str *str = (struct data_str*)val;
806 gint len;
808 str->len = tvb_get_letohl(tvb, offset);
809 str->str = tvb_get_seasonal_stringz(tvb, offset + 4, &len);
810 /* XXX test str->len == len */
811 return 4 + len;
814 static int vvalue_tvb_lpwstr(tvbuff_t *tvb , int offset, void *val)
816 struct data_str *str = (struct data_str*)val;
817 gint len;
818 gchar *ptr;
820 str->len = tvb_get_letohl(tvb, offset);
822 ptr = tvb_get_ephemeral_unicode_stringz(tvb, offset + 4, &len, ENC_LITTLE_ENDIAN);
823 str->str = se_strdup (ptr);
825 return 4 + len;
828 static int vvalue_tvb_vector_internal(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type, int num)
830 const int offset_in = offset;
831 const gboolean varsize = (type->size == -1);
832 const int elsize = varsize ? (int)sizeof(struct data_blob) : type->size;
833 guint8 *data = se_alloc(elsize * num);
834 int len, i;
836 val->len = num;
837 val->u.vt_ui1 = data;
838 DISSECTOR_ASSERT((void*)&val->u == ((void*)&val->u.vt_ui1));
840 for (i=0; i<num; i++) {
841 len = type->tvb_get(tvb, offset, data);
842 data += elsize;
843 offset += len;
844 if (varsize && (offset % 4) ) { /* at begin or end of loop ??? */
845 int padding = 4 - (offset % 4);
846 offset += padding;
849 return offset - offset_in;
852 static int vvalue_tvb_vector(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type)
854 const int num = tvb_get_letohl(tvb, offset);
855 return 4 + vvalue_tvb_vector_internal(tvb , offset+4, val, type, num);
858 static void vvalue_strbuf_append_null(emem_strbuf_t *strbuf _U_, void *ptr _U_)
861 static void vvalue_strbuf_append_i1(emem_strbuf_t *strbuf, void *ptr)
863 gint8 i1 = *(gint8*)ptr;
864 ep_strbuf_append_printf(strbuf, "%d", (int)i1);
867 static void vvalue_strbuf_append_i2(emem_strbuf_t *strbuf, void *ptr)
869 gint16 i2 = *(gint16*)ptr;
870 ep_strbuf_append_printf(strbuf, "%d", (int)i2);
873 static void vvalue_strbuf_append_i4(emem_strbuf_t *strbuf, void *ptr)
875 gint32 i4 = *(gint32*)ptr;
876 ep_strbuf_append_printf(strbuf, "%d", i4);
879 static void vvalue_strbuf_append_i8(emem_strbuf_t *strbuf, void *ptr)
881 gint64 i8 = *(gint64*)ptr;
882 ep_strbuf_append_printf(strbuf, "%ld", i8);
885 static void vvalue_strbuf_append_ui1(emem_strbuf_t *strbuf, void *ptr)
887 guint8 ui1 = *(guint8*)ptr;
888 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui1);
891 static void vvalue_strbuf_append_ui2(emem_strbuf_t *strbuf, void *ptr)
893 guint16 ui2 = *(guint16*)ptr;
894 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui2);
897 static void vvalue_strbuf_append_ui4(emem_strbuf_t *strbuf, void *ptr)
899 guint32 ui4 = *(guint32*)ptr;
900 ep_strbuf_append_printf(strbuf, "%d", ui4);
903 static void vvalue_strbuf_append_ui8(emem_strbuf_t *strbuf, void *ptr)
905 guint64 ui8 = *(guint64*)ptr;
906 ep_strbuf_append_printf(strbuf, "%lu", ui8);
909 static void vvalue_strbuf_append_r4(emem_strbuf_t *strbuf, void *ptr)
911 float r4 = *(float*)ptr;
912 ep_strbuf_append_printf(strbuf, "%g", (double)r4);
915 static void vvalue_strbuf_append_r8(emem_strbuf_t *strbuf, void *ptr)
917 double r8 = *(double*)ptr;
918 ep_strbuf_append_printf(strbuf, "%g", r8);
921 static void vvalue_strbuf_append_str(emem_strbuf_t *strbuf, void *ptr)
923 struct data_str *str = (struct data_str*)ptr;
924 ep_strbuf_append_printf(strbuf, "\"%s\"", str->str);
927 static void vvalue_strbuf_append_blob(emem_strbuf_t *strbuf, void *ptr)
929 struct data_blob *blob = (struct data_blob*)ptr;
930 ep_strbuf_append_printf(strbuf, "size: %d", (int)blob->size);
933 static void vvalue_strbuf_append_bool(emem_strbuf_t *strbuf, void *ptr)
935 guint16 val = *(guint*)ptr;
936 switch (val) {
937 case 0:
938 ep_strbuf_append(strbuf, "False");
939 break;
940 case 0xffff:
941 ep_strbuf_append(strbuf, "True");
942 break;
943 default:
944 ep_strbuf_append_printf(strbuf, "Invalid (0x%4x)", val);
948 static void vvalue_strbuf_append_vector(emem_strbuf_t *strbuf, struct vt_vector val, struct vtype *type)
950 const int elsize = (type->size == -1) ? (int)sizeof(struct data_blob) : type->size;
951 unsigned i;
952 guint8 *data = val.u.vt_ui1;
953 ep_strbuf_append_c(strbuf, '[');
954 for (i=0; i<val.len; i++) {
955 if (i>0) {
956 ep_strbuf_append_c(strbuf, ',');
958 type->strbuf_append(strbuf, data);
959 data += elsize;
961 ep_strbuf_append_c(strbuf, ']');
965 static struct vtype VT_TYPE[] = {
966 {VT_EMPTY, "VT_EMPTY", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
967 {VT_NULL, "VT_NULL", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
968 {VT_I2, "VT_I2", 2, vvalue_tvb_get2, vvalue_strbuf_append_i2},
969 {VT_I4, "VT_I4", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
970 {VT_R4, "VT_R4", 4, vvalue_tvb_get4, vvalue_strbuf_append_r4},
971 {VT_R8, "VT_R8", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
972 {VT_CY, "VT_CY", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
973 {VT_DATE, "VT_DATE", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
974 // {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_bstr, vvalue_strbuf_append_str},
975 {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
976 {VT_ERROR, "VT_ERROR", 8, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
977 {VT_BOOL, "VT_BOOL", 2, vvalue_tvb_get2, vvalue_strbuf_append_bool},
978 {VT_VARIANT, "VT_VARIANT", -1, NULL, NULL},
979 {VT_DECIMAL, "VT_DECIMAL", 16, NULL, NULL},
980 {VT_I1, "VT_I1", 1, vvalue_tvb_get1, vvalue_strbuf_append_i1},
981 {VT_UI1, "VT_UI1", 1, vvalue_tvb_get1, vvalue_strbuf_append_ui1},
982 {VT_UI2, "VT_UI2", 2, vvalue_tvb_get2, vvalue_strbuf_append_ui2},
983 {VT_UI4, "VT_UI4", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
984 {VT_I8, "VT_I8", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
985 {VT_UI8, "VT_UI8", 8, vvalue_tvb_get8, vvalue_strbuf_append_ui8},
986 {VT_INT, "VT_INT", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
987 {VT_UINT, "VT_UINT", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
988 {VT_LPSTR, "VT_LPSTR", -1, vvalue_tvb_lpstr, vvalue_strbuf_append_str},
989 {VT_LPWSTR, "VT_LPWSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
990 {VT_COMPRESSED_LPWSTR, "VT_COMPRESSED_LPWSTR", -1, NULL, vvalue_strbuf_append_str},
991 {VT_FILETIME, "VT_FILETIME", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
992 {VT_BLOB, "VT_BLOB", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
993 {VT_BLOB_OBJECT, "VT_BLOB_OBJECT", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
994 {VT_CLSID, "VT_CLSID", 16, NULL, NULL},
997 static struct vtype *vType_get_type(enum vType t) {
998 unsigned i;
999 t &= 0xFF;
1000 for (i=0; i<array_length(VT_TYPE); i++) {
1001 if (t == VT_TYPE[i].tag) {
1002 return &VT_TYPE[i];
1005 return NULL;
1008 static char *str_CBaseStorageVariant(struct CBaseStorageVariant *value, gboolean print_type)
1011 emem_strbuf_t *strbuf = ep_strbuf_new(NULL);
1012 if (value == NULL) {
1013 return "<NULL>";
1016 if (value->type == NULL) {
1017 return "<??""?>";
1020 if (print_type) {
1021 ep_strbuf_append(strbuf, value->type->str);
1023 if (value->vType & 0xFF00) {
1024 ep_strbuf_append_printf(strbuf, "[%d]", value->vValue.vt_vector.len);
1026 ep_strbuf_append(strbuf, ": ");
1029 switch (value->vType & 0xFF00) {
1030 case 0:
1031 value->type->strbuf_append(strbuf, &value->vValue);
1032 break;
1033 case VT_ARRAY:
1034 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_array.vData, value->type);
1035 break;
1036 case VT_VECTOR:
1037 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_vector, value->type);
1038 break;
1039 default:
1040 ep_strbuf_append(strbuf, "Invalid");
1043 return strbuf->str;
1046 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree _U_,
1047 struct CBaseStorageVariant *value, const char *text)
1049 int i, len;
1050 proto_item *ti, *ti_type, *ti_val;
1051 proto_tree *tree, *tr;
1052 enum vType baseType, highType;
1054 ZERO_STRUCT(*value);
1056 ti = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1057 tree = proto_item_add_subtree(ti, ett_CBaseStorageVariant);
1059 value->vType = tvb_get_letohs(tvb, offset);
1060 value->type = vType_get_type(value->vType);
1062 ti_type = proto_tree_add_text(tree, tvb, offset, 2, "vType: %s", value->type->str);
1063 offset += 2;
1065 value->vData1 = tvb_get_guint8(tvb, offset);
1066 proto_tree_add_text(tree, tvb, offset, 1, "vData1: %d", value->vData1);
1067 offset += 1;
1069 value->vData2 = tvb_get_guint8(tvb, offset);
1070 proto_tree_add_text(tree, tvb, offset, 1, "vData2: %d", value->vData2);
1071 offset += 1;
1073 baseType = value->vType & 0x00FF;
1074 highType = value->vType & 0xFF00;
1076 if (value->type == NULL) {
1077 goto not_supported;
1080 ti_val = proto_tree_add_text(tree, tvb, offset, 0, "vValue");
1082 switch (highType) {
1083 case VT_EMPTY:
1084 len = value->type->tvb_get(tvb, offset, &value->vValue.vt_single);
1085 offset += len;
1086 break;
1087 case VT_VECTOR:
1088 proto_item_append_text(ti_type, "|VT_VECTOR");
1089 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Vector);
1091 len = vvalue_tvb_vector(tvb, offset, &value->vValue.vt_vector, value->type);
1092 proto_tree_add_text(tr, tvb, offset, 4, "num: %d", value->vValue.vt_vector.len);
1093 offset += len;
1094 break;
1095 case VT_ARRAY: {
1096 guint16 cDims, fFeatures;
1097 guint32 cbElements, cElements, lLbound;
1098 int num = 1;
1100 proto_item_append_text(ti_type, "|VT_ARRAY");
1101 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Array);
1103 cDims = tvb_get_letohs(tvb, offset);
1104 proto_tree_add_text(tr, tvb, offset, 2, "cDims: %d", cDims);
1105 offset += 2;
1107 fFeatures = tvb_get_letohs(tvb, offset);
1108 proto_tree_add_text(tr, tvb, offset, 2, "fFeaturess: %d", fFeatures);
1109 offset += 2;
1111 cbElements = tvb_get_letohl(tvb, offset);
1112 proto_tree_add_text(tr, tvb, offset, 4, "cbElements: %d", cbElements);
1113 offset += 4;
1114 for (i=0; i<cDims; i++) {
1115 cElements = tvb_get_letohl(tvb, offset);
1116 lLbound = tvb_get_letohl(tvb, offset + 4);
1117 proto_tree_add_text(tr, tvb, offset, 8, "Rgsabound[%d]: (%d:%d)", i, cElements, lLbound);
1118 offset += 8;
1119 num *= cElements;
1122 len = vvalue_tvb_vector_internal(tvb , offset, &value->vValue.vt_array.vData, value->type, num);
1123 offset += len;
1124 break;
1126 default:
1127 proto_item_append_text(ti_type, "|0x%x", highType);
1129 proto_item_set_end(ti, tvb, offset);
1130 proto_item_set_end(ti_val, tvb, offset);
1132 proto_item_append_text(ti_val, " %s", str_CBaseStorageVariant(value, false));
1133 proto_item_append_text(ti, " %s", str_CBaseStorageVariant(value, true));
1135 goto done;
1137 not_supported:
1138 proto_item_append_text(ti, ": sorry, vType %02x not handled yet!", (unsigned)value->vType);
1139 done:
1140 return offset;
1143 enum {
1144 DBKIND_GUID_NAME = 0,
1145 DBKIND_GUID_PROPID = 1
1148 static int parse_CDbColId(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree, const char *text)
1150 guint32 eKind, ulId;
1151 e_guid_t guid;
1152 static const char *KIND[] = {"DBKIND_GUID_NAME", "DBKIND_GUID_PROPID"};
1154 proto_item *tree_item = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1155 proto_tree *tree = proto_item_add_subtree(tree_item, ett_CDbColId);
1157 eKind = tvb_get_letohl(tvb, offset);
1158 proto_tree_add_text(tree, tvb, offset, 4, "eKind: %s (%u)", eKind < 2 ? KIND[eKind] : "???", eKind);
1159 offset += 4;
1161 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingGuidAlign");
1163 offset = parse_guid(tvb, offset, tree, &guid, "GUID");
1165 ulId = tvb_get_letohl(tvb, offset);
1166 proto_tree_add_text(tree, tvb, offset, 4, "ulId: %d", ulId);
1167 offset += 4;
1169 if (eKind == DBKIND_GUID_NAME) {
1170 char *name;
1171 int len = ulId; //*2 ???
1172 name = tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
1173 proto_tree_add_text(tree, tvb, offset, len, "vString: \"%s\"", name);
1174 proto_item_append_text(tree_item, " \"%s\"", name);
1175 offset += len;
1176 } else if (eKind == DBKIND_GUID_PROPID) {
1177 proto_item_append_text(tree_item, " %08x", ulId);
1178 } else {
1179 proto_item_append_text(tree_item, "<INVALID>");
1182 proto_item_set_end(tree_item, tvb, offset);
1184 return offset;
1187 struct GuidPropertySet {
1188 e_guid_t guid;
1189 const char *def;
1190 const char *desc;
1191 const value_string *id_map;
1194 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1195 proto_tree *pad_tree, struct GuidPropertySet *propset,
1196 const char *fmt, ...)
1198 static const value_string EMPTY_VS[] = {{0, NULL}};
1199 const value_string *vs = (propset && propset->id_map) ? propset->id_map : EMPTY_VS;
1200 guint32 id, opt, status;
1201 struct CBaseStorageVariant value;
1202 proto_item *item;
1203 proto_tree *tree;
1204 const char *str;
1205 va_list ap;
1207 va_start(ap, fmt);
1208 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1209 va_end(ap);
1211 tree = proto_item_add_subtree(item, ett_CDbProp);
1213 id = tvb_get_letohl(tvb, offset);
1214 str = val_to_str(id, vs, "0x%08x");
1215 proto_tree_add_text(tree, tvb, offset, 4, "Id: %s (0x%08x)", str[0] == '0' ? "" : str, id);
1216 offset += 4;
1217 proto_item_append_text(item, " Id: %s", str);
1219 opt = tvb_get_letohl(tvb, offset);
1220 proto_tree_add_text(tree, tvb, offset, 4, "Options: %08x", opt);
1221 offset += 4;
1223 status = tvb_get_letohl(tvb, offset);
1224 proto_tree_add_text(tree, tvb, offset, 4, "Status: %08x", status);
1225 offset += 4;
1227 offset = parse_CDbColId(tvb, offset, tree, pad_tree, "colid");
1229 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &value, "vValue");
1231 str = str_CBaseStorageVariant(&value, true);
1232 proto_item_append_text(item, " %s", str);
1233 proto_item_set_end(item, tvb, offset);
1235 return offset;
1238 /* 2.2.1.31.1 */
1239 static const value_string DBPROPSET_FSCIFRMWRK_EXT_IDS[] = {
1240 {0x02, "DBPROP_CI_CATALOG_NAME"},
1241 {0x03, "DBPROP_CI_INCLUDE_SCOPES"},
1242 {0x04, "DBPROP_CI_SCOPE_FLAGS"},
1243 {0x07, "DBPROP_CI_QUERY_TYPE"},
1244 {0, NULL}
1247 static const value_string DBPROPSET_QUERYEXT_IDS[] = {
1248 {0x02, "DBPROP_USECONTENTINDEX"},
1249 {0x03, "DBPROP_DEFERNONINDEXEDTRIMMING"},
1250 {0x04, "DBPROP_USEEXTENDEDDBTYPES"},
1251 {0x05, "DBPROP_IGNORENOISEONLYCLAUSES"},
1252 {0x06, "DBPROP_GENERICOPTIONS_STRING"},
1253 {0x07, "DBPROP_FIRSTROWS"},
1254 {0x08, "DBPROP_DEFERCATALOGVERIFICATION"},
1255 {0x0a, "DBPROP_GENERATEPARSETREE"},
1256 {0x0c, "DBPROP_FREETEXTANYTERM"},
1257 {0x0d, "DBPROP_FREETEXTUSESTEMMING"},
1258 {0x0e, "DBPROP_IGNORESBRI"},
1259 {0x10, "DBPROP_ENABLEROWSETEVENTS"},
1260 {0, NULL}
1263 static const value_string DBPROPSET_CIFRMWRKCORE_EXT_IDS[] = {
1264 {0x02, "DBPROP_MACHINE"},
1265 {0x03, "DBPROP_CLIENT_CLSID"},
1266 {0, NULL}
1269 static const value_string DBPROPSET_MSIDXS_ROWSETEXT_IDS[] = {
1270 {0x02, "MSIDXSPROP_ROWSETQUERYSTATUS"},
1271 {0x03, "MSIDXSPROP_COMMAND_LOCALE_STRING"},
1272 {0x04, "MSIDXSPROP_QUERY_RESTRICTION"},
1273 {0x05, "MSIDXSPROP_PARSE_TREE"},
1274 {0x06, "MSIDXSPROP_MAX_RANK"},
1275 {0x07, "MSIDXSPROP_RESULTS_FOUND"},
1276 {0, NULL}
1279 static struct GuidPropertySet GuidPropertySet[] = {
1280 {{0xa9bd1526, 0x6a80, 0x11d0, {0x8c, 0x9d, 0x00, 0x20, 0xaf, 0x1d, 0x74, 0x0e}},
1281 "DBPROPSET_FSCIFRMWRK_EXT", "File system content index framework",
1282 DBPROPSET_FSCIFRMWRK_EXT_IDS},
1283 {{0xa7ac77ed, 0xf8d7, 0x11ce, {0xa7, 0x98, 0x00, 0x20, 0xf8, 0x00, 0x80, 0x25}},
1284 "DBPROPSET_QUERYEXT", "Query extension",
1285 DBPROPSET_QUERYEXT_IDS},
1286 {{0xafafaca5, 0xb5d1, 0x11d0, {0x8c, 0x62, 0x00, 0xc0, 0x4f, 0xc2, 0xdb, 0x8d}},
1287 "DBPROPSET_CIFRMWRKCORE_EXT", "Content index framework core",
1288 DBPROPSET_CIFRMWRKCORE_EXT_IDS},
1289 {{0xAA6EE6B0, 0xE828, 0x11D0, {0xB2, 0x3E, 0x00, 0xAA, 0x00, 0x47, 0xFC, 0x01}},
1290 "DBPROPSET_MSIDXS_ROWSETEXT", "???",
1291 DBPROPSET_MSIDXS_ROWSETEXT_IDS},
1294 static struct GuidPropertySet *GuidPropertySet_find_guid(const e_guid_t *guid)
1296 unsigned i;
1297 for (i=0; i<array_length(GuidPropertySet); i++) {
1298 if (guid_cmp(&GuidPropertySet[i].guid, guid) == 0) {
1299 return &GuidPropertySet[i];
1302 return NULL;
1305 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1306 proto_tree *pad_tree, const char *fmt, ...)
1308 int i, num;
1309 e_guid_t guid;
1310 struct GuidPropertySet *pset;
1311 proto_item *item;
1312 proto_tree *tree;
1313 va_list ap;
1315 va_start(ap, fmt);
1316 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1317 va_end(ap);
1319 tree = proto_item_add_subtree(item, ett_CDbPropSet);
1321 offset = parse_guid(tvb, offset, tree, &guid, "guidPropertySet");
1323 pset = GuidPropertySet_find_guid(&guid);
1325 if (pset) {
1326 proto_item_append_text(item, " \"%s\" (%s)", pset->desc, pset->def);
1327 } else {
1328 const char *guid_str = guid_to_str(&guid);
1329 proto_item_append_text(item, " {%s}", guid_str);
1332 offset = parse_padding(tvb, offset, 4, pad_tree, "guidPropertySet");
1334 num = tvb_get_letohl(tvb, offset);
1335 proto_tree_add_text(tree, tvb, offset, 4, "cProperties: %d", num);
1336 offset += 4;
1337 proto_item_append_text(item, " Num: %d", num);
1339 for (i = 0; i<num; i++) {
1340 offset = parse_padding(tvb, offset, 4, pad_tree, "aProp[%d]", i);
1341 offset = parse_CDbProp(tvb, offset, tree, pad_tree, pset, "aProp[%d]", i);
1344 proto_item_set_end(item, tvb, offset);
1345 return offset;
1348 static int parse_PropertySetArray(tvbuff_t *tvb, int offset, int size_offset,
1349 proto_tree *parent_tree, proto_tree *pad_tree,
1350 const char *fmt, ...)
1352 const int offset_in = offset;
1353 guint32 size, num;
1354 int i;
1355 proto_tree *tree;
1356 proto_item *item;
1357 va_list ap;
1359 va_start(ap, fmt);
1360 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1361 va_end(ap);
1363 tree = proto_item_add_subtree(item, ett_CDbPropSet_Array);
1365 size = tvb_get_letohl(tvb, size_offset);
1366 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_Blob1, tvb,
1367 size_offset, 4, ENC_LITTLE_ENDIAN);
1369 num = tvb_get_letohl(tvb, offset);
1370 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_PropSets_num, tvb,
1371 offset, 4, ENC_LITTLE_ENDIAN);
1372 offset += 4;
1374 for (i = 0; i < (int)num; i++) {
1375 offset = parse_CDbPropSet(tvb, offset, tree, pad_tree, "PropertySet[%d]", i);
1378 proto_item_set_end(item, tvb, offset);
1379 DISSECTOR_ASSERT(offset - offset_in == (int)size);
1380 return offset;
1383 int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...)
1385 guint32 count, v, i;
1386 proto_item *item;
1388 va_list ap;
1390 va_start(ap, fmt);
1391 item = proto_tree_add_text_valist(tree, tvb, offset, 0, fmt, ap);
1392 va_end(ap);
1394 count = tvb_get_letohl(tvb, offset);
1395 offset += 4;
1397 proto_item_append_text(item, " Count %u [", count);
1398 for (i=0; i<count; i++) {
1399 v = tvb_get_letohl(tvb, offset);
1400 offset += 4;
1401 if (i>0) {
1402 proto_item_append_text(item, ",%u", v);
1403 } else {
1404 proto_item_append_text(item, "%u", v);
1407 proto_item_append_text(item, "]");
1408 return offset;
1411 /* 2.2.1.23 RANGEBOUNDARY */
1412 int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1413 proto_tree *pad_tree, const char *fmt, ...)
1415 guint32 ulType;
1416 guint8 labelPresent;
1417 proto_item *item;
1418 proto_tree *tree;
1419 struct CBaseStorageVariant prval;
1420 va_list ap;
1422 va_start(ap, fmt);
1423 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1424 tree = proto_item_add_subtree(item, ett_RANGEBOUNDARY);
1425 va_end(ap);
1427 ulType = tvb_get_letohl(tvb, offset);
1428 proto_tree_add_text(tree, tvb, offset, 4, "ulType 0x%08x", ulType);
1429 proto_item_append_text(item, ": Type 0x%08x", ulType);
1430 offset += 4;
1432 ZERO_STRUCT(prval);
1433 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &prval, "prVal");
1435 labelPresent = tvb_get_guint8(tvb, offset);
1436 proto_tree_add_text(tree, tvb, offset, 1, "labelPresent: %s", labelPresent ? "True" : "False");
1437 offset += 1;
1439 if (labelPresent) {
1440 guint32 ccLabel;
1441 const char *label;
1442 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingLabelPresent");
1444 ccLabel = tvb_get_letohl(tvb, offset);
1445 proto_tree_add_text(tree, tvb, offset, 4, "ccLabel: %u", ccLabel);
1446 offset += 4;
1448 label = tvb_get_unicode_string(tvb, offset, 2*ccLabel, ENC_LITTLE_ENDIAN);
1449 proto_tree_add_text(tree, tvb, offset, 2*ccLabel, "Label: \"%s\"", label);
1450 proto_item_append_text(item, " Label: \"%s\"", label);
1451 offset += 2*ccLabel;
1454 proto_item_append_text(item, " Val: %s", str_CBaseStorageVariant(&prval, true));
1456 proto_item_set_end(item, tvb, offset);
1457 return offset;
1461 /* 2.2.1.22 CRangeCategSpec */
1462 int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
1463 proto_tree *parent_tree, proto_tree *pad_tree,
1464 const char *fmt, ...)
1466 proto_item *item;
1467 proto_tree *tree;
1468 va_list ap;
1469 unsigned i;
1470 guint32 lcid, cRange;
1472 va_start(ap, fmt);
1473 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1474 tree = proto_item_add_subtree(item, ett_CRangeCategSpec);
1475 va_end(ap);
1477 lcid = tvb_get_letohl(tvb, offset);
1478 proto_tree_add_text(tree, tvb, offset, 4, "Lcid 0x%08x", lcid);
1479 offset += 4;
1481 cRange = tvb_get_letohl(tvb, offset);
1482 proto_tree_add_text(tree, tvb, offset, 4, "cRange 0x%08x", cRange);
1483 offset += 4;
1485 for (i=0; i<cRange; i++) {
1486 offset = parse_RANGEBOUNDARY(tvb, offset, tree, pad_tree, "aRangeBegin[%u]", i);
1490 proto_item_set_end(item, tvb, offset);
1491 return offset;
1494 /* 2.2.1.21 CCategSpec */
1495 int parse_CCategSpec(tvbuff_t *tvb, int offset,
1496 proto_tree *parent_tree, proto_tree *pad_tree,
1497 const char *fmt, ...)
1499 proto_item *item;
1500 proto_tree *tree;
1502 va_list ap;
1503 guint32 type;
1505 va_start(ap, fmt);
1506 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1507 tree = proto_item_add_subtree(item, ett_CCategSpec);
1508 va_end(ap);
1510 type = tvb_get_letohl(tvb, offset);
1511 proto_tree_add_text(tree, tvb, offset, 4, "Type 0x%08x", type);
1512 proto_item_append_text(item, " Type %u", type);
1513 offset += 4;
1515 offset = parse_CSort(tvb, offset, tree, pad_tree, "CSort");
1517 offset = parse_CRangeCategSpec(tvb, offset, tree, pad_tree, "CRangeCategSpec");
1519 proto_item_set_end(item, tvb, offset);
1520 return offset;
1523 /* 2.2.1.25 CAggregSpec */
1524 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
1525 proto_tree *parent_tree, proto_tree *pad_tree,
1526 const char *fmt, ...)
1528 proto_item *item;
1529 proto_tree *tree;
1530 va_list ap;
1531 guint8 type;
1532 guint32 ccAlias, idColumn, ulMaxNumToReturn, idRepresentative;
1533 const char *alias;
1535 va_start(ap, fmt);
1536 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1537 tree = proto_item_add_subtree(item, ett_CAggregSpec);
1538 va_end(ap);
1540 type = tvb_get_guint8(tvb, offset);
1541 proto_tree_add_text(tree, tvb, offset, 1, "type: %u", type);
1542 proto_item_append_text(item, "type: %u", type);
1543 offset += 1;
1545 offset = parse_padding(tvb, offset, 4, pad_tree, "padding");
1547 ccAlias = tvb_get_letohl(tvb, offset);
1548 proto_tree_add_text(tree, tvb, offset, 1, "ccAlias: %u", ccAlias);
1549 offset += 4;
1551 alias = tvb_get_unicode_string(tvb, offset, 2*ccAlias, ENC_LITTLE_ENDIAN);
1552 proto_tree_add_text(tree, tvb, offset, 2*ccAlias, "Alias: %s", alias);
1553 offset += 2*ccAlias;
1555 idColumn = tvb_get_letohl(tvb, offset);
1556 proto_tree_add_text(tree, tvb, offset, 1, "idColumn: %u", idColumn);
1557 offset += 4;
1558 /* Optional ???
1559 ulMaxNumToReturn, idRepresentative;
1561 fprintf(stderr, "WARNING, dont know if optional members are present!\n ");
1563 proto_item_set_end(item, tvb, offset);
1564 return offset;
1567 /* 2.2.1.24 CAggregSet */
1568 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
1569 proto_tree *parent_tree, proto_tree *pad_tree,
1570 const char *fmt, ...)
1572 guint32 cCount, i;
1573 proto_item *item;
1574 proto_tree *tree;
1576 va_list ap;
1578 va_start(ap, fmt);
1579 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1580 tree = proto_item_add_subtree(item, ett_CAggregSet);
1581 va_end(ap);
1583 cCount = tvb_get_letohl(tvb, offset);
1584 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1585 offset += 4;
1587 for (i=0; i<cCount; i++) {
1588 /* 2.2.1.25 CAggregSpec */
1589 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "AggregSpecs[%u]", i);
1592 proto_item_set_end(item, tvb, offset);
1593 return offset;
1596 /* 2.2.1.27 CAggregSortKey */
1597 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
1598 proto_tree *parent_tree, proto_tree *pad_tree,
1599 const char *fmt, ...)
1601 guint32 order;
1602 proto_item *item;
1603 proto_tree *tree;
1605 va_list ap;
1607 va_start(ap, fmt);
1608 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1609 tree = proto_item_add_subtree(item, ett_CAggregSortKey);
1610 va_end(ap);
1612 order = tvb_get_letohl(tvb, offset);
1613 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", order);
1614 offset += 4;
1616 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "ColumnSpec");
1618 proto_item_set_end(item, tvb, offset);
1619 return offset;
1623 /* 2.2.1.26 CSortAggregSet */
1624 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
1625 proto_tree *parent_tree, proto_tree *pad_tree,
1626 const char *fmt, ...)
1628 guint32 cCount, i;
1629 proto_item *item;
1630 proto_tree *tree;
1632 va_list ap;
1634 va_start(ap, fmt);
1635 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1636 tree = proto_item_add_subtree(item, ett_CSortAggregSet);
1637 va_end(ap);
1639 cCount = tvb_get_letohl(tvb, offset);
1640 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1641 offset += 4;
1643 for (i=0; i<cCount; i++) {
1644 /* 2.2.1.27 CAggregSortKey */
1645 offset = parse_CAggregSortKey(tvb, offset, tree, pad_tree, "SortKeys[%u]", i);
1648 proto_item_set_end(item, tvb, offset);
1649 return offset;
1652 enum CInGroupSortAggregSet_type {
1653 GroupIdDefault = 0x00, /* The default for all ranges. */
1654 GroupIdMinValue = 0x01, /*The first range in the parent's group.*/
1655 GroupIdNull = 0x02, /*The last range in the parent's group.*/
1656 GroupIdValue = 0x03,
1659 /* 2.2.1.29 CInGroupSortAggregSet */
1660 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
1661 proto_tree *parent_tree, proto_tree *pad_tree,
1662 const char *fmt, ...)
1664 proto_item *item;
1665 proto_tree *tree;
1666 va_list ap;
1667 enum CInGroupSortAggregSet_type type;
1669 va_start(ap, fmt);
1670 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1671 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSet);
1672 va_end(ap);
1674 type = tvb_get_guint8(tvb, offset);
1675 proto_tree_add_text(tree, tvb, offset, 1, "Type: 0x%02x", (unsigned)type);
1676 offset += 1;
1678 offset = parse_padding(tvb, offset, 4, pad_tree, "CInGroupSortAggregSet");
1680 if (type == GroupIdValue) {
1681 struct CBaseStorageVariant id;
1682 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &id, "inGroupId");
1685 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
1687 proto_item_set_end(item, tvb, offset);
1688 return offset;
1692 /* 2.2.1.28 CInGroupSortAggregSets */
1693 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
1694 proto_tree *parent_tree, proto_tree *pad_tree,
1695 const char *fmt, ...)
1697 guint32 cCount, i;
1698 proto_item *item;
1699 proto_tree *tree;
1701 va_list ap;
1703 va_start(ap, fmt);
1704 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1705 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSets);
1706 va_end(ap);
1708 cCount = tvb_get_letohl(tvb, offset);
1709 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1710 offset += 4;
1712 for (i=0; i<cCount; i++) {
1713 /* 2.2.1.29 CInGroupSortAggregSet */
1714 offset = parse_CInGroupSortAggregSet(tvb, offset, tree, pad_tree, "SortSets[%u]", i);
1717 proto_item_set_end(item, tvb, offset);
1718 return offset;
1721 /* 2.2.1.20 CCategorizationSpec */
1722 int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
1723 proto_tree *parent_tree, proto_tree *pad_tree,
1724 const char *fmt, ...)
1726 guint32 cMaxResults;
1727 proto_item *item;
1728 proto_tree *tree;
1730 va_list ap;
1732 va_start(ap, fmt);
1733 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1734 tree = proto_item_add_subtree(item, ett_CCategorizationSpec);
1735 va_end(ap);
1737 /* 2.2.1.18 CColumnSet */
1738 offset = parse_CColumnSet(tvb, offset, tree, "csColumns");
1740 /* 2.2.1.21 CCategSpec */
1741 offset = parse_CCategSpec(tvb, offset, tree, pad_tree, "Spec");
1743 /* 2.2.1.24 CAggregSet */
1744 offset = parse_CAggregSet(tvb, offset, tree, pad_tree, "AggregSet");
1746 /* 2.2.1.26 CSortAggregSet */
1747 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
1749 /* 2.2.1.28 CInGroupSortAggregSets */
1750 offset = parse_CInGroupSortAggregSets(tvb, offset, tree, pad_tree, "InGroupSortAggregSets");
1752 cMaxResults = tvb_get_letohl(tvb, offset);
1753 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", cMaxResults);
1754 offset += 4;
1756 proto_item_set_end(item, tvb, offset);
1757 return offset;
1760 int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
1761 proto_tree *parent_tree, proto_tree *pad_tree _U_,
1762 const char *fmt, ...)
1764 guint32 opt, maxres, timeout;
1765 proto_item *item;
1766 proto_tree *tree;
1768 va_list ap;
1770 va_start(ap, fmt);
1771 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1772 tree = proto_item_add_subtree(item, ett_CRowsetProperties);
1773 va_end(ap);
1775 opt = tvb_get_letohl(tvb, offset);
1776 proto_tree_add_text(tree, tvb, offset, 4, "uBooleanOptions: 0x%08x", opt);
1777 offset += 4;
1779 proto_tree_add_text(tree, tvb, offset, 4, "ulMaxOpenRows (ignored)");
1780 offset += 4;
1782 proto_tree_add_text(tree, tvb, offset, 4, "ulMemoryUsage (ignored)");
1783 offset += 4;
1785 maxres = tvb_get_letohl(tvb, offset);
1786 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", maxres);
1787 offset += 4;
1789 timeout = tvb_get_letohl(tvb, offset);
1790 proto_tree_add_text(tree, tvb, offset, 4, "cCmdTimeout: %u", timeout);
1791 offset += 4;
1793 proto_item_set_end(item, tvb, offset);
1794 return offset;
1797 int parse_CPidMapper(tvbuff_t *tvb, int offset,
1798 proto_tree *parent_tree, proto_tree *pad_tree,
1799 const char *fmt, ...)
1801 proto_item *item;
1802 proto_tree *tree;
1803 va_list ap;
1804 guint32 count, i;
1806 va_start(ap, fmt);
1807 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1808 tree = proto_item_add_subtree(item, ett_CPidMapper);
1809 va_end(ap);
1811 count = tvb_get_letohl(tvb, offset);
1812 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
1813 offset += 4;
1815 offset = parse_padding(tvb, offset, 8, pad_tree, "CPidMapper_PropSpec");
1817 for (i=0; i<count; i++) {
1818 struct CFullPropSpec v;
1819 ZERO_STRUCT(v);
1820 offset = parse_padding(tvb, offset, 4, pad_tree,
1821 "CPidMapper_PropSpec[%u]", i); //at begin or end of loop???
1822 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v, "PropSpec[%u]", i);
1825 proto_item_set_end(item, tvb, offset);
1826 return offset;
1829 /* Code to actually dissect the packets */
1831 static int dissect_CPMConnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
1833 proto_item *ti;
1834 proto_tree *tree;
1835 gint offset = 16;
1836 guint len;
1837 guint32 version;
1839 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
1840 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
1841 proto_item_set_text(ti, "CPMConnect%s", in ? "In" : "Out");
1842 col_append_str(pinfo->cinfo, COL_INFO, "Connect");
1844 version = tvb_get_letohl(tvb, offset);
1845 ti = proto_tree_add_item(tree, hf_mswsp_msg_Connect_Version, tvb,
1846 offset, 4, ENC_LITTLE_ENDIAN);
1847 if (version & 0xffff0000) {
1848 proto_item_append_text(ti, " 64 bit");
1850 switch (version & 0xffff) {
1851 case 0x102:
1852 proto_item_append_text(ti, " w2k8 or vista");
1853 break;
1854 case 0x109:
1855 proto_item_append_text(ti, " XP or w2k3, with Windows Search 4.0");
1856 break;
1857 case 0x700:
1858 proto_item_append_text(ti, " win7 or w2k8r2");
1859 break;
1861 offset += 4;
1863 if (in) {
1864 guint32 blob_size1_off, blob_size2_off;
1865 proto_tree *pad_tree;
1867 ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
1868 pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
1870 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_ClientIsRemote, tvb,
1871 offset, 4, ENC_LITTLE_ENDIAN);
1872 offset += 4;
1874 /* _cbBlob1 */
1875 blob_size1_off = offset;
1876 offset += 4;
1878 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcbBlob2");
1880 /* _cbBlob2 */
1881 blob_size2_off = offset;
1882 offset += 4;
1884 offset = parse_padding(tvb, offset, 16, pad_tree, "_padding");
1886 len = tvb_unicode_strsize(tvb, offset);
1887 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_MachineName, tvb,
1888 offset, len, ENC_UTF_16);
1889 /*This shouldnt be necessary, is this a bug or is there some GUI setting I've missed?*/
1890 proto_item_set_text(ti, "Remote machine: %s",
1891 tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN));
1892 offset += len;
1894 len = tvb_unicode_strsize(tvb, offset);
1895 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_UserName, tvb,
1896 offset, len, ENC_UTF_16);
1897 proto_item_set_text(ti, "User: %s", tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN));
1898 offset += len;
1900 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcPropSets");
1902 offset = parse_PropertySetArray(tvb, offset, blob_size1_off, tree, pad_tree, "PropSets");
1904 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingExtPropset");
1906 offset = parse_PropertySetArray(tvb, offset, blob_size2_off, tree, pad_tree, "ExtPropset");
1908 offset = parse_padding(tvb, offset, 8, pad_tree, "???");
1910 DISSECTOR_ASSERT(offset == (int)tvb_length(tvb));
1912 /* make "Padding" the last item */
1913 proto_tree_move_item(tree, ti, proto_tree_get_parent(pad_tree));
1914 } else {
1917 return tvb_length(tvb);
1920 static int dissect_CPMDisconnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
1922 col_append_str(pinfo->cinfo, COL_INFO, "Disconnect");
1923 return tvb_length(tvb);
1926 static int dissect_CPMCreateQuery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
1928 gint offset = 16;
1929 proto_item *ti;
1930 proto_tree *tree;
1932 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
1933 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
1935 proto_item_set_text(ti, "CPMCreateQuery%s", in ? "In" : "Out");
1936 col_append_str(pinfo->cinfo, COL_INFO, "CreateQuery");
1938 if (in) {
1939 proto_item *ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
1940 proto_tree *pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
1941 guint8 CColumnSetPresent, CRestrictionPresent, CSortSetPresent, CCategorizationSetPresent;
1942 guint32 size = tvb_get_letohl(tvb, offset);
1943 proto_tree_add_text(tree, tvb, offset, 4, "size");
1944 proto_tree_add_text(tree, tvb, offset, size, "ALL");
1945 offset += 4;
1947 CColumnSetPresent = tvb_get_guint8(tvb, offset);
1948 proto_tree_add_text(tree, tvb, offset, 1, "CColumnSetPresent: %s", CColumnSetPresent ? "True" : "False");
1949 offset += 1;
1951 if (CColumnSetPresent) {
1952 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCColumnSetPresent");
1953 offset = parse_CColumnSet(tvb, offset, tree, "CColumnSet");
1956 CRestrictionPresent = tvb_get_guint8(tvb, offset);
1957 proto_tree_add_text(tree, tvb, offset, 1, "CRestrictionPresent: %s", CColumnSetPresent ? "True" : "False");
1958 offset += 1;
1959 if (CRestrictionPresent) {
1960 offset = parse_CRestrictionArray(tvb, offset, tree, pad_tree, "RestrictionArray");
1963 CSortSetPresent = tvb_get_guint8(tvb, offset);
1964 proto_tree_add_text(tree, tvb, offset, 1, "CSortSetPresent: %s", CSortSetPresent ? "True" : "False");
1965 offset += 1;
1966 if (CSortSetPresent) {
1967 offset = parse_padding(tvb, offset, 4, tree, "paddingCSortSetPresent");
1969 proto_tree_add_text(tree, tvb, offset, 8, "XXX");
1970 offset += 8;
1972 offset = parse_CSortSet(tvb, offset, tree, pad_tree, "SortSet");
1975 CCategorizationSetPresent = tvb_get_guint8(tvb, offset);
1976 proto_tree_add_text(tree, tvb, offset, 1, "CCategorizationSetPresent: %s", CCategorizationSetPresent ? "True" : "False");
1977 offset += 1;
1979 if (CCategorizationSetPresent) {
1980 guint32 count, i;
1981 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCCategorizationSetPresent");
1982 /* 2.2.1.19 CCategorizationSet */
1983 count = tvb_get_letohl(tvb, offset);
1984 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
1985 offset += 4;
1986 for (i=0; i<count; i++) {
1987 offset = parse_CCategorizationSpec(tvb, offset, tree, pad_tree, "categories[%u]", i);
1991 offset = parse_padding(tvb, offset, 4, tree, "XXXX"); //XXX
1993 offset = parse_CRowsetProperties(tvb, offset, tree, pad_tree, "RowSetProperties");
1995 offset = parse_CPidMapper(tvb, offset, tree, pad_tree, "PidMapper");
1998 return tvb_length(tvb);
2001 static int dissect_CPMFreeCursor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2003 col_append_str(pinfo->cinfo, COL_INFO, "FreeCursor");
2004 return tvb_length(tvb);
2007 static int dissect_CPMGetRows(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2009 col_append_str(pinfo->cinfo, COL_INFO, "GetRows");
2010 return tvb_length(tvb);
2013 static int dissect_CPMRatioFinished(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2015 col_append_str(pinfo->cinfo, COL_INFO, "RatioFinished");
2016 return tvb_length(tvb);
2019 static int dissect_CPMCompareBmk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2021 col_append_str(pinfo->cinfo, COL_INFO, "CompareBmk");
2022 return tvb_length(tvb);
2025 static int dissect_CPMGetApproximatePosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2027 col_append_str(pinfo->cinfo, COL_INFO, "GetApproximatePosition");
2028 return tvb_length(tvb);
2031 static int dissect_CPMSetBindings(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2033 col_append_str(pinfo->cinfo, COL_INFO, "SetBindings");
2034 return tvb_length(tvb);
2037 static int dissect_CPMGetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2039 col_append_str(pinfo->cinfo, COL_INFO, "GetNotify");
2040 return tvb_length(tvb);
2043 static int dissect_CPMSendNotifyOut(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2045 col_append_str(pinfo->cinfo, COL_INFO, "SendNotify");
2046 return tvb_length(tvb);
2049 static int dissect_CPMGetQueryStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2051 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatus");
2052 return tvb_length(tvb);
2055 static int dissect_CPMCiState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2057 col_append_str(pinfo->cinfo, COL_INFO, "CiState");
2058 return tvb_length(tvb);
2061 static int dissect_CPMFetchValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2063 col_append_str(pinfo->cinfo, COL_INFO, "FetchValue");
2064 return tvb_length(tvb);
2067 static int dissect_CPMGetQueryStatusEx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2069 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatusEx");
2070 return tvb_length(tvb);
2073 static int dissect_CPMRestartPosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2075 col_append_str(pinfo->cinfo, COL_INFO, "RestartPosition");
2076 return tvb_length(tvb);
2079 static int dissect_CPMSetCatState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2081 col_append_str(pinfo->cinfo, COL_INFO, "SetCatState");
2082 return tvb_length(tvb);
2085 static int dissect_CPMGetRowsetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2087 col_append_str(pinfo->cinfo, COL_INFO, "GetRowsetNotify");
2088 return tvb_length(tvb);
2091 static int dissect_CPMFindIndices(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2093 col_append_str(pinfo->cinfo, COL_INFO, "FindIndices");
2094 return tvb_length(tvb);
2097 static int dissect_CPMSetScopePrioritization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2099 col_append_str(pinfo->cinfo, COL_INFO, "SetScopePrioritization");
2100 return tvb_length(tvb);
2103 static int dissect_CPMGetScopeStatistics(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2105 col_append_str(pinfo->cinfo, COL_INFO, "GetScopeStatistics");
2106 return tvb_length(tvb);
2111 dissect_mswsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean in)
2113 static const char *dbg_wait = NULL;
2114 static int wait_frame = -1;
2116 proto_tree *mswsp_tree = NULL;
2117 struct {
2118 guint32 msg;
2119 guint32 status;
2120 guint32 checksum;
2121 guint32 reserved;
2122 } hdr;
2123 int (*fn)(tvbuff_t*, packet_info*, proto_tree*, gboolean);
2125 if (tvb_length(tvb) < 16) {
2126 return 0;
2129 if (dbg_wait == NULL) {
2130 dbg_wait = getenv("DBG_FRAME");
2131 if (dbg_wait == NULL) {
2132 dbg_wait = "no";
2133 } else {
2134 wait_frame = atoi(dbg_wait);
2138 if ((int)pinfo->fd->num == wait_frame) {
2139 static volatile gboolean wait = 1;
2140 while(wait) {
2141 sleep(1);
2145 hdr.msg = tvb_get_letohl(tvb, 0);
2147 switch(hdr.msg) {
2148 case 0xC8:
2149 fn = dissect_CPMConnect;
2150 break;
2151 case 0xC9:
2152 fn = dissect_CPMDisconnect;
2153 break;
2154 case 0xCA:
2155 fn = dissect_CPMCreateQuery;
2156 break;
2157 case 0xCB:
2158 fn = dissect_CPMFreeCursor;
2159 break;
2160 case 0xCC:
2161 fn = dissect_CPMGetRows;
2162 break;
2163 case 0xCD:
2164 fn = dissect_CPMRatioFinished;
2165 break;
2166 case 0xCE:
2167 fn = dissect_CPMCompareBmk;
2168 break;
2169 case 0xCF:
2170 fn = dissect_CPMGetApproximatePosition;
2171 break;
2172 case 0xD0:
2173 fn = dissect_CPMSetBindings;
2174 break;
2175 case 0xD1:
2176 fn = dissect_CPMGetNotify;
2177 break;
2178 case 0xD2:
2179 fn = dissect_CPMSendNotifyOut;
2180 break;
2181 case 0xD7:
2182 fn = dissect_CPMGetQueryStatus;
2183 break;
2184 case 0xD9:
2185 fn = dissect_CPMCiState;
2186 break;
2187 case 0xE4:
2188 fn = dissect_CPMFetchValue;
2189 break;
2190 case 0xE7:
2191 fn = dissect_CPMGetQueryStatusEx;
2192 break;
2193 case 0xE8:
2194 fn = dissect_CPMRestartPosition;
2195 break;
2196 case 0xEC:
2197 fn = dissect_CPMSetCatState;
2198 break;
2199 case 0xF1:
2200 fn = dissect_CPMGetRowsetNotify;
2201 break;
2202 case 0xF2:
2203 fn = dissect_CPMFindIndices;
2204 break;
2205 case 0xF3:
2206 fn = dissect_CPMSetScopePrioritization;
2207 break;
2208 case 0xF4:
2209 fn = dissect_CPMGetScopeStatistics;
2210 break;
2211 default:
2212 return 0;
2215 hdr.status = tvb_get_letohl(tvb, 4);
2216 hdr.checksum = tvb_get_letohl(tvb, 8);
2218 /* col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS-WSP"); */
2219 col_append_str(pinfo->cinfo, COL_PROTOCOL, " WSP");
2220 /* col_clear(pinfo->cinfo, COL_INFO); */
2222 col_set_str(pinfo->cinfo, COL_INFO, "WSP ");
2223 col_append_str(pinfo->cinfo, COL_INFO, in ? "Request: " : "Response: ");
2225 if (tree) {
2226 proto_tree *hdr_tree;
2227 proto_item *ti, *hti;
2229 ti = proto_tree_add_item(tree, proto_mswsp, tvb, 0, -1, ENC_NA);
2230 mswsp_tree = proto_item_add_subtree(ti, ett_mswsp);
2232 hti = proto_tree_add_item(mswsp_tree, hf_mswsp_hdr, tvb, 0, 16, ENC_NA);
2233 hdr_tree = proto_item_add_subtree(hti, ett_mswsp_hdr);
2235 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_msg, tvb,
2236 0, 4, ENC_LITTLE_ENDIAN);
2237 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_status,
2238 tvb, 4, 4, ENC_LITTLE_ENDIAN);
2239 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_checksum,
2240 tvb, 8, 4, ENC_LITTLE_ENDIAN);
2241 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_reserved, tvb,
2242 12, 4, ENC_LITTLE_ENDIAN);
2245 fn(tvb, pinfo, mswsp_tree, in);
2247 /* Return the amount of data this dissector was able to dissect */
2248 return tvb_length(tvb);
2252 /* Register the protocol with Wireshark */
2254 /* this format is require because a script is used to build the C function
2255 that calls all the protocol registration.
2258 void
2259 proto_register_mswsp(void)
2261 module_t *mswsp_module;
2263 /* Setup list of header fields See Section 1.6.1 for details*/
2264 static const value_string msg_ids[] = {
2265 {0x000000C8, "CPMConnect"}, /* In/Out */
2266 {0x000000C9, "CPMDisconnect"},
2267 {0x000000CA, "CPMCreateQuery"}, /* In/Out */
2268 {0x000000CB, "CPMFreeCursor"}, /* In/Out */
2269 {0x000000CC, "CPMGetRows"}, /* In/Out */
2270 {0x000000CD, "CPMRatioFinished"}, /* In/Out */
2271 {0x000000CE, "CPMCompareBmk"}, /* In/Out */
2272 {0x000000CF, "CPMGetApproximatePosition"}, /* In/Out */
2273 {0x000000D0, "CPMSetBindingsIn"},
2274 {0x000000D1, "CPMGetNotify"},
2275 {0x000000D2, "CPMSendNotifyOut"},
2276 {0x000000D7, "CPMGetQueryStatusIn"}, /* In/Out */
2277 {0x000000D9, "CPMCiStateInOut"},
2278 {0x000000E4, "CPMFetchValue"}, /* In/Out */
2279 {0x000000E7, "CPMGetQueryStatusEx"}, /* In/Out */
2280 {0x000000E8, "CPMRestartPositionIn"},
2281 {0x000000EC, "CPMSetCatStateIn"}, /* (not supported) */
2282 {0x000000F1, "CPMGetRowsetNotify"}, /* In/Out */
2283 {0x000000F2, "CPMFindIndices"}, /* In/Out */
2284 {0x000000F3, "CPMSetScopePrioritization"}, /* In/Out */
2285 {0x000000F4, "CPMGetScopeStatistics"}, /* In/Out */
2287 static hf_register_info hf[] = {
2288 { &hf_mswsp_hdr,
2289 { "Header", "mswsp.hdr",
2290 FT_NONE, BASE_NONE , NULL, 0,
2291 "Message header", HFILL }
2293 { &hf_mswsp_hdr_msg,
2294 { "Msg id", "mswsp.hdr.id",
2295 FT_UINT32, BASE_HEX , VALS(msg_ids), 0,
2296 "Message id", HFILL }
2298 { &hf_mswsp_hdr_status,
2299 { "Status", "mswsp.hdr.status",
2300 FT_UINT32, BASE_HEX , NULL, 0,
2301 "Status", HFILL }
2303 { &hf_mswsp_hdr_checksum,
2304 { "checksum", "mswsp.hdr.checksum",
2305 FT_UINT32, BASE_HEX , NULL, 0,
2306 "Checksum", HFILL }
2308 { &hf_mswsp_hdr_reserved,
2309 { "Reserved", "mswsp.hdr.reserved",
2310 FT_UINT32, BASE_HEX , NULL, 0,
2311 "Reserved", HFILL }
2313 { &hf_mswsp_msg,
2314 { "msg", "mswsp.msg",
2315 FT_NONE, BASE_NONE , NULL, 0,
2316 "Message", HFILL }
2318 { &hf_mswsp_msg_Connect_Version,
2319 { "Version", "mswsp.Connect.version",
2320 FT_UINT32, BASE_HEX , NULL, 0,
2321 "Version",HFILL }
2323 { &hf_mswsp_msg_ConnectIn_ClientIsRemote,
2324 { "Remote", "mswsp.ConnectIn.isRemote",
2325 FT_BOOLEAN, BASE_HEX , NULL, 0,
2326 "Client is remote",HFILL }
2328 { &hf_mswsp_msg_ConnectIn_Blob1,
2329 { "Size", "mswsp.ConnectIn.propset.size",
2330 FT_UINT32, BASE_DEC , NULL, 0,
2331 "Size of PropSet fields",HFILL }
2333 { &hf_mswsp_msg_ConnectIn_Blob2,
2334 { "Size", "mswsp.ConnectIn.extpropset.size",
2335 FT_UINT32, BASE_DEC , NULL, 0,
2336 "Size of ExtPropSet fields",HFILL }
2338 { &hf_mswsp_msg_ConnectIn_MachineName,
2339 { "Remote machine", "mswsp.ConnectIn.machine",
2340 FT_STRINGZ, BASE_NONE , NULL, 0,
2341 "Name of remote machine",HFILL }
2343 { &hf_mswsp_msg_ConnectIn_UserName,
2344 { "User", "mswsp.ConnectIn.user",
2345 FT_STRINGZ, BASE_NONE , NULL, 0,
2346 "Name of remote user",HFILL }
2348 { &hf_mswsp_msg_ConnectIn_PropSets_num,
2349 { "Num", "mswsp.ConnectIn.propset.num",
2350 FT_UINT32, BASE_DEC , NULL, 0,
2351 "Number of Property Sets", HFILL }
2353 { &hf_mswsp_msg_ConnectIn_ExtPropSets_num,
2354 { "Num", "mswsp.ConnectIn.extpropset.num",
2355 FT_UINT32, BASE_DEC , NULL, 0,
2356 "Number of extended Property Sets", HFILL }
2361 /* Setup protocol subtree array */
2362 static gint *ett[] = {
2363 &ett_mswsp,
2364 &ett_mswsp_hdr,
2365 &ett_mswsp_msg,
2366 &ett_mswsp_pad,
2367 &ett_mswsp_property_restriction,
2368 &ett_CRestrictionArray,
2369 &ett_CBaseStorageVariant,
2370 &ett_CBaseStorageVariant_Vector,
2371 &ett_CBaseStorageVariant_Array,
2372 &ett_CDbColId,
2373 &ett_GUID,
2374 &ett_CDbProp,
2375 &ett_CDbPropSet,
2376 &ett_CDbPropSet_Array,
2377 &ett_CRestriction,
2378 &ett_CNodeRestriction,
2379 &ett_CPropertyRestriction,
2380 &ett_CCoercionRestriction,
2381 &ett_CContentRestriction,
2382 &ett_RANGEBOUNDARY,
2383 &ett_CRangeCategSpec,
2384 &ett_CCategSpec,
2385 &ett_CAggregSpec,
2386 &ett_CAggregSet,
2387 &ett_CCategorizationSpec,
2388 &ett_CAggregSortKey,
2389 &ett_CSortAggregSet,
2390 &ett_CInGroupSortAggregSet,
2391 &ett_CInGroupSortAggregSets,
2392 &ett_CRowsetProperties,
2393 &ett_CFullPropSpec,
2394 &ett_CPidMapper,
2395 &ett_CSort,
2396 &ett_CSortSet,
2399 int i;
2401 /* Register the protocol name and description */
2402 proto_mswsp = proto_register_protocol("Windows Search Protocol",
2403 "MS-WSP", "mswsp");
2405 /* Required function calls to register the header fields and subtrees used */
2406 proto_register_field_array(proto_mswsp, hf, array_length(hf));
2407 proto_register_subtree_array(ett, array_length(ett));
2409 for (i=0; i<(int)array_length(GuidPropertySet); i++) {
2410 guids_add_guid(&GuidPropertySet[i].guid, GuidPropertySet[i].def);
2414 /* Register preferences module (See Section 2.6 for more on preferences) */
2415 /* (Registration of a prefs callback is not required if there are no */
2416 /* prefs-dependent registration functions (eg: a port pref). */
2417 /* See proto_reg_handoff below. */
2418 /* If a prefs callback is not needed, use NULL instead of */
2419 /* proto_reg_handoff_mswsp in the following). */
2420 mswsp_module = prefs_register_protocol(proto_mswsp,
2421 proto_reg_handoff_mswsp);
2423 /* Register preferences module under preferences subtree.
2424 Use this function instead of prefs_register_protocol if you want to group
2425 preferences of several protocols under one preferences subtree.
2426 Argument subtree identifies grouping tree node name, several subnodes can be
2427 specified using slash '/' (e.g. "OSI/X.500" - protocol preferences will be
2428 accessible under Protocols->OSI->X.500-><PROTOSHORTNAME> preferences node.
2430 /* mswsp_module = prefs_register_protocol_subtree(subtree, */
2431 /* proto_mswsp, proto_reg_handoff_mswsp); */
2433 /* Register a sample preference */
2434 prefs_register_bool_preference(mswsp_module, "show_hex",
2435 "Display numbers in Hex",
2436 "Enable to display numerical values in hexadecimal.",
2437 &gPREF_HEX);
2439 /* Register a sample port preference */
2440 prefs_register_uint_preference(mswsp_module, "tcp.port", "mswsp TCP Port",
2441 " mswsp TCP port if other than the default",
2442 10, &gPORT_PREF);
2445 static int dissect_mswsp_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2446 smb_info_t *si = pinfo->private_data;
2447 gboolean in = si->request;
2449 smb_transact_info_t *tri = (si->sip->extra_info_type == SMB_EI_TRI) ? si->sip->extra_info : NULL;
2450 smb_fid_info_t *fid_info = NULL;
2451 GSList *iter;
2453 fprintf(stderr, "dissect_mswsp_smb %s frame: %d tid: %d op: %02x ",
2454 in ? "Request" : "Response",
2455 pinfo->fd->num, si->tid, si->cmd);
2457 if (tri == NULL) {
2458 fprintf(stderr, " extra_info_type: %d\n", si->sip->extra_info_type);
2459 return 0;
2462 for (iter = si->ct->GSL_fid_info; iter; iter = g_slist_next(iter)) {
2463 smb_fid_info_t *info = iter->data;
2464 if ((info->tid == si->tid) && (info->fid == tri->fid)) {
2465 fid_info = info;
2466 break;
2470 if ((fid_info->fsi == NULL) || (fid_info->fsi->filename == NULL)) {
2471 fprintf(stderr, " no %s\n", fid_info->fsi ? "filename" : "fsi");
2472 return 0;
2475 fprintf(stderr, " file: %s\n", fid_info->fsi->filename);
2477 if (strcasecmp(fid_info->fsi->filename, "\\MsFteWds") != 0) {
2478 return 0;
2481 return dissect_mswsp(tvb, pinfo, tree, in);
2485 static int dissect_mswsp_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2486 smb2_info_t *si = pinfo->private_data;
2487 gboolean in = !(si->flags & SMB2_FLAGS_RESPONSE);
2489 //si->tree->share_type == SMB2_SHARE_TYPE_PIPE
2490 //si->tree->connect_frame
2492 fprintf(stderr, "dissect_mswsp %d <> %d : op %02x %s %s type: %d extra_file: %s\n",
2493 pinfo->fd->num, si->tree ? (int)si->tree->connect_frame : -1,
2494 si->opcode,
2495 pinfo->dcerpc_procedure_name ? pinfo->dcerpc_procedure_name : "<NULL>",
2496 in ? "Request" : "Response", si->tree ? si->tree->share_type : -1,
2497 si->saved ? (si->saved->extra_info_type == SMB2_EI_FILENAME ? (char*)si->saved->extra_info : "<OTHER>") : "<NONE>"
2501 if (strcmp(pinfo->dcerpc_procedure_name, "File: MsFteWds") != 0) {
2502 return 0;
2505 return dissect_mswsp(tvb, pinfo, tree, in);
2510 /* If this dissector uses sub-dissector registration add a registration routine.
2511 This exact format is required because a script is used to find these
2512 routines and create the code that calls these routines.
2514 If this function is registered as a prefs callback (see prefs_register_protocol
2515 above) this function is also called by preferences whenever "Apply" is pressed;
2516 In that case, it should accommodate being called more than once.
2518 Simple form of proto_reg_handoff_mswsp which can be used if there are
2519 no prefs-dependent registration function calls.
2522 void
2523 proto_reg_handoff_mswsp(void)
2525 heur_dissector_add("smb_transact", dissect_mswsp_smb, proto_mswsp);
2526 heur_dissector_add("smb2_heur_subdissectors", dissect_mswsp_smb2, proto_mswsp);
2531 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2533 * Local variables:
2534 * c-basic-offset: 4
2535 * tab-width: 8
2536 * indent-tabs-mode: nil
2537 * End:
2539 * vi: set shiftwidth=4 tabstop=8 expandtab:
2540 * :indentSize=4:tabSize=8:noTabs=true: