Fixup: tvb_get_string(z) -> tvb_get_string(z)_enc
[metze/wireshark/wip.git] / epan / dissectors / packet-dplay.c
1 /* packet-dplay.c
2  * This is a dissector for the DirectPlay protocol.
3  * Copyright 2006 - 2008 by Kai Blin
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
22  * USA.51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  *
24  */
25
26 #include "config.h"
27
28 #include <epan/packet.h>
29 #include <epan/wmem/wmem.h>
30 #include <epan/aftypes.h>
31 #include <string.h>
32
33 /* function declarations */
34 void proto_register_dplay(void);
35 void proto_reg_handoff_dplay(void);
36
37 static void dissect_dplay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
38 static gint dissect_type1a_message(proto_tree *tree, tvbuff_t *tvb, gint offset);
39
40 static int proto_dplay = -1;
41
42 /* Common data fields */
43 static int hf_dplay_size = -1;              /* Size of the whole data */
44 static int hf_dplay_token = -1;
45 static int hf_dplay_saddr_af = -1;          /* WINSOCK_AF_INET, as this dissector does not handle IPX yet */
46 static int hf_dplay_saddr_port = -1;        /* port to use for the reply to this packet */
47 static int hf_dplay_saddr_ip = -1;          /* IP to use for the reply to this packet, or 0.0.0.0,
48                                                then use the same IP as this packet used. */
49 static int hf_dplay_saddr_padding = -1;     /* null padding used in s_addr_in structures */
50 static int hf_dplay_play_str = -1;          /* always "play" without a null terminator */
51 static int hf_dplay_command = -1;           /* the dplay command this message contains*/
52 static int hf_dplay_proto_dialect = -1;     /* 0x0b00 for dplay7, 0x0e00 for dplay9 */
53 static int hf_dplay_play_str_2 = -1;        /* packet type 0x0015 encapsulates another packet */
54 static int hf_dplay_command_2 = -1;         /* that also has a "play" string, a command and a */
55 static int hf_dplay_proto_dialect_2 = -1;   /* protocol dialect, same as above */
56 static const int DPLAY_HEADER_OFFSET = 28;  /* The dplay header is 28 bytes in size */
57 static int hf_dplay_player_msg = -1;
58
59 /* The following fields are not part of the header, but hopefully have the same
60  * meaning for all packets they show up in. */
61
62 static int hf_dplay_sess_desc_flags = -1; /* This is a 32bit field with some sort of a flag */
63 static int hf_dplay_flags_no_create_players = -1;
64 static int hf_dplay_flags_0002 = -1;
65 static int hf_dplay_flags_migrate_host = -1;
66 static int hf_dplay_flags_short_player_msg = -1;
67 static int hf_dplay_flags_ignored = -1;
68 static int hf_dplay_flags_can_join = -1;
69 static int hf_dplay_flags_use_ping = -1;
70 static int hf_dplay_flags_no_player_updates = -1;
71 static int hf_dplay_flags_use_auth = -1;
72 static int hf_dplay_flags_private_session = -1;
73 static int hf_dplay_flags_password_req = -1;
74 static int hf_dplay_flags_route = -1;
75 static int hf_dplay_flags_server_player_only = -1;
76 static int hf_dplay_flags_reliable = -1;
77 static int hf_dplay_flags_preserve_order = -1;
78 static int hf_dplay_flags_optimize_latency = -1;
79 static int hf_dplay_flags_acqire_voice = -1;
80 static int hf_dplay_flags_no_sess_desc_changes = -1;
81
82 #define DPLAY_FLAG_NO_CREATE_PLAYERS 0x0001
83 #define DPLAY_FLAG_0002 0x0002
84 #define DPLAY_FLAG_MIGRATE_HOST 0x0004
85 #define DPLAY_FLAG_SHORT_PLAYER_MSG 0x0008
86 #define DPLAY_FLAG_IGNORED 0x0010
87 #define DPLAY_FLAG_CAN_JOIN 0x0020
88 #define DPLAY_FLAG_USE_PING 0x0040
89 #define DPLAY_FLAG_NO_P_UPD 0x0080
90 #define DPLAY_FLAG_USE_AUTH 0x0100
91 #define DPLAY_FLAG_PRIV_SESS 0x0200
92 #define DPLAY_FLAG_PASS_REQ 0x0400
93 #define DPLAY_FLAG_ROUTE 0x0800
94 #define DPLAY_FLAG_SRV_ONLY 0x1000
95 #define DPLAY_FLAG_RELIABLE 0x2000
96 #define DPLAY_FLAG_ORDER 0x4000
97 #define DPLAY_FLAG_OPT_LAT 0x8000
98 #define DPLAY_FLAG_ACQ_VOICE 0x10000
99 #define DPLAY_FLAG_NO_SESS_DESC_CHANGES 0x20000
100
101 /* Session description structure fields */
102 static int hf_dplay_sess_desc_length = -1;
103 static int hf_dplay_game_guid = -1;
104 static int hf_dplay_instance_guid = -1;
105 static int hf_dplay_max_players = -1;
106 static int hf_dplay_curr_players = -1;
107 static int hf_dplay_sess_name_ptr = -1;
108 static int hf_dplay_passwd_ptr = -1;
109 static int hf_dplay_sess_desc_reserved_1 = -1;
110 static int hf_dplay_sess_desc_reserved_2 = -1;
111 static int hf_dplay_sess_desc_user_1 = -1;
112 static int hf_dplay_sess_desc_user_2 = -1;
113 static int hf_dplay_sess_desc_user_3 = -1;
114 static int hf_dplay_sess_desc_user_4 = -1;
115
116 /* PackedPlayer structure fields */
117 static int hf_dplay_pp_size = -1;
118 static int hf_dplay_pp_flags = -1;
119 static int hf_dplay_pp_flag_sysplayer = -1;
120 static int hf_dplay_pp_flag_nameserver = -1;
121 static int hf_dplay_pp_flag_in_group = -1;
122 static int hf_dplay_pp_flag_sending = -1;
123 static int hf_dplay_pp_id = -1;
124 static int hf_dplay_pp_short_name_len = -1;
125 static int hf_dplay_pp_long_name_len = -1;
126 static int hf_dplay_pp_sp_data_size = -1;
127 static int hf_dplay_pp_player_data_size = -1;
128 static int hf_dplay_pp_num_players = -1;
129 static int hf_dplay_pp_system_player = -1;
130 static int hf_dplay_pp_fixed_size = -1;
131 static int hf_dplay_pp_dialect = -1;
132 static int hf_dplay_pp_unknown_1 = -1;
133 static int hf_dplay_pp_short_name = -1;
134 static int hf_dplay_pp_long_name = -1;
135 static int hf_dplay_pp_sp_data = -1;
136 static int hf_dplay_pp_player_data = -1;
137 static int hf_dplay_pp_player_id = -1;
138 static int hf_dplay_pp_parent_id = -1;
139 #define DPLAY_PP_FLAG_SYSPLAYER 0x01
140 #define DPLAY_PP_FLAG_NAMESERVER 0x02
141 #define DPLAY_PP_FLAG_IN_GROUP 0x04
142 #define DPLAY_PP_FLAG_SENDING 0x08
143
144 /* SuperPackedPlayer structure fields */
145 static int hf_dplay_spp_size = -1;
146 static int hf_dplay_spp_flags = -1;
147 static int hf_dplay_spp_flags_sysplayer = -1;
148 static int hf_dplay_spp_flags_nameserver = -1;
149 static int hf_dplay_spp_flags_in_group = -1;
150 static int hf_dplay_spp_flags_sending = -1;
151 static int hf_dplay_spp_id = -1;
152 static int hf_dplay_spp_player_info_mask = -1;
153 static int hf_dplay_spp_have_short_name = -1;
154 static int hf_dplay_spp_have_long_name = -1;
155 static int hf_dplay_spp_sp_length_type = -1;
156 static int hf_dplay_spp_pd_length_type = -1;
157 static int hf_dplay_spp_player_count_type = -1;
158 static int hf_dplay_spp_have_parent_id = -1;
159 static int hf_dplay_spp_shortcut_count_type = -1;
160 static int hf_dplay_spp_dialect = -1;
161 static int hf_dplay_spp_sys_player_id = -1;
162 static int hf_dplay_spp_short_name = -1;
163 static int hf_dplay_spp_long_name = -1;
164 static int hf_dplay_spp_player_data_length = -1;
165 static int hf_dplay_spp_player_data = -1;
166 static int hf_dplay_spp_sp_data_length = -1;
167 static int hf_dplay_spp_sp_data = -1;
168 static int hf_dplay_spp_player_count = -1;
169 static int hf_dplay_spp_player_id = -1;
170 static int hf_dplay_spp_parent_id = -1;
171 static int hf_dplay_spp_shortcut_count = -1;
172 static int hf_dplay_spp_shortcut_id = -1;
173 #define DPLAY_SPP_FLAG_SYSPLAYER 0x01
174 #define DPLAY_SPP_FLAG_NAMESERVER 0x02
175 #define DPLAY_SPP_FLAG_IN_GROUP 0x04
176 #define DPLAY_SPP_FLAG_SENDING 0x08
177
178 /* SecurityDesc structure fields */
179 static int hf_dplay_sd_size = -1;
180 static int hf_dplay_sd_flags = -1;
181 static int hf_dplay_sd_sspi = -1;
182 static int hf_dplay_sd_capi = -1;
183 static int hf_dplay_sd_capi_type = -1;
184 static int hf_dplay_sd_enc_alg = -1;
185
186 /* Message Type 0x0001 data fields */
187 static int hf_dplay_type_01_name_offset = -1;
188 static int hf_dplay_type_01_game_name = -1;
189
190 /* Message Type 0x0002 data fields */
191 static int hf_dplay_type_02_game_guid = -1;
192 static int hf_dplay_type_02_password_offset = -1;
193 static int hf_dplay_type_02_flags = -1;
194 static int hf_dplay_type_02_password = -1;
195 static int hf_enum_sess_flag_join = -1;
196 static int hf_enum_sess_flag_all = -1;
197 static int hf_enum_sess_flag_passwd = -1;
198 #define DPLAY_ENUM_SESS_FLAG_JOIN 0x0001
199 #define DPLAY_ENUM_SESS_FLAG_ALL 0x0002
200 #define DPLAY_ENUM_SESS_FLAG_PASSWD 0x0040
201
202 /* Message Type 0x0005 data fields */
203 static int hf_dplay_type_05_flags = -1;
204 static int hf_dplay_type_05_system_player = -1;
205 static int hf_dplay_type_05_name_server = -1;
206 static int hf_dplay_type_05_local = -1;
207 static int hf_dplay_type_05_unknown = -1; /* unknown, but always set */
208 static int hf_dplay_type_05_secure = -1;
209 #define DPLAY_TYPE05_FLAG_SYSPLAYER 0x001
210 #define DPLAY_TYPE05_FLAG_NAMESERVER 0x002
211 #define DPLAY_TYPE05_FLAG_LOCAL 0x004
212 #define DPLAY_TYPE05_FLAG_UNKNOWN 0x008
213 #define DPLAY_TYPE05_FLAG_SECURE 0x200
214
215 /* Message Type 0x0007 data fields */
216 static int hf_dplay_type_07_dpid = -1;
217 static int hf_dplay_type_07_sspi_offset = -1;
218 static int hf_dplay_type_07_capi_offset = -1;
219 static int hf_dplay_type_07_hresult = -1;
220 static int hf_dplay_type_07_sspi = -1;
221 static int hf_dplay_type_07_capi = -1;
222
223 /* Data fields for message types 0x08, 0x09, 0x0b, 0x0c, 0x0d, 0x0e */
224 static int hf_dplay_multi_id_to = -1;
225 static int hf_dplay_multi_player_id = -1;
226 static int hf_dplay_multi_group_id = -1;
227 static int hf_dplay_multi_create_offset = -1;
228 static int hf_dplay_multi_password_offset = -1;
229 static int hf_dplay_multi_password = -1;
230
231 /* Message Type 0x000f data fields */
232 static int hf_dplay_type_0f_id_to = -1;
233 static int hf_dplay_type_0f_id = -1;
234 static int hf_dplay_type_0f_data_size = -1;
235 static int hf_dplay_type_0f_data_offset = -1;
236 static int hf_dplay_type_0f_data = -1;
237
238 /* Message Type 0x0013 data fields */
239 static int hf_dplay_type_13_id_to = -1;
240 static int hf_dplay_type_13_player_id = -1;
241 static int hf_dplay_type_13_group_id = -1;
242 static int hf_dplay_type_13_create_offset = -1;
243 static int hf_dplay_type_13_password_offset = -1;
244 static int hf_dplay_type_13_password = -1;
245 static int hf_dplay_type_13_tick_count = -1;
246
247 /* Message Type 0x0015 data fields */
248 static int hf_dplay_message_guid = -1;
249 static int hf_dplay_type_15_packet_idx = -1;
250 static int hf_dplay_type_15_data_size = -1;
251 static int hf_dplay_type_15_offset = -1;
252 static int hf_dplay_type_15_total_packets = -1;
253 static int hf_dplay_type_15_msg_size = -1;
254 static int hf_dplay_type_15_packet_offset = -1;
255
256 /* Message Type 0x0016 and 0x0017 data fields */
257 static int hf_dplay_ping_id_from = -1;
258 static int hf_dplay_ping_tick_count = -1;
259
260 /* Message Type 0x001a data fields */
261 static int hf_dplay_type_1a_id_to = -1;
262 static int hf_dplay_type_1a_sess_name_ofs = -1;
263 static int hf_dplay_type_1a_password_ofs = -1;
264 static int hf_dplay_type_1a_session_name = -1;
265 static int hf_dplay_type_1a_password = -1;
266
267 /* Message Type 0x0029 data fields */
268 static int hf_dplay_type_29_player_count = -1;
269 static int hf_dplay_type_29_group_count = -1;
270 static int hf_dplay_type_29_packed_offset = -1;
271 static int hf_dplay_type_29_shortcut_count = -1;
272 static int hf_dplay_type_29_description_offset = -1;
273 static int hf_dplay_type_29_name_offset = -1;
274 static int hf_dplay_type_29_password_offset = -1;
275 static int hf_dplay_type_29_game_name = -1;
276 static int hf_dplay_type_29_password = -1;
277
278 /* Message Type 0x002f data fields */
279 static int hf_dplay_type_2f_dpid = -1;
280
281 /* various */
282 static gint ett_dplay = -1;
283 static gint ett_dplay_header = -1;
284 static gint ett_dplay_sockaddr = -1;
285 static gint ett_dplay_data = -1;
286 static gint ett_dplay_enc_packet = -1;
287 static gint ett_dplay_flags = -1;
288 static gint ett_dplay_sess_desc_flags = -1;
289 static gint ett_dplay_pp_flags = -1;
290 static gint ett_dplay_spp_flags = -1;
291 static gint ett_dplay_spp_info_mask = -1;
292 static gint ett_dplay_type02_flags = -1;
293 static gint ett_dplay_type05_flags = -1;
294 static gint ett_dplay_type29_spp = -1;
295
296 static const value_string dplay_command_val[] = {
297     { 0x0001, "Enum Sessions Reply" },
298     { 0x0002, "Enum Sessions" },
299     { 0x0003, "Enum Players Reply" },
300     { 0x0004, "Enum Players" },
301     { 0x0005, "Request Player ID" },
302     { 0x0006, "Request Group ID" },
303     { 0x0007, "Request Player Reply" },
304     { 0x0008, "Create Player" },
305     { 0x0009, "Create Group" },
306     { 0x000a, "Player Message" },
307     { 0x000b, "Delete Player" },
308     { 0x000c, "Delete Group" },
309     { 0x000d, "Add Player To Group" },
310     { 0x000e, "Delete Player From Group" },
311     { 0x000f, "Player Data Changed" },
312     { 0x0010, "Player Name Changed" },
313     { 0x0011, "Group Data Changed" },
314     { 0x0012, "Group Name Changed" },
315     { 0x0013, "Add Forward Request" },
316     /* There is no command 0x0014 */
317     { 0x0015, "Packet" },
318     { 0x0016, "Ping" },
319     { 0x0017, "Pong" },
320     { 0x0018, "You Are Dead" },
321     { 0x0019, "Player Wrapper" },
322     { 0x001a, "Session Desc Changed" },
323     { 0x001c, "Challenge" },
324     { 0x001d, "Access Granted" },
325     { 0x001e, "Logon Denied" },
326     { 0x001f, "Auth Error" },
327     { 0x0020, "Negotiate" },
328     { 0x0021, "Challenge Response" },
329     { 0x0022, "Signed"},
330     /* There is no command 0x0023 */
331     { 0x0024, "Add Forward Reply" },
332     { 0x0025, "Ask For Multicast" },
333     { 0x0026, "Ask For Multicast Guaranteed" },
334     { 0x0027, "Add Shortcut To Group" },
335     { 0x0028, "Delete Group From Group" },
336     { 0x0029, "Super Enum Players Reply" },
337     /* There is no command 0x002a */
338     { 0x002b, "Key Exchange" },
339     { 0x002c, "Key Exchange Reply" },
340     { 0x002d, "Chat" },
341     { 0x002e, "Add Forward" },
342     { 0x002f, "Add Forward ACK" },
343     { 0x0030, "Packet2 Data" },
344     { 0x0031, "Packet2 ACK" },
345     /* No commands 0x0032, 0x0033, 0x0034 */
346     { 0x0035, "I Am Nameserver" },
347     { 0x0036, "Voice" },
348     { 0x0037, "Multicast Delivery" },
349     { 0x0038, "Create Players Verify"},
350     { 0     , NULL },
351 };
352
353 static const value_string dplay_af_val[] = {
354     { WINSOCK_AF_INET, "AF_INET" },
355     { WINSOCK_AF_IPX, "AF_IPX" },
356     { 0     , NULL},
357 };
358
359 static const value_string dplay_proto_dialect_val[] = {
360     { 0x0009, "dplay 6" },
361     { 0x000a, "dplay 6.1" },
362     { 0x000b, "dplay 6.1a" },
363     { 0x000c, "dplay 7.1" },
364     { 0x000d, "dplay 8" },
365     { 0x000e, "dplay 9"},
366     { 0     , NULL},
367 };
368
369 static const value_string dplay_token_val[] = {
370     { 0xfab, "Remote Message" },
371     { 0xcab, "Forwarded Message" },
372     { 0xbab, "Server Message" },
373     { 0    , NULL },
374 };
375
376 static const value_string dplay_spp_length_val[] = {
377     { 0x0, "Not present" },
378     { 0x1, "One byte" },
379     { 0x2, "Two bytes" },
380     { 0x3, "Four bytes" },
381     { 0  , NULL},
382 };
383
384 static const value_string dplay_enc_alg_val[] = {
385     { 0x0000, "Default" },
386     { 0x6611, "AES" },
387     { 0x6603, "3DES" },
388     { 0x6601, "DES" },
389     { 0x6602, "RC2" },
390     { 0x6801, "RC4" },
391     { 0     , NULL },
392 };
393
394 static const value_string yes_no_val[] = {
395     { 0x0, "No" },
396     { 0x1, "Yes" },
397     { 0  , NULL },
398 };
399
400 static const true_false_string tfs_dplay_flag = {
401     "present",
402     "absent"
403 };
404
405 /* borrowed from epan/dissectors/packets-smb-common.c */
406 static gint display_unicode_string(proto_tree *tree, gint hf_index, tvbuff_t *tvb, gint offset)
407 {
408     char *str, *p;
409     gint len;
410     gint charoffset;
411     guint16 character;
412
413     /* display a unicode string from the tree and return new offset */
414
415     /*
416      * Get the length of the string.
417      * XXX - is it a bug or a feature that this will throw an exception
418      * if we don't find the '\0'?  I think it's a feature.
419      */
420     len = 0;
421     while (tvb_get_letohs(tvb, offset + len) != '\0')
422         len += 2;
423     len += 2;   /* count the '\0' too */
424
425     /*
426      * Allocate a buffer for the string; "len" is the length in
427      * bytes, not the length in characters.
428      */
429     str = (char *)wmem_alloc(wmem_packet_scope(), len/2);
430
431     /*
432      * XXX - this assumes the string is just ISO 8859-1; we need
433      * to better handle multiple character sets in Wireshark,
434      * including Unicode/ISO 10646, and multiple encodings of
435      * that character set (UCS-2, UTF-8, etc.).
436      */
437     charoffset = offset;
438     p = str;
439     while ((character = tvb_get_letohs(tvb, charoffset)) != '\0') {
440         *p++ = (char) character;
441         charoffset += 2;
442     }
443     *p = '\0';
444
445     proto_tree_add_string(tree, hf_index, tvb, offset, len, str);
446
447     return  offset+len;
448 }
449
450 static gint dissect_sockaddr_in(proto_tree *tree, tvbuff_t *tvb, gint offset)
451 {
452     proto_item *sa_item = NULL;
453     proto_tree *sa_tree = NULL;
454
455     sa_item = proto_tree_add_text(tree, tvb, offset, 16,
456             "DirectPlay sockaddr_in structure");
457     sa_tree = proto_item_add_subtree(sa_item, ett_dplay_sockaddr);
458     proto_tree_add_item(sa_tree, hf_dplay_saddr_af, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2;
459     proto_tree_add_item(sa_tree, hf_dplay_saddr_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
460     proto_tree_add_item(sa_tree, hf_dplay_saddr_ip, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4;
461     proto_tree_add_item(sa_tree, hf_dplay_saddr_padding, tvb, offset, 8, ENC_NA); offset += 8;
462     return offset;
463 }
464
465 static gint dissect_session_desc(proto_tree *tree, tvbuff_t *tvb, gint offset)
466 {
467     guint32 flags;
468     proto_item *flags_item = NULL;
469     proto_tree *flags_tree = NULL;
470
471     flags = tvb_get_letohl(tvb, offset+4);
472
473     proto_tree_add_item(tree, hf_dplay_sess_desc_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
474     flags_item = proto_tree_add_item(tree, hf_dplay_sess_desc_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
475     flags_tree = proto_item_add_subtree(flags_item, ett_dplay_sess_desc_flags);
476     proto_tree_add_boolean(flags_tree, hf_dplay_flags_no_sess_desc_changes, tvb, offset, 4, flags);
477     proto_tree_add_boolean(flags_tree, hf_dplay_flags_acqire_voice, tvb, offset, 4, flags);
478     proto_tree_add_boolean(flags_tree, hf_dplay_flags_optimize_latency, tvb, offset, 4, flags);
479     proto_tree_add_boolean(flags_tree, hf_dplay_flags_preserve_order, tvb, offset, 4, flags);
480     proto_tree_add_boolean(flags_tree, hf_dplay_flags_reliable, tvb, offset, 4, flags);
481     proto_tree_add_boolean(flags_tree, hf_dplay_flags_server_player_only, tvb, offset, 4, flags);
482     proto_tree_add_boolean(flags_tree, hf_dplay_flags_route, tvb, offset, 4, flags);
483     proto_tree_add_boolean(flags_tree, hf_dplay_flags_password_req, tvb, offset, 4, flags);
484     proto_tree_add_boolean(flags_tree, hf_dplay_flags_private_session, tvb, offset, 4, flags);
485     proto_tree_add_boolean(flags_tree, hf_dplay_flags_use_auth, tvb, offset, 4, flags);
486     proto_tree_add_boolean(flags_tree, hf_dplay_flags_no_player_updates, tvb, offset, 4, flags);
487     proto_tree_add_boolean(flags_tree, hf_dplay_flags_use_ping, tvb, offset, 4, flags);
488     proto_tree_add_boolean(flags_tree, hf_dplay_flags_can_join, tvb, offset, 4, flags);
489     proto_tree_add_boolean(flags_tree, hf_dplay_flags_ignored, tvb, offset, 4, flags);
490     proto_tree_add_boolean(flags_tree, hf_dplay_flags_short_player_msg, tvb, offset, 4, flags);
491     proto_tree_add_boolean(flags_tree, hf_dplay_flags_migrate_host, tvb, offset, 4, flags);
492     proto_tree_add_boolean(flags_tree, hf_dplay_flags_0002, tvb, offset, 4, flags);
493     proto_tree_add_boolean(flags_tree, hf_dplay_flags_no_create_players, tvb, offset, 4, flags);
494     offset += 4;
495
496     proto_tree_add_item(tree, hf_dplay_instance_guid, tvb, offset, 16, ENC_BIG_ENDIAN); offset += 16;
497     proto_tree_add_item(tree, hf_dplay_game_guid, tvb, offset, 16, ENC_BIG_ENDIAN); offset += 16;
498     proto_tree_add_item(tree, hf_dplay_max_players, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
499     proto_tree_add_item(tree, hf_dplay_curr_players, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
500     proto_tree_add_item(tree, hf_dplay_sess_name_ptr, tvb, offset, 4, ENC_NA); offset += 4;
501     proto_tree_add_item(tree, hf_dplay_passwd_ptr, tvb, offset, 4, ENC_NA); offset += 4;
502     proto_tree_add_item(tree, hf_dplay_sess_desc_reserved_1, tvb, offset, 4, ENC_NA); offset += 4;
503     proto_tree_add_item(tree, hf_dplay_sess_desc_reserved_2, tvb, offset, 4, ENC_NA); offset += 4;
504     proto_tree_add_item(tree, hf_dplay_sess_desc_user_1, tvb, offset, 4, ENC_NA); offset += 4;
505     proto_tree_add_item(tree, hf_dplay_sess_desc_user_2, tvb, offset, 4, ENC_NA); offset += 4;
506     proto_tree_add_item(tree, hf_dplay_sess_desc_user_3, tvb, offset, 4, ENC_NA); offset += 4;
507     proto_tree_add_item(tree, hf_dplay_sess_desc_user_4, tvb, offset, 4, ENC_NA); offset += 4;
508
509     return offset;
510 }
511
512 static gint dissect_packed_player(proto_tree *tree, tvbuff_t *tvb, gint offset)
513 {
514     proto_tree *flags_tree;
515     proto_item *flags_item;
516     guint32 flags, sn_len, ln_len, sd_len, pd_len, num_players, i;
517     gint size;
518
519     size = tvb_get_letohl(tvb, offset);
520     proto_tree_add_item(tree, hf_dplay_pp_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
521
522     flags = tvb_get_letohl(tvb, offset);
523     flags_item = proto_tree_add_item(tree, hf_dplay_pp_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
524     flags_tree = proto_item_add_subtree(flags_item, ett_dplay_pp_flags);
525     proto_tree_add_boolean(flags_tree, hf_dplay_pp_flag_sending, tvb, offset, 4, flags);
526     proto_tree_add_boolean(flags_tree, hf_dplay_pp_flag_in_group, tvb, offset, 4, flags);
527     proto_tree_add_boolean(flags_tree, hf_dplay_pp_flag_nameserver, tvb, offset, 4, flags);
528     proto_tree_add_boolean(flags_tree, hf_dplay_pp_flag_sysplayer, tvb, offset, 4, flags);
529     offset += 4;
530
531     proto_tree_add_item(tree, hf_dplay_pp_id, tvb, offset, 4, ENC_NA); offset += 4;
532
533     sn_len = tvb_get_letohl(tvb, offset);
534     proto_tree_add_item(tree, hf_dplay_pp_short_name_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
535     ln_len = tvb_get_letohl(tvb, offset);
536     proto_tree_add_item(tree, hf_dplay_pp_long_name_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
537     sd_len = tvb_get_letohl(tvb, offset);
538     proto_tree_add_item(tree, hf_dplay_pp_sp_data_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
539     pd_len = tvb_get_letohl(tvb, offset);
540     proto_tree_add_item(tree, hf_dplay_pp_player_data_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
541     num_players = tvb_get_letohl(tvb, offset);
542     proto_tree_add_item(tree, hf_dplay_pp_num_players, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
543
544     proto_tree_add_item(tree, hf_dplay_pp_system_player, tvb, offset, 4, ENC_NA); offset += 4;
545     proto_tree_add_item(tree, hf_dplay_pp_fixed_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
546     proto_tree_add_item(tree, hf_dplay_pp_dialect, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
547     proto_tree_add_item(tree, hf_dplay_pp_unknown_1, tvb, offset, 4, ENC_NA); offset += 4;
548
549     if (sn_len)
550         offset = display_unicode_string(tree, hf_dplay_pp_short_name, tvb, offset);
551
552     if (ln_len)
553         offset = display_unicode_string(tree, hf_dplay_pp_long_name, tvb, offset);
554
555     proto_tree_add_item(tree, hf_dplay_pp_sp_data, tvb, offset, sd_len, ENC_NA);
556     offset += sd_len;
557
558     if (pd_len) {
559         proto_tree_add_item(tree, hf_dplay_pp_player_data, tvb, offset, pd_len, ENC_NA);
560         offset += pd_len;
561     }
562
563     for (i=0; i < num_players; ++i) {
564         proto_tree_add_item(tree, hf_dplay_pp_player_id, tvb, offset, 4, ENC_NA); offset += 4;
565     }
566
567     /* Size seems to miss the unknown empty dword */
568     if (size + 4 > offset) {
569         proto_tree_add_item(tree, hf_dplay_pp_parent_id, tvb, offset, 4, ENC_NA); offset += 4;
570     }
571
572     return offset;
573 }
574
575 static gint spp_get_value(guint32 length_type, tvbuff_t *tvb, gint offset, guint32 *value)
576 {
577     gint len = 0;
578
579     *value = 0;
580
581     switch (length_type) {
582         case 1:
583             len = 1;
584             *value = tvb_get_guint8(tvb, offset);
585             break;
586         case 2:
587             len = 2;
588             *value = tvb_get_letohs(tvb, offset);
589             break;
590         case 3:
591             len = 4;
592             *value = tvb_get_letohl(tvb, offset);
593             break;
594     }
595
596     return len;
597 }
598
599 static gint dissect_dplay_super_packed_player(proto_tree *tree, tvbuff_t *tvb, gint offset)
600 {
601     guint32 flags, is_sysplayer, info_mask;
602     guint32 have_short_name, have_long_name, sp_length_type, pd_length_type;
603     guint32 player_count_type, have_parent_id, shortcut_count_type;
604     guint32 player_data_length, sp_data_length, player_count, shortcut_count;
605     proto_item *flags_item = NULL, *im_item = NULL;
606     proto_tree *flags_tree = NULL, *im_tree = NULL;
607     gint len;
608
609     proto_tree_add_item(tree, hf_dplay_spp_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
610
611     flags = tvb_get_letohl(tvb, offset);
612     is_sysplayer = flags & 0x00000001;
613     flags_item = proto_tree_add_item(tree, hf_dplay_spp_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
614     flags_tree = proto_item_add_subtree(flags_item, ett_dplay_spp_flags);
615     proto_tree_add_boolean(flags_tree, hf_dplay_spp_flags_sending, tvb, offset, 4, flags);
616     proto_tree_add_boolean(flags_tree, hf_dplay_spp_flags_in_group, tvb, offset, 4, flags);
617     proto_tree_add_boolean(flags_tree, hf_dplay_spp_flags_nameserver, tvb, offset, 4, flags);
618     proto_tree_add_boolean(flags_tree, hf_dplay_spp_flags_sysplayer, tvb, offset, 4, flags);
619     offset += 4;
620     proto_tree_add_item(tree, hf_dplay_spp_id, tvb, offset, 4, ENC_NA); offset += 4;
621
622     info_mask = tvb_get_letohl(tvb, offset);
623
624     have_short_name     =  info_mask & 0x00000001;
625     have_long_name      = (info_mask & 0x00000002) >> 1;
626     sp_length_type      = (info_mask & 0x0000000c) >> 2;
627     pd_length_type      = (info_mask & 0x00000030) >> 4;
628     player_count_type   = (info_mask & 0x000000c0) >> 6;
629     have_parent_id      = (info_mask & 0x00000100) >> 8;
630     shortcut_count_type = (info_mask & 0x00000600) >> 9;
631
632     im_item = proto_tree_add_item(tree, hf_dplay_spp_player_info_mask, tvb, offset, 4, ENC_LITTLE_ENDIAN);
633
634     im_tree = proto_item_add_subtree(im_item, ett_dplay_spp_info_mask);
635     proto_tree_add_uint(im_tree, hf_dplay_spp_have_short_name, tvb, offset, 4, have_short_name);
636     proto_tree_add_uint(im_tree, hf_dplay_spp_have_long_name, tvb, offset, 4, have_long_name);
637     proto_tree_add_uint(im_tree, hf_dplay_spp_sp_length_type, tvb, offset, 4, sp_length_type);
638     proto_tree_add_uint(im_tree, hf_dplay_spp_pd_length_type, tvb, offset, 4, pd_length_type);
639     proto_tree_add_uint(im_tree, hf_dplay_spp_player_count_type, tvb, offset, 4, player_count_type);
640     proto_tree_add_uint(im_tree, hf_dplay_spp_have_parent_id, tvb, offset, 4, have_parent_id);
641     proto_tree_add_uint(im_tree, hf_dplay_spp_shortcut_count_type, tvb, offset, 4, shortcut_count_type);
642     offset+=4;
643
644     if (is_sysplayer) {
645         proto_tree_add_item(tree, hf_dplay_spp_dialect, tvb, offset, 4, ENC_LITTLE_ENDIAN);
646     } else {
647         proto_tree_add_item(tree, hf_dplay_spp_sys_player_id, tvb, offset, 4, ENC_NA);
648     }
649     offset += 4;
650
651     if (have_short_name) {
652         offset = display_unicode_string(tree, hf_dplay_spp_short_name, tvb, offset);
653     }
654
655     if (have_long_name) {
656         offset = display_unicode_string(tree, hf_dplay_spp_long_name, tvb, offset);
657     }
658
659     if (pd_length_type) {
660         len = spp_get_value(pd_length_type, tvb, offset, &player_data_length);
661         proto_tree_add_item(tree, hf_dplay_spp_player_data_length, tvb, offset, len, ENC_LITTLE_ENDIAN);
662         offset += len;
663         proto_tree_add_item(tree, hf_dplay_spp_player_data, tvb, offset, player_data_length, ENC_NA);
664         offset += player_data_length;
665     }
666
667     if (sp_length_type) {
668         len = spp_get_value(sp_length_type, tvb, offset, &sp_data_length);
669         proto_tree_add_item(tree, hf_dplay_spp_sp_data_length, tvb, offset, len, ENC_LITTLE_ENDIAN);
670         offset += len;
671         proto_tree_add_item(tree, hf_dplay_spp_sp_data, tvb, offset, sp_data_length, ENC_NA);
672         offset += sp_data_length;
673     }
674
675     if (player_count_type) {
676         guint32 i;
677
678         len = spp_get_value(player_count_type, tvb, offset, &player_count);
679         proto_tree_add_item(tree, hf_dplay_spp_player_count, tvb, offset, len, ENC_LITTLE_ENDIAN);
680         offset += len;
681         for (i=0; i < player_count; ++i) {
682             proto_tree_add_item(tree, hf_dplay_spp_player_id, tvb, offset, 4, ENC_NA); offset += 4;
683         }
684     }
685
686     if (have_parent_id) {
687         proto_tree_add_item(tree, hf_dplay_spp_parent_id, tvb, offset, 4, ENC_NA); offset += 4;
688     }
689
690     if (shortcut_count_type) {
691         guint32 i;
692
693         len = spp_get_value(shortcut_count_type, tvb, offset, &shortcut_count);
694         proto_tree_add_item(tree, hf_dplay_spp_shortcut_count, tvb, offset, len, ENC_LITTLE_ENDIAN);
695         offset += len;
696         for (i=0; i < shortcut_count; ++i) {
697             proto_tree_add_item(tree, hf_dplay_spp_shortcut_id, tvb, offset, 4, ENC_NA); offset += 4;
698         }
699     }
700
701     return offset;
702 }
703
704 static gint dissect_security_desc(proto_tree *tree, tvbuff_t *tvb, gint offset)
705 {
706     proto_tree_add_item(tree, hf_dplay_sd_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
707     proto_tree_add_item(tree, hf_dplay_sd_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
708     proto_tree_add_item(tree, hf_dplay_sd_sspi, tvb, offset, 4, ENC_NA); offset += 4;
709     proto_tree_add_item(tree, hf_dplay_sd_capi, tvb, offset, 4, ENC_NA); offset += 4;
710     proto_tree_add_item(tree, hf_dplay_sd_capi_type, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
711     proto_tree_add_item(tree, hf_dplay_sd_enc_alg, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
712     return offset;
713 }
714
715 static gint dissect_dplay_header(proto_tree *tree, tvbuff_t *tvb, gint offset)
716 {
717     guint32 mixed, size, token;
718
719     mixed = tvb_get_letohl(tvb, offset);
720     size = mixed & 0x000FFFFF;
721     token = (mixed & 0xFFF00000) >> 20;
722
723     proto_tree_add_uint(tree, hf_dplay_size, tvb, offset, 4, size);
724     proto_tree_add_uint(tree, hf_dplay_token, tvb, offset, 4, token);
725     offset += 4;
726     offset = dissect_sockaddr_in(tree, tvb, offset);
727     proto_tree_add_item(tree, hf_dplay_play_str, tvb, offset, 4, ENC_ASCII|ENC_NA); offset += 4;
728     proto_tree_add_item(tree, hf_dplay_command, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2;
729     proto_tree_add_item(tree, hf_dplay_proto_dialect, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2;
730     return offset;
731 }
732
733 static gint dissect_type01_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
734 {
735     guint32 name_offset;
736
737     offset = dissect_session_desc(tree, tvb, offset);
738     name_offset = tvb_get_letohl(tvb, offset);
739     proto_tree_add_item(tree, hf_dplay_type_01_name_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
740
741     if (name_offset != 0) {
742         offset = display_unicode_string(tree, hf_dplay_type_01_game_name, tvb, offset);
743     }
744     return offset;
745 }
746
747 static gint dissect_type02_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
748 {
749     guint32 passwd_offset;
750     guint32 flags;
751     proto_item *flags_item = NULL;
752     proto_tree *flags_tree = NULL;
753
754     passwd_offset = tvb_get_letohl(tvb, offset + 16);
755     flags = tvb_get_letohl(tvb, offset + 20);
756
757     proto_tree_add_item(tree, hf_dplay_type_02_game_guid, tvb, offset, 16, ENC_BIG_ENDIAN); offset += 16;
758     proto_tree_add_item(tree, hf_dplay_type_02_password_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
759
760     flags_item = proto_tree_add_item(tree, hf_dplay_type_02_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
761     flags_tree = proto_item_add_subtree(flags_item, ett_dplay_type02_flags);
762     proto_tree_add_boolean(flags_tree, hf_enum_sess_flag_passwd, tvb, offset, 4, flags);
763     proto_tree_add_boolean(flags_tree, hf_enum_sess_flag_all, tvb, offset, 4, flags);
764     proto_tree_add_boolean(flags_tree, hf_enum_sess_flag_join, tvb, offset, 4, flags);
765     offset += 4;
766
767     if (passwd_offset != 0) {
768         offset = display_unicode_string(tree, hf_dplay_type_02_password, tvb, offset);
769     }
770     return offset;
771 }
772
773 static gint dissect_type05_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
774 {
775     proto_item *flag_item;
776     proto_item *flag_tree;
777     guint32 flags;
778
779     flags = tvb_get_letohl(tvb, offset);
780     flag_item = proto_tree_add_item(tree, hf_dplay_type_05_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
781     flag_tree = proto_item_add_subtree(flag_item, ett_dplay_type05_flags);
782     proto_tree_add_boolean(flag_tree, hf_dplay_type_05_secure, tvb, offset, 4, flags);
783     proto_tree_add_boolean(flag_tree, hf_dplay_type_05_unknown, tvb, offset, 4, flags);
784     proto_tree_add_boolean(flag_tree, hf_dplay_type_05_local, tvb, offset, 4, flags);
785     proto_tree_add_boolean(flag_tree, hf_dplay_type_05_name_server, tvb, offset, 4, flags);
786     proto_tree_add_boolean(flag_tree, hf_dplay_type_05_system_player, tvb, offset, 4, flags);
787     offset += 4;
788     return offset;
789 }
790
791 static gint dissect_type07_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
792 {
793     guint32 sspi_offset, capi_offset;
794
795     proto_tree_add_item(tree, hf_dplay_type_07_dpid, tvb, offset, 4, ENC_NA); offset += 4;
796     offset = dissect_security_desc(tree, tvb, offset);
797
798     sspi_offset = tvb_get_letohl(tvb, offset);
799     proto_tree_add_item(tree, hf_dplay_type_07_sspi_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
800
801     capi_offset = tvb_get_letohl(tvb, offset);
802     proto_tree_add_item(tree, hf_dplay_type_07_capi_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
803
804     proto_tree_add_item(tree, hf_dplay_type_07_hresult, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
805
806     if (sspi_offset) {
807         offset = display_unicode_string(tree, hf_dplay_type_07_sspi, tvb, offset);
808     }
809
810     if (capi_offset) {
811         offset = display_unicode_string(tree, hf_dplay_type_07_capi, tvb, offset);
812     }
813     return offset;
814 }
815
816 static gint dissect_player_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
817 {
818     guint32 pp_ofs;
819
820     proto_tree_add_item(tree, hf_dplay_multi_id_to, tvb, offset, 4, ENC_NA); offset += 4;
821     proto_tree_add_item(tree, hf_dplay_multi_player_id, tvb, offset, 4, ENC_NA); offset += 4;
822     proto_tree_add_item(tree, hf_dplay_multi_group_id, tvb, offset, 4, ENC_NA); offset += 4;
823     pp_ofs = tvb_get_letohl(tvb, offset);
824     proto_tree_add_item(tree, hf_dplay_multi_create_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
825     proto_tree_add_item(tree, hf_dplay_multi_password_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
826     if (pp_ofs)
827         offset = dissect_packed_player(tree, tvb, offset);
828     if (tvb_bytes_exist(tvb, offset, 2))
829         offset = display_unicode_string(tree, hf_dplay_multi_password, tvb, offset);
830     return offset;
831 }
832
833 static gint dissect_type0f_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
834 {
835     guint32 data_size;
836
837     proto_tree_add_item(tree, hf_dplay_type_0f_id_to, tvb, offset, 4, ENC_NA); offset += 4;
838     proto_tree_add_item(tree, hf_dplay_type_0f_id, tvb, offset, 4, ENC_NA); offset += 4;
839     data_size = tvb_get_letohl(tvb, offset);
840     proto_tree_add_item(tree, hf_dplay_type_0f_data_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
841     proto_tree_add_item(tree, hf_dplay_type_0f_data_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
842     proto_tree_add_item(tree, hf_dplay_type_0f_data, tvb, offset, data_size, ENC_NA);
843     offset += data_size;
844
845     return offset;
846 }
847
848 static gint dissect_type13_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
849 {
850     guint32 pp_ofs, pw_ofs;
851
852     proto_tree_add_item(tree, hf_dplay_type_13_id_to, tvb, offset, 4, ENC_NA); offset += 4;
853     proto_tree_add_item(tree, hf_dplay_type_13_player_id, tvb, offset, 4, ENC_NA); offset += 4;
854     proto_tree_add_item(tree, hf_dplay_type_13_group_id, tvb, offset, 4, ENC_NA); offset += 4;
855     pp_ofs = tvb_get_letohl(tvb, offset);
856     proto_tree_add_item(tree, hf_dplay_type_13_create_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
857     pw_ofs = tvb_get_letohl(tvb, offset);
858     proto_tree_add_item(tree, hf_dplay_type_13_password_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
859     if (pp_ofs)
860         offset = dissect_packed_player(tree, tvb, offset);
861     if (pw_ofs)
862         offset = display_unicode_string(tree, hf_dplay_type_13_password, tvb, offset);
863     proto_tree_add_item(tree, hf_dplay_type_13_tick_count, tvb, offset, 4, ENC_NA); offset += 4;
864
865     return offset;
866 }
867
868 static gint dissect_type15_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
869 {
870     guint16 second_message_type;
871     proto_item *enc_item = NULL;
872     proto_tree *enc_tree = NULL;
873     second_message_type = tvb_get_letohs(tvb, 72);
874
875     proto_tree_add_item(tree, hf_dplay_message_guid, tvb, offset, 16, ENC_BIG_ENDIAN); offset += 16;
876     proto_tree_add_item(tree, hf_dplay_type_15_packet_idx, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
877     proto_tree_add_item(tree, hf_dplay_type_15_data_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
878     proto_tree_add_item(tree, hf_dplay_type_15_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
879     proto_tree_add_item(tree, hf_dplay_type_15_total_packets, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
880     proto_tree_add_item(tree, hf_dplay_type_15_msg_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
881     proto_tree_add_item(tree, hf_dplay_type_15_packet_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
882
883     enc_item = proto_tree_add_text(tree, tvb, offset, -1, "DirectPlay encapsulated packet");
884     enc_tree = proto_item_add_subtree(enc_item, ett_dplay_enc_packet);
885
886     proto_tree_add_item(enc_tree, hf_dplay_play_str_2, tvb, offset, 4, ENC_ASCII|ENC_NA); offset += 4;
887     proto_tree_add_item(enc_tree, hf_dplay_command_2, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2;
888     proto_tree_add_item(enc_tree, hf_dplay_proto_dialect_2, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2;
889
890     switch(second_message_type)
891     {
892         case 0x0005:
893             offset = dissect_type05_message(enc_tree, tvb, offset);
894             break;
895         case 0x0007:
896             offset = dissect_type05_message(enc_tree, tvb, offset);
897             break;
898         case 0x0008:
899         case 0x0009:
900         case 0x000b:
901         case 0x000c:
902         case 0x000d:
903         case 0x000e:
904         case 0x002e:
905             offset = dissect_player_message(enc_tree, tvb, offset);
906             break;
907         case 0x0013:
908             offset = dissect_type13_message(enc_tree, tvb, offset);
909             break;
910         case 0x001a:
911             offset = dissect_type1a_message(enc_tree, tvb, offset);
912             break;
913     }
914
915     return offset;
916 }
917
918 static gint dissect_ping_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
919 {
920     proto_tree_add_item(tree, hf_dplay_ping_id_from, tvb, offset, 4, ENC_NA); offset += 4;
921     proto_tree_add_item(tree, hf_dplay_ping_tick_count, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
922
923     return offset;
924 }
925
926 static gint dissect_type1a_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
927 {
928     guint32 sn_ofs, pw_ofs;
929
930     proto_tree_add_item(tree, hf_dplay_type_1a_id_to, tvb, offset, 4, ENC_NA); offset += 4;
931     sn_ofs = tvb_get_letohl(tvb, offset);
932     proto_tree_add_item(tree, hf_dplay_type_1a_sess_name_ofs, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
933     pw_ofs = tvb_get_letohl(tvb, offset);
934     proto_tree_add_item(tree, hf_dplay_type_1a_password_ofs, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
935     offset = dissect_session_desc(tree, tvb, offset);
936
937     if (sn_ofs) {
938         offset = display_unicode_string(tree, hf_dplay_type_1a_session_name, tvb, offset);
939     }
940
941     if (pw_ofs) {
942         offset = display_unicode_string(tree, hf_dplay_type_1a_password, tvb, offset);
943     }
944
945     return offset;
946 }
947
948 static gint dissect_type29_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
949 {
950     guint32 password_offset = tvb_get_letohl(tvb, offset + 24);
951     gint player_count, group_count, shortcut_count;
952     gint i;
953
954     player_count = tvb_get_letohl(tvb, offset);
955     proto_tree_add_item(tree, hf_dplay_type_29_player_count, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
956     group_count = tvb_get_letohl(tvb, offset);
957     proto_tree_add_item(tree, hf_dplay_type_29_group_count, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
958     proto_tree_add_item(tree, hf_dplay_type_29_packed_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
959     shortcut_count = tvb_get_letohl(tvb, offset);
960     proto_tree_add_item(tree, hf_dplay_type_29_shortcut_count, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
961     proto_tree_add_item(tree, hf_dplay_type_29_description_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
962     proto_tree_add_item(tree, hf_dplay_type_29_name_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
963     proto_tree_add_item(tree, hf_dplay_type_29_password_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
964     offset = dissect_session_desc(tree, tvb, offset);
965     offset = display_unicode_string(tree, hf_dplay_type_29_game_name, tvb, offset);
966
967     if (password_offset != 0) {
968         offset = display_unicode_string(tree, hf_dplay_type_29_password, tvb, offset);
969     }
970
971     for (i=0; i < player_count; ++i) {
972         proto_item *spp_item;
973         proto_tree *spp_tree;
974
975         spp_item = proto_tree_add_text(tree, tvb, offset, 0, "Player %d", i);
976         spp_tree = proto_item_add_subtree(spp_item, ett_dplay_type29_spp);
977         offset = dissect_dplay_super_packed_player(spp_tree, tvb, offset);
978     }
979
980     for (i=0; i < group_count; ++i) {
981         proto_item *spp_item;
982         proto_tree *spp_tree;
983
984         spp_item = proto_tree_add_text(tree, tvb, offset, 0, "Group %d", i);
985         spp_tree = proto_item_add_subtree(spp_item, ett_dplay_type29_spp);
986         offset = dissect_dplay_super_packed_player(spp_tree, tvb, offset);
987     }
988
989     for (i=0; i < shortcut_count; ++i) {
990         proto_item *spp_item;
991         proto_tree *spp_tree;
992
993         spp_item = proto_tree_add_text(tree, tvb, offset, 0, "Shortcut %d", i);
994         spp_tree = proto_item_add_subtree(spp_item, ett_dplay_type29_spp);
995         offset = dissect_dplay_super_packed_player(spp_tree, tvb, offset);
996     }
997
998     return offset;
999 }
1000
1001 static gint dissect_type2f_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
1002 {
1003     proto_tree_add_item(tree, hf_dplay_type_2f_dpid, tvb, offset, 4, ENC_NA); offset += 4;
1004     return offset;
1005 }
1006
1007 static void dissect_dplay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1008 {
1009     guint16 message_type;
1010     guint16 second_message_type = G_MAXUINT16;
1011     guint16 proto_version;
1012     guint32 dplay_id;
1013     guint8 play_id[] = {'p','l','a','y'};
1014
1015     dplay_id = tvb_get_letohl(tvb, 20);
1016     message_type = tvb_get_letohs(tvb, 24);
1017     proto_version = tvb_get_letohs(tvb, 26);
1018
1019     if(memcmp(play_id, (guint8 *)&dplay_id, 4) != 0)
1020     {
1021         col_set_str(pinfo->cinfo, COL_PROTOCOL, "DPLAY");
1022         col_set_str(pinfo->cinfo,COL_INFO, "DPlay data packet");
1023         return;
1024     }
1025
1026     if(message_type == 0x0015)
1027     {
1028         second_message_type = tvb_get_letohs(tvb, 72);
1029     }
1030
1031     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DPLAY");
1032
1033     if(message_type == 0x0015)
1034         col_add_fstr(pinfo->cinfo,COL_INFO, "%s: %s, holding a %s",
1035             val_to_str(proto_version, dplay_proto_dialect_val, "Unknown (0x%04x)"),
1036             val_to_str(message_type, dplay_command_val, "Unknown (0x%04x)"),
1037             val_to_str(second_message_type, dplay_command_val, "Unknown (0x%04x)"));
1038     else
1039         col_add_fstr(pinfo->cinfo,COL_INFO, "%s: %s",
1040             val_to_str(proto_version, dplay_proto_dialect_val, "Unknown (0x%04x)"),
1041             val_to_str(message_type, dplay_command_val, "Unknown (0x%04x)"));
1042
1043     if(tree)
1044     {
1045         proto_item *dplay_item = NULL;
1046         proto_item *header_item = NULL;
1047         proto_item *data_item = NULL;
1048         proto_tree *dplay_tree = NULL;
1049         proto_tree *dplay_header = NULL;
1050         proto_tree *dplay_data = NULL;
1051         gint offset = 0;
1052
1053         dplay_item = proto_tree_add_item(tree, proto_dplay, tvb, 0, -1, ENC_NA);
1054         dplay_tree = proto_item_add_subtree(dplay_item, ett_dplay);
1055         header_item = proto_tree_add_text(dplay_tree, tvb, offset, DPLAY_HEADER_OFFSET, "DirectPlay header");
1056         dplay_header = proto_item_add_subtree(header_item, ett_dplay_header);
1057
1058         offset = dissect_dplay_header(dplay_header, tvb, offset);
1059
1060         /* Special handling for empty type 0x0004 packets */
1061         if(message_type == 0x0004)
1062             return;
1063
1064         data_item = proto_tree_add_text(dplay_tree, tvb, offset, -1, "DirectPlay data");
1065         dplay_data = proto_item_add_subtree(data_item, ett_dplay_data);
1066
1067         switch(message_type)
1068         {
1069             case 0x0001:
1070                 dissect_type01_message(dplay_data, tvb, offset);
1071                 break;
1072             case 0x0002:
1073                 dissect_type02_message(dplay_data, tvb, offset);
1074                 break;
1075             case 0x0005:
1076                 dissect_type05_message(dplay_data, tvb, offset);
1077                 break;
1078             case 0x0007:
1079                 dissect_type07_message(dplay_data, tvb, offset);
1080                 break;
1081             case 0x0008:
1082             case 0x0009:
1083             /* type 0a doesn't have a dplay header and is not handled here */
1084             case 0x000b:
1085             case 0x000c:
1086             case 0x000d:
1087             case 0x000e:
1088             case 0x002e:
1089             case 0x0038:
1090                 dissect_player_message(dplay_data, tvb, offset);
1091                 break;
1092             case 0x000f:
1093                 dissect_type0f_message(dplay_data, tvb, offset);
1094                 break;
1095             case 0x0013:
1096                 dissect_type13_message(dplay_data, tvb, offset);
1097                 break;
1098             case 0x0015:
1099                 dissect_type15_message(dplay_data, tvb, offset);
1100                 break;
1101             case 0x0016:
1102             case 0x0017:
1103                 dissect_ping_message(dplay_data, tvb, offset);
1104                 break;
1105             case 0x001a:
1106                 dissect_type1a_message(dplay_data, tvb, offset);
1107                 break;
1108             case 0x0029:
1109                 dissect_type29_message(dplay_data, tvb, offset);
1110                 break;
1111             case 0x002f:
1112                 dissect_type2f_message(dplay_data, tvb, offset);
1113                 break;
1114         }
1115     }
1116
1117 }
1118
1119 static void dissect_dplay_player_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1120 {
1121     guint32 mixed, size, token;
1122
1123     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DPLAY");
1124     col_set_str(pinfo->cinfo,COL_INFO, "DPlay player to player message");
1125
1126     if(tree)
1127     {
1128         proto_item *dplay_item = NULL;
1129         proto_item *data_item = NULL;
1130         proto_tree *dplay_tree = NULL;
1131         proto_tree *data_tree = NULL;
1132         gint offset = 0;
1133
1134         dplay_item = proto_tree_add_item(tree, proto_dplay, tvb, offset, -1, ENC_NA);
1135         dplay_tree = proto_item_add_subtree(dplay_item, ett_dplay);
1136         data_item  = proto_tree_add_text(dplay_tree, tvb, offset, -1, "Message content");
1137         data_tree  = proto_item_add_subtree(data_item, ett_dplay_data);
1138         mixed = tvb_get_letohl(tvb, offset);
1139         size = mixed & 0x000FFFFF;
1140         token = (mixed & 0xFFF00000) >> 20;
1141
1142         proto_tree_add_uint(data_tree, hf_dplay_size, tvb, offset, 4, size);
1143         proto_tree_add_uint(data_tree, hf_dplay_token, tvb, offset, 4, token);
1144         offset += 4;
1145         offset = dissect_sockaddr_in(data_tree, tvb, offset);
1146         /* Now there's two dplay IDs iff the session desc does not have the
1147          * "short player message" flag set */
1148         proto_tree_add_item(data_tree, hf_dplay_player_msg, tvb, offset, -1, ENC_NA);
1149
1150     }
1151 }
1152 static gboolean heur_dissect_dplay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1153 {
1154     guint32 dplay_id, token;
1155
1156     if(tvb_length(tvb) < 25)
1157         return FALSE;
1158
1159     /* The string play = 0x706c6179 */
1160     dplay_id = tvb_get_letohl(tvb, 20);
1161     if( dplay_id == 0x706c6179) {
1162         dissect_dplay(tvb, pinfo, tree);
1163         return TRUE;
1164     }
1165
1166
1167     /* There is a player to player message that does not contain "play" */
1168     token = tvb_get_letohl(tvb, 0);
1169     token = (token & 0xfff00000) >> 20;
1170     if (token == 0xfab || token == 0xbab || token == 0xcab) {
1171       /* Check the s_addr_in structure */
1172       if (tvb_get_letohs(tvb, 4) == WINSOCK_AF_INET) {
1173         int offset;
1174         for (offset = 12; offset <= 20; offset++)
1175           if (tvb_get_guint8(tvb, offset) != 0)
1176             return FALSE;
1177
1178         dissect_dplay_player_msg(tvb, pinfo, tree);
1179         return TRUE;
1180       }
1181     }
1182
1183     return FALSE;
1184 }
1185
1186 void proto_register_dplay(void)
1187 {
1188     static hf_register_info hf [] = {
1189     /* Common data fields */
1190     { &hf_dplay_size,
1191         { "DirectPlay package size", "dplay.size", FT_UINT32, BASE_DEC,
1192         NULL, 0x0, NULL, HFILL}},
1193     { &hf_dplay_token,
1194         { "DirectPlay token", "dplay.token", FT_UINT32, BASE_HEX,
1195         VALS(dplay_token_val), 0x0, NULL, HFILL}},
1196     { &hf_dplay_saddr_af,
1197         { "DirectPlay s_addr_in address family", "dplay.saddr.af", FT_UINT16, BASE_HEX,
1198         VALS(dplay_af_val), 0x0, NULL, HFILL}},
1199     { &hf_dplay_saddr_port,
1200         { "DirectPlay s_addr_in port", "dplay.saddr.port", FT_UINT16, BASE_DEC,
1201         NULL, 0x0, NULL, HFILL}},
1202     { &hf_dplay_saddr_ip,
1203         { "DirectPlay s_addr_in ip address", "dplay.saddr.ip", FT_IPv4, BASE_NONE,
1204         NULL, 0x0, NULL, HFILL}},
1205     { &hf_dplay_saddr_padding,
1206         { "DirectPlay s_addr_in null padding", "dplay.saddr.padding", FT_BYTES, BASE_NONE,
1207         NULL, 0x0, NULL, HFILL}},
1208     { &hf_dplay_play_str,
1209         { "DirectPlay action string", "dplay.dplay_str", FT_STRING, BASE_NONE,
1210         NULL, 0x0, NULL, HFILL}},
1211     { &hf_dplay_command,
1212         { "DirectPlay command", "dplay.command", FT_UINT16, BASE_HEX,
1213         VALS(dplay_command_val), 0x0, NULL, HFILL}},
1214     { &hf_dplay_proto_dialect,
1215         { "DirectPlay dialect version", "dplay.dialect.version", FT_UINT16, BASE_HEX,
1216         VALS(dplay_proto_dialect_val), 0x0, NULL, HFILL}},
1217     { &hf_dplay_play_str_2,
1218         { "DirectPlay second action string", "dplay.dplay_str_2", FT_STRING, BASE_NONE,
1219         NULL, 0x0, NULL, HFILL}},
1220     { &hf_dplay_command_2,
1221         { "DirectPlay second command", "dplay.command_2", FT_UINT16, BASE_HEX,
1222         VALS(dplay_command_val), 0x0, NULL, HFILL}},
1223     { &hf_dplay_proto_dialect_2,
1224         { "DirectPlay second dialect version", "dplay.dialect.version_2", FT_UINT16, BASE_HEX,
1225         VALS(dplay_proto_dialect_val), 0x0, NULL, HFILL}},
1226     { &hf_dplay_player_msg,
1227         { "DirectPlay Player to Player message", "dplay.player_msg", FT_BYTES, BASE_NONE,
1228         NULL, 0x0, NULL, HFILL}},
1229
1230     /* Session Desc structure fields */
1231     { &hf_dplay_sess_desc_flags,
1232         { "DirectPlay session desc flags", "dplay.flags", FT_UINT32, BASE_HEX,
1233         NULL, 0x0, NULL, HFILL}},
1234     { &hf_dplay_flags_no_create_players,
1235         { "no create players flag", "dplay.flags.no_create_players", FT_BOOLEAN, 32,
1236         TFS(&tfs_dplay_flag), DPLAY_FLAG_NO_CREATE_PLAYERS, "No Create Players", HFILL}},
1237     { &hf_dplay_flags_0002,
1238         { "unused", "dplay.flags.unused", FT_BOOLEAN, 32,
1239         TFS(&tfs_dplay_flag), DPLAY_FLAG_0002, NULL, HFILL}},
1240     { &hf_dplay_flags_migrate_host,
1241         { "migrate host flag", "dplay.flags.migrate_host", FT_BOOLEAN, 32,
1242         TFS(&tfs_dplay_flag), DPLAY_FLAG_MIGRATE_HOST, "Migrate Host", HFILL}},
1243     { &hf_dplay_flags_short_player_msg,
1244         { "short player message", "dplay.flags.short_player_msg", FT_BOOLEAN, 32,
1245         TFS(&tfs_dplay_flag), DPLAY_FLAG_SHORT_PLAYER_MSG, "Short Player Msg", HFILL}},
1246     { &hf_dplay_flags_ignored,
1247         { "ignored", "dplay.flags.ignored", FT_BOOLEAN, 32,
1248         TFS(&tfs_dplay_flag), DPLAY_FLAG_IGNORED, NULL, HFILL}},
1249     { &hf_dplay_flags_can_join,
1250         { "can join", "dplay.flags.can_join", FT_BOOLEAN, 32,
1251         TFS(&tfs_dplay_flag), DPLAY_FLAG_CAN_JOIN, NULL, HFILL}},
1252     { &hf_dplay_flags_use_ping,
1253         { "use ping", "dplay.flags.use_ping", FT_BOOLEAN, 32,
1254         TFS(&tfs_dplay_flag), DPLAY_FLAG_USE_PING, NULL, HFILL}},
1255     { &hf_dplay_flags_no_player_updates,
1256         { "no player updates", "dplay.flags.no_player_updates", FT_BOOLEAN, 32,
1257         TFS(&tfs_dplay_flag), DPLAY_FLAG_NO_P_UPD, NULL, HFILL}},
1258     { &hf_dplay_flags_use_auth,
1259         { "use authentication", "dplay.flags.use_auth", FT_BOOLEAN, 32,
1260         TFS(&tfs_dplay_flag), DPLAY_FLAG_USE_AUTH, "Use Auth", HFILL}},
1261     { &hf_dplay_flags_private_session,
1262         { "private session", "dplay.flags.priv_sess", FT_BOOLEAN, 32,
1263         TFS(&tfs_dplay_flag), DPLAY_FLAG_PRIV_SESS, "Priv Session", HFILL}},
1264     { &hf_dplay_flags_password_req,
1265         { "password required", "dplay.flags.pass_req", FT_BOOLEAN, 32,
1266         TFS(&tfs_dplay_flag), DPLAY_FLAG_PASS_REQ, "Pass Req", HFILL}},
1267     { &hf_dplay_flags_route,
1268         { "route via game host", "dplay.flags.route", FT_BOOLEAN, 32,
1269         TFS(&tfs_dplay_flag), DPLAY_FLAG_ROUTE, "Route", HFILL}},
1270     { &hf_dplay_flags_server_player_only,
1271         { "get server player only", "dplay.flags.srv_p_only", FT_BOOLEAN, 32,
1272         TFS(&tfs_dplay_flag), DPLAY_FLAG_SRV_ONLY, "Svr Player Only", HFILL}},
1273     { &hf_dplay_flags_reliable,
1274         { "use reliable protocol", "dplay.flags.reliable", FT_BOOLEAN, 32,
1275         TFS(&tfs_dplay_flag), DPLAY_FLAG_RELIABLE, "Reliable", HFILL}},
1276     { &hf_dplay_flags_preserve_order,
1277         { "preserve order", "dplay.flags.order", FT_BOOLEAN, 32,
1278         TFS(&tfs_dplay_flag), DPLAY_FLAG_ORDER, "Order", HFILL}},
1279     { &hf_dplay_flags_optimize_latency,
1280         { "optimize for latency", "dplay.flags.opt_latency", FT_BOOLEAN, 32,
1281         TFS(&tfs_dplay_flag), DPLAY_FLAG_OPT_LAT, "Opt Latency", HFILL}},
1282     { &hf_dplay_flags_acqire_voice,
1283         { "acquire voice", "dplay.flags.acq_voice", FT_BOOLEAN, 32,
1284         TFS(&tfs_dplay_flag), DPLAY_FLAG_ACQ_VOICE, "Acq Voice", HFILL}},
1285     { &hf_dplay_flags_no_sess_desc_changes,
1286         { "no session desc changes", "dplay.flags.no_sess_desc", FT_BOOLEAN, 32,
1287         TFS(&tfs_dplay_flag), DPLAY_FLAG_NO_SESS_DESC_CHANGES, "No Sess Desc Changes", HFILL}},
1288     { &hf_dplay_instance_guid,
1289         { "DirectPlay instance guid", "dplay.instance.guid", FT_GUID, BASE_NONE,
1290         NULL, 0x0, NULL, HFILL}},
1291     { &hf_dplay_game_guid,
1292         { "DirectPlay game GUID", "dplay.game.guid", FT_GUID, BASE_NONE,
1293         NULL, 0x0, NULL, HFILL}},
1294     { &hf_dplay_sess_desc_length,
1295         { "DirectPlay session desc length", "dplay.sess_desc.length", FT_UINT32, BASE_DEC,
1296         NULL, 0x0, NULL, HFILL}},
1297     { &hf_dplay_max_players,
1298         { "DirectPlay max players", "dplay.sess_desc.max_players", FT_UINT32, BASE_DEC,
1299         NULL, 0x0, NULL, HFILL}},
1300     { &hf_dplay_curr_players,
1301         { "DirectPlay current players", "dplay.sess_desc.curr_players", FT_UINT32, BASE_DEC,
1302         NULL, 0x0, NULL, HFILL}},
1303     { &hf_dplay_sess_name_ptr,
1304         { "Session description name pointer placeholder", "dplay.sess_desc.name_ptr", FT_BYTES, BASE_NONE,
1305         NULL, 0x0, NULL, HFILL}},
1306     { &hf_dplay_passwd_ptr,
1307         { "Session description password pointer placeholder", "dplay.sess_desc.pw_ptr", FT_BYTES, BASE_NONE,
1308         NULL, 0x0, NULL, HFILL}},
1309     { &hf_dplay_sess_desc_reserved_1,
1310         { "Session description reserved 1", "dplay.sess_desc.res_1", FT_BYTES, BASE_NONE,
1311         NULL, 0x0, NULL, HFILL}},
1312     { &hf_dplay_sess_desc_reserved_2,
1313         { "Session description reserved 2", "dplay.sess_desc.res_2", FT_BYTES, BASE_NONE,
1314         NULL, 0x0, NULL, HFILL}},
1315     { &hf_dplay_sess_desc_user_1,
1316         { "Session description user defined 1", "dplay.sess_desc.user_1", FT_BYTES, BASE_NONE,
1317         NULL, 0x0, NULL, HFILL}},
1318     { &hf_dplay_sess_desc_user_2,
1319         { "Session description user defined 2", "dplay.sess_desc.user_2", FT_BYTES, BASE_NONE,
1320         NULL, 0x0, NULL, HFILL}},
1321     { &hf_dplay_sess_desc_user_3,
1322         { "Session description user defined 3", "dplay.sess_desc.user_3", FT_BYTES, BASE_NONE,
1323         NULL, 0x0, NULL, HFILL}},
1324     { &hf_dplay_sess_desc_user_4,
1325         { "Session description user defined 4", "dplay.sess_desc.user_4", FT_BYTES, BASE_NONE,
1326         NULL, 0x0, NULL, HFILL}},
1327
1328     /* PackedPlayer structure fields */
1329     { &hf_dplay_pp_size,
1330         { "PackedPlayer size", "dplay.pp.size", FT_UINT32, BASE_DEC,
1331         NULL, 0x0, NULL, HFILL}},
1332     { &hf_dplay_pp_flags,
1333         { "PackedPlayer flags", "dplay.pp.flags", FT_UINT32, BASE_HEX,
1334         NULL, 0x0, NULL, HFILL}},
1335     { &hf_dplay_pp_flag_sysplayer,
1336         { "is system player", "dplay.pp.flags.sysplayer", FT_BOOLEAN, 32,
1337         TFS(&tfs_dplay_flag), DPLAY_PP_FLAG_SYSPLAYER, NULL, HFILL}},
1338     { &hf_dplay_pp_flag_nameserver,
1339         { "is name server", "dplay.pp.flags.nameserver", FT_BOOLEAN, 32,
1340         TFS(&tfs_dplay_flag), DPLAY_PP_FLAG_NAMESERVER, NULL, HFILL}},
1341     { &hf_dplay_pp_flag_in_group,
1342         { "in group", "dplay.pp.flags.in_group", FT_BOOLEAN, 32,
1343         TFS(&tfs_dplay_flag), DPLAY_PP_FLAG_IN_GROUP, NULL, HFILL}},
1344     { &hf_dplay_pp_flag_sending,
1345         { "sending player on local machine", "dplay.pp.flags.sending", FT_BOOLEAN, 32,
1346         TFS(&tfs_dplay_flag), DPLAY_SPP_FLAG_SENDING, NULL, HFILL}},
1347     { &hf_dplay_pp_id,
1348         { "PackedPlayer ID", "dplay.pp.id", FT_BYTES, BASE_NONE,
1349         NULL, 0x0, NULL, HFILL}},
1350     { &hf_dplay_pp_short_name_len,
1351         { "PackedPlayer short name length", "dplay.pp.short_name_len", FT_UINT32, BASE_HEX,
1352         NULL, 0x0, NULL, HFILL}},
1353     { &hf_dplay_pp_long_name_len,
1354         { "PackedPlayer long name length", "dplay.pp.long_name_len", FT_UINT32, BASE_HEX,
1355         NULL, 0x0, NULL, HFILL}},
1356     { &hf_dplay_pp_sp_data_size,
1357         { "PackedPlayer service provider data size", "dplay.pp.sp_data_size", FT_UINT32, BASE_HEX,
1358         NULL, 0x0, NULL, HFILL}},
1359     { &hf_dplay_pp_player_data_size,
1360         { "PackedPlayer player data size", "dplay.pp.player_data_size", FT_UINT32, BASE_HEX,
1361         NULL, 0x0, NULL, HFILL}},
1362     { &hf_dplay_pp_num_players,
1363         { "PackedPlayer player count", "dplay.pp.player_count", FT_UINT32, BASE_HEX,
1364         NULL, 0x0, NULL, HFILL}},
1365     { &hf_dplay_pp_system_player,
1366         { "PackedPlayer system player ID", "dplay.pp.sysplayer_id", FT_BYTES, BASE_NONE,
1367         NULL, 0x0, NULL, HFILL}},
1368     { &hf_dplay_pp_fixed_size,
1369         { "PackedPlayer fixed size", "dplay.pp.fixed_size", FT_UINT32, BASE_DEC,
1370         NULL, 0x0, NULL, HFILL}},
1371     { &hf_dplay_pp_dialect,
1372         { "PackedPlayer dialect version", "dplay.pp.dialect", FT_UINT32, BASE_HEX,
1373         VALS(dplay_proto_dialect_val), 0x0, NULL, HFILL}},
1374     { &hf_dplay_pp_unknown_1,
1375         { "PackedPlayer unknown 1", "dplay.pp.unknown_1", FT_BYTES, BASE_NONE,
1376         NULL, 0x0, NULL, HFILL}},
1377     { &hf_dplay_pp_short_name,
1378         { "PackedPlayer short name", "dplay.pp.short_name", FT_STRING, BASE_NONE,
1379         NULL, 0x0, NULL, HFILL}},
1380     { &hf_dplay_pp_long_name,
1381         { "PackedPlayer long name", "dplay.pp.long_name", FT_STRING, BASE_NONE,
1382         NULL, 0x0, NULL, HFILL}},
1383     { &hf_dplay_pp_player_data,
1384         { "PackedPlayer player data", "dplay.pp.player_data", FT_BYTES, BASE_NONE,
1385         NULL, 0x0, NULL, HFILL}},
1386     { &hf_dplay_pp_sp_data,
1387         { "PackedPlayer service provider data", "dplay.pp.sp_data", FT_BYTES, BASE_NONE,
1388         NULL, 0x0, NULL, HFILL}},
1389     { &hf_dplay_pp_player_id,
1390         { "PackedPlayer player ID", "dplay.pp.player_id", FT_BYTES, BASE_NONE,
1391         NULL, 0x0, NULL, HFILL}},
1392     { &hf_dplay_pp_parent_id,
1393         { "PackedPlayer parent ID", "dplay.pp.parent_id", FT_BYTES, BASE_NONE,
1394         NULL, 0x0, NULL, HFILL}},
1395
1396     /* SuperPackedPlayer structure fields */
1397     { &hf_dplay_spp_size,
1398         { "SuperPackedPlayer size", "dplay.spp.size", FT_UINT32, BASE_DEC,
1399         NULL, 0x0, NULL, HFILL}},
1400     { &hf_dplay_spp_flags,
1401         { "SuperPackedPlayer flags", "dplay.spp.flags", FT_UINT32, BASE_HEX,
1402         NULL, 0x0, NULL, HFILL}},
1403     { &hf_dplay_spp_flags_sysplayer,
1404         { "is system player", "dplay.spp.flags.sysplayer", FT_BOOLEAN, 32,
1405         TFS(&tfs_dplay_flag), DPLAY_SPP_FLAG_SYSPLAYER, NULL, HFILL}},
1406     { &hf_dplay_spp_flags_nameserver,
1407         { "is name server", "dplay.spp.flags.nameserver", FT_BOOLEAN, 32,
1408         TFS(&tfs_dplay_flag), DPLAY_SPP_FLAG_NAMESERVER, NULL, HFILL}},
1409     { &hf_dplay_spp_flags_in_group,
1410         { "in group", "dplay.spp.flags.in_group", FT_BOOLEAN, 32,
1411         TFS(&tfs_dplay_flag), DPLAY_SPP_FLAG_IN_GROUP, NULL, HFILL}},
1412     { &hf_dplay_spp_flags_sending,
1413         { "sending player on local machine", "dplay.spp.flags.sending", FT_BOOLEAN, 32,
1414         TFS(&tfs_dplay_flag), DPLAY_SPP_FLAG_SENDING, NULL, HFILL}},
1415     { &hf_dplay_spp_id,
1416         { "SuperPackedPlayer ID", "dplay.spp.id", FT_BYTES, BASE_NONE,
1417         NULL, 0x0, NULL, HFILL}},
1418     { &hf_dplay_spp_player_info_mask,
1419         { "SuperPackedPlayer player info mask", "dplay.spp.pim", FT_UINT32, BASE_HEX,
1420         NULL, 0x0, NULL, HFILL}},
1421     { &hf_dplay_spp_have_short_name,
1422         { "SuperPackedPlayer have short name", "dplay.spp.pim.short_name", FT_UINT32, BASE_HEX,
1423         VALS(yes_no_val), 0x0, NULL, HFILL}},
1424     { &hf_dplay_spp_have_long_name,
1425         { "SuperPackedPlayer have long name", "dplay.spp.pim.long_name", FT_UINT32, BASE_HEX,
1426         VALS(yes_no_val), 0x0, NULL, HFILL}},
1427     { &hf_dplay_spp_sp_length_type,
1428         { "SuperPackedPlayer service provider length info", "dplay.spp.pim.sp_length", FT_UINT32, BASE_HEX,
1429         VALS(dplay_spp_length_val), 0x0, NULL, HFILL}},
1430     { &hf_dplay_spp_pd_length_type,
1431         { "SuperPackedPlayer player data length info", "dplay.spp.pim.pd_length", FT_UINT32, BASE_HEX,
1432         VALS(dplay_spp_length_val), 0x0, NULL, HFILL}},
1433     { &hf_dplay_spp_player_count_type,
1434         { "SuperPackedPlayer player count info", "dplay.spp.pim.player_count", FT_UINT32, BASE_HEX,
1435         VALS(dplay_spp_length_val), 0x0, NULL, HFILL}},
1436     { &hf_dplay_spp_have_parent_id,
1437         { "SuperPackedPlayer have parent ID", "dplay.spp.pim.parent_id", FT_UINT32, BASE_HEX,
1438         VALS(yes_no_val), 0x0, NULL, HFILL}},
1439     { &hf_dplay_spp_shortcut_count_type,
1440         { "SuperPackedPlayer shortcut count info", "dplay.spp.pim.shortcut_count", FT_UINT32, BASE_HEX,
1441         VALS(dplay_spp_length_val), 0x0, NULL, HFILL}},
1442     { &hf_dplay_spp_dialect,
1443         { "SuperPackedPlayer dialect version", "dplay.spp.dialect", FT_UINT32, BASE_HEX,
1444         VALS(dplay_proto_dialect_val), 0x0, NULL, HFILL}},
1445     { &hf_dplay_spp_sys_player_id,
1446         { "SuperPackedPlayer system player ID", "dplay.spp.sysplayer_id", FT_BYTES, BASE_NONE,
1447         NULL, 0x0, NULL, HFILL}},
1448     { &hf_dplay_spp_short_name,
1449         { "SuperPackedPlayer short name", "dplay.spp.short_name", FT_STRING, BASE_NONE,
1450         NULL, 0x0, NULL, HFILL}},
1451     { &hf_dplay_spp_long_name,
1452         { "SuperPackedPlayer long name", "dplay.spp.long_name", FT_STRING, BASE_NONE,
1453         NULL, 0x0, NULL, HFILL}},
1454     { &hf_dplay_spp_player_data_length,
1455         { "SuperPackedPlayer player data length", "dplay.spp.pd_length", FT_UINT32, BASE_HEX,
1456         NULL, 0x0, NULL, HFILL}},
1457     { &hf_dplay_spp_player_data,
1458         { "SuperPackedPlayer player data", "dplay.spp.player_data", FT_BYTES, BASE_NONE,
1459         NULL, 0x0, NULL, HFILL}},
1460     { &hf_dplay_spp_sp_data_length,
1461         { "SuperPackedPlayer service provider data length", "dplay.spp.sp_data_length", FT_UINT32, BASE_HEX,
1462         NULL, 0x0, NULL, HFILL}},
1463     { &hf_dplay_spp_sp_data,
1464         { "SuperPackedPlayer service provider data", "dplay.spp.sp_data", FT_BYTES, BASE_NONE,
1465         NULL, 0x0, NULL, HFILL}},
1466     { &hf_dplay_spp_player_count,
1467         { "SuperPackedPlayer player count", "dplay.spp.player_count", FT_UINT32, BASE_HEX,
1468         NULL, 0x0, NULL, HFILL}},
1469     { &hf_dplay_spp_player_id,
1470         { "SuperPackedPlayer player ID", "dplay.spp.player_id", FT_BYTES, BASE_NONE,
1471         NULL, 0x0, NULL, HFILL}},
1472     { &hf_dplay_spp_parent_id,
1473         { "SuperPackedPlayer parent ID", "dplay.spp.parent_id", FT_BYTES, BASE_NONE,
1474         NULL, 0x0, NULL, HFILL}},
1475     { &hf_dplay_spp_shortcut_count,
1476         { "SuperPackedPlayer shortcut count", "dplay.spp.shortcut_count", FT_UINT32, BASE_HEX,
1477         NULL, 0x0, NULL, HFILL}},
1478     { &hf_dplay_spp_shortcut_id,
1479         { "SuperPackedPlayer shortcut ID", "dplay.spp.shortcut_id", FT_BYTES, BASE_NONE,
1480         NULL, 0x0, NULL, HFILL}},
1481
1482     /* Data fields for SecDesc struct */
1483     { &hf_dplay_sd_size,
1484         { "SecDesc struct size", "dplay.sd.size", FT_UINT32, BASE_DEC,
1485         NULL, 0x0, NULL, HFILL}},
1486     { &hf_dplay_sd_flags,
1487         { "SecDesc flags", "dplay.sd.flags", FT_UINT32, BASE_HEX,
1488         NULL, 0x0, NULL, HFILL}},
1489     { &hf_dplay_sd_sspi,
1490         { "SecDesc SSPI provider ptr", "dplay.sd.sspi", FT_BYTES, BASE_NONE,
1491         NULL, 0x0, NULL, HFILL}},
1492     { &hf_dplay_sd_capi,
1493         { "SecDesc CAPI provider ptr", "dplay.sd.capi", FT_BYTES, BASE_NONE,
1494         NULL, 0x0, NULL, HFILL}},
1495     { &hf_dplay_sd_capi_type,
1496         { "SecDesc CAPI provider type", "dplay.sd.capi_type", FT_UINT32, BASE_HEX,
1497         NULL, 0x0, NULL, HFILL}},
1498     { &hf_dplay_sd_enc_alg,
1499         { "SecDesc encryption algorithm" , "dplay.sd.enc_alg", FT_UINT32, BASE_HEX,
1500         VALS(dplay_enc_alg_val), 0x0, NULL, HFILL}},
1501
1502     /* Data fields for message type 0x0001 */
1503     { &hf_dplay_type_01_name_offset,
1504         { "Enum Session Reply name offset", "dplay.type_01.name_offs", FT_UINT32, BASE_DEC,
1505         NULL, 0x0, NULL, HFILL}},
1506     { &hf_dplay_type_01_game_name,
1507         { "Enum Session Reply game name", "dplay.type_01.game_name", FT_STRING, BASE_NONE,
1508         NULL, 0x0, NULL, HFILL}},
1509
1510     /* Data fields for message type 0x0002 */
1511     { &hf_dplay_type_02_game_guid,
1512         { "DirectPlay game GUID", "dplay.type02.game.guid", FT_GUID, BASE_NONE,
1513         NULL, 0x0, NULL, HFILL}},
1514     { &hf_dplay_type_02_password_offset,
1515         { "Enum Sessions password offset", "dplay.type02.password_offset", FT_UINT32, BASE_DEC,
1516         NULL, 0x0, NULL, HFILL}},
1517     { &hf_dplay_type_02_flags,
1518         { "Enum Session flags", "dplay.type02.flags", FT_UINT32, BASE_HEX,
1519         NULL, 0x0, NULL, HFILL}},
1520     { &hf_dplay_type_02_password,
1521         { "Session password", "dplay.type02.password", FT_STRING, BASE_NONE,
1522         NULL, 0x0, NULL, HFILL}},
1523     { &hf_enum_sess_flag_join,
1524         { "Enumerate joinable sessions", "dplay.type02.joinable", FT_BOOLEAN, 32,
1525         TFS(&tfs_dplay_flag), DPLAY_ENUM_SESS_FLAG_JOIN, "Joinable", HFILL}},
1526     { &hf_enum_sess_flag_all,
1527         { "Enumerate all sessions", "dplay.type02.all", FT_BOOLEAN, 32,
1528         TFS(&tfs_dplay_flag), DPLAY_ENUM_SESS_FLAG_ALL, "All", HFILL}},
1529     { &hf_enum_sess_flag_passwd,
1530         { "Enumerate sessions requiring a password", "dplay.type02.pw_req", FT_BOOLEAN, 32,
1531         TFS(&tfs_dplay_flag), DPLAY_ENUM_SESS_FLAG_PASSWD, "Password", HFILL}},
1532
1533     /* Data fields for message type 0x0005 */
1534     { &hf_dplay_type_05_flags,
1535         { "Player ID request flags", "dplay.type_05.flags", FT_UINT32, BASE_HEX,
1536         NULL, 0x0, NULL, HFILL}},
1537     { &hf_dplay_type_05_system_player,
1538         { "is system player", "dplay.type_05.flags.sys_player", FT_BOOLEAN, 32,
1539         TFS(&tfs_dplay_flag), DPLAY_TYPE05_FLAG_SYSPLAYER, NULL, HFILL}},
1540     { &hf_dplay_type_05_name_server,
1541         { "is name server", "dplay.type_05.flags.name_server", FT_BOOLEAN, 32,
1542         TFS(&tfs_dplay_flag), DPLAY_TYPE05_FLAG_NAMESERVER, NULL, HFILL}},
1543     { &hf_dplay_type_05_local,
1544         { "is local player", "dplay.type_05.flags.local", FT_BOOLEAN, 32,
1545         TFS(&tfs_dplay_flag), DPLAY_TYPE05_FLAG_LOCAL, NULL, HFILL}},
1546     { &hf_dplay_type_05_unknown,
1547         { "unknown", "dplay.type_05.flags.unknown", FT_BOOLEAN, 32,
1548         TFS(&tfs_dplay_flag), DPLAY_TYPE05_FLAG_UNKNOWN, NULL, HFILL}},
1549     { &hf_dplay_type_05_secure,
1550         { "is secure session", "dplay.type_05.flags.secure", FT_BOOLEAN, 32,
1551         TFS(&tfs_dplay_flag), DPLAY_TYPE05_FLAG_SECURE, NULL, HFILL}},
1552
1553     /* Data fields for message type 0x0007 */
1554     { &hf_dplay_type_07_dpid,
1555         { "DirectPlay ID", "dplay.type_07.dpid", FT_BYTES, BASE_NONE,
1556         NULL, 0x0, NULL, HFILL}},
1557     { &hf_dplay_type_07_sspi_offset,
1558         { "SSPI provider offset", "dplay.type_07.sspi_offset", FT_UINT32, BASE_DEC,
1559         NULL, 0x0, NULL, HFILL}},
1560     { &hf_dplay_type_07_capi_offset,
1561         { "CAPI provider offset", "dplay.type_07.capi_offset", FT_UINT32, BASE_DEC,
1562         NULL, 0x0, NULL, HFILL}},
1563     { &hf_dplay_type_07_hresult,
1564         { "Request player HRESULT", "dplay.type_07.hresult", FT_UINT32, BASE_DEC,
1565         NULL, 0x0, NULL, HFILL}},
1566     { &hf_dplay_type_07_sspi,
1567         { "SSPI provider", "dplay.type_07.sspi", FT_STRING, BASE_NONE,
1568         NULL, 0x0, NULL, HFILL}},
1569     { &hf_dplay_type_07_capi,
1570         { "CAPI provider", "dplay.type_07.capi", FT_STRING, BASE_NONE,
1571         NULL, 0x0, NULL, HFILL}},
1572
1573     /* Data fields for message type 0x0008, 0x0009, 0x000b, 0x000c, 0x000d,
1574      * 0x000e, 0x002e and 0x0038*/
1575     { &hf_dplay_multi_id_to,
1576         { "ID to", "dplay.multi.id_to", FT_BYTES, BASE_NONE,
1577         NULL, 0x0, NULL, HFILL}},
1578     { &hf_dplay_multi_player_id,
1579         { "Player ID", "dplay.multi.player_id", FT_BYTES, BASE_NONE,
1580         NULL, 0x0, NULL, HFILL}},
1581     { &hf_dplay_multi_group_id,
1582         { "Group ID", "dplay.multi.group_id", FT_BYTES, BASE_NONE,
1583         NULL, 0x0, NULL, HFILL}},
1584     { &hf_dplay_multi_create_offset,
1585         { "Offset to PackedPlayer struct", "dplay.multi.create_offset", FT_UINT32, BASE_DEC,
1586         NULL, 0x0, NULL, HFILL}},
1587     { &hf_dplay_multi_password_offset,
1588         { "Offset to password", "dplay.multi.password_offset", FT_UINT32, BASE_DEC,
1589         NULL, 0x0, NULL, HFILL}},
1590     { &hf_dplay_multi_password,
1591         { "Password", "dplay.multi.password", FT_STRING, BASE_NONE,
1592         NULL, 0x0, NULL, HFILL}},
1593
1594     /* Data fields for message type 0x000f */
1595     { &hf_dplay_type_0f_id_to,
1596         { "ID to", "dplay.type_0f.id_to", FT_BYTES, BASE_NONE,
1597         NULL, 0x0, NULL, HFILL}},
1598     { &hf_dplay_type_0f_id,
1599         { "Player ID", "dplay.type_0f.player_id", FT_BYTES, BASE_NONE,
1600         NULL, 0x0, NULL, HFILL}},
1601     { &hf_dplay_type_0f_data_size,
1602         { "Data Size", "dplay.type_0f.data_size", FT_UINT32, BASE_DEC,
1603         NULL, 0x0, NULL, HFILL}},
1604     { &hf_dplay_type_0f_data_offset,
1605         { "Data Offset", "dplay.type_0f.data_offset", FT_UINT32, BASE_DEC,
1606         NULL, 0x0, NULL, HFILL}},
1607     { &hf_dplay_type_0f_data,
1608         { "Player Data", "dplay.type_0f.player_data", FT_BYTES, BASE_NONE,
1609         NULL, 0x0, NULL, HFILL}},
1610
1611     /* Data fields for message type 0x0013 */
1612     { &hf_dplay_type_13_id_to,
1613         { "ID to", "dplay.type_13.id_to", FT_BYTES, BASE_NONE,
1614         NULL, 0x0, NULL, HFILL}},
1615     { &hf_dplay_type_13_player_id,
1616         { "Player ID", "dplay.type_13.player_id", FT_BYTES, BASE_NONE,
1617         NULL, 0x0, NULL, HFILL}},
1618     { &hf_dplay_type_13_group_id,
1619         { "Group ID", "dplay.type_13.group_id", FT_BYTES, BASE_NONE,
1620         NULL, 0x0, NULL, HFILL}},
1621     { &hf_dplay_type_13_create_offset,
1622         { "Create Offset", "dplay.type_13.create_offset", FT_UINT32, BASE_DEC,
1623         NULL, 0x0, NULL, HFILL}},
1624     { &hf_dplay_type_13_password_offset,
1625         { "Password Offset", "dplay.type_13.password_offset", FT_UINT32, BASE_DEC,
1626         NULL, 0x0, NULL, HFILL}},
1627     { &hf_dplay_type_13_password,
1628         { "Password", "dplay.type_13.password", FT_STRING, BASE_NONE,
1629         NULL, 0x0, NULL, HFILL}},
1630     { &hf_dplay_type_13_tick_count,
1631         { "Tick count? Looks like an ID", "dplay.type_13.tick_count", FT_BYTES, BASE_NONE,
1632         NULL, 0x0, NULL, HFILL}},
1633
1634     /* Data fields for message type 0x0015 */
1635     { &hf_dplay_message_guid,
1636         { "Message GUID", "dplay.message.guid", FT_GUID, BASE_NONE,
1637         NULL, 0x0, NULL, HFILL}},
1638     { &hf_dplay_type_15_packet_idx,
1639         { "Packet Index", "dplay.type_15.packet_idx", FT_UINT32, BASE_DEC,
1640         NULL, 0x0, NULL, HFILL}},
1641     { &hf_dplay_type_15_data_size,
1642         { "Data Size", "dplay.type_15.data_size", FT_UINT32, BASE_DEC,
1643         NULL, 0x0, NULL, HFILL}},
1644     { &hf_dplay_type_15_offset,
1645         { "Offset", "dplay.type_15.offset", FT_UINT32, BASE_DEC,
1646         NULL, 0x0, NULL, HFILL}},
1647     { &hf_dplay_type_15_total_packets,
1648         { "Total Packets", "dplay.type_15.total_packets", FT_UINT32, BASE_DEC,
1649         NULL, 0x0, NULL, HFILL}},
1650     { &hf_dplay_type_15_msg_size,
1651         { "Message size", "dplay.type_15.message.size", FT_UINT32, BASE_DEC,
1652         NULL, 0x0, NULL, HFILL}},
1653     { &hf_dplay_type_15_packet_offset,
1654         { "Packet offset", "dplay.type_15.packet_offset", FT_UINT32, BASE_DEC,
1655         NULL, 0x0, NULL, HFILL}},
1656
1657     /* Data field for message type 0x0016 and 0x0017 */
1658     { &hf_dplay_ping_id_from,
1659         { "ID From", "dplay.ping.id_from", FT_BYTES, BASE_NONE,
1660         NULL, 0x0, NULL, HFILL}},
1661     { &hf_dplay_ping_tick_count,
1662         { "Tick Count", "dplay.ping.tick_count", FT_UINT32, BASE_DEC,
1663         NULL, 0x0, NULL, HFILL}},
1664
1665     /* Data fields for message type 0x001a */
1666     { &hf_dplay_type_1a_id_to,
1667         { "ID From", "dplay.type_1a.id_to", FT_BYTES, BASE_NONE,
1668         NULL, 0x0, NULL, HFILL}},
1669     { &hf_dplay_type_1a_sess_name_ofs,
1670         { "Session Name Offset", "dplay.type_1a.sess_name_ofs", FT_UINT32, BASE_DEC,
1671         NULL, 0x0, NULL, HFILL}},
1672     { &hf_dplay_type_1a_password_ofs,
1673         { "Password Offset", "dplay.type_1a.password_offset", FT_UINT32, BASE_DEC,
1674         NULL, 0x0, NULL, HFILL}},
1675     { &hf_dplay_type_1a_session_name,
1676         { "Session Name", "dplay.type_1a.session_name", FT_STRING, BASE_NONE,
1677         NULL, 0x0, NULL, HFILL}},
1678     { &hf_dplay_type_1a_password,
1679         { "Password", "dplay.type_1a.password", FT_STRING, BASE_NONE,
1680         NULL, 0x0, NULL, HFILL}},
1681
1682     /* Data fields for message type 0x0029 */
1683     { &hf_dplay_type_29_player_count,
1684         { "SuperEnumPlayers Reply player count", "dplay.type_29.player_count", FT_UINT32,
1685         BASE_DEC, NULL, 0x0, NULL, HFILL}},
1686     { &hf_dplay_type_29_group_count,
1687         { "SuperEnumPlayers Reply group count", "dplay.type_29.group_count", FT_UINT32,
1688         BASE_DEC, NULL, 0x0, NULL, HFILL}},
1689     { &hf_dplay_type_29_packed_offset,
1690         { "SuperEnumPlayers Reply packed offset", "dplay.type_29.packed_offset", FT_UINT32,
1691         BASE_DEC, NULL, 0x0, NULL, HFILL}},
1692     { &hf_dplay_type_29_shortcut_count,
1693         { "SuperEnumPlayers Reply shortcut count", "dplay.type_29.shortcut_count", FT_UINT32,
1694         BASE_DEC, NULL, 0x0, NULL, HFILL}},
1695     { &hf_dplay_type_29_description_offset,
1696         { "SuperEnumPlayers Reply description offset", "dplay.type_29.desc_offset", FT_UINT32,
1697         BASE_DEC, NULL, 0x0, NULL, HFILL}},
1698     { &hf_dplay_type_29_name_offset,
1699         { "SuperEnumPlayers Reply name offset", "dplay.type_29.name_offset", FT_UINT32,
1700         BASE_DEC, NULL, 0x0, NULL, HFILL}},
1701     { &hf_dplay_type_29_password_offset,
1702         { "SuperEnumPlayers Reply password offset", "dplay.type_29.pass_offset", FT_UINT32,
1703         BASE_DEC, NULL, 0x0, NULL, HFILL}},
1704     { &hf_dplay_type_29_game_name,
1705         { "SuperEnumPlayers Reply game name", "dplay.type_29.game_name", FT_STRING, BASE_NONE,
1706         NULL, 0x0, NULL, HFILL}},
1707     { &hf_dplay_type_29_password,
1708         { "SuperEnumPlayers Reply Password", "dplay.type_29.password", FT_STRING, BASE_NONE,
1709         NULL, 0x0, NULL, HFILL}},
1710
1711     /* Data fields for message type 0x002f */
1712     { &hf_dplay_type_2f_dpid,
1713         { "ID of the forwarded player", "dplay.type_29.id", FT_BYTES, BASE_NONE,
1714         NULL, 0x0, NULL, HFILL}},
1715     };
1716
1717     static gint *ett[] = {
1718         &ett_dplay,
1719         &ett_dplay_header,
1720         &ett_dplay_sockaddr,
1721         &ett_dplay_data,
1722         &ett_dplay_flags,
1723         &ett_dplay_enc_packet,
1724         &ett_dplay_sess_desc_flags,
1725         &ett_dplay_pp_flags,
1726         &ett_dplay_spp_flags,
1727         &ett_dplay_spp_info_mask,
1728         &ett_dplay_type02_flags,
1729         &ett_dplay_type05_flags,
1730         &ett_dplay_type29_spp,
1731     };
1732
1733     proto_dplay = proto_register_protocol (
1734         "DirectPlay Protocol",
1735         "DPLAY",
1736         "dplay"
1737         );
1738     proto_register_field_array(proto_dplay, hf, array_length(hf));
1739     proto_register_subtree_array(ett, array_length(ett));
1740 }
1741
1742 void proto_reg_handoff_dplay(void)
1743 {
1744     heur_dissector_add("udp", heur_dissect_dplay, proto_dplay);
1745     heur_dissector_add("tcp", heur_dissect_dplay, proto_dplay);
1746 }