s3-rpcclient: pure cosmetics for cmd_spoolss_enum_ports.
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blob1b8588ac48f6894e04a6e8146b80fdfa6ccb8488
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
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "rpcclient.h"
27 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
28 { \
29 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
30 _cli->srv_name_slash, _arg); \
31 W_ERROR_HAVE_NO_MEMORY(_printername); \
34 struct table_node {
35 const char *long_archi;
36 const char *short_archi;
37 int version;
40 /* The version int is used by getdrivers. Note that
41 all architecture strings that support mutliple
42 versions must be grouped together since enumdrivers
43 uses this property to prevent issuing multiple
44 enumdriver calls for the same arch */
47 static const struct table_node archi_table[]= {
49 {"Windows 4.0", "WIN40", 0 },
50 {"Windows NT x86", "W32X86", 2 },
51 {"Windows NT x86", "W32X86", 3 },
52 {"Windows NT R4000", "W32MIPS", 2 },
53 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
54 {"Windows NT PowerPC", "W32PPC", 2 },
55 {"Windows IA64", "IA64", 3 },
56 {"Windows x64", "x64", 3 },
57 {NULL, "", -1 }
60 /**
61 * @file
63 * rpcclient module for SPOOLSS rpc pipe.
65 * This generally just parses and checks command lines, and then calls
66 * a cli_spoolss function.
67 **/
69 /****************************************************************************
70 function to do the mapping between the long architecture name and
71 the short one.
72 ****************************************************************************/
74 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
76 int i=-1;
78 DEBUG(107,("Getting architecture dependant directory\n"));
79 do {
80 i++;
81 } while ( (archi_table[i].long_archi!=NULL ) &&
82 StrCaseCmp(long_archi, archi_table[i].long_archi) );
84 if (archi_table[i].long_archi==NULL) {
85 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
86 return NULL;
89 /* this might be client code - but shouldn't this be an fstrcpy etc? */
92 DEBUGADD(108,("index: [%d]\n", i));
93 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
94 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
96 return archi_table[i].short_archi;
99 /****************************************************************************
100 ****************************************************************************/
102 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
103 TALLOC_CTX *mem_ctx,
104 int argc, const char **argv)
106 WERROR werror;
107 POLICY_HND hnd;
109 if (argc != 2) {
110 printf("Usage: %s <printername>\n", argv[0]);
111 return WERR_OK;
114 if (!cli)
115 return WERR_GENERAL_FAILURE;
117 /* Open the printer handle */
119 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
120 argv[1],
121 PRINTER_ALL_ACCESS,
122 &hnd);
123 if (W_ERROR_IS_OK(werror)) {
124 printf("Printer %s opened successfully\n", argv[1]);
125 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
127 if (!W_ERROR_IS_OK(werror)) {
128 printf("Error closing printer handle! (%s)\n",
129 get_dos_error_msg(werror));
133 return werror;
137 /****************************************************************************
138 ****************************************************************************/
140 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
142 if (!r)
143 return;
145 printf("\tprintername:[%s]\n", r->printername);
146 printf("\tservername:[%s]\n", r->servername);
147 printf("\tcjobs:[0x%x]\n", r->cjobs);
148 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
149 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
150 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
151 r->time.day, r->time.day_of_week);
152 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
153 r->time.second, r->time.millisecond);
155 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
156 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
158 printf("\tversion:[0x%x]\n", r->version);
159 printf("\tfree_build:[0x%x]\n", r->free_build);
160 printf("\tspooling:[0x%x]\n", r->spooling);
161 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
162 printf("\tsession_counter:[0x%x]\n", r->session_counter);
163 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
164 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
165 printf("\tjob_error:[0x%x]\n", r->job_error);
166 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
167 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
168 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
169 printf("\tchange_id:[0x%x]\n", r->change_id);
170 printf("\tlast_error: %s\n", win_errstr(r->last_error));
171 printf("\tstatus:[0x%x]\n", r->status);
172 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
173 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
174 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
175 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
176 printf("\tref_ic:[0x%x]\n", r->ref_ic);
177 printf("\treserved2:[0x%x]\n", r->reserved2);
178 printf("\treserved3:[0x%x]\n", r->reserved3);
180 printf("\n");
183 /****************************************************************************
184 ****************************************************************************/
186 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
188 printf("\tflags:[0x%x]\n", r->flags);
189 printf("\tname:[%s]\n", r->name);
190 printf("\tdescription:[%s]\n", r->description);
191 printf("\tcomment:[%s]\n", r->comment);
193 printf("\n");
196 /****************************************************************************
197 ****************************************************************************/
199 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
201 printf("\tservername:[%s]\n", r->servername);
202 printf("\tprintername:[%s]\n", r->printername);
203 printf("\tsharename:[%s]\n", r->sharename);
204 printf("\tportname:[%s]\n", r->portname);
205 printf("\tdrivername:[%s]\n", r->drivername);
206 printf("\tcomment:[%s]\n", r->comment);
207 printf("\tlocation:[%s]\n", r->location);
208 printf("\tsepfile:[%s]\n", r->sepfile);
209 printf("\tprintprocessor:[%s]\n", r->printprocessor);
210 printf("\tdatatype:[%s]\n", r->datatype);
211 printf("\tparameters:[%s]\n", r->parameters);
212 printf("\tattributes:[0x%x]\n", r->attributes);
213 printf("\tpriority:[0x%x]\n", r->priority);
214 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
215 printf("\tstarttime:[0x%x]\n", r->starttime);
216 printf("\tuntiltime:[0x%x]\n", r->untiltime);
217 printf("\tstatus:[0x%x]\n", r->status);
218 printf("\tcjobs:[0x%x]\n", r->cjobs);
219 printf("\taverageppm:[0x%x]\n", r->averageppm);
221 if (r->secdesc)
222 display_sec_desc(r->secdesc);
224 printf("\n");
227 /****************************************************************************
228 ****************************************************************************/
230 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
232 display_sec_desc(r->secdesc);
234 printf("\n");
237 /****************************************************************************
238 ****************************************************************************/
240 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
242 printf("\tguid:[%s]\n", r->guid);
243 printf("\taction:[0x%x]\n", r->action);
247 /****************************************************************************
248 ****************************************************************************/
250 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
251 TALLOC_CTX *mem_ctx,
252 int argc, const char **argv)
254 WERROR result;
255 uint32_t level = 1;
256 union spoolss_PrinterInfo *info;
257 uint32_t i, count;
258 const char *name;
260 if (argc > 3) {
261 printf("Usage: %s [level] [name]\n", argv[0]);
262 return WERR_OK;
265 if (argc >= 2) {
266 level = atoi(argv[1]);
269 if (argc == 3) {
270 name = argv[2];
271 } else {
272 name = cli->srv_name_slash;
275 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
276 PRINTER_ENUM_LOCAL,
277 name,
278 level,
280 &count,
281 &info);
282 if (W_ERROR_IS_OK(result)) {
284 if (!count) {
285 printf ("No printers returned.\n");
286 goto done;
289 for (i = 0; i < count; i++) {
290 switch (level) {
291 case 0:
292 display_print_info0(&info[i].info0);
293 break;
294 case 1:
295 display_print_info1(&info[i].info1);
296 break;
297 case 2:
298 display_print_info2(&info[i].info2);
299 break;
300 case 3:
301 display_print_info3(&info[i].info3);
302 break;
303 default:
304 printf("unknown info level %d\n", level);
305 goto done;
309 done:
311 return result;
314 /****************************************************************************
315 ****************************************************************************/
317 static void display_port_info_1(struct spoolss_PortInfo1 *r)
319 printf("\tPort Name:\t[%s]\n", r->port_name);
322 /****************************************************************************
323 ****************************************************************************/
325 static void display_port_info_2(struct spoolss_PortInfo2 *r)
327 printf("\tPort Name:\t[%s]\n", r->port_name);
328 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
329 printf("\tDescription:\t[%s]\n", r->description);
330 printf("\tPort Type:\t" );
331 if (r->port_type) {
332 int comma = 0; /* hack */
333 printf( "[" );
334 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
335 printf( "Read" );
336 comma = 1;
338 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
339 printf( "%sWrite", comma ? ", " : "" );
340 comma = 1;
342 /* These two have slightly different interpretations
343 on 95/98/ME but I'm disregarding that for now */
344 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
345 printf( "%sRedirected", comma ? ", " : "" );
346 comma = 1;
348 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
349 printf( "%sNet-Attached", comma ? ", " : "" );
351 printf( "]\n" );
352 } else {
353 printf( "[Unset]\n" );
355 printf("\tReserved:\t[%d]\n", r->reserved);
356 printf("\n");
359 /****************************************************************************
360 ****************************************************************************/
362 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
363 TALLOC_CTX *mem_ctx, int argc,
364 const char **argv)
366 WERROR result;
367 uint32_t level = 1;
368 uint32_t count;
369 union spoolss_PortInfo *info;
371 if (argc > 2) {
372 printf("Usage: %s [level]\n", argv[0]);
373 return WERR_OK;
376 if (argc == 2) {
377 level = atoi(argv[1]);
380 /* Enumerate ports */
382 result = rpccli_spoolss_enumports(cli, mem_ctx,
383 cli->srv_name_slash,
384 level,
386 &count,
387 &info);
388 if (W_ERROR_IS_OK(result)) {
389 int i;
391 for (i = 0; i < count; i++) {
392 switch (level) {
393 case 1:
394 display_port_info_1(&info[i].info1);
395 break;
396 case 2:
397 display_port_info_2(&info[i].info2);
398 break;
399 default:
400 printf("unknown info level %d\n", level);
401 break;
406 return result;
409 /****************************************************************************
410 ****************************************************************************/
412 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
413 TALLOC_CTX *mem_ctx,
414 int argc, const char **argv)
416 POLICY_HND pol;
417 WERROR result;
418 NTSTATUS status;
419 uint32 info_level = 2;
420 union spoolss_PrinterInfo info;
421 struct spoolss_SetPrinterInfoCtr info_ctr;
422 const char *printername, *comment = NULL;
423 struct spoolss_DevmodeContainer devmode_ctr;
424 struct sec_desc_buf secdesc_ctr;
426 if (argc == 1 || argc > 3) {
427 printf("Usage: %s printername comment\n", argv[0]);
429 return WERR_OK;
432 /* Open a printer handle */
433 if (argc == 3) {
434 comment = argv[2];
437 ZERO_STRUCT(devmode_ctr);
438 ZERO_STRUCT(secdesc_ctr);
440 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
442 /* get a printer handle */
443 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
444 printername,
445 PRINTER_ALL_ACCESS,
446 &pol);
447 if (!W_ERROR_IS_OK(result))
448 goto done;
450 /* Get printer info */
451 result = rpccli_spoolss_getprinter(cli, mem_ctx,
452 &pol,
453 info_level,
455 &info);
456 if (!W_ERROR_IS_OK(result))
457 goto done;
460 /* Modify the comment. */
461 info.info2.comment = comment;
462 info.info2.secdesc = NULL;
463 info.info2.devmode = NULL;
465 info_ctr.level = 2;
466 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
468 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
469 &pol,
470 &info_ctr,
471 &devmode_ctr,
472 &secdesc_ctr,
473 0, /* command */
474 &result);
475 if (W_ERROR_IS_OK(result))
476 printf("Success in setting comment.\n");
478 done:
479 if (is_valid_policy_hnd(&pol))
480 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
482 return result;
485 /****************************************************************************
486 ****************************************************************************/
488 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
489 TALLOC_CTX *mem_ctx,
490 int argc, const char **argv)
492 POLICY_HND pol;
493 WERROR result;
494 NTSTATUS status;
495 uint32 info_level = 2;
496 union spoolss_PrinterInfo info;
497 const char *printername,
498 *new_printername = NULL;
499 struct spoolss_SetPrinterInfoCtr info_ctr;
500 struct spoolss_DevmodeContainer devmode_ctr;
501 struct sec_desc_buf secdesc_ctr;
503 ZERO_STRUCT(devmode_ctr);
504 ZERO_STRUCT(secdesc_ctr);
506 if (argc == 1 || argc > 3) {
507 printf("Usage: %s printername new_printername\n", argv[0]);
509 return WERR_OK;
512 /* Open a printer handle */
513 if (argc == 3) {
514 new_printername = argv[2];
517 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
519 /* get a printer handle */
520 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
521 printername,
522 PRINTER_ALL_ACCESS,
523 &pol);
524 if (!W_ERROR_IS_OK(result))
525 goto done;
527 /* Get printer info */
528 result = rpccli_spoolss_getprinter(cli, mem_ctx,
529 &pol,
530 info_level,
532 &info);
533 if (!W_ERROR_IS_OK(result))
534 goto done;
536 /* Modify the printername. */
537 info.info2.printername = new_printername;
538 info.info2.devmode = NULL;
539 info.info2.secdesc = NULL;
541 info_ctr.level = info_level;
542 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
544 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
545 &pol,
546 &info_ctr,
547 &devmode_ctr,
548 &secdesc_ctr,
549 0, /* command */
550 &result);
551 if (W_ERROR_IS_OK(result))
552 printf("Success in setting printername.\n");
554 done:
555 if (is_valid_policy_hnd(&pol))
556 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
558 return result;
561 /****************************************************************************
562 ****************************************************************************/
564 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
565 TALLOC_CTX *mem_ctx,
566 int argc, const char **argv)
568 POLICY_HND pol;
569 WERROR result;
570 uint32 info_level = 1;
571 const char *printername;
572 union spoolss_PrinterInfo info;
574 if (argc == 1 || argc > 3) {
575 printf("Usage: %s <printername> [level]\n", argv[0]);
576 return WERR_OK;
579 /* Open a printer handle */
580 if (argc == 3) {
581 info_level = atoi(argv[2]);
584 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
586 /* get a printer handle */
588 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
589 printername,
590 SEC_FLAG_MAXIMUM_ALLOWED,
591 &pol);
592 if (!W_ERROR_IS_OK(result))
593 goto done;
595 /* Get printer info */
597 result = rpccli_spoolss_getprinter(cli, mem_ctx,
598 &pol,
599 info_level,
601 &info);
602 if (!W_ERROR_IS_OK(result))
603 goto done;
605 /* Display printer info */
606 switch (info_level) {
607 case 0:
608 display_print_info0(&info.info0);
609 break;
610 case 1:
611 display_print_info1(&info.info1);
612 break;
613 case 2:
614 display_print_info2(&info.info2);
615 break;
616 case 3:
617 display_print_info3(&info.info3);
618 break;
619 case 7:
620 display_print_info7(&info.info7);
621 break;
622 default:
623 printf("unknown info level %d\n", info_level);
624 break;
626 done:
627 if (is_valid_policy_hnd(&pol))
628 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
630 return result;
633 /****************************************************************************
634 ****************************************************************************/
636 static void display_reg_value(REGISTRY_VALUE value)
638 char *text = NULL;
640 switch(value.type) {
641 case REG_DWORD:
642 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
643 *((uint32 *) value.data_p));
644 break;
645 case REG_SZ:
646 rpcstr_pull_talloc(talloc_tos(),
647 &text,
648 value.data_p,
649 value.size,
650 STR_TERMINATE);
651 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
652 break;
653 case REG_BINARY: {
654 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
655 size_t i, len;
656 printf("%s: REG_BINARY:", value.valuename);
657 len = strlen(hex);
658 for (i=0; i<len; i++) {
659 if (hex[i] == '\0') {
660 break;
662 if (i%40 == 0) {
663 putchar('\n');
665 putchar(hex[i]);
667 TALLOC_FREE(hex);
668 putchar('\n');
669 break;
671 case REG_MULTI_SZ: {
672 uint32 i, num_values;
673 char **values;
675 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
676 value.size, &num_values,
677 &values))) {
678 d_printf("reg_pull_multi_sz failed\n");
679 break;
682 for (i=0; i<num_values; i++) {
683 d_printf("%s\n", values[i]);
685 TALLOC_FREE(values);
686 break;
688 default:
689 printf("%s: unknown type %d\n", value.valuename, value.type);
694 /****************************************************************************
695 ****************************************************************************/
697 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
698 TALLOC_CTX *mem_ctx,
699 int argc, const char **argv)
701 POLICY_HND pol;
702 WERROR result;
703 fstring printername;
704 const char *valuename;
705 REGISTRY_VALUE value;
707 if (argc != 3) {
708 printf("Usage: %s <printername> <valuename>\n", argv[0]);
709 printf("<printername> of . queries print server\n");
710 return WERR_OK;
712 valuename = argv[2];
714 /* Open a printer handle */
716 if (strncmp(argv[1], ".", sizeof(".")) == 0)
717 fstrcpy(printername, cli->srv_name_slash);
718 else
719 slprintf(printername, sizeof(printername)-1, "%s\\%s",
720 cli->srv_name_slash, argv[1]);
722 /* get a printer handle */
724 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
725 printername,
726 SEC_FLAG_MAXIMUM_ALLOWED,
727 &pol);
728 if (!W_ERROR_IS_OK(result))
729 goto done;
731 /* Get printer info */
733 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
735 if (!W_ERROR_IS_OK(result))
736 goto done;
738 /* Display printer data */
740 fstrcpy(value.valuename, valuename);
741 display_reg_value(value);
744 done:
745 if (is_valid_policy_hnd(&pol))
746 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
748 return result;
751 /****************************************************************************
752 ****************************************************************************/
754 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
755 TALLOC_CTX *mem_ctx,
756 int argc, const char **argv)
758 POLICY_HND pol;
759 WERROR result;
760 NTSTATUS status;
761 fstring printername;
762 const char *valuename, *keyname;
763 REGISTRY_VALUE value;
765 uint32_t type;
766 uint8_t *buffer = NULL;
767 uint32_t offered = 0;
768 uint32_t needed;
770 if (argc != 4) {
771 printf("Usage: %s <printername> <keyname> <valuename>\n",
772 argv[0]);
773 printf("<printername> of . queries print server\n");
774 return WERR_OK;
776 valuename = argv[3];
777 keyname = argv[2];
779 /* Open a printer handle */
781 if (strncmp(argv[1], ".", sizeof(".")) == 0)
782 fstrcpy(printername, cli->srv_name_slash);
783 else
784 slprintf(printername, sizeof(printername)-1, "%s\\%s",
785 cli->srv_name_slash, argv[1]);
787 /* get a printer handle */
789 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
790 printername,
791 SEC_FLAG_MAXIMUM_ALLOWED,
792 &pol);
793 if (!W_ERROR_IS_OK(result))
794 goto done;
796 /* Get printer info */
798 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
799 &pol,
800 keyname,
801 valuename,
802 &type,
803 buffer,
804 offered,
805 &needed,
806 &result);
807 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
808 offered = needed;
809 buffer = talloc_array(mem_ctx, uint8_t, needed);
810 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
811 &pol,
812 keyname,
813 valuename,
814 &type,
815 buffer,
816 offered,
817 &needed,
818 &result);
821 if (!NT_STATUS_IS_OK(status)) {
822 goto done;
825 if (!W_ERROR_IS_OK(result)) {
826 goto done;
830 if (!W_ERROR_IS_OK(result))
831 goto done;
833 /* Display printer data */
835 fstrcpy(value.valuename, valuename);
836 value.type = type;
837 value.size = needed;
838 value.data_p = buffer;
840 display_reg_value(value);
842 done:
843 if (is_valid_policy_hnd(&pol))
844 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
846 return result;
849 /****************************************************************************
850 ****************************************************************************/
852 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
854 if (!r) {
855 return;
858 printf("Printer Driver Info 1:\n");
859 printf("\tDriver Name: [%s]\n\n", r->driver_name);
862 /****************************************************************************
863 ****************************************************************************/
865 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
867 if (!r) {
868 return;
871 printf("Printer Driver Info 2:\n");
872 printf("\tVersion: [%x]\n", r->version);
873 printf("\tDriver Name: [%s]\n", r->driver_name);
874 printf("\tArchitecture: [%s]\n", r->architecture);
875 printf("\tDriver Path: [%s]\n", r->driver_path);
876 printf("\tDatafile: [%s]\n", r->data_file);
877 printf("\tConfigfile: [%s]\n\n", r->config_file);
880 /****************************************************************************
881 ****************************************************************************/
883 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
885 int i;
887 if (!r) {
888 return;
891 printf("Printer Driver Info 3:\n");
892 printf("\tVersion: [%x]\n", r->version);
893 printf("\tDriver Name: [%s]\n", r->driver_name);
894 printf("\tArchitecture: [%s]\n", r->architecture);
895 printf("\tDriver Path: [%s]\n", r->driver_path);
896 printf("\tDatafile: [%s]\n", r->data_file);
897 printf("\tConfigfile: [%s]\n\n", r->config_file);
898 printf("\tHelpfile: [%s]\n\n", r->help_file);
900 for (i=0; r->dependent_files[i] != NULL; i++) {
901 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
904 printf("\n");
906 printf("\tMonitorname: [%s]\n", r->monitor_name);
907 printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
911 /****************************************************************************
912 ****************************************************************************/
914 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
915 TALLOC_CTX *mem_ctx,
916 int argc, const char **argv)
918 POLICY_HND pol;
919 WERROR werror;
920 uint32 info_level = 3;
921 const char *printername;
922 uint32 i;
923 bool success = False;
924 union spoolss_DriverInfo info;
925 uint32_t server_major_version;
926 uint32_t server_minor_version;
928 if ((argc == 1) || (argc > 3))
930 printf("Usage: %s <printername> [level]\n", argv[0]);
931 return WERR_OK;
934 /* get the arguments need to open the printer handle */
936 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
938 if (argc == 3)
939 info_level = atoi(argv[2]);
941 /* Open a printer handle */
943 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
944 printername,
945 PRINTER_ACCESS_USE,
946 &pol);
947 if (!W_ERROR_IS_OK(werror)) {
948 printf("Error opening printer handle for %s!\n", printername);
949 return werror;
952 /* loop through and print driver info level for each architecture */
954 for (i=0; archi_table[i].long_archi!=NULL; i++) {
956 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
957 &pol,
958 archi_table[i].long_archi,
959 info_level,
960 0, /* offered */
961 archi_table[i].version,
963 &info,
964 &server_major_version,
965 &server_minor_version);
966 if (!W_ERROR_IS_OK(werror))
967 continue;
969 /* need at least one success */
971 success = True;
973 printf ("\n[%s]\n", archi_table[i].long_archi);
975 switch (info_level) {
976 case 1:
977 display_print_driver1(&info.info1);
978 break;
979 case 2:
980 display_print_driver2(&info.info2);
981 break;
982 case 3:
983 display_print_driver3(&info.info3);
984 break;
985 default:
986 printf("unknown info level %d\n", info_level);
987 break;
991 /* Cleanup */
993 if (is_valid_policy_hnd(&pol))
994 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
996 if ( success )
997 werror = WERR_OK;
999 return werror;
1002 /****************************************************************************
1003 ****************************************************************************/
1005 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1006 TALLOC_CTX *mem_ctx,
1007 int argc, const char **argv)
1009 WERROR werror = WERR_OK;
1010 uint32_t level = 1;
1011 union spoolss_DriverInfo *info;
1012 uint32_t i, j, count;
1014 if (argc > 2) {
1015 printf("Usage: enumdrivers [level]\n");
1016 return WERR_OK;
1019 if (argc == 2) {
1020 level = atoi(argv[1]);
1024 /* loop through and print driver info level for each architecture */
1025 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1026 /* check to see if we already asked for this architecture string */
1028 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1029 continue;
1032 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1033 cli->srv_name_slash,
1034 archi_table[i].long_archi,
1035 level,
1037 &count,
1038 &info);
1040 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1041 printf("Server does not support environment [%s]\n",
1042 archi_table[i].long_archi);
1043 werror = WERR_OK;
1044 continue;
1047 if (count == 0) {
1048 continue;
1051 if (!W_ERROR_IS_OK(werror)) {
1052 printf("Error getting driver for environment [%s] - %d\n",
1053 archi_table[i].long_archi, W_ERROR_V(werror));
1054 continue;
1057 printf("\n[%s]\n", archi_table[i].long_archi);
1059 switch (level) {
1060 case 1:
1061 for (j=0; j < count; j++) {
1062 display_print_driver1(&info[j].info1);
1064 break;
1065 case 2:
1066 for (j=0; j < count; j++) {
1067 display_print_driver2(&info[j].info2);
1069 break;
1070 case 3:
1071 for (j=0; j < count; j++) {
1072 display_print_driver3(&info[j].info3);
1074 break;
1075 default:
1076 printf("unknown info level %d\n", level);
1077 return WERR_UNKNOWN_LEVEL;
1081 return werror;
1084 /****************************************************************************
1085 ****************************************************************************/
1087 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1089 printf("\tDirectory Name:[%s]\n", r->directory_name);
1092 /****************************************************************************
1093 ****************************************************************************/
1095 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1096 TALLOC_CTX *mem_ctx,
1097 int argc, const char **argv)
1099 WERROR result;
1100 NTSTATUS status;
1101 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1102 DATA_BLOB buffer;
1103 uint32_t offered;
1104 union spoolss_DriverDirectoryInfo info;
1105 uint32_t needed;
1107 if (argc > 2) {
1108 printf("Usage: %s [environment]\n", argv[0]);
1109 return WERR_OK;
1112 /* Get the arguments need to open the printer handle */
1114 if (argc == 2) {
1115 env = argv[1];
1118 /* Get the directory. Only use Info level 1 */
1120 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1121 cli->srv_name_slash,
1122 env,
1124 NULL, /* buffer */
1125 0, /* offered */
1126 NULL, /* info */
1127 &needed,
1128 &result);
1129 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1130 offered = needed;
1131 buffer = data_blob_talloc_zero(mem_ctx, needed);
1133 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1134 cli->srv_name_slash,
1135 env,
1137 &buffer,
1138 offered,
1139 &info,
1140 &needed,
1141 &result);
1144 if (W_ERROR_IS_OK(result)) {
1145 display_printdriverdir_1(&info.info1);
1148 return result;
1151 /****************************************************************************
1152 ****************************************************************************/
1154 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1155 struct spoolss_AddDriverInfo3 *info,
1156 const char *arch)
1159 int i;
1161 for (i=0; archi_table[i].long_archi != NULL; i++)
1163 if (strcmp(arch, archi_table[i].short_archi) == 0)
1165 info->version = archi_table[i].version;
1166 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1167 break;
1171 if (archi_table[i].long_archi == NULL)
1173 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1176 return;
1180 /**************************************************************************
1181 wrapper for strtok to get the next parameter from a delimited list.
1182 Needed to handle the empty parameter string denoted by "NULL"
1183 *************************************************************************/
1185 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1186 const char *delim, const char **dest,
1187 char **saveptr)
1189 char *ptr;
1191 /* get the next token */
1192 ptr = strtok_r(str, delim, saveptr);
1194 /* a string of 'NULL' is used to represent an empty
1195 parameter because two consecutive delimiters
1196 will not return an empty string. See man strtok(3)
1197 for details */
1198 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1199 ptr = NULL;
1202 if (dest != NULL) {
1203 *dest = talloc_strdup(mem_ctx, ptr);
1206 return ptr;
1209 /********************************************************************************
1210 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1211 string in the form of
1212 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1213 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1214 <Default Data Type>:<Comma Separated list of Files>
1215 *******************************************************************************/
1217 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1218 char *args)
1220 char *str, *str2;
1221 int count = 0;
1222 char *saveptr = NULL;
1223 struct spoolss_StringArray *deps;
1224 const char **file_array = NULL;
1225 int i;
1227 /* fill in the UNISTR fields */
1228 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1229 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1230 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1231 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1232 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1233 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1234 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1236 /* <Comma Separated List of Dependent Files> */
1237 /* save the beginning of the string */
1238 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1239 str = str2;
1241 /* begin to strip out each filename */
1242 str = strtok_r(str, ",", &saveptr);
1244 /* no dependent files, we are done */
1245 if (!str) {
1246 return true;
1249 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1250 if (!deps) {
1251 return false;
1254 while (str != NULL) {
1255 add_string_to_array(deps, str, &file_array, &count);
1256 str = strtok_r(NULL, ",", &saveptr);
1259 deps->string = talloc_zero_array(deps, const char *, count + 1);
1260 if (!deps->string) {
1261 return false;
1264 for (i=0; i < count; i++) {
1265 deps->string[i] = file_array[i];
1268 r->dependent_files = deps;
1270 return true;
1273 /****************************************************************************
1274 ****************************************************************************/
1276 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1277 TALLOC_CTX *mem_ctx,
1278 int argc, const char **argv)
1280 WERROR result;
1281 NTSTATUS status;
1282 uint32 level = 3;
1283 struct spoolss_AddDriverInfoCtr info_ctr;
1284 struct spoolss_AddDriverInfo3 info3;
1285 const char *arch;
1286 char *driver_args;
1288 /* parse the command arguments */
1289 if (argc != 3 && argc != 4)
1291 printf ("Usage: %s <Environment> \\\n", argv[0]);
1292 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1293 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1294 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1295 printf ("\t[version]\n");
1297 return WERR_OK;
1300 /* Fill in the spoolss_AddDriverInfo3 struct */
1301 ZERO_STRUCT(info3);
1303 arch = cmd_spoolss_get_short_archi(argv[1]);
1304 if (!arch) {
1305 printf ("Error Unknown architechture [%s]\n", argv[1]);
1306 return WERR_INVALID_PARAM;
1309 set_drv_info_3_env(mem_ctx, &info3, arch);
1311 driver_args = talloc_strdup( mem_ctx, argv[2] );
1312 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1314 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1315 return WERR_INVALID_PARAM;
1318 /* if printer driver version specified, override the default version
1319 * used by the architecture. This allows installation of Windows
1320 * 2000 (version 3) printer drivers. */
1321 if (argc == 4)
1323 info3.version = atoi(argv[3]);
1327 info_ctr.level = level;
1328 info_ctr.info.info3 = &info3;
1330 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1331 cli->srv_name_slash,
1332 &info_ctr,
1333 &result);
1334 if (!NT_STATUS_IS_OK(status)) {
1335 return ntstatus_to_werror(status);
1337 if (W_ERROR_IS_OK(result)) {
1338 printf ("Printer Driver %s successfully installed.\n",
1339 info3.driver_name);
1342 return result;
1346 /****************************************************************************
1347 ****************************************************************************/
1349 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1350 TALLOC_CTX *mem_ctx,
1351 int argc, const char **argv)
1353 WERROR result;
1354 struct spoolss_SetPrinterInfoCtr info_ctr;
1355 struct spoolss_SetPrinterInfo2 info2;
1357 /* parse the command arguments */
1358 if (argc != 5)
1360 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1361 return WERR_OK;
1364 /* Fill in the DRIVER_INFO_2 struct */
1365 ZERO_STRUCT(info2);
1367 info2.printername = argv[1];
1368 info2.drivername = argv[3];
1369 info2.sharename = argv[2];
1370 info2.portname = argv[4];
1371 info2.comment = "Created by rpcclient";
1372 info2.printprocessor = "winprint";
1373 info2.datatype = "RAW";
1374 info2.devmode = NULL;
1375 info2.secdesc = NULL;
1376 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1377 info2.priority = 0;
1378 info2.defaultpriority = 0;
1379 info2.starttime = 0;
1380 info2.untiltime = 0;
1382 /* These three fields must not be used by AddPrinter()
1383 as defined in the MS Platform SDK documentation..
1384 --jerry
1385 info2.status = 0;
1386 info2.cjobs = 0;
1387 info2.averageppm = 0;
1390 info_ctr.level = 2;
1391 info_ctr.info.info2 = &info2;
1393 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1394 &info_ctr);
1395 if (W_ERROR_IS_OK(result))
1396 printf ("Printer %s successfully installed.\n", argv[1]);
1398 return result;
1401 /****************************************************************************
1402 ****************************************************************************/
1404 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1405 TALLOC_CTX *mem_ctx,
1406 int argc, const char **argv)
1408 POLICY_HND pol;
1409 WERROR result;
1410 NTSTATUS status;
1411 uint32 level = 2;
1412 const char *printername;
1413 union spoolss_PrinterInfo info;
1414 struct spoolss_SetPrinterInfoCtr info_ctr;
1415 struct spoolss_DevmodeContainer devmode_ctr;
1416 struct sec_desc_buf secdesc_ctr;
1418 ZERO_STRUCT(devmode_ctr);
1419 ZERO_STRUCT(secdesc_ctr);
1421 /* parse the command arguments */
1422 if (argc != 3)
1424 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1425 return WERR_OK;
1428 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1430 /* Get a printer handle */
1432 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1433 printername,
1434 PRINTER_ALL_ACCESS,
1435 &pol);
1436 if (!W_ERROR_IS_OK(result))
1437 goto done;
1439 /* Get printer info */
1441 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1442 &pol,
1443 level,
1445 &info);
1446 if (!W_ERROR_IS_OK(result)) {
1447 printf ("Unable to retrieve printer information!\n");
1448 goto done;
1451 /* Set the printer driver */
1453 info.info2.drivername = argv[2];
1454 info.info2.devmode = NULL;
1455 info.info2.secdesc = NULL;
1457 info_ctr.level = 2;
1458 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1460 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1461 &pol,
1462 &info_ctr,
1463 &devmode_ctr,
1464 &secdesc_ctr,
1465 0, /* command */
1466 &result);
1467 if (!W_ERROR_IS_OK(result)) {
1468 printf("SetPrinter call failed!\n");
1469 goto done;;
1472 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1474 done:
1475 /* Cleanup */
1477 if (is_valid_policy_hnd(&pol))
1478 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1480 return result;
1484 /****************************************************************************
1485 ****************************************************************************/
1487 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1488 TALLOC_CTX *mem_ctx,
1489 int argc, const char **argv)
1491 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1492 NTSTATUS status;
1494 int i;
1495 int vers = -1;
1497 const char *arch = NULL;
1498 uint32_t delete_flags = 0;
1500 /* parse the command arguments */
1501 if (argc < 2 || argc > 4) {
1502 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1503 return WERR_OK;
1506 if (argc >= 3)
1507 arch = argv[2];
1508 if (argc == 4)
1509 vers = atoi (argv[3]);
1511 if (vers >= 0) {
1512 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1515 /* delete the driver for all architectures */
1516 for (i=0; archi_table[i].long_archi; i++) {
1518 if (arch && !strequal( archi_table[i].long_archi, arch))
1519 continue;
1521 if (vers >= 0 && archi_table[i].version != vers)
1522 continue;
1524 /* make the call to remove the driver */
1525 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1526 cli->srv_name_slash,
1527 archi_table[i].long_archi,
1528 argv[1],
1529 delete_flags,
1530 archi_table[i].version,
1531 &result);
1533 if ( !W_ERROR_IS_OK(result) )
1535 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1536 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1537 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1540 else
1542 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1543 archi_table[i].long_archi, archi_table[i].version);
1544 ret = WERR_OK;
1548 return ret;
1552 /****************************************************************************
1553 ****************************************************************************/
1555 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1556 TALLOC_CTX *mem_ctx,
1557 int argc, const char **argv)
1559 WERROR result = WERR_OK;
1560 NTSTATUS status;
1561 int i;
1563 /* parse the command arguments */
1564 if (argc != 2) {
1565 printf ("Usage: %s <driver>\n", argv[0]);
1566 return WERR_OK;
1569 /* delete the driver for all architectures */
1570 for (i=0; archi_table[i].long_archi; i++) {
1571 /* make the call to remove the driver */
1572 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1573 cli->srv_name_slash,
1574 archi_table[i].long_archi,
1575 argv[1],
1576 &result);
1577 if (!NT_STATUS_IS_OK(status)) {
1578 return result;
1580 if ( !W_ERROR_IS_OK(result) ) {
1581 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1582 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1583 argv[1], archi_table[i].long_archi,
1584 W_ERROR_V(result));
1586 } else {
1587 printf ("Driver %s removed for arch [%s].\n", argv[1],
1588 archi_table[i].long_archi);
1592 return result;
1595 /****************************************************************************
1596 ****************************************************************************/
1598 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1599 TALLOC_CTX *mem_ctx,
1600 int argc, const char **argv)
1602 WERROR result;
1603 NTSTATUS status;
1604 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1605 DATA_BLOB buffer;
1606 uint32_t offered;
1607 union spoolss_PrintProcessorDirectoryInfo info;
1608 uint32_t needed;
1610 /* parse the command arguments */
1611 if (argc > 2) {
1612 printf ("Usage: %s [environment]\n", argv[0]);
1613 return WERR_OK;
1616 if (argc == 2) {
1617 environment = argv[1];
1620 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1621 cli->srv_name_slash,
1622 environment,
1624 NULL, /* buffer */
1625 0, /* offered */
1626 NULL, /* info */
1627 &needed,
1628 &result);
1629 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1630 offered = needed;
1631 buffer = data_blob_talloc_zero(mem_ctx, needed);
1633 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1634 cli->srv_name_slash,
1635 environment,
1637 &buffer,
1638 offered,
1639 &info,
1640 &needed,
1641 &result);
1644 if (W_ERROR_IS_OK(result)) {
1645 printf("%s\n", info.info1.directory_name);
1648 return result;
1651 /****************************************************************************
1652 ****************************************************************************/
1654 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1655 int argc, const char **argv)
1657 POLICY_HND handle;
1658 WERROR werror;
1659 NTSTATUS status;
1660 const char *printername;
1661 union spoolss_AddFormInfo info;
1662 struct spoolss_AddFormInfo1 info1;
1663 struct spoolss_AddFormInfo2 info2;
1664 uint32_t level = 1;
1666 /* Parse the command arguments */
1668 if (argc < 3 || argc > 5) {
1669 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1670 return WERR_OK;
1673 /* Get a printer handle */
1675 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1677 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1678 printername,
1679 PRINTER_ALL_ACCESS,
1680 &handle);
1681 if (!W_ERROR_IS_OK(werror))
1682 goto done;
1684 /* Dummy up some values for the form data */
1686 if (argc == 4) {
1687 level = atoi(argv[3]);
1690 switch (level) {
1691 case 1:
1692 info1.flags = SPOOLSS_FORM_USER;
1693 info1.form_name = argv[2];
1694 info1.size.width = 100;
1695 info1.size.height = 100;
1696 info1.area.left = 0;
1697 info1.area.top = 10;
1698 info1.area.right = 20;
1699 info1.area.bottom = 30;
1701 info.info1 = &info1;
1703 break;
1704 case 2:
1705 info2.flags = SPOOLSS_FORM_USER;
1706 info2.form_name = argv[2];
1707 info2.size.width = 100;
1708 info2.size.height = 100;
1709 info2.area.left = 0;
1710 info2.area.top = 10;
1711 info2.area.right = 20;
1712 info2.area.bottom = 30;
1713 info2.keyword = argv[2];
1714 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
1715 info2.mui_dll = NULL;
1716 info2.ressource_id = 0;
1717 info2.display_name = argv[2];
1718 info2.lang_id = 0;
1720 info.info2 = &info2;
1722 break;
1725 /* Add the form */
1728 status = rpccli_spoolss_AddForm(cli, mem_ctx,
1729 &handle,
1730 level,
1731 info,
1732 &werror);
1734 done:
1735 if (is_valid_policy_hnd(&handle))
1736 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1738 return werror;
1741 /****************************************************************************
1742 ****************************************************************************/
1744 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1745 int argc, const char **argv)
1747 POLICY_HND handle;
1748 WERROR werror;
1749 NTSTATUS status;
1750 const char *printername;
1751 union spoolss_AddFormInfo info;
1752 struct spoolss_AddFormInfo1 info1;
1754 /* Parse the command arguments */
1756 if (argc != 3) {
1757 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1758 return WERR_OK;
1761 /* Get a printer handle */
1763 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1765 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1766 printername,
1767 SEC_FLAG_MAXIMUM_ALLOWED,
1768 &handle);
1769 if (!W_ERROR_IS_OK(werror))
1770 goto done;
1772 /* Dummy up some values for the form data */
1774 info1.flags = SPOOLSS_FORM_PRINTER;
1775 info1.size.width = 100;
1776 info1.size.height = 100;
1777 info1.area.left = 0;
1778 info1.area.top = 1000;
1779 info1.area.right = 2000;
1780 info1.area.bottom = 3000;
1781 info1.form_name = argv[2];
1783 info.info1 = &info1;
1785 /* Set the form */
1787 status = rpccli_spoolss_SetForm(cli, mem_ctx,
1788 &handle,
1789 argv[2],
1791 info,
1792 &werror);
1794 done:
1795 if (is_valid_policy_hnd(&handle))
1796 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1798 return werror;
1801 /****************************************************************************
1802 ****************************************************************************/
1804 static const char *get_form_flag(int form_flag)
1806 switch (form_flag) {
1807 case SPOOLSS_FORM_USER:
1808 return "FORM_USER";
1809 case SPOOLSS_FORM_BUILTIN:
1810 return "FORM_BUILTIN";
1811 case SPOOLSS_FORM_PRINTER:
1812 return "FORM_PRINTER";
1813 default:
1814 return "unknown";
1818 /****************************************************************************
1819 ****************************************************************************/
1821 static void display_form_info1(struct spoolss_FormInfo1 *r)
1823 printf("%s\n" \
1824 "\tflag: %s (%d)\n" \
1825 "\twidth: %d, length: %d\n" \
1826 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1827 r->form_name, get_form_flag(r->flags), r->flags,
1828 r->size.width, r->size.height,
1829 r->area.left, r->area.right,
1830 r->area.top, r->area.bottom);
1833 /****************************************************************************
1834 ****************************************************************************/
1836 static void display_form_info2(struct spoolss_FormInfo2 *r)
1838 printf("%s\n" \
1839 "\tflag: %s (%d)\n" \
1840 "\twidth: %d, length: %d\n" \
1841 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
1842 r->form_name, get_form_flag(r->flags), r->flags,
1843 r->size.width, r->size.height,
1844 r->area.left, r->area.right,
1845 r->area.top, r->area.bottom);
1846 printf("\tkeyword: %s\n", r->keyword);
1847 printf("\tstring_type: 0x%08x\n", r->string_type);
1848 printf("\tmui_dll: %s\n", r->mui_dll);
1849 printf("\tressource_id: 0x%08x\n", r->ressource_id);
1850 printf("\tdisplay_name: %s\n", r->display_name);
1851 printf("\tlang_id: %d\n", r->lang_id);
1852 printf("\n");
1855 /****************************************************************************
1856 ****************************************************************************/
1858 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1859 int argc, const char **argv)
1861 POLICY_HND handle;
1862 WERROR werror;
1863 NTSTATUS status;
1864 const char *printername;
1865 DATA_BLOB buffer;
1866 uint32_t offered = 0;
1867 union spoolss_FormInfo info;
1868 uint32_t needed;
1869 uint32_t level = 1;
1871 /* Parse the command arguments */
1873 if (argc < 3 || argc > 5) {
1874 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1875 return WERR_OK;
1878 /* Get a printer handle */
1880 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1882 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1883 printername,
1884 SEC_FLAG_MAXIMUM_ALLOWED,
1885 &handle);
1886 if (!W_ERROR_IS_OK(werror))
1887 goto done;
1889 if (argc == 4) {
1890 level = atoi(argv[3]);
1893 /* Get the form */
1895 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1896 &handle,
1897 argv[2],
1898 level,
1899 NULL,
1900 offered,
1901 &info,
1902 &needed,
1903 &werror);
1904 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
1905 buffer = data_blob_talloc_zero(mem_ctx, needed);
1906 offered = needed;
1907 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1908 &handle,
1909 argv[2],
1910 level,
1911 &buffer,
1912 offered,
1913 &info,
1914 &needed,
1915 &werror);
1918 if (!NT_STATUS_IS_OK(status)) {
1919 return werror;
1922 switch (level) {
1923 case 1:
1924 display_form_info1(&info.info1);
1925 break;
1926 case 2:
1927 display_form_info2(&info.info2);
1928 break;
1931 done:
1932 if (is_valid_policy_hnd(&handle))
1933 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1935 return werror;
1938 /****************************************************************************
1939 ****************************************************************************/
1941 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1942 TALLOC_CTX *mem_ctx, int argc,
1943 const char **argv)
1945 POLICY_HND handle;
1946 WERROR werror;
1947 NTSTATUS status;
1948 const char *printername;
1950 /* Parse the command arguments */
1952 if (argc != 3) {
1953 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1954 return WERR_OK;
1957 /* Get a printer handle */
1959 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1961 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1962 printername,
1963 SEC_FLAG_MAXIMUM_ALLOWED,
1964 &handle);
1965 if (!W_ERROR_IS_OK(werror))
1966 goto done;
1968 /* Delete the form */
1970 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
1971 &handle,
1972 argv[2],
1973 &werror);
1974 if (!NT_STATUS_IS_OK(status)) {
1975 return ntstatus_to_werror(status);
1978 done:
1979 if (is_valid_policy_hnd(&handle))
1980 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1982 return werror;
1985 /****************************************************************************
1986 ****************************************************************************/
1988 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1989 TALLOC_CTX *mem_ctx, int argc,
1990 const char **argv)
1992 POLICY_HND handle;
1993 WERROR werror;
1994 const char *printername;
1995 uint32 num_forms, level = 1, i;
1996 union spoolss_FormInfo *forms;
1998 /* Parse the command arguments */
2000 if (argc < 2 || argc > 4) {
2001 printf ("Usage: %s <printer> [level]\n", argv[0]);
2002 return WERR_OK;
2005 /* Get a printer handle */
2007 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2009 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2010 printername,
2011 SEC_FLAG_MAXIMUM_ALLOWED,
2012 &handle);
2013 if (!W_ERROR_IS_OK(werror))
2014 goto done;
2016 if (argc == 3) {
2017 level = atoi(argv[2]);
2020 /* Enumerate forms */
2022 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2023 &handle,
2024 level,
2026 &num_forms,
2027 &forms);
2029 if (!W_ERROR_IS_OK(werror))
2030 goto done;
2032 /* Display output */
2034 for (i = 0; i < num_forms; i++) {
2035 switch (level) {
2036 case 1:
2037 display_form_info1(&forms[i].info1);
2038 break;
2039 case 2:
2040 display_form_info2(&forms[i].info2);
2041 break;
2045 done:
2046 if (is_valid_policy_hnd(&handle))
2047 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2049 return werror;
2052 /****************************************************************************
2053 ****************************************************************************/
2055 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2056 TALLOC_CTX *mem_ctx,
2057 int argc, const char **argv)
2059 WERROR result;
2060 const char *printername;
2061 POLICY_HND pol;
2062 union spoolss_PrinterInfo info;
2063 REGISTRY_VALUE value;
2064 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2066 /* parse the command arguments */
2067 if (argc < 5) {
2068 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2069 " <value> <data>\n",
2070 argv[0]);
2071 result = WERR_INVALID_PARAM;
2072 goto done;
2075 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2077 value.type = REG_NONE;
2079 if (strequal(argv[2], "string")) {
2080 value.type = REG_SZ;
2083 if (strequal(argv[2], "binary")) {
2084 value.type = REG_BINARY;
2087 if (strequal(argv[2], "dword")) {
2088 value.type = REG_DWORD;
2091 if (strequal(argv[2], "multistring")) {
2092 value.type = REG_MULTI_SZ;
2095 if (value.type == REG_NONE) {
2096 printf("Unknown data type: %s\n", argv[2]);
2097 result = WERR_INVALID_PARAM;
2098 goto done;
2101 /* get a printer handle */
2103 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2104 printername,
2105 SEC_FLAG_MAXIMUM_ALLOWED,
2106 &pol);
2107 if (!W_ERROR_IS_OK(result))
2108 goto done;
2110 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2111 &pol,
2114 &info);
2115 if (!W_ERROR_IS_OK(result))
2116 goto done;
2118 printf("%s\n", current_timestring(tmp_ctx, True));
2119 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2121 /* Set the printer data */
2123 fstrcpy(value.valuename, argv[3]);
2125 switch (value.type) {
2126 case REG_SZ: {
2127 UNISTR2 data;
2128 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2129 value.size = data.uni_str_len * 2;
2130 if (value.size) {
2131 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2132 value.size);
2133 } else {
2134 value.data_p = NULL;
2136 break;
2138 case REG_DWORD: {
2139 uint32 data = strtoul(argv[4], NULL, 10);
2140 value.size = sizeof(data);
2141 if (sizeof(data)) {
2142 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2143 sizeof(data));
2144 } else {
2145 value.data_p = NULL;
2147 break;
2149 case REG_BINARY: {
2150 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2151 value.data_p = data.data;
2152 value.size = data.length;
2153 break;
2155 case REG_MULTI_SZ: {
2156 int i;
2157 size_t len = 0;
2158 char *p;
2160 for (i=4; i<argc; i++) {
2161 if (strcmp(argv[i], "NULL") == 0) {
2162 argv[i] = "";
2164 len += strlen(argv[i])+1;
2167 value.size = len*2;
2168 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2169 if (value.data_p == NULL) {
2170 result = WERR_NOMEM;
2171 goto done;
2174 p = (char *)value.data_p;
2175 len = value.size;
2176 for (i=4; i<argc; i++) {
2177 size_t l = (strlen(argv[i])+1)*2;
2178 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2179 p += l;
2180 len -= l;
2182 SMB_ASSERT(len == 0);
2183 break;
2185 default:
2186 printf("Unknown data type: %s\n", argv[2]);
2187 result = WERR_INVALID_PARAM;
2188 goto done;
2191 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2193 if (!W_ERROR_IS_OK(result)) {
2194 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2195 goto done;
2197 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2199 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2200 &pol,
2203 &info);
2204 if (!W_ERROR_IS_OK(result))
2205 goto done;
2207 printf("%s\n", current_timestring(tmp_ctx, True));
2208 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2210 done:
2211 /* cleanup */
2212 TALLOC_FREE(tmp_ctx);
2213 if (is_valid_policy_hnd(&pol))
2214 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2216 return result;
2219 /****************************************************************************
2220 ****************************************************************************/
2222 static void display_job_info1(struct spoolss_JobInfo1 *r)
2224 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2225 r->user_name, r->document_name, r->text_status, r->pages_printed,
2226 r->total_pages);
2229 /****************************************************************************
2230 ****************************************************************************/
2232 static void display_job_info2(struct spoolss_JobInfo2 *r)
2234 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2235 r->position, r->job_id,
2236 r->user_name, r->document_name, r->text_status, r->pages_printed,
2237 r->total_pages, r->size);
2240 /****************************************************************************
2241 ****************************************************************************/
2243 static void display_job_info3(struct spoolss_JobInfo3 *r)
2245 printf("jobid[%d], next_jobid[%d]\n",
2246 r->job_id, r->next_job_id);
2249 /****************************************************************************
2250 ****************************************************************************/
2252 static void display_job_info4(struct spoolss_JobInfo4 *r)
2254 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2255 r->position, r->job_id,
2256 r->user_name, r->document_name, r->text_status, r->pages_printed,
2257 r->total_pages, r->size, r->size_high);
2260 /****************************************************************************
2261 ****************************************************************************/
2263 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2264 TALLOC_CTX *mem_ctx, int argc,
2265 const char **argv)
2267 WERROR result;
2268 uint32_t level = 1, count, i;
2269 const char *printername;
2270 POLICY_HND hnd;
2271 union spoolss_JobInfo *info;
2273 if (argc < 2 || argc > 3) {
2274 printf("Usage: %s printername [level]\n", argv[0]);
2275 return WERR_OK;
2278 if (argc == 3) {
2279 level = atoi(argv[2]);
2282 /* Open printer handle */
2284 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2286 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2287 printername,
2288 SEC_FLAG_MAXIMUM_ALLOWED,
2289 &hnd);
2290 if (!W_ERROR_IS_OK(result))
2291 goto done;
2293 /* Enumerate ports */
2295 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2296 &hnd,
2297 0, /* firstjob */
2298 1000, /* numjobs */
2299 level,
2301 &count,
2302 &info);
2303 if (!W_ERROR_IS_OK(result)) {
2304 goto done;
2307 for (i = 0; i < count; i++) {
2308 switch (level) {
2309 case 1:
2310 display_job_info1(&info[i].info1);
2311 break;
2312 case 2:
2313 display_job_info2(&info[i].info2);
2314 break;
2315 default:
2316 d_printf("unknown info level %d\n", level);
2317 break;
2321 done:
2322 if (is_valid_policy_hnd(&hnd)) {
2323 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2326 return result;
2329 /****************************************************************************
2330 ****************************************************************************/
2332 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2333 TALLOC_CTX *mem_ctx, int argc,
2334 const char **argv)
2336 WERROR result;
2337 const char *printername;
2338 struct policy_handle hnd;
2339 uint32_t job_id;
2340 uint32_t level = 1;
2341 union spoolss_JobInfo info;
2343 if (argc < 3 || argc > 4) {
2344 printf("Usage: %s printername job_id [level]\n", argv[0]);
2345 return WERR_OK;
2348 job_id = atoi(argv[2]);
2350 if (argc == 4) {
2351 level = atoi(argv[3]);
2354 /* Open printer handle */
2356 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2358 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2359 printername,
2360 SEC_FLAG_MAXIMUM_ALLOWED,
2361 &hnd);
2362 if (!W_ERROR_IS_OK(result)) {
2363 goto done;
2366 /* Enumerate ports */
2368 result = rpccli_spoolss_getjob(cli, mem_ctx,
2369 &hnd,
2370 job_id,
2371 level,
2373 &info);
2375 if (!W_ERROR_IS_OK(result)) {
2376 goto done;
2379 switch (level) {
2380 case 1:
2381 display_job_info1(&info.info1);
2382 break;
2383 case 2:
2384 display_job_info2(&info.info2);
2385 break;
2386 case 3:
2387 display_job_info3(&info.info3);
2388 break;
2389 case 4:
2390 display_job_info4(&info.info4);
2391 break;
2392 default:
2393 d_printf("unknown info level %d\n", level);
2394 break;
2397 done:
2398 if (is_valid_policy_hnd(&hnd)) {
2399 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2402 return result;
2406 /****************************************************************************
2407 ****************************************************************************/
2409 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2410 TALLOC_CTX *mem_ctx, int argc,
2411 const char **argv)
2413 WERROR result;
2414 uint32 i=0, val_needed, data_needed;
2415 const char *printername;
2416 POLICY_HND hnd;
2418 if (argc != 2) {
2419 printf("Usage: %s printername\n", argv[0]);
2420 return WERR_OK;
2423 /* Open printer handle */
2425 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2427 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2428 printername,
2429 SEC_FLAG_MAXIMUM_ALLOWED,
2430 &hnd);
2431 if (!W_ERROR_IS_OK(result))
2432 goto done;
2434 /* Enumerate data */
2436 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2437 &val_needed, &data_needed,
2438 NULL);
2439 while (W_ERROR_IS_OK(result)) {
2440 REGISTRY_VALUE value;
2441 result = rpccli_spoolss_enumprinterdata(
2442 cli, mem_ctx, &hnd, i++, val_needed,
2443 data_needed, 0, 0, &value);
2444 if (W_ERROR_IS_OK(result))
2445 display_reg_value(value);
2447 if (W_ERROR_V(result) == ERRnomoreitems)
2448 result = W_ERROR(ERRsuccess);
2450 done:
2451 if (is_valid_policy_hnd(&hnd))
2452 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2454 return result;
2457 /****************************************************************************
2458 ****************************************************************************/
2460 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2461 TALLOC_CTX *mem_ctx, int argc,
2462 const char **argv)
2464 WERROR result;
2465 uint32 i;
2466 const char *printername;
2467 const char *keyname = NULL;
2468 POLICY_HND hnd;
2469 REGVAL_CTR *ctr = NULL;
2471 if (argc != 3) {
2472 printf("Usage: %s printername <keyname>\n", argv[0]);
2473 return WERR_OK;
2476 keyname = argv[2];
2478 /* Open printer handle */
2480 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2482 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2483 printername,
2484 SEC_FLAG_MAXIMUM_ALLOWED,
2485 &hnd);
2486 if (!W_ERROR_IS_OK(result))
2487 goto done;
2489 /* Enumerate subkeys */
2491 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2492 return WERR_NOMEM;
2494 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2496 if (!W_ERROR_IS_OK(result))
2497 goto done;
2499 for (i=0; i < ctr->num_values; i++) {
2500 display_reg_value(*(ctr->values[i]));
2503 TALLOC_FREE( ctr );
2505 done:
2506 if (is_valid_policy_hnd(&hnd))
2507 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2509 return result;
2512 /****************************************************************************
2513 ****************************************************************************/
2515 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2516 TALLOC_CTX *mem_ctx, int argc,
2517 const char **argv)
2519 WERROR result;
2520 const char *printername;
2521 const char *keyname = NULL;
2522 POLICY_HND hnd;
2523 uint16 *keylist = NULL, *curkey;
2525 if (argc < 2 || argc > 3) {
2526 printf("Usage: %s printername [keyname]\n", argv[0]);
2527 return WERR_OK;
2530 if (argc == 3)
2531 keyname = argv[2];
2532 else
2533 keyname = "";
2535 /* Open printer handle */
2537 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2539 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2540 printername,
2541 SEC_FLAG_MAXIMUM_ALLOWED,
2542 &hnd);
2543 if (!W_ERROR_IS_OK(result))
2544 goto done;
2546 /* Enumerate subkeys */
2548 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2550 if (!W_ERROR_IS_OK(result))
2551 goto done;
2553 curkey = keylist;
2554 while (*curkey != 0) {
2555 char *subkey = NULL;
2556 rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
2557 STR_TERMINATE);
2558 if (!subkey) {
2559 break;
2561 printf("%s\n", subkey);
2562 curkey += strlen(subkey) + 1;
2565 done:
2567 SAFE_FREE(keylist);
2569 if (is_valid_policy_hnd(&hnd))
2570 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2572 return result;
2575 /****************************************************************************
2576 ****************************************************************************/
2578 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2579 TALLOC_CTX *mem_ctx, int argc,
2580 const char **argv)
2582 const char *printername;
2583 const char *clientname;
2584 POLICY_HND hnd;
2585 WERROR result;
2586 NTSTATUS status;
2587 struct spoolss_NotifyOption option;
2589 if (argc != 2) {
2590 printf("Usage: %s printername\n", argv[0]);
2591 result = WERR_OK;
2592 goto done;
2595 /* Open printer */
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 printf("Error opening %s\n", argv[1]);
2605 goto done;
2608 /* Create spool options */
2610 option.version = 2;
2611 option.count = 2;
2613 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2614 if (option.types == NULL) {
2615 result = WERR_NOMEM;
2616 goto done;
2619 option.types[0].type = PRINTER_NOTIFY_TYPE;
2620 option.types[0].count = 1;
2621 option.types[0].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2622 if (option.types[0].fields == NULL) {
2623 result = WERR_NOMEM;
2624 goto done;
2626 option.types[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2628 option.types[1].type = JOB_NOTIFY_TYPE;
2629 option.types[1].count = 1;
2630 option.types[1].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2631 if (option.types[1].fields == NULL) {
2632 result = WERR_NOMEM;
2633 goto done;
2635 option.types[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2637 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2638 if (!clientname) {
2639 result = WERR_NOMEM;
2640 goto done;
2643 /* Send rffpcnex */
2645 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2646 &hnd,
2649 clientname,
2650 123,
2651 &option,
2652 &result);
2653 if (!W_ERROR_IS_OK(result)) {
2654 printf("Error rffpcnex %s\n", argv[1]);
2655 goto done;
2658 done:
2659 if (is_valid_policy_hnd(&hnd))
2660 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2662 return result;
2665 /****************************************************************************
2666 ****************************************************************************/
2668 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2669 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2671 union spoolss_PrinterInfo info1, info2;
2672 WERROR werror;
2673 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2675 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2676 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2677 hnd1,
2680 &info1);
2681 if ( !W_ERROR_IS_OK(werror) ) {
2682 printf("failed (%s)\n", win_errstr(werror));
2683 talloc_destroy(mem_ctx);
2684 return False;
2686 printf("ok\n");
2688 printf("Retrieving printer properties for %s...", cli2->desthost);
2689 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2690 hnd2,
2693 &info2);
2694 if ( !W_ERROR_IS_OK(werror) ) {
2695 printf("failed (%s)\n", win_errstr(werror));
2696 talloc_destroy(mem_ctx);
2697 return False;
2699 printf("ok\n");
2701 talloc_destroy(mem_ctx);
2703 return True;
2706 /****************************************************************************
2707 ****************************************************************************/
2709 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2710 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2712 union spoolss_PrinterInfo info1, info2;
2713 WERROR werror;
2714 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2715 SEC_DESC *sd1, *sd2;
2716 bool result = True;
2719 printf("Retrieving printer security for %s...", cli1->desthost);
2720 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2721 hnd1,
2724 &info1);
2725 if ( !W_ERROR_IS_OK(werror) ) {
2726 printf("failed (%s)\n", win_errstr(werror));
2727 result = False;
2728 goto done;
2730 printf("ok\n");
2732 printf("Retrieving printer security for %s...", cli2->desthost);
2733 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2734 hnd2,
2737 &info2);
2738 if ( !W_ERROR_IS_OK(werror) ) {
2739 printf("failed (%s)\n", win_errstr(werror));
2740 result = False;
2741 goto done;
2743 printf("ok\n");
2746 printf("++ ");
2748 sd1 = info1.info3.secdesc;
2749 sd2 = info2.info3.secdesc;
2751 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2752 printf("NULL secdesc!\n");
2753 result = False;
2754 goto done;
2757 if (!sec_desc_equal( sd1, sd2 ) ) {
2758 printf("Security Descriptors *not* equal!\n");
2759 result = False;
2760 goto done;
2763 printf("Security descriptors match\n");
2765 done:
2766 talloc_destroy(mem_ctx);
2767 return result;
2771 /****************************************************************************
2772 ****************************************************************************/
2774 extern struct user_auth_info *rpcclient_auth_info;
2776 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2777 TALLOC_CTX *mem_ctx, int argc,
2778 const char **argv)
2780 const char *printername;
2781 char *printername_path = NULL;
2782 struct cli_state *cli_server2 = NULL;
2783 struct rpc_pipe_client *cli2 = NULL;
2784 POLICY_HND hPrinter1, hPrinter2;
2785 NTSTATUS nt_status;
2786 WERROR werror;
2788 if ( argc != 3 ) {
2789 printf("Usage: %s <printer> <server>\n", argv[0]);
2790 return WERR_OK;
2793 printername = argv[1];
2795 /* first get the connection to the remote server */
2797 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2798 NULL, 0,
2799 "IPC$", "IPC",
2800 get_cmdline_auth_info_username(rpcclient_auth_info),
2801 lp_workgroup(),
2802 get_cmdline_auth_info_password(rpcclient_auth_info),
2803 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2804 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2806 if ( !NT_STATUS_IS_OK(nt_status) )
2807 return WERR_GENERAL_FAILURE;
2809 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
2810 &cli2);
2811 if (!NT_STATUS_IS_OK(nt_status)) {
2812 printf("failed to open spoolss pipe on server %s (%s)\n",
2813 argv[2], nt_errstr(nt_status));
2814 return WERR_GENERAL_FAILURE;
2817 /* now open up both printers */
2819 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2821 printf("Opening %s...", printername_path);
2823 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2824 printername_path,
2825 PRINTER_ALL_ACCESS,
2826 &hPrinter1);
2827 if ( !W_ERROR_IS_OK(werror) ) {
2828 printf("failed (%s)\n", win_errstr(werror));
2829 goto done;
2831 printf("ok\n");
2833 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2835 printf("Opening %s...", printername_path);
2836 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2837 printername_path,
2838 PRINTER_ALL_ACCESS,
2839 &hPrinter2);
2840 if ( !W_ERROR_IS_OK(werror) ) {
2841 printf("failed (%s)\n", win_errstr(werror));
2842 goto done;
2844 printf("ok\n");
2846 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2847 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2848 #if 0
2849 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2850 #endif
2853 done:
2854 /* cleanup */
2856 printf("Closing printers...");
2857 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
2858 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
2859 printf("ok\n");
2861 /* close the second remote connection */
2863 cli_shutdown( cli_server2 );
2864 return WERR_OK;
2867 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
2869 printf("print_processor_name: %s\n", r->print_processor_name);
2872 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
2873 TALLOC_CTX *mem_ctx, int argc,
2874 const char **argv)
2876 WERROR werror;
2877 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2878 uint32_t num_procs, level = 1, i;
2879 union spoolss_PrintProcessorInfo *procs;
2881 /* Parse the command arguments */
2883 if (argc < 1 || argc > 4) {
2884 printf ("Usage: %s [environment] [level]\n", argv[0]);
2885 return WERR_OK;
2888 if (argc >= 2) {
2889 environment = argv[1];
2892 if (argc == 3) {
2893 level = atoi(argv[2]);
2896 /* Enumerate Print Processors */
2898 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
2899 cli->srv_name_slash,
2900 environment,
2901 level,
2903 &num_procs,
2904 &procs);
2905 if (!W_ERROR_IS_OK(werror))
2906 goto done;
2908 /* Display output */
2910 for (i = 0; i < num_procs; i++) {
2911 switch (level) {
2912 case 1:
2913 display_proc_info1(&procs[i].info1);
2914 break;
2918 done:
2919 return werror;
2922 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
2924 printf("name_array: %s\n", r->name_array);
2927 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
2928 TALLOC_CTX *mem_ctx, int argc,
2929 const char **argv)
2931 WERROR werror;
2932 const char *print_processor_name = "winprint";
2933 uint32_t num_procs, level = 1, i;
2934 union spoolss_PrintProcDataTypesInfo *procs;
2936 /* Parse the command arguments */
2938 if (argc < 1 || argc > 4) {
2939 printf ("Usage: %s [environment] [level]\n", argv[0]);
2940 return WERR_OK;
2943 if (argc >= 2) {
2944 print_processor_name = argv[1];
2947 if (argc == 3) {
2948 level = atoi(argv[2]);
2951 /* Enumerate Print Processor Data Types */
2953 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
2954 cli->srv_name_slash,
2955 print_processor_name,
2956 level,
2958 &num_procs,
2959 &procs);
2960 if (!W_ERROR_IS_OK(werror))
2961 goto done;
2963 /* Display output */
2965 for (i = 0; i < num_procs; i++) {
2966 switch (level) {
2967 case 1:
2968 display_proc_data_types_info1(&procs[i].info1);
2969 break;
2973 done:
2974 return werror;
2977 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
2979 printf("monitor_name: %s\n", r->monitor_name);
2982 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
2984 printf("monitor_name: %s\n", r->monitor_name);
2985 printf("environment: %s\n", r->environment);
2986 printf("dll_name: %s\n", r->dll_name);
2989 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
2990 TALLOC_CTX *mem_ctx, int argc,
2991 const char **argv)
2993 WERROR werror;
2994 uint32_t count, level = 1, i;
2995 union spoolss_MonitorInfo *info;
2997 /* Parse the command arguments */
2999 if (argc > 2) {
3000 printf("Usage: %s [level]\n", argv[0]);
3001 return WERR_OK;
3004 if (argc == 2) {
3005 level = atoi(argv[1]);
3008 /* Enumerate Print Monitors */
3010 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3011 cli->srv_name_slash,
3012 level,
3014 &count,
3015 &info);
3016 if (!W_ERROR_IS_OK(werror)) {
3017 goto done;
3020 /* Display output */
3022 for (i = 0; i < count; i++) {
3023 switch (level) {
3024 case 1:
3025 display_monitor1(&info[i].info1);
3026 break;
3027 case 2:
3028 display_monitor2(&info[i].info2);
3029 break;
3033 done:
3034 return werror;
3037 /* List of commands exported by this module */
3038 struct cmd_set spoolss_commands[] = {
3040 { "SPOOLSS" },
3042 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &syntax_spoolss, NULL, "Add a print driver", "" },
3043 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &syntax_spoolss, NULL, "Add a printer", "" },
3044 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &syntax_spoolss, NULL, "Delete a printer driver", "" },
3045 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &syntax_spoolss, NULL, "Delete a printer driver with files", "" },
3046 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &syntax_spoolss, NULL, "Enumerate printer data", "" },
3047 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &syntax_spoolss, NULL, "Enumerate printer data for a key", "" },
3048 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &syntax_spoolss, NULL, "Enumerate printer keys", "" },
3049 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &syntax_spoolss, NULL, "Enumerate print jobs", "" },
3050 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &syntax_spoolss, NULL, "Get print job", "" },
3051 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &syntax_spoolss, NULL, "Enumerate printer ports", "" },
3052 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
3053 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &syntax_spoolss, NULL, "Enumerate printers", "" },
3054 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &syntax_spoolss, NULL, "Get print driver data", "" },
3055 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
3056 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &syntax_spoolss, NULL, "Get print driver information", "" },
3057 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &syntax_spoolss, NULL, "Get print driver upload directory", "" },
3058 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &syntax_spoolss, NULL, "Get printer info", "" },
3059 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &syntax_spoolss, NULL, "Open printer handle", "" },
3060 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &syntax_spoolss, NULL, "Set printer driver", "" },
3061 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &syntax_spoolss, NULL, "Get print processor directory", "" },
3062 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &syntax_spoolss, NULL, "Add form", "" },
3063 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &syntax_spoolss, NULL, "Set form", "" },
3064 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &syntax_spoolss, NULL, "Get form", "" },
3065 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &syntax_spoolss, NULL, "Delete form", "" },
3066 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &syntax_spoolss, NULL, "Enumerate forms", "" },
3067 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &syntax_spoolss, NULL, "Set printer comment", "" },
3068 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &syntax_spoolss, NULL, "Set printername", "" },
3069 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &syntax_spoolss, NULL, "Set REG_SZ printer data", "" },
3070 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &syntax_spoolss, NULL, "Rffpcnex test", "" },
3071 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &syntax_spoolss, NULL, "Printer comparison test", "" },
3072 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &syntax_spoolss, NULL, "Enumerate Print Processors", "" },
3073 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &syntax_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
3074 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &syntax_spoolss, NULL, "Enumerate Print Monitors", "" },
3076 { NULL }