s4-netlogon: implement dcesrv_netr_DsRAddressToSitenamesExW
[Samba/aatanasov.git] / source3 / rpcclient / cmd_spoolss.c
blob48f9df3cacf71ef98cf80c9586a33fce67cc6d2c
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 char *text = NULL;
694 switch(value.type) {
695 case REG_DWORD:
696 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
697 *((uint32_t *) value.data_p));
698 break;
699 case REG_SZ:
700 rpcstr_pull_talloc(talloc_tos(),
701 &text,
702 value.data_p,
703 value.size,
704 STR_TERMINATE);
705 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
706 break;
707 case REG_BINARY: {
708 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
709 size_t i, len;
710 printf("%s: REG_BINARY:", value.valuename);
711 len = strlen(hex);
712 for (i=0; i<len; i++) {
713 if (hex[i] == '\0') {
714 break;
716 if (i%40 == 0) {
717 putchar('\n');
719 putchar(hex[i]);
721 TALLOC_FREE(hex);
722 putchar('\n');
723 break;
725 case REG_MULTI_SZ: {
726 uint32_t i, num_values;
727 char **values;
729 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
730 value.size, &num_values,
731 &values))) {
732 d_printf("reg_pull_multi_sz failed\n");
733 break;
736 printf("%s: REG_MULTI_SZ: \n", value.valuename);
737 for (i=0; i<num_values; i++) {
738 d_printf("%s\n", values[i]);
740 TALLOC_FREE(values);
741 break;
743 default:
744 printf("%s: unknown type %d\n", value.valuename, value.type);
749 /****************************************************************************
750 ****************************************************************************/
752 static void display_printer_data(const char *v,
753 enum winreg_Type type,
754 union spoolss_PrinterData *r)
756 int i;
758 switch (type) {
759 case REG_DWORD:
760 printf("%s: REG_DWORD: 0x%08x\n", v, r->value);
761 break;
762 case REG_SZ:
763 printf("%s: REG_SZ: %s\n", v, r->string);
764 break;
765 case REG_BINARY: {
766 char *hex = hex_encode_talloc(NULL,
767 r->binary.data, r->binary.length);
768 size_t len;
769 printf("%s: REG_BINARY:", v);
770 len = strlen(hex);
771 for (i=0; i<len; i++) {
772 if (hex[i] == '\0') {
773 break;
775 if (i%40 == 0) {
776 putchar('\n');
778 putchar(hex[i]);
780 TALLOC_FREE(hex);
781 putchar('\n');
782 break;
784 case REG_MULTI_SZ:
785 printf("%s: REG_MULTI_SZ: ", v);
786 for (i=0; r->string_array[i] != NULL; i++) {
787 printf("%s ", r->string_array[i]);
789 printf("\n");
790 break;
791 default:
792 printf("%s: unknown type 0x%02x:\n", v, type);
793 break;
797 /****************************************************************************
798 ****************************************************************************/
800 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
801 TALLOC_CTX *mem_ctx,
802 int argc, const char **argv)
804 struct policy_handle pol;
805 WERROR result;
806 fstring printername;
807 const char *valuename;
808 enum winreg_Type type;
809 union spoolss_PrinterData data;
811 if (argc != 3) {
812 printf("Usage: %s <printername> <valuename>\n", argv[0]);
813 printf("<printername> of . queries print server\n");
814 return WERR_OK;
816 valuename = argv[2];
818 /* Open a printer handle */
820 if (strncmp(argv[1], ".", sizeof(".")) == 0)
821 fstrcpy(printername, cli->srv_name_slash);
822 else
823 slprintf(printername, sizeof(printername)-1, "%s\\%s",
824 cli->srv_name_slash, argv[1]);
826 /* get a printer handle */
828 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
829 printername,
830 SEC_FLAG_MAXIMUM_ALLOWED,
831 &pol);
832 if (!W_ERROR_IS_OK(result))
833 goto done;
835 /* Get printer info */
837 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
838 &pol,
839 valuename,
841 &type,
842 &data);
843 if (!W_ERROR_IS_OK(result))
844 goto done;
846 /* Display printer data */
848 display_printer_data(valuename, type, &data);
850 done:
851 if (is_valid_policy_hnd(&pol))
852 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
854 return result;
857 /****************************************************************************
858 ****************************************************************************/
860 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
861 TALLOC_CTX *mem_ctx,
862 int argc, const char **argv)
864 struct policy_handle pol;
865 WERROR result;
866 NTSTATUS status;
867 fstring printername;
868 const char *valuename, *keyname;
869 struct regval_blob value;
871 enum winreg_Type type;
872 uint8_t *buffer = NULL;
873 uint32_t offered = 0;
874 uint32_t needed;
876 if (argc != 4) {
877 printf("Usage: %s <printername> <keyname> <valuename>\n",
878 argv[0]);
879 printf("<printername> of . queries print server\n");
880 return WERR_OK;
882 valuename = argv[3];
883 keyname = argv[2];
885 /* Open a printer handle */
887 if (strncmp(argv[1], ".", sizeof(".")) == 0)
888 fstrcpy(printername, cli->srv_name_slash);
889 else
890 slprintf(printername, sizeof(printername)-1, "%s\\%s",
891 cli->srv_name_slash, argv[1]);
893 /* get a printer handle */
895 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
896 printername,
897 SEC_FLAG_MAXIMUM_ALLOWED,
898 &pol);
899 if (!W_ERROR_IS_OK(result))
900 goto done;
902 /* Get printer info */
904 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
905 &pol,
906 keyname,
907 valuename,
908 &type,
909 buffer,
910 offered,
911 &needed,
912 &result);
913 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
914 offered = needed;
915 buffer = talloc_array(mem_ctx, uint8_t, needed);
916 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
917 &pol,
918 keyname,
919 valuename,
920 &type,
921 buffer,
922 offered,
923 &needed,
924 &result);
927 if (!NT_STATUS_IS_OK(status)) {
928 goto done;
931 if (!W_ERROR_IS_OK(result)) {
932 goto done;
936 if (!W_ERROR_IS_OK(result))
937 goto done;
939 /* Display printer data */
941 fstrcpy(value.valuename, valuename);
942 value.type = type;
943 value.size = needed;
944 value.data_p = buffer;
946 display_reg_value(value);
948 done:
949 if (is_valid_policy_hnd(&pol))
950 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
952 return result;
955 /****************************************************************************
956 ****************************************************************************/
958 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
960 if (!r) {
961 return;
964 printf("Printer Driver Info 1:\n");
965 printf("\tDriver Name: [%s]\n", r->driver_name);
966 printf("\n");
969 /****************************************************************************
970 ****************************************************************************/
972 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
974 if (!r) {
975 return;
978 printf("Printer Driver Info 2:\n");
979 printf("\tVersion: [%x]\n", r->version);
980 printf("\tDriver Name: [%s]\n", r->driver_name);
981 printf("\tArchitecture: [%s]\n", r->architecture);
982 printf("\tDriver Path: [%s]\n", r->driver_path);
983 printf("\tDatafile: [%s]\n", r->data_file);
984 printf("\tConfigfile: [%s]\n", r->config_file);
985 printf("\n");
988 /****************************************************************************
989 ****************************************************************************/
991 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
993 int i;
995 if (!r) {
996 return;
999 printf("Printer Driver Info 3:\n");
1000 printf("\tVersion: [%x]\n", r->version);
1001 printf("\tDriver Name: [%s]\n", r->driver_name);
1002 printf("\tArchitecture: [%s]\n", r->architecture);
1003 printf("\tDriver Path: [%s]\n", r->driver_path);
1004 printf("\tDatafile: [%s]\n", r->data_file);
1005 printf("\tConfigfile: [%s]\n", r->config_file);
1006 printf("\tHelpfile: [%s]\n", r->help_file);
1008 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1009 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1012 printf("\tMonitorname: [%s]\n", r->monitor_name);
1013 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1014 printf("\n");
1017 /****************************************************************************
1018 ****************************************************************************/
1020 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1022 int i;
1024 if (!r) {
1025 return;
1028 printf("Printer Driver Info 4:\n");
1029 printf("\tVersion: [%x]\n", r->version);
1030 printf("\tDriver Name: [%s]\n", r->driver_name);
1031 printf("\tArchitecture: [%s]\n", r->architecture);
1032 printf("\tDriver Path: [%s]\n", r->driver_path);
1033 printf("\tDatafile: [%s]\n", r->data_file);
1034 printf("\tConfigfile: [%s]\n", r->config_file);
1035 printf("\tHelpfile: [%s]\n", r->help_file);
1037 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1038 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1041 printf("\tMonitorname: [%s]\n", r->monitor_name);
1042 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1044 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1045 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1047 printf("\n");
1050 /****************************************************************************
1051 ****************************************************************************/
1053 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1055 if (!r) {
1056 return;
1059 printf("Printer Driver Info 5:\n");
1060 printf("\tVersion: [%x]\n", r->version);
1061 printf("\tDriver Name: [%s]\n", r->driver_name);
1062 printf("\tArchitecture: [%s]\n", r->architecture);
1063 printf("\tDriver Path: [%s]\n", r->driver_path);
1064 printf("\tDatafile: [%s]\n", r->data_file);
1065 printf("\tConfigfile: [%s]\n", r->config_file);
1066 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1067 printf("\tConfig Version: [0x%x]\n", r->config_version);
1068 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1069 printf("\n");
1072 /****************************************************************************
1073 ****************************************************************************/
1075 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1077 int i;
1079 if (!r) {
1080 return;
1083 printf("Printer Driver Info 6:\n");
1084 printf("\tVersion: [%x]\n", r->version);
1085 printf("\tDriver Name: [%s]\n", r->driver_name);
1086 printf("\tArchitecture: [%s]\n", r->architecture);
1087 printf("\tDriver Path: [%s]\n", r->driver_path);
1088 printf("\tDatafile: [%s]\n", r->data_file);
1089 printf("\tConfigfile: [%s]\n", r->config_file);
1090 printf("\tHelpfile: [%s]\n", r->help_file);
1092 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1093 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1096 printf("\tMonitorname: [%s]\n", r->monitor_name);
1097 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1099 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1100 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1103 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1104 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1105 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1106 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1107 printf("\tHardware ID: [%s]\n", r->hardware_id);
1108 printf("\tProvider: [%s]\n", r->provider);
1110 printf("\n");
1113 /****************************************************************************
1114 ****************************************************************************/
1116 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1118 int i;
1120 if (!r) {
1121 return;
1124 printf("Printer Driver Info 8:\n");
1125 printf("\tVersion: [%x]\n", r->version);
1126 printf("\tDriver Name: [%s]\n", r->driver_name);
1127 printf("\tArchitecture: [%s]\n", r->architecture);
1128 printf("\tDriver Path: [%s]\n", r->driver_path);
1129 printf("\tDatafile: [%s]\n", r->data_file);
1130 printf("\tConfigfile: [%s]\n", r->config_file);
1131 printf("\tHelpfile: [%s]\n", r->help_file);
1132 printf("\tMonitorname: [%s]\n", r->monitor_name);
1133 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1135 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1136 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1139 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1140 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1143 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1144 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1145 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1146 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1147 printf("\tHardware ID: [%s]\n", r->hardware_id);
1148 printf("\tProvider: [%s]\n", r->provider);
1149 printf("\tPrint Processor: [%s]\n", r->print_processor);
1150 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1151 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1152 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1154 printf("\tInf Path: [%s]\n", r->inf_path);
1155 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1156 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1157 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1159 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1160 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1161 (long long unsigned int)r->min_inbox_driver_ver_version);
1163 printf("\n");
1166 /****************************************************************************
1167 ****************************************************************************/
1169 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1170 TALLOC_CTX *mem_ctx,
1171 int argc, const char **argv)
1173 struct policy_handle pol;
1174 WERROR werror;
1175 uint32_t level = 3;
1176 const char *printername;
1177 uint32_t i;
1178 bool success = false;
1179 union spoolss_DriverInfo info;
1180 uint32_t server_major_version;
1181 uint32_t server_minor_version;
1183 if ((argc == 1) || (argc > 3)) {
1184 printf("Usage: %s <printername> [level]\n", argv[0]);
1185 return WERR_OK;
1188 /* get the arguments need to open the printer handle */
1190 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1192 if (argc == 3) {
1193 level = atoi(argv[2]);
1196 /* Open a printer handle */
1198 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1199 printername,
1200 PRINTER_ACCESS_USE,
1201 &pol);
1202 if (!W_ERROR_IS_OK(werror)) {
1203 printf("Error opening printer handle for %s!\n", printername);
1204 return werror;
1207 /* loop through and print driver info level for each architecture */
1209 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1211 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1212 &pol,
1213 archi_table[i].long_archi,
1214 level,
1215 0, /* offered */
1216 archi_table[i].version,
1218 &info,
1219 &server_major_version,
1220 &server_minor_version);
1221 if (!W_ERROR_IS_OK(werror)) {
1222 continue;
1225 /* need at least one success */
1227 success = true;
1229 printf("\n[%s]\n", archi_table[i].long_archi);
1231 switch (level) {
1232 case 1:
1233 display_print_driver1(&info.info1);
1234 break;
1235 case 2:
1236 display_print_driver2(&info.info2);
1237 break;
1238 case 3:
1239 display_print_driver3(&info.info3);
1240 break;
1241 case 4:
1242 display_print_driver4(&info.info4);
1243 break;
1244 case 5:
1245 display_print_driver5(&info.info5);
1246 break;
1247 case 6:
1248 display_print_driver6(&info.info6);
1249 break;
1250 case 8:
1251 display_print_driver8(&info.info8);
1252 break;
1253 default:
1254 printf("unknown info level %d\n", level);
1255 break;
1259 /* Cleanup */
1261 if (is_valid_policy_hnd(&pol)) {
1262 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1265 if (success) {
1266 werror = WERR_OK;
1269 return werror;
1272 /****************************************************************************
1273 ****************************************************************************/
1275 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1276 TALLOC_CTX *mem_ctx,
1277 const char *architecture,
1278 uint32_t level)
1280 WERROR werror;
1281 uint32_t count = 0;
1282 union spoolss_DriverInfo *info = NULL;
1283 uint32_t j;
1285 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1286 cli->srv_name_slash,
1287 architecture,
1288 level,
1290 &count,
1291 &info);
1293 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1294 printf("Server does not support environment [%s]\n",
1295 architecture);
1296 return WERR_OK;
1299 if (count == 0) {
1300 return WERR_OK;
1303 if (!W_ERROR_IS_OK(werror)) {
1304 printf("Error getting driver for environment [%s] - %s\n",
1305 architecture, win_errstr(werror));
1306 return werror;
1309 printf("\n[%s]\n", architecture);
1311 switch (level) {
1312 case 1:
1313 for (j=0; j < count; j++) {
1314 display_print_driver1(&info[j].info1);
1316 break;
1317 case 2:
1318 for (j=0; j < count; j++) {
1319 display_print_driver2(&info[j].info2);
1321 break;
1322 case 3:
1323 for (j=0; j < count; j++) {
1324 display_print_driver3(&info[j].info3);
1326 break;
1327 case 4:
1328 for (j=0; j < count; j++) {
1329 display_print_driver4(&info[j].info4);
1331 break;
1332 case 5:
1333 for (j=0; j < count; j++) {
1334 display_print_driver5(&info[j].info5);
1336 break;
1337 case 6:
1338 for (j=0; j < count; j++) {
1339 display_print_driver6(&info[j].info6);
1341 break;
1342 case 8:
1343 for (j=0; j < count; j++) {
1344 display_print_driver8(&info[j].info8);
1346 break;
1347 default:
1348 printf("unknown info level %d\n", level);
1349 return WERR_UNKNOWN_LEVEL;
1352 return werror;
1355 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1356 TALLOC_CTX *mem_ctx,
1357 int argc, const char **argv)
1359 WERROR werror = WERR_OK;
1360 uint32_t level = 1;
1361 uint32_t i;
1362 const char *architecture = NULL;
1364 if (argc > 3) {
1365 printf("Usage: enumdrivers [level] [architecture]\n");
1366 return WERR_OK;
1369 if (argc >= 2) {
1370 level = atoi(argv[1]);
1373 if (argc == 3) {
1374 architecture = argv[2];
1377 if (architecture) {
1378 return enum_driver_by_architecture(cli, mem_ctx,
1379 architecture,
1380 level);
1383 /* loop through and print driver info level for each architecture */
1384 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1385 /* check to see if we already asked for this architecture string */
1387 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1388 continue;
1391 werror = enum_driver_by_architecture(cli, mem_ctx,
1392 archi_table[i].long_archi,
1393 level);
1394 if (!W_ERROR_IS_OK(werror)) {
1395 break;
1399 return werror;
1402 /****************************************************************************
1403 ****************************************************************************/
1405 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1407 printf("\tDirectory Name:[%s]\n", r->directory_name);
1410 /****************************************************************************
1411 ****************************************************************************/
1413 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1414 TALLOC_CTX *mem_ctx,
1415 int argc, const char **argv)
1417 WERROR result;
1418 NTSTATUS status;
1419 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1420 DATA_BLOB buffer;
1421 uint32_t offered;
1422 union spoolss_DriverDirectoryInfo info;
1423 uint32_t needed;
1425 if (argc > 2) {
1426 printf("Usage: %s [environment]\n", argv[0]);
1427 return WERR_OK;
1430 /* Get the arguments need to open the printer handle */
1432 if (argc == 2) {
1433 env = argv[1];
1436 /* Get the directory. Only use Info level 1 */
1438 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1439 cli->srv_name_slash,
1440 env,
1442 NULL, /* buffer */
1443 0, /* offered */
1444 NULL, /* info */
1445 &needed,
1446 &result);
1447 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1448 offered = needed;
1449 buffer = data_blob_talloc_zero(mem_ctx, needed);
1451 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1452 cli->srv_name_slash,
1453 env,
1455 &buffer,
1456 offered,
1457 &info,
1458 &needed,
1459 &result);
1462 if (W_ERROR_IS_OK(result)) {
1463 display_printdriverdir_1(&info.info1);
1466 return result;
1469 /****************************************************************************
1470 ****************************************************************************/
1472 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1473 struct spoolss_AddDriverInfo3 *info,
1474 const char *arch)
1477 int i;
1479 for (i=0; archi_table[i].long_archi != NULL; i++)
1481 if (strcmp(arch, archi_table[i].short_archi) == 0)
1483 info->version = archi_table[i].version;
1484 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1485 break;
1489 if (archi_table[i].long_archi == NULL)
1491 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1494 return;
1498 /**************************************************************************
1499 wrapper for strtok to get the next parameter from a delimited list.
1500 Needed to handle the empty parameter string denoted by "NULL"
1501 *************************************************************************/
1503 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1504 const char *delim, const char **dest,
1505 char **saveptr)
1507 char *ptr;
1509 /* get the next token */
1510 ptr = strtok_r(str, delim, saveptr);
1512 /* a string of 'NULL' is used to represent an empty
1513 parameter because two consecutive delimiters
1514 will not return an empty string. See man strtok(3)
1515 for details */
1516 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1517 ptr = NULL;
1520 if (dest != NULL) {
1521 *dest = talloc_strdup(mem_ctx, ptr);
1524 return ptr;
1527 /********************************************************************************
1528 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1529 string in the form of
1530 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1531 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1532 <Default Data Type>:<Comma Separated list of Files>
1533 *******************************************************************************/
1535 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1536 char *args)
1538 char *str, *str2;
1539 int count = 0;
1540 char *saveptr = NULL;
1541 struct spoolss_StringArray *deps;
1542 const char **file_array = NULL;
1543 int i;
1545 /* fill in the UNISTR fields */
1546 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1547 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1548 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1549 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1550 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1551 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1552 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1554 /* <Comma Separated List of Dependent Files> */
1555 /* save the beginning of the string */
1556 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1557 str = str2;
1559 /* begin to strip out each filename */
1560 str = strtok_r(str, ",", &saveptr);
1562 /* no dependent files, we are done */
1563 if (!str) {
1564 return true;
1567 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1568 if (!deps) {
1569 return false;
1572 while (str != NULL) {
1573 add_string_to_array(deps, str, &file_array, &count);
1574 str = strtok_r(NULL, ",", &saveptr);
1577 deps->string = talloc_zero_array(deps, const char *, count + 1);
1578 if (!deps->string) {
1579 return false;
1582 for (i=0; i < count; i++) {
1583 deps->string[i] = file_array[i];
1586 r->dependent_files = deps;
1588 return true;
1591 /****************************************************************************
1592 ****************************************************************************/
1594 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1595 TALLOC_CTX *mem_ctx,
1596 int argc, const char **argv)
1598 WERROR result;
1599 NTSTATUS status;
1600 uint32_t level = 3;
1601 struct spoolss_AddDriverInfoCtr info_ctr;
1602 struct spoolss_AddDriverInfo3 info3;
1603 const char *arch;
1604 char *driver_args;
1606 /* parse the command arguments */
1607 if (argc != 3 && argc != 4)
1609 printf ("Usage: %s <Environment> \\\n", argv[0]);
1610 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1611 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1612 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1613 printf ("\t[version]\n");
1615 return WERR_OK;
1618 /* Fill in the spoolss_AddDriverInfo3 struct */
1619 ZERO_STRUCT(info3);
1621 arch = cmd_spoolss_get_short_archi(argv[1]);
1622 if (!arch) {
1623 printf ("Error Unknown architechture [%s]\n", argv[1]);
1624 return WERR_INVALID_PARAM;
1627 set_drv_info_3_env(mem_ctx, &info3, arch);
1629 driver_args = talloc_strdup( mem_ctx, argv[2] );
1630 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1632 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1633 return WERR_INVALID_PARAM;
1636 /* if printer driver version specified, override the default version
1637 * used by the architecture. This allows installation of Windows
1638 * 2000 (version 3) printer drivers. */
1639 if (argc == 4)
1641 info3.version = atoi(argv[3]);
1645 info_ctr.level = level;
1646 info_ctr.info.info3 = &info3;
1648 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1649 cli->srv_name_slash,
1650 &info_ctr,
1651 &result);
1652 if (!NT_STATUS_IS_OK(status)) {
1653 return ntstatus_to_werror(status);
1655 if (W_ERROR_IS_OK(result)) {
1656 printf ("Printer Driver %s successfully installed.\n",
1657 info3.driver_name);
1660 return result;
1664 /****************************************************************************
1665 ****************************************************************************/
1667 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1668 TALLOC_CTX *mem_ctx,
1669 int argc, const char **argv)
1671 WERROR result;
1672 struct spoolss_SetPrinterInfoCtr info_ctr;
1673 struct spoolss_SetPrinterInfo2 info2;
1675 /* parse the command arguments */
1676 if (argc != 5)
1678 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1679 return WERR_OK;
1682 /* Fill in the DRIVER_INFO_2 struct */
1683 ZERO_STRUCT(info2);
1685 info2.printername = argv[1];
1686 info2.drivername = argv[3];
1687 info2.sharename = argv[2];
1688 info2.portname = argv[4];
1689 info2.comment = "Created by rpcclient";
1690 info2.printprocessor = "winprint";
1691 info2.datatype = "RAW";
1692 info2.devmode = NULL;
1693 info2.secdesc = NULL;
1694 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1695 info2.priority = 0;
1696 info2.defaultpriority = 0;
1697 info2.starttime = 0;
1698 info2.untiltime = 0;
1700 /* These three fields must not be used by AddPrinter()
1701 as defined in the MS Platform SDK documentation..
1702 --jerry
1703 info2.status = 0;
1704 info2.cjobs = 0;
1705 info2.averageppm = 0;
1708 info_ctr.level = 2;
1709 info_ctr.info.info2 = &info2;
1711 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1712 &info_ctr);
1713 if (W_ERROR_IS_OK(result))
1714 printf ("Printer %s successfully installed.\n", argv[1]);
1716 return result;
1719 /****************************************************************************
1720 ****************************************************************************/
1722 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1723 TALLOC_CTX *mem_ctx,
1724 int argc, const char **argv)
1726 struct policy_handle pol;
1727 WERROR result;
1728 NTSTATUS status;
1729 uint32_t level = 2;
1730 const char *printername;
1731 union spoolss_PrinterInfo info;
1732 struct spoolss_SetPrinterInfoCtr info_ctr;
1733 struct spoolss_DevmodeContainer devmode_ctr;
1734 struct sec_desc_buf secdesc_ctr;
1736 ZERO_STRUCT(devmode_ctr);
1737 ZERO_STRUCT(secdesc_ctr);
1739 /* parse the command arguments */
1740 if (argc != 3)
1742 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1743 return WERR_OK;
1746 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1748 /* Get a printer handle */
1750 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1751 printername,
1752 PRINTER_ALL_ACCESS,
1753 &pol);
1754 if (!W_ERROR_IS_OK(result))
1755 goto done;
1757 /* Get printer info */
1759 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1760 &pol,
1761 level,
1763 &info);
1764 if (!W_ERROR_IS_OK(result)) {
1765 printf ("Unable to retrieve printer information!\n");
1766 goto done;
1769 /* Set the printer driver */
1771 info.info2.drivername = argv[2];
1772 info.info2.devmode = NULL;
1773 info.info2.secdesc = NULL;
1775 info_ctr.level = 2;
1776 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1778 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1779 &pol,
1780 &info_ctr,
1781 &devmode_ctr,
1782 &secdesc_ctr,
1783 0, /* command */
1784 &result);
1785 if (!W_ERROR_IS_OK(result)) {
1786 printf("SetPrinter call failed!\n");
1787 goto done;;
1790 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1792 done:
1793 /* Cleanup */
1795 if (is_valid_policy_hnd(&pol))
1796 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1798 return result;
1802 /****************************************************************************
1803 ****************************************************************************/
1805 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1806 TALLOC_CTX *mem_ctx,
1807 int argc, const char **argv)
1809 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1810 NTSTATUS status;
1812 int i;
1813 int vers = -1;
1815 const char *arch = NULL;
1816 uint32_t delete_flags = 0;
1818 /* parse the command arguments */
1819 if (argc < 2 || argc > 4) {
1820 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1821 return WERR_OK;
1824 if (argc >= 3)
1825 arch = argv[2];
1826 if (argc == 4)
1827 vers = atoi (argv[3]);
1829 if (vers >= 0) {
1830 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1833 /* delete the driver for all architectures */
1834 for (i=0; archi_table[i].long_archi; i++) {
1836 if (arch && !strequal( archi_table[i].long_archi, arch))
1837 continue;
1839 if (vers >= 0 && archi_table[i].version != vers)
1840 continue;
1842 /* make the call to remove the driver */
1843 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1844 cli->srv_name_slash,
1845 archi_table[i].long_archi,
1846 argv[1],
1847 delete_flags,
1848 archi_table[i].version,
1849 &result);
1851 if ( !W_ERROR_IS_OK(result) )
1853 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1854 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1855 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1858 else
1860 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1861 archi_table[i].long_archi, archi_table[i].version);
1862 ret = WERR_OK;
1866 return ret;
1870 /****************************************************************************
1871 ****************************************************************************/
1873 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1874 TALLOC_CTX *mem_ctx,
1875 int argc, const char **argv)
1877 WERROR result = WERR_OK;
1878 NTSTATUS status;
1879 int i;
1881 /* parse the command arguments */
1882 if (argc != 2) {
1883 printf ("Usage: %s <driver>\n", argv[0]);
1884 return WERR_OK;
1887 /* delete the driver for all architectures */
1888 for (i=0; archi_table[i].long_archi; i++) {
1889 /* make the call to remove the driver */
1890 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1891 cli->srv_name_slash,
1892 archi_table[i].long_archi,
1893 argv[1],
1894 &result);
1895 if (!NT_STATUS_IS_OK(status)) {
1896 return result;
1898 if ( !W_ERROR_IS_OK(result) ) {
1899 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1900 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1901 argv[1], archi_table[i].long_archi,
1902 W_ERROR_V(result));
1904 } else {
1905 printf ("Driver %s removed for arch [%s].\n", argv[1],
1906 archi_table[i].long_archi);
1910 return result;
1913 /****************************************************************************
1914 ****************************************************************************/
1916 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1917 TALLOC_CTX *mem_ctx,
1918 int argc, const char **argv)
1920 WERROR result;
1921 NTSTATUS status;
1922 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1923 DATA_BLOB buffer;
1924 uint32_t offered;
1925 union spoolss_PrintProcessorDirectoryInfo info;
1926 uint32_t needed;
1928 /* parse the command arguments */
1929 if (argc > 2) {
1930 printf ("Usage: %s [environment]\n", argv[0]);
1931 return WERR_OK;
1934 if (argc == 2) {
1935 environment = argv[1];
1938 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1939 cli->srv_name_slash,
1940 environment,
1942 NULL, /* buffer */
1943 0, /* offered */
1944 NULL, /* info */
1945 &needed,
1946 &result);
1947 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1948 offered = needed;
1949 buffer = data_blob_talloc_zero(mem_ctx, needed);
1951 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1952 cli->srv_name_slash,
1953 environment,
1955 &buffer,
1956 offered,
1957 &info,
1958 &needed,
1959 &result);
1962 if (W_ERROR_IS_OK(result)) {
1963 printf("%s\n", info.info1.directory_name);
1966 return result;
1969 /****************************************************************************
1970 ****************************************************************************/
1972 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1973 int argc, const char **argv)
1975 struct policy_handle handle;
1976 WERROR werror;
1977 NTSTATUS status;
1978 const char *printername;
1979 union spoolss_AddFormInfo info;
1980 struct spoolss_AddFormInfo1 info1;
1981 struct spoolss_AddFormInfo2 info2;
1982 uint32_t level = 1;
1984 /* Parse the command arguments */
1986 if (argc < 3 || argc > 5) {
1987 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1988 return WERR_OK;
1991 /* Get a printer handle */
1993 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1995 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1996 printername,
1997 PRINTER_ALL_ACCESS,
1998 &handle);
1999 if (!W_ERROR_IS_OK(werror))
2000 goto done;
2002 /* Dummy up some values for the form data */
2004 if (argc == 4) {
2005 level = atoi(argv[3]);
2008 switch (level) {
2009 case 1:
2010 info1.flags = SPOOLSS_FORM_USER;
2011 info1.form_name = argv[2];
2012 info1.size.width = 100;
2013 info1.size.height = 100;
2014 info1.area.left = 0;
2015 info1.area.top = 10;
2016 info1.area.right = 20;
2017 info1.area.bottom = 30;
2019 info.info1 = &info1;
2021 break;
2022 case 2:
2023 info2.flags = SPOOLSS_FORM_USER;
2024 info2.form_name = argv[2];
2025 info2.size.width = 100;
2026 info2.size.height = 100;
2027 info2.area.left = 0;
2028 info2.area.top = 10;
2029 info2.area.right = 20;
2030 info2.area.bottom = 30;
2031 info2.keyword = argv[2];
2032 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2033 info2.mui_dll = NULL;
2034 info2.ressource_id = 0;
2035 info2.display_name = argv[2];
2036 info2.lang_id = 0;
2038 info.info2 = &info2;
2040 break;
2043 /* Add the form */
2046 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2047 &handle,
2048 level,
2049 info,
2050 &werror);
2052 done:
2053 if (is_valid_policy_hnd(&handle))
2054 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2056 return werror;
2059 /****************************************************************************
2060 ****************************************************************************/
2062 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2063 int argc, const char **argv)
2065 struct policy_handle handle;
2066 WERROR werror;
2067 NTSTATUS status;
2068 const char *printername;
2069 union spoolss_AddFormInfo info;
2070 struct spoolss_AddFormInfo1 info1;
2072 /* Parse the command arguments */
2074 if (argc != 3) {
2075 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2076 return WERR_OK;
2079 /* Get a printer handle */
2081 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2083 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2084 printername,
2085 SEC_FLAG_MAXIMUM_ALLOWED,
2086 &handle);
2087 if (!W_ERROR_IS_OK(werror))
2088 goto done;
2090 /* Dummy up some values for the form data */
2092 info1.flags = SPOOLSS_FORM_PRINTER;
2093 info1.size.width = 100;
2094 info1.size.height = 100;
2095 info1.area.left = 0;
2096 info1.area.top = 1000;
2097 info1.area.right = 2000;
2098 info1.area.bottom = 3000;
2099 info1.form_name = argv[2];
2101 info.info1 = &info1;
2103 /* Set the form */
2105 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2106 &handle,
2107 argv[2],
2109 info,
2110 &werror);
2112 done:
2113 if (is_valid_policy_hnd(&handle))
2114 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2116 return werror;
2119 /****************************************************************************
2120 ****************************************************************************/
2122 static const char *get_form_flag(int form_flag)
2124 switch (form_flag) {
2125 case SPOOLSS_FORM_USER:
2126 return "FORM_USER";
2127 case SPOOLSS_FORM_BUILTIN:
2128 return "FORM_BUILTIN";
2129 case SPOOLSS_FORM_PRINTER:
2130 return "FORM_PRINTER";
2131 default:
2132 return "unknown";
2136 /****************************************************************************
2137 ****************************************************************************/
2139 static void display_form_info1(struct spoolss_FormInfo1 *r)
2141 printf("%s\n" \
2142 "\tflag: %s (%d)\n" \
2143 "\twidth: %d, length: %d\n" \
2144 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2145 r->form_name, get_form_flag(r->flags), r->flags,
2146 r->size.width, r->size.height,
2147 r->area.left, r->area.right,
2148 r->area.top, r->area.bottom);
2151 /****************************************************************************
2152 ****************************************************************************/
2154 static void display_form_info2(struct spoolss_FormInfo2 *r)
2156 printf("%s\n" \
2157 "\tflag: %s (%d)\n" \
2158 "\twidth: %d, length: %d\n" \
2159 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2160 r->form_name, get_form_flag(r->flags), r->flags,
2161 r->size.width, r->size.height,
2162 r->area.left, r->area.right,
2163 r->area.top, r->area.bottom);
2164 printf("\tkeyword: %s\n", r->keyword);
2165 printf("\tstring_type: 0x%08x\n", r->string_type);
2166 printf("\tmui_dll: %s\n", r->mui_dll);
2167 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2168 printf("\tdisplay_name: %s\n", r->display_name);
2169 printf("\tlang_id: %d\n", r->lang_id);
2170 printf("\n");
2173 /****************************************************************************
2174 ****************************************************************************/
2176 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2177 int argc, const char **argv)
2179 struct policy_handle handle;
2180 WERROR werror;
2181 NTSTATUS status;
2182 const char *printername;
2183 DATA_BLOB buffer;
2184 uint32_t offered = 0;
2185 union spoolss_FormInfo info;
2186 uint32_t needed;
2187 uint32_t level = 1;
2189 /* Parse the command arguments */
2191 if (argc < 3 || argc > 5) {
2192 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2193 return WERR_OK;
2196 /* Get a printer handle */
2198 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2200 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2201 printername,
2202 SEC_FLAG_MAXIMUM_ALLOWED,
2203 &handle);
2204 if (!W_ERROR_IS_OK(werror))
2205 goto done;
2207 if (argc == 4) {
2208 level = atoi(argv[3]);
2211 /* Get the form */
2213 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2214 &handle,
2215 argv[2],
2216 level,
2217 NULL,
2218 offered,
2219 &info,
2220 &needed,
2221 &werror);
2222 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2223 buffer = data_blob_talloc_zero(mem_ctx, needed);
2224 offered = needed;
2225 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2226 &handle,
2227 argv[2],
2228 level,
2229 &buffer,
2230 offered,
2231 &info,
2232 &needed,
2233 &werror);
2236 if (!NT_STATUS_IS_OK(status)) {
2237 return werror;
2240 switch (level) {
2241 case 1:
2242 display_form_info1(&info.info1);
2243 break;
2244 case 2:
2245 display_form_info2(&info.info2);
2246 break;
2249 done:
2250 if (is_valid_policy_hnd(&handle))
2251 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2253 return werror;
2256 /****************************************************************************
2257 ****************************************************************************/
2259 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2260 TALLOC_CTX *mem_ctx, int argc,
2261 const char **argv)
2263 struct policy_handle handle;
2264 WERROR werror;
2265 NTSTATUS status;
2266 const char *printername;
2268 /* Parse the command arguments */
2270 if (argc != 3) {
2271 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2272 return WERR_OK;
2275 /* Get a printer handle */
2277 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2279 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2280 printername,
2281 SEC_FLAG_MAXIMUM_ALLOWED,
2282 &handle);
2283 if (!W_ERROR_IS_OK(werror))
2284 goto done;
2286 /* Delete the form */
2288 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2289 &handle,
2290 argv[2],
2291 &werror);
2292 if (!NT_STATUS_IS_OK(status)) {
2293 return ntstatus_to_werror(status);
2296 done:
2297 if (is_valid_policy_hnd(&handle))
2298 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2300 return werror;
2303 /****************************************************************************
2304 ****************************************************************************/
2306 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2307 TALLOC_CTX *mem_ctx, int argc,
2308 const char **argv)
2310 struct policy_handle handle;
2311 WERROR werror;
2312 const char *printername;
2313 uint32_t num_forms, level = 1, i;
2314 union spoolss_FormInfo *forms;
2316 /* Parse the command arguments */
2318 if (argc < 2 || argc > 4) {
2319 printf ("Usage: %s <printer> [level]\n", argv[0]);
2320 return WERR_OK;
2323 /* Get a printer handle */
2325 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2327 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2328 printername,
2329 SEC_FLAG_MAXIMUM_ALLOWED,
2330 &handle);
2331 if (!W_ERROR_IS_OK(werror))
2332 goto done;
2334 if (argc == 3) {
2335 level = atoi(argv[2]);
2338 /* Enumerate forms */
2340 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2341 &handle,
2342 level,
2344 &num_forms,
2345 &forms);
2347 if (!W_ERROR_IS_OK(werror))
2348 goto done;
2350 /* Display output */
2352 for (i = 0; i < num_forms; i++) {
2353 switch (level) {
2354 case 1:
2355 display_form_info1(&forms[i].info1);
2356 break;
2357 case 2:
2358 display_form_info2(&forms[i].info2);
2359 break;
2363 done:
2364 if (is_valid_policy_hnd(&handle))
2365 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2367 return werror;
2370 /****************************************************************************
2371 ****************************************************************************/
2373 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2374 TALLOC_CTX *mem_ctx,
2375 int argc, const char **argv)
2377 WERROR result;
2378 NTSTATUS status;
2379 const char *printername;
2380 struct policy_handle pol;
2381 union spoolss_PrinterInfo info;
2382 enum winreg_Type type;
2383 union spoolss_PrinterData data;
2385 /* parse the command arguments */
2386 if (argc < 5) {
2387 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2388 " <value> <data>\n",
2389 argv[0]);
2390 result = WERR_INVALID_PARAM;
2391 goto done;
2394 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2396 type = REG_NONE;
2398 if (strequal(argv[2], "string")) {
2399 type = REG_SZ;
2402 if (strequal(argv[2], "binary")) {
2403 type = REG_BINARY;
2406 if (strequal(argv[2], "dword")) {
2407 type = REG_DWORD;
2410 if (strequal(argv[2], "multistring")) {
2411 type = REG_MULTI_SZ;
2414 if (type == REG_NONE) {
2415 printf("Unknown data type: %s\n", argv[2]);
2416 result = WERR_INVALID_PARAM;
2417 goto done;
2420 /* get a printer handle */
2422 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2423 printername,
2424 SEC_FLAG_MAXIMUM_ALLOWED,
2425 &pol);
2426 if (!W_ERROR_IS_OK(result)) {
2427 goto done;
2430 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2431 &pol,
2434 &info);
2435 if (!W_ERROR_IS_OK(result)) {
2436 goto done;
2439 printf("%s\n", current_timestring(mem_ctx, true));
2440 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2442 /* Set the printer data */
2444 switch (type) {
2445 case REG_SZ:
2446 data.string = talloc_strdup(mem_ctx, argv[4]);
2447 W_ERROR_HAVE_NO_MEMORY(data.string);
2448 break;
2449 case REG_DWORD:
2450 data.value = strtoul(argv[4], NULL, 10);
2451 break;
2452 case REG_BINARY:
2453 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2454 break;
2455 case REG_MULTI_SZ: {
2456 int i, num_strings;
2457 const char **strings = NULL;
2459 for (i=4; i<argc; i++) {
2460 if (strcmp(argv[i], "NULL") == 0) {
2461 argv[i] = "";
2463 if (!add_string_to_array(mem_ctx, argv[i],
2464 &strings,
2465 &num_strings)) {
2466 result = WERR_NOMEM;
2467 goto done;
2470 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2471 if (!data.string_array) {
2472 result = WERR_NOMEM;
2473 goto done;
2475 for (i=0; i < num_strings; i++) {
2476 data.string_array[i] = strings[i];
2478 break;
2480 default:
2481 printf("Unknown data type: %s\n", argv[2]);
2482 result = WERR_INVALID_PARAM;
2483 goto done;
2486 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2487 &pol,
2488 argv[3], /* value_name */
2489 type,
2490 data,
2491 0, /* autocalculated size */
2492 &result);
2493 if (!W_ERROR_IS_OK(result)) {
2494 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2495 goto done;
2497 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2499 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2500 &pol,
2503 &info);
2504 if (!W_ERROR_IS_OK(result)) {
2505 goto done;
2508 printf("%s\n", current_timestring(mem_ctx, true));
2509 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2511 done:
2512 /* cleanup */
2513 if (is_valid_policy_hnd(&pol)) {
2514 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2517 return result;
2520 /****************************************************************************
2521 ****************************************************************************/
2523 static void display_job_info1(struct spoolss_JobInfo1 *r)
2525 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2526 r->user_name, r->document_name, r->text_status, r->pages_printed,
2527 r->total_pages);
2530 /****************************************************************************
2531 ****************************************************************************/
2533 static void display_job_info2(struct spoolss_JobInfo2 *r)
2535 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2536 r->position, r->job_id,
2537 r->user_name, r->document_name, r->text_status, r->pages_printed,
2538 r->total_pages, r->size);
2541 /****************************************************************************
2542 ****************************************************************************/
2544 static void display_job_info3(struct spoolss_JobInfo3 *r)
2546 printf("jobid[%d], next_jobid[%d]\n",
2547 r->job_id, r->next_job_id);
2550 /****************************************************************************
2551 ****************************************************************************/
2553 static void display_job_info4(struct spoolss_JobInfo4 *r)
2555 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2556 r->position, r->job_id,
2557 r->user_name, r->document_name, r->text_status, r->pages_printed,
2558 r->total_pages, r->size, r->size_high);
2561 /****************************************************************************
2562 ****************************************************************************/
2564 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2565 TALLOC_CTX *mem_ctx, int argc,
2566 const char **argv)
2568 WERROR result;
2569 uint32_t level = 1, count, i;
2570 const char *printername;
2571 struct policy_handle hnd;
2572 union spoolss_JobInfo *info;
2574 if (argc < 2 || argc > 3) {
2575 printf("Usage: %s printername [level]\n", argv[0]);
2576 return WERR_OK;
2579 if (argc == 3) {
2580 level = atoi(argv[2]);
2583 /* Open printer handle */
2585 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2587 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2588 printername,
2589 SEC_FLAG_MAXIMUM_ALLOWED,
2590 &hnd);
2591 if (!W_ERROR_IS_OK(result))
2592 goto done;
2594 /* Enumerate ports */
2596 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2597 &hnd,
2598 0, /* firstjob */
2599 1000, /* numjobs */
2600 level,
2602 &count,
2603 &info);
2604 if (!W_ERROR_IS_OK(result)) {
2605 goto done;
2608 for (i = 0; i < count; i++) {
2609 switch (level) {
2610 case 1:
2611 display_job_info1(&info[i].info1);
2612 break;
2613 case 2:
2614 display_job_info2(&info[i].info2);
2615 break;
2616 default:
2617 d_printf("unknown info level %d\n", level);
2618 break;
2622 done:
2623 if (is_valid_policy_hnd(&hnd)) {
2624 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2627 return result;
2630 /****************************************************************************
2631 ****************************************************************************/
2633 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2634 TALLOC_CTX *mem_ctx, int argc,
2635 const char **argv)
2637 WERROR result;
2638 const char *printername;
2639 struct policy_handle hnd;
2640 uint32_t job_id;
2641 uint32_t level = 1;
2642 union spoolss_JobInfo info;
2644 if (argc < 3 || argc > 4) {
2645 printf("Usage: %s printername job_id [level]\n", argv[0]);
2646 return WERR_OK;
2649 job_id = atoi(argv[2]);
2651 if (argc == 4) {
2652 level = atoi(argv[3]);
2655 /* Open printer handle */
2657 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2659 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2660 printername,
2661 SEC_FLAG_MAXIMUM_ALLOWED,
2662 &hnd);
2663 if (!W_ERROR_IS_OK(result)) {
2664 goto done;
2667 /* Enumerate ports */
2669 result = rpccli_spoolss_getjob(cli, mem_ctx,
2670 &hnd,
2671 job_id,
2672 level,
2674 &info);
2676 if (!W_ERROR_IS_OK(result)) {
2677 goto done;
2680 switch (level) {
2681 case 1:
2682 display_job_info1(&info.info1);
2683 break;
2684 case 2:
2685 display_job_info2(&info.info2);
2686 break;
2687 case 3:
2688 display_job_info3(&info.info3);
2689 break;
2690 case 4:
2691 display_job_info4(&info.info4);
2692 break;
2693 default:
2694 d_printf("unknown info level %d\n", level);
2695 break;
2698 done:
2699 if (is_valid_policy_hnd(&hnd)) {
2700 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2703 return result;
2706 /****************************************************************************
2707 ****************************************************************************/
2709 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2710 TALLOC_CTX *mem_ctx, int argc,
2711 const char **argv)
2713 WERROR result;
2714 NTSTATUS status;
2715 const char *printername;
2716 struct policy_handle hnd;
2717 uint32_t job_id;
2718 enum spoolss_JobControl command;
2720 if (argc != 4) {
2721 printf("Usage: %s printername job_id command\n", argv[0]);
2722 return WERR_OK;
2725 job_id = atoi(argv[2]);
2726 command = atoi(argv[3]);
2728 /* Open printer handle */
2730 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2732 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2733 printername,
2734 SEC_FLAG_MAXIMUM_ALLOWED,
2735 &hnd);
2736 if (!W_ERROR_IS_OK(result)) {
2737 goto done;
2740 /* Set Job */
2742 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2743 &hnd,
2744 job_id,
2745 NULL,
2746 command,
2747 &result);
2749 if (!W_ERROR_IS_OK(result)) {
2750 goto done;
2753 done:
2754 if (is_valid_policy_hnd(&hnd)) {
2755 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2758 return result;
2761 /****************************************************************************
2762 ****************************************************************************/
2764 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2765 TALLOC_CTX *mem_ctx, int argc,
2766 const char **argv)
2768 WERROR result;
2769 NTSTATUS status;
2770 uint32_t i = 0;
2771 const char *printername;
2772 struct policy_handle hnd;
2773 uint32_t value_offered = 0;
2774 const char *value_name = NULL;
2775 uint32_t value_needed;
2776 enum winreg_Type type;
2777 uint8_t *data = NULL;
2778 uint32_t data_offered = 0;
2779 uint32_t data_needed;
2781 if (argc != 2) {
2782 printf("Usage: %s printername\n", argv[0]);
2783 return WERR_OK;
2786 /* Open printer handle */
2788 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2790 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2791 printername,
2792 SEC_FLAG_MAXIMUM_ALLOWED,
2793 &hnd);
2794 if (!W_ERROR_IS_OK(result)) {
2795 goto done;
2798 /* Enumerate data */
2800 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2801 &hnd,
2803 value_name,
2804 value_offered,
2805 &value_needed,
2806 &type,
2807 data,
2808 data_offered,
2809 &data_needed,
2810 &result);
2812 data_offered = data_needed;
2813 value_offered = value_needed;
2814 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2815 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2817 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2819 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2820 &hnd,
2821 i++,
2822 value_name,
2823 value_offered,
2824 &value_needed,
2825 &type,
2826 data,
2827 data_offered,
2828 &data_needed,
2829 &result);
2830 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2831 struct regval_blob v;
2832 fstrcpy(v.valuename, value_name);
2833 v.type = type;
2834 v.size = data_offered;
2835 v.data_p = data;
2836 display_reg_value(v);
2840 if (W_ERROR_V(result) == ERRnomoreitems) {
2841 result = W_ERROR(ERRsuccess);
2844 done:
2845 if (is_valid_policy_hnd(&hnd)) {
2846 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2849 return result;
2852 /****************************************************************************
2853 ****************************************************************************/
2855 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2856 TALLOC_CTX *mem_ctx, int argc,
2857 const char **argv)
2859 WERROR result;
2860 uint32_t i;
2861 const char *printername;
2862 struct policy_handle hnd;
2863 uint32_t count;
2864 struct spoolss_PrinterEnumValues *info;
2866 if (argc != 3) {
2867 printf("Usage: %s printername <keyname>\n", argv[0]);
2868 return WERR_OK;
2871 /* Open printer handle */
2873 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2875 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2876 printername,
2877 SEC_FLAG_MAXIMUM_ALLOWED,
2878 &hnd);
2879 if (!W_ERROR_IS_OK(result)) {
2880 goto done;
2883 /* Enumerate subkeys */
2885 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2886 &hnd,
2887 argv[2],
2889 &count,
2890 &info);
2891 if (!W_ERROR_IS_OK(result)) {
2892 goto done;
2895 for (i=0; i < count; i++) {
2896 display_printer_data(info[i].value_name,
2897 info[i].type,
2898 info[i].data);
2901 done:
2902 if (is_valid_policy_hnd(&hnd)) {
2903 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2906 return result;
2909 /****************************************************************************
2910 ****************************************************************************/
2912 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2913 TALLOC_CTX *mem_ctx, int argc,
2914 const char **argv)
2916 WERROR result;
2917 const char *printername;
2918 const char *keyname = NULL;
2919 struct policy_handle hnd;
2920 const char **key_buffer = NULL;
2921 int i;
2923 if (argc < 2 || argc > 3) {
2924 printf("Usage: %s printername [keyname]\n", argv[0]);
2925 return WERR_OK;
2928 if (argc == 3) {
2929 keyname = argv[2];
2930 } else {
2931 keyname = "";
2934 /* Open printer handle */
2936 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2938 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2939 printername,
2940 SEC_FLAG_MAXIMUM_ALLOWED,
2941 &hnd);
2942 if (!W_ERROR_IS_OK(result)) {
2943 goto done;
2946 /* Enumerate subkeys */
2948 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
2949 &hnd,
2950 keyname,
2951 &key_buffer,
2954 if (!W_ERROR_IS_OK(result)) {
2955 goto done;
2958 for (i=0; key_buffer && key_buffer[i]; i++) {
2959 printf("%s\n", key_buffer[i]);
2962 done:
2964 if (is_valid_policy_hnd(&hnd)) {
2965 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2968 return result;
2971 /****************************************************************************
2972 ****************************************************************************/
2974 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2975 TALLOC_CTX *mem_ctx, int argc,
2976 const char **argv)
2978 const char *printername;
2979 const char *clientname;
2980 struct policy_handle hnd;
2981 WERROR result;
2982 NTSTATUS status;
2983 struct spoolss_NotifyOption option;
2985 if (argc != 2) {
2986 printf("Usage: %s printername\n", argv[0]);
2987 result = WERR_OK;
2988 goto done;
2991 /* Open printer */
2993 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2995 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2996 printername,
2997 SEC_FLAG_MAXIMUM_ALLOWED,
2998 &hnd);
2999 if (!W_ERROR_IS_OK(result)) {
3000 printf("Error opening %s\n", argv[1]);
3001 goto done;
3004 /* Create spool options */
3006 option.version = 2;
3007 option.count = 2;
3009 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3010 if (option.types == NULL) {
3011 result = WERR_NOMEM;
3012 goto done;
3015 option.types[0].type = PRINTER_NOTIFY_TYPE;
3016 option.types[0].count = 1;
3017 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3018 if (option.types[0].fields == NULL) {
3019 result = WERR_NOMEM;
3020 goto done;
3022 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3024 option.types[1].type = JOB_NOTIFY_TYPE;
3025 option.types[1].count = 1;
3026 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3027 if (option.types[1].fields == NULL) {
3028 result = WERR_NOMEM;
3029 goto done;
3031 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3033 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3034 if (!clientname) {
3035 result = WERR_NOMEM;
3036 goto done;
3039 /* Send rffpcnex */
3041 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3042 &hnd,
3045 clientname,
3046 123,
3047 &option,
3048 &result);
3049 if (!W_ERROR_IS_OK(result)) {
3050 printf("Error rffpcnex %s\n", argv[1]);
3051 goto done;
3054 done:
3055 if (is_valid_policy_hnd(&hnd))
3056 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3058 return result;
3061 /****************************************************************************
3062 ****************************************************************************/
3064 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3065 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3067 union spoolss_PrinterInfo info1, info2;
3068 WERROR werror;
3069 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3071 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3072 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3073 hnd1,
3076 &info1);
3077 if ( !W_ERROR_IS_OK(werror) ) {
3078 printf("failed (%s)\n", win_errstr(werror));
3079 talloc_destroy(mem_ctx);
3080 return false;
3082 printf("ok\n");
3084 printf("Retrieving printer properties for %s...", cli2->desthost);
3085 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3086 hnd2,
3089 &info2);
3090 if ( !W_ERROR_IS_OK(werror) ) {
3091 printf("failed (%s)\n", win_errstr(werror));
3092 talloc_destroy(mem_ctx);
3093 return false;
3095 printf("ok\n");
3097 talloc_destroy(mem_ctx);
3099 return true;
3102 /****************************************************************************
3103 ****************************************************************************/
3105 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3106 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3108 union spoolss_PrinterInfo info1, info2;
3109 WERROR werror;
3110 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3111 SEC_DESC *sd1, *sd2;
3112 bool result = true;
3115 printf("Retrieving printer security for %s...", cli1->desthost);
3116 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3117 hnd1,
3120 &info1);
3121 if ( !W_ERROR_IS_OK(werror) ) {
3122 printf("failed (%s)\n", win_errstr(werror));
3123 result = false;
3124 goto done;
3126 printf("ok\n");
3128 printf("Retrieving printer security for %s...", cli2->desthost);
3129 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3130 hnd2,
3133 &info2);
3134 if ( !W_ERROR_IS_OK(werror) ) {
3135 printf("failed (%s)\n", win_errstr(werror));
3136 result = false;
3137 goto done;
3139 printf("ok\n");
3142 printf("++ ");
3144 sd1 = info1.info3.secdesc;
3145 sd2 = info2.info3.secdesc;
3147 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3148 printf("NULL secdesc!\n");
3149 result = false;
3150 goto done;
3153 if (!security_descriptor_equal( sd1, sd2 ) ) {
3154 printf("Security Descriptors *not* equal!\n");
3155 result = false;
3156 goto done;
3159 printf("Security descriptors match\n");
3161 done:
3162 talloc_destroy(mem_ctx);
3163 return result;
3167 /****************************************************************************
3168 ****************************************************************************/
3170 extern struct user_auth_info *rpcclient_auth_info;
3172 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3173 TALLOC_CTX *mem_ctx, int argc,
3174 const char **argv)
3176 const char *printername;
3177 char *printername_path = NULL;
3178 struct cli_state *cli_server2 = NULL;
3179 struct rpc_pipe_client *cli2 = NULL;
3180 struct policy_handle hPrinter1, hPrinter2;
3181 NTSTATUS nt_status;
3182 WERROR werror;
3184 if ( argc != 3 ) {
3185 printf("Usage: %s <printer> <server>\n", argv[0]);
3186 return WERR_OK;
3189 printername = argv[1];
3191 /* first get the connection to the remote server */
3193 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3194 NULL, 0,
3195 "IPC$", "IPC",
3196 get_cmdline_auth_info_username(rpcclient_auth_info),
3197 lp_workgroup(),
3198 get_cmdline_auth_info_password(rpcclient_auth_info),
3199 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3200 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3202 if ( !NT_STATUS_IS_OK(nt_status) )
3203 return WERR_GENERAL_FAILURE;
3205 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3206 &cli2);
3207 if (!NT_STATUS_IS_OK(nt_status)) {
3208 printf("failed to open spoolss pipe on server %s (%s)\n",
3209 argv[2], nt_errstr(nt_status));
3210 return WERR_GENERAL_FAILURE;
3213 /* now open up both printers */
3215 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3217 printf("Opening %s...", printername_path);
3219 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3220 printername_path,
3221 PRINTER_ALL_ACCESS,
3222 &hPrinter1);
3223 if ( !W_ERROR_IS_OK(werror) ) {
3224 printf("failed (%s)\n", win_errstr(werror));
3225 goto done;
3227 printf("ok\n");
3229 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3231 printf("Opening %s...", printername_path);
3232 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3233 printername_path,
3234 PRINTER_ALL_ACCESS,
3235 &hPrinter2);
3236 if ( !W_ERROR_IS_OK(werror) ) {
3237 printf("failed (%s)\n", win_errstr(werror));
3238 goto done;
3240 printf("ok\n");
3242 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3243 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3244 #if 0
3245 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3246 #endif
3249 done:
3250 /* cleanup */
3252 printf("Closing printers...");
3253 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3254 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3255 printf("ok\n");
3257 /* close the second remote connection */
3259 cli_shutdown( cli_server2 );
3260 return WERR_OK;
3263 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3265 printf("print_processor_name: %s\n", r->print_processor_name);
3268 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3269 TALLOC_CTX *mem_ctx, int argc,
3270 const char **argv)
3272 WERROR werror;
3273 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3274 uint32_t num_procs, level = 1, i;
3275 union spoolss_PrintProcessorInfo *procs;
3277 /* Parse the command arguments */
3279 if (argc < 1 || argc > 4) {
3280 printf ("Usage: %s [environment] [level]\n", argv[0]);
3281 return WERR_OK;
3284 if (argc >= 2) {
3285 environment = argv[1];
3288 if (argc == 3) {
3289 level = atoi(argv[2]);
3292 /* Enumerate Print Processors */
3294 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3295 cli->srv_name_slash,
3296 environment,
3297 level,
3299 &num_procs,
3300 &procs);
3301 if (!W_ERROR_IS_OK(werror))
3302 goto done;
3304 /* Display output */
3306 for (i = 0; i < num_procs; i++) {
3307 switch (level) {
3308 case 1:
3309 display_proc_info1(&procs[i].info1);
3310 break;
3314 done:
3315 return werror;
3318 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3320 printf("name_array: %s\n", r->name_array);
3323 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3324 TALLOC_CTX *mem_ctx, int argc,
3325 const char **argv)
3327 WERROR werror;
3328 const char *print_processor_name = "winprint";
3329 uint32_t num_procs, level = 1, i;
3330 union spoolss_PrintProcDataTypesInfo *procs;
3332 /* Parse the command arguments */
3334 if (argc < 1 || argc > 4) {
3335 printf ("Usage: %s [environment] [level]\n", argv[0]);
3336 return WERR_OK;
3339 if (argc >= 2) {
3340 print_processor_name = argv[1];
3343 if (argc == 3) {
3344 level = atoi(argv[2]);
3347 /* Enumerate Print Processor Data Types */
3349 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3350 cli->srv_name_slash,
3351 print_processor_name,
3352 level,
3354 &num_procs,
3355 &procs);
3356 if (!W_ERROR_IS_OK(werror))
3357 goto done;
3359 /* Display output */
3361 for (i = 0; i < num_procs; i++) {
3362 switch (level) {
3363 case 1:
3364 display_proc_data_types_info1(&procs[i].info1);
3365 break;
3369 done:
3370 return werror;
3373 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3375 printf("monitor_name: %s\n", r->monitor_name);
3378 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3380 printf("monitor_name: %s\n", r->monitor_name);
3381 printf("environment: %s\n", r->environment);
3382 printf("dll_name: %s\n", r->dll_name);
3385 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3386 TALLOC_CTX *mem_ctx, int argc,
3387 const char **argv)
3389 WERROR werror;
3390 uint32_t count, level = 1, i;
3391 union spoolss_MonitorInfo *info;
3393 /* Parse the command arguments */
3395 if (argc > 2) {
3396 printf("Usage: %s [level]\n", argv[0]);
3397 return WERR_OK;
3400 if (argc == 2) {
3401 level = atoi(argv[1]);
3404 /* Enumerate Print Monitors */
3406 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3407 cli->srv_name_slash,
3408 level,
3410 &count,
3411 &info);
3412 if (!W_ERROR_IS_OK(werror)) {
3413 goto done;
3416 /* Display output */
3418 for (i = 0; i < count; i++) {
3419 switch (level) {
3420 case 1:
3421 display_monitor1(&info[i].info1);
3422 break;
3423 case 2:
3424 display_monitor2(&info[i].info2);
3425 break;
3429 done:
3430 return werror;
3433 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3434 TALLOC_CTX *mem_ctx, int argc,
3435 const char **argv)
3437 WERROR result;
3438 NTSTATUS status;
3439 struct policy_handle handle, gdi_handle;
3440 const char *printername;
3441 struct spoolss_DevmodeContainer devmode_ctr;
3443 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3445 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3446 printername,
3447 SEC_FLAG_MAXIMUM_ALLOWED,
3448 &handle);
3449 if (!W_ERROR_IS_OK(result)) {
3450 return result;
3453 ZERO_STRUCT(devmode_ctr);
3455 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3456 &handle,
3457 &gdi_handle,
3458 &devmode_ctr,
3459 &result);
3460 if (!W_ERROR_IS_OK(result)) {
3461 goto done;
3464 done:
3465 if (is_valid_policy_hnd(&gdi_handle)) {
3466 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3468 if (is_valid_policy_hnd(&handle)) {
3469 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3472 return result;
3475 /* List of commands exported by this module */
3476 struct cmd_set spoolss_commands[] = {
3478 { "SPOOLSS" },
3480 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3481 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3482 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3483 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3484 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3485 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3486 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3487 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3488 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3489 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3490 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3491 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3492 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3493 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3494 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3495 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3496 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3497 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3498 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3499 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3500 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3501 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3502 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3503 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3504 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3505 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3506 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3507 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3508 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3509 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3510 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3511 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3512 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3513 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3514 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3516 { NULL }