s3: Lift the server_messaging_context from notify_job_status
[Samba/gbeck.git] / source3 / rpcclient / cmd_spoolss.c
blob0cfceec9e76be967ee554cd7e0c32c60259d6bcb
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9 Copyright (C) Guenther Deschner 2009
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "rpcclient.h"
27 #include "../librpc/gen_ndr/cli_spoolss.h"
28 #include "rpc_client/cli_spoolss.h"
29 #include "rpc_client/init_spoolss.h"
30 #include "registry.h"
31 #include "registry/reg_objects.h"
32 #include "nt_printing.h"
34 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
35 { \
36 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
37 _cli->srv_name_slash, _arg); \
38 W_ERROR_HAVE_NO_MEMORY(_printername); \
41 /* The version int is used by getdrivers. Note that
42 all architecture strings that support mutliple
43 versions must be grouped together since enumdrivers
44 uses this property to prevent issuing multiple
45 enumdriver calls for the same arch */
48 static const struct print_architecture_table_node archi_table[]= {
50 {"Windows 4.0", "WIN40", 0 },
51 {"Windows NT x86", "W32X86", 2 },
52 {"Windows NT x86", "W32X86", 3 },
53 {"Windows NT R4000", "W32MIPS", 2 },
54 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
55 {"Windows NT PowerPC", "W32PPC", 2 },
56 {"Windows IA64", "IA64", 3 },
57 {"Windows x64", "x64", 3 },
58 {NULL, "", -1 }
61 /**
62 * @file
64 * rpcclient module for SPOOLSS rpc pipe.
66 * This generally just parses and checks command lines, and then calls
67 * a cli_spoolss function.
68 **/
70 /****************************************************************************
71 function to do the mapping between the long architecture name and
72 the short one.
73 ****************************************************************************/
75 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
77 int i=-1;
79 DEBUG(107,("Getting architecture dependant directory\n"));
80 do {
81 i++;
82 } while ( (archi_table[i].long_archi!=NULL ) &&
83 StrCaseCmp(long_archi, archi_table[i].long_archi) );
85 if (archi_table[i].long_archi==NULL) {
86 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
87 return NULL;
90 /* this might be client code - but shouldn't this be an fstrcpy etc? */
93 DEBUGADD(108,("index: [%d]\n", i));
94 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
95 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
97 return archi_table[i].short_archi;
100 /****************************************************************************
101 ****************************************************************************/
103 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
104 TALLOC_CTX *mem_ctx,
105 int argc, const char **argv)
107 WERROR werror;
108 struct policy_handle hnd;
109 uint32_t access_mask = PRINTER_ALL_ACCESS;
111 if (argc < 2) {
112 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
113 return WERR_OK;
116 if (argc >= 3) {
117 sscanf(argv[2], "%x", &access_mask);
120 /* Open the printer handle */
122 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
123 argv[1],
124 access_mask,
125 &hnd);
126 if (W_ERROR_IS_OK(werror)) {
127 printf("Printer %s opened successfully\n", argv[1]);
128 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
130 if (!W_ERROR_IS_OK(werror)) {
131 printf("Error closing printer handle! (%s)\n",
132 get_dos_error_msg(werror));
136 return werror;
140 /****************************************************************************
141 ****************************************************************************/
143 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
145 if (!r)
146 return;
148 printf("\tprintername:[%s]\n", r->printername);
149 printf("\tservername:[%s]\n", r->servername);
150 printf("\tcjobs:[0x%x]\n", r->cjobs);
151 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
152 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
153 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
154 r->time.day, r->time.day_of_week);
155 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
156 r->time.second, r->time.millisecond);
158 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
159 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
161 printf("\tversion:[0x%x]\n", r->version);
162 printf("\tfree_build:[0x%x]\n", r->free_build);
163 printf("\tspooling:[0x%x]\n", r->spooling);
164 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
165 printf("\tsession_counter:[0x%x]\n", r->session_counter);
166 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
167 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
168 printf("\tjob_error:[0x%x]\n", r->job_error);
169 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
170 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
171 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
172 printf("\tchange_id:[0x%x]\n", r->change_id);
173 printf("\tlast_error: %s\n", win_errstr(r->last_error));
174 printf("\tstatus:[0x%x]\n", r->status);
175 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
176 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
177 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
178 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
179 printf("\tref_ic:[0x%x]\n", r->ref_ic);
180 printf("\treserved2:[0x%x]\n", r->reserved2);
181 printf("\treserved3:[0x%x]\n", r->reserved3);
183 printf("\n");
186 /****************************************************************************
187 ****************************************************************************/
189 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
191 printf("\tflags:[0x%x]\n", r->flags);
192 printf("\tname:[%s]\n", r->name);
193 printf("\tdescription:[%s]\n", r->description);
194 printf("\tcomment:[%s]\n", r->comment);
196 printf("\n");
199 /****************************************************************************
200 ****************************************************************************/
202 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
204 printf("\tservername:[%s]\n", r->servername);
205 printf("\tprintername:[%s]\n", r->printername);
206 printf("\tsharename:[%s]\n", r->sharename);
207 printf("\tportname:[%s]\n", r->portname);
208 printf("\tdrivername:[%s]\n", r->drivername);
209 printf("\tcomment:[%s]\n", r->comment);
210 printf("\tlocation:[%s]\n", r->location);
211 printf("\tsepfile:[%s]\n", r->sepfile);
212 printf("\tprintprocessor:[%s]\n", r->printprocessor);
213 printf("\tdatatype:[%s]\n", r->datatype);
214 printf("\tparameters:[%s]\n", r->parameters);
215 printf("\tattributes:[0x%x]\n", r->attributes);
216 printf("\tpriority:[0x%x]\n", r->priority);
217 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
218 printf("\tstarttime:[0x%x]\n", r->starttime);
219 printf("\tuntiltime:[0x%x]\n", r->untiltime);
220 printf("\tstatus:[0x%x]\n", r->status);
221 printf("\tcjobs:[0x%x]\n", r->cjobs);
222 printf("\taverageppm:[0x%x]\n", r->averageppm);
224 if (r->secdesc)
225 display_sec_desc(r->secdesc);
227 printf("\n");
230 /****************************************************************************
231 ****************************************************************************/
233 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
235 display_sec_desc(r->secdesc);
237 printf("\n");
240 /****************************************************************************
241 ****************************************************************************/
243 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
245 printf("\tservername:[%s]\n", r->servername);
246 printf("\tprintername:[%s]\n", r->printername);
247 printf("\tattributes:[0x%x]\n", r->attributes);
248 printf("\n");
251 /****************************************************************************
252 ****************************************************************************/
254 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
256 printf("\tprintername:[%s]\n", r->printername);
257 printf("\tportname:[%s]\n", r->portname);
258 printf("\tattributes:[0x%x]\n", r->attributes);
259 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
260 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
261 printf("\n");
264 /****************************************************************************
265 ****************************************************************************/
267 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
269 printf("\tstatus:[0x%x]\n", r->status);
270 printf("\n");
273 /****************************************************************************
274 ****************************************************************************/
276 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
278 printf("\tguid:[%s]\n", r->guid);
279 printf("\taction:[0x%x]\n", r->action);
280 printf("\n");
283 /****************************************************************************
284 ****************************************************************************/
286 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
287 TALLOC_CTX *mem_ctx,
288 int argc, const char **argv)
290 WERROR result;
291 uint32_t level = 1;
292 union spoolss_PrinterInfo *info;
293 uint32_t i, count;
294 const char *name;
295 uint32_t flags = PRINTER_ENUM_LOCAL;
297 if (argc > 4) {
298 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
299 return WERR_OK;
302 if (argc >= 2) {
303 level = atoi(argv[1]);
306 if (argc >= 3) {
307 name = argv[2];
308 } else {
309 name = cli->srv_name_slash;
312 if (argc == 4) {
313 flags = atoi(argv[3]);
316 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
317 flags,
318 name,
319 level,
321 &count,
322 &info);
323 if (W_ERROR_IS_OK(result)) {
325 if (!count) {
326 printf ("No printers returned.\n");
327 goto done;
330 for (i = 0; i < count; i++) {
331 switch (level) {
332 case 0:
333 display_print_info0(&info[i].info0);
334 break;
335 case 1:
336 display_print_info1(&info[i].info1);
337 break;
338 case 2:
339 display_print_info2(&info[i].info2);
340 break;
341 case 3:
342 display_print_info3(&info[i].info3);
343 break;
344 case 4:
345 display_print_info4(&info[i].info4);
346 break;
347 case 5:
348 display_print_info5(&info[i].info5);
349 break;
350 case 6:
351 display_print_info6(&info[i].info6);
352 break;
353 default:
354 printf("unknown info level %d\n", level);
355 goto done;
359 done:
361 return result;
364 /****************************************************************************
365 ****************************************************************************/
367 static void display_port_info_1(struct spoolss_PortInfo1 *r)
369 printf("\tPort Name:\t[%s]\n", r->port_name);
372 /****************************************************************************
373 ****************************************************************************/
375 static void display_port_info_2(struct spoolss_PortInfo2 *r)
377 printf("\tPort Name:\t[%s]\n", r->port_name);
378 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
379 printf("\tDescription:\t[%s]\n", r->description);
380 printf("\tPort Type:\t" );
381 if (r->port_type) {
382 int comma = 0; /* hack */
383 printf( "[" );
384 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
385 printf( "Read" );
386 comma = 1;
388 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
389 printf( "%sWrite", comma ? ", " : "" );
390 comma = 1;
392 /* These two have slightly different interpretations
393 on 95/98/ME but I'm disregarding that for now */
394 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
395 printf( "%sRedirected", comma ? ", " : "" );
396 comma = 1;
398 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
399 printf( "%sNet-Attached", comma ? ", " : "" );
401 printf( "]\n" );
402 } else {
403 printf( "[Unset]\n" );
405 printf("\tReserved:\t[%d]\n", r->reserved);
406 printf("\n");
409 /****************************************************************************
410 ****************************************************************************/
412 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
413 TALLOC_CTX *mem_ctx, int argc,
414 const char **argv)
416 WERROR result;
417 uint32_t level = 1;
418 uint32_t count;
419 union spoolss_PortInfo *info;
421 if (argc > 2) {
422 printf("Usage: %s [level]\n", argv[0]);
423 return WERR_OK;
426 if (argc == 2) {
427 level = atoi(argv[1]);
430 /* Enumerate ports */
432 result = rpccli_spoolss_enumports(cli, mem_ctx,
433 cli->srv_name_slash,
434 level,
436 &count,
437 &info);
438 if (W_ERROR_IS_OK(result)) {
439 int i;
441 for (i = 0; i < count; i++) {
442 switch (level) {
443 case 1:
444 display_port_info_1(&info[i].info1);
445 break;
446 case 2:
447 display_port_info_2(&info[i].info2);
448 break;
449 default:
450 printf("unknown info level %d\n", level);
451 break;
456 return result;
459 /****************************************************************************
460 ****************************************************************************/
462 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
463 TALLOC_CTX *mem_ctx,
464 int argc, const char **argv)
466 struct policy_handle pol;
467 WERROR result;
468 NTSTATUS status;
469 uint32_t info_level = 2;
470 union spoolss_PrinterInfo info;
471 struct spoolss_SetPrinterInfoCtr info_ctr;
472 struct spoolss_SetPrinterInfo2 info2;
473 const char *printername, *comment = NULL;
474 struct spoolss_DevmodeContainer devmode_ctr;
475 struct sec_desc_buf secdesc_ctr;
477 if (argc == 1 || argc > 3) {
478 printf("Usage: %s printername comment\n", argv[0]);
480 return WERR_OK;
483 /* Open a printer handle */
484 if (argc == 3) {
485 comment = argv[2];
488 ZERO_STRUCT(devmode_ctr);
489 ZERO_STRUCT(secdesc_ctr);
491 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
493 /* get a printer handle */
494 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
495 printername,
496 PRINTER_ALL_ACCESS,
497 &pol);
498 if (!W_ERROR_IS_OK(result))
499 goto done;
501 /* Get printer info */
502 result = rpccli_spoolss_getprinter(cli, mem_ctx,
503 &pol,
504 info_level,
506 &info);
507 if (!W_ERROR_IS_OK(result))
508 goto done;
511 /* Modify the comment. */
512 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
513 info2.comment = comment;
515 info_ctr.level = 2;
516 info_ctr.info.info2 = &info2;
518 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
519 &pol,
520 &info_ctr,
521 &devmode_ctr,
522 &secdesc_ctr,
523 0, /* command */
524 &result);
525 if (W_ERROR_IS_OK(result))
526 printf("Success in setting comment.\n");
528 done:
529 if (is_valid_policy_hnd(&pol))
530 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
532 return result;
535 /****************************************************************************
536 ****************************************************************************/
538 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
539 TALLOC_CTX *mem_ctx,
540 int argc, const char **argv)
542 struct policy_handle pol;
543 WERROR result;
544 NTSTATUS status;
545 uint32_t info_level = 2;
546 union spoolss_PrinterInfo info;
547 const char *printername,
548 *new_printername = NULL;
549 struct spoolss_SetPrinterInfoCtr info_ctr;
550 struct spoolss_SetPrinterInfo2 info2;
551 struct spoolss_DevmodeContainer devmode_ctr;
552 struct sec_desc_buf secdesc_ctr;
554 ZERO_STRUCT(devmode_ctr);
555 ZERO_STRUCT(secdesc_ctr);
557 if (argc == 1 || argc > 3) {
558 printf("Usage: %s printername new_printername\n", argv[0]);
560 return WERR_OK;
563 /* Open a printer handle */
564 if (argc == 3) {
565 new_printername = argv[2];
568 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
570 /* get a printer handle */
571 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
572 printername,
573 PRINTER_ALL_ACCESS,
574 &pol);
575 if (!W_ERROR_IS_OK(result))
576 goto done;
578 /* Get printer info */
579 result = rpccli_spoolss_getprinter(cli, mem_ctx,
580 &pol,
581 info_level,
583 &info);
584 if (!W_ERROR_IS_OK(result))
585 goto done;
587 /* Modify the printername. */
588 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
589 info2.printername = new_printername;
591 info_ctr.level = 2;
592 info_ctr.info.info2 = &info2;
594 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
595 &pol,
596 &info_ctr,
597 &devmode_ctr,
598 &secdesc_ctr,
599 0, /* command */
600 &result);
601 if (W_ERROR_IS_OK(result))
602 printf("Success in setting printername.\n");
604 done:
605 if (is_valid_policy_hnd(&pol))
606 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
608 return result;
611 /****************************************************************************
612 ****************************************************************************/
614 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
615 TALLOC_CTX *mem_ctx,
616 int argc, const char **argv)
618 struct policy_handle pol;
619 WERROR result;
620 uint32_t level = 1;
621 const char *printername;
622 union spoolss_PrinterInfo info;
624 if (argc == 1 || argc > 3) {
625 printf("Usage: %s <printername> [level]\n", argv[0]);
626 return WERR_OK;
629 /* Open a printer handle */
630 if (argc == 3) {
631 level = atoi(argv[2]);
634 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
636 /* get a printer handle */
638 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
639 printername,
640 SEC_FLAG_MAXIMUM_ALLOWED,
641 &pol);
642 if (!W_ERROR_IS_OK(result)) {
643 goto done;
646 /* Get printer info */
648 result = rpccli_spoolss_getprinter(cli, mem_ctx,
649 &pol,
650 level,
652 &info);
653 if (!W_ERROR_IS_OK(result)) {
654 goto done;
657 /* Display printer info */
658 switch (level) {
659 case 0:
660 display_print_info0(&info.info0);
661 break;
662 case 1:
663 display_print_info1(&info.info1);
664 break;
665 case 2:
666 display_print_info2(&info.info2);
667 break;
668 case 3:
669 display_print_info3(&info.info3);
670 break;
671 case 4:
672 display_print_info4(&info.info4);
673 break;
674 case 5:
675 display_print_info5(&info.info5);
676 break;
677 case 6:
678 display_print_info6(&info.info6);
679 break;
680 case 7:
681 display_print_info7(&info.info7);
682 break;
683 default:
684 printf("unknown info level %d\n", level);
685 break;
687 done:
688 if (is_valid_policy_hnd(&pol)) {
689 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
692 return result;
695 /****************************************************************************
696 ****************************************************************************/
698 static void display_reg_value(struct regval_blob *value)
700 const char *text = NULL;
701 DATA_BLOB blob;
703 switch(regval_type(value)) {
704 case REG_DWORD:
705 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
706 *((uint32_t *) regval_data_p(value)));
707 break;
708 case REG_SZ:
709 blob = data_blob_const(regval_data_p(value), regval_size(value));
710 pull_reg_sz(talloc_tos(), &blob, &text);
711 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
712 break;
713 case REG_BINARY: {
714 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
715 size_t i, len;
716 printf("%s: REG_BINARY:", regval_name(value));
717 len = strlen(hex);
718 for (i=0; i<len; i++) {
719 if (hex[i] == '\0') {
720 break;
722 if (i%40 == 0) {
723 putchar('\n');
725 putchar(hex[i]);
727 TALLOC_FREE(hex);
728 putchar('\n');
729 break;
731 case REG_MULTI_SZ: {
732 uint32_t i;
733 const char **values;
734 blob = data_blob_const(regval_data_p(value), regval_size(value));
736 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
737 d_printf("pull_reg_multi_sz failed\n");
738 break;
741 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
742 for (i=0; values[i] != NULL; i++) {
743 d_printf("%s\n", values[i]);
745 TALLOC_FREE(values);
746 break;
748 default:
749 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
754 /****************************************************************************
755 ****************************************************************************/
757 static void display_printer_data(const char *v,
758 enum winreg_Type type,
759 uint8_t *data,
760 uint32_t length)
762 int i;
763 union spoolss_PrinterData r;
764 DATA_BLOB blob = data_blob_const(data, length);
765 WERROR result;
767 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
768 if (!W_ERROR_IS_OK(result)) {
769 return;
772 switch (type) {
773 case REG_DWORD:
774 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
775 break;
776 case REG_SZ:
777 printf("%s: REG_SZ: %s\n", v, r.string);
778 break;
779 case REG_BINARY: {
780 char *hex = hex_encode_talloc(NULL,
781 r.binary.data, r.binary.length);
782 size_t len;
783 printf("%s: REG_BINARY:", v);
784 len = strlen(hex);
785 for (i=0; i<len; i++) {
786 if (hex[i] == '\0') {
787 break;
789 if (i%40 == 0) {
790 putchar('\n');
792 putchar(hex[i]);
794 TALLOC_FREE(hex);
795 putchar('\n');
796 break;
798 case REG_MULTI_SZ:
799 printf("%s: REG_MULTI_SZ: ", v);
800 for (i=0; r.string_array[i] != NULL; i++) {
801 printf("%s ", r.string_array[i]);
803 printf("\n");
804 break;
805 default:
806 printf("%s: unknown type 0x%02x:\n", v, type);
807 break;
811 /****************************************************************************
812 ****************************************************************************/
814 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
815 TALLOC_CTX *mem_ctx,
816 int argc, const char **argv)
818 struct policy_handle pol;
819 WERROR result;
820 fstring printername;
821 const char *valuename;
822 enum winreg_Type type;
823 uint8_t *data;
824 uint32_t needed;
826 if (argc != 3) {
827 printf("Usage: %s <printername> <valuename>\n", argv[0]);
828 printf("<printername> of . queries print server\n");
829 return WERR_OK;
831 valuename = argv[2];
833 /* Open a printer handle */
835 if (strncmp(argv[1], ".", sizeof(".")) == 0)
836 fstrcpy(printername, cli->srv_name_slash);
837 else
838 slprintf(printername, sizeof(printername)-1, "%s\\%s",
839 cli->srv_name_slash, argv[1]);
841 /* get a printer handle */
843 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
844 printername,
845 SEC_FLAG_MAXIMUM_ALLOWED,
846 &pol);
847 if (!W_ERROR_IS_OK(result))
848 goto done;
850 /* Get printer info */
852 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
853 &pol,
854 valuename,
856 &type,
857 &needed,
858 &data);
859 if (!W_ERROR_IS_OK(result))
860 goto done;
862 /* Display printer data */
864 display_printer_data(valuename, type, data, needed);
866 done:
867 if (is_valid_policy_hnd(&pol))
868 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
870 return result;
873 /****************************************************************************
874 ****************************************************************************/
876 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
877 TALLOC_CTX *mem_ctx,
878 int argc, const char **argv)
880 struct policy_handle pol;
881 WERROR result;
882 NTSTATUS status;
883 fstring printername;
884 const char *valuename, *keyname;
886 enum winreg_Type type;
887 uint8_t *data = NULL;
888 uint32_t offered = 0;
889 uint32_t needed;
891 if (argc != 4) {
892 printf("Usage: %s <printername> <keyname> <valuename>\n",
893 argv[0]);
894 printf("<printername> of . queries print server\n");
895 return WERR_OK;
897 valuename = argv[3];
898 keyname = argv[2];
900 /* Open a printer handle */
902 if (strncmp(argv[1], ".", sizeof(".")) == 0)
903 fstrcpy(printername, cli->srv_name_slash);
904 else
905 slprintf(printername, sizeof(printername)-1, "%s\\%s",
906 cli->srv_name_slash, argv[1]);
908 /* get a printer handle */
910 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
911 printername,
912 SEC_FLAG_MAXIMUM_ALLOWED,
913 &pol);
914 if (!W_ERROR_IS_OK(result))
915 goto done;
917 /* Get printer info */
919 data = talloc_zero_array(mem_ctx, uint8_t, offered);
920 if (!data) {
921 goto done;
924 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
925 &pol,
926 keyname,
927 valuename,
928 &type,
929 data,
930 offered,
931 &needed,
932 &result);
933 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
934 offered = needed;
935 data = talloc_zero_array(mem_ctx, uint8_t, offered);
936 if (!data) {
937 goto done;
939 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
940 &pol,
941 keyname,
942 valuename,
943 &type,
944 data,
945 offered,
946 &needed,
947 &result);
950 if (!NT_STATUS_IS_OK(status)) {
951 goto done;
954 if (!W_ERROR_IS_OK(result))
955 goto done;
957 /* Display printer data */
959 display_printer_data(valuename, type, data, needed);
962 done:
963 if (is_valid_policy_hnd(&pol))
964 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
966 return result;
969 /****************************************************************************
970 ****************************************************************************/
972 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
974 if (!r) {
975 return;
978 printf("Printer Driver Info 1:\n");
979 printf("\tDriver Name: [%s]\n", r->driver_name);
980 printf("\n");
983 /****************************************************************************
984 ****************************************************************************/
986 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
988 if (!r) {
989 return;
992 printf("Printer Driver Info 2:\n");
993 printf("\tVersion: [%x]\n", r->version);
994 printf("\tDriver Name: [%s]\n", r->driver_name);
995 printf("\tArchitecture: [%s]\n", r->architecture);
996 printf("\tDriver Path: [%s]\n", r->driver_path);
997 printf("\tDatafile: [%s]\n", r->data_file);
998 printf("\tConfigfile: [%s]\n", r->config_file);
999 printf("\n");
1002 /****************************************************************************
1003 ****************************************************************************/
1005 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1007 int i;
1009 if (!r) {
1010 return;
1013 printf("Printer Driver Info 3:\n");
1014 printf("\tVersion: [%x]\n", r->version);
1015 printf("\tDriver Name: [%s]\n", r->driver_name);
1016 printf("\tArchitecture: [%s]\n", r->architecture);
1017 printf("\tDriver Path: [%s]\n", r->driver_path);
1018 printf("\tDatafile: [%s]\n", r->data_file);
1019 printf("\tConfigfile: [%s]\n", r->config_file);
1020 printf("\tHelpfile: [%s]\n", r->help_file);
1022 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1023 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1026 printf("\tMonitorname: [%s]\n", r->monitor_name);
1027 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1028 printf("\n");
1031 /****************************************************************************
1032 ****************************************************************************/
1034 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1036 int i;
1038 if (!r) {
1039 return;
1042 printf("Printer Driver Info 4:\n");
1043 printf("\tVersion: [%x]\n", r->version);
1044 printf("\tDriver Name: [%s]\n", r->driver_name);
1045 printf("\tArchitecture: [%s]\n", r->architecture);
1046 printf("\tDriver Path: [%s]\n", r->driver_path);
1047 printf("\tDatafile: [%s]\n", r->data_file);
1048 printf("\tConfigfile: [%s]\n", r->config_file);
1049 printf("\tHelpfile: [%s]\n", r->help_file);
1051 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1052 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1055 printf("\tMonitorname: [%s]\n", r->monitor_name);
1056 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1058 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1059 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1061 printf("\n");
1064 /****************************************************************************
1065 ****************************************************************************/
1067 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1069 if (!r) {
1070 return;
1073 printf("Printer Driver Info 5:\n");
1074 printf("\tVersion: [%x]\n", r->version);
1075 printf("\tDriver Name: [%s]\n", r->driver_name);
1076 printf("\tArchitecture: [%s]\n", r->architecture);
1077 printf("\tDriver Path: [%s]\n", r->driver_path);
1078 printf("\tDatafile: [%s]\n", r->data_file);
1079 printf("\tConfigfile: [%s]\n", r->config_file);
1080 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1081 printf("\tConfig Version: [0x%x]\n", r->config_version);
1082 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1083 printf("\n");
1086 /****************************************************************************
1087 ****************************************************************************/
1089 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1091 int i;
1093 if (!r) {
1094 return;
1097 printf("Printer Driver Info 6:\n");
1098 printf("\tVersion: [%x]\n", r->version);
1099 printf("\tDriver Name: [%s]\n", r->driver_name);
1100 printf("\tArchitecture: [%s]\n", r->architecture);
1101 printf("\tDriver Path: [%s]\n", r->driver_path);
1102 printf("\tDatafile: [%s]\n", r->data_file);
1103 printf("\tConfigfile: [%s]\n", r->config_file);
1104 printf("\tHelpfile: [%s]\n", r->help_file);
1106 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1107 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1110 printf("\tMonitorname: [%s]\n", r->monitor_name);
1111 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1113 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1114 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1117 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1118 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1119 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1120 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1121 printf("\tHardware ID: [%s]\n", r->hardware_id);
1122 printf("\tProvider: [%s]\n", r->provider);
1124 printf("\n");
1127 /****************************************************************************
1128 ****************************************************************************/
1130 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1132 int i;
1134 if (!r) {
1135 return;
1138 printf("Printer Driver Info 8:\n");
1139 printf("\tVersion: [%x]\n", r->version);
1140 printf("\tDriver Name: [%s]\n", r->driver_name);
1141 printf("\tArchitecture: [%s]\n", r->architecture);
1142 printf("\tDriver Path: [%s]\n", r->driver_path);
1143 printf("\tDatafile: [%s]\n", r->data_file);
1144 printf("\tConfigfile: [%s]\n", r->config_file);
1145 printf("\tHelpfile: [%s]\n", r->help_file);
1146 printf("\tMonitorname: [%s]\n", r->monitor_name);
1147 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1149 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1150 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1153 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1154 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1157 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1158 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1159 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1160 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1161 printf("\tHardware ID: [%s]\n", r->hardware_id);
1162 printf("\tProvider: [%s]\n", r->provider);
1163 printf("\tPrint Processor: [%s]\n", r->print_processor);
1164 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1165 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1166 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1168 printf("\tInf Path: [%s]\n", r->inf_path);
1169 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1170 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1171 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1173 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1174 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1175 (long long unsigned int)r->min_inbox_driver_ver_version);
1177 printf("\n");
1180 /****************************************************************************
1181 ****************************************************************************/
1183 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1184 TALLOC_CTX *mem_ctx,
1185 int argc, const char **argv)
1187 struct policy_handle pol;
1188 WERROR werror;
1189 uint32_t level = 3;
1190 const char *printername;
1191 uint32_t i;
1192 bool success = false;
1193 union spoolss_DriverInfo info;
1194 uint32_t server_major_version;
1195 uint32_t server_minor_version;
1197 if ((argc == 1) || (argc > 3)) {
1198 printf("Usage: %s <printername> [level]\n", argv[0]);
1199 return WERR_OK;
1202 /* get the arguments need to open the printer handle */
1204 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1206 if (argc == 3) {
1207 level = atoi(argv[2]);
1210 /* Open a printer handle */
1212 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1213 printername,
1214 PRINTER_ACCESS_USE,
1215 &pol);
1216 if (!W_ERROR_IS_OK(werror)) {
1217 printf("Error opening printer handle for %s!\n", printername);
1218 return werror;
1221 /* loop through and print driver info level for each architecture */
1223 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1225 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1226 &pol,
1227 archi_table[i].long_archi,
1228 level,
1229 0, /* offered */
1230 archi_table[i].version,
1232 &info,
1233 &server_major_version,
1234 &server_minor_version);
1235 if (!W_ERROR_IS_OK(werror)) {
1236 continue;
1239 /* need at least one success */
1241 success = true;
1243 printf("\n[%s]\n", archi_table[i].long_archi);
1245 switch (level) {
1246 case 1:
1247 display_print_driver1(&info.info1);
1248 break;
1249 case 2:
1250 display_print_driver2(&info.info2);
1251 break;
1252 case 3:
1253 display_print_driver3(&info.info3);
1254 break;
1255 case 4:
1256 display_print_driver4(&info.info4);
1257 break;
1258 case 5:
1259 display_print_driver5(&info.info5);
1260 break;
1261 case 6:
1262 display_print_driver6(&info.info6);
1263 break;
1264 case 8:
1265 display_print_driver8(&info.info8);
1266 break;
1267 default:
1268 printf("unknown info level %d\n", level);
1269 break;
1273 /* Cleanup */
1275 if (is_valid_policy_hnd(&pol)) {
1276 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1279 if (success) {
1280 werror = WERR_OK;
1283 return werror;
1286 /****************************************************************************
1287 ****************************************************************************/
1289 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1290 TALLOC_CTX *mem_ctx,
1291 const char *architecture,
1292 uint32_t level)
1294 WERROR werror;
1295 uint32_t count = 0;
1296 union spoolss_DriverInfo *info = NULL;
1297 uint32_t j;
1299 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1300 cli->srv_name_slash,
1301 architecture,
1302 level,
1304 &count,
1305 &info);
1307 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1308 printf("Server does not support environment [%s]\n",
1309 architecture);
1310 return WERR_OK;
1313 if (count == 0) {
1314 return WERR_OK;
1317 if (!W_ERROR_IS_OK(werror)) {
1318 printf("Error getting driver for environment [%s] - %s\n",
1319 architecture, win_errstr(werror));
1320 return werror;
1323 printf("\n[%s]\n", architecture);
1325 switch (level) {
1326 case 1:
1327 for (j=0; j < count; j++) {
1328 display_print_driver1(&info[j].info1);
1330 break;
1331 case 2:
1332 for (j=0; j < count; j++) {
1333 display_print_driver2(&info[j].info2);
1335 break;
1336 case 3:
1337 for (j=0; j < count; j++) {
1338 display_print_driver3(&info[j].info3);
1340 break;
1341 case 4:
1342 for (j=0; j < count; j++) {
1343 display_print_driver4(&info[j].info4);
1345 break;
1346 case 5:
1347 for (j=0; j < count; j++) {
1348 display_print_driver5(&info[j].info5);
1350 break;
1351 case 6:
1352 for (j=0; j < count; j++) {
1353 display_print_driver6(&info[j].info6);
1355 break;
1356 case 8:
1357 for (j=0; j < count; j++) {
1358 display_print_driver8(&info[j].info8);
1360 break;
1361 default:
1362 printf("unknown info level %d\n", level);
1363 return WERR_UNKNOWN_LEVEL;
1366 return werror;
1369 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1370 TALLOC_CTX *mem_ctx,
1371 int argc, const char **argv)
1373 WERROR werror = WERR_OK;
1374 uint32_t level = 1;
1375 uint32_t i;
1376 const char *architecture = NULL;
1378 if (argc > 3) {
1379 printf("Usage: enumdrivers [level] [architecture]\n");
1380 return WERR_OK;
1383 if (argc >= 2) {
1384 level = atoi(argv[1]);
1387 if (argc == 3) {
1388 architecture = argv[2];
1391 if (architecture) {
1392 return enum_driver_by_architecture(cli, mem_ctx,
1393 architecture,
1394 level);
1397 /* loop through and print driver info level for each architecture */
1398 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1399 /* check to see if we already asked for this architecture string */
1401 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1402 continue;
1405 werror = enum_driver_by_architecture(cli, mem_ctx,
1406 archi_table[i].long_archi,
1407 level);
1408 if (!W_ERROR_IS_OK(werror)) {
1409 break;
1413 return werror;
1416 /****************************************************************************
1417 ****************************************************************************/
1419 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1421 printf("\tDirectory Name:[%s]\n", r->directory_name);
1424 /****************************************************************************
1425 ****************************************************************************/
1427 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1428 TALLOC_CTX *mem_ctx,
1429 int argc, const char **argv)
1431 WERROR result;
1432 NTSTATUS status;
1433 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1434 DATA_BLOB buffer;
1435 uint32_t offered;
1436 union spoolss_DriverDirectoryInfo info;
1437 uint32_t needed;
1439 if (argc > 2) {
1440 printf("Usage: %s [environment]\n", argv[0]);
1441 return WERR_OK;
1444 /* Get the arguments need to open the printer handle */
1446 if (argc == 2) {
1447 env = argv[1];
1450 /* Get the directory. Only use Info level 1 */
1452 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1453 cli->srv_name_slash,
1454 env,
1456 NULL, /* buffer */
1457 0, /* offered */
1458 NULL, /* info */
1459 &needed,
1460 &result);
1461 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1462 offered = needed;
1463 buffer = data_blob_talloc_zero(mem_ctx, needed);
1465 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1466 cli->srv_name_slash,
1467 env,
1469 &buffer,
1470 offered,
1471 &info,
1472 &needed,
1473 &result);
1476 if (W_ERROR_IS_OK(result)) {
1477 display_printdriverdir_1(&info.info1);
1480 return result;
1483 /****************************************************************************
1484 ****************************************************************************/
1486 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1487 struct spoolss_AddDriverInfo3 *info,
1488 const char *arch)
1491 int i;
1493 for (i=0; archi_table[i].long_archi != NULL; i++)
1495 if (strcmp(arch, archi_table[i].short_archi) == 0)
1497 info->version = archi_table[i].version;
1498 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1499 break;
1503 if (archi_table[i].long_archi == NULL)
1505 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1508 return;
1512 /**************************************************************************
1513 wrapper for strtok to get the next parameter from a delimited list.
1514 Needed to handle the empty parameter string denoted by "NULL"
1515 *************************************************************************/
1517 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1518 const char *delim, const char **dest,
1519 char **saveptr)
1521 char *ptr;
1523 /* get the next token */
1524 ptr = strtok_r(str, delim, saveptr);
1526 /* a string of 'NULL' is used to represent an empty
1527 parameter because two consecutive delimiters
1528 will not return an empty string. See man strtok(3)
1529 for details */
1530 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1531 ptr = NULL;
1534 if (dest != NULL) {
1535 *dest = talloc_strdup(mem_ctx, ptr);
1538 return ptr;
1541 /********************************************************************************
1542 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1543 string in the form of
1544 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1545 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1546 <Default Data Type>:<Comma Separated list of Files>
1547 *******************************************************************************/
1549 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1550 char *args)
1552 char *str, *str2;
1553 int count = 0;
1554 char *saveptr = NULL;
1555 struct spoolss_StringArray *deps;
1556 const char **file_array = NULL;
1557 int i;
1559 /* fill in the UNISTR fields */
1560 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1561 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1562 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1563 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1564 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1565 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1566 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1568 /* <Comma Separated List of Dependent Files> */
1569 /* save the beginning of the string */
1570 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1571 str = str2;
1573 /* begin to strip out each filename */
1574 str = strtok_r(str, ",", &saveptr);
1576 /* no dependent files, we are done */
1577 if (!str) {
1578 return true;
1581 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1582 if (!deps) {
1583 return false;
1586 while (str != NULL) {
1587 add_string_to_array(deps, str, &file_array, &count);
1588 str = strtok_r(NULL, ",", &saveptr);
1591 deps->string = talloc_zero_array(deps, const char *, count + 1);
1592 if (!deps->string) {
1593 return false;
1596 for (i=0; i < count; i++) {
1597 deps->string[i] = file_array[i];
1600 r->dependent_files = deps;
1602 return true;
1605 /****************************************************************************
1606 ****************************************************************************/
1608 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1609 TALLOC_CTX *mem_ctx,
1610 int argc, const char **argv)
1612 WERROR result;
1613 NTSTATUS status;
1614 uint32_t level = 3;
1615 struct spoolss_AddDriverInfoCtr info_ctr;
1616 struct spoolss_AddDriverInfo3 info3;
1617 const char *arch;
1618 char *driver_args;
1620 /* parse the command arguments */
1621 if (argc != 3 && argc != 4)
1623 printf ("Usage: %s <Environment> \\\n", argv[0]);
1624 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1625 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1626 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1627 printf ("\t[version]\n");
1629 return WERR_OK;
1632 /* Fill in the spoolss_AddDriverInfo3 struct */
1633 ZERO_STRUCT(info3);
1635 arch = cmd_spoolss_get_short_archi(argv[1]);
1636 if (!arch) {
1637 printf ("Error Unknown architechture [%s]\n", argv[1]);
1638 return WERR_INVALID_PARAM;
1641 set_drv_info_3_env(mem_ctx, &info3, arch);
1643 driver_args = talloc_strdup( mem_ctx, argv[2] );
1644 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1646 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1647 return WERR_INVALID_PARAM;
1650 /* if printer driver version specified, override the default version
1651 * used by the architecture. This allows installation of Windows
1652 * 2000 (version 3) printer drivers. */
1653 if (argc == 4)
1655 info3.version = atoi(argv[3]);
1659 info_ctr.level = level;
1660 info_ctr.info.info3 = &info3;
1662 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1663 cli->srv_name_slash,
1664 &info_ctr,
1665 &result);
1666 if (!NT_STATUS_IS_OK(status)) {
1667 return ntstatus_to_werror(status);
1669 if (W_ERROR_IS_OK(result)) {
1670 printf ("Printer Driver %s successfully installed.\n",
1671 info3.driver_name);
1674 return result;
1678 /****************************************************************************
1679 ****************************************************************************/
1681 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1682 TALLOC_CTX *mem_ctx,
1683 int argc, const char **argv)
1685 WERROR result;
1686 struct spoolss_SetPrinterInfoCtr info_ctr;
1687 struct spoolss_SetPrinterInfo2 info2;
1689 /* parse the command arguments */
1690 if (argc != 5)
1692 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1693 return WERR_OK;
1696 /* Fill in the DRIVER_INFO_2 struct */
1697 ZERO_STRUCT(info2);
1699 info2.printername = argv[1];
1700 info2.drivername = argv[3];
1701 info2.sharename = argv[2];
1702 info2.portname = argv[4];
1703 info2.comment = "Created by rpcclient";
1704 info2.printprocessor = "winprint";
1705 info2.datatype = "RAW";
1706 info2.devmode_ptr = 0;
1707 info2.secdesc_ptr = 0;
1708 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1709 info2.priority = 0;
1710 info2.defaultpriority = 0;
1711 info2.starttime = 0;
1712 info2.untiltime = 0;
1714 /* These three fields must not be used by AddPrinter()
1715 as defined in the MS Platform SDK documentation..
1716 --jerry
1717 info2.status = 0;
1718 info2.cjobs = 0;
1719 info2.averageppm = 0;
1722 info_ctr.level = 2;
1723 info_ctr.info.info2 = &info2;
1725 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1726 &info_ctr);
1727 if (W_ERROR_IS_OK(result))
1728 printf ("Printer %s successfully installed.\n", argv[1]);
1730 return result;
1733 /****************************************************************************
1734 ****************************************************************************/
1736 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1737 TALLOC_CTX *mem_ctx,
1738 int argc, const char **argv)
1740 struct policy_handle pol;
1741 WERROR result;
1742 NTSTATUS status;
1743 uint32_t level = 2;
1744 const char *printername;
1745 union spoolss_PrinterInfo info;
1746 struct spoolss_SetPrinterInfoCtr info_ctr;
1747 struct spoolss_SetPrinterInfo2 info2;
1748 struct spoolss_DevmodeContainer devmode_ctr;
1749 struct sec_desc_buf secdesc_ctr;
1751 ZERO_STRUCT(devmode_ctr);
1752 ZERO_STRUCT(secdesc_ctr);
1754 /* parse the command arguments */
1755 if (argc != 3)
1757 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1758 return WERR_OK;
1761 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1763 /* Get a printer handle */
1765 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1766 printername,
1767 PRINTER_ALL_ACCESS,
1768 &pol);
1769 if (!W_ERROR_IS_OK(result))
1770 goto done;
1772 /* Get printer info */
1774 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1775 &pol,
1776 level,
1778 &info);
1779 if (!W_ERROR_IS_OK(result)) {
1780 printf ("Unable to retrieve printer information!\n");
1781 goto done;
1784 /* Set the printer driver */
1786 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1787 info2.drivername = argv[2];
1789 info_ctr.level = 2;
1790 info_ctr.info.info2 = &info2;
1792 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1793 &pol,
1794 &info_ctr,
1795 &devmode_ctr,
1796 &secdesc_ctr,
1797 0, /* command */
1798 &result);
1799 if (!W_ERROR_IS_OK(result)) {
1800 printf("SetPrinter call failed!\n");
1801 goto done;;
1804 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1806 done:
1807 /* Cleanup */
1809 if (is_valid_policy_hnd(&pol))
1810 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1812 return result;
1816 /****************************************************************************
1817 ****************************************************************************/
1819 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1820 TALLOC_CTX *mem_ctx,
1821 int argc, const char **argv)
1823 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1824 NTSTATUS status;
1826 int i;
1827 int vers = -1;
1829 const char *arch = NULL;
1830 uint32_t delete_flags = 0;
1832 /* parse the command arguments */
1833 if (argc < 2 || argc > 4) {
1834 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1835 return WERR_OK;
1838 if (argc >= 3)
1839 arch = argv[2];
1840 if (argc == 4)
1841 vers = atoi (argv[3]);
1843 if (vers >= 0) {
1844 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1847 /* delete the driver for all architectures */
1848 for (i=0; archi_table[i].long_archi; i++) {
1850 if (arch && !strequal( archi_table[i].long_archi, arch))
1851 continue;
1853 if (vers >= 0 && archi_table[i].version != vers)
1854 continue;
1856 /* make the call to remove the driver */
1857 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1858 cli->srv_name_slash,
1859 archi_table[i].long_archi,
1860 argv[1],
1861 delete_flags,
1862 archi_table[i].version,
1863 &result);
1865 if ( !W_ERROR_IS_OK(result) )
1867 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1868 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1869 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1872 else
1874 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1875 archi_table[i].long_archi, archi_table[i].version);
1876 ret = WERR_OK;
1880 return ret;
1884 /****************************************************************************
1885 ****************************************************************************/
1887 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1888 TALLOC_CTX *mem_ctx,
1889 int argc, const char **argv)
1891 WERROR result = WERR_OK;
1892 NTSTATUS status;
1893 int i;
1895 /* parse the command arguments */
1896 if (argc != 2) {
1897 printf ("Usage: %s <driver>\n", argv[0]);
1898 return WERR_OK;
1901 /* delete the driver for all architectures */
1902 for (i=0; archi_table[i].long_archi; i++) {
1903 /* make the call to remove the driver */
1904 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1905 cli->srv_name_slash,
1906 archi_table[i].long_archi,
1907 argv[1],
1908 &result);
1909 if (!NT_STATUS_IS_OK(status)) {
1910 return result;
1912 if ( !W_ERROR_IS_OK(result) ) {
1913 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1914 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1915 argv[1], archi_table[i].long_archi,
1916 W_ERROR_V(result));
1918 } else {
1919 printf ("Driver %s removed for arch [%s].\n", argv[1],
1920 archi_table[i].long_archi);
1924 return result;
1927 /****************************************************************************
1928 ****************************************************************************/
1930 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1931 TALLOC_CTX *mem_ctx,
1932 int argc, const char **argv)
1934 WERROR result;
1935 NTSTATUS status;
1936 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1937 DATA_BLOB buffer;
1938 uint32_t offered;
1939 union spoolss_PrintProcessorDirectoryInfo info;
1940 uint32_t needed;
1942 /* parse the command arguments */
1943 if (argc > 2) {
1944 printf ("Usage: %s [environment]\n", argv[0]);
1945 return WERR_OK;
1948 if (argc == 2) {
1949 environment = argv[1];
1952 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1953 cli->srv_name_slash,
1954 environment,
1956 NULL, /* buffer */
1957 0, /* offered */
1958 NULL, /* info */
1959 &needed,
1960 &result);
1961 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1962 offered = needed;
1963 buffer = data_blob_talloc_zero(mem_ctx, needed);
1965 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1966 cli->srv_name_slash,
1967 environment,
1969 &buffer,
1970 offered,
1971 &info,
1972 &needed,
1973 &result);
1976 if (W_ERROR_IS_OK(result)) {
1977 printf("%s\n", info.info1.directory_name);
1980 return result;
1983 /****************************************************************************
1984 ****************************************************************************/
1986 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1987 int argc, const char **argv)
1989 struct policy_handle handle;
1990 WERROR werror;
1991 NTSTATUS status;
1992 const char *printername;
1993 union spoolss_AddFormInfo info;
1994 struct spoolss_AddFormInfo1 info1;
1995 struct spoolss_AddFormInfo2 info2;
1996 uint32_t level = 1;
1998 /* Parse the command arguments */
2000 if (argc < 3 || argc > 5) {
2001 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2002 return WERR_OK;
2005 /* Get a printer handle */
2007 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2009 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2010 printername,
2011 PRINTER_ALL_ACCESS,
2012 &handle);
2013 if (!W_ERROR_IS_OK(werror))
2014 goto done;
2016 /* Dummy up some values for the form data */
2018 if (argc == 4) {
2019 level = atoi(argv[3]);
2022 switch (level) {
2023 case 1:
2024 info1.flags = SPOOLSS_FORM_USER;
2025 info1.form_name = argv[2];
2026 info1.size.width = 100;
2027 info1.size.height = 100;
2028 info1.area.left = 0;
2029 info1.area.top = 10;
2030 info1.area.right = 20;
2031 info1.area.bottom = 30;
2033 info.info1 = &info1;
2035 break;
2036 case 2:
2037 info2.flags = SPOOLSS_FORM_USER;
2038 info2.form_name = argv[2];
2039 info2.size.width = 100;
2040 info2.size.height = 100;
2041 info2.area.left = 0;
2042 info2.area.top = 10;
2043 info2.area.right = 20;
2044 info2.area.bottom = 30;
2045 info2.keyword = argv[2];
2046 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2047 info2.mui_dll = NULL;
2048 info2.ressource_id = 0;
2049 info2.display_name = argv[2];
2050 info2.lang_id = 0;
2052 info.info2 = &info2;
2054 break;
2057 /* Add the form */
2060 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2061 &handle,
2062 level,
2063 info,
2064 &werror);
2066 done:
2067 if (is_valid_policy_hnd(&handle))
2068 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2070 return werror;
2073 /****************************************************************************
2074 ****************************************************************************/
2076 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2077 int argc, const char **argv)
2079 struct policy_handle handle;
2080 WERROR werror;
2081 NTSTATUS status;
2082 const char *printername;
2083 union spoolss_AddFormInfo info;
2084 struct spoolss_AddFormInfo1 info1;
2086 /* Parse the command arguments */
2088 if (argc != 3) {
2089 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2090 return WERR_OK;
2093 /* Get a printer handle */
2095 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2097 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2098 printername,
2099 SEC_FLAG_MAXIMUM_ALLOWED,
2100 &handle);
2101 if (!W_ERROR_IS_OK(werror))
2102 goto done;
2104 /* Dummy up some values for the form data */
2106 info1.flags = SPOOLSS_FORM_PRINTER;
2107 info1.size.width = 100;
2108 info1.size.height = 100;
2109 info1.area.left = 0;
2110 info1.area.top = 1000;
2111 info1.area.right = 2000;
2112 info1.area.bottom = 3000;
2113 info1.form_name = argv[2];
2115 info.info1 = &info1;
2117 /* Set the form */
2119 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2120 &handle,
2121 argv[2],
2123 info,
2124 &werror);
2126 done:
2127 if (is_valid_policy_hnd(&handle))
2128 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2130 return werror;
2133 /****************************************************************************
2134 ****************************************************************************/
2136 static const char *get_form_flag(int form_flag)
2138 switch (form_flag) {
2139 case SPOOLSS_FORM_USER:
2140 return "FORM_USER";
2141 case SPOOLSS_FORM_BUILTIN:
2142 return "FORM_BUILTIN";
2143 case SPOOLSS_FORM_PRINTER:
2144 return "FORM_PRINTER";
2145 default:
2146 return "unknown";
2150 /****************************************************************************
2151 ****************************************************************************/
2153 static void display_form_info1(struct spoolss_FormInfo1 *r)
2155 printf("%s\n" \
2156 "\tflag: %s (%d)\n" \
2157 "\twidth: %d, length: %d\n" \
2158 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2159 r->form_name, get_form_flag(r->flags), r->flags,
2160 r->size.width, r->size.height,
2161 r->area.left, r->area.right,
2162 r->area.top, r->area.bottom);
2165 /****************************************************************************
2166 ****************************************************************************/
2168 static void display_form_info2(struct spoolss_FormInfo2 *r)
2170 printf("%s\n" \
2171 "\tflag: %s (%d)\n" \
2172 "\twidth: %d, length: %d\n" \
2173 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2174 r->form_name, get_form_flag(r->flags), r->flags,
2175 r->size.width, r->size.height,
2176 r->area.left, r->area.right,
2177 r->area.top, r->area.bottom);
2178 printf("\tkeyword: %s\n", r->keyword);
2179 printf("\tstring_type: 0x%08x\n", r->string_type);
2180 printf("\tmui_dll: %s\n", r->mui_dll);
2181 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2182 printf("\tdisplay_name: %s\n", r->display_name);
2183 printf("\tlang_id: %d\n", r->lang_id);
2184 printf("\n");
2187 /****************************************************************************
2188 ****************************************************************************/
2190 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2191 int argc, const char **argv)
2193 struct policy_handle handle;
2194 WERROR werror;
2195 NTSTATUS status;
2196 const char *printername;
2197 DATA_BLOB buffer;
2198 uint32_t offered = 0;
2199 union spoolss_FormInfo info;
2200 uint32_t needed;
2201 uint32_t level = 1;
2203 /* Parse the command arguments */
2205 if (argc < 3 || argc > 5) {
2206 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2207 return WERR_OK;
2210 /* Get a printer handle */
2212 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2214 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2215 printername,
2216 SEC_FLAG_MAXIMUM_ALLOWED,
2217 &handle);
2218 if (!W_ERROR_IS_OK(werror))
2219 goto done;
2221 if (argc == 4) {
2222 level = atoi(argv[3]);
2225 /* Get the form */
2227 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2228 &handle,
2229 argv[2],
2230 level,
2231 NULL,
2232 offered,
2233 &info,
2234 &needed,
2235 &werror);
2236 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2237 buffer = data_blob_talloc_zero(mem_ctx, needed);
2238 offered = needed;
2239 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2240 &handle,
2241 argv[2],
2242 level,
2243 &buffer,
2244 offered,
2245 &info,
2246 &needed,
2247 &werror);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 return werror;
2254 switch (level) {
2255 case 1:
2256 display_form_info1(&info.info1);
2257 break;
2258 case 2:
2259 display_form_info2(&info.info2);
2260 break;
2263 done:
2264 if (is_valid_policy_hnd(&handle))
2265 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2267 return werror;
2270 /****************************************************************************
2271 ****************************************************************************/
2273 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2274 TALLOC_CTX *mem_ctx, int argc,
2275 const char **argv)
2277 struct policy_handle handle;
2278 WERROR werror;
2279 NTSTATUS status;
2280 const char *printername;
2282 /* Parse the command arguments */
2284 if (argc != 3) {
2285 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2286 return WERR_OK;
2289 /* Get a printer handle */
2291 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2293 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2294 printername,
2295 SEC_FLAG_MAXIMUM_ALLOWED,
2296 &handle);
2297 if (!W_ERROR_IS_OK(werror))
2298 goto done;
2300 /* Delete the form */
2302 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2303 &handle,
2304 argv[2],
2305 &werror);
2306 if (!NT_STATUS_IS_OK(status)) {
2307 return ntstatus_to_werror(status);
2310 done:
2311 if (is_valid_policy_hnd(&handle))
2312 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2314 return werror;
2317 /****************************************************************************
2318 ****************************************************************************/
2320 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2321 TALLOC_CTX *mem_ctx, int argc,
2322 const char **argv)
2324 struct policy_handle handle;
2325 WERROR werror;
2326 const char *printername;
2327 uint32_t num_forms, level = 1, i;
2328 union spoolss_FormInfo *forms;
2330 /* Parse the command arguments */
2332 if (argc < 2 || argc > 4) {
2333 printf ("Usage: %s <printer> [level]\n", argv[0]);
2334 return WERR_OK;
2337 /* Get a printer handle */
2339 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2341 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2342 printername,
2343 SEC_FLAG_MAXIMUM_ALLOWED,
2344 &handle);
2345 if (!W_ERROR_IS_OK(werror))
2346 goto done;
2348 if (argc == 3) {
2349 level = atoi(argv[2]);
2352 /* Enumerate forms */
2354 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2355 &handle,
2356 level,
2358 &num_forms,
2359 &forms);
2361 if (!W_ERROR_IS_OK(werror))
2362 goto done;
2364 /* Display output */
2366 for (i = 0; i < num_forms; i++) {
2367 switch (level) {
2368 case 1:
2369 display_form_info1(&forms[i].info1);
2370 break;
2371 case 2:
2372 display_form_info2(&forms[i].info2);
2373 break;
2377 done:
2378 if (is_valid_policy_hnd(&handle))
2379 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2381 return werror;
2384 /****************************************************************************
2385 ****************************************************************************/
2387 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2388 TALLOC_CTX *mem_ctx,
2389 int argc, const char **argv)
2391 WERROR result;
2392 NTSTATUS status;
2393 const char *printername;
2394 struct policy_handle pol;
2395 union spoolss_PrinterInfo info;
2396 enum winreg_Type type;
2397 union spoolss_PrinterData data;
2398 DATA_BLOB blob;
2400 /* parse the command arguments */
2401 if (argc < 5) {
2402 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2403 " <value> <data>\n",
2404 argv[0]);
2405 return WERR_OK;
2408 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2410 type = REG_NONE;
2412 if (strequal(argv[2], "string")) {
2413 type = REG_SZ;
2416 if (strequal(argv[2], "binary")) {
2417 type = REG_BINARY;
2420 if (strequal(argv[2], "dword")) {
2421 type = REG_DWORD;
2424 if (strequal(argv[2], "multistring")) {
2425 type = REG_MULTI_SZ;
2428 if (type == REG_NONE) {
2429 printf("Unknown data type: %s\n", argv[2]);
2430 result = WERR_INVALID_PARAM;
2431 goto done;
2434 /* get a printer handle */
2436 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2437 printername,
2438 SEC_FLAG_MAXIMUM_ALLOWED,
2439 &pol);
2440 if (!W_ERROR_IS_OK(result)) {
2441 goto done;
2444 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2445 &pol,
2448 &info);
2449 if (!W_ERROR_IS_OK(result)) {
2450 goto done;
2453 printf("%s\n", current_timestring(mem_ctx, true));
2454 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2456 /* Set the printer data */
2458 switch (type) {
2459 case REG_SZ:
2460 data.string = talloc_strdup(mem_ctx, argv[4]);
2461 W_ERROR_HAVE_NO_MEMORY(data.string);
2462 break;
2463 case REG_DWORD:
2464 data.value = strtoul(argv[4], NULL, 10);
2465 break;
2466 case REG_BINARY:
2467 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2468 break;
2469 case REG_MULTI_SZ: {
2470 int i, num_strings;
2471 const char **strings = NULL;
2473 for (i=4; i<argc; i++) {
2474 if (strcmp(argv[i], "NULL") == 0) {
2475 argv[i] = "";
2477 if (!add_string_to_array(mem_ctx, argv[i],
2478 &strings,
2479 &num_strings)) {
2480 result = WERR_NOMEM;
2481 goto done;
2484 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2485 if (!data.string_array) {
2486 result = WERR_NOMEM;
2487 goto done;
2489 for (i=0; i < num_strings; i++) {
2490 data.string_array[i] = strings[i];
2492 break;
2494 default:
2495 printf("Unknown data type: %s\n", argv[2]);
2496 result = WERR_INVALID_PARAM;
2497 goto done;
2500 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2501 if (!W_ERROR_IS_OK(result)) {
2502 goto done;
2505 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2506 &pol,
2507 argv[3], /* value_name */
2508 type,
2509 blob.data,
2510 blob.length,
2511 &result);
2512 if (!W_ERROR_IS_OK(result)) {
2513 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2514 goto done;
2516 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2518 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2519 &pol,
2522 &info);
2523 if (!W_ERROR_IS_OK(result)) {
2524 goto done;
2527 printf("%s\n", current_timestring(mem_ctx, true));
2528 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2530 done:
2531 /* cleanup */
2532 if (is_valid_policy_hnd(&pol)) {
2533 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2536 return result;
2539 /****************************************************************************
2540 ****************************************************************************/
2542 static void display_job_info1(struct spoolss_JobInfo1 *r)
2544 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2545 r->user_name, r->document_name, r->text_status, r->pages_printed,
2546 r->total_pages);
2549 /****************************************************************************
2550 ****************************************************************************/
2552 static void display_job_info2(struct spoolss_JobInfo2 *r)
2554 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2555 r->position, r->job_id,
2556 r->user_name, r->document_name, r->text_status, r->pages_printed,
2557 r->total_pages, r->size);
2560 /****************************************************************************
2561 ****************************************************************************/
2563 static void display_job_info3(struct spoolss_JobInfo3 *r)
2565 printf("jobid[%d], next_jobid[%d]\n",
2566 r->job_id, r->next_job_id);
2569 /****************************************************************************
2570 ****************************************************************************/
2572 static void display_job_info4(struct spoolss_JobInfo4 *r)
2574 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2575 r->position, r->job_id,
2576 r->user_name, r->document_name, r->text_status, r->pages_printed,
2577 r->total_pages, r->size, r->size_high);
2580 /****************************************************************************
2581 ****************************************************************************/
2583 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2584 TALLOC_CTX *mem_ctx, int argc,
2585 const char **argv)
2587 WERROR result;
2588 uint32_t level = 1, count, i;
2589 const char *printername;
2590 struct policy_handle hnd;
2591 union spoolss_JobInfo *info;
2593 if (argc < 2 || argc > 3) {
2594 printf("Usage: %s printername [level]\n", argv[0]);
2595 return WERR_OK;
2598 if (argc == 3) {
2599 level = atoi(argv[2]);
2602 /* Open printer handle */
2604 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2606 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2607 printername,
2608 SEC_FLAG_MAXIMUM_ALLOWED,
2609 &hnd);
2610 if (!W_ERROR_IS_OK(result))
2611 goto done;
2613 /* Enumerate ports */
2615 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2616 &hnd,
2617 0, /* firstjob */
2618 1000, /* numjobs */
2619 level,
2621 &count,
2622 &info);
2623 if (!W_ERROR_IS_OK(result)) {
2624 goto done;
2627 for (i = 0; i < count; i++) {
2628 switch (level) {
2629 case 1:
2630 display_job_info1(&info[i].info1);
2631 break;
2632 case 2:
2633 display_job_info2(&info[i].info2);
2634 break;
2635 default:
2636 d_printf("unknown info level %d\n", level);
2637 break;
2641 done:
2642 if (is_valid_policy_hnd(&hnd)) {
2643 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2646 return result;
2649 /****************************************************************************
2650 ****************************************************************************/
2652 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2653 TALLOC_CTX *mem_ctx, int argc,
2654 const char **argv)
2656 WERROR result;
2657 const char *printername;
2658 struct policy_handle hnd;
2659 uint32_t job_id;
2660 uint32_t level = 1;
2661 union spoolss_JobInfo info;
2663 if (argc < 3 || argc > 4) {
2664 printf("Usage: %s printername job_id [level]\n", argv[0]);
2665 return WERR_OK;
2668 job_id = atoi(argv[2]);
2670 if (argc == 4) {
2671 level = atoi(argv[3]);
2674 /* Open printer handle */
2676 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2678 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2679 printername,
2680 SEC_FLAG_MAXIMUM_ALLOWED,
2681 &hnd);
2682 if (!W_ERROR_IS_OK(result)) {
2683 goto done;
2686 /* Enumerate ports */
2688 result = rpccli_spoolss_getjob(cli, mem_ctx,
2689 &hnd,
2690 job_id,
2691 level,
2693 &info);
2695 if (!W_ERROR_IS_OK(result)) {
2696 goto done;
2699 switch (level) {
2700 case 1:
2701 display_job_info1(&info.info1);
2702 break;
2703 case 2:
2704 display_job_info2(&info.info2);
2705 break;
2706 case 3:
2707 display_job_info3(&info.info3);
2708 break;
2709 case 4:
2710 display_job_info4(&info.info4);
2711 break;
2712 default:
2713 d_printf("unknown info level %d\n", level);
2714 break;
2717 done:
2718 if (is_valid_policy_hnd(&hnd)) {
2719 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2722 return result;
2725 /****************************************************************************
2726 ****************************************************************************/
2728 static struct {
2729 const char *name;
2730 enum spoolss_JobControl val;
2731 } cmdvals[] = {
2732 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2733 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2734 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2735 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2736 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2737 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2738 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2739 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2740 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2743 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2745 int i;
2747 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2748 if (strequal(cmdvals[i].name, cmd)) {
2749 return cmdvals[i].val;
2752 return (enum spoolss_JobControl)atoi(cmd);
2755 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2756 TALLOC_CTX *mem_ctx, int argc,
2757 const char **argv)
2759 WERROR result;
2760 NTSTATUS status;
2761 const char *printername;
2762 struct policy_handle hnd;
2763 uint32_t job_id;
2764 enum spoolss_JobControl command;
2766 if (argc != 4) {
2767 printf("Usage: %s printername job_id command\n", argv[0]);
2768 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2769 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2770 return WERR_OK;
2773 job_id = atoi(argv[2]);
2774 command = parse_setjob_command(argv[3]);
2776 /* Open printer handle */
2778 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2780 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2781 printername,
2782 SEC_FLAG_MAXIMUM_ALLOWED,
2783 &hnd);
2784 if (!W_ERROR_IS_OK(result)) {
2785 goto done;
2788 /* Set Job */
2790 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2791 &hnd,
2792 job_id,
2793 NULL,
2794 command,
2795 &result);
2797 if (!W_ERROR_IS_OK(result)) {
2798 goto done;
2801 done:
2802 if (is_valid_policy_hnd(&hnd)) {
2803 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2806 return result;
2809 /****************************************************************************
2810 ****************************************************************************/
2812 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2813 TALLOC_CTX *mem_ctx, int argc,
2814 const char **argv)
2816 WERROR result;
2817 NTSTATUS status;
2818 uint32_t i = 0;
2819 const char *printername;
2820 struct policy_handle hnd;
2821 uint32_t value_offered = 0;
2822 const char *value_name = NULL;
2823 uint32_t value_needed;
2824 enum winreg_Type type;
2825 uint8_t *data = NULL;
2826 uint32_t data_offered = 0;
2827 uint32_t data_needed;
2829 if (argc != 2) {
2830 printf("Usage: %s printername\n", argv[0]);
2831 return WERR_OK;
2834 /* Open printer handle */
2836 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2838 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2839 printername,
2840 SEC_FLAG_MAXIMUM_ALLOWED,
2841 &hnd);
2842 if (!W_ERROR_IS_OK(result)) {
2843 goto done;
2846 /* Enumerate data */
2848 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2849 &hnd,
2851 value_name,
2852 value_offered,
2853 &value_needed,
2854 &type,
2855 data,
2856 data_offered,
2857 &data_needed,
2858 &result);
2860 data_offered = data_needed;
2861 value_offered = value_needed;
2862 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2863 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2865 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2867 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2868 &hnd,
2869 i++,
2870 value_name,
2871 value_offered,
2872 &value_needed,
2873 &type,
2874 data,
2875 data_offered,
2876 &data_needed,
2877 &result);
2878 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2879 struct regval_blob *v;
2881 v = regval_compose(talloc_tos(),
2882 value_name,
2883 type,
2884 data,
2885 data_offered);
2886 if (v == NULL) {
2887 result = WERR_NOMEM;
2888 goto done;
2891 display_reg_value(v);
2892 talloc_free(v);
2896 if (W_ERROR_V(result) == ERRnomoreitems) {
2897 result = W_ERROR(ERRsuccess);
2900 done:
2901 if (is_valid_policy_hnd(&hnd)) {
2902 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2905 return result;
2908 /****************************************************************************
2909 ****************************************************************************/
2911 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2912 TALLOC_CTX *mem_ctx, int argc,
2913 const char **argv)
2915 WERROR result;
2916 uint32_t i;
2917 const char *printername;
2918 struct policy_handle hnd;
2919 uint32_t count;
2920 struct spoolss_PrinterEnumValues *info;
2922 if (argc != 3) {
2923 printf("Usage: %s printername <keyname>\n", argv[0]);
2924 return WERR_OK;
2927 /* Open printer handle */
2929 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2931 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2932 printername,
2933 SEC_FLAG_MAXIMUM_ALLOWED,
2934 &hnd);
2935 if (!W_ERROR_IS_OK(result)) {
2936 goto done;
2939 /* Enumerate subkeys */
2941 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2942 &hnd,
2943 argv[2],
2945 &count,
2946 &info);
2947 if (!W_ERROR_IS_OK(result)) {
2948 goto done;
2951 for (i=0; i < count; i++) {
2952 display_printer_data(info[i].value_name,
2953 info[i].type,
2954 info[i].data->data,
2955 info[i].data->length);
2958 done:
2959 if (is_valid_policy_hnd(&hnd)) {
2960 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2963 return result;
2966 /****************************************************************************
2967 ****************************************************************************/
2969 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2970 TALLOC_CTX *mem_ctx, int argc,
2971 const char **argv)
2973 WERROR result;
2974 const char *printername;
2975 const char *keyname = NULL;
2976 struct policy_handle hnd;
2977 const char **key_buffer = NULL;
2978 int i;
2979 uint32_t offered = 0;
2981 if (argc < 2 || argc > 4) {
2982 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
2983 return WERR_OK;
2986 if (argc >= 3) {
2987 keyname = argv[2];
2988 } else {
2989 keyname = "";
2992 if (argc == 4) {
2993 offered = atoi(argv[3]);
2996 /* Open printer handle */
2998 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3000 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3001 printername,
3002 SEC_FLAG_MAXIMUM_ALLOWED,
3003 &hnd);
3004 if (!W_ERROR_IS_OK(result)) {
3005 goto done;
3008 /* Enumerate subkeys */
3010 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3011 &hnd,
3012 keyname,
3013 &key_buffer,
3014 offered);
3016 if (!W_ERROR_IS_OK(result)) {
3017 goto done;
3020 for (i=0; key_buffer && key_buffer[i]; i++) {
3021 printf("%s\n", key_buffer[i]);
3024 done:
3026 if (is_valid_policy_hnd(&hnd)) {
3027 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3030 return result;
3033 /****************************************************************************
3034 ****************************************************************************/
3036 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3037 TALLOC_CTX *mem_ctx, int argc,
3038 const char **argv)
3040 const char *printername;
3041 const char *clientname;
3042 struct policy_handle hnd;
3043 WERROR result;
3044 NTSTATUS status;
3045 struct spoolss_NotifyOption option;
3047 if (argc != 2) {
3048 printf("Usage: %s printername\n", argv[0]);
3049 result = WERR_OK;
3050 goto done;
3053 /* Open printer */
3055 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3057 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3058 printername,
3059 SEC_FLAG_MAXIMUM_ALLOWED,
3060 &hnd);
3061 if (!W_ERROR_IS_OK(result)) {
3062 printf("Error opening %s\n", argv[1]);
3063 goto done;
3066 /* Create spool options */
3068 option.version = 2;
3069 option.count = 2;
3071 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3072 if (option.types == NULL) {
3073 result = WERR_NOMEM;
3074 goto done;
3077 option.types[0].type = PRINTER_NOTIFY_TYPE;
3078 option.types[0].count = 1;
3079 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3080 if (option.types[0].fields == NULL) {
3081 result = WERR_NOMEM;
3082 goto done;
3084 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3086 option.types[1].type = JOB_NOTIFY_TYPE;
3087 option.types[1].count = 1;
3088 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3089 if (option.types[1].fields == NULL) {
3090 result = WERR_NOMEM;
3091 goto done;
3093 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3095 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3096 if (!clientname) {
3097 result = WERR_NOMEM;
3098 goto done;
3101 /* Send rffpcnex */
3103 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3104 &hnd,
3107 clientname,
3108 123,
3109 &option,
3110 &result);
3111 if (!W_ERROR_IS_OK(result)) {
3112 printf("Error rffpcnex %s\n", argv[1]);
3113 goto done;
3116 done:
3117 if (is_valid_policy_hnd(&hnd))
3118 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3120 return result;
3123 /****************************************************************************
3124 ****************************************************************************/
3126 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3127 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3129 union spoolss_PrinterInfo info1, info2;
3130 WERROR werror;
3131 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3133 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3134 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3135 hnd1,
3138 &info1);
3139 if ( !W_ERROR_IS_OK(werror) ) {
3140 printf("failed (%s)\n", win_errstr(werror));
3141 talloc_destroy(mem_ctx);
3142 return false;
3144 printf("ok\n");
3146 printf("Retrieving printer properties for %s...", cli2->desthost);
3147 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3148 hnd2,
3151 &info2);
3152 if ( !W_ERROR_IS_OK(werror) ) {
3153 printf("failed (%s)\n", win_errstr(werror));
3154 talloc_destroy(mem_ctx);
3155 return false;
3157 printf("ok\n");
3159 talloc_destroy(mem_ctx);
3161 return true;
3164 /****************************************************************************
3165 ****************************************************************************/
3167 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3168 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3170 union spoolss_PrinterInfo info1, info2;
3171 WERROR werror;
3172 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3173 struct security_descriptor *sd1, *sd2;
3174 bool result = true;
3177 printf("Retrieving printer security for %s...", cli1->desthost);
3178 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3179 hnd1,
3182 &info1);
3183 if ( !W_ERROR_IS_OK(werror) ) {
3184 printf("failed (%s)\n", win_errstr(werror));
3185 result = false;
3186 goto done;
3188 printf("ok\n");
3190 printf("Retrieving printer security for %s...", cli2->desthost);
3191 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3192 hnd2,
3195 &info2);
3196 if ( !W_ERROR_IS_OK(werror) ) {
3197 printf("failed (%s)\n", win_errstr(werror));
3198 result = false;
3199 goto done;
3201 printf("ok\n");
3204 printf("++ ");
3206 sd1 = info1.info3.secdesc;
3207 sd2 = info2.info3.secdesc;
3209 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3210 printf("NULL secdesc!\n");
3211 result = false;
3212 goto done;
3215 if (!security_descriptor_equal( sd1, sd2 ) ) {
3216 printf("Security Descriptors *not* equal!\n");
3217 result = false;
3218 goto done;
3221 printf("Security descriptors match\n");
3223 done:
3224 talloc_destroy(mem_ctx);
3225 return result;
3229 /****************************************************************************
3230 ****************************************************************************/
3232 extern struct user_auth_info *rpcclient_auth_info;
3234 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3235 TALLOC_CTX *mem_ctx, int argc,
3236 const char **argv)
3238 const char *printername;
3239 char *printername_path = NULL;
3240 struct cli_state *cli_server2 = NULL;
3241 struct rpc_pipe_client *cli2 = NULL;
3242 struct policy_handle hPrinter1, hPrinter2;
3243 NTSTATUS nt_status;
3244 WERROR werror;
3246 if ( argc != 3 ) {
3247 printf("Usage: %s <printer> <server>\n", argv[0]);
3248 return WERR_OK;
3251 printername = argv[1];
3253 /* first get the connection to the remote server */
3255 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3256 NULL, 0,
3257 "IPC$", "IPC",
3258 get_cmdline_auth_info_username(rpcclient_auth_info),
3259 lp_workgroup(),
3260 get_cmdline_auth_info_password(rpcclient_auth_info),
3261 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3262 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3264 if ( !NT_STATUS_IS_OK(nt_status) )
3265 return WERR_GENERAL_FAILURE;
3267 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3268 &cli2);
3269 if (!NT_STATUS_IS_OK(nt_status)) {
3270 printf("failed to open spoolss pipe on server %s (%s)\n",
3271 argv[2], nt_errstr(nt_status));
3272 return WERR_GENERAL_FAILURE;
3275 /* now open up both printers */
3277 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3279 printf("Opening %s...", printername_path);
3281 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3282 printername_path,
3283 PRINTER_ALL_ACCESS,
3284 &hPrinter1);
3285 if ( !W_ERROR_IS_OK(werror) ) {
3286 printf("failed (%s)\n", win_errstr(werror));
3287 goto done;
3289 printf("ok\n");
3291 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3293 printf("Opening %s...", printername_path);
3294 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3295 printername_path,
3296 PRINTER_ALL_ACCESS,
3297 &hPrinter2);
3298 if ( !W_ERROR_IS_OK(werror) ) {
3299 printf("failed (%s)\n", win_errstr(werror));
3300 goto done;
3302 printf("ok\n");
3304 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3305 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3306 #if 0
3307 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3308 #endif
3311 done:
3312 /* cleanup */
3314 printf("Closing printers...");
3315 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3316 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3317 printf("ok\n");
3319 /* close the second remote connection */
3321 cli_shutdown( cli_server2 );
3322 return WERR_OK;
3325 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3327 printf("print_processor_name: %s\n", r->print_processor_name);
3330 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3331 TALLOC_CTX *mem_ctx, int argc,
3332 const char **argv)
3334 WERROR werror;
3335 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3336 uint32_t num_procs, level = 1, i;
3337 union spoolss_PrintProcessorInfo *procs;
3339 /* Parse the command arguments */
3341 if (argc < 1 || argc > 4) {
3342 printf ("Usage: %s [environment] [level]\n", argv[0]);
3343 return WERR_OK;
3346 if (argc >= 2) {
3347 environment = argv[1];
3350 if (argc == 3) {
3351 level = atoi(argv[2]);
3354 /* Enumerate Print Processors */
3356 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3357 cli->srv_name_slash,
3358 environment,
3359 level,
3361 &num_procs,
3362 &procs);
3363 if (!W_ERROR_IS_OK(werror))
3364 goto done;
3366 /* Display output */
3368 for (i = 0; i < num_procs; i++) {
3369 switch (level) {
3370 case 1:
3371 display_proc_info1(&procs[i].info1);
3372 break;
3376 done:
3377 return werror;
3380 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3382 printf("name_array: %s\n", r->name_array);
3385 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3386 TALLOC_CTX *mem_ctx, int argc,
3387 const char **argv)
3389 WERROR werror;
3390 const char *print_processor_name = "winprint";
3391 uint32_t num_procs, level = 1, i;
3392 union spoolss_PrintProcDataTypesInfo *procs;
3394 /* Parse the command arguments */
3396 if (argc < 1 || argc > 4) {
3397 printf ("Usage: %s [environment] [level]\n", argv[0]);
3398 return WERR_OK;
3401 if (argc >= 2) {
3402 print_processor_name = argv[1];
3405 if (argc == 3) {
3406 level = atoi(argv[2]);
3409 /* Enumerate Print Processor Data Types */
3411 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3412 cli->srv_name_slash,
3413 print_processor_name,
3414 level,
3416 &num_procs,
3417 &procs);
3418 if (!W_ERROR_IS_OK(werror))
3419 goto done;
3421 /* Display output */
3423 for (i = 0; i < num_procs; i++) {
3424 switch (level) {
3425 case 1:
3426 display_proc_data_types_info1(&procs[i].info1);
3427 break;
3431 done:
3432 return werror;
3435 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3437 printf("monitor_name: %s\n", r->monitor_name);
3440 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3442 printf("monitor_name: %s\n", r->monitor_name);
3443 printf("environment: %s\n", r->environment);
3444 printf("dll_name: %s\n", r->dll_name);
3447 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3448 TALLOC_CTX *mem_ctx, int argc,
3449 const char **argv)
3451 WERROR werror;
3452 uint32_t count, level = 1, i;
3453 union spoolss_MonitorInfo *info;
3455 /* Parse the command arguments */
3457 if (argc > 2) {
3458 printf("Usage: %s [level]\n", argv[0]);
3459 return WERR_OK;
3462 if (argc == 2) {
3463 level = atoi(argv[1]);
3466 /* Enumerate Print Monitors */
3468 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3469 cli->srv_name_slash,
3470 level,
3472 &count,
3473 &info);
3474 if (!W_ERROR_IS_OK(werror)) {
3475 goto done;
3478 /* Display output */
3480 for (i = 0; i < count; i++) {
3481 switch (level) {
3482 case 1:
3483 display_monitor1(&info[i].info1);
3484 break;
3485 case 2:
3486 display_monitor2(&info[i].info2);
3487 break;
3491 done:
3492 return werror;
3495 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3496 TALLOC_CTX *mem_ctx, int argc,
3497 const char **argv)
3499 WERROR result;
3500 NTSTATUS status;
3501 struct policy_handle handle, gdi_handle;
3502 const char *printername;
3503 struct spoolss_DevmodeContainer devmode_ctr;
3505 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3507 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3508 printername,
3509 SEC_FLAG_MAXIMUM_ALLOWED,
3510 &handle);
3511 if (!W_ERROR_IS_OK(result)) {
3512 return result;
3515 ZERO_STRUCT(devmode_ctr);
3517 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3518 &handle,
3519 &gdi_handle,
3520 &devmode_ctr,
3521 &result);
3522 if (!W_ERROR_IS_OK(result)) {
3523 goto done;
3526 done:
3527 if (is_valid_policy_hnd(&gdi_handle)) {
3528 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3530 if (is_valid_policy_hnd(&handle)) {
3531 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3534 return result;
3537 /* List of commands exported by this module */
3538 struct cmd_set spoolss_commands[] = {
3540 { "SPOOLSS" },
3542 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3543 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3544 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3545 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3546 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3547 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3548 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3549 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3550 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3551 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3552 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3553 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3554 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3555 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3556 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3557 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3558 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3559 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3560 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3561 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3562 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3563 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3564 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3565 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3566 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3567 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3568 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3569 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3570 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3571 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3572 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3573 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3574 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3575 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3576 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
3578 { NULL }