MSWSP: factor out parse_CSort() & parse_CSortSet()
[wireshark-wip.git] / epan / dissectors / packet-mswsp.c
blob6135449ea7e2f9ac3acfaf2ea31e591bccf2294c
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, ...);
201 /* 2.2.1.17 CRestriction */
202 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
203 struct CRestriction *v, const char *fmt, ...);
205 /* 2.2.1.18 CColumnSet */
206 static int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...);
208 /* 2.2.1.20 CCategorizationSpec */
209 static int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
210 proto_tree *parent_tree, proto_tree *pad_tree,
211 const char *fmt, ...);
213 /* 2.2.1.21 CCategSpec */
214 static int parse_CCategSpec(tvbuff_t *tvb, int offset,
215 proto_tree *parent_tree, proto_tree *pad_tree,
216 const char *fmt, ...);
218 /* 2.2.1.22 CRangeCategSpec */
219 static int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
220 proto_tree *parent_tree, proto_tree *pad_tree,
221 const char *fmt, ...);
223 /* 2.2.1.23 RANGEBOUNDARY */
224 static int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
225 proto_tree *pad_tree, const char *fmt, ...);
227 /* 2.2.1.24 CAggregSet */
228 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
229 proto_tree *parent_tree, proto_tree *pad_tree,
230 const char *fmt, ...);
232 /* 2.2.1.25 CAggregSpec */
233 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
234 proto_tree *parent_tree, proto_tree *pad_tree,
235 const char *fmt, ...);
237 /* 2.2.1.26 CSortAggregSet */
238 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
239 proto_tree *parent_tree, proto_tree *pad_tree,
240 const char *fmt, ...);
242 /* 2.2.1.27 CAggregSortKey */
243 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
244 proto_tree *parent_tree, proto_tree *pad_tree,
245 const char *fmt, ...);
247 /* 2.2.1.28 CInGroupSortAggregSets */
248 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
249 proto_tree *parent_tree, proto_tree *pad_tree,
250 const char *fmt, ...);
252 /* 2.2.1.29 CInGroupSortAggregSet */
253 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
254 proto_tree *parent_tree, proto_tree *pad_tree,
255 const char *fmt, ...);
256 /* 2.2.1.30 CDbColId */
257 static int parse_CDbColId(tvbuff_t *tvb, int offset,
258 proto_tree *parent_tree, proto_tree *pad_tree, const char *text);
260 /* 2.2.1.31 CDbProp */
261 struct GuidPropertySet;
262 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
263 proto_tree *pad_tree, struct GuidPropertySet *propset,
264 const char *fmt, ...);
266 /* 2.2.1.32 CDbPropSet */
267 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
268 proto_tree *pad_tree, const char *fmt, ...);
269 /* 2.2.1.33 CPidMapper */
270 static int parse_CPidMapper(tvbuff_t *tvb, int offset,
271 proto_tree *parent_tree, proto_tree *pad_tree,
272 const char *fmt, ...);
274 /* 2.2.1.41 CRowsetProperties */
275 static int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
276 proto_tree *parent_tree, proto_tree *pad_tree,
277 const char *fmt, ...);
279 /* 2.2.1.43 CSortSet */
280 static int parse_CSortSet(tvbuff_t *tvb, int offset,
281 proto_tree *parent_tree, proto_tree *pad_tree,
282 const char *fmt, ...);
285 2.2.1.4 CInternalPropertyRestriction
286 2.2.1.5 CNatLanguageRestriction
287 2.2.1.9 CScopeRestriction
288 2.2.1.11 CVectorRestriction
289 2.2.1.13 CRelDocRestriction
290 2.2.1.14 CProbRestriction
291 2.2.1.15 CFeedbackRestriction
292 2.2.1.16 CRestrictionArray
293 2.2.1.19 CCategorizationSet
294 2.2.1.34 CColumnGroupArray
295 2.2.1.35 CColumnGroup
296 2.2.1.36 SProperty
297 2.2.1.37 CRowSeekAt
298 2.2.1.38 CRowSeekAtRatio
299 2.2.1.39 CRowSeekByBookmark
300 2.2.1.40 CRowSeekNext
301 2.2.1.42 CRowVariant
302 2.2.1.44 CTableColumn
303 2.2.1.45 SERIALIZEDPROPERTYVALUE
304 2.2.1.46 CCompletionCategSp
307 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
308 proto_tree *pad_tree _U_,
309 const char *fmt, ...)
311 guint32 col, ord, ind, lcid;
313 proto_item *item;
314 proto_tree *tree;
316 va_list ap;
318 va_start(ap, fmt);
319 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
320 va_end(ap);
321 tree = proto_item_add_subtree(item, ett_CSort);
323 col = tvb_get_letohl(tvb, offset);
324 proto_tree_add_text(tree, tvb, offset, 4, "column: %u", col);
325 offset += 4;
327 ord = tvb_get_letohl(tvb, offset);
328 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", ord);
329 offset += 4;
331 ind = tvb_get_letohl(tvb, offset);
332 proto_tree_add_text(tree, tvb, offset, 4, "individual: %u", ind);
333 offset += 4;
335 lcid = tvb_get_letohl(tvb, offset);
336 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", lcid);
337 offset += 4;
339 proto_item_set_end(item, tvb, offset);
340 return offset;
343 static int parse_CSortSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
344 proto_tree *pad_tree,
345 const char *fmt, ...)
347 guint32 count, i;
349 proto_item *item;
350 proto_tree *tree;
352 va_list ap;
354 va_start(ap, fmt);
355 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
356 va_end(ap);
357 tree = proto_item_add_subtree(item, ett_CSortSet);
359 count = tvb_get_letohl(tvb, offset);
360 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
361 offset += 4;
363 for (i=0; i<count; i++) {
364 offset = parse_CSort(tvb, offset, tree, pad_tree, "sortArray[%u]", i);
367 proto_item_set_end(item, tvb, offset);
368 return offset;
372 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset,
373 proto_tree *parent_tree, proto_tree *pad_tree,
374 struct CFullPropSpec *v, const char *fmt, ...)
376 static const value_string KIND[] = {
377 {0, "PRSPEC_LPWSTR"},
378 {1, "PRSPEC_PROPID"},
379 {0, NULL}
382 const char *guid_str;
383 proto_item *item;
384 proto_tree *tree;
385 va_list ap;
387 va_start(ap, fmt);
388 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
389 va_end(ap);
390 tree = proto_item_add_subtree(item, ett_CFullPropSpec);
392 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingPropSet");
394 offset = parse_guid(tvb, offset, tree, &v->guid, "GUID");
395 guid_str = guids_resolve_guid_to_str(&v->guid );
396 proto_item_append_text(item, " {%s}", guid_str);
398 v->kind = tvb_get_letohl(tvb, offset);
399 proto_tree_add_text(tree, tvb, offset, 4, "ulKind: %s ", val_to_str(v->kind, KIND, "(Unknown: 0x%x)"));
400 offset += 4;
402 v->u.propid = tvb_get_letohl(tvb, offset);
403 proto_tree_add_text(tree, tvb, offset, 4, "propid: %u ", v->u.propid);
404 offset += 4;
406 if (v->kind == PRSPEC_LPWSTR) {
407 int len = 2*v->u.propid;
408 v->u.name = tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
409 proto_tree_add_text(tree, tvb, offset, len, "name: \"%s\"", v->u.name);
410 proto_item_append_text(item, " \"%s\"", v->u.name);
411 offset += len;
412 } else if (v->kind == PRSPEC_PROPID) {
413 proto_item_append_text(item, " 0x%08x", v->u.propid);
414 } else {
415 proto_item_append_text(item, "<INVALID>");
418 proto_item_set_end(item, tvb, offset);
419 return offset;
424 static const value_string PR_VALS[] = {
425 {PRLT, "PRLT"},
426 {PRLE, "PRLE"},
427 {PRGT, "PRGT"},
428 {PRGE, "PRGE"},
429 {PREQ, "PREQ"},
430 {PRNE, "PRNE"},
431 {PRRE, "PRRE"},
432 {PRAllBits, "PRAllBits"},
433 {PRSomeBits, "PRSomeBits"},
434 {PRAll, "PRAll"},
435 {PRSome, "PRSome"},
439 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
440 proto_tree *pad_tree, struct CPropertyRestriction *v,
441 const char *fmt, ...)
443 proto_tree *tree;
444 proto_item *item;
445 const char *str;
446 va_list ap;
448 va_start(ap, fmt);
449 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
450 va_end(ap);
452 tree = proto_item_add_subtree(item, ett_CPropertyRestriction);
454 v->relop = tvb_get_letohl(tvb, offset);
455 str = val_to_str(v->relop, PR_VALS, "0x%04x");
456 proto_tree_add_text(tree, tvb, offset, 4, "relop: %s (0x%04x)",
457 str[0]=='\0' ? "" : str, v->relop);
458 proto_item_append_text(item, " Op: %s", str);
459 offset += 4;
461 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
463 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &v->prval, "prval");
465 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_lcid");
467 v->lcid = tvb_get_letohl(tvb, offset);
468 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", v->lcid);
469 offset += 4;
471 proto_item_set_end(item, tvb, offset);
473 return offset;
476 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
477 proto_tree *pad_tree, struct CCoercionRestriction *v,
478 const char *fmt, ...)
480 proto_tree *tree;
481 proto_item *item;
482 va_list ap;
484 va_start(ap, fmt);
485 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
486 va_end(ap);
488 tree = proto_item_add_subtree(item, ett_CCoercionRestriction);
490 v->value = tvb_get_letohl(tvb, offset);
491 proto_tree_add_text(tree, tvb, offset, 4, "value: %g", (double)v->value);
492 offset += 4;
494 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &v->child, "child");
496 proto_item_set_end(item, tvb, offset);
497 return offset;
500 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
501 proto_tree *pad_tree, struct CContentRestriction *v,
502 const char *fmt, ...)
504 proto_tree *tree;
505 proto_item *item;
506 va_list ap;
507 guint32 cc;
508 const char *str;
511 va_start(ap, fmt);
512 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
513 va_end(ap);
515 tree = proto_item_add_subtree(item, ett_CContentRestriction);
517 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
519 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding1");
521 cc = tvb_get_letohl(tvb, offset);
522 proto_tree_add_text(tree, tvb, offset, 4, "cc: %u", cc);
523 offset += 4;
525 // str = tvb_get_ephemeral_string_enc(tvb, offset, 2*cc, ENC_UTF_16);
526 str = tvb_get_unicode_string(tvb, offset, 2*cc, ENC_LITTLE_ENDIAN);
527 v->phrase = se_strdup(str);
528 proto_tree_add_text(tree, tvb, offset, 2*cc, "phrase: %s", str);
529 offset += 2*cc;
531 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding2");
533 v->lcid = tvb_get_letohl(tvb, offset);
534 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", v->lcid);
535 offset += 4;
537 v->method = tvb_get_letohl(tvb, offset);
538 proto_tree_add_text(tree, tvb, offset, 4, "method: 0x%08x", v->method);
539 offset += 4;
541 proto_item_set_end(item, tvb, offset);
542 return offset;
546 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
547 proto_tree *pad_tree _U_, struct CReuseWhere *v,
548 const char *fmt, ...)
550 proto_item *item;
551 va_list ap;
554 va_start(ap, fmt);
555 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
556 va_end(ap);
558 v->whereId = tvb_get_letohl(tvb, offset);
559 offset += 4;
561 proto_item_append_text(item, "Id: %u", v->whereId);
563 proto_item_set_end(item, tvb, offset);
564 return offset;
567 static value_string RT_VALS[] = {
568 {RTNone, "RTNone"},
569 {RTAnd, "RTAnd"},
570 {RTOr, "RTOr"},
571 {RTNot, "RTNot"},
572 {RTContent, "RTContent"},
573 {RTProperty, "RTProperty"},
574 {RTProximity, "RTProximity"},
575 {RTVector, ""},
576 {RTNatLanguage, "RTNatLanguage"},
577 {RTScope, "RTScope"},
578 {RTCoerce_Add, "RTCoerce_Add"},
579 {RTCoerce_Multiply, "RTCoerce_Multiply"},
580 {RTCoerce_Absolute, "RTCoerce_Absolute"},
581 {RTProb, "RTProb"},
582 {RTFeedback, "RTFeedback"},
583 {RTReldoc, "RTReldoc"},
584 {RTReuseWhere, "RTReuseWhere"},
585 {RTInternalProp, "RTInternalProp"},
586 {RTPhrase, "RTInternalProp"},
589 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
590 struct CRestriction *v, const char *fmt, ...)
592 proto_tree *tree;
593 proto_item *item, *ti;
594 const char *str;
595 va_list ap;
597 va_start(ap, fmt);
598 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
599 va_end(ap);
601 tree = proto_item_add_subtree(item, ett_CRestriction);
604 v->ulType = tvb_get_letohl(tvb, offset);
605 str = val_to_str(v->ulType, RT_VALS, "0x%.8x");
606 ti = proto_tree_add_text(tree, tvb, offset, 4, "ulType: %s (0x%.8x)",
607 str[0] == '0' ? "" : str, v->ulType);
608 proto_item_append_text(item, " Type: %s", str);
609 offset += 4;
611 v->Weight = tvb_get_letohl(tvb, offset);
612 ti = proto_tree_add_text(tree, tvb, offset, 4, "Weight: %u", v->ulType);
613 offset += 4;
615 switch(v->ulType) {
616 case RTNone:
617 break;
618 case RTAnd:
619 case RTOr:
620 case RTProximity:
621 case RTPhrase:
623 v->u.RTAnd = ep_alloc(sizeof(struct CNodeRestriction)); //XXX
624 offset = parse_CNodeRestriction(tvb, offset, tree, pad_tree, v->u.RTAnd, "CNodeRestriction");
625 break;
627 case RTNot:
629 v->u.RTNot = ep_alloc(sizeof(struct CRestriction)); //XXX
630 offset = parse_CRestriction(tvb, offset, tree, pad_tree,
631 v->u.RTNot, "CRestriction");
632 break;
634 case RTProperty:
636 v->u.RTProperty = ep_alloc(sizeof(struct CPropertyRestriction)); //XXX
637 offset = parse_CPropertyRestriction(tvb, offset, tree, pad_tree,
638 v->u.RTProperty, "CPropertyRestriction");
639 break;
641 case RTCoerce_Add:
642 case RTCoerce_Multiply:
643 case RTCoerce_Absolute:
645 v->u.RTCoerce_Add = ep_alloc(sizeof(struct CCoercionRestriction)); //XXX
646 offset = parse_CCoercionRestriction(tvb, offset, tree, pad_tree,
647 v->u.RTCoerce_Add, "CCoercionRestriction");
648 break;
650 case RTContent: {
651 v->u.RTContent = ep_alloc(sizeof(struct CContentRestriction)); //XXX
652 offset = parse_CContentRestriction(tvb, offset, tree, pad_tree,
653 v->u.RTContent, "CContentRestriction");
654 break;
656 case RTReuseWhere: {
657 v->u.RTReuseWhere = ep_alloc(sizeof(struct CReuseWhere)); //XXX
658 offset = parse_CReuseWhere(tvb, offset, tree, pad_tree,
659 v->u.RTReuseWhere, "CReuseWhere");
660 break;
662 default:
663 fprintf(stderr, "CRestriciont 0x%08x not Supported\n", v->ulType);
664 proto_item_append_text(item, " Not supported!");
667 proto_item_set_end(item, tvb, offset);
668 return offset;
671 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
672 proto_tree *pad_tree, struct CNodeRestriction *v,
673 const char *fmt, ...)
675 proto_tree *tree;
676 proto_item *item, *ti;
677 unsigned i;
678 va_list ap;
680 va_start(ap, fmt);
681 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
682 va_end(ap);
683 tree = proto_item_add_subtree(item, ett_CNodeRestriction);
685 v->cNode = tvb_get_letohl(tvb, offset);
686 ti = proto_tree_add_text(tree, tvb, offset, 4, "cNode: %u", v->cNode);
687 offset += 4;
688 for (i=0; i<v->cNode; i++) {
689 struct CRestriction r;
690 ZERO_STRUCT(r);
691 offset = parse_padding(tvb, offset, 4, pad_tree, "paNode[%u]", i); /*at begin or end of loop ????*/
692 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "paNode[%u]", i);
694 // offset = parse_padding(tvb, offset, 4, pad_tree, "paNode[%u]", i); /*at begin or end of loop ????*/
697 proto_item_set_end(item, tvb, offset);
698 return offset;
702 /*****************************************************************************************/
704 static int vvalue_tvb_get0(tvbuff_t *tvb _U_, int offset _U_, void *val _U_)
706 return 0;
709 static int vvalue_tvb_get1(tvbuff_t *tvb, int offset, void *val)
711 guint8 *ui1 = (guint8*)val;
712 *ui1 = tvb_get_guint8(tvb, offset);
713 return 1;
716 static int vvalue_tvb_get2(tvbuff_t *tvb , int offset, void *val)
718 guint16 *ui2 = (guint16*)val;
719 *ui2 = tvb_get_letohs(tvb, offset);
720 return 2;
723 static int vvalue_tvb_get4(tvbuff_t *tvb , int offset, void *val)
725 guint32 *ui4 = (guint32*)val;
726 *ui4 = tvb_get_letohl(tvb, offset);
727 return 4;
730 static int vvalue_tvb_get8(tvbuff_t *tvb , int offset, void *val)
732 guint64 *ui8 = (guint64*)val;
733 *ui8 = tvb_get_letoh64(tvb, offset);
734 return 8;
737 static int vvalue_tvb_blob(tvbuff_t *tvb , int offset, void *val)
739 struct data_blob *blob = (struct data_blob*)val;
740 guint32 len = tvb_get_letohl(tvb, offset);
741 const guint8 *data = tvb_get_ptr(tvb, offset + 4, len);
743 blob->size = len;
744 blob->data = se_memdup(data, len);
746 return 4 + len;
749 static int vvalue_tvb_bstr(tvbuff_t *tvb , int offset, void *val)
751 struct data_str *str = (struct data_str*)val;
752 guint32 len = tvb_get_letohl(tvb, offset);
753 const void *ptr = tvb_get_ptr(tvb, offset + 4, len);
755 //XXX this might be UTF-16
756 str->len = len;
757 str->str = se_strndup(ptr, len);
758 return 4 + len;
761 static int vvalue_tvb_lpstr(tvbuff_t *tvb , int offset, void *val)
763 struct data_str *str = (struct data_str*)val;
764 gint len;
766 str->len = tvb_get_letohl(tvb, offset);
767 str->str = tvb_get_seasonal_stringz(tvb, offset + 4, &len);
768 /* XXX test str->len == len */
769 return 4 + len;
772 static int vvalue_tvb_lpwstr(tvbuff_t *tvb , int offset, void *val)
774 struct data_str *str = (struct data_str*)val;
775 gint len;
776 gchar *ptr;
778 str->len = tvb_get_letohl(tvb, offset);
780 ptr = tvb_get_ephemeral_unicode_stringz(tvb, offset + 4, &len, ENC_LITTLE_ENDIAN);
781 str->str = se_strdup (ptr);
783 return 4 + len;
786 static int vvalue_tvb_vector_internal(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type, int num)
788 const int offset_in = offset;
789 const gboolean varsize = (type->size == -1);
790 const int elsize = varsize ? (int)sizeof(struct data_blob) : type->size;
791 guint8 *data = se_alloc(elsize * num);
792 int len, i;
794 val->len = num;
795 val->u.vt_ui1 = data;
796 DISSECTOR_ASSERT((void*)&val->u == ((void*)&val->u.vt_ui1));
798 for (i=0; i<num; i++) {
799 len = type->tvb_get(tvb, offset, data);
800 data += elsize;
801 offset += len;
802 if (varsize && (offset % 4) ) { /* at begin or end of loop ??? */
803 int padding = 4 - (offset % 4);
804 offset += padding;
807 return offset - offset_in;
810 static int vvalue_tvb_vector(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type)
812 const int num = tvb_get_letohl(tvb, offset);
813 return 4 + vvalue_tvb_vector_internal(tvb , offset+4, val, type, num);
816 static void vvalue_strbuf_append_null(emem_strbuf_t *strbuf _U_, void *ptr _U_)
819 static void vvalue_strbuf_append_i1(emem_strbuf_t *strbuf, void *ptr)
821 gint8 i1 = *(gint8*)ptr;
822 ep_strbuf_append_printf(strbuf, "%d", (int)i1);
825 static void vvalue_strbuf_append_i2(emem_strbuf_t *strbuf, void *ptr)
827 gint16 i2 = *(gint16*)ptr;
828 ep_strbuf_append_printf(strbuf, "%d", (int)i2);
831 static void vvalue_strbuf_append_i4(emem_strbuf_t *strbuf, void *ptr)
833 gint32 i4 = *(gint32*)ptr;
834 ep_strbuf_append_printf(strbuf, "%d", i4);
837 static void vvalue_strbuf_append_i8(emem_strbuf_t *strbuf, void *ptr)
839 gint64 i8 = *(gint64*)ptr;
840 ep_strbuf_append_printf(strbuf, "%ld", i8);
843 static void vvalue_strbuf_append_ui1(emem_strbuf_t *strbuf, void *ptr)
845 guint8 ui1 = *(guint8*)ptr;
846 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui1);
849 static void vvalue_strbuf_append_ui2(emem_strbuf_t *strbuf, void *ptr)
851 guint16 ui2 = *(guint16*)ptr;
852 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui2);
855 static void vvalue_strbuf_append_ui4(emem_strbuf_t *strbuf, void *ptr)
857 guint32 ui4 = *(guint32*)ptr;
858 ep_strbuf_append_printf(strbuf, "%d", ui4);
861 static void vvalue_strbuf_append_ui8(emem_strbuf_t *strbuf, void *ptr)
863 guint64 ui8 = *(guint64*)ptr;
864 ep_strbuf_append_printf(strbuf, "%lu", ui8);
867 static void vvalue_strbuf_append_r4(emem_strbuf_t *strbuf, void *ptr)
869 float r4 = *(float*)ptr;
870 ep_strbuf_append_printf(strbuf, "%g", (double)r4);
873 static void vvalue_strbuf_append_r8(emem_strbuf_t *strbuf, void *ptr)
875 double r8 = *(double*)ptr;
876 ep_strbuf_append_printf(strbuf, "%g", r8);
879 static void vvalue_strbuf_append_str(emem_strbuf_t *strbuf, void *ptr)
881 struct data_str *str = (struct data_str*)ptr;
882 ep_strbuf_append_printf(strbuf, "\"%s\"", str->str);
885 static void vvalue_strbuf_append_blob(emem_strbuf_t *strbuf, void *ptr)
887 struct data_blob *blob = (struct data_blob*)ptr;
888 ep_strbuf_append_printf(strbuf, "size: %d", (int)blob->size);
891 static void vvalue_strbuf_append_bool(emem_strbuf_t *strbuf, void *ptr)
893 guint16 val = *(guint*)ptr;
894 switch (val) {
895 case 0:
896 ep_strbuf_append(strbuf, "False");
897 break;
898 case 0xffff:
899 ep_strbuf_append(strbuf, "True");
900 break;
901 default:
902 ep_strbuf_append_printf(strbuf, "Invalid (0x%4x)", val);
906 static void vvalue_strbuf_append_vector(emem_strbuf_t *strbuf, struct vt_vector val, struct vtype *type)
908 const int elsize = (type->size == -1) ? (int)sizeof(struct data_blob) : type->size;
909 unsigned i;
910 guint8 *data = val.u.vt_ui1;
911 ep_strbuf_append_c(strbuf, '[');
912 for (i=0; i<val.len; i++) {
913 if (i>0) {
914 ep_strbuf_append_c(strbuf, ',');
916 type->strbuf_append(strbuf, data);
917 data += elsize;
919 ep_strbuf_append_c(strbuf, ']');
923 static struct vtype VT_TYPE[] = {
924 {VT_EMPTY, "VT_EMPTY", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
925 {VT_NULL, "VT_NULL", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
926 {VT_I2, "VT_I2", 2, vvalue_tvb_get2, vvalue_strbuf_append_i2},
927 {VT_I4, "VT_I4", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
928 {VT_R4, "VT_R4", 4, vvalue_tvb_get4, vvalue_strbuf_append_r4},
929 {VT_R8, "VT_R8", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
930 {VT_CY, "VT_CY", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
931 {VT_DATE, "VT_DATE", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
932 // {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_bstr, vvalue_strbuf_append_str},
933 {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
934 {VT_ERROR, "VT_ERROR", 8, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
935 {VT_BOOL, "VT_BOOL", 2, vvalue_tvb_get2, vvalue_strbuf_append_bool},
936 {VT_VARIANT, "VT_VARIANT", -1, NULL, NULL},
937 {VT_DECIMAL, "VT_DECIMAL", 16, NULL, NULL},
938 {VT_I1, "VT_I1", 1, vvalue_tvb_get1, vvalue_strbuf_append_i1},
939 {VT_UI1, "VT_UI1", 1, vvalue_tvb_get1, vvalue_strbuf_append_ui1},
940 {VT_UI2, "VT_UI2", 2, vvalue_tvb_get2, vvalue_strbuf_append_ui2},
941 {VT_UI4, "VT_UI4", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
942 {VT_I8, "VT_I8", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
943 {VT_UI8, "VT_UI8", 8, vvalue_tvb_get8, vvalue_strbuf_append_ui8},
944 {VT_INT, "VT_INT", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
945 {VT_UINT, "VT_UINT", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
946 {VT_LPSTR, "VT_LPSTR", -1, vvalue_tvb_lpstr, vvalue_strbuf_append_str},
947 {VT_LPWSTR, "VT_LPWSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
948 {VT_COMPRESSED_LPWSTR, "VT_COMPRESSED_LPWSTR", -1, NULL, vvalue_strbuf_append_str},
949 {VT_FILETIME, "VT_FILETIME", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
950 {VT_BLOB, "VT_BLOB", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
951 {VT_BLOB_OBJECT, "VT_BLOB_OBJECT", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
952 {VT_CLSID, "VT_CLSID", 16, NULL, NULL},
955 static struct vtype *vType_get_type(enum vType t) {
956 unsigned i;
957 t &= 0xFF;
958 for (i=0; i<array_length(VT_TYPE); i++) {
959 if (t == VT_TYPE[i].tag) {
960 return &VT_TYPE[i];
963 return NULL;
966 static char *str_CBaseStorageVariant(struct CBaseStorageVariant *value, gboolean print_type)
969 emem_strbuf_t *strbuf = ep_strbuf_new(NULL);
970 if (value == NULL) {
971 return "<NULL>";
974 if (value->type == NULL) {
975 return "<??""?>";
978 if (print_type) {
979 ep_strbuf_append(strbuf, value->type->str);
981 if (value->vType & 0xFF00) {
982 ep_strbuf_append_printf(strbuf, "[%d]", value->vValue.vt_vector.len);
984 ep_strbuf_append(strbuf, ": ");
987 switch (value->vType & 0xFF00) {
988 case 0:
989 value->type->strbuf_append(strbuf, &value->vValue);
990 break;
991 case VT_ARRAY:
992 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_array.vData, value->type);
993 break;
994 case VT_VECTOR:
995 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_vector, value->type);
996 break;
997 default:
998 ep_strbuf_append(strbuf, "Invalid");
1001 return strbuf->str;
1004 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree _U_,
1005 struct CBaseStorageVariant *value, const char *text)
1007 int i, len;
1008 proto_item *ti, *ti_type, *ti_val;
1009 proto_tree *tree, *tr;
1010 enum vType baseType, highType;
1012 ZERO_STRUCT(*value);
1014 ti = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1015 tree = proto_item_add_subtree(ti, ett_CBaseStorageVariant);
1017 value->vType = tvb_get_letohs(tvb, offset);
1018 value->type = vType_get_type(value->vType);
1020 ti_type = proto_tree_add_text(tree, tvb, offset, 2, "vType: %s", value->type->str);
1021 offset += 2;
1023 value->vData1 = tvb_get_guint8(tvb, offset);
1024 proto_tree_add_text(tree, tvb, offset, 1, "vData1: %d", value->vData1);
1025 offset += 1;
1027 value->vData2 = tvb_get_guint8(tvb, offset);
1028 proto_tree_add_text(tree, tvb, offset, 1, "vData2: %d", value->vData2);
1029 offset += 1;
1031 baseType = value->vType & 0x00FF;
1032 highType = value->vType & 0xFF00;
1034 if (value->type == NULL) {
1035 goto not_supported;
1038 ti_val = proto_tree_add_text(tree, tvb, offset, 0, "vValue");
1040 switch (highType) {
1041 case VT_EMPTY:
1042 len = value->type->tvb_get(tvb, offset, &value->vValue.vt_single);
1043 offset += len;
1044 break;
1045 case VT_VECTOR:
1046 proto_item_append_text(ti_type, "|VT_VECTOR");
1047 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Vector);
1049 len = vvalue_tvb_vector(tvb, offset, &value->vValue.vt_vector, value->type);
1050 proto_tree_add_text(tr, tvb, offset, 4, "num: %d", value->vValue.vt_vector.len);
1051 offset += len;
1052 break;
1053 case VT_ARRAY: {
1054 guint16 cDims, fFeatures;
1055 guint32 cbElements, cElements, lLbound;
1056 int num = 1;
1058 proto_item_append_text(ti_type, "|VT_ARRAY");
1059 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Array);
1061 cDims = tvb_get_letohs(tvb, offset);
1062 proto_tree_add_text(tr, tvb, offset, 2, "cDims: %d", cDims);
1063 offset += 2;
1065 fFeatures = tvb_get_letohs(tvb, offset);
1066 proto_tree_add_text(tr, tvb, offset, 2, "fFeaturess: %d", fFeatures);
1067 offset += 2;
1069 cbElements = tvb_get_letohl(tvb, offset);
1070 proto_tree_add_text(tr, tvb, offset, 4, "cbElements: %d", cbElements);
1071 offset += 4;
1072 for (i=0; i<cDims; i++) {
1073 cElements = tvb_get_letohl(tvb, offset);
1074 lLbound = tvb_get_letohl(tvb, offset + 4);
1075 proto_tree_add_text(tr, tvb, offset, 8, "Rgsabound[%d]: (%d:%d)", i, cElements, lLbound);
1076 offset += 8;
1077 num *= cElements;
1080 len = vvalue_tvb_vector_internal(tvb , offset, &value->vValue.vt_array.vData, value->type, num);
1081 offset += len;
1082 break;
1084 default:
1085 proto_item_append_text(ti_type, "|0x%x", highType);
1087 proto_item_set_end(ti, tvb, offset);
1088 proto_item_set_end(ti_val, tvb, offset);
1090 proto_item_append_text(ti_val, " %s", str_CBaseStorageVariant(value, false));
1091 proto_item_append_text(ti, " %s", str_CBaseStorageVariant(value, true));
1093 goto done;
1095 not_supported:
1096 proto_item_append_text(ti, ": sorry, vType %02x not handled yet!", (unsigned)value->vType);
1097 done:
1098 return offset;
1101 enum {
1102 DBKIND_GUID_NAME = 0,
1103 DBKIND_GUID_PROPID = 1
1106 static int parse_CDbColId(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree, const char *text)
1108 guint32 eKind, ulId;
1109 e_guid_t guid;
1110 static const char *KIND[] = {"DBKIND_GUID_NAME", "DBKIND_GUID_PROPID"};
1112 proto_item *tree_item = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1113 proto_tree *tree = proto_item_add_subtree(tree_item, ett_CDbColId);
1115 eKind = tvb_get_letohl(tvb, offset);
1116 proto_tree_add_text(tree, tvb, offset, 4, "eKind: %s (%u)", eKind < 2 ? KIND[eKind] : "???", eKind);
1117 offset += 4;
1119 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingGuidAlign");
1121 offset = parse_guid(tvb, offset, tree, &guid, "GUID");
1123 ulId = tvb_get_letohl(tvb, offset);
1124 proto_tree_add_text(tree, tvb, offset, 4, "ulId: %d", ulId);
1125 offset += 4;
1127 if (eKind == DBKIND_GUID_NAME) {
1128 char *name;
1129 int len = ulId; //*2 ???
1130 name = tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
1131 proto_tree_add_text(tree, tvb, offset, len, "vString: \"%s\"", name);
1132 proto_item_append_text(tree_item, " \"%s\"", name);
1133 offset += len;
1134 } else if (eKind == DBKIND_GUID_PROPID) {
1135 proto_item_append_text(tree_item, " %08x", ulId);
1136 } else {
1137 proto_item_append_text(tree_item, "<INVALID>");
1140 proto_item_set_end(tree_item, tvb, offset);
1142 return offset;
1145 struct GuidPropertySet {
1146 e_guid_t guid;
1147 const char *def;
1148 const char *desc;
1149 const value_string *id_map;
1152 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1153 proto_tree *pad_tree, struct GuidPropertySet *propset,
1154 const char *fmt, ...)
1156 static const value_string EMPTY_VS[] = {{0, NULL}};
1157 const value_string *vs = (propset && propset->id_map) ? propset->id_map : EMPTY_VS;
1158 guint32 id, opt, status;
1159 struct CBaseStorageVariant value;
1160 proto_item *item;
1161 proto_tree *tree;
1162 const char *str;
1163 va_list ap;
1165 va_start(ap, fmt);
1166 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1167 va_end(ap);
1169 tree = proto_item_add_subtree(item, ett_CDbProp);
1171 id = tvb_get_letohl(tvb, offset);
1172 str = val_to_str(id, vs, "0x%08x");
1173 proto_tree_add_text(tree, tvb, offset, 4, "Id: %s (0x%08x)", str[0] == '0' ? "" : str, id);
1174 offset += 4;
1175 proto_item_append_text(item, " Id: %s", str);
1177 opt = tvb_get_letohl(tvb, offset);
1178 proto_tree_add_text(tree, tvb, offset, 4, "Options: %08x", opt);
1179 offset += 4;
1181 status = tvb_get_letohl(tvb, offset);
1182 proto_tree_add_text(tree, tvb, offset, 4, "Status: %08x", status);
1183 offset += 4;
1185 offset = parse_CDbColId(tvb, offset, tree, pad_tree, "colid");
1187 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &value, "vValue");
1189 str = str_CBaseStorageVariant(&value, true);
1190 proto_item_append_text(item, " %s", str);
1191 proto_item_set_end(item, tvb, offset);
1193 return offset;
1196 /* 2.2.1.31.1 */
1197 static const value_string DBPROPSET_FSCIFRMWRK_EXT_IDS[] = {
1198 {0x02, "DBPROP_CI_CATALOG_NAME"},
1199 {0x03, "DBPROP_CI_INCLUDE_SCOPES"},
1200 {0x04, "DBPROP_CI_SCOPE_FLAGS"},
1201 {0x07, "DBPROP_CI_QUERY_TYPE"},
1202 {0, NULL}
1205 static const value_string DBPROPSET_QUERYEXT_IDS[] = {
1206 {0x02, "DBPROP_USECONTENTINDEX"},
1207 {0x03, "DBPROP_DEFERNONINDEXEDTRIMMING"},
1208 {0x04, "DBPROP_USEEXTENDEDDBTYPES"},
1209 {0x05, "DBPROP_IGNORENOISEONLYCLAUSES"},
1210 {0x06, "DBPROP_GENERICOPTIONS_STRING"},
1211 {0x07, "DBPROP_FIRSTROWS"},
1212 {0x08, "DBPROP_DEFERCATALOGVERIFICATION"},
1213 {0x0a, "DBPROP_GENERATEPARSETREE"},
1214 {0x0c, "DBPROP_FREETEXTANYTERM"},
1215 {0x0d, "DBPROP_FREETEXTUSESTEMMING"},
1216 {0x0e, "DBPROP_IGNORESBRI"},
1217 {0x10, "DBPROP_ENABLEROWSETEVENTS"},
1218 {0, NULL}
1221 static const value_string DBPROPSET_CIFRMWRKCORE_EXT_IDS[] = {
1222 {0x02, "DBPROP_MACHINE"},
1223 {0x03, "DBPROP_CLIENT_CLSID"},
1224 {0, NULL}
1227 static const value_string DBPROPSET_MSIDXS_ROWSETEXT_IDS[] = {
1228 {0x02, "MSIDXSPROP_ROWSETQUERYSTATUS"},
1229 {0x03, "MSIDXSPROP_COMMAND_LOCALE_STRING"},
1230 {0x04, "MSIDXSPROP_QUERY_RESTRICTION"},
1231 {0x05, "MSIDXSPROP_PARSE_TREE"},
1232 {0x06, "MSIDXSPROP_MAX_RANK"},
1233 {0x07, "MSIDXSPROP_RESULTS_FOUND"},
1234 {0, NULL}
1237 static struct GuidPropertySet GuidPropertySet[] = {
1238 {{0xa9bd1526, 0x6a80, 0x11d0, {0x8c, 0x9d, 0x00, 0x20, 0xaf, 0x1d, 0x74, 0x0e}},
1239 "DBPROPSET_FSCIFRMWRK_EXT", "File system content index framework",
1240 DBPROPSET_FSCIFRMWRK_EXT_IDS},
1241 {{0xa7ac77ed, 0xf8d7, 0x11ce, {0xa7, 0x98, 0x00, 0x20, 0xf8, 0x00, 0x80, 0x25}},
1242 "DBPROPSET_QUERYEXT", "Query extension",
1243 DBPROPSET_QUERYEXT_IDS},
1244 {{0xafafaca5, 0xb5d1, 0x11d0, {0x8c, 0x62, 0x00, 0xc0, 0x4f, 0xc2, 0xdb, 0x8d}},
1245 "DBPROPSET_CIFRMWRKCORE_EXT", "Content index framework core",
1246 DBPROPSET_CIFRMWRKCORE_EXT_IDS},
1247 {{0xAA6EE6B0, 0xE828, 0x11D0, {0xB2, 0x3E, 0x00, 0xAA, 0x00, 0x47, 0xFC, 0x01}},
1248 "DBPROPSET_MSIDXS_ROWSETEXT", "???",
1249 DBPROPSET_MSIDXS_ROWSETEXT_IDS},
1252 static struct GuidPropertySet *GuidPropertySet_find_guid(const e_guid_t *guid)
1254 unsigned i;
1255 for (i=0; i<array_length(GuidPropertySet); i++) {
1256 if (guid_cmp(&GuidPropertySet[i].guid, guid) == 0) {
1257 return &GuidPropertySet[i];
1260 return NULL;
1263 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1264 proto_tree *pad_tree, const char *fmt, ...)
1266 int i, num;
1267 e_guid_t guid;
1268 struct GuidPropertySet *pset;
1269 proto_item *item;
1270 proto_tree *tree;
1271 va_list ap;
1273 va_start(ap, fmt);
1274 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1275 va_end(ap);
1277 tree = proto_item_add_subtree(item, ett_CDbPropSet);
1279 offset = parse_guid(tvb, offset, tree, &guid, "guidPropertySet");
1281 pset = GuidPropertySet_find_guid(&guid);
1283 if (pset) {
1284 proto_item_append_text(item, " \"%s\" (%s)", pset->desc, pset->def);
1285 } else {
1286 const char *guid_str = guid_to_str(&guid);
1287 proto_item_append_text(item, " {%s}", guid_str);
1290 offset = parse_padding(tvb, offset, 4, pad_tree, "guidPropertySet");
1292 num = tvb_get_letohl(tvb, offset);
1293 proto_tree_add_text(tree, tvb, offset, 4, "cProperties: %d", num);
1294 offset += 4;
1295 proto_item_append_text(item, " Num: %d", num);
1297 for (i = 0; i<num; i++) {
1298 offset = parse_padding(tvb, offset, 4, pad_tree, "aProp[%d]", i);
1299 offset = parse_CDbProp(tvb, offset, tree, pad_tree, pset, "aProp[%d]", i);
1302 proto_item_set_end(item, tvb, offset);
1303 return offset;
1306 static int parse_PropertySetArray(tvbuff_t *tvb, int offset, int size_offset,
1307 proto_tree *parent_tree, proto_tree *pad_tree,
1308 const char *fmt, ...)
1310 const int offset_in = offset;
1311 guint32 size, num;
1312 int i;
1313 proto_tree *tree;
1314 proto_item *item;
1315 va_list ap;
1317 va_start(ap, fmt);
1318 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1319 va_end(ap);
1321 tree = proto_item_add_subtree(item, ett_CDbPropSet_Array);
1323 size = tvb_get_letohl(tvb, size_offset);
1324 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_Blob1, tvb,
1325 size_offset, 4, ENC_LITTLE_ENDIAN);
1327 num = tvb_get_letohl(tvb, offset);
1328 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_PropSets_num, tvb,
1329 offset, 4, ENC_LITTLE_ENDIAN);
1330 offset += 4;
1332 for (i = 0; i < (int)num; i++) {
1333 offset = parse_CDbPropSet(tvb, offset, tree, pad_tree, "PropertySet[%d]", i);
1336 proto_item_set_end(item, tvb, offset);
1337 DISSECTOR_ASSERT(offset - offset_in == (int)size);
1338 return offset;
1341 int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...)
1343 guint32 count, v, i;
1344 proto_item *item;
1346 va_list ap;
1348 va_start(ap, fmt);
1349 item = proto_tree_add_text_valist(tree, tvb, offset, 0, fmt, ap);
1350 va_end(ap);
1352 count = tvb_get_letohl(tvb, offset);
1353 offset += 4;
1355 proto_item_append_text(item, " Count %u [", count);
1356 for (i=0; i<count; i++) {
1357 v = tvb_get_letohl(tvb, offset);
1358 offset += 4;
1359 if (i>0) {
1360 proto_item_append_text(item, ",%u", v);
1361 } else {
1362 proto_item_append_text(item, "%u", v);
1365 proto_item_append_text(item, "]");
1366 return offset;
1369 /* 2.2.1.23 RANGEBOUNDARY */
1370 int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1371 proto_tree *pad_tree, const char *fmt, ...)
1373 guint32 ulType;
1374 guint8 labelPresent;
1375 proto_item *item;
1376 proto_tree *tree;
1377 struct CBaseStorageVariant prval;
1378 va_list ap;
1380 va_start(ap, fmt);
1381 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1382 tree = proto_item_add_subtree(item, ett_RANGEBOUNDARY);
1383 va_end(ap);
1385 ulType = tvb_get_letohl(tvb, offset);
1386 proto_tree_add_text(tree, tvb, offset, 4, "ulType 0x%08x", ulType);
1387 proto_item_append_text(item, ": Type 0x%08x", ulType);
1388 offset += 4;
1390 ZERO_STRUCT(prval);
1391 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &prval, "prVal");
1393 labelPresent = tvb_get_guint8(tvb, offset);
1394 proto_tree_add_text(tree, tvb, offset, 1, "labelPresent: %s", labelPresent ? "True" : "False");
1395 offset += 1;
1397 if (labelPresent) {
1398 guint32 ccLabel;
1399 const char *label;
1400 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingLabelPresent");
1402 ccLabel = tvb_get_letohl(tvb, offset);
1403 proto_tree_add_text(tree, tvb, offset, 4, "ccLabel: %u", ccLabel);
1404 offset += 4;
1406 label = tvb_get_unicode_string(tvb, offset, 2*ccLabel, ENC_LITTLE_ENDIAN);
1407 proto_tree_add_text(tree, tvb, offset, 2*ccLabel, "Label: \"%s\"", label);
1408 proto_item_append_text(item, " Label: \"%s\"", label);
1409 offset += 2*ccLabel;
1412 proto_item_append_text(item, " Val: %s", str_CBaseStorageVariant(&prval, true));
1414 proto_item_set_end(item, tvb, offset);
1415 return offset;
1419 /* 2.2.1.22 CRangeCategSpec */
1420 int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
1421 proto_tree *parent_tree, proto_tree *pad_tree,
1422 const char *fmt, ...)
1424 proto_item *item;
1425 proto_tree *tree;
1426 va_list ap;
1427 unsigned i;
1428 guint32 lcid, cRange;
1430 va_start(ap, fmt);
1431 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1432 tree = proto_item_add_subtree(item, ett_CRangeCategSpec);
1433 va_end(ap);
1435 lcid = tvb_get_letohl(tvb, offset);
1436 proto_tree_add_text(tree, tvb, offset, 4, "Lcid 0x%08x", lcid);
1437 offset += 4;
1439 cRange = tvb_get_letohl(tvb, offset);
1440 proto_tree_add_text(tree, tvb, offset, 4, "cRange 0x%08x", cRange);
1441 offset += 4;
1443 for (i=0; i<cRange; i++) {
1444 offset = parse_RANGEBOUNDARY(tvb, offset, tree, pad_tree, "aRangeBegin[%u]", i);
1448 proto_item_set_end(item, tvb, offset);
1449 return offset;
1452 /* 2.2.1.21 CCategSpec */
1453 int parse_CCategSpec(tvbuff_t *tvb, int offset,
1454 proto_tree *parent_tree, proto_tree *pad_tree,
1455 const char *fmt, ...)
1457 proto_item *item;
1458 proto_tree *tree;
1460 va_list ap;
1461 guint32 type;
1463 va_start(ap, fmt);
1464 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1465 tree = proto_item_add_subtree(item, ett_CCategSpec);
1466 va_end(ap);
1468 type = tvb_get_letohl(tvb, offset);
1469 proto_tree_add_text(tree, tvb, offset, 4, "Type 0x%08x", type);
1470 proto_item_append_text(item, " Type %u", type);
1471 offset += 4;
1473 offset = parse_CSort(tvb, offset, tree, pad_tree, "CSort");
1475 offset = parse_CRangeCategSpec(tvb, offset, tree, pad_tree, "CRangeCategSpec");
1477 proto_item_set_end(item, tvb, offset);
1478 return offset;
1481 /* 2.2.1.25 CAggregSpec */
1482 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
1483 proto_tree *parent_tree, proto_tree *pad_tree,
1484 const char *fmt, ...)
1486 proto_item *item;
1487 proto_tree *tree;
1488 va_list ap;
1489 guint8 type;
1490 guint32 ccAlias, idColumn, ulMaxNumToReturn, idRepresentative;
1491 const char *alias;
1493 va_start(ap, fmt);
1494 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1495 tree = proto_item_add_subtree(item, ett_CAggregSpec);
1496 va_end(ap);
1498 type = tvb_get_guint8(tvb, offset);
1499 proto_tree_add_text(tree, tvb, offset, 1, "type: %u", type);
1500 proto_item_append_text(item, "type: %u", type);
1501 offset += 1;
1503 offset = parse_padding(tvb, offset, 4, pad_tree, "padding");
1505 ccAlias = tvb_get_letohl(tvb, offset);
1506 proto_tree_add_text(tree, tvb, offset, 1, "ccAlias: %u", ccAlias);
1507 offset += 4;
1509 alias = tvb_get_unicode_string(tvb, offset, 2*ccAlias, ENC_LITTLE_ENDIAN);
1510 proto_tree_add_text(tree, tvb, offset, 2*ccAlias, "Alias: %s", alias);
1511 offset += 2*ccAlias;
1513 idColumn = tvb_get_letohl(tvb, offset);
1514 proto_tree_add_text(tree, tvb, offset, 1, "idColumn: %u", idColumn);
1515 offset += 4;
1516 /* Optional ???
1517 ulMaxNumToReturn, idRepresentative;
1519 fprintf(stderr, "WARNING, dont know if optional members are present!\n ");
1521 proto_item_set_end(item, tvb, offset);
1522 return offset;
1525 /* 2.2.1.24 CAggregSet */
1526 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
1527 proto_tree *parent_tree, proto_tree *pad_tree,
1528 const char *fmt, ...)
1530 guint32 cCount, i;
1531 proto_item *item;
1532 proto_tree *tree;
1534 va_list ap;
1536 va_start(ap, fmt);
1537 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1538 tree = proto_item_add_subtree(item, ett_CAggregSet);
1539 va_end(ap);
1541 cCount = tvb_get_letohl(tvb, offset);
1542 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1543 offset += 4;
1545 for (i=0; i<cCount; i++) {
1546 /* 2.2.1.25 CAggregSpec */
1547 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "AggregSpecs[%u]", i);
1550 proto_item_set_end(item, tvb, offset);
1551 return offset;
1554 /* 2.2.1.27 CAggregSortKey */
1555 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
1556 proto_tree *parent_tree, proto_tree *pad_tree,
1557 const char *fmt, ...)
1559 guint32 order;
1560 proto_item *item;
1561 proto_tree *tree;
1563 va_list ap;
1565 va_start(ap, fmt);
1566 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1567 tree = proto_item_add_subtree(item, ett_CAggregSortKey);
1568 va_end(ap);
1570 order = tvb_get_letohl(tvb, offset);
1571 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", order);
1572 offset += 4;
1574 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "ColumnSpec");
1576 proto_item_set_end(item, tvb, offset);
1577 return offset;
1581 /* 2.2.1.26 CSortAggregSet */
1582 static int parse_CSortAggregSet(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_CSortAggregSet);
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.27 CAggregSortKey */
1603 offset = parse_CAggregSortKey(tvb, offset, tree, pad_tree, "SortKeys[%u]", i);
1606 proto_item_set_end(item, tvb, offset);
1607 return offset;
1610 enum CInGroupSortAggregSet_type {
1611 GroupIdDefault = 0x00, /* The default for all ranges. */
1612 GroupIdMinValue = 0x01, /*The first range in the parent's group.*/
1613 GroupIdNull = 0x02, /*The last range in the parent's group.*/
1614 GroupIdValue = 0x03,
1617 /* 2.2.1.29 CInGroupSortAggregSet */
1618 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
1619 proto_tree *parent_tree, proto_tree *pad_tree,
1620 const char *fmt, ...)
1622 proto_item *item;
1623 proto_tree *tree;
1624 va_list ap;
1625 enum CInGroupSortAggregSet_type type;
1627 va_start(ap, fmt);
1628 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1629 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSet);
1630 va_end(ap);
1632 type = tvb_get_guint8(tvb, offset);
1633 proto_tree_add_text(tree, tvb, offset, 1, "Type: 0x%02x", (unsigned)type);
1634 offset += 1;
1636 offset = parse_padding(tvb, offset, 4, pad_tree, "CInGroupSortAggregSet");
1638 if (type == GroupIdValue) {
1639 struct CBaseStorageVariant id;
1640 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &id, "inGroupId");
1643 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
1645 proto_item_set_end(item, tvb, offset);
1646 return offset;
1650 /* 2.2.1.28 CInGroupSortAggregSets */
1651 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
1652 proto_tree *parent_tree, proto_tree *pad_tree,
1653 const char *fmt, ...)
1655 guint32 cCount, i;
1656 proto_item *item;
1657 proto_tree *tree;
1659 va_list ap;
1661 va_start(ap, fmt);
1662 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1663 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSets);
1664 va_end(ap);
1666 cCount = tvb_get_letohl(tvb, offset);
1667 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1668 offset += 4;
1670 for (i=0; i<cCount; i++) {
1671 /* 2.2.1.29 CInGroupSortAggregSet */
1672 offset = parse_CInGroupSortAggregSet(tvb, offset, tree, pad_tree, "SortSets[%u]", i);
1675 proto_item_set_end(item, tvb, offset);
1676 return offset;
1679 /* 2.2.1.20 CCategorizationSpec */
1680 int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
1681 proto_tree *parent_tree, proto_tree *pad_tree,
1682 const char *fmt, ...)
1684 guint32 cMaxResults;
1685 proto_item *item;
1686 proto_tree *tree;
1688 va_list ap;
1690 va_start(ap, fmt);
1691 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1692 tree = proto_item_add_subtree(item, ett_CCategorizationSpec);
1693 va_end(ap);
1695 /* 2.2.1.18 CColumnSet */
1696 offset = parse_CColumnSet(tvb, offset, tree, "csColumns");
1698 /* 2.2.1.21 CCategSpec */
1699 offset = parse_CCategSpec(tvb, offset, tree, pad_tree, "Spec");
1701 /* 2.2.1.24 CAggregSet */
1702 offset = parse_CAggregSet(tvb, offset, tree, pad_tree, "AggregSet");
1704 /* 2.2.1.26 CSortAggregSet */
1705 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
1707 /* 2.2.1.28 CInGroupSortAggregSets */
1708 offset = parse_CInGroupSortAggregSets(tvb, offset, tree, pad_tree, "InGroupSortAggregSets");
1710 cMaxResults = tvb_get_letohl(tvb, offset);
1711 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", cMaxResults);
1712 offset += 4;
1714 proto_item_set_end(item, tvb, offset);
1715 return offset;
1718 int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
1719 proto_tree *parent_tree, proto_tree *pad_tree _U_,
1720 const char *fmt, ...)
1723 proto_item *item;
1724 proto_tree *tree;
1726 va_list ap;
1728 va_start(ap, fmt);
1729 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1730 tree = proto_item_add_subtree(item, ett_CRowsetProperties);
1731 va_end(ap);
1733 proto_tree_add_text(tree, tvb, offset, 4, "uBooleanOptions");
1734 offset += 4;
1736 proto_tree_add_text(tree, tvb, offset, 4, "ulMaxOpenRows (ignored)");
1737 offset += 4;
1739 proto_tree_add_text(tree, tvb, offset, 4, "ulMemoryUsage (ignored)");
1740 offset += 4;
1742 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults");
1743 offset += 4;
1745 proto_tree_add_text(tree, tvb, offset, 4, "cCmdTimeout");
1746 offset += 4;
1748 proto_item_set_end(item, tvb, offset);
1749 return offset;
1752 int parse_CPidMapper(tvbuff_t *tvb, int offset,
1753 proto_tree *parent_tree, proto_tree *pad_tree,
1754 const char *fmt, ...)
1756 proto_item *item;
1757 proto_tree *tree;
1758 va_list ap;
1759 guint32 count, i;
1761 va_start(ap, fmt);
1762 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1763 tree = proto_item_add_subtree(item, ett_CPidMapper);
1764 va_end(ap);
1766 count = tvb_get_letohl(tvb, offset);
1767 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
1768 offset += 4;
1770 offset = parse_padding(tvb, offset, 8, pad_tree, "CPidMapper_PropSpec");
1772 for (i=0; i<count; i++) {
1773 struct CFullPropSpec v;
1774 ZERO_STRUCT(v);
1775 offset = parse_padding(tvb, offset, 4, pad_tree,
1776 "CPidMapper_PropSpec[%u]", i); //at begin or end of loop???
1777 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v, "PropSpec[%u]", i);
1780 proto_item_set_end(item, tvb, offset);
1781 return offset;
1784 /* Code to actually dissect the packets */
1786 static int dissect_CPMConnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
1788 proto_item *ti;
1789 proto_tree *tree;
1790 gint offset = 16;
1791 guint len;
1792 guint32 version;
1794 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
1795 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
1796 proto_item_set_text(ti, "CPMConnect%s", in ? "In" : "Out");
1797 col_append_str(pinfo->cinfo, COL_INFO, "Connect");
1799 version = tvb_get_letohl(tvb, offset);
1800 ti = proto_tree_add_item(tree, hf_mswsp_msg_Connect_Version, tvb,
1801 offset, 4, ENC_LITTLE_ENDIAN);
1802 if (version & 0xffff0000) {
1803 proto_item_append_text(ti, " 64 bit");
1805 switch (version & 0xffff) {
1806 case 0x102:
1807 proto_item_append_text(ti, " w2k8 or vista");
1808 break;
1809 case 0x109:
1810 proto_item_append_text(ti, " XP or w2k3, with Windows Search 4.0");
1811 break;
1812 case 0x700:
1813 proto_item_append_text(ti, " win7 or w2k8r2");
1814 break;
1816 offset += 4;
1818 if (in) {
1819 guint32 blob_size1_off, blob_size2_off;
1820 proto_tree *pad_tree;
1822 ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
1823 pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
1825 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_ClientIsRemote, tvb,
1826 offset, 4, ENC_LITTLE_ENDIAN);
1827 offset += 4;
1829 /* _cbBlob1 */
1830 blob_size1_off = offset;
1831 offset += 4;
1833 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcbBlob2");
1835 /* _cbBlob2 */
1836 blob_size2_off = offset;
1837 offset += 4;
1839 offset = parse_padding(tvb, offset, 16, pad_tree, "_padding");
1841 len = tvb_unicode_strsize(tvb, offset);
1842 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_MachineName, tvb,
1843 offset, len, ENC_UTF_16);
1844 /*This shouldnt be necessary, is this a bug or is there some GUI setting I've missed?*/
1845 proto_item_set_text(ti, "Remote machine: %s",
1846 tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN));
1847 offset += len;
1849 len = tvb_unicode_strsize(tvb, offset);
1850 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_UserName, tvb,
1851 offset, len, ENC_UTF_16);
1852 proto_item_set_text(ti, "User: %s", tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN));
1853 offset += len;
1855 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcPropSets");
1857 offset = parse_PropertySetArray(tvb, offset, blob_size1_off, tree, pad_tree, "PropSets");
1859 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingExtPropset");
1861 offset = parse_PropertySetArray(tvb, offset, blob_size2_off, tree, pad_tree, "ExtPropset");
1863 offset = parse_padding(tvb, offset, 8, pad_tree, "???");
1865 DISSECTOR_ASSERT(offset == (int)tvb_length(tvb));
1867 /* make "Padding" the last item */
1868 proto_tree_move_item(tree, ti, proto_tree_get_parent(pad_tree));
1869 } else {
1872 return tvb_length(tvb);
1875 static int dissect_CPMDisconnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
1877 col_append_str(pinfo->cinfo, COL_INFO, "Disconnect");
1878 return tvb_length(tvb);
1881 static int dissect_CPMCreateQuery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
1883 gint offset = 16;
1884 proto_item *ti;
1885 proto_tree *tree;
1887 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
1888 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
1890 proto_item_set_text(ti, "CPMCreateQuery%s", in ? "In" : "Out");
1891 col_append_str(pinfo->cinfo, COL_INFO, "CreateQuery");
1893 if (in) {
1894 proto_item *ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
1895 proto_tree *pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
1896 guint8 CColumnSetPresent, CRestrictionPresent, CSortSetPresent, CCategorizationSetPresent;
1897 guint32 size = tvb_get_letohl(tvb, offset);
1898 proto_tree_add_text(tree, tvb, offset, 4, "size");
1899 proto_tree_add_text(tree, tvb, offset, size, "ALL");
1900 offset += 4;
1902 CColumnSetPresent = tvb_get_guint8(tvb, offset);
1903 proto_tree_add_text(tree, tvb, offset, 1, "CColumnSetPresent: %s", CColumnSetPresent ? "True" : "False");
1904 offset += 1;
1906 if (CColumnSetPresent) {
1907 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCColumnSetPresent");
1908 offset = parse_CColumnSet(tvb, offset, tree, "CColumnSet");
1911 CRestrictionPresent = tvb_get_guint8(tvb, offset);
1912 proto_tree_add_text(tree, tvb, offset, 1, "CRestrictionPresent: %s", CColumnSetPresent ? "True" : "False");
1913 offset += 1;
1914 if (CRestrictionPresent) {
1915 guint8 count, present;
1916 int i;
1917 count = tvb_get_guint8(tvb, offset);
1918 present = tvb_get_guint8(tvb, offset);
1919 ti = proto_tree_add_text(tree, tvb, offset, 0, "CRestrictionSet: count %d", count);
1920 offset += 2;
1921 if (present) {
1922 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCRestrictionPresent");
1924 for (i=0; i<count; i++) {
1925 struct CRestriction r;
1926 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "CRestrictionArray[%d]", i);
1929 proto_item_set_end(ti, tvb, offset);
1932 CSortSetPresent = tvb_get_guint8(tvb, offset);
1933 proto_tree_add_text(tree, tvb, offset, 1, "CSortSetPresent: %s", CSortSetPresent ? "True" : "False");
1934 offset += 1;
1935 if (CSortSetPresent) {
1936 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCSortSetPresent");
1937 offset = parse_CSortSet(tvb, offset, tree, pad_tree, "SortSet");
1940 CCategorizationSetPresent = tvb_get_guint8(tvb, offset);
1941 proto_tree_add_text(tree, tvb, offset, 1, "CCategorizationSetPresent: %s", CCategorizationSetPresent ? "True" : "False");
1942 offset += 1;
1944 if (CCategorizationSetPresent) {
1945 guint32 count, i;
1946 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCCategorizationSetPresent");
1947 /* 2.2.1.19 CCategorizationSet */
1948 count = tvb_get_letohl(tvb, offset);
1949 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
1950 offset += 4;
1951 for (i=0; i<count; i++) {
1952 offset = parse_CCategorizationSpec(tvb, offset, tree, pad_tree, "categories[%u]", i);
1956 offset = parse_CRowsetProperties(tvb, offset, tree, pad_tree, "RowSetProperties");
1958 offset = parse_CPidMapper(tvb, offset, tree, pad_tree, "PidMapper");
1961 return tvb_length(tvb);
1964 static int dissect_CPMFreeCursor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
1966 col_append_str(pinfo->cinfo, COL_INFO, "FreeCursor");
1967 return tvb_length(tvb);
1970 static int dissect_CPMGetRows(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
1972 col_append_str(pinfo->cinfo, COL_INFO, "GetRows");
1973 return tvb_length(tvb);
1976 static int dissect_CPMRatioFinished(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
1978 col_append_str(pinfo->cinfo, COL_INFO, "RatioFinished");
1979 return tvb_length(tvb);
1982 static int dissect_CPMCompareBmk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
1984 col_append_str(pinfo->cinfo, COL_INFO, "CompareBmk");
1985 return tvb_length(tvb);
1988 static int dissect_CPMGetApproximatePosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
1990 col_append_str(pinfo->cinfo, COL_INFO, "GetApproximatePosition");
1991 return tvb_length(tvb);
1994 static int dissect_CPMSetBindings(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
1996 col_append_str(pinfo->cinfo, COL_INFO, "SetBindings");
1997 return tvb_length(tvb);
2000 static int dissect_CPMGetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2002 col_append_str(pinfo->cinfo, COL_INFO, "GetNotify");
2003 return tvb_length(tvb);
2006 static int dissect_CPMSendNotifyOut(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2008 col_append_str(pinfo->cinfo, COL_INFO, "SendNotify");
2009 return tvb_length(tvb);
2012 static int dissect_CPMGetQueryStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2014 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatus");
2015 return tvb_length(tvb);
2018 static int dissect_CPMCiState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2020 col_append_str(pinfo->cinfo, COL_INFO, "CiState");
2021 return tvb_length(tvb);
2024 static int dissect_CPMFetchValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2026 col_append_str(pinfo->cinfo, COL_INFO, "FetchValue");
2027 return tvb_length(tvb);
2030 static int dissect_CPMGetQueryStatusEx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2032 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatusEx");
2033 return tvb_length(tvb);
2036 static int dissect_CPMRestartPosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2038 col_append_str(pinfo->cinfo, COL_INFO, "RestartPosition");
2039 return tvb_length(tvb);
2042 static int dissect_CPMSetCatState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2044 col_append_str(pinfo->cinfo, COL_INFO, "SetCatState");
2045 return tvb_length(tvb);
2048 static int dissect_CPMGetRowsetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2050 col_append_str(pinfo->cinfo, COL_INFO, "GetRowsetNotify");
2051 return tvb_length(tvb);
2054 static int dissect_CPMFindIndices(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2056 col_append_str(pinfo->cinfo, COL_INFO, "FindIndices");
2057 return tvb_length(tvb);
2060 static int dissect_CPMSetScopePrioritization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2062 col_append_str(pinfo->cinfo, COL_INFO, "SetScopePrioritization");
2063 return tvb_length(tvb);
2066 static int dissect_CPMGetScopeStatistics(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2068 col_append_str(pinfo->cinfo, COL_INFO, "GetScopeStatistics");
2069 return tvb_length(tvb);
2074 dissect_mswsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean in)
2076 static const char *dbg_wait = NULL;
2077 static int wait_frame = -1;
2079 proto_tree *mswsp_tree = NULL;
2080 struct {
2081 guint32 msg;
2082 guint32 status;
2083 guint32 checksum;
2084 guint32 reserved;
2085 } hdr;
2086 int (*fn)(tvbuff_t*, packet_info*, proto_tree*, gboolean);
2088 if (tvb_length(tvb) < 16) {
2089 return 0;
2092 if (dbg_wait == NULL) {
2093 dbg_wait = getenv("DBG_FRAME");
2094 if (dbg_wait == NULL) {
2095 dbg_wait = "no";
2096 } else {
2097 wait_frame = atoi(dbg_wait);
2101 if ((int)pinfo->fd->num == wait_frame) {
2102 static volatile gboolean wait = 1;
2103 while(wait) {
2104 sleep(1);
2108 hdr.msg = tvb_get_letohl(tvb, 0);
2110 switch(hdr.msg) {
2111 case 0xC8:
2112 fn = dissect_CPMConnect;
2113 break;
2114 case 0xC9:
2115 fn = dissect_CPMDisconnect;
2116 break;
2117 case 0xCA:
2118 fn = dissect_CPMCreateQuery;
2119 break;
2120 case 0xCB:
2121 fn = dissect_CPMFreeCursor;
2122 break;
2123 case 0xCC:
2124 fn = dissect_CPMGetRows;
2125 break;
2126 case 0xCD:
2127 fn = dissect_CPMRatioFinished;
2128 break;
2129 case 0xCE:
2130 fn = dissect_CPMCompareBmk;
2131 break;
2132 case 0xCF:
2133 fn = dissect_CPMGetApproximatePosition;
2134 break;
2135 case 0xD0:
2136 fn = dissect_CPMSetBindings;
2137 break;
2138 case 0xD1:
2139 fn = dissect_CPMGetNotify;
2140 break;
2141 case 0xD2:
2142 fn = dissect_CPMSendNotifyOut;
2143 break;
2144 case 0xD7:
2145 fn = dissect_CPMGetQueryStatus;
2146 break;
2147 case 0xD9:
2148 fn = dissect_CPMCiState;
2149 break;
2150 case 0xE4:
2151 fn = dissect_CPMFetchValue;
2152 break;
2153 case 0xE7:
2154 fn = dissect_CPMGetQueryStatusEx;
2155 break;
2156 case 0xE8:
2157 fn = dissect_CPMRestartPosition;
2158 break;
2159 case 0xEC:
2160 fn = dissect_CPMSetCatState;
2161 break;
2162 case 0xF1:
2163 fn = dissect_CPMGetRowsetNotify;
2164 break;
2165 case 0xF2:
2166 fn = dissect_CPMFindIndices;
2167 break;
2168 case 0xF3:
2169 fn = dissect_CPMSetScopePrioritization;
2170 break;
2171 case 0xF4:
2172 fn = dissect_CPMGetScopeStatistics;
2173 break;
2174 default:
2175 return 0;
2178 hdr.status = tvb_get_letohl(tvb, 4);
2179 hdr.checksum = tvb_get_letohl(tvb, 8);
2181 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS-WSP");
2182 /* col_clear(pinfo->cinfo, COL_INFO); */
2184 col_set_str(pinfo->cinfo, COL_INFO, "WSP ");
2185 col_append_str(pinfo->cinfo, COL_INFO, in ? "Request: " : "Response: ");
2187 if (tree) {
2188 proto_tree *hdr_tree;
2189 proto_item *ti, *hti;
2191 ti = proto_tree_add_item(tree, proto_mswsp, tvb, 0, -1, ENC_NA);
2192 mswsp_tree = proto_item_add_subtree(ti, ett_mswsp);
2194 hti = proto_tree_add_item(mswsp_tree, hf_mswsp_hdr, tvb, 0, 16, ENC_NA);
2195 hdr_tree = proto_item_add_subtree(hti, ett_mswsp_hdr);
2197 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_msg, tvb,
2198 0, 4, ENC_LITTLE_ENDIAN);
2199 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_status,
2200 tvb, 4, 4, ENC_LITTLE_ENDIAN);
2201 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_checksum,
2202 tvb, 8, 4, ENC_LITTLE_ENDIAN);
2203 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_reserved, tvb,
2204 12, 4, ENC_LITTLE_ENDIAN);
2207 fn(tvb, pinfo, mswsp_tree, in);
2209 /* Return the amount of data this dissector was able to dissect */
2210 return tvb_length(tvb);
2214 /* Register the protocol with Wireshark */
2216 /* this format is require because a script is used to build the C function
2217 that calls all the protocol registration.
2220 void
2221 proto_register_mswsp(void)
2223 module_t *mswsp_module;
2225 /* Setup list of header fields See Section 1.6.1 for details*/
2226 static const value_string msg_ids[] = {
2227 {0x000000C8, "CPMConnect"}, /* In/Out */
2228 {0x000000C9, "CPMDisconnect"},
2229 {0x000000CA, "CPMCreateQuery"}, /* In/Out */
2230 {0x000000CB, "CPMFreeCursor"}, /* In/Out */
2231 {0x000000CC, "CPMGetRows"}, /* In/Out */
2232 {0x000000CD, "CPMRatioFinished"}, /* In/Out */
2233 {0x000000CE, "CPMCompareBmk"}, /* In/Out */
2234 {0x000000CF, "CPMGetApproximatePosition"}, /* In/Out */
2235 {0x000000D0, "CPMSetBindingsIn"},
2236 {0x000000D1, "CPMGetNotify"},
2237 {0x000000D2, "CPMSendNotifyOut"},
2238 {0x000000D7, "CPMGetQueryStatusIn"}, /* In/Out */
2239 {0x000000D9, "CPMCiStateInOut"},
2240 {0x000000E4, "CPMFetchValue"}, /* In/Out */
2241 {0x000000E7, "CPMGetQueryStatusEx"}, /* In/Out */
2242 {0x000000E8, "CPMRestartPositionIn"},
2243 {0x000000EC, "CPMSetCatStateIn"}, /* (not supported) */
2244 {0x000000F1, "CPMGetRowsetNotify"}, /* In/Out */
2245 {0x000000F2, "CPMFindIndices"}, /* In/Out */
2246 {0x000000F3, "CPMSetScopePrioritization"}, /* In/Out */
2247 {0x000000F4, "CPMGetScopeStatistics"}, /* In/Out */
2249 static hf_register_info hf[] = {
2250 { &hf_mswsp_hdr,
2251 { "Header", "mswsp.hdr",
2252 FT_NONE, BASE_NONE , NULL, 0,
2253 "Message header", HFILL }
2255 { &hf_mswsp_hdr_msg,
2256 { "Msg id", "mswsp.hdr.id",
2257 FT_UINT32, BASE_HEX , VALS(msg_ids), 0,
2258 "Message id", HFILL }
2260 { &hf_mswsp_hdr_status,
2261 { "Status", "mswsp.hdr.status",
2262 FT_UINT32, BASE_HEX , NULL, 0,
2263 "Status", HFILL }
2265 { &hf_mswsp_hdr_checksum,
2266 { "checksum", "mswsp.hdr.checksum",
2267 FT_UINT32, BASE_HEX , NULL, 0,
2268 "Checksum", HFILL }
2270 { &hf_mswsp_hdr_reserved,
2271 { "Reserved", "mswsp.hdr.reserved",
2272 FT_UINT32, BASE_HEX , NULL, 0,
2273 "Reserved", HFILL }
2275 { &hf_mswsp_msg,
2276 { "msg", "mswsp.msg",
2277 FT_NONE, BASE_NONE , NULL, 0,
2278 "Message", HFILL }
2280 { &hf_mswsp_msg_Connect_Version,
2281 { "Version", "mswsp.Connect.version",
2282 FT_UINT32, BASE_HEX , NULL, 0,
2283 "Version",HFILL }
2285 { &hf_mswsp_msg_ConnectIn_ClientIsRemote,
2286 { "Remote", "mswsp.ConnectIn.isRemote",
2287 FT_BOOLEAN, BASE_HEX , NULL, 0,
2288 "Client is remote",HFILL }
2290 { &hf_mswsp_msg_ConnectIn_Blob1,
2291 { "Size", "mswsp.ConnectIn.propset.size",
2292 FT_UINT32, BASE_DEC , NULL, 0,
2293 "Size of PropSet fields",HFILL }
2295 { &hf_mswsp_msg_ConnectIn_Blob2,
2296 { "Size", "mswsp.ConnectIn.extpropset.size",
2297 FT_UINT32, BASE_DEC , NULL, 0,
2298 "Size of ExtPropSet fields",HFILL }
2300 { &hf_mswsp_msg_ConnectIn_MachineName,
2301 { "Remote machine", "mswsp.ConnectIn.machine",
2302 FT_STRINGZ, BASE_NONE , NULL, 0,
2303 "Name of remote machine",HFILL }
2305 { &hf_mswsp_msg_ConnectIn_UserName,
2306 { "User", "mswsp.ConnectIn.user",
2307 FT_STRINGZ, BASE_NONE , NULL, 0,
2308 "Name of remote user",HFILL }
2310 { &hf_mswsp_msg_ConnectIn_PropSets_num,
2311 { "Num", "mswsp.ConnectIn.propset.num",
2312 FT_UINT32, BASE_DEC , NULL, 0,
2313 "Number of Property Sets", HFILL }
2315 { &hf_mswsp_msg_ConnectIn_ExtPropSets_num,
2316 { "Num", "mswsp.ConnectIn.extpropset.num",
2317 FT_UINT32, BASE_DEC , NULL, 0,
2318 "Number of extended Property Sets", HFILL }
2323 /* Setup protocol subtree array */
2324 static gint *ett[] = {
2325 &ett_mswsp,
2326 &ett_mswsp_hdr,
2327 &ett_mswsp_msg,
2328 &ett_mswsp_pad,
2329 &ett_mswsp_property_restriction,
2330 &ett_CRestrictionArray,
2331 &ett_CBaseStorageVariant,
2332 &ett_CBaseStorageVariant_Vector,
2333 &ett_CBaseStorageVariant_Array,
2334 &ett_CDbColId,
2335 &ett_GUID,
2336 &ett_CDbProp,
2337 &ett_CDbPropSet,
2338 &ett_CDbPropSet_Array,
2339 &ett_CRestriction,
2340 &ett_CNodeRestriction,
2341 &ett_CPropertyRestriction,
2342 &ett_CCoercionRestriction,
2343 &ett_CContentRestriction,
2344 &ett_RANGEBOUNDARY,
2345 &ett_CRangeCategSpec,
2346 &ett_CCategSpec,
2347 &ett_CAggregSpec,
2348 &ett_CAggregSet,
2349 &ett_CCategorizationSpec,
2350 &ett_CAggregSortKey,
2351 &ett_CSortAggregSet,
2352 &ett_CInGroupSortAggregSet,
2353 &ett_CInGroupSortAggregSets,
2354 &ett_CRowsetProperties,
2355 &ett_CFullPropSpec,
2356 &ett_CPidMapper,
2357 &ett_CSort,
2358 &ett_CSortSet,
2361 int i;
2363 /* Register the protocol name and description */
2364 proto_mswsp = proto_register_protocol("Windows Search Protocol",
2365 "MS-WSP", "mswsp");
2367 /* Required function calls to register the header fields and subtrees used */
2368 proto_register_field_array(proto_mswsp, hf, array_length(hf));
2369 proto_register_subtree_array(ett, array_length(ett));
2371 for (i=0; i<(int)array_length(GuidPropertySet); i++) {
2372 guids_add_guid(&GuidPropertySet[i].guid, GuidPropertySet[i].def);
2376 /* Register preferences module (See Section 2.6 for more on preferences) */
2377 /* (Registration of a prefs callback is not required if there are no */
2378 /* prefs-dependent registration functions (eg: a port pref). */
2379 /* See proto_reg_handoff below. */
2380 /* If a prefs callback is not needed, use NULL instead of */
2381 /* proto_reg_handoff_mswsp in the following). */
2382 mswsp_module = prefs_register_protocol(proto_mswsp,
2383 proto_reg_handoff_mswsp);
2385 /* Register preferences module under preferences subtree.
2386 Use this function instead of prefs_register_protocol if you want to group
2387 preferences of several protocols under one preferences subtree.
2388 Argument subtree identifies grouping tree node name, several subnodes can be
2389 specified using slash '/' (e.g. "OSI/X.500" - protocol preferences will be
2390 accessible under Protocols->OSI->X.500-><PROTOSHORTNAME> preferences node.
2392 /* mswsp_module = prefs_register_protocol_subtree(subtree, */
2393 /* proto_mswsp, proto_reg_handoff_mswsp); */
2395 /* Register a sample preference */
2396 prefs_register_bool_preference(mswsp_module, "show_hex",
2397 "Display numbers in Hex",
2398 "Enable to display numerical values in hexadecimal.",
2399 &gPREF_HEX);
2401 /* Register a sample port preference */
2402 prefs_register_uint_preference(mswsp_module, "tcp.port", "mswsp TCP Port",
2403 " mswsp TCP port if other than the default",
2404 10, &gPORT_PREF);
2407 static int dissect_mswsp_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2408 smb_info_t *si = pinfo->private_data;
2409 gboolean in = si->request;
2411 fprintf(stderr, "dissect_mswsp_smb %d <> %d : op %02x %s %s type: %d\n",
2412 pinfo->fd->num, si->tid,
2413 si->cmd,
2414 pinfo->dcerpc_procedure_name ? pinfo->dcerpc_procedure_name : "<NULL>",
2415 in ? "Request" : "Response", si->tid);
2418 if (strcmp(pinfo->dcerpc_procedure_name, "File: MsFteWds") != 0) {
2419 return 0;
2422 return dissect_mswsp(tvb, pinfo, tree, in);
2426 static int dissect_mswsp_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2427 smb2_info_t *si = pinfo->private_data;
2428 gboolean in = !(si->flags & SMB2_FLAGS_RESPONSE);
2430 //si->tree->share_type == SMB2_SHARE_TYPE_PIPE
2431 //si->tree->connect_frame
2433 fprintf(stderr, "dissect_mswsp %d <> %d : op %02x %s %s type: %d extra_file: %s\n",
2434 pinfo->fd->num, si->tree ? (int)si->tree->connect_frame : -1,
2435 si->opcode,
2436 pinfo->dcerpc_procedure_name ? pinfo->dcerpc_procedure_name : "<NULL>",
2437 in ? "Request" : "Response", si->tree ? si->tree->share_type : -1,
2438 si->saved ? (si->saved->extra_info_type == SMB2_EI_FILENAME ? (char*)si->saved->extra_info : "<OTHER>") : "<NONE>"
2442 if (strcmp(pinfo->dcerpc_procedure_name, "File: MsFteWds") != 0) {
2443 return 0;
2446 return dissect_mswsp(tvb, pinfo, tree, in);
2451 /* If this dissector uses sub-dissector registration add a registration routine.
2452 This exact format is required because a script is used to find these
2453 routines and create the code that calls these routines.
2455 If this function is registered as a prefs callback (see prefs_register_protocol
2456 above) this function is also called by preferences whenever "Apply" is pressed;
2457 In that case, it should accommodate being called more than once.
2459 Simple form of proto_reg_handoff_mswsp which can be used if there are
2460 no prefs-dependent registration function calls.
2463 void
2464 proto_reg_handoff_mswsp(void)
2466 heur_dissector_add("smb_transact", dissect_mswsp_smb, proto_mswsp);
2467 heur_dissector_add("smb2_heur_subdissectors", dissect_mswsp_smb2, proto_mswsp);
2472 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2474 * Local variables:
2475 * c-basic-offset: 4
2476 * tab-width: 8
2477 * indent-tabs-mode: nil
2478 * End:
2480 * vi: set shiftwidth=4 tabstop=8 expandtab:
2481 * :indentSize=4:tabSize=8:noTabs=true: