change a whole bunch of ethereal into wireshark
[obnox/wireshark/wip.git] / epan / dissectors / packet-dcerpc-wkssvc.c
1 /* packet-dcerpc-wkssvc.c
2  * Routines for SMB \\PIPE\\wkssvc packet disassembly
3  * Copyright 2001, Tim Potter <tpot@samba.org>
4  * Copyright 2003, Richard Sharpe <rsharpe@richardsharpe.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <glib.h>
32 #include <epan/packet.h>
33 #include "packet-dcerpc.h"
34 #include "packet-dcerpc-wkssvc.h"
35 #include "packet-dcerpc-nt.h"
36 #include "packet-windows-common.h"
37
38 static int proto_dcerpc_wkssvc = -1;
39 static int hf_wkssvc_opnum = -1;
40 static int hf_wkssvc_server = -1;
41 static int hf_wkssvc_info_level = -1;
42 static int hf_wkssvc_platform_id = -1; 
43 static int hf_wkssvc_net_group = -1;
44 static int hf_wkssvc_ver_major = -1;
45 static int hf_wkssvc_ver_minor = -1;
46 static int hf_wkssvc_lan_root = -1;
47 static int hf_wkssvc_rc = -1;
48 static int hf_wkssvc_logged_on_users = -1;
49 static int hf_wkssvc_pref_max = -1;
50 static int hf_wkssvc_enum_handle = -1;
51 static int hf_wkssvc_junk = -1;
52 static int hf_wkssvc_user_name = -1;
53 static int hf_wkssvc_num_entries = -1;
54 static int hf_wkssvc_logon_domain = -1;
55 static int hf_wkssvc_other_domains = -1;
56 static int hf_wkssvc_logon_server = -1;
57 static int hf_wkssvc_entries_read = -1;
58 static int hf_wkssvc_total_entries = -1;
59 static int hf_wkssvc_char_wait = -1;
60 static int hf_wkssvc_collection_time = -1;
61 static int hf_wkssvc_maximum_collection_count = -1;
62 static int hf_wkssvc_keep_conn = -1;
63 static int hf_wkssvc_max_cmds = -1;
64 static int hf_wkssvc_sess_timeout = -1;
65 static int hf_wkssvc_siz_char_buf = -1;
66 static int hf_wkssvc_max_threads = -1;
67 static int hf_wkssvc_lock_quota = -1;
68 static int hf_wkssvc_lock_increment = -1;
69 static int hf_wkssvc_lock_maximum = -1;
70 static int hf_wkssvc_pipe_increment = -1;
71 static int hf_wkssvc_pipe_maximum = -1;
72 static int hf_wkssvc_cache_file_timeout = -1;
73 static int hf_wkssvc_dormant_file_limit = -1;
74 static int hf_wkssvc_read_ahead_throughput = -1;
75 static int hf_wkssvc_num_mailslot_buffers = -1;
76 static int hf_wkssvc_num_srv_announce_buffers = -1;
77 static int hf_wkssvc_max_illegal_datagram_events = -1;
78 static int hf_wkssvc_illegal_datagram_event_reset_frequency = -1;
79 static int hf_wkssvc_log_election_packets = -1;
80 static int hf_wkssvc_use_opportunistic_locking = -1; 
81 static int hf_wkssvc_use_unlock_behind = -1; 
82 static int hf_wkssvc_use_close_behind = -1; 
83 static int hf_wkssvc_buf_named_pipes = -1;
84 static int hf_wkssvc_use_lock_read_unlock = -1;
85 static int hf_wkssvc_utilize_nt_caching = -1;
86 static int hf_wkssvc_use_raw_read = -1;
87 static int hf_wkssvc_use_raw_write = -1;
88 static int hf_wkssvc_use_write_raw_data = -1;
89 static int hf_wkssvc_use_encryption = -1; 
90 static int hf_wkssvc_buf_files_deny_write = -1;
91 static int hf_wkssvc_buf_read_only_files = -1;
92 static int hf_wkssvc_force_core_create_mode = -1;
93 static int hf_wkssvc_use_512_byte_max_transfer = -1;
94 static int hf_wkssvc_parm_err = -1;
95 static int hf_wkssvc_errlog_sz = -1;
96 static int hf_wkssvc_print_buf_time = -1;
97 static int hf_wkssvc_wrk_heuristics = -1;
98 static int hf_wkssvc_quality_of_service = -1;
99 static int hf_wkssvc_number_of_vcs = -1;
100 static int hf_wkssvc_transport_name = -1;
101 static int hf_wkssvc_transport_address = -1;
102 static int hf_wkssvc_wan_ish = -1;
103 static int hf_wkssvc_domain_to_join = -1;
104 static int hf_wkssvc_ou_for_computer_account = -1;
105 static int hf_wkssvc_account_used_for_join = -1;
106 static int hf_wkssvc_encrypted_password = -1;
107 static int hf_wkssvc_join_flags = -1;
108 static int hf_wkssvc_unjoin_flags = -1;
109 static int hf_wkssvc_rename_flags = -1;
110 static int hf_wkssvc_join_options_join_type = -1;
111 static int hf_wkssvc_join_options_acct_create = -1;
112 static int hf_wkssvc_unjoin_options_acct_delete = -1;
113 static int hf_wkssvc_join_options_win9x_upgrade = -1;
114 static int hf_wkssvc_join_options_domain_join_if_joined = -1;
115 static int hf_wkssvc_join_options_join_unsecure = -1;
116 static int hf_wkssvc_join_options_machine_pwd_passed = -1;
117 static int hf_wkssvc_join_options_defer_spn_set = -1;
118 static int hf_wkssvc_account_used_for_unjoin = -1;
119 static int hf_wkssvc_alternate_name = -1;
120 static int hf_wkssvc_account_used_for_alternate_name = -1;
121 static int hf_wkssvc_reserved = -1;
122
123 static gint ett_dcerpc_wkssvc = -1;
124 static gint ett_dcerpc_wkssvc_join_flags = -1;
125
126
127 static e_uuid_t uuid_dcerpc_wkssvc = {
128         0x6bffd098, 0xa112, 0x3610,
129         { 0x98, 0x33, 0x46, 0xc3, 0xf8, 0x7e, 0x34, 0x5a }
130 };
131
132 static int
133 wkssvc_dissect_ENUM_HANDLE(tvbuff_t *tvb, int offset,
134                            packet_info *pinfo, proto_tree *tree,
135                            guint8 *drep)
136 {
137
138   offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
139                               hf_wkssvc_enum_handle, 0);
140   return offset;
141
142 }
143
144 static guint16 ver_dcerpc_wkssvc = 1;
145
146 /*
147  * IDL typedef struct {
148  * IDL   long platform_id;
149  * IDL   [string] [unique] wchar_t *server;
150  * IDL   [string] [unique] wchar_t *lan_grp;
151  * IDL   long ver_major;
152  * IDL   long ver_minor;
153  * IDL } WKS_INFO_100;
154  */
155 static int
156 wkssvc_dissect_WKS_INFO_100(tvbuff_t *tvb, int offset,
157                             packet_info *pinfo, proto_tree *tree,
158                             guint8 *drep)
159 {
160         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
161                         hf_wkssvc_platform_id, NULL);
162
163         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
164                         NDR_POINTER_UNIQUE, "Server", hf_wkssvc_server, 0);
165
166         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
167                         NDR_POINTER_UNIQUE, "Net Group", hf_wkssvc_net_group, 0);
168
169         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
170                         hf_wkssvc_ver_major, NULL);
171
172         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
173                         hf_wkssvc_ver_minor, NULL);
174
175         return offset;
176 }
177
178 /*
179  * IDL typedef struct {
180  * IDL   long platform_id;
181  * IDL   [string] [unique] wchar_t *server;
182  * IDL   [string] [unique] wchar_t *lan_grp;
183  * IDL   long ver_major;
184  * IDL   long ver_minor;
185  * IDL   [string] [unique] wchar_t *lan_root;
186  * IDL } WKS_INFO_101;
187  */
188 static int
189 wkssvc_dissect_WKS_INFO_101(tvbuff_t *tvb, int offset,
190                             packet_info *pinfo, proto_tree *tree,
191                             guint8 *drep)
192 {
193         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
194                         hf_wkssvc_platform_id, NULL);
195
196         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
197                         NDR_POINTER_UNIQUE, "Server", hf_wkssvc_server, 0);
198
199         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
200                         NDR_POINTER_UNIQUE, "Net Group", hf_wkssvc_net_group, 0);
201
202         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
203                         hf_wkssvc_ver_major, NULL);
204
205         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
206                         hf_wkssvc_ver_minor, NULL);
207
208         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
209                         NDR_POINTER_UNIQUE, "Lan Root", hf_wkssvc_lan_root, 0);
210
211         return offset;
212 }
213
214 /*
215  * IDL typedef struct {
216  * IDL   long platform_id;
217  * IDL   [string] [unique] wchar_t *server;
218  * IDL   [string] [unique] wchar_t *lan_grp;
219  * IDL   long ver_major;
220  * IDL   long ver_minor;
221  * IDL   [string] [unique] wchar_t *lan_root;
222  * IDL   long logged_on_users;
223  * IDL } WKS_INFO_102;
224  */
225 static int
226 wkssvc_dissect_WKS_INFO_102(tvbuff_t *tvb, int offset,
227                             packet_info *pinfo, proto_tree *tree,
228                             guint8 *drep)
229 {
230         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
231                         hf_wkssvc_platform_id, NULL);
232
233         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
234                         NDR_POINTER_UNIQUE, "Server", hf_wkssvc_server, 0);
235
236         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
237                         NDR_POINTER_UNIQUE, "Net Group", hf_wkssvc_net_group, 0);
238
239         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
240                         hf_wkssvc_ver_major, NULL);
241
242         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
243                         hf_wkssvc_ver_minor, NULL);
244
245         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
246                         NDR_POINTER_UNIQUE, "Lan Root", hf_wkssvc_lan_root, 0);
247
248         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
249                         hf_wkssvc_logged_on_users, NULL);
250
251         return offset;
252 }
253 /*
254  * IDL typedef struct {
255  * IDL   long wki502_sess_timeout;
256  * IDL } WKS_INFO_502;
257  */
258 static int
259 wkssvc_dissect_WKS_INFO_502(tvbuff_t *tvb, int offset,
260                             packet_info *pinfo, proto_tree *tree,
261                             guint8 *drep)
262 {
263         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
264                         hf_wkssvc_char_wait, NULL);
265
266         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
267                         hf_wkssvc_collection_time, NULL);
268
269         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
270                         hf_wkssvc_maximum_collection_count, NULL);
271
272         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
273                         hf_wkssvc_keep_conn, NULL);
274
275         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
276                         hf_wkssvc_max_cmds, NULL);
277
278         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
279                         hf_wkssvc_sess_timeout, NULL);
280
281         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
282                         hf_wkssvc_siz_char_buf, NULL);
283
284         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
285                         hf_wkssvc_max_threads, NULL);   
286
287         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
288                         hf_wkssvc_lock_quota, NULL);    
289
290         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
291                         hf_wkssvc_lock_increment, NULL);        
292
293         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
294                         hf_wkssvc_lock_maximum, NULL);  
295
296         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
297                         hf_wkssvc_pipe_increment, NULL);        
298
299         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
300                         hf_wkssvc_pipe_maximum, NULL);  
301
302         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
303                         hf_wkssvc_cache_file_timeout, NULL);    
304
305         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
306                         hf_wkssvc_dormant_file_limit, NULL);    
307
308         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
309                         hf_wkssvc_read_ahead_throughput, NULL); 
310
311         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
312                         hf_wkssvc_num_mailslot_buffers, NULL);  
313
314         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
315                         hf_wkssvc_num_srv_announce_buffers, NULL);      
316
317         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
318                         hf_wkssvc_max_illegal_datagram_events, NULL);   
319
320         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
321                             hf_wkssvc_illegal_datagram_event_reset_frequency, 
322                                     NULL);
323
324         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
325                         hf_wkssvc_log_election_packets, NULL);  
326
327         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
328                         hf_wkssvc_use_opportunistic_locking, NULL);
329
330         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
331                         hf_wkssvc_use_unlock_behind, NULL);
332
333         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
334                         hf_wkssvc_use_close_behind, NULL);
335
336         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
337                         hf_wkssvc_buf_named_pipes, NULL);                       
338         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
339                         hf_wkssvc_use_lock_read_unlock, NULL);  
340
341         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
342                         hf_wkssvc_utilize_nt_caching, NULL);    
343
344         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
345                         hf_wkssvc_use_raw_read, NULL);  
346
347         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
348                         hf_wkssvc_use_raw_write, NULL); 
349
350         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
351                         hf_wkssvc_use_write_raw_data, NULL);    
352
353         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
354                         hf_wkssvc_use_encryption, NULL);        
355
356         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
357                         hf_wkssvc_buf_files_deny_write, NULL);  
358
359         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
360                         hf_wkssvc_buf_read_only_files, NULL);   
361
362         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
363                         hf_wkssvc_force_core_create_mode, NULL);        
364
365         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
366                         hf_wkssvc_use_512_byte_max_transfer, NULL);     
367
368         return offset;
369 }
370
371 static int
372 wkssvc_dissect_WKS_INFO_1010(tvbuff_t *tvb, int offset,
373                              packet_info *pinfo, proto_tree *tree,
374                              guint8 *drep)
375 {
376         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
377                         hf_wkssvc_char_wait, NULL);
378
379         return offset;
380 }
381
382 static int
383 wkssvc_dissect_WKS_INFO_1011(tvbuff_t *tvb, int offset,
384                              packet_info *pinfo, proto_tree *tree,
385                              guint8 *drep)
386 {
387         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
388                         hf_wkssvc_collection_time, NULL);
389
390         return offset;
391 }
392
393 static int
394 wkssvc_dissect_WKS_INFO_1012(tvbuff_t *tvb, int offset,
395                              packet_info *pinfo, proto_tree *tree,
396                              guint8 *drep)
397 {
398         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
399                         hf_wkssvc_maximum_collection_count, NULL);
400
401         return offset;
402 }
403
404 static int
405 wkssvc_dissect_WKS_INFO_1013(tvbuff_t *tvb, int offset,
406                              packet_info *pinfo, proto_tree *tree,
407                              guint8 *drep)
408 {
409         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
410                         hf_wkssvc_keep_conn, NULL);
411
412         return offset;
413 }
414
415 static int
416 wkssvc_dissect_WKS_INFO_1018(tvbuff_t *tvb, int offset,
417                              packet_info *pinfo, proto_tree *tree,
418                              guint8 *drep)
419 {
420         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
421                         hf_wkssvc_sess_timeout, NULL);
422
423         return offset;
424 }
425
426 static int
427 wkssvc_dissect_WKS_INFO_1023(tvbuff_t *tvb, int offset,
428                              packet_info *pinfo, proto_tree *tree,
429                              guint8 *drep)
430 {
431         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
432                         hf_wkssvc_siz_char_buf, NULL);
433
434         return offset;
435 }
436
437 static int
438 wkssvc_dissect_WKS_INFO_1027(tvbuff_t *tvb, int offset,
439                              packet_info *pinfo, proto_tree *tree,
440                              guint8 *drep)
441 {
442         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
443                         hf_wkssvc_errlog_sz, NULL);
444
445         return offset;
446 }
447
448 static int
449 wkssvc_dissect_WKS_INFO_1033(tvbuff_t *tvb, int offset,
450                              packet_info *pinfo, proto_tree *tree,
451                              guint8 *drep)
452 {
453         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
454                         hf_wkssvc_max_threads, NULL);
455
456         return offset;
457 }
458
459 /*
460  * IDL long NetWkstaGetInfo(
461  * IDL      [in] [string] [unique] wchar_t *ServerName,
462  * IDL      [in] long level,
463  * IDL      [out] [ref] WKS_INFO_UNION *wks
464  * IDL );
465  */
466 static int
467 wkssvc_dissect_netwkstagetinfo_rqst(tvbuff_t *tvb, int offset, 
468                                     packet_info *pinfo, proto_tree *tree,
469                                     guint8 *drep)
470 {
471         dcerpc_info *di;
472         guint32 level;
473
474         di = pinfo->private_data;
475
476         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
477                                               NDR_POINTER_UNIQUE, "Server", 
478                                               hf_wkssvc_server, 0);
479
480         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
481                                     hf_wkssvc_info_level, &level);
482
483         if (!check_col(pinfo->cinfo, COL_INFO))
484                 return offset;
485
486         switch (level) {
487                 case 100:
488                         col_append_str(pinfo->cinfo, COL_INFO, ", WKS_INFO_100 level");
489                         break;
490                 case 101:
491                         col_append_str(pinfo->cinfo, COL_INFO, ", WKS_INFO_101 level");
492                         break;
493                 case 102:
494                         col_append_str(pinfo->cinfo, COL_INFO, ", WKS_INFO_102 level");
495                         break;
496                 case 502:
497                         col_append_str(pinfo->cinfo, COL_INFO, ", WKS_INFO_502 level");
498                         break;
499                 default:
500                         col_append_str(pinfo->cinfo, COL_INFO, ", WKS_INFO_xxx level");
501         }       
502
503         return offset;
504
505 }
506
507 /*
508  * IDL typedef [switch_type(long)] union {
509  * IDL   [case(100)] [unique] WKS_INFO_100 *wks100;
510  * IDL   [case(101)] [unique] WKS_INFO_101 *wks101;
511  * IDL   [case(102)] [unique] WKS_INFO_102 *wks102;
512  * IDL   [case(502)] [unique] WKS_INFO_502 *wks502;
513  * IDL   [case(1010)] [unique] WKS_INFO_1010 *wks1010;
514  * IDL   [case(1011)] [unique] WKS_INFO_1011 *wks1011;
515  * IDL   [case(1012)] [unique] WKS_INFO_1012 *wks1012;
516  * IDL   [case(1013)] [unique] WKS_INFO_1013 *wks1013;
517  * IDL   [case(1018)] [unique] WKS_INFO_1018 *wks1018;
518  * IDL   [case(1023)] [unique] WKS_INFO_1023 *wks1023;
519  * IDL   [case(1027)] [unique] WKS_INFO_1027 *wks1027;
520  * IDL   [case(1033)] [unique] WKS_INFO_1033 *wks1033;
521  * IDL } WKS_INFO_UNION;
522  */
523 static int
524 wkssvc_dissect_WKS_GETINFO_UNION(tvbuff_t *tvb, int offset,
525                                  packet_info *pinfo, proto_tree *tree,
526                                  guint8 *drep)
527 {
528         guint32 level;
529
530         ALIGN_TO_4_BYTES;
531
532         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_wkssvc_info_level, &level);
533
534         switch(level){
535         case 100:
536                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
537                         wkssvc_dissect_WKS_INFO_100,
538                         NDR_POINTER_UNIQUE, "WKS_INFO_100:", -1);
539                 break;
540
541         case 101:
542                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
543                         wkssvc_dissect_WKS_INFO_101,
544                         NDR_POINTER_UNIQUE, "WKS_INFO_101:", -1);
545                 break;
546
547         case 102:
548                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
549                         wkssvc_dissect_WKS_INFO_102,
550                         NDR_POINTER_UNIQUE, "WKS_INFO_102:", -1);
551                 break;
552
553                 /* There is a 302 and 402 level, but I am too lazy today */
554
555         case 502:
556                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
557                                              wkssvc_dissect_WKS_INFO_502,
558                                              NDR_POINTER_UNIQUE, 
559                                              "WKS_INFO_502:", -1);
560                 break;
561
562         case 1010:
563                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
564                                              wkssvc_dissect_WKS_INFO_1010,
565                                              NDR_POINTER_UNIQUE, 
566                                              "WKS_INFO_1010:", -1);
567                 break;
568
569         case 1011:
570                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
571                                              wkssvc_dissect_WKS_INFO_1011,
572                                              NDR_POINTER_UNIQUE, 
573                                              "WKS_INFO_1011:", -1);
574                 break;
575
576         case 1012:
577                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
578                                              wkssvc_dissect_WKS_INFO_1012,
579                                              NDR_POINTER_UNIQUE, 
580                                              "WKS_INFO_1012:", -1);
581                 break;
582
583         case 1013:
584                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
585                                              wkssvc_dissect_WKS_INFO_1013,
586                                              NDR_POINTER_UNIQUE, 
587                                              "WKS_INFO_1013:", -1);
588                 break;
589
590         case 1018:
591                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
592                                              wkssvc_dissect_WKS_INFO_1018,
593                                              NDR_POINTER_UNIQUE, 
594                                              "WKS_INFO_1018:", -1);
595                 break;
596
597         case 1023:
598                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
599                                              wkssvc_dissect_WKS_INFO_1023,
600                                              NDR_POINTER_UNIQUE, 
601                                              "WKS_INFO_1023:", -1);
602                 break;
603
604         case 1027:
605                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
606                                              wkssvc_dissect_WKS_INFO_1027,
607                                              NDR_POINTER_UNIQUE, 
608                                              "WKS_INFO_1027:", -1);
609                 break;
610
611         case 1033:
612                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
613                                              wkssvc_dissect_WKS_INFO_1033,
614                                              NDR_POINTER_UNIQUE, 
615                                              "WKS_INFO_1033:", -1);
616                 break;
617
618                 /*      case 1018:
619                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
620                                              wkssvc_dissect_WKS_INFO_1018,
621                                              NDR_POINTER_UNIQUE, 
622                                              "WKS_INFO_1018:", -1);
623                                              break; */
624
625         }
626
627         return offset;
628
629 }
630
631 static int wkssvc_dissect_netwkstagetinfo_reply(tvbuff_t *tvb, int offset,
632                                                 packet_info *pinfo, 
633                                                 proto_tree *tree,
634                                                 guint8 *drep)
635 {
636         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
637                         wkssvc_dissect_WKS_GETINFO_UNION,
638                         NDR_POINTER_REF, "Server Info", -1);
639
640         offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
641                         hf_wkssvc_rc, NULL);
642
643         return offset;
644 }
645
646 /*
647  * IDL long NetWkstaSetInfo(
648  * IDL      [in] [string] [unique] wchar_t *ServerName,
649  * IDL      [in] long level,
650  * IDL      [in] [ref] WKS_INFO_UNION *wks,
651  * IDL      [out] long parm_err
652  * IDL );
653  */
654 static int wkssvc_dissect_netwkstasetinfo_rqst(tvbuff_t *tvb, int offset,
655                                                packet_info *pinfo, 
656                                                proto_tree *tree,
657                                                guint8 *drep)
658 {
659         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
660                                               NDR_POINTER_UNIQUE, "Server", 
661                                               hf_wkssvc_server, 0);
662
663         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
664                                     hf_wkssvc_info_level, 0);
665
666         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
667                         wkssvc_dissect_WKS_GETINFO_UNION,
668                         NDR_POINTER_REF, "Server Info", -1);
669
670         return offset;
671
672 }
673
674 static int wkssvc_dissect_netwkstasetinfo_reply(tvbuff_t *tvb, int offset,
675                                                 packet_info *pinfo, 
676                                                 proto_tree *tree,
677                                                 guint8 *drep)
678 {
679         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
680                                     hf_wkssvc_parm_err, 0);
681
682         offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
683         hf_wkssvc_rc, NULL);
684
685         return offset;
686
687 }
688
689 /*
690  * IDL typedef struct {
691  * IDL   [string] [unique] wchar_t *dev;
692  * IDL } USER_INFO_0;
693  */
694 static int
695 wkssvc_dissect_USER_INFO_0(tvbuff_t *tvb, int offset,
696                                      packet_info *pinfo, proto_tree *tree,
697                                      guint8 *drep)
698 {
699         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
700                         NDR_POINTER_UNIQUE, "User Name", 
701                         hf_wkssvc_user_name, 0);
702
703         return offset;
704 }
705
706 static int
707 wkssvc_dissect_USER_INFO_0_array(tvbuff_t *tvb, int offset,
708                                      packet_info *pinfo, proto_tree *tree,
709                                      guint8 *drep)
710 {
711         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
712                         wkssvc_dissect_USER_INFO_0);
713
714         return offset;
715 }
716
717 /*
718  * IDL typedef struct {
719  * IDL   long EntriesRead;
720  * IDL   [size_is(EntriesRead)] [unique] USER_INFO_0 *devs;
721  * IDL } USER_INFO_0_CONTAINER;
722  */
723 static int
724 wkssvc_dissect_USER_INFO_0_CONTAINER(tvbuff_t *tvb, int offset,
725                                      packet_info *pinfo, proto_tree *tree,
726                                      guint8 *drep)
727 {
728         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
729                 hf_wkssvc_num_entries, NULL);
730
731         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
732                 wkssvc_dissect_USER_INFO_0_array, NDR_POINTER_UNIQUE,
733                 "USER_INFO_0 array:", -1);
734
735         return offset;
736 }
737
738 /*
739  * IDL typedef struct {
740  * IDL   [string] [unique] wchar_t *user_name;
741  * IDL   [string] [unique] wchar_t *logon_domain;
742  * IDL   [string] [unique] wchar_t *other_domains;
743  * IDL   [string] [unique] wchar_t *logon_server;
744  * IDL } USER_INFO_1;
745  */
746 static int
747 wkssvc_dissect_USER_INFO_1(tvbuff_t *tvb, int offset,
748                                      packet_info *pinfo, proto_tree *tree,
749                                      guint8 *drep)
750 {
751         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
752                                               NDR_POINTER_UNIQUE, "User Name", 
753                                               hf_wkssvc_user_name, 0);
754
755         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
756                         NDR_POINTER_UNIQUE, "Logon Domain", 
757                                               hf_wkssvc_logon_domain, 0);
758
759         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
760                         NDR_POINTER_UNIQUE, "Other Domains", 
761                                               hf_wkssvc_other_domains, 0);
762
763         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
764                         NDR_POINTER_UNIQUE, "Logon Server", 
765                                               hf_wkssvc_logon_server, 0);
766
767
768         return offset;
769 }
770 static int
771 wkssvc_dissect_USER_INFO_1_array(tvbuff_t *tvb, int offset,
772                                      packet_info *pinfo, proto_tree *tree,
773                                      guint8 *drep)
774 {
775         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
776                         wkssvc_dissect_USER_INFO_1);
777
778         return offset;
779 }
780
781 /*
782  * IDL typedef struct {
783  * IDL   long EntriesRead;
784  * IDL   [size_is(EntriesRead)] [unique] USER_INFO_1 *devs;
785  * IDL } USER_INFO_1_CONTAINER;
786  */
787 static int
788 wkssvc_dissect_USER_INFO_1_CONTAINER(tvbuff_t *tvb, int offset,
789                                      packet_info *pinfo, proto_tree *tree,
790                                      guint8 *drep)
791 {
792         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
793                 hf_wkssvc_num_entries, NULL);
794
795         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
796                 wkssvc_dissect_USER_INFO_1_array, NDR_POINTER_UNIQUE,
797                 "USER_INFO_1 array:", -1);
798
799         return offset;
800 }
801
802 /*
803  * IDL typedef [switch_type(long)] union {
804  * IDL   [case(0)] [unique] USER_INFO_0_CONTAINER *dev0;
805  * IDL   [case(1)] [unique] USER_INFO_1_CONTAINER *dev1;
806  * IDL } CHARDEV_ENUM_UNION;
807  */
808 static int
809 wkssvc_dissect_USER_ENUM_UNION(tvbuff_t *tvb, int offset,
810                                      packet_info *pinfo, proto_tree *tree,
811                                      guint8 *drep)
812 {
813         guint32 level;
814         dcerpc_info *di;
815
816         di = pinfo->private_data;
817
818         ALIGN_TO_4_BYTES;
819
820         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_wkssvc_info_level, &level);
821
822         switch(level){
823         case 0:
824                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
825                         wkssvc_dissect_USER_INFO_0_CONTAINER,
826                         NDR_POINTER_UNIQUE, "USER_INFO_0_CONTAINER:", -1);
827                 if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
828                         col_append_str(pinfo->cinfo, COL_INFO, ", USER_INFO_0 level");
829                 break;
830         case 1:
831                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
832                         wkssvc_dissect_USER_INFO_1_CONTAINER,
833                         NDR_POINTER_UNIQUE, "USER_INFO_1_CONTAINER:", -1);
834                 if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
835                         col_append_str(pinfo->cinfo, COL_INFO, ", USER_INFO_1 level");
836                 break;
837         }
838
839         return offset;
840 }
841
842 /*
843  * IDL long NetWkstaEnumUsers(
844  * IDL      [in] [string] [unique] wchar_t *ServerName,
845  * IDL      [in] long level,
846  * IDL      [in] [out] [ref] WKS_USER_ENUM_STRUCT *users,
847  * IDL      [in] long prefmaxlen,
848  * IDL      [out] long *entriesread,
849  * IDL      [out] long *totalentries,
850  * IDL      [in] [out] [ref] long *resumehandle
851  * IDL );
852  */
853 static int
854 wkssvc_dissect_netwkstaenumusers_rqst(tvbuff_t *tvb, int offset, 
855                                       packet_info *pinfo, proto_tree *tree,
856                                       guint8 *drep)
857 {
858         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
859                                               NDR_POINTER_UNIQUE, "Server", 
860                                               hf_wkssvc_server, 0);
861
862         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
863                                     hf_wkssvc_info_level, 0);
864
865         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
866                         wkssvc_dissect_USER_ENUM_UNION,
867                         NDR_POINTER_REF, "User Info", -1);
868         /* Seems to be junk here ... */
869         /*      offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, 
870                                     hf_wkssvc_junk, 0);
871
872         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, 
873                                      wkssvc_dissect_ENUM_HANDLE,
874                                      NDR_POINTER_UNIQUE, "Junk Handle", -1);
875
876         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, 
877         hf_wkssvc_junk, 0); */
878
879         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
880                                     hf_wkssvc_pref_max, 0);
881
882         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, 
883                                      wkssvc_dissect_ENUM_HANDLE,
884                                      NDR_POINTER_UNIQUE, "Enum Handle", -1);
885
886         return offset;
887
888 }
889
890 static int wkssvc_dissect_netwkstaenumusers_reply(tvbuff_t *tvb, int offset,
891                                                   packet_info *pinfo, 
892                                                   proto_tree *tree,
893                                                   guint8 *drep)
894 {
895         /* There seems to be an info level there first */
896         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
897                                     hf_wkssvc_info_level, 0);
898
899         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
900                         wkssvc_dissect_USER_ENUM_UNION,
901                         NDR_POINTER_REF, "User Info", -1);
902
903         /* Entries read seems to be in the enum array ... */
904
905         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
906                                     hf_wkssvc_total_entries, 0);
907
908         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, 
909                                      wkssvc_dissect_ENUM_HANDLE,
910                                      NDR_POINTER_UNIQUE, "Enum Handle", -1);
911
912         offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
913         hf_wkssvc_rc, NULL);
914
915         return offset;
916 }
917
918 /*
919  * IDL typedef struct {
920  * IDL   long quality_of_service;
921  * IDL   long number_of_vcs;
922  * IDL   [string] [unique] wchar_t *transport_name;
923  * IDL   [string] [unique] wchar_t *transport_address; 
924  * IDL   BOOL wan_ish;
925  * IDL } TRANSPORT_INFO_0;
926  */
927 static int
928 wkssvc_dissect_TRANSPORT_INFO_0(tvbuff_t *tvb, int offset,
929                                      packet_info *pinfo, proto_tree *tree,
930                                      guint8 *drep)
931 {
932         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
933                                     hf_wkssvc_quality_of_service, 0);
934
935         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
936                                     hf_wkssvc_number_of_vcs, 0);
937
938         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
939                         NDR_POINTER_UNIQUE, "Transport Name", 
940                         hf_wkssvc_transport_name, 0);
941
942         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
943                         NDR_POINTER_UNIQUE, "Transport Address", 
944                         hf_wkssvc_transport_address, 0);
945
946         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
947                                     hf_wkssvc_wan_ish, 0);
948
949         return offset;
950 }
951
952 static int
953 wkssvc_dissect_TRANSPORT_INFO_0_array(tvbuff_t *tvb, int offset,
954                                      packet_info *pinfo, proto_tree *tree,
955                                      guint8 *drep)
956 {
957         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
958                         wkssvc_dissect_TRANSPORT_INFO_0);
959
960         return offset;
961 }
962
963 /*
964  * IDL typedef struct {
965  * IDL   long EntriesRead;
966  * IDL   [size_is(EntriesRead)] [unique] TRANSPORT_INFO_0 *devs;
967  * IDL } TRANSPORT_INFO_0_CONTAINER;
968  */
969 static int
970 wkssvc_dissect_TRANSPORT_INFO_0_CONTAINER(tvbuff_t *tvb, int offset,
971                                      packet_info *pinfo, proto_tree *tree,
972                                      guint8 *drep)
973 {
974         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
975                 hf_wkssvc_num_entries, NULL);
976
977         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
978                 wkssvc_dissect_TRANSPORT_INFO_0_array, NDR_POINTER_UNIQUE,
979                 "TRANSPORT_INFO_0 array:", -1);
980
981         return offset;
982 }
983
984 /*
985  * IDL typedef [switch_type(long)] union {
986  * IDL   [case(0)] [unique] TRANSPORT_INFO_0_CONTAINER *dev0;
987  * IDL } TRANSPORT_ENUM_UNION;
988  */
989 static int
990 wkssvc_dissect_TRANSPORT_ENUM_UNION(tvbuff_t *tvb, int offset,
991                                      packet_info *pinfo, proto_tree *tree,
992                                      guint8 *drep)
993 {
994         guint32 level;
995
996         ALIGN_TO_4_BYTES;
997
998         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_wkssvc_info_level, &level);
999
1000         switch(level){
1001         case 0:
1002                 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1003                         wkssvc_dissect_TRANSPORT_INFO_0_CONTAINER,
1004                         NDR_POINTER_UNIQUE, "TRANSPORT_INFO_0_CONTAINER:", -1);
1005                 break;
1006
1007         }
1008
1009         return offset;
1010 }
1011
1012 /*
1013  * IDL long NetWkstaTransportEnum(
1014  * IDL      [in] [string] [unique] wchar_t *ServerName,
1015  * IDL      [in] long level,
1016  * IDL      [in] [out] [ref] WKS_TRANSPORT_ENUM_STRUCT *users,
1017  * IDL      [in] long prefmaxlen,
1018  * IDL      [out] long *entriesread,
1019  * IDL      [out] long *totalentries,
1020  * IDL      [in] [out] [ref] long *resumehandle
1021  * IDL );
1022  */
1023 static int
1024 wkssvc_dissect_netwkstatransportenum_rqst(tvbuff_t *tvb, int offset, 
1025                                       packet_info *pinfo, proto_tree *tree,
1026                                       guint8 *drep)
1027 {
1028         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
1029                                               NDR_POINTER_UNIQUE, "Server", 
1030                                               hf_wkssvc_server, 0);
1031
1032         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1033                                     hf_wkssvc_info_level, 0);
1034
1035         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1036                         wkssvc_dissect_TRANSPORT_ENUM_UNION,
1037                         NDR_POINTER_REF, "Transport Info", -1);
1038
1039         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1040                                     hf_wkssvc_pref_max, 0);
1041
1042         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, 
1043                                      wkssvc_dissect_ENUM_HANDLE,
1044                                      NDR_POINTER_UNIQUE, "Enum Handle", -1);
1045
1046         return offset;
1047
1048 }
1049
1050 static int wkssvc_dissect_netwkstatransportenum_reply(tvbuff_t *tvb, 
1051                                                       int offset,
1052                                                       packet_info *pinfo, 
1053                                                       proto_tree *tree,
1054                                                       guint8 *drep)
1055 {
1056         /* There seems to be an info level there first */
1057         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1058                                     hf_wkssvc_info_level, 0);
1059
1060         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1061                         wkssvc_dissect_TRANSPORT_ENUM_UNION,
1062                         NDR_POINTER_REF, "Transport Info", -1);
1063
1064         /* Entries read seems to be in the enum array ... */
1065
1066         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1067                                     hf_wkssvc_total_entries, 0);
1068
1069         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, 
1070                                      wkssvc_dissect_ENUM_HANDLE,
1071                                      NDR_POINTER_UNIQUE, "Enum Handle", -1);
1072
1073         offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
1074         hf_wkssvc_rc, NULL);
1075
1076         return offset;
1077 }
1078
1079
1080 /*
1081  * IDL typedef struct {
1082  * IDL  char element_278[524];
1083  * IDL } TYPE_30;
1084  */
1085
1086 static int
1087 wkssvc_dissect_TYPE_30(tvbuff_t *tvb, int offset,
1088                                      packet_info *pinfo, proto_tree *tree,
1089                                      guint8 *drep _U_)
1090 {
1091         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1092
1093         if(di->conformant_run){
1094                 return offset;   /* cant modify offset while performing conformant run */
1095         }
1096
1097         proto_tree_add_item(tree, hf_wkssvc_encrypted_password, tvb, offset,
1098                 524, TRUE);
1099         offset += 524;
1100         
1101         return offset;          
1102 }
1103
1104
1105
1106 /*
1107  * IDL
1108  * IDL long NetrJoinDomain2(
1109  * IDL       [in] [unique] [string] wchar_t *ServerName,
1110  * IDL       [in] [string] wchar_t DomainName,
1111  * IDL       [in] [unique] [string] wchar_t *AccountOU,
1112  * IDL       [in] [unique] [string] wchar_t *Account,
1113  * IDL       [in] [unique] TYPE_30 *Encrypted_password,
1114  * IDL       [in] long JoinOptions
1115  * IDL );
1116  */
1117
1118 static const true_false_string join_flags_domain_join = {
1119         "Join the computer to a domain",
1120         "Join the computer to a workgroup"
1121 };
1122
1123 static const true_false_string join_flags_acct_create = {
1124         "Create the account on the domain",
1125         "Do not create the account"
1126 };
1127
1128 static const true_false_string unjoin_flags_acct_delete = {
1129         "Delete the account when a domain is left",
1130         "Do not delete the account when a domain is left"
1131 };
1132
1133 static const true_false_string join_flags_win9x_upgrade = {
1134         "The join operation is occurring as part of an upgrade of Windows 9x",
1135         "The join operation is not part of a Windows 9x upgrade"
1136 };
1137
1138 static const true_false_string join_flags_domain_join_if_joined = {
1139         "Allow a join to a new domain even if the computer is already joined to a domain",
1140         "Do not allow join to a new domain if the computer is already joined to a domain"
1141 };
1142
1143 static const true_false_string join_flags_unsecure = {
1144         "Performs an unsecured join",
1145         "Perform a secured join"
1146 };
1147
1148 static const true_false_string join_flags_machine_pwd_passed = {
1149         "Set the machine password after domain join to passed password",
1150         "Do not set the machine password after domain join to passed password"
1151 };
1152
1153 static const true_false_string join_flags_defer_spn_set = {
1154         "Defer setting of servicePrincipalName and dNSHostName attributes on the computer object until a rename operation",
1155         "Set servicePrincipalName and dNSHostName attributes on the computer object"
1156 };
1157
1158
1159 static int wkssvc_dissect_netr_join_domain2_rqst(tvbuff_t *tvb, int offset, 
1160                                       packet_info *pinfo, proto_tree *parent_tree,
1161                                       guint8 *drep)
1162 {
1163         guint32 join_flags = 0;
1164         proto_item *item;
1165         proto_tree *tree = NULL;
1166
1167         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
1168                                               NDR_POINTER_UNIQUE, "Server", 
1169                                               hf_wkssvc_server, 0);
1170
1171         offset = dissect_ndr_cvstring(tvb, offset, pinfo, parent_tree, drep,
1172                                       sizeof(guint16), hf_wkssvc_domain_to_join,
1173                                       TRUE, NULL);
1174
1175         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
1176                                               NDR_POINTER_UNIQUE, "Computer account OU", 
1177                                               hf_wkssvc_ou_for_computer_account, 0);
1178
1179         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
1180                                               NDR_POINTER_UNIQUE, 
1181                                               "Account used for join operation", 
1182                                               hf_wkssvc_account_used_for_join, 0);
1183
1184         offset = dissect_ndr_pointer(tvb, offset, pinfo, parent_tree, drep,
1185                 wkssvc_dissect_TYPE_30, NDR_POINTER_UNIQUE, 
1186                 "Encrypted password", -1);
1187
1188         join_flags = tvb_get_letohl(tvb, offset);
1189         item = proto_tree_add_item(parent_tree, hf_wkssvc_join_flags, tvb, offset, 4, TRUE);
1190         if (parent_tree) {
1191                 tree = proto_item_add_subtree(item, ett_dcerpc_wkssvc_join_flags);
1192         }
1193
1194         proto_tree_add_boolean(tree, hf_wkssvc_join_options_defer_spn_set, tvb, 
1195                                offset, 4, join_flags);
1196
1197         proto_tree_add_boolean(tree, hf_wkssvc_join_options_machine_pwd_passed, tvb, 
1198                                offset, 4, join_flags);
1199
1200         proto_tree_add_boolean(tree, hf_wkssvc_join_options_join_unsecure, tvb, 
1201                                offset, 4, join_flags);
1202
1203         proto_tree_add_boolean(tree, hf_wkssvc_join_options_domain_join_if_joined, 
1204                                tvb, offset, 4, join_flags);
1205
1206         proto_tree_add_boolean(tree, hf_wkssvc_join_options_win9x_upgrade, tvb, 
1207                                offset, 4, join_flags);
1208
1209         proto_tree_add_boolean(tree, hf_wkssvc_join_options_acct_create, tvb, 
1210                                offset, 4, join_flags);
1211
1212         proto_tree_add_boolean(tree, hf_wkssvc_join_options_join_type, tvb, 
1213                                offset, 4, join_flags);
1214         offset += 4;
1215
1216         return offset;
1217 }
1218
1219
1220 static int wkssvc_dissect_netr_join_domain2_reply(tvbuff_t *tvb, int offset, 
1221                                       packet_info *pinfo, proto_tree *tree,
1222                                       guint8 *drep)
1223 {
1224         offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
1225                         hf_wkssvc_rc, NULL);
1226
1227         return offset;
1228 }
1229
1230
1231 /*
1232  * IDL long NetrUnjoinDomain2(
1233  * IDL       [in] [unique] [string] wchar_t *ServerName,
1234  * IDL       [in] [unique] [string] wchar_t *Account
1235  * IDL       [in] [unique] TYPE_30 *Encrypted_password,
1236  * IDL       [in] long UnjoinOptions
1237  * IDL );
1238  */
1239
1240 static int wkssvc_dissect_netr_unjoin_domain2_rqst(tvbuff_t *tvb, int offset, 
1241                                       packet_info *pinfo, proto_tree *parent_tree,
1242                                       guint8 *drep)
1243 {
1244         guint32 unjoin_flags = 0;
1245         proto_item *item;
1246         proto_tree *tree = NULL;
1247
1248
1249         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
1250                                               NDR_POINTER_UNIQUE, "Server", 
1251                                               hf_wkssvc_server, 0);
1252
1253         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
1254                                               NDR_POINTER_UNIQUE, 
1255                                               "Account used for unjoin operation", 
1256                                               hf_wkssvc_account_used_for_unjoin, 0);
1257
1258
1259         offset = dissect_ndr_pointer(tvb, offset, pinfo, parent_tree, drep,
1260                 wkssvc_dissect_TYPE_30, NDR_POINTER_UNIQUE, 
1261                 "Encrypted password", -1);
1262
1263         unjoin_flags = tvb_get_letohl(tvb, offset);
1264         item = proto_tree_add_item(parent_tree, hf_wkssvc_unjoin_flags, tvb, offset, 4, TRUE);
1265         if (parent_tree) {
1266                 tree = proto_item_add_subtree(item, ett_dcerpc_wkssvc_join_flags);
1267         }
1268
1269         proto_tree_add_boolean(tree, hf_wkssvc_unjoin_options_acct_delete, tvb, 
1270                                offset, 4, unjoin_flags);
1271         offset += 4;
1272
1273         return offset;
1274
1275 }
1276
1277
1278 static int wkssvc_dissect_netr_unjoin_domain2_reply(tvbuff_t *tvb, int offset, 
1279                                       packet_info *pinfo, proto_tree *tree,
1280                                       guint8 *drep)
1281 {
1282         offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
1283                         hf_wkssvc_rc, NULL);
1284
1285         return offset;
1286 }
1287
1288
1289
1290 /*
1291  * IDL long NetrRenameMachineInDomain2(
1292  * IDL       [in] [unique] [string] wchar_t *ServerName,
1293  * IDL       [in] [unique] [string] wchar_t *NewMachineName,
1294  * IDL       [in] [unique] [string] wchar_t *Account,
1295  * IDL       [in] [unique] TYPE_30 *EncryptedPassword,
1296  * IDL       [in] long RenameOptions
1297  * IDL );
1298  */
1299
1300 static int wkssvc_dissect_netr_rename_machine_in_domain2_rqst(tvbuff_t *tvb, int offset, 
1301                                       packet_info *pinfo, proto_tree *parent_tree,
1302                                       guint8 *drep)
1303 {
1304         guint32 rename_flags = 0;
1305         proto_item *item;
1306         proto_tree *tree = NULL;
1307
1308
1309         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
1310                                               NDR_POINTER_UNIQUE, "Server", 
1311                                               hf_wkssvc_server, 0);
1312
1313         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
1314                                               NDR_POINTER_UNIQUE, 
1315                                               "New Machine Name", 
1316                                               hf_wkssvc_server, 0);
1317
1318         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
1319                                               NDR_POINTER_UNIQUE, 
1320                                               "Account used for rename operation", 
1321                                               hf_wkssvc_account_used_for_unjoin, 0);
1322
1323         offset = dissect_ndr_pointer(tvb, offset, pinfo, parent_tree, drep,
1324                 wkssvc_dissect_TYPE_30, NDR_POINTER_UNIQUE, 
1325                 "Encrypted password", -1);
1326
1327         rename_flags = tvb_get_letohl(tvb, offset);
1328         item = proto_tree_add_item(parent_tree, hf_wkssvc_rename_flags, tvb, offset, 4, TRUE);
1329         if (parent_tree) {
1330                 tree = proto_item_add_subtree(item, ett_dcerpc_wkssvc_join_flags);
1331         }
1332
1333         proto_tree_add_boolean(tree, hf_wkssvc_join_options_acct_create, tvb, 
1334                                offset, 4, rename_flags);
1335         offset += 4;
1336
1337         return offset;
1338
1339 }
1340
1341 static int wkssvc_dissect_netr_rename_machine_in_domain2_reply(tvbuff_t *tvb, int offset, 
1342                                       packet_info *pinfo, proto_tree *tree,
1343                                       guint8 *drep)
1344 {
1345         offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
1346                         hf_wkssvc_rc, NULL);
1347
1348         return offset;
1349 }
1350
1351
1352 /*
1353  * IDL long NetrAddAlternateComputerName(
1354  * IDL       [in] [unique] [string] wchar_t *ServerName,
1355  * IDL       [in] [unique] [string] wchar_t *NewAlternateMachineName,
1356  * IDL       [in] [unique] [string] wchar_t *Account,
1357  * IDL       [in] [unique] TYPE_30 *EncryptedPassword,
1358  * IDL       [in] long Reserved
1359  * IDL );
1360  */
1361
1362 static int wkssvc_dissect_netr_add_alternate_computername_rqst(tvbuff_t *tvb, int offset, 
1363                                       packet_info *pinfo, proto_tree *tree,
1364                                       guint8 *drep)
1365 {
1366         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
1367                                               NDR_POINTER_UNIQUE, "Server", 
1368                                               hf_wkssvc_server, 0);
1369
1370         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
1371                                               NDR_POINTER_UNIQUE, "New alternate computer name", 
1372                                               hf_wkssvc_alternate_name, 0);
1373
1374         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
1375                                               NDR_POINTER_UNIQUE, "Account name", 
1376                                               hf_wkssvc_account_used_for_alternate_name, 0);
1377
1378         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1379                 wkssvc_dissect_TYPE_30, NDR_POINTER_UNIQUE, 
1380                 "Encrypted password", -1);
1381
1382         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1383                         hf_wkssvc_reserved, NULL);
1384
1385         return offset;
1386 }
1387
1388 static int wkssvc_dissect_netr_add_alternate_computername_reply(tvbuff_t *tvb, int offset, 
1389                                       packet_info *pinfo, proto_tree *tree,
1390                                       guint8 *drep)
1391 {
1392         offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
1393                         hf_wkssvc_rc, NULL);
1394
1395         return offset;
1396 }
1397
1398 /*
1399  * IDL long NetrRemoveAlternateComputerName(
1400  * IDL       [in] [unique] [string] wchar_t *ServerName,
1401  * IDL       [in] [unique] [string] wchar_t *AlternateMachineNameToRemove,
1402  * IDL       [in] [unique] [string] wchar_t *Account,
1403  * IDL       [in] [unique] TYPE_30 *EncryptedPassword,
1404  * IDL       [in] long Reserved
1405  * IDL );
1406  */
1407
1408 static int wkssvc_dissect_netr_remove_alternate_computername_rqst(tvbuff_t *tvb, int offset, 
1409                                       packet_info *pinfo, proto_tree *tree,
1410                                       guint8 *drep)
1411 {
1412         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
1413                                               NDR_POINTER_UNIQUE, "Server", 
1414                                               hf_wkssvc_server, 0);
1415
1416         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
1417                                               NDR_POINTER_UNIQUE, "Alternate computer name to remove", 
1418                                               hf_wkssvc_alternate_name, 0);
1419
1420         offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
1421                                               NDR_POINTER_UNIQUE, "Account name", 
1422                                               hf_wkssvc_account_used_for_alternate_name, 0);
1423
1424         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
1425                 wkssvc_dissect_TYPE_30, NDR_POINTER_UNIQUE, 
1426                 "Encrypted password", -1);
1427
1428         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1429                         hf_wkssvc_reserved, NULL);
1430
1431         return offset;
1432 }
1433
1434
1435
1436 static int wkssvc_dissect_netr_remove_alternate_computername_reply(tvbuff_t *tvb, int offset, 
1437                                       packet_info *pinfo, proto_tree *tree,
1438                                       guint8 *drep)
1439 {
1440         offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
1441                         hf_wkssvc_rc, NULL);
1442
1443         return offset;
1444 }
1445
1446 static dcerpc_sub_dissector dcerpc_wkssvc_dissectors[] = {
1447         { WKS_NETRWKSTAGETINFO, "NetrWkstaGetInfo", 
1448           wkssvc_dissect_netwkstagetinfo_rqst, 
1449           wkssvc_dissect_netwkstagetinfo_reply},
1450         { WKS_NETRWKSTASETINFO, "NetrWkstaSetInfo",
1451           wkssvc_dissect_netwkstasetinfo_rqst,
1452           wkssvc_dissect_netwkstasetinfo_reply},
1453         { WKS_NETRWKSTAUSERENUM, "NetrWkstaUserEnum",
1454           wkssvc_dissect_netwkstaenumusers_rqst,
1455           wkssvc_dissect_netwkstaenumusers_reply},
1456         { WKS_NETRWKSTAUSERGETINFO, "NetrWkstaUserGetInfo", NULL, NULL },
1457         { WKS_NETRWKSTAUSERSETINFO, "NetrWkstaUserSetInfo", NULL, NULL },
1458         { WKS_NETRWKSTATRANSPORTENUM, "NetrWkstaTransportEnum",
1459           wkssvc_dissect_netwkstatransportenum_rqst, 
1460           wkssvc_dissect_netwkstatransportenum_reply},
1461         { WKS_NETRWKSTATRANSPORTADD, "NetrWkstaTransportAdd", NULL, NULL },
1462         { WKS_NETRWKSTATRANSPORTDEL, "NetrWkstaTransportDel", NULL, NULL },
1463         { WKS_NETRUSEADD, "NetrUseAdd", NULL, NULL },
1464         { WKS_NETRUSEGETINFO, "NetrUseGetInfo", NULL, NULL },
1465         { WKS_NETRUSEDEL, "NetrUseDel", NULL, NULL },
1466         { WKS_NETRUSEENUM, "NetrUseEnum", NULL, NULL },
1467         { WKS_NETRMESSAGEBUFFERSEND, "NetrMessageBufferSend", NULL, NULL },
1468         { WKS_NETRWORKSTATIONSTATISTICSGET, "NetrWorkstationStatisticsGet", 
1469           NULL, NULL },
1470         { WKS_NETRLOGONDOMAINNAMEADD, "NetrLogonDomainNameAdd", NULL, NULL },
1471         { WKS_NETRLOGONDOMAINNAMEDEL, "NetrLogonDomainNameDel", NULL, NULL },
1472         { WKS_NETRJOINDOMAIN, "NetrJoinDomain", NULL, NULL },
1473         { WKS_NETRUNJOINDOMAIN, "NetrUnjoinDomain", NULL, NULL },
1474         { WKS_NETRRENAMEMACHINEINDOMAIN, "NetrRenameMachineInDomain", 
1475           NULL, NULL },
1476         { WKS_NETRVALIDATENAME, "NetrValidateName", NULL, NULL },
1477         { WKS_NETRGETJOININFORMATION, "NetrGetJoinInformation", NULL, NULL },
1478         { WKS_NETRGETJOINABLEOUS, "NetrGetJoinableOUs", NULL, NULL },
1479         { WKS_NETRJOINDOMAIN2, "NetrJoinDomain2", 
1480           wkssvc_dissect_netr_join_domain2_rqst, 
1481           wkssvc_dissect_netr_join_domain2_reply},
1482         { WKS_NETRUNJOINDOMAIN2, "NetrUnjoinDomain2", 
1483           wkssvc_dissect_netr_unjoin_domain2_rqst,
1484           wkssvc_dissect_netr_unjoin_domain2_reply},
1485         { WKS_NETRRENAMEMACHINEINDOMAIN2, "NetrRenameMachineInDomain2", 
1486           wkssvc_dissect_netr_rename_machine_in_domain2_rqst,
1487           wkssvc_dissect_netr_rename_machine_in_domain2_reply},
1488         { WKS_NETRVALIDATENAME2, "NetrValidateName2", NULL, NULL },
1489         { WKS_NETRGETJOINABLEOUS2, "NetrGetJoinableOUs2", NULL, NULL },
1490         { WKS_NETRADDALTERNATECOMPUTERNAME, "NetrAddAlternateComputerName", 
1491            wkssvc_dissect_netr_add_alternate_computername_rqst,
1492            wkssvc_dissect_netr_add_alternate_computername_reply},
1493         { WKS_NETRREMOVEALTERNATECOMPUTERNAME,
1494           "NetrRemoveAlternateComputerName", 
1495            wkssvc_dissect_netr_remove_alternate_computername_rqst,
1496            wkssvc_dissect_netr_remove_alternate_computername_reply},
1497         { WKS_NETRSETPRIMARYCOMPUTERNAME, "NetrSetPrimaryComputerName", 
1498           NULL, NULL },
1499         { WKS_NETRENUMERATECOMPUTERNAMES, "NetrEnumerateComputerNames", 
1500           NULL, NULL },
1501         {0, NULL, NULL,  NULL }
1502 };
1503
1504 void
1505 proto_register_dcerpc_wkssvc(void)
1506 {
1507         static hf_register_info hf[] = { 
1508           { &hf_wkssvc_opnum,
1509             { "Operation", "wkssvc.opnum", FT_UINT16, BASE_DEC,
1510               NULL, 0x0, "", HFILL }},
1511           { &hf_wkssvc_server,
1512             { "Server", "wkssvc.server", FT_STRING, BASE_NONE,
1513               NULL, 0x0, "Server Name", HFILL}},
1514           { &hf_wkssvc_net_group,
1515             { "Net Group", "wkssvc.netgrp", FT_STRING, BASE_NONE,
1516               NULL, 0x0, "Net Group", HFILL}},
1517           { &hf_wkssvc_info_level,
1518             { "Info Level", "wkssvc.info_level", FT_UINT32,
1519               BASE_DEC, NULL, 0x0, "Info Level", HFILL}},
1520           { &hf_wkssvc_platform_id,
1521             { "Platform ID", "wkssvc.info.platform_id", FT_UINT32,
1522               BASE_DEC, VALS(platform_id_vals), 0x0, "Platform ID", HFILL}},
1523           { &hf_wkssvc_ver_major,
1524             { "Major Version", "wkssvc.version.major", FT_UINT32,
1525               BASE_DEC, NULL, 0x0, "Major Version", HFILL}},
1526           { &hf_wkssvc_ver_minor,
1527             { "Minor Version", "wkssvc.version.minor", FT_UINT32,
1528               BASE_DEC, NULL, 0x0, "Minor Version", HFILL}},
1529           { &hf_wkssvc_lan_root,
1530             { "Lan Root", "wkssvc.lan.root", FT_STRING, BASE_NONE,
1531               NULL, 0x0, "Lan Root", HFILL}},
1532           { &hf_wkssvc_logged_on_users,
1533             { "Logged On Users", "wkssvc.logged.on.users", FT_UINT32,
1534               BASE_DEC, NULL, 0x0, "Logged On Users", HFILL}},
1535           { &hf_wkssvc_pref_max, 
1536             { "Preferred Max Len", "wkssvc.pref.max.len", FT_INT32,
1537               BASE_DEC, NULL, 0x0, "Preferred Max Len", HFILL}},
1538           { &hf_wkssvc_junk, 
1539             { "Junk", "wkssvc.junk", FT_UINT32,
1540               BASE_DEC, NULL, 0x0, "Junk", HFILL}},
1541           { &hf_wkssvc_enum_handle,
1542             { "Enumeration handle", "wkssvc.enum_hnd", FT_BYTES,
1543               BASE_HEX, NULL, 0x0, "Enumeration Handle", HFILL}},
1544           { &hf_wkssvc_user_name,
1545             { "User Name", "wkssvc.user.name", FT_STRING, BASE_NONE,
1546               NULL, 0x0, "User Name", HFILL}},
1547           { &hf_wkssvc_logon_domain,
1548             { "Logon Domain", "wkssvc.logon.domain", FT_STRING, BASE_NONE,
1549               NULL, 0x0, "Logon Domain", HFILL}},
1550           { &hf_wkssvc_other_domains,
1551             { "Other Domains", "wkssvc.other.domains", FT_STRING, BASE_NONE,
1552               NULL, 0x0, "Other Domains", HFILL}},
1553           { &hf_wkssvc_logon_server,
1554             { "Logon Server", "wkssvc.logon.server", FT_STRING, BASE_NONE,
1555               NULL, 0x0, "Logon Server", HFILL}},
1556           { &hf_wkssvc_rc,
1557             { "Return code", "wkssvc.rc", FT_UINT32,
1558               BASE_HEX, VALS(DOS_errors), 0x0, "Return Code", HFILL}},
1559           { &hf_wkssvc_num_entries, 
1560             { "Num Entries", "wkssvc.num.entries", FT_INT32,
1561               BASE_DEC, NULL, 0x0, "Num Entries", HFILL}},
1562           { &hf_wkssvc_entries_read, 
1563             { "Entries Read", "wkssvc.entries.read", FT_INT32,
1564               BASE_DEC, NULL, 0x0, "Entries Read", HFILL}},
1565           { &hf_wkssvc_total_entries, 
1566             { "Total Entries", "wkssvc.total.entries", FT_INT32,
1567               BASE_DEC, NULL, 0x0, "Total Entries", HFILL}},
1568           { &hf_wkssvc_char_wait, 
1569             { "Char Wait", "wkssvc.char.wait", FT_INT32,
1570               BASE_DEC, NULL, 0x0, "Char Wait", HFILL}},
1571           { &hf_wkssvc_collection_time, 
1572             { "Collection Time", "wkssvc.collection.time", FT_INT32,
1573               BASE_DEC, NULL, 0x0, "Collection Time", HFILL}},
1574           { &hf_wkssvc_maximum_collection_count, 
1575             { "Maximum Collection Count", "wkssvc.maximum.collection.count", 
1576               FT_INT32,
1577               BASE_DEC, NULL, 0x0, "Maximum Collection Count", HFILL}},
1578           { &hf_wkssvc_keep_conn, 
1579             { "Keep Connection", "wkssvc.keep.connection", FT_INT32,
1580               BASE_DEC, NULL, 0x0, "Keep Connection", HFILL}},
1581           { &hf_wkssvc_max_cmds, 
1582             { "Maximum Commands", "wkssvc.maximum.commands", FT_INT32,
1583               BASE_DEC, NULL, 0x0, "Maximum Commands", HFILL}},
1584           { &hf_wkssvc_sess_timeout, 
1585             { "Session Timeout", "wkssvc.session.timeout", FT_INT32,
1586               BASE_DEC, NULL, 0x0, "Session Timeout", HFILL}},
1587           { &hf_wkssvc_siz_char_buf, 
1588             { "Character Buffer Size", "wkssvc.size.char.buff", FT_INT32,
1589               BASE_DEC, NULL, 0x0, "Character Buffer Size", HFILL}},
1590           { &hf_wkssvc_max_threads, 
1591             { "Maximum Threads", "wkssvc.maximum.threads", FT_INT32,
1592               BASE_DEC, NULL, 0x0, "Maximum Threads", HFILL}},
1593           { &hf_wkssvc_lock_quota, 
1594             { "Lock Quota", "wkssvc.lock.quota", FT_INT32,
1595               BASE_DEC, NULL, 0x0, "Lock Quota", HFILL}},
1596           { &hf_wkssvc_lock_increment, 
1597             { "Lock Increment", "wkssvc.lock.increment", FT_INT32,
1598               BASE_DEC, NULL, 0x0, "Lock Increment", HFILL}},
1599           { &hf_wkssvc_lock_maximum, 
1600             { "Lock Maximum", "wkssvc.lock.maximum", FT_INT32,
1601               BASE_DEC, NULL, 0x0, "Lock Maximum", HFILL}},
1602           { &hf_wkssvc_pipe_increment, 
1603             { "Pipe Increment", "wkssvc.pipe.increment", FT_INT32,
1604               BASE_DEC, NULL, 0x0, "Pipe Increment", HFILL}},
1605           { &hf_wkssvc_pipe_maximum, 
1606             { "Pipe Maximum", "wkssvc.pipe.maximum", FT_INT32,
1607               BASE_DEC, NULL, 0x0, "Pipe Maximum", HFILL}},
1608           { &hf_wkssvc_cache_file_timeout, 
1609             { "Cache File Timeout", "wkssvc.cache.file.timeout", FT_INT32,
1610               BASE_DEC, NULL, 0x0, "Cache File Timeout", HFILL}},
1611           { &hf_wkssvc_dormant_file_limit, 
1612             { "Dormant File Limit", "wkssvc.dormant.file.limit", FT_INT32,
1613               BASE_DEC, NULL, 0x0, "Dormant File Limit", HFILL}},
1614           { &hf_wkssvc_read_ahead_throughput, 
1615             { "Read Ahead Throughput", "wkssvc.read.ahead.throughput", FT_INT32,
1616               BASE_DEC, NULL, 0x0, "Read Ahead Throughput", HFILL}},
1617           { &hf_wkssvc_num_mailslot_buffers, 
1618             { "Num Mailslot Buffers", "wkssvc.num.mailslot.buffers", FT_INT32,
1619               BASE_DEC, NULL, 0x0, "Num Mailslot Buffers", HFILL}},
1620           { &hf_wkssvc_num_srv_announce_buffers, 
1621             { "Num Srv Announce Buffers", "wkssvc.num.srv.announce.buffers", FT_INT32,
1622               BASE_DEC, NULL, 0x0, "Num Srv Announce Buffers", HFILL}},
1623           { &hf_wkssvc_max_illegal_datagram_events, 
1624             { "Max Illegal Datagram Events", "wkssvc.max.illegal.datagram.events", FT_INT32,
1625               BASE_DEC, NULL, 0x0, "Max Illegal Datagram Events", HFILL}},
1626           { &hf_wkssvc_illegal_datagram_event_reset_frequency, 
1627             { "Illegal Datagram Event Reset Frequency", "wkssvc.illegal.datagram.reset.frequency", FT_INT32,
1628               BASE_DEC, NULL, 0x0, "Illegal Datagram Event Reset Frequency", HFILL}},
1629           { &hf_wkssvc_log_election_packets, 
1630             { "Log Election Packets", "wkssvc.log.election.packets", FT_INT32,
1631               BASE_DEC, NULL, 0x0, "Log Election Packets", HFILL}},
1632           { &hf_wkssvc_use_opportunistic_locking, 
1633             { "Use Opportunistic Locking", "wkssvc.use.oplocks", FT_INT32,
1634               BASE_DEC, NULL, 0x0, "Use OpLocks", HFILL}},
1635           { &hf_wkssvc_use_unlock_behind, 
1636             { "Use Lock Behind", "wkssvc.use.lock.behind", FT_INT32,
1637               BASE_DEC, NULL, 0x0, "Use Lock Behind", HFILL}},
1638           { &hf_wkssvc_use_close_behind, 
1639             { "Use Close Behind", "wkssvc.use.close.behind", FT_INT32,
1640               BASE_DEC, NULL, 0x0, "Use Close Behind", HFILL}},
1641           { &hf_wkssvc_buf_named_pipes, 
1642             { "Buffer Named Pipes", "wkssvc.buffer.named.pipes", FT_INT32,
1643               BASE_DEC, NULL, 0x0, "Buffer Named Pipes", HFILL}},
1644           { &hf_wkssvc_use_lock_read_unlock, 
1645             { "Use Lock Read Unlock", "wkssvc.use.lock.read.unlock", FT_INT32,
1646               BASE_DEC, NULL, 0x0, "Use Lock Read Unlock", HFILL}},
1647           { &hf_wkssvc_utilize_nt_caching, 
1648             { "Utilize NT Caching", "wkssvc.utilize.nt.caching", FT_INT32,
1649               BASE_DEC, NULL, 0x0, "Utilize NT Caching", HFILL}},
1650           { &hf_wkssvc_use_raw_read, 
1651             { "Use Raw Read", "wkssvc.use.raw.read", FT_INT32,
1652               BASE_DEC, NULL, 0x0, "Use Raw Read", HFILL}},
1653           { &hf_wkssvc_use_raw_write, 
1654             { "Use Raw Write", "wkssvc.use.raw.write", FT_INT32,
1655               BASE_DEC, NULL, 0x0, "Use Raw Write", HFILL}},
1656           { &hf_wkssvc_use_write_raw_data, 
1657             { "Use Write Raw Data", "wkssvc.use.write.raw.data", FT_INT32,
1658               BASE_DEC, NULL, 0x0, "Use Write Raw Data", HFILL}},
1659           { &hf_wkssvc_use_encryption, 
1660             { "Use Encryption", "wkssvc.use.encryption", FT_INT32,
1661               BASE_DEC, NULL, 0x0, "Use Encryption", HFILL}},
1662           { &hf_wkssvc_buf_files_deny_write, 
1663             { "Buffer Files Deny Write", "wkssvc.buf.files.deny.write", FT_INT32,
1664               BASE_DEC, NULL, 0x0, "Buffer Files Deny Write", HFILL}},
1665           { &hf_wkssvc_buf_read_only_files, 
1666             { "Buffer Files Read Only", "wkssvc.buf.files.read.only", FT_INT32,
1667               BASE_DEC, NULL, 0x0, "Buffer Files Read Only", HFILL}},
1668           { &hf_wkssvc_force_core_create_mode, 
1669             { "Force Core Create Mode", "wkssvc.force.core.create.mode", FT_INT32,
1670               BASE_DEC, NULL, 0x0, "Force Core Create Mode", HFILL}},
1671           { &hf_wkssvc_use_512_byte_max_transfer, 
1672             { "Use 512 Byte Max Transfer", "wkssvc.use.512.byte.max.transfer", FT_INT32,
1673               BASE_DEC, NULL, 0x0, "Use 512 Byte Maximum Transfer", HFILL}},
1674           { &hf_wkssvc_parm_err, 
1675             { "Parameter Error Offset", "wkssvc.parm.err", FT_INT32,
1676               BASE_DEC, NULL, 0x0, "Parameter Error Offset", HFILL}},
1677           { &hf_wkssvc_errlog_sz, 
1678             { "Error Log Size", "wkssvc.errlog.sz", FT_INT32,
1679               BASE_DEC, NULL, 0x0, "Error Log Size", HFILL}},
1680           { &hf_wkssvc_print_buf_time, 
1681             { "Print Buf Time", "wkssvc.print.buf.time", FT_INT32,
1682               BASE_DEC, NULL, 0x0, "Print Buff Time", HFILL}},
1683           { &hf_wkssvc_wrk_heuristics, 
1684             { "Wrk Heuristics", "wkssvc.wrk.heuristics", FT_INT32,
1685               BASE_DEC, NULL, 0x0, "Wrk Heuristics", HFILL}},
1686           { &hf_wkssvc_quality_of_service, 
1687             { "Quality Of Service", "wkssvc.qos", FT_INT32,
1688               BASE_DEC, NULL, 0x0, "Quality Of Service", HFILL}},
1689           { &hf_wkssvc_number_of_vcs, 
1690             { "Number Of VCs", "wkssvc.number.of.vcs", FT_INT32,
1691               BASE_DEC, NULL, 0x0, "Number of VSs", HFILL}},
1692           { &hf_wkssvc_transport_name,
1693             { "Transport Name", "wkssvc.transport.name", FT_STRING, BASE_NONE,
1694               NULL, 0x0, "Transport Name", HFILL}},
1695           { &hf_wkssvc_transport_address,
1696             { "Transport Address", "wkssvc.transport.address", FT_STRING, 
1697               BASE_NONE,
1698               NULL, 0x0, "Transport Address", HFILL}},
1699           { &hf_wkssvc_wan_ish, 
1700             { "WAN ish", "wkssvc.wan.ish", FT_INT32,
1701               BASE_DEC, NULL, 0x0, "WAN ish", HFILL}},
1702           { &hf_wkssvc_domain_to_join,
1703             { "Domain or Workgroup to join", "wkssvc.join.domain", FT_STRING, BASE_NONE,
1704               NULL, 0x0, "Domain or Workgroup to join", HFILL}},
1705           { &hf_wkssvc_ou_for_computer_account,
1706             { "Organizational Unit (OU) for computer account", 
1707               "wkssvc.join.computer_account_ou", FT_STRING, BASE_NONE,
1708               NULL, 0x0, "Organizational Unit (OU) for computer account", HFILL}},
1709           { &hf_wkssvc_account_used_for_join,
1710             { "Account used for join operations", "wkssvc.join.account_used", FT_STRING, BASE_NONE,
1711               NULL, 0x0, "Account used for join operations", HFILL}},
1712           { &hf_wkssvc_join_flags,
1713             { "Domain join flags", "wkssvc.join.flags",
1714             FT_UINT32, BASE_HEX, NULL, 0x0,
1715             "Domain join flags", HFILL }},
1716           { &hf_wkssvc_unjoin_flags,
1717             { "Domain unjoin flags", "wkssvc.unjoin.flags",
1718             FT_UINT32, BASE_HEX, NULL, 0x0,
1719             "Domain unjoin flags", HFILL }},
1720           { &hf_wkssvc_rename_flags,
1721             { "Machine rename flags", "wkssvc.rename.flags",
1722             FT_UINT32, BASE_HEX, NULL, 0x0,
1723             "Machine rename flags", HFILL }},
1724           { &hf_wkssvc_join_options_join_type,
1725             { "Join type", "wkssvc.join.options.join_type", 
1726               FT_BOOLEAN, 32, TFS(&join_flags_domain_join), 0x00000001,
1727               "Join type", HFILL}},
1728           { &hf_wkssvc_join_options_acct_create,
1729             { "Computer account creation", "wkssvc.join.options.account_create", 
1730               FT_BOOLEAN, 32, TFS(&join_flags_acct_create), 0x00000002,
1731               "Computer account creation", HFILL}},
1732           { &hf_wkssvc_unjoin_options_acct_delete,
1733             { "Computer account deletion", "wkssvc.unjoin.options.account_delete", 
1734               FT_BOOLEAN, 32, TFS(&unjoin_flags_acct_delete), 0x00000004,
1735               "Computer account deletion", HFILL}},
1736           { &hf_wkssvc_join_options_win9x_upgrade,
1737             { "Win9x upgrade", "wkssvc.join.options.win9x_upgrade", 
1738               FT_BOOLEAN, 32, TFS(&join_flags_win9x_upgrade), 0x00000010,
1739               "Win9x upgrade", HFILL}},
1740           { &hf_wkssvc_join_options_domain_join_if_joined,
1741             { "New domain join if already joined", 
1742               "wkssvc.join.options.domain_join_if_joined", 
1743               FT_BOOLEAN, 32, TFS(&join_flags_domain_join_if_joined),
1744               0x00000020,
1745               "New domain join if already joined", HFILL}},
1746           { &hf_wkssvc_join_options_join_unsecure,
1747             { "Unsecure join", "wkssvc.join.options.insecure_join", 
1748               FT_BOOLEAN, 32, TFS(&join_flags_unsecure), 
1749               0x00000040, "Unsecure join", HFILL}},
1750           { &hf_wkssvc_join_options_machine_pwd_passed,
1751             { "Machine pwd passed", "wkssvc.join.options.machine_pwd_passed",
1752               FT_BOOLEAN, 32, TFS(&join_flags_machine_pwd_passed), 
1753               0x00000080, "Machine pwd passed", HFILL}},
1754           { &hf_wkssvc_join_options_defer_spn_set,
1755             { "Defer SPN set", "wkssvc.join.options.defer_spn_set",
1756               FT_BOOLEAN, 32, TFS(&join_flags_defer_spn_set), 
1757               0x00000100, "Defer SPN set", HFILL}},
1758           { &hf_wkssvc_account_used_for_unjoin,
1759             { "Account used for unjoin operations", 
1760                "wkssvc.unjoin.account_used", FT_STRING, BASE_NONE,
1761                NULL, 0x0, "Account used for unjoin operations", HFILL}},
1762           { &hf_wkssvc_account_used_for_alternate_name,
1763             { "Account used for alternate name operations", 
1764               "wkssvc.alternate_operations_account", FT_STRING, BASE_NONE,
1765               NULL, 0x0, "Account used for alternate name operations", HFILL}},
1766           { &hf_wkssvc_alternate_name,
1767             { "Alternate computer name", "wkssvc.alternate_computer_name", FT_STRING, BASE_NONE,
1768               NULL, 0x0, "Alternate computer name", HFILL}},
1769           { &hf_wkssvc_encrypted_password, 
1770             { "Encrypted password", "wkssvc.crypt_password", FT_BYTES, BASE_HEX,
1771                 NULL, 0, "Encrypted Password", HFILL }},
1772           { &hf_wkssvc_reserved,
1773             { "Reserved field", "wkssvc.reserved", FT_INT32,
1774               BASE_HEX, NULL, 0x0, "Reserved field", HFILL}},
1775         };
1776         static gint *ett[] = {
1777                 &ett_dcerpc_wkssvc,
1778                 &ett_dcerpc_wkssvc_join_flags
1779         };
1780
1781         proto_dcerpc_wkssvc = proto_register_protocol(
1782                 "Microsoft Workstation Service", "WKSSVC", "wkssvc");
1783
1784         proto_register_field_array(proto_dcerpc_wkssvc, hf, array_length(hf));
1785         proto_register_subtree_array(ett, array_length(ett));
1786 }
1787
1788 void
1789 proto_reg_handoff_dcerpc_wkssvc(void)
1790 {
1791         /* Register protocol as dcerpc */
1792
1793         dcerpc_init_uuid(proto_dcerpc_wkssvc, ett_dcerpc_wkssvc,
1794                          &uuid_dcerpc_wkssvc, ver_dcerpc_wkssvc,
1795                          dcerpc_wkssvc_dissectors, hf_wkssvc_opnum);
1796 }