gpo: Add CSE for applying smb.conf
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blob85062541da222b8236ccf8e70d49f140c40d6760
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
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
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.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
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 #include "lib/util/smb_strtox.h"
39 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
40 { \
41 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
42 _cli->srv_name_slash, _arg); \
43 W_ERROR_HAVE_NO_MEMORY(_printername); \
46 /* The version int is used by getdrivers. Note that
47 all architecture strings that support mutliple
48 versions must be grouped together since enumdrivers
49 uses this property to prevent issuing multiple
50 enumdriver calls for the same arch */
53 static const struct print_architecture_table_node archi_table[]= {
55 {"Windows 4.0", "WIN40", 0 },
56 {"Windows NT x86", "W32X86", 2 },
57 {"Windows NT x86", "W32X86", 3 },
58 {"Windows NT R4000", "W32MIPS", 2 },
59 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
60 {"Windows NT PowerPC", "W32PPC", 2 },
61 {"Windows IA64", "IA64", 3 },
62 {"Windows x64", "x64", 3 },
63 {NULL, "", -1 }
66 /**
67 * @file
69 * rpcclient module for SPOOLSS rpc pipe.
71 * This generally just parses and checks command lines, and then calls
72 * a cli_spoolss function.
73 **/
75 /****************************************************************************
76 function to do the mapping between the long architecture name and
77 the short one.
78 ****************************************************************************/
80 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
82 int i=-1;
84 DEBUG(107,("Getting architecture dependent directory\n"));
85 do {
86 i++;
87 } while ( (archi_table[i].long_archi!=NULL ) &&
88 strcasecmp_m(long_archi, archi_table[i].long_archi) );
90 if (archi_table[i].long_archi==NULL) {
91 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
92 return NULL;
95 /* this might be client code - but shouldn't this be an fstrcpy etc? */
98 DEBUGADD(108,("index: [%d]\n", i));
99 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
100 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
102 return archi_table[i].short_archi;
105 /****************************************************************************
106 ****************************************************************************/
108 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
109 TALLOC_CTX *mem_ctx,
110 int argc, const char **argv)
112 WERROR werror;
113 struct policy_handle hnd;
114 uint32_t access_mask = PRINTER_ALL_ACCESS;
115 struct dcerpc_binding_handle *b = cli->binding_handle;
117 if (argc < 2) {
118 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
119 return WERR_OK;
122 if (argc >= 3) {
123 sscanf(argv[2], "%x", &access_mask);
126 /* Open the printer handle */
128 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
129 argv[1],
130 access_mask,
131 &hnd);
132 if (W_ERROR_IS_OK(werror)) {
133 printf("Printer %s opened successfully\n", argv[1]);
134 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
136 if (!W_ERROR_IS_OK(werror)) {
137 printf("Error closing printer handle! (%s)\n",
138 get_dos_error_msg(werror));
142 return werror;
145 /****************************************************************************
146 ****************************************************************************/
148 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
149 TALLOC_CTX *mem_ctx,
150 int argc, const char **argv)
152 WERROR werror;
153 struct policy_handle hnd;
154 uint32_t access_mask = PRINTER_ALL_ACCESS;
155 NTSTATUS status;
156 struct spoolss_DevmodeContainer devmode_ctr;
157 struct dcerpc_binding_handle *b = cli->binding_handle;
159 ZERO_STRUCT(devmode_ctr);
161 if (argc < 2) {
162 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
163 return WERR_OK;
166 if (argc >= 3) {
167 sscanf(argv[2], "%x", &access_mask);
170 /* Open the printer handle */
172 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
173 argv[1],
174 NULL,
175 devmode_ctr,
176 access_mask,
177 &hnd,
178 &werror);
179 if (!NT_STATUS_IS_OK(status)) {
180 return ntstatus_to_werror(status);
182 if (W_ERROR_IS_OK(werror)) {
183 printf("Printer %s opened successfully\n", argv[1]);
184 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
186 if (!W_ERROR_IS_OK(werror)) {
187 printf("Error closing printer handle! (%s)\n",
188 get_dos_error_msg(werror));
192 return werror;
195 /****************************************************************************
196 ****************************************************************************/
198 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
200 if (!r)
201 return;
203 printf("\tprintername:[%s]\n", r->printername);
204 printf("\tservername:[%s]\n", r->servername);
205 printf("\tcjobs:[0x%x]\n", r->cjobs);
206 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
207 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
208 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
209 r->time.day, r->time.day_of_week);
210 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
211 r->time.second, r->time.millisecond);
213 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
214 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
216 printf("\tversion:[0x%x]\n", r->version);
217 printf("\tfree_build:[0x%x]\n", r->free_build);
218 printf("\tspooling:[0x%x]\n", r->spooling);
219 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
220 printf("\tsession_counter:[0x%x]\n", r->session_counter);
221 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
222 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
223 printf("\tjob_error:[0x%x]\n", r->job_error);
224 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
225 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
226 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
227 printf("\tchange_id:[0x%x]\n", r->change_id);
228 printf("\tlast_error: %s\n", win_errstr(r->last_error));
229 printf("\tstatus:[0x%x]\n", r->status);
230 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
231 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
232 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
233 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
234 printf("\tref_ic:[0x%x]\n", r->ref_ic);
235 printf("\treserved2:[0x%x]\n", r->reserved2);
236 printf("\treserved3:[0x%x]\n", r->reserved3);
238 printf("\n");
241 /****************************************************************************
242 ****************************************************************************/
244 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
246 printf("\tflags:[0x%x]\n", r->flags);
247 printf("\tname:[%s]\n", r->name);
248 printf("\tdescription:[%s]\n", r->description);
249 printf("\tcomment:[%s]\n", r->comment);
251 printf("\n");
254 /****************************************************************************
255 ****************************************************************************/
257 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
259 printf("\tservername:[%s]\n", r->servername);
260 printf("\tprintername:[%s]\n", r->printername);
261 printf("\tsharename:[%s]\n", r->sharename);
262 printf("\tportname:[%s]\n", r->portname);
263 printf("\tdrivername:[%s]\n", r->drivername);
264 printf("\tcomment:[%s]\n", r->comment);
265 printf("\tlocation:[%s]\n", r->location);
266 printf("\tsepfile:[%s]\n", r->sepfile);
267 printf("\tprintprocessor:[%s]\n", r->printprocessor);
268 printf("\tdatatype:[%s]\n", r->datatype);
269 printf("\tparameters:[%s]\n", r->parameters);
270 printf("\tattributes:[0x%x]\n", r->attributes);
271 printf("\tpriority:[0x%x]\n", r->priority);
272 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
273 printf("\tstarttime:[0x%x]\n", r->starttime);
274 printf("\tuntiltime:[0x%x]\n", r->untiltime);
275 printf("\tstatus:[0x%x]\n", r->status);
276 printf("\tcjobs:[0x%x]\n", r->cjobs);
277 printf("\taverageppm:[0x%x]\n", r->averageppm);
279 if (r->secdesc)
280 display_sec_desc(r->secdesc);
282 printf("\n");
285 /****************************************************************************
286 ****************************************************************************/
288 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
290 display_sec_desc(r->secdesc);
292 printf("\n");
295 /****************************************************************************
296 ****************************************************************************/
298 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
300 printf("\tservername:[%s]\n", r->servername);
301 printf("\tprintername:[%s]\n", r->printername);
302 printf("\tattributes:[0x%x]\n", r->attributes);
303 printf("\n");
306 /****************************************************************************
307 ****************************************************************************/
309 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
311 printf("\tprintername:[%s]\n", r->printername);
312 printf("\tportname:[%s]\n", r->portname);
313 printf("\tattributes:[0x%x]\n", r->attributes);
314 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
315 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
316 printf("\n");
319 /****************************************************************************
320 ****************************************************************************/
322 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
324 printf("\tstatus:[0x%x]\n", r->status);
325 printf("\n");
328 /****************************************************************************
329 ****************************************************************************/
331 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
333 printf("\tguid:[%s]\n", r->guid);
334 printf("\taction:[0x%x]\n", r->action);
335 printf("\n");
338 /****************************************************************************
339 ****************************************************************************/
341 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
342 TALLOC_CTX *mem_ctx,
343 int argc, const char **argv)
345 WERROR result;
346 uint32_t level = 1;
347 union spoolss_PrinterInfo *info;
348 uint32_t i, count;
349 const char *name;
350 uint32_t flags = PRINTER_ENUM_LOCAL;
352 if (argc > 4) {
353 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
354 return WERR_OK;
357 if (argc >= 2) {
358 level = atoi(argv[1]);
361 if (argc >= 3) {
362 name = argv[2];
363 } else {
364 name = cli->srv_name_slash;
367 if (argc == 4) {
368 flags = atoi(argv[3]);
371 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
372 flags,
373 name,
374 level,
376 &count,
377 &info);
378 if (W_ERROR_IS_OK(result)) {
380 if (!count) {
381 printf ("No printers returned.\n");
382 goto done;
385 for (i = 0; i < count; i++) {
386 switch (level) {
387 case 0:
388 display_print_info0(&info[i].info0);
389 break;
390 case 1:
391 display_print_info1(&info[i].info1);
392 break;
393 case 2:
394 display_print_info2(&info[i].info2);
395 break;
396 case 3:
397 display_print_info3(&info[i].info3);
398 break;
399 case 4:
400 display_print_info4(&info[i].info4);
401 break;
402 case 5:
403 display_print_info5(&info[i].info5);
404 break;
405 case 6:
406 display_print_info6(&info[i].info6);
407 break;
408 default:
409 printf("unknown info level %d\n", level);
410 goto done;
414 done:
416 return result;
419 /****************************************************************************
420 ****************************************************************************/
422 static void display_port_info_1(struct spoolss_PortInfo1 *r)
424 printf("\tPort Name:\t[%s]\n", r->port_name);
427 /****************************************************************************
428 ****************************************************************************/
430 static void display_port_info_2(struct spoolss_PortInfo2 *r)
432 printf("\tPort Name:\t[%s]\n", r->port_name);
433 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
434 printf("\tDescription:\t[%s]\n", r->description);
435 printf("\tPort Type:\t" );
436 if (r->port_type) {
437 int comma = 0; /* hack */
438 printf( "[" );
439 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
440 printf( "Read" );
441 comma = 1;
443 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
444 printf( "%sWrite", comma ? ", " : "" );
445 comma = 1;
447 /* These two have slightly different interpretations
448 on 95/98/ME but I'm disregarding that for now */
449 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
450 printf( "%sRedirected", comma ? ", " : "" );
451 comma = 1;
453 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
454 printf( "%sNet-Attached", comma ? ", " : "" );
456 printf( "]\n" );
457 } else {
458 printf( "[Unset]\n" );
460 printf("\tReserved:\t[%d]\n", r->reserved);
461 printf("\n");
464 /****************************************************************************
465 ****************************************************************************/
467 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
468 TALLOC_CTX *mem_ctx, int argc,
469 const char **argv)
471 WERROR result;
472 uint32_t level = 1;
473 uint32_t count;
474 union spoolss_PortInfo *info;
476 if (argc > 2) {
477 printf("Usage: %s [level]\n", argv[0]);
478 return WERR_OK;
481 if (argc == 2) {
482 level = atoi(argv[1]);
485 /* Enumerate ports */
487 result = rpccli_spoolss_enumports(cli, mem_ctx,
488 cli->srv_name_slash,
489 level,
491 &count,
492 &info);
493 if (W_ERROR_IS_OK(result)) {
494 int i;
496 for (i = 0; i < count; i++) {
497 switch (level) {
498 case 1:
499 display_port_info_1(&info[i].info1);
500 break;
501 case 2:
502 display_port_info_2(&info[i].info2);
503 break;
504 default:
505 printf("unknown info level %d\n", level);
506 break;
511 return result;
514 /****************************************************************************
515 ****************************************************************************/
517 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
518 TALLOC_CTX *mem_ctx,
519 int argc, const char **argv)
521 struct policy_handle pol;
522 WERROR result;
523 NTSTATUS status;
524 uint32_t info_level = 2;
525 union spoolss_PrinterInfo info;
526 struct spoolss_SetPrinterInfoCtr info_ctr;
527 struct spoolss_SetPrinterInfo2 info2;
528 const char *printername, *comment = NULL;
529 struct spoolss_DevmodeContainer devmode_ctr;
530 struct sec_desc_buf secdesc_ctr;
531 struct dcerpc_binding_handle *b = cli->binding_handle;
533 if (argc == 1 || argc > 3) {
534 printf("Usage: %s printername comment\n", argv[0]);
536 return WERR_OK;
539 /* Open a printer handle */
540 if (argc == 3) {
541 comment = argv[2];
544 ZERO_STRUCT(devmode_ctr);
545 ZERO_STRUCT(secdesc_ctr);
547 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
549 /* get a printer handle */
550 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
551 printername,
552 PRINTER_ALL_ACCESS,
553 &pol);
554 if (!W_ERROR_IS_OK(result))
555 goto done;
557 /* Get printer info */
558 result = rpccli_spoolss_getprinter(cli, mem_ctx,
559 &pol,
560 info_level,
562 &info);
563 if (!W_ERROR_IS_OK(result))
564 goto done;
567 /* Modify the comment. */
568 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
569 info2.comment = comment;
571 info_ctr.level = 2;
572 info_ctr.info.info2 = &info2;
574 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
575 &pol,
576 &info_ctr,
577 &devmode_ctr,
578 &secdesc_ctr,
579 0, /* command */
580 &result);
581 if (!NT_STATUS_IS_OK(status)) {
582 result = ntstatus_to_werror(status);
583 goto done;
585 if (W_ERROR_IS_OK(result))
586 printf("Success in setting comment.\n");
588 done:
589 if (is_valid_policy_hnd(&pol)) {
590 WERROR _result;
591 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
594 return result;
597 /****************************************************************************
598 ****************************************************************************/
600 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
601 TALLOC_CTX *mem_ctx,
602 int argc, const char **argv)
604 struct policy_handle pol;
605 WERROR result;
606 NTSTATUS status;
607 uint32_t info_level = 2;
608 union spoolss_PrinterInfo info;
609 const char *printername,
610 *new_printername = NULL;
611 struct spoolss_SetPrinterInfoCtr info_ctr;
612 struct spoolss_SetPrinterInfo2 info2;
613 struct spoolss_DevmodeContainer devmode_ctr;
614 struct sec_desc_buf secdesc_ctr;
615 struct dcerpc_binding_handle *b = cli->binding_handle;
617 ZERO_STRUCT(devmode_ctr);
618 ZERO_STRUCT(secdesc_ctr);
620 if (argc == 1 || argc > 3) {
621 printf("Usage: %s printername new_printername\n", argv[0]);
623 return WERR_OK;
626 /* Open a printer handle */
627 if (argc == 3) {
628 new_printername = argv[2];
631 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
633 /* get a printer handle */
634 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
635 printername,
636 PRINTER_ALL_ACCESS,
637 &pol);
638 if (!W_ERROR_IS_OK(result))
639 goto done;
641 /* Get printer info */
642 result = rpccli_spoolss_getprinter(cli, mem_ctx,
643 &pol,
644 info_level,
646 &info);
647 if (!W_ERROR_IS_OK(result))
648 goto done;
650 /* Modify the printername. */
651 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
652 info2.printername = new_printername;
654 info_ctr.level = 2;
655 info_ctr.info.info2 = &info2;
657 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
658 &pol,
659 &info_ctr,
660 &devmode_ctr,
661 &secdesc_ctr,
662 0, /* command */
663 &result);
664 if (!NT_STATUS_IS_OK(status)) {
665 result = ntstatus_to_werror(status);
666 goto done;
668 if (W_ERROR_IS_OK(result))
669 printf("Success in setting printername.\n");
671 done:
672 if (is_valid_policy_hnd(&pol)) {
673 WERROR _result;
674 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
677 return result;
680 /****************************************************************************
681 ****************************************************************************/
683 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
684 TALLOC_CTX *mem_ctx,
685 int argc, const char **argv)
687 struct policy_handle pol;
688 WERROR result;
689 uint32_t level = 1;
690 const char *printername;
691 union spoolss_PrinterInfo info;
692 struct dcerpc_binding_handle *b = cli->binding_handle;
694 if (argc == 1 || argc > 3) {
695 printf("Usage: %s <printername> [level]\n", argv[0]);
696 return WERR_OK;
699 /* Open a printer handle */
700 if (argc == 3) {
701 level = atoi(argv[2]);
704 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
706 /* get a printer handle */
708 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
709 printername,
710 SEC_FLAG_MAXIMUM_ALLOWED,
711 &pol);
712 if (!W_ERROR_IS_OK(result)) {
713 goto done;
716 /* Get printer info */
718 result = rpccli_spoolss_getprinter(cli, mem_ctx,
719 &pol,
720 level,
722 &info);
723 if (!W_ERROR_IS_OK(result)) {
724 goto done;
727 /* Display printer info */
728 switch (level) {
729 case 0:
730 display_print_info0(&info.info0);
731 break;
732 case 1:
733 display_print_info1(&info.info1);
734 break;
735 case 2:
736 display_print_info2(&info.info2);
737 break;
738 case 3:
739 display_print_info3(&info.info3);
740 break;
741 case 4:
742 display_print_info4(&info.info4);
743 break;
744 case 5:
745 display_print_info5(&info.info5);
746 break;
747 case 6:
748 display_print_info6(&info.info6);
749 break;
750 case 7:
751 display_print_info7(&info.info7);
752 break;
753 default:
754 printf("unknown info level %d\n", level);
755 break;
757 done:
758 if (is_valid_policy_hnd(&pol)) {
759 WERROR _result;
760 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
763 return result;
766 /****************************************************************************
767 ****************************************************************************/
769 static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
771 const char *text = NULL;
773 switch(type) {
774 case REG_DWORD:
775 if (blob.length >= sizeof(uint32_t)) {
776 printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
777 } else {
778 printf("%s: REG_DWORD: <invalid>\n", name);
780 break;
781 case REG_SZ:
782 pull_reg_sz(talloc_tos(), &blob, &text);
783 printf("%s: REG_SZ: %s\n", name, text ? text : "");
784 break;
785 case REG_BINARY: {
786 char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
787 size_t i, len;
788 printf("%s: REG_BINARY:", name);
789 len = strlen(hex);
790 for (i=0; i<len; i++) {
791 if (hex[i] == '\0') {
792 break;
794 if (i%40 == 0) {
795 putchar('\n');
797 putchar(hex[i]);
799 TALLOC_FREE(hex);
800 putchar('\n');
801 break;
803 case REG_MULTI_SZ: {
804 uint32_t i;
805 const char **values;
807 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
808 d_printf("pull_reg_multi_sz failed\n");
809 break;
812 printf("%s: REG_MULTI_SZ: \n", name);
813 for (i=0; values[i] != NULL; i++) {
814 d_printf("%s\n", values[i]);
816 TALLOC_FREE(values);
817 break;
819 default:
820 printf("%s: unknown type %d\n", name, type);
825 /****************************************************************************
826 ****************************************************************************/
828 static void display_printer_data(const char *v,
829 enum winreg_Type type,
830 uint8_t *data,
831 uint32_t length)
833 int i;
834 union spoolss_PrinterData r;
835 DATA_BLOB blob = data_blob_const(data, length);
836 WERROR result;
837 enum ndr_err_code ndr_err;
839 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
840 if (!W_ERROR_IS_OK(result)) {
841 return;
844 switch (type) {
845 case REG_DWORD:
846 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
847 break;
848 case REG_SZ:
849 printf("%s: REG_SZ: %s\n", v, r.string);
850 break;
851 case REG_BINARY: {
852 char *hex = hex_encode_talloc(NULL,
853 r.binary.data, r.binary.length);
854 size_t len;
855 printf("%s: REG_BINARY:", v);
856 len = strlen(hex);
857 for (i=0; i<len; i++) {
858 if (hex[i] == '\0') {
859 break;
861 if (i%40 == 0) {
862 putchar('\n');
864 putchar(hex[i]);
866 TALLOC_FREE(hex);
867 putchar('\n');
868 putchar('\n');
870 if (strequal(v, "OsVersion")) {
871 struct spoolss_OSVersion os;
872 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
873 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion);
874 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
875 // add output here;
876 printf("OsMajor: %u\n", os.major);
877 printf("OsMinor: %u\n", os.minor);
878 printf("OsBuild: %u\n", os.build);
879 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
882 if (strequal(v, "OsVersionEx")) {
883 struct spoolss_OSVersionEx os;
884 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
885 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersionEx);
886 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
887 printf("OsMajor: %u\n", os.major);
888 printf("OsMinor: %u\n", os.minor);
889 printf("OsBuild: %u\n", os.build);
890 printf("ServicePackMajor: %u\n", os.service_pack_major);
891 printf("ServicePackMinor: %u\n", os.service_pack_minor);
892 NDR_PRINT_DEBUG(spoolss_OSVersionEx, &os);
895 break;
897 case REG_MULTI_SZ:
898 printf("%s: REG_MULTI_SZ: ", v);
899 for (i=0; r.string_array[i] != NULL; i++) {
900 printf("%s ", r.string_array[i]);
902 printf("\n");
903 break;
904 default:
905 printf("%s: unknown type 0x%02x:\n", v, type);
906 break;
910 /****************************************************************************
911 ****************************************************************************/
913 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
914 TALLOC_CTX *mem_ctx,
915 int argc, const char **argv)
917 struct policy_handle pol;
918 WERROR result;
919 fstring printername;
920 const char *valuename;
921 enum winreg_Type type;
922 uint8_t *data;
923 uint32_t needed;
924 struct dcerpc_binding_handle *b = cli->binding_handle;
926 if (argc != 3) {
927 printf("Usage: %s <printername> <valuename>\n", argv[0]);
928 printf("<printername> of . queries print server\n");
929 return WERR_OK;
931 valuename = argv[2];
933 /* Open a printer handle */
935 if (strncmp(argv[1], ".", sizeof(".")) == 0)
936 fstrcpy(printername, cli->srv_name_slash);
937 else
938 slprintf(printername, sizeof(printername)-1, "%s\\%s",
939 cli->srv_name_slash, argv[1]);
941 /* get a printer handle */
943 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
944 printername,
945 SEC_FLAG_MAXIMUM_ALLOWED,
946 &pol);
947 if (!W_ERROR_IS_OK(result))
948 goto done;
950 /* Get printer info */
952 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
953 &pol,
954 valuename,
956 &type,
957 &needed,
958 &data);
959 if (!W_ERROR_IS_OK(result))
960 goto done;
962 /* Display printer data */
964 display_printer_data(valuename, type, data, needed);
966 done:
967 if (is_valid_policy_hnd(&pol)) {
968 WERROR _result;
969 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
972 return result;
975 /****************************************************************************
976 ****************************************************************************/
978 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
979 TALLOC_CTX *mem_ctx,
980 int argc, const char **argv)
982 struct policy_handle pol;
983 WERROR result;
984 NTSTATUS status;
985 fstring printername;
986 const char *valuename, *keyname;
988 enum winreg_Type type;
989 uint8_t *data = NULL;
990 uint32_t offered = 0;
991 uint32_t needed;
992 struct dcerpc_binding_handle *b = cli->binding_handle;
994 if (argc != 4) {
995 printf("Usage: %s <printername> <keyname> <valuename>\n",
996 argv[0]);
997 printf("<printername> of . queries print server\n");
998 return WERR_OK;
1000 valuename = argv[3];
1001 keyname = argv[2];
1003 /* Open a printer handle */
1005 if (strncmp(argv[1], ".", sizeof(".")) == 0)
1006 fstrcpy(printername, cli->srv_name_slash);
1007 else
1008 slprintf(printername, sizeof(printername)-1, "%s\\%s",
1009 cli->srv_name_slash, argv[1]);
1011 /* get a printer handle */
1013 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1014 printername,
1015 SEC_FLAG_MAXIMUM_ALLOWED,
1016 &pol);
1017 if (!W_ERROR_IS_OK(result))
1018 goto done;
1020 /* Get printer info */
1022 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1023 if (!data) {
1024 goto done;
1027 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1028 &pol,
1029 keyname,
1030 valuename,
1031 &type,
1032 data,
1033 offered,
1034 &needed,
1035 &result);
1036 if (!NT_STATUS_IS_OK(status)) {
1037 result = ntstatus_to_werror(status);
1038 goto done;
1040 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1041 offered = needed;
1042 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1043 if (!data) {
1044 goto done;
1046 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1047 &pol,
1048 keyname,
1049 valuename,
1050 &type,
1051 data,
1052 offered,
1053 &needed,
1054 &result);
1057 if (!NT_STATUS_IS_OK(status)) {
1058 result = ntstatus_to_werror(status);
1059 goto done;
1062 if (!W_ERROR_IS_OK(result))
1063 goto done;
1065 /* Display printer data */
1067 display_printer_data(valuename, type, data, needed);
1070 done:
1071 if (is_valid_policy_hnd(&pol)) {
1072 WERROR _result;
1073 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1076 return result;
1079 /****************************************************************************
1080 ****************************************************************************/
1082 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1084 if (!r) {
1085 return;
1088 printf("Printer Driver Info 1:\n");
1089 printf("\tDriver Name: [%s]\n", r->driver_name);
1090 printf("\n");
1093 /****************************************************************************
1094 ****************************************************************************/
1096 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1098 if (!r) {
1099 return;
1102 printf("Printer Driver Info 2:\n");
1103 printf("\tVersion: [%x]\n", r->version);
1104 printf("\tDriver Name: [%s]\n", r->driver_name);
1105 printf("\tArchitecture: [%s]\n", r->architecture);
1106 printf("\tDriver Path: [%s]\n", r->driver_path);
1107 printf("\tDatafile: [%s]\n", r->data_file);
1108 printf("\tConfigfile: [%s]\n", r->config_file);
1109 printf("\n");
1112 /****************************************************************************
1113 ****************************************************************************/
1115 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1117 int i;
1119 if (!r) {
1120 return;
1123 printf("Printer Driver Info 3:\n");
1124 printf("\tVersion: [%x]\n", r->version);
1125 printf("\tDriver Name: [%s]\n", r->driver_name);
1126 printf("\tArchitecture: [%s]\n", r->architecture);
1127 printf("\tDriver Path: [%s]\n", r->driver_path);
1128 printf("\tDatafile: [%s]\n", r->data_file);
1129 printf("\tConfigfile: [%s]\n", r->config_file);
1130 printf("\tHelpfile: [%s]\n", r->help_file);
1132 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1133 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1136 printf("\tMonitorname: [%s]\n", r->monitor_name);
1137 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1138 printf("\n");
1141 /****************************************************************************
1142 ****************************************************************************/
1144 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1146 int i;
1148 if (!r) {
1149 return;
1152 printf("Printer Driver Info 4:\n");
1153 printf("\tVersion: [%x]\n", r->version);
1154 printf("\tDriver Name: [%s]\n", r->driver_name);
1155 printf("\tArchitecture: [%s]\n", r->architecture);
1156 printf("\tDriver Path: [%s]\n", r->driver_path);
1157 printf("\tDatafile: [%s]\n", r->data_file);
1158 printf("\tConfigfile: [%s]\n", r->config_file);
1159 printf("\tHelpfile: [%s]\n", r->help_file);
1161 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1162 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1165 printf("\tMonitorname: [%s]\n", r->monitor_name);
1166 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1168 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1169 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1171 printf("\n");
1174 /****************************************************************************
1175 ****************************************************************************/
1177 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1179 if (!r) {
1180 return;
1183 printf("Printer Driver Info 5:\n");
1184 printf("\tVersion: [%x]\n", r->version);
1185 printf("\tDriver Name: [%s]\n", r->driver_name);
1186 printf("\tArchitecture: [%s]\n", r->architecture);
1187 printf("\tDriver Path: [%s]\n", r->driver_path);
1188 printf("\tDatafile: [%s]\n", r->data_file);
1189 printf("\tConfigfile: [%s]\n", r->config_file);
1190 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1191 printf("\tConfig Version: [0x%x]\n", r->config_version);
1192 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1193 printf("\n");
1196 /****************************************************************************
1197 ****************************************************************************/
1199 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1201 int i;
1203 if (!r) {
1204 return;
1207 printf("Printer Driver Info 6:\n");
1208 printf("\tVersion: [%x]\n", r->version);
1209 printf("\tDriver Name: [%s]\n", r->driver_name);
1210 printf("\tArchitecture: [%s]\n", r->architecture);
1211 printf("\tDriver Path: [%s]\n", r->driver_path);
1212 printf("\tDatafile: [%s]\n", r->data_file);
1213 printf("\tConfigfile: [%s]\n", r->config_file);
1214 printf("\tHelpfile: [%s]\n", r->help_file);
1216 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1217 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1220 printf("\tMonitorname: [%s]\n", r->monitor_name);
1221 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1223 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1224 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1227 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1228 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1229 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1230 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1231 printf("\tHardware ID: [%s]\n", r->hardware_id);
1232 printf("\tProvider: [%s]\n", r->provider);
1234 printf("\n");
1237 /****************************************************************************
1238 ****************************************************************************/
1240 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1242 int i;
1244 if (!r) {
1245 return;
1248 printf("Printer Driver Info 8:\n");
1249 printf("\tVersion: [%x]\n", r->version);
1250 printf("\tDriver Name: [%s]\n", r->driver_name);
1251 printf("\tArchitecture: [%s]\n", r->architecture);
1252 printf("\tDriver Path: [%s]\n", r->driver_path);
1253 printf("\tDatafile: [%s]\n", r->data_file);
1254 printf("\tConfigfile: [%s]\n", r->config_file);
1255 printf("\tHelpfile: [%s]\n", r->help_file);
1256 printf("\tMonitorname: [%s]\n", r->monitor_name);
1257 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1259 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1260 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1263 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1264 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1267 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1268 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1269 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1270 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1271 printf("\tHardware ID: [%s]\n", r->hardware_id);
1272 printf("\tProvider: [%s]\n", r->provider);
1273 printf("\tPrint Processor: [%s]\n", r->print_processor);
1274 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1275 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1276 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1278 printf("\tInf Path: [%s]\n", r->inf_path);
1279 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1280 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1281 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1283 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1284 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1285 (long long unsigned int)r->min_inbox_driver_ver_version);
1287 printf("\n");
1290 /****************************************************************************
1291 ****************************************************************************/
1293 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1294 TALLOC_CTX *mem_ctx,
1295 int argc, const char **argv)
1297 struct policy_handle pol;
1298 WERROR werror;
1299 uint32_t level = 3;
1300 const char *printername;
1301 uint32_t i;
1302 bool success = false;
1303 union spoolss_DriverInfo info;
1304 uint32_t server_major_version;
1305 uint32_t server_minor_version;
1306 struct dcerpc_binding_handle *b = cli->binding_handle;
1308 if ((argc == 1) || (argc > 3)) {
1309 printf("Usage: %s <printername> [level]\n", argv[0]);
1310 return WERR_OK;
1313 /* get the arguments need to open the printer handle */
1315 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1317 if (argc == 3) {
1318 level = atoi(argv[2]);
1321 /* Open a printer handle */
1323 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1324 printername,
1325 PRINTER_ACCESS_USE,
1326 &pol);
1327 if (!W_ERROR_IS_OK(werror)) {
1328 printf("Error opening printer handle for %s!\n", printername);
1329 return werror;
1332 /* loop through and print driver info level for each architecture */
1334 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1336 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1337 &pol,
1338 archi_table[i].long_archi,
1339 level,
1340 0, /* offered */
1341 archi_table[i].version,
1343 &info,
1344 &server_major_version,
1345 &server_minor_version);
1346 if (!W_ERROR_IS_OK(werror)) {
1347 continue;
1350 /* need at least one success */
1352 success = true;
1354 printf("\n[%s]\n", archi_table[i].long_archi);
1356 switch (level) {
1357 case 1:
1358 display_print_driver1(&info.info1);
1359 break;
1360 case 2:
1361 display_print_driver2(&info.info2);
1362 break;
1363 case 3:
1364 display_print_driver3(&info.info3);
1365 break;
1366 case 4:
1367 display_print_driver4(&info.info4);
1368 break;
1369 case 5:
1370 display_print_driver5(&info.info5);
1371 break;
1372 case 6:
1373 display_print_driver6(&info.info6);
1374 break;
1375 case 8:
1376 display_print_driver8(&info.info8);
1377 break;
1378 default:
1379 printf("unknown info level %d\n", level);
1380 break;
1384 /* Cleanup */
1386 if (is_valid_policy_hnd(&pol)) {
1387 WERROR _result;
1388 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1391 if (success) {
1392 werror = WERR_OK;
1395 return werror;
1398 /****************************************************************************
1399 ****************************************************************************/
1401 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1402 TALLOC_CTX *mem_ctx,
1403 const char *architecture,
1404 uint32_t level)
1406 WERROR werror;
1407 uint32_t count = 0;
1408 union spoolss_DriverInfo *info = NULL;
1409 uint32_t j;
1411 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1412 cli->srv_name_slash,
1413 architecture,
1414 level,
1416 &count,
1417 &info);
1419 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1420 printf("Server does not support environment [%s]\n",
1421 architecture);
1422 return WERR_OK;
1425 if (count == 0) {
1426 return WERR_OK;
1429 if (!W_ERROR_IS_OK(werror)) {
1430 printf("Error getting driver for environment [%s] - %s\n",
1431 architecture, win_errstr(werror));
1432 return werror;
1435 printf("\n[%s]\n", architecture);
1437 switch (level) {
1438 case 1:
1439 for (j=0; j < count; j++) {
1440 display_print_driver1(&info[j].info1);
1442 break;
1443 case 2:
1444 for (j=0; j < count; j++) {
1445 display_print_driver2(&info[j].info2);
1447 break;
1448 case 3:
1449 for (j=0; j < count; j++) {
1450 display_print_driver3(&info[j].info3);
1452 break;
1453 case 4:
1454 for (j=0; j < count; j++) {
1455 display_print_driver4(&info[j].info4);
1457 break;
1458 case 5:
1459 for (j=0; j < count; j++) {
1460 display_print_driver5(&info[j].info5);
1462 break;
1463 case 6:
1464 for (j=0; j < count; j++) {
1465 display_print_driver6(&info[j].info6);
1467 break;
1468 case 8:
1469 for (j=0; j < count; j++) {
1470 display_print_driver8(&info[j].info8);
1472 break;
1473 default:
1474 printf("unknown info level %d\n", level);
1475 return WERR_INVALID_LEVEL;
1478 return werror;
1481 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1482 TALLOC_CTX *mem_ctx,
1483 int argc, const char **argv)
1485 WERROR werror = WERR_OK;
1486 uint32_t level = 1;
1487 uint32_t i;
1488 const char *architecture = NULL;
1490 if (argc > 3) {
1491 printf("Usage: enumdrivers [level] [architecture]\n");
1492 return WERR_OK;
1495 if (argc >= 2) {
1496 level = atoi(argv[1]);
1499 if (argc == 3) {
1500 architecture = argv[2];
1503 if (architecture) {
1504 return enum_driver_by_architecture(cli, mem_ctx,
1505 architecture,
1506 level);
1509 /* loop through and print driver info level for each architecture */
1510 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1511 /* check to see if we already asked for this architecture string */
1513 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1514 continue;
1517 werror = enum_driver_by_architecture(cli, mem_ctx,
1518 archi_table[i].long_archi,
1519 level);
1520 if (!W_ERROR_IS_OK(werror)) {
1521 break;
1525 return werror;
1528 /****************************************************************************
1529 ****************************************************************************/
1531 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1533 printf("\tDirectory Name:[%s]\n", r->directory_name);
1536 /****************************************************************************
1537 ****************************************************************************/
1539 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1540 TALLOC_CTX *mem_ctx,
1541 int argc, const char **argv)
1543 WERROR result;
1544 NTSTATUS status;
1545 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1546 DATA_BLOB buffer;
1547 uint32_t offered;
1548 union spoolss_DriverDirectoryInfo info;
1549 uint32_t needed;
1550 struct dcerpc_binding_handle *b = cli->binding_handle;
1552 if (argc > 2) {
1553 printf("Usage: %s [environment]\n", argv[0]);
1554 return WERR_OK;
1557 /* Get the arguments need to open the printer handle */
1559 if (argc == 2) {
1560 env = argv[1];
1563 /* Get the directory. Only use Info level 1 */
1565 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1566 cli->srv_name_slash,
1567 env,
1569 NULL, /* buffer */
1570 0, /* offered */
1571 NULL, /* info */
1572 &needed,
1573 &result);
1574 if (!NT_STATUS_IS_OK(status)) {
1575 return ntstatus_to_werror(status);
1577 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1578 offered = needed;
1579 buffer = data_blob_talloc_zero(mem_ctx, needed);
1581 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1582 cli->srv_name_slash,
1583 env,
1585 &buffer,
1586 offered,
1587 &info,
1588 &needed,
1589 &result);
1590 if (!NT_STATUS_IS_OK(status)) {
1591 return ntstatus_to_werror(status);
1595 if (W_ERROR_IS_OK(result)) {
1596 display_printdriverdir_1(&info.info1);
1599 return result;
1602 /****************************************************************************
1603 ****************************************************************************/
1605 static WERROR cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client *cli,
1606 TALLOC_CTX *mem_ctx,
1607 int argc, const char **argv)
1609 HRESULT hresult;
1610 NTSTATUS status;
1611 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1612 uint32_t offered;
1613 uint32_t needed;
1614 struct dcerpc_binding_handle *b = cli->binding_handle;
1615 const char *package_id = "";
1616 const char *cab = NULL;
1618 if (argc > 4) {
1619 printf("Usage: %s [environment] [package_id]\n", argv[0]);
1620 return WERR_OK;
1623 /* Get the arguments need to open the printer handle */
1625 if (argc >= 2) {
1626 env = argv[1];
1629 if (argc == 3) {
1630 package_id = argv[2];
1633 offered = 1;
1634 cab = talloc_zero_array(mem_ctx, char, offered);
1635 if (cab == NULL) {
1636 return WERR_NOT_ENOUGH_MEMORY;
1638 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1639 cli->srv_name_slash,
1640 env,
1641 NULL,
1642 package_id,
1643 cab,
1644 offered,
1645 &needed,
1646 &hresult);
1647 if (!NT_STATUS_IS_OK(status)) {
1648 return ntstatus_to_werror(status);
1651 if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult)), WERR_INSUFFICIENT_BUFFER)) {
1652 offered = needed;
1653 cab = talloc_zero_array(mem_ctx, char, offered);
1654 if (cab == NULL) {
1655 return WERR_NOT_ENOUGH_MEMORY;
1657 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1658 cli->srv_name_slash,
1659 env,
1660 NULL,
1661 package_id,
1662 cab,
1663 offered,
1664 &needed,
1665 &hresult);
1666 if (!NT_STATUS_IS_OK(status)) {
1667 return ntstatus_to_werror(status);
1671 return W_ERROR(WIN32_FROM_HRESULT(hresult));
1675 /****************************************************************************
1676 ****************************************************************************/
1678 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1679 struct spoolss_AddDriverInfo3 *info,
1680 const char *arch)
1683 int i;
1685 for (i=0; archi_table[i].long_archi != NULL; i++)
1687 if (strcmp(arch, archi_table[i].short_archi) == 0)
1689 info->version = archi_table[i].version;
1690 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1691 break;
1695 if (archi_table[i].long_archi == NULL)
1697 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1700 return;
1704 /**************************************************************************
1705 wrapper for strtok to get the next parameter from a delimited list.
1706 Needed to handle the empty parameter string denoted by "NULL"
1707 *************************************************************************/
1709 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1710 const char *delim, const char **dest,
1711 char **saveptr)
1713 char *ptr;
1715 /* get the next token */
1716 ptr = strtok_r(str, delim, saveptr);
1718 /* a string of 'NULL' is used to represent an empty
1719 parameter because two consecutive delimiters
1720 will not return an empty string. See man strtok(3)
1721 for details */
1722 if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1723 ptr = NULL;
1726 if (dest != NULL) {
1727 *dest = talloc_strdup(mem_ctx, ptr);
1730 return ptr;
1733 /********************************************************************************
1734 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1735 string in the form of
1736 <Long Driver Name>:<Driver File Name>:<Data File Name>:\
1737 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1738 <Default Data Type>:<Comma Separated list of Files>
1739 *******************************************************************************/
1741 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1742 char *args)
1744 char *str, *str2;
1745 size_t count = 0;
1746 char *saveptr = NULL;
1747 struct spoolss_StringArray *deps;
1748 const char **file_array = NULL;
1749 int i;
1751 /* fill in the UNISTR fields */
1752 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1753 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1754 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1755 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1756 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1757 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1758 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1760 /* <Comma Separated List of Dependent Files> */
1761 /* save the beginning of the string */
1762 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1763 str = str2;
1765 /* begin to strip out each filename */
1766 str = strtok_r(str, ",", &saveptr);
1768 /* no dependent files, we are done */
1769 if (!str) {
1770 return true;
1773 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1774 if (!deps) {
1775 return false;
1778 while (str != NULL) {
1779 bool ok;
1780 ok = add_string_to_array(deps, str, &file_array, &count);
1781 if (!ok) {
1782 return false;
1784 str = strtok_r(NULL, ",", &saveptr);
1787 deps->string = talloc_zero_array(deps, const char *, count + 1);
1788 if (!deps->string) {
1789 return false;
1792 for (i=0; i < count; i++) {
1793 deps->string[i] = file_array[i];
1796 r->dependent_files = deps;
1798 return true;
1801 /****************************************************************************
1802 ****************************************************************************/
1804 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1805 TALLOC_CTX *mem_ctx,
1806 int argc, const char **argv)
1808 WERROR result;
1809 NTSTATUS status;
1810 uint32_t level = 3;
1811 struct spoolss_AddDriverInfoCtr info_ctr;
1812 struct spoolss_AddDriverInfo3 info3;
1813 const char *arch;
1814 char *driver_args;
1815 struct dcerpc_binding_handle *b = cli->binding_handle;
1817 /* parse the command arguments */
1818 if (argc != 3 && argc != 4)
1820 printf ("Usage: %s <Environment> \\\n", argv[0]);
1821 printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1822 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1823 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1824 printf ("\t[version]\n");
1826 return WERR_OK;
1829 /* Fill in the spoolss_AddDriverInfo3 struct */
1830 ZERO_STRUCT(info3);
1832 arch = cmd_spoolss_get_short_archi(argv[1]);
1833 if (!arch) {
1834 printf ("Error Unknown architecture [%s]\n", argv[1]);
1835 return WERR_INVALID_PARAMETER;
1838 set_drv_info_3_env(mem_ctx, &info3, arch);
1840 driver_args = talloc_strdup( mem_ctx, argv[2] );
1841 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1843 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1844 return WERR_INVALID_PARAMETER;
1847 /* if printer driver version specified, override the default version
1848 * used by the architecture. This allows installation of Windows
1849 * 2000 (version 3) printer drivers. */
1850 if (argc == 4)
1852 info3.version = atoi(argv[3]);
1856 info_ctr.level = level;
1857 info_ctr.info.info3 = &info3;
1859 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1860 cli->srv_name_slash,
1861 &info_ctr,
1862 &result);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 return ntstatus_to_werror(status);
1866 if (W_ERROR_IS_OK(result)) {
1867 printf ("Printer Driver %s successfully installed.\n",
1868 info3.driver_name);
1871 return result;
1875 /****************************************************************************
1876 ****************************************************************************/
1878 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1879 TALLOC_CTX *mem_ctx,
1880 int argc, const char **argv)
1882 WERROR result;
1883 struct spoolss_SetPrinterInfoCtr info_ctr;
1884 struct spoolss_SetPrinterInfo2 info2;
1886 /* parse the command arguments */
1887 if (argc != 5)
1889 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1890 return WERR_OK;
1893 /* Fill in the DRIVER_INFO_2 struct */
1894 ZERO_STRUCT(info2);
1896 info2.printername = argv[1];
1897 info2.drivername = argv[3];
1898 info2.sharename = argv[2];
1899 info2.portname = argv[4];
1900 info2.comment = "Created by rpcclient";
1901 info2.printprocessor = "winprint";
1902 info2.datatype = "RAW";
1903 info2.devmode_ptr = 0;
1904 info2.secdesc_ptr = 0;
1905 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1906 info2.priority = 0;
1907 info2.defaultpriority = 0;
1908 info2.starttime = 0;
1909 info2.untiltime = 0;
1911 /* These three fields must not be used by AddPrinter()
1912 as defined in the MS Platform SDK documentation..
1913 --jerry
1914 info2.status = 0;
1915 info2.cjobs = 0;
1916 info2.averageppm = 0;
1919 info_ctr.level = 2;
1920 info_ctr.info.info2 = &info2;
1922 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1923 &info_ctr);
1924 if (W_ERROR_IS_OK(result))
1925 printf ("Printer %s successfully installed.\n", argv[1]);
1927 return result;
1930 /****************************************************************************
1931 ****************************************************************************/
1933 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1934 TALLOC_CTX *mem_ctx,
1935 int argc, const char **argv)
1937 struct policy_handle pol;
1938 WERROR result;
1939 NTSTATUS status;
1940 uint32_t level = 2;
1941 const char *printername;
1942 union spoolss_PrinterInfo info;
1943 struct spoolss_SetPrinterInfoCtr info_ctr;
1944 struct spoolss_SetPrinterInfo2 info2;
1945 struct spoolss_DevmodeContainer devmode_ctr;
1946 struct sec_desc_buf secdesc_ctr;
1947 struct dcerpc_binding_handle *b = cli->binding_handle;
1949 ZERO_STRUCT(devmode_ctr);
1950 ZERO_STRUCT(secdesc_ctr);
1952 /* parse the command arguments */
1953 if (argc != 3)
1955 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1956 return WERR_OK;
1959 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1961 /* Get a printer handle */
1963 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1964 printername,
1965 PRINTER_ALL_ACCESS,
1966 &pol);
1967 if (!W_ERROR_IS_OK(result))
1968 goto done;
1970 /* Get printer info */
1972 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1973 &pol,
1974 level,
1976 &info);
1977 if (!W_ERROR_IS_OK(result)) {
1978 printf ("Unable to retrieve printer information!\n");
1979 goto done;
1982 /* Set the printer driver */
1984 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1985 info2.drivername = argv[2];
1987 info_ctr.level = 2;
1988 info_ctr.info.info2 = &info2;
1990 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1991 &pol,
1992 &info_ctr,
1993 &devmode_ctr,
1994 &secdesc_ctr,
1995 0, /* command */
1996 &result);
1997 if (!NT_STATUS_IS_OK(status)) {
1998 result = ntstatus_to_werror(status);
1999 goto done;
2001 if (!W_ERROR_IS_OK(result)) {
2002 printf("SetPrinter call failed!\n");
2003 goto done;
2006 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
2008 done:
2009 /* Cleanup */
2011 if (is_valid_policy_hnd(&pol)) {
2012 WERROR _result;
2013 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2016 return result;
2020 /****************************************************************************
2021 ****************************************************************************/
2023 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
2024 TALLOC_CTX *mem_ctx,
2025 int argc, const char **argv)
2027 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
2028 NTSTATUS status;
2029 struct dcerpc_binding_handle *b = cli->binding_handle;
2031 int i;
2032 int vers = -1;
2034 const char *arch = NULL;
2035 uint32_t delete_flags = 0;
2037 /* parse the command arguments */
2038 if (argc < 2 || argc > 5) {
2039 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
2040 return WERR_OK;
2043 if (argc >= 3)
2044 arch = argv[2];
2045 if (argc >= 4) {
2046 vers = atoi(argv[3]);
2047 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
2049 if (argc == 5)
2050 delete_flags = atoi(argv[4]);
2052 /* delete the driver for all architectures */
2053 for (i=0; archi_table[i].long_archi; i++) {
2055 if (arch && !strequal(archi_table[i].long_archi, arch))
2056 continue;
2058 if (vers >= 0 && archi_table[i].version != vers)
2059 continue;
2061 /* make the call to remove the driver */
2062 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
2063 cli->srv_name_slash,
2064 archi_table[i].long_archi,
2065 argv[1],
2066 delete_flags,
2067 archi_table[i].version,
2068 &result);
2069 if (!NT_STATUS_IS_OK(status)) {
2070 return ntstatus_to_werror(status);
2072 if ( !W_ERROR_IS_OK(result) )
2074 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2075 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
2076 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
2079 else
2081 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
2082 archi_table[i].long_archi, archi_table[i].version);
2083 ret = WERR_OK;
2087 return ret;
2091 /****************************************************************************
2092 ****************************************************************************/
2094 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
2095 TALLOC_CTX *mem_ctx,
2096 int argc, const char **argv)
2098 WERROR result = WERR_OK;
2099 NTSTATUS status;
2100 int i;
2101 struct dcerpc_binding_handle *b = cli->binding_handle;
2103 /* parse the command arguments */
2104 if (argc != 2) {
2105 printf ("Usage: %s <driver>\n", argv[0]);
2106 return WERR_OK;
2109 /* delete the driver for all architectures */
2110 for (i=0; archi_table[i].long_archi; i++) {
2111 result = WERR_OK;
2113 /* make the call to remove the driver */
2114 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2115 cli->srv_name_slash,
2116 archi_table[i].long_archi,
2117 argv[1],
2118 &result);
2119 if (!NT_STATUS_IS_OK(status)) {
2120 result = ntstatus_to_werror(status);
2121 continue;
2123 if ( !W_ERROR_IS_OK(result) ) {
2124 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2125 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2126 argv[1], archi_table[i].long_archi,
2127 win_errstr(result));
2129 } else {
2130 printf ("Driver %s removed for arch [%s].\n", argv[1],
2131 archi_table[i].long_archi);
2135 return result;
2138 /****************************************************************************
2139 ****************************************************************************/
2141 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2142 TALLOC_CTX *mem_ctx,
2143 int argc, const char **argv)
2145 WERROR result;
2146 NTSTATUS status;
2147 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2148 DATA_BLOB buffer;
2149 uint32_t offered;
2150 union spoolss_PrintProcessorDirectoryInfo info;
2151 uint32_t needed;
2152 struct dcerpc_binding_handle *b = cli->binding_handle;
2154 /* parse the command arguments */
2155 if (argc > 2) {
2156 printf ("Usage: %s [environment]\n", argv[0]);
2157 return WERR_OK;
2160 if (argc == 2) {
2161 environment = argv[1];
2164 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2165 cli->srv_name_slash,
2166 environment,
2168 NULL, /* buffer */
2169 0, /* offered */
2170 NULL, /* info */
2171 &needed,
2172 &result);
2173 if (!NT_STATUS_IS_OK(status)) {
2174 return ntstatus_to_werror(status);
2176 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2177 offered = needed;
2178 buffer = data_blob_talloc_zero(mem_ctx, needed);
2180 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2181 cli->srv_name_slash,
2182 environment,
2184 &buffer,
2185 offered,
2186 &info,
2187 &needed,
2188 &result);
2189 if (!NT_STATUS_IS_OK(status)) {
2190 return ntstatus_to_werror(status);
2194 if (W_ERROR_IS_OK(result)) {
2195 printf("%s\n", info.info1.directory_name);
2198 return result;
2201 /****************************************************************************
2202 ****************************************************************************/
2204 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2205 int argc, const char **argv)
2207 struct policy_handle handle;
2208 WERROR werror;
2209 NTSTATUS status;
2210 const char *printername;
2211 struct spoolss_AddFormInfoCtr info_ctr;
2212 struct spoolss_AddFormInfo1 info1;
2213 struct spoolss_AddFormInfo2 info2;
2214 uint32_t level = 1;
2215 struct dcerpc_binding_handle *b = cli->binding_handle;
2217 /* Parse the command arguments */
2219 if (argc < 3 || argc > 5) {
2220 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2221 return WERR_OK;
2224 /* Get a printer handle */
2226 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2228 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2229 printername,
2230 PRINTER_ALL_ACCESS,
2231 &handle);
2232 if (!W_ERROR_IS_OK(werror))
2233 goto done;
2235 /* Dummy up some values for the form data */
2237 if (argc == 4) {
2238 level = atoi(argv[3]);
2241 switch (level) {
2242 case 1:
2243 info1.flags = SPOOLSS_FORM_USER;
2244 info1.form_name = argv[2];
2245 info1.size.width = 100;
2246 info1.size.height = 100;
2247 info1.area.left = 0;
2248 info1.area.top = 10;
2249 info1.area.right = 20;
2250 info1.area.bottom = 30;
2252 info_ctr.level = 1;
2253 info_ctr.info.info1 = &info1;
2255 break;
2256 case 2:
2257 info2.flags = SPOOLSS_FORM_USER;
2258 info2.form_name = argv[2];
2259 info2.size.width = 100;
2260 info2.size.height = 100;
2261 info2.area.left = 0;
2262 info2.area.top = 10;
2263 info2.area.right = 20;
2264 info2.area.bottom = 30;
2265 info2.keyword = argv[2];
2266 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2267 info2.mui_dll = NULL;
2268 info2.ressource_id = 0;
2269 info2.display_name = argv[2];
2270 info2.lang_id = 0;
2272 info_ctr.level = 2;
2273 info_ctr.info.info2 = &info2;
2275 break;
2276 default:
2277 werror = WERR_INVALID_PARAMETER;
2278 goto done;
2281 /* Add the form */
2283 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2284 &handle,
2285 &info_ctr,
2286 &werror);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 werror = ntstatus_to_werror(status);
2289 goto done;
2291 done:
2292 if (is_valid_policy_hnd(&handle)) {
2293 WERROR _result;
2294 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2297 return werror;
2300 /****************************************************************************
2301 ****************************************************************************/
2303 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2304 int argc, const char **argv)
2306 struct policy_handle handle;
2307 WERROR werror;
2308 NTSTATUS status;
2309 const char *printername;
2310 struct spoolss_AddFormInfoCtr info_ctr;
2311 struct spoolss_AddFormInfo1 info1;
2312 struct dcerpc_binding_handle *b = cli->binding_handle;
2314 /* Parse the command arguments */
2316 if (argc != 3) {
2317 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2318 return WERR_OK;
2321 /* Get a printer handle */
2323 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2325 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2326 printername,
2327 SEC_FLAG_MAXIMUM_ALLOWED,
2328 &handle);
2329 if (!W_ERROR_IS_OK(werror))
2330 goto done;
2332 /* Dummy up some values for the form data */
2334 info1.flags = SPOOLSS_FORM_PRINTER;
2335 info1.size.width = 100;
2336 info1.size.height = 100;
2337 info1.area.left = 0;
2338 info1.area.top = 1000;
2339 info1.area.right = 2000;
2340 info1.area.bottom = 3000;
2341 info1.form_name = argv[2];
2343 info_ctr.info.info1 = &info1;
2344 info_ctr.level = 1;
2346 /* Set the form */
2348 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2349 &handle,
2350 argv[2],
2351 &info_ctr,
2352 &werror);
2353 if (!NT_STATUS_IS_OK(status)) {
2354 werror = ntstatus_to_werror(status);
2355 goto done;
2357 done:
2358 if (is_valid_policy_hnd(&handle)) {
2359 WERROR _result;
2360 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2363 return werror;
2366 /****************************************************************************
2367 ****************************************************************************/
2369 static const char *get_form_flag(int form_flag)
2371 switch (form_flag) {
2372 case SPOOLSS_FORM_USER:
2373 return "FORM_USER";
2374 case SPOOLSS_FORM_BUILTIN:
2375 return "FORM_BUILTIN";
2376 case SPOOLSS_FORM_PRINTER:
2377 return "FORM_PRINTER";
2378 default:
2379 return "unknown";
2383 /****************************************************************************
2384 ****************************************************************************/
2386 static void display_form_info1(struct spoolss_FormInfo1 *r)
2388 printf("%s\n" \
2389 "\tflag: %s (%d)\n" \
2390 "\twidth: %d, length: %d\n" \
2391 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2392 r->form_name, get_form_flag(r->flags), r->flags,
2393 r->size.width, r->size.height,
2394 r->area.left, r->area.right,
2395 r->area.top, r->area.bottom);
2398 /****************************************************************************
2399 ****************************************************************************/
2401 static void display_form_info2(struct spoolss_FormInfo2 *r)
2403 printf("%s\n" \
2404 "\tflag: %s (%d)\n" \
2405 "\twidth: %d, length: %d\n" \
2406 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2407 r->form_name, get_form_flag(r->flags), r->flags,
2408 r->size.width, r->size.height,
2409 r->area.left, r->area.right,
2410 r->area.top, r->area.bottom);
2411 printf("\tkeyword: %s\n", r->keyword);
2412 printf("\tstring_type: 0x%08x\n", r->string_type);
2413 printf("\tmui_dll: %s\n", r->mui_dll);
2414 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2415 printf("\tdisplay_name: %s\n", r->display_name);
2416 printf("\tlang_id: %d\n", r->lang_id);
2417 printf("\n");
2420 /****************************************************************************
2421 ****************************************************************************/
2423 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2424 int argc, const char **argv)
2426 struct policy_handle handle;
2427 WERROR werror;
2428 NTSTATUS status;
2429 const char *printername;
2430 DATA_BLOB buffer;
2431 uint32_t offered = 0;
2432 union spoolss_FormInfo info;
2433 uint32_t needed;
2434 uint32_t level = 1;
2435 struct dcerpc_binding_handle *b = cli->binding_handle;
2437 /* Parse the command arguments */
2439 if (argc < 3 || argc > 5) {
2440 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2441 return WERR_OK;
2444 /* Get a printer handle */
2446 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2448 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2449 printername,
2450 SEC_FLAG_MAXIMUM_ALLOWED,
2451 &handle);
2452 if (!W_ERROR_IS_OK(werror))
2453 goto done;
2455 if (argc == 4) {
2456 level = atoi(argv[3]);
2459 /* Get the form */
2461 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2462 &handle,
2463 argv[2],
2464 level,
2465 NULL,
2466 offered,
2467 &info,
2468 &needed,
2469 &werror);
2470 if (!NT_STATUS_IS_OK(status)) {
2471 werror = ntstatus_to_werror(status);
2472 goto done;
2474 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2475 buffer = data_blob_talloc_zero(mem_ctx, needed);
2476 offered = needed;
2477 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2478 &handle,
2479 argv[2],
2480 level,
2481 &buffer,
2482 offered,
2483 &info,
2484 &needed,
2485 &werror);
2486 if (!NT_STATUS_IS_OK(status)) {
2487 werror = ntstatus_to_werror(status);
2488 goto done;
2492 if (!W_ERROR_IS_OK(werror)) {
2493 goto done;
2496 switch (level) {
2497 case 1:
2498 display_form_info1(&info.info1);
2499 break;
2500 case 2:
2501 display_form_info2(&info.info2);
2502 break;
2505 done:
2506 if (is_valid_policy_hnd(&handle)) {
2507 WERROR _result;
2508 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2511 return werror;
2514 /****************************************************************************
2515 ****************************************************************************/
2517 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2518 TALLOC_CTX *mem_ctx, int argc,
2519 const char **argv)
2521 struct policy_handle handle;
2522 WERROR werror;
2523 NTSTATUS status;
2524 const char *printername;
2525 struct dcerpc_binding_handle *b = cli->binding_handle;
2527 /* Parse the command arguments */
2529 if (argc != 3) {
2530 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2531 return WERR_OK;
2534 /* Get a printer handle */
2536 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2538 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2539 printername,
2540 SEC_FLAG_MAXIMUM_ALLOWED,
2541 &handle);
2542 if (!W_ERROR_IS_OK(werror))
2543 goto done;
2545 /* Delete the form */
2547 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2548 &handle,
2549 argv[2],
2550 &werror);
2551 if (!NT_STATUS_IS_OK(status)) {
2552 werror = ntstatus_to_werror(status);
2553 goto done;
2556 done:
2557 if (is_valid_policy_hnd(&handle)) {
2558 WERROR _result;
2559 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2562 return werror;
2565 /****************************************************************************
2566 ****************************************************************************/
2568 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2569 TALLOC_CTX *mem_ctx, int argc,
2570 const char **argv)
2572 struct policy_handle handle;
2573 WERROR werror;
2574 const char *printername;
2575 uint32_t num_forms, level = 1, i;
2576 union spoolss_FormInfo *forms;
2577 struct dcerpc_binding_handle *b = cli->binding_handle;
2579 /* Parse the command arguments */
2581 if (argc < 2 || argc > 4) {
2582 printf ("Usage: %s <printer> [level]\n", argv[0]);
2583 return WERR_OK;
2586 /* Get a printer handle */
2588 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2590 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2591 printername,
2592 SEC_FLAG_MAXIMUM_ALLOWED,
2593 &handle);
2594 if (!W_ERROR_IS_OK(werror))
2595 goto done;
2597 if (argc == 3) {
2598 level = atoi(argv[2]);
2601 /* Enumerate forms */
2603 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2604 &handle,
2605 level,
2607 &num_forms,
2608 &forms);
2610 if (!W_ERROR_IS_OK(werror))
2611 goto done;
2613 /* Display output */
2615 for (i = 0; i < num_forms; i++) {
2616 switch (level) {
2617 case 1:
2618 display_form_info1(&forms[i].info1);
2619 break;
2620 case 2:
2621 display_form_info2(&forms[i].info2);
2622 break;
2626 done:
2627 if (is_valid_policy_hnd(&handle)) {
2628 WERROR _result;
2629 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2632 return werror;
2635 /****************************************************************************
2636 ****************************************************************************/
2638 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2639 TALLOC_CTX *mem_ctx,
2640 int argc, const char **argv)
2642 WERROR result;
2643 NTSTATUS status;
2644 const char *printername;
2645 struct policy_handle pol = { 0, };
2646 union spoolss_PrinterInfo info;
2647 enum winreg_Type type;
2648 union spoolss_PrinterData data;
2649 DATA_BLOB blob;
2650 struct dcerpc_binding_handle *b = cli->binding_handle;
2651 int error = 0;
2653 /* parse the command arguments */
2654 if (argc < 5) {
2655 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2656 " <value> <data>\n",
2657 argv[0]);
2658 return WERR_OK;
2661 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2663 type = REG_NONE;
2665 if (strequal(argv[2], "string")) {
2666 type = REG_SZ;
2669 if (strequal(argv[2], "binary")) {
2670 type = REG_BINARY;
2673 if (strequal(argv[2], "dword")) {
2674 type = REG_DWORD;
2677 if (strequal(argv[2], "multistring")) {
2678 type = REG_MULTI_SZ;
2681 if (type == REG_NONE) {
2682 printf("Unknown data type: %s\n", argv[2]);
2683 result = WERR_INVALID_PARAMETER;
2684 goto done;
2687 /* get a printer handle */
2689 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2690 printername,
2691 SEC_FLAG_MAXIMUM_ALLOWED,
2692 &pol);
2693 if (!W_ERROR_IS_OK(result)) {
2694 goto done;
2697 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2698 &pol,
2701 &info);
2702 if (!W_ERROR_IS_OK(result)) {
2703 goto done;
2706 printf("%s\n", current_timestring(mem_ctx, true));
2707 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2709 /* Set the printer data */
2711 switch (type) {
2712 case REG_SZ:
2713 data.string = talloc_strdup(mem_ctx, argv[4]);
2714 W_ERROR_HAVE_NO_MEMORY(data.string);
2715 break;
2716 case REG_DWORD:
2717 data.value = smb_strtoul(argv[4],
2718 NULL,
2720 &error,
2721 SMB_STR_STANDARD);
2722 if (error != 0) {
2723 result = WERR_INVALID_PARAMETER;
2724 goto done;
2727 break;
2728 case REG_BINARY:
2729 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2730 break;
2731 case REG_MULTI_SZ: {
2732 int i;
2733 size_t num_strings;
2734 const char **strings = NULL;
2736 num_strings = 0;
2738 for (i=4; i<argc; i++) {
2739 if (strcmp(argv[i], "NULL") == 0) {
2740 argv[i] = "";
2742 if (!add_string_to_array(mem_ctx, argv[i],
2743 &strings,
2744 &num_strings)) {
2745 result = WERR_NOT_ENOUGH_MEMORY;
2746 goto done;
2749 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2750 if (!data.string_array) {
2751 result = WERR_NOT_ENOUGH_MEMORY;
2752 goto done;
2754 for (i=0; i < num_strings; i++) {
2755 data.string_array[i] = strings[i];
2757 break;
2759 default:
2760 printf("Unknown data type: %s\n", argv[2]);
2761 result = WERR_INVALID_PARAMETER;
2762 goto done;
2765 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2766 if (!W_ERROR_IS_OK(result)) {
2767 goto done;
2770 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2771 &pol,
2772 argv[3], /* value_name */
2773 type,
2774 blob.data,
2775 blob.length,
2776 &result);
2777 if (!NT_STATUS_IS_OK(status)) {
2778 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2779 result = ntstatus_to_werror(status);
2780 goto done;
2782 if (!W_ERROR_IS_OK(result)) {
2783 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2784 goto done;
2786 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2788 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2789 &pol,
2792 &info);
2793 if (!W_ERROR_IS_OK(result)) {
2794 goto done;
2797 printf("%s\n", current_timestring(mem_ctx, true));
2798 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2800 done:
2801 /* cleanup */
2802 if (is_valid_policy_hnd(&pol)) {
2803 WERROR _result;
2804 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2807 return result;
2810 /****************************************************************************
2811 ****************************************************************************/
2813 static void display_job_info1(struct spoolss_JobInfo1 *r)
2815 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2816 r->user_name, r->document_name, r->text_status, r->pages_printed,
2817 r->total_pages);
2820 /****************************************************************************
2821 ****************************************************************************/
2823 static void display_job_info2(struct spoolss_JobInfo2 *r)
2825 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2826 r->position, r->job_id,
2827 r->user_name, r->document_name, r->text_status, r->pages_printed,
2828 r->total_pages, r->size);
2831 /****************************************************************************
2832 ****************************************************************************/
2834 static void display_job_info3(struct spoolss_JobInfo3 *r)
2836 printf("jobid[%d], next_jobid[%d]\n",
2837 r->job_id, r->next_job_id);
2840 /****************************************************************************
2841 ****************************************************************************/
2843 static void display_job_info4(struct spoolss_JobInfo4 *r)
2845 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2846 r->position, r->job_id,
2847 r->user_name, r->document_name, r->text_status, r->pages_printed,
2848 r->total_pages, r->size, r->size_high);
2851 /****************************************************************************
2852 ****************************************************************************/
2854 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2855 TALLOC_CTX *mem_ctx, int argc,
2856 const char **argv)
2858 WERROR result;
2859 uint32_t level = 1, count, i;
2860 const char *printername;
2861 struct policy_handle hnd;
2862 union spoolss_JobInfo *info;
2863 struct dcerpc_binding_handle *b = cli->binding_handle;
2865 if (argc < 2 || argc > 3) {
2866 printf("Usage: %s printername [level]\n", argv[0]);
2867 return WERR_OK;
2870 if (argc == 3) {
2871 level = atoi(argv[2]);
2874 /* Open printer handle */
2876 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2878 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2879 printername,
2880 SEC_FLAG_MAXIMUM_ALLOWED,
2881 &hnd);
2882 if (!W_ERROR_IS_OK(result))
2883 goto done;
2885 /* Enumerate ports */
2887 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2888 &hnd,
2889 0, /* firstjob */
2890 1000, /* numjobs */
2891 level,
2893 &count,
2894 &info);
2895 if (!W_ERROR_IS_OK(result)) {
2896 goto done;
2899 for (i = 0; i < count; i++) {
2900 switch (level) {
2901 case 1:
2902 display_job_info1(&info[i].info1);
2903 break;
2904 case 2:
2905 display_job_info2(&info[i].info2);
2906 break;
2907 default:
2908 d_printf("unknown info level %d\n", level);
2909 break;
2913 done:
2914 if (is_valid_policy_hnd(&hnd)) {
2915 WERROR _result;
2916 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2919 return result;
2922 /****************************************************************************
2923 ****************************************************************************/
2925 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2926 TALLOC_CTX *mem_ctx, int argc,
2927 const char **argv)
2929 WERROR result;
2930 const char *printername;
2931 struct policy_handle hnd;
2932 uint32_t job_id;
2933 uint32_t level = 1;
2934 union spoolss_JobInfo info;
2935 struct dcerpc_binding_handle *b = cli->binding_handle;
2937 if (argc < 3 || argc > 4) {
2938 printf("Usage: %s printername job_id [level]\n", argv[0]);
2939 return WERR_OK;
2942 job_id = atoi(argv[2]);
2944 if (argc == 4) {
2945 level = atoi(argv[3]);
2948 /* Open printer handle */
2950 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2952 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2953 printername,
2954 SEC_FLAG_MAXIMUM_ALLOWED,
2955 &hnd);
2956 if (!W_ERROR_IS_OK(result)) {
2957 goto done;
2960 /* Enumerate ports */
2962 result = rpccli_spoolss_getjob(cli, mem_ctx,
2963 &hnd,
2964 job_id,
2965 level,
2967 &info);
2969 if (!W_ERROR_IS_OK(result)) {
2970 goto done;
2973 switch (level) {
2974 case 1:
2975 display_job_info1(&info.info1);
2976 break;
2977 case 2:
2978 display_job_info2(&info.info2);
2979 break;
2980 case 3:
2981 display_job_info3(&info.info3);
2982 break;
2983 case 4:
2984 display_job_info4(&info.info4);
2985 break;
2986 default:
2987 d_printf("unknown info level %d\n", level);
2988 break;
2991 done:
2992 if (is_valid_policy_hnd(&hnd)) {
2993 WERROR _result;
2994 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2997 return result;
3000 /****************************************************************************
3001 ****************************************************************************/
3003 static struct {
3004 const char *name;
3005 enum spoolss_JobControl val;
3006 } cmdvals[] = {
3007 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
3008 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
3009 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
3010 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
3011 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
3012 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
3013 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
3014 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
3015 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
3018 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
3020 int i;
3022 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
3023 if (strequal(cmdvals[i].name, cmd)) {
3024 return cmdvals[i].val;
3027 return (enum spoolss_JobControl)atoi(cmd);
3030 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
3031 TALLOC_CTX *mem_ctx, int argc,
3032 const char **argv)
3034 WERROR result;
3035 NTSTATUS status;
3036 const char *printername;
3037 struct policy_handle hnd;
3038 uint32_t job_id;
3039 enum spoolss_JobControl command;
3040 struct dcerpc_binding_handle *b = cli->binding_handle;
3042 if (argc != 4) {
3043 printf("Usage: %s printername job_id command\n", argv[0]);
3044 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
3045 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
3046 return WERR_OK;
3049 job_id = atoi(argv[2]);
3050 command = parse_setjob_command(argv[3]);
3052 /* Open printer handle */
3054 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3056 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3057 printername,
3058 SEC_FLAG_MAXIMUM_ALLOWED,
3059 &hnd);
3060 if (!W_ERROR_IS_OK(result)) {
3061 goto done;
3064 /* Set Job */
3066 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3067 &hnd,
3068 job_id,
3069 NULL,
3070 command,
3071 &result);
3072 if (!NT_STATUS_IS_OK(status)) {
3073 result = ntstatus_to_werror(status);
3074 goto done;
3076 if (!W_ERROR_IS_OK(result)) {
3077 goto done;
3080 done:
3081 if (is_valid_policy_hnd(&hnd)) {
3082 WERROR _result;
3083 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3086 return result;
3089 /****************************************************************************
3090 ****************************************************************************/
3092 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
3093 TALLOC_CTX *mem_ctx, int argc,
3094 const char **argv)
3096 WERROR result;
3097 NTSTATUS status;
3098 const char *printername;
3099 struct policy_handle hnd;
3100 uint32_t value_needed;
3101 enum winreg_Type type;
3102 uint32_t data_needed;
3103 struct dcerpc_binding_handle *b = cli->binding_handle;
3104 struct spoolss_EnumPrinterData r;
3106 if (argc != 2) {
3107 printf("Usage: %s printername\n", argv[0]);
3108 return WERR_OK;
3111 /* Open printer handle */
3113 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3115 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3116 printername,
3117 SEC_FLAG_MAXIMUM_ALLOWED,
3118 &hnd);
3119 if (!W_ERROR_IS_OK(result)) {
3120 goto done;
3123 /* Enumerate data */
3125 r.in.handle = &hnd;
3126 r.in.enum_index = 0;
3127 r.in.value_offered = 0;
3128 r.in.data_offered = 0;
3129 r.out.value_name = NULL;
3130 r.out.value_needed = &value_needed;
3131 r.out.type = &type;
3132 r.out.data = NULL;
3133 r.out.data_needed = &data_needed;
3135 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3136 if (!NT_STATUS_IS_OK(status)) {
3137 result = ntstatus_to_werror(status);
3138 goto done;
3141 if (!W_ERROR_IS_OK(r.out.result)) {
3142 result = r.out.result;
3143 goto done;
3146 r.in.data_offered = *r.out.data_needed;
3147 r.in.value_offered = *r.out.value_needed;
3148 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3149 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3151 do {
3153 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3154 if (!NT_STATUS_IS_OK(status)) {
3155 result = ntstatus_to_werror(status);
3156 goto done;
3159 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3160 result = WERR_OK;
3161 break;
3164 r.in.enum_index++;
3166 display_reg_value(r.out.value_name, *r.out.type,
3167 data_blob_const(r.out.data, r.in.data_offered));
3169 } while (W_ERROR_IS_OK(r.out.result));
3171 done:
3172 if (is_valid_policy_hnd(&hnd)) {
3173 WERROR _result;
3174 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3177 return result;
3180 /****************************************************************************
3181 ****************************************************************************/
3183 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3184 TALLOC_CTX *mem_ctx, int argc,
3185 const char **argv)
3187 WERROR result;
3188 uint32_t i;
3189 const char *printername;
3190 struct policy_handle hnd;
3191 uint32_t count;
3192 struct spoolss_PrinterEnumValues *info;
3193 struct dcerpc_binding_handle *b = cli->binding_handle;
3195 if (argc != 3) {
3196 printf("Usage: %s printername <keyname>\n", argv[0]);
3197 return WERR_OK;
3200 /* Open printer handle */
3202 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3204 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3205 printername,
3206 SEC_FLAG_MAXIMUM_ALLOWED,
3207 &hnd);
3208 if (!W_ERROR_IS_OK(result)) {
3209 goto done;
3212 /* Enumerate subkeys */
3214 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3215 &hnd,
3216 argv[2],
3218 &count,
3219 &info);
3220 if (!W_ERROR_IS_OK(result)) {
3221 goto done;
3224 for (i=0; i < count; i++) {
3225 display_printer_data(info[i].value_name,
3226 info[i].type,
3227 info[i].data->data,
3228 info[i].data->length);
3231 done:
3232 if (is_valid_policy_hnd(&hnd)) {
3233 WERROR _result;
3234 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3237 return result;
3240 /****************************************************************************
3241 ****************************************************************************/
3243 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3244 TALLOC_CTX *mem_ctx, int argc,
3245 const char **argv)
3247 WERROR result;
3248 const char *printername;
3249 const char *keyname = NULL;
3250 struct policy_handle hnd;
3251 const char **key_buffer = NULL;
3252 int i;
3253 uint32_t offered = 0;
3254 struct dcerpc_binding_handle *b = cli->binding_handle;
3256 if (argc < 2 || argc > 4) {
3257 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3258 return WERR_OK;
3261 if (argc >= 3) {
3262 keyname = argv[2];
3263 } else {
3264 keyname = "";
3267 if (argc == 4) {
3268 offered = atoi(argv[3]);
3271 /* Open printer handle */
3273 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3275 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3276 printername,
3277 SEC_FLAG_MAXIMUM_ALLOWED,
3278 &hnd);
3279 if (!W_ERROR_IS_OK(result)) {
3280 goto done;
3283 /* Enumerate subkeys */
3285 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3286 &hnd,
3287 keyname,
3288 &key_buffer,
3289 offered);
3291 if (!W_ERROR_IS_OK(result)) {
3292 goto done;
3295 for (i=0; key_buffer && key_buffer[i]; i++) {
3296 printf("%s\n", key_buffer[i]);
3299 done:
3301 if (is_valid_policy_hnd(&hnd)) {
3302 WERROR _result;
3303 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3306 return result;
3309 /****************************************************************************
3310 ****************************************************************************/
3312 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3313 TALLOC_CTX *mem_ctx, int argc,
3314 const char **argv)
3316 const char *printername;
3317 const char *clientname;
3318 struct policy_handle hnd = { 0, };
3319 WERROR result;
3320 NTSTATUS status;
3321 struct spoolss_NotifyOption option;
3322 struct dcerpc_binding_handle *b = cli->binding_handle;
3324 if (argc != 2) {
3325 printf("Usage: %s printername\n", argv[0]);
3326 result = WERR_OK;
3327 goto done;
3330 /* Open printer */
3332 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3334 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3335 printername,
3336 SEC_FLAG_MAXIMUM_ALLOWED,
3337 &hnd);
3338 if (!W_ERROR_IS_OK(result)) {
3339 printf("Error opening %s\n", argv[1]);
3340 goto done;
3343 /* Create spool options */
3345 option.version = 2;
3346 option.count = 2;
3348 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3349 if (option.types == NULL) {
3350 result = WERR_NOT_ENOUGH_MEMORY;
3351 goto done;
3354 option.types[0].type = PRINTER_NOTIFY_TYPE;
3355 option.types[0].count = 1;
3356 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3357 if (option.types[0].fields == NULL) {
3358 result = WERR_NOT_ENOUGH_MEMORY;
3359 goto done;
3361 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3363 option.types[1].type = JOB_NOTIFY_TYPE;
3364 option.types[1].count = 1;
3365 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3366 if (option.types[1].fields == NULL) {
3367 result = WERR_NOT_ENOUGH_MEMORY;
3368 goto done;
3370 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3372 clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3373 if (!clientname) {
3374 result = WERR_NOT_ENOUGH_MEMORY;
3375 goto done;
3378 /* Send rffpcnex */
3380 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3381 &hnd,
3384 clientname,
3385 123,
3386 &option,
3387 &result);
3388 if (!NT_STATUS_IS_OK(status)) {
3389 result = ntstatus_to_werror(status);
3390 goto done;
3392 if (!W_ERROR_IS_OK(result)) {
3393 printf("Error rffpcnex %s\n", argv[1]);
3394 goto done;
3397 done:
3398 if (is_valid_policy_hnd(&hnd)) {
3399 WERROR _result;
3400 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3403 return result;
3406 /****************************************************************************
3407 ****************************************************************************/
3409 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3410 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3412 union spoolss_PrinterInfo info1, info2;
3413 WERROR werror;
3414 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3416 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3417 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3418 hnd1,
3421 &info1);
3422 if ( !W_ERROR_IS_OK(werror) ) {
3423 printf("failed (%s)\n", win_errstr(werror));
3424 talloc_destroy(mem_ctx);
3425 return false;
3427 printf("ok\n");
3429 printf("Retrieving printer properties for %s...", cli2->desthost);
3430 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3431 hnd2,
3434 &info2);
3435 if ( !W_ERROR_IS_OK(werror) ) {
3436 printf("failed (%s)\n", win_errstr(werror));
3437 talloc_destroy(mem_ctx);
3438 return false;
3440 printf("ok\n");
3442 talloc_destroy(mem_ctx);
3444 return true;
3447 /****************************************************************************
3448 ****************************************************************************/
3450 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3451 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3453 union spoolss_PrinterInfo info1, info2;
3454 WERROR werror;
3455 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3456 struct security_descriptor *sd1, *sd2;
3457 bool result = true;
3460 printf("Retrieving printer security for %s...", cli1->desthost);
3461 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3462 hnd1,
3465 &info1);
3466 if ( !W_ERROR_IS_OK(werror) ) {
3467 printf("failed (%s)\n", win_errstr(werror));
3468 result = false;
3469 goto done;
3471 printf("ok\n");
3473 printf("Retrieving printer security for %s...", cli2->desthost);
3474 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3475 hnd2,
3478 &info2);
3479 if ( !W_ERROR_IS_OK(werror) ) {
3480 printf("failed (%s)\n", win_errstr(werror));
3481 result = false;
3482 goto done;
3484 printf("ok\n");
3487 printf("++ ");
3489 sd1 = info1.info3.secdesc;
3490 sd2 = info2.info3.secdesc;
3492 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3493 printf("NULL secdesc!\n");
3494 result = false;
3495 goto done;
3498 if (!security_descriptor_equal( sd1, sd2 ) ) {
3499 printf("Security Descriptors *not* equal!\n");
3500 result = false;
3501 goto done;
3504 printf("Security descriptors match\n");
3506 done:
3507 talloc_destroy(mem_ctx);
3508 return result;
3512 /****************************************************************************
3513 ****************************************************************************/
3515 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3516 TALLOC_CTX *mem_ctx, int argc,
3517 const char **argv)
3519 const char *printername;
3520 char *printername_path = NULL;
3521 struct cli_state *cli_server2 = NULL;
3522 struct rpc_pipe_client *cli2 = NULL;
3523 struct policy_handle hPrinter1, hPrinter2;
3524 NTSTATUS nt_status;
3525 WERROR werror;
3527 if ( argc != 3 ) {
3528 printf("Usage: %s <printer> <server>\n", argv[0]);
3529 return WERR_OK;
3532 printername = argv[1];
3534 /* first get the connection to the remote server */
3536 nt_status = cli_full_connection_creds(&cli_server2, lp_netbios_name(), argv[2],
3537 NULL, 0,
3538 "IPC$", "IPC",
3539 get_cmdline_auth_info_creds(
3540 popt_get_cmdline_auth_info()),
3541 CLI_FULL_CONNECTION_IPC);
3542 if ( !NT_STATUS_IS_OK(nt_status) )
3543 return WERR_GEN_FAILURE;
3545 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
3546 &cli2);
3547 if (!NT_STATUS_IS_OK(nt_status)) {
3548 printf("failed to open spoolss pipe on server %s (%s)\n",
3549 argv[2], nt_errstr(nt_status));
3550 return WERR_GEN_FAILURE;
3553 /* now open up both printers */
3555 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3557 printf("Opening %s...", printername_path);
3559 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3560 printername_path,
3561 PRINTER_ALL_ACCESS,
3562 &hPrinter1);
3563 if ( !W_ERROR_IS_OK(werror) ) {
3564 printf("failed (%s)\n", win_errstr(werror));
3565 goto done;
3567 printf("ok\n");
3569 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3571 printf("Opening %s...", printername_path);
3572 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3573 printername_path,
3574 PRINTER_ALL_ACCESS,
3575 &hPrinter2);
3576 if ( !W_ERROR_IS_OK(werror) ) {
3577 printf("failed (%s)\n", win_errstr(werror));
3578 goto done;
3580 printf("ok\n");
3582 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3583 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3584 #if 0
3585 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3586 #endif
3589 done:
3590 /* cleanup */
3592 printf("Closing printers...");
3594 WERROR _result;
3595 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3596 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3598 printf("ok\n");
3600 /* close the second remote connection */
3602 cli_shutdown( cli_server2 );
3603 return WERR_OK;
3606 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3608 printf("print_processor_name: %s\n", r->print_processor_name);
3611 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3612 TALLOC_CTX *mem_ctx, int argc,
3613 const char **argv)
3615 WERROR werror;
3616 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3617 uint32_t num_procs, level = 1, i;
3618 union spoolss_PrintProcessorInfo *procs;
3620 /* Parse the command arguments */
3622 if (argc < 1 || argc > 4) {
3623 printf ("Usage: %s [environment] [level]\n", argv[0]);
3624 return WERR_OK;
3627 if (argc >= 2) {
3628 environment = argv[1];
3631 if (argc == 3) {
3632 level = atoi(argv[2]);
3635 /* Enumerate Print Processors */
3637 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3638 cli->srv_name_slash,
3639 environment,
3640 level,
3642 &num_procs,
3643 &procs);
3644 if (!W_ERROR_IS_OK(werror))
3645 goto done;
3647 /* Display output */
3649 for (i = 0; i < num_procs; i++) {
3650 switch (level) {
3651 case 1:
3652 display_proc_info1(&procs[i].info1);
3653 break;
3657 done:
3658 return werror;
3661 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3663 printf("name_array: %s\n", r->name_array);
3666 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3667 TALLOC_CTX *mem_ctx, int argc,
3668 const char **argv)
3670 WERROR werror;
3671 const char *print_processor_name = "winprint";
3672 uint32_t num_procs, level = 1, i;
3673 union spoolss_PrintProcDataTypesInfo *procs;
3675 /* Parse the command arguments */
3677 if (argc < 1 || argc > 4) {
3678 printf ("Usage: %s [environment] [level]\n", argv[0]);
3679 return WERR_OK;
3682 if (argc >= 2) {
3683 print_processor_name = argv[1];
3686 if (argc == 3) {
3687 level = atoi(argv[2]);
3690 /* Enumerate Print Processor Data Types */
3692 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3693 cli->srv_name_slash,
3694 print_processor_name,
3695 level,
3697 &num_procs,
3698 &procs);
3699 if (!W_ERROR_IS_OK(werror))
3700 goto done;
3702 /* Display output */
3704 for (i = 0; i < num_procs; i++) {
3705 switch (level) {
3706 case 1:
3707 display_proc_data_types_info1(&procs[i].info1);
3708 break;
3712 done:
3713 return werror;
3716 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3718 printf("monitor_name: %s\n", r->monitor_name);
3721 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3723 printf("monitor_name: %s\n", r->monitor_name);
3724 printf("environment: %s\n", r->environment);
3725 printf("dll_name: %s\n", r->dll_name);
3728 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3729 TALLOC_CTX *mem_ctx, int argc,
3730 const char **argv)
3732 WERROR werror;
3733 uint32_t count, level = 1, i;
3734 union spoolss_MonitorInfo *info;
3736 /* Parse the command arguments */
3738 if (argc > 2) {
3739 printf("Usage: %s [level]\n", argv[0]);
3740 return WERR_OK;
3743 if (argc == 2) {
3744 level = atoi(argv[1]);
3747 /* Enumerate Print Monitors */
3749 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3750 cli->srv_name_slash,
3751 level,
3753 &count,
3754 &info);
3755 if (!W_ERROR_IS_OK(werror)) {
3756 goto done;
3759 /* Display output */
3761 for (i = 0; i < count; i++) {
3762 switch (level) {
3763 case 1:
3764 display_monitor1(&info[i].info1);
3765 break;
3766 case 2:
3767 display_monitor2(&info[i].info2);
3768 break;
3772 done:
3773 return werror;
3776 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3777 TALLOC_CTX *mem_ctx, int argc,
3778 const char **argv)
3780 WERROR result;
3781 NTSTATUS status;
3782 struct policy_handle handle, gdi_handle;
3783 const char *printername;
3784 struct spoolss_DevmodeContainer devmode_ctr;
3785 struct dcerpc_binding_handle *b = cli->binding_handle;
3787 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3789 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3790 printername,
3791 SEC_FLAG_MAXIMUM_ALLOWED,
3792 &handle);
3793 if (!W_ERROR_IS_OK(result)) {
3794 return result;
3797 ZERO_STRUCT(devmode_ctr);
3799 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3800 &handle,
3801 &gdi_handle,
3802 &devmode_ctr,
3803 &result);
3804 if (!NT_STATUS_IS_OK(status)) {
3805 result = ntstatus_to_werror(status);
3806 goto done;
3808 if (!W_ERROR_IS_OK(result)) {
3809 goto done;
3812 done:
3813 if (is_valid_policy_hnd(&gdi_handle)) {
3814 WERROR _result;
3815 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3817 if (is_valid_policy_hnd(&handle)) {
3818 WERROR _result;
3819 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3822 return result;
3825 static WERROR cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client *cli,
3826 TALLOC_CTX *mem_ctx, int argc,
3827 const char **argv)
3829 WERROR result;
3830 NTSTATUS status;
3831 struct policy_handle handle, gdi_handle;
3832 const char *printername;
3833 struct spoolss_DevmodeContainer devmode_ctr;
3834 struct dcerpc_binding_handle *b = cli->binding_handle;
3835 DATA_BLOB in,out;
3836 uint32_t count = 0;
3838 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3840 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3841 printername,
3842 SEC_FLAG_MAXIMUM_ALLOWED,
3843 &handle);
3844 if (!W_ERROR_IS_OK(result)) {
3845 return result;
3848 ZERO_STRUCT(devmode_ctr);
3850 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3851 &handle,
3852 &gdi_handle,
3853 &devmode_ctr,
3854 &result);
3855 if (!NT_STATUS_IS_OK(status)) {
3856 result = ntstatus_to_werror(status);
3857 goto done;
3859 if (!W_ERROR_IS_OK(result)) {
3860 goto done;
3863 in = data_blob_string_const("");
3864 out = data_blob_talloc_zero(mem_ctx, 4);
3866 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3867 &gdi_handle,
3868 in.data,
3869 in.length,
3870 out.data,
3871 out.length,
3872 0, /* ul */
3873 &result);
3874 if (!NT_STATUS_IS_OK(status)) {
3875 result = ntstatus_to_werror(status);
3876 goto done;
3878 if (!W_ERROR_IS_OK(result)) {
3879 goto done;
3882 count = IVAL(out.data, 0);
3884 out = data_blob_talloc_zero(mem_ctx,
3885 count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
3887 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3888 &gdi_handle,
3889 in.data,
3890 in.length,
3891 out.data,
3892 out.length,
3893 0, /* ul */
3894 &result);
3895 if (!NT_STATUS_IS_OK(status)) {
3896 result = ntstatus_to_werror(status);
3897 goto done;
3899 if (!W_ERROR_IS_OK(result)) {
3900 goto done;
3904 enum ndr_err_code ndr_err;
3905 struct UNIVERSAL_FONT_ID_ctr r;
3907 ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
3908 (ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
3909 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3910 NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
3914 done:
3915 if (is_valid_policy_hnd(&gdi_handle)) {
3916 WERROR _result;
3917 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3919 if (is_valid_policy_hnd(&handle)) {
3920 WERROR _result;
3921 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3924 return result;
3927 static WERROR cmd_spoolss_get_core_printer_drivers(struct rpc_pipe_client *cli,
3928 TALLOC_CTX *mem_ctx, int argc,
3929 const char **argv)
3931 NTSTATUS status;
3932 HRESULT result;
3933 struct dcerpc_binding_handle *b = cli->binding_handle;
3934 const char *architecture = SPOOLSS_ARCHITECTURE_x64;
3935 struct spoolss_CorePrinterDriver core_printer_drivers;
3936 DATA_BLOB blob;
3937 bool ok;
3938 int i;
3939 uint32_t count;
3940 const char **array;
3942 if (argc == 1) {
3943 count = 1;
3944 array = talloc_zero_array(mem_ctx, const char *, count + 1);
3945 if (array == NULL) {
3946 return WERR_NOT_ENOUGH_MEMORY;
3948 array[0] = talloc_strdup(array, SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
3949 if (array[0] == NULL) {
3950 return WERR_NOT_ENOUGH_MEMORY;
3952 } else {
3953 count = argc -1;
3954 array = talloc_zero_array(mem_ctx, const char *, count + 1);
3955 if (array == NULL) {
3956 return WERR_NOT_ENOUGH_MEMORY;
3958 for (i = 0; i < argc - 1; i++) {
3959 array[i] = talloc_strdup(array, argv[i + 1]);
3960 if (array[i] == NULL) {
3961 return WERR_NOT_ENOUGH_MEMORY;
3966 ok = push_reg_multi_sz(mem_ctx, &blob, array);
3967 if (!ok) {
3968 return WERR_NOT_ENOUGH_MEMORY;
3971 status = dcerpc_spoolss_GetCorePrinterDrivers(b, mem_ctx,
3972 cli->srv_name_slash,
3973 architecture,
3974 blob.length/2,
3975 (uint16_t *)blob.data,
3976 count,
3977 &core_printer_drivers,
3978 &result);
3979 if (!NT_STATUS_IS_OK(status)) {
3980 return ntstatus_to_werror(status);
3983 if (!HRES_IS_OK(result)) {
3984 return W_ERROR(WIN32_FROM_HRESULT(result));
3987 return WERR_OK;
3990 static WERROR cmd_spoolss_enum_permachineconnections(struct rpc_pipe_client *cli,
3991 TALLOC_CTX *mem_ctx, int argc,
3992 const char **argv)
3994 NTSTATUS status;
3995 WERROR result;
3996 struct dcerpc_binding_handle *b = cli->binding_handle;
3997 const char *servername = cli->srv_name_slash;
3998 DATA_BLOB in = data_blob_null;
3999 struct spoolss_PrinterInfo4 *info;
4000 uint32_t needed, count;
4002 if (argc > 2) {
4003 printf("usage: %s [servername]\n", argv[0]);
4004 return WERR_OK;
4007 if (argc > 1) {
4008 servername = argv[1];
4011 status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
4012 servername,
4013 &in,
4014 in.length,
4015 &count,
4016 &info,
4017 &needed,
4018 &result);
4019 if (!NT_STATUS_IS_OK(status)) {
4020 return ntstatus_to_werror(status);
4023 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
4024 in = data_blob_talloc_zero(mem_ctx, needed);
4025 status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
4026 servername,
4027 &in,
4028 in.length,
4029 &count,
4030 &info,
4031 &needed,
4032 &result);
4033 if (!NT_STATUS_IS_OK(status)) {
4034 return ntstatus_to_werror(status);
4038 return result;
4041 static WERROR cmd_spoolss_add_permachineconnection(struct rpc_pipe_client *cli,
4042 TALLOC_CTX *mem_ctx, int argc,
4043 const char **argv)
4045 NTSTATUS status;
4046 WERROR result;
4047 struct dcerpc_binding_handle *b = cli->binding_handle;
4048 const char *servername = cli->srv_name_slash;
4049 const char *printername = "Microsoft Print to PDF";
4050 const char *printserver = "samba.org";
4051 const char *provider = ""; /* refers to Win32spl.dll then */
4052 const char *composed_printername;
4054 if (argc > 5) {
4055 printf("usage: %s [servername] [printername] [printserver] [provider]\n", argv[0]);
4056 return WERR_OK;
4059 if (argc > 1) {
4060 servername = argv[1];
4062 if (argc > 2) {
4063 printername = argv[2];
4065 if (argc > 3) {
4066 printserver = argv[3];
4068 if (argc > 4) {
4069 provider = argv[4];
4072 composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4073 printername);
4074 if (composed_printername == NULL) {
4075 return WERR_NOT_ENOUGH_MEMORY;
4077 status = dcerpc_spoolss_AddPerMachineConnection(b, mem_ctx,
4078 servername,
4079 composed_printername,
4080 printserver,
4081 provider,
4082 &result);
4083 if (!NT_STATUS_IS_OK(status)) {
4084 return ntstatus_to_werror(status);
4087 return result;
4090 static WERROR cmd_spoolss_del_permachineconnection(struct rpc_pipe_client *cli,
4091 TALLOC_CTX *mem_ctx, int argc,
4092 const char **argv)
4094 NTSTATUS status;
4095 WERROR result;
4096 struct dcerpc_binding_handle *b = cli->binding_handle;
4097 const char *servername = cli->srv_name_slash;
4098 const char *printername = "Microsoft Print to PDF";
4099 const char *composed_printername;
4101 if (argc > 3) {
4102 printf("usage: %s [servername] [printername]\n", argv[0]);
4103 return WERR_OK;
4106 if (argc > 1) {
4107 servername = argv[1];
4109 if (argc > 2) {
4110 printername = argv[2];
4113 composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4114 printername);
4115 if (composed_printername == NULL) {
4116 return WERR_NOT_ENOUGH_MEMORY;
4119 status = dcerpc_spoolss_DeletePerMachineConnection(b, mem_ctx,
4120 servername,
4121 composed_printername,
4122 &result);
4123 if (!NT_STATUS_IS_OK(status)) {
4124 return ntstatus_to_werror(status);
4127 return result;
4130 /* List of commands exported by this module */
4131 struct cmd_set spoolss_commands[] = {
4134 .name = "SPOOLSS",
4138 .name = "adddriver",
4139 .returntype = RPC_RTYPE_WERROR,
4140 .ntfn = NULL,
4141 .wfn = cmd_spoolss_addprinterdriver,
4142 .table = &ndr_table_spoolss,
4143 .rpc_pipe = NULL,
4144 .description = "Add a print driver",
4145 .usage = "",
4146 .use_netlogon_creds = false,
4149 .name = "addprinter",
4150 .returntype = RPC_RTYPE_WERROR,
4151 .ntfn = NULL,
4152 .wfn = cmd_spoolss_addprinterex,
4153 .table = &ndr_table_spoolss,
4154 .rpc_pipe = NULL,
4155 .description = "Add a printer",
4156 .usage = "",
4159 .name = "deldriver",
4160 .returntype = RPC_RTYPE_WERROR,
4161 .ntfn = NULL,
4162 .wfn = cmd_spoolss_deletedriver,
4163 .table = &ndr_table_spoolss,
4164 .rpc_pipe = NULL,
4165 .description = "Delete a printer driver",
4166 .usage = "",
4169 .name = "deldriverex",
4170 .returntype = RPC_RTYPE_WERROR,
4171 .ntfn = NULL,
4172 .wfn = cmd_spoolss_deletedriverex,
4173 .table = &ndr_table_spoolss,
4174 .rpc_pipe = NULL,
4175 .description = "Delete a printer driver with files",
4176 .usage = "",
4179 .name = "enumdata",
4180 .returntype = RPC_RTYPE_WERROR,
4181 .ntfn = NULL,
4182 .wfn = cmd_spoolss_enum_data,
4183 .table = &ndr_table_spoolss,
4184 .rpc_pipe = NULL,
4185 .description = "Enumerate printer data",
4186 .usage = "",
4189 .name = "enumdataex",
4190 .returntype = RPC_RTYPE_WERROR,
4191 .ntfn = NULL,
4192 .wfn = cmd_spoolss_enum_data_ex,
4193 .table = &ndr_table_spoolss,
4194 .rpc_pipe = NULL,
4195 .description = "Enumerate printer data for a key",
4196 .usage = "",
4199 .name = "enumkey",
4200 .returntype = RPC_RTYPE_WERROR,
4201 .ntfn = NULL,
4202 .wfn = cmd_spoolss_enum_printerkey,
4203 .table = &ndr_table_spoolss,
4204 .rpc_pipe = NULL,
4205 .description = "Enumerate printer keys",
4206 .usage = "",
4209 .name = "enumjobs",
4210 .returntype = RPC_RTYPE_WERROR,
4211 .ntfn = NULL,
4212 .wfn = cmd_spoolss_enum_jobs,
4213 .table = &ndr_table_spoolss,
4214 .rpc_pipe = NULL,
4215 .description = "Enumerate print jobs",
4216 .usage = "",
4219 .name = "getjob",
4220 .returntype = RPC_RTYPE_WERROR,
4221 .ntfn = NULL,
4222 .wfn = cmd_spoolss_get_job,
4223 .table = &ndr_table_spoolss,
4224 .rpc_pipe = NULL,
4225 .description = "Get print job",
4226 .usage = "",
4229 .name = "setjob",
4230 .returntype = RPC_RTYPE_WERROR,
4231 .ntfn = NULL,
4232 .wfn = cmd_spoolss_set_job,
4233 .table = &ndr_table_spoolss,
4234 .rpc_pipe = NULL,
4235 .description = "Set print job",
4236 .usage = "",
4239 .name = "enumports",
4240 .returntype = RPC_RTYPE_WERROR,
4241 .ntfn = NULL,
4242 .wfn = cmd_spoolss_enum_ports,
4243 .table = &ndr_table_spoolss,
4244 .rpc_pipe = NULL,
4245 .description = "Enumerate printer ports",
4246 .usage = "",
4249 .name = "enumdrivers",
4250 .returntype = RPC_RTYPE_WERROR,
4251 .ntfn = NULL,
4252 .wfn = cmd_spoolss_enum_drivers,
4253 .table = &ndr_table_spoolss,
4254 .rpc_pipe = NULL,
4255 .description = "Enumerate installed printer drivers",
4256 .usage = "",
4259 .name = "enumprinters",
4260 .returntype = RPC_RTYPE_WERROR,
4261 .ntfn = NULL,
4262 .wfn = cmd_spoolss_enum_printers,
4263 .table = &ndr_table_spoolss,
4264 .rpc_pipe = NULL,
4265 .description = "Enumerate printers",
4266 .usage = "",
4269 .name = "getdata",
4270 .returntype = RPC_RTYPE_WERROR,
4271 .ntfn = NULL,
4272 .wfn = cmd_spoolss_getprinterdata,
4273 .table = &ndr_table_spoolss,
4274 .rpc_pipe = NULL,
4275 .description = "Get print driver data",
4276 .usage = "",
4279 .name = "getdataex",
4280 .returntype = RPC_RTYPE_WERROR,
4281 .ntfn = NULL,
4282 .wfn = cmd_spoolss_getprinterdataex,
4283 .table = &ndr_table_spoolss,
4284 .rpc_pipe = NULL,
4285 .description = "Get printer driver data with keyname",
4286 .usage = "",
4289 .name = "getdriver",
4290 .returntype = RPC_RTYPE_WERROR,
4291 .ntfn = NULL,
4292 .wfn = cmd_spoolss_getdriver,
4293 .table = &ndr_table_spoolss,
4294 .rpc_pipe = NULL,
4295 .description = "Get print driver information",
4296 .usage = "",
4299 .name = "getdriverdir",
4300 .returntype = RPC_RTYPE_WERROR,
4301 .ntfn = NULL,
4302 .wfn = cmd_spoolss_getdriverdir,
4303 .table = &ndr_table_spoolss,
4304 .rpc_pipe = NULL,
4305 .description = "Get print driver upload directory",
4306 .usage = "",
4309 .name = "getdriverpackagepath",
4310 .returntype = RPC_RTYPE_WERROR,
4311 .ntfn = NULL,
4312 .wfn = cmd_spoolss_getdriverpackagepath,
4313 .table = &ndr_table_spoolss,
4314 .rpc_pipe = NULL,
4315 .description = "Get print driver package download directory",
4316 .usage = "",
4319 .name = "getprinter",
4320 .returntype = RPC_RTYPE_WERROR,
4321 .ntfn = NULL,
4322 .wfn = cmd_spoolss_getprinter,
4323 .table = &ndr_table_spoolss,
4324 .rpc_pipe = NULL,
4325 .description = "Get printer info",
4326 .usage = "",
4329 .name = "openprinter",
4330 .returntype = RPC_RTYPE_WERROR,
4331 .ntfn = NULL,
4332 .wfn = cmd_spoolss_open_printer,
4333 .table = &ndr_table_spoolss,
4334 .rpc_pipe = NULL,
4335 .description = "Open printer handle",
4336 .usage = "",
4339 .name = "openprinter_ex",
4340 .returntype = RPC_RTYPE_WERROR,
4341 .ntfn = NULL,
4342 .wfn = cmd_spoolss_open_printer_ex,
4343 .table = &ndr_table_spoolss,
4344 .rpc_pipe = NULL,
4345 .description = "Open printer handle",
4346 .usage = "",
4349 .name = "setdriver",
4350 .returntype = RPC_RTYPE_WERROR,
4351 .ntfn = NULL,
4352 .wfn = cmd_spoolss_setdriver,
4353 .table = &ndr_table_spoolss,
4354 .rpc_pipe = NULL,
4355 .description = "Set printer driver",
4356 .usage = "",
4359 .name = "getprintprocdir",
4360 .returntype = RPC_RTYPE_WERROR,
4361 .ntfn = NULL,
4362 .wfn = cmd_spoolss_getprintprocdir,
4363 .table = &ndr_table_spoolss,
4364 .rpc_pipe = NULL,
4365 .description = "Get print processor directory",
4366 .usage = "",
4369 .name = "addform",
4370 .returntype = RPC_RTYPE_WERROR,
4371 .ntfn = NULL,
4372 .wfn = cmd_spoolss_addform,
4373 .table = &ndr_table_spoolss,
4374 .rpc_pipe = NULL,
4375 .description = "Add form",
4376 .usage = "",
4379 .name = "setform",
4380 .returntype = RPC_RTYPE_WERROR,
4381 .ntfn = NULL,
4382 .wfn = cmd_spoolss_setform,
4383 .table = &ndr_table_spoolss,
4384 .rpc_pipe = NULL,
4385 .description = "Set form",
4386 .usage = "",
4389 .name = "getform",
4390 .returntype = RPC_RTYPE_WERROR,
4391 .ntfn = NULL,
4392 .wfn = cmd_spoolss_getform,
4393 .table = &ndr_table_spoolss,
4394 .rpc_pipe = NULL,
4395 .description = "Get form",
4396 .usage = "",
4399 .name = "deleteform",
4400 .returntype = RPC_RTYPE_WERROR,
4401 .ntfn = NULL,
4402 .wfn = cmd_spoolss_deleteform,
4403 .table = &ndr_table_spoolss,
4404 .rpc_pipe = NULL,
4405 .description = "Delete form",
4406 .usage = "",
4409 .name = "enumforms",
4410 .returntype = RPC_RTYPE_WERROR,
4411 .ntfn = NULL,
4412 .wfn = cmd_spoolss_enum_forms,
4413 .table = &ndr_table_spoolss,
4414 .rpc_pipe = NULL,
4415 .description = "Enumerate forms",
4416 .usage = "",
4419 .name = "setprinter",
4420 .returntype = RPC_RTYPE_WERROR,
4421 .ntfn = NULL,
4422 .wfn = cmd_spoolss_setprinter,
4423 .table = &ndr_table_spoolss,
4424 .rpc_pipe = NULL,
4425 .description = "Set printer comment",
4426 .usage = "",
4429 .name = "setprintername",
4430 .returntype = RPC_RTYPE_WERROR,
4431 .ntfn = NULL,
4432 .wfn = cmd_spoolss_setprintername,
4433 .table = &ndr_table_spoolss,
4434 .rpc_pipe = NULL,
4435 .description = "Set printername",
4436 .usage = "",
4439 .name = "setprinterdata",
4440 .returntype = RPC_RTYPE_WERROR,
4441 .ntfn = NULL,
4442 .wfn = cmd_spoolss_setprinterdata,
4443 .table = &ndr_table_spoolss,
4444 .rpc_pipe = NULL,
4445 .description = "Set REG_SZ printer data",
4446 .usage = "",
4449 .name = "rffpcnex",
4450 .returntype = RPC_RTYPE_WERROR,
4451 .ntfn = NULL,
4452 .wfn = cmd_spoolss_rffpcnex,
4453 .table = &ndr_table_spoolss,
4454 .rpc_pipe = NULL,
4455 .description = "Rffpcnex test",
4456 .usage = "",
4459 .name = "printercmp",
4460 .returntype = RPC_RTYPE_WERROR,
4461 .ntfn = NULL,
4462 .wfn = cmd_spoolss_printercmp,
4463 .table = &ndr_table_spoolss,
4464 .rpc_pipe = NULL,
4465 .description = "Printer comparison test",
4466 .usage = "",
4469 .name = "enumprocs",
4470 .returntype = RPC_RTYPE_WERROR,
4471 .ntfn = NULL,
4472 .wfn = cmd_spoolss_enum_procs,
4473 .table = &ndr_table_spoolss,
4474 .rpc_pipe = NULL,
4475 .description = "Enumerate Print Processors",
4476 .usage = "",
4479 .name = "enumprocdatatypes",
4480 .returntype = RPC_RTYPE_WERROR,
4481 .ntfn = NULL,
4482 .wfn = cmd_spoolss_enum_proc_data_types,
4483 .table = &ndr_table_spoolss,
4484 .rpc_pipe = NULL,
4485 .description = "Enumerate Print Processor Data Types",
4486 .usage = "",
4489 .name = "enummonitors",
4490 .returntype = RPC_RTYPE_WERROR,
4491 .ntfn = NULL,
4492 .wfn = cmd_spoolss_enum_monitors,
4493 .table = &ndr_table_spoolss,
4494 .rpc_pipe = NULL,
4495 .description = "Enumerate Print Monitors",
4496 .usage = "",
4499 .name = "createprinteric",
4500 .returntype = RPC_RTYPE_WERROR,
4501 .ntfn = NULL,
4502 .wfn = cmd_spoolss_create_printer_ic,
4503 .table = &ndr_table_spoolss,
4504 .rpc_pipe = NULL,
4505 .description = "Create Printer IC",
4506 .usage = "",
4509 .name = "playgdiscriptonprinteric",
4510 .returntype = RPC_RTYPE_WERROR,
4511 .ntfn = NULL,
4512 .wfn = cmd_spoolss_play_gdi_script_on_printer_ic,
4513 .table = &ndr_table_spoolss,
4514 .rpc_pipe = NULL,
4515 .description = "Create Printer IC",
4516 .usage = "",
4519 .name = "getcoreprinterdrivers",
4520 .returntype = RPC_RTYPE_WERROR,
4521 .ntfn = NULL,
4522 .wfn = cmd_spoolss_get_core_printer_drivers,
4523 .table = &ndr_table_spoolss,
4524 .rpc_pipe = NULL,
4525 .description = "Get CorePrinterDriver",
4526 .usage = "",
4529 .name = "enumpermachineconnections",
4530 .returntype = RPC_RTYPE_WERROR,
4531 .ntfn = NULL,
4532 .wfn = cmd_spoolss_enum_permachineconnections,
4533 .table = &ndr_table_spoolss,
4534 .rpc_pipe = NULL,
4535 .description = "Enumerate Per Machine Connections",
4536 .usage = "",
4539 .name = "addpermachineconnection",
4540 .returntype = RPC_RTYPE_WERROR,
4541 .ntfn = NULL,
4542 .wfn = cmd_spoolss_add_permachineconnection,
4543 .table = &ndr_table_spoolss,
4544 .rpc_pipe = NULL,
4545 .description = "Add Per Machine Connection",
4546 .usage = "",
4549 .name = "delpermachineconnection",
4550 .returntype = RPC_RTYPE_WERROR,
4551 .ntfn = NULL,
4552 .wfn = cmd_spoolss_del_permachineconnection,
4553 .table = &ndr_table_spoolss,
4554 .rpc_pipe = NULL,
4555 .description = "Delete Per Machine Connection",
4556 .usage = "",
4559 .name = NULL,