22f4b67dc49f65fc3c2eb618e9ef04101207567e
[obnox/wireshark/wip.git] / packet-dcerpc-spoolss.c
1 /* packet-dcerpc-spoolss.c
2  * Routines for SMB \PIPE\spoolss packet disassembly
3  * Copyright 2001-2003, Tim Potter <tpot@samba.org>
4  *
5  * $Id: packet-dcerpc-spoolss.c,v 1.101 2003/06/17 05:29:45 tpot Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 /* TODO list:
27
28  - audit of item lengths
29
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <glib.h>
37 #include <string.h>
38
39 #include <epan/packet.h>
40 #include "packet-dcerpc.h"
41 #include "packet-dcerpc-nt.h"
42 #include "packet-dcerpc-spoolss.h"
43 #include "packet-dcerpc-reg.h"
44 #include "smb.h"
45 #include "packet-smb-common.h"
46
47 /* GetPrinterDriver2 */
48
49 static int hf_clientmajorversion = -1;
50 static int hf_clientminorversion = -1;
51 static int hf_servermajorversion = -1;
52 static int hf_serverminorversion = -1;
53 static int hf_driverpath = -1;
54 static int hf_datafile = -1;
55 static int hf_configfile = -1;
56 static int hf_helpfile = -1;
57 static int hf_monitorname = -1;
58 static int hf_defaultdatatype = -1;
59 static int hf_driverinfo_cversion = -1;
60 static int hf_dependentfiles = -1;
61
62 /* GetPrinter */
63
64 /* Times */
65
66 static int hf_start_time = -1;
67 static int hf_end_time = -1;
68 static int hf_elapsed_time = -1;
69
70 /****************************************************************************/
71
72 /*
73  * New hf index values - I'm in the process of doing a bit of a cleanup -tpot
74  */
75
76 static int hf_opnum = -1;
77 static int hf_hnd = -1;
78 static int hf_rc = -1;
79 static int hf_offered = -1;
80 static int hf_needed = -1;
81 static int hf_returned = -1;
82 static int hf_buffer_size = -1;
83 static int hf_buffer_data = -1;
84 static int hf_offset = -1;
85 static int hf_level = -1;
86 static int hf_access_required = -1;
87
88 static int hf_printername = -1;
89 static int hf_machinename = -1;
90 static int hf_notifyname = -1;
91 static int hf_printerdesc = -1;
92 static int hf_printercomment = -1;
93 static int hf_servername = -1;
94 static int hf_sharename = -1;
95 static int hf_portname = -1;
96 static int hf_printerlocation = -1;
97 static int hf_drivername = -1;
98 static int hf_architecture = -1;
99 static int hf_username = -1;
100 static int hf_documentname = -1;
101 static int hf_outputfile = -1;
102 static int hf_datatype = -1;
103 static int hf_textstatus = -1;
104 static int hf_sepfile = -1;
105 static int hf_printprocessor = -1;
106 static int hf_parameters = -1;
107
108 /* Printer information */
109
110 static int hf_printer_cjobs = -1;
111 static int hf_printer_total_jobs = -1;
112 static int hf_printer_total_bytes = -1;
113 static int hf_printer_global_counter = -1;
114 static int hf_printer_total_pages = -1;
115 static int hf_printer_major_version = -1;
116 static int hf_printer_build_version = -1;
117 static int hf_printer_unk7 = -1;
118 static int hf_printer_unk8 = -1;
119 static int hf_printer_unk9 = -1;
120 static int hf_printer_session_ctr = -1;
121 static int hf_printer_unk11 = -1;
122 static int hf_printer_printer_errors = -1;
123 static int hf_printer_unk13 = -1;
124 static int hf_printer_unk14 = -1;
125 static int hf_printer_unk15 = -1;
126 static int hf_printer_unk16 = -1;
127 static int hf_printer_changeid = -1;
128 static int hf_printer_unk18 = -1;
129 static int hf_printer_unk20 = -1;
130 static int hf_printer_c_setprinter = -1;
131 static int hf_printer_unk22 = -1;
132 static int hf_printer_unk23 = -1;
133 static int hf_printer_unk24 = -1;
134 static int hf_printer_unk25 = -1;
135 static int hf_printer_unk26 = -1;
136 static int hf_printer_unk27 = -1;
137 static int hf_printer_unk28 = -1;
138 static int hf_printer_unk29 = -1;
139 static int hf_printer_flags = -1;
140 static int hf_printer_priority = -1;
141 static int hf_printer_default_priority = -1;
142 static int hf_printer_jobs = -1;
143 static int hf_printer_averageppm = -1;
144 static int hf_printer_guid = -1;
145 static int hf_printer_action = -1;
146
147 /* Printer data */
148
149 static int hf_printerdata = -1;
150 static int hf_printerdata_key = -1;
151 static int hf_printerdata_value = -1;
152 static int hf_printerdata_type = -1;
153 static int hf_printerdata_size = -1; /* Length of printer data */
154 static int hf_printerdata_data = -1;
155 static int hf_printerdata_data_sz = -1;
156 static int hf_printerdata_data_dword = -1;
157
158 /* Devicemode */
159
160 static int hf_devmodectr_size = -1;
161
162 static int hf_devmode = -1;
163 static int hf_devmode_size = -1;
164 static int hf_devmode_spec_version = -1;
165 static int hf_devmode_driver_version = -1;
166 static int hf_devmode_size2 = -1;
167 static int hf_devmode_driver_extra_len = -1;
168 static int hf_devmode_fields = -1;
169 static int hf_devmode_orientation = -1;
170 static int hf_devmode_paper_size = -1;
171 static int hf_devmode_paper_width = -1;
172 static int hf_devmode_paper_length = -1;
173 static int hf_devmode_scale = -1;
174 static int hf_devmode_copies = -1;
175 static int hf_devmode_default_source = -1;
176 static int hf_devmode_print_quality = -1;
177 static int hf_devmode_color = -1;
178 static int hf_devmode_duplex = -1;
179 static int hf_devmode_y_resolution = -1;
180 static int hf_devmode_tt_option = -1;
181 static int hf_devmode_collate = -1;
182 static int hf_devmode_log_pixels = -1;
183 static int hf_devmode_bits_per_pel = -1;
184 static int hf_devmode_pels_width = -1;
185 static int hf_devmode_pels_height = -1;
186 static int hf_devmode_display_flags = -1;
187 static int hf_devmode_display_freq = -1;
188 static int hf_devmode_icm_method = -1;
189 static int hf_devmode_icm_intent = -1;
190 static int hf_devmode_media_type = -1;
191 static int hf_devmode_dither_type = -1;
192 static int hf_devmode_reserved1 = -1;
193 static int hf_devmode_reserved2 = -1;
194 static int hf_devmode_panning_width = -1;
195 static int hf_devmode_panning_height = -1;
196 static int hf_devmode_driver_extra = -1;
197
198 static int hf_devmode_fields_orientation = -1;
199 static int hf_devmode_fields_papersize = -1;
200 static int hf_devmode_fields_paperlength = -1;
201 static int hf_devmode_fields_paperwidth = -1;
202 static int hf_devmode_fields_scale = -1;
203 static int hf_devmode_fields_position = -1;
204 static int hf_devmode_fields_nup = -1;
205 static int hf_devmode_fields_copies = -1;
206 static int hf_devmode_fields_defaultsource = -1;
207 static int hf_devmode_fields_printquality = -1;
208 static int hf_devmode_fields_color = -1;
209 static int hf_devmode_fields_duplex = -1;
210 static int hf_devmode_fields_yresolution = -1;
211 static int hf_devmode_fields_ttoption = -1;
212 static int hf_devmode_fields_collate = -1;
213 static int hf_devmode_fields_formname = -1;
214 static int hf_devmode_fields_logpixels = -1;
215 static int hf_devmode_fields_bitsperpel = -1;
216 static int hf_devmode_fields_pelswidth = -1;
217 static int hf_devmode_fields_pelsheight = -1;
218 static int hf_devmode_fields_displayflags = -1;
219 static int hf_devmode_fields_displayfrequency = -1;
220 static int hf_devmode_fields_icmmethod = -1;
221 static int hf_devmode_fields_icmintent = -1;
222 static int hf_devmode_fields_mediatype = -1;
223 static int hf_devmode_fields_dithertype = -1;
224 static int hf_devmode_fields_panningwidth = -1;
225 static int hf_devmode_fields_panningheight = -1;
226
227 /* Print job */
228
229 static int hf_job_id = -1;
230 static int hf_job_priority = -1;
231 static int hf_job_position = -1;
232 static int hf_job_totalpages = -1;
233 static int hf_job_totalbytes = -1;
234 static int hf_job_pagesprinted = -1;
235 static int hf_job_bytesprinted = -1;
236 static int hf_job_size = -1;
237
238 static int hf_job_status = -1;
239 static int hf_job_status_paused = -1;
240 static int hf_job_status_error = -1;
241 static int hf_job_status_deleting = -1;
242 static int hf_job_status_spooling = -1;
243 static int hf_job_status_printing = -1;
244 static int hf_job_status_offline = -1;
245 static int hf_job_status_paperout = -1;
246 static int hf_job_status_printed = -1;
247 static int hf_job_status_deleted = -1;
248 static int hf_job_status_blocked = -1;
249 static int hf_job_status_user_intervention = -1;
250
251 /* Forms */
252
253 static int hf_form = -1;
254 static int hf_form_level = -1;
255 static int hf_form_name = -1;
256 static int hf_form_flags = -1;
257 static int hf_form_unknown = -1;
258 static int hf_form_width = -1;
259 static int hf_form_height = -1;
260 static int hf_form_left_margin = -1;
261 static int hf_form_top_margin = -1;
262 static int hf_form_horiz_len = -1;
263 static int hf_form_vert_len = -1;
264
265 static int hf_enumforms_num = -1;
266
267 /* Print notify */
268
269 static int hf_notify_options_version = -1;
270 static int hf_notify_options_flags = -1;
271 static int hf_notify_options_flags_refresh = -1;
272 static int hf_notify_options_count = -1;
273 static int hf_notify_option_type = -1;
274 static int hf_notify_option_reserved1 = -1;
275 static int hf_notify_option_reserved2 = -1;
276 static int hf_notify_option_reserved3 = -1;
277 static int hf_notify_option_count = -1;
278 static int hf_notify_option_data_count = -1;
279 static int hf_notify_info_count = -1;
280 static int hf_notify_info_version = -1;
281 static int hf_notify_info_flags = -1;
282 static int hf_notify_info_data_type = -1;
283 static int hf_notify_info_data_count = -1;
284 static int hf_notify_info_data_id = -1;
285 static int hf_notify_info_data_value1 = -1;
286 static int hf_notify_info_data_value2 = -1;
287 static int hf_notify_info_data_bufsize = -1;
288 static int hf_notify_info_data_buffer = -1;
289 static int hf_notify_info_data_buffer_len = -1;
290 static int hf_notify_info_data_buffer_data = -1;
291
292 static int hf_notify_field = -1;
293
294 static int hf_printerlocal = -1;
295
296 static int hf_rrpcn_changelow = -1;
297 static int hf_rrpcn_changehigh = -1;
298 static int hf_rrpcn_unk0 = -1;
299 static int hf_rrpcn_unk1 = -1;
300
301 static int hf_replyopenprinter_unk0 = -1;
302 static int hf_replyopenprinter_unk1 = -1;
303
304 /****************************************************************************/
305
306 /*
307  * Dissect SPOOLSS specific access rights
308  */
309
310 static int hf_server_access_admin = -1;
311 static int hf_server_access_enum = -1;
312 static int hf_printer_access_admin = -1;
313 static int hf_printer_access_use = -1;
314 static int hf_job_access_admin = -1;
315
316 static void
317 spoolss_printer_specific_rights(tvbuff_t *tvb, gint offset, proto_tree *tree,
318                                 guint32 access)
319 {
320         proto_tree_add_boolean(
321                 tree, hf_printer_access_use, tvb, offset, 4, access);
322
323         proto_tree_add_boolean(
324                 tree, hf_printer_access_admin, tvb, offset, 4, access);
325 }
326
327 struct access_mask_info spoolss_printer_access_mask_info = {
328         "SPOOLSS printer",
329         spoolss_printer_specific_rights,
330         NULL,                   /* Generic mapping table */
331         NULL                    /* Standard mapping table */
332 };
333
334 static void
335 spoolss_printserver_specific_rights(tvbuff_t *tvb, gint offset, 
336                                     proto_tree *tree, guint32 access)
337 {
338         proto_tree_add_boolean(
339                 tree, hf_server_access_enum, tvb, offset, 4, access);
340
341         proto_tree_add_boolean(
342                 tree, hf_server_access_admin, tvb, offset, 4, access);
343 }
344
345 struct access_mask_info spoolss_printserver_access_mask_info = {
346         "SPOOLSS print server",
347         spoolss_printserver_specific_rights,
348         NULL,                   /* Generic mapping table */
349         NULL                    /* Standard mapping table */
350 };
351
352 static void
353 spoolss_job_specific_rights(tvbuff_t *tvb, gint offset, 
354                             proto_tree *tree, guint32 access)
355 {
356         proto_tree_add_boolean(
357                 tree, hf_job_access_admin, tvb, offset, 4, access);
358 }
359
360 struct access_mask_info spoolss_job_access_mask_info = {
361         "SPOOLSS job",
362         spoolss_job_specific_rights,
363         NULL,                   /* Generic mapping table */
364         NULL                    /* Standard mapping table */
365 };
366
367 /*
368  * Routines to dissect a spoolss BUFFER
369  */
370
371 typedef struct {
372         tvbuff_t *tvb;
373         proto_item *tree;       /* Proto tree buffer located in */
374         proto_item *item;
375 } BUFFER;
376
377 static gint ett_BUFFER = -1;
378
379 static int
380 dissect_spoolss_buffer_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
381                             proto_tree *tree, char *drep)
382 {
383         dcerpc_info *di = pinfo->private_data;
384         BUFFER *b = (BUFFER *)di->private_data;
385         proto_item *item;
386         guint32 size;
387         const guint8 *data;
388
389         if (di->conformant_run)
390                 return offset;
391
392         /* Dissect size and data */
393
394         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
395                                     hf_buffer_size, &size);
396
397         offset = dissect_ndr_uint8s(tvb, offset, pinfo, NULL, drep,
398                                     hf_buffer_data, size, &data);
399
400         item = proto_tree_add_item(
401                 tree, hf_buffer_data, tvb, offset - size,
402                 size, drep[0] & 0x10);
403                 
404         /* Return buffer info */
405
406         if (b) {
407
408                 /* I'm not sure about this.  Putting the buffer into
409                    it's own tvb makes sense and the dissection code is
410                    much clearer, but the data is a proper subset of
411                    the actual tvb.  Not adding the new data source
412                    makes the hex display confusing as it switches
413                    between the 'DCERPC over SMB' tvb and the buffer
414                    tvb with no visual cues as to what is going on. */
415
416                 b->tvb = tvb_new_real_data(data, size, size);
417                 tvb_set_child_real_data_tvbuff(tvb, b->tvb);
418                 add_new_data_source(pinfo, b->tvb, "SPOOLSS buffer");
419
420                 b->item = item;
421                 b->tree = proto_item_add_subtree(item, ett_BUFFER);
422         }
423
424         return offset;
425 }
426
427 /* Dissect a spoolss buffer and return buffer data */
428
429 static int
430 dissect_spoolss_buffer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
431                        proto_tree *tree, char *drep, BUFFER *b)
432 {
433         dcerpc_info *di = pinfo->private_data;
434
435         if (b)
436                 memset(b, 0, sizeof(BUFFER));
437
438         di->private_data = b;
439
440         offset = dissect_ndr_pointer(
441                 tvb, offset, pinfo, tree, drep,
442                 dissect_spoolss_buffer_data, NDR_POINTER_UNIQUE, 
443                 "Buffer", -1);
444
445         return offset;
446 }
447
448 /*
449  * SYSTEM_TIME
450  */
451
452 static gint ett_SYSTEM_TIME;
453
454 static int hf_time_year = -1;
455 static int hf_time_month = -1;
456 static int hf_time_dow = -1;
457 static int hf_time_day = -1;
458 static int hf_time_hour = -1;
459 static int hf_time_minute = -1;
460 static int hf_time_second = -1;
461 static int hf_time_msec = -1;
462
463 static int
464 dissect_SYSTEM_TIME(tvbuff_t *tvb, int offset, packet_info *pinfo,
465                     proto_tree *tree, char *drep, char *name, 
466                     gboolean add_subtree, char **data)
467 {
468         proto_item *item = NULL;
469         proto_tree *subtree = tree;
470         guint16 year, month, day, hour, minute, second, millisecond;
471         char *str;
472
473         if (add_subtree) {
474                 item = proto_tree_add_text(tree, tvb, offset, 16, name);
475                 subtree = proto_item_add_subtree(item, ett_SYSTEM_TIME);
476         }
477
478         offset = dissect_ndr_uint16(
479                 tvb, offset, pinfo, subtree, drep, hf_time_year, &year);
480
481         offset = dissect_ndr_uint16(
482                 tvb, offset, pinfo, subtree, drep, hf_time_month, &month);
483
484         offset = dissect_ndr_uint16(
485                 tvb, offset, pinfo, subtree, drep, hf_time_dow, NULL);
486
487         offset = dissect_ndr_uint16(
488                 tvb, offset, pinfo, subtree, drep, hf_time_day, &day);
489
490         offset = dissect_ndr_uint16(
491                 tvb, offset, pinfo, subtree, drep, hf_time_hour, &hour);
492
493         offset = dissect_ndr_uint16(
494                 tvb, offset, pinfo, subtree, drep, hf_time_minute, &minute);
495
496         offset = dissect_ndr_uint16(
497                 tvb, offset, pinfo, subtree, drep, hf_time_second, &second);
498
499         offset = dissect_ndr_uint16(
500                 tvb, offset, pinfo, subtree, drep, hf_time_msec, &millisecond);
501
502         str = g_strdup_printf("%d/%02d/%02d %02d:%02d:%02d.%03d", 
503                               year, month, day, hour, minute, second,
504                               millisecond);
505
506         if (add_subtree) 
507                 proto_item_append_text(item, ": %s", str);
508
509         if (data)
510                 *data = str;
511         else
512                 g_free(str);
513
514         return offset;
515 }
516
517 static int
518 dissect_SYSTEM_TIME_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo,
519                         proto_tree *tree, char *drep)
520 {
521         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
522         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
523         char *str;
524
525         offset =  dissect_SYSTEM_TIME(
526                 tvb, offset, pinfo, tree, drep, NULL, FALSE, &str);
527
528         dcv->private_data = str;
529
530         return offset;
531 }
532
533 /*
534  * SpoolssClosePrinter
535  */
536
537 static int SpoolssClosePrinter_q(tvbuff_t *tvb, int offset,
538                                  packet_info *pinfo, proto_tree *tree,
539                                  char *drep _U_)
540 {
541         e_ctx_hnd policy_hnd;
542         char *pol_name;
543
544         /* Parse packet */
545
546         offset = dissect_nt_policy_hnd(
547                 tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
548                 FALSE, TRUE);
549
550         dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
551                              pinfo->fd->num);
552
553         if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
554                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
555                                 pol_name);
556
557         return offset;
558 }
559
560 static int SpoolssClosePrinter_r(tvbuff_t *tvb, int offset,
561                                  packet_info *pinfo, proto_tree *tree,
562                                  char *drep _U_)
563 {
564         /* Parse packet */
565
566         offset = dissect_nt_policy_hnd(
567                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
568                 FALSE, FALSE);
569
570
571         offset = dissect_doserror(
572                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
573
574         return offset;
575 }
576
577 /* Dissect some printer data.  The get/set/enum printerdata routines all
578    store value/data in a uint8 array.  We could use the ndr routines for
579    this but that would result in one item for each byte in the printer
580    data. */
581
582 static gint ett_printerdata_data = -1;
583 static gint ett_printerdata_value = -1;
584
585 static int dissect_printerdata_data(tvbuff_t *tvb, int offset,
586                                     packet_info *pinfo, proto_tree *tree,
587                                     char *drep _U_, guint32 type)
588 {
589         proto_item *item;
590         proto_tree *subtree;
591         guint32 size;
592
593         item = proto_tree_add_text(tree, tvb, offset, 0, "Data");
594
595         subtree = proto_item_add_subtree(item, ett_printerdata_data);
596
597         offset = dissect_ndr_uint32(
598                 tvb, offset, pinfo, subtree, drep, hf_printerdata_size, &size);
599
600         if (size) {
601
602                 offset = dissect_ndr_uint8s(
603                         tvb, offset, pinfo, subtree, drep,
604                         hf_printerdata_data, size, NULL);
605                 
606                 switch(type) {
607                 case DCERPC_REG_SZ: {
608                         char *data = tvb_fake_unicode(tvb, offset - size, size/2, TRUE);
609                         
610                         proto_item_append_text(item, ": %s", data);
611
612                         if (check_col(pinfo->cinfo, COL_INFO))
613                                 col_append_fstr(
614                                         pinfo->cinfo, COL_INFO, " = %s", data);
615
616                         proto_tree_add_string_hidden(
617                                 tree, hf_printerdata_data_sz, tvb,
618                                 offset - size, size, data);
619
620                         g_free(data);
621
622                         break;
623                 }
624                 case DCERPC_REG_DWORD: {
625                         guint32 data = tvb_get_letohl(tvb, offset - size);
626
627                         proto_item_append_text(item, ": 0x%08x", data);
628
629                         if (check_col(pinfo->cinfo, COL_INFO))
630                                 col_append_fstr(
631                                         pinfo->cinfo, COL_INFO, " = 0x%08x", 
632                                         data);
633
634                         proto_tree_add_uint_hidden(
635                                 tree, hf_printerdata_data_dword, tvb,
636                                 offset - size, 4, data);
637
638                         break;
639                 }
640                 case DCERPC_REG_BINARY:
641                         if (check_col(pinfo->cinfo, COL_INFO))
642                                 col_append_fstr(
643                                         pinfo->cinfo, COL_INFO, 
644                                         " = <binary data>");
645                         break;
646
647                 default:
648                         break;
649                 }
650         }
651         
652         proto_item_set_len(item, size + 4);
653
654         return offset;
655 }
656
657 /*
658  * SpoolssGetPrinterData
659  */
660
661 static int SpoolssGetPrinterData_q(tvbuff_t *tvb, int offset,
662                                    packet_info *pinfo, proto_tree *tree,
663                                    char *drep _U_)
664 {
665         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
666         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
667         char *value_name;
668
669         proto_tree_add_uint_hidden(
670                 tree, hf_printerdata, tvb, offset, 0, 1);
671
672         /* Parse packet */
673
674         offset = dissect_nt_policy_hnd(
675                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
676                 FALSE, FALSE);
677
678         value_name = dcv->private_data;
679
680         offset = dissect_ndr_cvstring(
681                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
682                 hf_printerdata_value, TRUE, value_name ? NULL : &value_name);
683
684         dcv->private_data = value_name;
685
686         if (check_col(pinfo->cinfo, COL_INFO))
687                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
688
689         offset = dissect_ndr_uint32(
690                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
691
692         return offset;
693 }
694
695 static int SpoolssGetPrinterData_r(tvbuff_t *tvb, int offset,
696                                    packet_info *pinfo, proto_tree *tree,
697                                    char *drep _U_)
698 {
699         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
700         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
701         guint32 type;
702
703         proto_tree_add_uint_hidden(
704                 tree, hf_printerdata, tvb, offset, 0, 1);
705
706         /* Parse packet */
707
708         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
709                                     hf_printerdata_type, &type);
710
711         if (check_col(pinfo->cinfo, COL_INFO)) {
712                 char *data = dcv->private_data ? dcv->private_data : "????";
713
714                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", data);
715         }
716
717         offset = dissect_printerdata_data(
718                 tvb, offset, pinfo, tree, drep, type);
719
720         offset = dissect_ndr_uint32(
721                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
722
723         offset = dissect_doserror(
724                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
725
726         return offset;
727 }
728
729 /*
730  * SpoolssGetPrinterDataEx
731  */
732
733 static int SpoolssGetPrinterDataEx_q(tvbuff_t *tvb, int offset,
734                                      packet_info *pinfo, proto_tree *tree,
735                                      char *drep _U_)
736 {
737         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
738         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
739         char *key_name, *value_name;
740
741         proto_tree_add_uint_hidden(
742                 tree, hf_printerdata, tvb, offset, 0, 1);
743
744         /* Parse packet */
745
746         offset = dissect_nt_policy_hnd(
747                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
748                 FALSE, FALSE);
749
750         offset = dissect_ndr_cvstring(
751                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
752                 hf_printerdata_key, TRUE, &key_name);
753
754         /*
755          * Register a cleanup function in case on of our tvbuff accesses
756          * throws an exception. We need to clean up key_name.
757          */
758         CLEANUP_PUSH(g_free, key_name);
759
760         offset = dissect_ndr_cvstring(
761                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
762                 hf_printerdata_value, TRUE, &value_name);
763
764         if (check_col(pinfo->cinfo, COL_INFO))
765                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s/%s",
766                                 key_name, value_name);
767
768         if (!dcv->private_data)
769                 dcv->private_data = g_strdup_printf(
770                         "%s/%s", key_name, value_name);
771
772         /*
773          * We're done with key_name, so we can call the cleanup handler to
774          * free it, and then pop the cleanup handler.
775          */
776         CLEANUP_CALL_AND_POP;
777
778         /*
779          * We're also done with value_name.
780          */
781         g_free(value_name);
782
783         offset = dissect_ndr_uint32(
784                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
785
786         return offset;
787 }
788
789 static int SpoolssGetPrinterDataEx_r(tvbuff_t *tvb, int offset,
790                                      packet_info *pinfo, proto_tree *tree,
791                                      char *drep _U_)
792 {
793         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
794         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
795         guint32 size, type;
796
797         proto_tree_add_uint_hidden(
798                 tree, hf_printerdata, tvb, offset, 0, 1);
799
800         /* Parse packet */
801
802         offset = dissect_ndr_uint32(
803                 tvb, offset, pinfo, tree, drep, hf_printerdata_type, &type);
804
805         offset = dissect_ndr_uint32(
806                 tvb, offset, pinfo, tree, drep, hf_returned, &size);
807
808         if (check_col(pinfo->cinfo, COL_INFO)) {
809                 char *data = dcv->private_data ? dcv->private_data : "????";
810
811                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", data);
812         }
813
814         if (size)
815                 dissect_printerdata_data(tvb, offset, pinfo, tree, drep, type);
816
817         offset += size;
818
819         offset = dissect_ndr_uint32(
820                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
821
822         offset = dissect_doserror(
823                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
824
825         return offset;
826 }
827
828 /*
829  * SpoolssSetPrinterData
830  */
831
832 static int SpoolssSetPrinterData_q(tvbuff_t *tvb, int offset,
833                                    packet_info *pinfo, proto_tree *tree,
834                                    char *drep _U_)
835 {
836         char *value_name = NULL;
837         guint32 type;
838
839         proto_tree_add_uint_hidden(
840                 tree, hf_printerdata, tvb, offset, 0, 1);
841
842         /* Parse packet */
843
844         offset = dissect_nt_policy_hnd(
845                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
846                 FALSE, FALSE);
847
848         offset = dissect_ndr_cvstring(
849                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
850                 hf_printerdata_value, TRUE, &value_name);
851
852         if (check_col(pinfo->cinfo, COL_INFO))
853                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
854
855         g_free(value_name);
856
857         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
858                                     hf_printerdata_type, &type);
859
860         offset = dissect_printerdata_data(
861                 tvb, offset, pinfo, tree, drep, type);
862
863         offset = dissect_ndr_uint32(
864                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
865
866         return offset;
867 }
868
869 static int SpoolssSetPrinterData_r(tvbuff_t *tvb, int offset,
870                                    packet_info *pinfo, proto_tree *tree,
871                                    char *drep _U_)
872 {
873         proto_tree_add_uint_hidden(
874                 tree, hf_printerdata, tvb, offset, 0, 1);
875
876         /* Parse packet */
877
878         offset = dissect_doserror(
879                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
880
881         return offset;
882 }
883
884 /*
885  * SpoolssSetPrinterDataEx
886  */
887
888 static int hf_setprinterdataex_max_len = -1;
889 static int hf_setprinterdataex_real_len = -1;
890 static int hf_setprinterdataex_data = -1;
891
892 static int SpoolssSetPrinterDataEx_q(tvbuff_t *tvb, int offset,
893                                      packet_info *pinfo, proto_tree *tree,
894                                      char *drep _U_)
895 {
896         char *key_name, *value_name;
897         guint32 max_len;
898
899         proto_tree_add_uint_hidden(
900                 tree, hf_printerdata, tvb, offset, 0, 1);
901
902         /* Parse packet */
903
904         offset = dissect_nt_policy_hnd(
905                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
906                 FALSE, FALSE);
907
908         offset = dissect_ndr_cvstring(
909                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
910                 hf_printerdata_key, TRUE, &key_name);
911
912         CLEANUP_PUSH(g_free, key_name);
913
914         offset = dissect_ndr_cvstring(
915                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
916                 hf_printerdata_value, TRUE, &value_name);
917
918         if (check_col(pinfo->cinfo, COL_INFO))
919                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s/%s",
920                                 key_name, value_name);
921
922         CLEANUP_CALL_AND_POP;
923         g_free(value_name);
924
925         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
926                                     hf_printerdata_type, NULL);
927
928         offset = dissect_ndr_uint32(
929                 tvb, offset, pinfo, tree, drep,
930                 hf_setprinterdataex_max_len, &max_len);
931
932         offset = dissect_ndr_uint8s(
933                 tvb, offset, pinfo, tree, drep,
934                 hf_setprinterdataex_data, max_len, NULL);
935
936         offset = dissect_ndr_uint32(
937                 tvb, offset, pinfo, tree, drep,
938                 hf_setprinterdataex_real_len, NULL);
939
940         return offset;
941 }
942
943 static int SpoolssSetPrinterDataEx_r(tvbuff_t *tvb, int offset,
944                                      packet_info *pinfo, proto_tree *tree,
945                                      char *drep _U_)
946 {
947         proto_tree_add_uint_hidden(
948                 tree, hf_printerdata, tvb, offset, 0, 1);
949
950         /* Parse packet */
951
952         offset = dissect_doserror(
953                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
954
955         return offset;
956 }
957
958 /* Yet another way to represent a unicode string - sheesh. This function
959    dissects a NULL terminate unicode string at the current offset and
960    returns the (char *) equivalent.  This really should return UTF8 or
961    something but we use tvb_fake_unicode() instead. */
962
963 /* XXX - "name" should be an hf_ value for an FT_STRING. */
964 static int
965 dissect_spoolss_uint16uni(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
966                           proto_tree *tree, char *drep _U_, char **data,
967                           char *name)
968 {
969         gint len, remaining;
970         char *text;
971
972         if (offset % 2)
973                 offset += 2 - (offset % 2);
974
975         /* Get remaining data in buffer as a string */
976
977         remaining = tvb_length_remaining(tvb, offset) / 2;
978         text = tvb_fake_unicode(tvb, offset, remaining, TRUE);
979         len = strlen(text);
980
981         proto_tree_add_text(tree, tvb, offset, len * 2, "%s: %s",
982                             name ? name : "String", text);
983
984         if (data)
985                 *data = text;
986         else
987                 g_free(text);
988
989         return offset + (len + 1) * 2;
990 }
991
992 /*
993  * DEVMODE
994  */
995
996 /* Devicemode orientation values */
997
998 static const value_string devmode_orientation_vals[] =
999 {
1000         { DEVMODE_ORIENTATION_PORTRAIT, "Portrait" },
1001         { DEVMODE_ORIENTATION_LANDSCAPE, "Landscape" },
1002         { 0, NULL }
1003 };
1004
1005 /* Paper size values.  International paper sizes is a fascinating
1006    topic.  No seriously!  (-: */
1007
1008 static const value_string devmode_papersize_vals[] =
1009 {
1010         { DEVMODE_PAPERSIZE_LETTER, "Letter" },
1011         { DEVMODE_PAPERSIZE_LETTERSMALL, "Letter (small)" },
1012         { DEVMODE_PAPERSIZE_TABLOID, "Tabloid" },
1013         { DEVMODE_PAPERSIZE_LEDGER, "Ledger" },
1014         { DEVMODE_PAPERSIZE_LEGAL, "Legal" },
1015         { DEVMODE_PAPERSIZE_STATEMENT, "Statement" },
1016         { DEVMODE_PAPERSIZE_EXECUTIVE, "Executive" },
1017         { DEVMODE_PAPERSIZE_A3, "A3" },
1018         { DEVMODE_PAPERSIZE_A4, "A4" },
1019         { DEVMODE_PAPERSIZE_A4SMALL, "A4 (small)" },
1020         { DEVMODE_PAPERSIZE_A5, "A5" },
1021         { DEVMODE_PAPERSIZE_B4, "B4" },
1022         { DEVMODE_PAPERSIZE_B5, "B5" },
1023         { DEVMODE_PAPERSIZE_FOLIO, "Folio" },
1024         { DEVMODE_PAPERSIZE_QUARTO, "Quarto" },
1025         { DEVMODE_PAPERSIZE_10X14, "10x14" },
1026         { DEVMODE_PAPERSIZE_11X17, "11x17" },
1027         { DEVMODE_PAPERSIZE_NOTE, "Note" },
1028         { DEVMODE_PAPERSIZE_ENV9, "Envelope #9" },
1029         { DEVMODE_PAPERSIZE_ENV10, "Envelope #10" },
1030         { DEVMODE_PAPERSIZE_ENV11, "Envelope #11" },
1031         { DEVMODE_PAPERSIZE_ENV12, "Envelope #12" },
1032         { DEVMODE_PAPERSIZE_ENV14, "Envelope #14" },
1033         { DEVMODE_PAPERSIZE_CSHEET, "C sheet" },
1034         { DEVMODE_PAPERSIZE_DSHEET, "D sheet" },
1035         { DEVMODE_PAPERSIZE_ESHEET, "E sheet" },
1036         { DEVMODE_PAPERSIZE_ENVDL, "Envelope DL" },
1037         { DEVMODE_PAPERSIZE_ENVC5, "Envelope C5" },
1038         { DEVMODE_PAPERSIZE_ENVC3, "Envelope C3" },
1039         { DEVMODE_PAPERSIZE_ENVC4, "Envelope C4" },
1040         { DEVMODE_PAPERSIZE_ENVC6, "Envelope C6" },
1041         { DEVMODE_PAPERSIZE_ENVC65, "Envelope C65" },
1042         { DEVMODE_PAPERSIZE_ENVB4, "Envelope B4" },
1043         { DEVMODE_PAPERSIZE_ENVB5, "Envelope B5" },
1044         { DEVMODE_PAPERSIZE_ENVB6, "Envelope B6" },
1045         { DEVMODE_PAPERSIZE_ENVITALY, "Envelope (Italy)" },
1046         { DEVMODE_PAPERSIZE_ENVMONARCH, "Envelope (Monarch)" },
1047         { DEVMODE_PAPERSIZE_ENVPERSONAL, "Envelope (Personal)" },
1048         { DEVMODE_PAPERSIZE_FANFOLDUS, "Fanfold (US)" },
1049         { DEVMODE_PAPERSIZE_FANFOLDSTDGERMAN, "Fanfold (Std German)" },
1050         { DEVMODE_PAPERSIZE_FANFOLDLGLGERMAN, "Fanfold (Legal German)" },
1051         { DEVMODE_PAPERSIZE_ISOB4, "B4 (ISO)" },
1052         { DEVMODE_PAPERSIZE_JAPANESEPOSTCARD, "Japanese postcard" },
1053         { DEVMODE_PAPERSIZE_9X11, "9x11" },
1054         { DEVMODE_PAPERSIZE_10X11, "10x11" },
1055         { DEVMODE_PAPERSIZE_15X11, "15x11" },
1056         { DEVMODE_PAPERSIZE_ENVINVITE, "Envelope (Invite)" },
1057         { DEVMODE_PAPERSIZE_RESERVED48, "Reserved (48)" },
1058         { DEVMODE_PAPERSIZE_RESERVED49, "Reserved (49)" },
1059         { DEVMODE_PAPERSIZE_LETTEREXTRA, "Letter (Extra)" },
1060         { DEVMODE_PAPERSIZE_LEGALEXTRA, "Legal (Extra)" },
1061         { DEVMODE_PAPERSIZE_TABLOIDEXTRA, "Tabloid (Extra)" },
1062         { DEVMODE_PAPERSIZE_A4EXTRA, "A4 (Extra)" },
1063         { DEVMODE_PAPERSIZE_LETTERTRANS, "Letter (Transverse)" },
1064         { DEVMODE_PAPERSIZE_A4TRANS, "A4 (Transverse)" },
1065         { DEVMODE_PAPERSIZE_LETTEREXTRATRANS, "Letter (Extra, Transverse)" },
1066         { DEVMODE_PAPERSIZE_APLUS, "A+" },
1067         { DEVMODE_PAPERSIZE_BPLUS, "B+" },
1068         { DEVMODE_PAPERSIZE_LETTERPLUS, "Letter+" },
1069         { DEVMODE_PAPERSIZE_A4PLUS, "A4+" },
1070         { DEVMODE_PAPERSIZE_A5TRANS, "A5 (Transverse)" },
1071         { DEVMODE_PAPERSIZE_B5TRANS, "B5 (Transverse)" },
1072         { DEVMODE_PAPERSIZE_A3EXTRA, "A3 (Extra)" },
1073         { DEVMODE_PAPERSIZE_A5EXTRA, "A5 (Extra)" },
1074         { DEVMODE_PAPERSIZE_B5EXTRA, "B5 (Extra)" },
1075         { DEVMODE_PAPERSIZE_A2, "A2" },
1076         { DEVMODE_PAPERSIZE_A3TRANS, "A3 (Transverse)" },
1077         { DEVMODE_PAPERSIZE_A3EXTRATRANS, "A3 (Extra, Transverse" },
1078         { DEVMODE_PAPERSIZE_DBLJAPANESEPOSTCARD, "Double Japanese Postcard" },
1079         { DEVMODE_PAPERSIZE_A6, "A6" },
1080         { DEVMODE_PAPERSIZE_JENVKAKU2, "Japanese Envelope (Kaku #2)" },
1081         { DEVMODE_PAPERSIZE_JENVKAKU3, "Japanese Envelope (Kaku #3)" },
1082         { DEVMODE_PAPERSIZE_JENVCHOU3, "Japanese Envelope (Chou #3)" },
1083         { DEVMODE_PAPERSIZE_JENVCHOU4, "Japaneve Envelope (Chou #4)" },
1084         { DEVMODE_PAPERSIZE_LETTERROT, "Letter (Rotated)" },
1085         { DEVMODE_PAPERSIZE_A3ROT, "A3 (Rotated)" },
1086         { DEVMODE_PAPERSIZE_A4ROT, "A4 (Rotated)" },
1087         { DEVMODE_PAPERSIZE_A5ROT, "A5 (Rotated)" },
1088         { DEVMODE_PAPERSIZE_B4JISROT, "B4 (JIS, Rotated)" },
1089         { DEVMODE_PAPERSIZE_B5JISROT, "B5 (JIS, Rotated)"},
1090         { DEVMODE_PAPERSIZE_JAPANESEPOSTCARDROT, 
1091           "Japanese Postcard (Rotated)" },
1092         { DEVMODE_PAPERSIZE_DBLJAPANESEPOSTCARDROT82, 
1093           "Double Japanese Postcard (Rotated)" },
1094         { DEVMODE_PAPERSIZE_A6ROT, "A6 (Rotated)" },
1095         { DEVMODE_PAPERSIZE_JENVKAKU2ROT, 
1096           "Japanese Envelope (Kaku #2, Rotated)" },
1097         { DEVMODE_PAPERSIZE_JENVKAKU3ROT, 
1098           "Japanese Envelope (Kaku #3, Rotated)" },
1099         { DEVMODE_PAPERSIZE_JENVCHOU3ROT, 
1100           "Japanese Envelope (Chou #3, Rotated)" },
1101         { DEVMODE_PAPERSIZE_JENVCHOU4ROT, 
1102           "Japanese Envelope (Chou #4, Rotated)" },
1103         { DEVMODE_PAPERSIZE_B6JIS, "B6 (JIS)" },
1104         { DEVMODE_PAPERSIZE_B6JISROT, "B6 (JIS, Rotated)" },
1105         { DEVMODE_PAPERSIZE_12X11, "12x11" },
1106         { DEVMODE_PAPERSIZE_JENVYOU4, "Japanese Envelope (You #4)" },
1107         { DEVMODE_PAPERSIZE_JENVYOU4ROT, 
1108           "Japanese Envelope (You #4, Rotated" },
1109         { DEVMODE_PAPERSIZE_P16K, "PRC 16K" },
1110         { DEVMODE_PAPERSIZE_P32K, "PRC 32K" },
1111         { DEVMODE_PAPERSIZE_P32KBIG, "P32K (Big)" },
1112         { DEVMODE_PAPERSIZE_PENV1, "PRC Envelope #1" },
1113         { DEVMODE_PAPERSIZE_PENV2, "PRC Envelope #2" },
1114         { DEVMODE_PAPERSIZE_PENV3, "PRC Envelope #3" },
1115         { DEVMODE_PAPERSIZE_PENV4, "PRC Envelope #4" },
1116         { DEVMODE_PAPERSIZE_PENV5, "PRC Envelope #5" },
1117         { DEVMODE_PAPERSIZE_PENV6, "PRC Envelope #6" },
1118         { DEVMODE_PAPERSIZE_PENV7, "PRC Envelope #7" },
1119         { DEVMODE_PAPERSIZE_PENV8, "PRC Envelope #8" },
1120         { DEVMODE_PAPERSIZE_PENV9, "PRC Envelope #9" },
1121         { DEVMODE_PAPERSIZE_PENV10, "PRC Envelope #10" },
1122         { DEVMODE_PAPERSIZE_P16KROT, "PRC 16K (Rotated)" },
1123         { DEVMODE_PAPERSIZE_P32KROT, "PRC 32K (Rotated)" },
1124         { DEVMODE_PAPERSIZE_P32KBIGROT, "PRC 32K (Big, Rotated)" },
1125         { DEVMODE_PAPERSIZE_PENV1ROT, "PRC Envelope #1 (Rotated)" },
1126         { DEVMODE_PAPERSIZE_PENV2ROT, "PRC Envelope #2 (Rotated)" },
1127         { DEVMODE_PAPERSIZE_PENV3ROT, "PRC Envelope #3 (Rotated)" },
1128         { DEVMODE_PAPERSIZE_PENV4ROT, "PRC Envelope #4 (Rotated)" },
1129         { DEVMODE_PAPERSIZE_PENV5ROT, "PRC Envelope #5 (Rotated)" },
1130         { DEVMODE_PAPERSIZE_PENV6ROT, "PRC Envelope #6 (Rotated)" },
1131         { DEVMODE_PAPERSIZE_PENV7ROT, "PRC Envelope #7 (Rotated)" },
1132         { DEVMODE_PAPERSIZE_PENV8ROT, "PRC Envelope #8 (Rotated)" },
1133         { DEVMODE_PAPERSIZE_PENV9ROT, "PRC Envelope #9 (Rotated)" },
1134         { DEVMODE_PAPERSIZE_PENV10ROT, "PRC Envelope #10 (Rotated)" },
1135         { 0, NULL }
1136 };
1137
1138 /* List of observed specversions */
1139
1140 static const value_string devmode_specversion_vals[] =
1141 {
1142         { 0x0320, "Observed" },
1143         { 0x0400, "Observed" },
1144         { 0x0401, "Observed" },
1145         { 0x040d, "Observed" },
1146         { 0, NULL }
1147 };
1148
1149 /* Paper sources */
1150
1151 static const value_string devmode_papersource_vals[] =
1152 {
1153         { DEVMODE_PAPERSOURCE_UPPER, "Upper" },
1154         { DEVMODE_PAPERSOURCE_LOWER, "Lower" },
1155         { DEVMODE_PAPERSOURCE_MIDDLE, "Middle" },
1156         { DEVMODE_PAPERSOURCE_MANUAL, "Manual" },
1157         { DEVMODE_PAPERSOURCE_ENV, "Envelope" },
1158         { DEVMODE_PAPERSOURCE_ENVMANUAL, "Envelope Manual" },
1159         { DEVMODE_PAPERSOURCE_AUTO, "Auto" },
1160         { DEVMODE_PAPERSOURCE_TRACTOR, "Tractor" },
1161         { DEVMODE_PAPERSOURCE_SMALLFMT, "Small Format" },
1162         { DEVMODE_PAPERSOURCE_LARGEFMAT, "Large Format" },
1163         { DEVMODE_PAPERSOURCE_LARGECAP, "Large Capacity" },
1164         { DEVMODE_PAPERSOURCE_CASSETTE, "Cassette" },
1165         { DEVMODE_PAPERSOURCE_FORMSRC, "Form Source" },
1166         { 0, NULL }
1167 };
1168
1169 /* Print quality */
1170
1171 static const value_string devmode_printquality_vals[] =
1172 {
1173         { DEVMODE_PRINTQUALITY_HIGH, "High" },
1174         { DEVMODE_PRINTQUALITY_MEDIUM, "Medium" },
1175         { DEVMODE_PRINTQUALITY_LOW, "Low" },
1176         { DEVMODE_PRINTQUALITY_DRAFT, "Draft" },
1177         { 0, NULL }
1178 };
1179
1180 /* Color */
1181
1182 static const value_string devmode_colour_vals[] =
1183 {
1184         { DEVMODE_COLOUR_COLOUR, "Colour" },
1185         { DEVMODE_COLOUR_MONO, "Monochrome" },
1186         { 0, NULL }
1187 };
1188
1189 /* TrueType options */
1190
1191 static const value_string devmode_ttoption_vals[] =
1192 {
1193         { 0, "Not set" },
1194         { DEVMODE_TTOPTION_BITMAP, "Bitmap" },
1195         { DEVMODE_TTOPTION_DOWNLOAD, "Download" },
1196         { DEVMODE_TTOPTION_DOWNLOAD_OUTLINE, "Download outline" },
1197         { DEVMODE_TTOPTION_SUBDEV, "Substitute device fonts" },
1198         { 0, NULL }
1199 };
1200
1201 /* Collate info */
1202
1203 static const value_string devmode_collate_vals[] =
1204 {
1205         { DEVMODE_COLLATE_FALSE, "False" },
1206         { DEVMODE_COLLATE_TRUE, "True" },
1207         { 0, NULL }
1208 };
1209
1210 /* Duplex info */
1211
1212 static const value_string devmode_duplex_vals[] =
1213 {
1214         { DEVMODE_DUPLEX_SIMPLEX, "Simplex" },
1215         { DEVMODE_DUPLEX_VERT, "Vertical" },
1216         { DEVMODE_DUPLEX_HORIZ, "Horizontal" },
1217         { 0, NULL }
1218 };
1219
1220 static const value_string devmode_displayflags_vals[] =
1221 {
1222         { 0, "Colour" },
1223         { DEVMODE_DISPLAYFLAGS_GRAYSCALE, "Grayscale" },
1224         { DEVMODE_DISPLAYFLAGS_INTERLACED, "Interlaced" },
1225         { 0, NULL }
1226 };
1227
1228 static const value_string devmode_icmmethod_vals[] =
1229 {
1230         { DEVMODE_ICMMETHOD_NONE, "None" },
1231         { DEVMODE_ICMMETHOD_SYSTEM, "System" },
1232         { DEVMODE_ICMMETHOD_DRIVER, "Driver" },
1233         { DEVMODE_ICMMETHOD_DEVICE, "Device" },
1234         { 0, NULL }
1235 };
1236
1237 static const value_string devmode_icmintent_vals[] =
1238 {
1239         { 0, "Not set" },
1240         { DEVMODE_ICMINTENT_SATURATE, "Saturate" },
1241         { DEVMODE_ICMINTENT_CONTRAST, "Contrast" },
1242         { DEVMODE_ICMINTENT_COLORIMETRIC, "Colorimetric" },
1243         { DEVMODE_ICMINTENT_ABS_COLORIMETRIC, "Absolute colorimetric" },
1244         { 0, NULL }
1245 };
1246
1247 static const value_string devmode_mediatype_vals[] =
1248 {
1249         { 0, "Not set" },
1250         { DEVMODE_MEDIATYPE_STANDARD, "Standard" },
1251         { DEVMODE_MEDIATYPE_TRANSPARENCY, "Transparency" },
1252         { DEVMODE_MEDIATYPE_GLOSSY, "Glossy" },
1253         { 0, NULL }
1254 };
1255
1256 static const value_string devmode_dithertype_vals[] =
1257 {
1258         { 0, "Not set" },
1259         { DEVMODE_DITHERTYPE_NONE, "None" },
1260         { DEVMODE_DITHERTYPE_COARSE, "Coarse" },
1261         { DEVMODE_DITHERTYPE_LINE, "Line" },
1262         { DEVMODE_DITHERTYPE_LINEART, "Line art" },
1263         { DEVMODE_DITHERTYPE_ERRORDIFFUSION, "Error diffusion" },
1264         { DEVMODE_DITHERTYPE_RESERVED6, "Reserved 6" },
1265         { DEVMODE_DITHERTYPE_RESERVED7, "Reserved 7" },
1266         { DEVMODE_DITHERTYPE_GRAYSCALE, "Grayscale" },
1267         { 0, NULL }
1268 };
1269
1270 static gint ett_DEVMODE_fields;
1271
1272 static int
1273 dissect_DEVMODE_fields(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1274                        proto_tree *tree, char *drep _U_, guint32 *pdata)
1275 {
1276         proto_item *item;
1277         proto_tree *subtree;
1278         guint32 fields;
1279
1280         proto_tree_add_uint_hidden(
1281                 tree, hf_devmode, tvb, offset, 0, 1);
1282
1283         offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
1284                                     hf_devmode_fields, &fields);
1285
1286         item = proto_tree_add_text(tree, tvb, offset - 4, 4,
1287                                    "Fields: 0x%08x", fields);
1288
1289         subtree = proto_item_add_subtree(item, ett_DEVMODE_fields);
1290
1291         proto_tree_add_boolean(
1292                 subtree, hf_devmode_fields_orientation, 
1293                 tvb, offset - 4, 4, fields);
1294
1295         proto_tree_add_boolean(
1296                 subtree, hf_devmode_fields_papersize, 
1297                 tvb, offset - 4, 4, fields);
1298
1299         proto_tree_add_boolean(
1300                 subtree, hf_devmode_fields_paperlength, 
1301                 tvb, offset - 4, 4, fields);
1302
1303         proto_tree_add_boolean(
1304                 subtree, hf_devmode_fields_paperwidth, 
1305                 tvb, offset - 4, 4, fields);
1306
1307         proto_tree_add_boolean(
1308                 subtree, hf_devmode_fields_scale, 
1309                 tvb, offset - 4, 4, fields);
1310
1311         proto_tree_add_boolean(
1312                 subtree, hf_devmode_fields_position, 
1313                 tvb, offset - 4, 4, fields);
1314
1315         proto_tree_add_boolean(
1316                 subtree, hf_devmode_fields_nup, 
1317                 tvb, offset - 4, 4, fields);
1318
1319         proto_tree_add_boolean(
1320                 subtree, hf_devmode_fields_copies, 
1321                 tvb, offset - 4, 4, fields);
1322
1323         proto_tree_add_boolean(
1324                 subtree, hf_devmode_fields_defaultsource, 
1325                 tvb, offset - 4, 4, fields);
1326
1327         proto_tree_add_boolean(
1328                 subtree, hf_devmode_fields_printquality, 
1329                 tvb, offset - 4, 4, fields);
1330
1331         proto_tree_add_boolean(
1332                 subtree, hf_devmode_fields_color, 
1333                 tvb, offset - 4, 4, fields);
1334
1335         proto_tree_add_boolean(
1336                 subtree, hf_devmode_fields_duplex, 
1337                 tvb, offset - 4, 4, fields);
1338
1339         proto_tree_add_boolean(
1340                 subtree, hf_devmode_fields_yresolution, 
1341                 tvb, offset - 4, 4, fields);
1342
1343         proto_tree_add_boolean(
1344                 subtree, hf_devmode_fields_ttoption, 
1345                 tvb, offset - 4, 4, fields);
1346
1347         proto_tree_add_boolean(
1348                 subtree, hf_devmode_fields_collate, 
1349                 tvb, offset - 4, 4, fields);
1350
1351         proto_tree_add_boolean(
1352                 subtree, hf_devmode_fields_formname, 
1353                 tvb, offset - 4, 4, fields);
1354
1355         proto_tree_add_boolean(
1356                 subtree, hf_devmode_fields_logpixels, 
1357                 tvb, offset - 4, 4, fields);
1358
1359         proto_tree_add_boolean(
1360                 subtree, hf_devmode_fields_bitsperpel, 
1361                 tvb, offset - 4, 4, fields);
1362
1363         proto_tree_add_boolean(
1364                 subtree, hf_devmode_fields_pelswidth, 
1365                 tvb, offset - 4, 4, fields);
1366
1367         proto_tree_add_boolean(
1368                 subtree, hf_devmode_fields_pelsheight, 
1369                 tvb, offset - 4, 4, fields);
1370
1371         proto_tree_add_boolean(
1372                 subtree, hf_devmode_fields_displayflags, 
1373                 tvb, offset - 4, 4, fields);
1374
1375         proto_tree_add_boolean(
1376                 subtree, hf_devmode_fields_displayfrequency, 
1377                 tvb, offset - 4, 4, fields);
1378
1379         proto_tree_add_boolean(
1380                 subtree, hf_devmode_fields_icmmethod, 
1381                 tvb, offset - 4, 4, fields);
1382
1383         proto_tree_add_boolean(
1384                 subtree, hf_devmode_fields_icmintent, 
1385                 tvb, offset - 4, 4, fields);
1386
1387         proto_tree_add_boolean(
1388                 subtree, hf_devmode_fields_mediatype, 
1389                 tvb, offset - 4, 4, fields);
1390
1391         proto_tree_add_boolean(
1392                 subtree, hf_devmode_fields_dithertype, 
1393                 tvb, offset - 4, 4, fields);
1394
1395         proto_tree_add_boolean(
1396                 subtree, hf_devmode_fields_panningwidth, 
1397                 tvb, offset - 4, 4, fields);
1398
1399         proto_tree_add_boolean(
1400                 subtree, hf_devmode_fields_panningheight, 
1401                 tvb, offset - 4, 4, fields);
1402
1403         if (pdata)
1404                 *pdata = fields;
1405
1406         return offset;
1407 }
1408
1409 static gint ett_DEVMODE = -1;
1410
1411 static int dissect_DEVMODE(tvbuff_t *tvb, int offset, packet_info *pinfo, 
1412                            proto_tree *tree, char *drep)
1413 {
1414         dcerpc_info *di = pinfo->private_data;
1415         proto_item *item;
1416         proto_tree *subtree;
1417         guint16 driver_extra;
1418         gint16 print_quality;
1419         guint32 fields;
1420         int struct_start = offset;
1421
1422         if (di->conformant_run)
1423                 return offset;  
1424
1425         item = proto_tree_add_text(tree, tvb, offset, 0, "Devicemode");
1426         subtree = proto_item_add_subtree(item, ett_DEVMODE);
1427
1428         offset = dissect_ndr_uint32(
1429                 tvb, offset, pinfo, subtree, drep, hf_devmode_size, 
1430                 NULL);
1431
1432         /* The device name is stored in a 32-wchar buffer */
1433
1434         dissect_spoolss_uint16uni(tvb, offset, pinfo, subtree, drep, NULL,
1435                 "Devicename");
1436         offset += 64;
1437
1438         offset = dissect_ndr_uint16(
1439                 tvb, offset, pinfo, subtree, drep, 
1440                 hf_devmode_spec_version, NULL);
1441
1442         offset = dissect_ndr_uint16(
1443                 tvb, offset, pinfo, subtree, drep, 
1444                 hf_devmode_driver_version, NULL);
1445
1446         offset = dissect_ndr_uint16(
1447                 tvb, offset, pinfo, subtree, drep, 
1448                 hf_devmode_size2, NULL);
1449
1450         offset = dissect_ndr_uint16(
1451                 tvb, offset, pinfo, subtree, drep, 
1452                 hf_devmode_driver_extra_len, &driver_extra);
1453
1454         offset = dissect_DEVMODE_fields(
1455                 tvb, offset, pinfo, subtree, drep, &fields);
1456
1457         offset = dissect_ndr_uint16(
1458                 tvb, offset, pinfo, subtree, drep, 
1459                 hf_devmode_orientation, NULL);
1460
1461         offset = dissect_ndr_uint16(
1462                 tvb, offset, pinfo, subtree, drep, 
1463                 hf_devmode_paper_size, NULL);
1464
1465         offset = dissect_ndr_uint16(
1466                 tvb, offset, pinfo, subtree, drep, 
1467                 hf_devmode_paper_length, NULL);
1468
1469         offset = dissect_ndr_uint16(
1470                 tvb, offset, pinfo, subtree, drep, 
1471                 hf_devmode_paper_width, NULL);
1472
1473         offset = dissect_ndr_uint16(
1474                 tvb, offset, pinfo, subtree, drep, 
1475                 hf_devmode_scale, NULL);
1476
1477         offset = dissect_ndr_uint16(
1478                 tvb, offset, pinfo, subtree, drep, 
1479                 hf_devmode_copies, NULL);
1480
1481         offset = dissect_ndr_uint16(
1482                 tvb, offset, pinfo, subtree, drep, 
1483                 hf_devmode_default_source, NULL);
1484
1485         offset = dissect_ndr_uint16(
1486                 tvb, offset, pinfo, NULL, drep, 
1487                 hf_devmode_print_quality, &print_quality);
1488
1489         if (print_quality < 0)
1490                 proto_tree_add_item(
1491                         subtree, hf_devmode_print_quality, tvb,
1492                         offset - 2, 2, drep[0] & 0x10);
1493         else
1494                 proto_tree_add_text(
1495                         subtree, tvb, offset - 4, 4, 
1496                         "Print Quality: %d dpi", print_quality);
1497
1498         offset = dissect_ndr_uint16(
1499                 tvb, offset, pinfo, subtree, drep, 
1500                 hf_devmode_color, NULL);
1501
1502         offset = dissect_ndr_uint16(
1503                 tvb, offset, pinfo, subtree, drep, 
1504                 hf_devmode_duplex, NULL);
1505
1506         offset = dissect_ndr_uint16(
1507                 tvb, offset, pinfo, subtree, drep, 
1508                 hf_devmode_y_resolution, NULL);
1509
1510         offset = dissect_ndr_uint16(
1511                 tvb, offset, pinfo, subtree, drep, 
1512                 hf_devmode_tt_option, NULL);
1513
1514         offset = dissect_ndr_uint16(
1515                 tvb, offset, pinfo, subtree, drep, 
1516                 hf_devmode_collate, NULL);
1517
1518         dissect_spoolss_uint16uni(tvb, offset, pinfo, subtree, drep, NULL,
1519                 "Form name");
1520         offset += 64;
1521
1522         offset = dissect_ndr_uint16(
1523                 tvb, offset, pinfo, subtree, drep, 
1524                 hf_devmode_log_pixels, NULL);
1525
1526         offset = dissect_ndr_uint32(
1527                 tvb, offset, pinfo, subtree, drep, 
1528                 hf_devmode_bits_per_pel, NULL);
1529
1530         offset = dissect_ndr_uint32(
1531                 tvb, offset, pinfo, subtree, drep, 
1532                 hf_devmode_pels_width, NULL);
1533
1534         offset = dissect_ndr_uint32(
1535                 tvb, offset, pinfo, subtree, drep, 
1536                 hf_devmode_pels_height, NULL);
1537
1538         offset = dissect_ndr_uint32(
1539                 tvb, offset, pinfo, subtree, drep, 
1540                 hf_devmode_display_flags, NULL);
1541
1542         offset = dissect_ndr_uint32(
1543                 tvb, offset, pinfo, subtree, drep, 
1544                 hf_devmode_display_freq, NULL);
1545         
1546         /* TODO: Some of the remaining fields are optional.  See
1547            rpc_parse/parse_spoolss.c in the Samba source for details. */
1548
1549         offset = dissect_ndr_uint32(
1550                 tvb, offset, pinfo, subtree, drep, 
1551                 hf_devmode_icm_method, NULL);
1552         
1553         offset = dissect_ndr_uint32(
1554                 tvb, offset, pinfo, subtree, drep, 
1555                 hf_devmode_icm_intent, NULL);
1556
1557         offset = dissect_ndr_uint32(
1558                 tvb, offset, pinfo, subtree, drep, 
1559                 hf_devmode_media_type, NULL);
1560         
1561         offset = dissect_ndr_uint32(
1562                 tvb, offset, pinfo, subtree, drep, 
1563                 hf_devmode_dither_type, NULL);
1564
1565         offset = dissect_ndr_uint32(
1566                 tvb, offset, pinfo, subtree, drep, 
1567                 hf_devmode_reserved1, NULL);
1568         
1569         offset = dissect_ndr_uint32(
1570                 tvb, offset, pinfo, subtree, drep, 
1571                 hf_devmode_reserved2, NULL);
1572         
1573         offset = dissect_ndr_uint32(
1574                 tvb, offset, pinfo, subtree, drep, 
1575                 hf_devmode_panning_width, NULL);
1576         
1577         offset = dissect_ndr_uint32(
1578                 tvb, offset, pinfo, subtree, drep, 
1579                 hf_devmode_panning_height, NULL);
1580
1581         if (driver_extra)
1582                 offset = dissect_ndr_uint8s(
1583                         tvb, offset, pinfo, subtree, drep,
1584                         hf_devmode_driver_extra, driver_extra, NULL);
1585                         
1586         proto_item_set_len(item, offset - struct_start);
1587
1588         return offset;                            
1589 }
1590
1591 /*
1592  * DEVMODE_CTR
1593  */
1594
1595 static gint ett_DEVMODE_CTR = -1;
1596
1597 static int dissect_DEVMODE_CTR(tvbuff_t *tvb, int offset, packet_info *pinfo, 
1598                                proto_tree *tree, char *drep)
1599 {
1600         proto_item *item;
1601         proto_tree *subtree;
1602         guint32 size;
1603
1604         item = proto_tree_add_text(
1605                 tree, tvb, offset, 0, "Devicemode container");
1606
1607         subtree = proto_item_add_subtree(item, ett_DEVMODE_CTR);
1608         
1609         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
1610                                     hf_devmodectr_size, &size);
1611
1612         offset = dissect_ndr_pointer(
1613                 tvb, offset, pinfo, subtree, drep,
1614                 dissect_DEVMODE, NDR_POINTER_UNIQUE, "Devicemode", -1);
1615
1616         return offset;
1617 }
1618         
1619 /*
1620  * Relative string given by offset into the current buffer.  Note that
1621  * the offset for subsequent relstrs are against the structure start, not
1622  * the point where the offset is parsed from.
1623  */
1624
1625 static gint ett_RELSTR = -1;
1626
1627 static int
1628 dissect_spoolss_relstr(tvbuff_t *tvb, int offset, packet_info *pinfo,
1629                        proto_tree *tree, char *drep, int hf_index,
1630                        int struct_start, char **data)
1631 {
1632         proto_item *item;
1633         proto_tree *subtree;
1634         guint32 relstr_offset, relstr_start, relstr_end;
1635         char *text;
1636
1637         /* Peek ahead to read the string.  We need this for the 
1638            proto_tree_add_string() call so filtering will work. */
1639
1640         offset = dissect_ndr_uint32(
1641                 tvb, offset, pinfo, NULL, drep, hf_offset, &relstr_offset);
1642
1643         relstr_start = relstr_offset + struct_start;
1644
1645         if (relstr_offset)
1646                 relstr_end = dissect_spoolss_uint16uni(
1647                         tvb, relstr_start, pinfo, NULL, drep, &text, NULL);
1648         else                    /* relstr_offset == 0 is a NULL string */
1649                 text = g_strdup("");
1650                 
1651         /* OK now add the proto item with the string value */
1652
1653         item = proto_tree_add_string(tree, hf_index, tvb, offset, 4, text);
1654         subtree = proto_item_add_subtree(item, ett_RELSTR);
1655
1656         dissect_ndr_uint32(
1657                 tvb, offset - 4, pinfo, subtree, drep, hf_offset, NULL);
1658
1659         if (relstr_offset)
1660                 dissect_spoolss_uint16uni(
1661                         tvb, relstr_start, pinfo, subtree, drep, NULL, NULL);
1662
1663         if (data)
1664                 *data = text;
1665         else
1666                 g_free(text);
1667
1668         return offset;
1669 }
1670
1671 /* An array of relative strings.  This is currently just a copy of the
1672    dissect_spoolss_relstr() function as I can't find an example driver that
1673    has more than one dependent file. */
1674
1675 static gint ett_RELSTR_ARRAY = -1;
1676
1677 static int
1678 dissect_spoolss_relstrarray(tvbuff_t *tvb, int offset, packet_info *pinfo,
1679                             proto_tree *tree, char *drep, int hf_index,
1680                             int struct_start, char **data)
1681 {
1682         proto_item *item;
1683         proto_tree *subtree;
1684         guint32 relstr_offset, relstr_start, relstr_end, relstr_len;
1685         char *text;
1686
1687         item = proto_tree_add_string(tree, hf_index, tvb, offset, 4, "");
1688
1689         subtree = proto_item_add_subtree(item, ett_RELSTR_ARRAY);
1690
1691         offset = dissect_ndr_uint32(
1692                 tvb, offset, pinfo, subtree, drep, hf_offset, &relstr_offset);
1693
1694         /* A relative offset of zero is a NULL string */
1695
1696         relstr_start = relstr_offset + struct_start;
1697
1698         if (relstr_offset)
1699                 relstr_end = dissect_spoolss_uint16uni(
1700                         tvb, relstr_start, pinfo, subtree, drep, &text, NULL);
1701         else {
1702                 text = g_strdup("NULL");
1703                 relstr_end = offset;
1704         }
1705
1706         relstr_len = relstr_end - relstr_start;
1707
1708         proto_item_append_text(item, text);
1709
1710         if (data)
1711                 *data = text;
1712         else
1713                 g_free(text);
1714
1715         return offset;
1716 }
1717
1718 /*
1719  * PRINTER_INFO_0
1720  */
1721
1722 static int hf_printer_status = -1;
1723
1724 static const value_string printer_status_vals[] =
1725 {
1726         { PRINTER_STATUS_OK, "OK" },
1727         { PRINTER_STATUS_PAUSED, "Paused" },
1728         { PRINTER_STATUS_ERROR, "Error" },
1729         { PRINTER_STATUS_PENDING_DELETION, "Pending deletion" },
1730         { PRINTER_STATUS_PAPER_JAM, "Paper jam" },
1731         { PRINTER_STATUS_PAPER_OUT, "Paper out" },
1732         { PRINTER_STATUS_MANUAL_FEED, "Manual feed" },
1733         { PRINTER_STATUS_PAPER_PROBLEM, "Paper problem" },
1734         { PRINTER_STATUS_OFFLINE, "Offline" },
1735         { PRINTER_STATUS_IO_ACTIVE, "IO active" },
1736         { PRINTER_STATUS_BUSY, "Busy" },
1737         { PRINTER_STATUS_PRINTING, "Printing" },
1738         { PRINTER_STATUS_OUTPUT_BIN_FULL, "Output bin full" },
1739         { PRINTER_STATUS_NOT_AVAILABLE, "Not available" },
1740         { PRINTER_STATUS_WAITING, "Waiting" },
1741         { PRINTER_STATUS_PROCESSING, "Processing" },
1742         { PRINTER_STATUS_INITIALIZING, "Initialising" },
1743         { PRINTER_STATUS_WARMING_UP, "Warming up" },
1744         { PRINTER_STATUS_TONER_LOW, "Toner low" },
1745         { PRINTER_STATUS_NO_TONER, "No toner" },
1746         { PRINTER_STATUS_PAGE_PUNT, "Page punt" },
1747         { PRINTER_STATUS_USER_INTERVENTION, "User intervention" },
1748         { PRINTER_STATUS_OUT_OF_MEMORY, "Out of memory" },
1749         { PRINTER_STATUS_DOOR_OPEN, "Door open" },
1750         { PRINTER_STATUS_SERVER_UNKNOWN, "Server unknown" },
1751         { PRINTER_STATUS_POWER_SAVE, "Power save" },
1752         { 0, NULL }
1753 };
1754
1755 static gint ett_PRINTER_INFO_0 = -1;
1756
1757 static int dissect_PRINTER_INFO_0(tvbuff_t *tvb, int offset, 
1758                                   packet_info *pinfo, proto_tree *tree, 
1759                                   char *drep)
1760 {
1761         offset = dissect_spoolss_relstr(
1762                 tvb, offset, pinfo, tree, drep, hf_printername,
1763                 0, NULL);
1764
1765         offset = dissect_spoolss_relstr(
1766                 tvb, offset, pinfo, tree, drep, hf_servername,
1767                 0, NULL);
1768
1769         offset = dissect_ndr_uint32(
1770                 tvb, offset, pinfo, tree, drep, hf_printer_cjobs, NULL);
1771
1772         offset = dissect_ndr_uint32(
1773                 tvb, offset, pinfo, tree, drep, hf_printer_total_jobs, 
1774                 NULL);
1775
1776         offset = dissect_ndr_uint32(
1777                 tvb, offset, pinfo, tree, drep, hf_printer_total_bytes, 
1778                 NULL);
1779
1780         offset = dissect_SYSTEM_TIME(
1781                 tvb, offset, pinfo, tree, drep, "Unknown time", TRUE, NULL);
1782
1783         offset = dissect_ndr_uint32(
1784                 tvb, offset, pinfo, tree, drep, hf_printer_global_counter, 
1785                 NULL);
1786
1787         offset = dissect_ndr_uint32(
1788                 tvb, offset, pinfo, tree, drep, hf_printer_total_pages, 
1789                 NULL);
1790
1791         offset = dissect_ndr_uint16(
1792                 tvb, offset, pinfo, tree, drep, hf_printer_major_version, 
1793                 NULL);
1794
1795         offset = dissect_ndr_uint16(
1796                 tvb, offset, pinfo, tree, drep, hf_printer_build_version, 
1797                 NULL);
1798
1799         offset = dissect_ndr_uint32(
1800                 tvb, offset, pinfo, tree, drep, hf_printer_unk7, NULL);
1801
1802         offset = dissect_ndr_uint32(
1803                 tvb, offset, pinfo, tree, drep, hf_printer_unk8, NULL);
1804
1805         offset = dissect_ndr_uint32(
1806                 tvb, offset, pinfo, tree, drep, hf_printer_unk9, NULL);
1807
1808         offset = dissect_ndr_uint32(
1809                 tvb, offset, pinfo, tree, drep, hf_printer_session_ctr, 
1810                 NULL);
1811
1812         offset = dissect_ndr_uint32( tvb, offset, pinfo, tree, drep,
1813                 hf_printer_unk11, NULL);
1814         
1815         offset = dissect_ndr_uint32( tvb, offset, pinfo, tree, drep,
1816                 hf_printer_printer_errors, NULL);
1817
1818         offset = dissect_ndr_uint32(
1819                 tvb, offset, pinfo, tree, drep, hf_printer_unk13, NULL);
1820
1821         offset = dissect_ndr_uint32(
1822                 tvb, offset, pinfo, tree, drep, hf_printer_unk14, NULL);
1823
1824         offset = dissect_ndr_uint32(
1825                 tvb, offset, pinfo, tree, drep, hf_printer_unk15, NULL);
1826
1827         offset = dissect_ndr_uint32(
1828                 tvb, offset, pinfo, tree, drep, hf_printer_unk16, NULL);
1829
1830         offset = dissect_ndr_uint32(
1831                 tvb, offset, pinfo, tree, drep, hf_printer_changeid, NULL);
1832
1833         offset = dissect_ndr_uint32(
1834                 tvb, offset, pinfo, tree, drep, hf_printer_unk18, NULL);
1835
1836         offset = dissect_ndr_uint32(
1837                 tvb, offset, pinfo, tree, drep, hf_printer_status, NULL);
1838
1839         offset = dissect_ndr_uint32(
1840                 tvb, offset, pinfo, tree, drep, hf_printer_unk20, NULL);
1841
1842         offset = dissect_ndr_uint32(
1843                 tvb, offset, pinfo, tree, drep, hf_printer_c_setprinter, 
1844                 NULL);
1845
1846         offset = dissect_ndr_uint16(
1847                 tvb, offset, pinfo, tree, drep, hf_printer_unk22, NULL);
1848
1849         offset = dissect_ndr_uint16(
1850                 tvb, offset, pinfo, tree, drep, hf_printer_unk23, NULL);
1851
1852         offset = dissect_ndr_uint16(
1853                 tvb, offset, pinfo, tree, drep, hf_printer_unk24, NULL);
1854
1855         offset = dissect_ndr_uint16(
1856                 tvb, offset, pinfo, tree, drep, hf_printer_unk25, NULL);
1857
1858         offset = dissect_ndr_uint16(
1859                 tvb, offset, pinfo, tree, drep, hf_printer_unk26, NULL);
1860
1861         offset = dissect_ndr_uint16(
1862                 tvb, offset, pinfo, tree, drep, hf_printer_unk27, NULL);
1863
1864         offset = dissect_ndr_uint16(
1865                 tvb, offset, pinfo, tree, drep, hf_printer_unk28, NULL);
1866
1867         offset = dissect_ndr_uint16(
1868                 tvb, offset, pinfo, tree, drep, hf_printer_unk29, NULL);
1869
1870         return offset;
1871 }
1872
1873 /*
1874  * PRINTER_INFO_1
1875  */
1876
1877 static gint ett_PRINTER_INFO_1 = -1;
1878
1879 static int dissect_PRINTER_INFO_1(tvbuff_t *tvb, int offset, 
1880                                   packet_info *pinfo, proto_tree *tree, 
1881                                   char *drep)
1882 {
1883         offset = dissect_ndr_uint32(
1884                 tvb, offset, pinfo, tree, drep,
1885                 hf_printer_flags, NULL);
1886
1887         offset = dissect_spoolss_relstr(
1888                 tvb, offset, pinfo, tree, drep, hf_printerdesc,
1889                 0, NULL);
1890
1891         offset = dissect_spoolss_relstr(
1892                 tvb, offset, pinfo, tree, drep, hf_printername,
1893                 0, NULL);
1894
1895         offset = dissect_spoolss_relstr(
1896                 tvb, offset, pinfo, tree, drep, hf_printercomment,
1897                 0, NULL);
1898
1899         return offset;
1900 }
1901
1902 /* Job status */
1903
1904 static const true_false_string tfs_job_status_paused = {
1905         "Job is paused",
1906         "Job is not paused"
1907 };
1908
1909 static const true_false_string tfs_job_status_error = {
1910         "Job has an error",
1911         "Job is OK"
1912 };
1913
1914 static const true_false_string tfs_job_status_deleting = {
1915         "Job is being deleted",
1916         "Job is not being deleted"
1917 };
1918
1919 static const true_false_string tfs_job_status_spooling = {
1920         "Job is being spooled",
1921         "Job is not being spooled"
1922 };
1923
1924 static const true_false_string tfs_job_status_printing = {
1925         "Job is being printed",
1926         "Job is not being printed"
1927 };
1928
1929 static const true_false_string tfs_job_status_offline = {
1930         "Job is offline",
1931         "Job is not offline"
1932 };
1933
1934 static const true_false_string tfs_job_status_paperout = {
1935         "Job is out of paper",
1936         "Job is not out of paper"
1937 };
1938
1939 static const true_false_string tfs_job_status_printed = {
1940         "Job has completed printing",
1941         "Job has not completed printing"
1942 };
1943
1944 static const true_false_string tfs_job_status_deleted = {
1945         "Job has been deleted",
1946         "Job has not been deleted"
1947 };
1948
1949 static const true_false_string tfs_job_status_blocked = {
1950         "Job has been blocked",
1951         "Job has not been blocked"
1952 };
1953
1954 static const true_false_string tfs_job_status_user_intervention = {
1955         "User intervention required",
1956         "User intervention not required"
1957 };
1958
1959 static gint ett_job_status = -1;
1960
1961 static int
1962 dissect_job_status(tvbuff_t *tvb, int offset, packet_info *pinfo,
1963                    proto_tree *tree, char *drep)
1964 {
1965         proto_item *item;
1966         proto_tree *subtree;
1967         guint32 status;
1968
1969         offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
1970                                     hf_job_status, &status);
1971
1972         item = proto_tree_add_text(tree, tvb, offset - 4, 4,
1973                                    "Status: 0x%08x", status);
1974
1975         subtree = proto_item_add_subtree(item, ett_job_status);
1976
1977         proto_tree_add_boolean(
1978                 subtree, hf_job_status_user_intervention, tvb, offset - 4, 4, 
1979                 status);
1980
1981         proto_tree_add_boolean(
1982                 subtree, hf_job_status_blocked, tvb, offset - 4, 4, status);
1983
1984         proto_tree_add_boolean(
1985                 subtree, hf_job_status_deleted, tvb, offset - 4, 4, status);
1986
1987         proto_tree_add_boolean(
1988                 subtree, hf_job_status_printed, tvb, offset - 4, 4, status);
1989
1990         proto_tree_add_boolean(
1991                 subtree, hf_job_status_paperout, tvb, offset - 4, 4, status);
1992
1993         proto_tree_add_boolean(
1994                 subtree, hf_job_status_offline, tvb, offset - 4, 4, status);
1995
1996         proto_tree_add_boolean(
1997                 subtree, hf_job_status_printing, tvb, offset - 4, 4, status);
1998
1999         proto_tree_add_boolean(
2000                 subtree, hf_job_status_spooling, tvb, offset - 4, 4, status);
2001
2002         proto_tree_add_boolean(
2003                 subtree, hf_job_status_deleting, tvb, offset - 4, 4, status);
2004
2005         proto_tree_add_boolean(
2006                 subtree, hf_job_status_error, tvb, offset - 4, 4, status);
2007
2008         proto_tree_add_boolean(
2009                 subtree, hf_job_status_paused, tvb, offset - 4, 4, status);
2010
2011         return offset;
2012 }
2013
2014 /* Printer attributes */
2015
2016 static gint ett_printer_attributes = -1;
2017
2018 static int hf_printer_attributes = -1;
2019 static int hf_printer_attributes_queued = -1;
2020 static int hf_printer_attributes_direct = -1;
2021 static int hf_printer_attributes_default = -1;
2022 static int hf_printer_attributes_shared = -1;
2023 static int hf_printer_attributes_network = -1;
2024 static int hf_printer_attributes_hidden = -1;
2025 static int hf_printer_attributes_local = -1;
2026 static int hf_printer_attributes_enable_devq = -1;
2027 static int hf_printer_attributes_keep_printed_jobs = -1;
2028 static int hf_printer_attributes_do_complete_first = -1;
2029 static int hf_printer_attributes_work_offline = -1;
2030 static int hf_printer_attributes_enable_bidi = -1;
2031 static int hf_printer_attributes_raw_only = -1;
2032 static int hf_printer_attributes_published = -1;
2033
2034 static const true_false_string tfs_printer_attributes_queued = {
2035         "Printer starts printing after last page spooled",
2036         "Printer starts printing while spooling"
2037 };
2038
2039 static const true_false_string tfs_printer_attributes_direct = {
2040         "Jobs sent directly to printer",
2041         "Jobs are spooled to printer before printing"
2042 };
2043
2044 static const true_false_string tfs_printer_attributes_default = {
2045         "Printer is the default printer",
2046         "Printer is not the default printer"
2047 };
2048
2049 static const true_false_string tfs_printer_attributes_shared = {
2050         "Printer is shared",
2051         "Printer is not shared"
2052 };
2053
2054 static const true_false_string tfs_printer_attributes_network = {
2055         "Printer is a network printer connection",
2056         "Printer is not a network printer connection"
2057 };
2058
2059 static const true_false_string tfs_printer_attributes_hidden = {
2060         "Reserved",
2061         "Reserved"
2062 };
2063
2064 static const true_false_string tfs_printer_attributes_local = {
2065         "Printer is a local printer",
2066         "Printer is not a local printer"
2067 };
2068
2069 static const true_false_string tfs_printer_attributes_enable_devq = {
2070         "Call DevQueryPrint",
2071         "Do not call DevQueryPrint"
2072 };
2073
2074 static const true_false_string tfs_printer_attributes_keep_printed_jobs = {
2075         "Jobs are kept after they are printed",
2076         "Jobs are deleted after printing"
2077 };
2078
2079 static const true_false_string tfs_printer_attributes_do_complete_first = {
2080         "Jobs that have completed spooling are scheduled before still spooling jobs",
2081         "Jobs are scheduled in the order they start spooling"
2082 };
2083
2084 static const true_false_string tfs_printer_attributes_work_offline = {
2085         "The printer is currently connected",
2086         "The printer is currently not connected"
2087 };
2088
2089 static const true_false_string tfs_printer_attributes_enable_bidi = {
2090         "Bidirectional communications are supported",
2091         "Bidirectional communications are not supported"
2092 };
2093
2094 static const true_false_string tfs_printer_attributes_raw_only = {
2095         "Only raw data type print jobs can be spooled",
2096         "All data type print jobs can be spooled"
2097 };
2098
2099 static const true_false_string tfs_printer_attributes_published = {
2100         "Printer is published in the directory",
2101         "Printer is not published in the directory"
2102 };
2103
2104 static int
2105 dissect_printer_attributes(tvbuff_t *tvb, int offset, packet_info *pinfo,
2106                            proto_tree *tree, char *drep)
2107 {
2108         proto_item *item;
2109         proto_tree *subtree;
2110         guint32 attributes;
2111
2112         offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
2113                                     hf_printer_attributes, &attributes);
2114
2115         item = proto_tree_add_text(tree, tvb, offset - 4, 4,
2116                                    "Attributes: 0x%08x", attributes);
2117
2118         subtree = proto_item_add_subtree(item, ett_printer_attributes);
2119
2120         proto_tree_add_boolean(
2121                 subtree, hf_printer_attributes_published,
2122                 tvb, offset - 4, 4, attributes);
2123
2124         proto_tree_add_boolean(
2125                 subtree, hf_printer_attributes_raw_only,
2126                 tvb, offset - 4, 4, attributes);
2127
2128         proto_tree_add_boolean(
2129                 subtree, hf_printer_attributes_enable_bidi,
2130                 tvb, offset - 4, 4, attributes);
2131
2132         proto_tree_add_boolean(
2133                 subtree, hf_printer_attributes_work_offline,
2134                 tvb, offset - 4, 4, attributes);
2135
2136         proto_tree_add_boolean(
2137                 subtree, hf_printer_attributes_do_complete_first,
2138                 tvb, offset - 4, 4, attributes);
2139
2140         proto_tree_add_boolean(
2141                 subtree, hf_printer_attributes_keep_printed_jobs,
2142                 tvb, offset - 4, 4, attributes);
2143
2144         proto_tree_add_boolean(
2145                 subtree, hf_printer_attributes_enable_devq,
2146                 tvb, offset - 4, 4, attributes);
2147
2148         proto_tree_add_boolean(
2149                 subtree, hf_printer_attributes_local,
2150                 tvb, offset - 4, 4, attributes);
2151
2152         proto_tree_add_boolean(
2153                 subtree, hf_printer_attributes_hidden,
2154                 tvb, offset - 4, 4, attributes);
2155
2156         proto_tree_add_boolean(
2157                 subtree, hf_printer_attributes_network,
2158                 tvb, offset - 4, 4, attributes);
2159
2160         proto_tree_add_boolean(
2161                 subtree, hf_printer_attributes_shared,
2162                 tvb, offset - 4, 4, attributes);
2163
2164         proto_tree_add_boolean(
2165                 subtree, hf_printer_attributes_default,
2166                 tvb, offset - 4, 4, attributes);
2167
2168         proto_tree_add_boolean(
2169                 subtree, hf_printer_attributes_direct,
2170                 tvb, offset - 4, 4, attributes);
2171
2172         proto_tree_add_boolean(
2173                 subtree, hf_printer_attributes_queued,
2174                 tvb, offset - 4, 4, attributes);
2175
2176         return offset;
2177 }
2178
2179 /*
2180  * PRINTER_INFO_2
2181  */
2182
2183 static gint ett_PRINTER_INFO_2 = -1;
2184
2185 static int dissect_PRINTER_INFO_2(tvbuff_t *tvb, int offset, 
2186                                   packet_info *pinfo, proto_tree *tree, 
2187                                   char *drep)
2188 {
2189         guint32 devmode_offset, secdesc_offset;
2190
2191         offset = dissect_spoolss_relstr(
2192                 tvb, offset, pinfo, tree, drep, hf_servername,
2193                 0, NULL);
2194
2195         offset = dissect_spoolss_relstr(
2196                 tvb, offset, pinfo, tree, drep, hf_printername,
2197                 0, NULL);
2198
2199         offset = dissect_spoolss_relstr(
2200                 tvb, offset, pinfo, tree, drep, hf_sharename,
2201                 0, NULL);
2202
2203         offset = dissect_spoolss_relstr(
2204                 tvb, offset, pinfo, tree, drep, hf_portname,
2205                 0, NULL);
2206
2207         offset = dissect_spoolss_relstr(
2208                 tvb, offset, pinfo, tree, drep, hf_drivername,
2209                 0, NULL);
2210
2211         offset = dissect_spoolss_relstr(
2212                 tvb, offset, pinfo, tree, drep, hf_printercomment,
2213                 0, NULL);
2214
2215         offset = dissect_spoolss_relstr(
2216                 tvb, offset, pinfo, tree, drep, hf_printerlocation,
2217                 0, NULL);
2218
2219         offset = dissect_ndr_uint32(
2220                 tvb, offset, pinfo, NULL, drep, hf_offset, 
2221                 &devmode_offset);
2222
2223         dissect_DEVMODE(tvb, devmode_offset - 4, pinfo, tree, drep);
2224
2225         offset = dissect_spoolss_relstr(
2226                 tvb, offset, pinfo, tree, drep, hf_sepfile,
2227                 0, NULL);
2228
2229         offset = dissect_spoolss_relstr(
2230                 tvb, offset, pinfo, tree, drep, hf_printprocessor,
2231                 0, NULL);
2232
2233         offset = dissect_spoolss_relstr(
2234                 tvb, offset, pinfo, tree, drep, hf_datatype,
2235                 0, NULL);
2236
2237         offset = dissect_spoolss_relstr(
2238                 tvb, offset, pinfo, tree, drep, hf_parameters,
2239                 0, NULL);
2240
2241         /*
2242          * XXX - what *is* the length of this security descriptor?
2243          * "prs_PRINTER_INFO_2()" is passed to "defer_ptr()", but
2244          * "defer_ptr" takes, as an argument, a function with a
2245          * different calling sequence from "prs_PRINTER_INFO_2()",
2246          * lacking the "len" argument, so that won't work.
2247          */
2248
2249         /* TODO: I think the length is only used to fix up the hex display
2250            pane.  We should be able to use proto_item_set_len() to avoid
2251            having to calculate the length. -tpot */
2252
2253         offset = dissect_ndr_uint32(
2254                 tvb, offset, pinfo, NULL, drep, hf_offset,
2255                 &secdesc_offset);
2256
2257         dissect_nt_sec_desc(
2258                 tvb, secdesc_offset, pinfo, tree, drep, 
2259                 tvb_length_remaining(tvb, secdesc_offset),
2260                 &spoolss_printer_access_mask_info);
2261
2262         offset = dissect_printer_attributes(tvb, offset, pinfo, tree, drep);
2263
2264         offset = dissect_ndr_uint32(
2265                 tvb, offset, pinfo, NULL, drep, hf_printer_priority,
2266                 NULL);
2267
2268         offset = dissect_ndr_uint32(
2269                 tvb, offset, pinfo, NULL, drep, 
2270                 hf_printer_default_priority, NULL);
2271
2272         offset = dissect_ndr_uint32(
2273                 tvb, offset, pinfo, NULL, drep, hf_start_time, NULL);
2274
2275         offset = dissect_ndr_uint32(
2276                 tvb, offset, pinfo, NULL, drep, hf_end_time, NULL);
2277
2278         offset = dissect_ndr_uint32(
2279                 tvb, offset, pinfo, tree, drep,
2280                 hf_printer_status, NULL);
2281
2282         offset = dissect_ndr_uint32(
2283                 tvb, offset, pinfo, NULL, drep, hf_printer_jobs, 
2284                 NULL);
2285
2286         offset = dissect_ndr_uint32(
2287                 tvb, offset, pinfo, NULL, drep, 
2288                 hf_printer_averageppm, NULL);
2289
2290         return offset;
2291 }
2292         
2293 /*
2294  * PRINTER_INFO_3
2295  */
2296
2297 static gint ett_PRINTER_INFO_3 = -1;
2298
2299 static int dissect_PRINTER_INFO_3(tvbuff_t *tvb, int offset, 
2300                                   packet_info *pinfo, proto_tree *tree, 
2301                                   char *drep)
2302 {
2303         offset = dissect_ndr_uint32(
2304                 tvb, offset, pinfo, tree, drep,
2305                 hf_printer_flags, NULL);
2306         
2307         offset = dissect_nt_sec_desc(
2308                 tvb, offset, pinfo, tree, drep, 
2309                 tvb_length_remaining(tvb, offset), 
2310                 &spoolss_printer_access_mask_info);
2311
2312         return offset;
2313 }
2314
2315 /*
2316  * PRINTER_INFO_7
2317  */
2318
2319 static gint ett_PRINTER_INFO_7 = -1;
2320
2321 static const value_string getprinter_action_vals[] = {
2322         { DS_PUBLISH, "Publish" },
2323         { DS_UNPUBLISH, "Unpublish" },
2324         { DS_UPDATE, "Update" },
2325
2326         /* Not sure what the constant values are here */
2327
2328 /*      { DS_PENDING, "Pending" }, */
2329 /*      { DS_REPUBLISH, "Republish" }, */
2330
2331         { 0, NULL }
2332 };
2333
2334 static int dissect_PRINTER_INFO_7(tvbuff_t *tvb, int offset, 
2335                                   packet_info *pinfo, proto_tree *tree, 
2336                                   char *drep)
2337 {
2338         offset = dissect_spoolss_relstr(
2339                 tvb, offset, pinfo, tree, drep, hf_printer_guid,
2340                 0, NULL);
2341
2342         offset = dissect_ndr_uint32(
2343                 tvb, offset, pinfo, tree, drep,
2344                 hf_printer_action, NULL);
2345         
2346         return offset;
2347 }
2348
2349 /*
2350  * PRINTER_DATATYPE structure
2351  */
2352
2353 static gint ett_PRINTER_DATATYPE = -1;
2354
2355 static int dissect_PRINTER_DATATYPE(tvbuff_t *tvb, int offset, 
2356                                     packet_info *pinfo, proto_tree *tree, 
2357                                     char *drep _U_)
2358 {
2359         dcerpc_info *di = pinfo->private_data;
2360
2361         if (di->conformant_run)
2362                 return offset;
2363
2364         offset = dissect_ndr_cvstring(
2365                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
2366                 hf_datatype, TRUE, NULL);
2367
2368         return offset;
2369 }
2370
2371 /*
2372  * USER_LEVEL_1 structure
2373  */
2374
2375 static gint ett_USER_LEVEL_1 = -1;
2376
2377 static int hf_userlevel_size = -1;
2378 static int hf_userlevel_client = -1;
2379 static int hf_userlevel_user = -1;
2380 static int hf_userlevel_build = -1;
2381 static int hf_userlevel_major = -1;
2382 static int hf_userlevel_minor = -1;
2383 static int hf_userlevel_processor = -1;
2384
2385 static int dissect_USER_LEVEL_1(tvbuff_t *tvb, int offset, 
2386                                 packet_info *pinfo, proto_tree *tree, 
2387                                 char *drep)
2388 {
2389         guint32 level;
2390
2391         /* Guy has pointed out that this dissection looks wrong.  In
2392            the ethereal output for a USER_LEVEL_1 it looks like the 
2393            info level and container pointer are transposed.  I'm not 
2394            even sure this structure is a container. */
2395
2396         offset = dissect_ndr_uint32(
2397                 tvb, offset, pinfo, tree, drep, hf_level, &level);
2398
2399         offset = dissect_ndr_uint32(
2400                 tvb, offset, pinfo, tree, drep, hf_userlevel_size, NULL);
2401
2402         offset = dissect_ndr_str_pointer_item(
2403                 tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
2404                 "Client", hf_userlevel_client, 0);
2405
2406         offset = dissect_ndr_str_pointer_item(
2407                 tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
2408                 "User", hf_userlevel_user, 0);
2409
2410         offset = dissect_ndr_uint32(
2411                 tvb, offset, pinfo, tree, drep, hf_userlevel_build, NULL);
2412
2413         offset = dissect_ndr_uint32(
2414                 tvb, offset, pinfo, tree, drep, hf_userlevel_major, NULL);
2415
2416         offset = dissect_ndr_uint32(
2417                 tvb, offset, pinfo, tree, drep, hf_userlevel_minor, NULL);
2418
2419         offset = dissect_ndr_uint32(
2420                 tvb, offset, pinfo, tree, drep, hf_userlevel_processor, NULL);
2421
2422         return offset;
2423 }
2424
2425 /*
2426  * USER_LEVEL_CTR structure
2427  */
2428
2429 static gint ett_USER_LEVEL_CTR = -1;
2430
2431 static int dissect_USER_LEVEL_CTR(tvbuff_t *tvb, int offset, 
2432                                   packet_info *pinfo, proto_tree *tree, 
2433                                   char *drep)
2434 {
2435         dcerpc_info *di = pinfo->private_data;
2436         proto_item *item;
2437         proto_tree *subtree;
2438         guint32 level;
2439
2440         if (di->conformant_run)
2441                 return offset;
2442
2443         item = proto_tree_add_text(
2444                 tree, tvb, offset, 0, "User level container");
2445
2446         subtree = proto_item_add_subtree(item, ett_USER_LEVEL_CTR);
2447         
2448         offset = dissect_ndr_uint32(
2449                 tvb, offset, pinfo, subtree, drep, hf_level, &level);
2450
2451         switch(level) {
2452         case 1:
2453                 offset = dissect_ndr_pointer(
2454                         tvb, offset, pinfo, subtree, drep,
2455                         dissect_USER_LEVEL_1, NDR_POINTER_UNIQUE,
2456                         "User level 1", -1);
2457                 break;
2458         default:
2459                 proto_tree_add_text(
2460                         tree, tvb, offset, 0,
2461                         "[Info level %d not decoded]", level);
2462                 break;
2463         }
2464
2465         return offset;
2466 }
2467
2468 /*
2469  * SpoolssOpenPrinterEx
2470  */
2471
2472 static int SpoolssOpenPrinterEx_q(tvbuff_t *tvb, int offset,
2473                                   packet_info *pinfo, proto_tree *tree,
2474                                   char *drep _U_)
2475 {
2476         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2477         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2478         char *name;
2479
2480         /* Parse packet */
2481
2482         offset = dissect_ndr_pointer_cb(
2483                 tvb, offset, pinfo, tree, drep,
2484                 dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
2485                 "Printer name", hf_printername, cb_wstr_postprocess,
2486                 GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
2487
2488         offset = dissect_ndr_pointer(
2489                 tvb, offset, pinfo, tree, drep,
2490                 dissect_PRINTER_DATATYPE, NDR_POINTER_UNIQUE,
2491                 "Printer datatype", -1);
2492
2493         offset = dissect_DEVMODE_CTR(tvb, offset, pinfo, tree, drep);
2494
2495         /* Luckily we can use the string stored in dcv->private_data as it
2496            appears before the printer datatype since we are at the top
2497            level. */
2498
2499         name = (char *)dcv->private_data;
2500
2501         if (name) {
2502                 if (name[0] == '\\' && name[1] == '\\')
2503                         name += 2;
2504
2505                 /* Determine if we are opening a printer or a print server */
2506
2507                 if (strchr(name, '\\')) 
2508                         offset = dissect_nt_access_mask(
2509                                 tvb, offset, pinfo, tree, drep, 
2510                                 hf_access_required,
2511                                 &spoolss_printer_access_mask_info);
2512                 else
2513                         offset = dissect_nt_access_mask(
2514                                 tvb, offset, pinfo, tree, drep, 
2515                                 hf_access_required,
2516                                 &spoolss_printserver_access_mask_info);
2517         } else {
2518
2519                 /* We can't decide what type of object being opened */
2520
2521                 offset = dissect_nt_access_mask(
2522                         tvb, offset, pinfo, tree, drep, hf_access_required,
2523                         NULL);
2524         }
2525
2526         offset = dissect_USER_LEVEL_CTR(tvb, offset, pinfo, tree, drep);
2527
2528         return offset;
2529 }
2530
2531 static int SpoolssOpenPrinterEx_r(tvbuff_t *tvb, int offset,
2532                                   packet_info *pinfo, proto_tree *tree,
2533                                   char *drep _U_)
2534 {
2535         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2536         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2537         e_ctx_hnd policy_hnd;
2538         proto_item *hnd_item;
2539         guint32 status;
2540
2541         /* Parse packet */
2542
2543         offset = dissect_nt_policy_hnd(
2544                 tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, &hnd_item,
2545                 TRUE, FALSE);
2546
2547         offset = dissect_doserror(
2548                 tvb, offset, pinfo, tree, drep, hf_rc, &status);
2549
2550         if (status == 0) {
2551
2552                 /* Associate the returned printer handle with a name */
2553
2554                 if (dcv->private_data) {
2555                         char *pol_name;
2556
2557                         pol_name = g_strdup_printf(
2558                                 "OpenPrinterEx(%s)", 
2559                                 (char *)dcv->private_data);
2560
2561                         dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
2562
2563                         g_free(pol_name);
2564                         g_free(dcv->private_data);
2565                         dcv->private_data = NULL;
2566                 }
2567
2568                 /*
2569                  * If we have a name for the handle, attach it to the item.
2570                  *
2571                  * XXX - we can't just do that above, as this may be called
2572                  * twice (see "dissect_pipe_dcerpc()", which calls the
2573                  * DCE RPC dissector twice), and in the first call we're
2574                  * not building a protocol tree (so we don't have an item
2575                  * to which to attach it) and in the second call
2576                  * "dcv->private_data" is NULL so we don't construct a
2577                  * name.
2578                  */
2579
2580                 if (hnd_item != NULL) {
2581                         char *name;
2582
2583                         if (dcerpc_smb_fetch_pol(&policy_hnd, &name, NULL, NULL,
2584                             pinfo->fd->num) && name != NULL)
2585                                 proto_item_append_text(hnd_item, ": %s", name);
2586                 }
2587         }
2588
2589         return offset;
2590 }
2591
2592 static const value_string printer_notify_option_data_vals[] = {
2593         { PRINTER_NOTIFY_SERVER_NAME, "Server name" },
2594         { PRINTER_NOTIFY_PRINTER_NAME, "Printer name" },
2595         { PRINTER_NOTIFY_SHARE_NAME, "Share name" },
2596         { PRINTER_NOTIFY_PORT_NAME, "Port name" },
2597         { PRINTER_NOTIFY_DRIVER_NAME, "Driver name" },
2598         { PRINTER_NOTIFY_COMMENT, "Comment" },
2599         { PRINTER_NOTIFY_LOCATION, "Location" },
2600         { PRINTER_NOTIFY_DEVMODE, "Devmode" },
2601         { PRINTER_NOTIFY_SEPFILE, "Sepfile" },
2602         { PRINTER_NOTIFY_PRINT_PROCESSOR, "Print processor" },
2603         { PRINTER_NOTIFY_PARAMETERS, "Parameters" },
2604         { PRINTER_NOTIFY_DATATYPE, "Datatype" },
2605         { PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "Security descriptor" },
2606         { PRINTER_NOTIFY_ATTRIBUTES, "Attributes" },
2607         { PRINTER_NOTIFY_PRIORITY, "Priority" },
2608         { PRINTER_NOTIFY_DEFAULT_PRIORITY, "Default priority" },
2609         { PRINTER_NOTIFY_START_TIME, "Start time" },
2610         { PRINTER_NOTIFY_UNTIL_TIME, "Until time" },
2611         { PRINTER_NOTIFY_STATUS, "Status" },
2612         { PRINTER_NOTIFY_STATUS_STRING, "Status string" },
2613         { PRINTER_NOTIFY_CJOBS, "Cjobs" },
2614         { PRINTER_NOTIFY_AVERAGE_PPM, "Average PPM" },
2615         { PRINTER_NOTIFY_TOTAL_PAGES, "Total pages" },
2616         { PRINTER_NOTIFY_PAGES_PRINTED, "Pages printed" },
2617         { PRINTER_NOTIFY_TOTAL_BYTES, "Total bytes" },
2618         { PRINTER_NOTIFY_BYTES_PRINTED, "Bytes printed" },
2619         { 0, NULL}
2620 };
2621
2622 static const value_string job_notify_option_data_vals[] = {
2623         { JOB_NOTIFY_PRINTER_NAME, "Printer name" },
2624         { JOB_NOTIFY_MACHINE_NAME, "Machine name" },
2625         { JOB_NOTIFY_PORT_NAME, "Port name" },
2626         { JOB_NOTIFY_USER_NAME, "User name" },
2627         { JOB_NOTIFY_NOTIFY_NAME, "Notify name" },
2628         { JOB_NOTIFY_DATATYPE, "Data type" },
2629         { JOB_NOTIFY_PRINT_PROCESSOR, "Print processor" },
2630         { JOB_NOTIFY_PARAMETERS, "Parameters" },
2631         { JOB_NOTIFY_DRIVER_NAME, "Driver name" },
2632         { JOB_NOTIFY_DEVMODE, "Devmode" },
2633         { JOB_NOTIFY_STATUS, "Status" },
2634         { JOB_NOTIFY_STATUS_STRING, "Status string" },
2635         { JOB_NOTIFY_SECURITY_DESCRIPTOR, "Security descriptor" },
2636         { JOB_NOTIFY_DOCUMENT, "Document" },
2637         { JOB_NOTIFY_PRIORITY, "Priority" },
2638         { JOB_NOTIFY_POSITION, "Position" },
2639         { JOB_NOTIFY_SUBMITTED, "Submitted" },
2640         { JOB_NOTIFY_START_TIME, "Start time" },
2641         { JOB_NOTIFY_UNTIL_TIME, "Until time" },
2642         { JOB_NOTIFY_TIME, "Time" },
2643         { JOB_NOTIFY_TOTAL_PAGES, "Total pages" },
2644         { JOB_NOTIFY_PAGES_PRINTED, "Pages printed" },
2645         { JOB_NOTIFY_TOTAL_BYTES, "Total bytes" },
2646         { JOB_NOTIFY_BYTES_PRINTED, "Bytes printed" },
2647         { 0, NULL}
2648 };
2649
2650 static int
2651 dissect_notify_field(tvbuff_t *tvb, int offset, packet_info *pinfo,
2652                      proto_tree *tree, char *drep, guint16 type,
2653                      guint16 *data)
2654 {
2655         guint16 field;
2656         char *str;
2657
2658         offset = dissect_ndr_uint16(
2659                 tvb, offset, pinfo, NULL, drep,
2660                 hf_notify_field, &field);
2661
2662         switch(type) {
2663         case PRINTER_NOTIFY_TYPE:
2664                 str = val_to_str(field, printer_notify_option_data_vals,
2665                                  "Unknown");
2666                 break;
2667         case JOB_NOTIFY_TYPE:
2668                 str = val_to_str(field, job_notify_option_data_vals,
2669                                  "Unknown");
2670                 break;
2671         default:
2672                 str = "Unknown notify type";
2673                 break;
2674         }
2675
2676         proto_tree_add_text(tree, tvb, offset - 2, 2,
2677                             "Field: %s (%d)", str, field);
2678
2679         if (data)
2680                 *data = field;
2681
2682         return offset;
2683 }
2684
2685 static int
2686 dissect_NOTIFY_OPTION_DATA(tvbuff_t *tvb, int offset, packet_info *pinfo,
2687                            proto_tree *tree, char *drep)
2688 {
2689         dcerpc_info *di = pinfo->private_data;
2690         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2691         guint32 count, i;
2692         guint16 type;
2693
2694         if (di->conformant_run)
2695                 return offset;
2696
2697         offset = dissect_ndr_uint32(
2698                 tvb, offset, pinfo, tree, drep,
2699                 hf_notify_option_data_count, &count);
2700
2701         type = GPOINTER_TO_INT(dcv->private_data);
2702
2703         for (i = 0; i < count; i++)
2704                 offset = dissect_notify_field(
2705                         tvb, offset, pinfo, tree, drep, type, NULL);
2706
2707         return offset;
2708 }
2709
2710 static const value_string printer_notify_types[] =
2711 {
2712         { PRINTER_NOTIFY_TYPE, "Printer notify" },
2713         { JOB_NOTIFY_TYPE, "Job notify" },
2714         { 0, NULL }
2715 };
2716
2717 static char *notify_plural(int count)
2718 {
2719         if (count == 1)
2720                 return "notification";
2721
2722         return "notifies";
2723 }
2724         
2725 static gint ett_NOTIFY_OPTION = -1;
2726
2727 static int
2728 dissect_NOTIFY_OPTION(tvbuff_t *tvb, int offset, packet_info *pinfo,
2729                       proto_tree *tree, char *drep)
2730 {
2731         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2732         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2733         proto_item *item;
2734         proto_tree *subtree;
2735         guint16 type;
2736         guint32 count;
2737
2738         item = proto_tree_add_text(tree, tvb, offset, 0, "Notify Option");
2739
2740         subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION);
2741
2742         offset = dissect_ndr_uint16(tvb, offset, pinfo, subtree, drep,
2743                                     hf_notify_option_type, &type);
2744
2745         proto_item_append_text(
2746                 item, ": %s", val_to_str(type, printer_notify_types, 
2747                                          "Unknown (%d)"));
2748
2749         offset = dissect_ndr_uint16(tvb, offset, pinfo, subtree, drep,
2750                                     hf_notify_option_reserved1, NULL);
2751
2752         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
2753                                     hf_notify_option_reserved2, NULL);
2754
2755         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
2756                                     hf_notify_option_reserved3, NULL);
2757
2758         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
2759                                     hf_notify_option_count, &count);
2760
2761         proto_item_append_text(
2762                 item, ", %d %s", count, notify_plural(count));
2763
2764         dcv->private_data = GINT_TO_POINTER((int)type);
2765
2766         offset = dissect_ndr_pointer(
2767                 tvb, offset, pinfo, subtree, drep,
2768                 dissect_NOTIFY_OPTION_DATA, NDR_POINTER_UNIQUE,
2769                 "Notify Option Data", -1);
2770
2771         return offset;
2772 }
2773
2774 static int
2775 dissect_NOTIFY_OPTIONS_ARRAY(tvbuff_t *tvb, int offset,
2776                              packet_info *pinfo, proto_tree *tree,
2777                              char *drep)
2778 {
2779         /* Why is a check for di->conformant_run not required here? */
2780
2781         offset = dissect_ndr_ucarray(
2782                 tvb, offset, pinfo, tree, drep, dissect_NOTIFY_OPTION);
2783
2784         return offset;
2785 }
2786
2787 static gint ett_notify_options_flags = -1;
2788
2789 static const true_false_string tfs_notify_options_flags_refresh = {
2790         "Data for all monitored fields is present",
2791         "Data for all monitored fields not present"
2792 };
2793
2794 static int
2795 dissect_notify_options_flags(tvbuff_t *tvb, int offset, packet_info *pinfo,
2796                              proto_tree *tree, char *drep)
2797 {
2798         proto_item *item;
2799         proto_tree *subtree;
2800         guint32 flags;
2801
2802         offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
2803                                     hf_notify_options_flags,
2804                                     &flags);
2805
2806         item = proto_tree_add_text(tree, tvb, offset - 4, 4,
2807                                    "Flags: 0x%08x", flags);
2808
2809         subtree = proto_item_add_subtree(item, ett_notify_options_flags);
2810
2811         proto_tree_add_boolean(
2812                 subtree, hf_notify_options_flags_refresh,
2813                 tvb, offset, 4, flags);
2814
2815         return offset;
2816 }
2817
2818 static int
2819 dissect_NOTIFY_OPTIONS_ARRAY_CTR(tvbuff_t *tvb, int offset,
2820                                  packet_info *pinfo, proto_tree *tree,
2821                                  char *drep)
2822 {
2823         dcerpc_info *di = pinfo->private_data;
2824
2825         if (di->conformant_run)
2826                 return offset;
2827
2828         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
2829                                     hf_notify_options_version, NULL);
2830
2831         offset = dissect_notify_options_flags(tvb, offset, pinfo, tree, drep);
2832
2833         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
2834                                     hf_notify_options_count, NULL);
2835
2836         offset = dissect_ndr_pointer(
2837                 tvb, offset, pinfo, tree, drep,
2838                 dissect_NOTIFY_OPTIONS_ARRAY, NDR_POINTER_UNIQUE,
2839                 "Notify Options Array", -1);
2840
2841         return offset;
2842 }
2843
2844 /*
2845  * SpoolssRFFPCNEX
2846  */
2847
2848 static gint ett_rffpcnex_flags = -1;
2849
2850 static int hf_rffpcnex_flags = -1;
2851 static int hf_rffpcnex_options = -1;
2852
2853 static int hf_rffpcnex_flags_add_printer = -1;
2854 static int hf_rffpcnex_flags_set_printer = -1;
2855 static int hf_rffpcnex_flags_delete_printer = -1;
2856 static int hf_rffpcnex_flags_failed_printer_connection = -1;
2857
2858 static const true_false_string tfs_rffpcnex_flags_add_printer = {
2859         "Notify on add printer",
2860         "Don't notify on add printer"
2861 };
2862
2863 static const true_false_string tfs_rffpcnex_flags_set_printer = {
2864         "Notify on set printer",
2865         "Don't notify on set printer"
2866 };
2867
2868 static const true_false_string tfs_rffpcnex_flags_delete_printer = {
2869         "Notify on delete printer",
2870         "Don't notify on delete printer"
2871 };
2872
2873 static const true_false_string tfs_rffpcnex_flags_failed_connection_printer = {
2874         "Notify on failed printer connection",
2875         "Don't notify on failed printer connection"
2876 };
2877
2878 static int hf_rffpcnex_flags_add_job = -1;
2879 static int hf_rffpcnex_flags_set_job = -1;
2880 static int hf_rffpcnex_flags_delete_job = -1;
2881 static int hf_rffpcnex_flags_write_job = -1;
2882
2883 static const true_false_string tfs_rffpcnex_flags_add_job = {
2884         "Notify on add job",
2885         "Don't notify on add job"
2886 };
2887
2888 static const true_false_string tfs_rffpcnex_flags_set_job = {
2889         "Notify on set job",
2890         "Don't notify on set job"
2891 };
2892
2893 static const true_false_string tfs_rffpcnex_flags_delete_job = {
2894         "Notify on delete job",
2895         "Don't notify on delete job"
2896 };
2897
2898 static const true_false_string tfs_rffpcnex_flags_write_job = {
2899         "Notify on writejob",
2900         "Don't notify on write job"
2901 };
2902
2903 static int hf_rffpcnex_flags_add_form = -1;
2904 static int hf_rffpcnex_flags_set_form = -1;
2905 static int hf_rffpcnex_flags_delete_form = -1;
2906
2907 static const true_false_string tfs_rffpcnex_flags_add_form = {
2908         "Notify on add form",
2909         "Don't notify on add form"
2910 };
2911
2912 static const true_false_string tfs_rffpcnex_flags_set_form = {
2913         "Notify on set form",
2914         "Don't notify on set form"
2915 };
2916
2917 static const true_false_string tfs_rffpcnex_flags_delete_form = {
2918         "Notify on delete form",
2919         "Don't notify on delete form"
2920 };
2921
2922 static int hf_rffpcnex_flags_add_port = -1;
2923 static int hf_rffpcnex_flags_configure_port = -1;
2924 static int hf_rffpcnex_flags_delete_port = -1;
2925
2926 static const true_false_string tfs_rffpcnex_flags_add_port = {
2927         "Notify on add port",
2928         "Don't notify on add port"
2929 };
2930
2931 static const true_false_string tfs_rffpcnex_flags_configure_port = {
2932         "Notify on configure port",
2933         "Don't notify on configure port"
2934 };
2935
2936 static const true_false_string tfs_rffpcnex_flags_delete_port = {
2937         "Notify on delete port",
2938         "Don't notify on delete port"
2939 };
2940
2941 static int hf_rffpcnex_flags_add_print_processor = -1;
2942 static int hf_rffpcnex_flags_delete_print_processor = -1;
2943
2944 static const true_false_string tfs_rffpcnex_flags_add_print_processor = {
2945         "Notify on add driver",
2946         "Don't notify on add driver"
2947 };
2948
2949 static const true_false_string tfs_rffpcnex_flags_delete_print_processor = {
2950         "Notify on add driver",
2951         "Don't notify on add driver"
2952 };
2953
2954 static int hf_rffpcnex_flags_add_driver = -1;
2955 static int hf_rffpcnex_flags_set_driver = -1;
2956 static int hf_rffpcnex_flags_delete_driver = -1;
2957
2958 static const true_false_string tfs_rffpcnex_flags_add_driver = {
2959         "Notify on add driver",
2960         "Don't notify on add driver"
2961 };
2962
2963 static const true_false_string tfs_rffpcnex_flags_set_driver = {
2964         "Notify on set driver",
2965         "Don't notify on set driver"
2966 };
2967
2968 static const true_false_string tfs_rffpcnex_flags_delete_driver = {
2969         "Notify on delete driver",
2970         "Don't notify on delete driver"
2971 };
2972
2973 static int hf_rffpcnex_flags_timeout = -1;
2974
2975 static const true_false_string tfs_rffpcnex_flags_timeout = {
2976         "Notify on timeout",
2977         "Don't notify on timeout"
2978 };
2979
2980 static int SpoolssRFFPCNEX_q(tvbuff_t *tvb, int offset,
2981                              packet_info *pinfo, proto_tree *tree,
2982                              char *drep _U_)
2983 {
2984         guint32 flags;
2985         proto_item *flags_item;
2986         proto_tree *flags_subtree;
2987
2988         /* Parse packet */
2989
2990         offset = dissect_nt_policy_hnd(
2991                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
2992                 FALSE, FALSE);
2993
2994         offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
2995                                     hf_rffpcnex_flags, &flags);
2996
2997         flags_item = proto_tree_add_text(tree, tvb, offset - 4, 4,
2998                                          "Flags: 0x%08x", flags);
2999
3000         flags_subtree = proto_item_add_subtree(flags_item, ett_rffpcnex_flags);
3001
3002         proto_tree_add_boolean(
3003                 flags_subtree, hf_rffpcnex_flags_timeout, tvb,
3004                 offset - 4, 4, flags);
3005
3006         proto_tree_add_boolean(
3007                 flags_subtree, hf_rffpcnex_flags_delete_driver, tvb,
3008                 offset - 4, 4, flags);
3009
3010         proto_tree_add_boolean(
3011                 flags_subtree, hf_rffpcnex_flags_set_driver, tvb,
3012                 offset - 4, 4, flags);
3013
3014         proto_tree_add_boolean(
3015                 flags_subtree, hf_rffpcnex_flags_add_driver, tvb,
3016                 offset - 4, 4, flags);
3017
3018         proto_tree_add_boolean(
3019                 flags_subtree,
3020                 hf_rffpcnex_flags_delete_print_processor, tvb,
3021                 offset - 4, 4, flags);
3022
3023         proto_tree_add_boolean(
3024                 flags_subtree, hf_rffpcnex_flags_add_print_processor,
3025                 tvb, offset - 4, 4, flags);
3026
3027         proto_tree_add_boolean(
3028                 flags_subtree, hf_rffpcnex_flags_delete_port, tvb,
3029                 offset - 4, 4, flags);
3030
3031         proto_tree_add_boolean(
3032                 flags_subtree, hf_rffpcnex_flags_configure_port, tvb,
3033                 offset - 4, 4, flags);
3034
3035         proto_tree_add_boolean(
3036                 flags_subtree, hf_rffpcnex_flags_add_port, tvb,
3037                 offset - 4, 4, flags);
3038
3039         proto_tree_add_boolean(
3040                 flags_subtree, hf_rffpcnex_flags_delete_form, tvb,
3041                 offset - 4, 4, flags);
3042
3043         proto_tree_add_boolean(
3044                 flags_subtree, hf_rffpcnex_flags_set_form, tvb,
3045                 offset - 4, 4, flags);
3046
3047         proto_tree_add_boolean(
3048                 flags_subtree, hf_rffpcnex_flags_add_form, tvb,
3049                 offset - 4, 4, flags);
3050
3051         proto_tree_add_boolean(
3052                 flags_subtree, hf_rffpcnex_flags_write_job, tvb,
3053                 offset - 4, 4, flags);
3054
3055         proto_tree_add_boolean(
3056                 flags_subtree, hf_rffpcnex_flags_delete_job, tvb,
3057                 offset - 4, 4, flags);
3058
3059         proto_tree_add_boolean(
3060                 flags_subtree, hf_rffpcnex_flags_set_job, tvb,
3061                 offset - 4, 4, flags);
3062
3063         proto_tree_add_boolean(
3064                 flags_subtree, hf_rffpcnex_flags_add_job, tvb,
3065                 offset - 4, 4, flags);
3066
3067         proto_tree_add_boolean(
3068                 flags_subtree,
3069                 hf_rffpcnex_flags_failed_printer_connection, tvb,
3070                 offset - 4, 4, flags);
3071
3072         proto_tree_add_boolean(
3073                 flags_subtree, hf_rffpcnex_flags_delete_printer, tvb,
3074                 offset - 4, 4, flags);
3075
3076         proto_tree_add_boolean(
3077                 flags_subtree, hf_rffpcnex_flags_set_printer, tvb,
3078                 offset - 4, 4, flags);
3079
3080         proto_tree_add_boolean(
3081                 flags_subtree, hf_rffpcnex_flags_add_printer, tvb,
3082                 offset - 4, 4, flags);
3083
3084         if (flags & SPOOLSS_PRINTER_CHANGE_PRINTER)
3085                 proto_item_append_text(flags_item, ", change printer");
3086
3087         if (flags & SPOOLSS_PRINTER_CHANGE_JOB)
3088                 proto_item_append_text(flags_item, ", change job");
3089
3090         if (flags & SPOOLSS_PRINTER_CHANGE_FORM)
3091                 proto_item_append_text(flags_item, ", change form");
3092
3093         if (flags & SPOOLSS_PRINTER_CHANGE_PORT)
3094                 proto_item_append_text(flags_item, ", change port");
3095
3096         if (flags & SPOOLSS_PRINTER_CHANGE_PRINTER_DRIVER)
3097                 proto_item_append_text(flags_item, ", change printer driver");
3098
3099         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
3100                                     hf_rffpcnex_options, NULL);
3101
3102         offset = dissect_ndr_str_pointer_item(
3103                 tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
3104                 "Server", hf_servername, 0);
3105
3106         offset = dissect_ndr_uint32(
3107                 tvb, offset, pinfo, tree, drep, hf_printerlocal, NULL);
3108
3109         offset = dissect_ndr_pointer(
3110                 tvb, offset, pinfo, tree, drep,
3111                 dissect_NOTIFY_OPTIONS_ARRAY_CTR, NDR_POINTER_UNIQUE,
3112                 "Notify Options Container", -1);
3113
3114         return offset;
3115 }
3116
3117 static int SpoolssRFFPCNEX_r(tvbuff_t *tvb, int offset,
3118                              packet_info *pinfo, proto_tree *tree,
3119                              char *drep _U_)
3120 {
3121         /* Parse packet */
3122
3123         offset = dissect_doserror(
3124                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
3125
3126         return offset;
3127 }
3128
3129 /*
3130  * SpoolssReplyOpenPrinter
3131  */
3132
3133 static int SpoolssReplyOpenPrinter_q(tvbuff_t *tvb, int offset,
3134                                      packet_info *pinfo, proto_tree *tree,
3135                                      char *drep _U_)
3136 {
3137         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
3138         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
3139         guint32 printerlocal;
3140         char *name = NULL;
3141
3142         /* Parse packet */
3143
3144         offset = dissect_ndr_cvstring(
3145                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
3146                 hf_servername, TRUE, &name);
3147
3148         if (check_col(pinfo->cinfo, COL_INFO) && name)
3149                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", name);
3150
3151         if (!dcv->private_data && name)
3152                 dcv->private_data = name;
3153         else
3154                 g_free(name);
3155
3156         offset = dissect_ndr_uint32(
3157                 tvb, offset, pinfo, tree, drep, hf_printerlocal, 
3158                 &printerlocal);
3159
3160         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
3161                                     hf_printerdata_type, NULL);
3162
3163         offset = dissect_ndr_uint32(
3164                 tvb, offset, pinfo, tree, drep, hf_replyopenprinter_unk0, 
3165                 NULL);
3166
3167         offset = dissect_ndr_uint32(
3168                 tvb, offset, pinfo, tree, drep, hf_replyopenprinter_unk1, 
3169                 NULL);
3170
3171         return offset;
3172 }
3173
3174 static int SpoolssReplyOpenPrinter_r(tvbuff_t *tvb, int offset,
3175                                      packet_info *pinfo, proto_tree *tree,
3176                                      char *drep _U_)
3177 {
3178         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
3179         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
3180         e_ctx_hnd policy_hnd;
3181         proto_item *hnd_item;
3182         guint32 status;
3183
3184         /* Parse packet */
3185
3186         offset = dissect_nt_policy_hnd(
3187                 tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, &hnd_item,
3188                 TRUE, FALSE);
3189         
3190         offset = dissect_doserror(
3191                 tvb, offset, pinfo, tree, drep, hf_rc, &status);
3192
3193         if (status == 0) {
3194
3195                 /* Associate the returned printer handle with a name */
3196
3197                 if (dcv->private_data) {
3198                         char *pol_name;
3199
3200                         pol_name = g_strdup_printf(
3201                                 "OpenPrinter(%s)",
3202                                 (char *)dcv->private_data);
3203
3204                         dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
3205
3206                         g_free(pol_name);
3207                         g_free(dcv->private_data);
3208                         dcv->private_data = NULL;
3209                 }
3210
3211                 /*
3212                  * If we have a name for the handle, attach it to the item.
3213                  *
3214                  * XXX - we can't just do that above, as this may be called
3215                  * twice (see "dissect_pipe_dcerpc()", which calls the
3216                  * DCE RPC dissector twice), and in the first call we're
3217                  * not building a protocol tree (so we don't have an item
3218                  * to which to attach it) and in the second call
3219                  * "dcv->private_data" is NULL so we don't construct a
3220                  * name.
3221                  */
3222
3223                 if (hnd_item != NULL) {
3224                         char *name;
3225
3226                         if (dcerpc_smb_fetch_pol(&policy_hnd, &name, NULL, NULL,
3227                             pinfo->fd->num) && name != NULL)
3228                                 proto_item_append_text(hnd_item, ": %s", name);
3229                 }
3230         }
3231
3232         return offset;
3233 }
3234
3235 /*
3236  * SpoolssGetPrinter
3237  */
3238
3239
3240
3241 static int SpoolssGetPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
3242                                proto_tree *tree, char *drep _U_)
3243 {
3244         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
3245         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
3246         guint32 level;
3247
3248         /* Parse packet */
3249
3250         offset = dissect_nt_policy_hnd(
3251                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
3252                 FALSE, FALSE);
3253
3254         offset = dissect_ndr_uint32(
3255                 tvb, offset, pinfo, tree, drep, hf_level, &level);
3256
3257         if (check_col(pinfo->cinfo, COL_INFO))
3258                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
3259
3260         dcv->private_data = (void *)level;
3261
3262         offset = dissect_spoolss_buffer(
3263                 tvb, offset, pinfo, tree, drep, NULL);
3264
3265         offset = dissect_ndr_uint32(
3266                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
3267
3268         return offset;
3269 }
3270
3271 static gint ett_PRINTER_INFO = -1;
3272
3273 static int SpoolssGetPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
3274                                 proto_tree *tree, char *drep _U_)
3275 {
3276         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
3277         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
3278         BUFFER buffer;
3279         gint16 level = (guint32)dcv->private_data;
3280         proto_item *item;
3281         proto_tree *subtree = NULL;
3282
3283         if (check_col(pinfo->cinfo, COL_INFO))
3284                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
3285
3286         /* Parse packet */
3287
3288         offset = dissect_spoolss_buffer(
3289                 tvb, offset, pinfo, tree, drep, &buffer);
3290
3291         if (buffer.tvb) {
3292                 switch(level) {
3293                 case 0:
3294                 case 1:
3295                 case 2:
3296                 case 3:
3297                 case 7:
3298                         item = proto_tree_add_text(
3299                                 buffer.tree, buffer.tvb, 0, -1,
3300                                 "Print info level %d", level);
3301                         
3302                         subtree = proto_item_add_subtree(
3303                                 item, ett_PRINTER_INFO);
3304                         break;
3305                 }
3306
3307                 switch(level) {
3308                 case 0:
3309                         dissect_PRINTER_INFO_0(
3310                                 buffer.tvb, 0, pinfo, subtree, drep);
3311                         break;
3312                 case 1:
3313                         dissect_PRINTER_INFO_1(
3314                                 buffer.tvb, 0, pinfo, subtree, drep);
3315                         break;
3316                 case 2:
3317                         dissect_PRINTER_INFO_2(
3318                                 buffer.tvb, 0, pinfo, subtree, drep);
3319                         break;
3320                 case 3:
3321                         dissect_PRINTER_INFO_3(
3322                                 buffer.tvb, 0, pinfo, subtree, drep);
3323                         break;
3324                 case 7:
3325                         dissect_PRINTER_INFO_7(
3326                                 buffer.tvb, 0, pinfo, subtree, drep);
3327                         break;
3328                 default:
3329                         proto_tree_add_text(
3330                                 buffer.tree, buffer.tvb, 0, -1,
3331                                 "[Unknown printer info level %d]", level);
3332                         break;
3333                 }
3334         }
3335
3336         offset = dissect_ndr_uint32(
3337                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
3338
3339         offset = dissect_doserror(
3340                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
3341
3342         return offset;
3343 }
3344
3345 /*
3346  * SEC_DESC_BUF
3347  */
3348
3349 static gint ett_SEC_DESC_BUF = -1;
3350
3351 static int hf_secdescbuf_maxlen = -1;
3352 static int hf_secdescbuf_undoc = -1;
3353 static int hf_secdescbuf_len = -1;
3354
3355 static int
3356 dissect_SEC_DESC_BUF(tvbuff_t *tvb, int offset, packet_info *pinfo,
3357                      proto_tree *tree, char *drep)
3358 {
3359         proto_item *item;
3360         proto_tree *subtree;
3361         guint32 len;
3362
3363         /* XXX: I think this is really a array of bytes which can be 
3364            dissected using dissect_ndr_cvstring().  The dissected data 
3365            can be passed to dissect_nt_sec_desc().  The problem is that
3366            dissect_nt_cvstring() passes back a char * where it really
3367            should pass back a tvb. */
3368
3369         item = proto_tree_add_text(
3370                 tree, tvb, offset, 0, "Security descriptor buffer");
3371
3372         subtree = proto_item_add_subtree(item, ett_SEC_DESC_BUF);
3373
3374         offset = dissect_ndr_uint32(
3375                 tvb, offset, pinfo, subtree, drep,
3376                 hf_secdescbuf_maxlen, NULL);
3377
3378         offset = dissect_ndr_uint32(
3379                 tvb, offset, pinfo, subtree, drep,
3380                 hf_secdescbuf_undoc, NULL);
3381
3382         offset = dissect_ndr_uint32(
3383                 tvb, offset, pinfo, subtree, drep,
3384                 hf_secdescbuf_len, &len);
3385         
3386         dissect_nt_sec_desc(
3387                 tvb, offset, pinfo, subtree, drep, len, 
3388                 &spoolss_printer_access_mask_info);
3389
3390         offset += len;  
3391
3392         return offset;
3393 }
3394
3395 /*
3396  * SPOOL_PRINTER_INFO_LEVEL
3397  */
3398
3399 static gint ett_SPOOL_PRINTER_INFO_LEVEL = -1;
3400
3401 /* spool printer info */
3402
3403 static int hf_spool_printer_info_devmode_ptr = -1;
3404 static int hf_spool_printer_info_secdesc_ptr = -1;
3405
3406 static int
3407 dissect_SPOOL_PRINTER_INFO(tvbuff_t *tvb, int offset, packet_info *pinfo,
3408                            proto_tree *tree, char *drep)
3409 {
3410         proto_item *item;
3411         proto_tree *subtree;
3412         guint32 level;
3413
3414         item = proto_tree_add_text(
3415                 tree, tvb, offset, 0, "Spool printer info level");
3416
3417         subtree = proto_item_add_subtree(item, ett_SPOOL_PRINTER_INFO_LEVEL);
3418
3419         offset = dissect_ndr_uint32(
3420                 tvb, offset, pinfo, subtree, drep, hf_level, &level);
3421
3422         switch(level) {
3423         case 3: {
3424                 guint32 devmode_ptr, secdesc_ptr;
3425
3426                 /* I can't seem to get this working with the correct
3427                    dissect_ndr_pointer() function so let's cheat and
3428                    dissect the pointers by hand. )-: */
3429
3430                 offset = dissect_ndr_uint32(
3431                         tvb, offset, pinfo, subtree, drep,
3432                         hf_spool_printer_info_devmode_ptr, 
3433                         &devmode_ptr);
3434
3435                 offset = dissect_ndr_uint32(
3436                         tvb, offset, pinfo, subtree, drep,
3437                         hf_spool_printer_info_secdesc_ptr, 
3438                         &secdesc_ptr);
3439
3440                 if (devmode_ptr)
3441                         offset = dissect_DEVMODE_CTR(
3442                                 tvb, offset, pinfo, subtree, drep);
3443
3444                 if (secdesc_ptr)
3445                         offset = dissect_SEC_DESC_BUF(
3446                                 tvb, offset, pinfo, subtree, drep);
3447
3448         break;
3449         }               
3450         case 2:
3451         default:
3452                 proto_tree_add_text(
3453                         subtree, tvb, offset, 0,
3454                         "[Unknown spool printer info level %d]", level);
3455                 break;
3456         }
3457
3458         return offset;
3459 }
3460
3461 /*
3462  * SpoolssSetPrinter
3463  */
3464
3465 static int hf_setprinter_cmd = -1;
3466
3467 static const value_string setprinter_cmd_vals[] = {
3468         { SPOOLSS_PRINTER_CONTROL_UNPAUSE, "Unpause" },
3469         { SPOOLSS_PRINTER_CONTROL_PAUSE, "Pause" },
3470         { SPOOLSS_PRINTER_CONTROL_RESUME, "Resume" },
3471         { SPOOLSS_PRINTER_CONTROL_PURGE, "Purge" },
3472         { SPOOLSS_PRINTER_CONTROL_SET_STATUS, "Set status" },
3473         { 0, NULL }
3474 };
3475
3476 static int SpoolssSetPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
3477                                proto_tree *tree, char *drep _U_)
3478 {
3479         guint32 level;
3480
3481         /* Parse packet */
3482
3483         offset = dissect_nt_policy_hnd(
3484                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
3485                 FALSE, FALSE);
3486
3487         offset = dissect_ndr_uint32(
3488                 tvb, offset, pinfo, tree, drep, hf_level, &level);
3489
3490         if (check_col(pinfo->cinfo, COL_INFO))
3491                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
3492
3493         offset = dissect_SPOOL_PRINTER_INFO(
3494                 tvb, offset, pinfo, tree, drep);
3495         
3496         offset = dissect_ndr_uint32(
3497                 tvb, offset, pinfo, tree, drep,
3498                 hf_setprinter_cmd, NULL);
3499
3500         return offset;
3501 }
3502
3503 static int SpoolssSetPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
3504                                 proto_tree *tree, char *drep _U_)
3505 {
3506         /* Parse packet */
3507
3508         offset = dissect_doserror(
3509                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
3510
3511         return offset;
3512 }
3513
3514 /*
3515  * FORM_REL
3516  */
3517
3518 static const value_string form_type_vals[] =
3519 {
3520         { SPOOLSS_FORM_USER, "User" },
3521         { SPOOLSS_FORM_BUILTIN, "Builtin" },
3522         { SPOOLSS_FORM_PRINTER, "Printer" },
3523         { 0, NULL }
3524 };
3525
3526 static gint ett_FORM_REL = -1;
3527
3528 static int dissect_FORM_REL(tvbuff_t *tvb, int offset, packet_info *pinfo,
3529                             proto_tree *tree, char *drep, int struct_start)
3530 {
3531         proto_item *item;
3532         proto_tree *subtree;
3533         guint32 flags;
3534         int item_start = offset;
3535         char *name = NULL;
3536
3537         item = proto_tree_add_text(tree, tvb, offset, 0, "Form");
3538
3539         subtree = proto_item_add_subtree(item, ett_FORM_REL);
3540
3541         offset = dissect_ndr_uint32(
3542                 tvb, offset, pinfo, subtree, drep, hf_form_flags, &flags);
3543
3544         offset = dissect_spoolss_relstr(
3545                 tvb, offset, pinfo, subtree, drep, hf_form_name,
3546                 struct_start, &name);
3547
3548         if (name) {
3549                 proto_item_append_text(item, ": %s", name);
3550                 g_free(name);
3551         }
3552
3553         offset = dissect_ndr_uint32(
3554                 tvb, offset, pinfo, subtree, drep,
3555                 hf_form_width, NULL);
3556
3557         offset = dissect_ndr_uint32(
3558                 tvb, offset, pinfo, subtree, drep,
3559                 hf_form_height, NULL);
3560
3561         offset = dissect_ndr_uint32(
3562                 tvb, offset, pinfo, subtree, drep,
3563                 hf_form_left_margin, NULL);
3564
3565         offset = dissect_ndr_uint32(
3566                 tvb, offset, pinfo, subtree, drep,
3567                 hf_form_top_margin, NULL);
3568
3569         offset = dissect_ndr_uint32(
3570                 tvb, offset, pinfo, subtree, drep,
3571                 hf_form_horiz_len, NULL);
3572
3573         offset = dissect_ndr_uint32(
3574                 tvb, offset, pinfo, subtree, drep,
3575                 hf_form_vert_len, NULL);
3576
3577         proto_item_set_len(item, offset - item_start);
3578
3579         return offset;
3580 }
3581
3582 /*
3583  * SpoolssEnumForms
3584  */
3585
3586 static int SpoolssEnumForms_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
3587                               proto_tree *tree, char *drep _U_)
3588 {
3589         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
3590         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
3591         guint32 level;
3592
3593         proto_tree_add_uint_hidden(
3594                 tree, hf_form, tvb, offset, 0, 1);
3595
3596         /* Parse packet */
3597
3598         offset = dissect_nt_policy_hnd(
3599                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
3600                 FALSE, FALSE);
3601
3602         offset = dissect_ndr_uint32(
3603                 tvb, offset, pinfo, tree, drep, hf_level, &level);
3604
3605         dcv->private_data = (void *)level;
3606
3607         if (check_col(pinfo->cinfo, COL_INFO))
3608                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
3609
3610         offset = dissect_spoolss_buffer(
3611                 tvb, offset, pinfo, tree, drep, NULL);
3612
3613         offset = dissect_ndr_uint32(
3614                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
3615
3616         return offset;
3617 }
3618
3619 static int SpoolssEnumForms_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
3620                               proto_tree *tree, char *drep _U_)
3621 {
3622         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
3623         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
3624         BUFFER buffer;
3625         guint32 level = (guint32)dcv->private_data, i, count;
3626         int buffer_offset;
3627
3628         proto_tree_add_uint_hidden(
3629                 tree, hf_form, tvb, offset, 0, 1);
3630
3631         /* Parse packet */
3632
3633         offset = dissect_spoolss_buffer(
3634                 tvb, offset, pinfo, tree, drep, &buffer);
3635
3636         offset = dissect_ndr_uint32(
3637                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
3638
3639         if (check_col(pinfo->cinfo, COL_INFO))
3640                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
3641
3642         offset = dissect_ndr_uint32(
3643                 tvb, offset, pinfo, tree, drep, hf_enumforms_num, &count);
3644
3645         /* Unfortunately this array isn't in NDR format so we can't
3646            use prs_array().  The other weird thing is the
3647            struct_start being inside the loop rather than outside.
3648            Very strange. */
3649
3650         buffer_offset = 0;
3651
3652         for (i = 0; i < count; i++) {
3653                 int struct_start = buffer_offset;
3654
3655                 buffer_offset = dissect_FORM_REL(
3656                         buffer.tvb, buffer_offset, pinfo, buffer.tree, drep,
3657                         struct_start);
3658         }
3659
3660         offset = dissect_doserror(
3661                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
3662
3663         return offset;
3664 }
3665
3666 /*
3667  * SpoolssDeletePrinter
3668  */
3669
3670 static int SpoolssDeletePrinter_q(tvbuff_t *tvb, int offset,
3671                                   packet_info *pinfo, proto_tree *tree,
3672                                   char *drep _U_)
3673 {
3674         /* Parse packet */
3675
3676         offset = dissect_nt_policy_hnd(
3677                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
3678                 FALSE, FALSE);
3679
3680         return offset;
3681 }
3682
3683 static int SpoolssDeletePrinter_r(tvbuff_t *tvb, int offset,
3684                                   packet_info *pinfo, proto_tree *tree,
3685                                   char *drep _U_)
3686 {
3687         /* Parse packet */
3688
3689         offset = dissect_nt_policy_hnd(
3690                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
3691                 FALSE, FALSE);
3692
3693         offset = dissect_doserror(
3694                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
3695
3696         return offset;
3697 }
3698
3699 static int SpoolssAddPrinterEx_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
3700                                  proto_tree *tree, char *drep _U_)
3701 {
3702         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
3703         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
3704         e_ctx_hnd policy_hnd;
3705         proto_item *hnd_item;
3706         guint32 status;
3707
3708         /* Parse packet */
3709
3710         offset = dissect_nt_policy_hnd(
3711                 tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, &hnd_item,
3712                 TRUE, FALSE);
3713
3714         offset = dissect_doserror(
3715                 tvb, offset, pinfo, tree, drep, hf_rc, &status);
3716
3717         if (status == 0) {
3718
3719                 /* Associate the returned printer handle with a name */
3720
3721                 if (dcv->private_data) {
3722
3723                         if (check_col(pinfo->cinfo, COL_INFO))
3724                                 col_append_fstr(
3725                                         pinfo->cinfo, COL_INFO, ", %s",
3726                                         (char *)dcv->private_data);
3727
3728                         dcerpc_smb_store_pol_name(
3729                                 &policy_hnd, pinfo, dcv->private_data);
3730
3731                         g_free(dcv->private_data);
3732                         dcv->private_data = NULL;
3733                 }
3734
3735                 /*
3736                  * If we have a name for the handle, attach it to the item.
3737                  *
3738                  * XXX - we can't just do that above, as this may be called
3739                  * twice (see "dissect_pipe_dcerpc()", which calls the
3740                  * DCE RPC dissector twice), and in the first call we're
3741                  * not building a protocol tree (so we don't have an item
3742                  * to which to attach it) and in the second call
3743                  * "dcv->private_data" is NULL so we don't construct a
3744                  * name.
3745                  */
3746
3747                 if (hnd_item != NULL) {
3748                         char *name;
3749
3750                         if (dcerpc_smb_fetch_pol(&policy_hnd, &name, NULL, NULL,
3751                             pinfo->fd->num) && name != NULL)
3752                                 proto_item_append_text(hnd_item, ": %s", name);
3753                 }
3754         }
3755
3756         return offset;
3757 }
3758
3759 /*
3760  * SpoolssEnumPrinterData
3761  */
3762
3763 static int hf_enumprinterdata_enumindex = -1;
3764 static int hf_enumprinterdata_value_offered = -1;
3765 static int hf_enumprinterdata_data_offered = -1;
3766 static int hf_enumprinterdata_value_len = -1;
3767 static int hf_enumprinterdata_value_needed = -1;
3768 static int hf_enumprinterdata_data_needed = -1;
3769
3770 static int SpoolssEnumPrinterData_q(tvbuff_t *tvb, int offset,
3771                                     packet_info *pinfo, proto_tree *tree,
3772                                     char *drep _U_)
3773 {
3774         guint32 ndx;
3775
3776         proto_tree_add_uint_hidden(
3777                 tree, hf_printerdata, tvb, offset, 0, 1);
3778
3779         /* Parse packet */
3780
3781         offset = dissect_nt_policy_hnd(
3782                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
3783                 FALSE, FALSE);
3784
3785         offset = dissect_ndr_uint32(
3786                 tvb, offset, pinfo, tree, drep, 
3787                 hf_enumprinterdata_enumindex, &ndx);
3788
3789         if (check_col(pinfo->cinfo, COL_INFO))
3790                 col_append_fstr(pinfo->cinfo, COL_INFO, ", index %d", ndx);
3791
3792         offset = dissect_ndr_uint32(
3793                 tvb, offset, pinfo, tree, drep,
3794                 hf_enumprinterdata_value_offered, NULL);
3795
3796         offset = dissect_ndr_uint32(
3797                 tvb, offset, pinfo, tree, drep,
3798                 hf_enumprinterdata_data_offered, NULL);
3799
3800         return offset;
3801 }
3802
3803 static int SpoolssEnumPrinterData_r(tvbuff_t *tvb, int offset,
3804                                     packet_info *pinfo, proto_tree *tree,
3805                                     char *drep _U_)
3806 {
3807         guint32 value_len, type;
3808         char *value;
3809         proto_item *value_item;
3810         proto_tree *value_subtree;
3811
3812         proto_tree_add_uint_hidden(
3813                 tree, hf_printerdata, tvb, offset, 0, 1);
3814
3815         /* Parse packet */
3816
3817         value_item = proto_tree_add_text(tree, tvb, offset, 0, "Value");
3818
3819         value_subtree = proto_item_add_subtree(
3820                 value_item, ett_printerdata_value);
3821
3822         offset = dissect_ndr_uint32(
3823                 tvb, offset, pinfo, value_subtree, drep,
3824                 hf_enumprinterdata_value_len, &value_len);
3825
3826         if (value_len) {
3827                 dissect_spoolss_uint16uni(
3828                         tvb, offset, pinfo, value_subtree, drep, &value, 
3829                         "Value name");
3830
3831                 offset += value_len * 2;
3832
3833                 if (check_col(pinfo->cinfo, COL_INFO) && value && value[0])
3834                         col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value);
3835
3836                 proto_item_append_text(value_item, ": %s", value);
3837
3838                 proto_tree_add_string_hidden(
3839                         tree, hf_printerdata_value, tvb, offset, 0, value);
3840
3841                 g_free(value);
3842         }
3843
3844         proto_item_set_len(value_item, value_len * 2 + 4);
3845
3846         offset = dissect_ndr_uint32(
3847                 tvb, offset, pinfo, value_subtree, drep,
3848                 hf_enumprinterdata_value_needed, NULL);
3849
3850         offset = dissect_ndr_uint32(
3851                 tvb, offset, pinfo, tree, drep, hf_printerdata_type, &type);
3852
3853         offset = dissect_printerdata_data(
3854                 tvb, offset, pinfo, tree, drep, type);
3855
3856         offset = dissect_ndr_uint32(
3857                 tvb, offset, pinfo, tree, drep,
3858                 hf_enumprinterdata_data_needed, NULL);
3859
3860         offset = dissect_doserror(
3861                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
3862
3863         return offset;
3864 }
3865
3866 /*
3867  * SpoolssEnumPrinters
3868  */
3869
3870 static gint ett_enumprinters_flags = -1;
3871
3872 static int hf_enumprinters_flags = -1;
3873 static int hf_enumprinters_flags_local = -1;
3874 static int hf_enumprinters_flags_name = -1;
3875 static int hf_enumprinters_flags_shared = -1;
3876 static int hf_enumprinters_flags_default = -1;
3877 static int hf_enumprinters_flags_connections = -1;
3878 static int hf_enumprinters_flags_network = -1;
3879 static int hf_enumprinters_flags_remote = -1;
3880
3881 static int SpoolssEnumPrinters_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
3882                                  proto_tree *tree, char *drep _U_)
3883 {
3884         guint32 level, flags;
3885         proto_tree *flags_subtree;
3886         proto_item *flags_item;
3887
3888         /* Parse packet */
3889
3890         offset = dissect_ndr_uint32(
3891                 tvb, offset, pinfo, NULL, drep,
3892                 hf_enumprinters_flags, &flags);
3893
3894         flags_item = proto_tree_add_text(tree, tvb, offset - 4, 4,
3895                                          "Flags: 0x%08x", flags);
3896
3897         flags_subtree = proto_item_add_subtree(
3898                 flags_item, ett_enumprinters_flags);
3899
3900         proto_tree_add_boolean(
3901                 flags_subtree, hf_enumprinters_flags_network, tvb,
3902                 offset - 4, 4, flags);
3903
3904         proto_tree_add_boolean(
3905                 flags_subtree, hf_enumprinters_flags_shared, tvb,
3906                 offset - 4, 4, flags);
3907
3908         proto_tree_add_boolean(
3909                 flags_subtree, hf_enumprinters_flags_remote, tvb,
3910                 offset - 4, 4, flags);
3911
3912         proto_tree_add_boolean(
3913                 flags_subtree, hf_enumprinters_flags_name, tvb,
3914                 offset - 4, 4, flags);
3915
3916         proto_tree_add_boolean(
3917                 flags_subtree, hf_enumprinters_flags_connections, tvb,
3918                 offset - 4, 4, flags);
3919
3920         proto_tree_add_boolean(
3921                 flags_subtree, hf_enumprinters_flags_local, tvb,
3922                 offset - 4, 4, flags);
3923
3924         proto_tree_add_boolean(
3925                 flags_subtree, hf_enumprinters_flags_default, tvb,
3926                 offset - 4, 4, flags);
3927
3928         offset = dissect_ndr_str_pointer_item(
3929                 tvb, offset, pinfo, tree, drep,
3930                 NDR_POINTER_UNIQUE, "Server name", hf_servername, 0);
3931
3932         offset = dissect_ndr_uint32(
3933                 tvb, offset, pinfo, tree, drep, hf_level, &level);
3934
3935         if (check_col(pinfo->cinfo, COL_INFO))
3936                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
3937
3938         offset = dissect_spoolss_buffer(
3939                 tvb, offset, pinfo, tree, drep, NULL);
3940
3941         offset = dissect_ndr_uint32(
3942                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
3943
3944         return offset;
3945 }
3946
3947 static int SpoolssEnumPrinters_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
3948                                  proto_tree *tree, char *drep _U_)
3949 {
3950         guint32 num_drivers;
3951
3952         /* Parse packet */
3953
3954         offset = dissect_spoolss_buffer(
3955                 tvb, offset, pinfo, tree, drep, NULL);
3956
3957         offset = dissect_ndr_uint32(
3958                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
3959
3960         offset = dissect_ndr_uint32(
3961                 tvb, offset, pinfo, tree, drep, hf_returned, 
3962                 &num_drivers);
3963
3964         offset = dissect_doserror(
3965                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
3966
3967         return offset;
3968 }
3969
3970 /*
3971  * AddPrinterDriver
3972  */
3973 #if 0
3974 static int SpoolssAddPrinterDriver_q(tvbuff_t *tvb, int offset,
3975                                      packet_info *pinfo, proto_tree *tree,
3976                                      char *drep)
3977 {
3978         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
3979         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
3980
3981         /* Parse packet */
3982
3983         offset = dissect_ndr_str_pointer_item(
3984                 tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
3985                 "Server", hf_servername, 0);
3986
3987         offset = dissect_spoolss_DRIVER_INFO_CTR(
3988                 tvb, offset, pinfo, tree, drep);
3989
3990         return offset;
3991 }
3992 #endif
3993 static int SpoolssAddPrinterDriver_r(tvbuff_t *tvb, int offset,
3994                                      packet_info *pinfo, proto_tree *tree,
3995                                      char *drep _U_)
3996 {
3997         /* Parse packet */
3998
3999         offset = dissect_doserror(
4000                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
4001
4002         return offset;
4003 }
4004
4005 /*
4006  * FORM_1
4007  */
4008
4009 static gint ett_FORM_1 = -1;
4010
4011 static int dissect_FORM_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
4012                           proto_tree *tree, char *drep)
4013 {
4014         proto_item *item;
4015         proto_tree *subtree;
4016         guint32 flags;
4017
4018         item = proto_tree_add_text(tree, tvb, offset, 0, "Form level 1");
4019
4020         subtree = proto_item_add_subtree(item, ett_FORM_1);
4021
4022         offset = dissect_ndr_str_pointer_item(
4023                 tvb, offset, pinfo, subtree, drep, NDR_POINTER_UNIQUE,
4024                 "Name", hf_form_name, 0);
4025
4026         /* Eek - we need to know whether this pointer was NULL or not.
4027            Currently there is not any way to do this. */
4028
4029         if (tvb_length_remaining(tvb, offset) == 0)
4030                 goto done;
4031
4032         offset = dissect_ndr_uint32(
4033                 tvb, offset, pinfo, subtree, drep, hf_form_flags, &flags);
4034
4035         offset = dissect_ndr_uint32(
4036                 tvb, offset, pinfo, subtree, drep,
4037                 hf_form_unknown, NULL);
4038
4039         offset = dissect_ndr_uint32(
4040                 tvb, offset, pinfo, subtree, drep,
4041                 hf_form_width, NULL);
4042
4043         offset = dissect_ndr_uint32(
4044                 tvb, offset, pinfo, subtree, drep,
4045                 hf_form_height, NULL);
4046
4047         offset = dissect_ndr_uint32(
4048                 tvb, offset, pinfo, subtree, drep,
4049                 hf_form_left_margin, NULL);
4050
4051         offset = dissect_ndr_uint32(
4052                 tvb, offset, pinfo, subtree, drep,
4053                 hf_form_top_margin, NULL);
4054
4055         offset = dissect_ndr_uint32(
4056                 tvb, offset, pinfo, subtree, drep,
4057                 hf_form_horiz_len, NULL);
4058
4059         offset = dissect_ndr_uint32(
4060                 tvb, offset, pinfo, subtree, drep,
4061                 hf_form_vert_len, NULL);
4062
4063  done:
4064         return offset;
4065 }
4066
4067 /*
4068  * FORM_CTR
4069  */
4070
4071 static gint ett_FORM_CTR = -1;
4072
4073 static int dissect_FORM_CTR(tvbuff_t *tvb, int offset,
4074                             packet_info *pinfo, proto_tree *tree,
4075                             char *drep)
4076 {
4077         proto_item *item;
4078         proto_tree *subtree;
4079         guint32 level;
4080
4081         item = proto_tree_add_text(tree, tvb, offset, 0, "Form container");
4082
4083         subtree = proto_item_add_subtree(item, ett_FORM_CTR);
4084
4085         offset = dissect_ndr_uint32(
4086                 tvb, offset, pinfo, subtree, drep, hf_form_level, &level);
4087
4088         switch(level) {
4089         case 1:
4090                 offset = dissect_FORM_1(tvb, offset, pinfo, subtree, drep);
4091                 break;
4092
4093         default:
4094                 proto_tree_add_text(
4095                         subtree, tvb, offset, 0,
4096                         "[Unknown form info level %d]", level);
4097                 break;
4098         }
4099
4100         return offset;
4101 }
4102
4103 /*
4104  * AddForm
4105  */
4106
4107 static int SpoolssAddForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
4108                             proto_tree *tree, char *drep _U_)
4109 {
4110         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4111         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4112         guint32 level;
4113
4114         proto_tree_add_uint_hidden(
4115                 tree, hf_form, tvb, offset, 0, 1);
4116
4117         /* Parse packet */
4118
4119         offset = dissect_nt_policy_hnd(
4120                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
4121                 FALSE, FALSE);
4122
4123         offset = dissect_ndr_uint32(
4124                 tvb, offset, pinfo, tree, drep, hf_form_level, &level);
4125
4126         if (check_col(pinfo->cinfo, COL_INFO))
4127                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
4128
4129         /* Store info level to match with reply packet */
4130
4131         dcv->private_data = (void *)level;
4132
4133         offset = dissect_FORM_CTR(tvb, offset, pinfo, tree, drep);
4134
4135         return offset;
4136 }
4137
4138 static int SpoolssAddForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
4139                             proto_tree *tree, char *drep _U_)
4140 {
4141         proto_tree_add_uint_hidden(
4142                 tree, hf_form, tvb, offset, 0, 1);
4143
4144         /* Parse packet */
4145
4146         offset = dissect_doserror(
4147                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
4148
4149         return offset;
4150 }
4151
4152 /*
4153  * DeleteForm
4154  */
4155
4156 static int SpoolssDeleteForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
4157                                proto_tree *tree, char *drep _U_)
4158 {
4159         char *name = NULL;
4160
4161         proto_tree_add_uint_hidden(
4162                 tree, hf_form, tvb, offset, 0, 1);
4163
4164         /* Parse packet */
4165
4166         offset = dissect_nt_policy_hnd(
4167                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
4168                 FALSE, FALSE);
4169
4170         offset = dissect_ndr_cvstring(
4171                 tvb, offset, pinfo, tree, drep,
4172                 sizeof(guint16), hf_form_name, TRUE, &name);
4173
4174         if (check_col(pinfo->cinfo, COL_INFO) && name)
4175                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", name);
4176
4177         g_free(name);
4178         
4179         return offset;
4180 }
4181
4182 static int SpoolssDeleteForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
4183                             proto_tree *tree, char *drep _U_)
4184 {
4185         proto_tree_add_uint_hidden(
4186                 tree, hf_form, tvb, offset, 0, 1);
4187
4188         /* Parse packet */
4189
4190         offset = dissect_doserror(
4191                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
4192
4193         return offset;
4194 }
4195
4196 /*
4197  * SetForm
4198  */
4199
4200 static int SpoolssSetForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
4201                             proto_tree *tree, char *drep _U_)
4202 {
4203         char *name = NULL;
4204         guint32 level;
4205
4206         proto_tree_add_uint_hidden(
4207                 tree, hf_form, tvb, offset, 0, 1);
4208
4209         /* Parse packet */
4210
4211         offset = dissect_nt_policy_hnd(
4212                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
4213                 FALSE, FALSE);
4214
4215         offset = dissect_ndr_cvstring(
4216                 tvb, offset, pinfo, tree, drep,
4217                 sizeof(guint16), hf_form_name, TRUE, &name);
4218
4219         if (check_col(pinfo->cinfo, COL_INFO) && name)
4220                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", name);
4221         
4222         g_free(name);
4223
4224         offset = dissect_ndr_uint32(
4225                 tvb, offset, pinfo, tree, drep, hf_form_level, &level);
4226
4227         if (check_col(pinfo->cinfo, COL_INFO))
4228                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
4229
4230         offset = dissect_FORM_CTR(tvb, offset, pinfo, tree, drep);
4231
4232         return offset;
4233 }
4234
4235 static int SpoolssSetForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
4236                             proto_tree *tree, char *drep _U_)
4237 {
4238         proto_tree_add_uint_hidden(
4239                 tree, hf_form, tvb, offset, 0, 1);
4240
4241         /* Parse packet */
4242
4243         offset = dissect_doserror(
4244                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
4245
4246         return offset;
4247 }
4248
4249 /*
4250  * GetForm
4251  */
4252
4253 static int SpoolssGetForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
4254                             proto_tree *tree, char *drep _U_)
4255 {
4256         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4257         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4258         guint32 level;
4259         char *name;
4260
4261         proto_tree_add_uint_hidden(
4262                 tree, hf_form, tvb, offset, 0, 1);
4263
4264         /* Parse packet */
4265
4266         offset = dissect_nt_policy_hnd(
4267                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
4268                 FALSE, FALSE);
4269
4270         offset = dissect_ndr_cvstring(
4271                 tvb, offset, pinfo, tree, drep,
4272                 sizeof(guint16), hf_form_name, TRUE, &name);
4273
4274         if (check_col(pinfo->cinfo, COL_INFO))
4275                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", name);
4276
4277         offset = dissect_ndr_uint32(
4278                 tvb, offset, pinfo, tree, drep, hf_form_level, &level);
4279
4280         dcv->private_data = (void *)level;
4281
4282         if (check_col(pinfo->cinfo, COL_INFO))
4283                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d",
4284                                 level);
4285
4286         offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep, NULL);
4287
4288         offset = dissect_ndr_uint32(
4289                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
4290
4291         return offset;
4292 }
4293
4294 static int SpoolssGetForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
4295                             proto_tree *tree, char *drep _U_)
4296 {
4297         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4298         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4299         BUFFER buffer;
4300         guint32 level = (guint32)dcv->private_data;
4301
4302         proto_tree_add_uint_hidden(
4303                 tree, hf_form, tvb, offset, 0, 1);
4304
4305         /* Parse packet */
4306
4307         offset = dissect_spoolss_buffer(
4308                 tvb, offset, pinfo, tree, drep, &buffer);
4309
4310         offset = dissect_ndr_uint32(
4311                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
4312
4313         if (check_col(pinfo->cinfo, COL_INFO))
4314                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
4315
4316         if (buffer.tvb) {
4317                 int buffer_offset = 0;
4318
4319                 switch(level) {
4320                 case 1: {
4321                         int struct_start = buffer_offset;
4322                         
4323                         buffer_offset = dissect_FORM_REL(
4324                                 buffer.tvb, buffer_offset, pinfo, tree, drep,
4325                                 struct_start);
4326                         break;
4327                 }
4328                         
4329                 default:
4330                         proto_tree_add_text(
4331                                 buffer.tree, buffer.tvb, buffer_offset, -1,
4332                                 "[Unknown form info level %d]", level);
4333                         break;
4334                 }
4335         }
4336
4337         offset = dissect_doserror(
4338                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
4339
4340         return offset;
4341 }
4342
4343 /* A generic reply function that just parses the status code.  Useful for
4344    unimplemented dissectors so the status code can be inserted into the
4345    INFO column. */
4346
4347 static int SpoolssGeneric_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
4348                             proto_tree *tree, char *drep _U_)
4349 {
4350         int len = tvb_length(tvb);
4351
4352         proto_tree_add_text(tree, tvb, offset, 0,
4353                             "[Unimplemented dissector: SPOOLSS]");
4354
4355         offset = dissect_doserror(
4356                 tvb, len - 4, pinfo, tree, drep, hf_rc, NULL);
4357
4358         return offset;
4359 }
4360
4361 /*
4362  * JOB_INFO_1
4363  */
4364
4365 static gint ett_JOB_INFO_1;
4366
4367 static int
4368 dissect_spoolss_JOB_INFO_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
4369                            proto_tree *tree, char *drep)
4370 {
4371         proto_item *item;
4372         proto_tree *subtree;
4373         int struct_start = offset;
4374         char *document_name;
4375
4376         item = proto_tree_add_text(tree, tvb, offset, 0, "Job info level 1");
4377
4378         subtree = proto_item_add_subtree(item, ett_JOB_INFO_1);
4379
4380         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
4381                                     hf_job_id, NULL);
4382
4383         offset = dissect_spoolss_relstr(
4384                 tvb, offset, pinfo, subtree, drep, hf_printername,
4385                 struct_start, NULL);
4386
4387         offset = dissect_spoolss_relstr(
4388                 tvb, offset, pinfo, subtree, drep, hf_servername,
4389                 struct_start, NULL);
4390
4391         offset = dissect_spoolss_relstr(
4392                 tvb, offset, pinfo, subtree, drep, hf_username,
4393                 struct_start, NULL);
4394
4395         offset = dissect_spoolss_relstr(
4396                 tvb, offset, pinfo, subtree, drep, hf_documentname,
4397                 struct_start, &document_name);
4398
4399         proto_item_append_text(item, ": %s", document_name);
4400         g_free(document_name);
4401
4402         offset = dissect_spoolss_relstr(
4403                 tvb, offset, pinfo, subtree, drep, hf_datatype,
4404                 struct_start, NULL);
4405
4406         offset = dissect_spoolss_relstr(
4407                 tvb, offset, pinfo, subtree, drep, hf_textstatus,
4408                 struct_start, NULL);
4409
4410         offset = dissect_job_status(tvb, offset, pinfo, subtree, drep);
4411
4412         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
4413                                     hf_job_priority, NULL);
4414
4415         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
4416                                     hf_job_position, NULL);
4417
4418         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
4419                                     hf_job_totalpages, NULL);
4420
4421         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
4422                                     hf_job_pagesprinted, NULL);
4423
4424         offset = dissect_SYSTEM_TIME(
4425                 tvb, offset, pinfo, subtree, drep, "Job Submission Time",
4426                 TRUE, NULL);
4427
4428         proto_item_set_len(item, offset - struct_start);
4429
4430         return offset;
4431 }
4432
4433 /*
4434  * JOB_INFO_2
4435  */
4436
4437 static gint ett_JOB_INFO_2;
4438
4439 static int
4440 dissect_spoolss_JOB_INFO_2(tvbuff_t *tvb, int offset, packet_info *pinfo,
4441                            proto_tree *tree, char *drep)
4442 {
4443         proto_item *item;
4444         proto_tree *subtree;
4445         int struct_start = offset;
4446         char *document_name;
4447         guint32 devmode_offset, secdesc_offset;
4448
4449         item = proto_tree_add_text(tree, tvb, offset, 0, "Job info level 2");
4450
4451         subtree = proto_item_add_subtree(item, ett_JOB_INFO_2);
4452
4453         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
4454                                     hf_job_id, NULL);
4455
4456         offset = dissect_spoolss_relstr(
4457                 tvb, offset, pinfo, subtree, drep, hf_printername,
4458                 struct_start, NULL);
4459
4460         offset = dissect_spoolss_relstr(
4461                 tvb, offset, pinfo, subtree, drep, hf_machinename,
4462                 struct_start, NULL);
4463
4464         offset = dissect_spoolss_relstr(
4465                 tvb, offset, pinfo, subtree, drep, hf_username,
4466                 struct_start, NULL);
4467
4468         offset = dissect_spoolss_relstr(
4469                 tvb, offset, pinfo, subtree, drep, hf_documentname,
4470                 struct_start, &document_name);
4471
4472         proto_item_append_text(item, ": %s", document_name);
4473         g_free(document_name);
4474
4475         offset = dissect_spoolss_relstr(
4476                 tvb, offset, pinfo, subtree, drep, hf_notifyname,
4477                 struct_start, NULL);
4478
4479         offset = dissect_spoolss_relstr(
4480                 tvb, offset, pinfo, subtree, drep, hf_datatype,
4481                 struct_start, NULL);
4482
4483         offset = dissect_spoolss_relstr(
4484                 tvb, offset, pinfo, subtree, drep, hf_printprocessor,
4485                 struct_start, NULL);
4486
4487         offset = dissect_spoolss_relstr(
4488                 tvb, offset, pinfo, subtree, drep, hf_parameters,
4489                 struct_start, NULL);
4490
4491         offset = dissect_spoolss_relstr(
4492                 tvb, offset, pinfo, subtree, drep, hf_drivername,
4493                 struct_start, NULL);
4494
4495         offset = dissect_ndr_uint32(
4496                 tvb, offset, pinfo, NULL, drep, hf_offset, 
4497                 &devmode_offset);
4498
4499         dissect_DEVMODE(
4500                 tvb, devmode_offset - 4 + struct_start, pinfo, subtree, drep);
4501
4502         offset = dissect_spoolss_relstr(
4503                 tvb, offset, pinfo, subtree, drep, hf_textstatus,
4504                 struct_start, NULL);
4505
4506         offset = dissect_ndr_uint32(
4507                 tvb, offset, pinfo, NULL, drep, hf_offset,
4508                 &secdesc_offset);
4509
4510         dissect_nt_sec_desc(
4511                 tvb, secdesc_offset, pinfo, subtree, drep,
4512                 tvb_length_remaining(tvb, secdesc_offset),
4513                 &spoolss_job_access_mask_info);
4514
4515         offset = dissect_job_status(tvb, offset, pinfo, subtree, drep);
4516
4517         offset = dissect_ndr_uint32(
4518                 tvb, offset, pinfo, subtree, drep, hf_job_priority, NULL);
4519
4520         offset = dissect_ndr_uint32(
4521                 tvb, offset, pinfo, subtree, drep, hf_job_position, NULL);
4522
4523         offset = dissect_ndr_uint32(
4524                 tvb, offset, pinfo, NULL, drep, hf_start_time, NULL);
4525
4526         offset = dissect_ndr_uint32(
4527                 tvb, offset, pinfo, NULL, drep, hf_end_time, NULL);
4528
4529         offset = dissect_ndr_uint32(
4530                 tvb, offset, pinfo, subtree, drep, hf_job_totalpages, NULL);
4531
4532         offset = dissect_ndr_uint32(
4533                 tvb, offset, pinfo, subtree, drep, hf_job_size, NULL);
4534
4535         offset = dissect_SYSTEM_TIME(
4536                 tvb, offset, pinfo, subtree, drep, "Job Submission Time",
4537                 TRUE, NULL);
4538
4539         offset = dissect_ndr_uint32(
4540                 tvb, offset, pinfo, NULL, drep, hf_elapsed_time, NULL);
4541
4542         offset = dissect_ndr_uint32(
4543                 tvb, offset, pinfo, subtree, drep, hf_job_pagesprinted, NULL);
4544
4545         proto_item_set_len(item, offset - struct_start);
4546
4547         return offset;
4548 }
4549
4550 /*
4551  * EnumJobs
4552  */
4553
4554 static int hf_enumjobs_firstjob = -1;
4555 static int hf_enumjobs_numjobs = -1;
4556
4557 static int SpoolssEnumJobs_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
4558                              proto_tree *tree, char *drep _U_)
4559 {
4560         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4561         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4562         guint32 level;
4563
4564         /* Parse packet */
4565
4566         offset = dissect_nt_policy_hnd(
4567                 tvb, offset, pinfo, tree, drep,
4568                 hf_hnd, NULL, NULL, FALSE, FALSE);
4569
4570         offset = dissect_ndr_uint32(
4571                 tvb, offset, pinfo, tree, drep, hf_enumjobs_firstjob, NULL);
4572
4573         offset = dissect_ndr_uint32(
4574                 tvb, offset, pinfo, tree, drep, hf_enumjobs_numjobs, NULL);
4575
4576         offset = dissect_ndr_uint32(
4577                 tvb, offset, pinfo, tree, drep, hf_level, &level);
4578
4579         dcv->private_data = (void *)level;
4580
4581         if (check_col(pinfo->cinfo, COL_INFO))
4582                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
4583
4584         offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep, NULL);
4585
4586         offset = dissect_ndr_uint32(
4587                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
4588
4589         return offset;
4590 }
4591
4592 static int SpoolssEnumJobs_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
4593                              proto_tree *tree, char *drep _U_)
4594 {
4595         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4596         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4597         gint16 level = (guint32)dcv->private_data;
4598         BUFFER buffer;
4599         guint32 num_jobs, i;
4600         int buffer_offset;
4601
4602         /* Parse packet */
4603
4604         offset = dissect_spoolss_buffer(
4605                 tvb, offset, pinfo, tree, drep, &buffer);
4606
4607         offset = dissect_ndr_uint32(
4608                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
4609
4610         offset = dissect_ndr_uint32(
4611                 tvb, offset, pinfo, tree, drep, hf_enumjobs_numjobs, 
4612                 &num_jobs);
4613
4614         buffer_offset = 0;
4615
4616         for (i = 0; i < num_jobs; i++) {
4617                 switch(level) {
4618                 case 1:
4619                         buffer_offset = dissect_spoolss_JOB_INFO_1(
4620                                 buffer.tvb, buffer_offset, pinfo, 
4621                                 buffer.tree, drep);
4622                         break;
4623                 case 2:
4624                         buffer_offset = dissect_spoolss_JOB_INFO_2(
4625                                 buffer.tvb, buffer_offset, pinfo, 
4626                                 buffer.tree, drep);
4627                         break;
4628                 default:
4629                         proto_tree_add_text(
4630                                 buffer.tree, buffer.tvb, 0, -1,
4631                                 "[Unknown job info level %d]", level);
4632                         break;
4633                 }
4634
4635         }
4636
4637         offset = dissect_doserror(
4638                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
4639
4640         return offset;
4641 }
4642
4643 /*
4644  * SetJob
4645  */
4646
4647 static const value_string setjob_commands[] = {
4648         { JOB_CONTROL_PAUSE, "Pause" },
4649         { JOB_CONTROL_RESUME, "Resume" },
4650         { JOB_CONTROL_CANCEL, "Cancel" },
4651         { JOB_CONTROL_RESTART, "Restart" },
4652         { JOB_CONTROL_DELETE, "Delete" },
4653         { 0, NULL }
4654 };
4655
4656 static int hf_setjob_cmd = -1;
4657
4658 static int SpoolssSetJob_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
4659                            proto_tree *tree, char *drep)
4660 {
4661         guint32 jobid, cmd;
4662
4663         /* Parse packet */
4664
4665         offset = dissect_nt_policy_hnd(
4666                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
4667                 FALSE, FALSE);
4668
4669         offset = dissect_ndr_uint32(
4670                 tvb, offset, pinfo, tree, drep, hf_job_id, &jobid);
4671
4672         offset = dissect_ndr_uint32(
4673                 tvb, offset, pinfo, tree, drep, hf_level, NULL);
4674
4675         offset = dissect_ndr_uint32(
4676                 tvb, offset, pinfo, tree, drep, hf_setjob_cmd, &cmd);
4677
4678         if (check_col(pinfo->cinfo, COL_INFO))
4679                 col_append_fstr(
4680                         pinfo->cinfo, COL_INFO, ", %s jobid %d",
4681                         val_to_str(cmd, setjob_commands, "Unknown (%d)"),
4682                         jobid);
4683
4684         return offset;
4685 }
4686
4687 static int SpoolssSetJob_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
4688                            proto_tree *tree, char *drep)
4689 {
4690         /* Parse packet */
4691
4692         offset = dissect_doserror(
4693                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
4694
4695         return offset;
4696 }
4697
4698 /*
4699  * GetJob
4700  */
4701
4702 static int SpoolssGetJob_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
4703                            proto_tree *tree, char *drep)
4704 {
4705         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4706         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4707         guint32 level, jobid;
4708
4709         /* Parse packet */
4710
4711         offset = dissect_nt_policy_hnd(
4712                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
4713                 FALSE, FALSE);
4714
4715         offset = dissect_ndr_uint32(
4716                 tvb, offset, pinfo, tree, drep, hf_job_id, &jobid);
4717
4718         offset = dissect_ndr_uint32(
4719                 tvb, offset, pinfo, tree, drep, hf_level, &level);
4720
4721         dcv->private_data = (void *)level;
4722
4723         if (check_col(pinfo->cinfo, COL_INFO))
4724                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d, jobid %d",
4725                                 level, jobid);
4726
4727         offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep, NULL);
4728
4729         offset = dissect_ndr_uint32(
4730                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
4731
4732         return offset;
4733 }
4734
4735 static int SpoolssGetJob_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
4736                         proto_tree *tree, char *drep)
4737 {
4738         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
4739         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
4740         gint32 level = (guint32)dcv->private_data;
4741         BUFFER buffer;
4742
4743         /* Parse packet */
4744
4745         offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep,
4746                                         &buffer);
4747
4748         if (buffer.tvb) {
4749                 int buffer_offset = 0;
4750                 
4751                 switch(level) {
4752                 case 1:
4753                         buffer_offset = dissect_spoolss_JOB_INFO_1(
4754                                 buffer.tvb, buffer_offset, pinfo, 
4755                                 buffer.tree, drep);
4756                         break;
4757                 case 2:
4758                 default:
4759                         proto_tree_add_text(
4760                                 buffer.tree, buffer.tvb, buffer_offset, -1,
4761                                 "[Unknown job info level %d]", level);
4762                         break;
4763                 }
4764         }
4765
4766         offset = dissect_ndr_uint32(
4767                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
4768
4769         offset = dissect_doserror(
4770                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
4771
4772         return offset;
4773 }
4774
4775 /*
4776  * StartPagePrinter
4777  */
4778
4779 static int SpoolssStartPagePrinter_q(tvbuff_t *tvb, int offset,
4780                                      packet_info *pinfo, proto_tree *tree,
4781                                      char *drep)
4782 {
4783         e_ctx_hnd policy_hnd;
4784         char *pol_name;
4785
4786         /* Parse packet */
4787
4788         offset = dissect_nt_policy_hnd(
4789                 tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
4790                 FALSE, FALSE);
4791
4792         dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
4793                              pinfo->fd->num);
4794
4795         if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
4796                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
4797                                 pol_name);
4798
4799         return offset;
4800 }
4801
4802 static int SpoolssStartPagePrinter_r(tvbuff_t *tvb, int offset,
4803                                      packet_info *pinfo, proto_tree *tree,
4804                                      char *drep)
4805 {
4806         /* Parse packet */
4807
4808         offset = dissect_doserror(
4809                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
4810
4811         return offset;
4812 }
4813
4814 /*
4815  * EndPagePrinter
4816  */
4817
4818 static int SpoolssEndPagePrinter_q(tvbuff_t *tvb, int offset,
4819                                    packet_info *pinfo, proto_tree *tree,
4820                                    char *drep)
4821 {
4822         e_ctx_hnd policy_hnd;
4823         char *pol_name;
4824
4825         /* Parse packet */
4826
4827         offset = dissect_nt_policy_hnd(
4828                 tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
4829                 FALSE, FALSE);
4830
4831         dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
4832                              pinfo->fd->num);
4833
4834         if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
4835                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
4836                                 pol_name);
4837
4838         return offset;
4839 }
4840
4841 static int SpoolssEndPagePrinter_r(tvbuff_t *tvb, int offset,
4842                                    packet_info *pinfo, proto_tree *tree,
4843                                    char *drep)
4844 {
4845         /* Parse packet */
4846
4847         offset = dissect_doserror(
4848                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
4849
4850         return offset;
4851 }
4852
4853 /*
4854  * DOC_INFO_1
4855  */
4856
4857 static gint ett_DOC_INFO_1 = -1;
4858
4859 static int
4860 dissect_spoolss_doc_info_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
4861                            proto_tree *tree, char *drep)
4862 {
4863         proto_item *item;
4864         proto_tree *subtree;
4865
4866         item = proto_tree_add_text(
4867                 tree, tvb, offset, 0, "Document info level 1");
4868
4869         subtree = proto_item_add_subtree(item, ett_DOC_INFO_1);
4870
4871         offset = dissect_ndr_str_pointer_item(
4872                 tvb, offset, pinfo, subtree, drep, NDR_POINTER_UNIQUE,
4873                 "Document name", hf_documentname, 0);
4874
4875         offset = dissect_ndr_str_pointer_item(
4876                 tvb, offset, pinfo, subtree, drep, NDR_POINTER_UNIQUE,
4877                 "Output file", hf_outputfile, 0);
4878
4879         offset = dissect_ndr_str_pointer_item(
4880                 tvb, offset, pinfo, subtree, drep, NDR_POINTER_UNIQUE,
4881                 "Data type", hf_datatype, 0);
4882
4883         return offset;
4884 }
4885
4886 static int
4887 dissect_spoolss_doc_info_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
4888                               proto_tree *tree, char *drep)
4889 {
4890         dcerpc_info *di = pinfo->private_data;
4891         guint32 info_level = 1; /* XXX */
4892
4893         if (di->conformant_run)
4894                 return offset;
4895
4896         switch(info_level) {
4897         case 1:
4898                 offset = dissect_spoolss_doc_info_1(
4899                         tvb, offset, pinfo, tree, drep);
4900                 break;
4901         default:
4902                 proto_tree_add_text(
4903                         tree, tvb, offset, 0,
4904                         "[Unknown documentinfo level %d]", info_level);
4905                 break;
4906         }
4907
4908         return offset;
4909 }
4910
4911 /*
4912  * DOC_INFO
4913  */
4914
4915 static gint ett_DOC_INFO = -1;
4916
4917 static int
4918 dissect_spoolss_doc_info(tvbuff_t *tvb, int offset, packet_info *pinfo,
4919                          proto_tree *tree, char *drep)
4920 {
4921         proto_item *item;
4922         proto_tree *subtree;
4923         guint32 level;
4924
4925         item = proto_tree_add_text(
4926                 tree, tvb, offset, 0, "Document info");
4927
4928         subtree = proto_item_add_subtree(item, ett_DOC_INFO);
4929
4930         offset = dissect_ndr_uint32(
4931                 tvb, offset, pinfo, subtree, drep, hf_level, &level);
4932
4933         offset = dissect_ndr_pointer(
4934                 tvb, offset, pinfo, subtree, drep,
4935                 dissect_spoolss_doc_info_data,
4936                 NDR_POINTER_UNIQUE, "Document info", -1);
4937
4938         return offset;
4939 }
4940
4941 /*
4942  * DOC_INFO_CTR
4943  */
4944
4945 static gint ett_DOC_INFO_CTR = -1;
4946
4947 static int
4948 dissect_spoolss_doc_info_ctr(tvbuff_t *tvb, int offset, packet_info *pinfo,
4949                              proto_tree *tree, char *drep)
4950 {
4951         proto_item *item;
4952         proto_tree *subtree;
4953
4954         item = proto_tree_add_text(
4955                 tree, tvb, offset, 0, "Document info container");
4956
4957         subtree = proto_item_add_subtree(item, ett_DOC_INFO_CTR);
4958
4959         offset = dissect_ndr_uint32(
4960                 tvb, offset, pinfo, subtree, drep, hf_level, NULL);
4961
4962         offset = dissect_spoolss_doc_info(
4963                 tvb, offset, pinfo, subtree, drep);
4964
4965         return offset;
4966 }
4967
4968 /*
4969  * StartDocPrinter
4970  */
4971
4972 static int SpoolssStartDocPrinter_q(tvbuff_t *tvb, int offset,
4973                                     packet_info *pinfo, proto_tree *tree,
4974                                     char *drep)
4975 {
4976         e_ctx_hnd policy_hnd;
4977         char *pol_name;
4978
4979         /* Parse packet */
4980
4981         offset = dissect_nt_policy_hnd(
4982                 tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
4983                 FALSE, FALSE);
4984
4985         dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
4986                              pinfo->fd->num);
4987
4988         if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
4989                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
4990                                 pol_name);
4991
4992         offset = dissect_spoolss_doc_info_ctr(tvb, offset, pinfo, tree, drep);
4993
4994         return offset;
4995 }
4996
4997 static int SpoolssStartDocPrinter_r(tvbuff_t *tvb, int offset,
4998                                     packet_info *pinfo, proto_tree *tree,
4999                                     char *drep)
5000 {
5001         /* Parse packet */
5002
5003         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
5004                                     hf_job_id, NULL);
5005
5006         offset = dissect_doserror(
5007                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
5008
5009         return offset;
5010 }
5011
5012 /*
5013  * EndDocPrinter
5014  */
5015
5016 static int SpoolssEndDocPrinter_q(tvbuff_t *tvb, int offset,
5017                                   packet_info *pinfo, proto_tree *tree,
5018                                   char *drep)
5019 {
5020         e_ctx_hnd policy_hnd;
5021         char *pol_name;
5022
5023         /* Parse packet */
5024
5025         offset = dissect_nt_policy_hnd(
5026                 tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
5027                 FALSE, FALSE);
5028
5029         dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
5030                              pinfo->fd->num);
5031
5032         if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
5033                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
5034                                 pol_name);
5035
5036
5037         return offset;
5038 }
5039
5040 static int SpoolssEndDocPrinter_r(tvbuff_t *tvb, int offset,
5041                                   packet_info *pinfo, proto_tree *tree,
5042                                   char *drep)
5043 {
5044         /* Parse packet */
5045
5046         offset = dissect_doserror(
5047                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
5048
5049         return offset;
5050 }
5051
5052 /*
5053  * WritePrinter
5054  */
5055
5056 static gint ett_writeprinter_buffer = -1;
5057
5058 static int hf_writeprinter_numwritten = -1;
5059
5060 static int SpoolssWritePrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
5061                                  proto_tree *tree, char *drep)
5062 {
5063         e_ctx_hnd policy_hnd;
5064         char *pol_name;
5065         guint32 size;
5066         proto_item *item;
5067         proto_tree *subtree;
5068
5069         /* Parse packet */
5070
5071         offset = dissect_nt_policy_hnd(
5072                 tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
5073                 FALSE, FALSE);
5074
5075         dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
5076                              pinfo->fd->num);
5077
5078         if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
5079                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
5080                                 pol_name);
5081
5082         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
5083                                     hf_buffer_size, &size);
5084
5085         if (check_col(pinfo->cinfo, COL_INFO))
5086                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %d bytes", size);
5087
5088         item = proto_tree_add_text(tree, tvb, offset, 0, "Buffer");
5089
5090         subtree = proto_item_add_subtree(item, ett_writeprinter_buffer);
5091
5092         offset = dissect_ndr_uint8s(tvb, offset, pinfo, subtree, drep,
5093                                     hf_buffer_data, size, NULL);
5094
5095         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
5096                                     hf_buffer_size, NULL);
5097
5098         proto_item_set_len(item, size + 4);
5099
5100         return offset;
5101 }
5102
5103 static int SpoolssWritePrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
5104                                  proto_tree *tree, char *drep)
5105 {
5106         guint32 size;
5107
5108         /* Parse packet */
5109
5110         offset = dissect_ndr_uint32(
5111                 tvb, offset, pinfo, tree, drep, hf_writeprinter_numwritten, 
5112                 &size);
5113
5114         if (check_col(pinfo->cinfo, COL_INFO))
5115                 col_append_fstr(
5116                         pinfo->cinfo, COL_INFO, ", %d bytes written", size);
5117
5118         offset = dissect_doserror(
5119                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
5120
5121         return offset;
5122 }
5123
5124 /*
5125  * DeletePrinterData
5126  */
5127
5128 static int SpoolssDeletePrinterData_q(tvbuff_t *tvb, int offset,
5129                                       packet_info *pinfo, proto_tree *tree,
5130                                       char *drep)
5131 {
5132         char *value_name;
5133
5134         proto_tree_add_uint_hidden(
5135                 tree, hf_printerdata, tvb, offset, 0, 1);
5136
5137         /* Parse packet */
5138
5139         offset = dissect_nt_policy_hnd(
5140                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
5141                 FALSE, FALSE);
5142
5143         offset = dissect_ndr_cvstring(
5144                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
5145                 hf_printerdata_value, TRUE, &value_name);
5146
5147         if (check_col(pinfo->cinfo, COL_INFO))
5148                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
5149
5150         g_free(value_name);
5151
5152         return offset;
5153 }
5154
5155 static int SpoolssDeletePrinterData_r(tvbuff_t *tvb, int offset,
5156                                       packet_info *pinfo, proto_tree *tree,
5157                                       char *drep)
5158 {
5159         proto_tree_add_uint_hidden(
5160                 tree, hf_printerdata, tvb, offset, 0, 1);
5161
5162         /* Parse packet */
5163
5164         offset = dissect_doserror(
5165                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
5166
5167         return offset;
5168 }
5169
5170
5171 /*
5172  * DRIVER_INFO_1
5173  */
5174
5175 static gint ett_DRIVER_INFO_1 = -1;
5176
5177 static int dissect_DRIVER_INFO_1(tvbuff_t *tvb, int offset,
5178                                  packet_info *pinfo, proto_tree *tree,
5179                                  char *drep)
5180 {
5181         proto_item *item;
5182         proto_tree *subtree;
5183         int struct_start = offset;
5184
5185         item = proto_tree_add_text(
5186                 tree, tvb, offset, 0, "Driver info level 1");
5187
5188         subtree = proto_item_add_subtree(item, ett_DRIVER_INFO_1);
5189
5190         offset = dissect_spoolss_relstr(
5191                 tvb, offset, pinfo, subtree, drep, hf_drivername,
5192                 struct_start, NULL);
5193
5194         return offset;
5195 }
5196
5197 /*
5198  * DRIVER_INFO_3
5199  */
5200
5201 static const value_string driverinfo_cversion_vals[] =
5202 {
5203         { 0, "Windows 95/98/Me" },
5204         { 2, "Windows NT 4.0" },
5205         { 3, "Windows 2000/XP" },
5206         { 0, NULL }
5207 };
5208
5209 static gint ett_DRIVER_INFO_3 = -1;
5210
5211 static int dissect_DRIVER_INFO_3(tvbuff_t *tvb, int offset,
5212                                  packet_info *pinfo, proto_tree *tree,
5213                                  char *drep)
5214 {
5215         proto_item *item;
5216         proto_tree *subtree;
5217         int struct_start = offset;
5218
5219         item = proto_tree_add_text(
5220                 tree, tvb, offset, 0, "Driver info level 3");
5221
5222         subtree = proto_item_add_subtree(item, ett_DRIVER_INFO_3);
5223
5224         offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
5225                                     hf_driverinfo_cversion, NULL);
5226
5227         offset = dissect_spoolss_relstr(
5228                 tvb, offset, pinfo, subtree, drep, hf_drivername,
5229                 struct_start, NULL);
5230
5231         offset = dissect_spoolss_relstr(
5232                 tvb, offset, pinfo, subtree, drep, hf_architecture,
5233                 struct_start, NULL);
5234
5235         offset = dissect_spoolss_relstr(
5236                 tvb, offset, pinfo, subtree, drep, hf_driverpath,
5237                 struct_start, NULL);
5238
5239         offset = dissect_spoolss_relstr(
5240                 tvb, offset, pinfo, subtree, drep, hf_datafile,
5241                 struct_start, NULL);
5242
5243         offset = dissect_spoolss_relstr(
5244                 tvb, offset, pinfo, subtree, drep, hf_configfile,
5245                 struct_start, NULL);
5246
5247         offset = dissect_spoolss_relstr(
5248                 tvb, offset, pinfo, subtree, drep, hf_helpfile,
5249                 struct_start, NULL);
5250
5251         offset = dissect_spoolss_relstrarray(
5252                 tvb, offset, pinfo, subtree, drep, hf_dependentfiles,
5253                 struct_start, NULL);
5254
5255         offset = dissect_spoolss_relstr(
5256                 tvb, offset, pinfo, subtree, drep, hf_monitorname,
5257                 struct_start, NULL);
5258
5259         offset = dissect_spoolss_relstr(
5260                 tvb, offset, pinfo, subtree, drep, hf_defaultdatatype,
5261                 struct_start, NULL);
5262
5263         return offset;
5264 }
5265
5266 /*
5267  * EnumPrinterDrivers
5268  */
5269
5270 static int SpoolssEnumPrinterDrivers_q(tvbuff_t *tvb, int offset,
5271                                        packet_info *pinfo, proto_tree *tree,
5272                                        char *drep)
5273 {
5274         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
5275         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
5276         guint32 level;
5277
5278         /* Parse packet */
5279
5280         offset = dissect_ndr_str_pointer_item(
5281                 tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
5282                 "Name", hf_servername, 0);
5283
5284         offset = dissect_ndr_str_pointer_item(
5285                 tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
5286                 "Environment", hf_servername, 0);
5287
5288         offset = dissect_ndr_uint32(
5289                 tvb, offset, pinfo, tree, drep, hf_level, &level);
5290
5291         dcv->private_data = (void *)level;
5292
5293         if (check_col(pinfo->cinfo, COL_INFO))
5294                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
5295
5296         offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep, NULL);
5297
5298         offset = dissect_ndr_uint32(
5299                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
5300
5301         return offset;
5302 }
5303
5304 static int SpoolssEnumPrinterDrivers_r(tvbuff_t *tvb, int offset,
5305                                        packet_info *pinfo, proto_tree *tree,
5306                                        char *drep)
5307 {
5308         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
5309         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
5310         guint32 level = (guint32)dcv->private_data, num_drivers, i;
5311         int buffer_offset;
5312         BUFFER buffer;
5313
5314         /* Parse packet */
5315
5316         offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep,
5317                                         &buffer);
5318
5319         offset = dissect_ndr_uint32(
5320                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
5321
5322         offset = dissect_ndr_uint32(
5323                 tvb, offset, pinfo, tree, drep, hf_returned, 
5324                 &num_drivers);
5325
5326         buffer_offset = 0;
5327
5328         for (i = 0; i < num_drivers; i++) {
5329                 switch(level) {
5330                 case 1:
5331                         buffer_offset = dissect_DRIVER_INFO_1(
5332                                 buffer.tvb, buffer_offset, pinfo,
5333                                 buffer.tree, drep);
5334                         break;
5335                 case 3:
5336                         buffer_offset = dissect_DRIVER_INFO_3(
5337                                 buffer.tvb, buffer_offset, pinfo,
5338                                 buffer.tree, drep);
5339                         break;
5340                 default:
5341                         proto_tree_add_text(
5342                                 buffer.tree, buffer.tvb, buffer_offset, -1,
5343                                 "[Unknown driver info level %d]", level);
5344                         goto done;
5345                 }
5346         }
5347
5348 done:
5349         offset = dissect_doserror(
5350                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
5351
5352         return offset;
5353 }
5354
5355 /*
5356  * GetPrinterDriver2
5357  */
5358
5359 static int SpoolssGetPrinterDriver2_q(tvbuff_t *tvb, int offset,
5360                                       packet_info *pinfo, proto_tree *tree,
5361                                       char *drep)
5362 {
5363         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
5364         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
5365         e_ctx_hnd policy_hnd;
5366         char *pol_name;
5367         guint32 level;
5368
5369         /* Parse packet */
5370
5371         offset = dissect_nt_policy_hnd(
5372                 tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
5373                 FALSE, FALSE);
5374
5375         dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
5376                              pinfo->fd->num);
5377
5378         if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
5379                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
5380                                 pol_name);
5381
5382         offset = dissect_ndr_str_pointer_item(
5383                 tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
5384                 "Architecture", hf_architecture, 0);
5385
5386         offset = dissect_ndr_uint32(
5387                 tvb, offset, pinfo, tree, drep, hf_level, &level);
5388
5389         dcv->private_data = (void *)level;
5390
5391         if (check_col(pinfo->cinfo, COL_INFO))
5392                 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
5393
5394         offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep, NULL);
5395
5396         offset = dissect_ndr_uint32(
5397                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
5398
5399         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
5400                                     hf_clientmajorversion, NULL);
5401
5402         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
5403                                     hf_clientminorversion, NULL);
5404
5405         return offset;
5406 }
5407
5408 static int SpoolssGetPrinterDriver2_r(tvbuff_t *tvb, int offset,
5409                                       packet_info *pinfo, proto_tree *tree,
5410                                       char *drep)
5411 {
5412         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
5413         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
5414         guint32 level = (guint32)dcv->private_data;
5415         BUFFER buffer;
5416
5417         /* Parse packet */
5418
5419         offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep,
5420                                         &buffer);
5421
5422         if (buffer.tvb) {
5423                 switch(level) {
5424                 case 1:
5425                         dissect_DRIVER_INFO_1(
5426                                 buffer.tvb, 0, pinfo, buffer.tree, drep);
5427                         break;
5428                 case 3:
5429                         dissect_DRIVER_INFO_3(
5430                                 buffer.tvb, 0, pinfo, buffer.tree, drep);
5431                         break;
5432                 default:
5433                         proto_tree_add_text(
5434                                 buffer.tree, buffer.tvb, 0, -1,
5435                                 "[Unknown driver info level %d]", level);
5436                         break;
5437                 }
5438         }
5439
5440         offset = dissect_ndr_uint32(
5441                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
5442
5443         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
5444                                     hf_servermajorversion, NULL);
5445
5446         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
5447                                     hf_serverminorversion, NULL);
5448
5449         offset = dissect_doserror(
5450                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
5451
5452         return offset;
5453 }
5454
5455 static int
5456 dissect_notify_info_data_buffer(tvbuff_t *tvb, int offset, packet_info *pinfo,
5457                                 proto_tree *tree, char *drep)
5458 {
5459         guint32 len;
5460
5461         offset = dissect_ndr_uint32(
5462                 tvb, offset, pinfo, tree, drep,
5463                 hf_notify_info_data_buffer_len, &len);
5464
5465         offset = dissect_ndr_uint16s(
5466                 tvb, offset, pinfo, tree, drep,
5467                 hf_notify_info_data_buffer_data, len);
5468
5469         return offset;
5470 }
5471
5472 static void cb_notify_str_postprocess(packet_info *pinfo _U_, 
5473                                       proto_tree *tree _U_,
5474                                       proto_item *item, tvbuff_t *tvb, 
5475                                       int start_offset, int end_offset,
5476                                       void *callback_args)
5477 {
5478         gint levels, hf_index = GPOINTER_TO_INT(callback_args);
5479         guint32 len;
5480         char *s;
5481
5482         /* Align start_offset on 4-byte boundary. */
5483
5484         if (start_offset % 4)
5485                 start_offset += 4 - (start_offset % 4);
5486
5487         /* Get string length */
5488
5489         len = tvb_get_letohl(tvb, start_offset);
5490
5491         s = tvb_fake_unicode(
5492                 tvb, start_offset + 4, (end_offset - start_offset - 4) / 2, TRUE);
5493
5494         /* Append string to upper-level proto_items */
5495
5496         levels = 2;
5497
5498         if (levels > 0 && item && s && s[0]) {
5499                 proto_item_append_text(item, ": %s", s);
5500                 item = item->parent;
5501                 levels--;
5502                 if (levels > 0) {
5503                         proto_item_append_text(item, ": %s", s);
5504                         item = item->parent;
5505                         levels--;
5506                         while (levels > 0) {
5507                                 proto_item_append_text(item, " %s", s);
5508                                 item = item->parent;
5509                                 levels--;
5510                         }
5511                 }
5512         }
5513
5514         /* Add hidden field so filter brings up any notify data */
5515
5516         if (hf_index != -1)
5517                 proto_tree_add_string_hidden(
5518                         tree, hf_index, tvb, start_offset, len, s);
5519
5520         g_free(s);
5521 }
5522
5523 /* Return the hf_index for a printer notify field.  This is used to
5524    add a hidden string to the display so that filtering will bring
5525    up relevant notify data. */
5526
5527 static int
5528 printer_notify_hf_index(int field)
5529 {
5530         int result = -1;
5531
5532         switch(field) {
5533         case PRINTER_NOTIFY_SERVER_NAME:
5534                 result = hf_servername;
5535                 break;
5536         case PRINTER_NOTIFY_PRINTER_NAME:
5537                 result = hf_printername;
5538                 break;
5539         case PRINTER_NOTIFY_SHARE_NAME:
5540                 result = hf_sharename;
5541                 break;
5542         case PRINTER_NOTIFY_PORT_NAME:
5543                 result = hf_portname;
5544                 break;
5545         case PRINTER_NOTIFY_DRIVER_NAME:
5546                 result = hf_drivername;
5547                 break;
5548         case PRINTER_NOTIFY_COMMENT:
5549                 result = hf_printercomment;
5550                 break;
5551         case PRINTER_NOTIFY_LOCATION:
5552                 result = hf_printerlocation;
5553                 break;
5554         case PRINTER_NOTIFY_SEPFILE:
5555                 result = hf_sepfile;
5556                 break;
5557         case PRINTER_NOTIFY_PRINT_PROCESSOR:
5558                 result = hf_printprocessor;
5559                 break;
5560         case PRINTER_NOTIFY_PARAMETERS:
5561                 result = hf_parameters;
5562                 break;
5563         case PRINTER_NOTIFY_DATATYPE:
5564                 result = hf_parameters;
5565                 break;
5566         }
5567
5568         return result;
5569 }
5570
5571 static int
5572 job_notify_hf_index(int field)
5573 {
5574         int result = -1;
5575
5576         switch(field) {
5577         case JOB_NOTIFY_PRINTER_NAME:
5578                 result = hf_printername;
5579                 break;
5580         case JOB_NOTIFY_MACHINE_NAME:
5581                 result = hf_machinename;
5582                 break;
5583         case JOB_NOTIFY_PORT_NAME:
5584                 result = hf_portname;
5585                 break;
5586         case JOB_NOTIFY_USER_NAME:
5587                 result = hf_username;
5588                 break;
5589         case JOB_NOTIFY_NOTIFY_NAME:
5590                 result = hf_notifyname;
5591                 break;
5592         case JOB_NOTIFY_DATATYPE:
5593                 result = hf_datatype;
5594                 break;
5595         case JOB_NOTIFY_PRINT_PROCESSOR:
5596                 result = hf_printprocessor;
5597                 break;
5598         case JOB_NOTIFY_DRIVER_NAME:
5599                 result = hf_drivername;
5600                 break;
5601         case JOB_NOTIFY_DOCUMENT:
5602                 result = hf_documentname;
5603                 break;
5604         case JOB_NOTIFY_PRIORITY:
5605                 result = hf_job_priority;
5606                 break;
5607         case JOB_NOTIFY_POSITION:
5608                 result = hf_job_position;
5609                 break;
5610         case JOB_NOTIFY_TOTAL_PAGES:
5611                 result = hf_job_totalpages;
5612                 break;
5613         case JOB_NOTIFY_PAGES_PRINTED:
5614                 result = hf_job_pagesprinted;
5615                 break;
5616         case JOB_NOTIFY_TOTAL_BYTES:
5617                 result = hf_job_totalbytes;
5618                 break;
5619         case JOB_NOTIFY_BYTES_PRINTED:
5620                 result = hf_job_bytesprinted;
5621                 break;
5622         }
5623
5624         return result;
5625 }
5626
5627 static int
5628 dissect_NOTIFY_INFO_DATA_printer(tvbuff_t *tvb, int offset, packet_info *pinfo,
5629                                  proto_tree *tree, proto_item *item,
5630                                  char *drep, guint16 field)
5631 {
5632         guint32 value1;
5633
5634         switch (field) {
5635
5636                 /* String notify data */
5637
5638         case PRINTER_NOTIFY_SERVER_NAME:
5639         case PRINTER_NOTIFY_PRINTER_NAME:
5640         case PRINTER_NOTIFY_SHARE_NAME:
5641         case PRINTER_NOTIFY_DRIVER_NAME:
5642         case PRINTER_NOTIFY_COMMENT:
5643         case PRINTER_NOTIFY_LOCATION:
5644         case PRINTER_NOTIFY_SEPFILE:
5645         case PRINTER_NOTIFY_PRINT_PROCESSOR:
5646         case PRINTER_NOTIFY_PARAMETERS:
5647         case PRINTER_NOTIFY_DATATYPE:
5648         case PRINTER_NOTIFY_PORT_NAME:
5649
5650                 offset = dissect_ndr_uint32(
5651                         tvb, offset, pinfo, tree, drep,
5652                         hf_notify_info_data_bufsize, &value1);
5653
5654                 offset = dissect_ndr_pointer_cb(
5655                         tvb, offset, pinfo, tree, drep,
5656                         dissect_notify_info_data_buffer,
5657                         NDR_POINTER_UNIQUE, "String",
5658                         hf_notify_info_data_buffer,
5659                         cb_notify_str_postprocess, 
5660                         GINT_TO_POINTER(printer_notify_hf_index(field)));
5661
5662                 break;
5663
5664         case PRINTER_NOTIFY_ATTRIBUTES:
5665
5666                 /* Value 1 is the printer attributes */
5667
5668                 offset = dissect_printer_attributes(
5669                         tvb, offset, pinfo, tree, drep);
5670
5671                 offset = dissect_ndr_uint32(
5672                         tvb, offset, pinfo, NULL, drep,
5673                         hf_notify_info_data_value2, NULL);
5674
5675                 break;
5676
5677         case PRINTER_NOTIFY_STATUS: {
5678                 guint32 status;
5679
5680                 /* Value 1 is the printer status */
5681
5682                 offset = dissect_ndr_uint32(
5683                         tvb, offset, pinfo, tree, drep,
5684                         hf_printer_status, &status);
5685
5686                 offset = dissect_ndr_uint32(
5687                         tvb, offset, pinfo, NULL, drep,
5688                         hf_notify_info_data_value2, NULL);
5689
5690                 proto_item_append_text(
5691                         item, ": %s", 
5692                         val_to_str(status, printer_status_vals, "Unknown"));
5693
5694                 break;
5695         }
5696
5697                 /* Unknown notify data */
5698
5699         case PRINTER_NOTIFY_SECURITY_DESCRIPTOR: /* Secdesc */
5700         case PRINTER_NOTIFY_DEVMODE: /* Devicemode */
5701
5702                 offset = dissect_ndr_uint32(
5703                         tvb, offset, pinfo, tree, drep,
5704                         hf_notify_info_data_bufsize, &value1);
5705
5706                 offset = dissect_ndr_pointer(
5707                         tvb, offset, pinfo, tree, drep,
5708                         dissect_notify_info_data_buffer,
5709                         NDR_POINTER_UNIQUE, "Buffer",
5710                         hf_notify_info_data_buffer);
5711
5712                 break;
5713
5714         default:
5715                 offset = dissect_ndr_uint32(
5716                         tvb, offset, pinfo, tree, drep,
5717                         hf_notify_info_data_value1, NULL);
5718
5719                 offset = dissect_ndr_uint32(
5720                         tvb, offset, pinfo, tree, drep,
5721                         hf_notify_info_data_value2, NULL);
5722
5723                 break;
5724         }
5725         return offset;
5726 }
5727
5728 static void notify_job_time_cb(packet_info *pinfo, proto_tree *tree _U_, 
5729                                proto_item *item, tvbuff_t *tvb _U_, 
5730                                int start_offset _U_, int end_offset _U_, 
5731                                void *callback_args _U_)
5732 {
5733         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
5734         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
5735         char *str = (char *)dcv->private_data;
5736
5737         /* Append job string stored in dcv->private_data by 
5738            dissect_SYSTEM_TIME_ptr() in the current item as well
5739            as the parent. */
5740
5741         proto_item_append_text(item, ": %s", str);
5742
5743         if (item)
5744                 proto_item_append_text(item->parent, ": %s", str);
5745 }
5746
5747 static int
5748 dissect_NOTIFY_INFO_DATA_job(tvbuff_t *tvb, int offset, packet_info *pinfo,
5749                              proto_tree *tree, proto_item *item, char *drep, 
5750                              guint16 field)
5751 {
5752         guint32 value1;
5753
5754         switch (field) {
5755
5756                 /* String notify data */
5757
5758         case JOB_NOTIFY_PRINTER_NAME:
5759         case JOB_NOTIFY_MACHINE_NAME:
5760         case JOB_NOTIFY_PORT_NAME:
5761         case JOB_NOTIFY_USER_NAME:
5762         case JOB_NOTIFY_NOTIFY_NAME:
5763         case JOB_NOTIFY_DATATYPE:
5764         case JOB_NOTIFY_PRINT_PROCESSOR:
5765         case JOB_NOTIFY_PARAMETERS:
5766         case JOB_NOTIFY_DRIVER_NAME:
5767         case JOB_NOTIFY_STATUS_STRING:
5768         case JOB_NOTIFY_DOCUMENT:
5769
5770                 offset = dissect_ndr_uint32(
5771                         tvb, offset, pinfo, tree, drep,
5772                         hf_notify_info_data_bufsize, &value1);
5773
5774                 offset = dissect_ndr_pointer_cb(
5775                         tvb, offset, pinfo, tree, drep,
5776                         dissect_notify_info_data_buffer,
5777                         NDR_POINTER_UNIQUE, "String",
5778                         hf_notify_info_data_buffer,
5779                         cb_notify_str_postprocess, 
5780                         GINT_TO_POINTER(job_notify_hf_index(field)));
5781
5782                 break;
5783
5784         case JOB_NOTIFY_STATUS:
5785                 offset = dissect_job_status(
5786                         tvb, offset, pinfo, tree, drep);
5787
5788                 offset = dissect_ndr_uint32(
5789                         tvb, offset, pinfo, NULL, drep,
5790                         hf_notify_info_data_value2, NULL);
5791
5792                 break;
5793
5794         case JOB_NOTIFY_SUBMITTED:
5795
5796                 /* SYSTEM_TIME */
5797
5798                 offset = dissect_ndr_uint32(
5799                         tvb, offset, pinfo, tree, drep,
5800                         hf_notify_info_data_buffer_len, NULL);
5801
5802                 offset = dissect_ndr_pointer_cb(
5803                         tvb, offset, pinfo, tree, drep,
5804                         dissect_SYSTEM_TIME_ptr, NDR_POINTER_UNIQUE,
5805                         "Time submitted", -1, notify_job_time_cb, NULL);
5806
5807                 break;
5808
5809         case JOB_NOTIFY_PRIORITY:
5810         case JOB_NOTIFY_POSITION:
5811         case JOB_NOTIFY_TOTAL_PAGES:
5812         case JOB_NOTIFY_PAGES_PRINTED:
5813         case JOB_NOTIFY_TOTAL_BYTES:
5814         case JOB_NOTIFY_BYTES_PRINTED: {
5815                 guint32 value;
5816
5817                 offset = dissect_ndr_uint32(
5818                         tvb, offset, pinfo, tree, drep,
5819                         hf_notify_info_data_value1, &value);
5820
5821                 offset = dissect_ndr_uint32(
5822                         tvb, offset, pinfo, tree, drep,
5823                         hf_notify_info_data_value2, NULL);
5824
5825                 proto_item_append_text(item, ": %d", value);
5826
5827                 proto_tree_add_uint_hidden(
5828                         tree, job_notify_hf_index(field), tvb,
5829                         offset, 4, value);
5830
5831                 break;
5832         }
5833
5834                 /* Unknown notify data */
5835
5836         case JOB_NOTIFY_DEVMODE:
5837
5838                 offset = dissect_ndr_uint32(
5839                         tvb, offset, pinfo, tree, drep,
5840                         hf_notify_info_data_bufsize, &value1);
5841
5842                 offset = dissect_ndr_pointer(
5843                         tvb, offset, pinfo, tree, drep,
5844                         dissect_notify_info_data_buffer,
5845                         NDR_POINTER_UNIQUE, "Buffer",
5846                         hf_notify_info_data_buffer);
5847
5848                 break;
5849
5850         default:
5851                 offset = dissect_ndr_uint32(
5852                         tvb, offset, pinfo, tree, drep,
5853                         hf_notify_info_data_value1, NULL);
5854
5855                 offset = dissect_ndr_uint32(
5856                         tvb, offset, pinfo, tree, drep,
5857                         hf_notify_info_data_value2, NULL);
5858         }
5859         return offset;
5860 }
5861
5862 static gint ett_NOTIFY_INFO_DATA;
5863
5864 static int
5865 dissect_NOTIFY_INFO_DATA(tvbuff_t *tvb, int offset, packet_info *pinfo,
5866                          proto_tree *tree, char *drep)
5867 {
5868         proto_item *item;
5869         proto_tree *subtree;
5870         guint32 count;
5871         guint16 type, field;
5872         char *field_string;
5873
5874         item = proto_tree_add_text(tree, tvb, offset, 0, "%s", "");
5875
5876         subtree = proto_item_add_subtree(item, ett_NOTIFY_INFO_DATA);
5877
5878         offset = dissect_ndr_uint16(
5879                 tvb, offset, pinfo, subtree, drep,
5880                 hf_notify_info_data_type, &type);
5881
5882         offset = dissect_notify_field(
5883                 tvb, offset, pinfo, subtree, drep, type, &field);
5884
5885         switch(type) {
5886         case PRINTER_NOTIFY_TYPE:
5887                 field_string = val_to_str(
5888                         field, printer_notify_option_data_vals, 
5889                         "Unknown (%d)");
5890                 break;
5891         case JOB_NOTIFY_TYPE:
5892                 field_string = val_to_str(
5893                         field, job_notify_option_data_vals, 
5894                         "Unknown (%d)");
5895                 break;
5896         default:
5897                 field_string = "Unknown field";
5898                 break;
5899         }
5900
5901         proto_item_append_text(
5902                 item, "%s, %s",
5903                 val_to_str(type, printer_notify_types, "Unknown (%d)"),
5904                 field_string);
5905
5906         offset = dissect_ndr_uint32(
5907                 tvb, offset, pinfo, subtree, drep,
5908                 hf_notify_info_data_count, &count);
5909
5910         offset = dissect_ndr_uint32(
5911                 tvb, offset, pinfo, subtree, drep,
5912                 hf_notify_info_data_id, NULL);
5913
5914         offset = dissect_ndr_uint32(
5915                 tvb, offset, pinfo, subtree, drep,
5916                 hf_notify_info_data_count, NULL);
5917
5918         /* The value here depends on (type, field) */
5919
5920         switch (type) {
5921         case PRINTER_NOTIFY_TYPE:
5922                 offset = dissect_NOTIFY_INFO_DATA_printer(
5923                         tvb, offset, pinfo, subtree, item, drep, field);
5924                 break;
5925         case JOB_NOTIFY_TYPE:
5926                 offset = dissect_NOTIFY_INFO_DATA_job(
5927                         tvb, offset, pinfo, subtree, item, drep, field);
5928                 break;
5929         default:
5930                 proto_tree_add_text(
5931                         tree, tvb, offset, 0,
5932                         "[Unknown notify type %d]", type);
5933                 break;
5934         }
5935
5936         return offset;
5937 }
5938
5939 static int
5940 dissect_NOTIFY_INFO(tvbuff_t *tvb, int offset, packet_info *pinfo,
5941                     proto_tree *tree, char *drep)
5942 {
5943         dcerpc_info *di = pinfo->private_data;
5944         guint32 count;
5945
5946         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
5947                                     hf_notify_info_version, NULL);
5948
5949         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
5950                                     hf_notify_info_flags, NULL);
5951
5952         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
5953                                     hf_notify_info_count, &count);
5954
5955         if (!di->conformant_run && check_col(pinfo->cinfo, COL_INFO))
5956                 col_append_fstr(
5957                         pinfo->cinfo, COL_INFO, ", %d %s", count,
5958                         notify_plural(count));
5959
5960         offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
5961                                      dissect_NOTIFY_INFO_DATA);
5962
5963         return offset;
5964 }
5965
5966 /*
5967  * RFNPCNEX
5968  */
5969
5970 static int SpoolssRFNPCNEX_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
5971                              proto_tree *tree, char *drep)
5972 {
5973         guint32 changeid;
5974
5975         /* Parse packet */
5976
5977         offset = dissect_nt_policy_hnd(
5978                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
5979                 FALSE, FALSE);
5980
5981         offset = dissect_ndr_uint32(
5982                 tvb, offset, pinfo, tree, drep, hf_rrpcn_changelow, &changeid);
5983
5984         if (check_col(pinfo->cinfo, COL_INFO))
5985                 col_append_fstr(
5986                         pinfo->cinfo, COL_INFO, ", changeid %d", changeid);
5987
5988         offset = dissect_ndr_pointer(
5989                 tvb, offset, pinfo, tree, drep,
5990                 dissect_NOTIFY_OPTIONS_ARRAY_CTR, NDR_POINTER_UNIQUE,
5991                 "Notify Options Array Container", -1);
5992
5993         return offset;
5994 }
5995
5996 static int SpoolssRFNPCNEX_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
5997                              proto_tree *tree, char *drep)
5998 {
5999         /* Parse packet */
6000
6001         offset = dissect_ndr_pointer(
6002                 tvb, offset, pinfo, tree, drep,
6003                 dissect_NOTIFY_INFO, NDR_POINTER_UNIQUE,
6004                 "Notify Info", -1);
6005
6006         offset = dissect_doserror(
6007                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
6008
6009         return offset;
6010 }
6011
6012 /*
6013  * RRPCN
6014  */
6015
6016 static int SpoolssRRPCN_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
6017                           proto_tree *tree, char *drep)
6018 {
6019         guint32 changeid;
6020
6021         /* Parse packet */
6022
6023         offset = dissect_nt_policy_hnd(
6024                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
6025                 FALSE, FALSE);
6026
6027         offset = dissect_ndr_uint32(
6028                 tvb, offset, pinfo, tree, drep, hf_rrpcn_changelow, &changeid);
6029
6030         if (check_col(pinfo->cinfo, COL_INFO))
6031                 col_append_fstr(
6032                         pinfo->cinfo, COL_INFO, ", changeid %d", changeid);
6033
6034         offset = dissect_ndr_uint32(
6035                 tvb, offset, pinfo, tree, drep, hf_rrpcn_changehigh, NULL);
6036
6037         offset = dissect_ndr_uint32(
6038                 tvb, offset, pinfo, tree, drep, hf_rrpcn_unk0, NULL);
6039
6040         offset = dissect_ndr_uint32(
6041                 tvb, offset, pinfo, tree, drep, hf_rrpcn_unk1, NULL);
6042
6043         offset = dissect_ndr_pointer(
6044                 tvb, offset, pinfo, tree, drep,
6045                 dissect_NOTIFY_INFO, NDR_POINTER_UNIQUE,
6046                 "Notify Info", -1);
6047
6048         /* Notify info */
6049
6050         return offset;
6051 }
6052
6053 static int SpoolssRRPCN_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
6054                           proto_tree *tree, char *drep)
6055 {
6056         /* Parse packet */
6057
6058         offset = dissect_ndr_uint32(
6059                 tvb, offset, pinfo, tree, drep, hf_rrpcn_unk0, NULL);
6060
6061         offset = dissect_doserror(
6062                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
6063
6064         return offset;
6065 }
6066
6067 /*
6068  * ReplyClosePrinter
6069  */
6070
6071 static int SpoolssReplyClosePrinter_q(tvbuff_t *tvb, int offset,
6072                                       packet_info *pinfo, proto_tree *tree,
6073                                       char *drep)
6074 {
6075         /* Parse packet */
6076
6077         offset = dissect_nt_policy_hnd(
6078                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
6079                 FALSE, TRUE);
6080
6081         return offset;
6082 }
6083
6084 static int SpoolssReplyClosePrinter_r(tvbuff_t *tvb, int offset,
6085                                       packet_info *pinfo, proto_tree *tree,
6086                                       char *drep)
6087 {
6088         /* Parse packet */
6089
6090         offset = dissect_nt_policy_hnd(
6091                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
6092                 FALSE, FALSE);
6093
6094         offset = dissect_doserror(
6095                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
6096
6097         return offset;
6098 }
6099
6100 /*
6101  * FCPN
6102  */
6103
6104 static int SpoolssFCPN_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
6105                         proto_tree *tree, char *drep)
6106 {
6107         /* Parse packet */
6108
6109         offset = dissect_nt_policy_hnd(
6110                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
6111                 FALSE, FALSE);
6112
6113         return offset;
6114 }
6115
6116 static int SpoolssFCPN_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
6117                         proto_tree *tree, char *drep)
6118 {
6119         /* Parse packet */
6120
6121         offset = dissect_doserror(
6122                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
6123
6124         return offset;
6125 }
6126
6127 /*
6128  * RouterReplyPrinter
6129  */
6130
6131 static int hf_routerreplyprinter_condition = -1;
6132 static int hf_routerreplyprinter_unknown1 = -1;
6133 static int hf_routerreplyprinter_changeid = -1;
6134
6135 static int SpoolssRouterReplyPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
6136                                        proto_tree *tree, char *drep)
6137 {
6138         /* Parse packet */
6139
6140         offset = dissect_nt_policy_hnd(
6141                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
6142                 FALSE, FALSE);
6143
6144         offset = dissect_ndr_uint32(
6145                 tvb, offset, pinfo, tree, drep,
6146                 hf_routerreplyprinter_condition, NULL);
6147
6148         offset = dissect_ndr_uint32(
6149                 tvb, offset, pinfo, tree, drep,
6150                 hf_routerreplyprinter_unknown1, NULL);
6151
6152         offset = dissect_ndr_uint32(
6153                 tvb, offset, pinfo, tree, drep,
6154                 hf_routerreplyprinter_changeid, NULL);
6155
6156         return offset;
6157 }
6158
6159 static int SpoolssRouterReplyPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
6160                                        proto_tree *tree, char *drep)
6161 {
6162         /* Parse packet */
6163
6164         offset = dissect_doserror(
6165                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
6166
6167         return offset;
6168 }
6169
6170 static int hf_keybuffer_size = -1;
6171 static int hf_keybuffer_data = -1;
6172
6173 static int
6174 dissect_spoolss_keybuffer(tvbuff_t *tvb, int offset, packet_info *pinfo,
6175                           proto_tree *tree, char *drep)
6176 {
6177         dcerpc_info *di = pinfo->private_data;
6178         guint32 size;
6179         int end_offset;
6180
6181         if (di->conformant_run)
6182                 return offset;
6183
6184         /* Dissect size and data */
6185
6186         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
6187                                     hf_keybuffer_size, &size);
6188
6189         end_offset = offset + (size*2);
6190         if (end_offset < offset) {
6191                 /*
6192                  * Overflow - make the end offset one past the end of
6193                  * the packet data, so we throw an exception (as the
6194                  * size is almost certainly too big).
6195                  */
6196                 end_offset = tvb_reported_length_remaining(tvb, offset) + 1;
6197         }
6198
6199         while (offset < end_offset)
6200                 offset = dissect_spoolss_uint16uni(
6201                         tvb, offset, pinfo, tree, drep, NULL, "Key");
6202
6203         return offset;
6204 }
6205
6206
6207 static int SpoolssEnumPrinterKey_q(tvbuff_t *tvb, int offset, 
6208                                    packet_info *pinfo, proto_tree *tree, 
6209                                    char *drep)
6210 {
6211         char *key_name;
6212
6213         /* Parse packet */
6214
6215         offset = dissect_nt_policy_hnd(
6216                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
6217                 FALSE, FALSE);
6218
6219         offset = dissect_ndr_cvstring(
6220                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
6221                 hf_printerdata_key, TRUE, &key_name);
6222
6223         if (check_col(pinfo->cinfo, COL_INFO)) {
6224                 char *kn = key_name;
6225
6226                 if (!key_name[0])
6227                         kn = "\"\"";
6228
6229                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", kn);
6230         }
6231
6232         g_free(key_name);
6233
6234         offset = dissect_ndr_uint32(
6235                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
6236
6237         return offset;
6238 }
6239
6240 static int SpoolssEnumPrinterKey_r(tvbuff_t *tvb, int offset, 
6241                                    packet_info *pinfo, proto_tree *tree, 
6242                                    char *drep)
6243 {
6244         /* Parse packet */
6245
6246         offset = dissect_spoolss_keybuffer(tvb, offset, pinfo, tree, drep);
6247
6248         offset = dissect_ndr_uint32(
6249                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
6250
6251         offset = dissect_doserror(
6252                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
6253
6254         return offset;
6255 }
6256
6257 static int hf_enumprinterdataex_num_values = -1;
6258 static int hf_enumprinterdataex_name_offset = -1;
6259 static int hf_enumprinterdataex_name_len = -1;
6260 static int hf_enumprinterdataex_name = -1;
6261 static int hf_enumprinterdataex_val_type = -1;
6262 static int hf_enumprinterdataex_val_offset = -1;
6263 static int hf_enumprinterdataex_val_len = -1;
6264 static int hf_enumprinterdataex_val_dword_low = -1;
6265 static int hf_enumprinterdataex_val_dword_high = -1;
6266 static int hf_enumprinterdataex_val_sz = -1;
6267
6268 static int SpoolssEnumPrinterDataEx_q(tvbuff_t *tvb, int offset, 
6269                                       packet_info *pinfo, proto_tree *tree, 
6270                                       char *drep)
6271 {
6272         char *key_name;
6273
6274         proto_tree_add_uint_hidden(
6275                 tree, hf_printerdata, tvb, offset, 0, 1);
6276
6277         /* Parse packet */
6278
6279         offset = dissect_nt_policy_hnd(
6280                 tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
6281                 FALSE, FALSE);
6282
6283         offset = dissect_ndr_cvstring(
6284                 tvb, offset, pinfo, tree, drep, sizeof(guint16),
6285                 hf_printerdata_key, TRUE, &key_name);
6286
6287         if (check_col(pinfo->cinfo, COL_INFO))
6288                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", key_name);
6289
6290         g_free(key_name);
6291
6292         offset = dissect_ndr_uint32(
6293                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
6294
6295         return offset;
6296 }
6297
6298 static gint ett_printer_enumdataex_value = -1;
6299
6300 static int
6301 dissect_spoolss_printer_enum_values(tvbuff_t *tvb, int offset, 
6302                                     packet_info *pinfo, proto_tree *tree,
6303                                     char *drep)
6304 {
6305         guint32 start = offset;
6306         guint32 name_offset, name_len, val_offset, val_len, val_type;
6307         char *name;
6308         proto_item *item;
6309         proto_tree *subtree;
6310
6311         /* Get offset of value name */
6312
6313         offset = dissect_ndr_uint32(
6314                 tvb, offset, pinfo, NULL, drep,
6315                 hf_enumprinterdataex_name_offset, &name_offset);
6316
6317         offset = dissect_ndr_uint32(
6318                 tvb, offset, pinfo, NULL, drep,
6319                 hf_enumprinterdataex_name_len, &name_len);
6320
6321         dissect_spoolss_uint16uni(
6322                 tvb, start + name_offset, pinfo, NULL, drep, 
6323                 &name, "Name");
6324
6325         item = proto_tree_add_text(tree, tvb, offset, 0, "Name: ");
6326
6327         subtree = proto_item_add_subtree(item, ett_printer_enumdataex_value);
6328
6329         proto_item_append_text(item, name);
6330                                
6331         proto_tree_add_text(
6332                 subtree, tvb, offset - 8, 4, "Name offset: %d", name_offset);
6333
6334         proto_tree_add_text(
6335                 subtree, tvb, offset - 4, 4, "Name len: %d", name_len);
6336
6337         proto_tree_add_text(
6338                 subtree, tvb, start + name_offset, (strlen(name) + 1) * 2,
6339                 "Name: %s", name);
6340
6341         offset = dissect_ndr_uint32(
6342                 tvb, offset, pinfo, subtree, drep, hf_printerdata_type, 
6343                 &val_type);
6344
6345         offset = dissect_ndr_uint32(
6346                 tvb, offset, pinfo, subtree, drep,
6347                 hf_enumprinterdataex_val_offset, &val_offset);
6348
6349         offset = dissect_ndr_uint32(
6350                 tvb, offset, pinfo, subtree, drep,
6351                 hf_enumprinterdataex_val_len, &val_len);
6352
6353         switch(val_type) {
6354         case DCERPC_REG_DWORD: {
6355                 guint32 value;
6356                 guint16 low, high;
6357                 int offset2 = offset + val_offset;
6358
6359                 /* Needs to be broken into two 16-byte ints because it may
6360                    not be aligned. */
6361
6362                 offset2 = dissect_ndr_uint16(
6363                         tvb, offset2, pinfo, subtree, drep,
6364                         hf_enumprinterdataex_val_dword_low, &low);
6365
6366                 offset2 = dissect_ndr_uint16(
6367                         tvb, offset2, pinfo, subtree, drep,
6368                         hf_enumprinterdataex_val_dword_high, &high);
6369
6370                 value = (high << 16) | low;
6371
6372                 proto_tree_add_text(subtree, tvb, start + val_offset, 4, 
6373                                     "Value: %d", value);
6374
6375                 proto_item_append_text(item, ", Value: %d", value);
6376
6377                 break;
6378         }
6379         case DCERPC_REG_SZ: {
6380                 char *value;
6381
6382                 dissect_spoolss_uint16uni(
6383                         tvb, start + val_offset, pinfo, subtree, drep, 
6384                         &value, "Value");
6385
6386                 proto_item_append_text(item, ", Value: %s", value);
6387
6388                 g_free(value);
6389
6390                 break;
6391         }
6392         case DCERPC_REG_BINARY:
6393
6394                 /* FIXME: nicer way to display this */
6395
6396                 proto_tree_add_text(subtree, tvb, start + val_offset, val_len,
6397                                     "Value: <binary data>");
6398                 break;
6399
6400         default:
6401                 proto_tree_add_text(subtree, tvb, start + val_offset, val_len,
6402                                     "%s: unknown type %d", name, val_type);
6403         }
6404
6405         g_free(name);
6406
6407         return offset;
6408 }
6409
6410 static gint ett_PRINTER_DATA_CTR;
6411
6412 static int SpoolssEnumPrinterDataEx_r(tvbuff_t *tvb, int offset, 
6413                                    packet_info *pinfo, proto_tree *tree, 
6414                                    char *drep)
6415 {
6416         guint32 size, num_values;
6417
6418         proto_tree_add_uint_hidden(
6419                 tree, hf_printerdata, tvb, offset, 0, 1);
6420
6421         /* Parse packet */
6422
6423         offset = dissect_ndr_uint32(
6424                 tvb, offset, pinfo, tree, drep,
6425                 hf_buffer_size, &size);
6426
6427         dissect_ndr_uint32(
6428                 tvb, offset + size + 4, pinfo, NULL, drep, hf_returned,
6429                 &num_values);
6430
6431         if (size) {
6432                 proto_item *item;
6433                 proto_tree *subtree;
6434                 int offset2 = offset;
6435                 guint32 i;
6436
6437                 item = proto_tree_add_text(
6438                         tree, tvb, offset, 0, "Printer data");
6439
6440                 subtree = proto_item_add_subtree(item, ett_PRINTER_DATA_CTR);
6441
6442                 for (i=0; i < num_values; i++)
6443                         offset2 = dissect_spoolss_printer_enum_values(
6444                                 tvb, offset2, pinfo, subtree, drep);
6445         }
6446
6447         offset += size;
6448
6449         offset = dissect_ndr_uint32(
6450                 tvb, offset, pinfo, tree, drep, hf_needed, NULL);
6451
6452         offset = dissect_ndr_uint32(
6453                 tvb, offset, pinfo, tree, drep, hf_returned, NULL);
6454
6455         offset = dissect_doserror(
6456                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
6457
6458         return offset;
6459 }
6460
6461 #if 0
6462
6463 /* Templates for new subdissectors */
6464
6465 /*
6466  * FOO
6467  */
6468
6469 static int SpoolssFoo_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
6470                         proto_tree *tree, char *drep)
6471 {
6472         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
6473         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
6474
6475         /* Parse packet */
6476
6477         return offset;
6478 }
6479
6480 static int SpoolssFoo_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
6481                         proto_tree *tree, char *drep)
6482 {
6483         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
6484         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
6485
6486         /* Parse packet */
6487
6488         offset = dissect_doserror(
6489                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
6490
6491         return offset;
6492 }
6493
6494 #endif
6495
6496 /*
6497  * List of subdissectors for this pipe.
6498  */
6499
6500 static dcerpc_sub_dissector dcerpc_spoolss_dissectors[] = {
6501         { SPOOLSS_ENUMPRINTERS, "EnumPrinters",
6502           SpoolssEnumPrinters_q, SpoolssEnumPrinters_r },
6503         { SPOOLSS_OPENPRINTER, "OpenPrinter",
6504           NULL, SpoolssGeneric_r },
6505         { SPOOLSS_SETJOB, "SetJob",
6506           SpoolssSetJob_q, SpoolssSetJob_r },
6507         { SPOOLSS_GETJOB, "GetJob",
6508           SpoolssGetJob_q, SpoolssGetJob_r },
6509         { SPOOLSS_ENUMJOBS, "EnumJobs",
6510           SpoolssEnumJobs_q, SpoolssEnumJobs_r },
6511         { SPOOLSS_ADDPRINTER, "AddPrinter",
6512           NULL, SpoolssGeneric_r },
6513         { SPOOLSS_DELETEPRINTER, "DeletePrinter",
6514           SpoolssDeletePrinter_q, SpoolssDeletePrinter_r },
6515         { SPOOLSS_SETPRINTER, "SetPrinter",
6516           SpoolssSetPrinter_q, SpoolssSetPrinter_r },
6517         { SPOOLSS_GETPRINTER, "GetPrinter",
6518           SpoolssGetPrinter_q, SpoolssGetPrinter_r },
6519         { SPOOLSS_ADDPRINTERDRIVER, "AddPrinterDriver",
6520           NULL, SpoolssAddPrinterDriver_r },
6521         { SPOOLSS_ENUMPRINTERDRIVERS, "EnumPrinterDrivers",
6522           SpoolssEnumPrinterDrivers_q, SpoolssEnumPrinterDrivers_r },
6523         { SPOOLSS_GETPRINTERDRIVER, "GetPrinterDriver",
6524           NULL, SpoolssGeneric_r },
6525         { SPOOLSS_GETPRINTERDRIVERDIRECTORY, "GetPrinterDriverDirectory",
6526           NULL, SpoolssGeneric_r },
6527         { SPOOLSS_DELETEPRINTERDRIVER, "DeletePrinterDriver",
6528           NULL, SpoolssGeneric_r },
6529         { SPOOLSS_ADDPRINTPROCESSOR, "AddPrintProcessor",
6530           NULL, SpoolssGeneric_r },
6531         { SPOOLSS_ENUMPRINTPROCESSORS, "EnumPrintProcessor",
6532           NULL, SpoolssGeneric_r },
6533         { SPOOLSS_GETPRINTPROCESSORDIRECTORY, "GetPrintProcessorDirectory",
6534           NULL, SpoolssGeneric_r },
6535         { SPOOLSS_STARTDOCPRINTER, "StartDocPrinter",
6536           SpoolssStartDocPrinter_q, SpoolssStartDocPrinter_r },
6537         { SPOOLSS_STARTPAGEPRINTER, "StartPagePrinter",
6538           SpoolssStartPagePrinter_q, SpoolssStartPagePrinter_r },
6539         { SPOOLSS_WRITEPRINTER, "WritePrinter",
6540           SpoolssWritePrinter_q, SpoolssWritePrinter_r },
6541         { SPOOLSS_ENDPAGEPRINTER, "EndPagePrinter",
6542           SpoolssEndPagePrinter_q, SpoolssEndPagePrinter_r },
6543         { SPOOLSS_ABORTPRINTER, "AbortPrinter",
6544           NULL, SpoolssGeneric_r },
6545         { SPOOLSS_READPRINTER, "ReadPrinter",
6546           NULL, SpoolssGeneric_r },
6547         { SPOOLSS_ENDDOCPRINTER, "EndDocPrinter",
6548           SpoolssEndDocPrinter_q, SpoolssEndDocPrinter_r },
6549         { SPOOLSS_ADDJOB, "AddJob",
6550           NULL, SpoolssGeneric_r },
6551         { SPOOLSS_SCHEDULEJOB, "ScheduleJob",
6552           NULL, SpoolssGeneric_r },
6553         { SPOOLSS_GETPRINTERDATA, "GetPrinterData",
6554           SpoolssGetPrinterData_q, SpoolssGetPrinterData_r },
6555         { SPOOLSS_SETPRINTERDATA, "SetPrinterData",
6556           SpoolssSetPrinterData_q, SpoolssSetPrinterData_r },
6557         { SPOOLSS_WAITFORPRINTERCHANGE, "WaitForPrinterChange",
6558           NULL, SpoolssGeneric_r },
6559         { SPOOLSS_CLOSEPRINTER, "ClosePrinter",
6560           SpoolssClosePrinter_q, SpoolssClosePrinter_r },
6561         { SPOOLSS_ADDFORM, "AddForm",
6562           SpoolssAddForm_q, SpoolssAddForm_r },
6563         { SPOOLSS_DELETEFORM, "DeleteForm",
6564           SpoolssDeleteForm_q, SpoolssDeleteForm_r },
6565         { SPOOLSS_GETFORM, "GetForm",
6566           SpoolssGetForm_q, SpoolssGetForm_r },
6567         { SPOOLSS_SETFORM, "SetForm",
6568           SpoolssSetForm_q, SpoolssSetForm_r },
6569         { SPOOLSS_ENUMFORMS, "EnumForms",
6570           SpoolssEnumForms_q, SpoolssEnumForms_r },
6571         { SPOOLSS_ENUMPORTS, "EnumPorts",
6572           NULL, SpoolssGeneric_r },
6573         { SPOOLSS_ENUMMONITORS, "EnumMonitors",
6574           NULL, SpoolssGeneric_r },
6575         { SPOOLSS_ADDPORT, "AddPort",
6576           NULL, SpoolssGeneric_r },
6577         { SPOOLSS_CONFIGUREPORT, "ConfigurePort",
6578           NULL, SpoolssGeneric_r },
6579         { SPOOLSS_DELETEPORT, "DeletePort",
6580           NULL, SpoolssGeneric_r },
6581         { SPOOLSS_CREATEPRINTERIC, "CreatePrinterIC",
6582           NULL, SpoolssGeneric_r },
6583         { SPOOLSS_PLAYGDISCRIPTONPRINTERIC, "PlayDiscriptOnPrinterIC",
6584           NULL, SpoolssGeneric_r },
6585         { SPOOLSS_DELETEPRINTERIC, "DeletePrinterIC",
6586           NULL, SpoolssGeneric_r },
6587         { SPOOLSS_ADDPRINTERCONNECTION, "AddPrinterConnection",
6588           NULL, SpoolssGeneric_r },
6589         { SPOOLSS_DELETEPRINTERCONNECTION, "DeletePrinterConnection",
6590           NULL, SpoolssGeneric_r },
6591         { SPOOLSS_PRINTERMESSAGEBOX, "PrinterMessageBox",
6592           NULL, SpoolssGeneric_r },
6593         { SPOOLSS_ADDMONITOR, "AddMonitor",
6594           NULL, SpoolssGeneric_r },
6595         { SPOOLSS_DELETEMONITOR, "DeleteMonitor",
6596           NULL, SpoolssGeneric_r },
6597         { SPOOLSS_DELETEPRINTPROCESSOR, "DeletePrintProcessor",
6598           NULL, SpoolssGeneric_r },
6599         { SPOOLSS_ADDPRINTPROVIDER, "AddPrintProvider",
6600           NULL, SpoolssGeneric_r },
6601         { SPOOLSS_DELETEPRINTPROVIDER, "DeletePrintProvider",
6602           NULL, SpoolssGeneric_r },
6603         { SPOOLSS_ENUMPRINTPROCDATATYPES, "EnumPrintProcDataTypes",
6604           NULL, SpoolssGeneric_r },
6605         { SPOOLSS_RESETPRINTER, "ResetPrinter",
6606           NULL, SpoolssGeneric_r },
6607         { SPOOLSS_GETPRINTERDRIVER2, "GetPrinterDriver2",
6608           SpoolssGetPrinterDriver2_q, SpoolssGetPrinterDriver2_r },
6609         { SPOOLSS_FINDFIRSTPRINTERCHANGENOTIFICATION,
6610           "FindFirstPrinterChangeNotification",
6611           NULL, SpoolssGeneric_r },
6612         { SPOOLSS_FINDNEXTPRINTERCHANGENOTIFICATION,
6613           "FindNextPrinterChangeNotification",
6614           NULL, SpoolssGeneric_r },
6615         { SPOOLSS_FCPN, "FCPN",
6616           SpoolssFCPN_q, SpoolssFCPN_r },
6617         { SPOOLSS_ROUTERFINDFIRSTPRINTERNOTIFICATIONOLD,
6618           "RouterFindFirstPrinterNotificationOld",
6619           NULL, SpoolssGeneric_r },
6620         { SPOOLSS_REPLYOPENPRINTER, "ReplyOpenPrinter",
6621           SpoolssReplyOpenPrinter_q, SpoolssReplyOpenPrinter_r },
6622         { SPOOLSS_ROUTERREPLYPRINTER, "RouterReplyPrinter",
6623           SpoolssRouterReplyPrinter_q, SpoolssRouterReplyPrinter_r },
6624         { SPOOLSS_REPLYCLOSEPRINTER, "ReplyClosePrinter",
6625           SpoolssReplyClosePrinter_q, SpoolssReplyClosePrinter_r },
6626         { SPOOLSS_ADDPORTEX, "AddPortEx",
6627           NULL, SpoolssGeneric_r },
6628         { SPOOLSS_REMOTEFINDFIRSTPRINTERCHANGENOTIFICATION,
6629           "RemoteFindFirstPrinterChangeNotification",
6630           NULL, SpoolssGeneric_r },
6631         { SPOOLSS_SPOOLERINIT, "SpoolerInit",
6632           NULL, SpoolssGeneric_r },
6633         { SPOOLSS_RESETPRINTEREX, "ResetPrinterEx",
6634           NULL, SpoolssGeneric_r },
6635         { SPOOLSS_RFFPCNEX, "RFFPCNEX",
6636           SpoolssRFFPCNEX_q, SpoolssRFFPCNEX_r },
6637         { SPOOLSS_RRPCN, "RRPCN",
6638           SpoolssRRPCN_q, SpoolssRRPCN_r },
6639         { SPOOLSS_RFNPCNEX, "RFNPCNEX",
6640           SpoolssRFNPCNEX_q, SpoolssRFNPCNEX_r },
6641         { SPOOLSS_OPENPRINTEREX, "OpenPrinterEx",
6642           SpoolssOpenPrinterEx_q, SpoolssOpenPrinterEx_r },
6643         { SPOOLSS_ADDPRINTEREX, "AddPrinterEx",
6644           NULL, SpoolssAddPrinterEx_r },
6645         { SPOOLSS_ENUMPRINTERDATA, "EnumPrinterData",
6646           SpoolssEnumPrinterData_q, SpoolssEnumPrinterData_r },
6647         { SPOOLSS_DELETEPRINTERDATA, "DeletePrinterData",
6648           SpoolssDeletePrinterData_q, SpoolssDeletePrinterData_r },
6649         { SPOOLSS_GETPRINTERDATAEX, "GetPrinterDataEx",
6650           SpoolssGetPrinterDataEx_q, SpoolssGetPrinterDataEx_r },
6651         { SPOOLSS_SETPRINTERDATAEX, "SetPrinterDataEx",
6652           SpoolssSetPrinterDataEx_q, SpoolssSetPrinterDataEx_r },
6653         { SPOOLSS_ENUMPRINTERDATAEX, "EnumPrinterDataEx",
6654           SpoolssEnumPrinterDataEx_q, SpoolssEnumPrinterDataEx_r },
6655         { SPOOLSS_ENUMPRINTERKEY, "EnumPrinterKey",
6656           SpoolssEnumPrinterKey_q, SpoolssEnumPrinterKey_r },
6657         { SPOOLSS_DELETEPRINTERDATAEX, "DeletePrinterDataEx",
6658           NULL, SpoolssGeneric_r },
6659         { SPOOLSS_DELETEPRINTERDRIVEREX, "DeletePrinterDriverEx",
6660           NULL, SpoolssGeneric_r },
6661         { SPOOLSS_ADDPRINTERDRIVEREX, "AddPrinterDriverEx",
6662           NULL, SpoolssGeneric_r },
6663
6664         { 0, NULL, NULL, NULL },
6665 };
6666
6667 /*
6668  * Dissector initialisation function
6669  */
6670
6671 /* Protocol registration */
6672
6673 static int proto_dcerpc_spoolss = -1;
6674 static gint ett_dcerpc_spoolss = -1;
6675
6676 static const value_string spoolss_opnum_vals[] = {
6677         { SPOOLSS_ENUMPRINTERS, "EnumPrinters" },
6678         { SPOOLSS_OPENPRINTER, "OpenPrinter" },
6679         { SPOOLSS_SETJOB, "SetJob" },
6680         { SPOOLSS_GETJOB, "GetJob" },
6681         { SPOOLSS_ENUMJOBS, "EnumJobs" },
6682         { SPOOLSS_ADDPRINTER, "AddPrinter" },
6683         { SPOOLSS_DELETEPRINTER, "DeletePrinter" },
6684         { SPOOLSS_SETPRINTER, "SetPrinter" },
6685         { SPOOLSS_GETPRINTER, "GetPrinter" },
6686         { SPOOLSS_ADDPRINTERDRIVER, "AddPrinterDriver" },
6687         { SPOOLSS_ENUMPRINTERDRIVERS, "EnumPrinterDrivers" },
6688         { SPOOLSS_GETPRINTERDRIVER, "GetPrinterDriver" },
6689         { SPOOLSS_GETPRINTERDRIVERDIRECTORY, "GetPrinterDriverDirectory" },
6690         { SPOOLSS_DELETEPRINTERDRIVER, "DeletePrinterDriver" },
6691         { SPOOLSS_ADDPRINTPROCESSOR, "AddPrintProcessor" },
6692         { SPOOLSS_ENUMPRINTPROCESSORS, "EnumPrintProcessor" },
6693         { SPOOLSS_GETPRINTPROCESSORDIRECTORY, "GetPrintProcessorDirectory" },
6694         { SPOOLSS_STARTDOCPRINTER, "StartDocPrinter" },
6695         { SPOOLSS_STARTPAGEPRINTER, "StartPagePrinter" },
6696         { SPOOLSS_WRITEPRINTER, "WritePrinter" },
6697         { SPOOLSS_ENDPAGEPRINTER, "EndPagePrinter" },
6698         { SPOOLSS_ABORTPRINTER, "AbortPrinter" },
6699         { SPOOLSS_READPRINTER, "ReadPrinter" },
6700         { SPOOLSS_ENDDOCPRINTER, "EndDocPrinter" },
6701         { SPOOLSS_ADDJOB, "AddJob" },
6702         { SPOOLSS_SCHEDULEJOB, "ScheduleJob" },
6703         { SPOOLSS_GETPRINTERDATA, "GetPrinterData" },
6704         { SPOOLSS_SETPRINTERDATA, "SetPrinterData" },
6705         { SPOOLSS_WAITFORPRINTERCHANGE, "WaitForPrinterChange" },
6706         { SPOOLSS_CLOSEPRINTER, "ClosePrinter" },
6707         { SPOOLSS_ADDFORM, "AddForm" },
6708         { SPOOLSS_DELETEFORM, "DeleteForm" },
6709         { SPOOLSS_GETFORM, "GetForm" },
6710         { SPOOLSS_SETFORM, "SetForm" },
6711         { SPOOLSS_ENUMFORMS, "EnumForms" },
6712         { SPOOLSS_ENUMPORTS, "EnumPorts" },
6713         { SPOOLSS_ENUMMONITORS, "EnumMonitors" },
6714         { SPOOLSS_ADDPORT, "AddPort" },
6715         { SPOOLSS_CONFIGUREPORT, "ConfigurePort" },
6716         { SPOOLSS_DELETEPORT, "DeletePort" },
6717         { SPOOLSS_CREATEPRINTERIC, "CreatePrinterIC" },
6718         { SPOOLSS_PLAYGDISCRIPTONPRINTERIC, "PlayDiscriptOnPrinterIC" },
6719         { SPOOLSS_DELETEPRINTERIC, "DeletePrinterIC" },
6720         { SPOOLSS_ADDPRINTERCONNECTION, "AddPrinterConnection" },
6721         { SPOOLSS_DELETEPRINTERCONNECTION, "DeletePrinterConnection" },
6722         { SPOOLSS_PRINTERMESSAGEBOX, "PrinterMessageBox" },
6723         { SPOOLSS_ADDMONITOR, "AddMonitor" },
6724         { SPOOLSS_DELETEMONITOR, "DeleteMonitor" },
6725         { SPOOLSS_DELETEPRINTPROCESSOR, "DeletePrintProcessor" },
6726         { SPOOLSS_ADDPRINTPROVIDER, "AddPrintProvider" },
6727         { SPOOLSS_DELETEPRINTPROVIDER, "DeletePrintProvider" },
6728         { SPOOLSS_ENUMPRINTPROCDATATYPES, "EnumPrintProcDataTypes" },
6729         { SPOOLSS_RESETPRINTER, "ResetPrinter" },
6730         { SPOOLSS_GETPRINTERDRIVER2, "GetPrinterDriver2" },
6731         { SPOOLSS_FINDFIRSTPRINTERCHANGENOTIFICATION, 
6732           "FindNextPrinterChangeNotification" },
6733         { SPOOLSS_FINDNEXTPRINTERCHANGENOTIFICATION, 
6734           "FindNextPrinterChangeNotification" },
6735         { SPOOLSS_FCPN, "FCPN" },
6736         { SPOOLSS_ROUTERFINDFIRSTPRINTERNOTIFICATIONOLD, 
6737           "RouterFindFirstPrinterNotificationOld" },
6738         { SPOOLSS_REPLYOPENPRINTER, "ReplyOpenPrinter" },
6739         { SPOOLSS_ROUTERREPLYPRINTER, "RouterReplyPrinter" },
6740         { SPOOLSS_REPLYCLOSEPRINTER, "ReplyClosePrinter" },
6741         { SPOOLSS_ADDPORTEX, "AddPortEx" },
6742         { SPOOLSS_REMOTEFINDFIRSTPRINTERCHANGENOTIFICATION, 
6743           "RemoteFindFirstPrinterChangeNotification" },
6744         { SPOOLSS_SPOOLERINIT, "SpoolerInit" },
6745         { SPOOLSS_RESETPRINTEREX, "ResetPrinterEx" },
6746         { SPOOLSS_RFFPCNEX, "RFFPCNEX" },
6747         { SPOOLSS_RRPCN, "RRPCN" },
6748         { SPOOLSS_RFNPCNEX, "RFNPCNEX" },
6749         { SPOOLSS_OPENPRINTEREX, "OpenPrinterEx" },
6750         { SPOOLSS_ADDPRINTEREX, "AddPrinterEx" },
6751         { SPOOLSS_ENUMPRINTERDATA, "EnumPrinterData" },
6752         { SPOOLSS_DELETEPRINTERDATA, "DeletePrinterData" },
6753         { SPOOLSS_GETPRINTERDATAEX, "GetPrinterDataEx" },
6754         { SPOOLSS_SETPRINTERDATAEX, "SetPrinterDataEx" },
6755         { SPOOLSS_ENUMPRINTERDATAEX, "EnumPrinterDataEx" },
6756         { SPOOLSS_ENUMPRINTERKEY, "EnumPrinterKey" },
6757         { SPOOLSS_DELETEPRINTERDATAEX, "DeletePrinterDataEx" },
6758         { SPOOLSS_DELETEPRINTERDRIVEREX, "DeletePrinterDriverEx" },
6759         { SPOOLSS_ADDPRINTERDRIVEREX, "AddPrinterDriverEx" },
6760         { 0, NULL }
6761 };
6762
6763 void
6764 proto_register_dcerpc_spoolss(void)
6765 {
6766         static hf_register_info hf[] = {
6767
6768                 /* GetPrinterDriver2 */
6769
6770                 { &hf_clientmajorversion,
6771                   { "Client major version", "spoolss.clientmajorversion", FT_UINT32, BASE_DEC,
6772                     NULL, 0x0, "Client printer driver major version", HFILL }},
6773                 { &hf_clientminorversion,
6774                   { "Client minor version", "spoolss.clientminorversion", FT_UINT32, BASE_DEC,
6775                     NULL, 0x0, "Client printer driver minor version", HFILL }},
6776                 { &hf_servermajorversion,
6777                   { "Server major version", "spoolss.servermajorversion", FT_UINT32, BASE_DEC,
6778                     NULL, 0x0, "Server printer driver major version", HFILL }},
6779                 { &hf_serverminorversion,
6780                   { "Server minor version", "spoolss.serverminorversion", FT_UINT32, BASE_DEC,
6781                     NULL, 0x0, "Server printer driver minor version", HFILL }},
6782                 { &hf_driverpath,
6783                   { "Driver path", "spoolss.driverpath", FT_STRING, BASE_NONE,
6784                     NULL, 0, "Driver path", HFILL }},
6785                 { &hf_datafile,
6786                   { "Data file", "spoolss.datafile", FT_STRING, BASE_NONE,
6787                     NULL, 0, "Data file", HFILL }},
6788                 { &hf_configfile,
6789                   { "Config file", "spoolss.configfile", FT_STRING, BASE_NONE,
6790                     NULL, 0, "Printer name", HFILL }},
6791                 { &hf_helpfile,
6792                   { "Help file", "spoolss.helpfile", FT_STRING, BASE_NONE,
6793                     NULL, 0, "Help file", HFILL }},
6794                 { &hf_monitorname,
6795                   { "Monitor name", "spoolss.monitorname", FT_STRING, BASE_NONE,
6796                     NULL, 0, "Monitor name", HFILL }},
6797                 { &hf_defaultdatatype,
6798                   { "Default data type", "spoolss.defaultdatatype", FT_STRING, BASE_NONE,
6799                     NULL, 0, "Default data type", HFILL }},
6800                 { &hf_driverinfo_cversion,
6801                   { "Driver version", "spoolss.driverversion", FT_UINT32, BASE_DEC,
6802                     VALS(driverinfo_cversion_vals), 0, "Printer name", HFILL }},
6803                 { &hf_dependentfiles,
6804                   { "Dependent files", "spoolss.dependentfiles", FT_STRING, BASE_NONE,
6805                     NULL, 0, "Dependent files", HFILL }},
6806
6807                 { &hf_printer_status,
6808                   { "Status", "spoolss.printer_status", FT_UINT32, BASE_DEC,
6809                    VALS(printer_status_vals), 0, "Status", HFILL }},
6810
6811                 /* Setprinter RPC */
6812
6813                 { &hf_setprinter_cmd,
6814                   { "Command", "spoolss.setprinter_cmd", FT_UINT32, BASE_DEC,
6815                    VALS(setprinter_cmd_vals), 0, "Command", HFILL }},
6816
6817                 /* Enumprinters */
6818
6819                 { &hf_enumprinters_flags,
6820                   { "Flags", "spoolss.enumprinters.flags",
6821                     FT_UINT32, BASE_HEX, NULL, 0, "Flags", HFILL }},
6822
6823                 { &hf_enumprinters_flags_local,
6824                   { "Enum local", "spoolss.enumprinters.flags.enum_local",
6825                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
6826                     PRINTER_ENUM_LOCAL, "Enum local", HFILL }},
6827
6828                 { &hf_enumprinters_flags_name,
6829                   { "Enum name", "spoolss.enumprinters.flags.enum_name",
6830                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
6831                     PRINTER_ENUM_NAME, "Enum name", HFILL }},
6832
6833                 { &hf_enumprinters_flags_shared,
6834                   { "Enum shared", "spoolss.enumprinters.flags.enum_shared",
6835                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
6836                     PRINTER_ENUM_SHARED, "Enum shared", HFILL }},
6837
6838                 { &hf_enumprinters_flags_default,
6839                   { "Enum default", "spoolss.enumprinters.flags.enum_default",
6840                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
6841                     PRINTER_ENUM_DEFAULT, "Enum default", HFILL }},
6842
6843                 { &hf_enumprinters_flags_connections,
6844                   { "Enum connections", "spoolss.enumprinters.flags.enum_connections",
6845                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
6846                     PRINTER_ENUM_CONNECTIONS, "Enum connections", HFILL }},
6847
6848                 { &hf_enumprinters_flags_network,
6849                   { "Enum network", "spoolss.enumprinters.flags.enum_network",
6850                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
6851                     PRINTER_ENUM_NETWORK, "Enum network", HFILL }},
6852
6853                 { &hf_enumprinters_flags_remote,
6854                   { "Enum remote", "spoolss.enumprinters.flags.enum_remote",
6855                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
6856                     PRINTER_ENUM_REMOTE, "Enum remote", HFILL }},
6857
6858                 /* GetPrinter */
6859
6860                 { &hf_start_time,
6861                   { "Start time", "spoolss.start_time",
6862                     FT_UINT32, BASE_DEC, NULL, 0, "Start time", HFILL }},
6863
6864                 { &hf_end_time,
6865                   { "End time", "spoolss.end_time",
6866                     FT_UINT32, BASE_DEC, NULL, 0, "End time", HFILL }},
6867
6868                 { &hf_elapsed_time,
6869                   { "Elapsed time", "spoolss.elapsed_time",
6870                     FT_UINT32, BASE_DEC, NULL, 0, "Elapsed time", HFILL }},
6871
6872                 /* 
6873                  * New hf index values 
6874                  */
6875
6876                 { &hf_opnum,
6877                   { "Operation", "spoolss.opnum", FT_UINT16, BASE_DEC,
6878                     VALS(spoolss_opnum_vals), 0x0, "Operation", HFILL }},
6879
6880                 { &hf_hnd,
6881                   { "Context handle", "spoolss.hnd", FT_BYTES, BASE_NONE,
6882                     NULL, 0x0, "SPOOLSS policy handle", HFILL }},
6883
6884                 { &hf_rc,
6885                   { "Return code", "spoolss.rc", FT_UINT32, BASE_HEX,
6886                     VALS(DOS_errors), 0x0, "SPOOLSS return code", HFILL }},
6887
6888                 { &hf_offered,
6889                   { "Offered", "spoolss.offered", FT_UINT32, BASE_DEC,
6890                     NULL, 0x0, "Size of buffer offered in this request", 
6891                     HFILL }},
6892
6893                 { &hf_needed,
6894                   { "Needed", "spoolss.needed", FT_UINT32, BASE_DEC,
6895                     NULL, 0x0, "Size of buffer required for request", HFILL }},
6896
6897                 { &hf_returned,
6898                   { "Returned", "spoolss.returned", FT_UINT32, BASE_DEC,
6899                     NULL, 0x0, "Number of items returned", HFILL }},
6900
6901                 { &hf_buffer_size,
6902                   { "Buffer size", "spoolss.buffer.size", FT_UINT32, BASE_DEC,
6903                     NULL, 0x0, "Size of buffer", HFILL }},
6904
6905                 { &hf_buffer_data,
6906                   { "Buffer data", "spoolss.buffer.data", FT_BYTES, BASE_HEX,
6907                     NULL, 0x0, "Contents of buffer", HFILL }},
6908
6909                 { &hf_offset,
6910                   { "Offset", "spoolss.offset", FT_UINT32, BASE_DEC,
6911                     NULL, 0x0, "Offset of data", HFILL }},
6912
6913                 { &hf_level,
6914                   { "Info level", "spoolss.enumjobs.level", FT_UINT32, 
6915                     BASE_DEC, NULL, 0x0, "Info level", HFILL }},
6916
6917
6918                 { &hf_printername,
6919                   { "Printer name", "spoolss.printername", FT_STRING, 
6920                     BASE_NONE, NULL, 0, "Printer name", HFILL }},
6921
6922                 { &hf_machinename,
6923                   { "Machine name", "spoolss.machinename", FT_STRING, 
6924                     BASE_NONE, NULL, 0, "Machine name", HFILL }},
6925
6926                 { &hf_notifyname,
6927                   { "Notify name", "spoolss.notifyname", FT_STRING, 
6928                     BASE_NONE, NULL, 0, "Notify name", HFILL }},
6929
6930                 { &hf_printerdesc,
6931                   { "Printer description", "spoolss.printerdesc", FT_STRING, 
6932                     BASE_NONE, NULL, 0, "Printer description", HFILL }},
6933
6934                 { &hf_printercomment,
6935                   { "Printer comment", "spoolss.printercomment", FT_STRING, 
6936                     BASE_NONE, NULL, 0, "Printer comment", HFILL }},
6937
6938                 { &hf_servername,
6939                   { "Server name", "spoolss.servername", FT_STRING, BASE_NONE,
6940                     NULL, 0, "Server name", HFILL }},
6941
6942                 { &hf_sharename,
6943                   { "Share name", "spoolss.sharename", FT_STRING, BASE_NONE,
6944                     NULL, 0, "Share name", HFILL }},
6945
6946                 { &hf_portname,
6947                   { "Port name", "spoolss.portname", FT_STRING, BASE_NONE,
6948                     NULL, 0, "Port name", HFILL }},
6949
6950                 { &hf_printerlocation,
6951                   { "Printer location", "spoolss.printerlocation", FT_STRING, 
6952                     BASE_NONE, NULL, 0, "Printer location", HFILL }},
6953
6954                 { &hf_architecture,
6955                   { "Architecture name", "spoolss.architecture", FT_STRING, 
6956                     BASE_NONE, NULL, 0, "Architecture name", HFILL }},
6957
6958                 { &hf_drivername,
6959                   { "Driver name", "spoolss.drivername", FT_STRING, BASE_NONE,
6960                     NULL, 0, "Driver name", HFILL }},
6961
6962                 { &hf_username,
6963                   { "User name", "spoolss.username", FT_STRING, BASE_NONE,
6964                     NULL, 0, "User name", HFILL }},
6965
6966                 { &hf_documentname,
6967                   { "Document name", "spoolss.document", FT_STRING, BASE_NONE,
6968                     NULL, 0, "Document name", HFILL }},
6969
6970                 { &hf_outputfile,
6971                   { "Output file", "spoolss.outputfile", FT_STRING, BASE_NONE,
6972                     NULL, 0, "Output File", HFILL }},
6973
6974                 { &hf_datatype,
6975                   { "Datatype", "spoolss.Datatype", FT_STRING, BASE_NONE,
6976                     NULL, 0, "Datatype", HFILL }},
6977
6978                 { &hf_textstatus,
6979                   { "Text status", "spoolss.textstatus", FT_STRING, BASE_NONE,
6980                     NULL, 0, "Text status", HFILL }},
6981
6982                 { &hf_sepfile,
6983                   { "Separator file", "spoolss.setpfile", FT_STRING, BASE_NONE,
6984                     NULL, 0, "Separator file", HFILL }},
6985
6986                 { &hf_parameters,
6987                   { "Parameters", "spoolss.parameters", FT_STRING, BASE_NONE,
6988                     NULL, 0, "Parameters", HFILL }},
6989
6990                 { &hf_printprocessor,
6991                   { "Print processor", "spoolss.printprocessor", FT_STRING, 
6992                     BASE_NONE, NULL, 0, "Print processor", HFILL }},
6993
6994                 /* Printer data */
6995
6996                 { &hf_printerdata,
6997                   { "Data", "spoolss.printerdata", FT_UINT32, 
6998                     BASE_HEX, NULL, 0, "Data", HFILL }},
6999
7000                 { &hf_printerdata_key,
7001                   { "Key", "spoolss.printerdata.key", FT_STRING, 
7002                     BASE_NONE, NULL, 0, "Printer data key", HFILL }},
7003
7004                 { &hf_printerdata_value,
7005                   { "Value", "spoolss.printerdata.value", 
7006                     FT_STRING, BASE_NONE, NULL, 0, "Printer data value", 
7007                     HFILL }},
7008
7009                 { &hf_printerdata_type,
7010                   { "Type", "spoolss.printerdata.type", 
7011                     FT_UINT32, BASE_DEC, VALS(reg_datatypes), 0, 
7012                     "Printer data type", HFILL }},
7013
7014                 { &hf_printerdata_size,
7015                   { "Size", "spoolss.printerdata.size", 
7016                     FT_UINT32, BASE_DEC, NULL, 0, "Printer data size", 
7017                     HFILL }},
7018
7019                 { &hf_printerdata_data,
7020                   { "Data", "spoolss.printerdata.data", FT_BYTES, BASE_HEX,
7021                     NULL, 0x0, "Printer data", HFILL }},
7022
7023                 { &hf_printerdata_data_dword,
7024                   { "DWORD data", "spoolss.printerdata.data.dword", 
7025                     FT_UINT32, BASE_HEX, NULL, 0, "DWORD data", HFILL }},
7026
7027                 { &hf_printerdata_data_sz,
7028                   { "String data", "spoolss.printerdata.data.sz", 
7029                     FT_STRING, BASE_NONE, NULL, 0, "String data", 
7030                     HFILL }},
7031
7032                 /* Devicemode */
7033
7034                 { &hf_devmodectr_size,
7035                   { "Devicemode ctr size", "spoolss.devicemodectr.size",
7036                     FT_UINT32, BASE_DEC, NULL, 0, "Devicemode ctr size", 
7037                     HFILL }},
7038
7039                 { &hf_devmode,
7040                   { "Devicemode", "spoolss.devmode", FT_UINT32, 
7041                     BASE_HEX, NULL, 0, "Devicemode", HFILL }},
7042
7043                 { &hf_devmode_size,
7044                   { "Size", "spoolss.devmode.size",
7045                     FT_UINT32, BASE_DEC, NULL, 0, "Size", HFILL }},
7046
7047                 { &hf_devmode_spec_version,
7048                   { "Spec version", "spoolss.devmode.spec_version",
7049                     FT_UINT16, BASE_DEC, VALS(devmode_specversion_vals), 
7050                     0, "Spec version", HFILL }},
7051
7052                 { &hf_devmode_driver_version,
7053                   { "Driver version", "spoolss.devmode.driver_version",
7054                     FT_UINT16, BASE_DEC, NULL, 0, "Driver version", HFILL }},
7055
7056                 { &hf_devmode_size2,
7057                   { "Size2", "spoolss.devmode.size2",
7058                     FT_UINT16, BASE_DEC, NULL, 0, "Size2", HFILL }},
7059
7060                 { &hf_devmode_driver_extra,
7061                   { "Driver extra", "spoolss.devmode.driver_extra",
7062                     FT_UINT16, BASE_DEC, NULL, 0, "Driver extra", HFILL }},
7063
7064                 { &hf_devmode_fields,
7065                   { "Fields", "spoolss.devmode.fields",
7066                     FT_UINT32, BASE_HEX, NULL, 0, "Fields", HFILL }},
7067
7068                 { &hf_devmode_orientation,
7069                   { "Orientation", "spoolss.devmode.orientation",
7070                     FT_UINT16, BASE_DEC, VALS(devmode_orientation_vals), 
7071                     0, "Orientation", HFILL }},
7072
7073                 { &hf_devmode_paper_size,
7074                   { "Paper size", "spoolss.devmode.paper_size",
7075                     FT_UINT16, BASE_DEC, VALS(devmode_papersize_vals), 
7076                     0, "Paper size", HFILL }},
7077
7078                 { &hf_devmode_paper_width,
7079                   { "Paper width", "spoolss.devmode.paper_width",
7080                     FT_UINT16, BASE_DEC, NULL, 0, "Paper width", HFILL }},
7081
7082                 { &hf_devmode_paper_length,
7083                   { "Paper length", "spoolss.devmode.paper_length",
7084                     FT_UINT16, BASE_DEC, NULL, 0, "Paper length", HFILL }},
7085
7086                 { &hf_devmode_scale,
7087                   { "Scale", "spoolss.devmode.scale",
7088                     FT_UINT16, BASE_DEC, NULL, 0, "Scale", HFILL }},
7089
7090                 { &hf_devmode_copies,
7091                   { "Copies", "spoolss.devmode.copies",
7092                     FT_UINT16, BASE_DEC, NULL, 0, "Copies", HFILL }},
7093
7094                 { &hf_devmode_default_source,
7095                   { "Default source", "spoolss.devmode.default_source",
7096                     FT_UINT16, BASE_DEC, VALS(devmode_papersource_vals), 
7097                     0, "Default source", HFILL }},
7098
7099                 { &hf_devmode_print_quality,
7100                   { "Print quality", "spoolss.devmode.print_quality",
7101                     FT_UINT16, BASE_DEC, VALS(devmode_printquality_vals), 
7102                     0, "Print quality", HFILL }},
7103
7104                 { &hf_devmode_color,
7105                   { "Color", "spoolss.devmode.color",
7106                     FT_UINT16, BASE_DEC, VALS(devmode_colour_vals), 0, 
7107                     "Color", HFILL }},
7108
7109                 { &hf_devmode_duplex,
7110                   { "Duplex", "spoolss.devmode.duplex",
7111                     FT_UINT16, BASE_DEC, VALS(devmode_duplex_vals), 0, 
7112                     "Duplex", HFILL }},
7113
7114                 { &hf_devmode_y_resolution,
7115                   { "Y resolution", "spoolss.devmode.y_resolution",
7116                     FT_UINT16, BASE_DEC, NULL, 0, "Y resolution", HFILL }},
7117
7118                 { &hf_devmode_tt_option,
7119                   { "TT option", "spoolss.devmode.tt_option",
7120                     FT_UINT16, BASE_DEC, VALS(devmode_ttoption_vals), 0, 
7121                     "TT option", HFILL }},
7122
7123                 { &hf_devmode_collate,
7124                   { "Collate", "spoolss.devmode.collate",
7125                     FT_UINT16, BASE_DEC, VALS(devmode_collate_vals), 0, 
7126                     "Collate", HFILL }},
7127
7128                 { &hf_devmode_log_pixels,
7129                   { "Log pixels", "spoolss.devmode.log_pixels",
7130                     FT_UINT16, BASE_DEC, NULL, 0, "Log pixels", HFILL }},
7131
7132                 { &hf_devmode_bits_per_pel,
7133                   { "Bits per pel", "spoolss.devmode.bits_per_pel",
7134                     FT_UINT32, BASE_DEC, NULL, 0, "Bits per pel", HFILL }},
7135
7136                 { &hf_devmode_pels_width,
7137                   { "Pels width", "spoolss.devmode.pels_width",
7138                     FT_UINT32, BASE_DEC, NULL, 0, "Pels width", HFILL }},
7139
7140                 { &hf_devmode_pels_height,
7141                   { "Pels height", "spoolss.devmode.pels_height",
7142                     FT_UINT32, BASE_DEC, NULL, 0, "Pels height", HFILL }},
7143
7144                 { &hf_devmode_display_flags,
7145                   { "Display flags", "spoolss.devmode.display_flags",
7146                     FT_UINT32, BASE_DEC, VALS(devmode_displayflags_vals), 0, 
7147                     "Display flags", HFILL }},
7148
7149                 { &hf_devmode_display_freq,
7150                   { "Display frequency", "spoolss.devmode.display_freq",
7151                     FT_UINT32, BASE_DEC, NULL, 0, "Display frequency", 
7152                     HFILL }},
7153
7154                 { &hf_devmode_icm_method,
7155                   { "ICM method", "spoolss.devmode.icm_method",
7156                     FT_UINT32, BASE_DEC, VALS(devmode_icmmethod_vals), 0, 
7157                     "ICM method", HFILL }},
7158
7159                 { &hf_devmode_icm_intent,
7160                   { "ICM intent", "spoolss.devmode.icm_intent",
7161                     FT_UINT32, BASE_DEC, VALS(devmode_icmintent_vals), 0, 
7162                     "ICM intent", HFILL }},
7163
7164                 { &hf_devmode_media_type,
7165                   { "Media type", "spoolss.devmode.media_type",
7166                     FT_UINT32, BASE_DEC, VALS(devmode_mediatype_vals), 0, 
7167                     "Media type", HFILL }},
7168
7169                 { &hf_devmode_dither_type,
7170                   { "Dither type", "spoolss.devmode.dither_type",
7171                     FT_UINT32, BASE_DEC, VALS(devmode_dithertype_vals), 0, 
7172                     "Dither type", HFILL }},
7173
7174                 { &hf_devmode_reserved1,
7175                   { "Reserved1", "spoolss.devmode.reserved1",
7176                     FT_UINT32, BASE_DEC, NULL, 0, "Reserved1", HFILL }},
7177
7178                 { &hf_devmode_reserved2,
7179                   { "Reserved2", "spoolss.devmode.reserved2",
7180                     FT_UINT32, BASE_DEC, NULL, 0, "Reserved2", HFILL }},
7181
7182                 { &hf_devmode_panning_width,
7183                   { "Panning width", "spoolss.devmode.panning_width",
7184                     FT_UINT32, BASE_DEC, NULL, 0, "Panning width", HFILL }},
7185
7186                 { &hf_devmode_panning_height,
7187                   { "Panning height", "spoolss.devmode.panning_height",
7188                     FT_UINT32, BASE_DEC, NULL, 0, "Panning height", HFILL }},
7189
7190                 { &hf_devmode_driver_extra_len,
7191                   { "Driver extra length", 
7192                     "spoolss.devmode.driver_extra_len",
7193                     FT_UINT32, BASE_DEC, NULL, 0, "Driver extra length", 
7194                     HFILL }},
7195
7196                 { &hf_devmode_driver_extra,
7197                   { "Driver extra", "spoolss.devmode.driver_extra",
7198                     FT_BYTES, BASE_HEX, NULL, 0, "Driver extra", HFILL }},
7199
7200                 /* Devicemode fields */
7201
7202                 { &hf_devmode_fields_orientation,
7203                   { "Orientation", "spoolss.devmode.fields.orientation",
7204                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7205                     DEVMODE_ORIENTATION, "Orientation", HFILL }},
7206
7207                 { &hf_devmode_fields_papersize,
7208                   { "Paper size", "spoolss.devmode.fields.paper_size",
7209                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7210                     DEVMODE_PAPERSIZE, "Paper size", HFILL }},
7211
7212                 { &hf_devmode_fields_paperlength,
7213                   { "Paper length", "spoolss.devmode.fields.paper_length",
7214                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7215                     DEVMODE_PAPERLENGTH, "Paper length", HFILL }},
7216
7217                 { &hf_devmode_fields_paperwidth,
7218                   { "Paper width", "spoolss.devmode.fields.paper_width",
7219                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7220                     DEVMODE_PAPERWIDTH, "Paper width", HFILL }},
7221
7222                 { &hf_devmode_fields_scale,
7223                   { "Scale", "spoolss.devmode.fields.scale",
7224                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7225                     DEVMODE_SCALE, "Scale", HFILL }},
7226
7227                 { &hf_devmode_fields_position,
7228                   { "Position", "spoolss.devmode.fields.position",
7229                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7230                     DEVMODE_POSITION, "Position", HFILL }},
7231
7232                 { &hf_devmode_fields_nup,
7233                   { "N-up", "spoolss.devmode.fields.nup",
7234                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7235                     DEVMODE_NUP, "N-up", HFILL }},
7236
7237                 { &hf_devmode_fields_copies,
7238                   { "Copies", "spoolss.devmode.fields.copies",
7239                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7240                     DEVMODE_COPIES, "Copies", HFILL }},
7241
7242                 { &hf_devmode_fields_defaultsource,
7243                   { "Default source", "spoolss.devmode.fields.default_source",
7244                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7245                     DEVMODE_DEFAULTSOURCE, "Default source", HFILL }},
7246
7247                 { &hf_devmode_fields_printquality,
7248                   { "Print quality", "spoolss.devmode.fields.print_quality",
7249                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7250                     DEVMODE_PRINTQUALITY, "Print quality", HFILL }},
7251
7252                 { &hf_devmode_fields_color,
7253                   { "Color", "spoolss.devmode.fields.color",
7254                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7255                     DEVMODE_COLOR, "Color", HFILL }},
7256
7257                 { &hf_devmode_fields_duplex,
7258                   { "Duplex", "spoolss.devmode.fields.duplex",
7259                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7260                     DEVMODE_DUPLEX, "Duplex", HFILL }},
7261
7262                 { &hf_devmode_fields_yresolution,
7263                   { "Y resolution", "spoolss.devmode.fields.y_resolution",
7264                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7265                     DEVMODE_YRESOLUTION, "Y resolution", HFILL }},
7266
7267                 { &hf_devmode_fields_ttoption,
7268                   { "TT option", "spoolss.devmode.fields.tt_option",
7269                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7270                     DEVMODE_TTOPTION, "TT option", HFILL }},
7271
7272                 { &hf_devmode_fields_collate,
7273                   { "Collate", "spoolss.devmode.fields.collate",
7274                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7275                     DEVMODE_COLLATE, "Collate", HFILL }},
7276
7277                 { &hf_devmode_fields_formname,
7278                   { "Form name", "spoolss.devmode.fields.form_name",
7279                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7280                     DEVMODE_FORMNAME, "Form name", HFILL }},
7281
7282                 { &hf_devmode_fields_logpixels,
7283                   { "Log pixels", "spoolss.devmode.fields.log_pixels",
7284                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7285                     DEVMODE_LOGPIXELS, "Log pixels", HFILL }},
7286
7287                 { &hf_devmode_fields_bitsperpel,
7288                   { "Bits per pel", "spoolss.devmode.fields.bits_per_pel",
7289                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7290                     DEVMODE_BITSPERPEL, "Bits per pel", HFILL }},
7291
7292                 { &hf_devmode_fields_pelswidth,
7293                   { "Pels width", "spoolss.devmode.fields.pels_width",
7294                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7295                     DEVMODE_PELSWIDTH, "Pels width", HFILL }},
7296
7297                 { &hf_devmode_fields_pelsheight,
7298                   { "Pels height", "spoolss.devmode.fields.pels_height",
7299                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7300                     DEVMODE_PELSHEIGHT, "Pels height", HFILL }},
7301
7302                 { &hf_devmode_fields_displayflags,
7303                   { "Display flags", "spoolss.devmode.fields.display_flags",
7304                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7305                     DEVMODE_DISPLAYFLAGS, "Display flags", HFILL }},
7306
7307                 { &hf_devmode_fields_displayfrequency,
7308                   { "Display frequency", 
7309                     "spoolss.devmode.fields.display_frequency",
7310                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7311                     DEVMODE_DISPLAYFREQUENCY, "Display frequency", HFILL }},
7312
7313                 { &hf_devmode_fields_icmmethod,
7314                   { "ICM method", "spoolss.devmode.fields.icm_method",
7315                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7316                     DEVMODE_ICMMETHOD, "ICM method", HFILL }},
7317
7318                 { &hf_devmode_fields_icmintent,
7319                   { "ICM intent", "spoolss.devmode.fields.icm_intent",
7320                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7321                     DEVMODE_ICMINTENT, "ICM intent", HFILL }},
7322
7323                 { &hf_devmode_fields_mediatype,
7324                   { "Media type", "spoolss.devmode.fields.media_type",
7325                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7326                     DEVMODE_MEDIATYPE, "Media type", HFILL }},
7327
7328                 { &hf_devmode_fields_dithertype,
7329                   { "Dither type", "spoolss.devmode.fields.dither_type",
7330                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7331                     DEVMODE_DITHERTYPE, "Dither type", HFILL }},
7332
7333                 { &hf_devmode_fields_panningwidth,
7334                   { "Panning width", "spoolss.devmode.fields.panning_width",
7335                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7336                     DEVMODE_PANNINGWIDTH, "Panning width", HFILL }},
7337
7338                 { &hf_devmode_fields_panningheight,
7339                   { "Panning height", "spoolss.devmode.fields.panning_height",
7340                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
7341                     DEVMODE_PANNINGHEIGHT, "Panning height", HFILL }},
7342
7343                 /* EnumPrinterData RPC */
7344
7345                 { &hf_enumprinterdata_enumindex,
7346                   { "Enum index", "spoolss.enumprinterdata.enumindex", 
7347                     FT_UINT32, BASE_DEC, NULL, 0x0, 
7348                     "Index for start of enumeration", HFILL }},
7349
7350                 { &hf_enumprinterdata_value_offered,
7351                   { "Value size offered", 
7352                     "spoolss.enumprinterdata.value_offered", FT_UINT32, 
7353                     BASE_DEC, NULL, 0x0, 
7354                     "Buffer size offered for printerdata value", HFILL }},
7355
7356                 { &hf_enumprinterdata_data_offered,
7357                   { "Data size offered", 
7358                     "spoolss.enumprinterdata.data_offered", FT_UINT32, 
7359                     BASE_DEC, NULL, 0x0, 
7360                     "Buffer size offered for printerdata data", HFILL }},
7361
7362                 { &hf_enumprinterdata_value_len,
7363                   { "Value length", 
7364                     "spoolss.enumprinterdata.value_len", FT_UINT32, 
7365                     BASE_DEC, NULL, 0x0, 
7366                     "Size of printerdata value", HFILL }},
7367
7368                 { &hf_enumprinterdata_value_needed,
7369                   { "Value size needed", 
7370                     "spoolss.enumprinterdata.value_needed", FT_UINT32, 
7371                     BASE_DEC, NULL, 0x0, 
7372                     "Buffer size needed for printerdata value", HFILL }},
7373
7374                 { &hf_enumprinterdata_data_needed,
7375                   { "Data size needed", 
7376                     "spoolss.enumprinterdata.data_needed", FT_UINT32, BASE_DEC,
7377                     NULL, 0x0, "Buffer size needed for printerdata data", 
7378                     HFILL }},
7379
7380                 /* Print jobs */
7381
7382                 { &hf_job_id,
7383                   { "Job ID", "spoolss.job.id", FT_UINT32, BASE_DEC,
7384                     NULL, 0x0, "Job identification number", HFILL }},
7385
7386                 { &hf_job_status,
7387                   { "Job status", "spoolss.job.status", FT_UINT32, BASE_DEC,
7388                     NULL, 0x0, "Job status", HFILL }},
7389
7390                 { &hf_job_status_paused,
7391                   { "Paused", "spoolss.job.status.paused", FT_BOOLEAN, 32,
7392                     TFS(&tfs_job_status_paused), JOB_STATUS_PAUSED,
7393                     "Paused", HFILL }},
7394
7395                 { &hf_job_status_error,
7396                   { "Error", "spoolss.job.status.error", FT_BOOLEAN, 32,
7397                     TFS(&tfs_job_status_error), JOB_STATUS_ERROR,
7398                     "Error", HFILL }},
7399
7400                 { &hf_job_status_deleting,
7401                   { "Deleting", "spoolss.job.status.deleting", FT_BOOLEAN, 32,
7402                     TFS(&tfs_job_status_deleting), JOB_STATUS_DELETING,
7403                     "Deleting", HFILL }},
7404
7405                 { &hf_job_status_spooling,
7406                   { "Spooling", "spoolss.job.status.spooling", FT_BOOLEAN, 32,
7407                     TFS(&tfs_job_status_spooling), JOB_STATUS_SPOOLING,
7408                     "Spooling", HFILL }},
7409
7410                 { &hf_job_status_printing,
7411                   { "Printing", "spoolss.job.status.printing", FT_BOOLEAN, 32,
7412                     TFS(&tfs_job_status_printing), JOB_STATUS_PRINTING,
7413                     "Printing", HFILL }},
7414
7415                 { &hf_job_status_offline,
7416                   { "Offline", "spoolss.job.status.offline", FT_BOOLEAN, 32,
7417                     TFS(&tfs_job_status_offline), JOB_STATUS_OFFLINE,
7418                     "Offline", HFILL }},
7419
7420                 { &hf_job_status_paperout,
7421                   { "Paperout", "spoolss.job.status.paperout", FT_BOOLEAN, 32,
7422                     TFS(&tfs_job_status_paperout), JOB_STATUS_PAPEROUT,
7423                     "Paperout", HFILL }},
7424
7425                 { &hf_job_status_printed,
7426                   { "Printed", "spoolss.job.status.printed", FT_BOOLEAN, 32,
7427                     TFS(&tfs_job_status_printed), JOB_STATUS_PRINTED,
7428                     "Printed", HFILL }},
7429
7430                 { &hf_job_status_deleted,
7431                   { "Deleted", "spoolss.job.status.deleted", FT_BOOLEAN, 32,
7432                     TFS(&tfs_job_status_deleted), JOB_STATUS_DELETED,
7433                     "Deleted", HFILL }},
7434
7435                 { &hf_job_status_blocked,
7436                   { "Blocked", "spoolss.job.status.blocked", FT_BOOLEAN, 32,
7437                     TFS(&tfs_job_status_blocked), JOB_STATUS_BLOCKED,
7438                     "Blocked", HFILL }},
7439
7440                 { &hf_job_status_user_intervention,
7441                   { "User intervention", 
7442                     "spoolss.job.status.user_intervention", FT_BOOLEAN, 32,
7443                     TFS(&tfs_job_status_user_intervention), 
7444                     JOB_STATUS_USER_INTERVENTION, "User intervention", 
7445                     HFILL }},
7446
7447                 { &hf_job_priority,
7448                   { "Job priority", "spoolss.job.priority", FT_UINT32, 
7449                     BASE_DEC, NULL, 0x0, "Job priority", HFILL }},
7450
7451                 { &hf_job_position,
7452                   { "Job position", "spoolss.job.position", FT_UINT32, 
7453                     BASE_DEC, NULL, 0x0, "Job position", HFILL }},
7454
7455                 { &hf_job_totalpages,
7456                   { "Job total pages", "spoolss.job.totalpages", FT_UINT32, 
7457                     BASE_DEC, NULL, 0x0, "Job total pages", HFILL }},
7458
7459                 { &hf_job_totalbytes,
7460                   { "Job total bytes", "spoolss.job.totalbytes", FT_UINT32, 
7461                     BASE_DEC, NULL, 0x0, "Job total bytes", HFILL }},
7462
7463                 { &hf_job_bytesprinted,
7464                   { "Job bytes printed", "spoolss.job.bytesprinted", 
7465                     FT_UINT32, BASE_DEC, NULL, 0x0, "Job bytes printed", 
7466                     HFILL }},
7467
7468                 { &hf_job_pagesprinted,
7469                   { "Job pages printed", "spoolss.job.pagesprinted", 
7470                     FT_UINT32, BASE_DEC, NULL, 0x0, "Job pages printed", 
7471                     HFILL }},
7472
7473                 { &hf_job_size,
7474                   { "Job size", "spoolss.job.size", FT_UINT32, BASE_DEC, 
7475                     NULL, 0x0, "Job size", HFILL }},
7476
7477                 /* Forms */
7478
7479                 { &hf_form,
7480                   { "Data", "spoolss.form", FT_UINT32, 
7481                     BASE_HEX, NULL, 0, "Data", HFILL }},
7482
7483                 { &hf_form_level,
7484                   { "Level", "spoolss.form.level", FT_UINT32,
7485                     BASE_DEC, NULL, 0, "Level", HFILL }},
7486
7487                 { &hf_form_name,
7488                   { "Name", "spoolss.form.name", FT_STRING, BASE_NONE,
7489                     NULL, 0, "Name", HFILL }},
7490
7491                 { &hf_form_flags,
7492                   { "Flags", "spoolss.form.flags", FT_UINT32,
7493                     BASE_DEC, VALS(form_type_vals), 0, "Flags", HFILL }},
7494
7495                 { &hf_form_unknown,
7496                   { "Unknown", "spoolss.form.unknown", FT_UINT32,
7497                     BASE_HEX, NULL, 0, "Unknown", HFILL }},
7498
7499                 { &hf_form_width,
7500                   { "Width", "spoolss.form.width", FT_UINT32,
7501                     BASE_DEC, NULL, 0, "Width", HFILL }},
7502
7503                 { &hf_form_height,
7504                   { "Height", "spoolss.form.height", FT_UINT32,
7505                     BASE_DEC, NULL, 0, "Height", HFILL }},
7506
7507                 { &hf_form_left_margin,
7508                   { "Left margin", "spoolss.form.left", FT_UINT32,
7509                     BASE_DEC, NULL, 0, "Left", HFILL }},
7510
7511                 { &hf_form_top_margin,
7512                   { "Top", "spoolss.form.top", FT_UINT32,
7513                     BASE_DEC, NULL, 0, "Top", HFILL }},
7514
7515                 { &hf_form_horiz_len,
7516                   { "Horizontal", "spoolss.form.horiz", FT_UINT32,
7517                     BASE_DEC, NULL, 0, "Horizontal", HFILL }},
7518
7519                 { &hf_form_vert_len,
7520                   { "Vertical", "spoolss.form.vert", FT_UINT32,
7521                     BASE_DEC, NULL, 0, "Vertical", HFILL }},
7522
7523                 { &hf_enumforms_num,
7524                   { "Num", "spoolss.enumforms.num", FT_UINT32,
7525                     BASE_DEC, NULL, 0, "Num", HFILL }},
7526
7527                 /* Print notify */
7528
7529                 { &hf_notify_options_version,
7530                   { "Version", "spoolss.notify_options.version", FT_UINT32, 
7531                     BASE_DEC, NULL, 0, "Version", HFILL }},
7532
7533                 { &hf_notify_options_flags,
7534                   { "Flags", "spoolss.notify_options.flags", FT_UINT32, 
7535                     BASE_DEC, NULL, 0, "Flags", HFILL }},
7536
7537                 { &hf_notify_options_count,
7538                   { "Count", "spoolss.notify_options.count", FT_UINT32, 
7539                     BASE_DEC, NULL, 0, "Count", HFILL }},
7540
7541                 { &hf_notify_option_type,
7542                   { "Type", "spoolss.notify_option.type", FT_UINT16, BASE_DEC,
7543                     VALS(printer_notify_types), 0, "Type", HFILL }},
7544
7545                 { &hf_notify_option_reserved1,
7546                   { "Reserved1", "spoolss.notify_option.reserved1", FT_UINT16, 
7547                     BASE_DEC, NULL, 0, "Reserved1", HFILL }},
7548
7549                 { &hf_notify_option_reserved2,
7550                   { "Reserved2", "spoolss.notify_option.reserved2", FT_UINT32, 
7551                     BASE_DEC, NULL, 0, "Reserved2", HFILL }},
7552
7553                 { &hf_notify_option_reserved3,
7554                   { "Reserved3", "spoolss.notify_option.reserved3", FT_UINT32, 
7555                     BASE_DEC, NULL, 0, "Reserved3", HFILL }},
7556
7557                 { &hf_notify_option_count,
7558                   { "Count", "spoolss.notify_option.count", FT_UINT32, 
7559                     BASE_DEC, NULL, 0, "Count", HFILL }},
7560
7561                 { &hf_notify_option_data_count,
7562                   { "Count", "spoolss.notify_option_data.count", FT_UINT32, 
7563                     BASE_DEC, NULL, 0, "Count", HFILL }},
7564
7565                 { &hf_notify_options_flags_refresh,
7566                   { "Refresh", "spoolss.notify_options.flags", FT_BOOLEAN, 32,
7567                     TFS(&tfs_notify_options_flags_refresh), 
7568                     PRINTER_NOTIFY_OPTIONS_REFRESH, "Refresh", HFILL }},
7569
7570                 { &hf_notify_info_count,
7571                   { "Count", "spoolss.notify_info.count", FT_UINT32, BASE_DEC,
7572                     NULL, 0, "Count", HFILL }},
7573
7574                 { &hf_notify_info_version,
7575                   { "Version", "spoolss.notify_info.version", FT_UINT32, 
7576                     BASE_DEC, NULL, 0, "Version", HFILL }},
7577
7578                 { &hf_notify_info_flags,
7579                   { "Flags", "spoolss.notify_info.flags", FT_UINT32, BASE_HEX,
7580                     NULL, 0, "Flags", HFILL }},
7581
7582                 { &hf_notify_info_data_type,
7583                   { "Type", "spoolss.notify_info_data.type", FT_UINT16, 
7584                     BASE_DEC, VALS(printer_notify_types), 0, "Type", HFILL }},
7585
7586                 { &hf_notify_field,
7587                   { "Field", "spoolss.notify_field", FT_UINT16, BASE_DEC,
7588                     NULL, 0, "Field", HFILL }},
7589
7590                 { &hf_notify_info_data_count,
7591                   { "Count", "spoolss.notify_info_data.count", FT_UINT32, 
7592                     BASE_DEC, NULL, 0, "Count", HFILL }},
7593
7594                 { &hf_notify_info_data_id,
7595                   { "Job Id", "spoolss.notify_info_data.jobid", FT_UINT32, 
7596                     BASE_DEC, NULL, 0, "Job Id", HFILL }},
7597
7598                 { &hf_notify_info_data_value1,
7599                   { "Value1", "spoolss.notify_info_data.value1", FT_UINT32, 
7600                     BASE_HEX, NULL, 0, "Value1", HFILL }},
7601
7602                 { &hf_notify_info_data_value2,
7603                   { "Value2", "spoolss.notify_info_data.value2", FT_UINT32, 
7604                     BASE_HEX, NULL, 0, "Value2", HFILL }},
7605
7606                 { &hf_notify_info_data_bufsize,
7607                   { "Buffer size", "spoolss.notify_info_data.bufsize", 
7608                     FT_UINT32, BASE_DEC, NULL, 0, "Buffer size", HFILL }},
7609
7610                 { &hf_notify_info_data_buffer,
7611                   { "Buffer", "spoolss.notify_info_data.buffer", FT_UINT32, 
7612                     BASE_HEX, NULL, 0, "Buffer", HFILL }},
7613
7614                 { &hf_notify_info_data_buffer_len,
7615                   { "Buffer length", "spoolss.notify_info_data.buffer.len", 
7616                     FT_UINT32, BASE_HEX, NULL, 0, "Buffer length", HFILL }},
7617
7618                 { &hf_notify_info_data_buffer_data,
7619                   { "Buffer data", "spoolss.notify_info_data.buffer.data", 
7620                     FT_BYTES, BASE_HEX, NULL, 0, "Buffer data", HFILL }},
7621
7622                 /* RffpCNex RPC */
7623
7624                 { &hf_rffpcnex_options,
7625                   { "Options", "spoolss.rffpcnex.options", FT_UINT32, BASE_DEC,
7626                     NULL, 0, "RFFPCNEX options", HFILL }},
7627
7628                 { &hf_printerlocal, /* XXX: move me */
7629                   { "Printer local", "spoolss.printer_local", FT_UINT32, 
7630                     BASE_DEC, NULL, 0, "Printer local", HFILL }},
7631
7632                 { &hf_rffpcnex_flags,
7633                   { "RFFPCNEX flags", "spoolss.rffpcnex.flags", FT_UINT32, 
7634                     BASE_DEC, NULL, 0, "RFFPCNEX flags", HFILL }},
7635
7636                 { &hf_rffpcnex_flags_add_printer,
7637                   { "Add printer", "spoolss.rffpcnex.flags.add_printer",
7638                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_add_printer),
7639                     SPOOLSS_PRINTER_CHANGE_ADD_PRINTER, "Add printer", 
7640                     HFILL }},
7641
7642                 { &hf_rffpcnex_flags_set_printer,
7643                   { "Set printer", "spoolss.rffpcnex.flags.set_printer",
7644                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_set_printer),
7645                     SPOOLSS_PRINTER_CHANGE_SET_PRINTER, "Set printer", 
7646                     HFILL }},
7647
7648                 { &hf_rffpcnex_flags_delete_printer,
7649                   { "Delete printer", "spoolss.rffpcnex.flags.delete_printer",
7650                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_delete_printer),
7651                     SPOOLSS_PRINTER_CHANGE_DELETE_PRINTER, "Delete printer", 
7652                     HFILL }},
7653
7654                 { &hf_rffpcnex_flags_add_job,
7655                   { "Add job", "spoolss.rffpcnex.flags.add_job",
7656                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_add_job),
7657                     SPOOLSS_PRINTER_CHANGE_ADD_JOB, "Add job", HFILL }},
7658
7659                 { &hf_rffpcnex_flags_set_job,
7660                   { "Set job", "spoolss.rffpcnex.flags.set_job",
7661                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_set_job),
7662                     SPOOLSS_PRINTER_CHANGE_SET_JOB, "Set job", HFILL }},
7663
7664                 { &hf_rffpcnex_flags_delete_job,
7665                   { "Delete job", "spoolss.rffpcnex.flags.delete_job",
7666                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_delete_job),
7667                     SPOOLSS_PRINTER_CHANGE_DELETE_JOB, "Delete job", HFILL }},
7668
7669                 { &hf_rffpcnex_flags_write_job,
7670                   { "Write job", "spoolss.rffpcnex.flags.write_job",
7671                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_write_job),
7672                     SPOOLSS_PRINTER_CHANGE_WRITE_JOB, "Write job", HFILL }},
7673
7674                 { &hf_rffpcnex_flags_add_form,
7675                   { "Add form", "spoolss.rffpcnex.flags.add_form",
7676                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_add_form),
7677                     SPOOLSS_PRINTER_CHANGE_ADD_FORM, "Add form", HFILL }},
7678
7679                 { &hf_rffpcnex_flags_set_form,
7680                   { "Set form", "spoolss.rffpcnex.flags.set_form",
7681                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_set_form),
7682                     SPOOLSS_PRINTER_CHANGE_SET_FORM, "Set form", HFILL }},
7683
7684                 { &hf_rffpcnex_flags_delete_form,
7685                   { "Delete form", "spoolss.rffpcnex.flags.delete_form",
7686                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_delete_form),
7687                     SPOOLSS_PRINTER_CHANGE_DELETE_FORM, "Delete form", 
7688                     HFILL }},
7689
7690                 { &hf_rffpcnex_flags_add_port,
7691                   { "Add port", "spoolss.rffpcnex.flags.add_port",
7692                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_add_port),
7693                     SPOOLSS_PRINTER_CHANGE_ADD_PORT, "Add port", HFILL }},
7694
7695                 { &hf_rffpcnex_flags_configure_port,
7696                   { "Configure port", "spoolss.rffpcnex.flags.configure_port",
7697                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_configure_port),
7698                     SPOOLSS_PRINTER_CHANGE_CONFIGURE_PORT, "Configure port", 
7699                     HFILL }},
7700
7701                 { &hf_rffpcnex_flags_delete_port,
7702                   { "Delete port", "spoolss.rffpcnex.flags.delete_port",
7703                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_delete_port),
7704                     SPOOLSS_PRINTER_CHANGE_DELETE_PORT, "Delete port", 
7705                     HFILL }},
7706
7707                 { &hf_rffpcnex_flags_add_print_processor,
7708                   { "Add processor", "spoolss.rffpcnex.flags.add_processor",
7709                     FT_BOOLEAN, 32, 
7710                     TFS(&tfs_rffpcnex_flags_add_print_processor),
7711                     SPOOLSS_PRINTER_CHANGE_ADD_PRINT_PROCESSOR, 
7712                     "Add processor", HFILL }},
7713
7714                 { &hf_rffpcnex_flags_delete_print_processor,
7715                   { "Delete processor", 
7716                     "spoolss.rffpcnex.flags.delete_processor", FT_BOOLEAN, 32, 
7717                     TFS(&tfs_rffpcnex_flags_delete_print_processor),
7718                     SPOOLSS_PRINTER_CHANGE_DELETE_PRINT_PROCESSOR, 
7719                     "Delete processor", HFILL }},
7720
7721                 { &hf_rffpcnex_flags_add_driver,
7722                   { "Add driver", "spoolss.rffpcnex.flags.add_driver",
7723                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_add_driver),
7724                     SPOOLSS_PRINTER_CHANGE_ADD_PRINTER_DRIVER, "Add driver", 
7725                     HFILL }},
7726
7727                 { &hf_rffpcnex_flags_set_driver,
7728                   { "Set driver", "spoolss.rffpcnex.flags.set_driver",
7729                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_set_driver),
7730                     SPOOLSS_PRINTER_CHANGE_SET_PRINTER_DRIVER, "Set driver", 
7731                     HFILL }},
7732
7733                 { &hf_rffpcnex_flags_delete_driver,
7734                   { "Delete driver", "spoolss.rffpcnex.flags.delete_driver",
7735                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_delete_driver),
7736                     SPOOLSS_PRINTER_CHANGE_DELETE_PRINTER_DRIVER, 
7737                     "Delete driver", HFILL }},
7738
7739                 { &hf_rffpcnex_flags_timeout,
7740                   { "Timeout", "spoolss.rffpcnex.flags.timeout",
7741                     FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_timeout),
7742                     SPOOLSS_PRINTER_CHANGE_TIMEOUT, "Timeout", HFILL }},
7743
7744                 { &hf_rffpcnex_flags_failed_printer_connection,
7745                   { "Failed printer connection", 
7746                     "spoolss.rffpcnex.flags.failed_connection_printer",
7747                     FT_BOOLEAN, 32, 
7748                     TFS(&tfs_rffpcnex_flags_failed_connection_printer),
7749                     SPOOLSS_PRINTER_CHANGE_FAILED_CONNECTION_PRINTER, 
7750                     "Failed printer connection", HFILL }},
7751
7752                 /* RRPCN RPC */
7753
7754                 { &hf_rrpcn_changelow,
7755                   { "Change low", "spoolss.rrpcn.changelow", FT_UINT32, 
7756                     BASE_DEC, NULL, 0, "Change low", HFILL }},
7757
7758                 { &hf_rrpcn_changehigh,
7759                   { "Change high", "spoolss.rrpcn.changehigh", FT_UINT32, 
7760                     BASE_DEC, NULL, 0, "Change high", HFILL }},
7761
7762                 { &hf_rrpcn_unk0,
7763                   { "Unknown 0", "spoolss.rrpcn.unk0", FT_UINT32, BASE_DEC,
7764                     NULL, 0, "Unknown 0", HFILL }},
7765
7766                 { &hf_rrpcn_unk1,
7767                   { "Unknown 1", "spoolss.rrpcn.unk1", FT_UINT32, BASE_DEC,
7768                     NULL, 0, "Unknown 1", HFILL }},
7769
7770                 /* ReplyOpenPrinter RPC */
7771
7772                 { &hf_replyopenprinter_unk0,
7773                   { "Unknown 0", "spoolss.replyopenprinter.unk0", FT_UINT32, 
7774                     BASE_DEC, NULL, 0, "Unknown 0", HFILL }},
7775
7776                 { &hf_replyopenprinter_unk1,
7777                   { "Unknown 1", "spoolss.replyopenprinter.unk1", FT_UINT32, 
7778                     BASE_DEC, NULL, 0, "Unknown 1", HFILL }},
7779
7780                 /* Printer attributes */
7781
7782                 { &hf_printer_attributes,
7783                   { "Attributes", "spoolss.printer_attributes", FT_UINT32,
7784                     BASE_HEX, NULL, 0, "Attributes", HFILL }},
7785
7786                 { &hf_printer_attributes_queued,
7787                   { "Queued", "spoolss.printer_attributes.queued", FT_BOOLEAN,
7788                     32, TFS(&tfs_printer_attributes_queued),
7789                     PRINTER_ATTRIBUTE_QUEUED, "Queued", HFILL }},
7790
7791                 { &hf_printer_attributes_direct,
7792                   { "Direct", "spoolss.printer_attributes.direct", FT_BOOLEAN,
7793                     32, TFS(&tfs_printer_attributes_direct),
7794                     PRINTER_ATTRIBUTE_DIRECT, "Direct", HFILL }},
7795
7796                 { &hf_printer_attributes_default,
7797                   { "Default (9x/ME only)", 
7798                     "spoolss.printer_attributes.default",FT_BOOLEAN,
7799                     32, TFS(&tfs_printer_attributes_default),
7800                     PRINTER_ATTRIBUTE_DEFAULT, "Default", HFILL }},
7801
7802                 { &hf_printer_attributes_shared,
7803                   { "Shared", "spoolss.printer_attributes.shared", FT_BOOLEAN,
7804                     32, TFS(&tfs_printer_attributes_shared),
7805                     PRINTER_ATTRIBUTE_SHARED, "Shared", HFILL }},
7806
7807                 { &hf_printer_attributes_network,
7808                   { "Network", "spoolss.printer_attributes.network", 
7809                     FT_BOOLEAN, 32, TFS(&tfs_printer_attributes_network),
7810                     PRINTER_ATTRIBUTE_NETWORK, "Network", HFILL }},
7811
7812                 { &hf_printer_attributes_hidden,
7813                   { "Hidden", "spoolss.printer_attributes.hidden", FT_BOOLEAN,
7814                     32, TFS(&tfs_printer_attributes_hidden),
7815                     PRINTER_ATTRIBUTE_HIDDEN, "Hidden", HFILL }},
7816
7817                 { &hf_printer_attributes_local,
7818                   { "Local", "spoolss.printer_attributes.local", FT_BOOLEAN,
7819                     32, TFS(&tfs_printer_attributes_local),
7820                     PRINTER_ATTRIBUTE_LOCAL, "Local", HFILL }},
7821
7822                 { &hf_printer_attributes_enable_devq,
7823                   { "Enable devq", "spoolss.printer_attributes.enable_devq", 
7824                     FT_BOOLEAN, 32, TFS(&tfs_printer_attributes_enable_devq),
7825                     PRINTER_ATTRIBUTE_ENABLE_DEVQ, "Enable evq", HFILL }},
7826
7827                 { &hf_printer_attributes_keep_printed_jobs,
7828                   { "Keep printed jobs", 
7829                     "spoolss.printer_attributes.keep_printed_jobs", FT_BOOLEAN,
7830                     32, TFS(&tfs_printer_attributes_keep_printed_jobs),
7831                     PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS, "Keep printed jobs", 
7832                     HFILL }},
7833
7834                 { &hf_printer_attributes_do_complete_first,
7835                   { "Do complete first", 
7836                     "spoolss.printer_attributes.do_complete_first", FT_BOOLEAN,
7837                     32, TFS(&tfs_printer_attributes_do_complete_first),
7838                     PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST, "Do complete first", 
7839                     HFILL }},
7840
7841                 { &hf_printer_attributes_work_offline,
7842                   { "Work offline (9x/ME only)", 
7843                     "spoolss.printer_attributes.work_offline", FT_BOOLEAN,
7844                     32, TFS(&tfs_printer_attributes_work_offline),
7845                     PRINTER_ATTRIBUTE_WORK_OFFLINE, "Work offline", HFILL }},
7846
7847                 { &hf_printer_attributes_enable_bidi,
7848                   { "Enable bidi (9x/ME only)", 
7849                     "spoolss.printer_attributes.enable_bidi", FT_BOOLEAN,
7850                     32, TFS(&tfs_printer_attributes_enable_bidi),
7851                     PRINTER_ATTRIBUTE_ENABLE_BIDI, "Enable bidi", HFILL }},
7852
7853                 { &hf_printer_attributes_raw_only,
7854                   { "Raw only", "spoolss.printer_attributes.raw_only", 
7855                     FT_BOOLEAN, 32, TFS(&tfs_printer_attributes_raw_only),
7856                     PRINTER_ATTRIBUTE_RAW_ONLY, "Raw only", HFILL }},
7857
7858                 { &hf_printer_attributes_published,
7859                   { "Published", "spoolss.printer_attributes.published", 
7860                     FT_BOOLEAN, 32, TFS(&tfs_printer_attributes_published),
7861                     PRINTER_ATTRIBUTE_PUBLISHED, "Published", HFILL }},
7862
7863                 /* Timestamps */
7864
7865                 { &hf_time_year,
7866                   { "Year", "spoolss.time.year", FT_UINT32, BASE_DEC,
7867                     NULL, 0x0, "Year", HFILL }},
7868
7869                 { &hf_time_month,
7870                   { "Month", "spoolss.time.month", FT_UINT32, BASE_DEC,
7871                     NULL, 0x0, "Month", HFILL }},
7872
7873                 { &hf_time_dow,
7874                   { "Day of week", "spoolss.time.dow", FT_UINT32, BASE_DEC,
7875                     NULL, 0x0, "Day of week", HFILL }},
7876
7877                 { &hf_time_day,
7878                   { "Day", "spoolss.time.day", FT_UINT32, BASE_DEC,
7879                     NULL, 0x0, "Day", HFILL }},
7880
7881                 { &hf_time_hour,
7882                   { "Hour", "spoolss.time.hour", FT_UINT32, BASE_DEC,
7883                     NULL, 0x0, "Hour", HFILL }},
7884
7885                 { &hf_time_minute,
7886                   { "Minute", "spoolss.time.minute", FT_UINT32, BASE_DEC,
7887                     NULL, 0x0, "Minute", HFILL }},
7888
7889                 { &hf_time_second,
7890                   { "Second", "spoolss.time.second", FT_UINT32, BASE_DEC,
7891                     NULL, 0x0, "Second", HFILL }},
7892
7893                 { &hf_time_msec,
7894                   { "Millisecond", "spoolss.time.msec", FT_UINT32, BASE_DEC,
7895                     NULL, 0x0, "Millisecond", HFILL }},
7896
7897                 /* Userlevel */
7898
7899                 { &hf_userlevel_size,
7900                   { "Size", "spoolss.userlevel.size",
7901                     FT_UINT32, BASE_DEC, NULL, 0, "Size", HFILL }},
7902
7903                 { &hf_userlevel_client,
7904                   { "Client", "spoolss.userlevel.client", FT_STRING, 
7905                     BASE_NONE, NULL, 0, "Client", HFILL }},
7906
7907                 { &hf_userlevel_user,
7908                   { "User", "spoolss.userlevel.user", FT_STRING, 
7909                     BASE_NONE, NULL, 0, "User", HFILL }},
7910
7911                 { &hf_userlevel_build,
7912                   { "Build", "spoolss.userlevel.build",
7913                     FT_UINT32, BASE_DEC, NULL, 0, "Build", HFILL }},
7914
7915                 { &hf_userlevel_major,
7916                   { "Major", "spoolss.userlevel.major",
7917                     FT_UINT32, BASE_DEC, NULL, 0, "Major", HFILL }},
7918
7919                 { &hf_userlevel_minor,
7920                   { "Minor", "spoolss.userlevel.minor",
7921                     FT_UINT32, BASE_DEC, NULL, 0, "Minor", HFILL }},
7922
7923                 { &hf_userlevel_processor,
7924                   { "Processor", "spoolss.userlevel.processor",
7925                     FT_UINT32, BASE_DEC, NULL, 0, "Processor", HFILL }},
7926
7927                 /* EnumprinterdataEx RPC */
7928
7929                 { &hf_enumprinterdataex_num_values,
7930                   { "Num values", "spoolss.enumprinterdataex.num_values",
7931                     FT_UINT32, BASE_DEC, NULL, 0x0, 
7932                     "Number of values returned", HFILL }},
7933
7934                 { &hf_enumprinterdataex_name_offset,
7935                   { "Name offset", "spoolss.enumprinterdataex.name_offset",
7936                     FT_UINT32, BASE_DEC, NULL, 0x0, 
7937                     "Name offset", HFILL }},
7938
7939                 { &hf_enumprinterdataex_name_len,
7940                   { "Name len", "spoolss.enumprinterdataex.name_len",
7941                     FT_UINT32, BASE_DEC, NULL, 0x0, 
7942                     "Name len", HFILL }},
7943
7944                 { &hf_enumprinterdataex_name,
7945                   { "Name", "spoolss.enumprinterdataex.name", 
7946                     FT_STRING, BASE_NONE, NULL, 0, "Name", HFILL }},
7947
7948                 { &hf_enumprinterdataex_val_type,
7949                   { "Value type", "spoolss.enumprinterdataex.value_type",
7950                     FT_UINT32, BASE_DEC, NULL, 0x0, 
7951                     "Value type", HFILL }},
7952
7953                 { &hf_enumprinterdataex_val_offset,
7954                   { "Value offset", "spoolss.enumprinterdataex.value_offset",
7955                     FT_UINT32, BASE_DEC, NULL, 0x0, 
7956                     "Value offset", HFILL }},
7957
7958                 { &hf_enumprinterdataex_val_len,
7959                   { "Value len", "spoolss.enumprinterdataex.value_len",
7960                     FT_UINT32, BASE_DEC, NULL, 0x0, 
7961                     "Value len", HFILL }},
7962
7963                 { &hf_enumprinterdataex_val_dword_high,
7964                   { "DWORD value (high)", 
7965                     "spoolss.enumprinterdataex.val_dword.high",
7966                     FT_UINT16, BASE_DEC, NULL, 0x0, 
7967                     "DWORD value (high)", HFILL }},
7968
7969                 { &hf_enumprinterdataex_val_dword_low,
7970                   { "DWORD value (low)", 
7971                     "spoolss.enumprinterdataex.val_dword.low",
7972                     FT_UINT16, BASE_DEC, NULL, 0x0, 
7973                     "DWORD value (low)", HFILL }},
7974
7975                 { &hf_enumprinterdataex_val_sz,
7976                   { "SZ value", "spoolss.printerdata.val_sz", 
7977                     FT_STRING, BASE_NONE, NULL, 0, "SZ value", HFILL }},
7978
7979                 /* RouterReplyPrinter RPC */
7980
7981                 { &hf_routerreplyprinter_condition,
7982                   { "Condition", "spoolss.routerreplyprinter.condition", 
7983                     FT_UINT32, BASE_DEC, NULL, 0, "Condition", HFILL }},
7984
7985                 { &hf_routerreplyprinter_unknown1,
7986                   { "Unknown1", "spoolss.routerreplyprinter.unknown1", 
7987                     FT_UINT32, BASE_DEC, NULL, 0, "Unknown1", HFILL }},
7988
7989                 { &hf_routerreplyprinter_changeid,
7990                   { "Change id", "spoolss.routerreplyprinter.changeid", 
7991                     FT_UINT32, BASE_DEC, NULL, 0, "Change id", HFILL }},
7992
7993                 /* EnumPrinterKey RPC */
7994
7995                 { &hf_keybuffer_size,
7996                   { "Key Buffer size", "spoolss.keybuffer.size", FT_UINT32, 
7997                     BASE_DEC, NULL, 0x0, "Size of buffer", HFILL }},
7998
7999                 { &hf_keybuffer_data,
8000                   { "Key Buffer data", "spoolss.keybuffer.data", FT_BYTES, 
8001                     BASE_HEX, NULL, 0x0, "Contents of buffer", HFILL }},
8002
8003                 /* SetJob RPC */
8004
8005                 { &hf_setjob_cmd,
8006                   { "Set job command", "spoolss.setjob.cmd", FT_UINT32, 
8007                     BASE_DEC, VALS(setjob_commands), 0x0, "Printer data name", 
8008                     HFILL }},
8009
8010                 /* EnumJobs RPC */
8011
8012                 { &hf_enumjobs_firstjob,
8013                   { "First job", "spoolss.enumjobs.firstjob", FT_UINT32, 
8014                     BASE_DEC, NULL, 0x0, "Index of first job to return", 
8015                     HFILL }},
8016
8017                 { &hf_enumjobs_numjobs,
8018                   { "Num jobs", "spoolss.enumjobs.numjobs", FT_UINT32, 
8019                     BASE_DEC, NULL, 0x0, "Number of jobs to return", HFILL }},
8020
8021                 /* Security descriptor buffer */
8022
8023                 { &hf_secdescbuf_maxlen,
8024                   { "Max len", "secdescbuf.max_len",
8025                     FT_UINT32, BASE_DEC, NULL, 0, "Max len", HFILL }},
8026
8027                 { &hf_secdescbuf_undoc,
8028                   { "Undocumented", "secdescbuf.undoc",
8029                     FT_UINT32, BASE_DEC, NULL, 0, "Undocumented", HFILL }},
8030
8031                 { &hf_secdescbuf_len,
8032                   { "Length", "secdescbuf.len",
8033                     FT_UINT32, BASE_DEC, NULL, 0, "Length", HFILL }},
8034
8035                 /* Spool printer info */
8036
8037                 { &hf_spool_printer_info_devmode_ptr,
8038                   { "Devmode pointer", "spoolprinterinfo.devmode_ptr",
8039                     FT_UINT32, BASE_HEX, NULL, 0, "Devmode pointer", HFILL }},
8040
8041                 { &hf_spool_printer_info_secdesc_ptr,
8042                   { "Secdesc pointer", "spoolprinterinfo.secdesc_ptr",
8043                     FT_UINT32, BASE_HEX, NULL, 0, "Secdesc pointer", HFILL }},
8044
8045                 /* WritePrinter RPC */
8046
8047                 { &hf_writeprinter_numwritten,
8048                   { "Num written", "spoolss.writeprinter.numwritten", 
8049                     FT_UINT32, BASE_DEC, NULL, 0x0, "Number of bytes written", 
8050                     HFILL }},
8051
8052                 /* Setprinterdataex RPC */
8053
8054                 { &hf_setprinterdataex_max_len,
8055                   { "Max len", "setprinterdataex.max_len",
8056                     FT_UINT32, BASE_DEC, NULL, 0, "Max len", HFILL }},
8057
8058                 { &hf_setprinterdataex_real_len,
8059                   { "Real len", "setprinterdataex.real_len",
8060                     FT_UINT32, BASE_DEC, NULL, 0, "Real len", HFILL }},
8061
8062                 { &hf_setprinterdataex_data,
8063                   { "Data", "setprinterdataex.data",
8064                     FT_BYTES, BASE_HEX, NULL, 0, "Data", HFILL }},
8065
8066                 /* Specific access rights */
8067
8068                 { &hf_access_required,
8069                   { "Access required", "spoolss.access_required",
8070                     FT_UINT32, BASE_HEX, NULL, 0x0, "Access required",
8071                     HFILL }},
8072
8073                 { &hf_server_access_admin,
8074                   { "Server admin", "spoolss.access_mask.server_admin",
8075                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
8076                     SERVER_ACCESS_ADMINISTER, "Server admin", HFILL }},
8077
8078                 { &hf_server_access_enum,
8079                   { "Server enum", "spoolss.access_mask.server_enum",
8080                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
8081                     SERVER_ACCESS_ENUMERATE, "Server enum", HFILL }},
8082
8083                 { &hf_printer_access_admin,
8084                   { "Printer admin", "spoolss.access_mask.printer_admin",
8085                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
8086                     PRINTER_ACCESS_ADMINISTER, "Printer admin", HFILL }},
8087
8088                 { &hf_printer_access_use,
8089                   { "Printer use", "spoolss.access_mask.printer_use",
8090                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
8091                     PRINTER_ACCESS_USE, "Printer use", HFILL }},
8092
8093                 { &hf_job_access_admin,
8094                   { "Job admin", "spoolss.access_mask.job_admin",
8095                     FT_BOOLEAN, 32, TFS(&flags_set_truth),
8096                     JOB_ACCESS_ADMINISTER, "Job admin", HFILL }},
8097
8098                 /* Printer information */
8099
8100                 { &hf_printer_cjobs,
8101                   { "CJobs", "spoolss.printer.cjobs", FT_UINT32,
8102                     BASE_DEC, NULL, 0, "CJobs", HFILL }},
8103
8104                 { &hf_printer_total_jobs,
8105                   { "Total jobs", "spoolss.printer.total_jobs", FT_UINT32,
8106                     BASE_DEC, NULL, 0, "Total jobs", HFILL }},
8107
8108                 { &hf_printer_total_bytes,
8109                   { "Total bytes", "spoolss.printer.total_bytes", FT_UINT32,
8110                     BASE_DEC, NULL, 0, "Total bytes", HFILL }},
8111
8112                 { &hf_printer_global_counter,
8113                   { "Global counter", "spoolss.printer.global_counter", 
8114                     FT_UINT32, BASE_DEC, NULL, 0, "Global counter", HFILL }},
8115
8116                 { &hf_printer_total_pages,
8117                   { "Total pages", "spoolss.printer.total_pages", FT_UINT32,
8118                     BASE_DEC, NULL, 0, "Total pages", HFILL }},
8119
8120                 { &hf_printer_major_version,
8121                   { "Major version", "spoolss.printer.major_version", 
8122                     FT_UINT16, BASE_DEC, NULL, 0, "Major version", HFILL }},
8123
8124                 { &hf_printer_build_version,
8125                   { "Build version", "spoolss.printer.build_version", 
8126                     FT_UINT16, BASE_DEC, NULL, 0, "Build version", HFILL }},
8127
8128                 { &hf_printer_unk7,
8129                   { "Unknown 7", "spoolss.printer.unknown7", FT_UINT32,
8130                     BASE_DEC, NULL, 0, "Unknown 7", HFILL }},           
8131
8132                 { &hf_printer_unk8,
8133                   { "Unknown 8", "spoolss.printer.unknown8", FT_UINT32,
8134                     BASE_DEC, NULL, 0, "Unknown 8", HFILL }},           
8135
8136                 { &hf_printer_unk9,
8137                   { "Unknown 9", "spoolss.printer.unknown9", FT_UINT32,
8138                     BASE_DEC, NULL, 0, "Unknown 9", HFILL }},           
8139
8140                 { &hf_printer_session_ctr,
8141                   { "Session counter", "spoolss.printer.session_ctr", 
8142                     FT_UINT32, BASE_DEC, NULL, 0, "Sessopm counter", HFILL }},
8143
8144                 { &hf_printer_unk11,
8145                   { "Unknown 11", "spoolss.printer.unknown11", FT_UINT32,
8146                     BASE_DEC, NULL, 0, "Unknown 11", HFILL }},          
8147
8148                 { &hf_printer_printer_errors,
8149                   { "Printer errors", "spoolss.printer.printer_errors", 
8150                     FT_UINT32, BASE_DEC, NULL, 0, "Printer errors", HFILL }},
8151
8152                 { &hf_printer_unk13,
8153                   { "Unknown 13", "spoolss.printer.unknown13", FT_UINT32,
8154                     BASE_DEC, NULL, 0, "Unknown 13", HFILL }},          
8155
8156                 { &hf_printer_unk14,
8157                   { "Unknown 14", "spoolss.printer.unknown14", FT_UINT32,
8158                     BASE_DEC, NULL, 0, "Unknown 14", HFILL }},          
8159
8160                 { &hf_printer_unk15,
8161                   { "Unknown 15", "spoolss.printer.unknown15", FT_UINT32,
8162                     BASE_DEC, NULL, 0, "Unknown 15", HFILL }},          
8163
8164                 { &hf_printer_unk16,
8165                   { "Unknown 16", "spoolss.printer.unknown16", FT_UINT32,
8166                     BASE_DEC, NULL, 0, "Unknown 16", HFILL }},          
8167
8168                 { &hf_printer_changeid,
8169                   { "Change id", "spoolss.printer.changeid", FT_UINT32,
8170                     BASE_DEC, NULL, 0, "Change id", HFILL }},           
8171
8172                 { &hf_printer_unk18,
8173                   { "Unknown 18", "spoolss.printer.unknown18", FT_UINT32,
8174                     BASE_DEC, NULL, 0, "Unknown 18", HFILL }},          
8175
8176                 { &hf_printer_unk20,
8177                   { "Unknown 20", "spoolss.printer.unknown20", FT_UINT32,
8178                     BASE_DEC, NULL, 0, "Unknown 20", HFILL }},          
8179
8180                 { &hf_printer_c_setprinter,
8181                   { "Csetprinter", "spoolss.printer.c_setprinter", 
8182                     FT_UINT32, BASE_DEC, NULL, 0, "Csetprinter", HFILL }},
8183
8184                 { &hf_printer_unk22,
8185                   { "Unknown 22", "spoolss.printer.unknown22", 
8186                     FT_UINT16, BASE_DEC, NULL, 0, "Unknown 22", HFILL }},
8187
8188                 { &hf_printer_unk23,
8189                   { "Unknown 23", "spoolss.printer.unknown23", 
8190                     FT_UINT16, BASE_DEC, NULL, 0, "Unknown 23", HFILL }},
8191
8192                 { &hf_printer_unk24,
8193                   { "Unknown 24", "spoolss.printer.unknown24", 
8194                     FT_UINT16, BASE_DEC, NULL, 0, "Unknown 24", HFILL }},
8195
8196                 { &hf_printer_unk25,
8197                   { "Unknown 25", "spoolss.printer.unknown25", 
8198                     FT_UINT16, BASE_DEC, NULL, 0, "Unknown 25", HFILL }},
8199
8200                 { &hf_printer_unk26,
8201                   { "Unknown 26", "spoolss.printer.unknown26", 
8202                     FT_UINT16, BASE_DEC, NULL, 0, "Unknown 26", HFILL }},
8203
8204                 { &hf_printer_unk27,
8205                   { "Unknown 27", "spoolss.printer.unknown27", 
8206                     FT_UINT16, BASE_DEC, NULL, 0, "Unknown 27", HFILL }},
8207
8208                 { &hf_printer_unk28,
8209                   { "Unknown 28", "spoolss.printer.unknown28", 
8210                     FT_UINT16, BASE_DEC, NULL, 0, "Unknown 28", HFILL }},
8211
8212                 { &hf_printer_unk29,
8213                   { "Unknown 29", "spoolss.printer.unknown29", 
8214                     FT_UINT16, BASE_DEC, NULL, 0, "Unknown 29", HFILL }},
8215
8216                 { &hf_printer_flags,
8217                   { "Flags", "spoolss.printer.flags", 
8218                     FT_UINT32, BASE_HEX, NULL, 0, "Flags", HFILL }},
8219
8220                 { &hf_printer_guid,
8221                   { "GUID", "spoolss.printer.guid", FT_STRING, 
8222                     BASE_NONE, NULL, 0, "GUID", HFILL }},
8223
8224                 { &hf_printer_action,
8225                   { "Action", "spoolss.printer.action", FT_UINT32, BASE_DEC,
8226                    VALS(getprinter_action_vals), 0, "Action", HFILL }},
8227         };
8228
8229         static gint *ett[] = {
8230                 &ett_dcerpc_spoolss,
8231                 &ett_PRINTER_DATATYPE,
8232                 &ett_DEVMODE_CTR,
8233                 &ett_DEVMODE,
8234                 &ett_DEVMODE_fields,
8235                 &ett_USER_LEVEL_CTR,
8236                 &ett_USER_LEVEL_1,
8237                 &ett_BUFFER,
8238                 &ett_PRINTER_INFO,
8239                 &ett_SPOOL_PRINTER_INFO_LEVEL,
8240                 &ett_PRINTER_INFO_0,
8241                 &ett_PRINTER_INFO_1,
8242                 &ett_PRINTER_INFO_2,
8243                 &ett_PRINTER_INFO_3,
8244                 &ett_PRINTER_INFO_7,
8245                 &ett_RELSTR,
8246                 &ett_RELSTR_ARRAY,
8247                 &ett_FORM_REL,
8248                 &ett_FORM_CTR,
8249                 &ett_FORM_1,
8250                 &ett_JOB_INFO_1,
8251                 &ett_JOB_INFO_2,
8252                 &ett_SEC_DESC_BUF,
8253                 &ett_SYSTEM_TIME,
8254                 &ett_DOC_INFO_1,
8255                 &ett_DOC_INFO,
8256                 &ett_DOC_INFO_CTR,
8257                 &ett_printerdata_value,
8258                 &ett_printerdata_data,
8259                 &ett_writeprinter_buffer,
8260                 &ett_DRIVER_INFO_1,
8261                 &ett_DRIVER_INFO_3,
8262                 &ett_rffpcnex_flags,
8263                 &ett_notify_options_flags,
8264                 &ett_NOTIFY_INFO_DATA,
8265                 &ett_NOTIFY_OPTION,
8266                 &ett_printer_attributes,
8267                 &ett_job_status,
8268                 &ett_enumprinters_flags,
8269                 &ett_PRINTER_DATA_CTR,
8270                 &ett_printer_enumdataex_value,
8271         };
8272
8273         proto_dcerpc_spoolss = proto_register_protocol(
8274                 "Microsoft Spool Subsystem", "SPOOLSS", "spoolss");
8275
8276         proto_register_field_array(proto_dcerpc_spoolss, hf, array_length(hf));
8277
8278         proto_register_subtree_array(ett, array_length(ett));
8279 }
8280
8281 /* Protocol handoff */
8282
8283 static e_uuid_t uuid_dcerpc_spoolss = {
8284         0x12345678, 0x1234, 0xabcd,
8285         { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
8286 };
8287
8288 static guint16 ver_dcerpc_spoolss = 1;
8289
8290 void
8291 proto_reg_handoff_dcerpc_spoolss(void)
8292 {
8293         /* Register protocol as dcerpc */
8294
8295         dcerpc_init_uuid(proto_dcerpc_spoolss, ett_dcerpc_spoolss,
8296                          &uuid_dcerpc_spoolss, ver_dcerpc_spoolss,
8297                          dcerpc_spoolss_dissectors, hf_opnum);
8298 }