2 * Routines for PROTONAME dissection
3 * Copyright 2012, Gregor Beck <gregor.beck@sernet.de>
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.
30 /* Include only as needed */
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"
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;
113 static int parse_padding(tvbuff_t
*tvb
, int offset
, int alignment
, proto_tree
*pad_tree
, const char *fmt
, ...)
115 if (offset
% alignment
) {
116 const int padding
= alignment
- (offset
% alignment
);
120 ti
= proto_tree_add_text_valist(pad_tree
, tvb
, offset
, padding
, fmt
, ap
);
123 proto_item_append_text(ti
, " (%d)", padding
);
126 DISSECTOR_ASSERT((offset
% alignment
) == 0);
130 static int parse_guid(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, e_guid_t
*guid
, const char *text
)
132 const char *guid_str
, *name
, *bytes
;
136 tvb_get_letohguid(tvb
, offset
, guid
);
137 guid_str
= guid_to_str(guid
);
138 name
= guids_get_guid_name(guid
);
140 ti
= proto_tree_add_text(tree
, tvb
, offset
, 16, "%s: %s {%s}", text
, name
? name
: "", guid_str
);
141 tr
= proto_item_add_subtree(ti
, ett_GUID
);
143 proto_tree_add_text(tr
, tvb
, offset
, 4, "time-low: 0x%08x", guid
->data1
);
145 proto_tree_add_text(tr
, tvb
, offset
, 2, "time-mid: 0x%04x", guid
->data2
);
147 proto_tree_add_text(tr
, tvb
, offset
, 2, "time-high-and-version: 0x%04x", guid
->data3
);
149 proto_tree_add_text(tr
, tvb
, offset
, 1, "clock_seq_hi_and_reserved: 0x%02x", guid
->data4
[0]);
151 proto_tree_add_text(tr
, tvb
, offset
, 1, "clock_seq_low: 0x%02x", guid
->data4
[1]);
153 bytes
= bytestring_to_str(&guid
->data4
[2], 6, ':');
154 proto_tree_add_text(tr
, tvb
, offset
, 6, "node: %s", bytes
);
160 /*****************************************************************************************/
161 /* 2.2.1.1 CBaseStorageVariant */
162 static int parse_CBaseStorageVariant(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
, proto_tree
*pad_tree
,
163 struct CBaseStorageVariant
*value
, const char *text
);
165 /* 2.2.1.2 CFullPropSpec */
166 static int parse_CFullPropSpec(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, proto_tree
*pad_tree
,
167 struct CFullPropSpec
*v
);
169 /* 2.2.1.3 CContentRestriction */
170 static int parse_CContentRestriction(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
171 proto_tree
*pad_tree
, struct CContentRestriction
*v
,
172 const char *fmt
, ...);
173 /* 2.2.1.6 CNodeRestriction */
174 static int parse_CNodeRestriction(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, proto_tree
*pad_tree
,
175 struct CNodeRestriction
*v
, const char* fmt
, ...);
177 /* 2.2.1.7 CPropertyRestriction */
178 static int parse_CPropertyRestriction(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
179 proto_tree
*pad_tree
, struct CPropertyRestriction
*v
,
180 const char *fmt
, ...);
182 /* 2.2.1.8 CReuseWhere */
183 static int parse_CReuseWhere(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
184 proto_tree
*pad_tree _U_
, struct CReuseWhere
*v
,
185 const char *fmt
, ...);
187 /* 2.2.1.12 CCoercionRestriction */
188 static int parse_CCoercionRestriction(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
189 proto_tree
*pad_tree
, struct CCoercionRestriction
*v
,
190 const char *fmt
, ...);
192 /* 2.2.1.17 CRestriction */
193 static int parse_CRestriction(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
, proto_tree
*pad_tree
,
194 struct CRestriction
*v
, const char *fmt
, ...);
196 /* 2.2.1.18 CColumnSet */
197 static int parse_CColumnSet(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, const char *fmt
, ...);
199 /* 2.2.1.20 CCategorizationSpec */
200 static int parse_CCategorizationSpec(tvbuff_t
*tvb
, int offset
,
201 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
202 const char *fmt
, ...);
204 /* 2.2.1.21 CCategSpec */
205 static int parse_CCategSpec(tvbuff_t
*tvb
, int offset
,
206 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
207 const char *fmt
, ...);
209 /* 2.2.1.22 CRangeCategSpec */
210 static int parse_CRangeCategSpec(tvbuff_t
*tvb
, int offset
,
211 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
212 const char *fmt
, ...);
214 /* 2.2.1.23 RANGEBOUNDARY */
215 static int parse_RANGEBOUNDARY(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
216 proto_tree
*pad_tree
, const char *fmt
, ...);
218 /* 2.2.1.24 CAggregSet */
219 static int parse_CAggregSet(tvbuff_t
*tvb
, int offset
,
220 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
221 const char *fmt
, ...);
223 /* 2.2.1.25 CAggregSpec */
224 static int parse_CAggregSpec(tvbuff_t
*tvb
, int offset
,
225 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
226 const char *fmt
, ...);
228 /* 2.2.1.26 CSortAggregSet */
229 static int parse_CSortAggregSet(tvbuff_t
*tvb
, int offset
,
230 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
231 const char *fmt
, ...);
233 /* 2.2.1.27 CAggregSortKey */
234 static int parse_CAggregSortKey(tvbuff_t
*tvb
, int offset
,
235 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
236 const char *fmt
, ...);
238 /* 2.2.1.28 CInGroupSortAggregSets */
239 static int parse_CInGroupSortAggregSets(tvbuff_t
*tvb
, int offset
,
240 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
241 const char *fmt
, ...);
243 /* 2.2.1.29 CInGroupSortAggregSet */
244 static int parse_CInGroupSortAggregSet(tvbuff_t
*tvb
, int offset
,
245 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
246 const char *fmt
, ...);
247 /* 2.2.1.30 CDbColId */
248 static int parse_CDbColId(tvbuff_t
*tvb
, int offset
,
249 proto_tree
*parent_tree
, proto_tree
*pad_tree
, const char *text
);
251 /* 2.2.1.31 CDbProp */
252 struct GuidPropertySet
;
253 static int parse_CDbProp(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
254 proto_tree
*pad_tree
, struct GuidPropertySet
*propset
,
255 const char *fmt
, ...);
257 /* 2.2.1.32 CDbPropSet */
258 static int parse_CDbPropSet(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
259 proto_tree
*pad_tree
, const char *fmt
, ...);
261 /* 2.2.1.41 CRowsetProperties */
262 static int parse_CRowsetProperties(tvbuff_t
*tvb
, int offset
,
263 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
264 const char *fmt
, ...);
268 2.2.1.4 CInternalPropertyRestriction
269 2.2.1.5 CNatLanguageRestriction
270 2.2.1.9 CScopeRestriction
272 2.2.1.11 CVectorRestriction
273 2.2.1.13 CRelDocRestriction
274 2.2.1.14 CProbRestriction
275 2.2.1.15 CFeedbackRestriction
276 2.2.1.16 CRestrictionArray
277 2.2.1.19 CCategorizationSet
279 2.2.1.34 CColumnGroupArray
280 2.2.1.35 CColumnGroup
283 2.2.1.38 CRowSeekAtRatio
284 2.2.1.39 CRowSeekByBookmark
285 2.2.1.40 CRowSeekNext
288 2.2.1.44 CTableColumn
289 2.2.1.45 SERIALIZEDPROPERTYVALUE
290 2.2.1.46 CCompletionCategSp
294 static int parse_CFullPropSpec(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, proto_tree
*pad_tree
,
295 struct CFullPropSpec
*v
)
297 static const value_string KIND
[] = {
298 {0, "PRSPEC_LPWSTR"},
299 {1, "PRSPEC_PROPID"},
302 const char *guid_str
;
303 proto_item
*tree_item
= proto_tree_get_parent(tree
);
305 offset
= parse_padding(tvb
, offset
, 8, pad_tree
, "paddingPropSet");
307 offset
= parse_guid(tvb
, offset
, tree
, &v
->guid
, "GUID");
308 guid_str
= guids_resolve_guid_to_str(&v
->guid
);
309 proto_item_append_text(tree_item
, " {%s}", guid_str
);
311 v
->kind
= tvb_get_letohl(tvb
, offset
);
312 proto_tree_add_text(tree
, tvb
, offset
, 4, "ulKind: %s ", val_to_str(v
->kind
, KIND
, "(Unknown: 0x%x)"));
315 v
->u
.propid
= tvb_get_letohl(tvb
, offset
);
316 proto_tree_add_text(tree
, tvb
, offset
, 4, "propid: %u ", v
->u
.propid
);
319 if (v
->kind
== PRSPEC_LPWSTR
) {
320 int len
= 2*v
->u
.propid
;
321 v
->u
.name
= tvb_get_unicode_string(tvb
, offset
, len
, ENC_LITTLE_ENDIAN
);
322 proto_tree_add_text(tree
, tvb
, offset
, len
, "name: \"%s\"", v
->u
.name
);
323 proto_item_append_text(tree_item
, " \"%s\"", v
->u
.name
);
325 } else if (v
->kind
== PRSPEC_PROPID
) {
326 proto_item_append_text(tree_item
, " 0x%08x", v
->u
.propid
);
328 proto_item_append_text(tree_item
, "<INVALID>");
335 static const value_string PR_VALS
[] = {
343 {PRAllBits
, "PRAllBits"},
344 {PRSomeBits
, "PRSomeBits"},
350 static int parse_CPropertyRestriction(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
351 proto_tree
*pad_tree
, struct CPropertyRestriction
*v
,
352 const char *fmt
, ...)
354 proto_tree
*tree
, *tr
;
355 proto_item
*item
, *ti
;
360 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
363 tree
= proto_item_add_subtree(item
, ett_CPropertyRestriction
);
365 v
->relop
= tvb_get_letohl(tvb
, offset
);
366 str
= val_to_str(v
->relop
, PR_VALS
, "0x%04x");
367 proto_tree_add_text(tree
, tvb
, offset
, 4, "relop: %s (0x%04x)",
368 str
[0]=='\0' ? "" : str
, v
->relop
);
369 proto_item_append_text(item
, " Op: %s", str
);
372 ti
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Property");
373 tr
= proto_item_add_subtree(ti
, ett_mswsp_property_restriction
);
374 offset
= parse_CFullPropSpec(tvb
, offset
, tr
, pad_tree
, &v
->property
);
375 proto_item_set_end(ti
, tvb
, offset
);
377 offset
= parse_CBaseStorageVariant(tvb
, offset
, tree
, pad_tree
, &v
->prval
, "prval");
379 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "padding_lcid");
381 v
->lcid
= tvb_get_letohl(tvb
, offset
);
382 proto_tree_add_text(tree
, tvb
, offset
, 4, "lcid: 0x%08x", v
->lcid
);
385 proto_item_set_end(item
, tvb
, offset
);
390 static int parse_CCoercionRestriction(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
391 proto_tree
*pad_tree
, struct CCoercionRestriction
*v
,
392 const char *fmt
, ...)
399 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
402 tree
= proto_item_add_subtree(item
, ett_CCoercionRestriction
);
404 v
->value
= tvb_get_letohl(tvb
, offset
);
405 proto_tree_add_text(tree
, tvb
, offset
, 4, "value: %g", (double)v
->value
);
408 offset
= parse_CRestriction(tvb
, offset
, tree
, pad_tree
, &v
->child
, "child");
410 proto_item_set_end(item
, tvb
, offset
);
414 static int parse_CContentRestriction(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
415 proto_tree
*pad_tree
, struct CContentRestriction
*v
,
416 const char *fmt
, ...)
426 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
429 tree
= proto_item_add_subtree(item
, ett_CContentRestriction
);
431 offset
= parse_CFullPropSpec(tvb
, offset
, tree
, pad_tree
, &v
->property
);
433 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "Padding1");
435 cc
= tvb_get_letohl(tvb
, offset
);
436 proto_tree_add_text(tree
, tvb
, offset
, 4, "cc: %u", cc
);
439 // str = tvb_get_ephemeral_string_enc(tvb, offset, 2*cc, ENC_UTF_16);
440 str
= tvb_get_unicode_string(tvb
, offset
, 2*cc
, ENC_LITTLE_ENDIAN
);
441 v
->phrase
= se_strdup(str
);
442 proto_tree_add_text(tree
, tvb
, offset
, 2*cc
, "phrase: %s", str
);
445 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "Padding2");
447 v
->lcid
= tvb_get_letohl(tvb
, offset
);
448 proto_tree_add_text(tree
, tvb
, offset
, 4, "lcid: 0x%08x", v
->lcid
);
451 v
->method
= tvb_get_letohl(tvb
, offset
);
452 proto_tree_add_text(tree
, tvb
, offset
, 4, "method: 0x%08x", v
->method
);
455 proto_item_set_end(item
, tvb
, offset
);
460 static int parse_CReuseWhere(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
461 proto_tree
*pad_tree _U_
, struct CReuseWhere
*v
,
462 const char *fmt
, ...)
469 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
472 v
->whereId
= tvb_get_letohl(tvb
, offset
);
475 proto_item_append_text(item
, "Id: %u", v
->whereId
);
477 proto_item_set_end(item
, tvb
, offset
);
481 static value_string RT_VALS
[] = {
486 {RTContent
, "RTContent"},
487 {RTProperty
, "RTProperty"},
488 {RTProximity
, "RTProximity"},
490 {RTNatLanguage
, "RTNatLanguage"},
491 {RTScope
, "RTScope"},
492 {RTCoerce_Add
, "RTCoerce_Add"},
493 {RTCoerce_Multiply
, "RTCoerce_Multiply"},
494 {RTCoerce_Absolute
, "RTCoerce_Absolute"},
496 {RTFeedback
, "RTFeedback"},
497 {RTReldoc
, "RTReldoc"},
498 {RTReuseWhere
, "RTReuseWhere"},
499 {RTInternalProp
, "RTInternalProp"},
500 {RTPhrase
, "RTInternalProp"},
503 static int parse_CRestriction(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
, proto_tree
*pad_tree
,
504 struct CRestriction
*v
, const char *fmt
, ...)
507 proto_item
*item
, *ti
;
512 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
515 tree
= proto_item_add_subtree(item
, ett_CRestriction
);
518 v
->ulType
= tvb_get_letohl(tvb
, offset
);
519 str
= val_to_str(v
->ulType
, RT_VALS
, "0x%.8x");
520 ti
= proto_tree_add_text(tree
, tvb
, offset
, 4, "ulType: %s (0x%.8x)",
521 str
[0] == '0' ? "" : str
, v
->ulType
);
522 proto_item_append_text(item
, " Type: %s", str
);
525 v
->Weight
= tvb_get_letohl(tvb
, offset
);
526 ti
= proto_tree_add_text(tree
, tvb
, offset
, 4, "Weight: %u", v
->ulType
);
537 v
->u
.RTAnd
= ep_alloc(sizeof(struct CNodeRestriction
)); //XXX
538 offset
= parse_CNodeRestriction(tvb
, offset
, tree
, pad_tree
, v
->u
.RTAnd
, "CNodeRestriction");
543 v
->u
.RTNot
= ep_alloc(sizeof(struct CRestriction
)); //XXX
544 offset
= parse_CRestriction(tvb
, offset
, tree
, pad_tree
,
545 v
->u
.RTNot
, "CRestriction");
550 v
->u
.RTProperty
= ep_alloc(sizeof(struct CPropertyRestriction
)); //XXX
551 offset
= parse_CPropertyRestriction(tvb
, offset
, tree
, pad_tree
,
552 v
->u
.RTProperty
, "CPropertyRestriction");
556 case RTCoerce_Multiply
:
557 case RTCoerce_Absolute
:
559 v
->u
.RTCoerce_Add
= ep_alloc(sizeof(struct CCoercionRestriction
)); //XXX
560 offset
= parse_CCoercionRestriction(tvb
, offset
, tree
, pad_tree
,
561 v
->u
.RTCoerce_Add
, "CCoercionRestriction");
565 v
->u
.RTContent
= ep_alloc(sizeof(struct CContentRestriction
)); //XXX
566 offset
= parse_CContentRestriction(tvb
, offset
, tree
, pad_tree
,
567 v
->u
.RTContent
, "CContentRestriction");
571 v
->u
.RTReuseWhere
= ep_alloc(sizeof(struct CReuseWhere
)); //XXX
572 offset
= parse_CReuseWhere(tvb
, offset
, tree
, pad_tree
,
573 v
->u
.RTReuseWhere
, "CReuseWhere");
577 fprintf(stderr
, "CRestriciont 0x%08x not Supported\n", v
->ulType
);
578 proto_item_append_text(item
, " Not supported!");
581 proto_item_set_end(item
, tvb
, offset
);
585 static int parse_CNodeRestriction(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
586 proto_tree
*pad_tree
, struct CNodeRestriction
*v
,
587 const char *fmt
, ...)
590 proto_item
*item
, *ti
;
595 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
597 tree
= proto_item_add_subtree(item
, ett_CNodeRestriction
);
599 v
->cNode
= tvb_get_letohl(tvb
, offset
);
600 ti
= proto_tree_add_text(tree
, tvb
, offset
, 4, "cNode: %u", v
->cNode
);
602 for (i
=0; i
<v
->cNode
; i
++) {
603 struct CRestriction r
;
605 offset
= parse_CRestriction(tvb
, offset
, tree
, pad_tree
, &r
, "paNode[%u]", i
);
607 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "paNode[%u]", i
); /*at begin or end of loop ????*/
610 proto_item_set_end(item
, tvb
, offset
);
615 /*****************************************************************************************/
617 static int vvalue_tvb_get0(tvbuff_t
*tvb _U_
, int offset _U_
, void *val _U_
)
622 static int vvalue_tvb_get1(tvbuff_t
*tvb
, int offset
, void *val
)
624 guint8
*ui1
= (guint8
*)val
;
625 *ui1
= tvb_get_guint8(tvb
, offset
);
629 static int vvalue_tvb_get2(tvbuff_t
*tvb
, int offset
, void *val
)
631 guint16
*ui2
= (guint16
*)val
;
632 *ui2
= tvb_get_letohs(tvb
, offset
);
636 static int vvalue_tvb_get4(tvbuff_t
*tvb
, int offset
, void *val
)
638 guint32
*ui4
= (guint32
*)val
;
639 *ui4
= tvb_get_letohl(tvb
, offset
);
643 static int vvalue_tvb_get8(tvbuff_t
*tvb
, int offset
, void *val
)
645 guint64
*ui8
= (guint64
*)val
;
646 *ui8
= tvb_get_letoh64(tvb
, offset
);
650 static int vvalue_tvb_blob(tvbuff_t
*tvb
, int offset
, void *val
)
652 struct data_blob
*blob
= (struct data_blob
*)val
;
653 guint32 len
= tvb_get_letohl(tvb
, offset
);
654 const guint8
*data
= tvb_get_ptr(tvb
, offset
+ 4, len
);
657 blob
->data
= se_memdup(data
, len
);
662 static int vvalue_tvb_bstr(tvbuff_t
*tvb
, int offset
, void *val
)
664 struct data_str
*str
= (struct data_str
*)val
;
665 guint32 len
= tvb_get_letohl(tvb
, offset
);
666 const void *ptr
= tvb_get_ptr(tvb
, offset
+ 4, len
);
668 //XXX this might be UTF-16
670 str
->str
= se_strndup(ptr
, len
);
674 static int vvalue_tvb_lpstr(tvbuff_t
*tvb
, int offset
, void *val
)
676 struct data_str
*str
= (struct data_str
*)val
;
679 str
->len
= tvb_get_letohl(tvb
, offset
);
680 str
->str
= tvb_get_seasonal_stringz(tvb
, offset
+ 4, &len
);
681 /* XXX test str->len == len */
685 static int vvalue_tvb_lpwstr(tvbuff_t
*tvb
, int offset
, void *val
)
687 struct data_str
*str
= (struct data_str
*)val
;
691 str
->len
= tvb_get_letohl(tvb
, offset
);
693 ptr
= tvb_get_ephemeral_unicode_stringz(tvb
, offset
+ 4, &len
, ENC_LITTLE_ENDIAN
);
694 str
->str
= se_strdup (ptr
);
699 static int vvalue_tvb_vector_internal(tvbuff_t
*tvb
, int offset
, struct vt_vector
*val
, struct vtype
*type
, int num
)
701 const int offset_in
= offset
;
702 const gboolean varsize
= (type
->size
== -1);
703 const int elsize
= varsize
? (int)sizeof(struct data_blob
) : type
->size
;
704 guint8
*data
= se_alloc(elsize
* num
);
708 val
->u
.vt_ui1
= data
;
709 DISSECTOR_ASSERT((void*)&val
->u
== ((void*)&val
->u
.vt_ui1
));
711 for (i
=0; i
<num
; i
++) {
712 len
= type
->tvb_get(tvb
, offset
, data
);
715 if (varsize
&& (offset
% 4) ) { /* at begin or end of loop ??? */
716 int padding
= 4 - (offset
% 4);
720 return offset
- offset_in
;
723 static int vvalue_tvb_vector(tvbuff_t
*tvb
, int offset
, struct vt_vector
*val
, struct vtype
*type
)
725 const int num
= tvb_get_letohl(tvb
, offset
);
726 return 4 + vvalue_tvb_vector_internal(tvb
, offset
+4, val
, type
, num
);
729 static void vvalue_strbuf_append_null(emem_strbuf_t
*strbuf _U_
, void *ptr _U_
)
732 static void vvalue_strbuf_append_i1(emem_strbuf_t
*strbuf
, void *ptr
)
734 gint8 i1
= *(gint8
*)ptr
;
735 ep_strbuf_append_printf(strbuf
, "%d", (int)i1
);
738 static void vvalue_strbuf_append_i2(emem_strbuf_t
*strbuf
, void *ptr
)
740 gint16 i2
= *(gint16
*)ptr
;
741 ep_strbuf_append_printf(strbuf
, "%d", (int)i2
);
744 static void vvalue_strbuf_append_i4(emem_strbuf_t
*strbuf
, void *ptr
)
746 gint32 i4
= *(gint32
*)ptr
;
747 ep_strbuf_append_printf(strbuf
, "%d", i4
);
750 static void vvalue_strbuf_append_i8(emem_strbuf_t
*strbuf
, void *ptr
)
752 gint64 i8
= *(gint64
*)ptr
;
753 ep_strbuf_append_printf(strbuf
, "%ld", i8
);
756 static void vvalue_strbuf_append_ui1(emem_strbuf_t
*strbuf
, void *ptr
)
758 guint8 ui1
= *(guint8
*)ptr
;
759 ep_strbuf_append_printf(strbuf
, "%u", (unsigned)ui1
);
762 static void vvalue_strbuf_append_ui2(emem_strbuf_t
*strbuf
, void *ptr
)
764 guint16 ui2
= *(guint16
*)ptr
;
765 ep_strbuf_append_printf(strbuf
, "%u", (unsigned)ui2
);
768 static void vvalue_strbuf_append_ui4(emem_strbuf_t
*strbuf
, void *ptr
)
770 guint32 ui4
= *(guint32
*)ptr
;
771 ep_strbuf_append_printf(strbuf
, "%d", ui4
);
774 static void vvalue_strbuf_append_ui8(emem_strbuf_t
*strbuf
, void *ptr
)
776 guint64 ui8
= *(guint64
*)ptr
;
777 ep_strbuf_append_printf(strbuf
, "%lu", ui8
);
780 static void vvalue_strbuf_append_r4(emem_strbuf_t
*strbuf
, void *ptr
)
782 float r4
= *(float*)ptr
;
783 ep_strbuf_append_printf(strbuf
, "%g", (double)r4
);
786 static void vvalue_strbuf_append_r8(emem_strbuf_t
*strbuf
, void *ptr
)
788 double r8
= *(double*)ptr
;
789 ep_strbuf_append_printf(strbuf
, "%g", r8
);
792 static void vvalue_strbuf_append_str(emem_strbuf_t
*strbuf
, void *ptr
)
794 struct data_str
*str
= (struct data_str
*)ptr
;
795 ep_strbuf_append_printf(strbuf
, "\"%s\"", str
->str
);
798 static void vvalue_strbuf_append_blob(emem_strbuf_t
*strbuf
, void *ptr
)
800 struct data_blob
*blob
= (struct data_blob
*)ptr
;
801 ep_strbuf_append_printf(strbuf
, "size: %d", (int)blob
->size
);
804 static void vvalue_strbuf_append_bool(emem_strbuf_t
*strbuf
, void *ptr
)
806 guint16 val
= *(guint
*)ptr
;
809 ep_strbuf_append(strbuf
, "False");
812 ep_strbuf_append(strbuf
, "True");
815 ep_strbuf_append_printf(strbuf
, "Invalid (0x%4x)", val
);
819 static void vvalue_strbuf_append_vector(emem_strbuf_t
*strbuf
, struct vt_vector val
, struct vtype
*type
)
821 const int elsize
= (type
->size
== -1) ? (int)sizeof(struct data_blob
) : type
->size
;
823 guint8
*data
= val
.u
.vt_ui1
;
824 ep_strbuf_append_c(strbuf
, '[');
825 for (i
=0; i
<val
.len
; i
++) {
827 ep_strbuf_append_c(strbuf
, ',');
829 type
->strbuf_append(strbuf
, data
);
832 ep_strbuf_append_c(strbuf
, ']');
836 static struct vtype VT_TYPE
[] = {
837 {VT_EMPTY
, "VT_EMPTY", 0, vvalue_tvb_get0
, vvalue_strbuf_append_null
},
838 {VT_NULL
, "VT_NULL", 0, vvalue_tvb_get0
, vvalue_strbuf_append_null
},
839 {VT_I2
, "VT_I2", 2, vvalue_tvb_get2
, vvalue_strbuf_append_i2
},
840 {VT_I4
, "VT_I4", 4, vvalue_tvb_get4
, vvalue_strbuf_append_i4
},
841 {VT_R4
, "VT_R4", 4, vvalue_tvb_get4
, vvalue_strbuf_append_r4
},
842 {VT_R8
, "VT_R8", 8, vvalue_tvb_get8
, vvalue_strbuf_append_r8
},
843 {VT_CY
, "VT_CY", 8, vvalue_tvb_get8
, vvalue_strbuf_append_i8
},
844 {VT_DATE
, "VT_DATE", 8, vvalue_tvb_get8
, vvalue_strbuf_append_r8
},
845 // {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_bstr, vvalue_strbuf_append_str},
846 {VT_BSTR
, "VT_BSTR", -1, vvalue_tvb_lpwstr
, vvalue_strbuf_append_str
},
847 {VT_ERROR
, "VT_ERROR", 8, vvalue_tvb_get4
, vvalue_strbuf_append_ui4
},
848 {VT_BOOL
, "VT_BOOL", 2, vvalue_tvb_get2
, vvalue_strbuf_append_bool
},
849 {VT_VARIANT
, "VT_VARIANT", -1, NULL
, NULL
},
850 {VT_DECIMAL
, "VT_DECIMAL", 16, NULL
, NULL
},
851 {VT_I1
, "VT_I1", 1, vvalue_tvb_get1
, vvalue_strbuf_append_i1
},
852 {VT_UI1
, "VT_UI1", 1, vvalue_tvb_get1
, vvalue_strbuf_append_ui1
},
853 {VT_UI2
, "VT_UI2", 2, vvalue_tvb_get2
, vvalue_strbuf_append_ui2
},
854 {VT_UI4
, "VT_UI4", 4, vvalue_tvb_get4
, vvalue_strbuf_append_ui4
},
855 {VT_I8
, "VT_I8", 8, vvalue_tvb_get8
, vvalue_strbuf_append_i8
},
856 {VT_UI8
, "VT_UI8", 8, vvalue_tvb_get8
, vvalue_strbuf_append_ui8
},
857 {VT_INT
, "VT_INT", 4, vvalue_tvb_get4
, vvalue_strbuf_append_i4
},
858 {VT_UINT
, "VT_UINT", 4, vvalue_tvb_get4
, vvalue_strbuf_append_ui4
},
859 {VT_LPSTR
, "VT_LPSTR", -1, vvalue_tvb_lpstr
, vvalue_strbuf_append_str
},
860 {VT_LPWSTR
, "VT_LPWSTR", -1, vvalue_tvb_lpwstr
, vvalue_strbuf_append_str
},
861 {VT_COMPRESSED_LPWSTR
, "VT_COMPRESSED_LPWSTR", -1, NULL
, vvalue_strbuf_append_str
},
862 {VT_FILETIME
, "VT_FILETIME", 8, vvalue_tvb_get8
, vvalue_strbuf_append_i8
},
863 {VT_BLOB
, "VT_BLOB", -1, vvalue_tvb_blob
, vvalue_strbuf_append_blob
},
864 {VT_BLOB_OBJECT
, "VT_BLOB_OBJECT", -1, vvalue_tvb_blob
, vvalue_strbuf_append_blob
},
865 {VT_CLSID
, "VT_CLSID", 16, NULL
, NULL
},
868 static struct vtype
*vType_get_type(enum vType t
) {
871 for (i
=0; i
<array_length(VT_TYPE
); i
++) {
872 if (t
== VT_TYPE
[i
].tag
) {
879 static char *str_CBaseStorageVariant(struct CBaseStorageVariant
*value
, gboolean print_type
)
882 emem_strbuf_t
*strbuf
= ep_strbuf_new(NULL
);
887 if (value
->type
== NULL
) {
892 ep_strbuf_append(strbuf
, value
->type
->str
);
894 if (value
->vType
& 0xFF00) {
895 ep_strbuf_append_printf(strbuf
, "[%d]", value
->vValue
.vt_vector
.len
);
897 ep_strbuf_append(strbuf
, ": ");
900 switch (value
->vType
& 0xFF00) {
902 value
->type
->strbuf_append(strbuf
, &value
->vValue
);
905 vvalue_strbuf_append_vector(strbuf
, value
->vValue
.vt_array
.vData
, value
->type
);
908 vvalue_strbuf_append_vector(strbuf
, value
->vValue
.vt_vector
, value
->type
);
911 ep_strbuf_append(strbuf
, "Invalid");
917 static int parse_CBaseStorageVariant(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
, proto_tree
*pad_tree _U_
,
918 struct CBaseStorageVariant
*value
, const char *text
)
921 proto_item
*ti
, *ti_type
, *ti_val
;
922 proto_tree
*tree
, *tr
;
923 enum vType baseType
, highType
;
927 ti
= proto_tree_add_text(parent_tree
, tvb
, offset
, 0, "%s", text
);
928 tree
= proto_item_add_subtree(ti
, ett_CBaseStorageVariant
);
930 value
->vType
= tvb_get_letohs(tvb
, offset
);
931 value
->type
= vType_get_type(value
->vType
);
933 ti_type
= proto_tree_add_text(tree
, tvb
, offset
, 2, "vType: %s", value
->type
->str
);
936 value
->vData1
= tvb_get_guint8(tvb
, offset
);
937 proto_tree_add_text(tree
, tvb
, offset
, 1, "vData1: %d", value
->vData1
);
940 value
->vData2
= tvb_get_guint8(tvb
, offset
);
941 proto_tree_add_text(tree
, tvb
, offset
, 1, "vData2: %d", value
->vData2
);
944 baseType
= value
->vType
& 0x00FF;
945 highType
= value
->vType
& 0xFF00;
947 if (value
->type
== NULL
) {
951 ti_val
= proto_tree_add_text(tree
, tvb
, offset
, 0, "vValue");
955 len
= value
->type
->tvb_get(tvb
, offset
, &value
->vValue
.vt_single
);
959 proto_item_append_text(ti_type
, "|VT_VECTOR");
960 tr
= proto_item_add_subtree(ti_val
, ett_CBaseStorageVariant_Vector
);
962 len
= vvalue_tvb_vector(tvb
, offset
, &value
->vValue
.vt_vector
, value
->type
);
963 proto_tree_add_text(tr
, tvb
, offset
, 4, "num: %d", value
->vValue
.vt_vector
.len
);
967 guint16 cDims
, fFeatures
;
968 guint32 cbElements
, cElements
, lLbound
;
971 proto_item_append_text(ti_type
, "|VT_ARRAY");
972 tr
= proto_item_add_subtree(ti_val
, ett_CBaseStorageVariant_Array
);
974 cDims
= tvb_get_letohs(tvb
, offset
);
975 proto_tree_add_text(tr
, tvb
, offset
, 2, "cDims: %d", cDims
);
978 fFeatures
= tvb_get_letohs(tvb
, offset
);
979 proto_tree_add_text(tr
, tvb
, offset
, 2, "fFeaturess: %d", fFeatures
);
982 cbElements
= tvb_get_letohl(tvb
, offset
);
983 proto_tree_add_text(tr
, tvb
, offset
, 4, "cbElements: %d", cbElements
);
985 for (i
=0; i
<cDims
; i
++) {
986 cElements
= tvb_get_letohl(tvb
, offset
);
987 lLbound
= tvb_get_letohl(tvb
, offset
+ 4);
988 proto_tree_add_text(tr
, tvb
, offset
, 8, "Rgsabound[%d]: (%d:%d)", i
, cElements
, lLbound
);
993 len
= vvalue_tvb_vector_internal(tvb
, offset
, &value
->vValue
.vt_array
.vData
, value
->type
, num
);
998 proto_item_append_text(ti_type
, "|0x%x", highType
);
1000 proto_item_set_end(ti
, tvb
, offset
);
1001 proto_item_set_end(ti_val
, tvb
, offset
);
1003 proto_item_append_text(ti_val
, " %s", str_CBaseStorageVariant(value
, false));
1004 proto_item_append_text(ti
, " %s", str_CBaseStorageVariant(value
, true));
1009 proto_item_append_text(ti
, ": sorry, vType %02x not handled yet!", (unsigned)value
->vType
);
1015 DBKIND_GUID_NAME
= 0,
1016 DBKIND_GUID_PROPID
= 1
1019 static int parse_CDbColId(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
, proto_tree
*pad_tree
, const char *text
)
1021 guint32 eKind
, ulId
;
1023 static const char *KIND
[] = {"DBKIND_GUID_NAME", "DBKIND_GUID_PROPID"};
1025 proto_item
*tree_item
= proto_tree_add_text(parent_tree
, tvb
, offset
, 0, "%s", text
);
1026 proto_tree
*tree
= proto_item_add_subtree(tree_item
, ett_CDbColId
);
1028 eKind
= tvb_get_letohl(tvb
, offset
);
1029 proto_tree_add_text(tree
, tvb
, offset
, 4, "eKind: %s (%u)", eKind
< 2 ? KIND
[eKind
] : "???", eKind
);
1032 offset
= parse_padding(tvb
, offset
, 8, pad_tree
, "paddingGuidAlign");
1034 offset
= parse_guid(tvb
, offset
, tree
, &guid
, "GUID");
1036 ulId
= tvb_get_letohl(tvb
, offset
);
1037 proto_tree_add_text(tree
, tvb
, offset
, 4, "ulId: %d", ulId
);
1040 if (eKind
== DBKIND_GUID_NAME
) {
1042 int len
= ulId
; //*2 ???
1043 name
= tvb_get_unicode_string(tvb
, offset
, len
, ENC_LITTLE_ENDIAN
);
1044 proto_tree_add_text(tree
, tvb
, offset
, len
, "vString: \"%s\"", name
);
1045 proto_item_append_text(tree_item
, " \"%s\"", name
);
1047 } else if (eKind
== DBKIND_GUID_PROPID
) {
1048 proto_item_append_text(tree_item
, " %08x", ulId
);
1050 proto_item_append_text(tree_item
, "<INVALID>");
1053 proto_item_set_end(tree_item
, tvb
, offset
);
1058 struct GuidPropertySet
{
1062 const value_string
*id_map
;
1065 static int parse_CDbProp(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
1066 proto_tree
*pad_tree
, struct GuidPropertySet
*propset
,
1067 const char *fmt
, ...)
1069 static const value_string EMPTY_VS
[] = {{0, NULL
}};
1070 const value_string
*vs
= (propset
&& propset
->id_map
) ? propset
->id_map
: EMPTY_VS
;
1071 guint32 id
, opt
, status
;
1072 struct CBaseStorageVariant value
;
1079 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1082 tree
= proto_item_add_subtree(item
, ett_CDbProp
);
1084 id
= tvb_get_letohl(tvb
, offset
);
1085 str
= val_to_str(id
, vs
, "0x%08x");
1086 proto_tree_add_text(tree
, tvb
, offset
, 4, "Id: %s (0x%08x)", str
[0] == '0' ? "" : str
, id
);
1088 proto_item_append_text(item
, " Id: %s", str
);
1090 opt
= tvb_get_letohl(tvb
, offset
);
1091 proto_tree_add_text(tree
, tvb
, offset
, 4, "Options: %08x", opt
);
1094 status
= tvb_get_letohl(tvb
, offset
);
1095 proto_tree_add_text(tree
, tvb
, offset
, 4, "Status: %08x", status
);
1098 offset
= parse_CDbColId(tvb
, offset
, tree
, pad_tree
, "colid");
1100 offset
= parse_CBaseStorageVariant(tvb
, offset
, tree
, pad_tree
, &value
, "vValue");
1102 str
= str_CBaseStorageVariant(&value
, true);
1103 proto_item_append_text(item
, " %s", str
);
1104 proto_item_set_end(item
, tvb
, offset
);
1110 static const value_string DBPROPSET_FSCIFRMWRK_EXT_IDS
[] = {
1111 {0x02, "DBPROP_CI_CATALOG_NAME"},
1112 {0x03, "DBPROP_CI_INCLUDE_SCOPES"},
1113 {0x04, "DBPROP_CI_SCOPE_FLAGS"},
1114 {0x07, "DBPROP_CI_QUERY_TYPE"},
1118 static const value_string DBPROPSET_QUERYEXT_IDS
[] = {
1119 {0x02, "DBPROP_USECONTENTINDEX"},
1120 {0x03, "DBPROP_DEFERNONINDEXEDTRIMMING"},
1121 {0x04, "DBPROP_USEEXTENDEDDBTYPES"},
1122 {0x05, "DBPROP_IGNORENOISEONLYCLAUSES"},
1123 {0x06, "DBPROP_GENERICOPTIONS_STRING"},
1124 {0x07, "DBPROP_FIRSTROWS"},
1125 {0x08, "DBPROP_DEFERCATALOGVERIFICATION"},
1126 {0x0a, "DBPROP_GENERATEPARSETREE"},
1127 {0x0c, "DBPROP_FREETEXTANYTERM"},
1128 {0x0d, "DBPROP_FREETEXTUSESTEMMING"},
1129 {0x0e, "DBPROP_IGNORESBRI"},
1130 {0x10, "DBPROP_ENABLEROWSETEVENTS"},
1134 static const value_string DBPROPSET_CIFRMWRKCORE_EXT_IDS
[] = {
1135 {0x02, "DBPROP_MACHINE"},
1136 {0x03, "DBPROP_CLIENT_CLSID"},
1140 static const value_string DBPROPSET_MSIDXS_ROWSETEXT_IDS
[] = {
1141 {0x02, "MSIDXSPROP_ROWSETQUERYSTATUS"},
1142 {0x03, "MSIDXSPROP_COMMAND_LOCALE_STRING"},
1143 {0x04, "MSIDXSPROP_QUERY_RESTRICTION"},
1144 {0x05, "MSIDXSPROP_PARSE_TREE"},
1145 {0x06, "MSIDXSPROP_MAX_RANK"},
1146 {0x07, "MSIDXSPROP_RESULTS_FOUND"},
1150 static struct GuidPropertySet GuidPropertySet
[] = {
1151 {{0xa9bd1526, 0x6a80, 0x11d0, {0x8c, 0x9d, 0x00, 0x20, 0xaf, 0x1d, 0x74, 0x0e}},
1152 "DBPROPSET_FSCIFRMWRK_EXT", "File system content index framework",
1153 DBPROPSET_FSCIFRMWRK_EXT_IDS
},
1154 {{0xa7ac77ed, 0xf8d7, 0x11ce, {0xa7, 0x98, 0x00, 0x20, 0xf8, 0x00, 0x80, 0x25}},
1155 "DBPROPSET_QUERYEXT", "Query extension",
1156 DBPROPSET_QUERYEXT_IDS
},
1157 {{0xafafaca5, 0xb5d1, 0x11d0, {0x8c, 0x62, 0x00, 0xc0, 0x4f, 0xc2, 0xdb, 0x8d}},
1158 "DBPROPSET_CIFRMWRKCORE_EXT", "Content index framework core",
1159 DBPROPSET_CIFRMWRKCORE_EXT_IDS
},
1160 {{0xAA6EE6B0, 0xE828, 0x11D0, {0xB2, 0x3E, 0x00, 0xAA, 0x00, 0x47, 0xFC, 0x01}},
1161 "DBPROPSET_MSIDXS_ROWSETEXT", "???",
1162 DBPROPSET_MSIDXS_ROWSETEXT_IDS
},
1165 static struct GuidPropertySet
*GuidPropertySet_find_guid(const e_guid_t
*guid
)
1168 for (i
=0; i
<array_length(GuidPropertySet
); i
++) {
1169 if (guid_cmp(&GuidPropertySet
[i
].guid
, guid
) == 0) {
1170 return &GuidPropertySet
[i
];
1176 static int parse_CDbPropSet(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
1177 proto_tree
*pad_tree
, const char *fmt
, ...)
1181 struct GuidPropertySet
*pset
;
1187 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1190 tree
= proto_item_add_subtree(item
, ett_CDbPropSet
);
1192 offset
= parse_guid(tvb
, offset
, tree
, &guid
, "guidPropertySet");
1194 pset
= GuidPropertySet_find_guid(&guid
);
1197 proto_item_append_text(item
, " \"%s\" (%s)", pset
->desc
, pset
->def
);
1199 const char *guid_str
= guid_to_str(&guid
);
1200 proto_item_append_text(item
, " {%s}", guid_str
);
1203 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "guidPropertySet");
1205 num
= tvb_get_letohl(tvb
, offset
);
1206 proto_tree_add_text(tree
, tvb
, offset
, 4, "cProperties: %d", num
);
1208 proto_item_append_text(item
, " Num: %d", num
);
1210 for (i
= 0; i
<num
; i
++) {
1211 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "aProp[%d]", i
);
1212 offset
= parse_CDbProp(tvb
, offset
, tree
, pad_tree
, pset
, "aProp[%d]", i
);
1215 proto_item_set_end(item
, tvb
, offset
);
1219 static int parse_PropertySetArray(tvbuff_t
*tvb
, int offset
, int size_offset
,
1220 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
1221 const char *fmt
, ...)
1223 const int offset_in
= offset
;
1231 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1234 tree
= proto_item_add_subtree(item
, ett_CDbPropSet_Array
);
1236 size
= tvb_get_letohl(tvb
, size_offset
);
1237 proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_Blob1
, tvb
,
1238 size_offset
, 4, ENC_LITTLE_ENDIAN
);
1240 num
= tvb_get_letohl(tvb
, offset
);
1241 proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_PropSets_num
, tvb
,
1242 offset
, 4, ENC_LITTLE_ENDIAN
);
1245 for (i
= 0; i
< (int)num
; i
++) {
1246 offset
= parse_CDbPropSet(tvb
, offset
, tree
, pad_tree
, "PropertySet[%d]", i
);
1249 proto_item_set_end(item
, tvb
, offset
);
1250 DISSECTOR_ASSERT(offset
- offset_in
== (int)size
);
1254 int parse_CColumnSet(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
, const char *fmt
, ...)
1256 guint32 count
, v
, i
;
1262 item
= proto_tree_add_text_valist(tree
, tvb
, offset
, 0, fmt
, ap
);
1265 count
= tvb_get_letohl(tvb
, offset
);
1268 proto_item_append_text(item
, " Count %u [", count
);
1269 for (i
=0; i
<count
; i
++) {
1270 v
= tvb_get_letohl(tvb
, offset
);
1273 proto_item_append_text(item
, ",%u", v
);
1275 proto_item_append_text(item
, "%u", v
);
1278 proto_item_append_text(item
, "]");
1282 /* 2.2.1.23 RANGEBOUNDARY */
1283 int parse_RANGEBOUNDARY(tvbuff_t
*tvb
, int offset
, proto_tree
*parent_tree
,
1284 proto_tree
*pad_tree
, const char *fmt
, ...)
1287 guint8 labelPresent
;
1290 struct CBaseStorageVariant prval
;
1294 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1295 tree
= proto_item_add_subtree(item
, ett_RANGEBOUNDARY
);
1298 ulType
= tvb_get_letohl(tvb
, offset
);
1299 proto_tree_add_text(tree
, tvb
, offset
, 4, "ulType 0x%08x", ulType
);
1300 proto_item_append_text(item
, ": Type 0x%08x", ulType
);
1304 offset
= parse_CBaseStorageVariant(tvb
, offset
, tree
, pad_tree
, &prval
, "prVal");
1306 labelPresent
= tvb_get_guint8(tvb
, offset
);
1307 proto_tree_add_text(tree
, tvb
, offset
, 1, "labelPresent: %s", labelPresent
? "True" : "False");
1313 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "paddingLabelPresent");
1315 ccLabel
= tvb_get_letohl(tvb
, offset
);
1316 proto_tree_add_text(tree
, tvb
, offset
, 4, "ccLabel: %u", ccLabel
);
1319 label
= tvb_get_unicode_string(tvb
, offset
, 2*ccLabel
, ENC_LITTLE_ENDIAN
);
1320 proto_tree_add_text(tree
, tvb
, offset
, 2*ccLabel
, "Label: \"%s\"", label
);
1321 proto_item_append_text(item
, " Label: \"%s\"", label
);
1322 offset
+= 2*ccLabel
;
1325 proto_item_append_text(item
, " Val: %s", str_CBaseStorageVariant(&prval
, true));
1327 proto_item_set_end(item
, tvb
, offset
);
1332 /* 2.2.1.22 CRangeCategSpec */
1333 int parse_CRangeCategSpec(tvbuff_t
*tvb
, int offset
,
1334 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
1335 const char *fmt
, ...)
1341 guint32 lcid
, cRange
;
1344 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1345 tree
= proto_item_add_subtree(item
, ett_CRangeCategSpec
);
1348 lcid
= tvb_get_letohl(tvb
, offset
);
1349 proto_tree_add_text(tree
, tvb
, offset
, 4, "Lcid 0x%08x", lcid
);
1352 cRange
= tvb_get_letohl(tvb
, offset
);
1353 proto_tree_add_text(tree
, tvb
, offset
, 4, "cRange 0x%08x", cRange
);
1356 for (i
=0; i
<cRange
; i
++) {
1357 offset
= parse_RANGEBOUNDARY(tvb
, offset
, tree
, pad_tree
, "aRangeBegin[%u]", i
);
1361 proto_item_set_end(item
, tvb
, offset
);
1365 /* 2.2.1.21 CCategSpec */
1366 int parse_CCategSpec(tvbuff_t
*tvb
, int offset
,
1367 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
1368 const char *fmt
, ...)
1377 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1378 tree
= proto_item_add_subtree(item
, ett_CCategSpec
);
1381 type
= tvb_get_letohl(tvb
, offset
);
1382 proto_tree_add_text(tree
, tvb
, offset
, 4, "Type 0x%08x", type
);
1383 proto_item_append_text(item
, " Type %u", type
);
1386 proto_tree_add_text(tree
, tvb
, offset
, 16, "CSort");
1389 offset
= parse_CRangeCategSpec(tvb
, offset
, tree
, pad_tree
, "CRangeCategSpec");
1391 proto_item_set_end(item
, tvb
, offset
);
1395 /* 2.2.1.25 CAggregSpec */
1396 static int parse_CAggregSpec(tvbuff_t
*tvb
, int offset
,
1397 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
1398 const char *fmt
, ...)
1404 guint32 ccAlias
, idColumn
, ulMaxNumToReturn
, idRepresentative
;
1408 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1409 tree
= proto_item_add_subtree(item
, ett_CAggregSpec
);
1412 type
= tvb_get_guint8(tvb
, offset
);
1413 proto_tree_add_text(tree
, tvb
, offset
, 1, "type: %u", type
);
1414 proto_item_append_text(item
, "type: %u", type
);
1417 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "padding");
1419 ccAlias
= tvb_get_letohl(tvb
, offset
);
1420 proto_tree_add_text(tree
, tvb
, offset
, 1, "ccAlias: %u", ccAlias
);
1423 alias
= tvb_get_unicode_string(tvb
, offset
, 2*ccAlias
, ENC_LITTLE_ENDIAN
);
1424 proto_tree_add_text(tree
, tvb
, offset
, 2*ccAlias
, "Alias: %s", alias
);
1425 offset
+= 2*ccAlias
;
1427 idColumn
= tvb_get_letohl(tvb
, offset
);
1428 proto_tree_add_text(tree
, tvb
, offset
, 1, "idColumn: %u", idColumn
);
1431 ulMaxNumToReturn, idRepresentative;
1434 proto_item_set_end(item
, tvb
, offset
);
1438 /* 2.2.1.24 CAggregSet */
1439 static int parse_CAggregSet(tvbuff_t
*tvb
, int offset
,
1440 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
1441 const char *fmt
, ...)
1450 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1451 tree
= proto_item_add_subtree(item
, ett_CAggregSet
);
1454 cCount
= tvb_get_letohl(tvb
, offset
);
1455 proto_tree_add_text(tree
, tvb
, offset
, 4, "count: %u", cCount
);
1458 for (i
=0; i
<cCount
; i
++) {
1459 /* 2.2.1.25 CAggregSpec */
1460 offset
= parse_CAggregSpec(tvb
, offset
, tree
, pad_tree
, "AggregSpecs[%u]", i
);
1463 proto_item_set_end(item
, tvb
, offset
);
1467 /* 2.2.1.27 CAggregSortKey */
1468 static int parse_CAggregSortKey(tvbuff_t
*tvb
, int offset
,
1469 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
1470 const char *fmt
, ...)
1479 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1480 tree
= proto_item_add_subtree(item
, ett_CAggregSortKey
);
1483 order
= tvb_get_letohl(tvb
, offset
);
1484 proto_tree_add_text(tree
, tvb
, offset
, 4, "order: %u", order
);
1487 offset
= parse_CAggregSpec(tvb
, offset
, tree
, pad_tree
, "ColumnSpec");
1489 proto_item_set_end(item
, tvb
, offset
);
1494 /* 2.2.1.26 CSortAggregSet */
1495 static int parse_CSortAggregSet(tvbuff_t
*tvb
, int offset
,
1496 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
1497 const char *fmt
, ...)
1506 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1507 tree
= proto_item_add_subtree(item
, ett_CSortAggregSet
);
1510 cCount
= tvb_get_letohl(tvb
, offset
);
1511 proto_tree_add_text(tree
, tvb
, offset
, 4, "count: %u", cCount
);
1514 for (i
=0; i
<cCount
; i
++) {
1515 /* 2.2.1.27 CAggregSortKey */
1516 offset
= parse_CAggregSortKey(tvb
, offset
, tree
, pad_tree
, "SortKeys[%u]", i
);
1519 proto_item_set_end(item
, tvb
, offset
);
1523 enum CInGroupSortAggregSet_type
{
1524 GroupIdDefault
= 0x00, /* The default for all ranges. */
1525 GroupIdMinValue
= 0x01, /*The first range in the parent's group.*/
1526 GroupIdNull
= 0x02, /*The last range in the parent's group.*/
1527 GroupIdValue
= 0x03,
1530 /* 2.2.1.29 CInGroupSortAggregSet */
1531 static int parse_CInGroupSortAggregSet(tvbuff_t
*tvb
, int offset
,
1532 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
1533 const char *fmt
, ...)
1538 enum CInGroupSortAggregSet_type type
;
1541 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1542 tree
= proto_item_add_subtree(item
, ett_CInGroupSortAggregSet
);
1545 type
= tvb_get_guint8(tvb
, offset
);
1546 proto_tree_add_text(tree
, tvb
, offset
, 1, "Type: 0x%02x", (unsigned)type
);
1549 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "CInGroupSortAggregSet");
1551 if (type
== GroupIdValue
) {
1552 struct CBaseStorageVariant id
;
1553 offset
= parse_CBaseStorageVariant(tvb
, offset
, tree
, pad_tree
, &id
, "inGroupId");
1556 offset
= parse_CSortAggregSet(tvb
, offset
, tree
, pad_tree
, "SortAggregSet");
1558 proto_item_set_end(item
, tvb
, offset
);
1563 /* 2.2.1.28 CInGroupSortAggregSets */
1564 static int parse_CInGroupSortAggregSets(tvbuff_t
*tvb
, int offset
,
1565 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
1566 const char *fmt
, ...)
1575 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1576 tree
= proto_item_add_subtree(item
, ett_CInGroupSortAggregSets
);
1579 cCount
= tvb_get_letohl(tvb
, offset
);
1580 proto_tree_add_text(tree
, tvb
, offset
, 4, "count: %u", cCount
);
1583 for (i
=0; i
<cCount
; i
++) {
1584 /* 2.2.1.29 CInGroupSortAggregSet */
1585 offset
= parse_CInGroupSortAggregSet(tvb
, offset
, tree
, pad_tree
, "SortSets[%u]", i
);
1588 proto_item_set_end(item
, tvb
, offset
);
1592 /* 2.2.1.20 CCategorizationSpec */
1593 int parse_CCategorizationSpec(tvbuff_t
*tvb
, int offset
,
1594 proto_tree
*parent_tree
, proto_tree
*pad_tree
,
1595 const char *fmt
, ...)
1597 guint32 cMaxResults
;
1604 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1605 tree
= proto_item_add_subtree(item
, ett_CCategorizationSpec
);
1608 /* 2.2.1.18 CColumnSet */
1609 offset
= parse_CColumnSet(tvb
, offset
, tree
, "csColumns");
1611 /* 2.2.1.21 CCategSpec */
1612 offset
= parse_CCategSpec(tvb
, offset
, tree
, pad_tree
, "Spec");
1614 /* 2.2.1.24 CAggregSet */
1615 offset
= parse_CAggregSet(tvb
, offset
, tree
, pad_tree
, "AggregSet");
1617 /* 2.2.1.26 CSortAggregSet */
1618 offset
= parse_CSortAggregSet(tvb
, offset
, tree
, pad_tree
, "SortAggregSet");
1620 /* 2.2.1.28 CInGroupSortAggregSets */
1621 offset
= parse_CInGroupSortAggregSets(tvb
, offset
, tree
, pad_tree
, "InGroupSortAggregSets");
1623 cMaxResults
= tvb_get_letohl(tvb
, offset
);
1624 proto_tree_add_text(tree
, tvb
, offset
, 4, "cMaxResults: %u", cMaxResults
);
1627 proto_item_set_end(item
, tvb
, offset
);
1631 int parse_CRowsetProperties(tvbuff_t
*tvb
, int offset
,
1632 proto_tree
*parent_tree
, proto_tree
*pad_tree _U_
,
1633 const char *fmt
, ...)
1642 item
= proto_tree_add_text_valist(parent_tree
, tvb
, offset
, 0, fmt
, ap
);
1643 tree
= proto_item_add_subtree(item
, ett_CRowsetProperties
);
1646 proto_tree_add_text(tree
, tvb
, offset
, 4, "uBooleanOptions");
1649 proto_tree_add_text(tree
, tvb
, offset
, 4, "ulMaxOpenRows (ignored)");
1652 proto_tree_add_text(tree
, tvb
, offset
, 4, "ulMemoryUsage (ignored)");
1655 proto_tree_add_text(tree
, tvb
, offset
, 4, "cMaxResults");
1658 proto_tree_add_text(tree
, tvb
, offset
, 4, "cCmdTimeout");
1661 proto_item_set_end(item
, tvb
, offset
);
1667 /* Code to actually dissect the packets */
1669 static int dissect_CPMConnect(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, gboolean in
)
1677 ti
= proto_tree_add_item(parent_tree
, hf_mswsp_msg
, tvb
, offset
, -1, ENC_NA
);
1678 tree
= proto_item_add_subtree(ti
, ett_mswsp_msg
);
1679 proto_item_set_text(ti
, "CPMConnect%s", in
? "In" : "Out");
1680 col_append_str(pinfo
->cinfo
, COL_INFO
, "Connect");
1682 version
= tvb_get_letohl(tvb
, offset
);
1683 ti
= proto_tree_add_item(tree
, hf_mswsp_msg_Connect_Version
, tvb
,
1684 offset
, 4, ENC_LITTLE_ENDIAN
);
1685 if (version
& 0xffff0000) {
1686 proto_item_append_text(ti
, " 64 bit");
1688 switch (version
& 0xffff) {
1690 proto_item_append_text(ti
, " w2k8 or vista");
1693 proto_item_append_text(ti
, " XP or w2k3, with Windows Search 4.0");
1696 proto_item_append_text(ti
, " win7 or w2k8r2");
1702 guint32 blob_size1_off
, blob_size2_off
;
1703 proto_tree
*pad_tree
;
1705 ti
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Padding");
1706 pad_tree
= proto_item_add_subtree(ti
, ett_mswsp_pad
);
1708 proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_ClientIsRemote
, tvb
,
1709 offset
, 4, ENC_LITTLE_ENDIAN
);
1713 blob_size1_off
= offset
;
1716 offset
= parse_padding(tvb
, offset
, 8, pad_tree
, "_paddingcbBlob2");
1719 blob_size2_off
= offset
;
1722 offset
= parse_padding(tvb
, offset
, 16, pad_tree
, "_padding");
1724 len
= tvb_unicode_strsize(tvb
, offset
);
1725 ti
= proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_MachineName
, tvb
,
1726 offset
, len
, ENC_UTF_16
);
1727 /*This shouldnt be necessary, is this a bug or is there some GUI setting I've missed?*/
1728 proto_item_set_text(ti
, "Remote machine: %s",
1729 tvb_get_unicode_string(tvb
, offset
, len
, ENC_LITTLE_ENDIAN
));
1732 len
= tvb_unicode_strsize(tvb
, offset
);
1733 ti
= proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_UserName
, tvb
,
1734 offset
, len
, ENC_UTF_16
);
1735 proto_item_set_text(ti
, "User: %s", tvb_get_unicode_string(tvb
, offset
, len
, ENC_LITTLE_ENDIAN
));
1738 offset
= parse_padding(tvb
, offset
, 8, pad_tree
, "_paddingcPropSets");
1740 offset
= parse_PropertySetArray(tvb
, offset
, blob_size1_off
, tree
, pad_tree
, "PropSets");
1742 offset
= parse_padding(tvb
, offset
, 8, pad_tree
, "paddingExtPropset");
1744 offset
= parse_PropertySetArray(tvb
, offset
, blob_size2_off
, tree
, pad_tree
, "ExtPropset");
1746 offset
= parse_padding(tvb
, offset
, 8, pad_tree
, "???");
1748 DISSECTOR_ASSERT(offset
== (int)tvb_length(tvb
));
1750 /* make "Padding" the last item */
1751 proto_tree_move_item(tree
, ti
, proto_tree_get_parent(pad_tree
));
1755 return tvb_length(tvb
);
1758 static int dissect_CPMDisconnect(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1760 col_append_str(pinfo
->cinfo
, COL_INFO
, "Disconnect");
1761 return tvb_length(tvb
);
1764 static int dissect_CPMCreateQuery(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, gboolean in
)
1770 ti
= proto_tree_add_item(parent_tree
, hf_mswsp_msg
, tvb
, offset
, -1, ENC_NA
);
1771 tree
= proto_item_add_subtree(ti
, ett_mswsp_msg
);
1773 proto_item_set_text(ti
, "CPMCreateQuery%s", in
? "In" : "Out");
1774 col_append_str(pinfo
->cinfo
, COL_INFO
, "CreateQuery");
1777 proto_item
*ti
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Padding");
1778 proto_tree
*pad_tree
= proto_item_add_subtree(ti
, ett_mswsp_pad
);
1779 guint8 CColumnSetPresent
, CRestrictionPresent
, CSortSetPresent
, CCategorizationSetPresent
;
1780 guint32 size
= tvb_get_letohl(tvb
, offset
);
1781 proto_tree_add_text(tree
, tvb
, offset
, 4, "size");
1782 proto_tree_add_text(tree
, tvb
, offset
, size
, "ALL");
1785 CColumnSetPresent
= tvb_get_guint8(tvb
, offset
);
1786 proto_tree_add_text(tree
, tvb
, offset
, 1, "CColumnSetPresent: %s", CColumnSetPresent
? "True" : "False");
1789 if (CColumnSetPresent
) {
1790 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "paddingCColumnSetPresent");
1791 offset
= parse_CColumnSet(tvb
, offset
, tree
, "CColumnSet");
1794 CRestrictionPresent
= tvb_get_guint8(tvb
, offset
);
1795 proto_tree_add_text(tree
, tvb
, offset
, 1, "CRestrictionPresent: %s", CColumnSetPresent
? "True" : "False");
1797 if (CRestrictionPresent
) {
1798 guint8 count
, present
;
1800 count
= tvb_get_guint8(tvb
, offset
);
1801 present
= tvb_get_guint8(tvb
, offset
);
1802 ti
= proto_tree_add_text(tree
, tvb
, offset
, 0, "CRestrictionSet: count %d", count
);
1805 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "paddingCRestrictionPresent");
1807 for (i
=0; i
<count
; i
++) {
1808 struct CRestriction r
;
1809 offset
= parse_CRestriction(tvb
, offset
, tree
, pad_tree
, &r
, "CRestrictionSet[%d]", i
);
1812 proto_item_set_end(ti
, tvb
, offset
);
1815 CSortSetPresent
= tvb_get_guint8(tvb
, offset
);
1816 proto_tree_add_text(tree
, tvb
, offset
, 1, "CSortSetPresent: %s", CSortSetPresent
? "True" : "False");
1818 if (CSortSetPresent
) {
1820 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "paddingCSortSetPresent");
1821 /*2.2.1.43 CSortSet */
1822 /*2.2.1.10 CSort 16Bytes */
1823 count
= tvb_get_letohl(tvb
, offset
);
1824 proto_tree_add_text(tree
, tvb
, offset
, 4 + 16*count
, "CSortSet: count %u", count
);
1825 offset
+= (4 + 16*count
);
1828 CCategorizationSetPresent
= tvb_get_guint8(tvb
, offset
);
1829 proto_tree_add_text(tree
, tvb
, offset
, 1, "CCategorizationSetPresent: %s", CCategorizationSetPresent
? "True" : "False");
1832 if (CCategorizationSetPresent
) {
1834 offset
= parse_padding(tvb
, offset
, 4, pad_tree
, "paddingCCategorizationSetPresent");
1835 /* 2.2.1.19 CCategorizationSet */
1836 count
= tvb_get_letohl(tvb
, offset
);
1837 proto_tree_add_text(tree
, tvb
, offset
, 4, "count: %u", count
);
1839 for (i
=0; i
<count
; i
++) {
1840 offset
= parse_CCategorizationSpec(tvb
, offset
, tree
, pad_tree
, "categories[%u]", i
);
1844 offset
= parse_CRowsetProperties(tvb
, offset
, tree
, pad_tree
, "RowSetProperties");
1847 return tvb_length(tvb
);
1850 static int dissect_CPMFreeCursor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1852 col_append_str(pinfo
->cinfo
, COL_INFO
, "FreeCursor");
1853 return tvb_length(tvb
);
1856 static int dissect_CPMGetRows(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1858 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetRows");
1859 return tvb_length(tvb
);
1862 static int dissect_CPMRatioFinished(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1864 col_append_str(pinfo
->cinfo
, COL_INFO
, "RatioFinished");
1865 return tvb_length(tvb
);
1868 static int dissect_CPMCompareBmk(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1870 col_append_str(pinfo
->cinfo
, COL_INFO
, "CompareBmk");
1871 return tvb_length(tvb
);
1874 static int dissect_CPMGetApproximatePosition(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1876 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetApproximatePosition");
1877 return tvb_length(tvb
);
1880 static int dissect_CPMSetBindings(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1882 col_append_str(pinfo
->cinfo
, COL_INFO
, "SetBindings");
1883 return tvb_length(tvb
);
1886 static int dissect_CPMGetNotify(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1888 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetNotify");
1889 return tvb_length(tvb
);
1892 static int dissect_CPMSendNotifyOut(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1894 col_append_str(pinfo
->cinfo
, COL_INFO
, "SendNotify");
1895 return tvb_length(tvb
);
1898 static int dissect_CPMGetQueryStatus(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1900 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetQueryStatus");
1901 return tvb_length(tvb
);
1904 static int dissect_CPMCiState(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1906 col_append_str(pinfo
->cinfo
, COL_INFO
, "CiState");
1907 return tvb_length(tvb
);
1910 static int dissect_CPMFetchValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1912 col_append_str(pinfo
->cinfo
, COL_INFO
, "FetchValue");
1913 return tvb_length(tvb
);
1916 static int dissect_CPMGetQueryStatusEx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1918 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetQueryStatusEx");
1919 return tvb_length(tvb
);
1922 static int dissect_CPMRestartPosition(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1924 col_append_str(pinfo
->cinfo
, COL_INFO
, "RestartPosition");
1925 return tvb_length(tvb
);
1928 static int dissect_CPMSetCatState(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1930 col_append_str(pinfo
->cinfo
, COL_INFO
, "SetCatState");
1931 return tvb_length(tvb
);
1934 static int dissect_CPMGetRowsetNotify(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1936 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetRowsetNotify");
1937 return tvb_length(tvb
);
1940 static int dissect_CPMFindIndices(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1942 col_append_str(pinfo
->cinfo
, COL_INFO
, "FindIndices");
1943 return tvb_length(tvb
);
1946 static int dissect_CPMSetScopePrioritization(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1948 col_append_str(pinfo
->cinfo
, COL_INFO
, "SetScopePrioritization");
1949 return tvb_length(tvb
);
1952 static int dissect_CPMGetScopeStatistics(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
1954 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetScopeStatistics");
1955 return tvb_length(tvb
);
1960 dissect_mswsp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, gboolean in
)
1962 static const char *dbg_wait
= NULL
;
1963 static int wait_frame
= -1;
1965 proto_tree
*mswsp_tree
= NULL
;
1972 int (*fn
)(tvbuff_t
*, packet_info
*, proto_tree
*, gboolean
);
1974 if (tvb_length(tvb
) < 16) {
1978 if (dbg_wait
== NULL
) {
1979 dbg_wait
= getenv("DBG_FRAME");
1980 if (dbg_wait
== NULL
) {
1983 wait_frame
= atoi(dbg_wait
);
1987 if ((int)pinfo
->fd
->num
== wait_frame
) {
1988 static volatile gboolean wait
= 1;
1994 hdr
.msg
= tvb_get_letohl(tvb
, 0);
1998 fn
= dissect_CPMConnect
;
2001 fn
= dissect_CPMDisconnect
;
2004 fn
= dissect_CPMCreateQuery
;
2007 fn
= dissect_CPMFreeCursor
;
2010 fn
= dissect_CPMGetRows
;
2013 fn
= dissect_CPMRatioFinished
;
2016 fn
= dissect_CPMCompareBmk
;
2019 fn
= dissect_CPMGetApproximatePosition
;
2022 fn
= dissect_CPMSetBindings
;
2025 fn
= dissect_CPMGetNotify
;
2028 fn
= dissect_CPMSendNotifyOut
;
2031 fn
= dissect_CPMGetQueryStatus
;
2034 fn
= dissect_CPMCiState
;
2037 fn
= dissect_CPMFetchValue
;
2040 fn
= dissect_CPMGetQueryStatusEx
;
2043 fn
= dissect_CPMRestartPosition
;
2046 fn
= dissect_CPMSetCatState
;
2049 fn
= dissect_CPMGetRowsetNotify
;
2052 fn
= dissect_CPMFindIndices
;
2055 fn
= dissect_CPMSetScopePrioritization
;
2058 fn
= dissect_CPMGetScopeStatistics
;
2064 hdr
.status
= tvb_get_letohl(tvb
, 4);
2065 hdr
.checksum
= tvb_get_letohl(tvb
, 8);
2067 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MS-WSP");
2068 /* col_clear(pinfo->cinfo, COL_INFO); */
2070 col_set_str(pinfo
->cinfo
, COL_INFO
, "WSP ");
2071 col_append_str(pinfo
->cinfo
, COL_INFO
, in
? "Request: " : "Response: ");
2074 proto_tree
*hdr_tree
;
2075 proto_item
*ti
, *hti
;
2077 ti
= proto_tree_add_item(tree
, proto_mswsp
, tvb
, 0, -1, ENC_NA
);
2078 mswsp_tree
= proto_item_add_subtree(ti
, ett_mswsp
);
2080 hti
= proto_tree_add_item(mswsp_tree
, hf_mswsp_hdr
, tvb
, 0, 16, ENC_NA
);
2081 hdr_tree
= proto_item_add_subtree(hti
, ett_mswsp_hdr
);
2083 proto_tree_add_item(hdr_tree
, hf_mswsp_hdr_msg
, tvb
,
2084 0, 4, ENC_LITTLE_ENDIAN
);
2085 proto_tree_add_item(hdr_tree
, hf_mswsp_hdr_status
,
2086 tvb
, 4, 4, ENC_LITTLE_ENDIAN
);
2087 proto_tree_add_item(hdr_tree
, hf_mswsp_hdr_checksum
,
2088 tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
2089 proto_tree_add_item(hdr_tree
, hf_mswsp_hdr_reserved
, tvb
,
2090 12, 4, ENC_LITTLE_ENDIAN
);
2093 fn(tvb
, pinfo
, mswsp_tree
, in
);
2095 /* Return the amount of data this dissector was able to dissect */
2096 return tvb_length(tvb
);
2100 /* Register the protocol with Wireshark */
2102 /* this format is require because a script is used to build the C function
2103 that calls all the protocol registration.
2107 proto_register_mswsp(void)
2109 module_t
*mswsp_module
;
2111 /* Setup list of header fields See Section 1.6.1 for details*/
2112 static const value_string msg_ids
[] = {
2113 {0x000000C8, "CPMConnect"}, /* In/Out */
2114 {0x000000C9, "CPMDisconnect"},
2115 {0x000000CA, "CPMCreateQuery"}, /* In/Out */
2116 {0x000000CB, "CPMFreeCursor"}, /* In/Out */
2117 {0x000000CC, "CPMGetRows"}, /* In/Out */
2118 {0x000000CD, "CPMRatioFinished"}, /* In/Out */
2119 {0x000000CE, "CPMCompareBmk"}, /* In/Out */
2120 {0x000000CF, "CPMGetApproximatePosition"}, /* In/Out */
2121 {0x000000D0, "CPMSetBindingsIn"},
2122 {0x000000D1, "CPMGetNotify"},
2123 {0x000000D2, "CPMSendNotifyOut"},
2124 {0x000000D7, "CPMGetQueryStatusIn"}, /* In/Out */
2125 {0x000000D9, "CPMCiStateInOut"},
2126 {0x000000E4, "CPMFetchValue"}, /* In/Out */
2127 {0x000000E7, "CPMGetQueryStatusEx"}, /* In/Out */
2128 {0x000000E8, "CPMRestartPositionIn"},
2129 {0x000000EC, "CPMSetCatStateIn"}, /* (not supported) */
2130 {0x000000F1, "CPMGetRowsetNotify"}, /* In/Out */
2131 {0x000000F2, "CPMFindIndices"}, /* In/Out */
2132 {0x000000F3, "CPMSetScopePrioritization"}, /* In/Out */
2133 {0x000000F4, "CPMGetScopeStatistics"}, /* In/Out */
2135 static hf_register_info hf
[] = {
2137 { "Header", "mswsp.hdr",
2138 FT_NONE
, BASE_NONE
, NULL
, 0,
2139 "Message header", HFILL
}
2141 { &hf_mswsp_hdr_msg
,
2142 { "Msg id", "mswsp.hdr.id",
2143 FT_UINT32
, BASE_HEX
, VALS(msg_ids
), 0,
2144 "Message id", HFILL
}
2146 { &hf_mswsp_hdr_status
,
2147 { "Status", "mswsp.hdr.status",
2148 FT_UINT32
, BASE_HEX
, NULL
, 0,
2151 { &hf_mswsp_hdr_checksum
,
2152 { "checksum", "mswsp.hdr.checksum",
2153 FT_UINT32
, BASE_HEX
, NULL
, 0,
2156 { &hf_mswsp_hdr_reserved
,
2157 { "Reserved", "mswsp.hdr.reserved",
2158 FT_UINT32
, BASE_HEX
, NULL
, 0,
2162 { "msg", "mswsp.msg",
2163 FT_NONE
, BASE_NONE
, NULL
, 0,
2166 { &hf_mswsp_msg_Connect_Version
,
2167 { "Version", "mswsp.Connect.version",
2168 FT_UINT32
, BASE_HEX
, NULL
, 0,
2171 { &hf_mswsp_msg_ConnectIn_ClientIsRemote
,
2172 { "Remote", "mswsp.ConnectIn.isRemote",
2173 FT_BOOLEAN
, BASE_HEX
, NULL
, 0,
2174 "Client is remote",HFILL
}
2176 { &hf_mswsp_msg_ConnectIn_Blob1
,
2177 { "Size", "mswsp.ConnectIn.propset.size",
2178 FT_UINT32
, BASE_DEC
, NULL
, 0,
2179 "Size of PropSet fields",HFILL
}
2181 { &hf_mswsp_msg_ConnectIn_Blob2
,
2182 { "Size", "mswsp.ConnectIn.extpropset.size",
2183 FT_UINT32
, BASE_DEC
, NULL
, 0,
2184 "Size of ExtPropSet fields",HFILL
}
2186 { &hf_mswsp_msg_ConnectIn_MachineName
,
2187 { "Remote machine", "mswsp.ConnectIn.machine",
2188 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
2189 "Name of remote machine",HFILL
}
2191 { &hf_mswsp_msg_ConnectIn_UserName
,
2192 { "User", "mswsp.ConnectIn.user",
2193 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
2194 "Name of remote user",HFILL
}
2196 { &hf_mswsp_msg_ConnectIn_PropSets_num
,
2197 { "Num", "mswsp.ConnectIn.propset.num",
2198 FT_UINT32
, BASE_DEC
, NULL
, 0,
2199 "Number of Property Sets", HFILL
}
2201 { &hf_mswsp_msg_ConnectIn_ExtPropSets_num
,
2202 { "Num", "mswsp.ConnectIn.extpropset.num",
2203 FT_UINT32
, BASE_DEC
, NULL
, 0,
2204 "Number of extended Property Sets", HFILL
}
2209 /* Setup protocol subtree array */
2210 static gint
*ett
[] = {
2215 &ett_mswsp_property_restriction
,
2216 &ett_CRestrictionArray
,
2217 &ett_CBaseStorageVariant
,
2218 &ett_CBaseStorageVariant_Vector
,
2219 &ett_CBaseStorageVariant_Array
,
2224 &ett_CDbPropSet_Array
,
2226 &ett_CNodeRestriction
,
2227 &ett_CPropertyRestriction
,
2228 &ett_CCoercionRestriction
,
2229 &ett_CContentRestriction
,
2231 &ett_CRangeCategSpec
,
2235 &ett_CCategorizationSpec
,
2236 &ett_CAggregSortKey
,
2237 &ett_CSortAggregSet
,
2238 &ett_CInGroupSortAggregSet
,
2239 &ett_CInGroupSortAggregSets
,
2240 &ett_CRowsetProperties
,
2245 /* Register the protocol name and description */
2246 proto_mswsp
= proto_register_protocol("Windows Search Protocol",
2249 /* Required function calls to register the header fields and subtrees used */
2250 proto_register_field_array(proto_mswsp
, hf
, array_length(hf
));
2251 proto_register_subtree_array(ett
, array_length(ett
));
2253 for (i
=0; i
<(int)array_length(GuidPropertySet
); i
++) {
2254 guids_add_guid(&GuidPropertySet
[i
].guid
, GuidPropertySet
[i
].def
);
2258 /* Register preferences module (See Section 2.6 for more on preferences) */
2259 /* (Registration of a prefs callback is not required if there are no */
2260 /* prefs-dependent registration functions (eg: a port pref). */
2261 /* See proto_reg_handoff below. */
2262 /* If a prefs callback is not needed, use NULL instead of */
2263 /* proto_reg_handoff_mswsp in the following). */
2264 mswsp_module
= prefs_register_protocol(proto_mswsp
,
2265 proto_reg_handoff_mswsp
);
2267 /* Register preferences module under preferences subtree.
2268 Use this function instead of prefs_register_protocol if you want to group
2269 preferences of several protocols under one preferences subtree.
2270 Argument subtree identifies grouping tree node name, several subnodes can be
2271 specified using slash '/' (e.g. "OSI/X.500" - protocol preferences will be
2272 accessible under Protocols->OSI->X.500-><PROTOSHORTNAME> preferences node.
2274 /* mswsp_module = prefs_register_protocol_subtree(subtree, */
2275 /* proto_mswsp, proto_reg_handoff_mswsp); */
2277 /* Register a sample preference */
2278 prefs_register_bool_preference(mswsp_module
, "show_hex",
2279 "Display numbers in Hex",
2280 "Enable to display numerical values in hexadecimal.",
2283 /* Register a sample port preference */
2284 prefs_register_uint_preference(mswsp_module
, "tcp.port", "mswsp TCP Port",
2285 " mswsp TCP port if other than the default",
2289 static int dissect_mswsp_smb(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
2290 smb_info_t
*si
= pinfo
->private_data
;
2291 gboolean in
= si
->request
;
2293 fprintf(stderr
, "dissect_mswsp_smb %d <> %d : op %02x %s %s type: %d\n",
2294 pinfo
->fd
->num
, si
->tid
,
2296 pinfo
->dcerpc_procedure_name
? pinfo
->dcerpc_procedure_name
: "<NULL>",
2297 in
? "Request" : "Response", si
->tid
);
2300 if (strcmp(pinfo
->dcerpc_procedure_name
, "File: MsFteWds") != 0) {
2304 return dissect_mswsp(tvb
, pinfo
, tree
, in
);
2308 static int dissect_mswsp_smb2(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
2309 smb2_info_t
*si
= pinfo
->private_data
;
2310 gboolean in
= !(si
->flags
& SMB2_FLAGS_RESPONSE
);
2312 //si->tree->share_type == SMB2_SHARE_TYPE_PIPE
2313 //si->tree->connect_frame
2315 fprintf(stderr
, "dissect_mswsp %d <> %d : op %02x %s %s type: %d extra_file: %s\n",
2316 pinfo
->fd
->num
, si
->tree
? (int)si
->tree
->connect_frame
: -1,
2318 pinfo
->dcerpc_procedure_name
? pinfo
->dcerpc_procedure_name
: "<NULL>",
2319 in
? "Request" : "Response", si
->tree
? si
->tree
->share_type
: -1,
2320 si
->saved
? (si
->saved
->extra_info_type
== SMB2_EI_FILENAME
? (char*)si
->saved
->extra_info
: "<OTHER>") : "<NONE>"
2324 if (strcmp(pinfo
->dcerpc_procedure_name
, "File: MsFteWds") != 0) {
2328 return dissect_mswsp(tvb
, pinfo
, tree
, in
);
2333 /* If this dissector uses sub-dissector registration add a registration routine.
2334 This exact format is required because a script is used to find these
2335 routines and create the code that calls these routines.
2337 If this function is registered as a prefs callback (see prefs_register_protocol
2338 above) this function is also called by preferences whenever "Apply" is pressed;
2339 In that case, it should accommodate being called more than once.
2341 Simple form of proto_reg_handoff_mswsp which can be used if there are
2342 no prefs-dependent registration function calls.
2346 proto_reg_handoff_mswsp(void)
2348 heur_dissector_add("smb_transact", dissect_mswsp_smb
, proto_mswsp
);
2349 heur_dissector_add("smb2_heur_subdissectors", dissect_mswsp_smb2
, proto_mswsp
);
2354 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2359 * indent-tabs-mode: nil
2362 * vi: set shiftwidth=4 tabstop=8 expandtab:
2363 * :indentSize=4:tabSize=8:noTabs=true: