s4-smb2: check for an invalid lock flags combination
[Samba/cd1.git] / source3 / rpcclient / cmd_spoolss.c
blobe24fb99e6fdc0a5b20b3bca2e6dddbaa70a2e6ed
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;
867 struct regval_blob value;
869 enum winreg_Type type;
870 uint8_t *buffer = NULL;
871 uint32_t offered = 0;
872 uint32_t needed;
874 if (argc != 4) {
875 printf("Usage: %s <printername> <keyname> <valuename>\n",
876 argv[0]);
877 printf("<printername> of . queries print server\n");
878 return WERR_OK;
880 valuename = argv[3];
881 keyname = argv[2];
883 /* Open a printer handle */
885 if (strncmp(argv[1], ".", sizeof(".")) == 0)
886 fstrcpy(printername, cli->srv_name_slash);
887 else
888 slprintf(printername, sizeof(printername)-1, "%s\\%s",
889 cli->srv_name_slash, argv[1]);
891 /* get a printer handle */
893 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
894 printername,
895 SEC_FLAG_MAXIMUM_ALLOWED,
896 &pol);
897 if (!W_ERROR_IS_OK(result))
898 goto done;
900 /* Get printer info */
902 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
903 &pol,
904 keyname,
905 valuename,
906 &type,
907 buffer,
908 offered,
909 &needed,
910 &result);
911 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
912 offered = needed;
913 buffer = talloc_array(mem_ctx, uint8_t, needed);
914 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
915 &pol,
916 keyname,
917 valuename,
918 &type,
919 buffer,
920 offered,
921 &needed,
922 &result);
925 if (!NT_STATUS_IS_OK(status)) {
926 goto done;
929 if (!W_ERROR_IS_OK(result)) {
930 goto done;
934 if (!W_ERROR_IS_OK(result))
935 goto done;
937 /* Display printer data */
939 fstrcpy(value.valuename, valuename);
940 value.type = type;
941 value.size = needed;
942 value.data_p = buffer;
944 display_reg_value(value);
946 done:
947 if (is_valid_policy_hnd(&pol))
948 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
950 return result;
953 /****************************************************************************
954 ****************************************************************************/
956 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
958 if (!r) {
959 return;
962 printf("Printer Driver Info 1:\n");
963 printf("\tDriver Name: [%s]\n", r->driver_name);
964 printf("\n");
967 /****************************************************************************
968 ****************************************************************************/
970 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
972 if (!r) {
973 return;
976 printf("Printer Driver Info 2:\n");
977 printf("\tVersion: [%x]\n", r->version);
978 printf("\tDriver Name: [%s]\n", r->driver_name);
979 printf("\tArchitecture: [%s]\n", r->architecture);
980 printf("\tDriver Path: [%s]\n", r->driver_path);
981 printf("\tDatafile: [%s]\n", r->data_file);
982 printf("\tConfigfile: [%s]\n", r->config_file);
983 printf("\n");
986 /****************************************************************************
987 ****************************************************************************/
989 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
991 int i;
993 if (!r) {
994 return;
997 printf("Printer Driver Info 3:\n");
998 printf("\tVersion: [%x]\n", r->version);
999 printf("\tDriver Name: [%s]\n", r->driver_name);
1000 printf("\tArchitecture: [%s]\n", r->architecture);
1001 printf("\tDriver Path: [%s]\n", r->driver_path);
1002 printf("\tDatafile: [%s]\n", r->data_file);
1003 printf("\tConfigfile: [%s]\n", r->config_file);
1004 printf("\tHelpfile: [%s]\n", r->help_file);
1006 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1007 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1010 printf("\tMonitorname: [%s]\n", r->monitor_name);
1011 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1012 printf("\n");
1015 /****************************************************************************
1016 ****************************************************************************/
1018 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1020 int i;
1022 if (!r) {
1023 return;
1026 printf("Printer Driver Info 4:\n");
1027 printf("\tVersion: [%x]\n", r->version);
1028 printf("\tDriver Name: [%s]\n", r->driver_name);
1029 printf("\tArchitecture: [%s]\n", r->architecture);
1030 printf("\tDriver Path: [%s]\n", r->driver_path);
1031 printf("\tDatafile: [%s]\n", r->data_file);
1032 printf("\tConfigfile: [%s]\n", r->config_file);
1033 printf("\tHelpfile: [%s]\n", r->help_file);
1035 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1036 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1039 printf("\tMonitorname: [%s]\n", r->monitor_name);
1040 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1042 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1043 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1045 printf("\n");
1048 /****************************************************************************
1049 ****************************************************************************/
1051 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1053 if (!r) {
1054 return;
1057 printf("Printer Driver Info 5:\n");
1058 printf("\tVersion: [%x]\n", r->version);
1059 printf("\tDriver Name: [%s]\n", r->driver_name);
1060 printf("\tArchitecture: [%s]\n", r->architecture);
1061 printf("\tDriver Path: [%s]\n", r->driver_path);
1062 printf("\tDatafile: [%s]\n", r->data_file);
1063 printf("\tConfigfile: [%s]\n", r->config_file);
1064 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1065 printf("\tConfig Version: [0x%x]\n", r->config_version);
1066 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1067 printf("\n");
1070 /****************************************************************************
1071 ****************************************************************************/
1073 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1075 int i;
1077 if (!r) {
1078 return;
1081 printf("Printer Driver Info 6:\n");
1082 printf("\tVersion: [%x]\n", r->version);
1083 printf("\tDriver Name: [%s]\n", r->driver_name);
1084 printf("\tArchitecture: [%s]\n", r->architecture);
1085 printf("\tDriver Path: [%s]\n", r->driver_path);
1086 printf("\tDatafile: [%s]\n", r->data_file);
1087 printf("\tConfigfile: [%s]\n", r->config_file);
1088 printf("\tHelpfile: [%s]\n", r->help_file);
1090 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1091 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1094 printf("\tMonitorname: [%s]\n", r->monitor_name);
1095 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1097 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1098 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1101 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1102 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1103 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1104 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1105 printf("\tHardware ID: [%s]\n", r->hardware_id);
1106 printf("\tProvider: [%s]\n", r->provider);
1108 printf("\n");
1111 /****************************************************************************
1112 ****************************************************************************/
1114 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1116 int i;
1118 if (!r) {
1119 return;
1122 printf("Printer Driver Info 8:\n");
1123 printf("\tVersion: [%x]\n", r->version);
1124 printf("\tDriver Name: [%s]\n", r->driver_name);
1125 printf("\tArchitecture: [%s]\n", r->architecture);
1126 printf("\tDriver Path: [%s]\n", r->driver_path);
1127 printf("\tDatafile: [%s]\n", r->data_file);
1128 printf("\tConfigfile: [%s]\n", r->config_file);
1129 printf("\tHelpfile: [%s]\n", r->help_file);
1130 printf("\tMonitorname: [%s]\n", r->monitor_name);
1131 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1133 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1134 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1137 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1138 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1141 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1142 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1143 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1144 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1145 printf("\tHardware ID: [%s]\n", r->hardware_id);
1146 printf("\tProvider: [%s]\n", r->provider);
1147 printf("\tPrint Processor: [%s]\n", r->print_processor);
1148 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1149 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1150 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1152 printf("\tInf Path: [%s]\n", r->inf_path);
1153 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1154 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1155 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1157 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1158 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1159 (long long unsigned int)r->min_inbox_driver_ver_version);
1161 printf("\n");
1164 /****************************************************************************
1165 ****************************************************************************/
1167 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1168 TALLOC_CTX *mem_ctx,
1169 int argc, const char **argv)
1171 struct policy_handle pol;
1172 WERROR werror;
1173 uint32_t level = 3;
1174 const char *printername;
1175 uint32_t i;
1176 bool success = false;
1177 union spoolss_DriverInfo info;
1178 uint32_t server_major_version;
1179 uint32_t server_minor_version;
1181 if ((argc == 1) || (argc > 3)) {
1182 printf("Usage: %s <printername> [level]\n", argv[0]);
1183 return WERR_OK;
1186 /* get the arguments need to open the printer handle */
1188 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1190 if (argc == 3) {
1191 level = atoi(argv[2]);
1194 /* Open a printer handle */
1196 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1197 printername,
1198 PRINTER_ACCESS_USE,
1199 &pol);
1200 if (!W_ERROR_IS_OK(werror)) {
1201 printf("Error opening printer handle for %s!\n", printername);
1202 return werror;
1205 /* loop through and print driver info level for each architecture */
1207 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1209 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1210 &pol,
1211 archi_table[i].long_archi,
1212 level,
1213 0, /* offered */
1214 archi_table[i].version,
1216 &info,
1217 &server_major_version,
1218 &server_minor_version);
1219 if (!W_ERROR_IS_OK(werror)) {
1220 continue;
1223 /* need at least one success */
1225 success = true;
1227 printf("\n[%s]\n", archi_table[i].long_archi);
1229 switch (level) {
1230 case 1:
1231 display_print_driver1(&info.info1);
1232 break;
1233 case 2:
1234 display_print_driver2(&info.info2);
1235 break;
1236 case 3:
1237 display_print_driver3(&info.info3);
1238 break;
1239 case 4:
1240 display_print_driver4(&info.info4);
1241 break;
1242 case 5:
1243 display_print_driver5(&info.info5);
1244 break;
1245 case 6:
1246 display_print_driver6(&info.info6);
1247 break;
1248 case 8:
1249 display_print_driver8(&info.info8);
1250 break;
1251 default:
1252 printf("unknown info level %d\n", level);
1253 break;
1257 /* Cleanup */
1259 if (is_valid_policy_hnd(&pol)) {
1260 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1263 if (success) {
1264 werror = WERR_OK;
1267 return werror;
1270 /****************************************************************************
1271 ****************************************************************************/
1273 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1274 TALLOC_CTX *mem_ctx,
1275 const char *architecture,
1276 uint32_t level)
1278 WERROR werror;
1279 uint32_t count = 0;
1280 union spoolss_DriverInfo *info = NULL;
1281 uint32_t j;
1283 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1284 cli->srv_name_slash,
1285 architecture,
1286 level,
1288 &count,
1289 &info);
1291 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1292 printf("Server does not support environment [%s]\n",
1293 architecture);
1294 return WERR_OK;
1297 if (count == 0) {
1298 return WERR_OK;
1301 if (!W_ERROR_IS_OK(werror)) {
1302 printf("Error getting driver for environment [%s] - %s\n",
1303 architecture, win_errstr(werror));
1304 return werror;
1307 printf("\n[%s]\n", architecture);
1309 switch (level) {
1310 case 1:
1311 for (j=0; j < count; j++) {
1312 display_print_driver1(&info[j].info1);
1314 break;
1315 case 2:
1316 for (j=0; j < count; j++) {
1317 display_print_driver2(&info[j].info2);
1319 break;
1320 case 3:
1321 for (j=0; j < count; j++) {
1322 display_print_driver3(&info[j].info3);
1324 break;
1325 case 4:
1326 for (j=0; j < count; j++) {
1327 display_print_driver4(&info[j].info4);
1329 break;
1330 case 5:
1331 for (j=0; j < count; j++) {
1332 display_print_driver5(&info[j].info5);
1334 break;
1335 case 6:
1336 for (j=0; j < count; j++) {
1337 display_print_driver6(&info[j].info6);
1339 break;
1340 case 8:
1341 for (j=0; j < count; j++) {
1342 display_print_driver8(&info[j].info8);
1344 break;
1345 default:
1346 printf("unknown info level %d\n", level);
1347 return WERR_UNKNOWN_LEVEL;
1350 return werror;
1353 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1354 TALLOC_CTX *mem_ctx,
1355 int argc, const char **argv)
1357 WERROR werror = WERR_OK;
1358 uint32_t level = 1;
1359 uint32_t i;
1360 const char *architecture = NULL;
1362 if (argc > 3) {
1363 printf("Usage: enumdrivers [level] [architecture]\n");
1364 return WERR_OK;
1367 if (argc >= 2) {
1368 level = atoi(argv[1]);
1371 if (argc == 3) {
1372 architecture = argv[2];
1375 if (architecture) {
1376 return enum_driver_by_architecture(cli, mem_ctx,
1377 architecture,
1378 level);
1381 /* loop through and print driver info level for each architecture */
1382 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1383 /* check to see if we already asked for this architecture string */
1385 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1386 continue;
1389 werror = enum_driver_by_architecture(cli, mem_ctx,
1390 archi_table[i].long_archi,
1391 level);
1392 if (!W_ERROR_IS_OK(werror)) {
1393 break;
1397 return werror;
1400 /****************************************************************************
1401 ****************************************************************************/
1403 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1405 printf("\tDirectory Name:[%s]\n", r->directory_name);
1408 /****************************************************************************
1409 ****************************************************************************/
1411 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1412 TALLOC_CTX *mem_ctx,
1413 int argc, const char **argv)
1415 WERROR result;
1416 NTSTATUS status;
1417 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1418 DATA_BLOB buffer;
1419 uint32_t offered;
1420 union spoolss_DriverDirectoryInfo info;
1421 uint32_t needed;
1423 if (argc > 2) {
1424 printf("Usage: %s [environment]\n", argv[0]);
1425 return WERR_OK;
1428 /* Get the arguments need to open the printer handle */
1430 if (argc == 2) {
1431 env = argv[1];
1434 /* Get the directory. Only use Info level 1 */
1436 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1437 cli->srv_name_slash,
1438 env,
1440 NULL, /* buffer */
1441 0, /* offered */
1442 NULL, /* info */
1443 &needed,
1444 &result);
1445 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1446 offered = needed;
1447 buffer = data_blob_talloc_zero(mem_ctx, needed);
1449 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1450 cli->srv_name_slash,
1451 env,
1453 &buffer,
1454 offered,
1455 &info,
1456 &needed,
1457 &result);
1460 if (W_ERROR_IS_OK(result)) {
1461 display_printdriverdir_1(&info.info1);
1464 return result;
1467 /****************************************************************************
1468 ****************************************************************************/
1470 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1471 struct spoolss_AddDriverInfo3 *info,
1472 const char *arch)
1475 int i;
1477 for (i=0; archi_table[i].long_archi != NULL; i++)
1479 if (strcmp(arch, archi_table[i].short_archi) == 0)
1481 info->version = archi_table[i].version;
1482 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1483 break;
1487 if (archi_table[i].long_archi == NULL)
1489 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1492 return;
1496 /**************************************************************************
1497 wrapper for strtok to get the next parameter from a delimited list.
1498 Needed to handle the empty parameter string denoted by "NULL"
1499 *************************************************************************/
1501 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1502 const char *delim, const char **dest,
1503 char **saveptr)
1505 char *ptr;
1507 /* get the next token */
1508 ptr = strtok_r(str, delim, saveptr);
1510 /* a string of 'NULL' is used to represent an empty
1511 parameter because two consecutive delimiters
1512 will not return an empty string. See man strtok(3)
1513 for details */
1514 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1515 ptr = NULL;
1518 if (dest != NULL) {
1519 *dest = talloc_strdup(mem_ctx, ptr);
1522 return ptr;
1525 /********************************************************************************
1526 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1527 string in the form of
1528 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1529 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1530 <Default Data Type>:<Comma Separated list of Files>
1531 *******************************************************************************/
1533 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1534 char *args)
1536 char *str, *str2;
1537 int count = 0;
1538 char *saveptr = NULL;
1539 struct spoolss_StringArray *deps;
1540 const char **file_array = NULL;
1541 int i;
1543 /* fill in the UNISTR fields */
1544 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1545 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1546 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1547 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1548 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1549 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1550 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1552 /* <Comma Separated List of Dependent Files> */
1553 /* save the beginning of the string */
1554 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1555 str = str2;
1557 /* begin to strip out each filename */
1558 str = strtok_r(str, ",", &saveptr);
1560 /* no dependent files, we are done */
1561 if (!str) {
1562 return true;
1565 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1566 if (!deps) {
1567 return false;
1570 while (str != NULL) {
1571 add_string_to_array(deps, str, &file_array, &count);
1572 str = strtok_r(NULL, ",", &saveptr);
1575 deps->string = talloc_zero_array(deps, const char *, count + 1);
1576 if (!deps->string) {
1577 return false;
1580 for (i=0; i < count; i++) {
1581 deps->string[i] = file_array[i];
1584 r->dependent_files = deps;
1586 return true;
1589 /****************************************************************************
1590 ****************************************************************************/
1592 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1593 TALLOC_CTX *mem_ctx,
1594 int argc, const char **argv)
1596 WERROR result;
1597 NTSTATUS status;
1598 uint32_t level = 3;
1599 struct spoolss_AddDriverInfoCtr info_ctr;
1600 struct spoolss_AddDriverInfo3 info3;
1601 const char *arch;
1602 char *driver_args;
1604 /* parse the command arguments */
1605 if (argc != 3 && argc != 4)
1607 printf ("Usage: %s <Environment> \\\n", argv[0]);
1608 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1609 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1610 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1611 printf ("\t[version]\n");
1613 return WERR_OK;
1616 /* Fill in the spoolss_AddDriverInfo3 struct */
1617 ZERO_STRUCT(info3);
1619 arch = cmd_spoolss_get_short_archi(argv[1]);
1620 if (!arch) {
1621 printf ("Error Unknown architechture [%s]\n", argv[1]);
1622 return WERR_INVALID_PARAM;
1625 set_drv_info_3_env(mem_ctx, &info3, arch);
1627 driver_args = talloc_strdup( mem_ctx, argv[2] );
1628 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1630 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1631 return WERR_INVALID_PARAM;
1634 /* if printer driver version specified, override the default version
1635 * used by the architecture. This allows installation of Windows
1636 * 2000 (version 3) printer drivers. */
1637 if (argc == 4)
1639 info3.version = atoi(argv[3]);
1643 info_ctr.level = level;
1644 info_ctr.info.info3 = &info3;
1646 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1647 cli->srv_name_slash,
1648 &info_ctr,
1649 &result);
1650 if (!NT_STATUS_IS_OK(status)) {
1651 return ntstatus_to_werror(status);
1653 if (W_ERROR_IS_OK(result)) {
1654 printf ("Printer Driver %s successfully installed.\n",
1655 info3.driver_name);
1658 return result;
1662 /****************************************************************************
1663 ****************************************************************************/
1665 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1666 TALLOC_CTX *mem_ctx,
1667 int argc, const char **argv)
1669 WERROR result;
1670 struct spoolss_SetPrinterInfoCtr info_ctr;
1671 struct spoolss_SetPrinterInfo2 info2;
1673 /* parse the command arguments */
1674 if (argc != 5)
1676 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1677 return WERR_OK;
1680 /* Fill in the DRIVER_INFO_2 struct */
1681 ZERO_STRUCT(info2);
1683 info2.printername = argv[1];
1684 info2.drivername = argv[3];
1685 info2.sharename = argv[2];
1686 info2.portname = argv[4];
1687 info2.comment = "Created by rpcclient";
1688 info2.printprocessor = "winprint";
1689 info2.datatype = "RAW";
1690 info2.devmode = NULL;
1691 info2.secdesc = NULL;
1692 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1693 info2.priority = 0;
1694 info2.defaultpriority = 0;
1695 info2.starttime = 0;
1696 info2.untiltime = 0;
1698 /* These three fields must not be used by AddPrinter()
1699 as defined in the MS Platform SDK documentation..
1700 --jerry
1701 info2.status = 0;
1702 info2.cjobs = 0;
1703 info2.averageppm = 0;
1706 info_ctr.level = 2;
1707 info_ctr.info.info2 = &info2;
1709 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1710 &info_ctr);
1711 if (W_ERROR_IS_OK(result))
1712 printf ("Printer %s successfully installed.\n", argv[1]);
1714 return result;
1717 /****************************************************************************
1718 ****************************************************************************/
1720 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1721 TALLOC_CTX *mem_ctx,
1722 int argc, const char **argv)
1724 struct policy_handle pol;
1725 WERROR result;
1726 NTSTATUS status;
1727 uint32_t level = 2;
1728 const char *printername;
1729 union spoolss_PrinterInfo info;
1730 struct spoolss_SetPrinterInfoCtr info_ctr;
1731 struct spoolss_DevmodeContainer devmode_ctr;
1732 struct sec_desc_buf secdesc_ctr;
1734 ZERO_STRUCT(devmode_ctr);
1735 ZERO_STRUCT(secdesc_ctr);
1737 /* parse the command arguments */
1738 if (argc != 3)
1740 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1741 return WERR_OK;
1744 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1746 /* Get a printer handle */
1748 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1749 printername,
1750 PRINTER_ALL_ACCESS,
1751 &pol);
1752 if (!W_ERROR_IS_OK(result))
1753 goto done;
1755 /* Get printer info */
1757 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1758 &pol,
1759 level,
1761 &info);
1762 if (!W_ERROR_IS_OK(result)) {
1763 printf ("Unable to retrieve printer information!\n");
1764 goto done;
1767 /* Set the printer driver */
1769 info.info2.drivername = argv[2];
1770 info.info2.devmode = NULL;
1771 info.info2.secdesc = NULL;
1773 info_ctr.level = 2;
1774 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1776 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1777 &pol,
1778 &info_ctr,
1779 &devmode_ctr,
1780 &secdesc_ctr,
1781 0, /* command */
1782 &result);
1783 if (!W_ERROR_IS_OK(result)) {
1784 printf("SetPrinter call failed!\n");
1785 goto done;;
1788 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1790 done:
1791 /* Cleanup */
1793 if (is_valid_policy_hnd(&pol))
1794 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1796 return result;
1800 /****************************************************************************
1801 ****************************************************************************/
1803 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1804 TALLOC_CTX *mem_ctx,
1805 int argc, const char **argv)
1807 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1808 NTSTATUS status;
1810 int i;
1811 int vers = -1;
1813 const char *arch = NULL;
1814 uint32_t delete_flags = 0;
1816 /* parse the command arguments */
1817 if (argc < 2 || argc > 4) {
1818 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1819 return WERR_OK;
1822 if (argc >= 3)
1823 arch = argv[2];
1824 if (argc == 4)
1825 vers = atoi (argv[3]);
1827 if (vers >= 0) {
1828 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1831 /* delete the driver for all architectures */
1832 for (i=0; archi_table[i].long_archi; i++) {
1834 if (arch && !strequal( archi_table[i].long_archi, arch))
1835 continue;
1837 if (vers >= 0 && archi_table[i].version != vers)
1838 continue;
1840 /* make the call to remove the driver */
1841 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1842 cli->srv_name_slash,
1843 archi_table[i].long_archi,
1844 argv[1],
1845 delete_flags,
1846 archi_table[i].version,
1847 &result);
1849 if ( !W_ERROR_IS_OK(result) )
1851 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1852 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1853 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1856 else
1858 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1859 archi_table[i].long_archi, archi_table[i].version);
1860 ret = WERR_OK;
1864 return ret;
1868 /****************************************************************************
1869 ****************************************************************************/
1871 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1872 TALLOC_CTX *mem_ctx,
1873 int argc, const char **argv)
1875 WERROR result = WERR_OK;
1876 NTSTATUS status;
1877 int i;
1879 /* parse the command arguments */
1880 if (argc != 2) {
1881 printf ("Usage: %s <driver>\n", argv[0]);
1882 return WERR_OK;
1885 /* delete the driver for all architectures */
1886 for (i=0; archi_table[i].long_archi; i++) {
1887 /* make the call to remove the driver */
1888 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1889 cli->srv_name_slash,
1890 archi_table[i].long_archi,
1891 argv[1],
1892 &result);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 return result;
1896 if ( !W_ERROR_IS_OK(result) ) {
1897 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1898 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1899 argv[1], archi_table[i].long_archi,
1900 W_ERROR_V(result));
1902 } else {
1903 printf ("Driver %s removed for arch [%s].\n", argv[1],
1904 archi_table[i].long_archi);
1908 return result;
1911 /****************************************************************************
1912 ****************************************************************************/
1914 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1915 TALLOC_CTX *mem_ctx,
1916 int argc, const char **argv)
1918 WERROR result;
1919 NTSTATUS status;
1920 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1921 DATA_BLOB buffer;
1922 uint32_t offered;
1923 union spoolss_PrintProcessorDirectoryInfo info;
1924 uint32_t needed;
1926 /* parse the command arguments */
1927 if (argc > 2) {
1928 printf ("Usage: %s [environment]\n", argv[0]);
1929 return WERR_OK;
1932 if (argc == 2) {
1933 environment = argv[1];
1936 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1937 cli->srv_name_slash,
1938 environment,
1940 NULL, /* buffer */
1941 0, /* offered */
1942 NULL, /* info */
1943 &needed,
1944 &result);
1945 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1946 offered = needed;
1947 buffer = data_blob_talloc_zero(mem_ctx, needed);
1949 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1950 cli->srv_name_slash,
1951 environment,
1953 &buffer,
1954 offered,
1955 &info,
1956 &needed,
1957 &result);
1960 if (W_ERROR_IS_OK(result)) {
1961 printf("%s\n", info.info1.directory_name);
1964 return result;
1967 /****************************************************************************
1968 ****************************************************************************/
1970 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1971 int argc, const char **argv)
1973 struct policy_handle handle;
1974 WERROR werror;
1975 NTSTATUS status;
1976 const char *printername;
1977 union spoolss_AddFormInfo info;
1978 struct spoolss_AddFormInfo1 info1;
1979 struct spoolss_AddFormInfo2 info2;
1980 uint32_t level = 1;
1982 /* Parse the command arguments */
1984 if (argc < 3 || argc > 5) {
1985 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1986 return WERR_OK;
1989 /* Get a printer handle */
1991 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1993 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1994 printername,
1995 PRINTER_ALL_ACCESS,
1996 &handle);
1997 if (!W_ERROR_IS_OK(werror))
1998 goto done;
2000 /* Dummy up some values for the form data */
2002 if (argc == 4) {
2003 level = atoi(argv[3]);
2006 switch (level) {
2007 case 1:
2008 info1.flags = SPOOLSS_FORM_USER;
2009 info1.form_name = argv[2];
2010 info1.size.width = 100;
2011 info1.size.height = 100;
2012 info1.area.left = 0;
2013 info1.area.top = 10;
2014 info1.area.right = 20;
2015 info1.area.bottom = 30;
2017 info.info1 = &info1;
2019 break;
2020 case 2:
2021 info2.flags = SPOOLSS_FORM_USER;
2022 info2.form_name = argv[2];
2023 info2.size.width = 100;
2024 info2.size.height = 100;
2025 info2.area.left = 0;
2026 info2.area.top = 10;
2027 info2.area.right = 20;
2028 info2.area.bottom = 30;
2029 info2.keyword = argv[2];
2030 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2031 info2.mui_dll = NULL;
2032 info2.ressource_id = 0;
2033 info2.display_name = argv[2];
2034 info2.lang_id = 0;
2036 info.info2 = &info2;
2038 break;
2041 /* Add the form */
2044 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2045 &handle,
2046 level,
2047 info,
2048 &werror);
2050 done:
2051 if (is_valid_policy_hnd(&handle))
2052 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2054 return werror;
2057 /****************************************************************************
2058 ****************************************************************************/
2060 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2061 int argc, const char **argv)
2063 struct policy_handle handle;
2064 WERROR werror;
2065 NTSTATUS status;
2066 const char *printername;
2067 union spoolss_AddFormInfo info;
2068 struct spoolss_AddFormInfo1 info1;
2070 /* Parse the command arguments */
2072 if (argc != 3) {
2073 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2074 return WERR_OK;
2077 /* Get a printer handle */
2079 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2081 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2082 printername,
2083 SEC_FLAG_MAXIMUM_ALLOWED,
2084 &handle);
2085 if (!W_ERROR_IS_OK(werror))
2086 goto done;
2088 /* Dummy up some values for the form data */
2090 info1.flags = SPOOLSS_FORM_PRINTER;
2091 info1.size.width = 100;
2092 info1.size.height = 100;
2093 info1.area.left = 0;
2094 info1.area.top = 1000;
2095 info1.area.right = 2000;
2096 info1.area.bottom = 3000;
2097 info1.form_name = argv[2];
2099 info.info1 = &info1;
2101 /* Set the form */
2103 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2104 &handle,
2105 argv[2],
2107 info,
2108 &werror);
2110 done:
2111 if (is_valid_policy_hnd(&handle))
2112 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2114 return werror;
2117 /****************************************************************************
2118 ****************************************************************************/
2120 static const char *get_form_flag(int form_flag)
2122 switch (form_flag) {
2123 case SPOOLSS_FORM_USER:
2124 return "FORM_USER";
2125 case SPOOLSS_FORM_BUILTIN:
2126 return "FORM_BUILTIN";
2127 case SPOOLSS_FORM_PRINTER:
2128 return "FORM_PRINTER";
2129 default:
2130 return "unknown";
2134 /****************************************************************************
2135 ****************************************************************************/
2137 static void display_form_info1(struct spoolss_FormInfo1 *r)
2139 printf("%s\n" \
2140 "\tflag: %s (%d)\n" \
2141 "\twidth: %d, length: %d\n" \
2142 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2143 r->form_name, get_form_flag(r->flags), r->flags,
2144 r->size.width, r->size.height,
2145 r->area.left, r->area.right,
2146 r->area.top, r->area.bottom);
2149 /****************************************************************************
2150 ****************************************************************************/
2152 static void display_form_info2(struct spoolss_FormInfo2 *r)
2154 printf("%s\n" \
2155 "\tflag: %s (%d)\n" \
2156 "\twidth: %d, length: %d\n" \
2157 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2158 r->form_name, get_form_flag(r->flags), r->flags,
2159 r->size.width, r->size.height,
2160 r->area.left, r->area.right,
2161 r->area.top, r->area.bottom);
2162 printf("\tkeyword: %s\n", r->keyword);
2163 printf("\tstring_type: 0x%08x\n", r->string_type);
2164 printf("\tmui_dll: %s\n", r->mui_dll);
2165 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2166 printf("\tdisplay_name: %s\n", r->display_name);
2167 printf("\tlang_id: %d\n", r->lang_id);
2168 printf("\n");
2171 /****************************************************************************
2172 ****************************************************************************/
2174 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2175 int argc, const char **argv)
2177 struct policy_handle handle;
2178 WERROR werror;
2179 NTSTATUS status;
2180 const char *printername;
2181 DATA_BLOB buffer;
2182 uint32_t offered = 0;
2183 union spoolss_FormInfo info;
2184 uint32_t needed;
2185 uint32_t level = 1;
2187 /* Parse the command arguments */
2189 if (argc < 3 || argc > 5) {
2190 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2191 return WERR_OK;
2194 /* Get a printer handle */
2196 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2198 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2199 printername,
2200 SEC_FLAG_MAXIMUM_ALLOWED,
2201 &handle);
2202 if (!W_ERROR_IS_OK(werror))
2203 goto done;
2205 if (argc == 4) {
2206 level = atoi(argv[3]);
2209 /* Get the form */
2211 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2212 &handle,
2213 argv[2],
2214 level,
2215 NULL,
2216 offered,
2217 &info,
2218 &needed,
2219 &werror);
2220 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2221 buffer = data_blob_talloc_zero(mem_ctx, needed);
2222 offered = needed;
2223 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2224 &handle,
2225 argv[2],
2226 level,
2227 &buffer,
2228 offered,
2229 &info,
2230 &needed,
2231 &werror);
2234 if (!NT_STATUS_IS_OK(status)) {
2235 return werror;
2238 switch (level) {
2239 case 1:
2240 display_form_info1(&info.info1);
2241 break;
2242 case 2:
2243 display_form_info2(&info.info2);
2244 break;
2247 done:
2248 if (is_valid_policy_hnd(&handle))
2249 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2251 return werror;
2254 /****************************************************************************
2255 ****************************************************************************/
2257 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2258 TALLOC_CTX *mem_ctx, int argc,
2259 const char **argv)
2261 struct policy_handle handle;
2262 WERROR werror;
2263 NTSTATUS status;
2264 const char *printername;
2266 /* Parse the command arguments */
2268 if (argc != 3) {
2269 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2270 return WERR_OK;
2273 /* Get a printer handle */
2275 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2277 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2278 printername,
2279 SEC_FLAG_MAXIMUM_ALLOWED,
2280 &handle);
2281 if (!W_ERROR_IS_OK(werror))
2282 goto done;
2284 /* Delete the form */
2286 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2287 &handle,
2288 argv[2],
2289 &werror);
2290 if (!NT_STATUS_IS_OK(status)) {
2291 return ntstatus_to_werror(status);
2294 done:
2295 if (is_valid_policy_hnd(&handle))
2296 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2298 return werror;
2301 /****************************************************************************
2302 ****************************************************************************/
2304 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2305 TALLOC_CTX *mem_ctx, int argc,
2306 const char **argv)
2308 struct policy_handle handle;
2309 WERROR werror;
2310 const char *printername;
2311 uint32_t num_forms, level = 1, i;
2312 union spoolss_FormInfo *forms;
2314 /* Parse the command arguments */
2316 if (argc < 2 || argc > 4) {
2317 printf ("Usage: %s <printer> [level]\n", argv[0]);
2318 return WERR_OK;
2321 /* Get a printer handle */
2323 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2325 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2326 printername,
2327 SEC_FLAG_MAXIMUM_ALLOWED,
2328 &handle);
2329 if (!W_ERROR_IS_OK(werror))
2330 goto done;
2332 if (argc == 3) {
2333 level = atoi(argv[2]);
2336 /* Enumerate forms */
2338 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2339 &handle,
2340 level,
2342 &num_forms,
2343 &forms);
2345 if (!W_ERROR_IS_OK(werror))
2346 goto done;
2348 /* Display output */
2350 for (i = 0; i < num_forms; i++) {
2351 switch (level) {
2352 case 1:
2353 display_form_info1(&forms[i].info1);
2354 break;
2355 case 2:
2356 display_form_info2(&forms[i].info2);
2357 break;
2361 done:
2362 if (is_valid_policy_hnd(&handle))
2363 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2365 return werror;
2368 /****************************************************************************
2369 ****************************************************************************/
2371 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2372 TALLOC_CTX *mem_ctx,
2373 int argc, const char **argv)
2375 WERROR result;
2376 NTSTATUS status;
2377 const char *printername;
2378 struct policy_handle pol;
2379 union spoolss_PrinterInfo info;
2380 enum winreg_Type type;
2381 union spoolss_PrinterData data;
2383 /* parse the command arguments */
2384 if (argc < 5) {
2385 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2386 " <value> <data>\n",
2387 argv[0]);
2388 result = WERR_INVALID_PARAM;
2389 goto done;
2392 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2394 type = REG_NONE;
2396 if (strequal(argv[2], "string")) {
2397 type = REG_SZ;
2400 if (strequal(argv[2], "binary")) {
2401 type = REG_BINARY;
2404 if (strequal(argv[2], "dword")) {
2405 type = REG_DWORD;
2408 if (strequal(argv[2], "multistring")) {
2409 type = REG_MULTI_SZ;
2412 if (type == REG_NONE) {
2413 printf("Unknown data type: %s\n", argv[2]);
2414 result = WERR_INVALID_PARAM;
2415 goto done;
2418 /* get a printer handle */
2420 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2421 printername,
2422 SEC_FLAG_MAXIMUM_ALLOWED,
2423 &pol);
2424 if (!W_ERROR_IS_OK(result)) {
2425 goto done;
2428 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2429 &pol,
2432 &info);
2433 if (!W_ERROR_IS_OK(result)) {
2434 goto done;
2437 printf("%s\n", current_timestring(mem_ctx, true));
2438 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2440 /* Set the printer data */
2442 switch (type) {
2443 case REG_SZ:
2444 data.string = talloc_strdup(mem_ctx, argv[4]);
2445 W_ERROR_HAVE_NO_MEMORY(data.string);
2446 break;
2447 case REG_DWORD:
2448 data.value = strtoul(argv[4], NULL, 10);
2449 break;
2450 case REG_BINARY:
2451 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2452 break;
2453 case REG_MULTI_SZ: {
2454 int i, num_strings;
2455 const char **strings = NULL;
2457 for (i=4; i<argc; i++) {
2458 if (strcmp(argv[i], "NULL") == 0) {
2459 argv[i] = "";
2461 if (!add_string_to_array(mem_ctx, argv[i],
2462 &strings,
2463 &num_strings)) {
2464 result = WERR_NOMEM;
2465 goto done;
2468 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2469 if (!data.string_array) {
2470 result = WERR_NOMEM;
2471 goto done;
2473 for (i=0; i < num_strings; i++) {
2474 data.string_array[i] = strings[i];
2476 break;
2478 default:
2479 printf("Unknown data type: %s\n", argv[2]);
2480 result = WERR_INVALID_PARAM;
2481 goto done;
2484 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2485 &pol,
2486 argv[3], /* value_name */
2487 type,
2488 data,
2489 0, /* autocalculated size */
2490 &result);
2491 if (!W_ERROR_IS_OK(result)) {
2492 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2493 goto done;
2495 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2497 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2498 &pol,
2501 &info);
2502 if (!W_ERROR_IS_OK(result)) {
2503 goto done;
2506 printf("%s\n", current_timestring(mem_ctx, true));
2507 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2509 done:
2510 /* cleanup */
2511 if (is_valid_policy_hnd(&pol)) {
2512 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2515 return result;
2518 /****************************************************************************
2519 ****************************************************************************/
2521 static void display_job_info1(struct spoolss_JobInfo1 *r)
2523 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2524 r->user_name, r->document_name, r->text_status, r->pages_printed,
2525 r->total_pages);
2528 /****************************************************************************
2529 ****************************************************************************/
2531 static void display_job_info2(struct spoolss_JobInfo2 *r)
2533 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2534 r->position, r->job_id,
2535 r->user_name, r->document_name, r->text_status, r->pages_printed,
2536 r->total_pages, r->size);
2539 /****************************************************************************
2540 ****************************************************************************/
2542 static void display_job_info3(struct spoolss_JobInfo3 *r)
2544 printf("jobid[%d], next_jobid[%d]\n",
2545 r->job_id, r->next_job_id);
2548 /****************************************************************************
2549 ****************************************************************************/
2551 static void display_job_info4(struct spoolss_JobInfo4 *r)
2553 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2554 r->position, r->job_id,
2555 r->user_name, r->document_name, r->text_status, r->pages_printed,
2556 r->total_pages, r->size, r->size_high);
2559 /****************************************************************************
2560 ****************************************************************************/
2562 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2563 TALLOC_CTX *mem_ctx, int argc,
2564 const char **argv)
2566 WERROR result;
2567 uint32_t level = 1, count, i;
2568 const char *printername;
2569 struct policy_handle hnd;
2570 union spoolss_JobInfo *info;
2572 if (argc < 2 || argc > 3) {
2573 printf("Usage: %s printername [level]\n", argv[0]);
2574 return WERR_OK;
2577 if (argc == 3) {
2578 level = atoi(argv[2]);
2581 /* Open printer handle */
2583 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2585 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2586 printername,
2587 SEC_FLAG_MAXIMUM_ALLOWED,
2588 &hnd);
2589 if (!W_ERROR_IS_OK(result))
2590 goto done;
2592 /* Enumerate ports */
2594 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2595 &hnd,
2596 0, /* firstjob */
2597 1000, /* numjobs */
2598 level,
2600 &count,
2601 &info);
2602 if (!W_ERROR_IS_OK(result)) {
2603 goto done;
2606 for (i = 0; i < count; i++) {
2607 switch (level) {
2608 case 1:
2609 display_job_info1(&info[i].info1);
2610 break;
2611 case 2:
2612 display_job_info2(&info[i].info2);
2613 break;
2614 default:
2615 d_printf("unknown info level %d\n", level);
2616 break;
2620 done:
2621 if (is_valid_policy_hnd(&hnd)) {
2622 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2625 return result;
2628 /****************************************************************************
2629 ****************************************************************************/
2631 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2632 TALLOC_CTX *mem_ctx, int argc,
2633 const char **argv)
2635 WERROR result;
2636 const char *printername;
2637 struct policy_handle hnd;
2638 uint32_t job_id;
2639 uint32_t level = 1;
2640 union spoolss_JobInfo info;
2642 if (argc < 3 || argc > 4) {
2643 printf("Usage: %s printername job_id [level]\n", argv[0]);
2644 return WERR_OK;
2647 job_id = atoi(argv[2]);
2649 if (argc == 4) {
2650 level = atoi(argv[3]);
2653 /* Open printer handle */
2655 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2657 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2658 printername,
2659 SEC_FLAG_MAXIMUM_ALLOWED,
2660 &hnd);
2661 if (!W_ERROR_IS_OK(result)) {
2662 goto done;
2665 /* Enumerate ports */
2667 result = rpccli_spoolss_getjob(cli, mem_ctx,
2668 &hnd,
2669 job_id,
2670 level,
2672 &info);
2674 if (!W_ERROR_IS_OK(result)) {
2675 goto done;
2678 switch (level) {
2679 case 1:
2680 display_job_info1(&info.info1);
2681 break;
2682 case 2:
2683 display_job_info2(&info.info2);
2684 break;
2685 case 3:
2686 display_job_info3(&info.info3);
2687 break;
2688 case 4:
2689 display_job_info4(&info.info4);
2690 break;
2691 default:
2692 d_printf("unknown info level %d\n", level);
2693 break;
2696 done:
2697 if (is_valid_policy_hnd(&hnd)) {
2698 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2701 return result;
2704 /****************************************************************************
2705 ****************************************************************************/
2707 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2708 TALLOC_CTX *mem_ctx, int argc,
2709 const char **argv)
2711 WERROR result;
2712 NTSTATUS status;
2713 const char *printername;
2714 struct policy_handle hnd;
2715 uint32_t job_id;
2716 enum spoolss_JobControl command;
2718 if (argc != 4) {
2719 printf("Usage: %s printername job_id command\n", argv[0]);
2720 return WERR_OK;
2723 job_id = atoi(argv[2]);
2724 command = atoi(argv[3]);
2726 /* Open printer handle */
2728 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2730 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2731 printername,
2732 SEC_FLAG_MAXIMUM_ALLOWED,
2733 &hnd);
2734 if (!W_ERROR_IS_OK(result)) {
2735 goto done;
2738 /* Set Job */
2740 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2741 &hnd,
2742 job_id,
2743 NULL,
2744 command,
2745 &result);
2747 if (!W_ERROR_IS_OK(result)) {
2748 goto done;
2751 done:
2752 if (is_valid_policy_hnd(&hnd)) {
2753 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2756 return result;
2759 /****************************************************************************
2760 ****************************************************************************/
2762 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2763 TALLOC_CTX *mem_ctx, int argc,
2764 const char **argv)
2766 WERROR result;
2767 NTSTATUS status;
2768 uint32_t i = 0;
2769 const char *printername;
2770 struct policy_handle hnd;
2771 uint32_t value_offered = 0;
2772 const char *value_name = NULL;
2773 uint32_t value_needed;
2774 enum winreg_Type type;
2775 uint8_t *data = NULL;
2776 uint32_t data_offered = 0;
2777 uint32_t data_needed;
2779 if (argc != 2) {
2780 printf("Usage: %s printername\n", argv[0]);
2781 return WERR_OK;
2784 /* Open printer handle */
2786 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2788 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2789 printername,
2790 SEC_FLAG_MAXIMUM_ALLOWED,
2791 &hnd);
2792 if (!W_ERROR_IS_OK(result)) {
2793 goto done;
2796 /* Enumerate data */
2798 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2799 &hnd,
2801 value_name,
2802 value_offered,
2803 &value_needed,
2804 &type,
2805 data,
2806 data_offered,
2807 &data_needed,
2808 &result);
2810 data_offered = data_needed;
2811 value_offered = value_needed;
2812 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2813 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2815 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2817 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2818 &hnd,
2819 i++,
2820 value_name,
2821 value_offered,
2822 &value_needed,
2823 &type,
2824 data,
2825 data_offered,
2826 &data_needed,
2827 &result);
2828 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2829 struct regval_blob v;
2830 fstrcpy(v.valuename, value_name);
2831 v.type = type;
2832 v.size = data_offered;
2833 v.data_p = data;
2834 display_reg_value(v);
2838 if (W_ERROR_V(result) == ERRnomoreitems) {
2839 result = W_ERROR(ERRsuccess);
2842 done:
2843 if (is_valid_policy_hnd(&hnd)) {
2844 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2847 return result;
2850 /****************************************************************************
2851 ****************************************************************************/
2853 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2854 TALLOC_CTX *mem_ctx, int argc,
2855 const char **argv)
2857 WERROR result;
2858 uint32_t i;
2859 const char *printername;
2860 struct policy_handle hnd;
2861 uint32_t count;
2862 struct spoolss_PrinterEnumValues *info;
2864 if (argc != 3) {
2865 printf("Usage: %s printername <keyname>\n", argv[0]);
2866 return WERR_OK;
2869 /* Open printer handle */
2871 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2873 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2874 printername,
2875 SEC_FLAG_MAXIMUM_ALLOWED,
2876 &hnd);
2877 if (!W_ERROR_IS_OK(result)) {
2878 goto done;
2881 /* Enumerate subkeys */
2883 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2884 &hnd,
2885 argv[2],
2887 &count,
2888 &info);
2889 if (!W_ERROR_IS_OK(result)) {
2890 goto done;
2893 for (i=0; i < count; i++) {
2894 display_printer_data(info[i].value_name,
2895 info[i].type,
2896 info[i].data);
2899 done:
2900 if (is_valid_policy_hnd(&hnd)) {
2901 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2904 return result;
2907 /****************************************************************************
2908 ****************************************************************************/
2910 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2911 TALLOC_CTX *mem_ctx, int argc,
2912 const char **argv)
2914 WERROR result;
2915 const char *printername;
2916 const char *keyname = NULL;
2917 struct policy_handle hnd;
2918 const char **key_buffer = NULL;
2919 int i;
2921 if (argc < 2 || argc > 3) {
2922 printf("Usage: %s printername [keyname]\n", argv[0]);
2923 return WERR_OK;
2926 if (argc == 3) {
2927 keyname = argv[2];
2928 } else {
2929 keyname = "";
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,
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 }