s3: fix net and rpcclient after setprinterdataex changes.
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blob5393ba75a9963fbf7be95688f098cb81fd1f5771
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/cli_spoolss.h"
29 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
30 { \
31 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
32 _cli->srv_name_slash, _arg); \
33 W_ERROR_HAVE_NO_MEMORY(_printername); \
36 /* The version int is used by getdrivers. Note that
37 all architecture strings that support mutliple
38 versions must be grouped together since enumdrivers
39 uses this property to prevent issuing multiple
40 enumdriver calls for the same arch */
43 static const struct print_architecture_table_node archi_table[]= {
45 {"Windows 4.0", "WIN40", 0 },
46 {"Windows NT x86", "W32X86", 2 },
47 {"Windows NT x86", "W32X86", 3 },
48 {"Windows NT R4000", "W32MIPS", 2 },
49 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
50 {"Windows NT PowerPC", "W32PPC", 2 },
51 {"Windows IA64", "IA64", 3 },
52 {"Windows x64", "x64", 3 },
53 {NULL, "", -1 }
56 /**
57 * @file
59 * rpcclient module for SPOOLSS rpc pipe.
61 * This generally just parses and checks command lines, and then calls
62 * a cli_spoolss function.
63 **/
65 /****************************************************************************
66 function to do the mapping between the long architecture name and
67 the short one.
68 ****************************************************************************/
70 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
72 int i=-1;
74 DEBUG(107,("Getting architecture dependant directory\n"));
75 do {
76 i++;
77 } while ( (archi_table[i].long_archi!=NULL ) &&
78 StrCaseCmp(long_archi, archi_table[i].long_archi) );
80 if (archi_table[i].long_archi==NULL) {
81 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
82 return NULL;
85 /* this might be client code - but shouldn't this be an fstrcpy etc? */
88 DEBUGADD(108,("index: [%d]\n", i));
89 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
90 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
92 return archi_table[i].short_archi;
95 /****************************************************************************
96 ****************************************************************************/
98 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
99 TALLOC_CTX *mem_ctx,
100 int argc, const char **argv)
102 WERROR werror;
103 struct policy_handle hnd;
105 if (argc != 2) {
106 printf("Usage: %s <printername>\n", argv[0]);
107 return WERR_OK;
110 if (!cli)
111 return WERR_GENERAL_FAILURE;
113 /* Open the printer handle */
115 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
116 argv[1],
117 PRINTER_ALL_ACCESS,
118 &hnd);
119 if (W_ERROR_IS_OK(werror)) {
120 printf("Printer %s opened successfully\n", argv[1]);
121 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
123 if (!W_ERROR_IS_OK(werror)) {
124 printf("Error closing printer handle! (%s)\n",
125 get_dos_error_msg(werror));
129 return werror;
133 /****************************************************************************
134 ****************************************************************************/
136 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
138 if (!r)
139 return;
141 printf("\tprintername:[%s]\n", r->printername);
142 printf("\tservername:[%s]\n", r->servername);
143 printf("\tcjobs:[0x%x]\n", r->cjobs);
144 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
145 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
146 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
147 r->time.day, r->time.day_of_week);
148 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
149 r->time.second, r->time.millisecond);
151 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
152 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
154 printf("\tversion:[0x%x]\n", r->version);
155 printf("\tfree_build:[0x%x]\n", r->free_build);
156 printf("\tspooling:[0x%x]\n", r->spooling);
157 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
158 printf("\tsession_counter:[0x%x]\n", r->session_counter);
159 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
160 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
161 printf("\tjob_error:[0x%x]\n", r->job_error);
162 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
163 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
164 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
165 printf("\tchange_id:[0x%x]\n", r->change_id);
166 printf("\tlast_error: %s\n", win_errstr(r->last_error));
167 printf("\tstatus:[0x%x]\n", r->status);
168 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
169 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
170 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
171 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
172 printf("\tref_ic:[0x%x]\n", r->ref_ic);
173 printf("\treserved2:[0x%x]\n", r->reserved2);
174 printf("\treserved3:[0x%x]\n", r->reserved3);
176 printf("\n");
179 /****************************************************************************
180 ****************************************************************************/
182 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
184 printf("\tflags:[0x%x]\n", r->flags);
185 printf("\tname:[%s]\n", r->name);
186 printf("\tdescription:[%s]\n", r->description);
187 printf("\tcomment:[%s]\n", r->comment);
189 printf("\n");
192 /****************************************************************************
193 ****************************************************************************/
195 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
197 printf("\tservername:[%s]\n", r->servername);
198 printf("\tprintername:[%s]\n", r->printername);
199 printf("\tsharename:[%s]\n", r->sharename);
200 printf("\tportname:[%s]\n", r->portname);
201 printf("\tdrivername:[%s]\n", r->drivername);
202 printf("\tcomment:[%s]\n", r->comment);
203 printf("\tlocation:[%s]\n", r->location);
204 printf("\tsepfile:[%s]\n", r->sepfile);
205 printf("\tprintprocessor:[%s]\n", r->printprocessor);
206 printf("\tdatatype:[%s]\n", r->datatype);
207 printf("\tparameters:[%s]\n", r->parameters);
208 printf("\tattributes:[0x%x]\n", r->attributes);
209 printf("\tpriority:[0x%x]\n", r->priority);
210 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
211 printf("\tstarttime:[0x%x]\n", r->starttime);
212 printf("\tuntiltime:[0x%x]\n", r->untiltime);
213 printf("\tstatus:[0x%x]\n", r->status);
214 printf("\tcjobs:[0x%x]\n", r->cjobs);
215 printf("\taverageppm:[0x%x]\n", r->averageppm);
217 if (r->secdesc)
218 display_sec_desc(r->secdesc);
220 printf("\n");
223 /****************************************************************************
224 ****************************************************************************/
226 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
228 display_sec_desc(r->secdesc);
230 printf("\n");
233 /****************************************************************************
234 ****************************************************************************/
236 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
238 printf("\tservername:[%s]\n", r->servername);
239 printf("\tprintername:[%s]\n", r->printername);
240 printf("\tattributes:[0x%x]\n", r->attributes);
241 printf("\n");
244 /****************************************************************************
245 ****************************************************************************/
247 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
249 printf("\tprintername:[%s]\n", r->printername);
250 printf("\tportname:[%s]\n", r->portname);
251 printf("\tattributes:[0x%x]\n", r->attributes);
252 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
253 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
254 printf("\n");
257 /****************************************************************************
258 ****************************************************************************/
260 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
262 printf("\tstatus:[0x%x]\n", r->status);
263 printf("\n");
266 /****************************************************************************
267 ****************************************************************************/
269 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
271 printf("\tguid:[%s]\n", r->guid);
272 printf("\taction:[0x%x]\n", r->action);
273 printf("\n");
276 /****************************************************************************
277 ****************************************************************************/
279 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
280 TALLOC_CTX *mem_ctx,
281 int argc, const char **argv)
283 WERROR result;
284 uint32_t level = 1;
285 union spoolss_PrinterInfo *info;
286 uint32_t i, count;
287 const char *name;
288 uint32_t flags = PRINTER_ENUM_LOCAL;
290 if (argc > 4) {
291 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
292 return WERR_OK;
295 if (argc >= 2) {
296 level = atoi(argv[1]);
299 if (argc >= 3) {
300 name = argv[2];
301 } else {
302 name = cli->srv_name_slash;
305 if (argc == 4) {
306 flags = atoi(argv[3]);
309 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
310 flags,
311 name,
312 level,
314 &count,
315 &info);
316 if (W_ERROR_IS_OK(result)) {
318 if (!count) {
319 printf ("No printers returned.\n");
320 goto done;
323 for (i = 0; i < count; i++) {
324 switch (level) {
325 case 0:
326 display_print_info0(&info[i].info0);
327 break;
328 case 1:
329 display_print_info1(&info[i].info1);
330 break;
331 case 2:
332 display_print_info2(&info[i].info2);
333 break;
334 case 3:
335 display_print_info3(&info[i].info3);
336 break;
337 case 4:
338 display_print_info4(&info[i].info4);
339 break;
340 case 5:
341 display_print_info5(&info[i].info5);
342 break;
343 case 6:
344 display_print_info6(&info[i].info6);
345 break;
346 default:
347 printf("unknown info level %d\n", level);
348 goto done;
352 done:
354 return result;
357 /****************************************************************************
358 ****************************************************************************/
360 static void display_port_info_1(struct spoolss_PortInfo1 *r)
362 printf("\tPort Name:\t[%s]\n", r->port_name);
365 /****************************************************************************
366 ****************************************************************************/
368 static void display_port_info_2(struct spoolss_PortInfo2 *r)
370 printf("\tPort Name:\t[%s]\n", r->port_name);
371 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
372 printf("\tDescription:\t[%s]\n", r->description);
373 printf("\tPort Type:\t" );
374 if (r->port_type) {
375 int comma = 0; /* hack */
376 printf( "[" );
377 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
378 printf( "Read" );
379 comma = 1;
381 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
382 printf( "%sWrite", comma ? ", " : "" );
383 comma = 1;
385 /* These two have slightly different interpretations
386 on 95/98/ME but I'm disregarding that for now */
387 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
388 printf( "%sRedirected", comma ? ", " : "" );
389 comma = 1;
391 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
392 printf( "%sNet-Attached", comma ? ", " : "" );
394 printf( "]\n" );
395 } else {
396 printf( "[Unset]\n" );
398 printf("\tReserved:\t[%d]\n", r->reserved);
399 printf("\n");
402 /****************************************************************************
403 ****************************************************************************/
405 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
406 TALLOC_CTX *mem_ctx, int argc,
407 const char **argv)
409 WERROR result;
410 uint32_t level = 1;
411 uint32_t count;
412 union spoolss_PortInfo *info;
414 if (argc > 2) {
415 printf("Usage: %s [level]\n", argv[0]);
416 return WERR_OK;
419 if (argc == 2) {
420 level = atoi(argv[1]);
423 /* Enumerate ports */
425 result = rpccli_spoolss_enumports(cli, mem_ctx,
426 cli->srv_name_slash,
427 level,
429 &count,
430 &info);
431 if (W_ERROR_IS_OK(result)) {
432 int i;
434 for (i = 0; i < count; i++) {
435 switch (level) {
436 case 1:
437 display_port_info_1(&info[i].info1);
438 break;
439 case 2:
440 display_port_info_2(&info[i].info2);
441 break;
442 default:
443 printf("unknown info level %d\n", level);
444 break;
449 return result;
452 /****************************************************************************
453 ****************************************************************************/
455 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
456 TALLOC_CTX *mem_ctx,
457 int argc, const char **argv)
459 struct policy_handle pol;
460 WERROR result;
461 NTSTATUS status;
462 uint32_t info_level = 2;
463 union spoolss_PrinterInfo info;
464 struct spoolss_SetPrinterInfoCtr info_ctr;
465 const char *printername, *comment = NULL;
466 struct spoolss_DevmodeContainer devmode_ctr;
467 struct sec_desc_buf secdesc_ctr;
469 if (argc == 1 || argc > 3) {
470 printf("Usage: %s printername comment\n", argv[0]);
472 return WERR_OK;
475 /* Open a printer handle */
476 if (argc == 3) {
477 comment = argv[2];
480 ZERO_STRUCT(devmode_ctr);
481 ZERO_STRUCT(secdesc_ctr);
483 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
485 /* get a printer handle */
486 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
487 printername,
488 PRINTER_ALL_ACCESS,
489 &pol);
490 if (!W_ERROR_IS_OK(result))
491 goto done;
493 /* Get printer info */
494 result = rpccli_spoolss_getprinter(cli, mem_ctx,
495 &pol,
496 info_level,
498 &info);
499 if (!W_ERROR_IS_OK(result))
500 goto done;
503 /* Modify the comment. */
504 info.info2.comment = comment;
505 info.info2.secdesc = NULL;
506 info.info2.devmode = NULL;
508 info_ctr.level = 2;
509 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
511 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
512 &pol,
513 &info_ctr,
514 &devmode_ctr,
515 &secdesc_ctr,
516 0, /* command */
517 &result);
518 if (W_ERROR_IS_OK(result))
519 printf("Success in setting comment.\n");
521 done:
522 if (is_valid_policy_hnd(&pol))
523 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
525 return result;
528 /****************************************************************************
529 ****************************************************************************/
531 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
532 TALLOC_CTX *mem_ctx,
533 int argc, const char **argv)
535 struct policy_handle pol;
536 WERROR result;
537 NTSTATUS status;
538 uint32_t info_level = 2;
539 union spoolss_PrinterInfo info;
540 const char *printername,
541 *new_printername = NULL;
542 struct spoolss_SetPrinterInfoCtr info_ctr;
543 struct spoolss_DevmodeContainer devmode_ctr;
544 struct sec_desc_buf secdesc_ctr;
546 ZERO_STRUCT(devmode_ctr);
547 ZERO_STRUCT(secdesc_ctr);
549 if (argc == 1 || argc > 3) {
550 printf("Usage: %s printername new_printername\n", argv[0]);
552 return WERR_OK;
555 /* Open a printer handle */
556 if (argc == 3) {
557 new_printername = argv[2];
560 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
562 /* get a printer handle */
563 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
564 printername,
565 PRINTER_ALL_ACCESS,
566 &pol);
567 if (!W_ERROR_IS_OK(result))
568 goto done;
570 /* Get printer info */
571 result = rpccli_spoolss_getprinter(cli, mem_ctx,
572 &pol,
573 info_level,
575 &info);
576 if (!W_ERROR_IS_OK(result))
577 goto done;
579 /* Modify the printername. */
580 info.info2.printername = new_printername;
581 info.info2.devmode = NULL;
582 info.info2.secdesc = NULL;
584 info_ctr.level = info_level;
585 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
587 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
588 &pol,
589 &info_ctr,
590 &devmode_ctr,
591 &secdesc_ctr,
592 0, /* command */
593 &result);
594 if (W_ERROR_IS_OK(result))
595 printf("Success in setting printername.\n");
597 done:
598 if (is_valid_policy_hnd(&pol))
599 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
601 return result;
604 /****************************************************************************
605 ****************************************************************************/
607 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
608 TALLOC_CTX *mem_ctx,
609 int argc, const char **argv)
611 struct policy_handle pol;
612 WERROR result;
613 uint32_t level = 1;
614 const char *printername;
615 union spoolss_PrinterInfo info;
617 if (argc == 1 || argc > 3) {
618 printf("Usage: %s <printername> [level]\n", argv[0]);
619 return WERR_OK;
622 /* Open a printer handle */
623 if (argc == 3) {
624 level = atoi(argv[2]);
627 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
629 /* get a printer handle */
631 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
632 printername,
633 SEC_FLAG_MAXIMUM_ALLOWED,
634 &pol);
635 if (!W_ERROR_IS_OK(result)) {
636 goto done;
639 /* Get printer info */
641 result = rpccli_spoolss_getprinter(cli, mem_ctx,
642 &pol,
643 level,
645 &info);
646 if (!W_ERROR_IS_OK(result)) {
647 goto done;
650 /* Display printer info */
651 switch (level) {
652 case 0:
653 display_print_info0(&info.info0);
654 break;
655 case 1:
656 display_print_info1(&info.info1);
657 break;
658 case 2:
659 display_print_info2(&info.info2);
660 break;
661 case 3:
662 display_print_info3(&info.info3);
663 break;
664 case 4:
665 display_print_info4(&info.info4);
666 break;
667 case 5:
668 display_print_info5(&info.info5);
669 break;
670 case 6:
671 display_print_info6(&info.info6);
672 break;
673 case 7:
674 display_print_info7(&info.info7);
675 break;
676 default:
677 printf("unknown info level %d\n", level);
678 break;
680 done:
681 if (is_valid_policy_hnd(&pol)) {
682 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
685 return result;
688 /****************************************************************************
689 ****************************************************************************/
691 static void display_reg_value(struct regval_blob value)
693 const char *text = NULL;
694 DATA_BLOB blob;
696 switch(value.type) {
697 case REG_DWORD:
698 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
699 *((uint32_t *) value.data_p));
700 break;
701 case REG_SZ:
702 blob = data_blob_const(value.data_p, value.size);
703 pull_reg_sz(talloc_tos(), &blob, &text);
704 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
705 break;
706 case REG_BINARY: {
707 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
708 size_t i, len;
709 printf("%s: REG_BINARY:", value.valuename);
710 len = strlen(hex);
711 for (i=0; i<len; i++) {
712 if (hex[i] == '\0') {
713 break;
715 if (i%40 == 0) {
716 putchar('\n');
718 putchar(hex[i]);
720 TALLOC_FREE(hex);
721 putchar('\n');
722 break;
724 case REG_MULTI_SZ: {
725 uint32_t i;
726 const char **values;
727 blob = data_blob_const(value.data_p, value.size);
729 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
730 d_printf("pull_reg_multi_sz failed\n");
731 break;
734 printf("%s: REG_MULTI_SZ: \n", value.valuename);
735 for (i=0; values[i] != NULL; i++) {
736 d_printf("%s\n", values[i]);
738 TALLOC_FREE(values);
739 break;
741 default:
742 printf("%s: unknown type %d\n", value.valuename, value.type);
747 /****************************************************************************
748 ****************************************************************************/
750 static void display_printer_data(const char *v,
751 enum winreg_Type type,
752 union spoolss_PrinterData *r)
754 int i;
756 switch (type) {
757 case REG_DWORD:
758 printf("%s: REG_DWORD: 0x%08x\n", v, r->value);
759 break;
760 case REG_SZ:
761 printf("%s: REG_SZ: %s\n", v, r->string);
762 break;
763 case REG_BINARY: {
764 char *hex = hex_encode_talloc(NULL,
765 r->binary.data, r->binary.length);
766 size_t len;
767 printf("%s: REG_BINARY:", v);
768 len = strlen(hex);
769 for (i=0; i<len; i++) {
770 if (hex[i] == '\0') {
771 break;
773 if (i%40 == 0) {
774 putchar('\n');
776 putchar(hex[i]);
778 TALLOC_FREE(hex);
779 putchar('\n');
780 break;
782 case REG_MULTI_SZ:
783 printf("%s: REG_MULTI_SZ: ", v);
784 for (i=0; r->string_array[i] != NULL; i++) {
785 printf("%s ", r->string_array[i]);
787 printf("\n");
788 break;
789 default:
790 printf("%s: unknown type 0x%02x:\n", v, type);
791 break;
795 /****************************************************************************
796 ****************************************************************************/
798 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
799 TALLOC_CTX *mem_ctx,
800 int argc, const char **argv)
802 struct policy_handle pol;
803 WERROR result;
804 fstring printername;
805 const char *valuename;
806 enum winreg_Type type;
807 union spoolss_PrinterData data;
809 if (argc != 3) {
810 printf("Usage: %s <printername> <valuename>\n", argv[0]);
811 printf("<printername> of . queries print server\n");
812 return WERR_OK;
814 valuename = argv[2];
816 /* Open a printer handle */
818 if (strncmp(argv[1], ".", sizeof(".")) == 0)
819 fstrcpy(printername, cli->srv_name_slash);
820 else
821 slprintf(printername, sizeof(printername)-1, "%s\\%s",
822 cli->srv_name_slash, argv[1]);
824 /* get a printer handle */
826 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
827 printername,
828 SEC_FLAG_MAXIMUM_ALLOWED,
829 &pol);
830 if (!W_ERROR_IS_OK(result))
831 goto done;
833 /* Get printer info */
835 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
836 &pol,
837 valuename,
839 &type,
840 &data);
841 if (!W_ERROR_IS_OK(result))
842 goto done;
844 /* Display printer data */
846 display_printer_data(valuename, type, &data);
848 done:
849 if (is_valid_policy_hnd(&pol))
850 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
852 return result;
855 /****************************************************************************
856 ****************************************************************************/
858 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
859 TALLOC_CTX *mem_ctx,
860 int argc, const char **argv)
862 struct policy_handle pol;
863 WERROR result;
864 NTSTATUS status;
865 fstring printername;
866 const char *valuename, *keyname;
868 enum winreg_Type type;
869 union spoolss_PrinterData data;
870 uint32_t offered = 0;
871 uint32_t needed;
873 if (argc != 4) {
874 printf("Usage: %s <printername> <keyname> <valuename>\n",
875 argv[0]);
876 printf("<printername> of . queries print server\n");
877 return WERR_OK;
879 valuename = argv[3];
880 keyname = argv[2];
882 /* Open a printer handle */
884 if (strncmp(argv[1], ".", sizeof(".")) == 0)
885 fstrcpy(printername, cli->srv_name_slash);
886 else
887 slprintf(printername, sizeof(printername)-1, "%s\\%s",
888 cli->srv_name_slash, argv[1]);
890 /* get a printer handle */
892 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
893 printername,
894 SEC_FLAG_MAXIMUM_ALLOWED,
895 &pol);
896 if (!W_ERROR_IS_OK(result))
897 goto done;
899 /* Get printer info */
901 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
902 &pol,
903 keyname,
904 valuename,
905 offered,
906 &type,
907 &data,
908 &needed,
909 &result);
910 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
911 offered = needed;
912 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
913 &pol,
914 keyname,
915 valuename,
916 offered,
917 &type,
918 &data,
919 &needed,
920 &result);
923 if (!NT_STATUS_IS_OK(status)) {
924 goto done;
927 if (!W_ERROR_IS_OK(result))
928 goto done;
930 /* Display printer data */
932 display_printer_data(valuename, type, &data);
935 done:
936 if (is_valid_policy_hnd(&pol))
937 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
939 return result;
942 /****************************************************************************
943 ****************************************************************************/
945 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
947 if (!r) {
948 return;
951 printf("Printer Driver Info 1:\n");
952 printf("\tDriver Name: [%s]\n", r->driver_name);
953 printf("\n");
956 /****************************************************************************
957 ****************************************************************************/
959 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
961 if (!r) {
962 return;
965 printf("Printer Driver Info 2:\n");
966 printf("\tVersion: [%x]\n", r->version);
967 printf("\tDriver Name: [%s]\n", r->driver_name);
968 printf("\tArchitecture: [%s]\n", r->architecture);
969 printf("\tDriver Path: [%s]\n", r->driver_path);
970 printf("\tDatafile: [%s]\n", r->data_file);
971 printf("\tConfigfile: [%s]\n", r->config_file);
972 printf("\n");
975 /****************************************************************************
976 ****************************************************************************/
978 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
980 int i;
982 if (!r) {
983 return;
986 printf("Printer Driver Info 3:\n");
987 printf("\tVersion: [%x]\n", r->version);
988 printf("\tDriver Name: [%s]\n", r->driver_name);
989 printf("\tArchitecture: [%s]\n", r->architecture);
990 printf("\tDriver Path: [%s]\n", r->driver_path);
991 printf("\tDatafile: [%s]\n", r->data_file);
992 printf("\tConfigfile: [%s]\n", r->config_file);
993 printf("\tHelpfile: [%s]\n", r->help_file);
995 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
996 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
999 printf("\tMonitorname: [%s]\n", r->monitor_name);
1000 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1001 printf("\n");
1004 /****************************************************************************
1005 ****************************************************************************/
1007 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1009 int i;
1011 if (!r) {
1012 return;
1015 printf("Printer Driver Info 4:\n");
1016 printf("\tVersion: [%x]\n", r->version);
1017 printf("\tDriver Name: [%s]\n", r->driver_name);
1018 printf("\tArchitecture: [%s]\n", r->architecture);
1019 printf("\tDriver Path: [%s]\n", r->driver_path);
1020 printf("\tDatafile: [%s]\n", r->data_file);
1021 printf("\tConfigfile: [%s]\n", r->config_file);
1022 printf("\tHelpfile: [%s]\n", r->help_file);
1024 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1025 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1028 printf("\tMonitorname: [%s]\n", r->monitor_name);
1029 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1031 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1032 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1034 printf("\n");
1037 /****************************************************************************
1038 ****************************************************************************/
1040 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1042 if (!r) {
1043 return;
1046 printf("Printer Driver Info 5:\n");
1047 printf("\tVersion: [%x]\n", r->version);
1048 printf("\tDriver Name: [%s]\n", r->driver_name);
1049 printf("\tArchitecture: [%s]\n", r->architecture);
1050 printf("\tDriver Path: [%s]\n", r->driver_path);
1051 printf("\tDatafile: [%s]\n", r->data_file);
1052 printf("\tConfigfile: [%s]\n", r->config_file);
1053 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1054 printf("\tConfig Version: [0x%x]\n", r->config_version);
1055 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1056 printf("\n");
1059 /****************************************************************************
1060 ****************************************************************************/
1062 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1064 int i;
1066 if (!r) {
1067 return;
1070 printf("Printer Driver Info 6:\n");
1071 printf("\tVersion: [%x]\n", r->version);
1072 printf("\tDriver Name: [%s]\n", r->driver_name);
1073 printf("\tArchitecture: [%s]\n", r->architecture);
1074 printf("\tDriver Path: [%s]\n", r->driver_path);
1075 printf("\tDatafile: [%s]\n", r->data_file);
1076 printf("\tConfigfile: [%s]\n", r->config_file);
1077 printf("\tHelpfile: [%s]\n", r->help_file);
1079 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1080 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1083 printf("\tMonitorname: [%s]\n", r->monitor_name);
1084 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1086 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1087 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1090 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1091 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1092 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1093 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1094 printf("\tHardware ID: [%s]\n", r->hardware_id);
1095 printf("\tProvider: [%s]\n", r->provider);
1097 printf("\n");
1100 /****************************************************************************
1101 ****************************************************************************/
1103 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1105 int i;
1107 if (!r) {
1108 return;
1111 printf("Printer Driver Info 8:\n");
1112 printf("\tVersion: [%x]\n", r->version);
1113 printf("\tDriver Name: [%s]\n", r->driver_name);
1114 printf("\tArchitecture: [%s]\n", r->architecture);
1115 printf("\tDriver Path: [%s]\n", r->driver_path);
1116 printf("\tDatafile: [%s]\n", r->data_file);
1117 printf("\tConfigfile: [%s]\n", r->config_file);
1118 printf("\tHelpfile: [%s]\n", r->help_file);
1119 printf("\tMonitorname: [%s]\n", r->monitor_name);
1120 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1122 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1123 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1126 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1127 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1130 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1131 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1132 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1133 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1134 printf("\tHardware ID: [%s]\n", r->hardware_id);
1135 printf("\tProvider: [%s]\n", r->provider);
1136 printf("\tPrint Processor: [%s]\n", r->print_processor);
1137 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1138 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1139 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1141 printf("\tInf Path: [%s]\n", r->inf_path);
1142 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1143 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1144 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1146 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1147 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1148 (long long unsigned int)r->min_inbox_driver_ver_version);
1150 printf("\n");
1153 /****************************************************************************
1154 ****************************************************************************/
1156 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1157 TALLOC_CTX *mem_ctx,
1158 int argc, const char **argv)
1160 struct policy_handle pol;
1161 WERROR werror;
1162 uint32_t level = 3;
1163 const char *printername;
1164 uint32_t i;
1165 bool success = false;
1166 union spoolss_DriverInfo info;
1167 uint32_t server_major_version;
1168 uint32_t server_minor_version;
1170 if ((argc == 1) || (argc > 3)) {
1171 printf("Usage: %s <printername> [level]\n", argv[0]);
1172 return WERR_OK;
1175 /* get the arguments need to open the printer handle */
1177 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1179 if (argc == 3) {
1180 level = atoi(argv[2]);
1183 /* Open a printer handle */
1185 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1186 printername,
1187 PRINTER_ACCESS_USE,
1188 &pol);
1189 if (!W_ERROR_IS_OK(werror)) {
1190 printf("Error opening printer handle for %s!\n", printername);
1191 return werror;
1194 /* loop through and print driver info level for each architecture */
1196 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1198 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1199 &pol,
1200 archi_table[i].long_archi,
1201 level,
1202 0, /* offered */
1203 archi_table[i].version,
1205 &info,
1206 &server_major_version,
1207 &server_minor_version);
1208 if (!W_ERROR_IS_OK(werror)) {
1209 continue;
1212 /* need at least one success */
1214 success = true;
1216 printf("\n[%s]\n", archi_table[i].long_archi);
1218 switch (level) {
1219 case 1:
1220 display_print_driver1(&info.info1);
1221 break;
1222 case 2:
1223 display_print_driver2(&info.info2);
1224 break;
1225 case 3:
1226 display_print_driver3(&info.info3);
1227 break;
1228 case 4:
1229 display_print_driver4(&info.info4);
1230 break;
1231 case 5:
1232 display_print_driver5(&info.info5);
1233 break;
1234 case 6:
1235 display_print_driver6(&info.info6);
1236 break;
1237 case 8:
1238 display_print_driver8(&info.info8);
1239 break;
1240 default:
1241 printf("unknown info level %d\n", level);
1242 break;
1246 /* Cleanup */
1248 if (is_valid_policy_hnd(&pol)) {
1249 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1252 if (success) {
1253 werror = WERR_OK;
1256 return werror;
1259 /****************************************************************************
1260 ****************************************************************************/
1262 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1263 TALLOC_CTX *mem_ctx,
1264 const char *architecture,
1265 uint32_t level)
1267 WERROR werror;
1268 uint32_t count = 0;
1269 union spoolss_DriverInfo *info = NULL;
1270 uint32_t j;
1272 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1273 cli->srv_name_slash,
1274 architecture,
1275 level,
1277 &count,
1278 &info);
1280 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1281 printf("Server does not support environment [%s]\n",
1282 architecture);
1283 return WERR_OK;
1286 if (count == 0) {
1287 return WERR_OK;
1290 if (!W_ERROR_IS_OK(werror)) {
1291 printf("Error getting driver for environment [%s] - %s\n",
1292 architecture, win_errstr(werror));
1293 return werror;
1296 printf("\n[%s]\n", architecture);
1298 switch (level) {
1299 case 1:
1300 for (j=0; j < count; j++) {
1301 display_print_driver1(&info[j].info1);
1303 break;
1304 case 2:
1305 for (j=0; j < count; j++) {
1306 display_print_driver2(&info[j].info2);
1308 break;
1309 case 3:
1310 for (j=0; j < count; j++) {
1311 display_print_driver3(&info[j].info3);
1313 break;
1314 case 4:
1315 for (j=0; j < count; j++) {
1316 display_print_driver4(&info[j].info4);
1318 break;
1319 case 5:
1320 for (j=0; j < count; j++) {
1321 display_print_driver5(&info[j].info5);
1323 break;
1324 case 6:
1325 for (j=0; j < count; j++) {
1326 display_print_driver6(&info[j].info6);
1328 break;
1329 case 8:
1330 for (j=0; j < count; j++) {
1331 display_print_driver8(&info[j].info8);
1333 break;
1334 default:
1335 printf("unknown info level %d\n", level);
1336 return WERR_UNKNOWN_LEVEL;
1339 return werror;
1342 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1343 TALLOC_CTX *mem_ctx,
1344 int argc, const char **argv)
1346 WERROR werror = WERR_OK;
1347 uint32_t level = 1;
1348 uint32_t i;
1349 const char *architecture = NULL;
1351 if (argc > 3) {
1352 printf("Usage: enumdrivers [level] [architecture]\n");
1353 return WERR_OK;
1356 if (argc >= 2) {
1357 level = atoi(argv[1]);
1360 if (argc == 3) {
1361 architecture = argv[2];
1364 if (architecture) {
1365 return enum_driver_by_architecture(cli, mem_ctx,
1366 architecture,
1367 level);
1370 /* loop through and print driver info level for each architecture */
1371 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1372 /* check to see if we already asked for this architecture string */
1374 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1375 continue;
1378 werror = enum_driver_by_architecture(cli, mem_ctx,
1379 archi_table[i].long_archi,
1380 level);
1381 if (!W_ERROR_IS_OK(werror)) {
1382 break;
1386 return werror;
1389 /****************************************************************************
1390 ****************************************************************************/
1392 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1394 printf("\tDirectory Name:[%s]\n", r->directory_name);
1397 /****************************************************************************
1398 ****************************************************************************/
1400 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1401 TALLOC_CTX *mem_ctx,
1402 int argc, const char **argv)
1404 WERROR result;
1405 NTSTATUS status;
1406 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1407 DATA_BLOB buffer;
1408 uint32_t offered;
1409 union spoolss_DriverDirectoryInfo info;
1410 uint32_t needed;
1412 if (argc > 2) {
1413 printf("Usage: %s [environment]\n", argv[0]);
1414 return WERR_OK;
1417 /* Get the arguments need to open the printer handle */
1419 if (argc == 2) {
1420 env = argv[1];
1423 /* Get the directory. Only use Info level 1 */
1425 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1426 cli->srv_name_slash,
1427 env,
1429 NULL, /* buffer */
1430 0, /* offered */
1431 NULL, /* info */
1432 &needed,
1433 &result);
1434 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1435 offered = needed;
1436 buffer = data_blob_talloc_zero(mem_ctx, needed);
1438 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1439 cli->srv_name_slash,
1440 env,
1442 &buffer,
1443 offered,
1444 &info,
1445 &needed,
1446 &result);
1449 if (W_ERROR_IS_OK(result)) {
1450 display_printdriverdir_1(&info.info1);
1453 return result;
1456 /****************************************************************************
1457 ****************************************************************************/
1459 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1460 struct spoolss_AddDriverInfo3 *info,
1461 const char *arch)
1464 int i;
1466 for (i=0; archi_table[i].long_archi != NULL; i++)
1468 if (strcmp(arch, archi_table[i].short_archi) == 0)
1470 info->version = archi_table[i].version;
1471 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1472 break;
1476 if (archi_table[i].long_archi == NULL)
1478 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1481 return;
1485 /**************************************************************************
1486 wrapper for strtok to get the next parameter from a delimited list.
1487 Needed to handle the empty parameter string denoted by "NULL"
1488 *************************************************************************/
1490 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1491 const char *delim, const char **dest,
1492 char **saveptr)
1494 char *ptr;
1496 /* get the next token */
1497 ptr = strtok_r(str, delim, saveptr);
1499 /* a string of 'NULL' is used to represent an empty
1500 parameter because two consecutive delimiters
1501 will not return an empty string. See man strtok(3)
1502 for details */
1503 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1504 ptr = NULL;
1507 if (dest != NULL) {
1508 *dest = talloc_strdup(mem_ctx, ptr);
1511 return ptr;
1514 /********************************************************************************
1515 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1516 string in the form of
1517 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1518 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1519 <Default Data Type>:<Comma Separated list of Files>
1520 *******************************************************************************/
1522 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1523 char *args)
1525 char *str, *str2;
1526 int count = 0;
1527 char *saveptr = NULL;
1528 struct spoolss_StringArray *deps;
1529 const char **file_array = NULL;
1530 int i;
1532 /* fill in the UNISTR fields */
1533 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1534 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1535 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1536 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1537 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1538 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1539 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1541 /* <Comma Separated List of Dependent Files> */
1542 /* save the beginning of the string */
1543 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1544 str = str2;
1546 /* begin to strip out each filename */
1547 str = strtok_r(str, ",", &saveptr);
1549 /* no dependent files, we are done */
1550 if (!str) {
1551 return true;
1554 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1555 if (!deps) {
1556 return false;
1559 while (str != NULL) {
1560 add_string_to_array(deps, str, &file_array, &count);
1561 str = strtok_r(NULL, ",", &saveptr);
1564 deps->string = talloc_zero_array(deps, const char *, count + 1);
1565 if (!deps->string) {
1566 return false;
1569 for (i=0; i < count; i++) {
1570 deps->string[i] = file_array[i];
1573 r->dependent_files = deps;
1575 return true;
1578 /****************************************************************************
1579 ****************************************************************************/
1581 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1582 TALLOC_CTX *mem_ctx,
1583 int argc, const char **argv)
1585 WERROR result;
1586 NTSTATUS status;
1587 uint32_t level = 3;
1588 struct spoolss_AddDriverInfoCtr info_ctr;
1589 struct spoolss_AddDriverInfo3 info3;
1590 const char *arch;
1591 char *driver_args;
1593 /* parse the command arguments */
1594 if (argc != 3 && argc != 4)
1596 printf ("Usage: %s <Environment> \\\n", argv[0]);
1597 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1598 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1599 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1600 printf ("\t[version]\n");
1602 return WERR_OK;
1605 /* Fill in the spoolss_AddDriverInfo3 struct */
1606 ZERO_STRUCT(info3);
1608 arch = cmd_spoolss_get_short_archi(argv[1]);
1609 if (!arch) {
1610 printf ("Error Unknown architechture [%s]\n", argv[1]);
1611 return WERR_INVALID_PARAM;
1614 set_drv_info_3_env(mem_ctx, &info3, arch);
1616 driver_args = talloc_strdup( mem_ctx, argv[2] );
1617 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1619 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1620 return WERR_INVALID_PARAM;
1623 /* if printer driver version specified, override the default version
1624 * used by the architecture. This allows installation of Windows
1625 * 2000 (version 3) printer drivers. */
1626 if (argc == 4)
1628 info3.version = atoi(argv[3]);
1632 info_ctr.level = level;
1633 info_ctr.info.info3 = &info3;
1635 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1636 cli->srv_name_slash,
1637 &info_ctr,
1638 &result);
1639 if (!NT_STATUS_IS_OK(status)) {
1640 return ntstatus_to_werror(status);
1642 if (W_ERROR_IS_OK(result)) {
1643 printf ("Printer Driver %s successfully installed.\n",
1644 info3.driver_name);
1647 return result;
1651 /****************************************************************************
1652 ****************************************************************************/
1654 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1655 TALLOC_CTX *mem_ctx,
1656 int argc, const char **argv)
1658 WERROR result;
1659 struct spoolss_SetPrinterInfoCtr info_ctr;
1660 struct spoolss_SetPrinterInfo2 info2;
1662 /* parse the command arguments */
1663 if (argc != 5)
1665 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1666 return WERR_OK;
1669 /* Fill in the DRIVER_INFO_2 struct */
1670 ZERO_STRUCT(info2);
1672 info2.printername = argv[1];
1673 info2.drivername = argv[3];
1674 info2.sharename = argv[2];
1675 info2.portname = argv[4];
1676 info2.comment = "Created by rpcclient";
1677 info2.printprocessor = "winprint";
1678 info2.datatype = "RAW";
1679 info2.devmode = NULL;
1680 info2.secdesc = NULL;
1681 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1682 info2.priority = 0;
1683 info2.defaultpriority = 0;
1684 info2.starttime = 0;
1685 info2.untiltime = 0;
1687 /* These three fields must not be used by AddPrinter()
1688 as defined in the MS Platform SDK documentation..
1689 --jerry
1690 info2.status = 0;
1691 info2.cjobs = 0;
1692 info2.averageppm = 0;
1695 info_ctr.level = 2;
1696 info_ctr.info.info2 = &info2;
1698 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1699 &info_ctr);
1700 if (W_ERROR_IS_OK(result))
1701 printf ("Printer %s successfully installed.\n", argv[1]);
1703 return result;
1706 /****************************************************************************
1707 ****************************************************************************/
1709 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1710 TALLOC_CTX *mem_ctx,
1711 int argc, const char **argv)
1713 struct policy_handle pol;
1714 WERROR result;
1715 NTSTATUS status;
1716 uint32_t level = 2;
1717 const char *printername;
1718 union spoolss_PrinterInfo info;
1719 struct spoolss_SetPrinterInfoCtr info_ctr;
1720 struct spoolss_DevmodeContainer devmode_ctr;
1721 struct sec_desc_buf secdesc_ctr;
1723 ZERO_STRUCT(devmode_ctr);
1724 ZERO_STRUCT(secdesc_ctr);
1726 /* parse the command arguments */
1727 if (argc != 3)
1729 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1730 return WERR_OK;
1733 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1735 /* Get a printer handle */
1737 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1738 printername,
1739 PRINTER_ALL_ACCESS,
1740 &pol);
1741 if (!W_ERROR_IS_OK(result))
1742 goto done;
1744 /* Get printer info */
1746 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1747 &pol,
1748 level,
1750 &info);
1751 if (!W_ERROR_IS_OK(result)) {
1752 printf ("Unable to retrieve printer information!\n");
1753 goto done;
1756 /* Set the printer driver */
1758 info.info2.drivername = argv[2];
1759 info.info2.devmode = NULL;
1760 info.info2.secdesc = NULL;
1762 info_ctr.level = 2;
1763 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1765 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1766 &pol,
1767 &info_ctr,
1768 &devmode_ctr,
1769 &secdesc_ctr,
1770 0, /* command */
1771 &result);
1772 if (!W_ERROR_IS_OK(result)) {
1773 printf("SetPrinter call failed!\n");
1774 goto done;;
1777 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1779 done:
1780 /* Cleanup */
1782 if (is_valid_policy_hnd(&pol))
1783 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1785 return result;
1789 /****************************************************************************
1790 ****************************************************************************/
1792 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1793 TALLOC_CTX *mem_ctx,
1794 int argc, const char **argv)
1796 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1797 NTSTATUS status;
1799 int i;
1800 int vers = -1;
1802 const char *arch = NULL;
1803 uint32_t delete_flags = 0;
1805 /* parse the command arguments */
1806 if (argc < 2 || argc > 4) {
1807 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1808 return WERR_OK;
1811 if (argc >= 3)
1812 arch = argv[2];
1813 if (argc == 4)
1814 vers = atoi (argv[3]);
1816 if (vers >= 0) {
1817 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1820 /* delete the driver for all architectures */
1821 for (i=0; archi_table[i].long_archi; i++) {
1823 if (arch && !strequal( archi_table[i].long_archi, arch))
1824 continue;
1826 if (vers >= 0 && archi_table[i].version != vers)
1827 continue;
1829 /* make the call to remove the driver */
1830 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1831 cli->srv_name_slash,
1832 archi_table[i].long_archi,
1833 argv[1],
1834 delete_flags,
1835 archi_table[i].version,
1836 &result);
1838 if ( !W_ERROR_IS_OK(result) )
1840 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1841 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1842 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1845 else
1847 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1848 archi_table[i].long_archi, archi_table[i].version);
1849 ret = WERR_OK;
1853 return ret;
1857 /****************************************************************************
1858 ****************************************************************************/
1860 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1861 TALLOC_CTX *mem_ctx,
1862 int argc, const char **argv)
1864 WERROR result = WERR_OK;
1865 NTSTATUS status;
1866 int i;
1868 /* parse the command arguments */
1869 if (argc != 2) {
1870 printf ("Usage: %s <driver>\n", argv[0]);
1871 return WERR_OK;
1874 /* delete the driver for all architectures */
1875 for (i=0; archi_table[i].long_archi; i++) {
1876 /* make the call to remove the driver */
1877 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1878 cli->srv_name_slash,
1879 archi_table[i].long_archi,
1880 argv[1],
1881 &result);
1882 if (!NT_STATUS_IS_OK(status)) {
1883 return result;
1885 if ( !W_ERROR_IS_OK(result) ) {
1886 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1887 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1888 argv[1], archi_table[i].long_archi,
1889 W_ERROR_V(result));
1891 } else {
1892 printf ("Driver %s removed for arch [%s].\n", argv[1],
1893 archi_table[i].long_archi);
1897 return result;
1900 /****************************************************************************
1901 ****************************************************************************/
1903 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1904 TALLOC_CTX *mem_ctx,
1905 int argc, const char **argv)
1907 WERROR result;
1908 NTSTATUS status;
1909 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1910 DATA_BLOB buffer;
1911 uint32_t offered;
1912 union spoolss_PrintProcessorDirectoryInfo info;
1913 uint32_t needed;
1915 /* parse the command arguments */
1916 if (argc > 2) {
1917 printf ("Usage: %s [environment]\n", argv[0]);
1918 return WERR_OK;
1921 if (argc == 2) {
1922 environment = argv[1];
1925 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1926 cli->srv_name_slash,
1927 environment,
1929 NULL, /* buffer */
1930 0, /* offered */
1931 NULL, /* info */
1932 &needed,
1933 &result);
1934 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1935 offered = needed;
1936 buffer = data_blob_talloc_zero(mem_ctx, needed);
1938 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1939 cli->srv_name_slash,
1940 environment,
1942 &buffer,
1943 offered,
1944 &info,
1945 &needed,
1946 &result);
1949 if (W_ERROR_IS_OK(result)) {
1950 printf("%s\n", info.info1.directory_name);
1953 return result;
1956 /****************************************************************************
1957 ****************************************************************************/
1959 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1960 int argc, const char **argv)
1962 struct policy_handle handle;
1963 WERROR werror;
1964 NTSTATUS status;
1965 const char *printername;
1966 union spoolss_AddFormInfo info;
1967 struct spoolss_AddFormInfo1 info1;
1968 struct spoolss_AddFormInfo2 info2;
1969 uint32_t level = 1;
1971 /* Parse the command arguments */
1973 if (argc < 3 || argc > 5) {
1974 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1975 return WERR_OK;
1978 /* Get a printer handle */
1980 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1982 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1983 printername,
1984 PRINTER_ALL_ACCESS,
1985 &handle);
1986 if (!W_ERROR_IS_OK(werror))
1987 goto done;
1989 /* Dummy up some values for the form data */
1991 if (argc == 4) {
1992 level = atoi(argv[3]);
1995 switch (level) {
1996 case 1:
1997 info1.flags = SPOOLSS_FORM_USER;
1998 info1.form_name = argv[2];
1999 info1.size.width = 100;
2000 info1.size.height = 100;
2001 info1.area.left = 0;
2002 info1.area.top = 10;
2003 info1.area.right = 20;
2004 info1.area.bottom = 30;
2006 info.info1 = &info1;
2008 break;
2009 case 2:
2010 info2.flags = SPOOLSS_FORM_USER;
2011 info2.form_name = argv[2];
2012 info2.size.width = 100;
2013 info2.size.height = 100;
2014 info2.area.left = 0;
2015 info2.area.top = 10;
2016 info2.area.right = 20;
2017 info2.area.bottom = 30;
2018 info2.keyword = argv[2];
2019 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2020 info2.mui_dll = NULL;
2021 info2.ressource_id = 0;
2022 info2.display_name = argv[2];
2023 info2.lang_id = 0;
2025 info.info2 = &info2;
2027 break;
2030 /* Add the form */
2033 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2034 &handle,
2035 level,
2036 info,
2037 &werror);
2039 done:
2040 if (is_valid_policy_hnd(&handle))
2041 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2043 return werror;
2046 /****************************************************************************
2047 ****************************************************************************/
2049 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2050 int argc, const char **argv)
2052 struct policy_handle handle;
2053 WERROR werror;
2054 NTSTATUS status;
2055 const char *printername;
2056 union spoolss_AddFormInfo info;
2057 struct spoolss_AddFormInfo1 info1;
2059 /* Parse the command arguments */
2061 if (argc != 3) {
2062 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2063 return WERR_OK;
2066 /* Get a printer handle */
2068 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2070 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2071 printername,
2072 SEC_FLAG_MAXIMUM_ALLOWED,
2073 &handle);
2074 if (!W_ERROR_IS_OK(werror))
2075 goto done;
2077 /* Dummy up some values for the form data */
2079 info1.flags = SPOOLSS_FORM_PRINTER;
2080 info1.size.width = 100;
2081 info1.size.height = 100;
2082 info1.area.left = 0;
2083 info1.area.top = 1000;
2084 info1.area.right = 2000;
2085 info1.area.bottom = 3000;
2086 info1.form_name = argv[2];
2088 info.info1 = &info1;
2090 /* Set the form */
2092 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2093 &handle,
2094 argv[2],
2096 info,
2097 &werror);
2099 done:
2100 if (is_valid_policy_hnd(&handle))
2101 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2103 return werror;
2106 /****************************************************************************
2107 ****************************************************************************/
2109 static const char *get_form_flag(int form_flag)
2111 switch (form_flag) {
2112 case SPOOLSS_FORM_USER:
2113 return "FORM_USER";
2114 case SPOOLSS_FORM_BUILTIN:
2115 return "FORM_BUILTIN";
2116 case SPOOLSS_FORM_PRINTER:
2117 return "FORM_PRINTER";
2118 default:
2119 return "unknown";
2123 /****************************************************************************
2124 ****************************************************************************/
2126 static void display_form_info1(struct spoolss_FormInfo1 *r)
2128 printf("%s\n" \
2129 "\tflag: %s (%d)\n" \
2130 "\twidth: %d, length: %d\n" \
2131 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2132 r->form_name, get_form_flag(r->flags), r->flags,
2133 r->size.width, r->size.height,
2134 r->area.left, r->area.right,
2135 r->area.top, r->area.bottom);
2138 /****************************************************************************
2139 ****************************************************************************/
2141 static void display_form_info2(struct spoolss_FormInfo2 *r)
2143 printf("%s\n" \
2144 "\tflag: %s (%d)\n" \
2145 "\twidth: %d, length: %d\n" \
2146 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2147 r->form_name, get_form_flag(r->flags), r->flags,
2148 r->size.width, r->size.height,
2149 r->area.left, r->area.right,
2150 r->area.top, r->area.bottom);
2151 printf("\tkeyword: %s\n", r->keyword);
2152 printf("\tstring_type: 0x%08x\n", r->string_type);
2153 printf("\tmui_dll: %s\n", r->mui_dll);
2154 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2155 printf("\tdisplay_name: %s\n", r->display_name);
2156 printf("\tlang_id: %d\n", r->lang_id);
2157 printf("\n");
2160 /****************************************************************************
2161 ****************************************************************************/
2163 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2164 int argc, const char **argv)
2166 struct policy_handle handle;
2167 WERROR werror;
2168 NTSTATUS status;
2169 const char *printername;
2170 DATA_BLOB buffer;
2171 uint32_t offered = 0;
2172 union spoolss_FormInfo info;
2173 uint32_t needed;
2174 uint32_t level = 1;
2176 /* Parse the command arguments */
2178 if (argc < 3 || argc > 5) {
2179 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2180 return WERR_OK;
2183 /* Get a printer handle */
2185 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2187 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2188 printername,
2189 SEC_FLAG_MAXIMUM_ALLOWED,
2190 &handle);
2191 if (!W_ERROR_IS_OK(werror))
2192 goto done;
2194 if (argc == 4) {
2195 level = atoi(argv[3]);
2198 /* Get the form */
2200 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2201 &handle,
2202 argv[2],
2203 level,
2204 NULL,
2205 offered,
2206 &info,
2207 &needed,
2208 &werror);
2209 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2210 buffer = data_blob_talloc_zero(mem_ctx, needed);
2211 offered = needed;
2212 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2213 &handle,
2214 argv[2],
2215 level,
2216 &buffer,
2217 offered,
2218 &info,
2219 &needed,
2220 &werror);
2223 if (!NT_STATUS_IS_OK(status)) {
2224 return werror;
2227 switch (level) {
2228 case 1:
2229 display_form_info1(&info.info1);
2230 break;
2231 case 2:
2232 display_form_info2(&info.info2);
2233 break;
2236 done:
2237 if (is_valid_policy_hnd(&handle))
2238 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2240 return werror;
2243 /****************************************************************************
2244 ****************************************************************************/
2246 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2247 TALLOC_CTX *mem_ctx, int argc,
2248 const char **argv)
2250 struct policy_handle handle;
2251 WERROR werror;
2252 NTSTATUS status;
2253 const char *printername;
2255 /* Parse the command arguments */
2257 if (argc != 3) {
2258 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2259 return WERR_OK;
2262 /* Get a printer handle */
2264 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2266 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2267 printername,
2268 SEC_FLAG_MAXIMUM_ALLOWED,
2269 &handle);
2270 if (!W_ERROR_IS_OK(werror))
2271 goto done;
2273 /* Delete the form */
2275 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2276 &handle,
2277 argv[2],
2278 &werror);
2279 if (!NT_STATUS_IS_OK(status)) {
2280 return ntstatus_to_werror(status);
2283 done:
2284 if (is_valid_policy_hnd(&handle))
2285 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2287 return werror;
2290 /****************************************************************************
2291 ****************************************************************************/
2293 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2294 TALLOC_CTX *mem_ctx, int argc,
2295 const char **argv)
2297 struct policy_handle handle;
2298 WERROR werror;
2299 const char *printername;
2300 uint32_t num_forms, level = 1, i;
2301 union spoolss_FormInfo *forms;
2303 /* Parse the command arguments */
2305 if (argc < 2 || argc > 4) {
2306 printf ("Usage: %s <printer> [level]\n", argv[0]);
2307 return WERR_OK;
2310 /* Get a printer handle */
2312 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2314 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2315 printername,
2316 SEC_FLAG_MAXIMUM_ALLOWED,
2317 &handle);
2318 if (!W_ERROR_IS_OK(werror))
2319 goto done;
2321 if (argc == 3) {
2322 level = atoi(argv[2]);
2325 /* Enumerate forms */
2327 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2328 &handle,
2329 level,
2331 &num_forms,
2332 &forms);
2334 if (!W_ERROR_IS_OK(werror))
2335 goto done;
2337 /* Display output */
2339 for (i = 0; i < num_forms; i++) {
2340 switch (level) {
2341 case 1:
2342 display_form_info1(&forms[i].info1);
2343 break;
2344 case 2:
2345 display_form_info2(&forms[i].info2);
2346 break;
2350 done:
2351 if (is_valid_policy_hnd(&handle))
2352 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2354 return werror;
2357 /****************************************************************************
2358 ****************************************************************************/
2360 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2361 TALLOC_CTX *mem_ctx,
2362 int argc, const char **argv)
2364 WERROR result;
2365 NTSTATUS status;
2366 const char *printername;
2367 struct policy_handle pol;
2368 union spoolss_PrinterInfo info;
2369 enum winreg_Type type;
2370 union spoolss_PrinterData data;
2372 /* parse the command arguments */
2373 if (argc < 5) {
2374 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2375 " <value> <data>\n",
2376 argv[0]);
2377 result = WERR_INVALID_PARAM;
2378 goto done;
2381 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2383 type = REG_NONE;
2385 if (strequal(argv[2], "string")) {
2386 type = REG_SZ;
2389 if (strequal(argv[2], "binary")) {
2390 type = REG_BINARY;
2393 if (strequal(argv[2], "dword")) {
2394 type = REG_DWORD;
2397 if (strequal(argv[2], "multistring")) {
2398 type = REG_MULTI_SZ;
2401 if (type == REG_NONE) {
2402 printf("Unknown data type: %s\n", argv[2]);
2403 result = WERR_INVALID_PARAM;
2404 goto done;
2407 /* get a printer handle */
2409 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2410 printername,
2411 SEC_FLAG_MAXIMUM_ALLOWED,
2412 &pol);
2413 if (!W_ERROR_IS_OK(result)) {
2414 goto done;
2417 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2418 &pol,
2421 &info);
2422 if (!W_ERROR_IS_OK(result)) {
2423 goto done;
2426 printf("%s\n", current_timestring(mem_ctx, true));
2427 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2429 /* Set the printer data */
2431 switch (type) {
2432 case REG_SZ:
2433 data.string = talloc_strdup(mem_ctx, argv[4]);
2434 W_ERROR_HAVE_NO_MEMORY(data.string);
2435 break;
2436 case REG_DWORD:
2437 data.value = strtoul(argv[4], NULL, 10);
2438 break;
2439 case REG_BINARY:
2440 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2441 break;
2442 case REG_MULTI_SZ: {
2443 int i, num_strings;
2444 const char **strings = NULL;
2446 for (i=4; i<argc; i++) {
2447 if (strcmp(argv[i], "NULL") == 0) {
2448 argv[i] = "";
2450 if (!add_string_to_array(mem_ctx, argv[i],
2451 &strings,
2452 &num_strings)) {
2453 result = WERR_NOMEM;
2454 goto done;
2457 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2458 if (!data.string_array) {
2459 result = WERR_NOMEM;
2460 goto done;
2462 for (i=0; i < num_strings; i++) {
2463 data.string_array[i] = strings[i];
2465 break;
2467 default:
2468 printf("Unknown data type: %s\n", argv[2]);
2469 result = WERR_INVALID_PARAM;
2470 goto done;
2473 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2474 &pol,
2475 argv[3], /* value_name */
2476 type,
2477 data,
2478 0, /* autocalculated size */
2479 &result);
2480 if (!W_ERROR_IS_OK(result)) {
2481 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2482 goto done;
2484 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2486 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2487 &pol,
2490 &info);
2491 if (!W_ERROR_IS_OK(result)) {
2492 goto done;
2495 printf("%s\n", current_timestring(mem_ctx, true));
2496 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2498 done:
2499 /* cleanup */
2500 if (is_valid_policy_hnd(&pol)) {
2501 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2504 return result;
2507 /****************************************************************************
2508 ****************************************************************************/
2510 static void display_job_info1(struct spoolss_JobInfo1 *r)
2512 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2513 r->user_name, r->document_name, r->text_status, r->pages_printed,
2514 r->total_pages);
2517 /****************************************************************************
2518 ****************************************************************************/
2520 static void display_job_info2(struct spoolss_JobInfo2 *r)
2522 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2523 r->position, r->job_id,
2524 r->user_name, r->document_name, r->text_status, r->pages_printed,
2525 r->total_pages, r->size);
2528 /****************************************************************************
2529 ****************************************************************************/
2531 static void display_job_info3(struct spoolss_JobInfo3 *r)
2533 printf("jobid[%d], next_jobid[%d]\n",
2534 r->job_id, r->next_job_id);
2537 /****************************************************************************
2538 ****************************************************************************/
2540 static void display_job_info4(struct spoolss_JobInfo4 *r)
2542 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2543 r->position, r->job_id,
2544 r->user_name, r->document_name, r->text_status, r->pages_printed,
2545 r->total_pages, r->size, r->size_high);
2548 /****************************************************************************
2549 ****************************************************************************/
2551 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2552 TALLOC_CTX *mem_ctx, int argc,
2553 const char **argv)
2555 WERROR result;
2556 uint32_t level = 1, count, i;
2557 const char *printername;
2558 struct policy_handle hnd;
2559 union spoolss_JobInfo *info;
2561 if (argc < 2 || argc > 3) {
2562 printf("Usage: %s printername [level]\n", argv[0]);
2563 return WERR_OK;
2566 if (argc == 3) {
2567 level = atoi(argv[2]);
2570 /* Open printer handle */
2572 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2574 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2575 printername,
2576 SEC_FLAG_MAXIMUM_ALLOWED,
2577 &hnd);
2578 if (!W_ERROR_IS_OK(result))
2579 goto done;
2581 /* Enumerate ports */
2583 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2584 &hnd,
2585 0, /* firstjob */
2586 1000, /* numjobs */
2587 level,
2589 &count,
2590 &info);
2591 if (!W_ERROR_IS_OK(result)) {
2592 goto done;
2595 for (i = 0; i < count; i++) {
2596 switch (level) {
2597 case 1:
2598 display_job_info1(&info[i].info1);
2599 break;
2600 case 2:
2601 display_job_info2(&info[i].info2);
2602 break;
2603 default:
2604 d_printf("unknown info level %d\n", level);
2605 break;
2609 done:
2610 if (is_valid_policy_hnd(&hnd)) {
2611 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2614 return result;
2617 /****************************************************************************
2618 ****************************************************************************/
2620 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2621 TALLOC_CTX *mem_ctx, int argc,
2622 const char **argv)
2624 WERROR result;
2625 const char *printername;
2626 struct policy_handle hnd;
2627 uint32_t job_id;
2628 uint32_t level = 1;
2629 union spoolss_JobInfo info;
2631 if (argc < 3 || argc > 4) {
2632 printf("Usage: %s printername job_id [level]\n", argv[0]);
2633 return WERR_OK;
2636 job_id = atoi(argv[2]);
2638 if (argc == 4) {
2639 level = atoi(argv[3]);
2642 /* Open printer handle */
2644 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2646 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2647 printername,
2648 SEC_FLAG_MAXIMUM_ALLOWED,
2649 &hnd);
2650 if (!W_ERROR_IS_OK(result)) {
2651 goto done;
2654 /* Enumerate ports */
2656 result = rpccli_spoolss_getjob(cli, mem_ctx,
2657 &hnd,
2658 job_id,
2659 level,
2661 &info);
2663 if (!W_ERROR_IS_OK(result)) {
2664 goto done;
2667 switch (level) {
2668 case 1:
2669 display_job_info1(&info.info1);
2670 break;
2671 case 2:
2672 display_job_info2(&info.info2);
2673 break;
2674 case 3:
2675 display_job_info3(&info.info3);
2676 break;
2677 case 4:
2678 display_job_info4(&info.info4);
2679 break;
2680 default:
2681 d_printf("unknown info level %d\n", level);
2682 break;
2685 done:
2686 if (is_valid_policy_hnd(&hnd)) {
2687 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2690 return result;
2693 /****************************************************************************
2694 ****************************************************************************/
2696 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2697 TALLOC_CTX *mem_ctx, int argc,
2698 const char **argv)
2700 WERROR result;
2701 NTSTATUS status;
2702 const char *printername;
2703 struct policy_handle hnd;
2704 uint32_t job_id;
2705 enum spoolss_JobControl command;
2707 if (argc != 4) {
2708 printf("Usage: %s printername job_id command\n", argv[0]);
2709 return WERR_OK;
2712 job_id = atoi(argv[2]);
2713 command = atoi(argv[3]);
2715 /* Open printer handle */
2717 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2719 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2720 printername,
2721 SEC_FLAG_MAXIMUM_ALLOWED,
2722 &hnd);
2723 if (!W_ERROR_IS_OK(result)) {
2724 goto done;
2727 /* Set Job */
2729 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2730 &hnd,
2731 job_id,
2732 NULL,
2733 command,
2734 &result);
2736 if (!W_ERROR_IS_OK(result)) {
2737 goto done;
2740 done:
2741 if (is_valid_policy_hnd(&hnd)) {
2742 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2745 return result;
2748 /****************************************************************************
2749 ****************************************************************************/
2751 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2752 TALLOC_CTX *mem_ctx, int argc,
2753 const char **argv)
2755 WERROR result;
2756 NTSTATUS status;
2757 uint32_t i = 0;
2758 const char *printername;
2759 struct policy_handle hnd;
2760 uint32_t value_offered = 0;
2761 const char *value_name = NULL;
2762 uint32_t value_needed;
2763 enum winreg_Type type;
2764 uint8_t *data = NULL;
2765 uint32_t data_offered = 0;
2766 uint32_t data_needed;
2768 if (argc != 2) {
2769 printf("Usage: %s printername\n", argv[0]);
2770 return WERR_OK;
2773 /* Open printer handle */
2775 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2777 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2778 printername,
2779 SEC_FLAG_MAXIMUM_ALLOWED,
2780 &hnd);
2781 if (!W_ERROR_IS_OK(result)) {
2782 goto done;
2785 /* Enumerate data */
2787 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2788 &hnd,
2790 value_name,
2791 value_offered,
2792 &value_needed,
2793 &type,
2794 data,
2795 data_offered,
2796 &data_needed,
2797 &result);
2799 data_offered = data_needed;
2800 value_offered = value_needed;
2801 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2802 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2804 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2806 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2807 &hnd,
2808 i++,
2809 value_name,
2810 value_offered,
2811 &value_needed,
2812 &type,
2813 data,
2814 data_offered,
2815 &data_needed,
2816 &result);
2817 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2818 struct regval_blob v;
2819 fstrcpy(v.valuename, value_name);
2820 v.type = type;
2821 v.size = data_offered;
2822 v.data_p = data;
2823 display_reg_value(v);
2827 if (W_ERROR_V(result) == ERRnomoreitems) {
2828 result = W_ERROR(ERRsuccess);
2831 done:
2832 if (is_valid_policy_hnd(&hnd)) {
2833 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2836 return result;
2839 /****************************************************************************
2840 ****************************************************************************/
2842 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2843 TALLOC_CTX *mem_ctx, int argc,
2844 const char **argv)
2846 WERROR result;
2847 uint32_t i;
2848 const char *printername;
2849 struct policy_handle hnd;
2850 uint32_t count;
2851 struct spoolss_PrinterEnumValues *info;
2853 if (argc != 3) {
2854 printf("Usage: %s printername <keyname>\n", argv[0]);
2855 return WERR_OK;
2858 /* Open printer handle */
2860 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2862 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2863 printername,
2864 SEC_FLAG_MAXIMUM_ALLOWED,
2865 &hnd);
2866 if (!W_ERROR_IS_OK(result)) {
2867 goto done;
2870 /* Enumerate subkeys */
2872 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2873 &hnd,
2874 argv[2],
2876 &count,
2877 &info);
2878 if (!W_ERROR_IS_OK(result)) {
2879 goto done;
2882 for (i=0; i < count; i++) {
2883 display_printer_data(info[i].value_name,
2884 info[i].type,
2885 info[i].data);
2888 done:
2889 if (is_valid_policy_hnd(&hnd)) {
2890 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2893 return result;
2896 /****************************************************************************
2897 ****************************************************************************/
2899 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2900 TALLOC_CTX *mem_ctx, int argc,
2901 const char **argv)
2903 WERROR result;
2904 const char *printername;
2905 const char *keyname = NULL;
2906 struct policy_handle hnd;
2907 const char **key_buffer = NULL;
2908 int i;
2910 if (argc < 2 || argc > 3) {
2911 printf("Usage: %s printername [keyname]\n", argv[0]);
2912 return WERR_OK;
2915 if (argc == 3) {
2916 keyname = argv[2];
2917 } else {
2918 keyname = "";
2921 /* Open printer handle */
2923 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2925 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2926 printername,
2927 SEC_FLAG_MAXIMUM_ALLOWED,
2928 &hnd);
2929 if (!W_ERROR_IS_OK(result)) {
2930 goto done;
2933 /* Enumerate subkeys */
2935 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
2936 &hnd,
2937 keyname,
2938 &key_buffer,
2941 if (!W_ERROR_IS_OK(result)) {
2942 goto done;
2945 for (i=0; key_buffer && key_buffer[i]; i++) {
2946 printf("%s\n", key_buffer[i]);
2949 done:
2951 if (is_valid_policy_hnd(&hnd)) {
2952 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2955 return result;
2958 /****************************************************************************
2959 ****************************************************************************/
2961 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2962 TALLOC_CTX *mem_ctx, int argc,
2963 const char **argv)
2965 const char *printername;
2966 const char *clientname;
2967 struct policy_handle hnd;
2968 WERROR result;
2969 NTSTATUS status;
2970 struct spoolss_NotifyOption option;
2972 if (argc != 2) {
2973 printf("Usage: %s printername\n", argv[0]);
2974 result = WERR_OK;
2975 goto done;
2978 /* Open printer */
2980 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2982 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2983 printername,
2984 SEC_FLAG_MAXIMUM_ALLOWED,
2985 &hnd);
2986 if (!W_ERROR_IS_OK(result)) {
2987 printf("Error opening %s\n", argv[1]);
2988 goto done;
2991 /* Create spool options */
2993 option.version = 2;
2994 option.count = 2;
2996 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2997 if (option.types == NULL) {
2998 result = WERR_NOMEM;
2999 goto done;
3002 option.types[0].type = PRINTER_NOTIFY_TYPE;
3003 option.types[0].count = 1;
3004 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3005 if (option.types[0].fields == NULL) {
3006 result = WERR_NOMEM;
3007 goto done;
3009 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3011 option.types[1].type = JOB_NOTIFY_TYPE;
3012 option.types[1].count = 1;
3013 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3014 if (option.types[1].fields == NULL) {
3015 result = WERR_NOMEM;
3016 goto done;
3018 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3020 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3021 if (!clientname) {
3022 result = WERR_NOMEM;
3023 goto done;
3026 /* Send rffpcnex */
3028 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3029 &hnd,
3032 clientname,
3033 123,
3034 &option,
3035 &result);
3036 if (!W_ERROR_IS_OK(result)) {
3037 printf("Error rffpcnex %s\n", argv[1]);
3038 goto done;
3041 done:
3042 if (is_valid_policy_hnd(&hnd))
3043 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3045 return result;
3048 /****************************************************************************
3049 ****************************************************************************/
3051 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3052 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3054 union spoolss_PrinterInfo info1, info2;
3055 WERROR werror;
3056 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3058 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3059 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3060 hnd1,
3063 &info1);
3064 if ( !W_ERROR_IS_OK(werror) ) {
3065 printf("failed (%s)\n", win_errstr(werror));
3066 talloc_destroy(mem_ctx);
3067 return false;
3069 printf("ok\n");
3071 printf("Retrieving printer properties for %s...", cli2->desthost);
3072 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3073 hnd2,
3076 &info2);
3077 if ( !W_ERROR_IS_OK(werror) ) {
3078 printf("failed (%s)\n", win_errstr(werror));
3079 talloc_destroy(mem_ctx);
3080 return false;
3082 printf("ok\n");
3084 talloc_destroy(mem_ctx);
3086 return true;
3089 /****************************************************************************
3090 ****************************************************************************/
3092 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3093 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3095 union spoolss_PrinterInfo info1, info2;
3096 WERROR werror;
3097 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3098 SEC_DESC *sd1, *sd2;
3099 bool result = true;
3102 printf("Retrieving printer security for %s...", cli1->desthost);
3103 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3104 hnd1,
3107 &info1);
3108 if ( !W_ERROR_IS_OK(werror) ) {
3109 printf("failed (%s)\n", win_errstr(werror));
3110 result = false;
3111 goto done;
3113 printf("ok\n");
3115 printf("Retrieving printer security for %s...", cli2->desthost);
3116 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3117 hnd2,
3120 &info2);
3121 if ( !W_ERROR_IS_OK(werror) ) {
3122 printf("failed (%s)\n", win_errstr(werror));
3123 result = false;
3124 goto done;
3126 printf("ok\n");
3129 printf("++ ");
3131 sd1 = info1.info3.secdesc;
3132 sd2 = info2.info3.secdesc;
3134 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3135 printf("NULL secdesc!\n");
3136 result = false;
3137 goto done;
3140 if (!security_descriptor_equal( sd1, sd2 ) ) {
3141 printf("Security Descriptors *not* equal!\n");
3142 result = false;
3143 goto done;
3146 printf("Security descriptors match\n");
3148 done:
3149 talloc_destroy(mem_ctx);
3150 return result;
3154 /****************************************************************************
3155 ****************************************************************************/
3157 extern struct user_auth_info *rpcclient_auth_info;
3159 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3160 TALLOC_CTX *mem_ctx, int argc,
3161 const char **argv)
3163 const char *printername;
3164 char *printername_path = NULL;
3165 struct cli_state *cli_server2 = NULL;
3166 struct rpc_pipe_client *cli2 = NULL;
3167 struct policy_handle hPrinter1, hPrinter2;
3168 NTSTATUS nt_status;
3169 WERROR werror;
3171 if ( argc != 3 ) {
3172 printf("Usage: %s <printer> <server>\n", argv[0]);
3173 return WERR_OK;
3176 printername = argv[1];
3178 /* first get the connection to the remote server */
3180 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3181 NULL, 0,
3182 "IPC$", "IPC",
3183 get_cmdline_auth_info_username(rpcclient_auth_info),
3184 lp_workgroup(),
3185 get_cmdline_auth_info_password(rpcclient_auth_info),
3186 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3187 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3189 if ( !NT_STATUS_IS_OK(nt_status) )
3190 return WERR_GENERAL_FAILURE;
3192 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3193 &cli2);
3194 if (!NT_STATUS_IS_OK(nt_status)) {
3195 printf("failed to open spoolss pipe on server %s (%s)\n",
3196 argv[2], nt_errstr(nt_status));
3197 return WERR_GENERAL_FAILURE;
3200 /* now open up both printers */
3202 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3204 printf("Opening %s...", printername_path);
3206 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3207 printername_path,
3208 PRINTER_ALL_ACCESS,
3209 &hPrinter1);
3210 if ( !W_ERROR_IS_OK(werror) ) {
3211 printf("failed (%s)\n", win_errstr(werror));
3212 goto done;
3214 printf("ok\n");
3216 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3218 printf("Opening %s...", printername_path);
3219 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3220 printername_path,
3221 PRINTER_ALL_ACCESS,
3222 &hPrinter2);
3223 if ( !W_ERROR_IS_OK(werror) ) {
3224 printf("failed (%s)\n", win_errstr(werror));
3225 goto done;
3227 printf("ok\n");
3229 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3230 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3231 #if 0
3232 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3233 #endif
3236 done:
3237 /* cleanup */
3239 printf("Closing printers...");
3240 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3241 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3242 printf("ok\n");
3244 /* close the second remote connection */
3246 cli_shutdown( cli_server2 );
3247 return WERR_OK;
3250 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3252 printf("print_processor_name: %s\n", r->print_processor_name);
3255 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3256 TALLOC_CTX *mem_ctx, int argc,
3257 const char **argv)
3259 WERROR werror;
3260 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3261 uint32_t num_procs, level = 1, i;
3262 union spoolss_PrintProcessorInfo *procs;
3264 /* Parse the command arguments */
3266 if (argc < 1 || argc > 4) {
3267 printf ("Usage: %s [environment] [level]\n", argv[0]);
3268 return WERR_OK;
3271 if (argc >= 2) {
3272 environment = argv[1];
3275 if (argc == 3) {
3276 level = atoi(argv[2]);
3279 /* Enumerate Print Processors */
3281 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3282 cli->srv_name_slash,
3283 environment,
3284 level,
3286 &num_procs,
3287 &procs);
3288 if (!W_ERROR_IS_OK(werror))
3289 goto done;
3291 /* Display output */
3293 for (i = 0; i < num_procs; i++) {
3294 switch (level) {
3295 case 1:
3296 display_proc_info1(&procs[i].info1);
3297 break;
3301 done:
3302 return werror;
3305 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3307 printf("name_array: %s\n", r->name_array);
3310 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3311 TALLOC_CTX *mem_ctx, int argc,
3312 const char **argv)
3314 WERROR werror;
3315 const char *print_processor_name = "winprint";
3316 uint32_t num_procs, level = 1, i;
3317 union spoolss_PrintProcDataTypesInfo *procs;
3319 /* Parse the command arguments */
3321 if (argc < 1 || argc > 4) {
3322 printf ("Usage: %s [environment] [level]\n", argv[0]);
3323 return WERR_OK;
3326 if (argc >= 2) {
3327 print_processor_name = argv[1];
3330 if (argc == 3) {
3331 level = atoi(argv[2]);
3334 /* Enumerate Print Processor Data Types */
3336 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3337 cli->srv_name_slash,
3338 print_processor_name,
3339 level,
3341 &num_procs,
3342 &procs);
3343 if (!W_ERROR_IS_OK(werror))
3344 goto done;
3346 /* Display output */
3348 for (i = 0; i < num_procs; i++) {
3349 switch (level) {
3350 case 1:
3351 display_proc_data_types_info1(&procs[i].info1);
3352 break;
3356 done:
3357 return werror;
3360 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3362 printf("monitor_name: %s\n", r->monitor_name);
3365 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3367 printf("monitor_name: %s\n", r->monitor_name);
3368 printf("environment: %s\n", r->environment);
3369 printf("dll_name: %s\n", r->dll_name);
3372 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3373 TALLOC_CTX *mem_ctx, int argc,
3374 const char **argv)
3376 WERROR werror;
3377 uint32_t count, level = 1, i;
3378 union spoolss_MonitorInfo *info;
3380 /* Parse the command arguments */
3382 if (argc > 2) {
3383 printf("Usage: %s [level]\n", argv[0]);
3384 return WERR_OK;
3387 if (argc == 2) {
3388 level = atoi(argv[1]);
3391 /* Enumerate Print Monitors */
3393 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3394 cli->srv_name_slash,
3395 level,
3397 &count,
3398 &info);
3399 if (!W_ERROR_IS_OK(werror)) {
3400 goto done;
3403 /* Display output */
3405 for (i = 0; i < count; i++) {
3406 switch (level) {
3407 case 1:
3408 display_monitor1(&info[i].info1);
3409 break;
3410 case 2:
3411 display_monitor2(&info[i].info2);
3412 break;
3416 done:
3417 return werror;
3420 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3421 TALLOC_CTX *mem_ctx, int argc,
3422 const char **argv)
3424 WERROR result;
3425 NTSTATUS status;
3426 struct policy_handle handle, gdi_handle;
3427 const char *printername;
3428 struct spoolss_DevmodeContainer devmode_ctr;
3430 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3432 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3433 printername,
3434 SEC_FLAG_MAXIMUM_ALLOWED,
3435 &handle);
3436 if (!W_ERROR_IS_OK(result)) {
3437 return result;
3440 ZERO_STRUCT(devmode_ctr);
3442 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3443 &handle,
3444 &gdi_handle,
3445 &devmode_ctr,
3446 &result);
3447 if (!W_ERROR_IS_OK(result)) {
3448 goto done;
3451 done:
3452 if (is_valid_policy_hnd(&gdi_handle)) {
3453 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3455 if (is_valid_policy_hnd(&handle)) {
3456 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3459 return result;
3462 /* List of commands exported by this module */
3463 struct cmd_set spoolss_commands[] = {
3465 { "SPOOLSS" },
3467 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3468 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3469 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3470 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3471 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3472 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3473 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3474 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3475 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3476 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3477 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3478 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3479 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3480 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3481 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3482 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3483 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3484 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3485 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3486 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3487 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3488 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3489 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3490 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3491 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3492 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3493 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3494 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3495 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3496 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3497 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3498 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3499 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3500 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3501 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3503 { NULL }