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