packaging(RHEL-CTDB):makerpms.sh: replace source/ by source3/
[Samba.git] / source3 / rpcclient / cmd_spoolss.c
blob8b1a6eac03624a7cf9d64ec9716176b497b855c5
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"
28 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
29 { \
30 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
31 _cli->srv_name_slash, _arg); \
32 W_ERROR_HAVE_NO_MEMORY(_printername); \
35 /* The version int is used by getdrivers. Note that
36 all architecture strings that support mutliple
37 versions must be grouped together since enumdrivers
38 uses this property to prevent issuing multiple
39 enumdriver calls for the same arch */
42 static const struct print_architecture_table_node archi_table[]= {
44 {"Windows 4.0", "WIN40", 0 },
45 {"Windows NT x86", "W32X86", 2 },
46 {"Windows NT x86", "W32X86", 3 },
47 {"Windows NT R4000", "W32MIPS", 2 },
48 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
49 {"Windows NT PowerPC", "W32PPC", 2 },
50 {"Windows IA64", "IA64", 3 },
51 {"Windows x64", "x64", 3 },
52 {NULL, "", -1 }
55 /**
56 * @file
58 * rpcclient module for SPOOLSS rpc pipe.
60 * This generally just parses and checks command lines, and then calls
61 * a cli_spoolss function.
62 **/
64 /****************************************************************************
65 function to do the mapping between the long architecture name and
66 the short one.
67 ****************************************************************************/
69 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
71 int i=-1;
73 DEBUG(107,("Getting architecture dependant directory\n"));
74 do {
75 i++;
76 } while ( (archi_table[i].long_archi!=NULL ) &&
77 StrCaseCmp(long_archi, archi_table[i].long_archi) );
79 if (archi_table[i].long_archi==NULL) {
80 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
81 return NULL;
84 /* this might be client code - but shouldn't this be an fstrcpy etc? */
87 DEBUGADD(108,("index: [%d]\n", i));
88 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
89 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
91 return archi_table[i].short_archi;
94 /****************************************************************************
95 ****************************************************************************/
97 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
98 TALLOC_CTX *mem_ctx,
99 int argc, const char **argv)
101 WERROR werror;
102 struct policy_handle hnd;
104 if (argc != 2) {
105 printf("Usage: %s <printername>\n", argv[0]);
106 return WERR_OK;
109 if (!cli)
110 return WERR_GENERAL_FAILURE;
112 /* Open the printer handle */
114 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
115 argv[1],
116 PRINTER_ALL_ACCESS,
117 &hnd);
118 if (W_ERROR_IS_OK(werror)) {
119 printf("Printer %s opened successfully\n", argv[1]);
120 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
122 if (!W_ERROR_IS_OK(werror)) {
123 printf("Error closing printer handle! (%s)\n",
124 get_dos_error_msg(werror));
128 return werror;
132 /****************************************************************************
133 ****************************************************************************/
135 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
137 if (!r)
138 return;
140 printf("\tprintername:[%s]\n", r->printername);
141 printf("\tservername:[%s]\n", r->servername);
142 printf("\tcjobs:[0x%x]\n", r->cjobs);
143 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
144 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
145 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
146 r->time.day, r->time.day_of_week);
147 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
148 r->time.second, r->time.millisecond);
150 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
151 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
153 printf("\tversion:[0x%x]\n", r->version);
154 printf("\tfree_build:[0x%x]\n", r->free_build);
155 printf("\tspooling:[0x%x]\n", r->spooling);
156 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
157 printf("\tsession_counter:[0x%x]\n", r->session_counter);
158 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
159 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
160 printf("\tjob_error:[0x%x]\n", r->job_error);
161 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
162 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
163 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
164 printf("\tchange_id:[0x%x]\n", r->change_id);
165 printf("\tlast_error: %s\n", win_errstr(r->last_error));
166 printf("\tstatus:[0x%x]\n", r->status);
167 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
168 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
169 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
170 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
171 printf("\tref_ic:[0x%x]\n", r->ref_ic);
172 printf("\treserved2:[0x%x]\n", r->reserved2);
173 printf("\treserved3:[0x%x]\n", r->reserved3);
175 printf("\n");
178 /****************************************************************************
179 ****************************************************************************/
181 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
183 printf("\tflags:[0x%x]\n", r->flags);
184 printf("\tname:[%s]\n", r->name);
185 printf("\tdescription:[%s]\n", r->description);
186 printf("\tcomment:[%s]\n", r->comment);
188 printf("\n");
191 /****************************************************************************
192 ****************************************************************************/
194 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
196 printf("\tservername:[%s]\n", r->servername);
197 printf("\tprintername:[%s]\n", r->printername);
198 printf("\tsharename:[%s]\n", r->sharename);
199 printf("\tportname:[%s]\n", r->portname);
200 printf("\tdrivername:[%s]\n", r->drivername);
201 printf("\tcomment:[%s]\n", r->comment);
202 printf("\tlocation:[%s]\n", r->location);
203 printf("\tsepfile:[%s]\n", r->sepfile);
204 printf("\tprintprocessor:[%s]\n", r->printprocessor);
205 printf("\tdatatype:[%s]\n", r->datatype);
206 printf("\tparameters:[%s]\n", r->parameters);
207 printf("\tattributes:[0x%x]\n", r->attributes);
208 printf("\tpriority:[0x%x]\n", r->priority);
209 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
210 printf("\tstarttime:[0x%x]\n", r->starttime);
211 printf("\tuntiltime:[0x%x]\n", r->untiltime);
212 printf("\tstatus:[0x%x]\n", r->status);
213 printf("\tcjobs:[0x%x]\n", r->cjobs);
214 printf("\taverageppm:[0x%x]\n", r->averageppm);
216 if (r->secdesc)
217 display_sec_desc(r->secdesc);
219 printf("\n");
222 /****************************************************************************
223 ****************************************************************************/
225 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
227 display_sec_desc(r->secdesc);
229 printf("\n");
232 /****************************************************************************
233 ****************************************************************************/
235 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
237 printf("\tservername:[%s]\n", r->servername);
238 printf("\tprintername:[%s]\n", r->printername);
239 printf("\tattributes:[0x%x]\n", r->attributes);
240 printf("\n");
243 /****************************************************************************
244 ****************************************************************************/
246 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
248 printf("\tprintername:[%s]\n", r->printername);
249 printf("\tportname:[%s]\n", r->portname);
250 printf("\tattributes:[0x%x]\n", r->attributes);
251 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
252 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
253 printf("\n");
256 /****************************************************************************
257 ****************************************************************************/
259 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
261 printf("\tstatus:[0x%x]\n", r->status);
262 printf("\n");
265 /****************************************************************************
266 ****************************************************************************/
268 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
270 printf("\tguid:[%s]\n", r->guid);
271 printf("\taction:[0x%x]\n", r->action);
272 printf("\n");
275 /****************************************************************************
276 ****************************************************************************/
278 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
279 TALLOC_CTX *mem_ctx,
280 int argc, const char **argv)
282 WERROR result;
283 uint32_t level = 1;
284 union spoolss_PrinterInfo *info;
285 uint32_t i, count;
286 const char *name;
287 uint32_t flags = PRINTER_ENUM_LOCAL;
289 if (argc > 4) {
290 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
291 return WERR_OK;
294 if (argc >= 2) {
295 level = atoi(argv[1]);
298 if (argc >= 3) {
299 name = argv[2];
300 } else {
301 name = cli->srv_name_slash;
304 if (argc == 4) {
305 flags = atoi(argv[3]);
308 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
309 flags,
310 name,
311 level,
313 &count,
314 &info);
315 if (W_ERROR_IS_OK(result)) {
317 if (!count) {
318 printf ("No printers returned.\n");
319 goto done;
322 for (i = 0; i < count; i++) {
323 switch (level) {
324 case 0:
325 display_print_info0(&info[i].info0);
326 break;
327 case 1:
328 display_print_info1(&info[i].info1);
329 break;
330 case 2:
331 display_print_info2(&info[i].info2);
332 break;
333 case 3:
334 display_print_info3(&info[i].info3);
335 break;
336 case 4:
337 display_print_info4(&info[i].info4);
338 break;
339 case 5:
340 display_print_info5(&info[i].info5);
341 break;
342 case 6:
343 display_print_info6(&info[i].info6);
344 break;
345 default:
346 printf("unknown info level %d\n", level);
347 goto done;
351 done:
353 return result;
356 /****************************************************************************
357 ****************************************************************************/
359 static void display_port_info_1(struct spoolss_PortInfo1 *r)
361 printf("\tPort Name:\t[%s]\n", r->port_name);
364 /****************************************************************************
365 ****************************************************************************/
367 static void display_port_info_2(struct spoolss_PortInfo2 *r)
369 printf("\tPort Name:\t[%s]\n", r->port_name);
370 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
371 printf("\tDescription:\t[%s]\n", r->description);
372 printf("\tPort Type:\t" );
373 if (r->port_type) {
374 int comma = 0; /* hack */
375 printf( "[" );
376 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
377 printf( "Read" );
378 comma = 1;
380 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
381 printf( "%sWrite", comma ? ", " : "" );
382 comma = 1;
384 /* These two have slightly different interpretations
385 on 95/98/ME but I'm disregarding that for now */
386 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
387 printf( "%sRedirected", comma ? ", " : "" );
388 comma = 1;
390 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
391 printf( "%sNet-Attached", comma ? ", " : "" );
393 printf( "]\n" );
394 } else {
395 printf( "[Unset]\n" );
397 printf("\tReserved:\t[%d]\n", r->reserved);
398 printf("\n");
401 /****************************************************************************
402 ****************************************************************************/
404 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
405 TALLOC_CTX *mem_ctx, int argc,
406 const char **argv)
408 WERROR result;
409 uint32_t level = 1;
410 uint32_t count;
411 union spoolss_PortInfo *info;
413 if (argc > 2) {
414 printf("Usage: %s [level]\n", argv[0]);
415 return WERR_OK;
418 if (argc == 2) {
419 level = atoi(argv[1]);
422 /* Enumerate ports */
424 result = rpccli_spoolss_enumports(cli, mem_ctx,
425 cli->srv_name_slash,
426 level,
428 &count,
429 &info);
430 if (W_ERROR_IS_OK(result)) {
431 int i;
433 for (i = 0; i < count; i++) {
434 switch (level) {
435 case 1:
436 display_port_info_1(&info[i].info1);
437 break;
438 case 2:
439 display_port_info_2(&info[i].info2);
440 break;
441 default:
442 printf("unknown info level %d\n", level);
443 break;
448 return result;
451 /****************************************************************************
452 ****************************************************************************/
454 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
455 TALLOC_CTX *mem_ctx,
456 int argc, const char **argv)
458 struct policy_handle pol;
459 WERROR result;
460 NTSTATUS status;
461 uint32_t info_level = 2;
462 union spoolss_PrinterInfo info;
463 struct spoolss_SetPrinterInfoCtr info_ctr;
464 const char *printername, *comment = NULL;
465 struct spoolss_DevmodeContainer devmode_ctr;
466 struct sec_desc_buf secdesc_ctr;
468 if (argc == 1 || argc > 3) {
469 printf("Usage: %s printername comment\n", argv[0]);
471 return WERR_OK;
474 /* Open a printer handle */
475 if (argc == 3) {
476 comment = argv[2];
479 ZERO_STRUCT(devmode_ctr);
480 ZERO_STRUCT(secdesc_ctr);
482 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
484 /* get a printer handle */
485 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
486 printername,
487 PRINTER_ALL_ACCESS,
488 &pol);
489 if (!W_ERROR_IS_OK(result))
490 goto done;
492 /* Get printer info */
493 result = rpccli_spoolss_getprinter(cli, mem_ctx,
494 &pol,
495 info_level,
497 &info);
498 if (!W_ERROR_IS_OK(result))
499 goto done;
502 /* Modify the comment. */
503 info.info2.comment = comment;
504 info.info2.secdesc = NULL;
505 info.info2.devmode = NULL;
507 info_ctr.level = 2;
508 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
510 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
511 &pol,
512 &info_ctr,
513 &devmode_ctr,
514 &secdesc_ctr,
515 0, /* command */
516 &result);
517 if (W_ERROR_IS_OK(result))
518 printf("Success in setting comment.\n");
520 done:
521 if (is_valid_policy_hnd(&pol))
522 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
524 return result;
527 /****************************************************************************
528 ****************************************************************************/
530 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
531 TALLOC_CTX *mem_ctx,
532 int argc, const char **argv)
534 struct policy_handle pol;
535 WERROR result;
536 NTSTATUS status;
537 uint32_t info_level = 2;
538 union spoolss_PrinterInfo info;
539 const char *printername,
540 *new_printername = NULL;
541 struct spoolss_SetPrinterInfoCtr info_ctr;
542 struct spoolss_DevmodeContainer devmode_ctr;
543 struct sec_desc_buf secdesc_ctr;
545 ZERO_STRUCT(devmode_ctr);
546 ZERO_STRUCT(secdesc_ctr);
548 if (argc == 1 || argc > 3) {
549 printf("Usage: %s printername new_printername\n", argv[0]);
551 return WERR_OK;
554 /* Open a printer handle */
555 if (argc == 3) {
556 new_printername = argv[2];
559 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
561 /* get a printer handle */
562 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
563 printername,
564 PRINTER_ALL_ACCESS,
565 &pol);
566 if (!W_ERROR_IS_OK(result))
567 goto done;
569 /* Get printer info */
570 result = rpccli_spoolss_getprinter(cli, mem_ctx,
571 &pol,
572 info_level,
574 &info);
575 if (!W_ERROR_IS_OK(result))
576 goto done;
578 /* Modify the printername. */
579 info.info2.printername = new_printername;
580 info.info2.devmode = NULL;
581 info.info2.secdesc = NULL;
583 info_ctr.level = info_level;
584 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
586 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
587 &pol,
588 &info_ctr,
589 &devmode_ctr,
590 &secdesc_ctr,
591 0, /* command */
592 &result);
593 if (W_ERROR_IS_OK(result))
594 printf("Success in setting printername.\n");
596 done:
597 if (is_valid_policy_hnd(&pol))
598 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
600 return result;
603 /****************************************************************************
604 ****************************************************************************/
606 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
607 TALLOC_CTX *mem_ctx,
608 int argc, const char **argv)
610 struct policy_handle pol;
611 WERROR result;
612 uint32_t level = 1;
613 const char *printername;
614 union spoolss_PrinterInfo info;
616 if (argc == 1 || argc > 3) {
617 printf("Usage: %s <printername> [level]\n", argv[0]);
618 return WERR_OK;
621 /* Open a printer handle */
622 if (argc == 3) {
623 level = atoi(argv[2]);
626 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
628 /* get a printer handle */
630 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
631 printername,
632 SEC_FLAG_MAXIMUM_ALLOWED,
633 &pol);
634 if (!W_ERROR_IS_OK(result)) {
635 goto done;
638 /* Get printer info */
640 result = rpccli_spoolss_getprinter(cli, mem_ctx,
641 &pol,
642 level,
644 &info);
645 if (!W_ERROR_IS_OK(result)) {
646 goto done;
649 /* Display printer info */
650 switch (level) {
651 case 0:
652 display_print_info0(&info.info0);
653 break;
654 case 1:
655 display_print_info1(&info.info1);
656 break;
657 case 2:
658 display_print_info2(&info.info2);
659 break;
660 case 3:
661 display_print_info3(&info.info3);
662 break;
663 case 4:
664 display_print_info4(&info.info4);
665 break;
666 case 5:
667 display_print_info5(&info.info5);
668 break;
669 case 6:
670 display_print_info6(&info.info6);
671 break;
672 case 7:
673 display_print_info7(&info.info7);
674 break;
675 default:
676 printf("unknown info level %d\n", level);
677 break;
679 done:
680 if (is_valid_policy_hnd(&pol)) {
681 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
684 return result;
687 /****************************************************************************
688 ****************************************************************************/
690 static void display_reg_value(struct regval_blob value)
692 const char *text = NULL;
693 DATA_BLOB blob;
695 switch(value.type) {
696 case REG_DWORD:
697 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
698 *((uint32_t *) value.data_p));
699 break;
700 case REG_SZ:
701 blob = data_blob_const(value.data_p, value.size);
702 pull_reg_sz(talloc_tos(), &blob, &text);
703 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
704 break;
705 case REG_BINARY: {
706 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
707 size_t i, len;
708 printf("%s: REG_BINARY:", value.valuename);
709 len = strlen(hex);
710 for (i=0; i<len; i++) {
711 if (hex[i] == '\0') {
712 break;
714 if (i%40 == 0) {
715 putchar('\n');
717 putchar(hex[i]);
719 TALLOC_FREE(hex);
720 putchar('\n');
721 break;
723 case REG_MULTI_SZ: {
724 uint32_t i;
725 const char **values;
726 blob = data_blob_const(value.data_p, value.size);
728 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
729 d_printf("pull_reg_multi_sz failed\n");
730 break;
733 printf("%s: REG_MULTI_SZ: \n", value.valuename);
734 for (i=0; values[i] != NULL; i++) {
735 d_printf("%s\n", values[i]);
737 TALLOC_FREE(values);
738 break;
740 default:
741 printf("%s: unknown type %d\n", value.valuename, value.type);
746 /****************************************************************************
747 ****************************************************************************/
749 static void display_printer_data(const char *v,
750 enum winreg_Type type,
751 union spoolss_PrinterData *r)
753 int i;
755 switch (type) {
756 case REG_DWORD:
757 printf("%s: REG_DWORD: 0x%08x\n", v, r->value);
758 break;
759 case REG_SZ:
760 printf("%s: REG_SZ: %s\n", v, r->string);
761 break;
762 case REG_BINARY: {
763 char *hex = hex_encode_talloc(NULL,
764 r->binary.data, r->binary.length);
765 size_t len;
766 printf("%s: REG_BINARY:", v);
767 len = strlen(hex);
768 for (i=0; i<len; i++) {
769 if (hex[i] == '\0') {
770 break;
772 if (i%40 == 0) {
773 putchar('\n');
775 putchar(hex[i]);
777 TALLOC_FREE(hex);
778 putchar('\n');
779 break;
781 case REG_MULTI_SZ:
782 printf("%s: REG_MULTI_SZ: ", v);
783 for (i=0; r->string_array[i] != NULL; i++) {
784 printf("%s ", r->string_array[i]);
786 printf("\n");
787 break;
788 default:
789 printf("%s: unknown type 0x%02x:\n", v, type);
790 break;
794 /****************************************************************************
795 ****************************************************************************/
797 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
798 TALLOC_CTX *mem_ctx,
799 int argc, const char **argv)
801 struct policy_handle pol;
802 WERROR result;
803 fstring printername;
804 const char *valuename;
805 enum winreg_Type type;
806 union spoolss_PrinterData data;
808 if (argc != 3) {
809 printf("Usage: %s <printername> <valuename>\n", argv[0]);
810 printf("<printername> of . queries print server\n");
811 return WERR_OK;
813 valuename = argv[2];
815 /* Open a printer handle */
817 if (strncmp(argv[1], ".", sizeof(".")) == 0)
818 fstrcpy(printername, cli->srv_name_slash);
819 else
820 slprintf(printername, sizeof(printername)-1, "%s\\%s",
821 cli->srv_name_slash, argv[1]);
823 /* get a printer handle */
825 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
826 printername,
827 SEC_FLAG_MAXIMUM_ALLOWED,
828 &pol);
829 if (!W_ERROR_IS_OK(result))
830 goto done;
832 /* Get printer info */
834 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
835 &pol,
836 valuename,
838 &type,
839 &data);
840 if (!W_ERROR_IS_OK(result))
841 goto done;
843 /* Display printer data */
845 display_printer_data(valuename, type, &data);
847 done:
848 if (is_valid_policy_hnd(&pol))
849 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
851 return result;
854 /****************************************************************************
855 ****************************************************************************/
857 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
858 TALLOC_CTX *mem_ctx,
859 int argc, const char **argv)
861 struct policy_handle pol;
862 WERROR result;
863 NTSTATUS status;
864 fstring printername;
865 const char *valuename, *keyname;
866 struct regval_blob value;
868 enum winreg_Type type;
869 uint8_t *buffer = NULL;
870 uint32_t offered = 0;
871 uint32_t needed;
873 if (argc != 4) {
874 printf("Usage: %s <printername> <keyname> <valuename>\n",
875 argv[0]);
876 printf("<printername> of . queries print server\n");
877 return WERR_OK;
879 valuename = argv[3];
880 keyname = argv[2];
882 /* Open a printer handle */
884 if (strncmp(argv[1], ".", sizeof(".")) == 0)
885 fstrcpy(printername, cli->srv_name_slash);
886 else
887 slprintf(printername, sizeof(printername)-1, "%s\\%s",
888 cli->srv_name_slash, argv[1]);
890 /* get a printer handle */
892 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
893 printername,
894 SEC_FLAG_MAXIMUM_ALLOWED,
895 &pol);
896 if (!W_ERROR_IS_OK(result))
897 goto done;
899 /* Get printer info */
901 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
902 &pol,
903 keyname,
904 valuename,
905 &type,
906 buffer,
907 offered,
908 &needed,
909 &result);
910 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
911 offered = needed;
912 buffer = talloc_array(mem_ctx, uint8_t, needed);
913 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
914 &pol,
915 keyname,
916 valuename,
917 &type,
918 buffer,
919 offered,
920 &needed,
921 &result);
924 if (!NT_STATUS_IS_OK(status)) {
925 goto done;
928 if (!W_ERROR_IS_OK(result)) {
929 goto done;
933 if (!W_ERROR_IS_OK(result))
934 goto done;
936 /* Display printer data */
938 fstrcpy(value.valuename, valuename);
939 value.type = type;
940 value.size = needed;
941 value.data_p = buffer;
943 display_reg_value(value);
945 done:
946 if (is_valid_policy_hnd(&pol))
947 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
949 return result;
952 /****************************************************************************
953 ****************************************************************************/
955 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
957 if (!r) {
958 return;
961 printf("Printer Driver Info 1:\n");
962 printf("\tDriver Name: [%s]\n", r->driver_name);
963 printf("\n");
966 /****************************************************************************
967 ****************************************************************************/
969 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
971 if (!r) {
972 return;
975 printf("Printer Driver Info 2:\n");
976 printf("\tVersion: [%x]\n", r->version);
977 printf("\tDriver Name: [%s]\n", r->driver_name);
978 printf("\tArchitecture: [%s]\n", r->architecture);
979 printf("\tDriver Path: [%s]\n", r->driver_path);
980 printf("\tDatafile: [%s]\n", r->data_file);
981 printf("\tConfigfile: [%s]\n", r->config_file);
982 printf("\n");
985 /****************************************************************************
986 ****************************************************************************/
988 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
990 int i;
992 if (!r) {
993 return;
996 printf("Printer Driver Info 3:\n");
997 printf("\tVersion: [%x]\n", r->version);
998 printf("\tDriver Name: [%s]\n", r->driver_name);
999 printf("\tArchitecture: [%s]\n", r->architecture);
1000 printf("\tDriver Path: [%s]\n", r->driver_path);
1001 printf("\tDatafile: [%s]\n", r->data_file);
1002 printf("\tConfigfile: [%s]\n", r->config_file);
1003 printf("\tHelpfile: [%s]\n", r->help_file);
1005 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1006 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1009 printf("\tMonitorname: [%s]\n", r->monitor_name);
1010 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1011 printf("\n");
1014 /****************************************************************************
1015 ****************************************************************************/
1017 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1019 int i;
1021 if (!r) {
1022 return;
1025 printf("Printer Driver Info 4:\n");
1026 printf("\tVersion: [%x]\n", r->version);
1027 printf("\tDriver Name: [%s]\n", r->driver_name);
1028 printf("\tArchitecture: [%s]\n", r->architecture);
1029 printf("\tDriver Path: [%s]\n", r->driver_path);
1030 printf("\tDatafile: [%s]\n", r->data_file);
1031 printf("\tConfigfile: [%s]\n", r->config_file);
1032 printf("\tHelpfile: [%s]\n", r->help_file);
1034 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1035 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1038 printf("\tMonitorname: [%s]\n", r->monitor_name);
1039 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1041 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1042 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1044 printf("\n");
1047 /****************************************************************************
1048 ****************************************************************************/
1050 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1052 if (!r) {
1053 return;
1056 printf("Printer Driver Info 5:\n");
1057 printf("\tVersion: [%x]\n", r->version);
1058 printf("\tDriver Name: [%s]\n", r->driver_name);
1059 printf("\tArchitecture: [%s]\n", r->architecture);
1060 printf("\tDriver Path: [%s]\n", r->driver_path);
1061 printf("\tDatafile: [%s]\n", r->data_file);
1062 printf("\tConfigfile: [%s]\n", r->config_file);
1063 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1064 printf("\tConfig Version: [0x%x]\n", r->config_version);
1065 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1066 printf("\n");
1069 /****************************************************************************
1070 ****************************************************************************/
1072 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1074 int i;
1076 if (!r) {
1077 return;
1080 printf("Printer Driver Info 6:\n");
1081 printf("\tVersion: [%x]\n", r->version);
1082 printf("\tDriver Name: [%s]\n", r->driver_name);
1083 printf("\tArchitecture: [%s]\n", r->architecture);
1084 printf("\tDriver Path: [%s]\n", r->driver_path);
1085 printf("\tDatafile: [%s]\n", r->data_file);
1086 printf("\tConfigfile: [%s]\n", r->config_file);
1087 printf("\tHelpfile: [%s]\n", r->help_file);
1089 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1090 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1093 printf("\tMonitorname: [%s]\n", r->monitor_name);
1094 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1096 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1097 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1100 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1101 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1102 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1103 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1104 printf("\tHardware ID: [%s]\n", r->hardware_id);
1105 printf("\tProvider: [%s]\n", r->provider);
1107 printf("\n");
1110 /****************************************************************************
1111 ****************************************************************************/
1113 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1115 int i;
1117 if (!r) {
1118 return;
1121 printf("Printer Driver Info 8:\n");
1122 printf("\tVersion: [%x]\n", r->version);
1123 printf("\tDriver Name: [%s]\n", r->driver_name);
1124 printf("\tArchitecture: [%s]\n", r->architecture);
1125 printf("\tDriver Path: [%s]\n", r->driver_path);
1126 printf("\tDatafile: [%s]\n", r->data_file);
1127 printf("\tConfigfile: [%s]\n", r->config_file);
1128 printf("\tHelpfile: [%s]\n", r->help_file);
1129 printf("\tMonitorname: [%s]\n", r->monitor_name);
1130 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1132 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1133 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1136 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1137 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1140 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1141 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1142 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1143 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1144 printf("\tHardware ID: [%s]\n", r->hardware_id);
1145 printf("\tProvider: [%s]\n", r->provider);
1146 printf("\tPrint Processor: [%s]\n", r->print_processor);
1147 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1148 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1149 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1151 printf("\tInf Path: [%s]\n", r->inf_path);
1152 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1153 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1154 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1156 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1157 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1158 (long long unsigned int)r->min_inbox_driver_ver_version);
1160 printf("\n");
1163 /****************************************************************************
1164 ****************************************************************************/
1166 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1167 TALLOC_CTX *mem_ctx,
1168 int argc, const char **argv)
1170 struct policy_handle pol;
1171 WERROR werror;
1172 uint32_t level = 3;
1173 const char *printername;
1174 uint32_t i;
1175 bool success = false;
1176 union spoolss_DriverInfo info;
1177 uint32_t server_major_version;
1178 uint32_t server_minor_version;
1180 if ((argc == 1) || (argc > 3)) {
1181 printf("Usage: %s <printername> [level]\n", argv[0]);
1182 return WERR_OK;
1185 /* get the arguments need to open the printer handle */
1187 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1189 if (argc == 3) {
1190 level = atoi(argv[2]);
1193 /* Open a printer handle */
1195 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1196 printername,
1197 PRINTER_ACCESS_USE,
1198 &pol);
1199 if (!W_ERROR_IS_OK(werror)) {
1200 printf("Error opening printer handle for %s!\n", printername);
1201 return werror;
1204 /* loop through and print driver info level for each architecture */
1206 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1208 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1209 &pol,
1210 archi_table[i].long_archi,
1211 level,
1212 0, /* offered */
1213 archi_table[i].version,
1215 &info,
1216 &server_major_version,
1217 &server_minor_version);
1218 if (!W_ERROR_IS_OK(werror)) {
1219 continue;
1222 /* need at least one success */
1224 success = true;
1226 printf("\n[%s]\n", archi_table[i].long_archi);
1228 switch (level) {
1229 case 1:
1230 display_print_driver1(&info.info1);
1231 break;
1232 case 2:
1233 display_print_driver2(&info.info2);
1234 break;
1235 case 3:
1236 display_print_driver3(&info.info3);
1237 break;
1238 case 4:
1239 display_print_driver4(&info.info4);
1240 break;
1241 case 5:
1242 display_print_driver5(&info.info5);
1243 break;
1244 case 6:
1245 display_print_driver6(&info.info6);
1246 break;
1247 case 8:
1248 display_print_driver8(&info.info8);
1249 break;
1250 default:
1251 printf("unknown info level %d\n", level);
1252 break;
1256 /* Cleanup */
1258 if (is_valid_policy_hnd(&pol)) {
1259 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1262 if (success) {
1263 werror = WERR_OK;
1266 return werror;
1269 /****************************************************************************
1270 ****************************************************************************/
1272 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1273 TALLOC_CTX *mem_ctx,
1274 const char *architecture,
1275 uint32_t level)
1277 WERROR werror;
1278 uint32_t count = 0;
1279 union spoolss_DriverInfo *info = NULL;
1280 uint32_t j;
1282 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1283 cli->srv_name_slash,
1284 architecture,
1285 level,
1287 &count,
1288 &info);
1290 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1291 printf("Server does not support environment [%s]\n",
1292 architecture);
1293 return WERR_OK;
1296 if (count == 0) {
1297 return WERR_OK;
1300 if (!W_ERROR_IS_OK(werror)) {
1301 printf("Error getting driver for environment [%s] - %s\n",
1302 architecture, win_errstr(werror));
1303 return werror;
1306 printf("\n[%s]\n", architecture);
1308 switch (level) {
1309 case 1:
1310 for (j=0; j < count; j++) {
1311 display_print_driver1(&info[j].info1);
1313 break;
1314 case 2:
1315 for (j=0; j < count; j++) {
1316 display_print_driver2(&info[j].info2);
1318 break;
1319 case 3:
1320 for (j=0; j < count; j++) {
1321 display_print_driver3(&info[j].info3);
1323 break;
1324 case 4:
1325 for (j=0; j < count; j++) {
1326 display_print_driver4(&info[j].info4);
1328 break;
1329 case 5:
1330 for (j=0; j < count; j++) {
1331 display_print_driver5(&info[j].info5);
1333 break;
1334 case 6:
1335 for (j=0; j < count; j++) {
1336 display_print_driver6(&info[j].info6);
1338 break;
1339 case 8:
1340 for (j=0; j < count; j++) {
1341 display_print_driver8(&info[j].info8);
1343 break;
1344 default:
1345 printf("unknown info level %d\n", level);
1346 return WERR_UNKNOWN_LEVEL;
1349 return werror;
1352 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1353 TALLOC_CTX *mem_ctx,
1354 int argc, const char **argv)
1356 WERROR werror = WERR_OK;
1357 uint32_t level = 1;
1358 uint32_t i;
1359 const char *architecture = NULL;
1361 if (argc > 3) {
1362 printf("Usage: enumdrivers [level] [architecture]\n");
1363 return WERR_OK;
1366 if (argc >= 2) {
1367 level = atoi(argv[1]);
1370 if (argc == 3) {
1371 architecture = argv[2];
1374 if (architecture) {
1375 return enum_driver_by_architecture(cli, mem_ctx,
1376 architecture,
1377 level);
1380 /* loop through and print driver info level for each architecture */
1381 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1382 /* check to see if we already asked for this architecture string */
1384 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1385 continue;
1388 werror = enum_driver_by_architecture(cli, mem_ctx,
1389 archi_table[i].long_archi,
1390 level);
1391 if (!W_ERROR_IS_OK(werror)) {
1392 break;
1396 return werror;
1399 /****************************************************************************
1400 ****************************************************************************/
1402 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1404 printf("\tDirectory Name:[%s]\n", r->directory_name);
1407 /****************************************************************************
1408 ****************************************************************************/
1410 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1411 TALLOC_CTX *mem_ctx,
1412 int argc, const char **argv)
1414 WERROR result;
1415 NTSTATUS status;
1416 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1417 DATA_BLOB buffer;
1418 uint32_t offered;
1419 union spoolss_DriverDirectoryInfo info;
1420 uint32_t needed;
1422 if (argc > 2) {
1423 printf("Usage: %s [environment]\n", argv[0]);
1424 return WERR_OK;
1427 /* Get the arguments need to open the printer handle */
1429 if (argc == 2) {
1430 env = argv[1];
1433 /* Get the directory. Only use Info level 1 */
1435 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1436 cli->srv_name_slash,
1437 env,
1439 NULL, /* buffer */
1440 0, /* offered */
1441 NULL, /* info */
1442 &needed,
1443 &result);
1444 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1445 offered = needed;
1446 buffer = data_blob_talloc_zero(mem_ctx, needed);
1448 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1449 cli->srv_name_slash,
1450 env,
1452 &buffer,
1453 offered,
1454 &info,
1455 &needed,
1456 &result);
1459 if (W_ERROR_IS_OK(result)) {
1460 display_printdriverdir_1(&info.info1);
1463 return result;
1466 /****************************************************************************
1467 ****************************************************************************/
1469 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1470 struct spoolss_AddDriverInfo3 *info,
1471 const char *arch)
1474 int i;
1476 for (i=0; archi_table[i].long_archi != NULL; i++)
1478 if (strcmp(arch, archi_table[i].short_archi) == 0)
1480 info->version = archi_table[i].version;
1481 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1482 break;
1486 if (archi_table[i].long_archi == NULL)
1488 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1491 return;
1495 /**************************************************************************
1496 wrapper for strtok to get the next parameter from a delimited list.
1497 Needed to handle the empty parameter string denoted by "NULL"
1498 *************************************************************************/
1500 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1501 const char *delim, const char **dest,
1502 char **saveptr)
1504 char *ptr;
1506 /* get the next token */
1507 ptr = strtok_r(str, delim, saveptr);
1509 /* a string of 'NULL' is used to represent an empty
1510 parameter because two consecutive delimiters
1511 will not return an empty string. See man strtok(3)
1512 for details */
1513 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1514 ptr = NULL;
1517 if (dest != NULL) {
1518 *dest = talloc_strdup(mem_ctx, ptr);
1521 return ptr;
1524 /********************************************************************************
1525 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1526 string in the form of
1527 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1528 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1529 <Default Data Type>:<Comma Separated list of Files>
1530 *******************************************************************************/
1532 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1533 char *args)
1535 char *str, *str2;
1536 int count = 0;
1537 char *saveptr = NULL;
1538 struct spoolss_StringArray *deps;
1539 const char **file_array = NULL;
1540 int i;
1542 /* fill in the UNISTR fields */
1543 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1544 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1545 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1546 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1547 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1548 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1549 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1551 /* <Comma Separated List of Dependent Files> */
1552 /* save the beginning of the string */
1553 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1554 str = str2;
1556 /* begin to strip out each filename */
1557 str = strtok_r(str, ",", &saveptr);
1559 /* no dependent files, we are done */
1560 if (!str) {
1561 return true;
1564 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1565 if (!deps) {
1566 return false;
1569 while (str != NULL) {
1570 add_string_to_array(deps, str, &file_array, &count);
1571 str = strtok_r(NULL, ",", &saveptr);
1574 deps->string = talloc_zero_array(deps, const char *, count + 1);
1575 if (!deps->string) {
1576 return false;
1579 for (i=0; i < count; i++) {
1580 deps->string[i] = file_array[i];
1583 r->dependent_files = deps;
1585 return true;
1588 /****************************************************************************
1589 ****************************************************************************/
1591 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1592 TALLOC_CTX *mem_ctx,
1593 int argc, const char **argv)
1595 WERROR result;
1596 NTSTATUS status;
1597 uint32_t level = 3;
1598 struct spoolss_AddDriverInfoCtr info_ctr;
1599 struct spoolss_AddDriverInfo3 info3;
1600 const char *arch;
1601 char *driver_args;
1603 /* parse the command arguments */
1604 if (argc != 3 && argc != 4)
1606 printf ("Usage: %s <Environment> \\\n", argv[0]);
1607 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1608 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1609 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1610 printf ("\t[version]\n");
1612 return WERR_OK;
1615 /* Fill in the spoolss_AddDriverInfo3 struct */
1616 ZERO_STRUCT(info3);
1618 arch = cmd_spoolss_get_short_archi(argv[1]);
1619 if (!arch) {
1620 printf ("Error Unknown architechture [%s]\n", argv[1]);
1621 return WERR_INVALID_PARAM;
1624 set_drv_info_3_env(mem_ctx, &info3, arch);
1626 driver_args = talloc_strdup( mem_ctx, argv[2] );
1627 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1629 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1630 return WERR_INVALID_PARAM;
1633 /* if printer driver version specified, override the default version
1634 * used by the architecture. This allows installation of Windows
1635 * 2000 (version 3) printer drivers. */
1636 if (argc == 4)
1638 info3.version = atoi(argv[3]);
1642 info_ctr.level = level;
1643 info_ctr.info.info3 = &info3;
1645 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1646 cli->srv_name_slash,
1647 &info_ctr,
1648 &result);
1649 if (!NT_STATUS_IS_OK(status)) {
1650 return ntstatus_to_werror(status);
1652 if (W_ERROR_IS_OK(result)) {
1653 printf ("Printer Driver %s successfully installed.\n",
1654 info3.driver_name);
1657 return result;
1661 /****************************************************************************
1662 ****************************************************************************/
1664 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1665 TALLOC_CTX *mem_ctx,
1666 int argc, const char **argv)
1668 WERROR result;
1669 struct spoolss_SetPrinterInfoCtr info_ctr;
1670 struct spoolss_SetPrinterInfo2 info2;
1672 /* parse the command arguments */
1673 if (argc != 5)
1675 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1676 return WERR_OK;
1679 /* Fill in the DRIVER_INFO_2 struct */
1680 ZERO_STRUCT(info2);
1682 info2.printername = argv[1];
1683 info2.drivername = argv[3];
1684 info2.sharename = argv[2];
1685 info2.portname = argv[4];
1686 info2.comment = "Created by rpcclient";
1687 info2.printprocessor = "winprint";
1688 info2.datatype = "RAW";
1689 info2.devmode = NULL;
1690 info2.secdesc = NULL;
1691 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1692 info2.priority = 0;
1693 info2.defaultpriority = 0;
1694 info2.starttime = 0;
1695 info2.untiltime = 0;
1697 /* These three fields must not be used by AddPrinter()
1698 as defined in the MS Platform SDK documentation..
1699 --jerry
1700 info2.status = 0;
1701 info2.cjobs = 0;
1702 info2.averageppm = 0;
1705 info_ctr.level = 2;
1706 info_ctr.info.info2 = &info2;
1708 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1709 &info_ctr);
1710 if (W_ERROR_IS_OK(result))
1711 printf ("Printer %s successfully installed.\n", argv[1]);
1713 return result;
1716 /****************************************************************************
1717 ****************************************************************************/
1719 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1720 TALLOC_CTX *mem_ctx,
1721 int argc, const char **argv)
1723 struct policy_handle pol;
1724 WERROR result;
1725 NTSTATUS status;
1726 uint32_t level = 2;
1727 const char *printername;
1728 union spoolss_PrinterInfo info;
1729 struct spoolss_SetPrinterInfoCtr info_ctr;
1730 struct spoolss_DevmodeContainer devmode_ctr;
1731 struct sec_desc_buf secdesc_ctr;
1733 ZERO_STRUCT(devmode_ctr);
1734 ZERO_STRUCT(secdesc_ctr);
1736 /* parse the command arguments */
1737 if (argc != 3)
1739 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1740 return WERR_OK;
1743 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1745 /* Get a printer handle */
1747 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1748 printername,
1749 PRINTER_ALL_ACCESS,
1750 &pol);
1751 if (!W_ERROR_IS_OK(result))
1752 goto done;
1754 /* Get printer info */
1756 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1757 &pol,
1758 level,
1760 &info);
1761 if (!W_ERROR_IS_OK(result)) {
1762 printf ("Unable to retrieve printer information!\n");
1763 goto done;
1766 /* Set the printer driver */
1768 info.info2.drivername = argv[2];
1769 info.info2.devmode = NULL;
1770 info.info2.secdesc = NULL;
1772 info_ctr.level = 2;
1773 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1775 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1776 &pol,
1777 &info_ctr,
1778 &devmode_ctr,
1779 &secdesc_ctr,
1780 0, /* command */
1781 &result);
1782 if (!W_ERROR_IS_OK(result)) {
1783 printf("SetPrinter call failed!\n");
1784 goto done;;
1787 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1789 done:
1790 /* Cleanup */
1792 if (is_valid_policy_hnd(&pol))
1793 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1795 return result;
1799 /****************************************************************************
1800 ****************************************************************************/
1802 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1803 TALLOC_CTX *mem_ctx,
1804 int argc, const char **argv)
1806 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1807 NTSTATUS status;
1809 int i;
1810 int vers = -1;
1812 const char *arch = NULL;
1813 uint32_t delete_flags = 0;
1815 /* parse the command arguments */
1816 if (argc < 2 || argc > 4) {
1817 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1818 return WERR_OK;
1821 if (argc >= 3)
1822 arch = argv[2];
1823 if (argc == 4)
1824 vers = atoi (argv[3]);
1826 if (vers >= 0) {
1827 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1830 /* delete the driver for all architectures */
1831 for (i=0; archi_table[i].long_archi; i++) {
1833 if (arch && !strequal( archi_table[i].long_archi, arch))
1834 continue;
1836 if (vers >= 0 && archi_table[i].version != vers)
1837 continue;
1839 /* make the call to remove the driver */
1840 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1841 cli->srv_name_slash,
1842 archi_table[i].long_archi,
1843 argv[1],
1844 delete_flags,
1845 archi_table[i].version,
1846 &result);
1848 if ( !W_ERROR_IS_OK(result) )
1850 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1851 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1852 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1855 else
1857 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1858 archi_table[i].long_archi, archi_table[i].version);
1859 ret = WERR_OK;
1863 return ret;
1867 /****************************************************************************
1868 ****************************************************************************/
1870 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1871 TALLOC_CTX *mem_ctx,
1872 int argc, const char **argv)
1874 WERROR result = WERR_OK;
1875 NTSTATUS status;
1876 int i;
1878 /* parse the command arguments */
1879 if (argc != 2) {
1880 printf ("Usage: %s <driver>\n", argv[0]);
1881 return WERR_OK;
1884 /* delete the driver for all architectures */
1885 for (i=0; archi_table[i].long_archi; i++) {
1886 /* make the call to remove the driver */
1887 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1888 cli->srv_name_slash,
1889 archi_table[i].long_archi,
1890 argv[1],
1891 &result);
1892 if (!NT_STATUS_IS_OK(status)) {
1893 return result;
1895 if ( !W_ERROR_IS_OK(result) ) {
1896 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1897 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1898 argv[1], archi_table[i].long_archi,
1899 W_ERROR_V(result));
1901 } else {
1902 printf ("Driver %s removed for arch [%s].\n", argv[1],
1903 archi_table[i].long_archi);
1907 return result;
1910 /****************************************************************************
1911 ****************************************************************************/
1913 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1914 TALLOC_CTX *mem_ctx,
1915 int argc, const char **argv)
1917 WERROR result;
1918 NTSTATUS status;
1919 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1920 DATA_BLOB buffer;
1921 uint32_t offered;
1922 union spoolss_PrintProcessorDirectoryInfo info;
1923 uint32_t needed;
1925 /* parse the command arguments */
1926 if (argc > 2) {
1927 printf ("Usage: %s [environment]\n", argv[0]);
1928 return WERR_OK;
1931 if (argc == 2) {
1932 environment = argv[1];
1935 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1936 cli->srv_name_slash,
1937 environment,
1939 NULL, /* buffer */
1940 0, /* offered */
1941 NULL, /* info */
1942 &needed,
1943 &result);
1944 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1945 offered = needed;
1946 buffer = data_blob_talloc_zero(mem_ctx, needed);
1948 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1949 cli->srv_name_slash,
1950 environment,
1952 &buffer,
1953 offered,
1954 &info,
1955 &needed,
1956 &result);
1959 if (W_ERROR_IS_OK(result)) {
1960 printf("%s\n", info.info1.directory_name);
1963 return result;
1966 /****************************************************************************
1967 ****************************************************************************/
1969 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1970 int argc, const char **argv)
1972 struct policy_handle handle;
1973 WERROR werror;
1974 NTSTATUS status;
1975 const char *printername;
1976 union spoolss_AddFormInfo info;
1977 struct spoolss_AddFormInfo1 info1;
1978 struct spoolss_AddFormInfo2 info2;
1979 uint32_t level = 1;
1981 /* Parse the command arguments */
1983 if (argc < 3 || argc > 5) {
1984 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1985 return WERR_OK;
1988 /* Get a printer handle */
1990 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1992 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1993 printername,
1994 PRINTER_ALL_ACCESS,
1995 &handle);
1996 if (!W_ERROR_IS_OK(werror))
1997 goto done;
1999 /* Dummy up some values for the form data */
2001 if (argc == 4) {
2002 level = atoi(argv[3]);
2005 switch (level) {
2006 case 1:
2007 info1.flags = SPOOLSS_FORM_USER;
2008 info1.form_name = argv[2];
2009 info1.size.width = 100;
2010 info1.size.height = 100;
2011 info1.area.left = 0;
2012 info1.area.top = 10;
2013 info1.area.right = 20;
2014 info1.area.bottom = 30;
2016 info.info1 = &info1;
2018 break;
2019 case 2:
2020 info2.flags = SPOOLSS_FORM_USER;
2021 info2.form_name = argv[2];
2022 info2.size.width = 100;
2023 info2.size.height = 100;
2024 info2.area.left = 0;
2025 info2.area.top = 10;
2026 info2.area.right = 20;
2027 info2.area.bottom = 30;
2028 info2.keyword = argv[2];
2029 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2030 info2.mui_dll = NULL;
2031 info2.ressource_id = 0;
2032 info2.display_name = argv[2];
2033 info2.lang_id = 0;
2035 info.info2 = &info2;
2037 break;
2040 /* Add the form */
2043 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2044 &handle,
2045 level,
2046 info,
2047 &werror);
2049 done:
2050 if (is_valid_policy_hnd(&handle))
2051 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2053 return werror;
2056 /****************************************************************************
2057 ****************************************************************************/
2059 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2060 int argc, const char **argv)
2062 struct policy_handle handle;
2063 WERROR werror;
2064 NTSTATUS status;
2065 const char *printername;
2066 union spoolss_AddFormInfo info;
2067 struct spoolss_AddFormInfo1 info1;
2069 /* Parse the command arguments */
2071 if (argc != 3) {
2072 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2073 return WERR_OK;
2076 /* Get a printer handle */
2078 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2080 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2081 printername,
2082 SEC_FLAG_MAXIMUM_ALLOWED,
2083 &handle);
2084 if (!W_ERROR_IS_OK(werror))
2085 goto done;
2087 /* Dummy up some values for the form data */
2089 info1.flags = SPOOLSS_FORM_PRINTER;
2090 info1.size.width = 100;
2091 info1.size.height = 100;
2092 info1.area.left = 0;
2093 info1.area.top = 1000;
2094 info1.area.right = 2000;
2095 info1.area.bottom = 3000;
2096 info1.form_name = argv[2];
2098 info.info1 = &info1;
2100 /* Set the form */
2102 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2103 &handle,
2104 argv[2],
2106 info,
2107 &werror);
2109 done:
2110 if (is_valid_policy_hnd(&handle))
2111 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2113 return werror;
2116 /****************************************************************************
2117 ****************************************************************************/
2119 static const char *get_form_flag(int form_flag)
2121 switch (form_flag) {
2122 case SPOOLSS_FORM_USER:
2123 return "FORM_USER";
2124 case SPOOLSS_FORM_BUILTIN:
2125 return "FORM_BUILTIN";
2126 case SPOOLSS_FORM_PRINTER:
2127 return "FORM_PRINTER";
2128 default:
2129 return "unknown";
2133 /****************************************************************************
2134 ****************************************************************************/
2136 static void display_form_info1(struct spoolss_FormInfo1 *r)
2138 printf("%s\n" \
2139 "\tflag: %s (%d)\n" \
2140 "\twidth: %d, length: %d\n" \
2141 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2142 r->form_name, get_form_flag(r->flags), r->flags,
2143 r->size.width, r->size.height,
2144 r->area.left, r->area.right,
2145 r->area.top, r->area.bottom);
2148 /****************************************************************************
2149 ****************************************************************************/
2151 static void display_form_info2(struct spoolss_FormInfo2 *r)
2153 printf("%s\n" \
2154 "\tflag: %s (%d)\n" \
2155 "\twidth: %d, length: %d\n" \
2156 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2157 r->form_name, get_form_flag(r->flags), r->flags,
2158 r->size.width, r->size.height,
2159 r->area.left, r->area.right,
2160 r->area.top, r->area.bottom);
2161 printf("\tkeyword: %s\n", r->keyword);
2162 printf("\tstring_type: 0x%08x\n", r->string_type);
2163 printf("\tmui_dll: %s\n", r->mui_dll);
2164 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2165 printf("\tdisplay_name: %s\n", r->display_name);
2166 printf("\tlang_id: %d\n", r->lang_id);
2167 printf("\n");
2170 /****************************************************************************
2171 ****************************************************************************/
2173 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2174 int argc, const char **argv)
2176 struct policy_handle handle;
2177 WERROR werror;
2178 NTSTATUS status;
2179 const char *printername;
2180 DATA_BLOB buffer;
2181 uint32_t offered = 0;
2182 union spoolss_FormInfo info;
2183 uint32_t needed;
2184 uint32_t level = 1;
2186 /* Parse the command arguments */
2188 if (argc < 3 || argc > 5) {
2189 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2190 return WERR_OK;
2193 /* Get a printer handle */
2195 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2197 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2198 printername,
2199 SEC_FLAG_MAXIMUM_ALLOWED,
2200 &handle);
2201 if (!W_ERROR_IS_OK(werror))
2202 goto done;
2204 if (argc == 4) {
2205 level = atoi(argv[3]);
2208 /* Get the form */
2210 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2211 &handle,
2212 argv[2],
2213 level,
2214 NULL,
2215 offered,
2216 &info,
2217 &needed,
2218 &werror);
2219 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2220 buffer = data_blob_talloc_zero(mem_ctx, needed);
2221 offered = needed;
2222 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2223 &handle,
2224 argv[2],
2225 level,
2226 &buffer,
2227 offered,
2228 &info,
2229 &needed,
2230 &werror);
2233 if (!NT_STATUS_IS_OK(status)) {
2234 return werror;
2237 switch (level) {
2238 case 1:
2239 display_form_info1(&info.info1);
2240 break;
2241 case 2:
2242 display_form_info2(&info.info2);
2243 break;
2246 done:
2247 if (is_valid_policy_hnd(&handle))
2248 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2250 return werror;
2253 /****************************************************************************
2254 ****************************************************************************/
2256 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2257 TALLOC_CTX *mem_ctx, int argc,
2258 const char **argv)
2260 struct policy_handle handle;
2261 WERROR werror;
2262 NTSTATUS status;
2263 const char *printername;
2265 /* Parse the command arguments */
2267 if (argc != 3) {
2268 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2269 return WERR_OK;
2272 /* Get a printer handle */
2274 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2276 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2277 printername,
2278 SEC_FLAG_MAXIMUM_ALLOWED,
2279 &handle);
2280 if (!W_ERROR_IS_OK(werror))
2281 goto done;
2283 /* Delete the form */
2285 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2286 &handle,
2287 argv[2],
2288 &werror);
2289 if (!NT_STATUS_IS_OK(status)) {
2290 return ntstatus_to_werror(status);
2293 done:
2294 if (is_valid_policy_hnd(&handle))
2295 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2297 return werror;
2300 /****************************************************************************
2301 ****************************************************************************/
2303 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2304 TALLOC_CTX *mem_ctx, int argc,
2305 const char **argv)
2307 struct policy_handle handle;
2308 WERROR werror;
2309 const char *printername;
2310 uint32_t num_forms, level = 1, i;
2311 union spoolss_FormInfo *forms;
2313 /* Parse the command arguments */
2315 if (argc < 2 || argc > 4) {
2316 printf ("Usage: %s <printer> [level]\n", argv[0]);
2317 return WERR_OK;
2320 /* Get a printer handle */
2322 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2324 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2325 printername,
2326 SEC_FLAG_MAXIMUM_ALLOWED,
2327 &handle);
2328 if (!W_ERROR_IS_OK(werror))
2329 goto done;
2331 if (argc == 3) {
2332 level = atoi(argv[2]);
2335 /* Enumerate forms */
2337 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2338 &handle,
2339 level,
2341 &num_forms,
2342 &forms);
2344 if (!W_ERROR_IS_OK(werror))
2345 goto done;
2347 /* Display output */
2349 for (i = 0; i < num_forms; i++) {
2350 switch (level) {
2351 case 1:
2352 display_form_info1(&forms[i].info1);
2353 break;
2354 case 2:
2355 display_form_info2(&forms[i].info2);
2356 break;
2360 done:
2361 if (is_valid_policy_hnd(&handle))
2362 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2364 return werror;
2367 /****************************************************************************
2368 ****************************************************************************/
2370 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2371 TALLOC_CTX *mem_ctx,
2372 int argc, const char **argv)
2374 WERROR result;
2375 NTSTATUS status;
2376 const char *printername;
2377 struct policy_handle pol;
2378 union spoolss_PrinterInfo info;
2379 enum winreg_Type type;
2380 union spoolss_PrinterData data;
2382 /* parse the command arguments */
2383 if (argc < 5) {
2384 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2385 " <value> <data>\n",
2386 argv[0]);
2387 result = WERR_INVALID_PARAM;
2388 goto done;
2391 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2393 type = REG_NONE;
2395 if (strequal(argv[2], "string")) {
2396 type = REG_SZ;
2399 if (strequal(argv[2], "binary")) {
2400 type = REG_BINARY;
2403 if (strequal(argv[2], "dword")) {
2404 type = REG_DWORD;
2407 if (strequal(argv[2], "multistring")) {
2408 type = REG_MULTI_SZ;
2411 if (type == REG_NONE) {
2412 printf("Unknown data type: %s\n", argv[2]);
2413 result = WERR_INVALID_PARAM;
2414 goto done;
2417 /* get a printer handle */
2419 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2420 printername,
2421 SEC_FLAG_MAXIMUM_ALLOWED,
2422 &pol);
2423 if (!W_ERROR_IS_OK(result)) {
2424 goto done;
2427 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2428 &pol,
2431 &info);
2432 if (!W_ERROR_IS_OK(result)) {
2433 goto done;
2436 printf("%s\n", current_timestring(mem_ctx, true));
2437 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2439 /* Set the printer data */
2441 switch (type) {
2442 case REG_SZ:
2443 data.string = talloc_strdup(mem_ctx, argv[4]);
2444 W_ERROR_HAVE_NO_MEMORY(data.string);
2445 break;
2446 case REG_DWORD:
2447 data.value = strtoul(argv[4], NULL, 10);
2448 break;
2449 case REG_BINARY:
2450 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2451 break;
2452 case REG_MULTI_SZ: {
2453 int i, num_strings;
2454 const char **strings = NULL;
2456 for (i=4; i<argc; i++) {
2457 if (strcmp(argv[i], "NULL") == 0) {
2458 argv[i] = "";
2460 if (!add_string_to_array(mem_ctx, argv[i],
2461 &strings,
2462 &num_strings)) {
2463 result = WERR_NOMEM;
2464 goto done;
2467 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2468 if (!data.string_array) {
2469 result = WERR_NOMEM;
2470 goto done;
2472 for (i=0; i < num_strings; i++) {
2473 data.string_array[i] = strings[i];
2475 break;
2477 default:
2478 printf("Unknown data type: %s\n", argv[2]);
2479 result = WERR_INVALID_PARAM;
2480 goto done;
2483 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2484 &pol,
2485 argv[3], /* value_name */
2486 type,
2487 data,
2488 0, /* autocalculated size */
2489 &result);
2490 if (!W_ERROR_IS_OK(result)) {
2491 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2492 goto done;
2494 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2496 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2497 &pol,
2500 &info);
2501 if (!W_ERROR_IS_OK(result)) {
2502 goto done;
2505 printf("%s\n", current_timestring(mem_ctx, true));
2506 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2508 done:
2509 /* cleanup */
2510 if (is_valid_policy_hnd(&pol)) {
2511 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2514 return result;
2517 /****************************************************************************
2518 ****************************************************************************/
2520 static void display_job_info1(struct spoolss_JobInfo1 *r)
2522 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2523 r->user_name, r->document_name, r->text_status, r->pages_printed,
2524 r->total_pages);
2527 /****************************************************************************
2528 ****************************************************************************/
2530 static void display_job_info2(struct spoolss_JobInfo2 *r)
2532 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2533 r->position, r->job_id,
2534 r->user_name, r->document_name, r->text_status, r->pages_printed,
2535 r->total_pages, r->size);
2538 /****************************************************************************
2539 ****************************************************************************/
2541 static void display_job_info3(struct spoolss_JobInfo3 *r)
2543 printf("jobid[%d], next_jobid[%d]\n",
2544 r->job_id, r->next_job_id);
2547 /****************************************************************************
2548 ****************************************************************************/
2550 static void display_job_info4(struct spoolss_JobInfo4 *r)
2552 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2553 r->position, r->job_id,
2554 r->user_name, r->document_name, r->text_status, r->pages_printed,
2555 r->total_pages, r->size, r->size_high);
2558 /****************************************************************************
2559 ****************************************************************************/
2561 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2562 TALLOC_CTX *mem_ctx, int argc,
2563 const char **argv)
2565 WERROR result;
2566 uint32_t level = 1, count, i;
2567 const char *printername;
2568 struct policy_handle hnd;
2569 union spoolss_JobInfo *info;
2571 if (argc < 2 || argc > 3) {
2572 printf("Usage: %s printername [level]\n", argv[0]);
2573 return WERR_OK;
2576 if (argc == 3) {
2577 level = atoi(argv[2]);
2580 /* Open printer handle */
2582 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2584 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2585 printername,
2586 SEC_FLAG_MAXIMUM_ALLOWED,
2587 &hnd);
2588 if (!W_ERROR_IS_OK(result))
2589 goto done;
2591 /* Enumerate ports */
2593 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2594 &hnd,
2595 0, /* firstjob */
2596 1000, /* numjobs */
2597 level,
2599 &count,
2600 &info);
2601 if (!W_ERROR_IS_OK(result)) {
2602 goto done;
2605 for (i = 0; i < count; i++) {
2606 switch (level) {
2607 case 1:
2608 display_job_info1(&info[i].info1);
2609 break;
2610 case 2:
2611 display_job_info2(&info[i].info2);
2612 break;
2613 default:
2614 d_printf("unknown info level %d\n", level);
2615 break;
2619 done:
2620 if (is_valid_policy_hnd(&hnd)) {
2621 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2624 return result;
2627 /****************************************************************************
2628 ****************************************************************************/
2630 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2631 TALLOC_CTX *mem_ctx, int argc,
2632 const char **argv)
2634 WERROR result;
2635 const char *printername;
2636 struct policy_handle hnd;
2637 uint32_t job_id;
2638 uint32_t level = 1;
2639 union spoolss_JobInfo info;
2641 if (argc < 3 || argc > 4) {
2642 printf("Usage: %s printername job_id [level]\n", argv[0]);
2643 return WERR_OK;
2646 job_id = atoi(argv[2]);
2648 if (argc == 4) {
2649 level = atoi(argv[3]);
2652 /* Open printer handle */
2654 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2656 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2657 printername,
2658 SEC_FLAG_MAXIMUM_ALLOWED,
2659 &hnd);
2660 if (!W_ERROR_IS_OK(result)) {
2661 goto done;
2664 /* Enumerate ports */
2666 result = rpccli_spoolss_getjob(cli, mem_ctx,
2667 &hnd,
2668 job_id,
2669 level,
2671 &info);
2673 if (!W_ERROR_IS_OK(result)) {
2674 goto done;
2677 switch (level) {
2678 case 1:
2679 display_job_info1(&info.info1);
2680 break;
2681 case 2:
2682 display_job_info2(&info.info2);
2683 break;
2684 case 3:
2685 display_job_info3(&info.info3);
2686 break;
2687 case 4:
2688 display_job_info4(&info.info4);
2689 break;
2690 default:
2691 d_printf("unknown info level %d\n", level);
2692 break;
2695 done:
2696 if (is_valid_policy_hnd(&hnd)) {
2697 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2700 return result;
2703 /****************************************************************************
2704 ****************************************************************************/
2706 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2707 TALLOC_CTX *mem_ctx, int argc,
2708 const char **argv)
2710 WERROR result;
2711 NTSTATUS status;
2712 const char *printername;
2713 struct policy_handle hnd;
2714 uint32_t job_id;
2715 enum spoolss_JobControl command;
2717 if (argc != 4) {
2718 printf("Usage: %s printername job_id command\n", argv[0]);
2719 return WERR_OK;
2722 job_id = atoi(argv[2]);
2723 command = atoi(argv[3]);
2725 /* Open printer handle */
2727 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2729 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2730 printername,
2731 SEC_FLAG_MAXIMUM_ALLOWED,
2732 &hnd);
2733 if (!W_ERROR_IS_OK(result)) {
2734 goto done;
2737 /* Set Job */
2739 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2740 &hnd,
2741 job_id,
2742 NULL,
2743 command,
2744 &result);
2746 if (!W_ERROR_IS_OK(result)) {
2747 goto done;
2750 done:
2751 if (is_valid_policy_hnd(&hnd)) {
2752 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2755 return result;
2758 /****************************************************************************
2759 ****************************************************************************/
2761 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2762 TALLOC_CTX *mem_ctx, int argc,
2763 const char **argv)
2765 WERROR result;
2766 NTSTATUS status;
2767 uint32_t i = 0;
2768 const char *printername;
2769 struct policy_handle hnd;
2770 uint32_t value_offered = 0;
2771 const char *value_name = NULL;
2772 uint32_t value_needed;
2773 enum winreg_Type type;
2774 uint8_t *data = NULL;
2775 uint32_t data_offered = 0;
2776 uint32_t data_needed;
2778 if (argc != 2) {
2779 printf("Usage: %s printername\n", argv[0]);
2780 return WERR_OK;
2783 /* Open printer handle */
2785 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2787 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2788 printername,
2789 SEC_FLAG_MAXIMUM_ALLOWED,
2790 &hnd);
2791 if (!W_ERROR_IS_OK(result)) {
2792 goto done;
2795 /* Enumerate data */
2797 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2798 &hnd,
2800 value_name,
2801 value_offered,
2802 &value_needed,
2803 &type,
2804 data,
2805 data_offered,
2806 &data_needed,
2807 &result);
2809 data_offered = data_needed;
2810 value_offered = value_needed;
2811 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2812 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2814 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2816 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2817 &hnd,
2818 i++,
2819 value_name,
2820 value_offered,
2821 &value_needed,
2822 &type,
2823 data,
2824 data_offered,
2825 &data_needed,
2826 &result);
2827 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2828 struct regval_blob v;
2829 fstrcpy(v.valuename, value_name);
2830 v.type = type;
2831 v.size = data_offered;
2832 v.data_p = data;
2833 display_reg_value(v);
2837 if (W_ERROR_V(result) == ERRnomoreitems) {
2838 result = W_ERROR(ERRsuccess);
2841 done:
2842 if (is_valid_policy_hnd(&hnd)) {
2843 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2846 return result;
2849 /****************************************************************************
2850 ****************************************************************************/
2852 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2853 TALLOC_CTX *mem_ctx, int argc,
2854 const char **argv)
2856 WERROR result;
2857 uint32_t i;
2858 const char *printername;
2859 struct policy_handle hnd;
2860 uint32_t count;
2861 struct spoolss_PrinterEnumValues *info;
2863 if (argc != 3) {
2864 printf("Usage: %s printername <keyname>\n", argv[0]);
2865 return WERR_OK;
2868 /* Open printer handle */
2870 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2872 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2873 printername,
2874 SEC_FLAG_MAXIMUM_ALLOWED,
2875 &hnd);
2876 if (!W_ERROR_IS_OK(result)) {
2877 goto done;
2880 /* Enumerate subkeys */
2882 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2883 &hnd,
2884 argv[2],
2886 &count,
2887 &info);
2888 if (!W_ERROR_IS_OK(result)) {
2889 goto done;
2892 for (i=0; i < count; i++) {
2893 display_printer_data(info[i].value_name,
2894 info[i].type,
2895 info[i].data);
2898 done:
2899 if (is_valid_policy_hnd(&hnd)) {
2900 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2903 return result;
2906 /****************************************************************************
2907 ****************************************************************************/
2909 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2910 TALLOC_CTX *mem_ctx, int argc,
2911 const char **argv)
2913 WERROR result;
2914 const char *printername;
2915 const char *keyname = NULL;
2916 struct policy_handle hnd;
2917 const char **key_buffer = NULL;
2918 int i;
2920 if (argc < 2 || argc > 3) {
2921 printf("Usage: %s printername [keyname]\n", argv[0]);
2922 return WERR_OK;
2925 if (argc == 3) {
2926 keyname = argv[2];
2927 } else {
2928 keyname = "";
2931 /* Open printer handle */
2933 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2935 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2936 printername,
2937 SEC_FLAG_MAXIMUM_ALLOWED,
2938 &hnd);
2939 if (!W_ERROR_IS_OK(result)) {
2940 goto done;
2943 /* Enumerate subkeys */
2945 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
2946 &hnd,
2947 keyname,
2948 &key_buffer,
2951 if (!W_ERROR_IS_OK(result)) {
2952 goto done;
2955 for (i=0; key_buffer && key_buffer[i]; i++) {
2956 printf("%s\n", key_buffer[i]);
2959 done:
2961 if (is_valid_policy_hnd(&hnd)) {
2962 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2965 return result;
2968 /****************************************************************************
2969 ****************************************************************************/
2971 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2972 TALLOC_CTX *mem_ctx, int argc,
2973 const char **argv)
2975 const char *printername;
2976 const char *clientname;
2977 struct policy_handle hnd;
2978 WERROR result;
2979 NTSTATUS status;
2980 struct spoolss_NotifyOption option;
2982 if (argc != 2) {
2983 printf("Usage: %s printername\n", argv[0]);
2984 result = WERR_OK;
2985 goto done;
2988 /* Open printer */
2990 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2992 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2993 printername,
2994 SEC_FLAG_MAXIMUM_ALLOWED,
2995 &hnd);
2996 if (!W_ERROR_IS_OK(result)) {
2997 printf("Error opening %s\n", argv[1]);
2998 goto done;
3001 /* Create spool options */
3003 option.version = 2;
3004 option.count = 2;
3006 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3007 if (option.types == NULL) {
3008 result = WERR_NOMEM;
3009 goto done;
3012 option.types[0].type = PRINTER_NOTIFY_TYPE;
3013 option.types[0].count = 1;
3014 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3015 if (option.types[0].fields == NULL) {
3016 result = WERR_NOMEM;
3017 goto done;
3019 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3021 option.types[1].type = JOB_NOTIFY_TYPE;
3022 option.types[1].count = 1;
3023 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3024 if (option.types[1].fields == NULL) {
3025 result = WERR_NOMEM;
3026 goto done;
3028 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3030 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3031 if (!clientname) {
3032 result = WERR_NOMEM;
3033 goto done;
3036 /* Send rffpcnex */
3038 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3039 &hnd,
3042 clientname,
3043 123,
3044 &option,
3045 &result);
3046 if (!W_ERROR_IS_OK(result)) {
3047 printf("Error rffpcnex %s\n", argv[1]);
3048 goto done;
3051 done:
3052 if (is_valid_policy_hnd(&hnd))
3053 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3055 return result;
3058 /****************************************************************************
3059 ****************************************************************************/
3061 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3062 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3064 union spoolss_PrinterInfo info1, info2;
3065 WERROR werror;
3066 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3068 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3069 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3070 hnd1,
3073 &info1);
3074 if ( !W_ERROR_IS_OK(werror) ) {
3075 printf("failed (%s)\n", win_errstr(werror));
3076 talloc_destroy(mem_ctx);
3077 return false;
3079 printf("ok\n");
3081 printf("Retrieving printer properties for %s...", cli2->desthost);
3082 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3083 hnd2,
3086 &info2);
3087 if ( !W_ERROR_IS_OK(werror) ) {
3088 printf("failed (%s)\n", win_errstr(werror));
3089 talloc_destroy(mem_ctx);
3090 return false;
3092 printf("ok\n");
3094 talloc_destroy(mem_ctx);
3096 return true;
3099 /****************************************************************************
3100 ****************************************************************************/
3102 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3103 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3105 union spoolss_PrinterInfo info1, info2;
3106 WERROR werror;
3107 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3108 SEC_DESC *sd1, *sd2;
3109 bool result = true;
3112 printf("Retrieving printer security for %s...", cli1->desthost);
3113 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3114 hnd1,
3117 &info1);
3118 if ( !W_ERROR_IS_OK(werror) ) {
3119 printf("failed (%s)\n", win_errstr(werror));
3120 result = false;
3121 goto done;
3123 printf("ok\n");
3125 printf("Retrieving printer security for %s...", cli2->desthost);
3126 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3127 hnd2,
3130 &info2);
3131 if ( !W_ERROR_IS_OK(werror) ) {
3132 printf("failed (%s)\n", win_errstr(werror));
3133 result = false;
3134 goto done;
3136 printf("ok\n");
3139 printf("++ ");
3141 sd1 = info1.info3.secdesc;
3142 sd2 = info2.info3.secdesc;
3144 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3145 printf("NULL secdesc!\n");
3146 result = false;
3147 goto done;
3150 if (!security_descriptor_equal( sd1, sd2 ) ) {
3151 printf("Security Descriptors *not* equal!\n");
3152 result = false;
3153 goto done;
3156 printf("Security descriptors match\n");
3158 done:
3159 talloc_destroy(mem_ctx);
3160 return result;
3164 /****************************************************************************
3165 ****************************************************************************/
3167 extern struct user_auth_info *rpcclient_auth_info;
3169 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3170 TALLOC_CTX *mem_ctx, int argc,
3171 const char **argv)
3173 const char *printername;
3174 char *printername_path = NULL;
3175 struct cli_state *cli_server2 = NULL;
3176 struct rpc_pipe_client *cli2 = NULL;
3177 struct policy_handle hPrinter1, hPrinter2;
3178 NTSTATUS nt_status;
3179 WERROR werror;
3181 if ( argc != 3 ) {
3182 printf("Usage: %s <printer> <server>\n", argv[0]);
3183 return WERR_OK;
3186 printername = argv[1];
3188 /* first get the connection to the remote server */
3190 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3191 NULL, 0,
3192 "IPC$", "IPC",
3193 get_cmdline_auth_info_username(rpcclient_auth_info),
3194 lp_workgroup(),
3195 get_cmdline_auth_info_password(rpcclient_auth_info),
3196 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3197 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3199 if ( !NT_STATUS_IS_OK(nt_status) )
3200 return WERR_GENERAL_FAILURE;
3202 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3203 &cli2);
3204 if (!NT_STATUS_IS_OK(nt_status)) {
3205 printf("failed to open spoolss pipe on server %s (%s)\n",
3206 argv[2], nt_errstr(nt_status));
3207 return WERR_GENERAL_FAILURE;
3210 /* now open up both printers */
3212 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3214 printf("Opening %s...", printername_path);
3216 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3217 printername_path,
3218 PRINTER_ALL_ACCESS,
3219 &hPrinter1);
3220 if ( !W_ERROR_IS_OK(werror) ) {
3221 printf("failed (%s)\n", win_errstr(werror));
3222 goto done;
3224 printf("ok\n");
3226 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3228 printf("Opening %s...", printername_path);
3229 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3230 printername_path,
3231 PRINTER_ALL_ACCESS,
3232 &hPrinter2);
3233 if ( !W_ERROR_IS_OK(werror) ) {
3234 printf("failed (%s)\n", win_errstr(werror));
3235 goto done;
3237 printf("ok\n");
3239 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3240 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3241 #if 0
3242 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3243 #endif
3246 done:
3247 /* cleanup */
3249 printf("Closing printers...");
3250 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3251 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3252 printf("ok\n");
3254 /* close the second remote connection */
3256 cli_shutdown( cli_server2 );
3257 return WERR_OK;
3260 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3262 printf("print_processor_name: %s\n", r->print_processor_name);
3265 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3266 TALLOC_CTX *mem_ctx, int argc,
3267 const char **argv)
3269 WERROR werror;
3270 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3271 uint32_t num_procs, level = 1, i;
3272 union spoolss_PrintProcessorInfo *procs;
3274 /* Parse the command arguments */
3276 if (argc < 1 || argc > 4) {
3277 printf ("Usage: %s [environment] [level]\n", argv[0]);
3278 return WERR_OK;
3281 if (argc >= 2) {
3282 environment = argv[1];
3285 if (argc == 3) {
3286 level = atoi(argv[2]);
3289 /* Enumerate Print Processors */
3291 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3292 cli->srv_name_slash,
3293 environment,
3294 level,
3296 &num_procs,
3297 &procs);
3298 if (!W_ERROR_IS_OK(werror))
3299 goto done;
3301 /* Display output */
3303 for (i = 0; i < num_procs; i++) {
3304 switch (level) {
3305 case 1:
3306 display_proc_info1(&procs[i].info1);
3307 break;
3311 done:
3312 return werror;
3315 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3317 printf("name_array: %s\n", r->name_array);
3320 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3321 TALLOC_CTX *mem_ctx, int argc,
3322 const char **argv)
3324 WERROR werror;
3325 const char *print_processor_name = "winprint";
3326 uint32_t num_procs, level = 1, i;
3327 union spoolss_PrintProcDataTypesInfo *procs;
3329 /* Parse the command arguments */
3331 if (argc < 1 || argc > 4) {
3332 printf ("Usage: %s [environment] [level]\n", argv[0]);
3333 return WERR_OK;
3336 if (argc >= 2) {
3337 print_processor_name = argv[1];
3340 if (argc == 3) {
3341 level = atoi(argv[2]);
3344 /* Enumerate Print Processor Data Types */
3346 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3347 cli->srv_name_slash,
3348 print_processor_name,
3349 level,
3351 &num_procs,
3352 &procs);
3353 if (!W_ERROR_IS_OK(werror))
3354 goto done;
3356 /* Display output */
3358 for (i = 0; i < num_procs; i++) {
3359 switch (level) {
3360 case 1:
3361 display_proc_data_types_info1(&procs[i].info1);
3362 break;
3366 done:
3367 return werror;
3370 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3372 printf("monitor_name: %s\n", r->monitor_name);
3375 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3377 printf("monitor_name: %s\n", r->monitor_name);
3378 printf("environment: %s\n", r->environment);
3379 printf("dll_name: %s\n", r->dll_name);
3382 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3383 TALLOC_CTX *mem_ctx, int argc,
3384 const char **argv)
3386 WERROR werror;
3387 uint32_t count, level = 1, i;
3388 union spoolss_MonitorInfo *info;
3390 /* Parse the command arguments */
3392 if (argc > 2) {
3393 printf("Usage: %s [level]\n", argv[0]);
3394 return WERR_OK;
3397 if (argc == 2) {
3398 level = atoi(argv[1]);
3401 /* Enumerate Print Monitors */
3403 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3404 cli->srv_name_slash,
3405 level,
3407 &count,
3408 &info);
3409 if (!W_ERROR_IS_OK(werror)) {
3410 goto done;
3413 /* Display output */
3415 for (i = 0; i < count; i++) {
3416 switch (level) {
3417 case 1:
3418 display_monitor1(&info[i].info1);
3419 break;
3420 case 2:
3421 display_monitor2(&info[i].info2);
3422 break;
3426 done:
3427 return werror;
3430 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3431 TALLOC_CTX *mem_ctx, int argc,
3432 const char **argv)
3434 WERROR result;
3435 NTSTATUS status;
3436 struct policy_handle handle, gdi_handle;
3437 const char *printername;
3438 struct spoolss_DevmodeContainer devmode_ctr;
3440 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3442 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3443 printername,
3444 SEC_FLAG_MAXIMUM_ALLOWED,
3445 &handle);
3446 if (!W_ERROR_IS_OK(result)) {
3447 return result;
3450 ZERO_STRUCT(devmode_ctr);
3452 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3453 &handle,
3454 &gdi_handle,
3455 &devmode_ctr,
3456 &result);
3457 if (!W_ERROR_IS_OK(result)) {
3458 goto done;
3461 done:
3462 if (is_valid_policy_hnd(&gdi_handle)) {
3463 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3465 if (is_valid_policy_hnd(&handle)) {
3466 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3469 return result;
3472 /* List of commands exported by this module */
3473 struct cmd_set spoolss_commands[] = {
3475 { "SPOOLSS" },
3477 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3478 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3479 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3480 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3481 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3482 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3483 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3484 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3485 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3486 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3487 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3488 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3489 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3490 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3491 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3492 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3493 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3494 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3495 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3496 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3497 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3498 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3499 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3500 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3501 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3502 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3503 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3504 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3505 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3506 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3507 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3508 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3509 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3510 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3511 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3513 { NULL }