MSWSP: add even more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-mswsp.c
blobd584d7daf1fb5b71b895086cdc4dfa2e0aa30712
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 <sys/types.h>
37 #include <unistd.h>
40 #include <glib.h>
42 #include <epan/packet.h>
43 #include <epan/prefs.h>
45 #include "packet-smb.h"
46 #include "packet-smb2.h"
48 /* IF PROTO exposes code to other dissectors, then it must be exported
49 in a header file. If not, a header file is not needed at all. */
51 * #include "packet-mswsp.h"
53 #include "mswsp.h"
55 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
57 /* Forward declaration we need below (if using proto_reg_handoff...
58 as a prefs callback) */
59 void proto_reg_handoff_mswsp(void);
61 /* Initialize the protocol and registered fields */
62 static int proto_mswsp = -1;
63 static int hf_mswsp_msg = -1;
64 static int hf_mswsp_hdr = -1;
65 static int hf_mswsp_hdr_msg = -1;
66 static int hf_mswsp_hdr_status = -1;
67 static int hf_mswsp_hdr_checksum = -1;
68 static int hf_mswsp_hdr_reserved = -1;
69 static int hf_mswsp_msg_Connect_Version = -1;
70 static int hf_mswsp_msg_ConnectIn_ClientIsRemote = -1;
71 static int hf_mswsp_msg_ConnectIn_Blob1 = -1;
72 static int hf_mswsp_msg_ConnectIn_Blob2 = -1;
73 static int hf_mswsp_msg_ConnectIn_MachineName = -1;
74 static int hf_mswsp_msg_ConnectIn_UserName = -1;
75 static int hf_mswsp_msg_ConnectIn_PropSets_num = -1;
76 static int hf_mswsp_msg_ConnectIn_ExtPropSets_num = -1;
79 /* Global sample preference ("controls" display of numbers) */
80 static gboolean gPREF_HEX = FALSE;
81 /* Global sample port pref */
82 static guint gPORT_PREF = 1234;
84 /* Initialize the subtree pointers */
85 static gint ett_mswsp = -1;
86 static gint ett_mswsp_hdr = -1;
87 static gint ett_mswsp_msg = -1;
88 static gint ett_mswsp_pad = -1;
90 static gint ett_mswsp_property_restriction = -1;
91 static gint ett_CRestrictionArray = -1;
92 static gint ett_CBaseStorageVariant = -1;
93 static gint ett_CBaseStorageVariant_Vector = -1;
94 static gint ett_CBaseStorageVariant_Array = -1;
95 static gint ett_CDbColId = -1;
96 static gint ett_GUID = -1;
97 static gint ett_CDbProp = -1;
98 static gint ett_CDbPropSet = -1;
99 static gint ett_CDbPropSet_Array = -1;
100 static gint ett_CRestriction = -1;
101 static gint ett_CNodeRestriction = -1;
102 static gint ett_CPropertyRestriction = -1;
103 static gint ett_CCoercionRestriction = -1;
104 static gint ett_CContentRestriction = -1;
105 static gint ett_RANGEBOUNDARY = -1;
106 static gint ett_CRangeCategSpec = -1;
107 static gint ett_CCategSpec = -1;
108 static gint ett_CAggregSpec = -1;
109 static gint ett_CAggregSet = -1;
110 static gint ett_CCategorizationSpec = -1;
111 static gint ett_CAggregSortKey = -1;
112 static gint ett_CSortAggregSet = -1;
113 static gint ett_CInGroupSortAggregSet = -1;
114 static gint ett_CInGroupSortAggregSets = -1;
115 static gint ett_CRowsetProperties = -1;
116 static gint ett_CFullPropSpec = -1;
117 static gint ett_CPidMapper = -1;
118 static gint ett_CSort = -1;
119 static gint ett_CSortSet = -1;
120 static gint ett_CNatLanguageRestriction = -1;
122 /******************************************************************************/
123 struct GuidPropertySet {
124 e_guid_t guid;
125 const char *def;
126 const char *desc;
127 const value_string *id_map;
130 /* 2.2.1.31.1 */
131 static const value_string DBPROPSET_FSCIFRMWRK_EXT_IDS[] = {
132 {0x02, "DBPROP_CI_CATALOG_NAME"},
133 {0x03, "DBPROP_CI_INCLUDE_SCOPES"},
134 {0x04, "DBPROP_CI_SCOPE_FLAGS"},
135 {0x07, "DBPROP_CI_QUERY_TYPE"},
136 {0, NULL}
139 static const value_string DBPROPSET_QUERYEXT_IDS[] = {
140 {0x02, "DBPROP_USECONTENTINDEX"},
141 {0x03, "DBPROP_DEFERNONINDEXEDTRIMMING"},
142 {0x04, "DBPROP_USEEXTENDEDDBTYPES"},
143 {0x05, "DBPROP_IGNORENOISEONLYCLAUSES"},
144 {0x06, "DBPROP_GENERICOPTIONS_STRING"},
145 {0x07, "DBPROP_FIRSTROWS"},
146 {0x08, "DBPROP_DEFERCATALOGVERIFICATION"},
147 {0x0a, "DBPROP_GENERATEPARSETREE"},
148 {0x0c, "DBPROP_FREETEXTANYTERM"},
149 {0x0d, "DBPROP_FREETEXTUSESTEMMING"},
150 {0x0e, "DBPROP_IGNORESBRI"},
151 {0x10, "DBPROP_ENABLEROWSETEVENTS"},
152 {0, NULL}
155 static const value_string DBPROPSET_CIFRMWRKCORE_EXT_IDS[] = {
156 {0x02, "DBPROP_MACHINE"},
157 {0x03, "DBPROP_CLIENT_CLSID"},
158 {0, NULL}
161 static const value_string DBPROPSET_MSIDXS_ROWSETEXT_IDS[] = {
162 {0x02, "MSIDXSPROP_ROWSETQUERYSTATUS"},
163 {0x03, "MSIDXSPROP_COMMAND_LOCALE_STRING"},
164 {0x04, "MSIDXSPROP_QUERY_RESTRICTION"},
165 {0x05, "MSIDXSPROP_PARSE_TREE"},
166 {0x06, "MSIDXSPROP_MAX_RANK"},
167 {0x07, "MSIDXSPROP_RESULTS_FOUND"},
168 {0, NULL}
171 /* 2.2.5.1 */
172 static const value_string QueryGuid_IDS[] = {
173 {0x02, "RankVector"},
174 {0x03, "System.Search.Rank"},
175 {0x04, "System.Search.HitCount"},
176 {0x05, "System.Search.EntryID"},
177 {0x06, "All"},
178 {0x09, "System.ItemURL"},
179 {0, NULL}
182 /* 2.2.5.2 */
183 static const value_string StorageGuid_IDS[] = {
184 {0x02, "System.ItemFolderNameDisplay"},
185 {0x03, "ClassId"},
186 {0x04, "System.ItemTypeText"},
187 {0x08, "FileIndex"},
188 {0x09, "USN"},
189 {0x0a, "System.ItemNameDisplay"},
190 {0x0b, "Path"},
191 {0x0c, "System.Size"},
192 {0x0d, "System.FileAttributes"},
193 {0x0e, "System.DateModified"},
194 {0x0f, "System.DateCreated"},
195 {0x10, "System.DateAccessed"},
196 {0x12, "AllocSize"},
197 {0x13, "System.Search.Contents"},
198 {0x14, "ShortFilename"},
199 {0x15, "FileFRN"},
200 {0x16, "Scope"},
201 {0, NULL}
204 static const value_string DocPropSetGuid_IDS[] = {
205 {0x02, "System.Title"},
206 {0x03, "System.Subject"},
207 {0x04, "System.Author"},
208 {0x05, "System.Keywords"},
209 {0x06, "System.Comment"},
210 {0x07, "DocTemplate"},
211 {0x08, "System.Document.LastAuthor"},
212 {0x09, "System.Document.RevisionNumber"},
213 {0x0a, "System.Document.EditTime???"},
214 {0x0b, "System.Document.DatePrinted"},
215 {0x0c, "System.Document.DateCreated"},
216 {0x0d, "System.Document.DateSaved"},
217 {0x0e, "System.Document.PageCount"},
218 {0x0f, "System.Document.WordCount"},
219 {0x10, "System.Document.CharacterCount"},
220 {0x11, "DocThumbnail"},
221 {0x12, "System.ApplicationName"},
222 {0, NULL}
225 static const value_string ShellDetails_IDS[] = {
226 { 5, "System.ComputerName"},
227 { 8, "System.ItemPathDisplayNarrow"},
228 { 9, "PercivedType"},
229 {11, "System.ItemType"},
230 {12, "FileCount"},
231 {14, "TotalFileSize"},
232 {24, "System.ParsingName"},
233 {25, "System.SFGAOFlags"},
234 {0, NULL}
237 static const value_string PropSet1_IDS[] = {
238 {100, "System.ThumbnailCacheId"},
239 {0, NULL}
242 static const value_string PropSet2_IDS[] = {
243 {3, "System.Kind"},
244 {0, NULL}
247 static const value_string MusicGuid_IDS[] = {
248 {0, NULL}
251 static const value_string PropSet3_IDS[] = {
252 { 2, "System.Message.BccAddress"},
253 { 3, "System.Message.BccName"},
254 { 4, "System.Message.CcAddress"},
255 { 5, "System.Message.CcName"},
256 { 6, "System.ItemFolderPathDisplay"},
257 { 7, "System.ItemPathDisplay"},
258 { 9, "System.Communication.AccountName"},
259 {10, "System.IsRead"},
260 {11, "System.Importance"},
261 {12, "System.FlagStatus"},
262 {13, "System.Message.FromAddress"},
263 {14, "System.Message.FromName"},
264 {15, "System.Message.Store"},
265 {16, "System.Message.ToAddress"},
266 {17, "System.Message.ToName"},
267 {18, "System.Contact.WebPage"},
268 {19, "System.Message.DateSent"},
269 {20, "System.Message.DateReceived"},
270 {21, "System.Message.AttachmentNames"},
271 {0, NULL}
274 static const value_string PropSet4_IDS[] = {
275 {100, "System.ItemFolderPathDisplayNarrow"},
276 {0, NULL}
279 static const value_string PropSet5_IDS[] = {
280 {100, "System.Contact.FullName"},
281 {0, NULL}
284 static const value_string PropSet6_IDS[] = {
285 {100, "System.ItemAuthors"},
286 {0, NULL}
289 static const value_string PropSet7_IDS[] = {
290 {2, "System.Shell.OmitFromView"},
291 {0, NULL}
294 static const value_string PropSet8_IDS[] = {
295 {2, "System.Shell.SFGAOFlagsStrings"},
296 {3, "System.Link.TargetSFGAOFlagsStrings"},
297 {0, NULL}
300 static struct GuidPropertySet GuidPropertySet[] = {
301 {{0xa9bd1526, 0x6a80, 0x11d0, {0x8c, 0x9d, 0x00, 0x20, 0xaf, 0x1d, 0x74, 0x0e}},
302 "DBPROPSET_FSCIFRMWRK_EXT", "File system content index framework",
303 DBPROPSET_FSCIFRMWRK_EXT_IDS},
304 {{0xa7ac77ed, 0xf8d7, 0x11ce, {0xa7, 0x98, 0x00, 0x20, 0xf8, 0x00, 0x80, 0x25}},
305 "DBPROPSET_QUERYEXT", "Query extension",
306 DBPROPSET_QUERYEXT_IDS},
307 {{0xafafaca5, 0xb5d1, 0x11d0, {0x8c, 0x62, 0x00, 0xc0, 0x4f, 0xc2, 0xdb, 0x8d}},
308 "DBPROPSET_CIFRMWRKCORE_EXT", "Content index framework core",
309 DBPROPSET_CIFRMWRKCORE_EXT_IDS},
310 {{0xAA6EE6B0, 0xE828, 0x11D0, {0xB2, 0x3E, 0x00, 0xAA, 0x00, 0x47, 0xFC, 0x01}},
311 "DBPROPSET_MSIDXS_ROWSETEXT", "???",
312 DBPROPSET_MSIDXS_ROWSETEXT_IDS},
313 {{0xB725F130, 0x47ef, 0x101a, {0xA5, 0xF1, 0x02, 0x60, 0x8C, 0x9E, 0xEB, 0xAC}},
314 "Storage", "Storage Property Set",
315 StorageGuid_IDS},
316 {{0xF29F85E0, 0x4FF9, 0x1068, {0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9}},
317 "Document", "Document Property Set",
318 DocPropSetGuid_IDS},
319 {{0x49691C90, 0x7E17, 0x101A, {0xA9, 0x1C, 0x08, 0x00, 0x2B, 0x2E, 0xCD, 0xA9}},
320 "Query", "Query Property Set",
321 QueryGuid_IDS},
322 {{0x28636AA6, 0x953D, 0x11D2, {0xB5, 0xD6, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xD0}},
323 "ShellDetails", "Shell Details Property Set",
324 ShellDetails_IDS},
325 {{0x446D16B1, 0x8DAD, 0x4870, {0xA7, 0x48, 0x40, 0x2E, 0xA4, 0x3D, 0x78, 0x8C}},
326 "???", "Unspecified Property Set",
327 PropSet1_IDS},
328 {{0x1E3EE840, 0xBC2B, 0x476C, {0x82, 0x37, 0x2A, 0xCD, 0x1A, 0x83, 0x9B, 0x22}},
329 "???", "Unspecified Property Set",
330 PropSet2_IDS},
331 {{0x56A3372E, 0xCE9C, 0x11d2, {0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6}},
332 "Music", "Music Property Set",
333 MusicGuid_IDS},
334 {{0xE3E0584C, 0xB788, 0x4A5A, {0xBB, 0x20, 0x7F, 0x5A, 0x44, 0xC9, 0xAC, 0xDD}},
335 "???", "Unspecified Property Set",
336 PropSet3_IDS},
337 {{0xDABD30ED, 0x0043, 0x4789, {0xA7, 0xF8, 0xD0, 0x13, 0xA4, 0x73, 0x66, 0x22}},
338 "???", "Unspecified Property Set",
339 PropSet4_IDS},
340 {{0x635E9051, 0x50A5, 0x4BA2, {0xB9, 0xDB, 0x4E, 0xD0, 0x56, 0xC7, 0x72, 0x96}},
341 "???", "Unspecified Property Set",
342 PropSet5_IDS},
343 {{0xD0A04F0A, 0x462A, 0x48A4, {0xBB, 0x2F, 0x37, 0x06, 0xE8, 0x8D, 0xBD, 0x7D}},
344 "???", "Unspecified Property Set",
345 PropSet6_IDS},
346 {{0xDE35258C, 0xC695, 0x4CBC, {0xB9, 0x82, 0x38, 0xB0, 0xAD, 0x24, 0xCE, 0xD0}},
347 "???", "Unspecified Property Set",
348 PropSet7_IDS},
349 {{0xD6942081, 0xD53B, 0x443D, {0xAD, 0x47, 0x5E, 0x05, 0x9D, 0x9C, 0xD2, 0x7A}},
350 "???", "Unspecified Property Set",
351 PropSet8_IDS},
354 static struct GuidPropertySet *GuidPropertySet_find_guid(const e_guid_t *guid)
356 unsigned i;
357 for (i=0; i<array_length(GuidPropertySet); i++) {
358 if (guid_cmp(&GuidPropertySet[i].guid, guid) == 0) {
359 return &GuidPropertySet[i];
362 return NULL;
365 /******************************************************************************/
367 static int parse_padding(tvbuff_t *tvb, int offset, int alignment, proto_tree *pad_tree, const char *fmt, ...)
369 if (offset % alignment) {
370 const int padding = alignment - (offset % alignment);
371 va_list ap;
372 proto_item *ti;
373 va_start(ap, fmt);
374 ti = proto_tree_add_text_valist(pad_tree, tvb, offset, padding, fmt, ap);
375 va_end(ap);
377 proto_item_append_text(ti, " (%d)", padding);
378 offset += padding;
380 DISSECTOR_ASSERT((offset % alignment) == 0);
381 return offset;
384 static int parse_guid(tvbuff_t *tvb, int offset, proto_tree *tree, e_guid_t *guid, const char *text)
386 const char *guid_str, *name, *bytes;
387 proto_tree *tr;
388 proto_item *ti;
390 tvb_get_letohguid(tvb, offset, guid);
391 guid_str = guid_to_str(guid);
392 name = guids_get_guid_name(guid);
394 ti = proto_tree_add_text(tree, tvb, offset, 16, "%s: %s {%s}", text, name ? name : "", guid_str);
395 tr = proto_item_add_subtree(ti, ett_GUID);
397 proto_tree_add_text(tr, tvb, offset, 4, "time-low: 0x%08x", guid->data1);
398 offset += 4;
399 proto_tree_add_text(tr, tvb, offset, 2, "time-mid: 0x%04x", guid->data2);
400 offset += 2;
401 proto_tree_add_text(tr, tvb, offset, 2, "time-high-and-version: 0x%04x", guid->data3);
402 offset += 2;
403 proto_tree_add_text(tr, tvb, offset, 1, "clock_seq_hi_and_reserved: 0x%02x", guid->data4[0]);
404 offset += 1;
405 proto_tree_add_text(tr, tvb, offset, 1, "clock_seq_low: 0x%02x", guid->data4[1]);
406 offset += 1;
407 bytes = bytestring_to_str(&guid->data4[2], 6, ':');
408 proto_tree_add_text(tr, tvb, offset, 6, "node: %s", bytes);
409 offset += 6;
411 return offset;
414 /*****************************************************************************************/
415 /* 2.2.1.1 CBaseStorageVariant */
416 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
417 struct CBaseStorageVariant *value, const char *text);
419 /* 2.2.1.2 CFullPropSpec */
420 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pad_tree,
421 struct CFullPropSpec *v, const char *fmt, ...);
423 /* 2.2.1.3 CContentRestriction */
424 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
425 proto_tree *pad_tree, struct CContentRestriction *v,
426 const char *fmt, ...);
428 /* 2.2.1.5 CNatLanguageRestriction */
429 static int parse_CNatLanguageRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
430 proto_tree *pad_tree, struct CNatLanguageRestriction *v,
431 const char *fmt, ...);
433 /* 2.2.1.6 CNodeRestriction */
434 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pad_tree,
435 struct CNodeRestriction *v, const char* fmt, ...);
437 /* 2.2.1.7 CPropertyRestriction */
438 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
439 proto_tree *pad_tree, struct CPropertyRestriction *v,
440 const char *fmt, ...);
442 /* 2.2.1.8 CReuseWhere */
443 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
444 proto_tree *pad_tree _U_, struct CReuseWhere *v,
445 const char *fmt, ...);
447 /* 2.2.1.10 CSort */
448 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
449 proto_tree *pad_tree _U_,
450 const char *fmt, ...);
452 /* 2.2.1.12 CCoercionRestriction */
453 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
454 proto_tree *pad_tree, struct CCoercionRestriction *v,
455 const char *fmt, ...);
456 /* 2.2.1.16 CRestrictionArray */
457 static int parse_CRestrictionArray(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
458 const char *fmt, ...);
460 /* 2.2.1.17 CRestriction */
461 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
462 struct CRestriction *v, const char *fmt, ...);
464 /* 2.2.1.18 CColumnSet */
465 static int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...);
467 /* 2.2.1.20 CCategorizationSpec */
468 static int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
469 proto_tree *parent_tree, proto_tree *pad_tree,
470 const char *fmt, ...);
472 /* 2.2.1.21 CCategSpec */
473 static int parse_CCategSpec(tvbuff_t *tvb, int offset,
474 proto_tree *parent_tree, proto_tree *pad_tree,
475 const char *fmt, ...);
477 /* 2.2.1.22 CRangeCategSpec */
478 static int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
479 proto_tree *parent_tree, proto_tree *pad_tree,
480 const char *fmt, ...);
482 /* 2.2.1.23 RANGEBOUNDARY */
483 static int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
484 proto_tree *pad_tree, const char *fmt, ...);
486 /* 2.2.1.24 CAggregSet */
487 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
488 proto_tree *parent_tree, proto_tree *pad_tree,
489 const char *fmt, ...);
491 /* 2.2.1.25 CAggregSpec */
492 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
493 proto_tree *parent_tree, proto_tree *pad_tree,
494 const char *fmt, ...);
496 /* 2.2.1.26 CSortAggregSet */
497 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
498 proto_tree *parent_tree, proto_tree *pad_tree,
499 const char *fmt, ...);
501 /* 2.2.1.27 CAggregSortKey */
502 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
503 proto_tree *parent_tree, proto_tree *pad_tree,
504 const char *fmt, ...);
506 /* 2.2.1.28 CInGroupSortAggregSets */
507 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
508 proto_tree *parent_tree, proto_tree *pad_tree,
509 const char *fmt, ...);
511 /* 2.2.1.29 CInGroupSortAggregSet */
512 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
513 proto_tree *parent_tree, proto_tree *pad_tree,
514 const char *fmt, ...);
515 /* 2.2.1.30 CDbColId */
516 static int parse_CDbColId(tvbuff_t *tvb, int offset,
517 proto_tree *parent_tree, proto_tree *pad_tree, const char *text);
519 /* 2.2.1.31 CDbProp */
520 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
521 proto_tree *pad_tree, struct GuidPropertySet *propset,
522 const char *fmt, ...);
524 /* 2.2.1.32 CDbPropSet */
525 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
526 proto_tree *pad_tree, const char *fmt, ...);
527 /* 2.2.1.33 CPidMapper */
528 static int parse_CPidMapper(tvbuff_t *tvb, int offset,
529 proto_tree *parent_tree, proto_tree *pad_tree,
530 const char *fmt, ...);
532 /* 2.2.1.41 CRowsetProperties */
533 static int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
534 proto_tree *parent_tree, proto_tree *pad_tree,
535 const char *fmt, ...);
537 /* 2.2.1.43 CSortSet */
538 static int parse_CSortSet(tvbuff_t *tvb, int offset,
539 proto_tree *parent_tree, proto_tree *pad_tree,
540 const char *fmt, ...);
543 2.2.1.4 CInternalPropertyRestriction
544 2.2.1.9 CScopeRestriction
545 2.2.1.11 CVectorRestriction
546 2.2.1.13 CRelDocRestriction
547 2.2.1.14 CProbRestriction
548 2.2.1.15 CFeedbackRestriction
549 2.2.1.19 CCategorizationSet
550 2.2.1.34 CColumnGroupArray
551 2.2.1.35 CColumnGroup
552 2.2.1.36 SProperty
553 2.2.1.37 CRowSeekAt
554 2.2.1.38 CRowSeekAtRatio
555 2.2.1.39 CRowSeekByBookmark
556 2.2.1.40 CRowSeekNext
557 2.2.1.42 CRowVariant
558 2.2.1.44 CTableColumn
559 2.2.1.45 SERIALIZEDPROPERTYVALUE
560 2.2.1.46 CCompletionCategSp
563 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
564 proto_tree *pad_tree _U_,
565 const char *fmt, ...)
567 guint32 col, ord, ind, lcid;
569 proto_item *item;
570 proto_tree *tree;
572 va_list ap;
574 va_start(ap, fmt);
575 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
576 va_end(ap);
577 tree = proto_item_add_subtree(item, ett_CSort);
579 col = tvb_get_letohl(tvb, offset);
580 proto_tree_add_text(tree, tvb, offset, 4, "column: %u", col);
581 offset += 4;
583 ord = tvb_get_letohl(tvb, offset);
584 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", ord);
585 offset += 4;
587 ind = tvb_get_letohl(tvb, offset);
588 proto_tree_add_text(tree, tvb, offset, 4, "individual: %u", ind);
589 offset += 4;
591 lcid = tvb_get_letohl(tvb, offset);
592 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", lcid);
593 offset += 4;
595 proto_item_set_end(item, tvb, offset);
596 return offset;
599 static int parse_CSortSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
600 proto_tree *pad_tree,
601 const char *fmt, ...)
603 guint32 count, i;
605 proto_item *item;
606 proto_tree *tree;
608 va_list ap;
610 va_start(ap, fmt);
611 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
612 va_end(ap);
613 tree = proto_item_add_subtree(item, ett_CSortSet);
615 count = tvb_get_letohl(tvb, offset);
616 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
617 offset += 4;
619 for (i=0; i<count; i++) {
620 offset = parse_padding(tvb, offset, 4, tree, "padding_sortArray[%u]", i);
621 offset = parse_CSort(tvb, offset, tree, pad_tree, "sortArray[%u]", i);
624 proto_item_set_end(item, tvb, offset);
625 return offset;
629 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset,
630 proto_tree *parent_tree, proto_tree *pad_tree,
631 struct CFullPropSpec *v, const char *fmt, ...)
633 static const value_string KIND[] = {
634 {0, "PRSPEC_LPWSTR"},
635 {1, "PRSPEC_PROPID"},
636 {0, NULL}
639 struct GuidPropertySet *pset;
640 const char *id_str, *guid_str;
642 proto_item *item;
643 proto_tree *tree;
644 va_list ap;
646 va_start(ap, fmt);
647 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
648 va_end(ap);
649 tree = proto_item_add_subtree(item, ett_CFullPropSpec);
651 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingPropSet");
653 offset = parse_guid(tvb, offset, tree, &v->guid, "GUID");
654 pset = GuidPropertySet_find_guid(&v->guid);
656 v->kind = tvb_get_letohl(tvb, offset);
657 proto_tree_add_text(tree, tvb, offset, 4, "ulKind: %s ", val_to_str(v->kind, KIND, "(Unknown: 0x%x)"));
658 offset += 4;
660 v->u.propid = tvb_get_letohl(tvb, offset);
661 proto_tree_add_text(tree, tvb, offset, 4, "propid: %u ", v->u.propid);
662 offset += 4;
664 if (v->kind == PRSPEC_LPWSTR) {
665 int len = 2*v->u.propid;
666 v->u.name = tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
667 proto_tree_add_text(tree, tvb, offset, len, "name: \"%s\"", v->u.name);
668 offset += len;
671 id_str = pset ? match_strval(v->u.propid, pset->id_map) : NULL;
673 if (id_str) {
674 proto_item_append_text(item, ": %s", id_str);
675 } else {
676 guid_str = guids_get_guid_name(&v->guid);
677 if (guid_str) {
678 proto_item_append_text(item, ": \"%s\"", guid_str);
679 } else {
680 guid_str = guid_to_str(&v->guid);
681 proto_item_append_text(item, ": {%s}", guid_str);
684 if (v->kind == PRSPEC_LPWSTR) {
685 proto_item_append_text(item, " \"%s\"", v->u.name);
686 } else if (v->kind == PRSPEC_PROPID) {
687 proto_item_append_text(item, " 0x%08x", v->u.propid);
688 } else {
689 proto_item_append_text(item, " <INVALID>");
693 proto_item_set_end(item, tvb, offset);
694 return offset;
699 static const value_string PR_VALS[] = {
700 {PRLT, "PRLT"},
701 {PRLE, "PRLE"},
702 {PRGT, "PRGT"},
703 {PRGE, "PRGE"},
704 {PREQ, "PREQ"},
705 {PRNE, "PRNE"},
706 {PRRE, "PRRE"},
707 {PRAllBits, "PRAllBits"},
708 {PRSomeBits, "PRSomeBits"},
709 {PRAll, "PRAll"},
710 {PRSome, "PRSome"},
714 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
715 proto_tree *pad_tree, struct CPropertyRestriction *v,
716 const char *fmt, ...)
718 proto_tree *tree;
719 proto_item *item;
720 const char *str;
721 va_list ap;
723 va_start(ap, fmt);
724 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
725 va_end(ap);
727 tree = proto_item_add_subtree(item, ett_CPropertyRestriction);
729 v->relop = tvb_get_letohl(tvb, offset);
730 str = val_to_str(v->relop, PR_VALS, "0x%04x");
731 proto_tree_add_text(tree, tvb, offset, 4, "relop: %s (0x%04x)",
732 str[0]=='\0' ? "" : str, v->relop);
733 proto_item_append_text(item, " Op: %s", str);
734 offset += 4;
736 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
738 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &v->prval, "prval");
740 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_lcid");
742 v->lcid = tvb_get_letohl(tvb, offset);
743 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", v->lcid);
744 offset += 4;
746 proto_item_set_end(item, tvb, offset);
748 return offset;
751 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
752 proto_tree *pad_tree, struct CCoercionRestriction *v,
753 const char *fmt, ...)
755 proto_tree *tree;
756 proto_item *item;
757 va_list ap;
759 va_start(ap, fmt);
760 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
761 va_end(ap);
763 tree = proto_item_add_subtree(item, ett_CCoercionRestriction);
765 v->value = tvb_get_letohl(tvb, offset);
766 proto_tree_add_text(tree, tvb, offset, 4, "value: %g", (double)v->value);
767 offset += 4;
769 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &v->child, "child");
771 proto_item_set_end(item, tvb, offset);
772 return offset;
775 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
776 proto_tree *pad_tree, struct CContentRestriction *v,
777 const char *fmt, ...)
779 proto_tree *tree;
780 proto_item *item;
781 va_list ap;
782 guint32 cc;
783 const char *str;
786 va_start(ap, fmt);
787 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
788 va_end(ap);
790 tree = proto_item_add_subtree(item, ett_CContentRestriction);
792 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
794 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding1");
796 cc = tvb_get_letohl(tvb, offset);
797 proto_tree_add_text(tree, tvb, offset, 4, "cc: %u", cc);
798 offset += 4;
800 // str = tvb_get_ephemeral_string_enc(tvb, offset, 2*cc, ENC_UTF_16);
801 str = tvb_get_unicode_string(tvb, offset, 2*cc, ENC_LITTLE_ENDIAN);
802 v->phrase = se_strdup(str);
803 proto_tree_add_text(tree, tvb, offset, 2*cc, "phrase: %s", str);
804 offset += 2*cc;
806 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding2");
808 v->lcid = tvb_get_letohl(tvb, offset);
809 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", v->lcid);
810 offset += 4;
812 v->method = tvb_get_letohl(tvb, offset);
813 proto_tree_add_text(tree, tvb, offset, 4, "method: 0x%08x", v->method);
814 offset += 4;
816 proto_item_set_end(item, tvb, offset);
817 return offset;
820 int parse_CNatLanguageRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
821 proto_tree *pad_tree, struct CNatLanguageRestriction *v,
822 const char *fmt, ...)
824 proto_tree *tree;
825 proto_item *item;
826 va_list ap;
827 guint32 cc;
828 const char *str;
831 va_start(ap, fmt);
832 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
833 va_end(ap);
835 tree = proto_item_add_subtree(item, ett_CNatLanguageRestriction);
837 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
839 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_cc");
841 cc = tvb_get_letohl(tvb, offset);
842 proto_tree_add_text(tree, tvb, offset, 4, "cc: %u", cc);
843 offset += 4;
845 // str = tvb_get_ephemeral_string_enc(tvb, offset, 2*cc, ENC_UTF_16);
846 str = tvb_get_unicode_string(tvb, offset, 2*cc, ENC_LITTLE_ENDIAN);
847 v->phrase = se_strdup(str);
848 proto_tree_add_text(tree, tvb, offset, 2*cc, "phrase: %s", str);
849 offset += 2*cc;
851 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_lcid");
853 v->lcid = tvb_get_letohl(tvb, offset);
854 proto_tree_add_text(tree, tvb, offset, 4, "lcid: 0x%08x", v->lcid);
855 offset += 4;
857 proto_item_set_end(item, tvb, offset);
858 return offset;
862 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
863 proto_tree *pad_tree _U_, struct CReuseWhere *v,
864 const char *fmt, ...)
866 proto_item *item;
867 va_list ap;
870 va_start(ap, fmt);
871 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
872 va_end(ap);
874 v->whereId = tvb_get_letohl(tvb, offset);
875 offset += 4;
877 proto_item_append_text(item, " Id: %u", v->whereId);
879 proto_item_set_end(item, tvb, offset);
880 return offset;
883 static value_string RT_VALS[] = {
884 {RTNone, "RTNone"},
885 {RTAnd, "RTAnd"},
886 {RTOr, "RTOr"},
887 {RTNot, "RTNot"},
888 {RTContent, "RTContent"},
889 {RTProperty, "RTProperty"},
890 {RTProximity, "RTProximity"},
891 {RTVector, ""},
892 {RTNatLanguage, "RTNatLanguage"},
893 {RTScope, "RTScope"},
894 {RTCoerce_Add, "RTCoerce_Add"},
895 {RTCoerce_Multiply, "RTCoerce_Multiply"},
896 {RTCoerce_Absolute, "RTCoerce_Absolute"},
897 {RTProb, "RTProb"},
898 {RTFeedback, "RTFeedback"},
899 {RTReldoc, "RTReldoc"},
900 {RTReuseWhere, "RTReuseWhere"},
901 {RTInternalProp, "RTInternalProp"},
902 {RTPhrase, "RTInternalProp"},
905 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
906 struct CRestriction *v, const char *fmt, ...)
908 proto_tree *tree;
909 proto_item *item;
910 const char *str;
911 va_list ap;
913 va_start(ap, fmt);
914 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
915 va_end(ap);
917 tree = proto_item_add_subtree(item, ett_CRestriction);
920 v->ulType = tvb_get_letohl(tvb, offset);
921 str = val_to_str(v->ulType, RT_VALS, "0x%.8x");
922 proto_tree_add_text(tree, tvb, offset, 4, "ulType: %s (0x%.8x)",
923 str[0] == '0' ? "" : str, v->ulType);
924 proto_item_append_text(item, " Type: %s", str);
925 offset += 4;
927 v->Weight = tvb_get_letohl(tvb, offset);
928 proto_tree_add_text(tree, tvb, offset, 4, "Weight: %u", v->ulType);
929 offset += 4;
931 switch(v->ulType) {
932 case RTNone:
933 break;
934 case RTAnd:
935 case RTOr:
936 case RTProximity:
937 case RTPhrase:
939 v->u.RTAnd = ep_alloc(sizeof(struct CNodeRestriction)); //XXX
940 offset = parse_CNodeRestriction(tvb, offset, tree, pad_tree, v->u.RTAnd, "CNodeRestriction");
941 break;
943 case RTNot:
945 v->u.RTNot = ep_alloc(sizeof(struct CRestriction)); //XXX
946 offset = parse_CRestriction(tvb, offset, tree, pad_tree,
947 v->u.RTNot, "CRestriction");
948 break;
950 case RTProperty:
952 v->u.RTProperty = ep_alloc(sizeof(struct CPropertyRestriction)); //XXX
953 offset = parse_CPropertyRestriction(tvb, offset, tree, pad_tree,
954 v->u.RTProperty, "CPropertyRestriction");
955 break;
957 case RTCoerce_Add:
958 case RTCoerce_Multiply:
959 case RTCoerce_Absolute:
961 v->u.RTCoerce_Add = ep_alloc(sizeof(struct CCoercionRestriction)); //XXX
962 offset = parse_CCoercionRestriction(tvb, offset, tree, pad_tree,
963 v->u.RTCoerce_Add, "CCoercionRestriction");
964 break;
966 case RTContent: {
967 v->u.RTContent = ep_alloc(sizeof(struct CContentRestriction)); //XXX
968 offset = parse_CContentRestriction(tvb, offset, tree, pad_tree,
969 v->u.RTContent, "CContentRestriction");
970 break;
972 case RTReuseWhere: {
973 v->u.RTReuseWhere = ep_alloc(sizeof(struct CReuseWhere)); //XXX
974 offset = parse_CReuseWhere(tvb, offset, tree, pad_tree,
975 v->u.RTReuseWhere, "CReuseWhere");
976 break;
978 case RTNatLanguage: {
979 v->u.RTNatLanguage = ep_alloc(sizeof(struct CNatLanguageRestriction)); //XXX
980 offset = parse_CNatLanguageRestriction(tvb, offset, tree, pad_tree,
981 v->u.RTNatLanguage, "CNatLanguageRestriction");
982 break;
984 default:
985 fprintf(stderr, "CRestriciont 0x%08x not Supported\n", v->ulType);
986 proto_item_append_text(item, " Not supported!");
989 proto_item_set_end(item, tvb, offset);
990 return offset;
993 static int parse_CRestrictionArray(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
994 const char *fmt, ...)
996 guint8 present, count;
998 proto_tree *tree;
999 proto_item *item;
1000 va_list ap;
1002 va_start(ap, fmt);
1003 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1004 va_end(ap);
1005 tree = proto_item_add_subtree(item, ett_CRestrictionArray);
1007 pad_tree = tree; //XXX
1009 count = tvb_get_guint8(tvb, offset);
1010 proto_tree_add_text(tree, tvb, offset, 1, "count: %u", count);
1011 offset += 1;
1013 present = tvb_get_guint8(tvb, offset);
1014 proto_tree_add_text(tree, tvb, offset, 1, "present: %u", present);
1015 offset += 1;
1017 if (present) {
1018 unsigned i;
1019 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCRestrictionPresent");
1021 for (i=0; i<count; i++) {
1022 struct CRestriction r;
1023 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "Restriction[%d]", i);
1026 proto_item_set_end(item, tvb, offset);
1027 return offset;
1030 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1031 proto_tree *pad_tree, struct CNodeRestriction *v,
1032 const char *fmt, ...)
1034 proto_tree *tree;
1035 proto_item *item;
1036 unsigned i;
1037 va_list ap;
1039 va_start(ap, fmt);
1040 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1041 va_end(ap);
1042 tree = proto_item_add_subtree(item, ett_CNodeRestriction);
1044 v->cNode = tvb_get_letohl(tvb, offset);
1045 proto_tree_add_text(tree, tvb, offset, 4, "cNode: %u", v->cNode);
1046 offset += 4;
1048 for (i=0; i<v->cNode; i++) {
1049 struct CRestriction r;
1050 ZERO_STRUCT(r);
1051 // offset = parse_padding(tvb, offset, 4, tree, "padding_paNode[%u]", i); /*at begin or end of loop ????*/
1052 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "paNode[%u]", i);
1053 offset = parse_padding(tvb, offset, 4, tree, "padding_paNode[%u]", i); /*at begin or end of loop ????*/
1055 // offset = parse_padding(tvb, offset, 4, pad_tree, "paNode[%u]", i); /*at begin or end of loop ????*/
1058 proto_item_set_end(item, tvb, offset);
1059 return offset;
1063 /*****************************************************************************************/
1065 static int vvalue_tvb_get0(tvbuff_t *tvb _U_, int offset _U_, void *val _U_)
1067 return 0;
1070 static int vvalue_tvb_get1(tvbuff_t *tvb, int offset, void *val)
1072 guint8 *ui1 = (guint8*)val;
1073 *ui1 = tvb_get_guint8(tvb, offset);
1074 return 1;
1077 static int vvalue_tvb_get2(tvbuff_t *tvb , int offset, void *val)
1079 guint16 *ui2 = (guint16*)val;
1080 *ui2 = tvb_get_letohs(tvb, offset);
1081 return 2;
1084 static int vvalue_tvb_get4(tvbuff_t *tvb , int offset, void *val)
1086 guint32 *ui4 = (guint32*)val;
1087 *ui4 = tvb_get_letohl(tvb, offset);
1088 return 4;
1091 static int vvalue_tvb_get8(tvbuff_t *tvb , int offset, void *val)
1093 guint64 *ui8 = (guint64*)val;
1094 *ui8 = tvb_get_letoh64(tvb, offset);
1095 return 8;
1098 static int vvalue_tvb_blob(tvbuff_t *tvb , int offset, void *val)
1100 struct data_blob *blob = (struct data_blob*)val;
1101 guint32 len = tvb_get_letohl(tvb, offset);
1102 const guint8 *data = tvb_get_ptr(tvb, offset + 4, len);
1104 blob->size = len;
1105 blob->data = se_memdup(data, len);
1107 return 4 + len;
1110 static int vvalue_tvb_bstr(tvbuff_t *tvb , int offset, void *val)
1112 struct data_str *str = (struct data_str*)val;
1113 guint32 len = tvb_get_letohl(tvb, offset);
1114 const void *ptr = tvb_get_ptr(tvb, offset + 4, len);
1116 //XXX this might be UTF-16
1117 str->len = len;
1118 str->str = se_strndup(ptr, len);
1119 return 4 + len;
1122 static int vvalue_tvb_lpstr(tvbuff_t *tvb , int offset, void *val)
1124 struct data_str *str = (struct data_str*)val;
1125 gint len;
1127 str->len = tvb_get_letohl(tvb, offset);
1128 str->str = tvb_get_seasonal_stringz(tvb, offset + 4, &len);
1129 /* XXX test str->len == len */
1130 return 4 + len;
1133 static int vvalue_tvb_lpwstr(tvbuff_t *tvb , int offset, void *val)
1135 struct data_str *str = (struct data_str*)val;
1136 gint len;
1137 gchar *ptr;
1139 str->len = tvb_get_letohl(tvb, offset);
1141 ptr = tvb_get_ephemeral_unicode_stringz(tvb, offset + 4, &len, ENC_LITTLE_ENDIAN);
1142 str->str = se_strdup (ptr);
1144 return 4 + len;
1147 static int vvalue_tvb_vector_internal(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type, int num)
1149 const int offset_in = offset;
1150 const gboolean varsize = (type->size == -1);
1151 const int elsize = varsize ? (int)sizeof(struct data_blob) : type->size;
1152 guint8 *data = se_alloc(elsize * num);
1153 int len, i;
1155 val->len = num;
1156 val->u.vt_ui1 = data;
1157 DISSECTOR_ASSERT((void*)&val->u == ((void*)&val->u.vt_ui1));
1159 for (i=0; i<num; i++) {
1160 len = type->tvb_get(tvb, offset, data);
1161 data += elsize;
1162 offset += len;
1163 if (varsize && (offset % 4) ) { /* at begin or end of loop ??? */
1164 int padding = 4 - (offset % 4);
1165 offset += padding;
1168 return offset - offset_in;
1171 static int vvalue_tvb_vector(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type)
1173 const int num = tvb_get_letohl(tvb, offset);
1174 return 4 + vvalue_tvb_vector_internal(tvb , offset+4, val, type, num);
1177 static void vvalue_strbuf_append_null(emem_strbuf_t *strbuf _U_, void *ptr _U_)
1180 static void vvalue_strbuf_append_i1(emem_strbuf_t *strbuf, void *ptr)
1182 gint8 i1 = *(gint8*)ptr;
1183 ep_strbuf_append_printf(strbuf, "%d", (int)i1);
1186 static void vvalue_strbuf_append_i2(emem_strbuf_t *strbuf, void *ptr)
1188 gint16 i2 = *(gint16*)ptr;
1189 ep_strbuf_append_printf(strbuf, "%d", (int)i2);
1192 static void vvalue_strbuf_append_i4(emem_strbuf_t *strbuf, void *ptr)
1194 gint32 i4 = *(gint32*)ptr;
1195 ep_strbuf_append_printf(strbuf, "%d", i4);
1198 static void vvalue_strbuf_append_i8(emem_strbuf_t *strbuf, void *ptr)
1200 gint64 i8 = *(gint64*)ptr;
1201 ep_strbuf_append_printf(strbuf, "%ld", i8);
1204 static void vvalue_strbuf_append_ui1(emem_strbuf_t *strbuf, void *ptr)
1206 guint8 ui1 = *(guint8*)ptr;
1207 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui1);
1210 static void vvalue_strbuf_append_ui2(emem_strbuf_t *strbuf, void *ptr)
1212 guint16 ui2 = *(guint16*)ptr;
1213 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui2);
1216 static void vvalue_strbuf_append_ui4(emem_strbuf_t *strbuf, void *ptr)
1218 guint32 ui4 = *(guint32*)ptr;
1219 ep_strbuf_append_printf(strbuf, "%d", ui4);
1222 static void vvalue_strbuf_append_ui8(emem_strbuf_t *strbuf, void *ptr)
1224 guint64 ui8 = *(guint64*)ptr;
1225 ep_strbuf_append_printf(strbuf, "%lu", ui8);
1228 static void vvalue_strbuf_append_r4(emem_strbuf_t *strbuf, void *ptr)
1230 float r4 = *(float*)ptr;
1231 ep_strbuf_append_printf(strbuf, "%g", (double)r4);
1234 static void vvalue_strbuf_append_r8(emem_strbuf_t *strbuf, void *ptr)
1236 double r8 = *(double*)ptr;
1237 ep_strbuf_append_printf(strbuf, "%g", r8);
1240 static void vvalue_strbuf_append_str(emem_strbuf_t *strbuf, void *ptr)
1242 struct data_str *str = (struct data_str*)ptr;
1243 ep_strbuf_append_printf(strbuf, "\"%s\"", str->str);
1246 static void vvalue_strbuf_append_blob(emem_strbuf_t *strbuf, void *ptr)
1248 struct data_blob *blob = (struct data_blob*)ptr;
1249 ep_strbuf_append_printf(strbuf, "size: %d", (int)blob->size);
1252 static void vvalue_strbuf_append_bool(emem_strbuf_t *strbuf, void *ptr)
1254 guint16 val = *(guint*)ptr;
1255 switch (val) {
1256 case 0:
1257 ep_strbuf_append(strbuf, "False");
1258 break;
1259 case 0xffff:
1260 ep_strbuf_append(strbuf, "True");
1261 break;
1262 default:
1263 ep_strbuf_append_printf(strbuf, "Invalid (0x%4x)", val);
1267 static void vvalue_strbuf_append_vector(emem_strbuf_t *strbuf, struct vt_vector val, struct vtype *type)
1269 const int elsize = (type->size == -1) ? (int)sizeof(struct data_blob) : type->size;
1270 unsigned i;
1271 guint8 *data = val.u.vt_ui1;
1272 ep_strbuf_append_c(strbuf, '[');
1273 for (i=0; i<val.len; i++) {
1274 if (i>0) {
1275 ep_strbuf_append_c(strbuf, ',');
1277 type->strbuf_append(strbuf, data);
1278 data += elsize;
1280 ep_strbuf_append_c(strbuf, ']');
1284 static struct vtype VT_TYPE[] = {
1285 {VT_EMPTY, "VT_EMPTY", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
1286 {VT_NULL, "VT_NULL", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
1287 {VT_I2, "VT_I2", 2, vvalue_tvb_get2, vvalue_strbuf_append_i2},
1288 {VT_I4, "VT_I4", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
1289 {VT_R4, "VT_R4", 4, vvalue_tvb_get4, vvalue_strbuf_append_r4},
1290 {VT_R8, "VT_R8", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
1291 {VT_CY, "VT_CY", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1292 {VT_DATE, "VT_DATE", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
1293 // {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_bstr, vvalue_strbuf_append_str},
1294 {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
1295 {VT_ERROR, "VT_ERROR", 8, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1296 {VT_BOOL, "VT_BOOL", 2, vvalue_tvb_get2, vvalue_strbuf_append_bool},
1297 {VT_VARIANT, "VT_VARIANT", -1, NULL, NULL},
1298 {VT_DECIMAL, "VT_DECIMAL", 16, NULL, NULL},
1299 {VT_I1, "VT_I1", 1, vvalue_tvb_get1, vvalue_strbuf_append_i1},
1300 {VT_UI1, "VT_UI1", 1, vvalue_tvb_get1, vvalue_strbuf_append_ui1},
1301 {VT_UI2, "VT_UI2", 2, vvalue_tvb_get2, vvalue_strbuf_append_ui2},
1302 {VT_UI4, "VT_UI4", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1303 {VT_I8, "VT_I8", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1304 {VT_UI8, "VT_UI8", 8, vvalue_tvb_get8, vvalue_strbuf_append_ui8},
1305 {VT_INT, "VT_INT", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
1306 {VT_UINT, "VT_UINT", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1307 {VT_LPSTR, "VT_LPSTR", -1, vvalue_tvb_lpstr, vvalue_strbuf_append_str},
1308 {VT_LPWSTR, "VT_LPWSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
1309 {VT_COMPRESSED_LPWSTR, "VT_COMPRESSED_LPWSTR", -1, NULL, vvalue_strbuf_append_str},
1310 {VT_FILETIME, "VT_FILETIME", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1311 {VT_BLOB, "VT_BLOB", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
1312 {VT_BLOB_OBJECT, "VT_BLOB_OBJECT", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
1313 {VT_CLSID, "VT_CLSID", 16, NULL, NULL},
1316 static struct vtype *vType_get_type(enum vType t) {
1317 unsigned i;
1318 t &= 0xFF;
1319 for (i=0; i<array_length(VT_TYPE); i++) {
1320 if (t == VT_TYPE[i].tag) {
1321 return &VT_TYPE[i];
1324 return NULL;
1327 static char *str_CBaseStorageVariant(struct CBaseStorageVariant *value, gboolean print_type)
1330 emem_strbuf_t *strbuf = ep_strbuf_new(NULL);
1331 if (value == NULL) {
1332 return "<NULL>";
1335 if (value->type == NULL) {
1336 return "<??""?>";
1339 if (print_type) {
1340 ep_strbuf_append(strbuf, value->type->str);
1342 if (value->vType & 0xFF00) {
1343 ep_strbuf_append_printf(strbuf, "[%d]", value->vValue.vt_vector.len);
1345 ep_strbuf_append(strbuf, ": ");
1348 switch (value->vType & 0xFF00) {
1349 case 0:
1350 value->type->strbuf_append(strbuf, &value->vValue);
1351 break;
1352 case VT_ARRAY:
1353 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_array.vData, value->type);
1354 break;
1355 case VT_VECTOR:
1356 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_vector, value->type);
1357 break;
1358 default:
1359 ep_strbuf_append(strbuf, "Invalid");
1362 return strbuf->str;
1365 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree _U_,
1366 struct CBaseStorageVariant *value, const char *text)
1368 int i, len;
1369 proto_item *ti, *ti_type, *ti_val;
1370 proto_tree *tree, *tr;
1371 enum vType baseType, highType;
1373 ZERO_STRUCT(*value);
1375 ti = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1376 tree = proto_item_add_subtree(ti, ett_CBaseStorageVariant);
1378 value->vType = tvb_get_letohs(tvb, offset);
1379 value->type = vType_get_type(value->vType);
1381 ti_type = proto_tree_add_text(tree, tvb, offset, 2, "vType: %s", value->type->str);
1382 offset += 2;
1384 value->vData1 = tvb_get_guint8(tvb, offset);
1385 proto_tree_add_text(tree, tvb, offset, 1, "vData1: %d", value->vData1);
1386 offset += 1;
1388 value->vData2 = tvb_get_guint8(tvb, offset);
1389 proto_tree_add_text(tree, tvb, offset, 1, "vData2: %d", value->vData2);
1390 offset += 1;
1392 baseType = value->vType & 0x00FF;
1393 highType = value->vType & 0xFF00;
1395 if (value->type == NULL) {
1396 goto not_supported;
1399 ti_val = proto_tree_add_text(tree, tvb, offset, 0, "vValue");
1401 switch (highType) {
1402 case VT_EMPTY:
1403 len = value->type->tvb_get(tvb, offset, &value->vValue.vt_single);
1404 offset += len;
1405 break;
1406 case VT_VECTOR:
1407 proto_item_append_text(ti_type, "|VT_VECTOR");
1408 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Vector);
1410 len = vvalue_tvb_vector(tvb, offset, &value->vValue.vt_vector, value->type);
1411 proto_tree_add_text(tr, tvb, offset, 4, "num: %d", value->vValue.vt_vector.len);
1412 offset += len;
1413 break;
1414 case VT_ARRAY: {
1415 guint16 cDims, fFeatures;
1416 guint32 cbElements, cElements, lLbound;
1417 int num = 1;
1419 proto_item_append_text(ti_type, "|VT_ARRAY");
1420 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Array);
1422 cDims = tvb_get_letohs(tvb, offset);
1423 proto_tree_add_text(tr, tvb, offset, 2, "cDims: %d", cDims);
1424 offset += 2;
1426 fFeatures = tvb_get_letohs(tvb, offset);
1427 proto_tree_add_text(tr, tvb, offset, 2, "fFeaturess: %d", fFeatures);
1428 offset += 2;
1430 cbElements = tvb_get_letohl(tvb, offset);
1431 proto_tree_add_text(tr, tvb, offset, 4, "cbElements: %d", cbElements);
1432 offset += 4;
1433 for (i=0; i<cDims; i++) {
1434 cElements = tvb_get_letohl(tvb, offset);
1435 lLbound = tvb_get_letohl(tvb, offset + 4);
1436 proto_tree_add_text(tr, tvb, offset, 8, "Rgsabound[%d]: (%d:%d)", i, cElements, lLbound);
1437 offset += 8;
1438 num *= cElements;
1441 len = vvalue_tvb_vector_internal(tvb , offset, &value->vValue.vt_array.vData, value->type, num);
1442 offset += len;
1443 break;
1445 default:
1446 proto_item_append_text(ti_type, "|0x%x", highType);
1448 proto_item_set_end(ti, tvb, offset);
1449 proto_item_set_end(ti_val, tvb, offset);
1451 proto_item_append_text(ti_val, " %s", str_CBaseStorageVariant(value, false));
1452 proto_item_append_text(ti, " %s", str_CBaseStorageVariant(value, true));
1454 goto done;
1456 not_supported:
1457 proto_item_append_text(ti, ": sorry, vType %02x not handled yet!", (unsigned)value->vType);
1458 done:
1459 return offset;
1462 enum {
1463 DBKIND_GUID_NAME = 0,
1464 DBKIND_GUID_PROPID = 1
1467 static int parse_CDbColId(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree, const char *text)
1469 guint32 eKind, ulId;
1470 e_guid_t guid;
1471 static const char *KIND[] = {"DBKIND_GUID_NAME", "DBKIND_GUID_PROPID"};
1473 proto_item *tree_item = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1474 proto_tree *tree = proto_item_add_subtree(tree_item, ett_CDbColId);
1476 eKind = tvb_get_letohl(tvb, offset);
1477 proto_tree_add_text(tree, tvb, offset, 4, "eKind: %s (%u)", eKind < 2 ? KIND[eKind] : "???", eKind);
1478 offset += 4;
1480 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingGuidAlign");
1482 offset = parse_guid(tvb, offset, tree, &guid, "GUID");
1484 ulId = tvb_get_letohl(tvb, offset);
1485 proto_tree_add_text(tree, tvb, offset, 4, "ulId: %d", ulId);
1486 offset += 4;
1488 if (eKind == DBKIND_GUID_NAME) {
1489 char *name;
1490 int len = ulId; //*2 ???
1491 name = tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
1492 proto_tree_add_text(tree, tvb, offset, len, "vString: \"%s\"", name);
1493 proto_item_append_text(tree_item, " \"%s\"", name);
1494 offset += len;
1495 } else if (eKind == DBKIND_GUID_PROPID) {
1496 proto_item_append_text(tree_item, " %08x", ulId);
1497 } else {
1498 proto_item_append_text(tree_item, "<INVALID>");
1501 proto_item_set_end(tree_item, tvb, offset);
1503 return offset;
1506 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1507 proto_tree *pad_tree, struct GuidPropertySet *propset,
1508 const char *fmt, ...)
1510 static const value_string EMPTY_VS[] = {{0, NULL}};
1511 const value_string *vs = (propset && propset->id_map) ? propset->id_map : EMPTY_VS;
1512 guint32 id, opt, status;
1513 struct CBaseStorageVariant value;
1514 proto_item *item;
1515 proto_tree *tree;
1516 const char *str;
1517 va_list ap;
1519 va_start(ap, fmt);
1520 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1521 va_end(ap);
1523 tree = proto_item_add_subtree(item, ett_CDbProp);
1525 id = tvb_get_letohl(tvb, offset);
1526 str = val_to_str(id, vs, "0x%08x");
1527 proto_tree_add_text(tree, tvb, offset, 4, "Id: %s (0x%08x)", str[0] == '0' ? "" : str, id);
1528 offset += 4;
1529 proto_item_append_text(item, " Id: %s", str);
1531 opt = tvb_get_letohl(tvb, offset);
1532 proto_tree_add_text(tree, tvb, offset, 4, "Options: %08x", opt);
1533 offset += 4;
1535 status = tvb_get_letohl(tvb, offset);
1536 proto_tree_add_text(tree, tvb, offset, 4, "Status: %08x", status);
1537 offset += 4;
1539 offset = parse_CDbColId(tvb, offset, tree, pad_tree, "colid");
1541 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &value, "vValue");
1543 str = str_CBaseStorageVariant(&value, true);
1544 proto_item_append_text(item, " %s", str);
1545 proto_item_set_end(item, tvb, offset);
1547 return offset;
1550 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1551 proto_tree *pad_tree, const char *fmt, ...)
1553 int i, num;
1554 e_guid_t guid;
1555 struct GuidPropertySet *pset;
1556 proto_item *item;
1557 proto_tree *tree;
1558 va_list ap;
1560 va_start(ap, fmt);
1561 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1562 va_end(ap);
1564 tree = proto_item_add_subtree(item, ett_CDbPropSet);
1566 offset = parse_guid(tvb, offset, tree, &guid, "guidPropertySet");
1568 pset = GuidPropertySet_find_guid(&guid);
1570 if (pset) {
1571 proto_item_append_text(item, " \"%s\" (%s)", pset->desc, pset->def);
1572 } else {
1573 const char *guid_str = guid_to_str(&guid);
1574 proto_item_append_text(item, " {%s}", guid_str);
1577 offset = parse_padding(tvb, offset, 4, pad_tree, "guidPropertySet");
1579 num = tvb_get_letohl(tvb, offset);
1580 proto_tree_add_text(tree, tvb, offset, 4, "cProperties: %d", num);
1581 offset += 4;
1582 proto_item_append_text(item, " Num: %d", num);
1584 for (i = 0; i<num; i++) {
1585 offset = parse_padding(tvb, offset, 4, pad_tree, "aProp[%d]", i);
1586 offset = parse_CDbProp(tvb, offset, tree, pad_tree, pset, "aProp[%d]", i);
1589 proto_item_set_end(item, tvb, offset);
1590 return offset;
1593 static int parse_PropertySetArray(tvbuff_t *tvb, int offset, int size_offset,
1594 proto_tree *parent_tree, proto_tree *pad_tree,
1595 const char *fmt, ...)
1597 const int offset_in = offset;
1598 guint32 size, num;
1599 int i;
1600 proto_tree *tree;
1601 proto_item *item;
1602 va_list ap;
1604 va_start(ap, fmt);
1605 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1606 va_end(ap);
1608 tree = proto_item_add_subtree(item, ett_CDbPropSet_Array);
1610 size = tvb_get_letohl(tvb, size_offset);
1611 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_Blob1, tvb,
1612 size_offset, 4, ENC_LITTLE_ENDIAN);
1614 num = tvb_get_letohl(tvb, offset);
1615 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_PropSets_num, tvb,
1616 offset, 4, ENC_LITTLE_ENDIAN);
1617 offset += 4;
1619 for (i = 0; i < (int)num; i++) {
1620 offset = parse_CDbPropSet(tvb, offset, tree, pad_tree, "PropertySet[%d]", i);
1623 proto_item_set_end(item, tvb, offset);
1624 DISSECTOR_ASSERT(offset - offset_in == (int)size);
1625 return offset;
1628 int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...)
1630 guint32 count, v, i;
1631 proto_item *item;
1633 va_list ap;
1635 va_start(ap, fmt);
1636 item = proto_tree_add_text_valist(tree, tvb, offset, 0, fmt, ap);
1637 va_end(ap);
1639 count = tvb_get_letohl(tvb, offset);
1640 offset += 4;
1642 proto_item_append_text(item, " Count %u [", count);
1643 for (i=0; i<count; i++) {
1644 v = tvb_get_letohl(tvb, offset);
1645 offset += 4;
1646 if (i>0) {
1647 proto_item_append_text(item, ",%u", v);
1648 } else {
1649 proto_item_append_text(item, "%u", v);
1652 proto_item_append_text(item, "]");
1653 return offset;
1656 /* 2.2.1.23 RANGEBOUNDARY */
1657 int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1658 proto_tree *pad_tree, const char *fmt, ...)
1660 guint32 ulType;
1661 guint8 labelPresent;
1662 proto_item *item;
1663 proto_tree *tree;
1664 struct CBaseStorageVariant prval;
1665 va_list ap;
1667 va_start(ap, fmt);
1668 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1669 tree = proto_item_add_subtree(item, ett_RANGEBOUNDARY);
1670 va_end(ap);
1672 ulType = tvb_get_letohl(tvb, offset);
1673 proto_tree_add_text(tree, tvb, offset, 4, "ulType 0x%08x", ulType);
1674 proto_item_append_text(item, ": Type 0x%08x", ulType);
1675 offset += 4;
1677 ZERO_STRUCT(prval);
1678 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &prval, "prVal");
1680 labelPresent = tvb_get_guint8(tvb, offset);
1681 proto_tree_add_text(tree, tvb, offset, 1, "labelPresent: %s", labelPresent ? "True" : "False");
1682 offset += 1;
1684 if (labelPresent) {
1685 guint32 ccLabel;
1686 const char *label;
1687 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingLabelPresent");
1689 ccLabel = tvb_get_letohl(tvb, offset);
1690 proto_tree_add_text(tree, tvb, offset, 4, "ccLabel: %u", ccLabel);
1691 offset += 4;
1693 label = tvb_get_unicode_string(tvb, offset, 2*ccLabel, ENC_LITTLE_ENDIAN);
1694 proto_tree_add_text(tree, tvb, offset, 2*ccLabel, "Label: \"%s\"", label);
1695 proto_item_append_text(item, " Label: \"%s\"", label);
1696 offset += 2*ccLabel;
1699 proto_item_append_text(item, " Val: %s", str_CBaseStorageVariant(&prval, true));
1701 proto_item_set_end(item, tvb, offset);
1702 return offset;
1706 /* 2.2.1.22 CRangeCategSpec */
1707 int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
1708 proto_tree *parent_tree, proto_tree *pad_tree,
1709 const char *fmt, ...)
1711 proto_item *item;
1712 proto_tree *tree;
1713 va_list ap;
1714 unsigned i;
1715 guint32 lcid, cRange;
1717 va_start(ap, fmt);
1718 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1719 tree = proto_item_add_subtree(item, ett_CRangeCategSpec);
1720 va_end(ap);
1722 lcid = tvb_get_letohl(tvb, offset);
1723 proto_tree_add_text(tree, tvb, offset, 4, "Lcid 0x%08x", lcid);
1724 offset += 4;
1726 cRange = tvb_get_letohl(tvb, offset);
1727 proto_tree_add_text(tree, tvb, offset, 4, "cRange 0x%08x", cRange);
1728 offset += 4;
1730 for (i=0; i<cRange; i++) {
1731 offset = parse_RANGEBOUNDARY(tvb, offset, tree, pad_tree, "aRangeBegin[%u]", i);
1735 proto_item_set_end(item, tvb, offset);
1736 return offset;
1739 /* 2.2.1.21 CCategSpec */
1740 int parse_CCategSpec(tvbuff_t *tvb, int offset,
1741 proto_tree *parent_tree, proto_tree *pad_tree,
1742 const char *fmt, ...)
1744 proto_item *item;
1745 proto_tree *tree;
1747 va_list ap;
1748 guint32 type;
1750 va_start(ap, fmt);
1751 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1752 tree = proto_item_add_subtree(item, ett_CCategSpec);
1753 va_end(ap);
1755 type = tvb_get_letohl(tvb, offset);
1756 proto_tree_add_text(tree, tvb, offset, 4, "Type 0x%08x", type);
1757 proto_item_append_text(item, " Type %u", type);
1758 offset += 4;
1760 offset = parse_CSort(tvb, offset, tree, pad_tree, "CSort");
1762 offset = parse_CRangeCategSpec(tvb, offset, tree, pad_tree, "CRangeCategSpec");
1764 proto_item_set_end(item, tvb, offset);
1765 return offset;
1768 /* 2.2.1.25 CAggregSpec */
1769 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
1770 proto_tree *parent_tree, proto_tree *pad_tree,
1771 const char *fmt, ...)
1773 proto_item *item;
1774 proto_tree *tree;
1775 va_list ap;
1776 guint8 type;
1777 guint32 ccAlias, idColumn, ulMaxNumToReturn, idRepresentative;
1778 const char *alias;
1780 va_start(ap, fmt);
1781 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1782 tree = proto_item_add_subtree(item, ett_CAggregSpec);
1783 va_end(ap);
1785 type = tvb_get_guint8(tvb, offset);
1786 proto_tree_add_text(tree, tvb, offset, 1, "type: %u", type);
1787 proto_item_append_text(item, "type: %u", type);
1788 offset += 1;
1790 offset = parse_padding(tvb, offset, 4, pad_tree, "padding");
1792 ccAlias = tvb_get_letohl(tvb, offset);
1793 proto_tree_add_text(tree, tvb, offset, 1, "ccAlias: %u", ccAlias);
1794 offset += 4;
1796 alias = tvb_get_unicode_string(tvb, offset, 2*ccAlias, ENC_LITTLE_ENDIAN);
1797 proto_tree_add_text(tree, tvb, offset, 2*ccAlias, "Alias: %s", alias);
1798 offset += 2*ccAlias;
1800 idColumn = tvb_get_letohl(tvb, offset);
1801 proto_tree_add_text(tree, tvb, offset, 1, "idColumn: %u", idColumn);
1802 offset += 4;
1803 /* Optional ???
1804 ulMaxNumToReturn, idRepresentative;
1806 fprintf(stderr, "WARNING, dont know if optional members are present!\n ");
1808 proto_item_set_end(item, tvb, offset);
1809 return offset;
1812 /* 2.2.1.24 CAggregSet */
1813 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
1814 proto_tree *parent_tree, proto_tree *pad_tree,
1815 const char *fmt, ...)
1817 guint32 cCount, i;
1818 proto_item *item;
1819 proto_tree *tree;
1821 va_list ap;
1823 va_start(ap, fmt);
1824 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1825 tree = proto_item_add_subtree(item, ett_CAggregSet);
1826 va_end(ap);
1828 cCount = tvb_get_letohl(tvb, offset);
1829 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1830 offset += 4;
1832 for (i=0; i<cCount; i++) {
1833 /* 2.2.1.25 CAggregSpec */
1834 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "AggregSpecs[%u]", i);
1837 proto_item_set_end(item, tvb, offset);
1838 return offset;
1841 /* 2.2.1.27 CAggregSortKey */
1842 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
1843 proto_tree *parent_tree, proto_tree *pad_tree,
1844 const char *fmt, ...)
1846 guint32 order;
1847 proto_item *item;
1848 proto_tree *tree;
1850 va_list ap;
1852 va_start(ap, fmt);
1853 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1854 tree = proto_item_add_subtree(item, ett_CAggregSortKey);
1855 va_end(ap);
1857 order = tvb_get_letohl(tvb, offset);
1858 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", order);
1859 offset += 4;
1861 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "ColumnSpec");
1863 proto_item_set_end(item, tvb, offset);
1864 return offset;
1868 /* 2.2.1.26 CSortAggregSet */
1869 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
1870 proto_tree *parent_tree, proto_tree *pad_tree,
1871 const char *fmt, ...)
1873 guint32 cCount, i;
1874 proto_item *item;
1875 proto_tree *tree;
1877 va_list ap;
1879 va_start(ap, fmt);
1880 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1881 tree = proto_item_add_subtree(item, ett_CSortAggregSet);
1882 va_end(ap);
1884 cCount = tvb_get_letohl(tvb, offset);
1885 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1886 offset += 4;
1888 for (i=0; i<cCount; i++) {
1889 /* 2.2.1.27 CAggregSortKey */
1890 offset = parse_CAggregSortKey(tvb, offset, tree, pad_tree, "SortKeys[%u]", i);
1893 proto_item_set_end(item, tvb, offset);
1894 return offset;
1897 enum CInGroupSortAggregSet_type {
1898 GroupIdDefault = 0x00, /* The default for all ranges. */
1899 GroupIdMinValue = 0x01, /*The first range in the parent's group.*/
1900 GroupIdNull = 0x02, /*The last range in the parent's group.*/
1901 GroupIdValue = 0x03,
1904 /* 2.2.1.29 CInGroupSortAggregSet */
1905 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
1906 proto_tree *parent_tree, proto_tree *pad_tree,
1907 const char *fmt, ...)
1909 proto_item *item;
1910 proto_tree *tree;
1911 va_list ap;
1912 enum CInGroupSortAggregSet_type type;
1914 va_start(ap, fmt);
1915 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1916 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSet);
1917 va_end(ap);
1919 type = tvb_get_guint8(tvb, offset);
1920 proto_tree_add_text(tree, tvb, offset, 1, "Type: 0x%02x", (unsigned)type);
1921 offset += 1;
1923 offset = parse_padding(tvb, offset, 4, pad_tree, "CInGroupSortAggregSet");
1925 if (type == GroupIdValue) {
1926 struct CBaseStorageVariant id;
1927 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &id, "inGroupId");
1930 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
1932 proto_item_set_end(item, tvb, offset);
1933 return offset;
1937 /* 2.2.1.28 CInGroupSortAggregSets */
1938 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
1939 proto_tree *parent_tree, proto_tree *pad_tree,
1940 const char *fmt, ...)
1942 guint32 cCount, i;
1943 proto_item *item;
1944 proto_tree *tree;
1946 va_list ap;
1948 va_start(ap, fmt);
1949 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1950 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSets);
1951 va_end(ap);
1953 cCount = tvb_get_letohl(tvb, offset);
1954 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
1955 offset += 4;
1957 for (i=0; i<cCount; i++) {
1958 /* 2.2.1.29 CInGroupSortAggregSet */
1959 offset = parse_CInGroupSortAggregSet(tvb, offset, tree, pad_tree, "SortSets[%u]", i);
1962 proto_item_set_end(item, tvb, offset);
1963 return offset;
1966 /* 2.2.1.20 CCategorizationSpec */
1967 int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
1968 proto_tree *parent_tree, proto_tree *pad_tree,
1969 const char *fmt, ...)
1971 guint32 cMaxResults;
1972 proto_item *item;
1973 proto_tree *tree;
1975 va_list ap;
1977 va_start(ap, fmt);
1978 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1979 tree = proto_item_add_subtree(item, ett_CCategorizationSpec);
1980 va_end(ap);
1982 /* 2.2.1.18 CColumnSet */
1983 offset = parse_CColumnSet(tvb, offset, tree, "csColumns");
1985 /* 2.2.1.21 CCategSpec */
1986 offset = parse_CCategSpec(tvb, offset, tree, pad_tree, "Spec");
1988 /* 2.2.1.24 CAggregSet */
1989 offset = parse_CAggregSet(tvb, offset, tree, pad_tree, "AggregSet");
1991 /* 2.2.1.26 CSortAggregSet */
1992 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
1994 /* 2.2.1.28 CInGroupSortAggregSets */
1995 offset = parse_CInGroupSortAggregSets(tvb, offset, tree, pad_tree, "InGroupSortAggregSets");
1997 cMaxResults = tvb_get_letohl(tvb, offset);
1998 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", cMaxResults);
1999 offset += 4;
2001 proto_item_set_end(item, tvb, offset);
2002 return offset;
2005 int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
2006 proto_tree *parent_tree, proto_tree *pad_tree _U_,
2007 const char *fmt, ...)
2009 guint32 opt, maxres, timeout;
2010 proto_item *item;
2011 proto_tree *tree;
2013 va_list ap;
2015 va_start(ap, fmt);
2016 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2017 tree = proto_item_add_subtree(item, ett_CRowsetProperties);
2018 va_end(ap);
2020 opt = tvb_get_letohl(tvb, offset);
2021 proto_tree_add_text(tree, tvb, offset, 4, "uBooleanOptions: 0x%08x", opt);
2022 offset += 4;
2024 proto_tree_add_text(tree, tvb, offset, 4, "ulMaxOpenRows (ignored)");
2025 offset += 4;
2027 proto_tree_add_text(tree, tvb, offset, 4, "ulMemoryUsage (ignored)");
2028 offset += 4;
2030 maxres = tvb_get_letohl(tvb, offset);
2031 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", maxres);
2032 offset += 4;
2034 timeout = tvb_get_letohl(tvb, offset);
2035 proto_tree_add_text(tree, tvb, offset, 4, "cCmdTimeout: %u", timeout);
2036 offset += 4;
2038 proto_item_set_end(item, tvb, offset);
2039 return offset;
2042 int parse_CPidMapper(tvbuff_t *tvb, int offset,
2043 proto_tree *parent_tree, proto_tree *pad_tree,
2044 const char *fmt, ...)
2046 proto_item *item;
2047 proto_tree *tree;
2048 va_list ap;
2049 guint32 count, i;
2051 va_start(ap, fmt);
2052 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2053 tree = proto_item_add_subtree(item, ett_CPidMapper);
2054 va_end(ap);
2056 count = tvb_get_letohl(tvb, offset);
2057 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
2058 offset += 4;
2060 offset = parse_padding(tvb, offset, 8, pad_tree, "CPidMapper_PropSpec");
2062 for (i=0; i<count; i++) {
2063 struct CFullPropSpec v;
2064 ZERO_STRUCT(v);
2065 offset = parse_padding(tvb, offset, 4, pad_tree,
2066 "CPidMapper_PropSpec[%u]", i); //at begin or end of loop???
2067 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v, "PropSpec[%u]", i);
2070 proto_item_set_end(item, tvb, offset);
2071 return offset;
2074 /* Code to actually dissect the packets */
2076 static int dissect_CPMConnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2078 proto_item *ti;
2079 proto_tree *tree;
2080 gint offset = 16;
2081 guint len;
2082 guint32 version;
2084 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2085 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
2086 proto_item_set_text(ti, "CPMConnect%s", in ? "In" : "Out");
2087 col_append_str(pinfo->cinfo, COL_INFO, "Connect");
2089 version = tvb_get_letohl(tvb, offset);
2090 ti = proto_tree_add_item(tree, hf_mswsp_msg_Connect_Version, tvb,
2091 offset, 4, ENC_LITTLE_ENDIAN);
2092 if (version & 0xffff0000) {
2093 proto_item_append_text(ti, " 64 bit");
2095 switch (version & 0xffff) {
2096 case 0x102:
2097 proto_item_append_text(ti, " w2k8 or vista");
2098 break;
2099 case 0x109:
2100 proto_item_append_text(ti, " XP or w2k3, with Windows Search 4.0");
2101 break;
2102 case 0x700:
2103 proto_item_append_text(ti, " win7 or w2k8r2");
2104 break;
2106 offset += 4;
2108 if (in) {
2109 guint32 blob_size1_off, blob_size2_off;
2110 proto_tree *pad_tree;
2112 ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
2113 pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
2115 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_ClientIsRemote, tvb,
2116 offset, 4, ENC_LITTLE_ENDIAN);
2117 offset += 4;
2119 /* _cbBlob1 */
2120 blob_size1_off = offset;
2121 offset += 4;
2123 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcbBlob2");
2125 /* _cbBlob2 */
2126 blob_size2_off = offset;
2127 offset += 4;
2129 offset = parse_padding(tvb, offset, 16, pad_tree, "_padding");
2131 len = tvb_unicode_strsize(tvb, offset);
2132 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_MachineName, tvb,
2133 offset, len, ENC_UTF_16);
2134 /*This shouldnt be necessary, is this a bug or is there some GUI setting I've missed?*/
2135 proto_item_set_text(ti, "Remote machine: %s",
2136 tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN));
2137 offset += len;
2139 len = tvb_unicode_strsize(tvb, offset);
2140 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_UserName, tvb,
2141 offset, len, ENC_UTF_16);
2142 proto_item_set_text(ti, "User: %s", tvb_get_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN));
2143 offset += len;
2145 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcPropSets");
2147 offset = parse_PropertySetArray(tvb, offset, blob_size1_off, tree, pad_tree, "PropSets");
2149 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingExtPropset");
2151 offset = parse_PropertySetArray(tvb, offset, blob_size2_off, tree, pad_tree, "ExtPropset");
2153 offset = parse_padding(tvb, offset, 8, pad_tree, "???");
2155 DISSECTOR_ASSERT(offset == (int)tvb_length(tvb));
2157 /* make "Padding" the last item */
2158 proto_tree_move_item(tree, ti, proto_tree_get_parent(pad_tree));
2159 } else {
2162 return tvb_length(tvb);
2165 static int dissect_CPMDisconnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2167 col_append_str(pinfo->cinfo, COL_INFO, "Disconnect");
2168 return tvb_length(tvb);
2171 static int dissect_CPMCreateQuery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2173 gint offset = 16;
2174 proto_item *ti;
2175 proto_tree *tree;
2177 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2178 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
2180 proto_item_set_text(ti, "CPMCreateQuery%s", in ? "In" : "Out");
2181 col_append_str(pinfo->cinfo, COL_INFO, "CreateQuery");
2183 if (in) {
2184 proto_item *ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
2185 proto_tree *pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
2186 guint8 CColumnSetPresent, CRestrictionPresent, CSortSetPresent, CCategorizationSetPresent;
2187 guint32 size = tvb_get_letohl(tvb, offset);
2188 proto_tree_add_text(tree, tvb, offset, 4, "size");
2189 proto_tree_add_text(tree, tvb, offset, size, "ALL");
2190 offset += 4;
2192 CColumnSetPresent = tvb_get_guint8(tvb, offset);
2193 proto_tree_add_text(tree, tvb, offset, 1, "CColumnSetPresent: %s", CColumnSetPresent ? "True" : "False");
2194 offset += 1;
2196 if (CColumnSetPresent) {
2197 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCColumnSetPresent");
2198 offset = parse_CColumnSet(tvb, offset, tree, "CColumnSet");
2201 CRestrictionPresent = tvb_get_guint8(tvb, offset);
2202 proto_tree_add_text(tree, tvb, offset, 1, "CRestrictionPresent: %s", CColumnSetPresent ? "True" : "False");
2203 offset += 1;
2204 if (CRestrictionPresent) {
2205 offset = parse_CRestrictionArray(tvb, offset, tree, pad_tree, "RestrictionArray");
2208 CSortSetPresent = tvb_get_guint8(tvb, offset);
2209 proto_tree_add_text(tree, tvb, offset, 1, "CSortSetPresent: %s", CSortSetPresent ? "True" : "False");
2210 offset += 1;
2211 if (CSortSetPresent) {
2212 offset = parse_padding(tvb, offset, 4, tree, "paddingCSortSetPresent");
2214 proto_tree_add_text(tree, tvb, offset, 8, "XXX");
2215 offset += 8;
2217 offset = parse_CSortSet(tvb, offset, tree, pad_tree, "SortSet");
2220 CCategorizationSetPresent = tvb_get_guint8(tvb, offset);
2221 proto_tree_add_text(tree, tvb, offset, 1, "CCategorizationSetPresent: %s", CCategorizationSetPresent ? "True" : "False");
2222 offset += 1;
2224 if (CCategorizationSetPresent) {
2225 guint32 count, i;
2226 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCCategorizationSetPresent");
2227 /* 2.2.1.19 CCategorizationSet */
2228 count = tvb_get_letohl(tvb, offset);
2229 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
2230 offset += 4;
2231 for (i=0; i<count; i++) {
2232 offset = parse_CCategorizationSpec(tvb, offset, tree, pad_tree, "categories[%u]", i);
2236 offset = parse_padding(tvb, offset, 4, tree, "XXXX"); //XXX
2238 offset = parse_CRowsetProperties(tvb, offset, tree, pad_tree, "RowSetProperties");
2240 offset = parse_CPidMapper(tvb, offset, tree, pad_tree, "PidMapper");
2243 return tvb_length(tvb);
2246 static int dissect_CPMFreeCursor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2248 col_append_str(pinfo->cinfo, COL_INFO, "FreeCursor");
2249 return tvb_length(tvb);
2252 static int dissect_CPMGetRows(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2254 col_append_str(pinfo->cinfo, COL_INFO, "GetRows");
2255 return tvb_length(tvb);
2258 static int dissect_CPMRatioFinished(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2260 col_append_str(pinfo->cinfo, COL_INFO, "RatioFinished");
2261 return tvb_length(tvb);
2264 static int dissect_CPMCompareBmk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2266 col_append_str(pinfo->cinfo, COL_INFO, "CompareBmk");
2267 return tvb_length(tvb);
2270 static int dissect_CPMGetApproximatePosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2272 col_append_str(pinfo->cinfo, COL_INFO, "GetApproximatePosition");
2273 return tvb_length(tvb);
2276 static int dissect_CPMSetBindings(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2278 col_append_str(pinfo->cinfo, COL_INFO, "SetBindings");
2279 return tvb_length(tvb);
2282 static int dissect_CPMGetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2284 col_append_str(pinfo->cinfo, COL_INFO, "GetNotify");
2285 return tvb_length(tvb);
2288 static int dissect_CPMSendNotifyOut(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2290 col_append_str(pinfo->cinfo, COL_INFO, "SendNotify");
2291 return tvb_length(tvb);
2294 static int dissect_CPMGetQueryStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2296 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatus");
2297 return tvb_length(tvb);
2300 static int dissect_CPMCiState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2302 col_append_str(pinfo->cinfo, COL_INFO, "CiState");
2303 return tvb_length(tvb);
2306 static int dissect_CPMFetchValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2308 col_append_str(pinfo->cinfo, COL_INFO, "FetchValue");
2309 return tvb_length(tvb);
2312 static int dissect_CPMGetQueryStatusEx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2314 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatusEx");
2315 return tvb_length(tvb);
2318 static int dissect_CPMRestartPosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2320 col_append_str(pinfo->cinfo, COL_INFO, "RestartPosition");
2321 return tvb_length(tvb);
2324 static int dissect_CPMSetCatState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2326 col_append_str(pinfo->cinfo, COL_INFO, "SetCatState");
2327 return tvb_length(tvb);
2330 static int dissect_CPMGetRowsetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2332 col_append_str(pinfo->cinfo, COL_INFO, "GetRowsetNotify");
2333 return tvb_length(tvb);
2336 static int dissect_CPMFindIndices(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2338 col_append_str(pinfo->cinfo, COL_INFO, "FindIndices");
2339 return tvb_length(tvb);
2342 static int dissect_CPMSetScopePrioritization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2344 col_append_str(pinfo->cinfo, COL_INFO, "SetScopePrioritization");
2345 return tvb_length(tvb);
2348 static int dissect_CPMGetScopeStatistics(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2350 col_append_str(pinfo->cinfo, COL_INFO, "GetScopeStatistics");
2351 return tvb_length(tvb);
2354 static void debug_frame(int frame)
2356 static const char *dbg_wait = NULL;
2357 static int wait_frame = -1;
2359 if (dbg_wait == NULL) {
2360 dbg_wait = getenv("DBG_FRAME");
2361 if (dbg_wait == NULL) {
2362 dbg_wait = "no";
2363 } else {
2364 wait_frame = atoi(dbg_wait);
2368 if (frame == wait_frame) {
2369 static volatile gboolean wait = 1;
2370 fprintf(stderr, "waiting for debugger with pid: %u\n", getpid());
2371 while(wait) {
2372 sleep(1);
2379 dissect_mswsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean in)
2381 proto_tree *mswsp_tree = NULL;
2382 struct {
2383 guint32 msg;
2384 guint32 status;
2385 guint32 checksum;
2386 guint32 reserved;
2387 } hdr;
2388 int (*fn)(tvbuff_t*, packet_info*, proto_tree*, gboolean);
2390 if (tvb_length(tvb) < 16) {
2391 return 0;
2394 hdr.msg = tvb_get_letohl(tvb, 0);
2396 switch(hdr.msg) {
2397 case 0xC8:
2398 fn = dissect_CPMConnect;
2399 break;
2400 case 0xC9:
2401 fn = dissect_CPMDisconnect;
2402 break;
2403 case 0xCA:
2404 fn = dissect_CPMCreateQuery;
2405 break;
2406 case 0xCB:
2407 fn = dissect_CPMFreeCursor;
2408 break;
2409 case 0xCC:
2410 fn = dissect_CPMGetRows;
2411 break;
2412 case 0xCD:
2413 fn = dissect_CPMRatioFinished;
2414 break;
2415 case 0xCE:
2416 fn = dissect_CPMCompareBmk;
2417 break;
2418 case 0xCF:
2419 fn = dissect_CPMGetApproximatePosition;
2420 break;
2421 case 0xD0:
2422 fn = dissect_CPMSetBindings;
2423 break;
2424 case 0xD1:
2425 fn = dissect_CPMGetNotify;
2426 break;
2427 case 0xD2:
2428 fn = dissect_CPMSendNotifyOut;
2429 break;
2430 case 0xD7:
2431 fn = dissect_CPMGetQueryStatus;
2432 break;
2433 case 0xD9:
2434 fn = dissect_CPMCiState;
2435 break;
2436 case 0xE4:
2437 fn = dissect_CPMFetchValue;
2438 break;
2439 case 0xE7:
2440 fn = dissect_CPMGetQueryStatusEx;
2441 break;
2442 case 0xE8:
2443 fn = dissect_CPMRestartPosition;
2444 break;
2445 case 0xEC:
2446 fn = dissect_CPMSetCatState;
2447 break;
2448 case 0xF1:
2449 fn = dissect_CPMGetRowsetNotify;
2450 break;
2451 case 0xF2:
2452 fn = dissect_CPMFindIndices;
2453 break;
2454 case 0xF3:
2455 fn = dissect_CPMSetScopePrioritization;
2456 break;
2457 case 0xF4:
2458 fn = dissect_CPMGetScopeStatistics;
2459 break;
2460 default:
2461 return 0;
2464 hdr.status = tvb_get_letohl(tvb, 4);
2465 hdr.checksum = tvb_get_letohl(tvb, 8);
2467 /* col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS-WSP"); */
2468 col_append_str(pinfo->cinfo, COL_PROTOCOL, " WSP");
2469 /* col_clear(pinfo->cinfo, COL_INFO); */
2471 col_set_str(pinfo->cinfo, COL_INFO, "WSP ");
2472 col_append_str(pinfo->cinfo, COL_INFO, in ? "Request: " : "Response: ");
2474 if (tree) {
2475 proto_tree *hdr_tree;
2476 proto_item *ti, *hti;
2478 ti = proto_tree_add_item(tree, proto_mswsp, tvb, 0, -1, ENC_NA);
2479 mswsp_tree = proto_item_add_subtree(ti, ett_mswsp);
2481 hti = proto_tree_add_item(mswsp_tree, hf_mswsp_hdr, tvb, 0, 16, ENC_NA);
2482 hdr_tree = proto_item_add_subtree(hti, ett_mswsp_hdr);
2484 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_msg, tvb,
2485 0, 4, ENC_LITTLE_ENDIAN);
2486 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_status,
2487 tvb, 4, 4, ENC_LITTLE_ENDIAN);
2488 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_checksum,
2489 tvb, 8, 4, ENC_LITTLE_ENDIAN);
2490 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_reserved, tvb,
2491 12, 4, ENC_LITTLE_ENDIAN);
2494 fn(tvb, pinfo, mswsp_tree, in);
2496 /* Return the amount of data this dissector was able to dissect */
2497 return tvb_length(tvb);
2501 /* Register the protocol with Wireshark */
2503 /* this format is require because a script is used to build the C function
2504 that calls all the protocol registration.
2507 void
2508 proto_register_mswsp(void)
2510 module_t *mswsp_module;
2512 /* Setup list of header fields See Section 1.6.1 for details*/
2513 static const value_string msg_ids[] = {
2514 {0x000000C8, "CPMConnect"}, /* In/Out */
2515 {0x000000C9, "CPMDisconnect"},
2516 {0x000000CA, "CPMCreateQuery"}, /* In/Out */
2517 {0x000000CB, "CPMFreeCursor"}, /* In/Out */
2518 {0x000000CC, "CPMGetRows"}, /* In/Out */
2519 {0x000000CD, "CPMRatioFinished"}, /* In/Out */
2520 {0x000000CE, "CPMCompareBmk"}, /* In/Out */
2521 {0x000000CF, "CPMGetApproximatePosition"}, /* In/Out */
2522 {0x000000D0, "CPMSetBindingsIn"},
2523 {0x000000D1, "CPMGetNotify"},
2524 {0x000000D2, "CPMSendNotifyOut"},
2525 {0x000000D7, "CPMGetQueryStatusIn"}, /* In/Out */
2526 {0x000000D9, "CPMCiStateInOut"},
2527 {0x000000E4, "CPMFetchValue"}, /* In/Out */
2528 {0x000000E7, "CPMGetQueryStatusEx"}, /* In/Out */
2529 {0x000000E8, "CPMRestartPositionIn"},
2530 {0x000000EC, "CPMSetCatStateIn"}, /* (not supported) */
2531 {0x000000F1, "CPMGetRowsetNotify"}, /* In/Out */
2532 {0x000000F2, "CPMFindIndices"}, /* In/Out */
2533 {0x000000F3, "CPMSetScopePrioritization"}, /* In/Out */
2534 {0x000000F4, "CPMGetScopeStatistics"}, /* In/Out */
2536 static hf_register_info hf[] = {
2537 { &hf_mswsp_hdr,
2538 { "Header", "mswsp.hdr",
2539 FT_NONE, BASE_NONE , NULL, 0,
2540 "Message header", HFILL }
2542 { &hf_mswsp_hdr_msg,
2543 { "Msg id", "mswsp.hdr.id",
2544 FT_UINT32, BASE_HEX , VALS(msg_ids), 0,
2545 "Message id", HFILL }
2547 { &hf_mswsp_hdr_status,
2548 { "Status", "mswsp.hdr.status",
2549 FT_UINT32, BASE_HEX , NULL, 0,
2550 "Status", HFILL }
2552 { &hf_mswsp_hdr_checksum,
2553 { "checksum", "mswsp.hdr.checksum",
2554 FT_UINT32, BASE_HEX , NULL, 0,
2555 "Checksum", HFILL }
2557 { &hf_mswsp_hdr_reserved,
2558 { "Reserved", "mswsp.hdr.reserved",
2559 FT_UINT32, BASE_HEX , NULL, 0,
2560 "Reserved", HFILL }
2562 { &hf_mswsp_msg,
2563 { "msg", "mswsp.msg",
2564 FT_NONE, BASE_NONE , NULL, 0,
2565 "Message", HFILL }
2567 { &hf_mswsp_msg_Connect_Version,
2568 { "Version", "mswsp.Connect.version",
2569 FT_UINT32, BASE_HEX , NULL, 0,
2570 "Version",HFILL }
2572 { &hf_mswsp_msg_ConnectIn_ClientIsRemote,
2573 { "Remote", "mswsp.ConnectIn.isRemote",
2574 FT_BOOLEAN, BASE_HEX , NULL, 0,
2575 "Client is remote",HFILL }
2577 { &hf_mswsp_msg_ConnectIn_Blob1,
2578 { "Size", "mswsp.ConnectIn.propset.size",
2579 FT_UINT32, BASE_DEC , NULL, 0,
2580 "Size of PropSet fields",HFILL }
2582 { &hf_mswsp_msg_ConnectIn_Blob2,
2583 { "Size", "mswsp.ConnectIn.extpropset.size",
2584 FT_UINT32, BASE_DEC , NULL, 0,
2585 "Size of ExtPropSet fields",HFILL }
2587 { &hf_mswsp_msg_ConnectIn_MachineName,
2588 { "Remote machine", "mswsp.ConnectIn.machine",
2589 FT_STRINGZ, BASE_NONE , NULL, 0,
2590 "Name of remote machine",HFILL }
2592 { &hf_mswsp_msg_ConnectIn_UserName,
2593 { "User", "mswsp.ConnectIn.user",
2594 FT_STRINGZ, BASE_NONE , NULL, 0,
2595 "Name of remote user",HFILL }
2597 { &hf_mswsp_msg_ConnectIn_PropSets_num,
2598 { "Num", "mswsp.ConnectIn.propset.num",
2599 FT_UINT32, BASE_DEC , NULL, 0,
2600 "Number of Property Sets", HFILL }
2602 { &hf_mswsp_msg_ConnectIn_ExtPropSets_num,
2603 { "Num", "mswsp.ConnectIn.extpropset.num",
2604 FT_UINT32, BASE_DEC , NULL, 0,
2605 "Number of extended Property Sets", HFILL }
2610 /* Setup protocol subtree array */
2611 static gint *ett[] = {
2612 &ett_mswsp,
2613 &ett_mswsp_hdr,
2614 &ett_mswsp_msg,
2615 &ett_mswsp_pad,
2616 &ett_mswsp_property_restriction,
2617 &ett_CRestrictionArray,
2618 &ett_CBaseStorageVariant,
2619 &ett_CBaseStorageVariant_Vector,
2620 &ett_CBaseStorageVariant_Array,
2621 &ett_CDbColId,
2622 &ett_GUID,
2623 &ett_CDbProp,
2624 &ett_CDbPropSet,
2625 &ett_CDbPropSet_Array,
2626 &ett_CRestriction,
2627 &ett_CNodeRestriction,
2628 &ett_CPropertyRestriction,
2629 &ett_CCoercionRestriction,
2630 &ett_CContentRestriction,
2631 &ett_RANGEBOUNDARY,
2632 &ett_CRangeCategSpec,
2633 &ett_CCategSpec,
2634 &ett_CAggregSpec,
2635 &ett_CAggregSet,
2636 &ett_CCategorizationSpec,
2637 &ett_CAggregSortKey,
2638 &ett_CSortAggregSet,
2639 &ett_CInGroupSortAggregSet,
2640 &ett_CInGroupSortAggregSets,
2641 &ett_CRowsetProperties,
2642 &ett_CFullPropSpec,
2643 &ett_CPidMapper,
2644 &ett_CSort,
2645 &ett_CSortSet,
2646 &ett_CNatLanguageRestriction,
2649 int i;
2651 /* Register the protocol name and description */
2652 proto_mswsp = proto_register_protocol("Windows Search Protocol",
2653 "MS-WSP", "mswsp");
2655 /* Required function calls to register the header fields and subtrees used */
2656 proto_register_field_array(proto_mswsp, hf, array_length(hf));
2657 proto_register_subtree_array(ett, array_length(ett));
2659 for (i=0; i<(int)array_length(GuidPropertySet); i++) {
2660 guids_add_guid(&GuidPropertySet[i].guid, GuidPropertySet[i].def);
2664 /* Register preferences module (See Section 2.6 for more on preferences) */
2665 /* (Registration of a prefs callback is not required if there are no */
2666 /* prefs-dependent registration functions (eg: a port pref). */
2667 /* See proto_reg_handoff below. */
2668 /* If a prefs callback is not needed, use NULL instead of */
2669 /* proto_reg_handoff_mswsp in the following). */
2670 mswsp_module = prefs_register_protocol(proto_mswsp,
2671 proto_reg_handoff_mswsp);
2673 /* Register preferences module under preferences subtree.
2674 Use this function instead of prefs_register_protocol if you want to group
2675 preferences of several protocols under one preferences subtree.
2676 Argument subtree identifies grouping tree node name, several subnodes can be
2677 specified using slash '/' (e.g. "OSI/X.500" - protocol preferences will be
2678 accessible under Protocols->OSI->X.500-><PROTOSHORTNAME> preferences node.
2680 /* mswsp_module = prefs_register_protocol_subtree(subtree, */
2681 /* proto_mswsp, proto_reg_handoff_mswsp); */
2683 /* Register a sample preference */
2684 prefs_register_bool_preference(mswsp_module, "show_hex",
2685 "Display numbers in Hex",
2686 "Enable to display numerical values in hexadecimal.",
2687 &gPREF_HEX);
2689 /* Register a sample port preference */
2690 prefs_register_uint_preference(mswsp_module, "tcp.port", "mswsp TCP Port",
2691 " mswsp TCP port if other than the default",
2692 10, &gPORT_PREF);
2695 static int dissect_mswsp_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2696 smb_info_t *si = pinfo->private_data;
2697 gboolean in = si->request;
2699 smb_transact_info_t *tri = (si->sip->extra_info_type == SMB_EI_TRI) ? si->sip->extra_info : NULL;
2700 smb_fid_info_t *fid_info = NULL;
2701 GSList *iter;
2703 debug_frame((int)pinfo->fd->num);
2705 fprintf(stderr, "dissect_mswsp_smb %s frame: %d tid: %d op: %02x ",
2706 in ? "Request" : "Response",
2707 pinfo->fd->num, si->tid, si->cmd);
2709 if (tri == NULL) {
2710 fprintf(stderr, " extra_info_type: %d\n", si->sip->extra_info_type);
2711 return 0;
2714 for (iter = si->ct->GSL_fid_info; iter; iter = g_slist_next(iter)) {
2715 smb_fid_info_t *info = iter->data;
2716 if ((info->tid == si->tid) && (info->fid == tri->fid)) {
2717 fid_info = info;
2718 break;
2722 if (!fid_info || !fid_info->fsi || !fid_info->fsi->filename) {
2723 fprintf(stderr, " no %s\n", fid_info ? (fid_info->fsi ? "filename" : "fsi") : "fid_info");
2724 return 0;
2727 fprintf(stderr, " file: %s\n", fid_info->fsi->filename);
2729 if (strcasecmp(fid_info->fsi->filename, "\\MsFteWds") != 0) {
2730 return 0;
2733 return dissect_mswsp(tvb, pinfo, tree, in);
2737 static int dissect_mswsp_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2738 smb2_info_t *si = pinfo->private_data;
2739 gboolean in = !(si->flags & SMB2_FLAGS_RESPONSE);
2741 //si->tree->share_type == SMB2_SHARE_TYPE_PIPE
2742 //si->tree->connect_frame
2744 debug_frame((int)pinfo->fd->num);
2746 fprintf(stderr, "dissect_mswsp %d <> %d : op %02x %s %s type: %d extra_file: %s\n",
2747 pinfo->fd->num, si->tree ? (int)si->tree->connect_frame : -1,
2748 si->opcode,
2749 pinfo->dcerpc_procedure_name ? pinfo->dcerpc_procedure_name : "<NULL>",
2750 in ? "Request" : "Response", si->tree ? si->tree->share_type : -1,
2751 si->saved ? (si->saved->extra_info_type == SMB2_EI_FILENAME ? (char*)si->saved->extra_info : "<OTHER>") : "<NONE>"
2755 if (strcmp(pinfo->dcerpc_procedure_name, "File: MsFteWds") != 0) {
2756 return 0;
2759 return dissect_mswsp(tvb, pinfo, tree, in);
2764 /* If this dissector uses sub-dissector registration add a registration routine.
2765 This exact format is required because a script is used to find these
2766 routines and create the code that calls these routines.
2768 If this function is registered as a prefs callback (see prefs_register_protocol
2769 above) this function is also called by preferences whenever "Apply" is pressed;
2770 In that case, it should accommodate being called more than once.
2772 Simple form of proto_reg_handoff_mswsp which can be used if there are
2773 no prefs-dependent registration function calls.
2776 void
2777 proto_reg_handoff_mswsp(void)
2779 heur_dissector_add("smb_transact", dissect_mswsp_smb, proto_mswsp);
2780 heur_dissector_add("smb2_heur_subdissectors", dissect_mswsp_smb2, proto_mswsp);
2785 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2787 * Local variables:
2788 * c-basic-offset: 4
2789 * tab-width: 8
2790 * indent-tabs-mode: nil
2791 * End:
2793 * vi: set shiftwidth=4 tabstop=8 expandtab:
2794 * :indentSize=4:tabSize=8:noTabs=true: