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