LDB:TDB backend - change counter variables to "unsigned" where appropriate
[Samba/cd1.git] / source3 / rpcclient / cmd_spoolss.c
blobecbc341b1627639e79f083f7499a894fa9c65eab
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 uint8_t *data,
753 uint32_t length)
755 int i;
756 union spoolss_PrinterData r;
757 DATA_BLOB blob = data_blob_const(data, length);
758 WERROR result;
760 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
761 if (!W_ERROR_IS_OK(result)) {
762 return;
765 switch (type) {
766 case REG_DWORD:
767 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
768 break;
769 case REG_SZ:
770 printf("%s: REG_SZ: %s\n", v, r.string);
771 break;
772 case REG_BINARY: {
773 char *hex = hex_encode_talloc(NULL,
774 r.binary.data, r.binary.length);
775 size_t len;
776 printf("%s: REG_BINARY:", v);
777 len = strlen(hex);
778 for (i=0; i<len; i++) {
779 if (hex[i] == '\0') {
780 break;
782 if (i%40 == 0) {
783 putchar('\n');
785 putchar(hex[i]);
787 TALLOC_FREE(hex);
788 putchar('\n');
789 break;
791 case REG_MULTI_SZ:
792 printf("%s: REG_MULTI_SZ: ", v);
793 for (i=0; r.string_array[i] != NULL; i++) {
794 printf("%s ", r.string_array[i]);
796 printf("\n");
797 break;
798 default:
799 printf("%s: unknown type 0x%02x:\n", v, type);
800 break;
804 /****************************************************************************
805 ****************************************************************************/
807 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
808 TALLOC_CTX *mem_ctx,
809 int argc, const char **argv)
811 struct policy_handle pol;
812 WERROR result;
813 fstring printername;
814 const char *valuename;
815 enum winreg_Type type;
816 uint8_t *data;
817 uint32_t needed;
819 if (argc != 3) {
820 printf("Usage: %s <printername> <valuename>\n", argv[0]);
821 printf("<printername> of . queries print server\n");
822 return WERR_OK;
824 valuename = argv[2];
826 /* Open a printer handle */
828 if (strncmp(argv[1], ".", sizeof(".")) == 0)
829 fstrcpy(printername, cli->srv_name_slash);
830 else
831 slprintf(printername, sizeof(printername)-1, "%s\\%s",
832 cli->srv_name_slash, argv[1]);
834 /* get a printer handle */
836 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
837 printername,
838 SEC_FLAG_MAXIMUM_ALLOWED,
839 &pol);
840 if (!W_ERROR_IS_OK(result))
841 goto done;
843 /* Get printer info */
845 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
846 &pol,
847 valuename,
849 &type,
850 &needed,
851 &data);
852 if (!W_ERROR_IS_OK(result))
853 goto done;
855 /* Display printer data */
857 display_printer_data(valuename, type, data, needed);
859 done:
860 if (is_valid_policy_hnd(&pol))
861 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
863 return result;
866 /****************************************************************************
867 ****************************************************************************/
869 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
870 TALLOC_CTX *mem_ctx,
871 int argc, const char **argv)
873 struct policy_handle pol;
874 WERROR result;
875 NTSTATUS status;
876 fstring printername;
877 const char *valuename, *keyname;
879 enum winreg_Type type;
880 uint8_t *data = NULL;
881 uint32_t offered = 0;
882 uint32_t needed;
884 if (argc != 4) {
885 printf("Usage: %s <printername> <keyname> <valuename>\n",
886 argv[0]);
887 printf("<printername> of . queries print server\n");
888 return WERR_OK;
890 valuename = argv[3];
891 keyname = argv[2];
893 /* Open a printer handle */
895 if (strncmp(argv[1], ".", sizeof(".")) == 0)
896 fstrcpy(printername, cli->srv_name_slash);
897 else
898 slprintf(printername, sizeof(printername)-1, "%s\\%s",
899 cli->srv_name_slash, argv[1]);
901 /* get a printer handle */
903 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
904 printername,
905 SEC_FLAG_MAXIMUM_ALLOWED,
906 &pol);
907 if (!W_ERROR_IS_OK(result))
908 goto done;
910 /* Get printer info */
912 data = talloc_zero_array(mem_ctx, uint8_t, offered);
913 if (!data) {
914 goto done;
917 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
918 &pol,
919 keyname,
920 valuename,
921 &type,
922 data,
923 offered,
924 &needed,
925 &result);
926 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
927 offered = needed;
928 data = talloc_zero_array(mem_ctx, uint8_t, offered);
929 if (!data) {
930 goto done;
932 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
933 &pol,
934 keyname,
935 valuename,
936 &type,
937 data,
938 offered,
939 &needed,
940 &result);
943 if (!NT_STATUS_IS_OK(status)) {
944 goto done;
947 if (!W_ERROR_IS_OK(result))
948 goto done;
950 /* Display printer data */
952 display_printer_data(valuename, type, data, needed);
955 done:
956 if (is_valid_policy_hnd(&pol))
957 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
959 return result;
962 /****************************************************************************
963 ****************************************************************************/
965 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
967 if (!r) {
968 return;
971 printf("Printer Driver Info 1:\n");
972 printf("\tDriver Name: [%s]\n", r->driver_name);
973 printf("\n");
976 /****************************************************************************
977 ****************************************************************************/
979 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
981 if (!r) {
982 return;
985 printf("Printer Driver Info 2:\n");
986 printf("\tVersion: [%x]\n", r->version);
987 printf("\tDriver Name: [%s]\n", r->driver_name);
988 printf("\tArchitecture: [%s]\n", r->architecture);
989 printf("\tDriver Path: [%s]\n", r->driver_path);
990 printf("\tDatafile: [%s]\n", r->data_file);
991 printf("\tConfigfile: [%s]\n", r->config_file);
992 printf("\n");
995 /****************************************************************************
996 ****************************************************************************/
998 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1000 int i;
1002 if (!r) {
1003 return;
1006 printf("Printer Driver Info 3:\n");
1007 printf("\tVersion: [%x]\n", r->version);
1008 printf("\tDriver Name: [%s]\n", r->driver_name);
1009 printf("\tArchitecture: [%s]\n", r->architecture);
1010 printf("\tDriver Path: [%s]\n", r->driver_path);
1011 printf("\tDatafile: [%s]\n", r->data_file);
1012 printf("\tConfigfile: [%s]\n", r->config_file);
1013 printf("\tHelpfile: [%s]\n", r->help_file);
1015 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1016 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1019 printf("\tMonitorname: [%s]\n", r->monitor_name);
1020 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1021 printf("\n");
1024 /****************************************************************************
1025 ****************************************************************************/
1027 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1029 int i;
1031 if (!r) {
1032 return;
1035 printf("Printer Driver Info 4:\n");
1036 printf("\tVersion: [%x]\n", r->version);
1037 printf("\tDriver Name: [%s]\n", r->driver_name);
1038 printf("\tArchitecture: [%s]\n", r->architecture);
1039 printf("\tDriver Path: [%s]\n", r->driver_path);
1040 printf("\tDatafile: [%s]\n", r->data_file);
1041 printf("\tConfigfile: [%s]\n", r->config_file);
1042 printf("\tHelpfile: [%s]\n", r->help_file);
1044 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1045 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1048 printf("\tMonitorname: [%s]\n", r->monitor_name);
1049 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1051 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1052 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1054 printf("\n");
1057 /****************************************************************************
1058 ****************************************************************************/
1060 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1062 if (!r) {
1063 return;
1066 printf("Printer Driver Info 5:\n");
1067 printf("\tVersion: [%x]\n", r->version);
1068 printf("\tDriver Name: [%s]\n", r->driver_name);
1069 printf("\tArchitecture: [%s]\n", r->architecture);
1070 printf("\tDriver Path: [%s]\n", r->driver_path);
1071 printf("\tDatafile: [%s]\n", r->data_file);
1072 printf("\tConfigfile: [%s]\n", r->config_file);
1073 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1074 printf("\tConfig Version: [0x%x]\n", r->config_version);
1075 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1076 printf("\n");
1079 /****************************************************************************
1080 ****************************************************************************/
1082 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1084 int i;
1086 if (!r) {
1087 return;
1090 printf("Printer Driver Info 6:\n");
1091 printf("\tVersion: [%x]\n", r->version);
1092 printf("\tDriver Name: [%s]\n", r->driver_name);
1093 printf("\tArchitecture: [%s]\n", r->architecture);
1094 printf("\tDriver Path: [%s]\n", r->driver_path);
1095 printf("\tDatafile: [%s]\n", r->data_file);
1096 printf("\tConfigfile: [%s]\n", r->config_file);
1097 printf("\tHelpfile: [%s]\n", r->help_file);
1099 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1100 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1103 printf("\tMonitorname: [%s]\n", r->monitor_name);
1104 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1106 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1107 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1110 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1111 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1112 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1113 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1114 printf("\tHardware ID: [%s]\n", r->hardware_id);
1115 printf("\tProvider: [%s]\n", r->provider);
1117 printf("\n");
1120 /****************************************************************************
1121 ****************************************************************************/
1123 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1125 int i;
1127 if (!r) {
1128 return;
1131 printf("Printer Driver Info 8:\n");
1132 printf("\tVersion: [%x]\n", r->version);
1133 printf("\tDriver Name: [%s]\n", r->driver_name);
1134 printf("\tArchitecture: [%s]\n", r->architecture);
1135 printf("\tDriver Path: [%s]\n", r->driver_path);
1136 printf("\tDatafile: [%s]\n", r->data_file);
1137 printf("\tConfigfile: [%s]\n", r->config_file);
1138 printf("\tHelpfile: [%s]\n", r->help_file);
1139 printf("\tMonitorname: [%s]\n", r->monitor_name);
1140 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1142 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1143 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1146 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1147 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1150 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1151 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1152 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1153 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1154 printf("\tHardware ID: [%s]\n", r->hardware_id);
1155 printf("\tProvider: [%s]\n", r->provider);
1156 printf("\tPrint Processor: [%s]\n", r->print_processor);
1157 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1158 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1159 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1161 printf("\tInf Path: [%s]\n", r->inf_path);
1162 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1163 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1164 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1166 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1167 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1168 (long long unsigned int)r->min_inbox_driver_ver_version);
1170 printf("\n");
1173 /****************************************************************************
1174 ****************************************************************************/
1176 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1177 TALLOC_CTX *mem_ctx,
1178 int argc, const char **argv)
1180 struct policy_handle pol;
1181 WERROR werror;
1182 uint32_t level = 3;
1183 const char *printername;
1184 uint32_t i;
1185 bool success = false;
1186 union spoolss_DriverInfo info;
1187 uint32_t server_major_version;
1188 uint32_t server_minor_version;
1190 if ((argc == 1) || (argc > 3)) {
1191 printf("Usage: %s <printername> [level]\n", argv[0]);
1192 return WERR_OK;
1195 /* get the arguments need to open the printer handle */
1197 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1199 if (argc == 3) {
1200 level = atoi(argv[2]);
1203 /* Open a printer handle */
1205 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1206 printername,
1207 PRINTER_ACCESS_USE,
1208 &pol);
1209 if (!W_ERROR_IS_OK(werror)) {
1210 printf("Error opening printer handle for %s!\n", printername);
1211 return werror;
1214 /* loop through and print driver info level for each architecture */
1216 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1218 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1219 &pol,
1220 archi_table[i].long_archi,
1221 level,
1222 0, /* offered */
1223 archi_table[i].version,
1225 &info,
1226 &server_major_version,
1227 &server_minor_version);
1228 if (!W_ERROR_IS_OK(werror)) {
1229 continue;
1232 /* need at least one success */
1234 success = true;
1236 printf("\n[%s]\n", archi_table[i].long_archi);
1238 switch (level) {
1239 case 1:
1240 display_print_driver1(&info.info1);
1241 break;
1242 case 2:
1243 display_print_driver2(&info.info2);
1244 break;
1245 case 3:
1246 display_print_driver3(&info.info3);
1247 break;
1248 case 4:
1249 display_print_driver4(&info.info4);
1250 break;
1251 case 5:
1252 display_print_driver5(&info.info5);
1253 break;
1254 case 6:
1255 display_print_driver6(&info.info6);
1256 break;
1257 case 8:
1258 display_print_driver8(&info.info8);
1259 break;
1260 default:
1261 printf("unknown info level %d\n", level);
1262 break;
1266 /* Cleanup */
1268 if (is_valid_policy_hnd(&pol)) {
1269 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1272 if (success) {
1273 werror = WERR_OK;
1276 return werror;
1279 /****************************************************************************
1280 ****************************************************************************/
1282 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1283 TALLOC_CTX *mem_ctx,
1284 const char *architecture,
1285 uint32_t level)
1287 WERROR werror;
1288 uint32_t count = 0;
1289 union spoolss_DriverInfo *info = NULL;
1290 uint32_t j;
1292 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1293 cli->srv_name_slash,
1294 architecture,
1295 level,
1297 &count,
1298 &info);
1300 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1301 printf("Server does not support environment [%s]\n",
1302 architecture);
1303 return WERR_OK;
1306 if (count == 0) {
1307 return WERR_OK;
1310 if (!W_ERROR_IS_OK(werror)) {
1311 printf("Error getting driver for environment [%s] - %s\n",
1312 architecture, win_errstr(werror));
1313 return werror;
1316 printf("\n[%s]\n", architecture);
1318 switch (level) {
1319 case 1:
1320 for (j=0; j < count; j++) {
1321 display_print_driver1(&info[j].info1);
1323 break;
1324 case 2:
1325 for (j=0; j < count; j++) {
1326 display_print_driver2(&info[j].info2);
1328 break;
1329 case 3:
1330 for (j=0; j < count; j++) {
1331 display_print_driver3(&info[j].info3);
1333 break;
1334 case 4:
1335 for (j=0; j < count; j++) {
1336 display_print_driver4(&info[j].info4);
1338 break;
1339 case 5:
1340 for (j=0; j < count; j++) {
1341 display_print_driver5(&info[j].info5);
1343 break;
1344 case 6:
1345 for (j=0; j < count; j++) {
1346 display_print_driver6(&info[j].info6);
1348 break;
1349 case 8:
1350 for (j=0; j < count; j++) {
1351 display_print_driver8(&info[j].info8);
1353 break;
1354 default:
1355 printf("unknown info level %d\n", level);
1356 return WERR_UNKNOWN_LEVEL;
1359 return werror;
1362 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1363 TALLOC_CTX *mem_ctx,
1364 int argc, const char **argv)
1366 WERROR werror = WERR_OK;
1367 uint32_t level = 1;
1368 uint32_t i;
1369 const char *architecture = NULL;
1371 if (argc > 3) {
1372 printf("Usage: enumdrivers [level] [architecture]\n");
1373 return WERR_OK;
1376 if (argc >= 2) {
1377 level = atoi(argv[1]);
1380 if (argc == 3) {
1381 architecture = argv[2];
1384 if (architecture) {
1385 return enum_driver_by_architecture(cli, mem_ctx,
1386 architecture,
1387 level);
1390 /* loop through and print driver info level for each architecture */
1391 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1392 /* check to see if we already asked for this architecture string */
1394 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1395 continue;
1398 werror = enum_driver_by_architecture(cli, mem_ctx,
1399 archi_table[i].long_archi,
1400 level);
1401 if (!W_ERROR_IS_OK(werror)) {
1402 break;
1406 return werror;
1409 /****************************************************************************
1410 ****************************************************************************/
1412 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1414 printf("\tDirectory Name:[%s]\n", r->directory_name);
1417 /****************************************************************************
1418 ****************************************************************************/
1420 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1421 TALLOC_CTX *mem_ctx,
1422 int argc, const char **argv)
1424 WERROR result;
1425 NTSTATUS status;
1426 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1427 DATA_BLOB buffer;
1428 uint32_t offered;
1429 union spoolss_DriverDirectoryInfo info;
1430 uint32_t needed;
1432 if (argc > 2) {
1433 printf("Usage: %s [environment]\n", argv[0]);
1434 return WERR_OK;
1437 /* Get the arguments need to open the printer handle */
1439 if (argc == 2) {
1440 env = argv[1];
1443 /* Get the directory. Only use Info level 1 */
1445 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1446 cli->srv_name_slash,
1447 env,
1449 NULL, /* buffer */
1450 0, /* offered */
1451 NULL, /* info */
1452 &needed,
1453 &result);
1454 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1455 offered = needed;
1456 buffer = data_blob_talloc_zero(mem_ctx, needed);
1458 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1459 cli->srv_name_slash,
1460 env,
1462 &buffer,
1463 offered,
1464 &info,
1465 &needed,
1466 &result);
1469 if (W_ERROR_IS_OK(result)) {
1470 display_printdriverdir_1(&info.info1);
1473 return result;
1476 /****************************************************************************
1477 ****************************************************************************/
1479 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1480 struct spoolss_AddDriverInfo3 *info,
1481 const char *arch)
1484 int i;
1486 for (i=0; archi_table[i].long_archi != NULL; i++)
1488 if (strcmp(arch, archi_table[i].short_archi) == 0)
1490 info->version = archi_table[i].version;
1491 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1492 break;
1496 if (archi_table[i].long_archi == NULL)
1498 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1501 return;
1505 /**************************************************************************
1506 wrapper for strtok to get the next parameter from a delimited list.
1507 Needed to handle the empty parameter string denoted by "NULL"
1508 *************************************************************************/
1510 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1511 const char *delim, const char **dest,
1512 char **saveptr)
1514 char *ptr;
1516 /* get the next token */
1517 ptr = strtok_r(str, delim, saveptr);
1519 /* a string of 'NULL' is used to represent an empty
1520 parameter because two consecutive delimiters
1521 will not return an empty string. See man strtok(3)
1522 for details */
1523 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1524 ptr = NULL;
1527 if (dest != NULL) {
1528 *dest = talloc_strdup(mem_ctx, ptr);
1531 return ptr;
1534 /********************************************************************************
1535 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1536 string in the form of
1537 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1538 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1539 <Default Data Type>:<Comma Separated list of Files>
1540 *******************************************************************************/
1542 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1543 char *args)
1545 char *str, *str2;
1546 int count = 0;
1547 char *saveptr = NULL;
1548 struct spoolss_StringArray *deps;
1549 const char **file_array = NULL;
1550 int i;
1552 /* fill in the UNISTR fields */
1553 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1554 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1555 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1556 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1557 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1558 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1559 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1561 /* <Comma Separated List of Dependent Files> */
1562 /* save the beginning of the string */
1563 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1564 str = str2;
1566 /* begin to strip out each filename */
1567 str = strtok_r(str, ",", &saveptr);
1569 /* no dependent files, we are done */
1570 if (!str) {
1571 return true;
1574 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1575 if (!deps) {
1576 return false;
1579 while (str != NULL) {
1580 add_string_to_array(deps, str, &file_array, &count);
1581 str = strtok_r(NULL, ",", &saveptr);
1584 deps->string = talloc_zero_array(deps, const char *, count + 1);
1585 if (!deps->string) {
1586 return false;
1589 for (i=0; i < count; i++) {
1590 deps->string[i] = file_array[i];
1593 r->dependent_files = deps;
1595 return true;
1598 /****************************************************************************
1599 ****************************************************************************/
1601 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1602 TALLOC_CTX *mem_ctx,
1603 int argc, const char **argv)
1605 WERROR result;
1606 NTSTATUS status;
1607 uint32_t level = 3;
1608 struct spoolss_AddDriverInfoCtr info_ctr;
1609 struct spoolss_AddDriverInfo3 info3;
1610 const char *arch;
1611 char *driver_args;
1613 /* parse the command arguments */
1614 if (argc != 3 && argc != 4)
1616 printf ("Usage: %s <Environment> \\\n", argv[0]);
1617 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1618 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1619 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1620 printf ("\t[version]\n");
1622 return WERR_OK;
1625 /* Fill in the spoolss_AddDriverInfo3 struct */
1626 ZERO_STRUCT(info3);
1628 arch = cmd_spoolss_get_short_archi(argv[1]);
1629 if (!arch) {
1630 printf ("Error Unknown architechture [%s]\n", argv[1]);
1631 return WERR_INVALID_PARAM;
1634 set_drv_info_3_env(mem_ctx, &info3, arch);
1636 driver_args = talloc_strdup( mem_ctx, argv[2] );
1637 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1639 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1640 return WERR_INVALID_PARAM;
1643 /* if printer driver version specified, override the default version
1644 * used by the architecture. This allows installation of Windows
1645 * 2000 (version 3) printer drivers. */
1646 if (argc == 4)
1648 info3.version = atoi(argv[3]);
1652 info_ctr.level = level;
1653 info_ctr.info.info3 = &info3;
1655 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1656 cli->srv_name_slash,
1657 &info_ctr,
1658 &result);
1659 if (!NT_STATUS_IS_OK(status)) {
1660 return ntstatus_to_werror(status);
1662 if (W_ERROR_IS_OK(result)) {
1663 printf ("Printer Driver %s successfully installed.\n",
1664 info3.driver_name);
1667 return result;
1671 /****************************************************************************
1672 ****************************************************************************/
1674 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1675 TALLOC_CTX *mem_ctx,
1676 int argc, const char **argv)
1678 WERROR result;
1679 struct spoolss_SetPrinterInfoCtr info_ctr;
1680 struct spoolss_SetPrinterInfo2 info2;
1682 /* parse the command arguments */
1683 if (argc != 5)
1685 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1686 return WERR_OK;
1689 /* Fill in the DRIVER_INFO_2 struct */
1690 ZERO_STRUCT(info2);
1692 info2.printername = argv[1];
1693 info2.drivername = argv[3];
1694 info2.sharename = argv[2];
1695 info2.portname = argv[4];
1696 info2.comment = "Created by rpcclient";
1697 info2.printprocessor = "winprint";
1698 info2.datatype = "RAW";
1699 info2.devmode_ptr = 0;
1700 info2.secdesc_ptr = 0;
1701 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1702 info2.priority = 0;
1703 info2.defaultpriority = 0;
1704 info2.starttime = 0;
1705 info2.untiltime = 0;
1707 /* These three fields must not be used by AddPrinter()
1708 as defined in the MS Platform SDK documentation..
1709 --jerry
1710 info2.status = 0;
1711 info2.cjobs = 0;
1712 info2.averageppm = 0;
1715 info_ctr.level = 2;
1716 info_ctr.info.info2 = &info2;
1718 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1719 &info_ctr);
1720 if (W_ERROR_IS_OK(result))
1721 printf ("Printer %s successfully installed.\n", argv[1]);
1723 return result;
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1730 TALLOC_CTX *mem_ctx,
1731 int argc, const char **argv)
1733 struct policy_handle pol;
1734 WERROR result;
1735 NTSTATUS status;
1736 uint32_t level = 2;
1737 const char *printername;
1738 union spoolss_PrinterInfo info;
1739 struct spoolss_SetPrinterInfoCtr info_ctr;
1740 struct spoolss_DevmodeContainer devmode_ctr;
1741 struct sec_desc_buf secdesc_ctr;
1743 ZERO_STRUCT(devmode_ctr);
1744 ZERO_STRUCT(secdesc_ctr);
1746 /* parse the command arguments */
1747 if (argc != 3)
1749 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1750 return WERR_OK;
1753 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1755 /* Get a printer handle */
1757 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1758 printername,
1759 PRINTER_ALL_ACCESS,
1760 &pol);
1761 if (!W_ERROR_IS_OK(result))
1762 goto done;
1764 /* Get printer info */
1766 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1767 &pol,
1768 level,
1770 &info);
1771 if (!W_ERROR_IS_OK(result)) {
1772 printf ("Unable to retrieve printer information!\n");
1773 goto done;
1776 /* Set the printer driver */
1778 info.info2.drivername = argv[2];
1779 info.info2.devmode = NULL;
1780 info.info2.secdesc = NULL;
1782 info_ctr.level = 2;
1783 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1785 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1786 &pol,
1787 &info_ctr,
1788 &devmode_ctr,
1789 &secdesc_ctr,
1790 0, /* command */
1791 &result);
1792 if (!W_ERROR_IS_OK(result)) {
1793 printf("SetPrinter call failed!\n");
1794 goto done;;
1797 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1799 done:
1800 /* Cleanup */
1802 if (is_valid_policy_hnd(&pol))
1803 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1805 return result;
1809 /****************************************************************************
1810 ****************************************************************************/
1812 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1813 TALLOC_CTX *mem_ctx,
1814 int argc, const char **argv)
1816 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1817 NTSTATUS status;
1819 int i;
1820 int vers = -1;
1822 const char *arch = NULL;
1823 uint32_t delete_flags = 0;
1825 /* parse the command arguments */
1826 if (argc < 2 || argc > 4) {
1827 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1828 return WERR_OK;
1831 if (argc >= 3)
1832 arch = argv[2];
1833 if (argc == 4)
1834 vers = atoi (argv[3]);
1836 if (vers >= 0) {
1837 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1840 /* delete the driver for all architectures */
1841 for (i=0; archi_table[i].long_archi; i++) {
1843 if (arch && !strequal( archi_table[i].long_archi, arch))
1844 continue;
1846 if (vers >= 0 && archi_table[i].version != vers)
1847 continue;
1849 /* make the call to remove the driver */
1850 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1851 cli->srv_name_slash,
1852 archi_table[i].long_archi,
1853 argv[1],
1854 delete_flags,
1855 archi_table[i].version,
1856 &result);
1858 if ( !W_ERROR_IS_OK(result) )
1860 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1861 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1862 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1865 else
1867 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1868 archi_table[i].long_archi, archi_table[i].version);
1869 ret = WERR_OK;
1873 return ret;
1877 /****************************************************************************
1878 ****************************************************************************/
1880 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1881 TALLOC_CTX *mem_ctx,
1882 int argc, const char **argv)
1884 WERROR result = WERR_OK;
1885 NTSTATUS status;
1886 int i;
1888 /* parse the command arguments */
1889 if (argc != 2) {
1890 printf ("Usage: %s <driver>\n", argv[0]);
1891 return WERR_OK;
1894 /* delete the driver for all architectures */
1895 for (i=0; archi_table[i].long_archi; i++) {
1896 /* make the call to remove the driver */
1897 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1898 cli->srv_name_slash,
1899 archi_table[i].long_archi,
1900 argv[1],
1901 &result);
1902 if (!NT_STATUS_IS_OK(status)) {
1903 return result;
1905 if ( !W_ERROR_IS_OK(result) ) {
1906 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1907 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1908 argv[1], archi_table[i].long_archi,
1909 W_ERROR_V(result));
1911 } else {
1912 printf ("Driver %s removed for arch [%s].\n", argv[1],
1913 archi_table[i].long_archi);
1917 return result;
1920 /****************************************************************************
1921 ****************************************************************************/
1923 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1924 TALLOC_CTX *mem_ctx,
1925 int argc, const char **argv)
1927 WERROR result;
1928 NTSTATUS status;
1929 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1930 DATA_BLOB buffer;
1931 uint32_t offered;
1932 union spoolss_PrintProcessorDirectoryInfo info;
1933 uint32_t needed;
1935 /* parse the command arguments */
1936 if (argc > 2) {
1937 printf ("Usage: %s [environment]\n", argv[0]);
1938 return WERR_OK;
1941 if (argc == 2) {
1942 environment = argv[1];
1945 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1946 cli->srv_name_slash,
1947 environment,
1949 NULL, /* buffer */
1950 0, /* offered */
1951 NULL, /* info */
1952 &needed,
1953 &result);
1954 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1955 offered = needed;
1956 buffer = data_blob_talloc_zero(mem_ctx, needed);
1958 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1959 cli->srv_name_slash,
1960 environment,
1962 &buffer,
1963 offered,
1964 &info,
1965 &needed,
1966 &result);
1969 if (W_ERROR_IS_OK(result)) {
1970 printf("%s\n", info.info1.directory_name);
1973 return result;
1976 /****************************************************************************
1977 ****************************************************************************/
1979 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1980 int argc, const char **argv)
1982 struct policy_handle handle;
1983 WERROR werror;
1984 NTSTATUS status;
1985 const char *printername;
1986 union spoolss_AddFormInfo info;
1987 struct spoolss_AddFormInfo1 info1;
1988 struct spoolss_AddFormInfo2 info2;
1989 uint32_t level = 1;
1991 /* Parse the command arguments */
1993 if (argc < 3 || argc > 5) {
1994 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1995 return WERR_OK;
1998 /* Get a printer handle */
2000 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2002 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2003 printername,
2004 PRINTER_ALL_ACCESS,
2005 &handle);
2006 if (!W_ERROR_IS_OK(werror))
2007 goto done;
2009 /* Dummy up some values for the form data */
2011 if (argc == 4) {
2012 level = atoi(argv[3]);
2015 switch (level) {
2016 case 1:
2017 info1.flags = SPOOLSS_FORM_USER;
2018 info1.form_name = argv[2];
2019 info1.size.width = 100;
2020 info1.size.height = 100;
2021 info1.area.left = 0;
2022 info1.area.top = 10;
2023 info1.area.right = 20;
2024 info1.area.bottom = 30;
2026 info.info1 = &info1;
2028 break;
2029 case 2:
2030 info2.flags = SPOOLSS_FORM_USER;
2031 info2.form_name = argv[2];
2032 info2.size.width = 100;
2033 info2.size.height = 100;
2034 info2.area.left = 0;
2035 info2.area.top = 10;
2036 info2.area.right = 20;
2037 info2.area.bottom = 30;
2038 info2.keyword = argv[2];
2039 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2040 info2.mui_dll = NULL;
2041 info2.ressource_id = 0;
2042 info2.display_name = argv[2];
2043 info2.lang_id = 0;
2045 info.info2 = &info2;
2047 break;
2050 /* Add the form */
2053 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2054 &handle,
2055 level,
2056 info,
2057 &werror);
2059 done:
2060 if (is_valid_policy_hnd(&handle))
2061 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2063 return werror;
2066 /****************************************************************************
2067 ****************************************************************************/
2069 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2070 int argc, const char **argv)
2072 struct policy_handle handle;
2073 WERROR werror;
2074 NTSTATUS status;
2075 const char *printername;
2076 union spoolss_AddFormInfo info;
2077 struct spoolss_AddFormInfo1 info1;
2079 /* Parse the command arguments */
2081 if (argc != 3) {
2082 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2083 return WERR_OK;
2086 /* Get a printer handle */
2088 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2090 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2091 printername,
2092 SEC_FLAG_MAXIMUM_ALLOWED,
2093 &handle);
2094 if (!W_ERROR_IS_OK(werror))
2095 goto done;
2097 /* Dummy up some values for the form data */
2099 info1.flags = SPOOLSS_FORM_PRINTER;
2100 info1.size.width = 100;
2101 info1.size.height = 100;
2102 info1.area.left = 0;
2103 info1.area.top = 1000;
2104 info1.area.right = 2000;
2105 info1.area.bottom = 3000;
2106 info1.form_name = argv[2];
2108 info.info1 = &info1;
2110 /* Set the form */
2112 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2113 &handle,
2114 argv[2],
2116 info,
2117 &werror);
2119 done:
2120 if (is_valid_policy_hnd(&handle))
2121 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2123 return werror;
2126 /****************************************************************************
2127 ****************************************************************************/
2129 static const char *get_form_flag(int form_flag)
2131 switch (form_flag) {
2132 case SPOOLSS_FORM_USER:
2133 return "FORM_USER";
2134 case SPOOLSS_FORM_BUILTIN:
2135 return "FORM_BUILTIN";
2136 case SPOOLSS_FORM_PRINTER:
2137 return "FORM_PRINTER";
2138 default:
2139 return "unknown";
2143 /****************************************************************************
2144 ****************************************************************************/
2146 static void display_form_info1(struct spoolss_FormInfo1 *r)
2148 printf("%s\n" \
2149 "\tflag: %s (%d)\n" \
2150 "\twidth: %d, length: %d\n" \
2151 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2152 r->form_name, get_form_flag(r->flags), r->flags,
2153 r->size.width, r->size.height,
2154 r->area.left, r->area.right,
2155 r->area.top, r->area.bottom);
2158 /****************************************************************************
2159 ****************************************************************************/
2161 static void display_form_info2(struct spoolss_FormInfo2 *r)
2163 printf("%s\n" \
2164 "\tflag: %s (%d)\n" \
2165 "\twidth: %d, length: %d\n" \
2166 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2167 r->form_name, get_form_flag(r->flags), r->flags,
2168 r->size.width, r->size.height,
2169 r->area.left, r->area.right,
2170 r->area.top, r->area.bottom);
2171 printf("\tkeyword: %s\n", r->keyword);
2172 printf("\tstring_type: 0x%08x\n", r->string_type);
2173 printf("\tmui_dll: %s\n", r->mui_dll);
2174 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2175 printf("\tdisplay_name: %s\n", r->display_name);
2176 printf("\tlang_id: %d\n", r->lang_id);
2177 printf("\n");
2180 /****************************************************************************
2181 ****************************************************************************/
2183 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2184 int argc, const char **argv)
2186 struct policy_handle handle;
2187 WERROR werror;
2188 NTSTATUS status;
2189 const char *printername;
2190 DATA_BLOB buffer;
2191 uint32_t offered = 0;
2192 union spoolss_FormInfo info;
2193 uint32_t needed;
2194 uint32_t level = 1;
2196 /* Parse the command arguments */
2198 if (argc < 3 || argc > 5) {
2199 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2200 return WERR_OK;
2203 /* Get a printer handle */
2205 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2207 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2208 printername,
2209 SEC_FLAG_MAXIMUM_ALLOWED,
2210 &handle);
2211 if (!W_ERROR_IS_OK(werror))
2212 goto done;
2214 if (argc == 4) {
2215 level = atoi(argv[3]);
2218 /* Get the form */
2220 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2221 &handle,
2222 argv[2],
2223 level,
2224 NULL,
2225 offered,
2226 &info,
2227 &needed,
2228 &werror);
2229 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2230 buffer = data_blob_talloc_zero(mem_ctx, needed);
2231 offered = needed;
2232 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2233 &handle,
2234 argv[2],
2235 level,
2236 &buffer,
2237 offered,
2238 &info,
2239 &needed,
2240 &werror);
2243 if (!NT_STATUS_IS_OK(status)) {
2244 return werror;
2247 switch (level) {
2248 case 1:
2249 display_form_info1(&info.info1);
2250 break;
2251 case 2:
2252 display_form_info2(&info.info2);
2253 break;
2256 done:
2257 if (is_valid_policy_hnd(&handle))
2258 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2260 return werror;
2263 /****************************************************************************
2264 ****************************************************************************/
2266 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2267 TALLOC_CTX *mem_ctx, int argc,
2268 const char **argv)
2270 struct policy_handle handle;
2271 WERROR werror;
2272 NTSTATUS status;
2273 const char *printername;
2275 /* Parse the command arguments */
2277 if (argc != 3) {
2278 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2279 return WERR_OK;
2282 /* Get a printer handle */
2284 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2286 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2287 printername,
2288 SEC_FLAG_MAXIMUM_ALLOWED,
2289 &handle);
2290 if (!W_ERROR_IS_OK(werror))
2291 goto done;
2293 /* Delete the form */
2295 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2296 &handle,
2297 argv[2],
2298 &werror);
2299 if (!NT_STATUS_IS_OK(status)) {
2300 return ntstatus_to_werror(status);
2303 done:
2304 if (is_valid_policy_hnd(&handle))
2305 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2307 return werror;
2310 /****************************************************************************
2311 ****************************************************************************/
2313 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2314 TALLOC_CTX *mem_ctx, int argc,
2315 const char **argv)
2317 struct policy_handle handle;
2318 WERROR werror;
2319 const char *printername;
2320 uint32_t num_forms, level = 1, i;
2321 union spoolss_FormInfo *forms;
2323 /* Parse the command arguments */
2325 if (argc < 2 || argc > 4) {
2326 printf ("Usage: %s <printer> [level]\n", argv[0]);
2327 return WERR_OK;
2330 /* Get a printer handle */
2332 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2334 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2335 printername,
2336 SEC_FLAG_MAXIMUM_ALLOWED,
2337 &handle);
2338 if (!W_ERROR_IS_OK(werror))
2339 goto done;
2341 if (argc == 3) {
2342 level = atoi(argv[2]);
2345 /* Enumerate forms */
2347 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2348 &handle,
2349 level,
2351 &num_forms,
2352 &forms);
2354 if (!W_ERROR_IS_OK(werror))
2355 goto done;
2357 /* Display output */
2359 for (i = 0; i < num_forms; i++) {
2360 switch (level) {
2361 case 1:
2362 display_form_info1(&forms[i].info1);
2363 break;
2364 case 2:
2365 display_form_info2(&forms[i].info2);
2366 break;
2370 done:
2371 if (is_valid_policy_hnd(&handle))
2372 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2374 return werror;
2377 /****************************************************************************
2378 ****************************************************************************/
2380 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2381 TALLOC_CTX *mem_ctx,
2382 int argc, const char **argv)
2384 WERROR result;
2385 NTSTATUS status;
2386 const char *printername;
2387 struct policy_handle pol;
2388 union spoolss_PrinterInfo info;
2389 enum winreg_Type type;
2390 union spoolss_PrinterData data;
2391 DATA_BLOB blob;
2393 /* parse the command arguments */
2394 if (argc < 5) {
2395 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2396 " <value> <data>\n",
2397 argv[0]);
2398 return WERR_OK;
2401 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2403 type = REG_NONE;
2405 if (strequal(argv[2], "string")) {
2406 type = REG_SZ;
2409 if (strequal(argv[2], "binary")) {
2410 type = REG_BINARY;
2413 if (strequal(argv[2], "dword")) {
2414 type = REG_DWORD;
2417 if (strequal(argv[2], "multistring")) {
2418 type = REG_MULTI_SZ;
2421 if (type == REG_NONE) {
2422 printf("Unknown data type: %s\n", argv[2]);
2423 result = WERR_INVALID_PARAM;
2424 goto done;
2427 /* get a printer handle */
2429 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2430 printername,
2431 SEC_FLAG_MAXIMUM_ALLOWED,
2432 &pol);
2433 if (!W_ERROR_IS_OK(result)) {
2434 goto done;
2437 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2438 &pol,
2441 &info);
2442 if (!W_ERROR_IS_OK(result)) {
2443 goto done;
2446 printf("%s\n", current_timestring(mem_ctx, true));
2447 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2449 /* Set the printer data */
2451 switch (type) {
2452 case REG_SZ:
2453 data.string = talloc_strdup(mem_ctx, argv[4]);
2454 W_ERROR_HAVE_NO_MEMORY(data.string);
2455 break;
2456 case REG_DWORD:
2457 data.value = strtoul(argv[4], NULL, 10);
2458 break;
2459 case REG_BINARY:
2460 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2461 break;
2462 case REG_MULTI_SZ: {
2463 int i, num_strings;
2464 const char **strings = NULL;
2466 for (i=4; i<argc; i++) {
2467 if (strcmp(argv[i], "NULL") == 0) {
2468 argv[i] = "";
2470 if (!add_string_to_array(mem_ctx, argv[i],
2471 &strings,
2472 &num_strings)) {
2473 result = WERR_NOMEM;
2474 goto done;
2477 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2478 if (!data.string_array) {
2479 result = WERR_NOMEM;
2480 goto done;
2482 for (i=0; i < num_strings; i++) {
2483 data.string_array[i] = strings[i];
2485 break;
2487 default:
2488 printf("Unknown data type: %s\n", argv[2]);
2489 result = WERR_INVALID_PARAM;
2490 goto done;
2493 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2494 if (!W_ERROR_IS_OK(result)) {
2495 goto done;
2498 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2499 &pol,
2500 argv[3], /* value_name */
2501 type,
2502 blob.data,
2503 blob.length,
2504 &result);
2505 if (!W_ERROR_IS_OK(result)) {
2506 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2507 goto done;
2509 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2511 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2512 &pol,
2515 &info);
2516 if (!W_ERROR_IS_OK(result)) {
2517 goto done;
2520 printf("%s\n", current_timestring(mem_ctx, true));
2521 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2523 done:
2524 /* cleanup */
2525 if (is_valid_policy_hnd(&pol)) {
2526 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2529 return result;
2532 /****************************************************************************
2533 ****************************************************************************/
2535 static void display_job_info1(struct spoolss_JobInfo1 *r)
2537 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2538 r->user_name, r->document_name, r->text_status, r->pages_printed,
2539 r->total_pages);
2542 /****************************************************************************
2543 ****************************************************************************/
2545 static void display_job_info2(struct spoolss_JobInfo2 *r)
2547 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2548 r->position, r->job_id,
2549 r->user_name, r->document_name, r->text_status, r->pages_printed,
2550 r->total_pages, r->size);
2553 /****************************************************************************
2554 ****************************************************************************/
2556 static void display_job_info3(struct spoolss_JobInfo3 *r)
2558 printf("jobid[%d], next_jobid[%d]\n",
2559 r->job_id, r->next_job_id);
2562 /****************************************************************************
2563 ****************************************************************************/
2565 static void display_job_info4(struct spoolss_JobInfo4 *r)
2567 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2568 r->position, r->job_id,
2569 r->user_name, r->document_name, r->text_status, r->pages_printed,
2570 r->total_pages, r->size, r->size_high);
2573 /****************************************************************************
2574 ****************************************************************************/
2576 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2577 TALLOC_CTX *mem_ctx, int argc,
2578 const char **argv)
2580 WERROR result;
2581 uint32_t level = 1, count, i;
2582 const char *printername;
2583 struct policy_handle hnd;
2584 union spoolss_JobInfo *info;
2586 if (argc < 2 || argc > 3) {
2587 printf("Usage: %s printername [level]\n", argv[0]);
2588 return WERR_OK;
2591 if (argc == 3) {
2592 level = atoi(argv[2]);
2595 /* Open printer handle */
2597 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2599 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2600 printername,
2601 SEC_FLAG_MAXIMUM_ALLOWED,
2602 &hnd);
2603 if (!W_ERROR_IS_OK(result))
2604 goto done;
2606 /* Enumerate ports */
2608 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2609 &hnd,
2610 0, /* firstjob */
2611 1000, /* numjobs */
2612 level,
2614 &count,
2615 &info);
2616 if (!W_ERROR_IS_OK(result)) {
2617 goto done;
2620 for (i = 0; i < count; i++) {
2621 switch (level) {
2622 case 1:
2623 display_job_info1(&info[i].info1);
2624 break;
2625 case 2:
2626 display_job_info2(&info[i].info2);
2627 break;
2628 default:
2629 d_printf("unknown info level %d\n", level);
2630 break;
2634 done:
2635 if (is_valid_policy_hnd(&hnd)) {
2636 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2639 return result;
2642 /****************************************************************************
2643 ****************************************************************************/
2645 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2646 TALLOC_CTX *mem_ctx, int argc,
2647 const char **argv)
2649 WERROR result;
2650 const char *printername;
2651 struct policy_handle hnd;
2652 uint32_t job_id;
2653 uint32_t level = 1;
2654 union spoolss_JobInfo info;
2656 if (argc < 3 || argc > 4) {
2657 printf("Usage: %s printername job_id [level]\n", argv[0]);
2658 return WERR_OK;
2661 job_id = atoi(argv[2]);
2663 if (argc == 4) {
2664 level = atoi(argv[3]);
2667 /* Open printer handle */
2669 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2671 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2672 printername,
2673 SEC_FLAG_MAXIMUM_ALLOWED,
2674 &hnd);
2675 if (!W_ERROR_IS_OK(result)) {
2676 goto done;
2679 /* Enumerate ports */
2681 result = rpccli_spoolss_getjob(cli, mem_ctx,
2682 &hnd,
2683 job_id,
2684 level,
2686 &info);
2688 if (!W_ERROR_IS_OK(result)) {
2689 goto done;
2692 switch (level) {
2693 case 1:
2694 display_job_info1(&info.info1);
2695 break;
2696 case 2:
2697 display_job_info2(&info.info2);
2698 break;
2699 case 3:
2700 display_job_info3(&info.info3);
2701 break;
2702 case 4:
2703 display_job_info4(&info.info4);
2704 break;
2705 default:
2706 d_printf("unknown info level %d\n", level);
2707 break;
2710 done:
2711 if (is_valid_policy_hnd(&hnd)) {
2712 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2715 return result;
2718 /****************************************************************************
2719 ****************************************************************************/
2721 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2722 TALLOC_CTX *mem_ctx, int argc,
2723 const char **argv)
2725 WERROR result;
2726 NTSTATUS status;
2727 const char *printername;
2728 struct policy_handle hnd;
2729 uint32_t job_id;
2730 enum spoolss_JobControl command;
2732 if (argc != 4) {
2733 printf("Usage: %s printername job_id command\n", argv[0]);
2734 return WERR_OK;
2737 job_id = atoi(argv[2]);
2738 command = atoi(argv[3]);
2740 /* Open printer handle */
2742 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2744 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2745 printername,
2746 SEC_FLAG_MAXIMUM_ALLOWED,
2747 &hnd);
2748 if (!W_ERROR_IS_OK(result)) {
2749 goto done;
2752 /* Set Job */
2754 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2755 &hnd,
2756 job_id,
2757 NULL,
2758 command,
2759 &result);
2761 if (!W_ERROR_IS_OK(result)) {
2762 goto done;
2765 done:
2766 if (is_valid_policy_hnd(&hnd)) {
2767 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2770 return result;
2773 /****************************************************************************
2774 ****************************************************************************/
2776 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2777 TALLOC_CTX *mem_ctx, int argc,
2778 const char **argv)
2780 WERROR result;
2781 NTSTATUS status;
2782 uint32_t i = 0;
2783 const char *printername;
2784 struct policy_handle hnd;
2785 uint32_t value_offered = 0;
2786 const char *value_name = NULL;
2787 uint32_t value_needed;
2788 enum winreg_Type type;
2789 uint8_t *data = NULL;
2790 uint32_t data_offered = 0;
2791 uint32_t data_needed;
2793 if (argc != 2) {
2794 printf("Usage: %s printername\n", argv[0]);
2795 return WERR_OK;
2798 /* Open printer handle */
2800 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2802 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2803 printername,
2804 SEC_FLAG_MAXIMUM_ALLOWED,
2805 &hnd);
2806 if (!W_ERROR_IS_OK(result)) {
2807 goto done;
2810 /* Enumerate data */
2812 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2813 &hnd,
2815 value_name,
2816 value_offered,
2817 &value_needed,
2818 &type,
2819 data,
2820 data_offered,
2821 &data_needed,
2822 &result);
2824 data_offered = data_needed;
2825 value_offered = value_needed;
2826 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2827 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2829 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2831 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2832 &hnd,
2833 i++,
2834 value_name,
2835 value_offered,
2836 &value_needed,
2837 &type,
2838 data,
2839 data_offered,
2840 &data_needed,
2841 &result);
2842 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2843 struct regval_blob v;
2844 fstrcpy(v.valuename, value_name);
2845 v.type = type;
2846 v.size = data_offered;
2847 v.data_p = data;
2848 display_reg_value(v);
2852 if (W_ERROR_V(result) == ERRnomoreitems) {
2853 result = W_ERROR(ERRsuccess);
2856 done:
2857 if (is_valid_policy_hnd(&hnd)) {
2858 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2861 return result;
2864 /****************************************************************************
2865 ****************************************************************************/
2867 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2868 TALLOC_CTX *mem_ctx, int argc,
2869 const char **argv)
2871 WERROR result;
2872 uint32_t i;
2873 const char *printername;
2874 struct policy_handle hnd;
2875 uint32_t count;
2876 struct spoolss_PrinterEnumValues *info;
2878 if (argc != 3) {
2879 printf("Usage: %s printername <keyname>\n", argv[0]);
2880 return WERR_OK;
2883 /* Open printer handle */
2885 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2887 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2888 printername,
2889 SEC_FLAG_MAXIMUM_ALLOWED,
2890 &hnd);
2891 if (!W_ERROR_IS_OK(result)) {
2892 goto done;
2895 /* Enumerate subkeys */
2897 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2898 &hnd,
2899 argv[2],
2901 &count,
2902 &info);
2903 if (!W_ERROR_IS_OK(result)) {
2904 goto done;
2907 for (i=0; i < count; i++) {
2908 display_printer_data(info[i].value_name,
2909 info[i].type,
2910 info[i].data->data,
2911 info[i].data->length);
2914 done:
2915 if (is_valid_policy_hnd(&hnd)) {
2916 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2919 return result;
2922 /****************************************************************************
2923 ****************************************************************************/
2925 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2926 TALLOC_CTX *mem_ctx, int argc,
2927 const char **argv)
2929 WERROR result;
2930 const char *printername;
2931 const char *keyname = NULL;
2932 struct policy_handle hnd;
2933 const char **key_buffer = NULL;
2934 int i;
2935 uint32_t offered = 0;
2937 if (argc < 2 || argc > 4) {
2938 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
2939 return WERR_OK;
2942 if (argc >= 3) {
2943 keyname = argv[2];
2944 } else {
2945 keyname = "";
2948 if (argc == 4) {
2949 offered = atoi(argv[3]);
2952 /* Open printer handle */
2954 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2956 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2957 printername,
2958 SEC_FLAG_MAXIMUM_ALLOWED,
2959 &hnd);
2960 if (!W_ERROR_IS_OK(result)) {
2961 goto done;
2964 /* Enumerate subkeys */
2966 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
2967 &hnd,
2968 keyname,
2969 &key_buffer,
2970 offered);
2972 if (!W_ERROR_IS_OK(result)) {
2973 goto done;
2976 for (i=0; key_buffer && key_buffer[i]; i++) {
2977 printf("%s\n", key_buffer[i]);
2980 done:
2982 if (is_valid_policy_hnd(&hnd)) {
2983 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2986 return result;
2989 /****************************************************************************
2990 ****************************************************************************/
2992 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2993 TALLOC_CTX *mem_ctx, int argc,
2994 const char **argv)
2996 const char *printername;
2997 const char *clientname;
2998 struct policy_handle hnd;
2999 WERROR result;
3000 NTSTATUS status;
3001 struct spoolss_NotifyOption option;
3003 if (argc != 2) {
3004 printf("Usage: %s printername\n", argv[0]);
3005 result = WERR_OK;
3006 goto done;
3009 /* Open printer */
3011 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3013 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3014 printername,
3015 SEC_FLAG_MAXIMUM_ALLOWED,
3016 &hnd);
3017 if (!W_ERROR_IS_OK(result)) {
3018 printf("Error opening %s\n", argv[1]);
3019 goto done;
3022 /* Create spool options */
3024 option.version = 2;
3025 option.count = 2;
3027 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3028 if (option.types == NULL) {
3029 result = WERR_NOMEM;
3030 goto done;
3033 option.types[0].type = PRINTER_NOTIFY_TYPE;
3034 option.types[0].count = 1;
3035 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3036 if (option.types[0].fields == NULL) {
3037 result = WERR_NOMEM;
3038 goto done;
3040 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3042 option.types[1].type = JOB_NOTIFY_TYPE;
3043 option.types[1].count = 1;
3044 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3045 if (option.types[1].fields == NULL) {
3046 result = WERR_NOMEM;
3047 goto done;
3049 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3051 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3052 if (!clientname) {
3053 result = WERR_NOMEM;
3054 goto done;
3057 /* Send rffpcnex */
3059 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3060 &hnd,
3063 clientname,
3064 123,
3065 &option,
3066 &result);
3067 if (!W_ERROR_IS_OK(result)) {
3068 printf("Error rffpcnex %s\n", argv[1]);
3069 goto done;
3072 done:
3073 if (is_valid_policy_hnd(&hnd))
3074 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3076 return result;
3079 /****************************************************************************
3080 ****************************************************************************/
3082 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3083 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3085 union spoolss_PrinterInfo info1, info2;
3086 WERROR werror;
3087 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3089 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3090 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3091 hnd1,
3094 &info1);
3095 if ( !W_ERROR_IS_OK(werror) ) {
3096 printf("failed (%s)\n", win_errstr(werror));
3097 talloc_destroy(mem_ctx);
3098 return false;
3100 printf("ok\n");
3102 printf("Retrieving printer properties for %s...", cli2->desthost);
3103 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3104 hnd2,
3107 &info2);
3108 if ( !W_ERROR_IS_OK(werror) ) {
3109 printf("failed (%s)\n", win_errstr(werror));
3110 talloc_destroy(mem_ctx);
3111 return false;
3113 printf("ok\n");
3115 talloc_destroy(mem_ctx);
3117 return true;
3120 /****************************************************************************
3121 ****************************************************************************/
3123 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3124 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3126 union spoolss_PrinterInfo info1, info2;
3127 WERROR werror;
3128 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3129 SEC_DESC *sd1, *sd2;
3130 bool result = true;
3133 printf("Retrieving printer security for %s...", cli1->desthost);
3134 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3135 hnd1,
3138 &info1);
3139 if ( !W_ERROR_IS_OK(werror) ) {
3140 printf("failed (%s)\n", win_errstr(werror));
3141 result = false;
3142 goto done;
3144 printf("ok\n");
3146 printf("Retrieving printer security for %s...", cli2->desthost);
3147 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3148 hnd2,
3151 &info2);
3152 if ( !W_ERROR_IS_OK(werror) ) {
3153 printf("failed (%s)\n", win_errstr(werror));
3154 result = false;
3155 goto done;
3157 printf("ok\n");
3160 printf("++ ");
3162 sd1 = info1.info3.secdesc;
3163 sd2 = info2.info3.secdesc;
3165 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3166 printf("NULL secdesc!\n");
3167 result = false;
3168 goto done;
3171 if (!security_descriptor_equal( sd1, sd2 ) ) {
3172 printf("Security Descriptors *not* equal!\n");
3173 result = false;
3174 goto done;
3177 printf("Security descriptors match\n");
3179 done:
3180 talloc_destroy(mem_ctx);
3181 return result;
3185 /****************************************************************************
3186 ****************************************************************************/
3188 extern struct user_auth_info *rpcclient_auth_info;
3190 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3191 TALLOC_CTX *mem_ctx, int argc,
3192 const char **argv)
3194 const char *printername;
3195 char *printername_path = NULL;
3196 struct cli_state *cli_server2 = NULL;
3197 struct rpc_pipe_client *cli2 = NULL;
3198 struct policy_handle hPrinter1, hPrinter2;
3199 NTSTATUS nt_status;
3200 WERROR werror;
3202 if ( argc != 3 ) {
3203 printf("Usage: %s <printer> <server>\n", argv[0]);
3204 return WERR_OK;
3207 printername = argv[1];
3209 /* first get the connection to the remote server */
3211 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3212 NULL, 0,
3213 "IPC$", "IPC",
3214 get_cmdline_auth_info_username(rpcclient_auth_info),
3215 lp_workgroup(),
3216 get_cmdline_auth_info_password(rpcclient_auth_info),
3217 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3218 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3220 if ( !NT_STATUS_IS_OK(nt_status) )
3221 return WERR_GENERAL_FAILURE;
3223 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3224 &cli2);
3225 if (!NT_STATUS_IS_OK(nt_status)) {
3226 printf("failed to open spoolss pipe on server %s (%s)\n",
3227 argv[2], nt_errstr(nt_status));
3228 return WERR_GENERAL_FAILURE;
3231 /* now open up both printers */
3233 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3235 printf("Opening %s...", printername_path);
3237 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3238 printername_path,
3239 PRINTER_ALL_ACCESS,
3240 &hPrinter1);
3241 if ( !W_ERROR_IS_OK(werror) ) {
3242 printf("failed (%s)\n", win_errstr(werror));
3243 goto done;
3245 printf("ok\n");
3247 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3249 printf("Opening %s...", printername_path);
3250 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3251 printername_path,
3252 PRINTER_ALL_ACCESS,
3253 &hPrinter2);
3254 if ( !W_ERROR_IS_OK(werror) ) {
3255 printf("failed (%s)\n", win_errstr(werror));
3256 goto done;
3258 printf("ok\n");
3260 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3261 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3262 #if 0
3263 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3264 #endif
3267 done:
3268 /* cleanup */
3270 printf("Closing printers...");
3271 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3272 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3273 printf("ok\n");
3275 /* close the second remote connection */
3277 cli_shutdown( cli_server2 );
3278 return WERR_OK;
3281 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3283 printf("print_processor_name: %s\n", r->print_processor_name);
3286 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3287 TALLOC_CTX *mem_ctx, int argc,
3288 const char **argv)
3290 WERROR werror;
3291 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3292 uint32_t num_procs, level = 1, i;
3293 union spoolss_PrintProcessorInfo *procs;
3295 /* Parse the command arguments */
3297 if (argc < 1 || argc > 4) {
3298 printf ("Usage: %s [environment] [level]\n", argv[0]);
3299 return WERR_OK;
3302 if (argc >= 2) {
3303 environment = argv[1];
3306 if (argc == 3) {
3307 level = atoi(argv[2]);
3310 /* Enumerate Print Processors */
3312 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3313 cli->srv_name_slash,
3314 environment,
3315 level,
3317 &num_procs,
3318 &procs);
3319 if (!W_ERROR_IS_OK(werror))
3320 goto done;
3322 /* Display output */
3324 for (i = 0; i < num_procs; i++) {
3325 switch (level) {
3326 case 1:
3327 display_proc_info1(&procs[i].info1);
3328 break;
3332 done:
3333 return werror;
3336 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3338 printf("name_array: %s\n", r->name_array);
3341 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3342 TALLOC_CTX *mem_ctx, int argc,
3343 const char **argv)
3345 WERROR werror;
3346 const char *print_processor_name = "winprint";
3347 uint32_t num_procs, level = 1, i;
3348 union spoolss_PrintProcDataTypesInfo *procs;
3350 /* Parse the command arguments */
3352 if (argc < 1 || argc > 4) {
3353 printf ("Usage: %s [environment] [level]\n", argv[0]);
3354 return WERR_OK;
3357 if (argc >= 2) {
3358 print_processor_name = argv[1];
3361 if (argc == 3) {
3362 level = atoi(argv[2]);
3365 /* Enumerate Print Processor Data Types */
3367 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3368 cli->srv_name_slash,
3369 print_processor_name,
3370 level,
3372 &num_procs,
3373 &procs);
3374 if (!W_ERROR_IS_OK(werror))
3375 goto done;
3377 /* Display output */
3379 for (i = 0; i < num_procs; i++) {
3380 switch (level) {
3381 case 1:
3382 display_proc_data_types_info1(&procs[i].info1);
3383 break;
3387 done:
3388 return werror;
3391 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3393 printf("monitor_name: %s\n", r->monitor_name);
3396 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3398 printf("monitor_name: %s\n", r->monitor_name);
3399 printf("environment: %s\n", r->environment);
3400 printf("dll_name: %s\n", r->dll_name);
3403 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3404 TALLOC_CTX *mem_ctx, int argc,
3405 const char **argv)
3407 WERROR werror;
3408 uint32_t count, level = 1, i;
3409 union spoolss_MonitorInfo *info;
3411 /* Parse the command arguments */
3413 if (argc > 2) {
3414 printf("Usage: %s [level]\n", argv[0]);
3415 return WERR_OK;
3418 if (argc == 2) {
3419 level = atoi(argv[1]);
3422 /* Enumerate Print Monitors */
3424 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3425 cli->srv_name_slash,
3426 level,
3428 &count,
3429 &info);
3430 if (!W_ERROR_IS_OK(werror)) {
3431 goto done;
3434 /* Display output */
3436 for (i = 0; i < count; i++) {
3437 switch (level) {
3438 case 1:
3439 display_monitor1(&info[i].info1);
3440 break;
3441 case 2:
3442 display_monitor2(&info[i].info2);
3443 break;
3447 done:
3448 return werror;
3451 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3452 TALLOC_CTX *mem_ctx, int argc,
3453 const char **argv)
3455 WERROR result;
3456 NTSTATUS status;
3457 struct policy_handle handle, gdi_handle;
3458 const char *printername;
3459 struct spoolss_DevmodeContainer devmode_ctr;
3461 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3463 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3464 printername,
3465 SEC_FLAG_MAXIMUM_ALLOWED,
3466 &handle);
3467 if (!W_ERROR_IS_OK(result)) {
3468 return result;
3471 ZERO_STRUCT(devmode_ctr);
3473 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3474 &handle,
3475 &gdi_handle,
3476 &devmode_ctr,
3477 &result);
3478 if (!W_ERROR_IS_OK(result)) {
3479 goto done;
3482 done:
3483 if (is_valid_policy_hnd(&gdi_handle)) {
3484 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3486 if (is_valid_policy_hnd(&handle)) {
3487 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3490 return result;
3493 /* List of commands exported by this module */
3494 struct cmd_set spoolss_commands[] = {
3496 { "SPOOLSS" },
3498 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3499 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3500 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3501 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3502 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3503 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3504 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3505 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3506 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3507 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3508 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3509 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3510 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3511 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3512 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3513 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3514 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3515 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3516 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3517 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3518 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3519 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3520 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3521 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3522 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3523 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3524 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3525 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3526 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3527 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3528 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3529 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3530 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3531 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3532 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3534 { NULL }