1 /* packet-dcerpc-spoolss.c
2 * Routines for SMB \PIPE\spoolss packet disassembly
3 * Copyright 2001-2002, Tim Potter <tpot@samba.org>
5 * $Id: packet-dcerpc-spoolss.c,v 1.20 2002/04/24 03:08:49 tpot Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
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.
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.
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.
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"
39 #include "packet-smb-common.h"
42 * New system for handling pointers and buffers. We act more like the NDR
43 * specification and have a list of deferred pointers which are processed
44 * after a structure has been parsed.
46 * Each structure has a parse function which takes as an argument a GList.
47 * As pointers are processed, they are appended onto this list. When the
48 * structure is complete, the pointers (referents) are processed by calling
49 * prs_referents(). In the case of function arguments, the
50 * prs_struct_and_referents() function is called as pointers are always
51 * processed immediately after the argument.
54 typedef int prs_fn(tvbuff_t *tvb, int offset, packet_info *pinfo,
55 proto_tree *tree, GList **dp_list, void **data);
57 /* Deferred referent */
60 prs_fn *fn; /* Parse function to call */
61 proto_tree *tree; /* Tree context */
64 /* A structure to hold needed ethereal state to pass to GList foreach
67 struct deferred_ptr_state {
75 void defer_ptr(GList **list, prs_fn *fn, proto_tree *tree)
77 struct deferred_ptr *dr;
79 dr = g_malloc(sizeof(struct deferred_ptr));
84 *list = g_list_append(*list, dr);
89 static int prs_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo,
90 proto_tree *tree, guint32 *data, char *name)
94 offset = prs_uint32(tvb, offset, pinfo, tree, &ptr, NULL);
97 proto_tree_add_text(tree, tvb, offset - 4, 4,
98 "%s pointer: 0x%08x", name, ptr);
106 /* Iterator function for prs_referents */
108 static void dr_iterator(gpointer data, gpointer user_data)
110 struct deferred_ptr *dp = (struct deferred_ptr *)data;
111 struct deferred_ptr_state *s = (struct deferred_ptr_state *)user_data;
115 *s->poffset = dp->fn(s->tvb, *s->poffset, s->pinfo, dp->tree,
116 s->dp_list, s->ptr_data);
119 s->ptr_data++; /* Ready for next parse fn */
122 /* Call the parse function for each element in the deferred pointers list.
123 If there are any additional pointers in these structures they are pushed
124 onto parent_dp_list. */
126 int prs_referents(tvbuff_t *tvb, int offset, packet_info *pinfo,
127 proto_tree *tree, GList **dp_list, GList **list,
130 struct deferred_ptr_state s;
131 int new_offset = offset;
133 /* Create a list of void pointers to store return data */
136 int len = g_list_length(*dp_list) * sizeof(void *);
139 *ptr_data = malloc(len);
140 memset(*ptr_data, 0, len);
145 /* Set up iterator data */
148 s.poffset = &new_offset;
151 s.ptr_data = ptr_data ? *ptr_data : NULL;
153 g_list_foreach(*list, dr_iterator, &s);
155 *list = NULL; /* XXX: free list */
160 /* Parse a structure then clean up any deferred referants it creates. */
162 static int prs_struct_and_referents(tvbuff_t *tvb, int offset,
163 packet_info *pinfo, proto_tree *tree,
164 prs_fn *fn, void **data, void ***ptr_data)
166 GList *dp_list = NULL;
168 offset = fn(tvb, offset, pinfo, tree, &dp_list, data);
170 offset = prs_referents(tvb, offset, pinfo, tree, &dp_list,
176 /* Parse a Win32 error, basically a DOS error. The spoolss API doesn't
177 use NT status codes. */
179 static int prs_werror(tvbuff_t *tvb, int offset, packet_info *pinfo,
180 proto_tree *tree, guint32 *data)
184 offset = prs_uint32(tvb, offset, pinfo, tree, &status, NULL);
187 proto_tree_add_text(tree, tvb, offset - 4, 4, "Status: %s",
188 val_to_str(status, DOS_errors,
191 if (status != 0 && check_col(pinfo->cinfo, COL_INFO))
192 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
193 val_to_str(status, DOS_errors,
202 /* Display a policy handle in the protocol tree */
204 static gint ett_POLICY_HND = -1;
206 static void display_pol(proto_tree *tree, tvbuff_t *tvb, int offset,
207 const guint8 *policy_hnd)
210 char *pol_name = NULL;
211 int pol_open_frame = 0, pol_close_frame = 0;
214 dcerpc_smb_fetch_pol(policy_hnd, &pol_name, &pol_open_frame,
217 item = proto_tree_add_text(tree, tvb, offset, 20,
219 pol_name ? ": " : "",
220 pol_name ? pol_name : "");
222 subtree = proto_item_add_subtree(item, ett_POLICY_HND);
225 proto_tree_add_text(subtree, tvb, offset, 0,
226 "Opened in frame %u", pol_open_frame);
229 proto_tree_add_text(subtree, tvb, offset, 0,
230 "Closed in frame %u", pol_close_frame);
232 proto_tree_add_text(subtree, tvb, offset, 20, "Policy Handle: %s",
233 tvb_bytes_to_str(tvb, offset, 20));
237 * SpoolssClosePrinter
240 static int SpoolssClosePrinter_q(tvbuff_t *tvb, int offset,
241 packet_info *pinfo, proto_tree *tree,
244 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
245 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
246 const guint8 *policy_hnd;
248 /* Update informational fields */
250 if (check_col(pinfo->cinfo, COL_INFO))
251 col_set_str(pinfo->cinfo, COL_INFO, "ClosePrinter request");
253 if (dcv->rep_frame != 0)
254 proto_tree_add_text(tree, tvb, offset, 0,
255 "Response in frame %u", dcv->rep_frame);
258 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
260 dcerpc_smb_store_pol(policy_hnd, NULL, 0, pinfo->fd->num);
262 display_pol(tree, tvb, offset - 20, policy_hnd);
264 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
269 static int SpoolssClosePrinter_r(tvbuff_t *tvb, int offset,
270 packet_info *pinfo, proto_tree *tree,
273 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
274 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
275 const guint8 *policy_hnd;
277 /* Update informational fields */
279 if (check_col(pinfo->cinfo, COL_INFO))
280 col_set_str(pinfo->cinfo, COL_INFO, "ClosePrinter response");
282 if (dcv->req_frame != 0)
283 proto_tree_add_text(tree, tvb, offset, 0,
284 "Request in frame %u", dcv->req_frame);
288 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
290 display_pol(tree, tvb, offset - 20, policy_hnd);
292 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
294 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
299 /* Parse a UNISTR2 structure */
301 static gint ett_UNISTR2 = -1;
303 static int prs_UNISTR2_dp(tvbuff_t *tvb, int offset, packet_info *pinfo,
304 proto_tree *tree, GList **dp_list, void **data)
308 guint32 length, the_offset, max_len;
309 int old_offset = offset;
313 offset = prs_uint32(tvb, offset, pinfo, tree, &length, NULL);
314 offset = prs_uint32(tvb, offset, pinfo, tree, &the_offset, NULL);
315 offset = prs_uint32(tvb, offset, pinfo, tree, &max_len, NULL);
317 offset = prs_uint16s(tvb, offset, pinfo, tree, max_len, &data16_offset,
320 text = fake_unicode(tvb, data16_offset, max_len);
322 item = proto_tree_add_text(tree, tvb, old_offset, offset - old_offset,
323 "UNISTR2: %s", text);
325 subtree = proto_item_add_subtree(item, ett_UNISTR2);
332 proto_tree_add_text(subtree, tvb, old_offset, 4, "Length: %u", length);
336 proto_tree_add_text(subtree, tvb, old_offset, 4, "Offset: %u",
341 proto_tree_add_text(subtree, tvb, old_offset, 4, "Max length: %u",
346 proto_tree_add_text(subtree, tvb, old_offset, max_len * 2, "Data");
352 * SpoolssGetPrinterData
355 static int SpoolssGetPrinterData_q(tvbuff_t *tvb, int offset,
356 packet_info *pinfo, proto_tree *tree,
359 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
360 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
361 char *value_name = NULL;
362 const guint8 *policy_hnd;
364 /* Update informational fields */
366 if (check_col(pinfo->cinfo, COL_INFO))
367 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinterData request");
369 if (dcv->rep_frame != 0)
370 proto_tree_add_text(tree, tvb, offset, 0,
371 "Response in frame %u", dcv->rep_frame);
375 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
377 display_pol(tree, tvb, offset - 20, policy_hnd);
379 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
380 prs_UNISTR2_dp, (void **)&value_name,
383 if (check_col(pinfo->cinfo, COL_INFO))
384 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
388 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Size");
390 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
395 static int SpoolssGetPrinterData_r(tvbuff_t *tvb, int offset,
396 packet_info *pinfo, proto_tree *tree,
399 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
400 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
401 GList *dp_list = NULL;
404 /* Update information fields */
406 if (check_col(pinfo->cinfo, COL_INFO))
407 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinterData response");
409 if (dcv->req_frame != 0)
410 proto_tree_add_text(tree, tvb, offset, 0,
411 "Request in frame %u", dcv->req_frame);
415 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
417 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
418 val_to_str(type, reg_datatypes, "Unknown type"));
420 offset = prs_uint32(tvb, offset, pinfo, tree, &size, "Size");
422 offset = prs_uint8s(tvb, offset, pinfo, tree, size, NULL, "Data");
424 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
426 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
428 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
434 * SpoolssGetPrinterDataEx
437 static int SpoolssGetPrinterDataEx_q(tvbuff_t *tvb, int offset,
438 packet_info *pinfo, proto_tree *tree,
441 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
442 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
443 char *key_name, *value_name;
444 const guint8 *policy_hnd;
446 /* Update informational fields */
448 if (check_col(pinfo->cinfo, COL_INFO))
449 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinterDataEx request");
451 if (dcv->rep_frame != 0)
452 proto_tree_add_text(tree, tvb, offset, 0,
453 "Response in frame %u", dcv->rep_frame);
457 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
459 display_pol(tree, tvb, offset - 20, policy_hnd);
461 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
462 prs_UNISTR2_dp, (void **)&key_name,
466 * Register a cleanup function in case on of our tvbuff accesses
467 * throws an exception. We need to clean up key_name.
469 CLEANUP_PUSH(g_free, key_name);
471 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
472 prs_UNISTR2_dp, (void **)&value_name,
475 if (check_col(pinfo->cinfo, COL_INFO))
476 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s/%s",
477 key_name, value_name);
480 * We're done with key_name, so we can call the cleanup handler to
481 * free it, and then pop the cleanup handler.
483 CLEANUP_CALL_AND_POP;
486 * We're also done with value_name.
490 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Size");
492 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
497 static int SpoolssGetPrinterDataEx_r(tvbuff_t *tvb, int offset,
498 packet_info *pinfo, proto_tree *tree,
501 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
502 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
505 /* Update informational fields */
507 if (check_col(pinfo->cinfo, COL_INFO))
508 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinterDataEx response");
510 if (dcv->req_frame != 0)
511 proto_tree_add_text(tree, tvb, offset, 0,
512 "Request in frame %u", dcv->req_frame);
516 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
518 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
519 val_to_str(type, reg_datatypes, "Unknown type"));
521 offset = prs_uint32(tvb, offset, pinfo, tree, &size, "Size");
523 offset = prs_uint8s(tvb, offset, pinfo, tree, size, NULL, "Data");
525 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
527 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
529 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
535 * SpoolssSetPrinterData
538 static int SpoolssSetPrinterData_q(tvbuff_t *tvb, int offset,
539 packet_info *pinfo, proto_tree *tree,
542 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
543 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
544 char *value_name = NULL;
545 guint32 type, max_len;
546 const guint8 *policy_hnd;
548 /* Update informational fields */
550 if (check_col(pinfo->cinfo, COL_INFO))
551 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinterData request");
553 if (dcv->rep_frame != 0)
554 proto_tree_add_text(tree, tvb, offset, 0,
555 "Response in frame %u", dcv->rep_frame);
559 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
561 display_pol(tree, tvb, offset - 20, policy_hnd);
563 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
564 prs_UNISTR2_dp, (void **)&value_name,
567 if (check_col(pinfo->cinfo, COL_INFO))
568 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
572 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
574 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
575 val_to_str(type, reg_datatypes, "Unknown type"));
577 offset = prs_uint32(tvb, offset, pinfo, tree, &max_len, "Max length");
579 offset = prs_uint8s(tvb, offset, pinfo, tree, max_len, NULL,
582 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real length");
584 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
589 static int SpoolssSetPrinterData_r(tvbuff_t *tvb, int offset,
590 packet_info *pinfo, proto_tree *tree,
593 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
594 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
595 GList *dp_list = NULL;
597 /* Update informational fields */
599 if (check_col(pinfo->cinfo, COL_INFO))
600 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinterData response");
602 if (dcv->req_frame != 0)
603 proto_tree_add_text(tree, tvb, offset, 0,
604 "Request in frame %u", dcv->req_frame);
608 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
610 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
616 * SpoolssSetPrinterDataEx
619 static int SpoolssSetPrinterDataEx_q(tvbuff_t *tvb, int offset,
620 packet_info *pinfo, proto_tree *tree,
623 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
624 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
625 GList *dp_list = NULL;
626 char *key_name, *value_name;
627 guint32 type, max_len;
628 const guint8 *policy_hnd;
630 /* Update informational fields */
632 if (check_col(pinfo->cinfo, COL_INFO))
633 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinterDataEx request");
635 if (dcv->rep_frame != 0)
636 proto_tree_add_text(tree, tvb, offset, 0,
637 "Response in frame %u", dcv->rep_frame);
641 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
643 display_pol(tree, tvb, offset - 20, policy_hnd);
645 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
646 prs_UNISTR2_dp, (void **)&key_name,
649 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
650 prs_UNISTR2_dp, (void **)&value_name,
653 if (check_col(pinfo->cinfo, COL_INFO))
654 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s/%s",
655 key_name, value_name);
660 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
662 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
663 val_to_str(type, reg_datatypes, "Unknown type"));
665 offset = prs_uint32(tvb, offset, pinfo, tree, &max_len, "Max length");
667 offset = prs_uint8s(tvb, offset, pinfo, tree, max_len, NULL,
670 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real length");
672 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
677 static int SpoolssSetPrinterDataEx_r(tvbuff_t *tvb, int offset,
678 packet_info *pinfo, proto_tree *tree,
681 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
682 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
683 GList *dp_list = NULL;
685 /* Update informational fields */
687 if (check_col(pinfo->cinfo, COL_INFO))
688 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinterDataEx response");
690 if (dcv->req_frame != 0)
691 proto_tree_add_text(tree, tvb, offset, 0,
692 "Request in frame %u", dcv->req_frame);
696 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
698 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
703 /* Yet another way to represent a unicode string - sheesh. */
705 static int prs_uint16uni(tvbuff_t *tvb, int offset, packet_info *pinfo,
706 proto_tree *tree, void **data, char *name)
708 gint len = 0, remaining, i;
711 offset = prs_align(offset, 2);
713 /* Get remaining data in buffer as a string */
715 remaining = tvb_length_remaining(tvb, offset)/2;
716 text = fake_unicode(tvb, offset, remaining);
720 proto_tree_add_text(tree, tvb, offset, (len + 1) * 2,
721 "%s: %s", name ? name : "UINT16UNI",
729 return offset + (len + 1) * 2;
736 static gint ett_DEVMODE = -1;
738 static int prs_DEVMODE(tvbuff_t *tvb, int offset, packet_info *pinfo,
739 proto_tree *tree, GList **dp_list, void **data)
746 item = proto_tree_add_text(tree, tvb, offset, 0, "DEVMODE");
748 subtree = proto_item_add_subtree(item, ett_DEVMODE);
750 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Size");
752 /* The device name is stored in a 32-wchar buffer */
754 prs_uint16uni(tvb, offset, pinfo, subtree, NULL, "Devicename");
757 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Spec version");
758 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Driver version");
759 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Size");
760 offset = prs_uint16(tvb, offset, pinfo, subtree, &extra, "Driver extra");
762 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Fields");
764 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Orientation");
765 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Paper size");
766 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Paper length");
767 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Paper width");
768 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Scale");
769 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Copies");
770 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Default source");
771 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Print quality");
772 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Color");
773 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Duplex");
774 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Y resolution");
775 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "TT option");
776 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Collate");
778 prs_uint16uni(tvb, offset, pinfo, subtree, NULL, "Form name");
781 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Log pixels");
783 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Bits per pel");
784 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Pels width");
785 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Pels height");
786 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Display flags");
787 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Display frequency");
788 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "ICM method");
789 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "ICM intent");
790 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Media type");
791 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Dither type");
792 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Reserved");
793 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Reserved");
794 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Panning width");
795 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Panning height");
798 offset = prs_uint8s(tvb, offset, pinfo, subtree, extra, NULL,
805 * Relative string given by offset into the current buffer. Note that
806 * the offset for subsequent relstrs are against the structure start, not
807 * the point where the offset is parsed from.
810 static gint ett_RELSTR = -1;
812 static int prs_relstr(tvbuff_t *tvb, int offset, packet_info *pinfo,
813 proto_tree *tree, GList **dp_list, int struct_start,
814 void **data, char *name)
818 guint32 relstr_offset, relstr_start, relstr_end;
820 char *text = strdup("NULL");
821 gint len = 0, remaining, i;
823 offset = prs_uint32(tvb, offset, pinfo, tree, &relstr_offset, NULL);
825 /* A relative offset of zero is a NULL string */
827 relstr_start = relstr_offset + struct_start;
830 relstr_end = prs_uint16uni(tvb, relstr_start, pinfo, tree,
831 (void **)&text, NULL);
835 item = proto_tree_add_text(tree, tvb, relstr_start,
836 relstr_end - relstr_start, "%s: %s",
837 name ? name : "RELSTR", text);
839 subtree = proto_item_add_subtree(item, ett_RELSTR);
846 proto_tree_add_text(subtree, tvb, offset - 4, 4,
847 "Relative offset: %d", relstr_offset);
849 proto_tree_add_text(subtree, tvb, relstr_start,
850 relstr_end - relstr_start, "Data");
859 static gint ett_PRINTER_INFO_0 = -1;
861 static int prs_PRINTER_INFO_0(tvbuff_t *tvb, int offset, packet_info *pinfo,
862 proto_tree *tree, GList **dp_list, void **data)
864 int struct_start = offset;
866 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
867 NULL, "Printer name");
868 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
869 NULL, "Server name");
871 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "CJobs");
872 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Total jobs");
873 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Total bytes");
875 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Year");
876 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Month");
877 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Day of week");
878 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Day");
879 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Hour");
880 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Minute");
881 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Second");
882 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Milliseconds");
884 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Global counter");
885 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Total pages");
887 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Major version");
888 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Build version");
890 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
891 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
892 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
893 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Session counter");
894 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
895 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Printer errors");
896 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
897 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
898 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
899 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
900 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Change id");
901 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
902 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Status");
903 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
904 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "C_setprinter");
906 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
907 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
908 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
909 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
910 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
911 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
912 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
913 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
922 static gint ett_PRINTER_INFO_1 = -1;
924 static int prs_PRINTER_INFO_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
925 proto_tree *tree, GList **dp_list, void **data)
927 int struct_start = offset;
929 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Flags");
931 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
932 NULL, "Description");
934 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
937 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
947 static gint ett_PRINTER_INFO_2 = -1;
949 static int prs_PRINTER_INFO_2(tvbuff_t *tvb, int offset, packet_info *pinfo,
950 proto_tree *tree, int len, GList **dp_list,
953 int struct_start = offset;
956 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
957 NULL, "Server name");
959 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
960 NULL, "Printer name");
962 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
965 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
968 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
969 NULL, "Driver name");
971 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
974 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
977 /* This is a relative devicemode */
979 offset = prs_uint32(tvb, offset, pinfo, tree, &rel_offset, NULL);
981 prs_DEVMODE(tvb, struct_start + rel_offset - 4, pinfo, tree,
984 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
985 NULL, "Separator file");
987 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
988 NULL, "Print processor");
990 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
993 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
996 /* This is a relative security descriptor */
998 offset = prs_uint32(tvb, offset, pinfo, tree, &rel_offset, NULL);
1000 dissect_nt_sec_desc(tvb, pinfo, struct_start + rel_offset, tree, len);
1002 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Attributes");
1004 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Priority");
1006 offset = prs_uint32(tvb, offset, pinfo, tree, NULL,
1007 "Default priority");
1009 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Start time");
1011 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "End time");
1013 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Status");
1015 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Jobs");
1017 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Average PPM");
1026 static gint ett_PRINTER_INFO_3 = -1;
1028 static int prs_PRINTER_INFO_3(tvbuff_t *tvb, int offset, packet_info *pinfo,
1029 proto_tree *tree, int len, GList **dp_list,
1032 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Flags");
1034 offset = dissect_nt_sec_desc(tvb, pinfo, offset, tree, len);
1043 static gint ett_DEVMODE_CTR = -1;
1045 static int prs_DEVMODE_CTR(tvbuff_t *tvb, int offset, packet_info *pinfo,
1046 proto_tree *tree, GList **dp_list, void **data)
1049 proto_tree *subtree;
1052 item = proto_tree_add_text(tree, tvb, offset, 0, "DEVMODE_CTR");
1054 subtree = proto_item_add_subtree(item, ett_DEVMODE_CTR);
1056 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Size");
1058 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Devicemode");
1061 offset = prs_DEVMODE(tvb, offset, pinfo, subtree, dp_list,
1068 * PRINTER_DEFAULT structure
1071 static gint ett_PRINTER_DEFAULT = -1;
1073 static int prs_PRINTER_DEFAULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1074 proto_tree *tree, GList **dp_list, void **data)
1076 GList *child_dp_list = NULL;
1078 proto_tree *subtree;
1079 guint32 ptr = 0, access;
1081 item = proto_tree_add_text(tree, tvb, offset, 0, "PRINTER_DEFAULT");
1083 subtree = proto_item_add_subtree(item, ett_PRINTER_DEFAULT);
1085 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Datatype");
1087 /* Not sure why this isn't a deferred pointer. I think this may be
1088 two structures stuck together. */
1091 offset = prs_UNISTR2_dp(tvb, offset, pinfo, subtree, dp_list,
1094 offset = prs_DEVMODE_CTR(tvb, offset, pinfo, subtree,
1095 &child_dp_list, NULL);
1097 offset = prs_uint32(tvb, offset, pinfo, subtree, &access, NULL);
1099 proto_tree_add_text(subtree, tvb, offset - 4, 4,
1100 "Access required: 0x%08x", access);
1102 offset = prs_referents(tvb, offset, pinfo, subtree, dp_list,
1103 &child_dp_list, NULL);
1109 * USER_LEVEL_1 structure
1112 static gint ett_USER_LEVEL_1 = -1;
1114 static int prs_USER_LEVEL_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
1115 proto_tree *tree, GList **dp_list, void **data)
1118 proto_tree *subtree;
1121 item = proto_tree_add_text(tree, tvb, offset, 0, "USER_LEVEL_1");
1123 subtree = proto_item_add_subtree(item, ett_USER_LEVEL_1);
1125 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Size");
1127 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Client name");
1130 defer_ptr(dp_list, prs_UNISTR2_dp, subtree);
1132 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "User name");
1135 defer_ptr(dp_list, prs_UNISTR2_dp, subtree);
1137 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Build");
1139 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Major");
1141 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Minor");
1143 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Processor");
1149 * USER_LEVEL structure
1152 static gint ett_USER_LEVEL = -1;
1154 static int prs_USER_LEVEL(tvbuff_t *tvb, int offset, packet_info *pinfo,
1155 proto_tree *tree, GList **parent_dp_list,
1159 proto_tree *subtree;
1163 item = proto_tree_add_text(tree, tvb, offset, 0, "USER_LEVEL");
1165 subtree = proto_item_add_subtree(item, ett_USER_LEVEL);
1167 offset = prs_uint32(tvb, offset, pinfo, subtree, &level, "Info level");
1169 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "User level");
1174 defer_ptr(parent_dp_list, prs_USER_LEVEL_1, subtree);
1177 proto_tree_add_text(
1178 tree, tvb, offset, 0,
1179 "[GetPrinter level %d not decoded]", level);
1188 * SpoolssOpenPrinterEx
1191 static int SpoolssOpenPrinterEx_q(tvbuff_t *tvb, int offset,
1192 packet_info *pinfo, proto_tree *tree,
1195 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1196 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1200 /* Update informational fields */
1202 if (check_col(pinfo->cinfo, COL_INFO))
1203 col_set_str(pinfo->cinfo, COL_INFO, "OpenPrinterEx request");
1205 if (dcv->rep_frame != 0)
1206 proto_tree_add_text(tree, tvb, offset, 0,
1207 "Response in frame %u", dcv->rep_frame);
1211 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Printer name");
1216 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1218 (void **)&printer_name,
1221 if (check_col(pinfo->cinfo, COL_INFO))
1222 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1225 /* Store printer name to match with response packet */
1227 dcv->private_data = printer_name;
1230 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1231 prs_PRINTER_DEFAULT, NULL, NULL);
1233 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "User switch");
1235 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1236 prs_USER_LEVEL, NULL, NULL);
1238 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1243 static int SpoolssOpenPrinterEx_r(tvbuff_t *tvb, int offset,
1244 packet_info *pinfo, proto_tree *tree,
1247 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1248 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1249 GList *dp_list = NULL;
1251 const guint8 *policy_hnd;
1253 /* Display informational data */
1255 if (check_col(pinfo->cinfo, COL_INFO))
1256 col_set_str(pinfo->cinfo, COL_INFO, "OpenPrinterEx response");
1258 if (dcv->req_frame != 0)
1259 proto_tree_add_text(tree, tvb, offset, 0,
1260 "Request in frame %u", dcv->req_frame);
1264 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1266 display_pol(tree, tvb, offset - 20, policy_hnd);
1268 offset = prs_werror(tvb, offset, pinfo, tree, &status);
1272 /* Associate the returned printer handle with a name */
1274 if (dcv->private_data) {
1275 dcerpc_smb_store_pol(policy_hnd, dcv->private_data,
1278 g_free(dcv->private_data);
1279 dcv->private_data = NULL;
1283 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1289 * NOTIFY_OPTION_DATA structure
1292 static gint ett_NOTIFY_OPTION_DATA = -1;
1294 static int prs_NOTIFY_OPTION_DATA(tvbuff_t *tvb, int offset,
1295 packet_info *pinfo, proto_tree *tree,
1296 GList **parent_dp_list, void **data)
1299 proto_tree *subtree;
1302 item = proto_tree_add_text(tree, tvb, offset, 0, "NOTIFY_OPTION_DATA");
1304 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION_DATA);
1306 offset = prs_uint32(tvb, offset, pinfo, subtree, &count, "Count");
1308 for (i = 0; i < count; i++)
1309 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL,
1316 * NOTIFY_OPTION structure
1319 static gint ett_NOTIFY_OPTION = -1;
1321 static int prs_NOTIFY_OPTION(tvbuff_t *tvb, int offset, packet_info *pinfo,
1322 proto_tree *tree, GList **parent_dp_list,
1326 proto_tree *subtree;
1329 item = proto_tree_add_text(tree, tvb, offset, 0, "NOTIFY_OPTION");
1331 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION);
1333 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Type");
1335 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Reserved");
1337 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Reserved");
1339 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Reserved");
1341 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Count");
1343 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Fields");
1346 defer_ptr(parent_dp_list, prs_NOTIFY_OPTION_DATA, subtree);
1352 * NOTIFY_OPTION_CTR structure
1355 static gint ett_NOTIFY_OPTION_CTR = -1;
1357 static int prs_NOTIFY_OPTION_CTR(tvbuff_t *tvb, int offset,
1358 packet_info *pinfo, proto_tree *tree,
1359 GList **dp_list, void **data)
1361 GList *child_dp_list = NULL;
1363 proto_tree *subtree;
1364 guint32 count, i, ptr;
1366 item = proto_tree_add_text(tree, tvb, offset, 0,
1367 "NOTIFY_OPTION_CTR");
1369 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION_CTR);
1371 offset = prs_uint32(tvb, offset, pinfo, subtree, &count, "Count");
1373 for (i = 0; i < count; i++)
1374 offset = prs_NOTIFY_OPTION(tvb, offset, pinfo, subtree,
1375 &child_dp_list, NULL);
1377 offset = prs_referents(tvb, offset, pinfo, subtree, dp_list,
1378 &child_dp_list, NULL);
1384 * NOTIFY_OPTION structure
1387 gint ett_NOTIFY_OPTION_ARRAY = -1;
1389 static int prs_NOTIFY_OPTION_ARRAY(tvbuff_t *tvb, int offset,
1390 packet_info *pinfo, proto_tree *tree,
1391 GList **dp_list, void **data)
1394 proto_tree *subtree;
1397 item = proto_tree_add_text(tree, tvb, offset, 0,
1398 "NOTIFY_OPTION_ARRAY");
1400 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION_ARRAY);
1402 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Version");
1404 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Flags");
1406 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Count");
1408 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Option type");
1411 defer_ptr(dp_list, prs_NOTIFY_OPTION_CTR, subtree);
1420 static int SpoolssRFFPCNEX_q(tvbuff_t *tvb, int offset,
1421 packet_info *pinfo, proto_tree *tree,
1424 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1425 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1428 const guint8 *policy_hnd;
1430 /* Update informational fields */
1432 if (check_col(pinfo->cinfo, COL_INFO))
1433 col_set_str(pinfo->cinfo, COL_INFO, "RFFPCNEX request");
1435 if (dcv->rep_frame != 0)
1436 proto_tree_add_text(tree, tvb, offset, 0,
1437 "Response in frame %u", dcv->rep_frame);
1441 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1443 display_pol(tree, tvb, offset - 20, policy_hnd);
1445 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Flags");
1447 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Options");
1449 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Local machine");
1452 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1454 (void *)&printer_name, NULL);
1456 if (check_col(pinfo->cinfo, COL_INFO))
1457 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1460 g_free(printer_name);
1463 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Printer local");
1465 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Option");
1468 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1469 prs_NOTIFY_OPTION_ARRAY,
1473 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1478 static int SpoolssRFFPCNEX_r(tvbuff_t *tvb, int offset,
1479 packet_info *pinfo, proto_tree *tree,
1482 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1483 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1485 /* Update informational fields */
1487 if (check_col(pinfo->cinfo, COL_INFO))
1488 col_set_str(pinfo->cinfo, COL_INFO, "RFFPCNEX response");
1490 if (dcv->req_frame != 0)
1491 proto_tree_add_text(tree, tvb, offset, 0,
1492 "Request in frame %u", dcv->req_frame);
1496 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
1498 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1504 * SpoolssReplyOpenPrinter
1507 static int SpoolssReplyOpenPrinter_q(tvbuff_t *tvb, int offset,
1508 packet_info *pinfo, proto_tree *tree,
1511 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1512 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1513 guint32 ptr = 0, type;
1515 /* Update informational fields */
1517 if (check_col(pinfo->cinfo, COL_INFO))
1518 col_set_str(pinfo->cinfo, COL_INFO, "ReplyOpenPrinter request");
1520 if (dcv->rep_frame != 0)
1521 proto_tree_add_text(tree, tvb, offset, 0,
1522 "Response in frame %u", dcv->rep_frame);
1526 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1527 prs_UNISTR2_dp, NULL, NULL);
1529 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Printer");
1531 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
1533 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
1534 val_to_str(type, reg_datatypes, "Unknown type"));
1536 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1538 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1540 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1545 static int SpoolssReplyOpenPrinter_r(tvbuff_t *tvb, int offset,
1546 packet_info *pinfo, proto_tree *tree,
1549 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1550 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1551 GList *dp_list = NULL;
1552 const guint8 *policy_hnd;
1554 /* Update informational fields */
1556 if (check_col(pinfo->cinfo, COL_INFO))
1557 col_set_str(pinfo->cinfo, COL_INFO, "ReplyOpenPrinter response");
1559 if (dcv->req_frame != 0)
1560 proto_tree_add_text(tree, tvb, offset, 0,
1561 "Request in frame %u", dcv->req_frame);
1565 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1567 display_pol(tree, tvb, offset - 20, policy_hnd);
1569 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
1571 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1580 static gint ett_BUFFER_DATA = -1;
1581 static gint ett_BUFFER_DATA_BUFFER = -1;
1583 struct BUFFER_DATA {
1584 proto_item *item; /* proto_item holding proto_tree */
1585 proto_tree *tree; /* proto_tree holding buffer data */
1587 int offset; /* Offset where data starts in tvb*/
1588 int size; /* Size of buffer data */
1591 static int prs_BUFFER_DATA(tvbuff_t *tvb, int offset, packet_info *pinfo,
1592 proto_tree *tree, GList **dp_list, void **data)
1594 proto_item *item, *subitem;
1595 proto_tree *subtree, *subsubtree;
1596 guint32 ptr = 0, size;
1599 item = proto_tree_add_text(tree, tvb, offset, 0, "BUFFER_DATA");
1601 subtree = proto_item_add_subtree(item, ett_BUFFER_DATA);
1603 offset = prs_uint32(tvb, offset, pinfo, subtree, &size, "Size");
1605 subitem = proto_tree_add_text(subtree, tvb, offset, size, "Data");
1607 subsubtree = proto_item_add_subtree(subitem, ett_BUFFER_DATA_BUFFER);
1609 offset = prs_uint8s(tvb, offset, pinfo, subsubtree, size,
1610 &data8_offset, NULL);
1612 /* Return some info which will help the caller "cast" the buffer
1613 data and dissect it further. */
1616 struct BUFFER_DATA *bd;
1618 bd = (struct BUFFER_DATA *)malloc(sizeof(struct BUFFER_DATA));
1621 bd->tree = subsubtree;
1623 bd->offset = data8_offset;
1636 static gint ett_BUFFER = -1;
1638 static int prs_BUFFER(tvbuff_t *tvb, int offset, packet_info *pinfo,
1639 proto_tree *tree, GList **dp_list, void **data)
1642 proto_tree *subtree;
1645 item = proto_tree_add_text(tree, tvb, offset, 0, "BUFFER");
1647 subtree = proto_item_add_subtree(item, ett_BUFFER);
1649 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Data");
1652 defer_ptr(dp_list, prs_BUFFER_DATA, subtree);
1661 static int SpoolssGetPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
1662 proto_tree *tree, char *drep)
1664 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1665 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1666 GList *dp_list = NULL;
1668 const guint8 *policy_hnd;
1670 /* Update informational fields */
1672 if (check_col(pinfo->cinfo, COL_INFO))
1673 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinter request");
1675 if (dcv->rep_frame != 0)
1676 proto_tree_add_text(tree, tvb, offset, 0,
1677 "Response in frame %u", dcv->rep_frame);
1681 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1683 display_pol(tree, tvb, offset - 20, policy_hnd);
1685 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
1687 if (check_col(pinfo->cinfo, COL_INFO))
1688 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1690 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1691 prs_BUFFER, NULL, NULL);
1693 dcv->private_data = (void *)level;
1695 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
1697 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1702 static int SpoolssGetPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
1703 proto_tree *tree, char *drep)
1705 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1706 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1707 GList *dp_list = NULL;
1709 struct BUFFER_DATA *bd = NULL;
1710 gint16 level = (guint32)dcv->private_data;
1712 /* Update informational fields */
1714 if (check_col(pinfo->cinfo, COL_INFO))
1715 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinter response");
1717 if (dcv->req_frame != 0)
1718 proto_tree_add_text(tree, tvb, offset, 0,
1719 "Request in frame %u", dcv->req_frame);
1721 if (check_col(pinfo->cinfo, COL_INFO))
1722 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1726 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1727 prs_BUFFER, NULL, &data_list);
1730 bd = (struct BUFFER_DATA *)data_list[0];
1732 if (bd && bd->tree) {
1733 proto_item_append_text(bd->item, ", PRINTER_INFO_%d", level);
1737 prs_PRINTER_INFO_0(bd->tvb, bd->offset, pinfo,
1738 bd->tree, &dp_list, NULL);
1742 prs_PRINTER_INFO_1(bd->tvb, bd->offset, pinfo,
1743 bd->tree, &dp_list, NULL);
1747 prs_PRINTER_INFO_2(bd->tvb, bd->offset, pinfo,
1748 bd->tree, bd->size, &dp_list, NULL);
1752 prs_PRINTER_INFO_3(bd->tvb, bd->offset, pinfo,
1753 bd->tree, bd->size, &dp_list, NULL);
1757 proto_tree_add_text(bd->tree, tvb, offset, 0,
1758 "[Unknown info level %d]", level);
1763 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
1765 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
1767 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1773 * SPOOL_PRINTER_INFO_LEVEL
1776 static gint ett_SPOOL_PRINTER_INFO_LEVEL = -1;
1778 static int prs_SPOOL_PRINTER_INFO_LEVEL(tvbuff_t *tvb, int offset,
1779 packet_info *pinfo, proto_tree *tree,
1780 GList **dp_list, void **data)
1783 proto_tree *subtree;
1784 guint32 ptr = 0, level;
1786 item = proto_tree_add_text(tree, tvb, offset, 0,
1787 "SPOOL_PRINTER_INFO_LEVEL");
1789 subtree = proto_item_add_subtree(item, ett_SPOOL_PRINTER_INFO_LEVEL);
1791 offset = prs_uint32(tvb, offset, pinfo, subtree, &level, "Level");
1805 static int SpoolssSetPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
1806 proto_tree *tree, char *drep)
1808 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1809 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1810 GList *dp_list = NULL;
1812 const guint8 *policy_hnd;
1814 /* Update informational fields */
1816 if (check_col(pinfo->cinfo, COL_INFO))
1817 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinter request");
1819 if (dcv->rep_frame != 0)
1820 proto_tree_add_text(tree, tvb, offset, 0,
1821 "Response in frame %u", dcv->rep_frame);
1825 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1827 display_pol(tree, tvb, offset - 20, policy_hnd);
1829 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
1831 if (check_col(pinfo->cinfo, COL_INFO))
1832 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1834 /* printer_info_level */
1836 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1837 prs_SPOOL_PRINTER_INFO_LEVEL,
1843 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Command");
1845 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1850 static int SpoolssSetPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
1851 proto_tree *tree, char *drep)
1853 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1854 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1855 GList *dp_list = NULL;
1857 /* Update informational fields */
1859 if (check_col(pinfo->cinfo, COL_INFO))
1860 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinter response");
1862 if (dcv->req_frame != 0)
1863 proto_tree_add_text(tree, tvb, offset, 0,
1864 "Request in frame %u", dcv->req_frame);
1868 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
1870 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1879 static const value_string form_type_vals[] =
1881 { FORM_USER, "FORM_USER" },
1882 { FORM_BUILTIN, "FORM_BUILTIN" },
1883 { FORM_PRINTER, "FORM_PRINTER" },
1887 static gint ett_FORM_REL = -1;
1889 static int prs_FORM_REL(tvbuff_t *tvb, int offset, packet_info *pinfo,
1890 proto_tree *tree, int struct_start, GList **dp_list,
1894 proto_tree *subtree;
1897 item = proto_tree_add_text(tree, tvb, offset, 0, "FORM_REL");
1899 subtree = proto_item_add_subtree(item, ett_FORM_REL);
1901 offset = prs_uint32(tvb, offset, pinfo, subtree, &flags, NULL);
1903 proto_tree_add_text(subtree, tvb, offset - 4, 4, "Flags: %s",
1904 val_to_str(flags, form_type_vals, "Unknown type"));
1906 offset = prs_relstr(tvb, offset, pinfo, subtree, dp_list,
1907 struct_start, NULL, "Name");
1909 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Width");
1911 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Height");
1913 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
1916 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
1919 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
1920 "Horizontal imageable length");
1922 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
1923 "Vertical imageable length");
1932 static int SpoolssEnumForms_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
1933 proto_tree *tree, char *drep)
1935 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1936 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1937 GList *dp_list = NULL;
1939 const guint8 *policy_hnd;
1941 /* Update informational fields */
1943 if (check_col(pinfo->cinfo, COL_INFO))
1944 col_set_str(pinfo->cinfo, COL_INFO, "EnumForms request");
1946 if (dcv->rep_frame != 0)
1947 proto_tree_add_text(tree, tvb, offset, 0,
1948 "Response in frame %u", dcv->rep_frame);
1952 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1954 display_pol(tree, tvb, offset - 20, policy_hnd);
1956 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
1958 dcv->private_data = (void *)level;
1960 if (check_col(pinfo->cinfo, COL_INFO))
1961 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1963 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1964 prs_BUFFER, NULL, NULL);
1966 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
1968 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1973 static int SpoolssEnumForms_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
1974 proto_tree *tree, char *drep)
1976 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1977 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1979 GList *dp_list = NULL;
1980 struct BUFFER_DATA *bd = NULL;
1983 /* Update informational fields */
1985 if (check_col(pinfo->cinfo, COL_INFO))
1986 col_set_str(pinfo->cinfo, COL_INFO, "EnumForms response");
1988 if (dcv->req_frame != 0)
1989 proto_tree_add_text(tree, tvb, offset, 0,
1990 "Request in frame %u", dcv->req_frame);
1994 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1995 prs_BUFFER, NULL, &data_list);
1997 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
1999 offset = prs_uint32(tvb, offset, pinfo, tree, &count, "Num entries");
2002 bd = (struct BUFFER_DATA *)data_list[0];
2004 CLEANUP_PUSH(g_free, bd);
2006 if (bd && bd->tree) {
2007 guint32 level = (guint32)dcv->private_data, i;
2008 GList *child_dp_list = NULL;
2010 if (check_col(pinfo->cinfo, COL_INFO))
2011 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
2013 proto_item_append_text(bd->item, ", FORM_%d", level);
2015 /* Unfortunately this array isn't in NDR format so we can't
2016 use prs_array(). The other weird thing is the
2017 struct_start being inside the loop rather than outside.
2020 for (i = 0; i < count; i++) {
2021 int struct_start = bd->offset;
2023 bd->offset = prs_FORM_REL(
2024 bd->tvb, bd->offset, pinfo, bd->tree,
2025 struct_start, &child_dp_list, NULL);
2030 CLEANUP_CALL_AND_POP;
2032 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2034 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2040 * SpoolssDeletePrinter
2043 static int SpoolssDeletePrinter_q(tvbuff_t *tvb, int offset,
2044 packet_info *pinfo, proto_tree *tree,
2047 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2048 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2049 const guint8 *policy_hnd;
2051 /* Update informational fields */
2053 if (check_col(pinfo->cinfo, COL_INFO))
2054 col_set_str(pinfo->cinfo, COL_INFO, "DeletePrinter request");
2056 if (dcv->rep_frame != 0)
2057 proto_tree_add_text(tree, tvb, offset, 0,
2058 "Response in frame %u", dcv->rep_frame);
2062 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2064 display_pol(tree, tvb, offset - 20, policy_hnd);
2066 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2071 static int SpoolssDeletePrinter_r(tvbuff_t *tvb, int offset,
2072 packet_info *pinfo, proto_tree *tree,
2075 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2076 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2077 const guint8 *policy_hnd;
2079 /* Update informational fields */
2081 if (check_col(pinfo->cinfo, COL_INFO))
2082 col_set_str(pinfo->cinfo, COL_INFO, "DeletePrinter response");
2084 if (dcv->req_frame != 0)
2085 proto_tree_add_text(tree, tvb, offset, 0,
2086 "Request in frame %u", dcv->req_frame);
2090 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2092 display_pol(tree, tvb, offset - 20, policy_hnd);
2094 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2096 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2105 static int SpoolssAddPrinterEx_q(tvbuff_t *tvb, int offset,
2106 packet_info *pinfo, proto_tree *tree,
2109 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2110 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2113 /* Update informational fields */
2115 if (check_col(pinfo->cinfo, COL_INFO))
2116 col_set_str(pinfo->cinfo, COL_INFO, "AddPrinterEx request");
2118 if (dcv->rep_frame != 0)
2119 proto_tree_add_text(tree, tvb, offset, 0,
2120 "Response in frame %u", dcv->rep_frame);
2124 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Server name");
2129 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2131 (void *)&printer_name, NULL);
2134 dcv->private_data = printer_name;
2137 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Level");
2139 /* TODO: PRINTER INFO LEVEL */
2141 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2142 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2143 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2144 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2146 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "User switch");
2148 /* TODO: USER LEVEL */
2150 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2155 static int SpoolssAddPrinterEx_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2156 proto_tree *tree, char *drep)
2158 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2159 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2161 const guint8 *policy_hnd;
2163 /* Update informational fields */
2165 if (check_col(pinfo->cinfo, COL_INFO))
2166 col_set_str(pinfo->cinfo, COL_INFO, "AddPrinterEx response");
2168 if (dcv->req_frame != 0)
2169 proto_tree_add_text(tree, tvb, offset, 0,
2170 "Request in frame %u", dcv->req_frame);
2174 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2176 display_pol(tree, tvb, offset - 20, policy_hnd);
2178 offset = prs_werror(tvb, offset, pinfo, tree, &status);
2182 /* Associate the returned printer handle with a name */
2184 if (dcv->private_data) {
2186 if (check_col(pinfo->cinfo, COL_INFO))
2188 pinfo->cinfo, COL_INFO, ", %s",
2189 (char *)dcv->private_data);
2191 dcerpc_smb_store_pol(
2192 policy_hnd, dcv->private_data, pinfo->fd->num, 0);
2194 g_free(dcv->private_data);
2195 dcv->private_data = NULL;
2199 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2205 * SpoolssEnumPrinterData
2208 static int SpoolssEnumPrinterData_q(tvbuff_t *tvb, int offset,
2209 packet_info *pinfo, proto_tree *tree,
2212 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2213 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2214 const guint8 *policy_hnd;
2216 /* Update informational fields */
2218 if (check_col(pinfo->cinfo, COL_INFO))
2219 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinterData request");
2221 if (dcv->rep_frame != 0)
2222 proto_tree_add_text(tree, tvb, offset, 0,
2223 "Response in frame %u", dcv->rep_frame);
2227 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2229 display_pol(tree, tvb, offset - 20, policy_hnd);
2231 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Index");
2233 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Value size");
2235 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Data size");
2237 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2242 static int SpoolssEnumPrinterData_r(tvbuff_t *tvb, int offset,
2243 packet_info *pinfo, proto_tree *tree,
2246 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2247 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2248 guint32 data_size, type, value_size;
2252 /* Update informational fields */
2254 if (check_col(pinfo->cinfo, COL_INFO))
2255 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinterData response");
2257 if (dcv->req_frame != 0)
2258 proto_tree_add_text(tree, tvb, offset, 0,
2259 "Request in frame %u", dcv->req_frame);
2263 offset = prs_uint32(tvb, offset, pinfo, tree, &value_size,
2266 offset = prs_uint16s(tvb, offset, pinfo, tree, value_size,
2267 &uint16s_offset, NULL);
2269 text = fake_unicode(tvb, uint16s_offset, value_size);
2271 proto_tree_add_text(tree, tvb, uint16s_offset,
2272 value_size * 2, "Value: %s", text);
2274 if (text[0] && check_col(pinfo->cinfo, COL_INFO))
2275 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", text);
2279 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real value size");
2281 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
2283 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
2284 val_to_str(type, reg_datatypes, "Unknown type"));
2286 offset = prs_uint32(tvb, offset, pinfo, tree, &data_size, "Data size");
2288 offset = prs_uint8s(tvb, offset, pinfo, tree, data_size, NULL,
2291 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real data size");
2293 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2295 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2301 * SpoolssEnumPrinters
2304 static int SpoolssEnumPrinters_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2305 proto_tree *tree, char *drep)
2307 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2308 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2311 /* Update informational fields */
2313 if (check_col(pinfo->cinfo, COL_INFO))
2314 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinters request");
2316 if (dcv->rep_frame != 0)
2317 proto_tree_add_text(tree, tvb, offset, 0,
2318 "Response in frame %u", dcv->rep_frame);
2322 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Flags");
2324 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Devicemode");
2327 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2328 prs_UNISTR2_dp, NULL, NULL);
2330 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2332 if (check_col(pinfo->cinfo, COL_INFO))
2333 col_append_fstr(pinfo->cinfo, COL_INFO, ", level, %d", level);
2335 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2336 prs_BUFFER, NULL, NULL);
2338 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
2340 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2345 static int SpoolssEnumPrinters_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2346 proto_tree *tree, char *drep)
2348 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2349 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2351 /* Update informational fields */
2353 if (check_col(pinfo->cinfo, COL_INFO))
2354 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinters response");
2356 if (dcv->req_frame != 0)
2357 proto_tree_add_text(tree, tvb, offset, 0,
2358 "Request in frame %u", dcv->req_frame);
2362 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2363 prs_BUFFER, NULL, NULL);
2365 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
2367 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Returned");
2369 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2371 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2380 static int SpoolssAddPrinterDriver_q(tvbuff_t *tvb, int offset,
2381 packet_info *pinfo, proto_tree *tree,
2384 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2385 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2387 /* Update informational fields */
2389 if (check_col(pinfo->cinfo, COL_INFO))
2390 col_set_str(pinfo->cinfo, COL_INFO, "AddPrinterDriver request");
2392 if (dcv->rep_frame != 0)
2393 proto_tree_add_text(tree, tvb, offset, 0,
2394 "Response in frame %u", dcv->rep_frame);
2398 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2403 static int SpoolssAddPrinterDriver_r(tvbuff_t *tvb, int offset,
2404 packet_info *pinfo, proto_tree *tree,
2407 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2408 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2410 /* Update informational fields */
2412 if (check_col(pinfo->cinfo, COL_INFO))
2413 col_set_str(pinfo->cinfo, COL_INFO, "AddPrinterDriver response");
2415 if (dcv->req_frame != 0)
2416 proto_tree_add_text(tree, tvb, offset, 0,
2417 "Request in frame %u", dcv->req_frame);
2421 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2423 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2432 static gint ett_FORM_1 = -1;
2434 static int prs_FORM_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
2435 proto_tree *tree, GList **dp_list, void **data)
2438 proto_tree *subtree;
2439 guint32 ptr = 0, flags;
2441 item = proto_tree_add_text(tree, tvb, offset, 0, "FORM_1");
2443 subtree = proto_item_add_subtree(item, ett_FORM_1);
2445 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Name");
2448 defer_ptr(dp_list, prs_UNISTR2_dp, subtree);
2450 offset = prs_uint32(tvb, offset, pinfo, subtree, &flags, NULL);
2452 proto_tree_add_text(subtree, tvb, offset - 4, 4, "Flags: %s",
2453 val_to_str(flags, form_type_vals, "Unknown type"));
2455 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Unknown");
2457 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Width");
2459 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Height");
2461 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
2464 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
2467 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
2468 "Horizontal imageable length");
2470 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
2471 "Vertical imageable length");
2480 static gint ett_FORM_CTR = -1;
2482 static int prs_FORM_CTR(tvbuff_t *tvb, int offset, packet_info *pinfo,
2483 proto_tree *tree, GList **dp_list, void **data)
2486 proto_tree *subtree;
2489 item = proto_tree_add_text(tree, tvb, offset, 0, "FORM_CTR");
2491 subtree = proto_item_add_subtree(item, ett_FORM_CTR);
2493 offset = prs_uint32(tvb, offset, pinfo, subtree, &level, "Level");
2497 offset = prs_struct_and_referents(tvb, offset, pinfo, subtree,
2498 prs_FORM_1, NULL, NULL);
2501 proto_tree_add_text(subtree, tvb, offset, 0,
2502 "[Unknown info level %d]", level);
2513 static int SpoolssAddForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2514 proto_tree *tree, char *drep)
2516 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2517 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2518 const guint8 *policy_hnd;
2521 /* Update informational fields */
2523 if (check_col(pinfo->cinfo, COL_INFO))
2524 col_set_str(pinfo->cinfo, COL_INFO, "AddForm request");
2526 if (dcv->rep_frame != 0)
2527 proto_tree_add_text(tree, tvb, offset, 0,
2528 "Response in frame %u", dcv->rep_frame);
2532 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2534 display_pol(tree, tvb, offset - 20, policy_hnd);
2536 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2538 if (check_col(pinfo->cinfo, COL_INFO))
2539 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
2541 /* Store info level to match with response packet */
2543 dcv->private_data = (void *)level;
2545 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2546 prs_FORM_CTR, NULL, NULL);
2548 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2553 static int SpoolssAddForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2554 proto_tree *tree, char *drep)
2556 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2557 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2559 /* Update informational fields */
2561 if (check_col(pinfo->cinfo, COL_INFO))
2562 col_set_str(pinfo->cinfo, COL_INFO, "AddForm response");
2564 if (dcv->req_frame != 0)
2565 proto_tree_add_text(tree, tvb, offset, 0,
2566 "Request in frame %u", dcv->req_frame);
2570 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2572 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2581 static int SpoolssDeleteForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2582 proto_tree *tree, char *drep)
2584 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2585 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2586 const guint8 *policy_hnd;
2589 /* Update informational fields */
2591 if (check_col(pinfo->cinfo, COL_INFO))
2592 col_set_str(pinfo->cinfo, COL_INFO, "DeleteForm request");
2594 if (dcv->rep_frame != 0)
2595 proto_tree_add_text(tree, tvb, offset, 0,
2596 "Response in frame %u", dcv->rep_frame);
2600 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2602 display_pol(tree, tvb, offset - 20, policy_hnd);
2604 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2605 prs_UNISTR2_dp, (void **)&form_name,
2608 if (check_col(pinfo->cinfo, COL_INFO))
2609 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", form_name);
2613 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2618 static int SpoolssDeleteForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2619 proto_tree *tree, char *drep)
2621 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2622 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2624 /* Update informational fields */
2626 if (check_col(pinfo->cinfo, COL_INFO))
2627 col_set_str(pinfo->cinfo, COL_INFO, "DeleteForm response");
2629 if (dcv->req_frame != 0)
2630 proto_tree_add_text(tree, tvb, offset, 0,
2631 "Request in frame %u", dcv->req_frame);
2635 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2637 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2646 static int SpoolssSetForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2647 proto_tree *tree, char *drep)
2649 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2650 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2651 const guint8 *policy_hnd;
2655 /* Update informational fields */
2657 if (check_col(pinfo->cinfo, COL_INFO))
2658 col_set_str(pinfo->cinfo, COL_INFO, "SetForm request");
2660 if (dcv->rep_frame != 0)
2661 proto_tree_add_text(tree, tvb, offset, 0,
2662 "Response in frame %u", dcv->rep_frame);
2666 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2668 display_pol(tree, tvb, offset - 20, policy_hnd);
2670 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2671 prs_UNISTR2_dp, (void **)&form_name,
2674 CLEANUP_PUSH(g_free, form_name);
2676 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2678 if (check_col(pinfo->cinfo, COL_INFO))
2679 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, level %d",
2682 CLEANUP_CALL_AND_POP;
2684 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2685 prs_FORM_CTR, NULL, NULL);
2687 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2692 static int SpoolssSetForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2693 proto_tree *tree, char *drep)
2695 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2696 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2697 proto_item *info_item;
2699 /* Update informational fields */
2701 if (check_col(pinfo->cinfo, COL_INFO))
2702 col_set_str(pinfo->cinfo, COL_INFO, "SetForm response");
2704 if (dcv->req_frame != 0)
2705 proto_tree_add_text(tree, tvb, offset, 0,
2706 "Request in frame %u", dcv->req_frame);
2710 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2712 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2721 static int SpoolssGetForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2722 proto_tree *tree, char *drep)
2724 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2725 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2727 const guint8 *policy_hnd;
2730 /* Update informational fields */
2732 if (check_col(pinfo->cinfo, COL_INFO))
2733 col_set_str(pinfo->cinfo, COL_INFO, "GetForm request");
2735 if (dcv->rep_frame != 0)
2736 proto_tree_add_text(tree, tvb, offset, 0,
2737 "Response in frame %u", dcv->rep_frame);
2741 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2743 display_pol(tree, tvb, offset - 20, policy_hnd);
2745 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2746 prs_UNISTR2_dp, (void **)&form_name,
2749 CLEANUP_PUSH(g_free, form_name);
2751 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2753 dcv->private_data = (void *)level;
2755 if (check_col(pinfo->cinfo, COL_INFO))
2756 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, level %d",
2759 CLEANUP_CALL_AND_POP;
2761 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2762 prs_BUFFER, NULL, NULL);
2764 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
2766 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2771 static int SpoolssGetForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2772 proto_tree *tree, char *drep)
2774 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2775 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2777 struct BUFFER_DATA *bd = NULL;
2779 /* Update informational fields */
2781 if (check_col(pinfo->cinfo, COL_INFO))
2782 col_set_str(pinfo->cinfo, COL_INFO, "GetForm response");
2784 if (dcv->req_frame != 0)
2785 proto_tree_add_text(tree, tvb, offset, 0,
2786 "Request in frame %u", dcv->req_frame);
2790 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2791 prs_BUFFER, NULL, &data_list);
2793 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
2796 bd = (struct BUFFER_DATA *)data_list[0];
2798 CLEANUP_PUSH(g_free, bd);
2800 if (bd && bd->tree) {
2801 guint32 level = (guint32)dcv->private_data;
2805 int struct_start = bd->offset;
2806 GList *dp_list = NULL;
2808 bd->offset = prs_FORM_REL(
2809 bd->tvb, bd->offset, pinfo, bd->tree,
2810 struct_start, &dp_list, NULL);
2814 proto_tree_add_text(
2815 bd->tree, bd->tvb, bd->offset, 0,
2816 "[Unknown info level %d]", level);
2822 CLEANUP_CALL_AND_POP;
2824 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2826 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2831 /* A generic reply function that just parses the status code. Useful for
2832 unimplemented dissectors so the status code can be inserted into the
2835 static int SpoolssGeneric_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2836 proto_tree *tree, char *drep)
2838 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2839 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2840 int len = tvb_length(tvb);
2842 proto_tree_add_text(tree, tvb, offset, 0,
2843 "[Unimplemented dissector: SPOOLSS]");
2845 if (dcv->req_frame != 0)
2846 proto_tree_add_text(tree, tvb, offset, 0,
2847 "Request in frame %u", dcv->req_frame);
2849 prs_werror(tvb, len - 4, pinfo, tree, NULL);
2858 static gint ett_JOB_INFO_1;
2860 static int prs_JOB_INFO_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
2861 proto_tree *tree, GList **dp_list, void **data)
2864 proto_tree *subtree;
2867 item = proto_tree_add_text(tree, tvb, offset, 0, "JOB_INFO_1");
2869 subtree = proto_item_add_subtree(item, ett_FORM_CTR);
2878 static gint ett_JOB_INFO_2;
2880 static int prs_JOB_INFO_2(tvbuff_t *tvb, int offset, packet_info *pinfo,
2881 proto_tree *tree, GList **dp_list, void **data)
2884 proto_tree *subtree;
2887 item = proto_tree_add_text(tree, tvb, offset, 0, "JOB_INFO_2");
2889 subtree = proto_item_add_subtree(item, ett_FORM_CTR);
2898 static int SpoolssEnumJobs_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2899 proto_tree *tree, char *drep)
2901 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2902 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2903 const guint8 *policy_hnd;
2906 /* Update informational fields */
2908 if (check_col(pinfo->cinfo, COL_INFO))
2909 col_set_str(pinfo->cinfo, COL_INFO, "EnumJobs request");
2911 if (dcv->rep_frame != 0)
2912 proto_tree_add_text(tree, tvb, offset, 0,
2913 "Response in frame %d", dcv->rep_frame);
2917 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2919 display_pol(tree, tvb, offset - 20, policy_hnd);
2921 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "First job");
2923 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Num jobs");
2925 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2927 dcv->private_data = (void *)level;
2929 if (check_col(pinfo->cinfo, COL_INFO))
2930 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
2932 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2933 prs_BUFFER, NULL, NULL);
2935 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
2937 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2942 static int SpoolssEnumJobs_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2943 proto_tree *tree, char *drep)
2945 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2946 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2948 struct BUFFER_DATA *bd = NULL;
2949 gint16 level = (guint32)dcv->private_data;
2951 /* Update informational fields */
2953 if (check_col(pinfo->cinfo, COL_INFO))
2954 col_set_str(pinfo->cinfo, COL_INFO, "EnumJobs response");
2956 if (dcv->req_frame != 0)
2957 proto_tree_add_text(tree, tvb, offset, 0,
2958 "Request in frame %d", dcv->req_frame);
2962 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2963 prs_BUFFER, NULL, &data_list);
2966 bd = (struct BUFFER_DATA *)data_list[0];
2968 if (bd && bd->tree) {
2969 proto_item_append_text(bd->item, ", JOB_INFO_%d", level);
2973 proto_tree_add_text(
2974 bd->tree, tvb, offset, 0,
2975 "[Unknown info level %d]", level);
2980 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
2982 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Returned");
2984 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2986 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2993 /* Templates for new subdissectors */
2999 static int SpoolssFoo_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
3000 proto_tree *tree, char *drep)
3002 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
3003 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
3005 /* Update informational fields */
3007 if (check_col(pinfo->cinfo, COL_INFO))
3008 col_set_str(pinfo->cinfo, COL_INFO, "Foo request");
3010 if (dcv->rep_frame != 0)
3011 proto_tree_add_text(tree, tvb, offset, 0,
3012 "Response in frame %u", dcv->rep_frame);
3016 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
3021 static int SpoolssFoo_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
3022 proto_tree *tree, char *drep)
3024 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
3025 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
3027 /* Update informational fields */
3029 if (check_col(pinfo->cinfo, COL_INFO))
3030 col_set_str(pinfo->cinfo, COL_INFO, "Foo response");
3032 if (dcv->req_frame != 0)
3033 proto_tree_add_text(tree, tvb, offset, 0,
3034 "Request in frame %u", dcv->req_frame);
3038 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
3046 * List of subdissectors for this pipe.
3049 static dcerpc_sub_dissector dcerpc_spoolss_dissectors[] = {
3050 { SPOOLSS_ENUMPRINTERS, "SPOOLSS_ENUMPRINTERS",
3051 SpoolssEnumPrinters_q, SpoolssEnumPrinters_r },
3052 { SPOOLSS_OPENPRINTER, "SPOOLSS_OPENPRINTER", NULL, SpoolssGeneric_r },
3053 { SPOOLSS_SETJOB, "SPOOLSS_SETJOB", NULL, SpoolssGeneric_r },
3054 { SPOOLSS_GETJOB, "SPOOLSS_GETJOB", NULL, SpoolssGeneric_r },
3055 { SPOOLSS_ENUMJOBS, "SPOOLSS_ENUMJOBS",
3056 SpoolssEnumJobs_q, SpoolssEnumJobs_r },
3057 { SPOOLSS_ADDPRINTER, "SPOOLSS_ADDPRINTER", NULL, SpoolssGeneric_r },
3058 { SPOOLSS_DELETEPRINTER, "SPOOLSS_DELETEPRINTER",
3059 SpoolssDeletePrinter_q, SpoolssDeletePrinter_r },
3060 { SPOOLSS_SETPRINTER, "SPOOLSS_SETPRINTER",
3061 SpoolssSetPrinter_q, SpoolssSetPrinter_r },
3062 { SPOOLSS_GETPRINTER, "SPOOLSS_GETPRINTER",
3063 SpoolssGetPrinter_q, SpoolssGetPrinter_r },
3064 { SPOOLSS_ADDPRINTERDRIVER, "SPOOLSS_ADDPRINTERDRIVER",
3065 NULL, SpoolssAddPrinterDriver_r },
3066 { SPOOLSS_ENUMPRINTERDRIVERS, "SPOOLSS_ENUMPRINTERDRIVERS", NULL,
3068 { SPOOLSS_GETPRINTERDRIVER, "SPOOLSS_GETPRINTERDRIVER", NULL,
3070 { SPOOLSS_GETPRINTERDRIVERDIRECTORY,
3071 "SPOOLSS_GETPRINTERDRIVERDIRECTORY", NULL, SpoolssGeneric_r },
3072 { SPOOLSS_DELETEPRINTERDRIVER, "SPOOLSS_DELETEPRINTERDRIVER", NULL,
3074 { SPOOLSS_ADDPRINTPROCESSOR, "SPOOLSS_ADDPRINTPROCESSOR", NULL,
3076 { SPOOLSS_ENUMPRINTPROCESSORS, "SPOOLSS_ENUMPRINTPROCESSORS", NULL,
3078 { SPOOLSS_GETPRINTPROCESSORDIRECTORY,
3079 "SPOOLSS_GETPRINTPROCESSORDIRECTORY", NULL, SpoolssGeneric_r },
3080 { SPOOLSS_STARTDOCPRINTER, "SPOOLSS_STARTDOCPRINTER", NULL,
3082 { SPOOLSS_STARTPAGEPRINTER, "SPOOLSS_STARTPAGEPRINTER", NULL,
3084 { SPOOLSS_WRITEPRINTER, "SPOOLSS_WRITEPRINTER", NULL,
3086 { SPOOLSS_ENDPAGEPRINTER, "SPOOLSS_ENDPAGEPRINTER", NULL,
3088 { SPOOLSS_ABORTPRINTER, "SPOOLSS_ABORTPRINTER", NULL,
3090 { SPOOLSS_READPRINTER,"SPOOLSS_READPRINTER", NULL, SpoolssGeneric_r },
3091 { SPOOLSS_ENDDOCPRINTER, "SPOOLSS_ENDDOCPRINTER", NULL,
3093 { SPOOLSS_ADDJOB, "SPOOLSS_ADDJOB", NULL, SpoolssGeneric_r },
3094 { SPOOLSS_SCHEDULEJOB, "SPOOLSS_SCHEDULEJOB", NULL, SpoolssGeneric_r },
3095 { SPOOLSS_GETPRINTERDATA, "SPOOLSS_GETPRINTERDATA",
3096 SpoolssGetPrinterData_q, SpoolssGetPrinterData_r },
3097 { SPOOLSS_SETPRINTERDATA, "SPOOLSS_SETPRINTERDATA",
3098 SpoolssSetPrinterData_q, SpoolssSetPrinterData_r },
3099 { SPOOLSS_WAITFORPRINTERCHANGE,"SPOOLSS_WAITFORPRINTERCHANGE", NULL,
3101 { SPOOLSS_CLOSEPRINTER, "SPOOLSS_CLOSEPRINTER",
3102 SpoolssClosePrinter_q, SpoolssClosePrinter_r },
3103 { SPOOLSS_ADDFORM, "SPOOLSS_ADDFORM",
3104 SpoolssAddForm_q, SpoolssAddForm_r },
3105 { SPOOLSS_DELETEFORM, "SPOOLSS_DELETEFORM",
3106 SpoolssDeleteForm_q, SpoolssDeleteForm_r },
3107 { SPOOLSS_GETFORM, "SPOOLSS_GETFORM",
3108 SpoolssGetForm_q, SpoolssGetForm_r },
3109 { SPOOLSS_SETFORM, "SPOOLSS_SETFORM",
3110 SpoolssSetForm_q, SpoolssSetForm_r },
3111 { SPOOLSS_ENUMFORMS, "SPOOLSS_ENUMFORMS",
3112 SpoolssEnumForms_q, SpoolssEnumForms_r },
3113 { SPOOLSS_ENUMPORTS, "SPOOLSS_ENUMPORTS", NULL, SpoolssGeneric_r },
3114 { SPOOLSS_ENUMMONITORS, "SPOOLSS_ENUMMONITORS", NULL,
3116 { SPOOLSS_ADDPORT,"SPOOLSS_ADDPORT", NULL, SpoolssGeneric_r },
3117 { SPOOLSS_CONFIGUREPORT,"SPOOLSS_CONFIGUREPORT", NULL,
3119 { SPOOLSS_DELETEPORT,"SPOOLSS_DELETEPORT", NULL, SpoolssGeneric_r },
3120 { SPOOLSS_CREATEPRINTERIC,"SPOOLSS_CREATEPRINTERIC", NULL,
3122 { SPOOLSS_PLAYGDISCRIPTONPRINTERIC, "SPOOLSS_PLAYGDISCRIPTONPRINTERIC",
3123 NULL, SpoolssGeneric_r },
3124 { SPOOLSS_DELETEPRINTERIC,"SPOOLSS_DELETEPRINTERIC", NULL,
3126 { SPOOLSS_ADDPRINTERCONNECTION,"SPOOLSS_ADDPRINTERCONNECTION", NULL,
3128 { SPOOLSS_DELETEPRINTERCONNECTION,"SPOOLSS_DELETEPRINTERCONNECTION",
3129 NULL, SpoolssGeneric_r },
3130 { SPOOLSS_PRINTERMESSAGEBOX,"SPOOLSS_PRINTERMESSAGEBOX", NULL,
3132 { SPOOLSS_ADDMONITOR,"SPOOLSS_ADDMONITOR", NULL,
3134 { SPOOLSS_DELETEMONITOR,"SPOOLSS_DELETEMONITOR", NULL,
3136 { SPOOLSS_DELETEPRINTPROCESSOR,"SPOOLSS_DELETEPRINTPROCESSOR", NULL,
3138 { SPOOLSS_ADDPRINTPROVIDOR,"SPOOLSS_ADDPRINTPROVIDER", NULL,
3140 { SPOOLSS_DELETEPRINTPROVIDOR,"SPOOLSS_DELETEPRINTPROVIDER", NULL,
3142 { SPOOLSS_ENUMPRINTPROCDATATYPES, "SPOOLSS_ENUMPRINTPROCDATATYPES",
3143 NULL, SpoolssGeneric_r },
3144 { SPOOLSS_RESETPRINTER,"SPOOLSS_RESETPRINTER", NULL,
3146 { SPOOLSS_GETPRINTERDRIVER2, "SPOOLSS_GETPRINTERDRIVER2", NULL,
3148 { SPOOLSS_FINDFIRSTPRINTERCHANGENOTIFICATION,
3149 "SPOOLSS_FINDFIRSTPRINTERCHANGENOTIFICATION", NULL,
3151 { SPOOLSS_FINDNEXTPRINTERCHANGENOTIFICATION,
3152 "SPOOLSS_FINDNEXTPRINTERCHANGENOTIFICATION", NULL,
3154 { SPOOLSS_FCPN, "SPOOLSS_FCPN", NULL, SpoolssGeneric_r },
3155 { SPOOLSS_ROUTERFINDFIRSTPRINTERNOTIFICATIONOLD,
3156 "SPOOLSS_ROUTERFINDFIRSTPRINTERNOTIFICATIONOLD", NULL,
3158 { SPOOLSS_REPLYOPENPRINTER, "SPOOLSS_REPLYOPENPRINTER",
3159 SpoolssReplyOpenPrinter_q, SpoolssReplyOpenPrinter_r },
3160 { SPOOLSS_ROUTERREPLYPRINTER,"SPOOLSS_ROUTERREPLYPRINTER", NULL,
3162 { SPOOLSS_REPLYCLOSEPRINTER, "SPOOLSS_REPLYCLOSEPRINTER", NULL,
3164 { SPOOLSS_ADDPORTEX,"SPOOLSS_ADDPORTEX", NULL, SpoolssGeneric_r },
3165 { SPOOLSS_REMOTEFINDFIRSTPRINTERCHANGENOTIFICATION,
3166 "SPOOLSS_REMOTEFINDFIRSTPRINTERCHANGENOTIFICATION", NULL,
3168 { SPOOLSS_SPOOLERINIT,"SPOOLSS_SPOOLERINIT", NULL, SpoolssGeneric_r },
3169 { SPOOLSS_RESETPRINTEREX,"SPOOLSS_RESETPRINTEREX", NULL,
3171 { SPOOLSS_RFFPCNEX, "SPOOLSS_RFFPCNEX",
3172 SpoolssRFFPCNEX_q, SpoolssRFFPCNEX_r },
3173 { SPOOLSS_RRPCN, "SPOOLSS_RRPCN", NULL, SpoolssGeneric_r },
3174 { SPOOLSS_RFNPCNEX, "SPOOLSS_RFNPCNEX", NULL, SpoolssGeneric_r },
3175 { SPOOLSS_OPENPRINTEREX, "SPOOLSS_OPENPRINTEREX",
3176 SpoolssOpenPrinterEx_q, SpoolssOpenPrinterEx_r },
3177 { SPOOLSS_ADDPRINTEREX, "SPOOLSS_ADDPRINTEREX",
3178 NULL, SpoolssAddPrinterEx_r },
3179 { SPOOLSS_ENUMPRINTERDATA, "SPOOLSS_ENUMPRINTERDATA",
3180 SpoolssEnumPrinterData_q, SpoolssEnumPrinterData_r },
3181 { SPOOLSS_DELETEPRINTERDATA, "SPOOLSS_DELETEPRINTERDATA", NULL,
3183 { SPOOLSS_GETPRINTERDATAEX, "SPOOLSS_GETPRINTERDATAEX",
3184 SpoolssGetPrinterDataEx_q, SpoolssGetPrinterDataEx_r },
3185 { SPOOLSS_SETPRINTERDATAEX, "SPOOLSS_SETPRINTERDATAEX",
3186 SpoolssSetPrinterDataEx_q, SpoolssSetPrinterDataEx_r },
3187 { SPOOLSS_ENUMPRINTERDATAEX,"SPOOLSS_ENUMPRINTERDATAEX", NULL,
3189 { SPOOLSS_ENUMPRINTERKEY,"SPOOLSS_ENUMPRINTERKEY", NULL,
3191 { SPOOLSS_DELETEPRINTERDATAEX,"SPOOLSS_DELETEPRINTERDATAEX", NULL,
3193 { SPOOLSS_DELETEPRINTERDRIVEREX,"SPOOLSS_DELETEPRINTERDRIVEREX", NULL,
3195 { SPOOLSS_ADDPRINTERDRIVEREX,"SPOOLSS_ADDPRINTERDRIVEREX", NULL,
3198 { 0, NULL, NULL, NULL },
3202 * Dissector initialisation function
3205 /* Protocol registration */
3207 static int proto_dcerpc_spoolss = -1;
3208 static gint ett_dcerpc_spoolss = -1;
3211 proto_register_dcerpc_spoolss(void)
3213 static gint *ett[] = {
3214 &ett_dcerpc_spoolss,
3215 &ett_NOTIFY_OPTION_ARRAY,
3216 &ett_NOTIFY_OPTION_CTR,
3218 &ett_NOTIFY_OPTION_DATA,
3219 &ett_PRINTER_DEFAULT,
3226 &ett_BUFFER_DATA_BUFFER,
3228 &ett_SPOOL_PRINTER_INFO_LEVEL,
3229 &ett_PRINTER_INFO_0,
3230 &ett_PRINTER_INFO_1,
3231 &ett_PRINTER_INFO_2,
3232 &ett_PRINTER_INFO_3,
3242 proto_dcerpc_spoolss = proto_register_protocol(
3243 "Microsoft Spool Subsystem", "SPOOLSS", "spoolss");
3245 proto_register_subtree_array(ett, array_length(ett));
3248 /* Protocol handoff */
3250 static e_uuid_t uuid_dcerpc_spoolss = {
3251 0x12345678, 0x1234, 0xabcd,
3252 { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
3255 static guint16 ver_dcerpc_spoolss = 1;
3258 proto_reg_handoff_dcerpc_spoolss(void)
3260 /* Register protocol as dcerpc */
3262 dcerpc_init_uuid(proto_dcerpc_spoolss, ett_dcerpc_spoolss,
3263 &uuid_dcerpc_spoolss, ver_dcerpc_spoolss,
3264 dcerpc_spoolss_dissectors);