1 /* packet-dcerpc-spoolss.c
2 * Routines for SMB \PIPE\spoolss packet disassembly
3 * Copyright 2001, Tim Potter <tpot@samba.org>
5 * $Id: packet-dcerpc-spoolss.c,v 1.4 2002/01/21 07:36:33 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"
41 * Hash table for matching responses to replies
44 #define REQUEST_HASH_INIT_COUNT 100
46 static GHashTable *request_hash;
47 static GMemChunk *request_hash_key_chunk;
48 static GMemChunk *request_hash_value_chunk;
56 guint16 opnum; /* Tag for union */
58 guint32 request_num; /* Request frame number */
59 guint32 response_num; /* Response frame number */
61 /* Per-request information */
76 static guint hash_request(gconstpointer k)
78 request_hash_key *r = (request_hash_key *)k;
80 return r->di.smb_fid + r->di.call_id + r->di.smb_fid;
83 /* Compare two requests */
85 static gint compare_request(gconstpointer k1, gconstpointer k2)
87 request_hash_key *r1 = (request_hash_key *)k1;
88 request_hash_key *r2 = (request_hash_key *)k2;
90 return r1->opnum == r2->opnum && r1->di.call_id == r2->di.call_id &&
91 r1->di.smb_fid == r2->di.smb_fid &&
92 r1->di.conv->index == r2->di.conv->index;
95 /* Store private information for a SPOOLSS request */
97 static void store_request_info(request_hash_key *key,
98 request_hash_value *value)
100 request_hash_key *chunk_key;
101 request_hash_value *chunk_value;
103 chunk_key = g_mem_chunk_alloc(request_hash_key_chunk);
104 chunk_value = g_mem_chunk_alloc(request_hash_value_chunk);
106 memcpy(chunk_key, key, sizeof(*key));
107 memcpy(chunk_value, value, sizeof(*value));
109 g_hash_table_insert(request_hash, chunk_key, chunk_value);
112 /* Store private information for a SPOOLSS call with no private
113 information. This is basically for updating the request/response frame
116 #define SPOOLSS_DUMMY (guint16)-1 /* Dummy opnum */
118 static void store_request_info_none(packet_info *pinfo, dcerpc_info *di)
120 request_hash_key key;
121 request_hash_value value;
123 memcpy(&key.di, di, sizeof(*di));
124 key.opnum = SPOOLSS_DUMMY;
126 value.opnum = SPOOLSS_DUMMY;
127 value.request_num = pinfo->fd->num;
128 value.response_num = 0;
130 store_request_info(&key, &value);
133 /* Store private information for a OpenPrinterEx request */
135 static void store_request_info_OpenPrinterEx(packet_info *pinfo,
139 request_hash_key key;
140 request_hash_value value;
142 memcpy(&key.di, di, sizeof(*di));
143 key.opnum = SPOOLSS_OPENPRINTEREX;
145 value.opnum = SPOOLSS_OPENPRINTEREX;
146 value.data.OpenPrinterEx.printer_name = strdup(printer_name);
147 value.request_num = pinfo->fd->num;
148 value.response_num = 0;
150 store_request_info(&key, &value);
153 /* Store private information for a GetPrinter request */
155 static void store_request_info_GetPrinter(packet_info *pinfo,
159 request_hash_key key;
160 request_hash_value value;
162 memcpy(&key.di, di, sizeof(*di));
163 key.opnum = SPOOLSS_GETPRINTER;
165 value.opnum = SPOOLSS_GETPRINTER;
166 value.data.GetPrinter.level = level;
167 value.request_num = pinfo->fd->num;
168 value.response_num = 0;
170 store_request_info(&key, &value);
173 /* Fetch private information for a SPOOLSS request */
175 static request_hash_value *fetch_request_info(packet_info *pinfo,
179 request_hash_key key;
180 request_hash_value *result;
185 result = g_hash_table_lookup(request_hash, &key);
187 if (result && result->opnum != opnum)
188 g_warning("Tag for response packet at frame %d is %d, not %d",
189 pinfo->fd->num, result->opnum, opnum);
194 /* Add a text item like "Response in frame %d" using some request_info */
196 static void add_request_text(proto_tree *tree, tvbuff_t *tvb, int offset,
197 request_hash_value *request_info)
199 if (request_info && request_info->response_num)
200 proto_tree_add_text(tree, tvb, offset, 0,
201 "Response in frame %d",
202 request_info->response_num);
205 /* Add a text item like "Request in frame %d" using some request_info */
207 static void add_response_text(proto_tree *tree, tvbuff_t *tvb, int offset,
208 request_hash_value *request_info)
210 if (request_info && request_info->request_num)
211 proto_tree_add_text(tree, tvb, offset, 0,
212 "Request in frame %d",
213 request_info->request_num);
217 * Hash table for matching policy handles to printer names
220 static int printer_ndx; /* Hack for printer names */
222 #define POLICY_HND_HASH_INIT_COUNT 100
224 static GHashTable *policy_hnd_hash;
225 static GMemChunk *policy_hnd_hash_key_chunk;
226 static GMemChunk *policy_hnd_hash_value_chunk;
229 guint8 policy_hnd[20];
230 } policy_hnd_hash_key;
234 } policy_hnd_hash_value;
236 static void dump_policy_hnd(const guint8 *policy_hnd)
240 for(i = 0; i < 20; i++) {
241 fprintf(stderr, "%02x ", policy_hnd[i]);
242 csum += policy_hnd[i];
245 fprintf(stderr, "- %d\n", csum);
248 static guint hash_policy_hnd(gconstpointer k)
250 policy_hnd_hash_key *p = (policy_hnd_hash_key *)k;
253 /* Bytes 4-7 of the policy handle are a timestamp so should make a
254 reasonable hash value */
256 hash = p->policy_hnd[4] + (p->policy_hnd[5] << 8) +
257 (p->policy_hnd[6] << 16) + (p->policy_hnd[7] << 24);
262 static gint compare_policy_hnd(gconstpointer k1, gconstpointer k2)
264 policy_hnd_hash_key *p1 = (policy_hnd_hash_key *)k1;
265 policy_hnd_hash_key *p2 = (policy_hnd_hash_key *)k2;
267 return memcmp(p1->policy_hnd, p2->policy_hnd, 20) == 0;
270 static gboolean is_null_policy_hnd(const guint8 *policy_hnd)
272 static guint8 null_policy_hnd[20];
274 return memcmp(policy_hnd, null_policy_hnd, 20) == 0;
277 /* Associate a policy handle with a printer name */
279 static void store_printer_name(const guint8 *policy_hnd, char *printer_name)
281 policy_hnd_hash_key *key;
282 policy_hnd_hash_value *value;
284 if (is_null_policy_hnd(policy_hnd))
287 key = g_mem_chunk_alloc(policy_hnd_hash_key_chunk);
288 value = g_mem_chunk_alloc(policy_hnd_hash_value_chunk);
290 memcpy(key->policy_hnd, policy_hnd, 20);
291 value->printer_name = strdup(printer_name);
293 g_hash_table_insert(policy_hnd_hash, key, value);
296 /* Retrieve a printer name from a policy handle */
298 static char *fetch_printer_name(const guint8 *policy_hnd)
300 policy_hnd_hash_key key;
301 policy_hnd_hash_value *value;
303 if (is_null_policy_hnd(policy_hnd))
306 memcpy(&key.policy_hnd, policy_hnd, 20);
308 value = g_hash_table_lookup(policy_hnd_hash, &key);
311 return value->printer_name;
316 /* Delete the association between a policy handle and printer name */
318 static void delete_printer_name(guint8 *policy_hnd)
322 /* Read a policy handle and append the printer name associated with it to
323 the packet info column */
325 static void append_printer_name(packet_info *pinfo, tvbuff_t *tvb,
326 int offset, const guint8 *policy_hnd)
328 if (check_col(pinfo->cinfo, COL_INFO)) {
331 printer_name = fetch_printer_name(policy_hnd);
334 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
340 * New system for handling pointers and buffers. We act more like the NDR
341 * specification and have a list of deferred pointers which are processed
342 * after a structure has been parsed.
344 * Each structure has a parse function which takes as an argument a GList.
345 * As pointers are processed, they are appended onto this list. When the
346 * structure is complete, the pointers (referents) are processed by calling
347 * prs_referents(). In the case of function arguments, the
348 * prs_struct_and_referents() function is called as pointers are always
349 * processed immediately after the argument.
352 typedef int prs_fn(tvbuff_t *tvb, int offset, packet_info *pinfo,
353 proto_tree *tree, GList **dp_list, void **data);
355 /* Deferred referent */
357 struct deferred_ptr {
358 prs_fn *fn; /* Parse function to call */
359 proto_tree *tree; /* Tree context */
362 /* A structure to hold needed ethereal state to pass to GList foreach
365 struct deferred_ptr_state {
373 void defer_ptr(GList **list, prs_fn *fn, proto_tree *tree)
375 struct deferred_ptr *dr;
377 dr = g_malloc(sizeof(struct deferred_ptr));
382 *list = g_list_append(*list, dr);
385 /* Parse a pointer */
387 static int prs_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo,
388 proto_tree *tree, guint32 *data, char *name)
392 offset = prs_uint32(tvb, offset, pinfo, tree, &ptr, NULL);
395 proto_tree_add_text(tree, tvb, offset - 4, 4,
396 "%s pointer: 0x%08x", name, ptr);
404 /* Iterator function for prs_referents */
406 static void dr_iterator(gpointer data, gpointer user_data)
408 struct deferred_ptr *dp = (struct deferred_ptr *)data;
409 struct deferred_ptr_state *s = (struct deferred_ptr_state *)user_data;
413 *s->poffset = dp->fn(s->tvb, *s->poffset, s->pinfo, dp->tree,
414 s->dp_list, s->ptr_data);
417 s->ptr_data++; /* Ready for next parse fn */
420 /* Call the parse function for each element in the deferred pointers list.
421 If there are any additional pointers in these structures they are pushed
422 onto parent_dp_list. */
424 int prs_referents(tvbuff_t *tvb, int offset, packet_info *pinfo,
425 proto_tree *tree, GList **dp_list, GList **list,
428 struct deferred_ptr_state s;
429 int new_offset = offset;
431 /* Create a list of void pointers to store return data */
434 int len = g_list_length(*dp_list) * sizeof(void *);
437 *ptr_data = malloc(len);
438 memset(*ptr_data, 0, len);
443 /* Set up iterator data */
446 s.poffset = &new_offset;
449 s.ptr_data = ptr_data ? *ptr_data : NULL;
451 g_list_foreach(*list, dr_iterator, &s);
453 *list = NULL; /* XXX: free list */
458 /* Parse a structure then clean up any deferred referants it creates. */
460 static int prs_struct_and_referents(tvbuff_t *tvb, int offset,
461 packet_info *pinfo, proto_tree *tree,
462 prs_fn *fn, void **data, void ***ptr_data)
464 GList *dp_list = NULL;
466 offset = fn(tvb, offset, pinfo, tree, &dp_list, data);
468 offset = prs_referents(tvb, offset, pinfo, tree, &dp_list,
474 /* Parse a Win32 error, basically a DOS error. The spoolss API doesn't
475 use NT status codes. */
477 static int prs_werror(tvbuff_t *tvb, int offset, packet_info *pinfo,
478 proto_tree *tree, guint32 *data)
482 offset = prs_uint32(tvb, offset, pinfo, tree, &status, NULL);
485 proto_tree_add_text(tree, tvb, offset - 4, 4, "Status: %s",
486 val_to_str(status, DOS_errors,
489 if (status != 0 && check_col(pinfo->cinfo, COL_INFO))
490 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
491 val_to_str(status, DOS_errors,
501 * SpoolssClosePrinter
504 static int SpoolssClosePrinter_q(tvbuff_t *tvb, int offset,
505 packet_info *pinfo, proto_tree *tree,
508 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
509 request_hash_value *request_info;
510 const guint8 *policy_hnd;
512 /* Update informational fields */
514 if (check_col(pinfo->cinfo, COL_INFO))
515 col_set_str(pinfo->cinfo, COL_INFO, "ClosePrinter request");
517 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
520 add_request_text(tree, tvb, offset, request_info);
522 store_request_info_none(pinfo, di);
526 offset = prs_policy_hnd(tvb, offset, pinfo, tree, &policy_hnd);
528 append_printer_name(pinfo, tvb, offset, policy_hnd);
530 if (tvb_length_remaining(tvb, offset) != 0)
531 proto_tree_add_text(tree, tvb, offset, 0,
532 "[Long frame (%d bytes): SPOOLSS]",
533 tvb_length_remaining(tvb, offset));
538 static int SpoolssClosePrinter_r(tvbuff_t *tvb, int offset,
539 packet_info *pinfo, proto_tree *tree,
542 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
543 request_hash_value *request_info;
545 /* Update informational fields */
547 if (check_col(pinfo->cinfo, COL_INFO))
548 col_set_str(pinfo->cinfo, COL_INFO, "ClosePrinter response");
550 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
551 add_response_text(tree, tvb, offset, request_info);
554 request_info->response_num = pinfo->fd->num;
558 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
560 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
562 if (tvb_length_remaining(tvb, offset) != 0)
563 proto_tree_add_text(tree, tvb, offset, 0,
564 "[Long frame (%d bytes): SPOOLSS]",
565 tvb_length_remaining(tvb, offset));
570 /* Parse a UNISTR2 structure */
572 static gint ett_UNISTR2 = -1;
574 static int prs_UNISTR2_dp(tvbuff_t *tvb, int offset, packet_info *pinfo,
575 proto_tree *tree, GList **dp_list, void **data)
579 guint32 length, the_offset, max_len;
580 int old_offset = offset;
584 offset = prs_uint32(tvb, offset, pinfo, tree, &length, NULL);
585 offset = prs_uint32(tvb, offset, pinfo, tree, &the_offset, NULL);
586 offset = prs_uint32(tvb, offset, pinfo, tree, &max_len, NULL);
588 offset = prs_uint16s(tvb, offset, pinfo, tree, max_len, &data16, NULL);
590 text = fake_unicode(data16, max_len);
592 item = proto_tree_add_text(tree, tvb, old_offset, offset - old_offset,
593 "UNISTR2: %s", text);
595 subtree = proto_item_add_subtree(item, ett_UNISTR2);
602 proto_tree_add_text(subtree, tvb, old_offset, 4, "Length: %d", length);
606 proto_tree_add_text(subtree, tvb, old_offset, 4, "Offset: %d",
611 proto_tree_add_text(subtree, tvb, old_offset, 4, "Max length: %d",
616 proto_tree_add_text(subtree, tvb, old_offset, max_len * 2, "Data");
622 * SpoolssGetPrinterData
625 static int SpoolssGetPrinterData_q(tvbuff_t *tvb, int offset,
626 packet_info *pinfo, proto_tree *tree,
629 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
630 request_hash_value *request_info;
633 /* Update informational fields */
635 if (check_col(pinfo->cinfo, COL_INFO))
636 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinterData request");
638 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
641 add_request_text(tree, tvb, offset, request_info);
643 store_request_info_none(pinfo, di);
647 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
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", value_name);
658 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Size");
660 if (tvb_length_remaining(tvb, offset) != 0)
661 proto_tree_add_text(tree, tvb, offset, 0,
662 "[Long frame (%d bytes): SPOOLSS]",
663 tvb_length_remaining(tvb, offset));
668 static int SpoolssGetPrinterData_r(tvbuff_t *tvb, int offset,
669 packet_info *pinfo, proto_tree *tree,
672 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
673 request_hash_value *request_info;
674 GList *dp_list = NULL;
677 /* Update information fields */
679 if (check_col(pinfo->cinfo, COL_INFO))
680 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinterData response");
682 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
683 add_response_text(tree, tvb, offset, request_info);
686 request_info->response_num = pinfo->fd->num;
690 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
692 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
693 val_to_str(type, reg_datatypes, "Unknown type"));
695 offset = prs_uint32(tvb, offset, pinfo, tree, &size, "Size");
697 offset = prs_uint8s(tvb, offset, pinfo, tree, size, NULL, "Data");
699 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
701 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
703 if (tvb_length_remaining(tvb, offset) != 0)
704 proto_tree_add_text(tree, tvb, offset, 0,
705 "[Long frame (%d bytes): SPOOLSS]",
706 tvb_length_remaining(tvb, offset));
712 * SpoolssGetPrinterDataEx
715 static int SpoolssGetPrinterDataEx_q(tvbuff_t *tvb, int offset,
716 packet_info *pinfo, proto_tree *tree,
719 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
720 request_hash_value *request_info;
721 char *key_name, *value_name;
723 /* Update informational fields */
725 if (check_col(pinfo->cinfo, COL_INFO))
726 col_set_str(pinfo->cinfo, COL_INFO,
727 "GetPrinterDataEx request");
729 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
732 add_request_text(tree, tvb, offset, request_info);
734 store_request_info_none(pinfo, di);
738 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
740 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
741 prs_UNISTR2_dp, (void **)&key_name,
744 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
745 prs_UNISTR2_dp, (void **)&value_name,
748 if (check_col(pinfo->cinfo, COL_INFO))
749 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s/%s",
750 key_name, value_name);
755 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Size");
757 if (tvb_length_remaining(tvb, offset) != 0)
758 proto_tree_add_text(tree, tvb, offset, 0,
759 "[Long frame (%d bytes): SPOOLSS]",
760 tvb_length_remaining(tvb, offset));
765 static int SpoolssGetPrinterDataEx_r(tvbuff_t *tvb, int offset,
766 packet_info *pinfo, proto_tree *tree,
769 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
770 request_hash_value *request_info;
773 /* Update informational fields */
775 if (check_col(pinfo->cinfo, COL_INFO))
776 col_set_str(pinfo->cinfo, COL_INFO,
777 "GetPrinterDataEx response");
779 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
780 add_response_text(tree, tvb, offset, request_info);
783 request_info->response_num = pinfo->fd->num;
787 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
789 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
790 val_to_str(type, reg_datatypes, "Unknown type"));
792 offset = prs_uint32(tvb, offset, pinfo, tree, &size, "Size");
794 offset = prs_uint8s(tvb, offset, pinfo, tree, size, NULL, "Data");
796 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
798 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
800 if (tvb_length_remaining(tvb, offset) != 0)
801 proto_tree_add_text(tree, tvb, offset, 0,
802 "[Long frame (%d bytes): SPOOLSS]",
803 tvb_length_remaining(tvb, offset));
809 * SpoolssSetPrinterData
812 static int SpoolssSetPrinterData_q(tvbuff_t *tvb, int offset,
813 packet_info *pinfo, proto_tree *tree,
816 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
817 request_hash_value *request_info;
819 guint32 type, max_len;
821 /* Update informational fields */
823 if (check_col(pinfo->cinfo, COL_INFO))
824 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinterData request");
826 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
829 add_request_text(tree, tvb, offset, request_info);
831 store_request_info_none(pinfo, di);
835 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
837 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
838 prs_UNISTR2_dp, (void **)&value_name,
841 if (check_col(pinfo->cinfo, COL_INFO))
842 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
846 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
848 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
849 val_to_str(type, reg_datatypes, "Unknown type"));
851 offset = prs_uint32(tvb, offset, pinfo, tree, &max_len, "Max length");
853 offset = prs_uint8s(tvb, offset, pinfo, tree, max_len, NULL,
856 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real length");
858 if (tvb_length_remaining(tvb, offset) != 0)
859 proto_tree_add_text(tree, tvb, offset, 0,
860 "[Long frame (%d bytes): SPOOLSS]",
861 tvb_length_remaining(tvb, offset));
866 static int SpoolssSetPrinterData_r(tvbuff_t *tvb, int offset,
867 packet_info *pinfo, proto_tree *tree,
870 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
871 request_hash_value *request_info;
872 GList *dp_list = NULL;
874 /* Update informational fields */
876 if (check_col(pinfo->cinfo, COL_INFO))
877 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinterData response");
879 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
880 add_response_text(tree, tvb, offset, request_info);
883 request_info->response_num = pinfo->fd->num;
887 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
889 if (tvb_length_remaining(tvb, offset) != 0)
890 proto_tree_add_text(tree, tvb, offset, 0,
891 "[Long frame (%d bytes): SPOOLSS]",
892 tvb_length_remaining(tvb, offset));
898 * SpoolssSetPrinterDataEx
901 static int SpoolssSetPrinterDataEx_q(tvbuff_t *tvb, int offset,
902 packet_info *pinfo, proto_tree *tree,
905 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
906 request_hash_value *request_info;
907 GList *dp_list = NULL;
908 char *key_name, *value_name;
909 guint32 type, max_len;
911 /* Update informational fields */
913 if (check_col(pinfo->cinfo, COL_INFO))
914 col_set_str(pinfo->cinfo, COL_INFO,
915 "SetPrinterDataEx request");
917 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
920 add_request_text(tree, tvb, offset, request_info);
922 store_request_info_none(pinfo, di);
926 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
928 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
929 prs_UNISTR2_dp, (void **)&key_name,
932 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
933 prs_UNISTR2_dp, (void **)&value_name,
936 if (check_col(pinfo->cinfo, COL_INFO))
937 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s/%s",
938 key_name, value_name);
943 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
945 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
946 val_to_str(type, reg_datatypes, "Unknown type"));
948 offset = prs_uint32(tvb, offset, pinfo, tree, &max_len, "Max length");
950 offset = prs_uint8s(tvb, offset, pinfo, tree, max_len, NULL,
953 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real length");
955 if (tvb_length_remaining(tvb, offset) != 0)
956 proto_tree_add_text(tree, tvb, offset, 0,
957 "[Long frame (%d bytes): SPOOLSS]",
958 tvb_length_remaining(tvb, offset));
963 static int SpoolssSetPrinterDataEx_r(tvbuff_t *tvb, int offset,
964 packet_info *pinfo, proto_tree *tree,
967 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
968 request_hash_value *request_info;
969 GList *dp_list = NULL;
971 /* Update informational fields */
973 if (check_col(pinfo->cinfo, COL_INFO))
974 col_set_str(pinfo->cinfo, COL_INFO,
975 "SetPrinterDataEx response");
977 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
978 add_response_text(tree, tvb, offset, request_info);
981 request_info->response_num = pinfo->fd->num;
985 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
987 if (tvb_length_remaining(tvb, offset) != 0)
988 proto_tree_add_text(tree, tvb, offset, 0,
989 "[Long frame (%d bytes): SPOOLSS]",
990 tvb_length_remaining(tvb, offset));
995 /* Yet another way to represent a unicode string - sheesh. */
997 static int prs_uint16uni(tvbuff_t *tvb, int offset, packet_info *pinfo,
998 proto_tree *tree, void **data, char *name)
1000 gint len = 0, remaining, i;
1004 offset = prs_align(offset, 2);
1006 /* Get a pointer to remaining data in buffer */
1008 remaining = tvb_length_remaining(tvb, offset);
1009 ptr = (guint16 *)tvb_get_ptr(tvb, offset, remaining);
1011 for (i = 0; i < remaining / 2; i++) {
1017 text = fake_unicode(ptr, len);
1020 proto_tree_add_text(tree, tvb, offset, (len + 1) * 2,
1021 "%s: %s", name ? name : "UINT16UNI",
1029 return offset + (len + 1) * 2;
1036 static gint ett_DEVMODE = -1;
1038 static int prs_DEVMODE(tvbuff_t *tvb, int offset, packet_info *pinfo,
1039 proto_tree *tree, GList **dp_list, void **data)
1042 proto_tree *subtree;
1046 item = proto_tree_add_text(tree, tvb, offset, 0, "DEVMODE");
1048 subtree = proto_item_add_subtree(item, ett_DEVMODE);
1050 offset = prs_uint16uni(tvb, offset, pinfo, subtree, NULL, "Devicename");
1052 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Spec version");
1053 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Driver version");
1054 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Size");
1055 offset = prs_uint16(tvb, offset, pinfo, subtree, &extra, "Driver extra");
1057 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Fields");
1059 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Orientation");
1060 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Paper size");
1061 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Paper length");
1062 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Paper width");
1063 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Scale");
1064 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Copies");
1065 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Default source");
1066 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Print quality");
1067 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Color");
1068 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Duplex");
1069 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Y resolution");
1070 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "TT option");
1071 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Collate");
1073 offset = prs_uint16s(tvb, offset, pinfo, subtree, 32, NULL, "Buffer");
1075 offset = prs_uint16uni(tvb, offset, pinfo, subtree, NULL, "Form name");
1077 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Log pixels");
1079 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Bits per pel");
1080 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Pels width");
1081 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Pels height");
1082 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Display flags");
1083 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Display frequency");
1084 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "ICM method");
1085 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "ICM intent");
1086 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Media type");
1087 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Dither type");
1088 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Reserved");
1089 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Reserved");
1090 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Panning width");
1091 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Panning height");
1094 offset = prs_uint8s(tvb, offset, pinfo, subtree, extra, NULL,
1101 * Relative string given by offset into the current buffer. Note that
1102 * the offset for subsequent relstrs are against the structure start, not
1103 * the point where the offset is parsed from.
1106 static gint ett_RELSTR = -1;
1108 static int prs_relstr(tvbuff_t *tvb, int offset, packet_info *pinfo,
1109 proto_tree *tree, GList **dp_list, int struct_start,
1110 void **data, char *name)
1113 proto_tree *subtree;
1114 guint32 relstr_offset, relstr_start, relstr_end;
1116 char *text = strdup("NULL");
1117 gint len = 0, remaining, i;
1119 offset = prs_uint32(tvb, offset, pinfo, tree, &relstr_offset, NULL);
1121 /* A relative offset of zero is a NULL string */
1123 relstr_start = relstr_offset + struct_start;
1126 relstr_end = prs_uint16uni(tvb, relstr_start, pinfo, tree,
1127 (void **)&text, NULL);
1129 relstr_end = offset;
1131 item = proto_tree_add_text(tree, tvb, relstr_start,
1132 relstr_end - relstr_start, "%s: %s",
1133 name ? name : "RELSTR", text);
1135 subtree = proto_item_add_subtree(item, ett_RELSTR);
1142 proto_tree_add_text(subtree, tvb, offset - 4, 4,
1143 "Relative offset: %d", relstr_offset);
1145 proto_tree_add_text(subtree, tvb, relstr_start,
1146 relstr_end - relstr_start, "Data");
1155 static gint ett_PRINTER_INFO_0 = -1;
1157 static int prs_PRINTER_INFO_0(tvbuff_t *tvb, int offset, packet_info *pinfo,
1158 proto_tree *tree, GList **dp_list, void **data)
1160 int struct_start = offset;
1162 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
1163 NULL, "Printer name");
1164 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
1165 NULL, "Server name");
1167 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "CJobs");
1168 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Total jobs");
1169 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Total bytes");
1171 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Year");
1172 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Month");
1173 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Day of week");
1174 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Day");
1175 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Hour");
1176 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Minute");
1177 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Second");
1178 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Milliseconds");
1180 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Global counter");
1181 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Total pages");
1183 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Major version");
1184 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Build version");
1186 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1187 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1188 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1189 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Session counter");
1190 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1191 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Printer errors");
1192 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1193 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1194 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1195 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1196 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Change id");
1197 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1198 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Status");
1199 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1200 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "C_setprinter");
1202 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
1203 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
1204 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
1205 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
1206 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
1207 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
1208 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
1209 offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Unknown");
1218 static gint ett_PRINTER_INFO_1 = -1;
1220 static int prs_PRINTER_INFO_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
1221 proto_tree *tree, GList **dp_list, void **data)
1230 static gint ett_PRINTER_INFO_2 = -1;
1232 static int prs_PRINTER_INFO_2(tvbuff_t *tvb, int offset, packet_info *pinfo,
1233 proto_tree *tree, GList **dp_list, void **data)
1235 int struct_start = offset;
1237 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
1238 NULL, "Server name");
1240 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
1241 NULL, "Printer name");
1243 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
1244 NULL, "Share name");
1246 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
1249 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
1250 NULL, "Driver name");
1252 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
1255 offset = prs_relstr(tvb, offset, pinfo, tree, dp_list, struct_start,
1265 static gint ett_PRINTER_INFO_3 = -1;
1267 static int prs_PRINTER_INFO_3(tvbuff_t *tvb, int offset, packet_info *pinfo,
1268 proto_tree *tree, GList **dp_list, void **data)
1277 static gint ett_DEVMODE_CTR = -1;
1279 static int prs_DEVMODE_CTR(tvbuff_t *tvb, int offset, packet_info *pinfo,
1280 proto_tree *tree, GList **dp_list, void **data)
1283 proto_tree *subtree;
1286 item = proto_tree_add_text(tree, tvb, offset, 0, "DEVMODE_CTR");
1288 subtree = proto_item_add_subtree(item, ett_DEVMODE_CTR);
1290 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Size");
1292 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Devicemode");
1295 defer_ptr(dp_list, prs_DEVMODE, subtree);
1301 * PRINTER_DEFAULT structure
1304 static gint ett_PRINTER_DEFAULT = -1;
1306 static int prs_PRINTER_DEFAULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1307 proto_tree *tree, GList **dp_list, void **data)
1309 GList *child_dp_list = NULL;
1311 proto_tree *subtree;
1312 guint32 ptr = 0, access;
1314 item = proto_tree_add_text(tree, tvb, offset, 0, "PRINTER_DEFAULT");
1316 subtree = proto_item_add_subtree(item, ett_PRINTER_DEFAULT);
1318 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Datatype");
1320 /* Not sure why this isn't a deferred pointer. I think this may be
1321 two structures stuck together. */
1324 offset = prs_UNISTR2_dp(tvb, offset, pinfo, subtree, dp_list,
1327 offset = prs_DEVMODE_CTR(tvb, offset, pinfo, subtree,
1328 &child_dp_list, NULL);
1330 offset = prs_uint32(tvb, offset, pinfo, subtree, &access, NULL);
1332 proto_tree_add_text(subtree, tvb, offset - 4, 4,
1333 "Access required: 0x%08x", access);
1335 offset = prs_referents(tvb, offset, pinfo, subtree, dp_list,
1336 &child_dp_list, NULL);
1342 * USER_LEVEL_1 structure
1345 static gint ett_USER_LEVEL_1 = -1;
1347 static int prs_USER_LEVEL_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
1348 proto_tree *tree, GList **dp_list, void **data)
1351 proto_tree *subtree;
1354 item = proto_tree_add_text(tree, tvb, offset, 0, "USER_LEVEL_1");
1356 subtree = proto_item_add_subtree(item, ett_USER_LEVEL_1);
1358 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Size");
1360 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Client name");
1363 defer_ptr(dp_list, prs_UNISTR2_dp, subtree);
1365 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "User name");
1368 defer_ptr(dp_list, prs_UNISTR2_dp, subtree);
1370 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Build");
1372 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Major");
1374 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Minor");
1376 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Processor");
1382 * USER_LEVEL structure
1385 static gint ett_USER_LEVEL = -1;
1387 static int prs_USER_LEVEL(tvbuff_t *tvb, int offset, packet_info *pinfo,
1388 proto_tree *tree, GList **parent_dp_list,
1392 proto_tree *subtree;
1396 item = proto_tree_add_text(tree, tvb, offset, 0, "USER_LEVEL");
1398 subtree = proto_item_add_subtree(item, ett_USER_LEVEL);
1400 offset = prs_uint32(tvb, offset, pinfo, subtree, &level, "Info level");
1402 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "User level");
1407 defer_ptr(parent_dp_list, prs_USER_LEVEL_1, subtree);
1410 proto_tree_add_text(
1411 tree, tvb, offset, 0,
1412 "[GetPrinter level %d not decoded]", level);
1421 * SpoolssOpenPrinterEx
1424 static int SpoolssOpenPrinterEx_q(tvbuff_t *tvb, int offset,
1425 packet_info *pinfo, proto_tree *tree,
1428 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1429 request_hash_value *request_info;
1433 /* Update informational fields */
1435 if (check_col(pinfo->cinfo, COL_INFO))
1436 col_set_str(pinfo->cinfo, COL_INFO, "OpenPrinterEx request");
1438 request_info = fetch_request_info(pinfo, di, SPOOLSS_OPENPRINTEREX);
1441 add_request_text(tree, tvb, offset, request_info);
1445 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Printer name");
1450 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1452 (void **)&printer_name,
1455 if (check_col(pinfo->cinfo, COL_INFO))
1456 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1459 if (!request_info) {
1461 /* Store printer name to match with response packet */
1463 store_request_info_OpenPrinterEx(pinfo, di,
1470 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1471 prs_PRINTER_DEFAULT, NULL, NULL);
1473 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "User switch");
1475 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1476 prs_USER_LEVEL, NULL, NULL);
1478 if (tvb_length_remaining(tvb, offset) != 0)
1479 proto_tree_add_text(tree, tvb, offset, 0,
1480 "[Long frame (%d bytes): SPOOLSS]",
1481 tvb_length_remaining(tvb, offset));
1486 static int SpoolssOpenPrinterEx_r(tvbuff_t *tvb, int offset,
1487 packet_info *pinfo, proto_tree *tree,
1490 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1491 request_hash_value *request_info;
1492 GList *dp_list = NULL;
1493 int start_offset = offset;
1496 /* Display informational data */
1498 if (check_col(pinfo->cinfo, COL_INFO))
1499 col_set_str(pinfo->cinfo, COL_INFO, "OpenPrinterEx response");
1501 request_info = fetch_request_info(pinfo, di, SPOOLSS_OPENPRINTEREX);
1502 add_response_text(tree, tvb, offset, request_info);
1505 request_info->response_num = pinfo->fd->num;
1509 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
1511 offset = prs_werror(tvb, offset, pinfo, tree, &status);
1514 const guint8 *policy_hnd;
1516 /* Associate the returned printer handle with a name */
1518 policy_hnd = tvb_get_ptr(tvb, start_offset, 20);
1524 request_info->data.OpenPrinterEx.printer_name;
1527 store_printer_name(policy_hnd, printer_name);
1531 if (tvb_length_remaining(tvb, offset) != 0)
1532 proto_tree_add_text(tree, tvb, offset, 0,
1533 "[Long frame (%d bytes): SPOOLSS]",
1534 tvb_length_remaining(tvb, offset));
1540 * NOTIFY_OPTION_DATA structure
1543 static gint ett_NOTIFY_OPTION_DATA = -1;
1545 static int prs_NOTIFY_OPTION_DATA(tvbuff_t *tvb, int offset,
1546 packet_info *pinfo, proto_tree *tree,
1547 GList **parent_dp_list, void **data)
1550 proto_tree *subtree;
1553 item = proto_tree_add_text(tree, tvb, offset, 0, "NOTIFY_OPTION_DATA");
1555 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION_DATA);
1557 offset = prs_uint32(tvb, offset, pinfo, subtree, &count, "Count");
1559 for (i = 0; i < count; i++)
1560 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL,
1567 * NOTIFY_OPTION structure
1570 static gint ett_NOTIFY_OPTION = -1;
1572 static int prs_NOTIFY_OPTION(tvbuff_t *tvb, int offset, packet_info *pinfo,
1573 proto_tree *tree, GList **parent_dp_list,
1577 proto_tree *subtree;
1580 item = proto_tree_add_text(tree, tvb, offset, 0, "NOTIFY_OPTION");
1582 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION);
1584 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Type");
1586 offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Reserved");
1588 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Reserved");
1590 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Reserved");
1592 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Count");
1594 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Fields");
1597 defer_ptr(parent_dp_list, prs_NOTIFY_OPTION_DATA, subtree);
1603 * NOTIFY_OPTION_CTR structure
1606 static gint ett_NOTIFY_OPTION_CTR = -1;
1608 static int prs_NOTIFY_OPTION_CTR(tvbuff_t *tvb, int offset,
1609 packet_info *pinfo, proto_tree *tree,
1610 GList **dp_list, void **data)
1612 GList *child_dp_list = NULL;
1614 proto_tree *subtree;
1615 guint32 count, i, ptr;
1617 item = proto_tree_add_text(tree, tvb, offset, 0,
1618 "NOTIFY_OPTION_CTR");
1620 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION_CTR);
1622 offset = prs_uint32(tvb, offset, pinfo, subtree, &count, "Count");
1624 for (i = 0; i < count; i++)
1625 offset = prs_NOTIFY_OPTION(tvb, offset, pinfo, subtree,
1626 &child_dp_list, NULL);
1628 offset = prs_referents(tvb, offset, pinfo, subtree, dp_list,
1629 &child_dp_list, NULL);
1635 * NOTIFY_OPTION structure
1638 gint ett_NOTIFY_OPTION_ARRAY = -1;
1640 static int prs_NOTIFY_OPTION_ARRAY(tvbuff_t *tvb, int offset,
1641 packet_info *pinfo, proto_tree *tree,
1642 GList **dp_list, void **data)
1645 proto_tree *subtree;
1648 item = proto_tree_add_text(tree, tvb, offset, 0,
1649 "NOTIFY_OPTION_ARRAY");
1651 subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION_ARRAY);
1653 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Version");
1655 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Flags");
1657 offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "Count");
1659 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Option type");
1662 defer_ptr(dp_list, prs_NOTIFY_OPTION_CTR, subtree);
1671 static int SpoolssRFFPCNEX_q(tvbuff_t *tvb, int offset,
1672 packet_info *pinfo, proto_tree *tree,
1675 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1676 request_hash_value *request_info;
1680 /* Update informational fields */
1682 if (check_col(pinfo->cinfo, COL_INFO))
1683 col_set_str(pinfo->cinfo, COL_INFO, "RFFPCNEX request");
1685 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
1688 add_request_text(tree, tvb, offset, request_info);
1690 store_request_info_none(pinfo, di);
1694 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
1696 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Flags");
1698 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Options");
1700 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Local machine");
1703 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1705 (void *)&printer_name, NULL);
1707 if (check_col(pinfo->cinfo, COL_INFO))
1708 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1712 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Printer local");
1714 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Option");
1717 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1718 prs_NOTIFY_OPTION_ARRAY,
1722 if (tvb_length_remaining(tvb, offset) != 0)
1723 proto_tree_add_text(tree, tvb, offset, 0,
1724 "[Long frame (%d bytes): SPOOLSS]",
1725 tvb_length_remaining(tvb, offset));
1730 static int SpoolssRFFPCNEX_r(tvbuff_t *tvb, int offset,
1731 packet_info *pinfo, proto_tree *tree,
1734 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1735 request_hash_value *request_info;
1737 /* Update informational fields */
1739 if (check_col(pinfo->cinfo, COL_INFO))
1740 col_set_str(pinfo->cinfo, COL_INFO, "RFFPCNEX response");
1742 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
1743 add_response_text(tree, tvb, offset, request_info);
1746 request_info->response_num = pinfo->fd->num;
1750 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
1752 if (tvb_length_remaining(tvb, offset) != 0)
1753 proto_tree_add_text(tree, tvb, offset, 0,
1754 "[Long frame (%d bytes): SPOOLSS]",
1755 tvb_length_remaining(tvb, offset));
1761 * SpoolssReplyOpenPrinter
1764 static int SpoolssReplyOpenPrinter_q(tvbuff_t *tvb, int offset,
1765 packet_info *pinfo, proto_tree *tree,
1768 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1769 request_hash_value *request_info;
1770 guint32 ptr = 0, type;
1772 /* Update informational fields */
1774 if (check_col(pinfo->cinfo, COL_INFO))
1775 col_set_str(pinfo->cinfo, COL_INFO,
1776 "ReplyOpenPrinter request");
1778 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
1781 add_request_text(tree, tvb, offset, request_info);
1783 store_request_info_none(pinfo, di);
1787 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1788 prs_UNISTR2_dp, NULL, NULL);
1790 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Printer");
1792 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
1794 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
1795 val_to_str(type, reg_datatypes, "Unknown type"));
1797 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1799 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
1801 if (tvb_length_remaining(tvb, offset) != 0)
1802 proto_tree_add_text(tree, tvb, offset, 0,
1803 "[Long frame (%d bytes): SPOOLSS]",
1804 tvb_length_remaining(tvb, offset));
1809 static int SpoolssReplyOpenPrinter_r(tvbuff_t *tvb, int offset,
1810 packet_info *pinfo, proto_tree *tree,
1813 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1814 request_hash_value *request_info;
1815 GList *dp_list = NULL;
1817 /* Update informational fields */
1819 if (check_col(pinfo->cinfo, COL_INFO))
1820 col_set_str(pinfo->cinfo, COL_INFO,
1821 "ReplyOpenPrinter response");
1823 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
1824 add_response_text(tree, tvb, offset, request_info);
1827 request_info->response_num = pinfo->fd->num;
1831 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
1833 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
1835 if (tvb_length_remaining(tvb, offset) != 0)
1836 proto_tree_add_text(tree, tvb, offset, 0,
1837 "[Long frame (%d bytes): SPOOLSS]",
1838 tvb_length_remaining(tvb, offset));
1847 static gint ett_BUFFER_DATA = -1;
1848 static gint ett_BUFFER_DATA_BUFFER = -1;
1850 struct BUFFER_DATA {
1851 guint8 *data8; /* Pointer to buffer data */
1852 proto_item *item; /* proto_item holding proto_tree */
1853 proto_tree *tree; /* proto_tree holding buffer data */
1855 int offset; /* Offset where data starts in tvb*/
1858 static int prs_BUFFER_DATA(tvbuff_t *tvb, int offset, packet_info *pinfo,
1859 proto_tree *tree, GList **dp_list, void **data)
1861 proto_item *item, *subitem;
1862 proto_tree *subtree, *subsubtree;
1863 guint32 ptr = 0, size;
1866 item = proto_tree_add_text(tree, tvb, offset, 0, "BUFFER_DATA");
1868 subtree = proto_item_add_subtree(item, ett_BUFFER_DATA);
1870 offset = prs_uint32(tvb, offset, pinfo, subtree, &size, "Size");
1872 subitem = proto_tree_add_text(subtree, tvb, offset, size, "Data");
1874 subsubtree = proto_item_add_subtree(subitem, ett_BUFFER_DATA_BUFFER);
1876 offset = prs_uint8s(tvb, offset, pinfo, subsubtree, size, &data8,
1879 /* Return some info which will help the caller "cast" the buffer
1880 data and dissect it further. */
1883 struct BUFFER_DATA *bd;
1885 bd = (struct BUFFER_DATA *)malloc(sizeof(struct BUFFER_DATA));
1889 bd->tree = subsubtree;
1891 bd->offset = offset - size;
1903 static gint ett_BUFFER = -1;
1905 static int prs_BUFFER(tvbuff_t *tvb, int offset, packet_info *pinfo,
1906 proto_tree *tree, GList **dp_list, void **data)
1909 proto_tree *subtree;
1912 item = proto_tree_add_text(tree, tvb, offset, 0, "BUFFER");
1914 subtree = proto_item_add_subtree(item, ett_BUFFER);
1916 offset = prs_ptr(tvb, offset, pinfo, subtree, &ptr, "Data");
1919 defer_ptr(dp_list, prs_BUFFER_DATA, subtree);
1928 static int SpoolssGetPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
1929 proto_tree *tree, char *drep)
1931 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1932 request_hash_value *request_info;
1933 GList *dp_list = NULL;
1935 const guint8 *policy_hnd;
1937 /* Update informational fields */
1939 if (check_col(pinfo->cinfo, COL_INFO))
1940 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinter request");
1942 request_info = fetch_request_info(pinfo, di, SPOOLSS_GETPRINTER);
1945 add_request_text(tree, tvb, offset, request_info);
1949 offset = prs_policy_hnd(tvb, offset, pinfo, tree, &policy_hnd);
1951 append_printer_name(pinfo, tvb, offset, policy_hnd);
1953 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
1955 if (check_col(pinfo->cinfo, COL_INFO))
1956 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
1958 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
1959 prs_BUFFER, NULL, NULL);
1961 if (!request_info) {
1963 /* Store info level to match with response packet */
1965 store_request_info_GetPrinter(pinfo, di, level);
1968 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
1970 if (tvb_length_remaining(tvb, offset) != 0)
1971 proto_tree_add_text(tree, tvb, offset, 0,
1972 "[Long frame (%d bytes): SPOOLSS]",
1973 tvb_length_remaining(tvb, offset));
1978 static int SpoolssGetPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
1979 proto_tree *tree, char *drep)
1981 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
1982 request_hash_value *request_info;
1983 GList *dp_list = NULL;
1985 struct BUFFER_DATA *bd = NULL;
1988 /* Update informational fields */
1990 if (check_col(pinfo->cinfo, COL_INFO))
1991 col_set_str(pinfo->cinfo, COL_INFO, "GetPrinter response");
1993 request_info = fetch_request_info(pinfo, di, SPOOLSS_GETPRINTER);
1994 add_response_text(tree, tvb, offset, request_info);
1997 request_info->response_num = pinfo->fd->num;
2001 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2002 prs_BUFFER, (void **)&data8,
2006 bd = (struct BUFFER_DATA *)data_list[0];
2008 if (bd && bd->tree && request_info) {
2009 gint16 level = request_info->data.GetPrinter.level;
2011 proto_item_append_text(bd->item, ", PRINTER_INFO_%d", level);
2015 prs_PRINTER_INFO_0(bd->tvb, bd->offset, pinfo,
2016 bd->tree, &dp_list, NULL);
2020 prs_PRINTER_INFO_2(bd->tvb, bd->offset, pinfo,
2021 bd->tree, &dp_list, NULL);
2025 proto_tree_add_text(tree, tvb, offset, 0,
2026 "[Unimplemented info level %d]",
2032 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
2034 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2036 if (tvb_length_remaining(tvb, offset) != 0)
2037 proto_tree_add_text(tree, tvb, offset, 0,
2038 "[Long frame (%d bytes): SPOOLSS]",
2039 tvb_length_remaining(tvb, offset));
2045 * SPOOL_PRINTER_INFO_LEVEL
2048 static gint ett_SPOOL_PRINTER_INFO_LEVEL = -1;
2050 static int prs_SPOOL_PRINTER_INFO_LEVEL(tvbuff_t *tvb, int offset,
2051 packet_info *pinfo, proto_tree *tree,
2052 GList **dp_list, void **data)
2055 proto_tree *subtree;
2056 guint32 ptr = 0, level;
2058 item = proto_tree_add_text(tree, tvb, offset, 0,
2059 "SPOOL_PRINTER_INFO_LEVEL");
2061 subtree = proto_item_add_subtree(item, ett_SPOOL_PRINTER_INFO_LEVEL);
2063 offset = prs_uint32(tvb, offset, pinfo, subtree, &level, "Level");
2077 static int SpoolssSetPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2078 proto_tree *tree, char *drep)
2080 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2081 request_hash_value *request_info;
2082 GList *dp_list = NULL;
2085 /* Update informational fields */
2087 if (check_col(pinfo->cinfo, COL_INFO))
2088 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinter request");
2090 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2093 add_request_text(tree, tvb, offset, request_info);
2095 store_request_info_none(pinfo, di);
2099 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
2101 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2103 if (check_col(pinfo->cinfo, COL_INFO))
2104 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
2106 /* printer_info_level */
2108 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2109 prs_SPOOL_PRINTER_INFO_LEVEL,
2115 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Command");
2117 if (tvb_length_remaining(tvb, offset) != 0)
2118 proto_tree_add_text(tree, tvb, offset, 0,
2119 "[Long frame (%d bytes): SPOOLSS]",
2120 tvb_length_remaining(tvb, offset));
2125 static int SpoolssSetPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2126 proto_tree *tree, char *drep)
2128 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2129 request_hash_value *request_info;
2130 GList *dp_list = NULL;
2132 /* Update informational fields */
2134 if (check_col(pinfo->cinfo, COL_INFO))
2135 col_set_str(pinfo->cinfo, COL_INFO, "SetPrinter response");
2137 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2138 add_response_text(tree, tvb, offset, request_info);
2141 request_info->response_num = pinfo->fd->num;
2145 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2147 if (tvb_length_remaining(tvb, offset) != 0)
2148 proto_tree_add_text(tree, tvb, offset, 0,
2149 "[Long frame (%d bytes): SPOOLSS]",
2150 tvb_length_remaining(tvb, offset));
2159 static int SpoolssEnumForms_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2160 proto_tree *tree, char *drep)
2162 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2163 request_hash_value *request_info;
2164 GList *dp_list = NULL;
2166 const guint8 *policy_hnd;
2168 /* Update informational fields */
2170 if (check_col(pinfo->cinfo, COL_INFO))
2171 col_set_str(pinfo->cinfo, COL_INFO, "EnumForms request");
2173 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2176 add_request_text(tree, tvb, offset, request_info);
2178 store_request_info_none(pinfo, di);
2182 offset = prs_policy_hnd(tvb, offset, pinfo, tree, &policy_hnd);
2184 append_printer_name(pinfo, tvb, offset, policy_hnd);
2186 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2188 if (check_col(pinfo->cinfo, COL_INFO))
2189 col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
2191 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2192 prs_BUFFER, NULL, NULL);
2194 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
2196 if (tvb_length_remaining(tvb, offset) != 0)
2197 proto_tree_add_text(tree, tvb, offset, 0,
2198 "[Long frame (%d bytes): SPOOLSS]",
2199 tvb_length_remaining(tvb, offset));
2204 static int SpoolssEnumForms_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2205 proto_tree *tree, char *drep)
2207 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2208 request_hash_value *request_info;
2209 GList *dp_list = NULL;
2211 /* Update informational fields */
2213 if (check_col(pinfo->cinfo, COL_INFO))
2214 col_set_str(pinfo->cinfo, COL_INFO, "EnumForms response");
2216 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2217 add_response_text(tree, tvb, offset, request_info);
2220 request_info->response_num = pinfo->fd->num;
2224 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2225 prs_BUFFER, NULL, NULL);
2227 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
2229 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Num entries");
2231 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2233 if (tvb_length_remaining(tvb, offset) != 0)
2234 proto_tree_add_text(tree, tvb, offset, 0,
2235 "[Long frame (%d bytes): SPOOLSS]",
2236 tvb_length_remaining(tvb, offset));
2242 * SpoolssDeletePrinter
2245 static int SpoolssDeletePrinter_q(tvbuff_t *tvb, int offset,
2246 packet_info *pinfo, proto_tree *tree,
2249 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2250 request_hash_value *request_info;
2251 const guint8 *policy_hnd;
2253 /* Update informational fields */
2255 if (check_col(pinfo->cinfo, COL_INFO))
2256 col_set_str(pinfo->cinfo, COL_INFO, "DeletePrinter request");
2258 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2261 add_request_text(tree, tvb, offset, request_info);
2263 store_request_info_none(pinfo, di);
2267 offset = prs_policy_hnd(tvb, offset, pinfo, tree, &policy_hnd);
2269 append_printer_name(pinfo, tvb, offset, policy_hnd);
2271 if (tvb_length_remaining(tvb, offset) != 0)
2272 proto_tree_add_text(tree, tvb, offset, 0,
2273 "[Long frame (%d bytes): SPOOLSS]",
2274 tvb_length_remaining(tvb, offset));
2279 static int SpoolssDeletePrinter_r(tvbuff_t *tvb, int offset,
2280 packet_info *pinfo, proto_tree *tree,
2283 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2284 request_hash_value *request_info;
2286 /* Update informational fields */
2288 if (check_col(pinfo->cinfo, COL_INFO))
2289 col_set_str(pinfo->cinfo, COL_INFO, "DeletePrinter response");
2291 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2292 add_response_text(tree, tvb, offset, request_info);
2295 request_info->response_num = pinfo->fd->num;
2299 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
2301 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2303 if (tvb_length_remaining(tvb, offset) != 0)
2304 proto_tree_add_text(tree, tvb, offset, 0,
2305 "[Long frame (%d bytes): SPOOLSS]",
2306 tvb_length_remaining(tvb, offset));
2315 static int SpoolssAddPrinterEx_q(tvbuff_t *tvb, int offset,
2316 packet_info *pinfo, proto_tree *tree,
2319 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2320 request_hash_value *request_info;
2324 /* Update informational fields */
2326 if (check_col(pinfo->cinfo, COL_INFO))
2327 col_set_str(pinfo->cinfo, COL_INFO, "AddPrinterEx request");
2329 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2332 add_request_text(tree, tvb, offset, request_info);
2334 store_request_info_none(pinfo, di);
2338 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Server name");
2341 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2343 (void *)&printer_name, NULL);
2346 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Level");
2348 /* PRINTER INFO LEVEL */
2350 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2351 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2352 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2353 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Unknown");
2355 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "User switch");
2359 if (tvb_length_remaining(tvb, offset) != 0)
2360 proto_tree_add_text(tree, tvb, offset, 0,
2361 "[Long frame (%d bytes): SPOOLSS]",
2362 tvb_length_remaining(tvb, offset));
2367 static int SpoolssAddPrinterEx_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2368 proto_tree *tree, char *drep)
2370 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2371 request_hash_value *request_info;
2372 int start_offset = offset;
2375 /* Update informational fields */
2377 if (check_col(pinfo->cinfo, COL_INFO))
2378 col_set_str(pinfo->cinfo, COL_INFO, "AddPrinterEx response");
2380 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2381 add_response_text(tree, tvb, offset, request_info);
2384 request_info->response_num = pinfo->fd->num;
2388 offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
2390 offset = prs_werror(tvb, offset, pinfo, tree, &status);
2393 const guint8 *policy_hnd;
2396 /* Associate the returned printer handle with a name */
2398 policy_hnd = tvb_get_ptr(tvb, start_offset, 20);
2400 printer_name = strdup("<printer name here>");
2402 store_printer_name(policy_hnd, printer_name);
2404 if (check_col(pinfo->cinfo, COL_INFO))
2405 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
2411 if (tvb_length_remaining(tvb, offset) != 0)
2412 proto_tree_add_text(tree, tvb, offset, 0,
2413 "[Long frame (%d bytes): SPOOLSS]",
2414 tvb_length_remaining(tvb, offset));
2420 * SpoolssEnumPrinterData
2423 static int SpoolssEnumPrinterData_q(tvbuff_t *tvb, int offset,
2424 packet_info *pinfo, proto_tree *tree,
2427 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2428 request_hash_value *request_info;
2429 const guint8 *policy_hnd;
2431 /* Update informational fields */
2433 if (check_col(pinfo->cinfo, COL_INFO))
2434 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinterData request");
2436 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2439 add_request_text(tree, tvb, offset, request_info);
2441 store_request_info_none(pinfo, di);
2445 offset = prs_policy_hnd(tvb, offset, pinfo, tree, &policy_hnd);
2447 append_printer_name(pinfo, tvb, offset, policy_hnd);
2449 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Index");
2451 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Value size");
2453 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Data size");
2455 if (tvb_length_remaining(tvb, offset) != 0)
2456 proto_tree_add_text(tree, tvb, offset, 0,
2457 "[Long frame (%d bytes): SPOOLSS]",
2458 tvb_length_remaining(tvb, offset));
2463 static int SpoolssEnumPrinterData_r(tvbuff_t *tvb, int offset,
2464 packet_info *pinfo, proto_tree *tree,
2467 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2468 request_hash_value *request_info;
2469 guint32 data_size, type, value_size;
2473 /* Update informational fields */
2475 if (check_col(pinfo->cinfo, COL_INFO))
2476 col_set_str(pinfo->cinfo, COL_INFO,
2477 "EnumPrinterData response");
2479 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2480 add_response_text(tree, tvb, offset, request_info);
2483 request_info->response_num = pinfo->fd->num;
2487 offset = prs_uint32(tvb, offset, pinfo, tree, &value_size,
2490 offset = prs_uint16s(tvb, offset, pinfo, tree, value_size, &uint16s,
2493 text = fake_unicode(uint16s, value_size);
2495 proto_tree_add_text(tree, tvb, offset - value_size * 2,
2496 value_size * 2, "Value: %s", text);
2498 if (text[0] && check_col(pinfo->cinfo, COL_INFO))
2499 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", text);
2503 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real value size");
2505 offset = prs_uint32(tvb, offset, pinfo, tree, &type, NULL);
2507 proto_tree_add_text(tree, tvb, offset - 4, 4, "Type: %s",
2508 val_to_str(type, reg_datatypes, "Unknown type"));
2510 offset = prs_uint32(tvb, offset, pinfo, tree, &data_size, "Data size");
2512 offset = prs_uint8s(tvb, offset, pinfo, tree, data_size, NULL,
2515 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Real data size");
2517 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2519 if (tvb_length_remaining(tvb, offset) != 0)
2520 proto_tree_add_text(tree, tvb, offset, 0,
2521 "[Long frame (%d bytes): SPOOLSS]",
2522 tvb_length_remaining(tvb, offset));
2528 * SpoolssEnumPrinters
2531 static int SpoolssEnumPrinters_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2532 proto_tree *tree, char *drep)
2534 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2535 request_hash_value *request_info;
2538 /* Update informational fields */
2540 if (check_col(pinfo->cinfo, COL_INFO))
2541 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinters request");
2543 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2546 add_request_text(tree, tvb, offset, request_info);
2548 store_request_info_none(pinfo, di);
2552 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Flags");
2554 offset = prs_ptr(tvb, offset, pinfo, tree, &ptr, "Devicemode");
2557 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2558 prs_UNISTR2_dp, NULL, NULL);
2560 offset = prs_uint32(tvb, offset, pinfo, tree, &level, "Level");
2562 if (check_col(pinfo->cinfo, COL_INFO))
2563 col_append_fstr(pinfo->cinfo, COL_INFO, ", level, %d", level);
2565 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2566 prs_BUFFER, NULL, NULL);
2568 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Offered");
2570 if (tvb_length_remaining(tvb, offset) != 0)
2571 proto_tree_add_text(tree, tvb, offset, 0,
2572 "[Long frame (%d bytes): SPOOLSS]",
2573 tvb_length_remaining(tvb, offset));
2578 static int SpoolssEnumPrinters_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2579 proto_tree *tree, char *drep)
2581 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2582 request_hash_value *request_info;
2584 /* Update informational fields */
2586 if (check_col(pinfo->cinfo, COL_INFO))
2587 col_set_str(pinfo->cinfo, COL_INFO, "EnumPrinters response");
2589 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2590 add_response_text(tree, tvb, offset, request_info);
2593 request_info->response_num = pinfo->fd->num;
2597 offset = prs_struct_and_referents(tvb, offset, pinfo, tree,
2598 prs_BUFFER, NULL, NULL);
2600 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Needed");
2602 offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Returned");
2604 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2606 if (tvb_length_remaining(tvb, offset) != 0)
2607 proto_tree_add_text(tree, tvb, offset, 0,
2608 "[Long frame (%d bytes): SPOOLSS]",
2609 tvb_length_remaining(tvb, offset));
2618 static int SpoolssAddPrinterDriver_q(tvbuff_t *tvb, int offset,
2619 packet_info *pinfo, proto_tree *tree,
2622 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2623 request_hash_value *request_info;
2625 /* Update informational fields */
2627 if (check_col(pinfo->cinfo, COL_INFO))
2628 col_set_str(pinfo->cinfo, COL_INFO,
2629 "AddPrinterDriver request");
2631 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2634 add_request_text(tree, tvb, offset, request_info);
2636 store_request_info_none(pinfo, di);
2640 if (tvb_length_remaining(tvb, offset) != 0)
2641 proto_tree_add_text(tree, tvb, offset, 0,
2642 "[Long frame (%d bytes): SPOOLSS]",
2643 tvb_length_remaining(tvb, offset));
2648 static int SpoolssAddPrinterDriver_r(tvbuff_t *tvb, int offset,
2649 packet_info *pinfo, proto_tree *tree,
2652 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2653 request_hash_value *request_info;
2655 /* Update informational fields */
2657 if (check_col(pinfo->cinfo, COL_INFO))
2658 col_set_str(pinfo->cinfo, COL_INFO,
2659 "AddPrinterDriver response");
2661 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2662 add_response_text(tree, tvb, offset, request_info);
2665 request_info->response_num = pinfo->fd->num;
2669 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2671 if (tvb_length_remaining(tvb, offset) != 0)
2672 proto_tree_add_text(tree, tvb, offset, 0,
2673 "[Long frame (%d bytes): SPOOLSS]",
2674 tvb_length_remaining(tvb, offset));
2683 static int SpoolssAddForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2684 proto_tree *tree, char *drep)
2686 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2687 request_hash_value *request_info;
2689 /* Update informational fields */
2691 if (check_col(pinfo->cinfo, COL_INFO))
2692 col_set_str(pinfo->cinfo, COL_INFO, "AddForm response");
2694 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2695 add_response_text(tree, tvb, offset, request_info);
2698 request_info->response_num = pinfo->fd->num;
2702 offset = prs_werror(tvb, offset, pinfo, tree, NULL);
2704 if (tvb_length_remaining(tvb, offset) != 0)
2705 proto_tree_add_text(tree, tvb, offset, 0,
2706 "[Long frame (%d bytes): SPOOLSS]",
2707 tvb_length_remaining(tvb, offset));
2714 /* Templates for new subdissectors */
2720 static int SpoolssFoo_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
2721 proto_tree *tree, char *drep)
2723 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2724 request_hash_value *request_info;
2726 /* Update informational fields */
2728 if (check_col(pinfo->cinfo, COL_INFO))
2729 col_set_str(pinfo->cinfo, COL_INFO, "Foo request");
2731 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2734 add_request_text(tree, tvb, offset, request_info);
2736 store_request_info_none(pinfo, di);
2740 if (tvb_length_remaining(tvb, offset) != 0)
2741 proto_tree_add_text(tree, tvb, offset, 0,
2742 "[Long frame (%d bytes): SPOOLSS]",
2743 tvb_length_remaining(tvb, offset));
2748 static int SpoolssFoo_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
2749 proto_tree *tree, char *drep)
2751 dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
2752 request_hash_value *request_info;
2754 /* Update informational fields */
2756 if (check_col(pinfo->cinfo, COL_INFO))
2757 col_set_str(pinfo->cinfo, COL_INFO, "Foo response");
2759 request_info = fetch_request_info(pinfo, di, SPOOLSS_DUMMY);
2760 add_response_text(tree, tvb, offset, request_info);
2763 request_info->response_num = pinfo->fd->num;
2767 if (tvb_length_remaining(tvb, offset) != 0)
2768 proto_tree_add_text(tree, tvb, offset, 0,
2769 "[Long frame (%d bytes): SPOOLSS]",
2770 tvb_length_remaining(tvb, offset));
2778 * List of subdissectors for this pipe.
2781 static dcerpc_sub_dissector dcerpc_spoolss_dissectors[] = {
2782 { SPOOLSS_ENUMPRINTERS, "SPOOLSS_ENUMPRINTERS",
2783 SpoolssEnumPrinters_q, SpoolssEnumPrinters_r },
2784 { SPOOLSS_SETJOB, "SPOOLSS_SETJOB", NULL, NULL },
2785 { SPOOLSS_GETJOB, "SPOOLSS_GETJOB", NULL, NULL },
2786 { SPOOLSS_ENUMJOBS, "SPOOLSS_ENUMJOBS", NULL, NULL },
2787 { SPOOLSS_ADDPRINTER, "SPOOLSS_ADDPRINTER", NULL, NULL },
2788 { SPOOLSS_DELETEPRINTER, "SPOOLSS_DELETEPRINTER",
2789 SpoolssDeletePrinter_q, SpoolssDeletePrinter_r },
2790 { SPOOLSS_SETPRINTER, "SPOOLSS_SETPRINTER",
2791 SpoolssSetPrinter_q, SpoolssSetPrinter_r },
2792 { SPOOLSS_GETPRINTER, "SPOOLSS_GETPRINTER",
2793 SpoolssGetPrinter_q, SpoolssGetPrinter_r },
2794 { SPOOLSS_ADDPRINTERDRIVER, "SPOOLSS_ADDPRINTERDRIVER",
2795 NULL, SpoolssAddPrinterDriver_r },
2796 { SPOOLSS_ENUMPRINTERDRIVERS, "SPOOLSS_ENUMPRINTERDRIVERS", NULL, NULL },
2797 { SPOOLSS_GETPRINTERDRIVERDIRECTORY, "SPOOLSS_GETPRINTERDRIVERDIRECTORY", NULL, NULL },
2798 { SPOOLSS_DELETEPRINTERDRIVER, "SPOOLSS_DELETEPRINTERDRIVER", NULL, NULL },
2799 { SPOOLSS_ADDPRINTPROCESSOR, "SPOOLSS_ADDPRINTPROCESSOR", NULL, NULL },
2800 { SPOOLSS_ENUMPRINTPROCESSORS, "SPOOLSS_ENUMPRINTPROCESSORS", NULL, NULL },
2801 { SPOOLSS_STARTDOCPRINTER, "SPOOLSS_STARTDOCPRINTER", NULL, NULL },
2802 { SPOOLSS_STARTPAGEPRINTER, "SPOOLSS_STARTPAGEPRINTER", NULL, NULL },
2803 { SPOOLSS_WRITEPRINTER, "SPOOLSS_WRITEPRINTER", NULL, NULL },
2804 { SPOOLSS_ENDPAGEPRINTER, "SPOOLSS_ENDPAGEPRINTER", NULL, NULL },
2805 { SPOOLSS_ABORTPRINTER, "SPOOLSS_ABORTPRINTER", NULL, NULL },
2806 { SPOOLSS_ENDDOCPRINTER, "SPOOLSS_ENDDOCPRINTER", NULL, NULL },
2807 { SPOOLSS_ADDJOB, "SPOOLSS_ADDJOB", NULL, NULL },
2808 { SPOOLSS_SCHEDULEJOB, "SPOOLSS_SCHEDULEJOB", NULL, NULL },
2809 { SPOOLSS_GETPRINTERDATA, "SPOOLSS_GETPRINTERDATA",
2810 SpoolssGetPrinterData_q, SpoolssGetPrinterData_r },
2811 { SPOOLSS_SETPRINTERDATA, "SPOOLSS_SETPRINTERDATA",
2812 SpoolssSetPrinterData_q, SpoolssSetPrinterData_r },
2813 { SPOOLSS_CLOSEPRINTER, "SPOOLSS_CLOSEPRINTER",
2814 SpoolssClosePrinter_q, SpoolssClosePrinter_r },
2815 { SPOOLSS_ADDFORM, "SPOOLSS_ADDFORM",
2816 NULL, SpoolssAddForm_r },
2817 { SPOOLSS_DELETEFORM, "SPOOLSS_DELETEFORM", NULL, NULL },
2818 { SPOOLSS_GETFORM, "SPOOLSS_GETFORM", NULL, NULL },
2819 { SPOOLSS_SETFORM, "SPOOLSS_SETFORM", NULL, NULL },
2820 { SPOOLSS_ENUMFORMS, "SPOOLSS_ENUMFORMS",
2821 SpoolssEnumForms_q, SpoolssEnumForms_r },
2822 { SPOOLSS_ENUMPORTS, "SPOOLSS_ENUMPORTS", NULL, NULL },
2823 { SPOOLSS_ENUMMONITORS, "SPOOLSS_ENUMMONITORS", NULL, NULL },
2824 { SPOOLSS_ENUMPRINTPROCDATATYPES, "SPOOLSS_ENUMPRINTPROCDATATYPES", NULL, NULL },
2825 { SPOOLSS_GETPRINTERDRIVER2, "SPOOLSS_GETPRINTERDRIVER2", NULL, NULL },
2826 { SPOOLSS_FCPN, "SPOOLSS_FCPN", NULL, NULL },
2827 { SPOOLSS_REPLYOPENPRINTER, "SPOOLSS_REPLYOPENPRINTER",
2828 SpoolssReplyOpenPrinter_q, SpoolssReplyOpenPrinter_r },
2829 { SPOOLSS_REPLYCLOSEPRINTER, "SPOOLSS_REPLYCLOSEPRINTER", NULL, NULL },
2830 { SPOOLSS_RFFPCNEX, "SPOOLSS_RFFPCNEX",
2831 SpoolssRFFPCNEX_q, SpoolssRFFPCNEX_r },
2832 { SPOOLSS_RRPCN, "SPOOLSS_RRPCN", NULL, NULL },
2833 { SPOOLSS_RFNPCNEX, "SPOOLSS_RFNPCNEX", NULL, NULL },
2834 { SPOOLSS_OPENPRINTEREX, "SPOOLSS_OPENPRINTEREX",
2835 SpoolssOpenPrinterEx_q, SpoolssOpenPrinterEx_r },
2836 { SPOOLSS_ADDPRINTEREX, "SPOOLSS_ADDPRINTEREX",
2837 NULL, SpoolssAddPrinterEx_r },
2838 { SPOOLSS_ENUMPRINTERDATA, "SPOOLSS_ENUMPRINTERDATA",
2839 SpoolssEnumPrinterData_q, SpoolssEnumPrinterData_r },
2840 { SPOOLSS_DELETEPRINTERDATA, "SPOOLSS_DELETEPRINTERDATA", NULL, NULL },
2841 { SPOOLSS_GETPRINTERDATAEX, "SPOOLSS_GETPRINTERDATAEX",
2842 SpoolssGetPrinterDataEx_q, SpoolssGetPrinterDataEx_r },
2843 { SPOOLSS_SETPRINTERDATAEX, "SPOOLSS_SETPRINTERDATAEX",
2844 SpoolssSetPrinterDataEx_q, SpoolssSetPrinterDataEx_r },
2846 {0, NULL, NULL, NULL },
2850 * Dissector initialisation function
2853 static void spoolss_init(void)
2855 /* Initialise policy handle to printer name hash table */
2857 if (policy_hnd_hash_key_chunk)
2858 g_mem_chunk_destroy(policy_hnd_hash_key_chunk);
2860 if (policy_hnd_hash_value_chunk)
2861 g_mem_chunk_destroy(policy_hnd_hash_value_chunk);
2863 policy_hnd_hash_key_chunk = g_mem_chunk_new(
2864 "policy_hnd_hash_key_chunk", sizeof(policy_hnd_hash_key),
2865 POLICY_HND_HASH_INIT_COUNT * sizeof(policy_hnd_hash_key),
2868 policy_hnd_hash_value_chunk = g_mem_chunk_new(
2869 "policy_hnd_hash_value_chunk", sizeof(policy_hnd_hash_value),
2870 POLICY_HND_HASH_INIT_COUNT * sizeof(policy_hnd_hash_value),
2873 policy_hnd_hash = g_hash_table_new(hash_policy_hnd,
2874 compare_policy_hnd);
2876 /* Initialise request/response matching hash table */
2878 if (request_hash_key_chunk)
2879 g_mem_chunk_destroy(request_hash_key_chunk);
2881 request_hash_key_chunk = g_mem_chunk_new(
2882 "request_hash_key_chunk", sizeof(request_hash_key),
2883 REQUEST_HASH_INIT_COUNT * sizeof(request_hash_key),
2886 request_hash_value_chunk = g_mem_chunk_new(
2887 "request_hash_value_chunk", sizeof(request_hash_value),
2888 REQUEST_HASH_INIT_COUNT * sizeof(request_hash_value),
2891 request_hash = g_hash_table_new(hash_request, compare_request);
2894 /* Protocol registration */
2896 static int proto_dcerpc_spoolss = -1;
2897 static gint ett_dcerpc_spoolss = -1;
2900 proto_register_dcerpc_spoolss(void)
2902 static gint *ett[] = {
2903 &ett_dcerpc_spoolss,
2904 &ett_NOTIFY_OPTION_ARRAY,
2905 &ett_NOTIFY_OPTION_CTR,
2907 &ett_NOTIFY_OPTION_DATA,
2908 &ett_PRINTER_DEFAULT,
2915 &ett_BUFFER_DATA_BUFFER,
2917 &ett_SPOOL_PRINTER_INFO_LEVEL,
2918 &ett_PRINTER_INFO_0,
2919 &ett_PRINTER_INFO_1,
2920 &ett_PRINTER_INFO_2,
2921 &ett_PRINTER_INFO_3,
2925 proto_dcerpc_spoolss = proto_register_protocol(
2926 "Microsoft Spool Subsystem", "SPOOLSS", "spoolss");
2928 proto_register_subtree_array(ett, array_length(ett));
2930 register_init_routine(spoolss_init);
2933 /* Protocol handoff */
2935 static e_uuid_t uuid_dcerpc_spoolss = {
2936 0x12345678, 0x1234, 0xabcd,
2937 { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
2940 static guint16 ver_dcerpc_spoolss = 1;
2943 proto_reg_handoff_dcerpc_spoolss(void)
2945 /* Register protocol as dcerpc */
2947 dcerpc_init_uuid(proto_dcerpc_spoolss, ett_dcerpc_spoolss,
2948 &uuid_dcerpc_spoolss, ver_dcerpc_spoolss,
2949 dcerpc_spoolss_dissectors);