MSWSP: dissect CPMGetRowsIn
[wireshark-wip.git] / epan / dissectors / packet-mswsp.c
blob6932463d808fe263c8c1377fe85e85ed151111a2
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"
47 #include "packet-dcom.h" /* HRESULT */
49 /* IF PROTO exposes code to other dissectors, then it must be exported
50 in a header file. If not, a header file is not needed at all. */
52 * #include "packet-mswsp.h"
54 #include "mswsp.h"
56 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
58 /* Forward declaration we need below (if using proto_reg_handoff...
59 as a prefs callback) */
60 void proto_reg_handoff_mswsp(void);
62 /* Initialize the protocol and registered fields */
63 static int proto_mswsp = -1;
64 static int hf_mswsp_msg = -1;
65 static int hf_mswsp_hdr = -1;
66 static int hf_mswsp_hdr_msg = -1;
67 static int hf_mswsp_hdr_status = -1;
68 static int hf_mswsp_hdr_checksum = -1;
69 static int hf_mswsp_hdr_reserved = -1;
70 static int hf_mswsp_msg_Connect_Version = -1;
71 static int hf_mswsp_msg_ConnectIn_ClientIsRemote = -1;
72 static int hf_mswsp_msg_ConnectIn_Blob1 = -1;
73 static int hf_mswsp_msg_ConnectIn_Blob2 = -1;
74 static int hf_mswsp_msg_ConnectIn_MachineName = -1;
75 static int hf_mswsp_msg_ConnectIn_UserName = -1;
76 static int hf_mswsp_msg_ConnectIn_PropSets_num = -1;
77 static int hf_mswsp_msg_ConnectIn_ExtPropSets_num = -1;
80 /* Global sample preference ("controls" display of numbers) */
81 static gboolean gPREF_HEX = FALSE;
82 /* Global sample port pref */
83 static guint gPORT_PREF = 1234;
85 /* Initialize the subtree pointers */
86 static gint ett_mswsp = -1;
87 static gint ett_mswsp_hdr = -1;
88 static gint ett_mswsp_msg = -1;
89 static gint ett_mswsp_pad = -1;
91 static gint ett_mswsp_property_restriction = -1;
92 static gint ett_CRestrictionArray = -1;
93 static gint ett_CBaseStorageVariant = -1;
94 static gint ett_CBaseStorageVariant_Vector = -1;
95 static gint ett_CBaseStorageVariant_Array = -1;
96 static gint ett_CDbColId = -1;
97 static gint ett_GUID = -1;
98 static gint ett_CDbProp = -1;
99 static gint ett_CDbPropSet = -1;
100 static gint ett_CDbPropSet_Array = -1;
101 static gint ett_CRestriction = -1;
102 static gint ett_CNodeRestriction = -1;
103 static gint ett_CPropertyRestriction = -1;
104 static gint ett_CCoercionRestriction = -1;
105 static gint ett_CContentRestriction = -1;
106 static gint ett_RANGEBOUNDARY = -1;
107 static gint ett_CRangeCategSpec = -1;
108 static gint ett_CCategSpec = -1;
109 static gint ett_CAggregSpec = -1;
110 static gint ett_CAggregSet = -1;
111 static gint ett_CCategorizationSpec = -1;
112 static gint ett_CAggregSortKey = -1;
113 static gint ett_CSortAggregSet = -1;
114 static gint ett_CInGroupSortAggregSet = -1;
115 static gint ett_CInGroupSortAggregSets = -1;
116 static gint ett_CRowsetProperties = -1;
117 static gint ett_CFullPropSpec = -1;
118 static gint ett_CPidMapper = -1;
119 static gint ett_CSort = -1;
120 static gint ett_CSortSet = -1;
121 static gint ett_CNatLanguageRestriction = -1;
122 static gint ett_CColumnGroup = -1;
123 static gint ett_CColumnGroupArray = -1;
124 static gint ett_LCID = -1;
125 static gint ett_CTableColumn = -1;
127 /******************************************************************************/
128 struct GuidPropertySet {
129 e_guid_t guid;
130 const char *def;
131 const char *desc;
132 const value_string *id_map;
135 /* 2.2.1.31.1 */
136 static const value_string DBPROPSET_FSCIFRMWRK_EXT_IDS[] = {
137 {0x02, "DBPROP_CI_CATALOG_NAME"},
138 {0x03, "DBPROP_CI_INCLUDE_SCOPES"},
139 {0x04, "DBPROP_CI_SCOPE_FLAGS"},
140 {0x07, "DBPROP_CI_QUERY_TYPE"},
141 {0, NULL}
144 static const value_string DBPROPSET_QUERYEXT_IDS[] = {
145 {0x02, "DBPROP_USECONTENTINDEX"},
146 {0x03, "DBPROP_DEFERNONINDEXEDTRIMMING"},
147 {0x04, "DBPROP_USEEXTENDEDDBTYPES"},
148 {0x05, "DBPROP_IGNORENOISEONLYCLAUSES"},
149 {0x06, "DBPROP_GENERICOPTIONS_STRING"},
150 {0x07, "DBPROP_FIRSTROWS"},
151 {0x08, "DBPROP_DEFERCATALOGVERIFICATION"},
152 {0x0a, "DBPROP_GENERATEPARSETREE"},
153 {0x0c, "DBPROP_FREETEXTANYTERM"},
154 {0x0d, "DBPROP_FREETEXTUSESTEMMING"},
155 {0x0e, "DBPROP_IGNORESBRI"},
156 {0x10, "DBPROP_ENABLEROWSETEVENTS"},
157 {0, NULL}
160 static const value_string DBPROPSET_CIFRMWRKCORE_EXT_IDS[] = {
161 {0x02, "DBPROP_MACHINE"},
162 {0x03, "DBPROP_CLIENT_CLSID"},
163 {0, NULL}
166 static const value_string DBPROPSET_MSIDXS_ROWSETEXT_IDS[] = {
167 {0x02, "MSIDXSPROP_ROWSETQUERYSTATUS"},
168 {0x03, "MSIDXSPROP_COMMAND_LOCALE_STRING"},
169 {0x04, "MSIDXSPROP_QUERY_RESTRICTION"},
170 {0x05, "MSIDXSPROP_PARSE_TREE"},
171 {0x06, "MSIDXSPROP_MAX_RANK"},
172 {0x07, "MSIDXSPROP_RESULTS_FOUND"},
173 {0, NULL}
176 /* 2.2.5.1 */
177 static const value_string QueryGuid_IDS[] = {
178 {0x02, "RankVector"},
179 {0x03, "System.Search.Rank"},
180 {0x04, "System.Search.HitCount"},
181 {0x05, "System.Search.EntryID"},
182 {0x06, "All"},
183 {0x09, "System.ItemURL"},
184 {0, NULL}
187 /* 2.2.5.2 */
188 static const value_string StorageGuid_IDS[] = {
189 {0x02, "System.ItemFolderNameDisplay"},
190 {0x03, "ClassId"},
191 {0x04, "System.ItemTypeText"},
192 {0x08, "FileIndex"},
193 {0x09, "USN"},
194 {0x0a, "System.ItemNameDisplay"},
195 {0x0b, "Path"},
196 {0x0c, "System.Size"},
197 {0x0d, "System.FileAttributes"},
198 {0x0e, "System.DateModified"},
199 {0x0f, "System.DateCreated"},
200 {0x10, "System.DateAccessed"},
201 {0x12, "AllocSize"},
202 {0x13, "System.Search.Contents"},
203 {0x14, "ShortFilename"},
204 {0x15, "FileFRN"},
205 {0x16, "Scope"},
206 {0, NULL}
209 static const value_string DocPropSetGuid_IDS[] = {
210 {0x02, "System.Title"},
211 {0x03, "System.Subject"},
212 {0x04, "System.Author"},
213 {0x05, "System.Keywords"},
214 {0x06, "System.Comment"},
215 {0x07, "DocTemplate"},
216 {0x08, "System.Document.LastAuthor"},
217 {0x09, "System.Document.RevisionNumber"},
218 {0x0a, "System.Document.EditTime???"},
219 {0x0b, "System.Document.DatePrinted"},
220 {0x0c, "System.Document.DateCreated"},
221 {0x0d, "System.Document.DateSaved"},
222 {0x0e, "System.Document.PageCount"},
223 {0x0f, "System.Document.WordCount"},
224 {0x10, "System.Document.CharacterCount"},
225 {0x11, "DocThumbnail"},
226 {0x12, "System.ApplicationName"},
227 {0, NULL}
230 static const value_string ShellDetails_IDS[] = {
231 { 5, "System.ComputerName"},
232 { 8, "System.ItemPathDisplayNarrow"},
233 { 9, "PercivedType"},
234 {11, "System.ItemType"},
235 {12, "FileCount"},
236 {14, "TotalFileSize"},
237 {24, "System.ParsingName"},
238 {25, "System.SFGAOFlags"},
239 {0, NULL}
242 static const value_string PropSet1_IDS[] = {
243 {100, "System.ThumbnailCacheId"},
244 {0, NULL}
247 static const value_string PropSet2_IDS[] = {
248 {3, "System.Kind"},
249 {0, NULL}
252 static const value_string MusicGuid_IDS[] = {
253 {0, NULL}
256 static const value_string PropSet3_IDS[] = {
257 { 2, "System.Message.BccAddress"},
258 { 3, "System.Message.BccName"},
259 { 4, "System.Message.CcAddress"},
260 { 5, "System.Message.CcName"},
261 { 6, "System.ItemFolderPathDisplay"},
262 { 7, "System.ItemPathDisplay"},
263 { 9, "System.Communication.AccountName"},
264 {10, "System.IsRead"},
265 {11, "System.Importance"},
266 {12, "System.FlagStatus"},
267 {13, "System.Message.FromAddress"},
268 {14, "System.Message.FromName"},
269 {15, "System.Message.Store"},
270 {16, "System.Message.ToAddress"},
271 {17, "System.Message.ToName"},
272 {18, "System.Contact.WebPage"},
273 {19, "System.Message.DateSent"},
274 {20, "System.Message.DateReceived"},
275 {21, "System.Message.AttachmentNames"},
276 {0, NULL}
279 static const value_string PropSet4_IDS[] = {
280 {100, "System.ItemFolderPathDisplayNarrow"},
281 {0, NULL}
284 static const value_string PropSet5_IDS[] = {
285 {100, "System.Contact.FullName"},
286 {0, NULL}
289 static const value_string PropSet6_IDS[] = {
290 {100, "System.ItemAuthors"},
291 {0, NULL}
294 static const value_string PropSet7_IDS[] = {
295 {2, "System.Shell.OmitFromView"},
296 {0, NULL}
299 static const value_string PropSet8_IDS[] = {
300 {2, "System.Shell.SFGAOFlagsStrings"},
301 {3, "System.Link.TargetSFGAOFlagsStrings"},
302 {0, NULL}
305 static const value_string PropSet9_IDS[] = {
306 {100, "System.ItemDate"},
307 {0, NULL}
310 static const value_string PropSet10_IDS[] = {
311 { 5, "System.MIMEType"},
312 { 8, "System.Search.GatherTime"},
313 { 9, "System.Search.AccessCount"},
314 {11, "System.Search.LastIndexedTotalTime"},
315 {0, NULL}
318 static const value_string PropSet11_IDS[] = {
319 {5, "System.Priority"},
320 {8, "System.Messagee.HasAttachments"},
321 {0, NULL}
324 static const value_string DocCharacter_IDS[] = {
325 {2, "System.Search.Autosummary"},
326 {0, NULL}
329 static const value_string PropSet12_IDS[] = {
330 {100, "System.IsDeleted"},
331 {0, NULL}
334 static const value_string PropSet13_IDS[] = {
335 {100, "System.IsAttachment"},
336 {0, NULL}
339 static const value_string PropSet14_IDS[] = {
340 {100, "System.Message.ConversationID"},
341 {101, "System.Message.ConversationIndex"},
342 {0, NULL}
345 static const value_string DocPropSetGuid2_IDS[] = {
346 {0x02, "System.Category"},
347 {0x03, "System.Document.PresentationFormat"},
348 {0x04, "System.Document.ByteCount"},
349 {0x05, "System.Document.LineCount"},
350 {0x06, "System.Document.ParagraphCount"},
351 {0x07, "System.Document.SlideCount"},
352 {0x08, "DocNoteCount"},
353 {0x09, "System.Document.HiddenSlideCount"},
354 {0x0D, "DocPartTitles"},
355 {0x0E, "System.Document.Manager"},
356 {0x0F, "System.Company"},
357 {0, NULL}
360 static const value_string SystemContact_IDS[] = {
361 { 6, "System.Contact.JobTitle"},
362 { 7, "System.Contact.OfficeLocation"},
363 {20, "System.Contact.HomeTelephone"},
364 {25, "System.Contact.PrimaryTelephone"},
365 {35, "System.Contact.MobileTelephone"},
366 {47, "System.Contact.Birthday"},
367 {48, "System.Contact.PrimaryEmailAddress"},
368 {65, "System.Contact.HomeAddressCity"},
369 {69, "System.Contact.PersonalTitle"},
370 {71, "System.Contact.MiddleName"},
371 {73, "System.Contact.Suffix"},
372 {74, "System.Contact.NickName"},
373 {0, NULL}
376 static struct GuidPropertySet GuidPropertySet[] = {
377 {{0xa9bd1526, 0x6a80, 0x11d0, {0x8c, 0x9d, 0x00, 0x20, 0xaf, 0x1d, 0x74, 0x0e}},
378 "DBPROPSET_FSCIFRMWRK_EXT", "File system content index framework",
379 DBPROPSET_FSCIFRMWRK_EXT_IDS},
380 {{0xa7ac77ed, 0xf8d7, 0x11ce, {0xa7, 0x98, 0x00, 0x20, 0xf8, 0x00, 0x80, 0x25}},
381 "DBPROPSET_QUERYEXT", "Query extension",
382 DBPROPSET_QUERYEXT_IDS},
383 {{0xafafaca5, 0xb5d1, 0x11d0, {0x8c, 0x62, 0x00, 0xc0, 0x4f, 0xc2, 0xdb, 0x8d}},
384 "DBPROPSET_CIFRMWRKCORE_EXT", "Content index framework core",
385 DBPROPSET_CIFRMWRKCORE_EXT_IDS},
386 {{0xAA6EE6B0, 0xE828, 0x11D0, {0xB2, 0x3E, 0x00, 0xAA, 0x00, 0x47, 0xFC, 0x01}},
387 "DBPROPSET_MSIDXS_ROWSETEXT", "???",
388 DBPROPSET_MSIDXS_ROWSETEXT_IDS},
389 {{0xB725F130, 0x47ef, 0x101a, {0xA5, 0xF1, 0x02, 0x60, 0x8C, 0x9E, 0xEB, 0xAC}},
390 "Storage", "Storage Property Set",
391 StorageGuid_IDS},
392 {{0xF29F85E0, 0x4FF9, 0x1068, {0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9}},
393 "Document", "Document Property Set",
394 DocPropSetGuid_IDS},
395 {{0x49691C90, 0x7E17, 0x101A, {0xA9, 0x1C, 0x08, 0x00, 0x2B, 0x2E, 0xCD, 0xA9}},
396 "Query", "Query Property Set",
397 QueryGuid_IDS},
398 {{0x28636AA6, 0x953D, 0x11D2, {0xB5, 0xD6, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xD0}},
399 "ShellDetails", "Shell Details Property Set",
400 ShellDetails_IDS},
401 {{0x446D16B1, 0x8DAD, 0x4870, {0xA7, 0x48, 0x40, 0x2E, 0xA4, 0x3D, 0x78, 0x8C}},
402 "???", "Unspecified Property Set",
403 PropSet1_IDS},
404 {{0x1E3EE840, 0xBC2B, 0x476C, {0x82, 0x37, 0x2A, 0xCD, 0x1A, 0x83, 0x9B, 0x22}},
405 "???", "Unspecified Property Set",
406 PropSet2_IDS},
407 {{0x56A3372E, 0xCE9C, 0x11d2, {0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6}},
408 "Music", "Music Property Set",
409 MusicGuid_IDS},
410 {{0xE3E0584C, 0xB788, 0x4A5A, {0xBB, 0x20, 0x7F, 0x5A, 0x44, 0xC9, 0xAC, 0xDD}},
411 "???", "Unspecified Property Set",
412 PropSet3_IDS},
413 {{0xDABD30ED, 0x0043, 0x4789, {0xA7, 0xF8, 0xD0, 0x13, 0xA4, 0x73, 0x66, 0x22}},
414 "???", "Unspecified Property Set",
415 PropSet4_IDS},
416 {{0x635E9051, 0x50A5, 0x4BA2, {0xB9, 0xDB, 0x4E, 0xD0, 0x56, 0xC7, 0x72, 0x96}},
417 "???", "Unspecified Property Set",
418 PropSet5_IDS},
419 {{0xD0A04F0A, 0x462A, 0x48A4, {0xBB, 0x2F, 0x37, 0x06, 0xE8, 0x8D, 0xBD, 0x7D}},
420 "???", "Unspecified Property Set",
421 PropSet6_IDS},
422 {{0xDE35258C, 0xC695, 0x4CBC, {0xB9, 0x82, 0x38, 0xB0, 0xAD, 0x24, 0xCE, 0xD0}},
423 "???", "Unspecified Property Set",
424 PropSet7_IDS},
425 {{0xD6942081, 0xD53B, 0x443D, {0xAD, 0x47, 0x5E, 0x05, 0x9D, 0x9C, 0xD2, 0x7A}},
426 "???", "Unspecified Property Set",
427 PropSet8_IDS},
428 {{0xF7DB74B4, 0x4287, 0x4103, {0xAF, 0xBA, 0xF1, 0xB1, 0x3D, 0xCD, 0x75, 0xCF}},
429 "???", "Unspecified Property Set",
430 PropSet9_IDS},
431 {{0x0B63E350, 0x9CCC, 0x11d0, {0xBC, 0xDB, 0x00, 0x80, 0x5F, 0xCC, 0xCE, 0x04}},
432 "???", "Unspecified Property Set",
433 PropSet10_IDS},
434 {{0x9C1FCF74, 0x2D97, 0x41BA, {0xB4, 0xAE, 0xCB, 0x2E, 0x36, 0x61, 0xA6, 0xE4}},
435 "???", "Unspecified Property Set",
436 PropSet11_IDS},
437 {{0x560C36C0, 0x503A, 0x11CF, {0xBA, 0xA1, 0x00, 0x00, 0x4C, 0x75, 0x2A, 0x9A}},
438 "DocCharacter", "Document characterization Property Set",
439 DocCharacter_IDS},
440 {{0x5CDA5FC8, 0x33EE, 0x4FF3, {0x90, 0x94, 0xAE, 0x7B, 0xD8, 0x86, 0x8C, 0x4D}},
441 "???", "Unspecified Property Set",
442 PropSet12_IDS},
443 {{0xF23F425C, 0x71A1, 0x4FA8, {0x92, 0x2F, 0x67, 0x8E, 0xA4, 0xA6, 0x04, 0x08}},
444 "???", "Unspecified Property Set",
445 PropSet13_IDS},
446 {{0xDC8F80BD, 0xAF1E, 0x4289, {0x85, 0xB6, 0x3D, 0xFC, 0x1B, 0x49, 0x39, 0x92}},
447 "???", "Unspecified Property Set",
448 PropSet14_IDS},
449 {{0xD5CDD502, 0x2E9C, 0x101B, {0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE}},
450 "DocPropSet2", "Document Property Set 2",
451 DocPropSetGuid2_IDS},
452 {{0x176DC63C, 0x2688, 0x4E89, {0x81, 0x43, 0xA3, 0x47, 0x80, 0x0F, 0x25, 0xE9}},
453 "System.Contact", "System Contact Property Set",
454 SystemContact_IDS},
457 static struct GuidPropertySet *GuidPropertySet_find_guid(const e_guid_t *guid)
459 unsigned i;
460 for (i=0; i<array_length(GuidPropertySet); i++) {
461 if (guid_cmp(&GuidPropertySet[i].guid, guid) == 0) {
462 return &GuidPropertySet[i];
465 return NULL;
468 /******************************************************************************/
470 static int parse_padding(tvbuff_t *tvb, int offset, int alignment, proto_tree *pad_tree, const char *fmt, ...)
472 if (offset % alignment) {
473 const int padding = alignment - (offset % alignment);
474 va_list ap;
475 proto_item *ti;
476 va_start(ap, fmt);
477 ti = proto_tree_add_text_valist(pad_tree, tvb, offset, padding, fmt, ap);
478 va_end(ap);
480 proto_item_append_text(ti, " (%d)", padding);
481 offset += padding;
483 DISSECTOR_ASSERT((offset % alignment) == 0);
484 return offset;
487 static int parse_guid(tvbuff_t *tvb, int offset, proto_tree *tree, e_guid_t *guid, const char *text)
489 const char *guid_str, *name, *bytes;
490 proto_tree *tr;
491 proto_item *ti;
493 tvb_get_letohguid(tvb, offset, guid);
494 guid_str = guid_to_str(guid);
495 name = guids_get_guid_name(guid);
497 ti = proto_tree_add_text(tree, tvb, offset, 16, "%s: %s {%s}", text, name ? name : "", guid_str);
498 tr = proto_item_add_subtree(ti, ett_GUID);
500 proto_tree_add_text(tr, tvb, offset, 4, "time-low: 0x%08x", guid->data1);
501 offset += 4;
502 proto_tree_add_text(tr, tvb, offset, 2, "time-mid: 0x%04x", guid->data2);
503 offset += 2;
504 proto_tree_add_text(tr, tvb, offset, 2, "time-high-and-version: 0x%04x", guid->data3);
505 offset += 2;
506 proto_tree_add_text(tr, tvb, offset, 1, "clock_seq_hi_and_reserved: 0x%02x", guid->data4[0]);
507 offset += 1;
508 proto_tree_add_text(tr, tvb, offset, 1, "clock_seq_low: 0x%02x", guid->data4[1]);
509 offset += 1;
510 bytes = bytestring_to_str(&guid->data4[2], 6, ':');
511 proto_tree_add_text(tr, tvb, offset, 6, "node: %s", bytes);
512 offset += 6;
514 return offset;
517 static const value_string LCID_LID[] = {
518 {0x0407, "de-DE"},
519 {0x0409, "en-US"},
520 {0, NULL}
524 /*Language Code ID: http://msdn.microsoft.com/en-us/library/cc233968(v=prot.20).aspx */
525 static int parse_lcid(tvbuff_t *tvb, int offset, proto_tree *parent_tree, const char *text)
527 proto_item *item;
528 proto_tree *tree;
529 guint32 lcid;
530 const char *langid;
532 item = proto_tree_add_text(parent_tree, tvb, offset, 4, "%s", text);
533 tree = proto_item_add_subtree(item, ett_LCID);
535 lcid = tvb_get_letohl(tvb, offset);
536 langid = val_to_str(lcid & 0xFFFF, LCID_LID, "0x%04x");
537 proto_tree_add_text(tree, tvb, offset+2, 2, "Language ID: %s", langid);
538 proto_item_append_text(item, ": %s", langid);
539 proto_tree_add_text(tree, tvb, offset+1,1, "Sort ID: %u", (lcid >> 16) & 0xf);
540 offset += 4;
541 return offset;
544 /*****************************************************************************************/
545 /* 2.2.1.1 CBaseStorageVariant */
546 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
547 struct CBaseStorageVariant *value, const char *text);
549 /* 2.2.1.2 CFullPropSpec */
550 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pad_tree,
551 struct CFullPropSpec *v, const char *fmt, ...);
553 /* 2.2.1.3 CContentRestriction */
554 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
555 proto_tree *pad_tree, struct CContentRestriction *v,
556 const char *fmt, ...);
558 /* 2.2.1.5 CNatLanguageRestriction */
559 static int parse_CNatLanguageRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
560 proto_tree *pad_tree, struct CNatLanguageRestriction *v,
561 const char *fmt, ...);
563 /* 2.2.1.6 CNodeRestriction */
564 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pad_tree,
565 struct CNodeRestriction *v, const char* fmt, ...);
567 /* 2.2.1.7 CPropertyRestriction */
568 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
569 proto_tree *pad_tree, struct CPropertyRestriction *v,
570 const char *fmt, ...);
572 /* 2.2.1.8 CReuseWhere */
573 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
574 proto_tree *pad_tree _U_, struct CReuseWhere *v,
575 const char *fmt, ...);
577 /* 2.2.1.10 CSort */
578 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
579 proto_tree *pad_tree _U_,
580 const char *fmt, ...);
582 /* 2.2.1.12 CCoercionRestriction */
583 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
584 proto_tree *pad_tree, struct CCoercionRestriction *v,
585 const char *fmt, ...);
586 /* 2.2.1.16 CRestrictionArray */
587 static int parse_CRestrictionArray(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
588 const char *fmt, ...);
590 /* 2.2.1.17 CRestriction */
591 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
592 struct CRestriction *v, const char *fmt, ...);
594 /* 2.2.1.18 CColumnSet */
595 static int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...);
597 /* 2.2.1.20 CCategorizationSpec */
598 static int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
599 proto_tree *parent_tree, proto_tree *pad_tree,
600 const char *fmt, ...);
602 /* 2.2.1.21 CCategSpec */
603 static int parse_CCategSpec(tvbuff_t *tvb, int offset,
604 proto_tree *parent_tree, proto_tree *pad_tree,
605 const char *fmt, ...);
607 /* 2.2.1.22 CRangeCategSpec */
608 static int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
609 proto_tree *parent_tree, proto_tree *pad_tree,
610 const char *fmt, ...);
612 /* 2.2.1.23 RANGEBOUNDARY */
613 static int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
614 proto_tree *pad_tree, const char *fmt, ...);
616 /* 2.2.1.24 CAggregSet */
617 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
618 proto_tree *parent_tree, proto_tree *pad_tree,
619 const char *fmt, ...);
621 /* 2.2.1.25 CAggregSpec */
622 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
623 proto_tree *parent_tree, proto_tree *pad_tree,
624 const char *fmt, ...);
626 /* 2.2.1.26 CSortAggregSet */
627 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
628 proto_tree *parent_tree, proto_tree *pad_tree,
629 const char *fmt, ...);
631 /* 2.2.1.27 CAggregSortKey */
632 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
633 proto_tree *parent_tree, proto_tree *pad_tree,
634 const char *fmt, ...);
636 /* 2.2.1.28 CInGroupSortAggregSets */
637 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
638 proto_tree *parent_tree, proto_tree *pad_tree,
639 const char *fmt, ...);
641 /* 2.2.1.29 CInGroupSortAggregSet */
642 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
643 proto_tree *parent_tree, proto_tree *pad_tree,
644 const char *fmt, ...);
645 /* 2.2.1.30 CDbColId */
646 static int parse_CDbColId(tvbuff_t *tvb, int offset,
647 proto_tree *parent_tree, proto_tree *pad_tree, const char *text);
649 /* 2.2.1.31 CDbProp */
650 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
651 proto_tree *pad_tree, struct GuidPropertySet *propset,
652 const char *fmt, ...);
654 /* 2.2.1.32 CDbPropSet */
655 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
656 proto_tree *pad_tree, const char *fmt, ...);
657 /* 2.2.1.33 CPidMapper */
658 static int parse_CPidMapper(tvbuff_t *tvb, int offset,
659 proto_tree *parent_tree, proto_tree *pad_tree,
660 const char *fmt, ...);
662 /* 2.2.1.34 CColumnGroupArray */
663 static int parse_CColumnGroupArray(tvbuff_t *tvb, int offset,
664 proto_tree *parent_tree, proto_tree *pad_tree,
665 const char *fmt, ...);
667 /* 2.2.1.35 CColumnGroup */
668 static int parse_CColumnGroup(tvbuff_t *tvb, int offset,
669 proto_tree *parent_tree, proto_tree *pad_tree,
670 const char *fmt, ...);
672 /* 2.2.1.41 CRowsetProperties */
673 static int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
674 proto_tree *parent_tree, proto_tree *pad_tree,
675 const char *fmt, ...);
677 /* 2.2.1.43 CSortSet */
678 static int parse_CSortSet(tvbuff_t *tvb, int offset,
679 proto_tree *parent_tree, proto_tree *pad_tree,
680 const char *fmt, ...);
682 /* 2.2.1.44 CTableColumn */
683 static int parse_CTableColumn(tvbuff_t *tvb, int offset,
684 proto_tree *parent_tree, proto_tree *pad_tree,
685 const char *fmt, ...);
689 2.2.1.4 CInternalPropertyRestriction
690 2.2.1.9 CScopeRestriction
691 2.2.1.11 CVectorRestriction
692 2.2.1.13 CRelDocRestriction
693 2.2.1.14 CProbRestriction
694 2.2.1.15 CFeedbackRestriction
695 2.2.1.19 CCategorizationSet
696 2.2.1.37 CRowSeekAt
697 2.2.1.38 CRowSeekAtRatio
698 2.2.1.39 CRowSeekByBookmark
699 2.2.1.40 CRowSeekNext
700 2.2.1.42 CRowVariant
701 2.2.1.45 SERIALIZEDPROPERTYVALUE
702 2.2.1.46 CCompletionCategSp
705 static int parse_CSort(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
706 proto_tree *pad_tree _U_,
707 const char *fmt, ...)
709 guint32 col, ord, ind;
711 proto_item *item;
712 proto_tree *tree;
714 va_list ap;
716 va_start(ap, fmt);
717 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
718 va_end(ap);
719 tree = proto_item_add_subtree(item, ett_CSort);
721 col = tvb_get_letohl(tvb, offset);
722 proto_tree_add_text(tree, tvb, offset, 4, "column: %u", col);
723 offset += 4;
725 ord = tvb_get_letohl(tvb, offset);
726 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", ord);
727 offset += 4;
729 ind = tvb_get_letohl(tvb, offset);
730 proto_tree_add_text(tree, tvb, offset, 4, "individual: %u", ind);
731 offset += 4;
733 offset = parse_lcid(tvb, offset, tree, "lcid");
735 proto_item_set_end(item, tvb, offset);
736 return offset;
739 static int parse_CSortSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
740 proto_tree *pad_tree,
741 const char *fmt, ...)
743 guint32 count, i;
745 proto_item *item;
746 proto_tree *tree;
748 va_list ap;
750 va_start(ap, fmt);
751 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
752 va_end(ap);
753 tree = proto_item_add_subtree(item, ett_CSortSet);
755 count = tvb_get_letohl(tvb, offset);
756 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
757 offset += 4;
759 for (i=0; i<count; i++) {
760 offset = parse_padding(tvb, offset, 4, tree, "padding_sortArray[%u]", i);
761 offset = parse_CSort(tvb, offset, tree, pad_tree, "sortArray[%u]", i);
764 proto_item_set_end(item, tvb, offset);
765 return offset;
768 static int parse_CTableColumn(tvbuff_t *tvb, int offset,
769 proto_tree *parent_tree, proto_tree *pad_tree,
770 const char *fmt, ...)
772 proto_item *item;
773 proto_tree *tree;
774 va_list ap;
776 struct CFullPropSpec v;
777 guint8 used;
779 va_start(ap, fmt);
780 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
781 va_end(ap);
782 tree = proto_item_add_subtree(item, ett_CTableColumn);
784 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v, "PropSpec");
786 proto_tree_add_text(tree, tvb, offset, 4, "vType");
787 offset += 4;
789 proto_tree_add_text(tree, tvb, offset, 1, "AggreagateUsed");
790 offset += 1;
792 proto_tree_add_text(tree, tvb, offset, 1, "AggreagateType");
793 offset += 1;
795 used = tvb_get_guint8(tvb, offset);
796 proto_tree_add_text(tree, tvb, offset, 1, "ValueUsed");
797 offset += 1;
799 if (used) {
800 offset = parse_padding(tvb, offset, 2, pad_tree, "padding_Value");
802 proto_tree_add_text(tree, tvb, offset, 2, "ValueOffset");
803 offset += 2;
805 proto_tree_add_text(tree, tvb, offset, 2, "ValueSize");
806 offset += 2;
809 used = tvb_get_guint8(tvb, offset);
810 proto_tree_add_text(tree, tvb, offset, 1, "StatusUsed");
811 offset += 1;
813 if (used) {
814 offset = parse_padding(tvb, offset, 2, pad_tree, "padding_Status");
816 proto_tree_add_text(tree, tvb, offset, 2, "StatusOffset");
817 offset += 2;
820 used = tvb_get_guint8(tvb, offset);
821 proto_tree_add_text(tree, tvb, offset, 1, "LengthUsed");
822 offset += 1;
824 if (used) {
825 offset = parse_padding(tvb, offset, 2, pad_tree, "padding_Lenght");
827 proto_tree_add_text(tree, tvb, offset, 2, "LenghtOffset");
828 offset += 2;
831 proto_item_set_end(item, tvb, offset);
832 return offset;
836 static int parse_CFullPropSpec(tvbuff_t *tvb, int offset,
837 proto_tree *parent_tree, proto_tree *pad_tree,
838 struct CFullPropSpec *v, const char *fmt, ...)
840 static const value_string KIND[] = {
841 {0, "PRSPEC_LPWSTR"},
842 {1, "PRSPEC_PROPID"},
843 {0, NULL}
846 struct GuidPropertySet *pset;
847 const char *id_str, *guid_str;
849 proto_item *item;
850 proto_tree *tree;
851 va_list ap;
853 va_start(ap, fmt);
854 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
855 va_end(ap);
856 tree = proto_item_add_subtree(item, ett_CFullPropSpec);
858 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingPropSet");
860 offset = parse_guid(tvb, offset, tree, &v->guid, "GUID");
861 pset = GuidPropertySet_find_guid(&v->guid);
863 v->kind = (enum PRSPEC_Kind)tvb_get_letohl(tvb, offset);
864 proto_tree_add_text(tree, tvb, offset, 4, "ulKind: %s ", val_to_str(v->kind, KIND, "(Unknown: 0x%x)"));
865 offset += 4;
867 v->u.propid = tvb_get_letohl(tvb, offset);
868 proto_tree_add_text(tree, tvb, offset, 4, "propid: %u ", v->u.propid);
869 offset += 4;
871 if (v->kind == PRSPEC_LPWSTR) {
872 int len = 2*v->u.propid;
873 v->u.name = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, len, ENC_LITTLE_ENDIAN);
874 proto_tree_add_text(tree, tvb, offset, len, "name: \"%s\"", v->u.name);
875 offset += len;
878 id_str = pset ? try_val_to_str(v->u.propid, pset->id_map) : NULL;
880 if (id_str) {
881 proto_item_append_text(item, ": %s", id_str);
882 } else {
883 guid_str = guids_get_guid_name(&v->guid);
884 if (guid_str) {
885 proto_item_append_text(item, ": \"%s\"", guid_str);
886 } else {
887 guid_str = guid_to_str(&v->guid);
888 proto_item_append_text(item, ": {%s}", guid_str);
891 if (v->kind == PRSPEC_LPWSTR) {
892 proto_item_append_text(item, " \"%s\"", v->u.name);
893 } else if (v->kind == PRSPEC_PROPID) {
894 proto_item_append_text(item, " 0x%08x", v->u.propid);
895 } else {
896 proto_item_append_text(item, " <INVALID>");
900 proto_item_set_end(item, tvb, offset);
901 return offset;
906 static const value_string PR_VALS[] = {
907 {PRLT, "PRLT"},
908 {PRLE, "PRLE"},
909 {PRGT, "PRGT"},
910 {PRGE, "PRGE"},
911 {PREQ, "PREQ"},
912 {PRNE, "PRNE"},
913 {PRRE, "PRRE"},
914 {PRAllBits, "PRAllBits"},
915 {PRSomeBits, "PRSomeBits"},
916 {PRAll, "PRAll"},
917 {PRSome, "PRSome"},
921 static int parse_CPropertyRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
922 proto_tree *pad_tree, struct CPropertyRestriction *v,
923 const char *fmt, ...)
925 proto_tree *tree;
926 proto_item *item;
927 const char *str;
928 va_list ap;
930 va_start(ap, fmt);
931 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
932 va_end(ap);
934 tree = proto_item_add_subtree(item, ett_CPropertyRestriction);
936 v->relop = (enum relop)tvb_get_letohl(tvb, offset);
937 str = val_to_str(v->relop, PR_VALS, "0x%04x");
938 proto_tree_add_text(tree, tvb, offset, 4, "relop: %s (0x%04x)",
939 str[0]=='\0' ? "" : str, v->relop);
940 proto_item_append_text(item, " Op: %s", str);
941 offset += 4;
943 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
945 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &v->prval, "prval");
947 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_lcid");
949 v->lcid = tvb_get_letohl(tvb, offset);
950 offset = parse_lcid(tvb, offset, tree, "lcid");
952 proto_item_set_end(item, tvb, offset);
954 return offset;
957 static int parse_CCoercionRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
958 proto_tree *pad_tree, struct CCoercionRestriction *v,
959 const char *fmt, ...)
961 proto_tree *tree;
962 proto_item *item;
963 va_list ap;
965 va_start(ap, fmt);
966 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
967 va_end(ap);
969 tree = proto_item_add_subtree(item, ett_CCoercionRestriction);
971 v->value = tvb_get_letohl(tvb, offset);
972 proto_tree_add_text(tree, tvb, offset, 4, "value: %g", (double)v->value);
973 offset += 4;
975 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &v->child, "child");
977 proto_item_set_end(item, tvb, offset);
978 return offset;
981 static int parse_CContentRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
982 proto_tree *pad_tree, struct CContentRestriction *v,
983 const char *fmt, ...)
985 proto_tree *tree;
986 proto_item *item;
987 va_list ap;
988 guint32 cc;
989 const char *str;
992 va_start(ap, fmt);
993 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
994 va_end(ap);
996 tree = proto_item_add_subtree(item, ett_CContentRestriction);
998 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
1000 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding1");
1002 cc = tvb_get_letohl(tvb, offset);
1003 proto_tree_add_text(tree, tvb, offset, 4, "cc: %u", cc);
1004 offset += 4;
1006 // str = tvb_get_ephemeral_string_enc(tvb, offset, 2*cc, ENC_UTF_16);
1007 str = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, 2*cc, ENC_LITTLE_ENDIAN);
1008 v->phrase = se_strdup(str);
1009 proto_tree_add_text(tree, tvb, offset, 2*cc, "phrase: %s", str);
1010 offset += 2*cc;
1012 offset = parse_padding(tvb, offset, 4, pad_tree, "Padding2");
1014 v->lcid = tvb_get_letohl(tvb, offset);
1015 offset = parse_lcid(tvb, offset, tree, "lcid");
1017 v->method = tvb_get_letohl(tvb, offset);
1018 proto_tree_add_text(tree, tvb, offset, 4, "method: 0x%08x", v->method);
1019 offset += 4;
1021 proto_item_set_end(item, tvb, offset);
1022 return offset;
1025 int parse_CNatLanguageRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1026 proto_tree *pad_tree, struct CNatLanguageRestriction *v,
1027 const char *fmt, ...)
1029 proto_tree *tree;
1030 proto_item *item;
1031 va_list ap;
1032 guint32 cc;
1033 const char *str;
1036 va_start(ap, fmt);
1037 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1038 va_end(ap);
1040 tree = proto_item_add_subtree(item, ett_CNatLanguageRestriction);
1042 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v->property, "Property");
1044 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_cc");
1046 cc = tvb_get_letohl(tvb, offset);
1047 proto_tree_add_text(tree, tvb, offset, 4, "cc: %u", cc);
1048 offset += 4;
1050 // str = tvb_get_ephemeral_string_enc(tvb, offset, 2*cc, ENC_UTF_16);
1051 str = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, 2*cc, ENC_LITTLE_ENDIAN);
1052 v->phrase = se_strdup(str);
1053 proto_tree_add_text(tree, tvb, offset, 2*cc, "phrase: %s", str);
1054 offset += 2*cc;
1056 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_lcid");
1058 v->lcid = tvb_get_letohl(tvb, offset);
1059 offset = parse_lcid(tvb, offset, tree, "lcid");
1061 proto_item_set_end(item, tvb, offset);
1062 return offset;
1066 static int parse_CReuseWhere(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1067 proto_tree *pad_tree _U_, struct CReuseWhere *v,
1068 const char *fmt, ...)
1070 proto_item *item;
1071 va_list ap;
1074 va_start(ap, fmt);
1075 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1076 va_end(ap);
1078 v->whereId = tvb_get_letohl(tvb, offset);
1079 offset += 4;
1081 proto_item_append_text(item, " Id: %u", v->whereId);
1083 proto_item_set_end(item, tvb, offset);
1084 return offset;
1087 static value_string RT_VALS[] = {
1088 {RTNone, "RTNone"},
1089 {RTAnd, "RTAnd"},
1090 {RTOr, "RTOr"},
1091 {RTNot, "RTNot"},
1092 {RTContent, "RTContent"},
1093 {RTProperty, "RTProperty"},
1094 {RTProximity, "RTProximity"},
1095 {RTVector, ""},
1096 {RTNatLanguage, "RTNatLanguage"},
1097 {RTScope, "RTScope"},
1098 {RTCoerce_Add, "RTCoerce_Add"},
1099 {RTCoerce_Multiply, "RTCoerce_Multiply"},
1100 {RTCoerce_Absolute, "RTCoerce_Absolute"},
1101 {RTProb, "RTProb"},
1102 {RTFeedback, "RTFeedback"},
1103 {RTReldoc, "RTReldoc"},
1104 {RTReuseWhere, "RTReuseWhere"},
1105 {RTInternalProp, "RTInternalProp"},
1106 {RTPhrase, "RTInternalProp"},
1109 #define EP_ALLOC(T) (T*)ep_alloc(sizeof(T))
1111 static int parse_CRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
1112 struct CRestriction *v, const char *fmt, ...)
1114 proto_tree *tree;
1115 proto_item *item;
1116 const char *str;
1117 va_list ap;
1119 va_start(ap, fmt);
1120 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1121 va_end(ap);
1123 tree = proto_item_add_subtree(item, ett_CRestriction);
1126 v->ulType = (enum rType)tvb_get_letohl(tvb, offset);
1127 str = val_to_str(v->ulType, RT_VALS, "0x%.8x");
1128 proto_tree_add_text(tree, tvb, offset, 4, "ulType: %s (0x%.8x)",
1129 str[0] == '0' ? "" : str, v->ulType);
1130 proto_item_append_text(item, " Type: %s", str);
1131 offset += 4;
1133 v->Weight = tvb_get_letohl(tvb, offset);
1134 proto_tree_add_text(tree, tvb, offset, 4, "Weight: %u", v->ulType);
1135 offset += 4;
1137 switch(v->ulType) {
1138 case RTNone:
1139 break;
1140 case RTAnd:
1141 case RTOr:
1142 case RTProximity:
1143 case RTPhrase:
1145 v->u.RTAnd = EP_ALLOC(struct CNodeRestriction); //XXX
1146 offset = parse_CNodeRestriction(tvb, offset, tree, pad_tree, v->u.RTAnd, "CNodeRestriction");
1147 break;
1149 case RTNot:
1151 v->u.RTNot = EP_ALLOC(struct CRestriction); //XXX
1152 offset = parse_CRestriction(tvb, offset, tree, pad_tree,
1153 v->u.RTNot, "CRestriction");
1154 break;
1156 case RTProperty:
1158 v->u.RTProperty = EP_ALLOC(struct CPropertyRestriction); //XXX
1159 offset = parse_CPropertyRestriction(tvb, offset, tree, pad_tree,
1160 v->u.RTProperty, "CPropertyRestriction");
1161 break;
1163 case RTCoerce_Add:
1164 case RTCoerce_Multiply:
1165 case RTCoerce_Absolute:
1167 v->u.RTCoerce_Add = EP_ALLOC(struct CCoercionRestriction); //XXX
1168 offset = parse_CCoercionRestriction(tvb, offset, tree, pad_tree,
1169 v->u.RTCoerce_Add, "CCoercionRestriction");
1170 break;
1172 case RTContent: {
1173 v->u.RTContent = EP_ALLOC(struct CContentRestriction); //XXX
1174 offset = parse_CContentRestriction(tvb, offset, tree, pad_tree,
1175 v->u.RTContent, "CContentRestriction");
1176 break;
1178 case RTReuseWhere: {
1179 v->u.RTReuseWhere = EP_ALLOC(struct CReuseWhere); //XXX
1180 offset = parse_CReuseWhere(tvb, offset, tree, pad_tree,
1181 v->u.RTReuseWhere, "CReuseWhere");
1182 break;
1184 case RTNatLanguage: {
1185 v->u.RTNatLanguage = EP_ALLOC(struct CNatLanguageRestriction); //XXX
1186 offset = parse_CNatLanguageRestriction(tvb, offset, tree, pad_tree,
1187 v->u.RTNatLanguage, "CNatLanguageRestriction");
1188 break;
1190 default:
1191 fprintf(stderr, "CRestriciont 0x%08x not Supported\n", v->ulType);
1192 proto_item_append_text(item, " Not supported!");
1195 proto_item_set_end(item, tvb, offset);
1196 return offset;
1199 static int parse_CRestrictionArray(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree,
1200 const char *fmt, ...)
1202 guint8 present, count;
1204 proto_tree *tree;
1205 proto_item *item;
1206 va_list ap;
1208 va_start(ap, fmt);
1209 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1210 va_end(ap);
1211 tree = proto_item_add_subtree(item, ett_CRestrictionArray);
1213 pad_tree = tree; //XXX
1215 count = tvb_get_guint8(tvb, offset);
1216 proto_tree_add_text(tree, tvb, offset, 1, "count: %u", count);
1217 offset += 1;
1219 present = tvb_get_guint8(tvb, offset);
1220 proto_tree_add_text(tree, tvb, offset, 1, "present: %u", present);
1221 offset += 1;
1223 if (present) {
1224 unsigned i;
1225 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCRestrictionPresent");
1227 for (i=0; i<count; i++) {
1228 struct CRestriction r;
1229 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "Restriction[%d]", i);
1232 proto_item_set_end(item, tvb, offset);
1233 return offset;
1236 static int parse_CNodeRestriction(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1237 proto_tree *pad_tree, struct CNodeRestriction *v,
1238 const char *fmt, ...)
1240 proto_tree *tree;
1241 proto_item *item;
1242 unsigned i;
1243 va_list ap;
1245 va_start(ap, fmt);
1246 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1247 va_end(ap);
1248 tree = proto_item_add_subtree(item, ett_CNodeRestriction);
1250 v->cNode = tvb_get_letohl(tvb, offset);
1251 proto_tree_add_text(tree, tvb, offset, 4, "cNode: %u", v->cNode);
1252 offset += 4;
1254 for (i=0; i<v->cNode; i++) {
1255 struct CRestriction r;
1256 ZERO_STRUCT(r);
1257 // offset = parse_padding(tvb, offset, 4, tree, "padding_paNode[%u]", i); /*at begin or end of loop ????*/
1258 offset = parse_CRestriction(tvb, offset, tree, pad_tree, &r, "paNode[%u]", i);
1259 offset = parse_padding(tvb, offset, 4, tree, "padding_paNode[%u]", i); /*at begin or end of loop ????*/
1261 // offset = parse_padding(tvb, offset, 4, pad_tree, "paNode[%u]", i); /*at begin or end of loop ????*/
1264 proto_item_set_end(item, tvb, offset);
1265 return offset;
1269 /*****************************************************************************************/
1271 static int vvalue_tvb_get0(tvbuff_t *tvb _U_, int offset _U_, void *val _U_)
1273 return 0;
1276 static int vvalue_tvb_get1(tvbuff_t *tvb, int offset, void *val)
1278 guint8 *ui1 = (guint8*)val;
1279 *ui1 = tvb_get_guint8(tvb, offset);
1280 return 1;
1283 static int vvalue_tvb_get2(tvbuff_t *tvb , int offset, void *val)
1285 guint16 *ui2 = (guint16*)val;
1286 *ui2 = tvb_get_letohs(tvb, offset);
1287 return 2;
1290 static int vvalue_tvb_get4(tvbuff_t *tvb , int offset, void *val)
1292 guint32 *ui4 = (guint32*)val;
1293 *ui4 = tvb_get_letohl(tvb, offset);
1294 return 4;
1297 static int vvalue_tvb_get8(tvbuff_t *tvb , int offset, void *val)
1299 guint64 *ui8 = (guint64*)val;
1300 *ui8 = tvb_get_letoh64(tvb, offset);
1301 return 8;
1304 static int vvalue_tvb_blob(tvbuff_t *tvb , int offset, void *val)
1306 struct data_blob *blob = (struct data_blob*)val;
1307 guint32 len = tvb_get_letohl(tvb, offset);
1308 const guint8 *data = tvb_get_ptr(tvb, offset + 4, len);
1310 blob->size = len;
1311 blob->data = (guint8*)se_memdup(data, len);
1313 return 4 + len;
1316 static int vvalue_tvb_bstr(tvbuff_t *tvb , int offset, void *val)
1318 struct data_str *str = (struct data_str*)val;
1319 guint32 len = tvb_get_letohl(tvb, offset);
1320 const gchar *ptr = (const gchar*)tvb_get_ptr(tvb, offset + 4, len);
1322 //XXX this might be UTF-16
1323 str->len = len;
1324 str->str = se_strndup(ptr, len);
1325 return 4 + len;
1328 static int vvalue_tvb_lpstr(tvbuff_t *tvb , int offset, void *val)
1330 struct data_str *str = (struct data_str*)val;
1331 gint len;
1333 str->len = tvb_get_letohl(tvb, offset);
1334 str->str = tvb_get_stringz(wmem_packet_scope(), tvb, offset + 4, &len);
1335 /* XXX test str->len == len */
1336 return 4 + len;
1339 static int vvalue_tvb_lpwstr(tvbuff_t *tvb , int offset, void *val)
1341 struct data_str *str = (struct data_str*)val;
1342 gint len;
1343 const gchar *ptr;
1345 str->len = tvb_get_letohl(tvb, offset);
1347 ptr = tvb_get_unicode_stringz(wmem_packet_scope(), tvb, offset + 4, &len, ENC_LITTLE_ENDIAN);
1348 str->str = se_strdup (ptr);
1350 return 4 + len;
1353 static int vvalue_tvb_vector_internal(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type, int num)
1355 const int offset_in = offset;
1356 const gboolean varsize = (type->size == -1);
1357 const int elsize = varsize ? (int)sizeof(struct data_blob) : type->size;
1358 guint8 *data = (guint8*)se_alloc(elsize * num);
1359 int len, i;
1361 val->len = num;
1362 val->u.vt_ui1 = data;
1363 DISSECTOR_ASSERT((void*)&val->u == ((void*)&val->u.vt_ui1));
1365 for (i=0; i<num; i++) {
1366 len = type->tvb_get(tvb, offset, data);
1367 data += elsize;
1368 offset += len;
1369 if (varsize && (offset % 4) ) { /* at begin or end of loop ??? */
1370 int padding = 4 - (offset % 4);
1371 offset += padding;
1374 return offset - offset_in;
1377 static int vvalue_tvb_vector(tvbuff_t *tvb , int offset, struct vt_vector *val, struct vtype *type)
1379 const int num = tvb_get_letohl(tvb, offset);
1380 return 4 + vvalue_tvb_vector_internal(tvb , offset+4, val, type, num);
1383 static void vvalue_strbuf_append_null(emem_strbuf_t *strbuf _U_, void *ptr _U_)
1386 static void vvalue_strbuf_append_i1(emem_strbuf_t *strbuf, void *ptr)
1388 gint8 i1 = *(gint8*)ptr;
1389 ep_strbuf_append_printf(strbuf, "%d", (int)i1);
1392 static void vvalue_strbuf_append_i2(emem_strbuf_t *strbuf, void *ptr)
1394 gint16 i2 = *(gint16*)ptr;
1395 ep_strbuf_append_printf(strbuf, "%d", (int)i2);
1398 static void vvalue_strbuf_append_i4(emem_strbuf_t *strbuf, void *ptr)
1400 gint32 i4 = *(gint32*)ptr;
1401 ep_strbuf_append_printf(strbuf, "%d", i4);
1404 static void vvalue_strbuf_append_i8(emem_strbuf_t *strbuf, void *ptr)
1406 gint64 i8 = *(gint64*)ptr;
1407 ep_strbuf_append_printf(strbuf, "%ld", i8);
1410 static void vvalue_strbuf_append_ui1(emem_strbuf_t *strbuf, void *ptr)
1412 guint8 ui1 = *(guint8*)ptr;
1413 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui1);
1416 static void vvalue_strbuf_append_ui2(emem_strbuf_t *strbuf, void *ptr)
1418 guint16 ui2 = *(guint16*)ptr;
1419 ep_strbuf_append_printf(strbuf, "%u", (unsigned)ui2);
1422 static void vvalue_strbuf_append_ui4(emem_strbuf_t *strbuf, void *ptr)
1424 guint32 ui4 = *(guint32*)ptr;
1425 ep_strbuf_append_printf(strbuf, "%d", ui4);
1428 static void vvalue_strbuf_append_ui8(emem_strbuf_t *strbuf, void *ptr)
1430 guint64 ui8 = *(guint64*)ptr;
1431 ep_strbuf_append_printf(strbuf, "%lu", ui8);
1434 static void vvalue_strbuf_append_r4(emem_strbuf_t *strbuf, void *ptr)
1436 float r4 = *(float*)ptr;
1437 ep_strbuf_append_printf(strbuf, "%g", (double)r4);
1440 static void vvalue_strbuf_append_r8(emem_strbuf_t *strbuf, void *ptr)
1442 double r8 = *(double*)ptr;
1443 ep_strbuf_append_printf(strbuf, "%g", r8);
1446 static void vvalue_strbuf_append_str(emem_strbuf_t *strbuf, void *ptr)
1448 struct data_str *str = (struct data_str*)ptr;
1449 ep_strbuf_append_printf(strbuf, "\"%s\"", str->str);
1452 static void vvalue_strbuf_append_blob(emem_strbuf_t *strbuf, void *ptr)
1454 struct data_blob *blob = (struct data_blob*)ptr;
1455 ep_strbuf_append_printf(strbuf, "size: %d", (int)blob->size);
1458 static void vvalue_strbuf_append_bool(emem_strbuf_t *strbuf, void *ptr)
1460 guint16 val = *(guint*)ptr;
1461 switch (val) {
1462 case 0:
1463 ep_strbuf_append(strbuf, "False");
1464 break;
1465 case 0xffff:
1466 ep_strbuf_append(strbuf, "True");
1467 break;
1468 default:
1469 ep_strbuf_append_printf(strbuf, "Invalid (0x%4x)", val);
1473 static void vvalue_strbuf_append_vector(emem_strbuf_t *strbuf, struct vt_vector val, struct vtype *type)
1475 const int elsize = (type->size == -1) ? (int)sizeof(struct data_blob) : type->size;
1476 unsigned i;
1477 guint8 *data = val.u.vt_ui1;
1478 ep_strbuf_append_c(strbuf, '[');
1479 for (i=0; i<val.len; i++) {
1480 if (i>0) {
1481 ep_strbuf_append_c(strbuf, ',');
1483 type->strbuf_append(strbuf, data);
1484 data += elsize;
1486 ep_strbuf_append_c(strbuf, ']');
1490 static struct vtype VT_TYPE[] = {
1491 {VT_EMPTY, "VT_EMPTY", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
1492 {VT_NULL, "VT_NULL", 0, vvalue_tvb_get0, vvalue_strbuf_append_null},
1493 {VT_I2, "VT_I2", 2, vvalue_tvb_get2, vvalue_strbuf_append_i2},
1494 {VT_I4, "VT_I4", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
1495 {VT_R4, "VT_R4", 4, vvalue_tvb_get4, vvalue_strbuf_append_r4},
1496 {VT_R8, "VT_R8", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
1497 {VT_CY, "VT_CY", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1498 {VT_DATE, "VT_DATE", 8, vvalue_tvb_get8, vvalue_strbuf_append_r8},
1499 // {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_bstr, vvalue_strbuf_append_str},
1500 {VT_BSTR, "VT_BSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
1501 {VT_ERROR, "VT_ERROR", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1502 {VT_BOOL, "VT_BOOL", 2, vvalue_tvb_get2, vvalue_strbuf_append_bool},
1503 {VT_VARIANT, "VT_VARIANT", -1, NULL, NULL},
1504 {VT_DECIMAL, "VT_DECIMAL", 16, NULL, NULL},
1505 {VT_I1, "VT_I1", 1, vvalue_tvb_get1, vvalue_strbuf_append_i1},
1506 {VT_UI1, "VT_UI1", 1, vvalue_tvb_get1, vvalue_strbuf_append_ui1},
1507 {VT_UI2, "VT_UI2", 2, vvalue_tvb_get2, vvalue_strbuf_append_ui2},
1508 {VT_UI4, "VT_UI4", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1509 {VT_I8, "VT_I8", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1510 {VT_UI8, "VT_UI8", 8, vvalue_tvb_get8, vvalue_strbuf_append_ui8},
1511 {VT_INT, "VT_INT", 4, vvalue_tvb_get4, vvalue_strbuf_append_i4},
1512 {VT_UINT, "VT_UINT", 4, vvalue_tvb_get4, vvalue_strbuf_append_ui4},
1513 {VT_LPSTR, "VT_LPSTR", -1, vvalue_tvb_lpstr, vvalue_strbuf_append_str},
1514 {VT_LPWSTR, "VT_LPWSTR", -1, vvalue_tvb_lpwstr, vvalue_strbuf_append_str},
1515 {VT_COMPRESSED_LPWSTR, "VT_COMPRESSED_LPWSTR", -1, NULL, vvalue_strbuf_append_str},
1516 {VT_FILETIME, "VT_FILETIME", 8, vvalue_tvb_get8, vvalue_strbuf_append_i8},
1517 {VT_BLOB, "VT_BLOB", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
1518 {VT_BLOB_OBJECT, "VT_BLOB_OBJECT", -1, vvalue_tvb_blob, vvalue_strbuf_append_blob},
1519 {VT_CLSID, "VT_CLSID", 16, NULL, NULL},
1522 static struct vtype *vType_get_type(enum vType t) {
1523 unsigned i;
1524 t = (enum vType)(t & 0xFF);
1525 for (i=0; i<array_length(VT_TYPE); i++) {
1526 if (t == VT_TYPE[i].tag) {
1527 return &VT_TYPE[i];
1530 return NULL;
1533 static const char *str_CBaseStorageVariant(struct CBaseStorageVariant *value, gboolean print_type)
1536 emem_strbuf_t *strbuf = ep_strbuf_new(NULL);
1537 if (value == NULL) {
1538 return "<NULL>";
1541 if (value->type == NULL) {
1542 return "<??""?>";
1545 if (print_type) {
1546 ep_strbuf_append(strbuf, value->type->str);
1548 if (value->vType & 0xFF00) {
1549 ep_strbuf_append_printf(strbuf, "[%d]", value->vValue.vt_vector.len);
1551 ep_strbuf_append(strbuf, ": ");
1554 switch (value->vType & 0xFF00) {
1555 case 0:
1556 value->type->strbuf_append(strbuf, &value->vValue);
1557 break;
1558 case VT_ARRAY:
1559 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_array.vData, value->type);
1560 break;
1561 case VT_VECTOR:
1562 vvalue_strbuf_append_vector(strbuf, value->vValue.vt_vector, value->type);
1563 break;
1564 default:
1565 ep_strbuf_append(strbuf, "Invalid");
1568 return strbuf->str;
1571 static int parse_CBaseStorageVariant(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree _U_,
1572 struct CBaseStorageVariant *value, const char *text)
1574 int i, len;
1575 proto_item *ti, *ti_type, *ti_val;
1576 proto_tree *tree, *tr;
1577 // enum vType baseType;
1578 enum vType highType;
1580 ZERO_STRUCT(*value);
1582 ti = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1583 tree = proto_item_add_subtree(ti, ett_CBaseStorageVariant);
1585 value->vType = (enum vType)tvb_get_letohs(tvb, offset);
1586 value->type = vType_get_type(value->vType);
1588 ti_type = proto_tree_add_text(tree, tvb, offset, 2, "vType: %s", value->type->str);
1589 offset += 2;
1591 value->vData1 = tvb_get_guint8(tvb, offset);
1592 proto_tree_add_text(tree, tvb, offset, 1, "vData1: %d", value->vData1);
1593 offset += 1;
1595 value->vData2 = tvb_get_guint8(tvb, offset);
1596 proto_tree_add_text(tree, tvb, offset, 1, "vData2: %d", value->vData2);
1597 offset += 1;
1599 // baseType = (enum vType)(value->vType & 0x00FF);
1600 highType = (enum vType)(value->vType & 0xFF00);
1602 if (value->type == NULL) {
1603 goto not_supported;
1606 ti_val = proto_tree_add_text(tree, tvb, offset, 0, "vValue");
1608 switch (highType) {
1609 case VT_EMPTY:
1610 len = value->type->tvb_get(tvb, offset, &value->vValue.vt_single);
1611 offset += len;
1612 break;
1613 case VT_VECTOR:
1614 proto_item_append_text(ti_type, "|VT_VECTOR");
1615 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Vector);
1617 len = vvalue_tvb_vector(tvb, offset, &value->vValue.vt_vector, value->type);
1618 proto_tree_add_text(tr, tvb, offset, 4, "num: %d", value->vValue.vt_vector.len);
1619 offset += len;
1620 break;
1621 case VT_ARRAY: {
1622 guint16 cDims, fFeatures;
1623 guint32 cbElements, cElements, lLbound;
1624 int num = 1;
1626 proto_item_append_text(ti_type, "|VT_ARRAY");
1627 tr = proto_item_add_subtree(ti_val, ett_CBaseStorageVariant_Array);
1629 cDims = tvb_get_letohs(tvb, offset);
1630 proto_tree_add_text(tr, tvb, offset, 2, "cDims: %d", cDims);
1631 offset += 2;
1633 fFeatures = tvb_get_letohs(tvb, offset);
1634 proto_tree_add_text(tr, tvb, offset, 2, "fFeaturess: %d", fFeatures);
1635 offset += 2;
1637 cbElements = tvb_get_letohl(tvb, offset);
1638 proto_tree_add_text(tr, tvb, offset, 4, "cbElements: %d", cbElements);
1639 offset += 4;
1640 for (i=0; i<cDims; i++) {
1641 cElements = tvb_get_letohl(tvb, offset);
1642 lLbound = tvb_get_letohl(tvb, offset + 4);
1643 proto_tree_add_text(tr, tvb, offset, 8, "Rgsabound[%d]: (%d:%d)", i, cElements, lLbound);
1644 offset += 8;
1645 num *= cElements;
1648 len = vvalue_tvb_vector_internal(tvb , offset, &value->vValue.vt_array.vData, value->type, num);
1649 offset += len;
1650 break;
1652 default:
1653 proto_item_append_text(ti_type, "|0x%x", highType);
1655 proto_item_set_end(ti, tvb, offset);
1656 proto_item_set_end(ti_val, tvb, offset);
1658 proto_item_append_text(ti_val, " %s", str_CBaseStorageVariant(value, false));
1659 proto_item_append_text(ti, " %s", str_CBaseStorageVariant(value, true));
1661 goto done;
1663 not_supported:
1664 proto_item_append_text(ti, ": sorry, vType %02x not handled yet!", (unsigned)value->vType);
1665 done:
1666 return offset;
1669 enum {
1670 DBKIND_GUID_NAME = 0,
1671 DBKIND_GUID_PROPID = 1
1674 static int parse_CDbColId(tvbuff_t *tvb, int offset, proto_tree *parent_tree, proto_tree *pad_tree, const char *text)
1676 guint32 eKind, ulId;
1677 e_guid_t guid;
1678 static const char *KIND[] = {"DBKIND_GUID_NAME", "DBKIND_GUID_PROPID"};
1680 proto_item *tree_item = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s", text);
1681 proto_tree *tree = proto_item_add_subtree(tree_item, ett_CDbColId);
1683 eKind = tvb_get_letohl(tvb, offset);
1684 proto_tree_add_text(tree, tvb, offset, 4, "eKind: %s (%u)", eKind < 2 ? KIND[eKind] : "???", eKind);
1685 offset += 4;
1687 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingGuidAlign");
1689 offset = parse_guid(tvb, offset, tree, &guid, "GUID");
1691 ulId = tvb_get_letohl(tvb, offset);
1692 proto_tree_add_text(tree, tvb, offset, 4, "ulId: %d", ulId);
1693 offset += 4;
1695 if (eKind == DBKIND_GUID_NAME) {
1696 char *name;
1697 int len = ulId; //*2 ???
1698 name = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, len, ENC_LITTLE_ENDIAN);
1699 proto_tree_add_text(tree, tvb, offset, len, "vString: \"%s\"", name);
1700 proto_item_append_text(tree_item, " \"%s\"", name);
1701 offset += len;
1702 } else if (eKind == DBKIND_GUID_PROPID) {
1703 proto_item_append_text(tree_item, " %08x", ulId);
1704 } else {
1705 proto_item_append_text(tree_item, "<INVALID>");
1708 proto_item_set_end(tree_item, tvb, offset);
1710 return offset;
1713 static int parse_CDbProp(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1714 proto_tree *pad_tree, struct GuidPropertySet *propset,
1715 const char *fmt, ...)
1717 static const value_string EMPTY_VS[] = {{0, NULL}};
1718 const value_string *vs = (propset && propset->id_map) ? propset->id_map : EMPTY_VS;
1719 guint32 id, opt, status;
1720 struct CBaseStorageVariant value;
1721 proto_item *item;
1722 proto_tree *tree;
1723 const char *str;
1724 va_list ap;
1726 va_start(ap, fmt);
1727 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1728 va_end(ap);
1730 tree = proto_item_add_subtree(item, ett_CDbProp);
1732 id = tvb_get_letohl(tvb, offset);
1733 str = val_to_str(id, vs, "0x%08x");
1734 proto_tree_add_text(tree, tvb, offset, 4, "Id: %s (0x%08x)", str[0] == '0' ? "" : str, id);
1735 offset += 4;
1736 proto_item_append_text(item, " Id: %s", str);
1738 opt = tvb_get_letohl(tvb, offset);
1739 proto_tree_add_text(tree, tvb, offset, 4, "Options: %08x", opt);
1740 offset += 4;
1742 status = tvb_get_letohl(tvb, offset);
1743 proto_tree_add_text(tree, tvb, offset, 4, "Status: %08x", status);
1744 offset += 4;
1746 offset = parse_CDbColId(tvb, offset, tree, pad_tree, "colid");
1748 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &value, "vValue");
1750 str = str_CBaseStorageVariant(&value, true);
1751 proto_item_append_text(item, " %s", str);
1752 proto_item_set_end(item, tvb, offset);
1754 return offset;
1757 static int parse_CDbPropSet(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1758 proto_tree *pad_tree, const char *fmt, ...)
1760 int i, num;
1761 e_guid_t guid;
1762 struct GuidPropertySet *pset;
1763 proto_item *item;
1764 proto_tree *tree;
1765 va_list ap;
1767 va_start(ap, fmt);
1768 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1769 va_end(ap);
1771 tree = proto_item_add_subtree(item, ett_CDbPropSet);
1773 offset = parse_guid(tvb, offset, tree, &guid, "guidPropertySet");
1775 pset = GuidPropertySet_find_guid(&guid);
1777 if (pset) {
1778 proto_item_append_text(item, " \"%s\" (%s)", pset->desc, pset->def);
1779 } else {
1780 const char *guid_str = guid_to_str(&guid);
1781 proto_item_append_text(item, " {%s}", guid_str);
1784 offset = parse_padding(tvb, offset, 4, pad_tree, "guidPropertySet");
1786 num = tvb_get_letohl(tvb, offset);
1787 proto_tree_add_text(tree, tvb, offset, 4, "cProperties: %d", num);
1788 offset += 4;
1789 proto_item_append_text(item, " Num: %d", num);
1791 for (i = 0; i<num; i++) {
1792 offset = parse_padding(tvb, offset, 4, pad_tree, "aProp[%d]", i);
1793 offset = parse_CDbProp(tvb, offset, tree, pad_tree, pset, "aProp[%d]", i);
1796 proto_item_set_end(item, tvb, offset);
1797 return offset;
1800 static int parse_PropertySetArray(tvbuff_t *tvb, int offset, int size_offset,
1801 proto_tree *parent_tree, proto_tree *pad_tree,
1802 const char *fmt, ...)
1804 const int offset_in = offset;
1805 guint32 size, num;
1806 int i;
1807 proto_tree *tree;
1808 proto_item *item;
1809 va_list ap;
1811 va_start(ap, fmt);
1812 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1813 va_end(ap);
1815 tree = proto_item_add_subtree(item, ett_CDbPropSet_Array);
1817 size = tvb_get_letohl(tvb, size_offset);
1818 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_Blob1, tvb,
1819 size_offset, 4, ENC_LITTLE_ENDIAN);
1821 num = tvb_get_letohl(tvb, offset);
1822 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_PropSets_num, tvb,
1823 offset, 4, ENC_LITTLE_ENDIAN);
1824 offset += 4;
1826 for (i = 0; i < (int)num; i++) {
1827 offset = parse_CDbPropSet(tvb, offset, tree, pad_tree, "PropertySet[%d]", i);
1830 proto_item_set_end(item, tvb, offset);
1831 DISSECTOR_ASSERT(offset - offset_in == (int)size);
1832 return offset;
1835 int parse_CColumnSet(tvbuff_t *tvb, int offset, proto_tree *tree, const char *fmt, ...)
1837 guint32 count, v, i;
1838 proto_item *item;
1840 va_list ap;
1842 va_start(ap, fmt);
1843 item = proto_tree_add_text_valist(tree, tvb, offset, 0, fmt, ap);
1844 va_end(ap);
1846 count = tvb_get_letohl(tvb, offset);
1847 offset += 4;
1849 proto_item_append_text(item, " Count %u [", count);
1850 for (i=0; i<count; i++) {
1851 v = tvb_get_letohl(tvb, offset);
1852 offset += 4;
1853 if (i>0) {
1854 proto_item_append_text(item, ",%u", v);
1855 } else {
1856 proto_item_append_text(item, "%u", v);
1859 proto_item_append_text(item, "]");
1860 return offset;
1863 /* 2.2.1.23 RANGEBOUNDARY */
1864 int parse_RANGEBOUNDARY(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1865 proto_tree *pad_tree, const char *fmt, ...)
1867 guint32 ulType;
1868 guint8 labelPresent;
1869 proto_item *item;
1870 proto_tree *tree;
1871 struct CBaseStorageVariant prval;
1872 va_list ap;
1874 va_start(ap, fmt);
1875 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1876 tree = proto_item_add_subtree(item, ett_RANGEBOUNDARY);
1877 va_end(ap);
1879 ulType = tvb_get_letohl(tvb, offset);
1880 proto_tree_add_text(tree, tvb, offset, 4, "ulType 0x%08x", ulType);
1881 proto_item_append_text(item, ": Type 0x%08x", ulType);
1882 offset += 4;
1884 ZERO_STRUCT(prval);
1885 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &prval, "prVal");
1887 labelPresent = tvb_get_guint8(tvb, offset);
1888 proto_tree_add_text(tree, tvb, offset, 1, "labelPresent: %s", labelPresent ? "True" : "False");
1889 offset += 1;
1891 if (labelPresent) {
1892 guint32 ccLabel;
1893 const char *label;
1894 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingLabelPresent");
1896 ccLabel = tvb_get_letohl(tvb, offset);
1897 proto_tree_add_text(tree, tvb, offset, 4, "ccLabel: %u", ccLabel);
1898 offset += 4;
1900 label = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, 2*ccLabel, ENC_LITTLE_ENDIAN);
1901 proto_tree_add_text(tree, tvb, offset, 2*ccLabel, "Label: \"%s\"", label);
1902 proto_item_append_text(item, " Label: \"%s\"", label);
1903 offset += 2*ccLabel;
1906 proto_item_append_text(item, " Val: %s", str_CBaseStorageVariant(&prval, true));
1908 proto_item_set_end(item, tvb, offset);
1909 return offset;
1913 /* 2.2.1.22 CRangeCategSpec */
1914 int parse_CRangeCategSpec(tvbuff_t *tvb, int offset,
1915 proto_tree *parent_tree, proto_tree *pad_tree,
1916 const char *fmt, ...)
1918 proto_item *item;
1919 proto_tree *tree;
1920 va_list ap;
1921 unsigned i;
1922 guint32 cRange;
1924 va_start(ap, fmt);
1925 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1926 tree = proto_item_add_subtree(item, ett_CRangeCategSpec);
1927 va_end(ap);
1929 offset = parse_lcid(tvb, offset, tree, "lcid");
1931 cRange = tvb_get_letohl(tvb, offset);
1932 proto_tree_add_text(tree, tvb, offset, 4, "cRange 0x%08x", cRange);
1933 offset += 4;
1935 for (i=0; i<cRange; i++) {
1936 offset = parse_RANGEBOUNDARY(tvb, offset, tree, pad_tree, "aRangeBegin[%u]", i);
1940 proto_item_set_end(item, tvb, offset);
1941 return offset;
1944 /* 2.2.1.21 CCategSpec */
1945 int parse_CCategSpec(tvbuff_t *tvb, int offset,
1946 proto_tree *parent_tree, proto_tree *pad_tree,
1947 const char *fmt, ...)
1949 proto_item *item;
1950 proto_tree *tree;
1952 va_list ap;
1953 guint32 type;
1955 va_start(ap, fmt);
1956 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1957 tree = proto_item_add_subtree(item, ett_CCategSpec);
1958 va_end(ap);
1960 type = tvb_get_letohl(tvb, offset);
1961 proto_tree_add_text(tree, tvb, offset, 4, "Type 0x%08x", type);
1962 proto_item_append_text(item, " Type %u", type);
1963 offset += 4;
1965 offset = parse_CSort(tvb, offset, tree, pad_tree, "CSort");
1967 offset = parse_CRangeCategSpec(tvb, offset, tree, pad_tree, "CRangeCategSpec");
1969 proto_item_set_end(item, tvb, offset);
1970 return offset;
1973 /* 2.2.1.25 CAggregSpec */
1974 static int parse_CAggregSpec(tvbuff_t *tvb, int offset,
1975 proto_tree *parent_tree, proto_tree *pad_tree,
1976 const char *fmt, ...)
1978 proto_item *item;
1979 proto_tree *tree;
1980 va_list ap;
1981 guint8 type;
1982 guint32 ccAlias, idColumn;//, ulMaxNumToReturn, idRepresentative;
1983 const char *alias;
1985 va_start(ap, fmt);
1986 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
1987 tree = proto_item_add_subtree(item, ett_CAggregSpec);
1988 va_end(ap);
1990 type = tvb_get_guint8(tvb, offset);
1991 proto_tree_add_text(tree, tvb, offset, 1, "type: %u", type);
1992 proto_item_append_text(item, "type: %u", type);
1993 offset += 1;
1995 offset = parse_padding(tvb, offset, 4, pad_tree, "padding");
1997 ccAlias = tvb_get_letohl(tvb, offset);
1998 proto_tree_add_text(tree, tvb, offset, 1, "ccAlias: %u", ccAlias);
1999 offset += 4;
2001 alias = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, 2*ccAlias, ENC_LITTLE_ENDIAN);
2002 proto_tree_add_text(tree, tvb, offset, 2*ccAlias, "Alias: %s", alias);
2003 offset += 2*ccAlias;
2005 idColumn = tvb_get_letohl(tvb, offset);
2006 proto_tree_add_text(tree, tvb, offset, 1, "idColumn: %u", idColumn);
2007 offset += 4;
2008 /* Optional ???
2009 ulMaxNumToReturn, idRepresentative;
2011 fprintf(stderr, "WARNING, dont know if optional members are present!\n ");
2013 proto_item_set_end(item, tvb, offset);
2014 return offset;
2017 /* 2.2.1.24 CAggregSet */
2018 static int parse_CAggregSet(tvbuff_t *tvb, int offset,
2019 proto_tree *parent_tree, proto_tree *pad_tree,
2020 const char *fmt, ...)
2022 guint32 cCount, i;
2023 proto_item *item;
2024 proto_tree *tree;
2026 va_list ap;
2028 va_start(ap, fmt);
2029 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2030 tree = proto_item_add_subtree(item, ett_CAggregSet);
2031 va_end(ap);
2033 cCount = tvb_get_letohl(tvb, offset);
2034 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
2035 offset += 4;
2037 for (i=0; i<cCount; i++) {
2038 /* 2.2.1.25 CAggregSpec */
2039 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "AggregSpecs[%u]", i);
2042 proto_item_set_end(item, tvb, offset);
2043 return offset;
2046 /* 2.2.1.27 CAggregSortKey */
2047 static int parse_CAggregSortKey(tvbuff_t *tvb, int offset,
2048 proto_tree *parent_tree, proto_tree *pad_tree,
2049 const char *fmt, ...)
2051 guint32 order;
2052 proto_item *item;
2053 proto_tree *tree;
2055 va_list ap;
2057 va_start(ap, fmt);
2058 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2059 tree = proto_item_add_subtree(item, ett_CAggregSortKey);
2060 va_end(ap);
2062 order = tvb_get_letohl(tvb, offset);
2063 proto_tree_add_text(tree, tvb, offset, 4, "order: %u", order);
2064 offset += 4;
2066 offset = parse_CAggregSpec(tvb, offset, tree, pad_tree, "ColumnSpec");
2068 proto_item_set_end(item, tvb, offset);
2069 return offset;
2073 /* 2.2.1.26 CSortAggregSet */
2074 static int parse_CSortAggregSet(tvbuff_t *tvb, int offset,
2075 proto_tree *parent_tree, proto_tree *pad_tree,
2076 const char *fmt, ...)
2078 guint32 cCount, i;
2079 proto_item *item;
2080 proto_tree *tree;
2082 va_list ap;
2084 va_start(ap, fmt);
2085 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2086 tree = proto_item_add_subtree(item, ett_CSortAggregSet);
2087 va_end(ap);
2089 cCount = tvb_get_letohl(tvb, offset);
2090 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
2091 offset += 4;
2093 for (i=0; i<cCount; i++) {
2094 /* 2.2.1.27 CAggregSortKey */
2095 offset = parse_CAggregSortKey(tvb, offset, tree, pad_tree, "SortKeys[%u]", i);
2098 proto_item_set_end(item, tvb, offset);
2099 return offset;
2102 enum CInGroupSortAggregSet_type {
2103 GroupIdDefault = 0x00, /* The default for all ranges. */
2104 GroupIdMinValue = 0x01, /*The first range in the parent's group.*/
2105 GroupIdNull = 0x02, /*The last range in the parent's group.*/
2106 GroupIdValue = 0x03,
2109 /* 2.2.1.29 CInGroupSortAggregSet */
2110 static int parse_CInGroupSortAggregSet(tvbuff_t *tvb, int offset,
2111 proto_tree *parent_tree, proto_tree *pad_tree,
2112 const char *fmt, ...)
2114 proto_item *item;
2115 proto_tree *tree;
2116 va_list ap;
2117 enum CInGroupSortAggregSet_type type;
2119 va_start(ap, fmt);
2120 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2121 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSet);
2122 va_end(ap);
2124 type = (enum CInGroupSortAggregSet_type)tvb_get_guint8(tvb, offset);
2125 proto_tree_add_text(tree, tvb, offset, 1, "Type: 0x%02x", (unsigned)type);
2126 offset += 1;
2128 offset = parse_padding(tvb, offset, 4, pad_tree, "CInGroupSortAggregSet");
2130 if (type == GroupIdValue) {
2131 struct CBaseStorageVariant id;
2132 offset = parse_CBaseStorageVariant(tvb, offset, tree, pad_tree, &id, "inGroupId");
2135 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
2137 proto_item_set_end(item, tvb, offset);
2138 return offset;
2142 /* 2.2.1.28 CInGroupSortAggregSets */
2143 static int parse_CInGroupSortAggregSets(tvbuff_t *tvb, int offset,
2144 proto_tree *parent_tree, proto_tree *pad_tree,
2145 const char *fmt, ...)
2147 guint32 cCount, i;
2148 proto_item *item;
2149 proto_tree *tree;
2151 va_list ap;
2153 va_start(ap, fmt);
2154 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2155 tree = proto_item_add_subtree(item, ett_CInGroupSortAggregSets);
2156 va_end(ap);
2158 cCount = tvb_get_letohl(tvb, offset);
2159 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", cCount);
2160 offset += 4;
2162 for (i=0; i<cCount; i++) {
2163 /* 2.2.1.29 CInGroupSortAggregSet */
2164 offset = parse_CInGroupSortAggregSet(tvb, offset, tree, pad_tree, "SortSets[%u]", i);
2167 proto_item_set_end(item, tvb, offset);
2168 return offset;
2171 /* 2.2.1.20 CCategorizationSpec */
2172 int parse_CCategorizationSpec(tvbuff_t *tvb, int offset,
2173 proto_tree *parent_tree, proto_tree *pad_tree,
2174 const char *fmt, ...)
2176 guint32 cMaxResults;
2177 proto_item *item;
2178 proto_tree *tree;
2180 va_list ap;
2182 va_start(ap, fmt);
2183 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2184 tree = proto_item_add_subtree(item, ett_CCategorizationSpec);
2185 va_end(ap);
2187 /* 2.2.1.18 CColumnSet */
2188 offset = parse_CColumnSet(tvb, offset, tree, "csColumns");
2190 /* 2.2.1.21 CCategSpec */
2191 offset = parse_CCategSpec(tvb, offset, tree, pad_tree, "Spec");
2193 /* 2.2.1.24 CAggregSet */
2194 offset = parse_CAggregSet(tvb, offset, tree, pad_tree, "AggregSet");
2196 /* 2.2.1.26 CSortAggregSet */
2197 offset = parse_CSortAggregSet(tvb, offset, tree, pad_tree, "SortAggregSet");
2199 /* 2.2.1.28 CInGroupSortAggregSets */
2200 offset = parse_CInGroupSortAggregSets(tvb, offset, tree, pad_tree, "InGroupSortAggregSets");
2202 cMaxResults = tvb_get_letohl(tvb, offset);
2203 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", cMaxResults);
2204 offset += 4;
2206 proto_item_set_end(item, tvb, offset);
2207 return offset;
2210 int parse_CRowsetProperties(tvbuff_t *tvb, int offset,
2211 proto_tree *parent_tree, proto_tree *pad_tree _U_,
2212 const char *fmt, ...)
2214 guint32 opt, maxres, timeout;
2215 proto_item *item;
2216 proto_tree *tree;
2218 va_list ap;
2220 va_start(ap, fmt);
2221 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2222 tree = proto_item_add_subtree(item, ett_CRowsetProperties);
2223 va_end(ap);
2225 opt = tvb_get_letohl(tvb, offset);
2226 proto_tree_add_text(tree, tvb, offset, 4, "uBooleanOptions: 0x%08x", opt);
2227 offset += 4;
2229 proto_tree_add_text(tree, tvb, offset, 4, "ulMaxOpenRows (ignored)");
2230 offset += 4;
2232 proto_tree_add_text(tree, tvb, offset, 4, "ulMemoryUsage (ignored)");
2233 offset += 4;
2235 maxres = tvb_get_letohl(tvb, offset);
2236 proto_tree_add_text(tree, tvb, offset, 4, "cMaxResults: %u", maxres);
2237 offset += 4;
2239 timeout = tvb_get_letohl(tvb, offset);
2240 proto_tree_add_text(tree, tvb, offset, 4, "cCmdTimeout: %u", timeout);
2241 offset += 4;
2243 proto_item_set_end(item, tvb, offset);
2244 return offset;
2247 int parse_CPidMapper(tvbuff_t *tvb, int offset,
2248 proto_tree *parent_tree, proto_tree *pad_tree,
2249 const char *fmt, ...)
2251 proto_item *item;
2252 proto_tree *tree;
2253 va_list ap;
2254 guint32 count, i;
2256 va_start(ap, fmt);
2257 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2258 tree = proto_item_add_subtree(item, ett_CPidMapper);
2259 va_end(ap);
2261 count = tvb_get_letohl(tvb, offset);
2262 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
2263 offset += 4;
2265 offset = parse_padding(tvb, offset, 8, pad_tree, "CPidMapper_PropSpec");
2267 for (i=0; i<count; i++) {
2268 struct CFullPropSpec v;
2269 ZERO_STRUCT(v);
2270 offset = parse_padding(tvb, offset, 4, pad_tree,
2271 "CPidMapper_PropSpec[%u]", i); //at begin or end of loop???
2272 offset = parse_CFullPropSpec(tvb, offset, tree, pad_tree, &v, "PropSpec[%u]", i);
2275 proto_item_set_end(item, tvb, offset);
2276 return offset;
2279 /* 2.2.1.35 CColumnGroup */
2280 int parse_CColumnGroup(tvbuff_t *tvb, int offset,
2281 proto_tree *parent_tree, proto_tree *pad_tree _U_,
2282 const char *fmt, ...)
2284 proto_tree *tree;
2285 proto_item *item, *ti;
2286 va_list ap;
2288 guint32 count, groupPid, i;
2290 va_start(ap, fmt);
2291 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2292 va_end(ap);
2293 tree = proto_item_add_subtree(item, ett_CColumnGroup);
2295 count = tvb_get_letohl(tvb, offset);
2296 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
2297 offset += 4;
2299 groupPid = tvb_get_letohl(tvb, offset);
2300 ti = proto_tree_add_text(tree, tvb, offset, 4, "groupPid: 0x%08x", groupPid);
2301 if ((0xFFFF0000 & groupPid) == 0x7FFF0000) {
2302 proto_item_append_text(ti, " Idx: %u", groupPid & 0xFFFF);
2303 } else {
2304 proto_item_append_text(ti, "<Invalid>");
2306 offset += 4;
2308 for (i=0; i<count; i++) {
2309 /* 2.2.1.36 SProperty */
2310 guint32 pid, weight;
2311 pid = tvb_get_letohl(tvb, offset);
2312 weight = tvb_get_letohl(tvb, offset + 4);
2313 proto_tree_add_text(tree, tvb, offset, 8, "Props[%u]: pid: %u weight: %u", i, pid, weight);
2314 offset += 8;
2317 proto_item_set_end(item, tvb, offset);
2318 return offset;
2321 /* 2.2.1.34 CColumnGroupArray */
2322 int parse_CColumnGroupArray(tvbuff_t *tvb, int offset,
2323 proto_tree *parent_tree, proto_tree *pad_tree,
2324 const char *fmt, ...)
2326 proto_tree *tree;
2327 proto_item *item;
2328 va_list ap;
2330 guint32 count, i;
2332 va_start(ap, fmt);
2333 item = proto_tree_add_text_valist(parent_tree, tvb, offset, 0, fmt, ap);
2334 va_end(ap);
2335 tree = proto_item_add_subtree(item, ett_CColumnGroupArray);
2337 count = tvb_get_letohl(tvb, offset);
2338 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
2339 offset += 4;
2341 for (i=0; i<count; i++) {
2342 offset = parse_padding(tvb, offset, 4, pad_tree, "aGroupArray[%u]", i);
2343 offset = parse_CColumnGroup(tvb, offset, tree, pad_tree, "aGroupArray[%u]", i);
2346 proto_item_set_end(item, tvb, offset);
2347 return offset;
2351 /* Code to actually dissect the packets */
2353 static int dissect_CPMConnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2355 proto_item *ti;
2356 proto_tree *tree;
2357 gint offset = 16;
2358 guint len;
2359 guint32 version;
2361 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2362 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
2363 proto_item_set_text(ti, "CPMConnect%s", in ? "In" : "Out");
2364 col_append_str(pinfo->cinfo, COL_INFO, "Connect");
2366 version = tvb_get_letohl(tvb, offset);
2367 ti = proto_tree_add_item(tree, hf_mswsp_msg_Connect_Version, tvb,
2368 offset, 4, ENC_LITTLE_ENDIAN);
2369 if (version & 0xffff0000) {
2370 proto_item_append_text(ti, " 64 bit");
2372 switch (version & 0xffff) {
2373 case 0x102:
2374 proto_item_append_text(ti, " w2k8 or vista");
2375 break;
2376 case 0x109:
2377 proto_item_append_text(ti, " XP or w2k3, with Windows Search 4.0");
2378 break;
2379 case 0x700:
2380 proto_item_append_text(ti, " win7 or w2k8r2");
2381 break;
2383 offset += 4;
2385 if (in) {
2386 guint32 blob_size1_off, blob_size2_off;
2387 proto_tree *pad_tree;
2389 ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
2390 pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
2392 proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_ClientIsRemote, tvb,
2393 offset, 4, ENC_LITTLE_ENDIAN);
2394 offset += 4;
2396 /* _cbBlob1 */
2397 blob_size1_off = offset;
2398 offset += 4;
2400 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcbBlob2");
2402 /* _cbBlob2 */
2403 blob_size2_off = offset;
2404 offset += 4;
2406 offset = parse_padding(tvb, offset, 16, pad_tree, "_padding");
2408 len = tvb_unicode_strsize(tvb, offset);
2409 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_MachineName, tvb,
2410 offset, len, ENC_UTF_16);
2411 /*This shouldnt be necessary, is this a bug or is there some GUI setting I've missed?*/
2412 proto_item_set_text(ti, "Remote machine: %s",
2413 tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, len, ENC_LITTLE_ENDIAN));
2414 offset += len;
2416 len = tvb_unicode_strsize(tvb, offset);
2417 ti = proto_tree_add_item(tree, hf_mswsp_msg_ConnectIn_UserName, tvb,
2418 offset, len, ENC_UTF_16);
2419 proto_item_set_text(ti, "User: %s", tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, len, ENC_LITTLE_ENDIAN));
2420 offset += len;
2422 offset = parse_padding(tvb, offset, 8, pad_tree, "_paddingcPropSets");
2424 offset = parse_PropertySetArray(tvb, offset, blob_size1_off, tree, pad_tree, "PropSets");
2426 offset = parse_padding(tvb, offset, 8, pad_tree, "paddingExtPropset");
2428 offset = parse_PropertySetArray(tvb, offset, blob_size2_off, tree, pad_tree, "ExtPropset");
2430 offset = parse_padding(tvb, offset, 8, pad_tree, "???");
2432 DISSECTOR_ASSERT(offset == (int)tvb_length(tvb));
2434 /* make "Padding" the last item */
2435 proto_tree_move_item(tree, ti, proto_tree_get_parent(pad_tree));
2436 } else {
2439 return tvb_length(tvb);
2442 static int dissect_CPMDisconnect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2444 col_append_str(pinfo->cinfo, COL_INFO, "Disconnect");
2445 return tvb_length(tvb);
2448 static int dissect_CPMCreateQuery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2450 gint offset = 16;
2451 proto_item *item;
2452 proto_tree *tree;
2454 item = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2455 tree = proto_item_add_subtree(item, ett_mswsp_msg);
2457 proto_item_set_text(item, "CPMCreateQuery%s", in ? "In" : "Out");
2458 col_append_str(pinfo->cinfo, COL_INFO, "CreateQuery");
2460 if (in) {
2461 proto_item *ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
2462 proto_tree *pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
2463 guint8 CColumnSetPresent, CRestrictionPresent, CSortSetPresent, CCategorizationSetPresent;
2464 guint32 size = tvb_get_letohl(tvb, offset);
2465 proto_tree_add_text(tree, tvb, offset, 4, "size");
2466 proto_tree_add_text(tree, tvb, offset, size, "ALL");
2467 offset += 4;
2469 CColumnSetPresent = tvb_get_guint8(tvb, offset);
2470 proto_tree_add_text(tree, tvb, offset, 1, "CColumnSetPresent: %s", CColumnSetPresent ? "True" : "False");
2471 offset += 1;
2473 if (CColumnSetPresent) {
2474 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCColumnSetPresent");
2475 offset = parse_CColumnSet(tvb, offset, tree, "CColumnSet");
2478 CRestrictionPresent = tvb_get_guint8(tvb, offset);
2479 proto_tree_add_text(tree, tvb, offset, 1, "CRestrictionPresent: %s", CColumnSetPresent ? "True" : "False");
2480 offset += 1;
2481 if (CRestrictionPresent) {
2482 offset = parse_CRestrictionArray(tvb, offset, tree, pad_tree, "RestrictionArray");
2485 CSortSetPresent = tvb_get_guint8(tvb, offset);
2486 proto_tree_add_text(tree, tvb, offset, 1, "CSortSetPresent: %s", CSortSetPresent ? "True" : "False");
2487 offset += 1;
2488 if (CSortSetPresent) {
2489 offset = parse_padding(tvb, offset, 4, tree, "paddingCSortSetPresent");
2491 proto_tree_add_text(tree, tvb, offset, 8, "XXX");
2492 offset += 8;
2494 offset = parse_CSortSet(tvb, offset, tree, pad_tree, "SortSet");
2497 CCategorizationSetPresent = tvb_get_guint8(tvb, offset);
2498 proto_tree_add_text(tree, tvb, offset, 1, "CCategorizationSetPresent: %s", CCategorizationSetPresent ? "True" : "False");
2499 offset += 1;
2501 if (CCategorizationSetPresent) {
2502 guint32 count, i;
2503 offset = parse_padding(tvb, offset, 4, pad_tree, "paddingCCategorizationSetPresent");
2504 /* 2.2.1.19 CCategorizationSet */
2505 count = tvb_get_letohl(tvb, offset);
2506 proto_tree_add_text(tree, tvb, offset, 4, "count: %u", count);
2507 offset += 4;
2508 for (i=0; i<count; i++) {
2509 offset = parse_CCategorizationSpec(tvb, offset, tree, pad_tree, "categories[%u]", i);
2513 offset = parse_padding(tvb, offset, 4, tree, "XXXX"); //XXX
2515 offset = parse_CRowsetProperties(tvb, offset, tree, pad_tree, "RowSetProperties");
2517 offset = parse_CPidMapper(tvb, offset, tree, pad_tree, "PidMapper");
2519 offset = parse_CColumnGroupArray(tvb, offset, tree, pad_tree, "GroupArray");
2520 } else { /* out */
2521 proto_tree_add_text(tree, tvb, offset, 4, "TrueSequential");
2522 offset += 4;
2523 proto_tree_add_text(tree, tvb, offset, 4, "WorkIdUnique");
2524 offset += 4;
2525 proto_tree_add_text(tree, tvb, offset, -1, "Cursors");
2526 //offset += 4*(#CategorizationSet + 1);
2529 return tvb_length(tvb);
2532 static int dissect_CPMFreeCursor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2534 col_append_str(pinfo->cinfo, COL_INFO, "FreeCursor");
2535 return tvb_length(tvb);
2538 static int dissect_CPMGetRows(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2540 gint offset = 16;
2541 proto_item *item;
2542 proto_tree *tree;
2544 item = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, in ? 0 : -1, ENC_NA);
2545 tree = proto_item_add_subtree(item, ett_mswsp_msg);
2547 proto_item_set_text(item, "GetRows%s", in ? "In" : "Out");
2548 col_append_str(pinfo->cinfo, COL_INFO, "GetRows");
2550 if (in) {
2551 /* 2.2.3.11 */
2552 guint32 type;
2554 proto_tree_add_text(tree, tvb, offset, 4, "hCursor");
2555 offset += 4;
2557 proto_tree_add_text(tree, tvb, offset, 4, "cRowsToTransfer");
2558 offset += 4;
2560 proto_tree_add_text(tree, tvb, offset, 4, "cbRowWidth");
2561 offset += 4;
2563 proto_tree_add_text(tree, tvb, offset, 4, "cbSeek");
2564 offset += 4;
2566 proto_tree_add_text(tree, tvb, offset, 4, "cbReserved");
2567 offset += 4;
2569 proto_tree_add_text(tree, tvb, offset, 4, "cbReadBuffer");
2570 offset += 4;
2572 proto_tree_add_text(tree, tvb, offset, 4, "ulClientBase");
2573 offset += 4;
2575 proto_tree_add_text(tree, tvb, offset, 4, "fBwdFetch");
2576 offset += 4;
2578 type = tvb_get_letohl(tvb, offset);
2579 proto_tree_add_text(tree, tvb, offset, 4, "eType");
2580 offset += 4;
2582 proto_tree_add_text(tree, tvb, offset, 4, "chapt");
2583 offset += 4;
2585 proto_tree_add_text(tree, tvb, offset, type ? -1 : 0, "SeekDescription");
2587 } else {
2588 /* 2.2.3.12 */
2591 return tvb_length(tvb);
2594 static int dissect_CPMRatioFinished(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2596 col_append_str(pinfo->cinfo, COL_INFO, "RatioFinished");
2597 return tvb_length(tvb);
2600 static int dissect_CPMCompareBmk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2602 col_append_str(pinfo->cinfo, COL_INFO, "CompareBmk");
2603 return tvb_length(tvb);
2606 static int dissect_CPMGetApproximatePosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2608 col_append_str(pinfo->cinfo, COL_INFO, "GetApproximatePosition");
2609 return tvb_length(tvb);
2612 /* 2.2.3.10 */
2613 static int dissect_CPMSetBindings(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2615 gint offset = 16;
2617 col_append_str(pinfo->cinfo, COL_INFO, "SetBindings");
2619 if (in) {
2620 proto_item *ti;
2621 proto_tree *tree, *pad_tree;
2622 guint32 size, num, n;
2624 ti = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2625 tree = proto_item_add_subtree(ti, ett_mswsp_msg);
2627 proto_item_set_text(ti, "SetBindingsIn");
2629 ti = proto_tree_add_text(tree, tvb, offset, 0, "Padding");
2630 pad_tree = proto_item_add_subtree(ti, ett_mswsp_pad);
2632 proto_tree_add_text(tree, tvb, offset, 4, "hCursor");
2633 offset += 4;
2634 proto_tree_add_text(tree, tvb, offset, 4, "cbRow");
2635 offset += 4;
2637 size = tvb_get_letohl(tvb, offset);
2638 proto_tree_add_text(tree, tvb, offset, 4, "cbBindingDesc: %d", size);
2639 offset += 4;
2641 proto_tree_add_text(tree, tvb, offset, 4, "dummy");
2642 offset += 4;
2644 num = tvb_get_letohl(tvb, offset);
2645 proto_tree_add_text(tree, tvb, offset, 4, "cColumns: %u", num);
2646 offset += 4;
2648 proto_tree_add_text(tree, tvb, offset, size-4, "aColumns");
2649 for (n=0; n<num; n++) {
2650 offset = parse_padding(tvb, offset, 4, pad_tree, "padding_aColumns[%u]", n);
2651 offset = parse_CTableColumn(tvb, offset, tree, pad_tree, "aColumns[%u]", n);
2654 } else { /* server only returns status with header */
2657 return tvb_length(tvb);
2660 static int dissect_CPMGetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2662 col_append_str(pinfo->cinfo, COL_INFO, "GetNotify");
2663 return tvb_length(tvb);
2666 static int dissect_CPMSendNotifyOut(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2668 col_append_str(pinfo->cinfo, COL_INFO, "SendNotify");
2669 return tvb_length(tvb);
2672 static int dissect_CPMGetQueryStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2674 gint offset = 16;
2675 proto_item *item;
2676 proto_tree *tree;
2678 item = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2679 tree = proto_item_add_subtree(item, ett_mswsp_msg);
2681 proto_item_set_text(item, "GetQueryStatus%s", in ? "In" : "Out");
2682 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatus");
2684 if (in) {
2685 /* 2.2.3.7 */
2686 proto_tree_add_text(tree, tvb, offset, 4, "hCursor");
2687 offset += 4;
2688 } else {
2689 /* 2.2.3.7 */
2690 proto_tree_add_text(tree, tvb, offset, 4, "QStatus");
2691 offset += 4;
2694 return tvb_length(tvb);
2697 static int dissect_CPMCiState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2699 col_append_str(pinfo->cinfo, COL_INFO, "CiState");
2700 return tvb_length(tvb);
2703 static int dissect_CPMFetchValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2705 col_append_str(pinfo->cinfo, COL_INFO, "FetchValue");
2706 return tvb_length(tvb);
2709 static int dissect_CPMGetQueryStatusEx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2711 gint offset = 16;
2712 proto_item *item;
2713 proto_tree *tree;
2715 item = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, -1, ENC_NA);
2716 tree = proto_item_add_subtree(item, ett_mswsp_msg);
2718 proto_item_set_text(item, "GetQueryStatusEx%s", in ? "In" : "Out");
2719 col_append_str(pinfo->cinfo, COL_INFO, "GetQueryStatusEx");
2721 if (in) {
2722 /* 2.2.3.8 */
2723 proto_tree_add_text(tree, tvb, offset, 4, "hCursor");
2724 offset += 4;
2725 proto_tree_add_text(tree, tvb, offset, 4, "bmk");
2726 offset += 4;
2727 } else {
2728 /* 2.2.3.9 */
2729 proto_tree_add_text(tree, tvb, offset, 4, "QStatus");
2730 offset += 4;
2731 proto_tree_add_text(tree, tvb, offset, 4, "cFilteredDocuments");
2732 offset += 4;
2733 proto_tree_add_text(tree, tvb, offset, 4, "cDocumentsToFilter");
2734 offset += 4;
2735 proto_tree_add_text(tree, tvb, offset, 4, "dwRatioFinishedDenominator");
2736 offset += 4;
2737 proto_tree_add_text(tree, tvb, offset, 4, "dwRatioFinishedNumerator");
2738 offset += 4;
2739 proto_tree_add_text(tree, tvb, offset, 4, "iRowBmk");
2740 offset += 4;
2741 proto_tree_add_text(tree, tvb, offset, 4, "cRowsTotal");
2742 offset += 4;
2743 proto_tree_add_text(tree, tvb, offset, 4, "maxRank");
2744 offset += 4;
2745 proto_tree_add_text(tree, tvb, offset, 4, "cResultsFound");
2746 offset += 4;
2747 proto_tree_add_text(tree, tvb, offset, 4, "whereID");
2748 offset += 4;
2750 return tvb_length(tvb);
2753 static int dissect_CPMRestartPosition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2755 col_append_str(pinfo->cinfo, COL_INFO, "RestartPosition");
2756 return tvb_length(tvb);
2759 static int dissect_CPMSetCatState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2761 col_append_str(pinfo->cinfo, COL_INFO, "SetCatState");
2762 return tvb_length(tvb);
2765 static int dissect_CPMGetRowsetNotify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2767 col_append_str(pinfo->cinfo, COL_INFO, "GetRowsetNotify");
2768 return tvb_length(tvb);
2771 static int dissect_CPMFindIndices(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2773 col_append_str(pinfo->cinfo, COL_INFO, "FindIndices");
2774 return tvb_length(tvb);
2777 static int dissect_CPMSetScopePrioritization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, gboolean in _U_)
2779 col_append_str(pinfo->cinfo, COL_INFO, "SetScopePrioritization");
2780 return tvb_length(tvb);
2783 static int dissect_CPMGetScopeStatistics(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean in)
2786 gint offset = 16;
2787 proto_item *item;
2788 proto_tree *tree;
2790 item = proto_tree_add_item(parent_tree, hf_mswsp_msg, tvb, offset, in ? 0 : -1, ENC_NA);
2791 tree = proto_item_add_subtree(item, ett_mswsp_msg);
2793 proto_item_set_text(item, "GetScopeStatistics%s", in ? "In" : "Out");
2794 col_append_str(pinfo->cinfo, COL_INFO, "GetScopeStatistics");
2796 if (in) {
2797 /* 2.2.3.33 */
2798 } else {
2799 /* 2.2.3.34 */
2800 proto_tree_add_text(tree, tvb, offset, 4, "dwIndexedItems");
2801 offset += 4;
2802 proto_tree_add_text(tree, tvb, offset, 4, "dwOutstandingAdds");
2803 offset += 4;
2804 proto_tree_add_text(tree, tvb, offset, 4, "dwOustandingModifies");
2805 offset += 4;
2808 return tvb_length(tvb);
2811 static void debug_frame(int frame)
2813 static const char *dbg_wait = NULL;
2814 static int wait_frame = -1;
2816 if (dbg_wait == NULL) {
2817 dbg_wait = getenv("DBG_FRAME");
2818 if (dbg_wait == NULL) {
2819 dbg_wait = "no";
2820 } else {
2821 wait_frame = atoi(dbg_wait);
2825 if (frame == wait_frame) {
2826 static volatile gboolean wait = 1;
2827 fprintf(stderr, "waiting for debugger with pid: %u\n", getpid());
2828 while(wait) {
2829 sleep(1);
2835 static const value_string msg_ids[] = {
2836 {0x000000C8, "CPMConnect"}, /* In/Out */
2837 {0x000000C9, "CPMDisconnect"},
2838 {0x000000CA, "CPMCreateQuery"}, /* In/Out */
2839 {0x000000CB, "CPMFreeCursor"}, /* In/Out */
2840 {0x000000CC, "CPMGetRows"}, /* In/Out */
2841 {0x000000CD, "CPMRatioFinished"}, /* In/Out */
2842 {0x000000CE, "CPMCompareBmk"}, /* In/Out */
2843 {0x000000CF, "CPMGetApproximatePosition"}, /* In/Out */
2844 {0x000000D0, "CPMSetBindingsIn"},
2845 {0x000000D1, "CPMGetNotify"},
2846 {0x000000D2, "CPMSendNotifyOut"},
2847 {0x000000D7, "CPMGetQueryStatusIn"}, /* In/Out */
2848 {0x000000D9, "CPMCiStateInOut"},
2849 {0x000000E4, "CPMFetchValue"}, /* In/Out */
2850 {0x000000E7, "CPMGetQueryStatusEx"}, /* In/Out */
2851 {0x000000E8, "CPMRestartPositionIn"},
2852 {0x000000EC, "CPMSetCatStateIn"}, /* (not supported) */
2853 {0x000000F1, "CPMGetRowsetNotify"}, /* In/Out */
2854 {0x000000F2, "CPMFindIndices"}, /* In/Out */
2855 {0x000000F3, "CPMSetScopePrioritization"}, /* In/Out */
2856 {0x000000F4, "CPMGetScopeStatistics"}, /* In/Out */
2861 dissect_mswsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean in)
2863 proto_tree *mswsp_tree = NULL;
2864 struct {
2865 guint32 msg;
2866 guint32 status;
2867 guint32 checksum;
2868 guint32 reserved;
2869 } hdr;
2870 int (*fn)(tvbuff_t*, packet_info*, proto_tree*, gboolean);
2872 if (tvb_length(tvb) < 16) {
2873 return 0;
2876 hdr.msg = tvb_get_letohl(tvb, 0);
2878 switch(hdr.msg) {
2879 case 0xC8:
2880 fn = dissect_CPMConnect;
2881 break;
2882 case 0xC9:
2883 fn = dissect_CPMDisconnect;
2884 break;
2885 case 0xCA:
2886 fn = dissect_CPMCreateQuery;
2887 break;
2888 case 0xCB:
2889 fn = dissect_CPMFreeCursor;
2890 break;
2891 case 0xCC:
2892 fn = dissect_CPMGetRows;
2893 break;
2894 case 0xCD:
2895 fn = dissect_CPMRatioFinished;
2896 break;
2897 case 0xCE:
2898 fn = dissect_CPMCompareBmk;
2899 break;
2900 case 0xCF:
2901 fn = dissect_CPMGetApproximatePosition;
2902 break;
2903 case 0xD0:
2904 fn = dissect_CPMSetBindings;
2905 break;
2906 case 0xD1:
2907 fn = dissect_CPMGetNotify;
2908 break;
2909 case 0xD2:
2910 fn = dissect_CPMSendNotifyOut;
2911 break;
2912 case 0xD7:
2913 fn = dissect_CPMGetQueryStatus;
2914 break;
2915 case 0xD9:
2916 fn = dissect_CPMCiState;
2917 break;
2918 case 0xE4:
2919 fn = dissect_CPMFetchValue;
2920 break;
2921 case 0xE7:
2922 fn = dissect_CPMGetQueryStatusEx;
2923 break;
2924 case 0xE8:
2925 fn = dissect_CPMRestartPosition;
2926 break;
2927 case 0xEC:
2928 fn = dissect_CPMSetCatState;
2929 break;
2930 case 0xF1:
2931 fn = dissect_CPMGetRowsetNotify;
2932 break;
2933 case 0xF2:
2934 fn = dissect_CPMFindIndices;
2935 break;
2936 case 0xF3:
2937 fn = dissect_CPMSetScopePrioritization;
2938 break;
2939 case 0xF4:
2940 fn = dissect_CPMGetScopeStatistics;
2941 break;
2942 default:
2943 return 0;
2946 hdr.status = tvb_get_letohl(tvb, 4);
2947 hdr.checksum = tvb_get_letohl(tvb, 8);
2949 /* col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS-WSP"); */
2950 col_append_str(pinfo->cinfo, COL_PROTOCOL, " WSP");
2951 /* col_clear(pinfo->cinfo, COL_INFO); */
2953 col_set_str(pinfo->cinfo, COL_INFO, "WSP ");
2954 col_append_str(pinfo->cinfo, COL_INFO, in ? "Request: " : "Response: ");
2956 if (tree) {
2957 proto_tree *hdr_tree;
2958 proto_item *ti, *hti;
2960 ti = proto_tree_add_item(tree, proto_mswsp, tvb, 0, -1, ENC_NA);
2961 mswsp_tree = proto_item_add_subtree(ti, ett_mswsp);
2963 hti = proto_tree_add_item(mswsp_tree, hf_mswsp_hdr, tvb, 0, 16, ENC_NA);
2964 hdr_tree = proto_item_add_subtree(hti, ett_mswsp_hdr);
2966 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_msg, tvb,
2967 0, 4, ENC_LITTLE_ENDIAN);
2968 proto_item_append_text(hti, " %s", val_to_str(hdr.msg, VALS(msg_ids),
2969 "(Unknown: 0x%x)"));
2971 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_status, tvb,
2972 4, 4, ENC_LITTLE_ENDIAN);
2973 if (!in || hdr.status != 0) {
2974 proto_item_append_text(hti, " %s",
2975 val_to_str(hdr.status, VALS(dcom_hresult_vals),
2976 "(Unknown: 0x%x)"));
2979 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_checksum, tvb,
2980 8, 4, ENC_LITTLE_ENDIAN);
2981 /* todo: validate checksum */
2983 proto_tree_add_item(hdr_tree, hf_mswsp_hdr_reserved, tvb,
2984 12, 4, ENC_LITTLE_ENDIAN);
2987 fn(tvb, pinfo, mswsp_tree, in);
2989 /* Return the amount of data this dissector was able to dissect */
2990 return tvb_length(tvb);
2994 /* Register the protocol with Wireshark */
2996 /* this format is require because a script is used to build the C function
2997 that calls all the protocol registration.
3000 void
3001 proto_register_mswsp(void)
3003 module_t *mswsp_module;
3005 /* Setup list of header fields See Section 1.6.1 for details*/
3006 static hf_register_info hf[] = {
3007 { &hf_mswsp_hdr,
3008 { "Header", "mswsp.hdr",
3009 FT_NONE, BASE_NONE , NULL, 0,
3010 "Message header", HFILL }
3012 { &hf_mswsp_hdr_msg,
3013 { "Msg id", "mswsp.hdr.id",
3014 FT_UINT32, BASE_HEX , VALS(msg_ids), 0,
3015 "Message id", HFILL }
3017 { &hf_mswsp_hdr_status,
3018 { "Status", "mswsp.hdr.status",
3019 FT_UINT32, BASE_HEX , VALS(dcom_hresult_vals), 0,
3020 "Status", HFILL }
3022 { &hf_mswsp_hdr_checksum,
3023 { "checksum", "mswsp.hdr.checksum",
3024 FT_UINT32, BASE_HEX , NULL, 0,
3025 "Checksum", HFILL }
3027 { &hf_mswsp_hdr_reserved,
3028 { "Reserved", "mswsp.hdr.reserved",
3029 FT_UINT32, BASE_HEX , NULL, 0,
3030 "Reserved", HFILL }
3032 { &hf_mswsp_msg,
3033 { "msg", "mswsp.msg",
3034 FT_NONE, BASE_NONE , NULL, 0,
3035 "Message", HFILL }
3037 { &hf_mswsp_msg_Connect_Version,
3038 { "Version", "mswsp.Connect.version",
3039 FT_UINT32, BASE_HEX , NULL, 0,
3040 "Version",HFILL }
3042 { &hf_mswsp_msg_ConnectIn_ClientIsRemote,
3043 { "Remote", "mswsp.ConnectIn.isRemote",
3044 FT_BOOLEAN, BASE_HEX , NULL, 0,
3045 "Client is remote",HFILL }
3047 { &hf_mswsp_msg_ConnectIn_Blob1,
3048 { "Size", "mswsp.ConnectIn.propset.size",
3049 FT_UINT32, BASE_DEC , NULL, 0,
3050 "Size of PropSet fields",HFILL }
3052 { &hf_mswsp_msg_ConnectIn_Blob2,
3053 { "Size", "mswsp.ConnectIn.extpropset.size",
3054 FT_UINT32, BASE_DEC , NULL, 0,
3055 "Size of ExtPropSet fields",HFILL }
3057 { &hf_mswsp_msg_ConnectIn_MachineName,
3058 { "Remote machine", "mswsp.ConnectIn.machine",
3059 FT_STRINGZ, BASE_NONE , NULL, 0,
3060 "Name of remote machine",HFILL }
3062 { &hf_mswsp_msg_ConnectIn_UserName,
3063 { "User", "mswsp.ConnectIn.user",
3064 FT_STRINGZ, BASE_NONE , NULL, 0,
3065 "Name of remote user",HFILL }
3067 { &hf_mswsp_msg_ConnectIn_PropSets_num,
3068 { "Num", "mswsp.ConnectIn.propset.num",
3069 FT_UINT32, BASE_DEC , NULL, 0,
3070 "Number of Property Sets", HFILL }
3072 { &hf_mswsp_msg_ConnectIn_ExtPropSets_num,
3073 { "Num", "mswsp.ConnectIn.extpropset.num",
3074 FT_UINT32, BASE_DEC , NULL, 0,
3075 "Number of extended Property Sets", HFILL }
3080 /* Setup protocol subtree array */
3081 static gint *ett[] = {
3082 &ett_mswsp,
3083 &ett_mswsp_hdr,
3084 &ett_mswsp_msg,
3085 &ett_mswsp_pad,
3086 &ett_mswsp_property_restriction,
3087 &ett_CRestrictionArray,
3088 &ett_CBaseStorageVariant,
3089 &ett_CBaseStorageVariant_Vector,
3090 &ett_CBaseStorageVariant_Array,
3091 &ett_CDbColId,
3092 &ett_GUID,
3093 &ett_CDbProp,
3094 &ett_CDbPropSet,
3095 &ett_CDbPropSet_Array,
3096 &ett_CRestriction,
3097 &ett_CNodeRestriction,
3098 &ett_CPropertyRestriction,
3099 &ett_CCoercionRestriction,
3100 &ett_CContentRestriction,
3101 &ett_RANGEBOUNDARY,
3102 &ett_CRangeCategSpec,
3103 &ett_CCategSpec,
3104 &ett_CAggregSpec,
3105 &ett_CAggregSet,
3106 &ett_CCategorizationSpec,
3107 &ett_CAggregSortKey,
3108 &ett_CSortAggregSet,
3109 &ett_CInGroupSortAggregSet,
3110 &ett_CInGroupSortAggregSets,
3111 &ett_CRowsetProperties,
3112 &ett_CFullPropSpec,
3113 &ett_CPidMapper,
3114 &ett_CSort,
3115 &ett_CSortSet,
3116 &ett_CNatLanguageRestriction,
3117 &ett_CColumnGroup,
3118 &ett_CColumnGroupArray,
3119 &ett_LCID,
3120 &ett_CTableColumn,
3123 int i;
3125 /* Register the protocol name and description */
3126 proto_mswsp = proto_register_protocol("Windows Search Protocol",
3127 "MS-WSP", "mswsp");
3129 /* Required function calls to register the header fields and subtrees used */
3130 proto_register_field_array(proto_mswsp, hf, array_length(hf));
3131 proto_register_subtree_array(ett, array_length(ett));
3133 for (i=0; i<(int)array_length(GuidPropertySet); i++) {
3134 guids_add_guid(&GuidPropertySet[i].guid, GuidPropertySet[i].def);
3138 /* Register preferences module (See Section 2.6 for more on preferences) */
3139 /* (Registration of a prefs callback is not required if there are no */
3140 /* prefs-dependent registration functions (eg: a port pref). */
3141 /* See proto_reg_handoff below. */
3142 /* If a prefs callback is not needed, use NULL instead of */
3143 /* proto_reg_handoff_mswsp in the following). */
3144 mswsp_module = prefs_register_protocol(proto_mswsp,
3145 proto_reg_handoff_mswsp);
3147 /* Register preferences module under preferences subtree.
3148 Use this function instead of prefs_register_protocol if you want to group
3149 preferences of several protocols under one preferences subtree.
3150 Argument subtree identifies grouping tree node name, several subnodes can be
3151 specified using slash '/' (e.g. "OSI/X.500" - protocol preferences will be
3152 accessible under Protocols->OSI->X.500-><PROTOSHORTNAME> preferences node.
3154 /* mswsp_module = prefs_register_protocol_subtree(subtree, */
3155 /* proto_mswsp, proto_reg_handoff_mswsp); */
3157 /* Register a sample preference */
3158 prefs_register_bool_preference(mswsp_module, "show_hex",
3159 "Display numbers in Hex",
3160 "Enable to display numerical values in hexadecimal.",
3161 &gPREF_HEX);
3163 /* Register a sample port preference */
3164 prefs_register_uint_preference(mswsp_module, "tcp.port", "mswsp TCP Port",
3165 " mswsp TCP port if other than the default",
3166 10, &gPORT_PREF);
3169 static int dissect_mswsp_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
3170 smb_info_t *si = (smb_info_t*)pinfo->private_data;
3171 gboolean in = si->request;
3173 smb_transact_info_t *tri = (smb_transact_info_t *)((si->sip->extra_info_type == SMB_EI_TRI) ? si->sip->extra_info : NULL);
3174 smb_fid_info_t *fid_info = NULL;
3175 GSList *iter;
3177 debug_frame((int)pinfo->fd->num);
3179 fprintf(stderr, "dissect_mswsp_smb %s frame: %d tid: %d op: %02x ",
3180 in ? "Request" : "Response",
3181 pinfo->fd->num, si->tid, si->cmd);
3183 if (tri == NULL) {
3184 fprintf(stderr, " extra_info_type: %d\n", si->sip->extra_info_type);
3185 return 0;
3188 for (iter = si->ct->GSL_fid_info; iter; iter = g_slist_next(iter)) {
3189 smb_fid_info_t *info = (smb_fid_info_t *)iter->data;
3190 if ((info->tid == si->tid) && (info->fid == tri->fid)) {
3191 fid_info = info;
3192 break;
3196 if (!fid_info || !fid_info->fsi || !fid_info->fsi->filename) {
3197 fprintf(stderr, " no %s\n", fid_info ? (fid_info->fsi ? "filename" : "fsi") : "fid_info");
3198 return 0;
3201 fprintf(stderr, " file: %s\n", fid_info->fsi->filename);
3203 if (strcasecmp(fid_info->fsi->filename, "\\MsFteWds") != 0) {
3204 return 0;
3207 return dissect_mswsp(tvb, pinfo, tree, in);
3211 static int dissect_mswsp_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
3212 smb2_info_t *si = (smb2_info_t*)pinfo->private_data;
3213 gboolean in = !(si->flags & SMB2_FLAGS_RESPONSE);
3215 //si->tree->share_type == SMB2_SHARE_TYPE_PIPE
3216 //si->tree->connect_frame
3218 debug_frame((int)pinfo->fd->num);
3220 fprintf(stderr, "dissect_mswsp %d <> %d : op %02x %s %s type: %d extra_file: %s\n",
3221 pinfo->fd->num, si->tree ? (int)si->tree->connect_frame : -1,
3222 si->opcode,
3223 pinfo->dcerpc_procedure_name ? pinfo->dcerpc_procedure_name : "<NULL>",
3224 in ? "Request" : "Response", si->tree ? si->tree->share_type : -1,
3225 si->saved ? (si->saved->extra_info_type == SMB2_EI_FILENAME ? (char*)si->saved->extra_info : "<OTHER>") : "<NONE>"
3229 if (strcmp(pinfo->dcerpc_procedure_name, "File: MsFteWds") != 0) {
3230 return 0;
3233 return dissect_mswsp(tvb, pinfo, tree, in);
3238 /* If this dissector uses sub-dissector registration add a registration routine.
3239 This exact format is required because a script is used to find these
3240 routines and create the code that calls these routines.
3242 If this function is registered as a prefs callback (see prefs_register_protocol
3243 above) this function is also called by preferences whenever "Apply" is pressed;
3244 In that case, it should accommodate being called more than once.
3246 Simple form of proto_reg_handoff_mswsp which can be used if there are
3247 no prefs-dependent registration function calls.
3250 void
3251 proto_reg_handoff_mswsp(void)
3253 heur_dissector_add("smb_transact", dissect_mswsp_smb, proto_mswsp);
3254 heur_dissector_add("smb2_heur_subdissectors", dissect_mswsp_smb2, proto_mswsp);
3259 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3261 * Local variables:
3262 * c-basic-offset: 4
3263 * tab-width: 8
3264 * indent-tabs-mode: nil
3265 * End:
3267 * vi: set shiftwidth=4 tabstop=8 expandtab:
3268 * :indentSize=4:tabSize=8:noTabs=true: