s3-rpcclient: fix rpcclient after spoolss_SetPrinterData{Ex} IDL change.
[Samba/kamenim.git] / source3 / rpcclient / cmd_spoolss.c
blob8b7152152a6a0fbdba4472f52814e88f4d529abc
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_ptr = 0;
1680 info2.secdesc_ptr = 0;
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;
2371 DATA_BLOB blob;
2373 /* parse the command arguments */
2374 if (argc < 5) {
2375 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2376 " <value> <data>\n",
2377 argv[0]);
2378 result = WERR_INVALID_PARAM;
2379 goto done;
2382 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2384 type = REG_NONE;
2386 if (strequal(argv[2], "string")) {
2387 type = REG_SZ;
2390 if (strequal(argv[2], "binary")) {
2391 type = REG_BINARY;
2394 if (strequal(argv[2], "dword")) {
2395 type = REG_DWORD;
2398 if (strequal(argv[2], "multistring")) {
2399 type = REG_MULTI_SZ;
2402 if (type == REG_NONE) {
2403 printf("Unknown data type: %s\n", argv[2]);
2404 result = WERR_INVALID_PARAM;
2405 goto done;
2408 /* get a printer handle */
2410 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2411 printername,
2412 SEC_FLAG_MAXIMUM_ALLOWED,
2413 &pol);
2414 if (!W_ERROR_IS_OK(result)) {
2415 goto done;
2418 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2419 &pol,
2422 &info);
2423 if (!W_ERROR_IS_OK(result)) {
2424 goto done;
2427 printf("%s\n", current_timestring(mem_ctx, true));
2428 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2430 /* Set the printer data */
2432 switch (type) {
2433 case REG_SZ:
2434 data.string = talloc_strdup(mem_ctx, argv[4]);
2435 W_ERROR_HAVE_NO_MEMORY(data.string);
2436 break;
2437 case REG_DWORD:
2438 data.value = strtoul(argv[4], NULL, 10);
2439 break;
2440 case REG_BINARY:
2441 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2442 break;
2443 case REG_MULTI_SZ: {
2444 int i, num_strings;
2445 const char **strings = NULL;
2447 for (i=4; i<argc; i++) {
2448 if (strcmp(argv[i], "NULL") == 0) {
2449 argv[i] = "";
2451 if (!add_string_to_array(mem_ctx, argv[i],
2452 &strings,
2453 &num_strings)) {
2454 result = WERR_NOMEM;
2455 goto done;
2458 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2459 if (!data.string_array) {
2460 result = WERR_NOMEM;
2461 goto done;
2463 for (i=0; i < num_strings; i++) {
2464 data.string_array[i] = strings[i];
2466 break;
2468 default:
2469 printf("Unknown data type: %s\n", argv[2]);
2470 result = WERR_INVALID_PARAM;
2471 goto done;
2474 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2475 if (!W_ERROR_IS_OK(result)) {
2476 goto done;
2479 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2480 &pol,
2481 argv[3], /* value_name */
2482 type,
2483 blob.data,
2484 blob.length,
2485 &result);
2486 if (!W_ERROR_IS_OK(result)) {
2487 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2488 goto done;
2490 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2492 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2493 &pol,
2496 &info);
2497 if (!W_ERROR_IS_OK(result)) {
2498 goto done;
2501 printf("%s\n", current_timestring(mem_ctx, true));
2502 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2504 done:
2505 /* cleanup */
2506 if (is_valid_policy_hnd(&pol)) {
2507 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2510 return result;
2513 /****************************************************************************
2514 ****************************************************************************/
2516 static void display_job_info1(struct spoolss_JobInfo1 *r)
2518 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2519 r->user_name, r->document_name, r->text_status, r->pages_printed,
2520 r->total_pages);
2523 /****************************************************************************
2524 ****************************************************************************/
2526 static void display_job_info2(struct spoolss_JobInfo2 *r)
2528 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2529 r->position, r->job_id,
2530 r->user_name, r->document_name, r->text_status, r->pages_printed,
2531 r->total_pages, r->size);
2534 /****************************************************************************
2535 ****************************************************************************/
2537 static void display_job_info3(struct spoolss_JobInfo3 *r)
2539 printf("jobid[%d], next_jobid[%d]\n",
2540 r->job_id, r->next_job_id);
2543 /****************************************************************************
2544 ****************************************************************************/
2546 static void display_job_info4(struct spoolss_JobInfo4 *r)
2548 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2549 r->position, r->job_id,
2550 r->user_name, r->document_name, r->text_status, r->pages_printed,
2551 r->total_pages, r->size, r->size_high);
2554 /****************************************************************************
2555 ****************************************************************************/
2557 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2558 TALLOC_CTX *mem_ctx, int argc,
2559 const char **argv)
2561 WERROR result;
2562 uint32_t level = 1, count, i;
2563 const char *printername;
2564 struct policy_handle hnd;
2565 union spoolss_JobInfo *info;
2567 if (argc < 2 || argc > 3) {
2568 printf("Usage: %s printername [level]\n", argv[0]);
2569 return WERR_OK;
2572 if (argc == 3) {
2573 level = atoi(argv[2]);
2576 /* Open printer handle */
2578 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2580 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2581 printername,
2582 SEC_FLAG_MAXIMUM_ALLOWED,
2583 &hnd);
2584 if (!W_ERROR_IS_OK(result))
2585 goto done;
2587 /* Enumerate ports */
2589 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2590 &hnd,
2591 0, /* firstjob */
2592 1000, /* numjobs */
2593 level,
2595 &count,
2596 &info);
2597 if (!W_ERROR_IS_OK(result)) {
2598 goto done;
2601 for (i = 0; i < count; i++) {
2602 switch (level) {
2603 case 1:
2604 display_job_info1(&info[i].info1);
2605 break;
2606 case 2:
2607 display_job_info2(&info[i].info2);
2608 break;
2609 default:
2610 d_printf("unknown info level %d\n", level);
2611 break;
2615 done:
2616 if (is_valid_policy_hnd(&hnd)) {
2617 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2620 return result;
2623 /****************************************************************************
2624 ****************************************************************************/
2626 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2627 TALLOC_CTX *mem_ctx, int argc,
2628 const char **argv)
2630 WERROR result;
2631 const char *printername;
2632 struct policy_handle hnd;
2633 uint32_t job_id;
2634 uint32_t level = 1;
2635 union spoolss_JobInfo info;
2637 if (argc < 3 || argc > 4) {
2638 printf("Usage: %s printername job_id [level]\n", argv[0]);
2639 return WERR_OK;
2642 job_id = atoi(argv[2]);
2644 if (argc == 4) {
2645 level = atoi(argv[3]);
2648 /* Open printer handle */
2650 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2652 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2653 printername,
2654 SEC_FLAG_MAXIMUM_ALLOWED,
2655 &hnd);
2656 if (!W_ERROR_IS_OK(result)) {
2657 goto done;
2660 /* Enumerate ports */
2662 result = rpccli_spoolss_getjob(cli, mem_ctx,
2663 &hnd,
2664 job_id,
2665 level,
2667 &info);
2669 if (!W_ERROR_IS_OK(result)) {
2670 goto done;
2673 switch (level) {
2674 case 1:
2675 display_job_info1(&info.info1);
2676 break;
2677 case 2:
2678 display_job_info2(&info.info2);
2679 break;
2680 case 3:
2681 display_job_info3(&info.info3);
2682 break;
2683 case 4:
2684 display_job_info4(&info.info4);
2685 break;
2686 default:
2687 d_printf("unknown info level %d\n", level);
2688 break;
2691 done:
2692 if (is_valid_policy_hnd(&hnd)) {
2693 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2696 return result;
2699 /****************************************************************************
2700 ****************************************************************************/
2702 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2703 TALLOC_CTX *mem_ctx, int argc,
2704 const char **argv)
2706 WERROR result;
2707 NTSTATUS status;
2708 const char *printername;
2709 struct policy_handle hnd;
2710 uint32_t job_id;
2711 enum spoolss_JobControl command;
2713 if (argc != 4) {
2714 printf("Usage: %s printername job_id command\n", argv[0]);
2715 return WERR_OK;
2718 job_id = atoi(argv[2]);
2719 command = atoi(argv[3]);
2721 /* Open printer handle */
2723 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2725 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2726 printername,
2727 SEC_FLAG_MAXIMUM_ALLOWED,
2728 &hnd);
2729 if (!W_ERROR_IS_OK(result)) {
2730 goto done;
2733 /* Set Job */
2735 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2736 &hnd,
2737 job_id,
2738 NULL,
2739 command,
2740 &result);
2742 if (!W_ERROR_IS_OK(result)) {
2743 goto done;
2746 done:
2747 if (is_valid_policy_hnd(&hnd)) {
2748 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2751 return result;
2754 /****************************************************************************
2755 ****************************************************************************/
2757 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2758 TALLOC_CTX *mem_ctx, int argc,
2759 const char **argv)
2761 WERROR result;
2762 NTSTATUS status;
2763 uint32_t i = 0;
2764 const char *printername;
2765 struct policy_handle hnd;
2766 uint32_t value_offered = 0;
2767 const char *value_name = NULL;
2768 uint32_t value_needed;
2769 enum winreg_Type type;
2770 uint8_t *data = NULL;
2771 uint32_t data_offered = 0;
2772 uint32_t data_needed;
2774 if (argc != 2) {
2775 printf("Usage: %s printername\n", argv[0]);
2776 return WERR_OK;
2779 /* Open printer handle */
2781 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2783 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2784 printername,
2785 SEC_FLAG_MAXIMUM_ALLOWED,
2786 &hnd);
2787 if (!W_ERROR_IS_OK(result)) {
2788 goto done;
2791 /* Enumerate data */
2793 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2794 &hnd,
2796 value_name,
2797 value_offered,
2798 &value_needed,
2799 &type,
2800 data,
2801 data_offered,
2802 &data_needed,
2803 &result);
2805 data_offered = data_needed;
2806 value_offered = value_needed;
2807 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2808 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2810 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2812 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2813 &hnd,
2814 i++,
2815 value_name,
2816 value_offered,
2817 &value_needed,
2818 &type,
2819 data,
2820 data_offered,
2821 &data_needed,
2822 &result);
2823 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2824 struct regval_blob v;
2825 fstrcpy(v.valuename, value_name);
2826 v.type = type;
2827 v.size = data_offered;
2828 v.data_p = data;
2829 display_reg_value(v);
2833 if (W_ERROR_V(result) == ERRnomoreitems) {
2834 result = W_ERROR(ERRsuccess);
2837 done:
2838 if (is_valid_policy_hnd(&hnd)) {
2839 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2842 return result;
2845 /****************************************************************************
2846 ****************************************************************************/
2848 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2849 TALLOC_CTX *mem_ctx, int argc,
2850 const char **argv)
2852 WERROR result;
2853 uint32_t i;
2854 const char *printername;
2855 struct policy_handle hnd;
2856 uint32_t count;
2857 struct spoolss_PrinterEnumValues *info;
2859 if (argc != 3) {
2860 printf("Usage: %s printername <keyname>\n", argv[0]);
2861 return WERR_OK;
2864 /* Open printer handle */
2866 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2868 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2869 printername,
2870 SEC_FLAG_MAXIMUM_ALLOWED,
2871 &hnd);
2872 if (!W_ERROR_IS_OK(result)) {
2873 goto done;
2876 /* Enumerate subkeys */
2878 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2879 &hnd,
2880 argv[2],
2882 &count,
2883 &info);
2884 if (!W_ERROR_IS_OK(result)) {
2885 goto done;
2888 for (i=0; i < count; i++) {
2889 display_printer_data(info[i].value_name,
2890 info[i].type,
2891 info[i].data);
2894 done:
2895 if (is_valid_policy_hnd(&hnd)) {
2896 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2899 return result;
2902 /****************************************************************************
2903 ****************************************************************************/
2905 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2906 TALLOC_CTX *mem_ctx, int argc,
2907 const char **argv)
2909 WERROR result;
2910 const char *printername;
2911 const char *keyname = NULL;
2912 struct policy_handle hnd;
2913 const char **key_buffer = NULL;
2914 int i;
2915 uint32_t offered = 0;
2917 if (argc < 2 || argc > 4) {
2918 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
2919 return WERR_OK;
2922 if (argc >= 3) {
2923 keyname = argv[2];
2924 } else {
2925 keyname = "";
2928 if (argc == 4) {
2929 offered = atoi(argv[3]);
2932 /* Open printer handle */
2934 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2936 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2937 printername,
2938 SEC_FLAG_MAXIMUM_ALLOWED,
2939 &hnd);
2940 if (!W_ERROR_IS_OK(result)) {
2941 goto done;
2944 /* Enumerate subkeys */
2946 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
2947 &hnd,
2948 keyname,
2949 &key_buffer,
2950 offered);
2952 if (!W_ERROR_IS_OK(result)) {
2953 goto done;
2956 for (i=0; key_buffer && key_buffer[i]; i++) {
2957 printf("%s\n", key_buffer[i]);
2960 done:
2962 if (is_valid_policy_hnd(&hnd)) {
2963 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2966 return result;
2969 /****************************************************************************
2970 ****************************************************************************/
2972 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2973 TALLOC_CTX *mem_ctx, int argc,
2974 const char **argv)
2976 const char *printername;
2977 const char *clientname;
2978 struct policy_handle hnd;
2979 WERROR result;
2980 NTSTATUS status;
2981 struct spoolss_NotifyOption option;
2983 if (argc != 2) {
2984 printf("Usage: %s printername\n", argv[0]);
2985 result = WERR_OK;
2986 goto done;
2989 /* Open printer */
2991 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2993 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2994 printername,
2995 SEC_FLAG_MAXIMUM_ALLOWED,
2996 &hnd);
2997 if (!W_ERROR_IS_OK(result)) {
2998 printf("Error opening %s\n", argv[1]);
2999 goto done;
3002 /* Create spool options */
3004 option.version = 2;
3005 option.count = 2;
3007 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3008 if (option.types == NULL) {
3009 result = WERR_NOMEM;
3010 goto done;
3013 option.types[0].type = PRINTER_NOTIFY_TYPE;
3014 option.types[0].count = 1;
3015 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3016 if (option.types[0].fields == NULL) {
3017 result = WERR_NOMEM;
3018 goto done;
3020 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3022 option.types[1].type = JOB_NOTIFY_TYPE;
3023 option.types[1].count = 1;
3024 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3025 if (option.types[1].fields == NULL) {
3026 result = WERR_NOMEM;
3027 goto done;
3029 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3031 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3032 if (!clientname) {
3033 result = WERR_NOMEM;
3034 goto done;
3037 /* Send rffpcnex */
3039 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3040 &hnd,
3043 clientname,
3044 123,
3045 &option,
3046 &result);
3047 if (!W_ERROR_IS_OK(result)) {
3048 printf("Error rffpcnex %s\n", argv[1]);
3049 goto done;
3052 done:
3053 if (is_valid_policy_hnd(&hnd))
3054 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3056 return result;
3059 /****************************************************************************
3060 ****************************************************************************/
3062 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3063 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3065 union spoolss_PrinterInfo info1, info2;
3066 WERROR werror;
3067 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3069 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3070 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3071 hnd1,
3074 &info1);
3075 if ( !W_ERROR_IS_OK(werror) ) {
3076 printf("failed (%s)\n", win_errstr(werror));
3077 talloc_destroy(mem_ctx);
3078 return false;
3080 printf("ok\n");
3082 printf("Retrieving printer properties for %s...", cli2->desthost);
3083 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3084 hnd2,
3087 &info2);
3088 if ( !W_ERROR_IS_OK(werror) ) {
3089 printf("failed (%s)\n", win_errstr(werror));
3090 talloc_destroy(mem_ctx);
3091 return false;
3093 printf("ok\n");
3095 talloc_destroy(mem_ctx);
3097 return true;
3100 /****************************************************************************
3101 ****************************************************************************/
3103 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3104 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3106 union spoolss_PrinterInfo info1, info2;
3107 WERROR werror;
3108 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3109 SEC_DESC *sd1, *sd2;
3110 bool result = true;
3113 printf("Retrieving printer security for %s...", cli1->desthost);
3114 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3115 hnd1,
3118 &info1);
3119 if ( !W_ERROR_IS_OK(werror) ) {
3120 printf("failed (%s)\n", win_errstr(werror));
3121 result = false;
3122 goto done;
3124 printf("ok\n");
3126 printf("Retrieving printer security for %s...", cli2->desthost);
3127 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3128 hnd2,
3131 &info2);
3132 if ( !W_ERROR_IS_OK(werror) ) {
3133 printf("failed (%s)\n", win_errstr(werror));
3134 result = false;
3135 goto done;
3137 printf("ok\n");
3140 printf("++ ");
3142 sd1 = info1.info3.secdesc;
3143 sd2 = info2.info3.secdesc;
3145 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3146 printf("NULL secdesc!\n");
3147 result = false;
3148 goto done;
3151 if (!security_descriptor_equal( sd1, sd2 ) ) {
3152 printf("Security Descriptors *not* equal!\n");
3153 result = false;
3154 goto done;
3157 printf("Security descriptors match\n");
3159 done:
3160 talloc_destroy(mem_ctx);
3161 return result;
3165 /****************************************************************************
3166 ****************************************************************************/
3168 extern struct user_auth_info *rpcclient_auth_info;
3170 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3171 TALLOC_CTX *mem_ctx, int argc,
3172 const char **argv)
3174 const char *printername;
3175 char *printername_path = NULL;
3176 struct cli_state *cli_server2 = NULL;
3177 struct rpc_pipe_client *cli2 = NULL;
3178 struct policy_handle hPrinter1, hPrinter2;
3179 NTSTATUS nt_status;
3180 WERROR werror;
3182 if ( argc != 3 ) {
3183 printf("Usage: %s <printer> <server>\n", argv[0]);
3184 return WERR_OK;
3187 printername = argv[1];
3189 /* first get the connection to the remote server */
3191 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3192 NULL, 0,
3193 "IPC$", "IPC",
3194 get_cmdline_auth_info_username(rpcclient_auth_info),
3195 lp_workgroup(),
3196 get_cmdline_auth_info_password(rpcclient_auth_info),
3197 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3198 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3200 if ( !NT_STATUS_IS_OK(nt_status) )
3201 return WERR_GENERAL_FAILURE;
3203 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3204 &cli2);
3205 if (!NT_STATUS_IS_OK(nt_status)) {
3206 printf("failed to open spoolss pipe on server %s (%s)\n",
3207 argv[2], nt_errstr(nt_status));
3208 return WERR_GENERAL_FAILURE;
3211 /* now open up both printers */
3213 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3215 printf("Opening %s...", printername_path);
3217 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3218 printername_path,
3219 PRINTER_ALL_ACCESS,
3220 &hPrinter1);
3221 if ( !W_ERROR_IS_OK(werror) ) {
3222 printf("failed (%s)\n", win_errstr(werror));
3223 goto done;
3225 printf("ok\n");
3227 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3229 printf("Opening %s...", printername_path);
3230 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3231 printername_path,
3232 PRINTER_ALL_ACCESS,
3233 &hPrinter2);
3234 if ( !W_ERROR_IS_OK(werror) ) {
3235 printf("failed (%s)\n", win_errstr(werror));
3236 goto done;
3238 printf("ok\n");
3240 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3241 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3242 #if 0
3243 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3244 #endif
3247 done:
3248 /* cleanup */
3250 printf("Closing printers...");
3251 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3252 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3253 printf("ok\n");
3255 /* close the second remote connection */
3257 cli_shutdown( cli_server2 );
3258 return WERR_OK;
3261 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3263 printf("print_processor_name: %s\n", r->print_processor_name);
3266 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3267 TALLOC_CTX *mem_ctx, int argc,
3268 const char **argv)
3270 WERROR werror;
3271 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3272 uint32_t num_procs, level = 1, i;
3273 union spoolss_PrintProcessorInfo *procs;
3275 /* Parse the command arguments */
3277 if (argc < 1 || argc > 4) {
3278 printf ("Usage: %s [environment] [level]\n", argv[0]);
3279 return WERR_OK;
3282 if (argc >= 2) {
3283 environment = argv[1];
3286 if (argc == 3) {
3287 level = atoi(argv[2]);
3290 /* Enumerate Print Processors */
3292 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3293 cli->srv_name_slash,
3294 environment,
3295 level,
3297 &num_procs,
3298 &procs);
3299 if (!W_ERROR_IS_OK(werror))
3300 goto done;
3302 /* Display output */
3304 for (i = 0; i < num_procs; i++) {
3305 switch (level) {
3306 case 1:
3307 display_proc_info1(&procs[i].info1);
3308 break;
3312 done:
3313 return werror;
3316 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3318 printf("name_array: %s\n", r->name_array);
3321 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3322 TALLOC_CTX *mem_ctx, int argc,
3323 const char **argv)
3325 WERROR werror;
3326 const char *print_processor_name = "winprint";
3327 uint32_t num_procs, level = 1, i;
3328 union spoolss_PrintProcDataTypesInfo *procs;
3330 /* Parse the command arguments */
3332 if (argc < 1 || argc > 4) {
3333 printf ("Usage: %s [environment] [level]\n", argv[0]);
3334 return WERR_OK;
3337 if (argc >= 2) {
3338 print_processor_name = argv[1];
3341 if (argc == 3) {
3342 level = atoi(argv[2]);
3345 /* Enumerate Print Processor Data Types */
3347 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3348 cli->srv_name_slash,
3349 print_processor_name,
3350 level,
3352 &num_procs,
3353 &procs);
3354 if (!W_ERROR_IS_OK(werror))
3355 goto done;
3357 /* Display output */
3359 for (i = 0; i < num_procs; i++) {
3360 switch (level) {
3361 case 1:
3362 display_proc_data_types_info1(&procs[i].info1);
3363 break;
3367 done:
3368 return werror;
3371 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3373 printf("monitor_name: %s\n", r->monitor_name);
3376 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3378 printf("monitor_name: %s\n", r->monitor_name);
3379 printf("environment: %s\n", r->environment);
3380 printf("dll_name: %s\n", r->dll_name);
3383 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3384 TALLOC_CTX *mem_ctx, int argc,
3385 const char **argv)
3387 WERROR werror;
3388 uint32_t count, level = 1, i;
3389 union spoolss_MonitorInfo *info;
3391 /* Parse the command arguments */
3393 if (argc > 2) {
3394 printf("Usage: %s [level]\n", argv[0]);
3395 return WERR_OK;
3398 if (argc == 2) {
3399 level = atoi(argv[1]);
3402 /* Enumerate Print Monitors */
3404 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3405 cli->srv_name_slash,
3406 level,
3408 &count,
3409 &info);
3410 if (!W_ERROR_IS_OK(werror)) {
3411 goto done;
3414 /* Display output */
3416 for (i = 0; i < count; i++) {
3417 switch (level) {
3418 case 1:
3419 display_monitor1(&info[i].info1);
3420 break;
3421 case 2:
3422 display_monitor2(&info[i].info2);
3423 break;
3427 done:
3428 return werror;
3431 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3432 TALLOC_CTX *mem_ctx, int argc,
3433 const char **argv)
3435 WERROR result;
3436 NTSTATUS status;
3437 struct policy_handle handle, gdi_handle;
3438 const char *printername;
3439 struct spoolss_DevmodeContainer devmode_ctr;
3441 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3443 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3444 printername,
3445 SEC_FLAG_MAXIMUM_ALLOWED,
3446 &handle);
3447 if (!W_ERROR_IS_OK(result)) {
3448 return result;
3451 ZERO_STRUCT(devmode_ctr);
3453 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3454 &handle,
3455 &gdi_handle,
3456 &devmode_ctr,
3457 &result);
3458 if (!W_ERROR_IS_OK(result)) {
3459 goto done;
3462 done:
3463 if (is_valid_policy_hnd(&gdi_handle)) {
3464 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3466 if (is_valid_policy_hnd(&handle)) {
3467 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3470 return result;
3473 /* List of commands exported by this module */
3474 struct cmd_set spoolss_commands[] = {
3476 { "SPOOLSS" },
3478 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3479 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3480 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3481 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3482 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3483 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3484 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3485 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3486 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3487 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3488 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3489 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3490 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3491 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3492 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3493 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3494 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3495 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3496 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3497 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3498 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3499 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3500 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3501 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3502 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3503 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3504 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3505 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3506 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3507 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3508 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3509 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3510 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3511 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3512 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3514 { NULL }