1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4 
5    Copyright (C) Gerald Carter                2001-2005
6    Copyright (C) Tim Potter                        2000
7    Copyright (C) Andrew Tridgell              1992-1999
8    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9    Copyright (C) Guenther Deschner                 2009
10 
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15 
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20 
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24 
25 #include "includes.h"
26 #include "rpcclient.h"
27 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
28 #include "../librpc/gen_ndr/ndr_spoolss.h"
29 #include "rpc_client/cli_spoolss.h"
30 #include "rpc_client/init_spoolss.h"
31 #include "nt_printing.h"
32 #include "../libcli/security/display_sec.h"
33 #include "../libcli/security/security_descriptor.h"
34 #include "../libcli/registry/util_reg.h"
35 #include "libsmb/libsmb.h"
36 #include "popt_common_cmdline.h"
37 
38 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
39 { \
40 	_printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
41 		_cli->srv_name_slash, _arg); \
42 	W_ERROR_HAVE_NO_MEMORY(_printername); \
43 }
44 
45 /* The version int is used by getdrivers.  Note that
46    all architecture strings that support mutliple
47    versions must be grouped together since enumdrivers
48    uses this property to prevent issuing multiple
49    enumdriver calls for the same arch */
50 
51 
52 static const struct print_architecture_table_node archi_table[]= {
53 
54 	{"Windows 4.0",          "WIN40",	0 },
55 	{"Windows NT x86",       "W32X86",	2 },
56 	{"Windows NT x86",       "W32X86",	3 },
57 	{"Windows NT R4000",     "W32MIPS",	2 },
58 	{"Windows NT Alpha_AXP", "W32ALPHA",	2 },
59 	{"Windows NT PowerPC",   "W32PPC",	2 },
60 	{"Windows IA64",         "IA64",        3 },
61 	{"Windows x64",          "x64",         3 },
62 	{NULL,                   "",		-1 }
63 };
64 
65 /**
66  * @file
67  *
68  * rpcclient module for SPOOLSS rpc pipe.
69  *
70  * This generally just parses and checks command lines, and then calls
71  * a cli_spoolss function.
72  **/
73 
74 /****************************************************************************
75  function to do the mapping between the long architecture name and
76  the short one.
77 ****************************************************************************/
78 
cmd_spoolss_get_short_archi(const char * long_archi)79 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
80 {
81         int i=-1;
82 
83         DEBUG(107,("Getting architecture dependent directory\n"));
84         do {
85                 i++;
86         } while ( (archi_table[i].long_archi!=NULL ) &&
87                   strcasecmp_m(long_archi, archi_table[i].long_archi) );
88 
89         if (archi_table[i].long_archi==NULL) {
90                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
91                 return NULL;
92         }
93 
94 	/* this might be client code - but shouldn't this be an fstrcpy etc? */
95 
96 
97         DEBUGADD(108,("index: [%d]\n", i));
98         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
99         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
100 
101 	return archi_table[i].short_archi;
102 }
103 
104 /****************************************************************************
105 ****************************************************************************/
106 
cmd_spoolss_open_printer_ex(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)107 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
108                                             TALLOC_CTX *mem_ctx,
109                                             int argc, const char **argv)
110 {
111 	WERROR 	        werror;
112 	struct policy_handle	hnd;
113 	uint32_t access_mask = PRINTER_ALL_ACCESS;
114 	struct dcerpc_binding_handle *b = cli->binding_handle;
115 
116 	if (argc < 2) {
117 		printf("Usage: %s <printername> [access_mask]\n", argv[0]);
118 		return WERR_OK;
119 	}
120 
121 	if (argc >= 3) {
122 		sscanf(argv[2], "%x", &access_mask);
123 	}
124 
125 	/* Open the printer handle */
126 
127 	werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
128 					       argv[1],
129 					       access_mask,
130 					       &hnd);
131 	if (W_ERROR_IS_OK(werror)) {
132 		printf("Printer %s opened successfully\n", argv[1]);
133 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
134 
135 		if (!W_ERROR_IS_OK(werror)) {
136 			printf("Error closing printer handle! (%s)\n",
137 				get_dos_error_msg(werror));
138 		}
139 	}
140 
141 	return werror;
142 }
143 
144 /****************************************************************************
145 ****************************************************************************/
146 
cmd_spoolss_open_printer(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)147 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
148                                        TALLOC_CTX *mem_ctx,
149                                        int argc, const char **argv)
150 {
151 	WERROR 	        werror;
152 	struct policy_handle	hnd;
153 	uint32_t access_mask = PRINTER_ALL_ACCESS;
154 	NTSTATUS status;
155 	struct spoolss_DevmodeContainer devmode_ctr;
156 	struct dcerpc_binding_handle *b = cli->binding_handle;
157 
158 	ZERO_STRUCT(devmode_ctr);
159 
160 	if (argc < 2) {
161 		printf("Usage: %s <printername> [access_mask]\n", argv[0]);
162 		return WERR_OK;
163 	}
164 
165 	if (argc >= 3) {
166 		sscanf(argv[2], "%x", &access_mask);
167 	}
168 
169 	/* Open the printer handle */
170 
171 	status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
172 					    argv[1],
173 					    NULL,
174 					    devmode_ctr,
175 					    access_mask,
176 					    &hnd,
177 					    &werror);
178 	if (!NT_STATUS_IS_OK(status)) {
179 		return ntstatus_to_werror(status);
180 	}
181 	if (W_ERROR_IS_OK(werror)) {
182 		printf("Printer %s opened successfully\n", argv[1]);
183 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
184 
185 		if (!W_ERROR_IS_OK(werror)) {
186 			printf("Error closing printer handle! (%s)\n",
187 				get_dos_error_msg(werror));
188 		}
189 	}
190 
191 	return werror;
192 }
193 
194 /****************************************************************************
195 ****************************************************************************/
196 
display_print_info0(struct spoolss_PrinterInfo0 * r)197 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
198 {
199 	if (!r)
200 		return;
201 
202 	printf("\tprintername:[%s]\n", r->printername);
203 	printf("\tservername:[%s]\n", r->servername);
204 	printf("\tcjobs:[0x%x]\n", r->cjobs);
205 	printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
206 	printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
207 	printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
208 	       r->time.day, r->time.day_of_week);
209 	printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
210 	       r->time.second, r->time.millisecond);
211 
212 	printf("\tglobal_counter:[0x%x]\n", r->global_counter);
213 	printf("\ttotal_pages:[0x%x]\n", r->total_pages);
214 
215 	printf("\tversion:[0x%x]\n", r->version);
216 	printf("\tfree_build:[0x%x]\n", r->free_build);
217 	printf("\tspooling:[0x%x]\n", r->spooling);
218 	printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
219 	printf("\tsession_counter:[0x%x]\n", r->session_counter);
220 	printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
221 	printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
222 	printf("\tjob_error:[0x%x]\n", r->job_error);
223 	printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
224 	printf("\tprocessor_type:[0x%x]\n", r->processor_type);
225 	printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
226 	printf("\tchange_id:[0x%x]\n", r->change_id);
227 	printf("\tlast_error: %s\n", win_errstr(r->last_error));
228 	printf("\tstatus:[0x%x]\n", r->status);
229 	printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
230 	printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
231 	printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
232 	printf("\tprocessor_level:[0x%x]\n", r->processor_level);
233 	printf("\tref_ic:[0x%x]\n", r->ref_ic);
234 	printf("\treserved2:[0x%x]\n", r->reserved2);
235 	printf("\treserved3:[0x%x]\n", r->reserved3);
236 
237 	printf("\n");
238 }
239 
240 /****************************************************************************
241 ****************************************************************************/
242 
display_print_info1(struct spoolss_PrinterInfo1 * r)243 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
244 {
245 	printf("\tflags:[0x%x]\n", r->flags);
246 	printf("\tname:[%s]\n", r->name);
247 	printf("\tdescription:[%s]\n", r->description);
248 	printf("\tcomment:[%s]\n", r->comment);
249 
250 	printf("\n");
251 }
252 
253 /****************************************************************************
254 ****************************************************************************/
255 
display_print_info2(struct spoolss_PrinterInfo2 * r)256 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
257 {
258 	printf("\tservername:[%s]\n", r->servername);
259 	printf("\tprintername:[%s]\n", r->printername);
260 	printf("\tsharename:[%s]\n", r->sharename);
261 	printf("\tportname:[%s]\n", r->portname);
262 	printf("\tdrivername:[%s]\n", r->drivername);
263 	printf("\tcomment:[%s]\n", r->comment);
264 	printf("\tlocation:[%s]\n", r->location);
265 	printf("\tsepfile:[%s]\n", r->sepfile);
266 	printf("\tprintprocessor:[%s]\n", r->printprocessor);
267 	printf("\tdatatype:[%s]\n", r->datatype);
268 	printf("\tparameters:[%s]\n", r->parameters);
269 	printf("\tattributes:[0x%x]\n", r->attributes);
270 	printf("\tpriority:[0x%x]\n", r->priority);
271 	printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
272 	printf("\tstarttime:[0x%x]\n", r->starttime);
273 	printf("\tuntiltime:[0x%x]\n", r->untiltime);
274 	printf("\tstatus:[0x%x]\n", r->status);
275 	printf("\tcjobs:[0x%x]\n", r->cjobs);
276 	printf("\taverageppm:[0x%x]\n", r->averageppm);
277 
278 	if (r->secdesc)
279 		display_sec_desc(r->secdesc);
280 
281 	printf("\n");
282 }
283 
284 /****************************************************************************
285 ****************************************************************************/
286 
display_print_info3(struct spoolss_PrinterInfo3 * r)287 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
288 {
289 	display_sec_desc(r->secdesc);
290 
291 	printf("\n");
292 }
293 
294 /****************************************************************************
295 ****************************************************************************/
296 
display_print_info4(struct spoolss_PrinterInfo4 * r)297 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
298 {
299 	printf("\tservername:[%s]\n", r->servername);
300 	printf("\tprintername:[%s]\n", r->printername);
301 	printf("\tattributes:[0x%x]\n", r->attributes);
302 	printf("\n");
303 }
304 
305 /****************************************************************************
306 ****************************************************************************/
307 
display_print_info5(struct spoolss_PrinterInfo5 * r)308 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
309 {
310 	printf("\tprintername:[%s]\n", r->printername);
311 	printf("\tportname:[%s]\n", r->portname);
312 	printf("\tattributes:[0x%x]\n", r->attributes);
313 	printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
314 	printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
315 	printf("\n");
316 }
317 
318 /****************************************************************************
319 ****************************************************************************/
320 
display_print_info6(struct spoolss_PrinterInfo6 * r)321 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
322 {
323 	printf("\tstatus:[0x%x]\n", r->status);
324 	printf("\n");
325 }
326 
327 /****************************************************************************
328 ****************************************************************************/
329 
display_print_info7(struct spoolss_PrinterInfo7 * r)330 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
331 {
332 	printf("\tguid:[%s]\n", r->guid);
333 	printf("\taction:[0x%x]\n", r->action);
334 	printf("\n");
335 }
336 
337 /****************************************************************************
338 ****************************************************************************/
339 
cmd_spoolss_enum_printers(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)340 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
341 					TALLOC_CTX *mem_ctx,
342 					int argc, const char **argv)
343 {
344 	WERROR                  result;
345 	uint32_t		level = 1;
346 	union spoolss_PrinterInfo *info;
347 	uint32_t		i, count;
348 	const char *name;
349 	uint32_t flags = PRINTER_ENUM_LOCAL;
350 
351 	if (argc > 4) {
352 		printf("Usage: %s [level] [name] [flags]\n", argv[0]);
353 		return WERR_OK;
354 	}
355 
356 	if (argc >= 2) {
357 		level = atoi(argv[1]);
358 	}
359 
360 	if (argc >= 3) {
361 		name = argv[2];
362 	} else {
363 		name = cli->srv_name_slash;
364 	}
365 
366 	if (argc == 4) {
367 		flags = atoi(argv[3]);
368 	}
369 
370 	result = rpccli_spoolss_enumprinters(cli, mem_ctx,
371 					     flags,
372 					     name,
373 					     level,
374 					     0,
375 					     &count,
376 					     &info);
377 	if (W_ERROR_IS_OK(result)) {
378 
379 		if (!count) {
380 			printf ("No printers returned.\n");
381 			goto done;
382 		}
383 
384 		for (i = 0; i < count; i++) {
385 			switch (level) {
386 			case 0:
387 				display_print_info0(&info[i].info0);
388 				break;
389 			case 1:
390 				display_print_info1(&info[i].info1);
391 				break;
392 			case 2:
393 				display_print_info2(&info[i].info2);
394 				break;
395 			case 3:
396 				display_print_info3(&info[i].info3);
397 				break;
398 			case 4:
399 				display_print_info4(&info[i].info4);
400 				break;
401 			case 5:
402 				display_print_info5(&info[i].info5);
403 				break;
404 			case 6:
405 				display_print_info6(&info[i].info6);
406 				break;
407 			default:
408 				printf("unknown info level %d\n", level);
409 				goto done;
410 			}
411 		}
412 	}
413  done:
414 
415 	return result;
416 }
417 
418 /****************************************************************************
419 ****************************************************************************/
420 
display_port_info_1(struct spoolss_PortInfo1 * r)421 static void display_port_info_1(struct spoolss_PortInfo1 *r)
422 {
423 	printf("\tPort Name:\t[%s]\n", r->port_name);
424 }
425 
426 /****************************************************************************
427 ****************************************************************************/
428 
display_port_info_2(struct spoolss_PortInfo2 * r)429 static void display_port_info_2(struct spoolss_PortInfo2 *r)
430 {
431 	printf("\tPort Name:\t[%s]\n", r->port_name);
432 	printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
433 	printf("\tDescription:\t[%s]\n", r->description);
434 	printf("\tPort Type:\t" );
435 	if (r->port_type) {
436 		int comma = 0; /* hack */
437 		printf( "[" );
438 		if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
439 			printf( "Read" );
440 			comma = 1;
441 		}
442 		if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
443 			printf( "%sWrite", comma ? ", " : "" );
444 			comma = 1;
445 		}
446 		/* These two have slightly different interpretations
447 		 on 95/98/ME but I'm disregarding that for now */
448 		if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
449 			printf( "%sRedirected", comma ? ", " : "" );
450 			comma = 1;
451 		}
452 		if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
453 			printf( "%sNet-Attached", comma ? ", " : "" );
454 		}
455 		printf( "]\n" );
456 	} else {
457 		printf( "[Unset]\n" );
458 	}
459 	printf("\tReserved:\t[%d]\n", r->reserved);
460 	printf("\n");
461 }
462 
463 /****************************************************************************
464 ****************************************************************************/
465 
cmd_spoolss_enum_ports(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)466 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
467 				       TALLOC_CTX *mem_ctx, int argc,
468 				       const char **argv)
469 {
470 	WERROR         		result;
471 	uint32_t		level = 1;
472 	uint32_t		count;
473 	union spoolss_PortInfo *info;
474 
475 	if (argc > 2) {
476 		printf("Usage: %s [level]\n", argv[0]);
477 		return WERR_OK;
478 	}
479 
480 	if (argc == 2) {
481 		level = atoi(argv[1]);
482 	}
483 
484 	/* Enumerate ports */
485 
486 	result = rpccli_spoolss_enumports(cli, mem_ctx,
487 					  cli->srv_name_slash,
488 					  level,
489 					  0,
490 					  &count,
491 					  &info);
492 	if (W_ERROR_IS_OK(result)) {
493 		int i;
494 
495 		for (i = 0; i < count; i++) {
496 			switch (level) {
497 			case 1:
498 				display_port_info_1(&info[i].info1);
499 				break;
500 			case 2:
501 				display_port_info_2(&info[i].info2);
502 				break;
503 			default:
504 				printf("unknown info level %d\n", level);
505 				break;
506 			}
507 		}
508 	}
509 
510 	return result;
511 }
512 
513 /****************************************************************************
514 ****************************************************************************/
515 
cmd_spoolss_setprinter(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)516 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
517                                        TALLOC_CTX *mem_ctx,
518                                        int argc, const char **argv)
519 {
520 	struct policy_handle pol;
521 	WERROR		result;
522 	NTSTATUS	status;
523 	uint32_t 	info_level = 2;
524 	union spoolss_PrinterInfo info;
525 	struct spoolss_SetPrinterInfoCtr info_ctr;
526 	struct spoolss_SetPrinterInfo2 info2;
527 	const char	*printername, *comment = NULL;
528 	struct spoolss_DevmodeContainer devmode_ctr;
529 	struct sec_desc_buf secdesc_ctr;
530 	struct dcerpc_binding_handle *b = cli->binding_handle;
531 
532 	if (argc == 1 || argc > 3) {
533 		printf("Usage: %s printername comment\n", argv[0]);
534 
535 		return WERR_OK;
536 	}
537 
538 	/* Open a printer handle */
539 	if (argc == 3) {
540 		comment = argv[2];
541 	}
542 
543 	ZERO_STRUCT(devmode_ctr);
544 	ZERO_STRUCT(secdesc_ctr);
545 
546 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
547 
548 	/* get a printer handle */
549 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
550 					       printername,
551 					       PRINTER_ALL_ACCESS,
552 					       &pol);
553 	if (!W_ERROR_IS_OK(result))
554 		goto done;
555 
556 	/* Get printer info */
557 	result = rpccli_spoolss_getprinter(cli, mem_ctx,
558 					   &pol,
559 					   info_level,
560 					   0,
561 					   &info);
562         if (!W_ERROR_IS_OK(result))
563                 goto done;
564 
565 
566 	/* Modify the comment. */
567 	spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
568 	info2.comment = comment;
569 
570 	info_ctr.level = 2;
571 	info_ctr.info.info2 = &info2;
572 
573 	status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
574 					   &pol,
575 					   &info_ctr,
576 					   &devmode_ctr,
577 					   &secdesc_ctr,
578 					   0, /* command */
579 					   &result);
580 	if (!NT_STATUS_IS_OK(status)) {
581 		result = ntstatus_to_werror(status);
582 		goto done;
583 	}
584 	if (W_ERROR_IS_OK(result))
585 		printf("Success in setting comment.\n");
586 
587  done:
588 	if (is_valid_policy_hnd(&pol)) {
589 		WERROR _result;
590 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
591 	}
592 
593 	return result;
594 }
595 
596 /****************************************************************************
597 ****************************************************************************/
598 
cmd_spoolss_setprintername(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)599 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
600                                        TALLOC_CTX *mem_ctx,
601                                        int argc, const char **argv)
602 {
603 	struct policy_handle pol;
604 	WERROR		result;
605 	NTSTATUS	status;
606 	uint32_t 	info_level = 2;
607 	union spoolss_PrinterInfo info;
608 	const char 	*printername,
609 			*new_printername = NULL;
610 	struct spoolss_SetPrinterInfoCtr info_ctr;
611 	struct spoolss_SetPrinterInfo2 info2;
612 	struct spoolss_DevmodeContainer devmode_ctr;
613 	struct sec_desc_buf secdesc_ctr;
614 	struct dcerpc_binding_handle *b = cli->binding_handle;
615 
616 	ZERO_STRUCT(devmode_ctr);
617 	ZERO_STRUCT(secdesc_ctr);
618 
619 	if (argc == 1 || argc > 3) {
620 		printf("Usage: %s printername new_printername\n", argv[0]);
621 
622 		return WERR_OK;
623 	}
624 
625 	/* Open a printer handle */
626 	if (argc == 3) {
627 		new_printername = argv[2];
628 	}
629 
630 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
631 
632 	/* get a printer handle */
633 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
634 					       printername,
635 					       PRINTER_ALL_ACCESS,
636 					       &pol);
637 	if (!W_ERROR_IS_OK(result))
638 		goto done;
639 
640 	/* Get printer info */
641 	result = rpccli_spoolss_getprinter(cli, mem_ctx,
642 					   &pol,
643 					   info_level,
644 					   0,
645 					   &info);
646         if (!W_ERROR_IS_OK(result))
647                 goto done;
648 
649 	/* Modify the printername. */
650 	spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
651 	info2.printername = new_printername;
652 
653 	info_ctr.level = 2;
654 	info_ctr.info.info2 = &info2;
655 
656 	status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
657 					   &pol,
658 					   &info_ctr,
659 					   &devmode_ctr,
660 					   &secdesc_ctr,
661 					   0, /* command */
662 					   &result);
663 	if (!NT_STATUS_IS_OK(status)) {
664 		result = ntstatus_to_werror(status);
665 		goto done;
666 	}
667 	if (W_ERROR_IS_OK(result))
668 		printf("Success in setting printername.\n");
669 
670  done:
671 	if (is_valid_policy_hnd(&pol)) {
672 		WERROR _result;
673 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
674 	}
675 
676 	return result;
677 }
678 
679 /****************************************************************************
680 ****************************************************************************/
681 
cmd_spoolss_getprinter(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)682 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
683                                        TALLOC_CTX *mem_ctx,
684                                        int argc, const char **argv)
685 {
686 	struct policy_handle pol;
687 	WERROR          result;
688 	uint32_t 	level = 1;
689 	const char	*printername;
690 	union spoolss_PrinterInfo info;
691 	struct dcerpc_binding_handle *b = cli->binding_handle;
692 
693 	if (argc == 1 || argc > 3) {
694 		printf("Usage: %s <printername> [level]\n", argv[0]);
695 		return WERR_OK;
696 	}
697 
698 	/* Open a printer handle */
699 	if (argc == 3) {
700 		level = atoi(argv[2]);
701 	}
702 
703 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
704 
705 	/* get a printer handle */
706 
707 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
708 					       printername,
709 					       SEC_FLAG_MAXIMUM_ALLOWED,
710 					       &pol);
711 	if (!W_ERROR_IS_OK(result)) {
712 		goto done;
713 	}
714 
715 	/* Get printer info */
716 
717 	result = rpccli_spoolss_getprinter(cli, mem_ctx,
718 					   &pol,
719 					   level,
720 					   0,
721 					   &info);
722 	if (!W_ERROR_IS_OK(result)) {
723 		goto done;
724 	}
725 
726 	/* Display printer info */
727 	switch (level) {
728 	case 0:
729 		display_print_info0(&info.info0);
730 		break;
731 	case 1:
732 		display_print_info1(&info.info1);
733 		break;
734 	case 2:
735 		display_print_info2(&info.info2);
736 		break;
737 	case 3:
738 		display_print_info3(&info.info3);
739 		break;
740 	case 4:
741 		display_print_info4(&info.info4);
742 		break;
743 	case 5:
744 		display_print_info5(&info.info5);
745 		break;
746 	case 6:
747 		display_print_info6(&info.info6);
748 		break;
749 	case 7:
750 		display_print_info7(&info.info7);
751 		break;
752 	default:
753 		printf("unknown info level %d\n", level);
754 		break;
755 	}
756  done:
757 	if (is_valid_policy_hnd(&pol)) {
758 		WERROR _result;
759 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
760 	}
761 
762 	return result;
763 }
764 
765 /****************************************************************************
766 ****************************************************************************/
767 
display_reg_value(const char * name,enum winreg_Type type,DATA_BLOB blob)768 static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
769 {
770 	const char *text = NULL;
771 
772 	switch(type) {
773 	case REG_DWORD:
774 		if (blob.length >= sizeof(uint32_t)) {
775 			printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
776 		} else {
777 			printf("%s: REG_DWORD: <invalid>\n", name);
778 		}
779 		break;
780 	case REG_SZ:
781 		pull_reg_sz(talloc_tos(), &blob, &text);
782 		printf("%s: REG_SZ: %s\n", name, text ? text : "");
783 		break;
784 	case REG_BINARY: {
785 		char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
786 		size_t i, len;
787 		printf("%s: REG_BINARY:", name);
788 		len = strlen(hex);
789 		for (i=0; i<len; i++) {
790 			if (hex[i] == '\0') {
791 				break;
792 			}
793 			if (i%40 == 0) {
794 				putchar('\n');
795 			}
796 			putchar(hex[i]);
797 		}
798 		TALLOC_FREE(hex);
799 		putchar('\n');
800 		break;
801 	}
802 	case REG_MULTI_SZ: {
803 		uint32_t i;
804 		const char **values;
805 
806 		if (!pull_reg_multi_sz(NULL, &blob, &values)) {
807 			d_printf("pull_reg_multi_sz failed\n");
808 			break;
809 		}
810 
811 		printf("%s: REG_MULTI_SZ: \n", name);
812 		for (i=0; values[i] != NULL; i++) {
813 			d_printf("%s\n", values[i]);
814 		}
815 		TALLOC_FREE(values);
816 		break;
817 	}
818 	default:
819 		printf("%s: unknown type %d\n", name, type);
820 	}
821 
822 }
823 
824 /****************************************************************************
825 ****************************************************************************/
826 
display_printer_data(const char * v,enum winreg_Type type,uint8_t * data,uint32_t length)827 static void display_printer_data(const char *v,
828 				 enum winreg_Type type,
829 				 uint8_t *data,
830 				 uint32_t length)
831 {
832 	int i;
833 	union spoolss_PrinterData r;
834 	DATA_BLOB blob = data_blob_const(data, length);
835 	WERROR result;
836 	enum ndr_err_code ndr_err;
837 
838 	result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
839 	if (!W_ERROR_IS_OK(result)) {
840 		return;
841 	}
842 
843 	switch (type) {
844 	case REG_DWORD:
845 		printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
846 		break;
847 	case REG_SZ:
848 		printf("%s: REG_SZ: %s\n", v, r.string);
849 		break;
850 	case REG_BINARY: {
851 		char *hex = hex_encode_talloc(NULL,
852 			r.binary.data, r.binary.length);
853 		size_t len;
854 		printf("%s: REG_BINARY:", v);
855 		len = strlen(hex);
856 		for (i=0; i<len; i++) {
857 			if (hex[i] == '\0') {
858 				break;
859 			}
860 			if (i%40 == 0) {
861 				putchar('\n');
862 			}
863 			putchar(hex[i]);
864 		}
865 		TALLOC_FREE(hex);
866 		putchar('\n');
867 		putchar('\n');
868 
869 		if (strequal(v, "OsVersion")) {
870 			struct spoolss_OSVersion os;
871 			ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
872 				(ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion);
873 			if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
874 				// add output here;
875 				printf("OsMajor: %u\n", os.major);
876 				printf("OsMinor: %u\n", os.minor);
877 				printf("OsBuild: %u\n", os.build);
878 				NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
879 			}
880 		}
881 		if (strequal(v, "OsVersionEx")) {
882 			struct spoolss_OSVersionEx os;
883 			ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
884 				(ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersionEx);
885 			if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
886 				printf("OsMajor: %u\n", os.major);
887 				printf("OsMinor: %u\n", os.minor);
888 				printf("OsBuild: %u\n", os.build);
889 				printf("ServicePackMajor: %u\n", os.service_pack_major);
890 				printf("ServicePackMinor: %u\n", os.service_pack_minor);
891 				NDR_PRINT_DEBUG(spoolss_OSVersionEx, &os);
892 			}
893 		}
894 		break;
895 	}
896 	case REG_MULTI_SZ:
897 		printf("%s: REG_MULTI_SZ: ", v);
898 		for (i=0; r.string_array[i] != NULL; i++) {
899 			printf("%s ", r.string_array[i]);
900 		}
901 		printf("\n");
902 		break;
903 	default:
904 		printf("%s: unknown type 0x%02x:\n", v, type);
905 		break;
906 	}
907 }
908 
909 /****************************************************************************
910 ****************************************************************************/
911 
cmd_spoolss_getprinterdata(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)912 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
913 					   TALLOC_CTX *mem_ctx,
914 					   int argc, const char **argv)
915 {
916 	struct policy_handle pol;
917 	WERROR          result;
918 	fstring 	printername;
919 	const char *valuename;
920 	enum winreg_Type type;
921 	uint8_t *data;
922 	uint32_t needed;
923 	struct dcerpc_binding_handle *b = cli->binding_handle;
924 
925 	if (argc != 3) {
926 		printf("Usage: %s <printername> <valuename>\n", argv[0]);
927 		printf("<printername> of . queries print server\n");
928 		return WERR_OK;
929 	}
930 	valuename = argv[2];
931 
932 	/* Open a printer handle */
933 
934 	if (strncmp(argv[1], ".", sizeof(".")) == 0)
935 		fstrcpy(printername, cli->srv_name_slash);
936 	else
937 		slprintf(printername, sizeof(printername)-1, "%s\\%s",
938 			  cli->srv_name_slash, argv[1]);
939 
940 	/* get a printer handle */
941 
942 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
943 					       printername,
944 					       SEC_FLAG_MAXIMUM_ALLOWED,
945 					       &pol);
946 	if (!W_ERROR_IS_OK(result))
947 		goto done;
948 
949 	/* Get printer info */
950 
951 	result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
952 					       &pol,
953 					       valuename,
954 					       0,
955 					       &type,
956 					       &needed,
957 					       &data);
958 	if (!W_ERROR_IS_OK(result))
959 		goto done;
960 
961 	/* Display printer data */
962 
963 	display_printer_data(valuename, type, data, needed);
964 
965  done:
966 	if (is_valid_policy_hnd(&pol)) {
967 		WERROR _result;
968 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
969 	}
970 
971 	return result;
972 }
973 
974 /****************************************************************************
975 ****************************************************************************/
976 
cmd_spoolss_getprinterdataex(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)977 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
978 					     TALLOC_CTX *mem_ctx,
979 					     int argc, const char **argv)
980 {
981 	struct policy_handle pol;
982 	WERROR          result;
983 	NTSTATUS	status;
984 	fstring 	printername;
985 	const char *valuename, *keyname;
986 
987 	enum winreg_Type type;
988 	uint8_t *data = NULL;
989 	uint32_t offered = 0;
990 	uint32_t needed;
991 	struct dcerpc_binding_handle *b = cli->binding_handle;
992 
993 	if (argc != 4) {
994 		printf("Usage: %s <printername> <keyname> <valuename>\n",
995 		       argv[0]);
996 		printf("<printername> of . queries print server\n");
997 		return WERR_OK;
998 	}
999 	valuename = argv[3];
1000 	keyname = argv[2];
1001 
1002 	/* Open a printer handle */
1003 
1004 	if (strncmp(argv[1], ".", sizeof(".")) == 0)
1005 		fstrcpy(printername, cli->srv_name_slash);
1006 	else
1007 		slprintf(printername, sizeof(printername)-1, "%s\\%s",
1008 			  cli->srv_name_slash, argv[1]);
1009 
1010 	/* get a printer handle */
1011 
1012 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1013 					       printername,
1014 					       SEC_FLAG_MAXIMUM_ALLOWED,
1015 					       &pol);
1016 	if (!W_ERROR_IS_OK(result))
1017 		goto done;
1018 
1019 	/* Get printer info */
1020 
1021 	data = talloc_zero_array(mem_ctx, uint8_t, offered);
1022 	if (!data) {
1023 		goto done;
1024 	}
1025 
1026 	status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1027 						 &pol,
1028 						 keyname,
1029 						 valuename,
1030 						 &type,
1031 						 data,
1032 						 offered,
1033 						 &needed,
1034 						 &result);
1035 	if (!NT_STATUS_IS_OK(status)) {
1036 		result = ntstatus_to_werror(status);
1037 		goto done;
1038 	}
1039 	if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1040 		offered = needed;
1041 		data = talloc_zero_array(mem_ctx, uint8_t, offered);
1042 		if (!data) {
1043 			goto done;
1044 		}
1045 		status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1046 							 &pol,
1047 							 keyname,
1048 							 valuename,
1049 							 &type,
1050 							 data,
1051 							 offered,
1052 							 &needed,
1053 							 &result);
1054 	}
1055 
1056 	if (!NT_STATUS_IS_OK(status)) {
1057 		result = ntstatus_to_werror(status);
1058 		goto done;
1059 	}
1060 
1061 	if (!W_ERROR_IS_OK(result))
1062 		goto done;
1063 
1064 	/* Display printer data */
1065 
1066 	display_printer_data(valuename, type, data, needed);
1067 
1068 
1069  done:
1070 	if (is_valid_policy_hnd(&pol)) {
1071 		WERROR _result;
1072 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1073 	}
1074 
1075 	return result;
1076 }
1077 
1078 /****************************************************************************
1079 ****************************************************************************/
1080 
display_print_driver1(struct spoolss_DriverInfo1 * r)1081 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1082 {
1083 	if (!r) {
1084 		return;
1085 	}
1086 
1087 	printf("Printer Driver Info 1:\n");
1088 	printf("\tDriver Name: [%s]\n", r->driver_name);
1089 	printf("\n");
1090 }
1091 
1092 /****************************************************************************
1093 ****************************************************************************/
1094 
display_print_driver2(struct spoolss_DriverInfo2 * r)1095 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1096 {
1097 	if (!r) {
1098 		return;
1099 	}
1100 
1101 	printf("Printer Driver Info 2:\n");
1102 	printf("\tVersion: [%x]\n", r->version);
1103 	printf("\tDriver Name: [%s]\n", r->driver_name);
1104 	printf("\tArchitecture: [%s]\n", r->architecture);
1105 	printf("\tDriver Path: [%s]\n", r->driver_path);
1106 	printf("\tDatafile: [%s]\n", r->data_file);
1107 	printf("\tConfigfile: [%s]\n", r->config_file);
1108 	printf("\n");
1109 }
1110 
1111 /****************************************************************************
1112 ****************************************************************************/
1113 
display_print_driver3(struct spoolss_DriverInfo3 * r)1114 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1115 {
1116 	int i;
1117 
1118 	if (!r) {
1119 		return;
1120 	}
1121 
1122 	printf("Printer Driver Info 3:\n");
1123 	printf("\tVersion: [%x]\n", r->version);
1124 	printf("\tDriver Name: [%s]\n", r->driver_name);
1125 	printf("\tArchitecture: [%s]\n", r->architecture);
1126 	printf("\tDriver Path: [%s]\n", r->driver_path);
1127 	printf("\tDatafile: [%s]\n", r->data_file);
1128 	printf("\tConfigfile: [%s]\n", r->config_file);
1129 	printf("\tHelpfile: [%s]\n", r->help_file);
1130 
1131 	for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1132 		printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1133 	}
1134 
1135 	printf("\tMonitorname: [%s]\n", r->monitor_name);
1136 	printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1137 	printf("\n");
1138 }
1139 
1140 /****************************************************************************
1141 ****************************************************************************/
1142 
display_print_driver4(struct spoolss_DriverInfo4 * r)1143 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1144 {
1145 	int i;
1146 
1147 	if (!r) {
1148 		return;
1149 	}
1150 
1151 	printf("Printer Driver Info 4:\n");
1152 	printf("\tVersion: [%x]\n", r->version);
1153 	printf("\tDriver Name: [%s]\n", r->driver_name);
1154 	printf("\tArchitecture: [%s]\n", r->architecture);
1155 	printf("\tDriver Path: [%s]\n", r->driver_path);
1156 	printf("\tDatafile: [%s]\n", r->data_file);
1157 	printf("\tConfigfile: [%s]\n", r->config_file);
1158 	printf("\tHelpfile: [%s]\n", r->help_file);
1159 
1160 	for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1161 		printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1162 	}
1163 
1164 	printf("\tMonitorname: [%s]\n", r->monitor_name);
1165 	printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1166 
1167 	for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1168 		printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1169 	}
1170 	printf("\n");
1171 }
1172 
1173 /****************************************************************************
1174 ****************************************************************************/
1175 
display_print_driver5(struct spoolss_DriverInfo5 * r)1176 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1177 {
1178 	if (!r) {
1179 		return;
1180 	}
1181 
1182 	printf("Printer Driver Info 5:\n");
1183 	printf("\tVersion: [%x]\n", r->version);
1184 	printf("\tDriver Name: [%s]\n", r->driver_name);
1185 	printf("\tArchitecture: [%s]\n", r->architecture);
1186 	printf("\tDriver Path: [%s]\n", r->driver_path);
1187 	printf("\tDatafile: [%s]\n", r->data_file);
1188 	printf("\tConfigfile: [%s]\n", r->config_file);
1189 	printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1190 	printf("\tConfig Version: [0x%x]\n", r->config_version);
1191 	printf("\tDriver Version: [0x%x]\n", r->driver_version);
1192 	printf("\n");
1193 }
1194 
1195 /****************************************************************************
1196 ****************************************************************************/
1197 
display_print_driver6(struct spoolss_DriverInfo6 * r)1198 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1199 {
1200 	int i;
1201 
1202 	if (!r) {
1203 		return;
1204 	}
1205 
1206 	printf("Printer Driver Info 6:\n");
1207 	printf("\tVersion: [%x]\n", r->version);
1208 	printf("\tDriver Name: [%s]\n", r->driver_name);
1209 	printf("\tArchitecture: [%s]\n", r->architecture);
1210 	printf("\tDriver Path: [%s]\n", r->driver_path);
1211 	printf("\tDatafile: [%s]\n", r->data_file);
1212 	printf("\tConfigfile: [%s]\n", r->config_file);
1213 	printf("\tHelpfile: [%s]\n", r->help_file);
1214 
1215 	for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1216 		printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1217 	}
1218 
1219 	printf("\tMonitorname: [%s]\n", r->monitor_name);
1220 	printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1221 
1222 	for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1223 		printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1224 	}
1225 
1226 	printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1227 	printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1228 	printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1229 	printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1230 	printf("\tHardware ID: [%s]\n", r->hardware_id);
1231 	printf("\tProvider: [%s]\n", r->provider);
1232 
1233 	printf("\n");
1234 }
1235 
1236 /****************************************************************************
1237 ****************************************************************************/
1238 
display_print_driver8(struct spoolss_DriverInfo8 * r)1239 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1240 {
1241 	int i;
1242 
1243 	if (!r) {
1244 		return;
1245 	}
1246 
1247 	printf("Printer Driver Info 8:\n");
1248 	printf("\tVersion: [%x]\n", r->version);
1249 	printf("\tDriver Name: [%s]\n", r->driver_name);
1250 	printf("\tArchitecture: [%s]\n", r->architecture);
1251 	printf("\tDriver Path: [%s]\n", r->driver_path);
1252 	printf("\tDatafile: [%s]\n", r->data_file);
1253 	printf("\tConfigfile: [%s]\n", r->config_file);
1254 	printf("\tHelpfile: [%s]\n", r->help_file);
1255 	printf("\tMonitorname: [%s]\n", r->monitor_name);
1256 	printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1257 
1258 	for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1259 		printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1260 	}
1261 
1262 	for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1263 		printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1264 	}
1265 
1266 	printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1267 	printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1268 	printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1269 	printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1270 	printf("\tHardware ID: [%s]\n", r->hardware_id);
1271 	printf("\tProvider: [%s]\n", r->provider);
1272 	printf("\tPrint Processor: [%s]\n", r->print_processor);
1273 	printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1274 	for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1275 		printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1276 	}
1277 	printf("\tInf Path: [%s]\n", r->inf_path);
1278 	printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1279 	for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1280 		printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1281 	}
1282 	printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1283 	printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1284 		(long long unsigned int)r->min_inbox_driver_ver_version);
1285 
1286 	printf("\n");
1287 }
1288 
1289 /****************************************************************************
1290 ****************************************************************************/
1291 
cmd_spoolss_getdriver(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1292 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1293 				    TALLOC_CTX *mem_ctx,
1294 				    int argc, const char **argv)
1295 {
1296 	struct policy_handle pol;
1297 	WERROR          werror;
1298 	uint32_t	level = 3;
1299 	const char	*printername;
1300 	uint32_t	i;
1301 	bool		success = false;
1302 	union spoolss_DriverInfo info;
1303 	uint32_t server_major_version;
1304 	uint32_t server_minor_version;
1305 	struct dcerpc_binding_handle *b = cli->binding_handle;
1306 
1307 	if ((argc == 1) || (argc > 3)) {
1308 		printf("Usage: %s <printername> [level]\n", argv[0]);
1309 		return WERR_OK;
1310 	}
1311 
1312 	/* get the arguments need to open the printer handle */
1313 
1314 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1315 
1316 	if (argc == 3) {
1317 		level = atoi(argv[2]);
1318 	}
1319 
1320 	/* Open a printer handle */
1321 
1322 	werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1323 					       printername,
1324 					       PRINTER_ACCESS_USE,
1325 					       &pol);
1326 	if (!W_ERROR_IS_OK(werror)) {
1327 		printf("Error opening printer handle for %s!\n", printername);
1328 		return werror;
1329 	}
1330 
1331 	/* loop through and print driver info level for each architecture */
1332 
1333 	for (i=0; archi_table[i].long_archi!=NULL; i++) {
1334 
1335 		werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1336 							  &pol,
1337 							  archi_table[i].long_archi,
1338 							  level,
1339 							  0, /* offered */
1340 							  archi_table[i].version,
1341 							  2,
1342 							  &info,
1343 							  &server_major_version,
1344 							  &server_minor_version);
1345 		if (!W_ERROR_IS_OK(werror)) {
1346 			continue;
1347 		}
1348 
1349 		/* need at least one success */
1350 
1351 		success = true;
1352 
1353 		printf("\n[%s]\n", archi_table[i].long_archi);
1354 
1355 		switch (level) {
1356 		case 1:
1357 			display_print_driver1(&info.info1);
1358 			break;
1359 		case 2:
1360 			display_print_driver2(&info.info2);
1361 			break;
1362 		case 3:
1363 			display_print_driver3(&info.info3);
1364 			break;
1365 		case 4:
1366 			display_print_driver4(&info.info4);
1367 			break;
1368 		case 5:
1369 			display_print_driver5(&info.info5);
1370 			break;
1371 		case 6:
1372 			display_print_driver6(&info.info6);
1373 			break;
1374 		case 8:
1375 			display_print_driver8(&info.info8);
1376 			break;
1377 		default:
1378 			printf("unknown info level %d\n", level);
1379 			break;
1380 		}
1381 	}
1382 
1383 	/* Cleanup */
1384 
1385 	if (is_valid_policy_hnd(&pol)) {
1386 		WERROR _result;
1387 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1388 	}
1389 
1390 	if (success) {
1391 		werror = WERR_OK;
1392 	}
1393 
1394 	return werror;
1395 }
1396 
1397 /****************************************************************************
1398 ****************************************************************************/
1399 
enum_driver_by_architecture(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,const char * architecture,uint32_t level)1400 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1401 					  TALLOC_CTX *mem_ctx,
1402 					  const char *architecture,
1403 					  uint32_t level)
1404 {
1405 	WERROR werror;
1406 	uint32_t count = 0;
1407 	union spoolss_DriverInfo *info = NULL;
1408 	uint32_t j;
1409 
1410 	werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1411 						   cli->srv_name_slash,
1412 						   architecture,
1413 						   level,
1414 						   0,
1415 						   &count,
1416 						   &info);
1417 
1418 	if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1419 		printf("Server does not support environment [%s]\n",
1420 			architecture);
1421 		return WERR_OK;
1422 	}
1423 
1424 	if (count == 0) {
1425 		return WERR_OK;
1426 	}
1427 
1428 	if (!W_ERROR_IS_OK(werror)) {
1429 		printf("Error getting driver for environment [%s] - %s\n",
1430 			architecture, win_errstr(werror));
1431 		return werror;
1432 	}
1433 
1434 	printf("\n[%s]\n", architecture);
1435 
1436 	switch (level) {
1437 	case 1:
1438 		for (j=0; j < count; j++) {
1439 			display_print_driver1(&info[j].info1);
1440 		}
1441 		break;
1442 	case 2:
1443 		for (j=0; j < count; j++) {
1444 			display_print_driver2(&info[j].info2);
1445 		}
1446 		break;
1447 	case 3:
1448 		for (j=0; j < count; j++) {
1449 			display_print_driver3(&info[j].info3);
1450 		}
1451 		break;
1452 	case 4:
1453 		for (j=0; j < count; j++) {
1454 			display_print_driver4(&info[j].info4);
1455 		}
1456 		break;
1457 	case 5:
1458 		for (j=0; j < count; j++) {
1459 			display_print_driver5(&info[j].info5);
1460 		}
1461 		break;
1462 	case 6:
1463 		for (j=0; j < count; j++) {
1464 			display_print_driver6(&info[j].info6);
1465 		}
1466 		break;
1467 	case 8:
1468 		for (j=0; j < count; j++) {
1469 			display_print_driver8(&info[j].info8);
1470 		}
1471 		break;
1472 	default:
1473 		printf("unknown info level %d\n", level);
1474 		return WERR_INVALID_LEVEL;
1475 	}
1476 
1477 	return werror;
1478 }
1479 
cmd_spoolss_enum_drivers(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1480 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1481                                          TALLOC_CTX *mem_ctx,
1482                                          int argc, const char **argv)
1483 {
1484 	WERROR werror = WERR_OK;
1485 	uint32_t        level = 1;
1486 	uint32_t	i;
1487 	const char *architecture = NULL;
1488 
1489 	if (argc > 3) {
1490 		printf("Usage: enumdrivers [level] [architecture]\n");
1491 		return WERR_OK;
1492 	}
1493 
1494 	if (argc >= 2) {
1495 		level = atoi(argv[1]);
1496 	}
1497 
1498 	if (argc == 3) {
1499 		architecture = argv[2];
1500 	}
1501 
1502 	if (architecture) {
1503 		return enum_driver_by_architecture(cli, mem_ctx,
1504 						   architecture,
1505 						   level);
1506 	}
1507 
1508 	/* loop through and print driver info level for each architecture */
1509 	for (i=0; archi_table[i].long_archi!=NULL; i++) {
1510 		/* check to see if we already asked for this architecture string */
1511 
1512 		if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1513 			continue;
1514 		}
1515 
1516 		werror = enum_driver_by_architecture(cli, mem_ctx,
1517 						     archi_table[i].long_archi,
1518 						     level);
1519 		if (!W_ERROR_IS_OK(werror)) {
1520 			break;
1521 		}
1522 	}
1523 
1524 	return werror;
1525 }
1526 
1527 /****************************************************************************
1528 ****************************************************************************/
1529 
display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 * r)1530 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1531 {
1532 	printf("\tDirectory Name:[%s]\n", r->directory_name);
1533 }
1534 
1535 /****************************************************************************
1536 ****************************************************************************/
1537 
cmd_spoolss_getdriverdir(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1538 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1539                                          TALLOC_CTX *mem_ctx,
1540                                          int argc, const char **argv)
1541 {
1542 	WERROR result;
1543 	NTSTATUS status;
1544 	const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1545 	DATA_BLOB buffer;
1546 	uint32_t offered;
1547 	union spoolss_DriverDirectoryInfo info;
1548 	uint32_t needed;
1549 	struct dcerpc_binding_handle *b = cli->binding_handle;
1550 
1551 	if (argc > 2) {
1552 		printf("Usage: %s [environment]\n", argv[0]);
1553 		return WERR_OK;
1554 	}
1555 
1556 	/* Get the arguments need to open the printer handle */
1557 
1558 	if (argc == 2) {
1559 		env = argv[1];
1560 	}
1561 
1562 	/* Get the directory.  Only use Info level 1 */
1563 
1564 	status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1565 							  cli->srv_name_slash,
1566 							  env,
1567 							  1,
1568 							  NULL, /* buffer */
1569 							  0, /* offered */
1570 							  NULL, /* info */
1571 							  &needed,
1572 							  &result);
1573 	if (!NT_STATUS_IS_OK(status)) {
1574 		return ntstatus_to_werror(status);
1575 	}
1576 	if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1577 		offered = needed;
1578 		buffer = data_blob_talloc_zero(mem_ctx, needed);
1579 
1580 		status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1581 								  cli->srv_name_slash,
1582 								  env,
1583 								  1,
1584 								  &buffer,
1585 								  offered,
1586 								  &info,
1587 								  &needed,
1588 								  &result);
1589 		if (!NT_STATUS_IS_OK(status)) {
1590 			return ntstatus_to_werror(status);
1591 		}
1592 	}
1593 
1594 	if (W_ERROR_IS_OK(result)) {
1595 		display_printdriverdir_1(&info.info1);
1596 	}
1597 
1598 	return result;
1599 }
1600 
1601 /****************************************************************************
1602 ****************************************************************************/
1603 
cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1604 static WERROR cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client *cli,
1605 					       TALLOC_CTX *mem_ctx,
1606 					       int argc, const char **argv)
1607 {
1608 	HRESULT hresult;
1609 	NTSTATUS status;
1610 	const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1611 	uint32_t offered;
1612 	uint32_t needed;
1613 	struct dcerpc_binding_handle *b = cli->binding_handle;
1614 	const char *package_id = "";
1615 	const char *cab = NULL;
1616 
1617 	if (argc > 4) {
1618 		printf("Usage: %s [environment] [package_id]\n", argv[0]);
1619 		return WERR_OK;
1620 	}
1621 
1622 	/* Get the arguments need to open the printer handle */
1623 
1624 	if (argc >= 2) {
1625 		env = argv[1];
1626 	}
1627 
1628 	if (argc == 3) {
1629 		package_id = argv[2];
1630 	}
1631 
1632 	offered = 1;
1633 	cab = talloc_zero_array(mem_ctx, char, offered);
1634 	if (cab == NULL) {
1635 		return WERR_NOT_ENOUGH_MEMORY;
1636 	}
1637 	status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1638 							    cli->srv_name_slash,
1639 							    env,
1640 							    NULL,
1641 							    package_id,
1642 							    cab,
1643 							    offered,
1644 							    &needed,
1645 							    &hresult);
1646 	if (!NT_STATUS_IS_OK(status)) {
1647 		return ntstatus_to_werror(status);
1648 	}
1649 
1650 	if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult)), WERR_INSUFFICIENT_BUFFER)) {
1651 		offered = needed;
1652 		cab = talloc_zero_array(mem_ctx, char, offered);
1653 		if (cab == NULL) {
1654 			return WERR_NOT_ENOUGH_MEMORY;
1655 		}
1656 		status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1657 								    cli->srv_name_slash,
1658 								    env,
1659 								    NULL,
1660 								    package_id,
1661 								    cab,
1662 								    offered,
1663 								    &needed,
1664 								    &hresult);
1665 		if (!NT_STATUS_IS_OK(status)) {
1666 			return ntstatus_to_werror(status);
1667 		}
1668 	}
1669 
1670 	return W_ERROR(WIN32_FROM_HRESULT(hresult));
1671 }
1672 
1673 
1674 /****************************************************************************
1675 ****************************************************************************/
1676 
set_drv_info_3_env(TALLOC_CTX * mem_ctx,struct spoolss_AddDriverInfo3 * info,const char * arch)1677 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1678 			       struct spoolss_AddDriverInfo3 *info,
1679 			       const char *arch)
1680 {
1681 
1682 	int i;
1683 
1684 	for (i=0; archi_table[i].long_archi != NULL; i++)
1685 	{
1686 		if (strcmp(arch, archi_table[i].short_archi) == 0)
1687 		{
1688 			info->version = archi_table[i].version;
1689 			info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1690 			break;
1691 		}
1692 	}
1693 
1694 	if (archi_table[i].long_archi == NULL)
1695 	{
1696 		DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1697 	}
1698 
1699 	return;
1700 }
1701 
1702 
1703 /**************************************************************************
1704  wrapper for strtok to get the next parameter from a delimited list.
1705  Needed to handle the empty parameter string denoted by "NULL"
1706  *************************************************************************/
1707 
get_driver_3_param(TALLOC_CTX * mem_ctx,char * str,const char * delim,const char ** dest,char ** saveptr)1708 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1709 				const char *delim, const char **dest,
1710 				char **saveptr)
1711 {
1712 	char	*ptr;
1713 
1714 	/* get the next token */
1715 	ptr = strtok_r(str, delim, saveptr);
1716 
1717 	/* a string of 'NULL' is used to represent an empty
1718 	   parameter because two consecutive delimiters
1719 	   will not return an empty string.  See man strtok(3)
1720 	   for details */
1721 	if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1722 		ptr = NULL;
1723 	}
1724 
1725 	if (dest != NULL) {
1726 		*dest = talloc_strdup(mem_ctx, ptr);
1727 	}
1728 
1729 	return ptr;
1730 }
1731 
1732 /********************************************************************************
1733  fill in the members of a spoolss_AddDriverInfo3 struct using a character
1734  string in the form of
1735 	 <Long Driver Name>:<Driver File Name>:<Data File Name>:\
1736 	     <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1737 	     <Default Data Type>:<Comma Separated list of Files>
1738  *******************************************************************************/
1739 
init_drv_info_3_members(TALLOC_CTX * mem_ctx,struct spoolss_AddDriverInfo3 * r,char * args)1740 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1741                                     char *args)
1742 {
1743 	char	*str, *str2;
1744 	size_t count = 0;
1745 	char *saveptr = NULL;
1746 	struct spoolss_StringArray *deps;
1747 	const char **file_array = NULL;
1748 	int i;
1749 
1750 	/* fill in the UNISTR fields */
1751 	str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1752 	str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1753 	str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1754 	str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1755 	str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1756 	str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1757 	str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1758 
1759 	/* <Comma Separated List of Dependent Files> */
1760 	/* save the beginning of the string */
1761 	str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1762 	str = str2;
1763 
1764 	/* begin to strip out each filename */
1765 	str = strtok_r(str, ",", &saveptr);
1766 
1767 	/* no dependent files, we are done */
1768 	if (!str) {
1769 		return true;
1770 	}
1771 
1772 	deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1773 	if (!deps) {
1774 		return false;
1775 	}
1776 
1777 	while (str != NULL) {
1778 		bool ok;
1779 		ok = add_string_to_array(deps, str, &file_array, &count);
1780 		if (!ok) {
1781 			return false;
1782 		}
1783 		str = strtok_r(NULL, ",", &saveptr);
1784 	}
1785 
1786 	deps->string = talloc_zero_array(deps, const char *, count + 1);
1787 	if (!deps->string) {
1788 		return false;
1789 	}
1790 
1791 	for (i=0; i < count; i++) {
1792 		deps->string[i] = file_array[i];
1793 	}
1794 
1795 	r->dependent_files = deps;
1796 
1797 	return true;
1798 }
1799 
1800 /****************************************************************************
1801 ****************************************************************************/
1802 
cmd_spoolss_addprinterdriver(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1803 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1804                                              TALLOC_CTX *mem_ctx,
1805                                              int argc, const char **argv)
1806 {
1807 	WERROR result;
1808 	NTSTATUS status;
1809 	uint32_t                  level = 3;
1810 	struct spoolss_AddDriverInfoCtr info_ctr;
1811 	struct spoolss_AddDriverInfo3 info3;
1812 	const char		*arch;
1813 	char 			*driver_args;
1814 	struct dcerpc_binding_handle *b = cli->binding_handle;
1815 
1816 	/* parse the command arguments */
1817 	if (argc != 3 && argc != 4)
1818 	{
1819 		printf ("Usage: %s <Environment> \\\n", argv[0]);
1820 		printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1821     		printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1822 	    	printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1823 		printf ("\t[version]\n");
1824 
1825             return WERR_OK;
1826         }
1827 
1828 	/* Fill in the spoolss_AddDriverInfo3 struct */
1829 	ZERO_STRUCT(info3);
1830 
1831 	arch = cmd_spoolss_get_short_archi(argv[1]);
1832 	if (!arch) {
1833 		printf ("Error Unknown architecture [%s]\n", argv[1]);
1834 		return WERR_INVALID_PARAMETER;
1835 	}
1836 
1837 	set_drv_info_3_env(mem_ctx, &info3, arch);
1838 
1839 	driver_args = talloc_strdup( mem_ctx, argv[2] );
1840 	if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1841 	{
1842 		printf ("Error Invalid parameter list - %s.\n", argv[2]);
1843 		return WERR_INVALID_PARAMETER;
1844 	}
1845 
1846 	/* if printer driver version specified, override the default version
1847 	 * used by the architecture.  This allows installation of Windows
1848 	 * 2000 (version 3) printer drivers. */
1849 	if (argc == 4)
1850 	{
1851 		info3.version = atoi(argv[3]);
1852 	}
1853 
1854 
1855 	info_ctr.level		= level;
1856 	info_ctr.info.info3	= &info3;
1857 
1858 	status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1859 						 cli->srv_name_slash,
1860 						 &info_ctr,
1861 						 &result);
1862 	if (!NT_STATUS_IS_OK(status)) {
1863 		return ntstatus_to_werror(status);
1864 	}
1865 	if (W_ERROR_IS_OK(result)) {
1866 		printf ("Printer Driver %s successfully installed.\n",
1867 			info3.driver_name);
1868 	}
1869 
1870 	return result;
1871 }
1872 
1873 
1874 /****************************************************************************
1875 ****************************************************************************/
1876 
cmd_spoolss_addprinterex(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1877 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1878                                          TALLOC_CTX *mem_ctx,
1879                                          int argc, const char **argv)
1880 {
1881 	WERROR result;
1882 	struct spoolss_SetPrinterInfoCtr info_ctr;
1883 	struct spoolss_SetPrinterInfo2 info2;
1884 
1885 	/* parse the command arguments */
1886 	if (argc != 5)
1887 	{
1888 		printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1889 		return WERR_OK;
1890         }
1891 
1892 	/* Fill in the DRIVER_INFO_2 struct */
1893 	ZERO_STRUCT(info2);
1894 
1895 	info2.printername	= argv[1];
1896 	info2.drivername	= argv[3];
1897 	info2.sharename		= argv[2];
1898 	info2.portname		= argv[4];
1899 	info2.comment		= "Created by rpcclient";
1900 	info2.printprocessor	= "winprint";
1901 	info2.datatype		= "RAW";
1902 	info2.devmode_ptr	= 0;
1903 	info2.secdesc_ptr	= 0;
1904 	info2.attributes 	= PRINTER_ATTRIBUTE_SHARED;
1905 	info2.priority 		= 0;
1906 	info2.defaultpriority	= 0;
1907 	info2.starttime		= 0;
1908 	info2.untiltime		= 0;
1909 
1910 	/* These three fields must not be used by AddPrinter()
1911 	   as defined in the MS Platform SDK documentation..
1912 	   --jerry
1913 	info2.status		= 0;
1914 	info2.cjobs		= 0;
1915 	info2.averageppm	= 0;
1916 	*/
1917 
1918 	info_ctr.level = 2;
1919 	info_ctr.info.info2 = &info2;
1920 
1921 	result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1922 					     &info_ctr);
1923 	if (W_ERROR_IS_OK(result))
1924 		printf ("Printer %s successfully installed.\n", argv[1]);
1925 
1926 	return result;
1927 }
1928 
1929 /****************************************************************************
1930 ****************************************************************************/
1931 
cmd_spoolss_setdriver(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1932 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1933                                       TALLOC_CTX *mem_ctx,
1934                                       int argc, const char **argv)
1935 {
1936 	struct policy_handle	pol;
1937 	WERROR                  result;
1938 	NTSTATUS		status;
1939 	uint32_t		level = 2;
1940 	const char		*printername;
1941 	union spoolss_PrinterInfo info;
1942 	struct spoolss_SetPrinterInfoCtr info_ctr;
1943 	struct spoolss_SetPrinterInfo2 info2;
1944 	struct spoolss_DevmodeContainer devmode_ctr;
1945 	struct sec_desc_buf secdesc_ctr;
1946 	struct dcerpc_binding_handle *b = cli->binding_handle;
1947 
1948 	ZERO_STRUCT(devmode_ctr);
1949 	ZERO_STRUCT(secdesc_ctr);
1950 
1951 	/* parse the command arguments */
1952 	if (argc != 3)
1953 	{
1954 		printf ("Usage: %s <printer> <driver>\n", argv[0]);
1955 		return WERR_OK;
1956         }
1957 
1958 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1959 
1960 	/* Get a printer handle */
1961 
1962 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1963 					       printername,
1964 					       PRINTER_ALL_ACCESS,
1965 					       &pol);
1966 	if (!W_ERROR_IS_OK(result))
1967 		goto done;
1968 
1969 	/* Get printer info */
1970 
1971 	result = rpccli_spoolss_getprinter(cli, mem_ctx,
1972 					   &pol,
1973 					   level,
1974 					   0,
1975 					   &info);
1976 	if (!W_ERROR_IS_OK(result)) {
1977 		printf ("Unable to retrieve printer information!\n");
1978 		goto done;
1979 	}
1980 
1981 	/* Set the printer driver */
1982 
1983 	spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1984 	info2.drivername = argv[2];
1985 
1986 	info_ctr.level = 2;
1987 	info_ctr.info.info2 = &info2;
1988 
1989 	status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1990 					   &pol,
1991 					   &info_ctr,
1992 					   &devmode_ctr,
1993 					   &secdesc_ctr,
1994 					   0, /* command */
1995 					   &result);
1996 	if (!NT_STATUS_IS_OK(status)) {
1997 		result = ntstatus_to_werror(status);
1998 		goto done;
1999 	}
2000 	if (!W_ERROR_IS_OK(result)) {
2001 		printf("SetPrinter call failed!\n");
2002 		goto done;
2003 	}
2004 
2005 	printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
2006 
2007 done:
2008 	/* Cleanup */
2009 
2010 	if (is_valid_policy_hnd(&pol)) {
2011 		WERROR _result;
2012 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2013 	}
2014 
2015 	return result;
2016 }
2017 
2018 
2019 /****************************************************************************
2020 ****************************************************************************/
2021 
cmd_spoolss_deletedriverex(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2022 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
2023                                          TALLOC_CTX *mem_ctx,
2024                                          int argc, const char **argv)
2025 {
2026 	WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
2027 	NTSTATUS status;
2028 	struct dcerpc_binding_handle *b = cli->binding_handle;
2029 
2030 	int   i;
2031 	int vers = -1;
2032 
2033 	const char *arch = NULL;
2034 	uint32_t delete_flags = 0;
2035 
2036 	/* parse the command arguments */
2037 	if (argc < 2 || argc > 5) {
2038 		printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
2039 		return WERR_OK;
2040 	}
2041 
2042 	if (argc >= 3)
2043 		arch = argv[2];
2044 	if (argc >= 4) {
2045 		vers = atoi(argv[3]);
2046 		delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
2047 	}
2048 	if (argc == 5)
2049 		delete_flags = atoi(argv[4]);
2050 
2051 	/* delete the driver for all architectures */
2052 	for (i=0; archi_table[i].long_archi; i++) {
2053 
2054 		if (arch && !strequal(archi_table[i].long_archi, arch))
2055 			continue;
2056 
2057 		if (vers >= 0 && archi_table[i].version != vers)
2058 			continue;
2059 
2060 		/* make the call to remove the driver */
2061 		status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
2062 							      cli->srv_name_slash,
2063 							      archi_table[i].long_archi,
2064 							      argv[1],
2065 							      delete_flags,
2066 							      archi_table[i].version,
2067 							      &result);
2068 		if (!NT_STATUS_IS_OK(status)) {
2069 			return ntstatus_to_werror(status);
2070 		}
2071 		if ( !W_ERROR_IS_OK(result) )
2072 		{
2073 			if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2074 				printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
2075 					argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
2076 			}
2077 		}
2078 		else
2079 		{
2080 			printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
2081 			archi_table[i].long_archi, archi_table[i].version);
2082 			ret = WERR_OK;
2083 		}
2084 	}
2085 
2086 	return ret;
2087 }
2088 
2089 
2090 /****************************************************************************
2091 ****************************************************************************/
2092 
cmd_spoolss_deletedriver(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2093 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
2094                                          TALLOC_CTX *mem_ctx,
2095                                          int argc, const char **argv)
2096 {
2097 	WERROR result = WERR_OK;
2098 	NTSTATUS status;
2099 	int			i;
2100 	struct dcerpc_binding_handle *b = cli->binding_handle;
2101 
2102 	/* parse the command arguments */
2103 	if (argc != 2) {
2104 		printf ("Usage: %s <driver>\n", argv[0]);
2105 		return WERR_OK;
2106         }
2107 
2108 	/* delete the driver for all architectures */
2109 	for (i=0; archi_table[i].long_archi; i++) {
2110 		result = WERR_OK;
2111 
2112 		/* make the call to remove the driver */
2113 		status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2114 							    cli->srv_name_slash,
2115 							    archi_table[i].long_archi,
2116 							    argv[1],
2117 							    &result);
2118 		if (!NT_STATUS_IS_OK(status)) {
2119 			result = ntstatus_to_werror(status);
2120 			continue;
2121 		}
2122 		if ( !W_ERROR_IS_OK(result) ) {
2123 			if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2124 				printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2125 					argv[1], archi_table[i].long_archi,
2126 					win_errstr(result));
2127 			}
2128 		} else {
2129 			printf ("Driver %s removed for arch [%s].\n", argv[1],
2130 				archi_table[i].long_archi);
2131 		}
2132 	}
2133 
2134 	return result;
2135 }
2136 
2137 /****************************************************************************
2138 ****************************************************************************/
2139 
cmd_spoolss_getprintprocdir(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2140 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2141 					    TALLOC_CTX *mem_ctx,
2142 					    int argc, const char **argv)
2143 {
2144 	WERROR result;
2145 	NTSTATUS status;
2146 	const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2147 	DATA_BLOB buffer;
2148 	uint32_t offered;
2149 	union spoolss_PrintProcessorDirectoryInfo info;
2150 	uint32_t needed;
2151 	struct dcerpc_binding_handle *b = cli->binding_handle;
2152 
2153 	/* parse the command arguments */
2154 	if (argc > 2) {
2155 		printf ("Usage: %s [environment]\n", argv[0]);
2156 		return WERR_OK;
2157         }
2158 
2159 	if (argc == 2) {
2160 		environment = argv[1];
2161 	}
2162 
2163 	status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2164 							   cli->srv_name_slash,
2165 							   environment,
2166 							   1,
2167 							   NULL, /* buffer */
2168 							   0, /* offered */
2169 							   NULL, /* info */
2170 							   &needed,
2171 							   &result);
2172 	if (!NT_STATUS_IS_OK(status)) {
2173 		return ntstatus_to_werror(status);
2174 	}
2175 	if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2176 		offered = needed;
2177 		buffer = data_blob_talloc_zero(mem_ctx, needed);
2178 
2179 		status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2180 								   cli->srv_name_slash,
2181 								   environment,
2182 								   1,
2183 								   &buffer,
2184 								   offered,
2185 								   &info,
2186 								   &needed,
2187 								   &result);
2188 		if (!NT_STATUS_IS_OK(status)) {
2189 			return ntstatus_to_werror(status);
2190 		}
2191 	}
2192 
2193 	if (W_ERROR_IS_OK(result)) {
2194 		printf("%s\n", info.info1.directory_name);
2195 	}
2196 
2197 	return result;
2198 }
2199 
2200 /****************************************************************************
2201 ****************************************************************************/
2202 
cmd_spoolss_addform(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2203 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2204 				    int argc, const char **argv)
2205 {
2206 	struct policy_handle handle;
2207 	WERROR werror;
2208 	NTSTATUS status;
2209 	const char *printername;
2210 	struct spoolss_AddFormInfoCtr info_ctr;
2211 	struct spoolss_AddFormInfo1 info1;
2212 	struct spoolss_AddFormInfo2 info2;
2213 	uint32_t level = 1;
2214 	struct dcerpc_binding_handle *b = cli->binding_handle;
2215 
2216 	/* Parse the command arguments */
2217 
2218 	if (argc < 3 || argc > 5) {
2219 		printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2220 		return WERR_OK;
2221         }
2222 
2223 	/* Get a printer handle */
2224 
2225 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2226 
2227 	werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2228 					       printername,
2229 					       PRINTER_ALL_ACCESS,
2230 					       &handle);
2231 	if (!W_ERROR_IS_OK(werror))
2232 		goto done;
2233 
2234 	/* Dummy up some values for the form data */
2235 
2236 	if (argc == 4) {
2237 		level = atoi(argv[3]);
2238 	}
2239 
2240 	switch (level) {
2241 	case 1:
2242 		info1.flags		= SPOOLSS_FORM_USER;
2243 		info1.form_name		= argv[2];
2244 		info1.size.width	= 100;
2245 		info1.size.height	= 100;
2246 		info1.area.left		= 0;
2247 		info1.area.top		= 10;
2248 		info1.area.right	= 20;
2249 		info1.area.bottom	= 30;
2250 
2251 		info_ctr.level		= 1;
2252 		info_ctr.info.info1	= &info1;
2253 
2254 		break;
2255 	case 2:
2256 		info2.flags		= SPOOLSS_FORM_USER;
2257 		info2.form_name		= argv[2];
2258 		info2.size.width	= 100;
2259 		info2.size.height	= 100;
2260 		info2.area.left		= 0;
2261 		info2.area.top		= 10;
2262 		info2.area.right	= 20;
2263 		info2.area.bottom	= 30;
2264 		info2.keyword		= argv[2];
2265 		info2.string_type	= SPOOLSS_FORM_STRING_TYPE_NONE;
2266 		info2.mui_dll		= NULL;
2267 		info2.ressource_id	= 0;
2268 		info2.display_name	= argv[2];
2269 		info2.lang_id		= 0;
2270 
2271 		info_ctr.level		= 2;
2272 		info_ctr.info.info2	= &info2;
2273 
2274 		break;
2275 	default:
2276 		werror = WERR_INVALID_PARAMETER;
2277 		goto done;
2278 	}
2279 
2280 	/* Add the form */
2281 
2282 	status = dcerpc_spoolss_AddForm(b, mem_ctx,
2283 					&handle,
2284 					&info_ctr,
2285 					&werror);
2286 	if (!NT_STATUS_IS_OK(status)) {
2287 		werror = ntstatus_to_werror(status);
2288 		goto done;
2289 	}
2290  done:
2291 	if (is_valid_policy_hnd(&handle)) {
2292 		WERROR _result;
2293 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2294 	}
2295 
2296 	return werror;
2297 }
2298 
2299 /****************************************************************************
2300 ****************************************************************************/
2301 
cmd_spoolss_setform(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2302 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2303 				    int argc, const char **argv)
2304 {
2305 	struct policy_handle handle;
2306 	WERROR werror;
2307 	NTSTATUS status;
2308 	const char *printername;
2309 	struct spoolss_AddFormInfoCtr info_ctr;
2310 	struct spoolss_AddFormInfo1 info1;
2311 	struct dcerpc_binding_handle *b = cli->binding_handle;
2312 
2313 	/* Parse the command arguments */
2314 
2315 	if (argc != 3) {
2316 		printf ("Usage: %s <printer> <formname>\n", argv[0]);
2317 		return WERR_OK;
2318         }
2319 
2320 	/* Get a printer handle */
2321 
2322 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2323 
2324 	werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2325 					       printername,
2326 					       SEC_FLAG_MAXIMUM_ALLOWED,
2327 					       &handle);
2328 	if (!W_ERROR_IS_OK(werror))
2329 		goto done;
2330 
2331 	/* Dummy up some values for the form data */
2332 
2333 	info1.flags		= SPOOLSS_FORM_PRINTER;
2334 	info1.size.width	= 100;
2335 	info1.size.height	= 100;
2336 	info1.area.left		= 0;
2337 	info1.area.top		= 1000;
2338 	info1.area.right	= 2000;
2339 	info1.area.bottom	= 3000;
2340 	info1.form_name		= argv[2];
2341 
2342 	info_ctr.info.info1 = &info1;
2343 	info_ctr.level = 1;
2344 
2345 	/* Set the form */
2346 
2347 	status = dcerpc_spoolss_SetForm(b, mem_ctx,
2348 					&handle,
2349 					argv[2],
2350 					&info_ctr,
2351 					&werror);
2352 	if (!NT_STATUS_IS_OK(status)) {
2353 		werror = ntstatus_to_werror(status);
2354 		goto done;
2355 	}
2356  done:
2357 	if (is_valid_policy_hnd(&handle)) {
2358 		WERROR _result;
2359 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2360 	}
2361 
2362 	return werror;
2363 }
2364 
2365 /****************************************************************************
2366 ****************************************************************************/
2367 
get_form_flag(int form_flag)2368 static const char *get_form_flag(int form_flag)
2369 {
2370 	switch (form_flag) {
2371 	case SPOOLSS_FORM_USER:
2372 		return "FORM_USER";
2373 	case SPOOLSS_FORM_BUILTIN:
2374 		return "FORM_BUILTIN";
2375 	case SPOOLSS_FORM_PRINTER:
2376 		return "FORM_PRINTER";
2377 	default:
2378 		return "unknown";
2379 	}
2380 }
2381 
2382 /****************************************************************************
2383 ****************************************************************************/
2384 
display_form_info1(struct spoolss_FormInfo1 * r)2385 static void display_form_info1(struct spoolss_FormInfo1 *r)
2386 {
2387 	printf("%s\n" \
2388 		"\tflag: %s (%d)\n" \
2389 		"\twidth: %d, length: %d\n" \
2390 		"\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2391 		r->form_name, get_form_flag(r->flags), r->flags,
2392 		r->size.width, r->size.height,
2393 		r->area.left, r->area.right,
2394 		r->area.top, r->area.bottom);
2395 }
2396 
2397 /****************************************************************************
2398 ****************************************************************************/
2399 
display_form_info2(struct spoolss_FormInfo2 * r)2400 static void display_form_info2(struct spoolss_FormInfo2 *r)
2401 {
2402 	printf("%s\n" \
2403 		"\tflag: %s (%d)\n" \
2404 		"\twidth: %d, length: %d\n" \
2405 		"\tleft: %d, right: %d, top: %d, bottom: %d\n",
2406 		r->form_name, get_form_flag(r->flags), r->flags,
2407 		r->size.width, r->size.height,
2408 		r->area.left, r->area.right,
2409 		r->area.top, r->area.bottom);
2410 	printf("\tkeyword: %s\n", r->keyword);
2411 	printf("\tstring_type: 0x%08x\n", r->string_type);
2412 	printf("\tmui_dll: %s\n", r->mui_dll);
2413 	printf("\tressource_id: 0x%08x\n", r->ressource_id);
2414 	printf("\tdisplay_name: %s\n", r->display_name);
2415 	printf("\tlang_id: %d\n", r->lang_id);
2416 	printf("\n");
2417 }
2418 
2419 /****************************************************************************
2420 ****************************************************************************/
2421 
cmd_spoolss_getform(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2422 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2423 				    int argc, const char **argv)
2424 {
2425 	struct policy_handle handle;
2426 	WERROR werror;
2427 	NTSTATUS status;
2428 	const char *printername;
2429 	DATA_BLOB buffer;
2430 	uint32_t offered = 0;
2431 	union spoolss_FormInfo info;
2432 	uint32_t needed;
2433 	uint32_t level = 1;
2434 	struct dcerpc_binding_handle *b = cli->binding_handle;
2435 
2436 	/* Parse the command arguments */
2437 
2438 	if (argc < 3 || argc > 5) {
2439 		printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2440 		return WERR_OK;
2441         }
2442 
2443 	/* Get a printer handle */
2444 
2445 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2446 
2447 	werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2448 					       printername,
2449 					       SEC_FLAG_MAXIMUM_ALLOWED,
2450 					       &handle);
2451 	if (!W_ERROR_IS_OK(werror))
2452 		goto done;
2453 
2454 	if (argc == 4) {
2455 		level = atoi(argv[3]);
2456 	}
2457 
2458 	/* Get the form */
2459 
2460 	status = dcerpc_spoolss_GetForm(b, mem_ctx,
2461 					&handle,
2462 					argv[2],
2463 					level,
2464 					NULL,
2465 					offered,
2466 					&info,
2467 					&needed,
2468 					&werror);
2469 	if (!NT_STATUS_IS_OK(status)) {
2470 		werror = ntstatus_to_werror(status);
2471 		goto done;
2472 	}
2473 	if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2474 		buffer = data_blob_talloc_zero(mem_ctx, needed);
2475 		offered = needed;
2476 		status = dcerpc_spoolss_GetForm(b, mem_ctx,
2477 						&handle,
2478 						argv[2],
2479 						level,
2480 						&buffer,
2481 						offered,
2482 						&info,
2483 						&needed,
2484 						&werror);
2485 		if (!NT_STATUS_IS_OK(status)) {
2486 			werror = ntstatus_to_werror(status);
2487 			goto done;
2488 		}
2489 	}
2490 
2491 	if (!W_ERROR_IS_OK(werror)) {
2492 		goto done;
2493 	}
2494 
2495 	switch (level) {
2496 	case 1:
2497 		display_form_info1(&info.info1);
2498 		break;
2499 	case 2:
2500 		display_form_info2(&info.info2);
2501 		break;
2502 	}
2503 
2504  done:
2505 	if (is_valid_policy_hnd(&handle)) {
2506 		WERROR _result;
2507 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2508 	}
2509 
2510 	return werror;
2511 }
2512 
2513 /****************************************************************************
2514 ****************************************************************************/
2515 
cmd_spoolss_deleteform(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2516 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2517 				       TALLOC_CTX *mem_ctx, int argc,
2518 				       const char **argv)
2519 {
2520 	struct policy_handle handle;
2521 	WERROR werror;
2522 	NTSTATUS status;
2523 	const char *printername;
2524 	struct dcerpc_binding_handle *b = cli->binding_handle;
2525 
2526 	/* Parse the command arguments */
2527 
2528 	if (argc != 3) {
2529 		printf ("Usage: %s <printer> <formname>\n", argv[0]);
2530 		return WERR_OK;
2531         }
2532 
2533 	/* Get a printer handle */
2534 
2535 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2536 
2537 	werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2538 					       printername,
2539 					       SEC_FLAG_MAXIMUM_ALLOWED,
2540 					       &handle);
2541 	if (!W_ERROR_IS_OK(werror))
2542 		goto done;
2543 
2544 	/* Delete the form */
2545 
2546 	status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2547 					   &handle,
2548 					   argv[2],
2549 					   &werror);
2550 	if (!NT_STATUS_IS_OK(status)) {
2551 		werror = ntstatus_to_werror(status);
2552 		goto done;
2553 	}
2554 
2555  done:
2556 	if (is_valid_policy_hnd(&handle)) {
2557 		WERROR _result;
2558 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2559 	}
2560 
2561 	return werror;
2562 }
2563 
2564 /****************************************************************************
2565 ****************************************************************************/
2566 
cmd_spoolss_enum_forms(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2567 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2568 				       TALLOC_CTX *mem_ctx, int argc,
2569 				       const char **argv)
2570 {
2571 	struct policy_handle handle;
2572 	WERROR werror;
2573 	const char *printername;
2574 	uint32_t num_forms, level = 1, i;
2575 	union spoolss_FormInfo *forms;
2576 	struct dcerpc_binding_handle *b = cli->binding_handle;
2577 
2578 	/* Parse the command arguments */
2579 
2580 	if (argc < 2 || argc > 4) {
2581 		printf ("Usage: %s <printer> [level]\n", argv[0]);
2582 		return WERR_OK;
2583         }
2584 
2585 	/* Get a printer handle */
2586 
2587 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2588 
2589 	werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2590 					       printername,
2591 					       SEC_FLAG_MAXIMUM_ALLOWED,
2592 					       &handle);
2593 	if (!W_ERROR_IS_OK(werror))
2594 		goto done;
2595 
2596 	if (argc == 3) {
2597 		level = atoi(argv[2]);
2598 	}
2599 
2600 	/* Enumerate forms */
2601 
2602 	werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2603 					  &handle,
2604 					  level,
2605 					  0,
2606 					  &num_forms,
2607 					  &forms);
2608 
2609 	if (!W_ERROR_IS_OK(werror))
2610 		goto done;
2611 
2612 	/* Display output */
2613 
2614 	for (i = 0; i < num_forms; i++) {
2615 		switch (level) {
2616 		case 1:
2617 			display_form_info1(&forms[i].info1);
2618 			break;
2619 		case 2:
2620 			display_form_info2(&forms[i].info2);
2621 			break;
2622 		}
2623 	}
2624 
2625  done:
2626 	if (is_valid_policy_hnd(&handle)) {
2627 		WERROR _result;
2628 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2629 	}
2630 
2631 	return werror;
2632 }
2633 
2634 /****************************************************************************
2635 ****************************************************************************/
2636 
cmd_spoolss_setprinterdata(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2637 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2638 					    TALLOC_CTX *mem_ctx,
2639 					    int argc, const char **argv)
2640 {
2641 	WERROR result;
2642 	NTSTATUS status;
2643 	const char *printername;
2644 	struct policy_handle pol = { 0, };
2645 	union spoolss_PrinterInfo info;
2646 	enum winreg_Type type;
2647 	union spoolss_PrinterData data;
2648 	DATA_BLOB blob;
2649 	struct dcerpc_binding_handle *b = cli->binding_handle;
2650 	int error = 0;
2651 
2652 	/* parse the command arguments */
2653 	if (argc < 5) {
2654 		printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2655 			" <value> <data>\n",
2656 			argv[0]);
2657 		return WERR_OK;
2658 	}
2659 
2660 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2661 
2662 	type = REG_NONE;
2663 
2664 	if (strequal(argv[2], "string")) {
2665 		type = REG_SZ;
2666 	}
2667 
2668 	if (strequal(argv[2], "binary")) {
2669 		type = REG_BINARY;
2670 	}
2671 
2672 	if (strequal(argv[2], "dword")) {
2673 		type = REG_DWORD;
2674 	}
2675 
2676 	if (strequal(argv[2], "multistring")) {
2677 		type = REG_MULTI_SZ;
2678 	}
2679 
2680 	if (type == REG_NONE) {
2681 		printf("Unknown data type: %s\n", argv[2]);
2682 		result =  WERR_INVALID_PARAMETER;
2683 		goto done;
2684 	}
2685 
2686 	/* get a printer handle */
2687 
2688 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2689 					       printername,
2690 					       SEC_FLAG_MAXIMUM_ALLOWED,
2691 					       &pol);
2692 	if (!W_ERROR_IS_OK(result)) {
2693 		goto done;
2694 	}
2695 
2696 	result = rpccli_spoolss_getprinter(cli, mem_ctx,
2697 					   &pol,
2698 					   0,
2699 					   0,
2700 					   &info);
2701         if (!W_ERROR_IS_OK(result)) {
2702                 goto done;
2703 	}
2704 
2705 	printf("%s\n", current_timestring(mem_ctx, true));
2706 	printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2707 
2708 	/* Set the printer data */
2709 
2710 	switch (type) {
2711 	case REG_SZ:
2712 		data.string = talloc_strdup(mem_ctx, argv[4]);
2713 		W_ERROR_HAVE_NO_MEMORY(data.string);
2714 		break;
2715 	case REG_DWORD:
2716 		data.value = smb_strtoul(argv[4],
2717 					 NULL,
2718 					 10,
2719 					 &error,
2720 					 SMB_STR_STANDARD);
2721 		if (error != 0) {
2722 			result = WERR_INVALID_PARAMETER;
2723 			goto done;
2724 		}
2725 
2726 		break;
2727 	case REG_BINARY:
2728 		data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2729 		break;
2730 	case REG_MULTI_SZ: {
2731 		int i;
2732 		size_t num_strings;
2733 		const char **strings = NULL;
2734 
2735 		num_strings = 0;
2736 
2737 		for (i=4; i<argc; i++) {
2738 			if (strcmp(argv[i], "NULL") == 0) {
2739 				argv[i] = "";
2740 			}
2741 			if (!add_string_to_array(mem_ctx, argv[i],
2742 						 &strings,
2743 						 &num_strings)) {
2744 				result = WERR_NOT_ENOUGH_MEMORY;
2745 				goto done;
2746 			}
2747 		}
2748 		data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2749 		if (!data.string_array) {
2750 			result = WERR_NOT_ENOUGH_MEMORY;
2751 			goto done;
2752 		}
2753 		for (i=0; i < num_strings; i++) {
2754 			data.string_array[i] = strings[i];
2755 		}
2756 		break;
2757 		}
2758 	default:
2759 		printf("Unknown data type: %s\n", argv[2]);
2760 		result = WERR_INVALID_PARAMETER;
2761 		goto done;
2762 	}
2763 
2764 	result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2765 	if (!W_ERROR_IS_OK(result)) {
2766 		goto done;
2767 	}
2768 
2769 	status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2770 					       &pol,
2771 					       argv[3], /* value_name */
2772 					       type,
2773 					       blob.data,
2774 					       blob.length,
2775 					       &result);
2776 	if (!NT_STATUS_IS_OK(status)) {
2777 		printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2778 		result = ntstatus_to_werror(status);
2779 		goto done;
2780 	}
2781 	if (!W_ERROR_IS_OK(result)) {
2782 		printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2783 		goto done;
2784 	}
2785 	printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2786 
2787 	result = rpccli_spoolss_getprinter(cli, mem_ctx,
2788 					   &pol,
2789 					   0,
2790 					   0,
2791 					   &info);
2792         if (!W_ERROR_IS_OK(result)) {
2793                 goto done;
2794 	}
2795 
2796 	printf("%s\n", current_timestring(mem_ctx, true));
2797 	printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2798 
2799 done:
2800 	/* cleanup */
2801 	if (is_valid_policy_hnd(&pol)) {
2802 		WERROR _result;
2803 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2804 	}
2805 
2806 	return result;
2807 }
2808 
2809 /****************************************************************************
2810 ****************************************************************************/
2811 
display_job_info1(struct spoolss_JobInfo1 * r)2812 static void display_job_info1(struct spoolss_JobInfo1 *r)
2813 {
2814 	printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2815 	       r->user_name, r->document_name, r->text_status, r->pages_printed,
2816 	       r->total_pages);
2817 }
2818 
2819 /****************************************************************************
2820 ****************************************************************************/
2821 
display_job_info2(struct spoolss_JobInfo2 * r)2822 static void display_job_info2(struct spoolss_JobInfo2 *r)
2823 {
2824 	printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2825 	       r->position, r->job_id,
2826 	       r->user_name, r->document_name, r->text_status, r->pages_printed,
2827 	       r->total_pages, r->size);
2828 }
2829 
2830 /****************************************************************************
2831 ****************************************************************************/
2832 
display_job_info3(struct spoolss_JobInfo3 * r)2833 static void display_job_info3(struct spoolss_JobInfo3 *r)
2834 {
2835 	printf("jobid[%d], next_jobid[%d]\n",
2836 		r->job_id, r->next_job_id);
2837 }
2838 
2839 /****************************************************************************
2840 ****************************************************************************/
2841 
display_job_info4(struct spoolss_JobInfo4 * r)2842 static void display_job_info4(struct spoolss_JobInfo4 *r)
2843 {
2844 	printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2845 	       r->position, r->job_id,
2846 	       r->user_name, r->document_name, r->text_status, r->pages_printed,
2847 	       r->total_pages, r->size, r->size_high);
2848 }
2849 
2850 /****************************************************************************
2851 ****************************************************************************/
2852 
cmd_spoolss_enum_jobs(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2853 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2854 				      TALLOC_CTX *mem_ctx, int argc,
2855 				      const char **argv)
2856 {
2857 	WERROR result;
2858 	uint32_t level = 1, count, i;
2859 	const char *printername;
2860 	struct policy_handle hnd;
2861 	union spoolss_JobInfo *info;
2862 	struct dcerpc_binding_handle *b = cli->binding_handle;
2863 
2864 	if (argc < 2 || argc > 3) {
2865 		printf("Usage: %s printername [level]\n", argv[0]);
2866 		return WERR_OK;
2867 	}
2868 
2869 	if (argc == 3) {
2870 		level = atoi(argv[2]);
2871 	}
2872 
2873 	/* Open printer handle */
2874 
2875 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2876 
2877 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2878 					       printername,
2879 					       SEC_FLAG_MAXIMUM_ALLOWED,
2880 					       &hnd);
2881 	if (!W_ERROR_IS_OK(result))
2882 		goto done;
2883 
2884 	/* Enumerate ports */
2885 
2886 	result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2887 					 &hnd,
2888 					 0, /* firstjob */
2889 					 1000, /* numjobs */
2890 					 level,
2891 					 0,
2892 					 &count,
2893 					 &info);
2894 	if (!W_ERROR_IS_OK(result)) {
2895 		goto done;
2896 	}
2897 
2898 	for (i = 0; i < count; i++) {
2899 		switch (level) {
2900 		case 1:
2901 			display_job_info1(&info[i].info1);
2902 			break;
2903 		case 2:
2904 			display_job_info2(&info[i].info2);
2905 			break;
2906 		default:
2907 			d_printf("unknown info level %d\n", level);
2908 			break;
2909 		}
2910 	}
2911 
2912 done:
2913 	if (is_valid_policy_hnd(&hnd)) {
2914 		WERROR _result;
2915 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2916 	}
2917 
2918 	return result;
2919 }
2920 
2921 /****************************************************************************
2922 ****************************************************************************/
2923 
cmd_spoolss_get_job(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2924 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2925 				  TALLOC_CTX *mem_ctx, int argc,
2926 				  const char **argv)
2927 {
2928 	WERROR result;
2929 	const char *printername;
2930 	struct policy_handle hnd;
2931 	uint32_t job_id;
2932 	uint32_t level = 1;
2933 	union spoolss_JobInfo info;
2934 	struct dcerpc_binding_handle *b = cli->binding_handle;
2935 
2936 	if (argc < 3 || argc > 4) {
2937 		printf("Usage: %s printername job_id [level]\n", argv[0]);
2938 		return WERR_OK;
2939 	}
2940 
2941 	job_id = atoi(argv[2]);
2942 
2943 	if (argc == 4) {
2944 		level = atoi(argv[3]);
2945 	}
2946 
2947 	/* Open printer handle */
2948 
2949 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2950 
2951 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2952 					       printername,
2953 					       SEC_FLAG_MAXIMUM_ALLOWED,
2954 					       &hnd);
2955 	if (!W_ERROR_IS_OK(result)) {
2956 		goto done;
2957 	}
2958 
2959 	/* Enumerate ports */
2960 
2961 	result = rpccli_spoolss_getjob(cli, mem_ctx,
2962 				       &hnd,
2963 				       job_id,
2964 				       level,
2965 				       0,
2966 				       &info);
2967 
2968 	if (!W_ERROR_IS_OK(result)) {
2969 		goto done;
2970 	}
2971 
2972 	switch (level) {
2973 	case 1:
2974 		display_job_info1(&info.info1);
2975 		break;
2976 	case 2:
2977 		display_job_info2(&info.info2);
2978 		break;
2979 	case 3:
2980 		display_job_info3(&info.info3);
2981 		break;
2982 	case 4:
2983 		display_job_info4(&info.info4);
2984 		break;
2985 	default:
2986 		d_printf("unknown info level %d\n", level);
2987 		break;
2988 	}
2989 
2990 done:
2991 	if (is_valid_policy_hnd(&hnd)) {
2992 		WERROR _result;
2993 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2994 	}
2995 
2996 	return result;
2997 }
2998 
2999 /****************************************************************************
3000 ****************************************************************************/
3001 
3002 static struct {
3003 	const char *name;
3004 	enum spoolss_JobControl val;
3005 } cmdvals[] = {
3006 	{"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
3007 	{"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
3008 	{"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
3009 	{"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
3010 	{"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
3011 	{"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
3012 	{"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
3013 	{"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
3014 	{"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
3015 };
3016 
parse_setjob_command(const char * cmd)3017 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
3018 {
3019 	int i;
3020 
3021 	for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
3022 		if (strequal(cmdvals[i].name, cmd)) {
3023 			return cmdvals[i].val;
3024 		}
3025 	}
3026 	return (enum spoolss_JobControl)atoi(cmd);
3027 }
3028 
cmd_spoolss_set_job(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3029 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
3030 				  TALLOC_CTX *mem_ctx, int argc,
3031 				  const char **argv)
3032 {
3033 	WERROR result;
3034 	NTSTATUS status;
3035 	const char *printername;
3036 	struct policy_handle hnd;
3037 	uint32_t job_id;
3038 	enum spoolss_JobControl command;
3039 	struct dcerpc_binding_handle *b = cli->binding_handle;
3040 
3041 	if (argc != 4) {
3042 		printf("Usage: %s printername job_id command\n", argv[0]);
3043 		printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
3044 			"SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
3045 		return WERR_OK;
3046 	}
3047 
3048 	job_id = atoi(argv[2]);
3049 	command = parse_setjob_command(argv[3]);
3050 
3051 	/* Open printer handle */
3052 
3053 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3054 
3055 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3056 					       printername,
3057 					       SEC_FLAG_MAXIMUM_ALLOWED,
3058 					       &hnd);
3059 	if (!W_ERROR_IS_OK(result)) {
3060 		goto done;
3061 	}
3062 
3063 	/* Set Job */
3064 
3065 	status = dcerpc_spoolss_SetJob(b, mem_ctx,
3066 				       &hnd,
3067 				       job_id,
3068 				       NULL,
3069 				       command,
3070 				       &result);
3071 	if (!NT_STATUS_IS_OK(status)) {
3072 		result = ntstatus_to_werror(status);
3073 		goto done;
3074 	}
3075 	if (!W_ERROR_IS_OK(result)) {
3076 		goto done;
3077 	}
3078 
3079 done:
3080 	if (is_valid_policy_hnd(&hnd)) {
3081 		WERROR _result;
3082 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3083 	}
3084 
3085 	return result;
3086 }
3087 
3088 /****************************************************************************
3089 ****************************************************************************/
3090 
cmd_spoolss_enum_data(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3091 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
3092 				    TALLOC_CTX *mem_ctx, int argc,
3093 				    const char **argv)
3094 {
3095 	WERROR result;
3096 	NTSTATUS status;
3097 	const char *printername;
3098 	struct policy_handle hnd;
3099 	uint32_t value_needed;
3100 	enum winreg_Type type;
3101 	uint32_t data_needed;
3102 	struct dcerpc_binding_handle *b = cli->binding_handle;
3103 	struct spoolss_EnumPrinterData r;
3104 
3105 	if (argc != 2) {
3106 		printf("Usage: %s printername\n", argv[0]);
3107 		return WERR_OK;
3108 	}
3109 
3110 	/* Open printer handle */
3111 
3112 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3113 
3114 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3115 					       printername,
3116 					       SEC_FLAG_MAXIMUM_ALLOWED,
3117 					       &hnd);
3118 	if (!W_ERROR_IS_OK(result)) {
3119 		goto done;
3120 	}
3121 
3122 	/* Enumerate data */
3123 
3124 	r.in.handle = &hnd;
3125 	r.in.enum_index = 0;
3126 	r.in.value_offered = 0;
3127 	r.in.data_offered = 0;
3128 	r.out.value_name = NULL;
3129 	r.out.value_needed = &value_needed;
3130 	r.out.type = &type;
3131 	r.out.data = NULL;
3132 	r.out.data_needed = &data_needed;
3133 
3134 	status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3135 	if (!NT_STATUS_IS_OK(status)) {
3136 		result = ntstatus_to_werror(status);
3137 		goto done;
3138 	}
3139 
3140 	if (!W_ERROR_IS_OK(r.out.result)) {
3141 		result = r.out.result;
3142 		goto done;
3143 	}
3144 
3145 	r.in.data_offered	= *r.out.data_needed;
3146 	r.in.value_offered	= *r.out.value_needed;
3147 	r.out.data		= talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3148 	r.out.value_name	= talloc_zero_array(mem_ctx, char, r.in.value_offered);
3149 
3150 	do {
3151 
3152 		status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3153 		if (!NT_STATUS_IS_OK(status)) {
3154 			result = ntstatus_to_werror(status);
3155 			goto done;
3156 		}
3157 
3158 		if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3159 			result = WERR_OK;
3160 			break;
3161 		}
3162 
3163 		r.in.enum_index++;
3164 
3165 		display_reg_value(r.out.value_name, *r.out.type,
3166 				  data_blob_const(r.out.data, r.in.data_offered));
3167 
3168 	} while (W_ERROR_IS_OK(r.out.result));
3169 
3170 done:
3171 	if (is_valid_policy_hnd(&hnd)) {
3172 		WERROR _result;
3173 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3174 	}
3175 
3176 	return result;
3177 }
3178 
3179 /****************************************************************************
3180 ****************************************************************************/
3181 
cmd_spoolss_enum_data_ex(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3182 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3183 					  TALLOC_CTX *mem_ctx, int argc,
3184 					  const char **argv)
3185 {
3186 	WERROR result;
3187 	uint32_t i;
3188 	const char *printername;
3189 	struct policy_handle hnd;
3190 	uint32_t count;
3191 	struct spoolss_PrinterEnumValues *info;
3192 	struct dcerpc_binding_handle *b = cli->binding_handle;
3193 
3194 	if (argc != 3) {
3195 		printf("Usage: %s printername <keyname>\n", argv[0]);
3196 		return WERR_OK;
3197 	}
3198 
3199 	/* Open printer handle */
3200 
3201 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3202 
3203 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3204 					       printername,
3205 					       SEC_FLAG_MAXIMUM_ALLOWED,
3206 					       &hnd);
3207 	if (!W_ERROR_IS_OK(result)) {
3208 		goto done;
3209 	}
3210 
3211 	/* Enumerate subkeys */
3212 
3213 	result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3214 						  &hnd,
3215 						  argv[2],
3216 						  0,
3217 						  &count,
3218 						  &info);
3219 	if (!W_ERROR_IS_OK(result)) {
3220 		goto done;
3221 	}
3222 
3223 	for (i=0; i < count; i++) {
3224 		display_printer_data(info[i].value_name,
3225 				     info[i].type,
3226 				     info[i].data->data,
3227 				     info[i].data->length);
3228 	}
3229 
3230  done:
3231 	if (is_valid_policy_hnd(&hnd)) {
3232 		WERROR _result;
3233 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3234 	}
3235 
3236 	return result;
3237 }
3238 
3239 /****************************************************************************
3240 ****************************************************************************/
3241 
cmd_spoolss_enum_printerkey(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3242 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3243 					  TALLOC_CTX *mem_ctx, int argc,
3244 					  const char **argv)
3245 {
3246 	WERROR result;
3247 	const char *printername;
3248 	const char *keyname = NULL;
3249 	struct policy_handle hnd;
3250 	const char **key_buffer = NULL;
3251 	int i;
3252 	uint32_t offered = 0;
3253 	struct dcerpc_binding_handle *b = cli->binding_handle;
3254 
3255 	if (argc < 2 || argc > 4) {
3256 		printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3257 		return WERR_OK;
3258 	}
3259 
3260 	if (argc >= 3) {
3261 		keyname = argv[2];
3262 	} else {
3263 		keyname = "";
3264 	}
3265 
3266 	if (argc == 4) {
3267 		offered = atoi(argv[3]);
3268 	}
3269 
3270 	/* Open printer handle */
3271 
3272 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3273 
3274 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3275 					       printername,
3276 					       SEC_FLAG_MAXIMUM_ALLOWED,
3277 					       &hnd);
3278 	if (!W_ERROR_IS_OK(result)) {
3279 		goto done;
3280 	}
3281 
3282 	/* Enumerate subkeys */
3283 
3284 	result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3285 					       &hnd,
3286 					       keyname,
3287 					       &key_buffer,
3288 					       offered);
3289 
3290 	if (!W_ERROR_IS_OK(result)) {
3291 		goto done;
3292 	}
3293 
3294 	for (i=0; key_buffer && key_buffer[i]; i++) {
3295 		printf("%s\n", key_buffer[i]);
3296 	}
3297 
3298  done:
3299 
3300 	if (is_valid_policy_hnd(&hnd)) {
3301 		WERROR _result;
3302 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3303 	}
3304 
3305 	return result;
3306 }
3307 
3308 /****************************************************************************
3309 ****************************************************************************/
3310 
cmd_spoolss_rffpcnex(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3311 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3312 				     TALLOC_CTX *mem_ctx, int argc,
3313 				     const char **argv)
3314 {
3315 	const char *printername;
3316 	const char *clientname;
3317 	struct policy_handle hnd = { 0, };
3318 	WERROR result;
3319 	NTSTATUS status;
3320 	struct spoolss_NotifyOption option;
3321 	struct dcerpc_binding_handle *b = cli->binding_handle;
3322 
3323 	if (argc != 2) {
3324 		printf("Usage: %s printername\n", argv[0]);
3325 		result = WERR_OK;
3326 		goto done;
3327 	}
3328 
3329 	/* Open printer */
3330 
3331 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3332 
3333 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3334 					       printername,
3335 					       SEC_FLAG_MAXIMUM_ALLOWED,
3336 					       &hnd);
3337 	if (!W_ERROR_IS_OK(result)) {
3338 		printf("Error opening %s\n", argv[1]);
3339 		goto done;
3340 	}
3341 
3342 	/* Create spool options */
3343 
3344 	option.version = 2;
3345 	option.count = 2;
3346 
3347 	option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3348 	if (option.types == NULL) {
3349 		result = WERR_NOT_ENOUGH_MEMORY;
3350 		goto done;
3351 	}
3352 
3353 	option.types[0].type = PRINTER_NOTIFY_TYPE;
3354 	option.types[0].count = 1;
3355 	option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3356 	if (option.types[0].fields == NULL) {
3357 		result = WERR_NOT_ENOUGH_MEMORY;
3358 		goto done;
3359 	}
3360 	option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3361 
3362 	option.types[1].type = JOB_NOTIFY_TYPE;
3363 	option.types[1].count = 1;
3364 	option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3365 	if (option.types[1].fields == NULL) {
3366 		result = WERR_NOT_ENOUGH_MEMORY;
3367 		goto done;
3368 	}
3369 	option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3370 
3371 	clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3372 	if (!clientname) {
3373 		result = WERR_NOT_ENOUGH_MEMORY;
3374 		goto done;
3375 	}
3376 
3377 	/* Send rffpcnex */
3378 
3379 	status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3380 								     &hnd,
3381 								     0,
3382 								     0,
3383 								     clientname,
3384 								     123,
3385 								     &option,
3386 								     &result);
3387 	if (!NT_STATUS_IS_OK(status)) {
3388 		result = ntstatus_to_werror(status);
3389 		goto done;
3390 	}
3391 	if (!W_ERROR_IS_OK(result)) {
3392 		printf("Error rffpcnex %s\n", argv[1]);
3393 		goto done;
3394 	}
3395 
3396 done:
3397 	if (is_valid_policy_hnd(&hnd)) {
3398 		WERROR _result;
3399 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3400 	}
3401 
3402 	return result;
3403 }
3404 
3405 /****************************************************************************
3406 ****************************************************************************/
3407 
compare_printer(struct rpc_pipe_client * cli1,struct policy_handle * hnd1,struct rpc_pipe_client * cli2,struct policy_handle * hnd2)3408 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3409                              struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3410 {
3411 	union spoolss_PrinterInfo info1, info2;
3412 	WERROR werror;
3413 	TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3414 
3415 	printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3416 	werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3417 					   hnd1,
3418 					   2,
3419 					   0,
3420 					   &info1);
3421 	if ( !W_ERROR_IS_OK(werror) ) {
3422 		printf("failed (%s)\n", win_errstr(werror));
3423 		talloc_destroy(mem_ctx);
3424 		return false;
3425 	}
3426 	printf("ok\n");
3427 
3428 	printf("Retrieving printer properties for %s...", cli2->desthost);
3429 	werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3430 					   hnd2,
3431 					   2,
3432 					   0,
3433 					   &info2);
3434 	if ( !W_ERROR_IS_OK(werror) ) {
3435 		printf("failed (%s)\n", win_errstr(werror));
3436 		talloc_destroy(mem_ctx);
3437 		return false;
3438 	}
3439 	printf("ok\n");
3440 
3441 	talloc_destroy(mem_ctx);
3442 
3443 	return true;
3444 }
3445 
3446 /****************************************************************************
3447 ****************************************************************************/
3448 
compare_printer_secdesc(struct rpc_pipe_client * cli1,struct policy_handle * hnd1,struct rpc_pipe_client * cli2,struct policy_handle * hnd2)3449 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3450                                      struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3451 {
3452 	union spoolss_PrinterInfo info1, info2;
3453 	WERROR werror;
3454 	TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3455 	struct security_descriptor *sd1, *sd2;
3456 	bool result = true;
3457 
3458 
3459 	printf("Retrieving printer security for %s...", cli1->desthost);
3460 	werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3461 					   hnd1,
3462 					   3,
3463 					   0,
3464 					   &info1);
3465 	if ( !W_ERROR_IS_OK(werror) ) {
3466 		printf("failed (%s)\n", win_errstr(werror));
3467 		result = false;
3468 		goto done;
3469 	}
3470 	printf("ok\n");
3471 
3472 	printf("Retrieving printer security for %s...", cli2->desthost);
3473 	werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3474 					   hnd2,
3475 					   3,
3476 					   0,
3477 					   &info2);
3478 	if ( !W_ERROR_IS_OK(werror) ) {
3479 		printf("failed (%s)\n", win_errstr(werror));
3480 		result = false;
3481 		goto done;
3482 	}
3483 	printf("ok\n");
3484 
3485 
3486 	printf("++ ");
3487 
3488 	sd1 = info1.info3.secdesc;
3489 	sd2 = info2.info3.secdesc;
3490 
3491 	if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3492 		printf("NULL secdesc!\n");
3493 		result = false;
3494 		goto done;
3495 	}
3496 
3497 	if (!security_descriptor_equal( sd1, sd2 ) ) {
3498 		printf("Security Descriptors *not* equal!\n");
3499 		result = false;
3500 		goto done;
3501 	}
3502 
3503 	printf("Security descriptors match\n");
3504 
3505 done:
3506 	talloc_destroy(mem_ctx);
3507 	return result;
3508 }
3509 
3510 
3511 /****************************************************************************
3512 ****************************************************************************/
3513 
cmd_spoolss_printercmp(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3514 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3515 				     TALLOC_CTX *mem_ctx, int argc,
3516 				     const char **argv)
3517 {
3518 	const char *printername;
3519 	char *printername_path = NULL;
3520 	struct cli_state *cli_server2 = NULL;
3521 	struct rpc_pipe_client *cli2 = NULL;
3522 	struct policy_handle hPrinter1, hPrinter2;
3523 	NTSTATUS nt_status;
3524 	WERROR werror;
3525 
3526 	if ( argc != 3 )  {
3527 		printf("Usage: %s <printer> <server>\n", argv[0]);
3528 		return WERR_OK;
3529 	}
3530 
3531 	printername = argv[1];
3532 
3533 	/* first get the connection to the remote server */
3534 
3535 	nt_status = cli_full_connection(&cli_server2, lp_netbios_name(), argv[2],
3536 				NULL, 0,
3537 				"IPC$", "IPC",
3538 				get_cmdline_auth_info_username(
3539 					popt_get_cmdline_auth_info()),
3540 				lp_workgroup(),
3541 				get_cmdline_auth_info_password(
3542 					popt_get_cmdline_auth_info()),
3543 				get_cmdline_auth_info_use_kerberos(
3544 					popt_get_cmdline_auth_info()) ?
3545 					CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3546 				get_cmdline_auth_info_signing_state(
3547 					popt_get_cmdline_auth_info()));
3548 
3549 	if ( !NT_STATUS_IS_OK(nt_status) )
3550 		return WERR_GEN_FAILURE;
3551 
3552 	nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
3553 					     &cli2);
3554 	if (!NT_STATUS_IS_OK(nt_status)) {
3555 		printf("failed to open spoolss pipe on server %s (%s)\n",
3556 			argv[2], nt_errstr(nt_status));
3557 		return WERR_GEN_FAILURE;
3558 	}
3559 
3560 	/* now open up both printers */
3561 
3562 	RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3563 
3564 	printf("Opening %s...", printername_path);
3565 
3566 	werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3567 					       printername_path,
3568 					       PRINTER_ALL_ACCESS,
3569 					       &hPrinter1);
3570 	if ( !W_ERROR_IS_OK(werror) ) {
3571 		printf("failed (%s)\n", win_errstr(werror));
3572 		goto done;
3573 	}
3574 	printf("ok\n");
3575 
3576 	RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3577 
3578 	printf("Opening %s...", printername_path);
3579 	werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3580 					       printername_path,
3581 					       PRINTER_ALL_ACCESS,
3582 					       &hPrinter2);
3583 	if ( !W_ERROR_IS_OK(werror) ) {
3584 		 printf("failed (%s)\n", win_errstr(werror));
3585 		goto done;
3586 	}
3587 	printf("ok\n");
3588 
3589 	compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3590 	compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3591 #if 0
3592 	compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3593 #endif
3594 
3595 
3596 done:
3597 	/* cleanup */
3598 
3599 	printf("Closing printers...");
3600 	{
3601 		WERROR _result;
3602 		dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3603 		dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3604 	}
3605 	printf("ok\n");
3606 
3607 	/* close the second remote connection */
3608 
3609 	cli_shutdown( cli_server2 );
3610 	return WERR_OK;
3611 }
3612 
display_proc_info1(struct spoolss_PrintProcessorInfo1 * r)3613 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3614 {
3615 	printf("print_processor_name: %s\n", r->print_processor_name);
3616 }
3617 
cmd_spoolss_enum_procs(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3618 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3619 				     TALLOC_CTX *mem_ctx, int argc,
3620 				     const char **argv)
3621 {
3622 	WERROR werror;
3623 	const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3624 	uint32_t num_procs, level = 1, i;
3625 	union spoolss_PrintProcessorInfo *procs;
3626 
3627 	/* Parse the command arguments */
3628 
3629 	if (argc < 1 || argc > 4) {
3630 		printf ("Usage: %s [environment] [level]\n", argv[0]);
3631 		return WERR_OK;
3632         }
3633 
3634 	if (argc >= 2) {
3635 		environment = argv[1];
3636 	}
3637 
3638 	if (argc == 3) {
3639 		level = atoi(argv[2]);
3640 	}
3641 
3642 	/* Enumerate Print Processors */
3643 
3644 	werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3645 						    cli->srv_name_slash,
3646 						    environment,
3647 						    level,
3648 						    0,
3649 						    &num_procs,
3650 						    &procs);
3651 	if (!W_ERROR_IS_OK(werror))
3652 		goto done;
3653 
3654 	/* Display output */
3655 
3656 	for (i = 0; i < num_procs; i++) {
3657 		switch (level) {
3658 		case 1:
3659 			display_proc_info1(&procs[i].info1);
3660 			break;
3661 		}
3662 	}
3663 
3664  done:
3665 	return werror;
3666 }
3667 
display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 * r)3668 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3669 {
3670 	printf("name_array: %s\n", r->name_array);
3671 }
3672 
cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3673 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3674 					       TALLOC_CTX *mem_ctx, int argc,
3675 					       const char **argv)
3676 {
3677 	WERROR werror;
3678 	const char *print_processor_name = "winprint";
3679 	uint32_t num_procs, level = 1, i;
3680 	union spoolss_PrintProcDataTypesInfo *procs;
3681 
3682 	/* Parse the command arguments */
3683 
3684 	if (argc < 1 || argc > 4) {
3685 		printf ("Usage: %s [environment] [level]\n", argv[0]);
3686 		return WERR_OK;
3687         }
3688 
3689 	if (argc >= 2) {
3690 		print_processor_name = argv[1];
3691 	}
3692 
3693 	if (argc == 3) {
3694 		level = atoi(argv[2]);
3695 	}
3696 
3697 	/* Enumerate Print Processor Data Types */
3698 
3699 	werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3700 							    cli->srv_name_slash,
3701 							    print_processor_name,
3702 							    level,
3703 							    0,
3704 							    &num_procs,
3705 							    &procs);
3706 	if (!W_ERROR_IS_OK(werror))
3707 		goto done;
3708 
3709 	/* Display output */
3710 
3711 	for (i = 0; i < num_procs; i++) {
3712 		switch (level) {
3713 		case 1:
3714 			display_proc_data_types_info1(&procs[i].info1);
3715 			break;
3716 		}
3717 	}
3718 
3719  done:
3720 	return werror;
3721 }
3722 
display_monitor1(const struct spoolss_MonitorInfo1 * r)3723 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3724 {
3725 	printf("monitor_name: %s\n", r->monitor_name);
3726 }
3727 
display_monitor2(const struct spoolss_MonitorInfo2 * r)3728 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3729 {
3730 	printf("monitor_name: %s\n", r->monitor_name);
3731 	printf("environment: %s\n", r->environment);
3732 	printf("dll_name: %s\n", r->dll_name);
3733 }
3734 
cmd_spoolss_enum_monitors(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3735 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3736 					TALLOC_CTX *mem_ctx, int argc,
3737 					const char **argv)
3738 {
3739 	WERROR werror;
3740 	uint32_t count, level = 1, i;
3741 	union spoolss_MonitorInfo *info;
3742 
3743 	/* Parse the command arguments */
3744 
3745 	if (argc > 2) {
3746 		printf("Usage: %s [level]\n", argv[0]);
3747 		return WERR_OK;
3748 	}
3749 
3750 	if (argc == 2) {
3751 		level = atoi(argv[1]);
3752 	}
3753 
3754 	/* Enumerate Print Monitors */
3755 
3756 	werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3757 					     cli->srv_name_slash,
3758 					     level,
3759 					     0,
3760 					     &count,
3761 					     &info);
3762 	if (!W_ERROR_IS_OK(werror)) {
3763 		goto done;
3764 	}
3765 
3766 	/* Display output */
3767 
3768 	for (i = 0; i < count; i++) {
3769 		switch (level) {
3770 		case 1:
3771 			display_monitor1(&info[i].info1);
3772 			break;
3773 		case 2:
3774 			display_monitor2(&info[i].info2);
3775 			break;
3776 		}
3777 	}
3778 
3779  done:
3780 	return werror;
3781 }
3782 
cmd_spoolss_create_printer_ic(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3783 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3784 					    TALLOC_CTX *mem_ctx, int argc,
3785 					    const char **argv)
3786 {
3787 	WERROR result;
3788 	NTSTATUS status;
3789 	struct policy_handle handle, gdi_handle;
3790 	const char *printername;
3791 	struct spoolss_DevmodeContainer devmode_ctr;
3792 	struct dcerpc_binding_handle *b = cli->binding_handle;
3793 
3794 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3795 
3796 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3797 					       printername,
3798 					       SEC_FLAG_MAXIMUM_ALLOWED,
3799 					       &handle);
3800 	if (!W_ERROR_IS_OK(result)) {
3801 		return result;
3802 	}
3803 
3804 	ZERO_STRUCT(devmode_ctr);
3805 
3806 	status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3807 						&handle,
3808 						&gdi_handle,
3809 						&devmode_ctr,
3810 						&result);
3811 	if (!NT_STATUS_IS_OK(status)) {
3812 		result = ntstatus_to_werror(status);
3813 		goto done;
3814 	}
3815 	if (!W_ERROR_IS_OK(result)) {
3816 		goto done;
3817 	}
3818 
3819  done:
3820 	if (is_valid_policy_hnd(&gdi_handle)) {
3821 		WERROR _result;
3822 		dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3823 	}
3824 	if (is_valid_policy_hnd(&handle)) {
3825 		WERROR _result;
3826 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3827 	}
3828 
3829 	return result;
3830 }
3831 
cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3832 static WERROR cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client *cli,
3833 							TALLOC_CTX *mem_ctx, int argc,
3834 							const char **argv)
3835 {
3836 	WERROR result;
3837 	NTSTATUS status;
3838 	struct policy_handle handle, gdi_handle;
3839 	const char *printername;
3840 	struct spoolss_DevmodeContainer devmode_ctr;
3841 	struct dcerpc_binding_handle *b = cli->binding_handle;
3842 	DATA_BLOB in,out;
3843 	uint32_t count = 0;
3844 
3845 	RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3846 
3847 	result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3848 					       printername,
3849 					       SEC_FLAG_MAXIMUM_ALLOWED,
3850 					       &handle);
3851 	if (!W_ERROR_IS_OK(result)) {
3852 		return result;
3853 	}
3854 
3855 	ZERO_STRUCT(devmode_ctr);
3856 
3857 	status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3858 						&handle,
3859 						&gdi_handle,
3860 						&devmode_ctr,
3861 						&result);
3862 	if (!NT_STATUS_IS_OK(status)) {
3863 		result = ntstatus_to_werror(status);
3864 		goto done;
3865 	}
3866 	if (!W_ERROR_IS_OK(result)) {
3867 		goto done;
3868 	}
3869 
3870 	in = data_blob_string_const("");
3871 	out = data_blob_talloc_zero(mem_ctx, 4);
3872 
3873 	status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3874 							 &gdi_handle,
3875 							 in.data,
3876 							 in.length,
3877 							 out.data,
3878 							 out.length,
3879 							 0, /* ul */
3880 							 &result);
3881 	if (!NT_STATUS_IS_OK(status)) {
3882 		result = ntstatus_to_werror(status);
3883 		goto done;
3884 	}
3885 	if (!W_ERROR_IS_OK(result)) {
3886 		goto done;
3887 	}
3888 
3889 	count = IVAL(out.data, 0);
3890 
3891 	out = data_blob_talloc_zero(mem_ctx,
3892 				    count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
3893 
3894 	status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3895 							 &gdi_handle,
3896 							 in.data,
3897 							 in.length,
3898 							 out.data,
3899 							 out.length,
3900 							 0, /* ul */
3901 							 &result);
3902 	if (!NT_STATUS_IS_OK(status)) {
3903 		result = ntstatus_to_werror(status);
3904 		goto done;
3905 	}
3906 	if (!W_ERROR_IS_OK(result)) {
3907 		goto done;
3908 	}
3909 
3910 	{
3911 		enum ndr_err_code ndr_err;
3912 		struct UNIVERSAL_FONT_ID_ctr r;
3913 
3914 		ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
3915 			(ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
3916 		if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3917 			NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
3918 		}
3919 	}
3920 
3921  done:
3922 	if (is_valid_policy_hnd(&gdi_handle)) {
3923 		WERROR _result;
3924 		dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3925 	}
3926 	if (is_valid_policy_hnd(&handle)) {
3927 		WERROR _result;
3928 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3929 	}
3930 
3931 	return result;
3932 }
3933 
cmd_spoolss_get_core_printer_drivers(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3934 static WERROR cmd_spoolss_get_core_printer_drivers(struct rpc_pipe_client *cli,
3935 						   TALLOC_CTX *mem_ctx, int argc,
3936 						   const char **argv)
3937 {
3938 	NTSTATUS status;
3939 	HRESULT result;
3940 	struct dcerpc_binding_handle *b = cli->binding_handle;
3941 	const char *architecture = SPOOLSS_ARCHITECTURE_x64;
3942 	struct spoolss_CorePrinterDriver core_printer_drivers;
3943 	DATA_BLOB blob;
3944 	bool ok;
3945 	int i;
3946 	uint32_t count;
3947 	const char **array;
3948 
3949 	if (argc == 1) {
3950 		count = 1;
3951 		array = talloc_zero_array(mem_ctx, const char *, count + 1);
3952 		if (array == NULL) {
3953 			return WERR_NOT_ENOUGH_MEMORY;
3954 		}
3955 		array[0] = talloc_strdup(array, SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
3956 		if (array[0] == NULL) {
3957 			return WERR_NOT_ENOUGH_MEMORY;
3958 		}
3959 	} else {
3960 		count = argc -1;
3961 		array = talloc_zero_array(mem_ctx, const char *, count + 1);
3962 		if (array == NULL) {
3963 			return WERR_NOT_ENOUGH_MEMORY;
3964 		}
3965 		for (i = 0; i < argc - 1; i++) {
3966 			array[i] = talloc_strdup(array, argv[i + 1]);
3967 			if (array[i] == NULL) {
3968 				return WERR_NOT_ENOUGH_MEMORY;
3969 			}
3970 		}
3971 	}
3972 
3973 	ok = push_reg_multi_sz(mem_ctx, &blob, array);
3974 	if (!ok) {
3975 		return WERR_NOT_ENOUGH_MEMORY;
3976 	}
3977 
3978 	status = dcerpc_spoolss_GetCorePrinterDrivers(b, mem_ctx,
3979 						      cli->srv_name_slash,
3980 						      architecture,
3981 						      blob.length/2,
3982 						      (uint16_t *)blob.data,
3983 						      count,
3984 						      &core_printer_drivers,
3985 						      &result);
3986 	if (!NT_STATUS_IS_OK(status)) {
3987 		return ntstatus_to_werror(status);
3988 	}
3989 
3990 	if (!HRES_IS_OK(result)) {
3991 		return W_ERROR(WIN32_FROM_HRESULT(result));
3992 	}
3993 
3994 	return WERR_OK;
3995 }
3996 
cmd_spoolss_enum_permachineconnections(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)3997 static WERROR cmd_spoolss_enum_permachineconnections(struct rpc_pipe_client *cli,
3998 						     TALLOC_CTX *mem_ctx, int argc,
3999 						     const char **argv)
4000 {
4001 	NTSTATUS status;
4002 	WERROR result;
4003 	struct dcerpc_binding_handle *b = cli->binding_handle;
4004 	const char *servername = cli->srv_name_slash;
4005 	DATA_BLOB in = data_blob_null;
4006 	struct spoolss_PrinterInfo4 *info;
4007 	uint32_t needed, count;
4008 
4009 	if (argc > 2) {
4010 		printf("usage: %s [servername]\n", argv[0]);
4011 		return WERR_OK;
4012 	}
4013 
4014 	if (argc > 1) {
4015 		servername = argv[1];
4016 	}
4017 
4018 	status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
4019 							  servername,
4020 							  &in,
4021 							  in.length,
4022 							  &count,
4023 							  &info,
4024 							  &needed,
4025 							  &result);
4026 	if (!NT_STATUS_IS_OK(status)) {
4027 		return ntstatus_to_werror(status);
4028 	}
4029 
4030 	if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
4031 		in = data_blob_talloc_zero(mem_ctx, needed);
4032 		status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
4033 								  servername,
4034 								  &in,
4035 								  in.length,
4036 								  &count,
4037 								  &info,
4038 								  &needed,
4039 								  &result);
4040 		if (!NT_STATUS_IS_OK(status)) {
4041 			return ntstatus_to_werror(status);
4042 		}
4043 	}
4044 
4045 	return result;
4046 }
4047 
cmd_spoolss_add_permachineconnection(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)4048 static WERROR cmd_spoolss_add_permachineconnection(struct rpc_pipe_client *cli,
4049 						   TALLOC_CTX *mem_ctx, int argc,
4050 						   const char **argv)
4051 {
4052 	NTSTATUS status;
4053 	WERROR result;
4054 	struct dcerpc_binding_handle *b = cli->binding_handle;
4055 	const char *servername = cli->srv_name_slash;
4056 	const char *printername = "Microsoft Print to PDF";
4057 	const char *printserver = "samba.org";
4058 	const char *provider = ""; /* refers to Win32spl.dll then */
4059 	const char *composed_printername;
4060 
4061 	if (argc > 5) {
4062 		printf("usage: %s [servername] [printername] [printserver] [provider]\n", argv[0]);
4063 		return WERR_OK;
4064 	}
4065 
4066 	if (argc > 1) {
4067 		servername = argv[1];
4068 	}
4069 	if (argc > 2) {
4070 		printername = argv[2];
4071 	}
4072 	if (argc > 3) {
4073 		printserver = argv[3];
4074 	}
4075 	if (argc > 4) {
4076 		provider = argv[4];
4077 	}
4078 
4079 	composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4080 			printername);
4081 	if (composed_printername == NULL) {
4082 		return WERR_NOT_ENOUGH_MEMORY;
4083 	}
4084 	status = dcerpc_spoolss_AddPerMachineConnection(b, mem_ctx,
4085 							servername,
4086 							composed_printername,
4087 							printserver,
4088 							provider,
4089 							&result);
4090 	if (!NT_STATUS_IS_OK(status)) {
4091 		return ntstatus_to_werror(status);
4092 	}
4093 
4094 	return result;
4095 }
4096 
cmd_spoolss_del_permachineconnection(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)4097 static WERROR cmd_spoolss_del_permachineconnection(struct rpc_pipe_client *cli,
4098 						   TALLOC_CTX *mem_ctx, int argc,
4099 						   const char **argv)
4100 {
4101 	NTSTATUS status;
4102 	WERROR result;
4103 	struct dcerpc_binding_handle *b = cli->binding_handle;
4104 	const char *servername = cli->srv_name_slash;
4105 	const char *printername = "Microsoft Print to PDF";
4106 	const char *composed_printername;
4107 
4108 	if (argc > 3) {
4109 		printf("usage: %s [servername] [printername]\n", argv[0]);
4110 		return WERR_OK;
4111 	}
4112 
4113 	if (argc > 1) {
4114 		servername = argv[1];
4115 	}
4116 	if (argc > 2) {
4117 		printername = argv[2];
4118 	}
4119 
4120 	composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4121 			printername);
4122 	if (composed_printername == NULL) {
4123 		return WERR_NOT_ENOUGH_MEMORY;
4124 	}
4125 
4126 	status = dcerpc_spoolss_DeletePerMachineConnection(b, mem_ctx,
4127 							   servername,
4128 							   composed_printername,
4129 							   &result);
4130 	if (!NT_STATUS_IS_OK(status)) {
4131 		return ntstatus_to_werror(status);
4132 	}
4133 
4134 	return result;
4135 }
4136 
4137 /* List of commands exported by this module */
4138 struct cmd_set spoolss_commands[] = {
4139 
4140 	{
4141 		.name = "SPOOLSS",
4142 	},
4143 
4144 	{
4145 		.name               = "adddriver",
4146 		.returntype         = RPC_RTYPE_WERROR,
4147 		.ntfn               = NULL,
4148 		.wfn                = cmd_spoolss_addprinterdriver,
4149 		.table              = &ndr_table_spoolss,
4150 		.rpc_pipe           = NULL,
4151 		.description        = "Add a print driver",
4152 		.usage              = "",
4153 		.use_netlogon_creds = false,
4154 	},
4155 	{
4156 		.name               = "addprinter",
4157 		.returntype         = RPC_RTYPE_WERROR,
4158 		.ntfn               = NULL,
4159 		.wfn                = cmd_spoolss_addprinterex,
4160 		.table              = &ndr_table_spoolss,
4161 		.rpc_pipe           = NULL,
4162 		.description        = "Add a printer",
4163 		.usage              = "",
4164 	},
4165 	{
4166 		.name               = "deldriver",
4167 		.returntype         = RPC_RTYPE_WERROR,
4168 		.ntfn               = NULL,
4169 		.wfn                = cmd_spoolss_deletedriver,
4170 		.table              = &ndr_table_spoolss,
4171 		.rpc_pipe           = NULL,
4172 		.description        = "Delete a printer driver",
4173 		.usage              = "",
4174 	},
4175 	{
4176 		.name               = "deldriverex",
4177 		.returntype         = RPC_RTYPE_WERROR,
4178 		.ntfn               = NULL,
4179 		.wfn                = cmd_spoolss_deletedriverex,
4180 		.table              = &ndr_table_spoolss,
4181 		.rpc_pipe           = NULL,
4182 		.description        = "Delete a printer driver with files",
4183 		.usage              = "",
4184 	},
4185 	{
4186 		.name               = "enumdata",
4187 		.returntype         = RPC_RTYPE_WERROR,
4188 		.ntfn               = NULL,
4189 		.wfn                = cmd_spoolss_enum_data,
4190 		.table              = &ndr_table_spoolss,
4191 		.rpc_pipe           = NULL,
4192 		.description        = "Enumerate printer data",
4193 		.usage              = "",
4194 	},
4195 	{
4196 		.name               = "enumdataex",
4197 		.returntype         = RPC_RTYPE_WERROR,
4198 		.ntfn               = NULL,
4199 		.wfn                = cmd_spoolss_enum_data_ex,
4200 		.table              = &ndr_table_spoolss,
4201 		.rpc_pipe           = NULL,
4202 		.description        = "Enumerate printer data for a key",
4203 		.usage              = "",
4204 	},
4205 	{
4206 		.name               = "enumkey",
4207 		.returntype         = RPC_RTYPE_WERROR,
4208 		.ntfn               = NULL,
4209 		.wfn                = cmd_spoolss_enum_printerkey,
4210 		.table              = &ndr_table_spoolss,
4211 		.rpc_pipe           = NULL,
4212 		.description        = "Enumerate printer keys",
4213 		.usage              = "",
4214 	},
4215 	{
4216 		.name               = "enumjobs",
4217 		.returntype         = RPC_RTYPE_WERROR,
4218 		.ntfn               = NULL,
4219 		.wfn                = cmd_spoolss_enum_jobs,
4220 		.table              = &ndr_table_spoolss,
4221 		.rpc_pipe           = NULL,
4222 		.description        = "Enumerate print jobs",
4223 		.usage              = "",
4224 	},
4225 	{
4226 		.name               = "getjob",
4227 		.returntype         = RPC_RTYPE_WERROR,
4228 		.ntfn               = NULL,
4229 		.wfn                = cmd_spoolss_get_job,
4230 		.table              = &ndr_table_spoolss,
4231 		.rpc_pipe           = NULL,
4232 		.description        = "Get print job",
4233 		.usage              = "",
4234 	},
4235 	{
4236 		.name               = "setjob",
4237 		.returntype         = RPC_RTYPE_WERROR,
4238 		.ntfn               = NULL,
4239 		.wfn                = cmd_spoolss_set_job,
4240 		.table              = &ndr_table_spoolss,
4241 		.rpc_pipe           = NULL,
4242 		.description        = "Set print job",
4243 		.usage              = "",
4244 	},
4245 	{
4246 		.name               = "enumports",
4247 		.returntype         = RPC_RTYPE_WERROR,
4248 		.ntfn               = NULL,
4249 		.wfn                = cmd_spoolss_enum_ports,
4250 		.table              = &ndr_table_spoolss,
4251 		.rpc_pipe           = NULL,
4252 		.description        = "Enumerate printer ports",
4253 		.usage              = "",
4254 	},
4255 	{
4256 		.name               = "enumdrivers",
4257 		.returntype         = RPC_RTYPE_WERROR,
4258 		.ntfn               = NULL,
4259 		.wfn                = cmd_spoolss_enum_drivers,
4260 		.table              = &ndr_table_spoolss,
4261 		.rpc_pipe           = NULL,
4262 		.description        = "Enumerate installed printer drivers",
4263 		.usage              = "",
4264 	},
4265 	{
4266 		.name               = "enumprinters",
4267 		.returntype         = RPC_RTYPE_WERROR,
4268 		.ntfn               = NULL,
4269 		.wfn                = cmd_spoolss_enum_printers,
4270 		.table              = &ndr_table_spoolss,
4271 		.rpc_pipe           = NULL,
4272 		.description        = "Enumerate printers",
4273 		.usage              = "",
4274 	},
4275 	{
4276 		.name               = "getdata",
4277 		.returntype         = RPC_RTYPE_WERROR,
4278 		.ntfn               = NULL,
4279 		.wfn                = cmd_spoolss_getprinterdata,
4280 		.table              = &ndr_table_spoolss,
4281 		.rpc_pipe           = NULL,
4282 		.description        = "Get print driver data",
4283 		.usage              = "",
4284 	},
4285 	{
4286 		.name               = "getdataex",
4287 		.returntype         = RPC_RTYPE_WERROR,
4288 		.ntfn               = NULL,
4289 		.wfn                = cmd_spoolss_getprinterdataex,
4290 		.table              = &ndr_table_spoolss,
4291 		.rpc_pipe           = NULL,
4292 		.description        = "Get printer driver data with keyname",
4293 		.usage              = "",
4294 	},
4295 	{
4296 		.name               = "getdriver",
4297 		.returntype         = RPC_RTYPE_WERROR,
4298 		.ntfn               = NULL,
4299 		.wfn                = cmd_spoolss_getdriver,
4300 		.table              = &ndr_table_spoolss,
4301 		.rpc_pipe           = NULL,
4302 		.description        = "Get print driver information",
4303 		.usage              = "",
4304 	},
4305 	{
4306 		.name               = "getdriverdir",
4307 		.returntype         = RPC_RTYPE_WERROR,
4308 		.ntfn               = NULL,
4309 		.wfn                = cmd_spoolss_getdriverdir,
4310 		.table              = &ndr_table_spoolss,
4311 		.rpc_pipe           = NULL,
4312 		.description        = "Get print driver upload directory",
4313 		.usage              = "",
4314 	},
4315 	{
4316 		.name               = "getdriverpackagepath",
4317 		.returntype         = RPC_RTYPE_WERROR,
4318 		.ntfn               = NULL,
4319 		.wfn                = cmd_spoolss_getdriverpackagepath,
4320 		.table              = &ndr_table_spoolss,
4321 		.rpc_pipe           = NULL,
4322 		.description        = "Get print driver package download directory",
4323 		.usage              = "",
4324 	},
4325 	{
4326 		.name               = "getprinter",
4327 		.returntype         = RPC_RTYPE_WERROR,
4328 		.ntfn               = NULL,
4329 		.wfn                = cmd_spoolss_getprinter,
4330 		.table              = &ndr_table_spoolss,
4331 		.rpc_pipe           = NULL,
4332 		.description        = "Get printer info",
4333 		.usage              = "",
4334 	},
4335 	{
4336 		.name               = "openprinter",
4337 		.returntype         = RPC_RTYPE_WERROR,
4338 		.ntfn               = NULL,
4339 		.wfn                = cmd_spoolss_open_printer,
4340 		.table              = &ndr_table_spoolss,
4341 		.rpc_pipe           = NULL,
4342 		.description        = "Open printer handle",
4343 		.usage              = "",
4344 	},
4345 	{
4346 		.name               = "openprinter_ex",
4347 		.returntype         = RPC_RTYPE_WERROR,
4348 		.ntfn               = NULL,
4349 		.wfn                = cmd_spoolss_open_printer_ex,
4350 		.table              = &ndr_table_spoolss,
4351 		.rpc_pipe           = NULL,
4352 		.description        = "Open printer handle",
4353 		.usage              = "",
4354 	},
4355 	{
4356 		.name               = "setdriver",
4357 		.returntype         = RPC_RTYPE_WERROR,
4358 		.ntfn               = NULL,
4359 		.wfn                = cmd_spoolss_setdriver,
4360 		.table              = &ndr_table_spoolss,
4361 		.rpc_pipe           = NULL,
4362 		.description        = "Set printer driver",
4363 		.usage              = "",
4364 	},
4365 	{
4366 		.name               = "getprintprocdir",
4367 		.returntype         = RPC_RTYPE_WERROR,
4368 		.ntfn               = NULL,
4369 		.wfn                = cmd_spoolss_getprintprocdir,
4370 		.table              = &ndr_table_spoolss,
4371 		.rpc_pipe           = NULL,
4372 		.description        = "Get print processor directory",
4373 		.usage              = "",
4374 	},
4375 	{
4376 		.name               = "addform",
4377 		.returntype         = RPC_RTYPE_WERROR,
4378 		.ntfn               = NULL,
4379 		.wfn                = cmd_spoolss_addform,
4380 		.table              = &ndr_table_spoolss,
4381 		.rpc_pipe           = NULL,
4382 		.description        = "Add form",
4383 		.usage              = "",
4384 	},
4385 	{
4386 		.name               = "setform",
4387 		.returntype         = RPC_RTYPE_WERROR,
4388 		.ntfn               = NULL,
4389 		.wfn                = cmd_spoolss_setform,
4390 		.table              = &ndr_table_spoolss,
4391 		.rpc_pipe           = NULL,
4392 		.description        = "Set form",
4393 		.usage              = "",
4394 	},
4395 	{
4396 		.name               = "getform",
4397 		.returntype         = RPC_RTYPE_WERROR,
4398 		.ntfn               = NULL,
4399 		.wfn                = cmd_spoolss_getform,
4400 		.table              = &ndr_table_spoolss,
4401 		.rpc_pipe           = NULL,
4402 		.description        = "Get form",
4403 		.usage              = "",
4404 	},
4405 	{
4406 		.name               = "deleteform",
4407 		.returntype         = RPC_RTYPE_WERROR,
4408 		.ntfn               = NULL,
4409 		.wfn                = cmd_spoolss_deleteform,
4410 		.table              = &ndr_table_spoolss,
4411 		.rpc_pipe           = NULL,
4412 		.description        = "Delete form",
4413 		.usage              = "",
4414 	},
4415 	{
4416 		.name               = "enumforms",
4417 		.returntype         = RPC_RTYPE_WERROR,
4418 		.ntfn               = NULL,
4419 		.wfn                = cmd_spoolss_enum_forms,
4420 		.table              = &ndr_table_spoolss,
4421 		.rpc_pipe           = NULL,
4422 		.description        = "Enumerate forms",
4423 		.usage              = "",
4424 	},
4425 	{
4426 		.name               = "setprinter",
4427 		.returntype         = RPC_RTYPE_WERROR,
4428 		.ntfn               = NULL,
4429 		.wfn                = cmd_spoolss_setprinter,
4430 		.table              = &ndr_table_spoolss,
4431 		.rpc_pipe           = NULL,
4432 		.description        = "Set printer comment",
4433 		.usage              = "",
4434 	},
4435 	{
4436 		.name               = "setprintername",
4437 		.returntype         = RPC_RTYPE_WERROR,
4438 		.ntfn               = NULL,
4439 		.wfn                = cmd_spoolss_setprintername,
4440 		.table              = &ndr_table_spoolss,
4441 		.rpc_pipe           = NULL,
4442 		.description        = "Set printername",
4443 		.usage              = "",
4444 	},
4445 	{
4446 		.name               = "setprinterdata",
4447 		.returntype         = RPC_RTYPE_WERROR,
4448 		.ntfn               = NULL,
4449 		.wfn                = cmd_spoolss_setprinterdata,
4450 		.table              = &ndr_table_spoolss,
4451 		.rpc_pipe           = NULL,
4452 		.description        = "Set REG_SZ printer data",
4453 		.usage              = "",
4454 	},
4455 	{
4456 		.name               = "rffpcnex",
4457 		.returntype         = RPC_RTYPE_WERROR,
4458 		.ntfn               = NULL,
4459 		.wfn                = cmd_spoolss_rffpcnex,
4460 		.table              = &ndr_table_spoolss,
4461 		.rpc_pipe           = NULL,
4462 		.description        = "Rffpcnex test",
4463 		.usage              = "",
4464 	},
4465 	{
4466 		.name               = "printercmp",
4467 		.returntype         = RPC_RTYPE_WERROR,
4468 		.ntfn               = NULL,
4469 		.wfn                = cmd_spoolss_printercmp,
4470 		.table              = &ndr_table_spoolss,
4471 		.rpc_pipe           = NULL,
4472 		.description        = "Printer comparison test",
4473 		.usage              = "",
4474 	},
4475 	{
4476 		.name               = "enumprocs",
4477 		.returntype         = RPC_RTYPE_WERROR,
4478 		.ntfn               = NULL,
4479 		.wfn                = cmd_spoolss_enum_procs,
4480 		.table              = &ndr_table_spoolss,
4481 		.rpc_pipe           = NULL,
4482 		.description        = "Enumerate Print Processors",
4483 		.usage              = "",
4484 	},
4485 	{
4486 		.name               = "enumprocdatatypes",
4487 		.returntype         = RPC_RTYPE_WERROR,
4488 		.ntfn               = NULL,
4489 		.wfn                = cmd_spoolss_enum_proc_data_types,
4490 		.table              = &ndr_table_spoolss,
4491 		.rpc_pipe           = NULL,
4492 		.description        = "Enumerate Print Processor Data Types",
4493 		.usage              = "",
4494 	},
4495 	{
4496 		.name               = "enummonitors",
4497 		.returntype         = RPC_RTYPE_WERROR,
4498 		.ntfn               = NULL,
4499 		.wfn                = cmd_spoolss_enum_monitors,
4500 		.table              = &ndr_table_spoolss,
4501 		.rpc_pipe           = NULL,
4502 		.description        = "Enumerate Print Monitors",
4503 		.usage              = "",
4504 	},
4505 	{
4506 		.name               = "createprinteric",
4507 		.returntype         = RPC_RTYPE_WERROR,
4508 		.ntfn               = NULL,
4509 		.wfn                = cmd_spoolss_create_printer_ic,
4510 		.table              = &ndr_table_spoolss,
4511 		.rpc_pipe           = NULL,
4512 		.description        = "Create Printer IC",
4513 		.usage              = "",
4514 	},
4515 	{
4516 		.name               = "playgdiscriptonprinteric",
4517 		.returntype         = RPC_RTYPE_WERROR,
4518 		.ntfn               = NULL,
4519 		.wfn                = cmd_spoolss_play_gdi_script_on_printer_ic,
4520 		.table              = &ndr_table_spoolss,
4521 		.rpc_pipe           = NULL,
4522 		.description        = "Create Printer IC",
4523 		.usage              = "",
4524 	},
4525 	{
4526 		.name               = "getcoreprinterdrivers",
4527 		.returntype         = RPC_RTYPE_WERROR,
4528 		.ntfn               = NULL,
4529 		.wfn                = cmd_spoolss_get_core_printer_drivers,
4530 		.table              = &ndr_table_spoolss,
4531 		.rpc_pipe           = NULL,
4532 		.description        = "Get CorePrinterDriver",
4533 		.usage              = "",
4534 	},
4535 	{
4536 		.name               = "enumpermachineconnections",
4537 		.returntype         = RPC_RTYPE_WERROR,
4538 		.ntfn               = NULL,
4539 		.wfn                = cmd_spoolss_enum_permachineconnections,
4540 		.table              = &ndr_table_spoolss,
4541 		.rpc_pipe           = NULL,
4542 		.description        = "Enumerate Per Machine Connections",
4543 		.usage              = "",
4544 	},
4545 	{
4546 		.name               = "addpermachineconnection",
4547 		.returntype         = RPC_RTYPE_WERROR,
4548 		.ntfn               = NULL,
4549 		.wfn                = cmd_spoolss_add_permachineconnection,
4550 		.table              = &ndr_table_spoolss,
4551 		.rpc_pipe           = NULL,
4552 		.description        = "Add Per Machine Connection",
4553 		.usage              = "",
4554 	},
4555 	{
4556 		.name               = "delpermachineconnection",
4557 		.returntype         = RPC_RTYPE_WERROR,
4558 		.ntfn               = NULL,
4559 		.wfn                = cmd_spoolss_del_permachineconnection,
4560 		.table              = &ndr_table_spoolss,
4561 		.rpc_pipe           = NULL,
4562 		.description        = "Delete Per Machine Connection",
4563 		.usage              = "",
4564 	},
4565 	{
4566 		.name = NULL,
4567 	},
4568 };
4569