fix for new tvb_get_unicode_string() interface using wmem
[wireshark-wip.git] / epan / dissectors / packet-mswsp.c
blobb61327cd17aa664aef55118c4eb50ef81ffff00c
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;
121 static gint ett_CColumnGroup = -1;
122 static gint ett_CColumnGroupArray = -1;
123 static gint ett_LCID = -1;
124 static gint ett_CTableColumn = -1;
126 /******************************************************************************/
127 struct GuidPropertySet {
128 e_guid_t guid;
129 const char *def;
130 const char *desc;
131 const value_string *id_map;
134 /* 2.2.1.31.1 */
135 static const value_string DBPROPSET_FSCIFRMWRK_EXT_IDS[] = {
136 {0x02, "DBPROP_CI_CATALOG_NAME"},
137 {0x03, "DBPROP_CI_INCLUDE_SCOPES"},
138 {0x04, "DBPROP_CI_SCOPE_FLAGS"},
139 {0x07, "DBPROP_CI_QUERY_TYPE"},
140 {0, NULL}
143 static const value_string DBPROPSET_QUERYEXT_IDS[] = {
144 {0x02, "DBPROP_USECONTENTINDEX"},
145 {0x03, "DBPROP_DEFERNONINDEXEDTRIMMING"},
146 {0x04, "DBPROP_USEEXTENDEDDBTYPES"},
147 {0x05, "DBPROP_IGNORENOISEONLYCLAUSES"},
148 {0x06, "DBPROP_GENERICOPTIONS_STRING"},
149 {0x07, "DBPROP_FIRSTROWS"},
150 {0x08, "DBPROP_DEFERCATALOGVERIFICATION"},
151 {0x0a, "DBPROP_GENERATEPARSETREE"},
152 {0x0c, "DBPROP_FREETEXTANYTERM"},
153 {0x0d, "DBPROP_FREETEXTUSESTEMMING"},
154 {0x0e, "DBPROP_IGNORESBRI"},
155 {0x10, "DBPROP_ENABLEROWSETEVENTS"},
156 {0, NULL}
159 static const value_string DBPROPSET_CIFRMWRKCORE_EXT_IDS[] = {
160 {0x02, "DBPROP_MACHINE"},
161 {0x03, "DBPROP_CLIENT_CLSID"},
162 {0, NULL}
165 static const value_string DBPROPSET_MSIDXS_ROWSETEXT_IDS[] = {
166 {0x02, "MSIDXSPROP_ROWSETQUERYSTATUS"},
167 {0x03, "MSIDXSPROP_COMMAND_LOCALE_STRING"},
168 {0x04, "MSIDXSPROP_QUERY_RESTRICTION"},
169 {0x05, "MSIDXSPROP_PARSE_TREE"},
170 {0x06, "MSIDXSPROP_MAX_RANK"},
171 {0x07, "MSIDXSPROP_RESULTS_FOUND"},
172 {0, NULL}
175 /* 2.2.5.1 */
176 static const value_string QueryGuid_IDS[] = {
177 {0x02, "RankVector"},
178 {0x03, "System.Search.Rank"},
179 {0x04, "System.Search.HitCount"},
180 {0x05, "System.Search.EntryID"},
181 {0x06, "All"},
182 {0x09, "System.ItemURL"},
183 {0, NULL}
186 /* 2.2.5.2 */
187 static const value_string StorageGuid_IDS[] = {
188 {0x02, "System.ItemFolderNameDisplay"},
189 {0x03, "ClassId"},
190 {0x04, "System.ItemTypeText"},
191 {0x08, "FileIndex"},
192 {0x09, "USN"},
193 {0x0a, "System.ItemNameDisplay"},
194 {0x0b, "Path"},
195 {0x0c, "System.Size"},
196 {0x0d, "System.FileAttributes"},
197 {0x0e, "System.DateModified"},
198 {0x0f, "System.DateCreated"},
199 {0x10, "System.DateAccessed"},
200 {0x12, "AllocSize"},
201 {0x13, "System.Search.Contents"},
202 {0x14, "ShortFilename"},
203 {0x15, "FileFRN"},
204 {0x16, "Scope"},
205 {0, NULL}
208 static const value_string DocPropSetGuid_IDS[] = {
209 {0x02, "System.Title"},
210 {0x03, "System.Subject"},
211 {0x04, "System.Author"},
212 {0x05, "System.Keywords"},
213 {0x06, "System.Comment"},
214 {0x07, "DocTemplate"},
215 {0x08, "System.Document.LastAuthor"},
216 {0x09, "System.Document.RevisionNumber"},
217 {0x0a, "System.Document.EditTime???"},
218 {0x0b, "System.Document.DatePrinted"},
219 {0x0c, "System.Document.DateCreated"},
220 {0x0d, "System.Document.DateSaved"},
221 {0x0e, "System.Document.PageCount"},
222 {0x0f, "System.Document.WordCount"},
223 {0x10, "System.Document.CharacterCount"},
224 {0x11, "DocThumbnail"},
225 {0x12, "System.ApplicationName"},
226 {0, NULL}
229 static const value_string ShellDetails_IDS[] = {
230 { 5, "System.ComputerName"},
231 { 8, "System.ItemPathDisplayNarrow"},
232 { 9, "PercivedType"},
233 {11, "System.ItemType"},
234 {12, "FileCount"},
235 {14, "TotalFileSize"},
236 {24, "System.ParsingName"},
237 {25, "System.SFGAOFlags"},
238 {0, NULL}
241 static const value_string PropSet1_IDS[] = {
242 {100, "System.ThumbnailCacheId"},
243 {0, NULL}
246 static const value_string PropSet2_IDS[] = {
247 {3, "System.Kind"},
248 {0, NULL}
251 static const value_string MusicGuid_IDS[] = {
252 {0, NULL}
255 static const value_string PropSet3_IDS[] = {
256 { 2, "System.Message.BccAddress"},
257 { 3, "System.Message.BccName"},
258 { 4, "System.Message.CcAddress"},
259 { 5, "System.Message.CcName"},
260 { 6, "System.ItemFolderPathDisplay"},
261 { 7, "System.ItemPathDisplay"},
262 { 9, "System.Communication.AccountName"},
263 {10, "System.IsRead"},
264 {11, "System.Importance"},
265 {12, "System.FlagStatus"},
266 {13, "System.Message.FromAddress"},
267 {14, "System.Message.FromName"},
268 {15, "System.Message.Store"},
269 {16, "System.Message.ToAddress"},
270 {17, "System.Message.ToName"},
271 {18, "System.Contact.WebPage"},
272 {19, "System.Message.DateSent"},
273 {20, "System.Message.DateReceived"},
274 {21, "System.Message.AttachmentNames"},
275 {0, NULL}
278 static const value_string PropSet4_IDS[] = {
279 {100, "System.ItemFolderPathDisplayNarrow"},
280 {0, NULL}
283 static const value_string PropSet5_IDS[] = {
284 {100, "System.Contact.FullName"},
285 {0, NULL}
288 static const value_string PropSet6_IDS[] = {
289 {100, "System.ItemAuthors"},
290 {0, NULL}
293 static const value_string PropSet7_IDS[] = {
294 {2, "System.Shell.OmitFromView"},
295 {0, NULL}
298 static const value_string PropSet8_IDS[] = {
299 {2, "System.Shell.SFGAOFlagsStrings"},
300 {3, "System.Link.TargetSFGAOFlagsStrings"},
301 {0, NULL}
304 static const value_string PropSet9_IDS[] = {
305 {100, "System.ItemDate"},
306 {0, NULL}
309 static const value_string PropSet10_IDS[] = {
310 { 5, "System.MIMEType"},
311 { 8, "System.Search.GatherTime"},
312 { 9, "System.Search.AccessCount"},
313 {11, "System.Search.LastIndexedTotalTime"},
314 {0, NULL}
317 static const value_string PropSet11_IDS[] = {
318 {5, "System.Priority"},
319 {8, "System.Messagee.HasAttachments"},
320 {0, NULL}
323 static const value_string DocCharacter_IDS[] = {
324 {2, "System.Search.Autosummary"},
325 {0, NULL}
328 static const value_string PropSet12_IDS[] = {
329 {100, "System.IsDeleted"},
330 {0, NULL}
333 static const value_string PropSet13_IDS[] = {
334 {100, "System.IsAttachment"},
335 {0, NULL}
338 static const value_string PropSet14_IDS[] = {
339 {100, "System.Message.ConversationID"},
340 {101, "System.Message.ConversationIndex"},
341 {0, NULL}
344 static const value_string DocPropSetGuid2_IDS[] = {
345 {0x02, "System.Category"},
346 {0x03, "System.Document.PresentationFormat"},
347 {0x04, "System.Document.ByteCount"},
348 {0x05, "System.Document.LineCount"},
349 {0x06, "System.Document.ParagraphCount"},
350 {0x07, "System.Document.SlideCount"},
351 {0x08, "DocNoteCount"},
352 {0x09, "System.Document.HiddenSlideCount"},
353 {0x0D, "DocPartTitles"},
354 {0x0E, "System.Document.Manager"},
355 {0x0F, "System.Company"},
356 {0, NULL}
359 static const value_string SystemContact_IDS[] = {
360 { 6, "System.Contact.JobTitle"},
361 { 7, "System.Contact.OfficeLocation"},
362 {20, "System.Contact.HomeTelephone"},
363 {25, "System.Contact.PrimaryTelephone"},
364 {35, "System.Contact.MobileTelephone"},
365 {47, "System.Contact.Birthday"},
366 {48, "System.Contact.PrimaryEmailAddress"},
367 {65, "System.Contact.HomeAddressCity"},
368 {69, "System.Contact.PersonalTitle"},
369 {71, "System.Contact.MiddleName"},
370 {73, "System.Contact.Suffix"},
371 {74, "System.Contact.NickName"},
372 {0, NULL}
375 static struct GuidPropertySet GuidPropertySet[] = {
376 {{0xa9bd1526, 0x6a80, 0x11d0, {0x8c, 0x9d, 0x00, 0x20, 0xaf, 0x1d, 0x74, 0x0e}},
377 "DBPROPSET_FSCIFRMWRK_EXT", "File system content index framework",
378 DBPROPSET_FSCIFRMWRK_EXT_IDS},
379 {{0xa7ac77ed, 0xf8d7, 0x11ce, {0xa7, 0x98, 0x00, 0x20, 0xf8, 0x00, 0x80, 0x25}},
380 "DBPROPSET_QUERYEXT", "Query extension",
381 DBPROPSET_QUERYEXT_IDS},
382 {{0xafafaca5, 0xb5d1, 0x11d0, {0x8c, 0x62, 0x00, 0xc0, 0x4f, 0xc2, 0xdb, 0x8d}},
383 "DBPROPSET_CIFRMWRKCORE_EXT", "Content index framework core",
384 DBPROPSET_CIFRMWRKCORE_EXT_IDS},
385 {{0xAA6EE6B0, 0xE828, 0x11D0, {0xB2, 0x3E, 0x00, 0xAA, 0x00, 0x47, 0xFC, 0x01}},
386 "DBPROPSET_MSIDXS_ROWSETEXT", "???",
387 DBPROPSET_MSIDXS_ROWSETEXT_IDS},
388 {{0xB725F130, 0x47ef, 0x101a, {0xA5, 0xF1, 0x02, 0x60, 0x8C, 0x9E, 0xEB, 0xAC}},
389 "Storage", "Storage Property Set",
390 StorageGuid_IDS},
391 {{0xF29F85E0, 0x4FF9, 0x1068, {0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9}},
392 "Document", "Document Property Set",
393 DocPropSetGuid_IDS},
394 {{0x49691C90, 0x7E17, 0x101A, {0xA9, 0x1C, 0x08, 0x00, 0x2B, 0x2E, 0xCD, 0xA9}},
395 "Query", "Query Property Set",
396 QueryGuid_IDS},
397 {{0x28636AA6, 0x953D, 0x11D2, {0xB5, 0xD6, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xD0}},
398 "ShellDetails", "Shell Details Property Set",
399 ShellDetails_IDS},
400 {{0x446D16B1, 0x8DAD, 0x4870, {0xA7, 0x48, 0x40, 0x2E, 0xA4, 0x3D, 0x78, 0x8C}},
401 "???", "Unspecified Property Set",
402 PropSet1_IDS},
403 {{0x1E3EE840, 0xBC2B, 0x476C, {0x82, 0x37, 0x2A, 0xCD, 0x1A, 0x83, 0x9B, 0x22}},
404 "???", "Unspecified Property Set",
405 PropSet2_IDS},
406 {{0x56A3372E, 0xCE9C, 0x11d2, {0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6}},
407 "Music", "Music Property Set",
408 MusicGuid_IDS},
409 {{0xE3E0584C, 0xB788, 0x4A5A, {0xBB, 0x20, 0x7F, 0x5A, 0x44, 0xC9, 0xAC, 0xDD}},
410 "???", "Unspecified Property Set",
411 PropSet3_IDS},
412 {{0xDABD30ED, 0x0043, 0x4789, {0xA7, 0xF8, 0xD0, 0x13, 0xA4, 0x73, 0x66, 0x22}},
413 "???", "Unspecified Property Set",
414 PropSet4_IDS},
415 {{0x635E9051, 0x50A5, 0x4BA2, {0xB9, 0xDB, 0x4E, 0xD0, 0x56, 0xC7, 0x72, 0x96}},
416 "???", "Unspecified Property Set",
417 PropSet5_IDS},
418 {{0xD0A04F0A, 0x462A, 0x48A4, {0xBB, 0x2F, 0x37, 0x06, 0xE8, 0x8D, 0xBD, 0x7D}},
419 "???", "Unspecified Property Set",
420 PropSet6_IDS},
421 {{0xDE35258C, 0xC695, 0x4CBC, {0xB9, 0x82, 0x38, 0xB0, 0xAD, 0x24, 0xCE, 0xD0}},
422 "???", "Unspecified Property Set",
423 PropSet7_IDS},
424 {{0xD6942081, 0xD53B, 0x443D, {0xAD, 0x47, 0x5E, 0x05, 0x9D, 0x9C, 0xD2, 0x7A}},
425 "???", "Unspecified Property Set",
426 PropSet8_IDS},
427 {{0xF7DB74B4, 0x4287, 0x4103, {0xAF, 0xBA, 0xF1, 0xB1, 0x3D, 0xCD, 0x75, 0xCF}},
428 "???", "Unspecified Property Set",
429 PropSet9_IDS},
430 {{0x0B63E350, 0x9CCC, 0x11d0, {0xBC, 0xDB, 0x00, 0x80, 0x5F, 0xCC, 0xCE, 0x04}},
431 "???", "Unspecified Property Set",
432 PropSet10_IDS},
433 {{0x9C1FCF74, 0x2D97, 0x41BA, {0xB4, 0xAE, 0xCB, 0x2E, 0x36, 0x61, 0xA6, 0xE4}},
434 "???", "Unspecified Property Set",
435 PropSet11_IDS},
436 {{0x560C36C0, 0x503A, 0x11CF, {0xBA, 0xA1, 0x00, 0x00, 0x4C, 0x75, 0x2A, 0x9A}},
437 "DocCharacter", "Document characterization Property Set",
438 DocCharacter_IDS},
439 {{0x5CDA5FC8, 0x33EE, 0x4FF3, {0x90, 0x94, 0xAE, 0x7B, 0xD8, 0x86, 0x8C, 0x4D}},
440 "???", "Unspecified Property Set",
441 PropSet12_IDS},
442 {{0xF23F425C, 0x71A1, 0x4FA8, {0x92, 0x2F, 0x67, 0x8E, 0xA4, 0xA6, 0x04, 0x08}},
443 "???", "Unspecified Property Set",
444 PropSet13_IDS},
445 {{0xDC8F80BD, 0xAF1E, 0x4289, {0x85, 0xB6, 0x3D, 0xFC, 0x1B, 0x49, 0x39, 0x92}},
446 "???", "Unspecified Property Set",
447 PropSet14_IDS},
448 {{0xD5CDD502, 0x2E9C, 0x101B, {0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE}},
449 "DocPropSet2", "Document Property Set 2",
450 DocPropSetGuid2_IDS},
451 {{0x176DC63C, 0x2688, 0x4E89, {0x81, 0x43, 0xA3, 0x47, 0x80, 0x0F, 0x25, 0xE9}},
452 "System.Contact", "System Contact Property Set",
453 SystemContact_IDS},
456 static struct GuidPropertySet *GuidPropertySet_find_guid(const e_guid_t *guid)
458 unsigned i;
459 for (i=0; i<array_length(GuidPropertySet); i++) {
460 if (guid_cmp(&GuidPropertySet[i].guid, guid) == 0) {
461 return &GuidPropertySet[i];
464 return NULL;
467 /******************************************************************************/
469 static int parse_padding(tvbuff_t *tvb, int offset, int alignment, proto_tree *pad_tree, const char *fmt, ...)
471 if (offset % alignment) {
472 const int padding = alignment - (offset % alignment);
473 va_list ap;
474 proto_item *ti;
475 va_start(ap, fmt);
476 ti = proto_tree_add_text_valist(pad_tree, tvb, offset, padding, fmt, ap);
477 va_end(ap);
479 proto_item_append_text(ti, " (%d)", padding);
480 offset += padding;
482 DISSECTOR_ASSERT((offset % alignment) == 0);
483 return offset;
486 static int parse_guid(tvbuff_t *tvb, int offset, proto_tree *tree, e_guid_t *guid, const char *text)
488 const char *guid_str, *name, *bytes;
489 proto_tree *tr;
490 proto_item *ti;
492 tvb_get_letohguid(tvb, offset, guid);
493 guid_str = guid_to_str(guid);
494 name = guids_get_guid_name(guid);
496 ti = proto_tree_add_text(tree, tvb, offset, 16, "%s: %s {%s}", text, name ? name : "", guid_str);
497 tr = proto_item_add_subtree(ti, ett_GUID);
499 proto_tree_add_text(tr, tvb, offset, 4, "time-low: 0x%08x", guid->data1);
500 offset += 4;
501 proto_tree_add_text(tr, tvb, offset, 2, "time-mid: 0x%04x", guid->data2);
502 offset += 2;
503 proto_tree_add_text(tr, tvb, offset, 2, "time-high-and-version: 0x%04x", guid->data3);
504 offset += 2;
505 proto_tree_add_text(tr, tvb, offset, 1, "clock_seq_hi_and_reserved: 0x%02x", guid->data4[0]);
506 offset += 1;
507 proto_tree_add_text(tr, tvb, offset, 1, "clock_seq_low: 0x%02x", guid->data4[1]);
508 offset += 1;
509 bytes = bytestring_to_str(&guid->data4[2], 6, ':');
510 proto_tree_add_text(tr, tvb, offset, 6, "node: %s", bytes);
511 offset += 6;
513 return offset;
516 static const value_string LCID_LID[] = {
517 {0x0407, "de-DE"},
518 {0x0409, "en-US"},
519 {0, NULL}
523 /*Language Code ID: http://msdn.microsoft.com/en-us/library/cc233968(v=prot.20).aspx */
524 static int parse_lcid(tvbuff_t *tvb, int offset, proto_tree *parent_tree, const char *text)
526 proto_item *item;
527 proto_tree *tree;
528 guint32 lcid;
529 const char *langid;
531 item = proto_tree_add_text(parent_tree, tvb, offset, 4, "%s", text);
532 tree = proto_item_add_subtree(item, ett_LCID);
534 lcid = tvb_get_letohl(tvb, offset);
535 langid = val_to_str(lcid & 0xFFFF, LCID_LID, "0x%04x");
536 proto_tree_add_text(tree, tvb, offset+2, 2, "Language ID: %s", langid);
537 proto_item_append_text(item, ": %s", langid);
538 proto_tree_add_text(tree, tvb, offset+1,1, "Sort ID: %u", (lcid >> 16) & 0xf);
539 offset += 4;
540 return offset;
543 /*****************************************************************************************/
544 /* 2.2.1.1 CBaseStorageVariant */
545 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
546 struct CBaseStorageVariant *value, const char *text);
548 /* 2.2.1.2 CFullPropSpec */
549 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pad_tree,
550 struct CFullPropSpec *v, const char *fmt, ...);
552 /* 2.2.1.3 CContentRestriction */
553 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
554 proto_tree *pad_tree, struct CContentRestriction *v,
555 const char *fmt, ...);
557 /* 2.2.1.5 CNatLanguageRestriction */
558 static int parse_CNatLanguageRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
559 proto_tree *pad_tree, struct CNatLanguageRestriction *v,
560 const char *fmt, ...);
562 /* 2.2.1.6 CNodeRestriction */
563 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pad_tree,
564 struct CNodeRestriction *v, const char* fmt, ...);
566 /* 2.2.1.7 CPropertyRestriction */
567 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
568 proto_tree *pad_tree, struct CPropertyRestriction *v,
569 const char *fmt, ...);
571 /* 2.2.1.8 CReuseWhere */
572 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
573 proto_tree *pad_tree _U_, struct CReuseWhere *v,
574 const char *fmt, ...);
576 /* 2.2.1.10 CSort */
577 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
578 proto_tree *pad_tree _U_,
579 const char *fmt, ...);
581 /* 2.2.1.12 CCoercionRestriction */
582 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
583 proto_tree *pad_tree, struct CCoercionRestriction *v,
584 const char *fmt, ...);
585 /* 2.2.1.16 CRestrictionArray */
586 static int parse_CRestrictionArray(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
587 const char *fmt, ...);
589 /* 2.2.1.17 CRestriction */
590 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
591 struct CRestriction *v, const char *fmt, ...);
593 /* 2.2.1.18 CColumnSet */
594 static int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...);
596 /* 2.2.1.20 CCategorizationSpec */
597 static int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
598 proto_tree *parent_tree, proto_tree *pad_tree,
599 const char *fmt, ...);
601 /* 2.2.1.21 CCategSpec */
602 static int parse_CCategSpec(tvbuff_t *tvb, int offset,
603 proto_tree *parent_tree, proto_tree *pad_tree,
604 const char *fmt, ...);
606 /* 2.2.1.22 CRangeCategSpec */
607 static int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
608 proto_tree *parent_tree, proto_tree *pad_tree,
609 const char *fmt, ...);
611 /* 2.2.1.23 RANGEBOUNDARY */
612 static int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
613 proto_tree *pad_tree, const char *fmt, ...);
615 /* 2.2.1.24 CAggregSet */
616 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
617 proto_tree *parent_tree, proto_tree *pad_tree,
618 const char *fmt, ...);
620 /* 2.2.1.25 CAggregSpec */
621 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
622 proto_tree *parent_tree, proto_tree *pad_tree,
623 const char *fmt, ...);
625 /* 2.2.1.26 CSortAggregSet */
626 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
627 proto_tree *parent_tree, proto_tree *pad_tree,
628 const char *fmt, ...);
630 /* 2.2.1.27 CAggregSortKey */
631 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
632 proto_tree *parent_tree, proto_tree *pad_tree,
633 const char *fmt, ...);
635 /* 2.2.1.28 CInGroupSortAggregSets */
636 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
637 proto_tree *parent_tree, proto_tree *pad_tree,
638 const char *fmt, ...);
640 /* 2.2.1.29 CInGroupSortAggregSet */
641 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
642 proto_tree *parent_tree, proto_tree *pad_tree,
643 const char *fmt, ...);
644 /* 2.2.1.30 CDbColId */
645 static int parse_CDbColId(tvbuff_t *tvb, int offset,
646 proto_tree *parent_tree, proto_tree *pad_tree, const char *text);
648 /* 2.2.1.31 CDbProp */
649 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
650 proto_tree *pad_tree, struct GuidPropertySet *propset,
651 const char *fmt, ...);
653 /* 2.2.1.32 CDbPropSet */
654 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
655 proto_tree *pad_tree, const char *fmt, ...);
656 /* 2.2.1.33 CPidMapper */
657 static int parse_CPidMapper(tvbuff_t *tvb, int offset,
658 proto_tree *parent_tree, proto_tree *pad_tree,
659 const char *fmt, ...);
661 /* 2.2.1.34 CColumnGroupArray */
662 static int parse_CColumnGroupArray(tvbuff_t *tvb, int offset,
663 proto_tree *parent_tree, proto_tree *pad_tree,
664 const char *fmt, ...);
666 /* 2.2.1.35 CColumnGroup */
667 static int parse_CColumnGroup(tvbuff_t *tvb, int offset,
668 proto_tree *parent_tree, proto_tree *pad_tree,
669 const char *fmt, ...);
671 /* 2.2.1.41 CRowsetProperties */
672 static int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
673 proto_tree *parent_tree, proto_tree *pad_tree,
674 const char *fmt, ...);
676 /* 2.2.1.43 CSortSet */
677 static int parse_CSortSet(tvbuff_t *tvb, int offset,
678 proto_tree *parent_tree, proto_tree *pad_tree,
679 const char *fmt, ...);
681 /* 2.2.1.44 CTableColumn */
682 static int parse_CTableColumn(tvbuff_t *tvb, int offset,
683 proto_tree *parent_tree, proto_tree *pad_tree,
684 const char *fmt, ...);
688 2.2.1.4 CInternalPropertyRestriction
689 2.2.1.9 CScopeRestriction
690 2.2.1.11 CVectorRestriction
691 2.2.1.13 CRelDocRestriction
692 2.2.1.14 CProbRestriction
693 2.2.1.15 CFeedbackRestriction
694 2.2.1.19 CCategorizationSet
695 2.2.1.37 CRowSeekAt
696 2.2.1.38 CRowSeekAtRatio
697 2.2.1.39 CRowSeekByBookmark
698 2.2.1.40 CRowSeekNext
699 2.2.1.42 CRowVariant
700 2.2.1.45 SERIALIZEDPROPERTYVALUE
701 2.2.1.46 CCompletionCategSp
704 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
705 proto_tree *pad_tree _U_,
706 const char *fmt, ...)
708 guint32 col, ord, ind;
710 proto_item *item;
711 proto_tree *tree;
713 va_list ap;
715 va_start(ap, fmt);
716 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
717 va_end(ap);
718 tree = proto_item_add_subtree(item, ett_CSort);
720 col = tvb_get_letohl(tvb, offset);
721 proto_tree_add_text(tree, tvb, offset, 4, "column: %u", col);
722 offset += 4;
724 ord = tvb_get_letohl(tvb, offset);
725 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", ord);
726 offset += 4;
728 ind = tvb_get_letohl(tvb, offset);
729 proto_tree_add_text(tree, tvb, offset, 4, "individual: %u", ind);
730 offset += 4;
732 offset = parse_lcid(tvb, offset, tree, "lcid");
734 proto_item_set_end(item, tvb, offset);
735 return offset;
738 static int parse_CSortSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
739 proto_tree *pad_tree,
740 const char *fmt, ...)
742 guint32 count, i;
744 proto_item *item;
745 proto_tree *tree;
747 va_list ap;
749 va_start(ap, fmt);
750 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
751 va_end(ap);
752 tree = proto_item_add_subtree(item, ett_CSortSet);
754 count = tvb_get_letohl(tvb, offset);
755 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
756 offset += 4;
758 for (i=0; i<count; i++) {
759 offset = parse_padding(tvb, offset, 4, tree, "padding_sortArray[%u]", i);
760 offset = parse_CSort(tvb, offset, tree, pad_tree, "sortArray[%u]", i);
763 proto_item_set_end(item, tvb, offset);
764 return offset;
767 static int parse_CTableColumn(tvbuff_t *tvb, int offset,
768 proto_tree *parent_tree, proto_tree *pad_tree,
769 const char *fmt, ...)
771 proto_item *item;
772 proto_tree *tree;
773 va_list ap;
775 struct CFullPropSpec v;
776 guint8 used;
778 va_start(ap, fmt);
779 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
780 va_end(ap);
781 tree = proto_item_add_subtree(item, ett_CTableColumn);
783 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v, "PropSpec");
785 proto_tree_add_text(tree, tvb, offset, 4, "vType");
786 offset += 4;
788 proto_tree_add_text(tree, tvb, offset, 1, "AggreagateUsed");
789 offset += 1;
791 proto_tree_add_text(tree, tvb, offset, 1, "AggreagateType");
792 offset += 1;
794 used = tvb_get_guint8(tvb, offset);
795 proto_tree_add_text(tree, tvb, offset, 1, "ValueUsed");
796 offset += 1;
798 if (used) {
799 offset = parse_padding(tvb, offset, 2, pad_tree, "padding_Value");
801 proto_tree_add_text(tree, tvb, offset, 2, "ValueOffset");
802 offset += 2;
804 proto_tree_add_text(tree, tvb, offset, 2, "ValueSize");
805 offset += 2;
808 used = tvb_get_guint8(tvb, offset);
809 proto_tree_add_text(tree, tvb, offset, 1, "StatusUsed");
810 offset += 1;
812 if (used) {
813 offset = parse_padding(tvb, offset, 2, pad_tree, "padding_Status");
815 proto_tree_add_text(tree, tvb, offset, 2, "StatusOffset");
816 offset += 2;
819 used = tvb_get_guint8(tvb, offset);
820 proto_tree_add_text(tree, tvb, offset, 1, "LengthUsed");
821 offset += 1;
823 if (used) {
824 offset = parse_padding(tvb, offset, 2, pad_tree, "padding_Lenght");
826 proto_tree_add_text(tree, tvb, offset, 2, "LenghtOffset");
827 offset += 2;
830 proto_item_set_end(item, tvb, offset);
831 return offset;
835 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset,
836 proto_tree *parent_tree, proto_tree *pad_tree,
837 struct CFullPropSpec *v, const char *fmt, ...)
839 static const value_string KIND[] = {
840 {0, "PRSPEC_LPWSTR"},
841 {1, "PRSPEC_PROPID"},
842 {0, NULL}
845 struct GuidPropertySet *pset;
846 const char *id_str, *guid_str;
848 proto_item *item;
849 proto_tree *tree;
850 va_list ap;
852 va_start(ap, fmt);
853 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
854 va_end(ap);
855 tree = proto_item_add_subtree(item, ett_CFullPropSpec);
857 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingPropSet");
859 offset = parse_guid(tvb, offset, tree, &v->guid, "GUID");
860 pset = GuidPropertySet_find_guid(&v->guid);
862 v->kind = tvb_get_letohl(tvb, offset);
863 proto_tree_add_text(tree, tvb, offset, 4, "ulKind: %s ", val_to_str(v->kind, KIND, "(Unknown: 0x%x)"));
864 offset += 4;
866 v->u.propid = tvb_get_letohl(tvb, offset);
867 proto_tree_add_text(tree, tvb, offset, 4, "propid: %u ", v->u.propid);
868 offset += 4;
870 if (v->kind == PRSPEC_LPWSTR) {
871 int len = 2*v->u.propid;
872 v->u.name = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, len, ENC_LITTLE_ENDIAN);
873 proto_tree_add_text(tree, tvb, offset, len, "name: \"%s\"", v->u.name);
874 offset += len;
877 id_str = pset ? match_strval(v->u.propid, pset->id_map) : NULL;
879 if (id_str) {
880 proto_item_append_text(item, ": %s", id_str);
881 } else {
882 guid_str = guids_get_guid_name(&v->guid);
883 if (guid_str) {
884 proto_item_append_text(item, ": \"%s\"", guid_str);
885 } else {
886 guid_str = guid_to_str(&v->guid);
887 proto_item_append_text(item, ": {%s}", guid_str);
890 if (v->kind == PRSPEC_LPWSTR) {
891 proto_item_append_text(item, " \"%s\"", v->u.name);
892 } else if (v->kind == PRSPEC_PROPID) {
893 proto_item_append_text(item, " 0x%08x", v->u.propid);
894 } else {
895 proto_item_append_text(item, " <INVALID>");
899 proto_item_set_end(item, tvb, offset);
900 return offset;
905 static const value_string PR_VALS[] = {
906 {PRLT, "PRLT"},
907 {PRLE, "PRLE"},
908 {PRGT, "PRGT"},
909 {PRGE, "PRGE"},
910 {PREQ, "PREQ"},
911 {PRNE, "PRNE"},
912 {PRRE, "PRRE"},
913 {PRAllBits, "PRAllBits"},
914 {PRSomeBits, "PRSomeBits"},
915 {PRAll, "PRAll"},
916 {PRSome, "PRSome"},
920 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
921 proto_tree *pad_tree, struct CPropertyRestriction *v,
922 const char *fmt, ...)
924 proto_tree *tree;
925 proto_item *item;
926 const char *str;
927 va_list ap;
929 va_start(ap, fmt);
930 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
931 va_end(ap);
933 tree = proto_item_add_subtree(item, ett_CPropertyRestriction);
935 v->relop = tvb_get_letohl(tvb, offset);
936 str = val_to_str(v->relop, PR_VALS, "0x%04x");
937 proto_tree_add_text(tree, tvb, offset, 4, "relop: %s (0x%04x)",
938 str[0]=='\0' ? "" : str, v->relop);
939 proto_item_append_text(item, " Op: %s", str);
940 offset += 4;
942 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
944 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &v->prval, "prval");
946 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_lcid");
948 v->lcid = tvb_get_letohl(tvb, offset);
949 offset = parse_lcid(tvb, offset, tree, "lcid");
951 proto_item_set_end(item, tvb, offset);
953 return offset;
956 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
957 proto_tree *pad_tree, struct CCoercionRestriction *v,
958 const char *fmt, ...)
960 proto_tree *tree;
961 proto_item *item;
962 va_list ap;
964 va_start(ap, fmt);
965 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
966 va_end(ap);
968 tree = proto_item_add_subtree(item, ett_CCoercionRestriction);
970 v->value = tvb_get_letohl(tvb, offset);
971 proto_tree_add_text(tree, tvb, offset, 4, "value: %g", (double)v->value);
972 offset += 4;
974 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &v->child, "child");
976 proto_item_set_end(item, tvb, offset);
977 return offset;
980 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
981 proto_tree *pad_tree, struct CContentRestriction *v,
982 const char *fmt, ...)
984 proto_tree *tree;
985 proto_item *item;
986 va_list ap;
987 guint32 cc;
988 const char *str;
991 va_start(ap, fmt);
992 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
993 va_end(ap);
995 tree = proto_item_add_subtree(item, ett_CContentRestriction);
997 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
999 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding1");
1001 cc = tvb_get_letohl(tvb, offset);
1002 proto_tree_add_text(tree, tvb, offset, 4, "cc: %u", cc);
1003 offset += 4;
1005 // str = tvb_get_ephemeral_string_enc(tvb, offset, 2*cc, ENC_UTF_16);
1006 str = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, 2*cc, ENC_LITTLE_ENDIAN);
1007 v->phrase = se_strdup(str);
1008 proto_tree_add_text(tree, tvb, offset, 2*cc, "phrase: %s", str);
1009 offset += 2*cc;
1011 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding2");
1013 v->lcid = tvb_get_letohl(tvb, offset);
1014 offset = parse_lcid(tvb, offset, tree, "lcid");
1016 v->method = tvb_get_letohl(tvb, offset);
1017 proto_tree_add_text(tree, tvb, offset, 4, "method: 0x%08x", v->method);
1018 offset += 4;
1020 proto_item_set_end(item, tvb, offset);
1021 return offset;
1024 int parse_CNatLanguageRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1025 proto_tree *pad_tree, struct CNatLanguageRestriction *v,
1026 const char *fmt, ...)
1028 proto_tree *tree;
1029 proto_item *item;
1030 va_list ap;
1031 guint32 cc;
1032 const char *str;
1035 va_start(ap, fmt);
1036 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1037 va_end(ap);
1039 tree = proto_item_add_subtree(item, ett_CNatLanguageRestriction);
1041 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
1043 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_cc");
1045 cc = tvb_get_letohl(tvb, offset);
1046 proto_tree_add_text(tree, tvb, offset, 4, "cc: %u", cc);
1047 offset += 4;
1049 // str = tvb_get_ephemeral_string_enc(tvb, offset, 2*cc, ENC_UTF_16);
1050 str = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, 2*cc, ENC_LITTLE_ENDIAN);
1051 v->phrase = se_strdup(str);
1052 proto_tree_add_text(tree, tvb, offset, 2*cc, "phrase: %s", str);
1053 offset += 2*cc;
1055 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_lcid");
1057 v->lcid = tvb_get_letohl(tvb, offset);
1058 offset = parse_lcid(tvb, offset, tree, "lcid");
1060 proto_item_set_end(item, tvb, offset);
1061 return offset;
1065 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1066 proto_tree *pad_tree _U_, struct CReuseWhere *v,
1067 const char *fmt, ...)
1069 proto_item *item;
1070 va_list ap;
1073 va_start(ap, fmt);
1074 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1075 va_end(ap);
1077 v->whereId = tvb_get_letohl(tvb, offset);
1078 offset += 4;
1080 proto_item_append_text(item, " Id: %u", v->whereId);
1082 proto_item_set_end(item, tvb, offset);
1083 return offset;
1086 static value_string RT_VALS[] = {
1087 {RTNone, "RTNone"},
1088 {RTAnd, "RTAnd"},
1089 {RTOr, "RTOr"},
1090 {RTNot, "RTNot"},
1091 {RTContent, "RTContent"},
1092 {RTProperty, "RTProperty"},
1093 {RTProximity, "RTProximity"},
1094 {RTVector, ""},
1095 {RTNatLanguage, "RTNatLanguage"},
1096 {RTScope, "RTScope"},
1097 {RTCoerce_Add, "RTCoerce_Add"},
1098 {RTCoerce_Multiply, "RTCoerce_Multiply"},
1099 {RTCoerce_Absolute, "RTCoerce_Absolute"},
1100 {RTProb, "RTProb"},
1101 {RTFeedback, "RTFeedback"},
1102 {RTReldoc, "RTReldoc"},
1103 {RTReuseWhere, "RTReuseWhere"},
1104 {RTInternalProp, "RTInternalProp"},
1105 {RTPhrase, "RTInternalProp"},
1108 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
1109 struct CRestriction *v, const char *fmt, ...)
1111 proto_tree *tree;
1112 proto_item *item;
1113 const char *str;
1114 va_list ap;
1116 va_start(ap, fmt);
1117 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1118 va_end(ap);
1120 tree = proto_item_add_subtree(item, ett_CRestriction);
1123 v->ulType = tvb_get_letohl(tvb, offset);
1124 str = val_to_str(v->ulType, RT_VALS, "0x%.8x");
1125 proto_tree_add_text(tree, tvb, offset, 4, "ulType: %s (0x%.8x)",
1126 str[0] == '0' ? "" : str, v->ulType);
1127 proto_item_append_text(item, " Type: %s", str);
1128 offset += 4;
1130 v->Weight = tvb_get_letohl(tvb, offset);
1131 proto_tree_add_text(tree, tvb, offset, 4, "Weight: %u", v->ulType);
1132 offset += 4;
1134 switch(v->ulType) {
1135 case RTNone:
1136 break;
1137 case RTAnd:
1138 case RTOr:
1139 case RTProximity:
1140 case RTPhrase:
1142 v->u.RTAnd = ep_alloc(sizeof(struct CNodeRestriction)); //XXX
1143 offset = parse_CNodeRestriction(tvb, offset, tree, pad_tree, v->u.RTAnd, "CNodeRestriction");
1144 break;
1146 case RTNot:
1148 v->u.RTNot = ep_alloc(sizeof(struct CRestriction)); //XXX
1149 offset = parse_CRestriction(tvb, offset, tree, pad_tree,
1150 v->u.RTNot, "CRestriction");
1151 break;
1153 case RTProperty:
1155 v->u.RTProperty = ep_alloc(sizeof(struct CPropertyRestriction)); //XXX
1156 offset = parse_CPropertyRestriction(tvb, offset, tree, pad_tree,
1157 v->u.RTProperty, "CPropertyRestriction");
1158 break;
1160 case RTCoerce_Add:
1161 case RTCoerce_Multiply:
1162 case RTCoerce_Absolute:
1164 v->u.RTCoerce_Add = ep_alloc(sizeof(struct CCoercionRestriction)); //XXX
1165 offset = parse_CCoercionRestriction(tvb, offset, tree, pad_tree,
1166 v->u.RTCoerce_Add, "CCoercionRestriction");
1167 break;
1169 case RTContent: {
1170 v->u.RTContent = ep_alloc(sizeof(struct CContentRestriction)); //XXX
1171 offset = parse_CContentRestriction(tvb, offset, tree, pad_tree,
1172 v->u.RTContent, "CContentRestriction");
1173 break;
1175 case RTReuseWhere: {
1176 v->u.RTReuseWhere = ep_alloc(sizeof(struct CReuseWhere)); //XXX
1177 offset = parse_CReuseWhere(tvb, offset, tree, pad_tree,
1178 v->u.RTReuseWhere, "CReuseWhere");
1179 break;
1181 case RTNatLanguage: {
1182 v->u.RTNatLanguage = ep_alloc(sizeof(struct CNatLanguageRestriction)); //XXX
1183 offset = parse_CNatLanguageRestriction(tvb, offset, tree, pad_tree,
1184 v->u.RTNatLanguage, "CNatLanguageRestriction");
1185 break;
1187 default:
1188 fprintf(stderr, "CRestriciont 0x%08x not Supported\n", v->ulType);
1189 proto_item_append_text(item, " Not supported!");
1192 proto_item_set_end(item, tvb, offset);
1193 return offset;
1196 static int parse_CRestrictionArray(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
1197 const char *fmt, ...)
1199 guint8 present, count;
1201 proto_tree *tree;
1202 proto_item *item;
1203 va_list ap;
1205 va_start(ap, fmt);
1206 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1207 va_end(ap);
1208 tree = proto_item_add_subtree(item, ett_CRestrictionArray);
1210 pad_tree = tree; //XXX
1212 count = tvb_get_guint8(tvb, offset);
1213 proto_tree_add_text(tree, tvb, offset, 1, "count: %u", count);
1214 offset += 1;
1216 present = tvb_get_guint8(tvb, offset);
1217 proto_tree_add_text(tree, tvb, offset, 1, "present: %u", present);
1218 offset += 1;
1220 if (present) {
1221 unsigned i;
1222 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCRestrictionPresent");
1224 for (i=0; i<count; i++) {
1225 struct CRestriction r;
1226 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "Restriction[%d]", i);
1229 proto_item_set_end(item, tvb, offset);
1230 return offset;
1233 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1234 proto_tree *pad_tree, struct CNodeRestriction *v,
1235 const char *fmt, ...)
1237 proto_tree *tree;
1238 proto_item *item;
1239 unsigned i;
1240 va_list ap;
1242 va_start(ap, fmt);
1243 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1244 va_end(ap);
1245 tree = proto_item_add_subtree(item, ett_CNodeRestriction);
1247 v->cNode = tvb_get_letohl(tvb, offset);
1248 proto_tree_add_text(tree, tvb, offset, 4, "cNode: %u", v->cNode);
1249 offset += 4;
1251 for (i=0; i<v->cNode; i++) {
1252 struct CRestriction r;
1253 ZERO_STRUCT(r);
1254 // offset = parse_padding(tvb, offset, 4, tree, "padding_paNode[%u]", i); /*at begin or end of loop ????*/
1255 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "paNode[%u]", i);
1256 offset = parse_padding(tvb, offset, 4, tree, "padding_paNode[%u]", i); /*at begin or end of loop ????*/
1258 // offset = parse_padding(tvb, offset, 4, pad_tree, "paNode[%u]", i); /*at begin or end of loop ????*/
1261 proto_item_set_end(item, tvb, offset);
1262 return offset;
1266 /*****************************************************************************************/
1268 static int vvalue_tvb_get0(tvbuff_t *tvb _U_, int offset _U_, void *val _U_)
1270 return 0;
1273 static int vvalue_tvb_get1(tvbuff_t *tvb, int offset, void *val)
1275 guint8 *ui1 = (guint8*)val;
1276 *ui1 = tvb_get_guint8(tvb, offset);
1277 return 1;
1280 static int vvalue_tvb_get2(tvbuff_t *tvb , int offset, void *val)
1282 guint16 *ui2 = (guint16*)val;
1283 *ui2 = tvb_get_letohs(tvb, offset);
1284 return 2;
1287 static int vvalue_tvb_get4(tvbuff_t *tvb , int offset, void *val)
1289 guint32 *ui4 = (guint32*)val;
1290 *ui4 = tvb_get_letohl(tvb, offset);
1291 return 4;
1294 static int vvalue_tvb_get8(tvbuff_t *tvb , int offset, void *val)
1296 guint64 *ui8 = (guint64*)val;
1297 *ui8 = tvb_get_letoh64(tvb, offset);
1298 return 8;
1301 static int vvalue_tvb_blob(tvbuff_t *tvb , int offset, void *val)
1303 struct data_blob *blob = (struct data_blob*)val;
1304 guint32 len = tvb_get_letohl(tvb, offset);
1305 const guint8 *data = tvb_get_ptr(tvb, offset + 4, len);
1307 blob->size = len;
1308 blob->data = se_memdup(data, len);
1310 return 4 + len;
1313 static int vvalue_tvb_bstr(tvbuff_t *tvb , int offset, void *val)
1315 struct data_str *str = (struct data_str*)val;
1316 guint32 len = tvb_get_letohl(tvb, offset);
1317 const void *ptr = tvb_get_ptr(tvb, offset + 4, len);
1319 //XXX this might be UTF-16
1320 str->len = len;
1321 str->str = se_strndup(ptr, len);
1322 return 4 + len;
1325 static int vvalue_tvb_lpstr(tvbuff_t *tvb , int offset, void *val)
1327 struct data_str *str = (struct data_str*)val;
1328 gint len;
1330 str->len = tvb_get_letohl(tvb, offset);
1331 str->str = tvb_get_stringz(wmem_packet_scope(), tvb, offset + 4, &len);
1332 /* XXX test str->len == len */
1333 return 4 + len;
1336 static int vvalue_tvb_lpwstr(tvbuff_t *tvb , int offset, void *val)
1338 struct data_str *str = (struct data_str*)val;
1339 gint len;
1340 gchar *ptr;
1342 str->len = tvb_get_letohl(tvb, offset);
1344 ptr = tvb_get_unicode_stringz(wmem_packet_scope(), tvb, offset + 4, &len, ENC_LITTLE_ENDIAN);
1345 str->str = se_strdup (ptr);
1347 return 4 + len;
1350 static int vvalue_tvb_vector_internal(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type, int num)
1352 const int offset_in = offset;
1353 const gboolean varsize = (type->size == -1);
1354 const int elsize = varsize ? (int)sizeof(struct data_blob) : type->size;
1355 guint8 *data = se_alloc(elsize * num);
1356 int len, i;
1358 val->len = num;
1359 val->u.vt_ui1 = data;
1360 DISSECTOR_ASSERT((void*)&val->u == ((void*)&val->u.vt_ui1));
1362 for (i=0; i<num; i++) {
1363 len = type->tvb_get(tvb, offset, data);
1364 data += elsize;
1365 offset += len;
1366 if (varsize && (offset % 4) ) { /* at begin or end of loop ??? */
1367 int padding = 4 - (offset % 4);
1368 offset += padding;
1371 return offset - offset_in;
1374 static int vvalue_tvb_vector(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type)
1376 const int num = tvb_get_letohl(tvb, offset);
1377 return 4 + vvalue_tvb_vector_internal(tvb , offset+4, val, type, num);
1380 static void vvalue_strbuf_append_null(emem_strbuf_t *strbuf _U_, void *ptr _U_)
1383 static void vvalue_strbuf_append_i1(emem_strbuf_t *strbuf, void *ptr)
1385 gint8 i1 = *(gint8*)ptr;
1386 ep_strbuf_append_printf(strbuf, "%d", (int)i1);
1389 static void vvalue_strbuf_append_i2(emem_strbuf_t *strbuf, void *ptr)
1391 gint16 i2 = *(gint16*)ptr;
1392 ep_strbuf_append_printf(strbuf, "%d", (int)i2);
1395 static void vvalue_strbuf_append_i4(emem_strbuf_t *strbuf, void *ptr)
1397 gint32 i4 = *(gint32*)ptr;
1398 ep_strbuf_append_printf(strbuf, "%d", i4);
1401 static void vvalue_strbuf_append_i8(emem_strbuf_t *strbuf, void *ptr)
1403 gint64 i8 = *(gint64*)ptr;
1404 ep_strbuf_append_printf(strbuf, "%ld", i8);
1407 static void vvalue_strbuf_append_ui1(emem_strbuf_t *strbuf, void *ptr)
1409 guint8 ui1 = *(guint8*)ptr;
1410 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui1);
1413 static void vvalue_strbuf_append_ui2(emem_strbuf_t *strbuf, void *ptr)
1415 guint16 ui2 = *(guint16*)ptr;
1416 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui2);
1419 static void vvalue_strbuf_append_ui4(emem_strbuf_t *strbuf, void *ptr)
1421 guint32 ui4 = *(guint32*)ptr;
1422 ep_strbuf_append_printf(strbuf, "%d", ui4);
1425 static void vvalue_strbuf_append_ui8(emem_strbuf_t *strbuf, void *ptr)
1427 guint64 ui8 = *(guint64*)ptr;
1428 ep_strbuf_append_printf(strbuf, "%lu", ui8);
1431 static void vvalue_strbuf_append_r4(emem_strbuf_t *strbuf, void *ptr)
1433 float r4 = *(float*)ptr;
1434 ep_strbuf_append_printf(strbuf, "%g", (double)r4);
1437 static void vvalue_strbuf_append_r8(emem_strbuf_t *strbuf, void *ptr)
1439 double r8 = *(double*)ptr;
1440 ep_strbuf_append_printf(strbuf, "%g", r8);
1443 static void vvalue_strbuf_append_str(emem_strbuf_t *strbuf, void *ptr)
1445 struct data_str *str = (struct data_str*)ptr;
1446 ep_strbuf_append_printf(strbuf, "\"%s\"", str->str);
1449 static void vvalue_strbuf_append_blob(emem_strbuf_t *strbuf, void *ptr)
1451 struct data_blob *blob = (struct data_blob*)ptr;
1452 ep_strbuf_append_printf(strbuf, "size: %d", (int)blob->size);
1455 static void vvalue_strbuf_append_bool(emem_strbuf_t *strbuf, void *ptr)
1457 guint16 val = *(guint*)ptr;
1458 switch (val) {
1459 case 0:
1460 ep_strbuf_append(strbuf, "False");
1461 break;
1462 case 0xffff:
1463 ep_strbuf_append(strbuf, "True");
1464 break;
1465 default:
1466 ep_strbuf_append_printf(strbuf, "Invalid (0x%4x)", val);
1470 static void vvalue_strbuf_append_vector(emem_strbuf_t *strbuf, struct vt_vector val, struct vtype *type)
1472 const int elsize = (type->size == -1) ? (int)sizeof(struct data_blob) : type->size;
1473 unsigned i;
1474 guint8 *data = val.u.vt_ui1;
1475 ep_strbuf_append_c(strbuf, '[');
1476 for (i=0; i<val.len; i++) {
1477 if (i>0) {
1478 ep_strbuf_append_c(strbuf, ',');
1480 type->strbuf_append(strbuf, data);
1481 data += elsize;
1483 ep_strbuf_append_c(strbuf, ']');
1487 static struct vtype VT_TYPE[] = {
1488 {VT_EMPTY, "VT_EMPTY", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
1489 {VT_NULL, "VT_NULL", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
1490 {VT_I2, "VT_I2", 2, vvalue_tvb_get2, vvalue_strbuf_append_i2},
1491 {VT_I4, "VT_I4", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
1492 {VT_R4, "VT_R4", 4, vvalue_tvb_get4, vvalue_strbuf_append_r4},
1493 {VT_R8, "VT_R8", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
1494 {VT_CY, "VT_CY", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1495 {VT_DATE, "VT_DATE", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
1496 // {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_bstr, vvalue_strbuf_append_str},
1497 {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
1498 {VT_ERROR, "VT_ERROR", 8, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1499 {VT_BOOL, "VT_BOOL", 2, vvalue_tvb_get2, vvalue_strbuf_append_bool},
1500 {VT_VARIANT, "VT_VARIANT", -1, NULL, NULL},
1501 {VT_DECIMAL, "VT_DECIMAL", 16, NULL, NULL},
1502 {VT_I1, "VT_I1", 1, vvalue_tvb_get1, vvalue_strbuf_append_i1},
1503 {VT_UI1, "VT_UI1", 1, vvalue_tvb_get1, vvalue_strbuf_append_ui1},
1504 {VT_UI2, "VT_UI2", 2, vvalue_tvb_get2, vvalue_strbuf_append_ui2},
1505 {VT_UI4, "VT_UI4", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1506 {VT_I8, "VT_I8", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1507 {VT_UI8, "VT_UI8", 8, vvalue_tvb_get8, vvalue_strbuf_append_ui8},
1508 {VT_INT, "VT_INT", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
1509 {VT_UINT, "VT_UINT", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1510 {VT_LPSTR, "VT_LPSTR", -1, vvalue_tvb_lpstr, vvalue_strbuf_append_str},
1511 {VT_LPWSTR, "VT_LPWSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
1512 {VT_COMPRESSED_LPWSTR, "VT_COMPRESSED_LPWSTR", -1, NULL, vvalue_strbuf_append_str},
1513 {VT_FILETIME, "VT_FILETIME", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1514 {VT_BLOB, "VT_BLOB", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
1515 {VT_BLOB_OBJECT, "VT_BLOB_OBJECT", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
1516 {VT_CLSID, "VT_CLSID", 16, NULL, NULL},
1519 static struct vtype *vType_get_type(enum vType t) {
1520 unsigned i;
1521 t &= 0xFF;
1522 for (i=0; i<array_length(VT_TYPE); i++) {
1523 if (t == VT_TYPE[i].tag) {
1524 return &VT_TYPE[i];
1527 return NULL;
1530 static char *str_CBaseStorageVariant(struct CBaseStorageVariant *value, gboolean print_type)
1533 emem_strbuf_t *strbuf = ep_strbuf_new(NULL);
1534 if (value == NULL) {
1535 return "<NULL>";
1538 if (value->type == NULL) {
1539 return "<??""?>";
1542 if (print_type) {
1543 ep_strbuf_append(strbuf, value->type->str);
1545 if (value->vType & 0xFF00) {
1546 ep_strbuf_append_printf(strbuf, "[%d]", value->vValue.vt_vector.len);
1548 ep_strbuf_append(strbuf, ": ");
1551 switch (value->vType & 0xFF00) {
1552 case 0:
1553 value->type->strbuf_append(strbuf, &value->vValue);
1554 break;
1555 case VT_ARRAY:
1556 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_array.vData, value->type);
1557 break;
1558 case VT_VECTOR:
1559 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_vector, value->type);
1560 break;
1561 default:
1562 ep_strbuf_append(strbuf, "Invalid");
1565 return strbuf->str;
1568 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree _U_,
1569 struct CBaseStorageVariant *value, const char *text)
1571 int i, len;
1572 proto_item *ti, *ti_type, *ti_val;
1573 proto_tree *tree, *tr;
1574 enum vType baseType, highType;
1576 ZERO_STRUCT(*value);
1578 ti = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1579 tree = proto_item_add_subtree(ti, ett_CBaseStorageVariant);
1581 value->vType = tvb_get_letohs(tvb, offset);
1582 value->type = vType_get_type(value->vType);
1584 ti_type = proto_tree_add_text(tree, tvb, offset, 2, "vType: %s", value->type->str);
1585 offset += 2;
1587 value->vData1 = tvb_get_guint8(tvb, offset);
1588 proto_tree_add_text(tree, tvb, offset, 1, "vData1: %d", value->vData1);
1589 offset += 1;
1591 value->vData2 = tvb_get_guint8(tvb, offset);
1592 proto_tree_add_text(tree, tvb, offset, 1, "vData2: %d", value->vData2);
1593 offset += 1;
1595 baseType = value->vType & 0x00FF;
1596 highType = value->vType & 0xFF00;
1598 if (value->type == NULL) {
1599 goto not_supported;
1602 ti_val = proto_tree_add_text(tree, tvb, offset, 0, "vValue");
1604 switch (highType) {
1605 case VT_EMPTY:
1606 len = value->type->tvb_get(tvb, offset, &value->vValue.vt_single);
1607 offset += len;
1608 break;
1609 case VT_VECTOR:
1610 proto_item_append_text(ti_type, "|VT_VECTOR");
1611 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Vector);
1613 len = vvalue_tvb_vector(tvb, offset, &value->vValue.vt_vector, value->type);
1614 proto_tree_add_text(tr, tvb, offset, 4, "num: %d", value->vValue.vt_vector.len);
1615 offset += len;
1616 break;
1617 case VT_ARRAY: {
1618 guint16 cDims, fFeatures;
1619 guint32 cbElements, cElements, lLbound;
1620 int num = 1;
1622 proto_item_append_text(ti_type, "|VT_ARRAY");
1623 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Array);
1625 cDims = tvb_get_letohs(tvb, offset);
1626 proto_tree_add_text(tr, tvb, offset, 2, "cDims: %d", cDims);
1627 offset += 2;
1629 fFeatures = tvb_get_letohs(tvb, offset);
1630 proto_tree_add_text(tr, tvb, offset, 2, "fFeaturess: %d", fFeatures);
1631 offset += 2;
1633 cbElements = tvb_get_letohl(tvb, offset);
1634 proto_tree_add_text(tr, tvb, offset, 4, "cbElements: %d", cbElements);
1635 offset += 4;
1636 for (i=0; i<cDims; i++) {
1637 cElements = tvb_get_letohl(tvb, offset);
1638 lLbound = tvb_get_letohl(tvb, offset + 4);
1639 proto_tree_add_text(tr, tvb, offset, 8, "Rgsabound[%d]: (%d:%d)", i, cElements, lLbound);
1640 offset += 8;
1641 num *= cElements;
1644 len = vvalue_tvb_vector_internal(tvb , offset, &value->vValue.vt_array.vData, value->type, num);
1645 offset += len;
1646 break;
1648 default:
1649 proto_item_append_text(ti_type, "|0x%x", highType);
1651 proto_item_set_end(ti, tvb, offset);
1652 proto_item_set_end(ti_val, tvb, offset);
1654 proto_item_append_text(ti_val, " %s", str_CBaseStorageVariant(value, false));
1655 proto_item_append_text(ti, " %s", str_CBaseStorageVariant(value, true));
1657 goto done;
1659 not_supported:
1660 proto_item_append_text(ti, ": sorry, vType %02x not handled yet!", (unsigned)value->vType);
1661 done:
1662 return offset;
1665 enum {
1666 DBKIND_GUID_NAME = 0,
1667 DBKIND_GUID_PROPID = 1
1670 static int parse_CDbColId(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree, const char *text)
1672 guint32 eKind, ulId;
1673 e_guid_t guid;
1674 static const char *KIND[] = {"DBKIND_GUID_NAME", "DBKIND_GUID_PROPID"};
1676 proto_item *tree_item = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1677 proto_tree *tree = proto_item_add_subtree(tree_item, ett_CDbColId);
1679 eKind = tvb_get_letohl(tvb, offset);
1680 proto_tree_add_text(tree, tvb, offset, 4, "eKind: %s (%u)", eKind < 2 ? KIND[eKind] : "???", eKind);
1681 offset += 4;
1683 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingGuidAlign");
1685 offset = parse_guid(tvb, offset, tree, &guid, "GUID");
1687 ulId = tvb_get_letohl(tvb, offset);
1688 proto_tree_add_text(tree, tvb, offset, 4, "ulId: %d", ulId);
1689 offset += 4;
1691 if (eKind == DBKIND_GUID_NAME) {
1692 char *name;
1693 int len = ulId; //*2 ???
1694 name = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, len, ENC_LITTLE_ENDIAN);
1695 proto_tree_add_text(tree, tvb, offset, len, "vString: \"%s\"", name);
1696 proto_item_append_text(tree_item, " \"%s\"", name);
1697 offset += len;
1698 } else if (eKind == DBKIND_GUID_PROPID) {
1699 proto_item_append_text(tree_item, " %08x", ulId);
1700 } else {
1701 proto_item_append_text(tree_item, "<INVALID>");
1704 proto_item_set_end(tree_item, tvb, offset);
1706 return offset;
1709 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1710 proto_tree *pad_tree, struct GuidPropertySet *propset,
1711 const char *fmt, ...)
1713 static const value_string EMPTY_VS[] = {{0, NULL}};
1714 const value_string *vs = (propset && propset->id_map) ? propset->id_map : EMPTY_VS;
1715 guint32 id, opt, status;
1716 struct CBaseStorageVariant value;
1717 proto_item *item;
1718 proto_tree *tree;
1719 const char *str;
1720 va_list ap;
1722 va_start(ap, fmt);
1723 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1724 va_end(ap);
1726 tree = proto_item_add_subtree(item, ett_CDbProp);
1728 id = tvb_get_letohl(tvb, offset);
1729 str = val_to_str(id, vs, "0x%08x");
1730 proto_tree_add_text(tree, tvb, offset, 4, "Id: %s (0x%08x)", str[0] == '0' ? "" : str, id);
1731 offset += 4;
1732 proto_item_append_text(item, " Id: %s", str);
1734 opt = tvb_get_letohl(tvb, offset);
1735 proto_tree_add_text(tree, tvb, offset, 4, "Options: %08x", opt);
1736 offset += 4;
1738 status = tvb_get_letohl(tvb, offset);
1739 proto_tree_add_text(tree, tvb, offset, 4, "Status: %08x", status);
1740 offset += 4;
1742 offset = parse_CDbColId(tvb, offset, tree, pad_tree, "colid");
1744 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &value, "vValue");
1746 str = str_CBaseStorageVariant(&value, true);
1747 proto_item_append_text(item, " %s", str);
1748 proto_item_set_end(item, tvb, offset);
1750 return offset;
1753 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1754 proto_tree *pad_tree, const char *fmt, ...)
1756 int i, num;
1757 e_guid_t guid;
1758 struct GuidPropertySet *pset;
1759 proto_item *item;
1760 proto_tree *tree;
1761 va_list ap;
1763 va_start(ap, fmt);
1764 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1765 va_end(ap);
1767 tree = proto_item_add_subtree(item, ett_CDbPropSet);
1769 offset = parse_guid(tvb, offset, tree, &guid, "guidPropertySet");
1771 pset = GuidPropertySet_find_guid(&guid);
1773 if (pset) {
1774 proto_item_append_text(item, " \"%s\" (%s)", pset->desc, pset->def);
1775 } else {
1776 const char *guid_str = guid_to_str(&guid);
1777 proto_item_append_text(item, " {%s}", guid_str);
1780 offset = parse_padding(tvb, offset, 4, pad_tree, "guidPropertySet");
1782 num = tvb_get_letohl(tvb, offset);
1783 proto_tree_add_text(tree, tvb, offset, 4, "cProperties: %d", num);
1784 offset += 4;
1785 proto_item_append_text(item, " Num: %d", num);
1787 for (i = 0; i<num; i++) {
1788 offset = parse_padding(tvb, offset, 4, pad_tree, "aProp[%d]", i);
1789 offset = parse_CDbProp(tvb, offset, tree, pad_tree, pset, "aProp[%d]", i);
1792 proto_item_set_end(item, tvb, offset);
1793 return offset;
1796 static int parse_PropertySetArray(tvbuff_t *tvb, int offset, int size_offset,
1797 proto_tree *parent_tree, proto_tree *pad_tree,
1798 const char *fmt, ...)
1800 const int offset_in = offset;
1801 guint32 size, num;
1802 int i;
1803 proto_tree *tree;
1804 proto_item *item;
1805 va_list ap;
1807 va_start(ap, fmt);
1808 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1809 va_end(ap);
1811 tree = proto_item_add_subtree(item, ett_CDbPropSet_Array);
1813 size = tvb_get_letohl(tvb, size_offset);
1814 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_Blob1, tvb,
1815 size_offset, 4, ENC_LITTLE_ENDIAN);
1817 num = tvb_get_letohl(tvb, offset);
1818 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_PropSets_num, tvb,
1819 offset, 4, ENC_LITTLE_ENDIAN);
1820 offset += 4;
1822 for (i = 0; i < (int)num; i++) {
1823 offset = parse_CDbPropSet(tvb, offset, tree, pad_tree, "PropertySet[%d]", i);
1826 proto_item_set_end(item, tvb, offset);
1827 DISSECTOR_ASSERT(offset - offset_in == (int)size);
1828 return offset;
1831 int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...)
1833 guint32 count, v, i;
1834 proto_item *item;
1836 va_list ap;
1838 va_start(ap, fmt);
1839 item = proto_tree_add_text_valist(tree, tvb, offset, 0, fmt, ap);
1840 va_end(ap);
1842 count = tvb_get_letohl(tvb, offset);
1843 offset += 4;
1845 proto_item_append_text(item, " Count %u [", count);
1846 for (i=0; i<count; i++) {
1847 v = tvb_get_letohl(tvb, offset);
1848 offset += 4;
1849 if (i>0) {
1850 proto_item_append_text(item, ",%u", v);
1851 } else {
1852 proto_item_append_text(item, "%u", v);
1855 proto_item_append_text(item, "]");
1856 return offset;
1859 /* 2.2.1.23 RANGEBOUNDARY */
1860 int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1861 proto_tree *pad_tree, const char *fmt, ...)
1863 guint32 ulType;
1864 guint8 labelPresent;
1865 proto_item *item;
1866 proto_tree *tree;
1867 struct CBaseStorageVariant prval;
1868 va_list ap;
1870 va_start(ap, fmt);
1871 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1872 tree = proto_item_add_subtree(item, ett_RANGEBOUNDARY);
1873 va_end(ap);
1875 ulType = tvb_get_letohl(tvb, offset);
1876 proto_tree_add_text(tree, tvb, offset, 4, "ulType 0x%08x", ulType);
1877 proto_item_append_text(item, ": Type 0x%08x", ulType);
1878 offset += 4;
1880 ZERO_STRUCT(prval);
1881 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &prval, "prVal");
1883 labelPresent = tvb_get_guint8(tvb, offset);
1884 proto_tree_add_text(tree, tvb, offset, 1, "labelPresent: %s", labelPresent ? "True" : "False");
1885 offset += 1;
1887 if (labelPresent) {
1888 guint32 ccLabel;
1889 const char *label;
1890 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingLabelPresent");
1892 ccLabel = tvb_get_letohl(tvb, offset);
1893 proto_tree_add_text(tree, tvb, offset, 4, "ccLabel: %u", ccLabel);
1894 offset += 4;
1896 label = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, 2*ccLabel, ENC_LITTLE_ENDIAN);
1897 proto_tree_add_text(tree, tvb, offset, 2*ccLabel, "Label: \"%s\"", label);
1898 proto_item_append_text(item, " Label: \"%s\"", label);
1899 offset += 2*ccLabel;
1902 proto_item_append_text(item, " Val: %s", str_CBaseStorageVariant(&prval, true));
1904 proto_item_set_end(item, tvb, offset);
1905 return offset;
1909 /* 2.2.1.22 CRangeCategSpec */
1910 int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
1911 proto_tree *parent_tree, proto_tree *pad_tree,
1912 const char *fmt, ...)
1914 proto_item *item;
1915 proto_tree *tree;
1916 va_list ap;
1917 unsigned i;
1918 guint32 cRange;
1920 va_start(ap, fmt);
1921 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1922 tree = proto_item_add_subtree(item, ett_CRangeCategSpec);
1923 va_end(ap);
1925 offset = parse_lcid(tvb, offset, tree, "lcid");
1927 cRange = tvb_get_letohl(tvb, offset);
1928 proto_tree_add_text(tree, tvb, offset, 4, "cRange 0x%08x", cRange);
1929 offset += 4;
1931 for (i=0; i<cRange; i++) {
1932 offset = parse_RANGEBOUNDARY(tvb, offset, tree, pad_tree, "aRangeBegin[%u]", i);
1936 proto_item_set_end(item, tvb, offset);
1937 return offset;
1940 /* 2.2.1.21 CCategSpec */
1941 int parse_CCategSpec(tvbuff_t *tvb, int offset,
1942 proto_tree *parent_tree, proto_tree *pad_tree,
1943 const char *fmt, ...)
1945 proto_item *item;
1946 proto_tree *tree;
1948 va_list ap;
1949 guint32 type;
1951 va_start(ap, fmt);
1952 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1953 tree = proto_item_add_subtree(item, ett_CCategSpec);
1954 va_end(ap);
1956 type = tvb_get_letohl(tvb, offset);
1957 proto_tree_add_text(tree, tvb, offset, 4, "Type 0x%08x", type);
1958 proto_item_append_text(item, " Type %u", type);
1959 offset += 4;
1961 offset = parse_CSort(tvb, offset, tree, pad_tree, "CSort");
1963 offset = parse_CRangeCategSpec(tvb, offset, tree, pad_tree, "CRangeCategSpec");
1965 proto_item_set_end(item, tvb, offset);
1966 return offset;
1969 /* 2.2.1.25 CAggregSpec */
1970 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
1971 proto_tree *parent_tree, proto_tree *pad_tree,
1972 const char *fmt, ...)
1974 proto_item *item;
1975 proto_tree *tree;
1976 va_list ap;
1977 guint8 type;
1978 guint32 ccAlias, idColumn, ulMaxNumToReturn, idRepresentative;
1979 const char *alias;
1981 va_start(ap, fmt);
1982 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1983 tree = proto_item_add_subtree(item, ett_CAggregSpec);
1984 va_end(ap);
1986 type = tvb_get_guint8(tvb, offset);
1987 proto_tree_add_text(tree, tvb, offset, 1, "type: %u", type);
1988 proto_item_append_text(item, "type: %u", type);
1989 offset += 1;
1991 offset = parse_padding(tvb, offset, 4, pad_tree, "padding");
1993 ccAlias = tvb_get_letohl(tvb, offset);
1994 proto_tree_add_text(tree, tvb, offset, 1, "ccAlias: %u", ccAlias);
1995 offset += 4;
1997 alias = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, 2*ccAlias, ENC_LITTLE_ENDIAN);
1998 proto_tree_add_text(tree, tvb, offset, 2*ccAlias, "Alias: %s", alias);
1999 offset += 2*ccAlias;
2001 idColumn = tvb_get_letohl(tvb, offset);
2002 proto_tree_add_text(tree, tvb, offset, 1, "idColumn: %u", idColumn);
2003 offset += 4;
2004 /* Optional ???
2005 ulMaxNumToReturn, idRepresentative;
2007 fprintf(stderr, "WARNING, dont know if optional members are present!\n ");
2009 proto_item_set_end(item, tvb, offset);
2010 return offset;
2013 /* 2.2.1.24 CAggregSet */
2014 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
2015 proto_tree *parent_tree, proto_tree *pad_tree,
2016 const char *fmt, ...)
2018 guint32 cCount, i;
2019 proto_item *item;
2020 proto_tree *tree;
2022 va_list ap;
2024 va_start(ap, fmt);
2025 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2026 tree = proto_item_add_subtree(item, ett_CAggregSet);
2027 va_end(ap);
2029 cCount = tvb_get_letohl(tvb, offset);
2030 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
2031 offset += 4;
2033 for (i=0; i<cCount; i++) {
2034 /* 2.2.1.25 CAggregSpec */
2035 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "AggregSpecs[%u]", i);
2038 proto_item_set_end(item, tvb, offset);
2039 return offset;
2042 /* 2.2.1.27 CAggregSortKey */
2043 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
2044 proto_tree *parent_tree, proto_tree *pad_tree,
2045 const char *fmt, ...)
2047 guint32 order;
2048 proto_item *item;
2049 proto_tree *tree;
2051 va_list ap;
2053 va_start(ap, fmt);
2054 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2055 tree = proto_item_add_subtree(item, ett_CAggregSortKey);
2056 va_end(ap);
2058 order = tvb_get_letohl(tvb, offset);
2059 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", order);
2060 offset += 4;
2062 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "ColumnSpec");
2064 proto_item_set_end(item, tvb, offset);
2065 return offset;
2069 /* 2.2.1.26 CSortAggregSet */
2070 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
2071 proto_tree *parent_tree, proto_tree *pad_tree,
2072 const char *fmt, ...)
2074 guint32 cCount, i;
2075 proto_item *item;
2076 proto_tree *tree;
2078 va_list ap;
2080 va_start(ap, fmt);
2081 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2082 tree = proto_item_add_subtree(item, ett_CSortAggregSet);
2083 va_end(ap);
2085 cCount = tvb_get_letohl(tvb, offset);
2086 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
2087 offset += 4;
2089 for (i=0; i<cCount; i++) {
2090 /* 2.2.1.27 CAggregSortKey */
2091 offset = parse_CAggregSortKey(tvb, offset, tree, pad_tree, "SortKeys[%u]", i);
2094 proto_item_set_end(item, tvb, offset);
2095 return offset;
2098 enum CInGroupSortAggregSet_type {
2099 GroupIdDefault = 0x00, /* The default for all ranges. */
2100 GroupIdMinValue = 0x01, /*The first range in the parent's group.*/
2101 GroupIdNull = 0x02, /*The last range in the parent's group.*/
2102 GroupIdValue = 0x03,
2105 /* 2.2.1.29 CInGroupSortAggregSet */
2106 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
2107 proto_tree *parent_tree, proto_tree *pad_tree,
2108 const char *fmt, ...)
2110 proto_item *item;
2111 proto_tree *tree;
2112 va_list ap;
2113 enum CInGroupSortAggregSet_type type;
2115 va_start(ap, fmt);
2116 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2117 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSet);
2118 va_end(ap);
2120 type = tvb_get_guint8(tvb, offset);
2121 proto_tree_add_text(tree, tvb, offset, 1, "Type: 0x%02x", (unsigned)type);
2122 offset += 1;
2124 offset = parse_padding(tvb, offset, 4, pad_tree, "CInGroupSortAggregSet");
2126 if (type == GroupIdValue) {
2127 struct CBaseStorageVariant id;
2128 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &id, "inGroupId");
2131 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
2133 proto_item_set_end(item, tvb, offset);
2134 return offset;
2138 /* 2.2.1.28 CInGroupSortAggregSets */
2139 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
2140 proto_tree *parent_tree, proto_tree *pad_tree,
2141 const char *fmt, ...)
2143 guint32 cCount, i;
2144 proto_item *item;
2145 proto_tree *tree;
2147 va_list ap;
2149 va_start(ap, fmt);
2150 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2151 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSets);
2152 va_end(ap);
2154 cCount = tvb_get_letohl(tvb, offset);
2155 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
2156 offset += 4;
2158 for (i=0; i<cCount; i++) {
2159 /* 2.2.1.29 CInGroupSortAggregSet */
2160 offset = parse_CInGroupSortAggregSet(tvb, offset, tree, pad_tree, "SortSets[%u]", i);
2163 proto_item_set_end(item, tvb, offset);
2164 return offset;
2167 /* 2.2.1.20 CCategorizationSpec */
2168 int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
2169 proto_tree *parent_tree, proto_tree *pad_tree,
2170 const char *fmt, ...)
2172 guint32 cMaxResults;
2173 proto_item *item;
2174 proto_tree *tree;
2176 va_list ap;
2178 va_start(ap, fmt);
2179 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2180 tree = proto_item_add_subtree(item, ett_CCategorizationSpec);
2181 va_end(ap);
2183 /* 2.2.1.18 CColumnSet */
2184 offset = parse_CColumnSet(tvb, offset, tree, "csColumns");
2186 /* 2.2.1.21 CCategSpec */
2187 offset = parse_CCategSpec(tvb, offset, tree, pad_tree, "Spec");
2189 /* 2.2.1.24 CAggregSet */
2190 offset = parse_CAggregSet(tvb, offset, tree, pad_tree, "AggregSet");
2192 /* 2.2.1.26 CSortAggregSet */
2193 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
2195 /* 2.2.1.28 CInGroupSortAggregSets */
2196 offset = parse_CInGroupSortAggregSets(tvb, offset, tree, pad_tree, "InGroupSortAggregSets");
2198 cMaxResults = tvb_get_letohl(tvb, offset);
2199 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", cMaxResults);
2200 offset += 4;
2202 proto_item_set_end(item, tvb, offset);
2203 return offset;
2206 int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
2207 proto_tree *parent_tree, proto_tree *pad_tree _U_,
2208 const char *fmt, ...)
2210 guint32 opt, maxres, timeout;
2211 proto_item *item;
2212 proto_tree *tree;
2214 va_list ap;
2216 va_start(ap, fmt);
2217 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2218 tree = proto_item_add_subtree(item, ett_CRowsetProperties);
2219 va_end(ap);
2221 opt = tvb_get_letohl(tvb, offset);
2222 proto_tree_add_text(tree, tvb, offset, 4, "uBooleanOptions: 0x%08x", opt);
2223 offset += 4;
2225 proto_tree_add_text(tree, tvb, offset, 4, "ulMaxOpenRows (ignored)");
2226 offset += 4;
2228 proto_tree_add_text(tree, tvb, offset, 4, "ulMemoryUsage (ignored)");
2229 offset += 4;
2231 maxres = tvb_get_letohl(tvb, offset);
2232 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", maxres);
2233 offset += 4;
2235 timeout = tvb_get_letohl(tvb, offset);
2236 proto_tree_add_text(tree, tvb, offset, 4, "cCmdTimeout: %u", timeout);
2237 offset += 4;
2239 proto_item_set_end(item, tvb, offset);
2240 return offset;
2243 int parse_CPidMapper(tvbuff_t *tvb, int offset,
2244 proto_tree *parent_tree, proto_tree *pad_tree,
2245 const char *fmt, ...)
2247 proto_item *item;
2248 proto_tree *tree;
2249 va_list ap;
2250 guint32 count, i;
2252 va_start(ap, fmt);
2253 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2254 tree = proto_item_add_subtree(item, ett_CPidMapper);
2255 va_end(ap);
2257 count = tvb_get_letohl(tvb, offset);
2258 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
2259 offset += 4;
2261 offset = parse_padding(tvb, offset, 8, pad_tree, "CPidMapper_PropSpec");
2263 for (i=0; i<count; i++) {
2264 struct CFullPropSpec v;
2265 ZERO_STRUCT(v);
2266 offset = parse_padding(tvb, offset, 4, pad_tree,
2267 "CPidMapper_PropSpec[%u]", i); //at begin or end of loop???
2268 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v, "PropSpec[%u]", i);
2271 proto_item_set_end(item, tvb, offset);
2272 return offset;
2275 /* 2.2.1.35 CColumnGroup */
2276 int parse_CColumnGroup(tvbuff_t *tvb, int offset,
2277 proto_tree *parent_tree, proto_tree *pad_tree,
2278 const char *fmt, ...)
2280 proto_tree *tree;
2281 proto_item *item, *ti;
2282 va_list ap;
2284 guint32 count, groupPid, i;
2286 va_start(ap, fmt);
2287 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2288 va_end(ap);
2289 tree = proto_item_add_subtree(item, ett_CColumnGroup);
2291 count = tvb_get_letohl(tvb, offset);
2292 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
2293 offset += 4;
2295 groupPid = tvb_get_letohl(tvb, offset);
2296 ti = proto_tree_add_text(tree, tvb, offset, 4, "groupPid: 0x%08x", groupPid);
2297 if ((0xFFFF0000 & groupPid) == 0x7FFF0000) {
2298 proto_item_append_text(ti, " Idx: %u", groupPid & 0xFFFF);
2299 } else {
2300 proto_item_append_text(ti, "<Invalid>");
2302 offset += 4;
2304 for (i=0; i<count; i++) {
2305 /* 2.2.1.36 SProperty */
2306 guint32 pid, weight;
2307 pid = tvb_get_letohl(tvb, offset);
2308 weight = tvb_get_letohl(tvb, offset + 4);
2309 proto_tree_add_text(tree, tvb, offset, 8, "Props[%u]: pid: %u weight: %u", i, pid, weight);
2310 offset += 8;
2313 proto_item_set_end(item, tvb, offset);
2314 return offset;
2317 /* 2.2.1.34 CColumnGroupArray */
2318 int parse_CColumnGroupArray(tvbuff_t *tvb, int offset,
2319 proto_tree *parent_tree, proto_tree *pad_tree,
2320 const char *fmt, ...)
2322 proto_tree *tree;
2323 proto_item *item;
2324 va_list ap;
2326 guint32 count, i;
2328 va_start(ap, fmt);
2329 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2330 va_end(ap);
2331 tree = proto_item_add_subtree(item, ett_CColumnGroupArray);
2333 count = tvb_get_letohl(tvb, offset);
2334 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
2335 offset += 4;
2337 for (i=0; i<count; i++) {
2338 offset = parse_padding(tvb, offset, 4, pad_tree, "aGroupArray[%u]", i);
2339 offset = parse_CColumnGroup(tvb, offset, tree, pad_tree, "aGroupArray[%u]", i);
2342 proto_item_set_end(item, tvb, offset);
2343 return offset;
2347 /* Code to actually dissect the packets */
2349 static int dissect_CPMConnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2351 proto_item *ti;
2352 proto_tree *tree;
2353 gint offset = 16;
2354 guint len;
2355 guint32 version;
2357 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2358 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
2359 proto_item_set_text(ti, "CPMConnect%s", in ? "In" : "Out");
2360 col_append_str(pinfo->cinfo, COL_INFO, "Connect");
2362 version = tvb_get_letohl(tvb, offset);
2363 ti = proto_tree_add_item(tree, hf_mswsp_msg_Connect_Version, tvb,
2364 offset, 4, ENC_LITTLE_ENDIAN);
2365 if (version & 0xffff0000) {
2366 proto_item_append_text(ti, " 64 bit");
2368 switch (version & 0xffff) {
2369 case 0x102:
2370 proto_item_append_text(ti, " w2k8 or vista");
2371 break;
2372 case 0x109:
2373 proto_item_append_text(ti, " XP or w2k3, with Windows Search 4.0");
2374 break;
2375 case 0x700:
2376 proto_item_append_text(ti, " win7 or w2k8r2");
2377 break;
2379 offset += 4;
2381 if (in) {
2382 guint32 blob_size1_off, blob_size2_off;
2383 proto_tree *pad_tree;
2385 ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
2386 pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
2388 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_ClientIsRemote, tvb,
2389 offset, 4, ENC_LITTLE_ENDIAN);
2390 offset += 4;
2392 /* _cbBlob1 */
2393 blob_size1_off = offset;
2394 offset += 4;
2396 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcbBlob2");
2398 /* _cbBlob2 */
2399 blob_size2_off = offset;
2400 offset += 4;
2402 offset = parse_padding(tvb, offset, 16, pad_tree, "_padding");
2404 len = tvb_unicode_strsize(tvb, offset);
2405 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_MachineName, tvb,
2406 offset, len, ENC_UTF_16);
2407 /*This shouldnt be necessary, is this a bug or is there some GUI setting I've missed?*/
2408 proto_item_set_text(ti, "Remote machine: %s",
2409 tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, len, ENC_LITTLE_ENDIAN));
2410 offset += len;
2412 len = tvb_unicode_strsize(tvb, offset);
2413 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_UserName, tvb,
2414 offset, len, ENC_UTF_16);
2415 proto_item_set_text(ti, "User: %s", tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, len, ENC_LITTLE_ENDIAN));
2416 offset += len;
2418 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcPropSets");
2420 offset = parse_PropertySetArray(tvb, offset, blob_size1_off, tree, pad_tree, "PropSets");
2422 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingExtPropset");
2424 offset = parse_PropertySetArray(tvb, offset, blob_size2_off, tree, pad_tree, "ExtPropset");
2426 offset = parse_padding(tvb, offset, 8, pad_tree, "???");
2428 DISSECTOR_ASSERT(offset == (int)tvb_length(tvb));
2430 /* make "Padding" the last item */
2431 proto_tree_move_item(tree, ti, proto_tree_get_parent(pad_tree));
2432 } else {
2435 return tvb_length(tvb);
2438 static int dissect_CPMDisconnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2440 col_append_str(pinfo->cinfo, COL_INFO, "Disconnect");
2441 return tvb_length(tvb);
2444 static int dissect_CPMCreateQuery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2446 gint offset = 16;
2447 proto_item *item;
2448 proto_tree *tree;
2450 item = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2451 tree = proto_item_add_subtree(item, ett_mswsp_msg);
2453 proto_item_set_text(item, "CPMCreateQuery%s", in ? "In" : "Out");
2454 col_append_str(pinfo->cinfo, COL_INFO, "CreateQuery");
2456 if (in) {
2457 proto_item *ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
2458 proto_tree *pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
2459 guint8 CColumnSetPresent, CRestrictionPresent, CSortSetPresent, CCategorizationSetPresent;
2460 guint32 size = tvb_get_letohl(tvb, offset);
2461 proto_tree_add_text(tree, tvb, offset, 4, "size");
2462 proto_tree_add_text(tree, tvb, offset, size, "ALL");
2463 offset += 4;
2465 CColumnSetPresent = tvb_get_guint8(tvb, offset);
2466 proto_tree_add_text(tree, tvb, offset, 1, "CColumnSetPresent: %s", CColumnSetPresent ? "True" : "False");
2467 offset += 1;
2469 if (CColumnSetPresent) {
2470 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCColumnSetPresent");
2471 offset = parse_CColumnSet(tvb, offset, tree, "CColumnSet");
2474 CRestrictionPresent = tvb_get_guint8(tvb, offset);
2475 proto_tree_add_text(tree, tvb, offset, 1, "CRestrictionPresent: %s", CColumnSetPresent ? "True" : "False");
2476 offset += 1;
2477 if (CRestrictionPresent) {
2478 offset = parse_CRestrictionArray(tvb, offset, tree, pad_tree, "RestrictionArray");
2481 CSortSetPresent = tvb_get_guint8(tvb, offset);
2482 proto_tree_add_text(tree, tvb, offset, 1, "CSortSetPresent: %s", CSortSetPresent ? "True" : "False");
2483 offset += 1;
2484 if (CSortSetPresent) {
2485 offset = parse_padding(tvb, offset, 4, tree, "paddingCSortSetPresent");
2487 proto_tree_add_text(tree, tvb, offset, 8, "XXX");
2488 offset += 8;
2490 offset = parse_CSortSet(tvb, offset, tree, pad_tree, "SortSet");
2493 CCategorizationSetPresent = tvb_get_guint8(tvb, offset);
2494 proto_tree_add_text(tree, tvb, offset, 1, "CCategorizationSetPresent: %s", CCategorizationSetPresent ? "True" : "False");
2495 offset += 1;
2497 if (CCategorizationSetPresent) {
2498 guint32 count, i;
2499 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCCategorizationSetPresent");
2500 /* 2.2.1.19 CCategorizationSet */
2501 count = tvb_get_letohl(tvb, offset);
2502 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
2503 offset += 4;
2504 for (i=0; i<count; i++) {
2505 offset = parse_CCategorizationSpec(tvb, offset, tree, pad_tree, "categories[%u]", i);
2509 offset = parse_padding(tvb, offset, 4, tree, "XXXX"); //XXX
2511 offset = parse_CRowsetProperties(tvb, offset, tree, pad_tree, "RowSetProperties");
2513 offset = parse_CPidMapper(tvb, offset, tree, pad_tree, "PidMapper");
2515 offset = parse_CColumnGroupArray(tvb, offset, tree, pad_tree, "GroupArray");
2516 } else { /* out */
2517 proto_tree_add_text(tree, tvb, offset, 4, "TrueSequential");
2518 offset += 4;
2519 proto_tree_add_text(tree, tvb, offset, 4, "WorkIdUnique");
2520 offset += 4;
2521 proto_tree_add_text(tree, tvb, offset, -1, "Cursors");
2522 //offset += 4*(#CategorizationSet + 1);
2525 return tvb_length(tvb);
2528 static int dissect_CPMFreeCursor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2530 col_append_str(pinfo->cinfo, COL_INFO, "FreeCursor");
2531 return tvb_length(tvb);
2534 static int dissect_CPMGetRows(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2536 col_append_str(pinfo->cinfo, COL_INFO, "GetRows");
2537 return tvb_length(tvb);
2540 static int dissect_CPMRatioFinished(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2542 col_append_str(pinfo->cinfo, COL_INFO, "RatioFinished");
2543 return tvb_length(tvb);
2546 static int dissect_CPMCompareBmk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2548 col_append_str(pinfo->cinfo, COL_INFO, "CompareBmk");
2549 return tvb_length(tvb);
2552 static int dissect_CPMGetApproximatePosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2554 col_append_str(pinfo->cinfo, COL_INFO, "GetApproximatePosition");
2555 return tvb_length(tvb);
2558 /* 2.2.3.10 */
2559 static int dissect_CPMSetBindings(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2561 gint offset = 16;
2563 col_append_str(pinfo->cinfo, COL_INFO, "SetBindings");
2565 if (in) {
2566 proto_item *ti;
2567 proto_tree *tree, *pad_tree;
2568 guint32 size, num, n;
2570 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2571 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
2573 proto_item_set_text(ti, "SetBindingsIn");
2575 ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
2576 pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
2578 proto_tree_add_text(tree, tvb, offset, 4, "hCursor");
2579 offset += 4;
2580 proto_tree_add_text(tree, tvb, offset, 4, "cbRow");
2581 offset += 4;
2583 size = tvb_get_letohl(tvb, offset);
2584 proto_tree_add_text(tree, tvb, offset, 4, "cbBindingDesc: %d", size);
2585 offset += 4;
2587 proto_tree_add_text(tree, tvb, offset, 4, "dummy");
2588 offset += 4;
2590 num = tvb_get_letohl(tvb, offset);
2591 proto_tree_add_text(tree, tvb, offset, 4, "cColumns: %u", num);
2592 offset += 4;
2594 proto_tree_add_text(tree, tvb, offset, size-4, "aColumns");
2595 for (n=0; n<num; n++) {
2596 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_aColumns[%u]", n);
2597 offset = parse_CTableColumn(tvb, offset, tree, pad_tree, "aColumns[%u]", n);
2600 } else { /* server only returns status with header */
2603 return tvb_length(tvb);
2606 static int dissect_CPMGetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2608 col_append_str(pinfo->cinfo, COL_INFO, "GetNotify");
2609 return tvb_length(tvb);
2612 static int dissect_CPMSendNotifyOut(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2614 col_append_str(pinfo->cinfo, COL_INFO, "SendNotify");
2615 return tvb_length(tvb);
2618 static int dissect_CPMGetQueryStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2620 gint offset = 16;
2621 proto_item *item;
2622 proto_tree *tree;
2624 item = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2625 tree = proto_item_add_subtree(item, ett_mswsp_msg);
2627 proto_item_set_text(item, "GetQueryStatus%s", in ? "In" : "Out");
2628 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatus");
2630 if (in) {
2631 /* 2.2.3.7 */
2632 proto_tree_add_text(tree, tvb, offset, 4, "hCursor");
2633 offset += 4;
2634 } else {
2635 /* 2.2.3.7 */
2636 proto_tree_add_text(tree, tvb, offset, 4, "QStatus");
2637 offset += 4;
2640 return tvb_length(tvb);
2643 static int dissect_CPMCiState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2645 col_append_str(pinfo->cinfo, COL_INFO, "CiState");
2646 return tvb_length(tvb);
2649 static int dissect_CPMFetchValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2651 col_append_str(pinfo->cinfo, COL_INFO, "FetchValue");
2652 return tvb_length(tvb);
2655 static int dissect_CPMGetQueryStatusEx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2657 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatusEx");
2658 return tvb_length(tvb);
2661 static int dissect_CPMRestartPosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2663 col_append_str(pinfo->cinfo, COL_INFO, "RestartPosition");
2664 return tvb_length(tvb);
2667 static int dissect_CPMSetCatState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2669 col_append_str(pinfo->cinfo, COL_INFO, "SetCatState");
2670 return tvb_length(tvb);
2673 static int dissect_CPMGetRowsetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2675 col_append_str(pinfo->cinfo, COL_INFO, "GetRowsetNotify");
2676 return tvb_length(tvb);
2679 static int dissect_CPMFindIndices(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2681 col_append_str(pinfo->cinfo, COL_INFO, "FindIndices");
2682 return tvb_length(tvb);
2685 static int dissect_CPMSetScopePrioritization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2687 col_append_str(pinfo->cinfo, COL_INFO, "SetScopePrioritization");
2688 return tvb_length(tvb);
2691 static int dissect_CPMGetScopeStatistics(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2693 col_append_str(pinfo->cinfo, COL_INFO, "GetScopeStatistics");
2694 return tvb_length(tvb);
2697 static void debug_frame(int frame)
2699 static const char *dbg_wait = NULL;
2700 static int wait_frame = -1;
2702 if (dbg_wait == NULL) {
2703 dbg_wait = getenv("DBG_FRAME");
2704 if (dbg_wait == NULL) {
2705 dbg_wait = "no";
2706 } else {
2707 wait_frame = atoi(dbg_wait);
2711 if (frame == wait_frame) {
2712 static volatile gboolean wait = 1;
2713 fprintf(stderr, "waiting for debugger with pid: %u\n", getpid());
2714 while(wait) {
2715 sleep(1);
2722 dissect_mswsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean in)
2724 proto_tree *mswsp_tree = NULL;
2725 struct {
2726 guint32 msg;
2727 guint32 status;
2728 guint32 checksum;
2729 guint32 reserved;
2730 } hdr;
2731 int (*fn)(tvbuff_t*, packet_info*, proto_tree*, gboolean);
2733 if (tvb_length(tvb) < 16) {
2734 return 0;
2737 hdr.msg = tvb_get_letohl(tvb, 0);
2739 switch(hdr.msg) {
2740 case 0xC8:
2741 fn = dissect_CPMConnect;
2742 break;
2743 case 0xC9:
2744 fn = dissect_CPMDisconnect;
2745 break;
2746 case 0xCA:
2747 fn = dissect_CPMCreateQuery;
2748 break;
2749 case 0xCB:
2750 fn = dissect_CPMFreeCursor;
2751 break;
2752 case 0xCC:
2753 fn = dissect_CPMGetRows;
2754 break;
2755 case 0xCD:
2756 fn = dissect_CPMRatioFinished;
2757 break;
2758 case 0xCE:
2759 fn = dissect_CPMCompareBmk;
2760 break;
2761 case 0xCF:
2762 fn = dissect_CPMGetApproximatePosition;
2763 break;
2764 case 0xD0:
2765 fn = dissect_CPMSetBindings;
2766 break;
2767 case 0xD1:
2768 fn = dissect_CPMGetNotify;
2769 break;
2770 case 0xD2:
2771 fn = dissect_CPMSendNotifyOut;
2772 break;
2773 case 0xD7:
2774 fn = dissect_CPMGetQueryStatus;
2775 break;
2776 case 0xD9:
2777 fn = dissect_CPMCiState;
2778 break;
2779 case 0xE4:
2780 fn = dissect_CPMFetchValue;
2781 break;
2782 case 0xE7:
2783 fn = dissect_CPMGetQueryStatusEx;
2784 break;
2785 case 0xE8:
2786 fn = dissect_CPMRestartPosition;
2787 break;
2788 case 0xEC:
2789 fn = dissect_CPMSetCatState;
2790 break;
2791 case 0xF1:
2792 fn = dissect_CPMGetRowsetNotify;
2793 break;
2794 case 0xF2:
2795 fn = dissect_CPMFindIndices;
2796 break;
2797 case 0xF3:
2798 fn = dissect_CPMSetScopePrioritization;
2799 break;
2800 case 0xF4:
2801 fn = dissect_CPMGetScopeStatistics;
2802 break;
2803 default:
2804 return 0;
2807 hdr.status = tvb_get_letohl(tvb, 4);
2808 hdr.checksum = tvb_get_letohl(tvb, 8);
2810 /* col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS-WSP"); */
2811 col_append_str(pinfo->cinfo, COL_PROTOCOL, " WSP");
2812 /* col_clear(pinfo->cinfo, COL_INFO); */
2814 col_set_str(pinfo->cinfo, COL_INFO, "WSP ");
2815 col_append_str(pinfo->cinfo, COL_INFO, in ? "Request: " : "Response: ");
2817 if (tree) {
2818 proto_tree *hdr_tree;
2819 proto_item *ti, *hti;
2821 ti = proto_tree_add_item(tree, proto_mswsp, tvb, 0, -1, ENC_NA);
2822 mswsp_tree = proto_item_add_subtree(ti, ett_mswsp);
2824 hti = proto_tree_add_item(mswsp_tree, hf_mswsp_hdr, tvb, 0, 16, ENC_NA);
2825 hdr_tree = proto_item_add_subtree(hti, ett_mswsp_hdr);
2827 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_msg, tvb,
2828 0, 4, ENC_LITTLE_ENDIAN);
2829 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_status,
2830 tvb, 4, 4, ENC_LITTLE_ENDIAN);
2831 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_checksum,
2832 tvb, 8, 4, ENC_LITTLE_ENDIAN);
2833 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_reserved, tvb,
2834 12, 4, ENC_LITTLE_ENDIAN);
2837 fn(tvb, pinfo, mswsp_tree, in);
2839 /* Return the amount of data this dissector was able to dissect */
2840 return tvb_length(tvb);
2844 /* Register the protocol with Wireshark */
2846 /* this format is require because a script is used to build the C function
2847 that calls all the protocol registration.
2850 void
2851 proto_register_mswsp(void)
2853 module_t *mswsp_module;
2855 /* Setup list of header fields See Section 1.6.1 for details*/
2856 static const value_string msg_ids[] = {
2857 {0x000000C8, "CPMConnect"}, /* In/Out */
2858 {0x000000C9, "CPMDisconnect"},
2859 {0x000000CA, "CPMCreateQuery"}, /* In/Out */
2860 {0x000000CB, "CPMFreeCursor"}, /* In/Out */
2861 {0x000000CC, "CPMGetRows"}, /* In/Out */
2862 {0x000000CD, "CPMRatioFinished"}, /* In/Out */
2863 {0x000000CE, "CPMCompareBmk"}, /* In/Out */
2864 {0x000000CF, "CPMGetApproximatePosition"}, /* In/Out */
2865 {0x000000D0, "CPMSetBindingsIn"},
2866 {0x000000D1, "CPMGetNotify"},
2867 {0x000000D2, "CPMSendNotifyOut"},
2868 {0x000000D7, "CPMGetQueryStatusIn"}, /* In/Out */
2869 {0x000000D9, "CPMCiStateInOut"},
2870 {0x000000E4, "CPMFetchValue"}, /* In/Out */
2871 {0x000000E7, "CPMGetQueryStatusEx"}, /* In/Out */
2872 {0x000000E8, "CPMRestartPositionIn"},
2873 {0x000000EC, "CPMSetCatStateIn"}, /* (not supported) */
2874 {0x000000F1, "CPMGetRowsetNotify"}, /* In/Out */
2875 {0x000000F2, "CPMFindIndices"}, /* In/Out */
2876 {0x000000F3, "CPMSetScopePrioritization"}, /* In/Out */
2877 {0x000000F4, "CPMGetScopeStatistics"}, /* In/Out */
2879 static hf_register_info hf[] = {
2880 { &hf_mswsp_hdr,
2881 { "Header", "mswsp.hdr",
2882 FT_NONE, BASE_NONE , NULL, 0,
2883 "Message header", HFILL }
2885 { &hf_mswsp_hdr_msg,
2886 { "Msg id", "mswsp.hdr.id",
2887 FT_UINT32, BASE_HEX , VALS(msg_ids), 0,
2888 "Message id", HFILL }
2890 { &hf_mswsp_hdr_status,
2891 { "Status", "mswsp.hdr.status",
2892 FT_UINT32, BASE_HEX , NULL, 0,
2893 "Status", HFILL }
2895 { &hf_mswsp_hdr_checksum,
2896 { "checksum", "mswsp.hdr.checksum",
2897 FT_UINT32, BASE_HEX , NULL, 0,
2898 "Checksum", HFILL }
2900 { &hf_mswsp_hdr_reserved,
2901 { "Reserved", "mswsp.hdr.reserved",
2902 FT_UINT32, BASE_HEX , NULL, 0,
2903 "Reserved", HFILL }
2905 { &hf_mswsp_msg,
2906 { "msg", "mswsp.msg",
2907 FT_NONE, BASE_NONE , NULL, 0,
2908 "Message", HFILL }
2910 { &hf_mswsp_msg_Connect_Version,
2911 { "Version", "mswsp.Connect.version",
2912 FT_UINT32, BASE_HEX , NULL, 0,
2913 "Version",HFILL }
2915 { &hf_mswsp_msg_ConnectIn_ClientIsRemote,
2916 { "Remote", "mswsp.ConnectIn.isRemote",
2917 FT_BOOLEAN, BASE_HEX , NULL, 0,
2918 "Client is remote",HFILL }
2920 { &hf_mswsp_msg_ConnectIn_Blob1,
2921 { "Size", "mswsp.ConnectIn.propset.size",
2922 FT_UINT32, BASE_DEC , NULL, 0,
2923 "Size of PropSet fields",HFILL }
2925 { &hf_mswsp_msg_ConnectIn_Blob2,
2926 { "Size", "mswsp.ConnectIn.extpropset.size",
2927 FT_UINT32, BASE_DEC , NULL, 0,
2928 "Size of ExtPropSet fields",HFILL }
2930 { &hf_mswsp_msg_ConnectIn_MachineName,
2931 { "Remote machine", "mswsp.ConnectIn.machine",
2932 FT_STRINGZ, BASE_NONE , NULL, 0,
2933 "Name of remote machine",HFILL }
2935 { &hf_mswsp_msg_ConnectIn_UserName,
2936 { "User", "mswsp.ConnectIn.user",
2937 FT_STRINGZ, BASE_NONE , NULL, 0,
2938 "Name of remote user",HFILL }
2940 { &hf_mswsp_msg_ConnectIn_PropSets_num,
2941 { "Num", "mswsp.ConnectIn.propset.num",
2942 FT_UINT32, BASE_DEC , NULL, 0,
2943 "Number of Property Sets", HFILL }
2945 { &hf_mswsp_msg_ConnectIn_ExtPropSets_num,
2946 { "Num", "mswsp.ConnectIn.extpropset.num",
2947 FT_UINT32, BASE_DEC , NULL, 0,
2948 "Number of extended Property Sets", HFILL }
2953 /* Setup protocol subtree array */
2954 static gint *ett[] = {
2955 &ett_mswsp,
2956 &ett_mswsp_hdr,
2957 &ett_mswsp_msg,
2958 &ett_mswsp_pad,
2959 &ett_mswsp_property_restriction,
2960 &ett_CRestrictionArray,
2961 &ett_CBaseStorageVariant,
2962 &ett_CBaseStorageVariant_Vector,
2963 &ett_CBaseStorageVariant_Array,
2964 &ett_CDbColId,
2965 &ett_GUID,
2966 &ett_CDbProp,
2967 &ett_CDbPropSet,
2968 &ett_CDbPropSet_Array,
2969 &ett_CRestriction,
2970 &ett_CNodeRestriction,
2971 &ett_CPropertyRestriction,
2972 &ett_CCoercionRestriction,
2973 &ett_CContentRestriction,
2974 &ett_RANGEBOUNDARY,
2975 &ett_CRangeCategSpec,
2976 &ett_CCategSpec,
2977 &ett_CAggregSpec,
2978 &ett_CAggregSet,
2979 &ett_CCategorizationSpec,
2980 &ett_CAggregSortKey,
2981 &ett_CSortAggregSet,
2982 &ett_CInGroupSortAggregSet,
2983 &ett_CInGroupSortAggregSets,
2984 &ett_CRowsetProperties,
2985 &ett_CFullPropSpec,
2986 &ett_CPidMapper,
2987 &ett_CSort,
2988 &ett_CSortSet,
2989 &ett_CNatLanguageRestriction,
2990 &ett_CColumnGroup,
2991 &ett_CColumnGroupArray,
2992 &ett_LCID,
2993 &ett_CTableColumn,
2996 int i;
2998 /* Register the protocol name and description */
2999 proto_mswsp = proto_register_protocol("Windows Search Protocol",
3000 "MS-WSP", "mswsp");
3002 /* Required function calls to register the header fields and subtrees used */
3003 proto_register_field_array(proto_mswsp, hf, array_length(hf));
3004 proto_register_subtree_array(ett, array_length(ett));
3006 for (i=0; i<(int)array_length(GuidPropertySet); i++) {
3007 guids_add_guid(&GuidPropertySet[i].guid, GuidPropertySet[i].def);
3011 /* Register preferences module (See Section 2.6 for more on preferences) */
3012 /* (Registration of a prefs callback is not required if there are no */
3013 /* prefs-dependent registration functions (eg: a port pref). */
3014 /* See proto_reg_handoff below. */
3015 /* If a prefs callback is not needed, use NULL instead of */
3016 /* proto_reg_handoff_mswsp in the following). */
3017 mswsp_module = prefs_register_protocol(proto_mswsp,
3018 proto_reg_handoff_mswsp);
3020 /* Register preferences module under preferences subtree.
3021 Use this function instead of prefs_register_protocol if you want to group
3022 preferences of several protocols under one preferences subtree.
3023 Argument subtree identifies grouping tree node name, several subnodes can be
3024 specified using slash '/' (e.g. "OSI/X.500" - protocol preferences will be
3025 accessible under Protocols->OSI->X.500-><PROTOSHORTNAME> preferences node.
3027 /* mswsp_module = prefs_register_protocol_subtree(subtree, */
3028 /* proto_mswsp, proto_reg_handoff_mswsp); */
3030 /* Register a sample preference */
3031 prefs_register_bool_preference(mswsp_module, "show_hex",
3032 "Display numbers in Hex",
3033 "Enable to display numerical values in hexadecimal.",
3034 &gPREF_HEX);
3036 /* Register a sample port preference */
3037 prefs_register_uint_preference(mswsp_module, "tcp.port", "mswsp TCP Port",
3038 " mswsp TCP port if other than the default",
3039 10, &gPORT_PREF);
3042 static int dissect_mswsp_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
3043 smb_info_t *si = pinfo->private_data;
3044 gboolean in = si->request;
3046 smb_transact_info_t *tri = (si->sip->extra_info_type == SMB_EI_TRI) ? si->sip->extra_info : NULL;
3047 smb_fid_info_t *fid_info = NULL;
3048 GSList *iter;
3050 debug_frame((int)pinfo->fd->num);
3052 fprintf(stderr, "dissect_mswsp_smb %s frame: %d tid: %d op: %02x ",
3053 in ? "Request" : "Response",
3054 pinfo->fd->num, si->tid, si->cmd);
3056 if (tri == NULL) {
3057 fprintf(stderr, " extra_info_type: %d\n", si->sip->extra_info_type);
3058 return 0;
3061 for (iter = si->ct->GSL_fid_info; iter; iter = g_slist_next(iter)) {
3062 smb_fid_info_t *info = iter->data;
3063 if ((info->tid == si->tid) && (info->fid == tri->fid)) {
3064 fid_info = info;
3065 break;
3069 if (!fid_info || !fid_info->fsi || !fid_info->fsi->filename) {
3070 fprintf(stderr, " no %s\n", fid_info ? (fid_info->fsi ? "filename" : "fsi") : "fid_info");
3071 return 0;
3074 fprintf(stderr, " file: %s\n", fid_info->fsi->filename);
3076 if (strcasecmp(fid_info->fsi->filename, "\\MsFteWds") != 0) {
3077 return 0;
3080 return dissect_mswsp(tvb, pinfo, tree, in);
3084 static int dissect_mswsp_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
3085 smb2_info_t *si = pinfo->private_data;
3086 gboolean in = !(si->flags & SMB2_FLAGS_RESPONSE);
3088 //si->tree->share_type == SMB2_SHARE_TYPE_PIPE
3089 //si->tree->connect_frame
3091 debug_frame((int)pinfo->fd->num);
3093 fprintf(stderr, "dissect_mswsp %d <> %d : op %02x %s %s type: %d extra_file: %s\n",
3094 pinfo->fd->num, si->tree ? (int)si->tree->connect_frame : -1,
3095 si->opcode,
3096 pinfo->dcerpc_procedure_name ? pinfo->dcerpc_procedure_name : "<NULL>",
3097 in ? "Request" : "Response", si->tree ? si->tree->share_type : -1,
3098 si->saved ? (si->saved->extra_info_type == SMB2_EI_FILENAME ? (char*)si->saved->extra_info : "<OTHER>") : "<NONE>"
3102 if (strcmp(pinfo->dcerpc_procedure_name, "File: MsFteWds") != 0) {
3103 return 0;
3106 return dissect_mswsp(tvb, pinfo, tree, in);
3111 /* If this dissector uses sub-dissector registration add a registration routine.
3112 This exact format is required because a script is used to find these
3113 routines and create the code that calls these routines.
3115 If this function is registered as a prefs callback (see prefs_register_protocol
3116 above) this function is also called by preferences whenever "Apply" is pressed;
3117 In that case, it should accommodate being called more than once.
3119 Simple form of proto_reg_handoff_mswsp which can be used if there are
3120 no prefs-dependent registration function calls.
3123 void
3124 proto_reg_handoff_mswsp(void)
3126 heur_dissector_add("smb_transact", dissect_mswsp_smb, proto_mswsp);
3127 heur_dissector_add("smb2_heur_subdissectors", dissect_mswsp_smb2, proto_mswsp);
3132 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3134 * Local variables:
3135 * c-basic-offset: 4
3136 * tab-width: 8
3137 * indent-tabs-mode: nil
3138 * End:
3140 * vi: set shiftwidth=4 tabstop=8 expandtab:
3141 * :indentSize=4:tabSize=8:noTabs=true: