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.17 2002/04/18 00:29:17 guy 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 %d", pol_open_frame);
229 proto_tree_add_text(subtree, tvb, offset, 0,
230 "Closed in frame %d", 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 != -1)
254 proto_tree_add_text(tree, tvb, offset, 0,
255 "Response in frame %d", 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 != -1)
283 proto_tree_add_text(tree, tvb, offset, 0,
284 "Request in frame %d", 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 != -1)
370 proto_tree_add_text(tree, tvb, offset, 0,
371 "Response in frame %d", 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 != -1)
410 proto_tree_add_text(tree, tvb, offset, 0,
411 "Request in frame %d", 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 != -1)
452 proto_tree_add_text(tree, tvb, offset, 0,
453 "Response in frame %d", 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 != -1)
511 proto_tree_add_text(tree, tvb, offset, 0,
512 "Request in frame %d", 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 != -1)
554 proto_tree_add_text(tree, tvb, offset, 0,
555 "Response in frame %d", 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 != -1)
603 proto_tree_add_text(tree, tvb, offset, 0,
604 "Request in frame %d", 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 != -1)
636 proto_tree_add_text(tree, tvb, offset, 0,
637 "Response in frame %d", 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 != -1)
691 proto_tree_add_text(tree, tvb, offset, 0,
692 "Request in frame %d", 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, GList **dp_list, void **data)
952 int struct_start = offset;
955 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
956 NULL, "Server name");
958 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
959 NULL, "Printer name");
961 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
964 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
967 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
968 NULL, "Driver name");
970 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
973 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
976 /* This is a relative devicemode */
978 offset = prs_uint32(tvb, offset, pinfo, tree, &rel_offset, NULL);
980 prs_DEVMODE(tvb, struct_start + rel_offset - 4, pinfo, tree,
983 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
984 NULL, "Separator file");
986 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
987 NULL, "Print processor");
989 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
992 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
995 /* This is a relative security descriptor */
997 offset = prs_uint32(tvb, offset, pinfo, tree, &rel_offset, NULL);
999 dissect_nt_sec_desc(tvb, pinfo, struct_start + rel_offset, tree, 0);
1001 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Attributes");
1003 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Priority");
1005 offset = prs_uint32(tvb, offset, pinfo, tree, NULL,
1006 "Default priority");
1008 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Start time");
1010 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "End time");
1012 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Status");
1014 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Jobs");
1016 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Average PPM");
1025 static gint ett_PRINTER_INFO_3 = -1;
1027 static int prs_PRINTER_INFO_3(tvbuff_t *tvb, int offset, packet_info *pinfo,
1028 proto_tree *tree, GList **dp_list, void **data)
1030 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Flags");
1032 offset = dissect_nt_sec_desc(tvb, pinfo, offset, tree, 0);
1041 static gint ett_DEVMODE_CTR = -1;
1043 static int prs_DEVMODE_CTR(tvbuff_t *tvb, int offset, packet_info *pinfo,
1044 proto_tree *tree, GList **dp_list, void **data)
1047 proto_tree *subtree;
1050 item = proto_tree_add_text(tree, tvb, offset, 0, "DEVMODE_CTR");
1052 subtree = proto_item_add_subtree(item, ett_DEVMODE_CTR);
1054 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Size");
1056 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Devicemode");
1059 offset = prs_DEVMODE(tvb, offset, pinfo, subtree, dp_list,
1066 * PRINTER_DEFAULT structure
1069 static gint ett_PRINTER_DEFAULT = -1;
1071 static int prs_PRINTER_DEFAULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1072 proto_tree *tree, GList **dp_list, void **data)
1074 GList *child_dp_list = NULL;
1076 proto_tree *subtree;
1077 guint32 ptr = 0, access;
1079 item = proto_tree_add_text(tree, tvb, offset, 0, "PRINTER_DEFAULT");
1081 subtree = proto_item_add_subtree(item, ett_PRINTER_DEFAULT);
1083 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Datatype");
1085 /* Not sure why this isn't a deferred pointer. I think this may be
1086 two structures stuck together. */
1089 offset = prs_UNISTR2_dp(tvb, offset, pinfo, subtree, dp_list,
1092 offset = prs_DEVMODE_CTR(tvb, offset, pinfo, subtree,
1093 &child_dp_list, NULL);
1095 offset = prs_uint32(tvb, offset, pinfo, subtree, &access, NULL);
1097 proto_tree_add_text(subtree, tvb, offset - 4, 4,
1098 "Access required: 0x%08x", access);
1100 offset = prs_referents(tvb, offset, pinfo, subtree, dp_list,
1101 &child_dp_list, NULL);
1107 * USER_LEVEL_1 structure
1110 static gint ett_USER_LEVEL_1 = -1;
1112 static int prs_USER_LEVEL_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
1113 proto_tree *tree, GList **dp_list, void **data)
1116 proto_tree *subtree;
1119 item = proto_tree_add_text(tree, tvb, offset, 0, "USER_LEVEL_1");
1121 subtree = proto_item_add_subtree(item, ett_USER_LEVEL_1);
1123 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Size");
1125 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Client name");
1128 defer_ptr(dp_list, prs_UNISTR2_dp, subtree);
1130 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "User name");
1133 defer_ptr(dp_list, prs_UNISTR2_dp, subtree);
1135 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Build");
1137 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Major");
1139 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Minor");
1141 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Processor");
1147 * USER_LEVEL structure
1150 static gint ett_USER_LEVEL = -1;
1152 static int prs_USER_LEVEL(tvbuff_t *tvb, int offset, packet_info *pinfo,
1153 proto_tree *tree, GList **parent_dp_list,
1157 proto_tree *subtree;
1161 item = proto_tree_add_text(tree, tvb, offset, 0, "USER_LEVEL");
1163 subtree = proto_item_add_subtree(item, ett_USER_LEVEL);
1165 offset = prs_uint32(tvb, offset, pinfo, subtree, &level, "Info level");
1167 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "User level");
1172 defer_ptr(parent_dp_list, prs_USER_LEVEL_1, subtree);
1175 proto_tree_add_text(
1176 tree, tvb, offset, 0,
1177 "[GetPrinter level %d not decoded]", level);
1186 * SpoolssOpenPrinterEx
1189 static int SpoolssOpenPrinterEx_q(tvbuff_t *tvb, int offset,
1190 packet_info *pinfo, proto_tree *tree,
1193 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1194 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1198 /* Update informational fields */
1200 if (check_col(pinfo->cinfo, COL_INFO))
1201 col_set_str(pinfo->cinfo, COL_INFO, "OpenPrinterEx request");
1203 if (dcv->rep_frame != -1)
1204 proto_tree_add_text(tree, tvb, offset, 0,
1205 "Response in frame %d", dcv->rep_frame);
1209 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Printer name");
1214 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1216 (void **)&printer_name,
1219 if (check_col(pinfo->cinfo, COL_INFO))
1220 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1223 /* Store printer name to match with response packet */
1225 dcv->private_data = printer_name;
1228 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1229 prs_PRINTER_DEFAULT, NULL, NULL);
1231 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "User switch");
1233 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1234 prs_USER_LEVEL, NULL, NULL);
1236 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1241 static int SpoolssOpenPrinterEx_r(tvbuff_t *tvb, int offset,
1242 packet_info *pinfo, proto_tree *tree,
1245 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1246 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1247 GList *dp_list = NULL;
1249 const guint8 *policy_hnd;
1251 /* Display informational data */
1253 if (check_col(pinfo->cinfo, COL_INFO))
1254 col_set_str(pinfo->cinfo, COL_INFO, "OpenPrinterEx response");
1256 if (dcv->req_frame != -1)
1257 proto_tree_add_text(tree, tvb, offset, 0,
1258 "Request in frame %d", dcv->req_frame);
1262 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1264 display_pol(tree, tvb, offset - 20, policy_hnd);
1266 offset = prs_werror(tvb, offset, pinfo, tree, &status);
1270 /* Associate the returned printer handle with a name */
1272 if (dcv->private_data) {
1273 dcerpc_smb_store_pol(policy_hnd, dcv->private_data,
1276 g_free(dcv->private_data);
1277 dcv->private_data = NULL;
1281 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1287 * NOTIFY_OPTION_DATA structure
1290 static gint ett_NOTIFY_OPTION_DATA = -1;
1292 static int prs_NOTIFY_OPTION_DATA(tvbuff_t *tvb, int offset,
1293 packet_info *pinfo, proto_tree *tree,
1294 GList **parent_dp_list, void **data)
1297 proto_tree *subtree;
1300 item = proto_tree_add_text(tree, tvb, offset, 0, "NOTIFY_OPTION_DATA");
1302 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION_DATA);
1304 offset = prs_uint32(tvb, offset, pinfo, subtree, &count, "Count");
1306 for (i = 0; i < count; i++)
1307 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL,
1314 * NOTIFY_OPTION structure
1317 static gint ett_NOTIFY_OPTION = -1;
1319 static int prs_NOTIFY_OPTION(tvbuff_t *tvb, int offset, packet_info *pinfo,
1320 proto_tree *tree, GList **parent_dp_list,
1324 proto_tree *subtree;
1327 item = proto_tree_add_text(tree, tvb, offset, 0, "NOTIFY_OPTION");
1329 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION);
1331 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Type");
1333 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Reserved");
1335 offset = prs_uint32(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, "Count");
1341 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Fields");
1344 defer_ptr(parent_dp_list, prs_NOTIFY_OPTION_DATA, subtree);
1350 * NOTIFY_OPTION_CTR structure
1353 static gint ett_NOTIFY_OPTION_CTR = -1;
1355 static int prs_NOTIFY_OPTION_CTR(tvbuff_t *tvb, int offset,
1356 packet_info *pinfo, proto_tree *tree,
1357 GList **dp_list, void **data)
1359 GList *child_dp_list = NULL;
1361 proto_tree *subtree;
1362 guint32 count, i, ptr;
1364 item = proto_tree_add_text(tree, tvb, offset, 0,
1365 "NOTIFY_OPTION_CTR");
1367 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION_CTR);
1369 offset = prs_uint32(tvb, offset, pinfo, subtree, &count, "Count");
1371 for (i = 0; i < count; i++)
1372 offset = prs_NOTIFY_OPTION(tvb, offset, pinfo, subtree,
1373 &child_dp_list, NULL);
1375 offset = prs_referents(tvb, offset, pinfo, subtree, dp_list,
1376 &child_dp_list, NULL);
1382 * NOTIFY_OPTION structure
1385 gint ett_NOTIFY_OPTION_ARRAY = -1;
1387 static int prs_NOTIFY_OPTION_ARRAY(tvbuff_t *tvb, int offset,
1388 packet_info *pinfo, proto_tree *tree,
1389 GList **dp_list, void **data)
1392 proto_tree *subtree;
1395 item = proto_tree_add_text(tree, tvb, offset, 0,
1396 "NOTIFY_OPTION_ARRAY");
1398 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION_ARRAY);
1400 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Version");
1402 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Flags");
1404 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Count");
1406 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Option type");
1409 defer_ptr(dp_list, prs_NOTIFY_OPTION_CTR, subtree);
1418 static int SpoolssRFFPCNEX_q(tvbuff_t *tvb, int offset,
1419 packet_info *pinfo, proto_tree *tree,
1422 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1423 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1426 const guint8 *policy_hnd;
1428 /* Update informational fields */
1430 if (check_col(pinfo->cinfo, COL_INFO))
1431 col_set_str(pinfo->cinfo, COL_INFO, "RFFPCNEX request");
1433 if (dcv->rep_frame != -1)
1434 proto_tree_add_text(tree, tvb, offset, 0,
1435 "Response in frame %d", dcv->rep_frame);
1439 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1441 display_pol(tree, tvb, offset - 20, policy_hnd);
1443 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Flags");
1445 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Options");
1447 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Local machine");
1450 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1452 (void *)&printer_name, NULL);
1454 if (check_col(pinfo->cinfo, COL_INFO))
1455 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1458 g_free(printer_name);
1461 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Printer local");
1463 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Option");
1466 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1467 prs_NOTIFY_OPTION_ARRAY,
1471 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1476 static int SpoolssRFFPCNEX_r(tvbuff_t *tvb, int offset,
1477 packet_info *pinfo, proto_tree *tree,
1480 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1481 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1483 /* Update informational fields */
1485 if (check_col(pinfo->cinfo, COL_INFO))
1486 col_set_str(pinfo->cinfo, COL_INFO, "RFFPCNEX response");
1488 if (dcv->req_frame != -1)
1489 proto_tree_add_text(tree, tvb, offset, 0,
1490 "Request in frame %d", dcv->req_frame);
1494 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
1496 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1502 * SpoolssReplyOpenPrinter
1505 static int SpoolssReplyOpenPrinter_q(tvbuff_t *tvb, int offset,
1506 packet_info *pinfo, proto_tree *tree,
1509 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1510 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1511 guint32 ptr = 0, type;
1513 /* Update informational fields */
1515 if (check_col(pinfo->cinfo, COL_INFO))
1516 col_set_str(pinfo->cinfo, COL_INFO, "ReplyOpenPrinter request");
1518 if (dcv->rep_frame != -1)
1519 proto_tree_add_text(tree, tvb, offset, 0,
1520 "Response in frame %d", dcv->rep_frame);
1524 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1525 prs_UNISTR2_dp, NULL, NULL);
1527 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Printer");
1529 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
1531 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
1532 val_to_str(type, reg_datatypes, "Unknown type"));
1534 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1536 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1538 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1543 static int SpoolssReplyOpenPrinter_r(tvbuff_t *tvb, int offset,
1544 packet_info *pinfo, proto_tree *tree,
1547 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1548 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1549 GList *dp_list = NULL;
1550 const guint8 *policy_hnd;
1552 /* Update informational fields */
1554 if (check_col(pinfo->cinfo, COL_INFO))
1555 col_set_str(pinfo->cinfo, COL_INFO, "ReplyOpenPrinter response");
1557 if (dcv->req_frame != -1)
1558 proto_tree_add_text(tree, tvb, offset, 0,
1559 "Request in frame %d", dcv->req_frame);
1563 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1565 display_pol(tree, tvb, offset - 20, policy_hnd);
1567 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
1569 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1578 static gint ett_BUFFER_DATA = -1;
1579 static gint ett_BUFFER_DATA_BUFFER = -1;
1581 struct BUFFER_DATA {
1582 proto_item *item; /* proto_item holding proto_tree */
1583 proto_tree *tree; /* proto_tree holding buffer data */
1585 int offset; /* Offset where data starts in tvb*/
1588 static int prs_BUFFER_DATA(tvbuff_t *tvb, int offset, packet_info *pinfo,
1589 proto_tree *tree, GList **dp_list, void **data)
1591 proto_item *item, *subitem;
1592 proto_tree *subtree, *subsubtree;
1593 guint32 ptr = 0, size;
1596 item = proto_tree_add_text(tree, tvb, offset, 0, "BUFFER_DATA");
1598 subtree = proto_item_add_subtree(item, ett_BUFFER_DATA);
1600 offset = prs_uint32(tvb, offset, pinfo, subtree, &size, "Size");
1602 subitem = proto_tree_add_text(subtree, tvb, offset, size, "Data");
1604 subsubtree = proto_item_add_subtree(subitem, ett_BUFFER_DATA_BUFFER);
1606 offset = prs_uint8s(tvb, offset, pinfo, subsubtree, size,
1607 &data8_offset, NULL);
1609 /* Return some info which will help the caller "cast" the buffer
1610 data and dissect it further. */
1613 struct BUFFER_DATA *bd;
1615 bd = (struct BUFFER_DATA *)malloc(sizeof(struct BUFFER_DATA));
1618 bd->tree = subsubtree;
1620 bd->offset = data8_offset;
1632 static gint ett_BUFFER = -1;
1634 static int prs_BUFFER(tvbuff_t *tvb, int offset, packet_info *pinfo,
1635 proto_tree *tree, GList **dp_list, void **data)
1638 proto_tree *subtree;
1641 item = proto_tree_add_text(tree, tvb, offset, 0, "BUFFER");
1643 subtree = proto_item_add_subtree(item, ett_BUFFER);
1645 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Data");
1648 defer_ptr(dp_list, prs_BUFFER_DATA, subtree);
1657 static int SpoolssGetPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
1658 proto_tree *tree, char *drep)
1660 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1661 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1662 GList *dp_list = NULL;
1664 const guint8 *policy_hnd;
1666 /* Update informational fields */
1668 if (check_col(pinfo->cinfo, COL_INFO))
1669 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinter request");
1671 if (dcv->rep_frame != -1)
1672 proto_tree_add_text(tree, tvb, offset, 0,
1673 "Response in frame %d", dcv->rep_frame);
1677 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1679 display_pol(tree, tvb, offset - 20, policy_hnd);
1681 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
1683 if (check_col(pinfo->cinfo, COL_INFO))
1684 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1686 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1687 prs_BUFFER, NULL, NULL);
1689 dcv->private_data = (void *)level;
1691 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
1693 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1698 static int SpoolssGetPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
1699 proto_tree *tree, char *drep)
1701 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1702 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1703 GList *dp_list = NULL;
1705 struct BUFFER_DATA *bd = NULL;
1706 gint16 level = (guint32)dcv->private_data;
1708 /* Update informational fields */
1710 if (check_col(pinfo->cinfo, COL_INFO))
1711 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinter response");
1713 if (dcv->req_frame != -1)
1714 proto_tree_add_text(tree, tvb, offset, 0,
1715 "Request in frame %d", dcv->req_frame);
1717 if (check_col(pinfo->cinfo, COL_INFO))
1718 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1722 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1723 prs_BUFFER, NULL, &data_list);
1726 bd = (struct BUFFER_DATA *)data_list[0];
1728 if (bd && bd->tree) {
1729 proto_item_append_text(bd->item, ", PRINTER_INFO_%d", level);
1733 prs_PRINTER_INFO_0(bd->tvb, bd->offset, pinfo,
1734 bd->tree, &dp_list, NULL);
1738 prs_PRINTER_INFO_1(bd->tvb, bd->offset, pinfo,
1739 bd->tree, &dp_list, NULL);
1743 prs_PRINTER_INFO_2(bd->tvb, bd->offset, pinfo,
1744 bd->tree, &dp_list, NULL);
1748 prs_PRINTER_INFO_3(bd->tvb, bd->offset, pinfo,
1749 bd->tree, &dp_list, NULL);
1753 proto_tree_add_text(tree, tvb, offset, 0,
1754 "[Unimplemented info level %d]", level);
1760 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
1762 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
1764 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1770 * SPOOL_PRINTER_INFO_LEVEL
1773 static gint ett_SPOOL_PRINTER_INFO_LEVEL = -1;
1775 static int prs_SPOOL_PRINTER_INFO_LEVEL(tvbuff_t *tvb, int offset,
1776 packet_info *pinfo, proto_tree *tree,
1777 GList **dp_list, void **data)
1780 proto_tree *subtree;
1781 guint32 ptr = 0, level;
1783 item = proto_tree_add_text(tree, tvb, offset, 0,
1784 "SPOOL_PRINTER_INFO_LEVEL");
1786 subtree = proto_item_add_subtree(item, ett_SPOOL_PRINTER_INFO_LEVEL);
1788 offset = prs_uint32(tvb, offset, pinfo, subtree, &level, "Level");
1802 static int SpoolssSetPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
1803 proto_tree *tree, char *drep)
1805 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1806 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1807 GList *dp_list = NULL;
1809 const guint8 *policy_hnd;
1811 /* Update informational fields */
1813 if (check_col(pinfo->cinfo, COL_INFO))
1814 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinter request");
1816 if (dcv->rep_frame != -1)
1817 proto_tree_add_text(tree, tvb, offset, 0,
1818 "Response in frame %d", dcv->rep_frame);
1822 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1824 display_pol(tree, tvb, offset - 20, policy_hnd);
1826 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
1828 if (check_col(pinfo->cinfo, COL_INFO))
1829 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1831 /* printer_info_level */
1833 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1834 prs_SPOOL_PRINTER_INFO_LEVEL,
1840 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Command");
1842 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1847 static int SpoolssSetPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
1848 proto_tree *tree, char *drep)
1850 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1851 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1852 GList *dp_list = NULL;
1854 /* Update informational fields */
1856 if (check_col(pinfo->cinfo, COL_INFO))
1857 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinter response");
1859 if (dcv->req_frame != -1)
1860 proto_tree_add_text(tree, tvb, offset, 0,
1861 "Request in frame %d", dcv->req_frame);
1865 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
1867 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1876 static const value_string form_type_vals[] =
1878 { FORM_USER, "FORM_USER" },
1879 { FORM_BUILTIN, "FORM_BUILTIN" },
1880 { FORM_PRINTER, "FORM_PRINTER" },
1884 static gint ett_FORM_REL = -1;
1886 static int prs_FORM_REL(tvbuff_t *tvb, int offset, packet_info *pinfo,
1887 proto_tree *tree, int struct_start, GList **dp_list,
1891 proto_tree *subtree;
1894 item = proto_tree_add_text(tree, tvb, offset, 0, "FORM_REL");
1896 subtree = proto_item_add_subtree(item, ett_FORM_REL);
1898 offset = prs_uint32(tvb, offset, pinfo, subtree, &flags, NULL);
1900 proto_tree_add_text(subtree, tvb, offset - 4, 4, "Flags: %s",
1901 val_to_str(flags, form_type_vals, "Unknown type"));
1903 offset = prs_relstr(tvb, offset, pinfo, subtree, dp_list,
1904 struct_start, NULL, "Name");
1906 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Width");
1908 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Height");
1910 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
1913 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
1916 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
1917 "Horizontal imageable length");
1919 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
1920 "Vertical imageable length");
1929 static int SpoolssEnumForms_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
1930 proto_tree *tree, char *drep)
1932 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1933 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1934 GList *dp_list = NULL;
1936 const guint8 *policy_hnd;
1938 /* Update informational fields */
1940 if (check_col(pinfo->cinfo, COL_INFO))
1941 col_set_str(pinfo->cinfo, COL_INFO, "EnumForms request");
1943 if (dcv->rep_frame != -1)
1944 proto_tree_add_text(tree, tvb, offset, 0,
1945 "Response in frame %d", dcv->rep_frame);
1949 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
1951 display_pol(tree, tvb, offset - 20, policy_hnd);
1953 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
1955 dcv->private_data = (void *)level;
1957 if (check_col(pinfo->cinfo, COL_INFO))
1958 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1960 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1961 prs_BUFFER, NULL, NULL);
1963 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
1965 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
1970 static int SpoolssEnumForms_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
1971 proto_tree *tree, char *drep)
1973 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1974 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1976 GList *dp_list = NULL;
1977 struct BUFFER_DATA *bd = NULL;
1980 /* Update informational fields */
1982 if (check_col(pinfo->cinfo, COL_INFO))
1983 col_set_str(pinfo->cinfo, COL_INFO, "EnumForms response");
1985 if (dcv->req_frame != -1)
1986 proto_tree_add_text(tree, tvb, offset, 0,
1987 "Request in frame %d", dcv->req_frame);
1991 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1992 prs_BUFFER, NULL, &data_list);
1994 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
1996 offset = prs_uint32(tvb, offset, pinfo, tree, &count, "Num entries");
1999 bd = (struct BUFFER_DATA *)data_list[0];
2001 CLEANUP_PUSH(g_free, bd);
2003 if (bd && bd->tree) {
2004 guint32 level = (guint32)dcv->private_data, i;
2005 GList *child_dp_list = NULL;
2007 if (check_col(pinfo->cinfo, COL_INFO))
2008 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
2010 proto_item_append_text(bd->item, ", FORM_%d", level);
2012 /* Unfortunately this array isn't in NDR format so we can't
2013 use prs_array(). The other weird thing is the
2014 struct_start being inside the loop rather than outside.
2017 for (i = 0; i < count; i++) {
2018 int struct_start = bd->offset;
2020 bd->offset = prs_FORM_REL(
2021 bd->tvb, bd->offset, pinfo, bd->tree,
2022 struct_start, &child_dp_list, NULL);
2028 CLEANUP_CALL_AND_POP;
2030 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2032 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2038 * SpoolssDeletePrinter
2041 static int SpoolssDeletePrinter_q(tvbuff_t *tvb, int offset,
2042 packet_info *pinfo, proto_tree *tree,
2045 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2046 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2047 const guint8 *policy_hnd;
2049 /* Update informational fields */
2051 if (check_col(pinfo->cinfo, COL_INFO))
2052 col_set_str(pinfo->cinfo, COL_INFO, "DeletePrinter request");
2054 if (dcv->rep_frame != -1)
2055 proto_tree_add_text(tree, tvb, offset, 0,
2056 "Response in frame %d", dcv->rep_frame);
2060 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2062 display_pol(tree, tvb, offset - 20, policy_hnd);
2064 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2069 static int SpoolssDeletePrinter_r(tvbuff_t *tvb, int offset,
2070 packet_info *pinfo, proto_tree *tree,
2073 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2074 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2075 const guint8 *policy_hnd;
2077 /* Update informational fields */
2079 if (check_col(pinfo->cinfo, COL_INFO))
2080 col_set_str(pinfo->cinfo, COL_INFO, "DeletePrinter response");
2082 if (dcv->req_frame != -1)
2083 proto_tree_add_text(tree, tvb, offset, 0,
2084 "Request in frame %d", dcv->req_frame);
2088 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2090 display_pol(tree, tvb, offset - 20, policy_hnd);
2092 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2094 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2103 static int SpoolssAddPrinterEx_q(tvbuff_t *tvb, int offset,
2104 packet_info *pinfo, proto_tree *tree,
2107 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2108 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2111 /* Update informational fields */
2113 if (check_col(pinfo->cinfo, COL_INFO))
2114 col_set_str(pinfo->cinfo, COL_INFO, "AddPrinterEx request");
2116 if (dcv->rep_frame != -1)
2117 proto_tree_add_text(tree, tvb, offset, 0,
2118 "Response in frame %d", dcv->rep_frame);
2122 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Server name");
2127 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2129 (void *)&printer_name, NULL);
2132 dcv->private_data = printer_name;
2135 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Level");
2137 /* TODO: PRINTER INFO LEVEL */
2139 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2140 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2141 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2142 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2144 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "User switch");
2146 /* TODO: USER LEVEL */
2148 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2153 static int SpoolssAddPrinterEx_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2154 proto_tree *tree, char *drep)
2156 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2157 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2159 const guint8 *policy_hnd;
2161 /* Update informational fields */
2163 if (check_col(pinfo->cinfo, COL_INFO))
2164 col_set_str(pinfo->cinfo, COL_INFO, "AddPrinterEx response");
2166 if (dcv->req_frame != -1)
2167 proto_tree_add_text(tree, tvb, offset, 0,
2168 "Request in frame %d", dcv->req_frame);
2172 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2174 display_pol(tree, tvb, offset - 20, policy_hnd);
2176 offset = prs_werror(tvb, offset, pinfo, tree, &status);
2180 /* Associate the returned printer handle with a name */
2182 if (dcv->private_data) {
2184 if (check_col(pinfo->cinfo, COL_INFO))
2186 pinfo->cinfo, COL_INFO, ", %s",
2187 (char *)dcv->private_data);
2189 dcerpc_smb_store_pol(
2190 policy_hnd, dcv->private_data, pinfo->fd->num, 0);
2192 g_free(dcv->private_data);
2193 dcv->private_data = NULL;
2197 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2203 * SpoolssEnumPrinterData
2206 static int SpoolssEnumPrinterData_q(tvbuff_t *tvb, int offset,
2207 packet_info *pinfo, proto_tree *tree,
2210 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2211 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2212 const guint8 *policy_hnd;
2214 /* Update informational fields */
2216 if (check_col(pinfo->cinfo, COL_INFO))
2217 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinterData request");
2219 if (dcv->rep_frame != -1)
2220 proto_tree_add_text(tree, tvb, offset, 0,
2221 "Response in frame %d", dcv->rep_frame);
2225 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2227 display_pol(tree, tvb, offset - 20, policy_hnd);
2229 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Index");
2231 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Value size");
2233 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Data size");
2235 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2240 static int SpoolssEnumPrinterData_r(tvbuff_t *tvb, int offset,
2241 packet_info *pinfo, proto_tree *tree,
2244 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2245 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2246 guint32 data_size, type, value_size;
2250 /* Update informational fields */
2252 if (check_col(pinfo->cinfo, COL_INFO))
2253 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinterData response");
2255 if (dcv->req_frame != -1)
2256 proto_tree_add_text(tree, tvb, offset, 0,
2257 "Request in frame %d", dcv->req_frame);
2261 offset = prs_uint32(tvb, offset, pinfo, tree, &value_size,
2264 offset = prs_uint16s(tvb, offset, pinfo, tree, value_size,
2265 &uint16s_offset, NULL);
2267 text = fake_unicode(tvb, uint16s_offset, value_size);
2269 proto_tree_add_text(tree, tvb, uint16s_offset,
2270 value_size * 2, "Value: %s", text);
2272 if (text[0] && check_col(pinfo->cinfo, COL_INFO))
2273 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", text);
2277 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real value size");
2279 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
2281 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
2282 val_to_str(type, reg_datatypes, "Unknown type"));
2284 offset = prs_uint32(tvb, offset, pinfo, tree, &data_size, "Data size");
2286 offset = prs_uint8s(tvb, offset, pinfo, tree, data_size, NULL,
2289 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real data size");
2291 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2293 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2299 * SpoolssEnumPrinters
2302 static int SpoolssEnumPrinters_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2303 proto_tree *tree, char *drep)
2305 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2306 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2309 /* Update informational fields */
2311 if (check_col(pinfo->cinfo, COL_INFO))
2312 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinters request");
2314 if (dcv->rep_frame != -1)
2315 proto_tree_add_text(tree, tvb, offset, 0,
2316 "Response in frame %d", dcv->rep_frame);
2320 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Flags");
2322 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Devicemode");
2325 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2326 prs_UNISTR2_dp, NULL, NULL);
2328 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2330 if (check_col(pinfo->cinfo, COL_INFO))
2331 col_append_fstr(pinfo->cinfo, COL_INFO, ", level, %d", level);
2333 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2334 prs_BUFFER, NULL, NULL);
2336 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
2338 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2343 static int SpoolssEnumPrinters_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2344 proto_tree *tree, char *drep)
2346 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2347 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2349 /* Update informational fields */
2351 if (check_col(pinfo->cinfo, COL_INFO))
2352 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinters response");
2354 if (dcv->req_frame != -1)
2355 proto_tree_add_text(tree, tvb, offset, 0,
2356 "Request in frame %d", dcv->req_frame);
2360 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2361 prs_BUFFER, NULL, NULL);
2363 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
2365 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Returned");
2367 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2369 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2378 static int SpoolssAddPrinterDriver_q(tvbuff_t *tvb, int offset,
2379 packet_info *pinfo, proto_tree *tree,
2382 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2383 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2385 /* Update informational fields */
2387 if (check_col(pinfo->cinfo, COL_INFO))
2388 col_set_str(pinfo->cinfo, COL_INFO, "AddPrinterDriver request");
2390 if (dcv->rep_frame != -1)
2391 proto_tree_add_text(tree, tvb, offset, 0,
2392 "Response in frame %d", dcv->rep_frame);
2396 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2401 static int SpoolssAddPrinterDriver_r(tvbuff_t *tvb, int offset,
2402 packet_info *pinfo, proto_tree *tree,
2405 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2406 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2408 /* Update informational fields */
2410 if (check_col(pinfo->cinfo, COL_INFO))
2411 col_set_str(pinfo->cinfo, COL_INFO, "AddPrinterDriver response");
2413 if (dcv->req_frame != -1)
2414 proto_tree_add_text(tree, tvb, offset, 0,
2415 "Request in frame %d", dcv->req_frame);
2419 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2421 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2430 static gint ett_FORM_1 = -1;
2432 static int prs_FORM_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
2433 proto_tree *tree, GList **dp_list, void **data)
2436 proto_tree *subtree;
2437 guint32 ptr = 0, flags;
2439 item = proto_tree_add_text(tree, tvb, offset, 0, "FORM_1");
2441 subtree = proto_item_add_subtree(item, ett_FORM_1);
2443 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Name");
2446 defer_ptr(dp_list, prs_UNISTR2_dp, subtree);
2448 offset = prs_uint32(tvb, offset, pinfo, subtree, &flags, NULL);
2450 proto_tree_add_text(subtree, tvb, offset - 4, 4, "Flags: %s",
2451 val_to_str(flags, form_type_vals, "Unknown type"));
2453 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Unknown");
2455 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Width");
2457 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Height");
2459 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
2462 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
2465 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
2466 "Horizontal imageable length");
2468 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
2469 "Vertical imageable length");
2478 static gint ett_FORM_CTR = -1;
2480 static int prs_FORM_CTR(tvbuff_t *tvb, int offset, packet_info *pinfo,
2481 proto_tree *tree, GList **dp_list, void **data)
2484 proto_tree *subtree;
2487 item = proto_tree_add_text(tree, tvb, offset, 0, "FORM_CTR");
2489 subtree = proto_item_add_subtree(item, ett_FORM_CTR);
2491 offset = prs_uint32(tvb, offset, pinfo, subtree, &level, "Level");
2495 offset = prs_struct_and_referents(tvb, offset, pinfo, subtree,
2496 prs_FORM_1, NULL, NULL);
2499 proto_tree_add_text(subtree, tvb, offset, 0,
2500 "[Unimplemented info level %d]", level);
2511 static int SpoolssAddForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2512 proto_tree *tree, char *drep)
2514 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2515 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2516 const guint8 *policy_hnd;
2519 /* Update informational fields */
2521 if (check_col(pinfo->cinfo, COL_INFO))
2522 col_set_str(pinfo->cinfo, COL_INFO, "AddForm request");
2524 if (dcv->rep_frame != -1)
2525 proto_tree_add_text(tree, tvb, offset, 0,
2526 "Response in frame %d", dcv->rep_frame);
2530 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2532 display_pol(tree, tvb, offset - 20, policy_hnd);
2534 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2536 if (check_col(pinfo->cinfo, COL_INFO))
2537 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
2539 /* Store info level to match with response packet */
2541 dcv->private_data = (void *)level;
2543 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2544 prs_FORM_CTR, NULL, NULL);
2546 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2551 static int SpoolssAddForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2552 proto_tree *tree, char *drep)
2554 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2555 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2557 /* Update informational fields */
2559 if (check_col(pinfo->cinfo, COL_INFO))
2560 col_set_str(pinfo->cinfo, COL_INFO, "AddForm response");
2562 if (dcv->req_frame != -1)
2563 proto_tree_add_text(tree, tvb, offset, 0,
2564 "Request in frame %d", dcv->req_frame);
2568 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2570 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2579 static int SpoolssDeleteForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2580 proto_tree *tree, char *drep)
2582 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2583 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2584 const guint8 *policy_hnd;
2587 /* Update informational fields */
2589 if (check_col(pinfo->cinfo, COL_INFO))
2590 col_set_str(pinfo->cinfo, COL_INFO, "DeleteForm request");
2592 if (dcv->rep_frame != -1)
2593 proto_tree_add_text(tree, tvb, offset, 0,
2594 "Response in frame %d", dcv->rep_frame);
2598 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2600 display_pol(tree, tvb, offset - 20, policy_hnd);
2602 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2603 prs_UNISTR2_dp, (void **)&form_name,
2606 if (check_col(pinfo->cinfo, COL_INFO))
2607 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", form_name);
2611 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2616 static int SpoolssDeleteForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2617 proto_tree *tree, char *drep)
2619 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2620 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2622 /* Update informational fields */
2624 if (check_col(pinfo->cinfo, COL_INFO))
2625 col_set_str(pinfo->cinfo, COL_INFO, "DeleteForm response");
2627 if (dcv->req_frame != -1)
2628 proto_tree_add_text(tree, tvb, offset, 0,
2629 "Request in frame %d", dcv->req_frame);
2633 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2635 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2644 static int SpoolssSetForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2645 proto_tree *tree, char *drep)
2647 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2648 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2649 const guint8 *policy_hnd;
2653 /* Update informational fields */
2655 if (check_col(pinfo->cinfo, COL_INFO))
2656 col_set_str(pinfo->cinfo, COL_INFO, "SetForm request");
2658 if (dcv->rep_frame != -1)
2659 proto_tree_add_text(tree, tvb, offset, 0,
2660 "Response in frame %d", dcv->rep_frame);
2664 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2666 display_pol(tree, tvb, offset - 20, policy_hnd);
2668 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2669 prs_UNISTR2_dp, (void **)&form_name,
2672 CLEANUP_PUSH(g_free, form_name);
2674 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2676 if (check_col(pinfo->cinfo, COL_INFO))
2677 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, level %d",
2680 CLEANUP_CALL_AND_POP;
2682 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2683 prs_FORM_CTR, NULL, NULL);
2685 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2690 static int SpoolssSetForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2691 proto_tree *tree, char *drep)
2693 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2694 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2695 proto_item *info_item;
2697 /* Update informational fields */
2699 if (check_col(pinfo->cinfo, COL_INFO))
2700 col_set_str(pinfo->cinfo, COL_INFO, "SetForm response");
2702 if (dcv->req_frame != -1)
2703 proto_tree_add_text(tree, tvb, offset, 0,
2704 "Request in frame %d", dcv->req_frame);
2708 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2710 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2719 static int SpoolssGetForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2720 proto_tree *tree, char *drep)
2722 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2723 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2725 const guint8 *policy_hnd;
2728 /* Update informational fields */
2730 if (check_col(pinfo->cinfo, COL_INFO))
2731 col_set_str(pinfo->cinfo, COL_INFO, "GetForm request");
2733 if (dcv->rep_frame != -1)
2734 proto_tree_add_text(tree, tvb, offset, 0,
2735 "Response in frame %d", dcv->rep_frame);
2739 offset = prs_policy_hnd(tvb, offset, pinfo, NULL, &policy_hnd);
2741 display_pol(tree, tvb, offset - 20, policy_hnd);
2743 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2744 prs_UNISTR2_dp, (void **)&form_name,
2747 CLEANUP_PUSH(g_free, form_name);
2749 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2751 dcv->private_data = (void *)level;
2753 if (check_col(pinfo->cinfo, COL_INFO))
2754 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, level %d",
2757 CLEANUP_CALL_AND_POP;
2759 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2760 prs_BUFFER, NULL, NULL);
2762 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
2764 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2769 static int SpoolssGetForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2770 proto_tree *tree, char *drep)
2772 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2773 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2775 struct BUFFER_DATA *bd = NULL;
2777 /* Update informational fields */
2779 if (check_col(pinfo->cinfo, COL_INFO))
2780 col_set_str(pinfo->cinfo, COL_INFO, "GetForm response");
2782 if (dcv->req_frame != -1)
2783 proto_tree_add_text(tree, tvb, offset, 0,
2784 "Request in frame %d", dcv->req_frame);
2788 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2789 prs_BUFFER, NULL, &data_list);
2791 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
2794 bd = (struct BUFFER_DATA *)data_list[0];
2796 CLEANUP_PUSH(g_free, bd);
2798 if (bd && bd->tree) {
2799 guint32 level = (guint32)dcv->private_data;
2803 int struct_start = bd->offset;
2804 GList *dp_list = NULL;
2806 bd->offset = prs_FORM_REL(
2807 bd->tvb, bd->offset, pinfo, bd->tree,
2808 struct_start, &dp_list, NULL);
2812 proto_tree_add_text(
2813 bd->tree, bd->tvb, bd->offset, 0,
2814 "[Unknown info level %d]", level);
2820 CLEANUP_CALL_AND_POP;
2822 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2824 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2829 /* A generic reply function that just parses the status code. Useful for
2830 unimplemented dissectors so the status code can be inserted into the
2833 static int SpoolssGeneric_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2834 proto_tree *tree, char *drep)
2836 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2837 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2838 int len = tvb_length(tvb);
2840 proto_tree_add_text(tree, tvb, offset, 0,
2841 "[Unimplemented dissector: SPOOLSS]");
2843 if (dcv->req_frame != -1)
2844 proto_tree_add_text(tree, tvb, offset, 0,
2845 "Request in frame %d", dcv->req_frame);
2847 prs_werror(tvb, len - 4, pinfo, tree, NULL);
2856 /* Templates for new subdissectors */
2862 static int SpoolssFoo_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2863 proto_tree *tree, char *drep)
2865 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2866 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2868 /* Update informational fields */
2870 if (check_col(pinfo->cinfo, COL_INFO))
2871 col_set_str(pinfo->cinfo, COL_INFO, "Foo request");
2873 if (dcv->rep_frame != -1)
2874 proto_tree_add_text(tree, tvb, offset, 0,
2875 "Response in frame %d", dcv->rep_frame);
2879 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2884 static int SpoolssFoo_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2885 proto_tree *tree, char *drep)
2887 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2888 dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2890 /* Update informational fields */
2892 if (check_col(pinfo->cinfo, COL_INFO))
2893 col_set_str(pinfo->cinfo, COL_INFO, "Foo response");
2895 if (dcv->req_frame != -1)
2896 proto_tree_add_text(tree, tvb, offset, 0,
2897 "Request in frame %d", dcv->req_frame);
2901 dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
2909 * List of subdissectors for this pipe.
2912 static dcerpc_sub_dissector dcerpc_spoolss_dissectors[] = {
2913 { SPOOLSS_ENUMPRINTERS, "SPOOLSS_ENUMPRINTERS",
2914 SpoolssEnumPrinters_q, SpoolssEnumPrinters_r },
2915 { SPOOLSS_OPENPRINTER, "SPOOLSS_OPENPRINTER", NULL, SpoolssGeneric_r },
2916 { SPOOLSS_SETJOB, "SPOOLSS_SETJOB", NULL, SpoolssGeneric_r },
2917 { SPOOLSS_GETJOB, "SPOOLSS_GETJOB", NULL, SpoolssGeneric_r },
2918 { SPOOLSS_ENUMJOBS, "SPOOLSS_ENUMJOBS", NULL, SpoolssGeneric_r },
2919 { SPOOLSS_ADDPRINTER, "SPOOLSS_ADDPRINTER", NULL, SpoolssGeneric_r },
2920 { SPOOLSS_DELETEPRINTER, "SPOOLSS_DELETEPRINTER",
2921 SpoolssDeletePrinter_q, SpoolssDeletePrinter_r },
2922 { SPOOLSS_SETPRINTER, "SPOOLSS_SETPRINTER",
2923 SpoolssSetPrinter_q, SpoolssSetPrinter_r },
2924 { SPOOLSS_GETPRINTER, "SPOOLSS_GETPRINTER",
2925 SpoolssGetPrinter_q, SpoolssGetPrinter_r },
2926 { SPOOLSS_ADDPRINTERDRIVER, "SPOOLSS_ADDPRINTERDRIVER",
2927 NULL, SpoolssAddPrinterDriver_r },
2928 { SPOOLSS_ENUMPRINTERDRIVERS, "SPOOLSS_ENUMPRINTERDRIVERS", NULL,
2930 { SPOOLSS_GETPRINTERDRIVER, "SPOOLSS_GETPRINTERDRIVER", NULL,
2932 { SPOOLSS_GETPRINTERDRIVERDIRECTORY,
2933 "SPOOLSS_GETPRINTERDRIVERDIRECTORY", NULL, SpoolssGeneric_r },
2934 { SPOOLSS_DELETEPRINTERDRIVER, "SPOOLSS_DELETEPRINTERDRIVER", NULL,
2936 { SPOOLSS_ADDPRINTPROCESSOR, "SPOOLSS_ADDPRINTPROCESSOR", NULL,
2938 { SPOOLSS_ENUMPRINTPROCESSORS, "SPOOLSS_ENUMPRINTPROCESSORS", NULL,
2940 { SPOOLSS_GETPRINTPROCESSORDIRECTORY,
2941 "SPOOLSS_GETPRINTPROCESSORDIRECTORY", NULL, SpoolssGeneric_r },
2942 { SPOOLSS_STARTDOCPRINTER, "SPOOLSS_STARTDOCPRINTER", NULL,
2944 { SPOOLSS_STARTPAGEPRINTER, "SPOOLSS_STARTPAGEPRINTER", NULL,
2946 { SPOOLSS_WRITEPRINTER, "SPOOLSS_WRITEPRINTER", NULL,
2948 { SPOOLSS_ENDPAGEPRINTER, "SPOOLSS_ENDPAGEPRINTER", NULL,
2950 { SPOOLSS_ABORTPRINTER, "SPOOLSS_ABORTPRINTER", NULL,
2952 { SPOOLSS_READPRINTER,"SPOOLSS_READPRINTER", NULL, SpoolssGeneric_r },
2953 { SPOOLSS_ENDDOCPRINTER, "SPOOLSS_ENDDOCPRINTER", NULL,
2955 { SPOOLSS_ADDJOB, "SPOOLSS_ADDJOB", NULL, SpoolssGeneric_r },
2956 { SPOOLSS_SCHEDULEJOB, "SPOOLSS_SCHEDULEJOB", NULL, SpoolssGeneric_r },
2957 { SPOOLSS_GETPRINTERDATA, "SPOOLSS_GETPRINTERDATA",
2958 SpoolssGetPrinterData_q, SpoolssGetPrinterData_r },
2959 { SPOOLSS_SETPRINTERDATA, "SPOOLSS_SETPRINTERDATA",
2960 SpoolssSetPrinterData_q, SpoolssSetPrinterData_r },
2961 { SPOOLSS_WAITFORPRINTERCHANGE,"SPOOLSS_WAITFORPRINTERCHANGE", NULL,
2963 { SPOOLSS_CLOSEPRINTER, "SPOOLSS_CLOSEPRINTER",
2964 SpoolssClosePrinter_q, SpoolssClosePrinter_r },
2965 { SPOOLSS_ADDFORM, "SPOOLSS_ADDFORM",
2966 SpoolssAddForm_q, SpoolssAddForm_r },
2967 { SPOOLSS_DELETEFORM, "SPOOLSS_DELETEFORM",
2968 SpoolssDeleteForm_q, SpoolssDeleteForm_r },
2969 { SPOOLSS_GETFORM, "SPOOLSS_GETFORM",
2970 SpoolssGetForm_q, SpoolssGetForm_r },
2971 { SPOOLSS_SETFORM, "SPOOLSS_SETFORM",
2972 SpoolssSetForm_q, SpoolssSetForm_r },
2973 { SPOOLSS_ENUMFORMS, "SPOOLSS_ENUMFORMS",
2974 SpoolssEnumForms_q, SpoolssEnumForms_r },
2975 { SPOOLSS_ENUMPORTS, "SPOOLSS_ENUMPORTS", NULL, SpoolssGeneric_r },
2976 { SPOOLSS_ENUMMONITORS, "SPOOLSS_ENUMMONITORS", NULL,
2978 { SPOOLSS_ADDPORT,"SPOOLSS_ADDPORT", NULL, SpoolssGeneric_r },
2979 { SPOOLSS_CONFIGUREPORT,"SPOOLSS_CONFIGUREPORT", NULL,
2981 { SPOOLSS_DELETEPORT,"SPOOLSS_DELETEPORT", NULL, SpoolssGeneric_r },
2982 { SPOOLSS_CREATEPRINTERIC,"SPOOLSS_CREATEPRINTERIC", NULL,
2984 { SPOOLSS_PLAYGDISCRIPTONPRINTERIC, "SPOOLSS_PLAYGDISCRIPTONPRINTERIC",
2985 NULL, SpoolssGeneric_r },
2986 { SPOOLSS_DELETEPRINTERIC,"SPOOLSS_DELETEPRINTERIC", NULL,
2988 { SPOOLSS_ADDPRINTERCONNECTION,"SPOOLSS_ADDPRINTERCONNECTION", NULL,
2990 { SPOOLSS_DELETEPRINTERCONNECTION,"SPOOLSS_DELETEPRINTERCONNECTION",
2991 NULL, SpoolssGeneric_r },
2992 { SPOOLSS_PRINTERMESSAGEBOX,"SPOOLSS_PRINTERMESSAGEBOX", NULL,
2994 { SPOOLSS_ADDMONITOR,"SPOOLSS_ADDMONITOR", NULL,
2996 { SPOOLSS_DELETEMONITOR,"SPOOLSS_DELETEMONITOR", NULL,
2998 { SPOOLSS_DELETEPRINTPROCESSOR,"SPOOLSS_DELETEPRINTPROCESSOR", NULL,
3000 { SPOOLSS_ADDPRINTPROVIDOR,"SPOOLSS_ADDPRINTPROVIDER", NULL,
3002 { SPOOLSS_DELETEPRINTPROVIDOR,"SPOOLSS_DELETEPRINTPROVIDER", NULL,
3004 { SPOOLSS_ENUMPRINTPROCDATATYPES, "SPOOLSS_ENUMPRINTPROCDATATYPES",
3005 NULL, SpoolssGeneric_r },
3006 { SPOOLSS_RESETPRINTER,"SPOOLSS_RESETPRINTER", NULL,
3008 { SPOOLSS_GETPRINTERDRIVER2, "SPOOLSS_GETPRINTERDRIVER2", NULL,
3010 { SPOOLSS_FINDFIRSTPRINTERCHANGENOTIFICATION,
3011 "SPOOLSS_FINDFIRSTPRINTERCHANGENOTIFICATION", NULL,
3013 { SPOOLSS_FINDNEXTPRINTERCHANGENOTIFICATION,
3014 "SPOOLSS_FINDNEXTPRINTERCHANGENOTIFICATION", NULL,
3016 { SPOOLSS_FCPN, "SPOOLSS_FCPN", NULL, SpoolssGeneric_r },
3017 { SPOOLSS_ROUTERFINDFIRSTPRINTERNOTIFICATIONOLD,
3018 "SPOOLSS_ROUTERFINDFIRSTPRINTERNOTIFICATIONOLD", NULL,
3020 { SPOOLSS_REPLYOPENPRINTER, "SPOOLSS_REPLYOPENPRINTER",
3021 SpoolssReplyOpenPrinter_q, SpoolssReplyOpenPrinter_r },
3022 { SPOOLSS_ROUTERREPLYPRINTER,"SPOOLSS_ROUTERREPLYPRINTER", NULL,
3024 { SPOOLSS_REPLYCLOSEPRINTER, "SPOOLSS_REPLYCLOSEPRINTER", NULL,
3026 { SPOOLSS_ADDPORTEX,"SPOOLSS_ADDPORTEX", NULL, SpoolssGeneric_r },
3027 { SPOOLSS_REMOTEFINDFIRSTPRINTERCHANGENOTIFICATION,
3028 "SPOOLSS_REMOTEFINDFIRSTPRINTERCHANGENOTIFICATION", NULL,
3030 { SPOOLSS_SPOOLERINIT,"SPOOLSS_SPOOLERINIT", NULL, SpoolssGeneric_r },
3031 { SPOOLSS_RESETPRINTEREX,"SPOOLSS_RESETPRINTEREX", NULL,
3033 { SPOOLSS_RFFPCNEX, "SPOOLSS_RFFPCNEX",
3034 SpoolssRFFPCNEX_q, SpoolssRFFPCNEX_r },
3035 { SPOOLSS_RRPCN, "SPOOLSS_RRPCN", NULL, SpoolssGeneric_r },
3036 { SPOOLSS_RFNPCNEX, "SPOOLSS_RFNPCNEX", NULL, SpoolssGeneric_r },
3037 { SPOOLSS_OPENPRINTEREX, "SPOOLSS_OPENPRINTEREX",
3038 SpoolssOpenPrinterEx_q, SpoolssOpenPrinterEx_r },
3039 { SPOOLSS_ADDPRINTEREX, "SPOOLSS_ADDPRINTEREX",
3040 NULL, SpoolssAddPrinterEx_r },
3041 { SPOOLSS_ENUMPRINTERDATA, "SPOOLSS_ENUMPRINTERDATA",
3042 SpoolssEnumPrinterData_q, SpoolssEnumPrinterData_r },
3043 { SPOOLSS_DELETEPRINTERDATA, "SPOOLSS_DELETEPRINTERDATA", NULL,
3045 { SPOOLSS_GETPRINTERDATAEX, "SPOOLSS_GETPRINTERDATAEX",
3046 SpoolssGetPrinterDataEx_q, SpoolssGetPrinterDataEx_r },
3047 { SPOOLSS_SETPRINTERDATAEX, "SPOOLSS_SETPRINTERDATAEX",
3048 SpoolssSetPrinterDataEx_q, SpoolssSetPrinterDataEx_r },
3049 { SPOOLSS_ENUMPRINTERDATAEX,"SPOOLSS_ENUMPRINTERDATAEX", NULL,
3051 { SPOOLSS_ENUMPRINTERKEY,"SPOOLSS_ENUMPRINTERKEY", NULL,
3053 { SPOOLSS_DELETEPRINTERDATAEX,"SPOOLSS_DELETEPRINTERDATAEX", NULL,
3055 { SPOOLSS_DELETEPRINTERDRIVEREX,"SPOOLSS_DELETEPRINTERDRIVEREX", NULL,
3057 { SPOOLSS_ADDPRINTERDRIVEREX,"SPOOLSS_ADDPRINTERDRIVEREX", NULL,
3060 { 0, NULL, NULL, NULL },
3064 * Dissector initialisation function
3067 /* Protocol registration */
3069 static int proto_dcerpc_spoolss = -1;
3070 static gint ett_dcerpc_spoolss = -1;
3073 proto_register_dcerpc_spoolss(void)
3075 static gint *ett[] = {
3076 &ett_dcerpc_spoolss,
3077 &ett_NOTIFY_OPTION_ARRAY,
3078 &ett_NOTIFY_OPTION_CTR,
3080 &ett_NOTIFY_OPTION_DATA,
3081 &ett_PRINTER_DEFAULT,
3088 &ett_BUFFER_DATA_BUFFER,
3090 &ett_SPOOL_PRINTER_INFO_LEVEL,
3091 &ett_PRINTER_INFO_0,
3092 &ett_PRINTER_INFO_1,
3093 &ett_PRINTER_INFO_2,
3094 &ett_PRINTER_INFO_3,
3102 proto_dcerpc_spoolss = proto_register_protocol(
3103 "Microsoft Spool Subsystem", "SPOOLSS", "spoolss");
3105 proto_register_subtree_array(ett, array_length(ett));
3108 /* Protocol handoff */
3110 static e_uuid_t uuid_dcerpc_spoolss = {
3111 0x12345678, 0x1234, 0xabcd,
3112 { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
3115 static guint16 ver_dcerpc_spoolss = 1;
3118 proto_reg_handoff_dcerpc_spoolss(void)
3120 /* Register protocol as dcerpc */
3122 dcerpc_init_uuid(proto_dcerpc_spoolss, ett_dcerpc_spoolss,
3123 &uuid_dcerpc_spoolss, ver_dcerpc_spoolss,
3124 dcerpc_spoolss_dissectors);